[
  {
    "path": ".devcontainer/Dockerfile",
    "content": "ARG VARIANT=debian-12\nFROM mcr.microsoft.com/devcontainers/base:${VARIANT}\nUSER root\n\n# Install APT packages\nRUN apt-get update && export DEBIAN_FRONTEND=noninteractive \\\n    && apt-get -y install tar curl zip unzip bash-completion build-essential ripgrep htop \\\n    ninja-build ccache g++ mold gdb clang-format clang-tidy \\\n    rpm pkg-config cmake git gettext libsdl2-dev libsdl2-image-dev libsodium-dev \\\n    libpng-dev libbz2-dev libfmt-dev libgtest-dev libgmock-dev libbenchmark-dev zsh \\\n    qtbase5-dev qt6-base-dev ristretto \\\n    && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*\n\nRUN --mount=type=bind,source=tools/build_and_install_smpq.sh,target=/tmp/build_and_install_smpq.sh sh /tmp/build_and_install_smpq.sh\n\n# Install devilutionx-graphics-tools\nRUN git clone https://github.com/diasurgical/devilutionx-graphics-tools.git /tmp/devilutionx-graphics-tools && \\\n    cd /tmp/devilutionx-graphics-tools && \\\n    cmake -S. -Bbuild-rel -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF && \\\n    cmake --build build-rel -j $(getconf _NPROCESSORS_ONLN) && \\\n    cmake --install build-rel --component Binaries && \\\n    rm -rf /tmp/devilutionx-graphics-tools\n\n# Install devilutionx-mpq-tools\nRUN git clone https://github.com/diasurgical/devilutionx-mpq-tools.git /tmp/devilutionx-mpq-tools && \\\n    cd /tmp/devilutionx-mpq-tools && \\\n    cmake -S. -Bbuild-rel -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF && \\\n    cmake --build build-rel -j $(getconf _NPROCESSORS_ONLN) && \\\n    cmake --install build-rel && \\\n    rm -rf /tmp/devilutionx-mpq-tools\n\n# Install d1-graphics-tool\nRUN git clone https://github.com/diasurgical/d1-graphics-tool.git /tmp/d1-graphics-tool && \\\n    cd /tmp/d1-graphics-tool && \\\n    cmake -S. -Bbuild-rel -G Ninja -DCMAKE_BUILD_TYPE=Release && \\\n    cmake --build build-rel -j $(getconf _NPROCESSORS_ONLN) && \\\n    cmake --install build-rel && \\\n    rm -rf /tmp/d1-graphics-tool\n\n# Download spawn.mpq and fonts.mpq\nRUN curl --create-dirs -O -L --output-dir /usr/local/share/diasurgical/devilutionx/ \\\n    https://github.com/diasurgical/devilutionx-assets/releases/latest/download/spawn.mpq && \\\n    curl --create-dirs -O -L --output-dir /usr/local/share/diasurgical/devilutionx/ \\\n    https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq && \\\n    chown -R vscode: /usr/local/share/diasurgical/\n\n# Desktop environment configuration\nCOPY .devcontainer/fluxbox /home/vscode/.fluxbox/\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "{\n\t\"build\": {\n\t\t\"dockerfile\": \"Dockerfile\",\n\t\t\"context\": \"..\"\n\t},\n\t\"customizations\": {\n\t\t\"vscode\": {\n\t\t\t\"extensions\": [\n\t\t\t\t\"github.vscode-github-actions\",\n\t\t\t\t\"ms-vscode.cmake-tools\"\n\t\t\t]\n\t\t}\n\t},\n\t\"features\": {\n\t\t// https://github.com/devcontainers/features/tree/main/src/desktop-lite\n\t\t\"ghcr.io/devcontainers/features/desktop-lite:1\": {\n\t\t\t\"webPort\": 6080,\n\t\t\t\"password\": \"vscode\"\n\t\t},\n\t\t\"ghcr.io/devcontainers-contrib/features/zsh-plugins:0\": {},\n\t\t\"ghcr.io/stuartleeks/dev-container-features/shell-history:0\": {}\n\t},\n\t\"forwardPorts\": [\n\t\t6080\n\t],\n\t\"portsAttributes\": {\n\t\t\"6080\": {\n\t\t\t\"label\": \"desktop\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": ".devcontainer/fluxbox/apps",
    "content": "[transient] (role=GtkFileChooserDialog)\n  [Dimensions]  {70% 70%}\n  [Position]    (CENTER)        {0 0}\n[end]\n[app] (name=AppRun) (class=tiled)\n  [Fullscreen]  {yes}\n[end]\n"
  },
  {
    "path": ".devcontainer/fluxbox/menu",
    "content": "[begin] (  Application Menu  )\n    [exec] (File Manager) { nautilus /workspaces/devilutionX } </usr/share/icons/gnome/32x32/apps/file-manager.png>\n    [exec] (D1 Graphics Tool) { D1GraphicsTool } <>\n    [exec] (Text Editor) { mousepad } <>\n    [exec] (Terminal) { tilix -w ~ -e $(readlink -f /proc/$$/exe) -il } <>\n    [exec] (Web Browser) { x-www-browser --disable-dev-shm-usage } <>\n    [submenu] (System) {}\n        [exec] (Set Resolution) { tilix -t \"Set Resolution\" -e bash /usr/local/bin/set-resolution } <>\n        [exec] (Edit Application Menu) { mousepad ~/.fluxbox/menu } <>\n        [exec] (Passwords and Keys) { seahorse } <>\n        [exec] (Top Processes) { tilix -t \"Top\" -e htop } <>\n        [exec] (Disk Utilization) { tilix -t \"Disk Utilization\" -e ncdu / } <>\n        [exec] (Editres) {editres} <>\n        [exec] (Xfontsel) {xfontsel} <>\n        [exec] (Xkill) {xkill} <>\n        [exec] (Xrefresh) {xrefresh} <>\n    [end]\n    [config] (Configuration)\n    [workspaces] (Workspaces)\n[end]\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\r\n\r\n[*]\r\nindent_style = tab\r\nend_of_line = crlf\r\ncharset = utf-8\r\ntrim_trailing_whitespace = true\r\ninsert_final_newline = true\r\n\r\n[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]\r\n# Visual C++ Code Style settings\r\ncpp_generate_documentation_comments = doxygen_slash_star\r\n\r\n[*.java]\r\nend_of_line = lf\r\n\r\n[*.pot]\r\nend_of_line = lf\r\n\r\n[*.po]\r\nend_of_line = lf\r\n\r\n[*.lua]\r\nindent_style = space\r\nindent_size = 2\r\nend_of_line = lf\r\n\r\n[*.py]\r\nindent_style = space\r\nindent_size = 4\r\nend_of_line = lf\r\n\r\n[*.rb]\r\nend_of_line = lf\r\n\r\n[*.yml]\r\nindent_style = space\r\nend_of_line = lf\r\n\r\n[*.sh]\r\nend_of_line = lf\r\n\r\n[*.xml]\r\nend_of_line = lf\r\n\r\n[.clang-format]\r\nend_of_line = lf\r\n\r\n[.gitignore]\r\nend_of_line = lf\r\n\r\n[*.cmake]\r\nindent_style = space\r\nindent_size = 2\r\n\r\n[*.desktop]\r\nend_of_line = lf\r\n\r\n[*.md]\r\nindent_style = space\r\nindent_size = 2\r\nend_of_line = lf\r\n\r\n[*.txt]\r\nend_of_line = crlf\r\n\r\n[*.tsv]\r\ntrim_trailing_whitespace = false\r\n\r\n[*.plist]\r\nend_of_line = lf\r\n\r\n[AppRun]\r\nend_of_line = lf\r\n\r\n[{CMakeLists.txt,CMakeSettings.json}]\r\nindent_style = space\r\nindent_size = 2\r\nend_of_line = crlf\r\n\r\n[control]\r\nend_of_line = lf\r\n\r\n[devilutionx.spec]\r\nend_of_line = lf\r\n\r\n[Dockerfile]\r\nend_of_line = lf\r\n\r\n[ASSETS_VERSION]\r\nend_of_line = lf\r\n"
  },
  {
    "path": ".gdbinit",
    "content": "source tools/gdb/devilution_gdb/__init__.py\r\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Do not let git change line endings.\r\n* -text\r\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug report\ndescription: Create a report to help us improve\ntitle: \"[Issue Report]: \"\nlabels: [\"issue report\"]\nbody:\n  - type: dropdown\n    id: operating-system\n    attributes:\n      label: Operating System\n      options:\n        - Windows x64\n        - Windows x86\n        - Linux x64\n        - Linux x86\n        - Mac\n        - Android\n        - iOS\n        - Xbox One\n        - PlayStation 4\n        - Nintendo Switch\n        - PlayStation Vita\n        - Nintendo 3DS\n        - Other (please specify)\n    validations:\n      required: true\n  - type: dropdown\n    id: version\n    attributes:\n      label: DevilutionX version\n      options:\n        - 1.5.5\n        - 1.5.4\n        - 1.5.3\n        - 1.5.2\n        - 1.5.1\n        - 1.5.0\n        - 1.4.1\n        - 1.4.0\n        - 1.3.0\n        - 1.2.1\n        - 1.1.0\n        - Custom build (please specify commit ID)\n        - Other (please specify version number)\n    validations:\n      required: true\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe\n      placeholder: A clear and concise description of what the bug is.\n    validations:\n      required: true\n  - type: textarea\n    id: steps-to-reproduce\n    attributes:\n      label: To Reproduce\n      description: Steps to reproduce the behavior\n      placeholder: |\n        1. Go to '...'\n        2. Click on '...'\n        3. Scroll down to '...'\n        4. See error\n    validations:\n      required: true\n  - type: input\n    id: expected-behavior\n    attributes:\n      label: Expected Behavior\n      placeholder: A clear and concise description of what you expected to happen.\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional context\n      placeholder: Any other context about the problem here (screenshots, videos, code blocks, etc.).\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: Request a feature or improvement.\ntitle: \"[Feature Request]: \"\nlabels: [\"enhancement\"]\nbody:\n  - type: dropdown\n    id: feature-type\n    attributes:\n      label: Feature Type\n      options:\n        - Quality of Life\n        - Touch Controls\n        - Gamepad Controls\n        - Other (please specify)\n    validations:\n      required: true\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe\n      placeholder: A clear and concise description of the desired feature/change.\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: '/'\n    schedule:\n      interval: weekly\n"
  },
  {
    "path": ".github/workflows/3ds.yml",
    "content": "---\nname: Nintendo 3DS\n\non:  # yamllint disable-line rule:truthy\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    container: devkitpro/devkitarm:latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Install dependencies\n        run: |\n          apt-get update && apt-get install -y --no-install-recommends --no-install-suggests \\\n            ffmpeg\n\n      - name: Get external dependencies\n        run: |\n          wget https://github.com/diasurgical/bannertool/releases/download/1.2.0/bannertool.zip\n          unzip -j \"bannertool.zip\" \"linux-x86_64/bannertool\" -d \"/opt/devkitpro/tools/bin\"\n          wget https://github.com/3DSGuy/Project_CTR/releases/download/makerom-v0.18/makerom-v0.18-ubuntu_x86_64.zip\n          unzip \"makerom-v0.18-ubuntu_x86_64.zip\" \"makerom\" -d \"/opt/devkitpro/tools/bin\"\n          chmod a+x /opt/devkitpro/tools/bin/makerom\n\n      - name: Configure CMake\n        run: |\n          cmake \\\n            -S . \\\n            -B build \\\n            -G Ninja \\\n            -DCMAKE_BUILD_TYPE=RelWithDebInfo \\\n            -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake\n\n      - name: Build DevilutionX\n        run: cmake --build build\n\n      - name: Upload 3dsx Package\n        if: ${{ !env.ACT }}\n        uses: actions/upload-artifact@v7\n        with:\n          name: devilutionx.3dsx\n          path: ./build/devilutionx.3dsx\n\n      - name: Upload cia Package\n        if: ${{ !env.ACT }}\n        uses: actions/upload-artifact@v7\n        with:\n          name: devilutionx.cia\n          path: ./build/devilutionx.cia\n\n      - name: Update Release 3dsx\n        if: ${{ github.event_name == 'release' && !env.ACT }}\n        uses: svenstaro/upload-release-action@v2\n        with:\n          asset_name: devilutionx-3ds.3dsx\n          file: ./build/devilutionx.3dsx\n          overwrite: true\n\n      - name: Update Release cia\n        if: ${{ github.event_name == 'release' && !env.ACT }}\n        uses: svenstaro/upload-release-action@v2\n        with:\n          asset_name: devilutionx-3ds.cia\n          file: ./build/devilutionx.cia\n          overwrite: true\n"
  },
  {
    "path": ".github/workflows/Android.yml",
    "content": "name: Android\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Install gettext\n      run: sudo apt-get update && sudo apt-get install -y gettext\n\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: set up JDK 17\n      uses: actions/setup-java@v5\n      with:\n        java-version: '17'\n        distribution: 'adopt'\n        cache: gradle\n\n    - name: Install CMake\n      run: |\n        $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager \"cmake;3.31.0\"\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: android-project/app/.cxx\n        key: ${{ github.workflow }}-v5-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v5-\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: cd android-project && ./gradlew assembleDebug\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-debug.apk\n        path: android-project/app/build/outputs/apk/debug/app-debug.apk\n\n    - name: Clean up artifacts\n      run: rm -rf android-project/app/build/outputs\n"
  },
  {
    "path": ".github/workflows/Linux_aarch64.yml",
    "content": "name: Linux AArch64 (aarch64-linux-gnu)\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    # Installs dependencies, including arm64 libraries (runs `sudo apt-get update` as part of it)\n    - name: Install dependencies\n      run: Packaging/nix/debian-cross-aarch64-prep.sh\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v8-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v8-\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      env:\n        CMAKE_BUILD_TYPE: ${{github.event_name == 'release' && 'Release' || 'RelWithDebInfo'}}\n      # We set DEVILUTIONX_SYSTEM_LIBFMT=OFF because its soversion changes frequently.\n      # We set DEVILUTIONX_SYSTEM_LIBSODIUM=OFF because its soversion changes frequently.\n      # We set DEVILUTIONX_SYSTEM_BZIP2=OFF because Fedora and Debian do not agree on how to link it.\n      run: |\n        cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/aarch64-linux-gnu.toolchain.cmake \\\n          -DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=/usr -DCPACK=ON -DDEVILUTIONX_SYSTEM_LIBFMT=OFF \\\n          -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_BZIP2=OFF && \\\n        cmake --build build -j $(getconf _NPROCESSORS_ONLN) --target package\n\n    - name: Package\n      run: Packaging/nix/LinuxReleasePackaging.sh && mv devilutionx.tar.xz devilutionx-aarch64-linux-gnu.tar.xz\n\n    # AppImage cross-packaging is not implemented yet.\n    # - name: Package AppImage\n    #   run: Packaging/nix/AppImage.sh && mv devilutionx.appimage devilutionx-aarch64-linux-gnu.appimage\n\n    - name: Upload Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-aarch64-linux-gnu.tar.xz\n        path: devilutionx-aarch64-linux-gnu.tar.xz\n\n    # AppImage cross-packaging is not implemented yet.\n    # - name: Upload AppImage\n    #   if: ${{ !env.ACT }}\n    #   uses: actions/upload-artifact@v7\n    #   with:\n    #     name: devilutionx-aarch64-linux-gnu.appimage\n    #     path: devilutionx-aarch64-linux-gnu.appimage\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: devilutionx-aarch64-linux-gnu.*\n        file_glob: true\n        overwrite: true\n\n    - name: Clean up artifacts\n      run: rm -rf build/_CPack_Packages build/package build/*.deb build/*.rpm build/*.appimage build/*.tar.xz\n"
  },
  {
    "path": ".github/workflows/Linux_x86.yml",
    "content": "name: Linux x86 (i386-linux-gnu)\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    # Installs dependencies, including x86 libraries (runs `sudo apt-get update` as part of it)\n    - name: Install dependencies\n      run: Packaging/nix/debian-cross-i386-prep.sh\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v7-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v7-\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      env:\n        CMAKE_BUILD_TYPE: ${{github.event_name == 'release' && 'Release' || 'RelWithDebInfo'}}\n      # We set DEVILUTIONX_SYSTEM_LIBFMT=OFF because its soversion changes frequently.\n      # We set DEVILUTIONX_SYSTEM_LIBSODIUM=OFF because its soversion changes frequently.\n      # We set DEVILUTIONX_SYSTEM_BZIP2=OFF because Fedora and Debian do not agree on how to link it.\n      run: |\n        cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/linux_i386.toolchain.cmake \\\n          -DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=/usr -DCPACK=ON \\\n          -DBUILD_TESTING=OFF -DDEVILUTIONX_SYSTEM_LIBFMT=OFF -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF \\\n          -DDEVILUTIONX_SYSTEM_BZIP2=OFF && \\\n        cmake --build build -j $(getconf _NPROCESSORS_ONLN) --target package\n\n    - name: Package\n      run: Packaging/nix/LinuxReleasePackaging.sh && mv devilutionx.tar.xz devilutionx-i386-linux-gnu.tar.xz\n\n    # AppImage cross-packaging is not implemented yet.\n    # - name: Package AppImage\n    #   run: Packaging/nix/AppImage.sh && mv devilutionx.appimage devilutionx-i386-linux-gnu.appimage\n\n    - name: Upload Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-i386-linux-gnu.tar.xz\n        path: devilutionx-i386-linux-gnu.tar.xz\n\n    # AppImage cross-packaging is not implemented yet.\n    # - name: Upload AppImage\n    #   if: ${{ !env.ACT }}\n    #   uses: actions/upload-artifact@v7\n    #   with:\n    #     name: devilutionx-i386-linux-gnu.appimage\n    #     path: devilutionx-i386-linux-gnu.appimage\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: devilutionx-i386-linux-gnu.*\n        file_glob: true\n        overwrite: true\n\n    - name: Clean up artifacts\n      run: rm -rf build/_CPack_Packages build/package build/*.deb build/*.rpm build/*.appimage build/*.tar.xz\n"
  },
  {
    "path": ".github/workflows/Linux_x86_64.yml",
    "content": "name: Linux x86_64 (x86_64-linux-gnu)\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    # Installs dependencies and runs `sudo apt-get update` as part of it.\n    - name: Install dependencies\n      run: Packaging/nix/debian-host-prep.sh\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v7-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v7-\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      env:\n        CMAKE_BUILD_TYPE: ${{github.event_name == 'release' && 'Release' || 'RelWithDebInfo'}}\n      # We set DEVILUTIONX_SYSTEM_LIBFMT=OFF because its soversion changes frequently.\n      # We set DEVILUTIONX_SYSTEM_LIBSODIUM=OFF because its soversion changes frequently.\n      # We set DEVILUTIONX_SYSTEM_BZIP2=OFF because Fedora and Debian do not agree on how to link it.\n      run: |\n        cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=/usr -DCPACK=ON \\\n          -DDISCORD_INTEGRATION=ON -DBUILD_TESTING=OFF -DDEVILUTIONX_SYSTEM_LIBFMT=OFF \\\n          -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_BZIP2=OFF && \\\n        cmake --build build -j $(getconf _NPROCESSORS_ONLN) --target package\n\n    - name: Package\n      run: Packaging/nix/LinuxReleasePackaging.sh && mv devilutionx.tar.xz devilutionx-x86_64-linux-gnu.tar.xz\n\n    - name: Package AppImage\n      run: Packaging/nix/AppImage.sh && mv devilutionx.appimage devilutionx-x86_64-linux-gnu.appimage\n\n    - name: Upload Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-x86_64-linux-gnu.tar.xz\n        path: devilutionx-x86_64-linux-gnu.tar.xz\n\n    - name: Upload AppImage\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-x86_64-linux-gnu.appimage\n        path: devilutionx-x86_64-linux-gnu.appimage\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: devilutionx-x86_64-linux-gnu.*\n        file_glob: true\n        overwrite: true\n\n    - name: Clean up artifacts\n      run: rm -rf build/_CPack_Packages build/package build/*.deb build/*.rpm build/*.appimage build/*.tar.xz\n"
  },
  {
    "path": ".github/workflows/Linux_x86_64_SDL1.yml",
    "content": "name: Linux x64 SDL1\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt-get update &&\n        sudo apt-get install -y cmake file g++ git libfmt-dev libsdl1.2-dev libsodium-dev libpng-dev libbz2-dev rpm smpq\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v3-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v3-\n\n    - name: Configure CMake\n      shell: bash\n      working-directory: ${{github.workspace}}\n      # Disable LTO to work around an ICE in gcc11\n      run: cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DCPACK=ON -DUSE_SDL1=ON -DDISCORD_INTEGRATION=ON -DDISABLE_LTO=ON\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: cmake --build build -j $(nproc) --target package\n\n    - name: Package\n      run: Packaging/nix/LinuxReleasePackaging.sh\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx_linux_x86_64_SDL1.tar.xz\n        path: devilutionx.tar.xz\n\n    - name: Clean up artifacts\n      run: rm -rf build/_CPack_Packages build/package build/*.deb build/*.rpm build/*.appimage build/*.tar.xz\n"
  },
  {
    "path": ".github/workflows/Linux_x86_64_SDL3_test.yml",
    "content": "name: Linux x64 SDL3 Tests\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Install dependencies\n      run: |\n        sudo apt-get update -y\n        sudo apt-get install -y cmake curl g++ git libgtest-dev libgmock-dev libbenchmark-dev libfmt-dev libsodium-dev libpng-dev libbz2-dev libasound2-dev libxcursor-dev libxi-dev libxrandr-dev libxss-dev libxtst-dev libxkbcommon-dev wget\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v4-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v4-\n\n    # We specify `-DDEVILUTIONX_SYSTEM_BENCHMARK=OFF` to work around the following error:\n    # lto1: fatal error: bytecode stream in file ‘/usr/lib/x86_64-linux-gnu/libbenchmark_main.a’ generated with LTO version 11.2 instead of the expected 11.3\n    - name: Build tests\n      run: |\n        cmake -S. -Bbuild -G Ninja -DUSE_SDL3=ON -DDEVILUTIONX_SYSTEM_SDL3=OFF -DDEVILUTIONX_STATIC_SDL3=ON -DDEVILUTIONX_SYSTEM_SDL_IMAGE=OFF -DDEVILUTIONX_SYSTEM_BENCHMARK=OFF\n        wget -qnc https://github.com/diasurgical/devilutionx-assets/releases/download/v2/spawn.mpq -P build\n        cmake --build build -j $(nproc)\n\n    - name: Run tests\n      run: cd build && ctest --output-on-failure\n"
  },
  {
    "path": ".github/workflows/Linux_x86_64_test.yml",
    "content": "name: Linux x64 Tests\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Install dependencies\n      run: |\n        sudo apt-get update -y\n        sudo apt-get install -y cmake curl g++ git lcov libgtest-dev libgmock-dev libbenchmark-dev libfmt-dev libsdl2-dev libsodium-dev libpng-dev libbz2-dev wget\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v3-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v3-\n\n    # We specify `-DDEVILUTIONX_SYSTEM_BENCHMARK=OFF` to work around the following error:\n    # lto1: fatal error: bytecode stream in file ‘/usr/lib/x86_64-linux-gnu/libbenchmark_main.a’ generated with LTO version 11.2 instead of the expected 11.3\n    - name: Build tests\n      run: |\n        cmake -S. -Bbuild -G Ninja -DENABLE_CODECOVERAGE=ON -DDEVILUTIONX_SYSTEM_BENCHMARK=OFF\n        wget -qnc https://github.com/diasurgical/devilutionx-assets/releases/download/v2/spawn.mpq -P build\n        cmake --build build -j $(nproc)\n\n    - name: Run tests\n      run: cd build && ctest --output-on-failure\n\n    - name: Upload results\n      uses: codecov/codecov-action@v5\n      with:\n        token: ${{ secrets.CODECOV_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/PS4.yml",
    "content": "name: PS4\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  ps4:\n    runs-on: ubuntu-24.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: |\n        sudo apt-get update && \\\n        sudo apt-get install -y pacman-package-manager wget cmake git gettext smpq && \\\n        sudo tee -a /etc/pacman.conf > /dev/null <<TEXT\n        [pacbrew]\n        SigLevel = Optional TrustAll\n        Server = https://pacman.mydedibox.fr/pacbrew/packages/\n        TEXT\n    - name: Setup pacman packages\n      run: |\n        sudo pacman --noconfirm -Sy && \\\n        sudo pacman --noconfirm -S ps4-openorbis ps4-openorbis-portlibs && \\\n        echo \"#include <endian.h>\" | sudo tee /opt/pacbrew/ps4/openorbis/include/sys/endian.h\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: Packaging/ps4/build.sh\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-ps4.pkg\n        path: build-ps4/devilutionx.pkg\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        asset_name: devilutionx-ps4.pkg\n        file: build-ps4/devilutionx.pkg\n        overwrite: true\n"
  },
  {
    "path": ".github/workflows/PS5.yml",
    "content": "name: PS5 (ps5-payload-dev)\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\n\njobs:\n  ps5:\n    runs-on: ubuntu-24.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: |\n        sudo apt update\n        sudo apt install cmake pkg-config clang-15 lld-15\n        sudo apt install build-essential autoconf libtool yasm nasm\n        sudo apt install smpq gperf pkgconf libarchive-tools autopoint po4a git curl doxygen wget\n        wget https://github.com/ps5-payload-dev/pacbrew-repo/releases/download/v0.27/ps5-payload-dev.tar.gz\n        sudo tar -xf ps5-payload-dev.tar.gz -C /\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: Packaging/ps5/build.sh\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-ps5.zip\n        path: build-ps5/devilutionx-ps5.zip\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        asset_name: devilutionx-ps5.zip\n        file: build-ps5/devilutionx-ps5.zip\n        overwrite: true\n"
  },
  {
    "path": ".github/workflows/Windows9x_MinGW.yml",
    "content": "name: Windows 9x MinGW\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt-get update &&\n        sudo apt-get install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 mingw-w64-tools libz-mingw-w64-dev gettext dpkg-dev wget git sudo smpq &&\n        sudo rm /usr/i686-w64-mingw32/lib/libz.dll.a &&\n        sudo Packaging/windows/mingw9x-prep.sh\n\n    - name: Configure CMake\n      shell: bash\n      working-directory: ${{github.workspace}}\n      run: cmake -S. -Bbuild-windows9x -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DCPACK=ON -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/mingw9x.toolchain.cmake -DTARGET_PLATFORM=windows9x\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: |\n        cmake --build build-windows9x -j $(nproc) --target package\n        mv build-windows9x/devilutionx.zip devilutionx-win9x.zip\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        path: devilutionx-win9x.zip\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: devilutionx-win9x.zip\n        overwrite: true\n\n"
  },
  {
    "path": ".github/workflows/Windows_MSVC_x64.yml",
    "content": "name: Windows MSVC x64\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\npermissions:\n  contents: write\n\nenv:\n  VCPKG_FEATURE_FLAGS: dependencygraph\n  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: windows-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: ccache\n      uses: hendrikmuhs/ccache-action@v1.2\n\n    - name: Install latest CMake\n      uses: lukka/get-cmake@latest\n\n    - name: Restore or setup vcpkg\n      uses: lukka/run-vcpkg@v11.5\n      with:\n        vcpkgGitCommitId: 'a62ce77d56ee07513b4b67de1ec2daeaebfae51a'\n\n    - name: Fetch test data\n      run: |\n          mkdir build-ninja-vcpkg-relwithdebinfo\n          Invoke-WebRequest -Uri \"https://github.com/diasurgical/devilutionx-assets/releases/download/v2/spawn.mpq\" -OutFile \"build-ninja-vcpkg-relwithdebinfo/spawn.mpq\" -Resume\n\n    - name: Get CMakePresets.json\n      run: cp Packaging/windows/CMakePresets.json .\n\n    - name: Run CMake consuming CMakePresets.json and vcpkg.json by mean of vcpkg.\n      uses: lukka/run-cmake@v10\n      with:\n        configurePreset: 'ninja-vcpkg-relwithdebinfo'\n        buildPreset: 'ninja-vcpkg-relwithdebinfo'\n        testPreset: 'ninja-vcpkg-relwithdebinfo'\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx.exe\n        path: |\n            build-ninja-vcpkg-relwithdebinfo/devilutionx.exe\n            build-ninja-vcpkg-relwithdebinfo/bz2.dll\n            build-ninja-vcpkg-relwithdebinfo/fmt.dll\n            build-ninja-vcpkg-relwithdebinfo/libpng16.dll\n            build-ninja-vcpkg-relwithdebinfo/libsodium.dll\n            build-ninja-vcpkg-relwithdebinfo/SDL2.dll\n            build-ninja-vcpkg-relwithdebinfo/SDL2_image.dll\n            build-ninja-vcpkg-relwithdebinfo/zlib1.dll\n"
  },
  {
    "path": ".github/workflows/Windows_MinGW_x64.yml",
    "content": "name: Windows MinGW x64\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-24.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt-get update &&\n        sudo apt-get install -y cmake gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 pkg-config-mingw-w64-x86-64 libz-mingw-w64-dev gettext dpkg-dev wget git sudo smpq &&\n        sudo Packaging/windows/mingw-prep64.sh\n\n    - name: Configure CMake\n      shell: bash\n      working-directory: ${{github.workspace}}\n      run: cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DCPACK=ON -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/mingwcc64.toolchain.cmake -DDEVILUTIONX_SYSTEM_BZIP2=OFF -DDEVILUTIONX_STATIC_LIBSODIUM=ON -DDISCORD_INTEGRATION=ON -DSCREEN_READER_INTEGRATION=ON\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: cmake --build build -j $(nproc) --target package\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx_x64.zip\n        path: build/devilutionx.zip\n\n    - name: Move artifacts to new folder and split exe and other data into two folders\n      if: ${{ !env.ACT && github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'diasurgical/devilutionX'}}\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: mkdir artifacts_dir && unzip build/devilutionx.zip -d artifacts_dir && mkdir artifacts_dir/exe_dir && mv artifacts_dir/devilutionx/devilutionx.exe artifacts_dir/exe_dir && zip -m artifacts_dir/exe_dir/build.zip artifacts_dir/exe_dir/devilutionx.exe && rm artifacts_dir/devilutionx/libTolk.dll\n\n    - name: Pushes DLLs and devilutionx.mpq to another repository\n      if: ${{ !env.ACT && github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'diasurgical/devilutionX' }}\n      uses: cpina/github-action-push-to-another-repository@main\n      env:\n        SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}\n      with:\n        source-directory: artifacts_dir/devilutionx/\n        destination-github-username: 'artifacts-storage'\n        destination-repository-name: 'devilutionx-artifacts'\n        target-directory: data\n        commit-message: \"[DATA] ${{ github.event.head_commit.message }}\"\n        target-branch: master\n\n    - name: Pushes exe to another repository\n      if: ${{ !env.ACT && github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'diasurgical/devilutionX' }}\n      uses: cpina/github-action-push-to-another-repository@main\n      env:\n        SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}\n      with:\n        source-directory: artifacts_dir/exe_dir\n        destination-github-username: 'artifacts-storage'\n        destination-repository-name: 'devilutionx-artifacts'\n        target-directory: ${{ github.sha }}\n        commit-message: \"[EXE] ${{ github.event.head_commit.message }}\"\n        target-branch: master\n"
  },
  {
    "path": ".github/workflows/Windows_MinGW_x86.yml",
    "content": "name: Windows MinGW x86\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-24.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt update &&\n        sudo apt install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-mingw-w64-i686 libz-mingw-w64-dev gettext dpkg-dev wget git sudo smpq &&\n        sudo Packaging/windows/mingw-prep.sh\n\n    - name: Configure CMake\n      shell: bash\n      working-directory: ${{github.workspace}}\n      run: cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DCPACK=ON -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/mingwcc.toolchain.cmake -DDEVILUTIONX_SYSTEM_BZIP2=OFF -DDEVILUTIONX_STATIC_LIBSODIUM=ON -DDISCORD_INTEGRATION=ON -DSCREEN_READER_INTEGRATION=ON\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: cmake --build build -j $(nproc) --target package\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx_x86.zip\n        path: build/devilutionx.zip\n"
  },
  {
    "path": ".github/workflows/Windows_XP_32bit.yml",
    "content": "name: Windows XP MinGW\n\non:\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt update &&\n        sudo apt install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-mingw-w64-i686 libz-mingw-w64-dev gettext dpkg-dev wget git sudo smpq &&\n        sudo rm /usr/i686-w64-mingw32/lib/libz.dll.a &&\n        sudo Packaging/windows/mingw-prep.sh\n\n    - name: Configure CMake\n      shell: bash\n      working-directory: ${{github.workspace}}\n      run: cmake -S. -Bbuild-windowsxp -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DCPACK=ON -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/mingwcc.toolchain.cmake  -DTARGET_PLATFORM=windowsXP\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: |\n        cmake --build build-windowsxp -j $(nproc) --target package\n        mv build-windowsxp/devilutionx.zip devilutionx-windows-xp-32bit.zip\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        path: devilutionx-windows-xp-32bit.zip\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: devilutionx-windows-xp-32bit.zip\n        overwrite: true"
  },
  {
    "path": ".github/workflows/amiga-m68k.yml",
    "content": "---\nname: Amiga M68K\n\non:  # yamllint disable-line rule:truthy\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    container: amigadev/crosstools:m68k-amigaos-gcc10@sha256:e0ee27eb4174ba8f95143273dd2ecb0ffa23ca6a195e013030a681ab541b4a37\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Run prep.sh script\n        run: ./Packaging/amiga/prep.sh\n\n      - name: Configure CMake\n        run: |\n          cmake \\\n            -S . \\\n            -B build \\\n            -G Ninja \\\n            -DCMAKE_BUILD_TYPE=Release \\\n            -DM68K_COMMON=\"-s -fbbb=- -ffast-math\" \\\n            -DM68K_CPU=68040 \\\n            -DM68K_FPU=hard\n\n      - name: Build DevilutionX\n        run: cmake --build build\n\n      - name: Upload Package\n        if: ${{ !env.ACT }}\n        uses: actions/upload-artifact@v7\n        with:\n          name: devilutionx_m68k\n          path: ./build/devilutionx\n\n      - name: Update Release\n        if: ${{ github.event_name == 'release' && !env.ACT }}\n        uses: svenstaro/upload-release-action@v2\n        with:\n          asset_name: devilutionx-amiga-m68k\n          file: ./build/devilutionx\n          overwrite: true\n"
  },
  {
    "path": ".github/workflows/cache-cleanup.yml",
    "content": "name: Delete cache for a closed Pull Request\non:\n  pull_request:\n    types:\n      - closed\n\njobs:\n  cleanup:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check out code\n        uses: actions/checkout@v6\n\n      # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries\n      - name: Cleanup\n        run: |\n          gh extension install actions/gh-actions-cache\n\n          REPO=${{ github.repository }}\n          BRANCH=\"refs/pull/${{ github.event.pull_request.number }}/merge\"\n\n          echo \"Fetching list of cache key\"\n          cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )\n\n          ## Setting this to not fail the workflow while deleting cache keys.\n          set +e\n          echo \"Deleting caches...\"\n          for cacheKey in $cacheKeysForPR; do\n            gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm\n          done\n          echo \"Done\"\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/clang-format-check.yml",
    "content": "name: clang-format check\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  formatting-check:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Formatting Check (Source)\n      uses: jidicula/clang-format-action@v4.17.0\n      with:\n        clang-format-version: '18'\n        check-path: 'Source'\n\n    - name: Formatting Check (test)\n      uses: jidicula/clang-format-action@v4.17.0\n      with:\n        clang-format-version: '18'\n        check-path: 'test'\n"
  },
  {
    "path": ".github/workflows/clang-tidy-check.yml",
    "content": "name: clang-tidy check\n\non:\n  push:\n    branches:\n      - master\n    paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake', '.github/workflows/clang-tidy-check.yml']\n  pull_request:\n    types: [ opened, synchronize ]\n    paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake', '.github/workflows/clang-tidy-check.yml']\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  tidy-check:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Install dependencies\n      run: |\n        sudo apt-get update -y\n        sudo apt-get install -y cmake curl g++ git libgtest-dev libgmock-dev libbenchmark-dev libfmt-dev libsdl2-dev libsodium-dev libpng-dev libbz2-dev wget\n\n    - name: CMake Configure\n      run: cmake -S. -Bbuild\n\n    - name: clang-tidy Check\n      uses: cpp-linter/cpp-linter-action@v2\n      id: linter\n      with:\n        database: build # directory containing compile_commands.json\n        style: '' # using an empty string here disables clang-format checks. We leave the existing clang-format-check workflow to run clang-format instead\n        tidy-checks: '' # using an empty string here instructs the action to use only checks from the .clang-tidy file\n        ignore-tidy: '3rdParty'\n"
  },
  {
    "path": ".github/workflows/iOS.yml",
    "content": "name: iOS\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    # The CMake configure and build commands are platform agnostic and should work equally\n    # well on Windows or Mac.  You can convert this to a matrix build if you need\n    # cross-platform coverage.\n    # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix\n    runs-on: macos-14\n\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v5-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v5-\n\n    - name: Configure CMake\n      # Use a bash shell so we can use the same syntax for environment variable\n      # access regardless of the host operating system\n      shell: bash\n      working-directory: ${{github.workspace}}\n      run: cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/ios.toolchain.cmake  -DENABLE_BITCODE=0 -DPLATFORM=OS64\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: >\n        cmake --build build -j $(sysctl -n hw.physicalcpu) --config Release &&\n        cd build &&\n        mkdir Payload &&\n        mv devilutionx.app Payload &&\n        zip -r devilutionx-iOS.ipa Payload\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-iOS.ipa\n        path: build/devilutionx-iOS.ipa\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: build/devilutionx-iOS.ipa\n        overwrite: true\n\n    - name: Clean up artifacts\n      run: rm -rf build/Payload build/*.ipa\n"
  },
  {
    "path": ".github/workflows/macOS_arm64.yml",
    "content": "name: macOS arm64\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: macos-14\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: brew bundle install\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v2-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v2-\n\n    - name: Clean previous DMG\n      working-directory: ${{github.workspace}}\n      run: rm -f build/*.dmg\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      env:\n        CMAKE_BUILD_TYPE: ${{github.event_name == 'release' && 'Release' || 'RelWithDebInfo'}}\n      run: |\n        cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}} -DBUILD_TESTING=OFF \\\n          -DMACOSX_STANDALONE_APP_BUNDLE=ON && \\\n        cmake --build build -j $(sysctl -n hw.physicalcpu) --target package && \\\n        mv build/devilutionx.dmg build/devilutionx-arm64-macOS.dmg\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-arm64-macOS.dmg\n        path: build/devilutionx-arm64-macOS.dmg\n\n    - name: Clean up artifacts\n      run: rm -rf build/_CPack_Packages build/*.dmg\n"
  },
  {
    "path": ".github/workflows/macOS_x86_64.yml",
    "content": "name: macOS x86_64\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: macos-15-intel\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: brew bundle install\n\n    - name: Cache CMake build folder\n      uses: actions/cache@v5\n      with:\n        path: build\n        key: ${{ github.workflow }}-v4-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v4-\n\n    - name: Clean previous DMG\n      working-directory: ${{github.workspace}}\n      run: rm -f build/*.dmg\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      env:\n        CMAKE_BUILD_TYPE: ${{github.event_name == 'release' && 'Release' || 'RelWithDebInfo'}}\n      run: |\n        cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}} -DBUILD_TESTING=OFF \\\n          -DMACOSX_STANDALONE_APP_BUNDLE=ON -DDISCORD_INTEGRATION=ON && \\\n        cmake --build build -j $(sysctl -n hw.physicalcpu) --target package && \\\n        mv build/devilutionx.dmg build/devilutionx-x86_64-macOS.dmg\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-x86_64-macOS.dmg\n        path: build/devilutionx-x86_64-macOS.dmg\n\n    - name: Clean up artifacts\n      run: rm -rf build/_CPack_Packages build/*.dmg\n"
  },
  {
    "path": ".github/workflows/miyoo_mini_release.yml",
    "content": "name: Miyoo Mini Release Build\n\non:\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  miyoo-mini:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name:  Install toolchain\n      working-directory: ${{github.workspace}}\n      run: sudo Packaging/miyoo_mini/setup_toolchain.sh\n\n    - name:  Build\n      working-directory: ${{github.workspace}}\n      run: Packaging/miyoo_mini/build.sh\n\n    - name: Upload-OnionOS-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-miyoo-mini-onion-os.zip\n        path: build-miyoo-mini/devilutionx-miyoo-mini-onion-os.zip\n\n    - name: Upload-miniUI-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-miyoo-mini-miniui.zip\n        path: build-miyoo-mini/devilutionx-miyoo-mini-miniui.zip\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: \"build-miyoo-mini/devilutionx-*.zip\"\n        file_glob: true\n        overwrite: true\n"
  },
  {
    "path": ".github/workflows/opendingux_release.yml",
    "content": "name: OpenDingux Release Build\n\non:\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  gcw0:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt-get update &&\n        sudo apt-get install -y curl cmake git squashfs-tools &&\n        curl -L https://github.com/OpenDingux/buildroot/releases/download/od-2022.09.22/opendingux-gcw0-toolchain.2022-09-22.tar.xz -o gcw0-toolchain.tar.xz &&\n        sudo mkdir -p /opt/gcw0-toolchain && sudo chown -R \"${USER}:\" /opt/gcw0-toolchain &&\n        tar -C /opt -xf gcw0-toolchain.tar.xz &&\n        cd /opt/gcw0-toolchain && ./relocate-sdk.sh\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: Packaging/OpenDingux/build.sh rg350\n      env:\n        TOOLCHAIN: /opt/gcw0-toolchain\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-rg350.opk.zip\n        path: build-rg350/devilutionx-rg350.opk\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: \"build-rg350/devilutionx-rg350.opk\"\n        overwrite: true\n\n  lepus:\n    runs-on: ubuntu-22.04\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt update &&\n        sudo apt install -y curl cmake git squashfs-tools &&\n        curl -L https://github.com/OpenDingux/buildroot/releases/download/od-2022.09.22/opendingux-lepus-toolchain.2022-09-22.tar.xz -o lepus-toolchain.tar.xz &&\n        sudo mkdir -p /opt/lepus-toolchain && sudo chown -R \"${USER}:\" /opt/lepus-toolchain &&\n        tar -C /opt -xf lepus-toolchain.tar.xz &&\n        cd /opt/lepus-toolchain && ./relocate-sdk.sh\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: Packaging/OpenDingux/build.sh lepus\n      env:\n        TOOLCHAIN: /opt/lepus-toolchain\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-lepus.opk.zip\n        path: build-lepus/devilutionx-lepus.opk\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: \"build-lepus/devilutionx-lepus.opk\"\n        overwrite: true\n"
  },
  {
    "path": ".github/workflows/retrofw_release.yml",
    "content": "name: RetroFW Release Build\n\non:\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  retrofw:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt-get update &&\n        sudo apt-get install -y curl cmake git squashfs-tools gettext &&\n        curl -L https://github.com/retrofw/retrofw.github.io/releases/download/v2.3/mipsel-RetroFW-linux-uclibc_sdk-buildroot.tar.gz -o retrofw-toolchain.tar.gz &&\n        sudo mkdir -p /opt/retrofw-toolchain && sudo chown -R \"${USER}:\" /opt/retrofw-toolchain &&\n        tar -C /opt/retrofw-toolchain --strip-components=1 -xf retrofw-toolchain.tar.gz &&\n        cd /opt/retrofw-toolchain && ./relocate-sdk.sh\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: Packaging/OpenDingux/build.sh retrofw\n      env:\n        TOOLCHAIN: /opt/retrofw-toolchain\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-retrofw.opk.zip\n        path: build-retrofw/devilutionx-retrofw.opk\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: \"build-retrofw/devilutionx-retrofw.opk\"\n        overwrite: true\n"
  },
  {
    "path": ".github/workflows/s390x_qemu_big_endian_tests.yml",
    "content": "name: s390x qemu tests (big-endian)\n\n# The test suite takes ~50m to run so we only trigger it manually\non:\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  big-endian-qemu:\n    runs-on: ubuntu-22.04\n\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Cache .ccache\n      uses: actions/cache@v5\n      with:\n        path: .ccache\n        key: ${{ github.workflow }}-v1-${{ github.sha }}\n        restore-keys: ${{ github.workflow }}-v1-\n\n    - name: Get the qemu container\n      run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes\n\n    - name: Run tests\n      run: >\n        docker run --platform linux/s390x --rm --interactive --mount type=bind,source=$(pwd),target=/host s390x/alpine sh -c\n        \"\n        apk add --update-cache g++ ninja cmake ccache sdl2-dev sdl2_image-dev fmt-dev libpng-dev jpeg-dev bzip2-dev gtest-dev wget &&\n        cd /host &&\n        export CCACHE_DIR=/host/.ccache &&\n        cmake -S. -Bbuild -G Ninja -DNONET=ON -DNOSOUND=ON &&\n        wget -nv -nc https://github.com/diasurgical/devilutionx-assets/releases/download/v2/spawn.mpq -P build &&\n        cmake --build build -j $(nproc) &&\n        ctest --test-dir build --output-on-failure -j $(nproc)\n        \"\n"
  },
  {
    "path": ".github/workflows/src_dist_release.yml",
    "content": "name: Build source tarball\n\non:\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  make_src_dist:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt-get update &&\n        sudo apt-get install -y cmake curl libsdl2-dev libsdl2-image-dev libfmt-dev libsodium-dev libbz2-dev libgtest-dev libgmock-dev libbenchmark-dev git smpq gettext python-is-python3\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      run: tools/make_src_dist.py && mv build-src-dist/devilutionx-*.tar.xz devilutionx-src.tar.xz\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-src.tar.xz\n        path: devilutionx-src.tar.xz\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: \"devilutionx-src.tar.xz\"\n        overwrite: true\n\n  make_src_dist_fully_vendored:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Create Build Environment\n      run: >\n        sudo apt-get update &&\n        sudo apt-get install -y cmake curl libsdl2-dev libsdl2-image-dev libfmt-dev libsodium-dev libbz2-dev libgtest-dev libgmock-dev libbenchmark-dev git smpq gettext python-is-python3\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      run: tools/make_src_dist.py --fully_vendored && mv build-src-dist/devilutionx-*.tar.xz devilutionx-src-fully-vendored.tar.xz\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-src-fully-vendored.tar.xz\n        path: devilutionx-src-fully-vendored.tar.xz\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: \"devilutionx-src-fully-vendored.tar.xz\"\n        overwrite: true\n"
  },
  {
    "path": ".github/workflows/switch.yml",
    "content": "---\nname: Nintendo Switch\n\non:  # yamllint disable-line rule:truthy\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    container: devkitpro/devkita64:latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Configure CMake\n        run: |\n          cmake \\\n            -S . \\\n            -B build \\\n            -D CMAKE_BUILD_TYPE=RelWithDebInfo \\\n            -D CMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake\n\n      - name: Build DevilutionX\n        run: cmake --build build -j$(nproc)\n\n      - name: Upload Package\n        if: ${{ !env.ACT }}\n        uses: actions/upload-artifact@v7\n        with:\n          name: devilutionx.nro\n          path: ./build/devilutionx.nro\n\n      - name: Update Release\n        if: ${{ github.event_name == 'release' && !env.ACT }}\n        uses: svenstaro/upload-release-action@v2\n        with:\n          asset_name: devilutionx-switch.nro\n          file: ./build/devilutionx.nro\n          overwrite: true\n...\n"
  },
  {
    "path": ".github/workflows/translations.yml",
    "content": "name: Validate translations\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [ opened, synchronize ]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  fmt-check:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Install polib\n      run: sudo apt-get update && sudo apt-get install -y python3-polib\n\n    - name: Check\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: python3 tools/validate_translations.py\n"
  },
  {
    "path": ".github/workflows/vita.yml",
    "content": "---\nname: Sony PlayStation Vita\n\non:  # yamllint disable-line rule:truthy\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    container: vitasdk/vitasdk:latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Install dependencies\n        run: |\n          apk add \\\n            gettext \\\n            git \\\n            samurai \\\n            patch\n\n      - name: Configure CMake\n        run: |\n          cmake \\\n            -S . \\\n            -B build \\\n            -G Ninja \\\n            -DCMAKE_BUILD_TYPE=RelWithDebInfo \\\n            -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake\n\n      - name: Build DevilutionX\n        run: cmake --build build\n\n      - name: Upload Package\n        if: ${{ !env.ACT }}\n        uses: actions/upload-artifact@v7\n        with:\n          name: devilutionx.vpk\n          path: ./build/devilutionx.vpk\n\n      - name: Update Release\n        if: ${{ github.event_name == 'release' && !env.ACT }}\n        uses: svenstaro/upload-release-action@v2\n        with:\n          asset_name: devilutionx-vita.vpk\n          file: ./build/devilutionx.vpk\n          overwrite: true\n...\n"
  },
  {
    "path": ".github/workflows/xbox_nxdk.yml",
    "content": "name: Xbox\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  xbox:\n    runs-on: ubuntu-22.04\n    env:\n      NXDK_DIR: /opt/nxdk\n    steps:\n    - name: Install APT packages\n      run: sudo apt-get update && sudo apt-get install -y clang llvm lld bison flex cmake git gettext\n\n    - name: Clone nxdk Repo\n      shell: bash\n      run: git clone --recursive --depth 1 https://github.com/XboxDev/nxdk.git \"$NXDK_DIR\"\n\n    - name: Build nxdk\n      shell: bash\n      run: PATH=\"${NXDK_DIR}/bin:$PATH\" make -j $(nproc) -C \"$NXDK_DIR\" NXDK_ONLY=1 CFLAGS=-O2 CXXFLAGS=-O2 all cxbe\n\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Configure CMake\n      working-directory: ${{github.workspace}}\n      env:\n        CMAKE_BUILD_TYPE: ${{github.event_name == 'release' && 'Release' || 'RelWithDebInfo'}}\n      run: cmake -S. -Bbuild-xbox -DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=/opt/nxdk/share/toolchain-nxdk.cmake\n\n    - name: Build\n      working-directory: ${{github.workspace}}\n      shell: bash\n      run: cmake --build build-xbox -j $(nproc) --target nxdk_xbe\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-xbox\n        path: build-xbox/pkg/\n\n    - name: Package Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      working-directory: ${{github.workspace}}/build-xbox/pkg\n      run: zip -r ../../devilutionx-xbox.zip .\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: devilutionx-xbox.zip\n        overwrite: true\n"
  },
  {
    "path": ".github/workflows/xbox_one.yml",
    "content": "name: Xbox One / Series\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  pull_request:\n    types: [opened, synchronize]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n  release:\n    types: [published]\n    paths-ignore:\n      - '*.md'\n      - 'docs/**'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: windows-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: ccache\n      uses: hendrikmuhs/ccache-action@v1.2\n\n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v2\n      with:\n        msbuild-architecture: x64\n\n    - name: Configure git\n      shell: cmd\n      run: |\n        git config --global core.filemode false\n        git config --global core.autocrlf false\n\n    - name: Install gettext\n      run: >\n        New-Item -Path . -Name tools-gettext -ItemType Directory -Force &&\n        Invoke-WebRequest -Uri \"https://github.com/vslavik/gettext-tools-windows/releases/download/v0.22.5/gettext-tools-windows-0.22.5.zip\" -OutFile tools-gettext.zip -Resume &&\n        Expand-Archive tools-gettext.zip &&\n        Remove-Item tools-gettext.zip &&\n        Add-Content $env:GITHUB_PATH \"$((Get-Item tools-gettext).FullName)\\bin\"\n\n    - name: Build\n      shell: cmd\n      run: |\n        cd ${{ github.workspace }}\\Packaging\\xbox-one\n        build.bat\n\n    - name: Copy artifacts to package directory\n      run: >\n        New-Item -Path build\\uwp-project -Name pkg -ItemType Directory -Force &&\n        Get-Childitem -Path build\\uwp-project\\AppxPackages, build\\uwp-project\\Release\n        -Include Microsoft.VCLibs.x64.*.appx, devilutionX_*_x64.appx -File -Recurse |\n        Copy-Item -Destination build\\uwp-project\\pkg\\\n\n    - name: Upload-Package\n      if: ${{ !env.ACT }}\n      uses: actions/upload-artifact@v7\n      with:\n        name: devilutionx-xbox-one-series\n        if-no-files-found: error\n        path: |\n          build/uwp-project/pkg/\n\n    - name: Package Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      working-directory: ${{github.workspace}}/build/uwp-project/pkg/\n      run: 7z a -r ../../../devilutionx-xbox-one-series.zip .\n\n    - name: Update Release\n      if: ${{ github.event_name == 'release' && !env.ACT }}\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: devilutionx-xbox-one-series.zip\n        overwrite: true\n"
  },
  {
    "path": ".gitignore",
    "content": "# Generated by VC++ 6 builds\n/vc60.idb\n*.asm\n*.idb\n\n# macOS\n.DS_Store\n\n# CodeLite\n.CodeLite\n*.project\n*.workspace\n\n# Devilution Comparer\ndevilution-comparer\ncomparer-config.toml\n\n#ignore cmake cache\n/build-*/\n.vscode/tasks.json\n\n# Extra files in the source distribution (see make_src_dist.py)\n/dist/\n\n*.appimage\n*.AppImage\n\n# ELF object file, shared library and object archive.\n*.o\n*.so\n*.a\n\n# PE shared library and associated files.\n*.lib\n*.exp\n*.dll\n\n# PE executable.\n*.exe\n\n# GCC dependency file.\n*.d\n\n# Resource file.\n*.res\n\n# Created by https://www.gitignore.io/api/visualstudio\n\n### VisualStudio ###\n## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\nWinDebug/\nWinRel/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Vim swap files\n*.swp\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# Visual Studio Edit & Continue\nenc_temp_folder\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n# except for a top-level .cache directory (clangd uses /.cache/clangd for temporary files)\n/.cache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n# CodeRush\n.cr/\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# macOS\n.DS_Store\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n### VisualStudio Patch ###\n# By default, sensitive information, such as encrypted password\n# should be stored in the .pubxml.user file.\n*.pubxml.user\n\n# End of https://www.gitignore.io/api/visualstudio\n\n# Created by https://www.gitignore.io/api/xcode\n# Edit at https://www.gitignore.io/?templates=xcode\n\n### Visual Code\n/.vscode\n\n### Xcode ###\n# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n## User settings\nxcuserdata/\n\n## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)\n*.xcscmblueprint\n*.xccheckout\n\n## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)\nbuild/\nDerivedData/\n*.moved-aside\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\n\n### Xcode Patch ###\n*.xcodeproj/*\n!*.xcodeproj/project.pbxproj\n!*.xcodeproj/xcshareddata/\n!*.xcworkspace/contents.xcworkspacedata\n/*.gcno\n**/xcshareddata/WorkspaceSettings.xcsettings\n\n/libs\n\n# End of https://www.gitignore.io/api/xcode\n\n# Don't accidently commit the diabdat.mpq or any other MPQ files\n*.mpq\n\n### Nintendo Switch ###\nexefs/main\n/out/isenseconfig/CPI-Debug\n\n/docs/html/\n\n# ddraw wrapper configuration file\nddraw_settings.ini\nBrewfile.lock.json\n.vscode/settings.json\n\n# GPerf heap profile dumps\n*.heap\n*.mo\n\n# UWP copied assets\nuwp-project/Assets/data\nuwp-project/Assets/fonts\nuwp-project/Assets/gendata\nuwp-project/Assets/ui_art\n!uwp-project/devilutionX_TemporaryKey.pfx\n/.s390x-ccache/\n\n# Temporary directory for prep scripts and other purposes.\n/tmp/\n/compile_commands.json\n/tools/tmp\n"
  },
  {
    "path": ".lldbinit",
    "content": "script topsrcdir = topsrcdir if \"topsrcdir\" in locals() else os.getcwd()\r\nscript sys.path.append(os.path.join(topsrcdir, \"tools/lldb\"))\r\nscript import devilution_lldb\r\nscript devilution_lldb.init()\r\n"
  },
  {
    "path": "3rdParty/Lua/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\n# Workaround for deprecation of older CMake versions\r\nset(CMAKE_POLICY_VERSION_MINIMUM 3.22)\r\n\r\nset(LUA_ENABLE_TESTING OFF)\r\nset(LUA_BUILD_COMPILER OFF)\r\nif(DEVILUTIONX_STATIC_LUA)\r\n  set(LUA_ENABLE_SHARED OFF)\r\nelse()\r\n  set(LUA_ENABLE_SHARED ON)\r\nendif()\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(Lua\r\n    URL https://github.com/walterschell/Lua/archive/3ed55a56eaa05c9221f40b3c07d0e908eb1067b0.tar.gz\r\n    URL_HASH MD5=77907b8209f77c65cb681a5012f2d804\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(Lua)\r\n\r\n# Needed for sol2\r\nset(LUA_VERSION_STRING \"5.4.7\" PARENT_SCOPE)\r\n\r\nif(CMAKE_SYSTEM_NAME MATCHES \"Darwin\" AND DARWIN_MAJOR_VERSION VERSION_EQUAL 8)\r\n  # We need legacy-support from MacPorts for:\r\n  # localtime_r gmtime_r\r\n  find_package(MacportsLegacySupport REQUIRED)\r\n  target_link_libraries(lua_static PRIVATE MacportsLegacySupport::MacportsLegacySupport)\r\nelseif(TARGET_PLATFORM STREQUAL \"dos\")\r\n  target_compile_definitions(lua_static PUBLIC -DLUA_USE_C89)\r\nelseif(ANDROID AND (\"${ANDROID_ABI}\" STREQUAL \"armeabi-v7a\" OR \"${ANDROID_ABI}\" STREQUAL \"x86\"))\r\n  target_compile_definitions(lua_static PUBLIC -DLUA_USE_C89)\r\nelseif(NINTENDO_3DS OR VITA OR NINTENDO_SWITCH OR NXDK)\r\n  target_compile_definitions(lua_static PUBLIC -DLUA_USE_C89)\r\nelseif(IOS)\r\n  target_compile_definitions(lua_static PUBLIC -DLUA_USE_IOS)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/PKWare/CMakeLists.txt",
    "content": "add_library(PKWare STATIC\r\n  explode.cpp\r\n  implode.cpp)\r\ntarget_include_directories(PKWare PUBLIC .)\r\n"
  },
  {
    "path": "3rdParty/PKWare/Makefile",
    "content": "VC5_DIR ?= $(HOME)/DevStudio_5.10/VC\n\n# The $(VS6_DIR) directory is a copy of the \"Microsoft Visual Studio\" directory.\n#\n# To get a working setup on Linux or other \"portable\" copies of VS,\n# the following DLLs have to be copied to the\n# $(VS6_DIR)/VC98/Bin directory.\n#\n#     - $(VS6_DIR)/Common/MSDev98/Bin/MSPDB60.DLL\n#\n# And to the $(VC5_DIR)/bin directory.\n#\n#     - $(VC5_DIR)/SharedIDE/bin/MSDIS100.DLL\n#     - $(VC5_DIR)/SharedIDE/bin/MSPDB50.DLL\nVS6_DIR ?= $(HOME)/VS6\n\nVC6_DIR     = $(VS6_DIR)/VC98\n\nVC6_BIN_DIR = $(VC6_DIR)/Bin\nVC6_INC_DIR = $(VC6_DIR)/Include\nVC6_LIB_DIR = $(VC6_DIR)/Lib\n\nVC5_LIB_DIR = $(VC5_DIR)/lib\n\nIDE_DIR ?= $(VS6_DIR)/Common/MSDev98\nIDE_BIN_DIR = $(IDE_DIR)/bin\nifeq ($(OS),Windows_NT)\n\tCL = $(VC6_BIN_DIR)/CL.EXE\n\tRC = $(IDE_BIN_DIR)/RC.EXE\n\tVC5_LINK = $(VC5_DIR)/bin/link.exe\n\tVC6_LINK = $(VC6_BIN_DIR)/link.exe\nelse\n\tCL = wine $(VC6_BIN_DIR)/CL.EXE\n\tRC = wine $(IDE_BIN_DIR)/RC.EXE\n\tVC5_LINK = wine $(VC5_DIR)/bin/link.exe\n\tVC6_LINK = wine $(VC6_BIN_DIR)/link.exe\nendif\n\nCFLAGS=/nologo /c /GX /W3 /O1 /I $(VC6_INC_DIR) /FD /MT /D \"NDEBUG\" /D \"WIN32\" /D \"_WINDOWS\" /YX /Gm /Zi\nLINKFLAGS=/nologo /subsystem:windows /machine:I386 /incremental:no\n\nVC_LINK=$(VC5_LINK)\nLINKFLAGS+= /LIBPATH:$(VC5_LIB_DIR)\n\nall: pkware.lib\n\nPKWARE_SRC=$(sort $(wildcard *.cpp))\nPKWARE_OBJS=$(PKWARE_SRC:.cpp=.obj)\n\npkware.lib: $(PKWARE_OBJS)\n\t$(VC_LINK) -lib /OUT:$@ $^ /nologo\n\n%.obj: %.cpp\n\t$(CL) $(CFLAGS) /Fo$@ $<\n\nclean:\n\t@$(RM) -v $(PKWARE_OBJS) pkware.lib vc60.{idb,pch,pdb}\n\n.PHONY: clean all\n"
  },
  {
    "path": "3rdParty/PKWare/PKWare.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"explode.cpp\" />\n    <ClCompile Include=\"implode.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"pkware.h\" />\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>15.0</VCProjectVersion>\n    <ProjectGuid>{C7F9F3B4-2F7C-4672-9586-94D8BA0950B6}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>PKWare</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>.\\WinDebug\\</OutDir>\n    <IntDir>.\\WinDebug\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <OutDir>.\\WinRel</OutDir>\n    <IntDir>.\\WinRel</IntDir>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "3rdParty/PKWare/PKWare.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"explode.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"implode.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"pkware.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "3rdParty/PKWare/Pkware.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"Pkware\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\r\n\r\nCFG=Pkware - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE\r\n!MESSAGE NMAKE /f \"Pkware.mak\".\r\n!MESSAGE\r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE\r\n!MESSAGE NMAKE /f \"Pkware.mak\" CFG=\"Pkware - Win32 Debug\"\r\n!MESSAGE\r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE\r\n!MESSAGE \"Pkware - Win32 Release\" (based on \"Win32 (x86) Static Library\")\r\n!MESSAGE \"Pkware - Win32 Debug\" (based on \"Win32 (x86) Static Library\")\r\n!MESSAGE\r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"Pkware - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"WinRel\"\r\n# PROP BASE Intermediate_Dir \"WinRel\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"WinRel\"\r\n# PROP Intermediate_Dir \"WinRel\"\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_MBCS\" /D \"_LIB\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_MBCS\" /D \"_LIB\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLIB32=link.exe -lib\r\n# ADD BASE LIB32 /nologo\r\n# ADD LIB32 /nologo\r\n\r\n!ELSEIF  \"$(CFG)\" == \"Pkware - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"WinDebug\"\r\n# PROP BASE Intermediate_Dir \"WinDebug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"WinDebug\"\r\n# PROP Intermediate_Dir \"WinDebug\"\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_MBCS\" /D \"_LIB\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_MBCS\" /D \"_LIB\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLIB32=link.exe -lib\r\n# ADD BASE LIB32 /nologo\r\n# ADD LIB32 /nologo\r\n\r\n!ENDIF\r\n\r\n# Begin Target\r\n\r\n# Name \"Pkware - Win32 Release\"\r\n# Name \"Pkware - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\explode.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\implode.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "3rdParty/PKWare/explode.cpp",
    "content": "/*****************************************************************************/\n/* explode.cpp                            Copyright (c) Ladislav Zezula 2003 */\n/*---------------------------------------------------------------------------*/\n/* Implode function of PKWARE Data Compression library                       */\n/*---------------------------------------------------------------------------*/\n/*   Date    Ver   Who  Comment                                              */\n/* --------  ----  ---  -------                                              */\n/* 11.03.03  1.00  Lad  Splitted from Pkware.cpp                             */\n/* 08.04.03  1.01  Lad  Renamed to explode.cpp to be compatible with pkware  */\n/* 02.05.03  1.01  Lad  Stress test done                                     */\n/* 22.04.10  1.01  Lad  Documented                                           */\n/*****************************************************************************/\n\n#include <assert.h>\n#include <string.h>\n\n#include \"pkware.h\"\n\n#define PKDCL_OK                    0       \n#define PKDCL_STREAM_END            1   // All data from the input stream is read\n#define PKDCL_NEED_DICT             2   // Need more data (dictionary)\n#define PKDCL_CONTINUE             10   // Internal flag, not returned to user\n#define PKDCL_GET_INPUT            11   // Internal flag, not returned to user\n\nstatic char CopyrightPkware[] = \"PKWARE Data Compression Library for Win32\\r\\n\"\n                                \"Copyright 1989-1995 PKWARE Inc.  All Rights Reserved\\r\\n\"\n                                \"Patent No. 5,051,745\\r\\n\"\n                                \"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\\r\\n\"\n                                \"Version 1.11\\r\\n\";\n\n//-----------------------------------------------------------------------------\n// Tables\n\nstatic unsigned char DistBits[] = \n{\n    0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\n    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\n    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\n    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08\n};\n\nstatic unsigned char DistCode[] = \n{\n    0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,\n    0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,\n    0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,\n    0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00\n};\n\nstatic unsigned char ExLenBits[] =\n{\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08\n};\n\nstatic unsigned short LenBase[] =\n{\n    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,\n    0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106\n};\n\nstatic unsigned char LenBits[] =\n{\n    0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07\n};\n\nstatic unsigned char LenCode[] =\n{\n    0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00\n};\n\nstatic unsigned char ChBitsAsc[] =\n{\n    0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,\n    0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,\n    0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,\n    0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,\n    0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,\n    0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,\n    0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,\n    0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,\n    0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,\n    0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D\n};\n\nstatic unsigned short ChCodeAsc[] = \n{\n    0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,\n    0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,\n    0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,\n    0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,\n    0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,\n    0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,\n    0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,\n    0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,\n    0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,\n    0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,\n    0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,\n    0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,\n    0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,\n    0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,\n    0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,\n    0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,\n    0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,\n    0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,\n    0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,\n    0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,\n    0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,\n    0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,\n    0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,\n    0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,\n    0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,\n    0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,\n    0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,\n    0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,\n    0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,\n    0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,\n    0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,\n    0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000  \n};\n\n//-----------------------------------------------------------------------------\n// Local functions\n\nstatic void PKWAREAPI GenDecodeTabs(\n    unsigned char * positions,          // [out] Table of positions\n    unsigned char * start_indexes,      // [in] Table of start indexes\n    unsigned char * length_bits,        // [in] Table of lengths. Each length is stored as number of bits\n    size_t elements)                    // [in] Number of elements in start_indexes and length_bits\n{\n    unsigned int index;\n    unsigned int length;\n    size_t i;\n\n    for(i = 0; i < elements; i++)\n    {\n        length = 1 << length_bits[i];   // Get the length in bytes\n\n        for(index = start_indexes[i]; index < 0x100; index += length)\n        {\n            positions[index] = (unsigned char)i;\n        }\n    }\n}\n\nstatic void PKWAREAPI GenAscTabs(TDcmpStruct * pWork)\n{\n    unsigned short * pChCodeAsc = &ChCodeAsc[0xFF];\n    unsigned int  acc, add;\n    unsigned short count;\n\n    for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--)\n    {\n        unsigned char * pChBitsAsc = pWork->ChBitsAsc + count;\n        unsigned char bits_asc = *pChBitsAsc;\n\n        if(bits_asc <= 8)\n        {\n            add = (1 << bits_asc);\n            acc = *pChCodeAsc;\n\n            do\n            {\n                pWork->offs2C34[acc] = (unsigned char)count;\n                acc += add;\n            }\n            while(acc < 0x100);\n        }\n        else if((acc = (*pChCodeAsc & 0xFF)) != 0)\n        {\n            pWork->offs2C34[acc] = 0xFF;\n\n            if(*pChCodeAsc & 0x3F)\n            {\n                bits_asc -= 4;\n                *pChBitsAsc = bits_asc;\n\n                add = (1 << bits_asc);\n                acc = *pChCodeAsc >> 4;\n                do\n                {\n                    pWork->offs2D34[acc] = (unsigned char)count;\n                    acc += add;\n                }\n                while(acc < 0x100);\n            }\n            else\n            {\n                bits_asc -= 6;\n                *pChBitsAsc = bits_asc;\n\n                add = (1 << bits_asc);\n                acc = *pChCodeAsc >> 6;\n                do\n                {\n                    pWork->offs2E34[acc] = (unsigned char)count;\n                    acc += add;\n                }\n                while(acc < 0x80);\n            }\n        }\n        else\n        {\n            bits_asc -= 8;\n            *pChBitsAsc = bits_asc;\n\n            add = (1 << bits_asc);\n            acc = *pChCodeAsc >> 8;\n            do\n            {\n                pWork->offs2EB4[acc] = (unsigned char)count;\n                acc += add;\n            }\n            while(acc < 0x100);\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n// Removes given number of bits in the bit buffer. New bits are reloaded from\n// the input buffer, if needed.\n// Returns: PKDCL_OK:         Operation was successful\n//          PKDCL_STREAM_END: There are no more bits in the input buffer\n\nstatic int PKWAREAPI WasteBits(TDcmpStruct * pWork, unsigned int nBits)\n{\n    // If number of bits required is less than number of (bits in the buffer) ?\n    if(nBits <= pWork->extra_bits)\n    {\n        pWork->extra_bits -= nBits;\n        pWork->bit_buff  >>= nBits;\n        return PKDCL_OK;\n    }\n\n    // Load input buffer if necessary\n    pWork->bit_buff >>= pWork->extra_bits;\n    if(pWork->in_pos == pWork->in_bytes)\n    {\n        pWork->in_pos = sizeof(pWork->in_buff);\n        if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0)\n            return PKDCL_STREAM_END;\n        pWork->in_pos = 0;\n    }\n\n    // Update bit buffer\n    pWork->bit_buff  |= (pWork->in_buff[pWork->in_pos++] << 8);\n    pWork->bit_buff >>= (nBits - pWork->extra_bits);\n    pWork->extra_bits = (pWork->extra_bits - nBits) + 8;\n    return PKDCL_OK;\n}\n\n//-----------------------------------------------------------------------------\n// Decodes next literal from the input (compressed) data.\n// Returns : 0x000: One byte 0x00\n//           0x001: One byte 0x01\n//           ...\n//           0x0FF: One byte 0xFF\n//           0x100: Repetition, length of 0x02 bytes\n//           0x101: Repetition, length of 0x03 bytes\n//           ...\n//           0x304: Repetition, length of 0x206 bytes\n//           0x305: End of stream\n//           0x306: Error\n\nstatic unsigned int PKWAREAPI DecodeLit(TDcmpStruct * pWork)\n{\n    unsigned int extra_length_bits;    // Number of bits of extra literal length\n    unsigned int length_code;          // Length code\n    unsigned int value;\n\n    // Test the current bit in byte buffer. If is not set, simply return the next 8 bits.\n    if(pWork->bit_buff & 1)\n    {\n        // Remove one bit from the input data\n        if(WasteBits(pWork, 1))\n            return 0x306;   \n                      \n        // The next 8 bits hold the index to the length code table\n        length_code = pWork->LengthCodes[pWork->bit_buff & 0xFF];\n        \n        // Remove the apropriate number of bits\n        if(WasteBits(pWork, pWork->LenBits[length_code]))\n            return 0x306;\n\n        // Are there some extra bits for the obtained length code ?\n        if((extra_length_bits = pWork->ExLenBits[length_code]) != 0)\n        {\n            unsigned int extra_length = pWork->bit_buff & ((1 << extra_length_bits) - 1);\n\n            if(WasteBits(pWork, extra_length_bits))\n            {\n                if((length_code + extra_length) != 0x10E)\n                    return 0x306;\n            }\n            length_code = pWork->LenBase[length_code] + extra_length;\n        }\n\n        // In order to distinguish uncompressed byte from repetition length,\n        // we have to add 0x100 to the length.\n        return length_code + 0x100;\n    }\n\n    // Remove one bit from the input data\n    if(WasteBits(pWork, 1))\n        return 0x306;\n\n    // If the binary compression type, read 8 bits and return them as one byte.\n    if(pWork->ctype == CMP_BINARY)\n    {\n        unsigned int uncompressed_byte = pWork->bit_buff & 0xFF;\n\n        if(WasteBits(pWork, 8))\n            return 0x306;\n        return uncompressed_byte;\n    }\n\n    // When ASCII compression ...\n    if(pWork->bit_buff & 0xFF)\n    {\n        value = pWork->offs2C34[pWork->bit_buff & 0xFF];\n\n        if(value == 0xFF)\n        {\n            if(pWork->bit_buff & 0x3F)\n            {\n                if(WasteBits(pWork, 4))\n                    return 0x306;\n\n                value = pWork->offs2D34[pWork->bit_buff & 0xFF];\n            }\n            else\n            {\n                if(WasteBits(pWork, 6))\n                    return 0x306;\n\n                value = pWork->offs2E34[pWork->bit_buff & 0x7F];\n            }\n        }\n    }\n    else\n    {\n        if(WasteBits(pWork, 8))\n            return 0x306;\n\n        value = pWork->offs2EB4[pWork->bit_buff & 0xFF];\n    }\n\n    return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value;\n}\n\n//-----------------------------------------------------------------------------\n// Decodes the distance of the repetition, backwards relative to the\n// current output buffer position\n\nstatic unsigned int PKWAREAPI DecodeDist(TDcmpStruct * pWork, unsigned int rep_length)\n{\n    unsigned int dist_pos_code;            // Distance position code\n    unsigned int dist_pos_bits;            // Number of bits of distance position\n    unsigned int distance;                 // Distance position\n\n    // Next 2-8 bits in the input buffer is the distance position code\n    dist_pos_code = pWork->DistPosCodes[pWork->bit_buff & 0xFF];\n    dist_pos_bits = pWork->DistBits[dist_pos_code];\n    if(WasteBits(pWork, dist_pos_bits))\n        return 0;\n\n    if(rep_length == 2)\n    {\n        // If the repetition is only 2 bytes length,\n        // then take 2 bits from the stream in order to get the distance\n        distance = (dist_pos_code << 2) | (pWork->bit_buff & 0x03);\n        if(WasteBits(pWork, 2))\n            return 0;\n    }\n    else\n    {\n        // If the repetition is more than 2 bytes length,\n        // then take \"dsize_bits\" bits in order to get the distance\n        distance = (dist_pos_code << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask);\n        if(WasteBits(pWork, pWork->dsize_bits))\n            return 0;\n    }\n    return distance + 1;\n}\n\nstatic unsigned int PKWAREAPI Expand(TDcmpStruct * pWork)\n{\n    unsigned int next_literal;         // Literal decoded from the compressed data\n    unsigned int result;               // Value to be returned\n    unsigned int copyBytes;             // Number of bytes to copy to the output buffer\n\n    pWork->outputPos = 0x1000;          // Initialize output buffer position\n\n    // Decode the next literal from the input data.\n    // The returned literal can either be an uncompressed byte (next_literal < 0x100)\n    // or an encoded length of the repeating byte sequence that\n    // is to be copied to the current buffer position\n    while((result = next_literal = DecodeLit(pWork)) < 0x305)\n    {\n        // If the literal is greater than 0x100, it holds length\n        // of repeating byte sequence\n        // literal of 0x100 means repeating sequence of 0x2 bytes\n        // literal of 0x101 means repeating sequence of 0x3 bytes\n        // ...\n        // literal of 0x305 means repeating sequence of 0x207 bytes\n        if(next_literal >= 0x100)\n        {\n            unsigned char * source;\n            unsigned char * target;\n            unsigned int rep_length;       // Length of the repetition, in bytes\n            unsigned int minus_dist;       // Backward distance to the repetition, relative to the current buffer position\n\n            // Get the length of the repeating sequence.\n            // Note that the repeating block may overlap the current output position,\n            // for example if there was a sequence of equal bytes\n            rep_length = next_literal - 0xFE;\n\n            // Get backward distance to the repetition\n            if((minus_dist = DecodeDist(pWork, rep_length)) == 0)\n            {\n                result = 0x306;\n                break;\n            }\n\n            // Target and source pointer\n            target = &pWork->out_buff[pWork->outputPos];\n            source = target - minus_dist;\n\n            // Update buffer output position\n            pWork->outputPos += rep_length;\n\n            // Copy the repeating sequence\n            while(rep_length-- > 0)\n                *target++ = *source++;\n        }\n        else\n        {\n            pWork->out_buff[pWork->outputPos++] = (unsigned char)next_literal;\n        }\n    \n        // Flush the output buffer, if number of extracted bytes has reached the end\n        if(pWork->outputPos >= 0x2000)\n        {\n            // Copy decompressed data into user buffer\n            copyBytes = 0x1000;\n            pWork->write_buf((char *)&pWork->out_buff[0x1000], &copyBytes, pWork->param);\n\n            // Now copy the decompressed data to the first half of the buffer.\n            // This is needed because the decompression might reuse them as repetitions.\n            // Note that if the output buffer overflowed previously, the extra decompressed bytes\n            // are stored in \"out_buff_overflow\", and they will now be\n            // within decompressed part of the output buffer.\n            memmove(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);\n            pWork->outputPos -= 0x1000;\n        }\n    }\n\n    // Flush any remaining decompressed bytes\n    copyBytes = pWork->outputPos - 0x1000;\n    pWork->write_buf((char *)&pWork->out_buff[0x1000], &copyBytes, pWork->param);\n    return result;\n}\n\n\n//-----------------------------------------------------------------------------\n// Main exploding function.\n\nunsigned int PKWAREAPI explode(\n        unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned  int *size, void *param),\n        void         (PKWAREAPI *write_buf)(char *buf, unsigned  int *size, void *param),\n        char         *work_buf,\n        void         *param)\n{\n    TDcmpStruct * pWork = (TDcmpStruct *)work_buf;\n\n    // Initialize work struct and load compressed data\n    // Note: The caller must zero the \"work_buff\" before passing it to explode\n    pWork->read_buf   = read_buf;\n    pWork->write_buf  = write_buf;\n    pWork->param      = param;\n    pWork->in_pos     = sizeof(pWork->in_buff);\n    pWork->in_bytes   = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param);\n    if(pWork->in_bytes <= 4)\n        return CMP_BAD_DATA;\n\n    pWork->ctype      = pWork->in_buff[0]; // Get the compression type (CMP_BINARY or CMP_ASCII)\n    pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size\n    pWork->bit_buff   = pWork->in_buff[2]; // Initialize 16-bit bit buffer\n    pWork->extra_bits = 0;                 // Extra (over 8) bits\n    pWork->in_pos     = 3;                 // Position in input buffer\n\n    // Test for the valid dictionary size\n    if(4 > pWork->dsize_bits || pWork->dsize_bits > 6) \n        return CMP_INVALID_DICTSIZE;\n\n    pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction\n\n    if(pWork->ctype != CMP_BINARY)\n    {\n        if(pWork->ctype != CMP_ASCII)\n            return CMP_INVALID_MODE;\n\n        memcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc));\n        GenAscTabs(pWork);\n    }\n\n    memcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits));\n    GenDecodeTabs(pWork->LengthCodes, LenCode, pWork->LenBits, sizeof(pWork->LenBits));\n    memcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits));\n    memcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase));\n    memcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits));\n    GenDecodeTabs(pWork->DistPosCodes, DistCode, pWork->DistBits, sizeof(pWork->DistBits));\n    if(Expand(pWork) != 0x306)\n        return CMP_NO_ERROR;\n        \n    return CMP_ABORT;\n}\n"
  },
  {
    "path": "3rdParty/PKWare/implode.cpp",
    "content": "/*****************************************************************************/\n/* implode.cpp                            Copyright (c) Ladislav Zezula 2003 */\n/*---------------------------------------------------------------------------*/\n/* Implode function of PKWARE Data Compression library                       */\n/*---------------------------------------------------------------------------*/\n/*   Date    Ver   Who  Comment                                              */\n/* --------  ----  ---  -------                                              */\n/* 11.04.03  1.00  Lad  First version of implode.cpp                         */\n/* 02.05.03  1.00  Lad  Stress test done                                     */\n/* 22.04.10  1.01  Lad  Documented                                           */\n/*****************************************************************************/\n\n#include <assert.h>\n#include <string.h>\n\n#include \"pkware.h\"\n\n#if ((1200 < _MSC_VER) && (_MSC_VER < 1400))\n#pragma optimize(\"\", off)\n#endif\n\n//-----------------------------------------------------------------------------\n// Defines\n\n#define MAX_REP_LENGTH 0x204            // The longest allowed repetition\n\nstatic char CopyrightPkware[] = \"PKWARE Data Compression Library for Win32\\r\\n\"\n                                \"Copyright 1989-1995 PKWARE Inc.  All Rights Reserved\\r\\n\"\n                                \"Patent No. 5,051,745\\r\\n\"\n                                \"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\\r\\n\"\n                                \"Version 1.11\\r\\n\";\n\n//-----------------------------------------------------------------------------\n// Tables\n\nstatic unsigned char DistBits[] = \n{\n    0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\n    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\n    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\n    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08\n};\n\nstatic unsigned char DistCode[] = \n{\n    0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,\n    0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,\n    0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,\n    0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00\n};\n\nstatic unsigned char ExLenBits[] =\n{\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08\n};\n\nstatic unsigned char LenBits[] =\n{\n    0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07\n};\n\nstatic unsigned char LenCode[] =\n{\n    0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00\n};\n\nstatic unsigned char ChBitsAsc[] =\n{\n    0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,\n    0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,\n    0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,\n    0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,\n    0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,\n    0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,\n    0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,\n    0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,\n    0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,\n    0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,\n    0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D\n};\n\nstatic unsigned short ChCodeAsc[] = \n{\n    0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,\n    0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,\n    0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,\n    0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,\n    0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,\n    0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,\n    0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,\n    0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,\n    0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,\n    0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,\n    0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,\n    0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,\n    0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,\n    0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,\n    0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,\n    0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,\n    0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,\n    0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,\n    0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,\n    0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,\n    0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,\n    0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,\n    0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,\n    0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,\n    0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,\n    0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,\n    0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,\n    0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,\n    0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,\n    0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,\n    0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,\n    0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000  \n};\n\n//-----------------------------------------------------------------------------\n// Macros\n\n// Macro for calculating hash of the current byte pair.\n// Note that most exact byte pair hash would be buffer[0] + buffer[1] << 0x08,\n// but even this way gives nice indication of equal byte pairs, with significantly\n// smaller size of the array that holds numbers of those hashes\n#define BYTE_PAIR_HASH(buffer)   ((buffer[0] * 4) + (buffer[1] * 5))\n\n//-----------------------------------------------------------------------------\n// Local functions\n\n// Builds the \"hash_to_index\" table and \"pair_hash_offsets\" table.\n// Every element of \"hash_to_index\" will contain lowest index to the\n// \"pair_hash_offsets\" table, effectively giving offset of the first\n// occurence of the given PAIR_HASH in the input data.\nstatic void PKWAREAPI SortBuffer(TCmpStruct * pWork, unsigned char * buffer_begin, unsigned char * buffer_end)\n{\n    unsigned short * phash_to_index;\n    unsigned char  * buffer_ptr;\n    unsigned short total_sum = 0;\n    unsigned long byte_pair_hash;           // Hash value of the byte pair\n    unsigned short byte_pair_offs;          // Offset of the byte pair, relative to \"work_buff\"\n\n    // Zero the entire \"phash_to_index\" table\n    memset(pWork->phash_to_index, 0, sizeof(pWork->phash_to_index));\n    \n    // Step 1: Count amount of each PAIR_HASH in the input buffer\n    // The table will look like this:\n    //  offs 0x000: Number of occurences of PAIR_HASH 0\n    //  offs 0x001: Number of occurences of PAIR_HASH 1\n    //  ...\n    //  offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 (the highest hash value)\n    for(buffer_ptr = buffer_begin; buffer_ptr < buffer_end; buffer_ptr++)\n        pWork->phash_to_index[BYTE_PAIR_HASH(buffer_ptr)]++;\n\n    // Step 2: Convert the table to the array of PAIR_HASH amounts. \n    // Each element contains count of PAIR_HASHes that is less or equal\n    // to element index\n    // The table will look like this:\n    //  offs 0x000: Number of occurences of PAIR_HASH 0 or lower\n    //  offs 0x001: Number of occurences of PAIR_HASH 1 or lower\n    //  ...\n    //  offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 or lower\n    for(phash_to_index = pWork->phash_to_index; phash_to_index < &pWork->phash_to_index_end; phash_to_index++)\n    {\n        total_sum = total_sum + phash_to_index[0];\n        phash_to_index[0] = total_sum;\n    }\n\n    // Step 3: Convert the table to the array of indexes.\n    // Now, each element contains index to the first occurence of given PAIR_HASH\n    for(buffer_end--; buffer_end >= buffer_begin; buffer_end--)\n    {\n        byte_pair_hash = BYTE_PAIR_HASH(buffer_end);\n        byte_pair_offs = (unsigned short)(buffer_end - pWork->work_buff);\n\n        pWork->phash_to_index[byte_pair_hash]--;\n        pWork->phash_offs[pWork->phash_to_index[byte_pair_hash]] = byte_pair_offs;\n    }\n}\n\nstatic void PKWAREAPI FlushBuf(TCmpStruct * pWork)\n{\n    unsigned char save_ch1;\n    unsigned char save_ch2;\n    unsigned int size = 0x800;\n\n    pWork->write_buf(pWork->out_buff, &size, pWork->param);\n\n    save_ch1 = pWork->out_buff[0x800];\n    save_ch2 = pWork->out_buff[pWork->out_bytes];\n    pWork->out_bytes -= 0x800;\n\n    memset(pWork->out_buff, 0, sizeof(pWork->out_buff));\n\n    if(pWork->out_bytes != 0)\n        pWork->out_buff[0] = save_ch1;\n    if(pWork->out_bits != 0)\n        pWork->out_buff[pWork->out_bytes] = save_ch2;\n}\n\nstatic void PKWAREAPI OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)\n{\n    unsigned int out_bits;\n\n    // If more than 8 bits to output, do recursion\n    if(nbits > 8)\n    {\n        OutputBits(pWork, 8, bit_buff);\n        bit_buff >>= 8;\n        nbits -= 8;\n    }\n\n    // Add bits to the last out byte in out_buff;\n    out_bits = pWork->out_bits;\n    pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits);\n    pWork->out_bits += nbits;\n\n    // If 8 or more bits, increment number of bytes\n    if(pWork->out_bits > 8)\n    {\n        pWork->out_bytes++;\n        bit_buff >>= (8 - out_bits);\n        \n        pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff;\n        pWork->out_bits &= 7;\n    }\n    else\n    {\n        pWork->out_bits &= 7;\n        if(pWork->out_bits == 0)\n            pWork->out_bytes++;\n    }\n\n    // If there is enough compressed bytes, flush them\n    if(pWork->out_bytes >= 0x800)\n        FlushBuf(pWork);\n}\n\n// This function searches for a repetition\n// (a previous occurence of the current byte sequence)\n// Returns length of the repetition, and stores the backward distance \n// to pWork structure.\nstatic unsigned int PKWAREAPI FindRep(TCmpStruct * pWork, unsigned char * input_data)\n{\n    unsigned short * phash_to_index;            // Pointer into pWork->phash_to_index table\n    unsigned short * phash_offs;                // Pointer to the table containing offsets of each PAIR_HASH\n    unsigned char * repetition_limit;           // An eventual repetition must be at position below this pointer\n    unsigned char * prev_repetition;            // Pointer to the previous occurence of the current PAIR_HASH\n    unsigned char * prev_rep_end;               // End of the previous repetition\n    unsigned char * input_data_ptr;\n    unsigned short phash_offs_index;            // Index to the table with PAIR_HASH positions\n    unsigned short min_phash_offs;              // The lowest allowed hash offset\n    unsigned short offs_in_rep;                 // Offset within found repetition\n    unsigned int equal_byte_count;              // Number of bytes that are equal to the previous occurence\n    unsigned int rep_length = 1;                // Length of the found repetition\n    unsigned int rep_length2;                   // Secondary repetition\n    unsigned char pre_last_byte;                // Last but one byte from a repetion\n    unsigned short di_val;\n\n    // Calculate the previous position of the PAIR_HASH\n    phash_to_index   = pWork->phash_to_index + BYTE_PAIR_HASH(input_data);\n    min_phash_offs   = (unsigned short)((input_data - pWork->work_buff) - pWork->dsize_bytes + 1);\n    phash_offs_index = phash_to_index[0];\n\n    // If the PAIR_HASH offset is below the limit, find a next one\n    phash_offs = pWork->phash_offs + phash_offs_index;\n    if(*phash_offs < min_phash_offs)\n    {\n        while(*phash_offs < min_phash_offs)\n        {\n            phash_offs_index++;\n            phash_offs++;\n        }\n        *phash_to_index = phash_offs_index;\n    }\n\n    // Get the first location of the PAIR_HASH,\n    // and thus the first eventual location of byte repetition\n    phash_offs = pWork->phash_offs + phash_offs_index;\n    prev_repetition = pWork->work_buff + phash_offs[0];\n    repetition_limit = input_data - 1;\n    \n    // If the current PAIR_HASH was not encountered before,\n    // we haven't found a repetition.\n    if(prev_repetition >= repetition_limit)\n        return 0;\n\n    // We have found a match of a PAIR_HASH. Now we have to make sure\n    // that it is also a byte match, because PAIR_HASH is not unique.\n    // We compare the bytes and count the length of the repetition\n    input_data_ptr = input_data;\n    for(;;)\n    {\n        // If the first byte of the repetition and the so-far-last byte\n        // of the repetition are equal, we will compare the blocks.\n        if(*input_data_ptr == *prev_repetition && input_data_ptr[rep_length-1] == prev_repetition[rep_length-1])\n        {\n            // Skip the current byte\n            prev_repetition++;\n            input_data_ptr++;\n            equal_byte_count = 2;\n\n            // Now count how many more bytes are equal\n            while(equal_byte_count < MAX_REP_LENGTH)\n            {\n                prev_repetition++;\n                input_data_ptr++;\n                \n                // Are the bytes different ?\n                if(*prev_repetition != *input_data_ptr)\n                    break;\n\n                equal_byte_count++;\n            }\n\n            // If we found a repetition of at least the same length, take it.\n            // If there are multiple repetitions in the input buffer, this will\n            // make sure that we find the most recent one, which in turn allows\n            // us to store backward length in less amount of bits\n            input_data_ptr = input_data;\n            if(equal_byte_count >= rep_length)\n            {\n                // Calculate the backward distance of the repetition.\n                // Note that the distance is stored as decremented by 1\n                pWork->distance = (unsigned int)(input_data - prev_repetition + equal_byte_count - 1);\n\n                // Repetitions longer than 10 bytes will be stored in more bits,\n                // so they need a bit different handling\n                if((rep_length = equal_byte_count) > 10)\n                    break;\n            }\n        }\n\n        // Move forward in the table of PAIR_HASH repetitions.\n        // There might be a more recent occurence of the same repetition.\n        phash_offs_index++;\n        phash_offs++;\n        prev_repetition = pWork->work_buff + phash_offs[0];\n\n        // If the next repetition is beyond the minimum allowed repetition, we are done.\n        if(prev_repetition >= repetition_limit)\n        {\n            // A repetition must have at least 2 bytes, otherwise it's not worth it\n            return (rep_length >= 2) ? rep_length : 0;\n        }\n    }\n\n    // If the repetition has max length of 0x204 bytes, we can't go any fuhrter\n    if(equal_byte_count == MAX_REP_LENGTH)\n    {\n        pWork->distance--;\n        return equal_byte_count;\n    }\n\n    // Check for possibility of a repetition that occurs at more recent position\n    phash_offs = pWork->phash_offs + phash_offs_index;\n    if(pWork->work_buff + phash_offs[1] >= repetition_limit)\n        return rep_length;\n\n    //\n    // The following part checks if there isn't a longer repetition at\n    // a latter offset, that would lead to better compression.\n    //\n    // Example of data that can trigger this optimization:\n    //\n    //   \"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEQQQQQQQQQQQQ\"\n    //   \"XYZ\"\n    //   \"EEEEEEEEEEEEEEEEQQQQQQQQQQQQ\";\n    //\n    // Description of data in this buffer\n    //   [0x00] Single byte \"E\"\n    //   [0x01] Single byte \"E\"\n    //   [0x02] Repeat 0x1E bytes from [0x00]\n    //   [0x20] Single byte \"X\"\n    //   [0x21] Single byte \"Y\"\n    //   [0x22] Single byte \"Z\"\n    //   [0x23] 17 possible previous repetitions of length at least 0x10 bytes:\n    //          - Repetition of 0x10 bytes from [0x00] \"EEEEEEEEEEEEEEEE\"\n    //          - Repetition of 0x10 bytes from [0x01] \"EEEEEEEEEEEEEEEE\"\n    //          - Repetition of 0x10 bytes from [0x02] \"EEEEEEEEEEEEEEEE\"\n    //          ...\n    //          - Repetition of 0x10 bytes from [0x0F] \"EEEEEEEEEEEEEEEE\"\n    //          - Repetition of 0x1C bytes from [0x10] \"EEEEEEEEEEEEEEEEQQQQQQQQQQQQ\"\n    //          The last repetition is the best one.\n    //\n\n    pWork->offs09BC[0] = 0xFFFF;\n    pWork->offs09BC[1] = 0x0000;\n    di_val = 0;\n\n    // Note: I failed to figure out what does the table \"offs09BC\" mean.\n    // If anyone has an idea, let me know to zezula_at_volny_dot_cz\n    for(offs_in_rep = 1; offs_in_rep < rep_length; )\n    {\n        if(input_data[offs_in_rep] != input_data[di_val])\n        {\n            di_val = pWork->offs09BC[di_val];\n            if(di_val != 0xFFFF)\n                continue;\n        }\n        pWork->offs09BC[++offs_in_rep] = ++di_val;\n    }\n\n    // \n    // Now go through all the repetitions from the first found one\n    // to the current input data, and check if any of them migh be\n    // a start of a greater sequence match.\n    //\n\n    prev_repetition = pWork->work_buff + phash_offs[0];\n    prev_rep_end = prev_repetition + rep_length;\n    rep_length2 = rep_length;\n    \n    for(;;)\n    {\n        rep_length2 = pWork->offs09BC[rep_length2];\n        if(rep_length2 == 0xFFFF)\n            rep_length2 = 0;\n\n        // Get the pointer to the previous repetition\n        phash_offs = pWork->phash_offs + phash_offs_index;\n\n        // Skip those repetitions that don't reach the end\n        // of the first found repetition\n        do\n        {\n            phash_offs++;\n            phash_offs_index++;\n            prev_repetition = pWork->work_buff + *phash_offs;\n            if(prev_repetition >= repetition_limit)\n                return rep_length;\n        }\n        while(prev_repetition + rep_length2 < prev_rep_end);\n\n        // Verify if the last but one byte from the repetition matches\n        // the last but one byte from the input data.\n        // If not, find a next repetition\n        pre_last_byte = input_data[rep_length - 2];\n        if(pre_last_byte == prev_repetition[rep_length - 2])\n        {\n            // If the new repetition reaches beyond the end\n            // of previously found repetition, reset the repetition length to zero.\n            if(prev_repetition + rep_length2 != prev_rep_end)\n            {\n                prev_rep_end = prev_repetition;\n                rep_length2 = 0;\n            }\n        }\n        else\n        {\n            phash_offs = pWork->phash_offs + phash_offs_index;\n            do\n            {\n                phash_offs++;\n                phash_offs_index++;\n                prev_repetition = pWork->work_buff + *phash_offs;\n                if(prev_repetition >= repetition_limit)\n                    return rep_length;\n            }\n            while(prev_repetition[rep_length - 2] != pre_last_byte || prev_repetition[0] != input_data[0]);\n\n            // Reset the length of the repetition to 2 bytes only\n            prev_rep_end = prev_repetition + 2;\n            rep_length2 = 2;\n        }\n\n        // Find out how many more characters are equal to the first repetition.\n        while(*prev_rep_end == input_data[rep_length2])\n        {\n            if(++rep_length2 >= 0x204)\n                break;\n            prev_rep_end++;\n        }\n\n        // Is the newly found repetion at least as long as the previous one ?\n        if(rep_length2 >= rep_length)\n        {\n            // Calculate the distance of the new repetition\n            pWork->distance = (unsigned int)(input_data - prev_repetition - 1);\n            if((rep_length = rep_length2) == 0x204)\n                return rep_length;\n\n            // Update the additional elements in the \"offs09BC\" table\n            // to reflect new rep length\n            while(offs_in_rep < rep_length2)\n            {\n                if(input_data[offs_in_rep] != input_data[di_val])\n                {\n                    di_val = pWork->offs09BC[di_val];\n                    if(di_val != 0xFFFF)\n                        continue;\n                }\n                pWork->offs09BC[++offs_in_rep] = ++di_val;\n            }\n        }\n    }\n}\n\nstatic void PKWAREAPI WriteCmpData(TCmpStruct * pWork)\n{\n    unsigned char * input_data_end;         // Pointer to the end of the input data\n    unsigned char * input_data = pWork->work_buff + pWork->dsize_bytes + 0x204;\n    unsigned int input_data_ended = 0;      // If 1, then all data from the input stream have been already loaded\n    unsigned int save_rep_length;           // Saved length of current repetition\n    unsigned int save_distance = 0;         // Saved distance of current repetition\n    unsigned int rep_length;                // Length of the found repetition\n    unsigned int phase = 0;                 // \n\n    // Store the compression type and dictionary size\n    pWork->out_buff[0] = (char)pWork->ctype;\n    pWork->out_buff[1] = (char)pWork->dsize_bits;\n    pWork->out_bytes = 2;\n\n    // Reset output buffer to zero\n    memset(&pWork->out_buff[2], 0, sizeof(pWork->out_buff) - 2);\n    pWork->out_bits = 0;\n\n    while(input_data_ended == 0)\n    {\n        unsigned int bytes_to_load = 0x1000;\n        int total_loaded = 0;\n        int bytes_loaded;\n\n        // Load the bytes from the input stream, up to 0x1000 bytes\n        while(bytes_to_load != 0)\n        {\n            bytes_loaded = pWork->read_buf((char *)pWork->work_buff + pWork->dsize_bytes + 0x204 + total_loaded,\n                                                  &bytes_to_load,\n                                                   pWork->param);\n            if(bytes_loaded == 0)\n            {\n                if(total_loaded == 0 && phase == 0)\n                    goto __Exit;\n                input_data_ended = 1;\n                break;\n            }\n            else\n            {\n                bytes_to_load -= bytes_loaded;\n                total_loaded += bytes_loaded;\n            }\n        }\n\n        input_data_end = pWork->work_buff + pWork->dsize_bytes + total_loaded;\n        if(input_data_ended)\n            input_data_end += 0x204;\n        \n        //\n        // Warning: The end of the buffer passed to \"SortBuffer\" is actually 2 bytes beyond\n        // valid data. It is questionable if this is actually a bug or not,\n        // but it might cause the compressed data output to be dependent on random bytes\n        // that are in the buffer. \n        // To prevent that, the calling application must always zero the compression\n        // buffer before passing it to \"implode\"\n        //\n\n        // Search the PAIR_HASHes of the loaded blocks. Also, include\n        // previously compressed data, if any.\n        switch(phase)\n        {\n            case 0: \n                SortBuffer(pWork, input_data, input_data_end + 1);\n                phase++;\n                if(pWork->dsize_bytes != 0x1000)\n                    phase++;\n                break;\n\n            case 1:\n                SortBuffer(pWork, input_data - pWork->dsize_bytes + 0x204, input_data_end + 1);\n                phase++;\n                break;\n\n            default:\n                SortBuffer(pWork, input_data - pWork->dsize_bytes, input_data_end + 1);\n                break;\n        }\n\n        // Perform the compression of the current block\n        while(input_data < input_data_end)\n        {\n            // Find if the current byte sequence wasn't there before.\n            rep_length = FindRep(pWork, input_data);\n            while(rep_length != 0)\n            {\n                // If we found repetition of 2 bytes, that is 0x100 or fuhrter back,\n                // don't bother. Storing the distance of 0x100 bytes would actually\n                // take more space than storing the 2 bytes as-is.\n                if(rep_length == 2 && pWork->distance >= 0x100)\n                    break;\n\n                // When we are at the end of the input data, we cannot allow\n                // the repetition to go past the end of the input data.\n                if(input_data_ended && input_data + rep_length > input_data_end)\n                {\n                    // Shorten the repetition length so that it only covers valid data\n                    rep_length = (unsigned long)(input_data_end - input_data);\n                    if(rep_length < 2)\n                        break;\n\n                    // If we got repetition of 2 bytes, that is 0x100 or more backward, don't bother\n                    if(rep_length == 2 && pWork->distance >= 0x100)\n                        break;\n                    goto __FlushRepetition;\n                }\n\n                if(rep_length >= 8 || input_data + 1 >= input_data_end)\n                    goto __FlushRepetition;\n\n                // Try to find better repetition 1 byte later.\n                // Example: \"ARROCKFORT\" \"AROCKFORT\"\n                // When \"input_data\" points to the second string, FindRep\n                // returns the occurence of \"AR\". But there is longer repetition \"ROCKFORT\",\n                // beginning 1 byte after.\n                save_rep_length = rep_length;\n                save_distance = pWork->distance;\n                rep_length = FindRep(pWork, input_data + 1);\n\n                // Only use the new repetition if it's length is greater than the previous one\n                if(rep_length > save_rep_length)\n                {\n                    // If the new repetition if only 1 byte better\n                    // and the previous distance is less than 0x80 bytes, use the previous repetition\n                    if(rep_length > save_rep_length + 1 || save_distance > 0x80)\n                    {\n                        // Flush one byte, so that input_data will point to the secondary repetition\n                        OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);\n                        input_data++;\n                        continue;\n                    }\n                }\n\n                // Revert to the previous repetition\n                rep_length = save_rep_length;\n                pWork->distance = save_distance;\n\n                __FlushRepetition:\n\n                OutputBits(pWork, pWork->nChBits[rep_length + 0xFE], pWork->nChCodes[rep_length + 0xFE]);\n                if(rep_length == 2)\n                {\n                    OutputBits(pWork, pWork->dist_bits[pWork->distance >> 2],\n                                      pWork->dist_codes[pWork->distance >> 2]);\n                    OutputBits(pWork, 2, pWork->distance & 3);\n                }\n                else\n                {\n                    OutputBits(pWork, pWork->dist_bits[pWork->distance >> pWork->dsize_bits],\n                                      pWork->dist_codes[pWork->distance >> pWork->dsize_bits]);\n                    OutputBits(pWork, pWork->dsize_bits, pWork->dsize_mask & pWork->distance);\n                }\n\n                // Move the begin of the input data by the length of the repetition\n                input_data += rep_length;\n                goto _00402252;\n            }\n\n            // If there was no previous repetition for the current position in the input data,\n            // just output the 9-bit literal for the one character\n            OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);\n            input_data++;\n_00402252:;\n        }\n\n        if(input_data_ended == 0)\n        {\n            input_data -= 0x1000;\n            memmove(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + 0x204);\n        }\n    }\n\n__Exit:\n\n    // Write the termination literal\n    OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);\n    if(pWork->out_bits != 0)\n        pWork->out_bytes++;\n    pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);\n    return;\n}\n\n//-----------------------------------------------------------------------------\n// Main imploding function\n\nunsigned int PKWAREAPI implode(\n    unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param),\n    void         (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param),\n    char         *work_buf,\n    void         *param,\n    unsigned int *type,\n    unsigned int *dsize)\n{\n    TCmpStruct * pWork = (TCmpStruct *)work_buf;\n    unsigned int nChCode;\n    unsigned int nCount;\n    unsigned int i;\n    int nCount2;\n\n    // Fill the work buffer information\n    // Note: The caller must zero the \"work_buff\" before passing it to implode\n    pWork->read_buf    = read_buf;\n    pWork->write_buf   = write_buf;\n    pWork->dsize_bytes = *dsize;\n    pWork->ctype       = *type;\n    pWork->param       = param;\n    pWork->dsize_bits  = 4;\n    pWork->dsize_mask  = 0x0F;\n\n    // Test dictionary size\n    switch(*dsize)\n    {\n        case CMP_IMPLODE_DICT_SIZE3:    // 0x1000 bytes\n            pWork->dsize_bits++;\n            pWork->dsize_mask |= 0x20;\n            // No break here !!!\n\n        case CMP_IMPLODE_DICT_SIZE2:    // 0x800 bytes\n            pWork->dsize_bits++;\n            pWork->dsize_mask |= 0x10;\n            // No break here !!!\n\n        case CMP_IMPLODE_DICT_SIZE1:    // 0x400\n            break;\n\n        default:\n            return CMP_INVALID_DICTSIZE;\n    }\n\n    // Test the compression type\n    switch(*type)\n    {\n        case CMP_BINARY: // We will compress data with binary compression type\n            for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)\n            {\n                pWork->nChBits[nCount]  = 9;\n                pWork->nChCodes[nCount] = (unsigned short)nChCode;\n                nChCode = (nChCode & 0x0000FFFF) + 2;\n            }\n            break;\n\n\n        case CMP_ASCII: // We will compress data with ASCII compression type\n            for(nCount = 0; nCount < 0x100; nCount++)\n            {\n                pWork->nChBits[nCount]  = (unsigned char )(ChBitsAsc[nCount] + 1);\n                pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);\n            }\n            break;\n\n        default:\n            return CMP_INVALID_MODE;\n    }\n\n    for(i = 0; i < 0x10; i++)\n    {\n        if(1 << ExLenBits[i])\n        {\n            for(nCount2 = 0; nCount2 < (1 << ExLenBits[i]); nCount2++)\n            {\n                pWork->nChBits[nCount]  = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);\n                pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);\n                nCount++;\n            }\n        }\n    }\n\n    // Copy the distance codes and distance bits and perform the compression\n    memcpy(&pWork->dist_codes, DistCode, sizeof(DistCode));\n    memcpy(&pWork->dist_bits, DistBits, sizeof(DistBits));\n    WriteCmpData(pWork);\n    return CMP_NO_ERROR;\n}\n"
  },
  {
    "path": "3rdParty/PKWare/pkware.h",
    "content": "/*****************************************************************************/\n/* pkware.h                               Copyright (c) Ladislav Zezula 2003 */\n/*---------------------------------------------------------------------------*/\n/* Header file for PKWARE Data Compression Library                           */\n/*---------------------------------------------------------------------------*/\n/*   Date    Ver   Who  Comment                                              */\n/* --------  ----  ---  -------                                              */\n/* 31.03.03  1.00  Lad  The first version of pkware.h                        */\n/*****************************************************************************/\n\n#ifndef __PKWARE_H__\n#define __PKWARE_H__\n\n//-----------------------------------------------------------------------------\n// Defines\n\n#define CMP_BINARY             0            // Binary compression\n#define CMP_ASCII              1            // Ascii compression\n\n#define CMP_NO_ERROR           0\n#define CMP_INVALID_DICTSIZE   1\n#define CMP_INVALID_MODE       2\n#define CMP_BAD_DATA           3\n#define CMP_ABORT              4\n\n#define CMP_IMPLODE_DICT_SIZE1   1024       // Dictionary size of 1024\n#define CMP_IMPLODE_DICT_SIZE2   2048       // Dictionary size of 2048\n#define CMP_IMPLODE_DICT_SIZE3   4096       // Dictionary size of 4096\n\n//-----------------------------------------------------------------------------\n// Define calling convention\n\n#ifndef PKWAREAPI\n#ifdef WIN32\n#define PKWAREAPI  __cdecl                   // Use for normal __cdecl calling \n#else\n#define PKWAREAPI\n#endif\n#endif\n\n//-----------------------------------------------------------------------------\n// Internal structures\n\n// Compression structure\ntypedef struct\n{\n    unsigned int   distance;                // 0000: Backward distance of the currently found repetition, decreased by 1\n    unsigned int   out_bytes;               // 0004: # bytes available in out_buff            \n    unsigned int   out_bits;                // 0008: # of bits available in the last out byte\n    unsigned int   dsize_bits;              // 000C: Number of bits needed for dictionary size. 4 = 0x400, 5 = 0x800, 6 = 0x1000\n    unsigned int   dsize_mask;              // 0010: Bit mask for dictionary. 0x0F = 0x400, 0x1F = 0x800, 0x3F = 0x1000\n    unsigned int   ctype;                   // 0014: Compression type (CMP_ASCII or CMP_BINARY)\n    unsigned int   dsize_bytes;             // 0018: Dictionary size in bytes\n    unsigned char  dist_bits[0x40];         // 001C: Distance bits\n    unsigned char  dist_codes[0x40];        // 005C: Distance codes\n    unsigned char  nChBits[0x306];          // 009C: Table of literal bit lengths to be put to the output stream\n    unsigned short nChCodes[0x306];         // 03A2: Table of literal codes to be put to the output stream\n    unsigned short offs09AE;                // 09AE: \n\n    void         * param;                   // 09B0: User parameter\n    unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param);  // 9B4\n    void         (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param); // 9B8\n\n    unsigned short offs09BC[0x204];         // 09BC:\n    unsigned long  offs0DC4;                // 0DC4: \n    unsigned short phash_to_index[0x900];   // 0DC8: Array of indexes (one for each PAIR_HASH) to the \"pair_hash_offsets\" table\n    unsigned short phash_to_index_end;      // 1FC8: End marker for \"phash_to_index\" table\n    char           out_buff[0x802];         // 1FCA: Compressed data\n    unsigned char  work_buff[0x2204];       // 27CC: Work buffer\n                                            //  + DICT_OFFSET  => Dictionary\n                                            //  + UNCMP_OFFSET => Uncompressed data\n    unsigned short phash_offs[0x2204];      // 49D0: Table of offsets for each PAIR_HASH\n} TCmpStruct;\n\n#define CMP_BUFFER_SIZE  sizeof(TCmpStruct) // Size of compression structure.\n                                            // Defined as 36312 in pkware header file\n\n\n// Decompression structure\ntypedef struct\n{\n    unsigned long offs0000;                 // 0000\n    unsigned long ctype;                    // 0004: Compression type (CMP_BINARY or CMP_ASCII)\n    unsigned long outputPos;                // 0008: Position in output buffer\n    unsigned long dsize_bits;               // 000C: Dict size (4, 5, 6 for 0x400, 0x800, 0x1000)\n    unsigned long dsize_mask;               // 0010: Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000)\n    unsigned long bit_buff;                 // 0014: 16-bit buffer for processing input data\n    unsigned long extra_bits;               // 0018: Number of extra (above 8) bits in bit buffer\n    unsigned int  in_pos;                   // 001C: Position in in_buff\n    unsigned long in_bytes;                 // 0020: Number of bytes in input buffer\n    void        * param;                    // 0024: Custom parameter\n    unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param); // Pointer to function that reads data from the input stream\n    void         (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param);// Pointer to function that writes data to the output stream\n\n    unsigned char out_buff[0x2204];         // 0030: Output circle buffer.\n                                            //       0x0000 - 0x0FFF: Previous uncompressed data, kept for repetitions\n                                            //       0x1000 - 0x1FFF: Currently decompressed data\n                                            //       0x2000 - 0x2203: Reserve space for the longest possible repetition\n    unsigned char in_buff[0x800];           // 2234: Buffer for data to be decompressed\n    unsigned char DistPosCodes[0x100];      // 2A34: Table of distance position codes\n    unsigned char LengthCodes[0x100];       // 2B34: Table of length codes\n    unsigned char offs2C34[0x100];          // 2C34: Buffer for \n    unsigned char offs2D34[0x100];          // 2D34: Buffer for \n    unsigned char offs2E34[0x80];           // 2EB4: Buffer for \n    unsigned char offs2EB4[0x100];          // 2EB4: Buffer for \n    unsigned char ChBitsAsc[0x100];         // 2FB4: Buffer for \n    unsigned char DistBits[0x40];           // 30B4: Numbers of bytes to skip copied block length\n    unsigned char LenBits[0x10];            // 30F4: Numbers of bits for skip copied block length\n    unsigned char ExLenBits[0x10];          // 3104: Number of valid bits for copied block\n    unsigned short LenBase[0x10];           // 3114: Buffer for \n} TDcmpStruct;\n\n#define EXP_BUFFER_SIZE sizeof(TDcmpStruct) // Size of decompression structure\n                                            // Defined as 12596 in pkware headers\n\n//-----------------------------------------------------------------------------\n// Public functions\n\n#ifdef __cplusplus\n   extern \"C\" {\n#endif\n\nunsigned int PKWAREAPI implode(\n   unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param),\n   void         (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param),\n   char         *work_buf,\n   void         *param,\n   unsigned int *type,\n   unsigned int *dsize);\n\n\nunsigned int PKWAREAPI explode(\n   unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned  int *size, void *param),\n   void         (PKWAREAPI *write_buf)(char *buf, unsigned  int *size, void *param),\n   char         *work_buf,\n   void         *param);\n\n#ifdef __cplusplus\n   }                         // End of 'extern \"C\"' declaration\n#endif\n\n#endif // __PKWARE_H__\n"
  },
  {
    "path": "3rdParty/PicoSHA2/picosha2.h",
    "content": "/*\nThe MIT License (MIT)\n\nCopyright (C) 2017 okdshin\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*/\n#ifndef PICOSHA2_H\n#define PICOSHA2_H\n// picosha2:20140213\n\n#ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR\n#define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \\\n    1048576  //=1024*1024: default is 1MB memory\n#endif\n\n#include <algorithm>\n#include <cassert>\n#include <iterator>\n#include <sstream>\n#include <vector>\n#include <fstream>\nnamespace picosha2 {\ntypedef unsigned long word_t;\ntypedef unsigned char byte_t;\n\nstatic const size_t k_digest_size = 32;\n\nnamespace detail {\ninline byte_t mask_8bit(byte_t x) { return x & 0xff; }\n\ninline word_t mask_32bit(word_t x) { return x & 0xffffffff; }\n\nconst word_t add_constant[64] = {\n    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,\n    0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\n    0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,\n    0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n    0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\n    0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};\n\nconst word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,\n                                          0xa54ff53a, 0x510e527f, 0x9b05688c,\n                                          0x1f83d9ab, 0x5be0cd19};\n\ninline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }\n\ninline word_t maj(word_t x, word_t y, word_t z) {\n    return (x & y) ^ (x & z) ^ (y & z);\n}\n\ninline word_t rotr(word_t x, std::size_t n) {\n    assert(n < 32);\n    return mask_32bit((x >> n) | (x << (32 - n)));\n}\n\ninline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }\n\ninline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }\n\ninline word_t shr(word_t x, std::size_t n) {\n    assert(n < 32);\n    return x >> n;\n}\n\ninline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }\n\ninline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }\n\ntemplate <typename RaIter1, typename RaIter2>\nvoid hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) {\n    assert(first + 64 == last);\n    static_cast<void>(last);  // for avoiding unused-variable warning\n    word_t w[64];\n    std::fill(w, w + 64, 0);\n    for (std::size_t i = 0; i < 16; ++i) {\n        w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |\n               (static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |\n               (static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |\n               (static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));\n    }\n    for (std::size_t i = 16; i < 64; ++i) {\n        w[i] = mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) +\n                          w[i - 16]);\n    }\n\n    word_t a = *message_digest;\n    word_t b = *(message_digest + 1);\n    word_t c = *(message_digest + 2);\n    word_t d = *(message_digest + 3);\n    word_t e = *(message_digest + 4);\n    word_t f = *(message_digest + 5);\n    word_t g = *(message_digest + 6);\n    word_t h = *(message_digest + 7);\n\n    for (std::size_t i = 0; i < 64; ++i) {\n        word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];\n        word_t temp2 = bsig0(a) + maj(a, b, c);\n        h = g;\n        g = f;\n        f = e;\n        e = mask_32bit(d + temp1);\n        d = c;\n        c = b;\n        b = a;\n        a = mask_32bit(temp1 + temp2);\n    }\n    *message_digest += a;\n    *(message_digest + 1) += b;\n    *(message_digest + 2) += c;\n    *(message_digest + 3) += d;\n    *(message_digest + 4) += e;\n    *(message_digest + 5) += f;\n    *(message_digest + 6) += g;\n    *(message_digest + 7) += h;\n    for (std::size_t i = 0; i < 8; ++i) {\n        *(message_digest + i) = mask_32bit(*(message_digest + i));\n    }\n}\n\n}  // namespace detail\n\ntemplate <typename InIter>\nvoid output_hex(InIter first, InIter last, std::ostream& os) {\n    os.setf(std::ios::hex, std::ios::basefield);\n    while (first != last) {\n        os.width(2);\n        os.fill('0');\n        os << static_cast<unsigned int>(*first);\n        ++first;\n    }\n    os.setf(std::ios::dec, std::ios::basefield);\n}\n\ntemplate <typename InIter>\nvoid bytes_to_hex_string(InIter first, InIter last, std::string& hex_str) {\n    std::ostringstream oss;\n    output_hex(first, last, oss);\n    hex_str.assign(oss.str());\n}\n\ntemplate <typename InContainer>\nvoid bytes_to_hex_string(const InContainer& bytes, std::string& hex_str) {\n    bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);\n}\n\ntemplate <typename InIter>\nstd::string bytes_to_hex_string(InIter first, InIter last) {\n    std::string hex_str;\n    bytes_to_hex_string(first, last, hex_str);\n    return hex_str;\n}\n\ntemplate <typename InContainer>\nstd::string bytes_to_hex_string(const InContainer& bytes) {\n    std::string hex_str;\n    bytes_to_hex_string(bytes, hex_str);\n    return hex_str;\n}\n\nclass hash256_one_by_one {\n   public:\n    hash256_one_by_one() { init(); }\n\n    void init() {\n        buffer_.clear();\n        std::fill(data_length_digits_, data_length_digits_ + 4, 0);\n        std::copy(detail::initial_message_digest,\n                  detail::initial_message_digest + 8, h_);\n    }\n\n    template <typename RaIter>\n    void process(RaIter first, RaIter last) {\n        add_to_data_length(static_cast<word_t>(std::distance(first, last)));\n        std::copy(first, last, std::back_inserter(buffer_));\n        std::size_t i = 0;\n        for (; i + 64 <= buffer_.size(); i += 64) {\n            detail::hash256_block(h_, buffer_.begin() + i,\n                                  buffer_.begin() + i + 64);\n        }\n        buffer_.erase(buffer_.begin(), buffer_.begin() + i);\n    }\n\n    void finish() {\n        byte_t temp[64];\n        std::fill(temp, temp + 64, 0);\n        std::size_t remains = buffer_.size();\n        std::copy(buffer_.begin(), buffer_.end(), temp);\n        temp[remains] = 0x80;\n\n        if (remains > 55) {\n            std::fill(temp + remains + 1, temp + 64, 0);\n            detail::hash256_block(h_, temp, temp + 64);\n            std::fill(temp, temp + 64 - 4, 0);\n        } else {\n            std::fill(temp + remains + 1, temp + 64 - 4, 0);\n        }\n\n        write_data_bit_length(&(temp[56]));\n        detail::hash256_block(h_, temp, temp + 64);\n    }\n\n    template <typename OutIter>\n    void get_hash_bytes(OutIter first, OutIter last) const {\n        for (const word_t* iter = h_; iter != h_ + 8; ++iter) {\n            for (std::size_t i = 0; i < 4 && first != last; ++i) {\n                *(first++) = detail::mask_8bit(\n                    static_cast<byte_t>((*iter >> (24 - 8 * i))));\n            }\n        }\n    }\n\n   private:\n    void add_to_data_length(word_t n) {\n        word_t carry = 0;\n        data_length_digits_[0] += n;\n        for (std::size_t i = 0; i < 4; ++i) {\n            data_length_digits_[i] += carry;\n            if (data_length_digits_[i] >= 65536u) {\n                carry = data_length_digits_[i] >> 16;\n                data_length_digits_[i] &= 65535u;\n            } else {\n                break;\n            }\n        }\n    }\n    void write_data_bit_length(byte_t* begin) {\n        word_t data_bit_length_digits[4];\n        std::copy(data_length_digits_, data_length_digits_ + 4,\n                  data_bit_length_digits);\n\n        // convert byte length to bit length (multiply 8 or shift 3 times left)\n        word_t carry = 0;\n        for (std::size_t i = 0; i < 4; ++i) {\n            word_t before_val = data_bit_length_digits[i];\n            data_bit_length_digits[i] <<= 3;\n            data_bit_length_digits[i] |= carry;\n            data_bit_length_digits[i] &= 65535u;\n            carry = (before_val >> (16 - 3)) & 65535u;\n        }\n\n        // write data_bit_length\n        for (int i = 3; i >= 0; --i) {\n            (*begin++) = static_cast<byte_t>(data_bit_length_digits[i] >> 8);\n            (*begin++) = static_cast<byte_t>(data_bit_length_digits[i]);\n        }\n    }\n    std::vector<byte_t> buffer_;\n    word_t data_length_digits_[4];  // as 64bit integer (16bit x 4 integer)\n    word_t h_[8];\n};\n\ninline void get_hash_hex_string(const hash256_one_by_one& hasher,\n                                std::string& hex_str) {\n    byte_t hash[k_digest_size];\n    hasher.get_hash_bytes(hash, hash + k_digest_size);\n    return bytes_to_hex_string(hash, hash + k_digest_size, hex_str);\n}\n\ninline std::string get_hash_hex_string(const hash256_one_by_one& hasher) {\n    std::string hex_str;\n    get_hash_hex_string(hasher, hex_str);\n    return hex_str;\n}\n\nnamespace impl {\ntemplate <typename RaIter, typename OutIter>\nvoid hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int,\n                  std::random_access_iterator_tag) {\n    hash256_one_by_one hasher;\n    // hasher.init();\n    hasher.process(first, last);\n    hasher.finish();\n    hasher.get_hash_bytes(first2, last2);\n}\n\ntemplate <typename InputIter, typename OutIter>\nvoid hash256_impl(InputIter first, InputIter last, OutIter first2,\n                  OutIter last2, int buffer_size, std::input_iterator_tag) {\n    std::vector<byte_t> buffer(buffer_size);\n    hash256_one_by_one hasher;\n    // hasher.init();\n    while (first != last) {\n        int size = buffer_size;\n        for (int i = 0; i != buffer_size; ++i, ++first) {\n            if (first == last) {\n                size = i;\n                break;\n            }\n            buffer[i] = *first;\n        }\n        hasher.process(buffer.begin(), buffer.begin() + size);\n    }\n    hasher.finish();\n    hasher.get_hash_bytes(first2, last2);\n}\n}\n\ntemplate <typename InIter, typename OutIter>\nvoid hash256(InIter first, InIter last, OutIter first2, OutIter last2,\n             int buffer_size = PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR) {\n    picosha2::impl::hash256_impl(\n        first, last, first2, last2, buffer_size,\n        typename std::iterator_traits<InIter>::iterator_category());\n}\n\ntemplate <typename InIter, typename OutContainer>\nvoid hash256(InIter first, InIter last, OutContainer& dst) {\n    hash256(first, last, dst.begin(), dst.end());\n}\n\ntemplate <typename InContainer, typename OutIter>\nvoid hash256(const InContainer& src, OutIter first, OutIter last) {\n    hash256(src.begin(), src.end(), first, last);\n}\n\ntemplate <typename InContainer, typename OutContainer>\nvoid hash256(const InContainer& src, OutContainer& dst) {\n    hash256(src.begin(), src.end(), dst.begin(), dst.end());\n}\n\ntemplate <typename InIter>\nvoid hash256_hex_string(InIter first, InIter last, std::string& hex_str) {\n    byte_t hashed[k_digest_size];\n    hash256(first, last, hashed, hashed + k_digest_size);\n    std::ostringstream oss;\n    output_hex(hashed, hashed + k_digest_size, oss);\n    hex_str.assign(oss.str());\n}\n\ntemplate <typename InIter>\nstd::string hash256_hex_string(InIter first, InIter last) {\n    std::string hex_str;\n    hash256_hex_string(first, last, hex_str);\n    return hex_str;\n}\n\ninline void hash256_hex_string(const std::string& src, std::string& hex_str) {\n    hash256_hex_string(src.begin(), src.end(), hex_str);\n}\n\ntemplate <typename InContainer>\nvoid hash256_hex_string(const InContainer& src, std::string& hex_str) {\n    hash256_hex_string(src.begin(), src.end(), hex_str);\n}\n\ntemplate <typename InContainer>\nstd::string hash256_hex_string(const InContainer& src) {\n    return hash256_hex_string(src.begin(), src.end());\n}\ntemplate<typename OutIter>void hash256(std::ifstream& f, OutIter first, OutIter last){\n    hash256(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>(), first,last);\n\n}\n}// namespace picosha2\n#endif  // PICOSHA2_H\n"
  },
  {
    "path": "3rdParty/SDL2/CMake/FindSDL2.cmake",
    "content": "if(UWP_LIB AND NOT TARGET SDL2::SDL2-static)\r\n  set(SDL_BUILD_TYPE \"Release\")\r\n\r\n  if(CMAKE_BUILD_TYPE MATCHES \"Debug\")\r\n    set(SDL_BUILD_TYPE \"Debug\")\r\n  endif()\r\n\r\n  set(SDL2_LIBRARY \"${UWP_SDL2_DIR}/VisualC-WinRT/x64/${SDL_BUILD_TYPE}/SDL-UWP\")\r\n  set(SDL2_INCLUDE_DIR \"${UWP_SDL2_DIR}/include\")\r\n  add_library(SDL2_lib STATIC IMPORTED)\r\n  set_property(TARGET SDL2_lib PROPERTY IMPORTED_LOCATION \"${SDL2_LIBRARY}/SDL2.lib\")\r\n  set_property(TARGET SDL2_lib PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR})\r\n  add_library(SDL2::SDL2-static ALIAS SDL2_lib)\r\n  mark_as_advanced(SDL2_INCLUDE_DIR SDL2_LIBRARY)\r\n  set(SDL2_LIBRARIES ${SDL2_LIBRARY})\r\n  set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/SDL2/CMakeLists.txt",
    "content": "if(DEVILUTIONX_STATIC_SDL2)\r\n  set(BUILD_SHARED_LIBS OFF)\r\n  set(SDL_SHARED OFF)\r\n  set(SDL_STATIC ON)\r\n  if(PIE)\r\n    set(SDL_STATIC_PIC ON)\r\n  endif()\r\nelse()\r\n  set(BUILD_SHARED_LIBS ON)\r\n  set(SDL_SHARED ON)\r\n  set(SDL_STATIC OFF)\r\nendif()\r\nset(SDL_TEST_ENABLED_BY_DEFAULT OFF)\r\n\r\ninclude(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nif(TARGET_PLATFORM STREQUAL \"dos\")\r\n  set(DOS ON)\r\n  FetchContent_Declare(SDL2\r\n    # branch: dos-vbe-rebase\r\n    URL https://github.com/diasurgical/SDL/archive/20b47a62a12f0c7be4052fb5b32eb21d709d6f06.tar.gz\r\n    URL_HASH MD5=6e77a1d1a79d7f0dd6231b39515a341f\r\n  )\r\nelse()\r\n  FetchContent_Declare(SDL2\r\n    URL https://github.com/libsdl-org/SDL/releases/download/release-2.32.8/SDL2-2.32.8.tar.gz\r\n    URL_HASH SHA256=0ca83e9c9b31e18288c7ec811108e58bac1f1bb5ec6577ad386830eac51c787e\r\n  )\r\nendif()\r\nFetchContent_MakeAvailable_ExcludeFromAll(SDL2)\r\n"
  },
  {
    "path": "3rdParty/SDL3/CMakeLists.txt",
    "content": "if(DEVILUTIONX_STATIC_SDL3)\r\n  set(BUILD_SHARED_LIBS OFF)\r\n  set(SDL_SHARED OFF)\r\n  set(SDL_STATIC ON)\r\n  if(PIE)\r\n    set(SDL_STATIC_PIC ON)\r\n  endif()\r\nelse()\r\n  set(BUILD_SHARED_LIBS ON)\r\n  set(SDL_SHARED ON)\r\n  set(SDL_STATIC OFF)\r\nendif()\r\nset(SDL_TEST_ENABLED_BY_DEFAULT OFF)\r\n\r\ninclude(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nFetchContent_Declare(SDL3\r\n  URL https://github.com/libsdl-org/SDL/archive/f173fd28f04cb64ae054d6a97edb5d33925f539b.tar.gz\r\n  URL_HASH SHA256=f7501d84c1a7f168567c002f4e1db4f220c4a34c51f7fa7d199962d0ed5fb42c\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(SDL3)\r\n"
  },
  {
    "path": "3rdParty/SDL3_image/CMakeLists.txt",
    "content": "include(functions/dependency_options)\r\n\r\nif(NOT DEFINED DEVILUTIONX_SYSTEM_LIBPNG)\r\n  find_package(PNG QUIET)\r\n  if(PNG_FOUND)\r\n    message(\"-- Found png ${PNG_VERSION_STRING}\")\r\n  else()\r\n    message(\"-- Suitable system png package not found, will use png from source\")\r\n    set(DEVILUTIONX_SYSTEM_LIBPNG OFF)\r\n  endif()\r\nendif()\r\ndependency_options(\"libpng\" DEVILUTIONX_SYSTEM_LIBPNG ON DEVILUTIONX_STATIC_LIBPNG)\r\nif(DEVILUTIONX_SYSTEM_LIBPNG)\r\n  find_package(PNG REQUIRED)\r\nelse()\r\n  add_subdirectory(../libpng libpng)\r\nendif()\r\n\r\ninclude(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nif(DEVILUTIONX_STATIC_SDL_IMAGE)\r\n  set(BUILD_SHARED_LIBS OFF)\r\nelse()\r\n  set(BUILD_SHARED_LIBS ON)\r\nendif()\r\n\r\nset(SDLIMAGE_BACKEND_STB OFF)\r\nset(SDLIMAGE_AVIF OFF)\r\nset(SDLIMAGE_BMP OFF)\r\nset(SDLIMAGE_GIF OFF)\r\nset(SDLIMAGE_JPG OFF)\r\nset(SDLIMAGE_JXL OFF)\r\nset(SDLIMAGE_LBM OFF)\r\nset(SDLIMAGE_PCX OFF)\r\nset(SDLIMAGE_PNG ON)\r\nset(SDLIMAGE_PNM OFF)\r\nset(SDLIMAGE_QOI OFF)\r\nset(SDLIMAGE_SVG OFF)\r\nset(SDLIMAGE_TGA OFF)\r\nset(SDLIMAGE_TIF OFF)\r\nset(SDLIMAGE_WEBP OFF)\r\nset(SDLIMAGE_XCF OFF)\r\nset(SDLIMAGE_XPM OFF)\r\nset(SDLIMAGE_XV OFF)\r\nset(SDLIMAGE_AVIF_SAVE OFF)\r\nset(SDLIMAGE_JPG_SAVE OFF)\r\nset(SDLIMAGE_PNG_SAVE ON)\r\n\r\nFetchContent_Declare_ExcludeFromAll(SDL_image\r\n  URL https://github.com/libsdl-org/SDL_image/releases/download/release-3.2.4/SDL3_image-3.2.4.tar.gz\r\n  URL_HASH SHA256=a725bd6d04261fdda0dd8d950659e1dc15a8065d025275ef460d32ae7dcfc182\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(SDL_image)\r\n"
  },
  {
    "path": "3rdParty/SDL3_mixer/CMakeLists.txt",
    "content": "include(functions/dependency_options)\r\ninclude(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nif(DEVILUTIONX_STATIC_SDL_MIXER)\r\n  set(BUILD_SHARED_LIBS OFF)\r\nelse()\r\n  set(BUILD_SHARED_LIBS ON)\r\nendif()\r\n\r\nset(SDLMIXER_AIFF OFF)\r\nset(SDLMIXER_WAVE ON)\r\nset(SDLMIXER_VOC OFF)\r\nset(SDLMIXER_AU OFF)\r\nset(SDLMIXER_FLAC_LIBFLAC OFF)\r\nset(SDLMIXER_FLAC_DRFLAC OFF)\r\nset(SDLMIXER_GME OFF)\r\nset(SDLMIXER_MOD_XMP OFF)\r\nset(SDLMIXER_MP3_DRMP3 ON)\r\nset(SDLMIXER_MP3_MPG123 OFF)\r\nset(SDLMIXER_MIDI_FLUIDSYNTH OFF)\r\nset(SDLMIXER_MIDI_TIMIDITY OFF)\r\nset(SDLMIXER_OPUS OFF)\r\nset(SDLMIXER_VORBIS_STB OFF)\r\nset(SDLMIXER_VORBIS_VORBISFILE OFF)\r\nset(SDLMIXER_VORBIS_TREMOR OFF)\r\nset(SDLMIXER_WAVPACK OFF)\r\n\r\nFetchContent_Declare_ExcludeFromAll(SDL_mixer\r\n  URL https://github.com/libsdl-org/SDL_mixer/archive/7d37755016f0952c32c9483c556d8608da7ee82f.tar.gz\r\n  URL_HASH SHA256=2fa63f1eb623e3acd0012a461771eb93332e2026205f9487da3a3a75bc790111\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(SDL_mixer)\r\n"
  },
  {
    "path": "3rdParty/SDL_audiolib/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\nif(DEVILUTIONX_STATIC_SDL_AUDIOLIB)\r\n  set(BUILD_SHARED_LIBS OFF)\r\nelse()\r\n  set(BUILD_SHARED_LIBS ON)\r\nendif()\r\n\r\n# Will use our `fmt::fmt` target if it exists.\r\nset(WITH_SYSTEM_FMTLIB ON)\r\n\r\n# No need for the libsamplerate resampler:\r\nset(USE_RESAMP_SRC OFF)\r\n\r\n# No need for the SOX resampler:\r\nset(USE_RESAMP_SOXR OFF)\r\n\r\n# Exceptions are only used for fatal errors which we can't handle anyway:\r\nset(DISABLE_EXCEPTIONS ON)\r\n\r\n# We do not need any of the audio formats except WAV and mp3:\r\nset(USE_DEC_DRWAV ON)\r\nset(USE_DEC_DRFLAC OFF)\r\nset(USE_DEC_OPENMPT OFF)\r\nset(USE_DEC_XMP OFF)\r\nset(USE_DEC_MODPLUG OFF)\r\nset(USE_DEC_MPG123 OFF)\r\nset(USE_DEC_SNDFILE OFF)\r\nset(USE_DEC_LIBVORBIS OFF)\r\nset(USE_DEC_LIBOPUSFILE OFF)\r\nset(USE_DEC_FLAC OFF)\r\nset(USE_DEC_MUSEPACK OFF)\r\nset(USE_DEC_FLUIDSYNTH OFF)\r\nset(USE_DEC_BASSMIDI OFF)\r\nset(USE_DEC_WILDMIDI OFF)\r\nset(USE_DEC_ADLMIDI OFF)\r\nset(USE_DEC_DRMP3 ON)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(SDL_audiolib\r\n  URL https://github.com/realnc/SDL_audiolib/archive/cc1bb6af8d4cf5e200259072bde1edd1c8c5137e.tar.gz\r\n  URL_HASH MD5=0e8174264ac9c6b314c6b2d9a5f72efd)\r\nFetchContent_MakeAvailable_ExcludeFromAll(SDL_audiolib)\r\n\r\nadd_library(SDL_audiolib::SDL_audiolib ALIAS SDL_audiolib)\r\n\r\n# External library, disable warnings.\r\ntarget_compile_options(SDL_audiolib PRIVATE -w)\r\n"
  },
  {
    "path": "3rdParty/SDL_image/CMakeLists.txt",
    "content": "include(functions/dependency_options)\r\n\r\nif(NOT DEFINED DEVILUTIONX_SYSTEM_LIBPNG)\r\n  find_package(PNG QUIET)\r\n  if(PNG_FOUND)\r\n    message(\"-- Found png ${PNG_VERSION_STRING}\")\r\n  else()\r\n    message(\"-- Suitable system png package not found, will use png from source\")\r\n    set(DEVILUTIONX_SYSTEM_LIBPNG OFF)\r\n  endif()\r\nendif()\r\ndependency_options(\"libpng\" DEVILUTIONX_SYSTEM_LIBPNG ON DEVILUTIONX_STATIC_LIBPNG)\r\nif(DEVILUTIONX_SYSTEM_LIBPNG)\r\n  find_package(PNG REQUIRED)\r\nelse()\r\n  add_subdirectory(../libpng libpng)\r\nendif()\r\n\r\ninclude(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nFetchContent_Declare_ExcludeFromAll(SDL_image\r\n  URL https://github.com/libsdl-org/SDL_image/archive/refs/tags/release-2.0.5.tar.gz\r\n  URL_HASH MD5=3446ed7ee3c700065dcb33426a9b0c6e\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(SDL_image)\r\n\r\nif(DEVILUTIONX_STATIC_SDL_IMAGE)\r\n  add_library(SDL_image STATIC ${CMAKE_CURRENT_LIST_DIR}/IMG.c ${sdl_image_SOURCE_DIR}/IMG_png.c)\r\nelse()\r\n  add_library(SDL_image SHARED ${CMAKE_CURRENT_LIST_DIR}/IMG.c ${sdl_image_SOURCE_DIR}/IMG_png.c)\r\nendif()\r\n\r\ntarget_include_directories(SDL_image PRIVATE ${sdl_image_SOURCE_DIR})\r\ntarget_compile_definitions(SDL_image PRIVATE LOAD_PNG SDL_IMAGE_USE_COMMON_BACKEND)\r\ntarget_link_libraries(SDL_image PNG::PNG)\r\n\r\nif(TARGET SDL2::SDL2 AND NOT (DEVILUTIONX_STATIC_SDL2 AND TARGET SDL2::SDL2-static))\r\n  target_link_libraries(SDL_image SDL2::SDL2)\r\n  add_library(SDL2::SDL2_image ALIAS SDL_image)\r\nelseif(TARGET SDL2::SDL2-static)\r\n  target_link_libraries(SDL_image SDL2::SDL2-static)\r\n  add_library(SDL2::SDL2_image ALIAS SDL_image)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/SDL_image/IMG.c",
    "content": "/*\r\n  SDL_image:  An example image loading library for use with SDL\r\n  Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>\r\n  This software is provided 'as-is', without any express or implied\r\n  warranty.  In no event will the authors be held liable for any damages\r\n  arising from the use of this software.\r\n  Permission is granted to anyone to use this software for any purpose,\r\n  including commercial applications, and to alter it and redistribute it\r\n  freely, subject to the following restrictions:\r\n  1. The origin of this software must not be misrepresented; you must not\r\n         claim that you wrote the original software. If you use this software\r\n         in a product, an acknowledgment in the product documentation would be\r\n         appreciated but is not required.\r\n  2. Altered source versions must be plainly marked as such, and must not be\r\n         misrepresented as being the original software.\r\n  3. This notice may not be removed or altered from any source distribution.\r\n*/\r\n\r\n/* This is a heavily reduced version of IMG.c including only PNG support */\r\n\r\n#include \"SDL_image.h\"\r\n\r\nextern int IMG_InitPNG(void);\r\nextern void IMG_QuitPNG(void);\r\n\r\nstatic int initialized = 0;\r\n\r\nint IMG_Init(int flags) {\r\n  int result = 0;\r\n\r\n  /* Passing 0 returns the currently initialized loaders */\r\n  if (!flags) {\r\n    return initialized;\r\n  }\r\n\r\n  if (flags & IMG_INIT_PNG) {\r\n    if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) {\r\n      result |= IMG_INIT_PNG;\r\n    }\r\n  }\r\n  initialized |= result;\r\n\r\n  return result;\r\n}\r\n\r\nvoid IMG_Quit() {\r\n  if (initialized & IMG_INIT_PNG) {\r\n    IMG_QuitPNG();\r\n  }\r\n  initialized = 0;\r\n}\r\n"
  },
  {
    "path": "3rdParty/SheenBidi/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nset(BUILD_TESTING OFF)\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\n\r\nFetchContent_Declare_ExcludeFromAll(SheenBidi\r\n  URL https://github.com/Tehreer/SheenBidi/archive/refs/tags/v2.9.0.tar.gz\r\n  URL_HASH MD5=2c22cfad93a52afa7bd25ad56a3a4089\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(SheenBidi)\r\n"
  },
  {
    "path": "3rdParty/asio/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(asio\r\n    URL https://github.com/diasurgical/asio/archive/4bcf552fcea3e1ae555dde2ab33bc9fa6770da4d.tar.gz\r\n    URL_HASH MD5=7ffee993fc21b1115abf485958d03ac8\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(asio)\r\n\r\nadd_library(asio STATIC ${CMAKE_CURRENT_LIST_DIR}/asio_handle_exception.cpp)\r\ntarget_compile_definitions(asio PUBLIC ASIO_NO_EXCEPTIONS)\r\ntarget_include_directories(asio PUBLIC ${asio_SOURCE_DIR}/asio/include ${CMAKE_CURRENT_LIST_DIR})\r\n\r\nif(NINTENDO_3DS OR NINTENDO_SWITCH)\r\n  include(asio_defs REQUIRED)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/asio/asio_handle_exception.cpp",
    "content": "#include <string_view>\r\n\r\n#define ErrAsio(message) devilution::ErrDlg(\"ASIO Error\", message, __FILE__, __LINE__)\r\n\r\nnamespace devilution {\r\n\r\nextern void ErrDlg(const char* title, std::string_view error, std::string_view logFilePath, int logLineNr);\r\n\r\n} // namespace devilution\r\n\r\nnamespace asio::detail {\r\n\r\nvoid fatal_exception(const char* message)\r\n{\r\n\tErrAsio(message);\r\n}\r\n\r\n} // namespace asio::detail\r\n"
  },
  {
    "path": "3rdParty/asio/asio_handle_exception.hpp",
    "content": "#pragma once\r\n\r\n#include <asio/detail/throw_exception.hpp>\r\n\r\nnamespace asio::detail {\r\n\r\nvoid fatal_exception(const char *message);\r\n\r\ntemplate <typename Exception>\r\nvoid throw_exception(\r\n\tconst Exception &e\r\n\tASIO_SOURCE_LOCATION_PARAM)\r\n{\r\n  fatal_exception(e.what());\r\n}\r\n\r\n} // namespace asio::detail\r\n"
  },
  {
    "path": "3rdParty/benchmark/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\nFetchContent_Declare_ExcludeFromAll(\r\n  benchmark\r\n  URL https://github.com/google/benchmark/archive/refs/tags/v1.8.5.tar.gz\r\n  URL_HASH MD5=708d91ce255e8af4c1d7dfec50dff178\r\n)\r\n\r\nset(INSTALL_GTEST OFF)\r\n\r\nset(BENCHMARK_ENABLE_TESTING OFF)\r\nset(BENCHMARK_ENABLE_EXCEPTIONS OFF)\r\nset(BENCHMARK_ENABLE_WERROR OFF)\r\nset(BENCHMARK_ENABLE_INSTALL OFF)\r\n\r\nFetchContent_MakeAvailable_ExcludeFromAll(benchmark)\r\n"
  },
  {
    "path": "3rdParty/bzip2/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\ninclude(FetchContent)\r\n\r\nFetchContent_Declare_ExcludeFromAll(bzip2\r\n    GIT_REPOSITORY https://gitlab.com/bzip2/bzip2\r\n    GIT_TAG bzip2-1.0.8\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(bzip2)\r\n\r\nif(DEVILUTIONX_STATIC_BZIP2)\r\n  set(_lib_type STATIC)\r\nelse()\r\n  set(_lib_type SHARED)\r\nendif()\r\nadd_library(BZip2 ${_lib_type}\r\n  ${bzip2_SOURCE_DIR}/blocksort.c\r\n  ${bzip2_SOURCE_DIR}/bzlib.c\r\n  ${bzip2_SOURCE_DIR}/compress.c\r\n  ${bzip2_SOURCE_DIR}/crctable.c\r\n  ${bzip2_SOURCE_DIR}/decompress.c\r\n  ${bzip2_SOURCE_DIR}/huffman.c\r\n  ${bzip2_SOURCE_DIR}/randtable.c\r\n  ${bzip2_SOURCE_DIR}/bzlib.h\r\n  ${bzip2_SOURCE_DIR}/bzlib_private.h\r\n  ${CMAKE_CURRENT_LIST_DIR}/bz_internal_error.c\r\n)\r\ntarget_compile_definitions(BZip2 PRIVATE -DBZ_NO_STDIO)\r\ntarget_include_directories(BZip2 PUBLIC ${bzip2_SOURCE_DIR})\r\n\r\nadd_library(BZip2::BZip2 ALIAS BZip2)\r\n"
  },
  {
    "path": "3rdParty/bzip2/bz_internal_error.c",
    "content": "#include <stdio.h>\r\n\r\nvoid bz_internal_error(int errcode) {\r\n  fprintf(stderr, \"BZip2 fatal error %d\\n\", errcode);\r\n}\r\n"
  },
  {
    "path": "3rdParty/discord/.editorconfig",
    "content": "[*.patch]\r\nend_of_line = lf\r\n"
  },
  {
    "path": "3rdParty/discord/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nfind_package(Patch REQUIRED)\r\n\r\nset(Discord_SDK_URL \"https://dl-game-sdk.discordapp.net/3.2.1/discord_game_sdk.zip\")\r\nset(Discord_SDK_HASH \"73e5e1b3f8413a2c7184ef17476822f2\")\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n  FetchContent_Declare_ExcludeFromAll(discordsrc\r\n    URL ${Discord_SDK_URL}\r\n    URL_HASH MD5=${Discord_SDK_HASH}\r\n  )\r\nelse()\r\n  FetchContent_Declare_ExcludeFromAll(discordsrc\r\n    URL ${Discord_SDK_URL}\r\n    URL_HASH MD5=${Discord_SDK_HASH}\r\n    PATCH_COMMAND \"${Patch_EXECUTABLE}\" -p1 -N < \"${CMAKE_CURRENT_LIST_DIR}/fixes.patch\" || true\r\n  )\r\nendif()\r\nFetchContent_MakeAvailable_ExcludeFromAll(discordsrc)\r\n\r\nfile(GLOB discord_SRCS ${discordsrc_SOURCE_DIR}/cpp/*.cpp)\r\nadd_library(discord STATIC ${discord_SRCS})\r\ntarget_include_directories(discord INTERFACE \"${discordsrc_SOURCE_DIR}/..\")\r\n\r\nif(CMAKE_SYSTEM_PROCESSOR MATCHES \"aarch64\")\r\n  set(DISCORD_LIB_DIR \"${discordsrc_SOURCE_DIR}/lib/aarch64\")\r\nelseif(CMAKE_SIZEOF_VOID_P EQUAL 4)\r\n  set(DISCORD_LIB_DIR \"${discordsrc_SOURCE_DIR}/lib/x86\")\r\nelse()\r\n  set(DISCORD_LIB_DIR \"${discordsrc_SOURCE_DIR}/lib/x86_64\")\r\nendif()\r\nset(DISCORD_SHARED_LIB_FILENAME \"discord_game_sdk${CMAKE_SHARED_LIBRARY_SUFFIX}\")\r\n\r\nset(DISCORD_SHARED_LIB \"${DISCORD_LIB_DIR}/${DISCORD_SHARED_LIB_FILENAME}\")\r\nset(DISCORD_SHARED_LIB \"${DISCORD_SHARED_LIB}\" PARENT_SCOPE)\r\n\r\nfind_library(\r\n  DISCORD_LIB\r\n  NAMES \"${DISCORD_SHARED_LIB_FILENAME}\"\r\n  PATHS \"${DISCORD_LIB_DIR}\"\r\n  REQUIRED\r\n  NO_DEFAULT_PATH\r\n  NO_CMAKE_FIND_ROOT_PATH\r\n)\r\n\r\nmessage(\"-- 📚 discord_game_sdk: ${DISCORD_LIB}\")\r\n\r\n# Copy the dll so that tests and Debug builds can find it on Windows.\r\n# We also need it at this location to link to `discord_game_sdk.so` rather\r\n# than `_deps/discordsrc-src/lib/x86_64/discord_game_sdk.so` on Linux.\r\nfile(COPY \"${DISCORD_SHARED_LIB}\" DESTINATION \"${CMAKE_BINARY_DIR}\")\r\n\r\nadd_library(discord_game_sdk SHARED IMPORTED GLOBAL)\r\nset_target_properties(discord_game_sdk PROPERTIES\r\n  IMPORTED_IMPLIB \"${DISCORD_LIB}\"\r\n  IMPORTED_LOCATION \"${CMAKE_BINARY_DIR}/${DISCORD_SHARED_LIB_FILENAME}\"\r\n)\r\n"
  },
  {
    "path": "3rdParty/discord/fixes.patch",
    "content": "From 767aff84177e8805933ac4f980d9fc36a8b02af6 Mon Sep 17 00:00:00 2001\nFrom: Gleb Mazovetskiy <glex.spb@gmail.com>\nDate: Sat, 21 Jan 2023 13:09:38 +0000\nSubject: [PATCH] Various fixes\n\n1. Replaces `#include <Windows.h>` with `#include <windows.h>`\n   for compatibility with case-sensitive file systems (e.g. MinGW\n   cross-compilation on a Linux host).\n\n2. Adds missing `#include <cstdint>` to `cpp/types.h`.\n\n3. Fixes calling convention for callback lambdas.\n\nSigned-off-by: Gleb Mazovetskiy <glex.spb@gmail.com>\n---\n c/discord_game_sdk.h         |  2 +-\n cpp/achievement_manager.cpp  |  4 ++--\n cpp/activity_manager.cpp     | 10 +++++-----\n cpp/application_manager.cpp  |  6 +++---\n cpp/core.cpp                 |  2 +-\n cpp/ffi.h                    |  2 +-\n cpp/image_manager.cpp        |  2 +-\n cpp/lobby_manager.cpp        | 22 +++++++++++-----------\n cpp/overlay_manager.cpp      | 12 ++++++------\n cpp/relationship_manager.cpp |  2 +-\n cpp/storage_manager.cpp      |  6 +++---\n cpp/store_manager.cpp        |  6 +++---\n cpp/types.h                  |  4 +++-\n cpp/user_manager.cpp         |  2 +-\n cpp/voice_manager.cpp        |  2 +-\n examples/c/main.c            |  2 +-\n 16 files changed, 44 insertions(+), 42 deletions(-)\n\ndiff --git a/c/discord_game_sdk.h b/c/discord_game_sdk.h\nindex 4618756..f4c209a 100644\n--- a/c/discord_game_sdk.h\n+++ b/c/discord_game_sdk.h\n@@ -2,7 +2,7 @@\n #define _DISCORD_GAME_SDK_H_\n \n #ifdef _WIN32\n-#include <Windows.h>\n+#include <windows.h>\n #include <dxgi.h>\n #endif\n \ndiff --git a/cpp/achievement_manager.cpp b/cpp/achievement_manager.cpp\nindex 43a6d4c..9e92ad6 100644\n--- a/cpp/achievement_manager.cpp\n+++ b/cpp/achievement_manager.cpp\n@@ -34,7 +34,7 @@ void AchievementManager::SetUserAchievement(Snowflake achievementId,\n                                             std::uint8_t percentComplete,\n                                             std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -50,7 +50,7 @@ void AchievementManager::SetUserAchievement(Snowflake achievementId,\n \n void AchievementManager::FetchUserAchievements(std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/activity_manager.cpp b/cpp/activity_manager.cpp\nindex 3c20074..074f784 100644\n--- a/cpp/activity_manager.cpp\n+++ b/cpp/activity_manager.cpp\n@@ -84,7 +84,7 @@ Result ActivityManager::RegisterSteam(std::uint32_t steamId)\n \n void ActivityManager::UpdateActivity(Activity const& activity, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -102,7 +102,7 @@ void ActivityManager::UpdateActivity(Activity const& activity, std::function<voi\n \n void ActivityManager::ClearActivity(std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -119,7 +119,7 @@ void ActivityManager::SendRequestReply(UserId userId,\n                                        ActivityJoinRequestReply reply,\n                                        std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -141,7 +141,7 @@ void ActivityManager::SendInvite(UserId userId,\n                                  char const* content,\n                                  std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -161,7 +161,7 @@ void ActivityManager::SendInvite(UserId userId,\n \n void ActivityManager::AcceptInvite(UserId userId, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/application_manager.cpp b/cpp/application_manager.cpp\nindex 0e05f3f..98dac16 100644\n--- a/cpp/application_manager.cpp\n+++ b/cpp/application_manager.cpp\n@@ -13,7 +13,7 @@ namespace discord {\n \n void ApplicationManager::ValidateOrExit(std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -47,7 +47,7 @@ void ApplicationManager::GetCurrentBranch(char branch[4096])\n void ApplicationManager::GetOAuth2Token(std::function<void(Result, OAuth2Token const&)> callback)\n {\n     static auto wrapper =\n-      [](void* callbackData, EDiscordResult result, DiscordOAuth2Token* oauth2Token) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, DiscordOAuth2Token* oauth2Token) -> void {\n         std::unique_ptr<std::function<void(Result, OAuth2Token const&)>> cb(\n           reinterpret_cast<std::function<void(Result, OAuth2Token const&)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -62,7 +62,7 @@ void ApplicationManager::GetOAuth2Token(std::function<void(Result, OAuth2Token c\n \n void ApplicationManager::GetTicket(std::function<void(Result, char const*)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result, char const* data) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, char const* data) -> void {\n         std::unique_ptr<std::function<void(Result, char const*)>> cb(\n           reinterpret_cast<std::function<void(Result, char const*)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/core.cpp b/cpp/core.cpp\nindex 110c9ef..56b2801 100644\n--- a/cpp/core.cpp\n+++ b/cpp/core.cpp\n@@ -59,7 +59,7 @@ void Core::SetLogHook(LogLevel minLevel, std::function<void(LogLevel, char const\n     setLogHook_.DisconnectAll();\n     setLogHook_.Connect(std::move(hook));\n     static auto wrapper =\n-      [](void* callbackData, EDiscordLogLevel level, char const* message) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordLogLevel level, char const* message) -> void {\n         auto cb(reinterpret_cast<decltype(setLogHook_)*>(callbackData));\n         if (!cb) {\n             return;\ndiff --git a/cpp/ffi.h b/cpp/ffi.h\nindex 4a21057..3d2dd9d 100644\n--- a/cpp/ffi.h\n+++ b/cpp/ffi.h\n@@ -2,7 +2,7 @@\n #define _DISCORD_GAME_SDK_H_\n \n #ifdef _WIN32\n-#include <Windows.h>\n+#include <windows.h>\n #include <dxgi.h>\n #endif\n \ndiff --git a/cpp/image_manager.cpp b/cpp/image_manager.cpp\nindex 03b1db4..c90f337 100644\n--- a/cpp/image_manager.cpp\n+++ b/cpp/image_manager.cpp\n@@ -16,7 +16,7 @@ void ImageManager::Fetch(ImageHandle handle,\n                          std::function<void(Result, ImageHandle)> callback)\n {\n     static auto wrapper =\n-      [](void* callbackData, EDiscordResult result, DiscordImageHandle handleResult) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, DiscordImageHandle handleResult) -> void {\n         std::unique_ptr<std::function<void(Result, ImageHandle)>> cb(\n           reinterpret_cast<std::function<void(Result, ImageHandle)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/lobby_manager.cpp b/cpp/lobby_manager.cpp\nindex 3a95b1a..4000032 100644\n--- a/cpp/lobby_manager.cpp\n+++ b/cpp/lobby_manager.cpp\n@@ -167,7 +167,7 @@ void LobbyManager::CreateLobby(LobbyTransaction const& transaction,\n                                std::function<void(Result, Lobby const&)> callback)\n {\n     static auto wrapper =\n-      [](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {\n         std::unique_ptr<std::function<void(Result, Lobby const&)>> cb(\n           reinterpret_cast<std::function<void(Result, Lobby const&)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -185,7 +185,7 @@ void LobbyManager::UpdateLobby(LobbyId lobbyId,\n                                LobbyTransaction const& transaction,\n                                std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -204,7 +204,7 @@ void LobbyManager::UpdateLobby(LobbyId lobbyId,\n \n void LobbyManager::DeleteLobby(LobbyId lobbyId, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -222,7 +222,7 @@ void LobbyManager::ConnectLobby(LobbyId lobbyId,\n                                 std::function<void(Result, Lobby const&)> callback)\n {\n     static auto wrapper =\n-      [](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {\n         std::unique_ptr<std::function<void(Result, Lobby const&)>> cb(\n           reinterpret_cast<std::function<void(Result, Lobby const&)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -240,7 +240,7 @@ void LobbyManager::ConnectLobbyWithActivitySecret(\n   std::function<void(Result, Lobby const&)> callback)\n {\n     static auto wrapper =\n-      [](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void {\n         std::unique_ptr<std::function<void(Result, Lobby const&)>> cb(\n           reinterpret_cast<std::function<void(Result, Lobby const&)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -256,7 +256,7 @@ void LobbyManager::ConnectLobbyWithActivitySecret(\n \n void LobbyManager::DisconnectLobby(LobbyId lobbyId, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -403,7 +403,7 @@ void LobbyManager::UpdateMember(LobbyId lobbyId,\n                                 LobbyMemberTransaction const& transaction,\n                                 std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -426,7 +426,7 @@ void LobbyManager::SendLobbyMessage(LobbyId lobbyId,\n                                     std::uint32_t dataLength,\n                                     std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -452,7 +452,7 @@ Result LobbyManager::GetSearchQuery(LobbySearchQuery* query)\n \n void LobbyManager::Search(LobbySearchQuery const& query, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -487,7 +487,7 @@ Result LobbyManager::GetLobbyId(std::int32_t index, LobbyId* lobbyId)\n \n void LobbyManager::ConnectVoice(LobbyId lobbyId, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -502,7 +502,7 @@ void LobbyManager::ConnectVoice(LobbyId lobbyId, std::function<void(Result)> cal\n \n void LobbyManager::DisconnectVoice(LobbyId lobbyId, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/overlay_manager.cpp b/cpp/overlay_manager.cpp\nindex f4b1fba..d1bffc0 100644\n--- a/cpp/overlay_manager.cpp\n+++ b/cpp/overlay_manager.cpp\n@@ -49,7 +49,7 @@ void OverlayManager::IsLocked(bool* locked)\n \n void OverlayManager::SetLocked(bool locked, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -65,7 +65,7 @@ void OverlayManager::SetLocked(bool locked, std::function<void(Result)> callback\n void OverlayManager::OpenActivityInvite(ActivityActionType type,\n                                         std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -81,7 +81,7 @@ void OverlayManager::OpenActivityInvite(ActivityActionType type,\n \n void OverlayManager::OpenGuildInvite(char const* code, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -96,7 +96,7 @@ void OverlayManager::OpenGuildInvite(char const* code, std::function<void(Result\n \n void OverlayManager::OpenVoiceSettings(std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -182,7 +182,7 @@ void OverlayManager::SetImeCompositionRangeCallback(\n   std::function<void(std::int32_t, std::int32_t, Rect*, std::uint32_t)>\n     onImeCompositionRangeChanged)\n {\n-    static auto wrapper = [](void* callbackData,\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData,\n                              int32_t from,\n                              int32_t to,\n                              DiscordRect* bounds,\n@@ -205,7 +205,7 @@ void OverlayManager::SetImeSelectionBoundsCallback(\n   std::function<void(Rect, Rect, bool)> onImeSelectionBoundsChanged)\n {\n     static auto wrapper =\n-      [](void* callbackData, DiscordRect anchor, DiscordRect focus, bool isAnchorFirst) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, DiscordRect anchor, DiscordRect focus, bool isAnchorFirst) -> void {\n         std::unique_ptr<std::function<void(Rect, Rect, bool)>> cb(\n           reinterpret_cast<std::function<void(Rect, Rect, bool)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/relationship_manager.cpp b/cpp/relationship_manager.cpp\nindex dce874e..a427996 100644\n--- a/cpp/relationship_manager.cpp\n+++ b/cpp/relationship_manager.cpp\n@@ -44,7 +44,7 @@ IDiscordRelationshipEvents RelationshipManager::events_{\n \n void RelationshipManager::Filter(std::function<bool(Relationship const&)> filter)\n {\n-    static auto wrapper = [](void* callbackData, DiscordRelationship* relationship) -> bool {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, DiscordRelationship* relationship) -> bool {\n         auto cb(reinterpret_cast<std::function<bool(Relationship const&)>*>(callbackData));\n         if (!cb || !(*cb)) {\n             return {};\ndiff --git a/cpp/storage_manager.cpp b/cpp/storage_manager.cpp\nindex fbf9ca7..f114665 100644\n--- a/cpp/storage_manager.cpp\n+++ b/cpp/storage_manager.cpp\n@@ -32,7 +32,7 @@ void StorageManager::ReadAsync(char const* name,\n                                std::function<void(Result, std::uint8_t*, std::uint32_t)> callback)\n {\n     static auto wrapper =\n-      [](void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void {\n         std::unique_ptr<std::function<void(Result, std::uint8_t*, std::uint32_t)>> cb(\n           reinterpret_cast<std::function<void(Result, std::uint8_t*, std::uint32_t)>*>(\n             callbackData));\n@@ -53,7 +53,7 @@ void StorageManager::ReadAsyncPartial(\n   std::function<void(Result, std::uint8_t*, std::uint32_t)> callback)\n {\n     static auto wrapper =\n-      [](void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void {\n+      [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void {\n         std::unique_ptr<std::function<void(Result, std::uint8_t*, std::uint32_t)>> cb(\n           reinterpret_cast<std::function<void(Result, std::uint8_t*, std::uint32_t)>*>(\n             callbackData));\n@@ -80,7 +80,7 @@ void StorageManager::WriteAsync(char const* name,\n                                 std::uint32_t dataLength,\n                                 std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/store_manager.cpp b/cpp/store_manager.cpp\nindex 40c7e65..dd13cf9 100644\n--- a/cpp/store_manager.cpp\n+++ b/cpp/store_manager.cpp\n@@ -45,7 +45,7 @@ IDiscordStoreEvents StoreManager::events_{\n \n void StoreManager::FetchSkus(std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -89,7 +89,7 @@ Result StoreManager::GetSkuAt(std::int32_t index, Sku* sku)\n \n void StoreManager::FetchEntitlements(std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\n@@ -146,7 +146,7 @@ Result StoreManager::HasSkuEntitlement(Snowflake skuId, bool* hasEntitlement)\n \n void StoreManager::StartPurchase(Snowflake skuId, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/types.h b/cpp/types.h\nindex 76c4311..4e78f54 100644\n--- a/cpp/types.h\n+++ b/cpp/types.h\n@@ -1,9 +1,11 @@\n #pragma once\n \n+#include <cstdint>\n+\n #include \"ffi.h\"\n #include \"event.h\"\n #ifdef _WIN32\n-#include <Windows.h>\n+#include <windows.h>\n #include <dxgi.h>\n #endif\n \ndiff --git a/cpp/user_manager.cpp b/cpp/user_manager.cpp\nindex ddb6d5c..8617ec9 100644\n--- a/cpp/user_manager.cpp\n+++ b/cpp/user_manager.cpp\n@@ -42,7 +42,7 @@ Result UserManager::GetCurrentUser(User* currentUser)\n \n void UserManager::GetUser(UserId userId, std::function<void(Result, User const&)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result, DiscordUser* user) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result, DiscordUser* user) -> void {\n         std::unique_ptr<std::function<void(Result, User const&)>> cb(\n           reinterpret_cast<std::function<void(Result, User const&)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/cpp/voice_manager.cpp b/cpp/voice_manager.cpp\nindex 014ceb3..69d4904 100644\n--- a/cpp/voice_manager.cpp\n+++ b/cpp/voice_manager.cpp\n@@ -42,7 +42,7 @@ Result VoiceManager::GetInputMode(InputMode* inputMode)\n \n void VoiceManager::SetInputMode(InputMode inputMode, std::function<void(Result)> callback)\n {\n-    static auto wrapper = [](void* callbackData, EDiscordResult result) -> void {\n+    static auto wrapper = [] DISCORD_CALLBACK (void* callbackData, EDiscordResult result) -> void {\n         std::unique_ptr<std::function<void(Result)>> cb(\n           reinterpret_cast<std::function<void(Result)>*>(callbackData));\n         if (!cb || !(*cb)) {\ndiff --git a/examples/c/main.c b/examples/c/main.c\nindex 197c26d..45d8811 100644\n--- a/examples/c/main.c\n+++ b/examples/c/main.c\n@@ -3,7 +3,7 @@\n #include <assert.h>\n #include \"discord_game_sdk.h\"\n #ifdef _WIN32\n-#include <Windows.h>\n+#include <windows.h>\n #else\n #include <unistd.h>\n #include <string.h>\n-- \n2.37.2\n\n"
  },
  {
    "path": "3rdParty/find_steam_game/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(find_steam_game\r\n    URL https://github.com/cxong/find_steam_game/archive/a2bd6273fc002214052c2ee3bd48d7c1e7d3f366.tar.gz\r\n    URL_HASH MD5=a6950ce5d9ced8a259752bc2dc7f5311\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(find_steam_game)\r\n\r\nadd_library(find_steam_game INTERFACE)\r\ntarget_include_directories(find_steam_game INTERFACE ${find_steam_game_SOURCE_DIR})\r\n"
  },
  {
    "path": "3rdParty/googletest/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\nFetchContent_Declare_ExcludeFromAll(\r\n  googletest\r\n  URL https://github.com/google/googletest/releases/download/v1.15.2/googletest-1.15.2.tar.gz\r\n  URL_HASH MD5=7e11f6cfcf6498324ac82d567dcb891e\r\n)\r\n\r\nset(INSTALL_GTEST OFF)\r\n\r\n# For Windows: Prevent overriding the parent project's compiler/linker settings\r\nset(gtest_force_shared_crt ON CACHE BOOL \"\" FORCE)\r\n\r\nFetchContent_MakeAvailable_ExcludeFromAll(googletest)\r\n"
  },
  {
    "path": "3rdParty/libfmt/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\nif(NOT WIN32 AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)\r\n  # Enable POSIX extensions such as `readlink` and `ftruncate`.\r\n  add_definitions(-D_POSIX_C_SOURCE=200809L)\r\nendif()\r\n\r\n# Disable fmt/os.h functionality.\r\n# We do not use it and it is not supported on some systems.\r\nset(FMT_OS OFF)\r\n\r\nif(DEVILUTIONX_STATIC_LIBFMT)\r\n  set(BUILD_SHARED_LIBS OFF)\r\nelse()\r\n  set(BUILD_SHARED_LIBS ON)\r\nendif()\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(libfmt\r\n  URL https://github.com/fmtlib/fmt/releases/download/12.0.0/fmt-12.0.0.zip\r\n  URL_HASH SHA256=1c32293203449792bf8e94c7f6699c643887e826f2d66a80869b4f279fb07d25\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(libfmt)\r\n\r\n# We do not use locale-specific features of libfmt and disabling them reduces the size.\r\ntarget_compile_definitions(fmt PUBLIC FMT_USE_LOCALE=0)\r\n\r\nif(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n  target_compile_definitions(fmt PUBLIC FMT_USE_WRITE_CONSOLE)\r\nendif()\r\n\r\n# Reduces the overall binary size by 8 KiB.\r\nif(TARGET_PLATFORM STREQUAL \"rg99\")\r\n  target_compile_definitions(fmt PUBLIC FMT_BUILTIN_TYPES=0)\r\nendif()\r\n\r\n# https://github.com/fmtlib/fmt/issues/4189\r\nif(NINTENDO_3DS OR NINTENDO_SWITCH OR VITA)\r\n  target_compile_definitions(fmt PUBLIC FMT_USE_FALLBACK_FILE=1)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/libmpq/CMakeLists.txt",
    "content": "if(NOT TARGET ZLIB::ZLIB)\r\n  find_package(ZLIB REQUIRED)\r\nendif()\r\n\r\nif(NOT TARGET BZip2::BZip2)\r\n  find_package(BZip2 REQUIRED)\r\nendif()\r\n\r\ninclude(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(libmpq\r\n    URL https://github.com/diasurgical/libmpq/archive/7c2924d4553513eba1a70bbdb558198dd8c2726a.tar.gz\r\n    URL_HASH MD5=315c88c02b45851cdfee8460322de044\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(libmpq)\r\n\r\nadd_library(libmpq STATIC\r\n  ${libmpq_SOURCE_DIR}/libmpq/common.c\r\n  ${libmpq_SOURCE_DIR}/libmpq/explode.c\r\n  ${libmpq_SOURCE_DIR}/libmpq/extract.c\r\n  ${libmpq_SOURCE_DIR}/libmpq/huffman.c\r\n  ${libmpq_SOURCE_DIR}/libmpq/mpq.c\r\n  ${libmpq_SOURCE_DIR}/libmpq/wave.c\r\n)\r\n\r\ntarget_include_directories(libmpq PUBLIC ${libmpq_SOURCE_DIR})\r\ntarget_include_directories(libmpq PRIVATE ${CMAKE_CURRENT_LIST_DIR})\r\n\r\ntarget_link_libraries(libmpq PRIVATE ZLIB::ZLIB BZip2::BZip2)\r\n\r\nif(LIBMPQ_FILE_BUFFER_SIZE)\r\n  target_compile_definitions(libmpq PRIVATE \"LIBMPQ_FILE_BUFFER_SIZE=${LIBMPQ_FILE_BUFFER_SIZE}\")\r\nendif()\r\n\r\nif(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n  target_compile_definitions(libmpq PRIVATE LIBMPQ_WINDOWS_NO_WCHAR)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/libmpq/config.h",
    "content": "#define VERSION \"0.4.2\"\r\n"
  },
  {
    "path": "3rdParty/libpng/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\n# Workaround for deprecation of older CMake versions\r\nset(CMAKE_POLICY_VERSION_MINIMUM 3.22)\r\n\r\nif(NOT DISABLE_LTO)\r\n  # Force CMake to raise an error if INTERPROCEDURAL_OPTIMIZATION\r\n  # is enabled and compiler does not support IPO\r\n  set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)\r\nendif()\r\n\r\nif(DEVILUTIONX_STATIC_LIBPNG)\r\n  set(PNG_LIBRARY png_static)\r\n  set(PNG_STATIC ON)\r\n  set(PNG_SHARED OFF)\r\nelse()\r\n  set(PNG_LIBRARY png)\r\n  set(PNG_STATIC OFF)\r\n  set(PNG_SHARED ON)\r\nendif()\r\nset(PNG_TESTS OFF)\r\nset(PNG_EXECUTABLES OFF)\r\nset(SKIP_INSTALL_ALL ON)\r\n\r\nif(APPLE AND \"${CMAKE_OSX_ARCHITECTURES}\" STREQUAL \"arm64\")\r\n  set(PNG_ARM_NEON \"on\" CACHE STRING \"\" FORCE)\r\nendif()\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(libpng\r\n  URL https://github.com/glennrp/libpng/archive/0a158f3506502dfa23edfc42790dfaed82efba17.tar.gz\r\n  URL_HASH MD5=6d705417242732e8e081bff752c98c18\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(libpng)\r\n\r\ntarget_include_directories(${PNG_LIBRARY} INTERFACE\r\n  $<BUILD_INTERFACE:${libpng_SOURCE_DIR}>\r\n  $<BUILD_INTERFACE:${libpng_BINARY_DIR}>)\r\n\r\nadd_library(PNG::PNG ALIAS ${PNG_LIBRARY})\r\n"
  },
  {
    "path": "3rdParty/libsmackerdec/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(libsmackerdec\r\n    URL https://github.com/diasurgical/libsmackerdec/archive/0aaaf8c94a097b009d844db0d44dd7cd0ff81922.tar.gz\r\n    URL_HASH SHA256=c3a7fbc91531eee8989b1d281415adc0209d84ffc0437c6b0b4f677ae7fd3b41\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(libsmackerdec)\r\n\r\nadd_library(libsmackerdec STATIC\r\n  ${libsmackerdec_SOURCE_DIR}/src/BitReader.cpp\r\n  ${libsmackerdec_SOURCE_DIR}/src/FileStream.cpp\r\n  ${libsmackerdec_SOURCE_DIR}/src/LogError.cpp\r\n  ${libsmackerdec_SOURCE_DIR}/src/SmackerDecoder.cpp)\r\n\r\ntarget_include_directories(libsmackerdec PUBLIC ${libsmackerdec_SOURCE_DIR}/include)\r\n\r\nif(USE_SDL1)\r\n  target_link_libraries(libsmackerdec PUBLIC ${SDL_LIBRARY})\r\nelseif(USE_SDL3)\r\n  target_link_libraries(libsmackerdec PUBLIC SDL3::SDL3)\r\n  target_compile_definitions(libsmackerdec PUBLIC USE_SDL3)\r\nelseif(TARGET SDL2::SDL2 AND NOT (DEVILUTIONX_STATIC_SDL2 AND TARGET SDL2::SDL2-static))\r\n  target_link_libraries(libsmackerdec PUBLIC SDL2::SDL2)\r\nelseif(TARGET SDL2::SDL2-static)\r\n  target_link_libraries(libsmackerdec PUBLIC SDL2::SDL2-static)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/libsodium/CMakeLists.txt",
    "content": "if(NOT DEVILUTIONX_SYSTEM_LIBSODIUM)\r\n  include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\n  set(SODIUM_MINIMAL ON)\r\n  set(SODIUM_ENABLE_BLOCKING_RANDOM OFF)\r\n  set(SODIUM_DISABLE_TESTS ON)\r\n\r\n  if(DEVILUTIONX_STATIC_LIBSODIUM)\r\n    set(BUILD_SHARED_LIBS OFF)\r\n  else()\r\n    set(BUILD_SHARED_LIBS ON)\r\n  endif()\r\n  include(FetchContent)\r\n  FetchContent_Declare_ExcludeFromAll(libsodium\r\n      GIT_REPOSITORY https://github.com/robinlinden/libsodium-cmake.git\r\n      GIT_TAG a8ac4509b22b84d6c2eb7d7448f08678e4a67da6\r\n  )\r\n  FetchContent_MakeAvailable_ExcludeFromAll(libsodium)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/libzt/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\nset(BUILD_HOST_SELFTEST OFF)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(libzt\r\n  GIT_REPOSITORY https://github.com/diasurgical/libzt.git\r\n  GIT_TAG 1a9d83b8c4c2bdcd7ea6d8ab1dd2771b16eb4e13)\r\nFetchContent_MakeAvailable_ExcludeFromAll(libzt)\r\n\r\nif(NOT ANDROID)\r\n  set(libzt_LIB_NAME zt-static)\r\nelse()\r\n  set(libzt_LIB_NAME zt-shared)\r\nendif()\r\n\r\nforeach(\r\n  lib_name\r\n  zto_obj\r\n  libnatpmp_obj\r\n  libzt_obj\r\n  lwip_obj\r\n  miniupnpc_obj\r\n  zto_pic\r\n  zt_pic\r\n  natpmp_pic\r\n  lwip_pic\r\n  miniupnpc_pic\r\n  ztcore\r\n  ${libzt_LIB_NAME}\r\n)\r\n  if(TARGET ${lib_name})\r\n    # External library, ignore all warnings\r\n    target_compile_options(${lib_name} PRIVATE -w)\r\n  endif()\r\nendforeach(lib_name)\r\n\r\ntarget_include_directories(${libzt_LIB_NAME} INTERFACE\r\n  \"${libzt_SOURCE_DIR}/include\"\r\n  \"${libzt_SOURCE_DIR}/src\"\r\n  \"${libzt_SOURCE_DIR}/ext/lwip/src/include\")\r\n\r\nif(WIN32)\r\n  target_include_directories(${libzt_LIB_NAME} INTERFACE\r\n    \"${libzt_SOURCE_DIR}/ext/lwip-contrib/ports/win32/include\")\r\nelse()\r\n  target_include_directories(${libzt_LIB_NAME} INTERFACE\r\n    \"${libzt_SOURCE_DIR}/ext/lwip-contrib/ports/unix/port/include\")\r\nendif()\r\n\r\nif(MINGW_CROSS)\r\n  include(zt_defs REQUIRED)\r\nendif()\r\n\r\nif(MSVC)\r\n  target_compile_definitions(libnatpmp_obj PRIVATE -DSTATICLIB)\r\nendif()\r\n"
  },
  {
    "path": "3rdParty/magic_enum/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nFetchContent_Declare_ExcludeFromAll(magic_enum\r\n    URL https://github.com/Neargye/magic_enum/archive/refs/tags/v0.9.7.tar.gz\r\n    URL_HASH MD5=5afd218c48c3f7cf094889a182842a50\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(magic_enum)\r\n"
  },
  {
    "path": "3rdParty/sol2/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nset(SOL2_ENABLE_INSTALL OFF)\r\nset(SOL2_BUILD_LUA OFF)\r\nset(SOL2_LUA_VERSION \"${LUA_VERSION_STRING}\")\r\n\r\nFetchContent_Declare_ExcludeFromAll(sol2\r\n    # branch: devilutionx\r\n    # This is upstream c1f95a773c6f8f4fde8ca3efe872e7286afe4444 with the following PRs merged on top:\r\n    # https://github.com/ThePhD/sol2/pull/1712\r\n    # https://github.com/ThePhD/sol2/pull/1722\r\n    # https://github.com/ThePhD/sol2/pull/1676\r\n    # https://github.com/ThePhD/sol2/pull/1704\r\n    # https://github.com/ThePhD/sol2/pull/1705\r\n    # https://github.com/ThePhD/sol2/pull/1716\r\n    # https://github.com/ThePhD/sol2/pull/1674\r\n    # https://github.com/ThePhD/sol2/pull/1722\r\n    URL https://github.com/diasurgical/sol2/archive/832ac772c2cd3d9620d447e9e77897f7b5e806e3.tar.gz\r\n    URL_HASH MD5=06c9c0f3242ee803f50e8fd210fdfe4e\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(sol2)\r\n\r\ntarget_include_directories(sol2 SYSTEM BEFORE INTERFACE ${CMAKE_CURRENT_LIST_DIR}/sol_config)\r\ntarget_compile_definitions(sol2 INTERFACE SOL_NO_EXCEPTIONS=1)\r\n"
  },
  {
    "path": "3rdParty/sol2/sol_config/sol/config.hpp",
    "content": "#pragma once\r\n\r\n#define SOL_SAFE_USERTYPE 1\r\n#define SOL_SAFE_REFERENCES 1\r\n#define SOL_SAFE_FUNCTION_CALLS 1\r\n#define SOL_SAFE_FUNCTION 1\r\n#define SOL_SAFE_NUMERICS 1\r\n#define SOL_IN_DEBUG_DETECTED 0\r\n"
  },
  {
    "path": "3rdParty/sol2/sol_config/sol/debug.hpp",
    "content": "#pragma once\r\n\r\n// sol2 uses std::cout for debug logging by default.\r\n// We want to use SDL logging instead for better compatibility.\r\n\r\n#include <cstddef>\r\n#include <string>\r\n\r\n#include <sol/stack.hpp>\r\n\r\nnamespace devilutionx {\r\nvoid Sol2DebugPrintStack(lua_State *L);\r\nvoid Sol2DebugPrintSection(const std::string &message, lua_State *L);\r\n} // namespace devilutionx\r\n\r\nnamespace sol::detail::debug {\r\n\r\ninline std::string dump_types(lua_State *L) {\r\n  std::string visual;\r\n  std::size_t size = lua_gettop(L) + 1;\r\n  for (std::size_t i = 1; i < size; ++i) {\r\n    if (i != 1) {\r\n      visual += \" | \";\r\n    }\r\n    visual += type_name(L, stack::get<type>(L, static_cast<int>(i)));\r\n  }\r\n  return visual;\r\n}\r\n\r\ninline void print_stack(lua_State *L) { ::devilutionx::Sol2DebugPrintStack(L); }\r\n\r\ninline void print_section(const std::string &message, lua_State *L) {\r\n  ::devilutionx::Sol2DebugPrintSection(message, L);\r\n}\r\n\r\n} // namespace sol::detail::debug\r\n"
  },
  {
    "path": "3rdParty/tl/CMakeLists.txt",
    "content": "add_library(tl INTERFACE)\r\n\r\ntarget_include_directories(tl INTERFACE ${CMAKE_CURRENT_LIST_DIR})\r\n"
  },
  {
    "path": "3rdParty/tl/expected.hpp",
    "content": "///\n// expected - An implementation of std::expected with extensions\n// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)\n//\n// Documentation available at http://tl.tartanllama.xyz/\n//\n// To the extent possible under law, the author(s) have dedicated all\n// copyright and related and neighboring rights to this software to the\n// public domain worldwide. This software is distributed without any warranty.\n//\n// You should have received a copy of the CC0 Public Domain Dedication\n// along with this software. If not, see\n// <http://creativecommons.org/publicdomain/zero/1.0/>.\n///\n\n#ifndef TL_EXPECTED_HPP\n#define TL_EXPECTED_HPP\n\n#define TL_EXPECTED_VERSION_MAJOR 1\n#define TL_EXPECTED_VERSION_MINOR 1\n#define TL_EXPECTED_VERSION_PATCH 0\n\n#include <exception>\n#include <functional>\n#include <type_traits>\n#include <utility>\n\n#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)\n#define TL_EXPECTED_EXCEPTIONS_ENABLED\n#endif\n\n#if (defined(_MSC_VER) && _MSC_VER == 1900)\n#define TL_EXPECTED_MSVC2015\n#define TL_EXPECTED_MSVC2015_CONSTEXPR\n#else\n#define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \\\n     !defined(__clang__))\n#define TL_EXPECTED_GCC49\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 &&              \\\n     !defined(__clang__))\n#define TL_EXPECTED_GCC54\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 &&              \\\n     !defined(__clang__))\n#define TL_EXPECTED_GCC55\n#endif\n\n#if !defined(TL_ASSERT)\n// can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug\n#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49)\n#include <cassert>\n#define TL_ASSERT(x) assert(x)\n#else\n#define TL_ASSERT(x)\n#endif\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \\\n     !defined(__clang__))\n// GCC < 5 doesn't support overloading on const&& for member functions\n\n#define TL_EXPECTED_NO_CONSTRR\n// GCC < 5 doesn't support some standard C++11 type traits\n#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                         \\\n  std::has_trivial_copy_constructor<T>\n#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                            \\\n  std::has_trivial_copy_assign<T>\n\n// This one will be different for GCC 5.7 if it's ever supported\n#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)                               \\\n  std::is_trivially_destructible<T>\n\n// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks\n// std::vector for non-copyable types\n#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))\n#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX\n#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX\nnamespace tl {\nnamespace detail {\ntemplate <class T>\nstruct is_trivially_copy_constructible\n    : std::is_trivially_copy_constructible<T> {};\n#ifdef _GLIBCXX_VECTOR\ntemplate <class T, class A>\nstruct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};\n#endif\n} // namespace detail\n} // namespace tl\n#endif\n\n#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                         \\\n  tl::detail::is_trivially_copy_constructible<T>\n#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                            \\\n  std::is_trivially_copy_assignable<T>\n#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)                               \\\n  std::is_trivially_destructible<T>\n#else\n#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                         \\\n  std::is_trivially_copy_constructible<T>\n#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                            \\\n  std::is_trivially_copy_assignable<T>\n#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)                               \\\n  std::is_trivially_destructible<T>\n#endif\n\n#if __cplusplus > 201103L\n#define TL_EXPECTED_CXX14\n#endif\n\n#ifdef TL_EXPECTED_GCC49\n#define TL_EXPECTED_GCC49_CONSTEXPR\n#else\n#define TL_EXPECTED_GCC49_CONSTEXPR constexpr\n#endif\n\n#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) ||                \\\n     defined(TL_EXPECTED_GCC49))\n#define TL_EXPECTED_11_CONSTEXPR\n#else\n#define TL_EXPECTED_11_CONSTEXPR constexpr\n#endif\n\nnamespace tl {\ntemplate <class T, class E> class expected;\n\n#ifndef TL_MONOSTATE_INPLACE_MUTEX\n#define TL_MONOSTATE_INPLACE_MUTEX\nclass monostate {};\n\nstruct in_place_t {\n  explicit in_place_t() = default;\n};\nstatic constexpr in_place_t in_place{};\n#endif\n\ntemplate <class E> class unexpected {\npublic:\n  static_assert(!std::is_same<E, void>::value, \"E must not be void\");\n\n  unexpected() = delete;\n  constexpr explicit unexpected(const E &e) : m_val(e) {}\n\n  constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {}\n\n  template <class... Args, typename std::enable_if<std::is_constructible<\n                               E, Args &&...>::value>::type * = nullptr>\n  constexpr explicit unexpected(Args &&...args)\n      : m_val(std::forward<Args>(args)...) {}\n  template <\n      class U, class... Args,\n      typename std::enable_if<std::is_constructible<\n          E, std::initializer_list<U> &, Args &&...>::value>::type * = nullptr>\n  constexpr explicit unexpected(std::initializer_list<U> l, Args &&...args)\n      : m_val(l, std::forward<Args>(args)...) {}\n\n  constexpr const E &value() const & { return m_val; }\n  TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; }\n  TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); }\n  constexpr const E &&value() const && { return std::move(m_val); }\n\nprivate:\n  E m_val;\n};\n\n#ifdef __cpp_deduction_guides\ntemplate <class E> unexpected(E) -> unexpected<E>;\n#endif\n\ntemplate <class E>\nconstexpr bool operator==(const unexpected<E> &lhs, const unexpected<E> &rhs) {\n  return lhs.value() == rhs.value();\n}\ntemplate <class E>\nconstexpr bool operator!=(const unexpected<E> &lhs, const unexpected<E> &rhs) {\n  return lhs.value() != rhs.value();\n}\ntemplate <class E>\nconstexpr bool operator<(const unexpected<E> &lhs, const unexpected<E> &rhs) {\n  return lhs.value() < rhs.value();\n}\ntemplate <class E>\nconstexpr bool operator<=(const unexpected<E> &lhs, const unexpected<E> &rhs) {\n  return lhs.value() <= rhs.value();\n}\ntemplate <class E>\nconstexpr bool operator>(const unexpected<E> &lhs, const unexpected<E> &rhs) {\n  return lhs.value() > rhs.value();\n}\ntemplate <class E>\nconstexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {\n  return lhs.value() >= rhs.value();\n}\n\ntemplate <class E>\nunexpected<typename std::decay<E>::type> make_unexpected(E &&e) {\n  return unexpected<typename std::decay<E>::type>(std::forward<E>(e));\n}\n\nstruct unexpect_t {\n  unexpect_t() = default;\n};\nstatic constexpr unexpect_t unexpect{};\n\nnamespace detail {\ntemplate <typename E>\n[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) {\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n  throw std::forward<E>(e);\n#else\n  (void)e;\n#ifdef _MSC_VER\n  __assume(0);\n#else\n  __builtin_unreachable();\n#endif\n#endif\n}\n\n#ifndef TL_TRAITS_MUTEX\n#define TL_TRAITS_MUTEX\n// C++14-style aliases for brevity\ntemplate <class T> using remove_const_t = typename std::remove_const<T>::type;\ntemplate <class T>\nusing remove_reference_t = typename std::remove_reference<T>::type;\ntemplate <class T> using decay_t = typename std::decay<T>::type;\ntemplate <bool E, class T = void>\nusing enable_if_t = typename std::enable_if<E, T>::type;\ntemplate <bool B, class T, class F>\nusing conditional_t = typename std::conditional<B, T, F>::type;\n\n// std::conjunction from C++17\ntemplate <class...> struct conjunction : std::true_type {};\ntemplate <class B> struct conjunction<B> : B {};\ntemplate <class B, class... Bs>\nstruct conjunction<B, Bs...>\n    : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};\n\n#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L\n#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND\n#endif\n\n// In C++11 mode, there's an issue in libc++'s std::mem_fn\n// which results in a hard-error when using it in a noexcept expression\n// in some cases. This is a check to workaround the common failing case.\n#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND\ntemplate <class T>\nstruct is_pointer_to_non_const_member_func : std::false_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &&>\n    : std::true_type {};\n\ntemplate <class T> struct is_const_or_const_ref : std::false_type {};\ntemplate <class T> struct is_const_or_const_ref<T const &> : std::true_type {};\ntemplate <class T> struct is_const_or_const_ref<T const> : std::true_type {};\n#endif\n\n// std::invoke from C++17\n// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround\ntemplate <\n    typename Fn, typename... Args,\n#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND\n    typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value &&\n                             is_const_or_const_ref<Args...>::value)>,\n#endif\n    typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0>\nconstexpr auto invoke(Fn &&f, Args &&...args) noexcept(\n    noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))\n    -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {\n  return std::mem_fn(f)(std::forward<Args>(args)...);\n}\n\ntemplate <typename Fn, typename... Args,\n          typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>\nconstexpr auto invoke(Fn &&f, Args &&...args) noexcept(\n    noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))\n    -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {\n  return std::forward<Fn>(f)(std::forward<Args>(args)...);\n}\n\n// std::invoke_result from C++17\ntemplate <class F, class, class... Us> struct invoke_result_impl;\n\ntemplate <class F, class... Us>\nstruct invoke_result_impl<\n    F,\n    decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),\n    Us...> {\n  using type =\n      decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));\n};\n\ntemplate <class F, class... Us>\nusing invoke_result = invoke_result_impl<F, void, Us...>;\n\ntemplate <class F, class... Us>\nusing invoke_result_t = typename invoke_result<F, Us...>::type;\n\n#if defined(_MSC_VER) && _MSC_VER <= 1900\n// TODO make a version which works with MSVC 2015\ntemplate <class T, class U = T> struct is_swappable : std::true_type {};\n\ntemplate <class T, class U = T> struct is_nothrow_swappable : std::true_type {};\n#else\n// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept\nnamespace swap_adl_tests {\n// if swap ADL finds this then it would call std::swap otherwise (same\n// signature)\nstruct tag {};\n\ntemplate <class T> tag swap(T &, T &);\ntemplate <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);\n\n// helper functions to test if an unqualified swap is possible, and if it\n// becomes std::swap\ntemplate <class, class> std::false_type can_swap(...) noexcept(false);\ntemplate <class T, class U,\n          class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>\nstd::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),\n                                                    std::declval<U &>())));\n\ntemplate <class, class> std::false_type uses_std(...);\ntemplate <class T, class U>\nstd::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>\nuses_std(int);\n\ntemplate <class T>\nstruct is_std_swap_noexcept\n    : std::integral_constant<bool,\n                             std::is_nothrow_move_constructible<T>::value &&\n                                 std::is_nothrow_move_assignable<T>::value> {};\n\ntemplate <class T, std::size_t N>\nstruct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};\n\ntemplate <class T, class U>\nstruct is_adl_swap_noexcept\n    : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};\n} // namespace swap_adl_tests\n\ntemplate <class T, class U = T>\nstruct is_swappable\n    : std::integral_constant<\n          bool,\n          decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&\n              (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||\n               (std::is_move_assignable<T>::value &&\n                std::is_move_constructible<T>::value))> {};\n\ntemplate <class T, std::size_t N>\nstruct is_swappable<T[N], T[N]>\n    : std::integral_constant<\n          bool,\n          decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&\n              (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(\n                   0))::value ||\n               is_swappable<T, T>::value)> {};\n\ntemplate <class T, class U = T>\nstruct is_nothrow_swappable\n    : std::integral_constant<\n          bool,\n          is_swappable<T, U>::value &&\n              ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&\n                detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||\n               (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&\n                detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};\n#endif\n#endif\n\n// Trait for checking if a type is a tl::expected\ntemplate <class T> struct is_expected_impl : std::false_type {};\ntemplate <class T, class E>\nstruct is_expected_impl<expected<T, E>> : std::true_type {};\ntemplate <class T> using is_expected = is_expected_impl<decay_t<T>>;\n\ntemplate <class T, class E, class U>\nusing expected_enable_forward_value = detail::enable_if_t<\n    std::is_constructible<T, U &&>::value &&\n    !std::is_same<detail::decay_t<U>, in_place_t>::value &&\n    !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&\n    !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;\n\ntemplate <class T, class E, class U, class G, class UR, class GR>\nusing expected_enable_from_other = detail::enable_if_t<\n    std::is_constructible<T, UR>::value &&\n    std::is_constructible<E, GR>::value &&\n    !std::is_constructible<T, expected<U, G> &>::value &&\n    !std::is_constructible<T, expected<U, G> &&>::value &&\n    !std::is_constructible<T, const expected<U, G> &>::value &&\n    !std::is_constructible<T, const expected<U, G> &&>::value &&\n    !std::is_convertible<expected<U, G> &, T>::value &&\n    !std::is_convertible<expected<U, G> &&, T>::value &&\n    !std::is_convertible<const expected<U, G> &, T>::value &&\n    !std::is_convertible<const expected<U, G> &&, T>::value>;\n\ntemplate <class T, class U>\nusing is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;\n\ntemplate <class T>\nusing is_copy_constructible_or_void =\n    is_void_or<T, std::is_copy_constructible<T>>;\n\ntemplate <class T>\nusing is_move_constructible_or_void =\n    is_void_or<T, std::is_move_constructible<T>>;\n\ntemplate <class T>\nusing is_copy_assignable_or_void = is_void_or<T, std::is_copy_assignable<T>>;\n\ntemplate <class T>\nusing is_move_assignable_or_void = is_void_or<T, std::is_move_assignable<T>>;\n\n} // namespace detail\n\nnamespace detail {\nstruct no_init_t {};\nstatic constexpr no_init_t no_init{};\n\n// Implements the storage of the values, and ensures that the destructor is\n// trivial if it can be.\n//\n// This specialization is for where neither `T` or `E` is trivially\n// destructible, so the destructors must be called on destruction of the\n// `expected`\ntemplate <class T, class E, bool = std::is_trivially_destructible<T>::value,\n          bool = std::is_trivially_destructible<E>::value>\nstruct expected_storage_base {\n  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}\n  constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =\n                nullptr>\n  constexpr expected_storage_base(in_place_t, Args &&...args)\n      : m_val(std::forward<Args>(args)...), m_has_val(true) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,\n                                  Args &&...args)\n      : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =\n                nullptr>\n  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)\n      : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr explicit expected_storage_base(unexpect_t,\n                                           std::initializer_list<U> il,\n                                           Args &&...args)\n      : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}\n\n  ~expected_storage_base() {\n    if (m_has_val) {\n      m_val.~T();\n    } else {\n      m_unexpect.~unexpected<E>();\n    }\n  }\n  union {\n    T m_val;\n    unexpected<E> m_unexpect;\n    char m_no_init;\n  };\n  bool m_has_val;\n};\n\n// This specialization is for when both `T` and `E` are trivially-destructible,\n// so the destructor of the `expected` can be trivial.\ntemplate <class T, class E> struct expected_storage_base<T, E, true, true> {\n  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}\n  constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =\n                nullptr>\n  constexpr expected_storage_base(in_place_t, Args &&...args)\n      : m_val(std::forward<Args>(args)...), m_has_val(true) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,\n                                  Args &&...args)\n      : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =\n                nullptr>\n  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)\n      : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr explicit expected_storage_base(unexpect_t,\n                                           std::initializer_list<U> il,\n                                           Args &&...args)\n      : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}\n\n  ~expected_storage_base() = default;\n  union {\n    T m_val;\n    unexpected<E> m_unexpect;\n    char m_no_init;\n  };\n  bool m_has_val;\n};\n\n// T is trivial, E is not.\ntemplate <class T, class E> struct expected_storage_base<T, E, true, false> {\n  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}\n  TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t)\n      : m_no_init(), m_has_val(false) {}\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =\n                nullptr>\n  constexpr expected_storage_base(in_place_t, Args &&...args)\n      : m_val(std::forward<Args>(args)...), m_has_val(true) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,\n                                  Args &&...args)\n      : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =\n                nullptr>\n  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)\n      : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr explicit expected_storage_base(unexpect_t,\n                                           std::initializer_list<U> il,\n                                           Args &&...args)\n      : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}\n\n  ~expected_storage_base() {\n    if (!m_has_val) {\n      m_unexpect.~unexpected<E>();\n    }\n  }\n\n  union {\n    T m_val;\n    unexpected<E> m_unexpect;\n    char m_no_init;\n  };\n  bool m_has_val;\n};\n\n// E is trivial, T is not.\ntemplate <class T, class E> struct expected_storage_base<T, E, false, true> {\n  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}\n  constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =\n                nullptr>\n  constexpr expected_storage_base(in_place_t, Args &&...args)\n      : m_val(std::forward<Args>(args)...), m_has_val(true) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,\n                                  Args &&...args)\n      : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =\n                nullptr>\n  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)\n      : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr explicit expected_storage_base(unexpect_t,\n                                           std::initializer_list<U> il,\n                                           Args &&...args)\n      : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}\n\n  ~expected_storage_base() {\n    if (m_has_val) {\n      m_val.~T();\n    }\n  }\n  union {\n    T m_val;\n    unexpected<E> m_unexpect;\n    char m_no_init;\n  };\n  bool m_has_val;\n};\n\n// `T` is `void`, `E` is trivially-destructible\ntemplate <class E> struct expected_storage_base<void, E, false, true> {\n#if __GNUC__ <= 5\n// no constexpr for GCC 4/5 bug\n#else\n  TL_EXPECTED_MSVC2015_CONSTEXPR\n#endif\n  expected_storage_base() : m_has_val(true) {}\n\n  constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {}\n\n  constexpr expected_storage_base(in_place_t) : m_has_val(true) {}\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =\n                nullptr>\n  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)\n      : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr explicit expected_storage_base(unexpect_t,\n                                           std::initializer_list<U> il,\n                                           Args &&...args)\n      : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}\n\n  ~expected_storage_base() = default;\n  struct dummy {};\n  union {\n    unexpected<E> m_unexpect;\n    dummy m_val;\n  };\n  bool m_has_val;\n};\n\n// `T` is `void`, `E` is not trivially-destructible\ntemplate <class E> struct expected_storage_base<void, E, false, false> {\n  constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}\n  constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {}\n\n  constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {}\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =\n                nullptr>\n  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)\n      : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr explicit expected_storage_base(unexpect_t,\n                                           std::initializer_list<U> il,\n                                           Args &&...args)\n      : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}\n\n  ~expected_storage_base() {\n    if (!m_has_val) {\n      m_unexpect.~unexpected<E>();\n    }\n  }\n\n  union {\n    unexpected<E> m_unexpect;\n    char m_dummy;\n  };\n  bool m_has_val;\n};\n\n// This base class provides some handy member functions which can be used in\n// further derived classes\ntemplate <class T, class E>\nstruct expected_operations_base : expected_storage_base<T, E> {\n  using expected_storage_base<T, E>::expected_storage_base;\n\n  template <class... Args> void construct(Args &&...args) noexcept {\n    new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);\n    this->m_has_val = true;\n  }\n\n  template <class Rhs> void construct_with(Rhs &&rhs) noexcept {\n    new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());\n    this->m_has_val = true;\n  }\n\n  template <class... Args> void construct_error(Args &&...args) noexcept {\n    new (std::addressof(this->m_unexpect))\n        unexpected<E>(std::forward<Args>(args)...);\n    this->m_has_val = false;\n  }\n\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n\n  // These assign overloads ensure that the most efficient assignment\n  // implementation is used while maintaining the strong exception guarantee.\n  // The problematic case is where rhs has a value, but *this does not.\n  //\n  // This overload handles the case where we can just copy-construct `T`\n  // directly into place without throwing.\n  template <class U = T,\n            detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value>\n                * = nullptr>\n  void assign(const expected_operations_base &rhs) noexcept {\n    if (!this->m_has_val && rhs.m_has_val) {\n      geterr().~unexpected<E>();\n      construct(rhs.get());\n    } else {\n      assign_common(rhs);\n    }\n  }\n\n  // This overload handles the case where we can attempt to create a copy of\n  // `T`, then no-throw move it into place if the copy was successful.\n  template <class U = T,\n            detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&\n                                std::is_nothrow_move_constructible<U>::value>\n                * = nullptr>\n  void assign(const expected_operations_base &rhs) noexcept {\n    if (!this->m_has_val && rhs.m_has_val) {\n      T tmp = rhs.get();\n      geterr().~unexpected<E>();\n      construct(std::move(tmp));\n    } else {\n      assign_common(rhs);\n    }\n  }\n\n  // This overload is the worst-case, where we have to move-construct the\n  // unexpected value into temporary storage, then try to copy the T into place.\n  // If the construction succeeds, then everything is fine, but if it throws,\n  // then we move the old unexpected value back into place before rethrowing the\n  // exception.\n  template <class U = T,\n            detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&\n                                !std::is_nothrow_move_constructible<U>::value>\n                * = nullptr>\n  void assign(const expected_operations_base &rhs) {\n    if (!this->m_has_val && rhs.m_has_val) {\n      auto tmp = std::move(geterr());\n      geterr().~unexpected<E>();\n\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n      try {\n        construct(rhs.get());\n      } catch (...) {\n        geterr() = std::move(tmp);\n        throw;\n      }\n#else\n      construct(rhs.get());\n#endif\n    } else {\n      assign_common(rhs);\n    }\n  }\n\n  // These overloads do the same as above, but for rvalues\n  template <class U = T,\n            detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>\n                * = nullptr>\n  void assign(expected_operations_base &&rhs) noexcept {\n    if (!this->m_has_val && rhs.m_has_val) {\n      geterr().~unexpected<E>();\n      construct(std::move(rhs).get());\n    } else {\n      assign_common(std::move(rhs));\n    }\n  }\n\n  template <class U = T,\n            detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>\n                * = nullptr>\n  void assign(expected_operations_base &&rhs) {\n    if (!this->m_has_val && rhs.m_has_val) {\n      auto tmp = std::move(geterr());\n      geterr().~unexpected<E>();\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n      try {\n        construct(std::move(rhs).get());\n      } catch (...) {\n        geterr() = std::move(tmp);\n        throw;\n      }\n#else\n      construct(std::move(rhs).get());\n#endif\n    } else {\n      assign_common(std::move(rhs));\n    }\n  }\n\n#else\n\n  // If exceptions are disabled then we can just copy-construct\n  void assign(const expected_operations_base &rhs) noexcept {\n    if (!this->m_has_val && rhs.m_has_val) {\n      geterr().~unexpected<E>();\n      construct(rhs.get());\n    } else {\n      assign_common(rhs);\n    }\n  }\n\n  void assign(expected_operations_base &&rhs) noexcept {\n    if (!this->m_has_val && rhs.m_has_val) {\n      geterr().~unexpected<E>();\n      construct(std::move(rhs).get());\n    } else {\n      assign_common(std::move(rhs));\n    }\n  }\n\n#endif\n\n  // The common part of move/copy assigning\n  template <class Rhs> void assign_common(Rhs &&rhs) {\n    if (this->m_has_val) {\n      if (rhs.m_has_val) {\n        get() = std::forward<Rhs>(rhs).get();\n      } else {\n        destroy_val();\n        construct_error(std::forward<Rhs>(rhs).geterr());\n      }\n    } else {\n      if (!rhs.m_has_val) {\n        geterr() = std::forward<Rhs>(rhs).geterr();\n      }\n    }\n  }\n\n  bool has_value() const { return this->m_has_val; }\n\n  TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; }\n  constexpr const T &get() const & { return this->m_val; }\n  TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); }\n#ifndef TL_EXPECTED_NO_CONSTRR\n  constexpr const T &&get() const && { return std::move(this->m_val); }\n#endif\n\n  TL_EXPECTED_11_CONSTEXPR unexpected<E> &geterr() & {\n    return this->m_unexpect;\n  }\n  constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }\n  TL_EXPECTED_11_CONSTEXPR unexpected<E> &&geterr() && {\n    return std::move(this->m_unexpect);\n  }\n#ifndef TL_EXPECTED_NO_CONSTRR\n  constexpr const unexpected<E> &&geterr() const && {\n    return std::move(this->m_unexpect);\n  }\n#endif\n\n  TL_EXPECTED_11_CONSTEXPR void destroy_val() { get().~T(); }\n};\n\n// This base class provides some handy member functions which can be used in\n// further derived classes\ntemplate <class E>\nstruct expected_operations_base<void, E> : expected_storage_base<void, E> {\n  using expected_storage_base<void, E>::expected_storage_base;\n\n  template <class... Args> void construct() noexcept { this->m_has_val = true; }\n\n  // This function doesn't use its argument, but needs it so that code in\n  // levels above this can work independently of whether T is void\n  template <class Rhs> void construct_with(Rhs &&) noexcept {\n    this->m_has_val = true;\n  }\n\n  template <class... Args> void construct_error(Args &&...args) noexcept {\n    new (std::addressof(this->m_unexpect))\n        unexpected<E>(std::forward<Args>(args)...);\n    this->m_has_val = false;\n  }\n\n  template <class Rhs> void assign(Rhs &&rhs) noexcept {\n    if (!this->m_has_val) {\n      if (rhs.m_has_val) {\n        geterr().~unexpected<E>();\n        construct();\n      } else {\n        geterr() = std::forward<Rhs>(rhs).geterr();\n      }\n    } else {\n      if (!rhs.m_has_val) {\n        construct_error(std::forward<Rhs>(rhs).geterr());\n      }\n    }\n  }\n\n  bool has_value() const { return this->m_has_val; }\n\n  TL_EXPECTED_11_CONSTEXPR unexpected<E> &geterr() & {\n    return this->m_unexpect;\n  }\n  constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }\n  TL_EXPECTED_11_CONSTEXPR unexpected<E> &&geterr() && {\n    return std::move(this->m_unexpect);\n  }\n#ifndef TL_EXPECTED_NO_CONSTRR\n  constexpr const unexpected<E> &&geterr() const && {\n    return std::move(this->m_unexpect);\n  }\n#endif\n\n  TL_EXPECTED_11_CONSTEXPR void destroy_val() {\n    // no-op\n  }\n};\n\n// This class manages conditionally having a trivial copy constructor\n// This specialization is for when T and E are trivially copy constructible\ntemplate <class T, class E,\n          bool = is_void_or<T, TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::\n              value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>\nstruct expected_copy_base : expected_operations_base<T, E> {\n  using expected_operations_base<T, E>::expected_operations_base;\n};\n\n// This specialization is for when T or E are not trivially copy constructible\ntemplate <class T, class E>\nstruct expected_copy_base<T, E, false> : expected_operations_base<T, E> {\n  using expected_operations_base<T, E>::expected_operations_base;\n\n  expected_copy_base() = default;\n  expected_copy_base(const expected_copy_base &rhs)\n      : expected_operations_base<T, E>(no_init) {\n    if (rhs.has_value()) {\n      this->construct_with(rhs);\n    } else {\n      this->construct_error(rhs.geterr());\n    }\n  }\n\n  expected_copy_base(expected_copy_base &&rhs) = default;\n  expected_copy_base &operator=(const expected_copy_base &rhs) = default;\n  expected_copy_base &operator=(expected_copy_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial move constructor\n// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it\n// doesn't implement an analogue to std::is_trivially_move_constructible. We\n// have to make do with a non-trivial move constructor even if T is trivially\n// move constructible\n#ifndef TL_EXPECTED_GCC49\ntemplate <class T, class E,\n          bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value\n              &&std::is_trivially_move_constructible<E>::value>\nstruct expected_move_base : expected_copy_base<T, E> {\n  using expected_copy_base<T, E>::expected_copy_base;\n};\n#else\ntemplate <class T, class E, bool = false> struct expected_move_base;\n#endif\ntemplate <class T, class E>\nstruct expected_move_base<T, E, false> : expected_copy_base<T, E> {\n  using expected_copy_base<T, E>::expected_copy_base;\n\n  expected_move_base() = default;\n  expected_move_base(const expected_move_base &rhs) = default;\n\n  expected_move_base(expected_move_base &&rhs) noexcept(\n      std::is_nothrow_move_constructible<T>::value)\n      : expected_copy_base<T, E>(no_init) {\n    if (rhs.has_value()) {\n      this->construct_with(std::move(rhs));\n    } else {\n      this->construct_error(std::move(rhs.geterr()));\n    }\n  }\n  expected_move_base &operator=(const expected_move_base &rhs) = default;\n  expected_move_base &operator=(expected_move_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial copy assignment operator\ntemplate <class T, class E,\n          bool = is_void_or<\n              T, conjunction<TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),\n                             TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),\n                             TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value\n              &&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value\n                  &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value\n                      &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>\nstruct expected_copy_assign_base : expected_move_base<T, E> {\n  using expected_move_base<T, E>::expected_move_base;\n};\n\ntemplate <class T, class E>\nstruct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {\n  using expected_move_base<T, E>::expected_move_base;\n\n  expected_copy_assign_base() = default;\n  expected_copy_assign_base(const expected_copy_assign_base &rhs) = default;\n\n  expected_copy_assign_base(expected_copy_assign_base &&rhs) = default;\n  expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) {\n    this->assign(rhs);\n    return *this;\n  }\n  expected_copy_assign_base &\n  operator=(expected_copy_assign_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial move assignment operator\n// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it\n// doesn't implement an analogue to std::is_trivially_move_assignable. We have\n// to make do with a non-trivial move assignment operator even if T is trivially\n// move assignable\n#ifndef TL_EXPECTED_GCC49\ntemplate <class T, class E,\n          bool =\n              is_void_or<T, conjunction<std::is_trivially_destructible<T>,\n                                        std::is_trivially_move_constructible<T>,\n                                        std::is_trivially_move_assignable<T>>>::\n                  value &&std::is_trivially_destructible<E>::value\n                      &&std::is_trivially_move_constructible<E>::value\n                          &&std::is_trivially_move_assignable<E>::value>\nstruct expected_move_assign_base : expected_copy_assign_base<T, E> {\n  using expected_copy_assign_base<T, E>::expected_copy_assign_base;\n};\n#else\ntemplate <class T, class E, bool = false> struct expected_move_assign_base;\n#endif\n\ntemplate <class T, class E>\nstruct expected_move_assign_base<T, E, false>\n    : expected_copy_assign_base<T, E> {\n  using expected_copy_assign_base<T, E>::expected_copy_assign_base;\n\n  expected_move_assign_base() = default;\n  expected_move_assign_base(const expected_move_assign_base &rhs) = default;\n\n  expected_move_assign_base(expected_move_assign_base &&rhs) = default;\n\n  expected_move_assign_base &\n  operator=(const expected_move_assign_base &rhs) = default;\n\n  expected_move_assign_base &\n  operator=(expected_move_assign_base &&rhs) noexcept(\n      std::is_nothrow_move_constructible<T>::value\n          &&std::is_nothrow_move_assignable<T>::value) {\n    this->assign(std::move(rhs));\n    return *this;\n  }\n};\n\n// expected_delete_ctor_base will conditionally delete copy and move\n// constructors depending on whether T is copy/move constructible\ntemplate <class T, class E,\n          bool EnableCopy = (is_copy_constructible_or_void<T>::value &&\n                             std::is_copy_constructible<E>::value),\n          bool EnableMove = (is_move_constructible_or_void<T>::value &&\n                             std::is_move_constructible<E>::value)>\nstruct expected_delete_ctor_base {\n  expected_delete_ctor_base() = default;\n  expected_delete_ctor_base(const expected_delete_ctor_base &) = default;\n  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;\n  expected_delete_ctor_base &\n  operator=(const expected_delete_ctor_base &) = default;\n  expected_delete_ctor_base &\n  operator=(expected_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T, class E>\nstruct expected_delete_ctor_base<T, E, true, false> {\n  expected_delete_ctor_base() = default;\n  expected_delete_ctor_base(const expected_delete_ctor_base &) = default;\n  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;\n  expected_delete_ctor_base &\n  operator=(const expected_delete_ctor_base &) = default;\n  expected_delete_ctor_base &\n  operator=(expected_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T, class E>\nstruct expected_delete_ctor_base<T, E, false, true> {\n  expected_delete_ctor_base() = default;\n  expected_delete_ctor_base(const expected_delete_ctor_base &) = delete;\n  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;\n  expected_delete_ctor_base &\n  operator=(const expected_delete_ctor_base &) = default;\n  expected_delete_ctor_base &\n  operator=(expected_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T, class E>\nstruct expected_delete_ctor_base<T, E, false, false> {\n  expected_delete_ctor_base() = default;\n  expected_delete_ctor_base(const expected_delete_ctor_base &) = delete;\n  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;\n  expected_delete_ctor_base &\n  operator=(const expected_delete_ctor_base &) = default;\n  expected_delete_ctor_base &\n  operator=(expected_delete_ctor_base &&) noexcept = default;\n};\n\n// expected_delete_assign_base will conditionally delete copy and move\n// constructors depending on whether T and E are copy/move constructible +\n// assignable\ntemplate <class T, class E,\n          bool EnableCopy = (is_copy_constructible_or_void<T>::value &&\n                             std::is_copy_constructible<E>::value &&\n                             is_copy_assignable_or_void<T>::value &&\n                             std::is_copy_assignable<E>::value),\n          bool EnableMove = (is_move_constructible_or_void<T>::value &&\n                             std::is_move_constructible<E>::value &&\n                             is_move_assignable_or_void<T>::value &&\n                             std::is_move_assignable<E>::value)>\nstruct expected_delete_assign_base {\n  expected_delete_assign_base() = default;\n  expected_delete_assign_base(const expected_delete_assign_base &) = default;\n  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =\n      default;\n  expected_delete_assign_base &\n  operator=(const expected_delete_assign_base &) = default;\n  expected_delete_assign_base &\n  operator=(expected_delete_assign_base &&) noexcept = default;\n};\n\ntemplate <class T, class E>\nstruct expected_delete_assign_base<T, E, true, false> {\n  expected_delete_assign_base() = default;\n  expected_delete_assign_base(const expected_delete_assign_base &) = default;\n  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =\n      default;\n  expected_delete_assign_base &\n  operator=(const expected_delete_assign_base &) = default;\n  expected_delete_assign_base &\n  operator=(expected_delete_assign_base &&) noexcept = delete;\n};\n\ntemplate <class T, class E>\nstruct expected_delete_assign_base<T, E, false, true> {\n  expected_delete_assign_base() = default;\n  expected_delete_assign_base(const expected_delete_assign_base &) = default;\n  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =\n      default;\n  expected_delete_assign_base &\n  operator=(const expected_delete_assign_base &) = delete;\n  expected_delete_assign_base &\n  operator=(expected_delete_assign_base &&) noexcept = default;\n};\n\ntemplate <class T, class E>\nstruct expected_delete_assign_base<T, E, false, false> {\n  expected_delete_assign_base() = default;\n  expected_delete_assign_base(const expected_delete_assign_base &) = default;\n  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =\n      default;\n  expected_delete_assign_base &\n  operator=(const expected_delete_assign_base &) = delete;\n  expected_delete_assign_base &\n  operator=(expected_delete_assign_base &&) noexcept = delete;\n};\n\n// This is needed to be able to construct the expected_default_ctor_base which\n// follows, while still conditionally deleting the default constructor.\nstruct default_constructor_tag {\n  explicit constexpr default_constructor_tag() = default;\n};\n\n// expected_default_ctor_base will ensure that expected has a deleted default\n// consturctor if T is not default constructible.\n// This specialization is for when T is default constructible\ntemplate <class T, class E,\n          bool Enable =\n              std::is_default_constructible<T>::value || std::is_void<T>::value>\nstruct expected_default_ctor_base {\n  constexpr expected_default_ctor_base() noexcept = default;\n  constexpr expected_default_ctor_base(\n      expected_default_ctor_base const &) noexcept = default;\n  constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =\n      default;\n  expected_default_ctor_base &\n  operator=(expected_default_ctor_base const &) noexcept = default;\n  expected_default_ctor_base &\n  operator=(expected_default_ctor_base &&) noexcept = default;\n\n  constexpr explicit expected_default_ctor_base(default_constructor_tag) {}\n};\n\n// This specialization is for when T is not default constructible\ntemplate <class T, class E> struct expected_default_ctor_base<T, E, false> {\n  constexpr expected_default_ctor_base() noexcept = delete;\n  constexpr expected_default_ctor_base(\n      expected_default_ctor_base const &) noexcept = default;\n  constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =\n      default;\n  expected_default_ctor_base &\n  operator=(expected_default_ctor_base const &) noexcept = default;\n  expected_default_ctor_base &\n  operator=(expected_default_ctor_base &&) noexcept = default;\n\n  constexpr explicit expected_default_ctor_base(default_constructor_tag) {}\n};\n} // namespace detail\n\ntemplate <class E> class bad_expected_access : public std::exception {\npublic:\n  explicit bad_expected_access(E e) : m_val(std::move(e)) {}\n\n  virtual const char *what() const noexcept override {\n    return \"Bad expected access\";\n  }\n\n  const E &error() const & { return m_val; }\n  E &error() & { return m_val; }\n  const E &&error() const && { return std::move(m_val); }\n  E &&error() && { return std::move(m_val); }\n\nprivate:\n  E m_val;\n};\n\n/// An `expected<T, E>` object is an object that contains the storage for\n/// another object and manages the lifetime of this contained object `T`.\n/// Alternatively it could contain the storage for another unexpected object\n/// `E`. The contained object may not be initialized after the expected object\n/// has been initialized, and may not be destroyed before the expected object\n/// has been destroyed. The initialization state of the contained object is\n/// tracked by the expected object.\ntemplate <class T, class E>\nclass expected : private detail::expected_move_assign_base<T, E>,\n                 private detail::expected_delete_ctor_base<T, E>,\n                 private detail::expected_delete_assign_base<T, E>,\n                 private detail::expected_default_ctor_base<T, E> {\n  static_assert(!std::is_reference<T>::value, \"T must not be a reference\");\n  static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,\n                \"T must not be in_place_t\");\n  static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,\n                \"T must not be unexpect_t\");\n  static_assert(\n      !std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,\n      \"T must not be unexpected<E>\");\n  static_assert(!std::is_reference<E>::value, \"E must not be a reference\");\n\n  T *valptr() { return std::addressof(this->m_val); }\n  const T *valptr() const { return std::addressof(this->m_val); }\n  unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }\n  const unexpected<E> *errptr() const {\n    return std::addressof(this->m_unexpect);\n  }\n\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR U &val() {\n    return this->m_val;\n  }\n  TL_EXPECTED_11_CONSTEXPR unexpected<E> &err() { return this->m_unexpect; }\n\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  constexpr const U &val() const {\n    return this->m_val;\n  }\n  constexpr const unexpected<E> &err() const { return this->m_unexpect; }\n\n  using impl_base = detail::expected_move_assign_base<T, E>;\n  using ctor_base = detail::expected_default_ctor_base<T, E>;\n\npublic:\n  typedef T value_type;\n  typedef E error_type;\n  typedef unexpected<E> unexpected_type;\n\n#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&               \\\n    !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {\n    return and_then_impl(*this, std::forward<F>(f));\n  }\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {\n    return and_then_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F> constexpr auto and_then(F &&f) const & {\n    return and_then_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_EXPECTED_NO_CONSTRR\n  template <class F> constexpr auto and_then(F &&f) const && {\n    return and_then_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n\n#else\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR auto\n  and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected &>(),\n                                              std::forward<F>(f))) {\n    return and_then_impl(*this, std::forward<F>(f));\n  }\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR auto\n  and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),\n                                               std::forward<F>(f))) {\n    return and_then_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F>\n  constexpr auto and_then(F &&f) const & -> decltype(and_then_impl(\n      std::declval<expected const &>(), std::forward<F>(f))) {\n    return and_then_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_EXPECTED_NO_CONSTRR\n  template <class F>\n  constexpr auto and_then(F &&f) const && -> decltype(and_then_impl(\n      std::declval<expected const &&>(), std::forward<F>(f))) {\n    return and_then_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n#endif\n\n#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&               \\\n    !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F> constexpr auto map(F &&f) const & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n  template <class F> constexpr auto map(F &&f) const && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#else\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(\n      std::declval<expected &>(), std::declval<F &&>()))\n  map(F &&f) & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval<expected>(),\n                                                      std::declval<F &&>()))\n  map(F &&f) && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F>\n  constexpr decltype(expected_map_impl(std::declval<const expected &>(),\n                                       std::declval<F &&>()))\n  map(F &&f) const & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_EXPECTED_NO_CONSTRR\n  template <class F>\n  constexpr decltype(expected_map_impl(std::declval<const expected &&>(),\n                                       std::declval<F &&>()))\n  map(F &&f) const && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n#endif\n\n#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&               \\\n    !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F> constexpr auto transform(F &&f) const & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n  template <class F> constexpr auto transform(F &&f) const && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#else\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(\n      std::declval<expected &>(), std::declval<F &&>()))\n  transform(F &&f) & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval<expected>(),\n                                                      std::declval<F &&>()))\n  transform(F &&f) && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F>\n  constexpr decltype(expected_map_impl(std::declval<const expected &>(),\n                                       std::declval<F &&>()))\n  transform(F &&f) const & {\n    return expected_map_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_EXPECTED_NO_CONSTRR\n  template <class F>\n  constexpr decltype(expected_map_impl(std::declval<const expected &&>(),\n                                       std::declval<F &&>()))\n  transform(F &&f) const && {\n    return expected_map_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n#endif\n\n#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&               \\\n    !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F> constexpr auto map_error(F &&f) const & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n  template <class F> constexpr auto map_error(F &&f) const && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n#else\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),\n                                                   std::declval<F &&>()))\n  map_error(F &&f) & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),\n                                                   std::declval<F &&>()))\n  map_error(F &&f) && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F>\n  constexpr decltype(map_error_impl(std::declval<const expected &>(),\n                                    std::declval<F &&>()))\n  map_error(F &&f) const & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_EXPECTED_NO_CONSTRR\n  template <class F>\n  constexpr decltype(map_error_impl(std::declval<const expected &&>(),\n                                    std::declval<F &&>()))\n  map_error(F &&f) const && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n#endif\n#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&               \\\n    !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n  template <class F> TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F> constexpr auto transform_error(F &&f) const & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n  template <class F> constexpr auto transform_error(F &&f) const && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n#else\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),\n                                                   std::declval<F &&>()))\n  transform_error(F &&f) & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n  template <class F>\n  TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),\n                                                   std::declval<F &&>()))\n  transform_error(F &&f) && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n  template <class F>\n  constexpr decltype(map_error_impl(std::declval<const expected &>(),\n                                    std::declval<F &&>()))\n  transform_error(F &&f) const & {\n    return map_error_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_EXPECTED_NO_CONSTRR\n  template <class F>\n  constexpr decltype(map_error_impl(std::declval<const expected &&>(),\n                                    std::declval<F &&>()))\n  transform_error(F &&f) const && {\n    return map_error_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n#endif\n  template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & {\n    return or_else_impl(*this, std::forward<F>(f));\n  }\n\n  template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && {\n    return or_else_impl(std::move(*this), std::forward<F>(f));\n  }\n\n  template <class F> expected constexpr or_else(F &&f) const & {\n    return or_else_impl(*this, std::forward<F>(f));\n  }\n\n#ifndef TL_EXPECTED_NO_CONSTRR\n  template <class F> expected constexpr or_else(F &&f) const && {\n    return or_else_impl(std::move(*this), std::forward<F>(f));\n  }\n#endif\n  constexpr expected() = default;\n  constexpr expected(const expected &rhs) = default;\n  constexpr expected(expected &&rhs) = default;\n  expected &operator=(const expected &rhs) = default;\n  expected &operator=(expected &&rhs) = default;\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =\n                nullptr>\n  constexpr expected(in_place_t, Args &&...args)\n      : impl_base(in_place, std::forward<Args>(args)...),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)\n      : impl_base(in_place, il, std::forward<Args>(args)...),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <class G = E,\n            detail::enable_if_t<std::is_constructible<E, const G &>::value> * =\n                nullptr,\n            detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =\n                nullptr>\n  explicit constexpr expected(const unexpected<G> &e)\n      : impl_base(unexpect, e.value()),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <\n      class G = E,\n      detail::enable_if_t<std::is_constructible<E, const G &>::value> * =\n          nullptr,\n      detail::enable_if_t<std::is_convertible<const G &, E>::value> * = nullptr>\n  constexpr expected(unexpected<G> const &e)\n      : impl_base(unexpect, e.value()),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <\n      class G = E,\n      detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,\n      detail::enable_if_t<!std::is_convertible<G &&, E>::value> * = nullptr>\n  explicit constexpr expected(unexpected<G> &&e) noexcept(\n      std::is_nothrow_constructible<E, G &&>::value)\n      : impl_base(unexpect, std::move(e.value())),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <\n      class G = E,\n      detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,\n      detail::enable_if_t<std::is_convertible<G &&, E>::value> * = nullptr>\n  constexpr expected(unexpected<G> &&e) noexcept(\n      std::is_nothrow_constructible<E, G &&>::value)\n      : impl_base(unexpect, std::move(e.value())),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <class... Args,\n            detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =\n                nullptr>\n  constexpr explicit expected(unexpect_t, Args &&...args)\n      : impl_base(unexpect, std::forward<Args>(args)...),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_constructible<\n                E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  constexpr explicit expected(unexpect_t, std::initializer_list<U> il,\n                              Args &&...args)\n      : impl_base(unexpect, il, std::forward<Args>(args)...),\n        ctor_base(detail::default_constructor_tag{}) {}\n\n  template <class U, class G,\n            detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&\n                                  std::is_convertible<G const &, E>::value)> * =\n                nullptr,\n            detail::expected_enable_from_other<T, E, U, G, const U &, const G &>\n                * = nullptr>\n  explicit TL_EXPECTED_11_CONSTEXPR expected(const expected<U, G> &rhs)\n      : ctor_base(detail::default_constructor_tag{}) {\n    if (rhs.has_value()) {\n      this->construct(*rhs);\n    } else {\n      this->construct_error(rhs.error());\n    }\n  }\n\n  template <class U, class G,\n            detail::enable_if_t<(std::is_convertible<U const &, T>::value &&\n                                 std::is_convertible<G const &, E>::value)> * =\n                nullptr,\n            detail::expected_enable_from_other<T, E, U, G, const U &, const G &>\n                * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR expected(const expected<U, G> &rhs)\n      : ctor_base(detail::default_constructor_tag{}) {\n    if (rhs.has_value()) {\n      this->construct(*rhs);\n    } else {\n      this->construct_error(rhs.error());\n    }\n  }\n\n  template <\n      class U, class G,\n      detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&\n                            std::is_convertible<G &&, E>::value)> * = nullptr,\n      detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>\n  explicit TL_EXPECTED_11_CONSTEXPR expected(expected<U, G> &&rhs)\n      : ctor_base(detail::default_constructor_tag{}) {\n    if (rhs.has_value()) {\n      this->construct(std::move(*rhs));\n    } else {\n      this->construct_error(std::move(rhs.error()));\n    }\n  }\n\n  template <\n      class U, class G,\n      detail::enable_if_t<(std::is_convertible<U &&, T>::value &&\n                           std::is_convertible<G &&, E>::value)> * = nullptr,\n      detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR expected(expected<U, G> &&rhs)\n      : ctor_base(detail::default_constructor_tag{}) {\n    if (rhs.has_value()) {\n      this->construct(std::move(*rhs));\n    } else {\n      this->construct_error(std::move(rhs.error()));\n    }\n  }\n\n  template <\n      class U = T,\n      detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,\n      detail::expected_enable_forward_value<T, E, U> * = nullptr>\n  explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)\n      : expected(in_place, std::forward<U>(v)) {}\n\n  template <\n      class U = T,\n      detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,\n      detail::expected_enable_forward_value<T, E, U> * = nullptr>\n  TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)\n      : expected(in_place, std::forward<U>(v)) {}\n\n  template <\n      class U = T, class G = T,\n      detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =\n          nullptr,\n      detail::enable_if_t<!std::is_void<G>::value> * = nullptr,\n      detail::enable_if_t<\n          (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&\n           !detail::conjunction<std::is_scalar<T>,\n                                std::is_same<T, detail::decay_t<U>>>::value &&\n           std::is_constructible<T, U>::value &&\n           std::is_assignable<G &, U>::value &&\n           std::is_nothrow_move_constructible<E>::value)> * = nullptr>\n  expected &operator=(U &&v) {\n    if (has_value()) {\n      val() = std::forward<U>(v);\n    } else {\n      err().~unexpected<E>();\n      ::new (valptr()) T(std::forward<U>(v));\n      this->m_has_val = true;\n    }\n\n    return *this;\n  }\n\n  template <\n      class U = T, class G = T,\n      detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =\n          nullptr,\n      detail::enable_if_t<!std::is_void<U>::value> * = nullptr,\n      detail::enable_if_t<\n          (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&\n           !detail::conjunction<std::is_scalar<T>,\n                                std::is_same<T, detail::decay_t<U>>>::value &&\n           std::is_constructible<T, U>::value &&\n           std::is_assignable<G &, U>::value &&\n           std::is_nothrow_move_constructible<E>::value)> * = nullptr>\n  expected &operator=(U &&v) {\n    if (has_value()) {\n      val() = std::forward<U>(v);\n    } else {\n      auto tmp = std::move(err());\n      err().~unexpected<E>();\n\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n      try {\n        ::new (valptr()) T(std::forward<U>(v));\n        this->m_has_val = true;\n      } catch (...) {\n        err() = std::move(tmp);\n        throw;\n      }\n#else\n      ::new (valptr()) T(std::forward<U>(v));\n      this->m_has_val = true;\n#endif\n    }\n\n    return *this;\n  }\n\n  template <class G = E,\n            detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&\n                                std::is_assignable<G &, G>::value> * = nullptr>\n  expected &operator=(const unexpected<G> &rhs) {\n    if (!has_value()) {\n      err() = rhs;\n    } else {\n      this->destroy_val();\n      ::new (errptr()) unexpected<E>(rhs);\n      this->m_has_val = false;\n    }\n\n    return *this;\n  }\n\n  template <class G = E,\n            detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&\n                                std::is_move_assignable<G>::value> * = nullptr>\n  expected &operator=(unexpected<G> &&rhs) noexcept {\n    if (!has_value()) {\n      err() = std::move(rhs);\n    } else {\n      this->destroy_val();\n      ::new (errptr()) unexpected<E>(std::move(rhs));\n      this->m_has_val = false;\n    }\n\n    return *this;\n  }\n\n  template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<\n                               T, Args &&...>::value> * = nullptr>\n  void emplace(Args &&...args) {\n    if (has_value()) {\n      val().~T();\n    } else {\n      err().~unexpected<E>();\n      this->m_has_val = true;\n    }\n    ::new (valptr()) T(std::forward<Args>(args)...);\n  }\n\n  template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<\n                               T, Args &&...>::value> * = nullptr>\n  void emplace(Args &&...args) {\n    if (has_value()) {\n      val().~T();\n      ::new (valptr()) T(std::forward<Args>(args)...);\n    } else {\n      auto tmp = std::move(err());\n      err().~unexpected<E>();\n\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n      try {\n        ::new (valptr()) T(std::forward<Args>(args)...);\n        this->m_has_val = true;\n      } catch (...) {\n        err() = std::move(tmp);\n        throw;\n      }\n#else\n      ::new (valptr()) T(std::forward<Args>(args)...);\n      this->m_has_val = true;\n#endif\n    }\n  }\n\n  template <class U, class... Args,\n            detail::enable_if_t<std::is_nothrow_constructible<\n                T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  void emplace(std::initializer_list<U> il, Args &&...args) {\n    if (has_value()) {\n      T t(il, std::forward<Args>(args)...);\n      val() = std::move(t);\n    } else {\n      err().~unexpected<E>();\n      ::new (valptr()) T(il, std::forward<Args>(args)...);\n      this->m_has_val = true;\n    }\n  }\n\n  template <class U, class... Args,\n            detail::enable_if_t<!std::is_nothrow_constructible<\n                T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>\n  void emplace(std::initializer_list<U> il, Args &&...args) {\n    if (has_value()) {\n      T t(il, std::forward<Args>(args)...);\n      val() = std::move(t);\n    } else {\n      auto tmp = std::move(err());\n      err().~unexpected<E>();\n\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n      try {\n        ::new (valptr()) T(il, std::forward<Args>(args)...);\n        this->m_has_val = true;\n      } catch (...) {\n        err() = std::move(tmp);\n        throw;\n      }\n#else\n      ::new (valptr()) T(il, std::forward<Args>(args)...);\n      this->m_has_val = true;\n#endif\n    }\n  }\n\nprivate:\n  using t_is_void = std::true_type;\n  using t_is_not_void = std::false_type;\n  using t_is_nothrow_move_constructible = std::true_type;\n  using move_constructing_t_can_throw = std::false_type;\n  using e_is_nothrow_move_constructible = std::true_type;\n  using move_constructing_e_can_throw = std::false_type;\n\n  void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept {\n    // swapping void is a no-op\n  }\n\n  void swap_where_both_have_value(expected &rhs, t_is_not_void) {\n    using std::swap;\n    swap(val(), rhs.val());\n  }\n\n  void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(\n      std::is_nothrow_move_constructible<E>::value) {\n    ::new (errptr()) unexpected_type(std::move(rhs.err()));\n    rhs.err().~unexpected_type();\n    std::swap(this->m_has_val, rhs.m_has_val);\n  }\n\n  void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {\n    swap_where_only_one_has_value_and_t_is_not_void(\n        rhs, typename std::is_nothrow_move_constructible<T>::type{},\n        typename std::is_nothrow_move_constructible<E>::type{});\n  }\n\n  void swap_where_only_one_has_value_and_t_is_not_void(\n      expected &rhs, t_is_nothrow_move_constructible,\n      e_is_nothrow_move_constructible) noexcept {\n    auto temp = std::move(val());\n    val().~T();\n    ::new (errptr()) unexpected_type(std::move(rhs.err()));\n    rhs.err().~unexpected_type();\n    ::new (rhs.valptr()) T(std::move(temp));\n    std::swap(this->m_has_val, rhs.m_has_val);\n  }\n\n  void swap_where_only_one_has_value_and_t_is_not_void(\n      expected &rhs, t_is_nothrow_move_constructible,\n      move_constructing_e_can_throw) {\n    auto temp = std::move(val());\n    val().~T();\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n    try {\n      ::new (errptr()) unexpected_type(std::move(rhs.err()));\n      rhs.err().~unexpected_type();\n      ::new (rhs.valptr()) T(std::move(temp));\n      std::swap(this->m_has_val, rhs.m_has_val);\n    } catch (...) {\n      val() = std::move(temp);\n      throw;\n    }\n#else\n    ::new (errptr()) unexpected_type(std::move(rhs.err()));\n    rhs.err().~unexpected_type();\n    ::new (rhs.valptr()) T(std::move(temp));\n    std::swap(this->m_has_val, rhs.m_has_val);\n#endif\n  }\n\n  void swap_where_only_one_has_value_and_t_is_not_void(\n      expected &rhs, move_constructing_t_can_throw,\n      e_is_nothrow_move_constructible) {\n    auto temp = std::move(rhs.err());\n    rhs.err().~unexpected_type();\n#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED\n    try {\n      ::new (rhs.valptr()) T(std::move(val()));\n      val().~T();\n      ::new (errptr()) unexpected_type(std::move(temp));\n      std::swap(this->m_has_val, rhs.m_has_val);\n    } catch (...) {\n      rhs.err() = std::move(temp);\n      throw;\n    }\n#else\n    ::new (rhs.valptr()) T(std::move(val()));\n    val().~T();\n    ::new (errptr()) unexpected_type(std::move(temp));\n    std::swap(this->m_has_val, rhs.m_has_val);\n#endif\n  }\n\npublic:\n  template <class OT = T, class OE = E>\n  detail::enable_if_t<detail::is_swappable<OT>::value &&\n                      detail::is_swappable<OE>::value &&\n                      (std::is_nothrow_move_constructible<OT>::value ||\n                       std::is_nothrow_move_constructible<OE>::value)>\n  swap(expected &rhs) noexcept(\n      std::is_nothrow_move_constructible<T>::value\n          &&detail::is_nothrow_swappable<T>::value\n              &&std::is_nothrow_move_constructible<E>::value\n                  &&detail::is_nothrow_swappable<E>::value) {\n    if (has_value() && rhs.has_value()) {\n      swap_where_both_have_value(rhs, typename std::is_void<T>::type{});\n    } else if (!has_value() && rhs.has_value()) {\n      rhs.swap(*this);\n    } else if (has_value()) {\n      swap_where_only_one_has_value(rhs, typename std::is_void<T>::type{});\n    } else {\n      using std::swap;\n      swap(err(), rhs.err());\n    }\n  }\n\n  constexpr const T *operator->() const {\n    TL_ASSERT(has_value());\n    return valptr();\n  }\n  TL_EXPECTED_11_CONSTEXPR T *operator->() {\n    TL_ASSERT(has_value());\n    return valptr();\n  }\n\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  constexpr const U &operator*() const & {\n    TL_ASSERT(has_value());\n    return val();\n  }\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR U &operator*() & {\n    TL_ASSERT(has_value());\n    return val();\n  }\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  constexpr const U &&operator*() const && {\n    TL_ASSERT(has_value());\n    return std::move(val());\n  }\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR U &&operator*() && {\n    TL_ASSERT(has_value());\n    return std::move(val());\n  }\n\n  constexpr bool has_value() const noexcept { return this->m_has_val; }\n  constexpr explicit operator bool() const noexcept { return this->m_has_val; }\n\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR const U &value() const & {\n    if (!has_value())\n      detail::throw_exception(bad_expected_access<E>(err().value()));\n    return val();\n  }\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR U &value() & {\n    if (!has_value())\n      detail::throw_exception(bad_expected_access<E>(err().value()));\n    return val();\n  }\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR const U &&value() const && {\n    if (!has_value())\n      detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));\n    return std::move(val());\n  }\n  template <class U = T,\n            detail::enable_if_t<!std::is_void<U>::value> * = nullptr>\n  TL_EXPECTED_11_CONSTEXPR U &&value() && {\n    if (!has_value())\n      detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));\n    return std::move(val());\n  }\n\n  constexpr const E &error() const & {\n    TL_ASSERT(!has_value());\n    return err().value();\n  }\n  TL_EXPECTED_11_CONSTEXPR E &error() & {\n    TL_ASSERT(!has_value());\n    return err().value();\n  }\n  constexpr const E &&error() const && {\n    TL_ASSERT(!has_value());\n    return std::move(err().value());\n  }\n  TL_EXPECTED_11_CONSTEXPR E &&error() && {\n    TL_ASSERT(!has_value());\n    return std::move(err().value());\n  }\n\n  template <class U> constexpr T value_or(U &&v) const & {\n    static_assert(std::is_copy_constructible<T>::value &&\n                      std::is_convertible<U &&, T>::value,\n                  \"T must be copy-constructible and convertible to from U&&\");\n    return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));\n  }\n  template <class U> TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && {\n    static_assert(std::is_move_constructible<T>::value &&\n                      std::is_convertible<U &&, T>::value,\n                  \"T must be move-constructible and convertible to from U&&\");\n    return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));\n  }\n};\n\nnamespace detail {\ntemplate <class Exp> using exp_t = typename detail::decay_t<Exp>::value_type;\ntemplate <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;\ntemplate <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;\n\n#ifdef TL_EXPECTED_CXX14\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Exp>()))>\nconstexpr auto and_then_impl(Exp &&exp, F &&f) {\n  static_assert(detail::is_expected<Ret>::value, \"F must return an expected\");\n\n  return exp.has_value()\n             ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))\n             : Ret(unexpect, std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>()))>\nconstexpr auto and_then_impl(Exp &&exp, F &&f) {\n  static_assert(detail::is_expected<Ret>::value, \"F must return an expected\");\n\n  return exp.has_value() ? detail::invoke(std::forward<F>(f))\n                         : Ret(unexpect, std::forward<Exp>(exp).error());\n}\n#else\ntemplate <class> struct TC;\ntemplate <class Exp, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Exp>())),\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>\nauto and_then_impl(Exp &&exp, F &&f) -> Ret {\n  static_assert(detail::is_expected<Ret>::value, \"F must return an expected\");\n\n  return exp.has_value()\n             ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))\n             : Ret(unexpect, std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>())),\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>\nconstexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {\n  static_assert(detail::is_expected<Ret>::value, \"F must return an expected\");\n\n  return exp.has_value() ? detail::invoke(std::forward<F>(f))\n                         : Ret(unexpect, std::forward<Exp>(exp).error());\n}\n#endif\n\n#ifdef TL_EXPECTED_CXX14\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Exp>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto expected_map_impl(Exp &&exp, F &&f) {\n  using result = ret_t<Exp, detail::decay_t<Ret>>;\n  return exp.has_value() ? result(detail::invoke(std::forward<F>(f),\n                                                 *std::forward<Exp>(exp)))\n                         : result(unexpect, std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Exp>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto expected_map_impl(Exp &&exp, F &&f) {\n  using result = expected<void, err_t<Exp>>;\n  if (exp.has_value()) {\n    detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));\n    return result();\n  }\n\n  return result(unexpect, std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto expected_map_impl(Exp &&exp, F &&f) {\n  using result = ret_t<Exp, detail::decay_t<Ret>>;\n  return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))\n                         : result(unexpect, std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto expected_map_impl(Exp &&exp, F &&f) {\n  using result = expected<void, err_t<Exp>>;\n  if (exp.has_value()) {\n    detail::invoke(std::forward<F>(f));\n    return result();\n  }\n\n  return result(unexpect, std::forward<Exp>(exp).error());\n}\n#else\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Exp>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\n\nconstexpr auto expected_map_impl(Exp &&exp, F &&f)\n    -> ret_t<Exp, detail::decay_t<Ret>> {\n  using result = ret_t<Exp, detail::decay_t<Ret>>;\n\n  return exp.has_value() ? result(detail::invoke(std::forward<F>(f),\n                                                 *std::forward<Exp>(exp)))\n                         : result(unexpect, std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Exp>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\n\nauto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {\n  if (exp.has_value()) {\n    detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));\n    return {};\n  }\n\n  return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\n\nconstexpr auto expected_map_impl(Exp &&exp, F &&f)\n    -> ret_t<Exp, detail::decay_t<Ret>> {\n  using result = ret_t<Exp, detail::decay_t<Ret>>;\n\n  return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))\n                         : result(unexpect, std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\n\nauto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {\n  if (exp.has_value()) {\n    detail::invoke(std::forward<F>(f));\n    return {};\n  }\n\n  return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());\n}\n#endif\n\n#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&               \\\n    !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto map_error_impl(Exp &&exp, F &&f) {\n  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;\n  return exp.has_value()\n             ? result(*std::forward<Exp>(exp))\n             : result(unexpect, detail::invoke(std::forward<F>(f),\n                                               std::forward<Exp>(exp).error()));\n}\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto map_error_impl(Exp &&exp, F &&f) {\n  using result = expected<exp_t<Exp>, monostate>;\n  if (exp.has_value()) {\n    return result(*std::forward<Exp>(exp));\n  }\n\n  detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());\n  return result(unexpect, monostate{});\n}\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto map_error_impl(Exp &&exp, F &&f) {\n  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;\n  return exp.has_value()\n             ? result()\n             : result(unexpect, detail::invoke(std::forward<F>(f),\n                                               std::forward<Exp>(exp).error()));\n}\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto map_error_impl(Exp &&exp, F &&f) {\n  using result = expected<exp_t<Exp>, monostate>;\n  if (exp.has_value()) {\n    return result();\n  }\n\n  detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());\n  return result(unexpect, monostate{});\n}\n#else\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto map_error_impl(Exp &&exp, F &&f)\n    -> expected<exp_t<Exp>, detail::decay_t<Ret>> {\n  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;\n\n  return exp.has_value()\n             ? result(*std::forward<Exp>(exp))\n             : result(unexpect, detail::invoke(std::forward<F>(f),\n                                               std::forward<Exp>(exp).error()));\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {\n  using result = expected<exp_t<Exp>, monostate>;\n  if (exp.has_value()) {\n    return result(*std::forward<Exp>(exp));\n  }\n\n  detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());\n  return result(unexpect, monostate{});\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto map_error_impl(Exp &&exp, F &&f)\n    -> expected<exp_t<Exp>, detail::decay_t<Ret>> {\n  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;\n\n  return exp.has_value()\n             ? result()\n             : result(unexpect, detail::invoke(std::forward<F>(f),\n                                               std::forward<Exp>(exp).error()));\n}\n\ntemplate <class Exp, class F,\n          detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {\n  using result = expected<exp_t<Exp>, monostate>;\n  if (exp.has_value()) {\n    return result();\n  }\n\n  detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());\n  return result(unexpect, monostate{});\n}\n#endif\n\n#ifdef TL_EXPECTED_CXX14\ntemplate <class Exp, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto or_else_impl(Exp &&exp, F &&f) {\n  static_assert(detail::is_expected<Ret>::value, \"F must return an expected\");\n  return exp.has_value() ? std::forward<Exp>(exp)\n                         : detail::invoke(std::forward<F>(f),\n                                          std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\ndetail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {\n  return exp.has_value() ? std::forward<Exp>(exp)\n                         : (detail::invoke(std::forward<F>(f),\n                                           std::forward<Exp>(exp).error()),\n                            std::forward<Exp>(exp));\n}\n#else\ntemplate <class Exp, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nauto or_else_impl(Exp &&exp, F &&f) -> Ret {\n  static_assert(detail::is_expected<Ret>::value, \"F must return an expected\");\n  return exp.has_value() ? std::forward<Exp>(exp)\n                         : detail::invoke(std::forward<F>(f),\n                                          std::forward<Exp>(exp).error());\n}\n\ntemplate <class Exp, class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              std::declval<Exp>().error())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\ndetail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {\n  return exp.has_value() ? std::forward<Exp>(exp)\n                         : (detail::invoke(std::forward<F>(f),\n                                           std::forward<Exp>(exp).error()),\n                            std::forward<Exp>(exp));\n}\n#endif\n} // namespace detail\n\ntemplate <class T, class E, class U, class F>\nconstexpr bool operator==(const expected<T, E> &lhs,\n                          const expected<U, F> &rhs) {\n  return (lhs.has_value() != rhs.has_value())\n             ? false\n             : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);\n}\ntemplate <class T, class E, class U, class F>\nconstexpr bool operator!=(const expected<T, E> &lhs,\n                          const expected<U, F> &rhs) {\n  return (lhs.has_value() != rhs.has_value())\n             ? true\n             : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);\n}\ntemplate <class E, class F>\nconstexpr bool operator==(const expected<void, E> &lhs,\n                          const expected<void, F> &rhs) {\n  return (lhs.has_value() != rhs.has_value())\n             ? false\n             : (!lhs.has_value() ? lhs.error() == rhs.error() : true);\n}\ntemplate <class E, class F>\nconstexpr bool operator!=(const expected<void, E> &lhs,\n                          const expected<void, F> &rhs) {\n  return (lhs.has_value() != rhs.has_value())\n             ? true\n             : (!lhs.has_value() ? lhs.error() == rhs.error() : false);\n}\n\ntemplate <class T, class E, class U>\nconstexpr bool operator==(const expected<T, E> &x, const U &v) {\n  return x.has_value() ? *x == v : false;\n}\ntemplate <class T, class E, class U>\nconstexpr bool operator==(const U &v, const expected<T, E> &x) {\n  return x.has_value() ? *x == v : false;\n}\ntemplate <class T, class E, class U>\nconstexpr bool operator!=(const expected<T, E> &x, const U &v) {\n  return x.has_value() ? *x != v : true;\n}\ntemplate <class T, class E, class U>\nconstexpr bool operator!=(const U &v, const expected<T, E> &x) {\n  return x.has_value() ? *x != v : true;\n}\n\ntemplate <class T, class E>\nconstexpr bool operator==(const expected<T, E> &x, const unexpected<E> &e) {\n  return x.has_value() ? false : x.error() == e.value();\n}\ntemplate <class T, class E>\nconstexpr bool operator==(const unexpected<E> &e, const expected<T, E> &x) {\n  return x.has_value() ? false : x.error() == e.value();\n}\ntemplate <class T, class E>\nconstexpr bool operator!=(const expected<T, E> &x, const unexpected<E> &e) {\n  return x.has_value() ? true : x.error() != e.value();\n}\ntemplate <class T, class E>\nconstexpr bool operator!=(const unexpected<E> &e, const expected<T, E> &x) {\n  return x.has_value() ? true : x.error() != e.value();\n}\n\ntemplate <class T, class E,\n          detail::enable_if_t<(std::is_void<T>::value ||\n                               std::is_move_constructible<T>::value) &&\n                              detail::is_swappable<T>::value &&\n                              std::is_move_constructible<E>::value &&\n                              detail::is_swappable<E>::value> * = nullptr>\nvoid swap(expected<T, E> &lhs,\n          expected<T, E> &rhs) noexcept(noexcept(lhs.swap(rhs))) {\n  lhs.swap(rhs);\n}\n} // namespace tl\n\n#endif\n"
  },
  {
    "path": "3rdParty/tl/function_ref.hpp",
    "content": "///\r\n// function_ref - A low-overhead non-owning function\r\n// Written in 2017 by Simon Brand (@TartanLlama)\r\n//\r\n// To the extent possible under law, the author(s) have dedicated all\r\n// copyright and related and neighboring rights to this software to the\r\n// public domain worldwide. This software is distributed without any warranty.\r\n//\r\n// You should have received a copy of the CC0 Public Domain Dedication\r\n// along with this software. If not, see\r\n// <http://creativecommons.org/publicdomain/zero/1.0/>.\r\n///\r\n\r\n#ifndef TL_FUNCTION_REF_HPP\r\n#define TL_FUNCTION_REF_HPP\r\n\r\n#define TL_FUNCTION_REF_VERSION_MAJOR 1\r\n#define TL_FUNCTION_REF_VERSION_MINOR 0\r\n#define TL_FUNCTION_REF_VERSION_PATCH 0\r\n\r\n#if (defined(_MSC_VER) && _MSC_VER == 1900)\r\n/// \\exclude\r\n#define TL_FUNCTION_REF_MSVC2015\r\n#endif\r\n\r\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \\\r\n     !defined(__clang__))\r\n/// \\exclude\r\n#define TL_FUNCTION_REF_GCC49\r\n#endif\r\n\r\n#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 &&              \\\r\n     !defined(__clang__))\r\n/// \\exclude\r\n#define TL_FUNCTION_REF_GCC54\r\n#endif\r\n\r\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \\\r\n     !defined(__clang__))\r\n// GCC < 5 doesn't support overloading on const&& for member functions\r\n/// \\exclude\r\n#define TL_FUNCTION_REF_NO_CONSTRR\r\n#endif\r\n\r\n#if __cplusplus > 201103L\r\n/// \\exclude\r\n#define TL_FUNCTION_REF_CXX14\r\n#endif\r\n\r\n// constexpr implies const in C++11, not C++14\r\n#if (__cplusplus == 201103L || defined(TL_FUNCTION_REF_MSVC2015) ||            \\\r\n     defined(TL_FUNCTION_REF_GCC49)) &&                                        \\\r\n    !defined(TL_FUNCTION_REF_GCC54)\r\n/// \\exclude\r\n#define TL_FUNCTION_REF_11_CONSTEXPR\r\n#else\r\n/// \\exclude\r\n#define TL_FUNCTION_REF_11_CONSTEXPR constexpr\r\n#endif\r\n\r\n#include <functional>\r\n#include <utility>\r\n\r\nnamespace tl {\r\nnamespace detail {\r\nnamespace fnref {\r\n// C++14-style aliases for brevity\r\ntemplate <class T> using remove_const_t = typename std::remove_const<T>::type;\r\ntemplate <class T>\r\nusing remove_reference_t = typename std::remove_reference<T>::type;\r\ntemplate <class T> using decay_t = typename std::decay<T>::type;\r\ntemplate <bool E, class T = void>\r\nusing enable_if_t = typename std::enable_if<E, T>::type;\r\ntemplate <bool B, class T, class F>\r\nusing conditional_t = typename std::conditional<B, T, F>::type;\r\n\r\n// std::invoke from C++17\r\n// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround\r\ntemplate <typename Fn, typename... Args,\r\n          typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,\r\n          int = 0>\r\nconstexpr auto invoke(Fn &&f, Args &&... args) noexcept(\r\n    noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))\r\n    -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {\r\n  return std::mem_fn(f)(std::forward<Args>(args)...);\r\n}\r\n\r\ntemplate <typename Fn, typename... Args,\r\n          typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>{}>>\r\nconstexpr auto invoke(Fn &&f, Args &&... args) noexcept(\r\n    noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))\r\n    -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {\r\n  return std::forward<Fn>(f)(std::forward<Args>(args)...);\r\n}\r\n\r\n// std::invoke_result from C++17\r\ntemplate <class F, class, class... Us> struct invoke_result_impl;\r\n\r\ntemplate <class F, class... Us>\r\nstruct invoke_result_impl<\r\n    F, decltype(tl::detail::fnref::invoke(std::declval<F>(), std::declval<Us>()...), void()),\r\n    Us...> {\r\n  using type = decltype(tl::detail::fnref::invoke(std::declval<F>(), std::declval<Us>()...));\r\n};\r\n\r\ntemplate <class F, class... Us>\r\nusing invoke_result = invoke_result_impl<F, void, Us...>;\r\n\r\ntemplate <class F, class... Us>\r\nusing invoke_result_t = typename invoke_result<F, Us...>::type;\r\n\r\ntemplate <class, class R, class F, class... Args>\r\nstruct is_invocable_r_impl : std::false_type {};\r\n\r\ntemplate <class R, class F, class... Args>\r\nstruct is_invocable_r_impl<\r\n    typename std::is_convertible<invoke_result_t<F, Args...>, R>::type, R, F, Args...>\r\n    : std::true_type {};\r\n\r\ntemplate <class R, class F, class... Args>\r\nusing is_invocable_r = is_invocable_r_impl<std::true_type, R, F, Args...>;\r\n\r\n} // namespace detail\r\n} // namespace fnref\r\n\r\n/// A lightweight non-owning reference to a callable.\r\n///\r\n/// Example usage:\r\n///\r\n/// ```cpp\r\n/// void foo (function_ref<int(int)> func) {\r\n///     std::cout << \"Result is \" << func(21); //42\r\n/// }\r\n///\r\n/// foo([](int i) { return i*2; });\r\ntemplate <class F> class function_ref;\r\n\r\n/// Specialization for function types.\r\ntemplate <class R, class... Args> class function_ref<R(Args...)> {\r\npublic:\r\n  constexpr function_ref() noexcept = delete;\r\n\r\n  /// Creates a `function_ref` which refers to the same callable as `rhs`.\r\n    constexpr function_ref(const function_ref<R(Args...)> &rhs) noexcept = default;\r\n\r\n  /// Constructs a `function_ref` referring to `f`.\r\n  ///\r\n  /// \\synopsis template <typename F> constexpr function_ref(F &&f) noexcept\r\n  template <typename F,\r\n            detail::fnref::enable_if_t<\r\n                !std::is_same<detail::fnref::decay_t<F>, function_ref>::value &&\r\n                detail::fnref::is_invocable_r<R, F &&, Args...>::value> * = nullptr>\r\n  TL_FUNCTION_REF_11_CONSTEXPR function_ref(F &&f) noexcept\r\n      : obj_(const_cast<void*>(reinterpret_cast<const void *>(std::addressof(f)))) {\r\n    callback_ = [](void *obj, Args... args) -> R {\r\n      return detail::fnref::invoke(\r\n          *reinterpret_cast<typename std::add_pointer<F>::type>(obj),\r\n          std::forward<Args>(args)...);\r\n    };\r\n  }\r\n\r\n  /// Makes `*this` refer to the same callable as `rhs`.\r\n  TL_FUNCTION_REF_11_CONSTEXPR function_ref<R(Args...)> &\r\n  operator=(const function_ref<R(Args...)> &rhs) noexcept = default;\r\n\r\n  /// Makes `*this` refer to `f`.\r\n  ///\r\n  /// \\synopsis template <typename F> constexpr function_ref &operator=(F &&f) noexcept;\r\n  template <typename F,\r\n            detail::fnref::enable_if_t<detail::fnref::is_invocable_r<R, F &&, Args...>::value>\r\n                * = nullptr>\r\n  TL_FUNCTION_REF_11_CONSTEXPR function_ref<R(Args...)> &operator=(F &&f) noexcept {\r\n    obj_ = reinterpret_cast<void *>(std::addressof(f));\r\n    callback_ = [](void *obj, Args... args) {\r\n      return detail::fnref::invoke(\r\n          *reinterpret_cast<typename std::add_pointer<F>::type>(obj),\r\n          std::forward<Args>(args)...);\r\n    };\r\n\r\n    return *this;\r\n  }\r\n\r\n  /// Swaps the referred callables of `*this` and `rhs`.\r\n  constexpr void swap(function_ref<R(Args...)> &rhs) noexcept {\r\n    std::swap(obj_, rhs.obj_);\r\n    std::swap(callback_, rhs.callback_);\r\n  }\r\n\r\n  /// Call the stored callable with the given arguments.\r\n  R operator()(Args... args) const {\r\n    return callback_(obj_, std::forward<Args>(args)...);\r\n  }\r\n\r\nprivate:\r\n  void *obj_ = nullptr;\r\n  R (*callback_)(void *, Args...) = nullptr;\r\n};\r\n\r\n/// Swaps the referred callables of `lhs` and `rhs`.\r\ntemplate <typename R, typename... Args>\r\nconstexpr void swap(function_ref<R(Args...)> &lhs,\r\n                    function_ref<R(Args...)> &rhs) noexcept {\r\n  lhs.swap(rhs);\r\n}\r\n\r\n#if __cplusplus >= 201703L\r\ntemplate <typename R, typename... Args>\r\nfunction_ref(R (*)(Args...))->function_ref<R(Args...)>;\r\n\r\n// TODO, will require some kind of callable traits\r\n// template <typename F>\r\n// function_ref(F) -> function_ref</* deduced if possible */>;\r\n#endif\r\n} // namespace tl\r\n\r\n#endif\r\n"
  },
  {
    "path": "3rdParty/tolk/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\n# Workaround for deprecation of older CMake versions\r\nset(CMAKE_POLICY_VERSION_MINIMUM 3.22)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(Tolk\r\n    URL https://github.com/sig-a11y/tolk/archive/89de98779e3b6365dc1688538d5de4ecba3fdbab.tar.gz\r\n    URL_HASH MD5=724f6022186573dd9c5c2c92ed9e21e6\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(Tolk)\r\n\r\ntarget_include_directories(Tolk PUBLIC ${libTolk_SOURCE_DIR}/src)\r\n\r\nif(CMAKE_SIZEOF_VOID_P EQUAL 4)\r\n  set(TOLK_LIB_DIR \"${Tolk_SOURCE_DIR}/libs/x86\")\r\nelse()\r\n  set(TOLK_LIB_DIR \"${Tolk_SOURCE_DIR}/libs/x64\")\r\nendif()\r\nfile(GLOB TOLK_DLLS\r\n  LIST_DIRECTORIES false\r\n  \"${TOLK_LIB_DIR}/*.dll\"\r\n  \"${TOLK_LIB_DIR}/*.ini\")\r\nforeach(_TOLK_DLL_PATH ${TOLK_DLLS})\r\n  install(FILES \"${_TOLK_DLL_PATH}\"\r\n    DESTINATION \".\"\r\n  )\r\nendforeach()\r\n"
  },
  {
    "path": "3rdParty/unordered_dense/0001-Disable-PMR-support-for-mingw-std-threads-compat.patch",
    "content": "From 78eb7bc8a64099235daa3a8cb249a5ce35a4db07 Mon Sep 17 00:00:00 2001\nFrom: Gleb Mazovetskiy <glex.spb@gmail.com>\nDate: Sun, 4 Aug 2024 12:32:50 +0100\nSubject: [PATCH] Disable PMR support for mingw-std-threads compat\n\n---\n include/ankerl/unordered_dense.h | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/include/ankerl/unordered_dense.h b/include/ankerl/unordered_dense.h\nindex 2aaacd6..e6fee6e 100644\n--- a/include/ankerl/unordered_dense.h\n+++ b/include/ankerl/unordered_dense.h\n@@ -98,6 +98,8 @@\n #        include <cstdlib> // for abort\n #    endif\n \n+// DevilutionX disables PMR support because it does not play well with mingw-std-threads.\n+#if false\n #    if defined(__has_include)\n #        if __has_include(<memory_resource>)\n #            define ANKERL_UNORDERED_DENSE_PMR std::pmr // NOLINT(cppcoreguidelines-macro-usage)\n@@ -107,6 +109,7 @@\n #            include <experimental/memory_resource>                   // for polymorphic_allocator\n #        endif\n #    endif\n+#endif\n \n #    if defined(_MSC_VER) && defined(_M_X64)\n #        include <intrin.h>\n-- \n2.43.0\n\n"
  },
  {
    "path": "3rdParty/unordered_dense/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\ninclude(FetchContent)\r\n\r\nset(unordered_dense_URL \"https://github.com/martinus/unordered_dense/archive/refs/tags/v4.4.0.tar.gz\")\r\nset(unordered_dense_HASH \"f33c294a010540434b272754f937decf\")\r\n\r\nif(MINGW_CROSS)\r\n  find_package(Patch REQUIRED)\r\n  FetchContent_Declare_ExcludeFromAll(unordered_dense\r\n    URL ${unordered_dense_URL}\r\n    URL_HASH MD5=${unordered_dense_HASH}\r\n    PATCH_COMMAND \"${Patch_EXECUTABLE}\" -p1 -N < \"${CMAKE_CURRENT_LIST_DIR}/0001-Disable-PMR-support-for-mingw-std-threads-compat.patch\" || true\r\n  )\r\nelse()\r\n  FetchContent_Declare_ExcludeFromAll(unordered_dense\r\n    URL ${unordered_dense_URL}\r\n    URL_HASH MD5=${unordered_dense_HASH}\r\n  )\r\nendif()\r\nFetchContent_MakeAvailable_ExcludeFromAll(unordered_dense)\r\n"
  },
  {
    "path": "3rdParty/zlib/CMake/FindZLIB.cmake",
    "content": "# No-op, ZLIB::ZLIB is built from source.\r\n"
  },
  {
    "path": "3rdParty/zlib/CMakeLists.txt",
    "content": "include(functions/FetchContent_ExcludeFromAll_backport)\r\n\r\nset(CMAKE_POLICY_DEFAULT_CMP0048 NEW)\r\n\r\ninclude(FetchContent)\r\nFetchContent_Declare_ExcludeFromAll(zlib\r\n    URL https://www.zlib.net/zlib-1.3.tar.gz\r\n        https://www.zlib.net/fossils/zlib-1.3.tar.gz\r\n        https://github.com/madler/zlib/releases/download/v1.3/zlib-1.3.tar.gz\r\n    URL_HASH MD5=60373b133d630f74f4a1f94c1185a53f\r\n)\r\nFetchContent_MakeAvailable_ExcludeFromAll(zlib)\r\n\r\nif(DEVILUTIONX_STATIC_ZLIB)\r\n  add_library(ZLIB::ZLIB ALIAS zlibstatic)\r\n  target_include_directories(zlibstatic INTERFACE ${zlib_BINARY_DIR} ${zlib_SOURCE_DIR})\r\nelse()\r\n  add_library(ZLIB::ZLIB ALIAS zlib)\r\n  target_include_directories(zlib INTERFACE ${zlib_BINARY_DIR} ${zlib_SOURCE_DIR})\r\nendif()\r\n\r\n# 1. Set the variables that are usually set by FindZLIB.cmake.\r\n# 2. Add the module that stubs out `find_package(ZLIB ...)` calls.\r\nset(ZLIB_FOUND ON PARENT_SCOPE)\r\nset(ZLIB_LIBRARY ZLIB::ZLIB PARENT_SCOPE)\r\nset(ZLIB_LIBRARIES ZLIB::ZLIB PARENT_SCOPE)\r\nset(ZLIB_INCLUDE_DIR ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR} PARENT_SCOPE)\r\nset(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR} PARENT_SCOPE)\r\nset(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}/CMake\" PARENT_SCOPE)\r\n"
  },
  {
    "path": "Brewfile",
    "content": "brew \"cmake\"\r\nbrew \"fmt\"\r\nbrew \"sdl2\"\r\nbrew \"libsodium\"\r\nbrew \"pkg-config\"\r\nbrew \"googletest\"\r\nbrew \"google-benchmark\"\r\nbrew \"magic_enum\"\r\n"
  },
  {
    "path": "CMake/Assets.cmake",
    "content": "include(functions/copy_files)\r\ninclude(functions/trim_retired_files)\r\n\r\nif(NOT DEFINED DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY)\r\n  set(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/assets\")\r\nendif()\r\n\r\nset(devilutionx_langs be bg cs da de el es et fi fr hr hu it ja ko pl pt_BR ro ru uk sv tr zh_CN zh_TW)\r\nif(USE_GETTEXT_FROM_VCPKG)\r\n  # vcpkg doesn't add its own tools directory to the search path\r\n  list(APPEND Gettext_ROOT ${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/${VCPKG_TARGET_TRIPLET}/tools/gettext/bin)\r\nendif()\r\nfind_package(Gettext)\r\nif (Gettext_FOUND)\r\n  file(MAKE_DIRECTORY \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}\")\r\n  foreach(lang ${devilutionx_langs})\r\n    set(_po_file \"${CMAKE_CURRENT_SOURCE_DIR}/Translations/${lang}.po\")\r\n    set(_gmo_file \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/${lang}.gmo\")\r\n    set(_lang_target devilutionx_lang_${lang})\r\n    add_custom_command(\r\n      COMMAND \"${GETTEXT_MSGFMT_EXECUTABLE}\" -o \"${_gmo_file}\" \"${_po_file}\"\r\n      WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\"\r\n      OUTPUT \"${_gmo_file}\"\r\n      MAIN_DEPENDENCY \"${_po_file}\"\r\n      VERBATIM\r\n    )\r\n    add_custom_target(\"${_lang_target}\" DEPENDS \"${_gmo_file}\")\r\n    list(APPEND devilutionx_lang_targets \"${_lang_target}\")\r\n    list(APPEND devilutionx_lang_files \"${_gmo_file}\")\r\n\r\n    if(APPLE)\r\n      set_source_files_properties(\"${_gmo_file}\" PROPERTIES\r\n        MACOSX_PACKAGE_LOCATION Resources\r\n        XCODE_EXPLICIT_FILE_TYPE compiled)\r\n      add_dependencies(libdevilutionx \"${_lang_target}\")\r\n      add_dependencies(${BIN_TARGET} \"${_lang_target}\")\r\n      target_sources(${BIN_TARGET} PRIVATE \"${_gmo_file}\")\r\n    endif()\r\n\r\n    if(VITA)\r\n      list(APPEND VITA_TRANSLATIONS_LIST \"FILE\" \"${_gmo_file}\" \"assets/${lang}.gmo\")\r\n    endif()\r\n  endforeach()\r\nendif()\r\n\r\nset(devilutionx_assets\r\n  ASSETS_VERSION\r\n  arena/church.dun\r\n  arena/circle_of_death.dun\r\n  arena/hell.dun\r\n  data/boxleftend.clx\r\n  data/boxmiddle.clx\r\n  data/boxrightend.clx\r\n  data/charbg.clx\r\n  data/dirtybuc.clx\r\n  data/dirtybucp.clx\r\n  data/healthbox.clx\r\n  data/health.clx\r\n  data/hintbox.clx\r\n  data/hintboxbackground.clx\r\n  data/hinticons.clx\r\n  data/monstertags.clx\r\n  data/panel8buc.clx\r\n  data/panel8bucp.clx\r\n  data/resistance.clx\r\n  data/stash.clx\r\n  data/stashnavbtns.clx\r\n  data/talkbutton.clx\r\n  data/xpbar.clx\r\n  fonts/12-00.clx\r\n  fonts/12-01.clx\r\n  fonts/12-02.clx\r\n  fonts/12-03.clx\r\n  fonts/12-04.clx\r\n  fonts/12-05.clx\r\n  fonts/12-1f4.clx\r\n  fonts/12-1f6.clx\r\n  fonts/12-1f9.clx\r\n  fonts/12-20.clx\r\n  fonts/12-26.clx\r\n  fonts/12-e0.clx\r\n  fonts/22-00.clx\r\n  fonts/22-01.clx\r\n  fonts/22-02.clx\r\n  fonts/22-03.clx\r\n  fonts/22-04.clx\r\n  fonts/22-05.clx\r\n  fonts/22-20.clx\r\n  fonts/24-00.clx\r\n  fonts/24-01.clx\r\n  fonts/24-02.clx\r\n  fonts/24-03.clx\r\n  fonts/24-04.clx\r\n  fonts/24-05.clx\r\n  fonts/24-1f4.clx\r\n  fonts/24-1f6.clx\r\n  fonts/24-1f9.clx\r\n  fonts/24-20.clx\r\n  fonts/24-26.clx\r\n  fonts/24-e0.clx\r\n  fonts/30-00.clx\r\n  fonts/30-01.clx\r\n  fonts/30-02.clx\r\n  fonts/30-03.clx\r\n  fonts/30-04.clx\r\n  fonts/30-05.clx\r\n  fonts/30-20.clx\r\n  fonts/30-e0.clx\r\n  fonts/42-00.clx\r\n  fonts/42-01.clx\r\n  fonts/42-02.clx\r\n  fonts/42-03.clx\r\n  fonts/42-04.clx\r\n  fonts/42-05.clx\r\n  fonts/42-20.clx\r\n  fonts/46-00.clx\r\n  fonts/46-01.clx\r\n  fonts/46-02.clx\r\n  fonts/46-03.clx\r\n  fonts/46-04.clx\r\n  fonts/46-05.clx\r\n  fonts/46-20.clx\r\n  fonts/black.trn\r\n  fonts/blue.trn\r\n  fonts/buttonface.trn\r\n  fonts/buttonpushed.trn\r\n  fonts/gamedialogwhite.trn\r\n  fonts/gamedialogyellow.trn\r\n  fonts/gamedialogred.trn\r\n  fonts/golduis.trn\r\n  fonts/goldui.trn\r\n  fonts/grayuis.trn\r\n  fonts/grayui.trn\r\n  fonts/orange.trn\r\n  fonts/red.trn\r\n  fonts/tr/12-00.clx\r\n  fonts/tr/24-00.clx\r\n  fonts/tr/30-00.clx\r\n  fonts/tr/42-00.clx\r\n  fonts/tr/46-00.clx\r\n  fonts/whitegold.trn\r\n  fonts/white.trn\r\n  fonts/yellow.trn\r\n  gendata/cut2w.clx\r\n  gendata/cut3w.clx\r\n  gendata/cut4w.clx\r\n  gendata/cutgatew.clx\r\n  gendata/cutl1dw.clx\r\n  gendata/cutportlw.clx\r\n  gendata/cutportrw.clx\r\n  gendata/cutstartw.clx\r\n  gendata/cutttw.clx\r\n  gendata/pause.trn\r\n  levels/l1data/sklkngt.dun\r\n  levels/l2data/bonechat.dun\r\n  levels/towndata/automap.dun\r\n  levels/towndata/automap.amp\r\n  lua_internal/get_lua_function_signature.lua\r\n  lua/devilutionx/events.lua\r\n  lua/inspect.lua\r\n  lua/mods/adria_refills_mana/init.lua\r\n  lua/mods/clock/init.lua\r\n  \"lua/mods/Floating Numbers - Damage/init.lua\"\r\n  \"lua/mods/Floating Numbers - XP/init.lua\"\r\n  lua/repl_prelude.lua\r\n  plrgfx/warrior/whu/whufm.trn\r\n  plrgfx/warrior/whu/whulm.trn\r\n  plrgfx/warrior/whu/whuqm.trn\r\n  txtdata/Experience.tsv\r\n  txtdata/classes/barbarian/animations.tsv\r\n  txtdata/classes/barbarian/attributes.tsv\r\n  txtdata/classes/barbarian/sounds.tsv\r\n  txtdata/classes/barbarian/sprites.tsv\r\n  txtdata/classes/barbarian/starting_loadout.tsv\r\n  txtdata/classes/bard/animations.tsv\r\n  txtdata/classes/bard/attributes.tsv\r\n  txtdata/classes/bard/sounds.tsv\r\n  txtdata/classes/bard/sprites.tsv\r\n  txtdata/classes/bard/starting_loadout.tsv\r\n  txtdata/classes/monk/animations.tsv\r\n  txtdata/classes/monk/attributes.tsv\r\n  txtdata/classes/monk/sounds.tsv\r\n  txtdata/classes/monk/sprites.tsv\r\n  txtdata/classes/monk/starting_loadout.tsv\r\n  txtdata/classes/rogue/animations.tsv\r\n  txtdata/classes/rogue/attributes.tsv\r\n  txtdata/classes/rogue/sounds.tsv\r\n  txtdata/classes/rogue/sprites.tsv\r\n  txtdata/classes/rogue/starting_loadout.tsv\r\n  txtdata/classes/sorcerer/animations.tsv\r\n  txtdata/classes/sorcerer/attributes.tsv\r\n  txtdata/classes/sorcerer/sounds.tsv\r\n  txtdata/classes/sorcerer/sprites.tsv\r\n  txtdata/classes/sorcerer/starting_loadout.tsv\r\n  txtdata/classes/warrior/animations.tsv\r\n  txtdata/classes/warrior/attributes.tsv\r\n  txtdata/classes/warrior/sounds.tsv\r\n  txtdata/classes/warrior/sprites.tsv\r\n  txtdata/classes/warrior/starting_loadout.tsv\r\n  txtdata/classes/classdat.tsv\r\n  txtdata/items/item_prefixes.tsv\r\n  txtdata/items/item_suffixes.tsv\r\n  txtdata/items/itemdat.tsv\r\n  txtdata/items/unique_itemdat.tsv\r\n  txtdata/missiles/misdat.tsv\r\n  txtdata/missiles/missile_sprites.tsv\r\n  txtdata/monsters/monstdat.tsv\r\n  txtdata/monsters/unique_monstdat.tsv\r\n  txtdata/objects/objdat.tsv\r\n  txtdata/quests/questdat.tsv\r\n  txtdata/sound/effects.tsv\r\n  txtdata/spells/spelldat.tsv\r\n  txtdata/text/textdat.tsv\r\n  txtdata/towners/quest_dialog.tsv\r\n  txtdata/towners/towners.tsv\r\n  ui_art/diablo.pal\r\n  ui_art/creditsw.clx\r\n  ui_art/dvl_but_sml.clx\r\n  ui_art/dvl_lrpopup.clx\r\n  ui_art/mainmenuw.clx)\r\n\r\nif(NOT UNPACKED_MPQS)\r\n  list(APPEND devilutionx_assets\r\n    data/inv/objcurs-widths.txt)\r\nendif()\r\n\r\nif(NOT USE_SDL1 AND NOT VITA)\r\n  list(APPEND devilutionx_assets\r\n    ui_art/button.png\r\n    ui_art/directions2.png\r\n    ui_art/directions.png\r\n    ui_art/menu-levelup.png\r\n    ui_art/menu.png)\r\nendif()\r\n\r\nif(APPLE)\r\n  foreach(asset_file ${devilutionx_assets})\r\n    set(src \"${CMAKE_CURRENT_SOURCE_DIR}/assets/${asset_file}\")\r\n    get_filename_component(_asset_dir \"${asset_file}\" DIRECTORY)\r\n    set_source_files_properties(\"${src}\" PROPERTIES\r\n      MACOSX_PACKAGE_LOCATION \"Resources/${_asset_dir}\"\r\n      XCODE_EXPLICIT_FILE_TYPE compiled)\r\n    target_sources(${BIN_TARGET} PRIVATE \"${src}\")\r\n  endforeach()\r\nelse()\r\n  # Copy assets to the build assets subdirectory. This serves two purposes:\r\n  # - If smpq is installed, devilutionx.mpq is built from these files.\r\n  # - If smpq is not installed, the game will load the assets directly from this directory.\r\n  copy_files(\r\n    FILES ${devilutionx_assets}\r\n    SRC_PREFIX \"assets/\"\r\n    OUTPUT_DIR \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}\"\r\n    OUTPUT_VARIABLE DEVILUTIONX_OUTPUT_ASSETS_FILES)\r\n  set(DEVILUTIONX_MPQ_FILES ${devilutionx_assets})\r\n  if (Gettext_FOUND)\r\n    foreach(lang ${devilutionx_langs})\r\n      list(APPEND DEVILUTIONX_MPQ_FILES \"${lang}.gmo\")\r\n    endforeach()\r\n  endif()\r\n\r\n  add_trim_target(devilutionx_trim_assets\r\n    ROOT_FOLDER \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}\"\r\n    CURRENT_FILES ${DEVILUTIONX_MPQ_FILES})\r\n  if(devilutionx_lang_targets)\r\n    add_dependencies(devilutionx_trim_assets ${devilutionx_lang_targets})\r\n  endif()\r\n\r\n  if(BUILD_ASSETS_MPQ)\r\n    if(TARGET_PLATFORM STREQUAL \"dos\")\r\n      set(DEVILUTIONX_MPQ \"${CMAKE_CURRENT_BINARY_DIR}/devx.mpq\")\r\n    else()\r\n      set(DEVILUTIONX_MPQ \"${CMAKE_CURRENT_BINARY_DIR}/devilutionx.mpq\")\r\n    endif()\r\n    add_custom_command(\r\n      COMMENT \"Building devilutionx.mpq\"\r\n      OUTPUT \"${DEVILUTIONX_MPQ}\"\r\n      COMMAND ${CMAKE_COMMAND} -E remove -f \"${DEVILUTIONX_MPQ}\"\r\n      COMMAND ${SMPQ} -A -M 1 -C BZIP2 -c \"${DEVILUTIONX_MPQ}\" ${DEVILUTIONX_MPQ_FILES}\r\n      WORKING_DIRECTORY \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}\"\r\n      DEPENDS ${TRIM_COMMAND_BYPRODUCT} ${DEVILUTIONX_OUTPUT_ASSETS_FILES} ${devilutionx_lang_targets} ${devilutionx_lang_files}\r\n      VERBATIM)\r\n    add_custom_target(devilutionx_mpq DEPENDS \"${DEVILUTIONX_MPQ}\")\r\n    add_dependencies(devilutionx_mpq devilutionx_trim_assets)\r\n    add_dependencies(libdevilutionx devilutionx_mpq)\r\n  else()\r\n    add_custom_target(devilutionx_copied_assets DEPENDS ${DEVILUTIONX_OUTPUT_ASSETS_FILES} ${devilutionx_lang_targets})\r\n    add_dependencies(devilutionx_copied_assets devilutionx_trim_assets)\r\n    add_dependencies(libdevilutionx devilutionx_copied_assets)\r\n  endif()\r\nendif()\r\n\r\n"
  },
  {
    "path": "CMake/Definitions.cmake",
    "content": "# Defines without value\r\nforeach(\r\n  def_name\r\n  NOSOUND\r\n  NONET\r\n  NOEXIT\r\n  PREFILL_PLAYER_NAME\r\n  DISABLE_TCP\r\n  DISABLE_ZERO_TIER\r\n  DISABLE_STREAMING_MUSIC\r\n  DISABLE_STREAMING_SOUNDS\r\n  DISABLE_DEMOMODE\r\n  BUILD_TESTING\r\n  GPERF\r\n  GPERF_HEAP_MAIN\r\n  GPERF_HEAP_FIRST_GAME_ITERATION\r\n  PACKET_ENCRYPTION\r\n  DEVILUTIONX_RESAMPLER_SPEEX\r\n  DEVILUTIONX_RESAMPLER_SDL\r\n  DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n  SCREEN_READER_INTEGRATION\r\n  UNPACKED_MPQS\r\n  UNPACKED_SAVES\r\n  DEVILUTIONX_WINDOWS_NO_WCHAR\r\n)\r\n  if(${def_name})\r\n    list(APPEND DEVILUTIONX_DEFINITIONS ${def_name})\r\n  endif()\r\nendforeach(def_name)\r\n\r\n# Defines with value\r\nforeach(\r\n  def_name\r\n  DEFAULT_WIDTH\r\n  DEFAULT_HEIGHT\r\n  DEFAULT_AUDIO_SAMPLE_RATE\r\n  DEFAULT_AUDIO_CHANNELS\r\n  DEFAULT_AUDIO_BUFFER_SIZE\r\n  DEFAULT_AUDIO_RESAMPLING_QUALITY\r\n  DEFAULT_PER_PIXEL_LIGHTING\r\n  SDL1_VIDEO_MODE_BPP\r\n  SDL1_VIDEO_MODE_FLAGS\r\n  SDL1_VIDEO_MODE_SVID_FLAGS\r\n  SDL1_FORCE_SVID_VIDEO_MODE\r\n  SDL1_FORCE_DIRECT_RENDER\r\n  DEVILUTIONX_GAMEPAD_TYPE\r\n  HAS_KBCTRL\r\n  KBCTRL_BUTTON_DPAD_LEFT\r\n  KBCTRL_BUTTON_DPAD_RIGHT\r\n  KBCTRL_BUTTON_DPAD_UP\r\n  KBCTRL_BUTTON_DPAD_DOWN\r\n  KBCTRL_BUTTON_B\r\n  KBCTRL_BUTTON_A\r\n  KBCTRL_BUTTON_Y\r\n  KBCTRL_BUTTON_X\r\n  KBCTRL_BUTTON_LEFTSTICK\r\n  KBCTRL_BUTTON_RIGHTSTICK\r\n  KBCTRL_BUTTON_RIGHTSHOULDER\r\n  KBCTRL_BUTTON_LEFTSHOULDER\r\n  KBCTRL_BUTTON_TRIGGERLEFT\r\n  KBCTRL_BUTTON_TRIGGERRIGHT\r\n  KBCTRL_BUTTON_START\r\n  KBCTRL_BUTTON_BACK\r\n  KBCTRL_IGNORE_1\r\n  JOY_AXIS_LEFTX\r\n  JOY_AXIS_LEFTY\r\n  JOY_AXIS_RIGHTX\r\n  JOY_AXIS_RIGHTY\r\n  JOY_HAT_DPAD_UP_HAT\r\n  JOY_HAT_DPAD_UP\r\n  JOY_HAT_DPAD_DOWN_HAT\r\n  JOY_HAT_DPAD_DOWN\r\n  JOY_HAT_DPAD_LEFT_HAT\r\n  JOY_HAT_DPAD_LEFT\r\n  JOY_HAT_DPAD_RIGHT_HAT\r\n  JOY_HAT_DPAD_RIGHT\r\n  JOY_BUTTON_DPAD_LEFT\r\n  JOY_BUTTON_DPAD_RIGHT\r\n  JOY_BUTTON_DPAD_UP\r\n  JOY_BUTTON_DPAD_DOWN\r\n  JOY_BUTTON_B\r\n  JOY_BUTTON_A\r\n  JOY_BUTTON_Y\r\n  JOY_BUTTON_X\r\n  JOY_BUTTON_LEFTSTICK\r\n  JOY_BUTTON_RIGHTSTICK\r\n  JOY_BUTTON_RIGHTSHOULDER\r\n  JOY_BUTTON_LEFTSHOULDER\r\n  JOY_BUTTON_TRIGGERLEFT\r\n  JOY_BUTTON_TRIGGERRIGHT\r\n  JOY_BUTTON_START\r\n  JOY_BUTTON_BACK\r\n  REMAP_KEYBOARD_KEYS\r\n  DEVILUTIONX_DEFAULT_RESAMPLER\r\n  STREAM_ALL_AUDIO_MIN_FILE_SIZE\r\n  DEVILUTIONX_DISPLAY_PIXELFORMAT # SDL2-only\r\n  DEVILUTIONX_DISPLAY_TEXTURE_FORMAT # SDL2-only\r\n  DEVILUTIONX_SCREENSHOT_FORMAT\r\n  DARWIN_MAJOR_VERSION\r\n  DARWIN_MINOR_VERSION\r\n)\r\n  if(DEFINED ${def_name} AND NOT ${def_name} STREQUAL \"\")\r\n    list(APPEND DEVILUTIONX_DEFINITIONS ${def_name}=${${def_name}})\r\n  endif()\r\nendforeach(def_name)\r\n"
  },
  {
    "path": "CMake/Dependencies.cmake",
    "content": "# Options that control whether to use system dependencies or build them from source,\r\n# and whether to link them statically.\r\ninclude(functions/dependency_options)\r\ninclude(functions/emscripten_system_library)\r\n\r\nif(EMSCRIPTEN)\r\n  emscripten_system_library(\"zlib\" ZLIB::ZLIB USE_ZLIB=1)\r\nelse()\r\n  dependency_options(\"zlib\" DEVILUTIONX_SYSTEM_ZLIB ON DEVILUTIONX_STATIC_ZLIB)\r\n  if(NOT DEVILUTIONX_SYSTEM_ZLIB)\r\n    add_subdirectory(3rdParty/zlib)\r\n  endif()\r\nendif()\r\n\r\nif(SUPPORTS_MPQ)\r\n  # bzip2 is a libmpq dependency.\r\n  if(EMSCRIPTEN)\r\n    emscripten_system_library(\"bzip2\" BZip2::BZip2 USE_BZIP2=1)\r\n  else()\r\n    dependency_options(\"bzip2\" DEVILUTIONX_SYSTEM_BZIP2 ON DEVILUTIONX_STATIC_BZIP2)\r\n    if(NOT DEVILUTIONX_SYSTEM_BZIP2)\r\n      add_subdirectory(3rdParty/bzip2)\r\n    endif()\r\n  endif()\r\nendif()\r\n\r\nfind_package(Lua 5.4 QUIET)\r\nif(LUA_FOUND)\r\n  message(\"-- Found Lua ${LUA_VERSION_STRING}\")\r\nelse()\r\n  if(NOT DEFINED DEVILUTIONX_SYSTEM_LUA)\r\n    message(\"-- Suitable system Lua package not found, will use Lua from source\")\r\n    set(DEVILUTIONX_SYSTEM_LUA OFF)\r\n  endif()\r\nendif()\r\ndependency_options(\"lua\" DEVILUTIONX_SYSTEM_LUA ON DEVILUTIONX_STATIC_LUA)\r\nif(NOT DEVILUTIONX_SYSTEM_LUA)\r\n  add_subdirectory(3rdParty/Lua)\r\n  if(DEVILUTIONX_STATIC_LUA)\r\n    set(LUA_LIBRARIES lua_static)\r\n  else()\r\n    set(LUA_LIBRARIES lua_shared)\r\n  endif()\r\nelse()\r\n  find_package(Lua 5.4 REQUIRED)\r\n  include_directories(${LUA_INCLUDE_DIR})\r\nendif()\r\n\r\nadd_subdirectory(3rdParty/sol2)\r\n\r\nif(SCREEN_READER_INTEGRATION)\r\n  if(WIN32)\r\n    add_subdirectory(3rdParty/tolk)\r\n  else()\r\n    find_package(Speechd REQUIRED)\r\n  endif()\r\nendif()\r\n\r\nif(EMSCRIPTEN)\r\n  # We use `USE_PTHREADS=1` here to get a version of SDL2 that supports threads.\r\n  emscripten_system_library(\"SDL2\" SDL2::SDL2 USE_SDL=2 USE_PTHREADS=1)\r\n  list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/SDL2/CMake\")\r\nelseif(USE_SDL1)\r\n  find_package(SDL 1.2.10 REQUIRED)\r\n  include_directories(${SDL_INCLUDE_DIR})\r\nelseif(USE_SDL3)\r\n  dependency_options(\"SDL3\" DEVILUTIONX_SYSTEM_SDL3 ON DEVILUTIONX_STATIC_SDL3)\r\n  if(DEVILUTIONX_SYSTEM_SDL3)\r\n    find_package(SDL3 3.4.0 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)\r\n  else()\r\n    add_subdirectory(3rdParty/SDL3)\r\n  endif()\r\nelse()\r\n  dependency_options(\"SDL2\" DEVILUTIONX_SYSTEM_SDL2 ON DEVILUTIONX_STATIC_SDL2)\r\n  if(DEVILUTIONX_SYSTEM_SDL2)\r\n    find_package(SDL2 REQUIRED)\r\n    if(TARGET SDL2::SDL2)\r\n      if(TARGET SDL2::SDL2main)\r\n        set(SDL2_MAIN SDL2::SDL2main)\r\n      endif()\r\n    elseif(TARGET SDL2::SDL2-static)\r\n      # On some distros, such as vitasdk, only the SDL2::SDL2-static target is available.\r\n      # Alias to SDL2::SDL2 because some finder scripts may refer to SDL2::SDL2.\r\n      add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static)\r\n      if(TARGET SDL2::SDL2main)\r\n        set(SDL2_MAIN SDL2::SDL2main)\r\n      endif()\r\n    else()\r\n      # Assume an older Debian derivate that comes with an sdl2-config.cmake\r\n      # that only defines `SDL2_LIBRARIES` (as -lSDL2) and `SDL2_INCLUDE_DIRS`.\r\n      add_library(SDL2_lib INTERFACE)\r\n      target_link_libraries(SDL2_lib INTERFACE ${SDL2_LIBRARIES})\r\n      target_include_directories(SDL2_lib INTERFACE ${SDL2_INCLUDE_DIRS})\r\n      # Can't define an INTERFACE target with ::, so alias instead\r\n      add_library(SDL2::SDL2 ALIAS SDL2_lib)\r\n    endif()\r\n  elseif(UWP_LIB)\r\n    list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/SDL2/CMake\")\r\n    find_package(SDL2 REQUIRED)\r\n  else()\r\n    add_subdirectory(3rdParty/SDL2)\r\n    if(TARGET SDL2::SDL2main)\r\n      set(SDL2_MAIN SDL2::SDL2main)\r\n    endif()\r\n    list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/SDL2/CMake\")\r\n  endif()\r\nendif()\r\n\r\nadd_library(DevilutionX::SDL INTERFACE IMPORTED GLOBAL)\r\nif(USE_SDL1)\r\n  target_link_libraries(DevilutionX::SDL INTERFACE ${SDL_LIBRARY})\r\n  target_compile_definitions(DevilutionX::SDL INTERFACE USE_SDL1)\r\nelseif(USE_SDL3)\r\n  target_link_libraries(DevilutionX::SDL INTERFACE SDL3::SDL3)\r\n  target_compile_definitions(DevilutionX::SDL INTERFACE USE_SDL3)\r\nelse()\r\n  if(TARGET SDL2::SDL2 AND NOT (DEVILUTIONX_STATIC_SDL2 AND TARGET SDL2::SDL2-static))\r\n    target_link_libraries(DevilutionX::SDL INTERFACE SDL2::SDL2)\r\n  elseif(TARGET SDL2::SDL2-static)\r\n    target_link_libraries(DevilutionX::SDL INTERFACE SDL2::SDL2-static)\r\n  endif()\r\n  if(NOT UWP_LIB)\r\n    target_link_libraries(DevilutionX::SDL INTERFACE ${SDL2_MAIN})\r\n  endif()\r\nendif()\r\n\r\nmacro(_find_SDL_image QUIET_OR_REQUIRED)\r\n  # vcpkg uses sdl2-image as the package name\r\n  find_package(sdl2-image QUIET)\r\n  set(SDL_image_FOUND ${sdl2-image_FOUND})\r\n\r\n  if(NOT SDL_image_FOUND)\r\n    # Fall back on PkgConfig via FindSDL2_image.cmake\r\n    find_package(SDL2_image ${QUIET_OR_REQUIRED})\r\n    set(SDL_image_FOUND ${SDL2_image_FOUND})\r\n  endif()\r\nendmacro()\r\n\r\nif(USE_SDL1)\r\n  # No need for SDL_image.\r\nelseif(USE_SDL3)\r\n  if(NOT DEFINED DEVILUTIONX_SYSTEM_SDL_IMAGE)\r\n    find_package(SDL3_image QUIET CONFIG)\r\n    if(SDL3_image_FOUND)\r\n      message(\"-- Found SDL3_image\")\r\n    else()\r\n      message(\"-- Suitable system SDL3_image package not found, will use SDL3_image from source\")\r\n      set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\n    endif()\r\n  endif()\r\n  dependency_options(\"SDL3_image\" DEVILUTIONX_SYSTEM_SDL_IMAGE ON DEVILUTIONX_STATIC_SDL_IMAGE)\r\n  if(DEVILUTIONX_SYSTEM_SDL_IMAGE)\r\n    find_package(SDL3_image REQUIRED CONFIG)\r\n  else()\r\n    # Must be the same, see:\r\n    # https://github.com/libsdl-org/SDL_image/blob/11154afb7855293159588b245b446a4ef09e574f/CMakeLists.txt#L225-L233\r\n    set(DEVILUTIONX_STATIC_SDL_IMAGE ${DEVILUTIONX_STATIC_SDL3})\r\n    add_subdirectory(3rdParty/SDL3_image)\r\n  endif()\r\nelse()\r\n  if(EMSCRIPTEN)\r\n    emscripten_system_library(\"SDL_image\" SDL2::SDL2_image USE_SDL_IMAGE=2 \"SDL2_IMAGE_FORMATS='[\\\"png\\\"]'\")\r\n  else()\r\n    if(NOT DEFINED DEVILUTIONX_SYSTEM_SDL_IMAGE)\r\n      _find_SDL_image(QUIET)\r\n      if(SDL_image_FOUND)\r\n        message(\"-- Found SDL_image\")\r\n      else()\r\n        message(\"-- Suitable system SDL_image package not found, will use SDL_image from source\")\r\n        set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\n      endif()\r\n    endif()\r\n    dependency_options(\"SDL_image\" DEVILUTIONX_SYSTEM_SDL_IMAGE ON DEVILUTIONX_STATIC_SDL_IMAGE)\r\n    if(DEVILUTIONX_SYSTEM_SDL_IMAGE)\r\n      _find_SDL_image(REQUIRED)\r\n    else()\r\n      add_subdirectory(3rdParty/SDL_image)\r\n    endif()\r\n  endif()\r\nendif()\r\n\r\nif(NOT DEFINED DEVILUTIONX_SYSTEM_LIBFMT)\r\n  find_package(fmt 8.0.0 QUIET)\r\n  if(fmt_FOUND)\r\n    message(\"-- Found fmt ${fmt_VERSION}\")\r\n  else()\r\n    message(\"-- Suitable system fmt package not found, will use fmt from source\")\r\n    set(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\n  endif()\r\nendif()\r\ndependency_options(\"libfmt\" DEVILUTIONX_SYSTEM_LIBFMT ON DEVILUTIONX_STATIC_LIBFMT)\r\nif(DEVILUTIONX_SYSTEM_LIBFMT)\r\n  find_package(fmt 8.0.0 REQUIRED)\r\nelse()\r\n  add_subdirectory(3rdParty/libfmt)\r\nendif()\r\n\r\nif(NOT NOSOUND)\r\n  if(USE_SDL3)\r\n    if(NOT DEFINED DEVILUTIONX_SYSTEM_SDL_MIXER)\r\n      find_package(SDL3_mixer QUIET CONFIG)\r\n      if(SDL3_mixer_FOUND)\r\n        message(\"-- Found SDL3_mixer\")\r\n      else()\r\n        message(\"-- Suitable system SDL3_mixer package not found, will use SDL3_mixer from source\")\r\n        set(DEVILUTIONX_SYSTEM_SDL_MIXER OFF)\r\n      endif()\r\n    endif()\r\n    dependency_options(\"SDL3_mixer\" DEVILUTIONX_SYSTEM_SDL_MIXER ON DEVILUTIONX_STATIC_SDL_MIXER)\r\n    if(DEVILUTIONX_SYSTEM_SDL_MIXER)\r\n      find_package(SDL3_mixer REQUIRED CONFIG)\r\n    else()\r\n      add_subdirectory(3rdParty/SDL3_mixer)\r\n    endif()\r\n  else()\r\n    if(NOT DEFINED DEVILUTIONX_SYSTEM_SDL_AUDIOLIB)\r\n      find_package(SDL_audiolib QUIET)\r\n      if(SDL_audiolib_FOUND)\r\n        message(\"-- Found SDL_audiolib\")\r\n      else()\r\n        message(\"-- Suitable system SDL_audiolib package not found, will use SDL_audiolib from source\")\r\n        set(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF)\r\n      endif()\r\n    endif()\r\n    dependency_options(\"SDL_audiolib\" DEVILUTIONX_SYSTEM_SDL_AUDIOLIB ON DEVILUTIONX_STATIC_SDL_AUDIOLIB)\r\n    if(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB)\r\n      find_package(SDL_audiolib REQUIRED)\r\n    else()\r\n      add_subdirectory(3rdParty/SDL_audiolib)\r\n    endif()\r\n  endif()\r\nendif()\r\n\r\nif(PACKET_ENCRYPTION)\r\n  dependency_options(\"libsodium\" DEVILUTIONX_SYSTEM_LIBSODIUM ON DEVILUTIONX_STATIC_LIBSODIUM)\r\n  if(DEVILUTIONX_SYSTEM_LIBSODIUM)\r\n    set(sodium_USE_STATIC_LIBS ${DEVILUTIONX_STATIC_LIBSODIUM})\r\n    find_package(sodium REQUIRED)\r\n  else()\r\n    add_subdirectory(3rdParty/libsodium)\r\n  endif()\r\nendif()\r\n\r\nadd_subdirectory(3rdParty/libsmackerdec)\r\n\r\nif(WIN32 AND NOT UWP_LIB)\r\n  add_subdirectory(3rdParty/find_steam_game)\r\nendif()\r\n\r\nif(SUPPORTS_MPQ)\r\n  add_subdirectory(3rdParty/libmpq)\r\nendif()\r\n\r\nadd_subdirectory(3rdParty/tl)\r\n\r\nif(NOT DEFINED DEVILUTIONX_SYSTEM_SHEENBIDI)\r\n  find_package(SheenBidi 2.9.0 QUIET)\r\n  if(SheenBidi_FOUND)\r\n    message(\"-- Found SheenBidi ${SheenBidi_VERSION}\")\r\n  else()\r\n    message(\"-- Suitable system SheenBidi package not found, will use SheenBidi from source\")\r\n    set(DEVILUTIONX_SYSTEM_SHEENBIDI OFF)\r\n  endif()\r\nendif()\r\ndependency_options(\"SheenBidi\" DEVILUTIONX_SYSTEM_SHEENBIDI ON DEVILUTIONX_STATIC_SHEENBIDI)\r\nif(DEVILUTIONX_SYSTEM_SHEENBIDI)\r\n  find_package(SheenBidi REQUIRED)\r\nelse()\r\n  add_subdirectory(3rdParty/SheenBidi)\r\nendif()\r\n\r\nif(NOT DEFINED DEVILUTIONX_SYSTEM_UNORDERED_DENSE)\r\n  find_package(unordered_dense CONFIG QUIET)\r\n  if (unordered_dense_FOUND)\r\n    message(\"-- Found unordered_dense\")\r\n  else()\r\n    message(\"-- Suitable unordered_dense package not found, will use unordered_dense from source\")\r\n    set(DEVILUTIONX_SYSTEM_UNORDERED_DENSE OFF)\r\n  endif()\r\n  dependency_options(\"unordered_dense\" DEVILUTIONX_SYSTEM_UNORDERED_DENSE ON DEVILUTIONX_STATIC_UNORDERED_DENSE)\r\nendif()\r\nif(DEVILUTIONX_SYSTEM_UNORDERED_DENSE)\r\n  find_package(unordered_dense CONFIG REQUIRED)\r\nelse()\r\n  add_subdirectory(3rdParty/unordered_dense)\r\nendif()\r\n\r\nif(NOT DEFINED DEVILUTIONX_SYSTEM_MAGIC_ENUM)\r\n  find_package(magic_enum 0.9.7 QUIET)\r\n  if(magic_enum_FOUND)\r\n    message(\"-- Found magic_enum ${magic_enum_VERSION}\")\r\n  else()\r\n    message(\"-- Suitable system magic_enum package not found, will use magic_enum from source\")\r\n    set(DEVILUTIONX_SYSTEM_MAGIC_ENUM OFF)\r\n  endif()\r\nendif()\r\ndependency_options(\"magic_enum\" DEVILUTIONX_SYSTEM_MAGIC_ENUM ON DEVILUTIONX_STATIC_MAGIC_ENUM)\r\nif(DEVILUTIONX_SYSTEM_MAGIC_ENUM)\r\n  find_package(magic_enum REQUIRED)\r\nelse()\r\n  add_subdirectory(3rdParty/magic_enum)\r\nendif()\r\n\r\nif(SUPPORTS_MPQ OR NOT NONET)\r\n  add_subdirectory(3rdParty/PKWare)\r\nendif()\r\n\r\nif(NOT NONET AND NOT DISABLE_TCP)\r\n  add_subdirectory(3rdParty/asio)\r\nendif()\r\n\r\nif(NOT NONET AND NOT DISABLE_ZERO_TIER)\r\n  add_subdirectory(3rdParty/libzt)\r\nendif()\r\n\r\nif(DISCORD_INTEGRATION)\r\n  add_subdirectory(3rdParty/discord)\r\nendif()\r\n\r\nif(BUILD_TESTING)\r\n  dependency_options(\"googletest\" DEVILUTIONX_SYSTEM_GOOGLETEST ON DEVILUTIONX_STATIC_GOOGLETEST)\r\n  if(DEVILUTIONX_SYSTEM_GOOGLETEST)\r\n    find_package(GTest REQUIRED)\r\n    if(NOT TARGET GTest::gtest)\r\n      add_library(GTest::gtest ALIAS GTest::GTest)\r\n    endif()\r\n  else()\r\n    add_subdirectory(3rdParty/googletest)\r\n  endif()\r\n\r\n  dependency_options(\"benchmark\" DEVILUTIONX_SYSTEM_BENCHMARK ON DEVILUTIONX_STATIC_BENCHMARK)\r\n  if(DEVILUTIONX_SYSTEM_BENCHMARK)\r\n    find_package(benchmark REQUIRED)\r\n  else()\r\n    add_subdirectory(3rdParty/benchmark)\r\n  endif()\r\nendif()\r\n\r\nif(GPERF)\r\n  find_package(Gperftools REQUIRED)\r\n  message(\"INFO: ${GPERFTOOLS_LIBRARIES}\")\r\nendif()\r\n"
  },
  {
    "path": "CMake/Mods.cmake",
    "content": "include(functions/copy_files)\r\ninclude(functions/trim_retired_files)\r\n\r\nif(NOT DEFINED DEVILUTIONX_MODS_OUTPUT_DIRECTORY)\r\n  set(DEVILUTIONX_MODS_OUTPUT_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/mods\")\r\nendif()\r\n\r\nset(hellfire_mod\r\n  lua/mods/Hellfire/init.lua\r\n  nlevels/cutl5w.clx\r\n  nlevels/cutl6w.clx\r\n  nlevels/l5data/cornerstone.dun\r\n  nlevels/l5data/uberroom.dun\r\n  txtdata/classes/sorcerer/starting_loadout.tsv\r\n  txtdata/classes/classdat.tsv\r\n  txtdata/items/item_prefixes.tsv\r\n  txtdata/items/item_suffixes.tsv\r\n  txtdata/items/unique_itemdat.tsv\r\n  txtdata/missiles/misdat.tsv\r\n  txtdata/missiles/missile_sprites.tsv\r\n  txtdata/monsters/monstdat.tsv\r\n  txtdata/sound/effects.tsv\r\n  txtdata/spells/spelldat.tsv\r\n  txtdata/towners/quest_dialog.tsv\r\n  txtdata/towners/towners.tsv\r\n  ui_art/diablo.pal\r\n  ui_art/hf_titlew.clx\r\n  ui_art/supportw.clx\r\n  ui_art/mainmenuw.clx)\r\n\r\nif(NOT UNPACKED_MPQS)\r\n  list(APPEND hellfire_mod\r\n    data/inv/objcurs2-widths.txt)\r\nendif()\r\n\r\nif(APPLE)\r\n  foreach(asset_file ${hellfire_mod})\r\n    set(src \"${CMAKE_CURRENT_SOURCE_DIR}/mods/Hellfire/${asset_file}\")\r\n    get_filename_component(_asset_dir \"${asset_file}\" DIRECTORY)\r\n    set_source_files_properties(\"${src}\" PROPERTIES\r\n      MACOSX_PACKAGE_LOCATION \"Resources/mods/Hellfire/${_asset_dir}\"\r\n      XCODE_EXPLICIT_FILE_TYPE compiled)\r\n    target_sources(${BIN_TARGET} PRIVATE \"${src}\")\r\n  endforeach()\r\nelse()\r\n  copy_files(\r\n    FILES ${hellfire_mod}\r\n    SRC_PREFIX \"mods/Hellfire/\"\r\n    OUTPUT_DIR \"${DEVILUTIONX_MODS_OUTPUT_DIRECTORY}/Hellfire\"\r\n    OUTPUT_VARIABLE HELLFIRE_OUTPUT_FILES)\r\n  set(HELLFIRE_MPQ_FILES ${hellfire_mod})\r\n  add_trim_target(hellfire_trim_assets\r\n    ROOT_FOLDER \"${DEVILUTIONX_MODS_OUTPUT_DIRECTORY}/Hellfire\"\r\n    CURRENT_FILES ${HELLFIRE_MPQ_FILES})\r\n\r\n  if(BUILD_ASSETS_MPQ)\r\n    set(HELLFIRE_MPQ \"${DEVILUTIONX_MODS_OUTPUT_DIRECTORY}/Hellfire.mpq\")\r\n    add_custom_command(\r\n      COMMENT \"Building Hellfire.mpq\"\r\n      OUTPUT \"${HELLFIRE_MPQ}\"\r\n      COMMAND ${CMAKE_COMMAND} -E remove -f \"${HELLFIRE_MPQ}\"\r\n      COMMAND ${SMPQ} -A -M 1 -C BZIP2 -c \"${HELLFIRE_MPQ}\" ${HELLFIRE_MPQ_FILES}\r\n      WORKING_DIRECTORY \"${DEVILUTIONX_MODS_OUTPUT_DIRECTORY}/Hellfire\"\r\n      DEPENDS ${TRIM_COMMAND_BYPRODUCT} ${HELLFIRE_OUTPUT_FILES}\r\n      VERBATIM)\r\n    add_custom_target(hellfire_mpq DEPENDS \"${HELLFIRE_MPQ}\")\r\n    add_dependencies(hellfire_mpq hellfire_trim_assets)\r\n    add_dependencies(libdevilutionx hellfire_mpq)\r\n  else()\r\n    add_custom_target(hellfire_copied_assets DEPENDS ${HELLFIRE_OUTPUT_FILES})\r\n    add_dependencies(hellfire_copied_assets hellfire_trim_assets)\r\n    add_dependencies(libdevilutionx hellfire_copied_assets)\r\n  endif()\r\nendif()\r\n"
  },
  {
    "path": "CMake/MoldLinker.cmake",
    "content": "if(NOT CMAKE_CROSSCOMPILING)\r\n  find_program(\r\n    LD_MOLD_PATH\r\n    ld\r\n    PATHS\r\n    ${CMAKE_INSTALL_PREFIX}/libexec/mold\r\n    ENV LD_MOLD_PATH\r\n    NO_DEFAULT_PATH\r\n  )\r\n  if(NOT LD_MOLD_PATH STREQUAL \"LD_MOLD_PATH-NOTFOUND\")\r\n    set(_have_ld_mold ON)\r\n  else()\r\n    set(_have_ld_mold OFF)\r\n  endif()\r\nendif()\r\n\r\noption(USE_LD_MOLD \"Use mold linker\" ${_have_ld_mold})\r\n\r\nif(USE_LD_MOLD)\r\n  message(\"-- Using Mold linker (pass -DUSE_LD_MOLD=OFF to disable)\")\r\n  if(CMAKE_CXX_COMPILER_ID MATCHES \"GNU\" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)\r\n    if (_have_ld_mold)\r\n      get_filename_component(_mold_dir ${LD_MOLD_PATH} DIRECTORY)\r\n      set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -B${_mold_dir}\")\r\n      set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -B${_mold_dir}\")\r\n    else()\r\n      message(WARNING \"Cannot use mold linker: mold ld directory not found\")\r\n    endif()\r\n  elseif(CMAKE_CXX_COMPILER_ID MATCHES \"Clang|GNU\")\r\n    set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=mold\")\r\n    set(CMAKE_SHARED_LINKER_FLAGS \"${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=mold\")\r\n  endif()\r\nendif()\r\n"
  },
  {
    "path": "CMake/Platforms.cmake",
    "content": "if(HAIKU)\r\n  include(platforms/haiku)\r\nendif()\r\n\r\nif(CMAKE_SYSTEM_NAME MATCHES \"FreeBSD|OpenBSD|DragonFly|NetBSD\")\r\n  if(CMAKE_SYSTEM_NAME MATCHES \"NetBSD\")\r\n    add_definitions(-D_NETBSD_SOURCE)\r\n  else()\r\n    add_definitions(-D_BSD_SOURCE)\r\n    set(UBSAN OFF)\r\n  endif()\r\n  set(ASAN OFF)\r\n  add_definitions(-DO_LARGEFILE=0 -Dstat64=stat -Dlstat64=lstat -Dlseek64=lseek -Doff64_t=off_t -Dfstat64=fstat -Dftruncate64=ftruncate)\r\nendif()\r\n\r\nset(TARGET_PLATFORM host CACHE STRING \"Target platform\")\r\nset_property(CACHE TARGET_PLATFORM PROPERTY STRINGS host retrofw rg99 rg350 gkd350h cpigamesh miyoo_mini windows9x windowsXP)\r\nif(TARGET_PLATFORM STREQUAL \"retrofw\")\r\n  include(platforms/retrofw)\r\nelseif(TARGET_PLATFORM STREQUAL \"rg99\")\r\n  include(platforms/rg99)\r\nelseif(TARGET_PLATFORM STREQUAL \"rg350\")\r\n  include(platforms/rg350)\r\nelseif(TARGET_PLATFORM STREQUAL \"gkd350h\")\r\n  include(platforms/gkd350h)\r\nelseif(TARGET_PLATFORM STREQUAL \"cpigamesh\")\r\n  include(platforms/cpigamesh)\r\nelseif(TARGET_PLATFORM STREQUAL \"lepus\")\r\n  include(platforms/lepus)\r\nelseif(TARGET_PLATFORM STREQUAL \"miyoo_mini\")\r\n  include(platforms/miyoo_mini)\r\nelseif(TARGET_PLATFORM STREQUAL \"windows9x\")\r\n  include(platforms/windows9x)\r\nelseif(TARGET_PLATFORM STREQUAL \"windowsXP\")\r\n  include(platforms/windowsXP)\r\nelseif(TARGET_PLATFORM STREQUAL \"dos\")\r\n  include(platforms/dos)\r\nelseif(WIN32)\r\n  include(platforms/windows)\r\nendif()\r\n\r\nif(NINTENDO_SWITCH)\r\n  include(platforms/switch)\r\nendif()\r\n\r\nif(AMIGA)\r\n  include(platforms/amiga)\r\nendif()\r\n\r\nif(NINTENDO_3DS)\r\n  include(platforms/n3ds)\r\nendif()\r\n\r\nif(VITA)\r\n  include(\"$ENV{VITASDK}/share/vita.cmake\" REQUIRED)\r\n  include(platforms/vita)\r\nendif()\r\n\r\nif(PS4)\r\n  include(platforms/ps4)\r\nendif()\r\n\r\nif(ANDROID)\r\n  include(platforms/android)\r\nendif()\r\n\r\nif(IOS)\r\n  include(platforms/ios)\r\nendif()\r\n\r\nif(EMSCRIPTEN)\r\n  include(platforms/emscripten)\r\nendif()\r\n\r\nif(UWP_LIB)\r\n  include(platforms/uwp_lib)\r\nendif()\r\n\r\nif(NXDK)\r\n  include(platforms/xbox_nxdk)\r\nendif()\r\n\r\nif(CMAKE_SYSTEM_NAME MATCHES \"Darwin\")\r\n  # Some notable Darwin (macOS kernel) versions are:\r\n  #   8.x == macOS 10.4 (Tiger)\r\n  #   9.x == macOS 10.5 (Leopard)\r\n  #\r\n  # Importantly, a lot of the APIs first appeared in version 9, including\r\n  # the feature availability API (the <Availability.h> header).\r\n  #\r\n  # For Darwin 8 and below, we have to rely on the kernel version\r\n  # to detect available APIs.\r\n  string(REGEX REPLACE \"^([0-9]+)\\\\.([0-9]+).*$\" \"\\\\1\" DARWIN_MAJOR_VERSION \"${CMAKE_SYSTEM_VERSION}\")\r\n  string(REGEX REPLACE \"^([0-9]+)\\\\.([0-9]+).*$\" \"\\\\2\" DARWIN_MINOR_VERSION \"${CMAKE_SYSTEM_VERSION}\")\r\n\r\n  if(DARWIN_MAJOR_VERSION VERSION_EQUAL 8)\r\n    include(platforms/macos_tiger)\r\n  endif()\r\n\r\n  # For older macOS, we assume MacPorts because Homebrew only supports newer version\r\n  if(DARWIN_MAJOR_VERSION VERSION_LESS 11)\r\n    list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/platforms/macports/finders\")\r\n\r\n    # On MacPorts, libfmt is in a subdirectory:\r\n    list(APPEND CMAKE_MODULE_PATH \"/opt/local/lib/libfmt11/cmake\")\r\n  endif()\r\nendif()\r\n"
  },
  {
    "path": "CMake/Tests.cmake",
    "content": "include(GoogleTest)\r\ninclude(functions/copy_files)\r\n\r\nadd_library(libdevilutionx_so SHARED)\r\nset_target_properties(libdevilutionx_so PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})\r\n\r\ntarget_link_dependencies(libdevilutionx_so PUBLIC libdevilutionx)\r\nset_target_properties(libdevilutionx_so PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)\r\n\r\nadd_library(test_main OBJECT test/main.cpp)\r\ntarget_link_dependencies(test_main PUBLIC libdevilutionx_so GTest::gtest GTest::gmock)\r\n\r\nset(tests\r\n  animationinfo_test\r\n  appfat_test\r\n  automap_test\r\n  cursor_test\r\n  dead_test\r\n  diablo_test\r\n  drlg_common_test\r\n  drlg_l1_test\r\n  drlg_l2_test\r\n  drlg_l3_test\r\n  drlg_l4_test\r\n  effects_test\r\n  inv_test\r\n  items_test\r\n  math_test\r\n  missiles_test\r\n  multi_logging_test\r\n  pack_test\r\n  player_test\r\n  quests_test\r\n  scrollrt_test\r\n  stores_test\r\n  tile_properties_test\r\n  timedemo_test\r\n  townerdat_test\r\n  writehero_test\r\n  vendor_test\r\n)\r\nset(standalone_tests\r\n  codec_test\r\n  crawl_test\r\n  data_file_test\r\n  file_util_test\r\n  format_int_test\r\n  ini_test\r\n  palette_blending_test\r\n  parse_int_test\r\n  path_test\r\n  vision_test\r\n  random_test\r\n  rectangle_test\r\n  static_vector_test\r\n  str_cat_test\r\n  utf8_test\r\n)\r\nif(NOT USE_SDL1)\r\n  list(APPEND standalone_tests text_render_integration_test)\r\nendif()\r\nset(benchmarks\r\n  clx_render_benchmark\r\n  crawl_benchmark\r\n  dun_render_benchmark\r\n  light_render_benchmark\r\n  palette_blending_benchmark\r\n  path_benchmark\r\n)\r\n\r\ninclude(test/Fixtures.cmake)\r\n\r\nforeach(test_target ${tests} ${standalone_tests} ${benchmarks})\r\n  add_executable(${test_target} \"test/${test_target}.cpp\")\r\n  set_target_properties(${test_target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})\r\n  if(GPERF)\r\n    target_link_libraries(${test_target} PUBLIC ${GPERFTOOLS_LIBRARIES})\r\n  endif()\r\nendforeach()\r\n\r\nforeach(test_target ${tests} ${standalone_tests})\r\n  gtest_discover_tests(${test_target})\r\nendforeach()\r\n\r\nforeach(test_target ${tests})\r\n  target_link_libraries(${test_target} PRIVATE test_main)\r\nendforeach()\r\n\r\nforeach(test_target ${standalone_tests})\r\n  target_link_libraries(${test_target} PRIVATE GTest::gtest_main)\r\n  target_include_directories(${test_target} PRIVATE \"${PROJECT_SOURCE_DIR}/Source\")\r\nendforeach()\r\n\r\nforeach(target ${benchmarks})\r\n  target_link_libraries(${target} PRIVATE benchmark::benchmark benchmark::benchmark_main)\r\n  target_include_directories(${target} PRIVATE \"${PROJECT_SOURCE_DIR}/Source\")\r\nendforeach()\r\n\r\nadd_library(app_fatal_for_testing OBJECT test/app_fatal_for_testing.cpp)\r\ntarget_sources(app_fatal_for_testing INTERFACE $<TARGET_OBJECTS:app_fatal_for_testing>)\r\n\r\nadd_library(language_for_testing OBJECT test/language_for_testing.cpp)\r\ntarget_sources(language_for_testing INTERFACE $<TARGET_OBJECTS:language_for_testing>)\r\n\r\ntarget_link_dependencies(codec_test PRIVATE libdevilutionx_codec app_fatal_for_testing)\r\ntarget_link_dependencies(clx_render_benchmark\r\n  PRIVATE\r\n  DevilutionX::SDL\r\n  tl\r\n  app_fatal_for_testing\r\n  language_for_testing\r\n  libdevilutionx_clx_render\r\n  libdevilutionx_load_clx\r\n  libdevilutionx_log\r\n  libdevilutionx_surface\r\n)\r\ntarget_link_dependencies(crawl_test PRIVATE libdevilutionx_crawl)\r\ntarget_link_dependencies(crawl_benchmark PRIVATE libdevilutionx_crawl)\r\ntarget_link_dependencies(data_file_test PRIVATE libdevilutionx_txtdata app_fatal_for_testing language_for_testing)\r\ntarget_link_dependencies(dun_render_benchmark PRIVATE libdevilutionx_so)\r\ntarget_link_dependencies(file_util_test PRIVATE libdevilutionx_file_util app_fatal_for_testing)\r\ntarget_link_dependencies(format_int_test PRIVATE libdevilutionx_format_int language_for_testing)\r\ntarget_link_dependencies(ini_test PRIVATE libdevilutionx_ini app_fatal_for_testing)\r\ntarget_link_dependencies(light_render_benchmark PRIVATE libdevilutionx_light_render DevilutionX::SDL libdevilutionx_surface libdevilutionx_paths app_fatal_for_testing)\r\ntarget_link_dependencies(palette_blending_test PRIVATE libdevilutionx_palette_blending DevilutionX::SDL libdevilutionx_strings GTest::gmock app_fatal_for_testing)\r\ntarget_link_dependencies(palette_blending_benchmark\r\n  PRIVATE\r\n  DevilutionX::SDL\r\n  libdevilutionx_palette_blending\r\n  libdevilutionx_palette_kd_tree\r\n  app_fatal_for_testing\r\n)\r\ntarget_link_dependencies(parse_int_test PRIVATE libdevilutionx_parse_int)\r\ntarget_link_dependencies(path_test PRIVATE libdevilutionx_pathfinding libdevilutionx_direction app_fatal_for_testing)\r\ntarget_link_dependencies(vision_test PRIVATE libdevilutionx_vision)\r\ntarget_link_dependencies(path_benchmark PRIVATE libdevilutionx_pathfinding app_fatal_for_testing)\r\ntarget_link_dependencies(random_test PRIVATE libdevilutionx_random)\r\ntarget_link_dependencies(static_vector_test PRIVATE libdevilutionx_random app_fatal_for_testing)\r\ntarget_link_dependencies(str_cat_test PRIVATE libdevilutionx_strings)\r\nif(DEVILUTIONX_SCREENSHOT_FORMAT STREQUAL DEVILUTIONX_SCREENSHOT_FORMAT_PNG AND NOT USE_SDL1)\r\n  target_link_dependencies(text_render_integration_test\r\n    PRIVATE\r\n    DevilutionX::SDL\r\n    GTest::gmock\r\n    GTest::gtest\r\n    fmt::fmt\r\n    tl\r\n    app_fatal_for_testing\r\n    language_for_testing\r\n    libdevilutionx_primitive_render\r\n    libdevilutionx_strings\r\n    libdevilutionx_surface\r\n    libdevilutionx_surface_to_png\r\n    libdevilutionx_text_render\r\n  )\r\n  copy_files(\r\n    FILES\r\n      basic-colors.png\r\n      basic.png\r\n      horizontal_overflow.png\r\n      horizontal_overflow-colors.png\r\n      kerning_fit_spacing-colors.png\r\n      kerning_fit_spacing.png\r\n      kerning_fit_spacing__align_center-colors.png\r\n      kerning_fit_spacing__align_center.png\r\n      kerning_fit_spacing__align_center__newlines.png\r\n      kerning_fit_spacing__align_center__newlines_in_fmt-colors.png\r\n      kerning_fit_spacing__align_center__newlines_in_value-colors.png\r\n      kerning_fit_spacing__align_right-colors.png\r\n      kerning_fit_spacing__align_right.png\r\n      vertical_overflow.png\r\n      vertical_overflow-colors.png\r\n      cursor-start.png\r\n      cursor-middle.png\r\n      cursor-end.png\r\n      multiline_cursor-end_first_line.png\r\n      multiline_cursor-start_second_line.png\r\n      multiline_cursor-middle_second_line.png\r\n      multiline_cursor-end_second_line.png\r\n      highlight-partial.png\r\n      highlight-full.png\r\n      multiline_highlight.png\r\n    SRC_PREFIX test/fixtures/text_render_integration_test/\r\n    OUTPUT_DIR \"${DEVILUTIONX_TEST_FIXTURES_OUTPUT_DIRECTORY}/text_render_integration_test\"\r\n    OUTPUT_VARIABLE _text_render_integration_test_fixtures\r\n  )\r\n  add_custom_target(text_render_integration_test_resources\r\n    DEPENDS\r\n    \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/fonts/12-00.clx\"\r\n    \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/fonts/goldui.trn\"\r\n    \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/fonts/golduis.trn\"\r\n    \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/fonts/grayuis.trn\"\r\n    \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/fonts/grayui.trn\"\r\n    \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/ui_art/diablo.pal\"\r\n    ${_text_render_integration_test_fixtures}\r\n  )\r\n  add_dependencies(text_render_integration_test text_render_integration_test_resources)\r\nendif()\r\ntarget_link_dependencies(utf8_test PRIVATE libdevilutionx_utf8)\r\n\r\ntarget_include_directories(writehero_test PRIVATE 3rdParty/PicoSHA2)\r\n"
  },
  {
    "path": "CMake/VcPkgManifestFeatures.cmake",
    "content": "# See https://vcpkg.readthedocs.io/en/latest/users/manifests/\r\nif(USE_SDL1)\r\n  list(APPEND VCPKG_MANIFEST_FEATURES \"sdl1\")\r\nelseif(USE_SDL3)\r\n  list(APPEND VCPKG_MANIFEST_FEATURES \"sdl3\")\r\nelse()\r\n  list(APPEND VCPKG_MANIFEST_FEATURES \"sdl2\")\r\nendif()\r\nif(PACKET_ENCRYPTION)\r\n  list(APPEND VCPKG_MANIFEST_FEATURES \"encryption\")\r\nendif()\r\nif(USE_GETTEXT_FROM_VCPKG)\r\n  list(APPEND VCPKG_MANIFEST_FEATURES \"translations\")\r\nendif()\r\nif(BUILD_TESTING)\r\n  list(APPEND VCPKG_MANIFEST_FEATURES \"tests\")\r\nendif()\r\n"
  },
  {
    "path": "CMake/finders/FindGperftools.cmake",
    "content": "# Based on https://github.com/baidu/braft/blob/e7776cd03ccc04f18d0f0911200617a89ac3cdf0/cmake/FindGperftools.cmake\r\n\r\n# Tries to find Gperftools.\r\n#\r\n# Usage of this module as follows:\r\n#\r\n#     find_package(Gperftools)\r\n#\r\n# Variables used by this module, they can change the default behaviour and need\r\n# to be set before calling find_package:\r\n#\r\n#  Gperftools_ROOT_DIR  Set this variable to the root installation of\r\n#                       Gperftools if the module has problems finding\r\n#                       the proper installation path.\r\n#\r\n# Variables defined by this module:\r\n#\r\n#  GPERFTOOLS_FOUND              System has Gperftools libs/headers\r\n#  GPERFTOOLS_LIBRARIES          The Gperftools libraries (tcmalloc & profiler)\r\n#  GPERFTOOLS_INCLUDE_DIR        The location of Gperftools headers\r\n\r\nfind_library(GPERFTOOLS_TCMALLOC\r\n  NAMES tcmalloc\r\n  HINTS ${Gperftools_ROOT_DIR}/lib)\r\n\r\nfind_library(GPERFTOOLS_PROFILER\r\n  NAMES profiler\r\n  HINTS ${Gperftools_ROOT_DIR}/lib)\r\n\r\nfind_library(GPERFTOOLS_TCMALLOC_AND_PROFILER\r\n  NAMES tcmalloc_and_profiler\r\n  HINTS ${Gperftools_ROOT_DIR}/lib)\r\n\r\nfind_path(GPERFTOOLS_INCLUDE_DIR\r\n  NAMES gperftools/heap-profiler.h\r\n  HINTS ${Gperftools_ROOT_DIR}/include)\r\n\r\nset(GPERFTOOLS_LIBRARIES ${GPERFTOOLS_TCMALLOC_AND_PROFILER})\r\n\r\ninclude(FindPackageHandleStandardArgs)\r\nfind_package_handle_standard_args(\r\n  Gperftools\r\n  DEFAULT_MSG\r\n  GPERFTOOLS_LIBRARIES\r\n  GPERFTOOLS_INCLUDE_DIR)\r\n\r\nmark_as_advanced(\r\n  Gperftools_ROOT_DIR\r\n  GPERFTOOLS_TCMALLOC\r\n  GPERFTOOLS_PROFILER\r\n  GPERFTOOLS_TCMALLOC_AND_PROFILER\r\n  GPERFTOOLS_LIBRARIES\r\n  GPERFTOOLS_INCLUDE_DIR)\r\n"
  },
  {
    "path": "CMake/finders/FindSDL2_image.cmake",
    "content": "find_package(SDL2_image CONFIG)\r\n\r\nif(TARGET SDL2_image::SDL2_image)\r\n  if(NOT TARGET SDL2::SDL2_image)\r\n    add_library(SDL2::SDL2_image ALIAS SDL2_image::SDL2_image)\r\n  endif()\r\nelse()\r\n  find_package(PkgConfig)\r\n  pkg_check_modules(PC_SDL2_image QUIET SDL2_image>=2.0.0)\r\n\r\n  find_path(SDL2_image_INCLUDE_DIR SDL_image.h\r\n            HINTS ${PC_SDL2_image_INCLUDEDIR} ${PC_SDL2_image_INCLUDE_DIRS})\r\n          \r\n  find_library(SDL2_image_LIBRARY\r\n               NAMES SDL2_image libSDL2_image\r\n               HINTS ${PC_SDL2_image_LIBDIR} ${PC_SDL2_image_LIBRARY_DIRS})\r\n\r\n  include(FindPackageHandleStandardArgs)\r\n  find_package_handle_standard_args(SDL2_image DEFAULT_MSG\r\n                                    SDL2_image_INCLUDE_DIR SDL2_image_LIBRARY)\r\n\r\n  if(SDL2_image_FOUND AND NOT TARGET SDL2::SDL2_image)\r\n    add_library(SDL2::SDL2_image UNKNOWN IMPORTED)\r\n    set_target_properties(SDL2::SDL2_image PROPERTIES\r\n                          IMPORTED_LOCATION ${SDL2_image_LIBRARY}\r\n                          INTERFACE_INCLUDE_DIRECTORIES ${SDL2_image_INCLUDE_DIR})\r\n  endif()\r\n\r\n  if(SDL2_image_FOUND)\r\n    mark_as_advanced(SDL2_image_INCLUDE_DIR SDL2_image_LIBRARY)\r\n    set(SDL2_image_LIBRARIES ${SDL2_image_LIBRARY})\r\n    set(SDL2_image_INCLUDE_DIRS ${SDL2_image_INCLUDE_DIR})\r\n  endif()\r\nendif()\r\n"
  },
  {
    "path": "CMake/finders/FindSDL_audiolib.cmake",
    "content": "find_package(PkgConfig)\npkg_check_modules(PC_SDL_audiolib QUIET SDL_audiolib)\n\nfind_path(SDL_audiolib_INCLUDE_DIR aulib.h\n          HINTS ${PC_SDL_audiolib_INCLUDEDIR} ${PC_SDL_audiolib_INCLUDE_DIRS})\n\nfind_library(SDL_audiolib_LIBRARY\n             NAMES SDL_audiolib libSDL_audiolib\n             HINTS ${PC_SDL_audiolib_LIBDIR} ${PC_SDL_audiolib_LIBRARY_DIRS})\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(SDL_audiolib DEFAULT_MSG\n                                  SDL_audiolib_INCLUDE_DIR SDL_audiolib_LIBRARY)\n\nif(SDL_audiolib_FOUND AND NOT TARGET SDL_audiolib::SDL_audiolib)\n  add_library(SDL_audiolib::SDL_audiolib UNKNOWN IMPORTED)\n  set_target_properties(SDL_audiolib::SDL_audiolib PROPERTIES\n                        IMPORTED_LOCATION ${SDL_audiolib_LIBRARY}\n                        INTERFACE_INCLUDE_DIRECTORIES ${SDL_audiolib_INCLUDE_DIR})\nendif()\n\nif(SDL_audiolib_FOUND)\n  mark_as_advanced(SDL_audiolib_INCLUDE_DIR SDL_audiolib_LIBRARY)\n  set(SDL_audiolib_LIBRARIES ${SDL_audiolib_LIBRARY})\n  set(SDL_audiolib_INCLUDE_DIRS ${SDL_audiolib_INCLUDE_DIR})\nendif()\n"
  },
  {
    "path": "CMake/finders/FindSpeechd.cmake",
    "content": "# find speech-dispatcher library and header if available\n# Copyright (c) 2009, Jeremy Whiting <jpwhiting@kde.org>\n# Copyright (c) 2011, Raphael Kubo da Costa <kubito@gmail.com>\n# This module defines\n#  SPEECHD_INCLUDE_DIR, where to find libspeechd.h\n#  SPEECHD_LIBRARIES, the libraries needed to link against speechd\n#  SPEECHD_FOUND, If false, speechd was not found\n#\n# Redistribution and use is allowed according to the terms of the BSD license.\n# For details see the accompanying COPYING-CMAKE-SCRIPTS file.\n\nfind_path(SPEECHD_INCLUDE_DIR libspeechd.h PATH_SUFFIXES speech-dispatcher)\n\nfind_library(SPEECHD_LIBRARIES NAMES speechd)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Speechd REQUIRED_VARS SPEECHD_INCLUDE_DIR SPEECHD_LIBRARIES)\n"
  },
  {
    "path": "CMake/finders/Findsimpleini.cmake",
    "content": "find_package(PkgConfig QUIET)\r\nif(PKG_CONFIG_FOUND)\r\n  pkg_check_modules(PC_simpleini QUIET simpleini)\r\nendif()\r\n\r\nfind_path(simpleini_INCLUDE_DIR SimpleIni.h\r\n          HINTS ${PC_simpleini_INCLUDEDIR} ${PC_simpleini_INCLUDE_DIRS} ${SIMPLEINI_INCLUDE_DIRS})\r\n\r\nfind_library(simpleini_LIBRARY simpleini\r\n             HINTS ${PC_simpleini_LIBDIR} ${PC_simpleini_LIBRARY_DIRS} ${SIMPLEINI_LIBRARY_DIRS})\r\n\r\nlist(APPEND _required_vars \"simpleini_INCLUDE_DIR\")\r\nif(NOT simpleini_INCLUDE_DIR STREQUAL \"simpleini_INCLUDE_DIR-NOTFOUND\")\r\n  file(READ \"${simpleini_INCLUDE_DIR}/SimpleIni.h\" _version_header_content)\r\n  if(_version_header_content MATCHES \"<th>Version *<td>([0-9.]+)\")\r\n    set(simpleini_VERSION \"${CMAKE_MATCH_1}\")\r\n  endif()\r\nendif()\r\n\r\n# SimpleIni can be distributed as a header-only library, so the library is optional.\r\nif(NOT simpleini_LIBRARY STREQUAL \"simpleini_LIBRARY-NOTFOUND\")\r\n  list(APPEND _required_vars \"simpleini_LIBRARY\")\r\nendif()\r\n\r\ninclude(FindPackageHandleStandardArgs)\r\nfind_package_handle_standard_args(simpleini\r\n                                  REQUIRED_VARS ${_required_vars}\r\n                                  VERSION_VAR simpleini_VERSION)\r\n\r\nif(simpleini_FOUND AND NOT TARGET simpleini::simpleini)\r\n  if(simpleini_LIBRARY STREQUAL \"simpleini_LIBRARY-NOTFOUND\")\r\n    # Header-only distribution.\r\n    add_library(simpleini INTERFACE)\r\n    target_include_directories(simpleini INTERFACE ${simpleini_INCLUDE_DIR})\r\n    add_library(simpleini::simpleini ALIAS simpleini)\r\n  else()\r\n    # A distribution with a library.\r\n    add_library(simpleini::simpleini UNKNOWN IMPORTED)\r\n    set_target_properties(simpleini::simpleini PROPERTIES\r\n                          INTERFACE_INCLUDE_DIRECTORIES ${simpleini_INCLUDE_DIR}\r\n                          IMPORTED_LOCATION ${simpleini_LIBRARY})\r\n  endif()\r\nendif()\r\n\r\nif(simpleini_FOUND)\r\n  mark_as_advanced(simpleini_INCLUDE_DIR simpleini_LIBRARY)\r\n  set(simpleini_LIBRARIES ${simpleini_LIBRARY})\r\n  set(simpleini_INCLUDE_DIRS ${simpleini_INCLUDE_DIR})\r\nendif()\r\n"
  },
  {
    "path": "CMake/finders/Findsodium.cmake",
    "content": "# Written in 2016 by Henrik Steffen Gaßmann <henrik@gassmann.onl>\r\n#\r\n# To the extent possible under law, the author(s) have dedicated all\r\n# copyright and related and neighboring rights to this software to the\r\n# public domain worldwide. This software is distributed without any warranty.\r\n#\r\n# You should have received a copy of the CC0 Public Domain Dedication\r\n# along with this software. If not, see\r\n#\r\n#     https://creativecommons.org/publicdomain/zero/1.0/\r\n#\r\n########################################################################\r\n# Tries to find the local libsodium installation.\r\n#\r\n# On Windows the sodium_DIR environment variable is used as a default\r\n# hint which can be overridden by setting the corresponding cmake variable.\r\n#\r\n# Once done the following variables will be defined:\r\n#\r\n#   sodium_FOUND\r\n#   sodium_INCLUDE_DIR\r\n#   sodium_LIBRARY_DEBUG\r\n#   sodium_LIBRARY_RELEASE\r\n#   sodium_VERSION_STRING\r\n#\r\n# Furthermore an imported \"sodium\" target is created.\r\n#\r\n\r\nif (CMAKE_C_COMPILER_ID STREQUAL \"GNU\"\r\n    OR CMAKE_C_COMPILER_ID STREQUAL \"Clang\")\r\n    set(_GCC_COMPATIBLE 1)\r\nendif()\r\n\r\n# static library option\r\nif (NOT DEFINED sodium_USE_STATIC_LIBS)\r\n    option(sodium_USE_STATIC_LIBS \"enable to statically link against sodium\" OFF)\r\nendif()\r\nif(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST))\r\n    unset(sodium_LIBRARY CACHE)\r\n    unset(sodium_LIBRARY_DEBUG CACHE)\r\n    unset(sodium_LIBRARY_RELEASE CACHE)\r\n    unset(sodium_DLL_DEBUG CACHE)\r\n    unset(sodium_DLL_RELEASE CACHE)\r\n    set(sodium_USE_STATIC_LIBS_LAST ${sodium_USE_STATIC_LIBS} CACHE INTERNAL \"internal change tracking variable\")\r\nendif()\r\n\r\n\r\n########################################################################\r\n# UNIX\r\nif (UNIX OR CMAKE_SYSTEM_NAME STREQUAL \"Generic\" OR AMIGA)\r\n    # import pkg-config\r\n    find_package(PkgConfig QUIET)\r\n    if (PKG_CONFIG_FOUND)\r\n        pkg_check_modules(sodium_PKG QUIET libsodium)\r\n    endif()\r\n\r\n    if(sodium_USE_STATIC_LIBS)\r\n      if(sodium_PKG_STATIC_FOUND)\r\n        # Create a temporary list to manipulate the list of libraries we found\r\n        set(sodium_PKG_STATIC_LIBRARIES_TMP \"\")\r\n\r\n        # Mangle the library names into the format we need\r\n        foreach(_libname ${sodium_PKG_STATIC_LIBRARIES})\r\n          if (NOT _libname MATCHES \"^lib.*\\\\.a$\") # ignore strings already ending with .a\r\n            list(APPEND sodium_PKG_STATIC_LIBRARIES_TMP \"lib${_libname}.a\")\r\n          endif()\r\n        endforeach()\r\n\r\n        list(REMOVE_DUPLICATES sodium_PKG_STATIC_LIBRARIES_TMP)\r\n        # Replace the list with our processed one\r\n        set(sodium_PKG_STATIC_LIBRARIES ${sodium_PKG_STATIC_LIBRARIES_TMP})\r\n      else()\r\n        # if pkgconfig for libsodium doesn't provide\r\n        # static lib info, then override PKG_STATIC here..\r\n        set(sodium_PKG_STATIC_LIBRARIES libsodium.a)\r\n      endif()\r\n\r\n      set(XPREFIX sodium_PKG_STATIC)\r\n    else()\r\n      if(sodium_PKG_FOUND)\r\n        set(sodium_PKG_LIBRARIES sodium)\r\n      endif()\r\n\r\n      set(XPREFIX sodium_PKG)\r\n    endif()\r\n\r\n    # Feed pkgconfig results (if found) into standard find_* to populate\r\n    # the right CMake cache variables\r\n    find_path(sodium_INCLUDE_DIR sodium.h\r\n        HINTS ${${XPREFIX}_INCLUDE_DIRS}\r\n    )\r\n    find_library(sodium_LIBRARY_DEBUG NAMES ${${XPREFIX}_LIBRARIES}\r\n        HINTS ${${XPREFIX}_LIBRARY_DIRS}\r\n    )\r\n    find_library(sodium_LIBRARY_RELEASE NAMES ${${XPREFIX}_LIBRARIES}\r\n        HINTS ${${XPREFIX}_LIBRARY_DIRS}\r\n    )\r\n\r\n\r\n########################################################################\r\n# Windows\r\nelseif (WIN32)\r\n    set(sodium_DIR \"$ENV{sodium_DIR}\" CACHE FILEPATH \"sodium install directory\")\r\n    mark_as_advanced(sodium_DIR)\r\n\r\n    find_path(sodium_INCLUDE_DIR sodium.h\r\n        HINTS ${sodium_DIR}\r\n        PATH_SUFFIXES include\r\n    )\r\n\r\n    if (MSVC)\r\n        # detect target architecture\r\n    file(WRITE \"${CMAKE_CURRENT_BINARY_DIR}/arch.c\" [=[\r\n            #if defined _M_IX86\r\n            #error ARCH_VALUE x86_32\r\n            #elif defined _M_X64\r\n            #error ARCH_VALUE x86_64\r\n            #endif\r\n            #error ARCH_VALUE unknown\r\n        ]=])\r\n    try_compile(_UNUSED_VAR \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_BINARY_DIR}/arch.c\"\r\n            OUTPUT_VARIABLE _COMPILATION_LOG\r\n        )\r\n\r\n        # construct library path\r\n        if (CMAKE_SIZEOF_VOID_P EQUAL 4)\r\n            string(APPEND _PLATFORM_PATH \"Win32\")\r\n        elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)\r\n            string(APPEND _PLATFORM_PATH \"x64\")\r\n        else()\r\n            message(FATAL_ERROR \"Can't find target architecture. CMAKE_SIZEOF_VOID_P not 4 or 8.\")\r\n        endif()\r\n        string(APPEND _PLATFORM_PATH \"/$$CONFIG$$\")\r\n\r\n        if (MSVC_VERSION LESS 1900)\r\n            math(EXPR _VS_VERSION \"${MSVC_VERSION} / 10 - 60\")\r\n        else()\r\n            math(EXPR _VS_VERSION \"${MSVC_VERSION} / 10 - 50\")\r\n        endif()\r\n        string(APPEND _PLATFORM_PATH \"/v${_VS_VERSION}\")\r\n\r\n        if (sodium_USE_STATIC_LIBS)\r\n            string(APPEND _PLATFORM_PATH \"/static\")\r\n        else()\r\n            string(APPEND _PLATFORM_PATH \"/dynamic\")\r\n        endif()\r\n\r\n        string(REPLACE \"$$CONFIG$$\" \"Debug\" _DEBUG_PATH_SUFFIX \"${_PLATFORM_PATH}\")\r\n        string(REPLACE \"$$CONFIG$$\" \"Release\" _RELEASE_PATH_SUFFIX \"${_PLATFORM_PATH}\")\r\n\r\n        find_library(sodium_LIBRARY_DEBUG libsodium.lib\r\n            HINTS ${sodium_DIR}\r\n            PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX}\r\n        )\r\n        find_library(sodium_LIBRARY_RELEASE libsodium.lib\r\n            HINTS ${sodium_DIR}\r\n            PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX}\r\n        )\r\n        if (NOT sodium_USE_STATIC_LIBS)\r\n            set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES})\r\n            set(CMAKE_FIND_LIBRARY_SUFFIXES \".dll\")\r\n            find_library(sodium_DLL_DEBUG libsodium\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX}\r\n            )\r\n            find_library(sodium_DLL_RELEASE libsodium\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX}\r\n            )\r\n            set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK})\r\n        endif()\r\n\r\n    elseif(_GCC_COMPATIBLE)\r\n        if (sodium_USE_STATIC_LIBS)\r\n            find_library(sodium_LIBRARY_DEBUG libsodium.a\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES lib\r\n            )\r\n            find_library(sodium_LIBRARY_RELEASE libsodium.a\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES lib\r\n            )\r\n        else()\r\n            find_library(sodium_LIBRARY_DEBUG libsodium.dll.a\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES lib\r\n            )\r\n            find_library(sodium_LIBRARY_RELEASE libsodium.dll.a\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES lib\r\n            )\r\n\r\n            file(GLOB _DLL\r\n                LIST_DIRECTORIES false\r\n                RELATIVE \"${sodium_DIR}/bin\"\r\n                \"${sodium_DIR}/bin/libsodium*.dll\"\r\n            )\r\n            find_library(sodium_DLL_DEBUG ${_DLL} libsodium\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES bin\r\n            )\r\n            find_library(sodium_DLL_RELEASE ${_DLL} libsodium\r\n                HINTS ${sodium_DIR}\r\n                PATH_SUFFIXES bin\r\n            )\r\n        endif()\r\n    else()\r\n        message(FATAL_ERROR \"this platform is not supported by FindSodium.cmake\")\r\n    endif()\r\n\r\n\r\n########################################################################\r\n# unsupported\r\nelse()\r\n    message(FATAL_ERROR \"this platform is not supported by FindSodium.cmake\")\r\nendif()\r\n\r\n\r\n########################################################################\r\n# common stuff\r\n\r\n# extract sodium version\r\nif (sodium_INCLUDE_DIR)\r\n  set(_VERSION_HEADER \"${sodium_INCLUDE_DIR}/sodium/version.h\")\r\n  if(EXISTS \"${_VERSION_HEADER}\")\r\n        file(READ \"${_VERSION_HEADER}\" _VERSION_HEADER_CONTENT)\r\n    string(REGEX REPLACE \".*define[ \\t]+SODIUM_VERSION_STRING[^\\\"]+\\\"([^\\\"]+)\\\".*\" \"\\\\1\"\r\n                   sodium_VERSION_STRING \"${_VERSION_HEADER_CONTENT}\")\r\n    set(sodium_VERSION_STRING \"${sodium_VERSION_STRING}\")\r\n    endif()\r\nendif()\r\n\r\n# communicate results\r\ninclude(FindPackageHandleStandardArgs)\r\nfind_package_handle_standard_args(\r\n    sodium # The name must be either uppercase or match the filename case.\r\n    REQUIRED_VARS\r\n        sodium_LIBRARY_RELEASE\r\n        sodium_LIBRARY_DEBUG\r\n        sodium_INCLUDE_DIR\r\n    VERSION_VAR\r\n    sodium_VERSION_STRING\r\n)\r\n\r\n# mark file paths as advanced\r\nmark_as_advanced(sodium_INCLUDE_DIR)\r\nmark_as_advanced(sodium_LIBRARY_DEBUG)\r\nmark_as_advanced(sodium_LIBRARY_RELEASE)\r\nif (WIN32)\r\n    mark_as_advanced(sodium_DLL_DEBUG)\r\n    mark_as_advanced(sodium_DLL_RELEASE)\r\nendif()\r\n\r\n# create imported target\r\nif(sodium_USE_STATIC_LIBS)\r\n    set(_LIB_TYPE STATIC)\r\nelse()\r\n    set(_LIB_TYPE SHARED)\r\nendif()\r\nadd_library(sodium ${_LIB_TYPE} IMPORTED)\r\n\r\nset_target_properties(sodium PROPERTIES\r\n    INTERFACE_INCLUDE_DIRECTORIES \"${sodium_INCLUDE_DIR}\"\r\n    IMPORTED_LINK_INTERFACE_LANGUAGES \"C\"\r\n)\r\n\r\nif (sodium_USE_STATIC_LIBS)\r\n    set_target_properties(sodium PROPERTIES\r\n        INTERFACE_COMPILE_DEFINITIONS \"SODIUM_STATIC\"\r\n        IMPORTED_LOCATION \"${sodium_LIBRARY_RELEASE}\"\r\n        IMPORTED_LOCATION_DEBUG \"${sodium_LIBRARY_DEBUG}\"\r\n    )\r\nelse()\r\n    if (UNIX)\r\n        set_target_properties(sodium PROPERTIES\r\n            IMPORTED_LOCATION \"${sodium_LIBRARY_RELEASE}\"\r\n            IMPORTED_LOCATION_DEBUG \"${sodium_LIBRARY_DEBUG}\"\r\n        )\r\n    elseif (WIN32)\r\n        set_target_properties(sodium PROPERTIES\r\n            IMPORTED_IMPLIB \"${sodium_LIBRARY_RELEASE}\"\r\n            IMPORTED_IMPLIB_DEBUG \"${sodium_LIBRARY_DEBUG}\"\r\n        )\r\n        if (NOT (sodium_DLL_DEBUG MATCHES \".*-NOTFOUND\"))\r\n            set_target_properties(sodium PROPERTIES\r\n                IMPORTED_LOCATION_DEBUG \"${sodium_DLL_DEBUG}\"\r\n            )\r\n        endif()\r\n        if (NOT (sodium_DLL_RELEASE MATCHES \".*-NOTFOUND\"))\r\n            set_target_properties(sodium PROPERTIES\r\n                IMPORTED_LOCATION_RELWITHDEBINFO \"${sodium_DLL_RELEASE}\"\r\n                IMPORTED_LOCATION_MINSIZEREL \"${sodium_DLL_RELEASE}\"\r\n                IMPORTED_LOCATION_RELEASE \"${sodium_DLL_RELEASE}\"\r\n            )\r\n        endif()\r\n    endif()\r\nendif()\r\n"
  },
  {
    "path": "CMake/functions/FetchContent_ExcludeFromAll_backport.cmake",
    "content": "if(CMAKE_VERSION VERSION_LESS \"3.28.0\")\r\n  macro(FetchContent_Declare_ExcludeFromAll)\r\n    FetchContent_Declare(${ARGV})\r\n  endmacro()\r\n  # Like `FetchContent_MakeAvailable` but passes EXCLUDE_FROM_ALL to `add_subdirectory`.\r\n  macro(FetchContent_MakeAvailable_ExcludeFromAll)\r\n    foreach(name ${ARGV})\r\n      string(TOLOWER ${name} nameLower)\r\n      FetchContent_GetProperties(${name})\r\n      if(NOT ${${nameLower}_POPULATED})\r\n        FetchContent_Populate(${name})\r\n        if(EXISTS ${${nameLower}_SOURCE_DIR}/CMakeLists.txt)\r\n          add_subdirectory(${${nameLower}_SOURCE_DIR} ${${nameLower}_BINARY_DIR} EXCLUDE_FROM_ALL)\r\n        endif()\r\n      endif()\r\n    endforeach()\r\n  endmacro()\r\nelse()\r\n  macro(FetchContent_Declare_ExcludeFromAll)\r\n    FetchContent_Declare(${ARGV} EXCLUDE_FROM_ALL)\r\n  endmacro()\r\n  macro(FetchContent_MakeAvailable_ExcludeFromAll)\r\n    FetchContent_MakeAvailable(${ARGV})\r\n  endmacro()\r\nendif()\r\n"
  },
  {
    "path": "CMake/functions/copy_files.cmake",
    "content": "\r\n# copy_files(\r\n#   FILES <file...>\r\n#   OUTPUT_DIR <output_dir>\r\n#   [SRC_PREFIX <src_prefix>]\r\n#   [OUTPUT_VARIABLE <output_variable>]\r\n# )\r\nfunction(copy_files)\r\n  set(options)\r\n  set(oneValueArgs SRC_PREFIX OUTPUT_DIR OUTPUT_VARIABLE)\r\n  set(multiValueArgs FILES)\r\n  cmake_parse_arguments(PARSE_ARGV 0 arg\r\n      \"${options}\" \"${oneValueArgs}\" \"${multiValueArgs}\"\r\n  )\r\n  if(arg_UNPARSED_ARGUMENTS)\r\n     message(FATAL \"unknown arguments: ${arg_UNPARSED_ARGUMENTS}\")\r\n  endif()\r\n  if(OUTPUT_DIR IN_LIST arg_KEYWORDS_MISSING_VALUES)\r\n    message(FATAL \"OUTPUT_DIR is required\")\r\n  endif()\r\n\r\n  foreach(path ${arg_FILES})\r\n    set(src \"${CMAKE_CURRENT_SOURCE_DIR}/${arg_SRC_PREFIX}${path}\")\r\n    set(dst \"${arg_OUTPUT_DIR}/${path}\")\r\n    list(APPEND _out_paths \"${dst}\")\r\n    add_custom_command(\r\n      COMMENT \"Copying ${arg_SRC_PREFIX}${path}\"\r\n      OUTPUT \"${dst}\"\r\n      DEPENDS \"${src}\"\r\n      COMMAND ${CMAKE_COMMAND} -E copy \"${src}\" \"${dst}\"\r\n      VERBATIM\r\n    )\r\n  endforeach()\r\n  if(arg_OUTPUT_VARIABLE)\r\n    set(${arg_OUTPUT_VARIABLE} ${_out_paths} PARENT_SCOPE)\r\n  endif()\r\n\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/functions/dependency_options.cmake",
    "content": "# This function defines 2 options for finding and linking a dependency:\r\n#\r\n# 1. ${SYSTEM_OPTION_NAME}: whether to use the system version of the dependency (default: ${DEFAULT_SYSTEM_VALUE})\r\n# 2. ${STATIC_OPTION_NAME}: whether to link the dependency statically.\r\n#    The default is ON if ${SYSTEM_OPTION_NAME} is OFF or if target does not support shared libraries.\r\n#\r\n# The ${LIB_NAME} argument is a human-readable library name only used in option description strings.\r\nfunction(dependency_options LIB_NAME SYSTEM_OPTION_NAME DEFAULT_SYSTEM_VALUE STATIC_OPTION_NAME)\r\n  option(${SYSTEM_OPTION_NAME} \"Use system-provided ${LIB_NAME}\" ${DEFAULT_SYSTEM_VALUE})\r\n  get_property(_supports_shared_libs GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)\r\n  if(_supports_shared_libs)\r\n    if(${SYSTEM_OPTION_NAME})\r\n      set(_static_default OFF)\r\n    else()\r\n      set(_static_default ON)\r\n    endif()\r\n    option(${STATIC_OPTION_NAME} \"Link ${LIB_NAME} statically\" ${_static_default})\r\n  else()\r\n    set(${STATIC_OPTION_NAME} ON)\r\n    set(${STATIC_OPTION_NAME} ON PARENT_SCOPE)\r\n  endif()\r\n\r\n  if(${STATIC_OPTION_NAME})\r\n    set(_msg_type \"static\")\r\n  else()\r\n    set(_msg_type \"dynamic\")\r\n  endif()\r\n  if(${SYSTEM_OPTION_NAME})\r\n    set(_msg_source \"system library\")\r\n  else()\r\n    set(_msg_source \"library from source\")\r\n  endif()\r\n  message(\"-- 📚 ${LIB_NAME}: ${_msg_type} ${_msg_source}\")\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/functions/devilutionx_library.cmake",
    "content": "include(functions/genex)\r\ninclude(functions/set_relative_file_macro)\r\ninclude(functions/object_libraries)\r\n\r\n# This function is equivalent to `add_library` but applies DevilutionX-specific\r\n# compilation flags to it.\r\nfunction(add_devilutionx_library NAME)\r\n  add_library(${NAME} ${ARGN})\r\n\r\n  target_include_directories(${NAME} PUBLIC ${PROJECT_SOURCE_DIR}/Source)\r\n\r\n  target_compile_definitions(${NAME} PUBLIC ${DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS})\r\n  target_compile_options(${NAME} PUBLIC ${DEVILUTIONX_PLATFORM_COMPILE_OPTIONS})\r\n\r\n  genex_for_option(DEBUG)\r\n  target_compile_definitions(${NAME} PUBLIC \"$<${DEBUG_GENEX}:_DEBUG>\")\r\n\r\n  if(NOT NONET AND NOT DISABLE_TCP)\r\n    target_compile_definitions(${NAME} PUBLIC ASIO_STANDALONE)\r\n  endif()\r\n\r\n  genex_for_option(UBSAN)\r\n  target_compile_options(${NAME} PUBLIC $<${UBSAN_GENEX}:-fsanitize=undefined>)\r\n  target_link_libraries(${NAME} PUBLIC $<${UBSAN_GENEX}:-fsanitize=undefined>)\r\n\r\n  if(TSAN)\r\n    target_compile_options(${NAME} PUBLIC -fsanitize=thread)\r\n    target_link_libraries(${NAME} PUBLIC -fsanitize=thread)\r\n  else()\r\n    genex_for_option(ASAN)\r\n    target_compile_options(${NAME} PUBLIC \"$<${ASAN_GENEX}:-fsanitize=address;-fsanitize-recover=address>\")\r\n    target_link_libraries(${NAME} PUBLIC \"$<${ASAN_GENEX}:-fsanitize=address;-fsanitize-recover=address>\")\r\n  endif()\r\n\r\n  if(CMAKE_CXX_COMPILER_ID MATCHES \"GNU\")\r\n    genex_for_option(DEVILUTIONX_STATIC_CXX_STDLIB)\r\n    target_link_libraries(${NAME} PUBLIC $<${DEVILUTIONX_STATIC_CXX_STDLIB_GENEX}:-static-libgcc;-static-libstdc++>)\r\n  endif()\r\n\r\n  if(NOT CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n    # Note: For Valgrind support.\r\n    genex_for_option(DEBUG)\r\n    target_compile_options(${NAME} PUBLIC $<${DEBUG_GENEX}:-fno-omit-frame-pointer>)\r\n\r\n    # Warnings for devilutionX\r\n    target_compile_options(${NAME} PUBLIC -Wall -Wextra -Wno-unused-parameter)\r\n  endif()\r\n\r\n  if(NOT WIN32 AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)\r\n    # Enable POSIX extensions such as `readlink` and `ftruncate`.\r\n    add_definitions(-D_POSIX_C_SOURCE=200809L)\r\n  endif()\r\n\r\n  if(BUILD_TESTING)\r\n    if(ENABLE_CODECOVERAGE)\r\n      if(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n        message(WARNING \"Codecoverage not supported with MSVC\")\r\n      else()\r\n        target_compile_options(${NAME} PUBLIC --coverage)\r\n        target_link_options(${NAME} PUBLIC --coverage)\r\n      endif()\r\n    endif()\r\n\r\n    target_compile_definitions(${NAME} PRIVATE _DVL_EXPORTING)\r\n  endif()\r\n\r\n  target_compile_definitions(${NAME} PUBLIC ${DEVILUTIONX_DEFINITIONS})\r\n\r\n  set_relative_file_macro(${NAME})\r\nendfunction()\r\n\r\n# Same as add_devilutionx_library(${NAME} OBJECT).\r\nfunction(add_devilutionx_object_library NAME)\r\n  add_devilutionx_library(${NAME} OBJECT ${ARGN})\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/functions/emscripten_system_library.cmake",
    "content": "# This function defines a target that points to an Emscripten system library.\r\n#\r\n# Arguments:\r\n#   LIB_NAME: a human-readable library name.\r\n#   TARGET_NAME: the library target name\r\n#   ...ARGN: Emscripten flags.\r\n#\r\n# Example:\r\n#   emscripten_system_library(\"SDL2_image\" SDL2::SDL2_image USE_SDL_IMAGE=2 \"SDL2_IMAGE_FORMATS='[\\\"png\\\"]'\")\r\nfunction(emscripten_system_library LIB_NAME TARGET_NAME)\r\n  add_library(${TARGET_NAME} INTERFACE IMPORTED GLOBAL)\r\n  foreach(arg ${ARGN})\r\n    target_compile_options(${TARGET_NAME} INTERFACE \"SHELL:-s ${arg}\")\r\n    target_link_options(${TARGET_NAME} INTERFACE \"SHELL:-s ${arg}\")\r\n  endforeach()\r\n  message(\"-- 📚 ${LIB_NAME}: Emscripten system library via ${ARGN}\")\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/functions/genex.cmake",
    "content": "# Generator expression helpers\r\n\r\n# If \"NEW\", `set(CACHE ...)` does not override non-cache variables\r\nif(POLICY CMP0126)\r\n  cmake_policy(GET CMP0126 _cache_does_not_override_normal_vars_policy)\r\nelse()\r\n  set(_cache_does_not_override_normal_vars_policy \"OLD\")\r\nendif()\r\n\r\nmacro(GENEX_OPTION name default description)\r\n  if(_cache_does_not_override_normal_vars_policy STREQUAL \"NEW\")\r\n    set(_define_cache_var TRUE)\r\n  elseif(DEFINED ${name})\r\n    get_property(_define_cache_var CACHE ${name} PROPERTY TYPE)\r\n  endif()\r\n\r\n  if(_define_cache_var)\r\n    set(${name} ${default} CACHE STRING ${description})\r\n    set_property(CACHE ${name} PROPERTY STRINGS FOR_DEBUG FOR_RELEASE ON OFF)\r\n  else()\r\n    message(\"Skipping `set(CACHE ${name} ...)`: CMake is < 3.21 and a non-cache variable with the same name is already set (${name}=${${name}})\")\r\n  endif()\r\nendmacro()\r\n\r\n# Provide an option that defaults to ON in debug builds.\r\nmacro(DEBUG_OPTION name description)\r\n  GENEX_OPTION(${name} FOR_DEBUG ${description})\r\nendmacro()\r\n\r\n# Provide an option that defaults to ON in non-debug builds.\r\n# Note that this applies to Release, RelWithDebInfo, and MinSizeRel.\r\nmacro(RELEASE_OPTION name description)\r\n  GENEX_OPTION(${name} FOR_RELEASE ${description})\r\nendmacro()\r\n\r\n# Generate a generator expression for the given variable's current value.\r\n#\r\n# Supported variable values and what the resulting generator expression will evaluate to:\r\n# * FOR_DEBUG - 1 in Debug config.\r\n# * FOR_RELEASE - 1 in non-Debug config (Release, RelWithDebInfo).\r\n# * Boolean value (TRUE, FALSE, ON, 1, etc) - that value as 0 or 1.\r\n#\r\n# Result is set on ${option}_GENEX in the calling scope.\r\nfunction(genex_for_option name)\r\n  set(value ${${name}})\r\n  set(\r\n    ${name}_GENEX\r\n    $<IF:$<STREQUAL:${value},FOR_DEBUG>,$<CONFIG:Debug>,$<IF:$<STREQUAL:${value},FOR_RELEASE>,$<NOT:$<CONFIG:Debug>>,$<BOOL:${value}>>>\r\n    PARENT_SCOPE\r\n  )\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/functions/git.cmake",
    "content": "function(get_git_commit_hash output_var)\r\n  execute_process(\r\n    COMMAND git log -1 --format=%h\r\n    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\r\n    OUTPUT_VARIABLE GIT_COMMIT_HASH\r\n    OUTPUT_STRIP_TRAILING_WHITESPACE)\r\n  set(${output_var} ${GIT_COMMIT_HASH} PARENT_SCOPE)\r\nendfunction(get_git_commit_hash)\r\n"
  },
  {
    "path": "CMake/functions/object_libraries.cmake",
    "content": "# CMake has limited support for object libraries.\r\n#\r\n# The main limitation of CMake object libraries is the lack\r\n# of transitive dependency support.\r\n# The functions here provide a workaround for that.\r\n#\r\n# Use `target_link_dependencies` instead of `target_link_libraries`\r\n#\r\n# https://gitlab.kitware.com/cmake/cmake/-/issues/18090#note_861617\r\n#\r\n# At the end of the main `CMakeLists.txt`, call `resolve_target_link_dependencies()`.\r\n\r\n# Behaves like target_link_libraries, but propagates OBJECT libraries' objects\r\n#   up to the first non-object library.\r\nfunction(target_link_dependencies TARGET)\r\n  # The library we're linking may not have been defined yet,\r\n  # so we record it for now and resolve it later.\r\n\r\n  # CMake <3.19 limits which property names are allowed on INTERFACE targets,\r\n  # so we prefix the name with \"INTERFACE_\":\r\n  # https://cmake.org/cmake/help/v3.18/manual/cmake-buildsystem.7.html#interface-libraries\r\n  set_property(TARGET ${TARGET} APPEND PROPERTY INTERFACE_LINKED_DEPENDENCIES ${ARGN})\r\n  set_property(GLOBAL APPEND PROPERTY TARGETS_WITH_LINKED_DEPENDENCIES \"${TARGET}\")\r\nendfunction()\r\n\r\n# Transitively collects dependencies in topological order using depth-first search.\r\nfunction(_collect_linked_dependencies INITIAL_TARGET)\r\n  set(MODES PUBLIC PRIVATE INTERFACE)\r\n  list(APPEND STACK \"${INITIAL_TARGET}\")\r\n  while(NOT STACK STREQUAL \"\")\r\n    list(POP_BACK STACK TARGET)\r\n    if(${TARGET} MATCHES \"^\\\\$\")\r\n      set(FINALIZING ON)\r\n      string(SUBSTRING \"${TARGET}\" 1 -1 TARGET)\r\n    else()\r\n      set(FINALIZING OFF)\r\n    endif()\r\n\r\n    get_target_property(LINKED_DEPENDENCIES ${TARGET} INTERFACE_LINKED_DEPENDENCIES)\r\n    if(LINKED_DEPENDENCIES STREQUAL \"LINKED_DEPENDENCIES-NOTFOUND\")\r\n      # Not a `target_link_dependencies` target, nothing to do.\r\n      continue()\r\n    endif()\r\n\r\n    if(NOT FINALIZING)\r\n      get_target_property(LINKED_DEPENDENCIES_COLLECTED ${TARGET} INTERFACE_LINKED_DEPENDENCIES_COLLECTED)\r\n      if(NOT LINKED_DEPENDENCIES_COLLECTED STREQUAL \"LINKED_DEPENDENCIES_COLLECTED-NOTFOUND\")\r\n        # Already processed.\r\n        continue()\r\n      endif()\r\n\r\n      list(APPEND STACK \"$${TARGET}\")\r\n\r\n      get_target_property(LINKED_DEPENDENCIES_COLLECTING ${TARGET} INTERFACE_LINKED_DEPENDENCIES_COLLECTING)\r\n      if(NOT LINKED_DEPENDENCIES_COLLECTING STREQUAL \"LINKED_DEPENDENCIES_COLLECTING-NOTFOUND\")\r\n        # A cycle.\r\n        message(FATAL_ERROR \"Dependency cycle for ${TARGET}: ${STACK}\")\r\n      endif()\r\n      set_property(TARGET \"${TARGET}\" PROPERTY INTERFACE_LINKED_DEPENDENCIES_COLLECTING ON)\r\n    endif()\r\n\r\n    get_target_property(TARGET_TYPE ${TARGET} TYPE)\r\n    get_target_property(LINKED_DEPENDENCIES ${TARGET} INTERFACE_LINKED_DEPENDENCIES)\r\n    set(MODE PUBLIC)\r\n    foreach(ARG ${LINKED_DEPENDENCIES})\r\n      if(ARG IN_LIST MODES)\r\n        set(MODE ${ARG})\r\n        continue()\r\n      endif()\r\n      set(LIBRARY \"${ARG}\")\r\n      if(TARGET ${LIBRARY})\r\n        if(NOT FINALIZING)\r\n          list(APPEND STACK ${LIBRARY})\r\n          continue()\r\n        endif()\r\n\r\n        # When linking two OBJECT libraries together, record the input library objects in\r\n        #   a custom target property \"LINKED_OBJECTS\" together with any other existing ones\r\n        #   from the input library's LINKED_OBJECTS property.\r\n        # Accumulate LINKED_OBJECTS until reaching a non-object target, and add them as\r\n        #   extra sources - this will de-duplicate the list and link it into the target.\r\n        get_target_property(LIBRARY_TYPE ${LIBRARY} TYPE)\r\n\r\n        if(LIBRARY_TYPE STREQUAL \"OBJECT_LIBRARY\")\r\n          if(TARGET_TYPE STREQUAL \"INTERFACE_LIBRARY\")\r\n            message(FATAL_ERROR \"OBJECT to INTERFACE library linking is not supported.\")\r\n          endif()\r\n\r\n          # All transitive dependencies of this object library:\r\n          get_target_property(LIBRARY_LINKED_OBJECTS ${LIBRARY} LINKED_OBJECTS)\r\n          if(LIBRARY_LINKED_OBJECTS STREQUAL \"LIBRARY_LINKED_OBJECTS-NOTFOUND\")\r\n            set(LIBRARY_LINKED_OBJECTS)\r\n          endif()\r\n\r\n          # target_sources deduplicates the list but we also do it here for ease of debugging.\r\n          get_target_property(TARGET_LINKED_OBJECTS ${TARGET} LINKED_OBJECTS)\r\n          if(TARGET_LINKED_OBJECTS STREQUAL \"TARGET_LINKED_OBJECTS-NOTFOUND\")\r\n            set(TARGET_LINKED_OBJECTS)\r\n          endif()\r\n          list(APPEND TARGET_LINKED_OBJECTS ${LIBRARY_LINKED_OBJECTS} $<TARGET_OBJECTS:${LIBRARY}>)\r\n          list(REMOVE_DUPLICATES TARGET_LINKED_OBJECTS)\r\n\r\n          if(TARGET_TYPE STREQUAL \"OBJECT_LIBRARY\")\r\n            set_property(TARGET ${TARGET} PROPERTY LINKED_OBJECTS \"${TARGET_LINKED_OBJECTS}\")\r\n          else()\r\n            target_sources(${TARGET} PRIVATE ${TARGET_LINKED_OBJECTS})\r\n          endif()\r\n        endif()\r\n      endif()\r\n\r\n      if(FINALIZING)\r\n        target_link_libraries(${TARGET} ${MODE} \"${LIBRARY}\")\r\n      endif()\r\n    endforeach()\r\n    if(FINALIZING)\r\n      set_property(TARGET \"${TARGET}\" PROPERTY INTERFACE_LINKED_DEPENDENCIES_COLLECTED ON)\r\n    endif()\r\n  endwhile()\r\nendfunction()\r\n\r\n# Actually resolves the linked dependencies.\r\nfunction(resolve_target_link_dependencies)\r\n  set(MODES PUBLIC PRIVATE INTERFACE)\r\n  get_property(TARGETS GLOBAL PROPERTY TARGETS_WITH_LINKED_DEPENDENCIES)\r\n  foreach(TARGET ${TARGETS})\r\n    _collect_linked_dependencies(\"${TARGET}\" \"\")\r\n  endforeach()\r\n  set_property(GLOBAL PROPERTY TARGETS_WITH_LINKED_DEPENDENCIES)\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/functions/set_relative_file_macro.cmake",
    "content": "# Sets the __FILE__ macro value to be relative to CMAKE_SOURCE_DIR.\r\nfunction(set_relative_file_macro TARGET)\r\n  if(NOT CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n    if((CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12)\r\n        OR (CMAKE_CXX_COMPILER_ID MATCHES \"GNU\" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8))\r\n      target_compile_options(${TARGET} PUBLIC \"-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=\")\r\n    else()\r\n      get_target_property(_srcs ${TARGET} SOURCES)\r\n      foreach(_src ${_srcs})\r\n        set_source_files_properties(${_src} PROPERTIES COMPILE_DEFINITIONS __FILE__=\"${_src}\")\r\n      endforeach()\r\n      target_compile_options(${TARGET} PRIVATE -Wno-builtin-macro-redefined)\r\n    endif()\r\n  endif()\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/functions/trim_retired_files.cmake",
    "content": "set(SCRIPT_CONTENT [=[\r\ninclude(functions/trim_retired_files)\r\ntrim_retired_files(\"${ROOT_FOLDER}\" \"${CURRENT_FILES}\" \"${OUTPUT_FILE}\")\r\n]=])\r\n\r\nfunction(trim_retired_files root_folder current_files output_file)\r\n  file(\r\n    GLOB_RECURSE retired_files\r\n    RELATIVE \"${root_folder}\"\r\n    \"${root_folder}/*\")\r\n\r\n  list(REMOVE_ITEM retired_files ${current_files})\r\n  list(LENGTH retired_files retired_file_count)\r\n  foreach(retired_file ${retired_files})\r\n    file(REMOVE \"${root_folder}/${retired_file}\")\r\n  endforeach()\r\n\r\n  if(${retired_file_count} GREATER 0 OR NOT EXISTS ${output_file})\r\n    file(TOUCH ${output_file})\r\n  endif()\r\nendfunction(trim_retired_files)\r\n\r\nfunction(add_trim_target arg_TARGET_NAME)\r\n  set(oneValueArgs\r\n    ROOT_FOLDER\r\n    BYPRODUCT\r\n    SCRIPT_PATH)\r\n\r\n  set(multiValueArgs CURRENT_FILES)\r\n  cmake_parse_arguments(PARSE_ARGV 0 arg \"\" \"${oneValueArgs}\" \"${multiValueArgs}\")\r\n\r\n  if(NOT arg_ROOT_FOLDER)\r\n    message(FATAL_ERROR \"add_trim_command: missing required parameter ROOT_FOLDER\")\r\n  endif()\r\n  if(NOT arg_OUTPUT OR NOT arg_BYPRODUCT OR NOT arg_SCRIPT_PATH)\r\n    cmake_path(GET arg_ROOT_FOLDER FILENAME root_filename)\r\n    if(NOT arg_BYPRODUCT)\r\n      set(arg_BYPRODUCT \"${CMAKE_CURRENT_BINARY_DIR}/${root_filename}.rm\")\r\n    endif()\r\n    if(NOT arg_SCRIPT_PATH)\r\n      get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)\r\n      if(is_multi_config)\r\n        set(arg_SCRIPT_PATH \"${CMAKE_CURRENT_BINARY_DIR}/${root_filename}_$<CONFIG>.cmake\")\r\n      else()\r\n        set(arg_SCRIPT_PATH \"${CMAKE_CURRENT_BINARY_DIR}/${root_filename}.cmake\")\r\n      endif()\r\n    endif()\r\n  endif()\r\n\r\n  file(GENERATE OUTPUT \"${arg_SCRIPT_PATH}\" CONTENT \"${SCRIPT_CONTENT}\")\r\n  add_custom_target(\"${arg_TARGET_NAME}\"\r\n    COMMENT \"Trimming ${arg_ROOT_FOLDER}\"\r\n    BYPRODUCTS \"${arg_BYPRODUCT}\"\r\n    COMMAND ${CMAKE_COMMAND}\r\n      -D \"CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}\"\r\n      -D \"ROOT_FOLDER=${arg_ROOT_FOLDER}\"\r\n      -D \"CURRENT_FILES=${arg_CURRENT_FILES}\"\r\n      -D \"OUTPUT_FILE=${arg_BYPRODUCT}\"\r\n      -P \"${arg_SCRIPT_PATH}\"\r\n    VERBATIM)\r\n\r\n  set(TRIM_COMMAND_BYPRODUCT \"${arg_BYPRODUCT}\" PARENT_SCOPE)\r\nendfunction(add_trim_target)\r\n"
  },
  {
    "path": "CMake/platforms/.editorconfig",
    "content": "[ios.toolchain.cmake]\r\nend_of_line = lf\r\n"
  },
  {
    "path": "CMake/platforms/aarch64-linux-gnu-clang-static-libc++.toolchain.cmake",
    "content": "set(CMAKE_SYSTEM_NAME Linux)\r\nset(CMAKE_SYSTEM_PROCESSOR aarch64)\r\n\r\nset(triple aarch64-linux-gnu)\r\n\r\nset(CMAKE_C_COMPILER \"/usr/bin/clang\")\r\nset(CMAKE_C_COMPILER_TARGET \"${triple}\")\r\nset(CMAKE_CXX_COMPILER \"/usr/bin/clang++\")\r\nset(CMAKE_CXX_FLAGS_INIT \"-stdlib=libc++\")\r\nset(CMAKE_CXX_COMPILER_TARGET \"${triple}\")\r\nset(CMAKE_ASM_COMPILER \"/usr/bin/clang\")\r\nset(CMAKE_ASM_COMPILER_TARGET \"${triple}\")\r\nset(CMAKE_EXE_LINKER_FLAGS_INIT \"-fuse-ld=/usr/bin/ld.lld -static-libstdc++ -static-libgcc\")\r\n\r\nset(CMAKE_FIND_ROOT_PATH \"/usr/aarch64-linux-gnu;/usr\")\r\nset(CMAKE_LIBRARY_ARCHITECTURE \"${triple}\")\r\n\r\nset(CMAKE_STRIP \"/usr/bin/aarch64-linux-gnu-strip\")\r\nset(PKG_CONFIG_EXECUTABLE \"${CMAKE_CURRENT_LIST_DIR}/aarch64-linux-gnu-pkg-config\" CACHE STRING \"Path to pkg-config\")\r\n\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\n\r\nset(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)\r\n\r\nset(CPACK_DEBIAN_PACKAGE_ARCHITECTURE arm64)\r\n"
  },
  {
    "path": "CMake/platforms/aarch64-linux-gnu.toolchain.cmake",
    "content": "set(CMAKE_SYSTEM_NAME Linux)\r\nset(CMAKE_SYSTEM_PROCESSOR aarch64)\r\n\r\nset(CMAKE_C_COMPILER \"/usr/bin/aarch64-linux-gnu-gcc\")\r\nset(CMAKE_CXX_COMPILER \"/usr/bin/aarch64-linux-gnu-g++\")\r\n\r\nset(CMAKE_FIND_ROOT_PATH \"/usr/aarch64-linux-gnu;/usr\")\r\nset(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu)\r\n\r\nset(CMAKE_STRIP \"/usr/bin/aarch64-linux-gnu-strip\")\r\nset(PKG_CONFIG_EXECUTABLE \"${CMAKE_CURRENT_LIST_DIR}/aarch64-linux-gnu-pkg-config\" CACHE STRING \"Path to pkg-config\")\r\n\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\n\r\nset(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)\r\n\r\nset(CPACK_DEBIAN_PACKAGE_ARCHITECTURE arm64)\r\n"
  },
  {
    "path": "CMake/platforms/amiga.cmake",
    "content": "set(BUILD_TESTING OFF)\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(NONET ON)\r\nset(USE_SDL1 ON)\r\nset(SDL1_VIDEO_MODE_BPP 8)\r\n\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\nset(DEVILUTIONX_SYSTEM_ZLIB OFF)\r\n\r\n# Lower the optimization level to O2 because there are issues with O3.\r\nset(CMAKE_C_FLAGS_RELEASE \"${CMAKE_C_FLAGS_RELEASE} -O2\")\r\nset(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} -O2\")\r\n\r\n# `fseeko` fails to link on Amiga.\r\nadd_definitions(-Dfseeko=fseek)\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES ZLIB::ZLIB)\r\nif(NOT WARPOS)\r\n  list(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES -ldebug)\r\nendif()\r\n\r\nfile(COPY \"${CMAKE_CURRENT_SOURCE_DIR}/Packaging/amiga/devilutionx.info\" DESTINATION \"${CMAKE_CURRENT_BINARY_DIR}\")\r\n"
  },
  {
    "path": "CMake/platforms/android.cmake",
    "content": "# General build options.\r\nset(BUILD_TESTING OFF)\r\n\r\n# Disable all system dependencies.\r\n# All of these will be fetched via FetchContent and linked statically.\r\nset(DEVILUTIONX_SYSTEM_SDL2 OFF)\r\n\r\n# JNI source directory\r\nlist(APPEND DEVILUTIONX_PLATFORM_SUBDIRECTORIES platform/android)\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES libdevilutionx_android)\r\n\r\n# Static SDL2 on Android requires Position Independent Code.\r\nset(SDL_STATIC_PIC ON)\r\n\r\nset(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\nset(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBPNG OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\n\r\n# Package the assets with the APK.\r\nset(BUILD_ASSETS_MPQ OFF)\r\nset(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}/android-project/app/src/main/assets\")\r\n\r\n# Disable sanitizers. They're not supported out-of-the-box.\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\n\r\n# Disable in-game options to exit the game.\r\nset(NOEXIT ON)\r\n"
  },
  {
    "path": "CMake/platforms/cpigamesh.cmake",
    "content": "set(BUILD_TESTING OFF)\r\nset(NONET ON)\r\nset(PREFILL_PLAYER_NAME ON)\r\nset(HAS_KBCTRL 1)\r\nset(LTO ON)\r\nset(DIST ON)\r\nset(DEBUG OFF)\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT)\r\nset(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT)\r\nset(KBCTRL_BUTTON_DPAD_UP SDLK_UP)\r\nset(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN)\r\nset(KBCTRL_BUTTON_X SDLK_i)\r\nset(KBCTRL_BUTTON_Y SDLK_u)\r\nset(KBCTRL_BUTTON_B SDLK_k)\r\nset(KBCTRL_BUTTON_A SDLK_j)\r\nset(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_l)\r\nset(KBCTRL_BUTTON_LEFTSHOULDER SDLK_h)\r\nset(KBCTRL_BUTTON_AXIS_TRIGGERLEFT SDLK_y)\r\nset(KBCTRL_BUTTON_AXIS_TRIGGERRIGHT SDLK_o)\r\nset(KBCTRL_BUTTON_LEFTSTICK SDLK_PAGEUP)\r\nset(KBCTRL_BUTTON_RIGHTSTICK SDLK_PAGEDOWN)\r\nset(KBCTRL_BUTTON_START SDLK_RETURN)\r\nset(KBCTRL_BUTTON_BACK SDLK_SPACE)\r\n\r\nset(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} -O3\")\r\n"
  },
  {
    "path": "CMake/platforms/ctr/Tools3DS.cmake",
    "content": "############################################################################\r\n# Various macros for 3DS homebrews tools\r\n#\r\n# add_3dsx_target\r\n# ^^^^^^^^^^^^^^^\r\n#\r\n# This macro has two signatures :\r\n#\r\n# ## add_3dsx_target(target [NO_SMDH])\r\n#\r\n# Adds a target that generates a .3dsx file from `target`. If NO_SMDH is specified, no .smdh file will be generated.\r\n#\r\n# You can set the following variables to change the SMDH file :\r\n#\r\n# * APP_TITLE is the name of the app stored in the SMDH file (Optional)\r\n# * APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)\r\n# * APP_AUTHOR is the author of the app stored in the SMDH file (Optional)\r\n# * APP_ICON is the filename of the icon (.png), relative to the project folder.\r\n#   If not set, it attempts to use one of the following (in this order):\r\n#     - $(target).png\r\n#     - icon.png\r\n#     - $(libctru folder)/default_icon.png\r\n#\r\n# ## add_3dsx_target(target APP_TITLE APP_DESCRIPTION APP_AUTHOR [APP_ICON])\r\n#\r\n# This version will produce the SMDH with tha values passed as arguments. Tha APP_ICON is optional and follows the same rule as the other version of `add_3dsx_target`.\r\n#\r\n# add_cia_target(target RSF IMAGE SOUND [APP_TITLE APP_DESCRIPTION APP_AUTHOR [APP_ICON]])\r\n# ^^^^^^^^^^^^^^\r\n#\r\n# Same as add_3dsx_target but for CIA files.\r\n#\r\n# RSF is the .rsf file to be given to makerom.\r\n# IMAGE is either a .png or a cgfximage file.\r\n# SOUND is either a .wav or a cwavaudio file.\r\n#\r\n# add_netload_target(name target_or_file)\r\n# ^^^^^^^^^^^^^^^^^^\r\n#\r\n# Adds a target `name` that sends a .3dsx using the homebrew launcher netload system (3dslink).\r\n# target_or_file is either the name of a target or of file.\r\n#\r\n# add_binary_library(target input1 [input2 ...])\r\n# ^^^^^^^^^^^^^^^^^^\r\n#\r\n#    /!\\ Requires ASM to be enabled ( `enable_language(ASM)` or `project(yourprojectname C CXX ASM)`)\r\n#\r\n# Converts the files given as input to arrays of their binary data. This is useful to embed resources into your project.\r\n# For example, logo.bmp will generate the array `u8 logo_bmp[]` and its size `logo_bmp_size`. By linking this library, you\r\n# will also have access to a generated header file called `logo_bmp.h` which contains the declarations you need to use it.\r\n#\r\n#   Note : All dots in the filename are converted to `_`, and if it starts with a number, `_` will be prepended.\r\n#   For example 8x8.gas.tex would give the name _8x8_gas_tex.\r\n#\r\n# target_embed_file(target input1 [input2 ...])\r\n# ^^^^^^^^^^^^^^^^^\r\n#\r\n# Same as add_binary_library(tempbinlib input1 [input2 ...]) + target_link_libraries(target tempbinlib)\r\n#\r\n# add_shbin(output input [entrypoint] [shader_type])\r\n# ^^^^^^^^^^^^^^^^^^^^^^^\r\n#\r\n# Assembles the shader given as `input` into the file `output`. No file extension is added.\r\n# You can choose the shader assembler by setting SHADER_AS to `picasso` or `nihstro`.\r\n#\r\n# If `nihstro` is set as the assembler, entrypoint and shader_type will be used.\r\n# entrypoint is set to `main` by default\r\n# shader_type can be either VSHADER or GSHADER. By default it is VSHADER.\r\n#\r\n# generate_shbins(input1 [input2 ...])\r\n# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n#\r\n# Assemble all the shader files given as input into .shbin files. Those will be located in the folder `shaders` of the build directory.\r\n# The names of the output files will be <name of input without longest extension>.shbin. vshader.pica will output shader.shbin but shader.vertex.pica will output shader.shbin too.\r\n#\r\n# add_shbin_library(target input1 [input2 ...])\r\n# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n#\r\n#    /!\\ Requires ASM to be enabled ( `enable_language(ASM)` or `project(yourprojectname C CXX ASM)`)\r\n#\r\n# This is the same as calling generate_shbins and add_binary_library. This is the function to be used to reproduce devkitArm makefiles behaviour.\r\n# For example, add_shbin_library(shaders data/my1stshader.vsh.pica) will generate the target library `shaders` and you\r\n# will be able to use the shbin in your program by linking it, including `my1stshader_pica.h` and using `my1stshader_pica[]` and `my1stshader_pica_size`.\r\n#\r\n# target_embed_shader(target input1 [input2 ...])\r\n# ^^^^^^^^^^^^^^^^^\r\n#\r\n# Same as add_shbin_library(tempbinlib input1 [input2 ...]) + target_link_libraries(target tempbinlib)\r\n#\r\n############################################################################\r\n\r\nif(NOT NINTENDO_3DS)\r\n    message(WARNING \"Those tools can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.\")\r\nendif()\r\n\r\nget_filename_component(__tools3dsdir ${CMAKE_CURRENT_LIST_FILE} PATH) # Used to locate files to be used with configure_file\r\n\r\nmessage(STATUS \"Looking for 3ds tools...\")\r\n\r\n##############\r\n## 3DSXTOOL ##\r\n##############\r\nif(NOT _3DSXTOOL)\r\n    # message(STATUS \"Looking for 3dsxtool...\")\r\n    find_program(_3DSXTOOL 3dsxtool ${DEVKITPRO}/tools/bin)\r\n    if(_3DSXTOOL)\r\n        message(STATUS \"3dsxtool: ${_3DSXTOOL} - found\")\r\n    else()\r\n        message(WARNING \"3dsxtool - not found\")\r\n    endif()\r\nendif()\r\n\r\n\r\n##############\r\n## SMDHTOOL ##\r\n##############\r\nif(NOT SMDHTOOL)\r\n    # message(STATUS \"Looking for smdhtool...\")\r\n    find_program(SMDHTOOL smdhtool ${DEVKITPRO}/tools/bin)\r\n    if(SMDHTOOL)\r\n        message(STATUS \"smdhtool: ${SMDHTOOL} - found\")\r\n    else()\r\n        message(WARNING \"smdhtool - not found\")\r\n    endif()\r\nendif()\r\n\r\n################\r\n## BANNERTOOL ##\r\n################\r\nif(NOT BANNERTOOL)\r\n    # message(STATUS \"Looking for bannertool...\")\r\n    find_program(BANNERTOOL bannertool ${DEVKITPRO}/tools/bin /usr/local/bin)\r\n    if(BANNERTOOL)\r\n        message(STATUS \"bannertool: ${BANNERTOOL} - found\")\r\n    else()\r\n        message(WARNING \"bannertool - not found\")\r\n    endif()\r\nendif()\r\n\r\nset(FORCE_SMDHTOOL FALSE CACHE BOOL \"Force the use of smdhtool instead of bannertool\")\r\n\r\n#############\r\n## MAKEROM ##\r\n#############\r\nif(NOT MAKEROM)\r\n    # message(STATUS \"Looking for makerom...\")\r\n    find_program(MAKEROM makerom ${DEVKITPRO}/tools/bin /usr/local/bin)\r\n    if(MAKEROM)\r\n        message(STATUS \"makerom: ${MAKEROM} - found\")\r\n    else()\r\n        message(WARNING \"makerom - not found\")\r\n    endif()\r\nendif()\r\n\r\n\r\n\r\n#############\r\n##  STRIP  ##\r\n#############\r\nif(NOT STRIP)\r\n    # message(STATUS \"Looking for strip...\")\r\n    find_program(STRIP arm-none-eabi-strip ${DEVKITARM}/bin)\r\n    if(STRIP)\r\n        message(STATUS \"strip: ${STRIP} - found\")\r\n    else()\r\n        message(WARNING \"strip - not found\")\r\n    endif()\r\nendif()\r\n\r\n\r\n\r\n#############\r\n##  BIN2S  ##\r\n#############\r\nif(NOT BIN2S)\r\n    # message(STATUS \"Looking for bin2s...\")\r\n    find_program(BIN2S bin2s ${DEVKITPRO}/tools/bin)\r\n    if(BIN2S)\r\n        message(STATUS \"bin2s: ${BIN2S} - found\")\r\n    else()\r\n        message(WARNING \"bin2s - not found\")\r\n    endif()\r\nendif()\r\n\r\n###############\r\n##  3DSLINK  ##\r\n###############\r\nif(NOT _3DSLINK)\r\n    # message(STATUS \"Looking for 3dslink...\")\r\n    find_program(_3DSLINK 3dslink ${DEVKITPRO}/tools/bin)\r\n    if(_3DSLINK)\r\n        message(STATUS \"3dslink: ${_3DSLINK} - found\")\r\n    else()\r\n        message(WARNING \"3dslink - not found\")\r\n    endif()\r\nendif()\r\n\r\n#############\r\n## PICASSO ##\r\n#############\r\nif(NOT PICASSO_EXE)\r\n    # message(STATUS \"Looking for Picasso...\")\r\n    find_program(PICASSO_EXE picasso ${DEVKITPRO}/tools/bin)\r\n    if(PICASSO_EXE)\r\n        message(STATUS \"Picasso: ${PICASSO_EXE} - found\")\r\n        set(SHADER_AS picasso CACHE STRING \"The shader assembler to be used. Allowed values are 'none', 'picasso' or 'nihstro'\")\r\n    else()\r\n        message(STATUS \"Picasso - not found\")\r\n    endif()\r\nendif()\r\n\r\n\r\n#############\r\n## NIHSTRO ##\r\n#############\r\n\r\nif(NOT NIHSTRO_AS)\r\n    # message(STATUS \"Looking for nihstro...\")\r\n    find_program(NIHSTRO_AS nihstro ${DEVKITPRO}/tools/bin)\r\n    if(NIHSTRO_AS)\r\n        message(STATUS \"nihstro: ${NIHSTRO_AS} - found\")\r\n        set(SHADER_AS nihstro CACHE STRING \"The shader assembler to be used. Allowed values are 'none', 'picasso' or 'nihstro'\")\r\n    else()\r\n        message(STATUS \"nihstro - not found\")\r\n    endif()\r\nendif()\r\n\r\nset(SHADER_AS none CACHE STRING \"The shader assembler to be used. Allowed values are 'none', 'picasso' or 'nihstro'\")\r\n\r\n###############################\r\n###############################\r\n########    MACROS    #########\r\n###############################\r\n###############################\r\n\r\n\r\n###################\r\n### EXECUTABLES ###\r\n###################\r\n\r\n\r\nfunction(__add_smdh target APP_TITLE APP_DESCRIPTION APP_AUTHOR APP_ICON)\r\n    if(BANNERTOOL AND NOT FORCE_SMDHTOOL)\r\n        set(__SMDH_COMMAND ${BANNERTOOL} makesmdh -s ${APP_TITLE} -l ${APP_DESCRIPTION}  -p ${APP_AUTHOR} -i ${APP_ICON} -o ${CMAKE_CURRENT_BINARY_DIR}/${target})\r\n    else()\r\n        set(__SMDH_COMMAND ${SMDHTOOL} --create ${APP_TITLE} ${APP_DESCRIPTION} ${APP_AUTHOR} ${APP_ICON} ${CMAKE_CURRENT_BINARY_DIR}/${target})\r\n    endif()\r\n    add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}\r\n                        COMMAND ${__SMDH_COMMAND}\r\n                        WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}\r\n                        DEPENDS ${APP_ICON}\r\n                        VERBATIM\r\n    )\r\nendfunction()\r\n\r\nfunction(add_3dsx_target target)\r\n    get_filename_component(target_we ${target} NAME_WE)\r\n    if((NOT (${ARGC} GREATER 1 AND \"${ARGV1}\" STREQUAL \"NO_SMDH\") ) OR (${ARGC} GREATER 3) )\r\n        if(${ARGC} GREATER 3)\r\n            set(APP_TITLE ${ARGV1})\r\n            set(APP_DESCRIPTION ${ARGV2})\r\n            set(APP_AUTHOR ${ARGV3})\r\n        endif()\r\n        if(${ARGC} EQUAL 5)\r\n            set(APP_ICON ${ARGV4})\r\n        endif()\r\n        if(NOT APP_TITLE)\r\n            set(APP_TITLE ${target})\r\n        endif()\r\n        if(NOT APP_DESCRIPTION)\r\n            set(APP_DESCRIPTION \"Built with devkitARM & libctru\")\r\n        endif()\r\n        if(NOT APP_AUTHOR)\r\n            set(APP_AUTHOR \"Unspecified Author\")\r\n        endif()\r\n        if(NOT APP_ICON)\r\n            if(EXISTS ${target}.png)\r\n                set(APP_ICON ${target}.png)\r\n            elseif(EXISTS icon.png)\r\n                set(APP_ICON icon.png)\r\n            elseif(CTRULIB)\r\n                set(APP_ICON ${CTRULIB}/default_icon.png)\r\n            else()\r\n                message(FATAL_ERROR \"No icon found ! Please use NO_SMDH or provide some icon.\")\r\n            endif()\r\n        endif()\r\n        if( NOT ${target_we}.smdh)\r\n            __add_smdh(${target_we}.smdh ${APP_TITLE} ${APP_DESCRIPTION} ${APP_AUTHOR} ${APP_ICON})\r\n        endif()\r\n        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx\r\n                        COMMAND ${_3DSXTOOL} $<TARGET_FILE:${target}> ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx --smdh=${CMAKE_CURRENT_BINARY_DIR}/${target_we}.smdh --romfs=${CMAKE_CURRENT_BINARY_DIR}/romfs\r\n                        DEPENDS ${target} ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.smdh\r\n                        VERBATIM\r\n        )\r\n    else()\r\n        message(STATUS \"No smdh file will be generated\")\r\n        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx\r\n                        COMMAND ${_3DSXTOOL} $<TARGET_FILE:${target}> ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx --romfs=${CMAKE_CURRENT_BINARY_DIR}/romfs\r\n                        DEPENDS ${target}\r\n                        VERBATIM\r\n        )\r\n    endif()\r\n    add_custom_target(${target_we}_3dsx ALL SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx)\r\n    #set_target_properties(${target} PROPERTIES LINK_FLAGS \"-specs=3dsx.specs\")\r\nendfunction()\r\n\r\nfunction(__add_ncch_banner target IMAGE SOUND)\r\n    if(IMAGE MATCHES \".*\\\\.png$\")\r\n        set(IMG_PARAM -i ${IMAGE})\r\n    else()\r\n        set(IMG_PARAM -ci ${IMAGE})\r\n    endif()\r\n    if(SOUND MATCHES \".*\\\\.wav$\")\r\n        set(SND_PARAM -a ${SOUND})\r\n    else()\r\n        set(SND_PARAM -ca ${SOUND})\r\n    endif()\r\n    add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}\r\n                        COMMAND ${BANNERTOOL} makebanner -o ${CMAKE_CURRENT_BINARY_DIR}/${target} ${IMG_PARAM} ${SND_PARAM}\r\n                        WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}\r\n                        DEPENDS ${IMAGE} ${SOUND}\r\n                        VERBATIM\r\n    )\r\nendfunction()\r\n\r\nfunction(add_cia_target target RSF IMAGE SOUND)\r\n    get_filename_component(target_we ${target} NAME_WE)\r\n    if(${ARGC} GREATER 6)\r\n        set(APP_TITLE ${ARGV4})\r\n        set(APP_DESCRIPTION ${ARGV5})\r\n        set(APP_AUTHOR ${ARGV6})\r\n    endif()\r\n    if(${ARGC} EQUAL 8)\r\n        set(APP_ICON ${ARGV7})\r\n    endif()\r\n    if(NOT APP_TITLE)\r\n        set(APP_TITLE ${target})\r\n    endif()\r\n    if(NOT APP_DESCRIPTION)\r\n        set(APP_DESCRIPTION \"Built with devkitARM & libctru\")\r\n    endif()\r\n    if(NOT APP_AUTHOR)\r\n        set(APP_AUTHOR \"Unspecified Author\")\r\n    endif()\r\n    if(NOT APP_ICON)\r\n        if(EXISTS ${target}.png)\r\n            set(APP_ICON ${target}.png)\r\n        elseif(EXISTS icon.png)\r\n            set(APP_ICON icon.png)\r\n        elseif(CTRULIB)\r\n            set(APP_ICON ${CTRULIB}/default_icon.png)\r\n        else()\r\n            message(FATAL_ERROR \"No icon found ! Please use NO_SMDH or provide some icon.\")\r\n        endif()\r\n    endif()\r\n    if( NOT ${target_we}.smdh)\r\n        __add_smdh(${target_we}.smdh ${APP_TITLE} ${APP_DESCRIPTION} ${APP_AUTHOR} ${APP_ICON})\r\n    endif()\r\n    __add_ncch_banner(${target_we}.bnr ${IMAGE} ${SOUND})\r\n    add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.cia\r\n                        COMMAND ${STRIP} -o $<TARGET_FILE:${target}>-stripped $<TARGET_FILE:${target}>\r\n                        COMMAND ${MAKEROM}     -f cia\r\n                                            -target t\r\n                                            -exefslogo\r\n                                            -o ${target_we}.cia\r\n                                            -elf $<TARGET_FILE:${target}>-stripped\r\n                                            -rsf ${RSF}\r\n                                            -banner ${target_we}.bnr\r\n                                            -icon ${target_we}.smdh\r\n                        DEPENDS ${target} ${RSF} ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.bnr ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.smdh\r\n                        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}\r\n                        VERBATIM\r\n    )\r\n\r\n    add_custom_target(${target_we}_cia ALL SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.cia)\r\n    #set_target_properties(${target} PROPERTIES LINK_FLAGS \"-specs=3dsx.specs\")\r\nendfunction()\r\n\r\nmacro(add_netload_target name target)\r\n    set(NETLOAD_IP \"\" CACHE STRING \"The ip address of the 3ds when using netload.\")\r\n    if(NETLOAD_IP)\r\n        set(__NETLOAD_IP_OPTION -a ${NETLOAD_IP})\r\n    endif()\r\n    if(NOT TARGET ${target})\r\n        message(\"NOT ${target}\")\r\n        set(FILE ${target})\r\n    else()\r\n        set(FILE ${CMAKE_CURRENT_BINARY_DIR}/${target}.3dsx)\r\n    endif()\r\n    add_custom_target(${name}\r\n                    COMMAND ${_3DSLINK} ${FILE} ${__NETLOAD_IP_OPTION}\r\n                    DEPENDS  ${FILE}\r\n    )\r\nendmacro()\r\n\r\n######################\r\n### File embedding ###\r\n######################\r\n\r\nmacro(add_binary_library libtarget)\r\n    if(NOT ${ARGC} GREATER 1)\r\n        message(FATAL_ERROR \"add_binary_library : Argument error (no input files)\")\r\n    endif()\r\n    get_cmake_property(ENABLED_LANGUAGES ENABLED_LANGUAGES)\r\n    if(NOT ENABLED_LANGUAGES MATCHES \".*ASM.*\")\r\n        message(FATAL_ERROR \"You have to enable ASM in order to use add_binary_library (or any target_embed_* which relies on it). Use enable_language(ASM) in your CMakeLists. Currently enabled languages are ${ENABLED_LANGUAGES}\")\r\n    endif()\r\n\r\n\r\n    foreach(__file ${ARGN})\r\n        get_filename_component(__file_wd ${__file} NAME)\r\n        string(REGEX REPLACE \"^([0-9])\" \"_\\\\1\" __BIN_FILE_NAME ${__file_wd}) # add '_' if the file name starts by a number\r\n        string(REGEX REPLACE \"[-./]\" \"_\" __BIN_FILE_NAME ${__BIN_FILE_NAME})\r\n\r\n        #Generate the header file\r\n        configure_file(${__tools3dsdir}/bin2s_header.h.in ${CMAKE_CURRENT_BINARY_DIR}/${libtarget}_include/${__BIN_FILE_NAME}.h)\r\n    endforeach()\r\n\r\n    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm)\r\n    # Generate the assembly file, and create the new target\r\n    add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm/${libtarget}.s\r\n                        COMMAND ${BIN2S} ${ARGN} > ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm/${libtarget}.s\r\n                        DEPENDS ${ARGN}\r\n                        WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}\r\n    )\r\n\r\n    add_library(${libtarget} ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm/${libtarget}.s)\r\n    target_include_directories(${libtarget} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/${libtarget}_include)\r\nendmacro()\r\n\r\nmacro(target_embed_file _target)\r\n    if(NOT ${ARGC} GREATER 1)\r\n        message(FATAL_ERROR \"target_embed_file : Argument error (no input files)\")\r\n    endif()\r\n    get_filename_component(__1st_file_wd ${ARGV1} NAME)\r\n    add_binary_library(__${_target}_embed_${__1st_file_wd} ${ARGN})\r\n    target_link_libraries(${_target} __${_target}_embed_${__1st_file_wd})\r\nendmacro()\r\n\r\n###################\r\n##### SHADERS #####\r\n###################\r\n\r\nmacro(add_shbin OUTPUT INPUT )\r\n\r\n    if(SHADER_AS STREQUAL \"picasso\")\r\n\r\n        if(${ARGC} GREATER 2)\r\n            message(WARNING \"Picasso doesn't support changing the entrypoint or shader type\")\r\n        endif()\r\n        add_custom_command(OUTPUT ${OUTPUT} COMMAND ${PICASSO_EXE} -o ${OUTPUT} ${INPUT} WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})\r\n\r\n    elseif(SHADER_AS STREQUAL \"nihstro\")\r\n        if(NOT NIHSTRO_AS)\r\n            message(SEND_ERROR \"SHADER_AS is set to nihstro, but nihstro wasn't found. Please set NIHSTRO_AS.\")\r\n        endif()\r\n        if(${ARGC} GREATER 2)\r\n            if(${ARGV2} EQUAL GSHADER)\r\n                set(SHADER_TYPE_FLAG \"-g\")\r\n            elseif(NOT ${ARGV2} EQUAL VSHADER)\r\n                set(_ENTRYPOINT ${ARGV2})\r\n            endif()\r\n        endif()\r\n        if(${ARGC} GREATER 3)\r\n            if(${ARGV2} EQUAL GSHADER)\r\n                set(SHADER_TYPE_FLAG \"-g\")\r\n            elseif(NOT ${ARGV3} EQUAL VSHADER)\r\n                set(_ENTRYPOINT ${ARGV3})\r\n            endif()\r\n        endif()\r\n        if(NOT _ENTRYPOINT)\r\n            set(_ENTRYPOINT \"main\")\r\n        endif()\r\n        add_custom_command(OUTPUT ${OUTPUT} COMMAND ${NIHSTRO_AS} ${INPUT} -o ${OUTPUT} -e ${_ENTRYPOINT} ${SHADER_TYPE_FLAG} WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})\r\n\r\n    else()\r\n        message(FATAL_ERROR \"Please set SHADER_AS to 'picasso' or 'nihstro' if you use the shbin feature.\")\r\n    endif()\r\n\r\nendmacro()\r\n\r\nfunction(generate_shbins)\r\n    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/shaders)\r\n    foreach(__shader_file ${ARGN})\r\n        get_filename_component(__shader_file_we ${__shader_file} NAME_WE)\r\n        #Generate the shbin file\r\n        list(APPEND __SHADERS_BIN_FILES ${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin)\r\n        add_shbin(${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin ${__shader_file})\r\n    endforeach()\r\nendfunction()\r\n\r\nfunction(add_shbin_library libtarget)\r\n    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/shaders)\r\n    foreach(__shader_file ${ARGN})\r\n        get_filename_component(__shader_file_we ${__shader_file} NAME_WE)\r\n        #Generate the shbin file\r\n        list(APPEND __SHADERS_BIN_FILES ${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin)\r\n        add_shbin(${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin ${__shader_file})\r\n    endforeach()\r\n    add_binary_library(${libtarget} ${__SHADERS_BIN_FILES})\r\nendfunction()\r\n\r\n\r\nmacro(target_embed_shader _target)\r\n    if(NOT ${ARGC} GREATER 1)\r\n        message(FATAL_ERROR \"target_embed_shader : Argument error (no input files)\")\r\n    endif()\r\n    get_filename_component(__1st_file_wd ${ARGV1} NAME)\r\n    add_shbin_library(__${_target}_embed_${__1st_file_wd} ${ARGN})\r\n    target_link_libraries(${_target} __${_target}_embed_${__1st_file_wd})\r\nendmacro()\r\n"
  },
  {
    "path": "CMake/platforms/ctr/asio_defs.cmake",
    "content": "target_compile_definitions(asio INTERFACE\r\n  ASIO_DISABLE_THREADS=ON\r\n  ASIO_HAS_UNISTD_H=ON)\r\n\r\n# Missing headers and declarations provided by DevilutionX\r\ntarget_include_directories(asio BEFORE INTERFACE ${PROJECT_SOURCE_DIR}/Source/platform/ctr/asio/include)\r\n"
  },
  {
    "path": "CMake/platforms/ctr/bin2s_header.h.in",
    "content": "extern const u8 @__BIN_FILE_NAME@_end[];\nextern const u8 @__BIN_FILE_NAME@[];\nextern const u32 @__BIN_FILE_NAME@_size;\n"
  },
  {
    "path": "CMake/platforms/ctr/modules/FindCITRO3D.cmake",
    "content": "# - Try to find citro3d\r\n# You can set CITRO3D_ROOT to specify a certain directory to look in first.\r\n# Once done this will define\r\n#  CITRO3D_FOUND - System has citro3d\r\n#  CITRO3D_INCLUDE_DIRS - The citro3d include directories\r\n#  CITRO3D_LIBRARIES - The libraries needed to use citro3d\r\n# Unless we are unable to find CTRULIB\r\n# It also adds an imported target named `3ds::citro3d`, Linking against it is\r\n# equivalent to:\r\n# target_link_libraries(mytarget ${CITRO3D_LIBRARIES})\r\n# target_include_directories(mytarget PRIVATE ${CITRO3D_INCLUDE_DIRS})\r\n\r\nif(NOT NINTENDO_3DS)\r\n    message(FATAL_ERROR \"This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.\")\r\nendif()\r\n\r\nif(CITRO3D_INCLUDE_DIR)\r\n    # Already in cache, be silent\r\n    set(CITRO3D_FIND_QUIETLY TRUE)\r\nendif(CITRO3D_INCLUDE_DIR)\r\n\r\ninclude(LibFindMacros)\r\ninclude(try_add_imported_target)\r\n\r\n# citro3d requires ctrulib\r\nlibfind_package(CITRO3D CTRULIB)\r\n\r\nset(_CITRO3D_SEARCHES)\r\n\r\n# Search CITRO3D_ROOT first if it is set.\r\nif(CITRO3D_ROOT)\r\n  set(_CITRO3D_SEARCH_ROOT\r\n    PATHS ${CITRO3D_ROOT}\r\n    NO_DEFAULT_PATH\r\n    NO_CMAKE_FIND_ROOT_PATH)\r\n  list(APPEND _CITRO3D_SEARCHES _CITRO3D_SEARCH_ROOT)\r\nendif()\r\n\r\n# Search below ${DEVKITPRO}, ${DEVKITARM} etc.\r\nset(_CITRO3D_SEARCH_CMAKE_REROOTED\r\n  PATHS / /citro3d /libctru /ctrulib\r\n  NO_DEFAULT_PATH\r\n  ONLY_CMAKE_FIND_ROOT_PATH)\r\nlist(APPEND _CITRO3D_SEARCHES _CITRO3D_SEARCH_CMAKE_REROOTED)\r\n\r\nset(_CITRO3D_SEARCH_NORMAL NO_CMAKE_FIND_ROOT_PATH)\r\nlist(APPEND _CITRO3D_SEARCHES _CITRO3D_SEARCH_NORMAL)\r\n\r\nforeach(search ${_CITRO3D_SEARCHES})\r\n  find_path(CITRO3D_INCLUDE_DIR NAMES citro3d.h\r\n    ${${search}}\r\n    PATH_SUFFIXES include)\r\n  find_library(CITRO3D_LIBRARY NAMES citro3d libcitro3d.a\r\n    ${${search}}\r\n    PATH_SUFFIXES lib)\r\nendforeach()\r\n\r\n#find_library(LIBM_LIBRARY NAMES m libm.a\r\n#  PATHS / /arm-none-eabi\r\n#  PATH_SUFFIXES lib/armv6k/fpu)\r\n\r\nset(LIBM_LIBRARY m)\r\n\r\nset(CITRO3D_PROCESS_INCLUDES CITRO3D_INCLUDE_DIR)\r\nset(CITRO3D_PROCESS_LIBS CITRO3D_LIBRARY LIBM_LIBRARY)\r\n\r\nlibfind_process(CITRO3D)\r\n\r\ntry_add_imported_target(CITRO3D m 3ds::ctrulib)\r\n"
  },
  {
    "path": "CMake/platforms/ctr/modules/FindCTRULIB.cmake",
    "content": "# - Try to find ctrulib\r\n# Once done this will define\r\n#  LIBCTRU_FOUND - System has ctrulib\r\n#  LIBCTRU_INCLUDE_DIRS - The ctrulib include directories\r\n#  LIBCTRU_LIBRARIES - The libraries needed to use ctrulib\r\n#\r\n# It also adds an imported target named `3ds::ctrulib`.\r\n# Linking it is the same as target_link_libraries(target ${LIBCTRU_LIBRARIES}) and target_include_directories(target ${LIBCTRU_INCLUDE_DIRS})\r\n\r\n# DevkitPro paths are broken on windows, so we have to fix those\r\nmacro(msys_to_cmake_path MsysPath ResultingPath)\r\n    string(REGEX REPLACE \"^/([a-zA-Z])/\" \"\\\\1:/\" ${ResultingPath} \"${MsysPath}\")\r\nendmacro()\r\n\r\nif(NOT DEVKITPRO)\r\n    msys_to_cmake_path(\"$ENV{DEVKITPRO}\" DEVKITPRO)\r\nendif()\r\n\r\nset(CTRULIB_PATHS $ENV{CTRULIB} libctru ctrulib ${DEVKITPRO}/libctru ${DEVKITPRO}/ctrulib)\r\n\r\nfind_path(LIBCTRU_INCLUDE_DIR 3ds.h\r\n          PATHS ${CTRULIB_PATHS}\r\n          PATH_SUFFIXES include libctru/include )\r\n\r\nfind_library(LIBCTRU_LIBRARY NAMES ctru libctru.a\r\n          PATHS ${CTRULIB_PATHS}\r\n          PATH_SUFFIXES lib libctru/lib )\r\n\r\nset(LIBCTRU_LIBRARIES ${LIBCTRU_LIBRARY} )\r\nset(LIBCTRU_INCLUDE_DIRS ${LIBCTRU_INCLUDE_DIR} )\r\n\r\ninclude(FindPackageHandleStandardArgs)\r\n# handle the QUIETLY and REQUIRED arguments and set LIBCTRU_FOUND to TRUE\r\n# if all listed variables are TRUE\r\nfind_package_handle_standard_args(CTRULIB  DEFAULT_MSG\r\n                                  LIBCTRU_LIBRARY LIBCTRU_INCLUDE_DIR)\r\n\r\nmark_as_advanced(LIBCTRU_INCLUDE_DIR LIBCTRU_LIBRARY )\r\nif(CTRULIB_FOUND)\r\n    set(CTRULIB ${LIBCTRU_INCLUDE_DIR}/..)\r\n    message(STATUS \"setting CTRULIB to ${CTRULIB}\")\r\n\r\n    add_library(3ds::ctrulib STATIC IMPORTED GLOBAL)\r\n    set_target_properties(3ds::ctrulib PROPERTIES\r\n        IMPORTED_LOCATION \"${LIBCTRU_LIBRARY}\"\r\n        INTERFACE_INCLUDE_DIRECTORIES \"${LIBCTRU_INCLUDE_DIR}\"\r\n    )\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/ctr/modules/FindPNG.cmake",
    "content": "# - Try to find png\r\n# You can set PNG_ROOT to specify a certain directory to look in first.\r\n# Once done this will define\r\n#  PNG_FOUND - System has png\r\n#  PNG_INCLUDE_DIRS - The png include directories\r\n#  PNG_LIBRARIES - The libraries needed to use png\r\n# Unless we are unable to find ZLIB\r\n# It also adds an imported target named `3ds::png`, Linking against it is\r\n# equivalent to:\r\n# target_link_libraries(mytarget ${PNG_LIBRARIES})\r\n# target_include_directories(mytarget PRIVATE ${PNG_INCLUDE_DIRS})\r\n\r\nif(NOT NINTENDO_3DS)\r\n    message(FATAL_ERROR \"This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.\")\r\nendif()\r\n\r\nif(PNG_INCLUDE_DIR)\r\n    # Already in cache, be silent\r\n    set(PNG_FIND_QUIETLY TRUE)\r\nendif(PNG_INCLUDE_DIR)\r\n\r\ninclude(LibFindMacros)\r\ninclude(try_add_imported_target)\r\n\r\nlibfind_package(PNG ZLIB)\r\n\r\nset(_PNG_SEARCHES)\r\n\r\n# Search PNG_ROOT first if it is set.\r\nif(PNG_ROOT)\r\n  set(_PNG_SEARCH_ROOT\r\n    PATHS ${PNG_ROOT}\r\n    NO_DEFAULT_PATH\r\n    NO_CMAKE_FIND_ROOT_PATH)\r\n  list(APPEND _PNG_SEARCHES _PNG_SEARCH_ROOT)\r\nendif()\r\n\r\n# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.\r\nset(_PNG_SEARCH_CMAKE_REROOTED\r\n  PATHS /\r\n  NO_DEFAULT_PATH\r\n  ONLY_CMAKE_FIND_ROOT_PATH)\r\nlist(APPEND _PNG_SEARCHES _PNG_SEARCH_CMAKE_REROOTED)\r\n\r\nset(_PNG_SEARCH_NORMAL NO_CMAKE_FIND_ROOT_PATH)\r\nlist(APPEND _PNG_SEARCHES _PNG_SEARCH_NORMAL)\r\n\r\nforeach(search ${_PNG_SEARCHES})\r\n  find_path(PNG_INCLUDE_DIR NAMES png.h\r\n    ${${search}}\r\n    PATH_SUFFIXES include)\r\n  find_library(PNG_LIBRARY NAMES png libpng.a\r\n    ${${search}}\r\n    PATH_SUFFIXES lib)\r\nendforeach()\r\n\r\n#find_library(LIBM_LIBRARY NAMES m libm.a\r\n#  PATHS / /arm-none-eabi\r\n#  PATH_SUFFIXES lib/armv6k/fpu)\r\n\r\nset(LIBM_LIBRARY m)\r\n\r\nset(PNG_PROCESS_INCLUDES PNG_INCLUDE_DIR)\r\nset(PNG_PROCESS_LIBS PNG_LIBRARY LIBM_LIBRARY)\r\n\r\nlibfind_process(PNG)\r\n\r\ntry_add_imported_target(PNG m 3ds::zlib)\r\nadd_library(PNG::PNG ALIAS 3ds::png)\r\n"
  },
  {
    "path": "CMake/platforms/ctr/modules/FindZLIB.cmake",
    "content": "# - Try to find zlib\r\n# You can set ZLIB_ROOT to specify a certain directory to look in first.\r\n# Once done this will define\r\n#  ZLIB_FOUND - System has zlib\r\n#  ZLIB_INCLUDE_DIRS - The zlib include directories\r\n#  ZLIB_LIBRARIES - The libraries needed to use zlib\r\n# It also adds an imported target named `3ds::zlib`, Linking against it is\r\n# equivalent to:\r\n# target_link_libraries(mytarget ${ZLIB_LIBRARY})\r\n# target_include_directories(mytarget PRIVATE ${ZLIB_INCLUDE_DIRS})\r\n\r\nif(NOT NINTENDO_3DS)\r\n    message(FATAL_ERROR \"This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.\")\r\nendif()\r\n\r\nif(ZLIB_INCLUDE_DIR)\r\n    # Already in cache, be silent\r\n    set(ZLIB_FIND_QUIETLY TRUE)\r\nendif(ZLIB_INCLUDE_DIR)\r\n\r\ninclude(LibFindMacros)\r\ninclude(try_add_imported_target)\r\n\r\nset(_ZLIB_SEARCHES)\r\n\r\n# Search ZLIB_ROOT first if it is set.\r\nif(ZLIB_ROOT)\r\n  set(_ZLIB_SEARCH_ROOT\r\n    PATHS ${ZLIB_ROOT}\r\n    NO_DEFAULT_PATH\r\n    NO_CMAKE_FIND_ROOT_PATH)\r\n  list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_ROOT)\r\nendif()\r\n\r\n# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.\r\nset(_ZLIB_SEARCH_CMAKE_REROOTED\r\n  PATHS /\r\n  NO_DEFAULT_PATH\r\n  ONLY_CMAKE_FIND_ROOT_PATH)\r\nlist(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_CMAKE_REROOTED)\r\n\r\nset(_ZLIB_SEARCH_NORMAL NO_CMAKE_FIND_ROOT_PATH)\r\nlist(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL)\r\n\r\nforeach(search ${_ZLIB_SEARCHES})\r\n  find_path(ZLIB_INCLUDE_DIR NAMES zlib.h\r\n    ${${search}}\r\n    PATH_SUFFIXES include)\r\n  find_library(ZLIB_LIBRARY NAMES z libz.a\r\n    ${${search}}\r\n    PATH_SUFFIXES lib)\r\nendforeach()\r\n\r\nset(ZLIB_PROCESS_INCLUDES ZLIB_INCLUDE_DIR)\r\nset(ZLIB_PROCESS_LIBS ZLIB_LIBRARY)\r\n\r\nlibfind_process(ZLIB)\r\n\r\ntry_add_imported_target(ZLIB)\r\n\r\nadd_library(ZLIB::ZLIB ALIAS 3ds::zlib)\r\n"
  },
  {
    "path": "CMake/platforms/ctr/modules/LibFindMacros.cmake",
    "content": "# Version 2.2\r\n# Public Domain, originally written by Lasse Kärkkäinen <tronic>\r\n# Maintained at https://github.com/Tronic/cmake-modules\r\n# Please send your improvements as pull requests on Github.\r\n\r\n# Find another package and make it a dependency of the current package.\r\n# This also automatically forwards the \"REQUIRED\" argument.\r\n# Usage: libfind_package(<prefix> <another package> [extra args to find_package])\r\nmacro (libfind_package PREFIX PKG)\r\n  set(${PREFIX}_args ${PKG} ${ARGN})\r\n  if (${PREFIX}_FIND_REQUIRED)\r\n    set(${PREFIX}_args ${${PREFIX}_args} REQUIRED)\r\n  endif()\r\n  find_package(${${PREFIX}_args})\r\n  set(${PREFIX}_DEPENDENCIES ${${PREFIX}_DEPENDENCIES};${PKG})\r\n  unset(${PREFIX}_args)\r\nendmacro()\r\n\r\n# A simple wrapper to make pkg-config searches a bit easier.\r\n# Works the same as CMake's internal pkg_check_modules but is always quiet.\r\nmacro (libfind_pkg_check_modules)\r\n  find_package(PkgConfig QUIET)\r\n  if (PKG_CONFIG_FOUND)\r\n    pkg_check_modules(${ARGN} QUIET)\r\n  endif()\r\nendmacro()\r\n\r\n# Avoid useless copy&pasta by doing what most simple libraries do anyway:\r\n# pkg-config, find headers, find library.\r\n# Usage: libfind_pkg_detect(<prefix> <pkg-config args> FIND_PATH <name> [other args] FIND_LIBRARY <name> [other args])\r\n# E.g. libfind_pkg_detect(SDL2 sdl2 FIND_PATH SDL.h PATH_SUFFIXES SDL2 FIND_LIBRARY SDL2)\r\nfunction (libfind_pkg_detect PREFIX)\r\n  # Parse arguments\r\n  set(argname pkgargs)\r\n  foreach (i ${ARGN})\r\n    if (\"${i}\" STREQUAL \"FIND_PATH\")\r\n      set(argname pathargs)\r\n    elseif (\"${i}\" STREQUAL \"FIND_LIBRARY\")\r\n      set(argname libraryargs)\r\n    else()\r\n      set(${argname} ${${argname}} ${i})\r\n    endif()\r\n  endforeach()\r\n  if (NOT pkgargs)\r\n    message(FATAL_ERROR \"libfind_pkg_detect requires at least a pkg_config package name to be passed.\")\r\n  endif()\r\n  # Find library\r\n  libfind_pkg_check_modules(${PREFIX}_PKGCONF ${pkgargs})\r\n  if (pathargs)\r\n    find_path(${PREFIX}_INCLUDE_DIR NAMES ${pathargs} HINTS ${${PREFIX}_PKGCONF_INCLUDE_DIRS})\r\n  endif()\r\n  if (libraryargs)\r\n    find_library(${PREFIX}_LIBRARY NAMES ${libraryargs} HINTS ${${PREFIX}_PKGCONF_LIBRARY_DIRS})\r\n  endif()\r\nendfunction()\r\n\r\n# Extracts a version #define from a version.h file, output stored to <PREFIX>_VERSION.\r\n# Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR)\r\n# Fourth argument \"QUIET\" may be used for silently testing different define names.\r\n# This function does nothing if the version variable is already defined.\r\nfunction (libfind_version_header PREFIX VERSION_H DEFINE_NAME)\r\n  # Skip processing if we already have a version or if the include dir was not found\r\n  if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR)\r\n    return()\r\n  endif()\r\n  set(quiet ${${PREFIX}_FIND_QUIETLY})\r\n  # Process optional arguments\r\n  foreach(arg ${ARGN})\r\n    if (arg STREQUAL \"QUIET\")\r\n      set(quiet TRUE)\r\n    else()\r\n      message(AUTHOR_WARNING \"Unknown argument ${arg} to libfind_version_header ignored.\")\r\n    endif()\r\n  endforeach()\r\n  # Read the header and parse for version number\r\n  set(filename \"${${PREFIX}_INCLUDE_DIR}/${VERSION_H}\")\r\n  if (NOT EXISTS ${filename})\r\n    if (NOT quiet)\r\n      message(AUTHOR_WARNING \"Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}\")\r\n    endif()\r\n    return()\r\n  endif()\r\n  file(READ \"${filename}\" header)\r\n  string(REGEX REPLACE \".*#[ \\t]*define[ \\t]*${DEFINE_NAME}[ \\t]*\\\"([^\\n]*)\\\".*\" \"\\\\1\" match \"${header}\")\r\n  # No regex match?\r\n  if (match STREQUAL header)\r\n    if (NOT quiet)\r\n      message(AUTHOR_WARNING \"Unable to find \\#define ${DEFINE_NAME} \\\"<version>\\\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}\")\r\n    endif()\r\n    return()\r\n  endif()\r\n  # Export the version string\r\n  set(${PREFIX}_VERSION \"${match}\" PARENT_SCOPE)\r\nendfunction()\r\n\r\n# Do the final processing once the paths have been detected.\r\n# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain\r\n# all the variables, each of which contain one include directory.\r\n# Ditto for ${PREFIX}_PROCESS_LIBS and library files.\r\n# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.\r\n# Also handles errors in case library detection was required, etc.\r\nfunction (libfind_process PREFIX)\r\n  # Skip processing if already processed during this configuration run\r\n  if (${PREFIX}_FOUND)\r\n    return()\r\n  endif()\r\n\r\n  set(found TRUE)  # Start with the assumption that the package was found\r\n\r\n  # Did we find any files? Did we miss includes? These are for formatting better error messages.\r\n  set(some_files FALSE)\r\n  set(missing_headers FALSE)\r\n\r\n  # Shorthands for some variables that we need often\r\n  set(quiet ${${PREFIX}_FIND_QUIETLY})\r\n  set(required ${${PREFIX}_FIND_REQUIRED})\r\n  set(exactver ${${PREFIX}_FIND_VERSION_EXACT})\r\n  set(findver \"${${PREFIX}_FIND_VERSION}\")\r\n  set(version \"${${PREFIX}_VERSION}\")\r\n\r\n  # Lists of config option names (all, includes, libs)\r\n  unset(configopts)\r\n  set(includeopts ${${PREFIX}_PROCESS_INCLUDES})\r\n  set(libraryopts ${${PREFIX}_PROCESS_LIBS})\r\n\r\n  # Process deps to add to\r\n  foreach (i ${PREFIX} ${${PREFIX}_DEPENDENCIES})\r\n    if (DEFINED ${i}_INCLUDE_OPTS OR DEFINED ${i}_LIBRARY_OPTS)\r\n      # The package seems to export option lists that we can use, woohoo!\r\n      list(APPEND includeopts ${${i}_INCLUDE_OPTS})\r\n      list(APPEND libraryopts ${${i}_LIBRARY_OPTS})\r\n    else()\r\n      # If plural forms don't exist or they equal singular forms\r\n      if ((NOT DEFINED ${i}_INCLUDE_DIRS AND NOT DEFINED ${i}_LIBRARIES) OR\r\n          (${i}_INCLUDE_DIR STREQUAL ${i}_INCLUDE_DIRS AND ${i}_LIBRARY STREQUAL ${i}_LIBRARIES))\r\n        # Singular forms can be used\r\n        if (DEFINED ${i}_INCLUDE_DIR)\r\n          list(APPEND includeopts ${i}_INCLUDE_DIR)\r\n        endif()\r\n        if (DEFINED ${i}_LIBRARY)\r\n          list(APPEND libraryopts ${i}_LIBRARY)\r\n        endif()\r\n      else()\r\n        # Oh no, we don't know the option names\r\n        message(FATAL_ERROR \"We couldn't determine config variable names for ${i} includes and libs. Aieeh!\")\r\n      endif()\r\n    endif()\r\n  endforeach()\r\n\r\n  if (includeopts)\r\n    list(REMOVE_DUPLICATES includeopts)\r\n  endif()\r\n\r\n  if (libraryopts)\r\n    list(REMOVE_DUPLICATES libraryopts)\r\n  endif()\r\n\r\n  string(REGEX REPLACE \".*[ ;]([^ ;]*(_INCLUDE_DIRS|_LIBRARIES))\" \"\\\\1\" tmp \"${includeopts} ${libraryopts}\")\r\n  if (NOT tmp STREQUAL \"${includeopts} ${libraryopts}\")\r\n    message(AUTHOR_WARNING \"Plural form ${tmp} found in config options of ${PREFIX}. This works as before but is now deprecated. Please only use singular forms INCLUDE_DIR and LIBRARY, and update your find scripts for LibFindMacros > 2.0 automatic dependency system (most often you can simply remove the PROCESS variables entirely).\")\r\n  endif()\r\n\r\n  # Include/library names separated by spaces (notice: not CMake lists)\r\n  unset(includes)\r\n  unset(libs)\r\n\r\n  # Process all includes and set found false if any are missing\r\n  foreach (i ${includeopts})\r\n    list(APPEND configopts ${i})\r\n    if (NOT \"${${i}}\" STREQUAL \"${i}-NOTFOUND\")\r\n      list(APPEND includes \"${${i}}\")\r\n    else()\r\n      set(found FALSE)\r\n      set(missing_headers TRUE)\r\n    endif()\r\n  endforeach()\r\n\r\n  # Process all libraries and set found false if any are missing\r\n  foreach (i ${libraryopts})\r\n    list(APPEND configopts ${i})\r\n    if (NOT \"${${i}}\" STREQUAL \"${i}-NOTFOUND\")\r\n      list(APPEND libs \"${${i}}\")\r\n    else()\r\n      set (found FALSE)\r\n    endif()\r\n  endforeach()\r\n\r\n  # Version checks\r\n  if (found AND findver)\r\n    if (NOT version)\r\n      message(WARNING \"The find module for ${PREFIX} does not provide version information, so we'll just assume that it is OK. Please fix the module or remove package version requirements to get rid of this warning.\")\r\n    elseif (version VERSION_LESS findver OR (exactver AND NOT version VERSION_EQUAL findver))\r\n      set(found FALSE)\r\n      set(version_unsuitable TRUE)\r\n    endif()\r\n  endif()\r\n\r\n  # If all-OK, hide all config options, export variables, print status and exit\r\n  if (found)\r\n    foreach (i ${configopts})\r\n      mark_as_advanced(${i})\r\n    endforeach()\r\n    if (NOT quiet)\r\n      message(STATUS \"Found ${PREFIX} ${${PREFIX}_LIBRARY} ${${PREFIX}_VERSION}\")\r\n      if (LIBFIND_DEBUG)\r\n        message(STATUS \"  ${PREFIX}_DEPENDENCIES=${${PREFIX}_DEPENDENCIES}\")\r\n        message(STATUS \"  ${PREFIX}_INCLUDE_OPTS=${includeopts}\")\r\n        message(STATUS \"  ${PREFIX}_INCLUDE_DIRS=${includes}\")\r\n        message(STATUS \"  ${PREFIX}_LIBRARY_OPTS=${libraryopts}\")\r\n        message(STATUS \"  ${PREFIX}_LIBRARIES=${libs}\")\r\n      endif()\r\n    endif()\r\n    set (${PREFIX}_INCLUDE_OPTS ${includeopts} PARENT_SCOPE)\r\n    set (${PREFIX}_LIBRARY_OPTS ${libraryopts} PARENT_SCOPE)\r\n    set (${PREFIX}_INCLUDE_DIRS ${includes} PARENT_SCOPE)\r\n    set (${PREFIX}_LIBRARIES ${libs} PARENT_SCOPE)\r\n    set (${PREFIX}_FOUND TRUE PARENT_SCOPE)\r\n    return()\r\n  endif()\r\n\r\n  # Format messages for debug info and the type of error\r\n  set(vars \"Relevant CMake configuration variables:\\n\")\r\n  foreach (i ${configopts})\r\n    mark_as_advanced(CLEAR ${i})\r\n    set(val ${${i}})\r\n    if (\"${val}\" STREQUAL \"${i}-NOTFOUND\")\r\n      set (val \"<not found>\")\r\n    elseif (val AND NOT EXISTS ${val})\r\n      set (val \"${val}  (does not exist)\")\r\n    else()\r\n      set(some_files TRUE)\r\n    endif()\r\n    set(vars \"${vars}  ${i}=${val}\\n\")\r\n  endforeach()\r\n  set(vars \"${vars}You may use CMake GUI, cmake -D or ccmake to modify the values. Delete CMakeCache.txt to discard all values and force full re-detection if necessary.\\n\")\r\n  if (version_unsuitable)\r\n    set(msg \"${PREFIX} ${${PREFIX}_VERSION} was found but\")\r\n    if (exactver)\r\n      set(msg \"${msg} only version ${findver} is acceptable.\")\r\n    else()\r\n      set(msg \"${msg} version ${findver} is the minimum requirement.\")\r\n    endif()\r\n  else()\r\n    if (missing_headers)\r\n      set(msg \"We could not find development headers for ${PREFIX}. Do you have the necessary dev package installed?\")\r\n    elseif (some_files)\r\n      set(msg \"We only found some files of ${PREFIX}, not all of them. Perhaps your installation is incomplete or maybe we just didn't look in the right place?\")\r\n      if(findver)\r\n        set(msg \"${msg} This could also be caused by incompatible version (if it helps, at least ${PREFIX} ${findver} should work).\")\r\n      endif()\r\n    else()\r\n      set(msg \"We were unable to find package ${PREFIX}.\")\r\n    endif()\r\n  endif()\r\n\r\n  # Fatal error out if REQUIRED\r\n  if (required)\r\n    set(msg \"REQUIRED PACKAGE NOT FOUND\\n${msg} This package is REQUIRED and you need to install it or adjust CMake configuration in order to continue building ${CMAKE_PROJECT_NAME}.\")\r\n    message(FATAL_ERROR \"${msg}\\n${vars}\")\r\n  endif()\r\n  # Otherwise just print a nasty warning\r\n  if (NOT quiet)\r\n    message(WARNING \"WARNING: MISSING PACKAGE\\n${msg} This package is NOT REQUIRED and you may ignore this warning but by doing so you may miss some functionality of ${CMAKE_PROJECT_NAME}. \\n${vars}\")\r\n  endif()\r\nendfunction()\r\n"
  },
  {
    "path": "CMake/platforms/ctr/modules/try_add_imported_target.cmake",
    "content": "macro(try_add_imported_target LIBNAME)\r\n  string(TOLOWER ${LIBNAME} ${LIBNAME}_lwr)\r\n  set(${LIBNAME}_TARGET 3ds::${${LIBNAME}_lwr})\r\n  if(${LIBNAME}_FOUND AND NOT TARGET ${${LIBNAME}_TARGET})\r\n    add_library(${${LIBNAME}_TARGET} STATIC IMPORTED GLOBAL)\r\n\r\n    set_target_properties(${${LIBNAME}_TARGET} PROPERTIES\r\n      IMPORTED_LOCATION \"${${LIBNAME}_LIBRARY}\"\r\n      INTERFACE_INCLUDE_DIRECTORIES \"${${LIBNAME}_INCLUDE_DIR}\")\r\n\r\n    if(${ARGC} GREATER 1)\r\n      target_link_libraries(${${LIBNAME}_TARGET} INTERFACE ${ARGN})\r\n    endif()\r\n  endif()\r\nendmacro()\r\n"
  },
  {
    "path": "CMake/platforms/debian-cross-pkg-config.sh",
    "content": "#!/bin/sh\n# pkg-config wrapper for cross-building\n# Sets pkg-config search path to search multiarch and historical cross-compiling paths.\n\n# https://gist.github.com/doug65536/ea9c52f9a65a655a2fd5cc4997e8443b\n\n# If the user has already set PKG_CONFIG_LIBDIR, believe it (even if empty):\n# it's documented to be an override\nif [ x\"${PKG_CONFIG_LIBDIR+set}\" = x ]; then\n  # GNU triplet for the compiler, e.g. i486-linux-gnu for Debian i386,\n  # i686-linux-gnu for Ubuntu i386\n  basename=\"`basename \"$0\"`\"\n  triplet=\"${basename%-pkg-config}\"\n  # Normalized multiarch path if any, e.g. i386-linux-gnu for i386\n  multiarch=\"`dpkg-architecture -t\"${triplet}\" -qDEB_HOST_MULTIARCH 2>/dev/null`\"\n  # Native multiarch path\n  if [ -f /usr/lib/pkg-config.multiarch ]; then\n    native_multiarch=\"$(cat /usr/lib/pkg-config.multiarch)\"\n\n    # This can be used for native builds as well, in that case, just exec pkg-config \"$@\" directly.\n    if [ \"$native_multiarch\" = \"$multiarch\" ]; then\n       exec pkg-config \"$@\"\n    fi\n  fi\n\n  PKG_CONFIG_LIBDIR=\"/usr/local/${triplet}/lib/pkgconfig\"\n  # For a native build we would also want to append /usr/local/lib/pkgconfig\n  # at this point; but this is a cross-building script, so don't\n  PKG_CONFIG_LIBDIR=\"$PKG_CONFIG_LIBDIR:/usr/local/share/pkgconfig\"\n\n  if [ -n \"$multiarch\" ]; then\n    PKG_CONFIG_LIBDIR=\"/usr/local/lib/${multiarch}/pkgconfig:$PKG_CONFIG_LIBDIR\"\n    PKG_CONFIG_LIBDIR=\"$PKG_CONFIG_LIBDIR:/usr/lib/${multiarch}/pkgconfig\"\n  fi\n\n  PKG_CONFIG_LIBDIR=\"$PKG_CONFIG_LIBDIR:/usr/${triplet}/lib/pkgconfig\"\n  # For a native build we would also want to append /usr/lib/pkgconfig\n  # at this point; but this is a cross-building script, so don't\n  # If you want to allow use of un-multiarched -dev packages for crossing\n  # (at the risk of finding build-arch stuff you didn't want, if not in a clean chroot)\n  # Uncomment the next line:\n  # PKG_CONFIG_LIBDIR=\"$PKG_CONFIG_LIBDIR:/usr/lib/pkgconfig\"\n  # ... but on Ubuntu we rely cross-building with non-multiarch libraries:\n  if dpkg-vendor --derives-from Ubuntu; then\n      PKG_CONFIG_LIBDIR=\"$PKG_CONFIG_LIBDIR:/usr/lib/pkgconfig\"\n  fi\n  PKG_CONFIG_LIBDIR=\"$PKG_CONFIG_LIBDIR:/usr/share/pkgconfig\"\n\n  export PKG_CONFIG_LIBDIR\nfi\n\nexec pkg-config \"$@\"\n"
  },
  {
    "path": "CMake/platforms/djcpp.toolchain.cmake",
    "content": "set(CMAKE_SYSTEM_NAME Generic)\r\nset(CMAKE_SYSTEM_VERSION 1)\r\n\r\nif($ENV{DJGPP_PREFIX})\r\n  set(DJGPP_PREFIX \"$ENV{DJGPP_PREFIX}\")\r\nelse()\r\n  set(DJGPP_PREFIX \"/opt/i386-pc-msdosdjgpp-toolchain\")\r\nendif()\r\n\r\nset(CMAKE_C_COMPILER \"${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-gcc\")\r\nset(CMAKE_CXX_COMPILER \"${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-g++\")\r\nset(CMAKE_STRIP \"${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-strip\")\r\nset(PKG_CONFIG_EXECUTABLE \"${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-pkg-config\" CACHE STRING \"Path to pkg-config\")\r\n\r\nset(CMAKE_EXE_LINKER_FLAGS_INIT \"-static\")\r\n\r\nset(DJGPP_ROOT \"${DJGPP_PREFIX}/i386-pc-msdosdjgpp\")\r\n\r\nset(CMAKE_FIND_ROOT_PATH \"${DJGPP_ROOT}\")\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)\r\n\r\nlink_directories(\"${DJGPP_ROOT}/lib\")\r\ninclude_directories(BEFORE SYSTEM \"${DJGPP_ROOT}/sys-include\" \"${DJGPP_ROOT}/include\")\r\n\r\n"
  },
  {
    "path": "CMake/platforms/dos.cmake",
    "content": "set(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(DIST ON)\r\n\r\nset(NONET ON)\r\nset(NOSOUND ON)\r\nset(DEFAULT_PER_PIXEL_LIGHTING false)\r\n\r\nset(PREFILL_PLAYER_NAME ON)\r\n\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\nset(DEVILUTIONX_SYSTEM_ZLIB OFF)\r\nset(DEVILUTIONX_STATIC_ZLIB ON)\r\nset(DEVILUTIONX_SYSTEM_SDL2 OFF)\r\nset(DEVILUTIONX_STATIC_SDL2 ON)\r\nset(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBPNG OFF)\r\nset(DEVILUTIONX_DISPLAY_PIXELFORMAT SDL_PIXELFORMAT_INDEX8)\r\n\r\nset(DEVILUTIONX_PLATFORM_FILE_UTIL_LINK_LIBRARIES \"\")\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS $<$<CONFIG:Debug>:-gstabs>)\r\n\r\nadd_compile_definitions(\r\n  SDL_DISABLE_IMMINTRIN_H\r\n  SDL_DISABLE_XMMINTRIN_H\r\n  SDL_DISABLE_EMMINTRIN_H\r\n  SDL_DISABLE_PMMINTRIN_H\r\n  SDL_DISABLE_MMINTRIN_H\r\n)\r\n"
  },
  {
    "path": "CMake/platforms/emscripten.cmake",
    "content": "set(BUILD_TESTING OFF)\r\nset(BUILD_ASSETS_MPQ OFF)\r\nset(DISABLE_ZERO_TIER ON)\r\nset(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\n\r\n# Emscripten ports do have a bzip2 but it fails to link with this error:\r\n#   warning: _BZ2_bzDecompress may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library\r\n#   error: undefined symbol: BZ2_bzDecompressEnd (referenced by top-level compiled C/C++ code)\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\n\r\nfile(COPY \"${CMAKE_CURRENT_SOURCE_DIR}/Packaging/emscripten/index.html\" DESTINATION \"${CMAKE_CURRENT_BINARY_DIR}\")\r\n"
  },
  {
    "path": "CMake/platforms/gkd350h.cmake",
    "content": "set(BUILD_ASSETS_MPQ OFF)\r\nset(DISABLE_ZERO_TIER ON)\r\nset(USE_SDL1 ON)\r\n\r\n# Do not warn about unknown attributes, such as [[nodiscard]].\r\n# As this build uses an older compiler, there are lots of them.\r\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-attributes\")\r\n\r\n# GKD350h IPU scaler is broken at the moment\r\nset(DEFAULT_WIDTH 320)\r\nset(DEFAULT_HEIGHT 240)\r\n\r\nset(SDL1_VIDEO_MODE_BPP 16)\r\nset(PREFILL_PLAYER_NAME ON)\r\n\r\n# In joystick mode, GKD350h reports D-Pad as left stick,\r\n# so we have to use keyboard mode instead.\r\n\r\nset(HAS_KBCTRL 1)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT)\r\nset(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT)\r\nset(KBCTRL_BUTTON_DPAD_UP SDLK_UP)\r\nset(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN)\r\nset(KBCTRL_BUTTON_B SDLK_LCTRL)\r\nset(KBCTRL_BUTTON_A SDLK_LALT)\r\nset(KBCTRL_BUTTON_Y SDLK_SPACE)\r\nset(KBCTRL_BUTTON_X SDLK_LSHIFT)\r\nset(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_BACKSPACE)\r\nset(KBCTRL_BUTTON_LEFTSHOULDER SDLK_TAB)\r\n\r\n# We swap Select and Start because Start + D-Pad is overtaken by the kernel.\r\nset(KBCTRL_BUTTON_START SDLK_ESCAPE) # Select\r\nset(KBCTRL_BUTTON_BACK SDLK_RETURN) # Start\r\n\r\nset(JOY_AXIS_LEFTX 0)\r\nset(JOY_AXIS_LEFTY 1)\r\n\r\n# Unused joystick mappings (kept here for future reference).\r\nset(JOY_HAT_DPAD_UP_HAT 0)\r\nset(JOY_HAT_DPAD_UP 1)\r\nset(JOY_HAT_DPAD_DOWN_HAT 0)\r\nset(JOY_HAT_DPAD_DOWN 4)\r\nset(JOY_HAT_DPAD_LEFT_HAT 0)\r\nset(JOY_HAT_DPAD_LEFT 8)\r\nset(JOY_HAT_DPAD_RIGHT_HAT 0)\r\nset(JOY_HAT_DPAD_RIGHT 2)\r\nset(JOY_BUTTON_A 0)\r\nset(JOY_BUTTON_B 1)\r\nset(JOY_BUTTON_Y 2)\r\nset(JOY_BUTTON_X 3)\r\nset(JOY_BUTTON_RIGHTSHOULDER 7)\r\nset(JOY_BUTTON_LEFTSHOULDER 6)\r\nset(JOY_BUTTON_START 5)\r\nset(JOY_BUTTON_BACK 4)\r\n"
  },
  {
    "path": "CMake/platforms/haiku.cmake",
    "content": "set(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(DEVILUTIONX_STATIC_CXX_STDLIB OFF)\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES network)\r\n"
  },
  {
    "path": "CMake/platforms/ios.cmake",
    "content": "enable_language(OBJC)\r\n\r\n# General build options.\r\nset(BUILD_TESTING OFF)\r\n\r\n# Disable all system dependencies.\r\n# All of these will be fetched via FetchContent and linked statically.\r\nset(DEVILUTIONX_SYSTEM_SDL2 OFF)\r\nset(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\nset(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBPNG OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\n\r\nset(NOEXIT ON)\r\n\r\n# Disable sanitizers. They're not supported out-of-the-box.\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\n"
  },
  {
    "path": "CMake/platforms/ios.toolchain.cmake",
    "content": "# This file is part of the ios-cmake project. It was retrieved from\n# https://github.com/leetal/ios-cmake.git, which is a fork of\n# https://github.com/gerstrong/ios-cmake.git, which is a fork of\n# https://github.com/cristeab/ios-cmake.git, which is a fork of\n# https://code.google.com/p/ios-cmake/. Which in turn is based off of\n# the Platform/Darwin.cmake and Platform/UnixPaths.cmake files which\n# are included with CMake 2.8.4\n#\n# The ios-cmake project is licensed under the new BSD license.\n#\n# Copyright (c) 2014, Bogdan Cristea and LTE Engineering Software,\n# Kitware, Inc., Insight Software Consortium.  All rights reserved.\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n# 1. Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright\n# notice, this list of conditions and the following disclaimer in the\n# documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its\n# contributors may be used to endorse or promote products derived from\n# this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n#\n# This file is based on the Platform/Darwin.cmake and\n# Platform/UnixPaths.cmake files which are included with CMake 2.8.4\n# It has been altered for iOS development.\n#\n# Updated by Alex Stewart (alexs.mac@gmail.com)\n#\n# *****************************************************************************\n#      Now maintained by Alexander Widerberg (widerbergaren [at] gmail.com)\n#                      under the BSD-3-Clause license\n#                   https://github.com/leetal/ios-cmake\n# *****************************************************************************\n#\n#                           INFORMATION / HELP\n#\n###############################################################################\n#                                  OPTIONS                                    #\n###############################################################################\n#\n# PLATFORM: (default \"OS64\")\n#    OS = Build for iPhoneOS.\n#    OS64 = Build for arm64 iphoneOS.\n#    OS64COMBINED = Build for arm64 x86_64 iphoneOS + iphoneOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with \"-G Xcode\" argument in combination with the \"cmake --install\" CMake build step)\n#    SIMULATOR = Build for x86 i386 iphoneOS Simulator.\n#    SIMULATOR64 = Build for x86_64 iphoneOS Simulator.\n#    SIMULATORARM64 = Build for arm64 iphoneOS Simulator.\n#    SIMULATOR64COMBINED = Build for arm64 x86_64 iphoneOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith \"-G Xcode\" argument ONLY)\n#    TVOS = Build for arm64 tvOS.\n#    TVOSCOMBINED = Build for arm64 x86_64 tvOS + tvOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with \"-G Xcode\" argument in combination with the \"cmake --install\" CMake build step)\n#    SIMULATOR_TVOS = Build for x86_64 tvOS Simulator.\n#    SIMULATORARM64_TVOS = Build for arm64 tvOS Simulator.\n#    VISIONOSCOMBINED = Build for arm64 visionOS + visionOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with \"-G Xcode\" argument in combination with the \"cmake --install\" CMake build step)\n#    VISIONOS = Build for arm64 visionOS.\n#    SIMULATOR_VISIONOS = Build for arm64 visionOS Simulator.\n#    WATCHOS = Build for armv7k arm64_32 for watchOS.\n#    WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS + watchOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with \"-G Xcode\" argument in combination with the \"cmake --install\" CMake build step)\n#    SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator.\n#    SIMULATORARM64_WATCHOS = Build for arm64 for watchOS Simulator.\n#    MAC = Build for x86_64 macOS.\n#    MAC_ARM64 = Build for Apple Silicon macOS.\n#    MAC_UNIVERSAL = Combined build for x86_64 and Apple Silicon on macOS.\n#    MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS).\n#                   Note: The build argument \"MACOSX_DEPLOYMENT_TARGET\" can be used to control min-version of macOS\n#    MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS).\n#                         Note: The build argument \"MACOSX_DEPLOYMENT_TARGET\" can be used to control min-version of macOS\n#    MAC_CATALYST_UNIVERSAL = Combined build for x86_64 and Apple Silicon on Catalyst.\n#\n# CMAKE_OSX_SYSROOT: Path to the SDK to use.  By default this is\n#    automatically determined from PLATFORM and xcodebuild, but\n#    can also be manually specified (although this should not be required).\n#\n# CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform\n#    being compiled for.  By default, this is automatically determined from\n#    CMAKE_OSX_SYSROOT, but can also be manually specified (although this should\n#    not be required).\n#\n# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 6.0 on watchOS, 13.0 on tvOS+iOS/iPadOS, 11.0 on macOS, 1.0 on visionOS\n#\n# NAMED_LANGUAGE_SUPPORT:\n#    ON (default) = Will require \"enable_language(OBJC) and/or enable_language(OBJCXX)\" for full OBJC|OBJCXX support\n#    OFF = Will embed the OBJC and OBJCXX flags into the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (legacy behavior, CMake version < 3.16)\n#\n# ENABLE_BITCODE: (ON|OFF) Enables or disables bitcode support. Default OFF\n#\n# ENABLE_ARC: (ON|OFF) Enables or disables ARC support. Default ON (ARC enabled by default)\n#\n# ENABLE_VISIBILITY: (ON|OFF) Enables or disables symbol visibility support. Default OFF (visibility hidden by default)\n#\n# ENABLE_STRICT_TRY_COMPILE: (ON|OFF) Enables or disables strict try_compile() on all Check* directives (will run linker\n#    to actually check if linking is possible). Default OFF (will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY)\n#\n# ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM\n#    OS = armv7 armv7s arm64 (if applicable)\n#    OS64 = arm64 (if applicable)\n#    SIMULATOR = i386\n#    SIMULATOR64 = x86_64\n#    SIMULATORARM64 = arm64\n#    TVOS = arm64\n#    SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated)\n#    SIMULATORARM64_TVOS = arm64\n#    WATCHOS = armv7k arm64_32 (if applicable)\n#    SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated)\n#    SIMULATORARM64_WATCHOS = arm64\n#    MAC = x86_64\n#    MAC_ARM64 = arm64\n#    MAC_UNIVERSAL = x86_64 arm64\n#    MAC_CATALYST = x86_64\n#    MAC_CATALYST_ARM64 = arm64\n#    MAC_CATALYST_UNIVERSAL = x86_64 arm64\n#\n# NOTE: When manually specifying ARCHS, put a semi-colon between the entries. E.g., -DARCHS=\"armv7;arm64\"\n#\n###############################################################################\n#                                END OPTIONS                                  #\n###############################################################################\n#\n# This toolchain defines the following properties (available via get_property()) for use externally:\n#\n# PLATFORM: The currently targeted platform.\n# XCODE_VERSION: Version number (not including Build version) of Xcode detected.\n# SDK_VERSION: Version of SDK being used.\n# OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM).\n# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If \"ARCHS\" is overridden, this will *NOT* be set!\n#\n# This toolchain defines the following macros for use externally:\n#\n# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE XCODE_VARIANT)\n#   A convenience macro for setting xcode specific properties on targets.\n#   Available variants are: All, Release, RelWithDebInfo, Debug, MinSizeRel\n#   example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET \"3.1\" \"all\").\n#\n# find_host_package (PROGRAM ARGS)\n#   A macro used to find executable programs on the host system, not within the\n#   environment. Thanks to the android-cmake project for providing the\n#   command.\n#\n\ncmake_minimum_required(VERSION 3.8.0)\n\n# CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds.\n# NOTE: To improve single-library build-times, provide the flag \"OS_SINGLE_BUILD\" as a build argument.\nif(DEFINED OS_SINGLE_BUILD AND DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN})\n  return()\nendif()\nset(ENV{_IOS_TOOLCHAIN_HAS_RUN} true)\n\n# List of supported platform values\nlist(APPEND _supported_platforms\n        \"OS\" \"OS64\" \"OS64COMBINED\" \"SIMULATOR\" \"SIMULATOR64\" \"SIMULATORARM64\" \"SIMULATOR64COMBINED\"\n        \"TVOS\" \"TVOSCOMBINED\" \"SIMULATOR_TVOS\" \"SIMULATORARM64_TVOS\"\n        \"WATCHOS\" \"WATCHOSCOMBINED\" \"SIMULATOR_WATCHOS\" \"SIMULATORARM64_WATCHOS\"\n        \"MAC\" \"MAC_ARM64\" \"MAC_UNIVERSAL\"\n        \"VISIONOS\" \"SIMULATOR_VISIONOS\" \"VISIONOSCOMBINED\" \n        \"MAC_CATALYST\" \"MAC_CATALYST_ARM64\" \"MAC_CATALYST_UNIVERSAL\")\n\n# Cache what generator is used\nset(USED_CMAKE_GENERATOR \"${CMAKE_GENERATOR}\")\n\n# Check if using a CMake version capable of building combined FAT builds (simulator and target slices combined in one static lib)\nif(${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.14\")\n  set(MODERN_CMAKE YES)\nendif()\n\n# Get the Xcode version being used.\n# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs.\n# Workaround: On the first run (in which cache variables are always accessible), set an intermediary environment variable.\n#\n# NOTE: This pattern is used in many places in this toolchain to speed up checks of all sorts\nif(DEFINED XCODE_VERSION_INT)\n  # Environment variables are always preserved.\n  set(ENV{_XCODE_VERSION_INT} \"${XCODE_VERSION_INT}\")\nelseif(DEFINED ENV{_XCODE_VERSION_INT})\n  set(XCODE_VERSION_INT \"$ENV{_XCODE_VERSION_INT}\")\nelseif(NOT DEFINED XCODE_VERSION_INT)\n  find_program(XCODEBUILD_EXECUTABLE xcodebuild)\n  if(NOT XCODEBUILD_EXECUTABLE)\n    message(FATAL_ERROR \"xcodebuild not found. Please install either the standalone commandline tools or Xcode.\")\n  endif()\n  execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version\n          OUTPUT_VARIABLE XCODE_VERSION_INT\n          ERROR_QUIET\n          OUTPUT_STRIP_TRAILING_WHITESPACE)\n  string(REGEX MATCH \"Xcode [0-9\\\\.]+\" XCODE_VERSION_INT \"${XCODE_VERSION_INT}\")\n  string(REGEX REPLACE \"Xcode ([0-9\\\\.]+)\" \"\\\\1\" XCODE_VERSION_INT \"${XCODE_VERSION_INT}\")\n  set(XCODE_VERSION_INT \"${XCODE_VERSION_INT}\" CACHE INTERNAL \"\")\nendif()\n\n# Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur)\n# if you don't set a deployment target it will be set the way you only get 64-bit builds\n#if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0)\n# Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...)\n#  set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] \"arm64\")\n#endif()\n\n# Check if the platform variable is set\nif(DEFINED PLATFORM)\n  # Environment variables are always preserved.\n  set(ENV{_PLATFORM} \"${PLATFORM}\")\nelseif(DEFINED ENV{_PLATFORM})\n  set(PLATFORM \"$ENV{_PLATFORM}\")\nelseif(NOT DEFINED PLATFORM)\n  message(FATAL_ERROR \"PLATFORM argument not set. Bailing configure since I don't know what target you want to build for!\")\nendif ()\n\nif(PLATFORM MATCHES \".*COMBINED\" AND NOT CMAKE_GENERATOR MATCHES \"Xcode\")\n  message(FATAL_ERROR \"The combined builds support requires Xcode to be used as a generator via '-G Xcode' command-line argument in CMake\")\nendif()\n\n# Safeguard that the platform value is set and is one of the supported values\nlist(FIND _supported_platforms ${PLATFORM} contains_PLATFORM)\nif(\"${contains_PLATFORM}\" EQUAL \"-1\")\n  string(REPLACE \";\"  \"\\n * \" _supported_platforms_formatted \"${_supported_platforms}\")\n  message(FATAL_ERROR \" Invalid PLATFORM specified! Current value: ${PLATFORM}.\\n\"\n          \" Supported PLATFORM values: \\n * ${_supported_platforms_formatted}\")\nendif()\n\n# Check if Apple Silicon is supported\nif(PLATFORM MATCHES \"^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$|^(MAC_UNIVERSAL)$|^(MAC_CATALYST_UNIVERSAL)$\" AND ${CMAKE_VERSION} VERSION_LESS \"3.19.5\")\n  message(FATAL_ERROR \"Apple Silicon builds requires a minimum of CMake 3.19.5\")\nendif()\n\n# Touch the toolchain variable to suppress the \"unused variable\" warning.\n# This happens if CMake is invoked with the same command line the second time.\nif(CMAKE_TOOLCHAIN_FILE)\nendif()\n\n# Fix for PThread library not in path\nset(CMAKE_THREAD_LIBS_INIT \"-lpthread\")\nset(CMAKE_HAVE_THREADS_LIBRARY 1)\nset(CMAKE_USE_WIN32_THREADS_INIT 0)\nset(CMAKE_USE_PTHREADS_INIT 1)\n\n# Specify named language support defaults.\nif(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.16\")\n  set(NAMED_LANGUAGE_SUPPORT ON)\n  message(STATUS \"[DEFAULTS] Using explicit named language support! E.g., enable_language(CXX) is needed in the project files.\")\nelseif(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS \"3.16\")\n  set(NAMED_LANGUAGE_SUPPORT OFF)\n  message(STATUS \"[DEFAULTS] Disabling explicit named language support. Falling back to legacy behavior.\")\nelseif(DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS \"3.16\")\n  message(FATAL_ERROR \"CMake named language support for OBJC and OBJCXX was added in CMake 3.16.\")\nendif()\nset(NAMED_LANGUAGE_SUPPORT_INT ${NAMED_LANGUAGE_SUPPORT} CACHE BOOL\n        \"Whether or not to enable explicit named language support\" FORCE)\n\n# Specify the minimum version of the deployment target.\nif(NOT DEFINED DEPLOYMENT_TARGET)\n  if (PLATFORM MATCHES \"WATCHOS\")\n    # Unless specified, SDK version 4.0 is used by default as minimum target version (watchOS).\n    set(DEPLOYMENT_TARGET \"6.0\")\n  elseif(PLATFORM STREQUAL \"MAC\")\n    # Unless specified, SDK version 10.13 (High Sierra) is used by default as the minimum target version (macos).\n    set(DEPLOYMENT_TARGET \"11.0\")\n  elseif(PLATFORM STREQUAL \"VISIONOS\" OR PLATFORM STREQUAL \"SIMULATOR_VISIONOS\" OR PLATFORM STREQUAL \"VISIONOSCOMBINED\")\n    # Unless specified, SDK version 1.0 is used by default as minimum target version (visionOS).\n    set(DEPLOYMENT_TARGET \"1.0\")\n  elseif(PLATFORM STREQUAL \"MAC_ARM64\")\n    # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on arm).\n    set(DEPLOYMENT_TARGET \"11.0\")\n  elseif(PLATFORM STREQUAL \"MAC_UNIVERSAL\")\n    # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version for universal builds.\n    set(DEPLOYMENT_TARGET \"11.0\")\n  elseif(PLATFORM STREQUAL \"MAC_CATALYST\" OR PLATFORM STREQUAL \"MAC_CATALYST_ARM64\" OR PLATFORM STREQUAL \"MAC_CATALYST_UNIVERSAL\")\n    # Unless specified, SDK version 13.0 is used by default as the minimum target version (mac catalyst minimum requirement).\n    set(DEPLOYMENT_TARGET \"13.1\")\n  else()\n    # Unless specified, SDK version 11.0 is used by default as the minimum target version (iOS, tvOS).\n    set(DEPLOYMENT_TARGET \"13.0\")\n  endif()\n  message(STATUS \"[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!\")\nelseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES \"^MAC_CATALYST\" AND ${DEPLOYMENT_TARGET} VERSION_LESS \"13.1\")\n  message(FATAL_ERROR \"Mac Catalyst builds requires a minimum deployment target of 13.1!\")\nendif()\n\n# Store the DEPLOYMENT_TARGET in the cache\nset(DEPLOYMENT_TARGET \"${DEPLOYMENT_TARGET}\" CACHE INTERNAL \"\")\n\n# Handle the case where we are targeting iOS and a version above 10.3.4 (32-bit support dropped officially)\nif(PLATFORM STREQUAL \"OS\" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4)\n  set(PLATFORM \"OS64\")\n  message(STATUS \"Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.\")\nelseif(PLATFORM STREQUAL \"SIMULATOR\" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4)\n  set(PLATFORM \"SIMULATOR64\")\n  message(STATUS \"Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.\")\nendif()\n\nset(PLATFORM_INT \"${PLATFORM}\")\n\nif(DEFINED ARCHS)\n  string(REPLACE \";\" \"-\" ARCHS_SPLIT \"${ARCHS}\")\nendif()\n\n# Determine the platform name and architectures for use in xcodebuild commands\n# from the specified PLATFORM_INT name.\nif(PLATFORM_INT STREQUAL \"OS\")\n  set(SDK_NAME iphoneos)\n  if(NOT ARCHS)\n    set(ARCHS armv7 armv7s arm64)\n    set(APPLE_TARGET_TRIPLE_INT arm-apple-ios${DEPLOYMENT_TARGET})\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})  \n  endif()\nelseif(PLATFORM_INT STREQUAL \"OS64\")\n  set(SDK_NAME iphoneos)\n  if(NOT ARCHS)\n    if (XCODE_VERSION_INT VERSION_GREATER 10.0)\n      set(ARCHS arm64) # FIXME: Add arm64e when Apple has fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example\n    else()\n      set(ARCHS arm64)\n    endif()\n    set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET})\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})\n  endif()\nelseif(PLATFORM_INT STREQUAL \"OS64COMBINED\")\n  set(SDK_NAME iphoneos)\n  if(MODERN_CMAKE)\n    if(NOT ARCHS)\n      if (XCODE_VERSION_INT VERSION_GREATER 12.0)\n        set(ARCHS arm64 x86_64)\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] \"arm64\")\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] \"x86_64 arm64\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] \"arm64\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] \"x86_64 arm64\")\n      else()\n        set(ARCHS arm64 x86_64)\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] \"arm64\")\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] \"x86_64\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] \"arm64\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] \"x86_64\")\n      endif()\n      set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-ios${DEPLOYMENT_TARGET})\n    else()\n      set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})\n    endif()\n  else()\n    message(FATAL_ERROR \"Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work\")\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATOR64COMBINED\")\n  set(SDK_NAME iphonesimulator)\n  if(MODERN_CMAKE)\n    if(NOT ARCHS)\n      if (XCODE_VERSION_INT VERSION_GREATER 12.0)\n        set(ARCHS arm64 x86_64) # FIXME: Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] \"\")\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] \"x86_64 arm64\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] \"\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] \"x86_64 arm64\")\n      else()\n        set(ARCHS arm64 x86_64)\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] \"\")\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] \"x86_64\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] \"\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] \"x86_64\")\n      endif()\n      set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator)\n    else()\n      set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator)\n    endif()\n  else()\n    message(FATAL_ERROR \"Please make sure that you are running CMake 3.14+ to make the SIMULATOR64COMBINED setting work\")\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATOR\")\n  set(SDK_NAME iphonesimulator)\n  if(NOT ARCHS)\n    set(ARCHS i386)\n    set(APPLE_TARGET_TRIPLE_INT i386-apple-ios${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator)\n  endif()\n  message(DEPRECATION \"SIMULATOR IS DEPRECATED. Consider using SIMULATOR64 instead.\")\nelseif(PLATFORM_INT STREQUAL \"SIMULATOR64\")\n  set(SDK_NAME iphonesimulator)\n  if(NOT ARCHS)\n    set(ARCHS x86_64)\n    set(APPLE_TARGET_TRIPLE_INT x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATORARM64\")\n  set(SDK_NAME iphonesimulator)\n  if(NOT ARCHS)\n    set(ARCHS arm64)\n    set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"TVOS\")\n  set(SDK_NAME appletvos)\n  if(NOT ARCHS)\n    set(ARCHS arm64)\n    set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET})\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET})\n  endif()\nelseif (PLATFORM_INT STREQUAL \"TVOSCOMBINED\")\n  set(SDK_NAME appletvos)\n  if(MODERN_CMAKE)\n    if(NOT ARCHS)\n      set(ARCHS arm64 x86_64)\n      set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-tvos${DEPLOYMENT_TARGET})\n      set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] \"arm64\")\n      set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] \"x86_64 arm64\")\n      set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] \"arm64\")\n      set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] \"x86_64 arm64\")\n    else()\n      set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET})\n    endif()\n  else()\n    message(FATAL_ERROR \"Please make sure that you are running CMake 3.14+ to make the TVOSCOMBINED setting work\")\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATOR_TVOS\")\n  set(SDK_NAME appletvsimulator)\n  if(NOT ARCHS)\n    set(ARCHS x86_64)\n    set(APPLE_TARGET_TRIPLE_INT x86_64-apple-tvos${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATORARM64_TVOS\")\n  set(SDK_NAME appletvsimulator)\n  if(NOT ARCHS)\n    set(ARCHS arm64)\n    set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"WATCHOS\")\n  set(SDK_NAME watchos)\n  if(NOT ARCHS)\n    if (XCODE_VERSION_INT VERSION_GREATER 10.0)\n      set(ARCHS armv7k arm64_32)\n      set(APPLE_TARGET_TRIPLE_INT arm64_32-apple-watchos${DEPLOYMENT_TARGET})\n    else()\n      set(ARCHS armv7k)\n      set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos${DEPLOYMENT_TARGET})\n    endif()\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET})\n  endif()\nelseif(PLATFORM_INT STREQUAL \"WATCHOSCOMBINED\")\n  set(SDK_NAME watchos)\n  if(MODERN_CMAKE)\n    if(NOT ARCHS)\n      if (XCODE_VERSION_INT VERSION_GREATER 10.0)\n        set(ARCHS armv7k arm64_32 i386)\n        set(APPLE_TARGET_TRIPLE_INT arm64_32-i386-apple-watchos${DEPLOYMENT_TARGET})\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] \"armv7k arm64_32\")\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] \"i386\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] \"armv7k arm64_32\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] \"i386\")\n      else()\n        set(ARCHS armv7k i386)\n        set(APPLE_TARGET_TRIPLE_INT arm-i386-apple-watchos${DEPLOYMENT_TARGET})\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] \"armv7k\")\n        set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] \"i386\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] \"armv7k\")\n        set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] \"i386\")\n      endif()\n    else()\n      set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET})\n    endif()\n  else()\n    message(FATAL_ERROR \"Please make sure that you are running CMake 3.14+ to make the WATCHOSCOMBINED setting work\")\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATOR_WATCHOS\")\n  set(SDK_NAME watchsimulator)\n  if(NOT ARCHS)\n    set(ARCHS i386)\n    set(APPLE_TARGET_TRIPLE_INT i386-apple-watchos${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATORARM64_WATCHOS\")\n  set(SDK_NAME watchsimulator)\n  if(NOT ARCHS)\n    set(ARCHS arm64)\n    set(APPLE_TARGET_TRIPLE_INT arm64-apple-watchos${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"SIMULATOR_VISIONOS\")\n  set(SDK_NAME xrsimulator)\n  if(NOT ARCHS)\n    set(ARCHS arm64)\n    set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}-simulator)\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}-simulator)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"VISIONOS\")\n  set(SDK_NAME xros)\n  if(NOT ARCHS)\n    set(ARCHS arm64)\n    set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET})\n  else()\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET})\n  endif()\nelseif(PLATFORM_INT STREQUAL \"VISIONOSCOMBINED\")\n  set(SDK_NAME xros)\n  if(MODERN_CMAKE)\n    if(NOT ARCHS)\n      set(ARCHS arm64)\n      set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET})\n      set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xros*] \"arm64\")\n      set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xrsimulator*] \"arm64\")\n    else()\n      set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET})\n    endif()\n  else()\n    message(FATAL_ERROR \"Please make sure that you are running CMake 3.14+ to make the VISIONOSCOMBINED setting work\")\n  endif()\nelseif(PLATFORM_INT STREQUAL \"MAC\" OR PLATFORM_INT STREQUAL \"MAC_CATALYST\")\n  set(SDK_NAME macosx)\n  if(NOT ARCHS)\n    set(ARCHS x86_64)\n  endif()\n  string(REPLACE \";\" \"-\" ARCHS_SPLIT \"${ARCHS}\")\n  if(PLATFORM_INT STREQUAL \"MAC\")\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET})\n  elseif(PLATFORM_INT STREQUAL \"MAC_CATALYST\")\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi)\n  endif()\nelseif(PLATFORM_INT MATCHES \"^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$\")\n  set(SDK_NAME macosx)\n  if(NOT ARCHS)\n    set(ARCHS arm64)\n  endif()\n  string(REPLACE \";\" \"-\" ARCHS_SPLIT \"${ARCHS}\")\n  if(PLATFORM_INT STREQUAL \"MAC_ARM64\")\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET})\n  elseif(PLATFORM_INT STREQUAL \"MAC_CATALYST_ARM64\")\n    set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi)\n  endif()\nelseif(PLATFORM_INT STREQUAL \"MAC_UNIVERSAL\")\n  set(SDK_NAME macosx)\n  if(NOT ARCHS)\n    set(ARCHS \"x86_64;arm64\")\n  endif()\n  string(REPLACE \";\" \"-\" ARCHS_SPLIT \"${ARCHS}\")\n  set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET})\nelseif(PLATFORM_INT STREQUAL \"MAC_CATALYST_UNIVERSAL\")\n  set(SDK_NAME macosx)\n  if(NOT ARCHS)\n    set(ARCHS \"x86_64;arm64\")\n  endif()\n  string(REPLACE \";\" \"-\" ARCHS_SPLIT \"${ARCHS}\")\n  set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi)\nelse()\n  message(FATAL_ERROR \"Invalid PLATFORM: ${PLATFORM_INT}\")\nendif()\n\nstring(REPLACE \";\" \" \" ARCHS_SPACED \"${ARCHS}\")\n\nif(MODERN_CMAKE AND PLATFORM_INT MATCHES \".*COMBINED\" AND NOT CMAKE_GENERATOR MATCHES \"Xcode\")\n  message(FATAL_ERROR \"The COMBINED options only work with Xcode generator, -G Xcode\")\nendif()\n\nif(CMAKE_GENERATOR MATCHES \"Xcode\" AND PLATFORM_INT MATCHES \"^MAC_CATALYST\")\n  set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY \"libc++\")\n  set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS \"macosx\")\n  set(CMAKE_XCODE_ATTRIBUTE_SUPPORTS_MACCATALYST \"YES\")\n  if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET)\n    set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET \"10.15\")\n  else()\n    set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET \"${MACOSX_DEPLOYMENT_TARGET}\")\n  endif()\nelseif(CMAKE_GENERATOR MATCHES \"Xcode\")\n  set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY \"libc++\")\n  set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET \"${DEPLOYMENT_TARGET}\")\n  if(NOT PLATFORM_INT MATCHES \".*COMBINED\")\n    set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] \"${ARCHS_SPACED}\")\n    set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] \"${ARCHS_SPACED}\")\n  endif()\nendif()\n\n# If the user did not specify the SDK root to use, then query xcodebuild for it.\nif(DEFINED CMAKE_OSX_SYSROOT_INT)\n  # Environment variables are always preserved.\n  set(ENV{_CMAKE_OSX_SYSROOT_INT} \"${CMAKE_OSX_SYSROOT_INT}\")\nelseif(DEFINED ENV{_CMAKE_OSX_SYSROOT_INT})\n  set(CMAKE_OSX_SYSROOT_INT \"$ENV{_CMAKE_OSX_SYSROOT_INT}\")\nelseif(NOT DEFINED CMAKE_OSX_SYSROOT_INT)\n  execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version -sdk ${SDK_NAME} Path\n          OUTPUT_VARIABLE CMAKE_OSX_SYSROOT_INT\n          ERROR_QUIET\n          OUTPUT_STRIP_TRAILING_WHITESPACE)\nendif()\n\nif (NOT DEFINED CMAKE_OSX_SYSROOT_INT AND NOT DEFINED CMAKE_OSX_SYSROOT)\n  message(SEND_ERROR \"Please make sure that Xcode is installed and that the toolchain\"\n          \"is pointing to the correct path. Please run:\"\n          \"sudo xcode-select -s /Applications/Xcode.app/Contents/Developer\"\n          \"and see if that fixes the problem for you.\")\n  message(FATAL_ERROR \"Invalid CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT} \"\n          \"does not exist.\")\nelseif(DEFINED CMAKE_OSX_SYSROOT_INT)\n  set(CMAKE_OSX_SYSROOT_INT \"${CMAKE_OSX_SYSROOT_INT}\" CACHE INTERNAL \"\")\n  # Specify the location or name of the platform SDK to be used in CMAKE_OSX_SYSROOT.\n  set(CMAKE_OSX_SYSROOT \"${CMAKE_OSX_SYSROOT_INT}\" CACHE INTERNAL \"\")\nendif()\n\n# Use bitcode or not\nif(NOT DEFINED ENABLE_BITCODE)\n  message(STATUS \"[DEFAULTS] Disabling bitcode support by default. ENABLE_BITCODE not provided for override!\")\n  set(ENABLE_BITCODE OFF)\nendif()\nset(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL\n        \"Whether or not to enable bitcode\" FORCE)\n# Use ARC or not\nif(NOT DEFINED ENABLE_ARC)\n  # Unless specified, enable ARC support by default\n  set(ENABLE_ARC ON)\n  message(STATUS \"[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!\")\nendif()\nset(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL \"Whether or not to enable ARC\" FORCE)\n# Use hidden visibility or not\nif(NOT DEFINED ENABLE_VISIBILITY)\n  # Unless specified, disable symbols visibility by default\n  set(ENABLE_VISIBILITY OFF)\n  message(STATUS \"[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!\")\nendif()\nset(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL \"Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)\" FORCE)\n# Set strict compiler checks or not\nif(NOT DEFINED ENABLE_STRICT_TRY_COMPILE)\n  # Unless specified, disable strict try_compile()\n  set(ENABLE_STRICT_TRY_COMPILE OFF)\n  message(STATUS \"[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!\")\nendif()\nset(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL\n        \"Whether or not to use strict compiler checks\" FORCE)\n\n# Get the SDK version information.\nif(DEFINED SDK_VERSION)\n  # Environment variables are always preserved.\n  set(ENV{_SDK_VERSION} \"${SDK_VERSION}\")\nelseif(DEFINED ENV{_SDK_VERSION})\n  set(SDK_VERSION \"$ENV{_SDK_VERSION}\")\nelseif(NOT DEFINED SDK_VERSION)\n  execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -sdk ${CMAKE_OSX_SYSROOT_INT} -version SDKVersion\n          OUTPUT_VARIABLE SDK_VERSION\n          ERROR_QUIET\n          OUTPUT_STRIP_TRAILING_WHITESPACE)\nendif()\n\n# Find the Developer root for the specific iOS platform being compiled for\n# from CMAKE_OSX_SYSROOT.  Should be ../../ from SDK specified in\n# CMAKE_OSX_SYSROOT. There does not appear to be a direct way to obtain\n# this information from xcrun or xcodebuild.\nif (NOT DEFINED CMAKE_DEVELOPER_ROOT AND NOT CMAKE_GENERATOR MATCHES \"Xcode\")\n  get_filename_component(PLATFORM_SDK_DIR ${CMAKE_OSX_SYSROOT_INT} PATH)\n  get_filename_component(CMAKE_DEVELOPER_ROOT ${PLATFORM_SDK_DIR} PATH)\n  if (NOT EXISTS \"${CMAKE_DEVELOPER_ROOT}\")\n    message(FATAL_ERROR \"Invalid CMAKE_DEVELOPER_ROOT: ${CMAKE_DEVELOPER_ROOT} does not exist.\")\n  endif()\nendif()\n\n# Find the C & C++ compilers for the specified SDK.\nif(DEFINED CMAKE_C_COMPILER)\n  # Environment variables are always preserved.\n  set(ENV{_CMAKE_C_COMPILER} \"${CMAKE_C_COMPILER}\")\nelseif(DEFINED ENV{_CMAKE_C_COMPILER})\n  set(CMAKE_C_COMPILER \"$ENV{_CMAKE_C_COMPILER}\")\n  set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})\nelseif(NOT DEFINED CMAKE_C_COMPILER)\n  execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang\n          OUTPUT_VARIABLE CMAKE_C_COMPILER\n          ERROR_QUIET\n          OUTPUT_STRIP_TRAILING_WHITESPACE)\n  set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})\nendif()\nif(DEFINED CMAKE_CXX_COMPILER)\n  # Environment variables are always preserved.\n  set(ENV{_CMAKE_CXX_COMPILER} \"${CMAKE_CXX_COMPILER}\")\nelseif(DEFINED ENV{_CMAKE_CXX_COMPILER})\n  set(CMAKE_CXX_COMPILER \"$ENV{_CMAKE_CXX_COMPILER}\")\nelseif(NOT DEFINED CMAKE_CXX_COMPILER)\n  execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang++\n          OUTPUT_VARIABLE CMAKE_CXX_COMPILER\n          ERROR_QUIET\n          OUTPUT_STRIP_TRAILING_WHITESPACE)\nendif()\n# Find (Apple's) libtool.\nif(DEFINED BUILD_LIBTOOL)\n  # Environment variables are always preserved.\n  set(ENV{_BUILD_LIBTOOL} \"${BUILD_LIBTOOL}\")\nelseif(DEFINED ENV{_BUILD_LIBTOOL})\n  set(BUILD_LIBTOOL \"$ENV{_BUILD_LIBTOOL}\")\nelseif(NOT DEFINED BUILD_LIBTOOL)\n  execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find libtool\n          OUTPUT_VARIABLE BUILD_LIBTOOL\n          ERROR_QUIET\n          OUTPUT_STRIP_TRAILING_WHITESPACE)\nendif()\n# Find the toolchain's provided install_name_tool if none is found on the host\nif(DEFINED CMAKE_INSTALL_NAME_TOOL)\n  # Environment variables are always preserved.\n  set(ENV{_CMAKE_INSTALL_NAME_TOOL} \"${CMAKE_INSTALL_NAME_TOOL}\")\nelseif(DEFINED ENV{_CMAKE_INSTALL_NAME_TOOL})\n  set(CMAKE_INSTALL_NAME_TOOL \"$ENV{_CMAKE_INSTALL_NAME_TOOL}\")\nelseif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL)\n  execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find install_name_tool\n          OUTPUT_VARIABLE CMAKE_INSTALL_NAME_TOOL_INT\n          ERROR_QUIET\n          OUTPUT_STRIP_TRAILING_WHITESPACE)\n  set(CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL_INT} CACHE INTERNAL \"\")\nendif()\n\n# Configure libtool to be used instead of ar + ranlib to build static libraries.\n# This is required on Xcode 7+, but should also work on previous versions of\n# Xcode.\nget_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)\nforeach(lang ${languages})\n  set(CMAKE_${lang}_CREATE_STATIC_LIBRARY \"${BUILD_LIBTOOL} -static -o <TARGET> <LINK_FLAGS> <OBJECTS> \" CACHE INTERNAL \"\")\nendforeach()\n\n# CMake 3.14+ support building for iOS, watchOS, and tvOS out of the box.\nif(MODERN_CMAKE)\n  if(SDK_NAME MATCHES \"iphone\")\n    set(CMAKE_SYSTEM_NAME iOS)\n  elseif(SDK_NAME MATCHES \"xros\")\n      set(CMAKE_SYSTEM_NAME visionOS)\n  elseif(SDK_NAME MATCHES \"xrsimulator\")\n      set(CMAKE_SYSTEM_NAME visionOS)\n  elseif(SDK_NAME MATCHES \"macosx\")\n    set(CMAKE_SYSTEM_NAME Darwin)\n  elseif(SDK_NAME MATCHES \"appletv\")\n    set(CMAKE_SYSTEM_NAME tvOS)\n  elseif(SDK_NAME MATCHES \"watch\")\n    set(CMAKE_SYSTEM_NAME watchOS)\n  endif()\n  # Provide flags for a combined FAT library build on newer CMake versions\n  if(PLATFORM_INT MATCHES \".*COMBINED\")\n    set(CMAKE_IOS_INSTALL_COMBINED YES)\n    if(CMAKE_GENERATOR MATCHES \"Xcode\")\n      # Set the SDKROOT Xcode properties to a Xcode-friendly value (the SDK_NAME, E.g, iphoneos)\n      # This way, Xcode will automatically switch between the simulator and device SDK when building.\n      set(CMAKE_XCODE_ATTRIBUTE_SDKROOT \"${SDK_NAME}\")\n      # Force to not build just one ARCH, but all!\n      set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH \"NO\")\n    endif()\n  endif()\nelseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.10\")\n  # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified\n  set(CMAKE_SYSTEM_NAME iOS)\nelseif(NOT DEFINED CMAKE_SYSTEM_NAME)\n  # Legacy code path before CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified\n  set(CMAKE_SYSTEM_NAME Darwin)\nendif()\n# Standard settings.\nset(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL \"\")\nset(UNIX ON CACHE BOOL \"\")\nset(APPLE ON CACHE BOOL \"\")\nif(PLATFORM STREQUAL \"MAC\" OR PLATFORM STREQUAL \"MAC_ARM64\" OR PLATFORM STREQUAL \"MAC_UNIVERSAL\")\n  set(IOS OFF CACHE BOOL \"\")\n  set(MACOS ON CACHE BOOL \"\")\nelseif(PLATFORM STREQUAL \"MAC_CATALYST\" OR PLATFORM STREQUAL \"MAC_CATALYST_ARM64\" OR PLATFORM STREQUAL \"MAC_CATALYST_UNIVERSAL\")\n  set(IOS ON CACHE BOOL \"\")\n  set(MACOS ON CACHE BOOL \"\")\nelseif(PLATFORM STREQUAL \"VISIONOS\" OR PLATFORM STREQUAL \"SIMULATOR_VISIONOS\" OR PLATFORM STREQUAL \"VISIONOSCOMBINED\")\n  set(IOS OFF CACHE BOOL \"\")\n  set(VISIONOS ON CACHE BOOL \"\")\nelse()\n  set(IOS ON CACHE BOOL \"\")\nendif()\n# Set the architectures for which to build.\nset(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL \"\")\n# Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks\nif(NOT ENABLE_STRICT_TRY_COMPILE_INT)\n  set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)\nendif()\n# All iOS/Darwin specific settings - some may be redundant.\nif (NOT DEFINED CMAKE_MACOSX_BUNDLE)\n  set(CMAKE_MACOSX_BUNDLE YES)\nendif()\nset(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED \"NO\")\nset(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED \"NO\")\nset(CMAKE_SHARED_LIBRARY_PREFIX \"lib\")\nset(CMAKE_SHARED_LIBRARY_SUFFIX \".dylib\")\nset(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES \".tbd\" \".so\")\nset(CMAKE_SHARED_MODULE_PREFIX \"lib\")\nset(CMAKE_SHARED_MODULE_SUFFIX \".so\")\nset(CMAKE_C_COMPILER_ABI ELF)\nset(CMAKE_CXX_COMPILER_ABI ELF)\nset(CMAKE_C_HAS_ISYSROOT 1)\nset(CMAKE_CXX_HAS_ISYSROOT 1)\nset(CMAKE_MODULE_EXISTS 1)\nset(CMAKE_DL_LIBS \"\")\nset(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG \"-compatibility_version \")\nset(CMAKE_C_OSX_CURRENT_VERSION_FLAG \"-current_version \")\nset(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG \"${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}\")\nset(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG \"${CMAKE_C_OSX_CURRENT_VERSION_FLAG}\")\n\nif(ARCHS MATCHES \"((^|;|, )(arm64|arm64e|x86_64))+\")\n  set(CMAKE_C_SIZEOF_DATA_PTR 8)\n  set(CMAKE_CXX_SIZEOF_DATA_PTR 8)\n  if(ARCHS MATCHES \"((^|;|, )(arm64|arm64e))+\")\n    set(CMAKE_SYSTEM_PROCESSOR \"aarch64\")\n  else()\n    set(CMAKE_SYSTEM_PROCESSOR \"x86_64\")\n  endif()\nelse()\n  set(CMAKE_C_SIZEOF_DATA_PTR 4)\n  set(CMAKE_CXX_SIZEOF_DATA_PTR 4)\n  set(CMAKE_SYSTEM_PROCESSOR \"arm\")\nendif()\n\n# Note that only Xcode 7+ supports the newer more specific:\n# -m${SDK_NAME}-version-min flags, older versions of Xcode use:\n# -m(ios/ios-simulator)-version-min instead.\nif(${CMAKE_VERSION} VERSION_LESS \"3.11\")\n  if(PLATFORM_INT STREQUAL \"OS\" OR PLATFORM_INT STREQUAL \"OS64\")\n    if(XCODE_VERSION_INT VERSION_LESS 7.0)\n      set(SDK_NAME_VERSION_FLAGS\n              \"-mios-version-min=${DEPLOYMENT_TARGET}\")\n    else()\n      # Xcode 7.0+ uses flags we can build directly from SDK_NAME.\n      set(SDK_NAME_VERSION_FLAGS\n              \"-m${SDK_NAME}-version-min=${DEPLOYMENT_TARGET}\")\n    endif()\n  elseif(PLATFORM_INT STREQUAL \"TVOS\")\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mtvos-version-min=${DEPLOYMENT_TARGET}\")\n  elseif(PLATFORM_INT STREQUAL \"SIMULATOR_TVOS\")\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}\")\nelseif(PLATFORM_INT STREQUAL \"SIMULATORARM64_TVOS\")\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}\")\n  elseif(PLATFORM_INT STREQUAL \"WATCHOS\")\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mwatchos-version-min=${DEPLOYMENT_TARGET}\")\n  elseif(PLATFORM_INT STREQUAL \"SIMULATOR_WATCHOS\")\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}\")\n  elseif(PLATFORM_INT STREQUAL \"SIMULATORARM64_WATCHOS\")\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}\")\n  elseif(PLATFORM_INT STREQUAL \"MAC\")\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mmacosx-version-min=${DEPLOYMENT_TARGET}\")\n  else()\n    # SIMULATOR or SIMULATOR64 both use -mios-simulator-version-min.\n    set(SDK_NAME_VERSION_FLAGS\n            \"-mios-simulator-version-min=${DEPLOYMENT_TARGET}\")\n  endif()\nelseif(NOT PLATFORM_INT MATCHES \"^MAC_CATALYST\")\n  # Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets\n  set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} CACHE INTERNAL \"Minimum OS X deployment version\")\nendif()\n\nif(DEFINED APPLE_TARGET_TRIPLE_INT)\n  set(APPLE_TARGET_TRIPLE ${APPLE_TARGET_TRIPLE_INT} CACHE INTERNAL \"\")\n  set(CMAKE_C_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})\n  set(CMAKE_CXX_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})\n  set(CMAKE_ASM_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})\nendif()\n\nif(PLATFORM_INT MATCHES \"^MAC_CATALYST\")\n  set(C_TARGET_FLAGS \"-isystem ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/usr/include -iframework ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks\")\nendif()\n\nif(ENABLE_BITCODE_INT)\n  set(BITCODE \"-fembed-bitcode\")\n  set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE \"bitcode\")\n  set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE \"YES\")\nelse()\n  set(BITCODE \"\")\n  set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE \"NO\")\nendif()\n\nif(ENABLE_ARC_INT)\n  set(FOBJC_ARC \"-fobjc-arc\")\n  set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC \"YES\")\nelse()\n  set(FOBJC_ARC \"-fno-objc-arc\")\n  set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC \"NO\")\nendif()\n\nif(NAMED_LANGUAGE_SUPPORT_INT)\n  set(OBJC_VARS \"-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0\")\n  set(OBJC_LEGACY_VARS \"\")\nelse()\n  set(OBJC_VARS \"\")\n  set(OBJC_LEGACY_VARS \"-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0\")\nendif()\n\nif(NOT ENABLE_VISIBILITY_INT)\n  foreach(lang ${languages})\n    set(CMAKE_${lang}_VISIBILITY_PRESET \"hidden\" CACHE INTERNAL \"\")\n  endforeach()\n  set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN \"YES\")\n  set(VISIBILITY \"-fvisibility=hidden -fvisibility-inlines-hidden\")\nelse()\n  foreach(lang ${languages})\n    set(CMAKE_${lang}_VISIBILITY_PRESET \"default\" CACHE INTERNAL \"\")\n  endforeach()\n  set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN \"NO\")\n  set(VISIBILITY \"-fvisibility=default\")\nendif()\n\nif(DEFINED APPLE_TARGET_TRIPLE)\n  set(APPLE_TARGET_TRIPLE_FLAG \"-target ${APPLE_TARGET_TRIPLE}\")\nendif()\n\n#Check if Xcode generator is used since that will handle these flags automagically\nif(CMAKE_GENERATOR MATCHES \"Xcode\")\n  message(STATUS \"Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.\")\nelse()\n  set(CMAKE_C_FLAGS \"${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler during all C build types.\")\n  set(CMAKE_C_FLAGS_DEBUG \"-O0 -g ${CMAKE_C_FLAGS_DEBUG}\")\n  set(CMAKE_C_FLAGS_MINSIZEREL \"-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}\")\n  set(CMAKE_C_FLAGS_RELWITHDEBINFO \"-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}\")\n  set(CMAKE_C_FLAGS_RELEASE \"-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}\")\n  set(CMAKE_CXX_FLAGS \"${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler during all CXX build types.\")\n  set(CMAKE_CXX_FLAGS_DEBUG \"-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}\")\n  set(CMAKE_CXX_FLAGS_MINSIZEREL \"-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}\")\n  set(CMAKE_CXX_FLAGS_RELWITHDEBINFO \"-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}\")\n  set(CMAKE_CXX_FLAGS_RELEASE \"-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}\")\n  if(NAMED_LANGUAGE_SUPPORT_INT)\n    set(CMAKE_OBJC_FLAGS \"${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler during all OBJC build types.\")\n    set(CMAKE_OBJC_FLAGS_DEBUG \"-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}\")\n    set(CMAKE_OBJC_FLAGS_MINSIZEREL \"-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}\")\n    set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO \"-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}\")\n    set(CMAKE_OBJC_FLAGS_RELEASE \"-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}\")\n    set(CMAKE_OBJCXX_FLAGS \"${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler during all OBJCXX build types.\")\n    set(CMAKE_OBJCXX_FLAGS_DEBUG \"-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}\")\n    set(CMAKE_OBJCXX_FLAGS_MINSIZEREL \"-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}\")\n    set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO \"-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}\")\n    set(CMAKE_OBJCXX_FLAGS_RELEASE \"-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}\")\n  endif()\n  set(CMAKE_C_LINK_FLAGS \"${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler for all C link types.\")\n  set(CMAKE_CXX_LINK_FLAGS \"${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS}  -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler for all CXX link types.\")\n  if(NAMED_LANGUAGE_SUPPORT_INT)\n    set(CMAKE_OBJC_LINK_FLAGS \"${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler for all OBJC link types.\")\n    set(CMAKE_OBJCXX_LINK_FLAGS \"${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}\" CACHE INTERNAL\n     \"Flags used by the compiler for all OBJCXX link types.\")\n  endif()\n  set(CMAKE_ASM_FLAGS \"${CMAKE_C_FLAGS} -x assembler-with-cpp -arch ${CMAKE_OSX_ARCHITECTURES} ${APPLE_TARGET_TRIPLE_FLAG}\" CACHE INTERNAL\n     \"Flags used by the compiler for all ASM build types.\")\nendif()\n\n## Print status messages to inform of the current state\nmessage(STATUS \"Configuring ${SDK_NAME} build for platform: ${PLATFORM_INT}, architecture(s): ${ARCHS}\")\nmessage(STATUS \"Using SDK: ${CMAKE_OSX_SYSROOT_INT}\")\nmessage(STATUS \"Using C compiler: ${CMAKE_C_COMPILER}\")\nmessage(STATUS \"Using CXX compiler: ${CMAKE_CXX_COMPILER}\")\nmessage(STATUS \"Using libtool: ${BUILD_LIBTOOL}\")\nmessage(STATUS \"Using install name tool: ${CMAKE_INSTALL_NAME_TOOL}\")\nif(DEFINED APPLE_TARGET_TRIPLE)\n  message(STATUS \"Autoconf target triple: ${APPLE_TARGET_TRIPLE}\")\nendif()\nmessage(STATUS \"Using minimum deployment version: ${DEPLOYMENT_TARGET}\"\n        \" (SDK version: ${SDK_VERSION})\")\nif(MODERN_CMAKE)\n  message(STATUS \"Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!\")\n  if(PLATFORM_INT MATCHES \".*COMBINED\")\n    message(STATUS \"Will combine built (static) artifacts into FAT lib...\")\n  endif()\nendif()\nif(CMAKE_GENERATOR MATCHES \"Xcode\")\n  message(STATUS \"Using Xcode version: ${XCODE_VERSION_INT}\")\nendif()\nmessage(STATUS \"CMake version: ${CMAKE_VERSION}\")\nif(DEFINED SDK_NAME_VERSION_FLAGS)\n  message(STATUS \"Using version flags: ${SDK_NAME_VERSION_FLAGS}\")\nendif()\nmessage(STATUS \"Using a data_ptr size of: ${CMAKE_CXX_SIZEOF_DATA_PTR}\")\nif(ENABLE_BITCODE_INT)\n  message(STATUS \"Bitcode: Enabled\")\nelse()\n  message(STATUS \"Bitcode: Disabled\")\nendif()\n\nif(ENABLE_ARC_INT)\n  message(STATUS \"ARC: Enabled\")\nelse()\n  message(STATUS \"ARC: Disabled\")\nendif()\n\nif(ENABLE_VISIBILITY_INT)\n  message(STATUS \"Hiding symbols: Disabled\")\nelse()\n  message(STATUS \"Hiding symbols: Enabled\")\nendif()\n\n# Set global properties\nset_property(GLOBAL PROPERTY PLATFORM \"${PLATFORM}\")\nset_property(GLOBAL PROPERTY APPLE_TARGET_TRIPLE \"${APPLE_TARGET_TRIPLE_INT}\")\nset_property(GLOBAL PROPERTY SDK_VERSION \"${SDK_VERSION}\")\nset_property(GLOBAL PROPERTY XCODE_VERSION \"${XCODE_VERSION_INT}\")\nset_property(GLOBAL PROPERTY OSX_ARCHITECTURES \"${CMAKE_OSX_ARCHITECTURES}\")\n\n# Export configurable variables for the try_compile() command.\nset(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES\n        PLATFORM\n        XCODE_VERSION_INT\n        SDK_VERSION\n        NAMED_LANGUAGE_SUPPORT\n        DEPLOYMENT_TARGET\n        CMAKE_DEVELOPER_ROOT\n        CMAKE_OSX_SYSROOT_INT\n        ENABLE_BITCODE\n        ENABLE_ARC\n        CMAKE_ASM_COMPILER\n        CMAKE_C_COMPILER\n        CMAKE_C_COMPILER_TARGET\n        CMAKE_CXX_COMPILER\n        CMAKE_CXX_COMPILER_TARGET\n        BUILD_LIBTOOL\n        CMAKE_INSTALL_NAME_TOOL\n        CMAKE_C_FLAGS\n        CMAKE_C_DEBUG\n        CMAKE_C_MINSIZEREL\n        CMAKE_C_RELWITHDEBINFO\n        CMAKE_C_RELEASE\n        CMAKE_CXX_FLAGS\n        CMAKE_CXX_FLAGS_DEBUG\n        CMAKE_CXX_FLAGS_MINSIZEREL\n        CMAKE_CXX_FLAGS_RELWITHDEBINFO\n        CMAKE_CXX_FLAGS_RELEASE\n        CMAKE_C_LINK_FLAGS\n        CMAKE_CXX_LINK_FLAGS\n        CMAKE_ASM_FLAGS\n)\n\nif(NAMED_LANGUAGE_SUPPORT_INT)\n  list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES \n        CMAKE_OBJC_FLAGS\n        CMAKE_OBJC_DEBUG\n        CMAKE_OBJC_MINSIZEREL\n        CMAKE_OBJC_RELWITHDEBINFO\n        CMAKE_OBJC_RELEASE\n        CMAKE_OBJCXX_FLAGS\n        CMAKE_OBJCXX_DEBUG\n        CMAKE_OBJCXX_MINSIZEREL\n        CMAKE_OBJCXX_RELWITHDEBINFO\n        CMAKE_OBJCXX_RELEASE\n        CMAKE_OBJC_LINK_FLAGS\n        CMAKE_OBJCXX_LINK_FLAGS\n  )\nendif()\n\nset(CMAKE_PLATFORM_HAS_INSTALLNAME 1)\nset(CMAKE_SHARED_LINKER_FLAGS \"-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks\")\nset(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS \"-dynamiclib -Wl,-headerpad_max_install_names\")\nset(CMAKE_SHARED_MODULE_CREATE_C_FLAGS \"-bundle -Wl,-headerpad_max_install_names\")\nset(CMAKE_SHARED_MODULE_LOADER_C_FLAG \"-Wl,-bundle_loader,\")\nset(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG \"-Wl,-bundle_loader,\")\nset(CMAKE_FIND_LIBRARY_SUFFIXES \".tbd\" \".dylib\" \".so\" \".a\")\nset(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG \"-install_name\")\n\n# Set the find root to the SDK developer roots.\n# Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds.\nif(NOT PLATFORM_INT MATCHES \"^MAC.*$\")\n  list(APPEND CMAKE_FIND_ROOT_PATH \"${CMAKE_OSX_SYSROOT_INT}\" CACHE INTERNAL \"\")\n  set(CMAKE_IGNORE_PATH \"/System/Library/Frameworks;/usr/local/lib;/opt/homebrew\" CACHE INTERNAL \"\")\nendif()\n\n# Default to searching for frameworks first.\nIF(NOT DEFINED CMAKE_FIND_FRAMEWORK)\n  set(CMAKE_FIND_FRAMEWORK FIRST)\nENDIF(NOT DEFINED CMAKE_FIND_FRAMEWORK)\n\n# Set up the default search directories for frameworks.\nif(PLATFORM_INT MATCHES \"^MAC_CATALYST\") \n  set(CMAKE_FRAMEWORK_PATH\n          ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks\n          ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks\n          ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks\n          ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL \"\")\nelse()\n  set(CMAKE_FRAMEWORK_PATH\n          ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks\n          ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks\n          ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL \"\")\nendif()\n\n# By default, search both the specified iOS SDK and the remainder of the host filesystem.\nif(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)\n  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL \"\")\nendif()\nif(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)\n  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL \"\")\nendif()\nif(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)\n  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL \"\")\nendif()\nif(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)\n  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL \"\")\nendif()\n\n#\n# Some helper-macros below to simplify and beautify the CMakeFile\n#\n\n# This little macro lets you set any Xcode specific property.\nmacro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE XCODE_RELVERSION)\n  set(XCODE_RELVERSION_I \"${XCODE_RELVERSION}\")\n  if(XCODE_RELVERSION_I STREQUAL \"All\")\n    set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} \"${XCODE_VALUE}\")\n  else()\n    set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY}[variant=${XCODE_RELVERSION_I}] \"${XCODE_VALUE}\")\n  endif()\nendmacro(set_xcode_property)\n\n# This macro lets you find executable programs on the host system.\nmacro(find_host_package)\n  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\n  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)\n  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)\n  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER)\n  set(_TOOLCHAIN_IOS ${IOS})\n  set(IOS OFF)\n  find_package(${ARGN})\n  set(IOS ${_TOOLCHAIN_IOS})\n  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)\n  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)\n  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)\n  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)\nendmacro(find_host_package)\n"
  },
  {
    "path": "CMake/platforms/lepus.cmake",
    "content": "set(BUILD_ASSETS_MPQ OFF)\r\nset(USE_SDL1 ON)\r\n\r\nset(SDL1_VIDEO_MODE_BPP 8)\r\nset(SDL1_VIDEO_MODE_FLAGS SDL_HWSURFACE|SDL_TRIPLEBUF)\r\nset(SDL1_FORCE_SVID_VIDEO_MODE ON)\r\n\r\nset(PREFILL_PLAYER_NAME ON)\r\n\r\nset(JOY_AXIS_LEFTX 0)\r\nset(JOY_AXIS_LEFTY 1)\r\nset(JOY_AXIS_RIGHTX 2)\r\nset(JOY_AXIS_RIGHTY 3)\r\n\r\n# OpenDingux Beta does not currently support X-OD-NeedsJoystick,\r\n# so we use KBCTRL instead. Unfortunately, this partially breaks\r\n# external mouse and keyboard support.\r\nset(HAS_KBCTRL 1)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT)\r\nset(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT)\r\nset(KBCTRL_BUTTON_DPAD_UP SDLK_UP)\r\nset(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN)\r\nset(KBCTRL_BUTTON_B SDLK_LCTRL)\r\nset(KBCTRL_BUTTON_A SDLK_LALT)\r\nset(KBCTRL_BUTTON_Y SDLK_SPACE)\r\nset(KBCTRL_BUTTON_X SDLK_LSHIFT)\r\nset(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_BACKSPACE)\r\nset(KBCTRL_BUTTON_LEFTSHOULDER SDLK_TAB)\r\nset(KBCTRL_BUTTON_START SDLK_RETURN)\r\nset(KBCTRL_BUTTON_BACK SDLK_ESCAPE) # Select\r\nset(KBCTRL_BUTTON_TRIGGERLEFT SDLK_PAGEUP)\r\nset(KBCTRL_BUTTON_TRIGGERRIGHT SDLK_PAGEDOWN)\r\nset(KBCTRL_BUTTON_LEFTSTICK SDLK_KP_DIVIDE)\r\nset(KBCTRL_BUTTON_RIGHTSTICK SDLK_KP_PERIOD)\r\n\r\n# Joystick mappings that have no effect on OpenDingux Beta:\r\nset(JOY_HAT_DPAD_UP_HAT 0)\r\nset(JOY_HAT_DPAD_UP 1)\r\nset(JOY_HAT_DPAD_DOWN_HAT 0)\r\nset(JOY_HAT_DPAD_DOWN 4)\r\nset(JOY_HAT_DPAD_LEFT_HAT 0)\r\nset(JOY_HAT_DPAD_LEFT 8)\r\nset(JOY_HAT_DPAD_RIGHT_HAT 0)\r\nset(JOY_HAT_DPAD_RIGHT 2)\r\nset(JOY_BUTTON_A 0)\r\nset(JOY_BUTTON_B 1)\r\nset(JOY_BUTTON_Y 2)\r\nset(JOY_BUTTON_X 3)\r\nset(JOY_BUTTON_RIGHTSHOULDER 5)\r\nset(JOY_BUTTON_LEFTSHOULDER 4)\r\nset(JOY_BUTTON_TRIGGERLEFT 6)\r\nset(JOY_BUTTON_TRIGGERRIGHT 7)\r\nset(JOY_BUTTON_START 9)\r\nset(JOY_BUTTON_BACK 8)\r\nset(JOY_BUTTON_LEFTSTICK 10)\r\nset(JOY_BUTTON_RIGHTSTICK 11)\r\n\r\n# Map Power button to Esc (Menu in-game / Exit in-menu).\r\nset(REMAP_KEYBOARD_KEYS \"{SDLK_HOME,SDLK_ESCAPE}\")\r\n"
  },
  {
    "path": "CMake/platforms/linux_i386.toolchain.cmake",
    "content": "message(STATUS \"Using 32-bit toolchain\")\r\n\r\nset(CMAKE_CXX_FLAGS -m32 CACHE STRING \"\")\r\nset(CMAKE_C_FLAGS -m32 CACHE STRING \"\")\r\n\r\n# Affects pkg-config\r\nset_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE)\r\n# Used by pkg-config on Debian\r\nset(CMAKE_LIBRARY_ARCHITECTURE i386-linux-gnu)\r\n# Silly hack required to get the pkg-config path code to activate\r\nlist(APPEND CMAKE_PREFIX_PATH /usr)\r\n\r\n# Find where 32-bit CMake modules are stored\r\nfind_path(DIR NAMES cmake PATHS /usr/lib32 /usr/lib/i386-linux-gnu NO_DEFAULT_PATH)\r\n\r\nif(DIR)\r\n    message(STATUS \"Using 32-bit libraries from ${DIR}\")\r\n    # Read CMake modules from 32-bit packages\r\n    # set(CMAKE_FIND_ROOT_PATH ${DIR})\r\n    # set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\n    # set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\n    # set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)\r\nendif()\r\n\r\nset(PKG_CONFIG_EXECUTABLE \"${CMAKE_CURRENT_LIST_DIR}/i386-linux-gnu-pkg-config\" CACHE STRING \"Path to pkg-config\")\r\n\r\n# 32-bit NASM\r\nset(CMAKE_ASM_NASM_OBJECT_FORMAT elf)\r\nset(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)\r\n"
  },
  {
    "path": "CMake/platforms/macos_tiger.cmake",
    "content": "# ASAN and UBSAN are not supported by macports gcc14 on PowerPC.\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\n\r\n# SDL2 does not build for Tiger, so we use SDL1 instead.\r\nset(USE_SDL1 ON)\r\n\r\n# ZeroTier is yet to be tested.\r\nset(DISABLE_ZERO_TIER ON)\r\n\r\n# Use vendored libfmt until this issue is resolved:\r\n# https://trac.macports.org/ticket/71503\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\nset(DEVILUTIONX_STATIC_LIBFMT ON)\r\n\r\n# https://trac.macports.org/ticket/71511\r\nset(DEVILUTIONX_SYSTEM_GOOGLETEST OFF)\r\nset(DEVILUTIONX_STATIC_GOOGLETEST OFF)\r\nset(DEVILUTIONX_SYSTEM_BENCHMARK OFF)\r\nset(DEVILUTIONX_STATIC_BENCHMARK OFF)\r\n"
  },
  {
    "path": "CMake/platforms/macports/finders/FindMacportsLegacySupport.cmake",
    "content": "# Provides missing functions, such as localtime_r\r\nif(NOT TARGET MacportsLegacySupport::MacportsLegacySupport)\r\n  set(MacportsLegacySupport_INCLUDE_DIR /opt/local/include/LegacySupport)\r\n  mark_as_advanced(MacportsLegacySupport_INCLUDE_DIR)\r\n\r\n  find_library(MacportsLegacySupport_LIBRARY NAMES MacportsLegacySupport\r\n    PATHS /opt/local/lib)\r\n  mark_as_advanced(MacportsLegacySupport_LIBRARY)\r\n\r\n  include(FindPackageHandleStandardArgs)\r\n  FIND_PACKAGE_HANDLE_STANDARD_ARGS(\r\n      MacportsLegacySupport\r\n      DEFAULT_MSG\r\n      MacportsLegacySupport_LIBRARY MacportsLegacySupport_INCLUDE_DIR)\r\n\r\n  if(MacportsLegacySupport_FOUND)\r\n      set(MacportsLegacySupport_LIBRARIES ${MacportsLegacySupport_LIBRARY})\r\n      set(MacportsLegacySupport_INCLUDE_DIRS ${MacportsLegacySupport_INCLUDE_DIR})\r\n      add_library(MacportsLegacySupport::MacportsLegacySupport UNKNOWN IMPORTED)\r\n      set_target_properties(\r\n        MacportsLegacySupport::MacportsLegacySupport PROPERTIES\r\n        INTERFACE_INCLUDE_DIRECTORIES \"${MacportsLegacySupport_INCLUDE_DIR}\"\r\n      )\r\n      set_target_properties(\r\n        MacportsLegacySupport::MacportsLegacySupport PROPERTIES\r\n        IMPORTED_LINK_INTERFACE_LANGUAGES \"C\"\r\n        IMPORTED_LOCATION \"${MacportsLegacySupport_LIBRARY}\"\r\n      )\r\n  endif()\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/mingw/zt_defs.cmake",
    "content": "option(MINGW_STDTHREADS_GENERATE_STDHEADERS \"\" OFF)\r\n\r\n# Workaround for deprecation of older CMake versions\r\nset(CMAKE_POLICY_VERSION_MINIMUM 3.22)\r\n\r\nFetchContent_Declare_ExcludeFromAll(mingw-std-threads\r\n  GIT_REPOSITORY https://github.com/meganz/mingw-std-threads\r\n  GIT_TAG bee085c0a6cb32c59f0b55c7bba976fe6dcfca7f)\r\nFetchContent_MakeAvailable_ExcludeFromAll(mingw-std-threads)\r\n\r\ntarget_compile_definitions(libnatpmp_obj PRIVATE -D_WIN32_WINNT=0x601 -DSTATICLIB)\r\ntarget_compile_definitions(zto_obj PRIVATE -D_WIN32_WINNT=0x601)\r\ntarget_compile_definitions(zto_pic PRIVATE -D_WIN32_WINNT=0x601)\r\ntarget_compile_definitions(libzt_obj PRIVATE -D_WIN32_WINNT=0x601)\r\ntarget_compile_definitions(zt_pic PRIVATE -D_WIN32_WINNT=0x601)\r\ntarget_compile_definitions(${libzt_LIB_NAME} PRIVATE -D_WIN32_WINNT=0x601 -DADD_EXPORTS=1)\r\ntarget_compile_definitions(${libzt_LIB_NAME} PUBLIC -DADD_EXPORTS=1)\r\ntarget_link_libraries(libzt_obj PRIVATE mingw_stdthreads)\r\ntarget_link_libraries(${libzt_LIB_NAME} mingw_stdthreads)\r\n"
  },
  {
    "path": "CMake/platforms/mingw9x/include/windef.h",
    "content": "#ifndef _WINDEF_OVERRIDE_\r\n#define _WINDEF_OVERRIDE_\r\n\r\n#include_next <windef.h>\r\n\r\n// MinGW does not define these when _WIN32_WINNT < 0x0400\r\n// but it declares functions that use it unconditionally.\r\ntypedef enum _FINDEX_INFO_LEVELS {\r\n\tFindExInfoStandard,\r\n\tFindExInfoBasic,\r\n\tFindExInfoMaxInfoLevel\r\n} FINDEX_INFO_LEVELS;\r\ntypedef enum _FINDEX_SEARCH_OPS {\r\n\tFindExSearchNameMatch,\r\n\tFindExSearchLimitToDirectories,\r\n\tFindExSearchLimitToDevices,\r\n\tFindExSearchMaxSearchOp\r\n} FINDEX_SEARCH_OPS;\r\n\r\ntypedef void* SOLE_AUTHENTICATION_SERVICE;\r\n\r\n#endif /* _WINDEF_ */\r\n"
  },
  {
    "path": "CMake/platforms/mingw9x.toolchain.cmake",
    "content": "SET(MINGW_CROSS TRUE)\r\n\r\nSET(CROSS_PREFIX \"/usr\" CACHE STRING \"crosstool-NG prefix\")\r\n\r\nSET(CMAKE_SYSTEM_NAME Windows)\r\n\r\n# workaround\r\nlist(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES \"${CROSS_PREFIX}/i686-w64-mingw32/include\")\r\n\r\nlist(PREPEND CMAKE_C_STANDARD_INCLUDE_DIRECTORIES \"${CMAKE_CURRENT_LIST_DIR}/mingw9x/include\")\r\nlist(PREPEND CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES \"${CMAKE_CURRENT_LIST_DIR}/mingw9x/include\")\r\n\r\n# work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106103\r\nset(CMAKE_CXX_FLAGS_MINSIZEREL_INIT \"${CMAKE_CXX_FLAGS_MINSIZEREL_INIT} -fno-declone-ctor-dtor\")\r\n\r\nSET(CMAKE_C_COMPILER   \"i686-w64-mingw32-gcc\")\r\nSET(CMAKE_CXX_COMPILER \"i686-w64-mingw32-g++\")\r\nset(CMAKE_RC_COMPILER \"i686-w64-mingw32-windres\")\r\nset(CMAKE_STRIP \"${CROSS_PREFIX}/i686-w64-mingw32/bin/strip\")\r\nset(PKG_CONFIG_EXECUTABLE \"${CROSS_PREFIX}/bin/i686-w64-mingw32-pkg-config\" CACHE STRING \"Path to pkg-config\")\r\n\r\nSET(CMAKE_FIND_ROOT_PATH  \"${CROSS_PREFIX}/i686-w64-mingw32\" \"${CROSS_PREFIX}/i686-w64-mingw32/i686-w64-mingw32\")\r\n\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\n\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\r\n\r\nset(WIN32_INSTALL_DLLS \"${CROSS_PREFIX}/i686-w64-mingw32/bin/SDL.dll\")\r\n"
  },
  {
    "path": "CMake/platforms/mingwcc.toolchain.cmake",
    "content": "SET(MINGW_CROSS TRUE)\r\n\r\nSET(CROSS_PREFIX \"/usr\" CACHE STRING \"crosstool-NG prefix\")\r\n\r\nSET(CMAKE_SYSTEM_NAME Windows)\r\n\r\n# workaround\r\nlist(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES \"${CROSS_PREFIX}/i686-w64-mingw32/include\")\r\n\r\nSET(CMAKE_C_COMPILER   \"i686-w64-mingw32-gcc\")\r\nSET(CMAKE_CXX_COMPILER \"i686-w64-mingw32-g++\")\r\nset(CMAKE_RC_COMPILER \"i686-w64-mingw32-windres\")\r\nset(CMAKE_STRIP \"${CROSS_PREFIX}/i686-w64-mingw32/bin/strip\")\r\nset(PKG_CONFIG_EXECUTABLE \"${CROSS_PREFIX}/bin/i686-w64-mingw32-pkg-config\" CACHE STRING \"Path to pkg-config\")\r\n\r\nSET(CMAKE_FIND_ROOT_PATH  \"${CROSS_PREFIX}/i686-w64-mingw32\" \"${CROSS_PREFIX}/i686-w64-mingw32/i686-w64-mingw32\")\r\n\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\n\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\r\n"
  },
  {
    "path": "CMake/platforms/mingwcc64.toolchain.cmake",
    "content": "SET(MINGW_CROSS TRUE)\r\n\r\nSET(CROSS_PREFIX \"/usr\" CACHE STRING \"crosstool-NG prefix\")\r\n\r\nSET(CMAKE_SYSTEM_NAME Windows)\r\n\r\n# workaround\r\nlist(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES \"${CROSS_PREFIX}/x86_64-w64-mingw32/include\")\r\n\r\nSET(CMAKE_C_COMPILER   \"x86_64-w64-mingw32-gcc\")\r\nSET(CMAKE_CXX_COMPILER \"x86_64-w64-mingw32-g++\")\r\nset(CMAKE_RC_COMPILER \"x86_64-w64-mingw32-windres\")\r\nset(CMAKE_STRIP \"${CROSS_PREFIX}/x86_64-w64-mingw32/bin/strip\")\r\nset(PKG_CONFIG_EXECUTABLE \"${CROSS_PREFIX}/bin/x86_64-w64-mingw32-pkg-config\" CACHE STRING \"Path to pkg-config\")\r\n\r\nSET(CMAKE_FIND_ROOT_PATH  \"${CROSS_PREFIX}/x86_64-w64-mingw32\" \"${CROSS_PREFIX}/x86_64-w64-mingw32/x86_64-w64-mingw32\")\r\n\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\n\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\nSET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\r\nSET(SYSTEM_BITS x64)\r\n"
  },
  {
    "path": "CMake/platforms/miyoo_mini.cmake",
    "content": "set(USE_SDL1 ON)\r\nset(NONET ON)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\n\r\nset(SDL1_VIDEO_MODE_BPP 32)\r\nset(SDL1_VIDEO_MODE_FLAGS SDL_HWSURFACE)\r\nset(SDL1_FORCE_SVID_VIDEO_MODE ON)\r\n\r\nset(PREFILL_PLAYER_NAME ON)\r\nset(DEFAULT_AUDIO_SAMPLE_RATE 44100)\r\n\r\n# The mini's buttons are connected via GPIO and are mapped to keyboard inputs\r\nset(HAS_KBCTRL 1)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT)\r\nset(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT)\r\nset(KBCTRL_BUTTON_DPAD_UP SDLK_UP)\r\nset(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN)\r\nset(KBCTRL_BUTTON_B SDLK_SPACE)\r\nset(KBCTRL_BUTTON_A SDLK_LCTRL)\r\nset(KBCTRL_BUTTON_Y SDLK_LSHIFT)\r\nset(KBCTRL_BUTTON_X SDLK_LALT)\r\nset(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_t)\r\nset(KBCTRL_BUTTON_LEFTSHOULDER SDLK_e)\r\nset(KBCTRL_BUTTON_TRIGGERRIGHT SDLK_BACKSPACE)\r\nset(KBCTRL_BUTTON_TRIGGERLEFT SDLK_TAB)\r\nset(KBCTRL_BUTTON_START SDLK_RETURN)\r\nset(KBCTRL_BUTTON_BACK SDLK_RCTRL)\r\n"
  },
  {
    "path": "CMake/platforms/n3ds.cmake",
    "content": "#General compilation options\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(BUILD_TESTING OFF)\r\nset(BUILD_ASSETS_MPQ OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\nset(DEVILUTIONX_STATIC_LIBSODIUM ON)\r\nset(DEVILUTIONX_STATIC_LIBFMT ON)\r\nset(DISABLE_ZERO_TIER ON)\r\nset(LIBMPQ_FILE_BUFFER_SIZE 32768)\r\nset(NOEXIT ON)\r\n\r\n# 3DS libraries and compile definitions\r\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/ctr\")\r\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/ctr/modules\")\r\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/threads-stub\")\r\nfind_package(CITRO3D REQUIRED)\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_SUBDIRECTORIES platform/ctr)\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES libdevilutionx_ctr)\r\nlist(APPEND DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS __3DS__)\r\n\r\n# The 3ds build handles the stripping in a custom way.\r\nset(DEVILUTIONX_DISABLE_STRIP ON)\r\n\r\n#SDL video mode parameters\r\nset(USE_SDL1 ON)\r\nset(SDL1_VIDEO_MODE_FLAGS SDL_DOUBLEBUF|SDL_HWSURFACE)\r\nset(SDL1_FORCE_SVID_VIDEO_MODE ON)\r\nset(SDL1_VIDEO_MODE_BPP 8)\r\nset(DEFAULT_WIDTH 800)\r\nset(DEFAULT_HEIGHT 480)\r\nset(DEFAULT_PER_PIXEL_LIGHTING false)\r\n\r\n#Deploy assets to romfs\r\nset(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY \"${CMAKE_BINARY_DIR}/romfs\")\r\n\r\n#SDL Joystick axis mapping (circle-pad/C-stick)\r\nset(JOY_AXIS_LEFTX 0)\r\nset(JOY_AXIS_LEFTY 1)\r\nset(JOY_AXIS_RIGHTX 2)\r\nset(JOY_AXIS_RIGHTY 3)\r\n#SDL Joystick hat mapping (D-pad)\r\nset(JOY_HAT_DPAD_UP_HAT 0)\r\nset(JOY_HAT_DPAD_RIGHT_HAT 0)\r\nset(JOY_HAT_DPAD_DOWN_HAT 0)\r\nset(JOY_HAT_DPAD_LEFT_HAT 0)\r\nset(JOY_HAT_DPAD_UP 1)\r\nset(JOY_HAT_DPAD_RIGHT 2)\r\nset(JOY_HAT_DPAD_DOWN 4)\r\nset(JOY_HAT_DPAD_LEFT 8)\r\n#SDL Joystick button mapping (A / B and X / Y inverted)\r\nset(JOY_BUTTON_A 2)\r\nset(JOY_BUTTON_B 1)\r\nset(JOY_BUTTON_X 4)\r\nset(JOY_BUTTON_Y 3)\r\nset(JOY_BUTTON_LEFTSHOULDER 5)\r\nset(JOY_BUTTON_RIGHTSHOULDER 6)\r\nset(JOY_BUTTON_BACK 7)\r\nset(JOY_BUTTON_START 0)\r\nset(JOY_BUTTON_TRIGGERLEFT 8)\r\nset(JOY_BUTTON_TRIGGERRIGHT 9)\r\n#Additional gamepad related options\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(PREFILL_PLAYER_NAME ON)\r\n"
  },
  {
    "path": "CMake/platforms/ps4.cmake",
    "content": "set(DISCORD_INTEGRATION OFF)\r\nset(BUILD_TESTING OFF)\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\nSET(DISABLE_LTO ON)\r\nset(NONET ON)\r\nset(NOEXIT ON)\r\nset(DEVILUTIONX_GAMEPAD_TYPE PlayStation)\r\nset(BUILD_ASSETS_MPQ ON)\r\n\r\n# Packbrew SDK provides SDL_image, but FindSDL2_image() fails to\r\n# pick up its dependencies (with includes libjpeg, libwebp etc).\r\n# One way to address this, is to do the following:\r\n#\r\n#   target_link_libraries(${BIN_TARGET} PUBLIC ${PC_SDL2_image_LIBRARIES})\r\n#\r\n# or simply use the in-tree copy as follows:\r\nset(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\n\r\n# If the executable is stripped, create-fself fails with:\r\n# Failed to build FSELF: no symbol section\r\nset(DEVILUTIONX_DISABLE_STRIP ON)\r\n"
  },
  {
    "path": "CMake/platforms/retrofw.cmake",
    "content": "set(BUILD_ASSETS_MPQ OFF)\r\nset(NONET ON)\r\nset(USE_SDL1 ON)\r\nset(PREFILL_PLAYER_NAME ON)\r\nset(HAS_KBCTRL 1)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} -O3\")\r\nset(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT)\r\nset(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT)\r\nset(KBCTRL_BUTTON_DPAD_UP SDLK_UP)\r\nset(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN)\r\nset(KBCTRL_BUTTON_B SDLK_LCTRL)\r\nset(KBCTRL_BUTTON_A SDLK_LALT)\r\nset(KBCTRL_BUTTON_Y SDLK_SPACE)\r\nset(KBCTRL_BUTTON_X SDLK_LSHIFT)\r\nset(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_BACKSPACE)\r\nset(KBCTRL_BUTTON_LEFTSHOULDER SDLK_TAB)\r\nset(KBCTRL_BUTTON_START SDLK_RETURN)\r\nset(KBCTRL_BUTTON_LEFTSTICK SDLK_END) # Suspend\r\nset(KBCTRL_BUTTON_BACK SDLK_ESCAPE) # Select\r\nset(KBCTRL_IGNORE_1 SDLK_3) # Backlight\r\n"
  },
  {
    "path": "CMake/platforms/rg350.cmake",
    "content": "set(BUILD_ASSETS_MPQ OFF)\r\nset(USE_SDL1 ON)\r\n\r\n# LTO temporarily disabled to work around a compiler bug.\r\n# https://github.com/diasurgical/devilutionX/issues/4953\r\nset(DISABLE_LTO ON)\r\n\r\nset(SDL1_VIDEO_MODE_BPP 8)\r\nset(SDL1_VIDEO_MODE_FLAGS SDL_HWSURFACE|SDL_TRIPLEBUF)\r\nset(SDL1_FORCE_SVID_VIDEO_MODE ON)\r\n\r\nset(PREFILL_PLAYER_NAME ON)\r\n\r\nset(JOY_AXIS_LEFTX 0)\r\nset(JOY_AXIS_LEFTY 1)\r\nset(JOY_AXIS_RIGHTX 2)\r\nset(JOY_AXIS_RIGHTY 3)\r\n\r\n# OpenDingux Beta does not currently support X-OD-NeedsJoystick,\r\n# so we use KBCTRL instead. Unfortunately, this partially breaks\r\n# external mouse and keyboard support.\r\nset(HAS_KBCTRL 1)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT)\r\nset(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT)\r\nset(KBCTRL_BUTTON_DPAD_UP SDLK_UP)\r\nset(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN)\r\nset(KBCTRL_BUTTON_B SDLK_LCTRL)\r\nset(KBCTRL_BUTTON_A SDLK_LALT)\r\nset(KBCTRL_BUTTON_Y SDLK_SPACE)\r\nset(KBCTRL_BUTTON_X SDLK_LSHIFT)\r\nset(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_BACKSPACE)\r\nset(KBCTRL_BUTTON_LEFTSHOULDER SDLK_TAB)\r\nset(KBCTRL_BUTTON_START SDLK_RETURN)\r\nset(KBCTRL_BUTTON_BACK SDLK_ESCAPE) # Select\r\nset(KBCTRL_BUTTON_TRIGGERLEFT SDLK_PAGEUP)\r\nset(KBCTRL_BUTTON_TRIGGERRIGHT SDLK_PAGEDOWN)\r\nset(KBCTRL_BUTTON_LEFTSTICK SDLK_KP_DIVIDE)\r\nset(KBCTRL_BUTTON_RIGHTSTICK SDLK_KP_PERIOD)\r\n\r\n# Joystick mappings that have no effect on OpenDingux Beta:\r\nset(JOY_HAT_DPAD_UP_HAT 0)\r\nset(JOY_HAT_DPAD_UP 1)\r\nset(JOY_HAT_DPAD_DOWN_HAT 0)\r\nset(JOY_HAT_DPAD_DOWN 4)\r\nset(JOY_HAT_DPAD_LEFT_HAT 0)\r\nset(JOY_HAT_DPAD_LEFT 8)\r\nset(JOY_HAT_DPAD_RIGHT_HAT 0)\r\nset(JOY_HAT_DPAD_RIGHT 2)\r\nset(JOY_BUTTON_A 0)\r\nset(JOY_BUTTON_B 1)\r\nset(JOY_BUTTON_Y 2)\r\nset(JOY_BUTTON_X 3)\r\nset(JOY_BUTTON_RIGHTSHOULDER 5)\r\nset(JOY_BUTTON_LEFTSHOULDER 4)\r\nset(JOY_BUTTON_TRIGGERLEFT 6)\r\nset(JOY_BUTTON_TRIGGERRIGHT 7)\r\nset(JOY_BUTTON_START 9)\r\nset(JOY_BUTTON_BACK 8)\r\nset(JOY_BUTTON_LEFTSTICK 10)\r\nset(JOY_BUTTON_RIGHTSTICK 11)\r\n\r\n# Map Power button to Esc (Menu in-game / Exit in-menu).\r\nset(REMAP_KEYBOARD_KEYS \"{SDLK_HOME,SDLK_ESCAPE}\")\r\n"
  },
  {
    "path": "CMake/platforms/rg99.cmake",
    "content": "# RG99 has the same layout as RG300 but only 32 MiB RAM\r\nset(BUILD_ASSETS_MPQ OFF)\r\nset(UNPACKED_MPQS ON)\r\nset(UNPACKED_SAVES ON)\r\nset(NONET ON)\r\nset(USE_SDL1 ON)\r\n\r\n# Link `libstdc++` dynamically: ~1.3 MiB.\r\n# The OPK is mounted as squashfs and the binary is decompressed, while\r\n# the system `libstdc++` resides on disk.\r\nset(DEVILUTIONX_STATIC_CXX_STDLIB OFF)\r\n\r\n# -fmerge-all-constants saves ~4 KiB\r\n# -fsection-anchors saves ~4 KiB\r\nset(_extra_flags \"-fmerge-all-constants -fsection-anchors\")\r\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${_extra_flags}\")\r\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${_extra_flags}\")\r\n# -Wl,-z-stack-size: the default thread stack size for RG99 is 128 KiB, reduce it.\r\n#   https://wiki.musl-libc.org/functional-differences-from-glibc.html#Thread-stack-size\r\nset(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,stack-size=32768\")\r\n\r\n# 128 KiB\r\nset(DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT OFF)\r\n\r\n# Must stream most of the audio due to RAM constraints.\r\nset(STREAM_ALL_AUDIO_MIN_FILE_SIZE 4096)\r\n\r\n# Must use a smaller audio buffer due to RAM constraints.\r\nset(DEFAULT_AUDIO_BUFFER_SIZE 768)\r\n\r\n# Use lower resampling quality for FPS.\r\nset(DEFAULT_AUDIO_RESAMPLING_QUALITY 2)\r\n\r\n# RG-99 hardware scaler can only scale YUV.\r\n# The SDL library on RG-99 can convert 8-bit palettized surfaces to YUV automatically.\r\nset(SDL1_VIDEO_MODE_BPP 8)\r\nset(SDL1_FORCE_SVID_VIDEO_MODE ON)\r\nset(SDL1_FORCE_DIRECT_RENDER ON)\r\n\r\n# Must be an HWSURFACE for the scaler to work.\r\nset(SDL1_VIDEO_MODE_FLAGS SDL_HWSURFACE|SDL_FULLSCREEN)\r\n\r\n# Videos are 320x240, so they fit in video ram double-buffered.\r\nset(SDL1_VIDEO_MODE_SVID_FLAGS SDL_HWSURFACE|SDL_FULLSCREEN|SDL_DOUBLEBUF)\r\n\r\nset(PREFILL_PLAYER_NAME ON)\r\nset(HAS_KBCTRL 1)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT)\r\nset(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT)\r\nset(KBCTRL_BUTTON_DPAD_UP SDLK_UP)\r\nset(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN)\r\nset(KBCTRL_BUTTON_B SDLK_LCTRL)\r\nset(KBCTRL_BUTTON_A SDLK_LALT)\r\nset(KBCTRL_BUTTON_Y SDLK_SPACE)\r\nset(KBCTRL_BUTTON_X SDLK_LSHIFT)\r\nset(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_BACKSPACE)\r\nset(KBCTRL_BUTTON_LEFTSHOULDER SDLK_TAB)\r\nset(KBCTRL_BUTTON_START SDLK_RETURN)\r\nset(KBCTRL_BUTTON_LEFTSTICK SDLK_END) # Suspend\r\nset(KBCTRL_BUTTON_BACK SDLK_ESCAPE) # Select\r\nset(KBCTRL_IGNORE_1 SDLK_3) # Backlight\r\n"
  },
  {
    "path": "CMake/platforms/switch/asio_defs.cmake",
    "content": "# Enables a number of header file definitions required by ASIO\r\ntarget_compile_definitions(asio INTERFACE _DEFAULT_SOURCE=ON)\r\n\r\n# Missing headers and declarations provided by DevilutionX\r\ntarget_include_directories(asio BEFORE INTERFACE ${PROJECT_SOURCE_DIR}/Source/platform/switch/asio/include)\r\n"
  },
  {
    "path": "CMake/platforms/switch.cmake",
    "content": "list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/switch\")\r\n\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(BUILD_TESTING OFF)\r\nset(BUILD_ASSETS_MPQ OFF)\r\n\r\nset(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(DISABLE_ZERO_TIER ON)\r\nset(PREFILL_PLAYER_NAME ON)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Nintendo)\r\nset(NOEXIT ON)\r\n\r\nset(JOY_BUTTON_DPAD_LEFT 16)\r\nset(JOY_BUTTON_DPAD_UP 17)\r\nset(JOY_BUTTON_DPAD_RIGHT 18)\r\nset(JOY_BUTTON_DPAD_DOWN 19)\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_SUBDIRECTORIES platform/switch)\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES libdevilutionx_switch)\r\n"
  },
  {
    "path": "CMake/platforms/threads-stub/FindThreads.cmake",
    "content": "# Stub out the Threads package.\r\n# Some platforms do not have a system threads library but SDL threads are supported.\r\nadd_library(Threads::Threads INTERFACE IMPORTED GLOBAL)\r\n"
  },
  {
    "path": "CMake/platforms/uwp_lib.cmake",
    "content": "set(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(BUILD_ASSETS_MPQ OFF)\r\nset(BUILD_TESTING OFF)\r\nset(DISCORD_INTEGRATION OFF)\r\nset(DEVILUTIONX_GAMEPAD_TYPE Xbox)\r\n\r\n# setting all libs to be built statically and from source\r\nset(DEVILUTIONX_SYSTEM_SDL2 OFF)\r\nset(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\nset(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBPNG OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\nset(DEVILUTIONX_SYSTEM_ZLIB OFF)\r\n\r\nset(DEVILUTIONX_STATIC_SDL2 ON)\r\nset(DEVILUTIONX_STATIC_SDL_IMAGE ON)\r\nset(DEVILUTIONX_STATIC_SDL_AUDIOLIB ON)\r\nset(DEVILUTIONX_STATIC_LIBSODIUM ON)\r\nset(DEVILUTIONX_STATIC_LIBPNG ON)\r\nset(DEVILUTIONX_STATIC_LIBFMT ON)\r\nset(DEVILUTIONX_STATIC_BZIP2 ON)\r\nset(DEVILUTIONX_STATIC_ZLIB ON)\r\n\r\n# not really necessary but a good measure for SDL related stuff\r\nset(WINDOWS_STORE ON)\r\n\r\nadd_library(uwp_defs INTERFACE)\r\ntarget_compile_definitions(uwp_defs INTERFACE __UWP__=1)\r\nset(DEVILUTIONX_PLATFORM_ASSETS_LINK_LIBRARIES uwp_defs)\r\nset(DEVILUTIONX_PLATFORM_LINK_LIBRARIES uwp_defs)\r\n"
  },
  {
    "path": "CMake/platforms/vita.cmake",
    "content": "set(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(DEVILUTIONX_STATIC_CXX_STDLIB OFF)\r\nset(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBSODIUM OFF)\r\nset(BUILD_TESTING OFF)\r\nset(DISABLE_ZERO_TIER ON)\r\nset(PREFILL_PLAYER_NAME ON)\r\nset(DEVILUTIONX_GAMEPAD_TYPE PlayStation)\r\nset(NOEXIT ON)\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_SUBDIRECTORIES platform/vita)\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES libdevilutionx_vita)\r\nlist(APPEND DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS VITA)\r\n\r\n# The Vita build needs the information\r\nset(DEVILUTIONX_DISABLE_STRIP ON)\r\n"
  },
  {
    "path": "CMake/platforms/windows.cmake",
    "content": "set(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(DIST ON)\r\n\r\nset(DEVILUTIONX_PLATFORM_FILE_UTIL_LINK_LIBRARIES shlwapi)\r\nset(DEVILUTIONX_PLATFORM_ASSETS_LINK_LIBRARIES find_steam_game)\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES\r\n  find_steam_game\r\n  shlwapi\r\n  wsock32\r\n  ws2_32\r\n  wininet\r\n)\r\n\r\nadd_definitions(-DWINVER=0x0601 -D_WIN32_WINDOWS=0x0601 -D_WIN32_WINNT=0x0601)\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS \"/W3\" \"/Zc:__cplusplus\" \"/utf-8\")\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS)\r\nelse()\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS $<$<CONFIG:Debug>:-gstabs>)\r\nendif()\r\n\r\nif(MINGW_CROSS)\r\n  list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/mingw\")\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/windows9x.cmake",
    "content": "set(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(DIST ON)\r\n\r\nset(NONET ON)\r\nset(DISABLE_ZERO_TIER ON)\r\nset(USE_SDL1 ON)\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\nset(DEVILUTIONX_STATIC_LIBSODIUM OFF)\r\n\r\n# Compatibility with Windows 9x 8-bit mode and improved performance\r\nset(SDL1_VIDEO_MODE_BPP 8)\r\nset(SDL1_FORCE_DIRECT_RENDER ON)\r\n\r\nset(DEVILUTIONX_WINDOWS_NO_WCHAR ON)\r\n\r\n# `WINVER=0x0500` without `_WIN32_WINNT` is Windows 98.\r\n# MinGW force-defines `_WIN32_WINNT=0xa00` if it isn't defined, so define it as 0.\r\nadd_definitions(-DWINVER=0x0500 -D_WIN32_WINDOWS=0x0500 -D_WIN32_WINNT=0)\r\n\r\nset(DEVILUTIONX_PLATFORM_FILE_UTIL_LINK_LIBRARIES shlwapi)\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES\r\n  shlwapi\r\n  wsock32\r\n  ws2_32\r\n  wininet\r\n)\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS \"/W3\" \"/Zc:__cplusplus\" \"/utf-8\")\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS)\r\nelse()\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS $<$<CONFIG:Debug>:-gstabs>)\r\nendif()\r\n\r\nif(MINGW_CROSS)\r\n  list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/mingw\")\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/windowsXP.cmake",
    "content": "set(ASAN OFF)\r\nset(UBSAN OFF)\r\nset(DIST ON)\r\n\r\nset(DEVILUTIONX_PLATFORM_FILE_UTIL_LINK_LIBRARIES shlwapi)\r\nset(DEVILUTIONX_PLATFORM_ASSETS_LINK_LIBRARIES find_steam_game)\r\nset(DISABLE_ZERO_TIER ON)\r\nset(DISCORD_INTEGRATION OFF)\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\nset(DEVILUTIONX_STATIC_LIBSODIUM ON)\r\n\r\nlist(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES\r\n  find_steam_game\r\n  shlwapi\r\n  wsock32\r\n  ws2_32\r\n  wininet\r\n)\r\n\r\nadd_definitions(-DWINVER=0x0501 -D_WIN32_WINDOWS=0x0501 -D_WIN32_WINNT=0x0501)\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS \"/W3\" \"/Zc:__cplusplus\" \"/utf-8\")\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS)\r\nelse()\r\n  list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS $<$<CONFIG:Debug>:-gstabs>)\r\nendif()\r\n\r\nif(MINGW_CROSS)\r\n  list(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/mingw\")\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/xbox_nxdk/finders/FindPNG.cmake",
    "content": "if(NOT TARGET PNG::PNG)\r\n  find_package(PkgConfig REQUIRED)\r\n  pkg_check_modules(PNG REQUIRED IMPORTED_TARGET libpng)\r\n  add_library(PNG::PNG ALIAS PkgConfig::PNG)\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/xbox_nxdk/finders/FindSDL2.cmake",
    "content": "if(NOT TARGET SDL2::SDL2)\r\n  find_package(PkgConfig REQUIRED)\r\n  pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)\r\n  add_library(SDL2::SDL2 ALIAS PkgConfig::SDL2)\r\n  add_library(SDL2_nomain INTERFACE)\r\n  add_library(SDL2::SDL2main ALIAS SDL2_nomain)\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/xbox_nxdk/finders/FindZLIB.cmake",
    "content": "if(NOT TARGET ZLIB::ZLIB)\r\n  find_package(PkgConfig REQUIRED)\r\n  pkg_check_modules(ZLIB REQUIRED IMPORTED_TARGET zlib)\r\n  add_library(ZLIB::ZLIB ALIAS PkgConfig::ZLIB)\r\nendif()\r\n"
  },
  {
    "path": "CMake/platforms/xbox_nxdk.cmake",
    "content": "set(NONET ON)\r\nset(ASAN OFF)\r\nset(UBSAN OFF)\r\n\r\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/xbox_nxdk/finders\")\r\n\r\nset(DEVILUTIONX_SYSTEM_BZIP2 OFF)\r\nset(DEVILUTIONX_SYSTEM_LIBFMT OFF)\r\n\r\nset(BUILD_ASSETS_MPQ OFF)\r\nset(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/pkg/assets\")\r\nset(DEVILUTIONX_WINDOWS_NO_WCHAR ON)\r\n\r\nset(DEVILUTIONX_RESAMPLER_SPEEX OFF)\r\nset(DEFAULT_AUDIO_BUFFER_SIZE 5120)\r\n\r\nset(DEVILUTIONX_GAMEPAD_TYPE Xbox)\r\n\r\nset(CMAKE_THREAD_LIBS_INIT \"-lpthread\")\r\nset(CMAKE_HAVE_THREADS_LIBRARY 1)\r\nset(CMAKE_USE_WIN32_THREADS_INIT 0)\r\nset(CMAKE_USE_PTHREADS_INIT 1)\r\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.22)\r\n\r\nforeach(_policy CMP0135 CMP0141)\r\n  if(POLICY ${_policy})\r\n    cmake_policy(SET ${_policy} NEW)\r\n    set(CMAKE_POLICY_DEFAULT_${_policy} NEW)\r\n  endif()\r\nendforeach()\r\n\r\n# Projects added via `add_subdirectory` or `FetchContent` may have a lower\r\n# `cmake_minimum_required` than we set here. Set policies that we require\r\n# to their new value so that they still apply.\r\nset(CMAKE_POLICY_DEFAULT_CMP0069 NEW)\r\nset(CMAKE_POLICY_DEFAULT_CMP0077 NEW)\r\n\r\nif(IS_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}/dist\")\r\n  message(\"-- Detected a source distribution with the required FetchContent dependencies and devilutionx.mpq included\")\r\n  set(SRC_DIST ON)\r\n  add_subdirectory(dist)\r\nendif()\r\n\r\nif(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})\r\n  message(WARNING [[In-source build detected, please eg. create a new directory and use `cmake ..`]])\r\nendif()\r\n\r\ninclude(CMakeDependentOption)\r\n\r\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/CMake\")\r\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/CMake/finders\")\r\ninclude(functions/genex)\r\n\r\n# Options required by `VcPkgManifestFeatures`, which must be included before the `project` call.\r\noption(USE_SDL1 \"Use SDL1.2 instead of SDL2\" OFF)\r\noption(USE_SDL3 \"Use SDL3 instead of SDL2\" OFF)\r\noption(NONET \"Disable network support\" OFF)\r\ncmake_dependent_option(PACKET_ENCRYPTION \"Encrypt network packets\" ON \"NOT NONET\" OFF)\r\n# The gettext[tools] package takes a very long time to install\r\nif(CMAKE_TOOLCHAIN_FILE MATCHES \"vcpkg.cmake$\")\r\n  option(USE_GETTEXT_FROM_VCPKG \"Add vcpkg dependency for gettext[tools] for compiling translations\" OFF)\r\nendif()\r\noption(BUILD_TESTING \"Build tests.\" ON)\r\n\r\n# These must be included after the options above but before the `project` call.\r\ninclude(VcPkgManifestFeatures)\r\n\r\n# Set up the `project` before the rest of the options so that:\r\n#\r\n# 1. Properties such as `TARGET_SUPPORTS_SHARED_LIBS` are defined.\r\n# 2. Toolchain file is evaluated, required for `Platforms.cmake`,\r\n#    which can override the options.\r\nfile(STRINGS \"VERSION\" VERSION_STR)\r\nif(NOT \"${VERSION_STR}\" STREQUAL \"\")\r\n  string(REGEX MATCH \"([0-9]+\\\\.[0-9]+\\\\.[0-9]+).*\" VERSION_PREFIX ${VERSION_STR})\r\n  set(VERSION_NUM ${CMAKE_MATCH_1})\r\nendif()\r\n\r\nif(NOT VERSION_SUFFIX)\r\n  # For versions with a suffix, e.g. \"1.5.0-dev\", include\r\n  # the build type and the git hash.\r\n  set(VERSION_SUFFIX \"-$<CONFIG>\")\r\n  if(VERSION_PREFIX MATCHES \"-\")\r\n    if(NOT GIT_COMMIT_HASH)\r\n      include(functions/git)\r\n      get_git_commit_hash(GIT_COMMIT_HASH)\r\n    endif()\r\n    if(GIT_COMMIT_HASH)\r\n      set(VERSION_SUFFIX \"${VERSION_SUFFIX}-${GIT_COMMIT_HASH}\")\r\n    endif()\r\n  else()\r\n    # For versions without a suffix, e.g. \"1.5.0\" rather than \"1.5.0-dev\",\r\n    # only include the build type if it is a debug build.\r\n    set(VERSION_SUFFIX \"$<$<CONFIG:Debug>:$<CONFIG>>\")\r\n  endif()\r\nendif()\r\n\r\nproject(DevilutionX\r\n  VERSION ${VERSION_NUM}\r\n  LANGUAGES C CXX)\r\nset(PROJECT_VERSION_WITH_SUFFIX \"${VERSION_PREFIX}${VERSION_SUFFIX}\")\r\n\r\n# Platform definitions can override options and we want `cmake_dependent_option` to see the effects.\r\n# Note that a few options are still defined before this because they're needed by `VcPkgManifestFeatures.cmake`.\r\ninclude(Platforms)\r\n\r\n# This built-in CMake module adds a BUILD_TESTING option (ON by default).\r\n# Must be included in the top-level `CMakeLists.txt` after calling `project`.\r\n# Because we must include `VcPkgManifestFeatures` before the `project` call,\r\n# we add a BUILD_TESTING option ourselves above as well.\r\ninclude(CTest)\r\n\r\n# Debugging / profiling options\r\nDEBUG_OPTION(ASAN \"Enable address sanitizer\")\r\nDEBUG_OPTION(UBSAN \"Enable undefined behaviour sanitizer\")\r\noption(TSAN \"Enable thread sanitizer (not compatible with ASAN=ON)\" OFF)\r\nDEBUG_OPTION(DEBUG \"Enable debug mode in engine\")\r\noption(GPERF \"Build with GPerfTools profiler\" OFF)\r\ncmake_dependent_option(GPERF_HEAP_FIRST_GAME_ITERATION \"Save heap profile of the first game iteration\" OFF \"GPERF\" OFF)\r\noption(ENABLE_CODECOVERAGE \"Instrument code for code coverage (only enabled with BUILD_TESTING)\" OFF)\r\n\r\n# Packaging options\r\nRELEASE_OPTION(CPACK \"Configure CPack\")\r\noption(MACOSX_STANDALONE_APP_BUNDLE \"Generate a portable app bundle to use on other devices (requires sudo)\" OFF)\r\noption(WIN_NSIS \"Generate an NSIS installer\" OFF)\r\n\r\n# Network options\r\ncmake_dependent_option(DISABLE_TCP \"Disable TCP multiplayer option\" OFF \"NOT NONET\" ON)\r\ncmake_dependent_option(DISABLE_ZERO_TIER \"Disable ZeroTier multiplayer option\" OFF \"NOT NONET\" ON)\r\n\r\nif(USE_SDL1 AND USE_SDL3)\r\n  message(FATAL_ERROR \"USE_SDL1 and USE_SDL3 cannot be set at the same time\")\r\nendif()\r\n\r\n# Graphics options\r\nif(NOT USE_SDL1)\r\nif(USE_SDL3)\r\n  set(_texture_format_default \"SDL_PIXELFORMAT_XRGB8888\")\r\nelse()\r\n  set(_texture_format_default \"SDL_PIXELFORMAT_RGB888\")\r\nendif()\r\n  set(DEVILUTIONX_DISPLAY_TEXTURE_FORMAT \"${_texture_format_default}\" CACHE STRING \"Texture format for DevilutionX textures when using the GPU renderer\")\r\n  mark_as_advanced(DEVILUTIONX_DISPLAY_TEXTURE_FORMAT)\r\nendif()\r\n\r\nif(USE_SDL1)\r\n  # SDL_image in SDL1 does not support PNG, making PCX the only option.\r\n  set(DEVILUTIONX_SCREENSHOT_FORMAT \"DEVILUTIONX_SCREENSHOT_FORMAT_PCX\")\r\nelse()\r\n  set(DEVILUTIONX_SCREENSHOT_FORMAT \"DEVILUTIONX_SCREENSHOT_FORMAT_PNG\" CACHE STRING \"Screenshot format\")\r\n  set_property(CACHE DEVILUTIONX_SCREENSHOT_FORMAT PROPERTY STRINGS \"DEVILUTIONX_SCREENSHOT_FORMAT_PNG;DEVILUTIONX_SCREENSHOT_FORMAT_PCX\")\r\n  mark_as_advanced(DEVILUTIONX_SCREENSHOT_FORMAT)\r\nendif()\r\n\r\n# Sound options\r\noption(NOSOUND \"Disable sound support\" OFF)\r\noption(DEVILUTIONX_RESAMPLER_SPEEX \"Build with Speex resampler\" ON)\r\ncmake_dependent_option(DEVILUTIONX_RESAMPLER_SDL \"Build with SDL resampler\" ON \"NOT USE_SDL1\" OFF)\r\nif(DEVILUTIONX_RESAMPLER_SPEEX)\r\n  list(APPEND _resamplers Speex)\r\nendif()\r\nif(DEVILUTIONX_RESAMPLER_SDL)\r\n  list(APPEND _resamplers SDL)\r\nendif()\r\nlist(GET _resamplers 0 _default_resampler)\r\nset(DEVILUTIONX_DEFAULT_RESAMPLER ${_default_resampler} CACHE STRING \"Default resampler\")\r\nset_property(CACHE DEVILUTIONX_DEFAULT_RESAMPLER PROPERTY STRINGS ${_resamplers})\r\n\r\n# Optimization / link options\r\noption(DISABLE_LTO \"Disable link-time optimization (by default enabled in release mode)\" OFF)\r\noption(PIE \"Generate position-independent code\" OFF)\r\ncmake_dependent_option(DEVILUTIONX_DISABLE_RTTI \"Disable RTTI\" ON \"NONET\" OFF)\r\ncmake_dependent_option(DEVILUTIONX_DISABLE_EXCEPTIONS \"Disable exceptions\" ON \"DISABLE_ZERO_TIER\" OFF)\r\nRELEASE_OPTION(DEVILUTIONX_STATIC_CXX_STDLIB \"Link C++ standard library statically (if available)\")\r\noption(DEVILUTIONX_PROFILE_GENERATE \"Build a binary that generates the profile for PGO\" OFF)\r\noption(DEVILUTIONX_PROFILE_USE \"Build with PGO using the given profile file\" OFF)\r\nset(DEVILUTIONX_PROFILE_DIR \"\" CACHE STRING \"Directory where the profile is stored\")\r\n\r\ninclude(MoldLinker)\r\n\r\n# Memory / performance trade-off options\r\noption(UNPACKED_MPQS \"Expect MPQs to be unpacked and the data converted with devilutionx-mpq-tools\" OFF)\r\noption(UNPACKED_SAVES \"Uses unpacked save files instead of MPQ .sv/.hsv files\" OFF)\r\noption(DISABLE_STREAMING_MUSIC \"Disable streaming music (to work around broken platform implementations)\" OFF)\r\nmark_as_advanced(DISABLE_STREAMING_MUSIC)\r\noption(DISABLE_STREAMING_SOUNDS \"Disable streaming sounds (to work around broken platform implementations)\" OFF)\r\nmark_as_advanced(DISABLE_STREAMING_SOUNDS)\r\nset(STREAM_ALL_AUDIO_MIN_FILE_SIZE \"\" CACHE STRING \"If set, stream all the audio files larger than this size\")\r\nmark_as_advanced(STREAM_ALL_AUDIO_MIN_FILE_SIZE)\r\noption(DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT \"Whether to use a lookup table for transparency blending with black. This improves performance of blending transparent black overlays, such as quest dialog background, at the cost of 128 KiB of RAM.\" ON)\r\nmark_as_advanced(DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT)\r\n\r\n# Additional features\r\noption(DISABLE_DEMOMODE \"Disable demo mode support\" OFF)\r\noption(DISCORD_INTEGRATION \"Build with Discord SDK for rich presence support\" OFF)\r\noption(SCREEN_READER_INTEGRATION \"Build with screen reader support\" OFF)\r\nmark_as_advanced(SCREEN_READER_INTEGRATION)\r\n\r\n# If both UNPACKED_MPQS and UNPACKED_SAVES are enabled, we completely remove MPQ support.\r\nif(UNPACKED_MPQS AND UNPACKED_SAVES)\r\n  set(SUPPORTS_MPQ OFF)\r\nelse()\r\n  set(SUPPORTS_MPQ ON)\r\nendif()\r\n\r\n# By default, devilutionx.mpq and mods/Hellfire.mpq are built only if smpq is installed and MPQ support is enabled.\r\nif(SUPPORTS_MPQ AND NOT UNPACKED_MPQS)\r\n  if(BUILD_ASSETS_MPQ OR (CPACK STREQUAL \"ON\" AND (WIN32 OR CMAKE_SYSTEM_NAME STREQUAL \"Linux\")))\r\n    find_program(SMPQ smpq REQUIRED)\r\n  elseif(NOT DEFINED BUILD_ASSETS_MPQ AND NOT SRC_DIST)\r\n    find_program(SMPQ smpq)\r\n  endif()\r\n  if(SMPQ)\r\n    set(_has_smpq ON)\r\n  else()\r\n    set(_has_smpq OFF)\r\n  endif()\r\n  option(BUILD_ASSETS_MPQ \"If true, assets are packaged into devilutionx.mpq and mods/Hellfire to Hellfire.mpq.\" ${_has_smpq})\r\nelse()\r\n  set(BUILD_ASSETS_MPQS OFF)\r\nendif()\r\n\r\n# === Option overrides ===\r\n# TSAN is not compatible with ASAN.\r\nif(TSAN)\r\n  set(ASAN OFF)\r\nendif()\r\n\r\nif(MSVC AND NOT CMAKE_BUILD_TYPE STREQUAL \"Debug\" AND NOT DISABLE_LTO)\r\n  # Work around MSVC + CMake bug when LTO is enabled.\r\n  # See https://github.com/diasurgical/devilutionX/issues/3778\r\n  # and https://gitlab.kitware.com/cmake/cmake/-/issues/23035\r\n  set(BUILD_TESTING OFF)\r\nendif()\r\n\r\n# Note: `CMAKE_CROSSCOMPILING` is only available after the `project` call.\r\nif(CMAKE_CROSSCOMPILING)\r\n  set(BUILD_TESTING OFF)\r\nendif()\r\n\r\nif(DISABLE_DEMOMODE)\r\n  # Testing requires demomode.\r\n  set(BUILD_TESTING OFF)\r\nendif()\r\n\r\nif(BUILD_TESTING)\r\n  # When tests are enabled, we build a shared devilutionx_so library, which needs to be PIC to link.\r\n  set(PIE ON)\r\nendif()\r\n\r\n# Recalculate the dependent options that are defined before `include(Platforms)`:\r\nif(NONET)\r\n  # PACKET_ENCRYPTION is defined before `Platforms.cmake` is included.\r\n  # This means that if a `Platforms.cmake` sets NONET to OFF, PACKET_ENCRYPTION will not automatically\r\n  # reflect that.\r\n  set(PACKET_ENCRYPTION OFF)\r\nendif()\r\n# === End of option overrides ===\r\n\r\nif(PIE)\r\n  set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)\r\nendif()\r\n\r\nfind_program(CCACHE_PROGRAM ccache)\r\nif(CCACHE_PROGRAM)\r\n  set(CMAKE_C_COMPILER_LAUNCHER \"${CCACHE_PROGRAM}\")\r\n  set(CMAKE_CXX_COMPILER_LAUNCHER \"${CCACHE_PROGRAM}\")\r\nendif()\r\n\r\nif(DEVILUTIONX_DISABLE_RTTI)\r\n  if(CMAKE_CXX_COMPILER_ID MATCHES \"GNU|Clang\")\r\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fno-rtti\")\r\n  elseif(MSVC)\r\n    string(REGEX REPLACE \"/GR\" \"/GR-\" CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}\")\r\n  endif()\r\nendif()\r\n\r\nif(DEVILUTIONX_DISABLE_EXCEPTIONS)\r\n  if(CMAKE_CXX_COMPILER_ID MATCHES \"GNU|Clang\")\r\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fno-exceptions\")\r\n  elseif(MSVC)\r\n    string(REGEX REPLACE \"/EHsc\" \"/EHs-c-\" CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}\")\r\n  endif()\r\nendif()\r\n\r\n# Remove unused symbols in non-debug mode.\r\n# This is useful even with LTO (-84 KiB with MinSizeRel).\r\n#\r\n# PS4 toolchain crashes in `create-fself` when linking with these flags, so we exclude it:\r\n# https://github.com/PacBrew/ps4-openorbis/issues/8\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"GNU|Clang\" AND NOT PS4)\r\n  add_compile_options(\"$<$<NOT:$<CONFIG:Debug>>:-ffunction-sections;-fdata-sections>\")\r\n  if(APPLE)\r\n    add_link_options(\"$<$<NOT:$<CONFIG:Debug>>:LINKER:-dead_strip>\")\r\n  else()\r\n    add_link_options(\"$<$<NOT:$<CONFIG:Debug>>:LINKER:--gc-sections,--as-needed>\")\r\n  endif()\r\nendif()\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"GNU\")\r\n  # -fipa-pta and -fdevirtualize-at-ltrans improve performance.\r\n  add_compile_options(\"$<$<NOT:$<CONFIG:Debug>>:-fipa-pta;-fdevirtualize-at-ltrans>\")\r\nendif()\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"GNU|Clang\")\r\n  add_compile_options(\"$<$<BOOL:${DEVILUTIONX_PROFILE_GENERATE}>:-fprofile-generate>\")\r\n  add_link_options(\"$<$<BOOL:${DEVILUTIONX_PROFILE_GENERATE}>:-fprofile-generate>\")\r\n  add_compile_options(\"$<$<BOOL:${DEVILUTIONX_PROFILE_USE}>:-fprofile-use>\")\r\n  add_link_options(\"$<$<BOOL:${DEVILUTIONX_PROFILE_USE}>:-fprofile-use>\")\r\n  add_compile_options(\"$<$<BOOL:${DEVILUTIONX_PROFILE_DIR}>:-fprofile-dir=${DEVILUTIONX_PROFILE_DIR};-fprofile-prefix-path=${CMAKE_CURRENT_BINARY_DIR}>\")\r\n  add_link_options(\"$<$<BOOL:${DEVILUTIONX_PROFILE_DIR}>:-fprofile-dir=${DEVILUTIONX_PROFILE_DIR};-fprofile-prefix-path=${CMAKE_CURRENT_BINARY_DIR}>\")\r\nendif()\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n  # u8path() function is deprecated but there is no sensible alternative and it might even get un-deprecated.\r\n  add_definitions(-D_SILENCE_CXX20_U8PATH_DEPRECATION_WARNING)\r\n  if(${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.25\")\r\n    # This enables Edit & Continue support, see https://learn.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio#edit-and-continue-for-cmake-projects\r\n    set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT \"$<$<CONFIG:Debug>:EditAndContinue>\") # Sets /ZI compiler option, see https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html\r\n    add_link_options(\"$<$<CONFIG:Debug>:/INCREMENTAL>\")\r\n  endif()\r\nendif()\r\n\r\n# Not a genexp because CMake doesn't support it\r\n# https://gitlab.kitware.com/cmake/cmake/-/issues/20546\r\nif(NOT DISABLE_LTO)\r\n  # LTO if supported:\r\n  include(CheckIPOSupported)\r\n  check_ipo_supported(RESULT is_ipo_supported OUTPUT lto_error)\r\n  if(is_ipo_supported)\r\n    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)\r\n    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)\r\n    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL ON)\r\n  endif()\r\nendif()\r\n\r\nif(GPERF)\r\n  set(DEVILUTIONX_STATIC_CXX_STDLIB OFF)\r\n\r\n  if(GPERF_HEAP_FIRST_GAME_ITERATION)\r\n    set(GPERF_HEAP_MAIN ON)\r\n  endif()\r\n\r\n  # Compile with information about file and line numbers for everything\r\n  # even in non-Debug build types.\r\n  if(CMAKE_CXX_COMPILER_ID MATCHES \"GNU\")\r\n    add_compile_options(\"$<$<NOT:$<CONFIG:Debug>>:-g2>\")\r\n  elseif(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\")\r\n    # Use the more size-efficient `-gmlt` option on clang.\r\n    add_compile_options(\"$<$<NOT:$<CONFIG:Debug>>:-gmlt>\")\r\n  endif()\r\nendif()\r\n\r\nset(CMAKE_CXX_STANDARD 20)\r\n\r\n# On some platforms, such as DJGPP,\r\n# `-std=c++20` defines `__STRICT_ANSI__` which disables\r\n# all POSIX extensions, so we need to use `-std=gnu++20` instead.\r\nset(CMAKE_CXX_EXTENSIONS ON)\r\n\r\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\r\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON) # for clang-tidy\r\nset(CMAKE_THREAD_PREFER_PTHREAD ON)\r\nset(THREADS_PREFER_PTHREAD_FLAG ON)\r\nif(NOT TARGET_PLATFORM STREQUAL \"dos\")\r\n  find_package(Threads REQUIRED)\r\nendif()\r\n\r\n# Dependencies must be included after Platforms.\r\ninclude(Dependencies)\r\n\r\nadd_subdirectory(Source)\r\n\r\nset(BIN_TARGET devilutionx)\r\nif(NINTENDO_3DS)\r\n  set(BIN_TARGET ${BIN_TARGET}.elf)\r\nelseif(TARGET_PLATFORM STREQUAL \"dos\")\r\n  set(BIN_TARGET devx)\r\nendif()\r\n\r\nif(ANDROID)\r\n  add_library(${BIN_TARGET} SHARED Source/main.cpp)\r\nelseif(UWP_LIB)\r\n  set(BIN_TARGET libdevilutionx)\r\nelse()\r\n  add_executable(${BIN_TARGET}\r\n    WIN32\r\n    MACOSX_BUNDLE\r\n    Source/main.cpp\r\n    Packaging/windows/devilutionx.exe.manifest\r\n    Packaging/windows/devilutionx.rc\r\n    Packaging/apple/LaunchScreen.storyboard)\r\n\r\n    if(CMAKE_STRIP AND NOT DEVILUTIONX_DISABLE_STRIP)\r\n      add_custom_command(\r\n        TARGET ${BIN_TARGET} POST_BUILD\r\n        COMMAND $<$<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>>:${CMAKE_STRIP}>\r\n        ARGS $<TARGET_FILE:${BIN_TARGET}>)\r\n    endif()\r\nendif()\r\n\r\nif(TARGET_PLATFORM STREQUAL \"dos\")\r\n    # Allow multiple definitions for math stubs in DJGPP\r\n    set_target_properties(${BIN_TARGET} PROPERTIES\r\n        LINK_FLAGS \"-Wl,--allow-multiple-definition -static\"\r\n    )\r\n    target_link_libraries(${BIN_TARGET} PRIVATE m)\r\nendif()\r\n\r\nif(NOT UWP_LIB)\r\n  target_link_dependencies(${BIN_TARGET} PRIVATE libdevilutionx)\r\nendif()\r\n\r\nif(GPERF)\r\n  target_link_libraries(${BIN_TARGET} PUBLIC ${GPERFTOOLS_LIBRARIES})\r\nendif()\r\n\r\n# Must be included after `BIN_TARGET` and `libdevilutionx` are defined.\r\ninclude(Assets)\r\ninclude(Mods)\r\n\r\nif(EMSCRIPTEN)\r\n  target_link_options(${BIN_TARGET} PRIVATE --preload-file assets)\r\nendif()\r\n\r\nif(NOT USE_SDL1 AND NOT UWP_LIB)\r\n  target_link_libraries(${BIN_TARGET} PUBLIC ${SDL2_MAIN})\r\nendif()\r\n\r\nif(BUILD_TESTING)\r\n  include(Tests)\r\nendif()\r\n\r\ninclude(functions/set_relative_file_macro)\r\nset_relative_file_macro(${BIN_TARGET})\r\n\r\nif(APPLE)\r\n  set(MACOSX_BUNDLE_GUI_IDENTIFIER com.diasurgical.devilutionx)\r\n  set(MACOSX_BUNDLE_COPYRIGHT Unlicense)\r\n  set(MACOSX_BUNDLE_BUNDLE_NAME devilutionx)\r\n  set(MACOSX_BUNDLE_DISPLAY_NAME DevilutionX)\r\n  set(MACOSX_BUNDLE_INFO_STRING ${PROJECT_VERSION})\r\n  set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})\r\n  set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})\r\n  set(MACOSX_BUNDLE_LONG_VERSION_STRING \"Version ${PROJECT_VERSION}\")\r\n  if(IOS)\r\n    set(MACOSX_BUNDLE_REQUIRED_PLATFORM IPhoneOS)\r\n    set_target_properties(${BIN_TARGET} PROPERTIES XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY \"1,2\")\r\n    set(CMAKE_OSX_DEPLOYMENT_TARGET \"9.0\")\r\n  elseif(DARWIN_MAJOR_VERSION GREATER_EQUAL 17)\r\n    set(MACOSX_BUNDLE_REQUIRED_PLATFORM Carbon)\r\n    set(CMAKE_OSX_DEPLOYMENT_TARGET \"10.13.0\")\r\n  endif()\r\n  if(DARWIN_MAJOR_VERSION VERSION_LESS 9)\r\n    # Finder on OSX Tiger can only handle icns files with up to 128x128 icons.\r\n    set(_icon_file AppIcon_128)\r\n  else()\r\n    set(_icon_file AppIcon)\r\n  endif()\r\n  target_sources(${BIN_TARGET} PRIVATE \"Packaging/apple/${_icon_file}.icns\")\r\n  set_source_files_properties(\"./Packaging/apple/${_icon_file}.icns\" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)\r\n  set_target_properties(${BIN_TARGET} PROPERTIES MACOSX_BUNDLE_ICON_FILE \"${_icon_file}.icns\")\r\n  set_target_properties(${BIN_TARGET} PROPERTIES MACOSX_BUNDLE_INFO_PLIST \"${CMAKE_CURRENT_SOURCE_DIR}/Packaging/apple/Info.plist\")\r\n\r\n  install (TARGETS ${BIN_TARGET} DESTINATION ./)\r\n\r\n  if(MACOSX_STANDALONE_APP_BUNDLE)\r\n      install(CODE \"\r\n        include(BundleUtilities)\r\n        fixup_bundle(${CMAKE_BINARY_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app \\\"\\\" \\\"\\\")\r\n        \"\r\n        COMPONENT Runtime)\r\n  endif()\r\n\r\n  find_library(COREFOUNDATION_LIBRARY CoreFoundation)\r\n  if(COREFOUNDATION_LIBRARY)\r\n    target_link_libraries(libdevilutionx PUBLIC \"${COREFOUNDATION_LIBRARY}\")\r\n    target_compile_definitions(libdevilutionx PRIVATE USE_COREFOUNDATION)\r\n  endif()\r\n\r\n  set(MACOSX_BUNDLE_LONG_VERSION_STRING \"Version ${PROJECT_VERSION}\")\r\n  set(CPACK On)\r\nendif()\r\n\r\nif(NINTENDO_SWITCH)\r\n  nx_generate_nacp (${BIN_TARGET}.nacp\r\n    NAME    \"DevilutionX\"\r\n    AUTHOR  \"Devilution Team\"\r\n    VERSION \"${PROJECT_VERSION}\"\r\n  )\r\n\r\n  file(MAKE_DIRECTORY \"${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}\")\r\n  nx_create_nro(${BIN_TARGET}\r\n    NACP  ${BIN_TARGET}.nacp\r\n    ICON  \"${PROJECT_SOURCE_DIR}/Packaging/switch/icon.jpg\"\r\n    ROMFS ${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}\r\n  )\r\nendif()\r\n\r\nif(VITA)\r\n  set(VITA_APP_NAME \"devilutionX\")\r\n  set(VITA_TITLEID  \"DVLX00001\")\r\n  set(VITA_VERSION  \"01.00\")\r\n  set(VITA_MKSFOEX_FLAGS \"${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1\")\r\n  set(VITA_MKSFOEX_FLAGS \"${VITA_MKSFOEX_FLAGS} -d ATTRIBUTE2=12\")\r\n  vita_create_self(devilutionx.self devilutionx UNSAFE)\r\n  if(BUILD_ASSETS_MPQ OR SRC_DIST)\r\n    vita_create_vpk(devilutionx.vpk ${VITA_TITLEID} devilutionx.self\r\n      VERSION ${VITA_VERSION}\r\n      NAME ${VITA_APP_NAME}\r\n      FILE Packaging/vita/sce_sys sce_sys\r\n      FILE ${DEVILUTIONX_MPQ} devilutionx.mpq\r\n      FILE ${HELLFIRE_MPQ} mods/Hellfire.mpq\r\n    )\r\n  else()\r\n    vita_create_vpk(devilutionx.vpk ${VITA_TITLEID} devilutionx.self\r\n      VERSION ${VITA_VERSION}\r\n      NAME ${VITA_APP_NAME}\r\n      FILE Packaging/vita/sce_sys sce_sys\r\n      FILE assets assets\r\n      ${VITA_TRANSLATIONS_LIST}\r\n    )\r\n  endif()\r\n\r\nendif()\r\n\r\nif(PS4)\r\n  add_custom_command(\r\n    TARGET devilutionx_mpq POST_BUILD\r\n    COMMAND ${CMAKE_COMMAND} -E copy ${DEVILUTIONX_MPQ} \"${PROJECT_SOURCE_DIR}/Packaging/ps4/\")\r\n  add_custom_command(\r\n    TARGET hellfire_mpq POST_BUILD\r\n    COMMAND ${CMAKE_COMMAND} -E make_directory \"${PROJECT_SOURCE_DIR}/Packaging/ps4/mods\"\r\n    COMMAND ${CMAKE_COMMAND} -E copy ${HELLFIRE_MPQ} \"${PROJECT_SOURCE_DIR}/Packaging/ps4/mods/\")\r\n  add_self(${BIN_TARGET})\r\n  add_pkg(${BIN_TARGET} \"${PROJECT_SOURCE_DIR}/Packaging/ps4\"\r\n    \"DVLX00001\" \"DevilutionX\" \"${PROJECT_VERSION}\")\r\nendif()\r\n\r\nif(NINTENDO_3DS)\r\n  set(APP_TITLE       \"DevilutionX\")\r\n  set(APP_DESCRIPTION \"DevilutionX port for 3DS\")\r\n  set(APP_AUTHOR      \"Diasurgical Team\")\r\n  set(APP_ICON        \"${PROJECT_SOURCE_DIR}/Packaging/ctr/icon.png\")\r\n  set(APP_BANNER      \"${PROJECT_SOURCE_DIR}/Packaging/ctr/banner.png\")\r\n  set(APP_AUDIO       \"${CMAKE_BINARY_DIR}/banner_audio.wav\")\r\n  set(APP_RSF         \"${PROJECT_SOURCE_DIR}/Packaging/ctr/template.rsf\")\r\n  set(APP_VERSION ${PROJECT_VERSION})\r\n\r\n  find_program(FFMPEG ffmpeg)\r\n  if(FFMPEG)\r\n    add_custom_command(OUTPUT ${APP_AUDIO}\r\n      COMMAND ${FFMPEG} -y -ss 3.3 -t 3 -i \"${PROJECT_SOURCE_DIR}/Packaging/resources/shareware-startup.wav\" -af \"afade=t=in:st=0:d=0.1,afade=t=out:st=2.9:d=0.1\" ${APP_AUDIO}\r\n      DEPENDS ${PROJECT_SOURCE_DIR}/Packaging/resources/shareware-startup.wav\r\n      VERBATIM)\r\n  else()\r\n    add_custom_command(OUTPUT ${APP_AUDIO}\r\n      COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/Packaging/ctr/audio_silent.wav ${APP_AUDIO}\r\n      DEPENDS ${PROJECT_SOURCE_DIR}/Packaging/ctr/audio_silent.wav\r\n      VERBATIM)\r\n  endif()\r\n\r\n  include(Tools3DS)\r\n  add_3dsx_target(${BIN_TARGET})\r\n  add_cia_target(${BIN_TARGET} ${APP_RSF} ${APP_BANNER} ${APP_AUDIO})\r\nendif()\r\n\r\nif(NXDK)\r\n  target_link_libraries(${BIN_TARGET} PRIVATE \"${NXDK_DIR}/lib/libnxdk_automount_d.lib\")\r\n  target_link_options(${BIN_TARGET} PRIVATE \"-include:_automount_d_drive\")\r\n\r\n  set(_nxdk_pkg_dir \"${CMAKE_BINARY_DIR}/pkg\")\r\n  set(_xbe_path \"${_nxdk_pkg_dir}/default.xbe\")\r\n  add_custom_command(\r\n    OUTPUT \"${_xbe_path}\"\r\n    COMMAND \"${CMAKE_COMMAND}\" -E make_directory \"${_nxdk_pkg_dir}\"\r\n    COMMAND \"${NXDK_DIR}/tools/cxbe/cxbe\" \"-OUT:${_xbe_path}\" -TITLE:DevilutionX \"-Logo:${PROJECT_SOURCE_DIR}/Packaging/xbox_nxdk/xbe_logo.pgm\" \"${CMAKE_BINARY_DIR}/${BIN_TARGET}.exe\"\r\n    DEPENDS \"${BIN_TARGET}\"\r\n  )\r\n  add_custom_target(nxdk_xbe DEPENDS \"${_xbe_path}\")\r\nendif()\r\n\r\nif(CPACK AND (APPLE OR BUILD_ASSETS_MPQ OR SRC_DIST))\r\n  if(WIN32)\r\n    if(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\r\n      set(SDL2_WIN32_DLLS_DIR \"${CMAKE_BINARY_DIR}\")\r\n    else()\r\n      set(SDL2_WIN32_DLLS_DIR \"${SDL2_EXEC_PREFIX}\")\r\n    endif()\r\n    set(SDL2_WIN32_LICENSES_DIR \"${PROJECT_SOURCE_DIR}/Packaging/resources\")\r\n\r\n    file(GLOB SDL2_WIN32_ALL_DLLS\r\n      LIST_DIRECTORIES false\r\n      \"${SDL2_WIN32_DLLS_DIR}/*.dll\")\r\n    file(GLOB SDL2_WIN32_ALL_LICENSES\r\n      LIST_DIRECTORIES false\r\n      \"${SDL2_WIN32_LICENSES_DIR}/LICENSE*.txt\"\r\n      \"${SDL2_WIN32_LICENSES_DIR}/README*.txt\")\r\n\r\n    set(CPACK_PACKAGE_NAME ${project_name})\r\n    if(WIN_NSIS)\r\n      set(CPACK_PACKAGE_FILE_NAME \"${PROJECT_NAME}_${PROJECT_VERSION}_Installer\")\r\n      set(CPACK_GENERATOR \"NSIS\")\r\n      set(CPACK_PACKAGE_INSTALL_DIRECTORY \"${PROJECT_NAME}\")\r\n      set(CPACK_NSIS_MUI_ICON \"${PROJECT_SOURCE_DIR}/Packaging/windows/icon.ico\")\r\n      set(CPACK_NSIS_MUI_UNIICON \"${PROJECT_SOURCE_DIR}/Packaging/windows/icon.ico\")\r\n      set(CPACK_RESOURCE_FILE_LICENSE \"${PROJECT_SOURCE_DIR}/LICENSE.md\")\r\n      set(CPACK_NSIS_EXECUTABLES_DIRECTORY \".\")\r\n      set(CPACK_PACKAGE_EXECUTABLES \"devilutionx\" \"DevilutionX\")\r\n      set(CPACK_NSIS_MUI_FINISHPAGE_RUN \"${BIN_TARGET}\")\r\n    else()\r\n      set(CPACK_PACKAGE_FILE_NAME \"devilutionx\")\r\n      set(CPACK_GENERATOR \"ZIP\")\r\n    endif()\r\n    set(CPACK_STRIP_FILES TRUE)\r\n    install(TARGETS ${BIN_TARGET} DESTINATION .)\r\n    install(FILES \"${PROJECT_SOURCE_DIR}/Packaging/windows/README.txt\"\r\n      DESTINATION \".\"\r\n    )\r\n    install(FILES \"${DEVILUTIONX_MPQ}\"\r\n      DESTINATION \".\"\r\n    )\r\n    install(FILES \"${HELLFIRE_MPQ}\"\r\n      DESTINATION \"mods\"\r\n    )\r\n\r\n    foreach(_SDL2_WIN32_DLL_PATH ${SDL2_WIN32_ALL_DLLS} ${WIN32_INSTALL_DLLS})\r\n      install(FILES \"${_SDL2_WIN32_DLL_PATH}\"\r\n        DESTINATION \".\"\r\n      )\r\n    endforeach()\r\n\r\n    foreach(_SDL2_WIN32_LICENSE_PATH ${SDL2_WIN32_ALL_LICENSES})\r\n      install(FILES \"${_SDL2_WIN32_LICENSE_PATH}\"\r\n        DESTINATION \"LICENSE\"\r\n      )\r\n    endforeach()\r\n\r\n    if(DISCORD_SHARED_LIB)\r\n      install(FILES \"${DISCORD_SHARED_LIB}\"\r\n        DESTINATION \".\"\r\n      )\r\n    endif()\r\n\r\n    if(SCREEN_READER_INTEGRATION)\r\n      install(FILES \"${Tolk_BINARY_DIR}/libTolk.dll\"\r\n        DESTINATION \".\"\r\n      )\r\n    endif()\r\n\r\n  elseif(CMAKE_SYSTEM_NAME STREQUAL \"Linux\")\r\n    string(TOLOWER ${PROJECT_NAME} project_name)\r\n    set(CPACK_PACKAGE_NAME ${project_name})\r\n    set(CPACK_GENERATOR \"7Z\")\r\n    # Common *nix files\r\n    set(CPACK_STRIP_FILES TRUE)\r\n    install(TARGETS ${BIN_TARGET} DESTINATION bin)\r\n    set(desktop_file \"${PROJECT_SOURCE_DIR}/Packaging/nix/${project_name}.desktop\")\r\n    set(desktop_file_hellfire \"${PROJECT_SOURCE_DIR}/Packaging/nix/${project_name}-hellfire.desktop\")\r\n\r\n    find_program(DFI desktop-file-install)\r\n    if(DFI)\r\n      execute_process(COMMAND ${DFI} --dir=${CMAKE_BINARY_DIR} ${desktop_file})\r\n      set(desktop_file \"${CMAKE_BINARY_DIR}/${project_name}.desktop\")\r\n      execute_process(COMMAND ${DFI} --dir=${CMAKE_BINARY_DIR} ${desktop_file_hellfire})\r\n      set(desktop_file_hellfire \"${CMAKE_BINARY_DIR}/${project_name}-hellfire.desktop\")\r\n    endif()\r\n\r\n    install(FILES \"${desktop_file}\"\r\n      DESTINATION \"share/applications\"\r\n    )\r\n    install(FILES \"${desktop_file_hellfire}\"\r\n      DESTINATION \"share/applications\"\r\n    )\r\n    install(FILES \"${PROJECT_SOURCE_DIR}/Packaging/nix/README.txt\"\r\n      DESTINATION \"share/diasurgical/${project_name}\"\r\n    )\r\n    install(FILES \"${DEVILUTIONX_MPQ}\"\r\n      DESTINATION \"share/diasurgical/${project_name}\"\r\n    )\r\n    install(FILES \"${HELLFIRE_MPQ}\"\r\n      DESTINATION \"share/diasurgical/${project_name}/mods\"\r\n    )\r\n    install(FILES \"${PROJECT_SOURCE_DIR}/Packaging/resources/icon_flat.png\"\r\n      DESTINATION \"share/icons/hicolor/512x512/apps\"\r\n      RENAME \"${project_name}.png\"\r\n    )\r\n    install(FILES \"${PROJECT_SOURCE_DIR}/Packaging/resources/hellfire.png\"\r\n      DESTINATION \"share/icons/hicolor/512x512/apps\"\r\n      RENAME \"${project_name}-hellfire.png\"\r\n    )\r\n    install(FILES \"${PROJECT_SOURCE_DIR}/Packaging/nix/devilutionx.metainfo.xml\"\r\n      DESTINATION \"share/metainfo\"\r\n      RENAME \"${project_name}.metainfo.xml\"\r\n    )\r\n    if(DISCORD_SHARED_LIB)\r\n      install(FILES \"${DISCORD_SHARED_LIB}\" DESTINATION \"lib\")\r\n    endif()\r\n\r\n    # -G DEB\r\n    set(CPACK_PACKAGE_CONTACT \"anders@jenbo.dk\")\r\n    if(USE_SDL1)\r\n    set(CPACK_DEBIAN_PACKAGE_DEPENDS \"libsdl1.2debian\")\r\n    else()\r\n    set(CPACK_DEBIAN_PACKAGE_DEPENDS \"libsdl2-2.0-0, libsdl2-image-2.0-0\")\r\n    endif()\r\n    set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)\r\n\r\n    # -G RPM\r\n    set(CPACK_RPM_FILE_NAME RPM-DEFAULT)\r\n\r\n    find_program(RPMBUILD rpmbuild)\r\n    if(RPMBUILD)\r\n      list(APPEND CPACK_GENERATOR \"RPM\")\r\n    endif()\r\n    find_program(DPKG dpkg)\r\n    if(DPKG)\r\n      list(APPEND CPACK_GENERATOR \"DEB\")\r\n    endif()\r\n\r\n  elseif(APPLE)\r\n    set(CPACK_PACKAGE_FILE_NAME \"devilutionx\")\r\n    set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK \"ON\")\r\n    set(CPACK_STRIP_FILES TRUE)\r\n    set(CPACK_GENERATOR \"DragNDrop\")\r\n  endif()\r\n\r\n  set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})\r\n  set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})\r\n  set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})\r\n  include(CPack)\r\nendif()\r\n\r\nresolve_target_link_dependencies()\r\nif(UWP_LIB)\r\n  get_target_property(_linked_objects libdevilutionx LINKED_OBJECTS)\r\n  target_sources(libdevilutionx PRIVATE ${_linked_objects})\r\nendif()\r\n"
  },
  {
    "path": "CMakeSettings.json",
    "content": "{\r\n  \"configurations\": [\r\n    {\r\n      \"name\": \"x64-Debug\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Debug\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"inheritEnvironments\": [ \"msvc_x64\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x64\",\r\n      \"enableClangTidyCodeAnalysis\": true,\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    },\r\n    {\r\n      \"name\": \"x64-Debug-Translations\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Debug\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"inheritEnvironments\": [ \"msvc_x64\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x64\",\r\n      \"enableClangTidyCodeAnalysis\": true,\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        },\r\n        {\r\n          \"name\": \"USE_GETTEXT_FROM_VCPKG\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    },\r\n    {\r\n      \"name\": \"x64-Debug-SDL1\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Debug\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"inheritEnvironments\": [ \"msvc_x64\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x64\",\r\n      \"cmakeCommandArgs\": \"-DUSE_SDL1=ON\",\r\n      \"enableClangTidyCodeAnalysis\": true,\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    },\r\n    {\r\n      \"name\": \"x64-Release\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Release\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"cmakeCommandArgs\": \"-DCPACK=ON\",\r\n      \"inheritEnvironments\": [ \"msvc_x64\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x64\",\r\n      \"enableClangTidyCodeAnalysis\": true,\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    },\r\n    {\r\n      \"name\": \"x64-RelWithDebInfo\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"RelWithDebInfo\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"cmakeCommandArgs\": \"-DCPACK=ON\",\r\n      \"inheritEnvironments\": [ \"msvc_x64\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x64\",\r\n      \"enableClangTidyCodeAnalysis\": true,\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    },\r\n    {\r\n      \"name\": \"x86-Debug\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Debug\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"inheritEnvironments\": [ \"msvc_x86\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x86\",\r\n      \"enableClangTidyCodeAnalysis\": true,\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    },\r\n    {\r\n      \"name\": \"x86-Release\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Release\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"cmakeCommandArgs\": \"-DCPACK=ON\",\r\n      \"inheritEnvironments\": [ \"msvc_x86\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x86\",\r\n      \"enableClangTidyCodeAnalysis\": true,\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    },\r\n    {\r\n      \"name\": \"x64-Debug-WSL-GCC\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Debug\",\r\n      \"buildRoot\": \"${workspaceRoot}\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${env.USERPROFILE}\\\\CMakeBuilds\\\\${workspaceHash}\\\\install\\\\${name}\",\r\n      \"cmakeExecutable\": \"cmake\",\r\n      \"cmakeCommandArgs\": \"\",\r\n      \"buildCommandArgs\": \"\",\r\n      \"ctestCommandArgs\": \"\",\r\n      \"inheritEnvironments\": [ \"linux_x64\" ],\r\n      \"wslPath\": \"${defaultWSLPath}\",\r\n      \"variables\": [\r\n        {\r\n          \"name\": \"DISCORD_INTEGRATION\",\r\n          \"value\": \"True\",\r\n          \"type\": \"BOOL\"\r\n        }\r\n      ]\r\n    }\r\n  ]\r\n}\r\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\ncontact@diasurgical.org.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# Sustainable Use License\n\nVersion 1.0\n\n## Acceptance\n\nBy using the software, you agree to all of the terms and conditions below.\n\n## Copyright License\n\nThe licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.\n\n## Limitations\n\nYou may use or modify the software only for your own internal business purposes or for non-commercial or personal use.\nYou may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes.\nYou may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.\n\n## Patents\n\nThe licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.\n\n## Notices\n\nYou must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.\nIf you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.\n\n## No Other Rights\n\nThese terms do not imply any licenses other than those expressly granted in these terms.\n\n## Termination\n\nIf you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.\n\n## No Liability\n\nAs far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.\n\n## Definitions\n\nThe “licensor” is the entity offering these terms.\n\nThe “software” is the software the licensor makes available under these terms, including any portion of it.\n\n“You” refers to the individual or entity agreeing to these terms.\n\n“Your company” is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.\n\n“Your license” is the license granted to you for the software under these terms.\n\n“Use” means anything you do with the software requiring your license.\n\n“Trademark” means trademarks, service marks, and similar rights.\n"
  },
  {
    "path": "Packaging/OpenDingux/.editorconfig",
    "content": "[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n"
  },
  {
    "path": "Packaging/OpenDingux/.gitignore",
    "content": "/tmp/\n"
  },
  {
    "path": "Packaging/OpenDingux/README.md",
    "content": "# DevilutionX OpenDingux Port\n\nSee docs/building.md for build instructions.\n"
  },
  {
    "path": "Packaging/OpenDingux/build-all.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\ncd \"$(dirname \"${BASH_SOURCE[0]}\")/../..\"\n\nsource Packaging/OpenDingux/targets.sh\n\nfor target in \"${VALID_TARGETS[@]}\"; do\n\tPackaging/OpenDingux/build.sh \"$target\"\ndone\n"
  },
  {
    "path": "Packaging/OpenDingux/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\ncd \"$(dirname \"${BASH_SOURCE[0]}\")/../..\"\n\nsource Packaging/OpenDingux/targets.sh\nsource Packaging/OpenDingux/package-opk.sh\n\nusage() {\n  >&2 echo \"Usage: build.sh [--profile-generate|--profile-use] [--profile-dir PATH] [target]\"\n  >&2 usage_target\n}\n\ndeclare -rA BUILDROOT_REPOS=(\n\t[lepus]=https://github.com/OpenDingux/buildroot.git\n\t[retrofw]=https://github.com/retrofw/buildroot.git\n\t[rg99]=https://github.com/OpenDingux/buildroot.git\n\t[rg350]=https://github.com/OpenDingux/buildroot.git\n\t[gkd350h]=https://github.com/tonyjih/RG350_buildroot.git\n)\ndeclare -rA BUILDROOT_DEFCONFIGS=(\n\t[lepus]='od_lepus_defconfig BR2_EXTERNAL=board/opendingux'\n\t[retrofw]='RetroFW_defconfig BR2_EXTERNAL=retrofw'\n\t[rg99]='od_rs90_defconfig BR2_EXTERNAL=board/opendingux'\n\t[rg350]='od_gcw0_defconfig BR2_EXTERNAL=board/opendingux'\n\t[gkd350h]='rg350_defconfig BR2_EXTERNAL=board/opendingux'\n)\n\ndeclare TARGET\ndeclare BUILD_DIR\ndeclare BUILDROOT\ndeclare BUILDROOT_TARGET\ndeclare TOOLCHAIN\n\ndeclare -a CMAKE_CONFIGURE_OPTS=()\ndeclare PROFILE_GENERATE=0\ndeclare PROFILE_USE=0\ndeclare PROFILE_DIR=\"%q{HOME}/devilutionx-profile\"\ndeclare BUILD_TYPE=release\n\nmain() {\n\tparse_args \"$@\"\n\tBUILDROOT_TARGET=\"$TARGET\"\n\n\t# If a TOOLCHAIN environment variable is set, just use that.\n\tif [[ -z ${TOOLCHAIN:-} ]]; then\n\t\tBUILDROOT=\"${BUILDROOT:-$HOME/devilutionx-buildroots/$BUILDROOT_TARGET}\"\n\t\tTOOLCHAIN=\"${BUILDROOT}/output/host\"\n\tfi\n\n\t>&2 echo \"Building for target ${TARGET} in ${BUILD_DIR}\"\n\tset -x\n\tif [[ -n ${BUILDROOT:-} ]]; then\n\t\tprepare_buildroot\n\t\tmake_buildroot\n\tfi\n\tbuild\n\tpackage_opk\n}\n\nparse_args() {\n\tlocal -a positional=()\n\twhile [[ $# -gt 0 ]]; do\n\t\tcase \"$1\" in\n\t\t--profile-generate)\n\t\t\tPROFILE_GENERATE=1\n\t\t\tshift\n\t\t\t;;\n\t\t--profile-use)\n\t\t\tPROFILE_USE=1\n\t\t\tshift\n\t\t\t;;\n\t\t--profile-dir)\n\t\t\tshift\n\t\t\tif [[ $# -eq 0 ]]; then\n\t\t\t\tusage\n\t\t\t\texit 64\n\t\t\tfi\n\t\t\tPROFILE_DIR=\"$1\"\n\t\t\tshift\n\t\t\t;;\n\t\t-*|--*)\n\t\t\t>&2 echo \"Error: unknown argument $1\"\n\t\t\t>&2 echo\n\t\t\tusage\n\t\t\texit 64\n\t\t\t;;\n\t\t*)\n\t\t\tpositional+=(\"$1\")\n\t\t\tshift\n\t\t\t;;\n\t\tesac\n\tdone\n\tif [[ ${#positional[@]} -ne 1 ]] || ! check_target \"${positional[0]}\"; then\n\t\t>&2 echo \"Error: target is required\"\n\t\t>&2 echo\n\t\tusage\n\t\texit 64\n\tfi\n\tTARGET=\"${positional[0]}\"\n\tBUILD_DIR=\"build-${TARGET}\"\n\n\tif (( PROFILE_GENERATE )) && (( PROFILE_USE )); then\n\t\t>&2 echo \"Error: at most one of --profile-use and --profile-generate is allowed\"\n\t\texit 64\n\tfi\n\tif [[ $TARGET = rg99 ]]; then\n\t\tOPK_EXTRA_FILES+=(\n\t\t\tPackaging/OpenDingux/devilutionx-from-disk.sh\n\t\t\tPackaging/OpenDingux/devilutionx-umount-opk-and-run.sh\n\t\t)\n\t\tOPK_DESKTOP_EXEC=\"devilutionx-from-disk.sh\"\n\tfi\n\tif (( PROFILE_GENERATE )); then\n\t\tCMAKE_CONFIGURE_OPTS+=(\n\t\t\t\"-DDEVILUTIONX_PROFILE_GENERATE=ON\"\n\t\t\t\"-DDEVILUTIONX_PROFILE_DIR=${PROFILE_DIR}\"\n\t\t)\n\t\tOPK_DESKTOP_NAME=\"DevilutionX PG\"\n\t\tOPK_DESKTOP_EXEC=\"profile-generate.sh\"\n\t\tOPK_EXTRA_FILES+=(\n\t\t\tPackaging/OpenDingux/profile-generate.sh\n\t\t\ttest/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo\n\t\t)\n\t\tlocal -a demo_saves=(\n\t\t\ttest/fixtures/timedemo/WarriorLevel1to2/demo_0_reference_spawn_0.sv\n\t\t\ttest/fixtures/timedemo/WarriorLevel1to2/spawn_0.sv\n\t\t)\n\t\tif [[ $TARGET = rg99 ]]; then\n\t\t\t# We use unpacked saves on RG99.\n\t\t\tmkdir -p \"$BUILD_DIR/demo-saves\"\n\t\t\tunpack_and_minify_mpq --output-dir \"$BUILD_DIR/demo-saves\" \"${demo_saves[@]}\"\n\t\t\tOPK_EXTRA_FILES+=(\"$BUILD_DIR/demo-saves\"/*)\n\t\telse\n\t\t\tOPK_EXTRA_FILES+=(\"${demo_saves[@]}\")\n\t\tfi\n\tfi\n\tif (( PROFILE_USE )); then\n\t\tCMAKE_CONFIGURE_OPTS+=(\n\t\t\t\"-DDEVILUTIONX_PROFILE_USE=ON\"\n\t\t\t\"-DDEVILUTIONX_PROFILE_DIR=${PROFILE_DIR}\"\n\t\t)\n\tfi\n}\n\nprepare_buildroot() {\n\tif [[ -d $BUILDROOT ]]; then\n\t\treturn\n\tfi\n\tif [[ \"${BUILDROOT_REPOS[$BUILDROOT_TARGET]}\" == *.tar.gz ]]; then\n\t\tmkdir -p \"$BUILDROOT\"\n\t\tcurl -L --fail \"${BUILDROOT_REPOS[$BUILDROOT_TARGET]}\" | \\\n\t\t\ttar -xz --strip-components 1 -C \"$BUILDROOT\"\n\telse\n\t\tgit clone --depth=1 \"${BUILDROOT_REPOS[$BUILDROOT_TARGET]}\" \"$BUILDROOT\"\n\tfi\n\tcd \"$BUILDROOT\"\n\tmkdir -p ../shared-dl\n\tln -s ../shared-dl dl\n\n\t# Work around a BR2_EXTERNAL initialization bug in older buildroots.\n\tmkdir -p output\n\ttouch output/.br-external.mk\n\tlocal -a config_args=(${BUILDROOT_DEFCONFIGS[$BUILDROOT_TARGET]})\n\tlocal -r config=\"${config_args[0]}\"\n\n\t# If the buildroot uses per-package directories, disable them.\n\t# Otherwise, we'd have to buildroot the entire buildroot (up to `host-finalize`) to get\n\t# the merged host directory.\n\tif grep -q BR2_PER_PACKAGE_DIRECTORIES=y \"configs/${config}\"; then\n\t\tlocal -r new_config=\"${config%_defconfig}_no_ppd_defconfig\"\n\t\tsed 's/BR2_PER_PACKAGE_DIRECTORIES=y/# BR2_PER_PACKAGE_DIRECTORIES is not selected/' \\\n\t\t  \"configs/${config}\" > \"configs/${new_config}\"\n\t\tconfig_args[0]=\"$new_config\"\n\tfi\n\n\tmake \"${config_args[@]}\"\n\tcd -\n}\n\nmake_buildroot() {\n\tcd \"$BUILDROOT\"\n\tlocal -a env_args=(\n\t  # Unset client variables that cause issues with buildroot\n\t  -u PERL_MM_OPT\n\t  -u CMAKE_GENERATOR -u CMAKE_GENERATOR_PLATFORM -u CMAKE_GENERATOR_TOOLSET -u CMAKE_GENERATOR_INSTANCE\n\n\t  # Enable parallelism\n\t  BR2_JLEVEL=0\n\t)\n\tenv \"${env_args[@]}\" make toolchain sdl\n\tcd -\n}\n\ncmake_configure() {\n\t# libzt uses `-fstack-protector` GCC flag by default.\n\t# We disable `-fstack-protector` because it isn't supported by target libc.\n\tcmake -S. -B\"$BUILD_DIR\" \\\n\t\t-G \"Unix Makefiles\" \\\n\t\t\"-DTARGET_PLATFORM=$TARGET\" \\\n\t\t-DCMAKE_TOOLCHAIN_FILE=\"${TOOLCHAIN}/usr/share/buildroot/toolchainfile.cmake\" \\\n\t\t-DBUILD_TESTING=OFF \\\n\t\t-DDEVILUTIONX_SYSTEM_LIBFMT=OFF \\\n\t\t-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF \\\n\t\t-DDEVILUTIONX_SYSTEM_BZIP2=OFF \\\n\t\t-DSTACK_PROTECTOR=OFF \\\n\t\t\"${CMAKE_CONFIGURE_OPTS[@]}\"\n}\n\ncmake_build() {\n\tBR_CACHE_DIR=\"${HOME}/.buildroot-ccache\" cmake --build \"$BUILD_DIR\" -j \"$(getconf _NPROCESSORS_ONLN)\"\n}\n\nstrip_bin() {\n\t\"${TOOLCHAIN}/usr/bin/\"*-linux-strip -s -R .comment -R .gnu.version \"${BUILD_DIR}/devilutionx\"\n}\n\nbuild_debug() {\n\tcmake_configure -DCMAKE_BUILD_TYPE=Debug -DASAN=OFF -DUBSAN=OFF -DCMAKE_CXX_FLAGS_DEBUG=\"-g -fno-omit-frame-pointer\" \"$@\"\n\tcmake_build\n}\n\nbuild_relwithdebinfo() {\n\tcmake_configure -DCMAKE_BUILD_TYPE=RelWithDebInfo \"$@\"\n\tcmake_build\n}\n\nbuild_minsizerel() {\n\tcmake_configure -DCMAKE_BUILD_TYPE=MinSizeRel \"$@\"\n\tcmake_build\n\tstrip_bin\n}\n\nbuild_release() {\n\tcmake_configure -DCMAKE_BUILD_TYPE=Release \"$@\"\n\tcmake_build\n\tstrip_bin\n}\n\nbuild() {\n\trm -f \"${BUILD_DIR}/CMakeCache.txt\"\n\tbuild_\"$BUILD_TYPE\" \"$@\"\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "Packaging/OpenDingux/devilutionx-from-disk.sh",
    "content": "#!/bin/sh\n\n# Unpacks the mounted OPK to disk before running it\n# in order to avoid the memory overhead of squashfs.\n\nOPK_DIR=\"${PWD}\"\nSTORAGE=\"$(grep mmcblk /proc/mounts | cut -d' ' -f2 || echo /media/data/local/home)\"\nUNPACK_DIR=\"${STORAGE}/devilutionx-opk-on-disk\"\n\nset -e\nset -x\n\nDO_COPY=1\nif [ -f \"${UNPACK_DIR}/devilutionx\" ]; then\n\tINSTALLED_MD5=\"$(md5sum \"${UNPACK_DIR}/devilutionx\" | cut -d' ' -f1)\"\n\tOPK_MD5=\"$(md5sum \"${PWD}/devilutionx\" | cut -d' ' -f1)\"\n\tif [ \"$INSTALLED_MD5\" = \"$OPK_MD5\" ]; then\n\t\tDO_COPY=0\n\tfi\nfi\n\nif [ \"$DO_COPY\" = \"1\" ]; then\n\trm -rf \"$UNPACK_DIR\"\n\tmkdir -p \"$UNPACK_DIR\"\n\tcp -rf \"$OPK_DIR\"/* \"$UNPACK_DIR\"\nfi\n\nexec \"${UNPACK_DIR}/devilutionx-umount-opk-and-run.sh\" \"${UNPACK_DIR}/devilutionx\" \"$@\"\n"
  },
  {
    "path": "Packaging/OpenDingux/devilutionx-umount-opk-and-run.sh",
    "content": "#!/bin/sh\n\nset -x\necho | sudo -S umount -l \"$PWD\"\nexec \"$@\"\n"
  },
  {
    "path": "Packaging/OpenDingux/gkd350h-manual.txt",
    "content": "Copy diabdat.mpq from your CD (or GoG install folder) to:\n/usr/local/home/.local/share/diasurgical/devilution/\n\nFor Hellfire, also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, and hfvoice.mpq.\n\nFor Chinese, Japanese, and Korean text support copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq\n\nFor the Polish voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq\n\nFor the Russian voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq\n\nGame saves and diablo.ini are located at:\n/usr/local/home/.local/share/diasurgical/devilution/\n\nControls:\n\n- Joystick / D-Pad: move hero\n- ○: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- ×: select spell, back while in menus\n- △: pickup items, open nearby chests and doors, use item in the inventory\n- □: cast spell, delete character while in main menu\n- L: use health item from belt\n- R: use mana potion from belt\n- Select + ↑: game menu\n- Select + L or ←: character info\n- Select + R or →: inventory\n- Select + ↓: map\n- Select + □: Quest log\n- Select + ×: Spell book\n- Start + △○×□: Quick spell hotkeys\n\nKnown issues/quirks:\n\n* Start and Select are swapped in this version because Start + D-Pad controls backlight on the GKD350h.\n* There is nothing to map mouse emulation to in this version because of this but it isn't necessary to play the game. Unfortunately, this also means that you can't move the automap.\n* This version looks uglier than on RG350 because it uses software scaling beacuse the IPU on the GKD350h doesn't work.\n\nSource: https://github.com/diasurgical/devilutionX/\n"
  },
  {
    "path": "Packaging/OpenDingux/gkd350h.desktop",
    "content": "[Desktop Entry]\nName=DevilutionX\nComment=Diablo 1 for GKD350h\nExec=devilutionx\nTerminal=false\nType=Application\nStartupNotify=true\nIcon=icon_32\nCategories=games;\nX-OD-Manual=readme.gcw0.txt\nX-OD-NeedsDownscaling=true\n"
  },
  {
    "path": "Packaging/OpenDingux/lepus-manual.txt",
    "content": "Copy diabdat.mpq from your CD (or GoG install folder) to:\n~/.local/share/diasurgical/devilution/\n\nFor Hellfire, also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, and hfvoice.mpq.\n\nFor Chinese, Japanese, and Korean text support copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq\n\nFor the Polish voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq\n\nFor the Russian voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq\n\nGame saves and diablo.ini are located at:\n~/.local/share/diasurgical/devilution\n\n~ is your home directory, /media/data/home by default.\n\nControls:\n- D-pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- R: use mana potion from belt\n- L: use health item from belt\n- Start + Select: game menu (alt: Start + ↑)\n- Start + L or ←: character info\n- Start + R or →: inventory\n- Start + ↓: map\n- Start + Y: Quest log\n- Start + B: Spell book\n- Select + A/B/X/Y: hot spell\n- Select + D-pad: move map/cursor\n- Select + L: left mouse click\n- Select + R: right mouse click\n- Suspend: map\n\nSource: https://github.com/diasurgical/devilutionX/\n"
  },
  {
    "path": "Packaging/OpenDingux/lepus.desktop",
    "content": "[Desktop Entry]\nName=DevilutionX\nComment=Diablo 1 for OpenDingux\nExec=devilutionx\nTerminal=false\nType=Application\nStartupNotify=true\nIcon=icon_32\nCategories=games;\nX-OD-Manual=readme.lepus.txt\nX-OD-NeedsDownscaling=true\nX-OD-NeedsJoystick=true\n"
  },
  {
    "path": "Packaging/OpenDingux/package-opk.sh",
    "content": "#!/usr/bin/env bash\n\ndeclare OPK_DESKTOP_NAME\ndeclare OPK_DESKTOP_EXEC\ndeclare -a OPK_EXTRA_FILES\n\npackage_opk() {\n\tlocal ext\n\tif [[ $TARGET == rg350 ]] || [[ $TARGET == gkd350h ]]; then\n\t\text=gcw0\n\telse\n\t\text=\"$TARGET\"\n\tfi\n\tlocal -r tmp=\"${BUILD_DIR}/opk\"\n\tset -x\n\trm -rf \"$tmp\"\n\tmkdir -p \"$tmp\"\n\tcp \"Packaging/OpenDingux/${TARGET}.desktop\" \"${tmp}/default.${ext}.desktop\"\n\tcp \"Packaging/OpenDingux/${TARGET}-manual.txt\" \"${tmp}/readme.${ext}.txt\"\n\n\tif [[ -v OPK_DESKTOP_NAME ]]; then\n\t\tsed -i \"s/Name=.*/Name=${OPK_DESKTOP_NAME}/\" \"${tmp}/default.${ext}.desktop\"\n\tfi\n\tif [[ -v OPK_DESKTOP_EXEC ]]; then\n\t\tsed -i \"s/Exec=.*/Exec=${OPK_DESKTOP_EXEC}/\" \"${tmp}/default.${ext}.desktop\"\n\tfi\n\n\tmksquashfs \"${BUILD_DIR}/devilutionx\" \\\n\t\t\"${tmp}/default.${ext}.desktop\" \\\n\t\t\"${tmp}/readme.${ext}.txt\" Packaging/resources/icon_32.png \\\n\t\t\"${BUILD_DIR}/assets/\" \\\n\t\t\"${OPK_EXTRA_FILES[@]}\" \\\n\t\t\"${BUILD_DIR}/devilutionx-${TARGET}.opk\" \\\n\t\t-all-root -no-xattrs -noappend -no-exports -no-progress\n}\n\nif [[ \"${BASH_SOURCE[0]}\" == \"${0}\" ]]; then\n\tset -euo pipefail\n\n\tcd \"$(dirname \"${BASH_SOURCE[0]}\")/../..\"\n\n\tsource Packaging/OpenDingux/targets.sh\n\n\tusage() {\n\t\techo \"Usage: package-opk.sh [target]\"\n\t\tusage_target\n\t}\n\n\tif ! check_target \"$@\"; then\n\t\tusage\n\t\texit 64\n\tfi\n\n\tdeclare -r TARGET=\"$1\"\n\tdeclare -r BUILD_DIR=\"build-${TARGET}\"\n\tpackage_opk\nfi\n"
  },
  {
    "path": "Packaging/OpenDingux/profile-generate.sh",
    "content": "#!/bin/sh\n\nset -x\n\nSAVE_DIR=\"$(mktemp -d)\"\ncp \"${PWD}/demo_0_reference_spawn_0_sv\" \"${SAVE_DIR}/\"\ncp \"${PWD}/demo_0.dmo\" \"${SAVE_DIR}/\"\ncp -r \"${PWD}/spawn_0_sv\" \"${SAVE_DIR}/\"\nrm -rf \"${HOME}/devilutionx-profile\"\nmkdir -p \"${HOME}/devilutionx-profile\"\n./devilutionx-from-disk.sh --diablo --spawn --demo 0 --timedemo --save-dir \"$SAVE_DIR\" --data-dir ~/.local/share/diasurgical/devilution\nrm -rf \"$SAVE_DIR\"\n"
  },
  {
    "path": "Packaging/OpenDingux/retrofw-manual.txt",
    "content": "Copy diabdat.mpq from your CD (or GoG install folder) to:\n~/.local/share/diasurgical/devilution\n\nFor Hellfire, also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, and hfvoice.mpq.\n\nFor Chinese, Japanese, and Korean text support copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq\n\nFor the Polish voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq\n\nFor the Russian voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq\n\nGame saves and diablo.ini are located at:\n~/.local/share/diasurgical/devilution\n\n~ is your home directory, /home/retrofw by default.\n\nControls:\n- D-pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- R: use mana potion from belt\n- L: use health item from belt\n- Start + Select: game menu (alt: Start + ↑)\n- Start + L or ←: character info\n- Start + R or →: inventory\n- Start + ↓: map\n- Start + Y: Quest log\n- Start + B: Spell book\n- Select + A/B/X/Y: hot spell\n- Select + D-pad: move map/cursor\n- Select + L: left mouse click\n- Select + R: right mouse click\n- Suspend: map\n"
  },
  {
    "path": "Packaging/OpenDingux/retrofw.desktop",
    "content": "[Desktop Entry]\nName=DevilutionX\nComment=Diablo 1 for RetroFW\nExec=devilutionx\nTerminal=false\nType=Application\nStartupNotify=true\nIcon=icon_32\nCategories=games;\nX-OD-Manual=readme.retrofw.txt\nX-OD-NeedsDownscaling=true\nX-OD-NeedsJoystick=true\n"
  },
  {
    "path": "Packaging/OpenDingux/rg350-manual.txt",
    "content": "Copy diabdat.mpq from your CD (or GoG install folder) to:\n~/.local/share/diasurgical/devilution/\n\nFor Hellfire, also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, and hfvoice.mpq.\n\nFor Chinese, Japanese, and Korean text support copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq\n\nFor the Polish voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq\n\nFor the Russian voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq\n\nGame saves and diablo.ini are located at:\n~/.local/share/diasurgical/devilution/\n\n~ is your home directory, /media/data/home by default.\n\nControls:\n\n- Left analog or D-Pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- L1: use health item from belt\n- R1: use mana potion from belt\n- L2: character sheet (alt: Start + L1 or ←)\n- R2: inventory (alt: Start + R1 or →)\n- Left analog click: toggle automap (alt: Start + ↓)\n- Start + Select: game menu (alt: Start + ↑)\n- Select + A/B/X/Y: Spell hotkeys\n- Right analog: move automap or simulate mouse\n- Right analog click: left mouse click (alt: Select + L1)\n- Select + Right analog click: right mouse click (alt: Select + R1)\n- Select + L2: quest log (alt: Start + Y)\n- Select + R2: spell book (alt: Start + B)\n\nSource: https://github.com/diasurgical/devilutionX/\n"
  },
  {
    "path": "Packaging/OpenDingux/rg350.desktop",
    "content": "[Desktop Entry]\nName=DevilutionX\nComment=Diablo 1 for RG350\nExec=devilutionx\nTerminal=false\nType=Application\nStartupNotify=true\nIcon=icon_32\nCategories=games;\nX-OD-Manual=readme.gcw0.txt\nX-OD-NeedsDownscaling=true\nX-OD-NeedsJoystick=true\n"
  },
  {
    "path": "Packaging/OpenDingux/rg99-manual.txt",
    "content": "Copy diabdat.mpq from your CD (or GoG install folder) to:\n~/.local/share/diasurgical/devilution/\n\nFor Hellfire, also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, and hfvoice.mpq.\n\nFor Chinese, Japanese, and Korean text support copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq\n\nFor the Polish voice pack copy:\nhttps://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq\n\nGame saves and diablo.ini are located at:\n~/.local/share/diasurgical/devilution\n\n~ is your home directory, /media/data/home by default.\n\nControls:\n- D-pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- R: use mana potion from belt\n- L: use health item from belt\n- Start + Select: game menu (alt: Start + ↑)\n- Start + L or ←: character info\n- Start + R or →: inventory\n- Start + ↓: map\n- Start + Y: Quest log\n- Start + B: Spell book\n- Select + A/B/X/Y: hot spell\n- Select + D-pad: move map/cursor\n- Select + L: left mouse click\n- Select + R: right mouse click\n- Suspend: map\n"
  },
  {
    "path": "Packaging/OpenDingux/rg99-pgo.md",
    "content": "# RG99 profile-guided optimization\n\nThe RG99 build must be PGO'd for reasonable performance.\n\nHere are the instructions for producing a PGO'd build.\n\n1.  Install <https://github.com/diasurgical/devilutionx-mpq-tools>\n\n2.  Build the OPK for profiling data collection:\n\n    ```sh\n    TOOLCHAIN=/opt/rs90-toolchain Packaging/OpenDingux/build.sh rg99 --profile-generate\n    ```\n\n3.  Copy the OPK to RG99 (`rg99` is 10.1.1.3):\n\n    ```sh\n    scp -O build-rg99/devilutionx-rg99.opk rg99:/media/sdcard/apps\n    ```\n\n4.  Now, run the OPK. It will run the timedemo instead of the actual game and will take about 1 hour (due to heavy swapping).\n\n\n5.  Copy the profiling data from RG99:\n\n    ```sh\n    rm -rf /tmp/devilutionx-profile\n    scp -r -O rg99:/media/data/local/home/devilutionx-profile /tmp/devilutionx-profile\n    ```\n\n6.  Build the OPK use the collected profiling data:\n\n    ```sh\n    TOOLCHAIN=/opt/rs90-toolchain Packaging/OpenDingux/build.sh rg99 --profile-use --profile-dir /tmp/devilutionx-profile\n    ```\n\n7.  The final package is at `build-rg99/devilutionx-rg99.opk`.\n\n## Remote Debugging with VS Code\n\nIf the demo crashes and you cannot reproduce this on PC, you can\nuse a remote debugger to diagnose the issue.\n\nUnpack the package and copy it to the RG99:\n\n```bash\ncd build-rg99\nrm -rf squashfs-root\nunsquashfs devilutionx-rg99.opk\nssh rg99 'rm -rf /media/data/local/home/squashfs-root'\nscp -r -O squashfs-root/ rg99:/media/data/local/home/squashfs-root\n```\n\nThen, on RG99, prepare the demo files and run `gdbserver`:\n\n```bash\nmkdir -p demo\ncp -r squashfs-root/demo_0* demo\ncp -r squashfs-root/spawn_0_sv demo\ncd squashfs-root\ngdbserver 10.1.1.1:8001 devilutionx --diablo --spawn --demo 0 --timedemo \\\n  --save-dir ~/demo --data-dir ~/.local/share/diasurgical/devilution\n```\n\nThen, on the PC, add the following VS Code configuration to `.vscode/launch.json`:\n\n```json\n{\n\t\"name\": \"rg99 remote debug\",\n\t\"type\": \"cppdbg\",\n\t\"request\": \"launch\",\n\t\"program\": \"build-rg99/devilutionx\",\n\t\"stopAtEntry\": true,\n\t\"miDebuggerPath\": \"/opt/rs90-toolchain/bin/mipsel-linux-gdb\",\n\t\"miDebuggerArgs\": \"-ix /opt/rs90-toolchain/mipsel-rs90-linux-musl/sysroot/usr/share/buildroot/gdbinit\",\n\t\"MIMode\": \"gdb\",\n\t\"miDebuggerServerAddress\": \"10.1.1.3:8001\",\n\t\"targetArchitecture\": \"mips\",\n\t\"additionalSOLibSearchPath\": \"/opt/rs90-toolchain/mipsel-rs90-linux-musl/sysroot\",\n\t\"setupCommands\": [\n\t\t{\n\t\t\t\"description\": \"Enable pretty-printing for gdb\",\n\t\t\t\"text\": \"-enable-pretty-printing\",\n\t\t\t\"ignoreFailures\": true\n\t\t}\n\t],\n\t\"externalConsole\": false,\n\t\"cwd\": \"${workspaceFolder}\"\n}\n```\n\nFinally, run the configuration from the \"Run and Debug\" VS Code tab.\n"
  },
  {
    "path": "Packaging/OpenDingux/rg99.desktop",
    "content": "[Desktop Entry]\nName=DevilutionX\nComment=Diablo 1 for RG99\nExec=devilutionx\nTerminal=false\nType=Application\nStartupNotify=true\nIcon=icon_32\nCategories=games;\nX-OD-Manual=readme.rg99.txt\nX-OD-NeedsDownscaling=true\n"
  },
  {
    "path": "Packaging/OpenDingux/targets.sh",
    "content": "declare -ra VALID_TARGETS=(\n  lepus\n  retrofw\n  rg99\n  rg350\n  gkd350h\n)\n\nusage_target() {\n  echo -n \"\ttarget: target platform:\"\n  printf \" %s\" \"${VALID_TARGETS[@]}\"\n  echo\n}\n\ncheck_target() {\n  if [[ $# -eq 0 ]] || [[ -z $1 ]]; then\n    echo \"Error: target is missing\"\n    return 1\n  fi\n\n  for target in \"${VALID_TARGETS[@]}\"; do\n    if [[ $target == $1 ]]; then\n      return 0\n    fi\n  done\n  echo \"Error: invalid target\"\n  return 1\n}\n"
  },
  {
    "path": "Packaging/amiga/Dockerfile",
    "content": "FROM amigadev/crosstools:m68k-amigaos-gcc10\n\nRUN apt-get update && apt-get install --no-install-recommends -y smpq\nRUN mkdir /devilutionx-deps-build\nCOPY Packaging/amiga/prep.sh /devilutionx-deps-build/prep.sh\nRUN cd /devilutionx-deps-build && ./prep.sh\n\nCMD cmake -S. -Bbuild-amiga -DCPACK=ON \\\n\t\t-DCMAKE_BUILD_TYPE=Release \\\n\t\t-DM68K_CPU=68040 \\\n\t\t-DM68K_FPU=hard \\\n\t\t-DM68K_COMMON=\"-s -fbbb=- -ffast-math\" && \\\n\tcmake --build build-amiga -j $(nproc)\n"
  },
  {
    "path": "Packaging/amiga/prep.sh",
    "content": "#!/usr/bin/env bash\n\n# exit when any command fails\nset -euo pipefail\n\n#set compiler params\nexport TARGET='m68k-amigaos'\nexport SYSROOT=/opt/$TARGET\nexport M68K_CPU=68040\nexport M68K_FPU=hard\nexport M68K_CPU_FPU=\"-m${M68K_CPU} -m${M68K_FPU}-float\"\nexport M68K_COMMON=\"-s -ffast-math -fomit-frame-pointer -fbbb=-\"\nexport M68K_CFLAGS=\"${M68K_CPU_FPU} ${M68K_COMMON}\"\nexport M68K_CXXFLAGS=\"${M68K_CPU_FPU} ${M68K_COMMON}\"\n\nPARALLELISM=\"$(getconf _NPROCESSORS_ONLN)\"\n\nmkdir -p deps\nmkdir -p ${SYSROOT}/usr/lib\nmkdir -p ${SYSROOT}/usr/include\ncd deps\n\n# SDL1.2\nwget https://github.com/AmigaPorts/libSDL12/archive/master.tar.gz -O SDL-1.2.tar.gz\ntar -xvf SDL-1.2.tar.gz\ncd libSDL12-master\nmake PREFX=${SYSROOT} PREF=${SYSROOT} -j\"$PARALLELISM\"\nmkdir -p ${SYSROOT}/usr/lib\nmkdir -p ${SYSROOT}/usr/include\ncp -fvr libSDL.a ${SYSROOT}/usr/lib/\ncp -fvr include/* ${SYSROOT}/usr/include/\ncd ..\n"
  },
  {
    "path": "Packaging/apple/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>English</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>\n\t<key>CFBundleGetInfoString</key>\n\t<string>${MACOSX_BUNDLE_INFO_STRING}</string>\n\t<key>CFBundleIconFile</key>\n\t<string>${MACOSX_BUNDLE_ICON_FILE}</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleLongVersionString</key>\n\t<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>\n\t<key>CFBundleName</key>\n\t<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>${MACOSX_BUNDLE_DISPLAY_NAME}</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>NSHighResolutionCapable</key>\n\t<true/>\n\t<key>CSResourcesFileMapped</key>\n\t<true/>\n\t<key>LSRequires${MACOSX_BUNDLE_REQUIRED_PLATFORM}</key>\n\t<true/>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>${MACOSX_BUNDLE_COPYRIGHT}</string>\n\t<key>SDL_FILESYSTEM_BASE_DIR_TYPE</key>\n\t<string>resource</string>\n\t<key>NSSupportsAutomaticGraphicsSwitching</key>\n\t<true/>\n\t<key>UIApplicationSupportsIndirectInputEvents</key>\n\t<true/>\n\t<key>LSSupportsOpeningDocumentsInPlace</key>\n\t<true/>\n\t<key>UIFileSharingEnabled</key>\n\t<true/>\n\t<key>CADisableMinimumFrameDurationOnPhone</key>\n\t<true/>\n\t<key>UIDeviceFamily</key>\n\t<array>\n\t\t<integer>1</integer>\n\t\t<integer>2</integer>\n\t</array>\n\t<key>UIRequiresFullScreen</key>\n\t<true/>\n\t<key>UIStatusBarHidden</key>\n\t<true/>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIApplicationSceneManifest</key>\n\t<dict>\n\t\t<key>UIApplicationSupportsMultipleScenes</key>\n\t\t<false/>\n\t</dict>\n\t<key>CFBundleAllowMixedLocalizations</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Packaging/apple/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"14460.31\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\" initialViewController=\"Y6W-OH-hqX\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"14460.20\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"s0d-6b-0kx\">\n            <objects>\n                <viewController id=\"Y6W-OH-hqX\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"5EZ-qb-Rvc\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                        <viewLayoutGuide key=\"safeArea\" id=\"eJ7-NN-0U7\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"Ief-a0-LHa\" userLabel=\"First Responder\" customClass=\"UIResponder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"19.419642857142858\" y=\"44.927536231884062\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Packaging/apple/png2icns_tiger/.gitignore",
    "content": "/build*/\n"
  },
  {
    "path": "Packaging/apple/png2icns_tiger/CMakeLists.txt",
    "content": "# On Debian/Ubuntu, this requires libpng-dev and libicns-dev\ncmake_minimum_required(VERSION 3.22)\nproject(png2icns_tiger LANGUAGES C)\nadd_executable(png2icns_tiger png2icns_tiger.c)\nfind_package(PkgConfig REQUIRED)\npkg_check_modules(PNG REQUIRED IMPORTED_TARGET libpng)\npkg_check_modules(ICNS REQUIRED IMPORTED_TARGET libicns)\ntarget_link_libraries(png2icns_tiger PRIVATE PkgConfig::PNG PkgConfig::ICNS)\n"
  },
  {
    "path": "Packaging/apple/png2icns_tiger/png2icns_tiger.c",
    "content": "/*\n * png2icns_tiger - based on png2icns from the pngutils Debian package but\n * modified for Tiger support. See the section that says MODIFICATION.\n *\n * Copyright (C) 2008 Julien BLACHE <jb@jblache.org>\n * Copyright (C) 2012 Mathew Eis <mathew@eisbox.net>\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 * You should have received a copy of the GNU General Public License along\n * with this program; if not, write to the Free Software Foundation, Inc.,\n * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include <errno.h>\n\n#include <icns.h>\n#include <png.h>\n#include <setjmp.h>\n\n#define FALSE 0\n#define TRUE 1\n\n#if PNG_LIBPNG_VER >= 10209\n#define PNG2ICNS_EXPAND_GRAY 1\n#endif\n\nstatic int read_png(FILE *fp, png_bytepp buffer, int32_t *bpp, int32_t *width,\n                    int32_t *height) {\n  png_structp png_ptr;\n  png_infop info;\n  png_uint_32 w;\n  png_uint_32 h;\n  png_bytep *rows;\n\n  int bit_depth;\n  int32_t color_type;\n\n  int row;\n  int rowsize;\n\n  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);\n  if (png_ptr == NULL)\n    return FALSE;\n\n  info = png_create_info_struct(png_ptr);\n  if (info == NULL) {\n    png_destroy_read_struct(&png_ptr, NULL, NULL);\n    return FALSE;\n  }\n\n  if (setjmp(png_jmpbuf(png_ptr))) {\n    png_destroy_read_struct(&png_ptr, &info, NULL);\n    return FALSE;\n  }\n\n  png_init_io(png_ptr, fp);\n\n  png_read_info(png_ptr, info);\n  png_get_IHDR(png_ptr, info, &w, &h, &bit_depth, &color_type, NULL, NULL,\n               NULL);\n\n  switch (color_type) {\n  case PNG_COLOR_TYPE_GRAY:\n#ifdef PNG2ICNS_EXPAND_GRAY\n    png_set_expand_gray_1_2_4_to_8(png_ptr);\n#else\n    png_set_gray_1_2_4_to_8(png_ptr);\n#endif\n\n    if (bit_depth == 16) {\n      png_set_strip_16(png_ptr);\n      bit_depth = 8;\n    }\n\n    png_set_gray_to_rgb(png_ptr);\n    png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);\n    break;\n\n  case PNG_COLOR_TYPE_GRAY_ALPHA:\n#ifdef PNG2ICNS_EXPAND_GRAY\n    png_set_expand_gray_1_2_4_to_8(png_ptr);\n#else\n    png_set_gray_1_2_4_to_8(png_ptr);\n#endif\n\n    if (bit_depth == 16) {\n      png_set_strip_16(png_ptr);\n      bit_depth = 8;\n    }\n\n    png_set_gray_to_rgb(png_ptr);\n    break;\n\n  case PNG_COLOR_TYPE_PALETTE:\n    png_set_palette_to_rgb(png_ptr);\n\n    if (png_get_valid(png_ptr, info, PNG_INFO_tRNS))\n      png_set_tRNS_to_alpha(png_ptr);\n    else\n      png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);\n    break;\n\n  case PNG_COLOR_TYPE_RGB:\n    if (bit_depth == 16) {\n      png_set_strip_16(png_ptr);\n      bit_depth = 8;\n    }\n\n    png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);\n    break;\n\n  case PNG_COLOR_TYPE_RGB_ALPHA:\n    if (bit_depth == 16) {\n      png_set_strip_16(png_ptr);\n      bit_depth = 8;\n    }\n\n    break;\n  }\n\n  *width = w;\n  *height = h;\n  *bpp = bit_depth * 4;\n\n  png_set_interlace_handling(png_ptr);\n\n  png_read_update_info(png_ptr, info);\n\n  rowsize = png_get_rowbytes(png_ptr, info);\n  rows = malloc(sizeof(png_bytep) * h);\n  *buffer = malloc(rowsize * h + 8);\n\n  rows[0] = *buffer;\n  for (row = 1; row < h; row++) {\n    rows[row] = rows[row - 1] + rowsize;\n  }\n\n  png_read_image(png_ptr, rows);\n  png_destroy_read_struct(&png_ptr, &info, NULL);\n\n  free(rows);\n\n  return TRUE;\n}\n\nstatic int add_png_to_family(icns_family_t **iconFamily, char *pngname) {\n  FILE *pngfile;\n\n  int icnsErr = ICNS_STATUS_OK;\n  icns_image_t icnsImage;\n  icns_image_t icnsMask;\n  icns_type_t iconType;\n  icns_type_t maskType;\n  icns_icon_info_t iconInfo;\n\n  icns_element_t *iconElement = NULL;\n  icns_element_t *maskElement = NULL;\n  char iconStr[5] = {0, 0, 0, 0, 0};\n  char maskStr[5] = {0, 0, 0, 0, 0};\n  int iconDataOffset = 0;\n  int maskDataOffset = 0;\n\n  png_bytep buffer;\n  int width, height, bpp;\n\n  pngfile = fopen(pngname, \"rb\");\n  if (pngfile == NULL) {\n    fprintf(stderr, \"Could not open '%s' for reading: %s\\n\", pngname,\n            strerror(errno));\n    return FALSE;\n  }\n\n  if (!read_png(pngfile, &buffer, &bpp, &width, &height)) {\n    fprintf(stderr, \"Failed to read PNG file\\n\");\n    fclose(pngfile);\n\n    return FALSE;\n  }\n\n  fclose(pngfile);\n\n  icnsImage.imageWidth = width;\n  icnsImage.imageHeight = height;\n  icnsImage.imageChannels = 4;\n  icnsImage.imagePixelDepth = 8;\n  icnsImage.imageDataSize = width * height * 4;\n  icnsImage.imageData = buffer;\n\n  iconInfo.isImage = 1;\n  iconInfo.iconWidth = icnsImage.imageWidth;\n  iconInfo.iconHeight = icnsImage.imageHeight;\n  iconInfo.iconBitDepth = bpp;\n  iconInfo.iconChannels = (bpp == 32 ? 4 : 1);\n  iconInfo.iconPixelDepth = bpp / iconInfo.iconChannels;\n\n  iconType = icns_get_type_from_image_info(iconInfo);\n  maskType = icns_get_mask_type_for_icon_type(iconType);\n\n  /* MODIFICATION */\n  if (iconType == ICNS_128x128_32BIT_ARGB_DATA) {\n    /* libicns returns \"ic07\" for 128x128 icons but that doesn't work on Tiger\n     */\n    iconType = ICNS_128X128_32BIT_DATA;\n    maskType = ICNS_128X128_8BIT_MASK;\n  }\n  /* END OF MODIFICATION */\n\n  icns_type_str(iconType, iconStr);\n  icns_type_str(maskType, maskStr);\n\n  /* Only convert the icons that match sizes icns supports */\n  if (iconType == ICNS_NULL_TYPE) {\n    fprintf(stderr, \"Bad dimensions: PNG file '%s' is %dx%d\\n\", pngname, width,\n            height);\n    free(buffer);\n\n    return FALSE;\n  }\n\n  if (bpp != 32) {\n    fprintf(stderr, \"Bit depth %d unsupported in '%s'\\n\", bpp, pngname);\n    free(buffer);\n\n    return FALSE;\n  }\n\n  icns_set_print_errors(0);\n  if (icns_get_element_from_family(*iconFamily, iconType, &iconElement) ==\n      ICNS_STATUS_OK) {\n    icns_set_print_errors(1);\n\n    fprintf(stderr, \"Duplicate icon element of type '%s' detected (%s)\\n\",\n            iconStr, pngname);\n    free(buffer);\n\n    return FALSE;\n  }\n\n  icns_set_print_errors(1);\n\n  if ((iconType != ICNS_1024x1024_32BIT_ARGB_DATA) &&\n      (iconType != ICNS_512x512_32BIT_ARGB_DATA) &&\n      (iconType != ICNS_256x256_32BIT_ARGB_DATA) &&\n      (iconType != ICNS_128x128_32BIT_ARGB_DATA)) {\n    printf(\"Using icns type '%s', mask '%s' for '%s'\\n\", iconStr, maskStr,\n           pngname);\n  } else {\n    printf(\"Using icns type '%s' (ARGB) for '%s'\\n\", iconStr, pngname);\n  }\n\n  icnsErr = icns_new_element_from_image(&icnsImage, iconType, &iconElement);\n\n  if (iconElement != NULL) {\n    if (icnsErr == ICNS_STATUS_OK) {\n      icns_set_element_in_family(iconFamily, iconElement);\n    }\n    free(iconElement);\n  }\n\n  if ((iconType != ICNS_1024x1024_32BIT_ARGB_DATA) &&\n      (iconType != ICNS_512x512_32BIT_ARGB_DATA) &&\n      (iconType != ICNS_256x256_32BIT_ARGB_DATA) &&\n      (iconType != ICNS_128x128_32BIT_ARGB_DATA)) {\n    icns_init_image_for_type(maskType, &icnsMask);\n\n    iconDataOffset = 0;\n    maskDataOffset = 0;\n\n    while ((iconDataOffset < icnsImage.imageDataSize) &&\n           (maskDataOffset < icnsMask.imageDataSize)) {\n      icnsMask.imageData[maskDataOffset] =\n          icnsImage.imageData[iconDataOffset + 3];\n      iconDataOffset += 4; /* move to the next alpha byte */\n      maskDataOffset += 1; /* move to the next byte */\n    }\n\n    icnsErr = icns_new_element_from_mask(&icnsMask, maskType, &maskElement);\n\n    if (maskElement != NULL) {\n      if (icnsErr == ICNS_STATUS_OK) {\n        icns_set_element_in_family(iconFamily, maskElement);\n      }\n      free(maskElement);\n    }\n\n    icns_free_image(&icnsMask);\n  }\n\n  free(buffer);\n\n  return TRUE;\n}\n\nint main(int argc, char **argv) {\n  FILE *icnsfile;\n\n  icns_family_t *iconFamily;\n\n  int i;\n\n  if (argc < 3) {\n    printf(\"Usage: png2icns file.icns file1.png file2.png ... filen.png\\n\");\n    exit(1);\n  }\n\n  icnsfile = fopen(argv[1], \"wb+\");\n  if (icnsfile == NULL) {\n    fprintf(stderr, \"Could not open '%s' for writing: %s\\n\", argv[1],\n            strerror(errno));\n    exit(1);\n  }\n\n  icns_set_print_errors(1);\n  icns_create_family(&iconFamily);\n\n  for (i = 2; i < argc; i++) {\n    if (!add_png_to_family(&iconFamily, argv[i])) {\n      fclose(icnsfile);\n      unlink(argv[1]);\n\n      exit(1);\n    }\n  }\n\n  if (icns_write_family_to_file(icnsfile, iconFamily) != ICNS_STATUS_OK) {\n    fprintf(stderr, \"Failed to write icns file\\n\");\n    fclose(icnsfile);\n\n    exit(1);\n  }\n\n  fclose(icnsfile);\n\n  printf(\"Saved icns file to %s\\n\", argv[1]);\n\n  if (iconFamily != NULL)\n    free(iconFamily);\n\n  return 0;\n}\n"
  },
  {
    "path": "Packaging/apple/png2icns_tiger/run.sh",
    "content": "#!/bin/bash\n\nset -euo pipefail\n\ndeclare -r INPUT=../../resources/icon.png\ndeclare -ra SIZES=(16 32 128)\ndeclare -r OUTPUT=../AppIcon_128.icns\n\ndeclare -rA DEPENDENCY_SOURCES=(\n  [convert]=imagemagick\n  [cmake]=cmake\n)\n\ncheck_deps() {\n  local -a missing_deps=()\n  local path\n  for dep in \"${!DEPENDENCIES[@]}\"; do\n    if path=\"$(which \"$dep\")\"; then\n      echo >&2 \"Using $dep from $path\"\n    else\n      missing_deps+=(\"$dep\")\n    fi\n  done\n  if (( ${#missing_deps[@]} )); then\n    echo >&2 \"Error: Missing dependencies\"\n    for dep in \"${missing_deps[@]}\"; do\n      echo >&2 '* '\"Please install \\\"${dep}\\\", provided by ${DEPENDENCY_SOURCES[$dep]} on Debian/Ubuntu\"\n    done\n    exit 1\n  fi\n}\n\nmain() {\n  cd \"$(dirname \"$0\")\"\n  check_deps\n\n  set -x\n  mkdir -p tmp\n  { set +x; } 2> /dev/null\n\n  local path\n  local -a FILES=()\n  for s in \"${SIZES[@]}\"; do\n    path=\"tmp/output_${s}.png\"\n    FILES+=(\"$path\")\n\n    set -x\n    convert \"$INPUT\" -resize \"${s}x${s}\" \"$path\"\n    { set +x; } 2> /dev/null\n  done\n\n  set -x\n  cmake -S. -Bbuild-rel -DCMAKE_BUILD_TYPE=Release\n  cmake --build build-rel\n  build-rel/png2icns_tiger \"$OUTPUT\" \"${FILES[@]}\"\n  rm -rf tmp\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "Packaging/cpi-gamesh/__init__.py",
    "content": "\nimport pygame\nimport validators\nimport  commands\nfrom UI.constants import Width,Height,ICON_TYPES,RUNSYS\nfrom UI.simple_name_space import SimpleNamespace\nfrom UI.page  import Page\nfrom UI.label  import Label\nfrom UI.icon_item import IconItem\nfrom UI.keys_def  import CurKeys, IsKeyMenuOrB, IsKeyStartOrA\nfrom UI.skin_manager import MySkinManager\nfrom UI.lang_manager import MyLangManager\n\nfrom libs.DBUS  import is_wifi_connected_now,get_wifi_ip\nfrom collections import deque\nfrom enum import Enum\nimport os\nimport subprocess\nimport pipes\n\nclass DevilutionPage(Page):\n\t_FootMsg = [\"Nav\",\"Check\",\"Upgrade\",\"Back\",\"Play\"]\n\n\t_GameName = \"devilutionX\"\n\t_GamePath = \"/home/cpi/games/devilutionX\"\n\t_GameExecutable = _GamePath + \"/build/devilutionx\"\n\t_GameExecutableRevision = _GameExecutable + \".rev\"\n\t_GameBuildScript = _GamePath + \"/Packaging/cpi-gamesh/build.sh -t \" + pipes.quote(os.path.dirname(os.path.abspath( __file__ )))\n\t_GamePNG = _GamePath + \"/Packaging/cpi-gamesh/Devilution.png\"\n\t_DevilutionDiabdatmpq = \"/home/cpi/.local/share/diasurgical/devilution/diabdat.mpq\"\n\t_DevilutionDiabdatmpqPresent = False\n\t_GameInstalled = False\n\n\t_CiteNewUpdate = \"Ahh... fresh meat!\"\n\t_CiteCheckUpdate = \"Lets search the books...\"\n\t_CiteWelcome = \"Well, what can I do for ya?\"\n\t_CiteCompiling = \"Stay awhile and listen.\"\n\t_CiteDone = \"You must venture through the portal...\"\n\t_CiteFailed = \"Game Over. Better luck next time!\"\n\n\t_GitURL = \"https://github.com/diasurgical/devilutionX.git\"\n\t_GitBranch = \"master\"\n\t_GitRevision = \"\"\n\n\t_GameIcon = None\n\n\t_Process = None\n\t_Labels = {}\n\t_Coords = {}\n\n\t_ListFontObj = MyLangManager.TrFont(\"varela13\")\n\t_URLColor  = MySkinManager.GiveColor('URL')\n\t_TextColor = MySkinManager.GiveColor('Text')\n\n\tdef __init__(self):\n\t\tPage.__init__(self)\n\n\tdef InitLabels(self):\n\n\t\ty = 15\n\t\tx = 11\n\t\tyInc = 19\n\t\txGitRefLabelWidth = 48\n\n\t\tlabels = \\\n\t\t\t[[\"greeting\",self._CiteWelcome, self._TextColor, x, y],\n\t\t\t [\"status\", \"\", self._URLColor, x, y + 72-yInc],\n\t\t\t [\"comment\", \"\", self._TextColor, x, y + 72],\n\t\t\t [\"console_out\",\"\",self._URLColor, x, y + 72 + yInc],\n\t\t\t [\"label_rev\",\"GIT Revisions: \", self._TextColor, x, 132],\n\t\t\t [\"label_git_rev\",\"Source: \", self._TextColor, x, 151],\n\t\t\t [\"content_git_rev\",\"\", self._URLColor, x + xGitRefLabelWidth, 151],\n\t\t\t [\"label_bin_rev\",\"Bin: \", self._TextColor, x, 170],\n\t\t\t [\"content_bin_rev\",\"\", self._URLColor, x + xGitRefLabelWidth, 170]\n\t\t\t]\n\n\t\tfor i in labels:\n\t\t\tl = Label()\n\t\t\tl.SetCanvasHWND(self._CanvasHWND)\n\t\t\tl.Init(i[1],self._ListFontObj)\n\t\t\tl.SetColor(i[2])\n\t\t\tself._Labels[ i[0] ] = l\n\n\t\t\tc = SimpleNamespace()\n\t\t\tc.x = i[3]\n\t\t\tc.y = i[4]\n\t\t\tself._Coords[ i[0] ] = c\n\n\tdef GitGetRevision(self):\n\t\tif not os.path.exists(self._GamePath):\n\t\t\treturn \"game not installed\"\n\t\tprocess = subprocess.Popen(\"cd \" + pipes.quote(self._GamePath) + \"; git rev-parse HEAD\",stdout=subprocess.PIPE,stderr=subprocess.STDOUT, shell=True)\n\t\tself._GitRevision = process.communicate()[0].strip()\n\t\tprocess.wait()\n\t\treturn self._GitRevision\n\n\tdef ExectuableGetRevision(self):\n\t\ttry:\n\t\t\twith open(self._GameExecutableRevision, 'r') as file:\n\t\t\t\texecutableRevsion = file.read().replace('\\n', '')\n\t\t\treturn executableRevsion\n\t\texcept:\n\t\t\treturn \"unknown\"\n\n\tdef InitGameDirectory(self):\n\t\ttry:\n\t\t\tos.makedirs(self._GamePath)\n\t\texcept:\n\t\t\tpass\n\t\tself.StartShellProcess(\"cd \" + pipes.quote(self._GamePath) + \"; git clone --single-branch --branch \" + pipes.quote(self._GitBranch) + \" \" + pipes.quote(self._GitURL) + \" .\")\n\n\tdef CheckDevilutionMPQ(self):\n\t\tself._DevilutionDiabdatmpqPresent = os.path.isfile(self._DevilutionDiabdatmpq)\n\n\tdef CheckGameInstalled(self):\n\t\tself._GameInstalled = os.path.isfile(self._GameExecutable)\n\n\tdef UpdateFootMsg(self):\n\t\tif not self._GameInstalled:\n\t\t\tself._FootMsg = [\"Nav\",\"\",\"Install\",\"Back\",\"\"]\n\t\t\tself.UpdateLabel(\"status\", \"GIT Upgrade\")\n\t\t\tself.UpdateLabel(\"comment\", \"Press X to install\")\n\t\telif not self._DevilutionDiabdatmpqPresent:\n\t\t\tself._FootMsg = [\"Nav\",\"\",\"Upgrade\",\"Back\",\"Re-check\"]\n\t\t\tself.UpdateLabel(\"status\", \"Gamefile diabdat.mpq missing\")\n\t\t\tself.UpdateLabel(\"comment\", \"see readme\")\n\t\telse:\n\t\t\tself._FootMsg = [\"Nav\",\"\",\"Upgrade\",\"Back\",\"Play\"]\n\t\t\tself.UpdateLabel(\"status\", \"Ready\")\n\t\t\tself.UpdateLabel(\"comment\", self._CiteDone)\n\n\tdef Init(self):\n\t\tPage.Init(self)\n\n\t\tif self._Screen != None:\n\t\t\tif self._Screen._CanvasHWND != None and self._CanvasHWND == None:\n\t\t\t\tself._HWND = self._Screen._CanvasHWND\n\t\t\t\tself._CanvasHWND = pygame.Surface( (self._Screen._Width,self._Screen._Height) )\n\n\t\tif os.path.isfile(self._GamePNG):\n\t\t\tself._GameIcon = IconItem()\n\t\t\tself._GameIcon._ImageName = self._GamePNG\n\t\t\tself._GameIcon._MyType = ICON_TYPES[\"STAT\"]\n\t\t\tself._GameIcon._Parent = self\n\t\t\tself._GameIcon.Adjust(290,70,128,128,0)\n\n\t\tself.InitLabels()\n\t\tself.CheckDevilutionMPQ()\n\t\tself.CheckGameInstalled()\n\t\tself.UpdateFootMsg()\n\n\t\tself.UpdateLabel(\"content_git_rev\", self.GitGetRevision(), 24)\n\t\tself.UpdateLabel(\"content_bin_rev\", self.ExectuableGetRevision(), 24)\n\n\tdef UpdateLabel(self, label, msg, maxLen=38):\n\t\tprint(label + \": \" + msg)\n\t\tif len(msg) > maxLen:\n\t\t\tm = msg[:maxLen] + \"...\"\n\t\telse:\n\t\t\tm = msg\n\t\tself._Labels[label].SetText(m)\n\n\tdef StartShellProcess(self, cmd):\n\t\tprint(\"StartShellProcess \" + cmd)\n\t\tproc = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT, shell=True)\n\t\twhile(True):\n\t\t\tline = proc.stdout.readline()\n\t\t\tif line:\n\t\t\t\tself.UpdateLabel(\"console_out\", line.strip(), 48)\n\t\t\t\tself._Screen.Draw()\n\t\t\t\tself._Screen.SwapAndShow()\n\t\t\tif line == '' and proc.poll() is not None:\n\t\t\t\tbreak\n\t\tself.UpdateLabel(\"console_out\", \"\")\n\t\tself._Screen.Draw()\n\t\tself._Screen.SwapAndShow()\n\n\tdef GitUpgrade(self):\n\t\tself.UpdateLabel(\"status\", \"GIT Upgrade\")\n\t\tself.UpdateLabel(\"comment\", self._CiteCheckUpdate)\n\n\t\tcurRev = \"unset\"\n\t\tif not os.path.exists(self._GamePath):\n\t\t\tself.InitGameDirectory()\n\t\telse:\n\t\t\tcurRev = self.GitGetRevision()\n\t\t\tself.StartShellProcess(\"cd \" + pipes.quote(self._GamePath) + \"; git pull\")\n\t\t\n\t\tself._GitRevision = self.GitGetRevision()\n\t\tself.UpdateLabel(\"content_git_rev\", self._GitRevision, 24)\n\n\t\tif curRev != self._GitRevision:\n\t\t\tself.UpdateLabel(\"comment\", self._CiteNewUpdate)\n\t\telse:\n\t\t\tself.UpdateLabel(\"comment\", self._CiteDone)\n\n\t\tself._Screen.Draw()\n\t\tself._Screen.SwapAndShow()\n\n\tdef GitExectuableIsGitRevision(self):\n\t\treturn self.GitGetRevision() == self.ExectuableGetRevision()\n\n\tdef Build(self):\n\t\tself.UpdateLabel(\"status\", \"Building\")\n\t\tself.StartShellProcess(self._GameBuildScript)\n\n\tdef UpgradeAndBuild(self):\n\t\tself.GitUpgrade()\n\t\tself.UpdateLabel(\"comment\", self._CiteCompiling)\n\t\tself._Screen.Draw()\n\t\tself._Screen.SwapAndShow()\n\t\tif not self.GitExectuableIsGitRevision():\n\t\t\tself.Build()\n\n\t\tself.UpdateLabel(\"content_git_rev\", self.GitGetRevision(), 24)\n\t\tself.UpdateLabel(\"content_bin_rev\", self.ExectuableGetRevision(), 24)\n\n\t\tself.UpdateLabel(\"status\", \"Done\")\n\t\tif self.GitExectuableIsGitRevision():\n\t\t\tself.UpdateLabel(\"comment\", self._CiteDone)\n\t\telse:\n\t\t\tself.UpdateLabel(\"comment\", self._CiteFailed)\n\n\t\tself.CheckDevilutionMPQ()\n\t\tself.CheckGameInstalled()\n\t\tself.UpdateFootMsg()\n\t\t\n\t\tself._Screen.Draw()\n\t\tself._Screen.SwapAndShow()\n\n\tdef KeyDown(self,event):\n\n\t\tif IsKeyMenuOrB(event.key):\n\t\t\tself.ReturnToUpLevelPage()\n\t\t\tself._Screen.Draw()\n\t\t\tself._Screen.SwapAndShow()\n\n\t\tif self._DevilutionDiabdatmpqPresent and self._GameInstalled:\n\t\t\tif IsKeyStartOrA(event.key):\n\t\t\t\tpygame.event.post( pygame.event.Event(RUNSYS, message=self._GameExecutable))\n\t\t\tif event.key == CurKeys[\"X\"]:\n\t\t\t\tself.UpgradeAndBuild()\n\t\telif not self._GameInstalled:\n\t\t\tif event.key == CurKeys[\"X\"]:\n\t\t\t\tself.UpgradeAndBuild()\n\t\telif not self._DevilutionDiabdatmpqPresent:\n\t\t\tif IsKeyStartOrA(event.key):\n\t\t\t\tself.CheckDevilutionMPQ()\n\t\t\t\tself.CheckGameInstalled()\n\t\t\t\tself.UpdateFootMsg()\n\t\t\t\tself._Screen.Draw()\n\t\t\t\tself._Screen.SwapAndShow()\n\n\tdef Draw(self):\n\t\tself.ClearCanvas()\n\n\t\tif self._GameIcon != None:\n\t\t\tself._GameIcon.Draw()\n\n\t\tfor i in self._Labels:\n\t\t\tif i in self._Coords:\n\t\t\t\tself._Labels[i].NewCoord( self._Coords[i].x, self._Coords[i].y)\n\t\t\t\tself._Labels[i].Draw()\n\t\t\t\n\t\tif self._HWND != None:\n\t\t\tself._HWND.fill(MySkinManager.GiveColor('White'))\n\t\t\tself._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )\n\n\t\t\nclass APIOBJ(object):\n\n\t_Page = None\n\tdef __init__(self):\n\t\tpass\n\tdef Init(self,main_screen):\n\t\tself._Page = DevilutionPage()\n\t\tself._Page._Screen = main_screen\n\t\tself._Page._Name =\"devilutionX\"\n\t\tself._Page.Init()\n\t\t\n\tdef API(self,main_screen):\n\t\tif main_screen !=None:\n\t\t\tmain_screen.PushPage(self._Page)\n\t\t\tmain_screen.Draw()\n\t\t\tmain_screen.SwapAndShow()\n\nOBJ = APIOBJ()\ndef Init(main_screen):    \n\tOBJ.Init(main_screen)\ndef API(main_screen):\n\tOBJ.API(main_screen)\n"
  },
  {
    "path": "Packaging/cpi-gamesh/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\necho \"Building for target: clockwork pi GameSH\"\n\ndeclare -r DIR=\"$(dirname \"${BASH_SOURCE[0]}\")\"\ncd \"$DIR\"\ndeclare -r ABSDIR=\"$(pwd)\"\n\nusage() {\n\techo \"${BASH_SOURCE[0]} [--target /path/to/devliution/in/gameshell/menu] [--usage]\"\n\texit 1\n}\n\nPOSITIONAL=()\nwhile [[ $# -gt 0 ]]\ndo\nkey=\"$1\"\n\ncase $key in\n    -t|--target)\n    TARGET=\"$2\"\n    shift # past argument\n    shift # past value\n    ;;\n    --help|-h|--usage|-u)\n    usage\n    shift # past argument\n    ;;\n    *)    # unknown option\n    POSITIONAL+=(\"$1\") # save it in an array for later\n    shift # past argument\n    ;;\nesac\ndone\nset -- \"${POSITIONAL[@]}\" # restore positional parameters\n\ninstall_deps() {\n\tsudo apt install -y cmake libsdl2-dev libbz2-dev libsodium-dev\n}\n\nmain() {\n\tinstall_deps\n\tbuild\n\tinstall\n}\n\nbuild() {\n\tcd ../..\n\trm -f CMakeCache.txt\n\n\tcmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DTARGET_PLATFORM=cpigamesh -DDISABLE_LTO=ON\n\tcmake --build build -j $(getconf _NPROCESSORS_ONLN)\n\tcd -\n}\n\ninstall() {\n\tgit rev-parse HEAD > /home/cpi/games/devilutionX/build/devilutionx.rev\n\n\tif [ -z ${TARGET+x} ]; then\n\t\tlocal target_dir=\"25_devilutionX\"\n\telse\n\t\tlocal target_dir=${TARGET#\"/home/cpi/apps/Menu/\"}\n\tfi\n\n\tlocal script_dir=\"/home/cpi/apps/Menu/$target_dir\"\n\n\tlocal target_dir_base=`basename \"$target_dir\"`\n\tlocal target_dir_dir=`dirname \"$target_dir\"`\n\tlocal icon_name=\"${target_dir_dir}/${target_dir_base#*_}\"\n\n\tlocal icon_dir=\"/home/cpi/launcher/skin/default/Menu/GameShell/${icon_name}.png\"\n\n\techo $target_dir\n\techo $script_dir\n\techo $target_dir_base\n\techo $target_dir_dir\n\techo $icon_name\n\techo $icon_dir\n\n\tmkdir -p $script_dir\n\tcp __init__.py $script_dir\n\tcp Devilution.png $icon_dir\n}\n\nmain\n"
  },
  {
    "path": "Packaging/cpi-gamesh/readme.md",
    "content": "\n# devilutionX package for ClockworkPi GameShell\nFor more information about this device see [here](https://www.clockworkpi.com/gameshell).\n\n## Install devilutionX on the CPi GameShell\n\nTo install devilutionX, just copy the [\\_\\_init__.py](__init__.py) to a newly created folder under /home/cpi/apps/Menu and run it from the menu. The folder then symbolizes the devilutionX icon.\nFrom this menu, you can press 'X' to clone the git repository for devilutionX and compile the code. Dependencies are installed automatically (cmake and SDL development packages).\nOnce installed, 'X' pulls the updated code and does the compiling. Note that any changes made locally to the source are reverted before pulling.\n\nWhen the compile is finished and the diabdat.mpq is in place at '/home/cpi/.local/share/diasurgical/devilution/', you can play the game.\n - To run the Diablo: Hellfire expansion you will need to also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq.\n - For Chinese, Japanese, and Korean text support download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq and add it to the game folder.\n - For the Polish voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq.\nEnjoy!\n\nFor ClockworkOS v0.5, buster-backports are required to have updated libraries: https://backports.debian.org/Instructions/\n\n## Play devilutionX on the CPi GameShell\n\nWhen the game is compiled and the mpq files are in place, you can press \"A\" in the devilutionX menu to play.\n\nThe following key mapping is in place.\nUnfortunately, the mapping is not trivial as devilutionX and GameShell use their own not(yet) compatible shift mechanism.\nThe mapping is based on the standard GameShell keyboard layout, devilutionX uses the Nintento mapping.\n\n| GameShell Key                | Keyboard Key            | devilutionX Key            | devilutionX Action |\n| ---------------------     | ---------------         | ------------------------- | ------------------ |\n| D-Pad                        | Arrows                  | D-Pad                        | move hero |\n| Select + D-Pad            | Space + Arrows          | Back + D-Pad                | simulate mouse |\n| B                            | K                       | A                            | attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu |\n| A                            | J                       | B                            | select spell, back while in menus |\n| Y                            | I                       | X                            | pickup items, open nearby chests and doors, use item in the inventory |\n| X                            | U                       | Y                            | cast spell, delete character while in main menu |\n| Select                    | Space                   | Select                    | Select |\n| Start                        | Enter                   | Start                        | game menu, skip movie |\n| LK1                        | H                       | L1                        | use health item from belt  |\n| Start + Left        | Enter + Left      | Start + Left            | character sheet |\n| Start + Right        | Enter + Right     | Start + Right        | inventory |\n| LK5                        | L                       | R1                        | use mana item from belt |\n| Start + Down                | Enter + Down              | Start + Down                | automap |\n| Select + LK1                | Space + H                  | Select + L1                | left mouse click |\n| Start + X    | Enter + U    | Start + Y    | quest log |\n| Start + A    | Enter + J    | Start + B    | spell book |\n| Select + LK5                | Space + L                  | Select + R1                | right mouse click |\n| Select + A/B/X/Y            | Space + J/K/U/I         | Select + A/B/X/Y            | hot spell |\n"
  },
  {
    "path": "Packaging/ctr/template.rsf",
    "content": "BasicInfo:\n  Title                   : DevilutionX\n  ProductCode             : CTR-P-DIABLO\n  Logo                    : Homebrew # Nintendo / Licensed / Distributed / iQue / iQueForSystem\n\nRomFs:\n  # Specifies the root path of the read only file system to include in the ROM.\n  RootPath                : romfs\n\nTitleInfo:\n  Category                : Application\n  UniqueId                : 0x3F395\n\nOption:\n  UseOnSD                 : true # true if App is to be installed to SD\n  FreeProductCode         : true # Removes limitations on ProductCode\n  MediaFootPadding        : false # If true CCI files are created with padding\n  EnableCrypt             : false # Enables encryption for NCCH and CIA\n  EnableCompress          : true # Compresses where applicable (currently only exefs:/.code)\n  \nAccessControlInfo:\n  CoreVersion                   : 2\n\n  # Exheader Format Version\n  DescVersion                   : 2\n  \n  # Minimum Required Kernel Version (below is for 4.5.0)\n  ReleaseKernelMajor            : \"02\"\n  ReleaseKernelMinor            : \"33\" \n\n  # ExtData\n  UseExtSaveData                : false # enables ExtData       \n  #ExtSaveDataId                : 0x300 # only set this when the ID is different to the UniqueId\n\n  # FS:USER Archive Access Permissions\n  # Uncomment as required\n  FileSystemAccess:\n   #- CategorySystemApplication\n   #- CategoryHardwareCheck\n   - CategoryFileSystemTool\n   #- Debug\n   #- TwlCardBackup\n   #- TwlNandData\n   #- Boss\n   - DirectSdmc\n   #- Core\n   #- CtrNandRo\n   #- CtrNandRw\n   #- CtrNandRoWrite\n   #- CategorySystemSettings\n   #- CardBoard\n   #- ExportImportIvs\n   #- DirectSdmcWrite\n   #- SwitchCleanup\n   #- SaveDataMove\n   #- Shop\n   #- Shell\n   #- CategoryHomeMenu\n\n  # Process Settings\n  MemoryType                    : Application # Application/System/Base\n  SystemMode                    : 80MB # 64MB(Default)/96MB/80MB/72MB/32MB\n  IdealProcessor                : 0\n  AffinityMask                  : 1\n  Priority                      : 16\n  MaxCpu                        : 0x9E # Default\n  HandleTableSize               : 0x200\n  DisableDebug                  : false\n  EnableForceDebug              : false\n  CanWriteSharedPage            : true\n  CanUsePrivilegedPriority      : false\n  CanUseNonAlphabetAndNumber    : true\n  PermitMainFunctionArgument    : true\n  CanShareDeviceMemory          : true\n  RunnableOnSleep               : false\n  SpecialMemoryArrange          : true\n\n  # New3DS Exclusive Process Settings\n  SystemModeExt                 : 124MB # Legacy(Default)/124MB/178MB  Legacy:Use Old3DS SystemMode\n  CpuSpeed                      : 804MHz # 256MHz(Default)/804MHz\n  EnableL2Cache                 : true # false(default)/true\n  CanAccessCore2                : true \n\n  # Virtual Address Mappings\n  IORegisterMapping:\n   - 1ff00000-1ff7ffff   # DSP memory\n  MemoryMapping: \n   - 1f000000-1f5fffff:r # VRAM\n\n  # Accessible SVCs, <Name>:<ID>\n  SystemCallAccess: \n    ArbitrateAddress: 34\n    Backdoor: 123\n    Break: 60\n    CancelTimer: 28\n    ClearEvent: 25\n    ClearTimer: 29\n    CloseHandle: 35\n    ConnectToPort: 45\n    ControlMemory: 1\n    ControlProcessMemory: 112\n    CreateAddressArbiter: 33\n    CreateEvent: 23\n    CreateMemoryBlock: 30\n    CreateMutex: 19\n    CreateSemaphore: 21\n    CreateThread: 8\n    CreateTimer: 26\n    DuplicateHandle: 39\n    ExitProcess: 3\n    ExitThread: 9\n    GetCurrentProcessorNumber: 17\n    GetHandleInfo: 41\n    GetProcessId: 53\n    GetProcessIdOfThread: 54\n    GetProcessIdealProcessor: 6\n    GetProcessInfo: 43\n    GetResourceLimit: 56\n    GetResourceLimitCurrentValues: 58\n    GetResourceLimitLimitValues: 57\n    GetSystemInfo: 42\n    GetSystemTick: 40\n    GetThreadContext: 59\n    GetThreadId: 55\n    GetThreadIdealProcessor: 15\n    GetThreadInfo: 44\n    GetThreadPriority: 11\n    MapMemoryBlock: 31\n    OutputDebugString: 61\n    QueryMemory: 2\n    ReleaseMutex: 20\n    ReleaseSemaphore: 22\n    SendSyncRequest1: 46\n    SendSyncRequest2: 47\n    SendSyncRequest3: 48\n    SendSyncRequest4: 49\n    SendSyncRequest: 50\n    SetThreadPriority: 12\n    SetTimer: 27\n    SignalEvent: 24\n    SleepThread: 10\n    UnmapMemoryBlock: 32\n    WaitSynchronization1: 36\n    WaitSynchronizationN: 37\n\n  # Service List\n  # Maximum 34 services (32 if firmware is prior to 9.6.0)\n  ServiceAccessControl:\n   - APT:U\n   - ac:u\n   - am:net\n   - boss:U\n   - cam:u\n   - cecd:u\n   - cfg:nor\n   - cfg:u\n   - csnd:SND\n   - dsp::DSP\n   - frd:u\n   - fs:USER\n   - gsp::Gpu\n   - hid:USER\n   - http:C\n   - ir:rst\n   - ir:u\n   - ir:USER\n   - mic:u\n   - ndm:u\n   - news:u\n   - nwm::UDS\n   - ptm:u\n   - pxi:dev\n   - soc:U\n   - ssl:C\n   - y2r:u\n\n\nSystemControlInfo:\n  SaveDataSize: 0KB # Change if the app uses savedata\n  RemasterVersion: 2\n  StackSize: 0x40000\n\n  # Modules that run services listed above should be included below\n  # Maximum 48 dependencies\n  # <module name>:<module titleid>\n  Dependency: \n    ac: 0x0004013000002402\n    act: 0x0004013000003802\n    am: 0x0004013000001502\n    boss: 0x0004013000003402\n    camera: 0x0004013000001602\n    cecd: 0x0004013000002602\n    cfg: 0x0004013000001702\n    codec: 0x0004013000001802\n    csnd: 0x0004013000002702\n    dlp: 0x0004013000002802\n    dsp: 0x0004013000001a02\n    friends: 0x0004013000003202\n    gpio: 0x0004013000001b02\n    gsp: 0x0004013000001c02\n    hid: 0x0004013000001d02\n    http: 0x0004013000002902\n    i2c: 0x0004013000001e02\n    ir: 0x0004013000003302\n    mcu: 0x0004013000001f02\n    mic: 0x0004013000002002\n    ndm: 0x0004013000002b02\n    news: 0x0004013000003502\n    nfc: 0x0004013000004002\n    nim: 0x0004013000002c02\n    nwm: 0x0004013000002d02\n    pdn: 0x0004013000002102\n    ps: 0x0004013000003102\n    ptm: 0x0004013000002202\n    qtm: 0x0004013020004202\n    ro: 0x0004013000003702\n    socket: 0x0004013000002e02\n    spi: 0x0004013000002302\n    ssl: 0x0004013000002f02\n"
  },
  {
    "path": "Packaging/emscripten/index.html",
    "content": "<!DOCTYPE html>\r\n<html>\r\n\r\n<head>\r\n\t<meta charset=\"utf-8\">\r\n\t<title>DevilutionX</title>\r\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n\t<style>\r\n\t\tbody {\r\n\t\t\tfont-family: arial;\r\n\t\t\tmargin: 0;\r\n\t\t\tpadding: none;\r\n\t\t}\r\n\r\n\t\t.emscripten {\r\n\t\t\tpadding-right: 0;\r\n\t\t\tmargin-left: auto;\r\n\t\t\tmargin-right: auto;\r\n\t\t\tdisplay: block;\r\n\t\t}\r\n\r\n\t\tdiv.emscripten {\r\n\t\t\ttext-align: center;\r\n\t\t}\r\n\r\n\t\tdiv.emscripten_border {\r\n\t\t\tborder: 1px solid black;\r\n\t\t}\r\n\r\n\t\t/* the canvas *must not* have any border or padding, or mouse coords will be wrong */\r\n\t\tcanvas.emscripten {\r\n\t\t\tborder: 0px none;\r\n\t\t\tbackground-color: black;\r\n\t\t}\r\n\r\n\t\t#emscripten_logo {\r\n\t\t\tdisplay: inline-block;\r\n\t\t\tmargin: 0;\r\n\t\t}\r\n\r\n\t\t.spinner {\r\n\t\t\theight: 30px;\r\n\t\t\twidth: 30px;\r\n\t\t\tmargin: 0;\r\n\t\t\tmargin-top: 20px;\r\n\t\t\tmargin-left: 20px;\r\n\t\t\tdisplay: inline-block;\r\n\t\t\tvertical-align: top;\r\n\r\n\t\t\t-webkit-animation: rotation .8s linear infinite;\r\n\t\t\t-moz-animation: rotation .8s linear infinite;\r\n\t\t\t-o-animation: rotation .8s linear infinite;\r\n\t\t\tanimation: rotation 0.8s linear infinite;\r\n\r\n\t\t\tborder-left: 5px solid rgb(235, 235, 235);\r\n\t\t\tborder-right: 5px solid rgb(235, 235, 235);\r\n\t\t\tborder-bottom: 5px solid rgb(235, 235, 235);\r\n\t\t\tborder-top: 5px solid rgb(120, 120, 120);\r\n\r\n\t\t\tborder-radius: 100%;\r\n\t\t\tbackground-color: rgb(189, 215, 46);\r\n\t\t}\r\n\r\n\t\t@-webkit-keyframes rotation {\r\n\t\t\tfrom {\r\n\t\t\t\t-webkit-transform: rotate(0deg);\r\n\t\t\t}\r\n\r\n\t\t\tto {\r\n\t\t\t\t-webkit-transform: rotate(360deg);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@-moz-keyframes rotation {\r\n\t\t\tfrom {\r\n\t\t\t\t-moz-transform: rotate(0deg);\r\n\t\t\t}\r\n\r\n\t\t\tto {\r\n\t\t\t\t-moz-transform: rotate(360deg);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@-o-keyframes rotation {\r\n\t\t\tfrom {\r\n\t\t\t\t-o-transform: rotate(0deg);\r\n\t\t\t}\r\n\r\n\t\t\tto {\r\n\t\t\t\t-o-transform: rotate(360deg);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@keyframes rotation {\r\n\t\t\tfrom {\r\n\t\t\t\ttransform: rotate(0deg);\r\n\t\t\t}\r\n\r\n\t\t\tto {\r\n\t\t\t\ttransform: rotate(360deg);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t#status {\r\n\t\t\tdisplay: inline-block;\r\n\t\t\tvertical-align: top;\r\n\t\t\tmargin-top: 30px;\r\n\t\t\tmargin-left: 20px;\r\n\t\t\tfont-weight: bold;\r\n\t\t\tcolor: rgb(120, 120, 120);\r\n\t\t}\r\n\r\n\t\t#progress {\r\n\t\t\theight: 20px;\r\n\t\t\twidth: 300px;\r\n\t\t}\r\n\r\n\t\t#controls {\r\n\t\t\tdisplay: inline-block;\r\n\t\t\tfloat: right;\r\n\t\t\tvertical-align: top;\r\n\t\t\tmargin-top: 30px;\r\n\t\t\tmargin-right: 20px;\r\n\t\t}\r\n\r\n\t\t#output {\r\n\t\t\twidth: 100%;\r\n\t\t\theight: 200px;\r\n\t\t\tmargin: 0 auto;\r\n\t\t\tmargin-top: 10px;\r\n\t\t\tborder-left: 0px;\r\n\t\t\tborder-right: 0px;\r\n\t\t\tpadding-left: 0px;\r\n\t\t\tpadding-right: 0px;\r\n\t\t\tdisplay: block;\r\n\t\t\tbackground-color: black;\r\n\t\t\tcolor: white;\r\n\t\t\tfont-family: 'Lucida Console', Monaco, monospace;\r\n\t\t\toutline: none;\r\n\t\t}\r\n\t</style>\r\n</head>\r\n\r\n<body>\r\n\t<div class=\"spinner\" id='spinner'></div>\r\n\t<div class=\"emscripten\" id=\"status\">Downloading...</div>\r\n\r\n\t<div class=\"emscripten\">\r\n\t\t<progress value=\"0\" max=\"100\" id=\"progress\" hidden=1></progress>\r\n\t</div>\r\n\r\n\t<div class=\"emscripten_border\">\r\n\t\t<canvas class=\"emscripten\" id=\"canvas\" oncontextmenu=\"event.preventDefault()\" tabindex=-1></canvas>\r\n\t</div>\r\n\t<textarea id=\"output\" rows=\"8\"></textarea>\r\n\r\n\t<script type='text/javascript'>\r\n\t\tvar statusElement = document.getElementById('status');\r\n\t\tvar progressElement = document.getElementById('progress');\r\n\t\tvar spinnerElement = document.getElementById('spinner');\r\n\r\n\t\tvar Module = {\r\n\t\t\tpreRun: [],\r\n\t\t\tpostRun: [],\r\n\t\t\tprint: (function () {\r\n\t\t\t\tvar element = document.getElementById('output');\r\n\t\t\t\tif (element) element.value = ''; // clear browser cache\r\n\t\t\t\treturn function (text) {\r\n\t\t\t\t\tif (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');\r\n\t\t\t\t\tconsole.log(text);\r\n\t\t\t\t\tif (element) {\r\n\t\t\t\t\t\telement.value += text + \"\\n\";\r\n\t\t\t\t\t\telement.scrollTop = element.scrollHeight; // focus on bottom\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t})(),\r\n\t\t\tcanvas: (function () {\r\n\t\t\t\tvar canvas = document.getElementById('canvas');\r\n\r\n\t\t\t\t// As a default initial behavior, pop up an alert when webgl context is lost. To make your\r\n\t\t\t\t// application robust, you may want to override this behavior before shipping!\r\n\t\t\t\t// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2\r\n\t\t\t\tcanvas.addEventListener(\"webglcontextlost\", function (e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);\r\n\r\n\t\t\t\treturn canvas;\r\n\t\t\t})(),\r\n\t\t\tsetStatus: function (text) {\r\n\t\t\t\tif (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };\r\n\t\t\t\tif (text === Module.setStatus.last.text) return;\r\n\t\t\t\tvar m = text.match(/([^(]+)\\((\\d+(\\.\\d+)?)\\/(\\d+)\\)/);\r\n\t\t\t\tvar now = Date.now();\r\n\t\t\t\tif (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon\r\n\t\t\t\tModule.setStatus.last.time = now;\r\n\t\t\t\tModule.setStatus.last.text = text;\r\n\t\t\t\tif (m) {\r\n\t\t\t\t\ttext = m[1];\r\n\t\t\t\t\tprogressElement.value = parseInt(m[2]) * 100;\r\n\t\t\t\t\tprogressElement.max = parseInt(m[4]) * 100;\r\n\t\t\t\t\tprogressElement.hidden = false;\r\n\t\t\t\t\tspinnerElement.hidden = false;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tprogressElement.value = null;\r\n\t\t\t\t\tprogressElement.max = null;\r\n\t\t\t\t\tprogressElement.hidden = true;\r\n\t\t\t\t\tif (!text) spinnerElement.style.display = 'none';\r\n\t\t\t\t}\r\n\t\t\t\tstatusElement.innerHTML = text;\r\n\t\t\t},\r\n\t\t\ttotalDependencies: 0,\r\n\t\t\tmonitorRunDependencies: function (left) {\r\n\t\t\t\tthis.totalDependencies = Math.max(this.totalDependencies, left);\r\n\t\t\t\tModule.setStatus(left ? 'Preparing... (' + (this.totalDependencies - left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');\r\n\t\t\t}\r\n\t\t};\r\n\t\tModule.setStatus('Downloading...');\r\n\t\twindow.onerror = function (event) {\r\n\t\t\t// TODO: do not warn on ok events like simulating an infinite loop or exitStatus\r\n\t\t\tModule.setStatus('Exception thrown, see JavaScript console');\r\n\t\t\tspinnerElement.style.display = 'none';\r\n\t\t\tModule.setStatus = function (text) {\r\n\t\t\t\tif (text) Module.printErr('[post-exception status] ' + text);\r\n\t\t\t};\r\n\t\t};\r\n\t</script>\r\n\t<script async type=\"text/javascript\" src=\"devilutionx.js\"></script>\r\n</body>\r\n\r\n</html>\r\n"
  },
  {
    "path": "Packaging/haiku/devilutionX.rdef.in",
    "content": "/*\n * Resources for Haiku\n */\n\nresource app_flags B_SINGLE_LAUNCH;\n\nresource app_version {\n       major  = @MAJOR@,\n       middle = @MIDDLE@,\n       minor  = @MINOR@,\n\n       variety = B_APPV_FINAL,\n       internal = 0,\n\n       short_info = \"devilutionX\",\n       long_info = \"Diablo build for modern operating systems\"\n};\n\nresource app_signature \"application/x-vnd.diasurgical-devilutionX\";\n\nresource vector_icon {\n\t$\"6E6369660A050004016C03400000020106023EF000000000000000401800477F\"\n\t$\"FF49200000FD5252FFFF0606038E020202000602381D74BA3DDC3CAC7E3A85D7\"\n\t$\"474E1B48C45A00FFFFFFFFFF29290381030303EB3939020106023E1000000000\"\n\t$\"0000003E300048600043000000FF7C7CFFCD0505037103030E0204C282C38EC2\"\n\t$\"82C38ECB18CA6ECA21C0BABF67B9BDCA21C0BACA0CC181CA0CC181C0A3BAD1C2\"\n\t$\"75C495CC5CCB38C275C4950204C282C38EC282C38ECB18CA6ECA21C0BABF67B9\"\n\t$\"BDCA21C0BACA0CC181CA0CC181C0A3BAD1C275C495CC5CCB38C275C4950607FE\"\n\t$\"1BBE7CCC84C21ACC84C04BCC84C3E9CC84C76FCB79C5CACB6ACB30CB9CCA5FC9\"\n\t$\"08CCAEC9C1C8FDC899C61FC7E7C72AC8A0C4CBC6FAC21AC6BAC9420A0DB8B2BB\"\n\t$\"E0B8B2C206BA25C379BA25C99FBB97CA58BC50CA58BCADCAE3BE7CCBCAC160C8\"\n\t$\"E6C160C4EBC2D3C379C2D339BBF4B9B50A0BB8B2BBE0B8B2C206BA25C379BA25\"\n\t$\"C99FBB97CA58BC50CA58BCADCAE3BE7CCBCABE7CC5A4BFEEC5A4BFEEBF220A06\"\n\t$\"B8B2BBE0BFEEBF22C2D339BDC3BC9ABFEDBB83BBF4B9B50A08BFEEC5A4BE7CC5\"\n\t$\"A4BE7CCBCAC160C8E6C160C4EBC2D3C379C2D339BFEEBF220A04BE7CC5A4BE7C\"\n\t$\"C7D0C160C4EBBFEEC5A40A03BDC3BC9AC2D339BFEEBB84020ABDC3B617BE1FB6\"\n\t$\"17BD66B617BCB3B657BD09B62EBC5CB67FBB13B48ABB59B444BACEB4CFBB1EB7\"\n\t$\"ECBB46B795BAF5B843BADEB8FCBADEB89FBADEBA6EBDC3BBE0BC50BBE0BF35BB\"\n\t$\"E0C0A7B8FCC0A7BA6EC0A7B89FC068B7ECC090B843C03FB795C144B51CC189B5\"\n\t$\"62C0FEB4D7BED3B657BF29B67FBE7CB62E0A04BB97CA58BC50CA58BC50C548BB\"\n\t$\"97C4EB0805C906C096C8B3C141CAECC2ACCA3FBF61C93EC06C0805C906C096C8\"\n\t$\"B3C141CAECC2ACCA3FBF61C93EC06C020ABDC3B617BE1FB617BD66B617BCB3B6\"\n\t$\"57BD09B62EBC5CB67FBB09B475BB4EB42FBAC3B4BABB1EB7ECBB46B795BAF5B8\"\n\t$\"43BADEB8FCBADEB89FBADEBA6EBDC3BBE0BC50BBE0BF35BBE0C0A7B8FCC0A7BA\"\n\t$\"6EC0A7B89FC068B7ECC090B843C03FB79544B512C19EB557C113B4CDBED3B657\"\n\t$\"BF29B67FBE7CB62E0E0A070100000A0001011001178100040A010102000A0001\"\n\t$\"031001178300040A030104000A050105000A040106000A020107000A09010800\"\n\t$\"0A0001091001178300040A06010A000A07010B000A00010C1001178100040A08\"\n\t$\"010D00\"\n};\n"
  },
  {
    "path": "Packaging/miyoo_mini/build.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\ndeclare -r PACKAGING_DIR=`cd -- \"$(dirname \"$0\")\" >/dev/null 2>&1; pwd -P`\ndeclare -r CFLAGS=\"-O3 -marm -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7ve -Wall\"\ndeclare -r LDFLAGS=\"-lSDL -lmi_sys -lmi_gfx -s -lSDL -lSDL_image\"\ndeclare -r BUILD_DIR=\"build-miyoo-mini\"\ndeclare -r MIYOO_CUSTOM_SDL_REPO=\"https://github.com/Brocky/SDL-1.2-miyoo-mini.git\"\ndeclare -r MIYOO_CUSTOM_SDL_BRANCH=\"miniui-miyoomini\"\n\nmain() {\n\t# ensure we are in devilutionx root\n\tcd \"$PACKAGING_DIR/../..\"\n\n\trm -f \"$BUILD_DIR/CMakeCache.txt\"\n\tcmake_configure -DCMAKE_BUILD_TYPE=Release\n\tcmake_build\n\tpackage_onion\n\tpackage_miniui\n}\n\ncmake_configure() {\n\tcmake -S. -B\"$BUILD_DIR\" \\\n\t\t-DTARGET_PLATFORM=miyoo_mini \\\n\t\t-DCMAKE_BUILD_TYPE=Release \\\n\t\t-DCMAKE_TOOLCHAIN_FILE=\"${PACKAGING_DIR}/toolchainfile.cmake\" \\\n\t\t-DBUILD_TESTING=OFF \\\n\t\t-DDISABLE_DEMOMODE=ON \\\n\t\t\"$@\"\n}\n\ncmake_build() {\n\tcmake --build \"$BUILD_DIR\" -j $(getconf _NPROCESSORS_ONLN)\n}\n\nbuild_custom_sdl() {\n\t# make clean folder for custom SDL build\n\trm -rf $BUILD_DIR/CustomSDL\n\tmkdir  $BUILD_DIR/CustomSDL\n\n\t# clone the repo and build the lib\n\tcd $BUILD_DIR/CustomSDL\n\tgit clone $MIYOO_CUSTOM_SDL_REPO --branch $MIYOO_CUSTOM_SDL_BRANCH --single-branch .\n\n\tPATH=\"/opt/miyoomini-toolchain/usr/bin:${PATH}:/opt/miyoomini-toolchain/usr/arm-linux-gnueabihf/sysroot/bin\" \\\n\tCROSS_COMPILE=/opt/miyoomini-toolchain/usr/bin/arm-linux-gnueabihf- \\\n\tPREFIX=/opt/miyoomini-toolchain/usr/arm-linux-gnueabihf/sysroot/usr \\\n\tUNION_PLATFORM=miyoomini \\\n\t./make.sh\n\n\t# change back to devilutionx root\n\tcd \"$PACKAGING_DIR/../..\"\n\tcp -rfL \"$BUILD_DIR/CustomSDL/build/.libs/libSDL-1.2.so.0\" \"$BUILD_DIR/OnionOS/Roms/PORTS/Games/Diablo (DevilutionX)/lib/libSDL-1.2.so.0\"\n}\n\nprepare_onion_skeleton() {\n\tmkdir -p $BUILD_DIR/OnionOS\n\n\t# Copy basic skeleton\n\tcp -rf  Packaging/miyoo_mini/skeleton_OnionOS/* $BUILD_DIR/OnionOS\n\n\t# ensure lib dir for custom SDL\n\tmkdir -p \"$BUILD_DIR/OnionOS/Roms/PORTS/Games/Diablo (DevilutionX)/lib\"\n}\n\npackage_onion() {\n\tprepare_onion_skeleton\n\tbuild_custom_sdl\n\t# copy assets mpq\n\tcp -f $BUILD_DIR/devilutionx.mpq \"$BUILD_DIR/OnionOS/Roms/PORTS/Games/Diablo (DevilutionX)/devilutionx.mpq\"\n\t# copy executable\n\tcp -f $BUILD_DIR/devilutionx \"$BUILD_DIR/OnionOS/Roms/PORTS/Games/Diablo (DevilutionX)/devilutionx\"\n\n\trm -f $BUILD_DIR/onion.zip\n\n\tcd $BUILD_DIR/OnionOS\n\tzip -r ../devilutionx-miyoo-mini-onion-os.zip .\n\tcd \"$PACKAGING_DIR/../..\"\n}\n\nprepare_miniui_skeleton() {\n\tmkdir -p $BUILD_DIR/MiniUI\n\n\t# copy basic skeleton\n\tcp -rf  Packaging/miyoo_mini/skeleton_MiniUI/* $BUILD_DIR/MiniUI\n\n\t# ensure devilutionx asset dir\n\tmkdir -p $BUILD_DIR/MiniUI/Diablo/assets\n}\n\npackage_miniui() {\n\tprepare_miniui_skeleton\n\t# copy assets\n\tcp -rf $BUILD_DIR/assets/* $BUILD_DIR/MiniUI/Diablo/assets\n\t# copy executable\n\tcp -f $BUILD_DIR/devilutionx $BUILD_DIR/MiniUI/Diablo/devilutionx\n\n\trm -f $BUILD_DIR/miniui.zip\n\n\tcd $BUILD_DIR/MiniUI\n\tzip -r ../devilutionx-miyoo-mini-miniui.zip .\n\tcd \"$PACKAGING_DIR/../..\"\n}\n\nmain\n"
  },
  {
    "path": "Packaging/miyoo_mini/setup_toolchain.sh",
    "content": "#!/bin/sh\n\nmain() {\n\tinstall_dependencies\n\tinstall_toolchain\n}\n\ninstall_toolchain() {\n\tTOOLCHAIN_VERSION=v0.0.3\n\tTOOLCHAIN_TAR=\"miyoomini-toolchain.tar.xz\"\n\n\tTOOLCHAIN_ARCH=`uname -m`\n\tif [ \"$TOOLCHAIN_ARCH\" = \"aarch64\" ]; then\n\t\tTOOLCHAIN_REPO=miyoomini-toolchain-buildroot-aarch64\n\telse\n\t\tTOOLCHAIN_REPO=miyoomini-toolchain-buildroot\n\tfi\n\n\tTOOLCHAIN_URL=\"https://github.com/shauninman/$TOOLCHAIN_REPO/releases/download/$TOOLCHAIN_VERSION/$TOOLCHAIN_TAR\"\n\n\tcd /opt\n\twget \"$TOOLCHAIN_URL\"\n\techo \"extracting remote toolchain $TOOLCHAIN_VERSION ($TOOLCHAIN_ARCH)\"\n\n\ttar xf \"./$TOOLCHAIN_TAR\"\n\trm -rf \"./$TOOLCHAIN_TAR\"\n}\n\ninstall_dependencies() {\n\tapt-get -y update && apt-get -y install \\\n\t\tbc \\\n\t\tbuild-essential \\\n\t\tbzip2 \\\n\t\tbzr \\\n\t\tcmake \\\n\t\tcmake-curses-gui \\\n\t\tcpio \\\n\t\tgettext \\\n\t\tgit \\\n\t\tlibncurses5-dev \\\n\t\tmake \\\n\t\trsync \\\n\t\tscons \\\n  \t\tsmpq \\\n\t\ttree \\\n\t\tunzip \\\n\t\twget \\\n\t\tzip\n}\n\nmain\n"
  },
  {
    "path": "Packaging/miyoo_mini/skeleton_MiniUI/Diablo/Diablo.m3u",
    "content": "launch.sh"
  },
  {
    "path": "Packaging/miyoo_mini/skeleton_MiniUI/Diablo/launch.sh",
    "content": "#!/bin/sh\n\ncd \"$(dirname \"$0\")\"\nHOME=\"$USERDATA_PATH\"\n\nif [ -f \"DIABDAT.MPQ\" ] || [ -f \"spawn.mpq\" ]; then\n\t./devilutionx\nelse\n\tshow \"okay.png\"\n\tsay \"Missing DIABDAT.MPQ!\"$'\\n\\n'\"Please see readme.txt\"$'\\n'\"in the Diablo folder\"$'\\n'\"on your SD card.\"$'\\n'\n\tconfirm only\nfi\n"
  },
  {
    "path": "Packaging/miyoo_mini/skeleton_MiniUI/Diablo/readme.txt",
    "content": "devilutionx(Diablo port) for MiniUI\r\n====================================\r\n\r\nInstallation\r\n--------\r\n- Copy this folder onto your SD card in the location /Roms/Native Games (SH)/\r\n\r\nFor the full game:\r\n  - Get the DIABDAT.MPQ from either the CD or GOG release (https://github.com/diasurgical/devilutionX/wiki/Extracting-the-.MPQs-from-the-GoG-installer)\r\n  - Copy the DIABDAT.MPQ into this folder\r\n  - Optional: If you want to also play the Hellfire expansion, copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq into this fodler aswell\r\n\r\nFor the free shareware version:\r\n  - Get the spawn.mpq (https://github.com/diasurgical/devilutionx-assets/releases/latest/download/spawn.mpq)\r\n  - Copy the spawn.mpq into this folder\r\n\r\nControls\r\n--------\r\n- D-Pad: move\r\n- A: Attack nearest enemy, talk to NPC, pickup/place in inventory, OK in menus\r\n- B: select spell, back in menus\r\n- X: pickup items, open chests and doors, use item in inventory\r\n- Y: cast spell, delete character in main menu\r\n- L: use health item from belt\r\n- R: use mana potion from belt\r\n- L2: character panel\r\n- R2: inventory panel\r\n- Menu: game menu\r\n\r\n- Start show quick acess overlay\r\n- Start + Up: game menu\r\n- Start + Down: toggle automap\r\n- Start + Left: character sheet\r\n- Start + Right: inventory\r\n- Start + Y: quest log\r\n- Start + B: spell book\r\n- Select + D-Pad: simulate arrow keys\r\n- Select + A;B;X;Y: spell hotkeys\r\n"
  },
  {
    "path": "Packaging/miyoo_mini/skeleton_OnionOS/Roms/PORTS/Games/Diablo (devilutionX)/_required_files.txt",
    "content": "Directory tree for \"Diablo (DevilutionX)\"\r\n|\r\n|   devilutionx\r\n|   devilutionx.mpq\r\n|   DIABDAT.MPQ\r\n|   _required_files.txt\r\n|\r\n\\---lib\r\n        libSDL-1.2.so.0\r\n"
  },
  {
    "path": "Packaging/miyoo_mini/skeleton_OnionOS/Roms/PORTS/Shortcuts/Action/Diablo (DevilutionX).notfound",
    "content": "#!/bin/sh\n# Standalone Ports Script Template\n\n# main configuration :\nGameName=\"Diablo (DevilutionX)\"\nGameDir=\"Diablo (DevilutionX)\"\nGameExecutable=\"devilutionx\"\nGameDataFile=\"DIABDAT.MPQ\"\n\n# additional configuration :\nKillAudioserver=0\nPerformanceMode=0\n\n# specific to this port :\nFullGamePath=\"/mnt/SDCARD/Roms/PORTS/Games/$GameDir\"\n\nsavedir=\"/mnt/SDCARD/Saves/CurrentProfile/saves/DevilutionX\"\nconfigdir=\"/mnt/SDCARD/Saves/CurrentProfile/config/DevilutionX\"\nmkdir -p \"$savedir\"\nmkdir -p \"$configdir\"\n\nexport SDL_HIDE_BATTERY=1\n\nArguments=\"--data-dir \\\"$FullGamePath\\\" --save-dir \\\"$savedir\\\" --config-dir \\\"$configdir\\\" --diablo\"\n\n\n# running command line :\n/mnt/SDCARD/Emu/PORTS/launch_standalone.sh \"$GameName\" \"$GameDir\" \"$GameExecutable\" \"$Arguments\" \"$GameDataFile\" \"$KillAudioserver\" \"$PerformanceMode\"\n"
  },
  {
    "path": "Packaging/miyoo_mini/skeleton_OnionOS/readme.txt",
    "content": "DevilutionX (Diablo port) for OnionOS\r\n====================================\r\n\r\nInstallation\r\n--------\r\n- Activate the Ports Collection inside the Onion Installer on your device\r\n- Copy the Roms folder from this archive to the root of your sd card\r\n\r\nFor the full game:\r\n  - Get the DIABDAT.MPQ from the CD, GOG or Battle.net release (https://github.com/diasurgical/devilutionX/wiki/Extracting-the-.MPQs-from-the-GoG-installer)\r\n  - Copy the DIABDAT.MPQ into Roms/PORTS/Games/Diablo (DevilutionX)\r\n  - Optional: If you want to also play the Hellfire expansion, copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq into the same folder\r\n\r\nFor the free shareware version:\r\n  - Get the spawn.mpq (https://github.com/diasurgical/devilutionx-assets/releases/download/v2/spawn.mpq)\r\n  - Copy the spawn.mpq into Roms/PORTS/Games/Diablo (DevilutionX)\r\n\r\nControls\r\n--------\r\n- D-Pad: move\r\n- A: Attack nearest enemy, talk to NPC, pickup/place in inventory, OK in menus\r\n- B: select spell, back in menus\r\n- X: pickup items, open chests and doors, use item in inventory\r\n- Y: cast spell, delete character in main menu\r\n- L: use health item from belt\r\n- R: use mana potion from belt\r\n- L2: character panel\r\n- R2: inventory panel\r\n- Menu: game menu\r\n\r\n- Start show quick acess overlay\r\n- Start + Up: game menu\r\n- Start + Down: toggle automap\r\n- Start + Left: character sheet\r\n- Start + Right: inventory\r\n- Start + Y: quest log\r\n- Start + B: spell book\r\n- Select + D-Pad: simulate arrow keys\r\n- Select + A;B;X;Y: spell hotkeys\r\n"
  },
  {
    "path": "Packaging/miyoo_mini/toolchainfile.cmake",
    "content": "set(CMAKE_SYSTEM_NAME Linux)\r\nset(CMAKE_SYSTEM_VERSION 1)\r\nset(CMAKE_SYSTEM_PROCESSOR arm)\r\nset(CMAKE_PROGRAM_PATH \"/opt/miyoomini-toolchain/bin\")\r\nset(CMAKE_SYSROOT \"/opt/miyoomini-toolchain/arm-linux-gnueabihf/sysroot\")\r\nset(CMAKE_FIND_ROOT_PATH \"/opt/miyoomini-toolchain/arm-linux-gnueabihf/sysroot\")\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\r\nset(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\r\nset(ENV{PKG_CONFIG_SYSROOT_DIR} \"/opt/miyoomini-toolchain/arm-linux-gnueabihf/sysroot\")\r\nset(CMAKE_C_COMPILER \"/opt/miyoomini-toolchain/bin/arm-linux-gnueabihf-gcc\")\r\n"
  },
  {
    "path": "Packaging/nix/AppImage.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\nset -x\n\nBUILD_DIR=\"${1-build}\"\ncmake --install \"$BUILD_DIR\" --prefix \"${BUILD_DIR}/AppDir/usr\"\nmv \"$BUILD_DIR\"/AppDir/usr/share/diasurgical/devilutionx/devilutionx.mpq \"$BUILD_DIR\"/AppDir/usr/bin/devilutionx.mpq\n\nAPPIMAGE_BUILDER=\"${APPIMAGE_BUILDER:-linuxdeploy-x86_64.AppImage}\"\nif ! which \"$APPIMAGE_BUILDER\"; then\n\tif ! [[ -f linuxdeploy-x86_64.AppImage ]]; then\n\t\twget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -N\n\t\tchmod +x linuxdeploy-x86_64.AppImage\n\tfi\n\tAPPIMAGE_BUILDER=../linuxdeploy-x86_64.AppImage\nfi\n\nSRC_DIR=\"${PWD}\"\ncd \"$BUILD_DIR\"\nLD_LIBRARY_PATH=\"${PWD}/AppDir/usr/lib\" \"$APPIMAGE_BUILDER\" --appimage-extract-and-run \\\n\t--appdir=AppDir \\\n\t--custom-apprun=\"${SRC_DIR}/Packaging/nix/AppRun\" \\\n\t-d \"${SRC_DIR}/Packaging/nix/devilutionx.desktop\" \\\n\t-o appimage\ncd -\n\nmv \"${BUILD_DIR}/\"DevilutionX*.AppImage devilutionx.appimage\n"
  },
  {
    "path": "Packaging/nix/AppRun",
    "content": "#!/bin/sh\nexec \"$APPDIR/usr/bin/devilutionx\" \"$@\"\n"
  },
  {
    "path": "Packaging/nix/LinuxReleasePackaging.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\nset -x\n\nBUILD_DIR=\"${1-build}\"\n\nmkdir -p \"${BUILD_DIR}/package\"\n\nPKG_PATH=(\"${BUILD_DIR}/_CPack_Packages/Linux/7Z/\"devilutionx-*/)\nPKG_PATH=\"${PKG_PATH[@]}\"\nPKG_PATH=\"${PKG_PATH%/}\"\n\ncp \"${PKG_PATH}/bin/devilutionx\" \"${BUILD_DIR}/package/devilutionx\"\nif [[ -f \"${PKG_PATH}/lib/discord_game_sdk.so\" ]]; then\n\tcp \"${PKG_PATH}/lib/discord_game_sdk.so\" \"${BUILD_DIR}/package/\"\n\tcat <<'SH' > \"${BUILD_DIR}/package/devilutionx.sh\"\n#!/bin/sh\nBASEDIR=\"$(dirname \"$(realpath \"$0\")\")\"\nLD_LIBRARY_PATH=\"$BASEDIR\" \"$BASEDIR\"/devilutionx \"$@\"\nSH\n\tchmod +x \"${BUILD_DIR}/package/devilutionx.sh\"\nfi\n\ncp \"${BUILD_DIR}/devilutionx\" \"${BUILD_DIR}/package/devilutionx\"\ncp \"${BUILD_DIR}/devilutionx.mpq\" \"${BUILD_DIR}/package/devilutionx.mpq\"\n\nif which dpkg 2>/dev/null; then\n\tcp \"${BUILD_DIR}/\"devilutionx*.deb \"${BUILD_DIR}/package/devilutionx.deb\"\nfi\nif which rpmbuild; then\n\tcp \"${BUILD_DIR}/\"devilutionx*.rpm \"${BUILD_DIR}/package/devilutionx.rpm\"\nfi\n\ncp ./Packaging/nix/README.txt \"${BUILD_DIR}/package/README.txt\"\ncp ./Packaging/resources/LICENSE.CC-BY.txt \"${BUILD_DIR}/package/LICENSE.CC-BY.txt\"\ncp ./Packaging/resources/LICENSE.OFL.txt \"${BUILD_DIR}/package/LICENSE.OFL.txt\"\ncd \"${BUILD_DIR}/package/\" && tar -cavf ../../devilutionx.tar.xz *\n"
  },
  {
    "path": "Packaging/nix/README.txt",
    "content": "# DevilutionX\nDevilutionX is a source port of Diablo and Hellfire that strives to make it simple to run the game while providing engine improvements, bugfixes, and some optional quality of life features.\n\n# Links\nDiscord: https://discord.gg/devilutionx\nGitHub: https://github.com/diasurgical/devilutionX\n\nCheck out the manual for what features are available and how best to take advantage of them: https://github.com/diasurgical/devilutionX/wiki\nFor a full list of changes see our changelog: https://github.com/diasurgical/devilutionX/blob/master/docs/CHANGELOG.md\n\n# How To Install:\n - Extract the files in the archive.\n - Install libsdl2\n - Copy DIABDAT.MPQ from the CD or GOG-installation (or extract it from the GoG installer) to the DevilutionX folder.\n - To run the Diablo: Hellfire expansion you will need to also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq.\n - For Chinese, Japanese, and Korean text support download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq and add it to the game folder.\n - For the Polish voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq.\n - For the Russian voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq.\n - Run ./devilutionx\n\n# Multiplayer\n - TCP/IP requires the host to expose port 6112.\n\nAll games are encrypted and password protected.\n\n# Save Games and configurations\nThe configurations and save games are located in:\n~/.local/share/diasurgical/devilution\n\n# Credits\n - See list of contributors https://github.com/diasurgical/devilutionX/graphs/contributors\n\n# Legal\nThis software is being released to the Public Domain. No assets of Diablo are being provided. You must own a copy of Diablo and have access to the assets beforehand in order to use this software.\n\nBattle.net® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Battle.net and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\n\nDiablo® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\n\nThis software is in no way associated with or endorsed by Blizzard Entertainment®.\n"
  },
  {
    "path": "Packaging/nix/debian-cross-aarch64-prep.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\nset -x\n\nFLAVOR=\"$(lsb_release -sc)\"\n\nif dpkg-vendor --derives-from Ubuntu; then\n\tsudo tee /etc/apt/sources.list.d/arm64.list <<LIST\ndeb [arch=arm64] http://ports.ubuntu.com/ ${FLAVOR} main restricted\ndeb [arch=arm64] http://ports.ubuntu.com/ ${FLAVOR}-updates main restricted\ndeb [arch=arm64] http://ports.ubuntu.com/ ${FLAVOR} universe\ndeb [arch=arm64] http://ports.ubuntu.com/ ${FLAVOR}-updates universe\ndeb [arch=arm64] http://ports.ubuntu.com/ ${FLAVOR} multiverse\ndeb [arch=arm64] http://ports.ubuntu.com/ ${FLAVOR}-updates multiverse\ndeb [arch=arm64] http://ports.ubuntu.com/ ${FLAVOR}-backports main restricted universe multiverse\nLIST\n\tsudo sed -E -i 's/deb (http|file|mirror)/deb [arch=amd64,i386] \\1/' /etc/apt/sources.list\n\tcat /etc/apt/sources.list\nfi\n\n\nPACKAGES=(\n  cmake git smpq gettext dpkg-cross libc-dev-arm64-cross\n  libsdl2-dev:arm64 libsdl2-image-dev:arm64 libsodium-dev:arm64\n  libpng-dev:arm64 libbz2-dev:arm64 libfmt-dev:arm64\n  libspeechd-dev:arm64\n)\n\nif (( $# < 1 )) || [[ \"$1\" != --no-gcc ]]; then\n  PACKAGES+=(crossbuild-essential-arm64)\nfi\n\n\nsudo dpkg --add-architecture arm64\nsudo apt-get update\nsudo apt-get install -y \"${PACKAGES[@]}\"\n"
  },
  {
    "path": "Packaging/nix/debian-cross-i386-prep.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\nset -x\n\nPACKAGES=(\n  cmake git smpq gettext\n  libsdl2-dev:i386 libsdl2-image-dev:i386 libsodium-dev:i386\n  libpng-dev:i386 libbz2-dev:i386 libfmt-dev:i386 libspeechd-dev:i386\n)\n\nif (( $# < 1 )) || [[ \"$1\" != --no-gcc ]]; then\n  PACKAGES+=(g++-multilib)\nfi\n\nsudo dpkg --add-architecture i386\nsudo apt-get update\nsudo apt-get install --ignore-hold -y \"${PACKAGES[@]}\"\n\n"
  },
  {
    "path": "Packaging/nix/debian-host-prep.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\nset -x\n\nPACKAGES=(\n  rpm pkg-config cmake git smpq gettext libsdl2-dev libsdl2-image-dev libsodium-dev\n  libpng-dev libbz2-dev libfmt-dev libspeechd-dev\n)\n\nif (( $# < 1 )) || [[ \"$1\" != --no-gcc ]]; then\n  PACKAGES+=(g++)\nfi\n\nsudo apt-get update\nsudo apt-get install -y \"${PACKAGES[@]}\"\n\n"
  },
  {
    "path": "Packaging/nix/devilutionx-hellfire.desktop",
    "content": "[Desktop Entry]\nName=DevilutionX Hellfire\nGenericName=DevilutionX Hellfire\nComment=Play Diablo: Hellfire\nComment[da]=Spil Diablo: Hellfire\nComment[hr]=Igrajte Diablo: Hellfire\nComment[it]=Gioca a Diablo: Hellfire\nComment[ru]=Играть в Diablo: Hellfire\nComment[ua]=Грати в Diablo: Hellfire\nExec=devilutionx --hellfire\nIcon=devilutionx-hellfire\nTerminal=false\nType=Application\nX-DCOP-ServiceType=Multi\nX-KDE-StartupNotify=true\nCategories=Game;RolePlaying;\nKeywords=Game;Diablo;Hellfire;Action;RPG;DevilutionX;\n"
  },
  {
    "path": "Packaging/nix/devilutionx.6",
    "content": ".TH DEVILUTIONX 6 \"May 2025\" \"1.5.4\" \"DevilutionX Community\"\n.SH NAME\ndevilutionx \\- A port of Diablo and Hellfire\n.SH SYNOPSIS\ndevilutionx [OPTION]\n.SH DESCRIPTION\n.I DevilutionX\nis a port of\n.B Diablo\nand\n.B Hellfire\nthat strives to make it simple to run the game while providing engine improvements, bugfixes, and some optional quality of life features.\n.SH OPTIONS\n.TP\n.B \\-h, \\-\\-help\nThis lists all command line options and exit.\n.TP\n.B \\-\\-version\nPrint the version and exit.\n.TP\n.B \\-\\-data\\-dir\nSpecify the folder of\n.I diabdat.mpq.\n.TP\n.B \\-\\-save\\-dir\nSpecify the folder of save files.\n.TP\n.B \\-\\-config\\-dir\nSpecify the location of\n.I diablo.ini.\n.TP\n.B \\-\\-lang\nSpecify the language code (e.g.\n.I en\nor\n.I pt_BR\n).\n.TP\n.B \\-n\nSkip startup videos.\n.TP\n.B \\-f\nDisplay frames per second.\n.TP\n.B \\-\\-verbose\nEnable verbose logging.\n.TP\n.B \\-\\-record \\fI<#>\\fR\nRecord a demo file.\n.TP\n.B \\-\\-demo \\fI<#>\\fR\nPlay a demo file.\n.TP\n.B \\-\\-timedemo\nDisable all frame limiting during demo playback.\n.SH GAME SELECTION\n.TP\n.B \\-\\-spawn\nForce Shareware mode.\n.TP\n.B \\-\\-diablo\nForce Diablo mode.\n.TP\n.B \\-\\-hellfire\nForce Hellfire mode.\n.SH MULTI-PLAYER\nTCP/IP requires the host to expose the port the game is listening on, 6112 by default. Private games are encrypted and password protected.\n.SH SAVE GAMES AND CONFIGURATIONS\nBy default the configurations and save games are located in:\n.I ~/.local/share/diasurgical/devilution\n.SH INSTALLATION\nTo install\n.B DevilutionX:\n.IP 1.\nExtract the files in the archive.\n.IP 2.\nInstall\n.B libsdl2.\n.IP 3.\nCopy\n.I DIABDAT.MPQ\nfrom the CD or GOG-installation (or extract it from the GOG installer) to the DevilutionX folder.\n.IP 4.\nTo run the Diablo: Hellfire expansion you will need to also copy\n.I hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq.\n.IP 5.\nFor Chinese, Japanese, and Korean text support download:\n\n.B https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq\n\nand add it to the game folder.\n.RE\n\n.IP 6.\nFor the Polish voice pack download:\n\n.B https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq\n.IP 7.\nFor the Russian voice pack download:\n\n.B https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq\n\n.IP 8.\nFor the Spanish voice pack download:\n\n.B https://github.com/diasurgical/devilutionx-assets/releases/latest/download/es.mpq\n.IP 8.\nRun\n.B ./devilutionx\n.SH REPORTING BUGS\nReport bugs at\n.B https://github.com/diasurgical/devilutionX/\n.SH SEE ALSO\nDiscord:\n.B https://discord.gg/devilutionx\n.RE\n.PP\nGitHub:\n.B https://github.com/diasurgical/devilutionX\n.RE\n.PP\nManual:\n.B https://github.com/diasurgical/devilutionX/wiki\n.RE\n.PP\nChangelog:\n.B https://github.com/diasurgical/devilutionX/blob/master/docs/CHANGELOG.md\n.RE\n.SH AUTHOR\nWritten by the DevilutionX community.\n.SH COPYRIGHT\nDevilutionX is made publicly available and released under the Sustainable Use License (see LICENSE).\n\n.B https://github.com/diasurgical/DevilutionX/blob/master/LICENSE.md\n.P\nThe source code in this repository is for non-commercial use only. If you use the source code, you may not charge others for access to it or any derivative work thereof.\n.P\nDiablo® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\n.P\nDevilutionX and any of its maintainers are in no way associated with or endorsed by Blizzard Entertainment®.\n"
  },
  {
    "path": "Packaging/nix/devilutionx.desktop",
    "content": "[Desktop Entry]\nName=DevilutionX\nGenericName=DevilutionX\nComment=Play Diablo I\nComment[da]=Spil Diablo I\nComment[hr]=Igrajte Diablo I\nComment[it]=Gioca a Diablo I\nComment[ru]=Играть в Diablo I\nComment[ua]=Грати в Diablo I\nExec=devilutionx --diablo\nIcon=devilutionx\nTerminal=false\nType=Application\nX-DCOP-ServiceType=Multi\nX-KDE-StartupNotify=true\nCategories=Game;RolePlaying;\nKeywords=Game;Diablo;Action;RPG;DevilutionX;\n"
  },
  {
    "path": "Packaging/nix/devilutionx.metainfo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<component type=\"desktop-application\">\n\t<id>org.diasurgical.DevilutionX</id>\n\n\t<developer id=\"org.diasurgical\">\n\t\t<name>Diasurgical team</name>\n\t</developer>\n\n\t<name>DevilutionX</name>\n\t<summary>Experience Diablo and Hellfire anew</summary>\n\n\t<metadata_license>CC-BY-SA-4.0</metadata_license>\n\t<project_license>SUL-1.0</project_license>\n\n\t<branding>\n\t\t<color type=\"primary\" scheme_preference=\"light\">#c86666</color>\n\t\t<color type=\"primary\" scheme_preference=\"dark\">#640000</color>\n\t</branding>\n\n\t<url type=\"homepage\">https://github.com/diasurgical/devilutionX</url>\n\t<url type=\"bugtracker\">https://github.com/diasurgical/devilutionX/issues</url>\n\t<url type=\"contact\">https://discord.gg/devilutionx</url>\n\t<url type=\"vcs-browser\">https://github.com/diasurgical/devilutionX</url>\n\n\t<content_rating type=\"oars-1.1\">\n\t\t<content_attribute id=\"violence-fantasy\">moderate</content_attribute>\n\t\t<content_attribute id=\"drugs-alcohol\">moderate</content_attribute>\n\t\t<content_attribute id=\"sex-nudity\">moderate</content_attribute>\n\t\t<content_attribute id=\"sex-themes\">moderate</content_attribute>\n\t\t<content_attribute id=\"language-profanity\">mild</content_attribute>\n\t\t<content_attribute id=\"language-humor\">mild</content_attribute>\n\t\t<content_attribute id=\"social-chat\">intense</content_attribute>\n\t</content_rating>\n\n\t<categories>\n\t\t<category>Game</category>\n\t\t<category>ActionGame</category>\n\t\t<category>RolePlaying</category>\n\t</categories>\n\n\t<supports>\n\t\t<control>pointing</control>\n\t\t<control>keyboard</control>\n\t\t<control>touch</control>\n\t\t<control>gamepad</control>\n\t</supports>\n\n\t<description>\n\t\t<p>\n      DevilutionX is a source port of Diablo and Hellfire that strives to make it simple to run the game while providing engine improvements, bugfixes, and some optional quality of life features. This includes support for modern operating systems and higher resolutions, controller and touch control support, translations, stash, optional experience and enemy health bars, etc.\n\t\t</p>\n\t\t<p>\n      Note: DevilutionX requires data files from original Diablo/Hellfire. By default, a demo version of Diablo is installed.\n\t\t</p>\n\t\t<p>\n\t  To install the full version of Diablo, copy DIABDAT.MPQ from the CD or GOG-installation (or extract it from the GoG installer) to ~/.var/app/org.diasurgical.DevilutionX/data/diasurgical/devilution.\n\t\t</p>\n\t\t<p>\n\t  To run the Diablo: Hellfire expansion you will need to also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq.\n\t\t</p>\n\t</description>\n\n\t<launchable type=\"desktop-id\">devilutionx.desktop</launchable>\n\t<screenshots>\n\t\t<screenshot type=\"default\">\n\t\t\t<image>https://raw.githubusercontent.com/flathub/org.diasurgical.DevilutionX/master/screens/screen1.png</image>\n\t\t\t<caption>Diablo gameplay in widescreen</caption>\n\t\t</screenshot>\n\t\t<screenshot>\n\t\t\t<image>https://raw.githubusercontent.com/flathub/org.diasurgical.DevilutionX/master/screens/screen2.png</image>\n\t\t\t<caption>Diablo gameplay with enemy health bar and XP bar</caption>\n\t\t</screenshot>\n\t\t<screenshot>\n\t\t\t<image>https://raw.githubusercontent.com/flathub/org.diasurgical.DevilutionX/master/screens/screen3.png</image>\n\t\t\t<caption>Diablo gameplay on Android mobile device</caption>\n\t\t</screenshot>\n\t</screenshots>\n\t<releases>\n\t\t<release version=\"1.5.5\" date=\"2025-10-31\">\n\t\t\t<description>\n\t\t\t\t<p>This release includes the following updates:</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>App icon on Linux is now aligned with Android</li>\n\t\t\t\t\t<li>Adjusted game speeds for Multiplayer</li>\n\t\t\t\t\t<li>You can now use CTRL+ Mouse Scroll to zoom the map</li>\n\t\t\t\t\t<li>Murphy Shrine has been added to Crippling Shrines</li>\n\t\t\t\t\t<li>Updates to Russian and Polish translations</li>\n\t\t\t\t\t<li>Crash fixes</li>\n\t\t\t\t</ul>\n\t\t\t\t<p>Please visit the full changelog for more detailed notes</p>\n\t\t\t</description>\n\t\t\t<url>https://github.com/diasurgical/devilutionX/releases/tag/1.5.5</url>\n\t\t</release>\n\t\t<release version=\"1.5.4\" date=\"2025-02-08\">\n\t\t\t<description>\n\t\t\t\t<p>This release includes the following updates:</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>Invalid items are now unusable</li>\n\t\t\t\t\t<li>Improved gamepad controls</li>\n\t\t\t\t\t<li>Updated Italian, Russian and Ukrainian translations</li>\n\t\t\t\t\t<li>Fixed multiple crashes</li>\n\t\t\t\t\t<li>Improved item validation in multiplayer</li>\n\t\t\t\t\t<li>Fixed multiple bugs found in original Diablo and Hellfire</li>\n\t\t\t\t</ul>\n\t\t\t\t<p>Please visit the full changelog for more detailed notes</p>\n\t\t\t</description>\n\t\t\t<url>https://github.com/diasurgical/devilutionX/releases/tag/1.5.4</url>\n\t\t</release>\n\t\t<release version=\"1.5.3\" date=\"2024-08-30\">\n\t\t\t<description>\n\t\t\t\t<p>This release includes the following updates:</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>Resolved validation multiplayer errors</li>\n\t\t\t\t\t<li>Added Hungarian translation</li>\n\t\t\t\t\t<li>Added Turkish translation</li>\n\t\t\t\t\t<li>Fixed issue where a line is repeated in the info panel</li>\n\t\t\t\t\t<li>Fixed errors when converting Hellfire saved games</li>\n\t\t\t\t</ul>\n\t\t\t\t<p>Please visit the full changelog for more detailed notes</p>\n\t\t\t</description>\n\t\t\t<url>https://github.com/diasurgical/devilutionX/releases/tag/1.5.3</url>\n\t\t</release>\n\t\t<release version=\"1.5.2\" date=\"2024-02-04\">\n\t\t\t<description>\n\t\t\t\t<p>This release includes the following updates:</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>Fix issues with joining games due to invalid player data</li>\n\t\t\t\t\t<li>Improve rendering of Chinese/Japanese/Korean texts</li>\n\t\t\t\t\t<li>Fix Hellfire items not saving their identified state</li>\n\t\t\t\t\t<li>Fix stash corrupting when converting a hero between Diablo and Hellfire</li>\n\t\t\t\t</ul>\n\t\t\t\t<p>Please visit the full changelog for more detailed notes</p>\n\t\t\t</description>\n\t\t\t<url>https://github.com/diasurgical/devilutionX/releases/tag/1.5.2</url>\n\t\t</release>\n\t\t<release version=\"1.5.1\" date=\"2023-09-02\">\n\t\t\t<description>\n\t\t\t\t<p>This is a primarily bugfix release, which includes the following updates:</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>Resolve various gameplay and graphical issues</li>\n\t\t\t\t\t<li>Revamped settings menu for better organization</li>\n\t\t\t\t\t<li>Rectification of crashes identified in version 1.5.0</li>\n\t\t\t\t\t<li>Reduced RAM usage for improved performance</li>\n\t\t\t\t\t<li>Updates to PVP arenas</li>\n\t\t\t\t\t<li>Increased reliability in multiplayer functionality</li>\n\t\t\t\t\t<li>Improved translations</li>\n\t\t\t\t\t<li>Fixed gameplay recording playback issues</li>\n\t\t\t\t</ul>\n\t\t\t\t<p>Please visit the full changelog for more detailed notes</p>\n\t\t\t</description>\n\t\t\t<url>https://github.com/diasurgical/devilutionX/releases/tag/1.5.1</url>\n\t\t</release>\n\t\t<release version=\"1.5.0\" date=\"2023-06-13\">\n\t\t\t<description>\n\t\t\t\t<p>This release includes a lot of features, such as:</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>All quests are playable in multiplayer</li>\n\t\t\t\t\t<li>PVP arenas</li>\n\t\t\t\t\t<li>Controller button remapping</li>\n\t\t\t\t\t<li>Tons of bugfixes, including for original Diablo/Hellfire</li>\n\t\t\t\t</ul>\n\t\t\t\t<p>And a lot more! Please visit the link for detailed notes.</p>\n\t\t\t</description>\n\t\t\t<url>https://github.com/diasurgical/devilutionX/releases/tag/1.5.0</url>\n\t\t</release>\n\t\t<release version=\"1.4.1\" date=\"2022-07-25\" />\n\t\t<release version=\"1.4.0\" date=\"2022-04-14\" />\n\t\t<release version=\"1.3.0\" date=\"2021-11-02\" />\n\t\t<release version=\"1.2.1\" date=\"2021-04-13\" />\n\t\t<release version=\"1.2.0\" date=\"2021-04-06\" />\n\t\t<release version=\"1.1.0\" date=\"2020-10-11\" />\n\t\t<release version=\"1.0.3\" date=\"2020-10-11\" />\n\t\t<release version=\"1.0.2\" date=\"2020-10-10\" />\n\t\t<release version=\"1.0.1\" date=\"2020-03-09\" />\n\t\t<release version=\"1.0.0\" date=\"2019-12-31\" />\n\t\t<release version=\"0.5.0\" date=\"2019-10-10\" />\n\t\t<release version=\"0.4.0\" date=\"2019-03-20\" />\n\t\t<release version=\"0.3.1\" date=\"2019-03-20\" />\n\t\t<release version=\"0.3.0\" date=\"2019-03-20\" />\n\t\t<release version=\"0.2.0\" date=\"2019-03-17\" />\n\t\t<release version=\"0.1.0\" date=\"2019-02-27\" />\n\t</releases>\n</component>\n"
  },
  {
    "path": "Packaging/pi/README.txt",
    "content": "# DevilutionX\nDevilutionX is a source port of Diablo and Hellfire that strives to make it simple to run the game while providing engine improvements, bugfixes, and some optional quality of life features.\n\n# Links\nDiscord: https://discord.gg/devilutionx\nGitHub: https://github.com/diasurgical/devilutionX\n\nCheck out the manual for what features are available and how best to take advantage of them: https://github.com/diasurgical/devilutionX/wiki\nFor a full list of changes see our changelog: https://github.com/diasurgical/devilutionX/blob/master/docs/CHANGELOG.md\n\n# How To Install:\n - Extract the files in the archive.\n - Install libsdl2\n - Copy DIABDAT.MPQ from the CD or GOG-installation (or extract it from the GoG installer) to the DevilutionX folder.\n - To run the Diablo: Hellfire expansion you will need to also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq.\n - For Chinese, Japanese, and Korean text support download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq and add it to the game folder.\n - For the Polish voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq.\n - For the Russian voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq.\n - Run ./devilutionx\n\n# Raspberry Pi performance\n - This build is compiled for Raspbian Stretch\n - For the best experience set upscale=0 in diablo.ini and set the system resolution to 640x480\n - Alternately you can enable experimental GL-drivers via raspi-config for upscaling support\n\n# Multiplayer\n - TCP/IP requires the host to expose port 6112.\n\nAll games are encrypted and password protected.\n\n# Save Games and configurations\nThe configurations and save games are located in:\n~/.local/share/diasurgical/devilution\n\n# Credits\n - See list of contributors https://github.com/diasurgical/devilutionX/graphs/contributors\n\n# Legal\nThis software is being released to the Public Domain. No assets of Diablo are being provided. You must own a copy of Diablo and have access to the assets beforehand in order to use this software.\n\nBattle.net® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Battle.net and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\n\nDiablo® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\n\nThis software is in no way associated with or endorsed by Blizzard Entertainment®.\n"
  },
  {
    "path": "Packaging/ps4/README.md",
    "content": "# devilutionX PS4 port\r\n\r\n## Prerequisites\r\n- A Playstation 4 capable of running homebrew.\r\n- Game assets from the Diablo game (diabdat.mpq),\r\n  or its [shareware][shareware] (spawn.mpq)\r\n\r\n## Installation\r\n- Install the devilutionX PS4 pkg\r\n- Copy the game assets (e.g., via ftp) to /user/data/diasurgical/devilution/\r\n- Launch the game\r\n\r\n## Known limitations\r\n - No networking\r\n\r\n## Controls\r\n- D-pad: move hero\r\n- ○: attack nearby enemies, talk to townspeople and merchants, pickup/place\r\n     items in the inventory, OK while in main menu\r\n- ×: select spell, back while in menus\r\n- △: pickup items, open nearby chests and doors, use item in the inventory\r\n- □: cast spell, delete character while in main menu\r\n- L1: use health item from belt\r\n- R1: use mana potion from belt\r\n- L2: toggle character sheet\r\n- R2: toggle inventory\r\n- Left stick: move hero\r\n- Right stick: move cursor\r\n- L3: toggle auto map\r\n- R3: click with cursor\r\n\r\n## Building from Source\r\nInstall the [PacBrew openorbis SDK][pacbrew-openorbis], then run the following\r\n bash script.\r\n```console\r\ndevilutionX$ ./Packaging/ps4/build.sh\r\n```\r\n\r\n[shareware]: http://ftp.blizzard.com/pub/demos/diablosw.exe\r\n[pacbrew-openorbis]: https://github.com/PacBrew/pacbrew-packages\r\n"
  },
  {
    "path": "Packaging/ps4/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nSCRIPTDIR=\"${BASH_SOURCE[0]}\"\nSCRIPTDIR=\"$(dirname \"${SCRIPTDIR}\")\"\n\ncmake -S \"${SCRIPTDIR}/../../\" \\\n      -B build-ps4 \\\n      -DCMAKE_BUILD_TYPE=Release \\\n      -DCMAKE_VERBOSE_MAKEFILE=ON \\\n      -DCMAKE_TOOLCHAIN_FILE=\"/opt/pacbrew/ps4/openorbis/cmake/ps4.cmake\"\n\ncmake --build build-ps4 -j $(getconf _NPROCESSORS_ONLN)\nmv build-ps4/IV0001-DVLX00001_00-*.pkg build-ps4/devilutionx.pkg\n"
  },
  {
    "path": "Packaging/ps5/README.md",
    "content": "# devilutionX PS5 port\r\n\r\n## Prerequisites\r\n- A Playstation 5 capable of running the [ps5-payload-websrv][websrv] homebrew.\r\n- Game assets from the Diablo game (diabdat.mpq),\r\n  or its [shareware][shareware] (spawn.mpq)\r\n\r\n## Installation\r\n- Copy the game assets (e.g., via ftp) to /data/homebrew/devilutionX\r\n- Launch the [ps5-payload-websrv][websrv] homebrew\r\n- Launch the game from your browser at http://PS5-IP:8080, or using the\r\n  [companion launcher][launcher] from the PS5 menu system\r\n\r\n## Controls\r\n- D-pad: move hero\r\n- ○: attack nearby enemies, talk to townspeople and merchants, pickup/place\r\n     items in the inventory, OK while in main menu\r\n- ×: select spell, back while in menus\r\n- △: pickup items, open nearby chests and doors, use item in the inventory\r\n- □: cast spell, delete character while in main menu\r\n- L1: use health item from belt\r\n- R1: use mana potion from belt\r\n- L2: toggle character sheet\r\n- R2: toggle inventory\r\n- Left stick: move hero\r\n- Right stick: move cursor\r\n- L3: toggle auto map\r\n- R3: click with cursor\r\n\r\n## Building from Source\r\nInstall the [PacBrew PS5 SDK][pacbrew], then run the following\r\n bash script:\r\n```console\r\ndevilutionX$ ./Packaging/ps5/build.sh\r\n```\r\n\r\n[shareware]: http://ftp.blizzard.com/pub/demos/diablosw.exe\r\n[pacbrew]: https://github.com/ps5-payload-dev/pacbrew-repo\r\n[websrv]: https://github.com/ps5-payload-dev/websrv\r\n[launcher]: https://github.com/ps5-payload-dev/websrv/blob/master/homebrew/IV9999-FAKE00001_00-HOMEBREWLOADER01.pkg?raw=true\r\n"
  },
  {
    "path": "Packaging/ps5/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nSCRIPTDIR=\"${BASH_SOURCE[0]}\"\nSCRIPTDIR=\"$(dirname \"${SCRIPTDIR}\")\"\n\nif [ -z \"${PS5_PAYLOAD_SDK}\" ]; then\n    export PS5_PAYLOAD_SDK=/opt/ps5-payload-sdk\nfi\n\nsource \"${PS5_PAYLOAD_SDK}/toolchain/prospero.sh\"\n\n${CMAKE} -DCMAKE_BUILD_TYPE=Release \\\n\t -DDISCORD_INTEGRATION=OFF \\\n\t -DBUILD_TESTING=OFF \\\n\t -DASAN=OFF \\\n\t -DUBSAN=OFF \\\n\t -DDISABLE_LTO=ON \\\n\t -DNOEXIT=ON \\\n\t -DNONET=OFF \\\n\t -DBUILD_ASSETS_MPQ=ON \\\n\t -DDEVILUTIONX_SYSTEM_SDL_IMAGE=OFF \\\n\t -B build-ps5 \\\n\t -S \"${SCRIPTDIR}/../../\"\n${MAKE} -C build-ps5 -j $(getconf _NPROCESSORS_ONLN)\n\nrm -rf build-ps5/DevilutionX\nmkdir build-ps5/DevilutionX\n\ncp -r \"${SCRIPTDIR}/sce_sys\" build-ps5/DevilutionX/\ncp \"${SCRIPTDIR}/homebrew.js\" build-ps5/DevilutionX/\ncp \"${SCRIPTDIR}/README.md\" build-ps5/DevilutionX/\ncp build-ps5/devilutionx.mpq build-ps5/DevilutionX/\ncp build-ps5/devilutionx build-ps5/DevilutionX/devilutionx.elf\n\n# Let github actions do this?\ncd build-ps5\nrm -f devilutionx-ps5.zip\nzip -r devilutionx-ps5.zip DevilutionX\n"
  },
  {
    "path": "Packaging/ps5/homebrew.js",
    "content": "\nasync function main() {\n    const PAYLOAD = window.workingDir + '/devilutionx.elf';\n\n    return {\n        mainText: \"DevilutionX\",\n        secondaryText: 'Diablo build for modern OSes',\n        onclick: async () => {\n\t    return {\n\t\tpath: PAYLOAD,\n\t\targs: ''\n\t    };\n        },\n\toptions: [\n\t    {\n\t\ttext: \"Force Shareware mode\",\n\t\tonclick: async () => {\n\t\t    return {\n\t\t\tpath: PAYLOAD,\n\t\t\targs: '--spawn'\n\t\t    };\n\t\t}\n            },\n\t    {\n\t\ttext: \"Force Diablo mode\",\n\t\tonclick: async () => {\n\t\t    return {\n\t\t\tpath: PAYLOAD,\n\t\t\targs: '--diablo'\n\t\t    };\n\t\t}\n\t    },\n\t    {\n\t\ttext: \"Force Hellfire mode\",\n\t\tonclick: async () => {\n\t\t    return {\n\t\t\tpath: PAYLOAD,\n\t\t\targs: '--hellfire'\n\t\t    };\n\t\t}\n\t    }\n\t]\n    };\n}\n"
  },
  {
    "path": "Packaging/resources/LICENSE.CC-BY.txt",
    "content": "Attribution 4.0 International\n\n=======================================================================\n\nCreative Commons Corporation (\"Creative Commons\") is not a law firm and\ndoes not provide legal services or legal advice. Distribution of\nCreative Commons public licenses does not create a lawyer-client or\nother relationship. Creative Commons makes its licenses and related\ninformation available on an \"as-is\" basis. Creative Commons gives no\nwarranties regarding its licenses, any material licensed under their\nterms and conditions, or any related information. Creative Commons\ndisclaims all liability for damages resulting from their use to the\nfullest extent possible.\n\nUsing Creative Commons Public Licenses\n\nCreative Commons public licenses provide a standard set of terms and\nconditions that creators and other rights holders may use to share\noriginal works of authorship and other material subject to copyright\nand certain other rights specified in the public license below. The\nfollowing considerations are for informational purposes only, are not\nexhaustive, and do not form part of our licenses.\n\n     Considerations for licensors: Our public licenses are\n     intended for use by those authorized to give the public\n     permission to use material in ways otherwise restricted by\n     copyright and certain other rights. Our licenses are\n     irrevocable. Licensors should read and understand the terms\n     and conditions of the license they choose before applying it.\n     Licensors should also secure all rights necessary before\n     applying our licenses so that the public can reuse the\n     material as expected. Licensors should clearly mark any\n     material not subject to the license. This includes other CC-\n     licensed material, or material used under an exception or\n     limitation to copyright. More considerations for licensors:\n    wiki.creativecommons.org/Considerations_for_licensors\n\n     Considerations for the public: By using one of our public\n     licenses, a licensor grants the public permission to use the\n     licensed material under specified terms and conditions. If\n     the licensor's permission is not necessary for any reason--for\n     example, because of any applicable exception or limitation to\n     copyright--then that use is not regulated by the license. Our\n     licenses grant only permissions under copyright and certain\n     other rights that a licensor has authority to grant. Use of\n     the licensed material may still be restricted for other\n     reasons, including because others have copyright or other\n     rights in the material. A licensor may make special requests,\n     such as asking that all changes be marked or described.\n     Although not required by our licenses, you are encouraged to\n     respect those requests where reasonable. More considerations\n     for the public:\n    wiki.creativecommons.org/Considerations_for_licensees\n\n=======================================================================\n\nCreative Commons Attribution 4.0 International Public License\n\nBy exercising the Licensed Rights (defined below), You accept and agree\nto be bound by the terms and conditions of this Creative Commons\nAttribution 4.0 International Public License (\"Public License\"). To the\nextent this Public License may be interpreted as a contract, You are\ngranted the Licensed Rights in consideration of Your acceptance of\nthese terms and conditions, and the Licensor grants You such rights in\nconsideration of benefits the Licensor receives from making the\nLicensed Material available under these terms and conditions.\n\n\nSection 1 -- Definitions.\n\n  a. Adapted Material means material subject to Copyright and Similar\n     Rights that is derived from or based upon the Licensed Material\n     and in which the Licensed Material is translated, altered,\n     arranged, transformed, or otherwise modified in a manner requiring\n     permission under the Copyright and Similar Rights held by the\n     Licensor. For purposes of this Public License, where the Licensed\n     Material is a musical work, performance, or sound recording,\n     Adapted Material is always produced where the Licensed Material is\n     synched in timed relation with a moving image.\n\n  b. Adapter's License means the license You apply to Your Copyright\n     and Similar Rights in Your contributions to Adapted Material in\n     accordance with the terms and conditions of this Public License.\n\n  c. Copyright and Similar Rights means copyright and/or similar rights\n     closely related to copyright including, without limitation,\n     performance, broadcast, sound recording, and Sui Generis Database\n     Rights, without regard to how the rights are labeled or\n     categorized. For purposes of this Public License, the rights\n     specified in Section 2(b)(1)-(2) are not Copyright and Similar\n     Rights.\n\n  d. Effective Technological Measures means those measures that, in the\n     absence of proper authority, may not be circumvented under laws\n     fulfilling obligations under Article 11 of the WIPO Copyright\n     Treaty adopted on December 20, 1996, and/or similar international\n     agreements.\n\n  e. Exceptions and Limitations means fair use, fair dealing, and/or\n     any other exception or limitation to Copyright and Similar Rights\n     that applies to Your use of the Licensed Material.\n\n  f. Licensed Material means the artistic or literary work, database,\n     or other material to which the Licensor applied this Public\n     License.\n\n  g. Licensed Rights means the rights granted to You subject to the\n     terms and conditions of this Public License, which are limited to\n     all Copyright and Similar Rights that apply to Your use of the\n     Licensed Material and that the Licensor has authority to license.\n\n  h. Licensor means the individual(s) or entity(ies) granting rights\n     under this Public License.\n\n  i. Share means to provide material to the public by any means or\n     process that requires permission under the Licensed Rights, such\n     as reproduction, public display, public performance, distribution,\n     dissemination, communication, or importation, and to make material\n     available to the public including in ways that members of the\n     public may access the material from a place and at a time\n     individually chosen by them.\n\n  j. Sui Generis Database Rights means rights other than copyright\n     resulting from Directive 96/9/EC of the European Parliament and of\n     the Council of 11 March 1996 on the legal protection of databases,\n     as amended and/or succeeded, as well as other essentially\n     equivalent rights anywhere in the world.\n\n  k. You means the individual or entity exercising the Licensed Rights\n     under this Public License. Your has a corresponding meaning.\n\n\nSection 2 -- Scope.\n\n  a. License grant.\n\n       1. Subject to the terms and conditions of this Public License,\n          the Licensor hereby grants You a worldwide, royalty-free,\n          non-sublicensable, non-exclusive, irrevocable license to\n          exercise the Licensed Rights in the Licensed Material to:\n\n            a. reproduce and Share the Licensed Material, in whole or\n               in part; and\n\n            b. produce, reproduce, and Share Adapted Material.\n\n       2. Exceptions and Limitations. For the avoidance of doubt, where\n          Exceptions and Limitations apply to Your use, this Public\n          License does not apply, and You do not need to comply with\n          its terms and conditions.\n\n       3. Term. The term of this Public License is specified in Section\n          6(a).\n\n       4. Media and formats; technical modifications allowed. The\n          Licensor authorizes You to exercise the Licensed Rights in\n          all media and formats whether now known or hereafter created,\n          and to make technical modifications necessary to do so. The\n          Licensor waives and/or agrees not to assert any right or\n          authority to forbid You from making technical modifications\n          necessary to exercise the Licensed Rights, including\n          technical modifications necessary to circumvent Effective\n          Technological Measures. For purposes of this Public License,\n          simply making modifications authorized by this Section 2(a)\n          (4) never produces Adapted Material.\n\n       5. Downstream recipients.\n\n            a. Offer from the Licensor -- Licensed Material. Every\n               recipient of the Licensed Material automatically\n               receives an offer from the Licensor to exercise the\n               Licensed Rights under the terms and conditions of this\n               Public License.\n\n            b. No downstream restrictions. You may not offer or impose\n               any additional or different terms or conditions on, or\n               apply any Effective Technological Measures to, the\n               Licensed Material if doing so restricts exercise of the\n               Licensed Rights by any recipient of the Licensed\n               Material.\n\n       6. No endorsement. Nothing in this Public License constitutes or\n          may be construed as permission to assert or imply that You\n          are, or that Your use of the Licensed Material is, connected\n          with, or sponsored, endorsed, or granted official status by,\n          the Licensor or others designated to receive attribution as\n          provided in Section 3(a)(1)(A)(i).\n\n  b. Other rights.\n\n       1. Moral rights, such as the right of integrity, are not\n          licensed under this Public License, nor are publicity,\n          privacy, and/or other similar personality rights; however, to\n          the extent possible, the Licensor waives and/or agrees not to\n          assert any such rights held by the Licensor to the limited\n          extent necessary to allow You to exercise the Licensed\n          Rights, but not otherwise.\n\n       2. Patent and trademark rights are not licensed under this\n          Public License.\n\n       3. To the extent possible, the Licensor waives any right to\n          collect royalties from You for the exercise of the Licensed\n          Rights, whether directly or through a collecting society\n          under any voluntary or waivable statutory or compulsory\n          licensing scheme. In all other cases the Licensor expressly\n          reserves any right to collect such royalties.\n\n\nSection 3 -- License Conditions.\n\nYour exercise of the Licensed Rights is expressly made subject to the\nfollowing conditions.\n\n  a. Attribution.\n\n       1. If You Share the Licensed Material (including in modified\n          form), You must:\n\n            a. retain the following if it is supplied by the Licensor\n               with the Licensed Material:\n\n                 i. identification of the creator(s) of the Licensed\n                    Material and any others designated to receive\n                    attribution, in any reasonable manner requested by\n                    the Licensor (including by pseudonym if\n                    designated);\n\n                ii. a copyright notice;\n\n               iii. a notice that refers to this Public License;\n\n                iv. a notice that refers to the disclaimer of\n                    warranties;\n\n                 v. a URI or hyperlink to the Licensed Material to the\n                    extent reasonably practicable;\n\n            b. indicate if You modified the Licensed Material and\n               retain an indication of any previous modifications; and\n\n            c. indicate the Licensed Material is licensed under this\n               Public License, and include the text of, or the URI or\n               hyperlink to, this Public License.\n\n       2. You may satisfy the conditions in Section 3(a)(1) in any\n          reasonable manner based on the medium, means, and context in\n          which You Share the Licensed Material. For example, it may be\n          reasonable to satisfy the conditions by providing a URI or\n          hyperlink to a resource that includes the required\n          information.\n\n       3. If requested by the Licensor, You must remove any of the\n          information required by Section 3(a)(1)(A) to the extent\n          reasonably practicable.\n\n       4. If You Share Adapted Material You produce, the Adapter's\n          License You apply must not prevent recipients of the Adapted\n          Material from complying with this Public License.\n\n\nSection 4 -- Sui Generis Database Rights.\n\nWhere the Licensed Rights include Sui Generis Database Rights that\napply to Your use of the Licensed Material:\n\n  a. for the avoidance of doubt, Section 2(a)(1) grants You the right\n     to extract, reuse, reproduce, and Share all or a substantial\n     portion of the contents of the database;\n\n  b. if You include all or a substantial portion of the database\n     contents in a database in which You have Sui Generis Database\n     Rights, then the database in which You have Sui Generis Database\n     Rights (but not its individual contents) is Adapted Material; and\n\n  c. You must comply with the conditions in Section 3(a) if You Share\n     all or a substantial portion of the contents of the database.\n\nFor the avoidance of doubt, this Section 4 supplements and does not\nreplace Your obligations under this Public License where the Licensed\nRights include other Copyright and Similar Rights.\n\n\nSection 5 -- Disclaimer of Warranties and Limitation of Liability.\n\n  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE\n     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS\n     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF\n     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,\n     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,\n     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR\n     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,\n     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT\n     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT\n     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.\n\n  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE\n     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,\n     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,\n     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,\n     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR\n     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN\n     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR\n     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR\n     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.\n\n  c. The disclaimer of warranties and limitation of liability provided\n     above shall be interpreted in a manner that, to the extent\n     possible, most closely approximates an absolute disclaimer and\n     waiver of all liability.\n\n\nSection 6 -- Term and Termination.\n\n  a. This Public License applies for the term of the Copyright and\n     Similar Rights licensed here. However, if You fail to comply with\n     this Public License, then Your rights under this Public License\n     terminate automatically.\n\n  b. Where Your right to use the Licensed Material has terminated under\n     Section 6(a), it reinstates:\n\n       1. automatically as of the date the violation is cured, provided\n          it is cured within 30 days of Your discovery of the\n          violation; or\n\n       2. upon express reinstatement by the Licensor.\n\n     For the avoidance of doubt, this Section 6(b) does not affect any\n     right the Licensor may have to seek remedies for Your violations\n     of this Public License.\n\n  c. For the avoidance of doubt, the Licensor may also offer the\n     Licensed Material under separate terms or conditions or stop\n     distributing the Licensed Material at any time; however, doing so\n     will not terminate this Public License.\n\n  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public\n     License.\n\n\nSection 7 -- Other Terms and Conditions.\n\n  a. The Licensor shall not be bound by any additional or different\n     terms or conditions communicated by You unless expressly agreed.\n\n  b. Any arrangements, understandings, or agreements regarding the\n     Licensed Material not stated herein are separate from and\n     independent of the terms and conditions of this Public License.\n\n\nSection 8 -- Interpretation.\n\n  a. For the avoidance of doubt, this Public License does not, and\n     shall not be interpreted to, reduce, limit, restrict, or impose\n     conditions on any use of the Licensed Material that could lawfully\n     be made without permission under this Public License.\n\n  b. To the extent possible, if any provision of this Public License is\n     deemed unenforceable, it shall be automatically reformed to the\n     minimum extent necessary to make it enforceable. If the provision\n     cannot be reformed, it shall be severed from this Public License\n     without affecting the enforceability of the remaining terms and\n     conditions.\n\n  c. No term or condition of this Public License will be waived and no\n     failure to comply consented to unless expressly agreed to by the\n     Licensor.\n\n  d. Nothing in this Public License constitutes or may be interpreted\n     as a limitation upon, or waiver of, any privileges and immunities\n     that apply to the Licensor or You, including from the legal\n     processes of any jurisdiction or authority.\n\n\n=======================================================================\n\nCreative Commons is not a party to its public\nlicenses. Notwithstanding, Creative Commons may elect to apply one of\nits public licenses to material it publishes and in those instances\nwill be considered the “Licensor.” The text of the Creative Commons\npublic licenses is dedicated to the public domain under the CC0 Public\nDomain Dedication. Except for the limited purpose of indicating that\nmaterial is shared under a Creative Commons public license or as\notherwise permitted by the Creative Commons policies published at\ncreativecommons.org/policies, Creative Commons does not authorize the\nuse of the trademark \"Creative Commons\" or any other trademark or logo\nof Creative Commons without its prior written consent including,\nwithout limitation, in connection with any unauthorized modifications\nto any of its public licenses or any other arrangements,\nunderstandings, or agreements concerning use of licensed material. For\nthe avoidance of doubt, this paragraph does not form part of the\npublic licenses.\n\nCreative Commons may be contacted at creativecommons.org.\n\n"
  },
  {
    "path": "Packaging/resources/LICENSE.OFL.txt",
    "content": "This Font Software is Copyright (c) 1997-2009, SIL International (https://scripts.sil.org/)\r\nwith Reserved Font Names \"Charis\" and \"SIL\".\r\n\r\nThis Font Software is licensed under the SIL Open Font License, Version 1.1.\r\nThis license is copied below, and is also available with a FAQ at:\r\nhttps://scripts.sil.org/OFL\r\n\r\n\r\n-----------------------------------------------------------\r\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\r\n-----------------------------------------------------------\r\n\r\nPREAMBLE\r\nThe goals of the Open Font License (OFL) are to stimulate worldwide\r\ndevelopment of collaborative font projects, to support the font creation\r\nefforts of academic and linguistic communities, and to provide a free and\r\nopen framework in which fonts may be shared and improved in partnership\r\nwith others.\r\n\r\nThe OFL allows the licensed fonts to be used, studied, modified and\r\nredistributed freely as long as they are not sold by themselves. The\r\nfonts, including any derivative works, can be bundled, embedded, \r\nredistributed and/or sold with any software provided that any reserved\r\nnames are not used by derivative works. The fonts and derivatives,\r\nhowever, cannot be released under any other type of license. The\r\nrequirement for fonts to remain under this license does not apply\r\nto any document created using the fonts or their derivatives.\r\n\r\nDEFINITIONS\r\n\"Font Software\" refers to the set of files released by the Copyright\r\nHolder(s) under this license and clearly marked as such. This may\r\ninclude source files, build scripts and documentation.\r\n\r\n\"Reserved Font Name\" refers to any names specified as such after the\r\ncopyright statement(s).\r\n\r\n\"Original Version\" refers to the collection of Font Software components as\r\ndistributed by the Copyright Holder(s).\r\n\r\n\"Modified Version\" refers to any derivative made by adding to, deleting,\r\nor substituting -- in part or in whole -- any of the components of the\r\nOriginal Version, by changing formats or by porting the Font Software to a\r\nnew environment.\r\n\r\n\"Author\" refers to any designer, engineer, programmer, technical\r\nwriter or other person who contributed to the Font Software.\r\n\r\nPERMISSION & CONDITIONS\r\nPermission is hereby granted, free of charge, to any person obtaining\r\na copy of the Font Software, to use, study, copy, merge, embed, modify,\r\nredistribute, and sell modified and unmodified copies of the Font\r\nSoftware, subject to the following conditions:\r\n\r\n1) Neither the Font Software nor any of its individual components,\r\nin Original or Modified Versions, may be sold by itself.\r\n\r\n2) Original or Modified Versions of the Font Software may be bundled,\r\nredistributed and/or sold with any software, provided that each copy\r\ncontains the above copyright notice and this license. These can be\r\nincluded either as stand-alone text files, human-readable headers or\r\nin the appropriate machine-readable metadata fields within text or\r\nbinary files as long as those fields can be easily viewed by the user.\r\n\r\n3) No Modified Version of the Font Software may use the Reserved Font\r\nName(s) unless explicit written permission is granted by the corresponding\r\nCopyright Holder. This restriction only applies to the primary font name as\r\npresented to the users.\r\n\r\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\r\nSoftware shall not be used to promote, endorse or advertise any\r\nModified Version, except to acknowledge the contribution(s) of the\r\nCopyright Holder(s) and the Author(s) or with their explicit written\r\npermission.\r\n\r\n5) The Font Software, modified or unmodified, in part or in whole,\r\nmust be distributed entirely under this license, and must not be\r\ndistributed under any other license. The requirement for fonts to\r\nremain under this license does not apply to any document created\r\nusing the Font Software.\r\n\r\nTERMINATION\r\nThis license becomes null and void if any of the above conditions are\r\nnot met.\r\n\r\nDISCLAIMER\r\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\r\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\r\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\r\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\r\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\r\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\r\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM\r\nOTHER DEALINGS IN THE FONT SOFTWARE.\r\n"
  },
  {
    "path": "Packaging/resources/LICENSE.zlib.txt",
    "content": "The source code to this library used with SDL_ttf can be found here:\nhttps://github.com/libsdl-org/SDL_image/tree/main/external\n---\n\nCopyright notice:\n\n (C) 1995-2010 Jean-loup Gailly and Mark Adler\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  Jean-loup Gailly        Mark Adler\n  jloup@gzip.org          madler@alumni.caltech.edu\n\nIf you use the zlib library in a product, we would appreciate *not* receiving\nlengthy legal documents to sign.  The sources are provided for free but without\nwarranty of any kind.  The library has been entirely written by Jean-loup\nGailly and Mark Adler; it does not include third-party code.\n"
  },
  {
    "path": "Packaging/resources/README-SDL.txt",
    "content": "\nPlease distribute this file with the SDL runtime environment:\n\nThe Simple DirectMedia Layer (SDL for short) is a cross-platform library\ndesigned to make it easy to write multi-media software, such as games\nand emulators.\n\nThe Simple DirectMedia Layer library source code is available from:\nhttps://www.libsdl.org/\n\nThis library is distributed under the terms of the zlib license:\nhttps://www.zlib.net/zlib_license.html\n\n"
  },
  {
    "path": "Packaging/switch/README.txt",
    "content": "# Nintendo Switch Port of DevilutionX (Diablo)\r\n\r\n# How To Install:\r\n - Put `devilutionx.nro` into `/switch/devilutionx`\r\n - Copy diabdat.mpq from your CD (or GoG install folder) to `/switch/devilutionx`.\r\n - To run the Diablo: Hellfire expansion you will need to also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq.\r\n - For Chinese, Japanese, and Korean text support download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq and add it to the game folder.\r\n - For the Polish voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq.\r\n - For the Russian voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq.\r\n - Launch `devilutionx.nro`. (Do not use album to launch; see the note below.)\r\n - *Note:* Hold R on any installed game and launch it. Do not use album to launch. If you use album, the homebrew will only have a small amount memory available, and the touch keyboard won't work. This is true for all homebrew, not just DevilutionX.\r\n\r\n# Joycon Controls\r\n- Left analog or D-Pad: move hero\r\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\r\n- B: select spell, back while in menus\r\n- X: pickup items, open nearby chests and doors, use item in the inventory\r\n- Y: cast spell, delete character while in main menu\r\n- L: use health item from belt\r\n- R: use mana potion from belt\r\n- ZL: character sheet (alt: Start + L1 or ←)\r\n- ZR: inventory (alt: Start + L2 or →)\r\n- Left analog click: toggle automap (alt: Start + ↓)\r\n- Start + Select: game menu (alt: Start + ↑)\r\n- Select + A/B/X/Y: Spell hotkeys\r\n- Right analog: move automap or simulate mouse\r\n- Right analog click or Select + L: left mouse click\r\n- Select + Right analog click: right mouse click (alt: Select + R1)\r\n- Select + L2: quest log (alt: Start + Y)\r\n- Select + R2: spell book (alt: Start + B)\r\n\r\n# Credits\r\n - See list of contributors https://github.com/diasurgical/devilutionX/graphs/contributors\r\n\r\n# Links\r\nDiscord: https://discord.gg/devilutionx\r\nGitHub: https://github.com/diasurgical/devilutionX\r\n\r\nCheck out the manual for what features are available and how best to take advantage of them: https://github.com/diasurgical/devilutionX/wiki\r\nFor a full list of changes see our changelog: https://github.com/diasurgical/devilutionX/blob/master/docs/CHANGELOG.md\r\n\r\n# Legal\r\nDevilutionX is released to the Public Domain. The documentation and functionality provided by DevilutionX may only be utilized with assets provided by ownership of Diablo.\r\n\r\nThe source code in this repository is for non-commercial use only. If you use the source code you may not charge others for access to it or any derivative work thereof.\r\n\r\nDiablo® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\r\n\r\nDevilutionX and any of its maintainers are in no way associated with or endorsed by Blizzard Entertainment®.\r\n"
  },
  {
    "path": "Packaging/switch/packages.txt",
    "content": "switch-mesa\r\nswitch-glad\r\nswitch-glm\r\nswitch-libpng\r\nswitch-sdl2\r\nswitch-libsodium\r\nlibnx\r\ndevkitA64\r\ngeneral-tools\r\nswitch-tools\r\nswitch-bzip2\r\n"
  },
  {
    "path": "Packaging/vita/README.txt",
    "content": "# devilutionX PS Vita port\r\n\r\n## How To Play:\r\n - Install VPK\r\n - Copy diabdat.mpq from your CD or GoG installation (or [extract it from the GoG installer](https://github.com/diasurgical/devilutionX/wiki/Extracting-the-.MPQs-from-the-GoG-installer)) to the `ux0:/data/diasurgical/devilution/`.\r\n - For Chinese, Japanese, and Korean text support download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq and add it to the game folder.\r\n - For the Polish voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq.\r\n - For the Russian voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq.\r\n\r\n# Building from Source\r\n\r\n```\r\ncd build\r\ncmake -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..\r\nmake\r\n```\r\n\r\n# Multiplayer\r\n - Not supported yet\r\n\r\n# Controls\r\n\r\n## Default\r\n\r\n- Left analog or D-Pad: move hero\r\n- ○: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\r\n- ×: select spell, back while in menus\r\n- △: pickup items, open nearby chests and doors, use item in the inventory\r\n- □: cast spell, delete character while in main menu\r\n- L1: use health item from belt\r\n- R1: use mana potion from belt\r\n- Left back touch panel: character sheet (alt: Start + ←, alt: L2 on ds4)\r\n- Right back touch panel: inventory (alt: Start + →, alt: R2 on ds4)\r\n- Start + ↓: toggle automap\r\n- Start + Select: game menu (alt: Start + ↑)\r\n- Select + ×/○/□/△: Spell hotkeys\r\n- Right analog: move automap or simulate mouse\r\n- Select + L1: left mouse click\r\n- Select + R1: right mouse click\r\n- Start + □: quest log\r\n- Start + △: spell book\r\n\r\n## Options\r\n\r\nThere's special section `controls` in diablo.ini file, that allows you to adjust controls:\r\n```\r\n[controls]\r\nswitch_potions_and_clicks=0\r\ndpad_hotkeys=0\r\nenable_second_touchscreen=1\r\nsdl2_controller_mapping=50535669746120436f6e74726f6c6c65,PSVita Controller,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,leftstick:b14,rightstick:b15,\r\n```\r\n\r\n- **dpad_hotkeys:** dpad works as hotkeys without holding Start button\r\n- **switch_potions_and_clicks:** L1/R1 works as left/right mouse clicks by debault, and as health/mana potion while holding Select\r\n- **sdl2_controller_mapping:** allows you to remap controls. It uses https://github.com/gabomdq/SDL_GameControllerDB syntax\r\n- **enable_second_touchscreen:** enable/disable back touch mapping to L2/R2\r\n"
  },
  {
    "path": "Packaging/vita/sce_sys/livearea/contents/template.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n\r\n<livearea style=\"psmobile\" format-ver=\"01.00\" content-rev=\"1\">\r\n \r\n\t<livearea-background>\r\n    \t<image>bg.png</image>\r\n\t</livearea-background>\r\n\r\n\t<gate>\r\n\t\t<startup-image>startup.png</startup-image>\r\n\t</gate>\r\n\r\n\t<frame id=\"frame1\">\r\n\t\t<liveitem>\r\n\t\t\t<image>logo0.png</image>\r\n\t\t</liveitem>\r\n\t</frame>\r\n\r\n\t<frame id=\"frame2\">\r\n\t\t<liveitem>\r\n\t\t\t<text valign=\"bottom\" align=\"left\" text-align=\"left\" text-valign=\"bottom\" line-space=\"3\" ellipsis=\"on\">\r\n\t\t\t\t<str color=\"#ffffff\" size=\"30\" bold=\"on\" shadow=\"on\">devilutionX</str>\r\n\t\t\t</text>\r\n\t\t</liveitem>\r\n\t</frame>\r\n</livearea>"
  },
  {
    "path": "Packaging/windows/CMakePresets.json",
    "content": "{\r\n\t\"version\": 3,\r\n\t\"cmakeMinimumRequired\": {\r\n\t\t\"major\": 3,\r\n\t\t\"minor\": 19,\r\n\t\t\"patch\": 0\r\n\t},\r\n\t\"configurePresets\": [\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg\",\r\n\t\t\t\"displayName\": \"Ninja with VcPkg Configure Settings\",\r\n\t\t\t\"description\": \"Configure with vcpkg toolchain\",\r\n\t\t\t\"binaryDir\": \"${sourceDir}/build-${presetName}\",\r\n\t\t\t\"generator\": \"Ninja\",\r\n\t\t\t\"cacheVariables\": {\r\n\t\t\t\t\"CMAKE_TOOLCHAIN_FILE\": {\r\n\t\t\t\t\t\"type\": \"FILEPATH\",\r\n\t\t\t\t\t\"value\": \"$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\"\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-debug\",\r\n\t\t\t\"displayName\": \"Ninja with VcPkg Configure Settings with CMAKE_BUILD_TYPE=Debug\",\r\n\t\t\t\"inherits\": \"ninja-vcpkg\",\r\n\t\t\t\"cacheVariables\": {\r\n\t\t\t\t\"CMAKE_BUILD_TYPE\": \"Debug\"\r\n\t\t\t}\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-relwithdebinfo\",\r\n\t\t\t\"displayName\": \"Ninja with VcPkg Configure Settings with CMAKE_BUILD_TYPE=RelWithDebInfo\",\r\n\t\t\t\"inherits\": \"ninja-vcpkg\",\r\n\t\t\t\"cacheVariables\": {\r\n\t\t\t\t\"CMAKE_BUILD_TYPE\": \"RelWithDebInfo\",\r\n\t\t\t\t\"DISABLE_LTO\": {\r\n\t\t\t\t\t\"type\": \"BOOL\",\r\n\t\t\t\t\t\"value\": \"ON\"\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-discord-relwithdebinfo\",\r\n\t\t\t\"displayName\": \"Ninja with VcPkg Configure Settings with DISCORD_INTEGRATION=ON CMAKE_BUILD_TYPE=RelWithDebInfo\",\r\n\t\t\t\"inherits\": \"ninja-vcpkg-relwithdebinfo\",\r\n\t\t\t\"cacheVariables\": {\r\n\t\t\t\t\"DISCORD_INTEGRATION\": {\r\n\t\t\t\t\t\"type\": \"BOOL\",\r\n\t\t\t\t\t\"value\": \"ON\"\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t],\r\n\t\"buildPresets\": [\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-debug\",\r\n\t\t\t\"configurePreset\": \"ninja-vcpkg-debug\",\r\n\t\t\t\"displayName\": \"Build ninja-vcpkg-debug\",\r\n\t\t\t\"description\": \"Build ninja-vcpkg-debug Configuration\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-relwithdebinfo\",\r\n\t\t\t\"configurePreset\": \"ninja-vcpkg-relwithdebinfo\",\r\n\t\t\t\"displayName\": \"Build ninja-vcpkg-relwithdebinfo\",\r\n\t\t\t\"description\": \"Build ninja-vcpkg-relwithdebinfo Configuration\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-discord-relwithdebinfo\",\r\n\t\t\t\"configurePreset\": \"ninja-vcpkg-discord-relwithdebinfo\",\r\n\t\t\t\"displayName\": \"Build ninja-vcpkg-discord-relwithdebinfo\",\r\n\t\t\t\"description\": \"Build ninja-vcpkg-discord-relwithdebinfo Configuration\"\r\n\t\t}\r\n\t],\r\n\t\"testPresets\": [\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-debug\",\r\n\t\t\t\"configurePreset\": \"ninja-vcpkg-debug\",\r\n\t\t\t\"output\": {\"outputOnFailure\": true}\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-relwithdebinfo\",\r\n\t\t\t\"configurePreset\": \"ninja-vcpkg-relwithdebinfo\",\r\n\t\t\t\"output\": {\"outputOnFailure\": true}\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"name\": \"ninja-vcpkg-discord-relwithdebinfo\",\r\n\t\t\t\"configurePreset\": \"ninja-vcpkg-discord-relwithdebinfo\",\r\n\t\t\t\"output\": {\"outputOnFailure\": true}\r\n\t\t}\r\n\t]\r\n}\r\n"
  },
  {
    "path": "Packaging/windows/README.txt",
    "content": "# DevilutionX\r\nDevilutionX is a source port of Diablo and Hellfire that strives to make it simple to run the game while providing engine improvements, bugfixes, and some optional quality of life features.\r\n\r\n# Links\r\nDiscord: https://discord.gg/devilutionx\r\nGitHub: https://github.com/diasurgical/devilutionX\r\n\r\nCheck out the manual for what features are available and how best to take advantage of them: https://github.com/diasurgical/devilutionX/wiki\r\nFor a full list of changes see our changelog: https://github.com/diasurgical/devilutionX/blob/master/docs/CHANGELOG.md\r\n\r\n# How To Install:\r\n - Extract the files in the zip\r\n - Copy DIABDAT.MPQ from the CD or GOG-installation (or extract it from the GoG installer) to the DevilutionX folder.\r\n - To run the Diablo: Hellfire expansion you will need to also copy hellfire.mpq, hfmonk.mpq, hfmusic.mpq, hfvoice.mpq.\r\n - For Chinese, Japanese, and Korean text support download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq and add it to the game folder.\r\n - For the Polish voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq.\r\n - For the Russian voice pack download https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq.\r\n - Run devilutionx.exe\r\n\r\n# Multiplayer\r\n - TCP/IP requires the host to expose port 6112.\r\n\r\nAll games are encrypted and password protected.\r\n\r\n# Save Games and configurations\r\nThe configurations and save games are located in:\r\nC:\\Users\\[username]\\AppData\\Roaming\\diasurgical\\devilution\r\n\r\n# Credits\r\n - See list of contributors https://github.com/diasurgical/devilutionX/graphs/contributors\r\n\r\n# Legal\r\nThis software is being released to the Public Domain. No assets of Diablo are being provided. You must own a copy of Diablo and have access to the assets beforehand in order to use this software.\r\n\r\nBattle.net® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Battle.net and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\r\n\r\nDiablo® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\r\n\r\nThis software is in no way associated with or endorsed by Blizzard Entertainment®.\r\n"
  },
  {
    "path": "Packaging/windows/devilutionx.exe.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\" xmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\">\n\t<asmv3:application>\n\t\t<asmv3:windowsSettings>\n\t\t\t<dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">true/pm</dpiAware>\n\t\t</asmv3:windowsSettings>\n\t</asmv3:application>\n</assembly>\n"
  },
  {
    "path": "Packaging/windows/devilutionx.rc",
    "content": "#ifdef __MINGW32__\r\n#include \"winuser.h\"\r\n#define MANIFEST_RESOURCE_ID 1\r\nMANIFEST_RESOURCE_ID RT_MANIFEST \"devilutionx.exe.manifest\"\r\n#endif\r\n\r\nIDI_ICON1               ICON    DISCARDABLE     \"icon.ico\"\r\n"
  },
  {
    "path": "Packaging/windows/dos-prep.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\nINSTALL_PREFIX=/opt/i386-pc-msdosdjgpp-toolchain\n\n# only use sudo when necessary\nif [ `id -u` -ne 0 ]; then\n\tSUDO=sudo\nelse\n\tSUDO=\"\"\nfi\n\n# Install dependencies on Debian / Ubuntu:\ninstall_system_deps() {\n\tif which apt-get 2>/dev/null; then\n\t\tset -x\n\t\t$SUDO apt-get update\n\t\t$SUDO apt-get install bison flex curl gcc g++ make texinfo zlib1g-dev tar bzip2 \\\n\t\t\tgzip xz-utils unzip python3-dev m4 dos2unix nasm cmake\n\t\t{ set +x; } 2>/dev/null\n\tfi\n}\n\n# Build and install DJGPP\nbuild_and_install_djgpp() {\n\tgit clone https://github.com/jwt27/build-gcc.git\n\tcd build-gcc\n\t$SUDO ./build-djgpp.sh --prefix=\"$INSTALL_PREFIX\" --batch binutils gcc-14.2.0 djgpp-cvs\n\tcd -\n\t$SUDO rm -rf build-gcc\n}\n\nmain() {\n\tset -x\n\tmkdir -p tmp/dos-prep\n\tcd tmp/dos-prep\n\tinstall_system_deps\n\tbuild_and_install_djgpp\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "Packaging/windows/mingw-prep.sh",
    "content": "#!/usr/bin/env bash\n\nSDLDEV_VERS=2.32.0\nSODIUM_VERS=1.0.20\n\n# exit when any command fails\nset -euo pipefail\n\n# detect architecture from script name\nif echo \"$(basename $0)\" | grep -q 64; then\n    MINGW_ARCH=x86_64-w64-mingw32\n    SODIUM_ARCH=win64\nelse\n    MINGW_ARCH=i686-w64-mingw32\n    SODIUM_ARCH=win32\nfi\n\n# set MINGW_PREFIX\nMINGW_PREFIX=/usr/${MINGW_ARCH}\nif [ ! -d \"${MINGW_PREFIX}\" ]; then\n    echo \"MinGW prefix not found (${MINGW_PREFIX})\"\n    exit 1\nelse\n    echo \"Installing to ${MINGW_PREFIX}\"\nfi\n\n# only use sudo when necessary\nif [ `id -u` -ne 0 ]; then\n    SUDO=sudo\nelse\n    SUDO=\"\"\nfi\n\nrm -rf \"tmp-mingw-${MINGW_ARCH}-prep\"\nmkdir -p \"tmp-mingw-${MINGW_ARCH}-prep\"\ncd \"tmp-mingw-${MINGW_ARCH}-prep\"\n\nwget -q https://www.libsdl.org/release/SDL2-devel-${SDLDEV_VERS}-mingw.tar.gz -OSDL2-devel-${SDLDEV_VERS}-mingw.tar.gz\ntar -xzf SDL2-devel-${SDLDEV_VERS}-mingw.tar.gz\nsed -i '/$(CROSS_PATH)\\/cmake/ s/^/#/' SDL2*/Makefile\n$SUDO make -C SDL2*/ cross CROSS_PATH=/usr ARCHITECTURES=${MINGW_ARCH}\n\nwget -q https://github.com/jedisct1/libsodium/releases/download/${SODIUM_VERS}-RELEASE/libsodium-${SODIUM_VERS}-mingw.tar.gz -Olibsodium-${SODIUM_VERS}-mingw.tar.gz\ntar -xzf libsodium-${SODIUM_VERS}-mingw.tar.gz --no-same-owner\n$SUDO cp -r libsodium-${SODIUM_ARCH}/* ${MINGW_PREFIX}\n\n# Fixup pkgconfig prefix:\nfind \"${MINGW_PREFIX}/lib/pkgconfig/\" -name '*.pc' -exec \\\n  $SUDO sed -i \"s|^prefix=.*|prefix=${MINGW_PREFIX}|\" '{}' \\;\n\n# Fixup CMake prefix:\nfind \"${MINGW_PREFIX}\" -name '*.cmake' -exec \\\n  $SUDO sed -i \"s|/opt/local/${MINGW_ARCH}|${MINGW_PREFIX}|\" '{}' \\;\n\n# Fixup zlib linking:\n$SUDO mv \"${MINGW_PREFIX}/lib/libz.dll.a\" \"${MINGW_PREFIX}/lib/libz.dll.a.bak\"\n"
  },
  {
    "path": "Packaging/windows/mingw9x-prep.sh",
    "content": "#!/usr/bin/env bash\n\nSDLDEV_VERS=1.2.15\nSODIUM_VERS=1.0.20\n\n# exit when any command fails\nset -euo pipefail\n\nMINGW_ARCH=i686-w64-mingw32\nSODIUM_ARCH=win32\n\n# set MINGW_PREFIX\nMINGW_PREFIX=/usr/${MINGW_ARCH}\nif [ ! -d \"${MINGW_PREFIX}\" ]; then\n    echo \"MinGW prefix not found (${MINGW_PREFIX})\"\n    exit 1\nelse\n    echo \"Installing to ${MINGW_PREFIX}\"\nfi\n\n# only use sudo when necessary\nif [ `id -u` -ne 0 ]; then\n    SUDO=sudo\nelse\n    SUDO=\"\"\nfi\n\nrm -rf tmp-mingw9x-prep\nmkdir -p tmp-mingw9x-prep\ncd tmp-mingw9x-prep\n\ncurl --no-progress-meter -OL https://www.libsdl.org/release/SDL-devel-${SDLDEV_VERS}-mingw32.tar.gz\ntar -xzf SDL-devel-${SDLDEV_VERS}-mingw32.tar.gz\n$SUDO cp -r SDL-*/include/* ${MINGW_PREFIX}/include\n$SUDO cp -r SDL-*/lib/* ${MINGW_PREFIX}/lib\n$SUDO cp -r SDL-*/bin/* ${MINGW_PREFIX}/bin\n\nwget -q https://github.com/jedisct1/libsodium/releases/download/${SODIUM_VERS}-RELEASE/libsodium-${SODIUM_VERS}-mingw.tar.gz -Olibsodium-${SODIUM_VERS}-mingw.tar.gz\ntar -xzf libsodium-${SODIUM_VERS}-mingw.tar.gz --no-same-owner\n$SUDO cp -r libsodium-${SODIUM_ARCH}/* ${MINGW_PREFIX}\n\n# Fixup pkgconfig prefix:\nfind \"${MINGW_PREFIX}/lib/pkgconfig/\" -name '*.pc' -exec \\\n  $SUDO sed -i \"s|^prefix=.*|prefix=${MINGW_PREFIX}|\" '{}' \\;\n\n# Fixup CMake prefix:\nfind \"${MINGW_PREFIX}\" -name '*.cmake' -exec \\\n  $SUDO sed -i \"s|/opt/local/${MINGW_ARCH}|${MINGW_PREFIX}|\" '{}' \\;\n"
  },
  {
    "path": "Packaging/xbox-one/build.bat",
    "content": "call VsDevCmd.bat\r\n\r\nmkdir ..\\..\\build\r\ncd ..\\..\\build\r\n\r\ngit clone --branch SDL2 https://github.com/libsdl-org/SDL.git\r\ngit -C SDL reset --hard 10135b2d7bbed6ea0cba24410ebc12887d92968d\r\nmsbuild /p:PlatformToolset=v143;TargetPlatformVersion=10.0.26100.0;TargetPlatformMinVersion=10.0.14393.0;ConfigurationType=StaticLibrary;Configuration=Release;Platform=x64 SDL\\VisualC-WinRT\\SDL-UWP.vcxproj\r\n\r\ncmake -DUWP_LIB=1 -DUWP_SDL2_DIR=\"%CD%/SDL\" -DCMAKE_BUILD_TYPE=x64-Release ..\r\n\r\nmsbuild /p:Configuration=Release;Platform=x64 /m DevilutionX.sln\r\n\r\npowershell \"Get-Content ..\\uwp-project\\Package.appxmanifest.template | %% {$_ -replace '__PROJECT_VERSION__',$(Select-String -Path ..\\VERSION -Pattern \\d+\\.\\d+\\.\\d+).Matches[0].Value} | Out-File -FilePath ..\\uwp-project\\Package.appxmanifest -encoding ASCII\"\r\n\r\nmsbuild /p:Configuration=Release;Platform=x64;AppxBundle=Always;AppxBundlePlatforms=x64 /m ..\\uwp-project\\devilutionx.sln\r\n\r\npowershell \"Get-Childitem -Path uwp-project\\AppxPackages, uwp-project\\Release -Include Microsoft.VCLibs.x64.*.appx, devilutionX_*_x64.appx -File -Recurse | Compress-Archive -DestinationPath ..\\devilutionx.zip\"\r\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img width=\"560\" height=\"144\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7ac73801-ef7b-4cc1-8442-a191a2a0a1ce\" />\n</p>\n\n---\n\n[![Discord Channel](https://img.shields.io/discord/518540764754608128?color=%237289DA&logo=discord&logoColor=%23FFFFFF)](https://discord.gg/devilutionx)\n[![Downloads](https://img.shields.io/github/downloads/diasurgical/devilutionX/total.svg)](https://github.com/diasurgical/devilutionX/releases/latest)\n[![Codecov](https://codecov.io/gh/diasurgical/devilutionX/branch/master/graph/badge.svg)](https://codecov.io/gh/diasurgical/devilutionX)\n\n<p align=\"center\">\n<img width=\"853\" height=\"480\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ee902926-6382-4ee5-b1c2-7947e8b434e9\" />\n</p>\n\n<sub>*(The health-bar and XP-bar are off by default but can be enabled in the [game settings](https://github.com/diasurgical/DevilutionX/wiki/Config-File). Widescreen can also be disabled if preferred.)*</sub>\n\n# What is DevilutionX\n\nDevilutionX is a port of Diablo and Hellfire that strives to make it simple to run the game while providing engine improvements, bug fixes, and some optional quality of life features.\n\nCheck out the [manual](https://github.com/diasurgical/devilutionX/wiki) for available features and how to take advantage of them.\n\nFor a full list of changes, see our [changelog](docs/CHANGELOG.md).\n\n# How to Install\n\nNote: You'll need access to the data from the original game. If you don't have an original CD, you can [buy Diablo from GoG.com](https://www.gog.com/game/diablo) or Battle.net. Alternatively, you can use `spawn.mpq` from the [shareware](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/spawn.mpq) [[2]](http://ftp.blizzard.com/pub/demos/diablosw.exe) version, in place of `DIABDAT.MPQ`, to play the shareware portion of the game.\n\nDownload the latest [DevilutionX release](https://github.com/diasurgical/devilutionX/releases/latest) and extract the contents to a location of your choosing or [build from source](#building-from-source).\n\n- Copy `DIABDAT.MPQ` from the CD or Diablo installation (or [extract it from the GoG installer](https://github.com/diasurgical/devilutionX/wiki/Extracting-MPQs-from-the-GoG-installer)) to the DevilutionX folder.\n- To run the Diablo: Hellfire expansion, you will also need to copy `hellfire.mpq`, `hfmonk.mpq`, `hfmusic.mpq`, and `hfvoice.mpq`.\n\nFor more detailed instructions: [Installation Instructions](./docs/installing.md).\n\n# Contributing\n\nWe are always looking for more people to help with [coding](docs/CONTRIBUTING.md), [documentation](https://github.com/diasurgical/devilutionX/wiki), [testing the latest builds](#test-builds), spreading the word, or simply just hanging out on our [Discord server](https://discord.gg/devilutionx).\n\n# Mods\n\nWe hope to provide a good starting point for mods. In addition to the full Devilution source code, we also provide modding tools. Check out the list of known [mods based on DevilutionX](https://github.com/diasurgical/devilutionX/wiki/Mods).\n\n# Test Builds\n\nIf you want to help test the latest development version (make sure to back up your files, as these may contain bugs), you can fetch the test build artifact from one of the build servers:\n\n*Note: You must be logged into GitHub to download the attachments!*\n\n[![Linux x86_64](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_x86_64.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_x86_64.yml?query=branch%3Amaster)\n[![Linux AArch64](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_aarch64.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_aarch64.yml?query=branch%3Amaster)\n[![Linux x86](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_x86.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_x86.yml?query=branch%3Amaster)\n[![Linux x86_64 SDL1](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_x86_64_SDL1.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Linux_x86_64_SDL1.yml?query=branch%3Amaster)\n[![macOS x86_64](https://github.com/diasurgical/devilutionX/actions/workflows/macOS_x86_64.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/macOS_x86_64.yml?query=branch%3Amaster)\n[![Windows MinGW x64](https://github.com/diasurgical/devilutionX/actions/workflows/Windows_MinGW_x64.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Windows_MinGW_x64.yml?query=branch%3Amaster)\n[![Windows MinGW x86](https://github.com/diasurgical/devilutionX/actions/workflows/Windows_MinGW_x86.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Windows_MinGW_x86.yml?query=branch%3Amaster)\n[![Windows MSVC x64](https://github.com/diasurgical/devilutionX/actions/workflows/Windows_MSVC_x64.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Windows_MSVC_x64.yml?query=branch%3Amaster)\n[![Android](https://github.com/diasurgical/devilutionX/actions/workflows/Android.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/Android.yml?query=branch%3Amaster)\n[![iOS](https://github.com/diasurgical/devilutionX/actions/workflows/iOS.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/iOS.yml?query=branch%3Amaster)\n[![PS4](https://github.com/diasurgical/devilutionX/actions/workflows/PS4.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/PS4.yml?query=branch%3Amaster)\n[![Original Xbox](https://github.com/diasurgical/devilutionX/actions/workflows/xbox_nxdk.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/xbox_nxdk.yml?query=branch%3Amaster)\n[![Xbox One/Series](https://github.com/diasurgical/devilutionX/actions/workflows/xbox_one.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/xbox_one.yml?query=branch%3Amaster)\n[![Nintendo Switch](https://github.com/diasurgical/devilutionX/actions/workflows/switch.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/switch.yml)\n[![Sony PlayStation Vita](https://github.com/diasurgical/devilutionX/actions/workflows/vita.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/vita.yml)\n[![Nintendo 3DS](https://github.com/diasurgical/devilutionX/actions/workflows/3ds.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/3ds.yml)\n[![Amiga M68K](https://github.com/diasurgical/devilutionX/actions/workflows/amiga-m68k.yml/badge.svg)](https://github.com/diasurgical/devilutionX/actions/workflows/amiga-m68k.yml)\n\n# Building from Source\n\nWant to compile the program by yourself? Great! Simply follow the [build instructions](./docs/building.md).\n\n# Credits\n\n- The original Devilution project: [Devilution](https://github.com/diasurgical/devilution#credits)\n- [Everyone](https://github.com/diasurgical/devilutionX/graphs/contributors) who worked on Devilution/DevilutionX\n- [Nikolay Popov](https://www.instagram.com/nikolaypopovz/) for UI and graphics\n- [WiAParker](https://wiaparker.pl/projekty/diablo-hellfire/) for the Polish voice pack\n- And thanks to all who support the project, report bugs, and help spread the word ❤️\n\n# Legal\n\nDevilutionX is made publicly available and released under the Sustainable Use License (see [LICENSE](LICENSE.md)).\n\nThe source code in this repository is for non-commercial use only. If you use the source code, you may not charge others for access to it or any derivative work thereof.\n\nDiablo® - Copyright © 1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.\n\nDevilutionX and any of its maintainers are in no way associated with or endorsed by Blizzard Entertainment®.\n"
  },
  {
    "path": "Source/.clang-format",
    "content": "BasedOnStyle: webkit\nAlignTrailingComments: true\nAllowShortBlocksOnASingleLine: true\nAllowShortCaseLabelsOnASingleLine: true\nAllowShortFunctionsOnASingleLine: All\nAllowShortIfStatementsOnASingleLine: WithoutElse\nPointerAlignment: Right\nTabWidth: 4\nUseTab: ForIndentation\nSortIncludes: true\nNamespaceIndentation: None\nFixNamespaceComments: true\nQualifierAlignment: Left\n"
  },
  {
    "path": "Source/.clang-tidy",
    "content": "---\r\n# clang-tidy configuration\r\n#\r\n# clang-tidy can be run manually like this:\r\n#\r\n#     run-clang-tidy -p build 'Source.*'\r\n#\r\n# To apply fixes suggested by clang-tidy, run:\r\n#\r\n#     run-clang-tidy -p build -fix -format 'Source.*'\r\n#\r\n# To limit the run to certain checks:\r\n#\r\n#     run-clang-tidy -checks='-*,modernize-use-nullptr' -p build 'Source.*'\r\n#\r\n# clang-tidy also has several IDE integrations listed here:\r\n# https://clang.llvm.org/extra/clang-tidy/Integrations.html\r\n\r\n# Enable most checks.\r\n#\r\n# Built-in checks:\r\n# https://clang.llvm.org/extra/clang-tidy/checks/list.html\r\n#\r\n# Exclusions:\r\n#\r\n# -modernize-avoid-c-arrays\r\n#   We use C-arrays throughout, e.g. for `constexpr char []`.\r\n#   `std::array` is not a replacement because its length is\r\n#   not deduced.\r\n#\r\n# -modernize-use-trailing-return-type\r\n#   A purely stylistic change that we do not want.\r\n#\r\n# -modernize-concat-nested-namespaces\r\n# -modernize-avoid-bind\r\n#   Compatibility with older compilers.\r\nChecks: >\r\n  -*,\r\n  bugprone-*,\r\n  cppcoreguidelines-pro-type-cstyle-cast,\r\n  google-runtime-int,\r\n  llvm-include-order,\r\n  llvm-namespace-comment,\r\n  misc-*,\r\n  modernize-*,\r\n  performance-*,\r\n  portability-*,\r\n  readability-*,\r\n  -readability-identifier-length,\r\n  -bugprone-easily-swappable-parameters,\r\n  -readability-magic-numbers,\r\n  -misc-non-private-member-variables-in-classes,\r\n  -modernize-avoid-c-arrays,\r\n  -modernize-use-trailing-return-type,\r\n  -modernize-concat-nested-namespaces,\r\n  -modernize-avoid-bind,\r\n  -modernize-use-constraints\r\n\r\nHeaderFilterRegex: \"^(Source|test)\\\\.h$\"\r\n\r\nCheckOptions:\r\n  - { key: readability-identifier-naming.NamespaceCase,           value: lower_case }\r\n  - { key: readability-identifier-naming.ClassCase,               value: CamelCase  }\r\n  - { key: readability-identifier-naming.StructCase,              value: CamelCase  }\r\n  - { key: readability-identifier-naming.TemplateParameterCase,   value: CamelCase  }\r\n  - { key: readability-identifier-naming.MethodCase,              value: camelBack  }\r\n  - { key: readability-identifier-naming.FunctionCase,            value: CamelCase  }\r\n  - { key: readability-identifier-naming.ParameterCase,           value: camelBack  }\r\n  - { key: readability-identifier-naming.MemberCase,              value: camelBack  }\r\n  - { key: readability-identifier-naming.VariableCase,            value: camelBack  }\r\n  - { key: readability-identifier-naming.ClassMemberCase,         value: lower_case }\r\n  - { key: readability-identifier-naming.GlobalVariableCase,      value: aNy_CasE   }\r\n  - { key: readability-identifier-naming.GlobalFunctionCase,      value: aNy_CasE   }\r\n  - { key: readability-identifier-naming.ClassMemberSuffix,       value: _          }\r\n  - { key: readability-identifier-naming.PrivateMemberSuffix,     value: _          }\r\n  - { key: readability-identifier-naming.ProtectedMemberSuffix,   value: _          }\r\n  - { key: readability-identifier-naming.EnumConstantCase,        value: CamelCase  }\r\n  - { key: readability-identifier-naming.ConstexprVariableCase,   value: CamelCase  }\r\n  - { key: readability-identifier-naming.GlobalConstantCase,      value: CamelCase  }\r\n  - { key: readability-identifier-naming.MemberConstantCase,      value: CamelCase  }\r\n  - { key: readability-identifier-naming.StaticConstantCase,      value: CamelCase  }\r\n\r\n  # Allow short if-statements without braces\r\n  - { key: readability-braces-around-statements.ShortStatementLines, value: 3 }\r\n\r\n  # Use <cstdint> fixed-width integer types instead of short, long and long long\r\n  - { key: google-runtime-int.UnsignedTypePrefix, value: \"std::uint\" }\r\n  - { key: google-runtime-int.SignedTypePrefix, value: \"std::int\" }\r\n  - { key: google-runtime-int.TypeSuffix, value: \"_t\" }\r\n\r\n  # `int8_t` aren't used as chars, disable misleading warning.\r\n  - { key: bugprone-signed-char-misuse.CharTypdefsToIgnore, value: \"std::int8_t\" }\r\n\r\n  - { key: readability-identifier-length.MinimumLoopCounterNameLength, value: 1 }\r\n\r\n  # Ignore warnings for individual SDL headers, e.g. SDL_video.h, SDL_render.h\r\n  - { key: misc-include-cleaner.IgnoreHeaders, value: 'SDL_.*\\\\.h' }\r\n"
  },
  {
    "path": "Source/CMakeLists.txt",
    "content": "include(Definitions)\r\ninclude(functions/devilutionx_library)\r\ninclude(functions/genex)\r\n\r\nset(libdevilutionx_SRCS\r\n  appfat.cpp\r\n  automap.cpp\r\n  capture.cpp\r\n  cursor.cpp\r\n  dead.cpp\r\n  debug.cpp\r\n  diablo.cpp\r\n  diablo_msg.cpp\r\n  doom.cpp\r\n  gamemenu.cpp\r\n  gmenu.cpp\r\n  help.cpp\r\n  hwcursor.cpp\r\n  interfac.cpp\r\n  inv.cpp\r\n  loadsave.cpp\r\n  menu.cpp\r\n  minitext.cpp\r\n  missiles.cpp\r\n  movie.cpp\r\n  msg.cpp\r\n  nthread.cpp\r\n  pfile.cpp\r\n  plrmsg.cpp\r\n  portal.cpp\r\n  restrict.cpp\r\n  sync.cpp\r\n  tmsg.cpp\r\n  towners.cpp\r\n  track.cpp\r\n\r\n  control/control_chat.cpp\r\n  control/control_chat_commands.cpp\r\n  control/control_flasks.cpp\r\n  control/control_gold.cpp\r\n  control/control_infobox.cpp\r\n  control/control_panel.cpp\r\n\r\n  controls/axis_direction.cpp\r\n  controls/controller_motion.cpp\r\n  controls/controller.cpp\r\n  controls/devices/joystick.cpp\r\n  controls/devices/kbcontroller.cpp\r\n  controls/game_controls.cpp\r\n  controls/keymapper.cpp\r\n  controls/menu_controls.cpp\r\n  controls/modifier_hints.cpp\r\n  controls/plrctrls.cpp\r\n\r\n  DiabloUI/button.cpp\r\n  DiabloUI/credits.cpp\r\n  DiabloUI/credits_lines.cpp\r\n  DiabloUI/diabloui.cpp\r\n  DiabloUI/dialogs.cpp\r\n  DiabloUI/hero/selhero.cpp\r\n  DiabloUI/mainmenu.cpp\r\n  DiabloUI/multi/selconn.cpp\r\n  DiabloUI/multi/selgame.cpp\r\n  DiabloUI/progress.cpp\r\n  DiabloUI/scrollbar.cpp\r\n  DiabloUI/selok.cpp\r\n  DiabloUI/selstart.cpp\r\n  DiabloUI/selyesno.cpp\r\n  DiabloUI/settingsmenu.cpp\r\n  DiabloUI/support_lines.cpp\r\n  DiabloUI/title.cpp\r\n  DiabloUI/text_input.cpp\r\n\r\n  dvlnet/abstract_net.cpp\r\n  dvlnet/base.cpp\r\n  dvlnet/cdwrap.cpp\r\n  dvlnet/frame_queue.cpp\r\n  dvlnet/loopback.cpp\r\n  dvlnet/packet.cpp\r\n\r\n  engine/actor_position.cpp\r\n  engine/animationinfo.cpp\r\n  engine/backbuffer_state.cpp\r\n  engine/dx.cpp\r\n  engine/events.cpp\r\n  engine/palette.cpp\r\n  engine/sound_position.cpp\r\n  engine/trn.cpp\r\n\r\n  engine/render/automap_render.cpp\r\n  engine/render/scrollrt.cpp\r\n\r\n  items/validation.cpp\r\n\r\n  levels/reencode_dun_cels.cpp\r\n  levels/setmaps.cpp\r\n  levels/themes.cpp\r\n  levels/tile_properties.cpp\r\n  levels/town.cpp\r\n  levels/trigs.cpp\r\n\r\n  lua/autocomplete.cpp\r\n  lua/lua_event.cpp\r\n  lua/lua_global.cpp\r\n  lua/modules/audio.cpp\r\n  lua/modules/hellfire.cpp\r\n  lua/modules/dev.cpp\r\n  lua/modules/dev/display.cpp\r\n  lua/modules/dev/items.cpp\r\n  lua/modules/dev/level.cpp\r\n  lua/modules/dev/level/map.cpp\r\n  lua/modules/dev/level/warp.cpp\r\n  lua/modules/dev/monsters.cpp\r\n  lua/modules/dev/player.cpp\r\n  lua/modules/dev/player/gold.cpp\r\n  lua/modules/dev/player/spells.cpp\r\n  lua/modules/dev/player/stats.cpp\r\n  lua/modules/dev/quests.cpp\r\n  lua/modules/dev/search.cpp\r\n  lua/modules/dev/towners.cpp\r\n  lua/modules/floatingnumbers.cpp\r\n  lua/modules/i18n.cpp\r\n  lua/modules/items.cpp\r\n  lua/modules/log.cpp\r\n  lua/modules/monsters.cpp\r\n  lua/modules/player.cpp\r\n  lua/modules/render.cpp\r\n  lua/modules/system.cpp\r\n  lua/modules/towners.cpp\r\n  lua/repl.cpp\r\n\r\n  monsters/validation.cpp\r\n\r\n  panels/charpanel.cpp\r\n  panels/console.cpp\r\n  panels/info_box.cpp\r\n  panels/mainpanel.cpp\r\n  panels/partypanel.cpp\r\n  panels/spell_book.cpp\r\n  panels/spell_icons.cpp\r\n  panels/spell_list.cpp\r\n\r\n  platform/locale.cpp\r\n\r\n  portals/validation.cpp\r\n\r\n  qol/autopickup.cpp\r\n  qol/chatlog.cpp\r\n  qol/floatingnumbers.cpp\r\n  qol/itemlabels.cpp\r\n  qol/monhealthbar.cpp\r\n  qol/stash.cpp\r\n  qol/xpbar.cpp\r\n\r\n  quests/validation.cpp\r\n\r\n  storm/storm_net.cpp\r\n  storm/storm_svid.cpp\r\n\r\n  tables/misdat.cpp\r\n  tables/textdat.cpp\r\n  tables/townerdat.cpp\r\n\r\n  utils/display.cpp\r\n  utils/language.cpp\r\n  utils/sdl_bilinear_scale.cpp\r\n  utils/sdl_thread.cpp\r\n  utils/surface_to_clx.cpp\r\n  utils/timer.cpp)\r\n\r\n# These files are responsible for most of the runtime in Debug mode.\r\n# Apply some optimizations to them even in Debug mode to get reasonable performance.\r\n#\r\n# They also perform better with -O2 rather than -O3 even in Release mode.\r\nset(_optimize_in_debug_srcs\r\n  engine/render/clx_render.cpp\r\n  engine/render/dun_render.cpp\r\n  engine/render/text_render.cpp\r\n  utils/cel_to_clx.cpp\r\n  utils/cl2_to_clx.cpp\r\n  utils/pcx_to_clx.cpp)\r\nif(CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\")\r\n  set_source_files_properties(${_optimize_in_debug_srcs} PROPERTIES COMPILE_OPTIONS \"-O2;--param=max-vartrack-size=900000000\")\r\nelseif(CMAKE_CXX_COMPILER_ID STREQUAL \"Clang\")\r\n  set_source_files_properties(${_optimize_in_debug_srcs} PROPERTIES COMPILE_OPTIONS \"-O2\")\r\nendif()\r\n\r\n# We need to define all the object libraries first\r\n# because our workaround for transitive dependency support\r\n# requires targets to exist when calling `target_link_dependencies`\r\n# (see object_libraries.cmake).\r\n\r\nadd_devilutionx_object_library(libdevilutionx_assets\r\n  engine/assets.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_assets PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  tl\r\n  libdevilutionx_headless_mode\r\n  libdevilutionx_game_mode\r\n  libdevilutionx_mpq\r\n  libdevilutionx_paths\r\n  libdevilutionx_sdl2_to_1_2_backports\r\n  libdevilutionx_strings\r\n  ${DEVILUTIONX_PLATFORM_ASSETS_LINK_LIBRARIES}\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_cel_to_clx\r\n  utils/cel_to_clx.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_cel_to_clx\r\n  PRIVATE\r\n  libdevilutionx_endian_write\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_cl2_to_clx\r\n  utils/cl2_to_clx.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_cl2_to_clx\r\n  PRIVATE\r\n  libdevilutionx_endian_write\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_clx_render\r\n  engine/render/clx_render.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_clx_render PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  libdevilutionx_light_render\r\n  libdevilutionx_palette_blending\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_codec\r\n  codec.cpp\r\n  sha.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_codec PRIVATE\r\n  DevilutionX::SDL\r\n  libdevilutionx_log\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_controller_buttons\r\n  controls/controller_buttons.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_controller_buttons\r\n  DevilutionX::SDL\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_control_mode\r\n  controls/control_mode.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_control_mode PUBLIC\r\n  libdevilutionx_controller_buttons\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_padmapper\r\n  controls/padmapper.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_padmapper PUBLIC\r\n  libdevilutionx_controller_buttons\r\n  libdevilutionx_options\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_palette_kd_tree\r\n  utils/palette_kd_tree.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_palette_kd_tree PUBLIC\r\n  DevilutionX::SDL\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_paths\r\n  utils/paths.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_paths PUBLIC\r\n  DevilutionX::SDL\r\n  libdevilutionx_file_util\r\n  libdevilutionx_log\r\n  libdevilutionx_sdl2_to_1_2_backports\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_pcx_to_clx\r\n  utils/pcx_to_clx.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_pcx_to_clx\r\n  PUBLIC\r\n  DevilutionX::SDL\r\n  libdevilutionx_assets\r\n  libdevilutionx_endian_write\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_primitive_render\r\n  engine/render/primitive_render.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_primitive_render\r\n  PUBLIC\r\n  libdevilutionx_palette_blending\r\n  libdevilutionx_surface\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_crawl\r\n  crawl.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_crawl PUBLIC\r\n  tl\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_direction\r\n  engine/direction.cpp\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_dun_render\r\n  engine/render/dun_render.cpp\r\n)\r\ntarget_link_libraries(libdevilutionx_dun_render\r\n  PUBLIC\r\n  DevilutionX::SDL\r\n  libdevilutionx_light_render\r\n  libdevilutionx_surface\r\n  PRIVATE\r\n  libdevilutionx_options\r\n)\r\n\r\nadd_library(libdevilutionx_endian_write INTERFACE)\r\ntarget_link_libraries(libdevilutionx_endian_write INTERFACE\r\n  DevilutionX::SDL\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_surface\r\n  engine/surface.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_surface PUBLIC\r\n  DevilutionX::SDL\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_file_util\r\n  utils/file_util.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_file_util PRIVATE\r\n  DevilutionX::SDL\r\n  libdevilutionx_log\r\n  ${DEVILUTIONX_PLATFORM_FILE_UTIL_LINK_LIBRARIES}\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_format_int\r\n  utils/format_int.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_format_int PUBLIC\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_game_mode\r\n  game_mode.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_game_mode PRIVATE\r\n  tl\r\n  magic_enum::magic_enum\r\n  libdevilutionx_options\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_gendung\r\n  levels/crypt.cpp\r\n  levels/drlg_l1.cpp\r\n  levels/drlg_l2.cpp\r\n  levels/drlg_l3.cpp\r\n  levels/drlg_l4.cpp\r\n  levels/gendung.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_gendung PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  tl\r\n  libdevilutionx_assets\r\n  libdevilutionx_items\r\n  libdevilutionx_monster\r\n  libdevilutionx_random\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_headless_mode\r\n  headless_mode.cpp\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_init\r\n  init.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_init PUBLIC\r\n  magic_enum::magic_enum\r\n  libdevilutionx_assets\r\n  libdevilutionx_config\r\n  libdevilutionx_mpq\r\n  libdevilutionx_options\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_load_cel\r\n  engine/load_cel.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_load_cel\r\n  PUBLIC\r\n  tl\r\n  PRIVATE\r\n  libdevilutionx_strings\r\n)\r\nif(SUPPORTS_MPQ)\r\n  target_link_dependencies(libdevilutionx_load_cel PRIVATE\r\n    libdevilutionx_mpq\r\n    libdevilutionx_cel_to_clx\r\n  )\r\nelse()\r\n  target_link_dependencies(libdevilutionx_load_cel PRIVATE\r\n    libdevilutionx_load_clx\r\n  )\r\nendif()\r\n\r\nadd_devilutionx_object_library(libdevilutionx_load_cl2\r\n  engine/load_cl2.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_load_cl2\r\n  PUBLIC\r\n  tl\r\n  libdevilutionx_endian_write\r\n  PRIVATE\r\n  libdevilutionx_strings\r\n)\r\nif(SUPPORTS_MPQ)\r\n  target_link_dependencies(libdevilutionx_load_cl2 PUBLIC\r\n    libdevilutionx_mpq\r\n    libdevilutionx_cl2_to_clx\r\n  )\r\nelse()\r\n  target_link_dependencies(libdevilutionx_load_cl2 PRIVATE\r\n    libdevilutionx_load_clx\r\n  )\r\nendif()\r\n\r\nadd_devilutionx_object_library(libdevilutionx_load_clx\r\n  engine/load_clx.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_load_clx\r\n  PUBLIC\r\n  tl\r\n  PRIVATE\r\n  libdevilutionx_assets\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_load_pcx\r\n  engine/load_pcx.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_load_pcx\r\n  PRIVATE\r\n  DevilutionX::SDL\r\n  libdevilutionx_sdl2_to_1_2_backports\r\n  libdevilutionx_log\r\n  libdevilutionx_strings\r\n)\r\nif(SUPPORTS_MPQ)\r\n  target_link_dependencies(libdevilutionx_load_pcx PUBLIC\r\n    libdevilutionx_assets\r\n    libdevilutionx_pcx_to_clx\r\n  )\r\nelse()\r\n  target_link_dependencies(libdevilutionx_load_pcx PRIVATE\r\n    libdevilutionx_load_clx\r\n  )\r\nendif()\r\n\r\nadd_devilutionx_object_library(libdevilutionx_light_render\r\n  engine/render/light_render.cpp\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_lighting\r\n  lighting.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_lighting PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  magic_enum::magic_enum\r\n  tl\r\n  unordered_dense::unordered_dense\r\n  libdevilutionx_vision\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_logged_fstream\r\n  utils/logged_fstream.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_logged_fstream PUBLIC\r\n  libdevilutionx_file_util\r\n  libdevilutionx_log\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_items\r\n  tables/itemdat.cpp\r\n  items.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_items PUBLIC\r\n  DevilutionX::SDL\r\n  sol2::sol2\r\n  tl\r\n  libdevilutionx_headless_mode\r\n  libdevilutionx_sound\r\n  libdevilutionx_spells\r\n  libdevilutionx_stores\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_ini\r\n  utils/ini.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_ini PUBLIC\r\n  fmt::fmt\r\n  tl\r\n  unordered_dense::unordered_dense\r\n  libdevilutionx_strings\r\n  libdevilutionx_utf8\r\n)\r\n\r\n# We use an INTERFACE library rather than an OBJECT library\r\n# because `libdevilutionx_log` does not have any sources.\r\nadd_library(libdevilutionx_log INTERFACE)\r\ntarget_include_directories(libdevilutionx_log INTERFACE\r\n  ${PROJECT_SOURCE_DIR}/Source)\r\ntarget_link_libraries(libdevilutionx_log INTERFACE\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n)\r\ntarget_sources(libdevilutionx_log INTERFACE $<TARGET_OBJECTS:libdevilutionx_strings>)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_level_objects\r\n  tables/objdat.cpp\r\n  objects.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_level_objects PUBLIC\r\n  DevilutionX::SDL\r\n  unordered_dense::unordered_dense\r\n  tl\r\n  libdevilutionx_direction\r\n  libdevilutionx_headless_mode\r\n  libdevilutionx_monster\r\n  libdevilutionx_options\r\n  libdevilutionx_player\r\n  libdevilutionx_random\r\n  libdevilutionx_txtdata\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_monster\r\n  tables/monstdat.cpp\r\n  monster.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_monster\r\n  PUBLIC\r\n  DevilutionX::SDL\r\n  magic_enum::magic_enum\r\n  sol2::sol2\r\n  tl\r\n  unordered_dense::unordered_dense\r\n  libdevilutionx_game_mode\r\n  libdevilutionx_headless_mode\r\n  libdevilutionx_sound\r\n  libdevilutionx_txtdata\r\n  PRIVATE\r\n  libdevilutionx_cl2_to_clx\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_palette_blending\r\n  utils/palette_blending.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_palette_blending PUBLIC\r\n  DevilutionX::SDL\r\n  libdevilutionx_palette_kd_tree\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_parse_int\r\n  utils/parse_int.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_parse_int PUBLIC\r\n  tl\r\n)\r\n\r\nif(SUPPORTS_MPQ)\r\n  add_devilutionx_object_library(libdevilutionx_mpq\r\n    mpq/mpq_common.cpp\r\n    mpq/mpq_reader.cpp\r\n    mpq/mpq_sdl_rwops.cpp\r\n    mpq/mpq_writer.cpp\r\n  )\r\n  target_link_dependencies(libdevilutionx_mpq PUBLIC\r\n    DevilutionX::SDL\r\n    fmt::fmt\r\n    tl\r\n    libmpq\r\n    libdevilutionx_file_util\r\n    libdevilutionx_logged_fstream\r\n    libdevilutionx_pkware_encrypt\r\n    libdevilutionx_strings\r\n  )\r\nelse()\r\n  add_library(libdevilutionx_mpq INTERFACE)\r\nendif()\r\n\r\nadd_devilutionx_object_library(libdevilutionx_multiplayer\r\n  multi.cpp\r\n  pack.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_multiplayer PUBLIC\r\n  libdevilutionx_config\r\n  libdevilutionx_items\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_options\r\n  options.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_options PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  magic_enum::magic_enum\r\n  tl\r\n  unordered_dense::unordered_dense\r\n  libdevilutionx_controller_buttons\r\n  libdevilutionx_control_mode\r\n  libdevilutionx_logged_fstream\r\n  libdevilutionx_quick_messages\r\n  libdevilutionx_strings\r\n  libdevilutionx_ini\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_pathfinding\r\n  engine/path.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_pathfinding PUBLIC\r\n  tl\r\n  libdevilutionx_crawl\r\n  libdevilutionx_direction\r\n)\r\n\r\nif(SUPPORTS_MPQ OR NOT NONET)\r\n  add_devilutionx_object_library(libdevilutionx_pkware_encrypt\r\n    encrypt.cpp\r\n  )\r\n  target_link_dependencies(libdevilutionx_pkware_encrypt PUBLIC\r\n    DevilutionX::SDL\r\n    PKWare\r\n  )\r\nelse()\r\n  add_library(libdevilutionx_pkware_encrypt INTERFACE)\r\nendif()\r\n\r\nadd_devilutionx_object_library(libdevilutionx_player\r\n  player.cpp\r\n  tables/playerdat.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_player\r\n  PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  magic_enum::magic_enum\r\n  sol2::sol2\r\n  tl\r\n  unordered_dense::unordered_dense\r\n  libdevilutionx_game_mode\r\n  PRIVATE\r\n  libdevilutionx_load_cl2\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_quests\r\n  quests.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_quests PUBLIC\r\n  libdevilutionx_surface\r\n  libdevilutionx_gendung\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_random\r\n  engine/random.cpp\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_quick_messages\r\n  quick_messages.cpp\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_spells\r\n  tables/spelldat.cpp\r\n  spells.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_spells PUBLIC\r\n  tl\r\n  libdevilutionx_player\r\n  libdevilutionx_txtdata\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_text_render\r\n  engine/render/text_render.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_text_render\r\n  PUBLIC\r\n  libdevilutionx_surface\r\n  PRIVATE\r\n  fmt::fmt\r\n  unordered_dense::unordered_dense\r\n  libdevilutionx_clx_render\r\n  libdevilutionx_game_mode\r\n  libdevilutionx_load_cel\r\n  libdevilutionx_load_clx\r\n  libdevilutionx_load_pcx\r\n  libdevilutionx_log\r\n  libdevilutionx_primitive_render\r\n  libdevilutionx_ticks\r\n  libdevilutionx_utf8\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_ticks\r\n  engine/ticks.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_ticks PRIVATE\r\n  DevilutionX::SDL\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_txtdata\r\n  data/file.cpp\r\n  data/parser.cpp\r\n  data/record_reader.cpp\r\n  data/value_reader.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_txtdata PUBLIC\r\n  fmt::fmt\r\n  tl\r\n  libdevilutionx_assets\r\n  libdevilutionx_parse_int\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_utf8\r\n  utils/utf8.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_utf8 PRIVATE\r\n  SheenBidi::SheenBidi\r\n)\r\n\r\nif(NOSOUND)\r\n  add_devilutionx_object_library(libdevilutionx_sound\r\n    effects_stubs.cpp\r\n    engine/sound_stubs.cpp\r\n  )\r\n  target_link_dependencies(libdevilutionx_sound PUBLIC\r\n    DevilutionX::SDL\r\n    fmt::fmt\r\n    magic_enum::magic_enum\r\n    tl\r\n    unordered_dense::unordered_dense\r\n    libdevilutionx_options\r\n    libdevilutionx_random\r\n    libdevilutionx_sdl2_to_1_2_backports\r\n  )\r\nelse()\r\n  add_devilutionx_object_library(libdevilutionx_sound\r\n    effects.cpp\r\n    engine/sound.cpp\r\n    utils/soundsample.cpp\r\n  )\r\n  if(USE_SDL3)\r\n    target_link_dependencies(libdevilutionx_sound PUBLIC\r\n      SDL3_mixer::SDL3_mixer\r\n    )\r\n  else()\r\n    target_sources(libdevilutionx_sound PRIVATE\r\n      utils/push_aulib_decoder.cpp)\r\n    target_link_dependencies(libdevilutionx_sound PUBLIC\r\n      SDL_audiolib::SDL_audiolib\r\n    )\r\n  endif()\r\n  target_link_dependencies(libdevilutionx_sound PUBLIC\r\n    DevilutionX::SDL\r\n    fmt::fmt\r\n    magic_enum::magic_enum\r\n    tl\r\n    unordered_dense::unordered_dense\r\n    libdevilutionx_options\r\n    libdevilutionx_random\r\n    libdevilutionx_sdl2_to_1_2_backports\r\n  )\r\nendif()\r\n\r\nadd_devilutionx_object_library(libdevilutionx_stores\r\n  stores.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_stores PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  tl\r\n  libdevilutionx_clx_render\r\n  libdevilutionx_options\r\n  libdevilutionx_sound\r\n  libdevilutionx_strings\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_strings\r\n  utils/str_cat.cpp\r\n  utils/str_case.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_strings PRIVATE\r\n  fmt::fmt)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_utils_console\r\n  utils/console.cpp\r\n)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_vision\r\n  vision.cpp\r\n)\r\ntarget_link_dependencies(libdevilutionx_vision PUBLIC\r\n  tl\r\n)\r\n\r\nif(USE_SDL1)\r\n  add_devilutionx_library(libdevilutionx_sdl2_to_1_2_backports STATIC\r\n    utils/sdl2_to_1_2_backports.cpp\r\n  )\r\n  target_link_dependencies(libdevilutionx_sdl2_to_1_2_backports PRIVATE\r\n    libdevilutionx_strings\r\n    libdevilutionx_utils_console\r\n  )\r\n  target_link_libraries(DevilutionX::SDL INTERFACE\r\n    libdevilutionx_sdl2_to_1_2_backports\r\n  )\r\n  if(APPLE)\r\n    enable_language(OBJC)\r\n    target_sources(libdevilutionx_sdl2_to_1_2_backports PRIVATE\r\n      platform/macos_sdl1/SDL_filesystem.m)\r\n    target_link_libraries(libdevilutionx_sdl2_to_1_2_backports PRIVATE\r\n      \"-framework Foundation\")\r\n  endif()\r\nelse()\r\n  add_library(libdevilutionx_sdl2_to_1_2_backports INTERFACE)\r\nendif()\r\n\r\nif(IOS)\r\n  list(APPEND libdevilutionx_SRCS platform/ios/ios_paths.m)\r\nendif()\r\n\r\nif(NOT DISABLE_DEMOMODE)\r\n  list(APPEND libdevilutionx_SRCS engine/demomode.cpp)\r\nendif()\r\n\r\nif(NOT NONET)\r\n  if(NOT DISABLE_TCP)\r\n    list(APPEND libdevilutionx_SRCS\r\n      dvlnet/tcp_client.cpp\r\n      dvlnet/tcp_server.cpp)\r\n  endif()\r\n  if(NOT DISABLE_ZERO_TIER)\r\n    list(APPEND libdevilutionx_SRCS\r\n      dvlnet/protocol_zt.cpp\r\n      dvlnet/zerotier_native.cpp\r\n      dvlnet/zerotier_lwip.cpp)\r\n  endif()\r\nendif()\r\n\r\nif(NOT USE_SDL1)\r\n  list(APPEND libdevilutionx_SRCS\r\n    controls/devices/game_controller.cpp\r\n    controls/touch/event_handlers.cpp\r\n    controls/touch/gamepad.cpp\r\n    controls/touch/renderers.cpp)\r\nendif()\r\n\r\nif(DISCORD_INTEGRATION)\r\n  list(APPEND libdevilutionx_SRCS\r\n    discord/discord.cpp\r\n  )\r\nendif()\r\n\r\nif(SCREEN_READER_INTEGRATION)\r\n  list(APPEND libdevilutionx_SRCS\r\n    utils/screen_reader.cpp\r\n  )\r\nendif()\r\n\r\nif(DEVILUTIONX_SCREENSHOT_FORMAT STREQUAL DEVILUTIONX_SCREENSHOT_FORMAT_PCX)\r\n  list(APPEND libdevilutionx_SRCS\r\n    utils/surface_to_pcx.cpp\r\n  )\r\nendif()\r\n\r\nif(DEVILUTIONX_SCREENSHOT_FORMAT STREQUAL DEVILUTIONX_SCREENSHOT_FORMAT_PNG)\r\n  add_devilutionx_object_library(libdevilutionx_surface_to_png\r\n    utils/surface_to_png.cpp\r\n  )\r\n  target_link_dependencies(libdevilutionx_surface_to_png\r\n    PUBLIC\r\n    DevilutionX::SDL\r\n    tl\r\n    libdevilutionx_surface\r\n  )\r\n  if(USE_SDL3)\r\n    target_link_dependencies(libdevilutionx_surface_to_png PUBLIC SDL3_image::SDL3_image)\r\n    target_compile_definitions(libdevilutionx_surface_to_png INTERFACE USE_SDL3)\r\n  else()\r\n    target_link_dependencies(libdevilutionx_surface_to_png PUBLIC SDL2::SDL2_image)\r\n  endif()\r\nendif()\r\n\r\nadd_devilutionx_object_library(libdevilutionx ${libdevilutionx_SRCS})\r\ntarget_include_directories(libdevilutionx PUBLIC ${CMAKE_CURRENT_BINARY_DIR})\r\ntarget_link_dependencies(libdevilutionx PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  libsmackerdec\r\n  ${LUA_LIBRARIES}\r\n  magic_enum::magic_enum\r\n  sol2::sol2\r\n  tl\r\n  unordered_dense::unordered_dense\r\n  libdevilutionx_assets\r\n  libdevilutionx_clx_render\r\n  libdevilutionx_codec\r\n  libdevilutionx_config\r\n  libdevilutionx_controller_buttons\r\n  libdevilutionx_control_mode\r\n  libdevilutionx_crawl\r\n  libdevilutionx_direction\r\n  libdevilutionx_dun_render\r\n  libdevilutionx_surface\r\n  libdevilutionx_file_util\r\n  libdevilutionx_format_int\r\n  libdevilutionx_game_mode\r\n  libdevilutionx_gendung\r\n  libdevilutionx_headless_mode\r\n  libdevilutionx_ini\r\n  libdevilutionx_init\r\n  libdevilutionx_items\r\n  libdevilutionx_level_objects\r\n  libdevilutionx_light_render\r\n  libdevilutionx_lighting\r\n  libdevilutionx_monster\r\n  libdevilutionx_mpq\r\n  libdevilutionx_multiplayer\r\n  libdevilutionx_options\r\n  libdevilutionx_padmapper\r\n  libdevilutionx_palette_blending\r\n  libdevilutionx_parse_int\r\n  libdevilutionx_pathfinding\r\n  libdevilutionx_pkware_encrypt\r\n  libdevilutionx_player\r\n  libdevilutionx_primitive_render\r\n  libdevilutionx_quests\r\n  libdevilutionx_quick_messages\r\n  libdevilutionx_random\r\n  libdevilutionx_sound\r\n  libdevilutionx_spells\r\n  libdevilutionx_stores\r\n  libdevilutionx_strings\r\n  libdevilutionx_text_render\r\n  libdevilutionx_txtdata\r\n  libdevilutionx_ticks\r\n  libdevilutionx_utf8\r\n  libdevilutionx_utils_console\r\n)\r\nif(NOT TARGET_PLATFORM STREQUAL \"dos\")\r\n  target_link_dependencies(libdevilutionx PUBLIC Threads::Threads)\r\nendif()\r\nif(DEVILUTIONX_SCREENSHOT_FORMAT STREQUAL DEVILUTIONX_SCREENSHOT_FORMAT_PNG)\r\n  target_link_dependencies(libdevilutionx PUBLIC libdevilutionx_surface_to_png)\r\nendif()\r\n\r\n# Use file GENERATE instead of configure_file because configure_file\r\n# does not support generator expressions.\r\nget_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)\r\nadd_library(libdevilutionx_config INTERFACE)\r\nif(is_multi_config)\r\n  set(CONFIG_PATH $<CONFIG>/config.h)\r\n  target_include_directories(libdevilutionx_config INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>)\r\nelse()\r\n  set(CONFIG_PATH config.h)\r\n  target_include_directories(libdevilutionx_config INTERFACE ${CMAKE_CURRENT_BINARY_DIR})\r\nendif()\r\nfile(GENERATE OUTPUT ${CONFIG_PATH} CONTENT\r\n\"#pragma once\r\n#define PROJECT_NAME \\\"${PROJECT_NAME}\\\"\r\n#define PROJECT_VERSION \\\"${PROJECT_VERSION_WITH_SUFFIX}\\\"\r\n#define PROJECT_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}\r\n#define PROJECT_VERSION_MINOR ${PROJECT_VERSION_MINOR}\r\n#define PROJECT_VERSION_PATCH ${PROJECT_VERSION_PATCH}\r\n\")\r\n\r\nif(DISCORD_INTEGRATION)\r\n  target_compile_definitions(libdevilutionx PRIVATE DISCORD)\r\n  target_link_libraries(libdevilutionx PRIVATE discord discord_game_sdk)\r\nendif()\r\n\r\nif(SCREEN_READER_INTEGRATION)\r\n  if(WIN32)\r\n    target_compile_definitions(libdevilutionx PRIVATE Tolk)\r\n    target_link_libraries(libdevilutionx PUBLIC Tolk)\r\n  else()\r\n    target_include_directories(libdevilutionx PUBLIC ${Speechd_INCLUDE_DIRS})\r\n    target_link_libraries(libdevilutionx PUBLIC speechd)\r\n  endif()\r\nendif()\r\n\r\nif(USE_SDL1)\r\n  # No need for SDL_image\r\nelseif(USE_SDL3)\r\n  target_link_libraries(libdevilutionx PUBLIC SDL3_image::SDL3_image)\r\nelse()\r\n  target_link_libraries(libdevilutionx PUBLIC SDL2::SDL2_image)\r\nendif()\r\n\r\nif(NOT NONET)\r\n  if(NOT DISABLE_TCP)\r\n    target_link_libraries(libdevilutionx PUBLIC asio)\r\n  endif()\r\n  if(PACKET_ENCRYPTION)\r\n    target_link_libraries(libdevilutionx PUBLIC sodium)\r\n  endif()\r\nendif()\r\n\r\nif(NOT NOSOUND AND NOT USE_SDL3)\r\n  target_link_libraries(libdevilutionx PUBLIC SDL_audiolib::SDL_audiolib)\r\nendif()\r\n\r\nif(NOT NONET AND NOT DISABLE_ZERO_TIER)\r\n  if(NOT ANDROID)\r\n    target_link_libraries(libdevilutionx PUBLIC zt-static)\r\n  else()\r\n    target_link_libraries(libdevilutionx PUBLIC zt-shared)\r\n  endif()\r\nendif()\r\n\r\nforeach(path ${DEVILUTIONX_PLATFORM_SUBDIRECTORIES})\r\n  add_subdirectory(${path})\r\nendforeach()\r\n\r\ntarget_link_dependencies(libdevilutionx PUBLIC ${DEVILUTIONX_PLATFORM_LINK_LIBRARIES})\r\n\r\nif(CMAKE_CXX_COMPILER_ID MATCHES \"GNU\")\r\n  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9 AND NOT AMIGA)\r\n    target_link_libraries(libdevilutionx PUBLIC stdc++fs)\r\n  endif()\r\nelseif(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\")\r\n  # Assumes libc++ (clang) is used rather than libstdc++ (gcc).\r\n  # This is not always true but these are ancient clang versions anyway.\r\n  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7)\r\n    target_link_libraries(libdevilutionx PUBLIC c++experimental)\r\n  elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)\r\n    target_link_libraries(libdevilutionx PUBLIC c++fs)\r\n  endif()\r\nendif()\r\n"
  },
  {
    "path": "Source/DiabloUI/button.cpp",
    "content": "#include \"DiabloUI/button.h\"\r\n\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_mouse.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/load_pcx.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList ButtonSprites;\r\n\r\n} // namespace\r\n\r\nvoid LoadDialogButtonGraphics()\r\n{\r\n\tButtonSprites = LoadOptionalClx(\"ui_art\\\\dvl_but_sml.clx\");\r\n\tif (!ButtonSprites) {\r\n\t\tButtonSprites = LoadPcxSpriteList(\"ui_art\\\\but_sml\", 15);\r\n\t}\r\n}\r\n\r\nvoid FreeDialogButtonGraphics()\r\n{\r\n\tButtonSprites = std::nullopt;\r\n}\r\n\r\nClxSprite ButtonSprite(bool pressed)\r\n{\r\n\treturn (*ButtonSprites)[pressed ? 1 : 0];\r\n}\r\n\r\nvoid RenderButton(const UiButton &button)\r\n{\r\n\tconst Surface &out = Surface(DiabloUiSurface()).subregion(button.m_rect.x, button.m_rect.y, button.m_rect.w, button.m_rect.h);\r\n\tRenderClxSprite(out, ButtonSprite(button.IsPressed()), { 0, 0 });\r\n\r\n\tRectangle textRect { { 0, 0 }, { button.m_rect.w, button.m_rect.h } };\r\n\tif (!button.IsPressed()) {\r\n\t\t--textRect.position.y;\r\n\t}\r\n\r\n\tDrawString(out, button.GetText(), textRect,\r\n\t    { .flags = UiFlags::AlignCenter | UiFlags::FontSizeDialog | UiFlags::ColorDialogWhite });\r\n}\r\n\r\nbool HandleMouseEventButton(const SDL_Event &event, UiButton *button)\r\n{\r\n\tif (event.button.button != SDL_BUTTON_LEFT)\r\n\t\treturn false;\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\tif (button->IsPressed()) {\r\n\t\t\tbutton->Activate();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\t\tbutton->Press();\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nvoid HandleGlobalMouseUpButton(UiButton *button)\r\n{\r\n\tbutton->Release();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/button.h",
    "content": "#pragma once\r\n\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconst Uint16 DialogButtonWidth = 110;\r\nconst Uint16 DialogButtonHeight = 28;\r\n\r\nvoid LoadDialogButtonGraphics();\r\nvoid FreeDialogButtonGraphics();\r\nClxSprite ButtonSprite(bool pressed);\r\nvoid RenderButton(const UiButton &button);\r\nbool HandleMouseEventButton(const SDL_Event &event, UiButton *button);\r\nvoid HandleGlobalMouseUpButton(UiButton *button);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/credits.cpp",
    "content": "#include <algorithm>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/credits_lines.h\"\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/support_lines.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"controls/input.h\"\r\n#include \"controls/menu_controls.h\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconst SDL_Rect VIEWPORT = { 0, 114, 640, 251 };\r\nconst int LINE_H = 22;\r\n\r\n// The maximum number of visible lines is the number of whole lines\r\n// (VIEWPORT.h / LINE_H) rounded up, plus one extra line for when\r\n// a line is leaving the screen while another one is entering.\r\n#define MAX_VISIBLE_LINES ((VIEWPORT.h - 1) / LINE_H + 2)\r\n\r\nclass CreditsRenderer {\r\n\r\npublic:\r\n\tCreditsRenderer(const char *const *text, std::size_t textLines)\r\n\t{\r\n\t\tfor (size_t i = 0; i < textLines; i++) {\r\n\t\t\tconst std::string_view orgText = _(text[i]);\r\n\r\n\t\t\tuint16_t offset = 0;\r\n\t\t\tsize_t indexFirstNotTab = 0;\r\n\t\t\twhile (indexFirstNotTab < orgText.size() && orgText[indexFirstNotTab] == '\\t') {\r\n\t\t\t\toffset += 40;\r\n\t\t\t\tindexFirstNotTab++;\r\n\t\t\t}\r\n\r\n\t\t\tconst std::string paragraphs = WordWrapString(orgText.substr(indexFirstNotTab), 580 - offset, FontSizeDialog);\r\n\r\n\t\t\tsize_t previous = 0;\r\n\t\t\twhile (true) {\r\n\t\t\t\tconst size_t next = paragraphs.find('\\n', previous);\r\n\t\t\t\tlinesToRender.emplace_back(LineContent { offset, paragraphs.substr(previous, next - previous) });\r\n\t\t\t\tif (next == std::string::npos)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tprevious = next + 1;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tticks_begin_ = SDL_GetTicks();\r\n\t\tprev_offset_y_ = 0;\r\n\t\tfinished_ = false;\r\n\t}\r\n\r\n\t~CreditsRenderer()\r\n\t{\r\n\t\tArtBackgroundWidescreen = std::nullopt;\r\n\t\tArtBackground = std::nullopt;\r\n\t}\r\n\r\n\tvoid Render();\r\n\r\n\t[[nodiscard]] bool Finished() const\r\n\t{\r\n\t\treturn finished_;\r\n\t}\r\n\r\nprivate:\r\n\tstruct LineContent {\r\n\t\tuint16_t offset;\r\n\t\tstd::string text;\r\n\t};\r\n\r\n\tstd::vector<LineContent> linesToRender;\r\n\tbool finished_;\r\n\tUint32 ticks_begin_;\r\n\tint prev_offset_y_;\r\n};\r\n\r\nvoid CreditsRenderer::Render()\r\n{\r\n\tconst int offsetY = -VIEWPORT.h + ((SDL_GetTicks() - ticks_begin_) / 40);\r\n\tif (offsetY == prev_offset_y_)\r\n\t\treturn;\r\n\tprev_offset_y_ = offsetY;\r\n\r\n\tSDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tif (ArtBackgroundWidescreen)\r\n\t\tRenderClxSprite(Surface(DiabloUiSurface()), (*ArtBackgroundWidescreen)[0], uiPosition - Displacement { 320, 0 });\r\n\tRenderClxSprite(Surface(DiabloUiSurface()), (*ArtBackground)[0], uiPosition);\r\n\r\n\tconst std::size_t linesBegin = std::max(offsetY / LINE_H, 0);\r\n\tconst std::size_t linesEnd = std::min(linesBegin + MAX_VISIBLE_LINES, linesToRender.size());\r\n\r\n\tif (linesBegin >= linesEnd) {\r\n\t\tif (linesEnd == linesToRender.size())\r\n\t\t\tfinished_ = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tSDL_Rect viewport = VIEWPORT;\r\n\tviewport.x += uiPosition.x;\r\n\tviewport.y += uiPosition.y;\r\n\tScaleOutputRect(&viewport);\r\n\r\n\t// We use unscaled coordinates for calculation throughout.\r\n\tSint16 destY = static_cast<Sint16>(uiPosition.y + VIEWPORT.y - (offsetY - linesBegin * LINE_H));\r\n\tfor (std::size_t i = linesBegin; i < linesEnd; ++i, destY += LINE_H) {\r\n\t\tconst Sint16 destX = uiPosition.x + VIEWPORT.x + 31;\r\n\r\n\t\tauto &lineContent = linesToRender[i];\r\n\r\n\t\tSDL_Rect dstRect = MakeSdlRect(destX + lineContent.offset, destY, 0, 0);\r\n\t\tScaleOutputRect(&dstRect);\r\n\t\tdstRect.x -= viewport.x;\r\n\t\tdstRect.y -= viewport.y;\r\n\r\n\t\tconst Surface &out = Surface(DiabloUiSurface(), viewport);\r\n\t\tDrawString(out, lineContent.text, Point { dstRect.x, dstRect.y },\r\n\t\t    { .flags = UiFlags::FontSizeDialog | UiFlags::ColorDialogWhite, .spacing = -1 });\r\n\t}\r\n}\r\n\r\nbool TextDialog(const char *const *text, std::size_t textLines)\r\n{\r\n\tCreditsRenderer creditsRenderer(text, textLines);\r\n\tbool endMenu = false;\r\n\r\n\tif (IsHardwareCursor())\r\n\t\tSetHardwareCursorVisible(false);\r\n\r\n\tSDL_Event event;\r\n\tdo {\r\n\t\tcreditsRenderer.Render();\r\n\t\tUiFadeIn();\r\n\t\twhile (PollEvent(&event)) {\r\n\t\t\tswitch (event.type) {\r\n\t\t\tcase SDL_EVENT_KEY_DOWN:\r\n\t\t\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\t\t\tendMenu = true;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tfor (const MenuAction menuAction : GetMenuActions(event)) {\r\n\t\t\t\t\tif (IsNoneOf(menuAction, MenuAction_BACK, MenuAction_SELECT))\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\tendMenu = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tUiHandleEvents(&event);\r\n\t\t}\r\n\t} while (!endMenu && !creditsRenderer.Finished());\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nbool UiCreditsDialog()\r\n{\r\n\tArtBackgroundWidescreen = LoadOptionalClx(\"ui_art\\\\creditsw.clx\");\r\n\tLoadBackgroundArt(\"ui_art\\\\credits\");\r\n\r\n\treturn TextDialog(CreditLines, CreditLinesSize);\r\n}\r\n\r\nbool UiSupportDialog()\r\n{\r\n\tArtBackgroundWidescreen = LoadOptionalClx(\"ui_art\\\\supportw.clx\");\r\n\tif (ArtBackgroundWidescreen.has_value()) {\r\n\t\tLoadBackgroundArt(\"ui_art\\\\support\");\r\n\t} else {\r\n\t\tArtBackgroundWidescreen = LoadOptionalClx(\"ui_art\\\\creditsw.clx\");\r\n\t\tLoadBackgroundArt(\"ui_art\\\\credits\");\r\n\t}\r\n\r\n\treturn TextDialog(SupportLines, SupportLinesSize);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/credits_lines.cpp",
    "content": "#include <cstddef>\r\n\r\n#include \"DiabloUI/credits_lines.h\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nconst char *const CreditLines[] = {\r\n\tN_(\"Game Design\"),\r\n\t\"\tBlizzard North\",\r\n\t\"\",\r\n\tN_(\"Senior Designers\"),\r\n\t\"\tErich Schaefer, David Brevik\",\r\n\t\"\",\r\n\tN_(\"Additional Design\"),\r\n\t\"\tMax Schaefer, Eric Sexton, Kenneth Williams\",\r\n\t\"\",\r\n\tN_(\"Lead Programmer\"),\r\n\t\"\tDavid Brevik\",\r\n\t\"\",\r\n\tN_(\"Senior Programmers\"),\r\n\t\"\tRichard Seis, Doron Gartner,\",\r\n\t\"\tPatrick Wyatt, Mike O'Brien\",\r\n\t\"\",\r\n\tN_(\"Programming\"),\r\n\t\"\tPeter Brevik, Robin van der Wel, Jon Morin\",\r\n\t\"\",\r\n\tN_(\"Special Guest Programmers\"),\r\n\t\"\tCollin Murray, Frank Pearce\",\r\n\t\"\",\r\n\tN_(\"Battle.net Programming\"),\r\n\t\"\tMike O'Brien, Mike Morhaime, Dan Liebgold\",\r\n\t\"\",\r\n\tN_(\"Serial Communications Programming\"),\r\n\t\"\tJeff Strain, Mike O'Brien\",\r\n\t\"\",\r\n\tN_(\"Installer Programming\"),\r\n\t\"\tBob Fitch, Patrick Wyatt\",\r\n\t\"\",\r\n\tN_(\"Art Directors\"),\r\n\t\"\tErich Schaefer, Samwise Didier\",\r\n\t\"\",\r\n\tN_(\"Artwork\"),\r\n\t\"\tMichio Okamura, Eric Sexton, Ben Haas, Patrick Tougas,\",\r\n\t\"\tKelly Johnson, Erich Schaefer, Max Schaefer, Hugh Tom\",\r\n\t\"\tByrne, Roman Kenney, Samwise Didier, Dave Berggren,\",\r\n\t\"\tMicky Neilson, Eric Flannum, Justin Thavirat, Brian\",\r\n\t\"\tSousa, Stu Rose, Nick Carpenter, Joeyray Hall\",\r\n\t\"\",\r\n\tN_(\"Technical Artwork\"),\r\n\t\"\tChristopher Root, Mark Sutherland,\",\r\n\t\"\tRobert Djordjevich, Jeffrey Vaughn\",\r\n\t\"\",\r\n\tN_(\"Cinematic Art Directors\"),\r\n\t\"\tDuane Stinnett, Matt Samia\",\r\n\t\"\",\r\n\tN_(\"3D Cinematic Artwork\"),\r\n\t\"\tDuane Stinnett, Matt Samia, Rob McNaughton,\",\r\n\t\"\tEric Flannum, Dave Pursley, Micky Neilson,\",\r\n\t\"\tMaxx Marshall, Trevor Jacobs, Brian Sousa,\",\r\n\t\"\tSamwise Didier, Ron Smorynski, Ben Haas, Patrick Tougas\",\r\n\t\"\",\r\n\tN_(\"Cinematic Technical Artwork\"),\r\n\t\"\tJoeyray Hall \",\r\n\t\"\",\r\n\tN_(\"Executive Producer\"),\r\n\t\"\tAllen Adham\",\r\n\t\"\",\r\n\tN_(\"Producer\"),\r\n\t\"\tBill Roper\",\r\n\t\"\",\r\n\tN_(\"Associate Producer\"),\r\n\t\"\tJames Phinney\",\r\n\t\"\",\r\n\tN_(/* TRANSLATORS: Keep Strike Team as Name */ \"Diablo Strike Team\"),\r\n\t\"\tAllen Adham, Ron Millar, Mike O'Brien,\",\r\n\t\"\tJames Phinney, Bill Roper, Patrick Wyatt\",\r\n\t\"\",\r\n\tN_(\"Music\"),\r\n\t\"\tMatt Uelmen\",\r\n\t\"\",\r\n\tN_(\"Sound Design\"),\r\n\t\"\tMatt Uelmen, Glenn Stafford\",\r\n\t\"\",\r\n\tN_(\"Cinematic Music & Sound\"),\r\n\t\"\tGlenn Stafford, Matt Uelmen\",\r\n\t\"\",\r\n\tN_(\"Voice Production, Direction & Casting\"),\r\n\t\"\tMark Schwarz, Glenn Stafford, Bill Roper\",\r\n\t\"\",\r\n\tN_(\"Script & Story\"),\r\n\t\"\tErich Schaefer, Eric Sexton,\",\r\n\t\"\tChris Metzen, Bill Roper\",\r\n\t\"\",\r\n\tN_(\"Voice Editing\"),\r\n\t\"\tGlenn Stafford\",\r\n\t\"\",\r\n\tN_(\"Voices\"),\r\n\t\"\tMichael Haley, Glynnis Talken, Michael Gough,\",\r\n\t\"\tPaul Eiding, Lani Minella, Steve Brodie, Bill Roper,\",\r\n\t\"\tMark Schwarz, Glenn Stafford, Chris Metzen, Max Schaefer\",\r\n\t\"\",\r\n\tN_(\"Recording Engineer\"),\r\n\t\"\tRobert Koenigsberg\",\r\n\t\"\",\r\n\tN_(\"Manual Design & Layout\"),\r\n\t\"\tPeter Underwood, Jeffrey Vaughn,\",\r\n\t\"\tChris Metzen, Bill Roper\",\r\n\t\"\",\r\n\tN_(\"Manual Artwork\"),\r\n\t\"\tSamwise Didier, Chris Metzen,\",\r\n\t\"\tRoman Kenney, Maxx Marshall\",\r\n\t\"\",\r\n\tN_(\"Provisional Director of QA (Lead Tester)\"),\r\n\t\"\tShane Dabiri\",\r\n\t\"\",\r\n\tN_(\"QA Assault Team (Testers)\"),\r\n\t\"\tChristopher Cross, Mike Givens, Dave Hale,\",\r\n\t\"\tBrian \\\"Doc\\\" Love, Hung Nguyen, Dean Shipley,\",\r\n\t\"\tChris Sigaty, Ian Welke, Jamie Wiggs\",\r\n\t\"\",\r\n\tN_(\"QA Special Ops Team (Compatibility Testers)\"),\r\n\t\"\tAdam Maxwell, Russell \\\"Rug\\\" Miller\",\r\n\t\"\",\r\n\tN_(\"QA Artillery Support (Additional Testers) \"),\r\n\t\"\tRich Alcazar, Mike Jones, Rev. Dan Moore, Matt Morris,\",\r\n\t\"\tMark Pfeiffer, Harish \\\"Pepe the Enforcer\\\" Rao, Chris Millar\",\r\n\t\"\",\r\n\tN_(\"QA Counterintelligence\"),\r\n\t\"\tAlan Dabiri, Jesse McReynolds, Walter Takata\",\r\n\t\"\",\r\n\tN_(/* TRANSLATORS: A group of people */ \"Order of Network Information Services\"),\r\n\t\"\tRobert Bridenbecker, Jason \\\"Brother Shaggy\\\" Schmit,\",\r\n\t\"\tJamie \\\"Brother Gug\\\" Steigerwald, Richard Seis \",\r\n\t\"\",\r\n\tN_(\"Customer Support\"),\r\n\t\"\tJohn Schwartz, Vic Larson, Chad Chaudry, Mick Yanko,\",\r\n\t\"\tBrandon Riseling, Kirk Mahony, Tony Hardy, Richard\",\r\n\t\"\tAmtower, Collin Smith, Andrew Edwards, Roger Eberhart\",\r\n\t\"\",\r\n\tN_(\"Sales\"),\r\n\t\"\tJorge Rivero, Rob Beatie\",\r\n\t\"\",\r\n\tN_(\"Dunsel\"),\r\n\t\"\tAlan Dabiri\",\r\n\t\"\",\r\n\tN_(\"Mr. Dabiri's Background Vocalists\"),\r\n\t\"\tKarin Colenzo, Christina Cade,\",\r\n\t\"\tKim Farrington, Melissa Edwards\",\r\n\t\"\",\r\n\tN_(\"Public Relations\"),\r\n\t\"\tLinda Duttenhaver, Susan Wooley\",\r\n\t\"\",\r\n\tN_(\"Marketing\"),\r\n\t\"\tJohn Patrick, Steve Huot, Neal Hubbard, Kathy Carter\",\r\n\t\"\",\r\n\tN_(\"International Sales\"),\r\n\t\"\tRalph Becker, Chris Yoshimura\",\r\n\t\"\",\r\n\tN_(\"U.S. Sales\"),\r\n\t\"\tTodd Coyle, Danny Kearns\",\r\n\t\"\",\r\n\tN_(\"Manufacturing\"),\r\n\t\"\tJohn Goodman, Tom Bryan\",\r\n\t\"\",\r\n\tN_(\"Legal & Business\"),\r\n\t\"\tPaula Duffy, Eric Roeder, Paul Sams, Kenneth Williams\",\r\n\t\"\",\r\n\tN_(\"Special Thanks To\"),\r\n\t\"\tPrimenet, Earthlink, AOL, Compuserve, ATI, Matrox, STB, \",\r\n\t\"\tCreative Labs, Logitech, U.S. Robotics, Gravis, Cyrix\",\r\n\t\"\",\r\n\tN_(\"Thanks To\"),\r\n\t\"\tIan Colquhoun, Rod Shean, Brian Fitzgerald, Sharon Schafer, Todd \",\r\n\t\"\tSchafer, Richard and Sandra Schaefer, Rick Bowles, Greg Bogden, \",\r\n\t\"\tCindy Sievert, Brad Mason, Chuck Goldman, Karin Colenzo, Wendy \",\r\n\t\"\tBrevik, Jennie Brevik, Hanna Carroll, Katie Newell, Karen Weiss, \",\r\n\t\"\tKurt Beaver, Stan McDonald, Brian Sexton, Michael Wan, Megan \",\r\n\t\"\tWilliams, Jessica Gensley, Beth Ann Parks, Brian Piltin, Johnathan \",\r\n\t\"\tRoot, Brett Supernaw, Sabeer Bhatia, Mark Rearick, Brad Mason, \",\r\n\t\"\tDiane Kodama, Bernadette Sexton, Barbara Uhlmann, Patricia\",\r\n\t\"\tMcDonald, Kris Kelley, Alissa Vaage, Denise Hernandez, Paula \",\r\n\t\"\tWhite, Rachel Marie Hawley, Laura Gaber, Isaac Matarasso,\",\r\n\t\"\tSusan Stafford, Gretchen Witte, Jason Sailor, Eufemia Palomino, \",\r\n\t\"\tNathalie Didier, Nicole Welke, Dawn Caddel, Anna-Marcelle \",\r\n\t\"\tOkamura, Amber Okamura, Megan Okamura Tracey McNaughton, \",\r\n\t\"\tTrisha Ann Ochoa, Annie Strain, Dr. Gregory T. Street, Ray the Soda \",\r\n\t\"\tGuy, Sam Raimi, A. Guinness Brewing Co., John Woo, Chow Yun Fat, \",\r\n\t\"\tJackie Chan,Proposition 215, Rumiko Takahashi, Bunchy & Mason, \",\r\n\t\"\tThe Friends of Stan, The Zoo Crew, Team Hamro, Brazil 2001, RUSH, \",\r\n\t\"\tCornholio, THE BROS., Dar, Emeril Lagasse, Tom Waits, Ice-Cube, \",\r\n\t\"\tThe Strike Team Deflectors, Tony Levin, Big Jim and the Twins, \",\r\n\t\"\tJag`rmeister, The Megasphere, Condor, The Allower, The Sunday \",\r\n\t\"\tNight Group, Gravitar, Steinway Pianos, Round Table Pizza, The Poxy \",\r\n\t\"\tBoggards, Urban Mystic & Co., Caffeine, Hunter Rose, Marly \",\r\n\t\"\tmediums in the box, sweet Poteen, Dave Scarpitti, TheByter, Bim \",\r\n\t\"\tMan, Krissann for color, Patty at Avalon Tattoo, James, Whaleboy, \",\r\n\t\"\tDunsel Training Institute, monkeys, Dob Bole, Rootes Group, Porshe, \",\r\n\t\"\tBongo, Scarlett, Apollo, The House of Mediocrity, Amelias, The King, \",\r\n\t\"\tSaag and all the folks at Davidson\",\r\n\t\"\",\r\n\tN_(\"In memory of\"),\r\n\t\"\tLawrence and Barbara Williams\",\r\n\t\"\tDavid A. Hargrave\",\r\n\t\"\tTony \\\"Xatre\\\" Collin\",\r\n\t\"\tThomas H Sexton\",\r\n\t\"\",\r\n\tN_(\"Very Special Thanks to\"),\r\n\t\"\tBob and Jan Davidson\",\r\n\t\"\tWalter Forbes\",\r\n\t\"\",\r\n\t\"\t\tSynergistic Software\",\r\n\t\"\",\r\n\tN_(\"General Manager\"),\r\n\t\"\tBob Clardy\",\r\n\t\"\",\r\n\tN_(\"Lead Programmer\"),\r\n\t\"\tDonald Tsang\",\r\n\t\"\",\r\n\tN_(\"Software Engineering\"),\r\n\t\"\tJim Edwards, Gary Powell, D'Andre Pritchett\",\r\n\t\"\",\r\n\tN_(\"Art Director\"),\r\n\t\"\tKirt Lemons\",\r\n\t\"\",\r\n\tN_(\"Artists\"),\r\n\t\"\tDarren Lamb, Mike McMillen,\",\r\n\t\"\tJason Robertson, Peter Watje\",\r\n\t\"\",\r\n\tN_(\"Design\"),\r\n\t\"\tKirt Lemons, Donald Tsang, Peter Watje\",\r\n\t\"\tJim Edwards, Mike McMillen\",\r\n\t\"\",\r\n\tN_(\"Additional Design\"),\r\n\t\"\tMichael Ormsby\",\r\n\t\"\",\r\n\tN_(\"Sound Design, SFX & Audio Engineering\"),\r\n\t\"\tCraig Utterback\",\r\n\t\"\",\r\n\tN_(\"Quality Assurance Lead\"),\r\n\t\"\tMona Branham\",\r\n\t\"\",\r\n\tN_(\"Testers\"),\r\n\t\"\tChris Barker, Steve Chin, Derek Clardy, Conor Durdy,\",\r\n\t\"\tAmy Edwards, Greg Hightower, Tim Jensen, Jeremy Jones,\",\r\n\t\"\tJohn Lang, Daudi Pritchett, Doug Van Horne, Gordon Wilcox\",\r\n\t\"\",\r\n\tN_(\"Manual\"),\r\n\t\"\tSuzanne David, Linda Westerfield,\",\r\n\t\"\tAnn Dickens Clardy, Kirt Lemons\",\r\n\t\"\",\r\n\tN_(\"Voices\"),\r\n\t\"\tJim Edwards, Paul Eiding, Eve Forward,\",\r\n\t\"\tMackenzie Powell, Rodney Sherwood, Craig Utterback\",\r\n\t\"\",\r\n\t\"\",\r\n\tN_(\"\tAdditional Work\"),\r\n\t\"\",\r\n\tN_(\"Quest Text Writing\"),\r\n\t\"\tEve Forward\",\r\n\t\"\",\r\n\tN_(\"Thanks to\"),\r\n\t\"\tTrisha Durdy, Dustin Freeman, D'Andre Pritchett\",\r\n\t\"\",\r\n\t\"\",\r\n\t\"\",\r\n\tN_(\"\t\t\tSpecial Thanks to Blizzard Entertainment\"),\r\n\t\"\",\r\n\t\"\",\r\n\t\"\",\r\n\t\"\",\r\n\tN_(\"\t\t\tSierra On-Line Inc. Northwest\"),\r\n\t\"\",\r\n\tN_(\"Quality Assurance Manager\"),\r\n\t\"\tGary Stevens\",\r\n\t\"\",\r\n\tN_(\"Quality Assurance Lead Tester\"),\r\n\t\"\tBernadette Pryor\",\r\n\t\"\",\r\n\tN_(\"Main Testers\"),\r\n\t\"\tErik Johnson, David Lee, Kristofer Hall\",\r\n\t\"\",\r\n\tN_(\"Additional Testers\"),\r\n\t\"\tCade Myers, Jeff Ingham, Phil Kuhlmey,\",\r\n\t\"\tEric Gelfand, Mark Wyman, Torsten Reinl,\",\r\n\t\"\tErinn Hamilton\",\r\n\t\"\",\r\n\tN_(\"Product Marketing Manager\"),\r\n\t\"\tEddie Ranchigoda\",\r\n\t\"\",\r\n\tN_(\"Public Relations Manager\"),\r\n\t\"\tEric Twelker\",\r\n\t\"\",\r\n\tN_(\"Associate Product Manager\"),\r\n\t\"\tJoe Roth\",\r\n\t\"\",\r\n\tN_(\"Thanks to\"),\r\n\t\"\tCindy Vanous, Joshua Bentley, Robert Zimmerman, Robert Jerauld,\",\r\n\t\"\tDennis Ham, Andrea Stone, Beth Quintana, Jennifer Keenan, Gary Brown,\",\r\n\t\"\tKen Eaton, Matt Eslick, Kate Powell, Bryon Mcpherson, David Beetlestone\",\r\n\t\"\",\r\n\t\"\",\r\n\tN_(\"The Ring of One Thousand\"),\r\n\t\"\tAndrew Abernathy, Christopher Abramo, David Adams, David \",\r\n\t\"\tAdcox, Marko Agterberg, Cory Aiken, Judah Altaras, John \",\r\n\t\"\tAlvarez, Jose Alvarez, Richard Amable, Alexander Amaral, \",\r\n\t\"\tScott Amis, Vincent Amoroso, Mark An, David Andersen, Jason \",\r\n\t\"\tAndrew Abernathy, Christopher Abramo, David Adams, David \",\r\n\t\"\tAdcox, Marko Agterberg, Cory Aiken, Judah Altaras, John \",\r\n\t\"\tAlvarez, Jose Alvarez, Richard Amable, Alexander Amaral, \",\r\n\t\"\tScott Amis, Vincent Amoroso, Mark An, David Andersen, Jason \",\r\n\t\"\tAndersen, Aaron Anderson, George Anderson, Matthew \",\r\n\t\"\tAnderson, Michael Anderson, Sean Anderson, Robert Andrade, \",\r\n\t\"\tCerny Andre, Michael Andreev, Devin Angle, Brian Apple, \",\r\n\t\"\tBrian Arbuthnot, Billy Arden, Dorian Arnold, Andre Arsenault, \",\r\n\t\"\tErik Asplund, Mark Assam, John Athey, Jason Attard, Jeff \",\r\n\t\"\tAtwood, Ricky Au, Scott Avery, Rand Babcock, Steve Babel, \",\r\n\t\"\tRaymond Bacalso, Ed Bachta, Steven Back, Scott Baeder, Alex \",\r\n\t\"\tBaevski, Scott Bailey, Kenneth Baird, Thomas Baker, Todd \",\r\n\t\"\tBala, Jan Ball, Greg Baltz, Blake Baltzley, Doug Bambrick, Wes \",\r\n\t\"\tBangerter, Paul Barfuss, Chris Barghout, Dave Barnebey, Jon \",\r\n\t\"\tBarnhart, Terje Barth, Nicole Baskin, Bernard Baylen, Ryan \",\r\n\t\"\tBear, Phil Bedard, Todd Belcher, Chip Bell, Erez Ben-Aharon, \",\r\n\t\"\tJonathan Bender, Nick Bennett, Ireney Berezniak, Ted Berg, \",\r\n\t\"\tGunnar Bergem, Russell Beuker, Ed Bickford, Stephen Biles, \",\r\n\t\"\tJohn Billdt, Gerald Binder, John Bird, Hannah Blackerby, Tom \",\r\n\t\"\tBlackerby, Clayton Blackwell, Thomas Blake, Shawn Blaszak, \",\r\n\t\"\tDaniel Bliss, Fred Bliss, Jeff Bliss, Jon Blum, Rune Boersjoe, \",\r\n\t\"\tAndrew Boggs, Dave Boisvenu, Joe Bolt, John Bonds, Jeff \",\r\n\t\"\tBorenstein, Dorian Borin, Ed Boris, Bartholomew Botta, \",\r\n\t\"\tMichael Boutin, Michael Boyd, Charles Boyer, Mike \",\r\n\t\"\tBoyersmith, Michael Boyko, Eric Bradberry, John Brandstetter, \",\r\n\t\"\tRyan Breding, Paul Brinkmann, Patrick Briscoe, Scott Brisko, \",\r\n\t\"\tJeremy Britton, Adrian Broadhead, Glenn Brouwer, Joe Brown, \",\r\n\t\"\tSébastien Brulotte, Darrell Brunsch, William Bryan, Jason \",\r\n\t\"\tBucher, Chris Buchinger, Clayton Buckingham, John Buckles, \",\r\n\t\"\tDavid Bugay, Ed Bujone, Erik Burgess, Gabriel Burkett, Chris \",\r\n\t\"\tBurnes, Richard Butler, Jeffrey Bye, Dougall Campbell, Donnie \",\r\n\t\"\tCannon, Shane Cantrell, Connor Caple, Daniel Carey, James \",\r\n\t\"\tCarlton, Michael Carmel, Mike Carpenter, Ronald Carruthers, \",\r\n\t\"\tPhil Carter, Bryce Cartmill, Eric Cartwright, Anthony Caruso, \",\r\n\t\"\tLon Casey, Tim Caster, Aaron Chan, Otto Chan, Gene Chang, \",\r\n\t\"\tHsiao-Lung Chang, William Chang, George Chappel, Larry \",\r\n\t\"\tCharbonneau, Troy Chase, Bruce Chen, Chun Hsien Chen, Sam \",\r\n\t\"\tChen, Tzu-Mainn Chen, Mike Cheng, Chris Chiapusio, Damien \",\r\n\t\"\tChiesa, Nick Chin, Nim Ching, Jonathan Chinn, Michael Chinn, \",\r\n\t\"\tPhilander Chiu, Thayne Christiansen, Philip Chui, Steve \",\r\n\t\"\tCintamani, Richard Ciordia, Colin Clark, Steve Clark, Samuel \",\r\n\t\"\tClements, Meredith Clifton, Jeff Cohen, Dale Colton, Dax \",\r\n\t\"\tCombe, Matt Compton, Jacob Conklin, Richard Conn, Zac \",\r\n\t\"\tCook, Tim Coolong, Gregory Coomer, Dennis Cosgrove, Kelly \",\r\n\t\"\tCouch, Andrew Coulter, Eric Coutinho, David Coutts, James \",\r\n\t\"\tCraig, John Craig, Kazial Craig, John Crawford, Marcelo \",\r\n\t\"\tCrespo, Orville Crews, Tim Cristy, Elmer Crosby III, Russell \",\r\n\t\"\tCullison, Ryan Cupples, Andrew Dagley, Steve Dallaire, Richard \",\r\n\t\"\tDalton, David Dandar, Pro Daulo, Rob Dautermann, Mike \",\r\n\t\"\tDavies, Kalieb Davis, Marshall Davis, Ronald Davis, Danny De \",\r\n\t\"\tBie, Marc De Filippis, Myles Deighton, Kent Dejarnett, Anthony \",\r\n\t\"\tDelarosa, Neil Dempster, Peter Denitto, Joaquim Dentz, Scott \",\r\n\t\"\tDewar, Anish Dhingra, Philip Dhingra, David Diaz, Stewart \",\r\n\t\"\tDicks, Brad Dietz, Josh Dietz, Colleen Diggins, Mike Ditchburn, \",\r\n\t\"\tEric Dittman, Allen Do, Huy Doan, Matthew Dolman, Antoine \",\r\n\t\"\tDongois, Eamonn Donohoe, Bill Dorell, Mark Dorison, Dan \",\r\n\t\"\tDorsett, Chris Dorsey, Jim Dosé, Willis Doss, Chin Du, William \",\r\n\t\"\tDubis, Timothy Duewell, Brandon Dunn, Andrew Durham, Don \",\r\n\t\"\tDuvall, Kevin Dvojack, Daniel Eaton, Paul Eberting, Eric \",\r\n\t\"\tEchelbarger, Lance Eddleman, Ben Eggers, David Eggum, John \",\r\n\t\"\tEhde, Brian Eikenberry, Patrick Elven, Peter Engdahl, Philip \",\r\n\t\"\tEngdahl, Michael Ennis, Darren Eslinger, Eric Ezell, Darren \",\r\n\t\"\tFalslev, Stephen Feather, Tony Fenn, Ben Ferguson, Mike \",\r\n\t\"\tFernandez, Gwendal Feuillet, Guy Fietz, Julian Figueroa, Dale \",\r\n\t\"\tFillpot, Stan Finchem, Michael Finley, Nick Fisher, William \",\r\n\t\"\tFisher, Mark Fitlin, Dave Flatt, Joel J. Flores, John Folkers, \",\r\n\t\"\tSteven Forgie, Tom Forsythe, Matthew Foster, Scott Francis, \",\r\n\t\"\tJim Frank, Paulo Fraser, Glenn French, Kurt Frerichs, Chris \",\r\n\t\"\tFrey, Mark Friedman, Charles Friedmann, Dan Friend, Kirk \",\r\n\t\"\tFry, Aaron Fu, Erik Gaalema, Brandon Gabbard, Phil Gagner, \",\r\n\t\"\tTommy Gannon, David Gappmayer, Chris Garrison, Tony \",\r\n\t\"\tGarrison, David Gasca, Jeremy Gasser, Michael Geist, Michael \",\r\n\t\"\tGenereux, Daniel Genovese, Josh Gerwin, Paul Gibson, William \",\r\n\t\"\tGilchrist, Gabriel Gils Carbo, Chad Glendenin, Ryan Glinski, \",\r\n\t\"\tDean Gobrecht, Andrew Goldfinch, David Goodman, Mark \",\r\n\t\"\tGoodson, Matt Gordon, Frank Gorgenyi, Sean Gould, Perry \",\r\n\t\"\tGoutsos, Ed Govednik, Michael Grayson, Chris Green, Justin \",\r\n\t\"\tGrenier, Jeff Greulich, Don Grey, Rob Griesbeck, Don Griffes, \",\r\n\t\"\tKimberly Griffeth, Jay Grizzard, Don Gronlund, Joe Gross, \",\r\n\t\"\tTroy Growden, Greg Guilford, David Gusovsky, Jeremy \",\r\n\t\"\tGuthrie, Adam Gutierrez, James Guzicki, Matthew Haas, Matt \",\r\n\t\"\tHadley, Ryan Hagelstrom, Bobby Hagen, Ben Hall, Brian Hall, \",\r\n\t\"\tKris Hall, Calvin Hamilton, Kris Hamilton, Bo Hammil, Dave \",\r\n\t\"\tHans, Rick Hansen, Robert Harlan, Travis Harlan, Seth \",\r\n\t\"\tHarman, Jeff Harris, Shawn Hartford, Adam Hartsell, Neil \",\r\n\t\"\tHarvey, Ray Hayes, John Hein, Chris Heinonen, Christer \",\r\n\t\"\tHelsing, Chris Hempel, Dustin Hempel, Mathieu Henaire, Matt \",\r\n\t\"\tHenry, Chuck Herb, Michael Herron, Sage Herron, Thomas \",\r\n\t\"\tHerschbach, Cliff Hicks, Nelson Hicks, Paul Hierling, William \",\r\n\t\"\tHiers, Mike Higdon, Tim Hildebrand, Casey Hinkle, Ryan \",\r\n\t\"\tHitchings, Wes Hix, Alan Ho, Jenson Ho, Alan Hoffman, Jeff \",\r\n\t\"\tHoffman, Eleanor Hoffmann, Steve Hogg, Richard Holler, Brian \",\r\n\t\"\tHomolya, Wade Hone, Joe Horvath, Jeff Howe, Eric Hudson, \",\r\n\t\"\tGlen Huey, Chris Hufnagel, Joshua Hughes, Melissa Hughes, \",\r\n\t\"\tArief Hujaya, Thomas Hulen, Ryan Hupp, Justin Hurst, Rick \",\r\n\t\"\tHutchins, Steve Iams, Mike Iarossi, Bjorn Idren, Johan Idrén, \",\r\n\t\"\tMicah Imparato, Joe Ingersoll, David Ingram, Greg Ipp, Rodney \",\r\n\t\"\tIrvin, Darin Isola, Justin Itoh, Mario Ivan, Fredrik Ivarsson, \",\r\n\t\"\tDax Jacobson, Michael Jacques, Stevens Jacques, Duane Jahnke, \",\r\n\t\"\tWilliam Jambrosek, Daniel Janick, Narciso Jaramillo, Neil \",\r\n\t\"\tJariwala, Harvie Jarriell, Scott Javadi, Joe Jenkins, Bart \",\r\n\t\"\tJennings, Paul Jennings, Julien Jenny, Jason Jensen, Martin \",\r\n\t\"\tJeremy, Mark Jeschke, Andy Johnson, James Johnson, Leigh \",\r\n\t\"\tJohnson, Mark Johnson, Rupert Johnson, Clyde Jones, Michael \",\r\n\t\"\tJones, Tim Jordan, Ben Judy, Michael Kaae, Steve Kaczkowski, \",\r\n\t\"\tNeville Kadwa, Brian Kaisner, Yoshihisa Kameyama, Michael \",\r\n\t\"\tKanemura, Daniel Kao, Eric Karabin, Ben Katz, Christopher \",\r\n\t\"\tKawamura, Erick Kayser, Craig Keddie, Kevin Kelley, Bryan \",\r\n\t\"\tKemp, Michael Kendrigan, Dan Kerber, Timothy Kerber, Tomi \",\r\n\t\"\tKeski-Heikkilä, Greg Kettering, Nathan Kilber, Howard Kim, \",\r\n\t\"\tOrrin Kinion, Jon Kirst, David Kitch, John Klingbeil, Neil \",\r\n\t\"\tKlopfenstein, Kerry Knouse, David Knox, Said Kobeissi, Jeff \",\r\n\t\"\tKoches, Hades Kong, Jeff Kong, Kevin Konkle, Steve Koon, \",\r\n\t\"\tDavid Koontz, Dan Koopmann, Steve Koskela, Kuan Kou, \",\r\n\t\"\tCameron Kracke, Jensen Krage, York Kramer, Cedar Kraus, \",\r\n\t\"\tJason Kraus, Bobby Krimen, Melissa Krispli, Steven Krispli, \",\r\n\t\"\tJames Kruger, Charles Kubasta, Kimmo Kulonen, Frank \",\r\n\t\"\tLackaff, Michael Lacour, Matt Lake, Jason Landry, Hans Erik \",\r\n\t\"\tLange, Michael Laramee, Brad Lascelle, Pat Laschinger, Alan \",\r\n\t\"\tLau, Sean Laurence, Anthony Lavey, Jr., Gary Le, Huey Le, \",\r\n\t\"\tStephane Le Roy Audy, Lim Leandro, Charles Lee, Conroy Lee, \",\r\n\t\"\tMike Lee, Shih-Hang Lee, Jonathan Leipert, Jason Lemann, \",\r\n\t\"\tRon Lenzi, Mitchell Leon, Stephanie Lesniewski, Brendan \",\r\n\t\"\tLewis, Robert Lewis, Sam Liao, Tom Liem, Adam Ligas, Steven \",\r\n\t\"\tLiggett, Roger Lilley, Benjamin Lim, Jeff Lindholm, Johnson \",\r\n\t\"\tLinwood, David Litchman, Bruce Lithimane, William Liu, \",\r\n\t\"\tWilson Liu, Robert Lobdell, Chris Logan, Razvan Loghin, Jack \",\r\n\t\"\tLoh, George Loo, Russell Love, Juan Loyola, Ricardo Lozano, \",\r\n\t\"\tMike Luban, Tim Luc, Henry Luciano, Dianne Ludwig, Charles \",\r\n\t\"\tLueras, Derek Lung, Phong Ly, Scott MacGillivray, Dave Mack, \",\r\n\t\"\tAlec Mak, Steve Mamayek, Michael Mancini, Daniel Mann, \",\r\n\t\"\tMichael Mann, Chris Manofsky, Abdullah Marafie, Nicholas \",\r\n\t\"\tMarcy, Piompino Mariano, Bob Marius, Trey Marshall, Dane \",\r\n\t\"\tMartin, Gregg Martin, Renard Martin, Rich Martin, Scott \",\r\n\t\"\tMartin, Thomas Martin, Jon Masters, Christopher Mathews, \",\r\n\t\"\tJay Mathis, Marc Matthews, Chris Mazur, Doug McBride, \",\r\n\t\"\tMackey McCandlish, Robin McCollum, Steven McCombie, \",\r\n\t\"\tAndy McConnell, Michael McCourt, Bill McCoy, Doug \",\r\n\t\"\tMcCracken, Michael McDeed, Robert McDonald, Steve \",\r\n\t\"\tMcEachron, Craig McGee, Ryan McKenzie, Michael McKeown, \",\r\n\t\"\tDaniel McMahon, Colin McMillan, Ian McWilliam, Mark \",\r\n\t\"\tMcWilliams, Khann Mean, Bryan Meason, Kenneth Medley, \",\r\n\t\"\tJeff Meek, John Mehr, Christopher Mende, Brian Mendenhall, \",\r\n\t\"\tPeter Mengel, Michael Mersic, Mike Messom, Don Metcalf, \",\r\n\t\"\tGary Metzker, Scott Meyer, Joseph Michaud, Andrew Mielke, \",\r\n\t\"\tTravis Mikalson, Troy Milburn, Ike Miller, Ronnie Miller, Sean \",\r\n\t\"\tMiller, Steve Miller, Arthur Min, David Minniti, Brenda \",\r\n\t\"\tMirsberger, Bill Misek, David Mitchell, Joseph Mobley, Robert \",\r\n\t\"\tMollard, Will Mooar, Curtis Moore, Matthew Moore, Al \",\r\n\t\"\tMorales, Ryan Moran, Lance Mortensen, Karel Mrazek, Ward \",\r\n\t\"\tMullee, William Munoz, Kirk Munro, Craig Murray, Shawn P. \",\r\n\t\"\tMurray, Travis Murray, Michael Mushrush, Tom Mustaine, \",\r\n\t\"\tDavid Myers, Joseph Myett, Morgan Najar, Kenta Nakamura, \",\r\n\t\"\tDamian Nastri, Joshua Naumann, Nick Navarro, Douglas \",\r\n\t\"\tNeitzel, Arnold Ng, Anthony Nguyen, Steve Nguyen, Joseph \",\r\n\t\"\tNicholas, Charles Nickolaus, Jon Nisbet, Patrick Nomee, David \",\r\n\t\"\tNorling-Christensen, Bobby Norton, Joseph Nottingham, Frank \",\r\n\t\"\tO'Connor, Jon Oden, David Oester, Lavern Ogden, Zach \",\r\n\t\"\tOglesby, Lucas Oldfield, Toby Olsson, Aaron Ondek, Sean \",\r\n\t\"\tO'Neill, John Orlando, Samuel Orlando, Donovan Orloski, \",\r\n\t\"\tDavid Pai, Nikolas Paldan, David Palek, John Palmieri, Anthony \",\r\n\t\"\tPalmisano, Sanjay Pandit, Jesse Park, Alex Parker, Jimmy \",\r\n\t\"\tPasher, Lukasz Paszek, Andy Patterson, William Pelletier, \",\r\n\t\"\tDuane Pemberton, Ivan Pemic, Kelly Pendergast, Mike \",\r\n\t\"\tPenezich, Jon Penk, Willie Penley, Ron Penna, Matthew \",\r\n\t\"\tPennington, Kevin Pereira, Ross Perez, Ken Perkins, Brian \",\r\n\t\"\tPeterik, Kelly Peterson, Chris Phillips, Rod Pickett, Cameron \",\r\n\t\"\tPierce, Reuben Pierce, Tim Pilger, Billy Pippin, Brad Plank, \",\r\n\t\"\tBrian Plant, Craig Platt, David Plunkett, Michael Politi, Albert \",\r\n\t\"\tPortillo, Brian Powell, David Powell, Franklin Powers Jr., Alan \",\r\n\t\"\tPrecourt, Michael Pronchick, Julian Quintana, Justin Radziej, \",\r\n\t\"\tSteven Rajewski, Shawn Rawles, Ian Reardon, Marc Reed, Ric \",\r\n\t\"\tReichelt, Judd Reiffin, David Reilly, Garry Reisky, Drew \",\r\n\t\"\tRessler, Robert Reynolds, Walter Reynolds, Michael Rice, Ian \",\r\n\t\"\tRichards, James Richards, Raymond Richmond, Dustin Riggs, \",\r\n\t\"\tKeith Riskey, Brian Ro, Scott Roberts, Jorge Rodriguez, Chad \",\r\n\t\"\tRogers, Clint Rogers, Robert Rogers, Steve Rogers, Ethan Roots, \",\r\n\t\"\tRon Roque, William Ross, Sebastian Rossi, Jeff Rostis, Ben \",\r\n\t\"\tRoth, Demar Roth, Rich Rouse, Oleg Rovner, Jonathan Roy, \",\r\n\t\"\tDrew Rozema, Mike Ruggles, Mathias Russ, James Russell, Jim \",\r\n\t\"\tRutledge, James Rutter, Dave Ryder, Chris Salvadras, Anders \",\r\n\t\"\tSamnerud, Nick Sanders, Jakob Sandgren, Joe Sapinsky, Tyler \",\r\n\t\"\tSargent, Jonas Saunders, Mark Savage, Scott Sawyer, Robert \",\r\n\t\"\tScanlon, Trevor Schaben, Aaron Schmidt, Chris Schmidt, Greg \",\r\n\t\"\tSchultz, Nicholas Schumacher, Scott Schumacher, Kevin Scott, \",\r\n\t\"\tRastislav Seffer, Robert Seidler, Corey Sellers, Justin Sellers, \",\r\n\t\"\tMarc Senecal, George Shannon, Ian Sheffield, Anoop Shekar, \",\r\n\t\"\tSandeep Shekar, Kevin Shelton, Leon Shephard, Eric Shepperd, \",\r\n\t\"\tJeffrey Shneidman, Samuel Shockey, Mark Shoemaker, Mike \",\r\n\t\"\tShupe, Sean Sibbet, Brian Sidharta, Jimmy Sieben, Eric \",\r\n\t\"\tSiemens, William Silva, Jody Simpson, Jatinder Singh, Sonia \",\r\n\t\"\tSiu, Omar Skarsvaag, Tom Skiba, Carl Skow, David Skuse, \",\r\n\t\"\tRobert Slifka, Brent Smith, C. Eric Smith, Jared Smith, Jeffrey \",\r\n\t\"\tSmith, Owen Smith, Shannon Smith, Steven Smith, Edward Smola, \",\r\n\t\"\tMatthew Sneep, Eric Snow, Brad Sobel, Jean-Pierre Solignac, Rasmus \",\r\n\t\"\tSørensen, Andrew Sorg, Poppy Southcott, Ross Specter, Erik Spencer, \",\r\n\t\"\tKeith Spencer, Chris Springer, Erikson Squier, Dean St. Onge, Stewart \",\r\n\t\"\tStanfield, John Stanley, Terrence Staton, Benjamin Stein, James \",\r\n\t\"\tSteiner, David Steyer, William Stickney, Chris Stiff, James Stofer, \",\r\n\t\"\tNorm Storch, Patrick Stovall, Brandon Sturgeon, Sean Stutler, Anne \",\r\n\t\"\tSukprasert, Jamal Sullivan, Bruce Sully, Jay Sung, Park Sung \",\r\n\t\"\tJoon, Stein Sunnarvik, Nathan Surginer, Robert Swaringen, Lee \",\r\n\t\"\tSweeney, David Szabo, Scott Taft, Christian Takvam, Patrick \",\r\n\t\"\tTalaska, Tadashi Tamaki, Simon Tan, Mark Taraba, Khon-\",\r\n\t\"\tWhey Tay, John Taylor, Keith Taylor, Donald Temean, Phillip \",\r\n\t\"\tTesar, Pete Thao, Brian Thomas, Keith Thomas, Speed Thomas, \",\r\n\t\"\tMiles Thorpe, Paul Thurrott, Mike Timbol, Nicholas Timmins, \",\r\n\t\"\tTom Tobin, Robert Towster, Hien Tran, Timothy Traviss, Toby \",\r\n\t\"\tTraylor, Tony Treadwell, George Tremoulis, Paul Trinh, Thanh \",\r\n\t\"\tTrinh, Chris Tristan, Brad Truswell, Jason Tryon, Mike Tu, \",\r\n\t\"\tGernel Tuazon, Eric Tuggle, Mike Turnbull, Lyle Ubben, \",\r\n\t\"\tAmilcar Ubiera, Robert Ulozas, Arie Upton, Mark Van Noy, \",\r\n\t\"\tMatthew Van Sickler, Jake Vantlin, Tony Vasquez, Brady \",\r\n\t\"\tVauclin, Gianpiero Vecchi, Chad Verrall, Chris Vicente, Brett \",\r\n\t\"\tVickers, David Vickery, Jonathan Vilante, Simon Vince, Ben \",\r\n\t\"\tVinson, David Voelkert, Paul Vogt, Nicholas Voorhies, Robert \",\r\n\t\"\tVreeland, Mike Vrooman, Rick Vuong, Brian Wachhaus, Todd \",\r\n\t\"\tWachhaus, Caine Wade, Mathew Wadstein, Kenneth Wagenius, \",\r\n\t\"\tTrevor Wagner, John Wagstaff, Asad Wahid, Richard \",\r\n\t\"\tWahlberg, Helio Wakasugui, Richard Walker, Wilkins Walker, \",\r\n\t\"\tMatthew Wallace, Daniel Walsh, Joel Walters, Andrew Waltz, \",\r\n\t\"\tTom Wang, Tony Wang, Jay Ward, Jonathan Ward, John \",\r\n\t\"\tWarner, Mark Warren, Matt Washer, Mike Watson, Sean \",\r\n\t\"\tWattles, Mike Wayne, Christian Wehba, Benjamin Wei, Richard \",\r\n\t\"\tWeight, Cary Wells, David Wenck, Bill Werring, Leonard \",\r\n\t\"\tWesley, Marlon West, Mikael Westerbacka, Brian Wharry, \",\r\n\t\"\tChris White, Chris White, Jeremy White, Greg Whitlock, Gary \",\r\n\t\"\tWidener, Marty Wilfried, Israel Wilkinson, Michael Willams, \",\r\n\t\"\tDerek Williams, Sean Willson, Nitzan Wilnai, Jim Wilson, \",\r\n\t\"\tKarsten Wilson, William Wilt, Tim Winn, Brian Winzeler, Matt \",\r\n\t\"\tWise, Lee Wissmiller, Brendan Wolfe, Daniel Wolpert, Felix \",\r\n\t\"\tWong, Power Wong, Tony Wong, Tim Wood, Timothy Wood, \",\r\n\t\"\tJeremy Woods, Michael Woods, Bill Wright, Keith Wright, \",\r\n\t\"\tPatrick Wu, Gang Xie, Robert Yao, Sun Lim Yap, Stephen Yau, \",\r\n\t\"\tErek Yedwabnick, Christopher Yee, Nick Yee, Juan Yip, David \",\r\n\t\"\tYoung, Rob Young, Seth Young, Alex Yu, Terry Zahn, Jia-Ning \",\r\n\t\"\tZhang, Eric Zieg, Jordan Zielin, Clint Zimmerman, Matt Zinke \",\r\n\t\"\",\r\n\t\"\",\r\n\t\"\",\r\n\t\"\",\r\n\tN_(\"\tNo souls were sold in the making of this game.\"),\r\n\t\"\",\r\n\t\"\",\r\n\t\" \",\r\n\t\" \",\r\n\t\" \"\r\n};\r\n\r\nconst std::size_t CreditLinesSize = sizeof(CreditLines) / sizeof(CreditLines[0]);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/credits_lines.h",
    "content": "#include <cstddef>\r\n\r\nnamespace devilution {\r\n\r\nextern const char *const CreditLines[];\r\nextern const std::size_t CreditLinesSize;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/diabloui.cpp",
    "content": "#include \"DiabloUI/diabloui.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"DiabloUI/button.h\"\r\n#include \"DiabloUI/scrollbar.h\"\r\n#include \"DiabloUI/text_input.hpp\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"appfat.h\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/controller.h\"\r\n#include \"controls/input.h\"\r\n#include \"controls/menu_controls.h\"\r\n#include \"diablo.h\"\r\n#include \"discord/discord.h\"\r\n#include \"effects.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/load_pcx.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/sound.h\"\r\n#include \"engine/surface.hpp\"\r\n#include \"engine/ticks.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"init.hpp\"\r\n#include \"options.h\"\r\n#include \"player.h\"\r\n#include \"sound_effect_enums.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/screen_reader.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#ifdef __SWITCH__\r\n// for virtual keyboard on Switch\r\n#include \"platform/switch/keyboard.h\"\r\n#endif\r\n#ifdef __vita__\r\n// for virtual keyboard on Vita\r\n#include \"platform/vita/keyboard.h\"\r\n#endif\r\n#ifdef __3DS__\r\n// for virtual keyboard on 3DS\r\n#include \"platform/ctr/keyboard.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteList ArtLogo;\r\nOptionalOwnedClxSpriteList DifficultyIndicator;\r\n\r\nstd::array<OptionalOwnedClxSpriteList, 3> ArtFocus;\r\n\r\nOptionalOwnedClxSpriteList ArtBackgroundWidescreen;\r\nOptionalOwnedClxSpriteList ArtBackground;\r\nOptionalOwnedClxSpriteList ArtCursor;\r\n\r\nstd::size_t SelectedItem = 0;\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList ArtHero;\r\nstd::vector<uint8_t> ArtHeroPortraitOrder;\r\nstd::vector<OptionalOwnedClxSpriteList> ArtHeroOverrides;\r\n\r\nstd::size_t SelectedItemMax;\r\nstd::size_t ListViewportSize = 1;\r\nstd::size_t listOffset = 0;\r\n\r\nvoid (*gfnListFocus)(size_t value);\r\nvoid (*gfnListSelect)(size_t value);\r\nvoid (*gfnListEsc)();\r\nvoid (*gfnFullscreen)();\r\nbool (*gfnListYesNo)();\r\nstd::vector<UiItemBase *> gUiItems;\r\nUiList *gUiList = nullptr;\r\nbool UiItemsWraps;\r\n\r\nstd::optional<TextInputState> UiTextInputState;\r\nbool allowEmptyTextInput = false;\r\n\r\nconstexpr Uint32 ListDoubleClickTimeMs = 500;\r\nstd::size_t lastListClickIndex = static_cast<std::size_t>(-1);\r\nUint32 lastListClickTicks = 0;\r\n\r\nstruct ScrollBarState {\r\n\tbool upArrowPressed;\r\n\tbool downArrowPressed;\r\n\r\n\tScrollBarState()\r\n\t{\r\n\t\tupArrowPressed = false;\r\n\t\tdownArrowPressed = false;\r\n\t}\r\n} scrollBarState;\r\n\r\nvoid AdjustListOffset(std::size_t itemIndex)\r\n{\r\n\tif (itemIndex >= listOffset + ListViewportSize)\r\n\t\tlistOffset = itemIndex - (ListViewportSize - 1);\r\n\tif (itemIndex < listOffset)\r\n\t\tlistOffset = itemIndex;\r\n}\r\n\r\nuint32_t fadeTc;\r\nint fadeValue;\r\n\r\nvoid StartUiFadeIn()\r\n{\r\n\tfadeValue = 0;\r\n\tfadeTc = 0;\r\n}\r\n\r\nvoid UiUpdateFadePalette()\r\n{\r\n\tif (fadeValue == 256) return;\r\n\tif (fadeValue == 0 && fadeTc == 0) {\r\n\t\t// Start the fade-in.\r\n\t\tfadeTc = SDL_GetTicks();\r\n\t\tfadeValue = 0;\r\n\t\tBlackPalette();\r\n\t\t// We can skip hardware cursor update for fade level 0 (everything is black).\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int prevFadeValue = fadeValue;\r\n\tfadeValue = static_cast<int>((SDL_GetTicks() - fadeTc) / 2.083); // 32 frames @ 60hz\r\n\tif (fadeValue == prevFadeValue) return;\r\n\r\n\tif (fadeValue >= 256) {\r\n\t\t// Finish the fade-in:\r\n\t\tfadeValue = 256;\r\n\t\tfadeTc = 0;\r\n\t\tApplyGlobalBrightness(system_palette.data(), logical_palette.data());\r\n\t\tSystemPaletteUpdated();\r\n\t\tif (IsHardwareCursor()) ReinitializeHardwareCursor();\r\n\t\treturn;\r\n\t}\r\n\r\n\tSDL_Color palette[256];\r\n\tApplyGlobalBrightness(palette, logical_palette.data());\r\n\tApplyFadeLevel(fadeValue, system_palette.data(), palette);\r\n\r\n\tSystemPaletteUpdated();\r\n\tif (IsHardwareCursor()) ReinitializeHardwareCursor();\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsTextInputActive()\r\n{\r\n\treturn UiTextInputState.has_value();\r\n}\r\n\r\nvoid UiInitList(void (*fnFocus)(size_t value), void (*fnSelect)(size_t value), void (*fnEsc)(), const std::vector<std::unique_ptr<UiItemBase>> &items, bool itemsWraps, void (*fnFullscreen)(), bool (*fnYesNo)(), size_t selectedItem /*= 0*/)\r\n{\r\n\tSelectedItem = selectedItem;\r\n\tSelectedItemMax = 0;\r\n\tListViewportSize = 0;\r\n\tgfnListFocus = fnFocus;\r\n\tgfnListSelect = fnSelect;\r\n\tgfnListEsc = fnEsc;\r\n\tgfnFullscreen = fnFullscreen;\r\n\tgfnListYesNo = fnYesNo;\r\n\tgUiItems.clear();\r\n\tfor (const auto &item : items)\r\n\t\tgUiItems.push_back(item.get());\r\n\tUiItemsWraps = itemsWraps;\r\n\tlistOffset = 0;\r\n\tif (fnFocus != nullptr)\r\n\t\tfnFocus(selectedItem);\r\n\r\n#ifndef __SWITCH__\r\n\tSDLC_StopTextInput(ghMainWnd); // input is enabled by default\r\n#endif\r\n\tUiScrollbar *uiScrollbar = nullptr;\r\n\tfor (const auto &item : items) {\r\n\t\tif (item->IsType(UiType::Edit)) {\r\n\t\t\tauto *pItemUIEdit = static_cast<UiEdit *>(item.get());\r\n\t\t\tSDL_SetTextInputArea(ghMainWnd, &item->m_rect, 0);\r\n\t\t\tallowEmptyTextInput = pItemUIEdit->m_allowEmpty;\r\n#ifdef __SWITCH__\r\n\t\t\tswitch_start_text_input(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_max_length);\r\n#elif defined(__vita__)\r\n\t\t\tvita_start_text_input(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_max_length);\r\n#elif defined(__3DS__)\r\n\t\t\tctr_vkbdInput(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_value, pItemUIEdit->m_max_length);\r\n#else\r\n\t\t\tSDLC_StartTextInput(ghMainWnd);\r\n#endif\r\n\t\t\tUiTextInputState.emplace(TextInputState::Options {\r\n\t\t\t    .value = pItemUIEdit->m_value,\r\n\t\t\t    .cursor = &pItemUIEdit->m_cursor,\r\n\t\t\t    .maxLength = pItemUIEdit->m_max_length,\r\n\t\t\t});\r\n\t\t} else if (item->IsType(UiType::List)) {\r\n\t\t\tauto *uiList = static_cast<UiList *>(item.get());\r\n\t\t\tSelectedItemMax = std::max(uiList->m_vecItems.size() - 1, static_cast<size_t>(0));\r\n\t\t\tListViewportSize = uiList->viewportSize;\r\n\t\t\tgUiList = uiList;\r\n\t\t\tif (selectedItem <= SelectedItemMax && HasAnyOf(uiList->GetItem(selectedItem)->uiFlags, UiFlags::NeedsNextElement))\r\n\t\t\t\tAdjustListOffset(selectedItem + 1);\r\n\t\t\tSpeakText(uiList->GetItem(selectedItem)->m_text);\r\n\t\t} else if (item->IsType(UiType::Scrollbar)) {\r\n\t\t\tuiScrollbar = static_cast<UiScrollbar *>(item.get());\r\n\t\t}\r\n\t}\r\n\r\n\tAdjustListOffset(selectedItem);\r\n\r\n\tif (uiScrollbar != nullptr) {\r\n\t\tif (ListViewportSize >= static_cast<std::size_t>(SelectedItemMax + 1)) {\r\n\t\t\tuiScrollbar->Hide();\r\n\t\t} else {\r\n\t\t\tuiScrollbar->Show();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid UiRenderListItems()\r\n{\r\n\tUiRenderItems(gUiItems);\r\n}\r\n\r\nvoid UiInitList_clear()\r\n{\r\n\tSelectedItem = 0;\r\n\tSelectedItemMax = 0;\r\n\tListViewportSize = 1;\r\n\tgfnListFocus = nullptr;\r\n\tgfnListSelect = nullptr;\r\n\tgfnListEsc = nullptr;\r\n\tgfnFullscreen = nullptr;\r\n\tgfnListYesNo = nullptr;\r\n\tgUiList = nullptr;\r\n\tgUiItems.clear();\r\n\tUiItemsWraps = false;\r\n}\r\n\r\nvoid UiPlayMoveSound()\r\n{\r\n\teffects_play_sound(SfxID::MenuMove);\r\n}\r\n\r\nvoid UiPlaySelectSound()\r\n{\r\n\teffects_play_sound(SfxID::MenuSelect);\r\n}\r\n\r\nnamespace {\r\n\r\nvoid UiFocus(std::size_t itemIndex, bool checkUp, bool ignoreItemsWraps = false)\r\n{\r\n\tif (SelectedItem == itemIndex)\r\n\t\treturn;\r\n\r\n\tAdjustListOffset(itemIndex);\r\n\r\n\tconst auto *pItem = gUiList->GetItem(itemIndex);\r\n\twhile (HasAnyOf(pItem->uiFlags, UiFlags::ElementHidden | UiFlags::ElementDisabled)) {\r\n\t\tif (checkUp) {\r\n\t\t\tif (itemIndex > 0)\r\n\t\t\t\titemIndex -= 1;\r\n\t\t\telse if (UiItemsWraps && !ignoreItemsWraps)\r\n\t\t\t\titemIndex = SelectedItemMax;\r\n\t\t\telse\r\n\t\t\t\tcheckUp = false;\r\n\t\t} else {\r\n\t\t\tif (itemIndex < SelectedItemMax)\r\n\t\t\t\titemIndex += 1;\r\n\t\t\telse if (UiItemsWraps && !ignoreItemsWraps)\r\n\t\t\t\titemIndex = 0;\r\n\t\t\telse\r\n\t\t\t\tcheckUp = true;\r\n\t\t}\r\n\t\tpItem = gUiList->GetItem(itemIndex);\r\n\t}\r\n\tSpeakText(pItem->m_text);\r\n\r\n\tif (HasAnyOf(pItem->uiFlags, UiFlags::NeedsNextElement))\r\n\t\tAdjustListOffset(itemIndex + 1);\r\n\tAdjustListOffset(itemIndex);\r\n\r\n\tSelectedItem = itemIndex;\r\n\r\n\tUiPlayMoveSound();\r\n\r\n\tif (gfnListFocus != nullptr)\r\n\t\tgfnListFocus(itemIndex);\r\n}\r\n\r\nvoid UiFocusUp()\r\n{\r\n\tif (SelectedItem > 0)\r\n\t\tUiFocus(SelectedItem - 1, true);\r\n\telse if (UiItemsWraps)\r\n\t\tUiFocus(SelectedItemMax, true);\r\n}\r\n\r\nvoid UiFocusDown()\r\n{\r\n\tif (SelectedItem < SelectedItemMax)\r\n\t\tUiFocus(SelectedItem + 1, false);\r\n\telse if (UiItemsWraps)\r\n\t\tUiFocus(0, false);\r\n}\r\n\r\n// UiFocusPageUp/Down mimics the slightly weird behaviour of actual Diablo.\r\n\r\nvoid UiFocusPageUp()\r\n{\r\n\tif (listOffset == 0) {\r\n\t\tUiFocus(0, true, true);\r\n\t} else {\r\n\t\tconst std::size_t relpos = SelectedItem - listOffset;\r\n\t\tstd::size_t prevPageStart = SelectedItem - relpos;\r\n\t\tif (prevPageStart >= ListViewportSize)\r\n\t\t\tprevPageStart -= ListViewportSize;\r\n\t\telse\r\n\t\t\tprevPageStart = 0;\r\n\t\tAdjustListOffset(prevPageStart);\r\n\t\tUiFocus(listOffset + relpos, true, true);\r\n\t}\r\n}\r\n\r\nvoid UiFocusPageDown()\r\n{\r\n\tif (listOffset + ListViewportSize > static_cast<std::size_t>(SelectedItemMax)) {\r\n\t\tUiFocus(SelectedItemMax, false, true);\r\n\t} else {\r\n\t\tconst std::size_t relpos = SelectedItem - listOffset;\r\n\t\tstd::size_t nextPageEnd = SelectedItem + (ListViewportSize - relpos - 1);\r\n\t\tif (nextPageEnd + ListViewportSize <= static_cast<std::size_t>(SelectedItemMax))\r\n\t\t\tnextPageEnd += ListViewportSize;\r\n\t\telse\r\n\t\t\tnextPageEnd = SelectedItemMax;\r\n\t\tAdjustListOffset(nextPageEnd);\r\n\t\tUiFocus(listOffset + relpos, false, true);\r\n\t}\r\n}\r\n\r\nbool HandleMenuAction(MenuAction menuAction)\r\n{\r\n\tswitch (menuAction) {\r\n\tcase MenuAction_SELECT:\r\n\t\tUiFocusNavigationSelect();\r\n\t\treturn true;\r\n\tcase MenuAction_UP:\r\n\t\tUiFocusUp();\r\n\t\treturn true;\r\n\tcase MenuAction_DOWN:\r\n\t\tUiFocusDown();\r\n\t\treturn true;\r\n\tcase MenuAction_PAGE_UP:\r\n\t\tUiFocusPageUp();\r\n\t\treturn true;\r\n\tcase MenuAction_PAGE_DOWN:\r\n\t\tUiFocusPageDown();\r\n\t\treturn true;\r\n\tcase MenuAction_DELETE:\r\n\t\tUiFocusNavigationYesNo();\r\n\t\treturn true;\r\n\tcase MenuAction_BACK:\r\n\t\tif (gfnListEsc == nullptr)\r\n\t\t\treturn false;\r\n\t\tUiFocusNavigationEsc();\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nvoid UiOnBackgroundChange()\r\n{\r\n\tStartUiFadeIn();\r\n\r\n\tif (IsHardwareCursorEnabled() && ArtCursor && ControlDevice == ControlTypes::KeyboardAndMouse && GetCurrentCursorInfo().type() != CursorType::UserInterface) {\r\n\t\tSetHardwareCursor(CursorInfo::UserInterfaceCursor());\r\n\t}\r\n\r\n\t// It may take some time to get to the first `UiFadeIn()` call from here\r\n\t// if there is non-trivial initialization work, such as loading the list\r\n\t// of single-player characters.\r\n\t//\r\n\t// Black out the screen immediately to make it appear more smooth.\r\n\tSDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);\r\n\tif (DiabloUiSurface() == PalSurface)\r\n\t\tBltFast(nullptr, nullptr);\r\n\tRenderPresent();\r\n}\r\n\r\nvoid UiFocusNavigation(SDL_Event *event)\r\n{\r\n\tswitch (event->type) {\r\n\tcase SDL_EVENT_KEY_UP:\r\n\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\tcase SDL_EVENT_MOUSE_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_UP:\r\n\tcase SDL_EVENT_JOYSTICK_AXIS_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_BALL_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_HAT_MOTION:\r\n#ifndef USE_SDL1\r\n\tcase SDL_EVENT_MOUSE_WHEEL:\r\n\tcase SDL_EVENT_FINGER_UP:\r\n\tcase SDL_EVENT_FINGER_MOTION:\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_UP:\r\n\tcase SDL_EVENT_GAMEPAD_AXIS_MOTION:\r\n#endif\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_EXPOSED:\r\n#else\r\n#ifndef USE_SDL1\r\n\tcase SDL_WINDOWEVENT:\r\n#endif\r\n\tcase SDL_SYSWMEVENT:\r\n#endif\r\n\t\tmainmenu_restart_repintro();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tbool menuActionHandled = false;\r\n\tfor (const MenuAction menuAction : GetMenuActions(*event))\r\n\t\tmenuActionHandled |= HandleMenuAction(menuAction);\r\n\tif (menuActionHandled)\r\n\t\treturn;\r\n\r\n#ifndef USE_SDL1\r\n\tif (event->type == SDL_EVENT_MOUSE_WHEEL) {\r\n\t\tif (SDLC_EventWheelIntY(*event) > 0) {\r\n\t\t\tUiFocusUp();\r\n\t\t} else if (SDLC_EventWheelIntY(*event) < 0) {\r\n\t\t\tUiFocusDown();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n#else\r\n\tif (event->type == SDL_MOUSEBUTTONDOWN) {\r\n\t\tswitch (event->button.button) {\r\n\t\tcase SDL_BUTTON_WHEELUP:\r\n\t\t\tUiFocusUp();\r\n\t\t\treturn;\r\n\t\tcase SDL_BUTTON_WHEELDOWN:\r\n\t\t\tUiFocusDown();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tif (UiTextInputState.has_value() && HandleTextInputEvent(*event, *UiTextInputState)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (IsAnyOf(event->type, SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP)\r\n\t    && UiItemMouseEvents(event, gUiItems)) {\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid UiHandleEvents(SDL_Event *event)\r\n{\r\n\tif (event->type == SDL_EVENT_MOUSE_MOTION) {\r\n\t\tMousePosition = { SDLC_EventMotionIntX(*event), SDLC_EventMotionIntY(*event) };\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (event->type == SDL_EVENT_KEY_DOWN && SDLC_EventKey(*event) == SDLK_RETURN) {\r\n\t\tconst auto *state = SDLC_GetKeyState();\r\n\t\tif (state[SDLC_KEYSTATE_LALT] != 0 || state[SDLC_KEYSTATE_RALT] != 0) {\r\n\t\t\tGetOptions().Graphics.fullscreen.SetValue(!IsFullScreen());\r\n\t\t\tSaveOptions();\r\n\t\t\tif (gfnFullscreen != nullptr)\r\n\t\t\t\tgfnFullscreen();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tif (event->type == SDL_EVENT_QUIT) {\r\n\t\tdiablo_quit(0);\r\n\t}\r\n\r\n#ifndef USE_SDL1\r\n\tHandleControllerAddedOrRemovedEvent(*event);\r\n\r\n#ifdef USE_SDL3\r\n\tswitch (event->type) {\r\n\tcase SDL_EVENT_WINDOW_SHOWN:\r\n\tcase SDL_EVENT_WINDOW_EXPOSED:\r\n\tcase SDL_EVENT_WINDOW_RESTORED:\r\n\t\tgbActive = true;\r\n\t\tbreak;\r\n\tcase SDL_EVENT_WINDOW_HIDDEN:\r\n\tcase SDL_EVENT_WINDOW_MINIMIZED:\r\n\t\tgbActive = false;\r\n\t\tbreak;\r\n\tcase SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:\r\n\t\tDoReinitializeHardwareCursor();\r\n\t\tbreak;\r\n\tcase SDL_EVENT_WINDOW_FOCUS_LOST:\r\n\t\tif (*GetOptions().Gameplay.pauseOnFocusLoss) music_mute();\r\n\t\tbreak;\r\n\tcase SDL_EVENT_WINDOW_FOCUS_GAINED:\r\n\t\tif (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_unpause();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n#else\r\n\tif (event->type == SDL_WINDOWEVENT) {\r\n\t\tif (IsAnyOf(event->window.event, SDL_WINDOWEVENT_SHOWN, SDL_WINDOWEVENT_EXPOSED, SDL_WINDOWEVENT_RESTORED)) {\r\n\t\t\tgbActive = true;\r\n\t\t} else if (IsAnyOf(event->window.event, SDL_WINDOWEVENT_HIDDEN, SDL_WINDOWEVENT_MINIMIZED)) {\r\n\t\t\tgbActive = false;\r\n\t\t} else if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {\r\n\t\t\t// We reinitialize immediately (by calling `DoReinitializeHardwareCursor` instead of `ReinitializeHardwareCursor`)\r\n\t\t\t// because the cursor's Enabled state may have changed, resulting in changes to visibility.\r\n\t\t\t//\r\n\t\t\t// For example, if the previous size was too large for a hardware cursor then it was invisible\r\n\t\t\t// but may now become visible.\r\n\t\t\tDoReinitializeHardwareCursor();\r\n\t\t} else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST && *GetOptions().Gameplay.pauseOnFocusLoss) {\r\n\t\t\tmusic_mute();\r\n\t\t} else if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED && *GetOptions().Gameplay.pauseOnFocusLoss) {\r\n\t\t\tdiablo_focus_unpause();\r\n\t\t}\r\n\t}\r\n#endif\r\n#else\r\n\tif (event->type == SDL_ACTIVEEVENT && (event->active.state & SDL_APPINPUTFOCUS) != 0) {\r\n\t\tif (event->active.gain == 0)\r\n\t\t\tmusic_mute();\r\n\t\telse\r\n\t\t\tdiablo_focus_unpause();\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid UiFocusNavigationSelect()\r\n{\r\n\tUiPlaySelectSound();\r\n\tif (UiTextInputState.has_value()) {\r\n\t\tif (!allowEmptyTextInput && UiTextInputState->empty()) {\r\n\t\t\treturn;\r\n\t\t}\r\n#ifndef __SWITCH__\r\n\t\tSDLC_StopTextInput(ghMainWnd);\r\n#endif\r\n\t\tUiTextInputState = std::nullopt;\r\n\t}\r\n\tif (gfnListSelect != nullptr)\r\n\t\tgfnListSelect(SelectedItem);\r\n}\r\n\r\nvoid UiFocusNavigationEsc()\r\n{\r\n\tUiPlaySelectSound();\r\n\tif (UiTextInputState.has_value()) {\r\n#ifndef __SWITCH__\r\n\t\tSDLC_StopTextInput(ghMainWnd);\r\n#endif\r\n\t\tUiTextInputState = std::nullopt;\r\n\t}\r\n\tif (gfnListEsc != nullptr)\r\n\t\tgfnListEsc();\r\n}\r\n\r\nvoid UiFocusNavigationYesNo()\r\n{\r\n\tif (gfnListYesNo == nullptr)\r\n\t\treturn;\r\n\r\n\tif (gfnListYesNo())\r\n\t\tUiPlaySelectSound();\r\n}\r\n\r\nnamespace {\r\n\r\nbool IsInsideRect(const SDL_Event &event, const SDL_Rect &rect)\r\n{\r\n\tconst SDL_Point point = { SDLC_EventButtonIntX(event), SDLC_EventButtonIntY(event) };\r\n\treturn SDLC_PointInRect(&point, &rect);\r\n}\r\n\r\nvoid LoadHeros()\r\n{\r\n\tconstexpr unsigned PortraitHeight = 76;\r\n\tArtHero = LoadPcxSpriteList(\"ui_art\\\\heros\", -static_cast<int>(PortraitHeight));\r\n\tif (!ArtHero)\r\n\t\treturn;\r\n\tconst uint16_t numPortraits = ClxSpriteList { *ArtHero }.numSprites();\r\n\r\n\tArtHeroPortraitOrder.resize(GetNumPlayerClasses() + 1);\r\n\tfor (size_t i = 0; i < GetNumPlayerClasses(); ++i) {\r\n\t\tconst PlayerData &playerClassData = GetPlayerDataForClass(static_cast<HeroClass>(i));\r\n\t\tArtHeroPortraitOrder[i] = playerClassData.portrait;\r\n\t}\r\n\tArtHeroPortraitOrder.back() = 3;\r\n\tif (numPortraits >= 6) {\r\n\t\tArtHeroPortraitOrder.back() = 5;\r\n\t}\r\n\r\n\tArtHeroOverrides.resize(GetNumPlayerClasses() + 1);\r\n\tfor (size_t i = 0; i <= GetNumPlayerClasses(); ++i) {\r\n\t\tchar portraitPath[18];\r\n\t\t*BufCopy(portraitPath, \"ui_art\\\\hero\", i) = '\\0';\r\n\t\tArtHeroOverrides[i] = LoadPcx(portraitPath, /*transparentColor=*/std::nullopt, /*outPalette=*/nullptr, /*logError=*/false);\r\n\t}\r\n}\r\n\r\nvoid LoadUiGFX()\r\n{\r\n\tArtLogo = LoadPcxSpriteList(\"ui_art\\\\hf_logo2\", /*numFrames=*/16, /*transparentColor=*/0, nullptr, false);\r\n\tif (!ArtLogo.has_value()) {\r\n\t\tArtLogo = LoadPcxSpriteList(\"ui_art\\\\smlogo\", /*numFrames=*/15, /*transparentColor=*/250);\r\n\t}\r\n\tDifficultyIndicator = LoadPcx(\"ui_art\\\\r1_gry\", /*transparentColor=*/0);\r\n\tArtFocus[FOCUS_SMALL] = LoadPcxSpriteList(\"ui_art\\\\focus16\", /*numFrames=*/8, /*transparentColor=*/250);\r\n\tArtFocus[FOCUS_MED] = LoadPcxSpriteList(\"ui_art\\\\focus\", /*numFrames=*/8, /*transparentColor=*/250);\r\n\tArtFocus[FOCUS_BIG] = LoadPcxSpriteList(\"ui_art\\\\focus42\", /*numFrames=*/8, /*transparentColor=*/250);\r\n\r\n\tArtCursor = LoadPcx(\"ui_art\\\\cursor\", /*transparentColor=*/0);\r\n\r\n\tLoadHeros();\r\n}\r\n\r\n} // namespace\r\n\r\nClxSprite UiGetHeroDialogSprite(size_t heroClassIndex)\r\n{\r\n\treturn ArtHeroOverrides[heroClassIndex]\r\n\t    ? (*ArtHeroOverrides[heroClassIndex])[0]\r\n\t    : (*ArtHero)[ArtHeroPortraitOrder[heroClassIndex]];\r\n}\r\n\r\nvoid UnloadUiGFX()\r\n{\r\n\tArtHero = std::nullopt;\r\n\tfor (OptionalOwnedClxSpriteList &override : ArtHeroOverrides)\r\n\t\toverride = std::nullopt;\r\n\tArtCursor = std::nullopt;\r\n\tfor (auto &art : ArtFocus)\r\n\t\tart = std::nullopt;\r\n\tArtLogo = std::nullopt;\r\n\tDifficultyIndicator = std::nullopt;\r\n}\r\n\r\nvoid UiInitialize()\r\n{\r\n\tLoadUiGFX();\r\n\r\n\tif (ArtCursor) {\r\n\t\tif (!SDLC_HideCursor()) ErrSdl();\r\n\t}\r\n}\r\n\r\nvoid UiDestroy()\r\n{\r\n\tUnloadFonts();\r\n\tUnloadUiGFX();\r\n}\r\n\r\nbool UiValidPlayerName(std::string_view name)\r\n{\r\n\tif (name.empty())\r\n\t\treturn false;\r\n\r\n\t// Currently only allow saving PlayerNameLength bytes as a player name, so if the name is too long we'd have to truncate it.\r\n\t// That said the input buffer is only 16 bytes long...\r\n\tif (name.size() > PlayerNameLength)\r\n\t\treturn false;\r\n\r\n\tif (name.find_first_of(\",<>%&\\\\\\\"?*#/: \") != name.npos)\r\n\t\treturn false;\r\n\r\n\t// Only basic latin alphabet is supported for multiplayer characters to avoid rendering issues for players who do\r\n\t// not have fonts.mpq installed\r\n\tif (!c_all_of(name, IsBasicLatin))\r\n\t\treturn false;\r\n\r\n\tconst std::string_view bannedNames[] = {\r\n\t\t\"gvdl\",\r\n\t\t\"dvou\",\r\n\t\t\"tiju\",\r\n\t\t\"cjudi\",\r\n\t\t\"bttipmf\",\r\n\t\t\"ojhhfs\",\r\n\t\t\"cmj{{bse\",\r\n\t\t\"benjo\",\r\n\t};\r\n\r\n\tstd::string buffer { name };\r\n\tfor (char &character : buffer)\r\n\t\tcharacter++;\r\n\r\n\tconst std::string_view tempName { buffer };\r\n\tfor (const std::string_view bannedName : bannedNames) {\r\n\t\tif (tempName.find(bannedName) != tempName.npos)\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nSint16 GetCenterOffset(Sint16 w, Sint16 bw)\r\n{\r\n\tif (bw == 0) {\r\n\t\tbw = gnScreenWidth;\r\n\t}\r\n\r\n\treturn (bw - w) / 2;\r\n}\r\n\r\nvoid UiLoadDefaultPalette()\r\n{\r\n\tLoadPalette(\"ui_art\\\\diablo.pal\");\r\n\tUpdateSystemPalette(logical_palette);\r\n}\r\n\r\nbool UiLoadBlackBackground()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\tUiLoadDefaultPalette();\r\n\tUiOnBackgroundChange();\r\n\treturn true;\r\n}\r\n\r\nvoid LoadBackgroundArt(const char *pszFile, int frames)\r\n{\r\n\tArtBackground = std::nullopt;\r\n\tArtBackground = LoadPcxSpriteList(pszFile, static_cast<uint16_t>(frames), /*transparentColor=*/std::nullopt, logical_palette.data());\r\n\tif (!ArtBackground)\r\n\t\treturn;\r\n\r\n\tUpdateSystemPalette(logical_palette);\r\n\tUiOnBackgroundChange();\r\n}\r\n\r\nvoid UiAddBackground(std::vector<std::unique_ptr<UiItemBase>> *vecDialog)\r\n{\r\n\tconst SDL_Rect rect = MakeSdlRect(0, GetUIRectangle().position.y, 0, 0);\r\n\tif (ArtBackgroundWidescreen) {\r\n\t\tvecDialog->push_back(std::make_unique<UiImageClx>((*ArtBackgroundWidescreen)[0], rect, UiFlags::AlignCenter));\r\n\t}\r\n\tif (ArtBackground) {\r\n\t\tvecDialog->push_back(std::make_unique<UiImageClx>((*ArtBackground)[0], rect, UiFlags::AlignCenter));\r\n\t}\r\n}\r\n\r\nvoid UiAddLogo(std::vector<std::unique_ptr<UiItemBase>> *vecDialog, int y)\r\n{\r\n\tvecDialog->push_back(std::make_unique<UiImageAnimatedClx>(\r\n\t    *ArtLogo, MakeSdlRect(0, y, 0, 0), UiFlags::AlignCenter));\r\n}\r\n\r\nvoid UiFadeIn()\r\n{\r\n\tif (HeadlessMode) return;\r\n\tUiUpdateFadePalette();\r\n\tif (DiabloUiSurface() == PalSurface) {\r\n\t\tBltFast(nullptr, nullptr);\r\n\t}\r\n\tRenderPresent();\r\n}\r\n\r\nnamespace {\r\nClxSpriteList GetListSelectorSprites(int itemHeight)\r\n{\r\n\tint size;\r\n\tif (itemHeight >= 42) {\r\n\t\tsize = FOCUS_BIG;\r\n\t} else if (itemHeight >= 30) {\r\n\t\tsize = FOCUS_MED;\r\n\t} else {\r\n\t\tsize = FOCUS_SMALL;\r\n\t}\r\n\treturn *ArtFocus[size];\r\n}\r\n} // namespace\r\n\r\nvoid DrawSelector(const SDL_Rect &rect)\r\n{\r\n\tconst ClxSpriteList sprites = GetListSelectorSprites(rect.h);\r\n\tconst ClxSprite sprite = sprites[GetAnimationFrame(sprites.numSprites())];\r\n\r\n\t// TODO FOCUS_MED appears higher than the box\r\n\tconst int y = rect.y + ((rect.h - static_cast<int>(sprite.height())) / 2);\r\n\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\tRenderClxSprite(out, sprite, { rect.x, y });\r\n\tRenderClxSprite(out, sprite, { rect.x + rect.w - sprite.width(), y });\r\n}\r\n\r\nvoid UiClearScreen()\r\n{\r\n\tif (!ArtBackground || gnScreenWidth > (*ArtBackground)[0].width() || gnScreenHeight > (*ArtBackground)[0].height()) {\r\n\t\tSDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);\r\n\t}\r\n}\r\n\r\nvoid UiPollAndRender(std::optional<tl::function_ref<bool(SDL_Event &)>> eventHandler)\r\n{\r\n\tSDL_Event event;\r\n\twhile (PollEvent(&event)) {\r\n\t\tif (eventHandler && (*eventHandler)(event))\r\n\t\t\tcontinue;\r\n\t\tif (!SDLC_ConvertEventToRenderCoordinates(renderer, &event)) {\r\n\t\t\tLogWarn(LogCategory::Application, \"SDL_ConvertEventToRenderCoordinates: {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t}\r\n\t\tUiFocusNavigation(&event);\r\n\t\tUiHandleEvents(&event);\r\n\t}\r\n\tHandleMenuAction(GetMenuHeldUpDownAction());\r\n\tUiRenderListItems();\r\n\tDrawMouse();\r\n\tUiFadeIn();\r\n\r\n\t// Must happen after at least one call to `UiFadeIn` with non-zero fadeValue.\r\n\t// `UiFadeIn` reinitializes the hardware cursor only for fadeValue > 0.\r\n\tif (IsHardwareCursor() && fadeValue != 0)\r\n\t\tSetHardwareCursorVisible(ControlDevice == ControlTypes::KeyboardAndMouse);\r\n\r\n#ifdef __3DS__\r\n\t// Keyboard blocks until input is finished\r\n\t// so defer until after render and fade-in\r\n\tctr_vkbdFlush();\r\n#endif\r\n\r\n\tdiscord_manager::UpdateMenu();\r\n}\r\n\r\nnamespace {\r\n\r\nvoid Render(const UiText &uiText)\r\n{\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\tDrawString(out, uiText.GetText(), MakeRectangle(uiText.m_rect),\r\n\t    { .flags = uiText.GetFlags() | UiFlags::FontSizeDialog });\r\n}\r\n\r\nvoid Render(const UiArtText &uiArtText)\r\n{\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\tDrawString(out, uiArtText.GetText(), MakeRectangle(uiArtText.m_rect),\r\n\t    { .flags = uiArtText.GetFlags(), .spacing = uiArtText.GetSpacing(), .lineHeight = uiArtText.GetLineHeight() });\r\n}\r\n\r\nvoid Render(const UiImageClx &uiImage)\r\n{\r\n\tconst ClxSprite sprite = uiImage.sprite();\r\n\tint x = uiImage.m_rect.x;\r\n\tif (uiImage.isCentered()) {\r\n\t\tx += GetCenterOffset(sprite.width(), uiImage.m_rect.w);\r\n\t}\r\n\tRenderClxSprite(Surface(DiabloUiSurface()), sprite, { x, uiImage.m_rect.y });\r\n}\r\n\r\nvoid Render(const UiImageAnimatedClx &uiImage)\r\n{\r\n\tconst ClxSprite sprite = uiImage.sprite(GetAnimationFrame(uiImage.numFrames()));\r\n\tint x = uiImage.m_rect.x;\r\n\tif (uiImage.isCentered()) {\r\n\t\tx += GetCenterOffset(sprite.width(), uiImage.m_rect.w);\r\n\t}\r\n\tRenderClxSprite(Surface(DiabloUiSurface()), sprite, { x, uiImage.m_rect.y });\r\n}\r\n\r\nvoid Render(const UiArtTextButton &uiButton)\r\n{\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\tDrawString(out, uiButton.GetText(), MakeRectangle(uiButton.m_rect), { .flags = uiButton.GetFlags() });\r\n}\r\n\r\nvoid Render(const UiList &uiList)\r\n{\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\r\n\tfor (std::size_t i = listOffset; i < uiList.m_vecItems.size() && (i - listOffset) < ListViewportSize; ++i) {\r\n\t\tconst SDL_Rect rect = uiList.itemRect(static_cast<int>(i - listOffset));\r\n\t\tconst UiListItem &item = *uiList.GetItem(i);\r\n\t\tif (i == SelectedItem)\r\n\t\t\tDrawSelector(rect);\r\n\r\n\t\tconst Rectangle rectangle = MakeRectangle(rect).inset(\r\n\t\t    Displacement(GetListSelectorSprites(rect.h)[0].width(), 0));\r\n\r\n\t\tconst UiFlags uiFlags = uiList.GetFlags() | item.uiFlags;\r\n\t\tconst GameFontTables fontSize = GetFontSizeFromUiFlags(uiFlags);\r\n\t\tstd::string_view text = item.m_text.str();\r\n\t\twhile (GetLineWidth(text, fontSize, 1) > rectangle.size.width) {\r\n\t\t\ttext = std::string_view(text.data(), FindLastUtf8Symbols(text));\r\n\t\t}\r\n\r\n\t\tif (item.args.empty()) {\r\n\t\t\tDrawString(out, text, rectangle, { .flags = uiFlags, .spacing = uiList.GetSpacing() });\r\n\t\t} else {\r\n\t\t\tDrawStringWithColors(out, text, item.args, rectangle, { .flags = uiFlags, .spacing = uiList.GetSpacing() });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Render(const UiScrollbar &uiSb)\r\n{\r\n\tconst Surface out = Surface(DiabloUiSurface());\r\n\r\n\t// Bar background (tiled):\r\n\t{\r\n\t\tconst int bgY = uiSb.m_rect.y + uiSb.m_arrow[0].height();\r\n\t\tconst int bgH = DownArrowRect(uiSb).y - bgY;\r\n\t\tconst Surface backgroundOut = out.subregion(uiSb.m_rect.x, bgY, ScrollBarBgWidth, bgH);\r\n\t\tint y = 0;\r\n\t\twhile (y < bgH) {\r\n\t\t\tRenderClxSprite(backgroundOut, uiSb.m_bg, { 0, y });\r\n\t\t\ty += uiSb.m_bg.height();\r\n\t\t}\r\n\t}\r\n\r\n\t// Arrows:\r\n\t{\r\n\t\tconst SDL_Rect rect = UpArrowRect(uiSb);\r\n\t\tconst auto frame = static_cast<uint16_t>(scrollBarState.upArrowPressed ? ScrollBarArrowFrame_UP_ACTIVE : ScrollBarArrowFrame_UP);\r\n\t\tRenderClxSprite(out.subregion(rect.x, 0, ScrollBarArrowWidth, out.h()), uiSb.m_arrow[frame], { 0, rect.y });\r\n\t}\r\n\t{\r\n\t\tconst SDL_Rect rect = DownArrowRect(uiSb);\r\n\t\tconst auto frame = static_cast<uint16_t>(scrollBarState.downArrowPressed ? ScrollBarArrowFrame_DOWN_ACTIVE : ScrollBarArrowFrame_DOWN);\r\n\t\tRenderClxSprite(out.subregion(rect.x, 0, ScrollBarArrowWidth, out.h()), uiSb.m_arrow[frame], { 0, rect.y });\r\n\t}\r\n\r\n\t// Thumb:\r\n\tif (SelectedItemMax > 0) {\r\n\t\tconst SDL_Rect rect = ThumbRect(uiSb, SelectedItem, SelectedItemMax + 1);\r\n\t\tRenderClxSprite(out, uiSb.m_thumb, { rect.x, rect.y });\r\n\t}\r\n}\r\n\r\nvoid Render(const UiEdit &uiEdit)\r\n{\r\n\tDrawSelector(uiEdit.m_rect);\r\n\r\n\t// To simulate padding we inset the region used to draw text in an edit control\r\n\tconst Rectangle rect = MakeRectangle(uiEdit.m_rect).inset({ 43, 1 });\r\n\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\tDrawString(out, uiEdit.m_value, rect,\r\n\t    {\r\n\t        .flags = uiEdit.GetFlags(),\r\n\t        .cursorPosition = static_cast<int>(uiEdit.m_cursor.position),\r\n\t        .highlightRange = { static_cast<int>(uiEdit.m_cursor.selection.begin), static_cast<int>(uiEdit.m_cursor.selection.end) },\r\n\t        .highlightColor = 126,\r\n\t    });\r\n}\r\n\r\nbool HandleMouseEventArtTextButton(const SDL_Event &event, const UiArtTextButton *uiButton)\r\n{\r\n\tif (event.type != SDL_EVENT_MOUSE_BUTTON_UP || event.button.button != SDL_BUTTON_LEFT) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tuiButton->Activate();\r\n\treturn true;\r\n}\r\n\r\nbool HandleMouseEventList(const SDL_Event &event, UiList *uiList)\r\n{\r\n\tif (event.button.button != SDL_BUTTON_LEFT)\r\n\t\treturn false;\r\n\r\n\tif (!IsAnyOf(event.type, SDL_EVENT_MOUSE_BUTTON_UP, SDL_EVENT_MOUSE_BUTTON_DOWN)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tstd::size_t index = uiList->indexAt(event.button.y);\r\n\tif (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {\r\n\t\tuiList->Press(index);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (event.type == SDL_EVENT_MOUSE_BUTTON_UP && !uiList->IsPressed(index)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tindex += listOffset;\r\n\tconst bool hasFocusCallback = gfnListFocus != nullptr;\r\n\tconst Uint32 ticksNow = SDL_GetTicks();\r\n\tconst bool recentlyClickedSameItem = hasFocusCallback && lastListClickIndex == index && ticksNow - lastListClickTicks <= ListDoubleClickTimeMs;\r\n#ifndef USE_SDL1\r\n\tconst bool sdlReportedDoubleClick = event.button.clicks >= 2;\r\n#else\r\n\tconst bool sdlReportedDoubleClick = false;\r\n#endif\r\n\tconst bool doubleClicked = recentlyClickedSameItem || sdlReportedDoubleClick;\r\n\tlastListClickIndex = index;\r\n\tlastListClickTicks = ticksNow;\r\n\r\n\tif (hasFocusCallback && SelectedItem != index) {\r\n\t\tUiFocus(index, true, false);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (hasFocusCallback && !doubleClicked) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (HasAnyOf(uiList->GetItem(index)->uiFlags, UiFlags::ElementHidden | UiFlags::ElementDisabled))\r\n\t\treturn false;\r\n\tSelectedItem = index;\r\n\tUiFocusNavigationSelect();\r\n\r\n\treturn true;\r\n}\r\n\r\nbool HandleMouseEventScrollBar(const SDL_Event &event, const UiScrollbar *uiSb)\r\n{\r\n\tif (event.button.button != SDL_BUTTON_LEFT)\r\n\t\treturn false;\r\n\tif (event.type == SDL_EVENT_MOUSE_BUTTON_UP) {\r\n\t\tif (scrollBarState.upArrowPressed && IsInsideRect(event, UpArrowRect(*uiSb))) {\r\n\t\t\tUiFocusUp();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (scrollBarState.downArrowPressed && IsInsideRect(event, DownArrowRect(*uiSb))) {\r\n\t\t\tUiFocusDown();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {\r\n\t\tif (IsInsideRect(event, BarRect(*uiSb))) {\r\n\t\t\t// Scroll up or down based on thumb position.\r\n\t\t\tconst SDL_Rect thumbRect = ThumbRect(*uiSb, SelectedItem, SelectedItemMax + 1);\r\n\t\t\tif (event.button.y < thumbRect.y) {\r\n\t\t\t\tUiFocusPageUp();\r\n\t\t\t} else if (event.button.y > thumbRect.y + thumbRect.h) {\r\n\t\t\t\tUiFocusPageDown();\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (IsInsideRect(event, UpArrowRect(*uiSb))) {\r\n\t\t\tscrollBarState.upArrowPressed = true;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (IsInsideRect(event, DownArrowRect(*uiSb))) {\r\n\t\t\tscrollBarState.downArrowPressed = true;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool HandleMouseEvent(const SDL_Event &event, UiItemBase *item)\r\n{\r\n\tif (item->IsNotInteractive() || !IsInsideRect(event, item->m_rect))\r\n\t\treturn false;\r\n\tswitch (item->GetType()) {\r\n\tcase UiType::ArtTextButton:\r\n\t\treturn HandleMouseEventArtTextButton(event, static_cast<UiArtTextButton *>(item));\r\n\tcase UiType::Button:\r\n\t\treturn HandleMouseEventButton(event, static_cast<UiButton *>(item));\r\n\tcase UiType::List:\r\n\t\treturn HandleMouseEventList(event, static_cast<UiList *>(item));\r\n\tcase UiType::Scrollbar:\r\n\t\treturn HandleMouseEventScrollBar(event, static_cast<UiScrollbar *>(item));\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid UiRenderItem(const UiItemBase &item)\r\n{\r\n\tif (item.IsHidden())\r\n\t\treturn;\r\n\tswitch (item.GetType()) {\r\n\tcase UiType::Text:\r\n\t\tRender(static_cast<const UiText &>(item));\r\n\t\tbreak;\r\n\tcase UiType::ArtText:\r\n\t\tRender(static_cast<const UiArtText &>(item));\r\n\t\tbreak;\r\n\tcase UiType::ImageClx:\r\n\t\tRender(static_cast<const UiImageClx &>(item));\r\n\t\tbreak;\r\n\tcase UiType::ImageAnimatedClx:\r\n\t\tRender(static_cast<const UiImageAnimatedClx &>(item));\r\n\t\tbreak;\r\n\tcase UiType::ArtTextButton:\r\n\t\tRender(static_cast<const UiArtTextButton &>(item));\r\n\t\tbreak;\r\n\tcase UiType::Button:\r\n\t\tRenderButton(static_cast<const UiButton &>(item));\r\n\t\tbreak;\r\n\tcase UiType::List:\r\n\t\tRender(static_cast<const UiList &>(item));\r\n\t\tbreak;\r\n\tcase UiType::Scrollbar:\r\n\t\tRender(static_cast<const UiScrollbar &>(item));\r\n\t\tbreak;\r\n\tcase UiType::Edit:\r\n\t\tRender(static_cast<const UiEdit &>(item));\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid UiRenderItems(const std::vector<UiItemBase *> &items)\r\n{\r\n\tfor (const UiItemBase *item : items)\r\n\t\tUiRenderItem(*item);\r\n}\r\n\r\nvoid UiRenderItems(const std::vector<std::unique_ptr<UiItemBase>> &items)\r\n{\r\n\tfor (const std::unique_ptr<UiItemBase> &item : items)\r\n\t\tUiRenderItem(*item);\r\n}\r\n\r\nbool UiItemMouseEvents(SDL_Event *event, const std::vector<UiItemBase *> &items)\r\n{\r\n\tif (items.empty()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tbool handled = false;\r\n\tfor (const auto &item : items) {\r\n\t\tif (HandleMouseEvent(*event, item)) {\r\n\t\t\thandled = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (event->type == SDL_EVENT_MOUSE_BUTTON_UP && event->button.button == SDL_BUTTON_LEFT) {\r\n\t\tscrollBarState.downArrowPressed = scrollBarState.upArrowPressed = false;\r\n\t\tfor (const auto &item : items) {\r\n\t\t\tif (item->IsType(UiType::Button)) {\r\n\t\t\t\tHandleGlobalMouseUpButton(static_cast<UiButton *>(item));\r\n\t\t\t} else if (item->IsType(UiType::List)) {\r\n\t\t\t\tstatic_cast<UiList *>(item)->Release();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn handled;\r\n}\r\n\r\nbool UiItemMouseEvents(SDL_Event *event, const std::vector<std::unique_ptr<UiItemBase>> &items)\r\n{\r\n\tif (items.empty()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tbool handled = false;\r\n\tfor (const auto &item : items) {\r\n\t\tif (HandleMouseEvent(*event, item.get())) {\r\n\t\t\thandled = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (event->type == SDL_EVENT_MOUSE_BUTTON_UP && event->button.button == SDL_BUTTON_LEFT) {\r\n\t\tscrollBarState.downArrowPressed = scrollBarState.upArrowPressed = false;\r\n\t\tfor (const auto &item : items) {\r\n\t\t\tif (item->IsType(UiType::Button)) {\r\n\t\t\t\tHandleGlobalMouseUpButton(static_cast<UiButton *>(item.get()));\r\n\t\t\t} else if (item->IsType(UiType::List)) {\r\n\t\t\t\tstatic_cast<UiList *>(item.get())->Release();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn handled;\r\n}\r\n\r\nvoid DrawMouse()\r\n{\r\n\tif (ControlDevice != ControlTypes::KeyboardAndMouse || IsHardwareCursor() || !ArtCursor)\r\n\t\treturn;\r\n\tRenderClxSprite(Surface(DiabloUiSurface()), (*ArtCursor)[0], MousePosition);\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/diabloui.h",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_pcx.hpp\" // IWYU pragma: export\r\n#include \"player.h\"\r\n#include \"utils/display.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern std::size_t SelectedItem;\r\n\r\nbool IsTextInputActive();\r\n\r\nenum _artFocus : uint8_t {\r\n\tFOCUS_SMALL,\r\n\tFOCUS_MED,\r\n\tFOCUS_BIG,\r\n};\r\n\r\nenum _mainmenu_selections : uint8_t {\r\n\tMAINMENU_NONE,\r\n\tMAINMENU_SINGLE_PLAYER,\r\n\tMAINMENU_MULTIPLAYER,\r\n\tMAINMENU_SHOW_SUPPORT,\r\n\tMAINMENU_SETTINGS,\r\n\tMAINMENU_SHOW_CREDITS,\r\n\tMAINMENU_EXIT_DIABLO,\r\n\tMAINMENU_ATTRACT_MODE,\r\n};\r\n\r\nenum _selhero_selections : uint8_t {\r\n\tSELHERO_NEW_DUNGEON,\r\n\tSELHERO_CONTINUE,\r\n\tSELHERO_CONNECT,\r\n\tSELHERO_PREVIOUS,\r\n};\r\n\r\nstruct _uidefaultstats {\r\n\tuint16_t strength;\r\n\tuint16_t magic;\r\n\tuint16_t dexterity;\r\n\tuint16_t vitality;\r\n};\r\n\r\nstruct _uiheroinfo {\r\n\tuint32_t saveNumber;\r\n\tchar name[16];\r\n\tuint8_t level;\r\n\tHeroClass heroclass;\r\n\tuint8_t herorank;\r\n\tuint16_t strength;\r\n\tuint16_t magic;\r\n\tuint16_t dexterity;\r\n\tuint16_t vitality;\r\n\tbool hassaved;\r\n\tbool spawned;\r\n};\r\n\r\nextern OptionalOwnedClxSpriteList ArtLogo;\r\nextern OptionalOwnedClxSpriteList DifficultyIndicator;\r\nextern std::array<OptionalOwnedClxSpriteList, 3> ArtFocus;\r\nextern OptionalOwnedClxSpriteList ArtBackgroundWidescreen;\r\nextern OptionalOwnedClxSpriteList ArtBackground;\r\nextern OptionalOwnedClxSpriteList ArtCursor;\r\n\r\nextern bool (*gfnHeroInfo)(bool (*fninfofunc)(_uiheroinfo *));\r\n\r\ninline SDL_Surface *DiabloUiSurface()\r\n{\r\n\treturn PalSurface;\r\n}\r\n\r\nvoid UiDestroy();\r\nvoid UiTitleDialog();\r\nvoid UnloadUiGFX();\r\nvoid UiInitialize();\r\nbool UiValidPlayerName(std::string_view name); /* check */\r\nvoid UiSelHeroMultDialog(bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)), bool (*fncreate)(_uiheroinfo *), bool (*fnremove)(_uiheroinfo *), void (*fnstats)(HeroClass, _uidefaultstats *), _selhero_selections *dlgresult, uint32_t *saveNumber);\r\nvoid UiSelHeroSingDialog(bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)), bool (*fncreate)(_uiheroinfo *), bool (*fnremove)(_uiheroinfo *), void (*fnstats)(HeroClass, _uidefaultstats *), _selhero_selections *dlgresult, uint32_t *saveNumber, _difficulty *difficulty);\r\nbool UiCreditsDialog();\r\nbool UiSupportDialog();\r\nbool UiMainMenuDialog(const char *name, _mainmenu_selections *pdwResult, int attractTimeOut);\r\nbool UiProgressDialog(int (*fnfunc)());\r\nbool UiSelectGame(GameData *gameData, int *playerId);\r\nbool UiSelectProvider(GameData *gameData);\r\nvoid UiFadeIn();\r\nvoid UiHandleEvents(SDL_Event *event);\r\nbool UiItemMouseEvents(SDL_Event *event, const std::vector<UiItemBase *> &items);\r\nbool UiItemMouseEvents(SDL_Event *event, const std::vector<std::unique_ptr<UiItemBase>> &items);\r\nSint16 GetCenterOffset(Sint16 w, Sint16 bw = 0);\r\nvoid DrawMouse();\r\nvoid UiLoadDefaultPalette();\r\nbool UiLoadBlackBackground();\r\nvoid LoadBackgroundArt(const char *pszFile, int frames = 1);\r\nvoid UiAddBackground(std::vector<std::unique_ptr<UiItemBase>> *vecDialog);\r\nvoid UiAddLogo(std::vector<std::unique_ptr<UiItemBase>> *vecDialog, int y = GetUIRectangle().position.y);\r\nvoid UiFocusNavigationSelect();\r\nvoid UiFocusNavigationEsc();\r\nvoid UiFocusNavigationYesNo();\r\n\r\nvoid UiInitList(void (*fnFocus)(size_t value), void (*fnSelect)(size_t value), void (*fnEsc)(), const std::vector<std::unique_ptr<UiItemBase>> &items, bool wraps = false, void (*fnFullscreen)() = nullptr, bool (*fnYesNo)() = nullptr, size_t selectedItem = 0);\r\nvoid UiRenderListItems();\r\nvoid UiInitList_clear();\r\n\r\nvoid UiClearScreen();\r\nvoid UiPollAndRender(std::optional<tl::function_ref<bool(SDL_Event &)>> eventHandler = std::nullopt);\r\nvoid UiRenderItem(const UiItemBase &item);\r\nvoid UiRenderItems(const std::vector<UiItemBase *> &items);\r\nvoid UiRenderItems(const std::vector<std::unique_ptr<UiItemBase>> &items);\r\nClxSprite UiGetHeroDialogSprite(size_t heroClassIndex);\r\n\r\nvoid mainmenu_restart_repintro();\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/dialogs.cpp",
    "content": "#include \"DiabloUI/dialogs.h\"\r\n\r\n#include <cstdint>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_messagebox.h>\r\n#include <SDL3/SDL_mouse.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/button.h\"\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"controls/input.h\"\r\n#include \"controls/menu_controls.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/load_pcx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"init.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList ownedDialogSprite;\r\nstd::string wrappedText;\r\n\r\nbool dialogEnd;\r\n\r\nvoid DialogActionOK()\r\n{\r\n\tdialogEnd = true;\r\n}\r\n\r\nstd::vector<std::unique_ptr<UiItemBase>> vecNULL;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecOkDialog;\r\n\r\nOptionalClxSprite LoadDialogSprite(bool hasCaption, bool isError)\r\n{\r\n\tconstexpr uint8_t TransparentColor = 255;\r\n\tif (!hasCaption) {\r\n\t\townedDialogSprite = LoadPcx(isError ? \"ui_art\\\\srpopup\" : \"ui_art\\\\spopup\", TransparentColor);\r\n\t} else if (isError) {\r\n\t\townedDialogSprite = LoadOptionalClx(\"ui_art\\\\dvl_lrpopup.clx\");\r\n\t\tif (!ownedDialogSprite) {\r\n\t\t\townedDialogSprite = LoadPcx(\"ui_art\\\\lrpopup\", TransparentColor);\r\n\t\t}\r\n\t} else {\r\n\t\townedDialogSprite = LoadPcx(\"ui_art\\\\lpopup\", TransparentColor);\r\n\t}\r\n\tif (!ownedDialogSprite)\r\n\t\treturn std::nullopt;\r\n\treturn (*ownedDialogSprite)[0];\r\n}\r\n\r\nbool Init(std::string_view caption, std::string_view text, bool error, bool renderBehind)\r\n{\r\n\tif (!renderBehind) {\r\n\t\tif (!UiLoadBlackBackground()) {\r\n\t\t\tif (!SDLC_ShowCursor()) {\r\n\t\t\t\tLogError(\"{}\", SDL_GetError());\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (!IsHardwareCursor() && !ArtCursor) {\r\n\t\tArtCursor = LoadPcx(\"ui_art\\\\cursor\", /*transparentColor=*/0);\r\n\t}\r\n\tLoadDialogButtonGraphics();\r\n\r\n\tOptionalClxSprite dialogSprite = LoadDialogSprite(!caption.empty(), error);\r\n\tif (!dialogSprite)\r\n\t\treturn false;\r\n\r\n\tconst int dialogWidth = dialogSprite->width();\r\n\tconst int textWidth = dialogWidth - 40;\r\n\r\n\twrappedText = WordWrapString(text, textWidth, FontSizeDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tif (caption.empty()) {\r\n\t\tconst SDL_Rect rect1 = MakeSdlRect(uiPosition.x + 180, uiPosition.y + 168, dialogSprite->width(), dialogSprite->height());\r\n\t\tvecOkDialog.push_back(std::make_unique<UiImageClx>(*dialogSprite, rect1));\r\n\t\tconst SDL_Rect rect2 = MakeSdlRect(uiPosition.x + 200, uiPosition.y + 211, textWidth, 80);\r\n\t\tvecOkDialog.push_back(std::make_unique<UiText>(wrappedText, rect2, UiFlags::AlignCenter | UiFlags::ColorDialogWhite));\r\n\r\n\t\tconst SDL_Rect rect3 = MakeSdlRect(uiPosition.x + 265, uiPosition.y + 265, DialogButtonWidth, DialogButtonHeight);\r\n\t\tvecOkDialog.push_back(std::make_unique<UiButton>(_(\"OK\"), &DialogActionOK, rect3));\r\n\t} else {\r\n\t\tconst SDL_Rect rect1 = MakeSdlRect(uiPosition.x + 127, uiPosition.y + 100, dialogSprite->width(), dialogSprite->height());\r\n\t\tvecOkDialog.push_back(std::make_unique<UiImageClx>(*dialogSprite, rect1));\r\n\r\n\t\tconst SDL_Rect rect2 = MakeSdlRect(uiPosition.x + 147, uiPosition.y + 110, textWidth, 20);\r\n\t\tvecOkDialog.push_back(std::make_unique<UiText>(caption, rect2, UiFlags::AlignCenter | UiFlags::ColorYellow));\r\n\r\n\t\tconst SDL_Rect rect3 = MakeSdlRect(uiPosition.x + 147, uiPosition.y + 141, textWidth, 190);\r\n\t\tvecOkDialog.push_back(std::make_unique<UiText>(wrappedText, rect3, UiFlags::AlignCenter | UiFlags::ColorDialogWhite));\r\n\r\n\t\tconst SDL_Rect rect4 = MakeSdlRect(uiPosition.x + 264, uiPosition.y + 335, DialogButtonWidth, DialogButtonHeight);\r\n\t\tvecOkDialog.push_back(std::make_unique<UiButton>(_(\"OK\"), &DialogActionOK, rect4));\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid Deinit()\r\n{\r\n\townedDialogSprite = std::nullopt;\r\n\tvecOkDialog.clear();\r\n\tFreeDialogButtonGraphics();\r\n}\r\n\r\nvoid DialogLoop(const std::vector<std::unique_ptr<UiItemBase>> &items, const std::vector<std::unique_ptr<UiItemBase>> &renderBehind)\r\n{\r\n\tSDL_Event event;\r\n\tdialogEnd = false;\r\n\tdo {\r\n\t\twhile (PollEvent(&event)) {\r\n\t\t\tswitch (event.type) {\r\n\t\t\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\t\t\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\t\t\tUiItemMouseEvents(&event, items);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tfor (const MenuAction menuAction : GetMenuActions(event)) {\r\n\t\t\t\t\tif (IsNoneOf(menuAction, MenuAction_BACK, MenuAction_SELECT))\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\tdialogEnd = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tUiHandleEvents(&event);\r\n\t\t}\r\n\r\n\t\tUiClearScreen();\r\n\t\tUiRenderItems(renderBehind);\r\n\t\tUiRenderListItems();\r\n\t\tUiRenderItems(items);\r\n\t\tDrawMouse();\r\n\t\tUiFadeIn();\r\n\t} while (!dialogEnd);\r\n}\r\n\r\nvoid UiOkDialog(std::string_view caption, std::string_view text, bool error, const std::vector<std::unique_ptr<UiItemBase>> &renderBehind)\r\n{\r\n\tstatic bool inDialog = false;\r\n\r\n\tif (!caption.empty()) {\r\n\t\tLogError(\"{}\\n{}\", caption, text);\r\n\t} else {\r\n\t\tLogError(\"{}\", text);\r\n\t}\r\n\r\n\tif (!gbActive || inDialog) {\r\n\t\tif (!HeadlessMode) {\r\n\t\t\tif (!SDLC_ShowCursor()) {\r\n\t\t\t\tLogError(\"{}\", SDL_GetError());\r\n\t\t\t}\r\n\t\t\tconst std::string captionStr = std::string(caption);\r\n\t\t\tconst std::string textStr = std::string(text);\r\n\t\t\tif (!SDLC_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr)) {\r\n\t\t\t\tLogError(\"{}\", SDL_GetError());\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (IsHardwareCursor()) {\r\n\t\tif (!SDLC_ShowCursor()) {\r\n\t\t\tLogError(\"{}\", SDL_GetError());\r\n\t\t}\r\n\t}\r\n\r\n\tif (!Init(caption, text, error, !renderBehind.empty())) {\r\n\t\tLogError(\"{}\\n{}\", caption, text);\r\n\t\tconst std::string captionStr = std::string(caption);\r\n\t\tconst std::string textStr = std::string(text);\r\n\t\tif (!SDLC_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr)) {\r\n\t\t\tLogError(\"{}\", SDL_GetError());\r\n\t\t}\r\n\t}\r\n\r\n\tinDialog = true;\r\n\tSDL_SetSurfaceClipRect(DiabloUiSurface(), nullptr);\r\n\tDialogLoop(vecOkDialog, renderBehind);\r\n\tDeinit();\r\n\tinDialog = false;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid UiErrorOkDialog(std::string_view caption, std::string_view text, const std::vector<std::unique_ptr<UiItemBase>> &renderBehind)\r\n{\r\n\tUiOkDialog(caption, text, /*error=*/true, renderBehind);\r\n}\r\n\r\nvoid UiErrorOkDialog(std::string_view caption, std::string_view text, bool error)\r\n{\r\n\tUiOkDialog(caption, text, error, vecNULL);\r\n}\r\n\r\nvoid UiErrorOkDialog(std::string_view text, const std::vector<std::unique_ptr<UiItemBase>> &renderBehind)\r\n{\r\n\tUiErrorOkDialog({}, text, renderBehind);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/dialogs.h",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <string_view>\r\n\r\n#include \"DiabloUI/ui_item.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid UiErrorOkDialog(std::string_view text, const std::vector<std::unique_ptr<UiItemBase>> &renderBehind);\r\nvoid UiErrorOkDialog(std::string_view caption, std::string_view text, const std::vector<std::unique_ptr<UiItemBase>> &renderBehind);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/hero/selhero.cpp",
    "content": "#include \"DiabloUI/hero/selhero.h\"\r\n\r\n#include <algorithm>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstdlib>\r\n#include <cstring>\r\n#include <memory>\r\n#include <optional>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/dialogs.h\"\r\n#include \"DiabloUI/multi/selgame.h\"\r\n#include \"DiabloUI/scrollbar.h\"\r\n#include \"DiabloUI/selok.h\"\r\n#include \"DiabloUI/selyesno.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool selhero_endMenu;\r\nbool selhero_isMultiPlayer;\r\n\r\nbool (*gfnHeroInfo)(bool (*fninfofunc)(_uiheroinfo *));\r\nbool (*gfnHeroCreate)(_uiheroinfo *);\r\nvoid (*gfnHeroStats)(HeroClass, _uidefaultstats *);\r\n\r\nnamespace {\r\n\r\nstd::size_t selhero_SaveCount = 0;\r\n_uiheroinfo selhero_heros[MAX_CHARACTERS];\r\n_uiheroinfo selhero_heroInfo;\r\nchar textStats[6][4];\r\nconst char *title = \"\";\r\n_selhero_selections selhero_result;\r\nbool selhero_navigateYesNo;\r\nbool selhero_isSavegame;\r\n\r\nstd::vector<std::unique_ptr<UiItemBase>> vecSelHeroDialog;\r\nstd::vector<std::unique_ptr<UiListItem>> vecSelHeroDlgItems;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecSelDlgItems;\r\n\r\nUiImageClx *SELHERO_DIALOG_HERO_IMG;\r\n\r\nvoid SelheroListFocus(size_t value);\r\nvoid SelheroListSelect(size_t value);\r\nvoid SelheroListEsc();\r\nvoid SelheroLoadFocus(size_t value);\r\nvoid SelheroLoadSelect(size_t value);\r\nvoid SelheroNameSelect(size_t value);\r\nvoid SelheroNameEsc();\r\nvoid SelheroClassSelectorFocus(size_t value);\r\nvoid SelheroClassSelectorSelect(size_t value);\r\nvoid SelheroClassSelectorEsc();\r\nconst char *SelheroGenerateName(HeroClass heroClass);\r\n\r\nvoid SelheroUiFocusNavigationYesNo()\r\n{\r\n\tif (selhero_isSavegame)\r\n\t\tUiFocusNavigationYesNo();\r\n}\r\n\r\nvoid SelheroFree()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\r\n\tvecSelHeroDialog.clear();\r\n\r\n\tvecSelDlgItems.clear();\r\n\tvecSelHeroDlgItems.clear();\r\n\tUnloadScrollBar();\r\n}\r\n\r\nvoid SelheroSetStats()\r\n{\r\n\tSELHERO_DIALOG_HERO_IMG->setSprite(UiGetHeroDialogSprite(static_cast<size_t>(selhero_heroInfo.heroclass)));\r\n\tCopyUtf8(textStats[0], StrCat(selhero_heroInfo.level), sizeof(textStats[0]));\r\n\tCopyUtf8(textStats[1], StrCat(selhero_heroInfo.strength), sizeof(textStats[1]));\r\n\tCopyUtf8(textStats[2], StrCat(selhero_heroInfo.magic), sizeof(textStats[2]));\r\n\tCopyUtf8(textStats[3], StrCat(selhero_heroInfo.dexterity), sizeof(textStats[3]));\r\n\tCopyUtf8(textStats[4], StrCat(selhero_heroInfo.vitality), sizeof(textStats[4]));\r\n\tCopyUtf8(textStats[5], StrCat(selhero_heroInfo.saveNumber), sizeof(textStats[5]));\r\n}\r\n\r\nvoid RenderDifficultyIndicators()\r\n{\r\n\tif (!selhero_isSavegame)\r\n\t\treturn;\r\n\tconst uint16_t width = (*DifficultyIndicator)[0].width();\r\n\tconst uint16_t height = (*DifficultyIndicator)[0].height();\r\n\tSDL_Rect rect = MakeSdlRect(\r\n\t    SELHERO_DIALOG_HERO_IMG->m_rect.x + 1,\r\n\t    SELHERO_DIALOG_HERO_IMG->m_rect.y + SELHERO_DIALOG_HERO_IMG->m_rect.h - height - 1,\r\n\t    width,\r\n\t    height);\r\n\tfor (int i = 0; i <= DIFF_LAST; i++) {\r\n\t\tif (i >= selhero_heroInfo.herorank)\r\n\t\t\tbreak;\r\n\t\tUiRenderItem(UiImageClx((*DifficultyIndicator)[0], rect, UiFlags::None));\r\n\t\trect.x += width;\r\n\t}\r\n}\r\n\r\nUiArtTextButton *SELLIST_DIALOG_DELETE_BUTTON;\r\n\r\nbool SelHeroGetHeroInfo(_uiheroinfo *pInfo)\r\n{\r\n\tselhero_heros[selhero_SaveCount] = *pInfo;\r\n\r\n\tselhero_SaveCount++;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid SelheroListFocus(size_t value)\r\n{\r\n\tconst UiFlags baseFlags = UiFlags::AlignCenter | UiFlags::FontSize30;\r\n\tif (selhero_SaveCount != 0 && value < selhero_SaveCount) {\r\n\t\tmemcpy(&selhero_heroInfo, &selhero_heros[value], sizeof(selhero_heroInfo));\r\n\t\tSelheroSetStats();\r\n\t\tSELLIST_DIALOG_DELETE_BUTTON->SetFlags(baseFlags | UiFlags::ColorUiGold);\r\n\t\tselhero_isSavegame = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tSELHERO_DIALOG_HERO_IMG->setSprite(UiGetHeroDialogSprite(GetNumPlayerClasses()));\r\n\tfor (char *textStat : textStats)\r\n\t\tstrcpy(textStat, \"--\");\r\n\tSELLIST_DIALOG_DELETE_BUTTON->SetFlags(baseFlags | UiFlags::ColorUiSilver | UiFlags::ElementDisabled);\r\n\tselhero_isSavegame = false;\r\n}\r\n\r\nbool SelheroListDeleteYesNo()\r\n{\r\n\tselhero_navigateYesNo = selhero_isSavegame;\r\n\r\n\treturn selhero_navigateYesNo;\r\n}\r\n\r\nvoid SelheroListSelect(size_t value)\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tif (static_cast<std::size_t>(value) == selhero_SaveCount) {\r\n\t\tvecSelDlgItems.clear();\r\n\r\n\t\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 242), (Sint16)(uiPosition.y + 211), 365, 33 };\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiArtText>(_(\"Choose Class\").data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\t\tvecSelHeroDlgItems.clear();\r\n\t\tint itemH = 33;\r\n\t\tfor (size_t i = 0; i < GetNumPlayerClasses(); ++i) {\r\n\t\t\tconst HeroClass heroClass = static_cast<HeroClass>(i);\r\n\r\n\t\t\tif (heroClass == HeroClass::Monk && !gbIsHellfire) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (heroClass == HeroClass::Bard && !HaveBardAssets() && !(*GetOptions().Gameplay.testBard)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (heroClass == HeroClass::Barbarian && !HaveBarbarianAssets() && !(*GetOptions().Gameplay.testBarbarian)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst PlayerData &playerData = GetPlayerDataForClass(heroClass);\r\n\t\t\tvecSelHeroDlgItems.push_back(std::make_unique<UiListItem>(_(playerData.className), static_cast<int>(heroClass)));\r\n\t\t}\r\n\t\tif (vecSelHeroDlgItems.size() > 4)\r\n\t\t\titemH = 26;\r\n\t\tconst int itemY = static_cast<int>(246 + (176 - std::min<size_t>(vecSelHeroDlgItems.size(), 6) * itemH) / 2);\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiList>(vecSelHeroDlgItems, std::min<size_t>(vecSelHeroDlgItems.size(), 6), uiPosition.x + 264, (uiPosition.y + itemY), 320, itemH, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rectScrollBar = { (Sint16)(uiPosition.x + 585), (Sint16)(uiPosition.y + 244), 25, 178 };\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiScrollbar>((*ArtScrollBarBackground)[0], (*ArtScrollBarThumb)[0], *ArtScrollBarArrow, rectScrollBar));\r\n\r\n\t\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 279), (Sint16)(uiPosition.y + 429), 140, 35 };\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect2, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 429), (Sint16)(uiPosition.y + 429), 144, 35 };\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"Cancel\"), &UiFocusNavigationEsc, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tUiInitList(SelheroClassSelectorFocus, SelheroClassSelectorSelect, SelheroClassSelectorEsc, vecSelDlgItems, true);\r\n\t\tmemset(&selhero_heroInfo.name, 0, sizeof(selhero_heroInfo.name));\r\n\t\tselhero_heroInfo.saveNumber = pfile_ui_get_first_unused_save_num();\r\n\t\tSelheroSetStats();\r\n\t\ttitle = selhero_isMultiPlayer ? _(\"New Multi Player Hero\").data() : _(\"New Single Player Hero\").data();\r\n\t\tselhero_isSavegame = false;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (selhero_heroInfo.hassaved) {\r\n\t\tvecSelDlgItems.clear();\r\n\r\n\t\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 242), (Sint16)(uiPosition.y + 211), 365, 33 };\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiArtText>(_(\"Save File Exists\").data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\t\tvecSelHeroDlgItems.clear();\r\n\t\tvecSelHeroDlgItems.push_back(std::make_unique<UiListItem>(_(\"Load Game\"), 0));\r\n\t\tvecSelHeroDlgItems.push_back(std::make_unique<UiListItem>(_(\"New Game\"), 1));\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiList>(vecSelHeroDlgItems, vecSelHeroDlgItems.size(), uiPosition.x + 265, (uiPosition.y + 285), 320, 33, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 279), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect2, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 429), (Sint16)(uiPosition.y + 427), 144, 35 };\r\n\t\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"Cancel\"), &UiFocusNavigationEsc, rect3, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tUiInitList(SelheroLoadFocus, SelheroLoadSelect, selhero_List_Init, vecSelDlgItems, true);\r\n\t\ttitle = _(\"Single Player Characters\").data();\r\n\t\treturn;\r\n\t}\r\n\r\n\tSelheroLoadSelect(1);\r\n}\r\n\r\nvoid SelheroListEsc()\r\n{\r\n\tUiInitList_clear();\r\n\r\n\tselhero_endMenu = true;\r\n\tselhero_result = SELHERO_PREVIOUS;\r\n}\r\n\r\nvoid SelheroClassSelectorFocus(size_t value)\r\n{\r\n\tconst auto heroClass = static_cast<HeroClass>(vecSelHeroDlgItems[value]->m_value);\r\n\r\n\t_uidefaultstats defaults;\r\n\tgfnHeroStats(heroClass, &defaults);\r\n\r\n\tselhero_heroInfo.level = 1;\r\n\tselhero_heroInfo.heroclass = heroClass;\r\n\tselhero_heroInfo.strength = defaults.strength;\r\n\tselhero_heroInfo.magic = defaults.magic;\r\n\tselhero_heroInfo.dexterity = defaults.dexterity;\r\n\tselhero_heroInfo.vitality = defaults.vitality;\r\n\r\n\tSelheroSetStats();\r\n}\r\n\r\nbool ShouldPrefillHeroName()\r\n{\r\n#if defined(PREFILL_PLAYER_NAME)\r\n\treturn true;\r\n#else\r\n\treturn ControlMode != ControlTypes::KeyboardAndMouse;\r\n#endif\r\n}\r\n\r\nvoid RemoveSelHeroBackground()\r\n{\r\n\tvecSelHeroDialog.erase(vecSelHeroDialog.begin());\r\n\tArtBackground = std::nullopt;\r\n}\r\n\r\nvoid AddSelHeroBackground()\r\n{\r\n\tLoadBackgroundArt(\"ui_art\\\\selhero\");\r\n\tvecSelHeroDialog.insert(vecSelHeroDialog.begin(),\r\n\t    std::make_unique<UiImageClx>((*ArtBackground)[0], MakeSdlRect(0, GetUIRectangle().position.y, 0, 0), UiFlags::AlignCenter));\r\n}\r\n\r\nvoid SelheroClassSelectorSelect(size_t value)\r\n{\r\n\tauto hClass = static_cast<HeroClass>(vecSelHeroDlgItems[value]->m_value);\r\n\tif (gbIsSpawn && (hClass == HeroClass::Rogue || hClass == HeroClass::Sorcerer || (hClass == HeroClass::Bard && !HaveBardAssets()))) {\r\n\t\tRemoveSelHeroBackground();\r\n\t\tUiSelOkDialog(nullptr, _(\"The Rogue and Sorcerer are only available in the full retail version of Diablo. Visit https://www.gog.com/game/diablo to purchase.\").data(), false);\r\n\t\tAddSelHeroBackground();\r\n\t\tSelheroListSelect(selhero_SaveCount);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\ttitle = selhero_isMultiPlayer ? _(\"New Multi Player Hero\").data() : _(\"New Single Player Hero\").data();\r\n\tmemset(selhero_heroInfo.name, '\\0', sizeof(selhero_heroInfo.name));\r\n\tif (ShouldPrefillHeroName())\r\n\t\tstrcpy(selhero_heroInfo.name, SelheroGenerateName(selhero_heroInfo.heroclass));\r\n\tvecSelDlgItems.clear();\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 242), (Sint16)(uiPosition.y + 211), 365, 33 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiArtText>(_(\"Enter Name\").data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 265), (Sint16)(uiPosition.y + 317), 320, 33 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiEdit>(_(\"Enter Name\"), selhero_heroInfo.name, 15, false, rect2, UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 279), (Sint16)(uiPosition.y + 429), 140, 35 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 429), (Sint16)(uiPosition.y + 429), 144, 35 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"Cancel\"), &UiFocusNavigationEsc, rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tUiInitList(nullptr, SelheroNameSelect, SelheroNameEsc, vecSelDlgItems);\r\n}\r\n\r\nvoid SelheroClassSelectorEsc()\r\n{\r\n\tvecSelDlgItems.clear();\r\n\tvecSelHeroDlgItems.clear();\r\n\r\n\tif (selhero_SaveCount != 0) {\r\n\t\tselhero_List_Init();\r\n\t\treturn;\r\n\t}\r\n\r\n\tSelheroListEsc();\r\n}\r\n\r\nvoid SelheroNameSelect(size_t /*value*/)\r\n{\r\n\t// only check names in multiplayer, we don't care about them in single\r\n\tif (selhero_isMultiPlayer && !UiValidPlayerName(selhero_heroInfo.name)) {\r\n\t\tRemoveSelHeroBackground();\r\n\t\tUiSelOkDialog(title, _(\"Invalid name. A name cannot contain spaces, reserved characters, or reserved words.\\n\").data(), false);\r\n\t\tAddSelHeroBackground();\r\n\t} else {\r\n\t\tif (gfnHeroCreate(&selhero_heroInfo)) {\r\n\t\t\tSelheroLoadSelect(1);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tUiErrorOkDialog(_(/* TRANSLATORS: Error Message */ \"Unable to create character.\"), vecSelHeroDialog);\r\n\t}\r\n\r\n\tmemset(selhero_heroInfo.name, '\\0', sizeof(selhero_heroInfo.name));\r\n\tSelheroClassSelectorSelect(0);\r\n}\r\n\r\nvoid SelheroNameEsc()\r\n{\r\n\tSelheroListSelect(selhero_SaveCount);\r\n}\r\n\r\nvoid SelheroLoadFocus(size_t value)\r\n{\r\n}\r\n\r\nvoid SelheroLoadSelect(size_t value)\r\n{\r\n\tUiInitList_clear();\r\n\tselhero_endMenu = true;\r\n\tif (vecSelHeroDlgItems[value]->m_value == 0) {\r\n\t\tselhero_result = SELHERO_CONTINUE;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!selhero_isMultiPlayer) {\r\n\t\t// This is part of a dangerous hack to enable difficulty selection in single-player.\r\n\t\t// FIXME: Dialogs should not refer to each other's variables.\r\n\r\n\t\t// We disable `selhero_endMenu` and replace the background and art\r\n\t\t// and the item list with the difficulty selection ones.\r\n\t\t//\r\n\t\t// This means selhero's render loop will render selgame's items,\r\n\t\t// which happens to work because the render loops are similar.\r\n\t\tselhero_endMenu = false;\r\n\r\n\t\t// Set this to false so that we do not attempt to render difficulty indicators.\r\n\t\tselhero_isSavegame = false;\r\n\r\n\t\tSelheroFree();\r\n\t\tLoadBackgroundArt(\"ui_art\\\\selgame\");\r\n\t\tselgame_GameSelection_Select(0);\r\n\t}\r\n\r\n\tselhero_result = SELHERO_NEW_DUNGEON;\r\n}\r\n\r\nconst char *SelheroGenerateName(HeroClass heroClass)\r\n{\r\n\tstatic const char *const Names[6][10] = {\r\n\t\t{\r\n\t\t    // Warrior\r\n\t\t    \"Aidan\",\r\n\t\t    \"Qarak\",\r\n\t\t    \"Born\",\r\n\t\t    \"Cathan\",\r\n\t\t    \"Halbu\",\r\n\t\t    \"Lenalas\",\r\n\t\t    \"Maximus\",\r\n\t\t    \"Vane\",\r\n\t\t    \"Myrdgar\",\r\n\t\t    \"Rothat\",\r\n\t\t},\r\n\t\t{\r\n\t\t    // Rogue\r\n\t\t    \"Moreina\",\r\n\t\t    \"Akara\",\r\n\t\t    \"Kashya\",\r\n\t\t    \"Flavie\",\r\n\t\t    \"Divo\",\r\n\t\t    \"Oriana\",\r\n\t\t    \"Iantha\",\r\n\t\t    \"Shikha\",\r\n\t\t    \"Basanti\",\r\n\t\t    \"Elexa\",\r\n\t\t},\r\n\t\t{\r\n\t\t    // Sorcerer\r\n\t\t    \"Jazreth\",\r\n\t\t    \"Drognan\",\r\n\t\t    \"Armin\",\r\n\t\t    \"Fauztin\",\r\n\t\t    \"Jere\",\r\n\t\t    \"Kazzulk\",\r\n\t\t    \"Ranslor\",\r\n\t\t    \"Sarnakyle\",\r\n\t\t    \"Valthek\",\r\n\t\t    \"Horazon\",\r\n\t\t},\r\n\t\t{\r\n\t\t    // Monk\r\n\t\t    \"Akyev\",\r\n\t\t    \"Dvorak\",\r\n\t\t    \"Kekegi\",\r\n\t\t    \"Kharazim\",\r\n\t\t    \"Mikulov\",\r\n\t\t    \"Shenlong\",\r\n\t\t    \"Vedenin\",\r\n\t\t    \"Vhalit\",\r\n\t\t    \"Vylnas\",\r\n\t\t    \"Zhota\",\r\n\t\t},\r\n\t\t{\r\n\t\t    // Bard (uses Rogue names)\r\n\t\t    \"Moreina\",\r\n\t\t    \"Akara\",\r\n\t\t    \"Kashya\",\r\n\t\t    \"Flavie\",\r\n\t\t    \"Divo\",\r\n\t\t    \"Oriana\",\r\n\t\t    \"Iantha\",\r\n\t\t    \"Shikha\",\r\n\t\t    \"Basanti\",\r\n\t\t    \"Elexa\",\r\n\t\t},\r\n\t\t{\r\n\t\t    // Barbarian\r\n\t\t    \"Alaric\",\r\n\t\t    \"Barloc\",\r\n\t\t    \"Egtheow\",\r\n\t\t    \"Guthlaf\",\r\n\t\t    \"Heorogar\",\r\n\t\t    \"Hrothgar\",\r\n\t\t    \"Oslaf\",\r\n\t\t    \"Qual-Kehk\",\r\n\t\t    \"Ragnar\",\r\n\t\t    \"Ulf\",\r\n\t\t},\r\n\t};\r\n\r\n\tconst int iRand = rand() % 10;\r\n\r\n\treturn Names[static_cast<std::size_t>(heroClass) % 6][iRand];\r\n}\r\n\r\n} // namespace\r\n\r\nvoid selhero_Init()\r\n{\r\n\tAddSelHeroBackground();\r\n\tUiAddLogo(&vecSelHeroDialog);\r\n\tLoadScrollBar();\r\n\r\n\tselhero_SaveCount = 0;\r\n\tgfnHeroInfo(SelHeroGetHeroInfo);\r\n\tstd::reverse(selhero_heros, selhero_heros + selhero_SaveCount);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tvecSelDlgItems.clear();\r\n\tSDL_Rect rect = MakeSdlRect(uiPosition.x + 24, uiPosition.y + 161, 590, 35);\r\n\tvecSelHeroDialog.push_back(std::make_unique<UiArtText>(&title, rect, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\trect = MakeSdlRect(uiPosition.x + 30, uiPosition.y + 211, 180, 76);\r\n\tauto heroImg = std::make_unique<UiImageClx>(UiGetHeroDialogSprite(0), rect, UiFlags::None);\r\n\tSELHERO_DIALOG_HERO_IMG = heroImg.get();\r\n\tvecSelHeroDialog.push_back(std::move(heroImg));\r\n\r\n\tconst UiFlags labelFlags = UiFlags::FontSize12 | UiFlags::ColorUiSilverDark | UiFlags::AlignRight;\r\n\tconst UiFlags valueFlags = UiFlags::FontSize12 | UiFlags::ColorUiSilverDark | UiFlags::AlignCenter;\r\n\tconst int labelX = uiPosition.x + 39;\r\n\tconst int valueX = uiPosition.x + 159;\r\n\tconst int labelWidth = 110;\r\n\tconst int valueWidth = 40;\r\n\tconst int statHeight = 21;\r\n\r\n\tvecSelHeroDialog.push_back(std::make_unique<UiArtText>(_(\"Level:\").data(), MakeSdlRect(labelX, uiPosition.y + 323, labelWidth, statHeight), labelFlags));\r\n\tvecSelHeroDialog.push_back(std::make_unique<UiArtText>(textStats[0], MakeSdlRect(valueX, uiPosition.y + 323, valueWidth, statHeight), valueFlags));\r\n\r\n\tconst char *statLabels[] {\r\n\t\t_(\"Strength:\").data(), _(\"Magic:\").data(), _(\"Dexterity:\").data(), _(\"Vitality:\").data(),\r\n#ifdef _DEBUG\r\n\t\t_(\"Savegame:\").data()\r\n#endif\r\n\t};\r\n\tint statY = uiPosition.y + 358;\r\n\tfor (size_t i = 0; i < sizeof(statLabels) / sizeof(statLabels[0]); ++i) {\r\n\t\tvecSelHeroDialog.push_back(std::make_unique<UiArtText>(statLabels[i], MakeSdlRect(labelX, statY, labelWidth, statHeight), labelFlags));\r\n\t\tvecSelHeroDialog.push_back(std::make_unique<UiArtText>(textStats[i + 1], MakeSdlRect(valueX, statY, valueWidth, statHeight), valueFlags));\r\n\t\tstatY += statHeight;\r\n\t}\r\n}\r\n\r\nvoid selhero_List_Init()\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tsize_t selectedItem = 0;\r\n\tvecSelDlgItems.clear();\r\n\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 242), (Sint16)(uiPosition.y + 211), 365, 33 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiArtText>(_(\"Select Hero\").data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tvecSelHeroDlgItems.clear();\r\n\tfor (std::size_t i = 0; i < selhero_SaveCount; i++) {\r\n\t\tvecSelHeroDlgItems.push_back(std::make_unique<UiListItem>(std::string_view(selhero_heros[i].name), static_cast<int>(i)));\r\n\t\tif (selhero_heros[i].saveNumber == selhero_heroInfo.saveNumber)\r\n\t\t\tselectedItem = i;\r\n\t}\r\n\tvecSelHeroDlgItems.push_back(std::make_unique<UiListItem>(_(\"New Hero\"), static_cast<int>(selhero_SaveCount)));\r\n\r\n\tvecSelDlgItems.push_back(std::make_unique<UiList>(vecSelHeroDlgItems, 6, uiPosition.x + 265, (uiPosition.y + 256), 320, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 585), (Sint16)(uiPosition.y + 244), 25, 178 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiScrollbar>((*ArtScrollBarBackground)[0], (*ArtScrollBarThumb)[0], *ArtScrollBarArrow, rect2));\r\n\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 239), (Sint16)(uiPosition.y + 429), 120, 35 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 364), (Sint16)(uiPosition.y + 429), 120, 35 };\r\n\tauto setlistDialogDeleteButton = std::make_unique<UiArtTextButton>(_(\"Delete\"), &SelheroUiFocusNavigationYesNo, rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver | UiFlags::ElementDisabled);\r\n\tSELLIST_DIALOG_DELETE_BUTTON = setlistDialogDeleteButton.get();\r\n\tvecSelDlgItems.push_back(std::move(setlistDialogDeleteButton));\r\n\r\n\tconst SDL_Rect rect5 = { (Sint16)(uiPosition.x + 489), (Sint16)(uiPosition.y + 429), 144, 35 };\r\n\tvecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_(\"Cancel\"), &UiFocusNavigationEsc, rect5, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tUiInitList(SelheroListFocus, SelheroListSelect, SelheroListEsc, vecSelDlgItems, false, nullptr, SelheroListDeleteYesNo, selectedItem);\r\n\tif (selhero_isMultiPlayer) {\r\n\t\ttitle = _(\"Multi Player Characters\").data();\r\n\t} else {\r\n\t\ttitle = _(\"Single Player Characters\").data();\r\n\t}\r\n}\r\n\r\nstatic void UiSelHeroDialog(\r\n    bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)),\r\n    bool (*fncreate)(_uiheroinfo *),\r\n    void (*fnstats)(HeroClass, _uidefaultstats *),\r\n    bool (*fnremove)(_uiheroinfo *),\r\n    _selhero_selections *dlgresult,\r\n    uint32_t *saveNumber)\r\n{\r\n\tdo {\r\n\t\tgfnHeroInfo = fninfo;\r\n\t\tgfnHeroCreate = fncreate;\r\n\t\tgfnHeroStats = fnstats;\r\n\t\tselhero_result = *dlgresult;\r\n\r\n\t\tselhero_navigateYesNo = false;\r\n\r\n\t\tselhero_Init();\r\n\r\n\t\tif (selhero_SaveCount != 0) {\r\n\t\t\tselhero_heroInfo = {};\r\n\t\t\t// Search last used save and remember it as selected item\r\n\t\t\tfor (size_t i = 0; i < selhero_SaveCount; i++) {\r\n\t\t\t\tif (selhero_heros[i].saveNumber == *saveNumber) {\r\n\t\t\t\t\tmemcpy(&selhero_heroInfo, &selhero_heros[i], sizeof(selhero_heroInfo));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tselhero_List_Init();\r\n\t\t} else {\r\n\t\t\tSelheroListSelect(selhero_SaveCount);\r\n\t\t}\r\n\r\n\t\tselhero_endMenu = false;\r\n\t\twhile (!selhero_endMenu && !selhero_navigateYesNo) {\r\n\t\t\tUiClearScreen();\r\n\t\t\tUiRenderItems(vecSelHeroDialog);\r\n\t\t\tRenderDifficultyIndicators();\r\n\t\t\tUiPollAndRender();\r\n\t\t}\r\n\t\tSelheroFree();\r\n\r\n\t\tif (selhero_navigateYesNo) {\r\n\t\t\tchar dialogTitle[128];\r\n\t\t\tchar dialogText[256];\r\n\t\t\tif (selhero_isMultiPlayer) {\r\n\t\t\t\tCopyUtf8(dialogTitle, _(\"Delete Multi Player Hero\"), sizeof(dialogTitle));\r\n\t\t\t} else {\r\n\t\t\t\tCopyUtf8(dialogTitle, _(\"Delete Single Player Hero\"), sizeof(dialogTitle));\r\n\t\t\t}\r\n\t\t\tstrcpy(dialogText, fmt::format(fmt::runtime(_(\"Are you sure you want to delete the character \\\"{:s}\\\"?\")), selhero_heroInfo.name).c_str());\r\n\r\n\t\t\tif (UiSelHeroYesNoDialog(dialogTitle, dialogText))\r\n\t\t\t\tfnremove(&selhero_heroInfo);\r\n\t\t}\r\n\t} while (selhero_navigateYesNo);\r\n\r\n\t*dlgresult = selhero_result;\r\n\t*saveNumber = selhero_heroInfo.saveNumber;\r\n}\r\n\r\nvoid UiSelHeroSingDialog(\r\n    bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)),\r\n    bool (*fncreate)(_uiheroinfo *),\r\n    bool (*fnremove)(_uiheroinfo *),\r\n    void (*fnstats)(HeroClass, _uidefaultstats *),\r\n    _selhero_selections *dlgresult,\r\n    uint32_t *saveNumber,\r\n    _difficulty *difficulty)\r\n{\r\n\tselhero_isMultiPlayer = false;\r\n\tUiSelHeroDialog(fninfo, fncreate, fnstats, fnremove, dlgresult, saveNumber);\r\n\t*difficulty = nDifficulty;\r\n}\r\n\r\nvoid UiSelHeroMultDialog(\r\n    bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)),\r\n    bool (*fncreate)(_uiheroinfo *),\r\n    bool (*fnremove)(_uiheroinfo *),\r\n    void (*fnstats)(HeroClass, _uidefaultstats *),\r\n    _selhero_selections *dlgresult,\r\n    uint32_t *saveNumber)\r\n{\r\n\tselhero_isMultiPlayer = true;\r\n\tUiSelHeroDialog(fninfo, fncreate, fnstats, fnremove, dlgresult, saveNumber);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/hero/selhero.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nextern bool selhero_isMultiPlayer;\r\nextern bool selhero_endMenu;\r\n\r\nvoid selhero_Init();\r\nvoid selhero_List_Init();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/mainmenu.cpp",
    "content": "#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <optional>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nint mainmenu_attract_time_out; // seconds\r\nuint32_t dwAttractTicks;\r\n\r\nstd::vector<std::unique_ptr<UiItemBase>> vecMainMenuDialog;\r\nstd::vector<std::unique_ptr<UiListItem>> vecMenuItems;\r\n\r\n_mainmenu_selections MainMenuResult;\r\n\r\nvoid UiMainMenuSelect(size_t value)\r\n{\r\n\tMainMenuResult = (_mainmenu_selections)vecMenuItems[value]->m_value;\r\n}\r\n\r\n#ifndef NOEXIT\r\nvoid MainmenuEsc()\r\n{\r\n\tconst std::size_t last = vecMenuItems.size() - 1;\r\n\tif (SelectedItem == last) {\r\n\t\tUiMainMenuSelect(last);\r\n\t} else {\r\n\t\tSelectedItem = last;\r\n\t}\r\n}\r\n#endif\r\n\r\nvoid MainmenuLoad(const char *name)\r\n{\r\n\tvecMenuItems.push_back(std::make_unique<UiListItem>(_(\"Single Player\"), MAINMENU_SINGLE_PLAYER));\r\n\tvecMenuItems.push_back(std::make_unique<UiListItem>(_(\"Multi Player\"), MAINMENU_MULTIPLAYER));\r\n\tvecMenuItems.push_back(std::make_unique<UiListItem>(_(\"Settings\"), MAINMENU_SETTINGS));\r\n\tvecMenuItems.push_back(std::make_unique<UiListItem>(_(\"Support\"), MAINMENU_SHOW_SUPPORT));\r\n\tvecMenuItems.push_back(std::make_unique<UiListItem>(_(\"Show Credits\"), MAINMENU_SHOW_CREDITS));\r\n#ifndef NOEXIT\r\n\tvecMenuItems.push_back(std::make_unique<UiListItem>(gbIsHellfire ? _(\"Exit Hellfire\") : _(\"Exit Diablo\"), MAINMENU_EXIT_DIABLO));\r\n#endif\r\n\r\n\tif (!gbIsSpawn || gbIsHellfire) {\r\n\t\tArtBackgroundWidescreen = LoadOptionalClx(\"ui_art\\\\mainmenuw.clx\");\r\n\t\tLoadBackgroundArt(\"ui_art\\\\mainmenu\");\r\n\t} else {\r\n\t\tLoadBackgroundArt(\"ui_art\\\\swmmenu\");\r\n\t}\r\n\r\n\tUiAddBackground(&vecMainMenuDialog);\r\n\tUiAddLogo(&vecMainMenuDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tif (gbIsSpawn && gbIsHellfire) {\r\n\t\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x), (Sint16)(uiPosition.y + 145), 640, 30 };\r\n\t\tvecMainMenuDialog.push_back(std::make_unique<UiArtText>(_(\"Shareware\").data(), rect1, UiFlags::FontSize30 | UiFlags::ColorUiSilver | UiFlags::AlignCenter, 8));\r\n\t}\r\n\r\n\tvecMainMenuDialog.push_back(std::make_unique<UiList>(vecMenuItems, vecMenuItems.size(), uiPosition.x + 64, (uiPosition.y + 192), 510, 43, UiFlags::FontSize42 | UiFlags::ColorUiGold | UiFlags::AlignCenter, 5));\r\n\r\n\tconst SDL_Rect rect2 = { 17, (Sint16)(gnScreenHeight - 36), 605, 21 };\r\n\tvecMainMenuDialog.push_back(std::make_unique<UiArtText>(name, rect2, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark));\r\n\r\n#ifndef NOEXIT\r\n\tUiInitList(nullptr, UiMainMenuSelect, MainmenuEsc, vecMainMenuDialog, true);\r\n#else\r\n\tUiInitList(nullptr, UiMainMenuSelect, nullptr, vecMainMenuDialog, true);\r\n#endif\r\n}\r\n\r\nvoid MainmenuFree()\r\n{\r\n\tArtBackgroundWidescreen = std::nullopt;\r\n\tArtBackground = std::nullopt;\r\n\r\n\tvecMainMenuDialog.clear();\r\n\r\n\tvecMenuItems.clear();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid mainmenu_restart_repintro()\r\n{\r\n\tdwAttractTicks = SDL_GetTicks() + mainmenu_attract_time_out * 1000;\r\n}\r\n\r\nbool UiMainMenuDialog(const char *name, _mainmenu_selections *pdwResult, int attractTimeOut)\r\n{\r\n\tMainMenuResult = MAINMENU_NONE;\r\n\twhile (MainMenuResult == MAINMENU_NONE) {\r\n\t\tmainmenu_attract_time_out = attractTimeOut;\r\n\t\tMainmenuLoad(name);\r\n\r\n\t\tmainmenu_restart_repintro(); // for automatic starts\r\n\r\n\t\twhile (MainMenuResult == MAINMENU_NONE) {\r\n\t\t\tUiClearScreen();\r\n\t\t\tUiPollAndRender();\r\n\t\t\tif (SDL_GetTicks() >= dwAttractTicks && (HaveIntro() || gbIsHellfire)) {\r\n\t\t\t\tMainMenuResult = MAINMENU_ATTRACT_MODE;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tMainmenuFree();\r\n\t}\r\n\r\n\t*pdwResult = MainMenuResult;\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/multi/selconn.cpp",
    "content": "#include <cstddef>\r\n#include <memory>\r\n#include <optional>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"multi.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nint provider;\r\nconst char *ConnectionNames[] {\r\n\t\"ZeroTier\",\r\n\tN_(\"Client-Server (TCP)\"),\r\n\tN_(\"Offline\"),\r\n};\r\n\r\nnamespace {\r\n\r\nchar selconn_MaxPlayers[64];\r\nchar selconn_Description[256];\r\nchar selconn_Gateway[129];\r\nbool selconn_ReturnValue = false;\r\nbool selconn_EndMenu = false;\r\nGameData *selconn_GameData;\r\n\r\nstd::vector<std::unique_ptr<UiListItem>> vecConnItems;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecSelConnDlg;\r\n\r\n#define DESCRIPTION_WIDTH 205\r\n\r\nvoid SelconnEsc();\r\nvoid SelconnFocus(size_t value);\r\nvoid SelconnSelect(size_t value);\r\n\r\nvoid SelconnLoad()\r\n{\r\n\tLoadBackgroundArt(\"ui_art\\\\selconn\");\r\n\r\n#ifndef NONET\r\n#ifndef DISABLE_ZERO_TIER\r\n\tvecConnItems.push_back(std::make_unique<UiListItem>(std::string_view(ConnectionNames[SELCONN_ZT]), SELCONN_ZT));\r\n#endif\r\n#ifndef DISABLE_TCP\r\n\tvecConnItems.push_back(std::make_unique<UiListItem>(_(ConnectionNames[SELCONN_TCP]), SELCONN_TCP));\r\n#endif\r\n#endif\r\n\tvecConnItems.push_back(std::make_unique<UiListItem>(_(ConnectionNames[SELCONN_LOOPBACK]), SELCONN_LOOPBACK));\r\n\r\n\tUiAddBackground(&vecSelConnDlg);\r\n\tUiAddLogo(&vecSelConnDlg);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 24), (Sint16)(Sint16)(uiPosition.y + 161), 590, 35 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtText>(_(\"Multi Player Game\").data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 218), DESCRIPTION_WIDTH, 21 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtText>(selconn_MaxPlayers, rect2, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark));\r\n\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 256), DESCRIPTION_WIDTH, 21 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtText>(_(\"Requirements:\").data(), rect3, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark));\r\n\r\n\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 275), DESCRIPTION_WIDTH, 66 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtText>(selconn_Description, rect4, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark, 1, 16));\r\n\r\n\tconst SDL_Rect rect5 = { (Sint16)(uiPosition.x + 30), (Sint16)(uiPosition.y + 356), 220, 31 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtText>(_(\"no gateway needed\").data(), rect5, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiSilver, 0));\r\n\r\n\tconst SDL_Rect rect6 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 393), DESCRIPTION_WIDTH, 21 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtText>(selconn_Gateway, rect6, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorUiSilverDark));\r\n\r\n\tconst SDL_Rect rect7 = { (Sint16)(uiPosition.x + 300), (Sint16)(uiPosition.y + 211), 295, 33 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtText>(_(\"Select Connection\").data(), rect7, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect8 = { (Sint16)(uiPosition.x + 16), (Sint16)(uiPosition.y + 427), 250, 35 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtTextButton>(_(\"Change Gateway\"), nullptr, rect8, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold | UiFlags::ElementHidden));\r\n\r\n\tvecSelConnDlg.push_back(std::make_unique<UiList>(vecConnItems, vecConnItems.size(), uiPosition.x + 305, (uiPosition.y + 256), 285, 26, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::VerticalCenter | UiFlags::ColorUiGoldDark));\r\n\r\n\tconst SDL_Rect rect9 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect9, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect10 = { (Sint16)(uiPosition.x + 454), (Sint16)(uiPosition.y + 427), 144, 35 };\r\n\tvecSelConnDlg.push_back(std::make_unique<UiArtTextButton>(_(\"Cancel\"), &UiFocusNavigationEsc, rect10, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tUiInitList(SelconnFocus, SelconnSelect, SelconnEsc, vecSelConnDlg, true);\r\n}\r\n\r\nvoid SelconnFree()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\r\n\tvecConnItems.clear();\r\n\r\n\tvecSelConnDlg.clear();\r\n}\r\n\r\nvoid SelconnEsc()\r\n{\r\n\tselconn_ReturnValue = false;\r\n\tselconn_EndMenu = true;\r\n}\r\n\r\nvoid SelconnFocus(size_t value)\r\n{\r\n\tint players = MAX_PLRS;\r\n\tswitch (vecConnItems[value]->m_value) {\r\n\tcase SELCONN_TCP:\r\n\t\tCopyUtf8(selconn_Description, _(\"All computers must be connected to a TCP-compatible network.\"), sizeof(selconn_Description));\r\n\t\tplayers = MAX_PLRS;\r\n\t\tbreak;\r\n\tcase SELCONN_ZT:\r\n\t\tCopyUtf8(selconn_Description, _(\"All computers must be connected to the internet.\"), sizeof(selconn_Description));\r\n\t\tplayers = MAX_PLRS;\r\n\t\tbreak;\r\n\tcase SELCONN_LOOPBACK:\r\n\t\tCopyUtf8(selconn_Description, _(\"Play by yourself with no network exposure.\"), sizeof(selconn_Description));\r\n\t\tplayers = 1;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tCopyUtf8(selconn_MaxPlayers, fmt::format(fmt::runtime(_(\"Players Supported: {:d}\")), players), sizeof(selconn_MaxPlayers));\r\n\tCopyUtf8(selconn_Description, WordWrapString(selconn_Description, DESCRIPTION_WIDTH), sizeof(selconn_Description));\r\n}\r\n\r\nvoid SelconnSelect(size_t value)\r\n{\r\n\tprovider = vecConnItems[value]->m_value;\r\n\r\n\tSelconnFree();\r\n\tselconn_EndMenu = SNetInitializeProvider(provider, selconn_GameData);\r\n\tSelconnLoad();\r\n}\r\n\r\n} // namespace\r\n\r\nbool UiSelectProvider(GameData *gameData)\r\n{\r\n\tselconn_GameData = gameData;\r\n\tSelconnLoad();\r\n\r\n\tselconn_ReturnValue = true;\r\n\tselconn_EndMenu = false;\r\n\twhile (!selconn_EndMenu) {\r\n\t\tUiClearScreen();\r\n\t\tUiPollAndRender();\r\n\t}\r\n\tSelconnFree();\r\n\r\n\treturn selconn_ReturnValue;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/multi/selgame.cpp",
    "content": "#include \"DiabloUI/multi/selgame.h\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/hero/selhero.h\"\r\n#include \"DiabloUI/scrollbar.h\"\r\n#include \"DiabloUI/selok.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"config.h\"\r\n#include \"diablo.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"menu.h\"\r\n#include \"multi.h\"\r\n#include \"options.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nchar selgame_Label[32];\r\nchar selgame_Ip[129] = \"\";\r\nchar selgame_Password[16] = \"\";\r\nchar selgame_Description[512];\r\nstd::string selgame_Title;\r\nbool selgame_enteringGame;\r\nsize_t selgame_selectedGame;\r\nbool selgame_endMenu;\r\nint *gdwPlayerId;\r\n_difficulty nDifficulty;\r\nint nTickRate;\r\nint heroLevel;\r\n\r\nstatic GameData *m_game_data;\r\nextern int provider;\r\n\r\n#define DESCRIPTION_WIDTH 205\r\n\r\nnamespace {\r\n\r\nconst char *title = \"\";\r\n\r\nstd::vector<std::unique_ptr<UiListItem>> vecSelGameDlgItems;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecSelGameDialog;\r\nstd::vector<GameInfo> Gamelist;\r\nuint32_t firstPublicGameInfoRequestSend = 0;\r\nsize_t HighlightedItem;\r\n\r\nvoid selgame_FreeVectors()\r\n{\r\n\tvecSelGameDlgItems.clear();\r\n\r\n\tvecSelGameDialog.clear();\r\n}\r\n\r\nvoid selgame_Init()\r\n{\r\n\tLoadBackgroundArt(\"ui_art\\\\selgame\");\r\n\tLoadScrollBar();\r\n}\r\n\r\nvoid selgame_Free()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\tUnloadScrollBar();\r\n\tselgame_FreeVectors();\r\n}\r\n\r\nbool IsGameCompatible(const GameData &data)\r\n{\r\n\treturn (data.versionMajor == PROJECT_VERSION_MAJOR\r\n\t    && data.versionMinor == PROJECT_VERSION_MINOR\r\n\t    && data.versionPatch == PROJECT_VERSION_PATCH\r\n\t    && data.programid == GAME_ID);\r\n\treturn false;\r\n}\r\n\r\nstatic std::string GetErrorMessageIncompatibility(const GameData &data)\r\n{\r\n\tif (data.programid != GAME_ID) {\r\n\t\tstd::string_view gameMode;\r\n\t\tswitch (data.programid) {\r\n\t\tcase GameIdDiabloFull:\r\n\t\t\tgameMode = _(\"Diablo\");\r\n\t\t\tbreak;\r\n\t\tcase GameIdDiabloSpawn:\r\n\t\t\tgameMode = _(\"Diablo Shareware\");\r\n\t\t\tbreak;\r\n\t\tcase GameIdHellfireFull:\r\n\t\t\tgameMode = _(\"Hellfire\");\r\n\t\t\tbreak;\r\n\t\tcase GameIdHellfireSpawn:\r\n\t\t\tgameMode = _(\"Hellfire Shareware\");\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn std::string(_(\"The host is running a different game than you.\"));\r\n\t\t}\r\n\t\treturn fmt::format(fmt::runtime(_(\"The host is running a different game mode ({:s}) than you.\")), gameMode);\r\n\t} else {\r\n\t\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: Error message when somebody tries to join a game running another version. */ \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\")), PROJECT_VERSION, data.versionMajor, data.versionMinor, data.versionPatch);\r\n\t}\r\n}\r\n\r\nvoid UiInitGameSelectionList(std::string_view search)\r\n{\r\n\tselgame_enteringGame = false;\r\n\tselgame_selectedGame = 0;\r\n\r\n\tif (provider == SELCONN_LOOPBACK) {\r\n\t\tselgame_enteringGame = true;\r\n\t\tselgame_GameSelection_Select(0);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (provider == SELCONN_ZT) {\r\n\t\tCopyUtf8(selgame_Ip, GetOptions().Network.szPreviousZTGame, sizeof(selgame_Ip));\r\n\t} else {\r\n\t\tCopyUtf8(selgame_Ip, GetOptions().Network.szPreviousHost, sizeof(selgame_Ip));\r\n\t}\r\n\r\n\tselgame_FreeVectors();\r\n\r\n\tselgame_Label[0] = '\\0';\r\n\r\n\tUiAddBackground(&vecSelGameDialog);\r\n\tUiAddLogo(&vecSelGameDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tconst SDL_Rect rectScrollbar = { (Sint16)(uiPosition.x + 590), (Sint16)(uiPosition.y + 244), 25, 178 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiScrollbar>((*ArtScrollBarBackground)[0], (*ArtScrollBarThumb)[0], *ArtScrollBarArrow, rectScrollbar));\r\n\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 24), (Sint16)(uiPosition.y + 161), 590, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(ConnectionNames[provider]).data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 211), 205, 192 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(\"Description:\").data(), rect2, UiFlags::FontSize24 | UiFlags::ColorUiSilver));\r\n\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 256), DESCRIPTION_WIDTH, 192 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark, 1, 16));\r\n\r\n\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 300), (Sint16)(uiPosition.y + 211), 295, 33 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(\"Select Action\").data(), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n#ifdef PACKET_ENCRYPTION\r\n\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Create Game\"), 0, UiFlags::ColorUiGold));\r\n#endif\r\n\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Create Public Game\"), 1, UiFlags::ColorUiGold));\r\n\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Join Game\"), 2, UiFlags::ColorUiGold));\r\n\r\n\tif (provider == SELCONN_ZT) {\r\n\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(std::string_view {}, -1, UiFlags::ElementDisabled));\r\n\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Public Games\"), -1, UiFlags::ElementDisabled | UiFlags::ColorWhitegold));\r\n\r\n\t\tif (Gamelist.empty()) {\r\n\t\t\t// We expect the game list to be received after 3 seconds\r\n\t\t\tif (firstPublicGameInfoRequestSend == 0 || (SDL_GetTicks() - firstPublicGameInfoRequestSend) < 2000)\r\n\t\t\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Loading...\"), -1, UiFlags::ElementDisabled | UiFlags::ColorUiSilver));\r\n\t\t\telse\r\n\t\t\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"None\"), -1, UiFlags::ElementDisabled | UiFlags::ColorUiSilver));\r\n\t\t} else {\r\n\t\t\tfor (unsigned i = 0; i < Gamelist.size(); i++) {\r\n\t\t\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(std::string_view(Gamelist[i].name), i + 3, UiFlags::ColorUiGold));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvecSelGameDialog.push_back(std::make_unique<UiList>(vecSelGameDlgItems, 6, uiPosition.x + 305, (uiPosition.y + 255), 285, 26, UiFlags::AlignCenter | UiFlags::FontSize24));\r\n\r\n\tconst SDL_Rect rect5 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect6 = { (Sint16)(uiPosition.x + 449), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"CANCEL\"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tauto selectFn = [](size_t index) {\r\n\t\t// UiListItem::m_value could be different from\r\n\t\t// the index if packet encryption is disabled\r\n\t\tconst int itemValue = vecSelGameDlgItems[index]->m_value;\r\n\t\tselgame_GameSelection_Select(itemValue);\r\n\t};\r\n\r\n\tif (!search.empty()) {\r\n\t\tfor (size_t i = 0; i < vecSelGameDlgItems.size(); i++) {\r\n\t\t\tconst int gameIndex = vecSelGameDlgItems[i]->m_value - 3;\r\n\t\t\tif (gameIndex < 0)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (search == Gamelist[gameIndex].name)\r\n\t\t\t\tHighlightedItem = i;\r\n\t\t}\r\n\t}\r\n\r\n\tif (HighlightedItem >= vecSelGameDlgItems.size()) {\r\n\t\tHighlightedItem = vecSelGameDlgItems.size() - 1;\r\n\t}\r\n\r\n\tUiInitList(selgame_GameSelection_Focus, selectFn, selgame_GameSelection_Esc, vecSelGameDialog, true, nullptr, nullptr, HighlightedItem);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid selgame_GameSelection_Init()\r\n{\r\n\tUiInitGameSelectionList(\"\");\r\n}\r\n\r\nvoid selgame_GameSelection_Focus(size_t value)\r\n{\r\n\tHighlightedItem = value;\r\n\tconst UiListItem &item = *vecSelGameDlgItems[value];\r\n\tswitch (item.m_value) {\r\n\tcase 0:\r\n\t\tCopyUtf8(selgame_Description, _(\"Create a new game with a difficulty setting of your choice.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\tcase 1:\r\n\t\tCopyUtf8(selgame_Description, _(\"Create a new public game that anyone can join with a difficulty setting of your choice.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\tcase 2:\r\n\t\tif (provider == SELCONN_ZT) {\r\n\t\t\tCopyUtf8(selgame_Description, _(\"Enter Game ID to join a game already in progress.\"), sizeof(selgame_Description));\r\n\t\t} else {\r\n\t\t\tCopyUtf8(selgame_Description, _(\"Enter an IP or a hostname to join a game already in progress.\"), sizeof(selgame_Description));\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tconst GameInfo &gameInfo = Gamelist[item.m_value - 3];\r\n\t\tstd::string infoString = std::string(_(\"Join the public game already in progress.\"));\r\n\t\tinfoString.append(\"\\n\\n\");\r\n\t\tif (IsGameCompatible(gameInfo.gameData)) {\r\n\t\t\tstd::string_view difficulty;\r\n\t\t\tswitch (gameInfo.gameData.nDifficulty) {\r\n\t\t\tcase DIFF_NORMAL:\r\n\t\t\t\tdifficulty = _(\"Normal\");\r\n\t\t\t\tbreak;\r\n\t\t\tcase DIFF_NIGHTMARE:\r\n\t\t\t\tdifficulty = _(\"Nightmare\");\r\n\t\t\t\tbreak;\r\n\t\t\tcase DIFF_HELL:\r\n\t\t\t\tdifficulty = _(\"Hell\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tinfoString.append(fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} means: Game Difficulty. */ \"Difficulty: {:s}\")), difficulty));\r\n\t\t\tinfoString += '\\n';\r\n\t\t\tswitch (gameInfo.gameData.nTickRate) {\r\n\t\t\tcase 20:\r\n\t\t\t\tinfoString.append(_(\"Speed: Normal\"));\r\n\t\t\t\tbreak;\r\n\t\t\tcase 25:\r\n\t\t\t\tinfoString.append(_(\"Speed: Fast\"));\r\n\t\t\t\tbreak;\r\n\t\t\tcase 30:\r\n\t\t\t\tinfoString.append(_(\"Speed: Faster\"));\r\n\t\t\t\tbreak;\r\n\t\t\tcase 35:\r\n\t\t\t\tinfoString.append(_(\"Speed: Fastest\"));\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\t// This should not occur, so no translation is needed\r\n\t\t\t\tinfoString.append(StrCat(\"Speed: \", gameInfo.gameData.nTickRate));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tinfoString += '\\n';\r\n\t\t\tinfoString.append(_(\"Players: \"));\r\n\t\t\tfor (const auto &playerName : gameInfo.players) {\r\n\t\t\t\tinfoString.append(playerName);\r\n\t\t\t\tinfoString += ' ';\r\n\t\t\t}\r\n\t\t\tinfoString += '\\n';\r\n\t\t\tif (gameInfo.peerIsRelayed.value_or(false))\r\n\t\t\t\tinfoString.append(fmt::format(fmt::runtime(_(\"Ping: {:d} ms (RELAYED)\")), gameInfo.latency.value_or(0)));\r\n\t\t\telse\r\n\t\t\t\tinfoString.append(fmt::format(fmt::runtime(_(\"Ping: {:d} ms\")), gameInfo.latency.value_or(0)));\r\n\t\t} else {\r\n\t\t\tinfoString.append(GetErrorMessageIncompatibility(gameInfo.gameData));\r\n\t\t}\r\n\t\tCopyUtf8(selgame_Description, infoString, sizeof(selgame_Description));\r\n\t\tbreak;\r\n\t}\r\n\tCopyUtf8(selgame_Description, WordWrapString(selgame_Description, DESCRIPTION_WIDTH), sizeof(selgame_Description));\r\n}\r\n\r\n/**\r\n * @brief Load the current hero level from save file\r\n * @param pInfo Hero info\r\n * @return always true\r\n */\r\nbool UpdateHeroLevel(_uiheroinfo *pInfo)\r\n{\r\n\tif (pInfo->saveNumber == gSaveNumber)\r\n\t\theroLevel = pInfo->level;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid selgame_GameSelection_Select(size_t value)\r\n{\r\n\tselgame_enteringGame = true;\r\n\tselgame_selectedGame = value;\r\n\r\n\tgfnHeroInfo(UpdateHeroLevel);\r\n\r\n\tselgame_FreeVectors();\r\n\r\n\tif (value > 2) {\r\n\t\tCopyUtf8(selgame_Ip, Gamelist[value - 3].name, sizeof(selgame_Ip));\r\n\t\tselgame_Password_Select(value);\r\n\t\treturn;\r\n\t}\r\n\r\n\tUiAddBackground(&vecSelGameDialog);\r\n\tUiAddLogo(&vecSelGameDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 24), (Sint16)(uiPosition.y + 161), 590, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(&title, rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 34), (Sint16)(uiPosition.y + 211), 205, 33 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(selgame_Label, rect2, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 256), DESCRIPTION_WIDTH, 192 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark, 1, 16));\r\n\r\n\tswitch (value) {\r\n\tcase 0:\r\n\tcase 1: {\r\n\t\ttitle = _(\"Create Game\").data();\r\n\r\n\t\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 211), 295, 35 };\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(\"Select Difficulty\").data(), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Normal\"), DIFF_NORMAL));\r\n\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Nightmare\"), DIFF_NIGHTMARE));\r\n\t\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Hell\"), DIFF_HELL));\r\n\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiList>(vecSelGameDlgItems, vecSelGameDlgItems.size(), uiPosition.x + 300, (uiPosition.y + 282), 295, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rect5 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rect6 = { (Sint16)(uiPosition.x + 449), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"CANCEL\"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tUiInitList(selgame_Diff_Focus, selgame_Diff_Select, selgame_Diff_Esc, vecSelGameDialog, true);\r\n\t\tbreak;\r\n\t}\r\n\tcase 2: {\r\n\t\tselgame_Title = fmt::format(fmt::runtime(_(\"Join {:s} Games\")), _(ConnectionNames[provider]));\r\n\t\ttitle = selgame_Title.c_str();\r\n\r\n\t\tconst char *inputHint;\r\n\t\tif (provider == SELCONN_ZT) {\r\n\t\t\tinputHint = _(\"Enter Game ID\").data();\r\n\t\t} else {\r\n\t\t\tinputHint = _(\"Enter address\").data();\r\n\t\t}\r\n\r\n\t\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 305), (Sint16)(uiPosition.y + 211), 285, 33 };\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(inputHint, rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\t\tconst SDL_Rect rect5 = { (Sint16)(uiPosition.x + 305), (Sint16)(uiPosition.y + 314), 285, 33 };\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiEdit>(inputHint, selgame_Ip, 128, false, rect5, UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rect6 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tconst SDL_Rect rect7 = { (Sint16)(uiPosition.x + 449), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\t\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"CANCEL\"), &UiFocusNavigationEsc, rect7, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\t\tHighlightedItem = 0;\r\n\r\n#ifdef PACKET_ENCRYPTION\r\n\t\tUiInitList(nullptr, selgame_Password_Init, selgame_GameSelection_Init, vecSelGameDialog);\r\n#else\r\n\t\tUiInitList(nullptr, selgame_Password_Select, selgame_GameSelection_Init, vecSelGameDialog);\r\n#endif\r\n\t\tbreak;\r\n\t}\r\n\t}\r\n}\r\n\r\nvoid selgame_GameSelection_Esc()\r\n{\r\n\tUiInitList_clear();\r\n\tselgame_enteringGame = false;\r\n\tselgame_endMenu = true;\r\n}\r\n\r\nvoid selgame_Diff_Focus(size_t value)\r\n{\r\n\tswitch (vecSelGameDlgItems[value]->m_value) {\r\n\tcase DIFF_NORMAL:\r\n\t\tCopyUtf8(selgame_Label, _(\"Normal\"), sizeof(selgame_Label));\r\n\t\tCopyUtf8(selgame_Description, _(\"Normal Difficulty\\nThis is where a starting character should begin the quest to defeat Diablo.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\tcase DIFF_NIGHTMARE:\r\n\t\tCopyUtf8(selgame_Label, _(\"Nightmare\"), sizeof(selgame_Label));\r\n\t\tCopyUtf8(selgame_Description, _(\"Nightmare Difficulty\\nThe denizens of the Labyrinth have been bolstered and will prove to be a greater challenge. This is recommended for experienced characters only.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\tcase DIFF_HELL:\r\n\t\tCopyUtf8(selgame_Label, _(\"Hell\"), sizeof(selgame_Label));\r\n\t\tCopyUtf8(selgame_Description, _(\"Hell Difficulty\\nThe most powerful of the underworld's creatures lurk at the gateway into Hell. Only the most experienced characters should venture in this realm.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\t}\r\n\tCopyUtf8(selgame_Description, WordWrapString(selgame_Description, DESCRIPTION_WIDTH), sizeof(selgame_Description));\r\n}\r\n\r\nbool IsDifficultyAllowed(int value)\r\n{\r\n\tif (value == 0 || (value == 1 && heroLevel >= 20) || (value == 2 && heroLevel >= 30)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tselgame_Free();\r\n\r\n\tif (value == 1)\r\n\t\tUiSelOkDialog(title, _(\"Your character must reach level 20 before you can enter a multiplayer game of Nightmare difficulty.\").data(), false);\r\n\tif (value == 2)\r\n\t\tUiSelOkDialog(title, _(\"Your character must reach level 30 before you can enter a multiplayer game of Hell difficulty.\").data(), false);\r\n\r\n\tselgame_Init();\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid selgame_Diff_Select(size_t value)\r\n{\r\n\tif (selhero_isMultiPlayer && !IsDifficultyAllowed(vecSelGameDlgItems[value]->m_value)) {\r\n\t\tselgame_GameSelection_Select(selgame_selectedGame);\r\n\t\treturn;\r\n\t}\r\n\r\n\tnDifficulty = (_difficulty)vecSelGameDlgItems[value]->m_value;\r\n\r\n\tif (!selhero_isMultiPlayer) {\r\n\t\t// This is part of a dangerous hack to enable difficulty selection in single-player.\r\n\t\t// FIXME: Dialogs should not refer to each other's variables.\r\n\r\n\t\t// We're in the selhero loop instead of the selgame one.\r\n\t\t// Free the selgame data and flag the end of the selhero loop.\r\n\t\tselhero_endMenu = true;\r\n\r\n\t\t// We only call FreeVectors because ArtBackground.Unload()\r\n\t\t// will be called by selheroFree().\r\n\t\tselgame_FreeVectors();\r\n\r\n\t\t// We must clear the InitList because selhero's loop will perform\r\n\t\t// one more iteration after this function exits.\r\n\t\tUiInitList_clear();\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tselgame_GameSpeedSelection();\r\n}\r\n\r\nvoid selgame_Diff_Esc()\r\n{\r\n\tif (!selhero_isMultiPlayer) {\r\n\t\tselgame_Free();\r\n\r\n\t\tselhero_Init();\r\n\t\tselhero_List_Init();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (provider == SELCONN_LOOPBACK) {\r\n\t\tselgame_GameSelection_Esc();\r\n\t\treturn;\r\n\t}\r\n\r\n\tHighlightedItem = 0;\r\n\tselgame_GameSelection_Init();\r\n}\r\n\r\nvoid selgame_GameSpeedSelection()\r\n{\r\n\tgfnHeroInfo(UpdateHeroLevel);\r\n\r\n\tselgame_FreeVectors();\r\n\r\n\tUiAddBackground(&vecSelGameDialog);\r\n\tUiAddLogo(&vecSelGameDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 24), (Sint16)(uiPosition.y + 161), 590, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(\"Create Game\").data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 34), (Sint16)(uiPosition.y + 211), 205, 33 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(selgame_Label, rect2, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 256), DESCRIPTION_WIDTH, 192 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark, 1, 16));\r\n\r\n\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 211), 295, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(\"Select Game Speed\").data(), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Normal\"), 20));\r\n\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Fast\"), 30));\r\n\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Faster\"), 40));\r\n\tvecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_(\"Fastest\"), 50));\r\n\r\n\tvecSelGameDialog.push_back(std::make_unique<UiList>(vecSelGameDlgItems, vecSelGameDlgItems.size(), uiPosition.x + 300, (uiPosition.y + 279), 295, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect5 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect6 = { (Sint16)(uiPosition.x + 449), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"CANCEL\"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tUiInitList(selgame_Speed_Focus, selgame_Speed_Select, selgame_Speed_Esc, vecSelGameDialog, true);\r\n}\r\n\r\nvoid selgame_Speed_Focus(size_t value)\r\n{\r\n\tswitch (vecSelGameDlgItems[value]->m_value) {\r\n\tcase 20:\r\n\t\tCopyUtf8(selgame_Label, _(\"Normal\"), sizeof(selgame_Label));\r\n\t\tCopyUtf8(selgame_Description, _(\"Normal Speed\\nThis is where a starting character should begin the quest to defeat Diablo.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\tcase 30:\r\n\t\tCopyUtf8(selgame_Label, _(\"Fast\"), sizeof(selgame_Label));\r\n\t\tCopyUtf8(selgame_Description, _(\"Fast Speed\\nThe denizens of the Labyrinth have been hastened and will prove to be a greater challenge. This is recommended for experienced characters only.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\tcase 40:\r\n\t\tCopyUtf8(selgame_Label, _(\"Faster\"), sizeof(selgame_Label));\r\n\t\tCopyUtf8(selgame_Description, _(\"Faster Speed\\nMost monsters of the dungeon will seek you out quicker than ever before. Only an experienced champion should try their luck at this speed.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\tcase 50:\r\n\t\tCopyUtf8(selgame_Label, _(\"Fastest\"), sizeof(selgame_Label));\r\n\t\tCopyUtf8(selgame_Description, _(\"Fastest Speed\\nThe minions of the underworld will rush to attack without hesitation. Only a true speed demon should enter at this pace.\"), sizeof(selgame_Description));\r\n\t\tbreak;\r\n\t}\r\n\tCopyUtf8(selgame_Description, WordWrapString(selgame_Description, DESCRIPTION_WIDTH), sizeof(selgame_Description));\r\n}\r\n\r\nvoid selgame_Speed_Esc()\r\n{\r\n\tselgame_GameSelection_Select(selgame_selectedGame);\r\n}\r\n\r\nvoid selgame_Speed_Select(size_t value)\r\n{\r\n\tnTickRate = vecSelGameDlgItems[value]->m_value;\r\n\r\n\tif (provider == SELCONN_LOOPBACK || selgame_selectedGame == 1) {\r\n\t\tselgame_Password_Select(0);\r\n\t\treturn;\r\n\t}\r\n\r\n\tselgame_Password_Init(0);\r\n}\r\n\r\nvoid selgame_Password_Init(size_t /*value*/)\r\n{\r\n\tmemset(&selgame_Password, 0, sizeof(selgame_Password));\r\n\r\n\tselgame_FreeVectors();\r\n\r\n\tUiAddBackground(&vecSelGameDialog);\r\n\tUiAddLogo(&vecSelGameDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 24), (Sint16)(uiPosition.y + 161), 590, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(ConnectionNames[provider]).data(), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 211), 205, 192 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(\"Description:\").data(), rect2, UiFlags::FontSize24 | UiFlags::ColorUiSilver));\r\n\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 35), (Sint16)(uiPosition.y + 256), DESCRIPTION_WIDTH, 192 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark, 1, 16));\r\n\r\n\tconst SDL_Rect rect4 = { (Sint16)(uiPosition.x + 305), (Sint16)(uiPosition.y + 211), 285, 33 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtText>(_(\"Enter Password\").data(), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\t// Allow password to be empty only when joining games\r\n\tconst bool allowEmpty = selgame_selectedGame == 2;\r\n\tconst SDL_Rect rect5 = { (Sint16)(uiPosition.x + 305), (Sint16)(uiPosition.y + 314), 285, 33 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiEdit>(_(\"Enter Password\"), selgame_Password, 15, allowEmpty, rect5, UiFlags::FontSize24 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect6 = { (Sint16)(uiPosition.x + 299), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"OK\"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tconst SDL_Rect rect7 = { (Sint16)(uiPosition.x + 449), (Sint16)(uiPosition.y + 427), 140, 35 };\r\n\tvecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_(\"CANCEL\"), &UiFocusNavigationEsc, rect7, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tUiInitList(nullptr, selgame_Password_Select, selgame_Password_Esc, vecSelGameDialog);\r\n}\r\n\r\nstatic bool IsGameCompatibleWithErrorMessage(const GameData &data)\r\n{\r\n\tif (IsGameCompatible(data))\r\n\t\treturn IsDifficultyAllowed(data.nDifficulty);\r\n\r\n\tselgame_Free();\r\n\r\n\tconst std::string errorMessage = GetErrorMessageIncompatibility(data);\r\n\tUiSelOkDialog(title, errorMessage.c_str(), false);\r\n\r\n\tselgame_Init();\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid selgame_Password_Select(size_t /*value*/)\r\n{\r\n\tchar *gamePassword = nullptr;\r\n\tif (selgame_selectedGame == 0)\r\n\t\tgamePassword = selgame_Password;\r\n\tif (selgame_selectedGame == 2 && strlen(selgame_Password) > 0)\r\n\t\tgamePassword = selgame_Password;\r\n\r\n\t// If there is an error, the error message won't necessarily be set.\r\n\t// Clear the error so that we display \"Unknown network error\"\r\n\t// instead of an arbitrary message in that case.\r\n\tSDL_ClearError();\r\n\r\n\tif (selgame_selectedGame > 1) {\r\n\t\tbool allowJoin = true;\r\n\t\tif (selgame_selectedGame > 2)\r\n\t\t\tallowJoin = IsGameCompatible(Gamelist[selgame_selectedGame - 3].gameData);\r\n\t\tif (provider == SELCONN_ZT) {\r\n\t\t\tfor (unsigned int i = 0; i < (sizeof(selgame_Ip) / sizeof(selgame_Ip[0])); i++) {\r\n\t\t\t\tselgame_Ip[i] = (selgame_Ip[i] >= 'A' && selgame_Ip[i] <= 'Z') ? selgame_Ip[i] + 'a' - 'A' : selgame_Ip[i];\r\n\t\t\t}\r\n\t\t\tstrcpy(GetOptions().Network.szPreviousZTGame, selgame_Ip);\r\n\t\t} else {\r\n\t\t\tstrcpy(GetOptions().Network.szPreviousHost, selgame_Ip);\r\n\t\t}\r\n\t\tif (allowJoin && SNetJoinGame(selgame_Ip, gamePassword, gdwPlayerId)) {\r\n\t\t\tif (!IsGameCompatibleWithErrorMessage(*m_game_data)) {\r\n\t\t\t\tInitGameInfo();\r\n\t\t\t\tselgame_GameSelection_Select(1);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tUiInitList_clear();\r\n\t\t\tselgame_endMenu = true;\r\n\t\t} else {\r\n\t\t\tInitGameInfo();\r\n\t\t\tselgame_Free();\r\n\t\t\tstd::string error;\r\n\t\t\tif (!allowJoin)\r\n\t\t\t\terror = GetErrorMessageIncompatibility(Gamelist[selgame_selectedGame - 3].gameData);\r\n\t\t\telse\r\n\t\t\t\terror = SDL_GetError();\r\n\t\t\tif (error.empty())\r\n\t\t\t\terror = \"Unknown network error\";\r\n\t\t\tUiSelOkDialog(_(\"Multi Player Game\").data(), error.c_str(), false);\r\n\t\t\tselgame_Init();\r\n\t\t\tif (selgame_selectedGame == 2)\r\n\t\t\t\tselgame_Password_Init(selgame_selectedGame);\r\n\t\t\telse\r\n\t\t\t\tUiInitGameSelectionList(\"\");\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tm_game_data->nDifficulty = nDifficulty;\r\n\tm_game_data->nTickRate = nTickRate;\r\n\tm_game_data->bRunInTown = *GetOptions().Gameplay.runInTown ? 1 : 0;\r\n\tm_game_data->bTheoQuest = *GetOptions().Gameplay.theoQuest ? 1 : 0;\r\n\tm_game_data->bCowQuest = *GetOptions().Gameplay.cowQuest ? 1 : 0;\r\n\r\n\tGameData gameInitInfo = *m_game_data;\r\n\tgameInitInfo.swapLE();\r\n\tif (SNetCreateGame(nullptr, gamePassword, reinterpret_cast<char *>(&gameInitInfo), sizeof(gameInitInfo), gdwPlayerId)) {\r\n\t\tUiInitList_clear();\r\n\t\tselgame_endMenu = true;\r\n\t} else {\r\n\t\tselgame_Free();\r\n\t\tstd::string error = SDL_GetError();\r\n\t\tif (error.empty())\r\n\t\t\terror = \"Unknown network error\";\r\n\t\tUiSelOkDialog(_(\"Multi Player Game\").data(), error.c_str(), false);\r\n\t\tselgame_Init();\r\n\t\tselgame_Password_Init(0);\r\n\t}\r\n}\r\n\r\nvoid selgame_Password_Esc()\r\n{\r\n\tif (selgame_selectedGame == 2)\r\n\t\tselgame_GameSelection_Select(2);\r\n\telse\r\n\t\tselgame_GameSpeedSelection();\r\n}\r\n\r\nvoid RefreshGameList()\r\n{\r\n\tstatic uint32_t lastRequest = 0;\r\n\tstatic uint32_t lastUpdate = 0;\r\n\r\n\tif (selgame_enteringGame)\r\n\t\treturn;\r\n\r\n\tconst uint32_t currentTime = SDL_GetTicks();\r\n\r\n\tif ((lastRequest == 0 || currentTime - lastRequest > 30000) && DvlNet_SendInfoRequest()) {\r\n\t\tlastRequest = currentTime;\r\n\t\tlastUpdate = currentTime - 3000; // Give 2 sec for responses, but don't wait 5\r\n\t\tif (firstPublicGameInfoRequestSend == 0)\r\n\t\t\tfirstPublicGameInfoRequestSend = currentTime;\r\n\t}\r\n\r\n\tif (lastUpdate == 0 || currentTime - lastUpdate > 5000) {\r\n\t\tconst int gameIndex = vecSelGameDlgItems[HighlightedItem]->m_value - 3;\r\n\t\tconst std::string gameSearch = gameIndex >= 0 ? Gamelist[gameIndex].name : \"\";\r\n\t\tstd::vector<GameInfo> gamelist = DvlNet_GetGamelist();\r\n\t\tGamelist.clear();\r\n\t\tfor (unsigned i = 0; i < gamelist.size(); i++) {\r\n\t\t\tGamelist.push_back(gamelist[i]);\r\n\t\t}\r\n\t\tUiInitGameSelectionList(gameSearch);\r\n\t\tlastUpdate = currentTime;\r\n\t}\r\n}\r\n\r\nbool UiSelectGame(GameData *gameData, int *playerId)\r\n{\r\n\tfirstPublicGameInfoRequestSend = 0;\r\n\tgdwPlayerId = playerId;\r\n\tm_game_data = gameData;\r\n\tselgame_Init();\r\n\tHighlightedItem = 0;\r\n\tselgame_GameSelection_Init();\r\n\r\n\tselgame_endMenu = false;\r\n\r\n\tDvlNet_ClearPassword();\r\n\tDvlNet_ClearGamelist();\r\n\r\n\twhile (!selgame_endMenu) {\r\n\t\tUiClearScreen();\r\n\t\tUiPollAndRender();\r\n\t\tif (provider == SELCONN_ZT)\r\n\t\t\tRefreshGameList();\r\n\t}\r\n\tselgame_Free();\r\n\r\n\treturn selgame_enteringGame;\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/multi/selgame.h",
    "content": "#pragma once\r\n\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern _difficulty nDifficulty;\r\n\r\nvoid selgame_GameSelection_Init();\r\nvoid selgame_GameSelection_Focus(size_t value);\r\nvoid selgame_GameSelection_Select(size_t value);\r\nvoid selgame_GameSelection_Esc();\r\nvoid selgame_Diff_Focus(size_t value);\r\nvoid selgame_Diff_Select(size_t value);\r\nvoid selgame_Diff_Esc();\r\nvoid selgame_GameSpeedSelection();\r\nvoid selgame_Speed_Focus(size_t value);\r\nvoid selgame_Speed_Select(size_t value);\r\nvoid selgame_Speed_Esc();\r\nvoid selgame_Password_Init(size_t value);\r\nvoid selgame_Password_Select(size_t value);\r\nvoid selgame_Password_Esc();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/progress.cpp",
    "content": "#include <memory>\r\n#include <optional>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/button.h\"\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"controls/input.h\"\r\n#include \"controls/menu_controls.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/load_pcx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nOptionalOwnedClxSpriteList ArtPopupSm;\r\nOptionalOwnedClxSpriteList ArtProgBG;\r\nOptionalOwnedClxSpriteList ProgFil;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecProgress;\r\nbool endMenu;\r\n\r\nvoid DialogActionCancel()\r\n{\r\n\tendMenu = true;\r\n}\r\n\r\nvoid ProgressLoadBackground()\r\n{\r\n\tUiLoadBlackBackground();\r\n\tArtPopupSm = LoadPcx(\"ui_art\\\\spopup\");\r\n\tArtProgBG = LoadPcx(\"ui_art\\\\prog_bg\");\r\n}\r\n\r\nvoid ProgressLoadForeground()\r\n{\r\n\tLoadDialogButtonGraphics();\r\n\tProgFil = LoadPcx(\"ui_art\\\\prog_fil\");\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tconst SDL_Rect rect3 = { (Sint16)(uiPosition.x + 265), (Sint16)(uiPosition.y + 267), DialogButtonWidth, DialogButtonHeight };\r\n\tvecProgress.push_back(std::make_unique<UiButton>(_(\"Cancel\"), &DialogActionCancel, rect3));\r\n}\r\n\r\nvoid ProgressFreeBackground()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\tArtPopupSm = std::nullopt;\r\n\tArtProgBG = std::nullopt;\r\n}\r\n\r\nvoid ProgressFreeForeground()\r\n{\r\n\tvecProgress.clear();\r\n\tProgFil = std::nullopt;\r\n\tFreeDialogButtonGraphics();\r\n}\r\n\r\nPoint GetPosition()\r\n{\r\n\treturn { GetCenterOffset(280), GetCenterOffset(144, gnScreenHeight) };\r\n}\r\n\r\nvoid ProgressRenderBackground()\r\n{\r\n\tSDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);\r\n\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\tconst Point position = GetPosition();\r\n\tRenderClxSprite(out.subregion(position.x, position.y, 280, 140), (*ArtPopupSm)[0], { 0, 0 });\r\n\tRenderClxSprite(out.subregion(GetCenterOffset(227), 0, 227, out.h()), (*ArtProgBG)[0], { 0, position.y + 52 });\r\n}\r\n\r\nvoid ProgressRenderForeground(int progress)\r\n{\r\n\tconst Surface &out = Surface(DiabloUiSurface());\r\n\tconst Point position = GetPosition();\r\n\tif (progress != 0) {\r\n\t\tconst int x = GetCenterOffset(227);\r\n\t\tconst int w = 227 * progress / 100;\r\n\t\tRenderClxSprite(out.subregion(x, 0, w, out.h()), (*ProgFil)[0], { 0, position.y + 52 });\r\n\t}\r\n\t// Not rendering an actual button, only the top 2 rows of its graphics.\r\n\tRenderClxSprite(\r\n\t    out.subregion(GetCenterOffset(110), position.y + 99, DialogButtonWidth, 2),\r\n\t    ButtonSprite(/*pressed=*/false), { 0, 0 });\r\n}\r\n\r\n} // namespace\r\n\r\nbool UiProgressDialog(int (*fnfunc)())\r\n{\r\n\t// Blit the background once and then free it.\r\n\tProgressLoadBackground();\r\n\r\n\tProgressRenderBackground();\r\n\r\n\tif (RenderDirectlyToOutputSurface && PalSurface != nullptr) {\r\n\t\t// Render into all the backbuffers if there are multiple.\r\n\t\tconst void *initialPixels = PalSurface->pixels;\r\n\t\tUiFadeIn();\r\n\t\twhile (PalSurface->pixels != initialPixels) {\r\n\t\t\tProgressRenderBackground();\r\n\t\t\tUiFadeIn();\r\n\t\t}\r\n\t}\r\n\r\n\tProgressFreeBackground();\r\n\r\n\tProgressLoadForeground();\r\n\r\n\tendMenu = false;\r\n\tint progress = 0;\r\n\r\n\tSDL_Event event;\r\n\twhile (!endMenu && progress < 100) {\r\n\t\tprogress = fnfunc();\r\n\t\tProgressRenderForeground(progress);\r\n\t\tUiRenderItems(vecProgress);\r\n\t\tDrawMouse();\r\n\t\tUiFadeIn();\r\n\r\n\t\twhile (PollEvent(&event)) {\r\n\t\t\tswitch (event.type) {\r\n\t\t\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\t\t\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\t\t\tUiItemMouseEvents(&event, vecProgress);\r\n\t\t\t\tbreak;\r\n\t\t\tcase SDL_EVENT_KEY_DOWN:\r\n\t\t\t\tswitch (SDLC_EventKey(event)) {\r\n#ifndef USE_SDL1\r\n\t\t\t\tcase SDLK_KP_ENTER:\r\n#endif\r\n\t\t\t\tcase SDLK_ESCAPE:\r\n\t\t\t\tcase SDLK_RETURN:\r\n\t\t\t\tcase SDLK_SPACE:\r\n\t\t\t\t\tendMenu = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tfor (const MenuAction menuAction : GetMenuActions(event)) {\r\n\t\t\t\t\tif (IsNoneOf(menuAction, MenuAction_BACK, MenuAction_SELECT))\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\tendMenu = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tUiHandleEvents(&event);\r\n\t\t}\r\n\t}\r\n\tProgressFreeForeground();\r\n\r\n\treturn progress == 100;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/scrollbar.cpp",
    "content": "#include \"scrollbar.h\"\r\n\r\n#include <optional>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_pcx.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteList ArtScrollBarBackground;\r\nOptionalOwnedClxSpriteList ArtScrollBarThumb;\r\nOptionalOwnedClxSpriteList ArtScrollBarArrow;\r\n\r\nvoid LoadScrollBar()\r\n{\r\n\tArtScrollBarBackground = LoadPcx(\"ui_art\\\\sb_bg\");\r\n\tArtScrollBarThumb = LoadPcx(\"ui_art\\\\sb_thumb\");\r\n\tArtScrollBarArrow = LoadPcxSpriteList(\"ui_art\\\\sb_arrow\", 4);\r\n}\r\n\r\nvoid UnloadScrollBar()\r\n{\r\n\tArtScrollBarArrow = std::nullopt;\r\n\tArtScrollBarThumb = std::nullopt;\r\n\tArtScrollBarBackground = std::nullopt;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/scrollbar.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"utils/sdl_geometry.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern OptionalOwnedClxSpriteList ArtScrollBarBackground;\r\nextern OptionalOwnedClxSpriteList ArtScrollBarThumb;\r\nextern OptionalOwnedClxSpriteList ArtScrollBarArrow;\r\nconstexpr Uint16 ScrollBarBgWidth = 25;\r\n\r\nenum ScrollBarArrowFrame : uint8_t {\r\n\tScrollBarArrowFrame_UP_ACTIVE,\r\n\tScrollBarArrowFrame_UP,\r\n\tScrollBarArrowFrame_DOWN_ACTIVE,\r\n\tScrollBarArrowFrame_DOWN,\r\n};\r\n\r\nconstexpr Uint16 ScrollBarArrowWidth = 25;\r\n\r\ninline SDL_Rect UpArrowRect(const UiScrollbar &bar)\r\n{\r\n\treturn MakeSdlRect(\r\n\t    bar.m_rect.x,\r\n\t    bar.m_rect.y,\r\n\t    ScrollBarArrowWidth,\r\n\t    bar.m_arrow[0].height());\r\n}\r\n\r\ninline SDL_Rect DownArrowRect(const UiScrollbar &bar)\r\n{\r\n\treturn MakeSdlRect(\r\n\t    bar.m_rect.x,\r\n\t    bar.m_rect.y + bar.m_rect.h - bar.m_arrow[0].height(),\r\n\t    ScrollBarArrowWidth,\r\n\t    bar.m_arrow[0].height());\r\n}\r\n\r\ninline Uint16 BarHeight(const UiScrollbar &bar)\r\n{\r\n\treturn bar.m_rect.h - 2 * bar.m_arrow[0].height();\r\n}\r\n\r\ninline SDL_Rect BarRect(const UiScrollbar &bar)\r\n{\r\n\treturn MakeSdlRect(\r\n\t    bar.m_rect.x,\r\n\t    bar.m_rect.y + bar.m_arrow[0].height(),\r\n\t    ScrollBarArrowWidth,\r\n\t    BarHeight(bar));\r\n}\r\n\r\ninline SDL_Rect ThumbRect(const UiScrollbar &bar, size_t selectedIndex, size_t numItems)\r\n{\r\n\tconstexpr int ThumbOffsetX = 3;\r\n\tconst int thumbMaxY = BarHeight(bar) - bar.m_thumb.height();\r\n\tconst int thumbY = static_cast<int>(selectedIndex * thumbMaxY / (numItems - 1));\r\n\r\n\treturn MakeSdlRect(\r\n\t    bar.m_rect.x + ThumbOffsetX,\r\n\t    bar.m_rect.y + bar.m_arrow[0].height() + thumbY,\r\n\t    bar.m_rect.w - ThumbOffsetX,\r\n\t    bar.m_thumb.height());\r\n}\r\n\r\nvoid LoadScrollBar();\r\nvoid UnloadScrollBar();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/selok.cpp",
    "content": "#include \"DiabloUI/selok.h\"\r\n\r\n#include <cstddef>\r\n#include <memory>\r\n#include <optional>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nchar dialogText[256];\r\n\r\n} // namespace\r\n\r\nbool selok_endMenu;\r\n\r\nstd::vector<std::unique_ptr<UiListItem>> vecSelOkDialogItems;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecSelOkDialog;\r\n\r\n#define MESSAGE_WIDTH 400\r\n\r\nvoid selok_Free()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\r\n\tvecSelOkDialogItems.clear();\r\n\r\n\tvecSelOkDialog.clear();\r\n}\r\n\r\nvoid selok_Select(size_t /*value*/)\r\n{\r\n\tselok_endMenu = true;\r\n}\r\n\r\nvoid selok_Esc()\r\n{\r\n\tselok_endMenu = true;\r\n}\r\n\r\nvoid UiSelOkDialog(const char *title, const char *body, bool background)\r\n{\r\n\tif (!background) {\r\n\t\tUiLoadBlackBackground();\r\n\t} else {\r\n\t\tif (!gbIsSpawn) {\r\n\t\t\tLoadBackgroundArt(\"ui_art\\\\mainmenu\");\r\n\t\t} else {\r\n\t\t\tLoadBackgroundArt(\"ui_art\\\\swmmenu\");\r\n\t\t}\r\n\t}\r\n\r\n\tUiAddBackground(&vecSelOkDialog);\r\n\tUiAddLogo(&vecSelOkDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tif (title != nullptr) {\r\n\t\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 24), (Sint16)(uiPosition.y + 161), 590, 35 };\r\n\t\tvecSelOkDialog.push_back(std::make_unique<UiArtText>(title, rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\t\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 140), (Sint16)(uiPosition.y + 210), 560, 168 };\r\n\t\tvecSelOkDialog.push_back(std::make_unique<UiArtText>(dialogText, rect2, UiFlags::FontSize24 | UiFlags::ColorUiSilver));\r\n\t} else {\r\n\t\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 140), (Sint16)(uiPosition.y + 197), 560, 168 };\r\n\t\tvecSelOkDialog.push_back(std::make_unique<UiArtText>(dialogText, rect1, UiFlags::FontSize24 | UiFlags::ColorUiSilver));\r\n\t}\r\n\r\n\tvecSelOkDialogItems.push_back(std::make_unique<UiListItem>(_(\"OK\"), 0));\r\n\tvecSelOkDialog.push_back(std::make_unique<UiList>(vecSelOkDialogItems, 1, uiPosition.x + 230, (uiPosition.y + 390), 180, 35, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tCopyUtf8(dialogText, WordWrapString(body, MESSAGE_WIDTH, GameFont24), sizeof(dialogText));\r\n\r\n\tUiInitList(nullptr, selok_Select, selok_Esc, vecSelOkDialog, false);\r\n\r\n\tselok_endMenu = false;\r\n\twhile (!selok_endMenu) {\r\n\t\tUiClearScreen();\r\n\t\tUiRenderItems(vecSelOkDialog);\r\n\t\tUiPollAndRender();\r\n\t}\r\n\r\n\tselok_Free();\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/selok.h",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\n\r\nvoid UiSelOkDialog(const char *title, const char *body, bool background);\r\nvoid selok_Free();\r\nvoid selok_Select(int value);\r\nvoid selok_Esc();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/selstart.cpp",
    "content": "#include \"selstart.h\"\r\n\r\n#include <cstddef>\r\n#include <memory>\r\n#include <optional>\r\n#include <vector>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nbool endMenu;\r\n\r\nstd::vector<std::unique_ptr<UiListItem>> vecDialogItems;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecDialog;\r\n\r\nvoid ItemSelected(size_t value)\r\n{\r\n\tauto option = static_cast<StartUpGameMode>(vecDialogItems[value]->m_value);\r\n\tGetOptions().GameMode.gameMode.SetValue(option);\r\n\tGetOptions().Mods.SetHellfireEnabled(option == StartUpGameMode::Hellfire);\r\n\tSaveOptions();\r\n\tendMenu = true;\r\n}\r\n\r\nvoid EscPressed()\r\n{\r\n\tendMenu = true;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid UiSelStartUpGameOption()\r\n{\r\n\tArtBackgroundWidescreen = LoadOptionalClx(\"ui_art\\\\mainmenuw.clx\");\r\n\tLoadBackgroundArt(\"ui_art\\\\mainmenu\");\r\n\tUiAddBackground(&vecDialog);\r\n\tUiAddLogo(&vecDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Enter Hellfire\"), static_cast<int>(StartUpGameMode::Hellfire)));\r\n\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Switch to Diablo\"), static_cast<int>(StartUpGameMode::Diablo)));\r\n\tvecDialog.push_back(std::make_unique<UiList>(vecDialogItems, vecDialogItems.size(), uiPosition.x + 64, uiPosition.y + 240, 510, 43, UiFlags::AlignCenter | UiFlags::FontSize42 | UiFlags::ColorUiGold, 5));\r\n\r\n\tUiInitList(nullptr, ItemSelected, EscPressed, vecDialog, true);\r\n\r\n\tendMenu = false;\r\n\twhile (!endMenu) {\r\n\t\tUiClearScreen();\r\n\t\tUiRenderItems(vecDialog);\r\n\t\tUiPollAndRender();\r\n\t}\r\n\r\n\tArtBackground = std::nullopt;\r\n\tArtBackgroundWidescreen = std::nullopt;\r\n\tvecDialogItems.clear();\r\n\tvecDialog.clear();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/selstart.h",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\n\r\nvoid UiSelStartUpGameOption();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/selyesno.cpp",
    "content": "#include \"selyesno.h\"\r\n\r\n#include <cstddef>\r\n#include <memory>\r\n#include <optional>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nbool selyesno_endMenu;\r\nbool selyesno_value;\r\nchar selyesno_confirmationMessage[256];\r\n\r\nstd::vector<std::unique_ptr<UiListItem>> vecSelYesNoDialogItems;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecSelYesNoDialog;\r\n\r\n#define MESSAGE_WIDTH 400\r\n\r\nvoid SelyesnoFree()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\r\n\tvecSelYesNoDialogItems.clear();\r\n\r\n\tvecSelYesNoDialog.clear();\r\n}\r\n\r\nvoid SelyesnoSelect(size_t value)\r\n{\r\n\tselyesno_value = vecSelYesNoDialogItems[value]->m_value == 0;\r\n\tselyesno_endMenu = true;\r\n}\r\n\r\nvoid SelyesnoEsc()\r\n{\r\n\tselyesno_value = false;\r\n\tselyesno_endMenu = true;\r\n}\r\n\r\n} // namespace\r\n\r\nbool UiSelHeroYesNoDialog(const char *title, const char *body)\r\n{\r\n\tUiLoadBlackBackground();\r\n\tUiAddBackground(&vecSelYesNoDialog);\r\n\tUiAddLogo(&vecSelYesNoDialog);\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\r\n\tconst SDL_Rect rect1 = { (Sint16)(uiPosition.x + 24), (Sint16)(uiPosition.y + 161), 590, 35 };\r\n\tvecSelYesNoDialog.push_back(std::make_unique<UiArtText>(title, rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));\r\n\r\n\tconst SDL_Rect rect2 = { (Sint16)(uiPosition.x + 120), (Sint16)(uiPosition.y + 236), MESSAGE_WIDTH, 168 };\r\n\tvecSelYesNoDialog.push_back(std::make_unique<UiArtText>(selyesno_confirmationMessage, rect2, UiFlags::FontSize24 | UiFlags::ColorUiSilver));\r\n\r\n\tvecSelYesNoDialogItems.push_back(std::make_unique<UiListItem>(_(\"Yes\"), 0));\r\n\tvecSelYesNoDialogItems.push_back(std::make_unique<UiListItem>(_(\"No\"), 1));\r\n\tvecSelYesNoDialog.push_back(std::make_unique<UiList>(vecSelYesNoDialogItems, vecSelYesNoDialogItems.size(), uiPosition.x + 230, (uiPosition.y + 390), 180, 35, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));\r\n\r\n\tCopyUtf8(selyesno_confirmationMessage, WordWrapString(body, MESSAGE_WIDTH, GameFont24), sizeof(selyesno_confirmationMessage));\r\n\r\n\tUiInitList(nullptr, SelyesnoSelect, SelyesnoEsc, vecSelYesNoDialog, true);\r\n\r\n\tselyesno_value = true;\r\n\tselyesno_endMenu = false;\r\n\twhile (!selyesno_endMenu) {\r\n\t\tUiClearScreen();\r\n\t\tUiRenderItems(vecSelYesNoDialog);\r\n\t\tUiPollAndRender();\r\n\t}\r\n\r\n\tSelyesnoFree();\r\n\r\n\treturn selyesno_value;\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/selyesno.h",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\n\r\nbool UiSelHeroYesNoDialog(const char *title, const char *body);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/settingsmenu.cpp",
    "content": "#include <algorithm>\r\n#include <cassert>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/scrollbar.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"controls/controller.h\"\r\n#include \"controls/controller_buttons.h\"\r\n#include \"controls/controller_motion.h\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"controls/remap_keyboard.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"items.h\"\r\n#include \"options.h\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/static_vector.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nconstexpr size_t IndexKeyOrPadInput = 1;\r\nconstexpr size_t IndexPadTimerText = 2;\r\n\r\nbool endMenu = false;\r\nbool backToMain = false;\r\n\r\nstd::vector<std::unique_ptr<UiListItem>> vecDialogItems;\r\nstd::vector<std::unique_ptr<UiItemBase>> vecDialog;\r\nstd::vector<OptionEntryBase *> vecOptions;\r\nOptionCategoryBase *selectedCategory = nullptr;\r\nOptionEntryBase *selectedOption = nullptr;\r\n\r\nenum class ShownMenuType : uint8_t {\r\n\tCategories,\r\n\tSettings,\r\n\tListOption,\r\n\tKeyInput,\r\n\tPadInput,\r\n};\r\n\r\nShownMenuType shownMenu;\r\n\r\nchar optionDescription[512];\r\n\r\nRectangle rectList;\r\nRectangle rectDescription;\r\n\r\nenum class SpecialMenuEntry : int8_t {\r\n\tNone = -1,\r\n\tPreviousMenu = -2,\r\n\tUnbindKey = -3,\r\n\tBindPadButton = -4,\r\n\tUnbindPadButton = -5,\r\n};\r\n\r\nControllerButtonCombo padEntryCombo {};\r\nUint32 padEntryStartTime = 0;\r\nstd::string padEntryTimerText;\r\n\r\nbool IsValidEntry(OptionEntryBase *pOptionEntry)\r\n{\r\n\tauto flags = pOptionEntry->GetFlags();\r\n\tif (HasAnyOf(flags, OptionEntryFlags::NeedDiabloMpq) && !HaveIntro())\r\n\t\treturn false;\r\n\treturn HasNoneOf(flags, OptionEntryFlags::Invisible | (gbIsHellfire ? OptionEntryFlags::OnlyDiablo : OptionEntryFlags::OnlyHellfire));\r\n}\r\n\r\nstd::vector<DrawStringFormatArg> CreateDrawStringFormatArgForEntry(OptionEntryBase *pEntry)\r\n{\r\n\treturn std::vector<DrawStringFormatArg> {\r\n\t\t{ pEntry->GetName(), UiFlags::ColorUiGold },\r\n\t\t{ pEntry->GetValueDescription(), UiFlags::ColorUiSilver }\r\n\t};\r\n}\r\n\r\n/** @brief Check if the option text can't fit in one list line (list width minus drawn selector) */\r\nbool NeedsTwoLinesToDisplayOption(std::vector<DrawStringFormatArg> &formatArgs)\r\n{\r\n\treturn GetLineWidth(\"{}: {}\", formatArgs.data(), formatArgs.size(), 0, GameFontTables::GameFont24, 1) >= (rectList.size.width - 90);\r\n}\r\n\r\nvoid CleanUpSettingsUI()\r\n{\r\n\tUiInitList_clear();\r\n\r\n\tvecDialogItems.clear();\r\n\tvecDialog.clear();\r\n\tvecOptions.clear();\r\n\r\n\tArtBackground = std::nullopt;\r\n\tArtBackgroundWidescreen = std::nullopt;\r\n\tUnloadScrollBar();\r\n}\r\n\r\nvoid GoBackOneMenuLevel()\r\n{\r\n\tendMenu = true;\r\n\tswitch (shownMenu) {\r\n\tcase ShownMenuType::Categories:\r\n\t\tbackToMain = true;\r\n\t\tbreak;\r\n\tcase ShownMenuType::Settings:\r\n\t\tshownMenu = ShownMenuType::Categories;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tshownMenu = ShownMenuType::Settings;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid StartPadEntryTimer()\r\n{\r\n\tpadEntryCombo = ControllerButton_NONE;\r\n\tpadEntryStartTime = SDL_GetTicks();\r\n\tif (padEntryStartTime == 0)\r\n\t\tpadEntryStartTime++;\r\n\t// Removes access to these dialog items while entering bindings\r\n\tfor (size_t i = IndexPadTimerText + 1; i < vecDialogItems.size(); i++)\r\n\t\tvecDialogItems[i]->uiFlags |= UiFlags::ElementHidden;\r\n}\r\n\r\nvoid StopPadEntryTimer()\r\n{\r\n\tpadEntryCombo = ControllerButton_NONE;\r\n\tpadEntryStartTime = 0;\r\n\tpadEntryTimerText = \"\";\r\n\tvecDialogItems[IndexPadTimerText]->m_text = padEntryTimerText;\r\n\t// Restores access to these dialog items after binding is complete\r\n\tfor (size_t i = IndexPadTimerText + 1; i < vecDialogItems.size(); i++)\r\n\t\tvecDialogItems[i]->uiFlags &= ~UiFlags::ElementHidden;\r\n}\r\n\r\nvoid UpdatePadEntryTimerText()\r\n{\r\n\tif (shownMenu != ShownMenuType::PadInput)\r\n\t\treturn;\r\n\tconst Uint32 elapsed = SDL_GetTicks() - padEntryStartTime;\r\n\tif (padEntryStartTime == 0 || elapsed > 10000) {\r\n\t\tStopPadEntryTimer();\r\n\t\treturn;\r\n\t}\r\n\tpadEntryTimerText = StrCat(_(\"Press gamepad buttons to change.\"), \" \", 10 - elapsed / 1000);\r\n\tvecDialogItems[IndexPadTimerText]->m_text = padEntryTimerText;\r\n}\r\n\r\nvoid UpdateDescription(const OptionEntryBase &option)\r\n{\r\n\tauto paragraphs = WordWrapString(option.GetDescription(), rectDescription.size.width, GameFont12, 1);\r\n\tCopyUtf8(optionDescription, paragraphs, sizeof(optionDescription));\r\n}\r\n\r\nvoid UpdateDescription(const OptionCategoryBase &category)\r\n{\r\n\tauto paragraphs = WordWrapString(category.GetDescription(), rectDescription.size.width, GameFont12, 1);\r\n\tCopyUtf8(optionDescription, paragraphs, sizeof(optionDescription));\r\n}\r\n\r\nvoid ItemFocused(size_t value)\r\n{\r\n\tswitch (shownMenu) {\r\n\tcase ShownMenuType::Categories: {\r\n\t\tauto &vecItem = vecDialogItems[value];\r\n\t\toptionDescription[0] = '\\0';\r\n\t\tif (vecItem->m_value < 0)\r\n\t\t\treturn;\r\n\t\tauto *pCategory = GetOptions().GetCategories()[vecItem->m_value];\r\n\t\tUpdateDescription(*pCategory);\r\n\t} break;\r\n\tcase ShownMenuType::Settings: {\r\n\t\tauto &vecItem = vecDialogItems[value];\r\n\t\toptionDescription[0] = '\\0';\r\n\t\tif (vecItem->m_value < 0)\r\n\t\t\treturn;\r\n\t\tauto *pOption = vecOptions[vecItem->m_value];\r\n\t\tUpdateDescription(*pOption);\r\n\t} break;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nbool ChangeOptionValue(OptionEntryBase *pOption, size_t listIndex)\r\n{\r\n\tif (HasAnyOf(pOption->GetFlags(), OptionEntryFlags::RecreateUI)) {\r\n\t\tendMenu = true;\r\n\t\t// Clean up all UI related Data\r\n\t\tCleanUpSettingsUI();\r\n\t\tUnloadUiGFX();\r\n\t\tFreeItemGFX();\r\n\t\tselectedOption = pOption;\r\n\t}\r\n\r\n\tswitch (pOption->GetType()) {\r\n\tcase OptionEntryType::Boolean: {\r\n\t\tauto *pOptionBoolean = static_cast<OptionEntryBoolean *>(pOption);\r\n\t\tpOptionBoolean->SetValue(!**pOptionBoolean);\r\n\t} break;\r\n\tcase OptionEntryType::List: {\r\n\t\tauto *pOptionList = static_cast<OptionEntryListBase *>(pOption);\r\n\t\tpOptionList->SetActiveListIndex(listIndex);\r\n\t} break;\r\n\tcase OptionEntryType::Key:\r\n\tcase OptionEntryType::PadButton:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (HasAnyOf(pOption->GetFlags(), OptionEntryFlags::RecreateUI)) {\r\n\t\t// Reinitialize UI with changed settings (for example game mode, language or resolution)\r\n\t\tUiInitialize();\r\n\t\tInitItemGFX();\r\n\t\tSetHardwareCursor(CursorInfo::UnknownCursor());\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid ItemSelected(size_t value)\r\n{\r\n\tauto &vecItem = vecDialogItems[value];\r\n\tconst int vecItemValue = vecItem->m_value;\r\n\tif (vecItemValue < 0) {\r\n\t\tauto specialMenuEntry = static_cast<SpecialMenuEntry>(vecItemValue);\r\n\t\tswitch (specialMenuEntry) {\r\n\t\tcase SpecialMenuEntry::None:\r\n\t\t\tbreak;\r\n\t\tcase SpecialMenuEntry::PreviousMenu:\r\n\t\t\tGoBackOneMenuLevel();\r\n\t\t\tbreak;\r\n\t\tcase SpecialMenuEntry::UnbindKey: {\r\n\t\t\tauto *pOptionKey = static_cast<KeymapperOptions::Action *>(selectedOption);\r\n\t\t\tpOptionKey->SetValue(SDLK_UNKNOWN);\r\n\t\t\tvecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase SpecialMenuEntry::BindPadButton:\r\n\t\t\tStartPadEntryTimer();\r\n\t\t\tbreak;\r\n\t\tcase SpecialMenuEntry::UnbindPadButton:\r\n\t\t\tauto *pOptionPad = static_cast<PadmapperOptions::Action *>(selectedOption);\r\n\t\t\tpOptionPad->SetValue(ControllerButton_NONE);\r\n\t\t\tvecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (shownMenu) {\r\n\tcase ShownMenuType::Categories: {\r\n\t\tselectedCategory = GetOptions().GetCategories()[vecItemValue];\r\n\t\tendMenu = true;\r\n\t\tshownMenu = ShownMenuType::Settings;\r\n\t} break;\r\n\tcase ShownMenuType::Settings: {\r\n\t\tauto *pOption = vecOptions[vecItemValue];\r\n\t\tbool updateValueDescription = false;\r\n\t\tif (pOption->GetType() == OptionEntryType::List) {\r\n\t\t\tauto *pOptionList = static_cast<OptionEntryListBase *>(pOption);\r\n\t\t\tif (pOptionList->GetListSize() > 2) {\r\n\t\t\t\tselectedOption = pOption;\r\n\t\t\t\tendMenu = true;\r\n\t\t\t\tshownMenu = ShownMenuType::ListOption;\r\n\t\t\t} else {\r\n\t\t\t\t// If the list contains only two items, we don't show a submenu and instead change the option value instantly\r\n\t\t\t\tsize_t nextIndex = pOptionList->GetActiveListIndex() + 1;\r\n\t\t\t\tif (nextIndex >= pOptionList->GetListSize())\r\n\t\t\t\t\tnextIndex = 0;\r\n\t\t\t\tupdateValueDescription = ChangeOptionValue(pOption, nextIndex);\r\n\t\t\t}\r\n\t\t} else if (pOption->GetType() == OptionEntryType::Key) {\r\n\t\t\tselectedOption = pOption;\r\n\t\t\tendMenu = true;\r\n\t\t\tshownMenu = ShownMenuType::KeyInput;\r\n\t\t} else if (pOption->GetType() == OptionEntryType::PadButton) {\r\n\t\t\tselectedOption = pOption;\r\n\t\t\tendMenu = true;\r\n\t\t\tshownMenu = ShownMenuType::PadInput;\r\n\t\t} else {\r\n\t\t\tupdateValueDescription = ChangeOptionValue(pOption, 0);\r\n\t\t}\r\n\t\tif (updateValueDescription) {\r\n\t\t\tauto args = CreateDrawStringFormatArgForEntry(pOption);\r\n\t\t\tconst bool optionUsesTwoLines = ((value + 1) < vecDialogItems.size() && vecDialogItems[value]->m_value == vecDialogItems[value + 1]->m_value);\r\n\t\t\tif (NeedsTwoLinesToDisplayOption(args) != optionUsesTwoLines) {\r\n\t\t\t\tselectedOption = pOption;\r\n\t\t\t\tendMenu = true;\r\n\t\t\t} else {\r\n\t\t\t\tvecItem->args.clear();\r\n\t\t\t\tfor (auto &arg : args)\r\n\t\t\t\t\tvecItem->args.push_back(arg);\r\n\t\t\t\tif (optionUsesTwoLines) {\r\n\t\t\t\t\tvecDialogItems[value + 1]->m_text = std::string(pOption->GetValueDescription());\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} break;\r\n\tcase ShownMenuType::ListOption: {\r\n\t\tChangeOptionValue(selectedOption, vecItemValue);\r\n\t\tGoBackOneMenuLevel();\r\n\t} break;\r\n\tcase ShownMenuType::KeyInput:\r\n\tcase ShownMenuType::PadInput:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid EscPressed()\r\n{\r\n\tGoBackOneMenuLevel();\r\n}\r\n\r\nvoid FullscreenChanged()\r\n{\r\n\tauto *fullscreenOption = &GetOptions().Graphics.fullscreen;\r\n\r\n\tfor (auto &vecItem : vecDialogItems) {\r\n\t\tconst int vecItemValue = vecItem->m_value;\r\n\t\tif (vecItemValue < 0 || static_cast<size_t>(vecItemValue) >= vecOptions.size())\r\n\t\t\tcontinue;\r\n\r\n\t\tauto *pOption = vecOptions[vecItemValue];\r\n\t\tif (pOption != fullscreenOption)\r\n\t\t\tcontinue;\r\n\r\n\t\tvecItem->args.clear();\r\n\t\tfor (auto &arg : CreateDrawStringFormatArgForEntry(pOption))\r\n\t\t\tvecItem->args.push_back(arg);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid UiSettingsMenu()\r\n{\r\n\tbackToMain = false;\r\n\tshownMenu = ShownMenuType::Categories;\r\n\tselectedCategory = nullptr;\r\n\tselectedOption = nullptr;\r\n\r\n\tdo {\r\n\t\tendMenu = false;\r\n\r\n\t\t// For the settings menu, we use the full height and allow some more width.\r\n\t\tconst int uiWidth = std::clamp<int>(gnScreenWidth, 640, 720);\r\n\t\tconst Rectangle uiRectangle = {\r\n\t\t\t{ (gnScreenWidth - uiWidth) / 2, 0 },\r\n\t\t\t{ uiWidth, gnScreenHeight }\r\n\t\t};\r\n\r\n\t\tUiLoadBlackBackground();\r\n\t\tLoadScrollBar();\r\n\t\tUiAddBackground(&vecDialog);\r\n\t\tUiAddLogo(&vecDialog, uiRectangle.position.y);\r\n\r\n\t\tconst int descriptionLineHeight = IsSmallFontTall() ? 20 : 18;\r\n\t\tconst int descriptionMarginTop = IsSmallFontTall() ? 10 : 16;\r\n\r\n\t\toptionDescription[0] = '\\0';\r\n\r\n\t\tstd::string_view titleText;\r\n\t\tswitch (shownMenu) {\r\n\t\tcase ShownMenuType::Categories:\r\n\t\t\ttitleText = _(\"Settings\");\r\n\t\t\tbreak;\r\n\t\tcase ShownMenuType::Settings:\r\n\t\t\ttitleText = selectedCategory->GetName();\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\ttitleText = selectedOption->GetName();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tvecDialog.push_back(std::make_unique<UiArtText>(titleText.data(), MakeSdlRect(uiRectangle.position.x, uiRectangle.position.y + 161, uiRectangle.size.width, 35), UiFlags::FontSize30 | UiFlags::ColorUiSilver | UiFlags::AlignCenter, 8));\r\n\r\n\t\tsize_t itemToSelect = 0;\r\n\t\tstd::optional<tl::function_ref<bool(SDL_Event &)>> eventHandler;\r\n\r\n\t\tswitch (shownMenu) {\r\n\t\tcase ShownMenuType::Categories: {\r\n\t\t\tsize_t catIndex = 0;\r\n\t\t\tfor (OptionCategoryBase *pCategory : GetOptions().GetCategories()) {\r\n\t\t\t\tfor (OptionEntryBase *pEntry : pCategory->GetEntries()) {\r\n\t\t\t\t\tif (!IsValidEntry(pEntry))\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\tif (selectedCategory == pCategory)\r\n\t\t\t\t\t\titemToSelect = vecDialogItems.size();\r\n\t\t\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(pCategory->GetName(), static_cast<int>(catIndex), UiFlags::ColorUiGold));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcatIndex++;\r\n\t\t\t}\r\n\t\t} break;\r\n\t\tcase ShownMenuType::Settings: {\r\n\t\t\tfor (OptionEntryBase *pEntry : selectedCategory->GetEntries()) {\r\n\t\t\t\tif (!IsValidEntry(pEntry))\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (selectedOption == pEntry)\r\n\t\t\t\t\titemToSelect = vecDialogItems.size();\r\n\t\t\t\tauto formatArgs = CreateDrawStringFormatArgForEntry(pEntry);\r\n\t\t\t\tconst int optionId = static_cast<int>(vecOptions.size());\r\n\t\t\t\tif (NeedsTwoLinesToDisplayOption(formatArgs)) {\r\n\t\t\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string_view(\"{}:\"), formatArgs, optionId, UiFlags::ColorUiGold | UiFlags::NeedsNextElement));\r\n\t\t\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string(pEntry->GetValueDescription()), optionId, UiFlags::ColorUiSilver | UiFlags::ElementDisabled));\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string_view(\"{}: {}\"), formatArgs, optionId, UiFlags::ColorUiGold));\r\n\t\t\t\t}\r\n\t\t\t\tvecOptions.push_back(pEntry);\r\n\t\t\t}\r\n\t\t} break;\r\n\t\tcase ShownMenuType::ListOption: {\r\n\t\t\tauto *pOptionList = static_cast<OptionEntryListBase *>(selectedOption);\r\n\t\t\tfor (size_t i = 0; i < pOptionList->GetListSize(); i++) {\r\n\t\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(pOptionList->GetListDescription(i), static_cast<int>(i), UiFlags::ColorUiGold));\r\n\t\t\t}\r\n\t\t\titemToSelect = pOptionList->GetActiveListIndex();\r\n\t\t\tUpdateDescription(*pOptionList);\r\n\t\t} break;\r\n\t\tcase ShownMenuType::KeyInput: {\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Bound key:\"), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorWhitegold | UiFlags::ElementDisabled));\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string(selectedOption->GetValueDescription()), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorUiGold));\r\n\t\t\tassert(IndexKeyOrPadInput == vecDialogItems.size() - 1);\r\n\t\t\titemToSelect = IndexKeyOrPadInput;\r\n\t\t\teventHandler = [](SDL_Event &event) {\r\n\t\t\t\tif (SelectedItem != IndexKeyOrPadInput)\r\n\t\t\t\t\treturn false;\r\n\t\t\t\tuint32_t key = SDLK_UNKNOWN;\r\n\t\t\t\tswitch (event.type) {\r\n\t\t\t\tcase SDL_EVENT_KEY_DOWN: {\r\n\t\t\t\t\tSDL_Keycode keycode = SDLC_EventKey(event);\r\n\t\t\t\t\tremap_keyboard_key(&keycode);\r\n\t\t\t\t\tkey = static_cast<uint32_t>(keycode);\r\n\t\t\t\t\tif (key >= SDLK_A && key <= SDLK_Z) {\r\n\t\t\t\t\t\tkey -= 'a' - 'A';\r\n\t\t\t\t\t}\r\n\t\t\t\t} break;\r\n\t\t\t\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\t\t\t\t\tswitch (event.button.button) {\r\n\t\t\t\t\tcase SDL_BUTTON_MIDDLE:\r\n\t\t\t\t\tcase SDL_BUTTON_X1:\r\n\t\t\t\t\tcase SDL_BUTTON_X2:\r\n\t\t\t\t\t\tkey = event.button.button | KeymapperMouseButtonMask;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t\t\t\tcase SDL_EVENT_MOUSE_WHEEL:\r\n\t\t\t\t\tif (SDLC_EventWheelIntY(event) > 0) {\r\n\t\t\t\t\t\tkey = MouseScrollUpButton;\r\n\t\t\t\t\t} else if (SDLC_EventWheelIntY(event) < 0) {\r\n\t\t\t\t\t\tkey = MouseScrollDownButton;\r\n\t\t\t\t\t} else if (SDLC_EventWheelIntX(event) > 0) {\r\n\t\t\t\t\t\tkey = MouseScrollLeftButton;\r\n\t\t\t\t\t} else if (SDLC_EventWheelIntX(event) < 0) {\r\n\t\t\t\t\t\tkey = MouseScrollRightButton;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n#endif\r\n\t\t\t\t}\r\n\t\t\t\t// Ignore unknown keys\r\n\t\t\t\tif (key == SDLK_UNKNOWN)\r\n\t\t\t\t\treturn false;\r\n\t\t\t\tauto *pOptionKey = static_cast<KeymapperOptions::Action *>(selectedOption);\r\n\t\t\t\tif (!pOptionKey->SetValue(key))\r\n\t\t\t\t\treturn false;\r\n\t\t\t\tvecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription();\r\n\t\t\t\treturn true;\r\n\t\t\t};\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Press any key to change.\"), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorUiSilver | UiFlags::ElementDisabled));\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string_view {}, static_cast<int>(SpecialMenuEntry::None), UiFlags::ElementDisabled));\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Unbind key\"), static_cast<int>(SpecialMenuEntry::UnbindKey), UiFlags::ColorUiGold));\r\n\t\t\tUpdateDescription(*selectedOption);\r\n\t\t} break;\r\n\t\tcase ShownMenuType::PadInput: {\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Bound button combo:\"), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorWhitegold | UiFlags::ElementDisabled));\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(selectedOption->GetValueDescription(), static_cast<int>(SpecialMenuEntry::BindPadButton), UiFlags::ColorUiGold));\r\n\t\t\tassert(IndexKeyOrPadInput == vecDialogItems.size() - 1);\r\n\t\t\titemToSelect = IndexKeyOrPadInput;\r\n\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string_view(padEntryTimerText), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorUiSilver | UiFlags::ElementDisabled));\r\n\t\t\tassert(IndexPadTimerText == vecDialogItems.size() - 1);\r\n\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string_view {}, static_cast<int>(SpecialMenuEntry::None), UiFlags::ElementDisabled));\r\n\t\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Unbind button combo\"), static_cast<int>(SpecialMenuEntry::UnbindPadButton), UiFlags::ColorUiGold));\r\n\r\n\t\t\tpadEntryStartTime = 0;\r\n\t\t\teventHandler = [](SDL_Event &event) {\r\n\t\t\t\tif (padEntryStartTime == 0)\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\tconst StaticVector<ControllerButtonEvent, 4> ctrlEvents = ToControllerButtonEvents(event);\r\n\t\t\t\tfor (const ControllerButtonEvent ctrlEvent : ctrlEvents) {\r\n\t\t\t\t\tconst bool isGamepadMotion = IsControllerMotion(event);\r\n\t\t\t\t\tDetectInputMethod(event, ctrlEvent);\r\n\t\t\t\t\tif (event.type == SDL_EVENT_KEY_UP && SDLC_EventKey(event) == SDLK_ESCAPE) {\r\n\t\t\t\t\t\tStopPadEntryTimer();\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (isGamepadMotion || IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst bool modifierPressed = padEntryCombo.modifier != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.modifier);\r\n\t\t\t\t\tconst bool buttonPressed = padEntryCombo.button != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.button);\r\n\t\t\t\t\tif (ctrlEvent.up) {\r\n\t\t\t\t\t\t// When the player has released all relevant inputs, assume the binding is finished and stop the timer\r\n\t\t\t\t\t\tif (padEntryCombo.button != ControllerButton_NONE && !modifierPressed && !buttonPressed) {\r\n\t\t\t\t\t\t\tStopPadEntryTimer();\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tauto *pOptionPad = static_cast<PadmapperOptions::Action *>(selectedOption);\r\n\t\t\t\t\tif (!modifierPressed && buttonPressed)\r\n\t\t\t\t\t\tpadEntryCombo.modifier = padEntryCombo.button;\r\n\t\t\t\t\tpadEntryCombo.button = ctrlEvent.button;\r\n\t\t\t\t\tif (pOptionPad->SetValue(padEntryCombo))\r\n\t\t\t\t\t\tvecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription();\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t};\r\n\t\t\tUpdateDescription(*selectedOption);\r\n\t\t} break;\r\n\t\t}\r\n\r\n\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(std::string_view {}, static_cast<int>(SpecialMenuEntry::None), UiFlags::ElementDisabled));\r\n\t\tvecDialogItems.push_back(std::make_unique<UiListItem>(_(\"Previous Menu\"), static_cast<int>(SpecialMenuEntry::PreviousMenu), UiFlags::ColorUiGold));\r\n\r\n\t\tconstexpr int ListItemHeight = 26;\r\n\t\trectList = { uiRectangle.position + Displacement { 50, 204 },\r\n\t\t\tSize { uiRectangle.size.width - 100, std::min<int>(static_cast<int>(vecDialogItems.size()) * ListItemHeight, uiRectangle.size.height - 272) } };\r\n\t\trectDescription = { rectList.position + Displacement { -26, rectList.size.height + descriptionMarginTop },\r\n\t\t\tSize { uiRectangle.size.width - 50, 80 - descriptionMarginTop } };\r\n\t\tvecDialog.push_back(std::make_unique<UiScrollbar>((*ArtScrollBarBackground)[0], (*ArtScrollBarThumb)[0],\r\n\t\t    *ArtScrollBarArrow, MakeSdlRect(rectList.position.x + rectList.size.width + 5, rectList.position.y, 25, rectList.size.height)));\r\n\t\tvecDialog.push_back(std::make_unique<UiArtText>(optionDescription, MakeSdlRect(rectDescription),\r\n\t\t    UiFlags::FontSize12 | UiFlags::ColorUiSilverDark | UiFlags::AlignCenter, 1, descriptionLineHeight));\r\n\t\tvecDialog.push_back(std::make_unique<UiList>(vecDialogItems, rectList.size.height / ListItemHeight,\r\n\t\t    rectList.position.x, rectList.position.y, rectList.size.width, ListItemHeight, UiFlags::FontSize24 | UiFlags::AlignCenter));\r\n\r\n\t\tUiInitList(ItemFocused, ItemSelected, EscPressed, vecDialog, true, FullscreenChanged, nullptr, itemToSelect);\r\n\r\n\t\twhile (!endMenu) {\r\n\t\t\tUiClearScreen();\r\n\t\t\tUpdatePadEntryTimerText();\r\n\t\t\tUiPollAndRender(eventHandler);\r\n\t\t}\r\n\r\n\t\tCleanUpSettingsUI();\r\n\t} while (!backToMain);\r\n\r\n\tSaveOptions();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/settingsmenu.h",
    "content": "#pragma once\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid UiSettingsMenu();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/support_lines.cpp",
    "content": "#include <cstddef>\r\n\r\n#include \"DiabloUI/support_lines.h\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nconst char *const SupportLines[] = {\r\n\t\"\",\r\n\tN_(\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join our community where we talk about things related to Diablo, and the Hellfire expansion.\"),\r\n\t\"\",\r\n\tN_(\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at this address: https://github.com/diasurgical/devilutionX To help us better serve you, please be sure to include the version number, operating system, and the nature of the problem.\"),\r\n\t\"\",\r\n\t\"\",\r\n\tN_(\"Disclaimer:\"),\r\n\tN_(\"\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified the quality or compatibility of DevilutionX. All inquiries regarding DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment or GOG.com.\"),\r\n\t\"\",\r\n\t\"\",\r\n\tN_(\"\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto which are licensed under the SIL Open Font License, as well as Twitmoji which is licensed under CC-BY 4.0. The port also makes use of SDL which is licensed under the zlib-license. See the ReadMe for further details.\"),\r\n\t\"\",\r\n\t\"\",\r\n};\r\n\r\nconst std::size_t SupportLinesSize = sizeof(SupportLines) / sizeof(SupportLines[0]);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/support_lines.h",
    "content": "#include <cstddef>\r\n\r\nnamespace devilution {\r\n\r\nextern const char *const SupportLines[];\r\nextern const std::size_t SupportLinesSize;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/text_input.cpp",
    "content": "#include \"DiabloUI/text_input.hpp\"\r\n\r\n#include <memory>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_clipboard.h>\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"utils/log.hpp\"\r\n#include \"utils/parse_int.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_ptrs.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nbool HandleInputEvent(const SDL_Event &event, TextInputState &state,\r\n    tl::function_ref<bool(std::string_view)> typeFn,\r\n    [[maybe_unused]] tl::function_ref<bool(std::string_view)> assignFn)\r\n{\r\n\tconst auto modState = SDL_GetModState();\r\n\tconst bool isCtrl = (modState & SDL_KMOD_CTRL) != 0;\r\n\tconst bool isAlt = (modState & SDL_KMOD_ALT) != 0;\r\n\tconst bool isShift = (modState & SDL_KMOD_SHIFT) != 0;\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_KEY_DOWN: {\r\n\t\tswitch (SDLC_EventKey(event)) {\r\n#ifndef USE_SDL1\r\n\t\tcase SDLK_A:\r\n\t\t\tif (isCtrl) {\r\n\t\t\t\tstate.setCursorToStart();\r\n\t\t\t\tstate.setSelectCursorToEnd();\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\tcase SDLK_C:\r\n\t\t\tif (isCtrl) {\r\n\t\t\t\tconst std::string selectedText { state.selectedText() };\r\n\t\t\t\tif (SDLC_SetClipboardText(selectedText.c_str())) {\r\n\t\t\t\t\tLogError(\"Failed to set clipboard text: {}\", SDL_GetError());\r\n\t\t\t\t\tSDL_ClearError();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\tcase SDLK_X:\r\n\t\t\tif (isCtrl) {\r\n\t\t\t\tconst std::string selectedText { state.selectedText() };\r\n\t\t\t\tif (SDLC_SetClipboardText(selectedText.c_str())) {\r\n\t\t\t\t\tLogError(\"Failed to set clipboard text: {}\", SDL_GetError());\r\n\t\t\t\t\tSDL_ClearError();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tstate.eraseSelection();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\tcase SDLK_V:\r\n\t\t\tif (isCtrl) {\r\n\t\t\t\tif (SDLC_HasClipboardText()) {\r\n\t\t\t\t\tconst std::unique_ptr<char, SDLFreeDeleter<char>> clipboard { SDL_GetClipboardText() };\r\n\t\t\t\t\tif (clipboard == nullptr) {\r\n\t\t\t\t\t\tLogError(\"Failed to get clipboard text: {}\", SDL_GetError());\r\n\t\t\t\t\t\tSDL_ClearError();\r\n\t\t\t\t\t} else if (*clipboard != '\\0') {\r\n\t\t\t\t\t\ttypeFn(clipboard.get());\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn true;\r\n#endif\r\n\t\tcase SDLK_BACKSPACE:\r\n\t\t\tstate.backspace(/*word=*/isCtrl || isAlt);\r\n\t\t\treturn true;\r\n\t\tcase SDLK_DELETE:\r\n\t\t\tstate.del(/*word=*/isCtrl || isAlt);\r\n\t\t\treturn true;\r\n\t\tcase SDLK_LEFT:\r\n\t\t\tisShift ? state.moveSelectCursorLeft(/*word=*/isCtrl || isAlt) : state.moveCursorLeft(/*word=*/isCtrl || isAlt);\r\n\t\t\treturn true;\r\n\t\tcase SDLK_RIGHT:\r\n\t\t\tisShift ? state.moveSelectCursorRight(/*word=*/isCtrl || isAlt) : state.moveCursorRight(/*word=*/isCtrl || isAlt);\r\n\t\t\treturn true;\r\n\t\tcase SDLK_HOME:\r\n\t\t\tisShift ? state.setSelectCursorToStart() : state.setCursorToStart();\r\n\t\t\treturn true;\r\n\t\tcase SDLK_END:\r\n\t\t\tisShift ? state.setSelectCursorToEnd() : state.setCursorToEnd();\r\n\t\t\treturn true;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n#ifdef USE_SDL1\r\n\t\tif ((event.key.keysym.mod & KMOD_CTRL) == 0 && event.key.keysym.unicode >= ' ') {\r\n\t\t\tstd::string utf8;\r\n\t\t\tAppendUtf8(event.key.keysym.unicode, utf8);\r\n\t\t\ttypeFn(utf8);\r\n\t\t\treturn true;\r\n\t\t}\r\n#else\r\n\t\t// Mark events that will also trigger SDL_TEXTINPUT as handled.\r\n\t\treturn !isCtrl && !isAlt\r\n\t\t    && SDLC_EventKey(event) >= SDLK_SPACE && SDLC_EventKey(event) <= SDLK_Z;\r\n#endif\r\n\t} break;\r\n#ifndef USE_SDL1\r\n\tcase SDL_EVENT_TEXT_INPUT:\r\n#ifdef __vita__\r\n\t\tassignFn(event.text.text);\r\n#else\r\n\t\ttypeFn(event.text.text);\r\n#endif\r\n\t\treturn true;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_TEXT_EDITING:\r\n\tcase SDL_EVENT_TEXT_EDITING_CANDIDATES:\r\n#else\r\n\tcase SDL_TEXTEDITING:\r\n#endif\r\n\t\treturn true;\r\n#endif\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n} // namespace\r\n\r\nbool HandleTextInputEvent(const SDL_Event &event, TextInputState &state)\r\n{\r\n\treturn HandleInputEvent(\r\n\t    event, state, [&](std::string_view str) {\r\n\t\t\t\tstate.type(str);\r\n\t\t\t\treturn true; },\r\n\t    [&](std::string_view str) {\r\n\t\t    state.assign(str);\r\n\t\t    return true;\r\n\t    });\r\n}\r\n\r\n[[nodiscard]] int NumberInputState::value(int defaultValue) const\r\n{\r\n\treturn ParseInt<int>(textInput_.value()).value_or(defaultValue);\r\n}\r\n\r\nstd::string NumberInputState::filterStr(std::string_view str, bool allowMinus)\r\n{\r\n\tstd::string result;\r\n\tif (allowMinus && !str.empty() && str[0] == '-') {\r\n\t\tstr.remove_prefix(1);\r\n\t\tresult += '-';\r\n\t}\r\n\tfor (const char c : str) {\r\n\t\tif (c >= '0' && c <= '9') {\r\n\t\t\tresult += c;\r\n\t\t}\r\n\t}\r\n\treturn result;\r\n}\r\n\r\nvoid NumberInputState::type(std::string_view str)\r\n{\r\n\tconst std::string filtered = filterStr(\r\n\t    str, /*allowMinus=*/min_ < 0 && textInput_.cursorPosition() == 0);\r\n\tif (filtered.empty())\r\n\t\treturn;\r\n\ttextInput_.type(filtered);\r\n\tenforceRange();\r\n}\r\n\r\nvoid NumberInputState::assign(std::string_view str)\r\n{\r\n\tconst std::string filtered = filterStr(str, /*allowMinus=*/min_ < 0);\r\n\tif (filtered.empty()) {\r\n\t\ttextInput_.clear();\r\n\t\treturn;\r\n\t}\r\n\ttextInput_.assign(filtered);\r\n\tenforceRange();\r\n}\r\n\r\nvoid NumberInputState::enforceRange()\r\n{\r\n\tif (textInput_.empty())\r\n\t\treturn;\r\n\tParseIntResult<int> parsed = ParseInt<int>(textInput_.value());\r\n\tif (parsed.has_value()) {\r\n\t\tif (*parsed > max_) {\r\n\t\t\ttextInput_.assign(StrCat(max_));\r\n\t\t} else if (*parsed < min_) {\r\n\t\t\ttextInput_.assign(StrCat(min_));\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool HandleNumberInputEvent(const SDL_Event &event, NumberInputState &state)\r\n{\r\n\treturn HandleInputEvent(\r\n\t    event, state.textInput(), [&](std::string_view str) {\r\n\t\t\t\tstate.type(str);\r\n\t\t\t\treturn true; },\r\n\t    [&](std::string_view str) {\r\n\t\t    state.assign(str);\r\n\t\t    return true;\r\n\t    });\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/text_input.hpp",
    "content": "#pragma once\r\n\r\n#include <algorithm>\r\n#include <cstddef>\r\n#include <cstring>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/** @brief A range of bytes in text. */\r\nstruct TextRange {\r\n\tsize_t begin = 0;\r\n\tsize_t end = 0;\r\n\r\n\t[[nodiscard]] size_t size() const\r\n\t{\r\n\t\treturn end - begin;\r\n\t}\r\n\r\n\t[[nodiscard]] bool empty() const\r\n\t{\r\n\t\treturn begin == end;\r\n\t}\r\n\r\n\tvoid clear()\r\n\t{\r\n\t\tbegin = end = 0;\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief Current state of the cursor and the selection range.\r\n */\r\nstruct TextInputCursorState {\r\n\tsize_t position = 0;\r\n\tTextRange selection;\r\n};\r\n\r\n/**\r\n * @brief Manages state for a single-line text input with a cursor.\r\n *\r\n * The text value and the cursor position are stored externally.\r\n */\r\nclass TextInputState {\r\n\t/**\r\n\t * @brief Manages an unowned fixed size char array.\r\n\t */\r\n\tstruct Buffer {\r\n\t\tBuffer(char *begin, size_t maxLength)\r\n\t\t    : buf_(begin)\r\n\t\t    , maxLength_(maxLength)\r\n\t\t{\r\n\t\t\tstd::string_view str(begin);\r\n\t\t\tstr = TruncateUtf8(str, maxLength);\r\n\t\t\tlen_ = str.size();\r\n\t\t\tbuf_[len_] = '\\0';\r\n\t\t}\r\n\r\n\t\t[[nodiscard]] size_t size() const\r\n\t\t{\r\n\t\t\treturn len_;\r\n\t\t}\r\n\r\n\t\t[[nodiscard]] bool empty() const\r\n\t\t{\r\n\t\t\treturn len_ == 0;\r\n\t\t}\r\n\r\n\t\tBuffer &operator=(std::string_view value)\r\n\t\t{\r\n\t\t\tvalue = TruncateUtf8(value, maxLength_);\r\n\t\t\tCopyUtf8(buf_, value, maxLength_);\r\n\t\t\tlen_ = value.size();\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tvoid insert(size_t pos, std::string_view value)\r\n\t\t{\r\n\t\t\tvalue = truncateForInsertion(value);\r\n\t\t\tstd::memmove(&buf_[pos + value.size()], &buf_[pos], len_ - pos);\r\n\t\t\tstd::memcpy(&buf_[pos], value.data(), value.size());\r\n\t\t\tlen_ += value.size();\r\n\t\t\tbuf_[len_] = '\\0';\r\n\t\t}\r\n\r\n\t\tvoid erase(size_t pos, size_t len)\r\n\t\t{\r\n\t\t\tstd::memmove(&buf_[pos], &buf_[pos + len], len_ - (pos + len));\r\n\t\t\tlen_ -= len;\r\n\t\t\tbuf_[len_] = '\\0';\r\n\t\t}\r\n\r\n\t\tvoid clear()\r\n\t\t{\r\n\t\t\tlen_ = 0;\r\n\t\t\tbuf_[0] = '\\0';\r\n\t\t}\r\n\r\n\t\texplicit operator std::string_view() const\r\n\t\t{\r\n\t\t\treturn { buf_, len_ };\r\n\t\t}\r\n\r\n\tprivate:\r\n\t\t/**\r\n\t\t * @brief Truncates `text` so that it would fit when inserted,\r\n\t\t * respecting UTF-8 code point boundaries.\r\n\t\t */\r\n\t\t[[nodiscard]] std::string_view truncateForInsertion(std::string_view text) const\r\n\t\t{\r\n\t\t\treturn TruncateUtf8(text, maxLength_ - len_);\r\n\t\t}\r\n\r\n\t\tchar *buf_; // unowned\r\n\t\tsize_t maxLength_;\r\n\t\tsize_t len_;\r\n\t};\r\n\r\npublic:\r\n\tstruct Options {\r\n\t\tchar *value;                  // unowned\r\n\t\tTextInputCursorState *cursor; // unowned\r\n\t\tsize_t maxLength = 0;\r\n\t};\r\n\tTextInputState(const Options &options)\r\n\t    : value_(options.value, options.maxLength)\r\n\t    , cursor_(options.cursor)\r\n\t{\r\n\t\tcursor_->position = value_.size();\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view value() const\r\n\t{\r\n\t\treturn std::string_view(value_);\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view selectedText() const\r\n\t{\r\n\t\treturn value().substr(cursor_->selection.begin, cursor_->selection.size());\r\n\t}\r\n\r\n\t[[nodiscard]] bool empty() const\r\n\t{\r\n\t\treturn value_.empty();\r\n\t}\r\n\r\n\t[[nodiscard]] size_t cursorPosition() const\r\n\t{\r\n\t\treturn cursor_->position;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Overwrites the value with the given text and moves cursor to the end.\r\n\t */\r\n\tvoid assign(std::string_view text)\r\n\t{\r\n\t\tvalue_ = text;\r\n\t\tcursor_->position = value_.size();\r\n\t}\r\n\r\n\tvoid clear()\r\n\t{\r\n\t\tvalue_.clear();\r\n\t\tcursor_->position = 0;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Truncate to precisely `length` bytes.\r\n\t */\r\n\tvoid truncate(size_t length)\r\n\t{\r\n\t\tif (length >= value().size())\r\n\t\t\treturn;\r\n\t\tvalue_ = value().substr(0, length);\r\n\t\tcursor_->position = std::min(cursor_->position, value_.size());\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Erases the currently selected text and sets the cursor to selection start.\r\n\t */\r\n\tvoid eraseSelection()\r\n\t{\r\n\t\tvalue_.erase(cursor_->selection.begin, cursor_->selection.size());\r\n\t\tcursor_->position = cursor_->selection.begin;\r\n\t\tcursor_->selection.clear();\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Inserts the text at the current cursor position.\r\n\t */\r\n\tvoid type(std::string_view text)\r\n\t{\r\n\t\tif (!cursor_->selection.empty())\r\n\t\t\teraseSelection();\r\n\t\tconst size_t prevSize = value_.size();\r\n\t\tvalue_.insert(cursor_->position, text);\r\n\t\tcursor_->position += value_.size() - prevSize;\r\n\t}\r\n\r\n\tvoid backspace(bool word)\r\n\t{\r\n\t\tif (cursor_->selection.empty()) {\r\n\t\t\tif (cursor_->position == 0)\r\n\t\t\t\treturn;\r\n\t\t\tcursor_->selection.begin = prevPosition(word);\r\n\t\t\tcursor_->selection.end = cursor_->position;\r\n\t\t}\r\n\t\teraseSelection();\r\n\t}\r\n\r\n\tvoid del(bool word)\r\n\t{\r\n\t\tif (cursor_->selection.empty()) {\r\n\t\t\tif (cursor_->position == value_.size())\r\n\t\t\t\treturn;\r\n\t\t\tcursor_->selection.begin = cursor_->position;\r\n\t\t\tcursor_->selection.end = nextPosition(word);\r\n\t\t}\r\n\t\teraseSelection();\r\n\t}\r\n\r\n\tvoid setCursorToStart()\r\n\t{\r\n\t\tcursor_->position = 0;\r\n\t\tcursor_->selection.clear();\r\n\t}\r\n\r\n\tvoid setSelectCursorToStart()\r\n\t{\r\n\t\tif (cursor_->selection.empty()) {\r\n\t\t\tcursor_->selection.end = cursor_->position;\r\n\t\t} else if (cursor_->selection.end == cursor_->position) {\r\n\t\t\tcursor_->selection.end = cursor_->selection.begin;\r\n\t\t}\r\n\t\tcursor_->selection.begin = cursor_->position = 0;\r\n\t}\r\n\r\n\tvoid setCursorToEnd()\r\n\t{\r\n\t\tcursor_->position = value_.size();\r\n\t\tcursor_->selection.clear();\r\n\t}\r\n\r\n\tvoid setSelectCursorToEnd()\r\n\t{\r\n\t\tif (cursor_->selection.empty()) {\r\n\t\t\tcursor_->selection.begin = cursor_->position;\r\n\t\t} else if (cursor_->selection.begin == cursor_->position) {\r\n\t\t\tcursor_->selection.begin = cursor_->selection.end;\r\n\t\t}\r\n\t\tcursor_->selection.end = cursor_->position = value_.size();\r\n\t}\r\n\r\n\tvoid moveCursorLeft(bool word)\r\n\t{\r\n\t\tcursor_->selection.clear();\r\n\t\tif (cursor_->position == 0)\r\n\t\t\treturn;\r\n\t\tconst size_t newPosition = prevPosition(word);\r\n\t\tcursor_->position = newPosition;\r\n\t}\r\n\r\n\tvoid moveSelectCursorLeft(bool word)\r\n\t{\r\n\t\tif (cursor_->position == 0)\r\n\t\t\treturn;\r\n\t\tconst size_t newPosition = prevPosition(word);\r\n\t\tif (cursor_->selection.empty()) {\r\n\t\t\tcursor_->selection.begin = newPosition;\r\n\t\t\tcursor_->selection.end = cursor_->position;\r\n\t\t} else if (cursor_->selection.end == cursor_->position) {\r\n\t\t\tcursor_->selection.end = newPosition;\r\n\t\t} else {\r\n\t\t\tcursor_->selection.begin = newPosition;\r\n\t\t}\r\n\t\tcursor_->position = newPosition;\r\n\t}\r\n\r\n\tvoid moveCursorRight(bool word)\r\n\t{\r\n\t\tcursor_->selection.clear();\r\n\t\tif (cursor_->position == value_.size())\r\n\t\t\treturn;\r\n\t\tconst size_t newPosition = nextPosition(word);\r\n\t\tcursor_->position = newPosition;\r\n\t}\r\n\r\n\tvoid moveSelectCursorRight(bool word)\r\n\t{\r\n\t\tif (cursor_->position == value_.size())\r\n\t\t\treturn;\r\n\t\tconst size_t newPosition = nextPosition(word);\r\n\t\tif (cursor_->selection.empty()) {\r\n\t\t\tcursor_->selection.begin = cursor_->position;\r\n\t\t\tcursor_->selection.end = newPosition;\r\n\t\t} else if (cursor_->selection.begin == cursor_->position) {\r\n\t\t\tcursor_->selection.begin = newPosition;\r\n\t\t} else {\r\n\t\t\tcursor_->selection.end = newPosition;\r\n\t\t}\r\n\t\tcursor_->position = newPosition;\r\n\t}\r\n\r\nprivate:\r\n\t[[nodiscard]] static bool isWordSeparator(unsigned char c)\r\n\t{\r\n\t\tconst bool isAsciiWordChar = (c >= '0' && c <= '9')\r\n\t\t    || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_';\r\n\t\treturn c <= '\\x7E' && !isAsciiWordChar;\r\n\t}\r\n\r\n\t[[nodiscard]] size_t prevPosition(bool word) const\r\n\t{\r\n\t\tconst std::string_view str = beforeCursor();\r\n\t\tsize_t pos = FindLastUtf8Symbols(str);\r\n\t\tif (!word)\r\n\t\t\treturn pos;\r\n\t\twhile (pos > 0 && isWordSeparator(str[pos])) {\r\n\t\t\tpos = FindLastUtf8Symbols({ str.data(), pos });\r\n\t\t}\r\n\t\twhile (pos > 0) {\r\n\t\t\tconst size_t prevPos = FindLastUtf8Symbols({ str.data(), pos });\r\n\t\t\tif (isWordSeparator(str[prevPos]))\r\n\t\t\t\tbreak;\r\n\t\t\tpos = prevPos;\r\n\t\t}\r\n\t\treturn pos;\r\n\t}\r\n\r\n\t[[nodiscard]] size_t nextPosition(bool word) const\r\n\t{\r\n\t\tconst std::string_view str = afterCursor();\r\n\t\tsize_t pos = Utf8CodePointLen(str.data());\r\n\t\tif (!word)\r\n\t\t\treturn cursor_->position + pos;\r\n\t\twhile (pos < str.size() && isWordSeparator(str[pos])) {\r\n\t\t\tpos += Utf8CodePointLen(str.data() + pos);\r\n\t\t}\r\n\t\twhile (pos < str.size()) {\r\n\t\t\tpos += Utf8CodePointLen(str.data() + pos);\r\n\t\t\tif (isWordSeparator(str[pos]))\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\treturn cursor_->position + pos;\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view beforeCursor() const\r\n\t{\r\n\t\treturn value().substr(0, cursor_->position);\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view afterCursor() const\r\n\t{\r\n\t\treturn value().substr(cursor_->position);\r\n\t}\r\n\r\n\tBuffer value_;\r\n\tTextInputCursorState *cursor_; // unowned\r\n};\r\n\r\n/**\r\n * @brief Manages state for a number input with a cursor.\r\n */\r\nclass NumberInputState {\r\npublic:\r\n\tstruct Options {\r\n\t\tTextInputState::Options textOptions;\r\n\t\tint min;\r\n\t\tint max;\r\n\t};\r\n\tNumberInputState(const Options &options)\r\n\t    : textInput_(options.textOptions)\r\n\t    , min_(options.min)\r\n\t    , max_(options.max)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] bool empty() const\r\n\t{\r\n\t\treturn textInput_.empty();\r\n\t}\r\n\r\n\t[[nodiscard]] int value(int defaultValue = 0) const;\r\n\r\n\t[[nodiscard]] int max() const\r\n\t{\r\n\t\treturn max_;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Inserts the text at the current cursor position.\r\n\t *\r\n\t * Ignores non-numeric characters.\r\n\t */\r\n\tvoid type(std::string_view str);\r\n\r\n\t/**\r\n\t * @brief Sets the text of the input.\r\n\t *\r\n\t * Ignores non-numeric characters.\r\n\t */\r\n\tvoid assign(std::string_view str);\r\n\r\n\tTextInputState &textInput()\r\n\t{\r\n\t\treturn textInput_;\r\n\t}\r\n\r\nprivate:\r\n\tvoid enforceRange();\r\n\tstd::string filterStr(std::string_view str, bool allowMinus);\r\n\r\n\tTextInputState textInput_;\r\n\tint min_;\r\n\tint max_;\r\n};\r\n\r\nbool HandleTextInputEvent(const SDL_Event &event, TextInputState &state);\r\nbool HandleNumberInputEvent(const SDL_Event &event, NumberInputState &state);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/title.cpp",
    "content": "#include <memory>\r\n#include <optional>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"DiabloUI/ui_item.h\"\r\n#include \"controls/input.h\"\r\n#include \"controls/menu_controls.h\"\r\n#include \"discord/discord.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/load_pcx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList DiabloTitleLogo;\r\n\r\nstd::vector<std::unique_ptr<UiItemBase>> vecTitleScreen;\r\n\r\nvoid TitleLoad()\r\n{\r\n\tArtBackgroundWidescreen = LoadOptionalClx(\"ui_art\\\\hf_titlew.clx\");\r\n\tif (ArtBackgroundWidescreen.has_value()) {\r\n\t\tLoadBackgroundArt(\"ui_art\\\\hf_logo1\", 16);\r\n\t} else {\r\n\t\tLoadBackgroundArt(\"ui_art\\\\title\");\r\n\t\tDiabloTitleLogo = LoadPcxSpriteList(\"ui_art\\\\logo\", /*numFrames=*/15, /*transparentColor=*/250);\r\n\t}\r\n}\r\n\r\nvoid TitleFree()\r\n{\r\n\tArtBackground = std::nullopt;\r\n\tArtBackgroundWidescreen = std::nullopt;\r\n\tDiabloTitleLogo = std::nullopt;\r\n\r\n\tvecTitleScreen.clear();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid UiTitleDialog()\r\n{\r\n\tTitleLoad();\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tif (ArtBackgroundWidescreen.has_value()) {\r\n\t\tconst SDL_Rect rect = MakeSdlRect(0, uiPosition.y, 0, 0);\r\n\t\tif (ArtBackgroundWidescreen)\r\n\t\t\tvecTitleScreen.push_back(std::make_unique<UiImageClx>((*ArtBackgroundWidescreen)[0], rect, UiFlags::AlignCenter));\r\n\t\tvecTitleScreen.push_back(std::make_unique<UiImageAnimatedClx>(*ArtBackground, rect, UiFlags::AlignCenter));\r\n\t} else {\r\n\t\tUiAddBackground(&vecTitleScreen);\r\n\r\n\t\tvecTitleScreen.push_back(std::make_unique<UiImageAnimatedClx>(\r\n\t\t    *DiabloTitleLogo, MakeSdlRect(0, uiPosition.y + 182, 0, 0), UiFlags::AlignCenter));\r\n\r\n\t\tconst SDL_Rect rect = MakeSdlRect(uiPosition.x, uiPosition.y + 410, 640, 26);\r\n\t\tvecTitleScreen.push_back(std::make_unique<UiArtText>(_(\"Copyright © 1996-2001 Blizzard Entertainment\").data(), rect, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiSilver));\r\n\t}\r\n\r\n\tbool endMenu = false;\r\n\tconst Uint32 timeOut = SDL_GetTicks() + 7000;\r\n\r\n\tSDL_Event event;\r\n\twhile (!endMenu && SDL_GetTicks() < timeOut) {\r\n\t\tUiRenderItems(vecTitleScreen);\r\n\t\tUiFadeIn();\r\n\r\n\t\tdiscord_manager::UpdateMenu();\r\n\r\n\t\twhile (PollEvent(&event)) {\r\n\t\t\tif (c_any_of(GetMenuActions(event), [](MenuAction menuAction) { return menuAction != MenuAction_NONE; })) {\r\n\t\t\t\tendMenu = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tswitch (event.type) {\r\n\t\t\tcase SDL_EVENT_KEY_DOWN:\r\n\t\t\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\t\t\tendMenu = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tUiHandleEvents(&event);\r\n\t\t}\r\n\t}\r\n\r\n\tTitleFree();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/ui_flags.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class UiFlags : uint32_t {\r\n\t// clang-format off\r\n\tNone               = 0,\r\n\r\n\tFontSize12         = 1 << 0,\r\n\tFontSize24         = 1 << 1,\r\n\tFontSize30         = 1 << 2,\r\n\tFontSize42         = 1 << 3,\r\n\tFontSize46         = 1 << 4,\r\n\tFontSizeDialog     = 1 << 5,\r\n\r\n\tColorUiGold        = 1 << 6,\r\n\tColorUiSilver      = 1 << 7,\r\n\tColorUiGoldDark    = 1 << 8,\r\n\tColorUiSilverDark  = 1 << 9,\r\n\tColorDialogWhite   = 1 << 10,\r\n\tColorDialogYellow  = 1 << 11,\r\n\tColorDialogRed     = 1 << 12,\r\n\tColorYellow        = 1 << 13,\r\n\tColorGold          = 1 << 14,\r\n\tColorBlack         = 1 << 15,\r\n\tColorWhite         = 1 << 16,\r\n\tColorWhitegold     = 1 << 17,\r\n\tColorRed           = 1 << 18,\r\n\tColorBlue          = 1 << 19,\r\n\tColorOrange        = 1 << 20,\r\n\tColorButtonface    = 1 << 21,\r\n\tColorButtonpushed  = 1 << 22,\r\n\r\n\tAlignCenter        = 1 << 23,\r\n\tAlignRight         = 1 << 24,\r\n\tVerticalCenter     = 1 << 25,\r\n\r\n\tKerningFitSpacing  = 1 << 26,\r\n\r\n\tElementDisabled    = 1 << 27,\r\n\tElementHidden      = 1 << 28,\r\n\r\n\tPentaCursor        = 1 << 29,\r\n\tOutlined           = 1 << 30,\r\n\r\n\t/** @brief Ensures that the if current element is active that the next element is also visible. */\r\n\tNeedsNextElement   = 1U << 31U,\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(UiFlags);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/DiabloUI/ui_item.h",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <string>\r\n#include <vector>\r\n\r\n#include \"DiabloUI/text_input.hpp\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/string_or_view.hpp\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class UiType : uint8_t {\r\n\tText,\r\n\tArtText,\r\n\tArtTextButton,\r\n\tImageClx,\r\n\tImageAnimatedClx,\r\n\tButton,\r\n\tList,\r\n\tScrollbar,\r\n\tEdit,\r\n};\r\n\r\nclass UiItemBase {\r\npublic:\r\n\tvirtual ~UiItemBase() = default;\r\n\r\n\t[[nodiscard]] UiType GetType() const\r\n\t{\r\n\t\treturn type_;\r\n\t}\r\n\r\n\t[[nodiscard]] bool IsType(UiType testType) const\r\n\t{\r\n\t\treturn type_ == testType;\r\n\t}\r\n\r\n\t[[nodiscard]] UiFlags GetFlags() const\r\n\t{\r\n\t\treturn uiFlags_;\r\n\t}\r\n\r\n\t[[nodiscard]] bool IsHidden() const\r\n\t{\r\n\t\treturn HasAnyOf(uiFlags_, UiFlags::ElementHidden);\r\n\t}\r\n\r\n\t[[nodiscard]] bool IsNotInteractive() const\r\n\t{\r\n\t\treturn HasAnyOf(uiFlags_, UiFlags::ElementHidden | UiFlags::ElementDisabled);\r\n\t}\r\n\r\n\tvoid Hide()\r\n\t{\r\n\t\tuiFlags_ |= UiFlags::ElementHidden;\r\n\t}\r\n\r\n\tvoid Show()\r\n\t{\r\n\t\tuiFlags_ &= ~UiFlags::ElementHidden;\r\n\t}\r\n\r\nprotected:\r\n\tUiItemBase(UiType type, SDL_Rect rect, UiFlags flags)\r\n\t    : type_(type)\r\n\t    , m_rect(rect)\r\n\t    , uiFlags_(flags)\r\n\t{\r\n\t}\r\n\r\n\tvoid SetFlags(UiFlags flags)\r\n\t{\r\n\t\tuiFlags_ = flags;\r\n\t}\r\n\r\nprivate:\r\n\tUiType type_;\r\n\r\npublic:\r\n\tSDL_Rect m_rect;\r\n\r\nprivate:\r\n\tUiFlags uiFlags_;\r\n};\r\n\r\n//=============================================================================\r\nclass UiImageClx : public UiItemBase {\r\npublic:\r\n\tUiImageClx(ClxSprite sprite, SDL_Rect rect, UiFlags flags = UiFlags::None)\r\n\t    : UiItemBase(UiType::ImageClx, rect, flags)\r\n\t    , sprite_(sprite)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] bool isCentered() const\r\n\t{\r\n\t\treturn HasAnyOf(GetFlags(), UiFlags::AlignCenter);\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSprite sprite() const\r\n\t{\r\n\t\treturn sprite_;\r\n\t}\r\n\r\n\tvoid setSprite(ClxSprite sprite)\r\n\t{\r\n\t\tsprite_ = sprite;\r\n\t}\r\n\r\nprivate:\r\n\tClxSprite sprite_;\r\n};\r\n\r\n//=============================================================================\r\nclass UiImageAnimatedClx : public UiItemBase {\r\npublic:\r\n\tUiImageAnimatedClx(ClxSpriteList list, SDL_Rect rect, UiFlags flags = UiFlags::None)\r\n\t    : UiItemBase(UiType::ImageAnimatedClx, rect, flags)\r\n\t    , list_(list)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] bool isCentered() const\r\n\t{\r\n\t\treturn HasAnyOf(GetFlags(), UiFlags::AlignCenter);\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSprite sprite(uint16_t frame) const\r\n\t{\r\n\t\treturn list_[frame];\r\n\t}\r\n\r\n\t[[nodiscard]] uint16_t numFrames() const\r\n\t{\r\n\t\treturn list_.numSprites();\r\n\t}\r\n\r\nprivate:\r\n\tClxSpriteList list_;\r\n};\r\n\r\n//=============================================================================\r\n\r\nclass UiArtText : public UiItemBase {\r\npublic:\r\n\t/**\r\n\t * @brief Constructs a UI element containing a (presumed to be) static line of text\r\n\t * @param text Pointer to the first character of a c-string\r\n\t * @param rect screen region defining the area to draw the text\r\n\t * @param flags UiFlags controlling color/alignment/size\r\n\t * @param spacing Spacing between characters\r\n\t * @param lineHeight Vertical distance between text lines\r\n\t */\r\n\tUiArtText(const char *text, SDL_Rect rect, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1)\r\n\t    : UiItemBase(UiType::ArtText, rect, flags)\r\n\t    , text_(text)\r\n\t    , spacing_(spacing)\r\n\t    , lineHeight_(lineHeight)\r\n\t{\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Constructs a UI element containing a line of text that may change between frames\r\n\t * @param ptext Pointer to a c-string (pointer to a pointer to the first character)\r\n\t * @param rect screen region defining the area to draw the text\r\n\t * @param flags UiFlags controlling color/alignment/size\r\n\t * @param spacing Spacing between characters\r\n\t * @param lineHeight Vertical distance between text lines\r\n\t */\r\n\tUiArtText(const char **ptext, SDL_Rect rect, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1)\r\n\t    : UiItemBase(UiType::ArtText, rect, flags)\r\n\t    , textPointer_(ptext)\r\n\t    , spacing_(spacing)\r\n\t    , lineHeight_(lineHeight)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view GetText() const\r\n\t{\r\n\t\tif (text_ != nullptr)\r\n\t\t\treturn text_;\r\n\t\treturn *textPointer_;\r\n\t}\r\n\r\n\t[[nodiscard]] int GetSpacing() const\r\n\t{\r\n\t\treturn spacing_;\r\n\t}\r\n\r\n\t[[nodiscard]] int GetLineHeight() const\r\n\t{\r\n\t\treturn lineHeight_;\r\n\t}\r\n\r\nprivate:\r\n\tconst char *text_ = nullptr;\r\n\tconst char **textPointer_ = nullptr;\r\n\tint spacing_;\r\n\tint lineHeight_;\r\n};\r\n\r\n//=============================================================================\r\n\r\nclass UiScrollbar : public UiItemBase {\r\npublic:\r\n\tUiScrollbar(ClxSprite bg, ClxSprite thumb, ClxSpriteList arrow, SDL_Rect rect, UiFlags flags = UiFlags::None)\r\n\t    : UiItemBase(UiType::Scrollbar, rect, flags)\r\n\t    , m_bg(bg)\r\n\t    , m_thumb(thumb)\r\n\t    , m_arrow(arrow)\r\n\t{\r\n\t}\r\n\r\n\t// private:\r\n\tClxSprite m_bg;\r\n\tClxSprite m_thumb;\r\n\tClxSpriteList m_arrow;\r\n};\r\n\r\n//=============================================================================\r\n\r\nclass UiArtTextButton : public UiItemBase {\r\npublic:\r\n\tusing Callback = void (*)();\r\n\r\n\tUiArtTextButton(std::string_view text, Callback action, SDL_Rect rect, UiFlags flags = UiFlags::None)\r\n\t    : UiItemBase(UiType::ArtTextButton, rect, flags)\r\n\t    , text_(text)\r\n\t    , action_(action)\r\n\t{\r\n\t}\r\n\r\n\tvoid SetFlags(UiFlags flags)\r\n\t{\r\n\t\tUiItemBase::SetFlags(flags);\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view GetText() const\r\n\t{\r\n\t\treturn text_;\r\n\t}\r\n\r\n\tvoid Activate() const\r\n\t{\r\n\t\taction_();\r\n\t}\r\n\r\nprivate:\r\n\tstd::string_view text_;\r\n\tCallback action_;\r\n};\r\n\r\n//=============================================================================\r\n\r\nclass UiEdit : public UiItemBase {\r\npublic:\r\n\tUiEdit(std::string_view hint, char *value, std::size_t maxLength, bool allowEmpty, SDL_Rect rect, UiFlags flags = UiFlags::None)\r\n\t    : UiItemBase(UiType::Edit, rect, flags)\r\n\t    , m_hint(hint)\r\n\t    , m_value(value)\r\n\t    , m_max_length(maxLength)\r\n\t    , m_allowEmpty(allowEmpty)\r\n\t{\r\n\t}\r\n\r\n\t// private:\r\n\tstd::string_view m_hint;\r\n\tchar *m_value;\r\n\tstd::size_t m_max_length;\r\n\tTextInputCursorState m_cursor;\r\n\tbool m_allowEmpty;\r\n};\r\n\r\n//=============================================================================\r\n\r\n// Plain text\r\n\r\nclass UiText : public UiItemBase {\r\npublic:\r\n\tUiText(std::string_view text, SDL_Rect rect, UiFlags flags = UiFlags::ColorDialogWhite)\r\n\t    : UiItemBase(UiType::Text, rect, flags)\r\n\t    , text_(text)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view GetText() const\r\n\t{\r\n\t\treturn text_;\r\n\t}\r\n\r\nprivate:\r\n\tstd::string_view text_;\r\n};\r\n\r\n//=============================================================================\r\n\r\n// A button (uses Diablo sprites)\r\n\r\nclass UiButton : public UiItemBase {\r\npublic:\r\n\tusing Callback = void (*)();\r\n\r\n\tUiButton(std::string_view text, Callback action, SDL_Rect rect, UiFlags flags = UiFlags::None)\r\n\t    : UiItemBase(UiType::Button, rect, flags)\r\n\t    , text_(text)\r\n\t    , action_(action)\r\n\t    , pressed_(false)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view GetText() const\r\n\t{\r\n\t\treturn text_;\r\n\t}\r\n\r\n\tvoid Activate() const\r\n\t{\r\n\t\taction_();\r\n\t}\r\n\r\n\t[[nodiscard]] bool IsPressed() const\r\n\t{\r\n\t\treturn pressed_;\r\n\t}\r\n\r\n\tvoid Press()\r\n\t{\r\n\t\tpressed_ = true;\r\n\t}\r\n\r\n\tvoid Release()\r\n\t{\r\n\t\tpressed_ = false;\r\n\t}\r\n\r\nprivate:\r\n\tstd::string_view text_;\r\n\tCallback action_;\r\n\r\n\t// State\r\n\tbool pressed_;\r\n};\r\n\r\n//=============================================================================\r\n\r\nclass UiListItem {\r\npublic:\r\n\tUiListItem(StringOrView &&text = {}, int value = 0, UiFlags uiFlags = UiFlags::None)\r\n\t    : m_text(std::move(text))\r\n\t    , m_value(value)\r\n\t    , uiFlags(uiFlags)\r\n\t{\r\n\t}\r\n\r\n\tUiListItem(StringOrView &&text, std::vector<DrawStringFormatArg> &args, int value = 0, UiFlags uiFlags = UiFlags::None)\r\n\t    : m_text(std::move(text))\r\n\t    , args(args)\r\n\t    , m_value(value)\r\n\t    , uiFlags(uiFlags)\r\n\t{\r\n\t}\r\n\r\n\t// private:\r\n\tStringOrView m_text;\r\n\tstd::vector<DrawStringFormatArg> args;\r\n\tint m_value;\r\n\tUiFlags uiFlags;\r\n};\r\n\r\nclass UiList : public UiItemBase {\r\npublic:\r\n\tusing vUiListItem = std::vector<std::unique_ptr<UiListItem>>;\r\n\r\n\tUiList(const vUiListItem &vItems, size_t viewportMaxSize, Sint16 x, Sint16 y, Uint16 item_width, Uint16 item_height, UiFlags flags = UiFlags::None, int spacing = 1)\r\n\t    : UiList(PrivateConstructor {}, vItems, std::min<size_t>(viewportMaxSize, vItems.size()), x, y, item_width, item_height, flags, spacing)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] SDL_Rect itemRect(int i) const\r\n\t{\r\n\t\tSDL_Rect tmp;\r\n\t\ttmp.x = m_x;\r\n\t\ttmp.y = m_y + m_height * i;\r\n\t\ttmp.w = m_width;\r\n\t\ttmp.h = m_height;\r\n\r\n\t\treturn tmp;\r\n\t}\r\n\r\n\t[[nodiscard]] size_t indexAt(Sint16 y) const\r\n\t{\r\n\t\tASSERT(y >= m_rect.y);\r\n\t\tconst size_t index = (y - m_rect.y) / m_height;\r\n\t\tASSERT(index < m_vecItems.size());\r\n\t\treturn index;\r\n\t}\r\n\r\n\t[[nodiscard]] UiListItem *GetItem(std::size_t i) const\r\n\t{\r\n\t\treturn m_vecItems[i];\r\n\t}\r\n\r\n\t[[nodiscard]] int GetSpacing() const\r\n\t{\r\n\t\treturn spacing_;\r\n\t}\r\n\r\n\t[[nodiscard]] bool IsPressed(size_t index) const\r\n\t{\r\n\t\treturn pressed_item_index_ == index;\r\n\t}\r\n\r\n\tvoid Press(size_t index)\r\n\t{\r\n\t\tpressed_item_index_ = index;\r\n\t}\r\n\r\n\tvoid Release()\r\n\t{\r\n\t\tpressed_item_index_ = -1;\r\n\t}\r\n\r\n\t// private:\r\n\tsize_t viewportSize;\r\n\tSint16 m_x, m_y;\r\n\tUint16 m_width, m_height;\r\n\tstd::vector<UiListItem *> m_vecItems;\r\n\r\nprivate:\r\n\tstruct PrivateConstructor final {\r\n\t};\r\n\r\n\tUiList(PrivateConstructor tag, const vUiListItem &vItems, size_t viewportSize, Sint16 x, Sint16 y, Uint16 item_width, Uint16 item_height, UiFlags flags, int spacing)\r\n\t    : UiItemBase(UiType::List, { x, y, item_width, static_cast<Uint16>(item_height * viewportSize) }, flags)\r\n\t    , viewportSize(viewportSize)\r\n\t    , m_x(x)\r\n\t    , m_y(y)\r\n\t    , m_width(item_width)\r\n\t    , m_height(item_height)\r\n\t    , spacing_(spacing)\r\n\t{\r\n\t\tfor (const auto &item : vItems)\r\n\t\t\tm_vecItems.push_back(item.get());\r\n\r\n\t\tpressed_item_index_ = -1;\r\n\t}\r\n\r\n\tint spacing_;\r\n\r\n\t// State\r\n\tsize_t pressed_item_index_;\r\n};\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/appfat.cpp",
    "content": "/**\r\n * @file appfat.cpp\r\n *\r\n * Implementation of error dialogs.\r\n */\r\n\r\n#include <config.h>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_thread.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#include \"utils/sdl_compat.h\"\r\n#endif\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"diablo.h\"\r\n#include \"dvlnet/leaveinfo.hpp\"\r\n#include \"multi.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_thread.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n/** Set to true when a fatal error is encountered and the application should shut down. */\r\nbool Terminating = false;\r\n\r\n/** Thread id of the last callee to FreeDlg(). */\r\nSDL_ThreadID CleanupThreadId;\r\n\r\n/**\r\n * @brief Cleans up after a fatal application error.\r\n */\r\nvoid FreeDlg()\r\n{\r\n\tif (Terminating && CleanupThreadId != this_sdl_thread::get_id())\r\n\t\tSDL_Delay(20000);\r\n\r\n\tTerminating = true;\r\n\tCleanupThreadId = this_sdl_thread::get_id();\r\n\r\n\tif (gbIsMultiplayer) {\r\n\t\tif (SNetLeaveGame(leaveinfo_t::LEAVE_EXIT))\r\n\t\t\tSDL_Delay(2000);\r\n\t}\r\n\r\n\tSNetDestroy();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DisplayFatalErrorAndExit(std::string_view title, std::string_view body)\r\n{\r\n\tFreeDlg();\r\n\tUiErrorOkDialog(title, body);\r\n\tdiablo_quit(1);\r\n}\r\n\r\nvoid app_fatal(std::string_view str)\r\n{\r\n\tDisplayFatalErrorAndExit(_(\"Error\"), str);\r\n}\r\n\r\n#ifdef _DEBUG\r\nvoid assert_fail(int nLineNo, const char *pszFile, const char *pszFail)\r\n{\r\n\tapp_fatal(StrCat(\"assertion failed (\", pszFile, \":\", nLineNo, \")\\n\", pszFail));\r\n}\r\n#endif\r\n\r\nvoid ErrDlg(const char *title, std::string_view error, std::string_view logFilePath, int logLineNr)\r\n{\r\n\tDisplayFatalErrorAndExit(\r\n\t    title,\r\n\t    fmt::format(fmt::runtime(_(/* TRANSLATORS: Error message that displays relevant information for bug report */ \"{:s}\\n\\nThe error occurred at: {:s} line {:d}\")),\r\n\t        error, logFilePath, logLineNr));\r\n}\r\n\r\nvoid InsertCDDlg(std::string_view archiveName)\r\n{\r\n\tDisplayFatalErrorAndExit(_(\"Data File Error\"),\r\n\t    fmt::format(fmt::runtime(_(\"Unable to open main data archive ({:s}).\\n\"\r\n\t                               \"\\n\"\r\n\t                               \"Make sure that it is in the game folder.\")),\r\n\t        archiveName));\r\n}\r\n\r\nvoid DirErrorDlg(std::string_view error)\r\n{\r\n\tDisplayFatalErrorAndExit(\r\n\t    _(\"Read-Only Directory Error\"),\r\n\t    fmt::format(fmt::runtime(_(/* TRANSLATORS: Error when Program is not allowed to write data */ \"Unable to write to location:\\n{:s}\")),\r\n\t        error));\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/appfat.h",
    "content": "/**\r\n * @file appfat.h\r\n *\r\n * Interface of error dialogs.\r\n */\r\n#pragma once\r\n\r\n#include <string_view>\r\n\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\n#define ErrSdl() ErrDlg(\"SDL Error\", SDL_GetError(), __FILE__, __LINE__)\r\n\r\n#undef assert\r\n\r\n#ifndef _DEBUG\r\n#define assert(exp)\r\n#else\r\n#define assert(exp) (void)((exp) || (assert_fail(__LINE__, __FILE__, #exp), 0))\r\n#endif\r\n\r\n/**\r\n * @brief Terminates the game and displays an error message box.\r\n * @param str Message box title.\r\n * @param str Error message.\r\n */\r\n[[noreturn]] void DisplayFatalErrorAndExit(std::string_view title, std::string_view body);\r\n\r\n/**\r\n * @brief Terminates the game and displays an error message box.\r\n * @param str Error message.\r\n */\r\n[[noreturn]] void app_fatal(std::string_view str);\r\n\r\n#ifdef _DEBUG\r\n/**\r\n * @brief Show an error and exit the application.\r\n * @param nLineNo The line number of the assertion\r\n * @param pszFile File name where the assertion is located\r\n * @param pszFail Fail message\r\n */\r\n[[noreturn]] void assert_fail(int nLineNo, const char *pszFile, const char *pszFail);\r\n#endif\r\n/**\r\n * @brief Terminates the game and displays an error dialog box based on the given dialog_id.\r\n */\r\n[[noreturn]] void ErrDlg(const char *title, std::string_view error, std::string_view logFilePath, int logLineNr);\r\n\r\n/**\r\n * @brief Terminates the game with an insert CD error dialog.\r\n */\r\n[[noreturn]] void InsertCDDlg(std::string_view archiveName);\r\n\r\n/**\r\n * @brief Terminates the game with a read-only directory error dialog.\r\n */\r\n[[noreturn]] void DirErrorDlg(std::string_view error);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/automap.cpp",
    "content": "/**\r\n * @file automap.cpp\r\n *\r\n * Implementation of the in-game map overlay.\r\n */\r\n#include \"automap.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/render/automap_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"options.h\"\r\n#include \"player.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#include \"lighting.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\nPoint Automap;\r\n\r\nenum MapColors : uint8_t {\r\n\t/** color used to draw the player's arrow */\r\n\tMapColorsPlayer1 = (PAL8_ORANGE + 1),\r\n\tMapColorsPlayer2 = (PAL8_YELLOW + 1),\r\n\tMapColorsPlayer3 = (PAL8_RED + 1),\r\n\tMapColorsPlayer4 = (PAL8_BLUE + 1),\r\n\t/** color for bright map lines (doors, stairs etc.) */\r\n\tMapColorsBright = PAL8_YELLOW,\r\n\t/** color for dim map lines/dots */\r\n\tMapColorsDim = (PAL16_YELLOW + 8),\r\n\t/** color for items on automap */\r\n\tMapColorsItem = (PAL8_BLUE + 1),\r\n\t/** color for activated pentragram on automap */\r\n\tMapColorsPentagramOpen = (PAL8_RED + 2),\r\n\t/** color for cave lava on automap */\r\n\tMapColorsLava = (PAL8_ORANGE + 2),\r\n\t/** color for cave water on automap */\r\n\tMapColorsWater = (PAL8_BLUE + 2),\r\n\t/** color for hive acid on automap */\r\n\tMapColorsAcid = (PAL8_YELLOW + 4),\r\n};\r\n\r\nstruct AutomapTile {\r\n\t/** The general shape of the tile */\r\n\tenum class Types : uint8_t {\r\n\t\tNone,\r\n\t\tDiamond,\r\n\t\tVertical,\r\n\t\tHorizontal,\r\n\t\tCross,\r\n\t\tFenceVertical,\r\n\t\tFenceHorizontal,\r\n\t\tCorner,\r\n\t\tCaveHorizontalCross,\r\n\t\tCaveVerticalCross,\r\n\t\tCaveHorizontal,\r\n\t\tCaveVertical,\r\n\t\tCaveCross,\r\n\t\tBridge,\r\n\t\tRiver,\r\n\t\tRiverCornerEast,\r\n\t\tRiverCornerNorth,\r\n\t\tRiverCornerSouth,\r\n\t\tRiverCornerWest,\r\n\t\tRiverForkIn,\r\n\t\tRiverForkOut,\r\n\t\tRiverLeftIn,\r\n\t\tRiverLeftOut,\r\n\t\tRiverRightIn,\r\n\t\tRiverRightOut,\r\n\t\tCaveHorizontalWoodCross,\r\n\t\tCaveVerticalWoodCross,\r\n\t\tCaveLeftCorner,\r\n\t\tCaveRightCorner,\r\n\t\tCaveBottomCorner,\r\n\t\tCaveHorizontalWood,\r\n\t\tCaveVerticalWood,\r\n\t\tCaveWoodCross,\r\n\t\tCaveRightWoodCross,\r\n\t\tCaveLeftWoodCross,\r\n\t\tHorizontalLavaThin,\r\n\t\tVerticalLavaThin,\r\n\t\tBendSouthLavaThin,\r\n\t\tBendWestLavaThin,\r\n\t\tBendEastLavaThin,\r\n\t\tBendNorthLavaThin,\r\n\t\tVerticalWallLava,\r\n\t\tHorizontalWallLava,\r\n\t\tSELava,\r\n\t\tSWLava,\r\n\t\tNELava,\r\n\t\tNWLava,\r\n\t\tSLava,\r\n\t\tWLava,\r\n\t\tELava,\r\n\t\tNLava,\r\n\t\tLava,\r\n\t\tCaveHorizontalWallLava,\r\n\t\tCaveVerticalWallLava,\r\n\t\tHorizontalBridgeLava,\r\n\t\tVerticalBridgeLava,\r\n\t\tVerticalDiamond,\r\n\t\tHorizontalDiamond,\r\n\t\tPentagramClosed,\r\n\t\tPentagramOpen,\r\n\t};\r\n\r\n\tTypes type;\r\n\r\n\t/** Additional details about the given tile */\r\n\tenum class Flags : uint8_t {\r\n\t\t// clang-format off\r\n\t\tVerticalDoor      = 1 << 0,\r\n\t\tHorizontalDoor    = 1 << 1,\r\n\t\tVerticalArch      = 1 << 2,\r\n\t\tHorizontalArch    = 1 << 3,\r\n\t\tVerticalGrate     = 1 << 4,\r\n\t\tHorizontalGrate   = 1 << 5,\r\n\t\tVerticalPassage   = VerticalDoor | VerticalArch | VerticalGrate,\r\n\t\tHorizontalPassage = HorizontalDoor | HorizontalArch | HorizontalGrate,\r\n\t\tDirt              = 1 << 6,\r\n\t\tStairs            = 1 << 7,\r\n\t\t// clang-format on\r\n\t};\r\n\r\n\tFlags flags = {};\r\n\r\n\t[[nodiscard]] DVL_ALWAYS_INLINE constexpr bool hasFlag(Flags test) const\r\n\t{\r\n\t\treturn (static_cast<uint8_t>(flags) & static_cast<uint8_t>(test)) != 0;\r\n\t}\r\n\r\n\ttemplate <typename... Args>\r\n\t[[nodiscard]] DVL_ALWAYS_INLINE constexpr bool hasAnyFlag(Flags flag, Args... testFlags)\r\n\t{\r\n\t\treturn (static_cast<uint8_t>(this->flags)\r\n\t\t           & (static_cast<uint8_t>(flag) | ... | static_cast<uint8_t>(testFlags)))\r\n\t\t    != 0;\r\n\t}\r\n};\r\n\r\n/**\r\n * Maps from tile_id to automap type.\r\n */\r\nstd::array<AutomapTile, 256> AutomapTypeTiles;\r\n\r\n/**\r\n * @brief Draw a diamond on top tile.\r\n */\r\nvoid DrawDiamond(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tDrawMapLineNE(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::FullTile), color);\r\n\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::FullTile), color);\r\n\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileUp), AmLine(AmLineLength::FullTile), color);\r\n\tDrawMapLineNE(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::None), AmLine(AmLineLength::FullTile), color);\r\n}\r\n\r\n/**\r\n * @brief Draws a bright diamond and a line, orientation depending on the tileset.\r\n */\r\nvoid DrawMapVerticalDoor(const Surface &out, Point center, AutomapTile neTile, uint8_t colorBright, uint8_t colorDim)\r\n{\r\n\tAmWidthOffset lWidthOffset;\r\n\tAmHeightOffset lHeightOffset;\r\n\tAmWidthOffset dWidthOffset;\r\n\tAmHeightOffset dHeightOffset;\r\n\tAmLineLength length;\r\n\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_CATHEDRAL:\r\n\tcase DTYPE_CRYPT:\r\n\t\tlWidthOffset = AmWidthOffset::QuarterTileLeft;\r\n\t\tlHeightOffset = AmHeightOffset::QuarterTileUp;\r\n\r\n\t\tdWidthOffset = AmWidthOffset::HalfTileLeft;\r\n\t\tdHeightOffset = AmHeightOffset::HalfTileDown;\r\n\r\n\t\tlength = AmLineLength::HalfTile;\r\n\t\tbreak;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\tlWidthOffset = AmWidthOffset::ThreeQuartersTileLeft;\r\n\t\tlHeightOffset = AmHeightOffset::QuarterTileDown;\r\n\r\n\t\tdWidthOffset = AmWidthOffset::None;\r\n\t\tdHeightOffset = AmHeightOffset::None;\r\n\r\n\t\tlength = AmLineLength::FullTile;\r\n\t\tbreak;\r\n\tcase DTYPE_CAVES:\r\n\t\tlWidthOffset = AmWidthOffset::QuarterTileLeft;\r\n\t\tlHeightOffset = AmHeightOffset::ThreeQuartersTileDown;\r\n\r\n\t\tdWidthOffset = AmWidthOffset::HalfTileRight;\r\n\t\tdHeightOffset = AmHeightOffset::HalfTileDown;\r\n\r\n\t\tlength = AmLineLength::FullTile;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"Invalid leveltype\");\r\n\t}\r\n\tif (!(neTile.hasFlag(AutomapTile::Flags::VerticalPassage) && leveltype == DTYPE_CATHEDRAL))\r\n\t\tDrawMapLineNE(out, center + AmOffset(lWidthOffset, lHeightOffset), AmLine(length), colorDim);\r\n\tDrawDiamond(out, center + AmOffset(dWidthOffset, dHeightOffset), colorBright);\r\n}\r\n\r\n/**\r\n * @brief Draws a bright diamond and a line, orientation depending on the tileset.\r\n */\r\nvoid DrawMapHorizontalDoor(const Surface &out, Point center, AutomapTile nwTile, uint8_t colorBright, uint8_t colorDim)\r\n{\r\n\tAmWidthOffset lWidthOffset;\r\n\tAmHeightOffset lHeightOffset;\r\n\tAmWidthOffset dWidthOffset;\r\n\tAmHeightOffset dHeightOffset;\r\n\tAmLineLength length;\r\n\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_CATHEDRAL:\r\n\tcase DTYPE_CRYPT:\r\n\t\tlWidthOffset = AmWidthOffset::None;\r\n\t\tlHeightOffset = AmHeightOffset::HalfTileUp;\r\n\r\n\t\tdWidthOffset = AmWidthOffset::HalfTileRight;\r\n\t\tdHeightOffset = AmHeightOffset::HalfTileDown;\r\n\r\n\t\tlength = AmLineLength::HalfTile;\r\n\t\tbreak;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\tlWidthOffset = AmWidthOffset::QuarterTileRight;\r\n\t\tlHeightOffset = AmHeightOffset::QuarterTileUp;\r\n\r\n\t\tdWidthOffset = AmWidthOffset::None;\r\n\t\tdHeightOffset = AmHeightOffset::None;\r\n\r\n\t\tlength = AmLineLength::FullTile;\r\n\t\tbreak;\r\n\tcase DTYPE_CAVES:\r\n\t\tlWidthOffset = AmWidthOffset::QuarterTileLeft;\r\n\t\tlHeightOffset = AmHeightOffset::QuarterTileDown;\r\n\r\n\t\tdWidthOffset = AmWidthOffset::HalfTileLeft;\r\n\t\tdHeightOffset = AmHeightOffset::HalfTileDown;\r\n\r\n\t\tlength = AmLineLength::FullTile;\r\n\t\tbreak;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"Invalid leveltype\");\r\n\t}\r\n\tif (!(nwTile.hasFlag(AutomapTile::Flags::HorizontalPassage) && leveltype == DTYPE_CATHEDRAL))\r\n\t\tDrawMapLineSE(out, center + AmOffset(lWidthOffset, lHeightOffset), AmLine(length), colorDim);\r\n\tDrawDiamond(out, center + AmOffset(dWidthOffset, dHeightOffset), colorBright);\r\n}\r\n\r\n/**\r\n * @brief Draw 16 individual pixels equally spaced apart, used to communicate OOB area to the player.\r\n */\r\nvoid DrawDirt(const Surface &out, Point center, AutomapTile nwTile, AutomapTile neTile, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\t// Prevent the top dirt pixel from appearing inside arch diamonds\r\n\tif (!nwTile.hasAnyFlag(AutomapTile::Flags::HorizontalArch, AutomapTile::Flags::HorizontalGrate)\r\n\t    && !neTile.hasAnyFlag(AutomapTile::Flags::VerticalArch, AutomapTile::Flags::VerticalGrate))\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp), color);\r\n\tSetMapPixel(out, center, color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawBridge(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center, color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawRiverRightIn(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center, color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawRiverCornerSouth(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n}\r\n\r\nvoid DrawRiverCornerNorth(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n}\r\n\r\nvoid DrawRiverLeftOut(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center, color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawRiverLeftIn(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp), color);\r\n\tSetMapPixel(out, center, color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n}\r\n\r\nvoid DrawRiverCornerWest(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);\r\n}\r\n\r\nvoid DrawRiverCornerEast(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawRiverRightOut(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center, color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawRiver(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center, color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawRiverForkIn(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::FullTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp), color);\r\n\tSetMapPixel(out, center, color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color);\r\n}\r\n\r\nvoid DrawRiverForkOut(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color);\r\n\r\n\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n}\r\n\r\ntemplate <Direction TDir1, Direction TDir2>\r\nvoid DrawLavaRiver(const Surface &out, Point center, uint8_t color, bool hasBridge)\r\n{\r\n\t// First row (y = 0)\r\n\tif constexpr (IsAnyOf(Direction::NorthWest, TDir1, TDir2)) {\r\n\t\tif (!(hasBridge && IsAnyOf(TDir1, Direction::NorthWest))) {\r\n\t\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileUp), color);\r\n\t\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);\r\n\t\t}\r\n\t}\r\n\r\n\t// Second row (y = 1)\r\n\tif constexpr (IsAnyOf(Direction::NorthEast, TDir1, TDir2)) {\r\n\t\tif (!(hasBridge && IsAnyOf(Direction::NorthEast, TDir1, TDir2)))\r\n\t\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color);\r\n\t}\r\n\tif constexpr (IsAnyOf(Direction::NorthWest, TDir1, TDir2) || IsAnyOf(Direction::NorthEast, TDir1, TDir2)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::None), color);\r\n\t}\r\n\tif constexpr (IsAnyOf(Direction::SouthWest, TDir1, TDir2) || IsAnyOf(Direction::NorthWest, TDir1, TDir2)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color);\r\n\t}\r\n\tif constexpr (IsAnyOf(Direction::SouthWest, TDir1, TDir2)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);\r\n\t}\r\n\r\n\t// Third row (y = 2)\r\n\tif constexpr (IsAnyOf(Direction::NorthEast, TDir1, TDir2)) {\r\n\t\tif (!(hasBridge && IsAnyOf(Direction::NorthEast, TDir1, TDir2)))\r\n\t\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);\r\n\t}\r\n\tif constexpr (IsAnyOf(Direction::NorthEast, TDir1, TDir2) || IsAnyOf(Direction::SouthEast, TDir1, TDir2)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color);\r\n\t}\r\n\tif constexpr (IsAnyOf(Direction::SouthWest, TDir1, TDir2) || IsAnyOf(Direction::SouthEast, TDir1, TDir2)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color);\r\n\t}\r\n\tif constexpr (IsAnyOf(Direction::SouthWest, TDir1, TDir2)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\t}\r\n\r\n\t// Fourth row (y = 3)\r\n\tif constexpr (IsAnyOf(Direction::SouthEast, TDir1, TDir2)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color);\r\n\t}\r\n}\r\n\r\ntemplate <Direction TDir>\r\nvoid DrawLava(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tif constexpr (IsAnyOf(TDir, Direction::NorthWest, Direction::North, Direction::NorthEast, Direction::NoDirection)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp), color); // north corner\r\n\t}\r\n\tif constexpr (IsNoneOf(TDir, Direction::South, Direction::SouthEast, Direction::East)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileUp), color); // northwest edge\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), color);             // northwest edge\r\n\t}\r\n\tif constexpr (IsAnyOf(TDir, Direction::SouthWest, Direction::West, Direction::NorthWest, Direction::NoDirection)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileDown), color); // west corner\r\n\t}\r\n\tif constexpr (IsAnyOf(TDir, Direction::South, Direction::SouthWest, Direction::West, Direction::NorthWest, Direction::SouthEast, Direction::NoDirection)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), color);             // southwest edge\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), color); // southwest edge\r\n\t}\r\n\tif constexpr (IsAnyOf(TDir, Direction::South, Direction::SouthWest, Direction::SouthEast, Direction::NoDirection)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), color); // south corner\r\n\t}\r\n\tif constexpr (IsAnyOf(TDir, Direction::South, Direction::SouthWest, Direction::NorthEast, Direction::East, Direction::SouthEast, Direction::NoDirection)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), color);             // southeast edge\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), color); // southeast edge\r\n\t}\r\n\tif constexpr (IsAnyOf(TDir, Direction::NorthEast, Direction::East, Direction::SouthEast, Direction::NoDirection)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), color); // east corner\r\n\t}\r\n\tif constexpr (IsNoneOf(TDir, Direction::South, Direction::SouthWest, Direction::West)) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileUp), color); // northeast edge\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), color);             // northeast edge\r\n\t}\r\n\tif constexpr (TDir != Direction::South) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::None), color); // north center\r\n\t}\r\n\tif constexpr (TDir != Direction::East) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown), color); // west center\r\n\t}\r\n\tif constexpr (TDir != Direction::West) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::QuarterTileDown), color); // east center\r\n\t}\r\n\tif constexpr (TDir != Direction::North) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), color); // south center\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Draw 4 south-east facing lines, used to communicate trigger locations to the player.\r\n */\r\nvoid DrawStairs(const Surface &out, Point center, uint8_t color)\r\n{\r\n\tconstexpr int NumStairSteps = 4;\r\n\tconst Displacement offset = AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::QuarterTileDown);\r\n\tAmWidthOffset w = AmWidthOffset::QuarterTileLeft;\r\n\tAmHeightOffset h = AmHeightOffset::QuarterTileUp;\r\n\r\n\tif (IsAnyOf(leveltype, DTYPE_CATACOMBS, DTYPE_HELL)) {\r\n\t\tw = AmWidthOffset::QuarterTileLeft;\r\n\t\th = AmHeightOffset::ThreeQuartersTileUp;\r\n\t}\r\n\r\n\t// Initial point based on the 'center' position.\r\n\tPoint p = center + AmOffset(w, h);\r\n\r\n\tfor (int i = 0; i < NumStairSteps; ++i) {\r\n\t\tDrawMapLineSE(out, p, AmLine(AmLineLength::DoubleTile), color);\r\n\t\tp += offset;\r\n\t}\r\n}\r\n/**\r\n * @brief Redraws the bright line of the door diamond that gets overwritten by later drawn lines.\r\n */\r\nvoid FixHorizontalDoor(const Surface &out, Point center, AutomapTile nwTile, uint8_t colorBright)\r\n{\r\n\tif (leveltype != DTYPE_CATACOMBS && nwTile.hasFlag(AutomapTile::Flags::HorizontalDoor)) {\r\n\t\tDrawMapLineNE(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::FullTile), colorBright);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Redraws the bright line of the door diamond that gets overwritten by later drawn lines.\r\n */\r\nvoid FixVerticalDoor(const Surface &out, Point center, AutomapTile neTile, uint8_t colorBright)\r\n{\r\n\tif (leveltype != DTYPE_CATACOMBS && neTile.hasFlag(AutomapTile::Flags::VerticalDoor)) {\r\n\t\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileUp), AmLine(AmLineLength::FullTile), colorBright);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Draw half-tile length lines to connect walls to any walls to the north-west and/or north-east\r\n */\r\nvoid DrawWallConnections(const Surface &out, Point center, AutomapTile tile, AutomapTile nwTile, AutomapTile neTile, uint8_t colorBright, uint8_t colorDim)\r\n{\r\n\tif (tile.hasFlag(AutomapTile::Flags::HorizontalDoor) && nwTile.hasFlag(AutomapTile::Flags::HorizontalDoor)) {\r\n\t\t//  fix missing lower half of the line connecting door pairs in Lazarus' level\r\n\t\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::HalfTile), colorDim);\r\n\t}\r\n\tif (IsAnyOf(nwTile.type, AutomapTile::Types::HorizontalWallLava, AutomapTile::Types::Horizontal, AutomapTile::Types::HorizontalDiamond, AutomapTile::Types::FenceHorizontal, AutomapTile::Types::Cross, AutomapTile::Types::CaveVerticalWoodCross, AutomapTile::Types::CaveRightCorner)) {\r\n\t\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileUp), AmLine(AmLineLength::HalfTile), colorDim);\r\n\t\tFixHorizontalDoor(out, center, nwTile, colorBright);\r\n\t}\r\n\tif (IsAnyOf(neTile.type, AutomapTile::Types::VerticalWallLava, AutomapTile::Types::Vertical, AutomapTile::Types::VerticalDiamond, AutomapTile::Types::FenceVertical, AutomapTile::Types::Cross, AutomapTile::Types::CaveHorizontalWoodCross, AutomapTile::Types::CaveLeftCorner)) {\r\n\t\tDrawMapLineNE(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::HalfTile), colorDim);\r\n\t\tFixVerticalDoor(out, center, neTile, colorBright);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Draws a dotted line to represent a wall grate.\r\n */\r\nvoid DrawMapVerticalGrate(const Surface &out, Point center, uint8_t colorDim)\r\n{\r\n\tconst Point pos1 = center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None) + AmOffset(AmWidthOffset::EighthTileRight, AmHeightOffset::EighthTileUp);\r\n\tconst Point pos2 = center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None);\r\n\tconst Point pos3 = center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None) + AmOffset(AmWidthOffset::EighthTileLeft, AmHeightOffset::EighthTileDown);\r\n\r\n\tSetMapPixel(out, pos1 + Displacement { 0, 1 }, 0);\r\n\tSetMapPixel(out, pos2 + Displacement { 0, 1 }, 0);\r\n\tSetMapPixel(out, pos3 + Displacement { 0, 1 }, 0);\r\n\tSetMapPixel(out, pos1, colorDim);\r\n\tSetMapPixel(out, pos2, colorDim);\r\n\tSetMapPixel(out, pos3, colorDim);\r\n}\r\n\r\n/**\r\n * @brief Draws a dotted line to represent a wall grate.\r\n */\r\nvoid DrawMapHorizontalGrate(const Surface &out, Point center, uint8_t colorDim)\r\n{\r\n\tconst Point pos1 = center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None) + AmOffset(AmWidthOffset::EighthTileLeft, AmHeightOffset::EighthTileUp);\r\n\tconst Point pos2 = center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None);\r\n\tconst Point pos3 = center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None) + AmOffset(AmWidthOffset::EighthTileRight, AmHeightOffset::EighthTileDown);\r\n\r\n\tSetMapPixel(out, pos1 + Displacement { 0, 1 }, 0);\r\n\tSetMapPixel(out, pos2 + Displacement { 0, 1 }, 0);\r\n\tSetMapPixel(out, pos3 + Displacement { 0, 1 }, 0);\r\n\tSetMapPixel(out, pos1, colorDim);\r\n\tSetMapPixel(out, pos2, colorDim);\r\n\tSetMapPixel(out, pos3, colorDim);\r\n}\r\n\r\n/**\r\n * Left-facing obstacle\r\n */\r\nvoid DrawHorizontal(const Surface &out, Point center, AutomapTile tile, AutomapTile nwTile, AutomapTile neTile, AutomapTile seTile, uint8_t colorBright, uint8_t colorDim)\r\n{\r\n\tAmWidthOffset w = AmWidthOffset::None;\r\n\tAmHeightOffset h = AmHeightOffset::HalfTileUp;\r\n\tAmLineLength l = AmLineLength::FullAndHalfTile;\r\n\r\n\t// Draw a diamond in the top tile\r\n\tif (neTile.hasAnyFlag(AutomapTile::Flags::VerticalArch, AutomapTile::Flags::VerticalGrate)                                                                           // NE tile has an arch, so add a diamond for visual consistency\r\n\t    || nwTile.hasAnyFlag(AutomapTile::Flags::HorizontalArch, AutomapTile::Flags::HorizontalGrate)                                                                    // NW tile has an arch, so add a diamond for visual consistency\r\n\t    || tile.hasAnyFlag(AutomapTile::Flags::VerticalArch, AutomapTile::Flags::HorizontalArch, AutomapTile::Flags::VerticalGrate, AutomapTile::Flags::HorizontalGrate) // Current tile has an arch, add a diamond\r\n\t    || tile.type == AutomapTile::Types::HorizontalDiamond) {                                                                                                         // wall ending in hell that should end with a diamond\r\n\t\tw = AmWidthOffset::QuarterTileRight;\r\n\t\th = AmHeightOffset::QuarterTileUp;\r\n\t\tl = AmLineLength::FullTile; // shorten line to avoid overdraw\r\n\t\tDrawDiamond(out, center, colorDim);\r\n\t\tFixHorizontalDoor(out, center, nwTile, colorBright);\r\n\t\tFixVerticalDoor(out, center, neTile, colorBright);\r\n\t}\r\n\t// Shorten line to avoid overdraw\r\n\tif (IsAnyOf(leveltype, DTYPE_CAVES, DTYPE_NEST)\r\n\t    && IsAnyOf(tile.type, AutomapTile::Types::CaveVerticalCross, AutomapTile::Types::CaveVerticalWoodCross)\r\n\t    && !(IsAnyOf(seTile.type, AutomapTile::Types::Horizontal, AutomapTile::Types::CaveVerticalCross, AutomapTile::Types::CaveVerticalWoodCross, AutomapTile::Types::Corner))) {\r\n\t\tl = AmLineLength::FullTile;\r\n\t}\r\n\t// Draw the wall line if the wall is solid\r\n\tif (!tile.hasFlag(AutomapTile::Flags::HorizontalPassage)) {\r\n\t\tDrawMapLineSE(out, center + AmOffset(w, h), AmLine(l), colorDim);\r\n\t\treturn;\r\n\t}\r\n\t// Draw door or grate\r\n\tif (tile.hasFlag(AutomapTile::Flags::HorizontalDoor)) {\r\n\t\tDrawMapHorizontalDoor(out, center, nwTile, colorBright, colorDim);\r\n\t} else if (tile.hasFlag(AutomapTile::Flags::HorizontalGrate)) {\r\n\t\tDrawMapHorizontalGrate(out, center, colorDim);\r\n\t}\r\n}\r\n\r\n/**\r\n * Right-facing obstacle\r\n */\r\nvoid DrawVertical(const Surface &out, Point center, AutomapTile tile, AutomapTile nwTile, AutomapTile neTile, AutomapTile swTile, uint8_t colorBright, uint8_t colorDim)\r\n{\r\n\tAmWidthOffset w = AmWidthOffset::ThreeQuartersTileLeft;\r\n\tAmHeightOffset h = AmHeightOffset::QuarterTileDown;\r\n\tAmLineLength l = AmLineLength::FullAndHalfTile;\r\n\r\n\t// Draw a diamond in the top tile\r\n\tif (neTile.hasAnyFlag(AutomapTile::Flags::VerticalArch, AutomapTile::Flags::VerticalGrate)                                                                           // NE tile has an arch, so add a diamond for visual consistency\r\n\t    || nwTile.hasAnyFlag(AutomapTile::Flags::HorizontalArch, AutomapTile::Flags::HorizontalGrate)                                                                    // NW tile has an arch, so add a diamond for visual consistency\r\n\t    || tile.hasAnyFlag(AutomapTile::Flags::VerticalArch, AutomapTile::Flags::HorizontalArch, AutomapTile::Flags::VerticalGrate, AutomapTile::Flags::HorizontalGrate) // Current tile has an arch, add a diamond\r\n\t    || tile.type == AutomapTile::Types::VerticalDiamond) {                                                                                                           // wall ending in hell that should end with a diamond\r\n\t\tl = AmLineLength::FullTile;                                                                                                                                      // shorten line to avoid overdraw\r\n\t\tDrawDiamond(out, center, colorDim);\r\n\t\tFixVerticalDoor(out, center, nwTile, colorBright);\r\n\t\tFixVerticalDoor(out, center, neTile, colorBright);\r\n\t}\r\n\t// Shorten line to avoid overdraw and adjust offset to match\r\n\tif (IsAnyOf(leveltype, DTYPE_CAVES, DTYPE_NEST)\r\n\t    && IsAnyOf(tile.type, AutomapTile::Types::CaveHorizontalCross, AutomapTile::Types::CaveHorizontalWoodCross)\r\n\t    && !(IsAnyOf(swTile.type, AutomapTile::Types::Vertical, AutomapTile::Types::CaveHorizontalCross, AutomapTile::Types::CaveHorizontalWoodCross, AutomapTile::Types::Corner))) {\r\n\t\tw = AmWidthOffset::HalfTileLeft;\r\n\t\th = AmHeightOffset::None;\r\n\t\tl = AmLineLength::FullTile;\r\n\t}\r\n\t// Draw the wall line if the wall is solid\r\n\tif (!tile.hasFlag(AutomapTile::Flags::VerticalPassage)) {\r\n\t\tDrawMapLineNE(out, center + AmOffset(w, h), AmLine(l), colorDim);\r\n\t\treturn;\r\n\t}\r\n\t// Draw door or grate\r\n\tif (tile.hasFlag(AutomapTile::Flags::VerticalDoor)) {\r\n\t\tDrawMapVerticalDoor(out, center, neTile, colorBright, colorDim);\r\n\t} else if (tile.hasFlag(AutomapTile::Flags::VerticalGrate)) {\r\n\t\tDrawMapVerticalGrate(out, center, colorDim);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Draw half-tile length lines to connect walls to any walls to the south-west and/or south-east\r\n * (For caves the horizontal/vertical flags are swapped)\r\n */\r\nvoid DrawCaveWallConnections(const Surface &out, Point center, AutomapTile sTile, AutomapTile swTile, AutomapTile seTile, uint8_t colorDim)\r\n{\r\n\tif (IsAnyOf(swTile.type, AutomapTile::Types::CaveVerticalWallLava, AutomapTile::Types::CaveVertical, AutomapTile::Types::CaveVerticalWood, AutomapTile::Types::CaveCross, AutomapTile::Types::CaveWoodCross, AutomapTile::Types::CaveRightWoodCross, AutomapTile::Types::CaveLeftWoodCross, AutomapTile::Types::CaveRightCorner)) {\r\n\t\tDrawMapLineNE(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), AmLine(AmLineLength::HalfTile), colorDim);\r\n\t}\r\n\tif (IsAnyOf(seTile.type, AutomapTile::Types::CaveHorizontalWallLava, AutomapTile::Types::CaveHorizontal, AutomapTile::Types::CaveHorizontalWood, AutomapTile::Types::CaveCross, AutomapTile::Types::CaveWoodCross, AutomapTile::Types::CaveRightWoodCross, AutomapTile::Types::CaveLeftWoodCross, AutomapTile::Types::CaveLeftCorner)) {\r\n\t\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown), AmLine(AmLineLength::HalfTile), colorDim);\r\n\t}\r\n}\r\nvoid DrawCaveHorizontalDirt(const Surface &out, Point center, AutomapTile tile, AutomapTile swTile, uint8_t colorDim)\r\n{\r\n\tif (swTile.hasFlag(AutomapTile::Flags::Dirt) || (leveltype != DTYPE_TOWN && IsNoneOf(tile.type, AutomapTile::Types::CaveHorizontalWood, AutomapTile::Types::CaveHorizontalWoodCross, AutomapTile::Types::CaveWoodCross, AutomapTile::Types::CaveLeftWoodCross))) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileDown), colorDim);\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), colorDim);\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::ThreeQuartersTileDown), colorDim);\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), colorDim);\r\n\t}\r\n}\r\n\r\n/**\r\n * For caves the horizontal/vertical flags are swapped\r\n */\r\nvoid DrawCaveHorizontal(const Surface &out, Point center, AutomapTile tile, AutomapTile nwTile, AutomapTile swTile, uint8_t colorBright, uint8_t colorDim)\r\n{\r\n\tif (tile.hasFlag(AutomapTile::Flags::VerticalDoor)) {\r\n\t\tDrawMapHorizontalDoor(out, center, nwTile, colorBright, colorDim);\r\n\t} else {\r\n\t\tAmWidthOffset w;\r\n\t\tAmHeightOffset h;\r\n\t\tAmLineLength l;\r\n\r\n\t\tif (IsAnyOf(tile.type, AutomapTile::Types::CaveHorizontalCross, AutomapTile::Types::CaveHorizontalWoodCross)) {\r\n\t\t\tw = AmWidthOffset::HalfTileLeft;\r\n\t\t\th = AmHeightOffset::None;\r\n\t\t\tl = AmLineLength::FullTile;\r\n\t\t} else {\r\n\t\t\tw = AmWidthOffset::ThreeQuartersTileLeft;\r\n\t\t\th = AmHeightOffset::QuarterTileUp;\r\n\t\t\tl = AmLineLength::FullAndHalfTile;\r\n\t\t}\r\n\t\tDrawCaveHorizontalDirt(out, center, tile, swTile, colorDim);\r\n\t\tDrawMapLineSE(out, center + AmOffset(w, h), AmLine(l), colorDim);\r\n\t}\r\n}\r\n\r\nvoid DrawCaveVerticalDirt(const Surface &out, Point center, AutomapTile tile, AutomapTile seTile, uint8_t colorDim)\r\n{\r\n\tif (seTile.hasFlag(AutomapTile::Flags::Dirt) || (leveltype != DTYPE_TOWN && IsNoneOf(tile.type, AutomapTile::Types::CaveVerticalWood, AutomapTile::Types::CaveVerticalWoodCross, AutomapTile::Types::CaveWoodCross, AutomapTile::Types::CaveRightWoodCross))) {\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), colorDim);\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::QuarterTileRight, AmHeightOffset::ThreeQuartersTileDown), colorDim);\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), colorDim);\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileRight, AmHeightOffset::QuarterTileDown), colorDim);\r\n\t}\r\n}\r\n\r\n/**\r\n * For caves the horizontal/vertical flags are swapped\r\n */\r\nvoid DrawCaveVertical(const Surface &out, Point center, AutomapTile tile, AutomapTile neTile, AutomapTile seTile, uint8_t colorBright, uint8_t colorDim)\r\n{\r\n\tif (tile.hasFlag(AutomapTile::Flags::HorizontalDoor)) {\r\n\t\tDrawMapVerticalDoor(out, center, neTile, colorBright, colorDim);\r\n\t} else {\r\n\t\tAmLineLength l;\r\n\r\n\t\tif (IsAnyOf(tile.type, AutomapTile::Types::CaveVerticalCross, AutomapTile::Types::CaveVerticalWoodCross)) {\r\n\t\t\tl = AmLineLength::FullTile;\r\n\t\t} else {\r\n\t\t\tl = AmLineLength::FullAndHalfTile;\r\n\t\t}\r\n\t\tDrawCaveVerticalDirt(out, center, tile, seTile, colorDim);\r\n\t\tDrawMapLineNE(out, { center + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown) }, AmLine(l), colorDim);\r\n\t}\r\n}\r\n\r\nvoid DrawCaveLeftCorner(const Surface &out, Point center, uint8_t colorDim)\r\n{\r\n\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileUp), AmLine(AmLineLength::HalfTile), colorDim);\r\n\tDrawMapLineNE(out, center + AmOffset(AmWidthOffset::ThreeQuartersTileLeft, AmHeightOffset::QuarterTileDown), AmLine(AmLineLength::HalfTile), colorDim);\r\n}\r\n\r\nvoid DrawCaveRightCorner(const Surface &out, Point center, uint8_t colorDim)\r\n{\r\n\tDrawMapLineSE(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), AmLine(AmLineLength::HalfTile), colorDim);\r\n\tDrawMapLineNE(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None), AmLine(AmLineLength::HalfTile), colorDim);\r\n}\r\n\r\nvoid DrawMapEllipse(const Surface &out, Point from, int radius, uint8_t colorIndex)\r\n{\r\n\tconst int a = radius;\r\n\tconst int b = radius / 2;\r\n\r\n\tint x = 0;\r\n\tint y = b;\r\n\r\n\t// Offset ellipse so the center of the ellipse is the center of our megatile on the x plane\r\n\tfrom.x -= radius;\r\n\r\n\t// Initial point\r\n\tSetMapPixel(out, { from.x, from.y + b }, colorIndex);\r\n\tSetMapPixel(out, { from.x, from.y - b }, colorIndex);\r\n\r\n\t// Initialize the parameters\r\n\tint p1 = (b * b) - (a * a * b) + (a * a) / 4;\r\n\r\n\t// Region 1\r\n\twhile ((b * b * x) < (a * a * y)) {\r\n\t\tx++;\r\n\t\tif (p1 < 0) {\r\n\t\t\tp1 += (2 * b * b * x) + (b * b);\r\n\t\t} else {\r\n\t\t\ty--;\r\n\t\t\tp1 += (2 * b * b * x) - (2 * a * a * y) + (b * b);\r\n\t\t}\r\n\r\n\t\tSetMapPixel(out, { from.x + x, from.y + y }, colorIndex);\r\n\t\tSetMapPixel(out, { from.x - x, from.y + y }, colorIndex);\r\n\t\tSetMapPixel(out, { from.x + x, from.y - y }, colorIndex);\r\n\t\tSetMapPixel(out, { from.x - x, from.y - y }, colorIndex);\r\n\t}\r\n\r\n\t// Initialize the second parameter for Region 2\r\n\tint p2 = (b * b * ((x + 1) * (x + 1))) + (a * a * ((y - 1) * (y - 1))) - (a * a * b * b);\r\n\r\n\t// Region 2\r\n\twhile (y > 0) {\r\n\t\ty--;\r\n\t\tif (p2 > 0) {\r\n\t\t\tp2 += (-2 * a * a * y) + (a * a);\r\n\t\t} else {\r\n\t\t\tx++;\r\n\t\t\tp2 += (2 * b * b * x) - (2 * a * a * y) + (a * a);\r\n\t\t}\r\n\r\n\t\tSetMapPixel(out, { from.x + x, from.y + y }, colorIndex);\r\n\t\tSetMapPixel(out, { from.x - x, from.y + y }, colorIndex);\r\n\t\tSetMapPixel(out, { from.x + x, from.y - y }, colorIndex);\r\n\t\tSetMapPixel(out, { from.x - x, from.y - y }, colorIndex);\r\n\t}\r\n}\r\n\r\nvoid DrawMapStar(const Surface &out, Point from, int radius, uint8_t color)\r\n{\r\n\tconst int scaleFactor = 128;\r\n\tPoint anchors[5];\r\n\r\n\t// Offset star so the center of the star is the center of our megatile on the x plane\r\n\tfrom.x -= radius;\r\n\r\n\tanchors[0] = { from.x - (121 * radius / scaleFactor), from.y + (19 * radius / scaleFactor) }; // Left Point\r\n\tanchors[1] = { from.x + (121 * radius / scaleFactor), from.y + (19 * radius / scaleFactor) }; // Right Point\r\n\tanchors[2] = { from.x, from.y + (64 * radius / scaleFactor) };                                // Bottom Point\r\n\tanchors[3] = { from.x - (75 * radius / scaleFactor), from.y - (51 * radius / scaleFactor) };  // Top Left Point\r\n\tanchors[4] = { from.x + (75 * radius / scaleFactor), from.y - (51 * radius / scaleFactor) };  // Top Right Point\r\n\r\n\t// Draw lines between the anchors to form a star\r\n\tDrawMapFreeLine(out, anchors[3], anchors[1], color); // Connect Top Left -> Right\r\n\tDrawMapFreeLine(out, anchors[1], anchors[0], color); // Connect Right -> Left\r\n\tDrawMapFreeLine(out, anchors[0], anchors[4], color); // Connect Left -> Top Right\r\n\tDrawMapFreeLine(out, anchors[4], anchors[2], color); // Connect Top Right -> Bottom\r\n\tDrawMapFreeLine(out, anchors[2], anchors[3], color); // Connect Bottom -> Top Left\r\n}\r\n\r\n/**\r\n * @brief Check if a given tile has the provided AutomapTile flag\r\n */\r\nbool HasAutomapFlag(Point position, AutomapTile::Flags type)\r\n{\r\n\tif (position.x < 0 || position.x >= DMAXX || position.y < 0 || position.y >= DMAXX) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn AutomapTypeTiles[dungeon[position.x][position.y]].hasFlag(type);\r\n}\r\n\r\n/**\r\n * @brief Returns the automap shape at the given coordinate.\r\n */\r\nAutomapTile GetAutomapTileType(Point position)\r\n{\r\n\tif (position.x < 0 || position.x >= DMAXX || position.y < 0 || position.y >= DMAXX) {\r\n\t\treturn {};\r\n\t}\r\n\r\n\tAutomapTile tile = AutomapTypeTiles[dungeon[position.x][position.y]];\r\n\tif (tile.type == AutomapTile::Types::Corner) {\r\n\t\tif (HasAutomapFlag({ position.x - 1, position.y }, AutomapTile::Flags::HorizontalArch)) {\r\n\t\t\tif (HasAutomapFlag({ position.x, position.y - 1 }, AutomapTile::Flags::VerticalArch)) {\r\n\t\t\t\ttile.type = AutomapTile::Types::Diamond;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn tile;\r\n}\r\n\r\n/**\r\n * @brief Returns the automap shape at the given coordinate.\r\n */\r\nAutomapTile GetAutomapTypeView(Point map)\r\n{\r\n\tif (map.x == -1 && map.y >= 0 && map.y < DMAXY && AutomapView[0][map.y] != MAP_EXP_NONE) {\r\n\t\tif (HasAutomapFlag({ 0, map.y + 1 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ 0, map.y }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ 0, map.y - 1 }, AutomapTile::Flags::Dirt)) {\r\n\t\t\treturn {};\r\n\t\t}\r\n\t\treturn { AutomapTile::Types::None, AutomapTile::Flags::Dirt };\r\n\t}\r\n\r\n\tif (map.y == -1 && map.x >= 0 && map.x < DMAXY && AutomapView[map.x][0] != MAP_EXP_NONE) {\r\n\t\tif (HasAutomapFlag({ map.x + 1, 0 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ map.x, 0 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ map.x - 1, 0 }, AutomapTile::Flags::Dirt)) {\r\n\t\t\treturn {};\r\n\t\t}\r\n\t\treturn { AutomapTile::Types::None, AutomapTile::Flags::Dirt };\r\n\t}\r\n\r\n\tif (map.x < 0 || map.x >= DMAXX) {\r\n\t\treturn {};\r\n\t}\r\n\tif (map.y < 0 || map.y >= DMAXX) {\r\n\t\treturn {};\r\n\t}\r\n\tif (AutomapView[map.x][map.y] == MAP_EXP_NONE) {\r\n\t\treturn {};\r\n\t}\r\n\r\n\treturn GetAutomapTileType(map);\r\n}\r\n\r\n/**\r\n * @brief Renders the given automap shape at the specified screen coordinates.\r\n */\r\nvoid DrawAutomapTile(const Surface &out, Point center, Point map)\r\n{\r\n\tuint8_t colorBright = MapColorsBright;\r\n\tuint8_t colorDim = MapColorsDim;\r\n\tconst MapExplorationType explorationType = static_cast<MapExplorationType>(AutomapView[std::clamp(map.x, 0, DMAXX - 1)][std::clamp(map.y, 0, DMAXY - 1)]);\r\n\r\n\tswitch (explorationType) {\r\n\tcase MAP_EXP_SHRINE:\r\n\t\tcolorDim = PAL16_GRAY + 11;\r\n\t\tcolorBright = PAL16_GRAY + 3;\r\n\t\tbreak;\r\n\tcase MAP_EXP_OTHERS:\r\n\t\tcolorDim = PAL16_BEIGE + 10;\r\n\t\tcolorBright = PAL16_BEIGE + 2;\r\n\t\tbreak;\r\n\tcase MAP_EXP_SELF:\r\n\tcase MAP_EXP_NONE:\r\n\tcase MAP_EXP_OLD:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tbool noConnect = false;\r\n\tAutomapTile tile = GetAutomapTypeView(map + Direction::NoDirection);\r\n\tAutomapTile nwTile = GetAutomapTypeView(map + Direction::NorthWest);\r\n\tAutomapTile neTile = GetAutomapTypeView(map + Direction::NorthEast);\r\n\r\n#ifdef _DEBUG\r\n\tif (DebugVision) {\r\n\t\tif (IsTileLit(map.megaToWorld()))\r\n\t\t\tDrawDiamond(out, center, PAL8_ORANGE + 1);\r\n\t\tif (IsTileLit(map.megaToWorld() + Direction::South))\r\n\t\t\tDrawDiamond(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), PAL8_ORANGE + 1);\r\n\t\tif (IsTileLit(map.megaToWorld() + Direction::SouthWest))\r\n\t\t\tDrawDiamond(out, center + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), PAL8_ORANGE + 1);\r\n\t\tif (IsTileLit(map.megaToWorld() + Direction::SouthEast))\r\n\t\t\tDrawDiamond(out, center + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), PAL8_ORANGE + 1);\r\n\t}\r\n#endif\r\n\r\n\t// If the tile is an arch, grate, or diamond, we draw a diamond and therefore don't want connection lines\r\n\tif (tile.hasAnyFlag(AutomapTile::Flags::HorizontalArch, AutomapTile::Flags::VerticalArch, AutomapTile::Flags::HorizontalGrate, AutomapTile::Flags::VerticalGrate)\r\n\t    || nwTile.hasAnyFlag(AutomapTile::Flags::HorizontalArch, AutomapTile::Flags::HorizontalGrate)\r\n\t    || neTile.hasAnyFlag(AutomapTile::Flags::VerticalArch, AutomapTile::Flags::VerticalGrate)\r\n\t    || tile.type == AutomapTile::Types::Diamond) {\r\n\t\tnoConnect = true;\r\n\t}\r\n\r\n\t// These tilesets have doors where the connection lines would be drawn\r\n\tif (IsAnyOf(leveltype, DTYPE_CATACOMBS, DTYPE_CAVES) && (tile.hasFlag(AutomapTile::Flags::HorizontalDoor) || tile.hasFlag(AutomapTile::Flags::VerticalDoor)))\r\n\t\tnoConnect = true;\r\n\r\n\tconst AutomapTile swTile = GetAutomapTypeView(map + Direction::SouthWest);\r\n\tconst AutomapTile sTile = GetAutomapTypeView(map + Direction::South);\r\n\tconst AutomapTile seTile = GetAutomapTypeView(map + Direction::SouthEast);\r\n\tconst AutomapTile nTile = GetAutomapTypeView(map + Direction::North);\r\n\tconst AutomapTile wTile = GetAutomapTypeView(map + Direction::West);\r\n\tconst AutomapTile eTile = GetAutomapTypeView(map + Direction::East);\r\n\r\n\tif ((leveltype == DTYPE_TOWN && tile.hasFlag(AutomapTile::Flags::Dirt))\r\n\t    || (tile.hasFlag(AutomapTile::Flags::Dirt)\r\n\t        && (tile.type != AutomapTile::Types::None\r\n\t            || swTile.type != AutomapTile::Types::None\r\n\t            || sTile.type != AutomapTile::Types::None\r\n\t            || seTile.type != AutomapTile::Types::None\r\n\t            || IsAnyOf(nwTile.type, AutomapTile::Types::CaveCross, AutomapTile::Types::CaveVertical, AutomapTile::Types::CaveVerticalCross, AutomapTile::Types::CaveVerticalWallLava, AutomapTile::Types::CaveLeftWoodCross)\r\n\t            || IsAnyOf(nTile.type, AutomapTile::Types::CaveCross)\r\n\t            || IsAnyOf(neTile.type, AutomapTile::Types::CaveCross, AutomapTile::Types::CaveHorizontal, AutomapTile::Types::CaveHorizontalCross, AutomapTile::Types::CaveHorizontalWallLava, AutomapTile::Types::CaveRightWoodCross)\r\n\t            || IsAnyOf(wTile.type, AutomapTile::Types::CaveVerticalCross)\r\n\t            || IsAnyOf(eTile.type, AutomapTile::Types::CaveHorizontalCross)))) {\r\n\t\tDrawDirt(out, center, nwTile, neTile, colorDim);\r\n\t}\r\n\r\n\tif (tile.hasFlag(AutomapTile::Flags::Stairs)) {\r\n\t\tDrawStairs(out, center, colorBright);\r\n\t}\r\n\r\n\tif (!noConnect) {\r\n\t\tif (IsAnyOf(leveltype, DTYPE_TOWN, DTYPE_CAVES, DTYPE_NEST)) {\r\n\t\t\tDrawCaveWallConnections(out, center, sTile, swTile, seTile, colorDim);\r\n\t\t}\r\n\t\tDrawWallConnections(out, center, tile, nwTile, neTile, colorBright, colorDim);\r\n\t}\r\n\r\n\tuint8_t lavaColor = MapColorsLava;\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\tlavaColor = MapColorsAcid;\r\n\t} else if (setlevel && setlvlnum == Quests[Q_PWATER]._qslvl) {\r\n\t\tif (Quests[Q_PWATER]._qactive != QUEST_DONE) {\r\n\t\t\tlavaColor = MapColorsAcid;\r\n\t\t} else {\r\n\t\t\tlavaColor = MapColorsWater;\r\n\t\t}\r\n\t}\r\n\r\n\tswitch (tile.type) {\r\n\tcase AutomapTile::Types::Diamond: // stand-alone column or other unpassable object\r\n\t\tDrawDiamond(out, center, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Vertical:\r\n\tcase AutomapTile::Types::FenceVertical:\r\n\tcase AutomapTile::Types::VerticalDiamond:\r\n\t\tDrawVertical(out, center, tile, nwTile, neTile, swTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Horizontal:\r\n\tcase AutomapTile::Types::FenceHorizontal:\r\n\tcase AutomapTile::Types::HorizontalDiamond:\r\n\t\tDrawHorizontal(out, center, tile, nwTile, neTile, seTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Cross:\r\n\t\tDrawVertical(out, center, tile, nwTile, neTile, swTile, colorBright, colorDim);\r\n\t\tDrawHorizontal(out, center, tile, nwTile, neTile, seTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveHorizontalCross:\r\n\tcase AutomapTile::Types::CaveHorizontalWoodCross:\r\n\t\tDrawVertical(out, center, tile, nwTile, neTile, swTile, colorBright, colorDim);\r\n\t\tDrawCaveHorizontal(out, center, tile, nwTile, swTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveVerticalCross:\r\n\tcase AutomapTile::Types::CaveVerticalWoodCross:\r\n\t\tDrawHorizontal(out, center, tile, nwTile, neTile, seTile, colorBright, colorDim);\r\n\t\tDrawCaveVertical(out, center, tile, neTile, seTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveHorizontal:\r\n\tcase AutomapTile::Types::CaveHorizontalWood:\r\n\t\tDrawCaveHorizontal(out, center, tile, nwTile, swTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveVertical:\r\n\tcase AutomapTile::Types::CaveVerticalWood:\r\n\t\tDrawCaveVertical(out, center, tile, neTile, seTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveCross:\r\n\t\t// Add the missing dirt pixel\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), colorDim);\r\n\t\t[[fallthrough]];\r\n\tcase AutomapTile::Types::CaveWoodCross:\r\n\tcase AutomapTile::Types::CaveRightWoodCross:\r\n\tcase AutomapTile::Types::CaveLeftWoodCross:\r\n\t\tDrawCaveHorizontal(out, center, tile, nwTile, swTile, colorBright, colorDim);\r\n\t\tDrawCaveVertical(out, center, tile, neTile, seTile, colorBright, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveLeftCorner:\r\n\t\tDrawCaveLeftCorner(out, center, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveRightCorner:\r\n\t\tDrawCaveRightCorner(out, center, colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Corner:\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveBottomCorner:\r\n\t\t// Add the missing dirt pixel\r\n\t\t// BUGFIX: A tile in poisoned water supply isn't drawing this pixel\r\n\t\tSetMapPixel(out, center + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown), colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::None:\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Bridge:\r\n\t\tDrawBridge(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::River:\r\n\t\tDrawRiver(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverCornerEast:\r\n\t\tDrawRiverCornerEast(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverCornerNorth:\r\n\t\tDrawRiverCornerNorth(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverCornerSouth:\r\n\t\tDrawRiverCornerSouth(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverCornerWest:\r\n\t\tDrawRiverCornerWest(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverForkIn:\r\n\t\tDrawRiverForkIn(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverForkOut:\r\n\t\tDrawRiverForkOut(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverLeftIn:\r\n\t\tDrawRiverLeftIn(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverLeftOut:\r\n\t\tDrawRiverLeftOut(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverRightIn:\r\n\t\tDrawRiverRightIn(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::RiverRightOut:\r\n\t\tDrawRiverRightOut(out, center, MapColorsItem);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::HorizontalLavaThin:\r\n\t\tDrawLavaRiver<Direction::NorthWest, Direction::SouthEast>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::VerticalLavaThin:\r\n\t\tDrawLavaRiver<Direction::NorthEast, Direction::SouthWest>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::BendSouthLavaThin:\r\n\t\tDrawLavaRiver<Direction::SouthWest, Direction::SouthEast>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::BendWestLavaThin:\r\n\t\tDrawLavaRiver<Direction::NorthWest, Direction::SouthWest>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::BendEastLavaThin:\r\n\t\tDrawLavaRiver<Direction::NorthEast, Direction::SouthEast>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::BendNorthLavaThin:\r\n\t\tDrawLavaRiver<Direction::NorthWest, Direction::NorthEast>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::VerticalWallLava:\r\n\t\tDrawVertical(out, center, tile, nwTile, neTile, swTile, colorBright, colorDim);\r\n\t\tDrawLavaRiver<Direction::SouthEast, Direction::NoDirection>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::HorizontalWallLava:\r\n\t\tDrawHorizontal(out, center, tile, nwTile, neTile, swTile, colorBright, colorDim);\r\n\t\tDrawLavaRiver<Direction::SouthWest, Direction::NoDirection>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::SELava:\r\n\t\tDrawLava<Direction::SouthEast>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::SWLava:\r\n\t\tDrawLava<Direction::SouthWest>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::NELava:\r\n\t\tDrawLava<Direction::NorthEast>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::NWLava:\r\n\t\tDrawLava<Direction::NorthWest>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::SLava:\r\n\t\tDrawLava<Direction::South>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::WLava:\r\n\t\tDrawLava<Direction::West>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::ELava:\r\n\t\tDrawLava<Direction::East>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::NLava:\r\n\t\tDrawLava<Direction::North>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Lava:\r\n\t\tDrawLava<Direction::NoDirection>(out, center, lavaColor);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveHorizontalWallLava:\r\n\t\tDrawCaveHorizontal(out, center, tile, nwTile, swTile, colorBright, colorDim);\r\n\t\tDrawLavaRiver<Direction::NorthEast, Direction::NoDirection>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::CaveVerticalWallLava:\r\n\t\tDrawCaveVertical(out, center, tile, neTile, seTile, colorBright, colorDim);\r\n\t\tDrawLavaRiver<Direction::NorthWest, Direction::NoDirection>(out, center, lavaColor, false);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::HorizontalBridgeLava:\r\n\t\tDrawLavaRiver<Direction::NorthWest, Direction::SouthEast>(out, center, lavaColor, true);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::VerticalBridgeLava:\r\n\t\tDrawLavaRiver<Direction::NorthEast, Direction::SouthWest>(out, center, lavaColor, true);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::PentagramClosed:\r\n\t\t// Functions are called twice to integrate shadow. Shadows are not drawn inside these functions to avoid shadows being drawn on top of normal pixels.\r\n\t\tDrawMapEllipse(out, center + Displacement { 0, 1 }, AmLine(AmLineLength::OctupleTile), 0); // shadow\r\n\t\tDrawMapStar(out, center + Displacement { 0, 1 }, AmLine(AmLineLength::OctupleTile), 0);    // shadow\r\n\t\tDrawMapEllipse(out, center, AmLine(AmLineLength::OctupleTile), colorDim);\r\n\t\tDrawMapStar(out, center, AmLine(AmLineLength::OctupleTile), colorDim);\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::PentagramOpen:\r\n\t\t// Functions are called twice to integrate shadow. Shadows are not drawn inside these functions to avoid shadows being drawn on top of normal pixels.\r\n\t\tDrawMapEllipse(out, center + Displacement { 0, 1 }, AmLine(AmLineLength::OctupleTile), 0); // shadow\r\n\t\tDrawMapStar(out, center + Displacement { 0, 1 }, AmLine(AmLineLength::OctupleTile), 0);    // shadow\r\n\t\tDrawMapEllipse(out, center, AmLine(AmLineLength::OctupleTile), MapColorsPentagramOpen);\r\n\t\tDrawMapStar(out, center, AmLine(AmLineLength::OctupleTile), MapColorsPentagramOpen);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nDisplacement GetAutomapScreen()\r\n{\r\n\tDisplacement screen = {};\r\n\r\n\tif (GetAutomapType() == AutomapType::Minimap) {\r\n\t\tscreen = {\r\n\t\t\tMinimapRect.position.x + MinimapRect.size.width / 2,\r\n\t\t\tMinimapRect.position.y + MinimapRect.size.height / 2\r\n\t\t};\r\n\t} else {\r\n\t\tscreen = {\r\n\t\t\tgnScreenWidth / 2,\r\n\t\t\t(gnScreenHeight - GetMainPanel().size.height) / 2\r\n\t\t};\r\n\t}\r\n\tscreen += AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown);\r\n\r\n\treturn screen;\r\n}\r\n\r\nvoid SearchAutomapItem(const Surface &out, const Displacement &myPlayerOffset, int searchRadius, tl::function_ref<bool(Point position)> highlightTile)\r\n{\r\n\tconst Player &player = *MyPlayer;\r\n\tPoint tile = player.position.tile;\r\n\tif (player._pmode == PM_WALK_SIDEWAYS) {\r\n\t\ttile = player.position.future;\r\n\t\tif (player._pdir == Direction::West)\r\n\t\t\ttile.x++;\r\n\t\telse\r\n\t\t\ttile.y++;\r\n\t}\r\n\r\n\tconst int startX = std::clamp(tile.x - searchRadius, 0, MAXDUNX);\r\n\tconst int startY = std::clamp(tile.y - searchRadius, 0, MAXDUNY);\r\n\tconst int endX = std::clamp(tile.x + searchRadius, 0, MAXDUNX);\r\n\tconst int endY = std::clamp(tile.y + searchRadius, 0, MAXDUNY);\r\n\r\n\tconst AutomapType mapType = GetAutomapType();\r\n\tconst int scale = (mapType == AutomapType::Minimap) ? MinimapScale : AutoMapScale;\r\n\r\n\tfor (int i = startX; i < endX; i++) {\r\n\t\tfor (int j = startY; j < endY; j++) {\r\n\t\t\tif (!highlightTile({ i, j }))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst int px = i - 2 * AutomapOffset.deltaX - ViewPosition.x;\r\n\t\t\tconst int py = j - 2 * AutomapOffset.deltaY - ViewPosition.y;\r\n\r\n\t\t\tPoint screen = {\r\n\t\t\t\t(myPlayerOffset.deltaX * scale / 100 / 2) + (px - py) * AmLine(AmLineLength::DoubleTile),\r\n\t\t\t\t(myPlayerOffset.deltaY * scale / 100 / 2) + (px + py) * AmLine(AmLineLength::FullTile),\r\n\t\t\t};\r\n\r\n\t\t\tscreen += GetAutomapScreen();\r\n\r\n\t\t\tif (mapType != AutomapType::Minimap && CanPanelsCoverView()) {\r\n\t\t\t\tif (IsRightPanelOpen())\r\n\t\t\t\t\tscreen.x -= gnScreenWidth / 4;\r\n\t\t\t\tif (IsLeftPanelOpen())\r\n\t\t\t\t\tscreen.x += gnScreenWidth / 4;\r\n\t\t\t}\r\n\r\n\t\t\tscreen.y -= AmLine(AmLineLength::FullTile);\r\n\t\t\tDrawDiamond(out, screen, MapColorsItem);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nuint8_t GetPlayerMapColor(int id)\r\n{\r\n\tstatic constexpr uint8_t PlayerMapColors[] = {\r\n\t\tMapColorsPlayer1,\r\n\t\tMapColorsPlayer2,\r\n\t\tMapColorsPlayer3,\r\n\t\tMapColorsPlayer4,\r\n\t};\r\n\r\n\tif (id < 0 || id >= static_cast<int>(SDL_arraysize(PlayerMapColors)))\r\n\t\treturn MapColorsPlayer1;\r\n\r\n\treturn PlayerMapColors[id];\r\n}\r\n\r\n/**\r\n * @brief Renders an arrow on the automap, centered on and facing the direction of the player.\r\n */\r\nvoid DrawAutomapPlr(const Surface &out, const Displacement &myPlayerOffset, const Player &player)\r\n{\r\n\tconst uint8_t playerColor = GetPlayerMapColor(player.getId());\r\n\r\n\tconst Point tile = player.position.tile;\r\n\r\n\tconst int px = tile.x - 2 * AutomapOffset.deltaX - ViewPosition.x;\r\n\tconst int py = tile.y - 2 * AutomapOffset.deltaY - ViewPosition.y;\r\n\r\n\tDisplacement playerOffset = {};\r\n\tif (player.isWalking())\r\n\t\tplayerOffset = GetOffsetForWalking(player.AnimInfo, player._pdir);\r\n\r\n\tconst int scale = (GetAutomapType() == AutomapType::Minimap) ? MinimapScale : AutoMapScale;\r\n\r\n\tPoint base = {\r\n\t\t((playerOffset.deltaX + myPlayerOffset.deltaX) * scale / 100 / 2) + (px - py) * AmLine(AmLineLength::DoubleTile),\r\n\t\t((playerOffset.deltaY + myPlayerOffset.deltaY) * scale / 100 / 2) + (px + py) * AmLine(AmLineLength::FullTile) + AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileUp).deltaY\r\n\t};\r\n\r\n\tbase += GetAutomapScreen();\r\n\r\n\tif (CanPanelsCoverView()) {\r\n\t\tif (IsRightPanelOpen())\r\n\t\t\tbase.x -= gnScreenWidth / 4;\r\n\t\tif (IsLeftPanelOpen())\r\n\t\t\tbase.x += gnScreenWidth / 4;\r\n\t}\r\n\r\n\tswitch (player._pdir) {\r\n\tcase Direction::North: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileUp);\r\n\t\tDrawMapLineNS(out, point, AmLine(AmLineLength::DoubleTile), playerColor);\r\n\t\tDrawMapLineSteepNE(out, point + AmOffset(AmWidthOffset::EighthTileLeft, AmHeightOffset::HalfTileDown), AmLine(AmLineLength::HalfTile), playerColor);\r\n\t\tDrawMapLineSteepNW(out, point + AmOffset(AmWidthOffset::EighthTileRight, AmHeightOffset::HalfTileDown), AmLine(AmLineLength::HalfTile), playerColor);\r\n\t} break;\r\n\tcase Direction::NorthEast: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileUp);\r\n\t\tDrawMapLineWE(out, point + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::None), AmLine(AmLineLength::FullTile), playerColor);\r\n\t\tDrawMapLineNE(out, point + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown), AmLine(AmLineLength::FullTile), playerColor);\r\n\t\tDrawMapLineSteepSW(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t} break;\r\n\tcase Direction::East: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None);\r\n\t\tDrawMapLineNW(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t\tDrawMapLineWE(out, point + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None), AmLine(AmLineLength::DoubleTile), playerColor);\r\n\t\tDrawMapLineSW(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t} break;\r\n\tcase Direction::SouthEast: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown);\r\n\t\tDrawMapLineSteepNW(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t\tDrawMapLineSE(out, point + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::FullTile), playerColor);\r\n\t\tDrawMapLineWE(out, point + AmOffset(AmWidthOffset::QuarterTileLeft, AmHeightOffset::None) + Displacement { -1, 0 }, AmLine(AmLineLength::FullTile) + 1, playerColor);\r\n\t} break;\r\n\tcase Direction::South: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown);\r\n\t\tDrawMapLineNS(out, point + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileUp), AmLine(AmLineLength::DoubleTile), playerColor);\r\n\t\tDrawMapLineSteepSW(out, point + AmOffset(AmWidthOffset::EighthTileRight, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::HalfTile), playerColor);\r\n\t\tDrawMapLineSteepSE(out, point + AmOffset(AmWidthOffset::EighthTileLeft, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::HalfTile), playerColor);\r\n\t} break;\r\n\tcase Direction::SouthWest: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileDown);\r\n\t\tDrawMapLineSteepNE(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t\tDrawMapLineSW(out, point + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileUp), AmLine(AmLineLength::FullTile), playerColor);\r\n\t\tDrawMapLineWE(out, point, AmLine(AmLineLength::FullTile) + 1, playerColor);\r\n\t} break;\r\n\tcase Direction::West: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::None);\r\n\t\tDrawMapLineNE(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t\tDrawMapLineWE(out, point, AmLine(AmLineLength::DoubleTile) + 1, playerColor);\r\n\t\tDrawMapLineSE(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t} break;\r\n\tcase Direction::NorthWest: {\r\n\t\tconst Point point = base + AmOffset(AmWidthOffset::HalfTileLeft, AmHeightOffset::HalfTileUp);\r\n\t\tDrawMapLineNW(out, point + AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::HalfTileDown), AmLine(AmLineLength::FullTile), playerColor);\r\n\t\tDrawMapLineWE(out, point, AmLine(AmLineLength::FullTile) + 1, playerColor);\r\n\t\tDrawMapLineSteepSE(out, point, AmLine(AmLineLength::HalfTile), playerColor);\r\n\t} break;\r\n\tcase Direction::NoDirection:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Renders game info, such as the name of the current level, and in multi player the name of the game and the game password.\r\n */\r\nvoid DrawAutomapText(const Surface &out)\r\n{\r\n\tPoint linePosition { 8, 8 };\r\n\r\n\tauto advanceLine = [&](int numLines = 1) {\r\n\t\tlinePosition.y += 15 * numLines;\r\n\t};\r\n\r\n\tauto drawStringAndAdvanceLine = [&](std::string_view text, TextRenderOptions opts = {}, int numLines = 1) {\r\n\t\tDrawString(out, text, linePosition, opts);\r\n\t\tadvanceLine(numLines);\r\n\t};\r\n\r\n\tif (*GetOptions().Graphics.showFPS) {\r\n\t\tadvanceLine();\r\n\t}\r\n\r\n\tif (gbIsMultiplayer) {\r\n\t\tif (GameName != \"0.0.0.0\" && !IsLoopback) {\r\n\t\t\tstd::string description = std::string(_(\"Game: \"));\r\n\t\t\tdescription.append(GameName);\r\n\t\t\tdrawStringAndAdvanceLine(description);\r\n\t\t}\r\n\r\n\t\tstd::string description;\r\n\t\tif (IsLoopback) {\r\n\t\t\tdescription = std::string(_(\"Offline Game\"));\r\n\t\t} else if (PublicGame) {\r\n\t\t\tdescription = std::string(_(\"Public Game\"));\r\n\t\t} else {\r\n\t\t\tdescription = std::string(_(\"Password: \"));\r\n\t\t\tdescription.append(GamePassword);\r\n\t\t}\r\n\t\tdrawStringAndAdvanceLine(description);\r\n\t}\r\n\r\n\tif (setlevel) {\r\n\t\tdrawStringAndAdvanceLine(_(QuestLevelNames[setlvlnum]));\r\n\t} else {\r\n\t\tstd::string description;\r\n\t\tswitch (leveltype) {\r\n\t\tcase DTYPE_NEST:\r\n\t\t\tdescription = fmt::format(fmt::runtime(_(\"Level: Nest {:d}\")), currlevel - 16);\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_CRYPT:\r\n\t\t\tdescription = fmt::format(fmt::runtime(_(\"Level: Crypt {:d}\")), currlevel - 20);\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_TOWN:\r\n\t\t\tdescription = std::string(_(\"Town\"));\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tdescription = fmt::format(fmt::runtime(_(\"Level: {:d}\")), currlevel);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdrawStringAndAdvanceLine(description);\r\n\t}\r\n\r\n\tstd::string_view difficulty;\r\n\tswitch (sgGameInitInfo.nDifficulty) {\r\n\tcase DIFF_NORMAL:\r\n\t\tdifficulty = _(\"Normal\");\r\n\t\tbreak;\r\n\tcase DIFF_NIGHTMARE:\r\n\t\tdifficulty = _(\"Nightmare\");\r\n\t\tbreak;\r\n\tcase DIFF_HELL:\r\n\t\tdifficulty = _(\"Hell\");\r\n\t\tbreak;\r\n\t}\r\n\r\n\tconst std::string description = fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} means: Game Difficulty. */ \"Difficulty: {:s}\")), difficulty);\r\n\tdrawStringAndAdvanceLine(description);\r\n\r\n#ifdef _DEBUG\r\n\tif (DebugGodMode || DebugInvisible || DisableLighting || DebugVision || DebugPath || DebugGrid || DebugScrollViewEnabled) {\r\n\t\tconst TextRenderOptions disabled {\r\n\t\t\t.flags = UiFlags::ColorBlack,\r\n\t\t};\r\n\t\tconst TextRenderOptions enabled {\r\n\t\t\t.flags = UiFlags::ColorOrange,\r\n\t\t};\r\n\r\n\t\tadvanceLine();\r\n\t\tdrawStringAndAdvanceLine(\"Debug toggles:\");\r\n\t\tdrawStringAndAdvanceLine(\"Player:\");\r\n\t\tdrawStringAndAdvanceLine(\"God Mode\", DebugGodMode ? enabled : disabled);\r\n\t\tdrawStringAndAdvanceLine(\"Invisible\", DebugInvisible ? enabled : disabled);\r\n\t\tdrawStringAndAdvanceLine(\"Display:\");\r\n\t\tdrawStringAndAdvanceLine(\"Fullbright\", DisableLighting ? enabled : disabled);\r\n\t\tdrawStringAndAdvanceLine(\"Draw Vision\", DebugVision ? enabled : disabled);\r\n\t\tdrawStringAndAdvanceLine(\"Draw Path\", DebugPath ? enabled : disabled);\r\n\t\tdrawStringAndAdvanceLine(\"Draw Grid\", DebugGrid ? enabled : disabled);\r\n\t\tdrawStringAndAdvanceLine(\"Scroll View\", DebugScrollViewEnabled ? enabled : disabled);\r\n\t}\r\n#endif\r\n}\r\n\r\nstd::unique_ptr<AutomapTile[]> LoadAutomapData(size_t &tileCount)\r\n{\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_TOWN:\r\n\t\treturn LoadFileInMem<AutomapTile>(\"levels\\\\towndata\\\\automap.amp\", &tileCount);\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\treturn LoadFileInMem<AutomapTile>(\"levels\\\\l1data\\\\l1.amp\", &tileCount);\r\n\tcase DTYPE_CATACOMBS:\r\n\t\treturn LoadFileInMem<AutomapTile>(\"levels\\\\l2data\\\\l2.amp\", &tileCount);\r\n\tcase DTYPE_CAVES:\r\n\t\treturn LoadFileInMem<AutomapTile>(\"levels\\\\l3data\\\\l3.amp\", &tileCount);\r\n\tcase DTYPE_HELL:\r\n\t\treturn LoadFileInMem<AutomapTile>(\"levels\\\\l4data\\\\l4.amp\", &tileCount);\r\n\tcase DTYPE_NEST:\r\n\t\treturn LoadFileInMem<AutomapTile>(\"nlevels\\\\l6data\\\\l6.amp\", &tileCount);\r\n\tcase DTYPE_CRYPT:\r\n\t\treturn LoadFileInMem<AutomapTile>(\"nlevels\\\\l5data\\\\l5.amp\", &tileCount);\r\n\tdefault:\r\n\t\treturn nullptr;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nbool AutomapActive;\r\nAutomapType CurrentAutomapType = AutomapType::Opaque;\r\nuint8_t AutomapView[DMAXX][DMAXY];\r\nint AutoMapScale;\r\nint MinimapScale;\r\nDisplacement AutomapOffset;\r\nRectangle MinimapRect {};\r\n\r\nvoid InitAutomapOnce()\r\n{\r\n\tAutomapActive = false;\r\n\tAutoMapScale = 50;\r\n\r\n\t// Set the dimensions and screen position of the minimap relative to the screen dimensions\r\n\tconst int minimapWidth = gnScreenWidth / 4;\r\n\tconst Size minimapSize { minimapWidth, minimapWidth / 2 };\r\n\tconst int minimapPadding = gnScreenWidth / 128;\r\n\tMinimapRect = Rectangle { { gnScreenWidth - minimapPadding - minimapSize.width, minimapPadding }, minimapSize };\r\n\r\n\t// Set minimap scale\r\n\tconst int height = 480;\r\n\tconst int scale = 25;\r\n\tconst int factor = gnScreenHeight / height;\r\n\r\n\tif (factor >= 8) {\r\n\t\tMinimapScale = scale * 8;\r\n\t} else {\r\n\t\tMinimapScale = scale * factor;\r\n\t}\r\n}\r\n\r\nvoid InitAutomap()\r\n{\r\n\tsize_t tileCount = 0;\r\n\tconst std::unique_ptr<AutomapTile[]> tileTypes = LoadAutomapData(tileCount);\r\n\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_CATACOMBS:\r\n\t\ttileTypes[41] = { AutomapTile::Types::FenceHorizontal };\r\n\t\tbreak;\r\n\tcase DTYPE_TOWN: // Town automap uses a dun file that contains caves tileset\r\n\tcase DTYPE_CAVES:\r\n\tcase DTYPE_NEST:\r\n\t\ttileTypes[4] = { AutomapTile::Types::CaveBottomCorner };\r\n\t\ttileTypes[12] = { AutomapTile::Types::CaveRightCorner };\r\n\t\ttileTypes[13] = { AutomapTile::Types::CaveLeftCorner };\r\n\t\tif (IsAnyOf(leveltype, DTYPE_CAVES)) {\r\n\t\t\ttileTypes[129] = { AutomapTile::Types::CaveHorizontalWoodCross };\r\n\t\t\ttileTypes[131] = { AutomapTile::Types::CaveHorizontalWoodCross };\r\n\t\t\ttileTypes[133] = { AutomapTile::Types::CaveHorizontalWood };\r\n\t\t\ttileTypes[135] = { AutomapTile::Types::CaveHorizontalWood };\r\n\t\t\ttileTypes[150] = { AutomapTile::Types::CaveHorizontalWood };\r\n\t\t\ttileTypes[145] = { AutomapTile::Types::CaveHorizontalWood, AutomapTile::Flags::VerticalDoor };\r\n\t\t\ttileTypes[147] = { AutomapTile::Types::CaveHorizontalWood, AutomapTile::Flags::VerticalDoor };\r\n\t\t\ttileTypes[130] = { AutomapTile::Types::CaveVerticalWoodCross };\r\n\t\t\ttileTypes[132] = { AutomapTile::Types::CaveVerticalWoodCross };\r\n\t\t\ttileTypes[134] = { AutomapTile::Types::CaveVerticalWood };\r\n\t\t\ttileTypes[136] = { AutomapTile::Types::CaveVerticalWood };\r\n\t\t\ttileTypes[151] = { AutomapTile::Types::CaveVerticalWood };\r\n\t\t\ttileTypes[146] = { AutomapTile::Types::CaveVerticalWood, AutomapTile::Flags::HorizontalDoor };\r\n\t\t\ttileTypes[148] = { AutomapTile::Types::CaveVerticalWood, AutomapTile::Flags::HorizontalDoor };\r\n\t\t\ttileTypes[137] = { AutomapTile::Types::CaveWoodCross };\r\n\t\t\ttileTypes[140] = { AutomapTile::Types::CaveWoodCross };\r\n\t\t\ttileTypes[141] = { AutomapTile::Types::CaveWoodCross };\r\n\t\t\ttileTypes[142] = { AutomapTile::Types::CaveWoodCross };\r\n\t\t\ttileTypes[138] = { AutomapTile::Types::CaveRightWoodCross };\r\n\t\t\ttileTypes[139] = { AutomapTile::Types::CaveLeftWoodCross };\r\n\t\t\ttileTypes[14] = { AutomapTile::Types::HorizontalLavaThin };\r\n\t\t\ttileTypes[15] = { AutomapTile::Types::HorizontalLavaThin };\r\n\t\t\ttileTypes[16] = { AutomapTile::Types::VerticalLavaThin };\r\n\t\t\ttileTypes[17] = { AutomapTile::Types::VerticalLavaThin };\r\n\t\t\ttileTypes[18] = { AutomapTile::Types::BendSouthLavaThin };\r\n\t\t\ttileTypes[19] = { AutomapTile::Types::BendWestLavaThin };\r\n\t\t\ttileTypes[20] = { AutomapTile::Types::BendEastLavaThin };\r\n\t\t\ttileTypes[21] = { AutomapTile::Types::BendNorthLavaThin };\r\n\t\t\ttileTypes[22] = { AutomapTile::Types::VerticalWallLava };\r\n\t\t\ttileTypes[23] = { AutomapTile::Types::HorizontalWallLava };\r\n\t\t\ttileTypes[24] = { AutomapTile::Types::SELava };\r\n\t\t\ttileTypes[25] = { AutomapTile::Types::SWLava };\r\n\t\t\ttileTypes[26] = { AutomapTile::Types::NELava };\r\n\t\t\ttileTypes[27] = { AutomapTile::Types::NWLava };\r\n\t\t\ttileTypes[28] = { AutomapTile::Types::SLava };\r\n\t\t\ttileTypes[29] = { AutomapTile::Types::WLava };\r\n\t\t\ttileTypes[30] = { AutomapTile::Types::ELava };\r\n\t\t\ttileTypes[31] = { AutomapTile::Types::NLava };\r\n\t\t\ttileTypes[32] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[33] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[34] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[35] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[36] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[37] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[38] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[39] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[40] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[41] = { AutomapTile::Types::CaveHorizontalWallLava };\r\n\t\t\ttileTypes[42] = { AutomapTile::Types::CaveVerticalWallLava };\r\n\t\t\ttileTypes[43] = { AutomapTile::Types::HorizontalBridgeLava };\r\n\t\t\ttileTypes[44] = { AutomapTile::Types::VerticalBridgeLava };\r\n\t\t} else if (IsAnyOf(leveltype, DTYPE_NEST)) {\r\n\t\t\ttileTypes[102] = { AutomapTile::Types::HorizontalLavaThin };\r\n\t\t\ttileTypes[103] = { AutomapTile::Types::HorizontalLavaThin };\r\n\t\t\ttileTypes[108] = { AutomapTile::Types::HorizontalLavaThin };\r\n\t\t\ttileTypes[104] = { AutomapTile::Types::VerticalLavaThin };\r\n\t\t\ttileTypes[105] = { AutomapTile::Types::VerticalLavaThin };\r\n\t\t\ttileTypes[107] = { AutomapTile::Types::VerticalLavaThin };\r\n\t\t\ttileTypes[112] = { AutomapTile::Types::BendSouthLavaThin };\r\n\t\t\ttileTypes[113] = { AutomapTile::Types::BendWestLavaThin };\r\n\t\t\ttileTypes[110] = { AutomapTile::Types::BendEastLavaThin };\r\n\t\t\ttileTypes[111] = { AutomapTile::Types::BendNorthLavaThin };\r\n\t\t\ttileTypes[134] = { AutomapTile::Types::VerticalWallLava };\r\n\t\t\ttileTypes[135] = { AutomapTile::Types::HorizontalWallLava };\r\n\t\t\ttileTypes[118] = { AutomapTile::Types::SELava };\r\n\t\t\ttileTypes[119] = { AutomapTile::Types::SWLava };\r\n\t\t\ttileTypes[120] = { AutomapTile::Types::NELava };\r\n\t\t\ttileTypes[121] = { AutomapTile::Types::NWLava };\r\n\t\t\ttileTypes[106] = { AutomapTile::Types::SLava };\r\n\t\t\ttileTypes[114] = { AutomapTile::Types::WLava };\r\n\t\t\ttileTypes[130] = { AutomapTile::Types::ELava };\r\n\t\t\ttileTypes[122] = { AutomapTile::Types::NLava };\r\n\t\t\ttileTypes[117] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[124] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[126] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[127] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[128] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[129] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[131] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[132] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[133] = { AutomapTile::Types::Lava };\r\n\t\t\ttileTypes[136] = { AutomapTile::Types::CaveHorizontalWallLava };\r\n\t\t\ttileTypes[137] = { AutomapTile::Types::CaveVerticalWallLava };\r\n\t\t\ttileTypes[115] = { AutomapTile::Types::HorizontalBridgeLava };\r\n\t\t\ttileTypes[116] = { AutomapTile::Types::VerticalBridgeLava };\r\n\t\t}\r\n\t\tbreak;\r\n\tcase DTYPE_HELL:\r\n\t\ttileTypes[51] = { AutomapTile::Types::VerticalDiamond };\r\n\t\ttileTypes[55] = { AutomapTile::Types::HorizontalDiamond };\r\n\t\ttileTypes[102] = { AutomapTile::Types::PentagramClosed };\r\n\t\ttileTypes[111] = { AutomapTile::Types::PentagramOpen };\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\tfor (unsigned i = 0; i < tileCount; i++) {\r\n\t\tAutomapTypeTiles[i + 1] = tileTypes[i];\r\n\t}\r\n\r\n\tmemset(AutomapView, 0, sizeof(AutomapView));\r\n\r\n\tfor (auto &column : dFlags)\r\n\t\tfor (auto &dFlag : column)\r\n\t\t\tdFlag &= ~DungeonFlag::Explored;\r\n}\r\n\r\nvoid StartAutomap()\r\n{\r\n\tAutomapOffset = { 0, 0 };\r\n\tAutomapActive = true;\r\n}\r\n\r\nvoid AutomapUp()\r\n{\r\n\tAutomapOffset.deltaX--;\r\n\tAutomapOffset.deltaY--;\r\n}\r\n\r\nvoid AutomapDown()\r\n{\r\n\tAutomapOffset.deltaX++;\r\n\tAutomapOffset.deltaY++;\r\n}\r\n\r\nvoid AutomapLeft()\r\n{\r\n\tAutomapOffset.deltaX--;\r\n\tAutomapOffset.deltaY++;\r\n}\r\n\r\nvoid AutomapRight()\r\n{\r\n\tAutomapOffset.deltaX++;\r\n\tAutomapOffset.deltaY--;\r\n}\r\n\r\nvoid AutomapZoomIn()\r\n{\r\n\tint &scale = (GetAutomapType() == AutomapType::Minimap) ? MinimapScale : AutoMapScale;\r\n\r\n\tif (scale >= 200)\r\n\t\treturn;\r\n\r\n\tscale += 25;\r\n}\r\n\r\nvoid AutomapZoomOut()\r\n{\r\n\tint &scale = (GetAutomapType() == AutomapType::Minimap) ? MinimapScale : AutoMapScale;\r\n\r\n\tif (scale <= 25)\r\n\t\treturn;\r\n\r\n\tscale -= 25;\r\n}\r\n\r\nvoid DrawAutomap(const Surface &out)\r\n{\r\n\tAutomap = { (ViewPosition.x - 8) / 2, (ViewPosition.y - 8) / 2 };\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tAutomap += { -4, -4 };\r\n\t}\r\n\twhile (Automap.x + AutomapOffset.deltaX < 0)\r\n\t\tAutomapOffset.deltaX++;\r\n\twhile (Automap.x + AutomapOffset.deltaX >= DMAXX)\r\n\t\tAutomapOffset.deltaX--;\r\n\r\n\twhile (Automap.y + AutomapOffset.deltaY < 0)\r\n\t\tAutomapOffset.deltaY++;\r\n\twhile (Automap.y + AutomapOffset.deltaY >= DMAXY)\r\n\t\tAutomapOffset.deltaY--;\r\n\r\n\tAutomap += AutomapOffset;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tDisplacement myPlayerOffset = {};\r\n\tif (myPlayer.isWalking())\r\n\t\tmyPlayerOffset = GetOffsetForWalking(myPlayer.AnimInfo, myPlayer._pdir, true);\r\n\r\n\tconst int scale = (GetAutomapType() == AutomapType::Minimap) ? MinimapScale : AutoMapScale;\r\n\tconst int d = (scale * 64) / 100;\r\n\tint cells = 2 * (gnScreenWidth / 2 / d) + 1;\r\n\tif (((gnScreenWidth / 2) % d) != 0)\r\n\t\tcells++;\r\n\tif (((gnScreenWidth / 2) % d) >= (scale * 32) / 100)\r\n\t\tcells++;\r\n\tif ((myPlayerOffset.deltaX + myPlayerOffset.deltaY) != 0)\r\n\t\tcells++;\r\n\r\n\tif (GetAutomapType() == AutomapType::Minimap) {\r\n\t\t// Background fill\r\n\t\tDrawHalfTransparentRectTo(out, MinimapRect.position.x, MinimapRect.position.y, MinimapRect.size.width, MinimapRect.size.height);\r\n\r\n\t\tconst uint8_t frameShadowColor = PAL16_YELLOW + 12;\r\n\r\n\t\t// Shadow\r\n\t\tDrawHorizontalLine(out, MinimapRect.position + Displacement { -1, -1 }, MinimapRect.size.width + 1, frameShadowColor);\r\n\t\tDrawHorizontalLine(out, MinimapRect.position + Displacement { -2, MinimapRect.size.height + 1 }, MinimapRect.size.width + 4, frameShadowColor);\r\n\t\tDrawVerticalLine(out, MinimapRect.position + Displacement { -1, 0 }, MinimapRect.size.height, frameShadowColor);\r\n\t\tDrawVerticalLine(out, MinimapRect.position + Displacement { MinimapRect.size.width + 1, -2 }, MinimapRect.size.height + 3, frameShadowColor);\r\n\r\n\t\t// Frame\r\n\t\tDrawHorizontalLine(out, MinimapRect.position + Displacement { -2, -2 }, MinimapRect.size.width + 3, MapColorsDim);\r\n\t\tDrawHorizontalLine(out, MinimapRect.position + Displacement { -2, MinimapRect.size.height }, MinimapRect.size.width + 3, MapColorsDim);\r\n\t\tDrawVerticalLine(out, MinimapRect.position + Displacement { -2, -1 }, MinimapRect.size.height + 1, MapColorsDim);\r\n\t\tDrawVerticalLine(out, MinimapRect.position + Displacement { MinimapRect.size.width, -1 }, MinimapRect.size.height + 1, MapColorsDim);\r\n\r\n\t\tif (AutoMapShowItems)\r\n\t\t\tSearchAutomapItem(out, myPlayerOffset, 8, [](Point position) {\r\n\t\t\t\treturn dItem[position.x][position.y] != 0;\r\n\t\t\t});\r\n\t}\r\n\r\n\tPoint screen = {};\r\n\r\n\tscreen += GetAutomapScreen();\r\n\r\n\tif ((cells & 1) != 0) {\r\n\t\tscreen.x -= AmOffset(AmWidthOffset::DoubleTileRight, AmHeightOffset::None).deltaX * ((cells - 1) / 2);\r\n\t\tscreen.y -= AmOffset(AmWidthOffset::None, AmHeightOffset::DoubleTileDown).deltaY * ((cells + 1) / 2);\r\n\r\n\t} else {\r\n\t\tscreen.x -= AmOffset(AmWidthOffset::DoubleTileRight, AmHeightOffset::None).deltaX * (cells / 2) + AmOffset(AmWidthOffset::FullTileLeft, AmHeightOffset::None).deltaX;\r\n\t\tscreen.y -= AmOffset(AmWidthOffset::None, AmHeightOffset::DoubleTileDown).deltaY * (cells / 2) + AmOffset(AmWidthOffset::None, AmHeightOffset::FullTileDown).deltaY;\r\n\t}\r\n\tif ((ViewPosition.x & 1) != 0) {\r\n\t\tscreen.x -= AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None).deltaX;\r\n\t\tscreen.y -= AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown).deltaY;\r\n\t}\r\n\tif ((ViewPosition.y & 1) != 0) {\r\n\t\tscreen.x += AmOffset(AmWidthOffset::HalfTileRight, AmHeightOffset::None).deltaX;\r\n\t\tscreen.y -= AmOffset(AmWidthOffset::None, AmHeightOffset::HalfTileDown).deltaY;\r\n\t}\r\n\r\n\tscreen.x += scale * myPlayerOffset.deltaX / 100 / 2;\r\n\tscreen.y += scale * myPlayerOffset.deltaY / 100 / 2;\r\n\r\n\tif (CanPanelsCoverView()) {\r\n\t\tif (IsRightPanelOpen()) {\r\n\t\t\tscreen.x -= gnScreenWidth / 4;\r\n\t\t}\r\n\t\tif (IsLeftPanelOpen()) {\r\n\t\t\tscreen.x += gnScreenWidth / 4;\r\n\t\t}\r\n\t}\r\n\r\n\tPoint map = { Automap.x - cells, Automap.y - 1 };\r\n\r\n\tfor (int i = 0; i <= cells + 1; i++) {\r\n\t\tPoint tile1 = screen;\r\n\t\tfor (int j = 0; j < cells; j++) {\r\n\t\t\tDrawAutomapTile(out, tile1, { map.x + j, map.y - j });\r\n\t\t\ttile1.x += AmOffset(AmWidthOffset::DoubleTileRight, AmHeightOffset::None).deltaX;\r\n\t\t}\r\n\t\tmap.y++;\r\n\r\n\t\tPoint tile2 = screen + AmOffset(AmWidthOffset::FullTileLeft, AmHeightOffset::FullTileDown);\r\n\t\tfor (int j = 0; j <= cells; j++) {\r\n\t\t\tDrawAutomapTile(out, tile2, { map.x + j, map.y - j });\r\n\t\t\ttile2.x += AmOffset(AmWidthOffset::DoubleTileRight, AmHeightOffset::None).deltaX;\r\n\t\t}\r\n\t\tmap.x++;\r\n\t\tscreen.y += AmOffset(AmWidthOffset::None, AmHeightOffset::DoubleTileDown).deltaY;\r\n\t}\r\n\r\n\tfor (const Player &player : Players) {\r\n\t\tif (player.isOnActiveLevel() && player.plractive && !player._pLvlChanging && (&player == MyPlayer || player.friendlyMode)) {\r\n\t\t\tDrawAutomapPlr(out, myPlayerOffset, player);\r\n\t\t}\r\n\t}\r\n\r\n\tif (AutoMapShowItems)\r\n\t\tSearchAutomapItem(out, myPlayerOffset, 8, [](Point position) { return dItem[position.x][position.y] != 0; });\r\n#ifdef _DEBUG\r\n\tif (IsDebugAutomapHighlightNeeded())\r\n\t\tSearchAutomapItem(out, myPlayerOffset, std::max(MAXDUNX, MAXDUNY), ShouldHighlightDebugAutomapTile);\r\n#endif\r\n\r\n\tDrawAutomapText(out);\r\n}\r\n\r\nvoid UpdateAutomapExplorer(Point map, MapExplorationType explorer)\r\n{\r\n\tif (AutomapView[map.x][map.y] < explorer)\r\n\t\tAutomapView[map.x][map.y] = explorer;\r\n}\r\n\r\nvoid SetAutomapView(Point position, MapExplorationType explorer)\r\n{\r\n\tconst Point map { (position.x - 16) / 2, (position.y - 16) / 2 };\r\n\r\n\tif (map.x < 0 || map.x >= DMAXX || map.y < 0 || map.y >= DMAXY) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tUpdateAutomapExplorer(map, explorer);\r\n\r\n\tconst AutomapTile tile = GetAutomapTileType(map);\r\n\tconst bool solid = tile.hasFlag(AutomapTile::Flags::Dirt);\r\n\r\n\tswitch (tile.type) {\r\n\tcase AutomapTile::Types::Vertical:\r\n\t\tif (solid) {\r\n\t\t\tauto tileSW = GetAutomapTileType({ map.x, map.y + 1 });\r\n\t\t\tif (tileSW.type == AutomapTile::Types::Corner && tileSW.hasFlag(AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x, map.y + 1 }, explorer);\r\n\t\t} else if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) {\r\n\t\t\tUpdateAutomapExplorer({ map.x - 1, map.y }, explorer);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Horizontal:\r\n\t\tif (solid) {\r\n\t\t\tauto tileSE = GetAutomapTileType({ map.x + 1, map.y });\r\n\t\t\tif (tileSE.type == AutomapTile::Types::Corner && tileSE.hasFlag(AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x + 1, map.y }, explorer);\r\n\t\t} else if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) {\r\n\t\t\tUpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::Cross:\r\n\t\tif (solid) {\r\n\t\t\tauto tileSW = GetAutomapTileType({ map.x, map.y + 1 });\r\n\t\t\tif (tileSW.type == AutomapTile::Types::Corner && tileSW.hasFlag(AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x, map.y + 1 }, explorer);\r\n\t\t\tauto tileSE = GetAutomapTileType({ map.x + 1, map.y });\r\n\t\t\tif (tileSE.type == AutomapTile::Types::Corner && tileSE.hasFlag(AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x + 1, map.y }, explorer);\r\n\t\t} else {\r\n\t\t\tif (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x - 1, map.y }, explorer);\r\n\t\t\tif (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);\r\n\t\t\tif (HasAutomapFlag({ map.x - 1, map.y - 1 }, AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x - 1, map.y - 1 }, explorer);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::FenceVertical:\r\n\t\tif (solid) {\r\n\t\t\tif (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);\r\n\t\t\tauto tileSW = GetAutomapTileType({ map.x, map.y + 1 });\r\n\t\t\tif (tileSW.type == AutomapTile::Types::Corner && tileSW.hasFlag(AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x, map.y + 1 }, explorer);\r\n\t\t} else if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) {\r\n\t\t\tUpdateAutomapExplorer({ map.x - 1, map.y }, explorer);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AutomapTile::Types::FenceHorizontal:\r\n\t\tif (solid) {\r\n\t\t\tif (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x - 1, map.y }, explorer);\r\n\t\t\tauto tileSE = GetAutomapTileType({ map.x + 1, map.y });\r\n\t\t\tif (tileSE.type == AutomapTile::Types::Corner && tileSE.hasFlag(AutomapTile::Flags::Dirt))\r\n\t\t\t\tUpdateAutomapExplorer({ map.x + 1, map.y }, explorer);\r\n\t\t} else if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) {\r\n\t\t\tUpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid AutomapZoomReset()\r\n{\r\n\tAutomapOffset = { 0, 0 };\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/automap.h",
    "content": "/**\r\n * @file automap.h\r\n *\r\n * Interface of the in-game map overlay.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum MapExplorationType : uint8_t {\r\n\t/** unexplored map tile */\r\n\tMAP_EXP_NONE,\r\n\t/** map tile explored in vanilla - compatibility reasons */\r\n\tMAP_EXP_OLD,\r\n\t/** map explored by a shrine */\r\n\tMAP_EXP_SHRINE,\r\n\t/** map tile explored by someone else in multiplayer */\r\n\tMAP_EXP_OTHERS,\r\n\t/** map tile explored by current player */\r\n\tMAP_EXP_SELF,\r\n};\r\n\r\n/** Specifies whether the automap is enabled. */\r\nextern DVL_API_FOR_TEST bool AutomapActive;\r\n/** Tracks the explored areas of the map. */\r\nextern uint8_t AutomapView[DMAXX][DMAXY];\r\n/** Specifies the scale of the automap. */\r\nextern DVL_API_FOR_TEST int AutoMapScale;\r\nextern DVL_API_FOR_TEST int MinimapScale;\r\nextern DVL_API_FOR_TEST Displacement AutomapOffset;\r\nextern Rectangle MinimapRect;\r\n\r\n/** Defines the offsets used for Automap lines */\r\nenum class AmWidthOffset : int8_t {\r\n\tNone,\r\n\tEighthTileRight = TILE_WIDTH >> 4,\r\n\tQuarterTileRight = TILE_WIDTH >> 3,\r\n\tHalfTileRight = TILE_WIDTH >> 2,\r\n\tThreeQuartersTileRight = (TILE_WIDTH >> 1) - (TILE_WIDTH >> 3),\r\n\tFullTileRight = TILE_WIDTH >> 1,\r\n\tDoubleTileRight = TILE_WIDTH,\r\n\tEighthTileLeft = -EighthTileRight,\r\n\tQuarterTileLeft = -QuarterTileRight,\r\n\tHalfTileLeft = -HalfTileRight,\r\n\tThreeQuartersTileLeft = -ThreeQuartersTileRight,\r\n\tFullTileLeft = -FullTileRight,\r\n\tDoubleTileLeft = -DoubleTileRight,\r\n};\r\n\r\nenum class AmHeightOffset : int8_t {\r\n\tNone,\r\n\tEighthTileDown = TILE_HEIGHT >> 4,\r\n\tQuarterTileDown = TILE_HEIGHT >> 3,\r\n\tHalfTileDown = TILE_HEIGHT >> 2,\r\n\tThreeQuartersTileDown = (TILE_HEIGHT >> 1) - (TILE_HEIGHT >> 3),\r\n\tFullTileDown = TILE_HEIGHT >> 1,\r\n\tDoubleTileDown = TILE_HEIGHT,\r\n\tEighthTileUp = -EighthTileDown,\r\n\tQuarterTileUp = -QuarterTileDown,\r\n\tHalfTileUp = -HalfTileDown,\r\n\tThreeQuartersTileUp = -ThreeQuartersTileDown,\r\n\tFullTileUp = -FullTileDown,\r\n\tDoubleTileUp = -DoubleTileDown,\r\n};\r\n\r\nenum class AmLineLength : uint8_t {\r\n\tQuarterTile = 2,\r\n\tHalfTile = 4,\r\n\tFullTile = 8,\r\n\tFullAndHalfTile = 12,\r\n\tDoubleTile = 16,\r\n\tOctupleTile = 64,\r\n};\r\n\r\nenum class AutomapType : uint8_t {\r\n\tOpaque,\r\n\tFIRST = Opaque,\r\n\tTransparent,\r\n\tMinimap,\r\n\tLAST = Minimap\r\n};\r\n\r\nextern DVL_API_FOR_TEST AutomapType CurrentAutomapType;\r\n\r\n/**\r\n * @brief Sets the map type. Does not change `AutomapActive`.\r\n */\r\ninline void SetAutomapType(AutomapType type)\r\n{\r\n\tCurrentAutomapType = type;\r\n}\r\n\r\n/**\r\n * @brief Sets the map type. Does not change `AutomapActive`.\r\n */\r\ninline AutomapType GetAutomapType()\r\n{\r\n\treturn CurrentAutomapType;\r\n}\r\n\r\ninline Displacement AmOffset(AmWidthOffset x, AmHeightOffset y)\r\n{\r\n\tint scale = (GetAutomapType() == AutomapType::Minimap) ? MinimapScale : AutoMapScale;\r\n\r\n\treturn { scale * static_cast<int>(x) / 100, scale * static_cast<int>(y) / 100 };\r\n}\r\n\r\ninline int AmLine(AmLineLength l)\r\n{\r\n\tint scale = (GetAutomapType() == AutomapType::Minimap) ? MinimapScale : AutoMapScale;\r\n\r\n\treturn scale * static_cast<int>(l) / 100;\r\n}\r\n\r\n/**\r\n * @brief Sets the map type. Does not change `AutomapActive`.\r\n */\r\nvoid SetAutomapType(AutomapType type);\r\n\r\nAutomapType GetAutomapType();\r\n\r\n/**\r\n * @brief Initializes the automap.\r\n */\r\nvoid InitAutomapOnce();\r\n\r\n/**\r\n * @brief Loads the mapping between tile IDs and automap shapes.\r\n */\r\nvoid InitAutomap();\r\n\r\n/**\r\n * @brief Displays the automap.\r\n */\r\nvoid StartAutomap();\r\n\r\n/**\r\n * @brief Displays the minimap.\r\n */\r\nvoid StartMinimap();\r\n\r\n/**\r\n * @brief Scrolls the automap upwards.\r\n */\r\nvoid AutomapUp();\r\n\r\n/**\r\n * @brief Scrolls the automap downwards.\r\n */\r\nvoid AutomapDown();\r\n\r\n/**\r\n * @brief Scrolls the automap leftwards.\r\n */\r\nvoid AutomapLeft();\r\n\r\n/**\r\n * @brief Scrolls the automap rightwards.\r\n */\r\nvoid AutomapRight();\r\n\r\n/**\r\n * @brief Increases the zoom level of the automap.\r\n */\r\nvoid AutomapZoomIn();\r\n\r\n/**\r\n * @brief Decreases the zoom level of the automap.\r\n */\r\nvoid AutomapZoomOut();\r\n\r\n/**\r\n * @brief Renders the automap to the given buffer.\r\n */\r\nvoid DrawAutomap(const Surface &out);\r\n\r\n/**\r\n * @brief Updates automap explorer at point if value is higher than existing.\r\n */\r\nvoid UpdateAutomapExplorer(Point map, MapExplorationType explorer);\r\n\r\n/**\r\n * @brief Marks the given coordinate as within view on the automap.\r\n */\r\nvoid SetAutomapView(Point tile, MapExplorationType explorer);\r\n\r\n/**\r\n * @brief Resets the zoom level of the automap.\r\n */\r\nvoid AutomapZoomReset();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/capture.cpp",
    "content": "/**\r\n * @file capture.cpp\r\n *\r\n * Implementation of the screenshot function.\r\n */\r\n#include <cerrno>\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <cstring>\r\n#include <ctime>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_iostream.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl_compat.h\"\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#define DEVILUTIONX_SCREENSHOT_FORMAT_PCX 0\r\n#define DEVILUTIONX_SCREENSHOT_FORMAT_PNG 1\r\n\r\n#if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX\r\n#include \"utils/surface_to_pcx.hpp\"\r\n#endif\r\n#if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PNG\r\n#include \"utils/surface_to_png.hpp\"\r\n#endif\r\n\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/render/scrollrt.h\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nSDL_IOStream *CaptureFile(std::string *dstPath)\r\n{\r\n\tconst char *ext =\r\n#if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX\r\n\t    \".pcx\";\r\n#elif DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PNG\r\n\t    \".png\";\r\n#endif\r\n\tconst std::time_t tt = std::time(nullptr);\r\n\tconst std::tm *tm = std::localtime(&tt);\r\n\tconst std::string filename = tm != nullptr\r\n\t    ? StrCat(\"Screenshot from \",\r\n\t          LeftPad(tm->tm_year + 1900, 4, '0'), \"-\", LeftPad(tm->tm_mon + 1, 2, '0'), \"-\", LeftPad(tm->tm_mday, 2, '0'), \"-\",\r\n\t          LeftPad(tm->tm_hour, 2, '0'), \"-\", LeftPad(tm->tm_min, 2, '0'), \"-\", LeftPad(tm->tm_sec, 2, '0'))\r\n\t    : \"Screenshot\";\r\n\t*dstPath = StrCat(paths::PrefPath(), filename, ext);\r\n\tint i = 0;\r\n\twhile (FileExists(dstPath->c_str())) {\r\n\t\ti++;\r\n\t\t*dstPath = StrCat(paths::PrefPath(), filename, \"-\", i, ext);\r\n\t}\r\n\treturn SDL_IOFromFile(dstPath->c_str(), \"wb\");\r\n}\r\n\r\n/**\r\n * @brief Make a red version of the given palette and apply it to the screen.\r\n */\r\nvoid RedPalette()\r\n{\r\n\tfor (int i = 0; i < 256; i++) {\r\n\t\tsystem_palette[i].g = 0;\r\n\t\tsystem_palette[i].b = 0;\r\n\t}\r\n\tSystemPaletteUpdated();\r\n\tBltFast(nullptr, nullptr);\r\n\tRenderPresent();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid CaptureScreen()\r\n{\r\n\tstd::string fileName;\r\n\tconst uint32_t startTime = SDL_GetTicks();\r\n\r\n\tauto *outStream = CaptureFile(&fileName);\r\n\tif (outStream == nullptr) {\r\n\t\tLogError(\"Failed to open {} for writing: {}\", fileName, SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn;\r\n\t}\r\n\tDrawAndBlit();\r\n\r\n\tconst std::array<SDL_Color, 256> origSystemPalette = system_palette;\r\n\tRedPalette();\r\n\r\n\tsystem_palette = origSystemPalette;\r\n\tSystemPaletteUpdated();\r\n\r\n\tconst tl::expected<void, std::string> result =\r\n#if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX\r\n\t    WriteSurfaceToFilePcx(GlobalBackBuffer(), outStream);\r\n#elif DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PNG\r\n\t    WriteSurfaceToFilePng(GlobalBackBuffer(), outStream);\r\n#endif\r\n\r\n\tif (!result.has_value()) {\r\n\t\tLogError(\"Failed to save screenshot at {}: \", fileName, result.error());\r\n\t\tRemoveFile(fileName.c_str());\r\n\t} else {\r\n\t\tLog(\"Screenshot saved at {}\", fileName);\r\n\t}\r\n\tconst uint32_t timePassed = SDL_GetTicks() - startTime;\r\n\tif (timePassed < 300) {\r\n\t\tSDL_Delay(300 - timePassed);\r\n\t}\r\n\tRedrawEverything();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/capture.h",
    "content": "/**\r\n * @file capture.h\r\n *\r\n * Interface of the screenshot function.\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Save the current screen to a screen??.pcx (00-99) in file if available, then make the screen red for 200ms.\r\n */\r\nvoid CaptureScreen();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/codec.cpp",
    "content": "#include <algorithm>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include \"appfat.h\"\r\n#include \"sha.h\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstruct CodecSignature {\r\n\tuint32_t checksum;\r\n\tuint8_t error;\r\n\tuint8_t lastChunkSize;\r\n};\r\n\r\nconstexpr size_t BlockSizeBytes = BlockSize * sizeof(uint32_t);\r\nconstexpr size_t SignatureSize = 8;\r\n\r\nSHA1Context CodecInitKey(const char *pszPassword)\r\n{\r\n\tuint32_t pw[BlockSize]; // Repeat password until 64 char long\r\n\tstd::size_t j = 0;\r\n\tfor (uint32_t &value : pw) {\r\n\t\tif (pszPassword[j] == '\\0')\r\n\t\t\tj = 0;\r\n\t\tvalue = LoadLE32(&pszPassword[j]);\r\n\t\tj += sizeof(uint32_t);\r\n\t}\r\n\r\n\tuint32_t digest[SHA1HashSize];\r\n\t{\r\n\t\tSHA1Context context;\r\n\t\tSHA1Calculate(context, pw);\r\n\t\tSHA1Result(context, digest);\r\n\t}\r\n\r\n\tuint32_t key[BlockSize] {\r\n\t\t2908958655, 4146550480, 658981742, 1113311088, 3927878744, 679301322, 1760465731, 3305370375,\r\n\t\t2269115995, 3928541685, 580724401, 2607446661, 2233092279, 2416822349, 4106933702, 3046442503\r\n\t};\r\n\r\n\tfor (unsigned i = 0; i < BlockSize; ++i) {\r\n\t\tkey[i] ^= digest[(i + 3) % SHA1HashSize];\r\n\t}\r\n\r\n\tSHA1Context context;\r\n\tSHA1Calculate(context, key);\r\n\treturn context;\r\n}\r\n\r\nCodecSignature GetCodecSignature(std::byte *src)\r\n{\r\n\tCodecSignature result;\r\n\tresult.checksum = LoadLE32(src);\r\n\tsrc += 4;\r\n\tresult.error = static_cast<uint8_t>(*src++);\r\n\tresult.lastChunkSize = static_cast<uint8_t>(*src);\r\n\treturn result;\r\n}\r\n\r\nvoid SetCodecSignature(std::byte *dst, CodecSignature sig)\r\n{\r\n\t*dst++ = static_cast<std::byte>(sig.checksum);\r\n\t*dst++ = static_cast<std::byte>(sig.checksum >> 8);\r\n\t*dst++ = static_cast<std::byte>(sig.checksum >> 16);\r\n\t*dst++ = static_cast<std::byte>(sig.checksum >> 24);\r\n\t*dst++ = static_cast<std::byte>(sig.error);\r\n\t*dst++ = static_cast<std::byte>(sig.lastChunkSize);\r\n\t*dst++ = static_cast<std::byte>(0);\r\n\t*dst++ = static_cast<std::byte>(0);\r\n}\r\n\r\nvoid ByteSwapBlock(uint32_t *data)\r\n{\r\n\tfor (size_t i = 0; i < BlockSize; ++i)\r\n\t\tdata[i] = Swap32LE(data[i]);\r\n}\r\n\r\nvoid XorBlock(const uint32_t *shaResult, uint32_t *out)\r\n{\r\n\tfor (unsigned i = 0; i < BlockSize; ++i)\r\n\t\tout[i] ^= shaResult[i % SHA1HashSize];\r\n}\r\n\r\n} // namespace\r\n\r\nstd::size_t codec_decode(std::byte *pbSrcDst, std::size_t size, const char *pszPassword)\r\n{\r\n\tuint32_t buf[BlockSize];\r\n\tuint32_t dst[SHA1HashSize];\r\n\r\n\tSHA1Context context = CodecInitKey(pszPassword);\r\n\tif (size <= SignatureSize)\r\n\t\treturn 0;\r\n\tsize -= SignatureSize;\r\n\tif (size % BlockSize != 0)\r\n\t\treturn 0;\r\n\tfor (size_t i = 0; i < size; pbSrcDst += BlockSizeBytes, i += BlockSizeBytes) {\r\n\t\tmemcpy(buf, pbSrcDst, BlockSizeBytes);\r\n\t\tByteSwapBlock(buf);\r\n\t\tSHA1Result(context, dst);\r\n\t\tXorBlock(dst, buf);\r\n\t\tSHA1Calculate(context, buf);\r\n\t\tByteSwapBlock(buf);\r\n\t\tmemcpy(pbSrcDst, buf, BlockSizeBytes);\r\n\t}\r\n\r\n\tmemset(buf, 0, sizeof(buf));\r\n\tconst CodecSignature sig = GetCodecSignature(pbSrcDst);\r\n\tif (sig.error > 0) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tSHA1Result(context, dst);\r\n\tif (sig.checksum != dst[0]) {\r\n\t\tLogError(\"Checksum mismatch signature={} vs calculated={}\", sig.checksum, dst[0]);\r\n\t\tmemset(dst, 0, sizeof(dst));\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tsize += sig.lastChunkSize - BlockSizeBytes;\r\n\treturn size;\r\n}\r\n\r\nstd::size_t codec_get_encoded_len(std::size_t dwSrcBytes)\r\n{\r\n\tif (dwSrcBytes % BlockSizeBytes != 0)\r\n\t\tdwSrcBytes += BlockSizeBytes - (dwSrcBytes % BlockSizeBytes);\r\n\treturn dwSrcBytes + SignatureSize;\r\n}\r\n\r\nvoid codec_encode(std::byte *pbSrcDst, std::size_t size, std::size_t size64, const char *pszPassword)\r\n{\r\n\tuint32_t buf[BlockSize];\r\n\tuint32_t tmp[SHA1HashSize];\r\n\tuint32_t dst[SHA1HashSize];\r\n\r\n\tif (size64 != codec_get_encoded_len(size))\r\n\t\tapp_fatal(\"Invalid encode parameters\");\r\n\tSHA1Context context = CodecInitKey(pszPassword);\r\n\r\n\tsize_t lastChunk = 0;\r\n\twhile (size != 0) {\r\n\t\tconst size_t chunk = std::min(size, BlockSizeBytes);\r\n\t\tmemset(buf, 0, sizeof(buf));\r\n\t\tmemcpy(buf, pbSrcDst, chunk);\r\n\t\tByteSwapBlock(buf);\r\n\t\tSHA1Result(context, dst);\r\n\t\tSHA1Calculate(context, buf);\r\n\t\tXorBlock(dst, buf);\r\n\t\tByteSwapBlock(buf);\r\n\t\tmemcpy(pbSrcDst, buf, BlockSizeBytes);\r\n\t\tpbSrcDst += BlockSizeBytes;\r\n\t\tlastChunk = chunk;\r\n\t\tsize -= chunk;\r\n\t}\r\n\tmemset(buf, 0, sizeof(buf));\r\n\tSHA1Result(context, tmp);\r\n\tSetCodecSignature(pbSrcDst, CodecSignature { /*.checksum=*/*reinterpret_cast<uint32_t *>(tmp),\r\n\t                                /*.error=*/0,\r\n\t                                // lastChunk is at most 64 so will always fit in an 8 bit var\r\n\t                                /*.lastChunkSize=*/static_cast<uint8_t>(lastChunk) });\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/codec.h",
    "content": "/**\r\n * @file codec.h\r\n *\r\n * Interface of save game encryption algorithm.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n\r\nnamespace devilution {\r\n\r\nstd::size_t codec_decode(std::byte *pbSrcDst, std::size_t size, const char *pszPassword);\r\nstd::size_t codec_get_encoded_len(std::size_t dwSrcBytes);\r\nvoid codec_encode(std::byte *pbSrcDst, std::size_t size, std::size_t size_64, const char *pszPassword);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"DiabloUI/text_input.hpp\"\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"spells.h\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/string_or_view.hpp\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr Size SidePanelSize { 320, 352 };\r\n\r\nconstexpr Rectangle InfoBoxRect = { { 177, 46 }, { 288, 64 } };\r\n\r\nextern bool CharPanelButton[4];\r\nextern bool CharPanelButtonActive;\r\n\r\nextern int SpellbookTab;\r\n\r\nextern UiFlags InfoColor;\r\n\r\nextern StringOrView InfoString;\r\nextern StringOrView FloatingInfoString;\r\n\r\nextern Rectangle MainPanelButtonRect[8];\r\nextern Rectangle CharPanelButtonRect[4];\r\n\r\nextern bool MainPanelButtonDown;\r\nextern bool LevelButtonDown;\r\n\r\nextern std::optional<OwnedSurface> BottomBuffer;\r\nextern OptionalOwnedClxSpriteList GoldBoxBuffer;\r\n\r\nextern bool MainPanelFlag;\r\nextern bool ChatFlag;\r\nextern bool SpellbookFlag;\r\nextern bool CharFlag;\r\nextern bool SpellSelectFlag;\r\n\r\n[[nodiscard]] const Rectangle &GetMainPanel();\r\n[[nodiscard]] const Rectangle &GetLeftPanel();\r\n[[nodiscard]] const Rectangle &GetRightPanel();\r\nbool IsLeftPanelOpen();\r\nbool IsRightPanelOpen();\r\nvoid CalculatePanelAreas();\r\n\r\n/**\r\n * @brief Moves the mouse to the first attribute \"+\" button.\r\n */\r\nvoid FocusOnCharInfo();\r\nvoid OpenCharPanel();\r\nvoid CloseCharPanel();\r\nvoid ToggleCharPanel();\r\n\r\n/**\r\n * @brief Check if the UI can cover the game area entirely\r\n */\r\n[[nodiscard]] inline bool CanPanelsCoverView()\r\n{\r\n\tconst Rectangle &mainPanel = GetMainPanel();\r\n\treturn GetScreenWidth() <= mainPanel.size.width && GetScreenHeight() <= SidePanelSize.height + mainPanel.size.height;\r\n}\r\n\r\nvoid AddInfoBoxString(std::string_view str, bool floatingBox = false);\r\nvoid AddInfoBoxString(std::string &&str, bool floatingBox = false);\r\nvoid DrawPanelBox(const Surface &out, SDL_Rect srcRect, Point targetPosition);\r\nPoint GetPanelPosition(UiPanels panel, Point offset = { 0, 0 });\r\n\r\ntl::expected<void, std::string> InitMainPanel();\r\nvoid DrawMainPanel(const Surface &out);\r\n\r\n/**\r\n * Draws the control panel buttons in their current state. If the button is in the default\r\n * state draw it from the panel cel(extract its sub-rect). Else draw it from the buttons cel.\r\n */\r\nvoid DrawMainPanelButtons(const Surface &out);\r\n\r\n/**\r\n * Clears panel button flags.\r\n */\r\nvoid ResetMainPanelButtons();\r\n\r\n/**\r\n * Checks if the mouse cursor is within any of the panel buttons and flag it if so.\r\n */\r\nvoid CheckMainPanelButton();\r\n\r\nvoid CheckMainPanelButtonDead();\r\nvoid DoAutoMap();\r\nvoid CycleAutomapType();\r\n\r\n/**\r\n * Checks the mouse cursor position within the control panel and sets information\r\n * strings if needed.\r\n */\r\nvoid CheckPanelInfo();\r\n\r\n/**\r\n * Check if the mouse is within a control panel button that's flagged.\r\n * Takes appropriate action if so.\r\n */\r\nvoid CheckMainPanelButtonUp();\r\nvoid FreeControlPan();\r\n\r\n/**\r\n * Sets a string to be drawn in the info box and then draws it.\r\n */\r\nvoid DrawInfoBox(const Surface &out);\r\nvoid DrawFloatingInfoBox(const Surface &out);\r\nvoid CheckLevelButton();\r\nvoid CheckLevelButtonUp();\r\nvoid DrawLevelButton(const Surface &out);\r\nvoid CheckChrBtns();\r\nvoid ReleaseChrBtns(bool addAllStatPoints);\r\nvoid DrawDurIcon(const Surface &out);\r\nvoid RedBack(const Surface &out);\r\nvoid DrawDeathText(const Surface &out);\r\nvoid DrawSpellBook(const Surface &out);\r\n\r\nextern Rectangle CharPanelButtonRect[4];\r\n\r\nbool CheckKeypress(SDL_Keycode vkey);\r\nvoid DiabloHotkeyMsg(uint32_t dwMsg);\r\nvoid DrawChatBox(const Surface &out);\r\nbool CheckMuteButton();\r\nvoid CheckMuteButtonUp();\r\nvoid TypeChatMessage();\r\nvoid ResetChat();\r\nbool IsChatActive();\r\nbool IsChatAvailable();\r\nbool HandleTalkTextInputEvent(const SDL_Event &event);\r\n\r\n/**\r\n * Draws the top dome of the life flask (that part that protrudes out of the control panel).\r\n * The empty flask cel is drawn from the top of the flask to the fill level (there is always a 2 pixel \"air gap\") and\r\n * the filled flask cel is drawn from that level to the top of the control panel if required.\r\n */\r\nvoid DrawLifeFlaskUpper(const Surface &out);\r\n\r\n/**\r\n * Controls the drawing of the area of the life flask within the control panel.\r\n * First sets the fill amount then draws the empty flask cel portion then the filled\r\n * flask portion.\r\n */\r\nvoid DrawLifeFlaskLower(const Surface &out, bool drawFilledPortion);\r\n\r\n/**\r\n * Draws the top dome of the mana flask (that part that protrudes out of the control panel).\r\n * The empty flask cel is drawn from the top of the flask to the fill level (there is always a 2 pixel \"air gap\") and\r\n * the filled flask cel is drawn from that level to the top of the control panel if required.\r\n */\r\nvoid DrawManaFlaskUpper(const Surface &out);\r\n\r\n/**\r\n * Controls the drawing of the area of the mana flask within the control panel.\r\n */\r\nvoid DrawManaFlaskLower(const Surface &out, bool drawFilledPortion);\r\n\r\n/**\r\n * Controls drawing of current / max values (health, mana) within the control panel.\r\n */\r\nvoid DrawFlaskValues(const Surface &out, Point pos, int currValue, int maxValue);\r\n\r\n/**\r\n * @brief calls on the active player object to update HP/Mana percentage variables\r\n *\r\n * This is used to ensure that DrawFlaskAbovePanel routines display an accurate representation of the players health/mana\r\n *\r\n * @see Player::UpdateHitPointPercentage() and Player::UpdateManaPercentage()\r\n */\r\nvoid UpdateLifeManaPercent();\r\n\r\nextern bool DropGoldFlag;\r\n\r\nvoid DrawGoldSplit(const Surface &out);\r\nvoid control_drop_gold(SDL_Keycode vkey);\r\nvoid OpenGoldDrop(int8_t invIndex, int max);\r\nvoid CloseGoldDrop();\r\nbool HandleGoldDropTextInputEvent(const SDL_Event &event);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_chat.cpp",
    "content": "#include \"control_chat.hpp\"\r\n#include \"control.hpp\"\r\n#include \"control_panel.hpp\"\r\n\r\n#include \"control/control_chat_commands.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"options.h\"\r\n#include \"panels/console.hpp\"\r\n#include \"panels/mainpanel.hpp\"\r\n#include \"quick_messages.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::optional<TextInputState> ChatInputState;\r\nchar TalkMessage[MAX_SEND_STR_LEN];\r\nbool TalkButtonsDown[3];\r\nint sgbPlrTalkTbl;\r\nbool WhisperList[MAX_PLRS];\r\nOptionalOwnedClxSpriteList talkButtons;\r\n\r\nnamespace {\r\n\r\nchar TalkSave[8][MAX_SEND_STR_LEN];\r\nuint8_t TalkSaveIndex;\r\nuint8_t NextTalkSave;\r\nTextInputCursorState ChatCursor;\r\n\r\nint MuteButtons = 3;\r\nint MuteButtonPadding = 2;\r\nRectangle MuteButtonRect { { 172, 69 }, { 61, 16 } };\r\n\r\nvoid ResetChatMessage()\r\n{\r\n\tif (CheckChatCommand(TalkMessage))\r\n\t\treturn;\r\n\r\n\tuint32_t pmask = 0;\r\n\r\n\tfor (size_t i = 0; i < Players.size(); i++) {\r\n\t\tif (WhisperList[i])\r\n\t\t\tpmask |= 1 << i;\r\n\t}\r\n\r\n\tNetSendCmdString(pmask, TalkMessage);\r\n}\r\n\r\nvoid ControlPressEnter()\r\n{\r\n\tif (TalkMessage[0] != 0) {\r\n\t\tResetChatMessage();\r\n\t\tuint8_t i = 0;\r\n\t\tfor (; i < 8; i++) {\r\n\t\t\tif (strcmp(TalkSave[i], TalkMessage) == 0)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tif (i >= 8) {\r\n\t\t\tstrcpy(TalkSave[NextTalkSave], TalkMessage);\r\n\t\t\tNextTalkSave++;\r\n\t\t\tNextTalkSave &= 7;\r\n\t\t} else {\r\n\t\t\tuint8_t talkSave = NextTalkSave - 1;\r\n\t\t\ttalkSave &= 7;\r\n\t\t\tif (i != talkSave) {\r\n\t\t\t\tstrcpy(TalkSave[i], TalkSave[talkSave]);\r\n\t\t\t\t*BufCopy(TalkSave[talkSave], ChatInputState->value()) = '\\0';\r\n\t\t\t}\r\n\t\t}\r\n\t\tTalkMessage[0] = '\\0';\r\n\t\tTalkSaveIndex = NextTalkSave;\r\n\t}\r\n\tResetChat();\r\n}\r\n\r\nvoid ControlUpDown(int v)\r\n{\r\n\tfor (int i = 0; i < 8; i++) {\r\n\t\tTalkSaveIndex = (v + TalkSaveIndex) & 7;\r\n\t\tif (TalkSave[TalkSaveIndex][0] != 0) {\r\n\t\t\tChatInputState->assign(TalkSave[TalkSaveIndex]);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DrawChatBox(const Surface &out)\r\n{\r\n\tif (!ChatFlag)\r\n\t\treturn;\r\n\r\n\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\r\n\tDrawPanelBox(out, MakeSdlRect(175, sgbPlrTalkTbl + 20, 294, 5), mainPanelPosition + Displacement { 175, 4 });\r\n\tint off = 0;\r\n\tfor (int i = 293; i > 283; off++, i--) {\r\n\t\tDrawPanelBox(out, MakeSdlRect((off / 2) + 175, sgbPlrTalkTbl + off + 25, i, 1), mainPanelPosition + Displacement { (off / 2) + 175, off + 9 });\r\n\t}\r\n\tDrawPanelBox(out, MakeSdlRect(185, sgbPlrTalkTbl + 35, 274, 30), mainPanelPosition + Displacement { 185, 19 });\r\n\tDrawPanelBox(out, MakeSdlRect(180, sgbPlrTalkTbl + 65, 284, 5), mainPanelPosition + Displacement { 180, 49 });\r\n\tfor (int i = 0; i < 10; i++) {\r\n\t\tDrawPanelBox(out, MakeSdlRect(180, sgbPlrTalkTbl + i + 70, i + 284, 1), mainPanelPosition + Displacement { 180, i + 54 });\r\n\t}\r\n\tDrawPanelBox(out, MakeSdlRect(170, sgbPlrTalkTbl + 80, 310, 55), mainPanelPosition + Displacement { 170, 64 });\r\n\r\n\tint x = mainPanelPosition.x + 200;\r\n\tconst int y = mainPanelPosition.y + 10;\r\n\r\n\tconst uint32_t len = DrawString(out, TalkMessage, { { x, y }, { 250, 39 } },\r\n\t    {\r\n\t        .flags = UiFlags::ColorWhite | UiFlags::PentaCursor,\r\n\t        .lineHeight = 13,\r\n\t        .cursorPosition = static_cast<int>(ChatCursor.position),\r\n\t        .highlightRange = { static_cast<int>(ChatCursor.selection.begin), static_cast<int>(ChatCursor.selection.end) },\r\n\t    });\r\n\tChatInputState->truncate(len);\r\n\r\n\tx += 46;\r\n\tint talkBtn = 0;\r\n\tfor (size_t i = 0; i < Players.size(); i++) {\r\n\t\tPlayer &player = Players[i];\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tcontinue;\r\n\r\n\t\tconst UiFlags color = player.friendlyMode ? UiFlags::ColorWhitegold : UiFlags::ColorRed;\r\n\t\tconst Point talkPanPosition = mainPanelPosition + Displacement { 172, 84 + 18 * talkBtn };\r\n\t\tif (WhisperList[i]) {\r\n\t\t\t// the normal (unpressed) voice button is pre-rendered on the panel, only need to draw over it when the button is held\r\n\t\t\tif (TalkButtonsDown[talkBtn]) {\r\n\t\t\t\tconst unsigned spriteIndex = talkBtn == 0 ? 2 : 3; // the first button sprite includes a tip from the devils wing so is different to the rest.\r\n\t\t\t\tClxDraw(out, talkPanPosition, (*talkButtons)[spriteIndex]);\r\n\r\n\t\t\t\t// Draw the translated string over the top of the default (english) button. This graphic is inset to avoid overlapping the wingtip, letting\r\n\t\t\t\t// the first button be treated the same as the other two further down the panel.\r\n\t\t\t\tRenderClxSprite(out, (*TalkButton)[2], talkPanPosition + Displacement { 4, -15 });\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tunsigned spriteIndex = talkBtn == 0 ? 0 : 1; // the first button sprite includes a tip from the devils wing so is different to the rest.\r\n\t\t\tif (TalkButtonsDown[talkBtn])\r\n\t\t\t\tspriteIndex += 4; // held button sprites are at index 4 and 5 (with and without wingtip respectively)\r\n\t\t\tClxDraw(out, talkPanPosition, (*talkButtons)[spriteIndex]);\r\n\r\n\t\t\t// Draw the translated string over the top of the default (english) button. This graphic is inset to avoid overlapping the wingtip, letting\r\n\t\t\t// the first button be treated the same as the other two further down the panel.\r\n\t\t\tRenderClxSprite(out, (*TalkButton)[TalkButtonsDown[talkBtn] ? 1 : 0], talkPanPosition + Displacement { 4, -15 });\r\n\t\t}\r\n\t\tif (player.plractive) {\r\n\t\t\tDrawString(out, player._pName, { { x, y + 60 + talkBtn * 18 }, { 204, 0 } }, { .flags = color });\r\n\t\t}\r\n\r\n\t\ttalkBtn++;\r\n\t}\r\n}\r\n\r\nbool CheckMuteButton()\r\n{\r\n\tif (!ChatFlag)\r\n\t\treturn false;\r\n\r\n\tRectangle buttons = MuteButtonRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, buttons);\r\n\r\n\tbuttons.size.height = (MuteButtons * buttons.size.height) + ((MuteButtons - 1) * MuteButtonPadding);\r\n\r\n\tif (!buttons.contains(MousePosition))\r\n\t\treturn false;\r\n\r\n\tfor (bool &talkButtonDown : TalkButtonsDown) {\r\n\t\ttalkButtonDown = false;\r\n\t}\r\n\r\n\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\r\n\tTalkButtonsDown[(MousePosition.y - (69 + mainPanelPosition.y)) / 18] = true;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid CheckMuteButtonUp()\r\n{\r\n\tif (!ChatFlag)\r\n\t\treturn;\r\n\r\n\tfor (bool &talkButtonDown : TalkButtonsDown)\r\n\t\ttalkButtonDown = false;\r\n\r\n\tRectangle buttons = MuteButtonRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, buttons);\r\n\r\n\tbuttons.size.height = (MuteButtons * buttons.size.height) + ((MuteButtons - 1) * MuteButtonPadding);\r\n\r\n\tif (!buttons.contains(MousePosition))\r\n\t\treturn;\r\n\r\n\tint off = (MousePosition.y - buttons.position.y) / (MuteButtonRect.size.height + MuteButtonPadding);\r\n\r\n\tsize_t playerId = 0;\r\n\tfor (; playerId < Players.size() && off != -1; ++playerId) {\r\n\t\tif (playerId != MyPlayerId)\r\n\t\t\toff--;\r\n\t}\r\n\tif (playerId > 0 && playerId <= Players.size())\r\n\t\tWhisperList[playerId - 1] = !WhisperList[playerId - 1];\r\n}\r\n\r\nvoid TypeChatMessage()\r\n{\r\n\tif (!IsChatAvailable())\r\n\t\treturn;\r\n\r\n\tChatFlag = true;\r\n\tTalkMessage[0] = '\\0';\r\n\tChatInputState.emplace(TextInputState::Options {\r\n\t    .value = TalkMessage,\r\n\t    .cursor = &ChatCursor,\r\n\t    .maxLength = sizeof(TalkMessage) - 1 });\r\n\tfor (bool &talkButtonDown : TalkButtonsDown) {\r\n\t\ttalkButtonDown = false;\r\n\t}\r\n\tsgbPlrTalkTbl = GetMainPanel().size.height + PanelPaddingHeight;\r\n\tRedrawEverything();\r\n\tTalkSaveIndex = NextTalkSave;\r\n\r\n\tSDL_Rect rect = MakeSdlRect(GetMainPanel().position.x + 200, GetMainPanel().position.y + 22, 0, 27);\r\n\tSDL_SetTextInputArea(ghMainWnd, &rect, /*cursor=*/0);\r\n\tSDLC_StartTextInput(ghMainWnd);\r\n}\r\n\r\nvoid ResetChat()\r\n{\r\n\tChatFlag = false;\r\n\tSDLC_StopTextInput(ghMainWnd);\r\n\tChatCursor = {};\r\n\tChatInputState = std::nullopt;\r\n\tsgbPlrTalkTbl = 0;\r\n\tRedrawEverything();\r\n}\r\n\r\nbool IsChatActive()\r\n{\r\n\tif (!IsChatAvailable())\r\n\t\treturn false;\r\n\r\n\tif (!ChatFlag)\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CheckKeypress(SDL_Keycode vkey)\r\n{\r\n\tif (!IsChatAvailable())\r\n\t\treturn false;\r\n\tif (!ChatFlag)\r\n\t\treturn false;\r\n\r\n\tswitch (vkey) {\r\n\tcase SDLK_ESCAPE:\r\n\t\tResetChat();\r\n\t\treturn true;\r\n\tcase SDLK_RETURN:\r\n\tcase SDLK_KP_ENTER:\r\n\t\tControlPressEnter();\r\n\t\treturn true;\r\n\tcase SDLK_DOWN:\r\n\t\tControlUpDown(1);\r\n\t\treturn true;\r\n\tcase SDLK_UP:\r\n\t\tControlUpDown(-1);\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn vkey >= SDLK_SPACE && vkey <= SDLK_Z;\r\n\t}\r\n}\r\n\r\nvoid DiabloHotkeyMsg(uint32_t dwMsg)\r\n{\r\n\tassert(dwMsg < QuickMessages.size());\r\n\r\n#ifdef _DEBUG\r\n\tconstexpr std::string_view LuaPrefix = \"/lua \";\r\n\tfor (const std::string &msg : GetOptions().Chat.szHotKeyMsgs[dwMsg]) {\r\n\t\tif (!msg.starts_with(LuaPrefix)) continue;\r\n\t\tInitConsole();\r\n\t\tRunInConsole(std::string_view(msg).substr(LuaPrefix.size()));\r\n\t}\r\n#endif\r\n\r\n\tif (!IsChatAvailable()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (const std::string &msg : GetOptions().Chat.szHotKeyMsgs[dwMsg]) {\r\n#ifdef _DEBUG\r\n\t\tif (msg.starts_with(LuaPrefix)) continue;\r\n#endif\r\n\t\tchar charMsg[MAX_SEND_STR_LEN];\r\n\t\tCopyUtf8(charMsg, msg, sizeof(charMsg));\r\n\t\tNetSendCmdString(0xFFFFFF, charMsg);\r\n\t}\r\n}\r\n\r\nbool IsChatAvailable()\r\n{\r\n\treturn gbIsMultiplayer;\r\n}\r\n\r\nbool HandleTalkTextInputEvent(const SDL_Event &event)\r\n{\r\n\treturn HandleInputEvent(event, ChatInputState);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_chat.hpp",
    "content": "#pragma once\r\n\r\n#include <optional>\r\n#include <string_view>\r\n\r\n#include \"DiabloUI/text_input.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"msg.h\"\r\n#include \"multi.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nextern OptionalOwnedClxSpriteList talkButtons;\r\nextern std::optional<TextInputState> ChatInputState;\r\nextern char TalkMessage[MAX_SEND_STR_LEN];\r\nextern bool TalkButtonsDown[3];\r\nextern int sgbPlrTalkTbl;\r\nextern bool WhisperList[MAX_PLRS];\r\n\r\nbool CheckChatCommand(std::string_view text);\r\n\r\ntemplate <typename InputStateType>\r\nbool HandleInputEvent(const SDL_Event &event, std::optional<InputStateType> &inputState)\r\n{\r\n\tif (!inputState) {\r\n\t\treturn false; // No input state to handle\r\n\t}\r\n\r\n\tif constexpr (std::is_same_v<InputStateType, TextInputState>) {\r\n\t\treturn HandleTextInputEvent(event, *inputState);\r\n\t} else if constexpr (std::is_same_v<InputStateType, NumberInputState>) {\r\n\t\treturn HandleNumberInputEvent(event, *inputState);\r\n\t}\r\n\r\n\treturn false; // Unknown input state type\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_chat_commands.cpp",
    "content": "#include \"control_chat_commands.hpp\"\r\n#include \"control.hpp\"\r\n\r\n#include \"diablo_msg.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/parse_int.hpp\"\r\n#include \"utils/str_case.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct TextCmdItem {\r\n\tconst std::string text;\r\n\tconst std::string description;\r\n\tconst std::string requiredParameter;\r\n\tstd::string (*actionProc)(const std::string_view);\r\n};\r\n\r\nextern std::vector<TextCmdItem> TextCmdList;\r\n\r\nstd::string TextCmdHelp(const std::string_view parameter)\r\n{\r\n\tif (parameter.empty()) {\r\n\t\tstd::string ret;\r\n\t\tStrAppend(ret, _(\"Available Commands:\"));\r\n\t\tfor (const TextCmdItem &textCmd : TextCmdList) {\r\n\t\t\tStrAppend(ret, \" \", _(textCmd.text));\r\n\t\t}\r\n\t\treturn ret;\r\n\t}\r\n\tauto textCmdIterator = c_find_if(TextCmdList, [&](const TextCmdItem &elem) { return elem.text == parameter; });\r\n\tif (textCmdIterator == TextCmdList.end())\r\n\t\treturn StrCat(_(\"Command \"), parameter, _(\" is unknown.\"));\r\n\tauto &textCmdItem = *textCmdIterator;\r\n\tif (textCmdItem.requiredParameter.empty())\r\n\t\treturn StrCat(_(\"Description: \"), _(textCmdItem.description), _(\"\\nParameters: No additional parameter needed.\"));\r\n\treturn StrCat(_(\"Description: \"), _(textCmdItem.description), _(\"\\nParameters: \"), _(textCmdItem.requiredParameter));\r\n}\r\n\r\nvoid AppendArenaOverview(std::string &ret)\r\n{\r\n\tfor (int arena = SL_FIRST_ARENA; arena <= SL_LAST; arena++) {\r\n\t\tStrAppend(ret, \"\\n\", arena - SL_FIRST_ARENA + 1, \" (\", QuestLevelNames[arena], \")\");\r\n\t}\r\n}\r\n\r\nstd::string TextCmdArena(const std::string_view parameter)\r\n{\r\n\tstd::string ret;\r\n\tif (!gbIsMultiplayer) {\r\n\t\tStrAppend(ret, _(\"Arenas are only supported in multiplayer.\"));\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tif (parameter.empty()) {\r\n\t\tStrAppend(ret, _(\"What arena do you want to visit?\"));\r\n\t\tAppendArenaOverview(ret);\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tconst ParseIntResult<int> parsedParam = ParseInt<int>(parameter, /*min=*/0);\r\n\tconst _setlevels arenaLevel = parsedParam.has_value() ? static_cast<_setlevels>(parsedParam.value() - 1 + SL_FIRST_ARENA) : _setlevels::SL_NONE;\r\n\tif (!IsArenaLevel(arenaLevel)) {\r\n\t\tStrAppend(ret, _(\"Invalid arena-number. Valid numbers are:\"));\r\n\t\tAppendArenaOverview(ret);\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tif (!MyPlayer->isOnLevel(0) && !MyPlayer->isOnArenaLevel()) {\r\n\t\tStrAppend(ret, _(\"To enter a arena, you need to be in town or another arena.\"));\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tsetlvltype = GetArenaLevelType(arenaLevel);\r\n\tStartNewLvl(*MyPlayer, WM_DIABSETLVL, arenaLevel);\r\n\treturn ret;\r\n}\r\n\r\nstd::string TextCmdArenaPot(const std::string_view parameter)\r\n{\r\n\tstd::string ret;\r\n\tif (!gbIsMultiplayer) {\r\n\t\tStrAppend(ret, _(\"Arenas are only supported in multiplayer.\"));\r\n\t\treturn ret;\r\n\t}\r\n\tconst int numPots = ParseInt<int>(parameter, /*min=*/1).value_or(1);\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tfor (int potNumber = numPots; potNumber > 0; potNumber--) {\r\n\t\tItem item {};\r\n\t\tInitializeItem(item, IDI_ARENAPOT);\r\n\t\tGenerateNewSeed(item);\r\n\t\titem.updateRequiredStatsCacheForPlayer(myPlayer);\r\n\r\n\t\tif (!AutoPlaceItemInBelt(myPlayer, item, true, true) && !AutoPlaceItemInInventory(myPlayer, item, true)) {\r\n\t\t\tbreak; // inventory is full\r\n\t\t}\r\n\t}\r\n\r\n\treturn ret;\r\n}\r\n\r\nstd::string TextCmdInspect(const std::string_view parameter)\r\n{\r\n\tstd::string ret;\r\n\tif (!gbIsMultiplayer) {\r\n\t\tStrAppend(ret, _(\"Inspecting only supported in multiplayer.\"));\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tif (parameter.empty()) {\r\n\t\tStrAppend(ret, _(\"Stopped inspecting players.\"));\r\n\t\tInspectPlayer = MyPlayer;\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tconst std::string param = AsciiStrToLower(parameter);\r\n\tauto it = c_find_if(Players, [&param](const Player &player) {\r\n\t\treturn AsciiStrToLower(player._pName) == param;\r\n\t});\r\n\tif (it == Players.end()) {\r\n\t\tit = c_find_if(Players, [&param](const Player &player) {\r\n\t\t\treturn AsciiStrToLower(player._pName).find(param) != std::string::npos;\r\n\t\t});\r\n\t}\r\n\tif (it == Players.end()) {\r\n\t\tStrAppend(ret, _(\"No players found with such a name\"));\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tPlayer &player = *it;\r\n\tInspectPlayer = &player;\r\n\tStrAppend(ret, _(\"Inspecting player: \"));\r\n\tStrAppend(ret, player._pName);\r\n\tOpenCharPanel();\r\n\tif (!SpellbookFlag)\r\n\t\tinvflag = true;\r\n\tRedrawEverything();\r\n\treturn ret;\r\n}\r\n\r\nbool IsQuestEnabled(const Quest &quest)\r\n{\r\n\tswitch (quest._qidx) {\r\n\tcase Q_FARMER:\r\n\t\treturn gbIsHellfire && !sgGameInitInfo.bCowQuest;\r\n\tcase Q_JERSEY:\r\n\t\treturn gbIsHellfire && sgGameInitInfo.bCowQuest;\r\n\tcase Q_GIRL:\r\n\t\treturn gbIsHellfire && sgGameInitInfo.bTheoQuest;\r\n\tcase Q_CORNSTN:\r\n\t\treturn gbIsHellfire && !gbIsMultiplayer;\r\n\tcase Q_GRAVE:\r\n\tcase Q_DEFILER:\r\n\tcase Q_NAKRUL:\r\n\t\treturn gbIsHellfire;\r\n\tcase Q_TRADER:\r\n\t\treturn false;\r\n\tdefault:\r\n\t\treturn quest._qactive != QUEST_NOTAVAIL;\r\n\t}\r\n}\r\n\r\nstd::string TextCmdLevelSeed(const std::string_view parameter)\r\n{\r\n\tconst std::string_view levelType = setlevel ? \"set level\" : \"dungeon level\";\r\n\r\n\tchar gameId[] = {\r\n\t\tstatic_cast<char>((sgGameInitInfo.programid >> 24) & 0xFF),\r\n\t\tstatic_cast<char>((sgGameInitInfo.programid >> 16) & 0xFF),\r\n\t\tstatic_cast<char>((sgGameInitInfo.programid >> 8) & 0xFF),\r\n\t\tstatic_cast<char>(sgGameInitInfo.programid & 0xFF),\r\n\t\t'\\0'\r\n\t};\r\n\r\n\tconst std::string_view mode = gbIsMultiplayer ? \"MP\" : \"SP\";\r\n\tconst std::string_view questPool = UseMultiplayerQuests() ? \"MP\" : \"Full\";\r\n\r\n\tuint32_t questFlags = 0;\r\n\tfor (const Quest &quest : Quests) {\r\n\t\tquestFlags <<= 1;\r\n\t\tif (IsQuestEnabled(quest))\r\n\t\t\tquestFlags |= 1;\r\n\t}\r\n\r\n\treturn StrCat(\r\n\t    \"Seedinfo for \", levelType, \" \", currlevel, \"\\n\",\r\n\t    \"seed: \", DungeonSeeds[currlevel], \"\\n\",\r\n#ifdef _DEBUG\r\n\t    \"Mid1: \", glMid1Seed[currlevel], \"\\n\",\r\n\t    \"Mid2: \", glMid2Seed[currlevel], \"\\n\",\r\n\t    \"Mid3: \", glMid3Seed[currlevel], \"\\n\",\r\n\t    \"End: \", glEndSeed[currlevel], \"\\n\",\r\n#endif\r\n\t    \"\\n\",\r\n\t    gameId, \" \", mode, \"\\n\",\r\n\t    questPool, \" quests: \", questFlags, \"\\n\",\r\n\t    \"Storybook: \", DungeonSeeds[16]);\r\n}\r\n\r\nstd::string TextCmdPing(const std::string_view parameter)\r\n{\r\n\tstd::string ret;\r\n\tconst std::string param = AsciiStrToLower(parameter);\r\n\tauto it = c_find_if(Players, [&param](const Player &player) {\r\n\t\treturn AsciiStrToLower(player._pName) == param;\r\n\t});\r\n\tif (it == Players.end()) {\r\n\t\tit = c_find_if(Players, [&param](const Player &player) {\r\n\t\t\treturn AsciiStrToLower(player._pName).find(param) != std::string::npos;\r\n\t\t});\r\n\t}\r\n\tif (it == Players.end()) {\r\n\t\tStrAppend(ret, _(\"No players found with such a name\"));\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tPlayer &player = *it;\r\n\tDvlNetLatencies latencies = DvlNet_GetLatencies(player.getId());\r\n\r\n\tStrAppend(ret, fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} means: Character Name */ \"Latency statistics for {:s}:\")), player.name()));\r\n\r\n\tStrAppend(ret, \"\\n\", fmt::format(fmt::runtime(_(/* TRANSLATORS: Network connectivity statistics */ \"Echo latency: {:d} ms\")), latencies.echoLatency));\r\n\r\n\tif (latencies.providerLatency) {\r\n\t\tif (latencies.isRelayed && *latencies.isRelayed) {\r\n\t\t\tStrAppend(ret, \"\\n\", fmt::format(fmt::runtime(_(/* TRANSLATORS: Network connectivity statistics */ \"Provider latency: {:d} ms (Relayed)\")), *latencies.providerLatency));\r\n\t\t} else {\r\n\t\t\tStrAppend(ret, \"\\n\", fmt::format(fmt::runtime(_(/* TRANSLATORS: Network connectivity statistics */ \"Provider latency: {:d} ms\")), *latencies.providerLatency));\r\n\t\t}\r\n\t}\r\n\r\n\treturn ret;\r\n}\r\n\r\nstd::vector<TextCmdItem> TextCmdList = {\r\n\t{ \"/help\", N_(\"Prints help overview or help for a specific command.\"), N_(\"[command]\"), &TextCmdHelp },\r\n\t{ \"/arena\", N_(\"Enter a PvP Arena.\"), N_(\"<arena-number>\"), &TextCmdArena },\r\n\t{ \"/arenapot\", N_(\"Gives Arena Potions.\"), N_(\"<number>\"), &TextCmdArenaPot },\r\n\t{ \"/inspect\", N_(\"Inspects stats and equipment of another player.\"), N_(\"<player name>\"), &TextCmdInspect },\r\n\t{ \"/seedinfo\", N_(\"Show seed infos for current level.\"), \"\", &TextCmdLevelSeed },\r\n\t{ \"/ping\", N_(\"Show latency statistics for another player.\"), N_(\"<player name>\"), &TextCmdPing },\r\n};\r\n\r\n} // namespace\r\n\r\nbool CheckChatCommand(const std::string_view text)\r\n{\r\n\tif (text.size() < 1 || text[0] != '/')\r\n\t\treturn false;\r\n\r\n\tauto textCmdIterator = c_find_if(TextCmdList, [&](const TextCmdItem &elem) { return text.find(elem.text) == 0 && (text.length() == elem.text.length() || text[elem.text.length()] == ' '); });\r\n\tif (textCmdIterator == TextCmdList.end()) {\r\n\t\tInitDiabloMsg(StrCat(_(\"Command \"), \"\\\"\", text, \"\\\"\", _(\" is unknown.\")));\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconst TextCmdItem &textCmd = *textCmdIterator;\r\n\tstd::string_view parameter = \"\";\r\n\tif (text.length() > (textCmd.text.length() + 1))\r\n\t\tparameter = text.substr(textCmd.text.length() + 1);\r\n\tconst std::string result = textCmd.actionProc(parameter);\r\n\tif (result != \"\")\r\n\t\tInitDiabloMsg(result);\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_chat_commands.hpp",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\nnamespace devilution {\r\n\r\nbool CheckChatCommand(std::string_view text);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_flasks.cpp",
    "content": "#include \"control_flasks.hpp\"\r\n#include \"control.hpp\"\r\n\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::optional<OwnedSurface> pLifeBuff;\r\nstd::optional<OwnedSurface> pManaBuff;\r\n\r\nnamespace {\r\n\r\nRectangle FlaskTopRect { { 11, 3 }, { 62, 13 } };\r\nRectangle FlaskBottomRect { { 0, 16 }, { 88, 69 } };\r\n\r\n/**\r\n * Draws the dome of the flask that protrudes above the panel top line.\r\n * It draws a rectangle of fixed width 59 and height 'h' from the source buffer\r\n * into the target buffer.\r\n * @param out The target buffer.\r\n * @param celBuf Buffer of the flask cel.\r\n * @param targetPosition Target buffer coordinate.\r\n */\r\nvoid DrawFlaskAbovePanel(const Surface &out, const Surface &celBuf, Point targetPosition)\r\n{\r\n\tout.BlitFromSkipColorIndexZero(celBuf, MakeSdlRect(0, 0, celBuf.w(), celBuf.h()), targetPosition);\r\n}\r\n\r\n/**\r\n * @brief Draws the part of the life/mana flasks protruding above the bottom panel\r\n * @see DrawFlaskLower()\r\n * @param out The display region to draw to\r\n * @param sourceBuffer A sprite representing the appropriate background/empty flask style\r\n * @param offset X coordinate offset for where the flask should be drawn\r\n * @param fillPer How full the flask is (a value from 0 to 81)\r\n */\r\nvoid DrawFlaskUpper(const Surface &out, const Surface &sourceBuffer, int offset, int fillPer)\r\n{\r\n\tconst Rectangle &rect = FlaskTopRect;\r\n\tconst int emptyRows = std::clamp(81 - fillPer, 0, rect.size.height);\r\n\tconst int filledRows = rect.size.height - emptyRows;\r\n\r\n\t// Draw the empty part of the flask\r\n\tDrawFlaskAbovePanel(out,\r\n\t    sourceBuffer.subregion(rect.position.x, rect.position.y, rect.size.width, rect.size.height),\r\n\t    GetMainPanel().position + Displacement { offset, -rect.size.height });\r\n\r\n\t// Draw the filled part of the flask over the empty part\r\n\tif (filledRows > 0) {\r\n\t\tDrawFlaskAbovePanel(out,\r\n\t\t    BottomBuffer->subregion(offset, rect.position.y + emptyRows, rect.size.width, filledRows),\r\n\t\t    GetMainPanel().position + Displacement { offset, -rect.size.height + emptyRows });\r\n\t}\r\n}\r\n\r\n/**\r\n * Draws a section of the empty flask cel on top of the panel to create the illusion\r\n * of the flask getting empty. This function takes a cel and draws a\r\n * horizontal stripe of height (max-min) onto the given buffer.\r\n * @param out Target buffer.\r\n * @param celBuf Buffer of the flask cel.\r\n * @param targetPosition Target buffer coordinate.\r\n */\r\nvoid DrawFlaskOnPanel(const Surface &out, const Surface &celBuf, Point targetPosition)\r\n{\r\n\tout.BlitFrom(celBuf, MakeSdlRect(0, 0, celBuf.w(), celBuf.h()), targetPosition);\r\n}\r\n\r\n/**\r\n * @brief Draws the part of the life/mana flasks inside the bottom panel\r\n * @see DrawFlaskUpper()\r\n * @param out The display region to draw to\r\n * @param sourceBuffer A sprite representing the appropriate background/empty flask style\r\n * @param offset X coordinate offset for where the flask should be drawn\r\n * @param fillPer How full the flask is (a value from 0 to 80)\r\n * @param drawFilledPortion Indicates whether to draw the filled portion of the flask\r\n */\r\nvoid DrawFlaskLower(const Surface &out, const Surface &sourceBuffer, int offset, int fillPer, bool drawFilledPortion)\r\n{\r\n\tconst Rectangle &rect = FlaskBottomRect;\r\n\tconst int filledRows = std::clamp(fillPer, 0, rect.size.height);\r\n\tconst int emptyRows = rect.size.height - filledRows;\r\n\r\n\t// Draw the empty part of the flask\r\n\tif (emptyRows > 0) {\r\n\t\tDrawFlaskOnPanel(out,\r\n\t\t    sourceBuffer.subregion(rect.position.x, rect.position.y, rect.size.width, emptyRows),\r\n\t\t    GetMainPanel().position + Displacement { offset, 0 });\r\n\t}\r\n\r\n\t// Draw the filled part of the flask\r\n\tif (drawFilledPortion && filledRows > 0) {\r\n\t\tDrawFlaskOnPanel(out,\r\n\t\t    BottomBuffer->subregion(offset, rect.position.y + emptyRows, rect.size.width, filledRows),\r\n\t\t    GetMainPanel().position + Displacement { offset, emptyRows });\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DrawLifeFlaskUpper(const Surface &out)\r\n{\r\n\tconstexpr int LifeFlaskUpperOffset = 107;\r\n\tDrawFlaskUpper(out, *pLifeBuff, LifeFlaskUpperOffset, MyPlayer->_pHPPer);\r\n}\r\n\r\nvoid DrawManaFlaskUpper(const Surface &out)\r\n{\r\n\tconstexpr int ManaFlaskUpperOffset = 475;\r\n\tDrawFlaskUpper(out, *pManaBuff, ManaFlaskUpperOffset, MyPlayer->_pManaPer);\r\n}\r\n\r\nvoid DrawLifeFlaskLower(const Surface &out, bool drawFilledPortion)\r\n{\r\n\tconstexpr int LifeFlaskLowerOffset = 96;\r\n\tDrawFlaskLower(out, *pLifeBuff, LifeFlaskLowerOffset, MyPlayer->_pHPPer, drawFilledPortion);\r\n}\r\n\r\nvoid DrawManaFlaskLower(const Surface &out, bool drawFilledPortion)\r\n{\r\n\tconstexpr int ManaFlaskLowerOffset = 464;\r\n\tDrawFlaskLower(out, *pManaBuff, ManaFlaskLowerOffset, MyPlayer->_pManaPer, drawFilledPortion);\r\n}\r\n\r\nvoid DrawFlaskValues(const Surface &out, Point pos, int currValue, int maxValue)\r\n{\r\n\tconst UiFlags color = (currValue > 0 ? (currValue == maxValue ? UiFlags::ColorGold : UiFlags::ColorWhite) : UiFlags::ColorRed);\r\n\r\n\tauto drawStringWithShadow = [out, color](std::string_view text, Point pos) {\r\n\t\tDrawString(out, text, pos + Displacement { -1, -1 },\r\n\t\t    { .flags = UiFlags::ColorBlack | UiFlags::KerningFitSpacing, .spacing = 0 });\r\n\t\tDrawString(out, text, pos,\r\n\t\t    { .flags = color | UiFlags::KerningFitSpacing, .spacing = 0 });\r\n\t};\r\n\r\n\tconst std::string currText = StrCat(currValue);\r\n\tdrawStringWithShadow(currText, pos - Displacement { GetLineWidth(currText, GameFont12) + 1, 0 });\r\n\tdrawStringWithShadow(\"/\", pos);\r\n\tdrawStringWithShadow(StrCat(maxValue), pos + Displacement { GetLineWidth(\"/\", GameFont12) + 1, 0 });\r\n}\r\n\r\nvoid UpdateLifeManaPercent()\r\n{\r\n\tMyPlayer->UpdateManaPercentage();\r\n\tMyPlayer->UpdateHitPointPercentage();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_flasks.hpp",
    "content": "#pragma once\r\n\r\n#include <optional>\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern std::optional<OwnedSurface> pLifeBuff;\r\nextern std::optional<OwnedSurface> pManaBuff;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_gold.cpp",
    "content": "#include \"control.hpp\"\r\n#include \"control_chat.hpp\"\r\n\r\n#include \"DiabloUI/text_input.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"inv.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool DropGoldFlag;\r\nTextInputCursorState GoldDropCursor;\r\nchar GoldDropText[21];\r\n\r\nnamespace {\r\n\r\nint8_t GoldDropInvIndex;\r\nstd::optional<NumberInputState> GoldDropInputState;\r\n\r\nvoid RemoveGold(Player &player, int goldIndex, int amount)\r\n{\r\n\tconst int gi = goldIndex - INVITEM_INV_FIRST;\r\n\tplayer.InvList[gi]._ivalue -= amount;\r\n\tif (player.InvList[gi]._ivalue > 0) {\r\n\t\tSetPlrHandGoldCurs(player.InvList[gi]);\r\n\t\tNetSyncInvItem(player, gi);\r\n\t} else {\r\n\t\tplayer.RemoveInvItem(gi);\r\n\t}\r\n\r\n\tMakeGoldStack(player.HoldItem, amount);\r\n\tNewCursor(player.HoldItem);\r\n\r\n\tplayer._pGold = CalculateGold(player);\r\n}\r\n\r\nint GetGoldDropMax()\r\n{\r\n\treturn GoldDropInputState->max();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DrawGoldSplit(const Surface &out)\r\n{\r\n\tconst int dialogX = 30;\r\n\r\n\tClxDraw(out, GetPanelPosition(UiPanels::Inventory, { dialogX, 178 }), (*GoldBoxBuffer)[0]);\r\n\r\n\tconst std::string_view amountText = GoldDropText;\r\n\tconst TextInputCursorState &cursor = GoldDropCursor;\r\n\tconst int max = GetGoldDropMax();\r\n\r\n\tconst std::string description = fmt::format(\r\n\t    fmt::runtime(ngettext(\r\n\t        /* TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.*/\r\n\t        \"You have {:s} gold piece. How many do you want to remove?\",\r\n\t        \"You have {:s} gold pieces. How many do you want to remove?\",\r\n\t        max)),\r\n\t    FormatInteger(max));\r\n\r\n\t// Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words\r\n\tconst std::string wrapped = WordWrapString(description, 200);\r\n\r\n\t// The split gold dialog is roughly 4 lines high, but we need at least one line for the player to input an amount.\r\n\t// Using a clipping region 50 units high (approx 3 lines with a lineheight of 17) to ensure there is enough room left\r\n\t//  for the text entered by the player.\r\n\tDrawString(out, wrapped, { GetPanelPosition(UiPanels::Inventory, { dialogX + 31, 75 }), { 200, 50 } },\r\n\t    { .flags = UiFlags::ColorWhitegold | UiFlags::AlignCenter, .lineHeight = 17 });\r\n\r\n\t// Even a ten digit amount of gold only takes up about half a line. There's no need to wrap or clip text here so we\r\n\t// use the Point form of DrawString.\r\n\tDrawString(out, amountText, GetPanelPosition(UiPanels::Inventory, { dialogX + 37, 128 }),\r\n\t    {\r\n\t        .flags = UiFlags::ColorWhite | UiFlags::PentaCursor,\r\n\t        .cursorPosition = static_cast<int>(cursor.position),\r\n\t        .highlightRange = { static_cast<int>(cursor.selection.begin), static_cast<int>(cursor.selection.end) },\r\n\t    });\r\n}\r\n\r\nvoid control_drop_gold(SDL_Keycode vkey)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer.hasNoLife()) {\r\n\t\tCloseGoldDrop();\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (vkey) {\r\n\tcase SDLK_RETURN:\r\n\tcase SDLK_KP_ENTER:\r\n\t\tif (const int value = GoldDropInputState->value(); value != 0) {\r\n\t\t\tRemoveGold(myPlayer, GoldDropInvIndex, value);\r\n\t\t}\r\n\t\tCloseGoldDrop();\r\n\t\tbreak;\r\n\tcase SDLK_ESCAPE:\r\n\t\tCloseGoldDrop();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid OpenGoldDrop(int8_t invIndex, int max)\r\n{\r\n\tDropGoldFlag = true;\r\n\tGoldDropInvIndex = invIndex;\r\n\tGoldDropText[0] = '\\0';\r\n\tGoldDropInputState.emplace(NumberInputState::Options {\r\n\t    .textOptions {\r\n\t        .value = GoldDropText,\r\n\t        .cursor = &GoldDropCursor,\r\n\t        .maxLength = sizeof(GoldDropText) - 1,\r\n\t    },\r\n\t    .min = 0,\r\n\t    .max = max,\r\n\t});\r\n\tSDLC_StartTextInput(ghMainWnd);\r\n}\r\n\r\nvoid CloseGoldDrop()\r\n{\r\n\tif (!DropGoldFlag)\r\n\t\treturn;\r\n\tSDLC_StopTextInput(ghMainWnd);\r\n\tDropGoldFlag = false;\r\n\tGoldDropInputState = std::nullopt;\r\n\tGoldDropInvIndex = 0;\r\n}\r\n\r\nbool HandleGoldDropTextInputEvent(const SDL_Event &event)\r\n{\r\n\treturn HandleInputEvent(event, GoldDropInputState);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_infobox.cpp",
    "content": "#include \"control.hpp\"\r\n#include \"control_panel.hpp\"\r\n\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"panels/partypanel.hpp\"\r\n#include \"qol/stash.h\"\r\n#include \"qol/xpbar.h\"\r\n#include \"towners.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/screen_reader.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nStringOrView InfoString;\r\nStringOrView FloatingInfoString;\r\n\r\nnamespace {\r\n\r\nvoid PrintInfo(const Surface &out)\r\n{\r\n\tif (ChatFlag)\r\n\t\treturn;\r\n\r\n\tconst int space[] = { 18, 12, 6, 3, 0 };\r\n\tRectangle infoBox = InfoBoxRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, infoBox);\r\n\r\n\tconst auto newLineCount = static_cast<int>(c_count(InfoString.str(), '\\n'));\r\n\tconst int spaceIndex = std::min(4, newLineCount);\r\n\tconst int spacing = space[spaceIndex];\r\n\tconst int lineHeight = 12 + spacing;\r\n\r\n\t// Adjusting the line height to add spacing between lines\r\n\t// will also add additional space beneath the last line\r\n\t// which throws off the vertical centering\r\n\tinfoBox.position.y += spacing / 2;\r\n\r\n\tSpeakText(InfoString);\r\n\r\n\tDrawString(out, InfoString, infoBox,\r\n\t    {\r\n\t        .flags = InfoColor | UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::KerningFitSpacing,\r\n\t        .spacing = 2,\r\n\t        .lineHeight = lineHeight,\r\n\t    });\r\n}\r\n\r\nRectangle GetFloatingInfoRect(const int lineHeight, const int textSpacing)\r\n{\r\n\t// Calculate the width and height of the floating info box\r\n\tconst std::string txt = std::string(FloatingInfoString);\r\n\r\n\tauto lines = SplitByChar(txt, '\\n');\r\n\tconst GameFontTables font = GameFont12;\r\n\tint maxW = 0;\r\n\r\n\tfor (const auto &line : lines) {\r\n\t\tconst int w = GetLineWidth(line, font, textSpacing, nullptr);\r\n\t\tmaxW = std::max(maxW, w);\r\n\t}\r\n\r\n\tconst auto lineCount = 1 + static_cast<int>(c_count(FloatingInfoString.str(), '\\n'));\r\n\tconst int totalH = lineCount * lineHeight;\r\n\r\n\tconst Player &player = *InspectPlayer;\r\n\r\n\t// 1) Equipment (Rect position)\r\n\tif (pcursinvitem >= INVITEM_HEAD && pcursinvitem < INVITEM_INV_FIRST) {\r\n\t\tconst int slot = pcursinvitem - INVITEM_HEAD;\r\n\t\tstatic constexpr Point equipLocal[] = {\r\n\t\t\t{ 133, 59 },\r\n\t\t\t{ 48, 205 },\r\n\t\t\t{ 249, 205 },\r\n\t\t\t{ 205, 60 },\r\n\t\t\t{ 17, 160 },\r\n\t\t\t{ 248, 160 },\r\n\t\t\t{ 133, 160 },\r\n\t\t};\r\n\r\n\t\tPoint itemPosition = equipLocal[slot];\r\n\t\tauto &item = player.InvBody[slot];\r\n\t\tconst Size frame = GetInvItemSize(item._iCurs + CURSOR_FIRSTITEM);\r\n\r\n\t\tif (slot == INVLOC_HAND_LEFT) {\r\n\t\t\titemPosition.x += frame.width == InventorySlotSizeInPixels.width\r\n\t\t\t    ? InventorySlotSizeInPixels.width\r\n\t\t\t    : 0;\r\n\t\t\titemPosition.y += frame.height == 3 * InventorySlotSizeInPixels.height\r\n\t\t\t    ? 0\r\n\t\t\t    : -InventorySlotSizeInPixels.height;\r\n\t\t} else if (slot == INVLOC_HAND_RIGHT) {\r\n\t\t\titemPosition.x += frame.width == InventorySlotSizeInPixels.width\r\n\t\t\t    ? (InventorySlotSizeInPixels.width - 1)\r\n\t\t\t    : 1;\r\n\t\t\titemPosition.y += frame.height == 3 * InventorySlotSizeInPixels.height\r\n\t\t\t    ? 0\r\n\t\t\t    : -InventorySlotSizeInPixels.height;\r\n\t\t}\r\n\r\n\t\titemPosition.y++;                  // Align position to bottom left of the item graphic\r\n\t\titemPosition.x += frame.width / 2; // Align position to center of the item graphic\r\n\t\titemPosition.x -= maxW / 2;        // Align position to the center of the floating item info box\r\n\r\n\t\tconst Point screen = GetPanelPosition(UiPanels::Inventory, itemPosition);\r\n\r\n\t\treturn { { screen.x, screen.y }, { maxW, totalH } };\r\n\t}\r\n\r\n\t// 2) Inventory grid (Rect position)\r\n\tif (pcursinvitem >= INVITEM_INV_FIRST && pcursinvitem < INVITEM_INV_FIRST + InventoryGridCells) {\r\n\t\tconst int itemIdx = pcursinvitem - INVITEM_INV_FIRST;\r\n\r\n\t\tfor (int j = 0; j < InventoryGridCells; ++j) {\r\n\t\t\tif (player.InvGrid[j] > 0 && player.InvGrid[j] - 1 == itemIdx) {\r\n\t\t\t\tconst Item &it = player.InvList[itemIdx];\r\n\t\t\t\tPoint itemPosition = InvRect[j + SLOTXY_INV_FIRST].position;\r\n\r\n\t\t\t\titemPosition.x += GetInventorySize(it).width * InventorySlotSizeInPixels.width / 2; // Align position to center of the item graphic\r\n\t\t\t\titemPosition.x -= maxW / 2;                                                         // Align position to the center of the floating item info box\r\n\r\n\t\t\t\tconst Point screen = GetPanelPosition(UiPanels::Inventory, itemPosition);\r\n\r\n\t\t\t\treturn { { screen.x, screen.y }, { maxW, totalH } };\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// 3) Belt (Rect position)\r\n\tif (pcursinvitem >= INVITEM_BELT_FIRST && pcursinvitem < INVITEM_BELT_FIRST + MaxBeltItems) {\r\n\t\tconst int itemIdx = pcursinvitem - INVITEM_BELT_FIRST;\r\n\t\tfor (int i = 0; i < MaxBeltItems; ++i) {\r\n\t\t\tif (player.SpdList[i].isEmpty())\r\n\t\t\t\tcontinue;\r\n\t\t\tif (i != itemIdx)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst Item &item = player.SpdList[i];\r\n\t\t\tPoint itemPosition = InvRect[i + SLOTXY_BELT_FIRST].position;\r\n\r\n\t\t\titemPosition.x += GetInventorySize(item).width * InventorySlotSizeInPixels.width / 2; // Align position to center of the item graphic\r\n\t\t\titemPosition.x -= maxW / 2;                                                           // Align position to the center of the floating item info box\r\n\r\n\t\t\tconst Point screen = GetMainPanel().position + Displacement { itemPosition.x, itemPosition.y };\r\n\r\n\t\t\treturn { { screen.x, screen.y }, { maxW, totalH } };\r\n\t\t}\r\n\t}\r\n\r\n\t// 4) Stash (Rect position)\r\n\tif (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\tfor (auto slot : StashGridRange) {\r\n\t\t\tauto itemId = Stash.GetItemIdAtPosition(slot);\r\n\t\t\tif (itemId == StashStruct::EmptyCell)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (itemId != pcursstashitem)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst Item &item = Stash.stashList[itemId];\r\n\t\t\tPoint itemPosition = GetStashSlotCoord(slot);\r\n\t\t\tconst Size itemGridSize = GetInventorySize(item);\r\n\r\n\t\t\titemPosition.y += itemGridSize.height * (InventorySlotSizeInPixels.height + 1) - 1; // Align position to bottom left of the item graphic\r\n\t\t\titemPosition.x += itemGridSize.width * InventorySlotSizeInPixels.width / 2;         // Align position to center of the item graphic\r\n\t\t\titemPosition.x -= maxW / 2;                                                         // Align position to the center of the floating item info box\r\n\r\n\t\t\treturn { { itemPosition.x, itemPosition.y }, { maxW, totalH } };\r\n\t\t}\r\n\t}\r\n\r\n\treturn { { 0, 0 }, { 0, 0 } };\r\n}\r\n\r\nint GetHoverSpriteHeight()\r\n{\r\n\tif (pcursinvitem >= INVITEM_HEAD && pcursinvitem < INVITEM_INV_FIRST) {\r\n\t\tauto &it = (*InspectPlayer).InvBody[pcursinvitem - INVITEM_HEAD];\r\n\t\treturn GetInvItemSize(it._iCurs + CURSOR_FIRSTITEM).height + 1;\r\n\t}\r\n\tif (pcursinvitem >= INVITEM_INV_FIRST\r\n\t    && pcursinvitem < INVITEM_INV_FIRST + InventoryGridCells) {\r\n\t\tconst int idx = pcursinvitem - INVITEM_INV_FIRST;\r\n\t\tauto &it = (*InspectPlayer).InvList[idx];\r\n\t\treturn GetInventorySize(it).height * (InventorySlotSizeInPixels.height + 1)\r\n\t\t    - InventorySlotSizeInPixels.height;\r\n\t}\r\n\tif (pcursinvitem >= INVITEM_BELT_FIRST\r\n\t    && pcursinvitem < INVITEM_BELT_FIRST + MaxBeltItems) {\r\n\t\tconst int idx = pcursinvitem - INVITEM_BELT_FIRST;\r\n\t\tauto &it = (*InspectPlayer).SpdList[idx];\r\n\t\treturn GetInventorySize(it).height * (InventorySlotSizeInPixels.height + 1)\r\n\t\t    - InventorySlotSizeInPixels.height - 1;\r\n\t}\r\n\tif (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\tauto &it = Stash.stashList[pcursstashitem];\r\n\t\treturn GetInventorySize(it).height * (InventorySlotSizeInPixels.height + 1);\r\n\t}\r\n\treturn InventorySlotSizeInPixels.height;\r\n}\r\n\r\nint ClampAboveOrBelow(int anchorY, int spriteH, int boxH, int pad, int linePad)\r\n{\r\n\tconst int yAbove = anchorY - spriteH - boxH - pad;\r\n\tconst int yBelow = anchorY + linePad / 2 + pad;\r\n\treturn (yAbove >= 0) ? yAbove : yBelow;\r\n}\r\n\r\nvoid PrintFloatingInfo(const Surface &out)\r\n{\r\n\tif (ChatFlag)\r\n\t\treturn;\r\n\tif (FloatingInfoString.empty())\r\n\t\treturn;\r\n\r\n\tconst int verticalSpacing = 3;\r\n\tconst int lineHeight = 12 + verticalSpacing;\r\n\tconst int textSpacing = 2;\r\n\tconst int hPadding = 5;\r\n\tconst int vPadding = 4;\r\n\r\n\tRectangle floatingInfoBox = GetFloatingInfoRect(lineHeight, textSpacing);\r\n\r\n\t// Prevent the floating info box from going off-screen horizontally\r\n\tfloatingInfoBox.position.x = std::clamp(floatingInfoBox.position.x, hPadding, GetScreenWidth() - (floatingInfoBox.size.width + hPadding));\r\n\r\n\tconst int spriteH = GetHoverSpriteHeight();\r\n\tconst int anchorY = floatingInfoBox.position.y;\r\n\r\n\t// Prevent the floating info box from going off-screen vertically\r\n\tfloatingInfoBox.position.y = ClampAboveOrBelow(anchorY, spriteH, floatingInfoBox.size.height, vPadding, verticalSpacing);\r\n\r\n\tSpeakText(FloatingInfoString);\r\n\r\n\tfor (int i = 0; i < 3; i++)\r\n\t\tDrawHalfTransparentRectTo(out, floatingInfoBox.position.x - hPadding, floatingInfoBox.position.y - vPadding, floatingInfoBox.size.width + hPadding * 2, floatingInfoBox.size.height + vPadding * 2);\r\n\tDrawHalfTransparentVerticalLine(out, { floatingInfoBox.position.x - hPadding - 1, floatingInfoBox.position.y - vPadding - 1 }, floatingInfoBox.size.height + (vPadding * 2) + 2, PAL16_GRAY + 10);\r\n\tDrawHalfTransparentVerticalLine(out, { floatingInfoBox.position.x + hPadding + floatingInfoBox.size.width, floatingInfoBox.position.y - vPadding - 1 }, floatingInfoBox.size.height + (vPadding * 2) + 2, PAL16_GRAY + 10);\r\n\tDrawHalfTransparentHorizontalLine(out, { floatingInfoBox.position.x - hPadding, floatingInfoBox.position.y - vPadding - 1 }, floatingInfoBox.size.width + (hPadding * 2), PAL16_GRAY + 10);\r\n\tDrawHalfTransparentHorizontalLine(out, { floatingInfoBox.position.x - hPadding, floatingInfoBox.position.y + vPadding + floatingInfoBox.size.height }, floatingInfoBox.size.width + (hPadding * 2), PAL16_GRAY + 10);\r\n\r\n\tDrawString(out, FloatingInfoString, floatingInfoBox,\r\n\t    {\r\n\t        .flags = InfoColor | UiFlags::AlignCenter | UiFlags::VerticalCenter,\r\n\t        .spacing = textSpacing,\r\n\t        .lineHeight = lineHeight,\r\n\t    });\r\n}\r\n\r\n} // namespace\r\n\r\nvoid AddInfoBoxString(std::string_view str, bool floatingBox /*= false*/)\r\n{\r\n\tStringOrView &infoString = floatingBox ? FloatingInfoString : InfoString;\r\n\r\n\tif (infoString.empty())\r\n\t\tinfoString = str;\r\n\telse\r\n\t\tinfoString = StrCat(infoString, \"\\n\", str);\r\n}\r\n\r\nvoid AddInfoBoxString(std::string &&str, bool floatingBox /*= false*/)\r\n{\r\n\tStringOrView &infoString = floatingBox ? FloatingInfoString : InfoString;\r\n\r\n\tif (infoString.empty())\r\n\t\tinfoString = std::move(str);\r\n\telse\r\n\t\tinfoString = StrCat(infoString, \"\\n\", str);\r\n}\r\n\r\nvoid CheckPanelInfo()\r\n{\r\n\tMainPanelFlag = false;\r\n\tInfoString = StringOrView {};\r\n\tFloatingInfoString = StringOrView {};\r\n\r\n\tconst int totalButtons = IsChatAvailable() ? TotalMpMainPanelButtons : TotalSpMainPanelButtons;\r\n\r\n\tfor (int i = 0; i < totalButtons; i++) {\r\n\t\tRectangle button = MainPanelButtonRect[i];\r\n\r\n\t\tSetPanelObjectPosition(UiPanels::Main, button);\r\n\r\n\t\tif (button.contains(MousePosition)) {\r\n\t\t\tif (i != 7) {\r\n\t\t\t\tInfoString = _(PanBtnStr[i]);\r\n\t\t\t} else {\r\n\t\t\t\tif (MyPlayer->friendlyMode)\r\n\t\t\t\t\tInfoString = _(\"Player friendly\");\r\n\t\t\t\telse\r\n\t\t\t\t\tInfoString = _(\"Player attack\");\r\n\t\t\t}\r\n\t\t\tif (PanBtnHotKey[i] != nullptr) {\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Hotkey: {:s}\")), _(PanBtnHotKey[i])));\r\n\t\t\t}\r\n\t\t\tInfoColor = UiFlags::ColorWhite;\r\n\t\t\tMainPanelFlag = true;\r\n\t\t}\r\n\t}\r\n\r\n\tRectangle spellSelectButton = SpellButtonRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, spellSelectButton);\r\n\r\n\tif (!SpellSelectFlag && spellSelectButton.contains(MousePosition)) {\r\n\t\tInfoString = _(\"Select current spell button\");\r\n\t\tInfoColor = UiFlags::ColorWhite;\r\n\t\tMainPanelFlag = true;\r\n\t\tAddInfoBoxString(_(\"Hotkey: 's'\"));\r\n\t\tconst Player &myPlayer = *MyPlayer;\r\n\t\tconst SpellID spellId = myPlayer._pRSpell;\r\n\t\tif (IsValidSpell(spellId)) {\r\n\t\t\tswitch (myPlayer._pRSplType) {\r\n\t\t\tcase SpellType::Skill:\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"{:s} Skill\")), pgettext(\"spell\", GetSpellData(spellId).sNameText)));\r\n\t\t\t\tbreak;\r\n\t\t\tcase SpellType::Spell: {\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"{:s} Spell\")), pgettext(\"spell\", GetSpellData(spellId).sNameText)));\r\n\t\t\t\tconst int spellLevel = myPlayer.GetSpellLevel(spellId);\r\n\t\t\t\tAddInfoBoxString(spellLevel == 0 ? _(\"Spell Level 0 - Unusable\") : fmt::format(fmt::runtime(_(\"Spell Level {:d}\")), spellLevel));\r\n\t\t\t} break;\r\n\t\t\tcase SpellType::Scroll: {\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Scroll of {:s}\")), pgettext(\"spell\", GetSpellData(spellId).sNameText)));\r\n\t\t\t\tconst int scrollCount = c_count_if(InventoryAndBeltPlayerItemsRange { myPlayer }, [spellId](const Item &item) {\r\n\t\t\t\t\treturn item.isScrollOf(spellId);\r\n\t\t\t\t});\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(ngettext(\"{:d} Scroll\", \"{:d} Scrolls\", scrollCount)), scrollCount));\r\n\t\t\t} break;\r\n\t\t\tcase SpellType::Charges:\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Staff of {:s}\")), pgettext(\"spell\", GetSpellData(spellId).sNameText)));\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(ngettext(\"{:d} Charge\", \"{:d} Charges\", myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges)), myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges));\r\n\t\t\t\tbreak;\r\n\t\t\tcase SpellType::Invalid:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tRectangle belt = BeltRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, belt);\r\n\r\n\tif (belt.contains(MousePosition))\r\n\t\tpcursinvitem = CheckInvHLight();\r\n\r\n\tif (CheckXPBarInfo())\r\n\t\tMainPanelFlag = true;\r\n}\r\n\r\nvoid DrawInfoBox(const Surface &out)\r\n{\r\n\tDrawPanelBox(out, MakeSdlRect(InfoBoxRect.position.x, InfoBoxRect.position.y + PanelPaddingHeight, InfoBoxRect.size.width, InfoBoxRect.size.height), GetMainPanel().position + Displacement { InfoBoxRect.position.x, InfoBoxRect.position.y });\r\n\tif (!MainPanelFlag && !trigflag && pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell && !SpellSelectFlag && pcurs != CURSOR_HOURGLASS) {\r\n\t\tInfoString = StringOrView {};\r\n\t\tInfoColor = UiFlags::ColorWhite;\r\n\t}\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tif (SpellSelectFlag || trigflag || pcurs == CURSOR_HOURGLASS) {\r\n\t\tInfoColor = UiFlags::ColorWhite;\r\n\t} else if (!myPlayer.HoldItem.isEmpty()) {\r\n\t\tif (myPlayer.HoldItem._itype == ItemType::Gold) {\r\n\t\t\tconst int nGold = myPlayer.HoldItem._ivalue;\r\n\t\t\tInfoString = fmt::format(fmt::runtime(ngettext(\"{:s} gold piece\", \"{:s} gold pieces\", nGold)), FormatInteger(nGold));\r\n\t\t} else if (!myPlayer.CanUseItem(myPlayer.HoldItem)) {\r\n\t\t\tInfoString = _(\"Requirements not met\");\r\n\t\t} else {\r\n\t\t\tInfoString = myPlayer.HoldItem.getName();\r\n\t\t\tInfoColor = myPlayer.HoldItem.getTextColor();\r\n\t\t}\r\n\t} else {\r\n\t\tif (pcursitem != -1)\r\n\t\t\tGetItemStr(Items[pcursitem]);\r\n\t\telse if (ObjectUnderCursor != nullptr)\r\n\t\t\tGetObjectStr(*ObjectUnderCursor);\r\n\t\tif (pcursmonst != -1) {\r\n\t\t\tif (leveltype != DTYPE_TOWN) {\r\n\t\t\t\tconst Monster &monster = Monsters[pcursmonst];\r\n\t\t\t\tInfoColor = UiFlags::ColorWhite;\r\n\t\t\t\tInfoString = monster.name();\r\n\t\t\t\tif (monster.isUnique()) {\r\n\t\t\t\t\tInfoColor = UiFlags::ColorWhitegold;\r\n\t\t\t\t\tPrintUniqueHistory();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tPrintMonstHistory(monster.type().type);\r\n\t\t\t\t}\r\n\t\t\t} else if (pcursitem == -1) {\r\n\t\t\t\tInfoString = std::string_view(Towners[pcursmonst].name);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (PlayerUnderCursor != nullptr) {\r\n\t\t\tInfoColor = UiFlags::ColorWhitegold;\r\n\t\t\tconst auto &target = *PlayerUnderCursor;\r\n\t\t\tInfoString = std::string_view(target._pName);\r\n\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"{:s}, Level: {:d}\")), target.getClassName(), target.getCharacterLevel()));\r\n\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Hit Points {:d} of {:d}\")), target._pHitPoints >> 6, target._pMaxHP >> 6));\r\n\t\t}\r\n\t\tif (PortraitIdUnderCursor != -1) {\r\n\t\t\tInfoColor = UiFlags::ColorWhitegold;\r\n\t\t\tauto &target = Players[PortraitIdUnderCursor];\r\n\t\t\tInfoString = std::string_view(target._pName);\r\n\t\t\tAddInfoBoxString(_(\"Right click to inspect\"));\r\n\t\t}\r\n\t}\r\n\tif (!InfoString.empty())\r\n\t\tPrintInfo(out);\r\n}\r\n\r\nvoid DrawFloatingInfoBox(const Surface &out)\r\n{\r\n\tif (pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell) {\r\n\t\tFloatingInfoString = StringOrView {};\r\n\t\tInfoColor = UiFlags::ColorWhite;\r\n\t}\r\n\r\n\tif (!FloatingInfoString.empty())\r\n\t\tPrintFloatingInfo(out);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_panel.cpp",
    "content": "#include \"control_panel.hpp\"\r\n#include \"control.hpp\"\r\n#include \"control_chat.hpp\"\r\n#include \"control_flasks.hpp\"\r\n\r\n#include \"automap.h\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/modifier_hints.h\"\r\n#include \"diablo_msg.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/trn.hpp\"\r\n#include \"gamemenu.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"minitext.h\"\r\n#include \"options.h\"\r\n#include \"panels/charpanel.hpp\"\r\n#include \"panels/mainpanel.hpp\"\r\n#include \"panels/partypanel.hpp\"\r\n#include \"panels/spell_book.hpp\"\r\n#include \"panels/spell_icons.hpp\"\r\n#include \"panels/spell_list.hpp\"\r\n#include \"pfile.h\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool CharPanelButton[4];\r\nbool LevelButtonDown;\r\nbool CharPanelButtonActive;\r\nUiFlags InfoColor;\r\nint SpellbookTab;\r\nbool ChatFlag;\r\nbool SpellbookFlag;\r\nbool CharFlag;\r\nbool MainPanelFlag;\r\nbool MainPanelButtonDown;\r\nbool SpellSelectFlag;\r\nRectangle MainPanel;\r\nRectangle LeftPanel;\r\nRectangle RightPanel;\r\nstd::optional<OwnedSurface> BottomBuffer;\r\nOptionalOwnedClxSpriteList GoldBoxBuffer;\r\n\r\nconst Rectangle &GetMainPanel()\r\n{\r\n\treturn MainPanel;\r\n}\r\nconst Rectangle &GetLeftPanel()\r\n{\r\n\treturn LeftPanel;\r\n}\r\nconst Rectangle &GetRightPanel()\r\n{\r\n\treturn RightPanel;\r\n}\r\nbool IsLeftPanelOpen()\r\n{\r\n\treturn CharFlag || QuestLogIsOpen || IsStashOpen;\r\n}\r\nbool IsRightPanelOpen()\r\n{\r\n\treturn invflag || SpellbookFlag;\r\n}\r\n\r\nconstexpr Size IncrementAttributeButtonSize { 41, 22 };\r\n/** Maps from attribute_id to the rectangle on screen used for attribute increment buttons. */\r\nRectangle CharPanelButtonRect[4] = {\r\n\t{ { 137, 138 }, IncrementAttributeButtonSize },\r\n\t{ { 137, 166 }, IncrementAttributeButtonSize },\r\n\t{ { 137, 195 }, IncrementAttributeButtonSize },\r\n\t{ { 137, 223 }, IncrementAttributeButtonSize }\r\n};\r\n\r\nconstexpr Size WidePanelButtonSize { 71, 20 };\r\nconstexpr Size PanelButtonSize { 33, 32 };\r\n/** Positions of panel buttons. */\r\nRectangle MainPanelButtonRect[8] = {\r\n\t// clang-format off\r\n\t{ {   9,   9 }, WidePanelButtonSize }, // char button\r\n\t{ {   9,  35 }, WidePanelButtonSize }, // quests button\r\n\t{ {   9,  75 }, WidePanelButtonSize }, // map button\r\n\t{ {   9, 101 }, WidePanelButtonSize }, // menu button\r\n\t{ { 560,   9 }, WidePanelButtonSize }, // inv button\r\n\t{ { 560,  35 }, WidePanelButtonSize }, // spells button\r\n\t{ {  87,  91 }, PanelButtonSize     }, // chat button\r\n\t{ { 527,  91 }, PanelButtonSize     }, // friendly fire button\r\n\t// clang-format on\r\n};\r\n\r\nRectangle LevelButtonRect = { { 40, -39 }, { 41, 22 } };\r\n\r\nconstexpr int BeltItems = 8;\r\nconstexpr Size BeltSize { (INV_SLOT_SIZE_PX + 1) * BeltItems, INV_SLOT_SIZE_PX };\r\nRectangle BeltRect { { 205, 5 }, BeltSize };\r\n\r\nRectangle SpellButtonRect { { 565, 64 }, { 56, 56 } };\r\n\r\nint PanelPaddingHeight = 16;\r\n\r\n/** Maps from panel_button_id to panel button description. */\r\nconst char *const PanBtnStr[8] = {\r\n\tN_(\"Character Information\"),\r\n\tN_(\"Quests log\"),\r\n\tN_(\"Automap\"),\r\n\tN_(\"Main Menu\"),\r\n\tN_(\"Inventory\"),\r\n\tN_(\"Spell book\"),\r\n\tN_(\"Send Message\"),\r\n\t\"\" // Player attack\r\n};\r\n\r\n/** Maps from panel_button_id to hotkey name. */\r\nconst char *const PanBtnHotKey[8] = { \"'c'\", \"'q'\", N_(\"Tab\"), N_(\"Esc\"), \"'i'\", \"'b'\", N_(\"Enter\"), nullptr };\r\n\r\nint TotalSpMainPanelButtons = 6;\r\nint TotalMpMainPanelButtons = 8;\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList pDurIcons;\r\nOptionalOwnedClxSpriteList multiButtons;\r\nOptionalOwnedClxSpriteList pMainPanelButtons;\r\n\r\nenum panel_button_id : uint8_t {\r\n\tPanelButtonCharinfo,\r\n\tPanelButtonFirst = PanelButtonCharinfo,\r\n\tPanelButtonQlog,\r\n\tPanelButtonAutomap,\r\n\tPanelButtonMainmenu,\r\n\tPanelButtonInventory,\r\n\tPanelButtonSpellbook,\r\n\tPanelButtonSendmsg,\r\n\tPanelButtonFriendly,\r\n\tPanelButtonLast = PanelButtonFriendly,\r\n};\r\n\r\nbool MainPanelButtons[PanelButtonLast + 1];\r\n\r\nvoid SetMainPanelButtonDown(int btnId)\r\n{\r\n\tMainPanelButtons[btnId] = true;\r\n\tRedrawComponent(PanelDrawComponent::ControlButtons);\r\n\tMainPanelButtonDown = true;\r\n}\r\n\r\nvoid SetMainPanelButtonUp()\r\n{\r\n\tRedrawComponent(PanelDrawComponent::ControlButtons);\r\n\tMainPanelButtonDown = false;\r\n}\r\n\r\nint CapStatPointsToAdd(int remainingStatPoints, const Player &player, CharacterAttribute attribute)\r\n{\r\n\tconst int pointsToReachCap = player.GetMaximumAttributeValue(attribute) - player.GetBaseAttributeValue(attribute);\r\n\r\n\treturn std::min(remainingStatPoints, pointsToReachCap);\r\n}\r\n\r\nint DrawDurIcon4Item(const Surface &out, Item &pItem, int x, int c)\r\n{\r\n\tconst int durabilityThresholdGold = 5;\r\n\tconst int durabilityThresholdRed = 2;\r\n\r\n\tif (pItem.isEmpty())\r\n\t\treturn x;\r\n\tif (pItem._iDurability > durabilityThresholdGold)\r\n\t\treturn x;\r\n\tif (c == 0) {\r\n\t\tswitch (pItem._itype) {\r\n\t\tcase ItemType::Sword:\r\n\t\t\tc = 1;\r\n\t\t\tbreak;\r\n\t\tcase ItemType::Axe:\r\n\t\t\tc = 5;\r\n\t\t\tbreak;\r\n\t\tcase ItemType::Bow:\r\n\t\t\tc = 6;\r\n\t\t\tbreak;\r\n\t\tcase ItemType::Mace:\r\n\t\t\tc = 4;\r\n\t\t\tbreak;\r\n\t\tcase ItemType::Staff:\r\n\t\t\tc = 7;\r\n\t\t\tbreak;\r\n\t\tcase ItemType::Shield:\r\n\t\tdefault:\r\n\t\t\tc = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// Calculate how much of the icon should be gold and red\r\n\tconst int height = (*pDurIcons)[c].height(); // Height of durability icon CEL\r\n\tint partition = 0;\r\n\tif (pItem._iDurability > durabilityThresholdRed) {\r\n\t\tconst int current = pItem._iDurability - durabilityThresholdRed;\r\n\t\tpartition = (height * current) / (durabilityThresholdGold - durabilityThresholdRed);\r\n\t}\r\n\r\n\t// Draw icon\r\n\tconst int y = -17 + GetMainPanel().position.y;\r\n\tif (partition > 0) {\r\n\t\tconst Surface stenciledBuffer = out.subregionY(y - partition, partition);\r\n\t\tClxDraw(stenciledBuffer, { x, partition }, (*pDurIcons)[c + 8]); // Gold icon\r\n\t}\r\n\tif (partition != height) {\r\n\t\tconst Surface stenciledBuffer = out.subregionY(y - height, height - partition);\r\n\t\tClxDraw(stenciledBuffer, { x, height }, (*pDurIcons)[c]); // Red icon\r\n\t}\r\n\r\n\treturn x - (*pDurIcons)[c].height() - 8; // Add in spacing for the next durability icon\r\n}\r\n\r\nbool IsLevelUpButtonVisible()\r\n{\r\n\tif (SpellSelectFlag || CharFlag || MyPlayer->_pStatPts == 0) {\r\n\t\treturn false;\r\n\t}\r\n\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\treturn false;\r\n\t}\r\n\tif (IsPlayerInStore() || IsStashOpen) {\r\n\t\treturn false;\r\n\t}\r\n\tif (QuestLogIsOpen && GetLeftPanel().contains(GetMainPanel().position + Displacement { 0, -74 })) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid CalculatePanelAreas()\r\n{\r\n\tconstexpr Size MainPanelSize { 640, 128 };\r\n\r\n\tMainPanel = {\r\n\t\t{ (gnScreenWidth - MainPanelSize.width) / 2, gnScreenHeight - MainPanelSize.height },\r\n\t\tMainPanelSize\r\n\t};\r\n\tLeftPanel = {\r\n\t\t{ 0, 0 },\r\n\t\tSidePanelSize\r\n\t};\r\n\tRightPanel = {\r\n\t\t{ 0, 0 },\r\n\t\tSidePanelSize\r\n\t};\r\n\r\n\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\tLeftPanel.position.x = gnScreenWidth / 2 - LeftPanel.size.width;\r\n\t} else {\r\n\t\tif (gnScreenWidth - LeftPanel.size.width - RightPanel.size.width > MainPanel.size.width) {\r\n\t\t\tLeftPanel.position.x = (gnScreenWidth - LeftPanel.size.width - RightPanel.size.width - MainPanel.size.width) / 2;\r\n\t\t}\r\n\t}\r\n\tLeftPanel.position.y = (gnScreenHeight - LeftPanel.size.height - MainPanel.size.height) / 2;\r\n\r\n\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\tRightPanel.position.x = gnScreenWidth / 2;\r\n\t} else {\r\n\t\tRightPanel.position.x = gnScreenWidth - RightPanel.size.width - LeftPanel.position.x;\r\n\t}\r\n\tRightPanel.position.y = LeftPanel.position.y;\r\n\r\n\tgnViewportHeight = gnScreenHeight;\r\n\tif (gnScreenWidth <= MainPanel.size.width) {\r\n\t\t// Part of the screen is fully obscured by the UI\r\n\t\tgnViewportHeight -= MainPanel.size.height;\r\n\t}\r\n}\r\n\r\nvoid FocusOnCharInfo()\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (invflag || myPlayer._pStatPts <= 0)\r\n\t\treturn;\r\n\r\n\t// Find the first incrementable stat.\r\n\tint stat = -1;\r\n\tfor (auto attribute : enum_values<CharacterAttribute>()) {\r\n\t\tif (myPlayer.GetBaseAttributeValue(attribute) >= myPlayer.GetMaximumAttributeValue(attribute))\r\n\t\t\tcontinue;\r\n\t\tstat = static_cast<int>(attribute);\r\n\t}\r\n\tif (stat == -1)\r\n\t\treturn;\r\n\r\n\tSetCursorPos(CharPanelButtonRect[stat].Center());\r\n}\r\n\r\nvoid OpenCharPanel()\r\n{\r\n\tQuestLogIsOpen = false;\r\n\tCloseGoldWithdraw();\r\n\tCloseStash();\r\n\tCharFlag = true;\r\n}\r\n\r\nvoid CloseCharPanel()\r\n{\r\n\tCharFlag = false;\r\n\tif (IsInspectingPlayer()) {\r\n\t\tInspectPlayer = MyPlayer;\r\n\t\tRedrawEverything();\r\n\r\n\t\tif (InspectingFromPartyPanel)\r\n\t\t\tInspectingFromPartyPanel = false;\r\n\t\telse\r\n\t\t\tInitDiabloMsg(_(\"Stopped inspecting players.\"));\r\n\t}\r\n}\r\n\r\nvoid ToggleCharPanel()\r\n{\r\n\tif (CharFlag)\r\n\t\tCloseCharPanel();\r\n\telse\r\n\t\tOpenCharPanel();\r\n}\r\n\r\nPoint GetPanelPosition(UiPanels panel, Point offset)\r\n{\r\n\tconst Displacement displacement { offset.x, offset.y };\r\n\r\n\tswitch (panel) {\r\n\tcase UiPanels::Main:\r\n\t\treturn GetMainPanel().position + displacement;\r\n\tcase UiPanels::Quest:\r\n\tcase UiPanels::Character:\r\n\tcase UiPanels::Stash:\r\n\t\treturn GetLeftPanel().position + displacement;\r\n\tcase UiPanels::Spell:\r\n\tcase UiPanels::Inventory:\r\n\t\treturn GetRightPanel().position + displacement;\r\n\tdefault:\r\n\t\treturn GetMainPanel().position + displacement;\r\n\t}\r\n}\r\n\r\nvoid DrawPanelBox(const Surface &out, SDL_Rect srcRect, Point targetPosition)\r\n{\r\n\tout.BlitFrom(*BottomBuffer, srcRect, targetPosition);\r\n}\r\n\r\ntl::expected<void, std::string> InitMainPanel()\r\n{\r\n\tif (!HeadlessMode) {\r\n\t\tBottomBuffer.emplace(GetMainPanel().size.width, (GetMainPanel().size.height + PanelPaddingHeight) * (IsChatAvailable() ? 2 : 1));\r\n\t\tpManaBuff.emplace(88, 88);\r\n\t\tpLifeBuff.emplace(88, 88);\r\n\r\n\t\tRETURN_IF_ERROR(LoadPartyPanel());\r\n\t\tRETURN_IF_ERROR(LoadCharPanel());\r\n\t\tRETURN_IF_ERROR(LoadLargeSpellIcons());\r\n\t\t{\r\n\t\t\tASSIGN_OR_RETURN(const OwnedClxSpriteList sprite, LoadCelWithStatus(\"ctrlpan\\\\panel8\", GetMainPanel().size.width));\r\n\t\t\tClxDraw(*BottomBuffer, { 0, (GetMainPanel().size.height + PanelPaddingHeight) - 1 }, sprite[0]);\r\n\t\t}\r\n\t\t{\r\n\t\t\tconst Point bulbsPosition { 0, 87 };\r\n\t\t\tASSIGN_OR_RETURN(const OwnedClxSpriteList statusPanel, LoadCelWithStatus(\"ctrlpan\\\\p8bulbs\", 88));\r\n\t\t\tClxDraw(*pLifeBuff, bulbsPosition, statusPanel[0]);\r\n\t\t\tClxDraw(*pManaBuff, bulbsPosition, statusPanel[1]);\r\n\t\t}\r\n\t}\r\n\tChatFlag = false;\r\n\tChatInputState = std::nullopt;\r\n\tif (IsChatAvailable()) {\r\n\t\tif (!HeadlessMode) {\r\n\t\t\t{\r\n\t\t\t\tASSIGN_OR_RETURN(const OwnedClxSpriteList sprite, LoadCelWithStatus(\"ctrlpan\\\\talkpanl\", GetMainPanel().size.width));\r\n\t\t\t\tClxDraw(*BottomBuffer, { 0, (GetMainPanel().size.height + PanelPaddingHeight) * 2 - 1 }, sprite[0]);\r\n\t\t\t}\r\n\t\t\tmultiButtons = LoadCel(\"ctrlpan\\\\p8but2\", 33);\r\n\t\t\ttalkButtons = LoadCel(\"ctrlpan\\\\talkbutt\", 61);\r\n\t\t}\r\n\t\tsgbPlrTalkTbl = 0;\r\n\t\tTalkMessage[0] = '\\0';\r\n\t\tfor (bool &whisper : WhisperList)\r\n\t\t\twhisper = true;\r\n\t\tfor (bool &talkButtonDown : TalkButtonsDown)\r\n\t\t\ttalkButtonDown = false;\r\n\t}\r\n\tMainPanelFlag = false;\r\n\tLevelButtonDown = false;\r\n\tif (!HeadlessMode) {\r\n\t\tRETURN_IF_ERROR(LoadMainPanel());\r\n\t\tASSIGN_OR_RETURN(pMainPanelButtons, LoadCelWithStatus(\"ctrlpan\\\\panel8bu\", 71));\r\n\r\n\t\tstatic const uint16_t CharButtonsFrameWidths[9] { 95, 41, 41, 41, 41, 41, 41, 41, 41 };\r\n\t\tASSIGN_OR_RETURN(pChrButtons, LoadCelWithStatus(\"data\\\\charbut\", CharButtonsFrameWidths));\r\n\t}\r\n\tResetMainPanelButtons();\r\n\tif (!HeadlessMode)\r\n\t\tpDurIcons = LoadCel(\"items\\\\duricons\", 32);\r\n\tfor (bool &buttonEnabled : CharPanelButton)\r\n\t\tbuttonEnabled = false;\r\n\tCharPanelButtonActive = false;\r\n\tInfoString = StringOrView {};\r\n\tFloatingInfoString = StringOrView {};\r\n\tRedrawComponent(PanelDrawComponent::Health);\r\n\tRedrawComponent(PanelDrawComponent::Mana);\r\n\tCloseCharPanel();\r\n\tSpellSelectFlag = false;\r\n\tSpellbookTab = 0;\r\n\tSpellbookFlag = false;\r\n\r\n\tif (!HeadlessMode) {\r\n\t\tInitSpellBook();\r\n\t\tASSIGN_OR_RETURN(pQLogCel, LoadCelWithStatus(\"data\\\\quest\", static_cast<uint16_t>(SidePanelSize.width)));\r\n\t\tASSIGN_OR_RETURN(GoldBoxBuffer, LoadCelWithStatus(\"ctrlpan\\\\golddrop\", 261));\r\n\t}\r\n\tCloseGoldDrop();\r\n\tCalculatePanelAreas();\r\n\r\n\tif (!HeadlessMode)\r\n\t\tInitModifierHints();\r\n\r\n\treturn {};\r\n}\r\n\r\nvoid DrawMainPanel(const Surface &out)\r\n{\r\n\tDrawPanelBox(out, MakeSdlRect(0, sgbPlrTalkTbl + PanelPaddingHeight, GetMainPanel().size.width, GetMainPanel().size.height), GetMainPanel().position);\r\n\tDrawInfoBox(out);\r\n}\r\n\r\nvoid DrawMainPanelButtons(const Surface &out)\r\n{\r\n\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\r\n\tfor (int i = 0; i < TotalSpMainPanelButtons; i++) {\r\n\t\tif (!MainPanelButtons[i]) {\r\n\t\t\tDrawPanelBox(out, MakeSdlRect(MainPanelButtonRect[i].position.x, MainPanelButtonRect[i].position.y + PanelPaddingHeight, MainPanelButtonRect[i].size.width, MainPanelButtonRect[i].size.height + 1), mainPanelPosition + Displacement { MainPanelButtonRect[i].position.x, MainPanelButtonRect[i].position.y });\r\n\t\t} else {\r\n\t\t\tconst Point position = mainPanelPosition + Displacement { MainPanelButtonRect[i].position.x, MainPanelButtonRect[i].position.y };\r\n\t\t\tRenderClxSprite(out, (*pMainPanelButtons)[i], position);\r\n\t\t\tRenderClxSprite(out, (*PanelButtonDown)[i], position + Displacement { 4, 0 });\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsChatAvailable()) {\r\n\t\tRenderClxSprite(out, (*multiButtons)[MainPanelButtons[PanelButtonSendmsg] ? 1 : 0], mainPanelPosition + Displacement { MainPanelButtonRect[PanelButtonSendmsg].position.x, MainPanelButtonRect[PanelButtonSendmsg].position.y });\r\n\r\n\t\tconst Point friendlyButtonPosition = mainPanelPosition + Displacement { MainPanelButtonRect[PanelButtonFriendly].position.x, MainPanelButtonRect[PanelButtonFriendly].position.y };\r\n\r\n\t\tif (MyPlayer->friendlyMode)\r\n\t\t\tRenderClxSprite(out, (*multiButtons)[MainPanelButtons[PanelButtonFriendly] ? 3 : 2], friendlyButtonPosition);\r\n\t\telse\r\n\t\t\tRenderClxSprite(out, (*multiButtons)[MainPanelButtons[PanelButtonFriendly] ? 5 : 4], friendlyButtonPosition);\r\n\t}\r\n}\r\n\r\nvoid ResetMainPanelButtons()\r\n{\r\n\tfor (bool &panelButton : MainPanelButtons)\r\n\t\tpanelButton = false;\r\n\tSetMainPanelButtonUp();\r\n}\r\n\r\nvoid CheckMainPanelButton()\r\n{\r\n\tconst int totalButtons = IsChatAvailable() ? TotalMpMainPanelButtons : TotalSpMainPanelButtons;\r\n\r\n\tfor (int i = 0; i < totalButtons; i++) {\r\n\t\tRectangle button = MainPanelButtonRect[i];\r\n\r\n\t\tSetPanelObjectPosition(UiPanels::Main, button);\r\n\r\n\t\tif (button.contains(MousePosition)) {\r\n\t\t\tSetMainPanelButtonDown(i);\r\n\t\t}\r\n\t}\r\n\r\n\tRectangle spellSelectButton = SpellButtonRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, spellSelectButton);\r\n\r\n\tif (!SpellSelectFlag && spellSelectButton.contains(MousePosition)) {\r\n\t\tif ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0) {\r\n\t\t\tPlayer &myPlayer = *MyPlayer;\r\n\t\t\tmyPlayer._pRSpell = SpellID::Invalid;\r\n\t\t\tmyPlayer._pRSplType = SpellType::Invalid;\r\n\t\t\tRedrawEverything();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tDoSpeedBook();\r\n\t\tgamemenu_off();\r\n\t}\r\n}\r\n\r\nvoid CheckMainPanelButtonDead()\r\n{\r\n\tRectangle menuButton = MainPanelButtonRect[PanelButtonMainmenu];\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, menuButton);\r\n\r\n\tif (menuButton.contains(MousePosition)) {\r\n\t\tSetMainPanelButtonDown(PanelButtonMainmenu);\r\n\t\treturn;\r\n\t}\r\n\r\n\tRectangle chatButton = MainPanelButtonRect[PanelButtonSendmsg];\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, chatButton);\r\n\r\n\tif (chatButton.contains(MousePosition)) {\r\n\t\tSetMainPanelButtonDown(PanelButtonSendmsg);\r\n\t}\r\n}\r\n\r\nvoid DoAutoMap()\r\n{\r\n\tif (!AutomapActive)\r\n\t\tStartAutomap();\r\n\telse\r\n\t\tAutomapActive = false;\r\n}\r\n\r\nvoid CycleAutomapType()\r\n{\r\n\tif (!AutomapActive) {\r\n\t\tStartAutomap();\r\n\t\treturn;\r\n\t}\r\n\tconst AutomapType newType { static_cast<std::underlying_type_t<AutomapType>>(\r\n\t\t(static_cast<unsigned>(GetAutomapType()) + 1) % enum_size<AutomapType>::value) };\r\n\tSetAutomapType(newType);\r\n\tif (newType == AutomapType::FIRST) {\r\n\t\tAutomapActive = false;\r\n\t}\r\n}\r\n\r\nvoid CheckMainPanelButtonUp()\r\n{\r\n\tbool gamemenuOff = true;\r\n\r\n\tSetMainPanelButtonUp();\r\n\r\n\tfor (int i = PanelButtonFirst; i <= PanelButtonLast; i++) {\r\n\t\tif (!MainPanelButtons[i])\r\n\t\t\tcontinue;\r\n\r\n\t\tMainPanelButtons[i] = false;\r\n\r\n\t\tRectangle button = MainPanelButtonRect[i];\r\n\r\n\t\tSetPanelObjectPosition(UiPanels::Main, button);\r\n\r\n\t\tif (!button.contains(MousePosition))\r\n\t\t\tcontinue;\r\n\r\n\t\tswitch (i) {\r\n\t\tcase PanelButtonCharinfo:\r\n\t\t\tToggleCharPanel();\r\n\t\t\tbreak;\r\n\t\tcase PanelButtonQlog:\r\n\t\t\tCloseCharPanel();\r\n\t\t\tCloseGoldWithdraw();\r\n\t\t\tCloseStash();\r\n\t\t\tif (!QuestLogIsOpen)\r\n\t\t\t\tStartQuestlog();\r\n\t\t\telse\r\n\t\t\t\tQuestLogIsOpen = false;\r\n\t\t\tbreak;\r\n\t\tcase PanelButtonAutomap:\r\n\t\t\tDoAutoMap();\r\n\t\t\tbreak;\r\n\t\tcase PanelButtonMainmenu:\r\n\t\t\tif (MyPlayerIsDead) {\r\n\t\t\t\tif (!gbIsMultiplayer) {\r\n\t\t\t\t\tif (gbValidSaveFile)\r\n\t\t\t\t\t\tgamemenu_load_game(false);\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tgamemenu_exit_game(false);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tNetSendCmd(true, CMD_RETOWN);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t} else if (MyPlayer->hasNoLife()) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tqtextflag = false;\r\n\t\t\tgamemenu_handle_previous();\r\n\t\t\tgamemenuOff = false;\r\n\t\t\tbreak;\r\n\t\tcase PanelButtonInventory:\r\n\t\t\tSpellbookFlag = false;\r\n\t\t\tCloseGoldWithdraw();\r\n\t\t\tCloseStash();\r\n\t\t\tinvflag = !invflag;\r\n\t\t\tCloseGoldDrop();\r\n\t\t\tbreak;\r\n\t\tcase PanelButtonSpellbook:\r\n\t\t\tCloseInventory();\r\n\t\t\tCloseGoldDrop();\r\n\t\t\tSpellbookFlag = !SpellbookFlag;\r\n\t\t\tbreak;\r\n\t\tcase PanelButtonSendmsg:\r\n\t\t\tif (ChatFlag)\r\n\t\t\t\tResetChat();\r\n\t\t\telse\r\n\t\t\t\tTypeChatMessage();\r\n\t\t\tbreak;\r\n\t\tcase PanelButtonFriendly:\r\n\t\t\t// Toggle friendly Mode\r\n\t\t\tNetSendCmd(true, CMD_FRIENDLYMODE);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (gamemenuOff)\r\n\t\tgamemenu_off();\r\n}\r\n\r\nvoid FreeControlPan()\r\n{\r\n\tBottomBuffer = std::nullopt;\r\n\tpManaBuff = std::nullopt;\r\n\tpLifeBuff = std::nullopt;\r\n\tFreeLargeSpellIcons();\r\n\tFreeSpellBook();\r\n\tpMainPanelButtons = std::nullopt;\r\n\tmultiButtons = std::nullopt;\r\n\ttalkButtons = std::nullopt;\r\n\tpChrButtons = std::nullopt;\r\n\tpDurIcons = std::nullopt;\r\n\tpQLogCel = std::nullopt;\r\n\tGoldBoxBuffer = std::nullopt;\r\n\tFreeMainPanel();\r\n\tFreePartyPanel();\r\n\tFreeCharPanel();\r\n\tFreeModifierHints();\r\n}\r\n\r\nvoid CheckLevelButton()\r\n{\r\n\tif (!IsLevelUpButtonVisible()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tRectangle button = LevelButtonRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, button);\r\n\r\n\tif (!LevelButtonDown && button.contains(MousePosition))\r\n\t\tLevelButtonDown = true;\r\n}\r\n\r\nvoid CheckLevelButtonUp()\r\n{\r\n\tRectangle button = LevelButtonRect;\r\n\r\n\tSetPanelObjectPosition(UiPanels::Main, button);\r\n\r\n\tif (button.contains(MousePosition)) {\r\n\t\tOpenCharPanel();\r\n\t}\r\n\tLevelButtonDown = false;\r\n}\r\n\r\nvoid DrawLevelButton(const Surface &out)\r\n{\r\n\tif (IsLevelUpButtonVisible()) {\r\n\t\tconst int nCel = LevelButtonDown ? 2 : 1;\r\n\t\tDrawString(out, _(\"Level Up\"), { GetMainPanel().position + Displacement { 0, LevelButtonRect.position.y - 23 }, { 120, 0 } },\r\n\t\t    { .flags = UiFlags::ColorWhite | UiFlags::AlignCenter | UiFlags::KerningFitSpacing });\r\n\t\tRenderClxSprite(out, (*pChrButtons)[nCel], GetMainPanel().position + Displacement { LevelButtonRect.position.x, LevelButtonRect.position.y });\r\n\t}\r\n}\r\n\r\nvoid CheckChrBtns()\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer._pmode == PM_DEATH)\r\n\t\treturn;\r\n\r\n\tif (CharPanelButtonActive || myPlayer._pStatPts == 0)\r\n\t\treturn;\r\n\r\n\tfor (auto attribute : enum_values<CharacterAttribute>()) {\r\n\t\tif (myPlayer.GetBaseAttributeValue(attribute) >= myPlayer.GetMaximumAttributeValue(attribute))\r\n\t\t\tcontinue;\r\n\t\tauto buttonId = static_cast<size_t>(attribute);\r\n\t\tRectangle button = CharPanelButtonRect[buttonId];\r\n\t\tSetPanelObjectPosition(UiPanels::Character, button);\r\n\t\tif (button.contains(MousePosition)) {\r\n\t\t\tCharPanelButton[buttonId] = true;\r\n\t\t\tCharPanelButtonActive = true;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ReleaseChrBtns(bool addAllStatPoints)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer._pmode == PM_DEATH)\r\n\t\treturn;\r\n\r\n\tCharPanelButtonActive = false;\r\n\tfor (auto attribute : enum_values<CharacterAttribute>()) {\r\n\t\tauto buttonId = static_cast<size_t>(attribute);\r\n\t\tif (!CharPanelButton[buttonId])\r\n\t\t\tcontinue;\r\n\r\n\t\tCharPanelButton[buttonId] = false;\r\n\t\tRectangle button = CharPanelButtonRect[buttonId];\r\n\t\tSetPanelObjectPosition(UiPanels::Character, button);\r\n\t\tif (button.contains(MousePosition)) {\r\n\t\t\tPlayer &myPlayer = *MyPlayer;\r\n\t\t\tint statPointsToAdd = 1;\r\n\t\t\tif (addAllStatPoints)\r\n\t\t\t\tstatPointsToAdd = CapStatPointsToAdd(myPlayer._pStatPts, myPlayer, attribute);\r\n\t\t\tswitch (attribute) {\r\n\t\t\tcase CharacterAttribute::Strength:\r\n\t\t\t\tNetSendCmdParam1(true, CMD_ADDSTR, statPointsToAdd);\r\n\t\t\t\tmyPlayer._pStatPts -= statPointsToAdd;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CharacterAttribute::Magic:\r\n\t\t\t\tNetSendCmdParam1(true, CMD_ADDMAG, statPointsToAdd);\r\n\t\t\t\tmyPlayer._pStatPts -= statPointsToAdd;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CharacterAttribute::Dexterity:\r\n\t\t\t\tNetSendCmdParam1(true, CMD_ADDDEX, statPointsToAdd);\r\n\t\t\t\tmyPlayer._pStatPts -= statPointsToAdd;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CharacterAttribute::Vitality:\r\n\t\t\t\tNetSendCmdParam1(true, CMD_ADDVIT, statPointsToAdd);\r\n\t\t\t\tmyPlayer._pStatPts -= statPointsToAdd;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DrawDurIcon(const Surface &out)\r\n{\r\n\tconst bool hasRoomBetweenPanels = RightPanel.position.x - (LeftPanel.position.x + LeftPanel.size.width) >= 16 + (32 + 8 + 32 + 8 + 32 + 8 + 32) + 16;\r\n\tconst bool hasRoomUnderPanels = MainPanel.position.y - (RightPanel.position.y + RightPanel.size.height) >= 16 + 32 + 16;\r\n\r\n\tif (!hasRoomBetweenPanels && !hasRoomUnderPanels) {\r\n\t\tif (IsLeftPanelOpen() && IsRightPanelOpen())\r\n\t\t\treturn;\r\n\t}\r\n\r\n\tint x = MainPanel.position.x + MainPanel.size.width - 32 - 16;\r\n\tif (!hasRoomUnderPanels) {\r\n\t\tif (IsRightPanelOpen() && MainPanel.position.x + MainPanel.size.width > RightPanel.position.x)\r\n\t\t\tx -= MainPanel.position.x + MainPanel.size.width - RightPanel.position.x;\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tx = DrawDurIcon4Item(out, myPlayer.InvBody[INVLOC_HEAD], x, 3);\r\n\tx = DrawDurIcon4Item(out, myPlayer.InvBody[INVLOC_CHEST], x, 2);\r\n\tx = DrawDurIcon4Item(out, myPlayer.InvBody[INVLOC_HAND_LEFT], x, 0);\r\n\tDrawDurIcon4Item(out, myPlayer.InvBody[INVLOC_HAND_RIGHT], x, 0);\r\n}\r\n\r\nvoid RedBack(const Surface &out)\r\n{\r\n\tuint8_t *dst = out.begin();\r\n\tuint8_t *tbl = GetPauseTRN();\r\n\tfor (int h = gnViewportHeight; h != 0; h--, dst += out.pitch() - gnScreenWidth) {\r\n\t\tfor (int w = gnScreenWidth; w != 0; w--) {\r\n\t\t\tif (leveltype != DTYPE_HELL || *dst >= 32)\r\n\t\t\t\t*dst = tbl[*dst];\r\n\t\t\tdst++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DrawDeathText(const Surface &out)\r\n{\r\n\tconst TextRenderOptions largeTextOptions {\r\n\t\t.flags = UiFlags::FontSize42 | UiFlags::ColorGold | UiFlags::AlignCenter | UiFlags::VerticalCenter,\r\n\t\t.spacing = 2\r\n\t};\r\n\tconst TextRenderOptions smallTextOptions {\r\n\t\t.flags = UiFlags::FontSize30 | UiFlags::ColorGold | UiFlags::AlignCenter | UiFlags::VerticalCenter,\r\n\t\t.spacing = 2\r\n\t};\r\n\tstd::string text;\r\n\tconst int verticalPadding = 42;\r\n\tPoint linePosition { 0, gnScreenHeight / 2 - (verticalPadding * 2) };\r\n\r\n\ttext = _(\"You have died\");\r\n\tDrawString(out, text, linePosition, largeTextOptions);\r\n\tlinePosition.y += verticalPadding;\r\n\r\n\tstd::string buttonText;\r\n\r\n\tswitch (ControlMode) {\r\n\tcase ControlTypes::KeyboardAndMouse:\r\n\t\tbuttonText = _(\"ESC\");\r\n\t\tbreak;\r\n\tcase ControlTypes::Gamepad:\r\n\t\tbuttonText = ToString(GamepadType, ControllerButton_BUTTON_START);\r\n\t\tbreak;\r\n\tcase ControlTypes::VirtualGamepad:\r\n\t\tbuttonText = _(\"Menu Button\");\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (!gbIsMultiplayer) {\r\n\t\tif (gbValidSaveFile)\r\n\t\t\ttext = fmt::format(fmt::runtime(_(\"Press {} to load last save.\")), buttonText);\r\n\t\telse\r\n\t\t\ttext = fmt::format(fmt::runtime(_(\"Press {} to return to Main Menu.\")), buttonText);\r\n\r\n\t} else {\r\n\t\ttext = fmt::format(fmt::runtime(_(\"Press {} to restart in town.\")), buttonText);\r\n\t}\r\n\tDrawString(out, text, linePosition, smallTextOptions);\r\n}\r\n\r\nvoid SetPanelObjectPosition(UiPanels panel, Rectangle &button)\r\n{\r\n\tbutton.position = GetPanelPosition(panel, button.position);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/control/control_panel.hpp",
    "content": "#pragma once\r\n\r\n#include \"engine/rectangle.hpp\"\r\n#include \"panels/ui_panels.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern int TotalSpMainPanelButtons;\r\nextern int TotalMpMainPanelButtons;\r\nextern int PanelPaddingHeight;\r\nextern const char *const PanBtnStr[8];\r\nextern const char *const PanBtnHotKey[8];\r\nextern Rectangle SpellButtonRect;\r\nextern Rectangle BeltRect;\r\n\r\nvoid SetPanelObjectPosition(UiPanels panel, Rectangle &button);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/README.md",
    "content": "# Controls handling\n\nDevilutionX supports mouse & keyboard and gamepad input.\n\nThis directory currently mostly handles gamepad input.\n\nLow-level gamepad handling is abstracted and 3 implementations are provided:\n\n1. SDL2 controller API.\n\n2. SDL 1&2 joystick API.\n\n   This can be used in SDL1 joystick platforms and for mapping additional\n   buttons not defined by SDL2 controller mappings (e.g. additional Nintendo\n   Switch arrows).\n\n3. Keyboard keys acting as controller buttons.\n\n   This can be used for testing, or on devices where this is the\n   only or the easiest API to use (e.g. RetroFW).\n\nExample keyboard-as-controller build flags:\n\n```bash\ncmake .. -DUSE_SDL1=ON -DHAS_KBCTRL=1 -DPREFILL_PLAYER_NAME=ON \\\n-DKBCTRL_BUTTON_DPAD_LEFT=SDLK_LEFT \\\n-DKBCTRL_BUTTON_DPAD_RIGHT=SDLK_RIGHT \\\n-DKBCTRL_BUTTON_DPAD_UP=SDLK_UP \\\n-DKBCTRL_BUTTON_DPAD_DOWN=SDLK_DOWN \\\n-DKBCTRL_BUTTON_X=SDLK_y \\\n-DKBCTRL_BUTTON_Y=SDLK_x \\\n-DKBCTRL_BUTTON_B=SDLK_a \\\n-DKBCTRL_BUTTON_A=SDLK_b \\\n-DKBCTRL_BUTTON_RIGHTSHOULDER=SDLK_RIGHTBRACKET \\\n-DKBCTRL_BUTTON_LEFTSHOULDER=SDLK_LEFTBRACKET \\\n-DKBCTRL_BUTTON_LEFTSTICK=SDLK_TAB \\\n-DKBCTRL_BUTTON_START=SDLK_RETURN \\\n-DKBCTRL_BUTTON_BACK=SDLK_LSHIFT\n```\n"
  },
  {
    "path": "Source/controls/axis_direction.cpp",
    "content": "#include \"axis_direction.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nAxisDirection AxisDirectionRepeater::Get(AxisDirection axisDirection)\r\n{\r\n\tconst int now = SDL_GetTicks();\r\n\tswitch (axisDirection.x) {\r\n\tcase AxisDirectionX_LEFT:\r\n\t\tlast_right_ = 0;\r\n\t\tif (now - last_left_ < min_interval_ms_) {\r\n\t\t\taxisDirection.x = AxisDirectionX_NONE;\r\n\t\t} else {\r\n\t\t\tlast_left_ = now;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AxisDirectionX_RIGHT:\r\n\t\tlast_left_ = 0;\r\n\t\tif (now - last_right_ < min_interval_ms_) {\r\n\t\t\taxisDirection.x = AxisDirectionX_NONE;\r\n\t\t} else {\r\n\t\t\tlast_right_ = now;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AxisDirectionX_NONE:\r\n\t\tlast_left_ = last_right_ = 0;\r\n\t\tbreak;\r\n\t}\r\n\tswitch (axisDirection.y) {\r\n\tcase AxisDirectionY_UP:\r\n\t\tlast_down_ = 0;\r\n\t\tif (now - last_up_ < min_interval_ms_) {\r\n\t\t\taxisDirection.y = AxisDirectionY_NONE;\r\n\t\t} else {\r\n\t\t\tlast_up_ = now;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AxisDirectionY_DOWN:\r\n\t\tlast_up_ = 0;\r\n\t\tif (now - last_down_ < min_interval_ms_) {\r\n\t\t\taxisDirection.y = AxisDirectionY_NONE;\r\n\t\t} else {\r\n\t\t\tlast_down_ = now;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase AxisDirectionY_NONE:\r\n\t\tlast_up_ = last_down_ = 0;\r\n\t\tbreak;\r\n\t}\r\n\treturn axisDirection;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/axis_direction.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nenum AxisDirectionX : uint8_t {\r\n\tAxisDirectionX_NONE,\r\n\tAxisDirectionX_LEFT,\r\n\tAxisDirectionX_RIGHT\r\n};\r\nenum AxisDirectionY : uint8_t {\r\n\tAxisDirectionY_NONE,\r\n\tAxisDirectionY_UP,\r\n\tAxisDirectionY_DOWN\r\n};\r\n\r\n/**\r\n * @brief 8-way direction of a D-Pad or a thumb stick.\r\n */\r\nstruct AxisDirection {\r\n\tAxisDirectionX x;\r\n\tAxisDirectionY y;\r\n};\r\n\r\n/**\r\n * @brief Returns a non-empty AxisDirection at most once per the given time interval.\r\n */\r\nclass AxisDirectionRepeater {\r\npublic:\r\n\tAxisDirectionRepeater(int min_interval_ms = 200)\r\n\t    : last_left_(0)\r\n\t    , last_right_(0)\r\n\t    , last_up_(0)\r\n\t    , last_down_(0)\r\n\t    , min_interval_ms_(min_interval_ms)\r\n\t{\r\n\t}\r\n\r\n\tAxisDirection Get(AxisDirection axisDirection);\r\n\r\nprivate:\r\n\tint last_left_;\r\n\tint last_right_;\r\n\tint last_up_;\r\n\tint last_down_;\r\n\tint min_interval_ms_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/control_mode.cpp",
    "content": "#include \"controls/control_mode.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nControlTypes ControlMode = ControlTypes::None;\r\nControlTypes ControlDevice = ControlTypes::None;\r\n\r\nGamepadLayout GamepadType =\r\n#if defined(DEVILUTIONX_GAMEPAD_TYPE)\r\n    GamepadLayout::\r\n        DEVILUTIONX_GAMEPAD_TYPE;\r\n#else\r\n    GamepadLayout::Generic;\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/control_mode.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"controls/controller_buttons.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class ControlTypes : uint8_t {\r\n\tNone,\r\n\tKeyboardAndMouse,\r\n\tGamepad,\r\n\tVirtualGamepad,\r\n};\r\n\r\nextern ControlTypes ControlMode;\r\n\r\n/**\r\n * @brief Controlling device type.\r\n *\r\n * While simulating a mouse, `ControlMode` is set to `KeyboardAndMouse`,\r\n * even though a gamepad is used to control it.\r\n *\r\n * This value is always set to the actual active device type.\r\n */\r\nextern ControlTypes ControlDevice;\r\n\r\nextern GamepadLayout GamepadType;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/controller.cpp",
    "content": "#include \"controls/controller.h\"\r\n\r\n#include <cmath>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#ifndef USE_SDL1\r\n#include \"controls/devices/game_controller.h\"\r\n#endif\r\n#include \"controls/devices/joystick.h\"\r\n#include \"controls/devices/kbcontroller.h\"\r\n#include \"engine/demomode.h\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid UnlockControllerState(const SDL_Event &event)\r\n{\r\n#ifndef USE_SDL1\r\n\tGameController *const controller = GameController::Get(event);\r\n\tif (controller != nullptr) {\r\n\t\tcontroller->UnlockTriggerState();\r\n\t}\r\n#endif\r\n\tJoystick *const joystick = Joystick::Get(event);\r\n\tif (joystick != nullptr) {\r\n\t\tjoystick->UnlockHatState();\r\n\t}\r\n}\r\n\r\nStaticVector<ControllerButtonEvent, 4> ToControllerButtonEvents(const SDL_Event &event)\r\n{\r\n\tControllerButtonEvent result { ControllerButton_NONE, false };\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_UP:\r\n\tcase SDL_EVENT_KEY_UP:\r\n#ifndef USE_SDL1\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_UP:\r\n#endif\r\n\t\tresult.up = true;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n#if HAS_KBCTRL == 1\r\n\tif (!demo::IsRunning()) {\r\n\t\tresult.button = KbCtrlToControllerButton(event);\r\n\t\tif (result.button != ControllerButton_NONE)\r\n\t\t\treturn { result };\r\n\t}\r\n#endif\r\n#ifndef USE_SDL1\r\n\tGameController *const controller = GameController::Get(event);\r\n\tif (controller != nullptr) {\r\n\t\tresult.button = controller->ToControllerButton(event);\r\n\t\tif (result.button != ControllerButton_NONE) {\r\n\t\t\tif (result.button == ControllerButton_AXIS_TRIGGERLEFT || result.button == ControllerButton_AXIS_TRIGGERRIGHT) {\r\n\t\t\t\tresult.up = !controller->IsPressed(result.button);\r\n\t\t\t}\r\n\t\t\treturn { result };\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tconst Joystick *joystick = Joystick::Get(event);\r\n\tif (joystick != nullptr) {\r\n\t\treturn devilution::Joystick::ToControllerButtonEvents(event);\r\n\t}\r\n\r\n\treturn { result };\r\n}\r\n\r\nbool IsControllerButtonPressed(ControllerButton button)\r\n{\r\n#ifndef USE_SDL1\r\n\tif (GameController::IsPressedOnAnyController(button))\r\n\t\treturn true;\r\n#endif\r\n#if HAS_KBCTRL == 1\r\n\tif (!demo::IsRunning() && IsKbCtrlButtonPressed(button))\r\n\t\treturn true;\r\n#endif\r\n\treturn Joystick::IsPressedOnAnyJoystick(button);\r\n}\r\n\r\nbool IsControllerButtonComboPressed(ControllerButtonCombo combo)\r\n{\r\n\treturn IsControllerButtonPressed(combo.button)\r\n\t    && (combo.modifier == ControllerButton_NONE || IsControllerButtonPressed(combo.modifier));\r\n}\r\n\r\nbool HandleControllerAddedOrRemovedEvent(const SDL_Event &event)\r\n{\r\n#ifndef USE_SDL1\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_GAMEPAD_ADDED:\r\n\t\tGameController::Add(SDLC_EventGamepadDevice(event).which);\r\n\t\tbreak;\r\n\tcase SDL_EVENT_GAMEPAD_REMOVED:\r\n\t\tGameController::Remove(SDLC_EventGamepadDevice(event).which);\r\n\t\tbreak;\r\n\tcase SDL_EVENT_JOYSTICK_ADDED:\r\n\t\tJoystick::Add(event.jdevice.which);\r\n\t\tbreak;\r\n\tcase SDL_EVENT_JOYSTICK_REMOVED:\r\n\t\tJoystick::Remove(event.jdevice.which);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/controller.h",
    "content": "#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controller_buttons.h\"\r\n#include \"utils/static_vector.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n// Must be called exactly once at the start of each SDL input event.\r\nvoid UnlockControllerState(const SDL_Event &event);\r\n\r\nStaticVector<ControllerButtonEvent, 4> ToControllerButtonEvents(const SDL_Event &event);\r\n\r\nbool IsControllerButtonPressed(ControllerButton button);\r\nbool IsControllerButtonComboPressed(ControllerButtonCombo combo);\r\n\r\nbool HandleControllerAddedOrRemovedEvent(const SDL_Event &event);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/controller_buttons.cpp",
    "content": "#include \"controller_buttons.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nnamespace controller_button_icon {\r\n[[maybe_unused]] const std::string_view Playstation_Triangle = \"\\uE000\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_Square = \"\\uE001\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_X = \"\\uE002\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_Circle = \"\\uE003\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_Options = \"\\uE004\";    // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_Share = \"\\uE005\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_L2 = \"\\uE006\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_R2 = \"\\uE007\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_L1 = \"\\uE008\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_R1 = \"\\uE009\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_DPad_Up = \"\\uE00A\";    // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_DPad_Right = \"\\uE00B\"; // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_DPad_Down = \"\\uE00C\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_DPad_Left = \"\\uE00D\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_NW = \"\\uE00E\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_W = \"\\uE00F\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_SW = \"\\uE010\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_N = \"\\uE011\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick = \"\\uE012\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_S = \"\\uE013\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_NE = \"\\uE014\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_E = \"\\uE015\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_LStick_SE = \"\\uE016\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_L3 = \"\\uE017\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_NW = \"\\uE018\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_W = \"\\uE019\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_SW = \"\\uE01A\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_N = \"\\uE01B\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick = \"\\uE01C\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_S = \"\\uE01D\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_NE = \"\\uE01E\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_E = \"\\uE01F\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_RStick_SE = \"\\uE020\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_R3 = \"\\uE021\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Playstation_Touchpad = \"\\uE022\";   // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_X = \"\\uE023\";             // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_Y = \"\\uE024\";             // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_B = \"\\uE025\";             // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_A = \"\\uE026\";             // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_Plus = \"\\uE027\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_Minus = \"\\uE028\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_ZL = \"\\uE029\";            // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_ZR = \"\\uE02A\";            // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_L = \"\\uE02B\";             // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_R = \"\\uE02C\";             // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_DPad_Up = \"\\uE02D\";       // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_DPad_Right = \"\\uE02E\";    // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_DPad_Down = \"\\uE02F\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_DPad_Left = \"\\uE030\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_NW = \"\\uE031\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_W = \"\\uE032\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_SW = \"\\uE033\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_N = \"\\uE034\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick = \"\\uE035\";        // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_S = \"\\uE036\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_NE = \"\\uE037\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_E = \"\\uE038\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_SE = \"\\uE039\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_LStick_Click = \"\\uE03A\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_NW = \"\\uE03B\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_W = \"\\uE03C\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_SW = \"\\uE03D\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_N = \"\\uE03E\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick = \"\\uE03F\";        // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_S = \"\\uE040\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_NE = \"\\uE041\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_E = \"\\uE042\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_SE = \"\\uE043\";     // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_RStick_Click = \"\\uE044\";  // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_Home = \"\\uE045\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_Screenshot = \"\\uE046\";    // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_SL = \"\\uE047\";            // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Nintendo_SR = \"\\uE048\";            // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_Y = \"\\uE049\";                 // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_X = \"\\uE04A\";                 // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_A = \"\\uE04B\";                 // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_B = \"\\uE04C\";                 // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_Menu = \"\\uE04D\";              // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_View = \"\\uE04E\";              // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LT = \"\\uE04F\";                // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RT = \"\\uE050\";                // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LB = \"\\uE051\";                // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RB = \"\\uE052\";                // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_DPad_Up = \"\\uE053\";           // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_DPad_Right = \"\\uE054\";        // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_DPad_Down = \"\\uE055\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_DPad_Left = \"\\uE056\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_NW = \"\\uE057\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_W = \"\\uE058\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_SW = \"\\uE059\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_N = \"\\uE05A\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick = \"\\uE05B\";            // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_NE = \"\\uE05C\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_E = \"\\uE05D\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_SE = \"\\uE05E\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_LStick_Click = \"\\uE05F\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_NW = \"\\uE060\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_W = \"\\uE061\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_SW = \"\\uE062\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_N = \"\\uE063\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick = \"\\uE064\";            // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_S = \"\\uE065\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_NE = \"\\uE066\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_E = \"\\uE067\";          // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_SE = \"\\uE068\";         // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_RStick_Click = \"\\uE069\";      // NOLINT(readability-identifier-naming)\r\n[[maybe_unused]] const std::string_view Xbox_Xbox = \"\\uE06A\";              // NOLINT(readability-identifier-naming)\r\n} // namespace controller_button_icon\r\n\r\nstd::string_view ToGenericButtonText(ControllerButton button)\r\n{\r\n\tswitch (button) {\r\n\tcase devilution::ControllerButton_BUTTON_A:\r\n\t\treturn \"A\";\r\n\tcase devilution::ControllerButton_BUTTON_B:\r\n\t\treturn \"B\";\r\n\tcase devilution::ControllerButton_BUTTON_X:\r\n\t\treturn \"X\";\r\n\tcase devilution::ControllerButton_BUTTON_Y:\r\n\t\treturn \"Y\";\r\n\tcase devilution::ControllerButton_BUTTON_START:\r\n\t\treturn \"Start\";\r\n\tcase devilution::ControllerButton_BUTTON_BACK:\r\n\t\treturn \"Select\";\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERLEFT:\r\n\t\treturn \"LT\";\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERRIGHT:\r\n\t\treturn \"RT\";\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\treturn \"LB\";\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\treturn \"RB\";\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn \"LS\";\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSTICK:\r\n\t\treturn \"RS\";\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn \"Up\";\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn \"Down\";\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn \"Left\";\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn \"Right\";\r\n\tcase devilution::ControllerButton_NONE:\r\n\t\treturn \"None\";\r\n\tcase devilution::ControllerButton_IGNORE:\r\n\t\treturn \"Ignored\";\r\n\tdefault:\r\n\t\treturn \"Unknown\";\r\n\t}\r\n}\r\n\r\nstd::string_view ToPlayStationIcon(ControllerButton button)\r\n{\r\n\tswitch (button) {\r\n\tcase devilution::ControllerButton_BUTTON_A:\r\n\t\treturn controller_button_icon::Playstation_X;\r\n\tcase devilution::ControllerButton_BUTTON_B:\r\n\t\treturn controller_button_icon::Playstation_Circle;\r\n\tcase devilution::ControllerButton_BUTTON_X:\r\n\t\treturn controller_button_icon::Playstation_Square;\r\n\tcase devilution::ControllerButton_BUTTON_Y:\r\n\t\treturn controller_button_icon::Playstation_Triangle;\r\n\tcase devilution::ControllerButton_BUTTON_START:\r\n\t\treturn controller_button_icon::Playstation_Options;\r\n\tcase devilution::ControllerButton_BUTTON_BACK:\r\n\t\treturn controller_button_icon::Playstation_Share;\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERLEFT:\r\n\t\treturn controller_button_icon::Playstation_L2;\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERRIGHT:\r\n\t\treturn controller_button_icon::Playstation_R2;\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\treturn controller_button_icon::Playstation_L1;\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\treturn controller_button_icon::Playstation_R1;\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn controller_button_icon::Playstation_L3;\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSTICK:\r\n\t\treturn controller_button_icon::Playstation_R3;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn controller_button_icon::Playstation_DPad_Up;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn controller_button_icon::Playstation_DPad_Down;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn controller_button_icon::Playstation_DPad_Left;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn controller_button_icon::Playstation_DPad_Right;\r\n\tdefault:\r\n\t\treturn ToGenericButtonText(button);\r\n\t}\r\n}\r\n\r\nstd::string_view ToNintendoIcon(ControllerButton button)\r\n{\r\n\tswitch (button) {\r\n\tcase devilution::ControllerButton_BUTTON_A:\r\n\t\treturn controller_button_icon::Nintendo_B;\r\n\tcase devilution::ControllerButton_BUTTON_B:\r\n\t\treturn controller_button_icon::Nintendo_A;\r\n\tcase devilution::ControllerButton_BUTTON_X:\r\n\t\treturn controller_button_icon::Nintendo_Y;\r\n\tcase devilution::ControllerButton_BUTTON_Y:\r\n\t\treturn controller_button_icon::Nintendo_X;\r\n\tcase devilution::ControllerButton_BUTTON_START:\r\n\t\treturn controller_button_icon::Nintendo_Plus;\r\n\tcase devilution::ControllerButton_BUTTON_BACK:\r\n\t\treturn controller_button_icon::Nintendo_Minus;\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERLEFT:\r\n\t\treturn controller_button_icon::Nintendo_ZL;\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERRIGHT:\r\n\t\treturn controller_button_icon::Nintendo_ZR;\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\treturn controller_button_icon::Nintendo_L;\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\treturn controller_button_icon::Nintendo_R;\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn controller_button_icon::Nintendo_LStick_Click;\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSTICK:\r\n\t\treturn controller_button_icon::Nintendo_RStick_Click;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn controller_button_icon::Nintendo_DPad_Up;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn controller_button_icon::Nintendo_DPad_Down;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn controller_button_icon::Nintendo_DPad_Left;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn controller_button_icon::Nintendo_DPad_Right;\r\n\tdefault:\r\n\t\treturn ToGenericButtonText(button);\r\n\t}\r\n}\r\n\r\nstd::string_view ToXboxIcon(ControllerButton button)\r\n{\r\n\tswitch (button) {\r\n\tcase devilution::ControllerButton_BUTTON_A:\r\n\t\treturn controller_button_icon::Xbox_A;\r\n\tcase devilution::ControllerButton_BUTTON_B:\r\n\t\treturn controller_button_icon::Xbox_B;\r\n\tcase devilution::ControllerButton_BUTTON_X:\r\n\t\treturn controller_button_icon::Xbox_X;\r\n\tcase devilution::ControllerButton_BUTTON_Y:\r\n\t\treturn controller_button_icon::Xbox_Y;\r\n\tcase devilution::ControllerButton_BUTTON_START:\r\n\t\treturn controller_button_icon::Xbox_Menu;\r\n\tcase devilution::ControllerButton_BUTTON_BACK:\r\n\t\treturn controller_button_icon::Xbox_View;\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERLEFT:\r\n\t\treturn controller_button_icon::Xbox_LT;\r\n\tcase devilution::ControllerButton_AXIS_TRIGGERRIGHT:\r\n\t\treturn controller_button_icon::Xbox_RT;\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\treturn controller_button_icon::Xbox_LB;\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\treturn controller_button_icon::Xbox_RB;\r\n\tcase devilution::ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn controller_button_icon::Xbox_LStick_Click;\r\n\tcase devilution::ControllerButton_BUTTON_RIGHTSTICK:\r\n\t\treturn controller_button_icon::Xbox_RStick_Click;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn controller_button_icon::Xbox_DPad_Up;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn controller_button_icon::Xbox_DPad_Down;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn controller_button_icon::Xbox_DPad_Left;\r\n\tcase devilution::ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn controller_button_icon::Xbox_DPad_Right;\r\n\tdefault:\r\n\t\treturn ToGenericButtonText(button);\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nstd::string_view ToString(GamepadLayout gamepadType, ControllerButton button)\r\n{\r\n\tswitch (gamepadType) {\r\n\tcase GamepadLayout::PlayStation:\r\n\t\treturn ToPlayStationIcon(button);\r\n\tcase GamepadLayout::Nintendo:\r\n\t\treturn ToNintendoIcon(button);\r\n\tcase GamepadLayout::Xbox:\r\n\t\treturn ToXboxIcon(button);\r\n\tdefault:\r\n\tcase GamepadLayout::Generic:\r\n\t\treturn ToGenericButtonText(button);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/controller_buttons.h",
    "content": "#pragma once\r\n// Unifies joystick, gamepad, and keyboard controller APIs.\r\n\r\n#include <cstdint>\r\n#include <functional>\r\n#include <string_view>\r\n\r\nnamespace devilution {\r\n\r\n// NOTE: A, B, X, Y refer to physical positions on an XBox 360 controller.\r\n// A<->B and X<->Y are reversed on a Nintendo controller.\r\nenum ControllerButton : uint8_t {\r\n\tControllerButton_NONE,\r\n\tControllerButton_IGNORE,\r\n\tControllerButton_AXIS_TRIGGERLEFT,  // ZL (aka L2)\r\n\tControllerButton_AXIS_TRIGGERRIGHT, // ZR (aka R2)\r\n\tControllerButton_BUTTON_A,          // Bottom button\r\n\tControllerButton_BUTTON_B,          // Right button\r\n\tControllerButton_BUTTON_X,          // Left button\r\n\tControllerButton_BUTTON_Y,          // TOP button\r\n\tControllerButton_BUTTON_LEFTSTICK,\r\n\tControllerButton_BUTTON_RIGHTSTICK,\r\n\tControllerButton_BUTTON_LEFTSHOULDER,\r\n\tControllerButton_BUTTON_RIGHTSHOULDER,\r\n\tControllerButton_BUTTON_START,\r\n\tControllerButton_BUTTON_BACK,\r\n\tControllerButton_BUTTON_DPAD_UP,\r\n\tControllerButton_BUTTON_DPAD_DOWN,\r\n\tControllerButton_BUTTON_DPAD_LEFT,\r\n\tControllerButton_BUTTON_DPAD_RIGHT,\r\n\tFIRST = ControllerButton_NONE,\r\n\tLAST = ControllerButton_BUTTON_DPAD_RIGHT\r\n};\r\n\r\nstruct ControllerButtonCombo {\r\n\tconstexpr ControllerButtonCombo()\r\n\t    : modifier(ControllerButton_NONE)\r\n\t    , button(ControllerButton_NONE)\r\n\t{\r\n\t}\r\n\r\n\tconstexpr ControllerButtonCombo(ControllerButton button)\r\n\t    : modifier(ControllerButton_NONE)\r\n\t    , button(button)\r\n\t{\r\n\t}\r\n\r\n\tconstexpr ControllerButtonCombo(ControllerButton modifier, ControllerButton button)\r\n\t    : modifier(modifier)\r\n\t    , button(button)\r\n\t{\r\n\t}\r\n\r\n\tControllerButton modifier;\r\n\tControllerButton button;\r\n};\r\n\r\nstruct ControllerButtonEvent {\r\n\tControllerButtonEvent(ControllerButton button, bool up)\r\n\t    : button(button)\r\n\t    , up(up)\r\n\t{\r\n\t}\r\n\r\n\tControllerButton button;\r\n\tbool up;\r\n};\r\n\r\ninline bool IsDPadButton(ControllerButton button)\r\n{\r\n\treturn button == ControllerButton_BUTTON_DPAD_UP\r\n\t    || button == ControllerButton_BUTTON_DPAD_DOWN\r\n\t    || button == ControllerButton_BUTTON_DPAD_LEFT\r\n\t    || button == ControllerButton_BUTTON_DPAD_RIGHT;\r\n}\r\n\r\nenum class GamepadLayout : uint8_t {\r\n\tGeneric,\r\n\tNintendo,\r\n\tPlayStation,\r\n\tXbox,\r\n};\r\n\r\n[[nodiscard]] std::string_view ToString(GamepadLayout gamepadType, ControllerButton button);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/controller_motion.cpp",
    "content": "#include \"controls/controller_motion.h\"\r\n\r\n#include <cmath>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_gamepad.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"control/control.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/controller.h\"\r\n#ifndef USE_SDL1\r\n#include \"controls/devices/game_controller.h\"\r\n#endif\r\n#include \"controls/devices/joystick.h\"\r\n#include \"controls/game_controls.h\"\r\n#include \"controls/padmapper.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"controls/touch/gamepad.h\"\r\n#include \"engine/demomode.h\"\r\n#include \"options.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool SimulatingMouseWithPadmapper;\r\n\r\nnamespace {\r\n\r\nvoid ScaleJoystickAxes(float *x, float *y, float deadzone)\r\n{\r\n\t// radial and scaled dead_zone\r\n\t// https://web.archive.org/web/20200130014626/www.third-helix.com:80/2013/04/12/doing-thumbstick-dead-zones-right.html\r\n\t// input values go from -32767.0...+32767.0, output values are from -1.0 to 1.0;\r\n\r\n\tif (deadzone == 0) {\r\n\t\treturn;\r\n\t}\r\n\tif (deadzone >= 1.0) {\r\n\t\t*x = 0;\r\n\t\t*y = 0;\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst float maximum = 32767.0;\r\n\tfloat analogX = *x;\r\n\tfloat analogY = *y;\r\n\tconst float deadZone = deadzone * maximum;\r\n\r\n\tconst float magnitude = std::sqrt(analogX * analogX + analogY * analogY);\r\n\tif (magnitude >= deadZone) {\r\n\t\t// find scaled axis values with magnitudes between zero and maximum\r\n\t\tconst float scalingFactor = 1.F / magnitude * (magnitude - deadZone) / (maximum - deadZone);\r\n\t\tanalogX = (analogX * scalingFactor);\r\n\t\tanalogY = (analogY * scalingFactor);\r\n\r\n\t\t// std::clamp to ensure results will never exceed the max_axis value\r\n\t\tfloat clampingFactor = 1.F;\r\n\t\tconst float absAnalogX = std::fabs(analogX);\r\n\t\tconst float absAnalogY = std::fabs(analogY);\r\n\t\tif (absAnalogX > 1.0 || absAnalogY > 1.0) {\r\n\t\t\tif (absAnalogX > absAnalogY) {\r\n\t\t\t\tclampingFactor = 1.F / absAnalogX;\r\n\t\t\t} else {\r\n\t\t\t\tclampingFactor = 1.F / absAnalogY;\r\n\t\t\t}\r\n\t\t}\r\n\t\t*x = (clampingFactor * analogX);\r\n\t\t*y = (clampingFactor * analogY);\r\n\t} else {\r\n\t\t*x = 0;\r\n\t\t*y = 0;\r\n\t}\r\n}\r\n\r\nbool IsMovementOverriddenByPadmapper(ControllerButton button)\r\n{\r\n\tconst ControllerButtonEvent releaseEvent { button, true };\r\n\tconst std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(releaseEvent);\r\n\tconst ControllerButtonCombo buttonCombo = GetOptions().Padmapper.ButtonComboForAction(actionName);\r\n\treturn buttonCombo.modifier != ControllerButton_NONE;\r\n}\r\n\r\nbool TriggersQuickSpellAction(ControllerButton button)\r\n{\r\n\tconst ControllerButtonEvent releaseEvent { button, true };\r\n\tconst std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(releaseEvent);\r\n\r\n\tconst std::string_view prefix { \"QuickSpell\" };\r\n\tif (actionName.size() < prefix.size())\r\n\t\treturn false;\r\n\tconst std::string_view truncatedActionName { actionName.data(), prefix.size() };\r\n\treturn truncatedActionName == prefix;\r\n}\r\n\r\nbool IsPressedForMovement(ControllerButton button)\r\n{\r\n\treturn !PadMenuNavigatorActive\r\n\t    && IsControllerButtonPressed(button)\r\n\t    && !IsMovementOverriddenByPadmapper(button)\r\n\t    && !(SpellSelectFlag && TriggersQuickSpellAction(button));\r\n}\r\n\r\nvoid SetSimulatingMouseWithPadmapper(bool value)\r\n{\r\n\tif (SimulatingMouseWithPadmapper == value)\r\n\t\treturn;\r\n\tSimulatingMouseWithPadmapper = value;\r\n\tif (value) {\r\n\t\tLogVerbose(\"Control: begin simulating mouse with D-Pad\");\r\n\t} else {\r\n\t\tLogVerbose(\"Control: end simulating mouse with D-Pad\");\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nfloat leftStickX, leftStickY, rightStickX, rightStickY;\r\nfloat leftStickXUnscaled, leftStickYUnscaled, rightStickXUnscaled, rightStickYUnscaled;\r\nbool leftStickNeedsScaling, rightStickNeedsScaling;\r\n\r\nnamespace {\r\n\r\nvoid ScaleJoysticks()\r\n{\r\n\tconst Options &options = GetOptions();\r\n\tconst float rightDeadzone = options.Controller.fDeadzone;\r\n\tconst float leftDeadzone = options.Controller.fDeadzone;\r\n\r\n\tif (leftStickNeedsScaling) {\r\n\t\tleftStickX = leftStickXUnscaled;\r\n\t\tleftStickY = leftStickYUnscaled;\r\n\t\tScaleJoystickAxes(&leftStickX, &leftStickY, leftDeadzone);\r\n\t\tleftStickNeedsScaling = false;\r\n\t}\r\n\r\n\tif (rightStickNeedsScaling) {\r\n\t\trightStickX = rightStickXUnscaled;\r\n\t\trightStickY = rightStickYUnscaled;\r\n\t\tScaleJoystickAxes(&rightStickX, &rightStickY, rightDeadzone);\r\n\t\trightStickNeedsScaling = false;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsControllerMotion(const SDL_Event &event)\r\n{\r\n#ifndef USE_SDL1\r\n\tif (event.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {\r\n\t\treturn IsAnyOf(SDLC_EventGamepadAxis(event).axis,\r\n\t\t    SDL_GAMEPAD_AXIS_LEFTX,\r\n\t\t    SDL_GAMEPAD_AXIS_LEFTY,\r\n\t\t    SDL_GAMEPAD_AXIS_RIGHTX,\r\n\t\t    SDL_GAMEPAD_AXIS_RIGHTY);\r\n\t}\r\n#endif\r\n\r\n#if defined(JOY_AXIS_LEFTX) || defined(JOY_AXIS_LEFTY) || defined(JOY_AXIS_RIGHTX) || defined(JOY_AXIS_RIGHTY)\r\n\tif (event.type == SDL_EVENT_JOYSTICK_AXIS_MOTION) {\r\n\t\tswitch (event.jaxis.axis) {\r\n#ifdef JOY_AXIS_LEFTX\r\n\t\tcase JOY_AXIS_LEFTX:\r\n\t\t\treturn true;\r\n#endif\r\n#ifdef JOY_AXIS_LEFTY\r\n\t\tcase JOY_AXIS_LEFTY:\r\n\t\t\treturn true;\r\n#endif\r\n#ifdef JOY_AXIS_RIGHTX\r\n\t\tcase JOY_AXIS_RIGHTX:\r\n\t\t\treturn true;\r\n#endif\r\n#ifdef JOY_AXIS_RIGHTY\r\n\t\tcase JOY_AXIS_RIGHTY:\r\n\t\t\treturn true;\r\n#endif\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\treturn false;\r\n}\r\n\r\n// Updates motion state for mouse and joystick sticks.\r\nvoid ProcessControllerMotion(const SDL_Event &event)\r\n{\r\n#ifndef USE_SDL1\r\n\tGameController *const controller = GameController::Get(event);\r\n\tif (controller != nullptr && devilution::GameController::ProcessAxisMotion(event)) {\r\n\t\tScaleJoysticks();\r\n\t\tSetSimulatingMouseWithPadmapper(false);\r\n\t\treturn;\r\n\t}\r\n#endif\r\n\tJoystick *const joystick = Joystick::Get(event);\r\n\tif (joystick != nullptr && devilution::Joystick::ProcessAxisMotion(event)) {\r\n\t\tScaleJoysticks();\r\n\t\tSetSimulatingMouseWithPadmapper(false);\r\n\t}\r\n}\r\n\r\nAxisDirection GetAnalogStickDirection(float stickX, float stickY)\r\n{\r\n\t// avoid sqrt() by comparing squared magnitudes\r\n\tconst float magnitudeSquared = stickX * stickX + stickY * stickY;\r\n\tconst float thresholdSquared = StickDirectionThreshold * StickDirectionThreshold;\r\n\tif (magnitudeSquared < thresholdSquared)\r\n\t\treturn { AxisDirectionX_NONE, AxisDirectionY_NONE };\r\n\r\n\tconst float absX = std::fabs(stickX);\r\n\tconst float absY = std::fabs(stickY);\r\n\tAxisDirection result { AxisDirectionX_NONE, AxisDirectionY_NONE };\r\n\r\n\t// 8-way sectoring with 22.5° cutoffs\r\n\tconstexpr float DiagonalCutoff = 0.41421356F; // tan(22.5°)\r\n\tif (absX == 0.0F) {\r\n\t\tresult.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN;\r\n\t\treturn result;\r\n\t}\r\n\r\n\tconst float ratio = absY / absX;\r\n\tif (ratio <= DiagonalCutoff) {\r\n\t\tresult.x = stickX > 0 ? AxisDirectionX_RIGHT : AxisDirectionX_LEFT;\r\n\t\treturn result;\r\n\t}\r\n\tif (ratio >= 1.0F / DiagonalCutoff) {\r\n\t\tresult.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN;\r\n\t\treturn result;\r\n\t}\r\n\r\n\tresult.x = stickX > 0 ? AxisDirectionX_RIGHT : AxisDirectionX_LEFT;\r\n\tresult.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN;\r\n\treturn result;\r\n}\r\n\r\nAxisDirection GetLeftStickOrDpadDirection(bool usePadmapper)\r\n{\r\n\tAxisDirection result = GetAnalogStickDirection(leftStickX, leftStickY);\r\n\r\n\tbool isUpPressed = false;\r\n\tbool isDownPressed = false;\r\n\tbool isLeftPressed = false;\r\n\tbool isRightPressed = false;\r\n\r\n\tif (usePadmapper) {\r\n\t\tisUpPressed |= PadmapperIsActionActive(\"MoveUp\");\r\n\t\tisDownPressed |= PadmapperIsActionActive(\"MoveDown\");\r\n\t\tisLeftPressed |= PadmapperIsActionActive(\"MoveLeft\");\r\n\t\tisRightPressed |= PadmapperIsActionActive(\"MoveRight\");\r\n\t} else if (!SimulatingMouseWithPadmapper) {\r\n\t\tisUpPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_UP);\r\n\t\tisDownPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_DOWN);\r\n\t\tisLeftPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_LEFT);\r\n\t\tisRightPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_RIGHT);\r\n\t}\r\n\r\n#ifndef USE_SDL1\r\n\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\tisUpPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isUpPressed;\r\n\t\tisDownPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isDownPressed;\r\n\t\tisLeftPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isLeftPressed;\r\n\t\tisRightPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isRightPressed;\r\n\t}\r\n#endif\r\n\r\n\tif (isUpPressed) {\r\n\t\tresult.y = AxisDirectionY_UP;\r\n\t} else if (isDownPressed) {\r\n\t\tresult.y = AxisDirectionY_DOWN;\r\n\t}\r\n\r\n\tif (isLeftPressed) {\r\n\t\tresult.x = AxisDirectionX_LEFT;\r\n\t} else if (isRightPressed) {\r\n\t\tresult.x = AxisDirectionX_RIGHT;\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nvoid SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent)\r\n{\r\n\tif (ctrlEvent.button == ControllerButton_NONE)\r\n\t\treturn;\r\n\tif (!ctrlEvent.up && ctrlEvent.button == SuppressedButton)\r\n\t\treturn;\r\n\r\n\tconst std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(ctrlEvent);\r\n\tconst bool upTriggered = actionName == \"MouseUp\";\r\n\tconst bool downTriggered = actionName == \"MouseDown\";\r\n\tconst bool leftTriggered = actionName == \"MouseLeft\";\r\n\tconst bool rightTriggered = actionName == \"MouseRight\";\r\n\tif (!upTriggered && !downTriggered && !leftTriggered && !rightTriggered) {\r\n\t\tif (rightStickX == 0 && rightStickY == 0)\r\n\t\t\tSetSimulatingMouseWithPadmapper(false);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst bool upActive = (upTriggered && !ctrlEvent.up) || (!upTriggered && PadmapperIsActionActive(\"MouseUp\"));\r\n\tconst bool downActive = (downTriggered && !ctrlEvent.up) || (!downTriggered && PadmapperIsActionActive(\"MouseDown\"));\r\n\tconst bool leftActive = (leftTriggered && !ctrlEvent.up) || (!leftTriggered && PadmapperIsActionActive(\"MouseLeft\"));\r\n\tconst bool rightActive = (rightTriggered && !ctrlEvent.up) || (!rightTriggered && PadmapperIsActionActive(\"MouseRight\"));\r\n\r\n\trightStickX = 0;\r\n\trightStickY = 0;\r\n\tif (upActive)\r\n\t\trightStickY += 1.F;\r\n\tif (downActive)\r\n\t\trightStickY -= 1.F;\r\n\tif (leftActive)\r\n\t\trightStickX -= 1.F;\r\n\tif (rightActive)\r\n\t\trightStickX += 1.F;\r\n\tSetSimulatingMouseWithPadmapper(true);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/controller_motion.h",
    "content": "#pragma once\r\n\r\n// Processes and stores mouse and joystick motion.\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/axis_direction.h\"\r\n#include \"controls/controller.h\"\r\n\r\nnamespace devilution {\r\n\r\n// Whether we're currently simulating the mouse with SELECT + D-Pad.\r\nextern bool SimulatingMouseWithPadmapper;\r\n\r\n// Raw axis values.\r\nextern float leftStickXUnscaled, leftStickYUnscaled, rightStickXUnscaled, rightStickYUnscaled;\r\n\r\n// Axis values scaled to [-1, 1] range and clamped to a deadzone.\r\nextern float leftStickX, leftStickY, rightStickX, rightStickY;\r\n\r\n// Whether stick positions have been updated and need rescaling.\r\nextern bool leftStickNeedsScaling, rightStickNeedsScaling;\r\n\r\n// Minimum scaled stick magnitude to register a direction.\r\nconstexpr float StickDirectionThreshold = 0.4F;\r\n\r\n// Updates motion state for mouse and joystick sticks.\r\nvoid ProcessControllerMotion(const SDL_Event &event);\r\n\r\n// Indicates whether the event represents movement of an analog thumbstick.\r\nbool IsControllerMotion(const SDL_Event &event);\r\n\r\n// Returns direction of the left thumb stick or DPad (if allow_dpad = true).\r\nAxisDirection GetLeftStickOrDpadDirection(bool usePadmapper);\r\n\r\n// Simulates right-stick movement based on input from padmapper mouse movement actions.\r\nvoid SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/devices/game_controller.cpp",
    "content": "#include \"controls/devices/game_controller.h\"\r\n\r\n#include <cstddef>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_gamepad.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n\r\n#include \"controls/controller_motion.h\"\r\n#include \"controls/devices/joystick.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_ptrs.h\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution {\r\n\r\nstd::vector<GameController> GameController::controllers_;\r\n\r\nvoid GameController::UnlockTriggerState()\r\n{\r\n\ttrigger_left_state_ = ControllerButton_NONE;\r\n\ttrigger_right_state_ = ControllerButton_NONE;\r\n}\r\n\r\nControllerButton GameController::ToControllerButton(const SDL_Event &event)\r\n{\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_GAMEPAD_AXIS_MOTION: {\r\n\t\tconst SDL_GamepadAxisEvent &axis = SDLC_EventGamepadAxis(event);\r\n\t\tswitch (axis.axis) {\r\n\t\tcase SDL_GAMEPAD_AXIS_LEFT_TRIGGER:\r\n\t\t\tif (axis.value < 8192 && trigger_left_is_down_) { // 25% pressed\r\n\t\t\t\ttrigger_left_is_down_ = false;\r\n\t\t\t\ttrigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT;\r\n\t\t\t}\r\n\t\t\tif (axis.value > 16384 && !trigger_left_is_down_) { // 50% pressed\r\n\t\t\t\ttrigger_left_is_down_ = true;\r\n\t\t\t\ttrigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT;\r\n\t\t\t}\r\n\t\t\treturn trigger_left_state_;\r\n\t\tcase SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:\r\n\t\t\tif (axis.value < 8192 && trigger_right_is_down_) { // 25% pressed\r\n\t\t\t\ttrigger_right_is_down_ = false;\r\n\t\t\t\ttrigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT;\r\n\t\t\t}\r\n\t\t\tif (axis.value > 16384 && !trigger_right_is_down_) { // 50% pressed\r\n\t\t\t\ttrigger_right_is_down_ = true;\r\n\t\t\t\ttrigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT;\r\n\t\t\t}\r\n\t\t\treturn trigger_right_state_;\r\n\t\t}\r\n\t} break;\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_DOWN:\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_UP:\r\n\t\tswitch (SDLC_EventGamepadButton(event).button) {\r\n\t\tcase SDL_GAMEPAD_BUTTON_SOUTH:\r\n\t\t\treturn ControllerButton_BUTTON_A;\r\n\t\tcase SDL_GAMEPAD_BUTTON_EAST:\r\n\t\t\treturn ControllerButton_BUTTON_B;\r\n\t\tcase SDL_GAMEPAD_BUTTON_WEST:\r\n\t\t\treturn ControllerButton_BUTTON_X;\r\n\t\tcase SDL_GAMEPAD_BUTTON_NORTH:\r\n\t\t\treturn ControllerButton_BUTTON_Y;\r\n\t\tcase SDL_GAMEPAD_BUTTON_LEFT_STICK:\r\n\t\t\treturn ControllerButton_BUTTON_LEFTSTICK;\r\n\t\tcase SDL_GAMEPAD_BUTTON_RIGHT_STICK:\r\n\t\t\treturn ControllerButton_BUTTON_RIGHTSTICK;\r\n\t\tcase SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:\r\n\t\t\treturn ControllerButton_BUTTON_LEFTSHOULDER;\r\n\t\tcase SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:\r\n\t\t\treturn ControllerButton_BUTTON_RIGHTSHOULDER;\r\n\t\tcase SDL_GAMEPAD_BUTTON_START:\r\n\t\t\treturn ControllerButton_BUTTON_START;\r\n\t\tcase SDL_GAMEPAD_BUTTON_BACK:\r\n\t\t\treturn ControllerButton_BUTTON_BACK;\r\n\t\tcase SDL_GAMEPAD_BUTTON_DPAD_UP:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_UP;\r\n\t\tcase SDL_GAMEPAD_BUTTON_DPAD_DOWN:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_DOWN;\r\n\t\tcase SDL_GAMEPAD_BUTTON_DPAD_LEFT:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_LEFT;\r\n\t\tcase SDL_GAMEPAD_BUTTON_DPAD_RIGHT:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_RIGHT;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\treturn ControllerButton_NONE;\r\n}\r\n\r\nSDL_GamepadButton GameController::ToSdlGameControllerButton(ControllerButton button)\r\n{\r\n\tif (button == ControllerButton_AXIS_TRIGGERLEFT || button == ControllerButton_AXIS_TRIGGERRIGHT)\r\n\t\tUNIMPLEMENTED();\r\n\tswitch (button) {\r\n\tcase ControllerButton_BUTTON_A:\r\n\t\treturn SDL_GAMEPAD_BUTTON_SOUTH;\r\n\tcase ControllerButton_BUTTON_B:\r\n\t\treturn SDL_GAMEPAD_BUTTON_EAST;\r\n\tcase ControllerButton_BUTTON_X:\r\n\t\treturn SDL_GAMEPAD_BUTTON_WEST;\r\n\tcase ControllerButton_BUTTON_Y:\r\n\t\treturn SDL_GAMEPAD_BUTTON_NORTH;\r\n\tcase ControllerButton_BUTTON_BACK:\r\n\t\treturn SDL_GAMEPAD_BUTTON_BACK;\r\n\tcase ControllerButton_BUTTON_START:\r\n\t\treturn SDL_GAMEPAD_BUTTON_START;\r\n\tcase ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn SDL_GAMEPAD_BUTTON_LEFT_STICK;\r\n\tcase ControllerButton_BUTTON_RIGHTSTICK:\r\n\t\treturn SDL_GAMEPAD_BUTTON_RIGHT_STICK;\r\n\tcase ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\treturn SDL_GAMEPAD_BUTTON_LEFT_SHOULDER;\r\n\tcase ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\treturn SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER;\r\n\tcase ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn SDL_GAMEPAD_BUTTON_DPAD_UP;\r\n\tcase ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn SDL_GAMEPAD_BUTTON_DPAD_DOWN;\r\n\tcase ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn SDL_GAMEPAD_BUTTON_DPAD_LEFT;\r\n\tcase ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn SDL_GAMEPAD_BUTTON_DPAD_RIGHT;\r\n\tdefault:\r\n\t\treturn SDL_GAMEPAD_BUTTON_INVALID;\r\n\t}\r\n}\r\n\r\nbool GameController::IsPressed(ControllerButton button) const\r\n{\r\n\tif (button == ControllerButton_AXIS_TRIGGERLEFT)\r\n\t\treturn trigger_left_is_down_;\r\n\tif (button == ControllerButton_AXIS_TRIGGERRIGHT)\r\n\t\treturn trigger_right_is_down_;\r\n\r\n\tconst SDL_GamepadButton gcButton = ToSdlGameControllerButton(button);\r\n\treturn SDL_GamepadHasButton(sdl_game_controller_, gcButton) && SDL_GetGamepadButton(sdl_game_controller_, gcButton);\r\n}\r\n\r\nbool GameController::ProcessAxisMotion(const SDL_Event &event)\r\n{\r\n\tif (event.type != SDL_EVENT_GAMEPAD_AXIS_MOTION) return false;\r\n\tconst SDL_GamepadAxisEvent &axis = SDLC_EventGamepadAxis(event);\r\n\tswitch (axis.axis) {\r\n\tcase SDL_GAMEPAD_AXIS_LEFTX:\r\n\t\tleftStickXUnscaled = static_cast<float>(axis.value);\r\n\t\tleftStickNeedsScaling = true;\r\n\t\tbreak;\r\n\tcase SDL_GAMEPAD_AXIS_LEFTY:\r\n\t\tleftStickYUnscaled = static_cast<float>(-axis.value);\r\n\t\tleftStickNeedsScaling = true;\r\n\t\tbreak;\r\n\tcase SDL_GAMEPAD_AXIS_RIGHTX:\r\n\t\trightStickXUnscaled = static_cast<float>(axis.value);\r\n\t\trightStickNeedsScaling = true;\r\n\t\tbreak;\r\n\tcase SDL_GAMEPAD_AXIS_RIGHTY:\r\n\t\trightStickYUnscaled = static_cast<float>(-axis.value);\r\n\t\trightStickNeedsScaling = true;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n#ifdef USE_SDL3\r\nvoid GameController::Add(SDL_JoystickID joystickId)\r\n#else\r\nvoid GameController::Add(int joystickIndex)\r\n#endif\r\n{\r\n\tGameController result;\r\n#ifdef USE_SDL3\r\n\tLog(\"Opening game controller for joystick with ID {}\", joystickId);\r\n\tresult.sdl_game_controller_ = SDL_OpenGamepad(joystickId);\r\n#else\r\n\tLog(\"Opening game controller for joystick at index {}\", joystickIndex);\r\n\tresult.sdl_game_controller_ = SDL_GameControllerOpen(joystickIndex);\r\n#endif\r\n\r\n\tif (result.sdl_game_controller_ == nullptr) {\r\n\t\tLog(\"{}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn;\r\n\t}\r\n#ifdef USE_SDL3\r\n\tresult.instance_id_ = joystickId;\r\n\tconst SDLUniquePtr<char> mapping { SDL_GetGamepadMappingForID(joystickId) };\r\n#else\r\n\tSDL_Joystick *const sdlJoystick = SDL_GameControllerGetJoystick(result.sdl_game_controller_);\r\n\tresult.instance_id_ = SDL_JoystickInstanceID(sdlJoystick);\r\n\tconst SDL_JoystickGUID guid = SDL_JoystickGetGUID(sdlJoystick);\r\n\tconst SDLUniquePtr<char> mapping { SDL_GameControllerMappingForGUID(guid) };\r\n#endif\r\n\tcontrollers_.push_back(result);\r\n\r\n\tif (mapping) {\r\n\t\tLog(\"Opened game controller with mapping:\\n{}\", mapping.get());\r\n\t}\r\n}\r\n\r\nvoid GameController::Remove(SDL_JoystickID instanceId)\r\n{\r\n\tLog(\"Removing game controller with instance id {}\", instanceId);\r\n\tfor (std::size_t i = 0; i < controllers_.size(); ++i) {\r\n\t\tconst GameController &controller = controllers_[i];\r\n\t\tif (controller.instance_id_ != instanceId)\r\n\t\t\tcontinue;\r\n\t\tcontrollers_.erase(controllers_.begin() + i);\r\n\t\treturn;\r\n\t}\r\n\tLog(\"Game controller not found with instance id: {}\", instanceId);\r\n}\r\n\r\nGameController *GameController::Get(SDL_JoystickID instanceId)\r\n{\r\n\tfor (auto &controller : controllers_) {\r\n\t\tif (controller.instance_id_ == instanceId)\r\n\t\t\treturn &controller;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nGameController *GameController::Get(const SDL_Event &event)\r\n{\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_GAMEPAD_AXIS_MOTION:\r\n\t\treturn Get(SDLC_EventGamepadAxis(event).which);\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_DOWN:\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_UP:\r\n\t\treturn Get(SDLC_EventGamepadButton(event).which);\r\n\tdefault:\r\n\t\treturn nullptr;\r\n\t}\r\n}\r\n\r\nconst std::vector<GameController> &GameController::All()\r\n{\r\n\treturn controllers_;\r\n}\r\n\r\nbool GameController::IsPressedOnAnyController(ControllerButton button, SDL_JoystickID *which)\r\n{\r\n\tfor (auto &controller : controllers_)\r\n\t\tif (controller.IsPressed(button)) {\r\n\t\t\tif (which != nullptr)\r\n\t\t\t\t*which = controller.instance_id_;\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\treturn false;\r\n}\r\n\r\nGamepadLayout GameController::getLayout(const SDL_Event &event)\r\n{\r\n#if defined(DEVILUTIONX_GAMEPAD_TYPE)\r\n\treturn GamepadLayout::\r\n\t    DEVILUTIONX_GAMEPAD_TYPE;\r\n#elif USE_SDL3\r\n\tswitch (SDL_GetGamepadTypeForID(event.gdevice.which)) {\r\n\tcase SDL_GAMEPAD_TYPE_XBOX360:\r\n\tcase SDL_GAMEPAD_TYPE_XBOXONE:\r\n\t\treturn GamepadLayout::Xbox;\r\n\tcase SDL_GAMEPAD_TYPE_PS3:\r\n\tcase SDL_GAMEPAD_TYPE_PS4:\r\n\tcase SDL_GAMEPAD_TYPE_PS5:\r\n\t\treturn GamepadLayout::PlayStation;\r\n\tcase SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:\r\n\tcase SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:\r\n\tcase SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:\r\n\tcase SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:\r\n\t\treturn GamepadLayout::Nintendo;\r\n\tdefault:\r\n\t\treturn GamepadLayout::Generic;\r\n\t}\r\n#else\r\n#if SDL_VERSION_ATLEAST(2, 0, 12)\r\n\tconst int index = event.cdevice.which;\r\n\tconst SDL_GameControllerType gamepadType = SDL_GameControllerTypeForIndex(index);\r\n\tswitch (gamepadType) {\r\n\tcase SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:\r\n#if SDL_VERSION_ATLEAST(2, 24, 0)\r\n\tcase SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:\r\n\tcase SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:\r\n\tcase SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:\r\n#endif\r\n\t\treturn GamepadLayout::Nintendo;\r\n\tcase SDL_CONTROLLER_TYPE_PS3:\r\n\tcase SDL_CONTROLLER_TYPE_PS4:\r\n#if SDL_VERSION_ATLEAST(2, 0, 14)\r\n\tcase SDL_CONTROLLER_TYPE_PS5:\r\n#endif\r\n\t\treturn GamepadLayout::PlayStation;\r\n\tcase SDL_CONTROLLER_TYPE_XBOXONE:\r\n\tcase SDL_CONTROLLER_TYPE_XBOX360:\r\n#if SDL_VERSION_ATLEAST(2, 0, 16)\r\n\tcase SDL_CONTROLLER_TYPE_GOOGLE_STADIA:\r\n\tcase SDL_CONTROLLER_TYPE_AMAZON_LUNA:\r\n#if SDL_VERSION_ATLEAST(2, 24, 0)\r\n\tcase SDL_CONTROLLER_TYPE_NVIDIA_SHIELD:\r\n#endif\r\n#endif\r\n\t\treturn GamepadLayout::Xbox;\r\n#if SDL_VERSION_ATLEAST(2, 0, 14)\r\n\tcase SDL_CONTROLLER_TYPE_VIRTUAL:\r\n#endif\r\n\tcase SDL_CONTROLLER_TYPE_UNKNOWN:\r\n#if SDL_VERSION_ATLEAST(2, 30, 0)\r\n\tcase SDL_CONTROLLER_TYPE_MAX:\r\n#endif\r\n\t\tbreak;\r\n\t}\r\n#endif\r\n\treturn GamepadLayout::Generic;\r\n#endif // !defined(DEVILUTIONX_GAMEPAD_TYPE)\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/devices/game_controller.h",
    "content": "#pragma once\r\n\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_gamepad.h>\r\n#include <SDL3/SDL_joystick.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/controller_buttons.h\"\r\n#include \"controls/game_controls.h\"\r\n\r\nnamespace devilution {\r\n\r\nclass GameController {\r\n\tstatic std::vector<GameController> controllers_;\r\n\r\npublic:\r\n#ifdef USE_SDL3\r\n\tstatic void Add(SDL_JoystickID joystickId);\r\n#else\r\n\tstatic void Add(int joystickIndex);\r\n#endif\r\n\tstatic void Remove(SDL_JoystickID instanceId);\r\n\tstatic GameController *Get(SDL_JoystickID instanceId);\r\n\tstatic GameController *Get(const SDL_Event &event);\r\n\tstatic const std::vector<GameController> &All();\r\n\tstatic bool IsPressedOnAnyController(ControllerButton button, SDL_JoystickID *which = nullptr);\r\n\r\n\t// Must be called exactly once at the start of each SDL input event.\r\n\tvoid UnlockTriggerState();\r\n\r\n\tControllerButton ToControllerButton(const SDL_Event &event);\r\n\r\n\tbool IsPressed(ControllerButton button) const;\r\n\tstatic bool ProcessAxisMotion(const SDL_Event &event);\r\n\r\n#ifdef USE_SDL3\r\n\tstatic SDL_GamepadButton ToSdlGameControllerButton(ControllerButton button);\r\n#else\r\n\tstatic SDL_GameControllerButton ToSdlGameControllerButton(ControllerButton button);\r\n#endif\r\n\r\n\tstatic GamepadLayout getLayout(const SDL_Event &event);\r\n\r\nprivate:\r\n#ifdef USE_SDL3\r\n\tSDL_Gamepad *sdl_game_controller_ = nullptr;\r\n#else\r\n\tSDL_GameController *sdl_game_controller_ = nullptr;\r\n#endif\r\n\r\n\tSDL_JoystickID instance_id_ = -1;\r\n\r\n\tControllerButton trigger_left_state_ = ControllerButton_NONE;\r\n\tControllerButton trigger_right_state_ = ControllerButton_NONE;\r\n\tbool trigger_left_is_down_ = false;\r\n\tbool trigger_right_is_down_ = false;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/devices/joystick.cpp",
    "content": "#include \"controls/devices/joystick.h\"\r\n\r\n#include <cstddef>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_joystick.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"controls/controller_motion.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution {\r\n\r\nstd::vector<Joystick> Joystick::joysticks_;\r\n\r\nStaticVector<ControllerButtonEvent, 4> Joystick::ToControllerButtonEvents(const SDL_Event &event)\r\n{\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_DOWN:\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_UP: {\r\n#ifdef USE_SDL3\r\n\t\tconst bool up = !event.jbutton.down;\r\n#else\r\n\t\tconst bool up = (event.jbutton.state == SDL_RELEASED);\r\n#endif\r\n#if defined(JOY_BUTTON_A) || defined(JOY_BUTTON_B) || defined(JOY_BUTTON_X) || defined(JOY_BUTTON_Y)                                            \\\r\n    || defined(JOY_BUTTON_LEFTSTICK) || defined(JOY_BUTTON_RIGHTSTICK) || defined(JOY_BUTTON_LEFTSHOULDER) || defined(JOY_BUTTON_RIGHTSHOULDER) \\\r\n    || defined(JOY_BUTTON_TRIGGERLEFT) || defined(JOY_BUTTON_TRIGGERRIGHT) || defined(JOY_BUTTON_START) || defined(JOY_BUTTON_BACK)             \\\r\n    || defined(JOY_BUTTON_DPAD_LEFT) || defined(JOY_BUTTON_DPAD_UP) || defined(JOY_BUTTON_DPAD_RIGHT) || defined(JOY_BUTTON_DPAD_DOWN)\r\n\t\tswitch (event.jbutton.button) {\r\n#ifdef JOY_BUTTON_A\r\n\t\tcase JOY_BUTTON_A:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_A, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_B\r\n\t\tcase JOY_BUTTON_B:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_B, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_X\r\n\t\tcase JOY_BUTTON_X:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_X, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_Y\r\n\t\tcase JOY_BUTTON_Y:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_Y, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_LEFTSTICK\r\n\t\tcase JOY_BUTTON_LEFTSTICK:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_LEFTSTICK, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_RIGHTSTICK\r\n\t\tcase JOY_BUTTON_RIGHTSTICK:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_RIGHTSTICK, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_LEFTSHOULDER\r\n\t\tcase JOY_BUTTON_LEFTSHOULDER:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_LEFTSHOULDER, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_RIGHTSHOULDER\r\n\t\tcase JOY_BUTTON_RIGHTSHOULDER:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_RIGHTSHOULDER, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_TRIGGERLEFT\r\n\t\tcase JOY_BUTTON_TRIGGERLEFT:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_AXIS_TRIGGERLEFT, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_TRIGGERRIGHT\r\n\t\tcase JOY_BUTTON_TRIGGERRIGHT:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_AXIS_TRIGGERRIGHT, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_START\r\n\t\tcase JOY_BUTTON_START:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_START, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_BACK\r\n\t\tcase JOY_BUTTON_BACK:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_BACK, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_LEFT\r\n\t\tcase JOY_BUTTON_DPAD_LEFT:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_LEFT, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_UP\r\n\t\tcase JOY_BUTTON_DPAD_UP:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_UP, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_RIGHT\r\n\t\tcase JOY_BUTTON_DPAD_RIGHT:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_RIGHT, up } };\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_DOWN\r\n\t\tcase JOY_BUTTON_DPAD_DOWN:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_DOWN, up } };\r\n#endif\r\n\t\tdefault:\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_IGNORE, up } };\r\n\t\t}\r\n#else\r\n\t\treturn { ControllerButtonEvent { ControllerButton_IGNORE, up } };\r\n#endif\r\n\t}\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_JOYSTICK_HAT_MOTION:\r\n#else\r\n\tcase SDL_JOYHATMOTION:\r\n#endif\r\n\t{\r\n\t\tJoystick *joystick = Get(event);\r\n\t\tif (joystick == nullptr)\r\n\t\t\treturn { ControllerButtonEvent { ControllerButton_IGNORE, false } };\r\n\t\tjoystick->UpdateHatState(event.jhat);\r\n\t\treturn joystick->GetHatEvents();\r\n\t}\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_JOYSTICK_AXIS_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_BALL_MOTION:\r\n#else\r\n\tcase SDL_JOYAXISMOTION:\r\n\tcase SDL_JOYBALLMOTION:\r\n#endif\r\n\t\t// ProcessAxisMotion() requires a ControllerButtonEvent parameter\r\n\t\t// so provide one here using ControllerButton_NONE\r\n\t\treturn { ControllerButtonEvent { ControllerButton_NONE, false } };\r\n\tdefault:\r\n\t\treturn {};\r\n\t}\r\n}\r\n\r\nStaticVector<ControllerButtonEvent, 4> Joystick::GetHatEvents()\r\n{\r\n\tStaticVector<ControllerButtonEvent, 4> hatEvents;\r\n\tif (hatState_[0].didStateChange)\r\n\t\thatEvents.emplace_back(ControllerButton_BUTTON_DPAD_UP, !hatState_[0].pressed);\r\n\tif (hatState_[1].didStateChange)\r\n\t\thatEvents.emplace_back(ControllerButton_BUTTON_DPAD_DOWN, !hatState_[1].pressed);\r\n\tif (hatState_[2].didStateChange)\r\n\t\thatEvents.emplace_back(ControllerButton_BUTTON_DPAD_LEFT, !hatState_[2].pressed);\r\n\tif (hatState_[3].didStateChange)\r\n\t\thatEvents.emplace_back(ControllerButton_BUTTON_DPAD_RIGHT, !hatState_[3].pressed);\r\n\tif (hatEvents.size() == 0)\r\n\t\thatEvents.emplace_back(ControllerButton_IGNORE, false);\r\n\treturn hatEvents;\r\n}\r\n\r\nvoid Joystick::UpdateHatState(const SDL_JoyHatEvent &event)\r\n{\r\n\tif (lockHatState_)\r\n\t\treturn;\r\n#if defined(JOY_HAT_DPAD_UP_HAT) && defined(JOY_HAT_DPAD_UP)\r\n\tif (event.hat == JOY_HAT_DPAD_UP_HAT) {\r\n\t\tHatState &hatState = hatState_[0];\r\n\t\tbool pressed = (event.value & JOY_HAT_DPAD_UP) != 0;\r\n\t\thatState.didStateChange = (pressed != hatState.pressed);\r\n\t\thatState.pressed = pressed;\r\n\t}\r\n#endif\r\n#if defined(JOY_HAT_DPAD_DOWN_HAT) && defined(JOY_HAT_DPAD_DOWN)\r\n\tif (event.hat == JOY_HAT_DPAD_DOWN_HAT) {\r\n\t\tHatState &hatState = hatState_[1];\r\n\t\tbool pressed = (event.value & JOY_HAT_DPAD_DOWN) != 0;\r\n\t\thatState.didStateChange = (pressed != hatState.pressed);\r\n\t\thatState.pressed = pressed;\r\n\t}\r\n#endif\r\n#if defined(JOY_HAT_DPAD_LEFT_HAT) && defined(JOY_HAT_DPAD_LEFT)\r\n\tif (event.hat == JOY_HAT_DPAD_LEFT_HAT) {\r\n\t\tHatState &hatState = hatState_[2];\r\n\t\tbool pressed = (event.value & JOY_HAT_DPAD_LEFT) != 0;\r\n\t\thatState.didStateChange = (pressed != hatState.pressed);\r\n\t\thatState.pressed = pressed;\r\n\t}\r\n#endif\r\n#if defined(JOY_HAT_DPAD_RIGHT_HAT) && defined(JOY_HAT_DPAD_RIGHT)\r\n\tif (event.hat == JOY_HAT_DPAD_RIGHT_HAT) {\r\n\t\tHatState &hatState = hatState_[3];\r\n\t\tbool pressed = (event.value & JOY_HAT_DPAD_RIGHT) != 0;\r\n\t\thatState.didStateChange = (pressed != hatState.pressed);\r\n\t\thatState.pressed = pressed;\r\n\t}\r\n#endif\r\n\tlockHatState_ = true;\r\n}\r\n\r\nvoid Joystick::UnlockHatState()\r\n{\r\n\tlockHatState_ = false;\r\n\tfor (HatState &hatState : hatState_)\r\n\t\thatState.didStateChange = false;\r\n}\r\n\r\nint Joystick::ToSdlJoyButton(ControllerButton button)\r\n{\r\n#if defined(JOY_BUTTON_A) || defined(JOY_BUTTON_B) || defined(JOY_BUTTON_X) || defined(JOY_BUTTON_Y)                                                \\\r\n    || defined(JOY_BUTTON_BACK) || defined(JOY_BUTTON_START) || defined(JOY_BUTTON_LEFTSTICK) || defined(JOY_BUTTON_RIGHTSTICK)                     \\\r\n    || defined(JOY_BUTTON_LEFTSHOULDER) || defined(JOY_BUTTON_RIGHTSHOULDER) || defined(JOY_BUTTON_TRIGGERLEFT) || defined(JOY_BUTTON_TRIGGERRIGHT) \\\r\n    || defined(JOY_BUTTON_DPAD_LEFT) || defined(JOY_BUTTON_DPAD_UP) || defined(JOY_BUTTON_DPAD_RIGHT) || defined(JOY_BUTTON_DPAD_DOWN)\r\n\tswitch (button) {\r\n#ifdef JOY_BUTTON_A\r\n\tcase ControllerButton_BUTTON_A:\r\n\t\treturn JOY_BUTTON_A;\r\n#endif\r\n#ifdef JOY_BUTTON_B\r\n\tcase ControllerButton_BUTTON_B:\r\n\t\treturn JOY_BUTTON_B;\r\n#endif\r\n#ifdef JOY_BUTTON_X\r\n\tcase ControllerButton_BUTTON_X:\r\n\t\treturn JOY_BUTTON_X;\r\n#endif\r\n#ifdef JOY_BUTTON_Y\r\n\tcase ControllerButton_BUTTON_Y:\r\n\t\treturn JOY_BUTTON_Y;\r\n#endif\r\n#ifdef JOY_BUTTON_BACK\r\n\tcase ControllerButton_BUTTON_BACK:\r\n\t\treturn JOY_BUTTON_BACK;\r\n#endif\r\n#ifdef JOY_BUTTON_START\r\n\tcase ControllerButton_BUTTON_START:\r\n\t\treturn JOY_BUTTON_START;\r\n#endif\r\n#ifdef JOY_BUTTON_LEFTSTICK\r\n\tcase ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn JOY_BUTTON_LEFTSTICK;\r\n#endif\r\n#ifdef JOY_BUTTON_RIGHTSTICK\r\n\tcase ControllerButton_BUTTON_RIGHTSTICK:\r\n\t\treturn JOY_BUTTON_RIGHTSTICK;\r\n#endif\r\n#ifdef JOY_BUTTON_LEFTSHOULDER\r\n\tcase ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\treturn JOY_BUTTON_LEFTSHOULDER;\r\n#endif\r\n#ifdef JOY_BUTTON_RIGHTSHOULDER\r\n\tcase ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\treturn JOY_BUTTON_RIGHTSHOULDER;\r\n#endif\r\n#ifdef JOY_BUTTON_TRIGGERLEFT\r\n\tcase ControllerButton_AXIS_TRIGGERLEFT:\r\n\t\treturn JOY_BUTTON_TRIGGERLEFT;\r\n#endif\r\n#ifdef JOY_BUTTON_TRIGGERRIGHT\r\n\tcase ControllerButton_AXIS_TRIGGERRIGHT:\r\n\t\treturn JOY_BUTTON_TRIGGERRIGHT;\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_UP\r\n\tcase ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn JOY_BUTTON_DPAD_UP;\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_DOWN\r\n\tcase ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn JOY_BUTTON_DPAD_DOWN;\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_LEFT\r\n\tcase ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn JOY_BUTTON_DPAD_LEFT;\r\n#endif\r\n#ifdef JOY_BUTTON_DPAD_RIGHT\r\n\tcase ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn JOY_BUTTON_DPAD_RIGHT;\r\n#endif\r\n\tdefault:\r\n\t\treturn -1;\r\n\t}\r\n#else\r\n\treturn -1;\r\n#endif\r\n}\r\n\r\n// NOLINTNEXTLINE(readability-convert-member-functions-to-static): Not static if joystick mappings are defined.\r\nbool Joystick::IsHatButtonPressed(ControllerButton button) const\r\n{\r\n#if (defined(JOY_HAT_DPAD_UP_HAT) && defined(JOY_HAT_DPAD_UP)) || (defined(JOY_HAT_DPAD_DOWN_HAT) && defined(JOY_HAT_DPAD_DOWN)) || (defined(JOY_HAT_DPAD_LEFT_HAT) && defined(JOY_HAT_DPAD_LEFT)) || (defined(JOY_HAT_DPAD_RIGHT_HAT) && defined(JOY_HAT_DPAD_RIGHT))\r\n\tswitch (button) {\r\n#if defined(JOY_HAT_DPAD_UP_HAT) && defined(JOY_HAT_DPAD_UP)\r\n\tcase ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn (SDL_JoystickGetHat(sdl_joystick_, JOY_HAT_DPAD_UP_HAT) & JOY_HAT_DPAD_UP) != 0;\r\n#endif\r\n#if defined(JOY_HAT_DPAD_DOWN_HAT) && defined(JOY_HAT_DPAD_DOWN)\r\n\tcase ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn (SDL_JoystickGetHat(sdl_joystick_, JOY_HAT_DPAD_DOWN_HAT) & JOY_HAT_DPAD_DOWN) != 0;\r\n#endif\r\n#if defined(JOY_HAT_DPAD_LEFT_HAT) && defined(JOY_HAT_DPAD_LEFT)\r\n\tcase ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn (SDL_JoystickGetHat(sdl_joystick_, JOY_HAT_DPAD_LEFT_HAT) & JOY_HAT_DPAD_LEFT) != 0;\r\n#endif\r\n#if defined(JOY_HAT_DPAD_RIGHT_HAT) && defined(JOY_HAT_DPAD_RIGHT)\r\n\tcase ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn (SDL_JoystickGetHat(sdl_joystick_, JOY_HAT_DPAD_RIGHT_HAT) & JOY_HAT_DPAD_RIGHT) != 0;\r\n#endif\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\nbool Joystick::IsPressed(ControllerButton button) const\r\n{\r\n\tif (sdl_joystick_ == nullptr)\r\n\t\treturn false;\r\n\tif (IsHatButtonPressed(button))\r\n\t\treturn true;\r\n\tconst int joyButton = ToSdlJoyButton(button);\r\n\tif (joyButton == -1)\r\n\t\treturn false;\r\n#ifdef USE_SDL3\r\n\tconst int numButtons = SDL_GetNumJoystickButtons(sdl_joystick_);\r\n\treturn joyButton < numButtons && SDL_GetJoystickButton(sdl_joystick_, joyButton);\r\n#else\r\n\tconst int numButtons = SDL_JoystickNumButtons(sdl_joystick_);\r\n\treturn joyButton < numButtons && SDL_JoystickGetButton(sdl_joystick_, joyButton) != 0;\r\n#endif\r\n}\r\n\r\nbool Joystick::ProcessAxisMotion(const SDL_Event &event)\r\n{\r\n\tif (event.type != SDL_EVENT_JOYSTICK_AXIS_MOTION) return false;\r\n\r\n#if defined(JOY_AXIS_LEFTX) || defined(JOY_AXIS_LEFTY) || defined(JOY_AXIS_RIGHTX) || defined(JOY_AXIS_RIGHTY)\r\n\tswitch (event.jaxis.axis) {\r\n#ifdef JOY_AXIS_LEFTX\r\n\tcase JOY_AXIS_LEFTX:\r\n\t\tleftStickXUnscaled = event.jaxis.value;\r\n\t\tleftStickNeedsScaling = true;\r\n\t\treturn true;\r\n#endif\r\n#ifdef JOY_AXIS_LEFTY\r\n\tcase JOY_AXIS_LEFTY:\r\n\t\tleftStickYUnscaled = -event.jaxis.value;\r\n\t\tleftStickNeedsScaling = true;\r\n\t\treturn true;\r\n#endif\r\n#ifdef JOY_AXIS_RIGHTX\r\n\tcase JOY_AXIS_RIGHTX:\r\n\t\trightStickXUnscaled = event.jaxis.value;\r\n\t\trightStickNeedsScaling = true;\r\n\t\treturn true;\r\n#endif\r\n#ifdef JOY_AXIS_RIGHTY\r\n\tcase JOY_AXIS_RIGHTY:\r\n\t\trightStickYUnscaled = -event.jaxis.value;\r\n\t\trightStickNeedsScaling = true;\r\n\t\treturn true;\r\n#endif\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\n#ifdef USE_SDL3\r\nvoid Joystick::Add(SDL_JoystickID id)\r\n{\r\n\tJoystick result;\r\n\tconst char *name = SDL_GetJoystickNameForID(id);\r\n\tif (name == nullptr) {\r\n\t\tLogWarn(\"Error getting name for joystick {}\", id, SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t} else {\r\n\t\tLog(\"Adding joystick {}: {}\", id, name);\r\n\t}\r\n\tresult.sdl_joystick_ = SDL_OpenJoystick(id);\r\n\tif (result.sdl_joystick_ == nullptr) {\r\n\t\tLogError(\"{}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn;\r\n\t}\r\n\tresult.instance_id_ = id;\r\n\tjoysticks_.push_back(result);\r\n}\r\n#else\r\nvoid Joystick::Add(int deviceIndex)\r\n{\r\n\tif (SDL_NumJoysticks() <= deviceIndex)\r\n\t\treturn;\r\n\tJoystick result;\r\n\tLog(\"Adding joystick {}: {}\", deviceIndex,\r\n\t    SDL_JoystickNameForIndex(deviceIndex));\r\n\tresult.sdl_joystick_ = SDL_JoystickOpen(deviceIndex);\r\n\tif (result.sdl_joystick_ == nullptr) {\r\n\t\tLogError(\"{}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn;\r\n\t}\r\n#ifndef USE_SDL1\r\n\tresult.instance_id_ = SDL_JoystickInstanceID(result.sdl_joystick_);\r\n#endif\r\n\tjoysticks_.push_back(result);\r\n}\r\n#endif\r\n\r\nvoid Joystick::Remove(SDL_JoystickID instanceId)\r\n{\r\n#ifndef USE_SDL1\r\n\tLog(\"Removing joystick (instance id: {})\", instanceId);\r\n\tfor (std::size_t i = 0; i < joysticks_.size(); ++i) {\r\n\t\tconst Joystick &joystick = joysticks_[i];\r\n\t\tif (joystick.instance_id_ != instanceId)\r\n\t\t\tcontinue;\r\n\t\tjoysticks_.erase(joysticks_.begin() + i);\r\n\t\treturn;\r\n\t}\r\n\tLog(\"Joystick not found with instance id: {}\", instanceId);\r\n#endif\r\n}\r\n\r\nconst std::vector<Joystick> &Joystick::All()\r\n{\r\n\treturn joysticks_;\r\n}\r\n\r\nJoystick *Joystick::Get(SDL_JoystickID instanceId)\r\n{\r\n\tfor (auto &joystick : joysticks_) {\r\n\t\tif (joystick.instance_id_ == instanceId)\r\n\t\t\treturn &joystick;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nJoystick *Joystick::Get(const SDL_Event &event)\r\n{\r\n\tswitch (event.type) {\r\n#ifndef USE_SDL1\r\n\tcase SDL_EVENT_JOYSTICK_AXIS_MOTION:\r\n\t\treturn Get(event.jaxis.which);\r\n\tcase SDL_EVENT_JOYSTICK_BALL_MOTION:\r\n\t\treturn Get(event.jball.which);\r\n\tcase SDL_EVENT_JOYSTICK_HAT_MOTION:\r\n\t\treturn Get(event.jhat.which);\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_DOWN:\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_UP:\r\n\t\treturn Get(event.jbutton.which);\r\n\tdefault:\r\n\t\treturn nullptr;\r\n#else\r\n\tcase SDL_JOYAXISMOTION:\r\n\tcase SDL_JOYBALLMOTION:\r\n\tcase SDL_JOYHATMOTION:\r\n\tcase SDL_JOYBUTTONDOWN:\r\n\tcase SDL_JOYBUTTONUP:\r\n\t\treturn joysticks_.empty() ? nullptr : &joysticks_[0];\r\n\tdefault:\r\n\t\treturn nullptr;\r\n#endif\r\n\t}\r\n}\r\n\r\nbool Joystick::IsPressedOnAnyJoystick(ControllerButton button)\r\n{\r\n\tfor (auto &joystick : joysticks_)\r\n\t\tif (joystick.IsPressed(button))\r\n\t\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/devices/joystick.h",
    "content": "#pragma once\r\n// Joystick mappings for SDL1 and additional buttons on SDL2.\r\n\r\n#include <array>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"controls/controller.h\"\r\n#include \"controls/controller_buttons.h\"\r\n#include \"utils/static_vector.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nclass Joystick {\r\n\tstatic std::vector<Joystick> joysticks_;\r\n\r\npublic:\r\n#ifdef USE_SDL3\r\n\tstatic void Add(SDL_JoystickID deviceIndex);\r\n#else\r\n\tstatic void Add(int deviceIndex);\r\n#endif\r\n\tstatic void Remove(SDL_JoystickID instanceId);\r\n\tstatic Joystick *Get(SDL_JoystickID instanceId);\r\n\tstatic Joystick *Get(const SDL_Event &event);\r\n\tstatic const std::vector<Joystick> &All();\r\n\tstatic bool IsPressedOnAnyJoystick(ControllerButton button);\r\n\r\n\t// Must be called exactly once at the start of each SDL input event.\r\n\tvoid UnlockHatState();\r\n\r\n\tstatic StaticVector<ControllerButtonEvent, 4> ToControllerButtonEvents(const SDL_Event &event);\r\n\tbool IsPressed(ControllerButton button) const;\r\n\tstatic bool ProcessAxisMotion(const SDL_Event &event);\r\n\r\n\tSDL_JoystickID instance_id() const\r\n\t{\r\n\t\treturn instance_id_;\r\n\t}\r\n\r\nprivate:\r\n\tstruct HatState {\r\n\t\tbool pressed;\r\n\t\tbool didStateChange;\r\n\t};\r\n\r\n\tstatic int ToSdlJoyButton(ControllerButton button);\r\n\r\n\tbool IsHatButtonPressed(ControllerButton button) const;\r\n\tStaticVector<ControllerButtonEvent, 4> GetHatEvents();\r\n\tvoid UpdateHatState(const SDL_JoyHatEvent &event);\r\n\r\n\tSDL_Joystick *sdl_joystick_ = NULL;\r\n\tSDL_JoystickID instance_id_ = -1;\r\n\tstd::array<HatState, 4> hatState_;\r\n\tbool lockHatState_ = false;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/devices/kbcontroller.cpp",
    "content": "#include \"controls/devices/kbcontroller.h\"\r\n\r\n#if HAS_KBCTRL == 1\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"controls/controller_motion.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution {\r\n\r\nControllerButton KbCtrlToControllerButton(const SDL_Event &event)\r\n{\r\n\tswitch (event.type) {\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_KEY_DOWN:\r\n\tcase SDL_EVENT_KEY_DOWN:\r\n\t\tswitch (event.key.key)\r\n#else\r\n\tcase SDL_KEYDOWN:\r\n\tcase SDL_KEYUP:\r\n\t\tswitch (event.key.keysym.sym)\r\n#endif\r\n\t\t{\r\n#ifdef KBCTRL_IGNORE_1\r\n\t\tcase KBCTRL_IGNORE_1:\r\n\t\t\treturn ControllerButton_IGNORE;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_A\r\n\t\tcase KBCTRL_BUTTON_A:\r\n\t\t\treturn ControllerButton_BUTTON_A;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_B\r\n\t\tcase KBCTRL_BUTTON_B: // Right button\r\n\t\t\treturn ControllerButton_BUTTON_B;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_X\r\n\t\tcase KBCTRL_BUTTON_X: // Left button\r\n\t\t\treturn ControllerButton_BUTTON_X;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_Y\r\n\t\tcase KBCTRL_BUTTON_Y:\r\n\t\t\treturn ControllerButton_BUTTON_Y;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_LEFTSTICK\r\n\t\tcase KBCTRL_BUTTON_LEFTSTICK:\r\n\t\t\treturn ControllerButton_BUTTON_LEFTSTICK;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_RIGHTSTICK\r\n\t\tcase KBCTRL_BUTTON_RIGHTSTICK:\r\n\t\t\treturn ControllerButton_BUTTON_RIGHTSTICK;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_LEFTSHOULDER\r\n\t\tcase KBCTRL_BUTTON_LEFTSHOULDER:\r\n\t\t\treturn ControllerButton_BUTTON_LEFTSHOULDER;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_RIGHTSHOULDER\r\n\t\tcase KBCTRL_BUTTON_RIGHTSHOULDER:\r\n\t\t\treturn ControllerButton_BUTTON_RIGHTSHOULDER;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_TRIGGERLEFT\r\n\t\tcase KBCTRL_BUTTON_TRIGGERLEFT:\r\n\t\t\treturn ControllerButton_AXIS_TRIGGERLEFT;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_TRIGGERRIGHT\r\n\t\tcase KBCTRL_BUTTON_TRIGGERRIGHT:\r\n\t\t\treturn ControllerButton_AXIS_TRIGGERRIGHT;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_START\r\n\t\tcase KBCTRL_BUTTON_START:\r\n\t\t\treturn ControllerButton_BUTTON_START;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_BACK\r\n\t\tcase KBCTRL_BUTTON_BACK:\r\n\t\t\treturn ControllerButton_BUTTON_BACK;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_UP\r\n\t\tcase KBCTRL_BUTTON_DPAD_UP:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_UP;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_DOWN\r\n\t\tcase KBCTRL_BUTTON_DPAD_DOWN:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_DOWN;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_LEFT\r\n\t\tcase KBCTRL_BUTTON_DPAD_LEFT:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_LEFT;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_RIGHT\r\n\t\tcase KBCTRL_BUTTON_DPAD_RIGHT:\r\n\t\t\treturn ControllerButton_BUTTON_DPAD_RIGHT;\r\n#endif\r\n\t\tdefault:\r\n\t\t\treturn ControllerButton_NONE;\r\n\t\t}\r\n\tdefault:\r\n\t\treturn ControllerButton_NONE;\r\n\t}\r\n}\r\n\r\nSDL_Keycode ControllerButtonToKbCtrlKeyCode(ControllerButton button)\r\n{\r\n\tswitch (button) {\r\n#ifdef KBCTRL_BUTTON_A\r\n\tcase ControllerButton_BUTTON_A:\r\n\t\treturn KBCTRL_BUTTON_A;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_B\r\n\tcase ControllerButton_BUTTON_B:\r\n\t\treturn KBCTRL_BUTTON_B;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_X\r\n\tcase ControllerButton_BUTTON_X:\r\n\t\treturn KBCTRL_BUTTON_X;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_Y\r\n\tcase ControllerButton_BUTTON_Y:\r\n\t\treturn KBCTRL_BUTTON_Y;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_BACK\r\n\tcase ControllerButton_BUTTON_BACK:\r\n\t\treturn KBCTRL_BUTTON_BACK;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_START\r\n\tcase ControllerButton_BUTTON_START:\r\n\t\treturn KBCTRL_BUTTON_START;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_LEFTSTICK\r\n\tcase ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn KBCTRL_BUTTON_LEFTSTICK;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_RIGHTSTICK\r\n\tcase ControllerButton_BUTTON_RIGHTSTICK:\r\n\t\treturn KBCTRL_BUTTON_RIGHTSTICK;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_LEFTSHOULDER\r\n\tcase ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\treturn KBCTRL_BUTTON_LEFTSHOULDER;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_RIGHTSHOULDER\r\n\tcase ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\treturn KBCTRL_BUTTON_RIGHTSHOULDER;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_TRIGGERLEFT\r\n\tcase ControllerButton_AXIS_TRIGGERLEFT:\r\n\t\treturn KBCTRL_BUTTON_TRIGGERLEFT;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_TRIGGERRIGHT\r\n\tcase ControllerButton_AXIS_TRIGGERRIGHT:\r\n\t\treturn KBCTRL_BUTTON_TRIGGERRIGHT;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_UP\r\n\tcase ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn KBCTRL_BUTTON_DPAD_UP;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_DOWN\r\n\tcase ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn KBCTRL_BUTTON_DPAD_DOWN;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_LEFT\r\n\tcase ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn KBCTRL_BUTTON_DPAD_LEFT;\r\n#endif\r\n#ifdef KBCTRL_BUTTON_DPAD_RIGHT\r\n\tcase ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn KBCTRL_BUTTON_DPAD_RIGHT;\r\n#endif\r\n\tdefault:\r\n\t\treturn SDLK_UNKNOWN;\r\n\t}\r\n}\r\n\r\nbool IsKbCtrlButtonPressed(ControllerButton button)\r\n{\r\n\tSDL_Keycode key_code = ControllerButtonToKbCtrlKeyCode(button);\r\n\tif (key_code == SDLK_UNKNOWN)\r\n\t\treturn false;\r\n#ifdef USE_SDL3\r\n\treturn SDL_GetKeyboardState(nullptr)[SDL_GetScancodeFromKey(key_code, nullptr)];\r\n#elif !defined(USE_SDL1)\r\n\treturn SDL_GetKeyboardState(nullptr)[SDL_GetScancodeFromKey(key_code)];\r\n#else\r\n\treturn SDL_GetKeyState(nullptr)[key_code];\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n#endif\r\n"
  },
  {
    "path": "Source/controls/devices/kbcontroller.h",
    "content": "#pragma once\r\n\r\n// Keyboard keys acting like gamepad buttons\r\n#ifndef HAS_KBCTRL\r\n#define HAS_KBCTRL 0\r\n#endif\r\n\r\n#if HAS_KBCTRL == 1\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"controls/controller_buttons.h\"\r\n\r\nnamespace devilution {\r\n\r\nControllerButton KbCtrlToControllerButton(const SDL_Event &event);\r\n\r\nSDL_Keycode ControllerButtonToKbCtrlKeyCode(ControllerButton button);\r\n\r\nbool IsKbCtrlButtonPressed(ControllerButton button);\r\n\r\n} // namespace devilution\r\n#endif\r\n"
  },
  {
    "path": "Source/controls/game_controls.cpp",
    "content": "#include \"controls/game_controls.h\"\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/controller_motion.h\"\r\n#ifndef USE_SDL1\r\n#include \"controls/devices/game_controller.h\"\r\n#endif\r\n#include \"controls/devices/joystick.h\"\r\n#include \"controls/padmapper.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"controls/touch/gamepad.h\"\r\n#include \"doom.h\"\r\n#include \"gamemenu.h\"\r\n#include \"gmenu.h\"\r\n#include \"options.h\"\r\n#include \"panels/spell_list.hpp\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool PadMenuNavigatorActive = false;\r\nbool PadHotspellMenuActive = false;\r\nControllerButton SuppressedButton = ControllerButton_NONE;\r\n\r\nnamespace {\r\n\r\nSDL_Keycode TranslateControllerButtonToGameMenuKey(ControllerButton controllerButton)\r\n{\r\n\tswitch (TranslateTo(GamepadType, controllerButton)) {\r\n\tcase ControllerButton_BUTTON_A:\r\n\tcase ControllerButton_BUTTON_Y:\r\n\t\treturn SDLK_RETURN;\r\n\tcase ControllerButton_BUTTON_B:\r\n\tcase ControllerButton_BUTTON_BACK:\r\n\tcase ControllerButton_BUTTON_START:\r\n\t\treturn SDLK_ESCAPE;\r\n\tcase ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn SDLK_TAB; // Map\r\n\tdefault:\r\n\t\treturn SDLK_UNKNOWN;\r\n\t}\r\n}\r\n\r\nSDL_Keycode TranslateControllerButtonToMenuKey(ControllerButton controllerButton)\r\n{\r\n\tswitch (TranslateTo(GamepadType, controllerButton)) {\r\n\tcase ControllerButton_BUTTON_A:\r\n\t\treturn SDLK_SPACE;\r\n\tcase ControllerButton_BUTTON_B:\r\n\tcase ControllerButton_BUTTON_BACK:\r\n\tcase ControllerButton_BUTTON_START:\r\n\t\treturn SDLK_ESCAPE;\r\n\tcase ControllerButton_BUTTON_Y:\r\n\t\treturn SDLK_RETURN;\r\n\tcase ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn SDLK_TAB; // Map\r\n\tcase ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\treturn SDLK_LEFT;\r\n\tcase ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\treturn SDLK_RIGHT;\r\n\tcase ControllerButton_BUTTON_DPAD_UP:\r\n\t\treturn SDLK_UP;\r\n\tcase ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\treturn SDLK_DOWN;\r\n\tdefault:\r\n\t\treturn SDLK_UNKNOWN;\r\n\t}\r\n}\r\n\r\nSDL_Keycode TranslateControllerButtonToQuestLogKey(ControllerButton controllerButton)\r\n{\r\n\tswitch (TranslateTo(GamepadType, controllerButton)) {\r\n\tcase ControllerButton_BUTTON_A:\r\n\tcase ControllerButton_BUTTON_Y:\r\n\t\treturn SDLK_RETURN;\r\n\tcase ControllerButton_BUTTON_B:\r\n\t\treturn SDLK_SPACE;\r\n\tcase ControllerButton_BUTTON_LEFTSTICK:\r\n\t\treturn SDLK_TAB; // Map\r\n\tdefault:\r\n\t\treturn SDLK_UNKNOWN;\r\n\t}\r\n}\r\n\r\nbool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, GameAction *action)\r\n{\r\n\tconst bool inGameMenu = InGameMenu();\r\n\r\n#ifndef USE_SDL1\r\n\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\tswitch (event.type) {\r\n#ifdef USE_SDL3\r\n\t\tcase SDL_EVENT_FINGER_DOWN:\r\n#else\r\n\t\tcase SDL_FINGERDOWN:\r\n#endif\r\n\t\t\tif (VirtualGamepadState.menuPanel.charButton.isHeld && VirtualGamepadState.menuPanel.charButton.didStateChange) {\r\n\t\t\t\t*action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.menuPanel.questsButton.isHeld && VirtualGamepadState.menuPanel.questsButton.didStateChange) {\r\n\t\t\t\t*action = GameAction(GameActionType_TOGGLE_QUEST_LOG);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.menuPanel.inventoryButton.isHeld && VirtualGamepadState.menuPanel.inventoryButton.didStateChange) {\r\n\t\t\t\t*action = GameAction(GameActionType_TOGGLE_INVENTORY);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.menuPanel.mapButton.isHeld && VirtualGamepadState.menuPanel.mapButton.didStateChange) {\r\n\t\t\t\t*action = GameActionSendKey { SDLK_TAB, false };\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.primaryActionButton.isHeld && VirtualGamepadState.primaryActionButton.didStateChange) {\r\n\t\t\t\tif (!inGameMenu && !QuestLogIsOpen && !SpellbookFlag) {\r\n\t\t\t\t\t*action = GameAction(GameActionType_PRIMARY_ACTION);\r\n\t\t\t\t\tif (ControllerActionHeld == GameActionType_NONE) {\r\n\t\t\t\t\t\tControllerActionHeld = GameActionType_PRIMARY_ACTION;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (sgpCurrentMenu != nullptr || IsPlayerInStore() || QuestLogIsOpen) {\r\n\t\t\t\t\t*action = GameActionSendKey { SDLK_RETURN, false };\r\n\t\t\t\t} else {\r\n\t\t\t\t\t*action = GameActionSendKey { SDLK_SPACE, false };\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.secondaryActionButton.isHeld && VirtualGamepadState.secondaryActionButton.didStateChange) {\r\n\t\t\t\tif (!inGameMenu && !QuestLogIsOpen && !SpellbookFlag) {\r\n\t\t\t\t\t*action = GameAction(GameActionType_SECONDARY_ACTION);\r\n\t\t\t\t\tif (ControllerActionHeld == GameActionType_NONE)\r\n\t\t\t\t\t\tControllerActionHeld = GameActionType_SECONDARY_ACTION;\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.spellActionButton.isHeld && VirtualGamepadState.spellActionButton.didStateChange) {\r\n\t\t\t\tif (!inGameMenu && !QuestLogIsOpen && !SpellbookFlag) {\r\n\t\t\t\t\t*action = GameAction(GameActionType_CAST_SPELL);\r\n\t\t\t\t\tif (ControllerActionHeld == GameActionType_NONE)\r\n\t\t\t\t\t\tControllerActionHeld = GameActionType_CAST_SPELL;\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.cancelButton.isHeld && VirtualGamepadState.cancelButton.didStateChange) {\r\n\t\t\t\tif (inGameMenu || DoomFlag || SpellSelectFlag)\r\n\t\t\t\t\t*action = GameActionSendKey { SDLK_ESCAPE, false };\r\n\t\t\t\telse if (invflag)\r\n\t\t\t\t\t*action = GameAction(GameActionType_TOGGLE_INVENTORY);\r\n\t\t\t\telse if (SpellbookFlag)\r\n\t\t\t\t\t*action = GameAction(GameActionType_TOGGLE_SPELL_BOOK);\r\n\t\t\t\telse if (QuestLogIsOpen)\r\n\t\t\t\t\t*action = GameAction(GameActionType_TOGGLE_QUEST_LOG);\r\n\t\t\t\telse if (CharFlag)\r\n\t\t\t\t\t*action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.healthButton.isHeld && VirtualGamepadState.healthButton.didStateChange) {\r\n\t\t\t\tif (!QuestLogIsOpen && !SpellbookFlag && !IsPlayerInStore())\r\n\t\t\t\t\t*action = GameAction(GameActionType_USE_HEALTH_POTION);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (VirtualGamepadState.manaButton.isHeld && VirtualGamepadState.manaButton.didStateChange) {\r\n\t\t\t\tif (!QuestLogIsOpen && !SpellbookFlag && !IsPlayerInStore())\r\n\t\t\t\t\t*action = GameAction(GameActionType_USE_MANA_POTION);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n#ifdef USE_SDL3\r\n\t\tcase SDL_EVENT_FINGER_UP:\r\n#else\r\n\t\tcase SDL_FINGERUP:\r\n#endif\r\n\t\t\tif ((!VirtualGamepadState.primaryActionButton.isHeld && ControllerActionHeld == GameActionType_PRIMARY_ACTION)\r\n\t\t\t    || (!VirtualGamepadState.secondaryActionButton.isHeld && ControllerActionHeld == GameActionType_SECONDARY_ACTION)\r\n\t\t\t    || (!VirtualGamepadState.spellActionButton.isHeld && ControllerActionHeld == GameActionType_CAST_SPELL)) {\r\n\t\t\t\tControllerActionHeld = GameActionType_NONE;\r\n\t\t\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tif (PadMenuNavigatorActive || PadHotspellMenuActive)\r\n\t\treturn false;\r\n\r\n\tSDL_Keycode translation = SDLK_UNKNOWN;\r\n\r\n\tif (gmenu_is_active() || IsPlayerInStore())\r\n\t\ttranslation = TranslateControllerButtonToGameMenuKey(ctrlEvent.button);\r\n\telse if (inGameMenu)\r\n\t\ttranslation = TranslateControllerButtonToMenuKey(ctrlEvent.button);\r\n\telse if (QuestLogIsOpen)\r\n\t\ttranslation = TranslateControllerButtonToQuestLogKey(ctrlEvent.button);\r\n\r\n\tif (translation != SDLK_UNKNOWN) {\r\n\t\t*action = GameActionSendKey { static_cast<uint32_t>(translation), ctrlEvent.up };\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanDeferToMovementHandler(const PadmapperOptions::Action &action)\r\n{\r\n\tif (action.boundInput.modifier != ControllerButton_NONE)\r\n\t\treturn false;\r\n\r\n\tif (SpellSelectFlag) {\r\n\t\tconst std::string_view prefix { \"QuickSpell\" };\r\n\t\tconst std::string_view key { action.key };\r\n\t\tif (key.size() >= prefix.size()) {\r\n\t\t\tconst std::string_view truncated { key.data(), prefix.size() };\r\n\t\t\tif (truncated == prefix)\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn IsAnyOf(action.boundInput.button,\r\n\t    ControllerButton_BUTTON_DPAD_UP,\r\n\t    ControllerButton_BUTTON_DPAD_DOWN,\r\n\t    ControllerButton_BUTTON_DPAD_LEFT,\r\n\t    ControllerButton_BUTTON_DPAD_RIGHT);\r\n}\r\n\r\nvoid PressControllerButton(ControllerButton button)\r\n{\r\n\tif (IsStashOpen) {\r\n\t\tswitch (button) {\r\n\t\tcase ControllerButton_BUTTON_BACK:\r\n\t\t\tStartGoldWithdraw();\r\n\t\t\treturn;\r\n\t\tcase ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\t\tStash.PreviousPage();\r\n\t\t\treturn;\r\n\t\tcase ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\t\tStash.NextPage();\r\n\t\t\treturn;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (PadHotspellMenuActive) {\r\n\t\tauto quickSpellAction = [](size_t slot) {\r\n\t\t\tif (SpellSelectFlag) {\r\n\t\t\t\tSetSpeedSpell(slot);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tif (!*GetOptions().Gameplay.quickCast)\r\n\t\t\t\tToggleSpell(slot);\r\n\t\t\telse\r\n\t\t\t\tQuickCast(slot);\r\n\t\t};\r\n\t\tswitch (button) {\r\n\t\tcase devilution::ControllerButton_BUTTON_A:\r\n\t\t\tquickSpellAction(2);\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_B:\r\n\t\t\tquickSpellAction(3);\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_X:\r\n\t\t\tquickSpellAction(0);\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_Y:\r\n\t\t\tquickSpellAction(1);\r\n\t\t\treturn;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (PadMenuNavigatorActive) {\r\n\t\tswitch (button) {\r\n\t\tcase devilution::ControllerButton_BUTTON_DPAD_UP:\r\n\t\t\tPressEscKey();\r\n\t\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\t\tPadHotspellMenuActive = false;\r\n\t\t\tPadMenuNavigatorActive = false;\r\n\t\t\tgamemenu_on();\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\t\tCycleAutomapType();\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\t\tProcessGameAction(GameAction { GameActionType_TOGGLE_CHARACTER_INFO });\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\t\tProcessGameAction(GameAction { GameActionType_TOGGLE_INVENTORY });\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_A:\r\n\t\t\tProcessGameAction(GameAction { GameActionType_TOGGLE_SPELL_BOOK });\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_B:\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_X:\r\n\t\t\tProcessGameAction(GameAction { GameActionType_TOGGLE_QUEST_LOG });\r\n\t\t\treturn;\r\n\t\tcase devilution::ControllerButton_BUTTON_Y:\r\n#ifdef __3DS__\r\n\t\t\tGetOptions().Graphics.zoom.SetValue(!*GetOptions().Graphics.zoom);\r\n\t\t\tCalcViewportGeometry();\r\n#endif\r\n\t\t\treturn;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tconst PadmapperOptions::Action *action = GetOptions().Padmapper.findAction(button, IsControllerButtonPressed);\r\n\tif (action == nullptr) return;\r\n\tif (IsMovementHandlerActive() && CanDeferToMovementHandler(*action)) return;\r\n\tPadmapperPress(button, *action);\r\n}\r\n\r\n} // namespace\r\n\r\nControllerButton TranslateTo(GamepadLayout layout, ControllerButton button)\r\n{\r\n\tif (layout != GamepadLayout::Nintendo)\r\n\t\treturn button;\r\n\r\n\tswitch (button) {\r\n\tcase ControllerButton_BUTTON_A:\r\n\t\treturn ControllerButton_BUTTON_B;\r\n\tcase ControllerButton_BUTTON_B:\r\n\t\treturn ControllerButton_BUTTON_A;\r\n\tcase ControllerButton_BUTTON_X:\r\n\t\treturn ControllerButton_BUTTON_Y;\r\n\tcase ControllerButton_BUTTON_Y:\r\n\t\treturn ControllerButton_BUTTON_X;\r\n\tdefault:\r\n\t\treturn button;\r\n\t}\r\n}\r\n\r\nbool SkipsMovie(ControllerButtonEvent ctrlEvent)\r\n{\r\n\treturn IsAnyOf(ctrlEvent.button,\r\n\t    ControllerButton_BUTTON_A,\r\n\t    ControllerButton_BUTTON_B,\r\n\t    ControllerButton_BUTTON_START,\r\n\t    ControllerButton_BUTTON_BACK);\r\n}\r\n\r\nbool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent)\r\n{\r\n\tif (ctrlEvent.button == ControllerButton_NONE)\r\n\t\treturn false;\r\n\tif (!ctrlEvent.up && ctrlEvent.button == SuppressedButton)\r\n\t\treturn false;\r\n\tconst std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(ctrlEvent);\r\n\treturn IsAnyOf(actionName, \"LeftMouseClick1\", \"LeftMouseClick2\", \"RightMouseClick1\", \"RightMouseClick2\");\r\n}\r\n\r\nAxisDirection GetMoveDirection()\r\n{\r\n\treturn GetLeftStickOrDpadDirection(true);\r\n}\r\n\r\nbool HandleControllerButtonEvent(const SDL_Event &event, const ControllerButtonEvent ctrlEvent, GameAction &action)\r\n{\r\n\tif (ctrlEvent.button == ControllerButton_IGNORE) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tstruct ButtonReleaser {\r\n\t\t~ButtonReleaser()\r\n\t\t{\r\n\t\t\tif (ctrlEvent.up) PadmapperRelease(ctrlEvent.button, /*invokeAction=*/false);\r\n\t\t}\r\n\t\tControllerButtonEvent ctrlEvent;\r\n\t};\r\n\r\n\tconst ButtonReleaser buttonReleaser { ctrlEvent };\r\n\tconst bool isGamepadMotion = IsControllerMotion(event);\r\n\tif (!isGamepadMotion) {\r\n\t\tSimulateRightStickWithPadmapper(ctrlEvent);\r\n\t}\r\n\tDetectInputMethod(event, ctrlEvent);\r\n\tif (isGamepadMotion) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (ctrlEvent.button != ControllerButton_NONE && ctrlEvent.button == SuppressedButton) {\r\n\t\tif (!ctrlEvent.up)\r\n\t\t\treturn true;\r\n\t\tSuppressedButton = ControllerButton_NONE;\r\n\t}\r\n\r\n\tif (ctrlEvent.up && !PadmapperActionNameTriggeredByButtonEvent(ctrlEvent).empty()) {\r\n\t\t// Button press may have brought up a menu;\r\n\t\t// don't confuse release of that button with intent to interact with the menu\r\n\t\tPadmapperRelease(ctrlEvent.button, /*invokeAction=*/true);\r\n\t\treturn true;\r\n\t} else if (GetGameAction(event, ctrlEvent, &action)) {\r\n\t\tProcessGameAction(action);\r\n\t\treturn true;\r\n\t} else if (ctrlEvent.button != ControllerButton_NONE) {\r\n\t\tif (!ctrlEvent.up)\r\n\t\t\tPressControllerButton(ctrlEvent.button);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/game_controls.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/axis_direction.h\"\r\n#include \"controls/controller.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum GameActionType : uint8_t {\r\n\tGameActionType_NONE,\r\n\tGameActionType_USE_HEALTH_POTION,\r\n\tGameActionType_USE_MANA_POTION,\r\n\tGameActionType_PRIMARY_ACTION,   // Talk to towners, click on inv items, attack, etc.\r\n\tGameActionType_SECONDARY_ACTION, // Open chests, doors, pickup items.\r\n\tGameActionType_CAST_SPELL,\r\n\tGameActionType_TOGGLE_INVENTORY,\r\n\tGameActionType_TOGGLE_CHARACTER_INFO,\r\n\tGameActionType_TOGGLE_QUICK_SPELL_MENU,\r\n\tGameActionType_TOGGLE_SPELL_BOOK,\r\n\tGameActionType_TOGGLE_QUEST_LOG,\r\n\tGameActionType_SEND_KEY,\r\n};\r\n\r\nstruct GameActionSendKey {\r\n\tuint32_t vk_code;\r\n\tbool up;\r\n};\r\n\r\nstruct GameAction {\r\n\tGameActionType type;\r\n\r\n\tGameAction()\r\n\t    : type(GameActionType_NONE)\r\n\t{\r\n\t}\r\n\r\n\texplicit GameAction(GameActionType type)\r\n\t    : type(type)\r\n\t{\r\n\t}\r\n\r\n\tGameAction(GameActionSendKey send_key)\r\n\t    : type(GameActionType_SEND_KEY)\r\n\t    , send_key(send_key)\r\n\t{\r\n\t}\r\n\r\n\tunion {\r\n\t\tGameActionSendKey send_key;\r\n\t};\r\n};\r\n\r\nControllerButton TranslateTo(GamepadLayout layout, ControllerButton button);\r\n\r\nbool SkipsMovie(ControllerButtonEvent ctrlEvent);\r\n\r\nbool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent);\r\n\r\nAxisDirection GetMoveDirection();\r\n\r\nbool HandleControllerButtonEvent(const SDL_Event &event, const ControllerButtonEvent ctrlEvent, GameAction &action);\r\n\r\nextern bool PadMenuNavigatorActive;\r\nextern bool PadHotspellMenuActive;\r\n\r\n// Tracks the button most recently used as a modifier for another button.\r\n//\r\n// If two buttons are pressed simultaneously, SDL sends two events for which both buttons are in the pressed state.\r\n// The event processor may interpret the second event's button as a modifier for the action taken when processing the first event.\r\n// The code for the modifier will be stored here, and the event processor can check this value when processing the second event to suppress it.\r\nextern ControllerButton SuppressedButton;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/input.h",
    "content": "#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/controller.h\"\r\n#include \"controls/controller_motion.h\"\r\n\r\nnamespace devilution {\r\n\r\ninline bool PollEvent(SDL_Event *event)\r\n{\r\n#ifdef USE_SDL3\r\n\tconst bool result = SDL_PollEvent(event);\r\n#else\r\n\tconst bool result = SDL_PollEvent(event) != 0;\r\n#endif\r\n\tif (result) {\r\n\t\tUnlockControllerState(*event);\r\n\t\tProcessControllerMotion(*event);\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/keymapper.cpp",
    "content": "#include \"controls/keymapper.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"control/control.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nbool IsTextEntryKey(SDL_Keycode vkey)\r\n{\r\n\treturn IsAnyOf(vkey, SDLK_ESCAPE, SDLK_RETURN, SDLK_KP_ENTER, SDLK_BACKSPACE, SDLK_DOWN, SDLK_UP)\r\n#ifdef USE_SDL3\r\n\t    || (vkey >= SDLK_SPACE && vkey <= SDLK_Z);\r\n#else\r\n\t    || (vkey >= SDLK_SPACE && vkey <= SDLK_z);\r\n#endif\r\n}\r\n\r\nbool IsNumberEntryKey(SDL_Keycode vkey)\r\n{\r\n\treturn ((vkey >= SDLK_0 && vkey <= SDLK_9) || vkey == SDLK_BACKSPACE);\r\n}\r\n\r\nSDL_Keycode ToAsciiUpper(SDL_Keycode key)\r\n{\r\n\tif (\r\n#ifdef USE_SDL3\r\n\t    key >= SDLK_A && key <= SDLK_Z\r\n#else\r\n\t    key >= SDLK_a && key <= SDLK_z\r\n#endif\r\n\t) {\r\n\t\treturn static_cast<SDL_Keycode>(static_cast<int32_t>(key) - ('a' - 'A'));\r\n\t}\r\n\treturn key;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid KeymapperPress(SDL_Keycode key)\r\n{\r\n\tkey = ToAsciiUpper(key);\r\n\tconst KeymapperOptions::Action *action = GetOptions().Keymapper.findAction(static_cast<uint32_t>(key));\r\n\tif (action == nullptr || !action->actionPressed || !action->isEnabled()) return;\r\n\r\n\t// TODO: This should be handled outside of the keymapper.\r\n\tif (ChatFlag) return;\r\n\r\n\taction->actionPressed();\r\n}\r\n\r\nvoid KeymapperRelease(SDL_Keycode key)\r\n{\r\n\tkey = ToAsciiUpper(key);\r\n\tconst KeymapperOptions::Action *action = GetOptions().Keymapper.findAction(static_cast<uint32_t>(key));\r\n\tif (action == nullptr || !action->actionReleased || !action->isEnabled()) return;\r\n\r\n\t// TODO: This should be handled outside of the keymapper.\r\n\tif ((ChatFlag && IsTextEntryKey(key)) || (DropGoldFlag && IsNumberEntryKey(key))) return;\r\n\r\n\taction->actionReleased();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/keymapper.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nvoid KeymapperPress(SDL_Keycode key);\r\nvoid KeymapperRelease(SDL_Keycode key);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/menu_controls.cpp",
    "content": "#include \"controls/menu_controls.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"controls/axis_direction.h\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/controller.h\"\r\n#include \"controls/controller_motion.h\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"controls/remap_keyboard.h\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\nMenuAction GetMenuHeldUpDownAction()\r\n{\r\n\tstatic AxisDirectionRepeater repeater;\r\n\tconst AxisDirection dir = repeater.Get(GetLeftStickOrDpadDirection(false));\r\n\tswitch (dir.y) {\r\n\tcase AxisDirectionY_UP:\r\n\t\treturn MenuAction_UP;\r\n\tcase AxisDirectionY_DOWN:\r\n\t\treturn MenuAction_DOWN;\r\n\tdefault:\r\n\t\treturn MenuAction_NONE;\r\n\t}\r\n}\r\n\r\nstd::vector<MenuAction> GetMenuActions(const SDL_Event &event)\r\n{\r\n\tstd::vector<MenuAction> menuActions;\r\n\tfor (const ControllerButtonEvent ctrlEvent : ToControllerButtonEvents(event)) {\r\n\t\tif (ctrlEvent.button == ControllerButton_IGNORE) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst bool isGamepadMotion = IsControllerMotion(event);\r\n\t\tDetectInputMethod(event, ctrlEvent);\r\n\t\tif (isGamepadMotion) {\r\n\t\t\tmenuActions.push_back(GetMenuHeldUpDownAction());\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (!ctrlEvent.up) {\r\n\t\t\tswitch (TranslateTo(GamepadType, ctrlEvent.button)) {\r\n\t\t\tcase ControllerButton_BUTTON_A:\r\n\t\t\tcase ControllerButton_BUTTON_START:\r\n\t\t\t\tmenuActions.push_back(MenuAction_SELECT);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ControllerButton_BUTTON_BACK:\r\n\t\t\tcase ControllerButton_BUTTON_B:\r\n\t\t\t\tmenuActions.push_back(MenuAction_BACK);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ControllerButton_BUTTON_X:\r\n\t\t\t\tmenuActions.push_back(MenuAction_DELETE);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ControllerButton_BUTTON_DPAD_UP:\r\n\t\t\tcase ControllerButton_BUTTON_DPAD_DOWN:\r\n\t\t\t\tmenuActions.push_back(GetMenuHeldUpDownAction());\r\n\t\t\t\tbreak;\r\n\t\t\tcase ControllerButton_BUTTON_DPAD_LEFT:\r\n\t\t\t\tmenuActions.push_back(MenuAction_LEFT);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ControllerButton_BUTTON_DPAD_RIGHT:\r\n\t\t\t\tmenuActions.push_back(MenuAction_RIGHT);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ControllerButton_BUTTON_LEFTSHOULDER:\r\n\t\t\t\tmenuActions.push_back(MenuAction_PAGE_UP);\r\n\t\t\t\tbreak;\r\n\t\t\tcase ControllerButton_BUTTON_RIGHTSHOULDER:\r\n\t\t\t\tmenuActions.push_back(MenuAction_PAGE_DOWN);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (!menuActions.empty()) {\r\n\t\treturn menuActions;\r\n\t}\r\n\r\n\tif (event.type ==\r\n#ifdef USE_SDL3\r\n\t    SDL_EVENT_MOUSE_BUTTON_DOWN\r\n#else\r\n\t    SDL_MOUSEBUTTONDOWN\r\n#endif\r\n\t) {\r\n\t\tswitch (event.button.button) {\r\n\t\tcase SDL_BUTTON_X1:\r\n#if !SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t\tcase 8:\r\n#endif\r\n\t\t\treturn { MenuAction_BACK };\r\n\t\t}\r\n\t}\r\n\r\n#if HAS_KBCTRL == 0\r\n\tif (event.type == SDL_EVENT_KEY_DOWN) {\r\n\t\tSDL_Keycode sym = SDLC_EventKey(event);\r\n\t\tremap_keyboard_key(&sym);\r\n\t\tswitch (sym) {\r\n\t\tcase SDLK_UP:\r\n\t\t\treturn { MenuAction_UP };\r\n\t\tcase SDLK_DOWN:\r\n\t\t\treturn { MenuAction_DOWN };\r\n\t\tcase SDLK_TAB:\r\n\t\t\tif ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0) {\r\n\t\t\t\treturn { MenuAction_UP };\r\n\t\t\t}\r\n\t\t\treturn { MenuAction_DOWN };\r\n\t\tcase SDLK_PAGEUP:\r\n\t\t\treturn { MenuAction_PAGE_UP };\r\n\t\tcase SDLK_PAGEDOWN:\r\n\t\t\treturn { MenuAction_PAGE_DOWN };\r\n\t\tcase SDLK_RETURN:\r\n\t\t\tif ((SDL_GetModState() & SDL_KMOD_ALT) == 0) {\r\n\t\t\t\treturn { MenuAction_SELECT };\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SDLK_KP_ENTER:\r\n\t\t\treturn { MenuAction_SELECT };\r\n\t\tcase SDLK_SPACE:\r\n\t\t\tif (!IsTextInputActive()) {\r\n\t\t\t\treturn { MenuAction_SELECT };\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SDLK_DELETE:\r\n\t\t\tif (!IsTextInputActive()) {\r\n\t\t\t\treturn { MenuAction_DELETE };\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SDLK_LEFT:\r\n\t\t\tif (!IsTextInputActive()) {\r\n\t\t\t\treturn { MenuAction_LEFT };\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SDLK_RIGHT:\r\n\t\t\tif (!IsTextInputActive()) {\r\n\t\t\t\treturn { MenuAction_RIGHT };\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase SDLK_ESCAPE:\r\n\t\t\treturn { MenuAction_BACK };\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\treturn {};\r\n} // namespace devilution\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/menu_controls.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nenum MenuAction : uint8_t {\r\n\tMenuAction_NONE,\r\n\tMenuAction_SELECT,\r\n\tMenuAction_BACK,\r\n\tMenuAction_DELETE,\r\n\r\n\tMenuAction_UP,\r\n\tMenuAction_DOWN,\r\n\tMenuAction_LEFT,\r\n\tMenuAction_RIGHT,\r\n\r\n\tMenuAction_PAGE_UP,\r\n\tMenuAction_PAGE_DOWN,\r\n};\r\n\r\nstd::vector<MenuAction> GetMenuActions(const SDL_Event &event);\r\n\r\n/** Menu action from holding the left stick or DPad. */\r\nMenuAction GetMenuHeldUpDownAction();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/modifier_hints.cpp",
    "content": "#include \"controls/modifier_hints.h\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/controller_motion.h\"\r\n#include \"controls/game_controls.h\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"options.h\"\r\n#include \"panels/spell_book.hpp\"\r\n#include \"panels/spell_icons.hpp\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n/** Vertical distance between text lines. */\r\nconstexpr int LineHeight = 25;\r\n\r\n/** Horizontal margin of the hints circle from panel edge. */\r\nconstexpr int CircleMarginX = 16;\r\n\r\n/** Distance between the panel top and the circle top. */\r\nconstexpr int CircleTop = 101;\r\n\r\n/** Spell icon side size. */\r\nconstexpr int IconSize = 37;\r\n\r\nconstexpr int HintBoxSize = 39;\r\nconstexpr int HintBoxMargin = 5;\r\n\r\nOptionalOwnedClxSpriteList hintBox;\r\nOptionalOwnedClxSpriteList hintBoxBackground;\r\nOptionalOwnedClxSpriteList hintIcons;\r\n\r\nenum HintIcon : uint8_t {\r\n\tIconChar,\r\n\tIconInv,\r\n\tIconQuests,\r\n\tIconSpells,\r\n\tIconMap,\r\n\tIconMenu,\r\n\tIconNull\r\n};\r\n\r\nstruct CircleMenuHint {\r\n\tCircleMenuHint(HintIcon top, HintIcon right, HintIcon bottom, HintIcon left)\r\n\t    : top(top)\r\n\t    , right(right)\r\n\t    , bottom(bottom)\r\n\t    , left(left)\r\n\t{\r\n\t}\r\n\r\n\tHintIcon top;\r\n\tHintIcon right;\r\n\tHintIcon bottom;\r\n\tHintIcon left;\r\n};\r\n\r\n/**\r\n * @brief Draws hint text for a four button layout with the top/left edge of the bounding box at the position given by origin.\r\n * @param out The output buffer to draw on.\r\n * @param hint Struct describing the icon to draw.\r\n * @param origin Top left corner of the layout (relative to the output buffer).\r\n */\r\nvoid DrawCircleMenuHint(const Surface &out, const CircleMenuHint &hint, const Point &origin)\r\n{\r\n\tconst Displacement backgroundDisplacement = { (HintBoxSize - IconSize) / 2 + 1, (HintBoxSize - IconSize) / 2 - 1 };\r\n\tconst Point hintBoxPositions[4] = {\r\n\t\torigin + Displacement { 0, LineHeight - HintBoxSize },\r\n\t\torigin + Displacement { HintBoxSize + HintBoxMargin, LineHeight - HintBoxSize * 2 - HintBoxMargin },\r\n\t\torigin + Displacement { HintBoxSize + HintBoxMargin, LineHeight + HintBoxMargin },\r\n\t\torigin + Displacement { HintBoxSize * 2 + HintBoxMargin * 2, LineHeight - HintBoxSize }\r\n\t};\r\n\tconst Point iconPositions[4] = {\r\n\t\thintBoxPositions[0] + backgroundDisplacement,\r\n\t\thintBoxPositions[1] + backgroundDisplacement,\r\n\t\thintBoxPositions[2] + backgroundDisplacement,\r\n\t\thintBoxPositions[3] + backgroundDisplacement,\r\n\t};\r\n\tconst uint8_t iconIndices[4] { hint.left, hint.top, hint.bottom, hint.right };\r\n\r\n\tfor (int slot = 0; slot < 4; ++slot) {\r\n\t\tif (iconIndices[slot] == HintIcon::IconNull)\r\n\t\t\tcontinue;\r\n\r\n\t\tRenderClxSprite(out, (*hintBoxBackground)[0], iconPositions[slot]);\r\n\t\tRenderClxSprite(out.subregion(iconPositions[slot].x, iconPositions[slot].y, 37, 38), (*hintIcons)[iconIndices[slot]], { 0, 0 });\r\n\t\tRenderClxSprite(out, (*hintBox)[0], hintBoxPositions[slot]);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Draws hint text for a four button layout with the top/left edge of the bounding box at the position given by origin plus the icon for the spell mapped to that entry.\r\n * @param out The output buffer to draw on.\r\n * @param origin Top left corner of the layout (relative to the output buffer).\r\n */\r\nvoid DrawSpellsCircleMenuHint(const Surface &out, const Point &origin)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tconst Displacement spellIconDisplacement = { (HintBoxSize - IconSize) / 2 + 1, HintBoxSize - (HintBoxSize - IconSize) / 2 - 1 };\r\n\tconst Point hintBoxPositions[4] = {\r\n\t\torigin + Displacement { 0, LineHeight - HintBoxSize },\r\n\t\torigin + Displacement { HintBoxSize + HintBoxMargin, LineHeight - HintBoxSize * 2 - HintBoxMargin },\r\n\t\torigin + Displacement { HintBoxSize + HintBoxMargin, LineHeight + HintBoxMargin },\r\n\t\torigin + Displacement { HintBoxSize * 2 + HintBoxMargin * 2, LineHeight - HintBoxSize }\r\n\t};\r\n\tconst Point spellIconPositions[4] = {\r\n\t\thintBoxPositions[0] + spellIconDisplacement,\r\n\t\thintBoxPositions[1] + spellIconDisplacement,\r\n\t\thintBoxPositions[2] + spellIconDisplacement,\r\n\t\thintBoxPositions[3] + spellIconDisplacement,\r\n\t};\r\n\tconst uint64_t spells = myPlayer._pAblSpells | myPlayer._pMemSpells | myPlayer._pScrlSpells | myPlayer._pISpells;\r\n\tSpellID splId;\r\n\tSpellType splType;\r\n\r\n\tfor (int slot = 0; slot < 4; ++slot) {\r\n\t\tsplId = myPlayer._pSplHotKey[slot];\r\n\r\n\t\tif (IsValidSpell(splId) && (spells & GetSpellBitmask(splId)) != 0)\r\n\t\t\tsplType = (leveltype == DTYPE_TOWN && !GetSpellData(splId).isAllowedInTown()) ? SpellType::Invalid : myPlayer._pSplTHotKey[slot];\r\n\t\telse {\r\n\t\t\tsplType = SpellType::Invalid;\r\n\t\t\tsplId = SpellID::Null;\r\n\t\t}\r\n\r\n\t\tSetSpellTrans(splType);\r\n\t\tDrawSmallSpellIcon(out, spellIconPositions[slot], splId);\r\n\t\tRenderClxSprite(out, (*hintBox)[0], hintBoxPositions[slot]);\r\n\t}\r\n}\r\n\r\nvoid DrawGamepadMenuNavigator(const Surface &out)\r\n{\r\n\tif (!PadMenuNavigatorActive || SimulatingMouseWithPadmapper)\r\n\t\treturn;\r\n\tstatic const CircleMenuHint DPad(/*top=*/HintIcon::IconMenu, /*right=*/HintIcon::IconInv, /*bottom=*/HintIcon::IconMap, /*left=*/HintIcon::IconChar);\r\n\tstatic const CircleMenuHint Buttons(/*top=*/HintIcon::IconNull, /*right=*/HintIcon::IconNull, /*bottom=*/HintIcon::IconSpells, /*left=*/HintIcon::IconQuests);\r\n\tconst Rectangle &mainPanel = GetMainPanel();\r\n\tDrawCircleMenuHint(out, DPad, { mainPanel.position.x + CircleMarginX, mainPanel.position.y - CircleTop });\r\n\tDrawCircleMenuHint(out, Buttons, { mainPanel.position.x + mainPanel.size.width - HintBoxSize * 3 - CircleMarginX - HintBoxMargin * 2, mainPanel.position.y - CircleTop });\r\n}\r\n\r\nvoid DrawGamepadHotspellMenu(const Surface &out)\r\n{\r\n\tif (!PadHotspellMenuActive || SimulatingMouseWithPadmapper)\r\n\t\treturn;\r\n\r\n\tconst Rectangle &mainPanel = GetMainPanel();\r\n\tDrawSpellsCircleMenuHint(out, { mainPanel.position.x + mainPanel.size.width - HintBoxSize * 3 - CircleMarginX - HintBoxMargin * 2, mainPanel.position.y - CircleTop });\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InitModifierHints()\r\n{\r\n\thintBox = LoadClx(\"data\\\\hintbox.clx\");\r\n\thintBoxBackground = LoadClx(\"data\\\\hintboxbackground.clx\");\r\n\thintIcons = LoadClx(\"data\\\\hinticons.clx\");\r\n}\r\n\r\nvoid FreeModifierHints()\r\n{\r\n\thintIcons = std::nullopt;\r\n\thintBoxBackground = std::nullopt;\r\n\thintBox = std::nullopt;\r\n}\r\n\r\nvoid DrawControllerModifierHints(const Surface &out)\r\n{\r\n\tDrawGamepadMenuNavigator(out);\r\n\tDrawGamepadHotspellMenu(out);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/modifier_hints.h",
    "content": "#pragma once\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid DrawControllerModifierHints(const Surface &out);\r\nvoid InitModifierHints();\r\nvoid FreeModifierHints();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/padmapper.cpp",
    "content": "#include \"controls/padmapper.hpp\"\r\n\r\n#include <array>\r\n\r\n#include \"controller.h\"\r\n#include \"game_controls.h\"\r\n#include \"options.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\nstd::array<const PadmapperOptions::Action *, enum_size<ControllerButton>::value> ButtonToReleaseAction;\r\n} // namespace\r\n\r\nvoid PadmapperPress(ControllerButton button, const PadmapperOptions::Action &action)\r\n{\r\n\tif (action.actionPressed) action.actionPressed();\r\n\tSuppressedButton = action.boundInput.modifier;\r\n\tButtonToReleaseAction[static_cast<size_t>(button)] = &action;\r\n}\r\n\r\nvoid PadmapperRelease(ControllerButton button, bool invokeAction)\r\n{\r\n\tif (invokeAction) {\r\n\t\tconst PadmapperOptions::Action *action = ButtonToReleaseAction[static_cast<size_t>(button)];\r\n\t\tif (action == nullptr)\r\n\t\t\treturn; // Ignore unmapped buttons.\r\n\r\n\t\t// Check that the action can be triggered.\r\n\t\tif (action->actionReleased && action->isEnabled())\r\n\t\t\taction->actionReleased();\r\n\t}\r\n\tButtonToReleaseAction[static_cast<size_t>(button)] = nullptr;\r\n}\r\n\r\nbool PadmapperIsActionActive(std::string_view actionName)\r\n{\r\n\tfor (const PadmapperOptions::Action &action : GetOptions().Padmapper.actions) {\r\n\t\tif (action.key != actionName)\r\n\t\t\tcontinue;\r\n\t\tconst PadmapperOptions::Action *releaseAction = ButtonToReleaseAction[static_cast<size_t>(action.boundInput.button)];\r\n\t\treturn releaseAction != nullptr && releaseAction->key == actionName;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid PadmapperReleaseAllActiveButtons()\r\n{\r\n\tfor (const PadmapperOptions::Action *action : ButtonToReleaseAction) {\r\n\t\tif (action != nullptr) {\r\n\t\t\tPadmapperRelease(action->boundInput.button, /*invokeAction=*/true);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nstd::string_view PadmapperActionNameTriggeredByButtonEvent(ControllerButtonEvent ctrlEvent)\r\n{\r\n\tif (!ctrlEvent.up) {\r\n\t\tconst PadmapperOptions::Action *pressAction = GetOptions().Padmapper.findAction(ctrlEvent.button, IsControllerButtonPressed);\r\n\t\tif (pressAction == nullptr) return {};\r\n\t\treturn pressAction->key;\r\n\t}\r\n\tconst PadmapperOptions::Action *releaseAction = ButtonToReleaseAction[static_cast<size_t>(ctrlEvent.button)];\r\n\tif (releaseAction == nullptr) return {};\r\n\treturn releaseAction->key;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/padmapper.hpp",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\n#include \"controls/controller_buttons.h\"\r\n#include \"options.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid PadmapperPress(ControllerButton button, const PadmapperOptions::Action &action);\r\nvoid PadmapperRelease(ControllerButton button, bool invokeAction);\r\nvoid PadmapperReleaseAllActiveButtons();\r\n[[nodiscard]] bool PadmapperIsActionActive(std::string_view actionName);\r\n[[nodiscard]] std::string_view PadmapperActionNameTriggeredByButtonEvent(ControllerButtonEvent ctrlEvent);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/plrctrls.cpp",
    "content": "#include \"controls/plrctrls.h\"\r\n\r\n#include <algorithm>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <list>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_gamepad.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"automap.h\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/controller_motion.h\"\r\n#ifndef USE_SDL1\r\n#include \"controls/devices/game_controller.h\"\r\n#endif\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/game_controls.h\"\r\n#include \"controls/touch/gamepad.h\"\r\n#include \"cursor.h\"\r\n#include \"doom.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"gmenu.h\"\r\n#include \"help.h\"\r\n#include \"hwcursor.hpp\"\r\n#include \"inv.h\"\r\n#include \"items.h\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"levels/town.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"minitext.h\"\r\n#include \"missiles.h\"\r\n#include \"panels/spell_icons.hpp\"\r\n#include \"panels/spell_list.hpp\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"qol/chatlog.h\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"towners.h\"\r\n#include \"track.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nGameActionType ControllerActionHeld = GameActionType_NONE;\r\n\r\nbool StandToggle = false;\r\n\r\nint pcurstrig = -1;\r\nMissile *pcursmissile = nullptr;\r\nquest_id pcursquest = Q_INVALID;\r\n\r\n/**\r\n * Native game menu, controlled by simulating a keyboard.\r\n */\r\nbool InGameMenu()\r\n{\r\n\treturn IsPlayerInStore()\r\n\t    || HelpFlag\r\n\t    || ChatLogFlag\r\n\t    || ChatFlag\r\n\t    || qtextflag\r\n\t    || gmenu_is_active()\r\n\t    || PauseMode == 2\r\n\t    || (MyPlayer != nullptr && MyPlayer->_pInvincible && MyPlayer->hasNoLife());\r\n}\r\n\r\nnamespace {\r\n\r\nint Slot = SLOTXY_INV_FIRST;\r\nPoint ActiveStashSlot = InvalidStashPoint;\r\nint PreviousInventoryColumn = -1;\r\nbool BeltReturnsToStash = false;\r\n\r\nconst Direction FaceDir[3][3] = {\r\n\t// NONE             UP                DOWN\r\n\t{ Direction::South, Direction::North, Direction::South },        // NONE\r\n\t{ Direction::West, Direction::NorthWest, Direction::SouthWest }, // LEFT\r\n\t{ Direction::East, Direction::NorthEast, Direction::SouthEast }, // RIGHT\r\n};\r\n\r\n/**\r\n * Number of angles to turn to face the coordinate\r\n * @param destination Tile coordinates\r\n * @return -1 == down\r\n */\r\nint GetRotaryDistance(Point destination)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer.position.future == destination)\r\n\t\treturn -1;\r\n\r\n\tconst int d1 = static_cast<int>(myPlayer._pdir);\r\n\tconst int d2 = static_cast<int>(GetDirection(myPlayer.position.future, destination));\r\n\r\n\tconst int d = std::abs(d1 - d2);\r\n\tif (d > 4)\r\n\t\treturn 4 - (d % 4);\r\n\r\n\treturn d;\r\n}\r\n\r\n/**\r\n * @brief Get the best case walking steps to coordinates\r\n * @param position Tile coordinates\r\n */\r\nint GetMinDistance(Point position)\r\n{\r\n\treturn MyPlayer->position.future.WalkingDistance(position);\r\n}\r\n\r\n/**\r\n * @brief Get walking steps to coordinate\r\n * @param destination Tile coordinates\r\n * @param maxDistance the max number of steps to search\r\n * @return number of steps, or 0 if not reachable\r\n */\r\nint GetDistance(Point destination, int maxDistance)\r\n{\r\n\tif (GetMinDistance(destination) > maxDistance) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tint8_t walkpath[MaxPathLengthPlayer];\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tconst int steps = FindPath(CanStep, [&myPlayer](Point position) { return PosOkPlayer(myPlayer, position); }, myPlayer.position.future, destination, walkpath, std::min<size_t>(maxDistance, MaxPathLengthPlayer));\r\n\tif (steps > maxDistance)\r\n\t\treturn 0;\r\n\r\n\treturn steps;\r\n}\r\n\r\n/**\r\n * @brief Get distance to coordinate\r\n * @param destination Tile coordinates\r\n */\r\nint GetDistanceRanged(Point destination)\r\n{\r\n\treturn MyPlayer->position.future.ExactDistance(destination);\r\n}\r\n\r\nvoid FindItemOrObject()\r\n{\r\n\tconst WorldTilePosition futurePosition = MyPlayer->position.future;\r\n\tint rotations = 5;\r\n\r\n\tauto searchArea = PointsInRectangleColMajor(WorldTileRectangle { futurePosition, 1 });\r\n\r\n\tfor (const WorldTilePosition targetPosition : searchArea) {\r\n\t\t// As the player can not stand on the edge of the map this is safe from OOB\r\n\t\tconst int8_t itemId = dItem[targetPosition.x][targetPosition.y] - 1;\r\n\t\tif (itemId < 0) {\r\n\t\t\t// there shouldn't be any items that occupy multiple ground tiles, but just in case only considering positive indexes here\r\n\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst Item &item = Items[itemId];\r\n\t\tif (item.isEmpty() || item.selectionRegion == SelectionRegion::None) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst int newRotations = GetRotaryDistance(targetPosition);\r\n\t\tif (rotations < newRotations) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (targetPosition != futurePosition && GetDistance(targetPosition, 1) == 0) {\r\n\t\t\t// Don't check the tile we're leaving if the player is walking\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\trotations = newRotations;\r\n\t\tpcursitem = itemId;\r\n\t\tcursPosition = targetPosition;\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_TOWN || pcursitem != -1) {\r\n\t\treturn; // Don't look for objects in town\r\n\t}\r\n\r\n\tfor (const WorldTilePosition targetPosition : searchArea) {\r\n\t\tObject *object = FindObjectAtPosition(targetPosition);\r\n\t\tif (object == nullptr || !object->canInteractWith()) {\r\n\t\t\t// No object or non-interactive object\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (targetPosition == futurePosition && object->_oDoorFlag) {\r\n\t\t\tcontinue; // Ignore doorway so we don't get stuck behind barrels\r\n\t\t}\r\n\r\n\t\tconst int newRotations = GetRotaryDistance(targetPosition);\r\n\t\tif (rotations < newRotations) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (targetPosition != futurePosition && GetDistance(targetPosition, 1) == 0) {\r\n\t\t\t// Don't check the tile we're leaving if the player is walking\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (object->IsDisabled()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\trotations = newRotations;\r\n\t\tObjectUnderCursor = object;\r\n\t\tcursPosition = targetPosition;\r\n\t}\r\n}\r\n\r\nvoid CheckTownersNearby()\r\n{\r\n\tfor (size_t i = 0; i < GetNumTowners(); i++) {\r\n\t\tconst int distance = GetDistance(Towners[i].position, 2);\r\n\t\tif (distance == 0)\r\n\t\t\tcontinue;\r\n\t\tif (!IsTownerPresent(Towners[i]._ttype))\r\n\t\t\tcontinue;\r\n\t\tpcursmonst = static_cast<int>(i);\r\n\t}\r\n}\r\n\r\nbool HasRangedSpell()\r\n{\r\n\tconst SpellID spl = MyPlayer->_pRSpell;\r\n\r\n\treturn spl != SpellID::Invalid\r\n\t    && spl != SpellID::TownPortal\r\n\t    && spl != SpellID::Teleport\r\n\t    && GetSpellData(spl).isTargeted()\r\n\t    && !GetSpellData(spl).isAllowedInTown();\r\n}\r\n\r\nbool CanTargetMonster(const Monster &monster)\r\n{\r\n\tif ((monster.flags & MFLAG_HIDDEN) != 0)\r\n\t\treturn false;\r\n\tif (monster.isPlayerMinion())\r\n\t\treturn false;\r\n\tif (monster.hasNoLife()) // dead\r\n\t\treturn false;\r\n\r\n\tif (!IsTileLit(monster.position.tile)) // not visible\r\n\t\treturn false;\r\n\r\n\tconst int mx = monster.position.tile.x;\r\n\tconst int my = monster.position.tile.y;\r\n\tif (dMonster[mx][my] == 0)\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid FindRangedTarget()\r\n{\r\n\tint rotations = 0;\r\n\tint distance = 0;\r\n\tbool canTalk = false;\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst int mi = ActiveMonsters[i];\r\n\t\tconst Monster &monster = Monsters[mi];\r\n\r\n\t\tif (!CanTargetMonster(monster))\r\n\t\t\tcontinue;\r\n\r\n\t\tconst bool newCanTalk = CanTalkToMonst(monster);\r\n\t\tif (pcursmonst != -1 && !canTalk && newCanTalk)\r\n\t\t\tcontinue;\r\n\t\tconst int newDdistance = GetDistanceRanged(monster.position.future);\r\n\t\tconst int newRotations = GetRotaryDistance(monster.position.future);\r\n\t\tif (pcursmonst != -1 && canTalk == newCanTalk) {\r\n\t\t\tif (distance < newDdistance)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (distance == newDdistance && rotations < newRotations)\r\n\t\t\t\tcontinue;\r\n\t\t}\r\n\t\tdistance = newDdistance;\r\n\t\trotations = newRotations;\r\n\t\tcanTalk = newCanTalk;\r\n\t\tpcursmonst = mi;\r\n\t}\r\n}\r\n\r\nvoid FindMeleeTarget()\r\n{\r\n\tbool visited[MAXDUNX][MAXDUNY] = { {} };\r\n\tint maxSteps = 25; // Max steps for FindPath is 25\r\n\tint rotations = 0;\r\n\tbool canTalk = false;\r\n\r\n\tstruct SearchNode {\r\n\t\tint x, y;\r\n\t\tint steps;\r\n\t};\r\n\tstd::list<SearchNode> queue;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\t{\r\n\t\tconst int startX = myPlayer.position.future.x;\r\n\t\tconst int startY = myPlayer.position.future.y;\r\n\t\tvisited[startX][startY] = true;\r\n\t\tqueue.push_back({ startX, startY, 0 });\r\n\t}\r\n\r\n\twhile (!queue.empty()) {\r\n\t\tconst SearchNode node = queue.front();\r\n\t\tqueue.pop_front();\r\n\r\n\t\tfor (auto pathDir : PathDirs) {\r\n\t\t\tconst int dx = node.x + pathDir.deltaX;\r\n\t\t\tconst int dy = node.y + pathDir.deltaY;\r\n\r\n\t\t\tif (visited[dx][dy])\r\n\t\t\t\tcontinue; // already visisted\r\n\r\n\t\t\tif (node.steps > maxSteps) {\r\n\t\t\t\tvisited[dx][dy] = true;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (!PosOkPlayer(myPlayer, { dx, dy })) {\r\n\t\t\t\tvisited[dx][dy] = true;\r\n\r\n\t\t\t\tif (dMonster[dx][dy] != 0) {\r\n\t\t\t\t\tconst int mi = std::abs(dMonster[dx][dy]) - 1;\r\n\t\t\t\t\tconst Monster &monster = Monsters[mi];\r\n\t\t\t\t\tif (CanTargetMonster(monster)) {\r\n\t\t\t\t\t\tconst bool newCanTalk = CanTalkToMonst(monster);\r\n\t\t\t\t\t\tif (pcursmonst != -1 && !canTalk && newCanTalk)\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tconst int newRotations = GetRotaryDistance({ dx, dy });\r\n\t\t\t\t\t\tif (pcursmonst != -1 && canTalk == newCanTalk && rotations < newRotations)\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\trotations = newRotations;\r\n\t\t\t\t\t\tcanTalk = newCanTalk;\r\n\t\t\t\t\t\tpcursmonst = mi;\r\n\t\t\t\t\t\tif (!canTalk)\r\n\t\t\t\t\t\t\tmaxSteps = node.steps; // Monsters found, cap search to current steps\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (CanStep({ node.x, node.y }, { dx, dy })) {\r\n\t\t\t\tqueue.push_back({ dx, dy, node.steps + 1 });\r\n\t\t\t\tvisited[dx][dy] = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CheckMonstersNearby()\r\n{\r\n\tif (MyPlayer->UsesRangedWeapon() || HasRangedSpell()) {\r\n\t\tFindRangedTarget();\r\n\t\treturn;\r\n\t}\r\n\r\n\tFindMeleeTarget();\r\n}\r\n\r\nvoid CheckPlayerNearby()\r\n{\r\n\tint newDdistance;\r\n\tint rotations = 0;\r\n\tint distance = 0;\r\n\r\n\tif (pcursmonst != -1)\r\n\t\treturn;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tconst SpellID spl = myPlayer._pRSpell;\r\n\tif (myPlayer.friendlyMode && spl != SpellID::Resurrect && spl != SpellID::HealOther)\r\n\t\treturn;\r\n\r\n\tfor (const Player &player : Players) {\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tcontinue;\r\n\t\tconst int mx = player.position.future.x;\r\n\t\tconst int my = player.position.future.y;\r\n\t\tif (dPlayer[mx][my] == 0\r\n\t\t    || !IsTileLit(player.position.future)\r\n\t\t    || (player.hasNoLife() && spl != SpellID::Resurrect))\r\n\t\t\tcontinue;\r\n\r\n\t\tif (myPlayer.UsesRangedWeapon() || HasRangedSpell() || spl == SpellID::HealOther) {\r\n\t\t\tnewDdistance = GetDistanceRanged(player.position.future);\r\n\t\t} else {\r\n\t\t\tnewDdistance = GetDistance(player.position.future, distance);\r\n\t\t\tif (newDdistance == 0)\r\n\t\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (PlayerUnderCursor != nullptr && distance < newDdistance)\r\n\t\t\tcontinue;\r\n\t\tconst int newRotations = GetRotaryDistance(player.position.future);\r\n\t\tif (PlayerUnderCursor != nullptr && distance == newDdistance && rotations < newRotations)\r\n\t\t\tcontinue;\r\n\r\n\t\tdistance = newDdistance;\r\n\t\trotations = newRotations;\r\n\t\tPlayerUnderCursor = &player;\r\n\t}\r\n}\r\n\r\nvoid FindActor()\r\n{\r\n\tif (leveltype != DTYPE_TOWN)\r\n\t\tCheckMonstersNearby();\r\n\telse\r\n\t\tCheckTownersNearby();\r\n\r\n\tif (gbIsMultiplayer)\r\n\t\tCheckPlayerNearby();\r\n}\r\n\r\nvoid FindTrigger()\r\n{\r\n\tint rotations = 0;\r\n\tint distance = 0;\r\n\r\n\tif (pcursitem != -1 || ObjectUnderCursor != nullptr)\r\n\t\treturn; // Prefer showing items/objects over triggers (use of cursm* conflicts)\r\n\r\n\tfor (auto &missile : Missiles) {\r\n\t\tif (missile._mitype == MissileID::TownPortal || missile._mitype == MissileID::RedPortal) {\r\n\t\t\tconst int newDistance = GetDistance(missile.position.tile, 2);\r\n\t\t\tif (newDistance == 0)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (pcursmissile != nullptr && distance < newDistance)\r\n\t\t\t\tcontinue;\r\n\t\t\tconst int newRotations = GetRotaryDistance(missile.position.tile);\r\n\t\t\tif (pcursmissile != nullptr && distance == newDistance && rotations < newRotations)\r\n\t\t\t\tcontinue;\r\n\t\t\tcursPosition = missile.position.tile;\r\n\t\t\tpcursmissile = &missile;\r\n\t\t\tdistance = newDistance;\r\n\t\t\trotations = newRotations;\r\n\t\t}\r\n\t}\r\n\r\n\tif (pcursmissile == nullptr) {\r\n\t\tfor (int i = 0; i < numtrigs; i++) {\r\n\t\t\tconst int tx = trigs[i].position.x;\r\n\t\t\tint ty = trigs[i].position.y;\r\n\t\t\tif (trigs[i]._tlvl == 13)\r\n\t\t\t\tty -= 1;\r\n\t\t\tconst int newDistance = GetDistance({ tx, ty }, 2);\r\n\t\t\tif (newDistance == 0)\r\n\t\t\t\tcontinue;\r\n\t\t\tcursPosition = { tx, ty };\r\n\t\t\tpcurstrig = i;\r\n\t\t}\r\n\r\n\t\tif (pcurstrig == -1) {\r\n\t\t\tfor (auto &quest : Quests) {\r\n\t\t\t\tif (quest._qidx == Q_BETRAYER || currlevel != quest._qlevel || quest._qslvl == 0)\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tconst int newDistance = GetDistance(quest.position, 2);\r\n\t\t\t\tif (newDistance == 0)\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tcursPosition = quest.position;\r\n\t\t\t\tpcursquest = quest._qidx;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (pcursmonst != -1 || PlayerUnderCursor != nullptr || cursPosition.x == -1 || cursPosition.y == -1)\r\n\t\treturn; // Prefer monster/player info text\r\n\r\n\tCheckTrigForce();\r\n\tCheckTown();\r\n\tCheckRportal();\r\n}\r\n\r\nbool IsStandingGround()\r\n{\r\n\tif (ControlMode == ControlTypes::Gamepad) {\r\n\t\tconst ControllerButtonCombo standGroundCombo = GetOptions().Padmapper.ButtonComboForAction(\"StandGround\");\r\n\t\treturn StandToggle || IsControllerButtonComboPressed(standGroundCombo);\r\n\t}\r\n#ifndef USE_SDL1\r\n\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\treturn VirtualGamepadState.standButton.isHeld;\r\n\t}\r\n#endif\r\n\treturn false;\r\n}\r\n\r\nvoid Interact()\r\n{\r\n\tif (leveltype == DTYPE_TOWN && pcursmonst != -1) {\r\n\t\tNetSendCmdLocParam1(true, CMD_TALKXY, Towners[pcursmonst].position, pcursmonst);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (leveltype != DTYPE_TOWN && IsStandingGround()) {\r\n\t\tDirection pdir = myPlayer._pdir;\r\n\t\tconst AxisDirection moveDir = GetMoveDirection();\r\n\t\tconst bool motion = moveDir.x != AxisDirectionX_NONE || moveDir.y != AxisDirectionY_NONE;\r\n\t\tif (motion) {\r\n\t\t\tpdir = FaceDir[static_cast<std::size_t>(moveDir.x)][static_cast<std::size_t>(moveDir.y)];\r\n\t\t}\r\n\r\n\t\tPoint position = myPlayer.position.tile + pdir;\r\n\t\tif (pcursmonst != -1 && !motion) {\r\n\t\t\tposition = Monsters[pcursmonst].position.tile;\r\n\t\t}\r\n\r\n\t\tNetSendCmdLoc(MyPlayerId, true, myPlayer.UsesRangedWeapon() ? CMD_RATTACKXY : CMD_SATTACKXY, position);\r\n\t\tLastPlayerAction = PlayerActionType::Attack;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (pcursmonst != -1) {\r\n\t\tif (!myPlayer.UsesRangedWeapon() || CanTalkToMonst(Monsters[pcursmonst])) {\r\n\t\t\tNetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);\r\n\t\t} else {\r\n\t\t\tNetSendCmdParam1(true, CMD_RATTACKID, pcursmonst);\r\n\t\t}\r\n\t\tLastPlayerAction = PlayerActionType::AttackMonsterTarget;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (leveltype != DTYPE_TOWN && PlayerUnderCursor != nullptr && !PlayerUnderCursor->hasNoLife() && !myPlayer.friendlyMode) {\r\n\t\tNetSendCmdParam1(true, myPlayer.UsesRangedWeapon() ? CMD_RATTACKPID : CMD_ATTACKPID, PlayerUnderCursor->getId());\r\n\t\tLastPlayerAction = PlayerActionType::AttackPlayerTarget;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (ObjectUnderCursor != nullptr) {\r\n\t\tNetSendCmdLoc(MyPlayerId, true, CMD_OPOBJXY, cursPosition);\r\n\t\tLastPlayerAction = PlayerActionType::OperateObject;\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\nvoid AttrIncBtnSnap(AxisDirection dir)\r\n{\r\n\tstatic AxisDirectionRepeater repeater;\r\n\tdir = repeater.Get(dir);\r\n\tif (dir.y == AxisDirectionY_NONE)\r\n\t\treturn;\r\n\r\n\tif (CharPanelButtonActive && MyPlayer->_pStatPts <= 0)\r\n\t\treturn;\r\n\r\n\t// first, find our cursor location\r\n\tint slot = 0;\r\n\tRectangle button;\r\n\tfor (int i = 0; i < 4; i++) {\r\n\t\tbutton = CharPanelButtonRect[i];\r\n\t\tbutton.position = GetPanelPosition(UiPanels::Character, button.position);\r\n\t\tif (button.contains(MousePosition)) {\r\n\t\t\tslot = i;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (dir.y == AxisDirectionY_UP) {\r\n\t\tif (slot > 0)\r\n\t\t\t--slot;\r\n\t} else if (dir.y == AxisDirectionY_DOWN) {\r\n\t\tif (slot < 3)\r\n\t\t\t++slot;\r\n\t}\r\n\r\n\t// move cursor to our new location\r\n\tbutton = CharPanelButtonRect[slot];\r\n\tbutton.position = GetPanelPosition(UiPanels::Character, button.position);\r\n\tSetCursorPos(button.Center());\r\n}\r\n\r\nPoint InvGetEquipSlotCoord(const inv_body_loc invSlot)\r\n{\r\n\tPoint result = GetPanelPosition(UiPanels::Inventory);\r\n\tswitch (invSlot) {\r\n\tcase INVLOC_HEAD:\r\n\t\tresult.x += InvRect[SLOTXY_HEAD].Center().x;\r\n\t\tresult.y += InvRect[SLOTXY_HEAD].Center().y;\r\n\t\tbreak;\r\n\tcase INVLOC_RING_LEFT:\r\n\t\tresult.x += InvRect[SLOTXY_RING_LEFT].Center().x;\r\n\t\tresult.y += InvRect[SLOTXY_RING_LEFT].Center().y;\r\n\t\tbreak;\r\n\tcase INVLOC_RING_RIGHT:\r\n\t\tresult.x += InvRect[SLOTXY_RING_RIGHT].Center().x;\r\n\t\tresult.y += InvRect[SLOTXY_RING_RIGHT].Center().y;\r\n\t\tbreak;\r\n\tcase INVLOC_AMULET:\r\n\t\tresult.x += InvRect[SLOTXY_AMULET].Center().x;\r\n\t\tresult.y += InvRect[SLOTXY_AMULET].Center().y;\r\n\t\tbreak;\r\n\tcase INVLOC_HAND_LEFT:\r\n\t\tresult.x += InvRect[SLOTXY_HAND_LEFT].Center().x;\r\n\t\tresult.y += InvRect[SLOTXY_HAND_LEFT].Center().y;\r\n\t\tbreak;\r\n\tcase INVLOC_HAND_RIGHT:\r\n\t\tresult.x += InvRect[SLOTXY_HAND_RIGHT].Center().x;\r\n\t\tresult.y += InvRect[SLOTXY_HAND_RIGHT].Center().y;\r\n\t\tbreak;\r\n\tcase INVLOC_CHEST:\r\n\t\tresult.x += InvRect[SLOTXY_CHEST].Center().x;\r\n\t\tresult.y += InvRect[SLOTXY_CHEST].Center().y;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nPoint InvGetEquipSlotCoordFromInvSlot(const inv_xy_slot slot)\r\n{\r\n\tif (slot == SLOTXY_HEAD) {\r\n\t\treturn InvGetEquipSlotCoord(INVLOC_HEAD);\r\n\t}\r\n\tif (slot == SLOTXY_RING_LEFT) {\r\n\t\treturn InvGetEquipSlotCoord(INVLOC_RING_LEFT);\r\n\t}\r\n\tif (slot == SLOTXY_RING_RIGHT) {\r\n\t\treturn InvGetEquipSlotCoord(INVLOC_RING_RIGHT);\r\n\t}\r\n\tif (slot == SLOTXY_AMULET) {\r\n\t\treturn InvGetEquipSlotCoord(INVLOC_AMULET);\r\n\t}\r\n\tif (slot == SLOTXY_HAND_LEFT) {\r\n\t\treturn InvGetEquipSlotCoord(INVLOC_HAND_LEFT);\r\n\t}\r\n\tif (slot == SLOTXY_HAND_RIGHT) {\r\n\t\treturn InvGetEquipSlotCoord(INVLOC_HAND_RIGHT);\r\n\t}\r\n\tif (slot == SLOTXY_CHEST) {\r\n\t\treturn InvGetEquipSlotCoord(INVLOC_CHEST);\r\n\t}\r\n\r\n\treturn {};\r\n}\r\n\r\n/**\r\n * Get coordinates for a given slot\r\n */\r\nPoint GetSlotCoord(int slot)\r\n{\r\n\tif (slot >= SLOTXY_BELT_FIRST && slot <= SLOTXY_BELT_LAST) {\r\n\t\treturn GetPanelPosition(UiPanels::Main, InvRect[slot].Center());\r\n\t}\r\n\r\n\treturn GetPanelPosition(UiPanels::Inventory, InvRect[slot].Center());\r\n}\r\n\r\n/**\r\n * Return the item id of the current slot\r\n */\r\nint GetItemIdOnSlot(int slot)\r\n{\r\n\tif (slot >= SLOTXY_INV_FIRST && slot <= SLOTXY_INV_LAST) {\r\n\t\treturn std::abs(MyPlayer->InvGrid[slot - SLOTXY_INV_FIRST]);\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\n/**\r\n * Get item size (grid size) on the slot specified. Returns 1x1 if none exists.\r\n */\r\nSize GetItemSizeOnSlot(int slot)\r\n{\r\n\tif (slot >= SLOTXY_INV_FIRST && slot <= SLOTXY_INV_LAST) {\r\n\t\tconst int8_t ii = GetItemIdOnSlot(slot);\r\n\t\tif (ii != 0) {\r\n\t\t\tconst Item &item = MyPlayer->InvList[ii - 1];\r\n\t\t\tif (!item.isEmpty()) {\r\n\t\t\t\treturn GetInventorySize(item);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn { 1, 1 };\r\n}\r\n\r\n/**\r\n * Get item size (grid size) on the slot specified. Returns 1x1 if none exists.\r\n */\r\nSize GetItemSizeOnSlot(Point slot)\r\n{\r\n\tif (Rectangle { { 0, 0 }, { 10, 10 } }.contains(slot)) {\r\n\t\tconst StashStruct::StashCell ii = Stash.GetItemIdAtPosition(slot);\r\n\t\tif (ii != StashStruct::EmptyCell) {\r\n\t\t\tconst Item &item = Stash.stashList[ii];\r\n\t\t\tif (!item.isEmpty()) {\r\n\t\t\t\treturn GetInventorySize(item);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn { 1, 1 };\r\n}\r\n\r\n/**\r\n * Search for the first slot occupied by an item in the inventory.\r\n */\r\nint FindFirstSlotOnItem(int8_t itemInvId)\r\n{\r\n\tif (itemInvId == 0)\r\n\t\treturn -1;\r\n\tfor (int s = SLOTXY_INV_FIRST; s <= SLOTXY_INV_LAST; s++) {\r\n\t\tif (GetItemIdOnSlot(s) == itemInvId)\r\n\t\t\treturn s;\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\nPoint FindFirstStashSlotOnItem(StashStruct::StashCell itemInvId)\r\n{\r\n\tif (itemInvId == StashStruct::EmptyCell)\r\n\t\treturn InvalidStashPoint;\r\n\r\n\tfor (WorldTilePosition point : PointsInRectangle(WorldTileRectangle { { 0, 0 }, { 10, 10 } })) {\r\n\t\tif (Stash.GetItemIdAtPosition(point) == itemInvId)\r\n\t\t\treturn point;\r\n\t}\r\n\r\n\treturn InvalidStashPoint;\r\n}\r\n\r\n/**\r\n * Reset cursor position based on the current slot.\r\n */\r\nvoid ResetInvCursorPosition()\r\n{\r\n\tPoint mousePos {};\r\n\tif (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) {\r\n\t\tauto slot = Slot;\r\n\t\tSize itemSize = { 1, 1 };\r\n\r\n\t\tif (MyPlayer->HoldItem.isEmpty()) {\r\n\t\t\tconst int8_t itemInvId = GetItemIdOnSlot(Slot);\r\n\t\t\tif (itemInvId != 0) {\r\n\t\t\t\tslot = FindFirstSlotOnItem(itemInvId);\r\n\t\t\t\titemSize = GetItemSizeOnSlot(Slot);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\titemSize = GetInventorySize(MyPlayer->HoldItem);\r\n\t\t}\r\n\r\n\t\tmousePos = GetSlotCoord(slot);\r\n\t\tmousePos.x += ((itemSize.width - 1) * InventorySlotSizeInPixels.width) / 2;\r\n\t\tmousePos.y += ((itemSize.height - 1) * InventorySlotSizeInPixels.height) / 2;\r\n\t} else if (Slot >= SLOTXY_BELT_FIRST && Slot <= SLOTXY_BELT_LAST) {\r\n\t\tmousePos = GetSlotCoord(Slot);\r\n\t} else {\r\n\t\tmousePos = InvGetEquipSlotCoordFromInvSlot((inv_xy_slot)Slot);\r\n\t}\r\n\r\n\tSetCursorPos(mousePos);\r\n}\r\n\r\nint FindClosestInventorySlot(\r\n    Point mousePos, const Item &heldItem,\r\n    tl::function_ref<int(Point, int)> distanceFunction = [](Point mousePos, int slot) { return mousePos.ManhattanDistance(GetSlotCoord(slot)); })\r\n{\r\n\tint shortestDistance = std::numeric_limits<int>::max();\r\n\tint bestSlot = 0;\r\n\r\n\tauto checkCandidateSlot = [&](int slot) {\r\n\t\tconst int distance = distanceFunction(mousePos, slot);\r\n\t\tif (distance < shortestDistance) {\r\n\t\t\tshortestDistance = distance;\r\n\t\t\tbestSlot = slot;\r\n\t\t}\r\n\t};\r\n\r\n\tif (heldItem.isEmpty()) {\r\n\t\tfor (int i = SLOTXY_HEAD; i <= SLOTXY_CHEST; i++) {\r\n\t\t\tcheckCandidateSlot(i);\r\n\t\t}\r\n\t} else {\r\n\t\tif (heldItem._itype == ItemType::Ring) {\r\n\t\t\tfor (const int i : { SLOTXY_RING_LEFT, SLOTXY_RING_RIGHT }) {\r\n\t\t\t\tcheckCandidateSlot(i);\r\n\t\t\t}\r\n\t\t} else if (heldItem.isWeapon()) {\r\n\t\t\tcheckCandidateSlot(SLOTXY_HAND_LEFT);\r\n\t\t} else if (heldItem.isShield()) {\r\n\t\t\tcheckCandidateSlot(SLOTXY_HAND_RIGHT);\r\n\t\t} else if (heldItem.isHelm()) {\r\n\t\t\tcheckCandidateSlot(SLOTXY_HEAD);\r\n\t\t} else if (heldItem.isArmor()) {\r\n\t\t\tcheckCandidateSlot(SLOTXY_CHEST);\r\n\t\t} else if (heldItem._itype == ItemType::Amulet) {\r\n\t\t\tcheckCandidateSlot(SLOTXY_AMULET);\r\n\t\t}\r\n\t}\r\n\tfor (int i = SLOTXY_INV_FIRST; i <= SLOTXY_INV_LAST; i++) {\r\n\t\tcheckCandidateSlot(i);\r\n\t}\r\n\r\n\treturn bestSlot;\r\n}\r\n\r\nPoint FindClosestStashSlot(Point mousePos)\r\n{\r\n\tint shortestDistance = std::numeric_limits<int>::max();\r\n\tPoint bestSlot = {};\r\n\r\n\tfor (const Point point : PointsInRectangle(Rectangle { { 0, 0 }, Size { 10, 10 } })) {\r\n\t\tconst int distance = mousePos.ManhattanDistance(GetStashSlotCoord(point));\r\n\t\tif (distance < shortestDistance) {\r\n\t\t\tshortestDistance = distance;\r\n\t\t\tbestSlot = point;\r\n\t\t}\r\n\t}\r\n\r\n\treturn bestSlot;\r\n}\r\n\r\nvoid LiftInventoryItem()\r\n{\r\n\tconst int inventorySlot = (Slot >= 0) ? Slot : FindClosestInventorySlot(MousePosition, MyPlayer->HoldItem);\r\n\r\n\tint jumpSlot = inventorySlot; // If the cursor is over an inventory slot we may need to adjust it due to pasting items of different sizes over each other\r\n\tif (inventorySlot >= SLOTXY_INV_FIRST && inventorySlot <= SLOTXY_INV_LAST) {\r\n\t\tconst Size cursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(MyPlayer->HoldItem);\r\n\r\n\t\t// Find any item occupying a slot that is currently under the cursor\r\n\t\tconst int8_t itemUnderCursor = [](int inventorySlot, Size cursorSizeInCells) {\r\n\t\t\tif (inventorySlot < SLOTXY_INV_FIRST || inventorySlot > SLOTXY_INV_LAST)\r\n\t\t\t\treturn 0;\r\n\t\t\tfor (int x = 0; x < cursorSizeInCells.width; x++) {\r\n\t\t\t\tfor (int y = 0; y < cursorSizeInCells.height; y++) {\r\n\t\t\t\t\tconst int slotUnderCursor = inventorySlot + x + y * INV_ROW_SLOT_SIZE;\r\n\t\t\t\t\tif (slotUnderCursor > SLOTXY_INV_LAST)\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\tconst int itemId = GetItemIdOnSlot(slotUnderCursor);\r\n\t\t\t\t\tif (itemId != 0)\r\n\t\t\t\t\t\treturn itemId;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn 0;\r\n\t\t}(inventorySlot, cursorSizeInCells);\r\n\r\n\t\t// Capture the first slot of the first item (if any) under the cursor\r\n\t\tif (itemUnderCursor > 0)\r\n\t\t\tjumpSlot = FindFirstSlotOnItem(itemUnderCursor);\r\n\t}\r\n\tCheckInvItem();\r\n\r\n\tif (inventorySlot >= SLOTXY_INV_FIRST && inventorySlot <= SLOTXY_INV_LAST) {\r\n\t\tPoint mousePos = GetSlotCoord(jumpSlot);\r\n\t\tSlot = jumpSlot;\r\n\t\tconst Size newCursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? GetItemSizeOnSlot(jumpSlot) : GetInventorySize(MyPlayer->HoldItem);\r\n\t\tmousePos.x += ((newCursorSizeInCells.width - 1) * InventorySlotSizeInPixels.width) / 2;\r\n\t\tmousePos.y += ((newCursorSizeInCells.height - 1) * InventorySlotSizeInPixels.height) / 2;\r\n\t\tSetCursorPos(mousePos);\r\n\t}\r\n}\r\n\r\nvoid LiftStashItem()\r\n{\r\n\tconst Point stashSlot = (ActiveStashSlot != InvalidStashPoint) ? ActiveStashSlot : FindClosestStashSlot(MousePosition);\r\n\r\n\tSize cursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(MyPlayer->HoldItem);\r\n\r\n\t// Find any item occupying a slot that is currently under the cursor\r\n\tconst StashStruct::StashCell itemUnderCursor = [](Point stashSlot, Size cursorSizeInCells) -> StashStruct::StashCell {\r\n\t\tif (stashSlot == InvalidStashPoint)\r\n\t\t\treturn StashStruct::EmptyCell;\r\n\t\tfor (const Point slotUnderCursor : PointsInRectangle(Rectangle { stashSlot, cursorSizeInCells })) {\r\n\t\t\tif (slotUnderCursor.x >= 10 || slotUnderCursor.y >= 10)\r\n\t\t\t\tcontinue;\r\n\t\t\tconst StashStruct::StashCell itemId = Stash.GetItemIdAtPosition(slotUnderCursor);\r\n\t\t\tif (itemId != StashStruct::EmptyCell)\r\n\t\t\t\treturn itemId;\r\n\t\t}\r\n\t\treturn StashStruct::EmptyCell;\r\n\t}(stashSlot, cursorSizeInCells);\r\n\r\n\tconst Point jumpSlot = itemUnderCursor == StashStruct::EmptyCell ? stashSlot : FindFirstStashSlotOnItem(itemUnderCursor);\r\n\tCheckStashItem(MousePosition);\r\n\r\n\tPoint mousePos = GetStashSlotCoord(jumpSlot);\r\n\tActiveStashSlot = jumpSlot;\r\n\t// Center the Cursor based on the item we just put down or we're holding.\r\n\tcursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? GetItemSizeOnSlot(jumpSlot) : GetInventorySize(MyPlayer->HoldItem);\r\n\tmousePos.x += ((cursorSizeInCells.width) * InventorySlotSizeInPixels.width) / 2;\r\n\tmousePos.y += ((cursorSizeInCells.height) * InventorySlotSizeInPixels.height) / 2;\r\n\r\n\tSetCursorPos(mousePos);\r\n}\r\n\r\n/**\r\n * @brief Figures out where on the body to move when on the first row\r\n */\r\ninv_xy_slot InventoryMoveToBody(int slot)\r\n{\r\n\tPreviousInventoryColumn = slot - SLOTXY_INV_ROW1_FIRST;\r\n\tif (slot <= SLOTXY_INV_ROW1_FIRST + 2) { // first 3 general slots\r\n\t\treturn SLOTXY_RING_LEFT;\r\n\t}\r\n\tif (slot <= SLOTXY_INV_ROW1_FIRST + 6) { // middle 4 general slots\r\n\t\treturn SLOTXY_CHEST;\r\n\t}\r\n\t// last 3 general slots\r\n\treturn SLOTXY_RING_RIGHT;\r\n}\r\n\r\nvoid InventoryMove(AxisDirection dir)\r\n{\r\n\tPoint mousePos = MousePosition;\r\n\r\n\tconst Item &heldItem = MyPlayer->HoldItem;\r\n\t// normalize slots\r\n\tif (Slot < 0)\r\n\t\tSlot = FindClosestInventorySlot(mousePos, heldItem);\r\n\telse if (Slot > SLOTXY_BELT_LAST)\r\n\t\tSlot = SLOTXY_BELT_LAST;\r\n\r\n\tconst int initialSlot = Slot;\r\n\r\n\tconst bool isHoldingItem = !heldItem.isEmpty();\r\n\tSize itemSize = isHoldingItem ? GetInventorySize(heldItem) : Size { 1 };\r\n\r\n\t// when item is on cursor (pcurs > 1), this is the real cursor XY\r\n\tif (dir.x == AxisDirectionX_LEFT) {\r\n\t\tif (isHoldingItem) {\r\n\t\t\tif (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_BELT_LAST) {\r\n\t\t\t\tif (IsNoneOf(Slot, SLOTXY_INV_ROW1_FIRST, SLOTXY_INV_ROW2_FIRST, SLOTXY_INV_ROW3_FIRST, SLOTXY_INV_ROW4_FIRST, SLOTXY_BELT_FIRST)) {\r\n\t\t\t\t\tSlot -= 1;\r\n\t\t\t\t}\r\n\t\t\t} else if (heldItem._itype == ItemType::Ring) {\r\n\t\t\t\tSlot = SLOTXY_RING_LEFT;\r\n\t\t\t} else if (heldItem.isWeapon() || heldItem.isShield()) {\r\n\t\t\t\tSlot = SLOTXY_HAND_LEFT;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (Slot == SLOTXY_HAND_RIGHT) {\r\n\t\t\t\tSlot = SLOTXY_CHEST;\r\n\t\t\t} else if (Slot == SLOTXY_CHEST) {\r\n\t\t\t\tSlot = SLOTXY_HAND_LEFT;\r\n\t\t\t} else if (Slot == SLOTXY_AMULET) {\r\n\t\t\t\tSlot = SLOTXY_HEAD;\r\n\t\t\t} else if (Slot == SLOTXY_RING_RIGHT) {\r\n\t\t\t\tSlot = SLOTXY_RING_LEFT;\r\n\t\t\t} else if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_BELT_LAST) {\r\n\t\t\t\tconst int8_t itemId = GetItemIdOnSlot(Slot);\r\n\t\t\t\tif (itemId != 0) {\r\n\t\t\t\t\tfor (int i = 1; i < INV_ROW_SLOT_SIZE && !IsAnyOf(Slot - i + 1, SLOTXY_INV_ROW1_FIRST, SLOTXY_INV_ROW2_FIRST, SLOTXY_INV_ROW3_FIRST, SLOTXY_INV_ROW4_FIRST, SLOTXY_BELT_FIRST); i++) {\r\n\t\t\t\t\t\tif (itemId != GetItemIdOnSlot(Slot - i)) {\r\n\t\t\t\t\t\t\tSlot -= i;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (IsNoneOf(Slot, SLOTXY_INV_ROW1_FIRST, SLOTXY_INV_ROW2_FIRST, SLOTXY_INV_ROW3_FIRST, SLOTXY_INV_ROW4_FIRST, SLOTXY_BELT_FIRST)) {\r\n\t\t\t\t\tSlot -= 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (dir.x == AxisDirectionX_RIGHT) {\r\n\t\tif (isHoldingItem) {\r\n\t\t\tif (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_BELT_LAST) {\r\n\t\t\t\tif (IsNoneOf(Slot + itemSize.width - 1, SLOTXY_INV_ROW1_LAST, SLOTXY_INV_ROW2_LAST, SLOTXY_INV_ROW3_LAST, SLOTXY_INV_ROW4_LAST, SLOTXY_BELT_LAST)) {\r\n\t\t\t\t\tSlot += 1;\r\n\t\t\t\t}\r\n\t\t\t} else if (heldItem._itype == ItemType::Ring) {\r\n\t\t\t\tSlot = SLOTXY_RING_RIGHT;\r\n\t\t\t} else if (heldItem.isWeapon() || heldItem.isShield()) {\r\n\t\t\t\tSlot = SLOTXY_HAND_RIGHT;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (Slot == SLOTXY_RING_LEFT) {\r\n\t\t\t\tSlot = SLOTXY_RING_RIGHT;\r\n\t\t\t} else if (Slot == SLOTXY_HAND_LEFT) {\r\n\t\t\t\tSlot = SLOTXY_CHEST;\r\n\t\t\t} else if (Slot == SLOTXY_CHEST) {\r\n\t\t\t\tSlot = SLOTXY_HAND_RIGHT;\r\n\t\t\t} else if (Slot == SLOTXY_HEAD) {\r\n\t\t\t\tSlot = SLOTXY_AMULET;\r\n\t\t\t} else if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_BELT_LAST) {\r\n\t\t\t\tconst int8_t itemId = GetItemIdOnSlot(Slot);\r\n\t\t\t\tif (itemId != 0) {\r\n\t\t\t\t\tfor (int i = 1; i < INV_ROW_SLOT_SIZE && !IsAnyOf(Slot + i - 1, SLOTXY_INV_ROW1_LAST, SLOTXY_INV_ROW2_LAST, SLOTXY_INV_ROW3_LAST, SLOTXY_INV_ROW4_LAST, SLOTXY_BELT_LAST); i++) {\r\n\t\t\t\t\t\tif (itemId != GetItemIdOnSlot(Slot + i)) {\r\n\t\t\t\t\t\t\tSlot += i;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (IsNoneOf(Slot, SLOTXY_INV_ROW1_LAST, SLOTXY_INV_ROW2_LAST, SLOTXY_INV_ROW3_LAST, SLOTXY_INV_ROW4_LAST, SLOTXY_BELT_LAST)) {\r\n\t\t\t\t\tSlot += 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (dir.y == AxisDirectionY_UP) {\r\n\t\tif (isHoldingItem) {\r\n\t\t\tif (Slot >= SLOTXY_INV_ROW2_FIRST) { // general inventory\r\n\t\t\t\tSlot -= INV_ROW_SLOT_SIZE;\r\n\t\t\t} else if (Slot >= SLOTXY_INV_FIRST) {\r\n\t\t\t\tif (heldItem._itype == ItemType::Ring) {\r\n\t\t\t\t\tif (Slot >= SLOTXY_INV_ROW1_FIRST && Slot <= SLOTXY_INV_ROW1_FIRST + (INV_ROW_SLOT_SIZE / 2) - 1) {\r\n\t\t\t\t\t\tSlot = SLOTXY_RING_LEFT;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tSlot = SLOTXY_RING_RIGHT;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (heldItem.isWeapon()) {\r\n\t\t\t\t\tSlot = SLOTXY_HAND_LEFT;\r\n\t\t\t\t} else if (heldItem.isShield()) {\r\n\t\t\t\t\tSlot = SLOTXY_HAND_RIGHT;\r\n\t\t\t\t} else if (heldItem.isHelm()) {\r\n\t\t\t\t\tSlot = SLOTXY_HEAD;\r\n\t\t\t\t} else if (heldItem.isArmor()) {\r\n\t\t\t\t\tSlot = SLOTXY_CHEST;\r\n\t\t\t\t} else if (heldItem._itype == ItemType::Amulet) {\r\n\t\t\t\t\tSlot = SLOTXY_AMULET;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (Slot >= SLOTXY_INV_ROW1_FIRST && Slot <= SLOTXY_INV_ROW1_LAST) {\r\n\t\t\t\tSlot = InventoryMoveToBody(Slot);\r\n\t\t\t} else if (Slot == SLOTXY_CHEST || Slot == SLOTXY_HAND_LEFT) {\r\n\t\t\t\tSlot = SLOTXY_HEAD;\r\n\t\t\t} else if (Slot == SLOTXY_RING_LEFT) {\r\n\t\t\t\tSlot = SLOTXY_HAND_LEFT;\r\n\t\t\t} else if (Slot == SLOTXY_RING_RIGHT) {\r\n\t\t\t\tSlot = SLOTXY_HAND_RIGHT;\r\n\t\t\t} else if (Slot == SLOTXY_HAND_RIGHT) {\r\n\t\t\t\tSlot = SLOTXY_AMULET;\r\n\t\t\t} else if (Slot >= SLOTXY_INV_ROW2_FIRST) {\r\n\t\t\t\tconst int8_t itemId = GetItemIdOnSlot(Slot);\r\n\t\t\t\tif (itemId != 0) {\r\n\t\t\t\t\tfor (int i = 1; i < 5; i++) {\r\n\t\t\t\t\t\tif (Slot - i * INV_ROW_SLOT_SIZE < SLOTXY_INV_ROW1_FIRST) {\r\n\t\t\t\t\t\t\tSlot = InventoryMoveToBody(Slot - (i - 1) * INV_ROW_SLOT_SIZE);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (itemId != GetItemIdOnSlot(Slot - i * INV_ROW_SLOT_SIZE)) {\r\n\t\t\t\t\t\t\tSlot -= i * INV_ROW_SLOT_SIZE;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tSlot -= INV_ROW_SLOT_SIZE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (dir.y == AxisDirectionY_DOWN) {\r\n\t\tif (isHoldingItem) {\r\n\t\t\tif (Slot == SLOTXY_HEAD || Slot == SLOTXY_CHEST) {\r\n\t\t\t\tSlot = SLOTXY_INV_ROW1_FIRST + 4;\r\n\t\t\t} else if (Slot == SLOTXY_RING_LEFT || Slot == SLOTXY_HAND_LEFT) {\r\n\t\t\t\tSlot = SLOTXY_INV_ROW1_FIRST + (itemSize.width > 1 ? 0 : 1);\r\n\t\t\t} else if (Slot == SLOTXY_RING_RIGHT || Slot == SLOTXY_HAND_RIGHT || Slot == SLOTXY_AMULET) {\r\n\t\t\t\tSlot = SLOTXY_INV_ROW1_LAST - 1;\r\n\t\t\t} else if (Slot <= (SLOTXY_INV_ROW4_LAST - (itemSize.height * INV_ROW_SLOT_SIZE))) {\r\n\t\t\t\tSlot += INV_ROW_SLOT_SIZE;\r\n\t\t\t} else if (Slot <= SLOTXY_INV_LAST && heldItem._itype == ItemType::Misc && itemSize == Size { 1, 1 }) { // forcing only 1x1 misc items\r\n\t\t\t\tif (Slot + INV_ROW_SLOT_SIZE <= SLOTXY_BELT_LAST)\r\n\t\t\t\t\tSlot += INV_ROW_SLOT_SIZE;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (Slot == SLOTXY_HEAD) {\r\n\t\t\t\tSlot = SLOTXY_CHEST;\r\n\t\t\t} else if (Slot == SLOTXY_CHEST) {\r\n\t\t\t\tif (PreviousInventoryColumn >= 3 && PreviousInventoryColumn <= 6)\r\n\t\t\t\t\tSlot = SLOTXY_INV_ROW1_FIRST + PreviousInventoryColumn;\r\n\t\t\t\telse\r\n\t\t\t\t\tSlot = SLOTXY_INV_ROW1_FIRST + (INV_ROW_SLOT_SIZE / 2);\r\n\t\t\t} else if (Slot == SLOTXY_HAND_LEFT) {\r\n\t\t\t\tSlot = SLOTXY_RING_LEFT;\r\n\t\t\t} else if (Slot == SLOTXY_RING_LEFT) {\r\n\t\t\t\tif (PreviousInventoryColumn >= 0 && PreviousInventoryColumn <= 2)\r\n\t\t\t\t\tSlot = SLOTXY_INV_ROW1_FIRST + PreviousInventoryColumn;\r\n\t\t\t\telse\r\n\t\t\t\t\tSlot = SLOTXY_INV_ROW1_FIRST + 1;\r\n\t\t\t} else if (Slot == SLOTXY_RING_RIGHT) {\r\n\t\t\t\tif (PreviousInventoryColumn >= 7 && PreviousInventoryColumn <= 9)\r\n\t\t\t\t\tSlot = SLOTXY_INV_ROW1_FIRST + PreviousInventoryColumn;\r\n\t\t\t\telse\r\n\t\t\t\t\tSlot = SLOTXY_INV_ROW1_LAST - 1;\r\n\t\t\t} else if (Slot == SLOTXY_AMULET) {\r\n\t\t\t\tSlot = SLOTXY_HAND_RIGHT;\r\n\t\t\t} else if (Slot == SLOTXY_HAND_RIGHT) {\r\n\t\t\t\tSlot = SLOTXY_RING_RIGHT;\r\n\t\t\t} else if (Slot <= SLOTXY_INV_LAST) {\r\n\t\t\t\tconst int8_t itemId = GetItemIdOnSlot(Slot);\r\n\t\t\t\tif (itemId != 0) {\r\n\t\t\t\t\tfor (int i = 1; i < 5 && Slot + i * INV_ROW_SLOT_SIZE <= SLOTXY_BELT_LAST; i++) {\r\n\t\t\t\t\t\tif (itemId != GetItemIdOnSlot(Slot + i * INV_ROW_SLOT_SIZE)) {\r\n\t\t\t\t\t\t\tSlot += i * INV_ROW_SLOT_SIZE;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (Slot + INV_ROW_SLOT_SIZE <= SLOTXY_BELT_LAST) {\r\n\t\t\t\t\tSlot += INV_ROW_SLOT_SIZE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// no movement was made\r\n\tif (Slot == initialSlot)\r\n\t\treturn;\r\n\r\n\tif (Slot < SLOTXY_INV_FIRST) {\r\n\t\tmousePos = InvGetEquipSlotCoordFromInvSlot(static_cast<inv_xy_slot>(Slot));\r\n\t} else {\r\n\t\tmousePos = GetSlotCoord(Slot);\r\n\t}\r\n\t// If we're in the inventory we may need to move the cursor to an area that doesn't line up with the center of a cell\r\n\tif (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) {\r\n\t\tif (!isHoldingItem) {\r\n\t\t\t// If we're not holding an item\r\n\t\t\tconst int8_t itemInvId = GetItemIdOnSlot(Slot);\r\n\t\t\tif (itemInvId != 0) {\r\n\t\t\t\t// but the cursor moved over an item\r\n\t\t\t\tint itemSlot = FindFirstSlotOnItem(itemInvId);\r\n\t\t\t\tif (itemSlot < 0)\r\n\t\t\t\t\titemSlot = Slot;\r\n\r\n\t\t\t\t// then we need to offset the cursor so it shows over the center of the item\r\n\t\t\t\tmousePos = GetSlotCoord(itemSlot);\r\n\t\t\t\titemSize = GetItemSizeOnSlot(itemSlot);\r\n\t\t\t}\r\n\t\t}\r\n\t\t// At this point itemSize is either the size of the cell/item the hand cursor is over, or the size of the item we're currently holding.\r\n\t\t// mousePos is the center of the top left cell of the item under the hand cursor, or the top left cell of the region that could fit the item we're holding.\r\n\t\t// either way we need to offset the mouse position to account for items (we're holding or hovering over) with a dimension larger than a single cell.\r\n\t\tmousePos.x += ((itemSize.width - 1) * InventorySlotSizeInPixels.width) / 2;\r\n\t\tmousePos.y += ((itemSize.height - 1) * InventorySlotSizeInPixels.height) / 2;\r\n\t}\r\n\r\n\tif (mousePos == MousePosition) {\r\n\t\treturn; // Avoid wobbling when scaled\r\n\t}\r\n\r\n\tSetCursorPos(mousePos);\r\n}\r\n\r\n/**\r\n * Move the cursor around in the inventory\r\n * If mouse coords are at SLOTXY_CHEST_LAST, consider this center of equipment\r\n * small inventory squares are 29x29 (roughly)\r\n */\r\nvoid CheckInventoryMove(AxisDirection dir)\r\n{\r\n\tstatic AxisDirectionRepeater repeater(/*min_interval_ms=*/150);\r\n\tdir = repeater.Get(dir);\r\n\tif (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE)\r\n\t\treturn;\r\n\r\n\tInventoryMove(dir);\r\n}\r\n\r\n/**\r\n * @brief Try to clean the inventory related cursor states.\r\n * @return True if it is safe to close the inventory\r\n */\r\nbool BlurInventory()\r\n{\r\n\tif (!MyPlayer->HoldItem.isEmpty()) {\r\n\t\tif (!TryDropItem()) {\r\n\t\t\tMyPlayer->Say(HeroSpeech::WhereWouldIPutThis);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tCloseInventory();\r\n\tif (pcurs > CURSOR_HAND)\r\n\t\tNewCursor(CURSOR_HAND);\r\n\tif (CharFlag)\r\n\t\tFocusOnCharInfo();\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid StashMove(AxisDirection dir)\r\n{\r\n\tstatic AxisDirectionRepeater repeater(/*min_interval_ms=*/150);\r\n\tdir = repeater.Get(dir);\r\n\tif (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE)\r\n\t\treturn;\r\n\r\n\tconst Item &holdItem = MyPlayer->HoldItem;\r\n\tif (Slot < 0 && ActiveStashSlot == InvalidStashPoint) {\r\n\t\tconst int invSlot = FindClosestInventorySlot(MousePosition, holdItem);\r\n\t\tconst Point invSlotCoord = GetSlotCoord(invSlot);\r\n\t\tconst int invDistance = MousePosition.ManhattanDistance(invSlotCoord);\r\n\r\n\t\tconst Point stashSlot = FindClosestStashSlot(MousePosition);\r\n\t\tconst Point stashSlotCoord = GetStashSlotCoord(stashSlot);\r\n\t\tconst int stashDistance = MousePosition.ManhattanDistance(stashSlotCoord);\r\n\r\n\t\tif (invDistance < stashDistance) {\r\n\t\t\tBeltReturnsToStash = false;\r\n\t\t\tInventoryMove(dir);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tActiveStashSlot = stashSlot;\r\n\t}\r\n\r\n\tSize itemSize = holdItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(holdItem);\r\n\r\n\tif (dir.y == AxisDirectionY_UP) {\r\n\t\t// Check if we need to jump from belt to stash\r\n\t\tif (BeltReturnsToStash && Slot >= SLOTXY_BELT_FIRST && Slot <= SLOTXY_BELT_LAST) {\r\n\t\t\tconst int beltSlot = Slot - SLOTXY_BELT_FIRST;\r\n\t\t\tInvalidateInventorySlot();\r\n\t\t\tActiveStashSlot = { 2 + beltSlot, 10 - itemSize.height };\r\n\t\t\tdir.y = AxisDirectionY_NONE;\r\n\t\t}\r\n\t}\r\n\r\n\tif (dir.x == AxisDirectionX_LEFT) {\r\n\t\t// Check if we need to jump from general inventory to stash\r\n\t\tint firstSlot = Slot;\r\n\t\tif (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) {\r\n\t\t\tif (MyPlayer->HoldItem.isEmpty()) {\r\n\t\t\t\tconst int8_t itemId = GetItemIdOnSlot(Slot);\r\n\t\t\t\tif (itemId != 0) {\r\n\t\t\t\t\tfirstSlot = FindFirstSlotOnItem(itemId);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If we're in the leftmost column (or hovering over an item on the left side of the inventory) or\r\n\t\t//  left side of the body and we're moving left we need to move into the closest stash column\r\n\t\tif (IsAnyOf(firstSlot, SLOTXY_HEAD, SLOTXY_HAND_LEFT, SLOTXY_RING_LEFT, SLOTXY_AMULET, SLOTXY_CHEST, SLOTXY_INV_ROW1_FIRST, SLOTXY_INV_ROW2_FIRST, SLOTXY_INV_ROW3_FIRST, SLOTXY_INV_ROW4_FIRST)) {\r\n\t\t\tconst Point slotCoord = GetSlotCoord(Slot);\r\n\t\t\tInvalidateInventorySlot();\r\n\t\t\tActiveStashSlot = FindClosestStashSlot(slotCoord) - Displacement { itemSize.width - 1, 0 };\r\n\t\t\tdir.x = AxisDirectionX_NONE;\r\n\t\t}\r\n\t}\r\n\r\n\tif (Slot >= 0) {\r\n\t\tInventoryMove(dir);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (dir.x == AxisDirectionX_LEFT) {\r\n\t\tif (ActiveStashSlot.x > 0) {\r\n\t\t\tconst StashStruct::StashCell itemIdAtActiveStashSlot = Stash.GetItemIdAtPosition(ActiveStashSlot);\r\n\t\t\tActiveStashSlot.x--;\r\n\t\t\tif (holdItem.isEmpty() && itemIdAtActiveStashSlot != StashStruct::EmptyCell) {\r\n\t\t\t\twhile (ActiveStashSlot.x > 0 && itemIdAtActiveStashSlot == Stash.GetItemIdAtPosition(ActiveStashSlot)) {\r\n\t\t\t\t\tActiveStashSlot.x--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (dir.x == AxisDirectionX_RIGHT) {\r\n\t\t// If we're empty-handed and trying to move right while hovering over an item we may not\r\n\t\t//  have a free stash column to move to. If the item we're hovering over occupies the last\r\n\t\t//  column then we want to jump to the inventory instead of just moving one column over.\r\n\t\tconst Size itemUnderCursorSize = holdItem.isEmpty() ? GetItemSizeOnSlot(ActiveStashSlot) : itemSize;\r\n\t\tif (ActiveStashSlot.x < 10 - itemUnderCursorSize.width) {\r\n\t\t\tconst StashStruct::StashCell itemIdAtActiveStashSlot = Stash.GetItemIdAtPosition(ActiveStashSlot);\r\n\t\t\tActiveStashSlot.x++;\r\n\t\t\tif (holdItem.isEmpty() && itemIdAtActiveStashSlot != StashStruct::EmptyCell) {\r\n\t\t\t\twhile (ActiveStashSlot.x < 10 - itemSize.width && itemIdAtActiveStashSlot == Stash.GetItemIdAtPosition(ActiveStashSlot)) {\r\n\t\t\t\t\tActiveStashSlot.x++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst Point stashSlotCoord = GetStashSlotCoord(ActiveStashSlot);\r\n\t\t\tconst Point rightPanelCoord = { GetRightPanel().position.x, stashSlotCoord.y };\r\n\t\t\tSlot = FindClosestInventorySlot(rightPanelCoord, holdItem, [](Point mousePos, int slot) {\r\n\t\t\t\tconst Point slotPos = GetSlotCoord(slot);\r\n\t\t\t\t// Exaggerate the vertical difference so that moving from the top 6 rows of the\r\n\t\t\t\t//  stash is more likely to land on a body slot. The value 3 was found by trial and\r\n\t\t\t\t//  error, this allows moving from the top row of the stash to the head while\r\n\t\t\t\t//  empty-handed while 4 causes the amulet to be preferenced (due to less vertical\r\n\t\t\t\t//  distance) and 2 causes the left hand to be preferenced (due to less horizontal\r\n\t\t\t\t//  distance).\r\n\t\t\t\treturn std::abs(mousePos.y - slotPos.y) * 3 + std::abs(mousePos.x - slotPos.x);\r\n\t\t\t});\r\n\t\t\tActiveStashSlot = InvalidStashPoint;\r\n\t\t\tBeltReturnsToStash = false;\r\n\t\t}\r\n\t}\r\n\tif (dir.y == AxisDirectionY_UP) {\r\n\t\tif (ActiveStashSlot.y > 0) {\r\n\t\t\tconst StashStruct::StashCell itemIdAtActiveStashSlot = Stash.GetItemIdAtPosition(ActiveStashSlot);\r\n\t\t\tActiveStashSlot.y--;\r\n\t\t\tif (holdItem.isEmpty() && itemIdAtActiveStashSlot != StashStruct::EmptyCell) {\r\n\t\t\t\twhile (ActiveStashSlot.y > 0 && itemIdAtActiveStashSlot == Stash.GetItemIdAtPosition(ActiveStashSlot)) {\r\n\t\t\t\t\tActiveStashSlot.y--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (dir.y == AxisDirectionY_DOWN) {\r\n\t\tif (ActiveStashSlot.y < 10 - itemSize.height) {\r\n\t\t\tconst StashStruct::StashCell itemIdAtActiveStashSlot = Stash.GetItemIdAtPosition(ActiveStashSlot);\r\n\t\t\tActiveStashSlot.y++;\r\n\t\t\tif (holdItem.isEmpty() && itemIdAtActiveStashSlot != StashStruct::EmptyCell) {\r\n\t\t\t\twhile (ActiveStashSlot.y < 10 - itemSize.height && itemIdAtActiveStashSlot == Stash.GetItemIdAtPosition(ActiveStashSlot)) {\r\n\t\t\t\t\tActiveStashSlot.y++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else if ((holdItem.isEmpty() || CanBePlacedOnBelt(*MyPlayer, holdItem)) && ActiveStashSlot.x > 1) {\r\n\t\t\tconst int beltSlot = ActiveStashSlot.x - 2;\r\n\t\t\tSlot = SLOTXY_BELT_FIRST + beltSlot;\r\n\t\t\tActiveStashSlot = InvalidStashPoint;\r\n\t\t\tBeltReturnsToStash = true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (Slot >= 0) {\r\n\t\tResetInvCursorPosition();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (ActiveStashSlot != InvalidStashPoint) {\r\n\t\tPoint mousePos = GetStashSlotCoord(ActiveStashSlot);\r\n\t\t// At this point itemSize is the size of the item we're currently holding.\r\n\t\t// We need to offset the mouse position to account for items (we're holding or hovering over) with a dimension larger than a single cell.\r\n\t\tif (holdItem.isEmpty()) {\r\n\t\t\tconst StashStruct::StashCell itemIdAtActiveStashSlot = Stash.GetItemIdAtPosition(ActiveStashSlot);\r\n\t\t\tif (itemIdAtActiveStashSlot != StashStruct::EmptyCell) {\r\n\t\t\t\tconst Item stashItem = Stash.stashList[itemIdAtActiveStashSlot];\r\n\t\t\t\tconst Point firstSlotOnItem = FindFirstStashSlotOnItem(itemIdAtActiveStashSlot);\r\n\t\t\t\titemSize = GetInventorySize(stashItem);\r\n\t\t\t\tmousePos = GetStashSlotCoord(firstSlotOnItem);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tmousePos += Displacement { itemSize.width * INV_SLOT_HALF_SIZE_PX, itemSize.height * INV_SLOT_HALF_SIZE_PX };\r\n\t\tSetCursorPos(mousePos);\r\n\t\treturn;\r\n\t}\r\n\r\n\tFocusOnInventory();\r\n}\r\n\r\nvoid HotSpellMove(AxisDirection dir)\r\n{\r\n\tstatic AxisDirectionRepeater repeater;\r\n\tdir = repeater.Get(dir);\r\n\tif (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE)\r\n\t\treturn;\r\n\r\n\tauto spellListItems = GetSpellListItems();\r\n\r\n\tPoint position = MousePosition;\r\n\tint shortestDistance = std::numeric_limits<int>::max();\r\n\tfor (auto &spellListItem : spellListItems) {\r\n\t\tconst Point center = spellListItem.location + Displacement { SPLICONLENGTH / 2, -SPLICONLENGTH / 2 };\r\n\t\tconst int distance = MousePosition.ManhattanDistance(center);\r\n\t\tif (distance < shortestDistance) {\r\n\t\t\tposition = center;\r\n\t\t\tshortestDistance = distance;\r\n\t\t}\r\n\t}\r\n\r\n\tconst auto search = [&](AxisDirection dir, bool searchForward) {\r\n\t\tif (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE)\r\n\t\t\treturn;\r\n\r\n\t\tfor (size_t i = 0; i < spellListItems.size(); i++) {\r\n\t\t\tconst size_t index = searchForward ? spellListItems.size() - i - 1 : i;\r\n\r\n\t\t\tauto &spellListItem = spellListItems[index];\r\n\t\t\tif (spellListItem.isSelected)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst Point center = spellListItem.location + Displacement { SPLICONLENGTH / 2, -SPLICONLENGTH / 2 };\r\n\t\t\tif (dir.x == AxisDirectionX_LEFT && center.x >= MousePosition.x)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dir.x == AxisDirectionX_RIGHT && center.x <= MousePosition.x)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dir.x == AxisDirectionX_NONE && center.x != position.x)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dir.y == AxisDirectionY_UP && center.y >= MousePosition.y)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dir.y == AxisDirectionY_DOWN && center.y <= MousePosition.y)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dir.y == AxisDirectionY_NONE && center.y != position.y)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tposition = center;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t};\r\n\tsearch({ AxisDirectionX_NONE, dir.y }, dir.y == AxisDirectionY_DOWN);\r\n\tsearch({ dir.x, AxisDirectionY_NONE }, dir.x == AxisDirectionX_RIGHT);\r\n\r\n\tif (position != MousePosition) {\r\n\t\tSetCursorPos(position);\r\n\t}\r\n}\r\n\r\nvoid SpellBookMove(AxisDirection dir)\r\n{\r\n\tstatic AxisDirectionRepeater repeater;\r\n\tdir = repeater.Get(dir);\r\n\r\n\tif (dir.x == AxisDirectionX_LEFT) {\r\n\t\tif (SpellbookTab > 0)\r\n\t\t\tSpellbookTab--;\r\n\t} else if (dir.x == AxisDirectionX_RIGHT) {\r\n\t\tif ((gbIsHellfire && SpellbookTab < 4) || (!gbIsHellfire && SpellbookTab < 3))\r\n\t\t\tSpellbookTab++;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief check if stepping in direction (dir) from position is blocked.\r\n *\r\n * If you step from A to B, at least one of the Xs need to be clear:\r\n *\r\n *  AX\r\n *  XB\r\n *\r\n *  @return true if step is blocked\r\n */\r\nbool IsPathBlocked(Point position, Direction dir)\r\n{\r\n\tif (IsNoneOf(dir, Direction::North, Direction::East, Direction::South, Direction::West))\r\n\t\treturn false; // Steps along a major axis don't need to check corners\r\n\r\n\tauto leftStep { position + Left(dir) };\r\n\tauto rightStep { position + Right(dir) };\r\n\r\n\tif (IsTileNotSolid(leftStep) && IsTileNotSolid(rightStep))\r\n\t\treturn false;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\treturn !PosOkPlayer(myPlayer, leftStep) && !PosOkPlayer(myPlayer, rightStep);\r\n}\r\n\r\nvoid WalkInDir(Player &player, AxisDirection dir)\r\n{\r\n\tif (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) {\r\n\t\tif (ControlMode != ControlTypes::KeyboardAndMouse && player.walkpath[0] != WALK_NONE && player.destAction == ACTION_NONE)\r\n\t\t\tNetSendCmdLoc(player.getId(), true, CMD_WALKXY, player.position.future); // Stop walking\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction pdir = FaceDir[static_cast<std::size_t>(dir.x)][static_cast<std::size_t>(dir.y)];\r\n\tconst auto delta = player.position.future + pdir;\r\n\r\n\tif (!player.isWalking() && player.CanChangeAction())\r\n\t\tplayer._pdir = pdir;\r\n\r\n\tif (IsStandingGround()) {\r\n\t\tif (player._pmode == PM_STAND)\r\n\t\t\tStartStand(player, pdir);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (PosOkPlayer(player, delta) && IsPathBlocked(player.position.future, pdir)) {\r\n\t\tif (player._pmode == PM_STAND)\r\n\t\t\tStartStand(player, pdir);\r\n\t\treturn; // Don't start backtrack around obstacles\r\n\t}\r\n\r\n\tNetSendCmdLoc(player.getId(), true, CMD_WALKXY, delta);\r\n}\r\n\r\nvoid QuestLogMove(AxisDirection moveDir)\r\n{\r\n\tstatic AxisDirectionRepeater repeater;\r\n\tmoveDir = repeater.Get(moveDir);\r\n\tif (moveDir.y == AxisDirectionY_UP)\r\n\t\tQuestlogUp();\r\n\telse if (moveDir.y == AxisDirectionY_DOWN)\r\n\t\tQuestlogDown();\r\n}\r\n\r\nvoid StoreMove(AxisDirection moveDir)\r\n{\r\n\tstatic AxisDirectionRepeater repeater;\r\n\tmoveDir = repeater.Get(moveDir);\r\n\tif (moveDir.y == AxisDirectionY_UP)\r\n\t\tStoreUp();\r\n\telse if (moveDir.y == AxisDirectionY_DOWN)\r\n\t\tStoreDown();\r\n}\r\n\r\nusing HandleLeftStickOrDPadFn = void (*)(devilution::AxisDirection);\r\n\r\nHandleLeftStickOrDPadFn GetLeftStickOrDPadGameUIHandler()\r\n{\r\n\tif (SpellSelectFlag) {\r\n\t\treturn &HotSpellMove;\r\n\t}\r\n\tif (IsStashOpen) {\r\n\t\treturn &StashMove;\r\n\t}\r\n\tif (invflag) {\r\n\t\treturn &CheckInventoryMove;\r\n\t}\r\n\tif (CharFlag && MyPlayer->_pStatPts > 0) {\r\n\t\treturn &AttrIncBtnSnap;\r\n\t}\r\n\tif (QuestLogIsOpen) {\r\n\t\treturn &QuestLogMove;\r\n\t}\r\n\tif (SpellbookFlag) {\r\n\t\treturn &SpellBookMove;\r\n\t}\r\n\tif (IsPlayerInStore()) {\r\n\t\treturn &StoreMove;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nvoid ProcessLeftStickOrDPadGameUI()\r\n{\r\n\tHandleLeftStickOrDPadFn handler = GetLeftStickOrDPadGameUIHandler();\r\n\tif (handler != nullptr)\r\n\t\thandler(GetLeftStickOrDpadDirection(false));\r\n}\r\n\r\nvoid ProcessAutomapMovementGamepad()\r\n{\r\n\tif (!AutomapActive)\r\n\t\treturn;\r\n\r\n\tconst auto &padmapper = GetOptions().Padmapper;\r\n\r\n\tif (IsControllerButtonComboPressed(padmapper.ButtonComboForAction(\"AutomapMoveUp\")))\r\n\t\tAutomapUp();\r\n\tif (IsControllerButtonComboPressed(padmapper.ButtonComboForAction(\"AutomapMoveDown\")))\r\n\t\tAutomapDown();\r\n\tif (IsControllerButtonComboPressed(padmapper.ButtonComboForAction(\"AutomapMoveLeft\")))\r\n\t\tAutomapLeft();\r\n\tif (IsControllerButtonComboPressed(padmapper.ButtonComboForAction(\"AutomapMoveRight\")))\r\n\t\tAutomapRight();\r\n}\r\n\r\nvoid Movement(Player &player)\r\n{\r\n\tif (PadMenuNavigatorActive || PadHotspellMenuActive || InGameMenu())\r\n\t\treturn;\r\n\r\n\tif (GetLeftStickOrDPadGameUIHandler() == nullptr) {\r\n\t\tWalkInDir(player, GetMoveDirection());\r\n\t}\r\n}\r\n\r\nstruct RightStickAccumulator {\r\n\r\n\tRightStickAccumulator()\r\n\t{\r\n\t\tlastTc = SDL_GetTicks();\r\n\t\thiresDX = 0;\r\n\t\thiresDY = 0;\r\n\t}\r\n\r\n\tvoid Pool(int *x, int *y, int slowdown)\r\n\t{\r\n\t\tconst Uint32 tc = SDL_GetTicks();\r\n\t\tconst int dtc = tc - lastTc;\r\n\t\thiresDX += rightStickX * dtc;\r\n\t\thiresDY += rightStickY * dtc;\r\n\t\tconst int dx = static_cast<int>(hiresDX / slowdown);\r\n\t\tconst int dy = static_cast<int>(hiresDY / slowdown);\r\n\t\t*x += dx;\r\n\t\t*y -= dy;\r\n\t\tlastTc = tc;\r\n\t\t// keep track of remainder for sub-pixel motion\r\n\t\thiresDX -= dx * slowdown;\r\n\t\thiresDY -= dy * slowdown;\r\n\t}\r\n\r\n\tvoid Clear()\r\n\t{\r\n\t\tlastTc = SDL_GetTicks();\r\n\t}\r\n\r\n\tuint32_t lastTc;\r\n\tfloat hiresDX;\r\n\tfloat hiresDY;\r\n};\r\n\r\nbool IsStickMovementSignificant()\r\n{\r\n\t// avoid sqrt() by comparing squared magnitudes\r\n\tconst float leftStickMagnitudeSquared = leftStickX * leftStickX + leftStickY * leftStickY;\r\n\tconst float thresholdSquared = StickDirectionThreshold * StickDirectionThreshold;\r\n\r\n\treturn leftStickMagnitudeSquared >= thresholdSquared\r\n\t    || rightStickX != 0 || rightStickY != 0;\r\n}\r\n\r\nControlTypes GetInputTypeFromEvent(const SDL_Event &event)\r\n{\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_KEY_DOWN:\r\n\tcase SDL_EVENT_KEY_UP:\r\n\t\treturn ControlTypes::KeyboardAndMouse;\r\n#ifdef USE_SDL1\r\n\tcase SDL_MOUSEBUTTONDOWN:\r\n\tcase SDL_MOUSEBUTTONUP:\r\n\tcase SDL_MOUSEMOTION:\r\n\t\treturn ControlTypes::KeyboardAndMouse;\r\n#else\r\n\t\t// SDL 2/3-only events (touch / gamepad):\r\n\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\treturn event.button.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse;\r\n\tcase SDL_EVENT_MOUSE_MOTION:\r\n\t\treturn event.motion.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse;\r\n\tcase SDL_EVENT_MOUSE_WHEEL:\r\n\t\treturn event.wheel.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse;\r\n\tcase SDL_EVENT_FINGER_DOWN:\r\n\tcase SDL_EVENT_FINGER_UP:\r\n\tcase SDL_EVENT_FINGER_MOTION:\r\n\t\treturn ControlTypes::VirtualGamepad;\r\n\tcase SDL_EVENT_GAMEPAD_AXIS_MOTION:\r\n\t\tif (IsAnyOf(SDLC_EventGamepadAxis(event).axis, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)\r\n\t\t    || IsStickMovementSignificant()) {\r\n\t\t\treturn ControlTypes::Gamepad;\r\n\t\t}\r\n\t\tbreak;\r\n#endif // !USE_SDL1\r\n#ifndef USE_SDL1\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_DOWN:\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_UP:\r\n\tcase SDL_EVENT_GAMEPAD_ADDED:\r\n#endif\r\n\tcase SDL_EVENT_JOYSTICK_BALL_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_HAT_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_DOWN:\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_UP:\r\n\t\treturn ControlTypes::Gamepad;\r\n\tcase SDL_EVENT_JOYSTICK_AXIS_MOTION:\r\n#ifndef USE_SDL1\r\n\tcase SDL_EVENT_JOYSTICK_ADDED:\r\n#endif\r\n\t\tif (IsStickMovementSignificant()) return ControlTypes::Gamepad;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\treturn ControlTypes::None;\r\n}\r\n\r\nfloat rightStickLastMove = 0;\r\n\r\nbool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent)\r\n{\r\n\tif (!gbRunGame || AutomapActive)\r\n\t\treturn false;\r\n\r\n#if !defined(USE_SDL1) && !defined(JOY_AXIS_RIGHTX) && !defined(JOY_AXIS_RIGHTY)\r\n\tif (IsAnyOf(event.type,\r\n\t        SDL_EVENT_JOYSTICK_AXIS_MOTION, SDL_EVENT_JOYSTICK_HAT_MOTION,\r\n\t        SDL_EVENT_JOYSTICK_BUTTON_DOWN, SDL_EVENT_JOYSTICK_BUTTON_UP)\r\n\t    && !GameController::All().empty()) {\r\n\t\treturn true;\r\n\t}\r\n#endif\r\n\r\n\tif (rightStickX != 0 || rightStickY != 0 || rightStickLastMove != 0) {\r\n\t\trightStickLastMove = rightStickX + rightStickY; // Allow stick to come to a rest with out breaking simulation\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn SimulatingMouseWithPadmapper || IsSimulatedMouseClickBinding(gamepadEvent);\r\n}\r\n\r\nstd::string_view ControlTypeToString(ControlTypes controlType)\r\n{\r\n\tswitch (controlType) {\r\n\tcase ControlTypes::None:\r\n\t\treturn \"None\";\r\n\tcase ControlTypes::KeyboardAndMouse:\r\n\t\treturn \"KeyboardAndMouse\";\r\n\tcase ControlTypes::Gamepad:\r\n\t\treturn \"Gamepad\";\r\n\tcase ControlTypes::VirtualGamepad:\r\n\t\treturn \"VirtualGamepad\";\r\n\t}\r\n\treturn \"Invalid\";\r\n}\r\n\r\nvoid LogControlDeviceAndModeChange(ControlTypes newControlDevice, ControlTypes newControlMode)\r\n{\r\n\tif (!IsLogLevel(LogCategory::Application, SDL_LOG_PRIORITY_VERBOSE)) return;\r\n\tif (newControlDevice == ControlDevice && newControlMode == ControlMode)\r\n\t\treturn;\r\n\tconstexpr auto DebugChange = [](ControlTypes before, ControlTypes after) -> std::string {\r\n\t\tif (before == after)\r\n\t\t\treturn std::string { ControlTypeToString(before) };\r\n\t\treturn StrCat(ControlTypeToString(before), \" -> \", ControlTypeToString(after));\r\n\t};\r\n\tLogVerbose(\"Control: device {}, mode {}\", DebugChange(ControlDevice, newControlDevice), DebugChange(ControlMode, newControlMode));\r\n}\r\n\r\n#ifndef USE_SDL1\r\nstd::string_view GamepadTypeToString(GamepadLayout gamepadLayout)\r\n{\r\n\tswitch (gamepadLayout) {\r\n\tcase GamepadLayout::Nintendo:\r\n\t\treturn \"Nintendo\";\r\n\tcase GamepadLayout::PlayStation:\r\n\t\treturn \"PlayStation\";\r\n\tcase GamepadLayout::Xbox:\r\n\t\treturn \"Xbox\";\r\n\tcase GamepadLayout::Generic:\r\n\t\treturn \"Unknown\";\r\n\t}\r\n\treturn \"Invalid\";\r\n}\r\n\r\nvoid LogGamepadChange(GamepadLayout newGamepad)\r\n{\r\n\tif (!IsLogLevel(LogCategory::Application, SDL_LOG_PRIORITY_VERBOSE)) return;\r\n\tconstexpr auto DebugChange = [](GamepadLayout before, GamepadLayout after) -> std::string {\r\n\t\tif (before == after)\r\n\t\t\treturn std::string { GamepadTypeToString(before) };\r\n\t\treturn StrCat(GamepadTypeToString(before), \" -> \", GamepadTypeToString(after));\r\n\t};\r\n\tLogVerbose(\"Control: gamepad {}\", DebugChange(GamepadType, newGamepad));\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\nvoid DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent)\r\n{\r\n\tControlTypes inputType = GetInputTypeFromEvent(event);\r\n\r\n\tif (inputType == ControlTypes::None)\r\n\t\treturn;\r\n\r\n#ifdef __vita__\r\n\tif (inputType == ControlTypes::VirtualGamepad) {\r\n\t\tinputType = ControlTypes::Gamepad;\r\n\t}\r\n#endif\r\n\r\n#if HAS_KBCTRL == 1\r\n\tif (inputType == ControlTypes::KeyboardAndMouse && gamepadEvent.button != ControllerButton_NONE) {\r\n\t\tinputType = ControlTypes::Gamepad;\r\n\t}\r\n#endif\r\n\r\n\tconst ControlTypes newControlDevice = inputType;\r\n\tControlTypes newControlMode = inputType;\r\n\tif (ContinueSimulatedMouseEvent(event, gamepadEvent)) {\r\n\t\tnewControlMode = ControlMode;\r\n\t}\r\n\r\n\tLogControlDeviceAndModeChange(newControlDevice, newControlMode);\r\n\r\n\tif (newControlDevice != ControlDevice) {\r\n\t\tControlDevice = newControlDevice;\r\n\r\n#ifndef USE_SDL1\r\n\t\tif (ControlDevice != ControlTypes::KeyboardAndMouse) {\r\n\t\t\tif (IsHardwareCursor())\r\n\t\t\t\tSetHardwareCursor(CursorInfo::UnknownCursor());\r\n\t\t} else {\r\n\t\t\tResetCursor();\r\n\t\t}\r\n\t\tif (ControlDevice == ControlTypes::Gamepad) {\r\n\t\t\tconst GamepadLayout newGamepadLayout = GameController::getLayout(event);\r\n\t\t\tif (newGamepadLayout != GamepadType) {\r\n\t\t\t\tLogGamepadChange(newGamepadLayout);\r\n\t\t\t\tGamepadType = newGamepadLayout;\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n\t}\r\n\r\n\tif (newControlMode != ControlMode) {\r\n\t\tControlMode = newControlMode;\r\n\t\tCalculatePanelAreas();\r\n\t}\r\n}\r\n\r\nvoid ProcessGameAction(const GameAction &action)\r\n{\r\n\tswitch (action.type) {\r\n\tcase GameActionType_NONE:\r\n\tcase GameActionType_SEND_KEY:\r\n\t\tbreak;\r\n\tcase GameActionType_USE_HEALTH_POTION:\r\n\t\tUseBeltItem(BeltItemType::Healing);\r\n\t\tbreak;\r\n\tcase GameActionType_USE_MANA_POTION:\r\n\t\tUseBeltItem(BeltItemType::Mana);\r\n\t\tbreak;\r\n\tcase GameActionType_PRIMARY_ACTION:\r\n\t\tPerformPrimaryAction();\r\n\t\tbreak;\r\n\tcase GameActionType_SECONDARY_ACTION:\r\n\t\tPerformSecondaryAction();\r\n\t\tbreak;\r\n\tcase GameActionType_CAST_SPELL:\r\n\t\tif (!InGameMenu())\r\n\t\t\tPerformSpellAction();\r\n\t\tbreak;\r\n\tcase GameActionType_TOGGLE_QUICK_SPELL_MENU:\r\n\t\tif (!invflag || BlurInventory()) {\r\n\t\t\tif (!SpellSelectFlag)\r\n\t\t\t\tDoSpeedBook();\r\n\t\t\telse\r\n\t\t\t\tSpellSelectFlag = false;\r\n\t\t\tCloseCharPanel();\r\n\t\t\tQuestLogIsOpen = false;\r\n\t\t\tSpellbookFlag = false;\r\n\t\t\tCloseGoldWithdraw();\r\n\t\t\tCloseStash();\r\n\t\t}\r\n\t\tbreak;\r\n\tcase GameActionType_TOGGLE_CHARACTER_INFO:\r\n\t\tToggleCharPanel();\r\n\t\tif (CharFlag) {\r\n\t\t\tSpellSelectFlag = false;\r\n\t\t\tif (pcurs == CURSOR_DISARM)\r\n\t\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\tFocusOnCharInfo();\r\n\t\t}\r\n\t\tbreak;\r\n\tcase GameActionType_TOGGLE_QUEST_LOG:\r\n\t\tif (!QuestLogIsOpen) {\r\n\t\t\tStartQuestlog();\r\n\t\t\tCloseCharPanel();\r\n\t\t\tCloseGoldWithdraw();\r\n\t\t\tCloseStash();\r\n\t\t\tSpellSelectFlag = false;\r\n\t\t} else {\r\n\t\t\tQuestLogIsOpen = false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase GameActionType_TOGGLE_INVENTORY:\r\n\t\tif (invflag) {\r\n\t\t\tBlurInventory();\r\n\t\t} else {\r\n\t\t\tSpellbookFlag = false;\r\n\t\t\tSpellSelectFlag = false;\r\n\t\t\tinvflag = true;\r\n\t\t\tif (pcurs == CURSOR_DISARM)\r\n\t\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\tFocusOnInventory();\r\n\t\t}\r\n\t\tbreak;\r\n\tcase GameActionType_TOGGLE_SPELL_BOOK:\r\n\t\tif (BlurInventory()) {\r\n\t\t\tCloseInventory();\r\n\t\t\tSpellSelectFlag = false;\r\n\t\t\tSpellbookFlag = !SpellbookFlag;\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid HandleRightStickMotion()\r\n{\r\n\tstatic RightStickAccumulator acc;\r\n\t// deadzone is handled in ScaleJoystickAxes() already\r\n\tif (rightStickX == 0 && rightStickY == 0) {\r\n\t\tacc.Clear();\r\n\t\treturn;\r\n\t}\r\n\r\n\t{ // move cursor\r\n\t\tInvalidateInventorySlot();\r\n\t\tint x = MousePosition.x;\r\n\t\tint y = MousePosition.y;\r\n\t\tacc.Pool(&x, &y, 2);\r\n\t\tx = std::min(std::max(x, 0), gnScreenWidth - 1);\r\n\t\ty = std::min(std::max(y, 0), gnScreenHeight - 1);\r\n\r\n\t\t// We avoid calling `SetCursorPos` within the same SDL tick because\r\n\t\t// that can cause all stick motion events to arrive before all\r\n\t\t// cursor position events.\r\n\t\tstatic int lastMouseSetTick = 0;\r\n\t\tconst int now = SDL_GetTicks();\r\n\t\tif (now - lastMouseSetTick > 0) {\r\n\t\t\tResetCursor();\r\n\t\t\tSetCursorPos({ x, y });\r\n\t\t\tLogControlDeviceAndModeChange(ControlDevice, ControlTypes::KeyboardAndMouse);\r\n\r\n\t\t\tControlMode = ControlTypes::KeyboardAndMouse;\r\n\t\t\tlastMouseSetTick = now;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InvalidateInventorySlot()\r\n{\r\n\tSlot = -1;\r\n\tActiveStashSlot = InvalidStashPoint;\r\n}\r\n\r\n/**\r\n * @brief Moves the mouse to the first inventory slot.\r\n */\r\nvoid FocusOnInventory()\r\n{\r\n\tSlot = SLOTXY_INV_FIRST;\r\n\tResetInvCursorPosition();\r\n}\r\n\r\nbool PointAndClickState = false;\r\n\r\nvoid SetPointAndClick(bool value)\r\n{\r\n\tPointAndClickState = value;\r\n}\r\n\r\nbool IsPointAndClick()\r\n{\r\n\treturn PointAndClickState;\r\n}\r\n\r\nbool IsMovementHandlerActive()\r\n{\r\n\treturn GetLeftStickOrDPadGameUIHandler() != nullptr;\r\n}\r\n\r\nvoid plrctrls_after_check_curs_move()\r\n{\r\n\t// check for monsters first, then items, then towners.\r\n\tif (ControlMode == ControlTypes::KeyboardAndMouse || IsPointAndClick()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// While holding the button down we should retain target (but potentially lose it if it dies, goes out of view, etc)\r\n\tif (ControllerActionHeld != GameActionType_NONE && IsNoneOf(LastPlayerAction, PlayerActionType::None, PlayerActionType::Attack, PlayerActionType::Spell)) {\r\n\t\tInvalidateTargets();\r\n\r\n\t\tif (pcursmonst == -1 && ObjectUnderCursor == nullptr && pcursitem == -1 && pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell && PlayerUnderCursor == nullptr) {\r\n\t\t\tFindTrigger();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Clear focus set by cursor\r\n\tPlayerUnderCursor = nullptr;\r\n\tpcursmonst = -1;\r\n\tpcursitem = -1;\r\n\tObjectUnderCursor = nullptr;\r\n\r\n\tpcursmissile = nullptr;\r\n\tpcurstrig = -1;\r\n\tpcursquest = Q_INVALID;\r\n\tcursPosition = { -1, -1 };\r\n\tif (MyPlayer->_pInvincible) {\r\n\t\treturn;\r\n\t}\r\n\tif (DoomFlag) {\r\n\t\treturn;\r\n\t}\r\n\tif (!invflag) {\r\n\t\tInfoString = StringOrView {};\r\n\t\tFindActor();\r\n\t\tFindItemOrObject();\r\n\t\tFindTrigger();\r\n\t}\r\n}\r\n\r\nvoid plrctrls_every_frame()\r\n{\r\n\tProcessLeftStickOrDPadGameUI();\r\n\tHandleRightStickMotion();\r\n\tProcessAutomapMovementGamepad();\r\n}\r\n\r\nvoid plrctrls_after_game_logic()\r\n{\r\n\tMovement(*MyPlayer);\r\n}\r\n\r\nvoid UseBeltItem(BeltItemType type)\r\n{\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tconst Item &item = MyPlayer->SpdList[i];\r\n\t\tif (item.isEmpty()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst bool isRejuvenation = IsAnyOf(item._iMiscId, IMISC_REJUV, IMISC_FULLREJUV) || (item._iMiscId == IMISC_ARENAPOT && MyPlayer->isOnArenaLevel());\r\n\t\tconst bool isHealing = isRejuvenation || IsAnyOf(item._iMiscId, IMISC_HEAL, IMISC_FULLHEAL) || item.isScrollOf(SpellID::Healing);\r\n\t\tconst bool isMana = isRejuvenation || IsAnyOf(item._iMiscId, IMISC_MANA, IMISC_FULLMANA);\r\n\r\n\t\tif ((type == BeltItemType::Healing && isHealing) || (type == BeltItemType::Mana && isMana)) {\r\n\t\t\tUseInvItem(INVITEM_BELT_FIRST + i);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PerformPrimaryAction()\r\n{\r\n\tif (SpellSelectFlag) {\r\n\t\tSetSpell();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (invflag) { // inventory is open\r\n\t\tif (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) {\r\n\t\t\tif (pcurs == CURSOR_HOURGLASS)\r\n\t\t\t\treturn;\r\n\t\t\tTryIconCurs();\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t} else if (GetRightPanel().contains(MousePosition) || GetMainPanel().contains(MousePosition)) {\r\n\t\t\tLiftInventoryItem();\r\n\t\t} else if (IsStashOpen && GetLeftPanel().contains(MousePosition)) {\r\n\t\t\tLiftStashItem();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (CharFlag && !CharPanelButtonActive && MyPlayer->_pStatPts > 0) {\r\n\t\tCheckChrBtns();\r\n\t\tif (CharPanelButtonActive)\r\n\t\t\tReleaseChrBtns(false);\r\n\t\treturn;\r\n\t}\r\n\r\n\tInteract();\r\n}\r\n\r\nbool SpellHasActorTarget()\r\n{\r\n\tconst SpellID spl = MyPlayer->_pRSpell;\r\n\tif (spl == SpellID::TownPortal || spl == SpellID::Teleport)\r\n\t\treturn false;\r\n\r\n\tif (IsWallSpell(spl) && pcursmonst != -1) {\r\n\t\tcursPosition = Monsters[pcursmonst].position.tile;\r\n\t}\r\n\r\n\treturn PlayerUnderCursor != nullptr || pcursmonst != -1;\r\n}\r\n\r\nvoid UpdateSpellTarget(SpellID spell)\r\n{\r\n\tif (SpellHasActorTarget())\r\n\t\treturn;\r\n\r\n\tPlayerUnderCursor = nullptr;\r\n\tpcursmonst = -1;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tconst int range = spell == SpellID::Teleport ? 4 : 1;\r\n\r\n\tcursPosition = myPlayer.position.future + Displacement(myPlayer._pdir) * range;\r\n}\r\n\r\n/**\r\n * @brief Try dropping item in all 9 possible places\r\n */\r\nbool TryDropItem()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer.HoldItem.isEmpty()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tif (UseItemOpensHive(myPlayer.HoldItem, myPlayer.position.tile)) {\r\n\t\t\tOpenHive();\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (UseItemOpensGrave(myPlayer.HoldItem, myPlayer.position.tile)) {\r\n\t\t\tOpenGrave();\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tstd::optional<Point> itemTile = FindAdjacentPositionForItem(myPlayer.position.future, myPlayer._pdir);\r\n\tif (!itemTile) {\r\n\t\tmyPlayer.Say(HeroSpeech::WhereWouldIPutThis);\r\n\t\treturn false;\r\n\t}\r\n\r\n\tNetSendCmdPItem(true, CMD_PUTITEM, *itemTile, myPlayer.HoldItem);\r\n\tmyPlayer.HoldItem.clear();\r\n\tNewCursor(CURSOR_HAND);\r\n\treturn true;\r\n}\r\n\r\nvoid PerformSpellAction()\r\n{\r\n\tif (SpellSelectFlag) {\r\n\t\tSetSpell();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (QuestLogIsOpen)\r\n\t\treturn;\r\n\r\n\tif (invflag) {\r\n\t\tif (!MyPlayer->HoldItem.isEmpty())\r\n\t\t\tTryDropItem();\r\n\t\telse if (pcurs > CURSOR_HAND) {\r\n\t\t\tTryIconCurs();\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t} else if (pcursinvitem != -1) {\r\n\t\t\tconst int itemId = GetItemIdOnSlot(Slot);\r\n\t\t\tCheckInvItem(true, false);\r\n\t\t\tif (itemId != GetItemIdOnSlot(Slot))\r\n\t\t\t\tResetInvCursorPosition();\r\n\t\t} else if (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\t\tCheckStashItem(MousePosition, true, false);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!MyPlayer->HoldItem.isEmpty() && !TryDropItem())\r\n\t\treturn;\r\n\tif (pcurs > CURSOR_HAND)\r\n\t\tNewCursor(CURSOR_HAND);\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tconst SpellID spl = myPlayer._pRSpell;\r\n\tif ((PlayerUnderCursor == nullptr && (spl == SpellID::Resurrect || spl == SpellID::HealOther))\r\n\t    || (ObjectUnderCursor == nullptr && spl == SpellID::TrapDisarm)) {\r\n\t\tmyPlayer.Say(HeroSpeech::ICantCastThatHere);\r\n\t\treturn;\r\n\t}\r\n\r\n\tUpdateSpellTarget(myPlayer._pRSpell);\r\n\tCheckPlrSpell(false);\r\n\tif (PlayerUnderCursor != nullptr)\r\n\t\tLastPlayerAction = PlayerActionType::SpellPlayerTarget;\r\n\telse if (pcursmonst != -1)\r\n\t\tLastPlayerAction = PlayerActionType::SpellMonsterTarget;\r\n\telse\r\n\t\tLastPlayerAction = PlayerActionType::Spell;\r\n}\r\n\r\nvoid CtrlUseInvItem()\r\n{\r\n\tif (pcursinvitem == -1) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tconst Item &item = GetInventoryItem(myPlayer, pcursinvitem);\r\n\tif (item.isScroll()) {\r\n\t\tif (TargetsMonster(item._iSpell)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (GetSpellData(item._iSpell).isTargeted()) {\r\n\t\t\tUpdateSpellTarget(item._iSpell);\r\n\t\t}\r\n\t}\r\n\r\n\tconst int itemId = GetItemIdOnSlot(Slot);\r\n\tif (item.isEquipment()) {\r\n\t\tCheckInvItem(true, false); // auto-equip if it's an equipment\r\n\t} else {\r\n\t\tUseInvItem(pcursinvitem);\r\n\t}\r\n\tif (itemId != GetItemIdOnSlot(Slot)) {\r\n\t\tResetInvCursorPosition();\r\n\t}\r\n}\r\n\r\nvoid CtrlUseStashItem()\r\n{\r\n\tif (pcursstashitem == StashStruct::EmptyCell) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Item &item = Stash.stashList[pcursstashitem];\r\n\tif (item.isScroll()) {\r\n\t\tif (TargetsMonster(item._iSpell)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (GetSpellData(item._iSpell).isTargeted()) {\r\n\t\t\tUpdateSpellTarget(item._iSpell);\r\n\t\t}\r\n\t}\r\n\r\n\tif (item.isEquipment()) {\r\n\t\tCheckStashItem(MousePosition, true, false); // Auto-equip if it's equipment\r\n\t} else {\r\n\t\tUseStashItem(pcursstashitem);\r\n\t}\r\n\t// Todo reset cursor position if item is moved\r\n}\r\n\r\nvoid PerformSecondaryAction()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (invflag) {\r\n\t\tif (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) {\r\n\t\t\tTryIconCurs();\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t} else if (IsStashOpen) {\r\n\t\t\tif (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\t\t\tTransferItemToInventory(myPlayer, pcursstashitem);\r\n\t\t\t} else if (pcursinvitem != -1) {\r\n\t\t\t\tTransferItemToStash(myPlayer, pcursinvitem);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tCtrlUseInvItem();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!MyPlayer->HoldItem.isEmpty() && !TryDropItem())\r\n\t\treturn;\r\n\tif (pcurs > CURSOR_HAND)\r\n\t\tNewCursor(CURSOR_HAND);\r\n\r\n\tif (pcursitem != -1) {\r\n\t\tNetSendCmdLocParam1(true, CMD_GOTOAGETITEM, cursPosition, pcursitem);\r\n\t} else if (ObjectUnderCursor != nullptr) {\r\n\t\tNetSendCmdLoc(MyPlayerId, true, CMD_OPOBJXY, cursPosition);\r\n\t\tLastPlayerAction = PlayerActionType::OperateObject;\r\n\t} else {\r\n\t\tif (pcursmissile != nullptr) {\r\n\t\t\tMakePlrPath(myPlayer, pcursmissile->position.tile, true);\r\n\t\t\tmyPlayer.destAction = ACTION_WALK;\r\n\t\t} else if (pcurstrig != -1) {\r\n\t\t\tMakePlrPath(myPlayer, trigs[pcurstrig].position, true);\r\n\t\t\tmyPlayer.destAction = ACTION_WALK;\r\n\t\t} else if (pcursquest != Q_INVALID) {\r\n\t\t\tMakePlrPath(myPlayer, Quests[pcursquest].position, true);\r\n\t\t\tmyPlayer.destAction = ACTION_WALK;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid QuickCast(size_t slot)\r\n{\r\n\tconst PlayerActionType prevMouseButtonAction = LastPlayerAction;\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tconst SpellID spell = myPlayer._pSplHotKey[slot];\r\n\tconst SpellType spellType = myPlayer._pSplTHotKey[slot];\r\n\r\n\tif (ControlMode != ControlTypes::KeyboardAndMouse) {\r\n\t\tUpdateSpellTarget(spell);\r\n\t}\r\n\r\n\tCheckPlrSpell(false, spell, spellType);\r\n\tLastPlayerAction = prevMouseButtonAction;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/plrctrls.h",
    "content": "#pragma once\r\n// Controller actions implementation\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/controller.h\"\r\n#include \"controls/game_controls.h\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class BeltItemType : uint8_t {\r\n\tHealing,\r\n\tMana,\r\n};\r\n\r\nextern GameActionType ControllerActionHeld;\r\nextern bool StandToggle;\r\n\r\n// Runs every frame.\r\n// Handles menu movement.\r\nvoid plrctrls_every_frame();\r\n\r\n// Run after every game logic iteration.\r\n// Handles player movement.\r\nvoid plrctrls_after_game_logic();\r\n\r\n// Runs at the end of CheckCursMove()\r\n// Handles item, object, and monster auto-aim.\r\nvoid plrctrls_after_check_curs_move();\r\n\r\n// Moves the map if active, the cursor otherwise.\r\nvoid HandleRightStickMotion();\r\n\r\n// Whether we're in a dialog menu that the game handles natively with keyboard controls.\r\nbool InGameMenu();\r\n\r\nvoid SetPointAndClick(bool value);\r\n\r\nbool IsPointAndClick();\r\nbool IsMovementHandlerActive();\r\n\r\nvoid DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent);\r\nvoid ProcessGameAction(const GameAction &action);\r\n\r\nvoid UseBeltItem(BeltItemType type);\r\n\r\n// Talk to towners, click on inv items, attack, etc.\r\nvoid PerformPrimaryAction();\r\n\r\n// Open chests, doors, pickup items.\r\nvoid PerformSecondaryAction();\r\nvoid UpdateSpellTarget(SpellID spell);\r\nbool TryDropItem();\r\nvoid InvalidateInventorySlot();\r\nvoid FocusOnInventory();\r\nvoid PerformSpellAction();\r\nvoid QuickCast(size_t slot);\r\n\r\nextern int speedspellcount;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/remap_keyboard.h",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n// Re-maps a keyboard key as per the REMAP_KEYBOARD_KEYS define.\r\ninline void remap_keyboard_key(SDL_Keycode *sym)\r\n{\r\n#ifdef REMAP_KEYBOARD_KEYS\r\n\r\n\tstruct Mapping {\r\n\t\tSDL_Keycode from;\r\n\t\tSDL_Keycode to;\r\n\t};\r\n\tconstexpr Mapping kMappings[] = { REMAP_KEYBOARD_KEYS };\r\n\tfor (std::size_t i = 0; i < sizeof(kMappings) / sizeof(kMappings[0]); ++i) {\r\n\t\tif (*sym == kMappings[i].from) {\r\n\t\t\t*sym = kMappings[i].to;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/touch/event_handlers.cpp",
    "content": "#include \"controls/touch/event_handlers.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"control/control.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"diablo.h\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/scrollrt.h\"\r\n#include \"game_mode.hpp\"\r\n#include \"gmenu.h\"\r\n#include \"inv.h\"\r\n#include \"panels/spell_book.hpp\"\r\n#include \"panels/spell_list.hpp\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nusing SdlEventType = uint16_t;\r\n#else\r\nusing SdlEventType = uint8_t;\r\n#endif\r\n\r\nVirtualGamepadEventHandler Handler(&VirtualGamepadState);\r\n\r\nPoint ScaleToScreenCoordinates(float x, float y)\r\n{\r\n\treturn Point {\r\n\t\t(int)round(x * gnScreenWidth),\r\n\t\t(int)round(y * gnScreenHeight)\r\n\t};\r\n}\r\n\r\nconstexpr bool IsFingerDown(const SDL_Event &event)\r\n{\r\n\treturn event.type == SDL_EVENT_FINGER_DOWN;\r\n}\r\n\r\nconstexpr bool IsFingerUp(const SDL_Event &event)\r\n{\r\n\treturn event.type == SDL_EVENT_FINGER_UP;\r\n}\r\n\r\nconstexpr bool IsFingerMotion(const SDL_Event &event)\r\n{\r\n\treturn event.type == SDL_EVENT_FINGER_MOTION;\r\n}\r\n\r\nconstexpr SDL_FingerID FingerId(const SDL_TouchFingerEvent &event)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn event.fingerID;\r\n#else\r\n\treturn event.fingerId;\r\n#endif\r\n}\r\n\r\nvoid SimulateMouseMovement(const SDL_Event &event)\r\n{\r\n\tconst Point position = ScaleToScreenCoordinates(event.tfinger.x, event.tfinger.y);\r\n\r\n\tconst bool isInMainPanel = GetMainPanel().contains(position);\r\n\tconst bool isInLeftPanel = GetLeftPanel().contains(position);\r\n\tconst bool isInRightPanel = GetRightPanel().contains(position);\r\n\tif (IsStashOpen) {\r\n\t\tif (!SpellSelectFlag && !isInMainPanel && !isInLeftPanel && !isInRightPanel)\r\n\t\t\treturn;\r\n\t} else if (invflag) {\r\n\t\tif (!SpellSelectFlag && !isInMainPanel && !isInRightPanel)\r\n\t\t\treturn;\r\n\t}\r\n\r\n\tMousePosition = position;\r\n\r\n\tSetPointAndClick(true);\r\n\r\n\tInvalidateInventorySlot();\r\n}\r\n\r\nbool HandleGameMenuInteraction(const SDL_Event &event)\r\n{\r\n\tif (!gmenu_is_active())\r\n\t\treturn false;\r\n\tif (IsFingerDown(event) && gmenu_left_mouse(true))\r\n\t\treturn true;\r\n\tif (IsFingerMotion(event) && gmenu_on_mouse_move())\r\n\t\treturn true;\r\n\treturn IsFingerUp(event) && gmenu_left_mouse(false);\r\n}\r\n\r\nbool HandleStoreInteraction(const SDL_Event &event)\r\n{\r\n\tif (!IsPlayerInStore())\r\n\t\treturn false;\r\n\tif (IsFingerDown(event))\r\n\t\tCheckStoreBtn();\r\n\treturn true;\r\n}\r\n\r\nvoid HandleSpellBookInteraction(const SDL_Event &event)\r\n{\r\n\tif (!SpellbookFlag)\r\n\t\treturn;\r\n\r\n\tif (IsFingerUp(event))\r\n\t\tCheckSBook();\r\n}\r\n\r\nbool HandleSpeedBookInteraction(const SDL_Event &event)\r\n{\r\n\tif (!SpellSelectFlag)\r\n\t\treturn false;\r\n\tif (IsFingerUp(event))\r\n\t\tSetSpell();\r\n\treturn true;\r\n}\r\n\r\nvoid HandleBottomPanelInteraction(const SDL_Event &event)\r\n{\r\n\tif (!gbRunGame || !MyPlayer->HoldItem.isEmpty())\r\n\t\treturn;\r\n\r\n\tResetMainPanelButtons();\r\n\r\n\tif (!IsFingerUp(event)) {\r\n\t\tSpellSelectFlag = true;\r\n\t\tCheckMainPanelButton();\r\n\t\tSpellSelectFlag = false;\r\n\t} else {\r\n\t\tCheckMainPanelButton();\r\n\t\tif (MainPanelButtonDown)\r\n\t\t\tCheckMainPanelButtonUp();\r\n\t}\r\n}\r\n\r\nvoid HandleCharacterPanelInteraction(const SDL_Event &event)\r\n{\r\n\tif (!CharFlag)\r\n\t\treturn;\r\n\r\n\tif (IsFingerDown(event))\r\n\t\tCheckChrBtns();\r\n\telse if (IsFingerUp(event) && CharPanelButtonActive)\r\n\t\tReleaseChrBtns(false);\r\n}\r\n\r\nvoid HandleStashPanelInteraction(const SDL_Event &event)\r\n{\r\n\tif (!IsStashOpen || !MyPlayer->HoldItem.isEmpty())\r\n\t\treturn;\r\n\r\n\tif (!IsFingerUp(event)) {\r\n\t\tCheckStashButtonPress(MousePosition);\r\n\t} else {\r\n\t\tCheckStashButtonRelease(MousePosition);\r\n\t}\r\n}\r\n\r\nSdlEventType GetDeactivateEventType()\r\n{\r\n\tstatic const SdlEventType customEventType = SDL_RegisterEvents(1);\r\n\treturn customEventType;\r\n}\r\n\r\nbool IsDeactivateEvent(const SDL_Event &event)\r\n{\r\n\treturn event.type == GetDeactivateEventType();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid HandleTouchEvent(const SDL_Event &event)\r\n{\r\n\tSetPointAndClick(false);\r\n\r\n\tif (Handler.Handle(event)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!IsFingerDown(event) && !IsFingerUp(event) && !IsFingerMotion(event)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tSimulateMouseMovement(event);\r\n\r\n\tif (HandleGameMenuInteraction(event))\r\n\t\treturn;\r\n\r\n\tif (HandleStoreInteraction(event))\r\n\t\treturn;\r\n\r\n\tif (HandleSpeedBookInteraction(event))\r\n\t\treturn;\r\n\r\n\tHandleSpellBookInteraction(event);\r\n\tHandleBottomPanelInteraction(event);\r\n\tHandleCharacterPanelInteraction(event);\r\n\tHandleStashPanelInteraction(event);\r\n}\r\n\r\nvoid DeactivateTouchEventHandlers()\r\n{\r\n\tSDL_Event event;\r\n\tevent.type = GetDeactivateEventType();\r\n\tHandleTouchEvent(event);\r\n}\r\n\r\nbool VirtualGamepadEventHandler::Handle(const SDL_Event &event)\r\n{\r\n\tif (!IsDeactivateEvent(event)) {\r\n\t\tif (!VirtualGamepadState.isActive || (!IsFingerDown(event) && !IsFingerUp(event) && !IsFingerMotion(event))) {\r\n\t\t\tVirtualGamepadState.primaryActionButton.didStateChange = false;\r\n\t\t\tVirtualGamepadState.secondaryActionButton.didStateChange = false;\r\n\t\t\tVirtualGamepadState.spellActionButton.didStateChange = false;\r\n\t\t\tVirtualGamepadState.cancelButton.didStateChange = false;\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tif (charMenuButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (questsMenuButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (inventoryMenuButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (mapMenuButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (directionPadEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (leveltype != DTYPE_TOWN && standButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (primaryActionButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (secondaryActionButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (spellActionButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (cancelButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (healthButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\tif (manaButtonEventHandler.Handle(event))\r\n\t\treturn true;\r\n\r\n\treturn false;\r\n}\r\n\r\nbool VirtualDirectionPadEventHandler::Handle(const SDL_Event &event)\r\n{\r\n\tif (IsDeactivateEvent(event)) {\r\n\t\tisActive = false;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (IsFingerDown(event)) return HandleFingerDown(event.tfinger);\r\n\tif (IsFingerUp(event)) return HandleFingerUp(event.tfinger);\r\n\tif (IsFingerMotion(event)) return HandleFingerMotion(event.tfinger);\r\n\treturn false;\r\n}\r\n\r\nbool VirtualDirectionPadEventHandler::HandleFingerDown(const SDL_TouchFingerEvent &event)\r\n{\r\n\tif (isActive)\r\n\t\treturn false;\r\n\r\n\tconst float x = event.x;\r\n\tconst float y = event.y;\r\n\r\n\tconst Point touchCoordinates = ScaleToScreenCoordinates(x, y);\r\n\tif (!virtualDirectionPad->area.contains(touchCoordinates))\r\n\t\treturn false;\r\n\r\n\tvirtualDirectionPad->UpdatePosition(touchCoordinates);\r\n\tactiveFinger = FingerId(event);\r\n\tisActive = true;\r\n\treturn true;\r\n}\r\n\r\nbool VirtualDirectionPadEventHandler::HandleFingerUp(const SDL_TouchFingerEvent &event)\r\n{\r\n\tif (!isActive || FingerId(event) != activeFinger)\r\n\t\treturn false;\r\n\r\n\tconst Point position = virtualDirectionPad->area.position;\r\n\tvirtualDirectionPad->UpdatePosition(position);\r\n\tisActive = false;\r\n\treturn true;\r\n}\r\n\r\nbool VirtualDirectionPadEventHandler::HandleFingerMotion(const SDL_TouchFingerEvent &event)\r\n{\r\n\tif (!isActive || FingerId(event) != activeFinger)\r\n\t\treturn false;\r\n\r\n\tconst float x = event.x;\r\n\tconst float y = event.y;\r\n\r\n\tconst Point touchCoordinates = ScaleToScreenCoordinates(x, y);\r\n\tvirtualDirectionPad->UpdatePosition(touchCoordinates);\r\n\treturn true;\r\n}\r\n\r\nbool VirtualButtonEventHandler::Handle(const SDL_Event &event)\r\n{\r\n\tif (IsDeactivateEvent(event)) {\r\n\t\tisActive = false;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (!virtualButton->isUsable()) {\r\n\t\tvirtualButton->didStateChange = virtualButton->isHeld;\r\n\t\tvirtualButton->isHeld = false;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tvirtualButton->didStateChange = false;\r\n\r\n\tif (IsFingerDown(event)) return HandleFingerDown(event.tfinger);\r\n\tif (IsFingerUp(event)) return HandleFingerUp(event.tfinger);\r\n\tif (IsFingerMotion(event)) return HandleFingerMotion(event.tfinger);\r\n\treturn false;\r\n}\r\n\r\nbool VirtualButtonEventHandler::HandleFingerDown(const SDL_TouchFingerEvent &event)\r\n{\r\n\tif (isActive)\r\n\t\treturn false;\r\n\r\n\tconst float x = event.x;\r\n\tconst float y = event.y;\r\n\r\n\tconst Point touchCoordinates = ScaleToScreenCoordinates(x, y);\r\n\tif (!virtualButton->contains(touchCoordinates))\r\n\t\treturn false;\r\n\r\n\tif (toggles)\r\n\t\tvirtualButton->isHeld = !virtualButton->isHeld;\r\n\telse\r\n\t\tvirtualButton->isHeld = true;\r\n\r\n\tvirtualButton->didStateChange = true;\r\n\tactiveFinger = FingerId(event);\r\n\tisActive = true;\r\n\treturn true;\r\n}\r\n\r\nbool VirtualButtonEventHandler::HandleFingerUp(const SDL_TouchFingerEvent &event)\r\n{\r\n\tif (!isActive || FingerId(event) != activeFinger)\r\n\t\treturn false;\r\n\r\n\tif (!toggles) {\r\n\t\tif (virtualButton->isHeld)\r\n\t\t\tvirtualButton->didStateChange = true;\r\n\t\tvirtualButton->isHeld = false;\r\n\t}\r\n\r\n\tisActive = false;\r\n\treturn true;\r\n}\r\n\r\nbool VirtualButtonEventHandler::HandleFingerMotion(const SDL_TouchFingerEvent &event)\r\n{\r\n\tif (!isActive || FingerId(event) != activeFinger)\r\n\t\treturn false;\r\n\r\n\tif (toggles)\r\n\t\treturn true;\r\n\r\n\tconst float x = event.x;\r\n\tconst float y = event.y;\r\n\tconst Point touchCoordinates = ScaleToScreenCoordinates(x, y);\r\n\r\n\tconst bool wasHeld = virtualButton->isHeld;\r\n\tvirtualButton->isHeld = virtualButton->contains(touchCoordinates);\r\n\tvirtualButton->didStateChange = virtualButton->isHeld != wasHeld;\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/touch/event_handlers.h",
    "content": "#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/touch/gamepad.h\"\r\n\r\nnamespace devilution {\r\n\r\nclass VirtualDirectionPadEventHandler {\r\npublic:\r\n\tVirtualDirectionPadEventHandler(VirtualDirectionPad *virtualDirectionPad)\r\n\t    : virtualDirectionPad(virtualDirectionPad)\r\n\t    , activeFinger(0)\r\n\t    , isActive(false)\r\n\t{\r\n\t}\r\n\r\n\tbool Handle(const SDL_Event &event);\r\n\r\nprivate:\r\n\tVirtualDirectionPad *virtualDirectionPad;\r\n\tSDL_FingerID activeFinger;\r\n\tbool isActive;\r\n\r\n\tbool HandleFingerDown(const SDL_TouchFingerEvent &event);\r\n\tbool HandleFingerUp(const SDL_TouchFingerEvent &event);\r\n\tbool HandleFingerMotion(const SDL_TouchFingerEvent &event);\r\n};\r\n\r\nclass VirtualButtonEventHandler {\r\npublic:\r\n\tVirtualButtonEventHandler(VirtualButton *virtualButton, bool toggles = false)\r\n\t    : virtualButton(virtualButton)\r\n\t    , activeFinger(0)\r\n\t    , isActive(false)\r\n\t    , toggles(toggles)\r\n\t{\r\n\t}\r\n\r\n\tbool Handle(const SDL_Event &event);\r\n\r\nprivate:\r\n\tVirtualButton *virtualButton;\r\n\tSDL_FingerID activeFinger;\r\n\tbool isActive;\r\n\tbool toggles;\r\n\r\n\tbool HandleFingerDown(const SDL_TouchFingerEvent &event);\r\n\tbool HandleFingerUp(const SDL_TouchFingerEvent &event);\r\n\tbool HandleFingerMotion(const SDL_TouchFingerEvent &event);\r\n};\r\n\r\nclass VirtualGamepadEventHandler {\r\npublic:\r\n\tVirtualGamepadEventHandler(VirtualGamepad *virtualGamepad)\r\n\t    : charMenuButtonEventHandler(&virtualGamepad->menuPanel.charButton)\r\n\t    , questsMenuButtonEventHandler(&virtualGamepad->menuPanel.questsButton)\r\n\t    , inventoryMenuButtonEventHandler(&virtualGamepad->menuPanel.inventoryButton)\r\n\t    , mapMenuButtonEventHandler(&virtualGamepad->menuPanel.mapButton)\r\n\t    , directionPadEventHandler(&virtualGamepad->directionPad)\r\n\t    , standButtonEventHandler(&virtualGamepad->standButton, true)\r\n\t    , primaryActionButtonEventHandler(&virtualGamepad->primaryActionButton)\r\n\t    , secondaryActionButtonEventHandler(&virtualGamepad->secondaryActionButton)\r\n\t    , spellActionButtonEventHandler(&virtualGamepad->spellActionButton)\r\n\t    , cancelButtonEventHandler(&virtualGamepad->cancelButton)\r\n\t    , healthButtonEventHandler(&virtualGamepad->healthButton)\r\n\t    , manaButtonEventHandler(&virtualGamepad->manaButton)\r\n\t{\r\n\t}\r\n\r\n\tbool Handle(const SDL_Event &event);\r\n\r\nprivate:\r\n\tVirtualButtonEventHandler charMenuButtonEventHandler;\r\n\tVirtualButtonEventHandler questsMenuButtonEventHandler;\r\n\tVirtualButtonEventHandler inventoryMenuButtonEventHandler;\r\n\tVirtualButtonEventHandler mapMenuButtonEventHandler;\r\n\r\n\tVirtualDirectionPadEventHandler directionPadEventHandler;\r\n\tVirtualButtonEventHandler standButtonEventHandler;\r\n\r\n\tVirtualButtonEventHandler primaryActionButtonEventHandler;\r\n\tVirtualButtonEventHandler secondaryActionButtonEventHandler;\r\n\tVirtualButtonEventHandler spellActionButtonEventHandler;\r\n\tVirtualButtonEventHandler cancelButtonEventHandler;\r\n\r\n\tVirtualButtonEventHandler healthButtonEventHandler;\r\n\tVirtualButtonEventHandler manaButtonEventHandler;\r\n};\r\n\r\nvoid HandleTouchEvent(const SDL_Event &event);\r\nvoid DeactivateTouchEventHandlers();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/touch/gamepad.cpp",
    "content": "#include <cmath>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_video.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"control/control.hpp\"\r\n#include \"controls/touch/event_handlers.h\"\r\n#include \"controls/touch/gamepad.h\"\r\n#include \"quests.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nVirtualGamepad VirtualGamepadState;\r\n\r\nnamespace {\r\n\r\nconstexpr float Pi = 3.141592653589793F;\r\n\r\nint roundToInt(float value)\r\n{\r\n\treturn static_cast<int>(round(value));\r\n}\r\n\r\nconstexpr bool PointsUp(float angle)\r\n{\r\n\tconstexpr float UpAngle = Pi / 2;\r\n\tconstexpr float MinAngle = UpAngle - 3 * Pi / 8;\r\n\tconstexpr float MaxAngle = UpAngle + 3 * Pi / 8;\r\n\treturn MinAngle <= angle && angle <= MaxAngle;\r\n}\r\n\r\nconstexpr bool PointsDown(float angle)\r\n{\r\n\tconstexpr float DownAngle = -Pi / 2;\r\n\tconstexpr float MinAngle = DownAngle - 3 * Pi / 8;\r\n\tconstexpr float MaxAngle = DownAngle + 3 * Pi / 8;\r\n\treturn MinAngle <= angle && angle <= MaxAngle;\r\n}\r\n\r\nconstexpr bool PointsLeft(float angle)\r\n{\r\n\tconstexpr float MaxAngle = Pi - 3 * Pi / 8;\r\n\tconstexpr float MinAngle = -Pi + 3 * Pi / 8;\r\n\treturn !(MinAngle < angle && angle < MaxAngle);\r\n}\r\n\r\nconstexpr bool PointsRight(float angle)\r\n{\r\n\tconstexpr float MinAngle = -3 * Pi / 8;\r\n\tconstexpr float MaxAngle = 3 * Pi / 8;\r\n\treturn MinAngle <= angle && angle <= MaxAngle;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InitializeVirtualGamepad()\r\n{\r\n\tconst float sqrt2 = sqrtf(2.0F);\r\n\r\n\tconst int screenPixels = std::min(gnScreenWidth, gnScreenHeight);\r\n\tint inputMargin = screenPixels / 10;\r\n\tint menuButtonWidth = screenPixels / 10;\r\n\tint directionPadSize = screenPixels / 4;\r\n\tint padButtonSize = roundToInt(1.1F * screenPixels / 10);\r\n\tint padButtonSpacing = inputMargin / 3;\r\n\r\n#ifdef USE_SDL3\r\n\tconst float dpi = SDL_GetWindowDisplayScale(ghMainWnd);\r\n#else\r\n\tfloat dpi = 0.0F;\r\n\tfloat hdpi;\r\n\tfloat vdpi;\r\n\tconst int displayIndex = SDL_GetWindowDisplayIndex(ghMainWnd);\r\n\tif (SDL_GetDisplayDPI(displayIndex, nullptr, &hdpi, &vdpi) == 0) {\r\n\t\tint clientWidth;\r\n\t\tint clientHeight;\r\n\t\tif (renderer != nullptr)\r\n\t\t\tSDL_GetRendererOutputSize(renderer, &clientWidth, &clientHeight);\r\n\t\telse\r\n\t\t\tSDL_GetWindowSize(ghMainWnd, &clientWidth, &clientHeight);\r\n\r\n\t\thdpi *= static_cast<float>(gnScreenWidth) / clientWidth;\r\n\t\tvdpi *= static_cast<float>(gnScreenHeight) / clientHeight;\r\n\r\n\t\tdpi = std::min(hdpi, vdpi);\r\n\t}\r\n#endif\r\n\r\n\tif (dpi != 0.0F) {\r\n\t\tinputMargin = roundToInt(0.25F * dpi);\r\n\t\tmenuButtonWidth = roundToInt(0.2F * dpi);\r\n\t\tdirectionPadSize = roundToInt(dpi);\r\n\t\tpadButtonSize = roundToInt(0.3F * dpi);\r\n\t\tpadButtonSpacing = roundToInt(0.1F * dpi);\r\n\t}\r\n\r\n\tconst int menuPanelTopMargin = 30;\r\n\tconst int menuPanelButtonSpacing = 4;\r\n\tconst Size menuPanelButtonSize = { 64, 62 };\r\n\tconst int rightMarginMenuButton4 = menuPanelButtonSpacing + menuPanelButtonSize.width;\r\n\tconst int rightMarginMenuButton3 = rightMarginMenuButton4 + menuPanelButtonSpacing + menuPanelButtonSize.width;\r\n\tconst int rightMarginMenuButton2 = rightMarginMenuButton3 + menuPanelButtonSpacing + menuPanelButtonSize.width;\r\n\tconst int rightMarginMenuButton1 = rightMarginMenuButton2 + menuPanelButtonSpacing + menuPanelButtonSize.width;\r\n\r\n\tconst int padButtonAreaWidth = roundToInt(sqrt2 * (padButtonSize + padButtonSpacing));\r\n\r\n\tconst int padButtonRight = gnScreenWidth - inputMargin - padButtonSize / 2;\r\n\tconst int padButtonLeft = padButtonRight - padButtonAreaWidth;\r\n\tconst int padButtonBottom = gnScreenHeight - inputMargin - padButtonSize / 2;\r\n\tconst int padButtonTop = padButtonBottom - padButtonAreaWidth;\r\n\r\n\tRectangle &charButtonArea = VirtualGamepadState.menuPanel.charButton.area;\r\n\tcharButtonArea.position.x = gnScreenWidth - rightMarginMenuButton1 * menuButtonWidth / menuPanelButtonSize.width;\r\n\tcharButtonArea.position.y = menuPanelTopMargin * menuButtonWidth / menuPanelButtonSize.width;\r\n\tcharButtonArea.size.width = menuButtonWidth;\r\n\tcharButtonArea.size.height = menuPanelButtonSize.height * menuButtonWidth / menuPanelButtonSize.width;\r\n\r\n\tRectangle &questsButtonArea = VirtualGamepadState.menuPanel.questsButton.area;\r\n\tquestsButtonArea.position.x = gnScreenWidth - rightMarginMenuButton2 * menuButtonWidth / menuPanelButtonSize.width;\r\n\tquestsButtonArea.position.y = menuPanelTopMargin * menuButtonWidth / menuPanelButtonSize.width;\r\n\tquestsButtonArea.size.width = menuButtonWidth;\r\n\tquestsButtonArea.size.height = menuPanelButtonSize.height * menuButtonWidth / menuPanelButtonSize.width;\r\n\r\n\tRectangle &inventoryButtonArea = VirtualGamepadState.menuPanel.inventoryButton.area;\r\n\tinventoryButtonArea.position.x = gnScreenWidth - rightMarginMenuButton3 * menuButtonWidth / menuPanelButtonSize.width;\r\n\tinventoryButtonArea.position.y = menuPanelTopMargin * menuButtonWidth / menuPanelButtonSize.width;\r\n\tinventoryButtonArea.size.width = menuButtonWidth;\r\n\tinventoryButtonArea.size.height = menuPanelButtonSize.height * menuButtonWidth / menuPanelButtonSize.width;\r\n\r\n\tRectangle &mapButtonArea = VirtualGamepadState.menuPanel.mapButton.area;\r\n\tmapButtonArea.position.x = gnScreenWidth - rightMarginMenuButton4 * menuButtonWidth / menuPanelButtonSize.width;\r\n\tmapButtonArea.position.y = menuPanelTopMargin * menuButtonWidth / menuPanelButtonSize.width;\r\n\tmapButtonArea.size.width = menuButtonWidth;\r\n\tmapButtonArea.size.height = menuPanelButtonSize.height * menuButtonWidth / menuPanelButtonSize.width;\r\n\r\n\tRectangle &menuPanelArea = VirtualGamepadState.menuPanel.area;\r\n\tmenuPanelArea.position.x = gnScreenWidth - 399 * menuButtonWidth / menuPanelButtonSize.width;\r\n\tmenuPanelArea.position.y = 0;\r\n\tmenuPanelArea.size.width = 399 * menuButtonWidth / menuPanelButtonSize.width;\r\n\tmenuPanelArea.size.height = 162 * menuButtonWidth / menuPanelButtonSize.width;\r\n\r\n\tVirtualDirectionPad &directionPad = VirtualGamepadState.directionPad;\r\n\tCircle &directionPadArea = directionPad.area;\r\n\tdirectionPadArea.position.x = inputMargin + directionPadSize / 2;\r\n\tdirectionPadArea.position.y = gnScreenHeight - inputMargin - directionPadSize / 2;\r\n\tdirectionPadArea.radius = directionPadSize / 2;\r\n\tdirectionPad.position = directionPadArea.position;\r\n\r\n\tconst int standButtonDiagonalOffset = directionPadArea.radius + padButtonSpacing / 2 + padButtonSize / 2;\r\n\tconst int standButtonOffset = roundToInt(standButtonDiagonalOffset / sqrt2);\r\n\tCircle &standButtonArea = VirtualGamepadState.standButton.area;\r\n\tstandButtonArea.position.x = directionPadArea.position.x - standButtonOffset;\r\n\tstandButtonArea.position.y = directionPadArea.position.y + standButtonOffset;\r\n\tstandButtonArea.radius = padButtonSize / 2;\r\n\r\n\tCircle &primaryActionButtonArea = VirtualGamepadState.primaryActionButton.area;\r\n\tprimaryActionButtonArea.position.x = padButtonRight;\r\n\tprimaryActionButtonArea.position.y = (padButtonTop + padButtonBottom) / 2;\r\n\tprimaryActionButtonArea.radius = padButtonSize / 2;\r\n\r\n\tCircle &secondaryActionButtonArea = VirtualGamepadState.secondaryActionButton.area;\r\n\tsecondaryActionButtonArea.position.x = (padButtonLeft + padButtonRight) / 2;\r\n\tsecondaryActionButtonArea.position.y = padButtonTop;\r\n\tsecondaryActionButtonArea.radius = padButtonSize / 2;\r\n\r\n\tCircle &spellActionButtonArea = VirtualGamepadState.spellActionButton.area;\r\n\tspellActionButtonArea.position.x = padButtonLeft;\r\n\tspellActionButtonArea.position.y = (padButtonTop + padButtonBottom) / 2;\r\n\tspellActionButtonArea.radius = padButtonSize / 2;\r\n\r\n\tCircle &cancelButtonArea = VirtualGamepadState.cancelButton.area;\r\n\tcancelButtonArea.position.x = (padButtonLeft + padButtonRight) / 2;\r\n\tcancelButtonArea.position.y = padButtonBottom;\r\n\tcancelButtonArea.radius = padButtonSize / 2;\r\n\r\n\tVirtualPadButton &healthButton = VirtualGamepadState.healthButton;\r\n\tCircle &healthButtonArea = healthButton.area;\r\n\thealthButtonArea.position.x = directionPad.area.position.x - (padButtonSize + padButtonSpacing) / 2;\r\n\thealthButtonArea.position.y = directionPad.area.position.y - (directionPadSize + padButtonSize + padButtonSpacing) / 2;\r\n\thealthButtonArea.radius = padButtonSize / 2;\r\n\thealthButton.isUsable = []() { return !CharFlag && !QuestLogIsOpen; };\r\n\r\n\tVirtualPadButton &manaButton = VirtualGamepadState.manaButton;\r\n\tCircle &manaButtonArea = manaButton.area;\r\n\tmanaButtonArea.position.x = directionPad.area.position.x + (padButtonSize + padButtonSpacing) / 2;\r\n\tmanaButtonArea.position.y = directionPad.area.position.y - (directionPadSize + padButtonSize + padButtonSpacing) / 2;\r\n\tmanaButtonArea.radius = padButtonSize / 2;\r\n\tmanaButton.isUsable = []() { return !CharFlag && !QuestLogIsOpen; };\r\n}\r\n\r\nvoid ActivateVirtualGamepad()\r\n{\r\n\tVirtualGamepadState.isActive = true;\r\n}\r\n\r\nvoid DeactivateVirtualGamepad()\r\n{\r\n\tVirtualGamepadState.Deactivate();\r\n\tDeactivateTouchEventHandlers();\r\n}\r\n\r\nvoid VirtualGamepad::Deactivate()\r\n{\r\n\tisActive = false;\r\n\r\n\tmenuPanel.Deactivate();\r\n\tdirectionPad.Deactivate();\r\n\tstandButton.Deactivate();\r\n\r\n\tprimaryActionButton.Deactivate();\r\n\tsecondaryActionButton.Deactivate();\r\n\tspellActionButton.Deactivate();\r\n\tcancelButton.Deactivate();\r\n\r\n\thealthButton.Deactivate();\r\n\tmanaButton.Deactivate();\r\n}\r\n\r\nvoid VirtualMenuPanel::Deactivate()\r\n{\r\n\tcharButton.Deactivate();\r\n\tquestsButton.Deactivate();\r\n\tinventoryButton.Deactivate();\r\n\tmapButton.Deactivate();\r\n}\r\n\r\nvoid VirtualDirectionPad::UpdatePosition(Point touchCoordinates)\r\n{\r\n\tposition = touchCoordinates;\r\n\r\n\tconst Displacement diff = position - area.position;\r\n\tif (diff == Displacement { 0, 0 }) {\r\n\t\tisUpPressed = false;\r\n\t\tisDownPressed = false;\r\n\t\tisLeftPressed = false;\r\n\t\tisRightPressed = false;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!area.contains(position)) {\r\n\t\tint x = diff.deltaX;\r\n\t\tint y = diff.deltaY;\r\n\t\tconst float dist = sqrtf(static_cast<float>(x * x + y * y));\r\n\t\tx = roundToInt(x * area.radius / dist);\r\n\t\ty = roundToInt(y * area.radius / dist);\r\n\t\tposition.x = area.position.x + x;\r\n\t\tposition.y = area.position.y + y;\r\n\t}\r\n\r\n\tconst float angle = atan2f(static_cast<float>(-diff.deltaY), static_cast<float>(diff.deltaX));\r\n\r\n\tisUpPressed = PointsUp(angle);\r\n\tisDownPressed = PointsDown(angle);\r\n\tisLeftPressed = PointsLeft(angle);\r\n\tisRightPressed = PointsRight(angle);\r\n}\r\n\r\nvoid VirtualDirectionPad::Deactivate()\r\n{\r\n\tposition = area.position;\r\n\tisUpPressed = false;\r\n\tisDownPressed = false;\r\n\tisLeftPressed = false;\r\n\tisRightPressed = false;\r\n}\r\n\r\nvoid VirtualButton::Deactivate()\r\n{\r\n\tisHeld = false;\r\n\tdidStateChange = false;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/touch/gamepad.h",
    "content": "#pragma once\r\n\r\n#include <functional>\r\n\r\n#include \"controls/controller_buttons.h\"\r\n#include \"engine/circle.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstruct VirtualDirectionPad {\r\n\tCircle area;\r\n\tPoint position;\r\n\tbool isUpPressed { false };\r\n\tbool isDownPressed { false };\r\n\tbool isLeftPressed { false };\r\n\tbool isRightPressed { false };\r\n\r\n\tVirtualDirectionPad()\r\n\t    : area({ { 0, 0 }, 0 })\r\n\t    , position({ 0, 0 })\r\n\t{\r\n\t}\r\n\r\n\tvoid UpdatePosition(Point touchCoordinates);\r\n\tvoid Deactivate();\r\n};\r\n\r\nstruct VirtualButton {\r\n\tbool isHeld { false };\r\n\tbool didStateChange { false };\r\n\tstd::function<bool()> isUsable;\r\n\r\n\tVirtualButton()\r\n\t    : isUsable([]() { return true; })\r\n\t{\r\n\t}\r\n\r\n\tvirtual bool contains(Point point) = 0;\r\n\tvoid Deactivate();\r\n};\r\n\r\nstruct VirtualMenuButton : VirtualButton {\r\n\tRectangle area;\r\n\r\n\tVirtualMenuButton()\r\n\t    : area({ { 0, 0 }, { 0, 0 } })\r\n\t{\r\n\t}\r\n\r\n\tbool contains(Point point) override\r\n\t{\r\n\t\treturn area.contains(point);\r\n\t}\r\n};\r\n\r\nstruct VirtualPadButton : VirtualButton {\r\n\tCircle area;\r\n\r\n\tVirtualPadButton()\r\n\t    : area({ { 0, 0 }, 0 })\r\n\t{\r\n\t}\r\n\r\n\tbool contains(Point point) override\r\n\t{\r\n\t\treturn area.contains(point);\r\n\t}\r\n};\r\n\r\nstruct VirtualMenuPanel {\r\n\tVirtualMenuButton charButton;\r\n\tVirtualMenuButton questsButton;\r\n\tVirtualMenuButton inventoryButton;\r\n\tVirtualMenuButton mapButton;\r\n\tRectangle area;\r\n\r\n\tVirtualMenuPanel()\r\n\t    : area({ { 0, 0 }, { 0, 0 } })\r\n\t{\r\n\t}\r\n\r\n\tvoid Deactivate();\r\n};\r\n\r\nstruct VirtualGamepad {\r\n\tVirtualMenuPanel menuPanel;\r\n\tVirtualDirectionPad directionPad;\r\n\tVirtualPadButton standButton;\r\n\r\n\tVirtualPadButton primaryActionButton;\r\n\tVirtualPadButton secondaryActionButton;\r\n\tVirtualPadButton spellActionButton;\r\n\tVirtualPadButton cancelButton;\r\n\r\n\tVirtualPadButton healthButton;\r\n\tVirtualPadButton manaButton;\r\n\r\n\tbool isActive { false };\r\n\r\n\tVirtualGamepad() = default;\r\n\r\n\tvoid Deactivate();\r\n};\r\n\r\nvoid InitializeVirtualGamepad();\r\nvoid ActivateVirtualGamepad();\r\nvoid DeactivateVirtualGamepad();\r\n\r\nextern VirtualGamepad VirtualGamepadState;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/touch/renderers.cpp",
    "content": "#include \"controls/touch/renderers.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"control/control.hpp\"\r\n#include \"cursor.h\"\r\n#include \"diablo.h\"\r\n#include \"doom.h\"\r\n#include \"engine/events.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"init.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"minitext.h\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"towners.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nVirtualGamepadRenderer Renderer(&VirtualGamepadState);\r\n\r\nVirtualGamepadButtonType GetAttackButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_ATTACKDOWN : GAMEPAD_ATTACK;\r\n}\r\n\r\nVirtualGamepadButtonType GetTalkButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_TALKDOWN : GAMEPAD_TALK;\r\n}\r\n\r\nVirtualGamepadButtonType GetItemButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_ITEMDOWN : GAMEPAD_ITEM;\r\n}\r\n\r\nVirtualGamepadButtonType GetObjectButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_OBJECTDOWN : GAMEPAD_OBJECT;\r\n}\r\n\r\nVirtualGamepadButtonType GetCastButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_CASTSPELLDOWN : GAMEPAD_CASTSPELL;\r\n}\r\n\r\nVirtualGamepadButtonType GetBackButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_BACKDOWN : GAMEPAD_BACK;\r\n}\r\n\r\nVirtualGamepadButtonType GetBlankButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_BLANKDOWN : GAMEPAD_BLANK;\r\n}\r\n\r\nVirtualGamepadButtonType GetPotionButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_POTIONDOWN : GAMEPAD_POTION;\r\n}\r\n\r\nVirtualGamepadButtonType GetApplyButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_APPLYDOWN : GAMEPAD_APPLY;\r\n}\r\n\r\nVirtualGamepadButtonType GetEquipButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_EQUIPDOWN : GAMEPAD_EQUIP;\r\n}\r\n\r\nVirtualGamepadButtonType GetDropButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_DROPDOWN : GAMEPAD_DROP;\r\n}\r\n\r\nVirtualGamepadButtonType GetStairsButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_STAIRSDOWN : GAMEPAD_STAIRS;\r\n}\r\n\r\nVirtualGamepadButtonType GetStandButtonType(bool isPressed)\r\n{\r\n\treturn isPressed ? GAMEPAD_STANDDOWN : GAMEPAD_STAND;\r\n}\r\n\r\nvoid LoadButtonArt(ButtonTexture *buttonArt)\r\n{\r\n\tconstexpr unsigned Sprites = 13;\r\n\tconstexpr unsigned Frames = 2;\r\n\tbuttonArt->surface.reset(LoadPNG(\"ui_art\\\\button.png\"));\r\n\tif (buttonArt->surface == nullptr)\r\n\t\treturn;\r\n\r\n\tbuttonArt->numSprites = Sprites;\r\n\tbuttonArt->numFrames = Frames;\r\n}\r\n\r\nvoid LoadPotionArt(ButtonTexture *potionArt)\r\n{\r\n\tconst item_cursor_graphic potionGraphics[] {\r\n\t\tICURS_POTION_OF_HEALING,\r\n\t\tICURS_POTION_OF_MANA,\r\n\t\tICURS_POTION_OF_REJUVENATION,\r\n\t\tICURS_POTION_OF_FULL_HEALING,\r\n\t\tICURS_POTION_OF_FULL_MANA,\r\n\t\tICURS_POTION_OF_FULL_REJUVENATION,\r\n\t\tICURS_ARENA_POTION,\r\n\t\tICURS_SCROLL_OF\r\n\t};\r\n\r\n\tconst int potionFrame = static_cast<int>(CURSOR_FIRSTITEM) + static_cast<int>(ICURS_POTION_OF_HEALING);\r\n\tconst Size potionSize = GetInvItemSize(potionFrame);\r\n\r\n\tauto surface = SDLWrap::CreateRGBSurfaceWithFormat(\r\n\t    /*flags=*/0,\r\n\t    /*width=*/potionSize.width,\r\n\t    /*height=*/potionSize.height * sizeof(potionGraphics),\r\n\t    /*depth=*/8,\r\n\t    SDL_PIXELFORMAT_INDEX8);\r\n\r\n\tauto palette = SDLWrap::AllocPalette();\r\n\tif (!SDLC_SetSurfaceAndPaletteColors(surface.get(), palette.get(), logical_palette.data(), 0, 256))\r\n\t\tErrSdl();\r\n\r\n#ifdef USE_SDL3\r\n\tconst Uint32 bgColor = SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), SDL_GetSurfacePalette(&*surface), logical_palette[1].r, logical_palette[1].g, logical_palette[1].b);\r\n\tif (!SDL_FillSurfaceRect(surface.get(), nullptr, bgColor)) ErrSdl();\r\n\tif (!SDL_SetSurfaceColorKey(surface.get(), true, bgColor)) ErrSdl();\r\n#else\r\n\tconst Uint32 bgColor = SDL_MapRGB(surface->format, logical_palette[1].r, logical_palette[1].g, logical_palette[1].b);\r\n\tif (SDL_FillRect(surface.get(), nullptr, bgColor) < 0)\r\n\t\tErrSdl();\r\n\tif (SDL_SetColorKey(surface.get(), SDL_TRUE, bgColor) < 0)\r\n\t\tErrSdl();\r\n#endif\r\n\r\n\tPoint position { 0, 0 };\r\n\tfor (const item_cursor_graphic graphic : potionGraphics) {\r\n\t\tconst int cursorID = static_cast<int>(CURSOR_FIRSTITEM) + graphic;\r\n\t\tposition.y += potionSize.height;\r\n\t\tClxDraw(Surface(surface.get()), position, GetInvItemSprite(cursorID));\r\n\t}\r\n\r\n\tpotionArt->numFrames = sizeof(potionGraphics);\r\n\r\n\tpotionArt->surface.reset(\r\n#ifdef USE_SDL3\r\n\t    SDL_ConvertSurface(surface.get(), SDL_PIXELFORMAT_ARGB8888)\r\n#else\r\n\t    SDL_ConvertSurfaceFormat(surface.get(), SDL_PIXELFORMAT_ARGB8888, 0)\r\n#endif\r\n\t);\r\n}\r\n\r\nbool InteractsWithCharButton(Point point)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tif (myPlayer._pStatPts == 0)\r\n\t\treturn false;\r\n\tfor (auto attribute : enum_values<CharacterAttribute>()) {\r\n\t\tif (myPlayer.GetBaseAttributeValue(attribute) >= myPlayer.GetMaximumAttributeValue(attribute))\r\n\t\t\tcontinue;\r\n\t\tauto buttonId = static_cast<size_t>(attribute);\r\n\t\tRectangle button = CharPanelButtonRect[buttonId];\r\n\t\tbutton.position = GetPanelPosition(UiPanels::Character, button.position);\r\n\t\tif (button.contains(point)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n} // namespace\r\n\r\nSize ButtonTexture::size() const\r\n{\r\n\tint w, h;\r\n\tif (surface != nullptr) {\r\n\t\tw = surface->w;\r\n\t\th = surface->h;\r\n\t} else {\r\n#ifdef USE_SDL3\r\n\t\tfloat fw, fh;\r\n\t\tSDL_GetTextureSize(texture.get(), &fw, &fh);\r\n\t\tw = fw;\r\n\t\th = fh;\r\n#else\r\n\t\tSDL_QueryTexture(texture.get(), /*format=*/nullptr, /*access=*/nullptr, &w, &h);\r\n#endif\r\n\t}\r\n\tw /= numSprites;\r\n\th /= numFrames;\r\n\treturn Size { w, h };\r\n}\r\n\r\nvoid RenderVirtualGamepad(SDL_Renderer *renderer)\r\n{\r\n\tif (!gbRunGame)\r\n\t\treturn;\r\n\r\n\tconst RenderFunction renderFunction = [renderer](const ButtonTexture &art, SDL_Rect *src, SDL_Rect *dst) {\r\n\t\tif (art.texture == nullptr)\r\n\t\t\treturn;\r\n\r\n#ifdef USE_SDL3\r\n\t\tSDL_FRect fsrc, fdst;\r\n\t\tSDL_RectToFRect(src, &fsrc);\r\n\t\tSDL_RectToFRect(dst, &fdst);\r\n\t\tif (!SDL_RenderTexture(renderer, art.texture.get(), &fsrc, &fdst)) ErrSdl();\r\n#else\r\n\t\tif (SDL_RenderCopy(renderer, art.texture.get(), src, dst) <= -1) ErrSdl();\r\n#endif\r\n\t};\r\n\r\n\tRenderer.Render(renderFunction);\r\n}\r\n\r\nvoid RenderVirtualGamepad(SDL_Surface *surface)\r\n{\r\n\tif (!gbRunGame)\r\n\t\treturn;\r\n\r\n\tconst RenderFunction renderFunction = [surface](const ButtonTexture &art, SDL_Rect *src, SDL_Rect *dst) {\r\n\t\tif (art.surface == nullptr)\r\n\t\t\treturn;\r\n\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_BlitSurfaceScaled(art.surface.get(), src, surface, dst, SDL_SCALEMODE_LINEAR))\r\n#else\r\n\t\tif (SDL_BlitScaled(art.surface.get(), src, surface, dst) <= -1)\r\n#endif\r\n\t\t\tErrSdl();\r\n\t};\r\n\r\n\tRenderer.Render(renderFunction);\r\n}\r\n\r\nvoid VirtualGamepadRenderer::LoadArt()\r\n{\r\n\tmenuPanelRenderer.LoadArt();\r\n\tdirectionPadRenderer.LoadArt();\r\n\tLoadButtonArt(&buttonArt);\r\n\tLoadPotionArt(&potionArt);\r\n}\r\n\r\nvoid VirtualMenuPanelRenderer::LoadArt()\r\n{\r\n\tmenuArt.surface.reset(LoadPNG(\"ui_art\\\\menu.png\"));\r\n\tmenuArtLevelUp.surface.reset(LoadPNG(\"ui_art\\\\menu-levelup.png\"));\r\n}\r\n\r\nvoid VirtualDirectionPadRenderer::LoadArt()\r\n{\r\n\tpadArt.surface.reset(LoadPNG(\"ui_art\\\\directions.png\"));\r\n\tknobArt.surface.reset(LoadPNG(\"ui_art\\\\directions2.png\"));\r\n}\r\n\r\nvoid VirtualGamepadRenderer::Render(RenderFunction renderFunction)\r\n{\r\n\tif (CurrentEventHandler == DisableInputEventHandler)\r\n\t\treturn;\r\n\r\n\tprimaryActionButtonRenderer.Render(renderFunction, buttonArt);\r\n\tsecondaryActionButtonRenderer.Render(renderFunction, buttonArt);\r\n\tspellActionButtonRenderer.Render(renderFunction, buttonArt);\r\n\tcancelButtonRenderer.Render(renderFunction, buttonArt);\r\n\thealthButtonRenderer.Render(renderFunction, buttonArt);\r\n\tmanaButtonRenderer.Render(renderFunction, buttonArt);\r\n\r\n\thealthButtonRenderer.RenderPotion(renderFunction, potionArt);\r\n\tmanaButtonRenderer.RenderPotion(renderFunction, potionArt);\r\n\r\n\tif (leveltype != DTYPE_TOWN)\r\n\t\tstandButtonRenderer.Render(renderFunction, buttonArt);\r\n\tdirectionPadRenderer.Render(renderFunction);\r\n\tmenuPanelRenderer.Render(renderFunction);\r\n}\r\n\r\nvoid VirtualMenuPanelRenderer::Render(RenderFunction renderFunction)\r\n{\r\n\tconst int x = virtualMenuPanel->area.position.x;\r\n\tconst int y = virtualMenuPanel->area.position.y;\r\n\tconst int width = virtualMenuPanel->area.size.width;\r\n\tconst int height = virtualMenuPanel->area.size.height;\r\n\tSDL_Rect rect { x, y, width, height };\r\n\trenderFunction(MyPlayer->_pStatPts == 0 ? menuArt : menuArtLevelUp, nullptr, &rect);\r\n}\r\n\r\nvoid VirtualDirectionPadRenderer::Render(RenderFunction renderFunction)\r\n{\r\n\tRenderPad(renderFunction);\r\n\tRenderKnob(renderFunction);\r\n}\r\n\r\nvoid VirtualDirectionPadRenderer::RenderPad(RenderFunction renderFunction)\r\n{\r\n\tauto center = virtualDirectionPad->area.position;\r\n\tauto radius = virtualDirectionPad->area.radius;\r\n\tconst int diameter = 2 * radius;\r\n\r\n\tconst int x = center.x - radius;\r\n\tconst int y = center.y - radius;\r\n\tconst int width = diameter;\r\n\tconst int height = diameter;\r\n\tSDL_Rect rect { x, y, width, height };\r\n\trenderFunction(padArt, nullptr, &rect);\r\n}\r\n\r\nvoid VirtualDirectionPadRenderer::RenderKnob(RenderFunction renderFunction)\r\n{\r\n\tauto center = virtualDirectionPad->position;\r\n\tauto radius = virtualDirectionPad->area.radius / 3;\r\n\tconst int diameter = 2 * radius;\r\n\r\n\tconst int x = center.x - radius;\r\n\tconst int y = center.y - radius;\r\n\tconst int width = diameter;\r\n\tconst int height = diameter;\r\n\tSDL_Rect rect { x, y, width, height };\r\n\trenderFunction(knobArt, nullptr, &rect);\r\n}\r\n\r\nvoid VirtualPadButtonRenderer::Render(RenderFunction renderFunction, const ButtonTexture &buttonArt)\r\n{\r\n\tif (!virtualPadButton->isUsable())\r\n\t\treturn;\r\n\r\n\tconst VirtualGamepadButtonType buttonType = GetButtonType();\r\n\tconst Size size = buttonArt.size();\r\n\tconst auto index = static_cast<unsigned>(buttonType);\r\n\tconst int xOffset = size.width * (index / buttonArt.numFrames);\r\n\tconst int yOffset = size.height * (index % buttonArt.numFrames);\r\n\r\n\tauto center = virtualPadButton->area.position;\r\n\tauto radius = virtualPadButton->area.radius;\r\n\tconst int diameter = 2 * radius;\r\n\r\n\tconst int x = center.x - radius;\r\n\tconst int y = center.y - radius;\r\n\tconst int width = diameter;\r\n\tconst int height = diameter;\r\n\r\n\tSDL_Rect src = MakeSdlRect(xOffset, yOffset, size.width, size.height);\r\n\tSDL_Rect dst = MakeSdlRect(x, y, width, height);\r\n\trenderFunction(buttonArt, &src, &dst);\r\n}\r\n\r\nvoid PotionButtonRenderer::RenderPotion(RenderFunction renderFunction, const ButtonTexture &potionArt)\r\n{\r\n\tif (!virtualPadButton->isUsable())\r\n\t\treturn;\r\n\r\n\tstd::optional<VirtualGamepadPotionType> potionType = GetPotionType();\r\n\tif (potionType == std::nullopt)\r\n\t\treturn;\r\n\r\n\tconst int frame = *potionType;\r\n\tconst Size size = potionArt.size();\r\n\tconst int offset = size.height * frame;\r\n\r\n\tauto center = virtualPadButton->area.position;\r\n\tauto radius = virtualPadButton->area.radius * 8 / 10;\r\n\tconst int diameter = 2 * radius;\r\n\r\n\tconst int x = center.x - radius;\r\n\tconst int y = center.y - radius;\r\n\tconst int width = diameter;\r\n\tconst int height = diameter;\r\n\r\n\tSDL_Rect src = MakeSdlRect(0, offset, size.width, size.height);\r\n\tSDL_Rect dst = MakeSdlRect(x, y, width, height);\r\n\trenderFunction(potionArt, &src, &dst);\r\n}\r\n\r\nstd::optional<VirtualGamepadPotionType> PotionButtonRenderer::GetPotionType()\r\n{\r\n\tfor (const Item &item : InspectPlayer->SpdList) {\r\n\t\tif (item.isEmpty()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (potionType == BeltItemType::Healing) {\r\n\t\t\tif (item._iMiscId == IMISC_HEAL)\r\n\t\t\t\treturn GAMEPAD_HEALING;\r\n\t\t\tif (item._iMiscId == IMISC_FULLHEAL)\r\n\t\t\t\treturn GAMEPAD_FULL_HEALING;\r\n\t\t\tif (item.isScrollOf(SpellID::Healing))\r\n\t\t\t\treturn GAMEPAD_SCROLL_OF_HEALING;\r\n\t\t}\r\n\r\n\t\tif (potionType == BeltItemType::Mana) {\r\n\t\t\tif (item._iMiscId == IMISC_MANA)\r\n\t\t\t\treturn GAMEPAD_MANA;\r\n\t\t\tif (item._iMiscId == IMISC_FULLMANA)\r\n\t\t\t\treturn GAMEPAD_FULL_MANA;\r\n\t\t}\r\n\r\n\t\tif (item._iMiscId == IMISC_REJUV)\r\n\t\t\treturn GAMEPAD_REJUVENATION;\r\n\t\tif (item._iMiscId == IMISC_FULLREJUV)\r\n\t\t\treturn GAMEPAD_FULL_REJUVENATION;\r\n\t\tif (item._iMiscId == IMISC_ARENAPOT && MyPlayer->isOnArenaLevel())\r\n\t\t\treturn GAMEPAD_ARENA_POTION;\r\n\t}\r\n\r\n\treturn std::nullopt;\r\n}\r\n\r\nVirtualGamepadButtonType StandButtonRenderer::GetButtonType()\r\n{\r\n\treturn GetStandButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nVirtualGamepadButtonType PrimaryActionButtonRenderer::GetButtonType()\r\n{\r\n\t// NEED: Confirm surface\r\n\tif (qtextflag)\r\n\t\treturn GetTalkButtonType(virtualPadButton->isHeld);\r\n\tif (CharFlag && InteractsWithCharButton(MousePosition))\r\n\t\treturn GetApplyButtonType(virtualPadButton->isHeld);\r\n\tif (invflag)\r\n\t\treturn GetInventoryButtonType();\r\n\tif (leveltype == DTYPE_TOWN)\r\n\t\treturn GetTownButtonType();\r\n\treturn GetDungeonButtonType();\r\n}\r\n\r\nVirtualGamepadButtonType PrimaryActionButtonRenderer::GetTownButtonType()\r\n{\r\n\tif (IsPlayerInStore() || pcursmonst != -1)\r\n\t\treturn GetTalkButtonType(virtualPadButton->isHeld);\r\n\treturn GetBlankButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nVirtualGamepadButtonType PrimaryActionButtonRenderer::GetDungeonButtonType()\r\n{\r\n\tif (pcursmonst != -1) {\r\n\t\tconst Monster &monster = Monsters[pcursmonst];\r\n\t\tif (M_Talker(monster) || monster.talkMsg != TEXT_NONE)\r\n\t\t\treturn GetTalkButtonType(virtualPadButton->isHeld);\r\n\t}\r\n\treturn GetAttackButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nVirtualGamepadButtonType PrimaryActionButtonRenderer::GetInventoryButtonType()\r\n{\r\n\tif (pcursinvitem != -1 || pcursstashitem != StashStruct::EmptyCell || pcurs > CURSOR_HAND)\r\n\t\treturn GetItemButtonType(virtualPadButton->isHeld);\r\n\treturn GetBlankButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nextern int pcurstrig;\r\nextern Missile *pcursmissile;\r\nextern quest_id pcursquest;\r\n\r\nVirtualGamepadButtonType SecondaryActionButtonRenderer::GetButtonType()\r\n{\r\n\tif (pcursmissile != nullptr || pcurstrig != -1 || pcursquest != Q_INVALID) {\r\n\t\treturn GetStairsButtonType(virtualPadButton->isHeld);\r\n\t}\r\n\tif (InGameMenu() || QuestLogIsOpen || SpellbookFlag)\r\n\t\treturn GetBlankButtonType(virtualPadButton->isHeld);\r\n\tif (ObjectUnderCursor != nullptr)\r\n\t\treturn GetObjectButtonType(virtualPadButton->isHeld);\r\n\tif (pcursitem != -1)\r\n\t\treturn GetItemButtonType(virtualPadButton->isHeld);\r\n\tif (invflag) {\r\n\t\tif (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM)\r\n\t\t\treturn GetApplyButtonType(virtualPadButton->isHeld);\r\n\r\n\t\tif (pcursinvitem != -1) {\r\n\t\t\tconst Item &item = GetInventoryItem(*MyPlayer, pcursinvitem);\r\n\t\t\tif (!item.isScroll() || !TargetsMonster(item._iSpell)) {\r\n\t\t\t\tif (!item.isEquipment()) {\r\n\t\t\t\t\treturn GetApplyButtonType(virtualPadButton->isHeld);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn GetBlankButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nVirtualGamepadButtonType SpellActionButtonRenderer::GetButtonType()\r\n{\r\n\tif (!MyPlayer->HoldItem.isEmpty())\r\n\t\treturn GetDropButtonType(virtualPadButton->isHeld);\r\n\r\n\tif (invflag && pcursinvitem != -1 && pcurs == CURSOR_HAND) {\r\n\t\treturn GetEquipButtonType(virtualPadButton->isHeld);\r\n\t}\r\n\r\n\tif (!invflag && !InGameMenu() && !QuestLogIsOpen && !SpellbookFlag)\r\n\t\treturn GetCastButtonType(virtualPadButton->isHeld);\r\n\treturn GetBlankButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nVirtualGamepadButtonType CancelButtonRenderer::GetButtonType()\r\n{\r\n\tif (InGameMenu())\r\n\t\treturn GetBackButtonType(virtualPadButton->isHeld);\r\n\tif (DoomFlag || invflag || SpellbookFlag || QuestLogIsOpen || CharFlag)\r\n\t\treturn GetBackButtonType(virtualPadButton->isHeld);\r\n\treturn GetBlankButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nVirtualGamepadButtonType PotionButtonRenderer::GetButtonType()\r\n{\r\n\treturn GetPotionButtonType(virtualPadButton->isHeld);\r\n}\r\n\r\nvoid VirtualGamepadRenderer::UnloadArt()\r\n{\r\n\tmenuPanelRenderer.UnloadArt();\r\n\tdirectionPadRenderer.UnloadArt();\r\n\tbuttonArt.clearSurface();\r\n\tpotionArt.clearSurface();\r\n}\r\n\r\nvoid VirtualMenuPanelRenderer::UnloadArt()\r\n{\r\n\tmenuArt.clearSurface();\r\n\tmenuArtLevelUp.clearSurface();\r\n}\r\n\r\nvoid VirtualDirectionPadRenderer::UnloadArt()\r\n{\r\n\tpadArt.clearSurface();\r\n\tknobArt.clearSurface();\r\n}\r\n\r\nvoid InitVirtualGamepadGFX()\r\n{\r\n\tRenderer.LoadArt();\r\n}\r\n\r\nvoid FreeVirtualGamepadGFX()\r\n{\r\n\tRenderer.UnloadArt();\r\n}\r\n\r\nvoid VirtualGamepadRenderer::createTextures(SDL_Renderer &renderer)\r\n{\r\n\tmenuPanelRenderer.createTextures(renderer);\r\n\tdirectionPadRenderer.createTextures(renderer);\r\n\tif (buttonArt.surface != nullptr) {\r\n\t\tbuttonArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, buttonArt.surface.get()));\r\n\t\tbuttonArt.surface = nullptr;\r\n\t}\r\n\tif (potionArt.surface != nullptr) {\r\n\t\tpotionArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, potionArt.surface.get()));\r\n\t\tpotionArt.surface = nullptr;\r\n\t}\r\n}\r\n\r\nvoid VirtualMenuPanelRenderer::createTextures(SDL_Renderer &renderer)\r\n{\r\n\tif (menuArt.surface != nullptr) {\r\n\t\tmenuArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, menuArt.surface.get()));\r\n\t\tmenuArt.surface = nullptr;\r\n\t}\r\n\tif (menuArtLevelUp.surface != nullptr) {\r\n\t\tmenuArtLevelUp.texture.reset(SDL_CreateTextureFromSurface(&renderer, menuArtLevelUp.surface.get()));\r\n\t\tmenuArtLevelUp.surface = nullptr;\r\n\t}\r\n}\r\n\r\nvoid VirtualDirectionPadRenderer::createTextures(SDL_Renderer &renderer)\r\n{\r\n\tif (padArt.surface != nullptr) {\r\n\t\tpadArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, padArt.surface.get()));\r\n\t\tpadArt.surface = nullptr;\r\n\t}\r\n\tif (knobArt.surface != nullptr) {\r\n\t\tknobArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, knobArt.surface.get()));\r\n\t\tknobArt.surface = nullptr;\r\n\t}\r\n}\r\n\r\nvoid VirtualGamepadRenderer::destroyTextures()\r\n{\r\n\tmenuPanelRenderer.destroyTextures();\r\n\tdirectionPadRenderer.destroyTextures();\r\n\tbuttonArt.destroyTexture();\r\n\tpotionArt.destroyTexture();\r\n}\r\n\r\nvoid VirtualMenuPanelRenderer::destroyTextures()\r\n{\r\n\tmenuArt.destroyTexture();\r\n\tmenuArtLevelUp.destroyTexture();\r\n}\r\n\r\nvoid VirtualDirectionPadRenderer::destroyTextures()\r\n{\r\n\tpadArt.destroyTexture();\r\n\tknobArt.destroyTexture();\r\n}\r\n\r\nvoid InitVirtualGamepadTextures(SDL_Renderer &renderer)\r\n{\r\n\tRenderer.createTextures(renderer);\r\n}\r\n\r\nvoid FreeVirtualGamepadTextures()\r\n{\r\n\tRenderer.destroyTextures();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/controls/touch/renderers.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_render.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/plrctrls.h\"\r\n#include \"controls/touch/gamepad.h\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/png.h\"\r\n#include \"utils/sdl_ptrs.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum VirtualGamepadButtonType : uint8_t {\r\n\tGAMEPAD_ATTACK,\r\n\tGAMEPAD_ATTACKDOWN,\r\n\tGAMEPAD_TALK,\r\n\tGAMEPAD_TALKDOWN,\r\n\tGAMEPAD_ITEM,\r\n\tGAMEPAD_ITEMDOWN,\r\n\tGAMEPAD_OBJECT,\r\n\tGAMEPAD_OBJECTDOWN,\r\n\tGAMEPAD_CASTSPELL,\r\n\tGAMEPAD_CASTSPELLDOWN,\r\n\tGAMEPAD_BACK,\r\n\tGAMEPAD_BACKDOWN,\r\n\tGAMEPAD_BLANK,\r\n\tGAMEPAD_BLANKDOWN,\r\n\tGAMEPAD_APPLY,\r\n\tGAMEPAD_APPLYDOWN,\r\n\tGAMEPAD_EQUIP,\r\n\tGAMEPAD_EQUIPDOWN,\r\n\tGAMEPAD_DROP,\r\n\tGAMEPAD_DROPDOWN,\r\n\tGAMEPAD_STAIRS,\r\n\tGAMEPAD_STAIRSDOWN,\r\n\tGAMEPAD_STAND,\r\n\tGAMEPAD_STANDDOWN,\r\n\tGAMEPAD_POTION,\r\n\tGAMEPAD_POTIONDOWN,\r\n};\r\n\r\nenum VirtualGamepadPotionType : uint8_t {\r\n\tGAMEPAD_HEALING,\r\n\tGAMEPAD_MANA,\r\n\tGAMEPAD_REJUVENATION,\r\n\tGAMEPAD_FULL_HEALING,\r\n\tGAMEPAD_FULL_MANA,\r\n\tGAMEPAD_FULL_REJUVENATION,\r\n\tGAMEPAD_ARENA_POTION,\r\n\tGAMEPAD_SCROLL_OF_HEALING,\r\n};\r\n\r\nstruct ButtonTexture {\r\n\tSDLSurfaceUniquePtr surface;\r\n\tSDLTextureUniquePtr texture;\r\n\tunsigned numSprites = 1;\r\n\tunsigned numFrames = 1;\r\n\r\n\tSize size() const;\r\n\r\n\tvoid clearSurface()\r\n\t{\r\n\t\tsurface = nullptr;\r\n\t\tnumFrames = 1;\r\n\t}\r\n\r\n\tvoid destroyTexture()\r\n\t{\r\n\t\ttexture = nullptr;\r\n\t}\r\n};\r\n\r\ntypedef std::function<void(const ButtonTexture &art, SDL_Rect *src, SDL_Rect *dst)> RenderFunction;\r\n\r\nclass VirtualMenuPanelRenderer {\r\npublic:\r\n\tVirtualMenuPanelRenderer(VirtualMenuPanel *virtualMenuPanel)\r\n\t    : virtualMenuPanel(virtualMenuPanel)\r\n\t{\r\n\t}\r\n\r\n\tvoid LoadArt();\r\n\r\n\t/**\r\n\t * @brief Converts surfaces to textures.\r\n\t *\r\n\t * Must be called from the main thread.\r\n\t *\r\n\t * Per https://wiki.libsdl.org/SDL3/CategoryRender:\r\n\t * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986\r\n\t */\r\n\tvoid createTextures(SDL_Renderer &renderer);\r\n\r\n\t/**\r\n\t * @brief Must be called from the main thread.\r\n\t */\r\n\tvoid destroyTextures();\r\n\r\n\tvoid Render(RenderFunction renderFunction);\r\n\tvoid UnloadArt();\r\n\r\nprivate:\r\n\tVirtualMenuPanel *virtualMenuPanel;\r\n\tButtonTexture menuArt;\r\n\tButtonTexture menuArtLevelUp;\r\n};\r\n\r\nclass VirtualDirectionPadRenderer {\r\npublic:\r\n\tVirtualDirectionPadRenderer(VirtualDirectionPad *virtualDirectionPad)\r\n\t    : virtualDirectionPad(virtualDirectionPad)\r\n\t{\r\n\t}\r\n\r\n\tvoid LoadArt();\r\n\r\n\t/**\r\n\t * @brief Converts surfaces to textures.\r\n\t *\r\n\t * Must be called from the main thread.\r\n\t *\r\n\t * Per https://wiki.libsdl.org/SDL3/CategoryRender:\r\n\t * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986\r\n\t */\r\n\tvoid createTextures(SDL_Renderer &renderer);\r\n\r\n\t/**\r\n\t * @brief Must be called from the main thread.\r\n\t */\r\n\tvoid destroyTextures();\r\n\r\n\tvoid Render(RenderFunction renderFunction);\r\n\tvoid UnloadArt();\r\n\r\nprivate:\r\n\tVirtualDirectionPad *virtualDirectionPad;\r\n\tButtonTexture padArt;\r\n\tButtonTexture knobArt;\r\n\r\n\tvoid RenderPad(RenderFunction renderFunction);\r\n\tvoid RenderKnob(RenderFunction renderFunction);\r\n};\r\n\r\nclass VirtualPadButtonRenderer {\r\npublic:\r\n\tVirtualPadButtonRenderer(VirtualPadButton *virtualPadButton)\r\n\t    : virtualPadButton(virtualPadButton)\r\n\t{\r\n\t}\r\n\r\n\tvoid Render(RenderFunction renderFunction, const ButtonTexture &buttonArt);\r\n\r\nprotected:\r\n\tVirtualPadButton *virtualPadButton;\r\n\r\n\tvirtual VirtualGamepadButtonType GetButtonType() = 0;\r\n};\r\n\r\nclass StandButtonRenderer : public VirtualPadButtonRenderer {\r\npublic:\r\n\tStandButtonRenderer(VirtualPadButton *standButton)\r\n\t    : VirtualPadButtonRenderer(standButton)\r\n\t{\r\n\t}\r\n\r\nprivate:\r\n\tVirtualGamepadButtonType GetButtonType();\r\n};\r\n\r\nclass PrimaryActionButtonRenderer : public VirtualPadButtonRenderer {\r\npublic:\r\n\tPrimaryActionButtonRenderer(VirtualPadButton *primaryActionButton)\r\n\t    : VirtualPadButtonRenderer(primaryActionButton)\r\n\t{\r\n\t}\r\n\r\nprivate:\r\n\tVirtualGamepadButtonType GetButtonType();\r\n\tVirtualGamepadButtonType GetTownButtonType();\r\n\tVirtualGamepadButtonType GetDungeonButtonType();\r\n\tVirtualGamepadButtonType GetInventoryButtonType();\r\n};\r\n\r\nclass SecondaryActionButtonRenderer : public VirtualPadButtonRenderer {\r\npublic:\r\n\tSecondaryActionButtonRenderer(VirtualPadButton *secondaryActionButton)\r\n\t    : VirtualPadButtonRenderer(secondaryActionButton)\r\n\t{\r\n\t}\r\n\r\nprivate:\r\n\tVirtualGamepadButtonType GetButtonType();\r\n};\r\n\r\nclass SpellActionButtonRenderer : public VirtualPadButtonRenderer {\r\npublic:\r\n\tSpellActionButtonRenderer(VirtualPadButton *spellActionButton)\r\n\t    : VirtualPadButtonRenderer(spellActionButton)\r\n\t{\r\n\t}\r\n\r\nprivate:\r\n\tVirtualGamepadButtonType GetButtonType();\r\n};\r\n\r\nclass CancelButtonRenderer : public VirtualPadButtonRenderer {\r\npublic:\r\n\tCancelButtonRenderer(VirtualPadButton *cancelButton)\r\n\t    : VirtualPadButtonRenderer(cancelButton)\r\n\t{\r\n\t}\r\n\r\nprivate:\r\n\tVirtualGamepadButtonType GetButtonType();\r\n};\r\n\r\nclass PotionButtonRenderer : public VirtualPadButtonRenderer {\r\npublic:\r\n\tPotionButtonRenderer(VirtualPadButton *potionButton, BeltItemType potionType)\r\n\t    : VirtualPadButtonRenderer(potionButton)\r\n\t    , potionType(potionType)\r\n\t{\r\n\t}\r\n\r\n\tvoid RenderPotion(RenderFunction renderFunction, const ButtonTexture &potionArt);\r\n\r\nprivate:\r\n\tBeltItemType potionType;\r\n\r\n\tVirtualGamepadButtonType GetButtonType();\r\n\tstd::optional<VirtualGamepadPotionType> GetPotionType();\r\n};\r\n\r\nclass VirtualGamepadRenderer {\r\npublic:\r\n\tVirtualGamepadRenderer(VirtualGamepad *virtualGamepad)\r\n\t    : menuPanelRenderer(&virtualGamepad->menuPanel)\r\n\t    , directionPadRenderer(&virtualGamepad->directionPad)\r\n\t    , standButtonRenderer(&virtualGamepad->standButton)\r\n\t    , primaryActionButtonRenderer(&virtualGamepad->primaryActionButton)\r\n\t    , secondaryActionButtonRenderer(&virtualGamepad->secondaryActionButton)\r\n\t    , spellActionButtonRenderer(&virtualGamepad->spellActionButton)\r\n\t    , cancelButtonRenderer(&virtualGamepad->cancelButton)\r\n\t    , healthButtonRenderer(&virtualGamepad->healthButton, BeltItemType::Healing)\r\n\t    , manaButtonRenderer(&virtualGamepad->manaButton, BeltItemType::Mana)\r\n\t{\r\n\t}\r\n\r\n\tvoid LoadArt();\r\n\r\n\t/**\r\n\t * @brief Converts surfaces to textures.\r\n\t *\r\n\t * Must be called from the main thread.\r\n\t *\r\n\t * Per https://wiki.libsdl.org/SDL3/CategoryRender:\r\n\t * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986\r\n\t */\r\n\tvoid createTextures(SDL_Renderer &renderer);\r\n\r\n\t/**\r\n\t * @brief Must be called from the main thread.\r\n\t */\r\n\tvoid destroyTextures();\r\n\r\n\tvoid Render(RenderFunction renderFunction);\r\n\tvoid UnloadArt();\r\n\r\nprivate:\r\n\tVirtualMenuPanelRenderer menuPanelRenderer;\r\n\tVirtualDirectionPadRenderer directionPadRenderer;\r\n\tStandButtonRenderer standButtonRenderer;\r\n\r\n\tPrimaryActionButtonRenderer primaryActionButtonRenderer;\r\n\tSecondaryActionButtonRenderer secondaryActionButtonRenderer;\r\n\tSpellActionButtonRenderer spellActionButtonRenderer;\r\n\tCancelButtonRenderer cancelButtonRenderer;\r\n\r\n\tPotionButtonRenderer healthButtonRenderer;\r\n\tPotionButtonRenderer manaButtonRenderer;\r\n\r\n\tButtonTexture buttonArt;\r\n\tButtonTexture potionArt;\r\n};\r\n\r\nvoid InitVirtualGamepadGFX();\r\n\r\n/**\r\n * @brief Creates textures for the virtual gamepad.\r\n *\r\n * Must be called after `InitVirtualGamepadGFX`.\r\n * Must be called from the main thread.\r\n *\r\n * Per https://wiki.libsdl.org/SDL3/CategoryRender:\r\n * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986\r\n */\r\nvoid InitVirtualGamepadTextures(SDL_Renderer &renderer);\r\n\r\n/** @brief Must be called from the main thread. */\r\nvoid FreeVirtualGamepadTextures();\r\n\r\nvoid RenderVirtualGamepad(SDL_Renderer *renderer);\r\nvoid RenderVirtualGamepad(SDL_Surface *surface);\r\nvoid FreeVirtualGamepadGFX();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/cpp.hint",
    "content": "// Hint files help the Visual Studio IDE interpret Visual C++ identifiers\r\n// such as names of functions and macros.\r\n// For more information see https://go.microsoft.com/fwlink/?linkid=865984\r\n#define DVL_ALWAYS_INLINE\r\n#define DVL_ATTRIBUTE_HOT\r\n#define DVL_API_FOR_TEST\r\n#define DVL_REINITIALIZES\r\n"
  },
  {
    "path": "Source/crawl.cpp",
    "content": "#include \"crawl.hpp\"\r\n\r\n#include <type_traits>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/displacement.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool DoCrawl(unsigned radius, tl::function_ref<bool(Displacement)> function)\r\n{\r\n\treturn DoCrawl(radius, radius, function);\r\n}\r\n\r\nbool DoCrawl(unsigned minRadius, unsigned maxRadius, tl::function_ref<bool(Displacement)> function)\r\n{\r\n\tfor (int r = static_cast<int>(minRadius); r <= static_cast<int>(maxRadius); ++r) {\r\n\t\tif (!function(Displacement { 0, r })) return false;\r\n\t\tif (r == 0) continue;\r\n\t\tif (!function(Displacement { 0, -r })) return false;\r\n\t\tfor (int x = 1; x < r; ++x) {\r\n\t\t\tif (!function(Displacement { -x, r })) return false;\r\n\t\t\tif (!function(Displacement { x, r })) return false;\r\n\t\t\tif (!function(Displacement { -x, -r })) return false;\r\n\t\t\tif (!function(Displacement { x, -r })) return false;\r\n\t\t}\r\n\t\tif (r > 1) {\r\n\t\t\tconst int d = r - 1;\r\n\t\t\tif (!function(Displacement { -d, d })) return false;\r\n\t\t\tif (!function(Displacement { d, d })) return false;\r\n\t\t\tif (!function(Displacement { -d, -d })) return false;\r\n\t\t\tif (!function(Displacement { d, -d })) return false;\r\n\t\t}\r\n\t\tif (!function(Displacement { -r, 0 })) return false;\r\n\t\tif (!function(Displacement { r, 0 })) return false;\r\n\t\tfor (int y = 1; y < r; ++y) {\r\n\t\t\tif (!function(Displacement { -r, y })) return false;\r\n\t\t\tif (!function(Displacement { r, y })) return false;\r\n\t\t\tif (!function(Displacement { -r, -y })) return false;\r\n\t\t\tif (!function(Displacement { r, -y })) return false;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/crawl.hpp",
    "content": "#include <type_traits>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/displacement.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * CrawlTable specifies X- and Y-coordinate deltas from a missile target coordinate.\r\n *\r\n * n=4\r\n *\r\n *    y\r\n *    ^\r\n *    |  1\r\n *    | 3#4\r\n *    |  2\r\n *    +-----> x\r\n *\r\n * n=16\r\n *\r\n *    y\r\n *    ^\r\n *    |  314\r\n *    | B7 8C\r\n *    | F # G\r\n *    | D9 AE\r\n *    |  526\r\n *    +-------> x\r\n */\r\n\r\nbool DoCrawl(unsigned radius, tl::function_ref<bool(Displacement)> function);\r\nbool DoCrawl(unsigned minRadius, unsigned maxRadius, tl::function_ref<bool(Displacement)> function);\r\n\r\ntemplate <typename F>\r\nauto Crawl(unsigned radius, F function) -> std::invoke_result_t<decltype(function), Displacement>\r\n{\r\n\tstd::invoke_result_t<decltype(function), Displacement> result;\r\n\tDoCrawl(radius, [&result, &function](Displacement displacement) -> bool {\r\n\t\tresult = function(displacement);\r\n\t\treturn !result;\r\n\t});\r\n\treturn result;\r\n}\r\n\r\ntemplate <typename F>\r\nauto Crawl(unsigned minRadius, unsigned maxRadius, F function) -> std::invoke_result_t<decltype(function), Displacement>\r\n{\r\n\tstd::invoke_result_t<decltype(function), Displacement> result;\r\n\tDoCrawl(minRadius, maxRadius, [&result, &function](Displacement displacement) -> bool {\r\n\t\tresult = function(displacement);\r\n\t\treturn !result;\r\n\t});\r\n\treturn result;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/cursor.cpp",
    "content": "/**\r\n * @file cursor.cpp\r\n *\r\n * Implementation of cursor tracking functionality.\r\n */\r\n#include \"cursor.h\"\r\n\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <limits>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"doom.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/trn.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"missiles.h\"\r\n#include \"options.h\"\r\n#include \"qol/itemlabels.h\"\r\n#include \"qol/stash.h\"\r\n#include \"towners.h\"\r\n#include \"track.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/palette_blending.hpp\"\r\n#include \"utils/sdl_bilinear_scale.hpp\"\r\n#include \"utils/surface_to_clx.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#include \"engine/load_clx.hpp\"\r\n#else\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"utils/parse_int.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\nnamespace {\r\n/** Cursor images CEL */\r\nOptionalOwnedClxSpriteList pCursCels;\r\nOptionalOwnedClxSpriteList pCursCels2;\r\n\r\nOptionalOwnedClxSpriteList *HalfSizeItemSprites;\r\nOptionalOwnedClxSpriteList *HalfSizeItemSpritesRed;\r\n\r\nbool IsValidMonsterForSelection(const Monster &monster)\r\n{\r\n\tif (monster.hasNoLife())\r\n\t\treturn false;\r\n\tif ((monster.flags & MFLAG_HIDDEN) != 0)\r\n\t\treturn false;\r\n\tif (monster.isPlayerMinion())\r\n\t\treturn false;\r\n\treturn true;\r\n}\r\n\r\nbool TrySelectMonster(bool flipflag, Point tile, tl::function_ref<bool(const Monster &)> isValidMonster)\r\n{\r\n\tauto checkPosition = [&](SelectionRegion selectionRegion, Displacement displacement) {\r\n\t\tconst Point posToCheck = tile + displacement;\r\n\t\tif (!InDungeonBounds(posToCheck) || dMonster[posToCheck.x][posToCheck.y] == 0)\r\n\t\t\treturn;\r\n\t\tconst uint16_t monsterId = std::abs(dMonster[posToCheck.x][posToCheck.y]) - 1;\r\n\t\tconst Monster &monster = Monsters[monsterId];\r\n\t\tif (IsTileLit(posToCheck) && HasAnyOf(monster.data().selectionRegion, selectionRegion) && isValidMonster(monster)) {\r\n\t\t\tcursPosition = posToCheck;\r\n\t\t\tpcursmonst = monsterId;\r\n\t\t}\r\n\t};\r\n\r\n\tif (!flipflag)\r\n\t\tcheckPosition(SelectionRegion::Top, { 2, 1 });\r\n\tif (flipflag)\r\n\t\tcheckPosition(SelectionRegion::Top, { 1, 2 });\r\n\tcheckPosition(SelectionRegion::Top, { 2, 2 });\r\n\tif (!flipflag)\r\n\t\tcheckPosition(SelectionRegion::Middle, { 1, 0 });\r\n\tif (flipflag)\r\n\t\tcheckPosition(SelectionRegion::Middle, { 0, 1 });\r\n\tcheckPosition(SelectionRegion::Bottom, { 0, 0 });\r\n\tcheckPosition(SelectionRegion::Middle, { 1, 1 });\r\n\treturn pcursmonst != -1;\r\n}\r\n\r\nbool TrySelectTowner(bool flipflag, Point tile)\r\n{\r\n\tauto checkPosition = [&](Displacement displacement) {\r\n\t\tconst Point posToCheck = tile + displacement;\r\n\t\tif (!InDungeonBounds(posToCheck) || dMonster[posToCheck.x][posToCheck.y] == 0)\r\n\t\t\treturn;\r\n\t\tconst uint16_t monsterId = std::abs(dMonster[posToCheck.x][posToCheck.y]) - 1;\r\n\t\tcursPosition = posToCheck;\r\n\t\tpcursmonst = monsterId;\r\n\t};\r\n\tif (!flipflag)\r\n\t\tcheckPosition({ 1, 0 });\r\n\tif (flipflag)\r\n\t\tcheckPosition({ 0, 1 });\r\n\tcheckPosition({ 0, 0 });\r\n\tcheckPosition({ 1, 1 });\r\n\treturn pcursmonst != -1;\r\n}\r\n\r\nbool TrySelectPlayer(bool flipflag, const Point tile)\r\n{\r\n\tif (!flipflag && tile.x + 1 < MAXDUNX && dPlayer[tile.x + 1][tile.y] != 0) {\r\n\t\tconst uint8_t playerId = std::abs(dPlayer[tile.x + 1][tile.y]) - 1;\r\n\t\tPlayer &player = Players[playerId];\r\n\t\tif (&player != MyPlayer && !player.hasNoLife()) {\r\n\t\t\tcursPosition = tile + Displacement { 1, 0 };\r\n\t\t\tPlayerUnderCursor = &player;\r\n\t\t}\r\n\t}\r\n\tif (flipflag && tile.y + 1 < MAXDUNY && dPlayer[tile.x][tile.y + 1] != 0) {\r\n\t\tconst uint8_t playerId = std::abs(dPlayer[tile.x][tile.y + 1]) - 1;\r\n\t\tPlayer &player = Players[playerId];\r\n\t\tif (&player != MyPlayer && !player.hasNoLife()) {\r\n\t\t\tcursPosition = tile + Displacement { 0, 1 };\r\n\t\t\tPlayerUnderCursor = &player;\r\n\t\t}\r\n\t}\r\n\tif (dPlayer[tile.x][tile.y] != 0) {\r\n\t\tconst uint8_t playerId = std::abs(dPlayer[tile.x][tile.y]) - 1;\r\n\t\tPlayer &player = Players[playerId];\r\n\t\tif (&player != MyPlayer) {\r\n\t\t\tcursPosition = tile;\r\n\t\t\tPlayerUnderCursor = &player;\r\n\t\t}\r\n\t}\r\n\tif (TileContainsDeadPlayer(tile)) {\r\n\t\tfor (const Player &player : Players) {\r\n\t\t\tif (player.position.tile == tile && &player != MyPlayer) {\r\n\t\t\t\tcursPosition = tile;\r\n\t\t\t\tPlayerUnderCursor = &player;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (pcurs == CURSOR_RESURRECT) {\r\n\t\tfor (int xx = -1; xx < 2; xx++) {\r\n\t\t\tfor (int yy = -1; yy < 2; yy++) {\r\n\t\t\t\tif (TileContainsDeadPlayer(tile + Displacement { xx, yy })) {\r\n\t\t\t\t\tfor (const Player &player : Players) {\r\n\t\t\t\t\t\tif (player.position.tile == tile + Displacement { xx, yy } && &player != MyPlayer) {\r\n\t\t\t\t\t\t\tcursPosition = tile + Displacement { xx, yy };\r\n\t\t\t\t\t\t\tPlayerUnderCursor = &player;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (tile.x + 1 < MAXDUNX && tile.y + 1 < MAXDUNY && dPlayer[tile.x + 1][tile.y + 1] != 0) {\r\n\t\tconst uint8_t playerId = std::abs(dPlayer[tile.x + 1][tile.y + 1]) - 1;\r\n\t\tconst Player &player = Players[playerId];\r\n\t\tif (&player != MyPlayer && !player.hasNoLife()) {\r\n\t\t\tcursPosition = tile + Displacement { 1, 1 };\r\n\t\t\tPlayerUnderCursor = &player;\r\n\t\t}\r\n\t}\r\n\r\n\treturn PlayerUnderCursor != nullptr;\r\n}\r\n\r\n/**\r\n * @brief Try find an object starting with the tile below the current tile (tall objects like doors)\r\n */\r\nbool TrySelectObject(bool flipflag, Point tile)\r\n{\r\n\tPoint testPosition = tile + Direction::South;\r\n\tObject *object = FindObjectAtPosition(testPosition);\r\n\r\n\tif (object == nullptr || HasNoneOf(object->selectionRegion, SelectionRegion::Middle)) {\r\n\t\t// Either no object or can't interact from the test position, try the current tile\r\n\t\ttestPosition = tile;\r\n\t\tobject = FindObjectAtPosition(testPosition);\r\n\r\n\t\tif (object == nullptr || HasNoneOf(object->selectionRegion, SelectionRegion::Bottom)) {\r\n\t\t\t// Still no object (that could be activated from this position), try the tile to the bottom left or right\r\n\t\t\t//  (whichever is closest to the cursor as determined when we set flipflag earlier)\r\n\t\t\ttestPosition = tile + (flipflag ? Direction::SouthWest : Direction::SouthEast);\r\n\t\t\tobject = FindObjectAtPosition(testPosition);\r\n\r\n\t\t\tif (object != nullptr && HasNoneOf(object->selectionRegion, SelectionRegion::Middle)) {\r\n\t\t\t\t// Found an object but it's not in range, clear the pointer\r\n\t\t\t\tobject = nullptr;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (object == nullptr)\r\n\t\treturn false;\r\n\r\n\t// found object that can be activated with the given cursor position\r\n\tcursPosition = testPosition;\r\n\tObjectUnderCursor = object;\r\n\treturn true;\r\n}\r\n\r\nbool TrySelectItem(bool flipflag, Point tile)\r\n{\r\n\tif (!flipflag && tile.x + 1 < MAXDUNX && dItem[tile.x + 1][tile.y] > 0) {\r\n\t\tconst uint8_t itemId = dItem[tile.x + 1][tile.y] - 1;\r\n\t\tif (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Middle)) {\r\n\t\t\tcursPosition = tile + Displacement { 1, 0 };\r\n\t\t\tpcursitem = static_cast<int8_t>(itemId);\r\n\t\t}\r\n\t}\r\n\tif (flipflag && tile.y + 1 < MAXDUNY && dItem[tile.x][tile.y + 1] > 0) {\r\n\t\tconst uint8_t itemId = dItem[tile.x][tile.y + 1] - 1;\r\n\t\tif (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Middle)) {\r\n\t\t\tcursPosition = tile + Displacement { 0, 1 };\r\n\t\t\tpcursitem = static_cast<int8_t>(itemId);\r\n\t\t}\r\n\t}\r\n\tif (dItem[tile.x][tile.y] > 0) {\r\n\t\tconst uint8_t itemId = dItem[tile.x][tile.y] - 1;\r\n\t\tif (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Bottom)) {\r\n\t\t\tcursPosition = tile;\r\n\t\t\tpcursitem = static_cast<int8_t>(itemId);\r\n\t\t}\r\n\t}\r\n\tif (tile.x + 1 < MAXDUNX && tile.y + 1 < MAXDUNY && dItem[tile.x + 1][tile.y + 1] > 0) {\r\n\t\tconst uint8_t itemId = dItem[tile.x + 1][tile.y + 1] - 1;\r\n\t\tif (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Middle)) {\r\n\t\t\tcursPosition = tile + Displacement { 1, 1 };\r\n\t\t\tpcursitem = static_cast<int8_t>(itemId);\r\n\t\t}\r\n\t}\r\n\treturn pcursitem != -1;\r\n}\r\n\r\nbool TrySelectPixelBased(Point tile)\r\n{\r\n\tif (demo::IsRunning() || demo::IsRecording() || HeadlessMode) {\r\n\t\t// Recorded demos can run headless, but headless mode doesn't support loading sprites that are needed for pixel perfect selection\r\n\t\t// => Ensure demos are always compatible\r\n\t\t// => Never use sprites for selection when handling demos\r\n\t\treturn false;\r\n\t}\r\n\r\n\tauto checkSprite = [](Point renderingTile, const ClxSprite sprite, Displacement renderingOffset) {\r\n\t\tconst Point renderPosition = GetScreenPosition(renderingTile) + renderingOffset;\r\n\t\tPoint spriteTopLeft = renderPosition - Displacement { 0, sprite.height() };\r\n\t\tSize spriteSize = { sprite.width(), sprite.height() };\r\n\t\tif (*GetOptions().Graphics.zoom) {\r\n\t\t\tspriteSize *= 2;\r\n\t\t\tspriteTopLeft *= 2;\r\n\t\t}\r\n\t\tconst Rectangle spriteCoords = Rectangle(spriteTopLeft, spriteSize);\r\n\t\tif (!spriteCoords.contains(MousePosition))\r\n\t\t\treturn false;\r\n\t\tPoint pointInSprite = Point { 0, 0 } + (MousePosition - spriteCoords.position);\r\n\t\tif (*GetOptions().Graphics.zoom)\r\n\t\t\tpointInSprite /= 2;\r\n\t\treturn IsPointWithinClx(pointInSprite, sprite);\r\n\t};\r\n\r\n\tauto convertFromRenderingToWorldTile = [](Point renderingPoint) {\r\n\t\t// Columns\r\n\t\tDisplacement ret = Displacement(Direction::East) * renderingPoint.x;\r\n\t\t// Rows\r\n\t\tret += Displacement(Direction::South) * renderingPoint.y / 2;\r\n\t\tif ((renderingPoint.y & 1) == 1)\r\n\t\t\tret.deltaY += 1;\r\n\t\treturn ret;\r\n\t};\r\n\r\n\t// Try to find the selected entity from rendered pixels.\r\n\t// We search the rendered rows/columns backwards, because the last rendered tile overrides previous rendered pixels.\r\n\tauto searchArea = PointsInRectangle(Rectangle { { -1, -1 }, { 3, 8 } });\r\n\tfor (auto it = searchArea.rbegin(); it != searchArea.rend(); ++it) {\r\n\t\tconst Point renderingColumnRaw = *it;\r\n\t\tconst Point adjacentTile = tile + convertFromRenderingToWorldTile(renderingColumnRaw);\r\n\t\tif (!InDungeonBounds(adjacentTile))\r\n\t\t\tcontinue;\r\n\r\n\t\tint monsterId = dMonster[adjacentTile.x][adjacentTile.y];\r\n\t\t// Never select a monster if a target-player-only spell is selected\r\n\t\tif (monsterId != 0 && IsNoneOf(pcurs, CURSOR_HEALOTHER, CURSOR_RESURRECT)) {\r\n\t\t\tmonsterId = std::abs(monsterId) - 1;\r\n\t\t\tif (leveltype == DTYPE_TOWN) {\r\n\t\t\t\tconst Towner &towner = Towners[monsterId];\r\n\t\t\t\tconst ClxSprite sprite = towner.currentSprite();\r\n\t\t\t\tconst Displacement renderingOffset = towner.getRenderingOffset();\r\n\t\t\t\tif (checkSprite(adjacentTile, sprite, renderingOffset)) {\r\n\t\t\t\t\tcursPosition = adjacentTile;\r\n\t\t\t\t\tpcursmonst = monsterId;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tconst Monster &monster = Monsters[monsterId];\r\n\t\t\t\tif (IsTileLit(adjacentTile) && IsValidMonsterForSelection(monster)) {\r\n\t\t\t\t\tconst ClxSprite sprite = monster.animInfo.currentSprite();\r\n\t\t\t\t\tconst Displacement renderingOffset = monster.getRenderingOffset(sprite);\r\n\t\t\t\t\tif (checkSprite(adjacentTile, sprite, renderingOffset)) {\r\n\t\t\t\t\t\tcursPosition = adjacentTile;\r\n\t\t\t\t\t\tpcursmonst = monsterId;\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst int8_t dPlayerValue = dPlayer[adjacentTile.x][adjacentTile.y];\r\n\t\tif (dPlayerValue != 0) {\r\n\t\t\tconst uint8_t playerId = std::abs(dPlayerValue) - 1;\r\n\t\t\tif (playerId != MyPlayerId) {\r\n\t\t\t\tconst Player &player = Players[playerId];\r\n\t\t\t\tconst ClxSprite sprite = player.currentSprite();\r\n\t\t\t\tconst Displacement renderingOffset = player.getRenderingOffset(sprite);\r\n\t\t\t\tif (checkSprite(adjacentTile, sprite, renderingOffset)) {\r\n\t\t\t\t\tcursPosition = adjacentTile;\r\n\t\t\t\t\tPlayerUnderCursor = &player;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (TileContainsDeadPlayer(adjacentTile)) {\r\n\t\t\tfor (const Player &player : Players) {\r\n\t\t\t\tif (player.position.tile == adjacentTile && &player != MyPlayer) {\r\n\t\t\t\t\tconst ClxSprite sprite = player.currentSprite();\r\n\t\t\t\t\tconst Displacement renderingOffset = player.getRenderingOffset(sprite);\r\n\t\t\t\t\tif (checkSprite(adjacentTile, sprite, renderingOffset)) {\r\n\t\t\t\t\t\tcursPosition = adjacentTile;\r\n\t\t\t\t\t\tPlayerUnderCursor = &player;\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tObject *object = FindObjectAtPosition(adjacentTile);\r\n\t\tif (object != nullptr && object->canInteractWith()) {\r\n\t\t\tconst ClxSprite sprite = object->currentSprite();\r\n\t\t\tconst Displacement renderingOffset = object->getRenderingOffset(sprite, adjacentTile);\r\n\t\t\tif (checkSprite(adjacentTile, sprite, renderingOffset)) {\r\n\t\t\t\tcursPosition = adjacentTile;\r\n\t\t\t\tObjectUnderCursor = object;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tuint8_t itemId = dItem[adjacentTile.x][adjacentTile.y];\r\n\t\tif (itemId != 0) {\r\n\t\t\titemId = itemId - 1;\r\n\t\t\tconst Item &item = Items[itemId];\r\n\t\t\tconst ClxSprite sprite = item.AnimInfo.currentSprite();\r\n\t\t\tconst Displacement renderingOffset = item.getRenderingOffset(sprite);\r\n\t\t\tif (checkSprite(adjacentTile, sprite, renderingOffset)) {\r\n\t\t\t\tcursPosition = adjacentTile;\r\n\t\t\t\tpcursitem = static_cast<int8_t>(itemId);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n#ifndef UNPACKED_MPQS\r\nstd::vector<uint16_t> ReadWidths(AssetRef &&ref)\r\n{\r\n\tconst size_t len = ref.size();\r\n\tif (len == 0) {\r\n\t\tapp_fatal(\"Missing widths\");\r\n\t}\r\n\tconst std::unique_ptr<char[]> data { new char[len] };\r\n\r\n\tAssetHandle handle = OpenAsset(std::move(ref));\r\n\tif (!handle.ok() || !handle.read(data.get(), len)) {\r\n\t\tapp_fatal(\"Failed to load widths\");\r\n\t}\r\n\r\n\tstd::string_view str { data.get(), len };\r\n\tstd::vector<uint16_t> result;\r\n\twhile (!str.empty()) {\r\n\t\tconst char *end;\r\n\t\tconst ParseIntResult<uint16_t> parseResult = ParseInt<uint16_t>(str, std::numeric_limits<uint16_t>::min(),\r\n\t\t    std::numeric_limits<uint16_t>::max(), &end);\r\n\t\tif (!parseResult.has_value()) {\r\n\t\t\tapp_fatal(StrCat(\"Failed to parse width value from: [\", str, \"]\"));\r\n\t\t}\r\n\t\tresult.push_back(parseResult.value());\r\n\t\tstr.remove_prefix(end - str.data());\r\n\t\twhile (!str.empty() && (str[0] == '\\r' || str[0] == '\\n')) {\r\n\t\t\tstr.remove_prefix(1);\r\n\t\t}\r\n\t}\r\n\treturn result;\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\n/** Current highlighted monster */\r\nint pcursmonst = -1;\r\n\r\n/** inv_item value */\r\nint8_t pcursinvitem;\r\n/** StashItem value */\r\nuint16_t pcursstashitem;\r\n/** Current highlighted item */\r\nint8_t pcursitem;\r\n/** Current highlighted object */\r\nObject *ObjectUnderCursor;\r\n/** Current highlighted player */\r\nconst Player *PlayerUnderCursor;\r\n/** Current highlighted tile position */\r\nPoint cursPosition;\r\n/** Previously highlighted monster */\r\nint pcurstemp;\r\n/** Index of current cursor image */\r\nint pcurs;\r\n\r\nvoid InitCursor()\r\n{\r\n\tassert(!pCursCels);\r\n#ifdef UNPACKED_MPQS\r\n\tpCursCels = LoadClx(\"data\\\\inv\\\\objcurs.clx\");\r\n\tpCursCels2 = LoadOptionalClx(\"data\\\\inv\\\\objcurs2.clx\");\r\n#else\r\n\tpCursCels = LoadCel(\"data\\\\inv\\\\objcurs\", ReadWidths(FindAsset(\"data\\\\inv\\\\objcurs-widths.txt\")).data());\r\n\tAssetRef ref = FindAsset(\"data\\\\inv\\\\objcurs2-widths.txt\");\r\n\tif (ref.ok()) {\r\n\t\tpCursCels2 = LoadOptionalCel(\"data\\\\inv\\\\objcurs2\", ReadWidths(std::move(ref)).data());\r\n\t}\r\n#endif\r\n\tClearCursor();\r\n}\r\n\r\nvoid FreeCursor()\r\n{\r\n\tpCursCels = std::nullopt;\r\n\tpCursCels2 = std::nullopt;\r\n\tClearCursor();\r\n}\r\n\r\nClxSprite GetInvItemSprite(int cursId)\r\n{\r\n\tassert(cursId > 0);\r\n\tconst size_t numSprites = pCursCels->numSprites();\r\n\tif (static_cast<size_t>(cursId) <= numSprites) {\r\n\t\treturn (*pCursCels)[cursId - 1];\r\n\t}\r\n\tassert(pCursCels2.has_value());\r\n\tassert(cursId - numSprites <= pCursCels2->numSprites());\r\n\treturn (*pCursCels2)[cursId - numSprites - 1];\r\n}\r\n\r\nSize GetInvItemSize(int cursId)\r\n{\r\n\tconst ClxSprite sprite = GetInvItemSprite(cursId);\r\n\treturn { sprite.width(), sprite.height() };\r\n}\r\n\r\nClxSprite GetHalfSizeItemSprite(int cursId)\r\n{\r\n\treturn (*HalfSizeItemSprites[cursId])[0];\r\n}\r\n\r\nClxSprite GetHalfSizeItemSpriteRed(int cursId)\r\n{\r\n\treturn (*HalfSizeItemSpritesRed[cursId])[0];\r\n}\r\n\r\nvoid CreateHalfSizeItemSprites()\r\n{\r\n\tif (HalfSizeItemSprites != nullptr)\r\n\t\treturn;\r\n\tconst uint32_t numInvItems = pCursCels->numSprites() - (static_cast<uint32_t>(CURSOR_FIRSTITEM) - 1)\r\n\t    + (pCursCels2.has_value() ? pCursCels2->numSprites() : 0);\r\n\tHalfSizeItemSprites = new OptionalOwnedClxSpriteList[numInvItems];\r\n\tHalfSizeItemSpritesRed = new OptionalOwnedClxSpriteList[numInvItems];\r\n\tconst uint8_t *redTrn = GetInfravisionTRN();\r\n\r\n\tconstexpr int MaxWidth = 28 * 3;\r\n\tconstexpr int MaxHeight = 28 * 3;\r\n\tOwnedSurface ownedItemSurface { MaxWidth, MaxHeight };\r\n\tOwnedSurface ownedHalfSurface { MaxWidth / 2, MaxHeight / 2 };\r\n\r\n\tconst auto createHalfSize = [&, redTrn](const ClxSprite itemSprite, size_t outputIndex) {\r\n\t\tif (itemSprite.width() <= 28 && itemSprite.height() <= 28) {\r\n\t\t\t// Skip creating half-size sprites for 1x1 items because we always render them at full size anyway.\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst Surface itemSurface = ownedItemSurface.subregion(0, 0, itemSprite.width(), itemSprite.height());\r\n\t\tconst SDL_Rect itemSurfaceRect = MakeSdlRect(0, 0, itemSurface.w(), itemSurface.h());\r\n\r\n\t\tSDL_SetSurfaceClipRect(itemSurface.surface, &itemSurfaceRect);\r\n\t\tSDL_FillSurfaceRect(itemSurface.surface, nullptr, 1);\r\n\t\tClxDraw(itemSurface, { 0, itemSurface.h() }, itemSprite);\r\n\r\n\t\tconst Surface halfSurface = ownedHalfSurface.subregion(0, 0, itemSurface.w() / 2, itemSurface.h() / 2);\r\n\t\tconst SDL_Rect halfSurfaceRect = MakeSdlRect(0, 0, halfSurface.w(), halfSurface.h());\r\n\t\tSDL_SetSurfaceClipRect(halfSurface.surface, &halfSurfaceRect);\r\n\t\tBilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1);\r\n\t\tHalfSizeItemSprites[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1));\r\n\r\n\t\tSDL_FillSurfaceRect(itemSurface.surface, nullptr, 1);\r\n\t\tClxDrawTRN(itemSurface, { 0, itemSurface.h() }, itemSprite, redTrn);\r\n\t\tBilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1);\r\n\t\tHalfSizeItemSpritesRed[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1));\r\n\t};\r\n\r\n\tsize_t outputIndex = 0;\r\n\tfor (size_t i = static_cast<int>(CURSOR_FIRSTITEM) - 1, n = pCursCels->numSprites(); i < n; ++i, ++outputIndex) {\r\n\t\tcreateHalfSize((*pCursCels)[i], outputIndex);\r\n\t}\r\n\tif (pCursCels2.has_value()) {\r\n\t\tfor (size_t i = 0, n = pCursCels2->numSprites(); i < n; ++i, ++outputIndex) {\r\n\t\t\tcreateHalfSize((*pCursCels2)[i], outputIndex);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FreeHalfSizeItemSprites()\r\n{\r\n\tif (HalfSizeItemSprites != nullptr) {\r\n\t\tdelete[] HalfSizeItemSprites;\r\n\t\tHalfSizeItemSprites = nullptr;\r\n\t\tdelete[] HalfSizeItemSpritesRed;\r\n\t\tHalfSizeItemSpritesRed = nullptr;\r\n\t}\r\n}\r\n\r\nvoid DrawItem(const Item &item, const Surface &out, Point position, ClxSprite clx)\r\n{\r\n\tconst bool usable = !IsInspectingPlayer() ? item._iStatFlag : InspectPlayer->CanUseItem(item);\r\n\tif (usable) {\r\n\t\tClxDraw(out, position, clx);\r\n\t} else {\r\n\t\tClxDrawTRN(out, position, clx, GetInfravisionTRN());\r\n\t}\r\n}\r\n\r\nvoid ResetCursor()\r\n{\r\n\tNewCursor(pcurs);\r\n}\r\n\r\nvoid NewCursor(const Item &item)\r\n{\r\n\tif (item.isEmpty()) {\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t} else {\r\n\t\tNewCursor(item._iCurs + CURSOR_FIRSTITEM);\r\n\t}\r\n}\r\n\r\nvoid NewCursor(int cursId)\r\n{\r\n\tif (pcurs >= CURSOR_FIRSTITEM && cursId > CURSOR_HAND && cursId < CURSOR_HOURGLASS) {\r\n\t\tif (!TryDropItem()) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tif (cursId < CURSOR_HOURGLASS && MyPlayer != nullptr) {\r\n\t\tMyPlayer->HoldItem.clear();\r\n\t}\r\n\tpcurs = cursId;\r\n\r\n\tif (IsHardwareCursorEnabled() && ControlDevice == ControlTypes::KeyboardAndMouse) {\r\n\t\tif (!ArtCursor && cursId == CURSOR_NONE)\r\n\t\t\treturn;\r\n\r\n\t\tconst CursorInfo newCursor = ArtCursor\r\n\t\t    ? CursorInfo::UserInterfaceCursor()\r\n\t\t    : CursorInfo::GameCursor(cursId);\r\n\t\tif (newCursor != GetCurrentCursorInfo())\r\n\t\t\tSetHardwareCursor(newCursor);\r\n\t}\r\n}\r\n\r\nvoid DrawSoftwareCursor(const Surface &out, Point position, int cursId)\r\n{\r\n\tconst ClxSprite sprite = GetInvItemSprite(cursId);\r\n\tif (cursId >= CURSOR_FIRSTITEM && !MyPlayer->HoldItem.isEmpty()) {\r\n\t\tconst auto &heldItem = MyPlayer->HoldItem;\r\n\t\tClxDrawOutline(out, GetOutlineColor(heldItem, true), position, sprite);\r\n\t\tDrawItem(heldItem, out, position, sprite);\r\n\t} else {\r\n\t\tClxDraw(out, position, sprite);\r\n\t}\r\n}\r\n\r\nvoid InitLevelCursor()\r\n{\r\n\tNewCursor(CURSOR_HAND);\r\n\tcursPosition = ViewPosition;\r\n\tpcurstemp = -1;\r\n\tpcursmonst = -1;\r\n\tObjectUnderCursor = nullptr;\r\n\tpcursitem = -1;\r\n\tpcursstashitem = StashStruct::EmptyCell;\r\n\tPlayerUnderCursor = nullptr;\r\n\tClearCursor();\r\n}\r\n\r\nvoid CheckTown()\r\n{\r\n\tfor (auto &missile : Missiles) {\r\n\t\tif (missile._mitype == MissileID::TownPortal) {\r\n\t\t\tif (EntranceBoundaryContains(missile.position.tile, cursPosition)) {\r\n\t\t\t\ttrigflag = true;\r\n\t\t\t\tInfoString = _(\"Town Portal\");\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"from {:s}\")), Players[missile._misource]._pName));\r\n\t\t\t\tcursPosition = missile.position.tile;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CheckRportal()\r\n{\r\n\tfor (auto &missile : Missiles) {\r\n\t\tif (missile._mitype == MissileID::RedPortal) {\r\n\t\t\tif (EntranceBoundaryContains(missile.position.tile, cursPosition)) {\r\n\t\t\t\ttrigflag = true;\r\n\t\t\t\tInfoString = _(\"Portal to\");\r\n\t\t\t\tAddInfoBoxString(!setlevel ? _(\"The Unholy Altar\") : _(\"level 15\"));\r\n\t\t\t\tcursPosition = missile.position.tile;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DisplayTriggerInfo()\r\n{\r\n\tCheckTrigForce();\r\n\tCheckTown();\r\n\tCheckRportal();\r\n}\r\n\r\n/**\r\n * @brief Adjusts mouse position based on panels\r\n */\r\nvoid AlterMousePositionViaPanels(Point &screenPosition)\r\n{\r\n\tif (CanPanelsCoverView()) {\r\n\t\tif (IsLeftPanelOpen()) {\r\n\t\t\tscreenPosition.x -= GetScreenWidth() / 4;\r\n\t\t} else if (IsRightPanelOpen()) {\r\n\t\t\tscreenPosition.x += GetScreenWidth() / 4;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief If scrolling, offset the mousepos\r\n */\r\nvoid AlterMousePositionViaScrolling(Point &screenPosition, Rectangle mainPanel)\r\n{\r\n\tif (mainPanel.contains(MousePosition) && track_isscrolling()) {\r\n\t\tscreenPosition.y = mainPanel.position.y - 1;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Adjust based on current zoom\r\n */\r\nvoid AlterMousePositionViaZoom(Point &screenPosition)\r\n{\r\n\tif (*GetOptions().Graphics.zoom) {\r\n\t\tscreenPosition.x /= 2;\r\n\t\tscreenPosition.y /= 2;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Adjust by player offset and tile grid alignment\r\n */\r\nvoid AlterMousePositionViaPlayer(Point &screenPosition, const Player &myPlayer)\r\n{\r\n\tint xo = 0;\r\n\tint yo = 0;\r\n\tCalcTileOffset(&xo, &yo);\r\n\tscreenPosition.x += xo;\r\n\tscreenPosition.y += yo;\r\n\r\n\t// Adjust for player walking\r\n\tif (myPlayer.isWalking()) {\r\n\t\tconst Displacement offset = GetOffsetForWalking(myPlayer.AnimInfo, myPlayer._pdir, true);\r\n\t\tscreenPosition.x -= offset.deltaX;\r\n\t\tscreenPosition.y -= offset.deltaY;\r\n\r\n\t\t// Predict the next frame when walking to avoid input jitter\r\n\t\tconst DisplacementOf<int16_t> offset2 = myPlayer.position.CalculateWalkingOffsetShifted8(myPlayer._pdir, myPlayer.AnimInfo);\r\n\t\tconst DisplacementOf<int16_t> velocity = myPlayer.position.GetWalkingVelocityShifted8(myPlayer._pdir, myPlayer.AnimInfo);\r\n\t\tint fx = offset2.deltaX / 256;\r\n\t\tint fy = offset2.deltaY / 256;\r\n\t\tfx -= (offset2.deltaX + velocity.deltaX) / 256;\r\n\t\tfy -= (offset2.deltaY + velocity.deltaY) / 256;\r\n\r\n\t\tscreenPosition.x -= fx;\r\n\t\tscreenPosition.y -= fy;\r\n\t}\r\n}\r\n\r\nPoint ConvertToTileGrid(Point &screenPosition)\r\n{\r\n\tint columns = 0;\r\n\tint rows = 0;\r\n\tTilesInView(&columns, &rows);\r\n\tconst int lrow = rows - RowsCoveredByPanel();\r\n\r\n\t// Center player tile on screen\r\n\tPoint currentTile = ViewPosition;\r\n\tShiftGrid(&currentTile, -columns / 2, -lrow / 2);\r\n\r\n\t// Align grid\r\n\tif ((columns % 2) == 0 && (lrow % 2) == 0) {\r\n\t\tscreenPosition.y += TILE_HEIGHT / 2;\r\n\t} else if ((columns % 2) != 0 && (lrow % 2) != 0) {\r\n\t\tscreenPosition.x -= TILE_WIDTH / 2;\r\n\t} else if ((columns % 2) != 0 && (lrow % 2) == 0) {\r\n\t\tcurrentTile.y++;\r\n\t}\r\n\r\n\tif (*GetOptions().Graphics.zoom) {\r\n\t\tscreenPosition.y -= TILE_HEIGHT / 4;\r\n\t}\r\n\r\n\tconst int tx = screenPosition.x / TILE_WIDTH;\r\n\tconst int ty = screenPosition.y / TILE_HEIGHT;\r\n\tShiftGrid(&currentTile, tx, ty);\r\n\r\n\treturn currentTile;\r\n}\r\n\r\n/**\r\n * @brief Shift position to match diamond grid alignment\r\n */\r\nvoid ShiftToDiamondGridAlignment(Point screenPosition, Point &tile, bool &flipflag)\r\n{\r\n\tconst int px = screenPosition.x % TILE_WIDTH;\r\n\tconst int py = screenPosition.y % TILE_HEIGHT;\r\n\r\n\tconst bool flipy = py < (px / 2);\r\n\tif (flipy) {\r\n\t\ttile.y--;\r\n\t}\r\n\tconst bool flipx = py >= TILE_HEIGHT - (px / 2);\r\n\tif (flipx) {\r\n\t\ttile.x++;\r\n\t}\r\n\r\n\ttile.x = std::clamp(tile.x, 0, MAXDUNX - 1);\r\n\ttile.y = std::clamp(tile.y, 0, MAXDUNY - 1);\r\n\r\n\tflipflag = (flipy && flipx) || ((flipy || flipx) && px < TILE_WIDTH / 2);\r\n}\r\n\r\n/**\r\n * @brief While holding the button down we should retain target (but potentially lose it if it dies, goes out of view, etc)\r\n */\r\nbool CheckMouseHold(const Point currentTile)\r\n{\r\n\tif ((sgbMouseDown != CLICK_NONE || ControllerActionHeld != GameActionType_NONE) && IsNoneOf(LastPlayerAction, PlayerActionType::None, PlayerActionType::Attack, PlayerActionType::Spell)) {\r\n\t\tInvalidateTargets();\r\n\r\n\t\tif (pcursmonst == -1 && ObjectUnderCursor == nullptr && pcursitem == -1 && pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell && PlayerUnderCursor == nullptr) {\r\n\t\t\tcursPosition = currentTile;\r\n\t\t\tDisplayTriggerInfo();\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid ResetCursorInfo()\r\n{\r\n\tpcurstemp = pcursmonst;\r\n\tpcursmonst = -1;\r\n\tObjectUnderCursor = nullptr;\r\n\tpcursitem = -1;\r\n\tif (pcursinvitem != -1) {\r\n\t\tRedrawComponent(PanelDrawComponent::Belt);\r\n\t}\r\n\tpcursinvitem = -1;\r\n\tpcursstashitem = StashStruct::EmptyCell;\r\n\tPlayerUnderCursor = nullptr;\r\n\tShowUniqueItemInfoBox = false;\r\n\tMainPanelFlag = false;\r\n\ttrigflag = false;\r\n}\r\n\r\nbool CheckPlayerState(const Point currentTile, const Player &myPlayer)\r\n{\r\n\tif (myPlayer._pInvincible) {\r\n\t\treturn true;\r\n\t}\r\n\tif (!myPlayer.HoldItem.isEmpty() || SpellSelectFlag) {\r\n\t\tcursPosition = currentTile;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CheckPanelsAndFlags(Rectangle mainPanel)\r\n{\r\n\tif (mainPanel.contains(MousePosition)) {\r\n\t\tCheckPanelInfo();\r\n\t\treturn true;\r\n\t}\r\n\tif (DoomFlag) {\r\n\t\treturn true;\r\n\t}\r\n\tif (invflag && GetRightPanel().contains(MousePosition)) {\r\n\t\tpcursinvitem = CheckInvHLight();\r\n\t\treturn true;\r\n\t}\r\n\tif (IsStashOpen && GetLeftPanel().contains(MousePosition)) {\r\n\t\tpcursstashitem = CheckStashHLight(MousePosition);\r\n\t}\r\n\tif (SpellbookFlag && GetRightPanel().contains(MousePosition)) {\r\n\t\treturn true;\r\n\t}\r\n\tif (IsLeftPanelOpen() && GetLeftPanel().contains(MousePosition)) {\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CheckCursorActions(const Point currentTile, bool flipflag)\r\n{\r\n\tif (pcurs == CURSOR_IDENTIFY) {\r\n\t\tObjectUnderCursor = nullptr;\r\n\t\tpcursmonst = -1;\r\n\t\tpcursitem = -1;\r\n\t\tcursPosition = currentTile;\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (TrySelectPixelBased(currentTile))\r\n\t\treturn true;\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\t// Never select a monster if a target-player-only spell is selected\r\n\t\tif (IsNoneOf(pcurs, CURSOR_HEALOTHER, CURSOR_RESURRECT)) {\r\n\t\t\tif (pcurstemp != -1 && TrySelectMonster(flipflag, currentTile, [](const Monster &monster) {\r\n\t\t\t\t    if (!IsValidMonsterForSelection(monster))\r\n\t\t\t\t\t    return false;\r\n\t\t\t\t    if (monster.getId() != static_cast<unsigned>(pcurstemp))\r\n\t\t\t\t\t    return false;\r\n\t\t\t\t    return true;\r\n\t\t\t    })) {\r\n\t\t\t\t// found a valid previous selected monster\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (TrySelectMonster(flipflag, currentTile, IsValidMonsterForSelection)) {\r\n\t\t\t\t// found a valid monster\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tif (TrySelectTowner(flipflag, currentTile)) {\r\n\t\t\t// found a towner\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn TrySelectPlayer(flipflag, currentTile)\r\n\t    || TrySelectObject(flipflag, currentTile)\r\n\t    || TrySelectItem(flipflag, currentTile);\r\n}\r\n\r\n/**\r\n * @brief Checks for early return if an item is highlighted\r\n */\r\nvoid CheckCursMove()\r\n{\r\n\tif (IsItemLabelHighlighted())\r\n\t\treturn;\r\n\r\n\tPoint screenPosition = MousePosition;\r\n\tconst Rectangle &mainPanel = GetMainPanel();\r\n\r\n\tAlterMousePositionViaPanels(screenPosition);\r\n\tAlterMousePositionViaScrolling(screenPosition, mainPanel);\r\n\tAlterMousePositionViaZoom(screenPosition);\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tAlterMousePositionViaPlayer(screenPosition, myPlayer);\r\n\r\n\tbool flipflag = false;\r\n\tPoint currentTile = ConvertToTileGrid(screenPosition);\r\n\r\n\tShiftToDiamondGridAlignment(screenPosition, currentTile, flipflag);\r\n\r\n\tif (CheckMouseHold(currentTile)) return;\r\n\r\n\tResetCursorInfo();\r\n\r\n\tif (CheckPlayerState(currentTile, myPlayer) || CheckPanelsAndFlags(mainPanel) || CheckCursorActions(currentTile, flipflag)) return;\r\n\r\n\t// update cursor position\r\n\tcursPosition = currentTile;\r\n\tDisplayTriggerInfo();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/cursor.h",
    "content": "/**\r\n * @file cursor.h\r\n *\r\n * Interface of cursor tracking functionality.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class SelectionRegion : uint8_t {\r\n\tNone = 0,\r\n\tBottom = 1U << 0,\r\n\tMiddle = 1U << 1,\r\n\tTop = 1U << 2,\r\n};\r\nuse_enum_as_flags(SelectionRegion);\r\n\r\nenum cursor_id : uint8_t {\r\n\tCURSOR_NONE,\r\n\tCURSOR_HAND,\r\n\tCURSOR_IDENTIFY,\r\n\tCURSOR_REPAIR,\r\n\tCURSOR_RECHARGE,\r\n\tCURSOR_DISARM,\r\n\tCURSOR_OIL,\r\n\tCURSOR_TELEKINESIS,\r\n\tCURSOR_RESURRECT,\r\n\tCURSOR_TELEPORT,\r\n\tCURSOR_HEALOTHER,\r\n\tCURSOR_HOURGLASS,\r\n\tCURSOR_FIRSTITEM,\r\n};\r\n\r\nextern int pcursmonst;\r\nextern int8_t pcursinvitem;\r\nextern uint16_t pcursstashitem;\r\nextern int8_t pcursitem;\r\n\r\nstruct Object; // Defined in objects.h\r\nextern Object *ObjectUnderCursor;\r\n\r\nstruct Player; // Defined in player.h\r\nextern const Player *PlayerUnderCursor;\r\nextern Point cursPosition;\r\nextern DVL_API_FOR_TEST int pcurs;\r\n\r\nvoid InitCursor();\r\nvoid FreeCursor();\r\nvoid ResetCursor();\r\n\r\nstruct Item;\r\n/**\r\n * @brief Use the item sprite as the cursor (or show the default hand cursor if the item isEmpty)\r\n */\r\nvoid NewCursor(const Item &item);\r\n\r\nvoid NewCursor(int cursId);\r\n\r\nvoid InitLevelCursor();\r\nvoid CheckRportal();\r\nvoid CheckTown();\r\nvoid CheckCursMove();\r\n\r\nvoid DrawSoftwareCursor(const Surface &out, Point position, int cursId);\r\n\r\nvoid DrawItem(const Item &item, const Surface &out, Point position, ClxSprite clx);\r\n\r\n/** Returns the sprite for the given inventory index. */\r\nClxSprite GetInvItemSprite(int cursId);\r\n\r\nClxSprite GetHalfSizeItemSprite(int cursId);\r\nClxSprite GetHalfSizeItemSpriteRed(int cursId);\r\nvoid CreateHalfSizeItemSprites();\r\nvoid FreeHalfSizeItemSprites();\r\n\r\n/** Returns the width and height for an inventory index. */\r\nSize GetInvItemSize(int cursId);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/file.cpp",
    "content": "#include \"file.hpp\"\r\n\r\n#include <bitset>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <limits>\r\n#include <memory>\r\n\r\n#include <expected.hpp>\r\n#include <fmt/format.h>\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\ntl::expected<DataFile, DataFile::Error> DataFile::load(std::string_view path)\r\n{\r\n\tAssetRef ref = FindAsset(path);\r\n\tif (!ref.ok())\r\n\t\treturn tl::unexpected { Error::NotFound };\r\n\tconst size_t size = ref.size();\r\n\t// TODO: It should be possible to stream the data file contents instead of copying the whole thing into memory\r\n\tstd::unique_ptr<char[]> data { new char[size] };\r\n\t{\r\n\t\tAssetHandle handle = OpenAsset(std::move(ref));\r\n\t\tif (!handle.ok())\r\n\t\t\treturn tl::unexpected { Error::OpenFailed };\r\n\t\tif (size > 0 && !handle.read(data.get(), size))\r\n\t\t\treturn tl::unexpected { Error::BadRead };\r\n\t}\r\n\treturn DataFile { std::move(data), size };\r\n}\r\n\r\nDataFile DataFile::loadOrDie(std::string_view path)\r\n{\r\n\ttl::expected<DataFile, DataFile::Error> dataFileResult = DataFile::load(path);\r\n\tif (!dataFileResult.has_value()) {\r\n\t\tDataFile::reportFatalError(dataFileResult.error(), path);\r\n\t}\r\n\treturn *std::move(dataFileResult);\r\n}\r\n\r\nvoid DataFile::reportFatalError(Error code, std::string_view fileName)\r\n{\r\n\tswitch (code) {\r\n\tcase Error::NotFound:\r\n\tcase Error::OpenFailed:\r\n\tcase Error::BadRead:\r\n\t\tapp_fatal(fmt::format(fmt::runtime(_(\r\n\t\t                          /* TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name} */\r\n\t\t                          \"Unable to load data from file {0}\")),\r\n\t\t    fileName));\r\n\tcase Error::NoContent:\r\n\t\tapp_fatal(fmt::format(fmt::runtime(_(\r\n\t\t                          /* TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name} */\r\n\t\t                          \"{0} is incomplete, please check the file contents.\")),\r\n\t\t    fileName));\r\n\tcase Error::NotEnoughColumns:\r\n\t\tapp_fatal(fmt::format(fmt::runtime(_(\r\n\t\t                          /* TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name} */\r\n\t\t                          \"Your {0} file doesn't have the expected columns, please make sure it matches the documented format.\")),\r\n\t\t    fileName));\r\n\t}\r\n}\r\n\r\nvoid DataFile::reportFatalFieldError(DataFileField::Error code, std::string_view fileName, std::string_view fieldName, const DataFileField &field, std::string_view details)\r\n{\r\n\tstd::string detailsStr;\r\n\tif (!details.empty()) {\r\n\t\tdetailsStr = StrCat(\"\\n\", details);\r\n\t}\r\n\tswitch (code) {\r\n\tcase DataFileField::Error::NotANumber:\r\n\t\tapp_fatal(fmt::format(fmt::runtime(_(\r\n\t\t                          /* TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number} */\r\n\t\t                          \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\")),\r\n\t\t    field.currentValue(), fieldName, fileName, field.row(), field.column())\r\n\t\t              .append(detailsStr));\r\n\tcase DataFileField::Error::OutOfRange:\r\n\t\tapp_fatal(fmt::format(fmt::runtime(_(\r\n\t\t                          /* TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number} */\r\n\t\t                          \"Out of range value {0} for {1} in {2} at row {3} and column {4}\")),\r\n\t\t    field.currentValue(), fieldName, fileName, field.row(), field.column())\r\n\t\t              .append(detailsStr));\r\n\tcase DataFileField::Error::InvalidValue:\r\n\t\tapp_fatal(fmt::format(fmt::runtime(_(\r\n\t\t                          /* TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number} */\r\n\t\t                          \"Invalid value {0} for {1} in {2} at row {3} and column {4}\")),\r\n\t\t    field.currentValue(), fieldName, fileName, field.row(), field.column())\r\n\t\t              .append(detailsStr));\r\n\t}\r\n}\r\n\r\ntl::expected<void, DataFile::Error> DataFile::parseHeader(ColumnDefinition *begin, ColumnDefinition *end, tl::function_ref<tl::expected<uint8_t, ColumnDefinition::Error>(std::string_view)> mapper)\r\n{\r\n\tstd::bitset<std::numeric_limits<uint8_t>::max()> seenColumns;\r\n\tunsigned lastColumn = 0;\r\n\r\n\tRecordIterator firstRecord { data(), data() + size(), false };\r\n\tfor (DataFileField field : *firstRecord) {\r\n\t\tif (begin == end) {\r\n\t\t\t// All key columns have been identified\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tauto mapResult = mapper(*field);\r\n\t\tif (!mapResult.has_value()) {\r\n\t\t\t// not a key column\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst uint8_t columnType = mapResult.value();\r\n\t\tif (seenColumns.test(columnType)) {\r\n\t\t\t// Repeated column? unusual, maybe this should be an error\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tseenColumns.set(columnType);\r\n\r\n\t\tunsigned skipColumns = 0;\r\n\t\tif (field.column() > lastColumn)\r\n\t\t\tskipColumns = field.column() - lastColumn - 1;\r\n\t\tlastColumn = field.column();\r\n\r\n\t\t*begin = { columnType, skipColumns };\r\n\t\t++begin;\r\n\t}\r\n\r\n\t// Incrementing the iterator causes it to read to the end of the record in case we broke early (maybe there were extra columns)\r\n\t++firstRecord;\r\n\tif (firstRecord == this->end()) {\r\n\t\treturn tl::unexpected { Error::NoContent };\r\n\t}\r\n\r\n\tbody_ = firstRecord.data();\r\n\r\n\tif (begin != end) {\r\n\t\treturn tl::unexpected { Error::NotEnoughColumns };\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, DataFile::Error> DataFile::skipHeader()\r\n{\r\n\tRecordIterator it { data(), data() + size(), false };\r\n\t++it;\r\n\tif (it == this->end()) {\r\n\t\treturn tl::unexpected { Error::NoContent };\r\n\t}\r\n\tbody_ = it.data();\r\n\treturn {};\r\n}\r\n\r\nvoid DataFile::skipHeaderOrDie(std::string_view path)\r\n{\r\n\tif (tl::expected<void, DataFile::Error> result = skipHeader(); !result.has_value()) {\r\n\t\tDataFile::reportFatalError(result.error(), path);\r\n\t}\r\n}\r\n\r\n[[nodiscard]] size_t DataFile::numRecords() const\r\n{\r\n\tif (content_.empty()) return 0;\r\n\tconst auto numNewlines = static_cast<size_t>(c_count(content_, '\\n') + (content_.back() == '\\n' ? 0 : 1));\r\n\tif (numNewlines < 2) return 0;\r\n\treturn static_cast<size_t>(numNewlines - 1);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/file.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <limits>\r\n#include <memory>\r\n#include <string_view>\r\n\r\n#include <expected.hpp>\r\n#include <function_ref.hpp>\r\n\r\n#include \"iterators.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstruct ColumnDefinition {\r\n\tenum class Error {\r\n\t\tUnknownColumn\r\n\t};\r\n\r\n\tuint8_t type = std::numeric_limits<uint8_t>::max();\r\n\r\n\t// The number of fields between this column and the last one identified as important (or from start of the record if this is the first column we care about)\r\n\tunsigned skipLength = 0;\r\n\r\n\tbool operator==(const ColumnDefinition &other) const = default;\r\n\r\n\ttemplate <typename T>\r\n\texplicit operator T() const\r\n\t{\r\n\t\treturn static_cast<T>(type);\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief Container for a tab-delimited file following the TSV-like format described in txtdata/Readme.md\r\n */\r\nclass DataFile {\r\n\tstd::unique_ptr<const char[]> data_;\r\n\tstd::string_view content_;\r\n\r\n\tconst char *body_;\r\n\r\n\tDataFile() = delete;\r\n\r\n\t/**\r\n\t * @brief Creates a view over a sequence of utf8 code units, skipping over the BOM if present\r\n\t * @param data pointer to the raw data backing the view (this container will take ownership to ensure the lifetime of the view)\r\n\t * @param size total number of bytes/code units including the BOM if present\r\n\t */\r\n\tDataFile(std::unique_ptr<const char[]> &&data, size_t size)\r\n\t    : data_(std::move(data))\r\n\t    , content_(data_.get(), size)\r\n\t{\r\n\t\tconstexpr std::string_view utf8BOM = \"\\xef\\xbb\\xbf\";\r\n\t\tif (this->content_.starts_with(utf8BOM))\r\n\t\t\tthis->content_.remove_prefix(utf8BOM.size());\r\n\r\n\t\tbody_ = this->content_.data();\r\n\t}\r\n\r\npublic:\r\n\tenum class Error {\r\n\t\tNotFound,\r\n\t\tOpenFailed,\r\n\t\tBadRead,\r\n\t\tNoContent,\r\n\t\tNotEnoughColumns\r\n\t};\r\n\r\n\t/**\r\n\t * @brief Attempts to load a data file (using the same mechanism as other runtime assets)\r\n\t *\r\n\t * @param path file to load including the /txtdata/ prefix\r\n\t * @return an object containing an owned pointer to an in-memory copy of the file\r\n\t *         or an error code describing the reason for failure.\r\n\t */\r\n\tstatic tl::expected<DataFile, Error> load(std::string_view path);\r\n\r\n\tstatic DataFile loadOrDie(std::string_view path);\r\n\r\n\tstatic void reportFatalError(Error code, std::string_view fileName);\r\n\tstatic void reportFatalFieldError(DataFileField::Error code, std::string_view fileName, std::string_view fieldName, const DataFileField &field, std::string_view details = {});\r\n\r\n\tvoid resetHeader()\r\n\t{\r\n\t\tbody_ = content_.data();\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Attempts to parse the first row/record in the file, populating the range defined by [begin, end) using the provided mapping function\r\n\t *\r\n\t * This method will also set an internal marker so that future uses of the begin iterator skip the header line.\r\n\t * @param begin Start of the destination range\r\n\t * @param end End of the destination range\r\n\t * @param mapper Function that maps from a string_view to a unique numeric identifier for the column\r\n\t * @return If the file ends after the header or not enough columns were defined this function returns an error code describing the failure.\r\n\t */\r\n\t[[nodiscard]] tl::expected<void, DataFile::Error> parseHeader(ColumnDefinition *begin, ColumnDefinition *end, tl::function_ref<tl::expected<uint8_t, ColumnDefinition::Error>(std::string_view)> mapper);\r\n\r\n\t/**\r\n\t * @brief Templated version of parseHeader(uint8_t) to allow using directly with enum definitions of columns\r\n\t * @tparam T An enum or any type that defines operator uint8_t()\r\n\t * @param begin Start of the destination range\r\n\t * @param end End of the destination range\r\n\t * @param typedMapper Function that maps from a string_view to a unique T value\r\n\t * @return A void success result or an error code as described above\r\n\t */\r\n\ttemplate <typename T>\r\n\t[[nodiscard]] tl::expected<void, DataFile::Error> parseHeader(ColumnDefinition *begin, ColumnDefinition *end, std::function<tl::expected<T, ColumnDefinition::Error>(std::string_view)> typedMapper)\r\n\t{\r\n\t\treturn parseHeader(begin, end, [typedMapper](std::string_view label) { return typedMapper(label).transform([](T value) { return static_cast<uint8_t>(value); }); });\r\n\t}\r\n\r\n\t[[nodiscard]] tl::expected<void, DataFile::Error> skipHeader();\r\n\r\n\tvoid skipHeaderOrDie(std::string_view path);\r\n\r\n\t[[nodiscard]] RecordIterator begin() const\r\n\t{\r\n\t\treturn { body_, data() + size(), body_ != data() };\r\n\t}\r\n\r\n\t[[nodiscard]] RecordIterator end() const\r\n\t{\r\n\t\treturn {};\r\n\t}\r\n\r\n\t// Assumes a header\r\n\t[[nodiscard]] size_t numRecords() const;\r\n\r\n\t[[nodiscard]] const char *data() const\r\n\t{\r\n\t\treturn content_.data();\r\n\t}\r\n\r\n\t[[nodiscard]] size_t size() const\r\n\t{\r\n\t\treturn content_.size();\r\n\t}\r\n};\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/iterators.hpp",
    "content": "#pragma once\r\n\r\n#include <charconv>\r\n#include <optional>\r\n#include <ostream>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"parser.hpp\"\r\n#include \"utils/parse_int.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nclass DataFileField {\r\n\tGetFieldResult *state_;\r\n\tconst char *end_;\r\n\tunsigned row_;\r\n\tunsigned column_;\r\n\r\npublic:\r\n\tenum class Error {\r\n\t\tNotANumber,\r\n\t\tOutOfRange,\r\n\t\tInvalidValue\r\n\t};\r\n\r\n\tstatic tl::expected<void, Error> mapError(std::errc ec)\r\n\t{\r\n\t\tif (ec == std::errc())\r\n\t\t\treturn {};\r\n\t\tswitch (ec) {\r\n\t\tcase std::errc::result_out_of_range:\r\n\t\t\treturn tl::unexpected { Error::OutOfRange };\r\n\t\tcase std::errc::invalid_argument:\r\n\t\t\treturn tl::unexpected { Error::NotANumber };\r\n\t\tdefault:\r\n\t\t\treturn tl::unexpected { Error::InvalidValue };\r\n\t\t}\r\n\t}\r\n\r\n\tstatic tl::expected<void, Error> mapError(ParseIntError ec)\r\n\t{\r\n\t\tswitch (ec) {\r\n\t\tcase ParseIntError::OutOfRange:\r\n\t\t\treturn tl::unexpected { Error::OutOfRange };\r\n\t\tcase ParseIntError::ParseError:\r\n\t\t\treturn tl::unexpected { Error::NotANumber };\r\n\t\tdefault:\r\n\t\t\treturn tl::unexpected { Error::InvalidValue };\r\n\t\t}\r\n\t}\r\n\r\n\tDataFileField(GetFieldResult *state, const char *end, unsigned row, unsigned column)\r\n\t    : state_(state)\r\n\t    , end_(end)\r\n\t    , row_(row)\r\n\t    , column_(column)\r\n\t{\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a view of the current field\r\n\t *\r\n\t * This method scans the current field if this is the first value access since the last\r\n\t * advance. If you expect the field to contain a numeric value then calling parseInt first\r\n\t * is more efficient, but calling the methods in either order is supported.\r\n\t * @return The current field value (may be an empty string) or a zero length string_view\r\n\t */\r\n\t[[nodiscard]] std::string_view value()\r\n\t{\r\n\t\tif (state_->status == GetFieldResult::Status::ReadyToRead) {\r\n\t\t\t*state_ = GetNextField(state_->next, end_);\r\n\t\t}\r\n\t\treturn state_->value;\r\n\t}\r\n\r\n\t/**\r\n\t * Convenience function to let DataFileField instances be used like other single-value STL containers\r\n\t */\r\n\t[[nodiscard]] std::string_view operator*()\r\n\t{\r\n\t\treturn this->value();\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Attempts to parse the current field as a numeric value using std::from_chars\r\n\t *\r\n\t * You can freely interleave this method with calls to operator*. If this is the first value\r\n\t * access since the last advance this will scan the current field and store it for later\r\n\t * use with operator* or repeated calls to parseInt (even with different types).\r\n\t * @tparam T an Integral type supported by std::from_chars\r\n\t * @param destination value to store the result of successful parsing\r\n\t * @return an error code corresponding to the from_chars result if parsing failed\r\n\t */\r\n\ttemplate <typename T>\r\n\t[[nodiscard]] tl::expected<void, Error> parseInt(T &destination)\r\n\t{\r\n\t\tstd::from_chars_result result {};\r\n\t\tif (state_->status == GetFieldResult::Status::ReadyToRead) {\r\n\t\t\tconst char *begin = state_->next;\r\n\t\t\tresult = std::from_chars(begin, end_, destination);\r\n\t\t\tif (result.ec != std::errc::invalid_argument) {\r\n\t\t\t\t// from_chars was able to consume at least one character, consume the rest of the field\r\n\t\t\t\t*state_ = GetNextField(result.ptr, end_);\r\n\t\t\t\t// and prepend what was already parsed\r\n\t\t\t\tstate_->value = { begin, (state_->value.data() - begin) + state_->value.size() };\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tresult = std::from_chars(state_->value.data(), end_, destination);\r\n\t\t}\r\n\r\n\t\treturn mapError(result.ec);\r\n\t}\r\n\r\n\t[[nodiscard]] tl::expected<void, Error> parseBool(bool &destination)\r\n\t{\r\n\t\tconst std::string_view str = value();\r\n\t\tif (str == \"true\") {\r\n\t\t\tdestination = true;\r\n\t\t\treturn {};\r\n\t\t}\r\n\t\tif (str == \"false\") {\r\n\t\t\tdestination = false;\r\n\t\t\treturn {};\r\n\t\t}\r\n\t\treturn tl::make_unexpected(DataFileField::Error::InvalidValue);\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\t[[nodiscard]] tl::expected<void, Error> parseIntArray(T *destination, size_t n)\r\n\t{\r\n\t\tsize_t i = 0;\r\n\t\tfor (const std::string_view part : SplitByChar(value(), ',')) {\r\n\t\t\tif (i == n)\r\n\t\t\t\treturn tl::make_unexpected(Error::InvalidValue);\r\n\t\t\tconst std::from_chars_result result\r\n\t\t\t    = std::from_chars(part.data(), part.data() + part.size(), destination[i]);\r\n\t\t\tif (result.ec != std::errc())\r\n\t\t\t\treturn mapError(result.ec);\r\n\t\t\t++i;\r\n\t\t}\r\n\t\tif (i != n)\r\n\t\t\treturn tl::make_unexpected(Error::InvalidValue);\r\n\t\treturn {};\r\n\t}\r\n\r\n\ttemplate <typename T, size_t N>\r\n\t[[nodiscard]] tl::expected<void, Error> parseIntArray(T (&destination)[N])\r\n\t{\r\n\t\treturn parseIntArray<T>(destination, N);\r\n\t}\r\n\r\n\ttemplate <typename T, size_t N>\r\n\t[[nodiscard]] tl::expected<void, Error> parseIntArray(std::array<T, N> &destination)\r\n\t{\r\n\t\treturn parseIntArray<T>(destination.data(), N);\r\n\t}\r\n\r\n\ttemplate <typename T, typename ParseFn>\r\n\t[[nodiscard]] tl::expected<void, std::string> parseEnumArray(T *destination, size_t n, std::optional<T> fillMissing, ParseFn &&parseFn)\r\n\t{\r\n\t\tsize_t i = 0;\r\n\t\tconst std::string_view str = value();\r\n\t\tif (!str.empty()) {\r\n\t\t\tfor (const std::string_view part : SplitByChar(str, ',')) {\r\n\t\t\t\tif (i == n)\r\n\t\t\t\t\treturn tl::make_unexpected(StrCat(\"Too many values, max: \", n));\r\n\t\t\t\tauto result = parseFn(part);\r\n\t\t\t\tif (!result.has_value()) {\r\n\t\t\t\t\treturn tl::make_unexpected(std::move(result).error());\r\n\t\t\t\t}\r\n\t\t\t\tdestination[i++] = *result;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (i != n) {\r\n\t\t\tif (!fillMissing.has_value()) {\r\n\t\t\t\treturn tl::make_unexpected(StrCat(\"Too few values, expected \", n, \" got \", i));\r\n\t\t\t}\r\n\t\t\twhile (i < n) {\r\n\t\t\t\tdestination[i++] = *fillMissing;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\r\n\ttemplate <typename T, size_t N, typename ParseFn>\r\n\t[[nodiscard]] tl::expected<void, std::string> parseEnumArray(T (&destination)[N], std::optional<T> fillMissing, ParseFn &&parseFn)\r\n\t{\r\n\t\treturn parseEnumArray<T, ParseFn>(destination, N, std::move(fillMissing), std::forward<ParseFn>(parseFn));\r\n\t}\r\n\r\n\ttemplate <typename T, size_t N, typename ParseFn>\r\n\t[[nodiscard]] tl::expected<void, std::string> parseIntArray(std::array<T, N> &destination, std::optional<T> fillMissing, ParseFn &&parseFn)\r\n\t{\r\n\t\treturn parseEnumArray<T, ParseFn>(destination.data(), N, std::move(fillMissing), std::forward<ParseFn>(parseFn));\r\n\t}\r\n\r\n\ttemplate <typename T, typename ParseFn>\r\n\t[[nodiscard]] tl::expected<void, std::string> parseEnumList(T &destination, ParseFn &&parseFn)\r\n\t{\r\n\t\tdestination = {};\r\n\t\tconst std::string_view str = value();\r\n\t\tif (str.empty())\r\n\t\t\treturn {};\r\n\t\tfor (const std::string_view part : SplitByChar(str, ',')) {\r\n\t\t\tauto result = parseFn(part);\r\n\t\t\tif (!result.has_value())\r\n\t\t\t\treturn tl::make_unexpected(std::move(result).error());\r\n\t\t\tdestination |= result.value();\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\t[[nodiscard]] tl::expected<T, Error> asInt()\r\n\t{\r\n\t\tT value = 0;\r\n\t\treturn parseInt(value).map([value]() { return value; });\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Attempts to parse the current field as a fixed point value with 6 bits for the fraction\r\n\t *\r\n\t * You can freely interleave this method with calls to operator*. If this is the first value\r\n\t * access since the last advance this will scan the current field and store it for later\r\n\t * use with operator* or repeated calls to parseInt/Fixed6 (even with different types).\r\n\t * @tparam T an Integral type supported by std::from_chars\r\n\t * @param destination value to store the result of successful parsing\r\n\t * @return an error code equivalent to what you'd get from from_chars if parsing failed\r\n\t */\r\n\ttemplate <typename T>\r\n\t[[nodiscard]] tl::expected<void, Error> parseFixed6(T &destination)\r\n\t{\r\n\t\tParseIntResult<T> parseResult;\r\n\t\tif (state_->status == GetFieldResult::Status::ReadyToRead) {\r\n\t\t\tconst char *begin = state_->next;\r\n\t\t\t// first read, consume digits\r\n\t\t\tparseResult = ParseFixed6<T>({ begin, static_cast<size_t>(end_ - begin) }, &state_->next);\r\n\t\t\t// then read the remainder of the field\r\n\t\t\t*state_ = GetNextField(state_->next, end_);\r\n\t\t\t// and prepend what was already parsed\r\n\t\t\tstate_->value = { begin, (state_->value.data() - begin) + state_->value.size() };\r\n\t\t} else {\r\n\t\t\tparseResult = ParseFixed6<T>(state_->value);\r\n\t\t}\r\n\r\n\t\tif (parseResult.has_value()) {\r\n\t\t\tdestination = parseResult.value();\r\n\t\t\treturn {};\r\n\t\t} else {\r\n\t\t\treturn mapError(parseResult.error());\r\n\t\t}\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\t[[nodiscard]] tl::expected<T, Error> asFixed6()\r\n\t{\r\n\t\tT value = 0;\r\n\t\treturn parseFixed6(value).map([value]() { return value; });\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the current row number\r\n\t */\r\n\t[[nodiscard]] unsigned row() const\r\n\t{\r\n\t\treturn row_;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the current column/field number (from the start of the row/record)\r\n\t */\r\n\t[[nodiscard]] unsigned column() const\r\n\t{\r\n\t\treturn column_;\r\n\t}\r\n\r\n\t/**\r\n\t * Allows accessing the value of this field in a const context\r\n\t *\r\n\t * This requires an actual non-const value access to happen first before it returns\r\n\t * any useful results, intended for use in error reporting (or test output).\r\n\t */\r\n\t[[nodiscard]] std::string_view currentValue() const\r\n\t{\r\n\t\treturn state_->value;\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief Show the field value along with the row/column number (mainly used in test failure messages)\r\n * @param stream output stream, expected to have overloads for unsigned, std::string_view, and char*\r\n * @param field Object to display\r\n * @return the stream, to allow chaining\r\n */\r\ninline std::ostream &operator<<(std::ostream &stream, const DataFileField &field)\r\n{\r\n\treturn stream << \"\\\"\" << field.currentValue() << \"\\\" (at row \" << field.row() << \", column \" << field.column() << \")\";\r\n}\r\n\r\nclass FieldIterator {\r\n\tGetFieldResult *state_;\r\n\tconst char *const end_;\r\n\tconst unsigned row_;\r\n\tunsigned column_ = 0;\r\n\r\npublic:\r\n\tusing iterator_category = std::input_iterator_tag;\r\n\tusing value_type = DataFileField;\r\n\r\n\tFieldIterator()\r\n\t    : state_(nullptr)\r\n\t    , end_(nullptr)\r\n\t    , row_(0)\r\n\t{\r\n\t}\r\n\r\n\tFieldIterator(GetFieldResult *state, const char *end, unsigned row)\r\n\t    : state_(state)\r\n\t    , end_(end)\r\n\t    , row_(row)\r\n\t{\r\n\t\tstate_->status = GetFieldResult::Status::ReadyToRead;\r\n\t}\r\n\r\n\t[[nodiscard]] bool operator==(const FieldIterator &rhs) const\r\n\t{\r\n\t\tif (state_ == nullptr && rhs.state_ == nullptr)\r\n\t\t\treturn true;\r\n\r\n\t\treturn state_ != nullptr && rhs.state_ != nullptr && state_->next == rhs.state_->next;\r\n\t}\r\n\r\n\t[[nodiscard]] bool operator!=(const FieldIterator &rhs) const\r\n\t{\r\n\t\treturn !(*this == rhs);\r\n\t}\r\n\r\n\t/**\r\n\t * Advances to the next field in the current record\r\n\t */\r\n\tFieldIterator &operator++()\r\n\t{\r\n\t\treturn *this += 1;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Advances by the specified number of fields\r\n\t *\r\n\t * if a non-zero increment is provided and advancing the iterator causes it to reach the end\r\n\t * of the record the iterator is invalidated. It will compare equal to an end iterator and\r\n\t * cannot be used for value access or any further parsing\r\n\t * @param increment how many fields to advance (can be 0)\r\n\t * @return self-reference\r\n\t */\r\n\tFieldIterator &operator+=(unsigned increment)\r\n\t{\r\n\t\tif (increment == 0)\r\n\t\t\treturn *this;\r\n\r\n\t\tif (state_->status == GetFieldResult::Status::ReadyToRead) {\r\n\t\t\t// We never read the value and no longer need it, discard it so that we end up\r\n\t\t\t//  advancing past the field delimiter (as if a value access had happened)\r\n\t\t\t*state_ = DiscardField(state_->next, end_);\r\n\t\t}\r\n\r\n\t\tif (state_->endOfRecord()) {\r\n\t\t\tstate_ = nullptr;\r\n\t\t} else {\r\n\t\t\tunsigned fieldsSkipped = 0;\r\n\t\t\t// By this point we've already advanced past the end of this field (either because the\r\n\t\t\t//  last value access found the end of the field by necessity or we discarded it a few\r\n\t\t\t//  lines up), so we only need to advance further if an increment greater than 1 was\r\n\t\t\t//  provided.\r\n\t\t\t*state_ = DiscardMultipleFields(state_->next, end_, increment - 1, &fieldsSkipped);\r\n\t\t\t// As we've consumed the current field by this point we need to increment the internal\r\n\t\t\t//  column counter one extra time so we have an accurate value.\r\n\t\t\tcolumn_ += fieldsSkipped + 1;\r\n\t\t\t// We use Status::ReadyToRead as a marker so we only read the next value on the next\r\n\t\t\t//  value access, this allows consumers to choose the most efficient method (e.g. if\r\n\t\t\t//  they want the value as an int) or even repeated advances without using a value.\r\n\t\t\tstate_->status = GetFieldResult::Status::ReadyToRead;\r\n\t\t}\r\n\t\treturn *this;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a view of the current field\r\n\t *\r\n\t * The returned value is a thin wrapper over the current state of this iterator (or last\r\n\t * successful read if incrementing this iterator would result in it reaching the end state).\r\n\t */\r\n\t[[nodiscard]] value_type operator*()\r\n\t{\r\n\t\treturn { state_, end_, row_, column_ };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns the current row number\r\n\t */\r\n\t[[nodiscard]] unsigned row() const\r\n\t{\r\n\t\treturn row_;\r\n\t}\r\n\t/**\r\n\t * @brief Returns the current column/field number (from the start of the row/record)\r\n\t */\r\n\t[[nodiscard]] unsigned column() const\r\n\t{\r\n\t\treturn column_;\r\n\t}\r\n};\r\n\r\nclass DataFileRecord {\r\n\tGetFieldResult *state_;\r\n\tconst char *const end_;\r\n\tconst unsigned row_;\r\n\r\npublic:\r\n\tDataFileRecord(GetFieldResult *state, const char *end, unsigned row)\r\n\t    : state_(state)\r\n\t    , end_(end)\r\n\t    , row_(row)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] FieldIterator begin()\r\n\t{\r\n\t\treturn { state_, end_, row_ };\r\n\t}\r\n\r\n\t[[nodiscard]] FieldIterator end() const\r\n\t{\r\n\t\treturn {};\r\n\t}\r\n\r\n\t[[nodiscard]] unsigned row() const\r\n\t{\r\n\t\treturn row_;\r\n\t}\r\n};\r\n\r\nclass RecordIterator {\r\n\tGetFieldResult state_;\r\n\tconst char *const end_;\r\n\tunsigned row_ = 0;\r\n\r\npublic:\r\n\tusing iterator_category = std::forward_iterator_tag;\r\n\tusing value_type = DataFileRecord;\r\n\r\n\tRecordIterator()\r\n\t    : state_(nullptr, GetFieldResult::Status::EndOfFile)\r\n\t    , end_(nullptr)\r\n\t{\r\n\t}\r\n\r\n\tRecordIterator(const char *begin, const char *end, bool skippedHeader)\r\n\t    : state_(begin)\r\n\t    , end_(end)\r\n\t    , row_(skippedHeader ? 1 : 0)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] bool operator==(const RecordIterator &rhs) const\r\n\t{\r\n\t\treturn state_.next == rhs.state_.next;\r\n\t}\r\n\r\n\t[[nodiscard]] bool operator!=(const RecordIterator &rhs) const\r\n\t{\r\n\t\treturn !(*this == rhs);\r\n\t}\r\n\r\n\tRecordIterator &operator++()\r\n\t{\r\n\t\treturn *this += 1;\r\n\t}\r\n\r\n\tRecordIterator &operator+=(unsigned increment)\r\n\t{\r\n\t\tif (increment == 0)\r\n\t\t\treturn *this;\r\n\r\n\t\tif (!state_.endOfRecord()) {\r\n\t\t\t// The field iterator either hasn't been used or hasn't consumed the entire record\r\n\t\t\tstate_ = DiscardRemainingFields(state_.next, end_);\r\n\t\t}\r\n\r\n\t\tif (state_.endOfFile()) {\r\n\t\t\tstate_.next = nullptr;\r\n\t\t} else {\r\n\t\t\tunsigned recordsSkipped = 0;\r\n\t\t\t// By this point we've already advanced past the end of this record (either because the\r\n\t\t\t//  last value access found the end of the record by necessity or we discarded any\r\n\t\t\t//  leftovers a few lines up), so we only need to advance further if an increment\r\n\t\t\t//  greater than 1 was provided.\r\n\t\t\tstate_ = DiscardMultipleRecords(state_.next, end_, increment - 1, &recordsSkipped);\r\n\t\t\t// As we've consumed the current record by this point we need to increment the internal\r\n\t\t\t//  row counter one extra time so we have an accurate value.\r\n\t\t\trow_ += recordsSkipped + 1;\r\n\t\t\t// We use Status::ReadyToRead as a marker in case the DataFileField iterator is never\r\n\t\t\t//  used, so the next call to operator+= will advance past the current record\r\n\t\t\tstate_.status = GetFieldResult::Status::ReadyToRead;\r\n\t\t}\r\n\t\treturn *this;\r\n\t}\r\n\r\n\t[[nodiscard]] DataFileRecord operator*()\r\n\t{\r\n\t\treturn { &state_, end_, row_ };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Exposes the current location of this input iterator.\r\n\t *\r\n\t * This is only expected to be used internally so the DataFile instance knows where the header\r\n\t * ends and the body begins. You probably don't want to use this directly.\r\n\t */\r\n\t[[nodiscard]] const char *data() const\r\n\t{\r\n\t\treturn state_.next;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns the current row/record number (from the start of the file)\r\n\t *\r\n\t * The header row is always considered row 0, however if you've called DataFile.parseHeader()\r\n\t * before calling DataFile.begin() then you'll get row 1 as the first record of the range.\r\n\t */\r\n\t[[nodiscard]] unsigned row() const\r\n\t{\r\n\t\treturn row_;\r\n\t}\r\n};\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/parser.cpp",
    "content": "#include \"parser.hpp\"\r\n\r\nnamespace devilution {\r\nGetFieldResult HandleRecordTerminator(const char *begin, const char *end)\r\n{\r\n\tif (begin == end) {\r\n\t\treturn { end, GetFieldResult::Status::NoFinalTerminator };\r\n\t}\r\n\r\n\tif (*begin == '\\r') {\r\n\t\t++begin;\r\n\t\tif (begin == end) {\r\n\t\t\treturn { end, GetFieldResult::Status::FileTruncated };\r\n\t\t}\r\n\t\t// carriage returns should be followed by a newline, so let's let the following checks handle it\r\n\t}\r\n\tif (*begin == '\\n') {\r\n\t\t++begin;\r\n\t\tif (begin == end) {\r\n\t\t\treturn { end, GetFieldResult::Status::EndOfFile };\r\n\t\t}\r\n\r\n\t\treturn { begin, GetFieldResult::Status::EndOfRecord };\r\n\t}\r\n\r\n\treturn { begin, GetFieldResult::Status::BadRecordTerminator };\r\n}\r\n\r\nGetFieldResult DiscardMultipleFields(const char *begin, const char *end, unsigned skipLength, unsigned *fieldsSkipped)\r\n{\r\n\tGetFieldResult result { begin };\r\n\tunsigned skipCount = 0;\r\n\twhile (skipCount < skipLength) {\r\n\t\t++skipCount;\r\n\t\tresult = DiscardField(result.next, end);\r\n\t\tif (result.endOfRecord()) {\r\n\t\t\t// Found the end of record early\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (fieldsSkipped != nullptr) {\r\n\t\t*fieldsSkipped = skipCount;\r\n\t}\r\n\treturn result;\r\n}\r\n\r\nGetFieldResult DiscardMultipleRecords(const char *begin, const char *end, unsigned skipLength, unsigned *recordsSkipped)\r\n{\r\n\tGetFieldResult result { begin };\r\n\tunsigned skipCount = 0;\r\n\twhile (skipCount < skipLength) {\r\n\t\t++skipCount;\r\n\t\tresult = DiscardRemainingFields(result.next, end);\r\n\t\tif (result.endOfFile()) {\r\n\t\t\t// Found the end of file early\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (recordsSkipped != nullptr) {\r\n\t\t*recordsSkipped = skipCount;\r\n\t}\r\n\treturn result;\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/parser.hpp",
    "content": "#pragma once\r\n\r\n#include <algorithm>\r\n#include <string_view>\r\n\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstruct GetFieldResult {\r\n\tstd::string_view value;\r\n\r\n\tconst char *next = nullptr;\r\n\r\n\tenum class Status {\r\n\t\tReadyToRead,\r\n\t\tEndOfField,\r\n\t\tEndOfRecord,\r\n\t\tBadRecordTerminator,\r\n\t\tEndOfFile,\r\n\t\tFileTruncated,\r\n\t\tNoFinalTerminator\r\n\t} status\r\n\t    = Status::ReadyToRead;\r\n\r\n\tGetFieldResult() = default;\r\n\r\n\tGetFieldResult(const char *next)\r\n\t    : value()\r\n\t    , next(next)\r\n\t    , status(Status::ReadyToRead)\r\n\t{\r\n\t}\r\n\r\n\tGetFieldResult(const char *next, const Status &status)\r\n\t    : value()\r\n\t    , next(next)\r\n\t    , status(status)\r\n\t{\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Recreates a GetFieldResult with a new value\r\n\t */\r\n\tGetFieldResult(std::string_view value, const GetFieldResult &result)\r\n\t    : value(value)\r\n\t    , next(result.next)\r\n\t    , status(result.status)\r\n\t{\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns true if the last read reached the end of the current record\r\n\t */\r\n\t[[nodiscard]] bool endOfRecord() const\r\n\t{\r\n\t\treturn IsAnyOf(status, Status::EndOfRecord, Status::BadRecordTerminator) || endOfFile();\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns true if the last read reached the end of the file/stream\r\n\t */\r\n\t[[nodiscard]] bool endOfFile() const\r\n\t{\r\n\t\treturn IsAnyOf(status, Status::EndOfFile, Status::FileTruncated, Status::NoFinalTerminator);\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief Checks if this character is potentially part of a record terminator sequence\r\n * @param c character to check\r\n * @return true if it's a record terminator (lf) or carriage return (cr, accepted as the start of a crlf pair)\r\n */\r\nconstexpr bool IsRecordTerminator(char c)\r\n{\r\n\treturn c == '\\r' || c == '\\n';\r\n}\r\n\r\n/**\r\n * @brief Checks if this character is a field separator\r\n *\r\n * Note that record terminator sequences also act to separate fields\r\n * @param c character to check\r\n * @return true if it's a field separator (tab) or part of a record terminator sequence\r\n */\r\nconstexpr bool IsFieldSeparator(char c)\r\n{\r\n\treturn c == '\\t' || IsRecordTerminator(c);\r\n}\r\n\r\n/**\r\n * @brief Consumes the current record terminator sequence and returns a result describing whether at least one more record is available.\r\n *\r\n * Assumes that begin points to a record terminator (lf or crlf) or the last read reached the end\r\n * of the final record (in which case the terminator is optional). If we reached the end of the\r\n * stream (`begin == end`) then `status` will compare equal to Status::NoFinalTerminator. If we\r\n * found a carriage return (cr) character just before the end of the stream then it's likely the\r\n * file was truncated, `status` will contain Status::FileTruncated. If we found a carriage return\r\n * that is followed by any character other than a newline (lf), or `begin` didn't point to a record\r\n * terminator, then `status` will be Status::BadRecordTerminator and the file has probably been\r\n * mangled. Otherwise `status` will be Status::EndOfRecord at least one more record is available or\r\n * Status::EndOfFile if this was the end of the last record.\r\n * @param begin start of a stream (expected to be pointing to a record terminator)\r\n * @param end one past the last character of the stream\r\n * @return a struct containing a pointer to the start of the next record (if more characters are\r\n *          available) or a copy of end, and a status code describing the terminator.\r\n */\r\nGetFieldResult HandleRecordTerminator(const char *begin, const char *end);\r\n\r\n/**\r\n * @brief Consumes the current field (or record) separator and returns a result describing whether at least one more field is available.\r\n *\r\n * Assumes that begin points to a field or record separator (tab, cr, lf, or EOF). If there are\r\n * more fields in the current record then the return value will have a pointer to the start of the\r\n * next field and `status` will be GetFieldResult::Status::EndOfField. Otherwise refer to\r\n * HandleRecordTerminator for a description of the different codes.\r\n * @param begin start of a stream (expected to be pointing to a record separator)\r\n * @param end one past the last character of the stream\r\n * @return a struct containing a pointer to the start of the next field (if more characters are\r\n *          available) or a copy of end, and optionally an error code describing what type of\r\n *          separator was found.\r\n */\r\ninline GetFieldResult HandleFieldSeparator(const char *begin, const char *end)\r\n{\r\n\tif (begin != end && *begin == '\\t') {\r\n\t\treturn { begin + 1, GetFieldResult::Status::EndOfField };\r\n\t}\r\n\r\n\treturn HandleRecordTerminator(begin, end);\r\n}\r\n\r\n/**\r\n * @brief Advances to the next field separator without saving any characters\r\n * @param begin first character of the stream\r\n * @param end one past the last character in the stream\r\n * @return a GetFieldResult struct containing an empty value, a pointer to the start of the next\r\n *          field/record, and a status code describing what type of separator was found\r\n */\r\ninline GetFieldResult DiscardField(const char *begin, const char *end)\r\n{\r\n\tconst char *nextSeparator = std::find_if(begin, end, IsFieldSeparator);\r\n\r\n\treturn HandleFieldSeparator(nextSeparator, end);\r\n}\r\n\r\n/**\r\n * @brief Advances by the specified number of fields or until the end of the record, whichever occurs first\r\n * @param begin first character of the stream\r\n * @param end one past the last character in the stream\r\n * @param skipLength how many fields to skip (specifying 0 will cause the method to return without advancing)\r\n * @param fieldsSkipped optional output parameter, will be filled with a count of how many fields\r\n *                       were skipped in case the end of record was reached early\r\n * @return a GetFieldResult struct containing an empty value, a pointer to the start of the next\r\n *          field/record, and a status code describing what type of separator was found\r\n */\r\nGetFieldResult DiscardMultipleFields(const char *begin, const char *end, unsigned skipLength, unsigned *fieldsSkipped = nullptr);\r\n\r\n/**\r\n * @brief Advances by the specified number of records or until the end of the file, whichever occurs first\r\n * @param begin first character of the stream\r\n * @param end one past the last character in the stream\r\n * @param skipLength how many records to skip (specifying 0 will cause the method to return without advancing)\r\n * @param recordsSkipped optional output parameter, will be filled with a count of how many records\r\n *                        were skipped in case the end of file was reached early\r\n * @return a GetFieldResult struct containing an empty value, a pointer to the start of the next\r\n *          record, and a status code describing what type of separator was found\r\n */\r\nGetFieldResult DiscardMultipleRecords(const char *begin, const char *end, unsigned skipLength, unsigned *recordsSkipped = nullptr);\r\n\r\n/**\r\n * @brief Discard any remaining fields in the current record\r\n * @param begin pointer to the current character in the stream\r\n * @param end one past the last character in the stream\r\n * @return a GetFieldResult struct containing an empty value, the start of the next record (or\r\n *          `end`), and a status describing whether more records are available\r\n */\r\ninline GetFieldResult DiscardRemainingFields(const char *begin, const char *end)\r\n{\r\n\tconst char *nextSeparator = std::find_if(begin, end, IsRecordTerminator);\r\n\r\n\treturn HandleRecordTerminator(nextSeparator, end);\r\n}\r\n\r\n/**\r\n * @brief Returns a view of the next field from a tab-delimited stream.\r\n *\r\n * Note that the result *always* contains a value after calling this function as a zero-length\r\n * field is a valid value. This function consumes the field separator whenever possible, the\r\n * `next` member of the returned type will be either the start of the next field/record or `end`.\r\n * The `status` member contains additional information to distinguish between the end of a field\r\n * and the end of a record. If there are additional fields in this record then `status` will be\r\n * GetFieldResult::Status::EndOfField, otherwise refer to HandleRecordTerminator for the meanings\r\n * associated with the remaining codes.\r\n * @param begin first character of the stream\r\n * @param end one past the last character in the stream\r\n * @return a GetFieldResult struct containing a string_view of the field, the start of the next\r\n *          field/record, and a status code describing what type of separator was found\r\n */\r\ninline GetFieldResult GetNextField(const char *begin, const char *end)\r\n{\r\n\tconst char *nextSeparator = std::find_if(begin, end, IsFieldSeparator);\r\n\r\n\t// Can't use the string_view(It, It) constructor since that was only added in C++20...\r\n\treturn { { begin, static_cast<size_t>(nextSeparator - begin) }, HandleFieldSeparator(nextSeparator, end) };\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/record_reader.cpp",
    "content": "#include \"data/record_reader.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid RecordReader::advance()\r\n{\r\n\tif (needsIncrement_) {\r\n\t\t++it_;\r\n\t} else {\r\n\t\tneedsIncrement_ = true;\r\n\t}\r\n\tif (it_ == end_) {\r\n\t\tDataFile::reportFatalError(DataFile::Error::NotEnoughColumns, filename_);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/record_reader.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <string_view>\r\n#include <type_traits>\r\n\r\n#include <expected.hpp>\r\n#include <function_ref.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief A record reader that treats every error as fatal.\r\n */\r\nclass RecordReader {\r\npublic:\r\n\tRecordReader(DataFileRecord &record, std::string_view filename)\r\n\t    : it_(record.begin())\r\n\t    , end_(record.end())\r\n\t    , filename_(filename)\r\n\t{\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\ttypename std::enable_if_t<std::is_integral_v<T>, void>\r\n\treadInt(std::string_view name, T &out)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tfailOnError(field.parseInt(out), name, field);\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\ttypename std::enable_if_t<std::is_integral_v<T>, void>\r\n\treadOptionalInt(std::string_view name, T &out)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tif (field.value().empty()) return;\r\n\t\tfailOnError(field.parseInt(out), name, field);\r\n\t}\r\n\r\n\ttemplate <typename T, size_t N>\r\n\tvoid readIntArray(std::string_view name, T (&out)[N])\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tfailOnError(field.parseIntArray(out), name, field);\r\n\t}\r\n\r\n\ttemplate <typename T, size_t N, typename F>\r\n\tvoid readEnumArray(std::string_view name, std::optional<T> fillMissing, T (&out)[N], F &&parseFn)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tfailOnError(field.parseEnumArray(out, fillMissing, parseFn), name, field, DataFileField::Error::InvalidValue);\r\n\t}\r\n\r\n\ttemplate <typename T, size_t N>\r\n\tvoid readIntArray(std::string_view name, std::array<T, N> &out)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tfailOnError(field.parseIntArray(out), name, field);\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\ttypename std::enable_if_t<std::is_integral_v<T>, void>\r\n\treadFixed6(std::string_view name, T &out)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tfailOnError(field.parseFixed6(out), name, field);\r\n\t}\r\n\r\n\tvoid readBool(std::string_view name, bool &out)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tfailOnError(field.parseBool(out), name, field);\r\n\t}\r\n\r\n\tvoid readString(std::string_view name, std::string &out)\r\n\t{\r\n\t\tadvance();\r\n\t\tout = (*it_).value();\r\n\t}\r\n\r\n\ttemplate <typename T, typename F>\r\n\tvoid read(std::string_view name, T &out, F &&parseFn)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\ttl::expected<T, std::string> result = parseFn(field.value());\r\n\t\tfailOnError(result, name, field, DataFileField::Error::InvalidValue);\r\n\t\tout = *std::move(result);\r\n\t}\r\n\r\n\ttemplate <typename T, typename F>\r\n\tvoid readEnumList(std::string_view name, T &out, F &&parseFn)\r\n\t{\r\n\t\tDataFileField field = nextField();\r\n\t\tfailOnError(field.parseEnumList(out, std::forward<F>(parseFn)),\r\n\t\t    name, field, DataFileField::Error::InvalidValue);\r\n\t}\r\n\r\n\tstd::string_view value()\r\n\t{\r\n\t\tadvance();\r\n\t\tneedsIncrement_ = false;\r\n\t\treturn (*it_).value();\r\n\t}\r\n\r\n\tvoid advance();\r\n\r\n\tDataFileField nextField()\r\n\t{\r\n\t\tadvance();\r\n\t\treturn *it_;\r\n\t}\r\n\r\nprivate:\r\n\ttemplate <typename T>\r\n\tvoid failOnError(const tl::expected<T, DataFileField::Error> &result, std::string_view name, const DataFileField &field)\r\n\t{\r\n\t\tif (!result.has_value()) {\r\n\t\t\tDataFile::reportFatalFieldError(result.error(), filename_, name, field);\r\n\t\t}\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\tvoid failOnError(const tl::expected<T, std::string> &result, std::string_view name, const DataFileField &field, DataFileField::Error error)\r\n\t{\r\n\t\tif (!result.has_value()) {\r\n\t\t\tDataFile::reportFatalFieldError(error, filename_, name, field, result.error());\r\n\t\t}\r\n\t}\r\n\r\n\tFieldIterator it_;\r\n\tconst FieldIterator end_;\r\n\tstd::string_view filename_;\r\n\tbool needsIncrement_ = false;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/value_reader.cpp",
    "content": "#include \"data/value_reader.hpp\"\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"appfat.h\"\r\n\r\nnamespace devilution {\r\n\r\nValueReader::ValueReader(DataFile &dataFile, std::string_view filename)\r\n    : it_(dataFile.begin())\r\n    , end_(dataFile.end())\r\n    , filename_(filename)\r\n{\r\n}\r\n\r\nDataFileField ValueReader::getValueField(std::string_view expectedKey)\r\n{\r\n\tif (it_ == end_) {\r\n\t\tapp_fatal(fmt::format(\"Missing field {} in {}\", expectedKey, filename_));\r\n\t}\r\n\tDataFileRecord record = *it_;\r\n\tFieldIterator fieldIt = record.begin();\r\n\tconst FieldIterator endField = record.end();\r\n\r\n\tconst std::string_view key = (*fieldIt).value();\r\n\tif (key != expectedKey) {\r\n\t\tapp_fatal(fmt::format(\"Unexpected field in {}: got {}, expected {}\", filename_, key, expectedKey));\r\n\t}\r\n\r\n\t++fieldIt;\r\n\tif (fieldIt == endField) {\r\n\t\tDataFile::reportFatalError(DataFile::Error::NotEnoughColumns, filename_);\r\n\t}\r\n\treturn *fieldIt;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/data/value_reader.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <string_view>\r\n#include <type_traits>\r\n\r\n#include <expected.hpp>\r\n#include <function_ref.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief A value reader.\r\n */\r\nclass ValueReader {\r\npublic:\r\n\tValueReader(DataFile &dataFile, std::string_view filename);\r\n\r\n\tDataFileField getValueField(std::string_view expectedKey);\r\n\r\n\ttemplate <typename T, typename F>\r\n\tvoid readValue(std::string_view expectedKey, T &outValue, F &&readFn)\r\n\t{\r\n\t\tDataFileField valueField = getValueField(expectedKey);\r\n\t\tif (const tl::expected<void, devilution::DataFileField::Error> result = readFn(valueField, outValue);\r\n\t\t    !result.has_value()) {\r\n\t\t\tDataFile::reportFatalFieldError(result.error(), filename_, \"Value\", valueField);\r\n\t\t}\r\n\t\t++it_;\r\n\t}\r\n\r\n\ttemplate <typename T, typename F>\r\n\tvoid read(std::string_view expectedKey, T &outValue, F &&parseFn)\r\n\t{\r\n\t\treadValue(expectedKey, outValue, [&parseFn](DataFileField &valueField, T &outValue) -> tl::expected<void, devilution::DataFileField::Error> {\r\n\t\t\tconst auto result = parseFn(valueField.value());\r\n\t\t\tif (!result.has_value()) {\r\n\t\t\t\treturn tl::make_unexpected(devilution::DataFileField::Error::InvalidValue);\r\n\t\t\t}\r\n\r\n\t\t\toutValue = result.value();\r\n\t\t\treturn {};\r\n\t\t});\r\n\t}\r\n\r\n\ttemplate <typename T, typename F>\r\n\tvoid readEnumList(std::string_view expectedKey, T &outValue, F &&parseFn)\r\n\t{\r\n\t\treadValue(expectedKey, outValue, [&parseFn](DataFileField &valueField, T &outValue) -> tl::expected<void, devilution::DataFileField::Error> {\r\n\t\t\tconst auto result = valueField.parseEnumList(outValue, std::forward<F>(parseFn));\r\n\t\t\tif (!result.has_value()) {\r\n\t\t\t\treturn tl::make_unexpected(devilution::DataFileField::Error::InvalidValue);\r\n\t\t\t}\r\n\r\n\t\t\treturn {};\r\n\t\t});\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\ttypename std::enable_if_t<std::is_integral_v<T>, void>\r\n\treadInt(std::string_view expectedKey, T &outValue)\r\n\t{\r\n\t\treadValue(expectedKey, outValue, [](DataFileField &valueField, T &outValue) {\r\n\t\t\treturn valueField.parseInt(outValue);\r\n\t\t});\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\ttypename std::enable_if_t<std::is_integral_v<T>, void>\r\n\treadDecimal(std::string_view expectedKey, T &outValue)\r\n\t{\r\n\t\treadValue(expectedKey, outValue, [](DataFileField &valueField, T &outValue) {\r\n\t\t\treturn valueField.parseFixed6(outValue);\r\n\t\t});\r\n\t}\r\n\r\n\tvoid readString(std::string_view expectedKey, std::string &outValue)\r\n\t{\r\n\t\treadValue(expectedKey, outValue, [](DataFileField &valueField, std::string &outValue) {\r\n\t\t\toutValue = valueField.value();\r\n\t\t\treturn tl::expected<void, devilution::DataFileField::Error> {};\r\n\t\t});\r\n\t}\r\n\r\n\tvoid readChar(std::string_view expectedKey, char &outValue)\r\n\t{\r\n\t\treadValue(expectedKey, outValue, [](DataFileField &valueField, char &outValue) -> tl::expected<void, devilution::DataFileField::Error> {\r\n\t\t\tif (valueField.value().size() != 1) {\r\n\t\t\t\treturn tl::make_unexpected(devilution::DataFileField::Error::InvalidValue);\r\n\t\t\t}\r\n\r\n\t\t\toutValue = valueField.value().at(0);\r\n\t\t\treturn {};\r\n\t\t});\r\n\t}\r\n\r\nprivate:\r\n\tRecordIterator it_;\r\n\tconst RecordIterator end_;\r\n\tstd::string_view filename_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dead.cpp",
    "content": "/**\r\n * @file dead.cpp\r\n *\r\n * Implementation of functions for placing dead monsters.\r\n */\r\n#include \"dead.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"diablo.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"lighting.h\"\r\n#include \"monster.h\"\r\n#include \"tables/misdat.h\"\r\n\r\nnamespace devilution {\r\n\r\nCorpse Corpses[MaxCorpses];\r\nint8_t stonendx;\r\n\r\nnamespace {\r\nvoid InitDeadAnimationFromMonster(Corpse &corpse, const CMonster &mon)\r\n{\r\n\tconst AnimStruct &animData = mon.getAnimData(MonsterGraphic::Death);\r\n\tif (animData.sprites) {\r\n\t\tcorpse.sprites.emplace(*animData.sprites);\r\n\t} else {\r\n\t\tcorpse.sprites = std::nullopt;\r\n\t}\r\n\tcorpse.frame = animData.frames - 1;\r\n\tcorpse.width = animData.width;\r\n}\r\n\r\nvoid MoveLightToCorpse(Monster &monster)\r\n{\r\n\tfor (int dx = 0; dx < MAXDUNX; dx++) {\r\n\t\tfor (int dy = 0; dy < MAXDUNY; dy++) {\r\n\t\t\tif ((dCorpse[dx][dy] & 0x1F) == monster.corpseId) {\r\n\t\t\t\tChangeLightXY(monster.lightId, { dx, dy });\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tAddUnLight(monster.lightId);\r\n}\r\n} // namespace\r\n\r\nvoid InitCorpses()\r\n{\r\n\tint8_t mtypes[MaxMonsters] = {};\r\n\r\n\tint8_t nd = 0;\r\n\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tCMonster &monsterType = LevelMonsterTypes[i];\r\n\t\tif (mtypes[monsterType.type] != 0)\r\n\t\t\tcontinue;\r\n\r\n\t\tInitDeadAnimationFromMonster(Corpses[nd], monsterType);\r\n\t\tCorpses[nd].translationPaletteIndex = 0;\r\n\t\tnd++;\r\n\r\n\t\tmonsterType.corpseId = nd;\r\n\t\tmtypes[monsterType.type] = nd;\r\n\t}\r\n\r\n\tnd++; // Unused blood spatter\r\n\r\n\tif (!HeadlessMode)\r\n\t\tCorpses[nd].sprites.emplace(*GetMissileSpriteData(MissileGraphicID::StoneCurseShatter).sprites);\r\n\tCorpses[nd].frame = 11;\r\n\tCorpses[nd].width = 128;\r\n\tCorpses[nd].translationPaletteIndex = 0;\r\n\tnd++;\r\n\r\n\tstonendx = nd;\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tauto &monster = Monsters[ActiveMonsters[i]];\r\n\t\tif (monster.isUnique()) {\r\n\t\t\tInitDeadAnimationFromMonster(Corpses[nd], monster.type());\r\n\t\t\tCorpses[nd].translationPaletteIndex = ActiveMonsters[i] + 1;\r\n\t\t\tnd++;\r\n\r\n\t\t\tmonster.corpseId = nd;\r\n\t\t}\r\n\t}\r\n\r\n\tassert(static_cast<unsigned>(nd) <= MaxCorpses);\r\n}\r\n\r\nvoid AddCorpse(Point tilePosition, int8_t dv, Direction ddir)\r\n{\r\n\tdCorpse[tilePosition.x][tilePosition.y] = (dv & 0x1F) + (static_cast<int>(ddir) << 5);\r\n}\r\n\r\nvoid MoveLightsToCorpses()\r\n{\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tauto &monster = Monsters[ActiveMonsters[i]];\r\n\t\tif (!monster.isUnique())\r\n\t\t\tcontinue;\r\n\t\tMoveLightToCorpse(monster);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dead.h",
    "content": "/**\r\n * @file dead.h\r\n *\r\n * Interface of functions for placing dead monsters.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/direction.hpp\"\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstatic constexpr unsigned MaxCorpses = 31;\r\n\r\nstruct Corpse {\r\n\tOptionalClxSpriteListOrSheet sprites;\r\n\tint frame;\r\n\tuint16_t width;\r\n\tuint8_t translationPaletteIndex;\r\n\r\n\t/**\r\n\t * @brief Returns the sprite list for a given direction.\r\n\t *\r\n\t * @param direction One of the 16 directions. Valid range: [0, 15].\r\n\t * @return ClxSpriteList\r\n\t */\r\n\t[[nodiscard]] ClxSpriteList spritesForDirection(Direction direction) const\r\n\t{\r\n\t\treturn sprites->isSheet() ? sprites->sheet()[static_cast<size_t>(direction)] : sprites->list();\r\n\t}\r\n};\r\n\r\nextern Corpse Corpses[MaxCorpses];\r\nextern int8_t stonendx;\r\n\r\nvoid InitCorpses();\r\nvoid AddCorpse(Point tilePosition, int8_t dv, Direction ddir);\r\nvoid MoveLightsToCorpses();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/debug.cpp",
    "content": "/**\r\n * @file debug.cpp\r\n *\r\n * Implementation of debug functions.\r\n */\r\n\r\n#ifdef _DEBUG\r\n\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <cstdio>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"debug.h\"\r\n\r\n#include \"automap.h\"\r\n#include \"cursor.h\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"lighting.h\"\r\n#include \"missiles.h\"\r\n#include \"monster.h\"\r\n#include \"plrmsg.h\"\r\n#include \"utils/str_case.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::string TestMapPath;\r\nOptionalOwnedClxSpriteList pSquareCel;\r\nbool DebugToggle = false;\r\nbool DebugGodMode = false;\r\nbool DebugInvisible = false;\r\nbool DebugVision = false;\r\nbool DebugPath = false;\r\nbool DebugGrid = false;\r\nankerl::unordered_dense::map<int, Point> DebugCoordsMap;\r\nbool DebugScrollViewEnabled = false;\r\nstd::string debugTRN;\r\n\r\n// Used for debugging level generation\r\nuint32_t glMid1Seed[NUMLEVELS];\r\nuint32_t glMid2Seed[NUMLEVELS];\r\nuint32_t glMid3Seed[NUMLEVELS];\r\nuint32_t glEndSeed[NUMLEVELS];\r\n\r\nnamespace {\r\n\r\nDebugGridTextItem SelectedDebugGridTextItem;\r\n\r\nint DebugMonsterId;\r\n\r\nstd::vector<std::string> SearchMonsters;\r\nstd::vector<std::string> SearchItems;\r\nstd::vector<std::string> SearchObjects;\r\n\r\nvoid PrintDebugMonster(const Monster &monster)\r\n{\r\n\tEventPlrMsg(StrCat(\r\n\t                \"Monster \", static_cast<int>(monster.getId()), \" = \", monster.name(),\r\n\t                \"\\nX = \", monster.position.tile.x, \", Y = \", monster.position.tile.y,\r\n\t                \"\\nEnemy = \", monster.enemy, \", HP = \", monster.hitPoints,\r\n\t                \"\\nMode = \", static_cast<int>(monster.mode), \", Var1 = \", monster.var1),\r\n\t    UiFlags::ColorWhite);\r\n\r\n\tbool bActive = false;\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tif (&Monsters[ActiveMonsters[i]] == &monster) {\r\n\t\t\tbActive = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tEventPlrMsg(StrCat(\"Active List = \", bActive ? 1 : 0, \", Squelch = \", monster.activeForTicks), UiFlags::ColorWhite);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadDebugGFX()\r\n{\r\n\tpSquareCel = LoadCel(\"data\\\\square\", 64);\r\n}\r\n\r\nvoid FreeDebugGFX()\r\n{\r\n\tpSquareCel = std::nullopt;\r\n}\r\n\r\nvoid GetDebugMonster()\r\n{\r\n\tint monsterIndex = pcursmonst;\r\n\tif (monsterIndex == -1)\r\n\t\tmonsterIndex = std::abs(dMonster[cursPosition.x][cursPosition.y]) - 1;\r\n\r\n\tif (monsterIndex == -1)\r\n\t\tmonsterIndex = DebugMonsterId;\r\n\r\n\tPrintDebugMonster(Monsters[monsterIndex]);\r\n}\r\n\r\nvoid NextDebugMonster()\r\n{\r\n\tDebugMonsterId++;\r\n\tif (DebugMonsterId == MaxMonsters)\r\n\t\tDebugMonsterId = 0;\r\n\r\n\tEventPlrMsg(StrCat(\"Current debug monster = \", DebugMonsterId), UiFlags::ColorWhite);\r\n}\r\n\r\nvoid SetDebugLevelSeedInfos(uint32_t mid1Seed, uint32_t mid2Seed, uint32_t mid3Seed, uint32_t endSeed)\r\n{\r\n\tglMid1Seed[currlevel] = mid1Seed;\r\n\tglMid2Seed[currlevel] = mid2Seed;\r\n\tglMid3Seed[currlevel] = mid3Seed;\r\n\tglEndSeed[currlevel] = endSeed;\r\n}\r\n\r\nbool IsDebugGridTextNeeded()\r\n{\r\n\treturn SelectedDebugGridTextItem != DebugGridTextItem::None;\r\n}\r\n\r\nbool IsDebugGridInMegatiles()\r\n{\r\n\tswitch (SelectedDebugGridTextItem) {\r\n\tcase DebugGridTextItem::AutomapView:\r\n\tcase DebugGridTextItem::dungeon:\r\n\tcase DebugGridTextItem::pdungeon:\r\n\tcase DebugGridTextItem::Protected:\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nDebugGridTextItem GetDebugGridTextType()\r\n{\r\n\treturn SelectedDebugGridTextItem;\r\n}\r\n\r\nvoid SetDebugGridTextType(DebugGridTextItem value)\r\n{\r\n\tSelectedDebugGridTextItem = value;\r\n}\r\n\r\nbool GetDebugGridText(Point dungeonCoords, std::string &debugGridText)\r\n{\r\n\tint info = 0;\r\n\tint blankValue = 0;\r\n\tdebugGridText.clear();\r\n\tPoint megaCoords = dungeonCoords.worldToMega();\r\n\tswitch (SelectedDebugGridTextItem) {\r\n\tcase DebugGridTextItem::coords:\r\n\t\tStrAppend(debugGridText, dungeonCoords.x, \":\", dungeonCoords.y);\r\n\t\treturn true;\r\n\tcase DebugGridTextItem::cursorcoords:\r\n\t\tif (dungeonCoords != cursPosition)\r\n\t\t\treturn false;\r\n\t\tStrAppend(debugGridText, dungeonCoords.x, \":\", dungeonCoords.y);\r\n\t\treturn true;\r\n\tcase DebugGridTextItem::objectindex: {\r\n\t\tinfo = 0;\r\n\t\tObject *object = FindObjectAtPosition(dungeonCoords);\r\n\t\tif (object != nullptr) {\r\n\t\t\tinfo = static_cast<int>(object->_otype);\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\tcase DebugGridTextItem::microTiles: {\r\n\t\tconst MICROS &micros = DPieceMicros[dPiece[dungeonCoords.x][dungeonCoords.y]];\r\n\t\tfor (const LevelCelBlock tile : micros.mt) {\r\n\t\t\tif (!tile.hasValue()) break;\r\n\t\t\tif (!debugGridText.empty()) debugGridText += '\\n';\r\n\t\t\tStrAppend(debugGridText, tile.frame(), \" \");\r\n\t\t\tswitch (tile.type()) {\r\n\t\t\tcase TileType::Square: StrAppend(debugGridText, \"S\"); break;\r\n\t\t\tcase TileType::TransparentSquare: StrAppend(debugGridText, \"T\"); break;\r\n\t\t\tcase TileType::LeftTriangle: StrAppend(debugGridText, \"<\"); break;\r\n\t\t\tcase TileType::RightTriangle: StrAppend(debugGridText, \">\"); break;\r\n\t\t\tcase TileType::LeftTrapezoid: StrAppend(debugGridText, \"\\\\\"); break;\r\n\t\t\tcase TileType::RightTrapezoid: StrAppend(debugGridText, \"/\"); break;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (debugGridText.empty()) return false;\r\n\t\treturn true;\r\n\t} break;\r\n\tcase DebugGridTextItem::dPiece:\r\n\t\tinfo = dPiece[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dTransVal:\r\n\t\tinfo = dTransVal[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dLight:\r\n\t\tinfo = dLight[dungeonCoords.x][dungeonCoords.y];\r\n\t\tblankValue = LightsMax;\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dPreLight:\r\n\t\tinfo = dPreLight[dungeonCoords.x][dungeonCoords.y];\r\n\t\tblankValue = LightsMax;\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dFlags:\r\n\t\tinfo = static_cast<int>(dFlags[dungeonCoords.x][dungeonCoords.y]);\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dPlayer:\r\n\t\tinfo = dPlayer[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dMonster:\r\n\t\tinfo = dMonster[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::missiles: {\r\n\t\tfor (auto &missile : Missiles) {\r\n\t\t\tif (missile.position.tile == dungeonCoords) {\r\n\t\t\t\tif (!debugGridText.empty()) debugGridText += '\\n';\r\n\t\t\t\tdebugGridText.append(std::to_string((int)missile._mitype));\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (debugGridText.empty()) return false;\r\n\t\treturn true;\r\n\t} break;\r\n\tcase DebugGridTextItem::dCorpse:\r\n\t\tinfo = dCorpse[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dItem:\r\n\t\tinfo = dItem[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dSpecial:\r\n\t\tinfo = dSpecial[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dObject:\r\n\t\tinfo = dObject[dungeonCoords.x][dungeonCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::Solid:\r\n\t\tinfo = TileHasAny(dungeonCoords, TileProperties::Solid) << 0 | TileHasAny(dungeonCoords, TileProperties::BlockLight) << 1 | TileHasAny(dungeonCoords, TileProperties::BlockMissile) << 2;\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::Transparent:\r\n\t\tinfo = TileHasAny(dungeonCoords, TileProperties::Transparent) << 0 | TileHasAny(dungeonCoords, TileProperties::TransparentLeft) << 1 | TileHasAny(dungeonCoords, TileProperties::TransparentRight) << 2;\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::Trap:\r\n\t\tinfo = TileHasAny(dungeonCoords, TileProperties::Trap);\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::AutomapView:\r\n\t\tif (megaCoords.x >= 0 && megaCoords.x < DMAXX && megaCoords.y >= 0 && megaCoords.y < DMAXY)\r\n\t\t\tinfo = AutomapView[megaCoords.x][megaCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::dungeon:\r\n\t\tif (megaCoords.x >= 0 && megaCoords.x < DMAXX && megaCoords.y >= 0 && megaCoords.y < DMAXY)\r\n\t\t\tinfo = dungeon[megaCoords.x][megaCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::pdungeon:\r\n\t\tif (megaCoords.x >= 0 && megaCoords.x < DMAXX && megaCoords.y >= 0 && megaCoords.y < DMAXY)\r\n\t\t\tinfo = pdungeon[megaCoords.x][megaCoords.y];\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::Protected:\r\n\t\tif (megaCoords.x >= 0 && megaCoords.x < DMAXX && megaCoords.y >= 0 && megaCoords.y < DMAXY)\r\n\t\t\tinfo = Protected.test(megaCoords.x, megaCoords.y);\r\n\t\tbreak;\r\n\tcase DebugGridTextItem::None:\r\n\t\treturn false;\r\n\t}\r\n\tif (info == blankValue)\r\n\t\treturn false;\r\n\tStrAppend(debugGridText, info);\r\n\treturn true;\r\n}\r\n\r\nbool IsDebugAutomapHighlightNeeded()\r\n{\r\n\treturn SearchMonsters.size() > 0 || SearchItems.size() > 0 || SearchObjects.size() > 0;\r\n}\r\n\r\nbool ShouldHighlightDebugAutomapTile(Point position)\r\n{\r\n\tauto matchesSearched = [](const std::string_view name, const std::vector<std::string> &searchedNames) {\r\n\t\tconst std::string lowercaseName = AsciiStrToLower(name);\r\n\t\tfor (const auto &searchedName : searchedNames) {\r\n\t\t\tif (lowercaseName.find(searchedName) != std::string::npos) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n\r\n\tif (SearchMonsters.size() > 0 && dMonster[position.x][position.y] != 0) {\r\n\t\tconst int mi = std::abs(dMonster[position.x][position.y]) - 1;\r\n\t\tconst Monster &monster = Monsters[mi];\r\n\t\tif (matchesSearched(monster.name(), SearchMonsters))\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\tif (SearchItems.size() > 0 && dItem[position.x][position.y] != 0) {\r\n\t\tconst int itemId = std::abs(dItem[position.x][position.y]) - 1;\r\n\t\tconst Item &item = Items[itemId];\r\n\t\tif (matchesSearched(item.getName(), SearchItems))\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\tif (SearchObjects.size() > 0 && IsObjectAtPosition(position)) {\r\n\t\tconst Object &object = ObjectAtPosition(position);\r\n\t\tif (matchesSearched(object.name(), SearchObjects))\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid AddDebugAutomapMonsterHighlight(std::string_view name)\r\n{\r\n\tSearchMonsters.emplace_back(name);\r\n}\r\n\r\nvoid AddDebugAutomapItemHighlight(std::string_view name)\r\n{\r\n\tSearchItems.emplace_back(name);\r\n}\r\n\r\nvoid AddDebugAutomapObjectHighlight(std::string_view name)\r\n{\r\n\tSearchObjects.emplace_back(name);\r\n}\r\n\r\nvoid ClearDebugAutomapHighlights()\r\n{\r\n\tSearchMonsters.clear();\r\n\tSearchItems.clear();\r\n\tSearchObjects.clear();\r\n}\r\n\r\n} // namespace devilution\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/debug.h",
    "content": "/**\r\n * @file debug.h\r\n *\r\n * Interface of debug functions.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"diablo.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern std::string TestMapPath;\r\nextern OptionalOwnedClxSpriteList pSquareCel;\r\nextern bool DebugToggle;\r\nextern bool DebugGodMode;\r\nextern bool DebugInvisible;\r\nextern bool DebugVision;\r\nextern bool DebugPath;\r\nextern bool DebugGrid;\r\nextern ankerl::unordered_dense::map<int, Point> DebugCoordsMap;\r\nextern bool DebugScrollViewEnabled;\r\nextern std::string debugTRN;\r\nextern uint32_t glMid1Seed[NUMLEVELS];\r\nextern uint32_t glMid2Seed[NUMLEVELS];\r\nextern uint32_t glMid3Seed[NUMLEVELS];\r\nextern uint32_t glEndSeed[NUMLEVELS];\r\n\r\nenum class DebugGridTextItem : uint16_t {\r\n\tNone,\r\n\tmicroTiles,\r\n\tdPiece,\r\n\tdTransVal,\r\n\tdLight,\r\n\tdPreLight,\r\n\tdFlags,\r\n\tdPlayer,\r\n\tdMonster,\r\n\tmissiles,\r\n\tdCorpse,\r\n\tdObject,\r\n\tdItem,\r\n\tdSpecial,\r\n\r\n\tcoords,\r\n\tcursorcoords,\r\n\tobjectindex,\r\n\r\n\t// take dPiece as index\r\n\tSolid,\r\n\tTransparent,\r\n\tTrap,\r\n\r\n\t// megatiles\r\n\tAutomapView,\r\n\tdungeon,\r\n\tpdungeon,\r\n\tProtected,\r\n};\r\n\r\nvoid FreeDebugGFX();\r\nvoid LoadDebugGFX();\r\nvoid GetDebugMonster();\r\nvoid NextDebugMonster();\r\nvoid SetDebugLevelSeedInfos(uint32_t mid1Seed, uint32_t mid2Seed, uint32_t mid3Seed, uint32_t endSeed);\r\nbool IsDebugGridTextNeeded();\r\nbool IsDebugGridInMegatiles();\r\nDebugGridTextItem GetDebugGridTextType();\r\nvoid SetDebugGridTextType(DebugGridTextItem value);\r\nbool GetDebugGridText(Point dungeonCoords, std::string &debugGridText);\r\nbool IsDebugAutomapHighlightNeeded();\r\nbool ShouldHighlightDebugAutomapTile(Point position);\r\nvoid AddDebugAutomapMonsterHighlight(std::string_view name);\r\nvoid AddDebugAutomapItemHighlight(std::string_view name);\r\nvoid AddDebugAutomapObjectHighlight(std::string_view name);\r\nvoid ClearDebugAutomapHighlights();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/diablo.cpp",
    "content": "/**\r\n * @file diablo.cpp\r\n *\r\n * Implementation of the main game initialization functions.\r\n */\r\n#include <array>\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_init.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include <fmt/format.h>\r\n\r\n#include <config.h>\r\n\r\n#include \"DiabloUI/selstart.h\"\r\n#include \"appfat.h\"\r\n#include \"automap.h\"\r\n#include \"capture.h\"\r\n#include \"control/control.hpp\"\r\n#include \"cursor.h\"\r\n#include \"dead.h\"\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/keymapper.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"controls/remap_keyboard.h\"\r\n#include \"diablo.h\"\r\n#include \"diablo_msg.hpp\"\r\n#include \"discord/discord.h\"\r\n#include \"doom.h\"\r\n#include \"encrypt.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/events.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/sound.h\"\r\n#include \"game_mode.hpp\"\r\n#include \"gamemenu.h\"\r\n#include \"gmenu.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"help.h\"\r\n#include \"hwcursor.hpp\"\r\n#include \"init.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/drlg_l1.h\"\r\n#include \"levels/drlg_l2.h\"\r\n#include \"levels/drlg_l3.h\"\r\n#include \"levels/drlg_l4.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"levels/themes.h\"\r\n#include \"levels/town.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"lighting.h\"\r\n#include \"loadsave.h\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"lua/lua_global.hpp\"\r\n#include \"menu.h\"\r\n#include \"minitext.h\"\r\n#include \"missiles.h\"\r\n#include \"movie.h\"\r\n#include \"multi.h\"\r\n#include \"nthread.h\"\r\n#include \"objects.h\"\r\n#include \"options.h\"\r\n#include \"panels/console.hpp\"\r\n#include \"panels/info_box.hpp\"\r\n#include \"panels/partypanel.hpp\"\r\n#include \"panels/spell_book.hpp\"\r\n#include \"panels/spell_list.hpp\"\r\n#include \"pfile.h\"\r\n#include \"plrmsg.h\"\r\n#include \"qol/chatlog.h\"\r\n#include \"qol/floatingnumbers.h\"\r\n#include \"qol/itemlabels.h\"\r\n#include \"qol/monhealthbar.h\"\r\n#include \"qol/stash.h\"\r\n#include \"qol/xpbar.h\"\r\n#include \"quick_messages.hpp\"\r\n#include \"restrict.h\"\r\n#include \"stores.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"storm/storm_svid.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"towners.h\"\r\n#include \"track.h\"\r\n#include \"utils/console.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/parse_int.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/screen_reader.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_thread.h\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#ifndef USE_SDL1\r\n#include \"controls/touch/gamepad.h\"\r\n#include \"controls/touch/renderers.h\"\r\n#endif\r\n\r\n#ifdef __vita__\r\n#include \"platform/vita/touch.h\"\r\n#endif\r\n\r\n#ifdef GPERF_HEAP_FIRST_GAME_ITERATION\r\n#include <gperftools/heap-profiler.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nuint32_t DungeonSeeds[NUMLEVELS];\r\nstd::optional<uint32_t> LevelSeeds[NUMLEVELS];\r\nPoint MousePosition;\r\nbool gbRunGameResult;\r\nbool ReturnToMainMenu;\r\n/** Enable updating of player character, set to false once Diablo dies */\r\nbool gbProcessPlayers;\r\nbool gbLoadGame;\r\nbool cineflag;\r\nint PauseMode;\r\nclicktype sgbMouseDown;\r\nuint16_t gnTickDelay = 50;\r\nchar gszProductName[64] = \"DevilutionX vUnknown\";\r\n\r\n#ifdef _DEBUG\r\nbool DebugDisableNetworkTimeout = false;\r\nstd::vector<std::string> DebugCmdsFromCommandLine;\r\n#endif\r\nGameLogicStep gGameLogicStep = GameLogicStep::None;\r\n\r\n/** This and the following mouse variables are for handling in-game click-and-hold actions */\r\nPlayerActionType LastPlayerAction = PlayerActionType::None;\r\n\r\n// Controller support: Actions to run after updating the cursor state.\r\n// Defined in SourceX/controls/plctrls.cpp.\r\nextern void plrctrls_after_check_curs_move();\r\nextern void plrctrls_every_frame();\r\nextern void plrctrls_after_game_logic();\r\n\r\nnamespace {\r\n\r\nchar gszVersionNumber[64] = \"internal version unknown\";\r\n\r\nbool gbGameLoopStartup;\r\nbool forceSpawn;\r\nbool forceDiablo;\r\nint sgnTimeoutCurs;\r\nbool gbShowIntro = true;\r\n/** To know if these things have been done when we get to the diablo_deinit() function */\r\nbool was_archives_init = false;\r\n/** To know if surfaces have been initialized or not */\r\nbool was_window_init = false;\r\nbool was_ui_init = false;\r\n\r\nvoid StartGame(interface_mode uMsg)\r\n{\r\n\tCalcViewportGeometry();\r\n\tcineflag = false;\r\n\tInitCursor();\r\n#ifdef _DEBUG\r\n\tLoadDebugGFX();\r\n#endif\r\n\tassert(HeadlessMode || ghMainWnd);\r\n\tmusic_stop();\r\n\tInitMonsterHealthBar();\r\n\tInitXPBar();\r\n\tShowProgress(uMsg);\r\n\tgmenu_init_menu();\r\n\tInitLevelCursor();\r\n\tsgnTimeoutCurs = CURSOR_NONE;\r\n\tsgbMouseDown = CLICK_NONE;\r\n\tLastPlayerAction = PlayerActionType::None;\r\n}\r\n\r\nvoid FreeGame()\r\n{\r\n\tFreeMonsterHealthBar();\r\n\tFreeXPBar();\r\n\tFreeControlPan();\r\n\tFreeInvGFX();\r\n\tFreeGMenu();\r\n\tFreeQuestText();\r\n\tFreeInfoBoxGfx();\r\n\tFreeStoreMem();\r\n\r\n\tfor (Player &player : Players)\r\n\t\tResetPlayerGFX(player);\r\n\r\n\tFreeCursor();\r\n#ifdef _DEBUG\r\n\tFreeDebugGFX();\r\n#endif\r\n\tFreeGameMem();\r\n\tstream_stop();\r\n\tmusic_stop();\r\n}\r\n\r\nbool ProcessInput()\r\n{\r\n\tif (PauseMode == 2) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tplrctrls_every_frame();\r\n\r\n\tif (!gbIsMultiplayer && gmenu_is_active()) {\r\n\t\tRedrawViewport();\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (!gmenu_is_active() && sgnTimeoutCurs == CURSOR_NONE) {\r\n#ifdef __vita__\r\n\t\tFinishSimulatedMouseClicks(MousePosition);\r\n#endif\r\n\t\tCheckCursMove();\r\n\t\tplrctrls_after_check_curs_move();\r\n\t\tRepeatPlayerAction();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid LeftMouseCmd(bool bShift)\r\n{\r\n\tbool bNear;\r\n\r\n\tassert(!GetMainPanel().contains(MousePosition));\r\n\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tCloseGoldWithdraw();\r\n\t\tCloseStash();\r\n\t\tif (pcursitem != -1 && pcurs == CURSOR_HAND)\r\n\t\t\tNetSendCmdLocParam1(true, invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM, cursPosition, pcursitem);\r\n\t\tif (pcursmonst != -1)\r\n\t\t\tNetSendCmdLocParam1(true, CMD_TALKXY, cursPosition, pcursmonst);\r\n\t\tif (pcursitem == -1 && pcursmonst == -1 && PlayerUnderCursor == nullptr) {\r\n\t\t\tLastPlayerAction = PlayerActionType::Walk;\r\n\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, cursPosition);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tbNear = myPlayer.position.tile.WalkingDistance(cursPosition) < 2;\r\n\tif (pcursitem != -1 && pcurs == CURSOR_HAND && !bShift) {\r\n\t\tNetSendCmdLocParam1(true, invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM, cursPosition, pcursitem);\r\n\t} else if (ObjectUnderCursor != nullptr && !ObjectUnderCursor->IsDisabled() && (!bShift || (bNear && ObjectUnderCursor->_oBreak == 1))) {\r\n\t\tLastPlayerAction = PlayerActionType::OperateObject;\r\n\t\tNetSendCmdLoc(MyPlayerId, true, pcurs == CURSOR_DISARM ? CMD_DISARMXY : CMD_OPOBJXY, cursPosition);\r\n\t} else if (myPlayer.UsesRangedWeapon()) {\r\n\t\tif (bShift) {\r\n\t\t\tLastPlayerAction = PlayerActionType::Attack;\r\n\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_RATTACKXY, cursPosition);\r\n\t\t} else if (pcursmonst != -1) {\r\n\t\t\tif (CanTalkToMonst(Monsters[pcursmonst])) {\r\n\t\t\t\tNetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);\r\n\t\t\t} else {\r\n\t\t\t\tLastPlayerAction = PlayerActionType::AttackMonsterTarget;\r\n\t\t\t\tNetSendCmdParam1(true, CMD_RATTACKID, pcursmonst);\r\n\t\t\t}\r\n\t\t} else if (PlayerUnderCursor != nullptr && !PlayerUnderCursor->hasNoLife() && !myPlayer.friendlyMode) {\r\n\t\t\tLastPlayerAction = PlayerActionType::AttackPlayerTarget;\r\n\t\t\tNetSendCmdParam1(true, CMD_RATTACKPID, PlayerUnderCursor->getId());\r\n\t\t}\r\n\t} else {\r\n\t\tif (bShift) {\r\n\t\t\tif (pcursmonst != -1) {\r\n\t\t\t\tif (CanTalkToMonst(Monsters[pcursmonst])) {\r\n\t\t\t\t\tNetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tLastPlayerAction = PlayerActionType::Attack;\r\n\t\t\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_SATTACKXY, cursPosition);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tLastPlayerAction = PlayerActionType::Attack;\r\n\t\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_SATTACKXY, cursPosition);\r\n\t\t\t}\r\n\t\t} else if (pcursmonst != -1) {\r\n\t\t\tLastPlayerAction = PlayerActionType::AttackMonsterTarget;\r\n\t\t\tNetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);\r\n\t\t} else if (PlayerUnderCursor != nullptr && !PlayerUnderCursor->hasNoLife() && !myPlayer.friendlyMode) {\r\n\t\t\tLastPlayerAction = PlayerActionType::AttackPlayerTarget;\r\n\t\t\tNetSendCmdParam1(true, CMD_ATTACKPID, PlayerUnderCursor->getId());\r\n\t\t}\r\n\t}\r\n\tif (!bShift && pcursitem == -1 && ObjectUnderCursor == nullptr && pcursmonst == -1 && PlayerUnderCursor == nullptr) {\r\n\t\tLastPlayerAction = PlayerActionType::Walk;\r\n\t\tNetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, cursPosition);\r\n\t}\r\n}\r\n\r\nbool TryOpenDungeonWithMouse()\r\n{\r\n\tif (leveltype != DTYPE_TOWN)\r\n\t\treturn false;\r\n\r\n\tconst Item &holdItem = MyPlayer->HoldItem;\r\n\tif (holdItem.IDidx == IDI_RUNEBOMB && OpensHive(cursPosition))\r\n\t\tOpenHive();\r\n\telse if (holdItem.IDidx == IDI_MAPOFDOOM && OpensGrave(cursPosition))\r\n\t\tOpenGrave();\r\n\telse\r\n\t\treturn false;\r\n\r\n\tNewCursor(CURSOR_HAND);\r\n\treturn true;\r\n}\r\n\r\nvoid LeftMouseDown(uint16_t modState)\r\n{\r\n\tLastPlayerAction = PlayerActionType::None;\r\n\r\n\tif (gmenu_left_mouse(true))\r\n\t\treturn;\r\n\r\n\tif (CheckMuteButton())\r\n\t\treturn;\r\n\r\n\tif (sgnTimeoutCurs != CURSOR_NONE)\r\n\t\treturn;\r\n\r\n\tif (MyPlayerIsDead) {\r\n\t\tCheckMainPanelButtonDead();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (PauseMode == 2) {\r\n\t\treturn;\r\n\t}\r\n\tif (DoomFlag) {\r\n\t\tdoom_close();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (SpellSelectFlag) {\r\n\t\tSetSpell();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (IsPlayerInStore()) {\r\n\t\tCheckStoreBtn();\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst bool isShiftHeld = (modState & SDL_KMOD_SHIFT) != 0;\r\n\tconst bool isCtrlHeld = (modState & SDL_KMOD_CTRL) != 0;\r\n\r\n\tif (!GetMainPanel().contains(MousePosition)) {\r\n\t\tif (!gmenu_is_active() && !TryIconCurs()) {\r\n\t\t\tif (QuestLogIsOpen && GetLeftPanel().contains(MousePosition)) {\r\n\t\t\t\tQuestlogESC();\r\n\t\t\t} else if (qtextflag) {\r\n\t\t\t\tqtextflag = false;\r\n\t\t\t\tstream_stop();\r\n\t\t\t} else if (CharFlag && GetLeftPanel().contains(MousePosition)) {\r\n\t\t\t\tCheckChrBtns();\r\n\t\t\t} else if (invflag && GetRightPanel().contains(MousePosition)) {\r\n\t\t\t\tif (!DropGoldFlag)\r\n\t\t\t\t\tCheckInvItem(isShiftHeld, isCtrlHeld);\r\n\t\t\t} else if (IsStashOpen && GetLeftPanel().contains(MousePosition)) {\r\n\t\t\t\tif (!IsWithdrawGoldOpen)\r\n\t\t\t\t\tCheckStashItem(MousePosition, isShiftHeld, isCtrlHeld);\r\n\t\t\t\tCheckStashButtonPress(MousePosition);\r\n\t\t\t} else if (SpellbookFlag && GetRightPanel().contains(MousePosition)) {\r\n\t\t\t\tCheckSBook();\r\n\t\t\t} else if (!MyPlayer->HoldItem.isEmpty()) {\r\n\t\t\t\tif (!TryOpenDungeonWithMouse()) {\r\n\t\t\t\t\tconst Point currentPosition = MyPlayer->position.tile;\r\n\t\t\t\t\tstd::optional<Point> itemTile = FindAdjacentPositionForItem(currentPosition, GetDirection(currentPosition, cursPosition));\r\n\t\t\t\t\tif (itemTile) {\r\n\t\t\t\t\t\tNetSendCmdPItem(true, CMD_PUTITEM, *itemTile, MyPlayer->HoldItem);\r\n\t\t\t\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tCheckLevelButton();\r\n\t\t\t\tif (!LevelButtonDown)\r\n\t\t\t\t\tLeftMouseCmd(isShiftHeld);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tif (!ChatFlag && !DropGoldFlag && !IsWithdrawGoldOpen && !gmenu_is_active())\r\n\t\t\tCheckInvScrn(isShiftHeld, isCtrlHeld);\r\n\t\tCheckMainPanelButton();\r\n\t\tCheckStashButtonPress(MousePosition);\r\n\t\tif (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM)\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t}\r\n}\r\n\r\nvoid LeftMouseUp(uint16_t modState)\r\n{\r\n\tgmenu_left_mouse(false);\r\n\tCheckMuteButtonUp();\r\n\tif (MainPanelButtonDown)\r\n\t\tCheckMainPanelButtonUp();\r\n\tCheckStashButtonRelease(MousePosition);\r\n\tif (CharPanelButtonActive) {\r\n\t\tconst bool isShiftHeld = (modState & SDL_KMOD_SHIFT) != 0;\r\n\t\tReleaseChrBtns(isShiftHeld);\r\n\t}\r\n\tif (LevelButtonDown)\r\n\t\tCheckLevelButtonUp();\r\n\tif (IsPlayerInStore())\r\n\t\tReleaseStoreBtn();\r\n}\r\n\r\nvoid RightMouseDown(bool isShiftHeld)\r\n{\r\n\tLastPlayerAction = PlayerActionType::None;\r\n\r\n\tif (gmenu_is_active() || sgnTimeoutCurs != CURSOR_NONE || PauseMode == 2 || MyPlayer->_pInvincible) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (qtextflag) {\r\n\t\tqtextflag = false;\r\n\t\tstream_stop();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (DoomFlag) {\r\n\t\tdoom_close();\r\n\t\treturn;\r\n\t}\r\n\tif (IsPlayerInStore())\r\n\t\treturn;\r\n\tif (SpellSelectFlag) {\r\n\t\tSetSpell();\r\n\t\treturn;\r\n\t}\r\n\tif (SpellbookFlag && GetRightPanel().contains(MousePosition))\r\n\t\treturn;\r\n\tif (TryIconCurs())\r\n\t\treturn;\r\n\tif (pcursinvitem != -1 && UseInvItem(pcursinvitem))\r\n\t\treturn;\r\n\tif (pcursstashitem != StashStruct::EmptyCell && UseStashItem(pcursstashitem))\r\n\t\treturn;\r\n\tif (DidRightClickPartyPortrait())\r\n\t\treturn;\r\n\tif (pcurs == CURSOR_HAND) {\r\n\t\tCheckPlrSpell(isShiftHeld);\r\n\t} else if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) {\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t}\r\n}\r\n\r\nvoid ReleaseKey(SDL_Keycode vkey)\r\n{\r\n\tremap_keyboard_key(&vkey);\r\n\tif (sgnTimeoutCurs != CURSOR_NONE)\r\n\t\treturn;\r\n\tKeymapperRelease(vkey);\r\n}\r\n\r\nvoid ClosePanels()\r\n{\r\n\tif (CanPanelsCoverView()) {\r\n\t\tif (!IsLeftPanelOpen() && IsRightPanelOpen() && MousePosition.x < 480 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\tSetCursorPos(MousePosition + Displacement { 160, 0 });\r\n\t\t} else if (!IsRightPanelOpen() && IsLeftPanelOpen() && MousePosition.x > 160 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\tSetCursorPos(MousePosition - Displacement { 160, 0 });\r\n\t\t}\r\n\t}\r\n\tCloseInventory();\r\n\tCloseCharPanel();\r\n\tSpellbookFlag = false;\r\n\tQuestLogIsOpen = false;\r\n}\r\n\r\nvoid PressKey(SDL_Keycode vkey, uint16_t modState)\r\n{\r\n\tOptions &options = GetOptions();\r\n\tremap_keyboard_key(&vkey);\r\n\r\n\tif (vkey == SDLK_UNKNOWN)\r\n\t\treturn;\r\n\r\n\tif (gmenu_presskeys(vkey) || CheckKeypress(vkey)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (MyPlayerIsDead) {\r\n\t\tif (vkey == SDLK_ESCAPE) {\r\n\t\t\tif (!gbIsMultiplayer) {\r\n\t\t\t\tif (gbValidSaveFile)\r\n\t\t\t\t\tgamemenu_load_game(false);\r\n\t\t\t\telse\r\n\t\t\t\t\tgamemenu_exit_game(false);\r\n\t\t\t} else {\r\n\t\t\t\tNetSendCmd(true, CMD_RETOWN);\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (sgnTimeoutCurs != CURSOR_NONE) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tKeymapperPress(vkey);\r\n\t\tif (vkey == SDLK_RETURN || vkey == SDLK_KP_ENTER) {\r\n\t\t\tif ((modState & SDL_KMOD_ALT) != 0) {\r\n\t\t\t\toptions.Graphics.fullscreen.SetValue(!IsFullScreen());\r\n\t\t\t\tif (!demo::IsRunning()) SaveOptions();\r\n\t\t\t} else {\r\n\t\t\t\tTypeChatMessage();\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (vkey != SDLK_ESCAPE) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t// Disallow player from accessing escape menu during the frames before the death message appears\r\n\tif (vkey == SDLK_ESCAPE && MyPlayer->_pHitPoints > 0) {\r\n\t\tif (!PressEscKey()) {\r\n\t\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\t\tgamemenu_on();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (DropGoldFlag) {\r\n\t\tcontrol_drop_gold(vkey);\r\n\t\treturn;\r\n\t}\r\n\tif (IsWithdrawGoldOpen) {\r\n\t\tWithdrawGoldKeyPress(vkey);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (sgnTimeoutCurs != CURSOR_NONE) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tKeymapperPress(vkey);\r\n\r\n\tif (PauseMode == 2) {\r\n\t\tif ((vkey == SDLK_RETURN || vkey == SDLK_KP_ENTER) && (modState & SDL_KMOD_ALT) != 0) {\r\n\t\t\toptions.Graphics.fullscreen.SetValue(!IsFullScreen());\r\n\t\t\tif (!demo::IsRunning()) SaveOptions();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (DoomFlag) {\r\n\t\tdoom_close();\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (vkey) {\r\n\tcase SDLK_PLUS:\r\n\tcase SDLK_KP_PLUS:\r\n\tcase SDLK_EQUALS:\r\n\tcase SDLK_KP_EQUALS:\r\n\t\tif (AutomapActive) {\r\n\t\t\tAutomapZoomIn();\r\n\t\t}\r\n\t\treturn;\r\n\tcase SDLK_MINUS:\r\n\tcase SDLK_KP_MINUS:\r\n\tcase SDLK_UNDERSCORE:\r\n\t\tif (AutomapActive) {\r\n\t\t\tAutomapZoomOut();\r\n\t\t}\r\n\t\treturn;\r\n#ifdef _DEBUG\r\n\tcase SDLK_V:\r\n\t\tif ((modState & SDL_KMOD_SHIFT) != 0)\r\n\t\t\tNextDebugMonster();\r\n\t\telse\r\n\t\t\tGetDebugMonster();\r\n\t\treturn;\r\n#endif\r\n\tcase SDLK_RETURN:\r\n\tcase SDLK_KP_ENTER:\r\n\t\tif ((modState & SDL_KMOD_ALT) != 0) {\r\n\t\t\toptions.Graphics.fullscreen.SetValue(!IsFullScreen());\r\n\t\t\tif (!demo::IsRunning()) SaveOptions();\r\n\t\t} else if (IsPlayerInStore()) {\r\n\t\t\tStoreEnter();\r\n\t\t} else if (QuestLogIsOpen) {\r\n\t\t\tQuestlogEnter();\r\n\t\t} else {\r\n\t\t\tTypeChatMessage();\r\n\t\t}\r\n\t\treturn;\r\n\tcase SDLK_UP:\r\n\t\tif (IsPlayerInStore()) {\r\n\t\t\tStoreUp();\r\n\t\t} else if (QuestLogIsOpen) {\r\n\t\t\tQuestlogUp();\r\n\t\t} else if (HelpFlag) {\r\n\t\t\tHelpScrollUp();\r\n\t\t} else if (ChatLogFlag) {\r\n\t\t\tChatLogScrollUp();\r\n\t\t} else if (AutomapActive) {\r\n\t\t\tAutomapUp();\r\n\t\t} else if (IsStashOpen) {\r\n\t\t\tStash.PreviousPage();\r\n\t\t}\r\n\t\treturn;\r\n\tcase SDLK_DOWN:\r\n\t\tif (IsPlayerInStore()) {\r\n\t\t\tStoreDown();\r\n\t\t} else if (QuestLogIsOpen) {\r\n\t\t\tQuestlogDown();\r\n\t\t} else if (HelpFlag) {\r\n\t\t\tHelpScrollDown();\r\n\t\t} else if (ChatLogFlag) {\r\n\t\t\tChatLogScrollDown();\r\n\t\t} else if (AutomapActive) {\r\n\t\t\tAutomapDown();\r\n\t\t} else if (IsStashOpen) {\r\n\t\t\tStash.NextPage();\r\n\t\t}\r\n\t\treturn;\r\n\tcase SDLK_PAGEUP:\r\n\t\tif (IsPlayerInStore()) {\r\n\t\t\tStorePrior();\r\n\t\t} else if (ChatLogFlag) {\r\n\t\t\tChatLogScrollTop();\r\n\t\t}\r\n\t\treturn;\r\n\tcase SDLK_PAGEDOWN:\r\n\t\tif (IsPlayerInStore()) {\r\n\t\t\tStoreNext();\r\n\t\t} else if (ChatLogFlag) {\r\n\t\t\tChatLogScrollBottom();\r\n\t\t}\r\n\t\treturn;\r\n\tcase SDLK_LEFT:\r\n\t\tif (AutomapActive && !ChatFlag)\r\n\t\t\tAutomapLeft();\r\n\t\treturn;\r\n\tcase SDLK_RIGHT:\r\n\t\tif (AutomapActive && !ChatFlag)\r\n\t\t\tAutomapRight();\r\n\t\treturn;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid HandleMouseButtonDown(Uint8 button, uint16_t modState)\r\n{\r\n\tif (IsPlayerInStore() && (button == SDL_BUTTON_X1\r\n#if !SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t        || button == 8\r\n#endif\r\n\t        )) {\r\n\t\tStoreESC();\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (button) {\r\n\tcase SDL_BUTTON_LEFT:\r\n\t\tif (sgbMouseDown == CLICK_NONE) {\r\n\t\t\tsgbMouseDown = CLICK_LEFT;\r\n\t\t\tLeftMouseDown(modState);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase SDL_BUTTON_RIGHT:\r\n\t\tif (sgbMouseDown == CLICK_NONE) {\r\n\t\t\tsgbMouseDown = CLICK_RIGHT;\r\n\t\t\tRightMouseDown((modState & SDL_KMOD_SHIFT) != 0);\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tKeymapperPress(static_cast<SDL_Keycode>(button | KeymapperMouseButtonMask));\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid HandleMouseButtonUp(Uint8 button, uint16_t modState)\r\n{\r\n\tif (sgbMouseDown == CLICK_LEFT && button == SDL_BUTTON_LEFT) {\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\tsgbMouseDown = CLICK_NONE;\r\n\t\tLeftMouseUp(modState);\r\n\t} else if (sgbMouseDown == CLICK_RIGHT && button == SDL_BUTTON_RIGHT) {\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\tsgbMouseDown = CLICK_NONE;\r\n\t} else {\r\n\t\tKeymapperRelease(static_cast<SDL_Keycode>(button | KeymapperMouseButtonMask));\r\n\t}\r\n}\r\n\r\n[[maybe_unused]] void LogUnhandledEvent(const char *name, int value)\r\n{\r\n\tLogVerbose(\"Unhandled SDL event: {} {}\", name, value);\r\n}\r\n\r\nvoid PrepareForFadeIn()\r\n{\r\n\tif (HeadlessMode) return;\r\n\tBlackPalette();\r\n\r\n\t// Render the game to the buffer(s) with a fully black palette.\r\n\t// Palette fade-in will gradually make it visible.\r\n\tRedrawEverything();\r\n\twhile (IsRedrawEverything()) {\r\n\t\tDrawAndBlit();\r\n\t}\r\n}\r\n\r\nvoid GameEventHandler(const SDL_Event &event, uint16_t modState)\r\n{\r\n\t[[maybe_unused]] const Options &options = GetOptions();\r\n\tStaticVector<ControllerButtonEvent, 4> ctrlEvents = ToControllerButtonEvents(event);\r\n\tfor (const ControllerButtonEvent ctrlEvent : ctrlEvents) {\r\n\t\tGameAction action;\r\n\t\tif (HandleControllerButtonEvent(event, ctrlEvent, action) && action.type == GameActionType_SEND_KEY) {\r\n\t\t\tif ((action.send_key.vk_code & KeymapperMouseButtonMask) != 0) {\r\n\t\t\t\tconst unsigned button = action.send_key.vk_code & ~KeymapperMouseButtonMask;\r\n\t\t\t\tif (!action.send_key.up)\r\n\t\t\t\t\tHandleMouseButtonDown(static_cast<Uint8>(button), modState);\r\n\t\t\t\telse\r\n\t\t\t\t\tHandleMouseButtonUp(static_cast<Uint8>(button), modState);\r\n\t\t\t} else {\r\n\t\t\t\tif (!action.send_key.up)\r\n\t\t\t\t\tPressKey(static_cast<SDL_Keycode>(action.send_key.vk_code), modState);\r\n\t\t\t\telse\r\n\t\t\t\t\tReleaseKey(static_cast<SDL_Keycode>(action.send_key.vk_code));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (ctrlEvents.size() > 0 && ctrlEvents[0].button != ControllerButton_NONE) {\r\n\t\treturn;\r\n\t}\r\n\r\n#ifdef _DEBUG\r\n\tif (ConsoleHandleEvent(event)) {\r\n\t\treturn;\r\n\t}\r\n#endif\r\n\r\n\tif (IsChatActive() && HandleTalkTextInputEvent(event)) {\r\n\t\treturn;\r\n\t}\r\n\tif (DropGoldFlag && HandleGoldDropTextInputEvent(event)) {\r\n\t\treturn;\r\n\t}\r\n\tif (IsWithdrawGoldOpen && HandleGoldWithdrawTextInputEvent(event)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_KEY_DOWN:\r\n\t\tPressKey(SDLC_EventKey(event), modState);\r\n\t\treturn;\r\n\tcase SDL_EVENT_KEY_UP:\r\n\t\tReleaseKey(SDLC_EventKey(event));\r\n\t\treturn;\r\n\tcase SDL_EVENT_MOUSE_MOTION:\r\n\t\tif (ControlMode == ControlTypes::KeyboardAndMouse && invflag)\r\n\t\t\tInvalidateInventorySlot();\r\n\t\tMousePosition = { SDLC_EventMotionIntX(event), SDLC_EventMotionIntY(event) };\r\n\t\tgmenu_on_mouse_move();\r\n\t\treturn;\r\n\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\t\tMousePosition = { SDLC_EventButtonIntX(event), SDLC_EventButtonIntY(event) };\r\n\t\tHandleMouseButtonDown(event.button.button, modState);\r\n\t\treturn;\r\n\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\tMousePosition = { SDLC_EventButtonIntX(event), SDLC_EventButtonIntY(event) };\r\n\t\tHandleMouseButtonUp(event.button.button, modState);\r\n\t\treturn;\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tcase SDL_EVENT_MOUSE_WHEEL:\r\n\t\tif (SDLC_EventWheelIntY(event) > 0) { // Up\r\n\t\t\tif (IsPlayerInStore()) {\r\n\t\t\t\tStoreUp();\r\n\t\t\t} else if (QuestLogIsOpen) {\r\n\t\t\t\tQuestlogUp();\r\n\t\t\t} else if (HelpFlag) {\r\n\t\t\t\tHelpScrollUp();\r\n\t\t\t} else if (ChatLogFlag) {\r\n\t\t\t\tChatLogScrollUp();\r\n\t\t\t} else if (IsStashOpen) {\r\n\t\t\t\tStash.PreviousPage();\r\n\t\t\t} else if (SDL_GetModState() & SDL_KMOD_CTRL) {\r\n\t\t\t\tif (AutomapActive) {\r\n\t\t\t\t\tAutomapZoomIn();\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tKeymapperPress(MouseScrollUpButton);\r\n\t\t\t}\r\n\t\t} else if (SDLC_EventWheelIntY(event) < 0) { // down\r\n\t\t\tif (IsPlayerInStore()) {\r\n\t\t\t\tStoreDown();\r\n\t\t\t} else if (QuestLogIsOpen) {\r\n\t\t\t\tQuestlogDown();\r\n\t\t\t} else if (HelpFlag) {\r\n\t\t\t\tHelpScrollDown();\r\n\t\t\t} else if (ChatLogFlag) {\r\n\t\t\t\tChatLogScrollDown();\r\n\t\t\t} else if (IsStashOpen) {\r\n\t\t\t\tStash.NextPage();\r\n\t\t\t} else if (SDL_GetModState() & SDL_KMOD_CTRL) {\r\n\t\t\t\tif (AutomapActive) {\r\n\t\t\t\t\tAutomapZoomOut();\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tKeymapperPress(MouseScrollDownButton);\r\n\t\t\t}\r\n\t\t} else if (SDLC_EventWheelIntX(event) > 0) { // left\r\n\t\t\tKeymapperPress(MouseScrollLeftButton);\r\n\t\t} else if (SDLC_EventWheelIntX(event) < 0) { // right\r\n\t\t\tKeymapperPress(MouseScrollRightButton);\r\n\t\t}\r\n\t\tbreak;\r\n#endif\r\n\tdefault:\r\n\t\tif (IsCustomEvent(event.type)) {\r\n\t\t\tif (gbIsMultiplayer)\r\n\t\t\t\tpfile_write_hero();\r\n\t\t\tnthread_ignore_mutex(true);\r\n\t\t\tPaletteFadeOut(8);\r\n\t\t\tsound_stop();\r\n\t\t\tShowProgress(GetCustomEvent(event));\r\n\r\n\t\t\tPrepareForFadeIn();\r\n\t\t\tLoadPWaterPalette();\r\n\t\t\tif (gbRunGame)\r\n\t\t\t\tPaletteFadeIn(8);\r\n\t\t\tnthread_ignore_mutex(false);\r\n\t\t\tgbGameLoopStartup = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tMainWndProc(event);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid RunGameLoop(interface_mode uMsg)\r\n{\r\n\tdemo::NotifyGameLoopStart();\r\n\r\n\tnthread_ignore_mutex(true);\r\n\tStartGame(uMsg);\r\n\tassert(HeadlessMode || ghMainWnd);\r\n\tEventHandler previousHandler = SetEventHandler(GameEventHandler);\r\n\trun_delta_info();\r\n\tgbRunGame = true;\r\n\tgbProcessPlayers = IsDiabloAlive(true);\r\n\tgbRunGameResult = true;\r\n\r\n\tPrepareForFadeIn();\r\n\tLoadPWaterPalette();\r\n\tPaletteFadeIn(8);\r\n\tInitBackbufferState();\r\n\tRedrawEverything();\r\n\tgbGameLoopStartup = true;\r\n\tnthread_ignore_mutex(false);\r\n\r\n\tdiscord_manager::StartGame();\r\n\tlua::GameStart();\r\n#ifdef GPERF_HEAP_FIRST_GAME_ITERATION\r\n\tunsigned run_game_iteration = 0;\r\n#endif\r\n\r\n\twhile (gbRunGame) {\r\n\r\n#ifdef _DEBUG\r\n\t\tif (!gbGameLoopStartup && !DebugCmdsFromCommandLine.empty()) {\r\n\t\t\tInitConsole();\r\n\t\t\tfor (const std::string &cmd : DebugCmdsFromCommandLine) {\r\n\t\t\t\tRunInConsole(cmd);\r\n\t\t\t}\r\n\t\t\tDebugCmdsFromCommandLine.clear();\r\n\t\t}\r\n#endif\r\n\r\n\t\tSDL_Event event;\r\n\t\tuint16_t modState;\r\n\t\twhile (FetchMessage(&event, &modState)) {\r\n\t\t\tif (event.type == SDL_EVENT_QUIT) {\r\n\t\t\t\tgbRunGameResult = false;\r\n\t\t\t\tgbRunGame = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tHandleMessage(event, modState);\r\n\t\t}\r\n\t\tif (!gbRunGame)\r\n\t\t\tbreak;\r\n\r\n\t\tbool drawGame = true;\r\n\t\tbool processInput = true;\r\n\t\tconst bool runGameLoop = demo::IsRunning() ? demo::GetRunGameLoop(drawGame, processInput) : nthread_has_500ms_passed(&drawGame);\r\n\t\tif (demo::IsRecording())\r\n\t\t\tdemo::RecordGameLoopResult(runGameLoop);\r\n\r\n\t\tdiscord_manager::UpdateGame();\r\n\r\n\t\tif (!runGameLoop) {\r\n\t\t\tif (processInput)\r\n\t\t\t\tProcessInput();\r\n\t\t\tDvlNet_ProcessNetworkPackets();\r\n\t\t\tif (!drawGame)\r\n\t\t\t\tcontinue;\r\n\t\t\tRedrawViewport();\r\n\t\t\tDrawAndBlit();\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tProcessGameMessagePackets();\r\n\t\tif (game_loop(gbGameLoopStartup))\r\n\t\t\tdiablo_color_cyc_logic();\r\n\t\tgbGameLoopStartup = false;\r\n\t\tif (drawGame)\r\n\t\t\tDrawAndBlit();\r\n#ifdef GPERF_HEAP_FIRST_GAME_ITERATION\r\n\t\tif (run_game_iteration++ == 0)\r\n\t\t\tHeapProfilerDump(\"first_game_iteration\");\r\n#endif\r\n\t}\r\n\r\n\tdemo::NotifyGameLoopEnd();\r\n\r\n\tif (gbIsMultiplayer) {\r\n\t\tpfile_write_hero(/*writeGameData=*/false);\r\n\t\tsfile_write_stash();\r\n\t}\r\n\r\n\tPaletteFadeOut(8);\r\n\tNewCursor(CURSOR_NONE);\r\n\tClearScreenBuffer();\r\n\tRedrawEverything();\r\n\tscrollrt_draw_game_screen();\r\n\tpreviousHandler = SetEventHandler(previousHandler);\r\n\tassert(HeadlessMode || previousHandler == GameEventHandler);\r\n\tFreeGame();\r\n\r\n\tif (cineflag) {\r\n\t\tcineflag = false;\r\n\t\tDoEnding();\r\n\t}\r\n}\r\n\r\nvoid PrintWithRightPadding(std::string_view str, size_t width)\r\n{\r\n\tprintInConsole(str);\r\n\tif (str.size() >= width)\r\n\t\treturn;\r\n\tprintInConsole(std::string(width - str.size(), ' '));\r\n}\r\n\r\nvoid PrintHelpOption(std::string_view flags, std::string_view description)\r\n{\r\n\tprintInConsole(\"    \");\r\n\tPrintWithRightPadding(flags, 20);\r\n\tprintInConsole(\" \");\r\n\tPrintWithRightPadding(description, 30);\r\n\tprintNewlineInConsole();\r\n}\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nFILE *SdlLogFile = nullptr;\r\n\r\nextern \"C\" void SdlLogToFile(void *userdata, int category, SDL_LogPriority priority, const char *message)\r\n{\r\n\tFILE *file = reinterpret_cast<FILE *>(userdata);\r\n\tstatic const char *const LogPriorityPrefixes[SDL_LOG_PRIORITY_COUNT] = {\r\n\t\t\"\",\r\n\t\t\"VERBOSE\",\r\n\t\t\"DEBUG\",\r\n\t\t\"INFO\",\r\n\t\t\"WARN\",\r\n\t\t\"ERROR\",\r\n\t\t\"CRITICAL\"\r\n\t};\r\n\tstd::fprintf(file, \"%s: %s\\n\", LogPriorityPrefixes[priority], message);\r\n\tstd::fflush(file);\r\n}\r\n#endif\r\n\r\n[[noreturn]] void PrintHelpAndExit()\r\n{\r\n\tprintInConsole((/* TRANSLATORS: Commandline Option */ \"Options:\"));\r\n\tprintNewlineInConsole();\r\n\tPrintHelpOption(\"-h, --help\", _(/* TRANSLATORS: Commandline Option */ \"Print this message and exit\"));\r\n\tPrintHelpOption(\"--version\", _(/* TRANSLATORS: Commandline Option */ \"Print the version and exit\"));\r\n\tPrintHelpOption(\"--data-dir\", _(/* TRANSLATORS: Commandline Option */ \"Specify the folder of diabdat.mpq\"));\r\n\tPrintHelpOption(\"--save-dir\", _(/* TRANSLATORS: Commandline Option */ \"Specify the folder of save files\"));\r\n\tPrintHelpOption(\"--config-dir\", _(/* TRANSLATORS: Commandline Option */ \"Specify the location of diablo.ini\"));\r\n\tPrintHelpOption(\"--lang\", _(/* TRANSLATORS: Commandline Option */ \"Specify the language code (e.g. en or pt_BR)\"));\r\n\tPrintHelpOption(\"-n\", _(/* TRANSLATORS: Commandline Option */ \"Skip startup videos\"));\r\n\tPrintHelpOption(\"-f\", _(/* TRANSLATORS: Commandline Option */ \"Display frames per second\"));\r\n\tPrintHelpOption(\"--verbose\", _(/* TRANSLATORS: Commandline Option */ \"Enable verbose logging\"));\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tPrintHelpOption(\"--log-to-file <path>\", _(/* TRANSLATORS: Commandline Option */ \"Log to a file instead of stderr\"));\r\n#endif\r\n#ifndef DISABLE_DEMOMODE\r\n\tPrintHelpOption(\"--record <#>\", _(/* TRANSLATORS: Commandline Option */ \"Record a demo file\"));\r\n\tPrintHelpOption(\"--demo <#>\", _(/* TRANSLATORS: Commandline Option */ \"Play a demo file\"));\r\n\tPrintHelpOption(\"--timedemo\", _(/* TRANSLATORS: Commandline Option */ \"Disable all frame limiting during demo playback\"));\r\n#endif\r\n\tprintNewlineInConsole();\r\n\tprintInConsole(_(/* TRANSLATORS: Commandline Option */ \"Game selection:\"));\r\n\tprintNewlineInConsole();\r\n\tPrintHelpOption(\"--spawn\", _(/* TRANSLATORS: Commandline Option */ \"Force Shareware mode\"));\r\n\tPrintHelpOption(\"--diablo\", _(/* TRANSLATORS: Commandline Option */ \"Force Diablo mode\"));\r\n\tPrintHelpOption(\"--hellfire\", _(/* TRANSLATORS: Commandline Option */ \"Force Hellfire mode\"));\r\n\tprintInConsole(_(/* TRANSLATORS: Commandline Option */ \"Hellfire options:\"));\r\n\tprintNewlineInConsole();\r\n#ifdef _DEBUG\r\n\tprintNewlineInConsole();\r\n\tprintInConsole(\"Debug options:\");\r\n\tprintNewlineInConsole();\r\n\tPrintHelpOption(\"-i\", \"Ignore network timeout\");\r\n\tPrintHelpOption(\"+<internal command>\", \"Pass commands to the engine\");\r\n#endif\r\n\tprintNewlineInConsole();\r\n\tprintInConsole(_(\"Report bugs at https://github.com/diasurgical/devilutionX/\"));\r\n\tprintNewlineInConsole();\r\n\tdiablo_quit(0);\r\n}\r\n\r\nvoid PrintFlagMessage(std::string_view flag, std::string_view message)\r\n{\r\n\tprintInConsole(flag);\r\n\tprintInConsole(message);\r\n\tprintNewlineInConsole();\r\n}\r\n\r\nvoid PrintFlagRequiresArgument(std::string_view flag)\r\n{\r\n\tPrintFlagMessage(flag, \" requires an argument\");\r\n}\r\n\r\nvoid DiabloParseFlags(int argc, char **argv)\r\n{\r\n#ifdef _DEBUG\r\n\tint argumentIndexOfLastCommandPart = -1;\r\n\tstd::string currentCommand;\r\n#endif\r\n#ifndef DISABLE_DEMOMODE\r\n\tbool timedemo = false;\r\n\tint demoNumber = -1;\r\n\tint recordNumber = -1;\r\n\tbool createDemoReference = false;\r\n#endif\r\n\tfor (int i = 1; i < argc; i++) {\r\n\t\tconst std::string_view arg = argv[i];\r\n\t\tif (arg == \"-h\" || arg == \"--help\") {\r\n\t\t\tPrintHelpAndExit();\r\n\t\t} else if (arg == \"--version\") {\r\n\t\t\tprintInConsole(PROJECT_NAME);\r\n\t\t\tprintInConsole(\" v\");\r\n\t\t\tprintInConsole(PROJECT_VERSION);\r\n\t\t\tprintNewlineInConsole();\r\n\t\t\tdiablo_quit(0);\r\n\t\t} else if (arg == \"--data-dir\") {\r\n\t\t\tif (i + 1 == argc) {\r\n\t\t\t\tPrintFlagRequiresArgument(\"--data-dir\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tpaths::SetBasePath(argv[++i]);\r\n\t\t} else if (arg == \"--save-dir\") {\r\n\t\t\tif (i + 1 == argc) {\r\n\t\t\t\tPrintFlagRequiresArgument(\"--save-dir\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tpaths::SetPrefPath(argv[++i]);\r\n\t\t} else if (arg == \"--config-dir\") {\r\n\t\t\tif (i + 1 == argc) {\r\n\t\t\t\tPrintFlagRequiresArgument(\"--config-dir\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tpaths::SetConfigPath(argv[++i]);\r\n\t\t} else if (arg == \"--lang\") {\r\n\t\t\tif (i + 1 == argc) {\r\n\t\t\t\tPrintFlagRequiresArgument(\"--lang\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tforceLocale = argv[++i];\r\n#ifndef DISABLE_DEMOMODE\r\n\t\t} else if (arg == \"--demo\") {\r\n\t\t\tif (i + 1 == argc) {\r\n\t\t\t\tPrintFlagRequiresArgument(\"--demo\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tParseIntResult<int> parsedParam = ParseInt<int>(argv[++i]);\r\n\t\t\tif (!parsedParam.has_value()) {\r\n\t\t\t\tPrintFlagMessage(\"--demo\", \" must be a number\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tdemoNumber = parsedParam.value();\r\n\t\t\tgbShowIntro = false;\r\n\t\t} else if (arg == \"--timedemo\") {\r\n\t\t\ttimedemo = true;\r\n\t\t} else if (arg == \"--record\") {\r\n\t\t\tif (i + 1 == argc) {\r\n\t\t\t\tPrintFlagRequiresArgument(\"--record\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tParseIntResult<int> parsedParam = ParseInt<int>(argv[++i]);\r\n\t\t\tif (!parsedParam.has_value()) {\r\n\t\t\t\tPrintFlagMessage(\"--record\", \" must be a number\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\trecordNumber = parsedParam.value();\r\n\t\t} else if (arg == \"--create-reference\") {\r\n\t\t\tcreateDemoReference = true;\r\n#else\r\n\t\t} else if (arg == \"--demo\" || arg == \"--timedemo\" || arg == \"--record\" || arg == \"--create-reference\") {\r\n\t\t\tprintInConsole(\"Binary compiled without demo mode support.\");\r\n\t\t\tprintNewlineInConsole();\r\n\t\t\tdiablo_quit(1);\r\n#endif\r\n\t\t} else if (arg == \"-n\") {\r\n\t\t\tgbShowIntro = false;\r\n\t\t} else if (arg == \"-f\") {\r\n\t\t\tEnableFrameCount();\r\n\t\t} else if (arg == \"--spawn\") {\r\n\t\t\tforceSpawn = true;\r\n\t\t} else if (arg == \"--diablo\") {\r\n\t\t\tforceDiablo = true;\r\n\t\t} else if (arg == \"--hellfire\") {\r\n\t\t\tforceHellfire = true;\r\n\t\t} else if (arg == \"--vanilla\") {\r\n\t\t\tgbVanilla = true;\r\n\t\t} else if (arg == \"--verbose\") {\r\n\t\t\tSDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t\t} else if (arg == \"--log-to-file\") {\r\n\t\t\tif (i + 1 == argc) {\r\n\t\t\t\tPrintFlagRequiresArgument(\"--log-to-file\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tSdlLogFile = OpenFile(argv[++i], \"wb\");\r\n\t\t\tif (SdlLogFile == nullptr) {\r\n\t\t\t\tprintInConsole(\"Failed to open log file for writing\");\r\n\t\t\t\tdiablo_quit(64);\r\n\t\t\t}\r\n\t\t\tSDL_SetLogOutputFunction(&SdlLogToFile, /*userdata=*/SdlLogFile);\r\n#endif\r\n#ifdef _DEBUG\r\n\t\t} else if (arg == \"-i\") {\r\n\t\t\tDebugDisableNetworkTimeout = true;\r\n\t\t} else if (arg[0] == '+') {\r\n\t\t\tif (!currentCommand.empty())\r\n\t\t\t\tDebugCmdsFromCommandLine.push_back(currentCommand);\r\n\t\t\targumentIndexOfLastCommandPart = i;\r\n\t\t\tcurrentCommand = arg.substr(1);\r\n\t\t} else if (arg[0] != '-' && (argumentIndexOfLastCommandPart + 1) == i) {\r\n\t\t\tcurrentCommand.append(\" \");\r\n\t\t\tcurrentCommand.append(arg);\r\n\t\t\targumentIndexOfLastCommandPart = i;\r\n#endif\r\n\t\t} else {\r\n\t\t\tprintInConsole(\"unrecognized option '\");\r\n\t\t\tprintInConsole(argv[i]);\r\n\t\t\tprintInConsole(\"'\");\r\n\t\t\tprintNewlineInConsole();\r\n\t\t\tPrintHelpAndExit();\r\n\t\t}\r\n\t}\r\n\r\n#ifdef _DEBUG\r\n\tif (!currentCommand.empty())\r\n\t\tDebugCmdsFromCommandLine.push_back(currentCommand);\r\n#endif\r\n\r\n#ifndef DISABLE_DEMOMODE\r\n\tif (demoNumber != -1)\r\n\t\tdemo::InitPlayBack(demoNumber, timedemo);\r\n\tif (recordNumber != -1)\r\n\t\tdemo::InitRecording(recordNumber, createDemoReference);\r\n#endif\r\n}\r\n\r\nvoid DiabloInitScreen()\r\n{\r\n\tMousePosition = { gnScreenWidth / 2, gnScreenHeight / 2 };\r\n\tif (ControlMode == ControlTypes::KeyboardAndMouse)\r\n\t\tSetCursorPos(MousePosition);\r\n\r\n\tClrDiabloMsg();\r\n}\r\n\r\nvoid SetApplicationVersions()\r\n{\r\n\t*BufCopy(gszProductName, PROJECT_NAME, \" v\", PROJECT_VERSION) = '\\0';\r\n\t*BufCopy(gszVersionNumber, \"version \", PROJECT_VERSION) = '\\0';\r\n}\r\n\r\nvoid CheckArchivesUpToDate()\r\n{\r\n\tconst bool devilutionxMpqOutOfDate = IsDevilutionXMpqOutOfDate();\r\n\tconst bool fontsMpqOutOfDate = AreExtraFontsOutOfDate();\r\n\r\n\tif (devilutionxMpqOutOfDate && fontsMpqOutOfDate) {\r\n\t\tapp_fatal(_(\"Please update devilutionx.mpq and fonts.mpq to the latest version\"));\r\n\t} else if (devilutionxMpqOutOfDate) {\r\n\t\tapp_fatal(_(\"Failed to load UI resources.\\n\"\r\n\t\t            \"\\n\"\r\n\t\t            \"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"));\r\n\t} else if (fontsMpqOutOfDate) {\r\n\t\tapp_fatal(_(\"Please update fonts.mpq to the latest version\"));\r\n\t}\r\n}\r\n\r\nvoid ApplicationInit()\r\n{\r\n\tif (*GetOptions().Graphics.showFPS)\r\n\t\tEnableFrameCount();\r\n\r\n\tinit_create_window();\r\n\twas_window_init = true;\r\n\r\n\tInitializeScreenReader();\r\n\tLanguageInitialize();\r\n\r\n\tSetApplicationVersions();\r\n\r\n\tReadOnlyTest();\r\n}\r\n\r\nvoid DiabloInit()\r\n{\r\n\tif (forceSpawn || *GetOptions().GameMode.shareware)\r\n\t\tgbIsSpawn = true;\r\n\r\n\tbool wasHellfireDiscovered = false;\r\n\tif (!forceDiablo && !forceHellfire)\r\n\t\twasHellfireDiscovered = (HaveHellfire() && *GetOptions().GameMode.gameMode == StartUpGameMode::Ask);\r\n\tbool enableHellfire = forceHellfire || wasHellfireDiscovered;\r\n\tif (!forceDiablo && *GetOptions().GameMode.gameMode == StartUpGameMode::Hellfire) { // Migrate legacy options\r\n\t\tGetOptions().GameMode.gameMode.SetValue(StartUpGameMode::Diablo);\r\n\t\tenableHellfire = true;\r\n\t}\r\n\tif (forceDiablo || enableHellfire) {\r\n\t\tGetOptions().Mods.SetHellfireEnabled(enableHellfire);\r\n\t}\r\n\r\n\tgbIsHellfireSaveGame = gbIsHellfire;\r\n\r\n\tfor (size_t i = 0; i < QuickMessages.size(); i++) {\r\n\t\tauto &messages = GetOptions().Chat.szHotKeyMsgs[i];\r\n\t\tif (messages.empty()) {\r\n\t\t\tmessages.emplace_back(_(QuickMessages[i].message));\r\n\t\t}\r\n\t}\r\n\r\n#ifndef USE_SDL1\r\n\tInitializeVirtualGamepad();\r\n#endif\r\n\r\n\tUiInitialize();\r\n\twas_ui_init = true;\r\n\r\n\tif (wasHellfireDiscovered) {\r\n\t\tUiSelStartUpGameOption();\r\n\t\tif (!gbIsHellfire) {\r\n\t\t\t// Reinitialize the UI Elements because we changed the game\r\n\t\t\tUnloadUiGFX();\r\n\t\t\tUiInitialize();\r\n\t\t\tif (IsHardwareCursor())\r\n\t\t\t\tSetHardwareCursor(CursorInfo::UnknownCursor());\r\n\t\t}\r\n\t}\r\n\r\n\tDiabloInitScreen();\r\n\r\n\tsnd_init();\r\n\r\n\tui_sound_init();\r\n\r\n\t// Item graphics are loaded early, they already get touched during hero selection.\r\n\tInitItemGFX();\r\n\r\n\t// Always available.\r\n\tLoadSmallSelectionSpinner();\r\n\r\n\tCheckArchivesUpToDate();\r\n}\r\n\r\nvoid DiabloSplash()\r\n{\r\n\tif (!gbShowIntro)\r\n\t\treturn;\r\n\r\n\tif (*GetOptions().StartUp.splash == StartUpSplash::LogoAndTitleDialog)\r\n\t\tplay_movie(\"gendata\\\\logo.smk\", true);\r\n\r\n\tauto &intro = gbIsHellfire ? GetOptions().StartUp.hellfireIntro : GetOptions().StartUp.diabloIntro;\r\n\r\n\tif (*intro != StartUpIntro::Off) {\r\n\t\tif (gbIsHellfire)\r\n\t\t\tplay_movie(\"gendata\\\\Hellfire.smk\", true);\r\n\t\telse\r\n\t\t\tplay_movie(\"gendata\\\\diablo1.smk\", true);\r\n\t\tif (*intro == StartUpIntro::Once) {\r\n\t\t\tintro.SetValue(StartUpIntro::Off);\r\n\t\t\tif (!demo::IsRunning()) SaveOptions();\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsAnyOf(*GetOptions().StartUp.splash, StartUpSplash::TitleDialog, StartUpSplash::LogoAndTitleDialog))\r\n\t\tUiTitleDialog();\r\n}\r\n\r\nvoid DiabloDeinit()\r\n{\r\n\tFreeItemGFX();\r\n\r\n\tLuaShutdown();\r\n\tShutDownScreenReader();\r\n\r\n\tif (gbSndInited)\r\n\t\teffects_cleanup_sfx();\r\n\tsnd_deinit();\r\n\tif (was_ui_init)\r\n\t\tUiDestroy();\r\n\tif (was_archives_init)\r\n\t\tinit_cleanup();\r\n\tif (was_window_init)\r\n\t\tdx_cleanup(); // Cleanup SDL surfaces stuff, so we have to do it before SDL_Quit().\r\n\tUnloadFonts();\r\n\tif (SDL_WasInit((~0U) & ~SDL_INIT_HAPTIC) != 0)\r\n\t\tSDL_Quit();\r\n}\r\n\r\ntl::expected<void, std::string> LoadLvlGFX()\r\n{\r\n\tassert(pDungeonCels == nullptr);\r\n\tconstexpr int SpecialCelWidth = 64;\r\n\r\n\tconst auto loadAll = [](const char *cel, const char *til, const char *special) -> tl::expected<void, std::string> {\r\n\t\tASSIGN_OR_RETURN(pDungeonCels, LoadFileInMemWithStatus(cel));\r\n\t\tASSIGN_OR_RETURN(pMegaTiles, LoadFileInMemWithStatus<MegaTile>(til));\r\n\t\tASSIGN_OR_RETURN(pSpecialCels, LoadCelWithStatus(special, SpecialCelWidth));\r\n\t\treturn {};\r\n\t};\r\n\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_TOWN: {\r\n\t\tauto cel = LoadFileInMemWithStatus(\"nlevels\\\\towndata\\\\town.cel\");\r\n\t\tif (!cel.has_value()) {\r\n\t\t\tASSIGN_OR_RETURN(pDungeonCels, LoadFileInMemWithStatus(\"levels\\\\towndata\\\\town.cel\"));\r\n\t\t} else {\r\n\t\t\tpDungeonCels = std::move(*cel);\r\n\t\t}\r\n\t\tauto til = LoadFileInMemWithStatus<MegaTile>(\"nlevels\\\\towndata\\\\town.til\");\r\n\t\tif (!til.has_value()) {\r\n\t\t\tASSIGN_OR_RETURN(pMegaTiles, LoadFileInMemWithStatus<MegaTile>(\"levels\\\\towndata\\\\town.til\"));\r\n\t\t} else {\r\n\t\t\tpMegaTiles = std::move(*til);\r\n\t\t}\r\n\t\tASSIGN_OR_RETURN(pSpecialCels, LoadCelWithStatus(\"levels\\\\towndata\\\\towns\", SpecialCelWidth));\r\n\t\treturn {};\r\n\t}\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\treturn loadAll(\r\n\t\t    \"levels\\\\l1data\\\\l1.cel\",\r\n\t\t    \"levels\\\\l1data\\\\l1.til\",\r\n\t\t    \"levels\\\\l1data\\\\l1s\");\r\n\tcase DTYPE_CATACOMBS:\r\n\t\treturn loadAll(\r\n\t\t    \"levels\\\\l2data\\\\l2.cel\",\r\n\t\t    \"levels\\\\l2data\\\\l2.til\",\r\n\t\t    \"levels\\\\l2data\\\\l2s\");\r\n\tcase DTYPE_CAVES:\r\n\t\treturn loadAll(\r\n\t\t    \"levels\\\\l3data\\\\l3.cel\",\r\n\t\t    \"levels\\\\l3data\\\\l3.til\",\r\n\t\t    \"levels\\\\l1data\\\\l1s\");\r\n\tcase DTYPE_HELL:\r\n\t\treturn loadAll(\r\n\t\t    \"levels\\\\l4data\\\\l4.cel\",\r\n\t\t    \"levels\\\\l4data\\\\l4.til\",\r\n\t\t    \"levels\\\\l2data\\\\l2s\");\r\n\tcase DTYPE_NEST:\r\n\t\treturn loadAll(\r\n\t\t    \"nlevels\\\\l6data\\\\l6.cel\",\r\n\t\t    \"nlevels\\\\l6data\\\\l6.til\",\r\n\t\t    \"levels\\\\l1data\\\\l1s\");\r\n\tcase DTYPE_CRYPT:\r\n\t\treturn loadAll(\r\n\t\t    \"nlevels\\\\l5data\\\\l5.cel\",\r\n\t\t    \"nlevels\\\\l5data\\\\l5.til\",\r\n\t\t    \"nlevels\\\\l5data\\\\l5s\");\r\n\tdefault:\r\n\t\treturn tl::make_unexpected(\"LoadLvlGFX\");\r\n\t}\r\n}\r\n\r\ntl::expected<void, std::string> LoadAllGFX()\r\n{\r\n\tIncProgress();\r\n#if !defined(USE_SDL1) && !defined(__vita__)\r\n\tInitVirtualGamepadGFX();\r\n#endif\r\n\tIncProgress();\r\n\tRETURN_IF_ERROR(InitObjectGFX());\r\n\tIncProgress();\r\n\tRETURN_IF_ERROR(InitMissileGFX());\r\n\tIncProgress();\r\n\treturn {};\r\n}\r\n\r\n/**\r\n * @param entry Where is the player entering from\r\n */\r\nvoid CreateLevel(lvl_entry entry)\r\n{\r\n\tCreateDungeon(DungeonSeeds[currlevel], entry);\r\n\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_TOWN:\r\n\t\tInitTownTriggers();\r\n\t\tbreak;\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\tInitL1Triggers();\r\n\t\tbreak;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\tInitL2Triggers();\r\n\t\tbreak;\r\n\tcase DTYPE_CAVES:\r\n\t\tInitL3Triggers();\r\n\t\tbreak;\r\n\tcase DTYPE_HELL:\r\n\t\tInitL4Triggers();\r\n\t\tbreak;\r\n\tcase DTYPE_NEST:\r\n\t\tInitHiveTriggers();\r\n\t\tbreak;\r\n\tcase DTYPE_CRYPT:\r\n\t\tInitCryptTriggers();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"CreateLevel\");\r\n\t}\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tFreeupstairs();\r\n\t}\r\n\tLoadRndLvlPal(leveltype);\r\n}\r\n\r\nvoid UnstuckChargers()\r\n{\r\n\tif (gbIsMultiplayer) {\r\n\t\tfor (Player &player : Players) {\r\n\t\t\tif (!player.plractive)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (player._pLvlChanging)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (!player.isOnActiveLevel())\r\n\t\t\t\tcontinue;\r\n\t\t\tif (&player == MyPlayer)\r\n\t\t\t\tcontinue;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tMonster &monster = Monsters[ActiveMonsters[i]];\r\n\t\tif (monster.mode == MonsterMode::Charge)\r\n\t\t\tmonster.mode = MonsterMode::Stand;\r\n\t}\r\n}\r\n\r\nvoid UpdateMonsterLights()\r\n{\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tMonster &monster = Monsters[ActiveMonsters[i]];\r\n\r\n\t\tif ((monster.flags & MFLAG_BERSERK) != 0) {\r\n\t\t\tconst int lightRadius = leveltype == DTYPE_NEST ? 9 : 3;\r\n\t\t\tmonster.lightId = AddLight(monster.position.tile, lightRadius);\r\n\t\t}\r\n\r\n\t\tif (monster.lightId != NO_LIGHT) {\r\n\t\t\tif (monster.lightId == MyPlayer->lightId) { // Fix old saves where some monsters had 0 instead of NO_LIGHT\r\n\t\t\t\tmonster.lightId = NO_LIGHT;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst Light &light = Lights[monster.lightId];\r\n\t\t\tif (monster.position.tile != light.position.tile) {\r\n\t\t\t\tChangeLightXY(monster.lightId, monster.position.tile);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid GameLogic()\r\n{\r\n\tif (!ProcessInput()) {\r\n\t\treturn;\r\n\t}\r\n\tif (gbProcessPlayers) {\r\n\t\tgGameLogicStep = GameLogicStep::ProcessPlayers;\r\n\t\tProcessPlayers();\r\n\t}\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tgGameLogicStep = GameLogicStep::ProcessMonsters;\r\n#ifdef _DEBUG\r\n\t\tif (!DebugInvisible)\r\n#endif\r\n\t\t\tProcessMonsters();\r\n\t\tgGameLogicStep = GameLogicStep::ProcessObjects;\r\n\t\tProcessObjects();\r\n\t\tgGameLogicStep = GameLogicStep::ProcessMissiles;\r\n\t\tProcessMissiles();\r\n\t\tgGameLogicStep = GameLogicStep::ProcessItems;\r\n\t\tProcessItems();\r\n\t\tProcessLightList();\r\n\t\tProcessVisionList();\r\n\t} else {\r\n\t\tgGameLogicStep = GameLogicStep::ProcessTowners;\r\n\t\tProcessTowners();\r\n\t\tgGameLogicStep = GameLogicStep::ProcessItemsTown;\r\n\t\tProcessItems();\r\n\t\tgGameLogicStep = GameLogicStep::ProcessMissilesTown;\r\n\t\tProcessMissiles();\r\n\t}\r\n\tgGameLogicStep = GameLogicStep::None;\r\n\r\n#ifdef _DEBUG\r\n\tif (DebugScrollViewEnabled && (SDL_GetModState() & SDL_KMOD_SHIFT) != 0) {\r\n\t\tScrollView();\r\n\t}\r\n#endif\r\n\r\n\tsound_update();\r\n\tCheckTriggers();\r\n\tCheckQuests();\r\n\tRedrawViewport();\r\n\tpfile_update(false);\r\n\r\n\tplrctrls_after_game_logic();\r\n}\r\n\r\nvoid TimeoutCursor(bool bTimeout)\r\n{\r\n\tif (bTimeout) {\r\n\t\tif (sgnTimeoutCurs == CURSOR_NONE && sgbMouseDown == CLICK_NONE) {\r\n\t\t\tsgnTimeoutCurs = pcurs;\r\n\t\t\tmulti_net_ping();\r\n\t\t\tInfoString = StringOrView {};\r\n\t\t\tAddInfoBoxString(_(\"-- Network timeout --\"));\r\n\t\t\tAddInfoBoxString(_(\"-- Waiting for players --\"));\r\n\t\t\tfor (uint8_t i = 0; i < Players.size(); i++) {\r\n\t\t\t\tbool isConnected = (player_state[i] & PS_CONNECTED) != 0;\r\n\t\t\t\tbool isActive = (player_state[i] & PS_ACTIVE) != 0;\r\n\t\t\t\tif (!(isConnected && !isActive)) continue;\r\n\r\n\t\t\t\tDvlNetLatencies latencies = DvlNet_GetLatencies(i);\r\n\r\n\t\t\t\tstd::string ping = fmt::format(\r\n\t\t\t\t    fmt::runtime(_(/* TRANSLATORS: {:s} means: Character Name */ \"Player {:s} is timing out!\")),\r\n\t\t\t\t    Players[i].name());\r\n\r\n\t\t\t\tStrAppend(ping, \"\\n  \", fmt::format(fmt::runtime(_(/* TRANSLATORS: Network connectivity statistics */ \"Echo latency: {:d} ms\")), latencies.echoLatency));\r\n\r\n\t\t\t\tif (latencies.providerLatency) {\r\n\t\t\t\t\tif (latencies.isRelayed && *latencies.isRelayed) {\r\n\t\t\t\t\t\tStrAppend(ping, \"\\n  \", fmt::format(fmt::runtime(_(/* TRANSLATORS: Network connectivity statistics */ \"Provider latency: {:d} ms (Relayed)\")), *latencies.providerLatency));\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tStrAppend(ping, \"\\n  \", fmt::format(fmt::runtime(_(/* TRANSLATORS: Network connectivity statistics */ \"Provider latency: {:d} ms\")), *latencies.providerLatency));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tEventPlrMsg(ping);\r\n\t\t\t}\r\n\t\t\tNewCursor(CURSOR_HOURGLASS);\r\n\t\t\tRedrawEverything();\r\n\t\t}\r\n\t\tscrollrt_draw_game_screen();\r\n\t} else if (sgnTimeoutCurs != CURSOR_NONE) {\r\n\t\t// Timeout is gone, we should restore the previous cursor.\r\n\t\t// But the timeout cursor could already be changed by the now processed messages (for example item cursor from CMD_GETITEM).\r\n\t\t// Changing the item cursor back to the previous (hand) cursor could result in deleted items, because this resets Player.HoldItem (see NewCursor).\r\n\t\tif (pcurs == CURSOR_HOURGLASS)\r\n\t\t\tNewCursor(sgnTimeoutCurs);\r\n\t\tsgnTimeoutCurs = CURSOR_NONE;\r\n\t\tInfoString = StringOrView {};\r\n\t\tRedrawEverything();\r\n\t}\r\n}\r\n\r\nvoid HelpKeyPressed()\r\n{\r\n\tif (HelpFlag) {\r\n\t\tHelpFlag = false;\r\n\t} else if (IsPlayerInStore()) {\r\n\t\tInfoString = StringOrView {};\r\n\t\tAddInfoBoxString(_(\"No help available\")); /// BUGFIX: message isn't displayed\r\n\t\tAddInfoBoxString(_(\"while in stores\"));\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t} else {\r\n\t\tCloseInventory();\r\n\t\tCloseCharPanel();\r\n\t\tSpellbookFlag = false;\r\n\t\tSpellSelectFlag = false;\r\n\t\tif (qtextflag && leveltype == DTYPE_TOWN) {\r\n\t\t\tqtextflag = false;\r\n\t\t\tstream_stop();\r\n\t\t}\r\n\t\tQuestLogIsOpen = false;\r\n\t\tCancelCurrentDiabloMsg();\r\n\t\tgamemenu_off();\r\n\t\tDisplayHelp();\r\n\t\tdoom_close();\r\n\t}\r\n}\r\n\r\nvoid InventoryKeyPressed()\r\n{\r\n\tif (IsPlayerInStore())\r\n\t\treturn;\r\n\tinvflag = !invflag;\r\n\tif (!IsLeftPanelOpen() && CanPanelsCoverView()) {\r\n\t\tif (!invflag) { // We closed the inventory\r\n\t\t\tif (MousePosition.x < 480 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition + Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t} else if (!SpellbookFlag) { // We opened the inventory\r\n\t\t\tif (MousePosition.x > 160 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition - Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tSpellbookFlag = false;\r\n\tCloseGoldWithdraw();\r\n\tCloseStash();\r\n}\r\n\r\nvoid CharacterSheetKeyPressed()\r\n{\r\n\tif (IsPlayerInStore())\r\n\t\treturn;\r\n\tif (!IsRightPanelOpen() && CanPanelsCoverView()) {\r\n\t\tif (CharFlag) { // We are closing the character sheet\r\n\t\t\tif (MousePosition.x > 160 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition - Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t} else if (!QuestLogIsOpen) { // We opened the character sheet\r\n\t\t\tif (MousePosition.x < 480 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition + Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tToggleCharPanel();\r\n}\r\n\r\nvoid PartyPanelSideToggleKeyPressed()\r\n{\r\n\tPartySidePanelOpen = !PartySidePanelOpen;\r\n}\r\n\r\nvoid QuestLogKeyPressed()\r\n{\r\n\tif (IsPlayerInStore())\r\n\t\treturn;\r\n\tif (!QuestLogIsOpen) {\r\n\t\tStartQuestlog();\r\n\t} else {\r\n\t\tQuestLogIsOpen = false;\r\n\t}\r\n\tif (!IsRightPanelOpen() && CanPanelsCoverView()) {\r\n\t\tif (!QuestLogIsOpen) { // We closed the quest log\r\n\t\t\tif (MousePosition.x > 160 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition - Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t} else if (!CharFlag) { // We opened the character quest log\r\n\t\t\tif (MousePosition.x < 480 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition + Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tCloseCharPanel();\r\n\tCloseGoldWithdraw();\r\n\tCloseStash();\r\n}\r\n\r\nvoid DisplaySpellsKeyPressed()\r\n{\r\n\tif (IsPlayerInStore())\r\n\t\treturn;\r\n\tCloseCharPanel();\r\n\tQuestLogIsOpen = false;\r\n\tCloseInventory();\r\n\tSpellbookFlag = false;\r\n\tif (!SpellSelectFlag) {\r\n\t\tDoSpeedBook();\r\n\t} else {\r\n\t\tSpellSelectFlag = false;\r\n\t}\r\n\tLastPlayerAction = PlayerActionType::None;\r\n}\r\n\r\nvoid SpellBookKeyPressed()\r\n{\r\n\tif (IsPlayerInStore())\r\n\t\treturn;\r\n\tSpellbookFlag = !SpellbookFlag;\r\n\tif (!IsLeftPanelOpen() && CanPanelsCoverView()) {\r\n\t\tif (!SpellbookFlag) { // We closed the inventory\r\n\t\t\tif (MousePosition.x < 480 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition + Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t} else if (!invflag) { // We opened the inventory\r\n\t\t\tif (MousePosition.x > 160 && MousePosition.y < GetMainPanel().position.y) {\r\n\t\t\t\tSetCursorPos(MousePosition - Displacement { 160, 0 });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tCloseInventory();\r\n}\r\n\r\nvoid CycleSpellHotkeys(bool next)\r\n{\r\n\tStaticVector<size_t, NumHotkeys> validHotKeyIndexes;\r\n\tstd::optional<size_t> currentIndex;\r\n\tfor (size_t slot = 0; slot < NumHotkeys; slot++) {\r\n\t\tif (!IsValidSpeedSpell(slot))\r\n\t\t\tcontinue;\r\n\t\tif (MyPlayer->_pRSpell == MyPlayer->_pSplHotKey[slot] && MyPlayer->_pRSplType == MyPlayer->_pSplTHotKey[slot]) {\r\n\t\t\t// found current\r\n\t\t\tcurrentIndex = validHotKeyIndexes.size();\r\n\t\t}\r\n\t\tvalidHotKeyIndexes.emplace_back(slot);\r\n\t}\r\n\tif (validHotKeyIndexes.size() == 0)\r\n\t\treturn;\r\n\r\n\tsize_t newIndex;\r\n\tif (!currentIndex) {\r\n\t\tnewIndex = next ? 0 : (validHotKeyIndexes.size() - 1);\r\n\t} else if (next) {\r\n\t\tnewIndex = (*currentIndex == validHotKeyIndexes.size() - 1) ? 0 : (*currentIndex + 1);\r\n\t} else {\r\n\t\tnewIndex = *currentIndex == 0 ? (validHotKeyIndexes.size() - 1) : (*currentIndex - 1);\r\n\t}\r\n\tToggleSpell(validHotKeyIndexes[newIndex]);\r\n}\r\n\r\nbool IsPlayerDead()\r\n{\r\n\treturn MyPlayer->_pmode == PM_DEATH || MyPlayerIsDead;\r\n}\r\n\r\nbool IsGameRunning()\r\n{\r\n\treturn PauseMode != 2;\r\n}\r\n\r\nbool CanPlayerTakeAction()\r\n{\r\n\treturn !IsPlayerDead() && IsGameRunning();\r\n}\r\n\r\nbool CanAutomapBeToggledOff()\r\n{\r\n\t// check if every window is closed - if yes, automap can be toggled off\r\n\tif (!QuestLogIsOpen && !IsWithdrawGoldOpen && !IsStashOpen && !CharFlag\r\n\t    && !SpellbookFlag && !invflag && !isGameMenuOpen && !qtextflag && !SpellSelectFlag\r\n\t    && !ChatLogFlag && !HelpFlag)\r\n\t\treturn true;\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid OptionLanguageCodeChanged()\r\n{\r\n\tUnloadFonts();\r\n\tLanguageInitialize();\r\n\tLoadLanguageArchive();\r\n\teffects_cleanup_sfx(false);\r\n\tif (gbRunGame)\r\n\t\tsound_init();\r\n\telse\r\n\t\tui_sound_init();\r\n}\r\n\r\nconst auto OptionChangeHandlerLanguage = (GetOptions().Language.code.SetValueChangedCallback(OptionLanguageCodeChanged), true);\r\n\r\n} // namespace\r\n\r\nvoid InitKeymapActions()\r\n{\r\n\tOptions &options = GetOptions();\r\n\tfor (uint32_t i = 0; i < 8; ++i) {\r\n\t\toptions.Keymapper.AddAction(\r\n\t\t    \"BeltItem{}\",\r\n\t\t    N_(\"Belt item {}\"),\r\n\t\t    N_(\"Use Belt item.\"),\r\n\t\t    '1' + i,\r\n\t\t    [i] {\r\n\t\t\t    const Player &myPlayer = *MyPlayer;\r\n\t\t\t    if (!myPlayer.SpdList[i].isEmpty() && myPlayer.SpdList[i]._itype != ItemType::Gold) {\r\n\t\t\t\t    UseInvItem(INVITEM_BELT_FIRST + i);\r\n\t\t\t    }\r\n\t\t    },\r\n\t\t    nullptr,\r\n\t\t    CanPlayerTakeAction,\r\n\t\t    i + 1);\r\n\t}\r\n\tfor (uint32_t i = 0; i < NumHotkeys; ++i) {\r\n\t\toptions.Keymapper.AddAction(\r\n\t\t    \"QuickSpell{}\",\r\n\t\t    N_(\"Quick spell {}\"),\r\n\t\t    N_(\"Hotkey for skill or spell.\"),\r\n\t\t    i < 4 ? static_cast<uint32_t>(SDLK_F5) + i : static_cast<uint32_t>(SDLK_UNKNOWN),\r\n\t\t    [i]() {\r\n\t\t\t    if (SpellSelectFlag) {\r\n\t\t\t\t    SetSpeedSpell(i);\r\n\t\t\t\t    return;\r\n\t\t\t    }\r\n\t\t\t    if (!*GetOptions().Gameplay.quickCast)\r\n\t\t\t\t    ToggleSpell(i);\r\n\t\t\t    else\r\n\t\t\t\t    QuickCast(i);\r\n\t\t    },\r\n\t\t    nullptr,\r\n\t\t    CanPlayerTakeAction,\r\n\t\t    i + 1);\r\n\t}\r\n\toptions.Keymapper.AddAction(\r\n\t    \"QuickSpellPrevious\",\r\n\t    N_(\"Previous quick spell\"),\r\n\t    N_(\"Selects the previous quick spell (cycles).\"),\r\n\t    MouseScrollUpButton,\r\n\t    [] { CycleSpellHotkeys(false); },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"QuickSpellNext\",\r\n\t    N_(\"Next quick spell\"),\r\n\t    N_(\"Selects the next quick spell (cycles).\"),\r\n\t    MouseScrollDownButton,\r\n\t    [] { CycleSpellHotkeys(true); },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"UseHealthPotion\",\r\n\t    N_(\"Use health potion\"),\r\n\t    N_(\"Use health potions from belt.\"),\r\n\t    SDLK_UNKNOWN,\r\n\t    [] { UseBeltItem(BeltItemType::Healing); },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"UseManaPotion\",\r\n\t    N_(\"Use mana potion\"),\r\n\t    N_(\"Use mana potions from belt.\"),\r\n\t    SDLK_UNKNOWN,\r\n\t    [] { UseBeltItem(BeltItemType::Mana); },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"DisplaySpells\",\r\n\t    N_(\"Speedbook\"),\r\n\t    N_(\"Open Speedbook.\"),\r\n\t    'S',\r\n\t    DisplaySpellsKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"QuickSave\",\r\n\t    N_(\"Quick save\"),\r\n\t    N_(\"Saves the game.\"),\r\n\t    SDLK_F2,\r\n\t    [] { gamemenu_save_game(false); },\r\n\t    nullptr,\r\n\t    [&]() { return !gbIsMultiplayer && CanPlayerTakeAction(); });\r\n\toptions.Keymapper.AddAction(\r\n\t    \"QuickLoad\",\r\n\t    N_(\"Quick load\"),\r\n\t    N_(\"Loads the game.\"),\r\n\t    SDLK_F3,\r\n\t    [] { gamemenu_load_game(false); },\r\n\t    nullptr,\r\n\t    [&]() { return !gbIsMultiplayer && gbValidSaveFile && !IsPlayerInStore() && IsGameRunning(); });\r\n#ifndef NOEXIT\r\n\toptions.Keymapper.AddAction(\r\n\t    \"QuitGame\",\r\n\t    N_(\"Quit game\"),\r\n\t    N_(\"Closes the game.\"),\r\n\t    SDLK_UNKNOWN,\r\n\t    [] { gamemenu_quit_game(false); });\r\n#endif\r\n\toptions.Keymapper.AddAction(\r\n\t    \"StopHero\",\r\n\t    N_(\"Stop hero\"),\r\n\t    N_(\"Stops walking and cancel pending actions.\"),\r\n\t    SDLK_UNKNOWN,\r\n\t    [] { MyPlayer->Stop(); },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"ItemHighlighting\",\r\n\t    N_(\"Item highlighting\"),\r\n\t    N_(\"Show/hide items on ground.\"),\r\n\t    SDLK_LALT,\r\n\t    [] { HighlightKeyPressed(true); },\r\n\t    [] { HighlightKeyPressed(false); });\r\n\toptions.Keymapper.AddAction(\r\n\t    \"ToggleItemHighlighting\",\r\n\t    N_(\"Toggle item highlighting\"),\r\n\t    N_(\"Permanent show/hide items on ground.\"),\r\n\t    SDLK_RCTRL,\r\n\t    nullptr,\r\n\t    [] { ToggleItemLabelHighlight(); });\r\n\toptions.Keymapper.AddAction(\r\n\t    \"ToggleAutomap\",\r\n\t    N_(\"Toggle automap\"),\r\n\t    N_(\"Toggles if automap is displayed.\"),\r\n\t    SDLK_TAB,\r\n\t    DoAutoMap,\r\n\t    nullptr,\r\n\t    IsGameRunning);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"CycleAutomapType\",\r\n\t    N_(\"Cycle map type\"),\r\n\t    N_(\"Opaque -> Transparent -> Minimap -> None\"),\r\n\t    SDLK_M,\r\n\t    CycleAutomapType,\r\n\t    nullptr,\r\n\t    IsGameRunning);\r\n\r\n\toptions.Keymapper.AddAction(\r\n\t    \"Inventory\",\r\n\t    N_(\"Inventory\"),\r\n\t    N_(\"Open Inventory screen.\"),\r\n\t    'I',\r\n\t    InventoryKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"Character\",\r\n\t    N_(\"Character\"),\r\n\t    N_(\"Open Character screen.\"),\r\n\t    'C',\r\n\t    CharacterSheetKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"Party\",\r\n\t    N_(\"Party\"),\r\n\t    N_(\"Open side Party panel.\"),\r\n\t    'Y',\r\n\t    PartyPanelSideToggleKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"QuestLog\",\r\n\t    N_(\"Quest log\"),\r\n\t    N_(\"Open Quest log.\"),\r\n\t    'Q',\r\n\t    QuestLogKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"SpellBook\",\r\n\t    N_(\"Spellbook\"),\r\n\t    N_(\"Open Spellbook.\"),\r\n\t    'B',\r\n\t    SpellBookKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\tfor (uint32_t i = 0; i < QuickMessages.size(); ++i) {\r\n\t\toptions.Keymapper.AddAction(\r\n\t\t    \"QuickMessage{}\",\r\n\t\t    N_(\"Quick Message {}\"),\r\n\t\t    N_(\"Use Quick Message in chat.\"),\r\n\t\t    (i < 4) ? static_cast<uint32_t>(SDLK_F9) + i : static_cast<uint32_t>(SDLK_UNKNOWN),\r\n\t\t    [i]() { DiabloHotkeyMsg(i); },\r\n\t\t    nullptr,\r\n\t\t    nullptr,\r\n\t\t    i + 1);\r\n\t}\r\n\toptions.Keymapper.AddAction(\r\n\t    \"HideInfoScreens\",\r\n\t    N_(\"Hide Info Screens\"),\r\n\t    N_(\"Hide all info screens.\"),\r\n\t    SDLK_SPACE,\r\n\t    [] {\r\n\t\t    if (CanAutomapBeToggledOff())\r\n\t\t\t    AutomapActive = false;\r\n\r\n\t\t    ClosePanels();\r\n\t\t    HelpFlag = false;\r\n\t\t    ChatLogFlag = false;\r\n\t\t    SpellSelectFlag = false;\r\n\t\t    if (qtextflag && leveltype == DTYPE_TOWN) {\r\n\t\t\t    qtextflag = false;\r\n\t\t\t    stream_stop();\r\n\t\t    }\r\n\r\n\t\t    CancelCurrentDiabloMsg();\r\n\t\t    gamemenu_off();\r\n\t\t    doom_close();\r\n\t    },\r\n\t    nullptr,\r\n\t    IsGameRunning);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"Zoom\",\r\n\t    N_(\"Zoom\"),\r\n\t    N_(\"Zoom Game Screen.\"),\r\n\t    'Z',\r\n\t    [] {\r\n\t\t    GetOptions().Graphics.zoom.SetValue(!*GetOptions().Graphics.zoom);\r\n\t\t    CalcViewportGeometry();\r\n\t    },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"PauseGame\",\r\n\t    N_(\"Pause Game\"),\r\n\t    N_(\"Pauses the game.\"),\r\n\t    'P',\r\n\t    diablo_pause_game);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"PauseGameAlternate\",\r\n\t    N_(\"Pause Game (Alternate)\"),\r\n\t    N_(\"Pauses the game.\"),\r\n\t    SDLK_PAUSE,\r\n\t    diablo_pause_game);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"DecreaseBrightness\",\r\n\t    N_(\"Decrease Brightness\"),\r\n\t    N_(\"Reduce screen brightness.\"),\r\n\t    'F',\r\n\t    DecreaseBrightness,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"IncreaseBrightness\",\r\n\t    N_(\"Increase Brightness\"),\r\n\t    N_(\"Increase screen brightness.\"),\r\n\t    'G',\r\n\t    IncreaseBrightness,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"Help\",\r\n\t    N_(\"Help\"),\r\n\t    N_(\"Open Help Screen.\"),\r\n\t    SDLK_F1,\r\n\t    HelpKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"Screenshot\",\r\n\t    N_(\"Screenshot\"),\r\n\t    N_(\"Takes a screenshot.\"),\r\n\t    SDLK_PRINTSCREEN,\r\n\t    nullptr,\r\n\t    CaptureScreen);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"GameInfo\",\r\n\t    N_(\"Game info\"),\r\n\t    N_(\"Displays game infos.\"),\r\n\t    'V',\r\n\t    [] {\r\n\t\t    EventPlrMsg(fmt::format(\r\n\t\t                    fmt::runtime(_(/* TRANSLATORS: {:s} means: Project Name, Game Version. */ \"{:s} {:s}\")),\r\n\t\t                    PROJECT_NAME,\r\n\t\t                    PROJECT_VERSION),\r\n\t\t        UiFlags::ColorWhite);\r\n\t    },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"ChatLog\",\r\n\t    N_(\"Chat Log\"),\r\n\t    N_(\"Displays chat log.\"),\r\n\t    'L',\r\n\t    [] {\r\n\t\t    ToggleChatLog();\r\n\t    });\r\n\toptions.Keymapper.AddAction(\r\n\t    \"SortInv\",\r\n\t    N_(\"Sort Inventory\"),\r\n\t    N_(\"Sorts the inventory.\"),\r\n\t    'R',\r\n\t    [] {\r\n\t\t    ReorganizeInventory(*MyPlayer);\r\n\t    });\r\n#ifdef _DEBUG\r\n\toptions.Keymapper.AddAction(\r\n\t    \"OpenConsole\",\r\n\t    N_(\"Console\"),\r\n\t    N_(\"Opens Lua console.\"),\r\n\t    SDLK_GRAVE,\r\n\t    OpenConsole);\r\n\toptions.Keymapper.AddAction(\r\n\t    \"DebugToggle\",\r\n\t    \"Debug toggle\",\r\n\t    \"Programming is like magic.\",\r\n\t    'X',\r\n\t    [] {\r\n\t\t    DebugToggle = !DebugToggle;\r\n\t    });\r\n#endif\r\n\toptions.Keymapper.CommitActions();\r\n}\r\n\r\nvoid InitPadmapActions()\r\n{\r\n\tOptions &options = GetOptions();\r\n\tfor (int i = 0; i < 8; ++i) {\r\n\t\toptions.Padmapper.AddAction(\r\n\t\t    \"BeltItem{}\",\r\n\t\t    N_(\"Belt item {}\"),\r\n\t\t    N_(\"Use Belt item.\"),\r\n\t\t    ControllerButton_NONE,\r\n\t\t    [i] {\r\n\t\t\t    const Player &myPlayer = *MyPlayer;\r\n\t\t\t    if (!myPlayer.SpdList[i].isEmpty() && myPlayer.SpdList[i]._itype != ItemType::Gold) {\r\n\t\t\t\t    UseInvItem(INVITEM_BELT_FIRST + i);\r\n\t\t\t    }\r\n\t\t    },\r\n\t\t    nullptr,\r\n\t\t    CanPlayerTakeAction,\r\n\t\t    i + 1);\r\n\t}\r\n\tfor (uint32_t i = 0; i < NumHotkeys; ++i) {\r\n\t\toptions.Padmapper.AddAction(\r\n\t\t    \"QuickSpell{}\",\r\n\t\t    N_(\"Quick spell {}\"),\r\n\t\t    N_(\"Hotkey for skill or spell.\"),\r\n\t\t    ControllerButton_NONE,\r\n\t\t    [i]() {\r\n\t\t\t    if (SpellSelectFlag) {\r\n\t\t\t\t    SetSpeedSpell(i);\r\n\t\t\t\t    return;\r\n\t\t\t    }\r\n\t\t\t    if (!*GetOptions().Gameplay.quickCast)\r\n\t\t\t\t    ToggleSpell(i);\r\n\t\t\t    else\r\n\t\t\t\t    QuickCast(i);\r\n\t\t    },\r\n\t\t    nullptr,\r\n\t\t    []() { return CanPlayerTakeAction() && !InGameMenu(); },\r\n\t\t    i + 1);\r\n\t}\r\n\toptions.Padmapper.AddAction(\r\n\t    \"PrimaryAction\",\r\n\t    N_(\"Primary action\"),\r\n\t    N_(\"Attack monsters, talk to towners, lift and place inventory items.\"),\r\n\t    ControllerButton_BUTTON_B,\r\n\t    [] {\r\n\t\t    ControllerActionHeld = GameActionType_PRIMARY_ACTION;\r\n\t\t    LastPlayerAction = PlayerActionType::None;\r\n\t\t    PerformPrimaryAction();\r\n\t    },\r\n\t    [] {\r\n\t\t    ControllerActionHeld = GameActionType_NONE;\r\n\t\t    LastPlayerAction = PlayerActionType::None;\r\n\t    },\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"SecondaryAction\",\r\n\t    N_(\"Secondary action\"),\r\n\t    N_(\"Open chests, interact with doors, pick up items.\"),\r\n\t    ControllerButton_BUTTON_Y,\r\n\t    [] {\r\n\t\t    ControllerActionHeld = GameActionType_SECONDARY_ACTION;\r\n\t\t    LastPlayerAction = PlayerActionType::None;\r\n\t\t    PerformSecondaryAction();\r\n\t    },\r\n\t    [] {\r\n\t\t    ControllerActionHeld = GameActionType_NONE;\r\n\t\t    LastPlayerAction = PlayerActionType::None;\r\n\t    },\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"SpellAction\",\r\n\t    N_(\"Spell action\"),\r\n\t    N_(\"Cast the active spell.\"),\r\n\t    ControllerButton_BUTTON_X,\r\n\t    [] {\r\n\t\t    ControllerActionHeld = GameActionType_CAST_SPELL;\r\n\t\t    LastPlayerAction = PlayerActionType::None;\r\n\t\t    PerformSpellAction();\r\n\t    },\r\n\t    [] {\r\n\t\t    ControllerActionHeld = GameActionType_NONE;\r\n\t\t    LastPlayerAction = PlayerActionType::None;\r\n\t    },\r\n\t    []() { return CanPlayerTakeAction() && !InGameMenu(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"CancelAction\",\r\n\t    N_(\"Cancel action\"),\r\n\t    N_(\"Close menus.\"),\r\n\t    ControllerButton_BUTTON_A,\r\n\t    [] {\r\n\t\t    if (DoomFlag) {\r\n\t\t\t    doom_close();\r\n\t\t\t    return;\r\n\t\t    }\r\n\r\n\t\t    GameAction action;\r\n\t\t    if (SpellSelectFlag)\r\n\t\t\t    action = GameAction(GameActionType_TOGGLE_QUICK_SPELL_MENU);\r\n\t\t    else if (invflag)\r\n\t\t\t    action = GameAction(GameActionType_TOGGLE_INVENTORY);\r\n\t\t    else if (SpellbookFlag)\r\n\t\t\t    action = GameAction(GameActionType_TOGGLE_SPELL_BOOK);\r\n\t\t    else if (QuestLogIsOpen)\r\n\t\t\t    action = GameAction(GameActionType_TOGGLE_QUEST_LOG);\r\n\t\t    else if (CharFlag)\r\n\t\t\t    action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO);\r\n\t\t    ProcessGameAction(action);\r\n\t    },\r\n\t    nullptr,\r\n\t    [] { return DoomFlag || SpellSelectFlag || invflag || SpellbookFlag || QuestLogIsOpen || CharFlag; });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MoveUp\",\r\n\t    N_(\"Move up\"),\r\n\t    N_(\"Moves the player character up.\"),\r\n\t    ControllerButton_BUTTON_DPAD_UP,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MoveDown\",\r\n\t    N_(\"Move down\"),\r\n\t    N_(\"Moves the player character down.\"),\r\n\t    ControllerButton_BUTTON_DPAD_DOWN,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MoveLeft\",\r\n\t    N_(\"Move left\"),\r\n\t    N_(\"Moves the player character left.\"),\r\n\t    ControllerButton_BUTTON_DPAD_LEFT,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MoveRight\",\r\n\t    N_(\"Move right\"),\r\n\t    N_(\"Moves the player character right.\"),\r\n\t    ControllerButton_BUTTON_DPAD_RIGHT,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"StandGround\",\r\n\t    N_(\"Stand ground\"),\r\n\t    N_(\"Hold to prevent the player from moving.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"ToggleStandGround\",\r\n\t    N_(\"Toggle stand ground\"),\r\n\t    N_(\"Toggle whether the player moves.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] { StandToggle = !StandToggle; },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"UseHealthPotion\",\r\n\t    N_(\"Use health potion\"),\r\n\t    N_(\"Use health potions from belt.\"),\r\n\t    ControllerButton_BUTTON_LEFTSHOULDER,\r\n\t    [] { UseBeltItem(BeltItemType::Healing); },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"UseManaPotion\",\r\n\t    N_(\"Use mana potion\"),\r\n\t    N_(\"Use mana potions from belt.\"),\r\n\t    ControllerButton_BUTTON_RIGHTSHOULDER,\r\n\t    [] { UseBeltItem(BeltItemType::Mana); },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"Character\",\r\n\t    N_(\"Character\"),\r\n\t    N_(\"Open Character screen.\"),\r\n\t    ControllerButton_AXIS_TRIGGERLEFT,\r\n\t    [] {\r\n\t\t    ProcessGameAction(GameAction { GameActionType_TOGGLE_CHARACTER_INFO });\r\n\t    },\r\n\t    nullptr,\r\n\t    []() { return CanPlayerTakeAction() && !InGameMenu(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"Inventory\",\r\n\t    N_(\"Inventory\"),\r\n\t    N_(\"Open Inventory screen.\"),\r\n\t    ControllerButton_AXIS_TRIGGERRIGHT,\r\n\t    [] {\r\n\t\t    ProcessGameAction(GameAction { GameActionType_TOGGLE_INVENTORY });\r\n\t    },\r\n\t    nullptr,\r\n\t    []() { return CanPlayerTakeAction() && !InGameMenu(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"QuestLog\",\r\n\t    N_(\"Quest log\"),\r\n\t    N_(\"Open Quest log.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_AXIS_TRIGGERLEFT },\r\n\t    [] {\r\n\t\t    ProcessGameAction(GameAction { GameActionType_TOGGLE_QUEST_LOG });\r\n\t    },\r\n\t    nullptr,\r\n\t    []() { return CanPlayerTakeAction() && !InGameMenu(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"SpellBook\",\r\n\t    N_(\"Spellbook\"),\r\n\t    N_(\"Open Spellbook.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_AXIS_TRIGGERRIGHT },\r\n\t    [] {\r\n\t\t    ProcessGameAction(GameAction { GameActionType_TOGGLE_SPELL_BOOK });\r\n\t    },\r\n\t    nullptr,\r\n\t    []() { return CanPlayerTakeAction() && !InGameMenu(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"DisplaySpells\",\r\n\t    N_(\"Speedbook\"),\r\n\t    N_(\"Open Speedbook.\"),\r\n\t    ControllerButton_BUTTON_A,\r\n\t    [] {\r\n\t\t    ProcessGameAction(GameAction { GameActionType_TOGGLE_QUICK_SPELL_MENU });\r\n\t    },\r\n\t    nullptr,\r\n\t    []() { return CanPlayerTakeAction() && !InGameMenu(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"ToggleAutomap\",\r\n\t    N_(\"Toggle automap\"),\r\n\t    N_(\"Toggles if automap is displayed.\"),\r\n\t    ControllerButton_BUTTON_LEFTSTICK,\r\n\t    DoAutoMap);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"AutomapMoveUp\",\r\n\t    N_(\"Automap Move Up\"),\r\n\t    N_(\"Moves the automap up when active.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"AutomapMoveDown\",\r\n\t    N_(\"Automap Move Down\"),\r\n\t    N_(\"Moves the automap down when active.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"AutomapMoveLeft\",\r\n\t    N_(\"Automap Move Left\"),\r\n\t    N_(\"Moves the automap left when active.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"AutomapMoveRight\",\r\n\t    N_(\"Automap Move Right\"),\r\n\t    N_(\"Moves the automap right when active.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MouseUp\",\r\n\t    N_(\"Move mouse up\"),\r\n\t    N_(\"Simulates upward mouse movement.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_BUTTON_DPAD_UP },\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MouseDown\",\r\n\t    N_(\"Move mouse down\"),\r\n\t    N_(\"Simulates downward mouse movement.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_BUTTON_DPAD_DOWN },\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MouseLeft\",\r\n\t    N_(\"Move mouse left\"),\r\n\t    N_(\"Simulates leftward mouse movement.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_BUTTON_DPAD_LEFT },\r\n\t    [] {});\r\n\toptions.Padmapper.AddAction(\r\n\t    \"MouseRight\",\r\n\t    N_(\"Move mouse right\"),\r\n\t    N_(\"Simulates rightward mouse movement.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_BUTTON_DPAD_RIGHT },\r\n\t    [] {});\r\n\tauto leftMouseDown = [] {\r\n\t\tconst ControllerButtonCombo standGroundCombo = GetOptions().Padmapper.ButtonComboForAction(\"StandGround\");\r\n\t\tconst bool standGround = StandToggle || IsControllerButtonComboPressed(standGroundCombo);\r\n\t\tsgbMouseDown = CLICK_LEFT;\r\n\t\tLeftMouseDown(standGround ? SDL_KMOD_SHIFT : SDL_KMOD_NONE);\r\n\t};\r\n\tauto leftMouseUp = [] {\r\n\t\tconst ControllerButtonCombo standGroundCombo = GetOptions().Padmapper.ButtonComboForAction(\"StandGround\");\r\n\t\tconst bool standGround = StandToggle || IsControllerButtonComboPressed(standGroundCombo);\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\tsgbMouseDown = CLICK_NONE;\r\n\t\tLeftMouseUp(standGround ? SDL_KMOD_SHIFT : SDL_KMOD_NONE);\r\n\t};\r\n\toptions.Padmapper.AddAction(\r\n\t    \"LeftMouseClick1\",\r\n\t    N_(\"Left mouse click\"),\r\n\t    N_(\"Simulates the left mouse button.\"),\r\n\t    ControllerButton_BUTTON_RIGHTSTICK,\r\n\t    leftMouseDown,\r\n\t    leftMouseUp);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"LeftMouseClick2\",\r\n\t    N_(\"Left mouse click\"),\r\n\t    N_(\"Simulates the left mouse button.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_BUTTON_LEFTSHOULDER },\r\n\t    leftMouseDown,\r\n\t    leftMouseUp);\r\n\tauto rightMouseDown = [] {\r\n\t\tconst ControllerButtonCombo standGroundCombo = GetOptions().Padmapper.ButtonComboForAction(\"StandGround\");\r\n\t\tconst bool standGround = StandToggle || IsControllerButtonComboPressed(standGroundCombo);\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\tsgbMouseDown = CLICK_RIGHT;\r\n\t\tRightMouseDown(standGround);\r\n\t};\r\n\tauto rightMouseUp = [] {\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\tsgbMouseDown = CLICK_NONE;\r\n\t};\r\n\toptions.Padmapper.AddAction(\r\n\t    \"RightMouseClick1\",\r\n\t    N_(\"Right mouse click\"),\r\n\t    N_(\"Simulates the right mouse button.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_BUTTON_RIGHTSTICK },\r\n\t    rightMouseDown,\r\n\t    rightMouseUp);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"RightMouseClick2\",\r\n\t    N_(\"Right mouse click\"),\r\n\t    N_(\"Simulates the right mouse button.\"),\r\n\t    { ControllerButton_BUTTON_BACK, ControllerButton_BUTTON_RIGHTSHOULDER },\r\n\t    rightMouseDown,\r\n\t    rightMouseUp);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"PadHotspellMenu\",\r\n\t    N_(\"Gamepad hotspell menu\"),\r\n\t    N_(\"Hold to set or use spell hotkeys.\"),\r\n\t    ControllerButton_BUTTON_BACK,\r\n\t    [] { PadHotspellMenuActive = true; },\r\n\t    [] { PadHotspellMenuActive = false; });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"PadMenuNavigator\",\r\n\t    N_(\"Gamepad menu navigator\"),\r\n\t    N_(\"Hold to access gamepad menu navigation.\"),\r\n\t    ControllerButton_BUTTON_START,\r\n\t    [] { PadMenuNavigatorActive = true; },\r\n\t    [] { PadMenuNavigatorActive = false; });\r\n\tauto toggleGameMenu = [] {\r\n\t\tconst bool inMenu = gmenu_is_active();\r\n\t\tPressEscKey();\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\tPadHotspellMenuActive = false;\r\n\t\tPadMenuNavigatorActive = false;\r\n\t\tif (!inMenu)\r\n\t\t\tgamemenu_on();\r\n\t};\r\n\toptions.Padmapper.AddAction(\r\n\t    \"ToggleGameMenu1\",\r\n\t    N_(\"Toggle game menu\"),\r\n\t    N_(\"Opens the game menu.\"),\r\n\t    {\r\n\t        ControllerButton_BUTTON_BACK,\r\n\t        ControllerButton_BUTTON_START,\r\n\t    },\r\n\t    toggleGameMenu);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"ToggleGameMenu2\",\r\n\t    N_(\"Toggle game menu\"),\r\n\t    N_(\"Opens the game menu.\"),\r\n\t    {\r\n\t        ControllerButton_BUTTON_START,\r\n\t        ControllerButton_BUTTON_BACK,\r\n\t    },\r\n\t    toggleGameMenu);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"QuickSave\",\r\n\t    N_(\"Quick save\"),\r\n\t    N_(\"Saves the game.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] { gamemenu_save_game(false); },\r\n\t    nullptr,\r\n\t    [&]() { return !gbIsMultiplayer && CanPlayerTakeAction(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"QuickLoad\",\r\n\t    N_(\"Quick load\"),\r\n\t    N_(\"Loads the game.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] { gamemenu_load_game(false); },\r\n\t    nullptr,\r\n\t    [&]() { return !gbIsMultiplayer && gbValidSaveFile && !IsPlayerInStore() && IsGameRunning(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"ItemHighlighting\",\r\n\t    N_(\"Item highlighting\"),\r\n\t    N_(\"Show/hide items on ground.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] { HighlightKeyPressed(true); },\r\n\t    [] { HighlightKeyPressed(false); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"ToggleItemHighlighting\",\r\n\t    N_(\"Toggle item highlighting\"),\r\n\t    N_(\"Permanent show/hide items on ground.\"),\r\n\t    ControllerButton_NONE,\r\n\t    nullptr,\r\n\t    [] { ToggleItemLabelHighlight(); });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"HideInfoScreens\",\r\n\t    N_(\"Hide Info Screens\"),\r\n\t    N_(\"Hide all info screens.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {\r\n\t\t    if (CanAutomapBeToggledOff())\r\n\t\t\t    AutomapActive = false;\r\n\r\n\t\t    ClosePanels();\r\n\t\t    HelpFlag = false;\r\n\t\t    ChatLogFlag = false;\r\n\t\t    SpellSelectFlag = false;\r\n\t\t    if (qtextflag && leveltype == DTYPE_TOWN) {\r\n\t\t\t    qtextflag = false;\r\n\t\t\t    stream_stop();\r\n\t\t    }\r\n\r\n\t\t    CancelCurrentDiabloMsg();\r\n\t\t    gamemenu_off();\r\n\t\t    doom_close();\r\n\t    },\r\n\t    nullptr,\r\n\t    IsGameRunning);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"Zoom\",\r\n\t    N_(\"Zoom\"),\r\n\t    N_(\"Zoom Game Screen.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {\r\n\t\t    GetOptions().Graphics.zoom.SetValue(!*GetOptions().Graphics.zoom);\r\n\t\t    CalcViewportGeometry();\r\n\t    },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"PauseGame\",\r\n\t    N_(\"Pause Game\"),\r\n\t    N_(\"Pauses the game.\"),\r\n\t    ControllerButton_NONE,\r\n\t    diablo_pause_game);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"DecreaseBrightness\",\r\n\t    N_(\"Decrease Brightness\"),\r\n\t    N_(\"Reduce screen brightness.\"),\r\n\t    ControllerButton_NONE,\r\n\t    DecreaseBrightness,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"IncreaseBrightness\",\r\n\t    N_(\"Increase Brightness\"),\r\n\t    N_(\"Increase screen brightness.\"),\r\n\t    ControllerButton_NONE,\r\n\t    IncreaseBrightness,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"Help\",\r\n\t    N_(\"Help\"),\r\n\t    N_(\"Open Help Screen.\"),\r\n\t    ControllerButton_NONE,\r\n\t    HelpKeyPressed,\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"Screenshot\",\r\n\t    N_(\"Screenshot\"),\r\n\t    N_(\"Takes a screenshot.\"),\r\n\t    ControllerButton_NONE,\r\n\t    nullptr,\r\n\t    CaptureScreen);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"GameInfo\",\r\n\t    N_(\"Game info\"),\r\n\t    N_(\"Displays game infos.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {\r\n\t\t    EventPlrMsg(fmt::format(\r\n\t\t                    fmt::runtime(_(/* TRANSLATORS: {:s} means: Project Name, Game Version. */ \"{:s} {:s}\")),\r\n\t\t                    PROJECT_NAME,\r\n\t\t                    PROJECT_VERSION),\r\n\t\t        UiFlags::ColorWhite);\r\n\t    },\r\n\t    nullptr,\r\n\t    CanPlayerTakeAction);\r\n\toptions.Padmapper.AddAction(\r\n\t    \"SortInv\",\r\n\t    N_(\"Sort Inventory\"),\r\n\t    N_(\"Sorts the inventory.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {\r\n\t\t    ReorganizeInventory(*MyPlayer);\r\n\t    });\r\n\toptions.Padmapper.AddAction(\r\n\t    \"ChatLog\",\r\n\t    N_(\"Chat Log\"),\r\n\t    N_(\"Displays chat log.\"),\r\n\t    ControllerButton_NONE,\r\n\t    [] {\r\n\t\t    ToggleChatLog();\r\n\t    });\r\n\toptions.Padmapper.CommitActions();\r\n}\r\n\r\nvoid SetCursorPos(Point position)\r\n{\r\n\tif (ControlDevice != ControlTypes::KeyboardAndMouse) {\r\n\t\tMousePosition = position;\r\n\t\treturn;\r\n\t}\r\n\r\n\tLogicalToOutput(&position.x, &position.y);\r\n\tif (!demo::IsRunning())\r\n\t\tSDL_WarpMouseInWindow(ghMainWnd, position.x, position.y);\r\n}\r\n\r\nvoid FreeGameMem()\r\n{\r\n\tpDungeonCels = nullptr;\r\n\tpMegaTiles = nullptr;\r\n\tpSpecialCels = std::nullopt;\r\n\r\n\tFreeMonsters();\r\n\tFreeMissileGFX();\r\n\tFreeObjectGFX();\r\n\tFreeTownerGFX();\r\n\tFreeStashGFX();\r\n#ifndef USE_SDL1\r\n\tDeactivateVirtualGamepad();\r\n\tFreeVirtualGamepadGFX();\r\n#endif\r\n}\r\n\r\nbool StartGame(bool bNewGame, bool bSinglePlayer)\r\n{\r\n\tgbSelectProvider = true;\r\n\tReturnToMainMenu = false;\r\n\r\n\tdo {\r\n\t\tgbLoadGame = false;\r\n\r\n\t\tif (!NetInit(bSinglePlayer)) {\r\n\t\t\tgbRunGameResult = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t// Save 2.8 MiB of RAM by freeing all main menu resources\r\n\t\t// before starting the game.\r\n\t\tUiDestroy();\r\n\r\n\t\tgbSelectProvider = false;\r\n\r\n\t\tif (bNewGame || !gbValidSaveFile) {\r\n\t\t\tInitLevels();\r\n\t\t\tInitQuests();\r\n\t\t\tInitPortals();\r\n\t\t\tInitDungMsgs(*MyPlayer);\r\n\t\t\tDeltaSyncJunk();\r\n\t\t}\r\n\t\tgiNumberOfLevels = gbIsHellfire ? 25 : 17;\r\n\t\tinterface_mode uMsg = WM_DIABNEWGAME;\r\n\t\tif (gbValidSaveFile && gbLoadGame) {\r\n\t\t\tuMsg = WM_DIABLOADGAME;\r\n\t\t}\r\n\t\tRunGameLoop(uMsg);\r\n\t\tNetClose();\r\n\t\tUnloadFonts();\r\n\r\n\t\t// If the player left the game into the main menu,\r\n\t\t// initialize main menu resources.\r\n\t\tif (gbRunGameResult)\r\n\t\t\tUiInitialize();\r\n\t\tif (ReturnToMainMenu)\r\n\t\t\treturn true;\r\n\t} while (gbRunGameResult);\r\n\r\n\tSNetDestroy();\r\n\treturn gbRunGameResult;\r\n}\r\n\r\nvoid diablo_quit(int exitStatus)\r\n{\r\n\tFreeGameMem();\r\n\tmusic_stop();\r\n\tDiabloDeinit();\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tif (SdlLogFile != nullptr) std::fclose(SdlLogFile);\r\n#endif\r\n\r\n\texit(exitStatus);\r\n}\r\n\r\n#ifdef __UWP__\r\nvoid (*onInitialized)() = NULL;\r\n\r\nvoid setOnInitialized(void (*callback)())\r\n{\r\n\tonInitialized = callback;\r\n}\r\n#endif\r\n\r\nint DiabloMain(int argc, char **argv)\r\n{\r\n#ifdef _DEBUG\r\n\tSDL_SetLogPriorities(SDL_LOG_PRIORITY_DEBUG);\r\n#endif\r\n\r\n\tDiabloParseFlags(argc, argv);\r\n\tInitKeymapActions();\r\n\tInitPadmapActions();\r\n\r\n\t// Need to ensure devilutionx.mpq (and fonts.mpq if available) are loaded before attempting to read translation settings\r\n\tLoadCoreArchives();\r\n\twas_archives_init = true;\r\n\r\n\t// Read settings including translation next. This will use the presence of fonts.mpq and look for assets in devilutionx.mpq\r\n\tLoadOptions();\r\n\tif (demo::IsRunning()) demo::OverrideOptions();\r\n\r\n\t// Then look for a voice pack file based on the selected translation\r\n\tLoadLanguageArchive();\r\n\r\n\tApplicationInit();\r\n\tLuaInitialize();\r\n\tif (!demo::IsRunning()) SaveOptions();\r\n\r\n\t// Finally load game data\r\n\tLoadGameArchives();\r\n\r\n\tLoadTextData();\r\n\r\n\t// Load dynamic data before we go into the menu as we need to initialise player characters in memory pretty early.\r\n\tLoadPlayerDataFiles();\r\n\r\n\t// TODO: We can probably load this much later (when the game is starting).\r\n\tLoadSpellData();\r\n\tLoadMissileData();\r\n\tLoadMonsterData();\r\n\tLoadItemData();\r\n\tLoadObjectData();\r\n\tLoadQuestData();\r\n\r\n\tDiabloInit();\r\n#ifdef __UWP__\r\n\tonInitialized();\r\n#endif\r\n\tif (!demo::IsRunning()) SaveOptions();\r\n\r\n\tDiabloSplash();\r\n\tmainmenu_loop();\r\n\tDiabloDeinit();\r\n\r\n\treturn 0;\r\n}\r\n\r\nbool TryIconCurs()\r\n{\r\n\tif (pcurs == CURSOR_RESURRECT) {\r\n\t\tif (PlayerUnderCursor != nullptr) {\r\n\t\t\tNetSendCmdParam1(true, CMD_RESURRECT, PlayerUnderCursor->getId());\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (pcurs == CURSOR_HEALOTHER) {\r\n\t\tif (PlayerUnderCursor != nullptr) {\r\n\t\t\tNetSendCmdParam1(true, CMD_HEALOTHER, PlayerUnderCursor->getId());\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (pcurs == CURSOR_TELEKINESIS) {\r\n\t\tDoTelekinesis();\r\n\t\treturn true;\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (pcurs == CURSOR_IDENTIFY) {\r\n\t\tif (pcursinvitem != -1 && !IsInspectingPlayer())\r\n\t\t\tCheckIdentify(myPlayer, pcursinvitem);\r\n\t\telse if (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\t\tItem &item = Stash.stashList[pcursstashitem];\r\n\t\t\titem._iIdentified = true;\r\n\t\t}\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (pcurs == CURSOR_REPAIR) {\r\n\t\tif (pcursinvitem != -1 && !IsInspectingPlayer())\r\n\t\t\tDoRepair(myPlayer, pcursinvitem);\r\n\t\telse if (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\t\tItem &item = Stash.stashList[pcursstashitem];\r\n\t\t\tRepairItem(item, myPlayer.getCharacterLevel());\r\n\t\t}\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (pcurs == CURSOR_RECHARGE) {\r\n\t\tif (pcursinvitem != -1 && !IsInspectingPlayer())\r\n\t\t\tDoRecharge(myPlayer, pcursinvitem);\r\n\t\telse if (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\t\tItem &item = Stash.stashList[pcursstashitem];\r\n\t\t\tRechargeItem(item, myPlayer);\r\n\t\t}\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (pcurs == CURSOR_OIL) {\r\n\t\tbool changeCursor = true;\r\n\t\tif (pcursinvitem != -1 && !IsInspectingPlayer())\r\n\t\t\tchangeCursor = DoOil(myPlayer, pcursinvitem);\r\n\t\telse if (pcursstashitem != StashStruct::EmptyCell) {\r\n\t\t\tItem &item = Stash.stashList[pcursstashitem];\r\n\t\t\tchangeCursor = ApplyOilToItem(item, myPlayer);\r\n\t\t}\r\n\t\tif (changeCursor)\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (pcurs == CURSOR_TELEPORT) {\r\n\t\tconst SpellID spellID = myPlayer.inventorySpell;\r\n\t\tconst SpellType spellType = SpellType::Scroll;\r\n\t\tconst int spellFrom = myPlayer.spellFrom;\r\n\t\tif (IsWallSpell(spellID)) {\r\n\t\t\tconst Direction sd = GetDirection(myPlayer.position.tile, cursPosition);\r\n\t\t\tNetSendCmdLocParam4(true, CMD_SPELLXYD, cursPosition, static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), static_cast<uint16_t>(sd), spellFrom);\r\n\t\t} else if (pcursmonst != -1 && leveltype != DTYPE_TOWN) {\r\n\t\t\tNetSendCmdParam4(true, CMD_SPELLID, pcursmonst, static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), spellFrom);\r\n\t\t} else if (PlayerUnderCursor != nullptr && !PlayerUnderCursor->hasNoLife() && !myPlayer.friendlyMode) {\r\n\t\t\tNetSendCmdParam4(true, CMD_SPELLPID, PlayerUnderCursor->getId(), static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), spellFrom);\r\n\t\t} else {\r\n\t\t\tNetSendCmdLocParam3(true, CMD_SPELLXY, cursPosition, static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), spellFrom);\r\n\t\t}\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (pcurs == CURSOR_DISARM && ObjectUnderCursor == nullptr) {\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid diablo_pause_game()\r\n{\r\n\tif (!gbIsMultiplayer) {\r\n\t\tif (PauseMode != 0) {\r\n\t\t\tPauseMode = 0;\r\n\t\t} else {\r\n\t\t\tPauseMode = 2;\r\n\t\t\tsound_stop();\r\n\t\t\tqtextflag = false;\r\n\t\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\t}\r\n\r\n\t\tRedrawEverything();\r\n\t}\r\n}\r\n\r\nbool GameWasAlreadyPaused = false;\r\nbool MinimizePaused = false;\r\n\r\nbool diablo_is_focused()\r\n{\r\n#ifndef USE_SDL1\r\n\treturn SDL_GetKeyboardFocus() == ghMainWnd;\r\n#else\r\n\tUint8 appState = SDL_GetAppState();\r\n\treturn (appState & SDL_APPINPUTFOCUS) != 0;\r\n#endif\r\n}\r\n\r\nvoid diablo_focus_pause()\r\n{\r\n\tif (!movie_playing && (gbIsMultiplayer || MinimizePaused)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tGameWasAlreadyPaused = PauseMode != 0;\r\n\r\n\tif (!GameWasAlreadyPaused) {\r\n\t\tPauseMode = 2;\r\n\t\tsound_stop();\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t}\r\n\r\n\tSVidMute();\r\n\tmusic_mute();\r\n\r\n\tMinimizePaused = true;\r\n}\r\n\r\nvoid diablo_focus_unpause()\r\n{\r\n\tif (!GameWasAlreadyPaused) {\r\n\t\tPauseMode = 0;\r\n\t}\r\n\r\n\tSVidUnmute();\r\n\tmusic_unmute();\r\n\r\n\tMinimizePaused = false;\r\n}\r\n\r\nbool PressEscKey()\r\n{\r\n\tbool rv = false;\r\n\r\n\tif (DoomFlag) {\r\n\t\tdoom_close();\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (HelpFlag) {\r\n\t\tHelpFlag = false;\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (ChatLogFlag) {\r\n\t\tChatLogFlag = false;\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (qtextflag) {\r\n\t\tqtextflag = false;\r\n\t\tstream_stop();\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (IsPlayerInStore()) {\r\n\t\tStoreESC();\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (IsDiabloMsgAvailable()) {\r\n\t\tCancelCurrentDiabloMsg();\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (ChatFlag) {\r\n\t\tResetChat();\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (DropGoldFlag) {\r\n\t\tcontrol_drop_gold(SDLK_ESCAPE);\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (IsWithdrawGoldOpen) {\r\n\t\tWithdrawGoldKeyPress(SDLK_ESCAPE);\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (SpellSelectFlag) {\r\n\t\tSpellSelectFlag = false;\r\n\t\trv = true;\r\n\t}\r\n\r\n\tif (IsLeftPanelOpen() || IsRightPanelOpen()) {\r\n\t\tClosePanels();\r\n\t\trv = true;\r\n\t}\r\n\r\n\treturn rv;\r\n}\r\n\r\nvoid DisableInputEventHandler(const SDL_Event &event, uint16_t modState)\r\n{\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_MOUSE_MOTION:\r\n\t\tMousePosition = { SDLC_EventMotionIntX(event), SDLC_EventMotionIntY(event) };\r\n\t\treturn;\r\n\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\t\tif (sgbMouseDown != CLICK_NONE)\r\n\t\t\treturn;\r\n\t\tswitch (event.button.button) {\r\n\t\tcase SDL_BUTTON_LEFT:\r\n\t\t\tsgbMouseDown = CLICK_LEFT;\r\n\t\t\treturn;\r\n\t\tcase SDL_BUTTON_RIGHT:\r\n\t\t\tsgbMouseDown = CLICK_RIGHT;\r\n\t\t\treturn;\r\n\t\tdefault:\r\n\t\t\treturn;\r\n\t\t}\r\n\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\tsgbMouseDown = CLICK_NONE;\r\n\t\treturn;\r\n\t}\r\n\r\n\tMainWndProc(event);\r\n}\r\n\r\nvoid LoadGameLevelStopMusic(_music_id neededTrack)\r\n{\r\n\tif (neededTrack != sgnMusicTrack)\r\n\t\tmusic_stop();\r\n}\r\n\r\nvoid LoadGameLevelStartMusic(_music_id neededTrack)\r\n{\r\n\tif (sgnMusicTrack != neededTrack)\r\n\t\tmusic_start(neededTrack);\r\n\r\n\tif (MinimizePaused) {\r\n\t\tmusic_mute();\r\n\t}\r\n}\r\n\r\nvoid LoadGameLevelResetCursor()\r\n{\r\n\tif (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) {\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t}\r\n}\r\n\r\nvoid SetRndSeedForDungeonLevel()\r\n{\r\n\tif (setlevel) {\r\n\t\t// Maps are not randomly generated, but the monsters max hitpoints are.\r\n\t\t// So we need to ensure that we have a stable seed when generating quest/set-maps.\r\n\t\t// For this purpose we reuse the normal dungeon seeds.\r\n\t\tSetRndSeed(DungeonSeeds[static_cast<size_t>(setlvlnum)]);\r\n\t} else {\r\n\t\tSetRndSeed(DungeonSeeds[currlevel]);\r\n\t}\r\n}\r\n\r\nvoid LoadGameLevelFirstFlagEntry()\r\n{\r\n\tCloseInventory();\r\n\tqtextflag = false;\r\n\tif (!HeadlessMode) {\r\n\t\tInitInv();\r\n\t\tClearUniqueItemFlags();\r\n\t\tInitQuestText();\r\n\t\tInitInfoBoxGfx();\r\n\t\tInitHelp();\r\n\t}\r\n\tInitStores();\r\n\tInitAutomapOnce();\r\n}\r\n\r\nvoid LoadGameLevelStores()\r\n{\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tSetupTownStores();\r\n\t} else {\r\n\t\tFreeStoreMem();\r\n\t}\r\n}\r\n\r\nvoid LoadGameLevelStash()\r\n{\r\n\tconst bool isHellfireSaveGame = gbIsHellfireSaveGame;\r\n\r\n\tgbIsHellfireSaveGame = gbIsHellfire;\r\n\tLoadStash();\r\n\tgbIsHellfireSaveGame = isHellfireSaveGame;\r\n}\r\n\r\ntl::expected<void, std::string> LoadGameLevelDungeon(bool firstflag, lvl_entry lvldir, const Player &myPlayer)\r\n{\r\n\tif (firstflag || lvldir == ENTRY_LOAD || !myPlayer._pLvlVisited[currlevel] || gbIsMultiplayer) {\r\n\t\tHoldThemeRooms();\r\n\t\t[[maybe_unused]] const uint32_t mid1Seed = GetLCGEngineState();\r\n\t\tInitGolems();\r\n\t\tInitObjects();\r\n\t\t[[maybe_unused]] const uint32_t mid2Seed = GetLCGEngineState();\r\n\r\n\t\tIncProgress();\r\n\r\n\t\tRETURN_IF_ERROR(InitMonsters());\r\n\t\tInitItems();\r\n\t\tCreateThemeRooms();\r\n\r\n\t\tIncProgress();\r\n\r\n\t\t[[maybe_unused]] const uint32_t mid3Seed = GetLCGEngineState();\r\n\t\tInitMissiles();\r\n\t\tInitCorpses();\r\n#ifdef _DEBUG\r\n\t\tSetDebugLevelSeedInfos(mid1Seed, mid2Seed, mid3Seed, GetLCGEngineState());\r\n#endif\r\n\t\tSavePreLighting();\r\n\r\n\t\tIncProgress();\r\n\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tDeltaLoadLevel();\r\n\t} else {\r\n\t\tHoldThemeRooms();\r\n\t\tInitGolems();\r\n\t\tRETURN_IF_ERROR(InitMonsters());\r\n\t\tInitMissiles();\r\n\t\tInitCorpses();\r\n\r\n\t\tIncProgress();\r\n\r\n\t\tRETURN_IF_ERROR(LoadLevel());\r\n\r\n\t\tIncProgress();\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid LoadGameLevelSyncPlayerEntry(lvl_entry lvldir)\r\n{\r\n\tfor (Player &player : Players) {\r\n\t\tif (player.plractive && player.isOnActiveLevel() && (!player._pLvlChanging || &player == MyPlayer)) {\r\n\t\t\tif (player._pHitPoints > 0) {\r\n\t\t\t\tif (lvldir != ENTRY_LOAD)\r\n\t\t\t\t\tSyncInitPlrPos(player);\r\n\t\t\t} else {\r\n\t\t\t\tdFlags[player.position.tile.x][player.position.tile.y] |= DungeonFlag::DeadPlayer;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LoadGameLevelLightVision()\r\n{\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tmemcpy(dLight, dPreLight, sizeof(dLight));                                     // resets the light on entering a level to get rid of incorrect light\r\n\t\tChangeLightXY(Players[MyPlayerId].lightId, Players[MyPlayerId].position.tile); // forces player light refresh\r\n\t\tProcessLightList();\r\n\t\tProcessVisionList();\r\n\t}\r\n}\r\n\r\nvoid LoadGameLevelReturn()\r\n{\r\n\tViewPosition = GetMapReturnPosition();\r\n\tif (Quests[Q_BETRAYER]._qactive == QUEST_DONE)\r\n\t\tQuests[Q_BETRAYER]._qvar2 = 2;\r\n}\r\n\r\nvoid LoadGameLevelInitPlayers(bool firstflag, lvl_entry lvldir)\r\n{\r\n\tfor (Player &player : Players) {\r\n\t\tif (player.plractive && player.isOnActiveLevel()) {\r\n\t\t\tInitPlayerGFX(player);\r\n\t\t\tif (lvldir != ENTRY_LOAD)\r\n\t\t\t\tInitPlayer(player, firstflag);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LoadGameLevelSetVisited()\r\n{\r\n\tbool visited = false;\r\n\tfor (const Player &player : Players) {\r\n\t\tif (player.plractive)\r\n\t\t\tvisited = visited || player._pLvlVisited[currlevel];\r\n\t}\r\n}\r\n\r\ntl::expected<void, std::string> LoadGameLevelTown(bool firstflag, lvl_entry lvldir, const Player &myPlayer)\r\n{\r\n\tfor (int i = 0; i < MAXDUNX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tdFlags[i][j] |= DungeonFlag::Lit;\r\n\t\t}\r\n\t}\r\n\r\n\tInitTowners();\r\n\tInitStash();\r\n\tInitItems();\r\n\tInitMissiles();\r\n\r\n\tIncProgress();\r\n\r\n\tif (!firstflag && lvldir != ENTRY_LOAD && myPlayer._pLvlVisited[currlevel] && !gbIsMultiplayer)\r\n\t\tRETURN_IF_ERROR(LoadLevel());\r\n\tif (gbIsMultiplayer)\r\n\t\tDeltaLoadLevel();\r\n\r\n\tIncProgress();\r\n\r\n\tfor (int x = 0; x < DMAXX; x++)\r\n\t\tfor (int y = 0; y < DMAXY; y++)\r\n\t\t\tUpdateAutomapExplorer({ x, y }, MAP_EXP_SELF);\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> LoadGameLevelSetLevel(bool firstflag, lvl_entry lvldir, const Player &myPlayer)\r\n{\r\n\tLoadSetMap();\r\n\tIncProgress();\r\n\tRETURN_IF_ERROR(GetLevelMTypes());\r\n\tIncProgress();\r\n\tInitGolems();\r\n\tRETURN_IF_ERROR(InitMonsters());\r\n\tIncProgress();\r\n\tif (!HeadlessMode) {\r\n#if !defined(USE_SDL1) && !defined(__vita__)\r\n\t\tInitVirtualGamepadGFX();\r\n#endif\r\n\t\tRETURN_IF_ERROR(InitMissileGFX());\r\n\t\tIncProgress();\r\n\t}\r\n\tInitCorpses();\r\n\tIncProgress();\r\n\r\n\tif (lvldir == ENTRY_WARPLVL)\r\n\t\tGetPortalLvlPos();\r\n\tIncProgress();\r\n\r\n\tfor (Player &player : Players) {\r\n\t\tif (player.plractive && player.isOnActiveLevel()) {\r\n\t\t\tInitPlayerGFX(player);\r\n\t\t\tif (lvldir != ENTRY_LOAD)\r\n\t\t\t\tInitPlayer(player, firstflag);\r\n\t\t}\r\n\t}\r\n\tIncProgress();\r\n\tInitMultiView();\r\n\tIncProgress();\r\n\r\n\tif (firstflag || lvldir == ENTRY_LOAD || !myPlayer._pSLvlVisited[setlvlnum] || gbIsMultiplayer) {\r\n\t\tInitItems();\r\n\t\tSavePreLighting();\r\n\t} else {\r\n\t\tRETURN_IF_ERROR(LoadLevel());\r\n\t}\r\n\tif (gbIsMultiplayer) {\r\n\t\tDeltaLoadLevel();\r\n\t\tif (!UseMultiplayerQuests())\r\n\t\t\tResyncQuests();\r\n\t}\r\n\r\n\tPlayDungMsgs();\r\n\tInitMissiles();\r\n\tIncProgress();\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> LoadGameLevelStandardLevel(bool firstflag, lvl_entry lvldir, const Player &myPlayer)\r\n{\r\n\tCreateLevel(lvldir);\r\n\r\n\tIncProgress();\r\n\r\n\tSetRndSeedForDungeonLevel();\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tRETURN_IF_ERROR(GetLevelMTypes());\r\n\t\tInitThemes();\r\n\t\tif (!HeadlessMode)\r\n\t\t\tRETURN_IF_ERROR(LoadAllGFX());\r\n\t} else if (!HeadlessMode) {\r\n\t\tIncProgress();\r\n\r\n#if !defined(USE_SDL1) && !defined(__vita__)\r\n\t\tInitVirtualGamepadGFX();\r\n#endif\r\n\r\n\t\tIncProgress();\r\n\r\n\t\tRETURN_IF_ERROR(InitMissileGFX());\r\n\r\n\t\tIncProgress();\r\n\t\tIncProgress();\r\n\t}\r\n\r\n\tIncProgress();\r\n\r\n\tif (lvldir == ENTRY_RTNLVL) {\r\n\t\tLoadGameLevelReturn();\r\n\t}\r\n\r\n\tif (lvldir == ENTRY_WARPLVL)\r\n\t\tGetPortalLvlPos();\r\n\r\n\tIncProgress();\r\n\r\n\tLoadGameLevelInitPlayers(firstflag, lvldir);\r\n\tInitMultiView();\r\n\r\n\tIncProgress();\r\n\r\n\tLoadGameLevelSetVisited();\r\n\r\n\tSetRndSeedForDungeonLevel();\r\n\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tLoadGameLevelTown(firstflag, lvldir, myPlayer);\r\n\t} else {\r\n\t\tLoadGameLevelDungeon(firstflag, lvldir, myPlayer);\r\n\t}\r\n\r\n\tPlayDungMsgs();\r\n\r\n\tif (UseMultiplayerQuests())\r\n\t\tResyncMPQuests();\r\n\telse\r\n\t\tResyncQuests();\r\n\treturn {};\r\n}\r\n\r\nvoid LoadGameLevelCrypt()\r\n{\r\n\tif (CornerStone.isAvailable()) {\r\n\t\tCornerstoneLoad(CornerStone.position);\r\n\t}\r\n\tif (Quests[Q_NAKRUL]._qactive == QUEST_DONE && currlevel == 24) {\r\n\t\tSyncNakrulRoom();\r\n\t}\r\n}\r\n\r\nvoid LoadGameLevelCalculateCursor()\r\n{\r\n\t// Recalculate mouse selection of entities after level change/load\r\n\tLastPlayerAction = PlayerActionType::None;\r\n\tsgbMouseDown = CLICK_NONE;\r\n\tResetItemlabelHighlighted(); // level changed => item changed\r\n\tpcursmonst = -1;             // ensure pcurstemp is set to a valid value\r\n\tCheckCursMove();\r\n}\r\n\r\ntl::expected<void, std::string> LoadGameLevel(bool firstflag, lvl_entry lvldir)\r\n{\r\n\tconst _music_id neededTrack = GetLevelMusic(leveltype);\r\n\r\n\tClearFloatingNumbers();\r\n\tLoadGameLevelStopMusic(neededTrack);\r\n\tLoadGameLevelResetCursor();\r\n\tSetRndSeedForDungeonLevel();\r\n\tNaKrulTomeSequence = 0;\r\n\r\n\tIncProgress();\r\n\r\n\tRETURN_IF_ERROR(LoadTrns());\r\n\tMakeLightTable();\r\n\tRETURN_IF_ERROR(LoadLevelSOLData());\r\n\r\n\tIncProgress();\r\n\r\n\tRETURN_IF_ERROR(LoadLvlGFX());\r\n\tSetDungeonMicros(pDungeonCels, MicroTileLen);\r\n\tClearClxDrawCache();\r\n\r\n\tIncProgress();\r\n\r\n\tif (firstflag) {\r\n\t\tLoadGameLevelFirstFlagEntry();\r\n\t}\r\n\r\n\tSetRndSeedForDungeonLevel();\r\n\r\n\tLoadGameLevelStores();\r\n\r\n\tif (firstflag || lvldir == ENTRY_LOAD) {\r\n\t\tLoadGameLevelStash();\r\n\t}\r\n\r\n\tIncProgress();\r\n\r\n\tInitAutomap();\r\n\r\n\tif (leveltype != DTYPE_TOWN && lvldir != ENTRY_LOAD) {\r\n\t\tInitLighting();\r\n\t}\r\n\r\n\tInitLevelMonsters();\r\n\r\n\tIncProgress();\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (setlevel) {\r\n\t\tRETURN_IF_ERROR(LoadGameLevelSetLevel(firstflag, lvldir, myPlayer));\r\n\t} else {\r\n\t\tRETURN_IF_ERROR(LoadGameLevelStandardLevel(firstflag, lvldir, myPlayer));\r\n\t}\r\n\r\n\tSyncPortals();\r\n\tLoadGameLevelSyncPlayerEntry(lvldir);\r\n\r\n\tIncProgress();\r\n\tIncProgress();\r\n\r\n\tif (firstflag) {\r\n\t\tRETURN_IF_ERROR(InitMainPanel());\r\n\t}\r\n\r\n\tIncProgress();\r\n\r\n\tUpdateMonsterLights();\r\n\tUnstuckChargers();\r\n\r\n\tLoadGameLevelLightVision();\r\n\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tLoadGameLevelCrypt();\r\n\t}\r\n\r\n#ifndef USE_SDL1\r\n\tActivateVirtualGamepad();\r\n#endif\r\n\tLoadGameLevelStartMusic(neededTrack);\r\n\r\n\tCompleteProgress();\r\n\r\n\tLoadGameLevelCalculateCursor();\r\n\treturn {};\r\n}\r\n\r\nbool game_loop(bool bStartup)\r\n{\r\n\tconst uint16_t wait = bStartup ? sgGameInitInfo.nTickRate * 3 : 3;\r\n\r\n\tfor (unsigned i = 0; i < wait; i++) {\r\n\t\tif (!multi_handle_delta()) {\r\n\t\t\tTimeoutCursor(true);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tTimeoutCursor(false);\r\n\t\tGameLogic();\r\n\t\tClearLastSentPlayerCmd();\r\n\r\n\t\tif (!gbRunGame || !gbIsMultiplayer || demo::IsRunning() || demo::IsRecording() || !nthread_has_500ms_passed())\r\n\t\t\tbreak;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid diablo_color_cyc_logic()\r\n{\r\n\tif (!*GetOptions().Graphics.colorCycling)\r\n\t\treturn;\r\n\r\n\tif (PauseMode != 0)\r\n\t\treturn;\r\n\r\n\tif (leveltype == DTYPE_CAVES) {\r\n\t\tif (setlevel && setlvlnum == Quests[Q_PWATER]._qslvl) {\r\n\t\t\tUpdatePWaterPalette();\r\n\t\t} else {\r\n\t\t\tpalette_update_caves();\r\n\t\t}\r\n\t} else if (leveltype == DTYPE_HELL) {\r\n\t\tlighting_color_cycling();\r\n\t} else if (leveltype == DTYPE_NEST) {\r\n\t\tpalette_update_hive();\r\n\t} else if (leveltype == DTYPE_CRYPT) {\r\n\t\tpalette_update_crypt();\r\n\t}\r\n}\r\n\r\nbool IsDiabloAlive(bool playSFX)\r\n{\r\n\tif (Quests[Q_DIABLO]._qactive == QUEST_DONE && !gbIsMultiplayer) {\r\n\t\tif (playSFX)\r\n\t\t\tPlaySFX(SfxID::DiabloDeath);\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid PrintScreen(SDL_Keycode vkey)\r\n{\r\n\tReleaseKey(vkey);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/diablo.h",
    "content": "/**\r\n * @file diablo.h\r\n *\r\n * Interface of the main game initialization functions.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#ifdef _DEBUG\r\n#include \"tables/monstdat.h\"\r\n#endif\r\n#include \"levels/gendung.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/endian_read.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr uint32_t GameIdDiabloFull = LoadBE32(\"DRTL\");\r\nconstexpr uint32_t GameIdDiabloSpawn = LoadBE32(\"DSHR\");\r\nconstexpr uint32_t GameIdHellfireFull = LoadBE32(\"HRTL\");\r\nconstexpr uint32_t GameIdHellfireSpawn = LoadBE32(\"HSHR\");\r\n#define GAME_ID (gbIsHellfire ? (gbIsSpawn ? GameIdHellfireSpawn : GameIdHellfireFull) : (gbIsSpawn ? GameIdDiabloSpawn : GameIdDiabloFull))\r\n\r\n#define NUMLEVELS 25\r\n\r\nenum clicktype : int8_t {\r\n\tCLICK_NONE,\r\n\tCLICK_LEFT,\r\n\tCLICK_RIGHT,\r\n};\r\n\r\n/**\r\n * @brief Specifies what game logic step is currently executed\r\n */\r\nenum class GameLogicStep : uint8_t {\r\n\tNone,\r\n\tProcessPlayers,\r\n\tProcessMonsters,\r\n\tProcessObjects,\r\n\tProcessMissiles,\r\n\tProcessItems,\r\n\tProcessTowners,\r\n\tProcessItemsTown,\r\n\tProcessMissilesTown,\r\n};\r\n\r\nenum class PlayerActionType : uint8_t {\r\n\tNone,\r\n\tWalk,\r\n\tSpell,\r\n\tSpellMonsterTarget,\r\n\tSpellPlayerTarget,\r\n\tAttack,\r\n\tAttackMonsterTarget,\r\n\tAttackPlayerTarget,\r\n\tOperateObject,\r\n};\r\n\r\nextern uint32_t DungeonSeeds[NUMLEVELS];\r\nextern DVL_API_FOR_TEST std::optional<uint32_t> LevelSeeds[NUMLEVELS];\r\nextern Point MousePosition;\r\n\r\nextern bool gbRunGameResult;\r\nextern bool ReturnToMainMenu;\r\nextern bool gbProcessPlayers;\r\nextern DVL_API_FOR_TEST bool gbLoadGame;\r\nextern bool cineflag;\r\n/* These are defined in fonts.h */\r\nextern void FontsCleanup();\r\nextern DVL_API_FOR_TEST int PauseMode;\r\nextern clicktype sgbMouseDown;\r\nextern uint16_t gnTickDelay;\r\nextern char gszProductName[64];\r\n\r\nextern PlayerActionType LastPlayerAction;\r\n\r\nvoid InitKeymapActions();\r\nvoid SetCursorPos(Point position);\r\nvoid FreeGameMem();\r\nbool StartGame(bool bNewGame, bool bSinglePlayer);\r\n[[noreturn]] void diablo_quit(int exitStatus);\r\nint DiabloMain(int argc, char **argv);\r\nbool TryIconCurs();\r\nvoid diablo_pause_game();\r\nbool diablo_is_focused();\r\nvoid diablo_focus_pause();\r\nvoid diablo_focus_unpause();\r\nbool PressEscKey();\r\nvoid DisableInputEventHandler(const SDL_Event &event, uint16_t modState);\r\ntl::expected<void, std::string> LoadGameLevel(bool firstflag, lvl_entry lvldir);\r\nbool IsDiabloAlive(bool playSFX);\r\nvoid PrintScreen(SDL_Keycode vkey);\r\n\r\n/**\r\n * @param bStartup Process additional ticks before returning\r\n */\r\nbool game_loop(bool bStartup);\r\nvoid diablo_color_cyc_logic();\r\n\r\n/* rdata */\r\n\r\n#ifdef _DEBUG\r\nextern bool DebugDisableNetworkTimeout;\r\n#endif\r\n\r\n/**\r\n * @brief Specifies what game logic step is currently executed\r\n */\r\nextern GameLogicStep gGameLogicStep;\r\n\r\n#ifdef __UWP__\r\nvoid setOnInitialized(void (*)());\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/diablo_msg.cpp",
    "content": "/**\r\n * @file diablo_msg.cpp\r\n *\r\n * Implementation of in-game message functions.\r\n */\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <deque>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"diablo_msg.hpp\"\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"panels/info_box.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_split.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct MessageEntry {\r\n\tstd::string text;\r\n\tuint32_t duration; // Duration in milliseconds\r\n};\r\n\r\nstd::deque<MessageEntry> DiabloMessages;\r\nuint32_t msgStartTime;\r\nstd::vector<std::string> TextLines;\r\nint OuterHeight;\r\nint LineWidth;\r\nint LineHeight;\r\n\r\nvoid InitDiabloMsg()\r\n{\r\n\tTextLines.clear();\r\n\tif (DiabloMessages.empty())\r\n\t\treturn;\r\n\r\n\tLineWidth = 418;\r\n\tconst std::string_view text = DiabloMessages.front().text;\r\n\tconst std::string wrapped = WordWrapString(text, LineWidth, GameFont12);\r\n\tfor (const std::string_view line : SplitByChar(wrapped, '\\n')) {\r\n\t\tLineWidth = std::max(LineWidth, GetLineWidth(text, GameFont12));\r\n\t\tTextLines.emplace_back(line);\r\n\t}\r\n\r\n\tmsgStartTime = SDL_GetTicks();\r\n\tLineHeight = GetLineHeight(text, GameFont12);\r\n\tOuterHeight = static_cast<int>((TextLines.size()) * LineHeight) + 42;\r\n}\r\n\r\n} // namespace\r\n\r\n/** Maps from error_id to error message. */\r\nconst char *const MsgStrings[] = {\r\n\t\"\",\r\n\tN_(\"Game saved\"),\r\n\tN_(\"No multiplayer functions in demo\"),\r\n\tN_(\"Direct Sound Creation Failed\"),\r\n\tN_(\"Not available in shareware version\"),\r\n\tN_(\"Not enough space to save\"),\r\n\tN_(\"No Pause in town\"),\r\n\tN_(\"Copying to a hard disk is recommended\"),\r\n\tN_(\"Multiplayer sync problem\"),\r\n\tN_(\"No pause in multiplayer\"),\r\n\tN_(\"Loading...\"),\r\n\tN_(\"Saving...\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Some are weakened as one grows strong\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"New strength is forged through destruction\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Those who defend seldom attack\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"The sword of justice is swift and sharp\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"While the spirit is vigilant the body thrives\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"The powers of mana refocused renews\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Time cannot diminish the power of steel\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Magic is not always what it seems to be\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"What once was opened now is closed\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Intensity comes at the cost of wisdom\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Arcane power brings destruction\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"That which cannot be held cannot be harmed\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Crimson and Azure become as the sun\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Knowledge and wisdom at the cost of self\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Drink and be refreshed\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Wherever you go, there you are\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Energy comes at the cost of wisdom\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Riches abound when least expected\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Where avarice fails, patience gains reward\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Blessed by a benevolent companion!\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"The hands of men may be guided by fate\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Strength is bolstered by heavenly faith\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"The essence of life flows from within\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"The way is made clear when viewed from above\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Salvation comes at the cost of wisdom\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Mysteries are revealed in the light of reason\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Those who are last may yet be first\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Generosity brings its own rewards\"),\r\n\tN_(\"You must be at least level 8 to use this.\"),\r\n\tN_(\"You must be at least level 13 to use this.\"),\r\n\tN_(\"You must be at least level 17 to use this.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Arcane knowledge gained!\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"That which does not kill you...\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Knowledge is power.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Give and you shall receive.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Some experience is gained by touch.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"There's no place like home.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"Spiritual energy is restored.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"You feel more agile.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"You feel stronger.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"You feel wiser.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"You feel refreshed.\"),\r\n\tN_(/* TRANSLATORS: Shrine Text. Keep atmospheric. :) */ \"That which can break will.\"),\r\n};\r\n\r\nvoid InitDiabloMsg(diablo_message e, uint32_t duration /*= 3500*/)\r\n{\r\n\tInitDiabloMsg(LanguageTranslate(MsgStrings[e]), duration);\r\n}\r\n\r\nvoid InitDiabloMsg(std::string_view msg, uint32_t duration /*= 3500*/)\r\n{\r\n\tif (c_find_if(DiabloMessages, [&msg](const MessageEntry &entry) { return entry.text == msg; })\r\n\t    != DiabloMessages.end())\r\n\t\treturn;\r\n\r\n\tDiabloMessages.push_back({ std::string(msg), duration });\r\n\tif (DiabloMessages.size() == 1) {\r\n\t\tInitDiabloMsg();\r\n\t}\r\n}\r\n\r\nbool IsDiabloMsgAvailable()\r\n{\r\n\treturn !DiabloMessages.empty();\r\n}\r\n\r\nvoid CancelCurrentDiabloMsg()\r\n{\r\n\tif (!DiabloMessages.empty()) {\r\n\t\tDiabloMessages.pop_front();\r\n\t\tInitDiabloMsg();\r\n\t}\r\n}\r\n\r\nvoid ClrDiabloMsg()\r\n{\r\n\tDiabloMessages.clear();\r\n}\r\n\r\nvoid DrawDiabloMsg(const Surface &out)\r\n{\r\n\tconst ClxSpriteList sprites = *pSTextSlidCels;\r\n\tconst ClxSprite borderCornerTopLeftSprite = sprites[0];\r\n\tconst ClxSprite borderCornerBottomLeftSprite = sprites[1];\r\n\tconst ClxSprite borderCornerBottomRightSprite = sprites[2];\r\n\tconst ClxSprite borderCornerTopRightSprite = sprites[3];\r\n\tconst ClxSprite borderTopSprite = sprites[4];\r\n\tconst ClxSprite borderLeftSprite = sprites[5];\r\n\tconst ClxSprite borderBottomSprite = sprites[6];\r\n\tconst ClxSprite borderRightSprite = sprites[7];\r\n\r\n\tconst int borderPartWidth = 12;\r\n\tconst int borderPartHeight = 12;\r\n\r\n\tconst int textPaddingX = 5;\r\n\tconst int borderThickness = 3;\r\n\r\n\tconst int outerHeight = std::min<int>(out.h(), OuterHeight);\r\n\tconst int outerWidth = std::min<int>(out.w(), LineWidth + 2 * borderThickness + textPaddingX);\r\n\tconst int innerWidth = outerWidth - 2 * borderThickness;\r\n\tconst int lineWidth = innerWidth - textPaddingX;\r\n\tconst int innerHeight = outerHeight - 2 * borderThickness;\r\n\r\n\tconst Point topLeft { (out.w() - outerWidth) / 2, (out.h() - outerHeight) / 2 };\r\n\r\n\tconst int innerXBegin = topLeft.x + borderThickness;\r\n\tconst int innerXEnd = innerXBegin + innerWidth;\r\n\tconst int innerYBegin = topLeft.y + borderThickness;\r\n\tconst int innerYEnd = innerYBegin + innerHeight;\r\n\tconst int borderRightX = innerXEnd - (borderPartWidth - borderThickness);\r\n\tconst int borderBottomY = innerYEnd - (borderPartHeight - borderThickness);\r\n\r\n\tRenderClxSprite(out, borderCornerTopLeftSprite, topLeft);\r\n\tRenderClxSprite(out, borderCornerBottomLeftSprite, { topLeft.x, borderBottomY });\r\n\tRenderClxSprite(out, borderCornerBottomRightSprite, { borderRightX, borderBottomY });\r\n\tRenderClxSprite(out, borderCornerTopRightSprite, { borderRightX, topLeft.y });\r\n\r\n\tconst Surface horizontalBorderOut = out.subregionX(topLeft.x, outerWidth - borderPartWidth);\r\n\tfor (int x = borderPartWidth; x < horizontalBorderOut.w(); x += borderPartWidth) {\r\n\t\tRenderClxSprite(horizontalBorderOut, borderTopSprite, { x, topLeft.y });\r\n\t\tRenderClxSprite(horizontalBorderOut, borderBottomSprite, { x, borderBottomY });\r\n\t}\r\n\r\n\tconst Surface verticalBorderOut = out.subregionY(topLeft.y, outerHeight - borderPartHeight);\r\n\tfor (int y = borderPartHeight; y < verticalBorderOut.h(); y += borderPartHeight) {\r\n\t\tRenderClxSprite(verticalBorderOut, borderLeftSprite, { topLeft.x, y });\r\n\t\tRenderClxSprite(verticalBorderOut, borderRightSprite, { borderRightX, y });\r\n\t}\r\n\tDrawHalfTransparentRectTo(out, innerXBegin, innerYBegin, innerWidth, innerHeight);\r\n\r\n\tconst int textX = innerXBegin + textPaddingX;\r\n\tint textY = innerYBegin + (innerHeight - LineHeight * static_cast<int>(TextLines.size())) / 2;\r\n\tfor (const std::string &line : TextLines) {\r\n\t\tDrawString(out, line, { { textX, textY }, { lineWidth, LineHeight } },\r\n\t\t    { .flags = UiFlags::AlignCenter, .lineHeight = LineHeight });\r\n\t\ttextY += LineHeight;\r\n\t}\r\n\r\n\t// Calculate the time the current message has been displayed\r\n\tconst uint32_t messageElapsedTime = SDL_GetTicks() - msgStartTime;\r\n\r\n\t// Check if the current message's duration has passed\r\n\tif (!DiabloMessages.empty() && messageElapsedTime >= DiabloMessages.front().duration) {\r\n\t\tDiabloMessages.pop_front();\r\n\t\tInitDiabloMsg();\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/diablo_msg.hpp",
    "content": "/**\r\n * @file diablo_msg.hpp\r\n *\r\n * Interface of in-game message functions.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nenum diablo_message : uint8_t {\r\n\tEMSG_NONE,\r\n\tEMSG_GAME_SAVED,\r\n\tEMSG_NO_MULTIPLAYER_IN_DEMO,\r\n\tEMSG_DIRECT_SOUND_FAILED,\r\n\tEMSG_NOT_IN_SHAREWARE,\r\n\tEMSG_NO_SPACE_TO_SAVE,\r\n\tEMSG_NO_PAUSE_IN_TOWN,\r\n\tEMSG_COPY_TO_HDD,\r\n\tEMSG_DESYNC,\r\n\tEMSG_NO_PAUSE_IN_MP,\r\n\tEMSG_LOADING,\r\n\tEMSG_SAVING,\r\n\tEMSG_SHRINE_MYSTERIOUS,\r\n\tEMSG_SHRINE_HIDDEN,\r\n\tEMSG_SHRINE_GLOOMY,\r\n\tEMSG_SHRINE_WEIRD,\r\n\tEMSG_SHRINE_MAGICAL,\r\n\tEMSG_SHRINE_STONE,\r\n\tEMSG_SHRINE_RELIGIOUS,\r\n\tEMSG_SHRINE_ENCHANTED,\r\n\tEMSG_SHRINE_THAUMATURGIC,\r\n\tEMSG_SHRINE_FASCINATING,\r\n\tEMSG_SHRINE_CRYPTIC,\r\n\tEMSG_SHRINE_UNUSED,\r\n\tEMSG_SHRINE_ELDRITCH,\r\n\tEMSG_SHRINE_EERIE,\r\n\tEMSG_SHRINE_DIVINE,\r\n\tEMSG_SHRINE_HOLY,\r\n\tEMSG_SHRINE_SACRED,\r\n\tEMSG_SHRINE_SPIRITUAL,\r\n\tEMSG_SHRINE_SPOOKY1,\r\n\tEMSG_SHRINE_SPOOKY2,\r\n\tEMSG_SHRINE_ABANDONED,\r\n\tEMSG_SHRINE_CREEPY,\r\n\tEMSG_SHRINE_QUIET,\r\n\tEMSG_SHRINE_SECLUDED,\r\n\tEMSG_SHRINE_ORNATE,\r\n\tEMSG_SHRINE_GLIMMERING,\r\n\tEMSG_SHRINE_TAINTED1,\r\n\tEMSG_SHRINE_TAINTED2,\r\n\tEMSG_REQUIRES_LVL_8,\r\n\tEMSG_REQUIRES_LVL_13,\r\n\tEMSG_REQUIRES_LVL_17,\r\n\tEMSG_BONECHAMB,\r\n\tEMSG_SHRINE_OILY,\r\n\tEMSG_SHRINE_GLOWING,\r\n\tEMSG_SHRINE_MENDICANT,\r\n\tEMSG_SHRINE_SPARKLING,\r\n\tEMSG_SHRINE_TOWN,\r\n\tEMSG_SHRINE_SHIMMERING,\r\n\tEMSG_SHRINE_SOLAR1,\r\n\tEMSG_SHRINE_SOLAR2,\r\n\tEMSG_SHRINE_SOLAR3,\r\n\tEMSG_SHRINE_SOLAR4,\r\n\tEMSG_SHRINE_MURPHYS,\r\n};\r\n\r\nvoid InitDiabloMsg(diablo_message e, uint32_t duration = 3500);\r\nvoid InitDiabloMsg(std::string_view msg, uint32_t duration = 3500);\r\nbool IsDiabloMsgAvailable();\r\nvoid CancelCurrentDiabloMsg();\r\nvoid ClrDiabloMsg();\r\nvoid DrawDiabloMsg(const Surface &out);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/discord/discord.cpp",
    "content": "#include \"discord.h\"\r\n\r\n#ifdef _WIN32\r\n// On Windows, discordsrc-src/cpp/discord.h includes windows.h\r\n#define NOMINMAX 1\r\n#define WIN32_LEAN_AND_MEAN\r\n#endif\r\n#include <discordsrc-src/cpp/discord.h>\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cctype>\r\n#include <chrono>\r\n#include <string>\r\n#include <tuple>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"config.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"lua/lua_global.hpp\"\r\n#include \"multi.h\"\r\n#include \"panels/charpanel.hpp\"\r\n#include \"player.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nvoid ModChanged()\r\n{\r\n\tdiscord_manager::UpdateMenu(true);\r\n}\r\nconst auto ModChangedHandler = (AddModsChangedHandler(ModChanged), true);\r\n} // namespace\r\n\r\nnamespace discord_manager {\r\n\r\n// App ID used for DevilutionX's Diablo (classic Diablo's is 496571953147150354)\r\nconstexpr discord::ClientId DiscordDevilutionxAppId = 795760213524742205;\r\n\r\nconstexpr auto IgnoreResult = [](discord::Result result) {};\r\n\r\ndiscord::Core *discord_core = []() -> discord::Core * {\r\n\tdiscord::Core *core;\r\n\tdiscord::Result result = discord::Core::Create(DiscordDevilutionxAppId, DiscordCreateFlags_NoRequireDiscord, &core);\r\n\tif (result != discord::Result::Ok) {\r\n\t\tcore = nullptr;\r\n\t}\r\n\treturn core;\r\n}();\r\n\r\nstruct PlayerData {\r\n\tdungeon_type dungeonArea;\r\n\t_setlevels questMap;\r\n\tUint8 dungeonLevel;\r\n\tUint8 playerLevel;\r\n\tint playerGfx;\r\n\r\n\t// Why??? This is POD\r\n\tbool operator!=(const PlayerData &other) const\r\n\t{\r\n\t\treturn std::tie(dungeonArea, dungeonLevel, playerLevel, playerGfx) != std::tie(other.dungeonArea, other.dungeonLevel, other.playerLevel, other.playerGfx);\r\n\t}\r\n};\r\n\r\nbool want_menu_update = true;\r\nPlayerData tracked_data;\r\nSint64 start_time = 0;\r\n\r\nstd::string GetLocationString()\r\n{\r\n\t// Quest Level Name\r\n\tif (setlevel) {\r\n\t\treturn std::string(_(QuestLevelNames[setlvlnum]));\r\n\t}\r\n\r\n\t// Dungeon Name\r\n\tconstexpr std::array<const char *, DTYPE_LAST + 1> DungeonStrs = { N_(\"Town\"), N_(\"Cathedral\"), N_(\"Catacombs\"), N_(\"Caves\"), N_(\"Hell\"), N_(\"Nest\"), N_(\"Crypt\") };\r\n\tstd::string dungeonStr;\r\n\tif (tracked_data.dungeonArea != DTYPE_NONE) {\r\n\t\tdungeonStr = _(DungeonStrs[tracked_data.dungeonArea]);\r\n\t} else {\r\n\t\tdungeonStr = _(/* TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)*/ \"None\");\r\n\t}\r\n\r\n\t// Dungeon Level\r\n\tif (tracked_data.dungeonLevel > 0) {\r\n\t\tint level = tracked_data.dungeonLevel;\r\n\t\tif (tracked_data.dungeonArea == DTYPE_NEST)\r\n\t\t\tlevel -= 16;\r\n\t\telse if (tracked_data.dungeonArea == DTYPE_CRYPT)\r\n\t\t\tlevel -= 20;\r\n\r\n\t\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"*/ \"{} {}\")), dungeonStr, level);\r\n\t}\r\n\treturn dungeonStr;\r\n}\r\n\r\nstd::string GetCharacterString()\r\n{\r\n\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\" */ \"Lv {} {}\")), tracked_data.playerLevel, MyPlayer->getClassName());\r\n}\r\n\r\nstd::string GetDetailString()\r\n{\r\n\treturn StrCat(GetCharacterString(), \" - \", GetLocationString());\r\n}\r\n\r\nstd::string GetStateString()\r\n{\r\n\tconstexpr std::array<const char *, 3> DifficultyStrs = { N_(\"Normal\"), N_(\"Nightmare\"), N_(\"Hell\") };\r\n\tconst std::string_view difficultyStr = _(DifficultyStrs[sgGameInitInfo.nDifficulty]);\r\n\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: Discord state i.e. \"Nightmare difficulty\" */ \"{} difficulty\")), difficultyStr);\r\n}\r\n\r\nstd::string GetTooltipString()\r\n{\r\n\treturn StrCat(MyPlayer->_pName, \" - \", GetCharacterString());\r\n}\r\n\r\nstd::string GetPlayerAssetString()\r\n{\r\n\tchar chars[5] {\r\n\t\tGetPlayerSpriteDataForClass(MyPlayer->_pClass).classChar,\r\n\t\tArmourChar[tracked_data.playerGfx >> 4],\r\n\t\tWepChar[tracked_data.playerGfx & 0xF],\r\n\t\t'a',\r\n\t\t's'\r\n\t};\r\n\treturn std::string(chars, 5);\r\n}\r\n\r\nvoid ResetStartTime()\r\n{\r\n\tstart_time = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();\r\n}\r\n\r\nconst char *GetIconAsset()\r\n{\r\n\treturn gbIsHellfire ? \"hellfire\" : \"icon\";\r\n}\r\n\r\nvoid UpdateGame()\r\n{\r\n\tif (discord_core == nullptr)\r\n\t\treturn;\r\n\r\n\tauto newData = PlayerData {\r\n\t\tleveltype, setlvlnum, currlevel, MyPlayer->getCharacterLevel(), MyPlayer->_pgfxnum\r\n\t};\r\n\tif (newData != tracked_data) {\r\n\t\ttracked_data = newData;\r\n\r\n\t\t// Update status strings\r\n\t\tdiscord::Activity activity = {};\r\n\t\tactivity.SetName(PROJECT_NAME);\r\n\t\tactivity.SetState(GetStateString().c_str());\r\n\t\tactivity.SetDetails(GetDetailString().c_str());\r\n\t\tactivity.SetInstance(true);\r\n\r\n\t\tactivity.GetTimestamps().SetStart(start_time);\r\n\r\n\t\t// Set image assets\r\n\t\tactivity.GetAssets().SetLargeImage(GetPlayerAssetString().c_str());\r\n\t\tactivity.GetAssets().SetLargeText(GetTooltipString().c_str());\r\n\t\tactivity.GetAssets().SetSmallImage(GetIconAsset());\r\n\t\tactivity.GetAssets().SetSmallText(gszProductName);\r\n\r\n\t\tdiscord_core->ActivityManager().UpdateActivity(activity, IgnoreResult);\r\n\t}\r\n\tdiscord_core->RunCallbacks();\r\n}\r\n\r\nvoid StartGame()\r\n{\r\n\ttracked_data = PlayerData { dungeon_type::DTYPE_NONE, _setlevels::SL_NONE, 0, 0, 0 };\r\n\twant_menu_update = true;\r\n\tResetStartTime();\r\n}\r\n\r\nvoid UpdateMenu(bool forced)\r\n{\r\n\tif (discord_core == nullptr)\r\n\t\treturn;\r\n\r\n\tif (want_menu_update || forced) {\r\n\t\tif (!forced) {\r\n\t\t\tResetStartTime();\r\n\t\t}\r\n\t\twant_menu_update = false;\r\n\r\n\t\tdiscord::Activity activity = {};\r\n\t\tactivity.SetName(PROJECT_NAME);\r\n\t\tactivity.SetState(_(/* TRANSLATORS: Discord activity, not in game */ \"In Menu\").data());\r\n\r\n\t\tactivity.GetTimestamps().SetStart(start_time);\r\n\r\n\t\tactivity.GetAssets().SetLargeImage(GetIconAsset());\r\n\t\tactivity.GetAssets().SetLargeText(gszProductName);\r\n\r\n\t\tdiscord_core->ActivityManager().UpdateActivity(activity, IgnoreResult);\r\n\t}\r\n\tdiscord_core->RunCallbacks();\r\n}\r\n\r\n} // namespace discord_manager\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/discord/discord.h",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\nnamespace discord_manager {\r\n\r\n#ifdef DISCORD\r\nvoid UpdateGame();\r\nvoid StartGame();\r\nvoid UpdateMenu(bool forced = false);\r\n#else\r\nconstexpr void UpdateGame()\r\n{\r\n}\r\n\r\nconstexpr void StartGame()\r\n{\r\n}\r\n\r\nconstexpr void UpdateMenu(bool forced = false)\r\n{\r\n}\r\n#endif\r\n\r\n} // namespace discord_manager\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/doom.cpp",
    "content": "/**\r\n * @file doom.cpp\r\n *\r\n * Implementation of the map of the stars quest.\r\n */\r\n#include \"doom.h\"\r\n\r\n#include <optional>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nOptionalOwnedClxSpriteList DoomSprite;\r\n} // namespace\r\n\r\nbool DoomFlag;\r\n\r\nvoid doom_init()\r\n{\r\n\tDoomSprite = LoadCel(\"items\\\\map\\\\mapztown\", 640);\r\n\tDoomFlag = true;\r\n}\r\n\r\nvoid doom_close()\r\n{\r\n\tDoomFlag = false;\r\n\tDoomSprite = std::nullopt;\r\n}\r\n\r\nvoid doom_draw(const Surface &out)\r\n{\r\n\tif (!DoomFlag) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tClxDraw(out, GetUIRectangle().position + Displacement { 0, 352 }, (*DoomSprite)[0]);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/doom.h",
    "content": "/**\r\n * @file doom.h\r\n *\r\n * Interface of the map of the stars quest.\r\n */\r\n#pragma once\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern bool DoomFlag;\r\nvoid doom_init();\r\nvoid doom_close();\r\nvoid doom_draw(const Surface &out);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/abstract_net.cpp",
    "content": "#include \"dvlnet/abstract_net.h\"\r\n\r\n#include \"dvlnet/loopback.h\"\r\n#include \"utils/stubs.h\"\r\n\r\n#ifndef NONET\r\n#include \"dvlnet/cdwrap.h\"\r\n\r\n#ifndef DISABLE_ZERO_TIER\r\n#include \"dvlnet/base_protocol.h\"\r\n#include \"dvlnet/protocol_zt.h\"\r\n#endif\r\n\r\n#ifndef DISABLE_TCP\r\n#include \"dvlnet/tcp_client.h\"\r\n#endif\r\n#endif\r\n\r\nnamespace devilution::net {\r\n\r\nstd::unique_ptr<abstract_net> abstract_net::MakeNet(provider_t provider)\r\n{\r\n#ifdef NONET\r\n\treturn std::make_unique<loopback>();\r\n#else\r\n\tswitch (provider) {\r\n#ifndef DISABLE_TCP\r\n\tcase SELCONN_TCP:\r\n\t\treturn std::make_unique<cdwrap>([]() {\r\n\t\t\treturn std::make_unique<tcp_client>();\r\n\t\t});\r\n#endif\r\n#ifndef DISABLE_ZERO_TIER\r\n\tcase SELCONN_ZT:\r\n\t\treturn std::make_unique<cdwrap>([]() {\r\n\t\t\treturn std::make_unique<base_protocol<protocol_zt>>();\r\n\t\t});\r\n#endif\r\n\tcase SELCONN_LOOPBACK:\r\n\t\treturn std::make_unique<loopback>();\r\n\tdefault:\r\n\t\tABORT();\r\n\t}\r\n#endif\r\n}\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/abstract_net.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <exception>\r\n#include <memory>\r\n#include <string>\r\n#include <vector>\r\n\r\n#include \"multi.h\"\r\n#include \"storm/storm_net.hpp\"\r\n\r\nnamespace devilution::net {\r\n\r\nusing buffer_t = std::vector<unsigned char>;\r\nusing provider_t = unsigned long;\r\n\r\nclass abstract_net {\r\npublic:\r\n\tvirtual int create(std::string_view addrstr) = 0;\r\n\tvirtual int join(std::string_view addrstr) = 0;\r\n\tvirtual bool SNetReceiveMessage(uint8_t *sender, void **data, size_t *size) = 0;\r\n\tvirtual bool SNetSendMessage(uint8_t dest, void *data, size_t size) = 0;\r\n\tvirtual bool SNetReceiveTurns(char **data, size_t *size, uint32_t *status) = 0;\r\n\tvirtual bool SNetSendTurn(char *data, size_t size) = 0;\r\n\tvirtual void SNetGetProviderCaps(struct _SNETCAPS *caps) = 0;\r\n\tvirtual bool SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func) = 0;\r\n\tvirtual bool SNetUnregisterEventHandler(event_type evtype) = 0;\r\n\tvirtual bool SNetLeaveGame(net::leaveinfo_t type) = 0;\r\n\tvirtual bool SNetDropPlayer(int playerid, net::leaveinfo_t flags) = 0;\r\n\tvirtual bool SNetGetOwnerTurnsWaiting(uint32_t *turns) = 0;\r\n\tvirtual bool SNetGetTurnsInTransit(uint32_t *turns) = 0;\r\n\tvirtual void setup_gameinfo(buffer_t info) = 0;\r\n\tvirtual ~abstract_net() = default;\r\n\r\n\tvirtual std::string make_default_gamename() = 0;\r\n\r\n\tvirtual void process_network_packets()\r\n\t{\r\n\t}\r\n\r\n\tvirtual void setup_password(std::string passwd)\r\n\t{\r\n\t}\r\n\r\n\tvirtual void clear_password()\r\n\t{\r\n\t}\r\n\r\n\tvirtual bool send_info_request()\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tvirtual void clear_gamelist()\r\n\t{\r\n\t}\r\n\r\n\tvirtual std::vector<GameInfo> get_gamelist()\r\n\t{\r\n\t\treturn std::vector<GameInfo>();\r\n\t}\r\n\r\n\tvirtual DvlNetLatencies get_latencies(uint8_t playerid)\r\n\t{\r\n\t\treturn {};\r\n\t}\r\n\r\n\tstatic std::unique_ptr<abstract_net> MakeNet(provider_t provider);\r\n};\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/base.cpp",
    "content": "#include \"dvlnet/base.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nvoid base::process_network_packets()\r\n{\r\n\ttl::expected<void, PacketError> result = poll();\r\n\tif (!result.has_value()) {\r\n\t\tLogVerbose(\"Error polling network: {}\", result.error().what());\r\n\t}\r\n}\r\n\r\nvoid base::setup_gameinfo(buffer_t info)\r\n{\r\n\tgame_init_info = std::move(info);\r\n}\r\n\r\nvoid base::setup_password(std::string pw)\r\n{\r\n\tpktfty = std::make_unique<packet_factory>(pw);\r\n}\r\n\r\nvoid base::clear_password()\r\n{\r\n\tpktfty = std::make_unique<packet_factory>();\r\n}\r\n\r\nDvlNetLatencies base::get_latencies(uint8_t playerid)\r\n{\r\n\tDvlNetLatencies latencies = abstract_net::get_latencies(playerid);\r\n\tconst PlayerState &playerState = playerStateTable_[playerid];\r\n\tlatencies.echoLatency = playerState.roundTripLatency;\r\n\treturn latencies;\r\n}\r\n\r\nvoid base::RunEventHandler(_SNETEVENT &ev)\r\n{\r\n\tauto f = registered_handlers[static_cast<event_type>(ev.eventid)];\r\n\tif (f != nullptr) {\r\n\t\tf(&ev);\r\n\t}\r\n}\r\n\r\nvoid base::DisconnectNet(plr_t plr)\r\n{\r\n}\r\n\r\ntl::expected<void, PacketError> base::SendEchoRequest(plr_t player)\r\n{\r\n\tif (plr_self == PLR_BROADCAST)\r\n\t\treturn {};\r\n\tif (player == plr_self)\r\n\t\treturn {};\r\n\r\n\tconst timestamp_t now = SDL_GetTicks();\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t    = pktfty->make_packet<PT_ECHO_REQUEST>(plr_self, player, now);\r\n\tif (!pkt.has_value()) {\r\n\t\treturn tl::make_unexpected(pkt.error());\r\n\t}\r\n\treturn send(**pkt);\r\n}\r\n\r\ntl::expected<void, PacketError> base::HandleAccept(packet &pkt)\r\n{\r\n\tif (plr_self != PLR_BROADCAST) {\r\n\t\treturn {}; // already have player id\r\n\t}\r\n\tif (pkt.Cookie() == cookie_self) {\r\n\t\ttl::expected<plr_t, PacketError> newPlayerPkt = pkt.NewPlayer();\r\n\t\tif (!newPlayerPkt.has_value())\r\n\t\t\treturn tl::make_unexpected(newPlayerPkt.error());\r\n\t\tplr_self = *std::move(newPlayerPkt);\r\n\t\tConnect(plr_self);\r\n\t}\r\n\ttl::expected<const buffer_t *, PacketError> infoPkt = pkt.Info();\r\n\tif (!infoPkt.has_value())\r\n\t\treturn tl::make_unexpected(infoPkt.error());\r\n\tconst buffer_t &info = **infoPkt;\r\n\tif (game_init_info != info) {\r\n\t\tif (info.size() != sizeof(GameData)) {\r\n\t\t\tABORT();\r\n\t\t}\r\n\t\t// we joined and did not create\r\n\t\tgame_init_info = info;\r\n\t\t_SNETEVENT ev;\r\n\t\tev.eventid = EVENT_TYPE_PLAYER_CREATE_GAME;\r\n\t\tev.playerid = plr_self;\r\n\t\tev.data = const_cast<unsigned char *>(info.data());\r\n\t\tev.databytes = info.size();\r\n\t\tRunEventHandler(ev);\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, PacketError> base::HandleConnect(packet &pkt)\r\n{\r\n\treturn pkt.NewPlayer().transform([this](plr_t &&newPlayer) {\r\n\t\tConnect(newPlayer);\r\n\t});\r\n}\r\n\r\ntl::expected<void, PacketError> base::HandleTurn(packet &pkt)\r\n{\r\n\tconst plr_t src = pkt.Source();\r\n\tPlayerState &playerState = playerStateTable_[src];\r\n\tstd::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\treturn pkt.Turn().transform([&](turn_t &&turn) {\r\n\t\tturnQueue.push_back(turn);\r\n\t\tMakeReady(turn.SequenceNumber);\r\n\t});\r\n}\r\n\r\ntl::expected<void, PacketError> base::HandleDisconnect(packet &pkt)\r\n{\r\n\ttl::expected<plr_t, PacketError> newPlayer = pkt.NewPlayer();\r\n\tif (!newPlayer.has_value())\r\n\t\treturn tl::make_unexpected(newPlayer.error());\r\n\tif (*newPlayer == plr_self)\r\n\t\treturn tl::make_unexpected(\"We were dropped by the owner?\");\r\n\tif (IsConnected(*newPlayer)) {\r\n\t\ttl::expected<leaveinfo_t, PacketError> leaveinfo = pkt.LeaveInfo();\r\n\t\tif (!leaveinfo.has_value())\r\n\t\t\treturn tl::make_unexpected(leaveinfo.error());\r\n\t\t_SNETEVENT ev;\r\n\t\tev.eventid = EVENT_TYPE_PLAYER_LEAVE_GAME;\r\n\t\tev.playerid = *newPlayer;\r\n\t\tev.data = reinterpret_cast<unsigned char *>(&*leaveinfo);\r\n\t\tev.databytes = sizeof(leaveinfo_t);\r\n\t\tRunEventHandler(ev);\r\n\t\tDisconnectNet(*newPlayer);\r\n\t\tClearMsg(*newPlayer);\r\n\t\tPlayerState &playerState = playerStateTable_[*newPlayer];\r\n\t\tplayerState.isConnected = false;\r\n\t\tplayerState.turnQueue.clear();\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, PacketError> base::HandleEchoRequest(packet &pkt)\r\n{\r\n\t// If we have already left the game,\r\n\t// there is no need to respond to echoes\r\n\tif (plr_self == PLR_BROADCAST) return {};\r\n\r\n\treturn pkt.Time()\r\n\t    .and_then([&](cookie_t &&pktTime) {\r\n\t\t    return pktfty->make_packet<PT_ECHO_REPLY>(plr_self, pkt.Source(), pktTime);\r\n\t    })\r\n\t    .and_then([&](std::unique_ptr<packet> &&pkt) {\r\n\t\t    return send(*pkt);\r\n\t    });\r\n}\r\n\r\ntl::expected<void, PacketError> base::HandleEchoReply(packet &pkt)\r\n{\r\n\tconst uint32_t now = SDL_GetTicks();\r\n\tplr_t src = pkt.Source();\r\n\tif (src >= MAX_PLRS) return {};\r\n\treturn pkt.Time().transform([&](cookie_t &&pktTime) {\r\n\t\tPlayerState &playerState = playerStateTable_[src];\r\n\t\tplayerState.roundTripLatency = now - pktTime;\r\n\t});\r\n}\r\n\r\nvoid base::ClearMsg(plr_t plr)\r\n{\r\n\tmessage_queue.erase(std::remove_if(message_queue.begin(),\r\n\t                        message_queue.end(),\r\n\t                        [&](message_t &msg) {\r\n\t\t                        return msg.sender == plr;\r\n\t                        }),\r\n\t    message_queue.end());\r\n}\r\n\r\ntl::expected<void, PacketError> base::Connect(plr_t player)\r\n{\r\n\tPlayerState &playerState = playerStateTable_[player];\r\n\tconst bool wasConnected = playerState.isConnected;\r\n\tplayerState.isConnected = true;\r\n\r\n\tif (!wasConnected)\r\n\t\treturn SendFirstTurnIfReady(player);\r\n\treturn {};\r\n}\r\n\r\nbool base::IsConnected(plr_t player) const\r\n{\r\n\tconst PlayerState &playerState = playerStateTable_[player];\r\n\treturn playerState.isConnected;\r\n}\r\n\r\ntl::expected<void, PacketError> base::RecvLocal(packet &pkt)\r\n{\r\n\tif (pkt.Source() < MAX_PLRS) {\r\n\t\tif (tl::expected<void, PacketError> result = Connect(pkt.Source());\r\n\t\t    !result.has_value()) {\r\n\t\t\treturn result;\r\n\t\t}\r\n\t}\r\n\tswitch (pkt.Type()) {\r\n\tcase PT_MESSAGE:\r\n\t\treturn pkt.Message().transform([&](const buffer_t *message) {\r\n\t\t\tmessage_queue.emplace_back(pkt.Source(), *message);\r\n\t\t});\r\n\tcase PT_TURN:\r\n\t\treturn HandleTurn(pkt);\r\n\tcase PT_JOIN_ACCEPT:\r\n\t\treturn HandleAccept(pkt);\r\n\tcase PT_CONNECT:\r\n\t\treturn HandleConnect(pkt);\r\n\tcase PT_DISCONNECT:\r\n\t\treturn HandleDisconnect(pkt);\r\n\tcase PT_ECHO_REQUEST:\r\n\t\treturn HandleEchoRequest(pkt);\r\n\tcase PT_ECHO_REPLY:\r\n\t\treturn HandleEchoReply(pkt);\r\n\tdefault:\r\n\t\treturn {};\r\n\t\t// otherwise drop\r\n\t}\r\n}\r\n\r\nbool base::SNetReceiveMessage(uint8_t *sender, void **data, size_t *size)\r\n{\r\n\tuint32_t now = SDL_GetTicks();\r\n\tif (now == 0) now++;\r\n\tif (lastEchoTime == 0 || now - lastEchoTime > 5000) {\r\n\t\tfor (plr_t i = 0; i < Players.size(); i++)\r\n\t\t\tSendEchoRequest(i);\r\n\t\tlastEchoTime = now;\r\n\t}\r\n\tprocess_network_packets();\r\n\tif (message_queue.empty())\r\n\t\treturn false;\r\n\tmessage_last = message_queue.front();\r\n\tmessage_queue.pop_front();\r\n\t*sender = message_last.sender;\r\n\t*size = message_last.payload.size();\r\n\t*data = message_last.payload.data();\r\n\treturn true;\r\n}\r\n\r\nbool base::SNetSendMessage(uint8_t playerId, void *data, size_t size)\r\n{\r\n\tif (playerId != SNPLAYER_OTHERS && playerId >= MAX_PLRS)\r\n\t\tabort();\r\n\tauto *rawMessage = reinterpret_cast<unsigned char *>(data);\r\n\tconst buffer_t message(rawMessage, rawMessage + size);\r\n\tif (playerId == plr_self)\r\n\t\tmessage_queue.emplace_back(plr_self, message);\r\n\tplr_t dest;\r\n\tif (playerId == SNPLAYER_OTHERS)\r\n\t\tdest = PLR_BROADCAST;\r\n\telse\r\n\t\tdest = playerId;\r\n\tif (dest != plr_self) {\r\n\t\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t\t    = pktfty->make_packet<PT_MESSAGE>(plr_self, dest, message);\r\n\t\tif (!pkt.has_value()) {\r\n\t\t\tLogError(\"make_packet: {}\", pkt.error().what());\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\ttl::expected<void, PacketError> result = send(**pkt);\r\n\t\tif (!result.has_value()) {\r\n\t\t\tLogError(\"send: {}\", result.error().what());\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool base::AllTurnsArrived()\r\n{\r\n\tfor (size_t i = 0; i < Players.size(); ++i) {\r\n\t\tconst PlayerState &playerState = playerStateTable_[i];\r\n\t\tif (!playerState.isConnected)\r\n\t\t\tcontinue;\r\n\r\n\t\tconst std::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\t\tif (turnQueue.empty())\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool base::SNetReceiveTurns(char **data, size_t *size, uint32_t *status)\r\n{\r\n\tprocess_network_packets();\r\n\r\n\tfor (size_t i = 0; i < Players.size(); ++i) {\r\n\t\tstatus[i] = 0;\r\n\r\n\t\tPlayerState &playerState = playerStateTable_[i];\r\n\t\tif (!playerState.isConnected)\r\n\t\t\tcontinue;\r\n\r\n\t\tstatus[i] |= PS_CONNECTED;\r\n\r\n\t\tstd::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\t\twhile (!turnQueue.empty()) {\r\n\t\t\tconst turn_t &turn = turnQueue.front();\r\n\t\t\tconst seq_t diff = turn.SequenceNumber - current_turn;\r\n\t\t\tif (diff <= 0x7F)\r\n\t\t\t\tbreak;\r\n\t\t\tturnQueue.pop_front();\r\n\t\t}\r\n\t}\r\n\r\n\tif (AllTurnsArrived()) {\r\n\t\tfor (size_t i = 0; i < Players.size(); ++i) {\r\n\t\t\tPlayerState &playerState = playerStateTable_[i];\r\n\t\t\tif (!playerState.isConnected)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tstd::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\t\t\tif (turnQueue.empty())\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst turn_t &turn = turnQueue.front();\r\n\t\t\tif (turn.SequenceNumber != current_turn)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tplayerState.lastTurnValue = turn.Value;\r\n\t\t\tturnQueue.pop_front();\r\n\r\n\t\t\tstatus[i] |= PS_ACTIVE;\r\n\t\t\tstatus[i] |= PS_TURN_ARRIVED;\r\n\t\t\tsize[i] = sizeof(int32_t);\r\n\t\t\tdata[i] = reinterpret_cast<char *>(&playerState.lastTurnValue);\r\n\t\t}\r\n\r\n\t\tcurrent_turn++;\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\tfor (size_t i = 0; i < Players.size(); ++i) {\r\n\t\tconst PlayerState &playerState = playerStateTable_[i];\r\n\t\tif (!playerState.isConnected)\r\n\t\t\tcontinue;\r\n\r\n\t\tconst std::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\t\tif (turnQueue.empty())\r\n\t\t\tcontinue;\r\n\r\n\t\tstatus[i] |= PS_ACTIVE;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool base::SNetSendTurn(char *data, size_t size)\r\n{\r\n\tif (size != sizeof(int32_t))\r\n\t\tABORT();\r\n\r\n\tturn_t turn;\r\n\tturn.SequenceNumber = next_turn;\r\n\tstd::memcpy(&turn.Value, data, size);\r\n\tnext_turn++;\r\n\r\n\tPlayerState &playerState = playerStateTable_[plr_self];\r\n\tstd::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\tturnQueue.push_back(turn);\r\n\tSendTurnIfReady(turn);\r\n\treturn true;\r\n}\r\n\r\ntl::expected<void, PacketError> base::SendTurnIfReady(turn_t turn)\r\n{\r\n\tif (awaitingSequenceNumber_)\r\n\t\tawaitingSequenceNumber_ = !IsGameHost();\r\n\r\n\tif (!awaitingSequenceNumber_) {\r\n\t\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t\t    = pktfty->make_packet<PT_TURN>(plr_self, PLR_BROADCAST, turn);\r\n\t\tif (!pkt.has_value()) {\r\n\t\t\treturn tl::make_unexpected(pkt.error());\r\n\t\t}\r\n\t\treturn send(**pkt);\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, PacketError> base::SendFirstTurnIfReady(plr_t player)\r\n{\r\n\tif (awaitingSequenceNumber_)\r\n\t\treturn {};\r\n\r\n\tconst PlayerState &playerState = playerStateTable_[plr_self];\r\n\tconst std::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\tif (turnQueue.empty())\r\n\t\treturn {};\r\n\r\n\tfor (const turn_t turn : turnQueue) {\r\n\t\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t\t    = pktfty->make_packet<PT_TURN>(plr_self, player, turn);\r\n\t\tif (!pkt.has_value()) {\r\n\t\t\treturn tl::make_unexpected(pkt.error());\r\n\t\t}\r\n\t\ttl::expected<void, PacketError> result = send(**pkt);\r\n\t\tif (!result.has_value()) {\r\n\t\t\treturn result;\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, PacketError> base::MakeReady(seq_t sequenceNumber)\r\n{\r\n\tif (!awaitingSequenceNumber_)\r\n\t\treturn {};\r\n\r\n\tcurrent_turn = sequenceNumber;\r\n\tnext_turn = sequenceNumber;\r\n\tawaitingSequenceNumber_ = false;\r\n\r\n\tPlayerState &playerState = playerStateTable_[plr_self];\r\n\tstd::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\tfor (turn_t &turn : turnQueue) {\r\n\t\tturn.SequenceNumber = next_turn;\r\n\t\tnext_turn++;\r\n\t\tif (tl::expected<void, PacketError> result = SendTurnIfReady(turn);\r\n\t\t    !result.has_value()) {\r\n\t\t\treturn result;\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid base::SNetGetProviderCaps(struct _SNETCAPS *caps)\r\n{\r\n\tcaps->size = 0;                  // engine writes only ?!?\r\n\tcaps->flags = 0;                 // unused\r\n\tcaps->maxmessagesize = 512;      // capped to 512; underflow if < 24\r\n\tcaps->maxqueuesize = 0;          // unused\r\n\tcaps->maxplayers = MAX_PLRS;     // capped to 4\r\n\tcaps->bytessec = 1000000;        // ?\r\n\tcaps->latencyms = 0;             // unused\r\n\tcaps->defaultturnssec = 10;      // ?\r\n\tcaps->defaultturnsintransit = 2; // maximum acceptable number\r\n\t                                 // of turns in queue?\r\n}\r\n\r\nbool base::SNetUnregisterEventHandler(event_type evtype)\r\n{\r\n\tregistered_handlers.erase(evtype);\r\n\treturn true;\r\n}\r\n\r\nbool base::SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func)\r\n{\r\n\t/*\r\n  engine registers handler for:\r\n  EVENT_TYPE_PLAYER_LEAVE_GAME\r\n  EVENT_TYPE_PLAYER_CREATE_GAME (should be raised during SNetCreateGame\r\n  for non-creating player)\r\n  EVENT_TYPE_PLAYER_MESSAGE (for bnet? not implemented)\r\n  (engine uses same function for all three)\r\n*/\r\n\tregistered_handlers[evtype] = func;\r\n\treturn true;\r\n}\r\n\r\nbool base::SNetLeaveGame(net::leaveinfo_t type)\r\n{\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t    = pktfty->make_packet<PT_DISCONNECT>(\r\n\t        plr_self, PLR_BROADCAST, plr_self, type);\r\n\tif (!pkt.has_value()) {\r\n\t\tLogError(\"make_packet: {}\", pkt.error().what());\r\n\t\treturn false;\r\n\t}\r\n\ttl::expected<void, PacketError> result = send(**pkt);\r\n\tif (!result.has_value()) {\r\n\t\tLogError(\"send: {}\", result.error().what());\r\n\t\treturn false;\r\n\t}\r\n\tplr_self = PLR_BROADCAST;\r\n\treturn true;\r\n}\r\n\r\nbool base::SNetDropPlayer(int playerid, net::leaveinfo_t flags)\r\n{\r\n\tconst plr_t plr = static_cast<plr_t>(playerid);\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t    = pktfty->make_packet<PT_DISCONNECT>(\r\n\t        plr_self,\r\n\t        PLR_BROADCAST,\r\n\t        plr,\r\n\t        flags);\r\n\tif (!pkt.has_value()) {\r\n\t\tLogError(\"make_packet: {}\", pkt.error().what());\r\n\t\treturn false;\r\n\t}\r\n\t// Disconnect at the network layer first so we\r\n\t// don't send players their own disconnect packet\r\n\tDisconnectNet(plr);\r\n\ttl::expected<void, PacketError> sendResult = send(**pkt);\r\n\tif (!sendResult.has_value()) {\r\n\t\tLogError(\"send: {}\", sendResult.error().what());\r\n\t\treturn false;\r\n\t}\r\n\ttl::expected<void, PacketError> receiveResult = RecvLocal(**pkt);\r\n\tif (!receiveResult.has_value()) {\r\n\t\tLogError(\"SNetDropPlayer: {}\", receiveResult.error().what());\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nplr_t base::GetOwner()\r\n{\r\n\tfor (plr_t i = 0; i < Players.size(); ++i) {\r\n\t\tif (IsConnected(i)) {\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\treturn PLR_BROADCAST; // should be unreachable\r\n}\r\n\r\nbool base::SNetGetOwnerTurnsWaiting(uint32_t *turns)\r\n{\r\n\tprocess_network_packets();\r\n\r\n\tconst plr_t owner = GetOwner();\r\n\tconst PlayerState &playerState = playerStateTable_[owner];\r\n\tconst std::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\t*turns = static_cast<uint32_t>(turnQueue.size());\r\n\r\n\treturn true;\r\n}\r\n\r\nbool base::SNetGetTurnsInTransit(uint32_t *turns)\r\n{\r\n\tconst PlayerState &playerState = playerStateTable_[plr_self];\r\n\tconst std::deque<turn_t> &turnQueue = playerState.turnQueue;\r\n\t*turns = static_cast<uint32_t>(turnQueue.size());\r\n\treturn true;\r\n}\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/base.h",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstdint>\r\n#include <deque>\r\n#include <memory>\r\n#include <string>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"dvlnet/abstract_net.h\"\r\n#include \"dvlnet/packet.h\"\r\n#include \"multi.h\"\r\n#include \"storm/storm_net.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nclass base : public abstract_net {\r\npublic:\r\n\tbool SNetReceiveMessage(uint8_t *sender, void **data, size_t *size) override;\r\n\tbool SNetSendMessage(uint8_t playerId, void *data, size_t size) override;\r\n\tbool SNetReceiveTurns(char **data, size_t *size, uint32_t *status) override;\r\n\tbool SNetSendTurn(char *data, size_t size) override;\r\n\tvoid SNetGetProviderCaps(struct _SNETCAPS *caps) override;\r\n\tbool SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func) override;\r\n\tbool SNetUnregisterEventHandler(event_type evtype) override;\r\n\tbool SNetLeaveGame(net::leaveinfo_t type) override;\r\n\tbool SNetDropPlayer(int playerid, net::leaveinfo_t flags) override;\r\n\tbool SNetGetOwnerTurnsWaiting(uint32_t *turns) override;\r\n\tbool SNetGetTurnsInTransit(uint32_t *turns) override;\r\n\r\n\tvirtual tl::expected<void, PacketError> poll() = 0;\r\n\tvirtual tl::expected<void, PacketError> send(packet &pkt) = 0;\r\n\tvirtual void DisconnectNet(plr_t plr);\r\n\r\n\tvoid process_network_packets() override;\r\n\r\n\tvoid setup_gameinfo(buffer_t info) override;\r\n\r\n\tvoid setup_password(std::string pw) override;\r\n\tvoid clear_password() override;\r\n\r\n\tDvlNetLatencies get_latencies(uint8_t playerid) override;\r\n\r\n\t~base() override = default;\r\n\r\nprotected:\r\n\tankerl::unordered_dense::map<event_type, SEVTHANDLER> registered_handlers;\r\n\tbuffer_t game_init_info;\r\n\r\n\tstruct message_t {\r\n\t\tuint8_t sender;\r\n\t\tbuffer_t payload;\r\n\t\tmessage_t()\r\n\t\t    : sender(-1)\r\n\t\t    , payload({})\r\n\t\t{\r\n\t\t}\r\n\t\tmessage_t(int s, buffer_t p)\r\n\t\t    : sender(s)\r\n\t\t    , payload(p)\r\n\t\t{\r\n\t\t}\r\n\t};\r\n\r\n\tstruct PlayerState {\r\n\t\tbool isConnected = {};\r\n\t\tstd::deque<turn_t> turnQueue;\r\n\t\tint32_t lastTurnValue = {};\r\n\t\tuint32_t roundTripLatency = {};\r\n\t};\r\n\r\n\tseq_t current_turn = 0;\r\n\tseq_t next_turn = 0;\r\n\tmessage_t message_last;\r\n\tstd::deque<message_t> message_queue;\r\n\r\n\tplr_t plr_self = PLR_BROADCAST;\r\n\tcookie_t cookie_self = 0;\r\n\r\n\tstd::unique_ptr<packet_factory> pktfty;\r\n\r\n\ttl::expected<void, PacketError> Connect(plr_t player);\r\n\ttl::expected<void, PacketError> RecvLocal(packet &pkt);\r\n\tvoid RunEventHandler(_SNETEVENT &ev);\r\n\ttl::expected<void, PacketError> SendEchoRequest(plr_t player);\r\n\r\n\t[[nodiscard]] bool IsConnected(plr_t player) const;\r\n\tvirtual bool IsGameHost() = 0;\r\n\r\nprivate:\r\n\tstd::array<PlayerState, MAX_PLRS> playerStateTable_;\r\n\tbool awaitingSequenceNumber_ = true;\r\n\tuint32_t lastEchoTime = 0;\r\n\r\n\tplr_t GetOwner();\r\n\tbool AllTurnsArrived();\r\n\ttl::expected<void, PacketError> MakeReady(seq_t sequenceNumber);\r\n\ttl::expected<void, PacketError> SendTurnIfReady(turn_t turn);\r\n\ttl::expected<void, PacketError> SendFirstTurnIfReady(plr_t player);\r\n\tvoid ClearMsg(plr_t plr);\r\n\r\n\ttl::expected<void, PacketError> HandleAccept(packet &pkt);\r\n\ttl::expected<void, PacketError> HandleConnect(packet &pkt);\r\n\ttl::expected<void, PacketError> HandleTurn(packet &pkt);\r\n\ttl::expected<void, PacketError> HandleDisconnect(packet &pkt);\r\n\ttl::expected<void, PacketError> HandleEchoRequest(packet &pkt);\r\n\ttl::expected<void, PacketError> HandleEchoReply(packet &pkt);\r\n};\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/base_protocol.h",
    "content": "#pragma once\r\n\r\n#include <memory>\r\n#include <set>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"dvlnet/base.h\"\r\n#include \"dvlnet/packet.h\"\r\n#include \"player.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution::net {\r\n\r\ntemplate <class P>\r\nclass base_protocol : public base {\r\npublic:\r\n\tint create(std::string_view addrstr) override;\r\n\tint join(std::string_view addrstr) override;\r\n\ttl::expected<void, PacketError> poll() override;\r\n\ttl::expected<void, PacketError> send(packet &pkt) override;\r\n\tvoid DisconnectNet(plr_t plr) override;\r\n\r\n\tbool SNetLeaveGame(net::leaveinfo_t type) override;\r\n\r\n\tstd::string make_default_gamename() override;\r\n\tbool send_info_request() override;\r\n\tvoid clear_gamelist() override;\r\n\tstd::vector<GameInfo> get_gamelist() override;\r\n\tDvlNetLatencies get_latencies(uint8_t playerid) override;\r\n\r\n\t~base_protocol() override = default;\r\n\r\nprotected:\r\n\tbool IsGameHost() override;\r\n\r\nprivate:\r\n\tP proto;\r\n\ttypedef typename P::endpoint endpoint_t;\r\n\r\n\tstruct Peer {\r\n\t\tendpoint_t endpoint;\r\n\t\tstd::unique_ptr<std::deque<packet>> sendQueue;\r\n\t};\r\n\r\n\tendpoint_t firstpeer;\r\n\tstd::string gamename;\r\n\r\n\tstruct GameListValue {\r\n\t\tGameData data;\r\n\t\tstd::vector<std::string> playerNames;\r\n\t\tendpoint_t peer;\r\n\t};\r\n\tankerl::unordered_dense::map</*name*/ std::string, GameListValue> game_list;\r\n\tstd::array<Peer, MAX_PLRS> peers;\r\n\tbool isGameHost_;\r\n\r\n\tplr_t get_master();\r\n\ttl::expected<void, PacketError> InitiateHandshake(plr_t player);\r\n\ttl::expected<void, PacketError> SendTo(plr_t player, packet &pkt);\r\n\tvoid DrainSendQueue(plr_t player);\r\n\tvoid recv();\r\n\ttl::expected<void, PacketError> handle_join_request(packet &pkt, endpoint_t sender);\r\n\ttl::expected<void, PacketError> recv_decrypted(packet &pkt, endpoint_t sender);\r\n\ttl::expected<void, PacketError> recv_ingame(packet &pkt, endpoint_t sender);\r\n\tbool is_recognized(endpoint_t sender);\r\n\r\n\ttl::expected<void, PacketError> wait_network();\r\n\ttl::expected<void, PacketError> wait_firstpeer();\r\n\ttl::expected<void, PacketError> wait_join();\r\n};\r\n\r\ntemplate <class P>\r\nplr_t base_protocol<P>::get_master()\r\n{\r\n\tplr_t ret = plr_self;\r\n\tfor (plr_t i = 0; i < Players.size(); ++i)\r\n\t\tif (peers[i].endpoint)\r\n\t\t\tret = std::min(ret, i);\r\n\treturn ret;\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::wait_network()\r\n{\r\n\t// wait for ZeroTier for 5 seconds\r\n\tfor (auto i = 0; i < 500; ++i) {\r\n\t\ttl::expected<bool, PacketError> status = proto.network_online();\r\n\t\tif (!status.has_value())\r\n\t\t\treturn tl::make_unexpected(std::move(status).error());\r\n\t\tif (*status)\r\n\t\t\treturn {};\r\n\t\tSDL_Delay(10);\r\n\t}\r\n\treturn tl::make_unexpected(\"Timeout waiting for ZeroTier network initialization\");\r\n}\r\n\r\ntemplate <class P>\r\nvoid base_protocol<P>::DisconnectNet(plr_t plr)\r\n{\r\n\tPeer &peer = peers[plr];\r\n\tproto.disconnect(peer.endpoint);\r\n\tpeer = {};\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::wait_firstpeer()\r\n{\r\n\tfirstpeer = {};\r\n\t// wait for peer for 5 seconds\r\n\tfor (auto i = 0; i < 500; ++i) {\r\n\t\tauto it = game_list.find(gamename);\r\n\t\tif (it != game_list.end()) {\r\n\t\t\tfirstpeer = it->second.peer;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tsend_info_request();\r\n\t\trecv();\r\n\t\tSDL_Delay(10);\r\n\t}\r\n\tif (!firstpeer)\r\n\t\treturn tl::make_unexpected(\"Timeout waiting for response from game host\");\r\n\treturn {};\r\n}\r\n\r\ntemplate <class P>\r\nbool base_protocol<P>::send_info_request()\r\n{\r\n\ttl::expected<bool, PacketError> status = proto.peers_ready();\r\n\tif (!status.has_value()) {\r\n\t\tLogError(\"peers_ready: {}\", status.error().what());\r\n\t\treturn false;\r\n\t}\r\n\tif (!*status)\r\n\t\treturn false;\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t    = pktfty->make_packet<PT_INFO_REQUEST>(PLR_BROADCAST, PLR_MASTER);\r\n\tif (!pkt.has_value()) {\r\n\t\tLogError(\"make_packet: {}\", pkt.error().what());\r\n\t\treturn false;\r\n\t}\r\n\tproto.send_oob_mc((*pkt)->Data());\r\n\treturn true;\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::wait_join()\r\n{\r\n\tcookie_self = packet_out::GenerateCookie();\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t    = pktfty->make_packet<PT_JOIN_REQUEST>(PLR_BROADCAST, PLR_MASTER, cookie_self, game_init_info);\r\n\tif (!pkt.has_value()) {\r\n\t\treturn tl::make_unexpected(pkt.error());\r\n\t}\r\n\ttl::expected<void, PacketError> result = proto.send(firstpeer, (*pkt)->Data());\r\n\tif (!result.has_value()) {\r\n\t\treturn result;\r\n\t}\r\n\tfor (auto i = 0; i < 500; ++i) {\r\n\t\trecv();\r\n\t\tif (plr_self != PLR_BROADCAST)\r\n\t\t\treturn {}; // join successful\r\n\t\tSDL_Delay(10);\r\n\t}\r\n\treturn tl::make_unexpected(\"Timeout waiting to join game\");\r\n}\r\n\r\ntemplate <class P>\r\nint base_protocol<P>::create(std::string_view addrstr)\r\n{\r\n\tgamename = addrstr;\r\n\tisGameHost_ = true;\r\n\r\n\ttl::expected<void, PacketError> isReady = wait_network();\r\n\tif (!isReady.has_value()) {\r\n\t\tconst std::string_view message = isReady.error().what();\r\n\t\tSDL_SetError(\"%.*s\", static_cast<int>(message.size()), message.data());\r\n\t\treturn -1;\r\n\t}\r\n\tplr_self = 0;\r\n\tif (tl::expected<void, PacketError> result = Connect(plr_self);\r\n\t    !result.has_value()) {\r\n\t\tconst std::string_view message = result.error().what();\r\n\t\tSDL_SetError(\"%.*s\", static_cast<int>(message.size()), message.data());\r\n\t\treturn -1;\r\n\t}\r\n\treturn plr_self;\r\n}\r\n\r\ntemplate <class P>\r\nint base_protocol<P>::join(std::string_view addrstr)\r\n{\r\n\tgamename = addrstr;\r\n\tisGameHost_ = false;\r\n\r\n\ttl::expected<void, PacketError> isReady = wait_network();\r\n\tif (!isReady.has_value()) {\r\n\t\tconst std::string_view message = isReady.error().what();\r\n\t\tSDL_SetError(\"%.*s\", static_cast<int>(message.size()), message.data());\r\n\t\treturn -1;\r\n\t}\r\n\ttl::expected<void, PacketError> isPeerReady = wait_firstpeer();\r\n\tif (!isPeerReady.has_value()) {\r\n\t\tconst std::string_view message = isPeerReady.error().what();\r\n\t\tSDL_SetError(\"%.*s\", static_cast<int>(message.size()), message.data());\r\n\t\treturn -1;\r\n\t}\r\n\ttl::expected<void, PacketError> isJoined = wait_join();\r\n\tif (!isJoined.has_value()) {\r\n\t\tconst std::string_view message = isJoined.error().what();\r\n\t\tSDL_SetError(\"%.*s\", static_cast<int>(message.size()), message.data());\r\n\t\treturn -1;\r\n\t}\r\n\treturn (plr_self == PLR_BROADCAST ? -1 : plr_self);\r\n}\r\n\r\ntemplate <class P>\r\nbool base_protocol<P>::IsGameHost()\r\n{\r\n\treturn isGameHost_;\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::poll()\r\n{\r\n\trecv();\r\n\treturn {};\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::InitiateHandshake(plr_t player)\r\n{\r\n\tPeer &peer = peers[player];\r\n\r\n\t// The first packet sent will initiate the TCP connection over the ZeroTier network.\r\n\t// It will cause problems if both peers attempt to initiate the handshake simultaneously.\r\n\t// If the connection is already open, it should be safe to initiate from either end.\r\n\t// If not, only the player with the smaller player number should initiate the handshake.\r\n\tif (peer.endpoint && (plr_self < player || proto.is_peer_connected(peer.endpoint)))\r\n\t\treturn SendEchoRequest(player);\r\n\r\n\treturn {};\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::send(packet &pkt)\r\n{\r\n\tplr_t destination = pkt.Destination();\r\n\tif (destination == PLR_BROADCAST) {\r\n\t\tfor (plr_t player = 0; player < Players.size(); player++) {\r\n\t\t\ttl::expected<void, PacketError> result = SendTo(player, pkt);\r\n\t\t\tif (!result.has_value())\r\n\t\t\t\tLogError(\"Failed to send packet {} to player {}: {}\", static_cast<uint8_t>(pkt.Type()), player, result.error().what());\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\tif (destination >= MAX_PLRS)\r\n\t\treturn tl::make_unexpected(\"Invalid player ID\");\r\n\tif (destination == plr_self)\r\n\t\treturn {};\r\n\treturn SendTo(destination, pkt);\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::SendTo(plr_t player, packet &pkt)\r\n{\r\n\tPeer &peer = peers[player];\r\n\tif (!peer.endpoint)\r\n\t\treturn {};\r\n\r\n\t// The handshake uses echo packets so clients know\r\n\t// when they can safely drain their send queues\r\n\tif (peer.sendQueue && !IsAnyOf(pkt.Type(), PT_ECHO_REQUEST, PT_ECHO_REPLY)) {\r\n\t\tpeer.sendQueue->push_back(pkt);\r\n\t\treturn {};\r\n\t}\r\n\r\n\treturn proto.send(peer.endpoint, pkt.Data());\r\n}\r\n\r\ntemplate <class P>\r\nvoid base_protocol<P>::recv()\r\n{\r\n\tbuffer_t pkt_buf;\r\n\tendpoint_t sender;\r\n\twhile (proto.recv(sender, pkt_buf)) { // read until kernel buffer is empty?\r\n\t\ttl::expected<void, PacketError> result\r\n\t\t    = pktfty->make_packet(pkt_buf)\r\n\t\t          .and_then([&](std::unique_ptr<packet> &&pkt) {\r\n\t\t\t          return recv_decrypted(*pkt, sender);\r\n\t\t          });\r\n\t\tif (!result.has_value()) {\r\n\t\t\t// drop packet\r\n\t\t\tproto.disconnect(sender);\r\n\t\t\tLog(\"{}\", result.error().what());\r\n\t\t}\r\n\t}\r\n\twhile (proto.get_disconnected(sender)) {\r\n\t\tfor (plr_t i = 0; i < Players.size(); ++i) {\r\n\t\t\tif (peers[i].endpoint == sender) {\r\n\t\t\t\tDisconnectNet(i);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::handle_join_request(packet &inPkt, endpoint_t sender)\r\n{\r\n\tplr_t i;\r\n\tfor (i = 0; i < Players.size(); ++i) {\r\n\t\tPeer &peer = peers[i];\r\n\t\tif (i != plr_self && !peer.endpoint) {\r\n\t\t\tpeer.endpoint = sender;\r\n\t\t\tpeer.sendQueue = std::make_unique<std::deque<packet>>();\r\n\t\t\tif (tl::expected<void, PacketError> result = Connect(i);\r\n\t\t\t    !result.has_value()) {\r\n\t\t\t\treturn result;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif (i >= MAX_PLRS) {\r\n\t\t// already full\r\n\t\treturn {};\r\n\t}\r\n\r\n\tauto senderinfo = sender.serialize();\r\n\tfor (plr_t j = 0; j < Players.size(); ++j) {\r\n\t\tendpoint_t peer = peers[j].endpoint;\r\n\t\tif ((j != plr_self) && (j != i) && peer) {\r\n\t\t\ttl::expected<void, PacketError> result\r\n\t\t\t    = pktfty->make_packet<PT_CONNECT>(PLR_MASTER, PLR_BROADCAST, i, senderinfo)\r\n\t\t\t          .and_then([&](std::unique_ptr<packet> &&pkt) { return proto.send(peer, pkt->Data()); })\r\n\t\t\t          .and_then([&]() { return pktfty->make_packet<PT_CONNECT>(PLR_MASTER, PLR_BROADCAST, j, peer.serialize()); })\r\n\t\t\t          .and_then([&](std::unique_ptr<packet> &&pkt) { return proto.send(sender, pkt->Data()); });\r\n\t\t\tif (!result.has_value())\r\n\t\t\t\treturn result;\r\n\t\t}\r\n\t}\r\n\r\n\t// PT_JOIN_ACCEPT must be sent after all PT_CONNECT packets so the new player does\r\n\t// not resume game logic until after having been notified of all existing players\r\n\ttl::expected<cookie_t, PacketError> cookie = inPkt.Cookie();\r\n\tif (!cookie.has_value())\r\n\t\treturn tl::make_unexpected(cookie.error());\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t    = pktfty->make_packet<PT_JOIN_ACCEPT>(plr_self, PLR_BROADCAST, *cookie, i, game_init_info);\r\n\tif (!pkt.has_value())\r\n\t\treturn tl::make_unexpected(pkt.error());\r\n\ttl::expected<void, PacketError> result = proto.send(sender, (*pkt)->Data());\r\n\tif (!result.has_value())\r\n\t\treturn result;\r\n\tDrainSendQueue(i);\r\n\treturn {};\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::recv_decrypted(packet &pkt, endpoint_t sender)\r\n{\r\n\tif (pkt.Source() == PLR_BROADCAST && pkt.Destination() == PLR_MASTER && pkt.Type() == PT_INFO_REPLY) {\r\n\t\tsize_t neededSize = sizeof(GameData) + (PlayerNameLength * MAX_PLRS);\r\n\t\tconst tl::expected<const buffer_t *, PacketError> pktInfo = pkt.Info();\r\n\t\tif (!pktInfo.has_value())\r\n\t\t\treturn tl::make_unexpected(pktInfo.error());\r\n\t\tconst buffer_t &infoBuffer = **pktInfo;\r\n\t\tif (infoBuffer.size() < neededSize)\r\n\t\t\treturn {};\r\n\t\tGameData gameData;\r\n\t\tstd::memcpy(&gameData, infoBuffer.data(), sizeof(GameData));\r\n\t\tgameData.swapLE();\r\n\t\tif (gameData.size != sizeof(GameData))\r\n\t\t\treturn {};\r\n\t\tstd::vector<std::string> playerNames;\r\n\t\tfor (size_t i = 0; i < Players.size(); i++) {\r\n\t\t\tstd::string_view playerNameBuffer {\r\n\t\t\t\treinterpret_cast<const char *>(infoBuffer.data() + sizeof(GameData) + (i * PlayerNameLength)),\r\n\t\t\t\tPlayerNameLength\r\n\t\t\t};\r\n\t\t\tif (const size_t nullPos = playerNameBuffer.find('\\0'); nullPos != std::string_view::npos) {\r\n\t\t\t\tplayerNameBuffer.remove_suffix(playerNameBuffer.size() - nullPos);\r\n\t\t\t}\r\n\t\t\tif (!playerNameBuffer.empty()) {\r\n\t\t\t\tplayerNames.emplace_back(playerNameBuffer);\r\n\t\t\t}\r\n\t\t}\r\n\t\tstd::string gameName;\r\n\t\tsize_t gameNameSize = infoBuffer.size() - neededSize;\r\n\t\tgameName.resize(gameNameSize);\r\n\t\tstd::memcpy(&gameName[0], infoBuffer.data() + neededSize, gameNameSize);\r\n\t\tgame_list[gameName] = GameListValue { gameData, std::move(playerNames), sender };\r\n\t\treturn {};\r\n\t}\r\n\treturn recv_ingame(pkt, sender);\r\n}\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> base_protocol<P>::recv_ingame(packet &pkt, endpoint_t sender)\r\n{\r\n\tif (pkt.Source() == PLR_BROADCAST && pkt.Destination() == PLR_MASTER) {\r\n\t\tif (pkt.Type() == PT_JOIN_REQUEST) {\r\n\t\t\tif (tl::expected<void, PacketError> result = handle_join_request(pkt, sender);\r\n\t\t\t    !result.has_value()) {\r\n\t\t\t\treturn result;\r\n\t\t\t}\r\n\t\t} else if (pkt.Type() == PT_INFO_REQUEST) {\r\n\t\t\tif ((plr_self != PLR_BROADCAST) && (get_master() == plr_self)) {\r\n\t\t\t\tbuffer_t buf;\r\n\t\t\t\tbuf.resize(game_init_info.size() + (PlayerNameLength * MAX_PLRS) + gamename.size());\r\n\t\t\t\tstd::memcpy(buf.data(), &game_init_info[0], game_init_info.size());\r\n\t\t\t\tfor (size_t i = 0; i < Players.size(); i++) {\r\n\t\t\t\t\tif (Players[i].plractive) {\r\n\t\t\t\t\t\tstd::memcpy(buf.data() + game_init_info.size() + (i * PlayerNameLength), &Players[i]._pName, PlayerNameLength);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tstd::memset(buf.data() + game_init_info.size() + (i * PlayerNameLength), '\\0', PlayerNameLength);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tstd::memcpy(buf.data() + game_init_info.size() + (PlayerNameLength * MAX_PLRS), &gamename[0], gamename.size());\r\n\t\t\t\ttl::expected<std::unique_ptr<packet>, PacketError> reply\r\n\t\t\t\t    = pktfty->make_packet<PT_INFO_REPLY>(PLR_BROADCAST, PLR_MASTER, buf);\r\n\t\t\t\tif (!reply.has_value()) {\r\n\t\t\t\t\treturn tl::make_unexpected(reply.error());\r\n\t\t\t\t}\r\n\t\t\t\tproto.send_oob(sender, (*reply)->Data());\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\tif (pkt.Source() == PLR_MASTER && pkt.Type() == PT_CONNECT) {\r\n\t\tif (!is_recognized(sender)) {\r\n\t\t\tLogDebug(\"Invalid packet: PT_CONNECT received from unrecognized endpoint\");\r\n\t\t\treturn {};\r\n\t\t}\r\n\r\n\t\t// addrinfo packets\r\n\t\ttl::expected<plr_t, PacketError> newPlayer = pkt.NewPlayer();\r\n\t\tif (!newPlayer.has_value())\r\n\t\t\treturn tl::make_unexpected(newPlayer.error());\r\n\t\tPeer &peer = peers[*newPlayer];\r\n\t\ttl::expected<const buffer_t *, PacketError> pktInfo = pkt.Info();\r\n\t\tif (!pktInfo.has_value())\r\n\t\t\treturn tl::make_unexpected(pktInfo.error());\r\n\t\tif (tl::expected<void, PacketError> result = peer.endpoint.unserialize(**pktInfo);\r\n\t\t    !result.has_value()) {\r\n\t\t\treturn result;\r\n\t\t}\r\n\t\tpeer.sendQueue = std::make_unique<std::deque<packet>>();\r\n\t\tif (tl::expected<void, PacketError> result = Connect(*newPlayer);\r\n\t\t    !result.has_value()) {\r\n\t\t\treturn result;\r\n\t\t}\r\n\r\n\t\tif (plr_self != PLR_BROADCAST)\r\n\t\t\treturn InitiateHandshake(*newPlayer);\r\n\t\treturn {};\r\n\t}\r\n\tif (pkt.Source() >= MAX_PLRS) {\r\n\t\t// normal packets\r\n\t\tLogDebug(\"Invalid packet: packet source ({}) >= MAX_PLRS\", pkt.Source());\r\n\t\treturn {};\r\n\t}\r\n\tif (sender == firstpeer && pkt.Type() == PT_JOIN_ACCEPT) {\r\n\t\tplr_t src = pkt.Source();\r\n\t\tpeers[src].endpoint = sender;\r\n\t\tif (tl::expected<void, PacketError> result = Connect(src);\r\n\t\t    !result.has_value()) {\r\n\t\t\treturn result;\r\n\t\t}\r\n\t\tfirstpeer = {};\r\n\t} else if (sender != peers[pkt.Source()].endpoint) {\r\n\t\tLogDebug(\"Invalid packet: packet source ({}) received from unrecognized endpoint\", pkt.Source());\r\n\t\treturn {};\r\n\t}\r\n\tif (pkt.Destination() != plr_self && pkt.Destination() != PLR_BROADCAST)\r\n\t\treturn {}; // packet not for us, drop\r\n\r\n\tbool wasBroadcast = plr_self == PLR_BROADCAST;\r\n\tif (tl::expected<void, PacketError> result = RecvLocal(pkt);\r\n\t    !result.has_value()) {\r\n\t\treturn result;\r\n\t}\r\n\r\n\tif (plr_self != PLR_BROADCAST) {\r\n\t\tif (wasBroadcast) {\r\n\t\t\t// Send a handshake to everyone just after PT_JOIN_ACCEPT\r\n\t\t\tfor (plr_t player = 0; player < Players.size(); player++) {\r\n\t\t\t\tif (tl::expected<void, PacketError> result = InitiateHandshake(player);\r\n\t\t\t\t    !result.has_value()) {\r\n\t\t\t\t\treturn result;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDrainSendQueue(pkt.Source());\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntemplate <class P>\r\nvoid base_protocol<P>::DrainSendQueue(plr_t player)\r\n{\r\n\tPeer &srcPeer = peers[player];\r\n\tif (!srcPeer.sendQueue)\r\n\t\treturn;\r\n\r\n\tstd::deque<packet> &sendQueue = *srcPeer.sendQueue;\r\n\twhile (!sendQueue.empty()) {\r\n\t\tpacket &pkt = sendQueue.front();\r\n\t\ttl::expected<void, PacketError> result = proto.send(srcPeer.endpoint, pkt.Data());\r\n\t\tif (!result.has_value())\r\n\t\t\tLogError(\"DrainSendQueue failed to send packet: {}\", result.error().what());\r\n\t\tsendQueue.pop_front();\r\n\t}\r\n\r\n\tsrcPeer.sendQueue = nullptr;\r\n}\r\n\r\ntemplate <class P>\r\nbool base_protocol<P>::is_recognized(endpoint_t sender)\r\n{\r\n\tif (!sender)\r\n\t\treturn false;\r\n\r\n\tif (sender == firstpeer)\r\n\t\treturn true;\r\n\r\n\tfor (auto player = 0; player <= MAX_PLRS; player++) {\r\n\t\tif (sender == peers[player].endpoint)\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\ntemplate <class P>\r\nvoid base_protocol<P>::clear_gamelist()\r\n{\r\n\tgame_list.clear();\r\n}\r\n\r\ntemplate <class P>\r\nstd::vector<GameInfo> base_protocol<P>::get_gamelist()\r\n{\r\n\trecv();\r\n\tstd::vector<GameInfo> ret;\r\n\tret.reserve(game_list.size());\r\n\tfor (const auto &[name, gameInfo] : game_list) {\r\n\t\tconst auto &[gameData, players, endpoint] = gameInfo;\r\n\t\tstd::optional<int> latency = proto.get_latency_to(endpoint);\r\n\t\tstd::optional<bool> isRelayed = proto.is_peer_relayed(endpoint);\r\n\t\tret.push_back(GameInfo { name, gameData, players, latency, isRelayed });\r\n\t}\r\n\tc_sort(ret, [](const GameInfo &a, const GameInfo &b) { return a.name < b.name; });\r\n\treturn ret;\r\n}\r\n\r\ntemplate <class P>\r\nDvlNetLatencies base_protocol<P>::get_latencies(uint8_t playerid)\r\n{\r\n\tDvlNetLatencies latencies = base::get_latencies(playerid);\r\n\tPeer &srcPeer = peers[playerid];\r\n\tlatencies.providerLatency = proto.get_latency_to(srcPeer.endpoint);\r\n\tlatencies.isRelayed = proto.is_peer_relayed(srcPeer.endpoint);\r\n\treturn latencies;\r\n}\r\n\r\ntemplate <class P>\r\nbool base_protocol<P>::SNetLeaveGame(net::leaveinfo_t type)\r\n{\r\n\tauto ret = base::SNetLeaveGame(type);\r\n\trecv();\r\n\treturn ret;\r\n}\r\n\r\ntemplate <class P>\r\nstd::string base_protocol<P>::make_default_gamename()\r\n{\r\n\treturn proto.make_default_gamename();\r\n}\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/cdwrap.cpp",
    "content": "#include \"dvlnet/cdwrap.h\"\r\n\r\nnamespace devilution::net {\r\n\r\nvoid cdwrap::reset()\r\n{\r\n\tdvlnet_wrap = make_net_fn_();\r\n\tdvlnet_wrap->setup_gameinfo(game_init_info);\r\n\r\n\tif (game_pw != std::nullopt) {\r\n\t\tdvlnet_wrap->setup_password(*game_pw);\r\n\t} else {\r\n\t\tdvlnet_wrap->clear_password();\r\n\t}\r\n\r\n\tfor (const auto &[eventType, eventHandler] : registered_handlers)\r\n\t\tdvlnet_wrap->SNetRegisterEventHandler(eventType, eventHandler);\r\n}\r\n\r\nint cdwrap::create(std::string_view addrstr)\r\n{\r\n\treset();\r\n\treturn dvlnet_wrap->create(addrstr);\r\n}\r\n\r\nint cdwrap::join(std::string_view addrstr)\r\n{\r\n\tgame_init_info = buffer_t();\r\n\treset();\r\n\treturn dvlnet_wrap->join(addrstr);\r\n}\r\n\r\nvoid cdwrap::process_network_packets()\r\n{\r\n\tdvlnet_wrap->process_network_packets();\r\n}\r\n\r\nvoid cdwrap::setup_gameinfo(buffer_t info)\r\n{\r\n\tgame_init_info = std::move(info);\r\n\tif (dvlnet_wrap)\r\n\t\tdvlnet_wrap->setup_gameinfo(game_init_info);\r\n}\r\n\r\nbool cdwrap::SNetReceiveMessage(uint8_t *sender, void **data, size_t *size)\r\n{\r\n\treturn dvlnet_wrap->SNetReceiveMessage(sender, data, size);\r\n}\r\n\r\nbool cdwrap::SNetSendMessage(uint8_t playerID, void *data, size_t size)\r\n{\r\n\treturn dvlnet_wrap->SNetSendMessage(playerID, data, size);\r\n}\r\n\r\nbool cdwrap::SNetReceiveTurns(char **data, size_t *size, uint32_t *status)\r\n{\r\n\treturn dvlnet_wrap->SNetReceiveTurns(data, size, status);\r\n}\r\n\r\nbool cdwrap::SNetSendTurn(char *data, size_t size)\r\n{\r\n\treturn dvlnet_wrap->SNetSendTurn(data, size);\r\n}\r\n\r\nvoid cdwrap::SNetGetProviderCaps(struct _SNETCAPS *caps)\r\n{\r\n\tdvlnet_wrap->SNetGetProviderCaps(caps);\r\n}\r\n\r\nbool cdwrap::SNetUnregisterEventHandler(event_type evtype)\r\n{\r\n\tregistered_handlers.erase(evtype);\r\n\tif (dvlnet_wrap)\r\n\t\treturn dvlnet_wrap->SNetUnregisterEventHandler(evtype);\r\n\treturn true;\r\n}\r\n\r\nbool cdwrap::SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func)\r\n{\r\n\tregistered_handlers[evtype] = func;\r\n\tif (dvlnet_wrap)\r\n\t\treturn dvlnet_wrap->SNetRegisterEventHandler(evtype, func);\r\n\treturn true;\r\n}\r\n\r\nbool cdwrap::SNetLeaveGame(net::leaveinfo_t type)\r\n{\r\n\treturn dvlnet_wrap->SNetLeaveGame(type);\r\n}\r\n\r\nbool cdwrap::SNetDropPlayer(int playerid, net::leaveinfo_t flags)\r\n{\r\n\treturn dvlnet_wrap->SNetDropPlayer(playerid, flags);\r\n}\r\n\r\nbool cdwrap::SNetGetOwnerTurnsWaiting(uint32_t *turns)\r\n{\r\n\treturn dvlnet_wrap->SNetGetOwnerTurnsWaiting(turns);\r\n}\r\n\r\nbool cdwrap::SNetGetTurnsInTransit(uint32_t *turns)\r\n{\r\n\treturn dvlnet_wrap->SNetGetTurnsInTransit(turns);\r\n}\r\n\r\nstd::string cdwrap::make_default_gamename()\r\n{\r\n\treturn dvlnet_wrap->make_default_gamename();\r\n}\r\n\r\nbool cdwrap::send_info_request()\r\n{\r\n\treturn dvlnet_wrap->send_info_request();\r\n}\r\n\r\nvoid cdwrap::clear_gamelist()\r\n{\r\n\tdvlnet_wrap->clear_gamelist();\r\n}\r\n\r\nstd::vector<GameInfo> cdwrap::get_gamelist()\r\n{\r\n\treturn dvlnet_wrap->get_gamelist();\r\n}\r\n\r\nvoid cdwrap::setup_password(std::string pw)\r\n{\r\n\tgame_pw = pw;\r\n\treturn dvlnet_wrap->setup_password(pw);\r\n}\r\n\r\nvoid cdwrap::clear_password()\r\n{\r\n\tgame_pw = std::nullopt;\r\n\treturn dvlnet_wrap->clear_password();\r\n}\r\n\r\nDvlNetLatencies cdwrap::get_latencies(uint8_t playerid)\r\n{\r\n\treturn dvlnet_wrap->get_latencies(playerid);\r\n}\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/cdwrap.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <exception>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <function_ref.hpp>\r\n\r\n#include \"dvlnet/abstract_net.h\"\r\n#include \"storm/storm_net.hpp\"\r\n\r\nnamespace devilution::net {\r\n\r\nclass cdwrap : public abstract_net {\r\nprivate:\r\n\tstd::unique_ptr<abstract_net> dvlnet_wrap;\r\n\tankerl::unordered_dense::map<event_type, SEVTHANDLER> registered_handlers;\r\n\tbuffer_t game_init_info;\r\n\tstd::optional<std::string> game_pw;\r\n\ttl::function_ref<std::unique_ptr<abstract_net>()> make_net_fn_;\r\n\r\n\tvoid reset();\r\n\r\npublic:\r\n\texplicit cdwrap(tl::function_ref<std::unique_ptr<abstract_net>()> makeNetFn)\r\n\t    : make_net_fn_(makeNetFn)\r\n\t{\r\n\t\treset();\r\n\t}\r\n\r\n\tint create(std::string_view addrstr) override;\r\n\tint join(std::string_view addrstr) override;\r\n\tbool SNetReceiveMessage(uint8_t *sender, void **data, size_t *size) override;\r\n\tbool SNetSendMessage(uint8_t dest, void *data, size_t size) override;\r\n\tbool SNetReceiveTurns(char **data, size_t *size, uint32_t *status) override;\r\n\tbool SNetSendTurn(char *data, size_t size) override;\r\n\tvoid SNetGetProviderCaps(struct _SNETCAPS *caps) override;\r\n\tbool SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func) override;\r\n\tbool SNetUnregisterEventHandler(event_type evtype) override;\r\n\tbool SNetLeaveGame(net::leaveinfo_t type) override;\r\n\tbool SNetDropPlayer(int playerid, net::leaveinfo_t flags) override;\r\n\tbool SNetGetOwnerTurnsWaiting(uint32_t *turns) override;\r\n\tbool SNetGetTurnsInTransit(uint32_t *turns) override;\r\n\tvoid process_network_packets() override;\r\n\tvoid setup_gameinfo(buffer_t info) override;\r\n\tstd::string make_default_gamename() override;\r\n\tbool send_info_request() override;\r\n\tvoid clear_gamelist() override;\r\n\tstd::vector<GameInfo> get_gamelist() override;\r\n\tvoid setup_password(std::string pw) override;\r\n\tvoid clear_password() override;\r\n\tDvlNetLatencies get_latencies(uint8_t playerid) override;\r\n\r\n\tvirtual ~cdwrap() = default;\r\n};\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/frame_queue.cpp",
    "content": "#include \"dvlnet/frame_queue.h\"\r\n\r\n#include <cstring>\r\n\r\n#include \"appfat.h\"\r\n#include \"dvlnet/packet.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nnamespace {\r\n\r\nPacketError FrameQueueError()\r\n{\r\n\treturn PacketError(\"Incorrect frame size\");\r\n}\r\n\r\n} // namespace\r\n\r\nframesize_t frame_queue::Size() const\r\n{\r\n\treturn current_size;\r\n}\r\n\r\ntl::expected<buffer_t, PacketError> frame_queue::Read(framesize_t s)\r\n{\r\n\tif (current_size < s)\r\n\t\treturn tl::make_unexpected(FrameQueueError());\r\n\tbuffer_t ret;\r\n\twhile (s > 0 && s >= buffer_deque.front().size()) {\r\n\t\tconst framesize_t bufferSize = static_cast<framesize_t>(buffer_deque.front().size());\r\n\t\ts -= bufferSize;\r\n\t\tcurrent_size -= bufferSize;\r\n\t\tret.insert(ret.end(),\r\n\t\t    buffer_deque.front().begin(),\r\n\t\t    buffer_deque.front().end());\r\n\t\tbuffer_deque.pop_front();\r\n\t}\r\n\tif (s > 0) {\r\n\t\tret.insert(ret.end(),\r\n\t\t    buffer_deque.front().begin(),\r\n\t\t    buffer_deque.front().begin() + s);\r\n\t\tbuffer_deque.front().erase(buffer_deque.front().begin(),\r\n\t\t    buffer_deque.front().begin() + s);\r\n\t\tcurrent_size -= s;\r\n\t}\r\n\treturn ret;\r\n}\r\n\r\nvoid frame_queue::Write(buffer_t buf)\r\n{\r\n\tcurrent_size += static_cast<framesize_t>(buf.size());\r\n\tbuffer_deque.push_back(std::move(buf));\r\n}\r\n\r\ntl::expected<bool, PacketError> frame_queue::PacketReady()\r\n{\r\n\tif (nextsize == 0) {\r\n\t\tif (Size() < sizeof(framesize_t))\r\n\t\t\treturn false;\r\n\t\ttl::expected<buffer_t, PacketError> szbuf = Read(sizeof(framesize_t));\r\n\t\tif (!szbuf.has_value())\r\n\t\t\treturn tl::make_unexpected(szbuf.error());\r\n\t\tnextsize = LoadLE32(szbuf->data());\r\n\t\tif (nextsize == 0)\r\n\t\t\treturn tl::make_unexpected(FrameQueueError());\r\n\t}\r\n\treturn Size() >= (nextsize & frame_size_mask);\r\n}\r\n\r\nuint16_t frame_queue::ReadPacketFlags()\r\n{\r\n\tstatic_assert(sizeof(nextsize) == 4, \"framesize_t is not 4 bytes\");\r\n\treturn static_cast<uint16_t>(nextsize >> 16);\r\n}\r\n\r\ntl::expected<buffer_t, PacketError> frame_queue::ReadPacket()\r\n{\r\n\tconst framesize_t packetSize = nextsize & frame_size_mask;\r\n\tif (nextsize == 0 || Size() < packetSize)\r\n\t\treturn tl::make_unexpected(FrameQueueError());\r\n\ttl::expected<buffer_t, PacketError> ret = Read(packetSize);\r\n\tnextsize = 0;\r\n\treturn ret;\r\n}\r\n\r\ntl::expected<buffer_t, PacketError> frame_queue::MakeFrame(buffer_t packetbuf, uint16_t flags)\r\n{\r\n\tbuffer_t ret;\r\n\tconst framesize_t size = static_cast<framesize_t>(packetbuf.size());\r\n\tif (size > max_frame_size)\r\n\t\treturn tl::make_unexpected(\"Buffer exceeds maximum frame size\");\r\n\tstatic_assert(sizeof(size) == 4, \"framesize_t is not 4 bytes\");\r\n\tunsigned char sizeBuf[4];\r\n\tWriteLE32(sizeBuf, size | (static_cast<framesize_t>(flags) << 16));\r\n\tret.insert(ret.end(), sizeBuf, sizeBuf + 4);\r\n\tret.insert(ret.end(), packetbuf.begin(), packetbuf.end());\r\n\treturn ret;\r\n}\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/frame_queue.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <deque>\r\n#include <exception>\r\n#include <vector>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"dvlnet/packet.h\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\ntypedef std::vector<unsigned char> buffer_t;\r\ntypedef uint32_t framesize_t;\r\n\r\nclass frame_queue {\r\npublic:\r\n\tconstexpr static framesize_t frame_size_mask = 0xFFFF;\r\n\tconstexpr static framesize_t max_frame_size = 0xFFFF;\r\n\r\nprivate:\r\n\tframesize_t current_size = 0;\r\n\tstd::deque<buffer_t> buffer_deque;\r\n\tframesize_t nextsize = 0;\r\n\r\n\tframesize_t Size() const;\r\n\ttl::expected<buffer_t, PacketError> Read(framesize_t s);\r\n\r\npublic:\r\n\ttl::expected<bool, PacketError> PacketReady();\r\n\tuint16_t ReadPacketFlags();\r\n\ttl::expected<buffer_t, PacketError> ReadPacket();\r\n\tvoid Write(buffer_t buf);\r\n\r\n\tstatic tl::expected<buffer_t, PacketError> MakeFrame(buffer_t packetbuf, uint16_t flags = 0);\r\n};\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/leaveinfo.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nenum class leaveinfo_t : uint32_t {\r\n\tLEAVE_EXIT = 3,\r\n\tLEAVE_ENDING = 0x40000004,\r\n\tLEAVE_DROP = 0x40000006,\r\n};\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/loopback.cpp",
    "content": "#include \"dvlnet/loopback.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"multi.h\"\r\n#include \"player.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution::net {\r\n\r\nint loopback::create(std::string_view /*addrstr*/)\r\n{\r\n\tIsLoopback = true;\r\n\treturn plr_single;\r\n}\r\n\r\nint loopback::join(std::string_view /*addrstr*/)\r\n{\r\n\tABORT();\r\n}\r\n\r\nbool loopback::SNetReceiveMessage(uint8_t *sender, void **data, size_t *size)\r\n{\r\n\tif (message_queue.empty())\r\n\t\treturn false;\r\n\tmessage_last = message_queue.front();\r\n\tmessage_queue.pop();\r\n\t*sender = plr_single;\r\n\t*size = message_last.size();\r\n\t*data = message_last.data();\r\n\treturn true;\r\n}\r\n\r\nbool loopback::SNetSendMessage(uint8_t dest, void *data, size_t size)\r\n{\r\n\tif (dest == plr_single) {\r\n\t\tauto *rawMessage = reinterpret_cast<unsigned char *>(data);\r\n\t\tconst buffer_t message(rawMessage, rawMessage + size);\r\n\t\tmessage_queue.push(message);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool loopback::SNetReceiveTurns(char **data, size_t *size, uint32_t * /*status*/)\r\n{\r\n\tfor (size_t i = 0; i < Players.size(); ++i) {\r\n\t\tsize[i] = 0;\r\n\t\tdata[i] = nullptr;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool loopback::SNetSendTurn(char * /*data*/, size_t /*size*/)\r\n{\r\n\treturn true;\r\n}\r\n\r\nvoid loopback::SNetGetProviderCaps(struct _SNETCAPS *caps)\r\n{\r\n\tcaps->size = 0;                  // engine writes only ?!?\r\n\tcaps->flags = 0;                 // unused\r\n\tcaps->maxmessagesize = 512;      // capped to 512; underflow if < 24\r\n\tcaps->maxqueuesize = 0;          // unused\r\n\tcaps->maxplayers = MAX_PLRS;     // capped to 4\r\n\tcaps->bytessec = 1000000;        // ?\r\n\tcaps->latencyms = 0;             // unused\r\n\tcaps->defaultturnssec = 10;      // ?\r\n\tcaps->defaultturnsintransit = 1; // maximum acceptable number\r\n\t                                 // of turns in queue?\r\n}\r\n\r\nbool loopback::SNetRegisterEventHandler(event_type /*evtype*/,\r\n    SEVTHANDLER /*func*/)\r\n{\r\n\t// not called in real singleplayer mode\r\n\t// not needed in pseudo multiplayer mode (?)\r\n\treturn true;\r\n}\r\n\r\nbool loopback::SNetUnregisterEventHandler(event_type /*evtype*/)\r\n{\r\n\t// not called in real singleplayer mode\r\n\t// not needed in pseudo multiplayer mode (?)\r\n\treturn true;\r\n}\r\n\r\nbool loopback::SNetLeaveGame(net::leaveinfo_t /*type*/)\r\n{\r\n\tIsLoopback = false;\r\n\treturn true;\r\n}\r\n\r\nbool loopback::SNetDropPlayer(int /*playerid*/, net::leaveinfo_t /*flags*/)\r\n{\r\n\treturn true;\r\n}\r\n\r\nvoid loopback::setup_gameinfo(buffer_t info)\r\n{\r\n}\r\n\r\nbool loopback::SNetGetOwnerTurnsWaiting(uint32_t *turns)\r\n{\r\n\t*turns = 0;\r\n\treturn true;\r\n}\r\n\r\nbool loopback::SNetGetTurnsInTransit(uint32_t *turns)\r\n{\r\n\t*turns = 0;\r\n\treturn true;\r\n}\r\n\r\nstd::string loopback::make_default_gamename()\r\n{\r\n\treturn std::string(_(\"loopback\"));\r\n}\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/loopback.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <queue>\r\n#include <string>\r\n\r\n#include \"dvlnet/abstract_net.h\"\r\n\r\nnamespace devilution::net {\r\n\r\nclass loopback : public abstract_net {\r\nprivate:\r\n\tstd::queue<buffer_t> message_queue;\r\n\tbuffer_t message_last;\r\n\tuint8_t plr_single = 0;\r\n\r\npublic:\r\n\tloopback() = default;\r\n\r\n\tint create(std::string_view addrstr) override;\r\n\tint join(std::string_view addrstr) override;\r\n\tbool SNetReceiveMessage(uint8_t *sender, void **data, size_t *size) override;\r\n\tbool SNetSendMessage(uint8_t dest, void *data, size_t size) override;\r\n\tbool SNetReceiveTurns(char **data, size_t *size, uint32_t *status) override;\r\n\tbool SNetSendTurn(char *data, size_t size) override;\r\n\tvoid SNetGetProviderCaps(struct _SNETCAPS *caps) override;\r\n\tbool SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func) override;\r\n\tbool SNetUnregisterEventHandler(event_type evtype) override;\r\n\tbool SNetLeaveGame(net::leaveinfo_t type) override;\r\n\tbool SNetDropPlayer(int playerid, net::leaveinfo_t flags) override;\r\n\tbool SNetGetOwnerTurnsWaiting(uint32_t *turns) override;\r\n\tbool SNetGetTurnsInTransit(uint32_t *turns) override;\r\n\tvoid setup_gameinfo(buffer_t info) override;\r\n\tstd::string make_default_gamename() override;\r\n};\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/packet.cpp",
    "content": "#include \"dvlnet/packet.h\"\r\n\r\n#include <cassert>\r\n#include <cstdint>\r\n\r\n#ifdef PACKET_ENCRYPTION\r\n#include <sodium.h>\r\n#else\r\n#include <chrono>\r\n#include <random>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution::net {\r\n\r\n#ifdef PACKET_ENCRYPTION\r\n\r\ncookie_t packet_out::GenerateCookie()\r\n{\r\n\tcookie_t cookie;\r\n\trandombytes_buf(reinterpret_cast<unsigned char *>(&cookie),\r\n\t    sizeof(cookie_t));\r\n\treturn cookie;\r\n}\r\n\r\n#else\r\n\r\nclass cookie_generator {\r\npublic:\r\n\tcookie_generator()\r\n\t{\r\n\t\tunsigned seed = std::chrono::system_clock::now().time_since_epoch().count();\r\n\t\tgenerator.seed(seed);\r\n\t}\r\n\r\n\tcookie_t NewCookie()\r\n\t{\r\n\t\treturn distribution(generator);\r\n\t}\r\n\r\nprivate:\r\n\tstd::default_random_engine generator;\r\n\tstd::uniform_int_distribution<cookie_t> distribution;\r\n};\r\n\r\ncookie_generator CookieGenerator;\r\n\r\ncookie_t packet_out::GenerateCookie()\r\n{\r\n\treturn CookieGenerator.NewCookie();\r\n}\r\n\r\n#endif\r\n\r\nconst char *packet_type_to_string(uint8_t packetType)\r\n{\r\n\tswitch (packetType) {\r\n\tcase PT_MESSAGE:\r\n\t\treturn \"PT_MESSAGE\";\r\n\tcase PT_TURN:\r\n\t\treturn \"PT_TURN\";\r\n\tcase PT_JOIN_REQUEST:\r\n\t\treturn \"PT_JOIN_REQUEST\";\r\n\tcase PT_JOIN_ACCEPT:\r\n\t\treturn \"PT_JOIN_ACCEPT\";\r\n\tcase PT_CONNECT:\r\n\t\treturn \"PT_CONNECT\";\r\n\tcase PT_DISCONNECT:\r\n\t\treturn \"PT_DISCONNECT\";\r\n\tcase PT_INFO_REQUEST:\r\n\t\treturn \"PT_INFO_REQUEST\";\r\n\tcase PT_INFO_REPLY:\r\n\t\treturn \"PT_INFO_REPLY\";\r\n\tcase PT_ECHO_REQUEST:\r\n\t\treturn \"PT_ECHO_REQUEST\";\r\n\tcase PT_ECHO_REPLY:\r\n\t\treturn \"PT_ECHO_REPLY\";\r\n\tdefault:\r\n\t\treturn nullptr;\r\n\t}\r\n}\r\n\r\nPacketError PacketTypeError(std::uint8_t unknownPacketType)\r\n{\r\n\treturn PacketError(StrCat(\"Unknown packet type \", unknownPacketType));\r\n}\r\n\r\nPacketError PacketTypeError(std::initializer_list<packet_type> expectedTypes, std::uint8_t actual)\r\n{\r\n\tstd::string message = \"Expected packet of type \";\r\n\tconst auto appendPacketType = [&](std::uint8_t t) {\r\n\t\tconst char *typeStr = packet_type_to_string(t);\r\n\t\tif (typeStr != nullptr)\r\n\t\t\tmessage.append(typeStr);\r\n\t\telse\r\n\t\t\tStrAppend(message, t);\r\n\t};\r\n\r\n\tconstexpr char KJoinTypes[] = \" or \";\r\n\tfor (const packet_type t : expectedTypes) {\r\n\t\tappendPacketType(t);\r\n\t\tmessage.append(KJoinTypes);\r\n\t}\r\n\tmessage.resize(message.size() - (sizeof(KJoinTypes) - 1));\r\n\tmessage.append(\", got\");\r\n\tappendPacketType(actual);\r\n\treturn PacketError(std::move(message));\r\n}\r\n\r\nnamespace {\r\n\r\ntl::expected<void, PacketError> CheckPacketTypeOneOf(std::initializer_list<packet_type> expectedTypes, std::uint8_t actualType)\r\n{\r\n\tif (c_none_of(expectedTypes,\r\n\t        [actualType](uint8_t type) { return type == actualType; })) {\r\n\t\treturn tl::make_unexpected(PacketTypeError(expectedTypes, actualType));\r\n\t}\r\n\treturn {};\r\n}\r\n\r\n} // namespace\r\n\r\nconst buffer_t &packet::Data()\r\n{\r\n\tassert(have_encrypted || have_decrypted);\r\n\tif (have_encrypted)\r\n\t\treturn encrypted_buffer;\r\n\treturn decrypted_buffer;\r\n}\r\n\r\npacket_type packet::Type()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn m_type;\r\n}\r\n\r\nplr_t packet::Source() const\r\n{\r\n\tassert(have_decrypted);\r\n\treturn m_src;\r\n}\r\n\r\nplr_t packet::Destination() const\r\n{\r\n\tassert(have_decrypted);\r\n\treturn m_dest;\r\n}\r\n\r\ntl::expected<const buffer_t *, PacketError> packet::Message()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn CheckPacketTypeOneOf({ PT_MESSAGE }, m_type)\r\n\t    .transform([this]() { return &m_message; });\r\n}\r\n\r\ntl::expected<turn_t, PacketError> packet::Turn()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn CheckPacketTypeOneOf({ PT_TURN }, m_type)\r\n\t    .transform([this]() { return m_turn; });\r\n}\r\n\r\ntl::expected<cookie_t, PacketError> packet::Cookie()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn CheckPacketTypeOneOf({ PT_JOIN_REQUEST, PT_JOIN_ACCEPT }, m_type)\r\n\t    .transform([this]() { return m_cookie; });\r\n}\r\n\r\ntl::expected<plr_t, PacketError> packet::NewPlayer()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn CheckPacketTypeOneOf({ PT_JOIN_ACCEPT, PT_CONNECT, PT_DISCONNECT }, m_type)\r\n\t    .transform([this]() { return m_newplr; });\r\n}\r\n\r\ntl::expected<timestamp_t, PacketError> packet::Time()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn CheckPacketTypeOneOf({ PT_ECHO_REQUEST, PT_ECHO_REPLY }, m_type)\r\n\t    .transform([this]() { return m_time; });\r\n}\r\n\r\ntl::expected<const buffer_t *, PacketError> packet::Info()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn CheckPacketTypeOneOf({ PT_JOIN_REQUEST, PT_JOIN_ACCEPT, PT_CONNECT, PT_INFO_REPLY }, m_type)\r\n\t    .transform([this]() { return &m_info; });\r\n}\r\n\r\ntl::expected<leaveinfo_t, PacketError> packet::LeaveInfo()\r\n{\r\n\tassert(have_decrypted);\r\n\treturn CheckPacketTypeOneOf({ PT_DISCONNECT }, m_type)\r\n\t    .transform([this]() { return m_leaveinfo; });\r\n}\r\n\r\ntl::expected<void, PacketError> packet_in::Create(buffer_t buf)\r\n{\r\n\tassert(!have_encrypted && !have_decrypted);\r\n\tif (buf.size() < sizeof(packet_type) + 2 * sizeof(plr_t))\r\n\t\treturn tl::make_unexpected(PacketError());\r\n\r\n\tdecrypted_buffer = std::move(buf);\r\n\thave_decrypted = true;\r\n\r\n\t// TCP server implementation forwards the original data to clients\r\n\t// so although we are not decrypting anything,\r\n\t// we save a copy in encrypted_buffer anyway\r\n\tencrypted_buffer = decrypted_buffer;\r\n\thave_encrypted = true;\r\n\treturn {};\r\n}\r\n\r\n#ifdef PACKET_ENCRYPTION\r\ntl::expected<void, PacketError> packet_in::Decrypt(buffer_t buf)\r\n{\r\n\tassert(!have_encrypted && !have_decrypted);\r\n\tencrypted_buffer = std::move(buf);\r\n\thave_encrypted = true;\r\n\r\n\tif (encrypted_buffer.size() < crypto_secretbox_NONCEBYTES\r\n\t        + crypto_secretbox_MACBYTES\r\n\t        + sizeof(packet_type) + 2 * sizeof(plr_t))\r\n\t\treturn tl::make_unexpected(PacketError());\r\n\tauto pktlen = (encrypted_buffer.size()\r\n\t    - crypto_secretbox_NONCEBYTES\r\n\t    - crypto_secretbox_MACBYTES);\r\n\tdecrypted_buffer.resize(pktlen);\r\n\tconst int status = crypto_secretbox_open_easy(\r\n\t    decrypted_buffer.data(),\r\n\t    encrypted_buffer.data() + crypto_secretbox_NONCEBYTES,\r\n\t    encrypted_buffer.size() - crypto_secretbox_NONCEBYTES,\r\n\t    encrypted_buffer.data(),\r\n\t    key.data());\r\n\tif (status != 0) {\r\n\t\tauto code = PacketError::ErrorCode::DecryptionFailed;\r\n\t\tstd::string_view message = \"Failed to decrypt packet data\";\r\n\t\treturn tl::make_unexpected(PacketError(code, message));\r\n\t}\r\n\r\n\thave_decrypted = true;\r\n\treturn {};\r\n}\r\n#endif\r\n\r\n#ifdef PACKET_ENCRYPTION\r\ntl::expected<void, PacketError> packet_out::Encrypt()\r\n{\r\n\tassert(have_decrypted);\r\n\r\n\tif (have_encrypted)\r\n\t\treturn {};\r\n\r\n\tauto lenCleartext = decrypted_buffer.size();\r\n\tencrypted_buffer.insert(encrypted_buffer.begin(),\r\n\t    crypto_secretbox_NONCEBYTES, 0);\r\n\tencrypted_buffer.insert(encrypted_buffer.end(),\r\n\t    crypto_secretbox_MACBYTES + lenCleartext, 0);\r\n\trandombytes_buf(encrypted_buffer.data(), crypto_secretbox_NONCEBYTES);\r\n\tconst int status = crypto_secretbox_easy(\r\n\t    encrypted_buffer.data() + crypto_secretbox_NONCEBYTES,\r\n\t    decrypted_buffer.data(),\r\n\t    lenCleartext,\r\n\t    encrypted_buffer.data(),\r\n\t    key.data());\r\n\tif (status != 0) {\r\n\t\tauto code = PacketError::ErrorCode::EncryptionFailed;\r\n\t\tstd::string_view message = \"Failed to encrypt packet data\";\r\n\t\treturn tl::make_unexpected(PacketError(code, message));\r\n\t}\r\n\r\n\thave_encrypted = true;\r\n\treturn {};\r\n}\r\n#endif\r\n\r\npacket_factory::packet_factory()\r\n{\r\n\tsecure = false;\r\n}\r\n\r\npacket_factory::packet_factory(std::string pw)\r\n{\r\n\tsecure = false;\r\n\r\n#ifdef PACKET_ENCRYPTION\r\n\tif (sodium_init() < 0)\r\n\t\tABORT();\r\n\tpw.resize(std::min<std::size_t>(pw.size(), crypto_pwhash_argon2id_PASSWD_MAX));\r\n\tpw.resize(std::max<std::size_t>(pw.size(), crypto_pwhash_argon2id_PASSWD_MIN), 0);\r\n\tstd::string salt(\"W9bE9dQgVaeybwr2\");\r\n\tsalt.resize(crypto_pwhash_argon2id_SALTBYTES, 0);\r\n\tconst int status = crypto_pwhash(\r\n\t    key.data(),\r\n\t    crypto_secretbox_KEYBYTES,\r\n\t    pw.data(),\r\n\t    pw.size(),\r\n\t    reinterpret_cast<const unsigned char *>(salt.data()),\r\n\t    3 * crypto_pwhash_argon2id_OPSLIMIT_MIN,\r\n\t    2 * crypto_pwhash_argon2id_MEMLIMIT_MIN,\r\n\t    crypto_pwhash_ALG_ARGON2ID13);\r\n\tif (status != 0)\r\n\t\tABORT();\r\n\tsecure = true;\r\n#endif\r\n}\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/packet.h",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n#include <string>\r\n#include <type_traits>\r\n\r\n#include <expected.hpp>\r\n\r\n#ifdef PACKET_ENCRYPTION\r\n#include <sodium.h>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"dvlnet/abstract_net.h\"\r\n#include \"dvlnet/leaveinfo.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nenum packet_type : uint8_t {\r\n\t// clang-format off\r\n\tPT_MESSAGE      = 0x01,\r\n\tPT_TURN         = 0x02,\r\n\tPT_JOIN_REQUEST = 0x11,\r\n\tPT_JOIN_ACCEPT  = 0x12,\r\n\tPT_CONNECT      = 0x13,\r\n\tPT_DISCONNECT   = 0x14,\r\n\tPT_INFO_REQUEST = 0x21,\r\n\tPT_INFO_REPLY   = 0x22,\r\n\tPT_ECHO_REQUEST = 0x31,\r\n\tPT_ECHO_REPLY   = 0x32,\r\n\t// clang-format on\r\n};\r\n\r\n// Returns NULL for an invalid packet type.\r\nconst char *packet_type_to_string(uint8_t packetType);\r\n\r\ntypedef uint8_t plr_t;\r\ntypedef uint8_t seq_t;\r\ntypedef uint32_t cookie_t;\r\ntypedef uint32_t timestamp_t;\r\n#ifdef PACKET_ENCRYPTION\r\ntypedef std::array<unsigned char, crypto_secretbox_KEYBYTES> key_t;\r\n#else\r\n// Stub out the key_t definition as we're not doing any encryption.\r\nusing key_t = uint8_t;\r\n#endif\r\n\r\nstruct turn_t {\r\n\tseq_t SequenceNumber;\r\n\tint32_t Value;\r\n};\r\n\r\nstatic constexpr plr_t PLR_MASTER = 0xFE;\r\nstatic constexpr plr_t PLR_BROADCAST = 0xFF;\r\n\r\nclass PacketError {\r\npublic:\r\n\tenum class ErrorCode : uint8_t {\r\n\t\tNone,\r\n\t\tEncryptionFailed,\r\n\t\tDecryptionFailed\r\n\t};\r\n\r\n\tPacketError()\r\n\t    : message_(std::string_view(\"Incorrect packet size\"))\r\n\t    , code_(ErrorCode::None)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(const char message[])\r\n\t    : message_(std::string_view(message))\r\n\t    , code_(ErrorCode::None)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(std::string &&message)\r\n\t    : message_(std::move(message))\r\n\t    , code_(ErrorCode::None)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(std::string_view message)\r\n\t    : message_(message)\r\n\t    , code_(ErrorCode::None)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(ErrorCode code, const char message[])\r\n\t    : message_(std::string_view(message))\r\n\t    , code_(code)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(ErrorCode code, std::string &&message)\r\n\t    : message_(std::move(message))\r\n\t    , code_(code)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(ErrorCode code, std::string_view message)\r\n\t    : message_(message)\r\n\t    , code_(code)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(const PacketError &error)\r\n\t    : message_(std::string(error.message_))\r\n\t    , code_(error.code_)\r\n\t{\r\n\t}\r\n\r\n\tPacketError(PacketError &&error)\r\n\t    : message_(std::move(error.message_))\r\n\t    , code_(error.code_)\r\n\t{\r\n\t}\r\n\r\n\tstd::string_view what() const\r\n\t{\r\n\t\treturn message_;\r\n\t}\r\n\r\n\tErrorCode code() const\r\n\t{\r\n\t\treturn code_;\r\n\t}\r\n\r\nprivate:\r\n\tStringOrView message_;\r\n\tErrorCode code_;\r\n};\r\n\r\ninline PacketError IoHandlerError(std::string message)\r\n{\r\n\treturn PacketError(std::move(message));\r\n}\r\n\r\nPacketError PacketTypeError(std::uint8_t unknownPacketType);\r\nPacketError PacketTypeError(std::initializer_list<packet_type> expectedTypes, std::uint8_t actual);\r\n\r\nclass packet {\r\nprotected:\r\n\tpacket_type m_type;\r\n\tplr_t m_src;\r\n\tplr_t m_dest;\r\n\tbuffer_t m_message;\r\n\tturn_t m_turn;\r\n\tcookie_t m_cookie;\r\n\tplr_t m_newplr;\r\n\ttimestamp_t m_time;\r\n\tbuffer_t m_info;\r\n\tleaveinfo_t m_leaveinfo;\r\n\r\n\tconst key_t &key;\r\n\tbool have_encrypted = false;\r\n\tbool have_decrypted = false;\r\n\tbuffer_t encrypted_buffer;\r\n\tbuffer_t decrypted_buffer;\r\n\r\npublic:\r\n\tpacket(const key_t &k)\r\n\t    : key(k) {};\r\n\r\n\tconst buffer_t &Data();\r\n\r\n\tpacket_type Type();\r\n\tplr_t Source() const;\r\n\tplr_t Destination() const;\r\n\ttl::expected<const buffer_t *, PacketError> Message();\r\n\ttl::expected<turn_t, PacketError> Turn();\r\n\ttl::expected<cookie_t, PacketError> Cookie();\r\n\ttl::expected<plr_t, PacketError> NewPlayer();\r\n\ttl::expected<timestamp_t, PacketError> Time();\r\n\ttl::expected<const buffer_t *, PacketError> Info();\r\n\ttl::expected<leaveinfo_t, PacketError> LeaveInfo();\r\n};\r\n\r\ntemplate <class P>\r\nclass packet_proc : public packet {\r\npublic:\r\n\tusing packet::packet;\r\n\ttl::expected<void, PacketError> process_data();\r\n};\r\n\r\nclass packet_in : public packet_proc<packet_in> {\r\npublic:\r\n\tusing packet_proc<packet_in>::packet_proc;\r\n\ttl::expected<void, PacketError> Create(buffer_t buf);\r\n\ttl::expected<void, PacketError> process_element(buffer_t &x);\r\n\ttemplate <class T>\r\n\ttl::expected<void, PacketError> process_element(T &x);\r\n\ttl::expected<void, PacketError> Decrypt(buffer_t buf);\r\n};\r\n\r\nclass packet_out : public packet_proc<packet_out> {\r\npublic:\r\n\tusing packet_proc<packet_out>::packet_proc;\r\n\r\n\ttemplate <packet_type t, typename... Args>\r\n\tvoid create(Args... args);\r\n\r\n\ttl::expected<void, PacketError> process_element(buffer_t &x);\r\n\ttemplate <class T>\r\n\ttl::expected<void, PacketError> process_element(const T &x);\r\n\tstatic cookie_t GenerateCookie();\r\n\ttl::expected<void, PacketError> Encrypt();\r\n};\r\n\r\ntemplate <class P>\r\ntl::expected<void, PacketError> packet_proc<P>::process_data()\r\n{\r\n\tP &self = static_cast<P &>(*this);\r\n\t{\r\n\t\ttl::expected<void, PacketError> result\r\n\t\t    = self.process_element(m_type)\r\n\t\t          .and_then([&]() {\r\n\t\t\t          return self.process_element(m_src);\r\n\t\t          })\r\n\t\t          .and_then([&]() {\r\n\t\t\t          return self.process_element(m_dest);\r\n\t\t          });\r\n\t\tif (!result.has_value())\r\n\t\t\treturn result;\r\n\t}\r\n\tswitch (m_type) {\r\n\tcase PT_MESSAGE:\r\n\t\treturn self.process_element(m_message);\r\n\tcase PT_TURN:\r\n\t\treturn self.process_element(m_turn.SequenceNumber)\r\n\t\t    .and_then([&]() { return self.process_element(m_turn.Value); });\r\n\tcase PT_JOIN_REQUEST:\r\n\t\treturn self.process_element(m_cookie)\r\n\t\t    .and_then([&]() { return self.process_element(m_info); });\r\n\tcase PT_JOIN_ACCEPT:\r\n\t\treturn self.process_element(m_cookie)\r\n\t\t    .and_then([&]() { return self.process_element(m_newplr); })\r\n\t\t    .and_then([&]() { return self.process_element(m_info); });\r\n\tcase PT_CONNECT:\r\n\t\treturn self.process_element(m_newplr)\r\n\t\t    .and_then([&]() { return self.process_element(m_info); });\r\n\tcase PT_DISCONNECT:\r\n\t\treturn self.process_element(m_newplr)\r\n\t\t    .and_then([&]() { return self.process_element(m_leaveinfo); });\r\n\tcase PT_INFO_REPLY:\r\n\t\treturn self.process_element(m_info);\r\n\tcase PT_INFO_REQUEST:\r\n\t\treturn {};\r\n\tcase PT_ECHO_REQUEST:\r\n\tcase PT_ECHO_REPLY:\r\n\t\treturn self.process_element(m_time);\r\n\t}\r\n\treturn tl::make_unexpected(PacketTypeError(m_type));\r\n}\r\n\r\ninline tl::expected<void, PacketError> packet_in::process_element(buffer_t &x)\r\n{\r\n\tx.insert(x.begin(), decrypted_buffer.begin(), decrypted_buffer.end());\r\n\tdecrypted_buffer.resize(0);\r\n\treturn {};\r\n}\r\n\r\ntemplate <class T>\r\ntl::expected<void, PacketError> packet_in::process_element(T &x)\r\n{\r\n\tstatic_assert(std::is_integral<T>::value || std::is_enum<T>::value, \"Unsupported T\");\r\n\tstatic_assert(sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, \"Unsupported T\");\r\n\tif (decrypted_buffer.size() < sizeof(T)) {\r\n\t\treturn tl::make_unexpected(PacketError());\r\n\t}\r\n\tif (sizeof(T) == 4) {\r\n\t\tx = static_cast<T>(LoadLE32(decrypted_buffer.data()));\r\n\t} else if (sizeof(T) == 2) {\r\n\t\tx = static_cast<T>(LoadLE16(decrypted_buffer.data()));\r\n\t} else if (sizeof(T) == 1) {\r\n\t\tstd::memcpy(&x, decrypted_buffer.data(), sizeof(T));\r\n\t}\r\n\tdecrypted_buffer.erase(decrypted_buffer.begin(),\r\n\t    decrypted_buffer.begin() + sizeof(T));\r\n\treturn {};\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_INFO_REQUEST>(plr_t s, plr_t d)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_INFO_REQUEST;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_INFO_REPLY>(plr_t s, plr_t d, buffer_t i)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_INFO_REPLY;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_info = std::move(i);\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_MESSAGE>(plr_t s, plr_t d, buffer_t m)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_MESSAGE;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_message = std::move(m);\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_TURN>(plr_t s, plr_t d, turn_t u)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_TURN;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_turn = u;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_JOIN_REQUEST>(plr_t s, plr_t d,\r\n    cookie_t c, buffer_t i)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_JOIN_REQUEST;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_cookie = c;\r\n\tm_info = i;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_JOIN_ACCEPT>(plr_t s, plr_t d, cookie_t c,\r\n    plr_t n, buffer_t i)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_JOIN_ACCEPT;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_cookie = c;\r\n\tm_newplr = n;\r\n\tm_info = i;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_CONNECT>(plr_t s, plr_t d, plr_t n, buffer_t i)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_CONNECT;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_newplr = n;\r\n\tm_info = i;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_CONNECT>(plr_t s, plr_t d, plr_t n)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_CONNECT;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_newplr = n;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_DISCONNECT>(plr_t s, plr_t d, plr_t n,\r\n    leaveinfo_t l)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_DISCONNECT;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_newplr = n;\r\n\tm_leaveinfo = l;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_ECHO_REQUEST>(plr_t s, plr_t d, timestamp_t t)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_ECHO_REQUEST;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_time = t;\r\n}\r\n\r\ntemplate <>\r\ninline void packet_out::create<PT_ECHO_REPLY>(plr_t s, plr_t d, timestamp_t t)\r\n{\r\n\tif (have_encrypted || have_decrypted)\r\n\t\tABORT();\r\n\thave_decrypted = true;\r\n\tm_type = PT_ECHO_REPLY;\r\n\tm_src = s;\r\n\tm_dest = d;\r\n\tm_time = t;\r\n}\r\n\r\ninline tl::expected<void, PacketError> packet_out::process_element(buffer_t &x)\r\n{\r\n\tdecrypted_buffer.insert(decrypted_buffer.end(), x.begin(), x.end());\r\n\treturn {};\r\n}\r\n\r\ntemplate <class T>\r\ntl::expected<void, PacketError> packet_out::process_element(const T &x)\r\n{\r\n\tstatic_assert(std::is_integral<T>::value || std::is_enum<T>::value, \"Unsupported T\");\r\n\tstatic_assert(sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, \"Unsupported T\");\r\n\tif (sizeof(T) == 4) {\r\n\t\tunsigned char buf[4];\r\n\t\tif constexpr (std::is_enum<T>::value) {\r\n\t\t\tWriteLE32(buf, static_cast<std::underlying_type_t<T>>(x));\r\n\t\t} else {\r\n\t\t\tWriteLE32(buf, x);\r\n\t\t}\r\n\t\tdecrypted_buffer.insert(decrypted_buffer.end(), buf, buf + 4);\r\n\t} else if (sizeof(T) == 2) {\r\n\t\tunsigned char buf[2];\r\n\t\tif constexpr (std::is_enum<T>::value) {\r\n\t\t\tWriteLE16(buf, static_cast<std::underlying_type_t<T>>(x));\r\n\t\t} else {\r\n\t\t\tWriteLE16(buf, x);\r\n\t\t}\r\n\t\tdecrypted_buffer.insert(decrypted_buffer.end(), buf, buf + 2);\r\n\t} else if (sizeof(T) == 1) {\r\n\t\tdecrypted_buffer.push_back(static_cast<unsigned char>(x));\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nclass packet_factory {\r\n\tkey_t key = {};\r\n\tbool secure;\r\n\r\npublic:\r\n\tstatic constexpr unsigned short max_packet_size = 0xFFFF;\r\n\r\n\tpacket_factory();\r\n\tpacket_factory(std::string pw);\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> make_packet(buffer_t buf);\r\n\ttemplate <packet_type t, typename... Args>\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> make_packet(Args... args);\r\n};\r\n\r\ninline tl::expected<std::unique_ptr<packet>, PacketError> packet_factory::make_packet(buffer_t buf)\r\n{\r\n\tauto ret = std::make_unique<packet_in>(key);\r\n#ifndef PACKET_ENCRYPTION\r\n\ttl::expected<void, PacketError> isCreated = ret->Create(std::move(buf));\r\n#else\r\n\ttl::expected<void, PacketError> isCreated = !secure\r\n\t    ? ret->Create(std::move(buf))\r\n\t    : ret->Decrypt(std::move(buf));\r\n#endif\r\n\tif (!isCreated.has_value()) {\r\n\t\treturn tl::make_unexpected(isCreated.error());\r\n\t}\r\n\tif (const tl::expected<void, PacketError> result = ret->process_data(); !result.has_value()) {\r\n\t\treturn tl::make_unexpected(result.error());\r\n\t}\r\n\treturn ret;\r\n}\r\n\r\ntemplate <packet_type t, typename... Args>\r\ntl::expected<std::unique_ptr<packet>, PacketError> packet_factory::make_packet(Args... args)\r\n{\r\n\tauto ret = std::make_unique<packet_out>(key);\r\n\tret->create<t>(args...);\r\n\tif (const tl::expected<void, PacketError> result = ret->process_data(); !result.has_value()) {\r\n\t\treturn tl::make_unexpected(result.error());\r\n\t}\r\n#ifdef PACKET_ENCRYPTION\r\n\tif (secure) {\r\n\t\ttl::expected<void, PacketError> isEncrypted = ret->Encrypt();\r\n\t\tif (!isEncrypted.has_value()) {\r\n\t\t\treturn tl::make_unexpected(isEncrypted.error());\r\n\t\t}\r\n\t}\r\n#endif\r\n\treturn ret;\r\n}\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/protocol_zt.cpp",
    "content": "#include \"dvlnet/protocol_zt.h\"\r\n\r\n#include <optional>\r\n#include <random>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include <lwip/igmp.h>\r\n#include <lwip/mld6.h>\r\n#include <lwip/nd6.h>\r\n#include <lwip/sockets.h>\r\n#include <lwip/tcpip.h>\r\n\r\n#include \"dvlnet/zerotier_native.h\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nnamespace {\r\n\r\nbool GetMAC(const protocol_zt::endpoint &peer, uint64_t &mac)\r\n{\r\n\tip6_addr_t address = {};\r\n\tIP6_ADDR_PART(&address, 0, peer.addr[0], peer.addr[1], peer.addr[2], peer.addr[3]);\r\n\tIP6_ADDR_PART(&address, 1, peer.addr[4], peer.addr[5], peer.addr[6], peer.addr[7]);\r\n\tIP6_ADDR_PART(&address, 2, peer.addr[8], peer.addr[9], peer.addr[10], peer.addr[11]);\r\n\tIP6_ADDR_PART(&address, 3, peer.addr[12], peer.addr[13], peer.addr[14], peer.addr[15]);\r\n\r\n\tconst u8_t *hwaddr;\r\n\tif (nd6_get_next_hop_addr_or_queue(netif_default, nullptr, &address, &hwaddr) != ERR_OK)\r\n\t\treturn false;\r\n\r\n\tmac = hwaddr[0];\r\n\tmac = (mac << 8) | hwaddr[1];\r\n\tmac = (mac << 8) | hwaddr[2];\r\n\tmac = (mac << 8) | hwaddr[3];\r\n\tmac = (mac << 8) | hwaddr[4];\r\n\tmac = (mac << 8) | hwaddr[5];\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nprotocol_zt::protocol_zt()\r\n{\r\n\tzerotier_network_start();\r\n}\r\n\r\nvoid protocol_zt::set_nonblock(int fd)\r\n{\r\n\tstatic_assert(O_NONBLOCK == 1, \"O_NONBLOCK == 1 not satisfied\");\r\n\tauto mode = lwip_fcntl(fd, F_GETFL, 0);\r\n\tmode |= O_NONBLOCK;\r\n\tlwip_fcntl(fd, F_SETFL, mode);\r\n}\r\n\r\nvoid protocol_zt::set_nodelay(int fd)\r\n{\r\n\tconst int yes = 1;\r\n\tlwip_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&yes, sizeof(yes));\r\n}\r\n\r\nvoid protocol_zt::set_reuseaddr(int fd)\r\n{\r\n\tconst int yes = 1;\r\n\tlwip_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));\r\n}\r\n\r\ntl::expected<bool, PacketError> protocol_zt::network_online()\r\n{\r\n\tif (!zerotier_network_ready())\r\n\t\treturn false;\r\n\r\n\tstruct sockaddr_in6 in6 {\r\n\t};\r\n\tin6.sin6_port = htons(default_port);\r\n\tin6.sin6_family = AF_INET6;\r\n\tin6.sin6_addr = in6addr_any;\r\n\r\n\tif (fd_udp == -1) {\r\n\t\tfd_udp = lwip_socket(AF_INET6, SOCK_DGRAM, 0);\r\n\t\tset_reuseaddr(fd_udp);\r\n\t\tauto ret = lwip_bind(fd_udp, (struct sockaddr *)&in6, sizeof(in6));\r\n\t\tif (ret < 0) {\r\n\t\t\tstd::string_view format = \"Error binding to ZeroTier UDP socket: {}\";\r\n\t\t\tPacketError error = ProtocolError(format, strerror(errno));\r\n\t\t\treturn tl::make_unexpected(std::move(error));\r\n\t\t}\r\n\t\tset_nonblock(fd_udp);\r\n\t}\r\n\tif (fd_tcp == -1) {\r\n\t\tfd_tcp = lwip_socket(AF_INET6, SOCK_STREAM, 0);\r\n\t\tset_reuseaddr(fd_tcp);\r\n\t\tauto r1 = lwip_bind(fd_tcp, (struct sockaddr *)&in6, sizeof(in6));\r\n\t\tif (r1 < 0) {\r\n\t\t\tstd::string_view format = \"Error binding to ZeroTier TCP socket: {}\";\r\n\t\t\tPacketError error = ProtocolError(format, strerror(errno));\r\n\t\t\treturn tl::make_unexpected(std::move(error));\r\n\t\t}\r\n\t\tauto r2 = lwip_listen(fd_tcp, 10);\r\n\t\tif (r2 < 0) {\r\n\t\t\tstd::string_view format = \"Error listening on ZeroTier TCP socket: {}\";\r\n\t\t\tPacketError error = ProtocolError(format, strerror(errno));\r\n\t\t\treturn tl::make_unexpected(std::move(error));\r\n\t\t}\r\n\t\tset_nonblock(fd_tcp);\r\n\t\tset_nodelay(fd_tcp);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\ntl::expected<bool, PacketError> protocol_zt::peers_ready()\r\n{\r\n\treturn network_online()\r\n\t    .map([&](bool isOnline) { return isOnline && zerotier_peers_ready(); });\r\n}\r\n\r\ntl::expected<void, PacketError> protocol_zt::send(const endpoint &peer, const buffer_t &data)\r\n{\r\n\ttl::expected<buffer_t, PacketError> frame = frame_queue::MakeFrame(data);\r\n\tif (!frame.has_value())\r\n\t\treturn tl::make_unexpected(frame.error());\r\n\tpeer_list[peer].send_queue.push_back(*frame);\r\n\treturn {};\r\n}\r\n\r\nbool protocol_zt::send_oob(const endpoint &peer, const buffer_t &data) const\r\n{\r\n\tstruct sockaddr_in6 in6 {\r\n\t};\r\n\tin6.sin6_port = htons(default_port);\r\n\tin6.sin6_family = AF_INET6;\r\n\tstd::copy(peer.addr.begin(), peer.addr.end(), in6.sin6_addr.s6_addr);\r\n\tlwip_sendto(fd_udp, data.data(), data.size(), 0, (const struct sockaddr *)&in6, sizeof(in6));\r\n\treturn true;\r\n}\r\n\r\nbool protocol_zt::send_oob_mc(const buffer_t &data) const\r\n{\r\n\tendpoint mc;\r\n\tstd::copy(dvl_multicast_addr, dvl_multicast_addr + 16, mc.addr.begin());\r\n\treturn send_oob(mc, data);\r\n}\r\n\r\ntl::expected<bool, PacketError> protocol_zt::send_queued_peer(const endpoint &peer)\r\n{\r\n\tpeer_state &state = peer_list[peer];\r\n\tif (state.fd == -1) {\r\n\t\tstate.fd = lwip_socket(AF_INET6, SOCK_STREAM, 0);\r\n\t\tset_nodelay(state.fd);\r\n\t\tset_nonblock(state.fd);\r\n\t\tstruct sockaddr_in6 in6 {\r\n\t\t};\r\n\t\tin6.sin6_port = htons(default_port);\r\n\t\tin6.sin6_family = AF_INET6;\r\n\t\tstd::copy(peer.addr.begin(), peer.addr.end(), in6.sin6_addr.s6_addr);\r\n\t\tlwip_connect(state.fd, (const struct sockaddr *)&in6, sizeof(in6));\r\n\t}\r\n\twhile (!state.send_queue.empty()) {\r\n\t\tauto len = state.send_queue.front().size();\r\n\t\tauto r = lwip_send(state.fd, state.send_queue.front().data(), len, 0);\r\n\t\tif (r < 0) {\r\n\t\t\t// handle error\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (decltype(len)(r) < len) {\r\n\t\t\t// partial send\r\n\t\t\tauto it = state.send_queue.front().begin();\r\n\t\t\tstate.send_queue.front().erase(it, it + r);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (decltype(len)(r) == len) {\r\n\t\t\tstate.send_queue.pop_front();\r\n\t\t} else {\r\n\t\t\tstd::string_view format = \"Impossible number of bytes sent: {} available, {} sent\";\r\n\t\t\tPacketError error = ProtocolError(format, len, decltype(len)(r));\r\n\t\t\treturn tl::make_unexpected(std::move(error));\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool protocol_zt::recv_peer(const endpoint &peer)\r\n{\r\n\tunsigned char buf[PKTBUF_LEN];\r\n\tpeer_state &state = peer_list[peer];\r\n\twhile (true) {\r\n\t\tauto len = lwip_recv(state.fd, buf, sizeof(buf), 0);\r\n\t\tif (len >= 0) {\r\n\t\t\tstate.recv_queue.Write(buffer_t(buf, buf + len));\r\n\t\t} else {\r\n\t\t\treturn errno == EAGAIN || errno == EWOULDBLOCK;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool protocol_zt::send_queued_all()\r\n{\r\n\tfor (const auto &[endpoint, _] : peer_list) {\r\n\t\ttl::expected<bool, PacketError> result = send_queued_peer(endpoint);\r\n\t\tif (!result.has_value()) {\r\n\t\t\tLogError(\"send_queued_peer: {}\", result.error().what());\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (!*result) {\r\n\t\t\t// handle error?\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool protocol_zt::recv_from_peers()\r\n{\r\n\tfor (const auto &[endpoint, state] : peer_list) {\r\n\t\tif (state.fd != -1) {\r\n\t\t\tif (!recv_peer(endpoint)) {\r\n\t\t\t\tdisconnect_queue.push_back(endpoint);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool protocol_zt::recv_from_udp()\r\n{\r\n\tunsigned char buf[PKTBUF_LEN];\r\n\tstruct sockaddr_in6 in6 {\r\n\t};\r\n\tsocklen_t addrlen = sizeof(in6);\r\n\tauto len = lwip_recvfrom(fd_udp, buf, sizeof(buf), 0, (struct sockaddr *)&in6, &addrlen);\r\n\tif (len < 0)\r\n\t\treturn false;\r\n\tbuffer_t data(buf, buf + len);\r\n\tendpoint ep;\r\n\tstd::copy(in6.sin6_addr.s6_addr, in6.sin6_addr.s6_addr + 16, ep.addr.begin());\r\n\toob_recv_queue.emplace_back(ep, std::move(data));\r\n\treturn true;\r\n}\r\n\r\nbool protocol_zt::accept_all()\r\n{\r\n\tstruct sockaddr_in6 in6 {\r\n\t};\r\n\tsocklen_t addrlen = sizeof(in6);\r\n\twhile (true) {\r\n\t\tauto newfd = lwip_accept(fd_tcp, (struct sockaddr *)&in6, &addrlen);\r\n\t\tif (newfd < 0)\r\n\t\t\tbreak;\r\n\t\tendpoint ep;\r\n\t\tstd::copy(in6.sin6_addr.s6_addr, in6.sin6_addr.s6_addr + 16, ep.addr.begin());\r\n\t\tpeer_state &state = peer_list[ep];\r\n\t\tif (state.fd != -1) {\r\n\t\t\tLog(\"protocol_zt::accept_all: WARNING: overwriting connection\");\r\n\t\t\tSDL_SetError(\"protocol_zt::accept_all: WARNING: overwriting connection\");\r\n\t\t\tlwip_close(state.fd);\r\n\t\t}\r\n\t\tset_nonblock(newfd);\r\n\t\tset_nodelay(newfd);\r\n\t\tstate.fd = newfd;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool protocol_zt::recv(endpoint &peer, buffer_t &data)\r\n{\r\n\taccept_all();\r\n\tsend_queued_all();\r\n\trecv_from_peers();\r\n\trecv_from_udp();\r\n\r\n\tif (!oob_recv_queue.empty()) {\r\n\t\tpeer = oob_recv_queue.front().first;\r\n\t\tdata = oob_recv_queue.front().second;\r\n\t\toob_recv_queue.pop_front();\r\n\t\treturn true;\r\n\t}\r\n\r\n\tfor (auto &p : peer_list) {\r\n\t\ttl::expected<bool, PacketError> ready = p.second.recv_queue.PacketReady();\r\n\t\tif (!ready.has_value()) {\r\n\t\t\tLogError(\"PacketReady: {}\", ready.error().what());\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (!*ready)\r\n\t\t\tcontinue;\r\n\t\ttl::expected<buffer_t, PacketError> packet = p.second.recv_queue.ReadPacket();\r\n\t\tif (!packet.has_value()) {\r\n\t\t\tLogError(\"Failed reading packet data from peer: {}\", packet.error().what());\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tpeer = p.first;\r\n\t\tdata = *packet;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool protocol_zt::get_disconnected(endpoint &peer)\r\n{\r\n\tif (!disconnect_queue.empty()) {\r\n\t\tpeer = disconnect_queue.front();\r\n\t\tdisconnect_queue.pop_front();\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid protocol_zt::disconnect(const endpoint &peer)\r\n{\r\n\tconst auto it = peer_list.find(peer);\r\n\tif (it != peer_list.end()) {\r\n\t\tif (it->second.fd != -1) {\r\n\t\t\tif (lwip_close(it->second.fd) < 0) {\r\n\t\t\t\tLog(\"lwip_close: {}\", strerror(errno));\r\n\t\t\t\tSDL_SetError(\"lwip_close: %s\", strerror(errno));\r\n\t\t\t}\r\n\t\t}\r\n\t\tpeer_list.erase(it);\r\n\t}\r\n}\r\n\r\nvoid protocol_zt::close_all()\r\n{\r\n\tif (fd_tcp != -1) {\r\n\t\tlwip_close(fd_tcp);\r\n\t\tfd_tcp = -1;\r\n\t}\r\n\tif (fd_udp != -1) {\r\n\t\tlwip_close(fd_udp);\r\n\t\tfd_udp = -1;\r\n\t}\r\n\tfor (auto &[_, state] : peer_list) {\r\n\t\tif (state.fd != -1)\r\n\t\t\tlwip_close(state.fd);\r\n\t}\r\n\tpeer_list.clear();\r\n}\r\n\r\nprotocol_zt::~protocol_zt()\r\n{\r\n\tclose_all();\r\n}\r\n\r\nvoid protocol_zt::endpoint::from_string(const std::string &str)\r\n{\r\n\tip_addr_t a;\r\n\tif (ipaddr_aton(str.c_str(), &a) == 0)\r\n\t\treturn;\r\n\tif (!IP_IS_V6_VAL(a))\r\n\t\treturn;\r\n\tconst auto *r = reinterpret_cast<const unsigned char *>(a.u_addr.ip6.addr);\r\n\tstd::copy(r, r + 16, addr.begin());\r\n}\r\n\r\nuint64_t protocol_zt::current_ms()\r\n{\r\n\treturn 0;\r\n}\r\n\r\nbool protocol_zt::is_peer_connected(endpoint &peer)\r\n{\r\n\tconst auto it = peer_list.find(peer);\r\n\treturn it != peer_list.end() && it->second.fd != -1;\r\n}\r\n\r\nstd::optional<bool> protocol_zt::is_peer_relayed(const endpoint &peer) const\r\n{\r\n\tuint64_t mac;\r\n\tif (!GetMAC(peer, mac))\r\n\t\treturn std::nullopt;\r\n\treturn zerotier_is_relayed(mac);\r\n}\r\n\r\nstd::optional<int> protocol_zt::get_latency_to(const endpoint &peer) const\r\n{\r\n\tuint64_t mac;\r\n\tif (!GetMAC(peer, mac))\r\n\t\treturn std::nullopt;\r\n\treturn zerotier_latency(mac);\r\n}\r\n\r\nstd::string protocol_zt::make_default_gamename()\r\n{\r\n\tstd::string ret;\r\n\tstd::string allowedChars = \"abcdefghkopqrstuvwxyz\";\r\n\tstd::random_device rd;\r\n\tstd::uniform_int_distribution<size_t> dist(0, allowedChars.size() - 1);\r\n\tfor (size_t i = 0; i < 5; ++i) {\r\n\t\tret += allowedChars.at(dist(rd));\r\n\t}\r\n\treturn ret;\r\n}\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/protocol_zt.h",
    "content": "#pragma once\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <atomic>\r\n#include <cstdint>\r\n#include <deque>\r\n#include <exception>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"dvlnet/frame_queue.h\"\r\n#include \"dvlnet/packet.h\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\ntemplate <typename... Args>\r\nPacketError ProtocolError(std::string_view fmt, Args &&...args)\r\n{\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\treturn PacketError(str);\r\n}\r\n\r\nclass protocol_zt {\r\npublic:\r\n\tclass endpoint {\r\n\tpublic:\r\n\t\tstd::array<unsigned char, 16> addr = {};\r\n\r\n\t\texplicit operator bool() const\r\n\t\t{\r\n\t\t\tauto empty = std::array<unsigned char, 16> {};\r\n\t\t\treturn (addr != empty);\r\n\t\t}\r\n\r\n\t\tbool operator==(const endpoint &rhs) const\r\n\t\t{\r\n\t\t\treturn addr == rhs.addr;\r\n\t\t}\r\n\r\n\t\tbool operator!=(const endpoint &rhs) const\r\n\t\t{\r\n\t\t\treturn !(*this == rhs);\r\n\t\t}\r\n\r\n\t\tbool operator<(const endpoint &rhs) const\r\n\t\t{\r\n\t\t\treturn addr < rhs.addr;\r\n\t\t}\r\n\r\n\t\tbuffer_t serialize() const\r\n\t\t{\r\n\t\t\treturn buffer_t(addr.begin(), addr.end());\r\n\t\t}\r\n\r\n\t\ttl::expected<void, PacketError> unserialize(const buffer_t &buf)\r\n\t\t{\r\n\t\t\tif (buf.size() != 16) {\r\n\t\t\t\tstd::string_view format = \"Endpoint deserialization expected 16 bytes, got {}\";\r\n\t\t\t\tPacketError error = ProtocolError(format, buf.size());\r\n\t\t\t\treturn tl::make_unexpected(std::move(error));\r\n\t\t\t}\r\n\t\t\tstd::copy(buf.begin(), buf.end(), addr.begin());\r\n\t\t\treturn {};\r\n\t\t}\r\n\r\n\t\tvoid from_string(const std::string &str);\r\n\t};\r\n\tstruct EndpointHash {\r\n\t\tusing is_avalanching = void;\r\n\r\n\t\t[[nodiscard]] uint64_t operator()(const endpoint &e) const noexcept\r\n\t\t{\r\n\t\t\treturn ankerl::unordered_dense::hash<std::string_view> {}(\r\n\t\t\t    std::string_view { reinterpret_cast<const char *>(e.addr.data()), e.addr.size() });\r\n\t\t}\r\n\t};\r\n\r\n\tprotocol_zt();\r\n\t~protocol_zt();\r\n\tvoid disconnect(const endpoint &peer);\r\n\ttl::expected<void, PacketError> send(const endpoint &peer, const buffer_t &data);\r\n\tbool send_oob(const endpoint &peer, const buffer_t &data) const;\r\n\tbool send_oob_mc(const buffer_t &data) const;\r\n\tbool recv(endpoint &peer, buffer_t &data);\r\n\tbool get_disconnected(endpoint &peer);\r\n\ttl::expected<bool, PacketError> network_online();\r\n\ttl::expected<bool, PacketError> peers_ready();\r\n\tbool is_peer_connected(endpoint &peer);\r\n\tstd::optional<bool> is_peer_relayed(const endpoint &peer) const;\r\n\tstd::optional<int> get_latency_to(const endpoint &peer) const;\r\n\tstatic std::string make_default_gamename();\r\n\r\nprivate:\r\n\tstatic constexpr uint32_t PKTBUF_LEN = 65536;\r\n\tstatic constexpr uint16_t default_port = 6112;\r\n\r\n\tstruct peer_state {\r\n\t\tint fd = -1;\r\n\t\tstd::deque<buffer_t> send_queue;\r\n\t\tframe_queue recv_queue;\r\n\t};\r\n\r\n\tstd::deque<std::pair<endpoint, buffer_t>> oob_recv_queue;\r\n\tstd::deque<endpoint> disconnect_queue;\r\n\r\n\tankerl::unordered_dense::map<endpoint, peer_state, EndpointHash> peer_list;\r\n\tint fd_tcp = -1;\r\n\tint fd_udp = -1;\r\n\r\n\tstatic uint64_t current_ms();\r\n\tvoid close_all();\r\n\r\n\tstatic void set_nonblock(int fd);\r\n\tstatic void set_nodelay(int fd);\r\n\tstatic void set_reuseaddr(int fd);\r\n\r\n\ttl::expected<bool, PacketError> send_queued_peer(const endpoint &peer);\r\n\tbool recv_peer(const endpoint &peer);\r\n\tbool send_queued_all();\r\n\tbool recv_from_peers();\r\n\tbool recv_from_udp();\r\n\tbool accept_all();\r\n};\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/tcp_client.cpp",
    "content": "#include \"dvlnet/tcp_client.h\"\r\n\r\n#include <exception>\r\n#include <functional>\r\n#include <memory>\r\n#include <stdexcept>\r\n#include <system_error>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <asio/connect.hpp>\r\n#include <expected.hpp>\r\n\r\n#include \"options.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n\r\nnamespace devilution::net {\r\n\r\nint tcp_client::create(std::string_view addrstr)\r\n{\r\n\tauto port = *GetOptions().Network.port;\r\n\tlocal_server = std::make_unique<tcp_server>(ioc, std::string(addrstr), port, *pktfty);\r\n\treturn join(local_server->LocalhostSelf());\r\n}\r\n\r\nint tcp_client::join(std::string_view addrstr)\r\n{\r\n\tconstexpr int MsSleep = 10;\r\n\tconstexpr int NoSleep = 250;\r\n\r\n\tconst char *defaultPort = \"6112\";\r\n\tstd::string_view host;\r\n\tstd::string_view port = defaultPort;\r\n\tif (!addrstr.empty() && addrstr[0] == '[') {\r\n\t\t// Assume IPv6 address in square brackets, followed by port\r\n\t\t// Example: [::1]:6113\r\n\t\tsize_t pos = addrstr.find(']', 1);\r\n\t\tpos = pos != std::string::npos ? pos + 1 : addrstr.length();\r\n\t\thost = addrstr.substr(0, pos);\r\n\r\n\t\tif (pos != addrstr.length()) {\r\n\t\t\tif (addrstr[pos] != ':') {\r\n\t\t\t\tSDL_SetError(\"Invalid hostname: expected colon after square brackets\");\r\n\t\t\t\treturn -1;\r\n\t\t\t}\r\n\t\t\tif (++pos != addrstr.length())\r\n\t\t\t\tport = addrstr.substr(pos);\r\n\t\t}\r\n\t} else {\r\n\t\t// Assume \"hostname:port\"\r\n\t\tconst SplitByChar splithost(addrstr, ':');\r\n\t\tauto it = splithost.begin();\r\n\t\tif (it != splithost.end()) host = *it++;\r\n\t\tif (it != splithost.end()) port = *it++;\r\n\r\n\t\t// If there is more than one colon, assume it's just a plain IPv6 address\r\n\t\tif (it != splithost.end()) {\r\n\t\t\thost = addrstr;\r\n\t\t\tport = defaultPort;\r\n\t\t}\r\n\t}\r\n\r\n\tasio::error_code errorCode;\r\n\tconst asio::ip::basic_resolver_results<asio::ip::tcp> range = resolver.resolve(host, port, errorCode);\r\n\tif (errorCode) {\r\n\t\tSDL_SetError(\"%s\", errorCode.message().c_str());\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tasio::connect(sock, range, errorCode);\r\n\tif (errorCode) {\r\n\t\tSDL_SetError(\"%s\", errorCode.message().c_str());\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tconst asio::ip::tcp::no_delay option(true);\r\n\tsock.set_option(option, errorCode);\r\n\tif (errorCode)\r\n\t\tLogError(\"Client error setting socket option: {}\", errorCode.message());\r\n\r\n\tStartReceive();\r\n\t{\r\n\t\tcookie_self = packet_out::GenerateCookie();\r\n\t\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t\t    = pktfty->make_packet<PT_JOIN_REQUEST>(\r\n\t\t        PLR_BROADCAST, PLR_MASTER, cookie_self, game_init_info);\r\n\t\tif (!pkt.has_value()) {\r\n\t\t\tconst std::string_view message = pkt.error().what();\r\n\t\t\tSDL_SetError(\"make_packet: %.*s\", static_cast<int>(message.size()), message.data());\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\ttl::expected<void, PacketError> sendResult = send(**pkt);\r\n\t\tif (!sendResult.has_value()) {\r\n\t\t\tconst std::string_view message = sendResult.error().what();\r\n\t\t\tSDL_SetError(\"send: %.*s\", static_cast<int>(message.size()), message.data());\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tfor (auto i = 0; i < NoSleep; ++i) {\r\n\t\t\ttl::expected<void, PacketError> pollResult = poll();\r\n\t\t\tif (!pollResult.has_value()) {\r\n\t\t\t\tconst std::string_view message = pollResult.error().what();\r\n\t\t\t\tSDL_SetError(\"%.*s\", static_cast<int>(message.size()), message.data());\r\n\t\t\t\treturn -1;\r\n\t\t\t}\r\n\t\t\tif (plr_self != PLR_BROADCAST)\r\n\t\t\t\tbreak; // join successful\r\n\t\t\tSDL_Delay(MsSleep);\r\n\t\t}\r\n\t}\r\n\tif (plr_self == PLR_BROADCAST) {\r\n\t\tconst std::string_view message = _(\"Unable to connect\");\r\n\t\tSDL_SetError(\"%.*s\", static_cast<int>(message.size()), message.data());\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn plr_self;\r\n}\r\n\r\nbool tcp_client::IsGameHost()\r\n{\r\n\treturn local_server != nullptr;\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_client::poll()\r\n{\r\n\twhile (ioc.poll_one() > 0) {\r\n\t\tif (IsGameHost()) {\r\n\t\t\ttl::expected<void, PacketError> serverResult = local_server->CheckIoHandlerError();\r\n\t\t\tif (!serverResult.has_value())\r\n\t\t\t\treturn serverResult;\r\n\t\t}\r\n\t\tif (ioHandlerResult == std::nullopt)\r\n\t\t\tcontinue;\r\n\t\ttl::expected<void, PacketError> packetError = tl::make_unexpected(*ioHandlerResult);\r\n\t\tioHandlerResult = std::nullopt;\r\n\t\treturn packetError;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid tcp_client::HandleReceive(const asio::error_code &error, size_t bytesRead)\r\n{\r\n\tif (error) {\r\n\t\tconst PacketError packetError = IoHandlerError(error.message());\r\n\t\tRaiseIoHandlerError(packetError);\r\n\t\treturn;\r\n\t}\r\n\tif (bytesRead == 0) {\r\n\t\tconst PacketError packetError(_(\"error: read 0 bytes from server\"));\r\n\t\tRaiseIoHandlerError(packetError);\r\n\t\treturn;\r\n\t}\r\n\trecv_buffer.resize(bytesRead);\r\n\trecv_queue.Write(std::move(recv_buffer));\r\n\trecv_buffer.resize(frame_queue::max_frame_size);\r\n\twhile (true) {\r\n\t\ttl::expected<bool, PacketError> ready = recv_queue.PacketReady();\r\n\t\tif (!ready.has_value()) {\r\n\t\t\tRaiseIoHandlerError(ready.error());\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!*ready)\r\n\t\t\tbreak;\r\n\t\tif (recv_queue.ReadPacketFlags() == TcpErrorCodeFlags) {\r\n\t\t\tHandleTcpErrorCode();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\ttl::expected<void, PacketError> result\r\n\t\t    = recv_queue.ReadPacket()\r\n\t\t          .and_then([this](buffer_t &&pktData) { return pktfty->make_packet(pktData); })\r\n\t\t          .and_then([this](std::unique_ptr<packet> &&pkt) { return RecvLocal(*pkt); });\r\n\t\tif (!result.has_value()) {\r\n\t\t\tRaiseIoHandlerError(result.error());\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tStartReceive();\r\n}\r\n\r\nvoid tcp_client::StartReceive()\r\n{\r\n\tsock.async_receive(\r\n\t    asio::buffer(recv_buffer),\r\n\t    std::bind(&tcp_client::HandleReceive, this, std::placeholders::_1, std::placeholders::_2));\r\n}\r\n\r\nvoid tcp_client::HandleSend(const asio::error_code &error, size_t bytesSent)\r\n{\r\n\tif (error)\r\n\t\tRaiseIoHandlerError(error.message());\r\n}\r\n\r\nvoid tcp_client::HandleTcpErrorCode()\r\n{\r\n\ttl::expected<buffer_t, PacketError> packet = recv_queue.ReadPacket();\r\n\tif (!packet.has_value()) {\r\n\t\tRaiseIoHandlerError(packet.error());\r\n\t\treturn;\r\n\t}\r\n\r\n\tbuffer_t pktData = *packet;\r\n\tif (pktData.size() != 1) {\r\n\t\tRaiseIoHandlerError(PacketError());\r\n\t\treturn;\r\n\t}\r\n\r\n\tPacketError::ErrorCode code = static_cast<PacketError::ErrorCode>(pktData[0]);\r\n\tif (code == PacketError::ErrorCode::DecryptionFailed)\r\n\t\tRaiseIoHandlerError(_(\"Server failed to decrypt your packet. Check if you typed the password correctly.\"));\r\n\telse\r\n\t\tRaiseIoHandlerError(fmt::format(\"Unknown error code received from server: {:#04x}\", pktData[0]));\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_client::send(packet &pkt)\r\n{\r\n\ttl::expected<buffer_t, PacketError> frame = frame_queue::MakeFrame(pkt.Data());\r\n\tif (!frame.has_value())\r\n\t\treturn tl::make_unexpected(frame.error());\r\n\tstd::unique_ptr<buffer_t> framePtr = std::make_unique<buffer_t>(*frame);\r\n\tconst asio::mutable_buffer buf = asio::buffer(*framePtr);\r\n\tasio::async_write(sock, buf, [this, frame = std::move(framePtr)](const asio::error_code &error, size_t bytesSent) {\r\n\t\tHandleSend(error, bytesSent);\r\n\t});\r\n\treturn {};\r\n}\r\n\r\nvoid tcp_client::DisconnectNet(plr_t plr)\r\n{\r\n\tif (local_server != nullptr)\r\n\t\tlocal_server->DisconnectNet(plr);\r\n}\r\n\r\nbool tcp_client::SNetLeaveGame(net::leaveinfo_t type)\r\n{\r\n\tauto ret = base::SNetLeaveGame(type);\r\n\tprocess_network_packets();\r\n\tif (local_server != nullptr)\r\n\t\tlocal_server->Close();\r\n\tsock.close();\r\n\treturn ret;\r\n}\r\n\r\nstd::string tcp_client::make_default_gamename()\r\n{\r\n\treturn std::string(GetOptions().Network.szBindAddress);\r\n}\r\n\r\nvoid tcp_client::RaiseIoHandlerError(const PacketError &error)\r\n{\r\n\tioHandlerResult.emplace(error);\r\n}\r\n\r\ntcp_client::~tcp_client()\r\n    = default;\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/tcp_client.h",
    "content": "#pragma once\r\n\r\n#include <memory>\r\n#include <string>\r\n\r\n// This header must be included before any 3DS code\r\n// because 3DS SDK defines a macro with the same name\r\n// as an fmt template parameter in some versions of fmt.\r\n// See https://github.com/fmtlib/fmt/issues/3632\r\n//\r\n// 3DS uses some custom ASIO code that transitively includes\r\n// the 3DS SDK.\r\n#include <fmt/core.h>\r\n\r\n#include <asio/ts/buffer.hpp>\r\n#include <asio/ts/internet.hpp>\r\n#include <asio/ts/io_context.hpp>\r\n#include <asio/ts/net.hpp>\r\n#include <asio_handle_exception.hpp>\r\n\r\n#include \"dvlnet/base.h\"\r\n#include \"dvlnet/frame_queue.h\"\r\n#include \"dvlnet/packet.h\"\r\n#include \"dvlnet/tcp_server.h\"\r\n\r\nnamespace devilution::net {\r\n\r\nclass tcp_client : public base {\r\npublic:\r\n\tint create(std::string_view addrstr) override;\r\n\tint join(std::string_view addrstr) override;\r\n\r\n\ttl::expected<void, PacketError> poll() override;\r\n\ttl::expected<void, PacketError> send(packet &pkt) override;\r\n\tvoid DisconnectNet(plr_t plr) override;\r\n\r\n\tbool SNetLeaveGame(net::leaveinfo_t type) override;\r\n\r\n\t~tcp_client() override;\r\n\r\n\tstd::string make_default_gamename() override;\r\n\r\nprotected:\r\n\tbool IsGameHost() override;\r\n\r\nprivate:\r\n\tframe_queue recv_queue;\r\n\tbuffer_t recv_buffer = buffer_t(frame_queue::max_frame_size);\r\n\r\n\tasio::io_context ioc;\r\n\tasio::ip::tcp::resolver resolver = asio::ip::tcp::resolver(ioc);\r\n\tasio::ip::tcp::socket sock = asio::ip::tcp::socket(ioc);\r\n\tstd::unique_ptr<tcp_server> local_server; // must be declared *after* ioc\r\n\r\n\tstd::optional<PacketError> ioHandlerResult;\r\n\r\n\tvoid HandleReceive(const asio::error_code &error, size_t bytesRead);\r\n\tvoid StartReceive();\r\n\tvoid HandleSend(const asio::error_code &error, size_t bytesSent);\r\n\tvoid HandleTcpErrorCode();\r\n\r\n\tvoid RaiseIoHandlerError(const PacketError &error);\r\n};\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/tcp_server.cpp",
    "content": "#include \"dvlnet/tcp_server.h\"\r\n\r\n#include <chrono>\r\n#include <functional>\r\n#include <memory>\r\n#include <utility>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"dvlnet/base.h\"\r\n#include \"player.h\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution::net {\r\n\r\ntcp_server::tcp_server(asio::io_context &ioc, const std::string &bindaddr,\r\n    unsigned short port, packet_factory &pktfty)\r\n    : ioc(ioc)\r\n    , pktfty(pktfty)\r\n{\r\n\tauto addr = asio::ip::make_address(bindaddr);\r\n\tauto ep = asio::ip::tcp::endpoint(addr, port);\r\n\tacceptor = std::make_unique<asio::ip::tcp::acceptor>(ioc, ep, true);\r\n\tStartAccept();\r\n}\r\n\r\nstd::string tcp_server::LocalhostSelf()\r\n{\r\n\tauto addr = acceptor->local_endpoint().address();\r\n\tif (addr.is_unspecified()) {\r\n\t\tif (addr.is_v4()) {\r\n\t\t\treturn asio::ip::address_v4::loopback().to_string();\r\n\t\t}\r\n\t\tif (addr.is_v6()) {\r\n\t\t\treturn asio::ip::address_v6::loopback().to_string();\r\n\t\t}\r\n\t\tABORT();\r\n\t}\r\n\treturn addr.to_string();\r\n}\r\n\r\ntcp_server::scc tcp_server::MakeConnection()\r\n{\r\n\treturn std::make_shared<client_connection>(ioc);\r\n}\r\n\r\nplr_t tcp_server::NextFree()\r\n{\r\n\tfor (plr_t i = 0; i < Players.size(); ++i)\r\n\t\tif (!connections[i])\r\n\t\t\treturn i;\r\n\treturn PLR_BROADCAST;\r\n}\r\n\r\nbool tcp_server::Empty()\r\n{\r\n\tfor (plr_t i = 0; i < Players.size(); ++i)\r\n\t\tif (connections[i])\r\n\t\t\treturn false;\r\n\treturn true;\r\n}\r\n\r\nvoid tcp_server::StartReceive(const scc &con)\r\n{\r\n\tcon->socket.async_receive(\r\n\t    asio::buffer(con->recv_buffer),\r\n\t    std::bind(&tcp_server::HandleReceive, this, con, std::placeholders::_1, std::placeholders::_2));\r\n}\r\n\r\nvoid tcp_server::HandleReceive(const scc &con, const asio::error_code &ec,\r\n    size_t bytesRead)\r\n{\r\n\tif (ec || bytesRead == 0) {\r\n\t\tDropConnection(con);\r\n\t\treturn;\r\n\t}\r\n\tcon->recv_buffer.resize(bytesRead);\r\n\tcon->recv_queue.Write(std::move(con->recv_buffer));\r\n\tcon->recv_buffer.resize(frame_queue::max_frame_size);\r\n\twhile (true) {\r\n\t\ttl::expected<bool, PacketError> ready = con->recv_queue.PacketReady();\r\n\t\tif (!ready.has_value()) {\r\n\t\t\tLog(\"PacketReady: {}\", ready.error().what());\r\n\t\t\tDropConnection(con);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!*ready)\r\n\t\t\tbreak;\r\n\t\ttl::expected<buffer_t, PacketError> pktData = con->recv_queue.ReadPacket();\r\n\t\tif (!pktData.has_value()) {\r\n\t\t\tLog(\"ReadPacket: {}\", pktData.error().what());\r\n\t\t\tDropConnection(con);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\ttl::expected<std::unique_ptr<packet>, PacketError> pkt = pktfty.make_packet(*pktData);\r\n\t\tif (!pkt.has_value()) {\r\n\t\t\tLog(\"make_packet: {}\", pkt.error().what());\r\n\t\t\tif (pkt.error().code() == PacketError::ErrorCode::DecryptionFailed)\r\n\t\t\t\tStartSend(con, pkt.error().code());\r\n\t\t\tDropConnection(con);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (con->plr == PLR_BROADCAST) {\r\n\t\t\ttl::expected<void, PacketError> result = HandleReceiveNewPlayer(con, **pkt);\r\n\t\t\tif (!result.has_value()) {\r\n\t\t\t\tLog(\"HandleReceiveNewPlayer: {}\", result.error().what());\r\n\t\t\t\tDropConnection(con);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tcon->timeout = timeout_active;\r\n\t\t\ttl::expected<void, PacketError> result = HandleReceivePacket(**pkt);\r\n\t\t\tif (!result.has_value()) {\r\n\t\t\t\tLog(\"Network error: {}\", result.error().what());\r\n\t\t\t\tDropConnection(con);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tStartReceive(con);\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_server::HandleReceiveNewPlayer(const scc &con, packet &inPkt)\r\n{\r\n\tauto newplr = NextFree();\r\n\tif (newplr == PLR_BROADCAST)\r\n\t\treturn tl::make_unexpected(ServerError());\r\n\r\n\tif (Empty()) {\r\n\t\ttl::expected<const buffer_t *, PacketError> pktInfo = inPkt.Info();\r\n\t\tif (!pktInfo.has_value())\r\n\t\t\treturn tl::make_unexpected(pktInfo.error());\r\n\t\tgame_init_info = **pktInfo;\r\n\t}\r\n\r\n\tfor (plr_t player = 0; player < Players.size(); player++) {\r\n\t\tif (connections[player]) {\r\n\t\t\ttl::expected<void, PacketError> result\r\n\t\t\t    = pktfty.make_packet<PT_CONNECT>(PLR_MASTER, PLR_BROADCAST, newplr)\r\n\t\t\t          .and_then([&](std::unique_ptr<packet> &&pkt) { return StartSend(connections[player], *pkt); })\r\n\t\t\t          .and_then([&]() { return pktfty.make_packet<PT_CONNECT>(PLR_MASTER, PLR_BROADCAST, player); })\r\n\t\t\t          .and_then([&](std::unique_ptr<packet> &&pkt) { return StartSend(con, *pkt); });\r\n\t\t\tif (!result.has_value())\r\n\t\t\t\treturn result;\r\n\t\t}\r\n\t}\r\n\r\n\ttl::expected<void, PacketError> result\r\n\t    = inPkt.Cookie()\r\n\t          .and_then([&](cookie_t &&cookie) { return pktfty.make_packet<PT_JOIN_ACCEPT>(PLR_MASTER, PLR_BROADCAST, cookie, newplr, game_init_info); })\r\n\t          .and_then([&](std::unique_ptr<packet> &&pkt) { return StartSend(con, *pkt); });\r\n\tif (!result.has_value())\r\n\t\treturn result;\r\n\tcon->plr = newplr;\r\n\tconnections[newplr] = con;\r\n\tcon->timeout = timeout_active;\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_server::HandleReceivePacket(packet &pkt)\r\n{\r\n\treturn SendPacket(pkt);\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_server::SendPacket(packet &pkt)\r\n{\r\n\tif (pkt.Destination() == PLR_BROADCAST) {\r\n\t\tfor (size_t i = 0; i < Players.size(); ++i) {\r\n\t\t\tif (i == pkt.Source() || !connections[i])\r\n\t\t\t\tcontinue;\r\n\t\t\ttl::expected<void, PacketError> result = StartSend(connections[i], pkt);\r\n\t\t\tif (!result.has_value())\r\n\t\t\t\tLogError(\"Failed to send packet {} to player {}: {}\", static_cast<uint8_t>(pkt.Type()), i, result.error().what());\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\tif (pkt.Destination() >= MAX_PLRS)\r\n\t\treturn tl::make_unexpected(ServerError());\r\n\tif (pkt.Destination() == pkt.Source() || !connections[pkt.Destination()])\r\n\t\treturn {};\r\n\treturn StartSend(connections[pkt.Destination()], pkt);\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_server::StartSend(const scc &con, packet &pkt)\r\n{\r\n\treturn StartSend(con, pkt.Data(), 0);\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_server::StartSend(const scc &con, PacketError::ErrorCode errorCode)\r\n{\r\n\tbuffer_t pktData;\r\n\tpktData.push_back(static_cast<unsigned char>(errorCode));\r\n\treturn StartSend(con, pktData, TcpErrorCodeFlags);\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_server::StartSend(const scc &con, buffer_t pktData, uint16_t flags)\r\n{\r\n\ttl::expected<buffer_t, PacketError> frame = frame_queue::MakeFrame(pktData, flags);\r\n\tif (!frame.has_value())\r\n\t\treturn tl::make_unexpected(frame.error());\r\n\tstd::unique_ptr<buffer_t> framePtr = std::make_unique<buffer_t>(*frame);\r\n\tconst asio::mutable_buffer buf = asio::buffer(*framePtr);\r\n\tasio::async_write(con->socket, buf,\r\n\t    [this, con, frame = std::move(framePtr)](const asio::error_code &ec, size_t bytesSent) {\r\n\t\t    HandleSend(con, ec, bytesSent);\r\n\t    });\r\n\treturn {};\r\n}\r\n\r\nvoid tcp_server::HandleSend(const scc &con, const asio::error_code &ec,\r\n    size_t bytesSent)\r\n{\r\n\tif (ec) {\r\n\t\tLog(\"Network error: {}\", ec.message());\r\n\t\tDropConnection(con);\r\n\t}\r\n}\r\n\r\nvoid tcp_server::StartAccept()\r\n{\r\n\tauto nextcon = MakeConnection();\r\n\tacceptor->async_accept(\r\n\t    nextcon->socket,\r\n\t    std::bind(&tcp_server::HandleAccept, this, nextcon, std::placeholders::_1));\r\n}\r\n\r\nvoid tcp_server::HandleAccept(const scc &con, const asio::error_code &ec)\r\n{\r\n\tif (ec) {\r\n\t\tconst PacketError packetError = IoHandlerError(ec.message());\r\n\t\tRaiseIoHandlerError(packetError);\r\n\t\treturn;\r\n\t}\r\n\tif (NextFree() == PLR_BROADCAST) {\r\n\t\tDropConnection(con);\r\n\t} else {\r\n\t\tasio::error_code errorCode;\r\n\t\tconst asio::ip::tcp::no_delay option(true);\r\n\t\tcon->socket.set_option(option, errorCode);\r\n\t\tif (errorCode)\r\n\t\t\tLogError(\"Server error setting socket option: {}\", errorCode.message());\r\n\t\tcon->timeout = timeout_connect;\r\n\t\tStartReceive(con);\r\n\t\tStartTimeout(con);\r\n\t}\r\n\tStartAccept();\r\n}\r\n\r\nvoid tcp_server::StartTimeout(const scc &con)\r\n{\r\n\tcon->timer.expires_after(std::chrono::seconds(1));\r\n\tcon->timer.async_wait(\r\n\t    std::bind(&tcp_server::HandleTimeout, this, con, std::placeholders::_1));\r\n}\r\n\r\nvoid tcp_server::HandleTimeout(const scc &con, const asio::error_code &ec)\r\n{\r\n\tif (ec) {\r\n\t\tDropConnection(con);\r\n\t\treturn;\r\n\t}\r\n\tif (con->timeout > 0)\r\n\t\tcon->timeout -= 1;\r\n\tif (con->timeout <= 0) {\r\n\t\tcon->timeout = 0;\r\n\t\tDropConnection(con);\r\n\t\treturn;\r\n\t}\r\n\tStartTimeout(con);\r\n}\r\n\r\nvoid tcp_server::DropConnection(const scc &con)\r\n{\r\n\tconst plr_t plr = con->plr;\r\n\tcon->timer.cancel();\r\n\tcon->socket.close();\r\n\tif (plr == PLR_BROADCAST) {\r\n\t\treturn;\r\n\t}\r\n\tconnections[plr] = nullptr;\r\n\r\n\ttl::expected<std::unique_ptr<packet>, PacketError> pkt\r\n\t    = pktfty.make_packet<PT_DISCONNECT>(PLR_MASTER, PLR_BROADCAST,\r\n\t        plr, leaveinfo_t::LEAVE_DROP);\r\n\tif (pkt.has_value()) {\r\n\t\tSendPacket(**pkt);\r\n\t} else {\r\n\t\tLogError(\"make_packet<PT_DISCONNECT>: {}\", pkt.error().what());\r\n\t}\r\n}\r\n\r\nvoid tcp_server::RaiseIoHandlerError(const PacketError &error)\r\n{\r\n\tioHandlerResult.emplace(error);\r\n}\r\n\r\ntl::expected<void, PacketError> tcp_server::CheckIoHandlerError()\r\n{\r\n\tif (ioHandlerResult == std::nullopt)\r\n\t\treturn {};\r\n\ttl::expected<void, PacketError> packetError = tl::make_unexpected(*ioHandlerResult);\r\n\tioHandlerResult = std::nullopt;\r\n\treturn packetError;\r\n}\r\n\r\nvoid tcp_server::DisconnectNet(plr_t plr)\r\n{\r\n\tscc &con = connections[plr];\r\n\tif (con == nullptr)\r\n\t\treturn;\r\n\tcon->timer.cancel();\r\n\tcon->socket.close();\r\n\tcon = nullptr;\r\n}\r\n\r\nvoid tcp_server::Close()\r\n{\r\n\tacceptor->close();\r\n}\r\n\r\ntcp_server::~tcp_server()\r\n    = default;\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/tcp_server.h",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <memory>\r\n#include <string>\r\n\r\n// This header must be included before any 3DS code\r\n// because 3DS SDK defines a macro with the same name\r\n// as an fmt template parameter in some versions of fmt.\r\n// See https://github.com/fmtlib/fmt/issues/3632\r\n//\r\n// 3DS uses some custom ASIO code that transitively includes\r\n// the 3DS SDK.\r\n#include <fmt/core.h>\r\n\r\n#include <expected.hpp>\r\n\r\n#include <asio/ts/buffer.hpp>\r\n#include <asio/ts/internet.hpp>\r\n#include <asio/ts/io_context.hpp>\r\n#include <asio/ts/net.hpp>\r\n#include <asio_handle_exception.hpp>\r\n\r\n#include \"dvlnet/abstract_net.h\"\r\n#include \"dvlnet/frame_queue.h\"\r\n#include \"dvlnet/packet.h\"\r\n#include \"multi.h\"\r\n\r\nnamespace devilution::net {\r\n\r\nconstexpr uint16_t TcpErrorCodeFlags = 0x8000;\r\n\r\ninline PacketError ServerError()\r\n{\r\n\treturn PacketError(\"Invalid player ID\");\r\n}\r\n\r\nclass tcp_server {\r\npublic:\r\n\ttcp_server(asio::io_context &ioc, const std::string &bindaddr,\r\n\t    unsigned short port, packet_factory &pktfty);\r\n\tstd::string LocalhostSelf();\r\n\ttl::expected<void, PacketError> CheckIoHandlerError();\r\n\tvoid DisconnectNet(plr_t plr);\r\n\tvoid Close();\r\n\tvirtual ~tcp_server();\r\n\r\nprivate:\r\n\tstatic constexpr int timeout_connect = 30;\r\n\tstatic constexpr int timeout_active = 60;\r\n\r\n\tstruct client_connection {\r\n\t\tframe_queue recv_queue;\r\n\t\tbuffer_t recv_buffer = buffer_t(frame_queue::max_frame_size);\r\n\t\tplr_t plr = PLR_BROADCAST;\r\n\t\tasio::ip::tcp::socket socket;\r\n\t\tasio::steady_timer timer;\r\n\t\tint timeout;\r\n\t\tclient_connection(asio::io_context &ioc)\r\n\t\t    : socket(ioc)\r\n\t\t    , timer(ioc)\r\n\t\t{\r\n\t\t}\r\n\t};\r\n\r\n\ttypedef std::shared_ptr<client_connection> scc;\r\n\r\n\tasio::io_context &ioc;\r\n\tpacket_factory &pktfty;\r\n\tstd::unique_ptr<asio::ip::tcp::acceptor> acceptor;\r\n\tstd::array<scc, MAX_PLRS> connections;\r\n\tbuffer_t game_init_info;\r\n\r\n\tstd::optional<PacketError> ioHandlerResult;\r\n\r\n\tscc MakeConnection();\r\n\tplr_t NextFree();\r\n\tbool Empty();\r\n\tvoid StartAccept();\r\n\tvoid HandleAccept(const scc &con, const asio::error_code &ec);\r\n\tvoid StartReceive(const scc &con);\r\n\tvoid HandleReceive(const scc &con, const asio::error_code &ec, size_t bytesRead);\r\n\ttl::expected<void, PacketError> HandleReceiveNewPlayer(const scc &con, packet &pkt);\r\n\ttl::expected<void, PacketError> HandleReceivePacket(packet &pkt);\r\n\ttl::expected<void, PacketError> SendPacket(packet &pkt);\r\n\ttl::expected<void, PacketError> StartSend(const scc &con, packet &pkt);\r\n\ttl::expected<void, PacketError> StartSend(const scc &con, PacketError::ErrorCode errorCode);\r\n\ttl::expected<void, PacketError> StartSend(const scc &con, buffer_t pktData, uint16_t flags);\r\n\tvoid HandleSend(const scc &con, const asio::error_code &ec, size_t bytesSent);\r\n\tvoid StartTimeout(const scc &con);\r\n\tvoid HandleTimeout(const scc &con, const asio::error_code &ec);\r\n\tvoid DropConnection(const scc &con);\r\n\tvoid RaiseIoHandlerError(const PacketError &error);\r\n};\r\n\r\n} // namespace devilution::net\r\n"
  },
  {
    "path": "Source/dvlnet/zerotier_lwip.cpp",
    "content": "#include \"dvlnet/zerotier_lwip.h\"\r\n\r\n#include <lwip/igmp.h>\r\n#include <lwip/mld6.h>\r\n#include <lwip/sockets.h>\r\n#include <lwip/tcpip.h>\r\n\r\n#include \"dvlnet/zerotier_native.h\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nvoid print_ip6_addr(void *x)\r\n{\r\n\tchar ipstr[INET6_ADDRSTRLEN];\r\n\tauto *in = static_cast<sockaddr_in6 *>(x);\r\n\tlwip_inet_ntop(AF_INET6, &(in->sin6_addr), ipstr, INET6_ADDRSTRLEN);\r\n\tLog(\"ZeroTier: ZTS_EVENT_ADDR_NEW_IP6, addr={}\", ipstr);\r\n}\r\n\r\nvoid zt_ip6setup()\r\n{\r\n\tip6_addr_t mcaddr;\r\n\tmemcpy(mcaddr.addr, dvl_multicast_addr, 16);\r\n\tmcaddr.zone = 0;\r\n\tLOCK_TCPIP_CORE();\r\n\tmld6_joingroup(IP6_ADDR_ANY6, &mcaddr);\r\n\tUNLOCK_TCPIP_CORE();\r\n}\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/zerotier_lwip.h",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nvoid print_ip6_addr(void *x);\r\nvoid zt_ip6setup();\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/zerotier_native.cpp",
    "content": "#include \"dvlnet/zerotier_native.h\"\r\n\r\n#include <atomic>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n#include \"utils/stdcompat/filesystem.hpp\"\r\n#ifdef DVL_HAS_FILESYSTEM\r\n#define DVL_ZT_SYMLINK\r\n#endif\r\n#endif\r\n\r\n#ifdef DVL_ZT_SYMLINK\r\n#include <shlobj.h>\r\n#ifdef PACKET_ENCRYPTION\r\n#include <sodium.h>\r\n#endif\r\n\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n#endif\r\n\r\n#include <ZeroTierSockets.h>\r\n#include <cstdlib>\r\n\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/paths.h\"\r\n\r\n#include \"dvlnet/zerotier_lwip.h\"\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nnamespace {\r\n\r\n// static constexpr uint64_t zt_earth = 0x8056c2e21c000001;\r\nconstexpr uint64_t ZtNetwork = 0xa84ac5c10a7ebb5f;\r\n\r\nstd::atomic_bool zt_network_ready(false);\r\nstd::atomic_bool zt_node_online(false);\r\nstd::atomic_bool zt_joined(false);\r\nstd::atomic_uint zt_peers_ready(0);\r\n\r\nankerl::unordered_dense::map<uint64_t, zts_event_t> ztPeerEvents;\r\n\r\n#ifdef DVL_ZT_SYMLINK\r\nbool HasMultiByteChars(std::string_view path)\r\n{\r\n\treturn c_any_of(path, IsTrailUtf8CodeUnit);\r\n}\r\n\r\n#ifdef PACKET_ENCRYPTION\r\nstd::string ComputeAlternateFolderName(std::string_view path)\r\n{\r\n\tconst size_t hashSize = crypto_generichash_BYTES;\r\n\tunsigned char hash[hashSize];\r\n\r\n\tconst int status = crypto_generichash(hash, hashSize,\r\n\t    reinterpret_cast<const unsigned char *>(path.data()), path.size(),\r\n\t    nullptr, 0);\r\n\r\n\tif (status != 0)\r\n\t\treturn {};\r\n\r\n\tchar buf[hashSize * 2];\r\n\tfor (size_t i = 0; i < hashSize; ++i) {\r\n\t\tBufCopy(&buf[i * 2], AsHexPad2(hash[i]));\r\n\t}\r\n\treturn std::string(buf, hashSize * 2);\r\n}\r\n#else\r\nstd::string ComputeAlternateFolderName(std::string_view path)\r\n{\r\n\treturn {};\r\n}\r\n#endif\r\n\r\nstd::string ToZTCompliantPath(std::string_view configPath)\r\n{\r\n\tif (!HasMultiByteChars(configPath))\r\n\t\treturn std::string(configPath);\r\n\r\n\tchar commonAppDataPath[MAX_PATH];\r\n\tif (!SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, 0, commonAppDataPath))) {\r\n\t\tLogVerbose(\"Failed to retrieve common application data path\");\r\n\t\treturn std::string(configPath);\r\n\t}\r\n\r\n\tstd::error_code err;\r\n\tstd::string alternateConfigPath = StrCat(commonAppDataPath, \"\\\\diasurgical\\\\devilution\");\r\n\tstd::filesystem::create_directories(alternateConfigPath, err);\r\n\tif (err) {\r\n\t\tLogVerbose(\"Failed to create directories in ZT-compliant config path\");\r\n\t\treturn std::string(configPath);\r\n\t}\r\n\r\n\tstd::string alternateFolderName = ComputeAlternateFolderName(configPath);\r\n\tif (alternateFolderName == \"\") {\r\n\t\tLogVerbose(\"Failed to hash config path for ZT\");\r\n\t\treturn std::string(configPath);\r\n\t}\r\n\r\n\tstd::string symlinkPath = StrCat(alternateConfigPath, \"\\\\\", alternateFolderName);\r\n\tbool symlinkExists = std::filesystem::exists(\r\n\t    std::u8string_view(reinterpret_cast<const char8_t *>(symlinkPath.data()), symlinkPath.size()), err);\r\n\tif (err) {\r\n\t\tLogVerbose(\"Failed to determine if symlink for ZT-compliant config path exists\");\r\n\t\treturn std::string(configPath);\r\n\t}\r\n\r\n\tif (!symlinkExists) {\r\n\t\tstd::filesystem::create_directory_symlink(\r\n\t\t    std::u8string_view(reinterpret_cast<const char8_t *>(configPath.data()), configPath.size()),\r\n\t\t    std::u8string_view(reinterpret_cast<const char8_t *>(symlinkPath.data()), symlinkPath.size()),\r\n\t\t    err);\r\n\r\n\t\tif (err) {\r\n\t\t\tLogVerbose(\"Failed to create symlink for ZT-compliant config path\");\r\n\t\t\treturn std::string(configPath);\r\n\t\t}\r\n\t}\r\n\r\n\treturn StrCat(symlinkPath, \"\\\\\");\r\n}\r\n#endif\r\n\r\nvoid Callback(void *ptr)\r\n{\r\n\tzts_event_msg_t *msg = reinterpret_cast<zts_event_msg_t *>(ptr);\r\n\r\n\tswitch (msg->event_code) {\r\n\tcase ZTS_EVENT_NODE_ONLINE:\r\n\t\tLog(\"ZeroTier: ZTS_EVENT_NODE_ONLINE, nodeId={:x}\", (unsigned long long)msg->node->node_id);\r\n\t\tzt_node_online = true;\r\n\t\tif (!zt_joined) {\r\n\t\t\tzts_net_join(ZtNetwork);\r\n\t\t\tzt_joined = true;\r\n\t\t}\r\n\t\tbreak;\r\n\r\n\tcase ZTS_EVENT_NODE_OFFLINE:\r\n\t\tLog(\"ZeroTier: ZTS_EVENT_NODE_OFFLINE\");\r\n\t\tzt_node_online = false;\r\n\t\tbreak;\r\n\r\n\tcase ZTS_EVENT_NETWORK_READY_IP6:\r\n\t\tLog(\"ZeroTier: ZTS_EVENT_NETWORK_READY_IP6, networkId={:x}\", (unsigned long long)msg->network->net_id);\r\n\t\tzt_ip6setup();\r\n\t\tzt_network_ready = true;\r\n\t\tzt_peers_ready = SDL_GetTicks();\r\n\t\tbreak;\r\n\r\n\tcase ZTS_EVENT_ADDR_ADDED_IP6:\r\n\t\tprint_ip6_addr(&(msg->addr->addr));\r\n\t\tbreak;\r\n\r\n\tcase ZTS_EVENT_PEER_DIRECT:\r\n\tcase ZTS_EVENT_PEER_RELAY:\r\n\t\tztPeerEvents[msg->peer->peer_id] = static_cast<zts_event_t>(msg->event_code);\r\n\t\tif (!zerotier_peers_ready())\r\n\t\t\tzt_peers_ready = SDL_GetTicks();\r\n\t\tbreak;\r\n\r\n\tcase ZTS_EVENT_PEER_PATH_DEAD:\r\n\t\tztPeerEvents.erase(msg->peer->peer_id);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nbool zerotier_network_ready()\r\n{\r\n\treturn zt_network_ready && zt_node_online;\r\n}\r\n\r\nbool zerotier_peers_ready()\r\n{\r\n\treturn SDL_GetTicks() - zt_peers_ready >= 5000;\r\n}\r\n\r\nvoid zerotier_network_start()\r\n{\r\n\tstd::string configPath = paths::ConfigPath();\r\n#ifdef DVL_ZT_SYMLINK\r\n\tconfigPath = ToZTCompliantPath(configPath);\r\n#endif\r\n\tstd::string ztpath = configPath + \"zerotier\";\r\n\tzts_init_from_storage(ztpath.c_str());\r\n\tzts_init_set_event_handler(&Callback);\r\n\tzts_node_start();\r\n}\r\n\r\nbool zerotier_is_relayed(uint64_t mac)\r\n{\r\n\tbool isRelayed = true;\r\n\tif (zts_core_lock_obtain() != ZTS_ERR_OK)\r\n\t\treturn isRelayed;\r\n\tzts_peer_info_t peerInfo;\r\n\tif (zts_core_query_peer_info(ZtNetwork, mac, &peerInfo) == ZTS_ERR_OK) {\r\n\t\tauto peerEvent = ztPeerEvents.find(peerInfo.peer_id);\r\n\t\tif (peerEvent != ztPeerEvents.end())\r\n\t\t\tisRelayed = (peerEvent->second == ZTS_EVENT_PEER_RELAY);\r\n\t}\r\n\tzts_core_lock_release();\r\n\treturn isRelayed;\r\n}\r\n\r\nint zerotier_latency(uint64_t mac)\r\n{\r\n\tint latency = -1;\r\n\tif (zts_core_lock_obtain() != ZTS_ERR_OK)\r\n\t\treturn latency;\r\n\tzts_peer_info_t peerInfo;\r\n\tif (zts_core_query_peer_info(ZtNetwork, mac, &peerInfo) == ZTS_ERR_OK)\r\n\t\tlatency = peerInfo.latency;\r\n\tzts_core_lock_release();\r\n\treturn latency;\r\n}\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/dvlnet/zerotier_native.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\nnamespace net {\r\n\r\nbool zerotier_network_ready();\r\nbool zerotier_peers_ready();\r\nvoid zerotier_network_start();\r\nbool zerotier_is_relayed(uint64_t mac);\r\nint zerotier_latency(uint64_t mac);\r\n\r\n// NOTE: We have patched our libzt to have the corresponding multicast\r\n// MAC hardcoded, since libzt is still missing the proper handling.\r\nconst unsigned char dvl_multicast_addr[16] = {\r\n\t0xff, 0x0e, 0xa8, 0xa9, 0xb6, 0x11, 0x60, 0xce,\r\n\t0x04, 0x12, 0xfd, 0x73, 0x37, 0x86, 0x6f, 0xb7\r\n};\r\n\r\n} // namespace net\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/effects.cpp",
    "content": "/**\r\n * @file effects.cpp\r\n *\r\n * Implementation of functions for loading and playing sounds.\r\n */\r\n#include \"effects.h\"\r\n\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#include <expected.hpp>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/sound.h\"\r\n#include \"engine/sound_defs.hpp\"\r\n#include \"engine/sound_position.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"options.h\"\r\n#include \"player.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nint sfxdelay;\r\nSfxID sfxdnum = SfxID::None;\r\n\r\nnamespace {\r\n\r\n#ifndef DISABLE_STREAMING_SOUNDS\r\nconstexpr bool AllowStreaming = true;\r\n#else\r\nconstexpr bool AllowStreaming = false;\r\n#endif\r\n\r\n/** Specifies the sound file and the playback state of the current sound effect. */\r\nTSFX *sgpStreamSFX = nullptr;\r\n\r\n/** List of all sounds, except monsters and music */\r\nstd::vector<TSFX> sgSFX;\r\n\r\nvoid StreamPlay(TSFX *pSFX, int lVolume, int lPan)\r\n{\r\n\tassert(pSFX);\r\n\tassert(pSFX->bFlags & sfx_STREAM);\r\n\tstream_stop();\r\n\r\n\tif (lVolume >= VOLUME_MIN) {\r\n\t\tif (lVolume > VOLUME_MAX)\r\n\t\t\tlVolume = VOLUME_MAX;\r\n\t\tif (pSFX->pSnd == nullptr)\r\n\t\t\tpSFX->pSnd = sound_file_load(pSFX->pszName.c_str(), AllowStreaming);\r\n\t\tif (pSFX->pSnd->DSB.IsLoaded())\r\n\t\t\tpSFX->pSnd->DSB.PlayWithVolumeAndPan(lVolume, sound_get_or_set_sound_volume(1), lPan);\r\n\t\tsgpStreamSFX = pSFX;\r\n\t}\r\n}\r\n\r\nvoid StreamUpdate()\r\n{\r\n\tif (sgpStreamSFX != nullptr && !sgpStreamSFX->pSnd->isPlaying()) {\r\n\t\tstream_stop();\r\n\t}\r\n}\r\n\r\nvoid PlaySfxPriv(TSFX *pSFX, bool loc, Point position)\r\n{\r\n\tif (MyPlayer->pLvlLoad != 0 && gbIsMultiplayer) {\r\n\t\treturn;\r\n\t}\r\n\tif (!gbSndInited || !gbSoundOn || gbBufferMsgs != 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ((pSFX->bFlags & (sfx_STREAM | sfx_MISC)) == 0 && pSFX->pSnd != nullptr && pSFX->pSnd->isPlaying()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tint lVolume = 0;\r\n\tint lPan = 0;\r\n\tif (loc && !CalculateSoundPosition(position, &lVolume, &lPan)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ((pSFX->bFlags & sfx_STREAM) != 0) {\r\n\t\tStreamPlay(pSFX, lVolume, lPan);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (pSFX->pSnd == nullptr)\r\n\t\tpSFX->pSnd = sound_file_load(pSFX->pszName.c_str());\r\n\r\n\tif (pSFX->pSnd == nullptr || !pSFX->pSnd->DSB.IsLoaded())\r\n\t\treturn;\r\n\r\n\tconst auto id = static_cast<SfxID>(pSFX - sgSFX.data());\r\n\tconst bool useCuesVolume = (id >= SfxID::AccessibilityWeapon && id <= SfxID::AccessibilityInteract);\r\n\tconst int userVolume = useCuesVolume ? *GetOptions().Audio.audioCuesVolume : *GetOptions().Audio.soundVolume;\r\n\tsnd_play_snd(pSFX->pSnd.get(), lVolume, lPan, userVolume);\r\n}\r\n\r\nSfxID RndSFX(SfxID psfx)\r\n{\r\n\tswitch (psfx) {\r\n\tcase SfxID::Warrior69:\r\n\tcase SfxID::Sorceror69:\r\n\tcase SfxID::Rogue69:\r\n\tcase SfxID::Monk69:\r\n\tcase SfxID::Swing:\r\n\tcase SfxID::SpellAcid:\r\n\tcase SfxID::OperateShrine:\r\n\t\treturn PickRandomlyAmong({ psfx, static_cast<SfxID>(static_cast<int16_t>(psfx) + 1) });\r\n\tcase SfxID::Warrior14:\r\n\tcase SfxID::Warrior15:\r\n\tcase SfxID::Warrior16:\r\n\tcase SfxID::Warrior2:\r\n\tcase SfxID::Rogue14:\r\n\tcase SfxID::Sorceror14:\r\n\tcase SfxID::Monk14:\r\n\t\treturn PickRandomlyAmong({ psfx, static_cast<SfxID>(static_cast<int16_t>(psfx) + 1), static_cast<SfxID>(static_cast<int16_t>(psfx) + 2) });\r\n\tdefault:\r\n\t\treturn psfx;\r\n\t}\r\n}\r\n\r\ntl::expected<sfx_flag, std::string> ParseSfxFlag(std::string_view value)\r\n{\r\n\tif (value == \"Stream\") return sfx_STREAM;\r\n\tif (value == \"Misc\") return sfx_MISC;\r\n\tif (value == \"Ui\") return sfx_UI;\r\n\tif (value == \"Monk\") return sfx_MONK;\r\n\tif (value == \"Rogue\") return sfx_ROGUE;\r\n\tif (value == \"Warrior\") return sfx_WARRIOR;\r\n\tif (value == \"Sorcerer\") return sfx_SORCERER;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\nvoid LoadEffectsData()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\sound\\\\effects.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tsgSFX.clear();\r\n\tsgSFX.reserve(dataFile.numRecords());\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tTSFX &item = sgSFX.emplace_back();\r\n\t\treader.advance(); // Skip the first column (effect ID).\r\n\t\treader.readEnumList(\"flags\", item.bFlags, ParseSfxFlag);\r\n\t\treader.readString(\"path\", item.pszName);\r\n\t}\r\n\tsgSFX.shrink_to_fit();\r\n}\r\n\r\nvoid PrivSoundInit(uint8_t bLoadMask)\r\n{\r\n\tif (!gbSndInited) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (sgSFX.empty()) LoadEffectsData();\r\n\r\n\tfor (auto &sfx : sgSFX) {\r\n\t\tif (sfx.bFlags == 0 || sfx.pSnd != nullptr) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif ((sfx.bFlags & sfx_STREAM) != 0) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif ((sfx.bFlags & bLoadMask) == 0) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tsfx.pSnd = sound_file_load(sfx.pszName.c_str());\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nbool effect_is_playing(SfxID nSFX)\r\n{\r\n\tif (!gbSndInited) return false;\r\n\r\n\tTSFX *sfx = &sgSFX[static_cast<int16_t>(nSFX)];\r\n\tif (sfx->pSnd != nullptr)\r\n\t\treturn sfx->pSnd->isPlaying();\r\n\r\n\tif ((sfx->bFlags & sfx_STREAM) != 0)\r\n\t\treturn sfx == sgpStreamSFX;\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid stream_stop()\r\n{\r\n\tif (sgpStreamSFX != nullptr) {\r\n\t\tsgpStreamSFX->pSnd = nullptr;\r\n\t\tsgpStreamSFX = nullptr;\r\n\t}\r\n}\r\n\r\nvoid PlaySFX(SfxID psfx)\r\n{\r\n\tpsfx = RndSFX(psfx);\r\n\r\n\tif (!gbSndInited) return;\r\n\r\n\tPlaySfxPriv(&sgSFX[static_cast<int16_t>(psfx)], false, { 0, 0 });\r\n}\r\n\r\nvoid PlaySfxLoc(SfxID psfx, Point position, bool randomizeByCategory)\r\n{\r\n\tif (randomizeByCategory) {\r\n\t\tpsfx = RndSFX(psfx);\r\n\t}\r\n\r\n\tif (!gbSndInited) return;\r\n\r\n\tif (IsAnyOf(psfx, SfxID::Walk, SfxID::ShootBow, SfxID::CastSpell, SfxID::Swing)) {\r\n\t\tTSnd *pSnd = sgSFX[static_cast<int16_t>(psfx)].pSnd.get();\r\n\t\tif (pSnd != nullptr)\r\n\t\t\tpSnd->start_tc = 0;\r\n\t}\r\n\r\n\tPlaySfxPriv(&sgSFX[static_cast<int16_t>(psfx)], true, position);\r\n}\r\n\r\nvoid sound_stop()\r\n{\r\n\tif (!gbSndInited)\r\n\t\treturn;\r\n\tClearDuplicateSounds();\r\n\tfor (auto &sfx : sgSFX) {\r\n\t\tif (sfx.pSnd != nullptr && sfx.pSnd->DSB.IsLoaded()) {\r\n\t\t\tsfx.pSnd->DSB.Stop();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid sound_update()\r\n{\r\n\tif (!gbSndInited) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tStreamUpdate();\r\n}\r\n\r\nvoid effects_cleanup_sfx(bool fullUnload)\r\n{\r\n\tsound_stop();\r\n\r\n\tif (fullUnload) {\r\n\t\tsgSFX.clear();\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (auto &sfx : sgSFX)\r\n\t\tsfx.pSnd = nullptr;\r\n}\r\n\r\nvoid sound_init()\r\n{\r\n\tuint8_t mask = sfx_MISC;\r\n\tif (gbIsMultiplayer) {\r\n\t\tmask |= (sfx_WARRIOR | sfx_MONK);\r\n\t\tif (!gbIsSpawn)\r\n\t\t\tmask |= (sfx_ROGUE | sfx_SORCERER);\r\n\t} else {\r\n\t\tswitch (MyPlayer->_pClass) {\r\n\t\tcase HeroClass::Warrior:\r\n\t\tcase HeroClass::Barbarian:\r\n\t\t\tmask |= sfx_WARRIOR;\r\n\t\t\tbreak;\r\n\t\tcase HeroClass::Rogue:\r\n\t\tcase HeroClass::Bard:\r\n\t\t\tmask |= sfx_ROGUE;\r\n\t\t\tbreak;\r\n\t\tcase HeroClass::Sorcerer:\r\n\t\t\tmask |= sfx_SORCERER;\r\n\t\t\tbreak;\r\n\t\tcase HeroClass::Monk:\r\n\t\t\tmask |= sfx_MONK;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tif (static_cast<size_t>(MyPlayer->_pClass) < GetNumPlayerClasses()) {\r\n\t\t\t\t// this is a custom class, so we need to add init sounds, since we can't determine which ones will be used by it\r\n\t\t\t\tmask |= (sfx_WARRIOR | sfx_MONK);\r\n\t\t\t\tif (!gbIsSpawn)\r\n\t\t\t\t\tmask |= (sfx_ROGUE | sfx_SORCERER);\r\n\t\t\t} else {\r\n\t\t\t\tapp_fatal(\"effects:1\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tPrivSoundInit(mask);\r\n}\r\n\r\nvoid ui_sound_init()\r\n{\r\n\tPrivSoundInit(sfx_UI);\r\n}\r\n\r\nvoid effects_play_sound(SfxID id)\r\n{\r\n\tif (!gbSndInited || !gbSoundOn) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tTSFX &sfx = sgSFX[static_cast<int16_t>(id)];\r\n\tif (sfx.pSnd != nullptr && !sfx.pSnd->isPlaying()) {\r\n\t\tsnd_play_snd(sfx.pSnd.get(), 0, 0, *GetOptions().Audio.soundVolume);\r\n\t}\r\n}\r\n\r\nint GetSFXLength(SfxID nSFX)\r\n{\r\n\tTSFX &sfx = sgSFX[static_cast<int16_t>(nSFX)];\r\n\tif (sfx.pSnd == nullptr)\r\n\t\tsfx.pSnd = sound_file_load(sfx.pszName.c_str(),\r\n\t\t    /*stream=*/AllowStreaming && (sfx.bFlags & sfx_STREAM) != 0);\r\n\treturn sfx.pSnd->DSB.GetLength();\r\n}\r\n\r\ntl::expected<HeroSpeech, std::string> ParseHeroSpeech(std::string_view value)\r\n{\r\n\tconst std::optional<HeroSpeech> enumValueOpt = magic_enum::enum_cast<HeroSpeech>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value.\");\r\n}\r\n\r\ntl::expected<SfxID, std::string> ParseSfxId(std::string_view value)\r\n{\r\n\tconst std::optional<SfxID> enumValueOpt = magic_enum::enum_cast<SfxID>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value.\");\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/effects.h",
    "content": "/**\r\n * @file effects.h\r\n *\r\n * Interface of functions for loading and playing sounds.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <memory>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/sound.h\"\r\n#include \"sound_effect_enums.h\"\r\n\r\nnamespace devilution {\r\n\r\nstruct TSFX {\r\n\tuint8_t bFlags;\r\n\tstd::string pszName;\r\n\tstd::unique_ptr<TSnd> pSnd;\r\n};\r\n\r\nextern int sfxdelay;\r\nextern SfxID sfxdnum;\r\n\r\nbool effect_is_playing(SfxID nSFX);\r\nvoid stream_stop();\r\nvoid PlaySFX(SfxID psfx);\r\nvoid PlaySfxLoc(SfxID psfx, Point position, bool randomizeByCategory = true);\r\nvoid sound_stop();\r\nvoid sound_update();\r\nvoid effects_cleanup_sfx(bool fullUnload = true);\r\nvoid sound_init();\r\nvoid ui_sound_init();\r\nvoid effects_play_sound(SfxID);\r\nint GetSFXLength(SfxID nSFX);\r\n\r\ntl::expected<HeroSpeech, std::string> ParseHeroSpeech(std::string_view value);\r\ntl::expected<SfxID, std::string> ParseSfxId(std::string_view value);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/effects_stubs.cpp",
    "content": "// Stubbed implementations of effects for the NOSOUND mode.\r\n#include \"effects.h\"\r\n\r\n#include <expected.hpp>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"engine/random.hpp\"\r\n\r\nnamespace devilution {\r\nint sfxdelay;\r\nSfxID sfxdnum;\r\n\r\nbool effect_is_playing(SfxID nSFX) { return false; }\r\nvoid stream_stop() { }\r\nvoid PlaySFX(SfxID psfx)\r\n{\r\n\tswitch (psfx) {\r\n\tcase SfxID::Warrior69:\r\n\tcase SfxID::Sorceror69:\r\n\tcase SfxID::Rogue69:\r\n\tcase SfxID::Monk69:\r\n\tcase SfxID::Swing:\r\n\tcase SfxID::SpellAcid:\r\n\tcase SfxID::OperateShrine:\r\n\tcase SfxID::Warrior14:\r\n\tcase SfxID::Warrior15:\r\n\tcase SfxID::Warrior16:\r\n\tcase SfxID::Warrior2:\r\n\tcase SfxID::Rogue14:\r\n\tcase SfxID::Sorceror14:\r\n\tcase SfxID::Monk14:\r\n\t\tAdvanceRndSeed();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\nvoid PlaySfxLoc(SfxID psfx, Point position, bool randomizeByCategory)\r\n{\r\n\tif (!randomizeByCategory)\r\n\t\treturn;\r\n\r\n\tPlaySFX(psfx);\r\n}\r\nvoid sound_stop() { }\r\nvoid sound_update() { }\r\nvoid effects_cleanup_sfx(bool fullUnload) { }\r\nvoid sound_init() { }\r\nvoid ui_sound_init() { }\r\nvoid effects_play_sound(SfxID id) { }\r\nint GetSFXLength(SfxID nSFX) { return 0; }\r\n\r\ntl::expected<HeroSpeech, std::string> ParseHeroSpeech(std::string_view value)\r\n{\r\n\tconst std::optional<HeroSpeech> enumValueOpt = magic_enum::enum_cast<HeroSpeech>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value.\");\r\n}\r\n\r\ntl::expected<SfxID, std::string> ParseSfxId(std::string_view value)\r\n{\r\n\tconst std::optional<SfxID> enumValueOpt = magic_enum::enum_cast<SfxID>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value.\");\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/encrypt.cpp",
    "content": "/**\r\n * @file encrypt.cpp\r\n *\r\n * Implementation of functions for compression and decompressing MPQ data.\r\n */\r\n#include <array>\r\n#include <cctype>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n\r\n#include <pkware.h>\r\n\r\n#include \"encrypt.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct TDataInfo {\r\n\tstd::byte *srcData;\r\n\tuint32_t srcOffset;\r\n\tuint32_t srcSize;\r\n\tstd::byte *destData;\r\n\tuint32_t destOffset;\r\n\tsize_t destSize;\r\n\tbool error;\r\n};\r\n\r\nunsigned int PkwareBufferRead(char *buf, unsigned int *size, void *param) // NOLINT(readability-non-const-parameter)\r\n{\r\n\tauto *pInfo = reinterpret_cast<TDataInfo *>(param);\r\n\r\n\tuint32_t sSize;\r\n\tif (*size >= pInfo->srcSize - pInfo->srcOffset) {\r\n\t\tsSize = pInfo->srcSize - pInfo->srcOffset;\r\n\t} else {\r\n\t\tsSize = *size;\r\n\t}\r\n\r\n\tmemcpy(buf, pInfo->srcData + pInfo->srcOffset, sSize);\r\n\tpInfo->srcOffset += sSize;\r\n\r\n\treturn sSize;\r\n}\r\n\r\nvoid PkwareBufferWrite(char *buf, unsigned int *size, void *param) // NOLINT(readability-non-const-parameter)\r\n{\r\n\tauto *pInfo = reinterpret_cast<TDataInfo *>(param);\r\n\r\n\tpInfo->error = pInfo->error || pInfo->destOffset + *size > pInfo->destSize;\r\n\tif (pInfo->error) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tmemcpy(pInfo->destData + pInfo->destOffset, buf, *size);\r\n\tpInfo->destOffset += *size;\r\n}\r\n\r\n} // namespace\r\n\r\nuint32_t PkwareCompress(std::byte *srcData, uint32_t size)\r\n{\r\n\tconst std::unique_ptr<char[]> ptr = std::make_unique<char[]>(CMP_BUFFER_SIZE);\r\n\r\n\tunsigned destSize = 2 * size;\r\n\tif (destSize < 2 * 4096)\r\n\t\tdestSize = 2 * 4096;\r\n\r\n\tconst std::unique_ptr<std::byte[]> destData { new std::byte[destSize] };\r\n\r\n\tTDataInfo param;\r\n\tparam.srcData = srcData;\r\n\tparam.srcOffset = 0;\r\n\tparam.srcSize = size;\r\n\tparam.destData = destData.get();\r\n\tparam.destOffset = 0;\r\n\tparam.destSize = destSize;\r\n\tparam.error = false;\r\n\r\n\tunsigned type = 0;\r\n\tunsigned dsize = 4096;\r\n\timplode(PkwareBufferRead, PkwareBufferWrite, ptr.get(), &param, &type, &dsize);\r\n\r\n\tif (param.destOffset < size) {\r\n\t\tmemcpy(srcData, destData.get(), param.destOffset);\r\n\t\tsize = param.destOffset;\r\n\t}\r\n\r\n\treturn size;\r\n}\r\n\r\nuint32_t PkwareDecompress(std::byte *inBuff, uint32_t recvSize, size_t maxBytes)\r\n{\r\n\tconst std::unique_ptr<char[]> ptr = std::make_unique<char[]>(CMP_BUFFER_SIZE);\r\n\tconst std::unique_ptr<std::byte[]> outBuff { new std::byte[maxBytes] };\r\n\r\n\tTDataInfo info;\r\n\tinfo.srcData = inBuff;\r\n\tinfo.srcOffset = 0;\r\n\tinfo.srcSize = recvSize;\r\n\tinfo.destData = outBuff.get();\r\n\tinfo.destOffset = 0;\r\n\tinfo.destSize = maxBytes;\r\n\tinfo.error = false;\r\n\r\n\texplode(PkwareBufferRead, PkwareBufferWrite, ptr.get(), &info);\r\n\tif (info.error) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tmemcpy(inBuff, outBuff.get(), info.destOffset);\r\n\treturn info.destOffset;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/encrypt.h",
    "content": "/**\r\n * @file encrypt.h\r\n *\r\n * Interface of functions for compression and decompressing MPQ data.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nuint32_t PkwareCompress(std::byte *srcData, uint32_t size);\r\nuint32_t PkwareDecompress(std::byte *inBuff, uint32_t recvSize, size_t maxBytes);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/actor_position.cpp",
    "content": "#include \"actor_position.hpp\"\r\n\r\n#include <array>\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nenum class VelocityToUse : uint8_t {\r\n\tNone,\r\n\tFull,\r\n\tNegativeFull,\r\n\tHalf,\r\n\tNegativeHalf,\r\n\tQuarter,\r\n\tNegativeQuarter,\r\n};\r\n\r\nstruct RoundedWalkVelocity {\r\n\tint16_t quarter;\r\n\tint16_t half;\r\n\tint16_t full;\r\n\r\n\tint16_t getVelocity(VelocityToUse velocityToUse) const\r\n\t{\r\n\t\tswitch (velocityToUse) {\r\n\t\tcase VelocityToUse::Quarter:\r\n\t\t\treturn quarter;\r\n\t\tcase VelocityToUse::NegativeQuarter:\r\n\t\t\treturn -quarter;\r\n\t\tcase VelocityToUse::Half:\r\n\t\t\treturn half;\r\n\t\tcase VelocityToUse::NegativeHalf:\r\n\t\t\treturn -half;\r\n\t\tcase VelocityToUse::Full:\r\n\t\t\treturn full;\r\n\t\tcase VelocityToUse::NegativeFull:\r\n\t\t\treturn -full;\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n};\r\n\r\n/** @brief Maps from walk animation length to monster velocity (longer/slower animation means less velocity). */\r\nconstexpr RoundedWalkVelocity WalkVelocityForFrames[24] = {\r\n\t// clang-format off\r\n\t// Quarter, Half, Full\r\n\t{ 256, 512, 1024 },\r\n\t{ 128, 256,  512 },\r\n\t{  85, 170,  341 },\r\n\t{  64, 128,  256 },\r\n\t{  51, 102,  204 },\r\n\t{  42,  85,  170 },\r\n\t{  36,  73,  146 },\r\n\t{  32,  64,  128 },\r\n\t{  28,  56,  113 },\r\n\t{  26,  51,  102 },\r\n\t{  23,  46,   93 },\r\n\t{  21,  42,   85 },\r\n\t{  19,  39,   78 },\r\n\t{  18,  36,   73 },\r\n\t{  17,  34,   68 },\r\n\t{  16,  32,   64 },\r\n\t{  15,  30,   60 },\r\n\t{  14,  28,   57 },\r\n\t{  13,  26,   54 },\r\n\t{  12,  25,   51 },\r\n\t{  12,  24,   48 },\r\n\t{  11,  23,   46 },\r\n\t{  11,  22,   44 },\r\n\t{  10,  21,   42 }\r\n\t// clang-format on\r\n};\r\n\r\nstruct WalkParameter {\r\n\tVelocityToUse VelocityX;\r\n\tVelocityToUse VelocityY;\r\n\tDisplacementOf<int16_t> getVelocity(int8_t numberOfFrames) const\r\n\t{\r\n\t\tconst RoundedWalkVelocity &walkVelocity = WalkVelocityForFrames[numberOfFrames - 1];\r\n\t\tauto velocity = DisplacementOf<int16_t> {\r\n\t\t\twalkVelocity.getVelocity(VelocityX),\r\n\t\t\twalkVelocity.getVelocity(VelocityY),\r\n\t\t};\r\n\t\treturn velocity;\r\n\t}\r\n};\r\n\r\nconstexpr std::array<const WalkParameter, 8> WalkParameters { {\r\n\t// clang-format off\r\n\t// Direction      VelocityX,                   VelocityY\r\n\t{ /* South     */ VelocityToUse::None,         VelocityToUse::Half },\r\n\t{ /* SouthWest */ VelocityToUse::NegativeHalf, VelocityToUse::Quarter },\r\n\t{ /* West      */ VelocityToUse::NegativeFull, VelocityToUse::None },\r\n\t{ /* NorthWest */ VelocityToUse::NegativeHalf, VelocityToUse::NegativeQuarter },\r\n\t{ /* North     */ VelocityToUse::None,         VelocityToUse::NegativeHalf },\r\n\t{ /* NorthEast */ VelocityToUse::Half,         VelocityToUse::NegativeQuarter },\r\n\t{ /* East      */ VelocityToUse::Full,         VelocityToUse::None },\r\n\t{ /* SouthEast */ VelocityToUse::Half,         VelocityToUse::Quarter }\r\n\t// clang-format on\r\n} };\r\n\r\n} // namespace\r\n\r\nDisplacementOf<int8_t> ActorPosition::CalculateWalkingOffset(Direction dir, const AnimationInfo &animInfo) const\r\n{\r\n\tconst DisplacementOf<int16_t> offset = CalculateWalkingOffsetShifted4(dir, animInfo);\r\n\treturn { static_cast<int8_t>(offset.deltaX >> 4), static_cast<int8_t>(offset.deltaY >> 4) };\r\n}\r\n\r\nDisplacementOf<int16_t> ActorPosition::CalculateWalkingOffsetShifted4(Direction dir, const AnimationInfo &animInfo) const\r\n{\r\n\tconst int16_t velocityProgress = static_cast<int16_t>(animInfo.getAnimationProgress()) * animInfo.numberOfFrames / AnimationInfo::baseValueFraction;\r\n\tconst WalkParameter &walkParameter = WalkParameters[static_cast<size_t>(dir)];\r\n\tconst DisplacementOf<int16_t> velocity = walkParameter.getVelocity(animInfo.numberOfFrames);\r\n\tDisplacementOf<int16_t> offset = (velocity * velocityProgress);\r\n\treturn offset;\r\n}\r\n\r\nDisplacementOf<int16_t> ActorPosition::CalculateWalkingOffsetShifted8(Direction dir, const AnimationInfo &animInfo) const\r\n{\r\n\tDisplacementOf<int16_t> offset = CalculateWalkingOffsetShifted4(dir, animInfo);\r\n\toffset.deltaX <<= 4;\r\n\toffset.deltaY <<= 4;\r\n\treturn offset;\r\n}\r\n\r\nDisplacementOf<int16_t> ActorPosition::GetWalkingVelocityShifted4(Direction dir, const AnimationInfo &animInfo) const\r\n{\r\n\tconst WalkParameter &walkParameter = WalkParameters[static_cast<size_t>(dir)];\r\n\treturn walkParameter.getVelocity(animInfo.numberOfFrames);\r\n}\r\n\r\nDisplacementOf<int16_t> ActorPosition::GetWalkingVelocityShifted8(Direction dir, const AnimationInfo &animInfo) const\r\n{\r\n\tDisplacementOf<int16_t> velocity = GetWalkingVelocityShifted4(dir, animInfo);\r\n\tvelocity.deltaX <<= 4;\r\n\tvelocity.deltaY <<= 4;\r\n\treturn velocity;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/actor_position.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstruct ActorPosition {\r\n\tWorldTilePosition tile;\r\n\t/** Future tile position. Set at start of walking animation. */\r\n\tWorldTilePosition future;\r\n\t/** Tile position of player. Set via network on player input. */\r\n\tWorldTilePosition last;\r\n\t/** Most recent position in dPlayer. */\r\n\tWorldTilePosition old;\r\n\t/** Used for referring to position of player when finishing moving one tile (also used to define target coordinates for spells and ranged attacks) */\r\n\tWorldTilePosition temp;\r\n\r\n\t/** @brief Calculates the offset for the walking animation. */\r\n\tDisplacementOf<int8_t> CalculateWalkingOffset(Direction dir, const AnimationInfo &animInfo) const;\r\n\t/** @brief Calculates the offset for the walking animation. */\r\n\tDisplacementOf<int16_t> CalculateWalkingOffsetShifted4(Direction dir, const AnimationInfo &animInfo) const;\r\n\t/** @brief Calculates the offset for the walking animation. */\r\n\tDisplacementOf<int16_t> CalculateWalkingOffsetShifted8(Direction dir, const AnimationInfo &animInfo) const;\r\n\t/** @brief Returns Pixel velocity while walking. */\r\n\tDisplacementOf<int16_t> GetWalkingVelocityShifted4(Direction dir, const AnimationInfo &animInfo) const;\r\n\t/** @brief Returns Pixel velocity while walking. */\r\n\tDisplacementOf<int16_t> GetWalkingVelocityShifted8(Direction dir, const AnimationInfo &animInfo) const;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/animationinfo.cpp",
    "content": "/**\r\n * @file animationinfo.cpp\r\n *\r\n * Contains the core animation information and related logic\r\n */\r\n\r\n#include \"animationinfo.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n\r\n#include \"appfat.h\"\r\n#include \"nthread.h\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nint8_t AnimationInfo::getFrameToUseForRendering() const\r\n{\r\n\t// Normal logic is used,\r\n\t// - if no frame-skipping is required and so we have exactly one Animationframe per game tick\r\n\t// or\r\n\t// - if we load from a savegame where the new variables are not stored (we don't want to break savegame compatibility because of smoother rendering of one animation)\r\n\tif (relevantFramesForDistributing_ <= 0)\r\n\t\treturn std::max<int8_t>(0, currentFrame);\r\n\r\n\tif (currentFrame >= relevantFramesForDistributing_)\r\n\t\treturn currentFrame;\r\n\r\n\tint16_t ticksSinceSequenceStarted = ticksSinceSequenceStarted_;\r\n\tif (ticksSinceSequenceStarted_ < 0) {\r\n\t\tticksSinceSequenceStarted = 0;\r\n\t\tLog(\"getFrameToUseForRendering: Invalid ticksSinceSequenceStarted_ {}\", ticksSinceSequenceStarted_);\r\n\t}\r\n\r\n\t// we don't use the processed game ticks alone but also the fraction of the next game tick (if a rendering happens between game ticks). This helps to smooth the animations.\r\n\tconst int32_t totalTicksForCurrentAnimationSequence = getProgressToNextGameTick() + ticksSinceSequenceStarted;\r\n\r\n\tint8_t absoluteAnimationFrame = static_cast<int8_t>(totalTicksForCurrentAnimationSequence * tickModifier_ / baseValueFraction / baseValueFraction);\r\n\tif (skippedFramesFromPreviousAnimation_ > 0) {\r\n\t\t// absoluteAnimationFrames contains also the Frames from the previous Animation, so if we want to get the current Frame we have to remove them\r\n\t\tabsoluteAnimationFrame -= skippedFramesFromPreviousAnimation_;\r\n\t\tif (absoluteAnimationFrame < 0) {\r\n\t\t\t// We still display the remains of the previous Animation\r\n\t\t\tabsoluteAnimationFrame = numberOfFrames + absoluteAnimationFrame;\r\n\t\t}\r\n\t} else if (absoluteAnimationFrame >= relevantFramesForDistributing_) {\r\n\t\t// this can happen if we are at the last frame and the next game tick is due\r\n\t\tif (absoluteAnimationFrame >= (relevantFramesForDistributing_ + 1)) {\r\n\t\t\t// we should never have +2 frames even if next game tick is due\r\n\t\t\tLog(\"getFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {} MaxFrame {})\", absoluteAnimationFrame, relevantFramesForDistributing_);\r\n\t\t}\r\n\t\treturn relevantFramesForDistributing_ - 1;\r\n\t}\r\n\tif (absoluteAnimationFrame < 0) {\r\n\t\tLog(\"getFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {})\", absoluteAnimationFrame);\r\n\t\treturn 0;\r\n\t}\r\n\treturn absoluteAnimationFrame;\r\n}\r\n\r\nuint8_t AnimationInfo::getAnimationProgress() const\r\n{\r\n\tint16_t ticksSinceSequenceStarted = std::max<int16_t>(0, ticksSinceSequenceStarted_);\r\n\tint32_t tickModifier = tickModifier_;\r\n\r\n\tif (relevantFramesForDistributing_ <= 0) {\r\n\t\tif (ticksPerFrame <= 0) {\r\n\t\t\tLog(\"getAnimationProgress: Invalid ticksPerFrame {}\", ticksPerFrame);\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\t// This logic is used if animation distribution is not active (see getFrameToUseForRendering).\r\n\t\t// In this case the variables calculated with animation distribution are not initialized and we have to calculate them on the fly with the given information.\r\n\t\tticksSinceSequenceStarted = ((currentFrame * ticksPerFrame) + tickCounterOfCurrentFrame) * baseValueFraction;\r\n\t\ttickModifier = baseValueFraction / ticksPerFrame;\r\n\t}\r\n\r\n\tconst int32_t totalTicksForCurrentAnimationSequence = getProgressToNextGameTick() + ticksSinceSequenceStarted;\r\n\tconst int32_t progressInAnimationFrames = totalTicksForCurrentAnimationSequence * tickModifier;\r\n\tconst int32_t animationFraction = progressInAnimationFrames / numberOfFrames / baseValueFraction;\r\n\tassert(animationFraction <= baseValueFraction);\r\n\treturn static_cast<uint8_t>(animationFraction);\r\n}\r\n\r\nvoid AnimationInfo::setNewAnimation(OptionalClxSpriteList celSprite, int8_t numberOfFrames, int8_t ticksPerFrame, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int8_t numSkippedFrames /*= 0*/, int8_t distributeFramesBeforeFrame /*= 0*/, uint8_t previewShownGameTickFragments /*= 0*/)\r\n{\r\n\tif ((flags & AnimationDistributionFlags::RepeatedAction) == AnimationDistributionFlags::RepeatedAction && distributeFramesBeforeFrame != 0 && this->numberOfFrames == numberOfFrames && currentFrame + 1 >= distributeFramesBeforeFrame && currentFrame != this->numberOfFrames - 1) {\r\n\t\t// We showed the same Animation (for example a melee attack) before but truncated the Animation.\r\n\t\t// So now we should add them back to the new Animation. This increases the speed of the current Animation but the game logic/ticks isn't affected.\r\n\t\tskippedFramesFromPreviousAnimation_ = this->numberOfFrames - currentFrame - 1;\r\n\t} else {\r\n\t\tskippedFramesFromPreviousAnimation_ = 0;\r\n\t}\r\n\r\n\tif (ticksPerFrame <= 0) {\r\n\t\tLog(\"setNewAnimation: Invalid ticksPerFrame {}\", ticksPerFrame);\r\n\t\tticksPerFrame = 1;\r\n\t}\r\n\r\n\tthis->sprites = celSprite;\r\n\tthis->numberOfFrames = numberOfFrames;\r\n\tcurrentFrame = numSkippedFrames;\r\n\ttickCounterOfCurrentFrame = 0;\r\n\tthis->ticksPerFrame = ticksPerFrame;\r\n\tticksSinceSequenceStarted_ = 0;\r\n\trelevantFramesForDistributing_ = 0;\r\n\ttickModifier_ = 0;\r\n\tisPetrified = false;\r\n\r\n\tif (numSkippedFrames != 0 || flags != AnimationDistributionFlags::None) {\r\n\t\t// Animation Frames that will be adjusted for the skipped Frames/game ticks\r\n\t\tint8_t relevantAnimationFramesForDistributing = numberOfFrames;\r\n\t\tif (distributeFramesBeforeFrame != 0) {\r\n\t\t\t// After an attack hits (_pAFNum or _pSFNum) it can be canceled or another attack can be queued and this means the animation is canceled.\r\n\t\t\t// In normal attacks frame skipping always happens before the attack actual hit.\r\n\t\t\t// This has the advantage that the sword or bow always points to the enemy when the hit happens (_pAFNum or _pSFNum).\r\n\t\t\t// Our distribution logic must also regard this behaviour, so we are not allowed to distribute the skipped animations after the actual hit (_pAnimStopDistributingAfterFrame).\r\n\t\t\trelevantAnimationFramesForDistributing = distributeFramesBeforeFrame - 1;\r\n\t\t}\r\n\r\n\t\t// Game ticks that will be adjusted for the skipped Frames/game ticks\r\n\t\tint32_t relevantAnimationTicksForDistribution = relevantAnimationFramesForDistributing * ticksPerFrame;\r\n\r\n\t\t// How many game ticks will the Animation be really shown (skipped Frames and game ticks removed)\r\n\t\tint32_t relevantAnimationTicksWithSkipping = relevantAnimationTicksForDistribution - (numSkippedFrames * ticksPerFrame);\r\n\r\n\t\tif ((flags & AnimationDistributionFlags::ProcessAnimationPending) == AnimationDistributionFlags::ProcessAnimationPending) {\r\n\t\t\t// If processAnimation will be called after setNewAnimation (in same game tick as setNewAnimation), we increment the Animation-Counter.\r\n\t\t\t// If no delay is specified, this will result in complete skipped frame (see processAnimation).\r\n\t\t\t// But if we have a delay specified, this would only result in a reduced time the first frame is shown (one skipped delay).\r\n\t\t\t// Because of that, we only the remove one game tick from the time the Animation is shown\r\n\t\t\trelevantAnimationTicksWithSkipping -= 1;\r\n\t\t\t// The Animation Distribution Logic needs to account how many game ticks passed since the Animation started.\r\n\t\t\t// Because processAnimation will increase this later (in same game tick as setNewAnimation), we correct this upfront.\r\n\t\t\t// This also means Rendering should never happen with ticksSinceSequenceStarted_ < 0.\r\n\t\t\tticksSinceSequenceStarted_ = -baseValueFraction;\r\n\t\t}\r\n\r\n\t\tif ((flags & AnimationDistributionFlags::SkipsDelayOfLastFrame) == AnimationDistributionFlags::SkipsDelayOfLastFrame) {\r\n\t\t\t// The logic for player/monster/... (not processAnimation) only checks the frame not the delay.\r\n\t\t\t// That means if a delay is specified, the last-frame is shown less than the other frames\r\n\t\t\t// Example:\r\n\t\t\t// If we have a animation with 3 frames and with a delay of 1 (ticksPerFrame = 2).\r\n\t\t\t// The logic checks \"if (frame == 3) { start_new_animation(); }\"\r\n\t\t\t// This will result that frame 4 is the last shown Animation Frame.\r\n\t\t\t// GameTick\t\tFrame\t\tCnt\r\n\t\t\t// 1\t\t\t1\t\t\t0\r\n\t\t\t// 2\t\t\t1\t\t\t1\r\n\t\t\t// 3\t\t\t2\t\t\t0\r\n\t\t\t// 3\t\t\t2\t\t\t1\r\n\t\t\t// 4\t\t\t3\t\t\t0\r\n\t\t\t// 5\t\t\t-\t\t\t-\r\n\t\t\t// in game tick 5 ProcessPlayer sees Frame = 3 and stops the animation.\r\n\t\t\t// But Frame 3 is only shown 1 game tick and all other Frames are shown 2 game ticks.\r\n\t\t\t// That's why we need to remove the Delay of the last Frame from the time (game ticks) the Animation is shown\r\n\t\t\trelevantAnimationTicksWithSkipping -= (ticksPerFrame - 1);\r\n\t\t}\r\n\r\n\t\t// The truncated Frames from previous Animation will also be shown, so we also have to distribute them for the given time (game ticks)\r\n\t\trelevantAnimationTicksForDistribution += (skippedFramesFromPreviousAnimation_ * ticksPerFrame);\r\n\r\n\t\t// At this point we use fixed point math for the fragment calculations\r\n\t\trelevantAnimationTicksForDistribution *= baseValueFraction;\r\n\t\trelevantAnimationTicksWithSkipping *= baseValueFraction;\r\n\r\n\t\t// The preview animation was shown some times (less than one game tick)\r\n\t\t// So we overall have a longer time the animation is shown\r\n\t\tticksSinceSequenceStarted_ += previewShownGameTickFragments;\r\n\t\trelevantAnimationTicksWithSkipping += previewShownGameTickFragments;\r\n\r\n\t\t// if we skipped Frames we need to expand the game ticks to make one game tick for this Animation \"faster\"\r\n\t\tint32_t tickModifier = 0;\r\n\t\tif (relevantAnimationTicksWithSkipping != 0)\r\n\t\t\ttickModifier = baseValueFraction * relevantAnimationTicksForDistribution / relevantAnimationTicksWithSkipping;\r\n\r\n\t\t// tickModifier specifies the Animation fraction per game tick, so we have to remove the delay from the variable\r\n\t\ttickModifier /= ticksPerFrame;\r\n\r\n\t\trelevantFramesForDistributing_ = relevantAnimationFramesForDistributing;\r\n\t\ttickModifier_ = static_cast<uint16_t>(tickModifier);\r\n\t}\r\n}\r\n\r\nvoid AnimationInfo::changeAnimationData(OptionalClxSpriteList celSprite, int8_t numberOfFrames, int8_t ticksPerFrame)\r\n{\r\n\tif (numberOfFrames != this->numberOfFrames || ticksPerFrame != this->ticksPerFrame) {\r\n\t\t// Ensure that the currentFrame is still valid and that we disable ADL because the calculated values (for example tickModifier_) could be wrong\r\n\t\tif (numberOfFrames >= 1)\r\n\t\t\tcurrentFrame = std::clamp<int8_t>(currentFrame, 0, numberOfFrames - 1);\r\n\t\telse\r\n\t\t\tcurrentFrame = -1;\r\n\r\n\t\tthis->numberOfFrames = numberOfFrames;\r\n\t\tthis->ticksPerFrame = ticksPerFrame;\r\n\t\tticksSinceSequenceStarted_ = 0;\r\n\t\trelevantFramesForDistributing_ = 0;\r\n\t\ttickModifier_ = 0;\r\n\t}\r\n\tthis->sprites = celSprite;\r\n}\r\n\r\nvoid AnimationInfo::processAnimation(bool reverseAnimation /*= false*/)\r\n{\r\n\ttickCounterOfCurrentFrame++;\r\n\tticksSinceSequenceStarted_ += baseValueFraction;\r\n\tif (tickCounterOfCurrentFrame >= ticksPerFrame) {\r\n\t\ttickCounterOfCurrentFrame = 0;\r\n\t\tif (reverseAnimation) {\r\n\t\t\t--currentFrame;\r\n\t\t\tif (currentFrame == -1) {\r\n\t\t\t\tcurrentFrame = numberOfFrames - 1;\r\n\t\t\t\tticksSinceSequenceStarted_ = 0;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t++currentFrame;\r\n\t\t\tif (currentFrame >= numberOfFrames) {\r\n\t\t\t\tcurrentFrame = 0;\r\n\t\t\t\tticksSinceSequenceStarted_ = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nuint8_t AnimationInfo::getProgressToNextGameTick() const\r\n{\r\n\tif (isPetrified)\r\n\t\treturn 0;\r\n\treturn ProgressToNextGameTick;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/animationinfo.h",
    "content": "/**\r\n * @file animationinfo.h\r\n *\r\n * Contains the core animation information and related logic\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <type_traits>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Specifies what special logics are applied for a Animation\r\n */\r\nenum AnimationDistributionFlags : uint8_t {\r\n\tNone = 0,\r\n\t/**\r\n\t * @brief processAnimation will be called after setNewAnimation (in same game tick as NewPlrAnim)\r\n\t */\r\n\tProcessAnimationPending = 1 << 0,\r\n\t/**\r\n\t * @brief Delay of last Frame is ignored (for example, because only Frame and not delay is checked in game_logic)\r\n\t */\r\n\tSkipsDelayOfLastFrame = 1 << 1,\r\n\t/**\r\n\t * @brief Repeated Animation (for example same player melee attack, that can be repeated directly after hit frame and doesn't need to show all animation frames)\r\n\t */\r\n\tRepeatedAction = 1 << 2,\r\n};\r\n\r\n/**\r\n * @brief Contains the core animation information and related logic\r\n */\r\nclass AnimationInfo {\r\npublic:\r\n\t/**\r\n\t * @brief Animation sprite\r\n\t */\r\n\tOptionalClxSpriteList sprites;\r\n\t/**\r\n\t * @brief How many game ticks are needed to advance one Animation Frame\r\n\t */\r\n\tint8_t ticksPerFrame;\r\n\t/**\r\n\t * @brief Increases by one each game tick, counting how close we are to ticksPerFrame\r\n\t */\r\n\tint8_t tickCounterOfCurrentFrame;\r\n\t/**\r\n\t * @brief Number of frames in current animation\r\n\t */\r\n\tint8_t numberOfFrames;\r\n\t/**\r\n\t * @brief Current frame of animation\r\n\t */\r\n\tint8_t currentFrame;\r\n\t/**\r\n\t * @brief Is the animation currently petrified and shouldn't advance with gfProgressToNextGameTick\r\n\t */\r\n\tbool isPetrified;\r\n\r\n\t[[nodiscard]] ClxSprite currentSprite() const\r\n\t{\r\n\t\treturn (*sprites)[getFrameToUseForRendering()];\r\n\t}\r\n\r\n\t[[nodiscard]] bool isLastFrame() const\r\n\t{\r\n\t\treturn currentFrame >= (numberOfFrames - 1);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Calculates the Frame to use for the Animation rendering\r\n\t * @return The Frame to use for rendering\r\n\t */\r\n\t[[nodiscard]] int8_t getFrameToUseForRendering() const;\r\n\r\n\t/**\r\n\t * @brief Calculates the progress of the current animation as a fraction (see baseValueFraction)\r\n\t */\r\n\t[[nodiscard]] uint8_t getAnimationProgress() const;\r\n\r\n\t/**\r\n\t * @brief Sets the new Animation with all relevant information for rendering\r\n\t * @param sprites Animation sprites\r\n\t * @param numberOfFrames Number of Frames in Animation\r\n\t * @param ticksPerFrame How many game ticks are needed to advance one Animation Frame\r\n\t * @param flags Specifies what special logics are applied to this Animation\r\n\t * @param numSkippedFrames Number of Frames that will be skipped (for example with modifier \"faster attack\")\r\n\t * @param distributeFramesBeforeFrame Distribute the numSkippedFrames only before this frame\r\n\t * @param previewShownGameTickFragments Defines how long (in game ticks fraction) the preview animation was shown\r\n\t */\r\n\tvoid setNewAnimation(OptionalClxSpriteList sprites, int8_t numberOfFrames, int8_t ticksPerFrame, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int8_t numSkippedFrames = 0, int8_t distributeFramesBeforeFrame = 0, uint8_t previewShownGameTickFragments = 0);\r\n\r\n\t/**\r\n\t * @brief Changes the Animation Data on-the-fly. This is needed if a animation is currently in progress and the player changes his gear.\r\n\t * @param sprites Animation sprites\r\n\t * @param numberOfFrames Number of Frames in Animation\r\n\t * @param ticksPerFrame How many game ticks are needed to advance one Animation Frame\r\n\t */\r\n\tvoid changeAnimationData(OptionalClxSpriteList sprites, int8_t numberOfFrames, int8_t ticksPerFrame);\r\n\r\n\t/**\r\n\t * @brief Process the Animation for a game tick (for example advances the frame)\r\n\t * @param reverseAnimation Play the animation backwards (for example is used for \"unseen\" monster fading)\r\n\t */\r\n\tvoid processAnimation(bool reverseAnimation = false);\r\n\r\n\t/**\r\n\t * @brief Fractions in AnimationInfo are stored as fixed point (baseValueFraction/128 correspondents to 1/100%).\r\n\t */\r\n\tconstexpr static uint8_t baseValueFraction = 128;\r\n\r\nprivate:\r\n\t/**\r\n\t * @brief returns the progress as a fraction in time to the next game tick or no progress if the animation is frozen (see baseValueFraction)\r\n\t */\r\n\t[[nodiscard]] uint8_t getProgressToNextGameTick() const;\r\n\r\n\t/**\r\n\t * @brief Animation Frames that will be adjusted for the skipped Frames/game ticks\r\n\t */\r\n\tint8_t relevantFramesForDistributing_;\r\n\t/**\r\n\t * @brief Animation Frames that wasn't shown from previous Animation\r\n\t */\r\n\tint8_t skippedFramesFromPreviousAnimation_;\r\n\t/**\r\n\t * @brief Specifies how many animations-fractions (see baseValueFraction) are displayed between two game ticks. this can be more than one frame, if animations are skipped or less than one frame if the same animation is shown in multiple times (delay specified).\r\n\t */\r\n\tuint16_t tickModifier_;\r\n\t/**\r\n\t * @brief Number of game ticks after the current animation sequence started\r\n\t */\r\n\tint16_t ticksSinceSequenceStarted_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/assets.cpp",
    "content": "#include \"engine/assets.hpp\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <functional>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"game_mode.hpp\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n\r\n#if defined(_WIN32) && !defined(__UWP__) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n#include <find_steam_game.h>\r\n#endif\r\n\r\n#ifndef UNPACKED_MPQS\r\n#include \"mpq/mpq_sdl_rwops.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nstd::vector<std::string> OverridePaths;\r\nstd::map<int, MpqArchiveT, std::greater<>> MpqArchives;\r\nbool HasHellfireMpq;\r\n\r\nnamespace {\r\n\r\n#ifdef UNPACKED_MPQS\r\nchar *FindUnpackedMpqFile(char *relativePath)\r\n{\r\n\tchar *path = nullptr;\r\n\tfor (const auto &[_, unpackedDir] : MpqArchives) {\r\n\t\tpath = relativePath - unpackedDir.size();\r\n\t\tstd::memcpy(path, unpackedDir.data(), unpackedDir.size());\r\n\t\tif (FileExists(path)) break;\r\n\t\tpath = nullptr;\r\n\t}\r\n\treturn path;\r\n}\r\n#else\r\nbool IsDebugLogging()\r\n{\r\n\treturn IsLogLevel(LogCategory::Application, SDL_LOG_PRIORITY_DEBUG);\r\n}\r\n\r\nSDL_IOStream *OpenOptionalRWops(const std::string &path)\r\n{\r\n\t// SDL always logs an error in Debug mode.\r\n\t// We check the file presence in Debug mode to avoid this.\r\n\tif (IsDebugLogging() && !FileExists(path.c_str()))\r\n\t\treturn nullptr;\r\n\treturn SDL_IOFromFile(path.c_str(), \"rb\");\r\n};\r\n\r\nbool FindMpqFile(std::string_view filename, MpqArchive **archive, uint32_t *fileNumber)\r\n{\r\n\tconst MpqFileHash fileHash = CalculateMpqFileHash(filename);\r\n\r\n\tfor (auto &[_, mpqArchive] : MpqArchives) {\r\n\t\tif (mpqArchive.GetFileNumber(fileHash, *fileNumber)) {\r\n\t\t\t*archive = &mpqArchive;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n#endif\r\n\r\n} // namespace\r\n\r\n#ifdef UNPACKED_MPQS\r\nAssetRef FindAsset(std::string_view filename)\r\n{\r\n\tAssetRef result;\r\n\tif (filename.empty() || filename.back() == '\\\\')\r\n\t\treturn result;\r\n\tresult.path[0] = '\\0';\r\n\r\n\tchar pathBuf[AssetRef::PathBufSize];\r\n\tchar *const pathEnd = pathBuf + AssetRef::PathBufSize;\r\n\tchar *const relativePath = &pathBuf[AssetRef::PathBufSize - filename.size() - 1];\r\n\t*BufCopy(relativePath, filename) = '\\0';\r\n\r\n#if !defined(_WIN32) && !defined(__DJGPP__)\r\n\tstd::replace(relativePath, pathEnd, '\\\\', '/');\r\n#endif\r\n\t// Absolute path:\r\n\tif (relativePath[0] == '/') {\r\n\t\tif (FileExists(relativePath)) {\r\n\t\t\t*BufCopy(result.path, std::string_view(relativePath, filename.size())) = '\\0';\r\n\t\t}\r\n\t\treturn result;\r\n\t}\r\n\r\n\t// Unpacked MPQ file:\r\n\tchar *const unpackedMpqPath = FindUnpackedMpqFile(relativePath);\r\n\tif (unpackedMpqPath != nullptr) {\r\n\t\t*BufCopy(result.path, std::string_view(unpackedMpqPath, pathEnd - unpackedMpqPath)) = '\\0';\r\n\t\treturn result;\r\n\t}\r\n\r\n\t// The `/assets` directory next to the devilutionx binary.\r\n\tconst std::string &assetsPathPrefix = paths::AssetsPath();\r\n\tchar *assetsPath = relativePath - assetsPathPrefix.size();\r\n\tstd::memcpy(assetsPath, assetsPathPrefix.data(), assetsPathPrefix.size());\r\n\tif (FileExists(assetsPath)) {\r\n\t\t*BufCopy(result.path, std::string_view(assetsPath, pathEnd - assetsPath)) = '\\0';\r\n\t}\r\n\treturn result;\r\n}\r\n#else\r\nAssetRef FindAsset(std::string_view filename)\r\n{\r\n\tAssetRef result;\r\n\tif (filename.empty() || filename.back() == '\\\\')\r\n\t\treturn result;\r\n\r\n\tstd::string relativePath { filename };\r\n#ifndef _WIN32\r\n\tstd::replace(relativePath.begin(), relativePath.end(), '\\\\', '/');\r\n#endif\r\n\r\n\tif (relativePath[0] == '/') {\r\n\t\tresult.directHandle = SDL_IOFromFile(relativePath.c_str(), \"rb\");\r\n\t\tif (result.directHandle != nullptr) {\r\n\t\t\treturn result;\r\n\t\t}\r\n\t}\r\n\r\n\t// Files in the `PrefPath()` directory can override MPQ contents.\r\n\t{\r\n\t\tfor (const auto &overridePath : OverridePaths) {\r\n\t\t\tconst std::string path = overridePath + relativePath;\r\n\t\t\tresult.directHandle = OpenOptionalRWops(path);\r\n\t\t\tif (result.directHandle != nullptr) {\r\n\t\t\t\tLogVerbose(\"Loaded MPQ file override: {}\", path);\r\n\t\t\t\treturn result;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Look for the file in all the MPQ archives:\r\n\tif (FindMpqFile(filename, &result.archive, &result.fileNumber)) {\r\n\t\tresult.filename = filename;\r\n\t\treturn result;\r\n\t}\r\n\r\n\t// Load from the `/assets` directory next to the devilutionx binary.\r\n\tresult.directHandle = OpenOptionalRWops(paths::AssetsPath() + relativePath);\r\n\tif (result.directHandle != nullptr)\r\n\t\treturn result;\r\n\r\n#if defined(__ANDROID__) || defined(__APPLE__)\r\n\t// Fall back to the bundled assets on supported systems.\r\n\t// This is handled by SDL when we pass a relative path.\r\n\tif (!paths::AssetsPath().empty()) {\r\n\t\tresult.directHandle = SDL_IOFromFile(relativePath.c_str(), \"rb\");\r\n\t\tif (result.directHandle != nullptr)\r\n\t\t\treturn result;\r\n\t}\r\n#endif\r\n\r\n\treturn result;\r\n}\r\n#endif\r\n\r\nAssetHandle OpenAsset(AssetRef &&ref, bool threadsafe)\r\n{\r\n#if UNPACKED_MPQS\r\n\treturn AssetHandle { OpenFile(ref.path, \"rb\") };\r\n#else\r\n\tif (ref.archive != nullptr)\r\n\t\treturn AssetHandle { SDL_RWops_FromMpqFile(*ref.archive, ref.fileNumber, ref.filename, threadsafe) };\r\n\tif (ref.directHandle != nullptr) {\r\n\t\t// Transfer handle ownership:\r\n\t\tauto *handle = ref.directHandle;\r\n\t\tref.directHandle = nullptr;\r\n\t\treturn AssetHandle { handle };\r\n\t}\r\n\treturn AssetHandle { nullptr };\r\n#endif\r\n}\r\n\r\nAssetHandle OpenAsset(std::string_view filename, bool threadsafe)\r\n{\r\n\tAssetRef ref = FindAsset(filename);\r\n\tif (!ref.ok())\r\n\t\treturn AssetHandle {};\r\n\treturn OpenAsset(std::move(ref), threadsafe);\r\n}\r\n\r\nAssetHandle OpenAsset(std::string_view filename, size_t &fileSize, bool threadsafe)\r\n{\r\n\tAssetRef ref = FindAsset(filename);\r\n\tif (!ref.ok())\r\n\t\treturn AssetHandle {};\r\n\tfileSize = ref.size();\r\n\treturn OpenAsset(std::move(ref), threadsafe);\r\n}\r\n\r\nSDL_IOStream *OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe)\r\n{\r\n#ifdef UNPACKED_MPQS\r\n\tAssetRef ref = FindAsset(filename);\r\n\tif (!ref.ok())\r\n\t\treturn nullptr;\r\n\treturn SDL_IOFromFile(ref.path, \"rb\");\r\n#else\r\n\treturn OpenAsset(filename, threadsafe).release();\r\n#endif\r\n}\r\n\r\ntl::expected<AssetData, std::string> LoadAsset(std::string_view path)\r\n{\r\n\tAssetRef ref = FindAsset(path);\r\n\tif (!ref.ok()) {\r\n\t\treturn tl::make_unexpected(StrCat(\"Asset not found: \", path));\r\n\t}\r\n\r\n\tconst size_t size = ref.size();\r\n\tstd::unique_ptr<char[]> data { new char[size] };\r\n\r\n\tAssetHandle handle = OpenAsset(std::move(ref));\r\n\tif (!handle.ok()) {\r\n\t\treturn tl::make_unexpected(StrCat(\"Failed to open asset: \", path, \"\\n\", handle.error()));\r\n\t}\r\n\r\n\tif (size > 0 && !handle.read(data.get(), size)) {\r\n\t\treturn tl::make_unexpected(StrCat(\"Read failed: \", path, \"\\n\", handle.error()));\r\n\t}\r\n\r\n\treturn AssetData { std::move(data), size };\r\n}\r\n\r\nstd::string FailedToOpenFileErrorMessage(std::string_view path, std::string_view error)\r\n{\r\n\treturn fmt::format(fmt::runtime(_(\"Failed to open file:\\n{:s}\\n\\n{:s}\\n\\nThe MPQ file(s) might be damaged. Please check the file integrity.\")), path, error);\r\n}\r\n\r\nnamespace {\r\n#ifdef UNPACKED_MPQS\r\nstd::optional<std::string> FindUnpackedMpqData(std::span<const std::string> paths, std::string_view mpqName)\r\n{\r\n\tstd::string targetPath;\r\n\tfor (const std::string &path : paths) {\r\n\t\ttargetPath.clear();\r\n\t\ttargetPath.reserve(path.size() + mpqName.size() + 1);\r\n\t\ttargetPath.append(path).append(mpqName) += DirectorySeparator;\r\n\t\tif (FileExists(targetPath)) {\r\n\t\t\tLogVerbose(\"  Found unpacked MPQ directory: {}\", targetPath);\r\n\t\t\treturn targetPath;\r\n\t\t}\r\n\t}\r\n\treturn std::nullopt;\r\n}\r\n\r\nbool FindMPQ(std::span<const std::string> paths, std::string_view mpqName)\r\n{\r\n\treturn FindUnpackedMpqData(paths, mpqName).has_value();\r\n}\r\n\r\nbool LoadMPQ(std::span<const std::string> paths, std::string_view mpqName, int priority)\r\n{\r\n\tstd::optional<std::string> mpqPath = FindUnpackedMpqData(paths, mpqName);\r\n\tif (!mpqPath.has_value()) {\r\n\t\tLogVerbose(\"Missing: {}\", mpqName);\r\n\t\treturn false;\r\n\t}\r\n\tMpqArchives[priority] = *std::move(mpqPath);\r\n\treturn true;\r\n}\r\n#else\r\nbool FindMPQ(std::span<const std::string> paths, std::string_view mpqName)\r\n{\r\n\tstd::string mpqAbsPath;\r\n\tfor (const auto &path : paths) {\r\n\t\tmpqAbsPath = StrCat(path, mpqName, \".mpq\");\r\n\t\tif (FileExists(mpqAbsPath)) {\r\n\t\t\tLogVerbose(\"  Found: {} in {}\", mpqName, path);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool LoadMPQ(std::span<const std::string> paths, std::string_view mpqName, int priority, std::string_view ext = \".mpq\")\r\n{\r\n\tstd::optional<MpqArchive> archive;\r\n\tstd::string mpqAbsPath;\r\n\tstd::int32_t error = 0;\r\n\tfor (const auto &path : paths) {\r\n\t\tmpqAbsPath = StrCat(path, mpqName, ext);\r\n\t\tarchive = MpqArchive::Open(mpqAbsPath.c_str(), error);\r\n\t\tif (archive.has_value()) {\r\n\t\t\tLogVerbose(\"  Found: {} in {}\", mpqName, path);\r\n\t\t\tauto [it, inserted] = MpqArchives.emplace(priority, *std::move(archive));\r\n\t\t\tif (!inserted) {\r\n\t\t\t\tLogError(\"MPQ with priority {} is already registered, skipping {}\", priority, mpqName);\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (error != 0) {\r\n\t\t\tLogError(\"Error {}: {}\", MpqArchive::ErrorMessage(error), mpqAbsPath);\r\n\t\t}\r\n\t}\r\n\tif (error == 0) {\r\n\t\tLogVerbose(\"Missing: {}\", mpqName);\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n#endif\r\n\r\nstd::vector<std::string> GetMPQSearchPaths()\r\n{\r\n\tstd::vector<std::string> paths;\r\n\tpaths.push_back(paths::BasePath());\r\n\tpaths.push_back(paths::PrefPath());\r\n\tif (paths[0] == paths[1])\r\n\t\tpaths.pop_back();\r\n\tpaths.push_back(paths::ConfigPath());\r\n\tif (paths[0] == paths[1] || (paths.size() == 3 && (paths[0] == paths[2] || paths[1] == paths[2])))\r\n\t\tpaths.pop_back();\r\n\r\n#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__DJGPP__)\r\n\t// `XDG_DATA_HOME` is usually the root path of `paths::PrefPath()`, so we only\r\n\t// add `XDG_DATA_DIRS`.\r\n\tconst char *xdgDataDirs = std::getenv(\"XDG_DATA_DIRS\");\r\n\tif (xdgDataDirs != nullptr) {\r\n\t\tfor (const std::string_view path : SplitByChar(xdgDataDirs, ':')) {\r\n\t\t\tstd::string fullPath(path);\r\n\t\t\tif (!path.empty() && path.back() != '/')\r\n\t\t\t\tfullPath += '/';\r\n\t\t\tfullPath.append(\"diasurgical/devilutionx/\");\r\n\t\t\tpaths.push_back(std::move(fullPath));\r\n\t\t}\r\n\t} else {\r\n\t\tpaths.emplace_back(\"/usr/local/share/diasurgical/devilutionx/\");\r\n\t\tpaths.emplace_back(\"/usr/share/diasurgical/devilutionx/\");\r\n\t}\r\n#elif defined(NXDK)\r\n\tpaths.emplace_back(\"D:\\\\\");\r\n#elif defined(_WIN32) && !defined(__UWP__) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n\tchar gogpath[_FSG_PATH_MAX];\r\n\tfsg_get_gog_game_path(gogpath, \"1412601690\");\r\n\tif (strlen(gogpath) > 0) {\r\n\t\tpaths.emplace_back(std::string(gogpath) + \"/\");\r\n\t\tpaths.emplace_back(std::string(gogpath) + \"/hellfire/\");\r\n\t}\r\n#endif\r\n\r\n\tif (paths.empty() || !paths.back().empty()) {\r\n\t\tpaths.emplace_back(); // PWD\r\n\t}\r\n\r\n\tif (IsLogLevel(LogCategory::Application, SDL_LOG_PRIORITY_VERBOSE)) {\r\n\t\tLogVerbose(\"Paths:\\n    base: {}\\n    pref: {}\\n  config: {}\\n  assets: {}\",\r\n\t\t    paths::BasePath(), paths::PrefPath(), paths::ConfigPath(), paths::AssetsPath());\r\n\r\n\t\tstd::string message;\r\n\t\tfor (std::size_t i = 0; i < paths.size(); ++i) {\r\n\t\t\tmessage.append(StrCat(\"\\n\", LeftPad(i + 1, 6, ' '), \". '\", paths[i], \"'\"));\r\n\t\t}\r\n\t\tLogVerbose(\"MPQ search paths:{}\", message);\r\n\t}\r\n\r\n\treturn paths;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadCoreArchives()\r\n{\r\n\tauto paths = GetMPQSearchPaths();\r\n\r\n#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__3DS__) && !defined(__SWITCH__)\r\n\t// Load devilutionx.mpq first to get the font file for error messages\r\n#ifdef __DJGPP__\r\n\tLoadMPQ(paths, \"devx\", DevilutionXMpqPriority);\r\n#else\r\n\tLoadMPQ(paths, \"devilutionx\", DevilutionXMpqPriority);\r\n#endif\r\n#endif\r\n\tLoadMPQ(paths, \"fonts\", FontMpqPriority); // Extra fonts\r\n\tHasHellfireMpq = FindMPQ(paths, \"hellfire\");\r\n}\r\n\r\nvoid LoadLanguageArchive()\r\n{\r\n\tMpqArchives.erase(LangMpqPriority);\r\n\tconst std::string_view code = GetLanguageCode();\r\n\tif (code != \"en\") {\r\n\t\tLoadMPQ(GetMPQSearchPaths(), code, LangMpqPriority);\r\n\t}\r\n}\r\n\r\nvoid LoadGameArchives()\r\n{\r\n\tconst std::vector<std::string> paths = GetMPQSearchPaths();\r\n\tbool haveDiabdat = false;\r\n\tbool haveSpawn = false;\r\n\r\n#ifndef UNPACKED_MPQS\r\n\t// DIABDAT.MPQ is uppercase on the original CD and the GOG version.\r\n\thaveDiabdat = LoadMPQ(paths, \"DIABDAT\", MainMpqPriority, \".MPQ\");\r\n#endif\r\n\r\n\tif (!haveDiabdat) {\r\n\t\thaveDiabdat = LoadMPQ(paths, \"diabdat\", MainMpqPriority);\r\n\t\tif (!haveDiabdat) {\r\n\t\t\tgbIsSpawn = haveSpawn = LoadMPQ(paths, \"spawn\", MainMpqPriority);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!HeadlessMode) {\r\n\t\tif (!haveDiabdat && !haveSpawn) {\r\n\t\t\tLogError(\"{}\", SDL_GetError());\r\n\t\t\tInsertCDDlg(_(\"diabdat.mpq or spawn.mpq\"));\r\n\t\t}\r\n\t}\r\n\r\n\tif (forceHellfire && !HasHellfireMpq) {\r\n#ifdef UNPACKED_MPQS\r\n\t\tInsertCDDlg(\"hellfire\");\r\n#else\r\n\t\tInsertCDDlg(\"hellfire.mpq\");\r\n#endif\r\n\t}\r\n\r\n#ifndef UNPACKED_MPQS\r\n\t// In unpacked mode, all the hellfire data is in the hellfire directory.\r\n\tLoadMPQ(paths, \"hfbard\", 8110);\r\n\tLoadMPQ(paths, \"hfbarb\", 8120);\r\n#endif\r\n}\r\n\r\nvoid LoadHellfireArchives()\r\n{\r\n\tconst std::vector<std::string> paths = GetMPQSearchPaths();\r\n\tLoadMPQ(paths, \"hellfire\", 8000);\r\n\r\n#ifdef UNPACKED_MPQS\r\n\tconst std::string &hellfireDataPath = MpqArchives.at(8000);\r\n\tconst bool hasMonk = FileExists(hellfireDataPath + \"plrgfx/monk/mha/mhaas.clx\");\r\n\tconst bool hasMusic = FileExists(hellfireDataPath + \"music/dlvlf.wav\")\r\n\t    || FileExists(hellfireDataPath + \"music/dlvlf.mp3\");\r\n\tconst bool hasVoice = FileExists(hellfireDataPath + \"sfx/hellfire/cowsut1.wav\")\r\n\t    || FileExists(hellfireDataPath + \"sfx/hellfire/cowsut1.mp3\");\r\n#else\r\n\tconst bool hasMonk = LoadMPQ(paths, \"hfmonk\", 8100);\r\n\tconst bool hasMusic = LoadMPQ(paths, \"hfmusic\", 8200);\r\n\tconst bool hasVoice = LoadMPQ(paths, \"hfvoice\", 8500);\r\n#endif\r\n\r\n\tif (!hasMonk || !hasMusic || !hasVoice)\r\n\t\tDisplayFatalErrorAndExit(_(\"Some Hellfire MPQs are missing\"), _(\"Not all Hellfire MPQs were found.\\nPlease copy all the hf*.mpq files.\"));\r\n}\r\n\r\nvoid UnloadModArchives()\r\n{\r\n\tOverridePaths.clear();\r\n\r\n#ifndef UNPACKED_MPQS\r\n\tfor (auto it = MpqArchives.begin(); it != MpqArchives.end();) {\r\n\t\tif ((it->first >= 8000 && it->first < 9000) || it->first >= 10000) {\r\n\t\t\tit = MpqArchives.erase(it); // erase returns the next valid iterator\r\n\t\t} else {\r\n\t\t\t++it;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid LoadModArchives(std::span<const std::string_view> modnames)\r\n{\r\n\tstd::string targetPath;\r\n\tfor (const std::string_view modname : modnames) {\r\n\t\ttargetPath = StrCat(paths::PrefPath(), \"mods\" DIRECTORY_SEPARATOR_STR, modname, DIRECTORY_SEPARATOR_STR);\r\n\t\tif (FileExists(targetPath)) {\r\n\t\t\tOverridePaths.emplace_back(targetPath);\r\n\t\t}\r\n\t\ttargetPath = StrCat(paths::BasePath(), \"mods\" DIRECTORY_SEPARATOR_STR, modname, DIRECTORY_SEPARATOR_STR);\r\n\t\tif (FileExists(targetPath)) {\r\n\t\t\tOverridePaths.emplace_back(targetPath);\r\n\t\t}\r\n\t}\r\n\tOverridePaths.emplace_back(paths::PrefPath());\r\n\r\n\tint priority = 10000;\r\n\tauto paths = GetMPQSearchPaths();\r\n\tfor (const std::string_view modname : modnames) {\r\n\t\tLoadMPQ(paths, StrCat(\"mods\" DIRECTORY_SEPARATOR_STR, modname), priority);\r\n\t\tpriority++;\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/assets.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <functional>\r\n#include <map>\r\n#include <span>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"appfat.h\"\r\n#include \"game_mode.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/string_or_view.hpp\"\r\n\r\n#ifndef UNPACKED_MPQS\r\n#include \"mpq/mpq_reader.hpp\"\r\n#endif\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n#ifdef UNPACKED_MPQS\r\nstruct AssetRef {\r\n\tstatic constexpr size_t PathBufSize = 4088;\r\n\r\n\tchar path[PathBufSize];\r\n\r\n\t[[nodiscard]] bool ok() const\r\n\t{\r\n\t\treturn path[0] != '\\0';\r\n\t}\r\n\r\n\t// NOLINTNEXTLINE(readability-convert-member-functions-to-static)\r\n\t[[nodiscard]] const char *error() const\r\n\t{\r\n\t\treturn \"File not found\";\r\n\t}\r\n\r\n\t[[nodiscard]] size_t size() const\r\n\t{\r\n\t\tuintmax_t fileSize;\r\n\t\tif (!GetFileSize(path, &fileSize))\r\n\t\t\treturn 0;\r\n\t\treturn fileSize;\r\n\t}\r\n};\r\n\r\nstruct AssetHandle {\r\n\tFILE *handle = nullptr;\r\n\r\n\tAssetHandle() = default;\r\n\r\n\tAssetHandle(FILE *handle)\r\n\t    : handle(handle)\r\n\t{\r\n\t}\r\n\r\n\tAssetHandle(AssetHandle &&other) noexcept\r\n\t    : handle(other.handle)\r\n\t{\r\n\t\tother.handle = nullptr;\r\n\t}\r\n\r\n\tAssetHandle &operator=(AssetHandle &&other) noexcept\r\n\t{\r\n\t\thandle = other.handle;\r\n\t\tother.handle = nullptr;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\t~AssetHandle()\r\n\t{\r\n\t\tif (handle != nullptr)\r\n\t\t\tstd::fclose(handle);\r\n\t}\r\n\r\n\t[[nodiscard]] bool ok() const\r\n\t{\r\n\t\treturn handle != nullptr && std::ferror(handle) == 0;\r\n\t}\r\n\r\n\tbool read(void *buffer, size_t len)\r\n\t{\r\n\t\treturn std::fread(buffer, len, 1, handle) == 1;\r\n\t}\r\n\r\n\tbool seek(long pos)\r\n\t{\r\n\t\treturn std::fseek(handle, pos, SEEK_SET) == 0;\r\n\t}\r\n\r\n\t[[nodiscard]] const char *error() const\r\n\t{\r\n\t\treturn std::strerror(errno);\r\n\t}\r\n};\r\n#else\r\nstruct AssetRef {\r\n\t// An MPQ file reference:\r\n\tMpqArchive *archive = nullptr;\r\n\tuint32_t fileNumber;\r\n\tstd::string_view filename;\r\n\r\n\t// Alternatively, a direct SDL_IOStream handle:\r\n\tSDL_IOStream *directHandle = nullptr;\r\n\r\n\tAssetRef() = default;\r\n\r\n\tAssetRef(AssetRef &&other) noexcept\r\n\t    : archive(other.archive)\r\n\t    , fileNumber(other.fileNumber)\r\n\t    , filename(other.filename)\r\n\t    , directHandle(other.directHandle)\r\n\t{\r\n\t\tother.directHandle = nullptr;\r\n\t}\r\n\r\n\tAssetRef &operator=(AssetRef &&other) noexcept\r\n\t{\r\n\t\tcloseDirectHandle();\r\n\t\tarchive = other.archive;\r\n\t\tfileNumber = other.fileNumber;\r\n\t\tfilename = other.filename;\r\n\t\tdirectHandle = other.directHandle;\r\n\t\tother.directHandle = nullptr;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\t~AssetRef()\r\n\t{\r\n\t\tcloseDirectHandle();\r\n\t}\r\n\r\n\t[[nodiscard]] bool ok() const\r\n\t{\r\n\t\treturn directHandle != nullptr || archive != nullptr;\r\n\t}\r\n\r\n\t// NOLINTNEXTLINE(readability-convert-member-functions-to-static)\r\n\t[[nodiscard]] const char *error() const\r\n\t{\r\n\t\treturn SDL_GetError();\r\n\t}\r\n\r\n\t[[nodiscard]] size_t size() const\r\n\t{\r\n\t\tif (archive != nullptr) {\r\n\t\t\tint32_t error;\r\n\t\t\treturn archive->GetUnpackedFileSize(fileNumber, error);\r\n\t\t}\r\n\t\treturn static_cast<size_t>(SDL_GetIOSize(directHandle));\r\n\t}\r\n\r\nprivate:\r\n\tvoid closeDirectHandle()\r\n\t{\r\n\t\tif (directHandle != nullptr) {\r\n\t\t\tSDL_CloseIO(directHandle);\r\n\t\t}\r\n\t}\r\n};\r\n\r\nstruct AssetHandle {\r\n\tSDL_IOStream *handle = nullptr;\r\n\r\n\tAssetHandle() = default;\r\n\r\n\texplicit AssetHandle(SDL_IOStream *handle)\r\n\t    : handle(handle)\r\n\t{\r\n\t}\r\n\r\n\tAssetHandle(AssetHandle &&other) noexcept\r\n\t    : handle(other.handle)\r\n\t{\r\n\t\tother.handle = nullptr;\r\n\t}\r\n\r\n\tAssetHandle &operator=(AssetHandle &&other) noexcept\r\n\t{\r\n\t\tcloseHandle();\r\n\t\thandle = other.handle;\r\n\t\tother.handle = nullptr;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\t~AssetHandle()\r\n\t{\r\n\t\tcloseHandle();\r\n\t}\r\n\r\n\t[[nodiscard]] bool ok() const\r\n\t{\r\n\t\treturn handle != nullptr;\r\n\t}\r\n\r\n\tbool read(void *buffer, size_t len)\r\n\t{\r\n\t\treturn SDL_ReadIO(handle, buffer, len) == len;\r\n\t}\r\n\r\n\tbool seek(long pos)\r\n\t{\r\n\t\treturn SDL_SeekIO(handle, pos, SDL_IO_SEEK_SET) != -1;\r\n\t}\r\n\r\n\t[[nodiscard]] const char *error() const\r\n\t{\r\n\t\treturn SDL_GetError();\r\n\t}\r\n\r\n\tSDL_IOStream *release() &&\r\n\t{\r\n\t\tSDL_IOStream *result = handle;\r\n\t\thandle = nullptr;\r\n\t\treturn result;\r\n\t}\r\n\r\nprivate:\r\n\tvoid closeHandle()\r\n\t{\r\n\t\tif (handle != nullptr) {\r\n\t\t\tSDL_CloseIO(handle);\r\n\t\t}\r\n\t}\r\n};\r\n#endif\r\n\r\nstd::string FailedToOpenFileErrorMessage(std::string_view path, std::string_view error);\r\n\r\n[[noreturn]] inline void FailedToOpenFileError(std::string_view path, std::string_view error)\r\n{\r\n\tapp_fatal(FailedToOpenFileErrorMessage(path, error));\r\n}\r\n\r\ninline bool ValidatAssetRef(std::string_view path, const AssetRef &ref)\r\n{\r\n\tif (ref.ok())\r\n\t\treturn true;\r\n\tif (!HeadlessMode) {\r\n\t\tFailedToOpenFileError(path, ref.error());\r\n\t}\r\n\treturn false;\r\n}\r\n\r\ninline bool ValidateHandle(std::string_view path, const AssetHandle &handle)\r\n{\r\n\tif (handle.ok())\r\n\t\treturn true;\r\n\tif (!HeadlessMode) {\r\n\t\tFailedToOpenFileError(path, handle.error());\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nAssetRef FindAsset(std::string_view filename);\r\n\r\nAssetHandle OpenAsset(AssetRef &&ref, bool threadsafe = false);\r\nAssetHandle OpenAsset(std::string_view filename, bool threadsafe = false);\r\nAssetHandle OpenAsset(std::string_view filename, size_t &fileSize, bool threadsafe = false);\r\n\r\nSDL_IOStream *OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe = false);\r\n\r\nstruct AssetData {\r\n\tstd::unique_ptr<char[]> data;\r\n\tsize_t size;\r\n\r\n\texplicit operator std::string_view() const\r\n\t{\r\n\t\treturn std::string_view(data.get(), size);\r\n\t}\r\n};\r\n\r\ntl::expected<AssetData, std::string> LoadAsset(std::string_view path);\r\n\r\n#ifdef UNPACKED_MPQS\r\nusing MpqArchiveT = std::string;\r\n#else\r\nusing MpqArchiveT = MpqArchive;\r\n#endif\r\n\r\nextern DVL_API_FOR_TEST std::map<int, MpqArchiveT, std::greater<>> MpqArchives;\r\nconstexpr int MainMpqPriority = 1000;\r\nconstexpr int DevilutionXMpqPriority = 9000;\r\nconstexpr int LangMpqPriority = 9100;\r\nconstexpr int FontMpqPriority = 9200;\r\nextern bool HasHellfireMpq;\r\n\r\nvoid LoadCoreArchives();\r\nvoid LoadLanguageArchive();\r\nvoid LoadGameArchives();\r\nvoid LoadHellfireArchives();\r\nvoid UnloadModArchives();\r\nvoid LoadModArchives(std::span<const std::string_view> modnames);\r\n\r\n#ifdef BUILD_TESTING\r\n[[nodiscard]] inline bool HaveMainData() { return MpqArchives.find(MainMpqPriority) != MpqArchives.end(); }\r\n#endif\r\n[[nodiscard]] inline bool HaveExtraFonts() { return MpqArchives.find(FontMpqPriority) != MpqArchives.end(); }\r\n[[nodiscard]] inline bool HaveHellfire() { return HasHellfireMpq; }\r\n[[nodiscard]] inline bool HaveIntro() { return FindAsset(\"gendata\\\\diablo1.smk\").ok(); }\r\n[[nodiscard]] inline bool HaveFullMusic() { return FindAsset(\"music\\\\dintro.wav\").ok() || FindAsset(\"music\\\\dintro.mp3\").ok(); }\r\n[[nodiscard]] inline bool HaveBardAssets() { return FindAsset(\"plrgfx\\\\bard\\\\bha\\\\bhaas.clx\").ok(); }\r\n[[nodiscard]] inline bool HaveBarbarianAssets() { return FindAsset(\"plrgfx\\\\barbarian\\\\cha\\\\chaas.clx\").ok(); }\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/backbuffer_state.cpp",
    "content": "#include \"engine/backbuffer_state.hpp\"\r\n\r\n#include <array>\r\n#include <vector>\r\n\r\n#include \"engine/dx.h\"\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstruct RedrawState {\r\n\tenum {\r\n\t\tRedrawNone,\r\n\t\tRedrawViewportOnly,\r\n\t\tRedrawAll\r\n\t} Redraw;\r\n\tstd::array<bool, enum_size<PanelDrawComponent>::value> redrawComponents;\r\n};\r\n\r\nstruct BackbufferState {\r\n\tRedrawState redrawState;\r\n\tDrawnCursor cursor;\r\n};\r\n\r\nstruct BackbufferPtrAndState {\r\n\tvoid *ptr;\r\n\tBackbufferState state;\r\n};\r\n\r\nstd::vector<BackbufferPtrAndState> States;\r\n\r\nBackbufferState &GetBackbufferState()\r\n{\r\n\t// `PalSurface` is null in headless mode.\r\n\tvoid *ptr = PalSurface != nullptr ? PalSurface->pixels : nullptr;\r\n\tfor (BackbufferPtrAndState &ptrAndState : States) {\r\n\t\tif (ptrAndState.ptr == ptr)\r\n\t\t\treturn ptrAndState.state;\r\n\t}\r\n\tStates.emplace_back();\r\n\tBackbufferPtrAndState &ptrAndState = States.back();\r\n\tptrAndState.ptr = ptr;\r\n\tptrAndState.state.redrawState.Redraw = RedrawState::RedrawAll;\r\n\r\n\treturn ptrAndState.state;\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsRedrawEverything()\r\n{\r\n\treturn GetBackbufferState().redrawState.Redraw == RedrawState::RedrawAll;\r\n}\r\n\r\nvoid RedrawViewport()\r\n{\r\n\tfor (BackbufferPtrAndState &ptrAndState : States) {\r\n\t\tif (ptrAndState.state.redrawState.Redraw != RedrawState::RedrawAll) {\r\n\t\t\tptrAndState.state.redrawState.Redraw = RedrawState::RedrawViewportOnly;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool IsRedrawViewport()\r\n{\r\n\treturn GetBackbufferState().redrawState.Redraw == RedrawState::RedrawViewportOnly;\r\n}\r\n\r\nvoid RedrawComplete()\r\n{\r\n\tGetBackbufferState().redrawState.Redraw = RedrawState::RedrawNone;\r\n}\r\n\r\nvoid RedrawEverything()\r\n{\r\n\tfor (BackbufferPtrAndState &ptrAndState : States) {\r\n\t\tptrAndState.state.redrawState.Redraw = RedrawState::RedrawAll;\r\n\t}\r\n}\r\n\r\nvoid InitBackbufferState()\r\n{\r\n\tStates.clear();\r\n}\r\n\r\nvoid RedrawComponent(PanelDrawComponent component)\r\n{\r\n\tfor (BackbufferPtrAndState &ptrAndState : States) {\r\n\t\tptrAndState.state.redrawState.redrawComponents[static_cast<size_t>(component)] = true;\r\n\t}\r\n}\r\n\r\nbool IsRedrawComponent(PanelDrawComponent component)\r\n{\r\n\treturn GetBackbufferState().redrawState.redrawComponents[static_cast<size_t>(component)];\r\n}\r\n\r\nvoid RedrawComponentComplete(PanelDrawComponent component)\r\n{\r\n\tGetBackbufferState().redrawState.redrawComponents[static_cast<size_t>(component)] = false;\r\n}\r\n\r\nDrawnCursor &GetDrawnCursor()\r\n{\r\n\treturn GetBackbufferState().cursor;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/backbuffer_state.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nenum class PanelDrawComponent {\r\n\tHealth,\r\n\tMana,\r\n\tControlButtons,\r\n\tBelt,\r\n\r\n\tFIRST = Health,\r\n\tLAST = Belt\r\n};\r\n\r\nstruct DrawnCursor {\r\n\tRectangle rect;\r\n\tuint8_t behindBuffer[8192];\r\n};\r\n\r\nvoid InitBackbufferState();\r\n\r\nvoid RedrawEverything();\r\nbool IsRedrawEverything();\r\nvoid RedrawViewport();\r\nbool IsRedrawViewport();\r\nvoid RedrawComplete();\r\n\r\nvoid RedrawComponent(PanelDrawComponent component);\r\nbool IsRedrawComponent(PanelDrawComponent component);\r\nvoid RedrawComponentComplete(PanelDrawComponent component);\r\n\r\nDrawnCursor &GetDrawnCursor();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/circle.hpp",
    "content": "#pragma once\r\n\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstruct Circle {\r\n\tPoint position;\r\n\tint radius;\r\n\r\n\tconstexpr bool contains(Point point) const\r\n\t{\r\n\t\tDisplacement diff = point - position;\r\n\t\tint x = diff.deltaX;\r\n\t\tint y = diff.deltaY;\r\n\t\treturn x * x + y * y < radius * radius;\r\n\t}\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/clx_sprite.hpp",
    "content": "#pragma once\r\n/**\r\n * @file clx_sprite.hpp\r\n *\r\n * @brief CLX format sprites.\r\n *\r\n * CLX is a format used for DevilutionX graphics at runtime.\r\n * CLX encodes pixel in the same way CL2 but encodes metadata differently.\r\n *\r\n * Unlike CL2:\r\n *\r\n * 1. CLX frame header stores frame width and height.\r\n * 2. CLX frame header does not store 32-pixel block offsets.\r\n *\r\n * CLX frame header is 6 bytes:\r\n *\r\n *  Bytes |   Type   | Value\r\n * :-----:|:--------:|-------------\r\n *  0..2  | uint16_t | header size\r\n *  2..4  | uint16_t | width\r\n *  4..6  | uint16_t | height\r\n *\r\n * CL2 reference: https://github.com/savagesteel/d1-file-formats/blob/master/PC-Mac/CL2.md#2-file-structure\r\n */\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <iterator>\r\n#include <memory>\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/intrusive_optional.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nclass OptionalClxSprite;\r\n\r\n/**\r\n * @brief A single CLX sprite.\r\n */\r\nclass ClxSprite {\r\npublic:\r\n\texplicit constexpr ClxSprite(const uint8_t *data, uint32_t dataSize)\r\n\t    : data_(data)\r\n\t    , pixel_data_size_(dataSize - LoadLE16(data))\r\n\t{\r\n\t\tassert(data != nullptr);\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr uint16_t width() const\r\n\t{\r\n\t\treturn LoadLE16(&data_[2]);\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr uint16_t height() const\r\n\t{\r\n\t\treturn LoadLE16(&data_[4]);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief The raw pixel data (CL2 frame data).\r\n\t *\r\n\t * Format: https://github.com/savagesteel/d1-file-formats/blob/master/PC-Mac/CL2.md#42-cl2-frame-data\r\n\t */\r\n\t[[nodiscard]] constexpr const uint8_t *pixelData() const\r\n\t{\r\n\t\treturn &data_[LoadLE16(data_)];\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr uint32_t pixelDataSize() const\r\n\t{\r\n\t\treturn pixel_data_size_;\r\n\t}\r\n\r\n\tconstexpr bool operator==(const ClxSprite &other) const\r\n\t{\r\n\t\treturn data_ == other.data_;\r\n\t}\r\n\r\n\tconstexpr bool operator!=(const ClxSprite &other) const\r\n\t{\r\n\t\treturn !(*this == other);\r\n\t}\r\n\r\nprivate:\r\n\t// For OptionalClxSprite.\r\n\tconstexpr ClxSprite() = default;\r\n\r\n\tconst uint8_t *data_ = nullptr;\r\n\tuint32_t pixel_data_size_ = 0;\r\n\r\n\tfriend class OptionalClxSprite;\r\n};\r\n\r\nclass OwnedClxSpriteList;\r\nclass OptionalClxSpriteList;\r\nclass ClxSpriteListIterator;\r\n\r\n/**\r\n * @brief A list of `ClxSprite`s.\r\n */\r\nclass ClxSpriteList {\r\npublic:\r\n\texplicit constexpr ClxSpriteList(const uint8_t *data)\r\n\t    : data_(data)\r\n\t{\r\n\t\tassert(data != nullptr);\r\n\t}\r\n\r\n\tClxSpriteList(const OwnedClxSpriteList &owned);\r\n\r\n\t[[nodiscard]] OwnedClxSpriteList clone() const;\r\n\r\n\t[[nodiscard]] constexpr uint32_t numSprites() const\r\n\t{\r\n\t\treturn LoadLE32(data_);\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr ClxSprite operator[](size_t spriteIndex) const\r\n\t{\r\n\t\tassert(spriteIndex < numSprites());\r\n\t\tconst uint32_t begin = spriteOffset(spriteIndex);\r\n\t\tconst uint32_t end = spriteOffset(spriteIndex + 1);\r\n\t\treturn ClxSprite { &data_[begin], end - begin };\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr uint32_t spriteOffset(size_t spriteIndex) const\r\n\t{\r\n\t\treturn LoadLE32(&data_[4 + spriteIndex * 4]);\r\n\t}\r\n\r\n\t/** @brief The offset to the next sprite sheet, or file size if this is the last sprite sheet. */\r\n\t[[nodiscard]] constexpr uint32_t dataSize() const\r\n\t{\r\n\t\treturn LoadLE32(&data_[4 + numSprites() * 4]);\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr const uint8_t *data() const\r\n\t{\r\n\t\treturn data_;\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr ClxSpriteListIterator begin() const;\r\n\t[[nodiscard]] constexpr ClxSpriteListIterator end() const;\r\n\r\nprivate:\r\n\t// For OptionalClxSpriteList.\r\n\tconstexpr ClxSpriteList() = default;\r\n\r\n\tconst uint8_t *data_ = nullptr;\r\n\r\n\tfriend class OptionalClxSpriteList;\r\n};\r\n\r\nclass ClxSpriteListIterator {\r\npublic:\r\n\tusing iterator_category = std::forward_iterator_tag;\r\n\tusing difference_type = int;\r\n\tusing value_type = ClxSprite;\r\n\tusing pointer = void;\r\n\tusing reference = value_type &;\r\n\r\n\tconstexpr ClxSpriteListIterator(ClxSpriteList list, size_t index)\r\n\t    : list_(list)\r\n\t    , index_(index)\r\n\t{\r\n\t}\r\n\r\n\tconstexpr ClxSprite operator*()\r\n\t{\r\n\t\treturn list_[index_];\r\n\t}\r\n\r\n\tconstexpr ClxSpriteListIterator &operator++()\r\n\t{\r\n\t\t++index_;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tconstexpr ClxSpriteListIterator operator++(int)\r\n\t{\r\n\t\tauto copy = *this;\r\n\t\t++(*this);\r\n\t\treturn copy;\r\n\t}\r\n\r\n\tconstexpr bool operator==(const ClxSpriteListIterator &other) const\r\n\t{\r\n\t\treturn index_ == other.index_;\r\n\t}\r\n\r\n\tconstexpr bool operator!=(const ClxSpriteListIterator &other) const\r\n\t{\r\n\t\treturn !(*this == other);\r\n\t}\r\n\r\nprivate:\r\n\tClxSpriteList list_;\r\n\tsize_t index_;\r\n};\r\n\r\ninline constexpr ClxSpriteListIterator ClxSpriteList::begin() const\r\n{\r\n\treturn { *this, 0 };\r\n}\r\n\r\ninline constexpr ClxSpriteListIterator ClxSpriteList::end() const\r\n{\r\n\treturn { *this, numSprites() };\r\n}\r\n\r\nclass OwnedClxSpriteSheet;\r\nclass OptionalClxSpriteSheet;\r\nclass ClxSpriteSheetIterator;\r\n\r\n/**\r\n * @brief A sprite sheet is a list of `ClxSpriteList`s.\r\n */\r\nclass ClxSpriteSheet {\r\npublic:\r\n\texplicit constexpr ClxSpriteSheet(const uint8_t *data, uint16_t numLists)\r\n\t    : data_(data)\r\n\t    , num_lists_(numLists)\r\n\t{\r\n\t\tassert(data != nullptr);\r\n\t\tassert(num_lists_ > 0);\r\n\t}\r\n\r\n\tClxSpriteSheet(const OwnedClxSpriteSheet &owned);\r\n\r\n\t[[nodiscard]] constexpr uint16_t numLists() const\r\n\t{\r\n\t\treturn num_lists_;\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr ClxSpriteList operator[](size_t sheetIndex) const\r\n\t{\r\n\t\treturn ClxSpriteList { &data_[sheetOffset(sheetIndex)] };\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr uint32_t sheetOffset(size_t sheetIndex) const\r\n\t{\r\n\t\tassert(sheetIndex < num_lists_);\r\n\t\treturn LoadLE32(&data_[4 * sheetIndex]);\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr const uint8_t *data() const\r\n\t{\r\n\t\treturn data_;\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr ClxSpriteSheetIterator begin() const;\r\n\t[[nodiscard]] constexpr ClxSpriteSheetIterator end() const;\r\n\r\n\t[[nodiscard]] size_t dataSize() const\r\n\t{\r\n\t\treturn static_cast<size_t>(&data_[sheetOffset(num_lists_ - 1)] + (*this)[num_lists_ - 1].dataSize() - &data_[0]);\r\n\t}\r\n\r\nprivate:\r\n\t// For OptionalClxSpriteSheet.\r\n\tconstexpr ClxSpriteSheet() = default;\r\n\r\n\tconst uint8_t *data_ = nullptr;\r\n\tuint16_t num_lists_ = 0;\r\n\r\n\tfriend class OptionalClxSpriteSheet;\r\n};\r\n\r\nclass ClxSpriteSheetIterator {\r\npublic:\r\n\tusing iterator_category = std::forward_iterator_tag;\r\n\tusing difference_type = int;\r\n\tusing value_type = ClxSpriteList;\r\n\tusing pointer = void;\r\n\tusing reference = value_type &;\r\n\r\n\tconstexpr ClxSpriteSheetIterator(ClxSpriteSheet sheet, size_t index)\r\n\t    : sheet_(sheet)\r\n\t    , index_(index)\r\n\t{\r\n\t}\r\n\r\n\tconstexpr ClxSpriteList operator*()\r\n\t{\r\n\t\treturn sheet_[index_];\r\n\t}\r\n\r\n\tconstexpr ClxSpriteSheetIterator &operator++()\r\n\t{\r\n\t\t++index_;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tconstexpr ClxSpriteSheetIterator operator++(int)\r\n\t{\r\n\t\tauto copy = *this;\r\n\t\t++(*this);\r\n\t\treturn copy;\r\n\t}\r\n\r\n\tconstexpr bool operator==(const ClxSpriteSheetIterator &other) const\r\n\t{\r\n\t\treturn index_ == other.index_;\r\n\t}\r\n\r\n\tconstexpr bool operator!=(const ClxSpriteSheetIterator &other) const\r\n\t{\r\n\t\treturn !(*this == other);\r\n\t}\r\n\r\nprivate:\r\n\tClxSpriteSheet sheet_;\r\n\tsize_t index_;\r\n};\r\n\r\ninline constexpr ClxSpriteSheetIterator ClxSpriteSheet::begin() const\r\n{\r\n\treturn { *this, 0 };\r\n}\r\n\r\ninline constexpr ClxSpriteSheetIterator ClxSpriteSheet::end() const\r\n{\r\n\treturn { *this, num_lists_ };\r\n}\r\n\r\nclass OptionalOwnedClxSpriteList;\r\nclass OwnedClxSpriteListOrSheet;\r\n\r\n/**\r\n * @brief Implicitly convertible to `ClxSpriteList` and owns its data.\r\n */\r\nclass OwnedClxSpriteList {\r\npublic:\r\n\texplicit OwnedClxSpriteList(std::unique_ptr<uint8_t[]> &&data)\r\n\t    : data_(std::move(data))\r\n\t{\r\n\t\tassert(data_ != nullptr);\r\n\t}\r\n\r\n\tOwnedClxSpriteList(OwnedClxSpriteList &&) noexcept = default;\r\n\tOwnedClxSpriteList &operator=(OwnedClxSpriteList &&) noexcept = default;\r\n\r\n\t[[nodiscard]] OwnedClxSpriteList clone() const\r\n\t{\r\n\t\treturn ClxSpriteList { *this }.clone();\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSprite operator[](size_t spriteIndex) const\r\n\t{\r\n\t\treturn ClxSpriteList { *this }[spriteIndex];\r\n\t}\r\n\r\n\t[[nodiscard]] uint32_t numSprites() const\r\n\t{\r\n\t\treturn ClxSpriteList { *this }.numSprites();\r\n\t}\r\n\r\n\t[[nodiscard]] size_t dataSize() const\r\n\t{\r\n\t\treturn ClxSpriteList { *this }.dataSize();\r\n\t}\r\n\r\nprivate:\r\n\t// For OptionalOwnedClxSpriteList.\r\n\tOwnedClxSpriteList() = default;\r\n\r\n\tstd::unique_ptr<uint8_t[]> data_;\r\n\r\n\tfriend class ClxSpriteList; // for implicit conversion\r\n\tfriend class OptionalOwnedClxSpriteList;\r\n\tfriend class OwnedClxSpriteListOrSheet;\r\n};\r\n\r\ninline ClxSpriteList::ClxSpriteList(const OwnedClxSpriteList &owned)\r\n    : data_(owned.data_.get())\r\n{\r\n}\r\n\r\ninline OwnedClxSpriteList ClxSpriteList::clone() const\r\n{\r\n\tconst size_t size = dataSize();\r\n\tstd::unique_ptr<uint8_t[]> data { new uint8_t[size] };\r\n\tmemcpy(data.get(), data_, size);\r\n\treturn OwnedClxSpriteList { std::move(data) };\r\n}\r\n\r\n/**\r\n * @brief Implicitly convertible to `ClxSpriteSheet` and owns its data.\r\n */\r\nclass OwnedClxSpriteSheet {\r\npublic:\r\n\tOwnedClxSpriteSheet(std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)\r\n\t    : data_(std::move(data))\r\n\t    , num_lists_(numLists)\r\n\t{\r\n\t\tassert(data_ != nullptr);\r\n\t\tassert(numLists > 0);\r\n\t}\r\n\r\n\tOwnedClxSpriteSheet(OwnedClxSpriteSheet &&) noexcept = default;\r\n\tOwnedClxSpriteSheet &operator=(OwnedClxSpriteSheet &&) noexcept = default;\r\n\r\n\t[[nodiscard]] ClxSpriteList operator[](size_t sheetIndex) const\r\n\t{\r\n\t\treturn ClxSpriteSheet { *this }[sheetIndex];\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSpriteSheetIterator begin() const\r\n\t{\r\n\t\treturn ClxSpriteSheet { *this }.begin();\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSpriteSheetIterator end() const\r\n\t{\r\n\t\treturn ClxSpriteSheet { *this }.end();\r\n\t}\r\n\r\n\t[[nodiscard]] size_t dataSize() const\r\n\t{\r\n\t\treturn ClxSpriteSheet { *this }.dataSize();\r\n\t}\r\n\r\nprivate:\r\n\t// For OptionalOwnedClxSpriteList.\r\n\tOwnedClxSpriteSheet() = default;\r\n\r\n\tstd::unique_ptr<uint8_t[]> data_;\r\n\tuint16_t num_lists_ = 0;\r\n\r\n\tfriend class ClxSpriteSheet; // for implicit conversion.\r\n\tfriend class OptionalOwnedClxSpriteSheet;\r\n\tfriend class OwnedClxSpriteListOrSheet;\r\n};\r\n\r\ninline ClxSpriteSheet::ClxSpriteSheet(const OwnedClxSpriteSheet &owned)\r\n    : data_(owned.data_.get())\r\n    , num_lists_(owned.num_lists_)\r\n{\r\n}\r\n\r\nclass OwnedClxSpriteListOrSheet;\r\nclass OptionalClxSpriteListOrSheet;\r\n\r\ninline uint16_t GetNumListsFromClxListOrSheetBuffer(const uint8_t *data, size_t size)\r\n{\r\n\tconst uint32_t maybeNumFrames = LoadLE32(data);\r\n\r\n\t// If it is a number of frames, then the last frame offset will be equal to the size of the file.\r\n\tif (LoadLE32(&data[maybeNumFrames * 4 + 4]) != size)\r\n\t\treturn maybeNumFrames / 4;\r\n\r\n\t// Not a sprite sheet.\r\n\treturn 0;\r\n}\r\n\r\n/**\r\n * @brief A CLX sprite list or a sprite sheet (list of lists).\r\n */\r\nclass ClxSpriteListOrSheet {\r\npublic:\r\n\tconstexpr ClxSpriteListOrSheet(const uint8_t *data, uint16_t numLists)\r\n\t    : data_(data)\r\n\t    , num_lists_(numLists)\r\n\t{\r\n\t}\r\n\r\n\tClxSpriteListOrSheet(const OwnedClxSpriteListOrSheet &listOrSheet);\r\n\r\n\t[[nodiscard]] constexpr ClxSpriteList list() const\r\n\t{\r\n\t\tassert(num_lists_ == 0);\r\n\t\treturn ClxSpriteList { data_ };\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr ClxSpriteSheet sheet() const\r\n\t{\r\n\t\tassert(num_lists_ != 0);\r\n\t\treturn ClxSpriteSheet { data_, num_lists_ };\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr bool isSheet() const\r\n\t{\r\n\t\treturn num_lists_ != 0;\r\n\t}\r\n\r\n\t[[nodiscard]] size_t dataSize() const\r\n\t{\r\n\t\treturn isSheet() ? sheet().dataSize() : list().dataSize();\r\n\t}\r\n\r\nprivate:\r\n\t// For OptionalClxSpriteListOrSheet.\r\n\tconstexpr ClxSpriteListOrSheet() = default;\r\n\r\n\tconst uint8_t *data_ = nullptr;\r\n\tuint16_t num_lists_ = 0;\r\n\r\n\tfriend class OptionalClxSpriteListOrSheet;\r\n};\r\n\r\nclass OptionalOwnedClxSpriteListOrSheet;\r\n\r\n/**\r\n * @brief A CLX sprite list or a sprite sheet (list of lists).\r\n */\r\nclass OwnedClxSpriteListOrSheet {\r\npublic:\r\n\tstatic OwnedClxSpriteListOrSheet FromBuffer(std::unique_ptr<uint8_t[]> &&data, size_t size)\r\n\t{\r\n\t\tconst uint16_t numLists = GetNumListsFromClxListOrSheetBuffer(data.get(), size);\r\n\t\treturn OwnedClxSpriteListOrSheet { std::move(data), numLists };\r\n\t}\r\n\r\n\texplicit OwnedClxSpriteListOrSheet(std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)\r\n\t    : data_(std::move(data))\r\n\t    , num_lists_(numLists)\r\n\t{\r\n\t}\r\n\r\n\texplicit OwnedClxSpriteListOrSheet(OwnedClxSpriteSheet &&sheet)\r\n\t    : data_(std::move(sheet.data_))\r\n\t    , num_lists_(sheet.num_lists_)\r\n\t{\r\n\t}\r\n\r\n\texplicit OwnedClxSpriteListOrSheet(OwnedClxSpriteList &&list)\r\n\t    : data_(std::move(list.data_))\r\n\t    , num_lists_(0)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSpriteList list() const &\r\n\t{\r\n\t\tassert(num_lists_ == 0);\r\n\t\treturn ClxSpriteList { data_.get() };\r\n\t}\r\n\r\n\t[[nodiscard]] OwnedClxSpriteList list() &&\r\n\t{\r\n\t\tassert(num_lists_ == 0);\r\n\t\treturn OwnedClxSpriteList { std::move(data_) };\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSpriteSheet sheet() const &\r\n\t{\r\n\t\tassert(num_lists_ != 0);\r\n\t\treturn ClxSpriteSheet { data_.get(), num_lists_ };\r\n\t}\r\n\r\n\t[[nodiscard]] OwnedClxSpriteSheet sheet() &&\r\n\t{\r\n\t\tassert(num_lists_ != 0);\r\n\t\treturn OwnedClxSpriteSheet { std::move(data_), num_lists_ };\r\n\t}\r\n\r\n\t[[nodiscard]] bool isSheet() const\r\n\t{\r\n\t\treturn num_lists_ != 0;\r\n\t}\r\n\r\n\t[[nodiscard]] uint16_t numLists() const { return num_lists_; }\r\n\r\n\t[[nodiscard]] size_t dataSize() const\r\n\t{\r\n\t\treturn ClxSpriteListOrSheet { *this }.dataSize();\r\n\t}\r\n\r\nprivate:\r\n\t// For OptionalOwnedClxSpriteListOrSheet.\r\n\tOwnedClxSpriteListOrSheet() = default;\r\n\r\n\tstd::unique_ptr<uint8_t[]> data_;\r\n\tuint16_t num_lists_ = 0;\r\n\r\n\tfriend class ClxSpriteListOrSheet;\r\n\tfriend class OptionalOwnedClxSpriteListOrSheet;\r\n};\r\n\r\ninline ClxSpriteListOrSheet::ClxSpriteListOrSheet(const OwnedClxSpriteListOrSheet &listOrSheet)\r\n    : data_(listOrSheet.data_.get())\r\n    , num_lists_(listOrSheet.num_lists_)\r\n{\r\n}\r\n\r\n/**\r\n * @brief Equivalent to `std::optional<ClxSprite>` but smaller.\r\n */\r\nclass OptionalClxSprite {\r\n\tDEFINE_CONSTEXPR_INTRUSIVE_OPTIONAL(OptionalClxSprite, ClxSprite, data_, nullptr)\r\n};\r\n\r\n/**\r\n * @brief Equivalent to `std::optional<ClxSpriteList>` but smaller.\r\n */\r\nclass OptionalClxSpriteList {\r\n\tDEFINE_CONSTEXPR_INTRUSIVE_OPTIONAL(OptionalClxSpriteList, ClxSpriteList, data_, nullptr)\r\n};\r\n\r\n/**\r\n * @brief Equivalent to `std::optional<ClxSpriteSheet>` but smaller.\r\n */\r\nclass OptionalClxSpriteSheet {\r\n\tDEFINE_CONSTEXPR_INTRUSIVE_OPTIONAL(OptionalClxSpriteSheet, ClxSpriteSheet, data_, nullptr)\r\n};\r\n\r\n/**\r\n * @brief Equivalent to `std::optional<ClxSpriteListOrSheet>` but smaller.\r\n */\r\nclass OptionalClxSpriteListOrSheet {\r\npublic:\r\n\tDEFINE_INTRUSIVE_OPTIONAL(OptionalClxSpriteListOrSheet, ClxSpriteListOrSheet, data_, nullptr);\r\n};\r\n\r\n/**\r\n * @brief Equivalent to `std::optional<OwnedClxSpriteList>` but smaller.\r\n */\r\nclass OptionalOwnedClxSpriteList {\r\npublic:\r\n\tDEFINE_INTRUSIVE_OPTIONAL(OptionalOwnedClxSpriteList, OwnedClxSpriteList, data_, nullptr)\r\n};\r\n\r\n/**\r\n * @brief Equivalent to `std::optional<OwnedClxSpriteSheet>` but smaller.\r\n */\r\nclass OptionalOwnedClxSpriteSheet {\r\npublic:\r\n\tDEFINE_INTRUSIVE_OPTIONAL(OptionalOwnedClxSpriteSheet, OwnedClxSpriteSheet, data_, nullptr)\r\n};\r\n\r\nclass OptionalOwnedClxSpriteListOrSheet {\r\npublic:\r\n\tDEFINE_INTRUSIVE_OPTIONAL(OptionalOwnedClxSpriteListOrSheet, OwnedClxSpriteListOrSheet, data_, nullptr);\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/demomode.cpp",
    "content": "#include \"engine/demomode.h\"\r\n\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <limits>\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"engine/events.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"gmenu.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"menu.h\"\r\n#include \"nthread.h\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"utils/console.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/endian_stream.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n// #define LOG_DEMOMODE_MESSAGES\r\n// #define LOG_DEMOMODE_MESSAGES_MOUSEMOTION\r\n// #define LOG_DEMOMODE_MESSAGES_RENDERING\r\n// #define LOG_DEMOMODE_MESSAGES_GAMETICK\r\n\r\nnamespace {\r\n\r\nconstexpr uint8_t Version = 3;\r\n\r\nenum class LoadingStatus : uint8_t {\r\n\tSuccess,\r\n\tFileNotFound,\r\n\tUnsupportedVersion,\r\n};\r\n\r\nstruct MouseMotionEventData {\r\n\tuint16_t x;\r\n\tuint16_t y;\r\n};\r\n\r\nstruct MouseButtonEventData {\r\n\tuint16_t x;\r\n\tuint16_t y;\r\n\tuint16_t mod;\r\n\tuint8_t button;\r\n};\r\n\r\nstruct MouseWheelEventData {\r\n\tint16_t x;\r\n\tint16_t y;\r\n\tuint16_t mod;\r\n};\r\n\r\nstruct KeyEventData {\r\n\tuint32_t sym;\r\n\tuint16_t mod;\r\n};\r\n\r\nstruct DemoMsg {\r\n\tenum EventType : uint8_t {\r\n\t\tGameTick = 0,\r\n\t\tRendering = 1,\r\n\r\n\t\t// Inputs:\r\n\t\tMinEvent = 8,\r\n\r\n\t\tQuitEvent = 8,\r\n\t\tMouseMotionEvent = 9,\r\n\t\tMouseButtonDownEvent = 10,\r\n\t\tMouseButtonUpEvent = 11,\r\n\t\tMouseWheelEvent = 12,\r\n\t\tKeyDownEvent = 13,\r\n\t\tKeyUpEvent = 14,\r\n\r\n\t\tMinCustomEvent = 64,\r\n\t};\r\n\r\n\tEventType type;\r\n\tuint8_t progressToNextGameTick;\r\n\tunion {\r\n\t\tMouseMotionEventData motion;\r\n\t\tMouseButtonEventData button;\r\n\t\tMouseWheelEventData wheel;\r\n\t\tKeyEventData key;\r\n\t};\r\n\r\n\t[[nodiscard]] bool isEvent() const\r\n\t{\r\n\t\treturn type >= MinEvent;\r\n\t}\r\n};\r\n\r\nFILE *DemoFile;\r\nint DemoFileVersion;\r\nint DemoNumber = -1;\r\nstd::optional<DemoMsg> CurrentDemoMessage;\r\n\r\nbool Timedemo = false;\r\nint RecordNumber = -1;\r\nbool CreateDemoReference = false;\r\n\r\n// These options affect gameplay and are stored in the demo file.\r\nstruct {\r\n\tuint8_t tickRate = 20;\r\n\tbool runInTown = false;\r\n\tbool theoQuest = false;\r\n\tbool cowQuest = false;\r\n\tbool autoGoldPickup = false;\r\n\tbool autoElixirPickup = false;\r\n\tbool autoOilPickup = false;\r\n\tbool autoPickupInTown = false;\r\n\tbool autoEquipWeapons = false;\r\n\tbool autoEquipArmor = false;\r\n\tbool autoEquipHelms = false;\r\n\tbool autoEquipShields = false;\r\n\tbool autoEquipJewelry = false;\r\n\tbool randomizeQuests = false;\r\n\tbool showItemLabels = false;\r\n\tbool autoRefillBelt = false;\r\n\tbool disableCripplingShrines = false;\r\n\tuint8_t numHealPotionPickup = 0;\r\n\tuint8_t numFullHealPotionPickup = 0;\r\n\tuint8_t numManaPotionPickup = 0;\r\n\tuint8_t numFullManaPotionPickup = 0;\r\n\tuint8_t numRejuPotionPickup = 0;\r\n\tuint8_t numFullRejuPotionPickup = 0;\r\n} DemoSettings;\r\n\r\nFILE *DemoRecording;\r\nuint32_t DemoModeLastTick = 0;\r\n\r\nint LogicTick = 0;\r\nuint32_t StartTime = 0;\r\n\r\nuint16_t DemoGraphicsWidth = 640;\r\nuint16_t DemoGraphicsHeight = 480;\r\n\r\nvoid ReadSettings(FILE *in, uint8_t version) // NOLINT(readability-identifier-length)\r\n{\r\n\tDemoGraphicsWidth = ReadLE16(in);\r\n\tDemoGraphicsHeight = ReadLE16(in);\r\n\tif (version > 0) {\r\n\t\tDemoSettings.runInTown = ReadByte(in) != 0;\r\n\t\tDemoSettings.theoQuest = ReadByte(in) != 0;\r\n\t\tDemoSettings.cowQuest = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoGoldPickup = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoElixirPickup = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoOilPickup = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoPickupInTown = ReadByte(in) != 0;\r\n\t\t(void)ReadByte(in); // adriaRefillsMana (removed feature, kept for backward compatibility)\r\n\t\tDemoSettings.autoEquipWeapons = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoEquipArmor = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoEquipHelms = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoEquipShields = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoEquipJewelry = ReadByte(in) != 0;\r\n\t\tDemoSettings.randomizeQuests = ReadByte(in) != 0;\r\n\t\tDemoSettings.showItemLabels = ReadByte(in) != 0;\r\n\t\tDemoSettings.autoRefillBelt = ReadByte(in) != 0;\r\n\t\tDemoSettings.disableCripplingShrines = ReadByte(in) != 0;\r\n\t\tDemoSettings.numHealPotionPickup = ReadByte(in);\r\n\t\tDemoSettings.numFullHealPotionPickup = ReadByte(in);\r\n\t\tDemoSettings.numManaPotionPickup = ReadByte(in);\r\n\t\tDemoSettings.numFullManaPotionPickup = ReadByte(in);\r\n\t\tDemoSettings.numRejuPotionPickup = ReadByte(in);\r\n\t\tDemoSettings.numFullRejuPotionPickup = ReadByte(in);\r\n\t} else {\r\n\t\tDemoSettings = {};\r\n\t}\r\n\r\n\tstd::string message = StrCat(\"⚙️\\n\", _(\"Resolution\"), \"=\", DemoGraphicsWidth, \"x\", DemoGraphicsHeight);\r\n\tfor (const auto &[key, value] : std::initializer_list<std::pair<std::string_view, bool>> {\r\n\t         { _(\"Run in Town\"), DemoSettings.runInTown },\r\n\t         { _(\"Theo Quest\"), DemoSettings.theoQuest },\r\n\t         { _(\"Cow Quest\"), DemoSettings.cowQuest },\r\n\t         { _(\"Auto Gold Pickup\"), DemoSettings.autoGoldPickup },\r\n\t         { _(\"Auto Elixir Pickup\"), DemoSettings.autoGoldPickup },\r\n\t         { _(\"Auto Oil Pickup\"), DemoSettings.autoOilPickup },\r\n\t         { _(\"Auto Pickup in Town\"), DemoSettings.autoPickupInTown },\r\n\t         { _(\"Auto Equip Weapons\"), DemoSettings.autoEquipWeapons },\r\n\t         { _(\"Auto Equip Armor\"), DemoSettings.autoEquipArmor },\r\n\t         { _(\"Auto Equip Helms\"), DemoSettings.autoEquipHelms },\r\n\t         { _(\"Auto Equip Shields\"), DemoSettings.autoEquipShields },\r\n\t         { _(\"Auto Equip Jewelry\"), DemoSettings.autoEquipJewelry },\r\n\t         { _(\"Randomize Quests\"), DemoSettings.randomizeQuests },\r\n\t         { _(\"Show Item Labels\"), DemoSettings.showItemLabels },\r\n\t         { _(\"Auto Refill Belt\"), DemoSettings.autoRefillBelt },\r\n\t         { _(\"Disable Crippling Shrines\"), DemoSettings.disableCripplingShrines } }) {\r\n\t\tStrAppend(message, \"\\n\", key, \"=\", value ? \"1\" : \"0\");\r\n\t}\r\n\tfor (const auto &[key, value] : std::initializer_list<std::pair<std::string_view, uint8_t>> {\r\n\t         { _(\"Heal Potion Pickup\"), DemoSettings.numHealPotionPickup },\r\n\t         { _(\"Full Heal Potion Pickup\"), DemoSettings.numFullHealPotionPickup },\r\n\t         { _(\"Mana Potion Pickup\"), DemoSettings.numManaPotionPickup },\r\n\t         { _(\"Full Mana Potion Pickup\"), DemoSettings.numFullManaPotionPickup },\r\n\t         { _(\"Rejuvenation Potion Pickup\"), DemoSettings.numRejuPotionPickup },\r\n\t         { _(\"Full Rejuvenation Potion Pickup\"), DemoSettings.numFullRejuPotionPickup } }) {\r\n\t\tStrAppend(message, \"\\n\", key, \"=\", static_cast<int>(value));\r\n\t}\r\n\tLog(\"{}\", message);\r\n}\r\n\r\nvoid WriteSettings(FILE *out)\r\n{\r\n\tWriteLE16(out, gnScreenWidth);\r\n\tWriteLE16(out, gnScreenHeight);\r\n\tconst Options &options = GetOptions();\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.runInTown));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.theoQuest));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.cowQuest));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoGoldPickup));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoElixirPickup));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoOilPickup));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoPickupInTown));\r\n\tWriteByte(out, 0); // adriaRefillsMana (removed feature, kept for backward compatibility)\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoEquipWeapons));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoEquipArmor));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoEquipHelms));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoEquipShields));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoEquipJewelry));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.randomizeQuests));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.showItemLabels));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.autoRefillBelt));\r\n\tWriteByte(out, static_cast<uint8_t>(*options.Gameplay.disableCripplingShrines));\r\n\tWriteByte(out, *options.Gameplay.numHealPotionPickup);\r\n\tWriteByte(out, *options.Gameplay.numFullHealPotionPickup);\r\n\tWriteByte(out, *options.Gameplay.numManaPotionPickup);\r\n\tWriteByte(out, *options.Gameplay.numFullManaPotionPickup);\r\n\tWriteByte(out, *options.Gameplay.numRejuPotionPickup);\r\n\tWriteByte(out, *options.Gameplay.numFullRejuPotionPickup);\r\n}\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nbool CreateSdlEvent(const DemoMsg &dmsg, SDL_Event &event, uint16_t &modState)\r\n{\r\n\tconst uint8_t type = dmsg.type;\r\n\tswitch (type) {\r\n\tcase DemoMsg::MouseMotionEvent:\r\n#ifdef USE_SDL3\r\n\t\tevent.type = SDL_EVENT_MOUSE_MOTION;\r\n\t\tevent.motion.state = 0;\r\n\t\tevent.motion.xrel = 0.F;\r\n\t\tevent.motion.yrel = 0.F;\r\n#else\r\n\t\tevent.type = SDL_MOUSEMOTION;\r\n#endif\r\n\t\tevent.motion.which = 0;\r\n\t\tevent.motion.x = dmsg.motion.x;\r\n\t\tevent.motion.y = dmsg.motion.y;\r\n\t\treturn true;\r\n\tcase DemoMsg::MouseButtonDownEvent:\r\n\tcase DemoMsg::MouseButtonUpEvent:\r\n#ifdef USE_SDL3\r\n\t\tevent.type = type == DemoMsg::MouseButtonDownEvent ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP;\r\n\t\tevent.button.down = type == DemoMsg::MouseButtonDownEvent;\r\n\t\tevent.button.clicks = 1;\r\n#else\r\n\t\tevent.type = type == DemoMsg::MouseButtonDownEvent ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP;\r\n\t\tevent.button.state = type == DemoMsg::MouseButtonDownEvent ? SDL_PRESSED : SDL_RELEASED;\r\n#endif\r\n\t\tevent.button.which = 0;\r\n\t\tevent.button.button = dmsg.button.button;\r\n\t\tevent.button.x = dmsg.button.x;\r\n\t\tevent.button.y = dmsg.button.y;\r\n\t\tmodState = dmsg.button.mod;\r\n\t\treturn true;\r\n\tcase DemoMsg::MouseWheelEvent:\r\n#ifdef USE_SDL3\r\n\t\tevent.type = SDL_EVENT_MOUSE_WHEEL;\r\n#if SDL_VERSION_ATLEAST(3, 2, 12)\r\n\t\tevent.wheel.integer_x = dmsg.wheel.x;\r\n\t\tevent.wheel.integer_y = dmsg.wheel.y;\r\n#else\r\n\t\tevent.wheel.x = dmsg.wheel.x;\r\n\t\tevent.wheel.y = dmsg.wheel.y;\r\n#endif\r\n\t\tevent.wheel.mouse_x = 0;\r\n\t\tevent.wheel.mouse_y = 0;\r\n#else\r\n\t\tevent.type = SDL_MOUSEWHEEL;\r\n#endif\r\n\t\tevent.wheel.which = 0;\r\n\t\tevent.wheel.x = dmsg.wheel.x;\r\n\t\tevent.wheel.y = dmsg.wheel.y;\r\n\t\tmodState = dmsg.wheel.mod;\r\n\t\treturn true;\r\n\tcase DemoMsg::KeyDownEvent:\r\n\tcase DemoMsg::KeyUpEvent:\r\n#ifdef USE_SDL3\r\n\t\tevent.type = type == DemoMsg::KeyDownEvent ? SDL_EVENT_KEY_DOWN : SDL_EVENT_KEY_UP;\r\n\t\tevent.key.down = type == DemoMsg::KeyDownEvent;\r\n\t\tevent.key.scancode = SDL_GetScancodeFromKey(dmsg.key.sym, nullptr);\r\n\t\tevent.key.key = dmsg.key.sym;\r\n\t\tevent.key.mod = dmsg.key.mod;\r\n#else\r\n\t\tevent.type = type == DemoMsg::KeyDownEvent ? SDL_KEYDOWN : SDL_KEYUP;\r\n\t\tevent.key.state = type == DemoMsg::KeyDownEvent ? SDL_PRESSED : SDL_RELEASED;\r\n\t\tevent.key.keysym.scancode = SDL_GetScancodeFromKey(dmsg.key.sym);\r\n\t\tevent.key.keysym.sym = dmsg.key.sym;\r\n\t\tevent.key.keysym.mod = dmsg.key.mod;\r\n#endif\r\n\t\treturn true;\r\n\tdefault:\r\n\t\tif (type >= DemoMsg::MinCustomEvent) {\r\n\t\t\tCustomEventToSdlEvent(event, static_cast<interface_mode>(type - DemoMsg::MinCustomEvent));\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tevent.type = static_cast<SDL_EventType>(0);\r\n\t\tLogWarn(\"Unsupported demo event (type={})\", type);\r\n\t\treturn false;\r\n\t}\r\n}\r\n#else\r\nSDLKey Sdl2ToSdl1Key(uint32_t key)\r\n{\r\n\tif ((key & (1 << 30)) != 0) {\r\n\t\tconstexpr uint32_t Keys1Start = 57;\r\n\t\tconstexpr SDLKey Keys1[] {\r\n\t\t\tSDLK_CAPSLOCK, SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6,\r\n\t\t\tSDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12,\r\n\t\t\tSDLK_PRINTSCREEN, SDLK_SCROLLLOCK, SDLK_PAUSE, SDLK_INSERT, SDLK_HOME,\r\n\t\t\tSDLK_PAGEUP, SDLK_DELETE, SDLK_END, SDLK_PAGEDOWN, SDLK_RIGHT, SDLK_LEFT,\r\n\t\t\tSDLK_DOWN, SDLK_UP, SDLK_NUMLOCKCLEAR, SDLK_KP_DIVIDE, SDLK_KP_MULTIPLY,\r\n\t\t\tSDLK_KP_MINUS, SDLK_KP_PLUS, SDLK_KP_ENTER, SDLK_KP_1, SDLK_KP_2,\r\n\t\t\tSDLK_KP_3, SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_7, SDLK_KP_8,\r\n\t\t\tSDLK_KP_9, SDLK_KP_0, SDLK_KP_PERIOD\r\n\t\t};\r\n\t\tconstexpr uint32_t Keys2Start = 224;\r\n\t\tconstexpr SDLKey Keys2[] {\r\n\t\t\tSDLK_LCTRL, SDLK_LSHIFT, SDLK_LALT, SDLK_LGUI, SDLK_RCTRL, SDLK_RSHIFT,\r\n\t\t\tSDLK_RALT, SDLK_RGUI, SDLK_MODE\r\n\t\t};\r\n\t\tconst uint32_t scancode = key & ~(1 << 30);\r\n\t\tif (scancode >= Keys1Start) {\r\n\t\t\tif (scancode < Keys1Start + sizeof(Keys1) / sizeof(Keys1[0]))\r\n\t\t\t\treturn Keys1[scancode - Keys1Start];\r\n\t\t\tif (scancode >= Keys2Start && scancode < Keys2Start + sizeof(Keys2) / sizeof(Keys2[0]))\r\n\t\t\t\treturn Keys2[scancode - Keys2Start];\r\n\t\t}\r\n\t\tLogWarn(\"Demo: unknown key {:d}\", key);\r\n\t\treturn SDLK_UNKNOWN;\r\n\t}\r\n\tif (key <= 122) {\r\n\t\treturn static_cast<SDLKey>(key);\r\n\t}\r\n\tLogWarn(\"Demo: unknown key {:d}\", key);\r\n\treturn SDLK_UNKNOWN;\r\n}\r\n\r\nuint8_t Sdl2ToSdl1MouseButton(uint8_t button)\r\n{\r\n\tswitch (button) {\r\n\tcase 4:\r\n\t\treturn SDL_BUTTON_X1;\r\n\tcase 5:\r\n\t\treturn SDL_BUTTON_X2;\r\n\tdefault:\r\n\t\treturn button;\r\n\t}\r\n}\r\n\r\nbool CreateSdlEvent(const DemoMsg &dmsg, SDL_Event &event, uint16_t &modState)\r\n{\r\n\tconst uint8_t type = dmsg.type;\r\n\tswitch (type) {\r\n\tcase DemoMsg::MouseMotionEvent:\r\n\t\tevent.type = SDL_MOUSEMOTION;\r\n\t\tevent.motion.which = 0;\r\n\t\tevent.motion.x = dmsg.motion.x;\r\n\t\tevent.motion.y = dmsg.motion.y;\r\n\t\treturn true;\r\n\tcase DemoMsg::MouseButtonDownEvent:\r\n\tcase DemoMsg::MouseButtonUpEvent:\r\n\t\tevent.type = type == DemoMsg::MouseButtonDownEvent ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP;\r\n\t\tevent.button.which = 0;\r\n\t\tevent.button.button = Sdl2ToSdl1MouseButton(dmsg.button.button);\r\n\t\tevent.button.state = type == DemoMsg::MouseButtonDownEvent ? SDL_PRESSED : SDL_RELEASED;\r\n\t\tevent.button.x = dmsg.button.x;\r\n\t\tevent.button.y = dmsg.button.y;\r\n\t\tmodState = dmsg.button.mod;\r\n\t\treturn true;\r\n\tcase DemoMsg::MouseWheelEvent:\r\n\t\tif (dmsg.wheel.y == 0) {\r\n\t\t\tLogWarn(\"Demo: unsupported event (mouse wheel y == 0)\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tevent.type = SDL_MOUSEBUTTONDOWN;\r\n\t\tevent.button.which = 0;\r\n\t\tevent.button.button = dmsg.wheel.y > 0 ? SDL_BUTTON_WHEELUP : SDL_BUTTON_WHEELDOWN;\r\n\t\tmodState = dmsg.wheel.mod;\r\n\t\treturn true;\r\n\tcase DemoMsg::KeyDownEvent:\r\n\tcase DemoMsg::KeyUpEvent:\r\n\t\tevent.type = type == DemoMsg::KeyDownEvent ? SDL_KEYDOWN : SDL_KEYUP;\r\n\t\tevent.key.which = 0;\r\n\t\tevent.key.state = type == DemoMsg::KeyDownEvent ? SDL_PRESSED : SDL_RELEASED;\r\n\t\tevent.key.keysym.sym = Sdl2ToSdl1Key(dmsg.key.sym);\r\n\t\tevent.key.keysym.mod = static_cast<SDL_Keymod>(dmsg.key.mod);\r\n\t\treturn true;\r\n\tdefault:\r\n\t\tif (type >= DemoMsg::MinCustomEvent) {\r\n\t\t\tCustomEventToSdlEvent(event, static_cast<interface_mode>(type - DemoMsg::MinCustomEvent));\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tevent.type = static_cast<SDL_EventType>(0);\r\n\t\tLogWarn(\"Demo: unsupported event (type={:x})\", type);\r\n\t\treturn false;\r\n\t}\r\n}\r\n#endif\r\n\r\nuint8_t MapPreV2DemoMsgEventType(uint16_t type)\r\n{\r\n\tswitch (type) {\r\n\tcase 0x100:\r\n\t\treturn DemoMsg::QuitEvent;\r\n\tcase 0x300:\r\n\t\treturn DemoMsg::KeyDownEvent;\r\n\tcase 0x301:\r\n\t\treturn DemoMsg::KeyUpEvent;\r\n\tcase 0x400:\r\n\t\treturn DemoMsg::MouseMotionEvent;\r\n\tcase 0x401:\r\n\t\treturn DemoMsg::MouseButtonDownEvent;\r\n\tcase 0x402:\r\n\t\treturn DemoMsg::MouseButtonUpEvent;\r\n\tcase 0x403:\r\n\t\treturn DemoMsg::MouseWheelEvent;\r\n\r\n\tdefault:\r\n\t\tif (type < 0x8000) { // SDL_USEREVENT\r\n\t\t\tapp_fatal(StrCat(\"Unknown event \", type));\r\n\t\t}\r\n\t\treturn DemoMsg::MinCustomEvent + (type - 0x8000);\r\n\t}\r\n}\r\n\r\nvoid LogDemoMessage(const DemoMsg &dmsg)\r\n{\r\n#ifdef LOG_DEMOMODE_MESSAGES\r\n\tconst uint8_t progressToNextGameTick = dmsg.progressToNextGameTick;\r\n\tswitch (dmsg.type) {\r\n\tcase DemoMsg::GameTick:\r\n#ifdef LOG_DEMOMODE_MESSAGES_GAMETICK\r\n\t\tLog(\"⏲️  GameTick {:>3}\", progressToNextGameTick);\r\n#endif\r\n\t\tbreak;\r\n\tcase DemoMsg::Rendering:\r\n#ifdef LOG_DEMOMODE_MESSAGES_RENDERING\r\n\t\tLog(\"🖼️  Rendering {:>3}\", progressToNextGameTick);\r\n#endif\r\n\t\tbreak;\r\n\tcase DemoMsg::MouseMotionEvent:\r\n#ifdef LOG_DEMOMODE_MESSAGES_MOUSEMOTION\r\n\t\tLog(\"🖱️  Message {:>3} MOUSEMOTION {} {}\", progressToNextGameTick,\r\n\t\t    dmsg.motion.x, dmsg.motion.y);\r\n#endif\r\n\t\tbreak;\r\n\tcase DemoMsg::MouseButtonDownEvent:\r\n\tcase DemoMsg::MouseButtonUpEvent:\r\n\t\tLog(\"🖱️  Message {:>3} {} {} {} {} 0x{:x}\", progressToNextGameTick,\r\n\t\t    dmsg.type == DemoMsg::MouseButtonDownEvent ? \"MOUSEBUTTONDOWN\" : \"MOUSEBUTTONUP\",\r\n\t\t    dmsg.button.button, dmsg.button.x, dmsg.button.y, dmsg.button.mod);\r\n\t\tbreak;\r\n\tcase DemoMsg::MouseWheelEvent:\r\n\t\tLog(\"🖱️  Message {:>3} MOUSEWHEEL {} {} 0x{:x}\", progressToNextGameTick,\r\n\t\t    dmsg.wheel.x, dmsg.wheel.y, dmsg.wheel.mod);\r\n\t\tbreak;\r\n\tcase DemoMsg::KeyDownEvent:\r\n\tcase DemoMsg::KeyUpEvent:\r\n\t\tLog(\"🔤 Message {:>3} {} 0x{:x} 0x{:x}\", progressToNextGameTick,\r\n\t\t    dmsg.type == DemoMsg::KeyDownEvent ? \"KEYDOWN\" : \"KEYUP\",\r\n\t\t    dmsg.key.sym, dmsg.key.mod);\r\n\t\tbreak;\r\n\tcase DemoMsg::QuitEvent:\r\n\t\tLog(\"❎  Message {:>3} QUIT\", progressToNextGameTick);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tLog(\"📨  Message {:>3} USEREVENT {}\", progressToNextGameTick, static_cast<uint8_t>(dmsg.type));\r\n\t\tbreak;\r\n\t}\r\n#endif // LOG_DEMOMODE_MESSAGES\r\n}\r\n\r\nvoid CloseDemoFile()\r\n{\r\n\tif (DemoFile != nullptr) {\r\n\t\tstd::fclose(DemoFile);\r\n\t\tDemoFile = nullptr;\r\n\t}\r\n}\r\n\r\nLoadingStatus OpenDemoFile(int demoNumber)\r\n{\r\n\tCloseDemoFile();\r\n\tconst std::string path = StrCat(paths::PrefPath(), \"demo_\", demoNumber, \".dmo\");\r\n\tDemoFile = OpenFile(path.c_str(), \"rb\");\r\n\tif (DemoFile == nullptr) {\r\n\t\treturn LoadingStatus::FileNotFound;\r\n\t}\r\n\tDemoFileVersion = ReadByte(DemoFile);\r\n\tif (DemoFileVersion > Version) {\r\n\t\treturn LoadingStatus::UnsupportedVersion;\r\n\t}\r\n\tDemoNumber = demoNumber;\r\n\r\n\tgSaveNumber = ReadLE32(DemoFile);\r\n\tReadSettings(DemoFile, DemoFileVersion);\r\n\r\n\treturn LoadingStatus::Success;\r\n}\r\n\r\nstd::optional<DemoMsg> ReadDemoMessage()\r\n{\r\n\tconst uint8_t typeNum = DemoFileVersion >= 2 ? ReadByte(DemoFile) : ReadLE32(DemoFile);\r\n\r\n\tif (std::feof(DemoFile) != 0) {\r\n\t\tCloseDemoFile();\r\n\t\treturn std::nullopt;\r\n\t}\r\n\r\n\t// Events with the high bit 1 are Rendering events with the rest of the bits used\r\n\t// to encode `progressToNextGameTick` inline.\r\n\tif ((typeNum & 0b10000000) != 0) {\r\n\t\tDemoModeLastTick = SDL_GetTicks();\r\n\t\treturn DemoMsg { DemoMsg::Rendering, static_cast<uint8_t>(typeNum & 0b01111111u), {} };\r\n\t}\r\n\tconst uint8_t progressToNextGameTick = ReadByte(DemoFile);\r\n\r\n\tswitch (typeNum) {\r\n\tcase DemoMsg::GameTick:\r\n\tcase DemoMsg::Rendering:\r\n\t\tDemoModeLastTick = SDL_GetTicks();\r\n\t\treturn DemoMsg { static_cast<DemoMsg::EventType>(typeNum), progressToNextGameTick, {} };\r\n\tdefault: {\r\n\t\tconst uint8_t eventType = DemoFileVersion >= 2 ? typeNum : MapPreV2DemoMsgEventType(static_cast<uint16_t>(ReadLE32(DemoFile)));\r\n\t\tDemoMsg result { static_cast<DemoMsg::EventType>(eventType), progressToNextGameTick, {} };\r\n\t\tswitch (eventType) {\r\n\t\tcase DemoMsg::MouseMotionEvent: {\r\n\t\t\tresult.motion.x = ReadLE16(DemoFile);\r\n\t\t\tresult.motion.y = ReadLE16(DemoFile);\r\n\t\t} break;\r\n\t\tcase DemoMsg::MouseButtonDownEvent:\r\n\t\tcase DemoMsg::MouseButtonUpEvent: {\r\n\t\t\tresult.button.button = ReadByte(DemoFile);\r\n\t\t\tresult.button.x = ReadLE16(DemoFile);\r\n\t\t\tresult.button.y = ReadLE16(DemoFile);\r\n\t\t\tresult.button.mod = ReadLE16(DemoFile);\r\n\t\t} break;\r\n\t\tcase DemoMsg::MouseWheelEvent: {\r\n\t\t\tresult.wheel.x = DemoFileVersion >= 2 ? ReadLE16<int16_t>(DemoFile) : static_cast<int16_t>(ReadLE32<int32_t>(DemoFile));\r\n\t\t\tresult.wheel.y = DemoFileVersion >= 2 ? ReadLE16<int16_t>(DemoFile) : static_cast<int16_t>(ReadLE32<int32_t>(DemoFile));\r\n\t\t\tresult.wheel.mod = ReadLE16(DemoFile);\r\n\t\t} break;\r\n\t\tcase DemoMsg::KeyDownEvent:\r\n\t\tcase DemoMsg::KeyUpEvent: {\r\n\t\t\tresult.key.sym = static_cast<SDL_Keycode>(ReadLE32(DemoFile));\r\n\t\t\tresult.key.mod = static_cast<SDL_Keymod>(ReadLE16(DemoFile));\r\n\t\t} break;\r\n\t\tcase DemoMsg::QuitEvent: // SDL_QUIT\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tif (eventType < DemoMsg::MinCustomEvent) {\r\n\t\t\t\tapp_fatal(StrCat(\"Unknown event \", eventType));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tDemoModeLastTick = SDL_GetTicks();\r\n\t\treturn result;\r\n\t} break;\r\n\t}\r\n}\r\n\r\nvoid WriteDemoMsgHeader(DemoMsg::EventType type)\r\n{\r\n\tif (type == DemoMsg::Rendering && ProgressToNextGameTick <= 127) {\r\n\t\tWriteByte(DemoRecording, ProgressToNextGameTick | 0b10000000);\r\n\t\treturn;\r\n\t}\r\n\tWriteByte(DemoRecording, type);\r\n\tWriteByte(DemoRecording, ProgressToNextGameTick);\r\n}\r\n\r\n} // namespace\r\n\r\nnamespace demo {\r\n\r\nvoid InitPlayBack(int demoNumber, bool timedemo)\r\n{\r\n\tTimedemo = timedemo;\r\n\tControlMode = ControlTypes::KeyboardAndMouse;\r\n\r\n\tconst LoadingStatus status = OpenDemoFile(demoNumber);\r\n\tswitch (status) {\r\n\tcase LoadingStatus::Success:\r\n\t\treturn;\r\n\tcase LoadingStatus::FileNotFound:\r\n\t\tprintInConsole(\"Demo file not found\");\r\n\t\tbreak;\r\n\tcase LoadingStatus::UnsupportedVersion:\r\n\t\tprintInConsole(\"Unsupported Demo version\");\r\n\t\tbreak;\r\n\t}\r\n\tprintNewlineInConsole();\r\n\tdiablo_quit(1);\r\n}\r\n\r\nvoid InitRecording(int recordNumber, bool createDemoReference)\r\n{\r\n\tRecordNumber = recordNumber;\r\n\tCreateDemoReference = createDemoReference;\r\n}\r\nvoid OverrideOptions()\r\n{\r\n#ifndef USE_SDL1\r\n\tGetOptions().Graphics.fitToScreen.SetValue(false);\r\n#endif\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tGetOptions().Graphics.hardwareCursor.SetValue(false);\r\n#endif\r\n\tif (Timedemo) {\r\n\t\tGetOptions().Graphics.frameRateControl.SetValue(FrameRateControl::None);\r\n\t}\r\n\tforceResolution = Size(DemoGraphicsWidth, DemoGraphicsHeight);\r\n\r\n\tOptions &options = GetOptions();\r\n\toptions.Gameplay.runInTown.SetValue(DemoSettings.runInTown);\r\n\toptions.Gameplay.theoQuest.SetValue(DemoSettings.theoQuest);\r\n\toptions.Gameplay.cowQuest.SetValue(DemoSettings.cowQuest);\r\n\toptions.Gameplay.autoGoldPickup.SetValue(DemoSettings.autoGoldPickup);\r\n\toptions.Gameplay.autoElixirPickup.SetValue(DemoSettings.autoElixirPickup);\r\n\toptions.Gameplay.autoOilPickup.SetValue(DemoSettings.autoOilPickup);\r\n\toptions.Gameplay.autoPickupInTown.SetValue(DemoSettings.autoPickupInTown);\r\n\toptions.Gameplay.autoEquipWeapons.SetValue(DemoSettings.autoEquipWeapons);\r\n\toptions.Gameplay.autoEquipArmor.SetValue(DemoSettings.autoEquipArmor);\r\n\toptions.Gameplay.autoEquipHelms.SetValue(DemoSettings.autoEquipHelms);\r\n\toptions.Gameplay.autoEquipShields.SetValue(DemoSettings.autoEquipShields);\r\n\toptions.Gameplay.autoEquipJewelry.SetValue(DemoSettings.autoEquipJewelry);\r\n\toptions.Gameplay.randomizeQuests.SetValue(DemoSettings.randomizeQuests);\r\n\toptions.Gameplay.showItemLabels.SetValue(DemoSettings.showItemLabels);\r\n\toptions.Gameplay.autoRefillBelt.SetValue(DemoSettings.autoRefillBelt);\r\n\toptions.Gameplay.disableCripplingShrines.SetValue(DemoSettings.disableCripplingShrines);\r\n\toptions.Gameplay.numHealPotionPickup.SetValue(DemoSettings.numHealPotionPickup);\r\n\toptions.Gameplay.numFullHealPotionPickup.SetValue(DemoSettings.numFullHealPotionPickup);\r\n\toptions.Gameplay.numManaPotionPickup.SetValue(DemoSettings.numManaPotionPickup);\r\n\toptions.Gameplay.numFullManaPotionPickup.SetValue(DemoSettings.numFullManaPotionPickup);\r\n\toptions.Gameplay.numRejuPotionPickup.SetValue(DemoSettings.numRejuPotionPickup);\r\n\toptions.Gameplay.numFullRejuPotionPickup.SetValue(DemoSettings.numFullRejuPotionPickup);\r\n}\r\n\r\nbool IsRunning()\r\n{\r\n\treturn DemoNumber != -1;\r\n}\r\n\r\nbool IsRecording()\r\n{\r\n\treturn RecordNumber != -1;\r\n}\r\n\r\nbool GetRunGameLoop(bool &drawGame, bool &processInput)\r\n{\r\n\tif (CurrentDemoMessage == std::nullopt && DemoFile != nullptr)\r\n\t\tCurrentDemoMessage = ReadDemoMessage();\r\n\tif (CurrentDemoMessage == std::nullopt)\r\n\t\tapp_fatal(\"Demo queue empty\");\r\n\r\n\tconst DemoMsg &dmsg = *CurrentDemoMessage;\r\n\r\n\tif (CurrentDemoMessage->isEvent())\r\n\t\tapp_fatal(\"Unexpected event demo message in GetRunGameLoop\");\r\n\tLogDemoMessage(dmsg);\r\n\tif (Timedemo) {\r\n\t\t// disable additional rendering to speedup replay\r\n\t\tdrawGame = dmsg.type == DemoMsg::GameTick && !HeadlessMode;\r\n\t} else {\r\n\t\tconst int currentTickCount = SDL_GetTicks();\r\n\t\tconst int ticksElapsed = currentTickCount - DemoModeLastTick;\r\n\t\tconst bool tickDue = ticksElapsed >= gnTickDelay;\r\n\t\tdrawGame = false;\r\n\t\tif (tickDue) {\r\n\t\t\tif (dmsg.type == DemoMsg::GameTick) {\r\n\t\t\t\tDemoModeLastTick = currentTickCount;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tint32_t fraction = ticksElapsed * AnimationInfo::baseValueFraction / gnTickDelay;\r\n\t\t\tfraction = std::clamp<int32_t>(fraction, 0, AnimationInfo::baseValueFraction);\r\n\t\t\tconst uint8_t progressToNextGameTick = static_cast<uint8_t>(fraction);\r\n\t\t\tif (dmsg.type == DemoMsg::GameTick || dmsg.progressToNextGameTick > progressToNextGameTick) {\r\n\t\t\t\t// we are ahead of the replay => add a additional rendering for smoothness\r\n\t\t\t\tif (gbRunGame && PauseMode == 0 && (gbIsMultiplayer || !gmenu_is_active()) && gbProcessPlayers) // if game is not running or paused there is no next gametick in the near future\r\n\t\t\t\t\tProgressToNextGameTick = progressToNextGameTick;\r\n\t\t\t\tprocessInput = false;\r\n\t\t\t\tdrawGame = true;\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tProgressToNextGameTick = dmsg.progressToNextGameTick;\r\n\tconst bool isGameTick = dmsg.type == DemoMsg::GameTick;\r\n\tCurrentDemoMessage = std::nullopt;\r\n\tif (isGameTick)\r\n\t\tLogicTick++;\r\n\treturn isGameTick;\r\n}\r\n\r\nbool FetchMessage(SDL_Event *event, uint16_t *modState)\r\n{\r\n\tif (CurrentEventHandler == DisableInputEventHandler)\r\n\t\treturn false;\r\n\r\n\tSDL_Event e;\r\n\tif (\r\n#ifdef USE_SDL3\r\n\t    SDL_PollEvent(&e)\r\n#else\r\n\t    SDL_PollEvent(&e) != 0\r\n#endif\r\n\t) {\r\n\t\tif (e.type ==\r\n#ifdef USE_SDL3\r\n\t\t    SDL_EVENT_QUIT\r\n#else\r\n\t\t    SDL_QUIT\r\n#endif\r\n\t\t) {\r\n\t\t\t*event = e;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (e.type ==\r\n#ifdef USE_SDL3\r\n\t\t    SDL_EVENT_KEY_DOWN\r\n#else\r\n\t\t    SDL_KEYDOWN\r\n#endif\r\n\t\t) {\r\n\t\t\tconst SDL_Keycode key =\r\n#ifdef USE_SDL3\r\n\t\t\t    e.key.key;\r\n#else\r\n\t\t\t    e.key.keysym.sym;\r\n#endif\r\n\t\t\tif (key == SDLK_ESCAPE) {\r\n\t\t\t\tCloseDemoFile();\r\n\t\t\t\tCurrentDemoMessage = std::nullopt;\r\n\t\t\t\tDemoNumber = -1;\r\n\t\t\t\tTimedemo = false;\r\n\t\t\t\tlast_tick = SDL_GetTicks();\r\n\t\t\t} else if (IsAnyOf(key, SDLK_KP_PLUS, SDLK_PLUS) && sgGameInitInfo.nTickRate < 255) {\r\n\t\t\t\tsgGameInitInfo.nTickRate++;\r\n\t\t\t\tGetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate);\r\n\t\t\t\tgnTickDelay = 1000 / sgGameInitInfo.nTickRate;\r\n\t\t\t} else if (IsAnyOf(key, SDLK_KP_MINUS, SDLK_MINUS) && sgGameInitInfo.nTickRate > 1) {\r\n\t\t\t\tsgGameInitInfo.nTickRate--;\r\n\t\t\t\tGetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate);\r\n\t\t\t\tgnTickDelay = 1000 / sgGameInitInfo.nTickRate;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (CurrentDemoMessage == std::nullopt && DemoFile != nullptr)\r\n\t\tCurrentDemoMessage = ReadDemoMessage();\r\n\tif (CurrentDemoMessage != std::nullopt) {\r\n\t\tconst DemoMsg &dmsg = *CurrentDemoMessage;\r\n\t\tLogDemoMessage(dmsg);\r\n\t\tif (dmsg.isEvent()) {\r\n\t\t\tconst bool hasEvent = CreateSdlEvent(dmsg, *event, *modState);\r\n\t\t\tProgressToNextGameTick = dmsg.progressToNextGameTick;\r\n\t\t\tCurrentDemoMessage = std::nullopt;\r\n\t\t\treturn hasEvent;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid RecordGameLoopResult(bool runGameLoop)\r\n{\r\n\tWriteDemoMsgHeader(runGameLoop ? DemoMsg::GameTick : DemoMsg::Rendering);\r\n\r\n\tif (runGameLoop && !IsRunning())\r\n\t\tLogicTick++;\r\n}\r\n\r\nvoid RecordMessage(const SDL_Event &event, uint16_t modState)\r\n{\r\n\tif (!gbRunGame || DemoRecording == nullptr)\r\n\t\treturn;\r\n\tif (CurrentEventHandler == DisableInputEventHandler)\r\n\t\treturn;\r\n\tswitch (event.type) {\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_MOUSE_MOTION:\r\n#else\r\n\tcase SDL_MOUSEMOTION:\r\n#endif\r\n\t\tWriteDemoMsgHeader(DemoMsg::MouseMotionEvent);\r\n\t\tWriteLE16(DemoRecording, event.motion.x);\r\n\t\tWriteLE16(DemoRecording, event.motion.y);\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n#else\r\n\tcase SDL_MOUSEBUTTONDOWN:\r\n\tcase SDL_MOUSEBUTTONUP:\r\n#endif\r\n#ifdef USE_SDL1\r\n\t\tif (event.button.button == SDL_BUTTON_WHEELUP || event.button.button == SDL_BUTTON_WHEELDOWN) {\r\n\t\t\tWriteDemoMsgHeader(DemoMsg::MouseWheelEvent);\r\n\t\t\tWriteLE16(DemoRecording, 0);\r\n\t\t\tWriteLE16(DemoRecording, event.button.button == SDL_BUTTON_WHEELUP ? 1 : -1);\r\n\t\t\tWriteLE16(DemoRecording, modState);\r\n\t\t} else {\r\n#endif\r\n\t\t\tWriteDemoMsgHeader(\r\n#ifdef USE_SDL3\r\n\t\t\t    event.button.down\r\n#else\r\n\t\t    event.type == SDL_MOUSEBUTTONDOWN\r\n#endif\r\n\t\t\t        ? DemoMsg::MouseButtonDownEvent\r\n\t\t\t        : DemoMsg::MouseButtonUpEvent);\r\n\t\t\tWriteByte(DemoRecording, event.button.button);\r\n\t\t\tWriteLE16(DemoRecording, event.button.x);\r\n\t\t\tWriteLE16(DemoRecording, event.button.y);\r\n\t\t\tWriteLE16(DemoRecording, modState);\r\n#ifdef USE_SDL1\r\n\t\t}\r\n#endif\r\n\t\tbreak;\r\n#ifndef USE_SDL1\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_MOUSE_WHEEL:\r\n#else\r\n\tcase SDL_MOUSEWHEEL:\r\n#endif\r\n\t\tWriteDemoMsgHeader(DemoMsg::MouseWheelEvent);\r\n\r\n#ifdef USE_SDL3\r\n\t\tint wheelX, wheelY;\r\n#if SDL_VERSION_ATLEAST(3, 2, 12)\r\n\t\twheelX = event.wheel.integer_x;\r\n\t\twheelY = event.wheel.integer_y;\r\n#else\r\n\t\twheelX = event.wheel.x;\r\n\t\twheelY = event.wheel.y;\r\n#endif\r\n\t\tif (wheelX < std::numeric_limits<int16_t>::min()\r\n\t\t    || wheelX > std::numeric_limits<int16_t>::max()\r\n\t\t    || wheelY < std::numeric_limits<int16_t>::min()\r\n\t\t    || wheelY > std::numeric_limits<int16_t>::max()) {\r\n\t\t\tapp_fatal(StrCat(\"Mouse wheel event integer_x/y out of int16_t range. x=\",\r\n\t\t\t    wheelX, \" y=\", wheelY));\r\n\t\t}\r\n\t\tWriteLE16(DemoRecording, wheelX);\r\n\t\tWriteLE16(DemoRecording, wheelY);\r\n#else\r\n\t\tif (event.wheel.x < std::numeric_limits<int16_t>::min()\r\n\t\t    || event.wheel.x > std::numeric_limits<int16_t>::max()\r\n\t\t    || event.wheel.y < std::numeric_limits<int16_t>::min()\r\n\t\t    || event.wheel.y > std::numeric_limits<int16_t>::max()) {\r\n\t\t\tapp_fatal(StrCat(\"Mouse wheel event x/y out of int16_t range. x=\",\r\n\t\t\t    event.wheel.x, \" y=\", event.wheel.y));\r\n\t\t}\r\n\t\tWriteLE16(DemoRecording, event.wheel.x);\r\n\t\tWriteLE16(DemoRecording, event.wheel.y);\r\n#endif\r\n\t\tWriteLE16(DemoRecording, modState);\r\n\t\tbreak;\r\n#endif\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_KEY_DOWN:\r\n\tcase SDL_EVENT_KEY_UP:\r\n\t\tWriteDemoMsgHeader(event.key.down ? DemoMsg::KeyDownEvent : DemoMsg::KeyUpEvent);\r\n\t\tWriteLE32(DemoRecording, static_cast<uint32_t>(event.key.key));\r\n\t\tWriteLE16(DemoRecording, static_cast<uint16_t>(event.key.mod));\r\n\t\tbreak;\r\n#else\r\n\tcase SDL_KEYDOWN:\r\n\tcase SDL_KEYUP:\r\n\t\tWriteDemoMsgHeader(event.type == SDL_KEYDOWN ? DemoMsg::KeyDownEvent : DemoMsg::KeyUpEvent);\r\n\t\tWriteLE32(DemoRecording, static_cast<uint32_t>(event.key.keysym.sym));\r\n\t\tWriteLE16(DemoRecording, static_cast<uint16_t>(event.key.keysym.mod));\r\n\t\tbreak;\r\n#endif\r\n#ifndef USE_SDL1\r\n#ifndef USE_SDL3\r\n\tcase SDL_WINDOWEVENT:\r\n\t\tif (event.window.type == SDL_WINDOWEVENT_CLOSE) {\r\n\t\t\tWriteDemoMsgHeader(DemoMsg::QuitEvent);\r\n\t\t}\r\n\t\tbreak;\r\n#endif\r\n#endif\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_QUIT:\r\n#else\r\n\tcase SDL_QUIT:\r\n#endif\r\n\t\tWriteDemoMsgHeader(DemoMsg::QuitEvent);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tif (IsCustomEvent(event.type)) {\r\n\t\t\tWriteDemoMsgHeader(static_cast<DemoMsg::EventType>(\r\n\t\t\t    DemoMsg::MinCustomEvent + static_cast<uint8_t>(GetCustomEvent(event))));\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid NotifyGameLoopStart()\r\n{\r\n\tLogicTick = 0;\r\n\r\n\tif (IsRunning()) {\r\n\t\tStartTime = SDL_GetTicks();\r\n\t}\r\n\r\n\tif (IsRecording()) {\r\n\t\tconst std::string path = StrCat(paths::PrefPath(), \"demo_\", RecordNumber, \".dmo\");\r\n\t\tDemoRecording = OpenFile(path.c_str(), \"wb\");\r\n\t\tif (DemoRecording == nullptr) {\r\n\t\t\tRecordNumber = -1;\r\n\t\t\tLogError(\"Failed to open {} for writing\", path);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tWriteByte(DemoRecording, Version);\r\n\t\tWriteLE32(DemoRecording, gSaveNumber);\r\n\t\tWriteSettings(DemoRecording);\r\n\t}\r\n}\r\n\r\nvoid NotifyGameLoopEnd()\r\n{\r\n\tif (IsRecording()) {\r\n\t\tstd::fclose(DemoRecording);\r\n\t\tDemoRecording = nullptr;\r\n\t\tif (CreateDemoReference)\r\n\t\t\tpfile_write_hero_demo(RecordNumber);\r\n\r\n\t\tRecordNumber = -1;\r\n\t\tCreateDemoReference = false;\r\n\t}\r\n\r\n\tif (IsRunning() && !HeadlessMode) {\r\n\t\tconst float seconds = (SDL_GetTicks() - StartTime) / 1000.0F;\r\n\t\tLog(\"{} frames, {:.2f} seconds: {:.1f} fps\", LogicTick, seconds, LogicTick / seconds);\r\n\t\tgbRunGameResult = false;\r\n\t\tgbRunGame = false;\r\n\r\n\t\tHeroCompareResult compareResult = pfile_compare_hero_demo(DemoNumber, false);\r\n\t\tswitch (compareResult.status) {\r\n\t\tcase HeroCompareResult::ReferenceNotFound:\r\n\t\t\tLog(\"Timedemo: No final comparison because reference is not present.\");\r\n\t\t\tbreak;\r\n\t\tcase HeroCompareResult::Same:\r\n\t\t\tLog(\"Timedemo: Same outcome as initial run. :)\");\r\n\t\t\tbreak;\r\n\t\tcase HeroCompareResult::Difference:\r\n\t\t\tLog(\"Timedemo: Different outcome than initial run. ;(\\n{}\", compareResult.message);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nuint32_t SimulateMillisecondsSinceStartup()\r\n{\r\n\treturn LogicTick * 50;\r\n}\r\n\r\n} // namespace demo\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/demomode.h",
    "content": "/**\r\n * @file demomode.h\r\n *\r\n * Contains most of the the demomode specific logic\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace demo {\r\n\r\n#ifndef DISABLE_DEMOMODE\r\nvoid InitPlayBack(int demoNumber, bool timedemo);\r\nvoid InitRecording(int recordNumber, bool createDemoReference);\r\nvoid OverrideOptions();\r\n\r\nbool IsRunning();\r\nbool IsRecording();\r\n\r\nbool GetRunGameLoop(bool &drawGame, bool &processInput);\r\nbool FetchMessage(SDL_Event *event, uint16_t *modState);\r\nvoid RecordGameLoopResult(bool runGameLoop);\r\nvoid RecordMessage(const SDL_Event &event, uint16_t modState);\r\n\r\nvoid NotifyGameLoopStart();\r\nvoid NotifyGameLoopEnd();\r\n\r\nuint32_t SimulateMillisecondsSinceStartup();\r\n#else\r\ninline void OverrideOptions()\r\n{\r\n}\r\ninline bool IsRunning()\r\n{\r\n\treturn false;\r\n}\r\ninline bool IsRecording()\r\n{\r\n\treturn false;\r\n}\r\ninline bool GetRunGameLoop(bool &, bool &)\r\n{\r\n\treturn false;\r\n}\r\ninline bool FetchMessage(SDL_Event *, uint16_t *)\r\n{\r\n\treturn false;\r\n}\r\ninline void RecordGameLoopResult(bool)\r\n{\r\n}\r\ninline void RecordMessage(const SDL_Event &, uint16_t)\r\n{\r\n}\r\ninline void NotifyGameLoopStart()\r\n{\r\n}\r\ninline void NotifyGameLoopEnd()\r\n{\r\n}\r\ninline uint32_t SimulateMillisecondsSinceStartup()\r\n{\r\n\treturn 0;\r\n}\r\n#endif\r\n\r\n} // namespace demo\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/direction.cpp",
    "content": "#include \"engine/direction.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::string_view DirectionToString(Direction direction)\r\n{\r\n\tswitch (direction) {\r\n\tcase Direction::South:\r\n\t\treturn \"South\";\r\n\tcase Direction::SouthWest:\r\n\t\treturn \"SouthWest\";\r\n\tcase Direction::West:\r\n\t\treturn \"West\";\r\n\tcase Direction::NorthWest:\r\n\t\treturn \"NorthWest\";\r\n\tcase Direction::North:\r\n\t\treturn \"North\";\r\n\tcase Direction::NorthEast:\r\n\t\treturn \"NorthEast\";\r\n\tcase Direction::East:\r\n\t\treturn \"East\";\r\n\tcase Direction::SouthEast:\r\n\t\treturn \"SouthEast\";\r\n\tcase Direction::NoDirection:\r\n\t\treturn \"\";\r\n\t}\r\n\treturn \"Invalid\";\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/direction.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <string_view>\r\n#include <type_traits>\r\n\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class Direction : std::uint8_t {\r\n\tSouth,\r\n\tSouthWest,\r\n\tWest,\r\n\tNorthWest,\r\n\tNorth,\r\n\tNorthEast,\r\n\tEast,\r\n\tSouthEast,\r\n\tNoDirection\r\n};\r\n\r\n/** Maps from direction to a left turn from the direction. */\r\nDVL_ALWAYS_INLINE constexpr Direction Left(Direction facing)\r\n{\r\n\t// Direction left[8] = { Direction::SouthEast, Direction::South, Direction::SouthWest, Direction::West, Direction::NorthWest, Direction::North, Direction::NorthEast, Direction::East };\r\n\treturn static_cast<Direction>((static_cast<std::underlying_type_t<Direction>>(facing) + 7) % 8);\r\n}\r\n\r\n/** Maps from direction to a right turn from the direction. */\r\nDVL_ALWAYS_INLINE constexpr Direction Right(Direction facing)\r\n{\r\n\t// Direction right[8] = { Direction::SouthWest, Direction::West, Direction::NorthWest, Direction::North, Direction::NorthEast, Direction::East, Direction::SouthEast, Direction::South };\r\n\treturn static_cast<Direction>((static_cast<std::underlying_type_t<Direction>>(facing) + 1) % 8);\r\n}\r\n\r\n/** Maps from direction to the opposite direction. */\r\nDVL_ALWAYS_INLINE constexpr Direction Opposite(Direction facing)\r\n{\r\n\t// Direction opposite[8] = { Direction::North, Direction::NorthEast, Direction::East, Direction::SouthEast, Direction::South, Direction::SouthWest, Direction::West, Direction::NorthWest };\r\n\treturn static_cast<Direction>((static_cast<std::underlying_type_t<Direction>>(facing) + 4) % 8);\r\n}\r\n\r\nstd::string_view DirectionToString(Direction direction);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/displacement.hpp",
    "content": "#pragma once\r\n\r\n#include <cmath>\r\n#include <limits>\r\n\r\n#ifdef BUILD_TESTING\r\n#include <ostream>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"engine/direction.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename DeltaT>\r\nstruct DisplacementOf;\r\n\r\nusing Displacement = DisplacementOf<int>;\r\n\r\ntemplate <typename DeltaT>\r\nstruct DisplacementOf {\r\n\tDeltaT deltaX;\r\n\tDeltaT deltaY;\r\n\r\n\tDisplacementOf() = default;\r\n\r\n\ttemplate <typename DisplacementDeltaT>\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf(DisplacementOf<DisplacementDeltaT> other)\r\n\t    : deltaX(other.deltaX)\r\n\t    , deltaY(other.deltaY)\r\n\t{\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf(DeltaT deltaX, DeltaT deltaY)\r\n\t    : deltaX(deltaX)\r\n\t    , deltaY(deltaY)\r\n\t{\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE explicit constexpr DisplacementOf(DeltaT delta)\r\n\t    : deltaX(delta)\r\n\t    , deltaY(delta)\r\n\t{\r\n\t}\r\n\r\n\ttemplate <typename SizeT>\r\n\tDVL_ALWAYS_INLINE explicit constexpr DisplacementOf(const SizeOf<SizeT> &size)\r\n\t    : deltaX(size.width)\r\n\t    , deltaY(size.height)\r\n\t{\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE explicit constexpr DisplacementOf(Direction direction)\r\n\t    : DisplacementOf(fromDirection(direction))\r\n\t{\r\n\t}\r\n\r\n\ttemplate <typename DisplacementDeltaT>\r\n\tDVL_ALWAYS_INLINE constexpr bool operator==(const DisplacementOf<DisplacementDeltaT> &other) const\r\n\t{\r\n\t\treturn deltaX == other.deltaX && deltaY == other.deltaY;\r\n\t}\r\n\r\n\ttemplate <typename DisplacementDeltaT>\r\n\tDVL_ALWAYS_INLINE constexpr bool operator!=(const DisplacementOf<DisplacementDeltaT> &other) const\r\n\t{\r\n\t\treturn !(*this == other);\r\n\t}\r\n\r\n\ttemplate <typename DisplacementDeltaT = DeltaT>\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> &operator+=(DisplacementOf<DisplacementDeltaT> displacement)\r\n\t{\r\n\t\tdeltaX += displacement.deltaX;\r\n\t\tdeltaY += displacement.deltaY;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\ttemplate <typename DisplacementDeltaT = DeltaT>\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> &operator-=(DisplacementOf<DisplacementDeltaT> displacement)\r\n\t{\r\n\t\tdeltaX -= displacement.deltaX;\r\n\t\tdeltaY -= displacement.deltaY;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> &operator*=(const int factor)\r\n\t{\r\n\t\tdeltaX *= factor;\r\n\t\tdeltaY *= factor;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> &operator*=(const float factor)\r\n\t{\r\n\t\tdeltaX = static_cast<DeltaT>(deltaX * factor);\r\n\t\tdeltaY = static_cast<DeltaT>(deltaY * factor);\r\n\t\treturn *this;\r\n\t}\r\n\r\n\ttemplate <typename DeltaU>\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> &operator*=(const DisplacementOf<DeltaU> factor)\r\n\t{\r\n\t\tdeltaX = static_cast<DeltaT>(deltaX * factor.deltaX);\r\n\t\tdeltaY = static_cast<DeltaT>(deltaY * factor.deltaY);\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> &operator/=(const int factor)\r\n\t{\r\n\t\tdeltaX /= factor;\r\n\t\tdeltaY /= factor;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> &operator/=(const float factor)\r\n\t{\r\n\t\tdeltaX = static_cast<DeltaT>(deltaX / factor);\r\n\t\tdeltaY = static_cast<DeltaT>(deltaY / factor);\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE float magnitude() const\r\n\t{\r\n\t\t// If [x * x <= max], then [x <= max / x] for x > 0\r\n\t\tassert(deltaX == 0 || std::abs(deltaX) <= std::numeric_limits<DeltaT>::max() / std::abs(deltaX));\r\n\t\tassert(deltaY == 0 || std::abs(deltaY) <= std::numeric_limits<DeltaT>::max() / std::abs(deltaY));\r\n\r\n\t\t// If [x + y <= max], then [x <= max - y]\r\n\t\tassert(deltaX * deltaX <= std::numeric_limits<DeltaT>::max() - deltaY * deltaY);\r\n\r\n\t\t// Maximum precision of float is 24 bits\r\n\t\tassert(deltaX * deltaX + deltaY * deltaY < (1 << 24));\r\n\r\n\t\t// We do not use `std::hypot` here because it is slower and we do not need the extra precision.\r\n\t\treturn sqrtf(static_cast<float>(deltaX * deltaX + deltaY * deltaY));\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a new Displacement object in screen coordinates.\r\n\t *\r\n\t * Transforming from world space to screen space involves a rotation of -135° and scaling to fit within a 64x32 pixel tile (since Diablo uses isometric projection)\r\n\t * 32 and 16 are used as the x/y scaling factors being half the relevant max dimension, the rotation matrix is [[-, +], [-, -]] as sin(-135°) = cos(-135°) = ~-0.7.\r\n\t *\r\n\t * [-32,  32] [dx] = [-32dx +  32dy] = [  32dy - 32dx ] = [ 32(dy - dx)]\r\n\t * [-16, -16] [dy] = [-16dx + -16dy] = [-(16dy + 16dx)] = [-16(dy + dx)]\r\n\t *\r\n\t * @return A representation of the original displacement in screen coordinates.\r\n\t */\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> worldToScreen() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for transformations involving a rotation\");\r\n\t\treturn { (deltaY - deltaX) * 32, (deltaY + deltaX) * -16 };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a new Displacement object in world coordinates.\r\n\t *\r\n\t * This is an inverse matrix of the worldToScreen transformation.\r\n\t *\r\n\t * @return A representation of the original displacement in world coordinates.\r\n\t */\r\n\tDVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> screenToWorld() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for transformations involving a rotation\");\r\n\t\treturn { (2 * deltaY + deltaX) / -64, (2 * deltaY - deltaX) / -64 };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Missiles flip the axes for some reason -_-\r\n\t * @return negated and rounded world displacement, for use with missile movement routines.\r\n\t */\r\n\tconstexpr DisplacementOf<DeltaT> screenToMissile() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for transformations involving a rotation\");\r\n\t\tDeltaT xNumerator = 2 * deltaY + deltaX;\r\n\t\tDeltaT yNumerator = 2 * deltaY - deltaX;\r\n\t\tDeltaT xOffset = (xNumerator >= 0) ? 32 : -32;\r\n\t\tDeltaT yOffset = (yNumerator >= 0) ? 32 : -32;\r\n\t\treturn { (xNumerator + xOffset) / 64, (yNumerator + yOffset) / 64 };\r\n\t}\r\n\r\n\tconstexpr DisplacementOf<DeltaT> screenToLight() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for transformations involving a rotation\");\r\n\t\treturn { static_cast<DeltaT>((2 * deltaY + deltaX) / 8), static_cast<DeltaT>((2 * deltaY - deltaX) / 8) };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a 16 bit fixed point normalised displacement in isometric projection\r\n\t *\r\n\t * This will return a displacement of the form (-1.0 to 1.0, -0.5 to 0.5), to get a full tile offset you can multiply by 16\r\n\t */\r\n\t[[nodiscard]] Displacement worldToNormalScreen() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for transformations involving a rotation\");\r\n\t\t// Most transformations between world and screen space take shortcuts when scaling to simplify the math. This\r\n\t\t//  routine is typically used with missiles where we want a normal vector that can be multiplied with a target\r\n\t\t//  velocity (given in pixels). We could normalize the vector first but then we'd need to scale it during\r\n\t\t//  rotation from world to screen space. To save performing unnecessary divisions we rotate first without\r\n\t\t//  correcting the scaling. This gives a vector in elevation projection aligned with screen space.\r\n\t\tDisplacementOf<DeltaT> rotated { deltaY - deltaX, -(deltaY + deltaX) };\r\n\t\t// then normalize this vector\r\n\t\tDisplacement rotatedAndNormalized = rotated.normalized();\r\n\t\t// and finally scale the y axis to bring it to isometric projection\r\n\t\treturn { rotatedAndNormalized.deltaX, rotatedAndNormalized.deltaY / 2 };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Calculates a 16 bit fixed point normalized displacement (having magnitude of ~1.0) from the current Displacement\r\n\t */\r\n\t[[nodiscard]] Displacement normalized() const;\r\n\r\n\t[[nodiscard]] DVL_ALWAYS_INLINE constexpr DisplacementOf<DeltaT> Rotate(int quadrants) const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for Rotate\");\r\n\t\tconstexpr DeltaT Sines[] = { 0, 1, 0, -1 };\r\n\r\n\t\tquadrants = (quadrants % 4 + 4) % 4;\r\n\r\n\t\tDeltaT sine = Sines[quadrants];\r\n\t\tDeltaT cosine = Sines[(quadrants + 1) % 4];\r\n\r\n\t\treturn DisplacementOf { deltaX * cosine - deltaY * sine, deltaX * sine + deltaY * cosine };\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr DisplacementOf<DeltaT> flipX() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for flipX\");\r\n\t\treturn { static_cast<DeltaT>(-deltaX), deltaY };\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr DisplacementOf<DeltaT> flipY() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for flipY\");\r\n\t\treturn { deltaX, static_cast<DeltaT>(-deltaY) };\r\n\t}\r\n\r\n\t[[nodiscard]] constexpr DisplacementOf<DeltaT> flipXY() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for flipXY\");\r\n\t\treturn { static_cast<DeltaT>(-deltaX), static_cast<DeltaT>(-deltaY) };\r\n\t}\r\n\r\nprivate:\r\n\tDVL_ALWAYS_INLINE static constexpr DisplacementOf<DeltaT> fromDirection(Direction direction)\r\n\t{\r\n\t\tstatic_assert(std::is_signed<DeltaT>::value, \"DeltaT must be signed for conversion from Direction\");\r\n\t\tswitch (direction) {\r\n\t\tcase Direction::South:\r\n\t\t\treturn { 1, 1 };\r\n\t\tcase Direction::SouthWest:\r\n\t\t\treturn { 0, 1 };\r\n\t\tcase Direction::West:\r\n\t\t\treturn { -1, 1 };\r\n\t\tcase Direction::NorthWest:\r\n\t\t\treturn { -1, 0 };\r\n\t\tcase Direction::North:\r\n\t\t\treturn { -1, -1 };\r\n\t\tcase Direction::NorthEast:\r\n\t\t\treturn { 0, -1 };\r\n\t\tcase Direction::East:\r\n\t\t\treturn { 1, -1 };\r\n\t\tcase Direction::SouthEast:\r\n\t\t\treturn { 1, 0 };\r\n\t\tcase Direction::NoDirection:\r\n\t\t\treturn { 0, 0 };\r\n\t\tdefault:\r\n\t\t\treturn { 0, 0 };\r\n\t\t}\r\n\t};\r\n};\r\n\r\n#ifdef BUILD_TESTING\r\n/**\r\n * @brief Format displacements nicely in test failure messages\r\n * @param stream output stream, expected to have overloads for int and char*\r\n * @param offset Object to display\r\n * @return the stream, to allow chaining\r\n */\r\ntemplate <typename DisplacementDeltaT>\r\nstd::ostream &operator<<(std::ostream &stream, const DisplacementOf<DisplacementDeltaT> &offset)\r\n{\r\n\treturn stream << \"(x: \" << offset.deltaX << \", y: \" << offset.deltaY << \")\";\r\n}\r\n#endif\r\n\r\ntemplate <typename DisplacementDeltaT, typename OtherDisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator+(DisplacementOf<DisplacementDeltaT> a, DisplacementOf<OtherDisplacementDeltaT> b)\r\n{\r\n\ta += b;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT, typename OtherDisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator-(DisplacementOf<DisplacementDeltaT> a, DisplacementOf<OtherDisplacementDeltaT> b)\r\n{\r\n\ta -= b;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator*(DisplacementOf<DisplacementDeltaT> a, const int factor)\r\n{\r\n\ta *= factor;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator*(DisplacementOf<DisplacementDeltaT> a, const float factor)\r\n{\r\n\ta *= factor;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT, typename DisplacementDeltaU>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator*(DisplacementOf<DisplacementDeltaT> a, const DisplacementOf<DisplacementDeltaU> factor)\r\n{\r\n\ta *= factor;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator/(DisplacementOf<DisplacementDeltaT> a, const int factor)\r\n{\r\n\ta /= factor;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator/(DisplacementOf<DisplacementDeltaT> a, const float factor)\r\n{\r\n\ta /= factor;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator-(DisplacementOf<DisplacementDeltaT> a)\r\n{\r\n\treturn { -a.deltaX, -a.deltaY };\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator<<(DisplacementOf<DisplacementDeltaT> a, unsigned factor)\r\n{\r\n\treturn { a.deltaX << factor, a.deltaY << factor };\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> operator>>(DisplacementOf<DisplacementDeltaT> a, unsigned factor)\r\n{\r\n\treturn { a.deltaX >> factor, a.deltaY >> factor };\r\n}\r\n\r\ntemplate <typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<DisplacementDeltaT> abs(DisplacementOf<DisplacementDeltaT> a)\r\n{\r\n\treturn DisplacementOf<DisplacementDeltaT>(std::abs(a.deltaX), std::abs(a.deltaY));\r\n}\r\n\r\ntemplate <typename DeltaT>\r\nDisplacement DisplacementOf<DeltaT>::normalized() const\r\n{\r\n\tconst float magnitude = this->magnitude();\r\n\tDisplacement normalDisplacement = Displacement(*this) << 16u;\r\n\tnormalDisplacement /= magnitude;\r\n\treturn normalDisplacement;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/dx.cpp",
    "content": "/**\r\n * @file dx.cpp\r\n *\r\n * Implementation of functions setting up the graphics pipeline.\r\n */\r\n#include \"engine/dx.h\"\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_timer.h>\r\n#include <SDL3/SDL_video.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"init.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\n#ifndef USE_SDL1\r\n#include \"controls/touch/renderers.h\"\r\n#endif\r\n\r\n#ifdef __3DS__\r\n#include <3ds.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nint refreshDelay;\r\nSDL_Renderer *renderer;\r\n#ifndef USE_SDL1\r\nSDLTextureUniquePtr texture;\r\n#endif\r\n\r\n/** Currently active palette */\r\nSDLPaletteUniquePtr Palette;\r\n\r\n/** 24-bit renderer texture surface */\r\nSDLSurfaceUniquePtr RendererTextureSurface;\r\n\r\n/** 8-bit surface that we render to */\r\nSDL_Surface *PalSurface;\r\nnamespace {\r\nSDLSurfaceUniquePtr PinnedPalSurface;\r\n} // namespace\r\n\r\n/** Whether we render directly to the screen surface, i.e. `PalSurface == GetOutputSurface()` */\r\nbool RenderDirectlyToOutputSurface;\r\n\r\nnamespace {\r\n\r\nbool CanRenderDirectlyToOutputSurface()\r\n{\r\n#ifdef USE_SDL1\r\n#ifdef SDL1_FORCE_DIRECT_RENDER\r\n\treturn true;\r\n#else\r\n\tauto *outputSurface = GetOutputSurface();\r\n\treturn ((outputSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF\r\n\t    && outputSurface->w == gnScreenWidth && outputSurface->h == gnScreenHeight\r\n\t    && outputSurface->format->BitsPerPixel == 8);\r\n#endif\r\n#else // !USE_SDL1\r\n\tif (renderer != nullptr) return false;\r\n\tSDL_Surface *outputSurface = GetOutputSurface();\r\n\t// Assumes double-buffering is available.\r\n\treturn outputSurface->w == static_cast<int>(gnScreenWidth)\r\n\t    && outputSurface->h == static_cast<int>(gnScreenHeight)\r\n\t    && SDLC_SURFACE_BITSPERPIXEL(outputSurface) == 8;\r\n#endif\r\n}\r\n\r\n/**\r\n * @brief Limit FPS to avoid high CPU load, use when v-sync isn't available\r\n */\r\nvoid LimitFrameRate()\r\n{\r\n\tif (*GetOptions().Graphics.frameRateControl != FrameRateControl::CPUSleep)\r\n\t\treturn;\r\n\tstatic uint32_t frameDeadline;\r\n\tconst uint32_t tc = SDL_GetTicks() * 1000;\r\n\tuint32_t v = 0;\r\n\tif (frameDeadline > tc) {\r\n\t\tv = tc % refreshDelay;\r\n\t\tSDL_Delay(v / 1000 + 1); // ceil\r\n\t}\r\n\tframeDeadline = tc + v + refreshDelay;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid dx_init()\r\n{\r\n#ifndef USE_SDL1\r\n\tSDL_RaiseWindow(ghMainWnd);\r\n\tSDL_ShowWindow(ghMainWnd);\r\n#endif\r\n\r\n\tPalette = SDLWrap::AllocPalette();\r\n\tpalette_init();\r\n\tCreateBackBuffer();\r\n}\r\n\r\nSurface GlobalBackBuffer()\r\n{\r\n\treturn Surface(PalSurface, SDL_Rect { 0, 0, gnScreenWidth, gnScreenHeight });\r\n}\r\n\r\nvoid dx_cleanup()\r\n{\r\n#ifndef USE_SDL1\r\n\tif (ghMainWnd != nullptr)\r\n\t\tSDL_HideWindow(ghMainWnd);\r\n#endif\r\n\r\n\tPalSurface = nullptr;\r\n\tPinnedPalSurface = nullptr;\r\n\tPalette = nullptr;\r\n\tRendererTextureSurface = nullptr;\r\n#ifndef USE_SDL1\r\n\ttexture = nullptr;\r\n\tFreeVirtualGamepadTextures();\r\n\tif (*GetOptions().Graphics.upscale)\r\n\t\tSDL_DestroyRenderer(renderer);\r\n#endif\r\n\tSDL_DestroyWindow(ghMainWnd);\r\n}\r\n\r\nvoid CreateBackBuffer()\r\n{\r\n\tif (CanRenderDirectlyToOutputSurface()) {\r\n\t\tLog(\"{}\", \"Will render directly to the SDL output surface\");\r\n\t\tPalSurface = GetOutputSurface();\r\n\t\tRenderDirectlyToOutputSurface = true;\r\n\t} else {\r\n\t\tPinnedPalSurface = SDLWrap::CreateRGBSurfaceWithFormat(\r\n\t\t    /*flags=*/0,\r\n\t\t    /*width=*/gnScreenWidth,\r\n\t\t    /*height=*/gnScreenHeight,\r\n\t\t    /*depth=*/8,\r\n\t\t    SDL_PIXELFORMAT_INDEX8);\r\n\t\tPalSurface = PinnedPalSurface.get();\r\n\t}\r\n\r\n#if defined(USE_SDL3)\r\n\tif (!SDL_SetSurfacePalette(PalSurface, Palette.get())) ErrSdl();\r\n#elif !defined(USE_SDL1)\r\n\t// In SDL2, `PalSurface` points to the global `palette`.\r\n\tif (SDL_SetSurfacePalette(PalSurface, Palette.get()) < 0)\r\n\t\tErrSdl();\r\n#else\r\n\t// In SDL1, `PalSurface` owns its palette and we must update it every\r\n\t// time the global `palette` is changed. No need to do anything here as\r\n\t// the global `palette` doesn't have any colors set yet.\r\n#endif\r\n}\r\n\r\nvoid BltFast(SDL_Rect *srcRect, SDL_Rect *dstRect)\r\n{\r\n\tif (RenderDirectlyToOutputSurface)\r\n\t\treturn;\r\n\tBlit(PalSurface, srcRect, dstRect);\r\n}\r\n\r\nvoid Blit(SDL_Surface *src, SDL_Rect *srcRect, SDL_Rect *dstRect)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tSDL_Surface *dst = GetOutputSurface();\r\n#if defined(USE_SDL3)\r\n\tif (!SDL_BlitSurface(src, srcRect, dst, dstRect)) ErrSdl();\r\n#elif !defined(USE_SDL1)\r\n\tif (SDL_BlitSurface(src, srcRect, dst, dstRect) < 0)\r\n\t\tErrSdl();\r\n#else\r\n\tif (!OutputRequiresScaling()) {\r\n\t\tif (SDL_BlitSurface(src, srcRect, dst, dstRect) < 0)\r\n\t\t\tErrSdl();\r\n\t\treturn;\r\n\t}\r\n\r\n\tSDL_Rect scaledDstRect;\r\n\tif (dstRect != NULL) {\r\n\t\tscaledDstRect = *dstRect;\r\n\t\tScaleOutputRect(&scaledDstRect);\r\n\t\tdstRect = &scaledDstRect;\r\n\t}\r\n\r\n\t// Same pixel format: We can call BlitScaled directly.\r\n\tif (SDLBackport_PixelFormatFormatEq(src->format, dst->format)) {\r\n\t\tif (SDL_BlitScaled(src, srcRect, dst, dstRect) < 0)\r\n\t\t\tErrSdl();\r\n\t\treturn;\r\n\t}\r\n\r\n\t// If the surface has a color key, we must stretch first and can then call BlitSurface.\r\n\tif (SDL_HasColorKey(src)) {\r\n\t\tSDLSurfaceUniquePtr stretched = SDLWrap::CreateRGBSurface(SDL_SWSURFACE, dstRect->w, dstRect->h, src->format->BitsPerPixel,\r\n\t\t    src->format->Rmask, src->format->Gmask, src->format->BitsPerPixel, src->format->Amask);\r\n\t\tSDL_SetColorKey(stretched.get(), SDL_SRCCOLORKEY, src->format->colorkey);\r\n\t\tif (src->format->palette != NULL)\r\n\t\t\tSDL_SetPalette(stretched.get(), SDL_LOGPAL, src->format->palette->colors, 0, src->format->palette->ncolors);\r\n\t\tSDL_Rect stretched_rect = { 0, 0, dstRect->w, dstRect->h };\r\n\t\tif (SDL_SoftStretch(src, srcRect, stretched.get(), &stretched_rect) < 0\r\n\t\t    || SDL_BlitSurface(stretched.get(), &stretched_rect, dst, dstRect) < 0) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\t// A surface with a non-output pixel format but without a color key needs scaling.\r\n\t// We can convert the format and then call BlitScaled.\r\n\tSDLSurfaceUniquePtr converted = SDLWrap::ConvertSurface(src, dst->format, 0);\r\n\tif (SDL_BlitScaled(converted.get(), srcRect, dst, dstRect) < 0)\r\n\t\tErrSdl();\r\n#endif\r\n}\r\n\r\nvoid RenderPresent()\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tSDL_Surface *surface = GetOutputSurface();\r\n\r\n\tif (!gbActive) {\r\n\t\tLimitFrameRate();\r\n\t\treturn;\r\n\t}\r\n\r\n#ifndef USE_SDL1\r\n\tif (renderer != nullptr) {\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255)) ErrSdl();\r\n\t\tif (!SDL_RenderClear(renderer)) ErrSdl();\r\n\t\tif (!SDL_UpdateTexture(texture.get(), nullptr, surface->pixels, surface->pitch)) ErrSdl();\r\n\t\tif (!SDL_RenderTexture(renderer, texture.get(), nullptr, nullptr)) ErrSdl();\r\n#else\r\n\t\tif (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) <= -1) ErrSdl();\r\n\t\tif (SDL_RenderClear(renderer) <= -1) ErrSdl();\r\n\t\tif (SDL_UpdateTexture(texture.get(), nullptr, surface->pixels, surface->pitch) <= -1) ErrSdl();\r\n\t\tif (SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr) <= -1) ErrSdl();\r\n#endif\r\n\r\n\t\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\t\tRenderVirtualGamepad(renderer);\r\n\t\t}\r\n\t\tSDL_RenderPresent(renderer);\r\n\r\n\t\tif (*GetOptions().Graphics.frameRateControl != FrameRateControl::VerticalSync) {\r\n\t\t\tLimitFrameRate();\r\n\t\t}\r\n\t} else {\r\n\t\tif (ControlMode == ControlTypes::VirtualGamepad) {\r\n\t\t\tRenderVirtualGamepad(surface);\r\n\t\t}\r\n\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_UpdateWindowSurface(ghMainWnd)) ErrSdl();\r\n#else\r\n\t\tif (SDL_UpdateWindowSurface(ghMainWnd) <= -1) ErrSdl();\r\n#endif\r\n\r\n\t\tif (RenderDirectlyToOutputSurface)\r\n\t\t\tPalSurface = GetOutputSurface();\r\n\t\tLimitFrameRate();\r\n\t}\r\n#else\r\n\tif (SDL_Flip(surface) <= -1) {\r\n\t\tErrSdl();\r\n\t}\r\n\tif (RenderDirectlyToOutputSurface)\r\n\t\tPalSurface = GetOutputSurface();\r\n\tLimitFrameRate();\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/dx.h",
    "content": "/**\r\n * @file dx.h\r\n *\r\n * Interface of functions setting up the graphics pipeline.\r\n */\r\n#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/** Whether we render directly to the screen surface, i.e. `PalSurface == GetOutputSurface()` */\r\nextern bool RenderDirectlyToOutputSurface;\r\n\r\nextern SDL_Surface *PalSurface;\r\n\r\nSurface GlobalBackBuffer();\r\n\r\nvoid dx_init();\r\nvoid dx_cleanup();\r\nvoid CreateBackBuffer();\r\nvoid BltFast(SDL_Rect *srcRect, SDL_Rect *dstRect);\r\nvoid Blit(SDL_Surface *src, SDL_Rect *srcRect, SDL_Rect *dstRect);\r\nvoid RenderPresent();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/events.cpp",
    "content": "#include \"engine/events.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"controls/input.h\"\r\n#include \"controls/padmapper.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"interfac.h\"\r\n#include \"movie.h\"\r\n#include \"options.h\"\r\n#include \"panels/console.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\n#ifndef USE_SDL1\r\n#include \"controls/touch/event_handlers.h\"\r\n#endif\r\n\r\n#ifdef __vita__\r\n#include \"diablo.h\"\r\n#include \"platform/vita/touch.h\"\r\n#endif\r\n\r\n#ifdef __SWITCH__\r\n#include \"platform/switch/docking.h\"\r\n#include <switch.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nbool FalseAvail(const char *name, int value)\r\n{\r\n\tLogVerbose(\"Unhandled SDL event: {} {}\", name, value);\r\n\treturn true;\r\n}\r\n\r\nbool FetchMessage_Real(SDL_Event *event, uint16_t *modState)\r\n{\r\n#ifdef __SWITCH__\r\n\tHandleDocking();\r\n#endif\r\n\r\n\tSDL_Event e;\r\n\tif (!PollEvent(&e)) return false;\r\n\r\n\tevent->type = static_cast<SDL_EventType>(0);\r\n\t*modState = SDL_GetModState();\r\n\r\n#ifdef __vita__\r\n\tHandleTouchEvent(&e, MousePosition);\r\n#elif !defined(USE_SDL1)\r\n\tHandleTouchEvent(e);\r\n#endif\r\n\r\n\tif (e.type == SDL_EVENT_QUIT || IsCustomEvent(e.type)) {\r\n\t\t*event = e;\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Erroneous events generated by RG350 kernel.\r\n\tif (IsAnyOf(e.type, SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP) && SDLC_EventKey(e) == SDLK_UNKNOWN) return true;\r\n\r\n#if !defined(USE_SDL1) && !defined(__vita__)\r\n\tif (!movie_playing) {\r\n\t\t// SDL generates mouse events from touch-based inputs to provide basic\r\n\t\t// touchscreeen support for apps that don't explicitly handle touch events\r\n\t\tif (IsAnyOf(e.type, SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP)\r\n\t\t    && e.button.which == SDL_TOUCH_MOUSEID) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (e.type == SDL_EVENT_MOUSE_MOTION && e.motion.which == SDL_TOUCH_MOUSEID) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (e.type == SDL_EVENT_MOUSE_WHEEL && e.wheel.which == SDL_TOUCH_MOUSEID) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tif (!SDLC_ConvertEventToRenderCoordinates(renderer, &e)) {\r\n\t\tLogWarn(LogCategory::Application, \"SDL_ConvertEventToRenderCoordinates: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t}\r\n\r\n\tif (HandleControllerAddedOrRemovedEvent(e))\r\n\t\treturn true;\r\n\r\n\tswitch (e.type) {\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_GAMEPAD_AXIS_MOTION:\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_DOWN:\r\n\tcase SDL_EVENT_GAMEPAD_BUTTON_UP:\r\n\tcase SDL_EVENT_FINGER_DOWN:\r\n\tcase SDL_EVENT_FINGER_UP:\r\n\tcase SDL_EVENT_TEXT_EDITING:\r\n\tcase SDL_EVENT_TEXT_INPUT:\r\n\tcase SDL_EVENT_WINDOW_RESIZED:\r\n\tcase SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:\r\n\tcase SDL_EVENT_WINDOW_SHOWN:\r\n\tcase SDL_EVENT_WINDOW_MINIMIZED:\r\n\tcase SDL_EVENT_WINDOW_MAXIMIZED:\r\n\tcase SDL_EVENT_WINDOW_RESTORED:\r\n\tcase SDL_EVENT_WINDOW_HDR_STATE_CHANGED:\r\n\tcase SDL_EVENT_WINDOW_FOCUS_GAINED:\r\n\tcase SDL_EVENT_WINDOW_FOCUS_LOST:\r\n\tcase SDL_EVENT_MOUSE_WHEEL:\r\n\tcase SDL_EVENT_JOYSTICK_AXIS_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_HAT_MOTION:\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_DOWN:\r\n\tcase SDL_EVENT_JOYSTICK_BUTTON_UP:\r\n\tcase SDL_EVENT_MOUSE_MOTION:\r\n\tcase SDL_EVENT_MOUSE_BUTTON_DOWN:\r\n\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\t*event = e;\r\n\t\tbreak;\r\n\tcase SDL_EVENT_KEY_DOWN:\r\n\tcase SDL_EVENT_KEY_UP:\r\n\t\tif (e.key.key == SDLK_UNKNOWN) {\r\n\t\t\treturn FalseAvail(e.key.down ? \"SDL_EVENT_KEY_DOWN\" : \"SDL_EVENT_KEY_UP\", e.key.key);\r\n\t\t}\r\n\t\t*event = e;\r\n\t\tbreak;\r\n\tcase SDL_EVENT_AUDIO_DEVICE_ADDED:\r\n\t\treturn FalseAvail(\"SDL_EVENT_AUDIO_DEVICE_ADDED\", e.adevice.which);\r\n\tcase SDL_EVENT_AUDIO_DEVICE_REMOVED:\r\n\t\treturn FalseAvail(\"SDL_EVENT_AUDIO_DEVICE_REMOVED\", e.adevice.which);\r\n\tcase SDL_EVENT_KEYMAP_CHANGED:\r\n\t\treturn FalseAvail(\"SDL_EVENT_KEYMAP_CHANGED\", 0);\r\n#else\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tcase SDL_CONTROLLERAXISMOTION:\r\n\tcase SDL_CONTROLLERBUTTONDOWN:\r\n\tcase SDL_CONTROLLERBUTTONUP:\r\n\tcase SDL_FINGERDOWN:\r\n\tcase SDL_FINGERUP:\r\n\tcase SDL_TEXTEDITING:\r\n\tcase SDL_TEXTINPUT:\r\n\tcase SDL_WINDOWEVENT:\r\n\tcase SDL_MOUSEWHEEL:\r\n#else\r\n\tcase SDL_ACTIVEEVENT:\r\n#endif\r\n\tcase SDL_JOYAXISMOTION:\r\n\tcase SDL_JOYHATMOTION:\r\n\tcase SDL_JOYBUTTONDOWN:\r\n\tcase SDL_JOYBUTTONUP:\r\n\tcase SDL_MOUSEMOTION:\r\n\tcase SDL_MOUSEBUTTONDOWN:\r\n\tcase SDL_MOUSEBUTTONUP:\r\n\t\t*event = e;\r\n\t\tbreak;\r\n\tcase SDL_KEYDOWN:\r\n\tcase SDL_KEYUP:\r\n\t\tif (e.key.keysym.sym == -1)\r\n\t\t\treturn FalseAvail(e.type == SDL_KEYDOWN ? \"SDL_KEYDOWN\" : \"SDL_KEYUP\", e.key.keysym.sym);\r\n\t\t*event = e;\r\n\t\tbreak;\r\n#ifndef USE_SDL1\r\n#if SDL_VERSION_ATLEAST(2, 0, 4)\r\n\tcase SDL_AUDIODEVICEADDED:\r\n\t\treturn FalseAvail(\"SDL_AUDIODEVICEADDED\", e.adevice.which);\r\n\tcase SDL_AUDIODEVICEREMOVED:\r\n\t\treturn FalseAvail(\"SDL_AUDIODEVICEREMOVED\", e.adevice.which);\r\n\tcase SDL_KEYMAPCHANGED:\r\n\t\treturn FalseAvail(\"SDL_KEYMAPCHANGED\", 0);\r\n#endif\r\n#endif\r\n#endif\r\n\tdefault:\r\n\t\treturn FalseAvail(\"unknown\", e.type);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nEventHandler CurrentEventHandler;\r\n\r\nEventHandler SetEventHandler(EventHandler eventHandler)\r\n{\r\n\tPadmapperReleaseAllActiveButtons();\r\n\r\n\tEventHandler previousHandler = CurrentEventHandler;\r\n\tCurrentEventHandler = eventHandler;\r\n\treturn previousHandler;\r\n}\r\n\r\nbool FetchMessage(SDL_Event *event, uint16_t *modState)\r\n{\r\n\tconst bool available = demo::IsRunning() ? demo::FetchMessage(event, modState) : FetchMessage_Real(event, modState);\r\n\r\n\tif (available && demo::IsRecording())\r\n\t\tdemo::RecordMessage(*event, *modState);\r\n\r\n\treturn available;\r\n}\r\n\r\nvoid HandleMessage(const SDL_Event &event, uint16_t modState)\r\n{\r\n\tassert(CurrentEventHandler != nullptr);\r\n\r\n\tCurrentEventHandler(event, modState);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/events.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nusing EventHandler = void (*)(const SDL_Event &event, uint16_t modState);\r\n\r\n/** @brief The current input handler function */\r\nextern EventHandler CurrentEventHandler;\r\n\r\nEventHandler SetEventHandler(EventHandler NewProc);\r\n\r\nbool FetchMessage(SDL_Event *event, uint16_t *modState);\r\n\r\nvoid HandleMessage(const SDL_Event &event, uint16_t modState);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/lighting_defs.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n\r\nnamespace devilution {\r\n\r\n#define MAXLIGHTS 32\r\n#define MAXVISION 4\r\n#define NO_LIGHT -1\r\n\r\nconstexpr char LightsMax = 15;\r\n\r\n/** @brief A light table maps palette indices, so its size is the same as the palette size. */\r\nconstexpr size_t LightTableSize = 256;\r\n\r\n/** @brief Number of supported light levels */\r\nconstexpr size_t NumLightingLevels = LightsMax + 1;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_cel.cpp",
    "content": "#include \"engine/load_cel.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <string>\r\n\r\n#ifdef DEBUG_CEL_TO_CL2_SIZE\r\n#include <iostream>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#include \"engine/load_clx.hpp\"\r\n#else\r\n#include \"engine/load_file.hpp\"\r\n#include \"utils/cel_to_clx.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\ntl::expected<OwnedClxSpriteListOrSheet, std::string> LoadCelListOrSheetWithStatus(const char *pszName, PointerOrValue<uint16_t> widthOrWidths)\r\n{\r\n\tchar path[MaxMpqPathSize];\r\n\t*BufCopy(path, pszName, DEVILUTIONX_CEL_EXT) = '\\0';\r\n#ifdef UNPACKED_MPQS\r\n\treturn LoadClxListOrSheetWithStatus(path);\r\n#else\r\n\tsize_t size;\r\n\tASSIGN_OR_RETURN(std::unique_ptr<uint8_t[]> data, LoadFileInMemWithStatus<uint8_t>(path, &size));\r\n#ifdef DEBUG_CEL_TO_CL2_SIZE\r\n\tstd::cout << path;\r\n#endif\r\n\treturn CelToClx(data.get(), size, widthOrWidths);\r\n#endif\r\n}\r\n\r\nOwnedClxSpriteListOrSheet LoadCelListOrSheet(const char *pszName, PointerOrValue<uint16_t> widthOrWidths)\r\n{\r\n\ttl::expected<OwnedClxSpriteListOrSheet, std::string> result = LoadCelListOrSheetWithStatus(pszName, widthOrWidths);\r\n\tif (DVL_PREDICT_FALSE(!result.has_value())) app_fatal(result.error());\r\n\treturn std::move(result).value();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_cel.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"utils/pointer_value_union.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#define DEVILUTIONX_CEL_EXT \".clx\"\r\n#else\r\n#define DEVILUTIONX_CEL_EXT \".cel\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\ntl::expected<OwnedClxSpriteListOrSheet, std::string> LoadCelListOrSheetWithStatus(const char *pszName, PointerOrValue<uint16_t> widthOrWidths);\r\n\r\nOwnedClxSpriteListOrSheet LoadCelListOrSheet(const char *pszName, PointerOrValue<uint16_t> widthOrWidths);\r\n\r\ninline OwnedClxSpriteList LoadCel(const char *pszName, uint16_t width)\r\n{\r\n\treturn LoadCelListOrSheet(pszName, PointerOrValue<uint16_t> { width }).list();\r\n}\r\n\r\ninline OptionalOwnedClxSpriteList LoadOptionalCel(const char *pszName, uint16_t width)\r\n{\r\n\ttl::expected<OwnedClxSpriteListOrSheet, std::string> result = LoadCelListOrSheetWithStatus(pszName, PointerOrValue<uint16_t> { width });\r\n\tif (!result.has_value())\r\n\t\treturn std::nullopt;\r\n\treturn (*std::move(result)).list();\r\n}\r\n\r\ninline tl::expected<OwnedClxSpriteList, std::string> LoadCelWithStatus(const char *pszName, uint16_t width)\r\n{\r\n\tASSIGN_OR_RETURN(OwnedClxSpriteListOrSheet result, LoadCelListOrSheetWithStatus(pszName, PointerOrValue<uint16_t> { width }));\r\n\treturn std::move(result).list();\r\n}\r\n\r\ninline OwnedClxSpriteList LoadCel(const char *pszName, const uint16_t *widths)\r\n{\r\n\treturn LoadCelListOrSheet(pszName, PointerOrValue<uint16_t> { widths }).list();\r\n}\r\n\r\ninline OptionalOwnedClxSpriteList LoadOptionalCel(const char *pszName, const uint16_t *widths)\r\n{\r\n\ttl::expected<OwnedClxSpriteListOrSheet, std::string> result = LoadCelListOrSheetWithStatus(pszName, PointerOrValue<uint16_t> { widths });\r\n\tif (!result.has_value())\r\n\t\treturn std::nullopt;\r\n\treturn (*std::move(result)).list();\r\n}\r\n\r\ninline tl::expected<OwnedClxSpriteList, std::string> LoadCelWithStatus(const char *pszName, const uint16_t *widths)\r\n{\r\n\tASSIGN_OR_RETURN(OwnedClxSpriteListOrSheet result, LoadCelListOrSheetWithStatus(pszName, PointerOrValue<uint16_t> { widths }));\r\n\treturn std::move(result).list();\r\n}\r\n\r\ninline OwnedClxSpriteSheet LoadCelSheet(const char *pszName, uint16_t width)\r\n{\r\n\treturn LoadCelListOrSheet(pszName, PointerOrValue<uint16_t> { width }).sheet();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_cl2.cpp",
    "content": "#include \"engine/load_cl2.hpp\"\r\n\r\n#include <cstdint>\r\n#include <memory>\r\n#include <utility>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#include \"engine/load_clx.hpp\"\r\n#else\r\n#include \"engine/load_file.hpp\"\r\n#include \"utils/cl2_to_clx.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\ntl::expected<OwnedClxSpriteListOrSheet, std::string> LoadCl2ListOrSheetWithStatus(const char *pszName, PointerOrValue<uint16_t> widthOrWidths)\r\n{\r\n\tchar path[MaxMpqPathSize];\r\n\t*BufCopy(path, pszName, DEVILUTIONX_CL2_EXT) = '\\0';\r\n#ifdef UNPACKED_MPQS\r\n\treturn LoadClxListOrSheetWithStatus(path);\r\n#else\r\n\tsize_t size;\r\n\tASSIGN_OR_RETURN(std::unique_ptr<uint8_t[]> data, LoadFileInMemWithStatus<uint8_t>(path, &size));\r\n\treturn Cl2ToClx(std::move(data), size, widthOrWidths);\r\n#endif\r\n}\r\n\r\nOwnedClxSpriteListOrSheet LoadCl2ListOrSheet(const char *pszName, PointerOrValue<uint16_t> widthOrWidths)\r\n{\r\n\ttl::expected<OwnedClxSpriteListOrSheet, std::string> result = LoadCl2ListOrSheetWithStatus(pszName, widthOrWidths);\r\n\tif (!result.has_value()) app_fatal(result.error());\r\n\treturn std::move(result).value();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_cl2.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n#include <function_ref.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n#include \"utils/pointer_value_union.hpp\"\r\n#include \"utils/static_vector.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#define DEVILUTIONX_CL2_EXT \".clx\"\r\n#else\r\n#include \"utils/cl2_to_clx.hpp\"\r\n\r\n#define DEVILUTIONX_CL2_EXT \".cl2\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\ntl::expected<OwnedClxSpriteListOrSheet, std::string> LoadCl2ListOrSheetWithStatus(const char *pszName, PointerOrValue<uint16_t> widthOrWidths);\r\nOwnedClxSpriteListOrSheet LoadCl2ListOrSheet(const char *pszName, PointerOrValue<uint16_t> widthOrWidths);\r\n\r\ntemplate <size_t MaxCount>\r\ntl::expected<OwnedClxSpriteSheet, std::string> LoadMultipleCl2Sheet(tl::function_ref<const char *(size_t)> filenames, size_t count, uint16_t width)\r\n{\r\n\tStaticVector<std::array<char, MaxMpqPathSize>, MaxCount> paths;\r\n\tStaticVector<AssetRef, MaxCount> files;\r\n\tStaticVector<size_t, MaxCount> fileSizes;\r\n\tconst size_t sheetHeaderSize = 4 * count;\r\n\tsize_t totalSize = sheetHeaderSize;\r\n\tfor (size_t i = 0; i < count; ++i) {\r\n\t\t{\r\n\t\t\tconst char *path = filenames(i);\r\n\t\t\tpaths.emplace_back();\r\n\t\t\tmemcpy(paths.back().data(), path, strlen(path) + 1);\r\n\t\t}\r\n\t\tconst char *path = paths.back().data();\r\n\t\tfiles.emplace_back(FindAsset(path));\r\n\t\tif (!files.back().ok()) {\r\n\t\t\tFailedToOpenFileError(path, files.back().error());\r\n\t\t}\r\n\t\tconst size_t size = files.back().size();\r\n\t\tfileSizes.emplace_back(size);\r\n\t\ttotalSize += size;\r\n\t}\r\n\tauto data = std::unique_ptr<uint8_t[]> { new uint8_t[totalSize] };\r\n#ifndef UNPACKED_MPQS\r\n\tconst PointerOrValue<uint16_t> frameWidth { width };\r\n#endif\r\n\tsize_t accumulatedSize = sheetHeaderSize;\r\n\tfor (size_t i = 0; i < count; ++i) {\r\n\t\tconst size_t size = fileSizes[i];\r\n\t\tAssetHandle handle = OpenAsset(std::move(files[i]));\r\n\t\tif (!handle.ok() || !handle.read(&data[accumulatedSize], size)) {\r\n\t\t\tFailedToOpenFileError(paths[i].data(), handle.error());\r\n\t\t}\r\n\t\tWriteLE32(&data[i * 4], static_cast<uint32_t>(accumulatedSize));\r\n\t\taccumulatedSize += size;\r\n\t}\r\n#ifdef UNPACKED_MPQS\r\n\treturn OwnedClxSpriteSheet { std::move(data), static_cast<uint16_t>(count) };\r\n#else\r\n\treturn Cl2ToClx(std::move(data), accumulatedSize, frameWidth).sheet();\r\n#endif\r\n}\r\n\r\ninline tl::expected<OwnedClxSpriteList, std::string> LoadCl2WithStatus(const char *pszName, uint16_t width)\r\n{\r\n\tASSIGN_OR_RETURN(OwnedClxSpriteListOrSheet result, LoadCl2ListOrSheetWithStatus(pszName, PointerOrValue<uint16_t> { width }));\r\n\treturn std::move(result).list();\r\n}\r\n\r\ninline OwnedClxSpriteList LoadCl2(const char *pszName, uint16_t width)\r\n{\r\n\treturn LoadCl2ListOrSheet(pszName, PointerOrValue<uint16_t> { width }).list();\r\n}\r\n\r\ninline OwnedClxSpriteList LoadCl2(const char *pszName, const uint16_t *widths)\r\n{\r\n\treturn LoadCl2ListOrSheet(pszName, PointerOrValue<uint16_t> { widths }).list();\r\n}\r\n\r\ninline OwnedClxSpriteSheet LoadCl2Sheet(const char *pszName, uint16_t width)\r\n{\r\n\treturn LoadCl2ListOrSheet(pszName, PointerOrValue<uint16_t> { width }).sheet();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_clx.cpp",
    "content": "#include \"engine/load_clx.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteListOrSheet LoadOptionalClxListOrSheet(const char *path)\r\n{\r\n\tAssetRef ref = FindAsset(path);\r\n\tif (!ref.ok())\r\n\t\treturn std::nullopt;\r\n\tconst size_t size = ref.size();\r\n\tstd::unique_ptr<uint8_t[]> data { new uint8_t[size] };\r\n\t{\r\n\t\tAssetHandle handle = OpenAsset(std::move(ref));\r\n\t\tif (!handle.ok() || !handle.read(data.get(), size))\r\n\t\t\treturn std::nullopt;\r\n\t}\r\n\treturn OwnedClxSpriteListOrSheet::FromBuffer(std::move(data), size);\r\n}\r\n\r\ntl::expected<OwnedClxSpriteListOrSheet, std::string> LoadClxListOrSheetWithStatus(const char *path)\r\n{\r\n\tsize_t size;\r\n\ttl::expected<std::unique_ptr<uint8_t[]>, std::string> data = LoadFileInMemWithStatus<uint8_t>(path, &size);\r\n\tif (!data.has_value()) return tl::make_unexpected(std::move(data).error());\r\n\treturn OwnedClxSpriteListOrSheet::FromBuffer(std::move(data).value(), size);\r\n}\r\n\r\nOwnedClxSpriteListOrSheet LoadClxListOrSheet(const char *path)\r\n{\r\n\ttl::expected<OwnedClxSpriteListOrSheet, std::string> result = LoadClxListOrSheetWithStatus(path);\r\n\tif (!result.has_value()) app_fatal(result.error());\r\n\treturn std::move(result).value();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_clx.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"clx_sprite.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOwnedClxSpriteListOrSheet LoadClxListOrSheet(const char *path);\r\n\r\ntl::expected<OwnedClxSpriteListOrSheet, std::string> LoadClxListOrSheetWithStatus(const char *path);\r\n\r\ninline OwnedClxSpriteList LoadClx(const char *path)\r\n{\r\n\treturn LoadClxListOrSheet(path).list();\r\n}\r\n\r\ninline tl::expected<OwnedClxSpriteList, std::string> LoadClxWithStatus(const char *path)\r\n{\r\n\tASSIGN_OR_RETURN(OwnedClxSpriteListOrSheet result, LoadClxListOrSheetWithStatus(path));\r\n\treturn std::move(result).list();\r\n}\r\n\r\ninline OwnedClxSpriteSheet LoadClxSheet(const char *path)\r\n{\r\n\treturn LoadClxListOrSheet(path).sheet();\r\n}\r\n\r\nOptionalOwnedClxSpriteListOrSheet LoadOptionalClxListOrSheet(const char *path);\r\n\r\ninline OptionalOwnedClxSpriteList LoadOptionalClx(const char *path)\r\n{\r\n\tOptionalOwnedClxSpriteListOrSheet result = LoadOptionalClxListOrSheet(path);\r\n\tif (!result)\r\n\t\treturn std::nullopt;\r\n\treturn std::move(*result).list();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_file.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"utils/static_vector.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename T>\r\ntl::expected<void, std::string> LoadFileInMemWithStatus(const char *path, T *data)\r\n{\r\n\tsize_t size;\r\n\tAssetHandle handle = OpenAsset(path, size);\r\n\tif (!handle.ok()) {\r\n\t\tif (HeadlessMode) return {};\r\n\t\treturn tl::make_unexpected(FailedToOpenFileErrorMessage(path, handle.error()));\r\n\t}\r\n\tif ((size % sizeof(T)) != 0) {\r\n\t\treturn tl::make_unexpected(StrCat(\"File size does not align with type\\n\", path));\r\n\t}\r\n\tif (!handle.read(data, size)) {\r\n\t\treturn tl::make_unexpected(\"handle.read failed\");\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntemplate <typename T>\r\nvoid LoadFileInMem(const char *path, T *data)\r\n{\r\n\tconst tl::expected<void, std::string> result = LoadFileInMemWithStatus<T>(path, data);\r\n\tif (!result.has_value()) app_fatal(result.error());\r\n}\r\n\r\ntemplate <typename T>\r\ntl::expected<void, std::string> LoadFileInMemWithStatus(const char *path, T *data, std::size_t count)\r\n{\r\n\tAssetHandle handle = OpenAsset(path);\r\n\tif (!handle.ok()) {\r\n\t\tif (HeadlessMode) return {};\r\n\t\treturn tl::make_unexpected(FailedToOpenFileErrorMessage(path, handle.error()));\r\n\t}\r\n\tif (!handle.read(data, count * sizeof(T))) {\r\n\t\treturn tl::make_unexpected(\"handle.read failed\");\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntemplate <typename T>\r\nvoid LoadFileInMem(const char *path, T *data, std::size_t count)\r\n{\r\n\ttl::expected<void, std::string> result = LoadFileInMemWithStatus<T>(path, data, count);\r\n\tif (!result.has_value()) app_fatal(result.error());\r\n}\r\n\r\ntemplate <typename T>\r\nbool LoadOptionalFileInMem(const char *path, T *data, std::size_t count)\r\n{\r\n\tAssetHandle handle = OpenAsset(path);\r\n\treturn handle.ok() && handle.read(data, count * sizeof(T));\r\n}\r\n\r\ntemplate <typename T, std::size_t N>\r\ntl::expected<void, std::string> LoadFileInMemWithStatus(const char *path, std::array<T, N> &data)\r\n{\r\n\treturn LoadFileInMemWithStatus(path, data.data(), N);\r\n}\r\n\r\ntemplate <typename T, std::size_t N>\r\nvoid LoadFileInMem(const char *path, std::array<T, N> &data)\r\n{\r\n\tLoadFileInMem(path, data.data(), N);\r\n}\r\n\r\ntemplate <typename T = std::byte>\r\ntl::expected<std::unique_ptr<T[]>, std::string> LoadFileInMemWithStatus(const char *path, std::size_t *numRead = nullptr)\r\n{\r\n\tsize_t size;\r\n\tAssetHandle handle = OpenAsset(path, size);\r\n\tif (!handle.ok()) {\r\n\t\tif (HeadlessMode) return {};\r\n\t\treturn tl::make_unexpected(FailedToOpenFileErrorMessage(path, handle.error()));\r\n\t}\r\n\tif ((size % sizeof(T)) != 0) {\r\n\t\treturn tl::make_unexpected(StrCat(\"File size does not align with type\\n\", path));\r\n\t}\r\n\r\n\tif (numRead != nullptr)\r\n\t\t*numRead = size / sizeof(T);\r\n\r\n\tstd::unique_ptr<T[]> buf { new T[size / sizeof(T)] };\r\n\tif (!handle.read(buf.get(), size)) {\r\n\t\treturn tl::make_unexpected(\"handle.read failed\");\r\n\t}\r\n\treturn { std::move(buf) };\r\n}\r\n\r\n/**\r\n * @brief Load a file in to a buffer\r\n * @param path Path of file\r\n * @param numRead Number of T elements read\r\n * @return Buffer with content of file\r\n */\r\ntemplate <typename T = std::byte>\r\nstd::unique_ptr<T[]> LoadFileInMem(const char *path, std::size_t *numRead = nullptr)\r\n{\r\n\ttl::expected<std::unique_ptr<T[]>, std::string> result = LoadFileInMemWithStatus<T>(path, numRead);\r\n\tif (!result.has_value()) app_fatal(result.error());\r\n\treturn std::move(result).value();\r\n}\r\n\r\n/**\r\n * @brief Reads multiple files into a single buffer\r\n *\r\n * @tparam MaxFiles maximum number of files\r\n */\r\ntemplate <size_t MaxFiles>\r\nstruct MultiFileLoader {\r\n\tstruct DefaultFilterFn {\r\n\t\tbool operator()(size_t i) const\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t};\r\n\r\n\t/**\r\n\t * @param numFiles number of files to read\r\n\t * @param pathFn a function that returns the path for the given index\r\n\t * @param outOffsets a buffer index for the start of each file will be written here, then the total file size at the end.\r\n\t * @param filterFn a function that returns whether to load a file for the given index\r\n\t * @return std::unique_ptr<std::byte[]> the buffer with all the files\r\n\t */\r\n\ttemplate <typename PathFn, typename FilterFn = DefaultFilterFn>\r\n\t[[nodiscard]] std::unique_ptr<std::byte[]> operator()(size_t numFiles, PathFn &&pathFn, uint32_t *outOffsets,\r\n\t    FilterFn filterFn = DefaultFilterFn {})\r\n\t{\r\n\t\tStaticVector<std::array<char, MaxMpqPathSize>, MaxFiles> paths;\r\n\t\tStaticVector<AssetRef, MaxFiles> files;\r\n\t\tStaticVector<uint32_t, MaxFiles> sizes;\r\n\t\tsize_t totalSize = 0;\r\n\t\tfor (size_t i = 0, j = 0; i < numFiles; ++i) {\r\n\t\t\tif (!filterFn(i))\r\n\t\t\t\tcontinue;\r\n\t\t\t{\r\n\t\t\t\tconst char *path = pathFn(i);\r\n\t\t\t\tpaths.emplace_back();\r\n\t\t\t\tmemcpy(paths.back().data(), path, strlen(path) + 1);\r\n\t\t\t}\r\n\t\t\tconst char *path = paths.back().data();\r\n\t\t\tfiles.emplace_back(FindAsset(path));\r\n\t\t\tif (!ValidatAssetRef(path, files.back()))\r\n\t\t\t\treturn nullptr;\r\n\r\n\t\t\tconst size_t size = files.back().size();\r\n\t\t\tsizes.emplace_back(static_cast<uint32_t>(size));\r\n\t\t\toutOffsets[j] = static_cast<uint32_t>(totalSize);\r\n\t\t\ttotalSize += size;\r\n\t\t\t++j;\r\n\t\t}\r\n\t\toutOffsets[files.size()] = static_cast<uint32_t>(totalSize);\r\n\t\tstd::unique_ptr<std::byte[]> buf { new std::byte[totalSize] };\r\n\t\tfor (size_t i = 0, j = 0; i < numFiles; ++i) {\r\n\t\t\tif (!filterFn(i))\r\n\t\t\t\tcontinue;\r\n\t\t\tAssetHandle handle = OpenAsset(std::move(files[j]));\r\n\t\t\tif (!handle.ok() || !handle.read(&buf[outOffsets[j]], sizes[j])) {\r\n\t\t\t\tFailedToOpenFileError(paths[j].data(), handle.error());\r\n\t\t\t}\r\n\t\t\t++j;\r\n\t\t}\r\n\t\treturn buf;\r\n\t}\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_pcx.cpp",
    "content": "#include \"engine/load_pcx.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n#include <utility>\r\n\r\n#ifdef DEBUG_PCX_TO_CL2_SIZE\r\n#include <iostream>\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#else\r\n#include \"engine/assets.hpp\"\r\n#include \"utils/pcx.hpp\"\r\n#include \"utils/pcx_to_clx.hpp\"\r\n#endif\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteList LoadPcxSpriteList(const char *filename, int numFramesOrFrameHeight, std::optional<uint8_t> transparentColor, SDL_Color *outPalette, bool logError)\r\n{\r\n\tchar path[MaxMpqPathSize];\r\n\tchar *pathEnd = BufCopy(path, filename, DEVILUTIONX_PCX_EXT);\r\n\t*pathEnd = '\\0';\r\n#ifdef UNPACKED_MPQS\r\n\tOptionalOwnedClxSpriteList result = LoadOptionalClx(path);\r\n\tif (!result) {\r\n\t\tif (logError)\r\n\t\t\tLogError(\"Missing file: {}\", path);\r\n\t\treturn result;\r\n\t}\r\n\tif (outPalette != nullptr) {\r\n\t\tstd::memcpy(pathEnd - 3, \"pal\", 3);\r\n\t\tstd::array<uint8_t, 256 * 3> palette;\r\n\t\tLoadFileInMem(path, palette);\r\n\t\tfor (unsigned i = 0; i < 256; i++) {\r\n\t\t\toutPalette[i].r = palette[i * 3];\r\n\t\t\toutPalette[i].g = palette[i * 3 + 1];\r\n\t\t\toutPalette[i].b = palette[i * 3 + 2];\r\n#ifndef USE_SDL1\r\n\t\t\toutPalette[i].a = SDL_ALPHA_OPAQUE;\r\n#endif\r\n\t\t}\r\n\t}\r\n\treturn result;\r\n#else\r\n\tsize_t fileSize;\r\n\tAssetHandle handle = OpenAsset(path, fileSize);\r\n\tif (!handle.ok()) {\r\n\t\tif (logError)\r\n\t\t\tLogError(\"Missing file: {}\", path);\r\n\t\treturn std::nullopt;\r\n\t}\r\n#ifdef DEBUG_PCX_TO_CL2_SIZE\r\n\tstd::cout << filename;\r\n#endif\r\n\tOptionalOwnedClxSpriteList result = PcxToClx(handle, fileSize, numFramesOrFrameHeight, transparentColor, outPalette);\r\n\tif (!result)\r\n\t\treturn std::nullopt;\r\n\treturn result;\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/load_pcx.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#define DEVILUTIONX_PCX_EXT \".clx\"\r\n#else\r\n#define DEVILUTIONX_PCX_EXT \".pcx\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Loads a PCX file as a CLX sprite list.\r\n *\r\n * @param filename\r\n * @param numFramesOrFrameHeight Pass a positive value with the number of frames, or the frame height as a negative value.\r\n * @param transparentColor\r\n * @param outPalette\r\n * @return OptionalOwnedClxSpriteList\r\n */\r\nOptionalOwnedClxSpriteList LoadPcxSpriteList(const char *filename, int numFramesOrFrameHeight, std::optional<uint8_t> transparentColor = std::nullopt, SDL_Color *outPalette = nullptr, bool logError = true);\r\n\r\n/**\r\n * @brief Loads a PCX file as a CLX sprite list with a single sprite.\r\n *\r\n * @param filename\r\n * @param transparentColor\r\n * @param outPalette\r\n * @return OptionalOwnedClxSpriteList\r\n */\r\ninline OptionalOwnedClxSpriteList LoadPcx(const char *filename, std::optional<uint8_t> transparentColor = std::nullopt, SDL_Color *outPalette = nullptr, bool logError = true)\r\n{\r\n\treturn LoadPcxSpriteList(filename, 1, transparentColor, outPalette, logError);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/palette.cpp",
    "content": "/**\r\n * @file palette.cpp\r\n *\r\n * Implementation of functions for handling the engines color palette.\r\n */\r\n#include \"engine/palette.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <span>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/palette_blending.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::array<SDL_Color, 256> logical_palette;\r\nstd::array<SDL_Color, 256> system_palette;\r\n\r\nnamespace {\r\n\r\n/** Specifies whether the palette has max brightness. */\r\nbool sgbFadedIn = true;\r\n\r\nvoid LoadBrightness()\r\n{\r\n\tint brightnessValue = *GetOptions().Graphics.brightness;\r\n\tbrightnessValue = std::clamp(brightnessValue, 0, 100);\r\n\tGetOptions().Graphics.brightness.SetValue(brightnessValue - brightnessValue % 5);\r\n}\r\n\r\n/**\r\n * @brief Cycle the given range of colors in the palette\r\n * @param from First color index of the range\r\n * @param to First color index of the range\r\n */\r\nvoid CycleColors(int from, int to)\r\n{\r\n\tstd::rotate(logical_palette.begin() + from, logical_palette.begin() + from + 1, logical_palette.begin() + to + 1);\r\n\tstd::rotate(system_palette.begin() + from, system_palette.begin() + from + 1, system_palette.begin() + to + 1);\r\n\r\n\tfor (auto &palette : paletteTransparencyLookup) {\r\n\t\tstd::rotate(std::begin(palette) + from, std::begin(palette) + from + 1, std::begin(palette) + to + 1);\r\n\t}\r\n\r\n\tstd::rotate(&paletteTransparencyLookup[from][0], &paletteTransparencyLookup[from + 1][0], &paletteTransparencyLookup[to + 1][0]);\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n\tUpdateTransparencyLookupBlack16(from, to);\r\n#endif\r\n}\r\n\r\n/**\r\n * @brief Cycle the given range of colors in the palette in reverse direction\r\n * @param from First color index of the range\r\n * @param to Last color index of the range\r\n */\r\nvoid CycleColorsReverse(int from, int to)\r\n{\r\n\tstd::rotate(logical_palette.begin() + from, logical_palette.begin() + to, logical_palette.begin() + to + 1);\r\n\tstd::rotate(system_palette.begin() + from, system_palette.begin() + to, system_palette.begin() + to + 1);\r\n\r\n\tfor (auto &palette : paletteTransparencyLookup) {\r\n\t\tstd::rotate(std::begin(palette) + from, std::begin(palette) + to, std::begin(palette) + to + 1);\r\n\t}\r\n\r\n\tstd::rotate(&paletteTransparencyLookup[from][0], &paletteTransparencyLookup[to][0], &paletteTransparencyLookup[to + 1][0]);\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n\tUpdateTransparencyLookupBlack16(from, to);\r\n#endif\r\n}\r\n\r\n// When brightness==0, then a==0 (identity mapping)\r\n// When brightness==100, then a==-MaxAdjustment (maximum brightening)\r\nconstexpr float CalculateToneMappingParameter(int brightness)\r\n{\r\n\t// Maximum adjustment factor (tweak this constant to change the effect strength)\r\n\tconstexpr float MaxAdjustment = 2.0F;\r\n\treturn -(brightness / 100.0f) * MaxAdjustment;\r\n}\r\n\r\nconstexpr uint8_t MapTone(float a, uint8_t color)\r\n{\r\n\tconst auto x = static_cast<float>(color / 255.0f);\r\n\t// Our quadratic tone mapping: f(x) = a*x^2 + (1-a)*x.\r\n\tconst float y = std::clamp(a * x * x + (1.0f - a) * x, 0.0f, 1.0f);\r\n\treturn static_cast<uint8_t>(y * 255.0f + 0.5f);\r\n}\r\n\r\nvoid ApplyGlobalBrightnessSingleColor(SDL_Color &dst, const SDL_Color &src)\r\n{\r\n\tconst float a = CalculateToneMappingParameter(*GetOptions().Graphics.brightness);\r\n\tdst.r = MapTone(a, src.r);\r\n\tdst.g = MapTone(a, src.g);\r\n\tdst.b = MapTone(a, src.b);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid ApplyGlobalBrightness(SDL_Color *dst, const SDL_Color *src)\r\n{\r\n\t// Get the brightness slider value (0 = neutral, 100 = max brightening)\r\n\tconst int brightnessSlider = *GetOptions().Graphics.brightness;\r\n\r\n\t// Precompute a lookup table for speed.\r\n\tconst float a = CalculateToneMappingParameter(brightnessSlider);\r\n\tuint8_t toneMap[256];\r\n\tfor (int i = 0; i < 256; i++) {\r\n\t\ttoneMap[i] = MapTone(a, i);\r\n\t}\r\n\r\n\t// Apply the lookup table to each color channel in the palette.\r\n\tfor (int i = 0; i < 256; i++) {\r\n\t\tdst[i].r = toneMap[src[i].r];\r\n\t\tdst[i].g = toneMap[src[i].g];\r\n\t\tdst[i].b = toneMap[src[i].b];\r\n\t}\r\n}\r\n\r\nvoid ApplyFadeLevel(unsigned fadeval, SDL_Color *dst, const SDL_Color *src)\r\n{\r\n\tfor (int i = 0; i < 256; i++) {\r\n\t\tdst[i].r = (fadeval * src[i].r) / 256;\r\n\t\tdst[i].g = (fadeval * src[i].g) / 256;\r\n\t\tdst[i].b = (fadeval * src[i].b) / 256;\r\n\t}\r\n}\r\n\r\n// Applies a tone mapping curve based on the brightness slider value.\r\n// The brightness value is in the range [0, 100] where 0 is neutral (no change)\r\n// and 100 produces maximum brightening.\r\nvoid UpdateSystemPalette(std::span<const SDL_Color, 256> src)\r\n{\r\n\tApplyGlobalBrightness(system_palette.data(), src.data());\r\n\tSystemPaletteUpdated();\r\n\tRedrawEverything();\r\n}\r\n\r\nvoid SystemPaletteUpdated(int first, int ncolor)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tassert(Palette);\r\n\tif (!SDLC_SetSurfaceAndPaletteColors(PalSurface, Palette.get(), system_palette.data() + first, first, ncolor)) {\r\n\t\tErrSdl();\r\n\t}\r\n}\r\n\r\nvoid palette_init()\r\n{\r\n\tLoadBrightness();\r\n}\r\n\r\nvoid LoadPalette(const char *path)\r\n{\r\n\tassert(path != nullptr);\r\n\tif (HeadlessMode) return;\r\n\r\n\tLogVerbose(\"Loading palette from {}\", path);\r\n\tstd::array<Color, 256> palData;\r\n\tLoadFileInMem(path, palData);\r\n\tfor (unsigned i = 0; i < palData.size(); i++) {\r\n\t\tlogical_palette[i] = palData[i].toSDL();\r\n\t}\r\n}\r\n\r\nvoid LoadPaletteAndInitBlending(const char *path)\r\n{\r\n\tassert(path != nullptr);\r\n\tif (HeadlessMode) return;\r\n\tLoadPalette(path);\r\n\tif (leveltype == DTYPE_CAVES || leveltype == DTYPE_CRYPT) {\r\n\t\tGenerateBlendedLookupTable(logical_palette.data(), /*skipFrom=*/1, /*skipTo=*/31);\r\n\t} else if (leveltype == DTYPE_NEST) {\r\n\t\tGenerateBlendedLookupTable(logical_palette.data(), /*skipFrom=*/1, /*skipTo=*/15);\r\n\t} else {\r\n\t\tGenerateBlendedLookupTable(logical_palette.data());\r\n\t}\r\n}\r\n\r\nvoid LoadRndLvlPal(dungeon_type l)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tif (l == DTYPE_TOWN) {\r\n\t\tLoadPaletteAndInitBlending(\"levels\\\\towndata\\\\town.pal\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (l == DTYPE_CRYPT) {\r\n\t\tLoadPaletteAndInitBlending(\"nlevels\\\\l5data\\\\l5base.pal\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tint rv = RandomIntBetween(1, 4);\r\n\tchar szFileName[27];\r\n\tif (l == DTYPE_NEST) {\r\n\t\tif (!*GetOptions().Graphics.alternateNestArt) {\r\n\t\t\trv++;\r\n\t\t}\r\n\t\t*BufCopy(szFileName, R\"(nlevels\\l6data\\l6base)\", rv, \".pal\") = '\\0';\r\n\t} else {\r\n\t\tchar nbuf[3];\r\n\t\tconst char *end = BufCopy(nbuf, static_cast<int>(l));\r\n\t\tconst std::string_view n = std::string_view(nbuf, end - nbuf);\r\n\t\t*BufCopy(szFileName, \"levels\\\\l\", n, \"data\\\\l\", n, \"_\", rv, \".pal\") = '\\0';\r\n\t}\r\n\tLoadPaletteAndInitBlending(szFileName);\r\n}\r\n\r\nvoid IncreaseBrightness()\r\n{\r\n\tconst int brightnessValue = *GetOptions().Graphics.brightness;\r\n\tif (brightnessValue < 100) {\r\n\t\tconst int newBrightness = std::min(brightnessValue + 5, 100);\r\n\t\tGetOptions().Graphics.brightness.SetValue(newBrightness);\r\n\t\tUpdateSystemPalette(logical_palette);\r\n\t}\r\n}\r\n\r\nvoid DecreaseBrightness()\r\n{\r\n\tconst int brightnessValue = *GetOptions().Graphics.brightness;\r\n\tif (brightnessValue > 0) {\r\n\t\tconst int newBrightness = std::max(brightnessValue - 5, 0);\r\n\t\tGetOptions().Graphics.brightness.SetValue(newBrightness);\r\n\t\tUpdateSystemPalette(logical_palette);\r\n\t}\r\n}\r\n\r\nint UpdateBrightness(int brightness)\r\n{\r\n\tif (brightness >= 0) {\r\n\t\tGetOptions().Graphics.brightness.SetValue(brightness);\r\n\t\tUpdateSystemPalette(logical_palette);\r\n\t}\r\n\r\n\treturn *GetOptions().Graphics.brightness;\r\n}\r\n\r\nvoid BlackPalette()\r\n{\r\n\tfor (SDL_Color &c : system_palette) {\r\n\t\tc.r = c.g = c.b = 0;\r\n\t}\r\n\tSystemPaletteUpdated();\r\n}\r\n\r\nvoid PaletteFadeIn(int fr, const std::array<SDL_Color, 256> &srcPalette)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\tif (demo::IsRunning())\r\n\t\tfr = 0;\r\n\r\n\tstd::array<SDL_Color, 256> palette;\r\n\r\n#ifndef USE_SDL1\r\n\tfor (SDL_Color &color : palette) {\r\n\t\tcolor.a = SDL_ALPHA_OPAQUE;\r\n\t}\r\n#endif\r\n\r\n\tApplyGlobalBrightness(palette.data(), srcPalette.data());\r\n\r\n\tif (fr > 0) {\r\n\t\tconst uint32_t tc = SDL_GetTicks();\r\n\t\tfr *= 3;\r\n\t\tuint32_t prevFadeValue = 255;\r\n\t\tfor (uint32_t i = 0; i < 256; i = fr * (SDL_GetTicks() - tc) / 50) {\r\n\t\t\tif (i == prevFadeValue) {\r\n\t\t\t\tSDL_Delay(1);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tApplyFadeLevel(i, system_palette.data(), palette.data());\r\n\t\t\tSystemPaletteUpdated();\r\n\r\n\t\t\t// We can skip hardware cursor update for fade level 0 (everything is black).\r\n\t\t\tif (i != 0 && IsHardwareCursor()) {\r\n\t\t\t\tReinitializeHardwareCursor();\r\n\t\t\t}\r\n\r\n\t\t\tprevFadeValue = i;\r\n\r\n\t\t\tBltFast(nullptr, nullptr);\r\n\t\t\tRenderPresent();\r\n\t\t}\r\n\t}\r\n\tsystem_palette = palette;\r\n\tSystemPaletteUpdated();\r\n\tRedrawEverything();\r\n\tif (IsHardwareCursor()) ReinitializeHardwareCursor();\r\n\r\n\tif (fr <= 0) {\r\n\t\tBltFast(nullptr, nullptr);\r\n\t\tRenderPresent();\r\n\t}\r\n\r\n\tsgbFadedIn = true;\r\n}\r\n\r\nvoid PaletteFadeOut(int fr, const std::array<SDL_Color, 256> &srcPalette)\r\n{\r\n\tif (!sgbFadedIn || HeadlessMode)\r\n\t\treturn;\r\n\tif (demo::IsRunning())\r\n\t\tfr = 0;\r\n\r\n\tif (fr > 0) {\r\n\t\tSDL_Color palette[256];\r\n\t\tApplyGlobalBrightness(palette, srcPalette.data());\r\n\r\n\t\tconst uint32_t tc = SDL_GetTicks();\r\n\t\tfr *= 3;\r\n\t\tuint32_t prevFadeValue = 0;\r\n\t\tfor (uint32_t i = 0; i < 256; i = fr * (SDL_GetTicks() - tc) / 50) {\r\n\t\t\tif (i == prevFadeValue) {\r\n\t\t\t\tSDL_Delay(1);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tApplyFadeLevel(256 - i, system_palette.data(), palette);\r\n\t\t\tSystemPaletteUpdated();\r\n\t\t\tprevFadeValue = i;\r\n\r\n\t\t\tBltFast(nullptr, nullptr);\r\n\t\t\tRenderPresent();\r\n\t\t}\r\n\t}\r\n\r\n\tBlackPalette();\r\n\tif (IsHardwareCursor()) ReinitializeHardwareCursor();\r\n\r\n\tif (fr <= 0) {\r\n\t\tBltFast(nullptr, nullptr);\r\n\t\tRenderPresent();\r\n\t}\r\n\r\n\tsgbFadedIn = false;\r\n}\r\n\r\nvoid palette_update_caves()\r\n{\r\n\tCycleColors(1, 31);\r\n\tSystemPaletteUpdated(1, 31);\r\n}\r\n\r\n/**\r\n * @brief Cycle the lava every other frame, and glow every frame\r\n * Lava has 15 colors and the glow 16, so the full animation has 240 frames before it loops\r\n */\r\nvoid palette_update_crypt()\r\n{\r\n\tstatic bool delayLava = false;\r\n\r\n\tif (!delayLava) {\r\n\t\tCycleColorsReverse(1, 15);\r\n\t\tdelayLava = false;\r\n\t}\r\n\r\n\tCycleColorsReverse(16, 31);\r\n\tSystemPaletteUpdated(1, 31);\r\n\tdelayLava = !delayLava;\r\n}\r\n\r\n/**\r\n * @brief Cycle the pond waves and bubles colors every 3rd frame\r\n * Bubles have 8 colors and waves 7, so the full animation has 56 frames before it loops\r\n */\r\nvoid palette_update_hive()\r\n{\r\n\tstatic uint8_t delay = 0;\r\n\r\n\tif (delay != 2) {\r\n\t\tdelay++;\r\n\t\treturn;\r\n\t}\r\n\r\n\tCycleColorsReverse(1, 8);\r\n\tCycleColorsReverse(9, 15);\r\n\tSystemPaletteUpdated(1, 15);\r\n\tdelay = 0;\r\n}\r\n\r\nvoid SetLogicalPaletteColor(unsigned i, const SDL_Color &color)\r\n{\r\n\tlogical_palette[i] = color;\r\n\tApplyGlobalBrightnessSingleColor(system_palette[i], logical_palette[i]);\r\n\tSystemPaletteUpdated(i, 1);\r\n\tUpdateBlendedLookupTableSingleColor(logical_palette.data(), i);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/palette.h",
    "content": "/**\r\n * @file palette.h\r\n *\r\n * Interface of functions for handling the engines color palette.\r\n */\r\n#pragma once\r\n\r\n#include <array>\r\n#include <cstdint>\r\n#include <span>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"levels/gendung_defs.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n// Diablo uses a 256 color palette\r\n// Entry 0-127 (0x00-0x7F) are level specific\r\n// Entry 128-255 (0x80-0xFF) are global\r\n\r\n// standard palette for all levels\r\n// 8 or 16 shades per color\r\n// example (dark blue): PAL16_BLUE+14, PAL8_BLUE+7\r\n// example (light red): PAL16_RED+2, PAL8_RED\r\n// example (orange): PAL16_ORANGE+8, PAL8_ORANGE+4\r\n#define PAL8_BLUE 128\r\n#define PAL8_RED 136\r\n#define PAL8_YELLOW 144\r\n#define PAL8_ORANGE 152\r\n#define PAL16_BEIGE 160\r\n#define PAL16_BLUE 176\r\n#define PAL16_YELLOW 192\r\n#define PAL16_ORANGE 208\r\n#define PAL16_RED 224\r\n#define PAL16_GRAY 240\r\n\r\n/**\r\n * @brief An RGB color without an alpha component.\r\n */\r\nstruct Color {\r\n\tuint8_t rgb[3];\r\n\r\n\t[[nodiscard]] SDL_Color toSDL() const\r\n\t{\r\n\t\tSDL_Color sdlColor;\r\n\t\tsdlColor.r = rgb[0];\r\n\t\tsdlColor.g = rgb[1];\r\n\t\tsdlColor.b = rgb[2];\r\n#ifndef USE_SDL1\r\n\t\tsdlColor.a = SDL_ALPHA_OPAQUE;\r\n#endif\r\n\t\treturn sdlColor;\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief The palette before global brightness / fade effects.\r\n *\r\n * However, color cycling / swapping is applied to this palette.\r\n */\r\nextern std::array<SDL_Color, 256> logical_palette;\r\n\r\n/**\r\n * @brief This palette is the actual palette used for rendering.\r\n *\r\n * It is usually `logical_palette` with the global brightness setting\r\n * and fade-in/out applied.\r\n */\r\nextern std::array<SDL_Color, 256> system_palette;\r\n\r\nvoid palette_init();\r\n\r\n/**\r\n * @brief Loads `logical_palette` from path.\r\n */\r\nvoid LoadPalette(const char *path);\r\n\r\n/**\r\n * @brief Loads `logical_palette` from path, and generates the blending lookup table\r\n */\r\nvoid LoadPaletteAndInitBlending(const char *path);\r\n\r\n/**\r\n * @brief Sets a single `logical_palette` color and updates the corresponding `system_color`.\r\n */\r\nvoid SetLogicalPaletteColor(unsigned colorIndex, const SDL_Color &color);\r\n\r\nvoid LoadRndLvlPal(dungeon_type l);\r\nvoid IncreaseBrightness();\r\n\r\n/**\r\n * @brief Updates the system palette by copying from `src` and applying the global brightness setting.\r\n *\r\n * `src` which is usually `logical_palette`.\r\n */\r\nvoid UpdateSystemPalette(std::span<const SDL_Color, 256> src);\r\n\r\n/**\r\n * @brief Fade screen from black\r\n * @param fr Steps per 50ms\r\n */\r\nvoid PaletteFadeIn(int fr, const std::array<SDL_Color, 256> &srcPalette = logical_palette);\r\n\r\n/**\r\n * @brief Fade screen to black\r\n * @param fr Steps per 50ms\r\n */\r\nvoid PaletteFadeOut(int fr, const std::array<SDL_Color, 256> &srcPalette = logical_palette);\r\n\r\n/**\r\n * @brief Applies global brightness setting to `src` and writes the result to `dst`.\r\n */\r\nvoid ApplyGlobalBrightness(SDL_Color *dst, const SDL_Color *src);\r\n\r\n/**\r\n * @brief Applies a fade-to-black effect to `src` and writes the result to `dst`.\r\n *\r\n * @param fadeval 0 - completely black, 256 - no effect.\r\n */\r\nvoid ApplyFadeLevel(unsigned fadeval, SDL_Color *dst, const SDL_Color *src);\r\n\r\n/**\r\n * @brief Call this when `system_palette` is updated directly.\r\n *\r\n * You do not need to call this when updating the system palette via `UpdateSystemPalette`, `PaletteFadeIn/Out`, or `BlackPalette`.\r\n */\r\nvoid SystemPaletteUpdated(int first = 0, int ncolor = 256);\r\n\r\nvoid DecreaseBrightness();\r\nint UpdateBrightness(int sliderValue);\r\n\r\n/**\r\n * @brief Sets `system_palette` to all-black and calls `SystemPaletteUpdated`.\r\n */\r\nvoid BlackPalette();\r\n\r\nvoid palette_update_caves();\r\nvoid palette_update_crypt();\r\nvoid palette_update_hive();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/path.cpp",
    "content": "/**\r\n * @file path.cpp\r\n *\r\n * Implementation of the path finding algorithms.\r\n */\r\n#include \"engine/path.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cmath>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <utility>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"crawl.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/static_vector.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n// The frame times for axis-aligned and diagonal steps are actually the same.\r\n//\r\n// However, we set the diagonal step cost a bit higher to avoid\r\n// excessive diagonal movement. For example, the frame times for these\r\n// two paths are the same: ↑↑ and ↗↖. However, ↑↑ looks more natural.\r\nconst int PathAxisAlignedStepCost = 100;\r\nconst int PathDiagonalStepCost = 101;\r\n\r\nnamespace {\r\n\r\nconstexpr size_t MaxPathNodes = 1024;\r\n\r\nusing NodeIndexType = uint16_t;\r\nusing CoordType = uint8_t;\r\nusing CostType = uint16_t;\r\nusing PointT = PointOf<CoordType>;\r\n\r\nstruct FrontierNode {\r\n\tPointT position;\r\n\r\n\t// Current best guess of the cost of the path to destination\r\n\t// if it goes through this node.\r\n\tCostType f;\r\n};\r\n\r\nstruct ExploredNode {\r\n\t// Preceding node (needed to reconstruct the path at the end).\r\n\tPointT prev;\r\n\r\n\t// The current lowest cost from start to this node (0 for the start node).\r\n\tCostType g;\r\n};\r\n\r\n// A simple map with a fixed number of buckets and static storage.\r\nclass ExploredNodes {\r\n\tstatic const size_t NumBuckets = 64;\r\n\tstatic const size_t BucketCapacity = 3 * MaxPathNodes / NumBuckets;\r\n\tusing Entry = std::pair<uint16_t, ExploredNode>;\r\n\tusing Bucket = StaticVector<Entry, BucketCapacity>;\r\n\r\npublic:\r\n\tusing value_type = Entry;\r\n\tusing iterator = value_type *;\r\n\tusing const_iterator = const value_type *;\r\n\r\n\t[[nodiscard]] const_iterator find(const PointT &point) const\r\n\t{\r\n\t\tconst Bucket &b = bucket(point);\r\n\t\tconst auto *const it = c_find_if(b, [r = repr(point)](const Entry &e) { return e.first == r; });\r\n\t\tif (it == b.end()) return nullptr;\r\n\t\treturn it;\r\n\t}\r\n\t[[nodiscard]] iterator find(const PointT &point)\r\n\t{\r\n\t\tBucket &b = bucket(point);\r\n\t\tauto *it = c_find_if(b, [r = repr(point)](const Entry &e) { return e.first == r; });\r\n\t\tif (it == b.end()) return nullptr;\r\n\t\treturn it;\r\n\t}\r\n\r\n\t// NOLINTNEXTLINE(readability-convert-member-functions-to-static)\r\n\t[[nodiscard]] const_iterator end() const { return nullptr; }\r\n\t// NOLINTNEXTLINE(readability-convert-member-functions-to-static)\r\n\t[[nodiscard]] iterator end() { return nullptr; }\r\n\r\n\tvoid emplace(const PointT &point, const ExploredNode &exploredNode)\r\n\t{\r\n\t\tbucket(point).emplace_back(repr(point), exploredNode);\r\n\t}\r\n\r\n\t[[nodiscard]] bool canInsert(const PointT &point) const\r\n\t{\r\n\t\treturn bucket(point).size() < BucketCapacity;\r\n\t}\r\n\r\nprivate:\r\n\t[[nodiscard]] const Bucket &bucket(const PointT &point) const { return buckets_[bucketIndex(point)]; }\r\n\t[[nodiscard]] Bucket &bucket(const PointT &point) { return buckets_[bucketIndex(point)]; }\r\n\t[[nodiscard]] static size_t bucketIndex(const PointT &point)\r\n\t{\r\n\t\treturn ((point.x & 0b111) << 3) | (point.y & 0b111);\r\n\t}\r\n\r\n\t[[nodiscard]] static uint16_t repr(const PointT &point)\r\n\t{\r\n\t\treturn (point.x << 8) | point.y;\r\n\t}\r\n\r\n\tstd::array<Bucket, NumBuckets> buckets_;\r\n};\r\n\r\nbool IsDiagonalStep(const Point &a, const Point &b)\r\n{\r\n\treturn a.x != b.x && a.y != b.y;\r\n}\r\n\r\n/**\r\n * @brief Returns the distance between 2 adjacent nodes.\r\n */\r\nCostType GetDistance(PointT startPosition, PointT destinationPosition)\r\n{\r\n\treturn IsDiagonalStep(startPosition, destinationPosition)\r\n\t    ? PathDiagonalStepCost\r\n\t    : PathAxisAlignedStepCost;\r\n}\r\n\r\n/**\r\n * @brief heuristic, estimated cost from startPosition to destinationPosition.\r\n */\r\nCostType GetHeuristicCost(PointT startPosition, PointT destinationPosition)\r\n{\r\n\t// This function needs to be admissible, i.e. it should never over-estimate\r\n\t// the distance.\r\n\t//\r\n\t// This calculation assumes we can take diagonal steps until we reach\r\n\t// the same row or column and then take the remaining axis-aligned steps.\r\n\tconst int dx = std::abs(static_cast<int>(startPosition.x) - static_cast<int>(destinationPosition.x));\r\n\tconst int dy = std::abs(static_cast<int>(startPosition.y) - static_cast<int>(destinationPosition.y));\r\n\tconst int diagSteps = std::min(dx, dy);\r\n\r\n\t// After we've taken `diagSteps`, the remaining steps in one coordinate\r\n\t// will be zero, and in the other coordinate it will be reduced by `diagSteps`.\r\n\t// We then still need to take the remaining steps:\r\n\t//   max(dx, dy) - diagSteps = max(dx, dy) - min(dx, dy) = abs(dx - dy)\r\n\tconst int axisAlignedSteps = std::abs(dx - dy);\r\n\treturn diagSteps * PathDiagonalStepCost + axisAlignedSteps * PathAxisAlignedStepCost;\r\n}\r\n\r\nint ReconstructPath(const ExploredNodes &explored, PointT dest, int8_t *path, size_t maxPathLength)\r\n{\r\n\tsize_t len = 0;\r\n\tPointT cur = dest;\r\n\twhile (true) {\r\n\t\tconst auto *const it = explored.find(cur);\r\n\t\tif (it == explored.end()) app_fatal(\"Failed to reconstruct path\");\r\n\t\tif (it->second.g == 0) break; // reached start\r\n\t\tif (len == maxPathLength) {\r\n\t\t\t// Path too long.\r\n\t\t\tlen = 0;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tpath[len++] = GetPathDirection(it->second.prev, cur);\r\n\t\tcur = it->second.prev;\r\n\t}\r\n\tstd::reverse(path, path + len);\r\n\tstd::fill(path + len, path + maxPathLength, -1);\r\n\treturn static_cast<int>(len);\r\n}\r\n\r\n} // namespace\r\n\r\nint8_t GetPathDirection(Point startPosition, Point destinationPosition)\r\n{\r\n\tconstexpr int8_t PathDirections[9] = { 5, 1, 6, 2, 0, 3, 8, 4, 7 };\r\n\treturn PathDirections[3 * (destinationPosition.y - startPosition.y) + 4 + destinationPosition.x - startPosition.x];\r\n}\r\n\r\nint FindPath(tl::function_ref<bool(Point, Point)> canStep, tl::function_ref<bool(Point)> posOk, Point startPosition, Point destinationPosition, int8_t *path, size_t maxPathLength)\r\n{\r\n\tconst PointT start { startPosition };\r\n\tconst PointT dest { destinationPosition };\r\n\r\n\tconst CostType initialHeuristicCost = GetHeuristicCost(start, dest);\r\n\tif (initialHeuristicCost > PathDiagonalStepCost * maxPathLength) {\r\n\t\t// Heuristic cost never underestimates the true cost, so we can give up early.\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tStaticVector<FrontierNode, MaxPathNodes> frontier;\r\n\tExploredNodes explored;\r\n\t{\r\n\t\tfrontier.emplace_back(FrontierNode { .position = start, .f = initialHeuristicCost });\r\n\t\texplored.emplace(start, ExploredNode { .prev = {}, .g = 0 });\r\n\t}\r\n\r\n\tconst auto frontierComparator = [&explored, &dest](const FrontierNode &a, const FrontierNode &b) {\r\n\t\t// We use heap functions from <algorithm> which form a max-heap.\r\n\t\t// We reverse the comparison sign here to get a min-heap.\r\n\t\tif (a.f != b.f) return a.f > b.f;\r\n\r\n\t\t// For nodes with the same f-score, prefer the ones with lower\r\n\t\t// heuristic cost (likely to be closer to the goal).\r\n\t\tconst CostType hA = GetHeuristicCost(a.position, dest);\r\n\t\tconst CostType hB = GetHeuristicCost(b.position, dest);\r\n\t\tif (hA != hB) return hA > hB;\r\n\r\n\t\t// Prefer diagonal steps first.\r\n\t\tconst ExploredNode &aInfo = explored.find(a.position)->second;\r\n\t\tconst ExploredNode &bInfo = explored.find(b.position)->second;\r\n\t\tconst bool isDiagonalA = IsDiagonalStep(aInfo.prev, a.position);\r\n\t\tconst bool isDiagonalB = IsDiagonalStep(bInfo.prev, b.position);\r\n\t\tif (isDiagonalA != isDiagonalB) return isDiagonalB;\r\n\r\n\t\t// Finally, disambiguate by coordinate:\r\n\t\tif (a.position.x != b.position.x) return a.position.x > b.position.x;\r\n\t\treturn a.position.y > b.position.y;\r\n\t};\r\n\r\n\twhile (!frontier.empty()) {\r\n\t\tconst FrontierNode cur = frontier.front(); // argmin(node.f) for node in openSet\r\n\r\n\t\tif (cur.position == destinationPosition) {\r\n\t\t\treturn ReconstructPath(explored, cur.position, path, maxPathLength);\r\n\t\t}\r\n\r\n\t\tstd::pop_heap(frontier.begin(), frontier.end(), frontierComparator);\r\n\t\tfrontier.pop_back();\r\n\t\tconst CostType curG = explored.find(cur.position)->second.g;\r\n\r\n\t\t// Discard invalid nodes.\r\n\r\n\t\t// If this node is already at the maximum number of steps, we can skip processing it.\r\n\t\t// We don't keep track of the maximum number of steps, so we approximate it.\r\n\t\tif (curG >= PathDiagonalStepCost * maxPathLength) continue;\r\n\r\n\t\t// When we discover a better path to a node, we push the node to the heap\r\n\t\t// with the new `f` value even if the node is already in the heap.\r\n\t\tif (curG + GetHeuristicCost(cur.position, dest) > cur.f) continue;\r\n\r\n\t\tfor (const DisplacementOf<int8_t> d : PathDirs) {\r\n\t\t\t// We're using `uint8_t` for coordinates. Avoid underflow:\r\n\t\t\tif ((cur.position.x == 0 && d.deltaX < 0) || (cur.position.y == 0 && d.deltaY < 0)) continue;\r\n\t\t\tconst PointT neighborPos = cur.position + d;\r\n\t\t\tconst bool ok = posOk(neighborPos);\r\n\t\t\tif (ok) {\r\n\t\t\t\tif (!canStep(cur.position, neighborPos)) continue;\r\n\t\t\t} else {\r\n\t\t\t\t// We allow targeting a non-walkable node if it is the destination.\r\n\t\t\t\tif (neighborPos != dest) continue;\r\n\t\t\t}\r\n\t\t\tconst CostType g = curG + GetDistance(cur.position, neighborPos);\r\n\t\t\tif (curG >= PathDiagonalStepCost * maxPathLength) continue;\r\n\t\t\tbool improved = false;\r\n\t\t\tif (auto *it = explored.find(neighborPos); it == explored.end()) {\r\n\t\t\t\tif (explored.canInsert(neighborPos)) {\r\n\t\t\t\t\texplored.emplace(neighborPos, ExploredNode { .prev = cur.position, .g = g });\r\n\t\t\t\t\timproved = true;\r\n\t\t\t\t}\r\n\t\t\t} else if (it->second.g > g) {\r\n\t\t\t\tit->second.prev = cur.position;\r\n\t\t\t\tit->second.g = g;\r\n\t\t\t\timproved = true;\r\n\t\t\t}\r\n\t\t\tif (improved) {\r\n\t\t\t\tconst CostType f = g + GetHeuristicCost(neighborPos, dest);\r\n\t\t\t\tif (frontier.size() < MaxPathNodes) {\r\n\t\t\t\t\t// We always push the node to the heap, even if the same position already exists in it.\r\n\t\t\t\t\t// When popping from the heap, we discard invalid nodes by checking that `g + h <= f`.\r\n\t\t\t\t\tfrontier.emplace_back(FrontierNode { .position = neighborPos, .f = f });\r\n\t\t\t\t\tstd::push_heap(frontier.begin(), frontier.end(), frontierComparator);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0; // no path\r\n}\r\n\r\nstd::optional<Point> FindClosestValidPosition(tl::function_ref<bool(Point)> posOk, Point startingPosition, unsigned int minimumRadius, unsigned int maximumRadius)\r\n{\r\n\treturn Crawl(minimumRadius, maximumRadius, [&](Displacement displacement) -> std::optional<Point> {\r\n\t\tPoint candidatePosition = startingPosition + displacement;\r\n\t\tif (posOk(candidatePosition))\r\n\t\t\treturn candidatePosition;\r\n\t\treturn {};\r\n\t});\r\n}\r\n\r\n#ifdef BUILD_TESTING\r\nint TestPathGetHeuristicCost(Point startPosition, Point destinationPosition)\r\n{\r\n\treturn GetHeuristicCost(startPosition, destinationPosition);\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/path.h",
    "content": "/**\r\n * @file path.h\r\n *\r\n * Interface of the path finding algorithms.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr size_t MaxPathLengthMonsters = 25;\r\nconstexpr size_t MaxPathLengthPlayer = 100;\r\n\r\n// Cost for an axis-aligned step (up/down/left/right). Visible for testing.\r\nextern const int PathAxisAlignedStepCost;\r\n\r\n// Cost for a diagonal step. Visible for testing.\r\nextern const int PathDiagonalStepCost;\r\n\r\n/**\r\n * @brief Find the shortest path from `startPosition` to `destinationPosition`.\r\n *\r\n * @param canStep specifies whether a step between two adjacent points is allowed.\r\n * @param posOk specifies whether a position can be stepped on.\r\n * @param startPosition\r\n * @param destinationPosition\r\n * @param path Resulting path represented as the step directions, which are indices in `PathDirs`. Must have room for `maxPathLength` steps.\r\n * @param maxPathLength The maximum allowed length of the resulting path.\r\n * @return The length of the resulting path, or 0 if there is no valid path.\r\n */\r\nint FindPath(tl::function_ref<bool(Point, Point)> canStep, tl::function_ref<bool(Point)> posOk, Point startPosition, Point destinationPosition, int8_t *path, size_t maxPathLength);\r\n\r\n/** For iterating over the 8 possible movement directions */\r\nconst Displacement PathDirs[8] = {\r\n\t// clang-format off\r\n\t{ -1, -1 }, //Direction::North\r\n\t{ -1,  1 }, //Direction::West\r\n\t{  1, -1 }, //Direction::East\r\n\t{  1,  1 }, //Direction::South\r\n\t{ -1,  0 }, //Direction::NorthWest\r\n\t{  0, -1 }, //Direction::NorthEast\r\n\t{  1,  0 }, //Direction::SouthEast\r\n\t{  0,  1 }, //Direction::SouthWest\r\n\t// clang-format on\r\n};\r\n\r\n/**\r\n * Returns a number representing the direction from a starting tile to a neighbouring tile.\r\n *\r\n * Used in the pathfinding code, each step direction is assigned a number like this:\r\n *       dx\r\n *     -1 0 1\r\n *     +-----\r\n *   -1|5 1 6\r\n * dy 0|2 0 3\r\n *    1|8 4 7\r\n */\r\n[[nodiscard]] int8_t GetPathDirection(Point startPosition, Point destinationPosition);\r\n\r\n/**\r\n * @brief Searches for the closest position that passes the check in expanding \"rings\".\r\n *\r\n * The search space is roughly equivalent to a square of tiles where the walking distance is equal to the radius except\r\n * the corners are \"rounded\" (inset) by one tile. For example the following is a search space of radius 4:\r\n * _XXXXXXX_\r\n * XX_____XX\r\n * X_______X\r\n * < snip  >\r\n * X_______X\r\n * XX_____XX\r\n * _XXXXXXX_\r\n *\r\n * @param posOk Used to check if a position is valid\r\n * @param startingPosition dungeon tile location to start the search from\r\n * @param minimumRadius A value from 0 to 50, allows skipping nearby tiles (e.g. specify radius 1 to skip checking the starting tile)\r\n * @param maximumRadius The maximum distance to check, defaults to 18 for vanilla compatibility but supports values up to 50\r\n * @return either the closest valid point or an empty optional\r\n */\r\nstd::optional<Point> FindClosestValidPosition(tl::function_ref<bool(Point)> posOk, Point startingPosition, unsigned int minimumRadius = 0, unsigned int maximumRadius = 18);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/point.hpp",
    "content": "#pragma once\r\n\r\n#include <algorithm>\r\n#include <cmath>\r\n#include <type_traits>\r\n#ifdef BUILD_TESTING\r\n#include <ostream>\r\n#endif\r\n\r\n#include \"engine/direction.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename CoordT>\r\nstruct PointOf;\r\n\r\nusing Point = PointOf<int>;\r\n\r\ntemplate <typename PointCoordT, typename OtherPointCoordT>\r\nconstexpr DisplacementOf<PointCoordT> operator-(PointOf<PointCoordT> a, PointOf<OtherPointCoordT> b);\r\n\r\ntemplate <typename CoordT>\r\nstruct PointOf {\r\n\tCoordT x;\r\n\tCoordT y;\r\n\r\n\tPointOf() = default;\r\n\r\n\ttemplate <typename PointCoordT>\r\n\tDVL_ALWAYS_INLINE constexpr PointOf(PointOf<PointCoordT> other)\r\n\t    : x(other.x)\r\n\t    , y(other.y)\r\n\t{\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr PointOf(CoordT x, CoordT y)\r\n\t    : x(x)\r\n\t    , y(y)\r\n\t{\r\n\t}\r\n\r\n\ttemplate <typename PointCoordT>\r\n\tDVL_ALWAYS_INLINE explicit constexpr PointOf(DisplacementOf<PointCoordT> other)\r\n\t    : x(other.deltaX)\r\n\t    , y(other.deltaY)\r\n\t{\r\n\t}\r\n\r\n\ttemplate <typename PointCoordT>\r\n\tDVL_ALWAYS_INLINE constexpr bool operator==(const PointOf<PointCoordT> &other) const\r\n\t{\r\n\t\treturn x == other.x && y == other.y;\r\n\t}\r\n\r\n\ttemplate <typename PointCoordT>\r\n\tDVL_ALWAYS_INLINE constexpr bool operator!=(const PointOf<PointCoordT> &other) const\r\n\t{\r\n\t\treturn !(*this == other);\r\n\t}\r\n\r\n\ttemplate <typename DisplacementDeltaT = int>\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> &operator+=(const DisplacementOf<DisplacementDeltaT> &displacement)\r\n\t{\r\n\t\tx += displacement.deltaX;\r\n\t\ty += displacement.deltaY;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> &operator+=(Direction direction)\r\n\t{\r\n\t\treturn (*this) += DisplacementOf<typename std::make_signed<CoordT>::type>(direction);\r\n\t}\r\n\r\n\ttemplate <typename DisplacementDeltaT = int>\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> &operator-=(const DisplacementOf<DisplacementDeltaT> &displacement)\r\n\t{\r\n\t\tx -= displacement.deltaX;\r\n\t\ty -= displacement.deltaY;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> &operator*=(const float factor)\r\n\t{\r\n\t\tx = static_cast<int>(x * factor);\r\n\t\ty = static_cast<int>(y * factor);\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> &operator*=(const int factor)\r\n\t{\r\n\t\tx *= factor;\r\n\t\ty *= factor;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> &operator/=(const int factor)\r\n\t{\r\n\t\tx /= factor;\r\n\t\ty /= factor;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> operator-() const\r\n\t{\r\n\t\tstatic_assert(std::is_signed<CoordT>::value, \"CoordT must be signed\");\r\n\t\treturn { -x, -y };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Fast approximate distance between two points, using only integer arithmetic, with less than ~5% error\r\n\t * @param other Pointer to which we want the distance\r\n\t * @return Magnitude of vector this -> other\r\n\t */\r\n\r\n\ttemplate <typename PointCoordT>\r\n\tconstexpr int ApproxDistance(PointOf<PointCoordT> other) const\r\n\t{\r\n\t\tconst Displacement offset = abs(Point(*this) - Point(other));\r\n\t\tconst auto [min, max] = std::minmax(offset.deltaX, offset.deltaY);\r\n\r\n\t\tint approx = max * 1007 + min * 441;\r\n\t\tif (max < (min * 16))\r\n\t\t\tapprox -= max * 40;\r\n\r\n\t\treturn (approx + 512) / 1024;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Calculates the exact distance between two points (as accurate as the closest integer representation)\r\n\t *\r\n\t * In practice it is likely that ApproxDistance gives the same result, especially for nearby points.\r\n\t * @param other Point to which we want the distance\r\n\t * @return Exact magnitude of vector this -> other\r\n\t */\r\n\ttemplate <typename PointCoordT>\r\n\tint ExactDistance(PointOf<PointCoordT> other) const\r\n\t{\r\n\t\tconst Displacement vector = Point(*this) - Point(other); // No need to call abs() as we square the values anyway\r\n\r\n\t\t// Casting multiplication operands to a wide type to address overflow warnings\r\n\t\treturn static_cast<int>(std::sqrt(static_cast<int64_t>(vector.deltaX) * vector.deltaX + static_cast<int64_t>(vector.deltaY) * vector.deltaY));\r\n\t}\r\n\r\n\ttemplate <typename PointCoordT>\r\n\tDVL_ALWAYS_INLINE constexpr int ManhattanDistance(PointOf<PointCoordT> other) const\r\n\t{\r\n\t\treturn std::abs(static_cast<int>(x) - static_cast<int>(other.x))\r\n\t\t    + std::abs(static_cast<int>(y) - static_cast<int>(other.y));\r\n\t}\r\n\r\n\ttemplate <typename PointCoordT>\r\n\tDVL_ALWAYS_INLINE constexpr int WalkingDistance(PointOf<PointCoordT> other) const\r\n\t{\r\n\t\treturn std::max<int>(\r\n\t\t    std::abs(static_cast<int>(x) - static_cast<int>(other.x)),\r\n\t\t    std::abs(static_cast<int>(y) - static_cast<int>(other.y)));\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Converts a coordinate in megatiles to the northmost of the 4 corresponding world tiles\r\n\t */\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> megaToWorld() const\r\n\t{\r\n\t\treturn { static_cast<CoordT>(16 + 2 * x), static_cast<CoordT>(16 + 2 * y) };\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Converts a coordinate in world tiles back to the corresponding megatile\r\n\t */\r\n\tDVL_ALWAYS_INLINE constexpr PointOf<CoordT> worldToMega() const\r\n\t{\r\n\t\treturn { static_cast<CoordT>((x - 16) / 2), static_cast<CoordT>((y - 16) / 2) };\r\n\t}\r\n};\r\n\r\n#ifdef BUILD_TESTING\r\n/**\r\n * @brief Format points nicely in test failure messages\r\n * @param stream output stream, expected to have overloads for int and char*\r\n * @param point Object to display\r\n * @return the stream, to allow chaining\r\n */\r\ntemplate <typename PointCoordT>\r\nstd::ostream &operator<<(std::ostream &stream, const PointOf<PointCoordT> &point)\r\n{\r\n\treturn stream << \"(x: \" << point.x << \", y: \" << point.y << \")\";\r\n}\r\n#endif\r\n\r\ntemplate <typename PointCoordT, typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr PointOf<PointCoordT> operator+(PointOf<PointCoordT> a, DisplacementOf<DisplacementDeltaT> displacement)\r\n{\r\n\ta += displacement;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename PointCoordT>\r\nDVL_ALWAYS_INLINE constexpr PointOf<PointCoordT> operator+(PointOf<PointCoordT> a, Direction direction)\r\n{\r\n\ta += direction;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename PointCoordT, typename OtherPointCoordT>\r\nDVL_ALWAYS_INLINE constexpr DisplacementOf<PointCoordT> operator-(PointOf<PointCoordT> a, PointOf<OtherPointCoordT> b)\r\n{\r\n\tstatic_assert(std::is_signed<PointCoordT>::value == std::is_signed<OtherPointCoordT>::value, \"points must have the same signedness\");\r\n\treturn { static_cast<PointCoordT>(a.x - b.x), static_cast<PointCoordT>(a.y - b.y) };\r\n}\r\n\r\ntemplate <typename PointCoordT, typename DisplacementDeltaT>\r\nDVL_ALWAYS_INLINE constexpr PointOf<PointCoordT> operator-(PointOf<PointCoordT> a, DisplacementOf<DisplacementDeltaT> displacement)\r\n{\r\n\ta -= displacement;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename PointCoordT>\r\nDVL_ALWAYS_INLINE constexpr PointOf<PointCoordT> operator*(PointOf<PointCoordT> a, const float factor)\r\n{\r\n\ta *= factor;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename PointCoordT>\r\nDVL_ALWAYS_INLINE constexpr PointOf<PointCoordT> operator*(PointOf<PointCoordT> a, const int factor)\r\n{\r\n\ta *= factor;\r\n\treturn a;\r\n}\r\n\r\ntemplate <typename PointCoordT>\r\nDVL_ALWAYS_INLINE constexpr PointOf<PointCoordT> abs(PointOf<PointCoordT> a)\r\n{\r\n\treturn { std::abs(a.x), std::abs(a.y) };\r\n}\r\n\r\n/**\r\n * @brief Calculate the best fit direction between two points\r\n * @param start Tile coordinate\r\n * @param destination Tile coordinate\r\n * @return A value from the direction enum\r\n */\r\ninline Direction GetDirection(Point start, Point destination)\r\n{\r\n\tDirection md;\r\n\r\n\tint mx = destination.x - start.x;\r\n\tint my = destination.y - start.y;\r\n\tif (mx >= 0) {\r\n\t\tif (my >= 0) {\r\n\t\t\tif (5 * mx <= (my * 2)) // mx/my <= 0.4, approximation of tan(22.5)\r\n\t\t\t\treturn Direction::SouthWest;\r\n\t\t\tmd = Direction::South;\r\n\t\t} else {\r\n\t\t\tmy = -my;\r\n\t\t\tif (5 * mx <= (my * 2))\r\n\t\t\t\treturn Direction::NorthEast;\r\n\t\t\tmd = Direction::East;\r\n\t\t}\r\n\t\tif (5 * my <= (mx * 2)) // my/mx <= 0.4\r\n\t\t\tmd = Direction::SouthEast;\r\n\t} else {\r\n\t\tmx = -mx;\r\n\t\tif (my >= 0) {\r\n\t\t\tif (5 * mx <= (my * 2))\r\n\t\t\t\treturn Direction::SouthWest;\r\n\t\t\tmd = Direction::West;\r\n\t\t} else {\r\n\t\t\tmy = -my;\r\n\t\t\tif (5 * mx <= (my * 2))\r\n\t\t\t\treturn Direction::NorthEast;\r\n\t\t\tmd = Direction::North;\r\n\t\t}\r\n\t\tif (5 * my <= (mx * 2))\r\n\t\t\tmd = Direction::NorthWest;\r\n\t}\r\n\treturn md;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/points_in_rectangle_range.hpp",
    "content": "#pragma once\r\n\r\n#include <iterator>\r\n\r\n#include \"point.hpp\"\r\n#include \"rectangle.hpp\"\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename CoordT>\r\nclass PointsInRectangleIteratorBase {\r\npublic:\r\n\tusing iterator_category = std::random_access_iterator_tag;\r\n\tusing difference_type = CoordT;\r\n\tusing value_type = PointOf<CoordT>;\r\n\tusing pointer = void;\r\n\tusing reference = value_type;\r\n\r\nprotected:\r\n\tconstexpr PointsInRectangleIteratorBase(PointOf<CoordT> origin, int majorDimension, int majorIndex, int minorIndex)\r\n\t    : origin(origin)\r\n\t    , majorDimension(majorDimension)\r\n\t    , majorIndex(majorIndex)\r\n\t    , minorIndex(minorIndex)\r\n\t{\r\n\t}\r\n\r\n\texplicit constexpr PointsInRectangleIteratorBase(PointOf<CoordT> origin, int majorDimension, int index = 0)\r\n\t    : PointsInRectangleIteratorBase(origin, majorDimension, index / majorDimension, index % majorDimension)\r\n\t{\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE void Increment()\r\n\t{\r\n\t\t++minorIndex;\r\n\t\tif (minorIndex >= majorDimension) {\r\n\t\t\t++majorIndex;\r\n\t\t\tminorIndex -= majorDimension;\r\n\t\t}\r\n\t}\r\n\r\n\tvoid Decrement()\r\n\t{\r\n\t\tif (minorIndex <= 0) {\r\n\t\t\t--majorIndex;\r\n\t\t\tminorIndex += majorDimension;\r\n\t\t}\r\n\t\t--minorIndex;\r\n\t}\r\n\r\n\tvoid Offset(difference_type delta)\r\n\t{\r\n\t\tmajorIndex += (minorIndex + delta) / majorDimension;\r\n\t\tminorIndex = (minorIndex + delta) % majorDimension;\r\n\t\tif (minorIndex < 0) {\r\n\t\t\tminorIndex += majorDimension;\r\n\t\t\t--majorIndex;\r\n\t\t}\r\n\t}\r\n\r\n\tPointOf<CoordT> origin;\r\n\r\n\tint majorDimension;\r\n\r\n\tint majorIndex;\r\n\tint minorIndex;\r\n};\r\n\r\ntemplate <typename CoordT>\r\nclass PointsInRectangle {\r\npublic:\r\n\tusing const_iterator = class PointsInRectangleIterator : public PointsInRectangleIteratorBase<CoordT> {\r\n\tpublic:\r\n\t\tusing iterator_category = typename PointsInRectangleIteratorBase<CoordT>::iterator_category;\r\n\t\tusing difference_type = typename PointsInRectangleIteratorBase<CoordT>::difference_type;\r\n\t\tusing value_type = typename PointsInRectangleIteratorBase<CoordT>::value_type;\r\n\t\tusing pointer = typename PointsInRectangleIteratorBase<CoordT>::pointer;\r\n\t\tusing reference = typename PointsInRectangleIteratorBase<CoordT>::reference;\r\n\r\n\t\tconstexpr PointsInRectangleIterator(RectangleOf<CoordT> region, int index = 0)\r\n\t\t    : PointsInRectangleIteratorBase<CoordT>(region.position, region.size.width, index)\r\n\t\t{\r\n\t\t}\r\n\r\n\t\tDVL_ALWAYS_INLINE value_type operator*() const\r\n\t\t{\r\n\t\t\t// Row-major iteration e.g. {0, 0}, {1, 0}, {2, 0}, {0, 1}, {1, 1}, ...\r\n\t\t\treturn this->origin + Displacement { this->minorIndex, this->majorIndex };\r\n\t\t}\r\n\r\n\t\t// Equality comparable concepts\r\n\t\tDVL_ALWAYS_INLINE bool operator==(const PointsInRectangleIterator &rhs) const\r\n\t\t{\r\n\t\t\treturn this->majorIndex == rhs.majorIndex && this->minorIndex == rhs.minorIndex;\r\n\t\t}\r\n\r\n\t\tDVL_ALWAYS_INLINE bool operator!=(const PointsInRectangleIterator &rhs) const\r\n\t\t{\r\n\t\t\treturn !(*this == rhs);\r\n\t\t}\r\n\r\n\t\t// Partially ordered concepts\r\n\t\tbool operator>=(const PointsInRectangleIterator &rhs) const\r\n\t\t{\r\n\t\t\treturn this->majorIndex > rhs.majorIndex || (this->majorIndex == rhs.majorIndex && this->minorIndex >= rhs.minorIndex);\r\n\t\t}\r\n\r\n\t\tbool operator<(const PointsInRectangleIterator &rhs) const\r\n\t\t{\r\n\t\t\treturn !(*this >= rhs);\r\n\t\t}\r\n\r\n\t\tbool operator<=(const PointsInRectangleIterator &rhs) const\r\n\t\t{\r\n\t\t\treturn this->majorIndex < rhs.majorIndex || (this->majorIndex == rhs.majorIndex && this->minorIndex <= rhs.minorIndex);\r\n\t\t}\r\n\r\n\t\tbool operator>(const PointsInRectangleIterator &rhs) const\r\n\t\t{\r\n\t\t\treturn !(*this <= rhs);\r\n\t\t}\r\n\r\n\t\tdifference_type operator-(const PointsInRectangleIterator &rhs) const\r\n\t\t{\r\n\t\t\treturn (this->majorIndex - rhs.majorIndex) * this->majorDimension + (this->minorIndex - rhs.minorIndex);\r\n\t\t}\r\n\r\n\t\t// Forward concepts\r\n\t\tDVL_ALWAYS_INLINE PointsInRectangleIterator &operator++()\r\n\t\t{\r\n\t\t\tthis->Increment();\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIterator operator++(int)\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\t++(*this);\r\n\t\t\treturn copy;\r\n\t\t}\r\n\r\n\t\t// Bidirectional concepts\r\n\t\tPointsInRectangleIterator &operator--()\r\n\t\t{\r\n\t\t\tthis->Decrement();\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIterator operator--(int)\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\t--(*this);\r\n\t\t\treturn copy;\r\n\t\t}\r\n\r\n\t\t// Random access concepts\r\n\t\tPointsInRectangleIterator operator+(difference_type delta) const\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\treturn copy += delta;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIterator &operator+=(difference_type delta)\r\n\t\t{\r\n\t\t\tthis->Offset(delta);\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tfriend PointsInRectangleIterator operator+(difference_type delta, const PointsInRectangleIterator &it)\r\n\t\t{\r\n\t\t\treturn it + delta;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIterator &operator-=(difference_type delta)\r\n\t\t{\r\n\t\t\treturn *this += -delta;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIterator operator-(difference_type delta) const\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\treturn copy -= delta;\r\n\t\t}\r\n\r\n\t\tvalue_type operator[](difference_type offset) const\r\n\t\t{\r\n\t\t\treturn **(this + offset);\r\n\t\t}\r\n\t};\r\n\r\n\tconstexpr PointsInRectangle(RectangleOf<CoordT> region)\r\n\t    : region(region)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator cbegin() const\r\n\t{\r\n\t\treturn region;\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator begin() const\r\n\t{\r\n\t\treturn cbegin();\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator cend() const\r\n\t{\r\n\t\treturn { region, region.size.width * region.size.height };\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator end() const\r\n\t{\r\n\t\treturn cend();\r\n\t}\r\n\r\n\t[[nodiscard]] auto crbegin() const\r\n\t{\r\n\t\t// explicit type needed for older GCC versions\r\n\t\treturn std::reverse_iterator<const_iterator>(cend());\r\n\t}\r\n\r\n\t[[nodiscard]] auto rbegin() const\r\n\t{\r\n\t\treturn crbegin();\r\n\t}\r\n\r\n\t[[nodiscard]] auto crend() const\r\n\t{\r\n\t\t// explicit type needed for older GCC versions\r\n\t\treturn std::reverse_iterator<const_iterator>(cbegin());\r\n\t}\r\n\r\n\t[[nodiscard]] auto rend() const\r\n\t{\r\n\t\treturn crend();\r\n\t}\r\n\r\nprotected:\r\n\tRectangleOf<CoordT> region;\r\n};\r\n\r\ntemplate <typename CoordT>\r\nclass PointsInRectangleColMajor {\r\npublic:\r\n\tusing const_iterator = class PointsInRectangleIteratorColMajor : public PointsInRectangleIteratorBase<CoordT> {\r\n\tpublic:\r\n\t\tusing iterator_category = typename PointsInRectangleIteratorBase<CoordT>::iterator_category;\r\n\t\tusing difference_type = typename PointsInRectangleIteratorBase<CoordT>::difference_type;\r\n\t\tusing value_type = typename PointsInRectangleIteratorBase<CoordT>::value_type;\r\n\t\tusing pointer = typename PointsInRectangleIteratorBase<CoordT>::pointer;\r\n\t\tusing reference = typename PointsInRectangleIteratorBase<CoordT>::reference;\r\n\r\n\t\tconstexpr PointsInRectangleIteratorColMajor(RectangleOf<CoordT> region, int index = 0)\r\n\t\t    : PointsInRectangleIteratorBase<CoordT>(region.position, region.size.height, index)\r\n\t\t{\r\n\t\t}\r\n\r\n\t\tDVL_ALWAYS_INLINE value_type operator*() const\r\n\t\t{\r\n\t\t\t// Col-major iteration e.g. {0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, ...\r\n\t\t\treturn this->origin + Displacement { this->majorIndex, this->minorIndex };\r\n\t\t}\r\n\r\n\t\t// Equality comparable concepts\r\n\t\tDVL_ALWAYS_INLINE bool operator==(const PointsInRectangleIteratorColMajor &rhs) const\r\n\t\t{\r\n\t\t\treturn this->majorIndex == rhs.majorIndex && this->minorIndex == rhs.minorIndex;\r\n\t\t}\r\n\r\n\t\tDVL_ALWAYS_INLINE bool operator!=(const PointsInRectangleIteratorColMajor &rhs) const\r\n\t\t{\r\n\t\t\treturn !(*this == rhs);\r\n\t\t}\r\n\r\n\t\t// Partially ordered concepts\r\n\t\tbool operator>=(const PointsInRectangleIteratorColMajor &rhs) const\r\n\t\t{\r\n\t\t\treturn this->majorIndex > rhs.majorIndex || (this->majorIndex == rhs.majorIndex && this->minorIndex >= rhs.minorIndex);\r\n\t\t}\r\n\r\n\t\tbool operator<(const PointsInRectangleIteratorColMajor &rhs) const\r\n\t\t{\r\n\t\t\treturn !(*this >= rhs);\r\n\t\t}\r\n\r\n\t\tbool operator<=(const PointsInRectangleIteratorColMajor &rhs) const\r\n\t\t{\r\n\t\t\treturn this->majorIndex < rhs.majorIndex || (this->majorIndex == rhs.majorIndex && this->minorIndex <= rhs.minorIndex);\r\n\t\t}\r\n\r\n\t\tbool operator>(const PointsInRectangleIteratorColMajor &rhs) const\r\n\t\t{\r\n\t\t\treturn !(*this <= rhs);\r\n\t\t}\r\n\r\n\t\tdifference_type operator-(const PointsInRectangleIteratorColMajor &rhs) const\r\n\t\t{\r\n\t\t\treturn (this->majorIndex - rhs.majorIndex) * this->majorDimension + (this->minorIndex - rhs.minorIndex);\r\n\t\t}\r\n\r\n\t\t// Forward concepts\r\n\t\tDVL_ALWAYS_INLINE PointsInRectangleIteratorColMajor &operator++()\r\n\t\t{\r\n\t\t\tthis->Increment();\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIteratorColMajor operator++(int)\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\t++(*this);\r\n\t\t\treturn copy;\r\n\t\t}\r\n\r\n\t\t// Bidirectional concepts\r\n\t\tPointsInRectangleIteratorColMajor &operator--()\r\n\t\t{\r\n\t\t\tthis->Decrement();\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIteratorColMajor operator--(int)\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\t--(*this);\r\n\t\t\treturn copy;\r\n\t\t}\r\n\r\n\t\t// Random access concepts\r\n\t\tPointsInRectangleIteratorColMajor operator+(difference_type delta) const\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\treturn copy += delta;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIteratorColMajor &operator+=(difference_type delta)\r\n\t\t{\r\n\t\t\tthis->Offset(delta);\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tfriend PointsInRectangleIteratorColMajor operator+(difference_type delta, const PointsInRectangleIteratorColMajor &it)\r\n\t\t{\r\n\t\t\treturn it + delta;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIteratorColMajor &operator-=(difference_type delta)\r\n\t\t{\r\n\t\t\treturn *this += -delta;\r\n\t\t}\r\n\r\n\t\tPointsInRectangleIteratorColMajor operator-(difference_type delta) const\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\treturn copy -= delta;\r\n\t\t}\r\n\r\n\t\tvalue_type operator[](difference_type offset) const\r\n\t\t{\r\n\t\t\treturn **(this + offset);\r\n\t\t}\r\n\t};\r\n\r\n\t// gcc6 needs a defined constructor?\r\n\tconstexpr PointsInRectangleColMajor(RectangleOf<CoordT> region)\r\n\t    : region(region)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator cbegin() const\r\n\t{\r\n\t\treturn region;\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator begin() const\r\n\t{\r\n\t\treturn cbegin();\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator cend() const\r\n\t{\r\n\t\treturn { region, region.size.width * region.size.height };\r\n\t}\r\n\r\n\t[[nodiscard]] const_iterator end() const\r\n\t{\r\n\t\treturn cend();\r\n\t}\r\n\r\n\t[[nodiscard]] auto crbegin() const\r\n\t{\r\n\t\t// explicit type needed for older GCC versions\r\n\t\treturn std::reverse_iterator<const_iterator>(cend());\r\n\t}\r\n\r\n\t[[nodiscard]] auto rbegin() const\r\n\t{\r\n\t\treturn crbegin();\r\n\t}\r\n\r\n\t[[nodiscard]] auto crend() const\r\n\t{\r\n\t\t// explicit type needed for older GCC versions\r\n\t\treturn std::reverse_iterator<const_iterator>(cbegin());\r\n\t}\r\n\r\n\t[[nodiscard]] auto rend() const\r\n\t{\r\n\t\treturn crend();\r\n\t}\r\n\r\nprotected:\r\n\tRectangleOf<CoordT> region;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/random.cpp",
    "content": "#include \"engine/random.hpp\"\r\n\r\n#include <bit>\r\n#include <chrono>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <limits>\r\n#include <random>\r\n\r\nnamespace devilution {\r\n\r\n/** Current game seed */\r\nuint32_t sglGameSeed;\r\n\r\n/** Borland C/C++ psuedo-random number generator needed for vanilla compatibility */\r\nstd::linear_congruential_engine<uint32_t, 0x015A4E35, 1, 0> diabloGenerator;\r\n\r\n/** Xoshiro pseudo-random number generator to provide less predictable seeds */\r\nxoshiro128plusplus seedGenerator;\r\n\r\nuint32_t xoshiro128plusplus::next()\r\n{\r\n\tconst uint32_t result = std::rotl(s[0] + s[3], 7) + s[0];\r\n\r\n\tconst uint32_t t = s[1] << 9;\r\n\r\n\ts[2] ^= s[0];\r\n\ts[3] ^= s[1];\r\n\ts[1] ^= s[2];\r\n\ts[0] ^= s[3];\r\n\r\n\ts[2] ^= t;\r\n\r\n\ts[3] = std::rotl(s[3], 11);\r\n\r\n\treturn result;\r\n}\r\n\r\nuint64_t xoshiro128plusplus::timeSeed()\r\n{\r\n\tauto now = std::chrono::system_clock::now();\r\n\tauto nano = std::chrono::nanoseconds(now.time_since_epoch());\r\n\treturn static_cast<uint64_t>(nano.count());\r\n}\r\n\r\nvoid xoshiro128plusplus::copy(state &dst, const state &src)\r\n{\r\n\tmemcpy(dst, src, sizeof(dst));\r\n}\r\n\r\nxoshiro128plusplus ReserveSeedSequence()\r\n{\r\n\txoshiro128plusplus reserved = seedGenerator;\r\n\tseedGenerator.jump();\r\n\treturn reserved;\r\n}\r\n\r\nuint32_t GenerateSeed()\r\n{\r\n\treturn seedGenerator.next();\r\n}\r\n\r\nvoid SetRndSeed(uint32_t seed)\r\n{\r\n\tdiabloGenerator.seed(seed);\r\n\tsglGameSeed = seed;\r\n}\r\n\r\nuint32_t GetLCGEngineState()\r\n{\r\n\treturn sglGameSeed;\r\n}\r\n\r\nvoid DiscardRandomValues(unsigned count)\r\n{\r\n\twhile (count != 0) {\r\n\t\tGenerateRandomNumber();\r\n\t\tcount--;\r\n\t}\r\n}\r\n\r\nuint32_t GenerateRandomNumber()\r\n{\r\n\tsglGameSeed = diabloGenerator();\r\n\treturn sglGameSeed;\r\n}\r\n\r\nint32_t AdvanceRndSeed()\r\n{\r\n\tconst int32_t seed = static_cast<int32_t>(GenerateRandomNumber());\r\n\t// since abs(INT_MIN) is undefined behavior, handle this value specially\r\n\treturn seed == std::numeric_limits<int32_t>::min() ? std::numeric_limits<int32_t>::min() : std::abs(seed);\r\n}\r\n\r\nint32_t GenerateRnd(int32_t v)\r\n{\r\n\tif (v <= 0)\r\n\t\treturn 0;\r\n\tif (v <= 0x7FFF) // use the high bits to correct for LCG bias\r\n\t\treturn (AdvanceRndSeed() >> 16) % v;\r\n\treturn AdvanceRndSeed() % v;\r\n}\r\n\r\nbool FlipCoin(unsigned frequency)\r\n{\r\n\t// Casting here because GenerateRnd takes a signed argument when it should take and yield unsigned.\r\n\treturn GenerateRnd(static_cast<int32_t>(frequency)) == 0;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/random.hpp",
    "content": "/**\r\n * @file random.hpp\r\n *\r\n * Contains convenience functions for random number generation\r\n *\r\n * This includes specific engine/distribution functions for logic that needs to be compatible with the base game.\r\n */\r\n#pragma once\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <initializer_list>\r\n#include <random>\r\n\r\nnamespace devilution {\r\n\r\nclass DiabloGenerator {\r\nprivate:\r\n\t/** Borland C/C++ psuedo-random number generator needed for vanilla compatibility */\r\n\tstd::linear_congruential_engine<uint32_t, 0x015A4E35, 1, 0> lcg;\r\n\r\npublic:\r\n\t/**\r\n\t * @brief Set the state of the RandomNumberEngine used by the base game to the specific seed\r\n\t * @param seed New engine state\r\n\t */\r\n\tDiabloGenerator(uint32_t seed)\r\n\t{\r\n\t\tlcg.seed(seed);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Advance the global RandomNumberEngine state by the specified number of rounds\r\n\t *\r\n\t * Only used to maintain vanilla compatibility until logic requiring reproducible random number generation is isolated.\r\n\t * @param count How many values to discard\r\n\t */\r\n\tvoid discardRandomValues(unsigned count)\r\n\t{\r\n\t\tlcg.discard(count);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Generates a random non-negative integer (most of the time) using the vanilla RNG\r\n\t *\r\n\t * This advances the engine state then interprets the new engine state as a signed value and calls std::abs to try\r\n\t * discard the high bit of the result. This usually returns a positive number but may very rarely return -2^31.\r\n\t *\r\n\t * This function is only used when the base game wants to store the seed used to generate an item or level, however\r\n\t * as the returned value is transformed about 50% of values do not reflect the actual engine state. It would be more\r\n\t * appropriate to use GetLCGEngineState() in these cases but that may break compatibility with the base game.\r\n\t *\r\n\t * @return A random number in the range [0,2^31) or -2^31\r\n\t */\r\n\tint32_t advanceRndSeed()\r\n\t{\r\n\t\tconst int32_t seed = static_cast<int32_t>(lcg());\r\n\t\t// since abs(INT_MIN) is undefined behavior, handle this value specially\r\n\t\treturn seed == std::numeric_limits<int32_t>::min() ? std::numeric_limits<int32_t>::min() : std::abs(seed);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Generates a random integer less than the given limit using the vanilla RNG\r\n\t *\r\n\t * If v is not a positive number this function returns 0 without calling the RNG.\r\n\t *\r\n\t * Limits between 32768 and 65534 should be avoided as a bug in vanilla means this function always returns a value\r\n\t * less than 32768 for limits in that range.\r\n\t *\r\n\t * This can very rarely return a negative value in the range (-v, -1] due to the bug in AdvanceRndSeed()\r\n\t *\r\n\t * @see AdvanceRndSeed()\r\n\t * @param v The upper limit for the return value\r\n\t * @return A random number in the range [0, v) or rarely a negative value in (-v, -1]\r\n\t */\r\n\tint32_t generateRnd(int32_t v)\r\n\t{\r\n\t\tif (v <= 0)\r\n\t\t\treturn 0;\r\n\t\tif (v <= 0x7FFF) // use the high bits to correct for LCG bias\r\n\t\t\treturn (advanceRndSeed() >> 16) % v;\r\n\t\treturn advanceRndSeed() % v;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Generates a random boolean value using the vanilla RNG\r\n\t *\r\n\t * This function returns true 1 in `frequency` of the time, otherwise false. For example the default frequency of 2\r\n\t * represents a 50/50 chance.\r\n\t *\r\n\t * @param frequency odds of returning a true value\r\n\t * @return A random boolean value\r\n\t */\r\n\tbool flipCoin(unsigned frequency)\r\n\t{\r\n\t\t// Casting here because GenerateRnd takes a signed argument when it should take and yield unsigned.\r\n\t\treturn generateRnd(static_cast<int32_t>(frequency)) == 0;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Picks one of the elements in the list randomly.\r\n\t *\r\n\t * @param values The values to pick from\r\n\t * @return A random value from the 'values' list.\r\n\t */\r\n\ttemplate <typename T>\r\n\tconst T pickRandomlyAmong(const std::initializer_list<T> &values)\r\n\t{\r\n\t\tconst auto index { std::max<int32_t>(generateRnd(static_cast<int32_t>(values.size())), 0) };\r\n\r\n\t\treturn *(values.begin() + index);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Generates a random non-negative integer\r\n\t *\r\n\t * Effectively the same as GenerateRnd but will never return a negative value\r\n\t * @param v upper limit for the return value\r\n\t * @return a value between 0 and v-1 inclusive, i.e. the range [0, v)\r\n\t */\r\n\tinline int32_t randomIntLessThan(int32_t v)\r\n\t{\r\n\t\treturn std::max<int32_t>(generateRnd(v), 0);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Randomly chooses a value somewhere within the given range\r\n\t * @param min lower limit, minimum possible value\r\n\t * @param max upper limit, either the maximum possible value for a closed range (the default behaviour) or one greater than the maximum value for a half-open range\r\n\t * @param halfOpen whether to use the limits as a half-open range or not\r\n\t * @return a randomly selected integer\r\n\t */\r\n\tinline int32_t randomIntBetween(int32_t min, int32_t max, bool halfOpen = false)\r\n\t{\r\n\t\treturn randomIntLessThan(max - min + (halfOpen ? 0 : 1)) + min;\r\n\t}\r\n};\r\n\r\n// Based on fmix32 implementation from MurmurHash3 created by Austin Appleby in 2008\r\n// https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash3.cpp#L68\r\n// and adapted from https://prng.di.unimi.it/splitmix64.c written in 2015 by Sebastiano Vigna\r\n//\r\n// See also:\r\n//  Guy L. Steele, Doug Lea, and Christine H. Flood. 2014.\r\n//  Fast splittable pseudorandom number generators. SIGPLAN Not. 49, 10 (October 2014), 453–472.\r\n//  https://doi.org/10.1145/2714064.2660195\r\nclass SplitMix32 {\r\n\tuint32_t state;\r\n\r\npublic:\r\n\tSplitMix32(uint32_t state)\r\n\t    : state(state)\r\n\t{\r\n\t}\r\n\r\n\tuint32_t next()\r\n\t{\r\n\t\tuint32_t z = (state += 0x9e3779b9);\r\n\t\tz = (z ^ (z >> 16)) * 0x85ebca6b;\r\n\t\tz = (z ^ (z >> 13)) * 0xc2b2ae35;\r\n\t\treturn z ^ (z >> 16);\r\n\t}\r\n\r\n\tvoid generate(uint32_t *begin, const uint32_t *end)\r\n\t{\r\n\t\twhile (begin != end) {\r\n\t\t\t*begin = next();\r\n\t\t\t++begin;\r\n\t\t}\r\n\t}\r\n};\r\n\r\n// Adapted from https://prng.di.unimi.it/splitmix64.c written in 2015 by Sebastiano Vigna\r\n//\r\n// See also:\r\n//  Guy L. Steele, Doug Lea, and Christine H. Flood. 2014.\r\n//  Fast splittable pseudorandom number generators. SIGPLAN Not. 49, 10 (October 2014), 453–472.\r\n//  https://doi.org/10.1145/2714064.2660195\r\nclass SplitMix64 {\r\n\tuint64_t state;\r\n\r\npublic:\r\n\tSplitMix64(uint64_t state)\r\n\t    : state(state)\r\n\t{\r\n\t}\r\n\r\n\tuint64_t next()\r\n\t{\r\n\t\tuint64_t z = (state += 0x9e3779b97f4a7c15);\r\n\t\tz = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;\r\n\t\tz = (z ^ (z >> 27)) * 0x94d049bb133111eb;\r\n\t\treturn z ^ (z >> 31);\r\n\t}\r\n\r\n\tvoid generate(uint64_t *begin, const uint64_t *end)\r\n\t{\r\n\t\twhile (begin != end) {\r\n\t\t\t*begin = next();\r\n\t\t\t++begin;\r\n\t\t}\r\n\t}\r\n};\r\n\r\n/** Adapted from https://prng.di.unimi.it/xoshiro128plusplus.c written in 2019 by David Blackman and Sebastiano Vigna */\r\nclass xoshiro128plusplus {\r\npublic:\r\n\ttypedef uint32_t state[4];\r\n\r\n\txoshiro128plusplus() { seed(); }\r\n\txoshiro128plusplus(const state &s) { copy(this->s, s); }\r\n\txoshiro128plusplus(uint64_t initialSeed) { seed(initialSeed); }\r\n\txoshiro128plusplus(uint32_t initialSeed) { seed(initialSeed); }\r\n\r\n\tuint32_t next();\r\n\r\n\t/* This is the jump function for the generator. It is equivalent\r\n\t   to 2^64 calls to next(); it can be used to generate 2^64\r\n\t   non-overlapping subsequences for parallel computations. */\r\n\tvoid jump()\r\n\t{\r\n\t\tstatic constexpr uint32_t JUMP[] = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b };\r\n\r\n\t\tuint32_t s0 = 0;\r\n\t\tuint32_t s1 = 0;\r\n\t\tuint32_t s2 = 0;\r\n\t\tuint32_t s3 = 0;\r\n\t\tfor (const uint32_t entry : JUMP)\r\n\t\t\tfor (int b = 0; b < 32; b++) {\r\n\t\t\t\tif (entry & UINT32_C(1) << b) {\r\n\t\t\t\t\ts0 ^= s[0];\r\n\t\t\t\t\ts1 ^= s[1];\r\n\t\t\t\t\ts2 ^= s[2];\r\n\t\t\t\t\ts3 ^= s[3];\r\n\t\t\t\t}\r\n\t\t\t\tnext();\r\n\t\t\t}\r\n\r\n\t\ts[0] = s0;\r\n\t\ts[1] = s1;\r\n\t\ts[2] = s2;\r\n\t\ts[3] = s3;\r\n\t}\r\n\r\n\tvoid save(state &s) const\r\n\t{\r\n\t\tcopy(s, this->s);\r\n\t}\r\n\r\nprivate:\r\n\tstate s;\r\n\r\n\tvoid seed(uint64_t value)\r\n\t{\r\n\t\tuint64_t seeds[2];\r\n\t\tSplitMix64 seedSequence { value };\r\n\t\tseedSequence.generate(seeds, seeds + 2);\r\n\r\n\t\ts[0] = static_cast<uint32_t>(seeds[0] >> 32);\r\n\t\ts[1] = static_cast<uint32_t>(seeds[0]);\r\n\t\ts[2] = static_cast<uint32_t>(seeds[1] >> 32);\r\n\t\ts[3] = static_cast<uint32_t>(seeds[1]);\r\n\t}\r\n\r\n\tvoid seed(uint32_t value)\r\n\t{\r\n\t\tSplitMix32 seedSequence { value };\r\n\t\tseedSequence.generate(s, s + 4);\r\n\t}\r\n\r\n\tvoid seed()\r\n\t{\r\n\t\tseed(timeSeed());\r\n\r\n#if !(defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0))\r\n\t\tstatic std::random_device rd;\r\n\t\tstd::uniform_int_distribution<uint32_t> dist;\r\n\t\tfor (uint32_t &cell : s)\r\n\t\t\tcell ^= dist(rd);\r\n#endif\r\n\t}\r\n\r\n\tstatic uint64_t timeSeed();\r\n\tstatic void copy(state &dst, const state &src);\r\n};\r\n\r\n/**\r\n * @brief Returns a copy of the global seed generator and fast-forwards the global seed generator to avoid collisions\r\n */\r\nxoshiro128plusplus ReserveSeedSequence();\r\n\r\n/**\r\n * @brief Advances the global seed generator state and returns the new value\r\n */\r\nuint32_t GenerateSeed();\r\n\r\n/**\r\n * @brief Set the state of the RandomNumberEngine used by the base game to the specific seed\r\n * @param seed New engine state\r\n */\r\nvoid SetRndSeed(uint32_t seed);\r\n\r\n/**\r\n * @brief Returns the current state of the RandomNumberEngine used by the base game\r\n *\r\n * This is only exposed to allow for debugging vanilla code and testing. Using this engine for new code is discouraged\r\n * due to the poor randomness and bugs in the implementation that need to be retained for compatibility.\r\n *\r\n * @return The current engine state\r\n */\r\nuint32_t GetLCGEngineState();\r\n\r\n/**\r\n * @brief Advance the global RandomNumberEngine state by the specified number of rounds\r\n *\r\n * Only used to maintain vanilla compatibility until logic requiring reproducible random number generation is isolated.\r\n * @param count How many values to discard\r\n */\r\nvoid DiscardRandomValues(unsigned count);\r\n\r\n/**\r\n * @brief Advances the global RandomNumberEngine state and returns the new value\r\n */\r\nuint32_t GenerateRandomNumber();\r\n\r\n/**\r\n * @brief Generates a random non-negative integer (most of the time) using the vanilla RNG\r\n *\r\n * This advances the engine state then interprets the new engine state as a signed value and calls std::abs to try\r\n * discard the high bit of the result. This usually returns a positive number but may very rarely return -2^31.\r\n *\r\n * This function is only used when the base game wants to store the seed used to generate an item or level, however\r\n * as the returned value is transformed about 50% of values do not reflect the actual engine state. It would be more\r\n * appropriate to use GetLCGEngineState() in these cases but that may break compatibility with the base game.\r\n *\r\n * @return A random number in the range [0,2^31) or -2^31\r\n */\r\n[[nodiscard]] int32_t AdvanceRndSeed();\r\n\r\n/**\r\n * @brief Generates a random integer less than the given limit using the vanilla RNG\r\n *\r\n * If v is not a positive number this function returns 0 without calling the RNG.\r\n *\r\n * Limits between 32768 and 65534 should be avoided as a bug in vanilla means this function always returns a value\r\n * less than 32768 for limits in that range.\r\n *\r\n * This can very rarely return a negative value in the range (-v, -1] due to the bug in AdvanceRndSeed()\r\n *\r\n * @see AdvanceRndSeed()\r\n * @param v The upper limit for the return value\r\n * @return A random number in the range [0, v) or rarely a negative value in (-v, -1]\r\n */\r\nint32_t GenerateRnd(int32_t v);\r\n\r\n/**\r\n * @brief Generates a random boolean value using the vanilla RNG\r\n *\r\n * This function returns true 1 in `frequency` of the time, otherwise false. For example the default frequency of 2\r\n * represents a 50/50 chance.\r\n *\r\n * @param frequency odds of returning a true value\r\n * @return A random boolean value\r\n */\r\nbool FlipCoin(unsigned frequency = 2);\r\n\r\n/**\r\n * @brief Picks one of the elements in the list randomly.\r\n *\r\n * @param values The values to pick from\r\n * @return A random value from the 'values' list.\r\n */\r\ntemplate <typename T>\r\nconst T PickRandomlyAmong(const std::initializer_list<T> &values)\r\n{\r\n\tconst auto index { std::max<int32_t>(GenerateRnd(static_cast<int32_t>(values.size())), 0) };\r\n\r\n\treturn *(values.begin() + index);\r\n}\r\n\r\n/**\r\n * @brief Generates a random non-negative integer\r\n *\r\n * Effectively the same as GenerateRnd but will never return a negative value\r\n * @param v upper limit for the return value\r\n * @return a value between 0 and v-1 inclusive, i.e. the range [0, v)\r\n */\r\ninline int32_t RandomIntLessThan(int32_t v)\r\n{\r\n\treturn std::max<int32_t>(GenerateRnd(v), 0);\r\n}\r\n\r\n/**\r\n * @brief Randomly chooses a value somewhere within the given range\r\n * @param min lower limit, minimum possible value\r\n * @param max upper limit, either the maximum possible value for a closed range (the default behaviour) or one greater than the maximum value for a half-open range\r\n * @param halfOpen whether to use the limits as a half-open range or not\r\n * @return a randomly selected integer\r\n */\r\ninline int32_t RandomIntBetween(int32_t min, int32_t max, bool halfOpen = false)\r\n{\r\n\treturn RandomIntLessThan(max - min + (halfOpen ? 0 : 1)) + min;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/rectangle.hpp",
    "content": "#pragma once\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename CoordT, typename SizeT = CoordT>\r\nstruct RectangleOf {\r\n\tPointOf<CoordT> position;\r\n\tSizeOf<SizeT> size;\r\n\r\n\tRectangleOf() = default;\r\n\r\n\tDVL_ALWAYS_INLINE constexpr RectangleOf(PointOf<CoordT> position, SizeOf<SizeT> size)\r\n\t    : position(position)\r\n\t    , size(size)\r\n\t{\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Constructs a rectangle centered on the given point and including all tiles within the given radius.\r\n\t *\r\n\t * The resulting rectangle will be square with an odd size equal to 2*radius + 1.\r\n\t *\r\n\t * @param center center point of the target rectangle\r\n\t * @param radius a non-negative value indicating how many tiles to include around the center\r\n\t */\r\n\tDVL_ALWAYS_INLINE explicit constexpr RectangleOf(PointOf<CoordT> center, SizeT radius)\r\n\t    : position(center - DisplacementOf<SizeT> { radius })\r\n\t    , size(static_cast<SizeT>(2 * radius + 1))\r\n\t{\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Whether this rectangle contains the given point.\r\n\t * Works correctly even if the point uses a different underlying numeric type\r\n\t */\r\n\ttemplate <typename PointCoordT>\r\n\tDVL_ALWAYS_INLINE constexpr bool contains(PointOf<PointCoordT> point) const\r\n\t{\r\n\t\treturn contains(point.x, point.y);\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\tconstexpr bool contains(T x, T y) const\r\n\t{\r\n\t\treturn x >= this->position.x\r\n\t\t    && x < (this->position.x + this->size.width)\r\n\t\t    && y >= this->position.y\r\n\t\t    && y < (this->position.y + this->size.height);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Computes the center of this rectangle in integer coordinates. Values are truncated towards zero.\r\n\t */\r\n\tconstexpr PointOf<CoordT> Center() const\r\n\t{\r\n\t\treturn position + DisplacementOf<SizeT>(size / 2);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a rectangle with all sides shrunk according to the given displacement\r\n\t *\r\n\t * Effectively moves the left/right edges in by deltaX, and the top/bottom edges in by deltaY\r\n\t */\r\n\tconstexpr RectangleOf<CoordT, SizeT> inset(DisplacementOf<SizeT> factor) const\r\n\t{\r\n\t\treturn {\r\n\t\t\tposition + factor,\r\n\t\t\tSizeOf<SizeT>(size.width - factor.deltaX * 2, size.height - factor.deltaY * 2)\r\n\t\t};\r\n\t}\r\n};\r\n\r\nusing Rectangle = RectangleOf<int, int>;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/automap_render.cpp",
    "content": "/**\r\n * @file automap_render.cpp\r\n *\r\n * Line drawing routines for the automap.\r\n */\r\n#include \"engine/render/automap_render.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"automap.h\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nenum class DirectionX : int8_t {\r\n\tEAST = 1,\r\n\tWEST = -1,\r\n};\r\n\r\nenum class DirectionY : int8_t {\r\n\tSOUTH = 1,\r\n\tNORTH = -1,\r\n};\r\n\r\ntemplate <DirectionX DirX, DirectionY DirY>\r\nvoid DrawMapLine(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\twhile (height-- > 0) {\r\n\t\tSetMapPixel(out, { from.x, from.y + 1 }, 0);\r\n\t\tSetMapPixel(out, from, colorIndex);\r\n\t\tfrom.x += static_cast<int>(DirX);\r\n\t\tSetMapPixel(out, { from.x, from.y + 1 }, 0);\r\n\t\tSetMapPixel(out, from, colorIndex);\r\n\t\tfrom.x += static_cast<int>(DirX);\r\n\t\tfrom.y += static_cast<int>(DirY);\r\n\t}\r\n\tSetMapPixel(out, { from.x, from.y + 1 }, 0);\r\n\tSetMapPixel(out, from, colorIndex);\r\n}\r\n\r\ntemplate <DirectionX DirX, DirectionY DirY>\r\nvoid DrawMapLineSteep(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\twhile (width-- > 0) {\r\n\t\tSetMapPixel(out, { from.x, from.y + 1 }, 0);\r\n\t\tSetMapPixel(out, from, colorIndex);\r\n\t\tfrom.y += static_cast<int>(DirY);\r\n\t\tSetMapPixel(out, { from.x, from.y + 1 }, 0);\r\n\t\tSetMapPixel(out, from, colorIndex);\r\n\t\tfrom.y += static_cast<int>(DirY);\r\n\t\tfrom.x += static_cast<int>(DirX);\r\n\t}\r\n\tSetMapPixel(out, { from.x, from.y + 1 }, 0);\r\n\tSetMapPixel(out, from, colorIndex);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DrawMapLineNS(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\tif (from.x < 0 || from.x >= out.w() || from.y >= out.h() || height <= 0 || from.y + height <= 0)\r\n\t\treturn;\r\n\r\n\tif (from.y < 0) {\r\n\t\theight += from.y;\r\n\t\tfrom.y = 0;\r\n\t}\r\n\r\n\tif (from.y + height > out.h())\r\n\t\theight = out.h() - from.y;\r\n\r\n\tfor (int i = 0; i < height; ++i) {\r\n\t\tSetMapPixel(out, { from.x, from.y + i }, colorIndex);\r\n\t}\r\n}\r\n\r\nvoid DrawMapLineWE(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\tif (from.y < 0 || from.y >= out.h() || from.x >= out.w() || width <= 0 || from.x + width <= 0)\r\n\t\treturn;\r\n\r\n\tif (from.x < 0) {\r\n\t\twidth += from.x;\r\n\t\tfrom.x = 0;\r\n\t}\r\n\r\n\tif (from.x + width > out.w())\r\n\t\twidth = out.w() - from.x;\r\n\r\n\tfor (int i = 0; i < width; ++i) {\r\n\t\tSetMapPixel(out, { from.x + i, from.y }, colorIndex);\r\n\t}\r\n}\r\n\r\nvoid DrawMapLineNE(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLine<DirectionX::EAST, DirectionY::NORTH>(out, from, height, colorIndex);\r\n}\r\n\r\nvoid DrawMapLineSE(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLine<DirectionX::EAST, DirectionY::SOUTH>(out, from, height, colorIndex);\r\n}\r\n\r\nvoid DrawMapLineNW(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLine<DirectionX::WEST, DirectionY::NORTH>(out, from, height, colorIndex);\r\n}\r\n\r\nvoid DrawMapLineSW(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLine<DirectionX::WEST, DirectionY::SOUTH>(out, from, height, colorIndex);\r\n}\r\n\r\nvoid DrawMapLineSteepNE(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLineSteep<DirectionX::EAST, DirectionY::NORTH>(out, from, width, colorIndex);\r\n}\r\n\r\nvoid DrawMapLineSteepSE(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLineSteep<DirectionX::EAST, DirectionY::SOUTH>(out, from, width, colorIndex);\r\n}\r\n\r\nvoid DrawMapLineSteepNW(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLineSteep<DirectionX::WEST, DirectionY::NORTH>(out, from, width, colorIndex);\r\n}\r\n\r\nvoid DrawMapLineSteepSW(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\tDrawMapLineSteep<DirectionX::WEST, DirectionY::SOUTH>(out, from, width, colorIndex);\r\n}\r\n\r\n/**\r\n * @brief Draws a line from first point to second point, unrestricted to the standard automap angles. Doesn't include shadow.\r\n */\r\nvoid DrawMapFreeLine(const Surface &out, Point from, Point to, uint8_t colorIndex)\r\n{\r\n\tconst int dx = std::abs(to.x - from.x);\r\n\tconst int dy = std::abs(to.y - from.y);\r\n\tconst int sx = from.x < to.x ? 1 : -1;\r\n\tconst int sy = from.y < to.y ? 1 : -1;\r\n\tint err = dx - dy;\r\n\r\n\twhile (true) {\r\n\t\tSetMapPixel(out, from, colorIndex);\r\n\r\n\t\tif (from.x == to.x && from.y == to.y) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tconst int e2 = 2 * err;\r\n\t\tif (e2 > -dy) {\r\n\t\t\terr -= dy;\r\n\t\t\tfrom.x += sx;\r\n\t\t}\r\n\t\tif (e2 < dx) {\r\n\t\t\terr += dx;\r\n\t\t\tfrom.y += sy;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SetMapPixel(const Surface &out, Point position, uint8_t color)\r\n{\r\n\tif (GetAutomapType() == AutomapType::Minimap && !MinimapRect.contains(position))\r\n\t\treturn;\r\n\r\n\tif (GetAutomapType() == AutomapType::Transparent) {\r\n\t\tSetHalfTransparentPixel(out, position, color);\r\n\t} else {\r\n\t\tout.SetPixel(position, color);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/automap_render.hpp",
    "content": "/**\r\n * @file automap_render.hpp\r\n * Defines 2 sets of rendering primitives for drawing automap lines.\r\n *\r\n * 1. DrawMapLine* - used for rendering most map lines - 2 pixels horizontally for each pixel vertically.\r\n * 2. DrawMapLineSteep* - currently only used for rendering the player arrow - 2 pixels vertically for each pixel horizontally.\r\n *\r\n * These functions draw a single extra pixel at the end of the line -- they always draw an odd number of pixels.\r\n * These functions clip to the output buffer -- they are safe to call with out-of-bounds coordinates.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid DrawMapLineNS(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\nvoid DrawMapLineWE(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards north east at an `atan(1/2)` angle.\r\n *\r\n * Draws 2 horizontal pixels for each vertical step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x + 2 * height + 1, from.y - height }`.\r\n */\r\nvoid DrawMapLineNE(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards south east at an `atan(1/2)` angle.\r\n *\r\n * Draws 2 horizontal pixels for each vertical step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x + 2 * height + 1, from.y + height }`.\r\n */\r\nvoid DrawMapLineSE(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards north west at an `atan(1/2)` angle.\r\n *\r\n * Draws 2 horizontal pixels for each vertical step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x - 2 * height + 1, from.y - height }`.\r\n */\r\nvoid DrawMapLineNW(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards south west at an `atan(1/2)` angle.\r\n *\r\n * Draws 2 horizontal pixels for each vertical step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x - 2 * height + 1, from.y + height }`.\r\n */\r\nvoid DrawMapLineSW(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards north east at an `atan(1/2)` angle.\r\n *\r\n * Draws 2 vertical pixels for each horizontal step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x + width + 1, from.y - 2 * width }`.\r\n */\r\nvoid DrawMapLineSteepNE(const Surface &out, Point from, int width, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards south east at an `atan(2)` angle.\r\n *\r\n * Draws 2 vertical pixels for each horizontal step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x + width + 1, from.y + 2 * width }`.\r\n */\r\nvoid DrawMapLineSteepSE(const Surface &out, Point from, int width, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards north west at an `atan(1/2)` angle.\r\n *\r\n * Draws 2 vertical pixels for each horizontal step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x - (width + 1), from.y - 2 * width }`.\r\n */\r\nvoid DrawMapLineSteepNW(const Surface &out, Point from, int width, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a line in the target buffer from the given point towards south west at an `atan(1/2)` angle.\r\n *\r\n * Draws 2 vertical pixels for each horizontal step, then an additional one where it draws 1 pixel.\r\n *\r\n * The end point is at `{ from.x - (width + 1), from.y + 2 * width }`.\r\n */\r\nvoid DrawMapLineSteepSW(const Surface &out, Point from, int width, std::uint8_t colorIndex);\r\nvoid DrawMapFreeLine(const Surface &out, Point from, Point to, uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw an automap pixel.\r\n *\r\n * Draw either an opaque pixel or a transparent pixel, depending on the automap mode.\r\n */\r\nvoid SetMapPixel(const Surface &out, Point position, uint8_t color);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/blit_impl.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <execution>\r\n#include <version>\r\n\r\n#include \"engine/render/light_render.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/palette_blending.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#if __cpp_lib_execution >= 201902L\r\n#define DEVILUTIONX_BLIT_EXECUTION_POLICY std::execution::unseq,\r\n#else\r\n#define DEVILUTIONX_BLIT_EXECUTION_POLICY\r\n#endif\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillDirect(uint8_t *dst, unsigned length, uint8_t color)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tstd::memset(dst, color, length);\r\n}\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsDirect(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tstd::memcpy(dst, src, length);\r\n}\r\n\r\nstruct BlitDirect {\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const\r\n\t{\r\n\t\tBlitPixelsDirect(dst, src, length);\r\n\t}\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t color, uint8_t *DVL_RESTRICT dst) const\r\n\t{\r\n\t\tBlitFillDirect(dst, length, color);\r\n\t}\r\n};\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillWithMap(uint8_t *dst, unsigned length, uint8_t color, const uint8_t *DVL_RESTRICT colorMap)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tstd::memset(dst, colorMap[color], length);\r\n}\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsWithMap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const uint8_t *DVL_RESTRICT colorMap)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, dst, [colorMap](uint8_t srcColor) { return colorMap[srcColor]; });\r\n}\r\n\r\nstruct BlitWithMap {\r\n\tconst uint8_t *DVL_RESTRICT colorMap;\r\n\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const\r\n\t{\r\n\t\tBlitPixelsWithMap(dst, src, length, colorMap);\r\n\t}\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t color, uint8_t *DVL_RESTRICT dst) const\r\n\t{\r\n\t\tBlitFillWithMap(dst, length, color, colorMap);\r\n\t}\r\n};\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillWithLightmap(uint8_t *dst, unsigned length, uint8_t color, const Lightmap &lightmap)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tconst uint8_t *light = lightmap.getLightingAt(dst);\r\n\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY light, light + length, dst, [color, &lightmap](uint8_t lightLevel) {\r\n\t\treturn lightmap.adjustColor(color, lightLevel);\r\n\t});\r\n}\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsWithLightmap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const Lightmap &lightmap)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tconst uint8_t *light = lightmap.getLightingAt(dst);\r\n\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, light, dst, [&lightmap](uint8_t srcColor, uint8_t lightLevel) {\r\n\t\treturn lightmap.adjustColor(srcColor, lightLevel);\r\n\t});\r\n}\r\n\r\nstruct BlitWithLightmap {\r\n\tconst Lightmap &lightmap;\r\n\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const\r\n\t{\r\n\t\tBlitPixelsWithLightmap(dst, src, length, lightmap);\r\n\t}\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t color, uint8_t *DVL_RESTRICT dst) const\r\n\t{\r\n\t\tBlitFillWithLightmap(dst, length, color, lightmap);\r\n\t}\r\n};\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillBlended(uint8_t *dst, unsigned length, uint8_t color)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tstd::for_each(DEVILUTIONX_BLIT_EXECUTION_POLICY dst, dst + length, [tbl = paletteTransparencyLookup[color]](uint8_t &dstColor) {\r\n\t\tdstColor = tbl[dstColor];\r\n\t});\r\n}\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsBlended(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, dst, dst, [pal = paletteTransparencyLookup](uint8_t srcColor, uint8_t dstColor) {\r\n\t\treturn pal[srcColor][dstColor];\r\n\t});\r\n}\r\n\r\nstruct BlitBlended {\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const\r\n\t{\r\n\t\tBlitPixelsBlended(dst, src, length);\r\n\t}\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t color, uint8_t *DVL_RESTRICT dst) const\r\n\t{\r\n\t\tBlitFillBlended(dst, length, color);\r\n\t}\r\n};\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsBlendedWithMap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const uint8_t *DVL_RESTRICT colorMap)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, dst, dst, [colorMap, pal = paletteTransparencyLookup](uint8_t srcColor, uint8_t dstColor) {\r\n\t\treturn pal[dstColor][colorMap[srcColor]];\r\n\t});\r\n}\r\n\r\nstruct BlitBlendedWithMap {\r\n\tconst uint8_t *DVL_RESTRICT colorMap;\r\n\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const\r\n\t{\r\n\t\tBlitPixelsBlendedWithMap(dst, src, length, colorMap);\r\n\t}\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t color, uint8_t *DVL_RESTRICT dst) const\r\n\t{\r\n\t\tBlitFillBlended(dst, length, colorMap[color]);\r\n\t}\r\n};\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillBlendedWithLightmap(uint8_t *dst, unsigned length, uint8_t color, const Lightmap &lightmap)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tconst uint8_t *light = lightmap.getLightingAt(dst);\r\n\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY light, light + length, dst, dst, [color, &lightmap, pal = paletteTransparencyLookup](uint8_t lightLevel, uint8_t dstColor) {\r\n\t\tuint8_t srcColor = lightmap.adjustColor(color, lightLevel);\r\n\t\treturn pal[srcColor][dstColor];\r\n\t});\r\n}\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsBlendedWithLightmap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const Lightmap &lightmap)\r\n{\r\n\tDVL_ASSUME(length != 0);\r\n\tconst uint8_t *light = lightmap.getLightingAt(dst);\r\n\r\n\tif (length < 1024) {\r\n\t\tuint8_t litSrc[1024];\r\n\t\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, light, litSrc, [&lightmap](uint8_t srcColor, uint8_t lightLevel) {\r\n\t\t\treturn lightmap.adjustColor(srcColor, lightLevel);\r\n\t\t});\r\n\t\tstd::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY litSrc, litSrc + length, dst, dst, [pal = paletteTransparencyLookup](uint8_t srcColor, uint8_t dstColor) {\r\n\t\t\treturn pal[dstColor][srcColor];\r\n\t\t});\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (size_t i = 0; i < length; i++) {\r\n\t\tuint8_t srcColor = src[i];\r\n\t\tuint8_t dstColor = dst[i];\r\n\t\tuint8_t lightLevel = light[i];\r\n\t\tuint8_t litColor = lightmap.adjustColor(srcColor, lightLevel);\r\n\t\tdst[i] = paletteTransparencyLookup[dstColor][litColor];\r\n\t}\r\n}\r\n\r\nstruct BlitBlendedWithLightmap {\r\n\tconst Lightmap &lightmap;\r\n\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const\r\n\t{\r\n\t\tBlitPixelsBlendedWithLightmap(dst, src, length, lightmap);\r\n\t}\r\n\tDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(unsigned length, uint8_t color, uint8_t *DVL_RESTRICT dst) const\r\n\t{\r\n\t\tBlitFillBlendedWithLightmap(dst, length, color, lightmap);\r\n\t}\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/clx_render.cpp",
    "content": "/**\r\n * @file clx_render.cpp\r\n *\r\n * CL2 rendering.\r\n */\r\n#include \"clx_render.hpp\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/blit_impl.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/clx_decode.hpp\"\r\n#include \"utils/static_vector.hpp\"\r\n\r\n#ifdef DEBUG_CLX\r\n#include <fmt/format.h>\r\n\r\n#include \"utils/str_cat.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\n/**\r\n * CL2 is similar to CEL, with the following differences:\r\n *\r\n * 1. Transparent runs can cross line boundaries.\r\n * 2. Control bytes are different, and the [0x80, 0xBE] control byte range\r\n *    indicates a fill-N command.\r\n */\r\n\r\nstruct BlitCommandInfo {\r\n\tconst uint8_t *srcEnd;\r\n\tunsigned length;\r\n};\r\n\r\nBlitCommandInfo ClxBlitInfo(const uint8_t *src)\r\n{\r\n\tconst uint8_t control = *src;\r\n\tif (!IsClxOpaque(control))\r\n\t\treturn { src + 1, control };\r\n\tif (IsClxOpaqueFill(control)) {\r\n\t\tconst uint8_t width = GetClxOpaqueFillWidth(control);\r\n\t\treturn { src + 2, width };\r\n\t}\r\n\tconst uint8_t width = GetClxOpaquePixelsWidth(control);\r\n\treturn { src + 1 + width, width };\r\n}\r\n\r\nstruct ClipX {\r\n\tint_fast16_t left;\r\n\tint_fast16_t right;\r\n\tint_fast16_t width;\r\n};\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT ClipX CalculateClipX(int_fast16_t x, std::size_t w, const Surface &out)\r\n{\r\n\tClipX clip;\r\n\tclip.left = static_cast<int_fast16_t>(x < 0 ? -x : 0);\r\n\tclip.right = static_cast<int_fast16_t>(static_cast<int_fast16_t>(x + w) > out.w() ? x + w - out.w() : 0);\r\n\tclip.width = static_cast<int_fast16_t>(w - clip.left - clip.right);\r\n\treturn clip;\r\n}\r\n\r\n// Source data for rendering backwards: first line of input -> last line of output.\r\nstruct RenderSrc {\r\n\tconst uint8_t *begin;\r\n\tconst uint8_t *end;\r\n\tuint_fast16_t width;\r\n};\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT const uint8_t *SkipRestOfLineWithOverrun(\r\n    const uint8_t *src, int_fast16_t srcWidth, SkipSize &skipSize)\r\n{\r\n\tint_fast16_t remainingWidth = srcWidth - skipSize.xOffset;\r\n\twhile (remainingWidth > 0) {\r\n\t\tconst auto [srcEnd, length] = ClxBlitInfo(src);\r\n\t\tsrc = srcEnd;\r\n\t\tremainingWidth -= length;\r\n\t}\r\n\tskipSize = GetSkipSize(remainingWidth, srcWidth);\r\n\treturn src;\r\n}\r\n\r\n// Returns the horizontal overrun.\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT int_fast16_t SkipLinesForRenderBackwardsWithOverrun(\r\n    Point &position, RenderSrc &src, int_fast16_t dstHeight)\r\n{\r\n\tSkipSize skipSize { 0, 0 };\r\n\twhile (position.y >= dstHeight && src.begin != src.end) {\r\n\t\tsrc.begin = SkipRestOfLineWithOverrun(\r\n\t\t    src.begin, static_cast<int_fast16_t>(src.width), skipSize);\r\n\t\tposition.y -= static_cast<int>(skipSize.wholeLines);\r\n\t}\r\n\treturn skipSize.xOffset;\r\n}\r\n\r\ntemplate <typename BlitFn>\r\nvoid DoRenderBackwardsClipY(\r\n    const Surface &out, Point position, RenderSrc src, BlitFn &&blitFn)\r\n{\r\n\t// Skip the bottom clipped lines.\r\n\tint_fast16_t xOffset = SkipLinesForRenderBackwardsWithOverrun(position, src, out.h());\r\n\tif (src.begin >= src.end)\r\n\t\treturn;\r\n\r\n\tauto *dst = &out[position];\r\n\tconst auto *dstBegin = out.begin();\r\n\tconst int dstPitch = out.pitch();\r\n\twhile (src.begin != src.end && dst >= dstBegin) {\r\n\t\tauto remainingWidth = static_cast<int_fast16_t>(src.width) - xOffset;\r\n\t\tdst += xOffset;\r\n\t\twhile (remainingWidth > 0) {\r\n\t\t\tuint8_t v = *src.begin++;\r\n\t\t\tif (IsClxOpaque(v)) {\r\n\t\t\t\tif (IsClxOpaqueFill(v)) {\r\n\t\t\t\t\tv = GetClxOpaqueFillWidth(v);\r\n\t\t\t\t\tconst uint8_t color = *src.begin++;\r\n\t\t\t\t\tblitFn(v, color, dst);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tv = GetClxOpaquePixelsWidth(v);\r\n\t\t\t\t\tblitFn(v, dst, src.begin);\r\n\t\t\t\t\tsrc.begin += v;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tdst += v;\r\n\t\t\tremainingWidth -= v;\r\n\t\t}\r\n\r\n\t\tconst SkipSize skipSize = GetSkipSize(remainingWidth, static_cast<int_fast16_t>(src.width));\r\n\t\txOffset = skipSize.xOffset;\r\n\t\tdst -= skipSize.wholeLines * dstPitch + src.width - remainingWidth;\r\n\t}\r\n}\r\n\r\ntemplate <typename BlitFn>\r\nvoid DoRenderBackwardsClipXY(\r\n    const Surface &out, Point position, RenderSrc src, ClipX clipX, BlitFn &&blitFn)\r\n{\r\n\t// Skip the bottom clipped lines.\r\n\tint_fast16_t xOffset = SkipLinesForRenderBackwardsWithOverrun(position, src, out.h());\r\n\tif (src.begin >= src.end)\r\n\t\treturn;\r\n\r\n\tposition.x += static_cast<int>(clipX.left);\r\n\tauto *dst = &out[position];\r\n\tconst auto *dstBegin = out.begin();\r\n\tconst int dstPitch = out.pitch();\r\n\r\n\twhile (src.begin != src.end && dst >= dstBegin) {\r\n\t\t// Skip initial src if clipping on the left.\r\n\t\t// Handles overshoot, i.e. when the RLE segment goes into the unclipped area.\r\n\t\tint_fast16_t remainingWidth = clipX.width;\r\n\t\tint_fast16_t remainingLeftClip = clipX.left - xOffset;\r\n\t\tif (remainingLeftClip < 0) {\r\n\t\t\tdst += std::min<unsigned>(remainingWidth, -remainingLeftClip);\r\n\t\t\tremainingWidth += remainingLeftClip;\r\n\t\t}\r\n\t\twhile (remainingLeftClip > 0) {\r\n\t\t\tauto [srcEnd, length] = ClxBlitInfo(src.begin);\r\n\t\t\tif (static_cast<int_fast16_t>(length) > remainingLeftClip) {\r\n\t\t\t\tconst uint8_t control = *src.begin;\r\n\t\t\t\tconst auto overshoot = static_cast<int>(length - remainingLeftClip);\r\n\t\t\t\tlength = std::min<unsigned>(remainingWidth, overshoot);\r\n\t\t\t\tif (IsClxOpaque(control)) {\r\n\t\t\t\t\tif (IsClxOpaqueFill(control)) {\r\n\t\t\t\t\t\tblitFn(length, src.begin[1], dst);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tblitFn(length, dst, src.begin + 1 + remainingLeftClip);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tdst += length;\r\n\t\t\t\tremainingWidth -= overshoot;\r\n\t\t\t\tsrc.begin = srcEnd;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tsrc.begin = srcEnd;\r\n\t\t\tremainingLeftClip -= length;\r\n\t\t}\r\n\t\twhile (remainingWidth > 0) {\r\n\t\t\tauto [srcEnd, length] = ClxBlitInfo(src.begin);\r\n\t\t\tconst uint8_t control = *src.begin;\r\n\t\t\tconst unsigned unclippedLength = length;\r\n\t\t\tlength = std::min<unsigned>(remainingWidth, length);\r\n\t\t\tif (IsClxOpaque(control)) {\r\n\t\t\t\tif (IsClxOpaqueFill(control)) {\r\n\t\t\t\t\tblitFn(length, src.begin[1], dst);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tblitFn(length, dst, src.begin + 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tsrc.begin = srcEnd;\r\n\t\t\tdst += length;\r\n\t\t\tremainingWidth -= unclippedLength; // result can be negative\r\n\t\t}\r\n\r\n\t\t// `remainingWidth` can be negative, in which case it is the amount of pixels\r\n\t\t// that the source has overran the line.\r\n\t\tremainingWidth += clipX.right;\r\n\t\tSkipSize skipSize;\r\n\t\tif (remainingWidth > 0) {\r\n\t\t\tskipSize.xOffset = static_cast<int_fast16_t>(src.width) - remainingWidth;\r\n\t\t\tsrc.begin = SkipRestOfLineWithOverrun(\r\n\t\t\t    src.begin, static_cast<int_fast16_t>(src.width), skipSize);\r\n\t\t} else {\r\n\t\t\tskipSize = GetSkipSize(remainingWidth, static_cast<int_fast16_t>(src.width));\r\n\t\t}\r\n\t\txOffset = skipSize.xOffset;\r\n\t\tdst -= dstPitch * skipSize.wholeLines + clipX.width;\r\n\t}\r\n}\r\n\r\ntemplate <typename BlitFn>\r\nvoid DoRenderBackwards(\r\n    const Surface &out, Point position, const uint8_t *src, size_t srcSize,\r\n    unsigned srcWidth, unsigned srcHeight, BlitFn &&blitFn)\r\n{\r\n\tif (position.y < 0 || position.y + 1 >= static_cast<int>(out.h() + srcHeight))\r\n\t\treturn;\r\n\tconst ClipX clipX = CalculateClipX(position.x, srcWidth, out);\r\n\tif (clipX.width <= 0)\r\n\t\treturn;\r\n\tconst RenderSrc srcForBackwards { src, src + srcSize, static_cast<uint_fast16_t>(srcWidth) };\r\n\tif (static_cast<std::size_t>(clipX.width) == srcWidth) {\r\n\t\tDoRenderBackwardsClipY(\r\n\t\t    out, position, srcForBackwards, std::forward<BlitFn>(blitFn));\r\n\t} else {\r\n\t\tDoRenderBackwardsClipXY(\r\n\t\t    out, position, srcForBackwards, clipX, std::forward<BlitFn>(blitFn));\r\n\t}\r\n}\r\n\r\nconstexpr size_t MaxOutlinePixels = 4096;\r\nconstexpr size_t MaxOutlineSpriteWidth = 253;\r\nusing OutlinePixels = StaticVector<PointOf<uint8_t>, MaxOutlinePixels>;\r\nusing OutlineRowSolidRuns = StaticVector<std::pair<uint8_t, uint8_t>, MaxOutlineSpriteWidth / 2 + 1>;\r\n\r\nstruct OutlinePixelsCacheEntry {\r\n\tOutlinePixels outlinePixels;\r\n\tconst void *spriteData = nullptr;\r\n\tbool skipColorIndexZero;\r\n};\r\nOutlinePixelsCacheEntry OutlinePixelsCache;\r\n\r\nvoid PopulateOutlinePixelsForRow(\r\n    const OutlineRowSolidRuns &runs,\r\n    const bool *DVL_RESTRICT below,\r\n    bool *DVL_RESTRICT cur,\r\n    bool *DVL_RESTRICT above,\r\n    uint8_t y,\r\n    OutlinePixels &result)\r\n{\r\n\tDVL_ASSUME(!runs.empty());\r\n\tfor (const auto &[begin, end] : runs) {\r\n\t\tif (!cur[static_cast<uint8_t>(begin - 1)]) {\r\n\t\t\tresult.emplace_back(static_cast<uint8_t>(begin - 1), y);\r\n\t\t\tcur[static_cast<uint8_t>(begin - 1)] = true;\r\n\t\t}\r\n\t\tif (!cur[end]) {\r\n\t\t\tresult.emplace_back(end, y);\r\n\t\t\tcur[end] = true;\r\n\t\t}\r\n\t\tfor (uint8_t x = begin; x < end; ++x) {\r\n\t\t\tif (!below[x]) {\r\n\t\t\t\tresult.emplace_back(x, static_cast<uint8_t>(y + 1));\r\n\t\t\t}\r\n\t\t\tif (!above[x]) {\r\n\t\t\t\tresult.emplace_back(x, static_cast<uint8_t>(y - 1));\r\n\t\t\t\tabove[x] = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AppendOutlineRowSolidRuns(uint8_t x, uint8_t w, OutlineRowSolidRuns &solidRuns)\r\n{\r\n\tif (solidRuns.empty() || solidRuns.back().second != x) {\r\n\t\tsolidRuns.emplace_back(x, x + w);\r\n\t} else {\r\n\t\tsolidRuns.back().second = static_cast<uint8_t>(x + w);\r\n\t}\r\n}\r\n\r\ntemplate <bool SkipColorIndexZero>\r\nvoid GetOutline(ClxSprite sprite, OutlinePixels &result) // NOLINT(readability-function-cognitive-complexity)\r\n{\r\n\tconst unsigned width = sprite.width();\r\n\tassert(width < MaxOutlineSpriteWidth);\r\n\r\n\tint x = 1;\r\n\tauto y = static_cast<uint8_t>(sprite.height());\r\n\r\n\tbool rows[3][MaxOutlineSpriteWidth + 2] = { {}, {}, {} };\r\n\tbool *rowAbove = rows[0];\r\n\tbool *row = rows[1];\r\n\tbool *rowBelow = rows[2];\r\n\r\n\tOutlineRowSolidRuns solidRuns[2];\r\n\tOutlineRowSolidRuns *solidRunAbove = &solidRuns[0];\r\n\tOutlineRowSolidRuns *solidRun = &solidRuns[1];\r\n\r\n\tconst uint8_t *src = sprite.pixelData();\r\n\tconst uint8_t *const end = src + sprite.pixelDataSize();\r\n\twhile (src < end) {\r\n\t\twhile (x <= static_cast<int>(width)) {\r\n\t\t\tconst auto v = static_cast<uint8_t>(*src++);\r\n\t\t\tuint8_t w;\r\n\t\t\tif (IsClxOpaque(v)) {\r\n\t\t\t\tif constexpr (SkipColorIndexZero) {\r\n\t\t\t\t\tif (IsClxOpaqueFill(v)) {\r\n\t\t\t\t\t\tw = GetClxOpaqueFillWidth(v);\r\n\t\t\t\t\t\tconst auto color = static_cast<uint8_t>(*src++);\r\n\t\t\t\t\t\tif (color != 0) {\r\n\t\t\t\t\t\t\tAppendOutlineRowSolidRuns(x, w, *solidRunAbove);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tw = GetClxOpaquePixelsWidth(v);\r\n\t\t\t\t\t\tbool prevZero = solidRunAbove->empty() || solidRunAbove->back().second != x;\r\n\t\t\t\t\t\tfor (unsigned i = 0; i < w; ++i) {\r\n\t\t\t\t\t\t\tconst auto color = static_cast<uint8_t>(src[i]);\r\n\t\t\t\t\t\t\tif (color == 0) {\r\n\t\t\t\t\t\t\t\tif (!prevZero) ++solidRunAbove->back().second;\r\n\t\t\t\t\t\t\t\tprevZero = true;\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tif (prevZero) solidRunAbove->emplace_back(x + i, x + i);\r\n\t\t\t\t\t\t\t\t++solidRunAbove->back().second;\r\n\t\t\t\t\t\t\t\tprevZero = false;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tsrc += w;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (IsClxOpaqueFill(v)) {\r\n\t\t\t\t\t\tw = GetClxOpaqueFillWidth(v);\r\n\t\t\t\t\t\t++src;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tw = GetClxOpaquePixelsWidth(v);\r\n\t\t\t\t\t\tsrc += w;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tAppendOutlineRowSolidRuns(x, w, *solidRunAbove);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tw = v;\r\n\t\t\t}\r\n\t\t\tx += w;\r\n\t\t}\r\n\r\n\t\tfor (const auto &[xBegin, xEnd] : *solidRunAbove) {\r\n\t\t\tstd::fill(rowAbove + xBegin, rowAbove + xEnd, true);\r\n\t\t}\r\n\r\n\t\tif (!solidRun->empty()) {\r\n\t\t\tPopulateOutlinePixelsForRow(*solidRun, rowBelow, row, rowAbove, static_cast<uint8_t>(y + 1), result);\r\n\t\t}\r\n\r\n\t\t// (0, 1, 2) => (2, 0, 1)\r\n\t\tstd::swap(row, rowBelow);\r\n\t\tstd::swap(row, rowAbove);\r\n\t\tstd::fill_n(rowAbove, width, false);\r\n\r\n\t\tstd::swap(solidRunAbove, solidRun);\r\n\t\tsolidRunAbove->clear();\r\n\r\n\t\tif (x > static_cast<int>(width + 1)) {\r\n\t\t\t// Transparent overrun.\r\n\t\t\tconst unsigned numWholeTransparentLines = (x - 1) / width;\r\n\t\t\tif (numWholeTransparentLines > 1) {\r\n\t\t\t\tif (!solidRun->empty()) {\r\n\t\t\t\t\tPopulateOutlinePixelsForRow(*solidRun, rowBelow, row, rowAbove, y, result);\r\n\t\t\t\t}\r\n\t\t\t\tsolidRun->clear();\r\n\t\t\t\tstd::fill_n(row, width, false);\r\n\t\t\t}\r\n\t\t\tif (numWholeTransparentLines > 2) std::fill_n(rowBelow, width, false);\r\n\t\t\ty -= static_cast<uint8_t>(numWholeTransparentLines);\r\n\t\t\tx = static_cast<int>((x - 1) % width) + 1;\r\n\t\t} else {\r\n\t\t\t--y;\r\n\t\t\tx = 1;\r\n\t\t}\r\n\t}\r\n\tstd::fill_n(rowAbove, width, false);\r\n\tif (!solidRun->empty()) {\r\n\t\tPopulateOutlinePixelsForRow(*solidRun, rowBelow, row, rowAbove, static_cast<uint8_t>(y + 1), result);\r\n\t}\r\n}\r\n\r\ntemplate <bool SkipColorIndexZero>\r\nvoid UpdateOutlinePixelsCache(ClxSprite sprite)\r\n{\r\n\tif (OutlinePixelsCache.spriteData == sprite.pixelData()\r\n\t    && OutlinePixelsCache.skipColorIndexZero == SkipColorIndexZero) {\r\n\t\treturn;\r\n\t}\r\n\tOutlinePixelsCache.skipColorIndexZero = SkipColorIndexZero;\r\n\tOutlinePixelsCache.spriteData = sprite.pixelData();\r\n\tOutlinePixelsCache.outlinePixels.clear();\r\n\tGetOutline<SkipColorIndexZero>(sprite, OutlinePixelsCache.outlinePixels);\r\n}\r\n\r\ntemplate <bool SkipColorIndexZero>\r\nvoid RenderClxOutline(const Surface &out, Point position, ClxSprite sprite, uint8_t color)\r\n{\r\n\tUpdateOutlinePixelsCache<SkipColorIndexZero>(sprite);\r\n\t--position.x;\r\n\tposition.y -= sprite.height();\r\n\tif (position.x >= 0 && position.x + sprite.width() + 2 < out.w()\r\n\t    && position.y >= 0 && position.y + sprite.height() + 2 < out.h()) {\r\n\t\tfor (const auto &[x, y] : OutlinePixelsCache.outlinePixels) {\r\n\t\t\t*out.at(position.x + x, position.y + y) = color;\r\n\t\t}\r\n\t} else {\r\n\t\tfor (const auto &[x, y] : OutlinePixelsCache.outlinePixels) {\r\n\t\t\tout.SetPixel(Point(position.x + x, position.y + y), color);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ClxApplyTrans(ClxSprite sprite, const uint8_t *trn)\r\n{\r\n\t// A bit of a hack but this is the only place in the code where we need mutable sprites.\r\n\tauto *dst = const_cast<uint8_t *>(sprite.pixelData());\r\n\tuint16_t remaining = sprite.pixelDataSize();\r\n\twhile (remaining != 0) {\r\n\t\tuint8_t val = *dst++;\r\n\t\t--remaining;\r\n\t\tif (!IsClxOpaque(val))\r\n\t\t\tcontinue;\r\n\t\tif (IsClxOpaqueFill(val)) {\r\n\t\t\t--remaining;\r\n\t\t\t*dst = trn[*dst];\r\n\t\t\tdst++;\r\n\t\t} else {\r\n\t\t\tval = GetClxOpaquePixelsWidth(val);\r\n\t\t\tremaining -= val;\r\n\t\t\twhile (val-- > 0) {\r\n\t\t\t\t*dst = trn[*dst];\r\n\t\t\t\tdst++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid ClxApplyTrans(ClxSpriteList list, const uint8_t *trn)\r\n{\r\n\tfor (const ClxSprite sprite : list) {\r\n\t\tClxApplyTrans(sprite, trn);\r\n\t}\r\n}\r\n\r\nvoid ClxApplyTrans(ClxSpriteSheet sheet, const uint8_t *trn)\r\n{\r\n\tfor (const ClxSpriteList list : sheet) {\r\n\t\tClxApplyTrans(list, trn);\r\n\t}\r\n}\r\n\r\nbool IsPointWithinClx(Point position, ClxSprite clx)\r\n{\r\n\tconst uint8_t *src = clx.pixelData();\r\n\tconst uint8_t *end = src + clx.pixelDataSize();\r\n\tconst uint16_t width = clx.width();\r\n\r\n\tint xCur = 0;\r\n\tint yCur = clx.height() - 1;\r\n\twhile (src < end) {\r\n\t\tif (yCur != position.y) {\r\n\t\t\tSkipSize skipSize {};\r\n\t\t\tskipSize.xOffset = xCur;\r\n\t\t\tsrc = SkipRestOfLineWithOverrun(src, width, skipSize);\r\n\t\t\tyCur -= skipSize.wholeLines;\r\n\t\t\txCur = skipSize.xOffset;\r\n\t\t\tif (yCur < position.y)\r\n\t\t\t\treturn false;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\twhile (xCur < width) {\r\n\t\t\tuint8_t val = *src++;\r\n\t\t\tif (!IsClxOpaque(val)) {\r\n\t\t\t\t// ignore transparent\r\n\t\t\t\txCur += val;\r\n\t\t\t\tif (xCur > position.x)\r\n\t\t\t\t\treturn false;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (IsClxOpaqueFill(val)) {\r\n\t\t\t\tval = GetClxOpaqueFillWidth(val);\r\n\t\t\t\tconst uint8_t color = *src++;\r\n\t\t\t\tif (xCur <= position.x && position.x < xCur + val)\r\n\t\t\t\t\treturn color != 0; // ignore shadows\r\n\t\t\t\txCur += val;\r\n\t\t\t} else {\r\n\t\t\t\tval = GetClxOpaquePixelsWidth(val);\r\n\t\t\t\tfor (uint8_t pixel = 0; pixel < val; pixel++) {\r\n\t\t\t\t\tconst uint8_t color = *src++;\r\n\t\t\t\t\tif (xCur == position.x)\r\n\t\t\t\t\t\treturn color != 0; // ignore shadows\r\n\t\t\t\t\txCur++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nstd::pair<int, int> ClxMeasureSolidHorizontalBounds(ClxSprite clx)\r\n{\r\n\tconst uint8_t *src = clx.pixelData();\r\n\tconst uint8_t *end = src + clx.pixelDataSize();\r\n\tconst uint16_t width = clx.width();\r\n\r\n\tint xBegin = width;\r\n\tint xEnd = 0;\r\n\tint xCur = 0;\r\n\twhile (src < end) {\r\n\t\twhile (xCur < width) {\r\n\t\t\tauto val = *src++;\r\n\t\t\tif (!IsClxOpaque(val)) {\r\n\t\t\t\txCur += val;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (IsClxOpaqueFill(val)) {\r\n\t\t\t\tval = GetClxOpaqueFillWidth(val);\r\n\t\t\t\t++src;\r\n\t\t\t} else {\r\n\t\t\t\tval = GetClxOpaquePixelsWidth(val);\r\n\t\t\t\tsrc += val;\r\n\t\t\t}\r\n\t\t\txBegin = std::min(xBegin, xCur);\r\n\t\t\txCur += val;\r\n\t\t\txEnd = std::max(xEnd, xCur);\r\n\t\t}\r\n\t\twhile (xCur >= width)\r\n\t\t\txCur -= width;\r\n\t\tif (xBegin == 0 && xEnd == width)\r\n\t\t\tbreak;\r\n\t}\r\n\treturn { xBegin, xEnd };\r\n}\r\n\r\n#ifdef DEBUG_CLX\r\nstd::string ClxDescribe(ClxSprite clx)\r\n{\r\n\tstd::string out = StrCat(\r\n\t    \"CLX sprite: \", clx.width(), \"x\", clx.height(), \" pixelDataSize=\", clx.pixelDataSize(),\r\n\t    \"b\\n\\n\"\r\n\t    \"command | width | bytes | color(s)\\n\"\r\n\t    \"--------|------:|------:|---------\\n\");\r\n\tconst uint8_t *src = clx.pixelData();\r\n\tconst uint8_t *end = src + clx.pixelDataSize();\r\n\twhile (src < end) {\r\n\t\tconst uint8_t control = *src++;\r\n\t\tif (IsClxOpaque(control)) {\r\n\t\t\tif (IsClxOpaqueFill(control)) {\r\n\t\t\t\tconst uint8_t length = GetClxOpaqueFillWidth(control);\r\n\t\t\t\tout.append(fmt::format(\"Fill    | {:>5} | {:>5} | {}\\n\", length, 2, src[1]));\r\n\t\t\t\t++src;\r\n\t\t\t} else {\r\n\t\t\t\tconst uint8_t length = GetClxOpaquePixelsWidth(control);\r\n\t\t\t\tout.append(fmt::format(\"Pixels  | {:>5} | {:>5} | {}\\n\", length, length + 1, fmt::join(src + 1, src + 1 + length, \" \")));\r\n\t\t\t\tsrc += length;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tout.append(fmt::format(\"Transp. | {:>5} | {:>5} |\\n\", control, 1));\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n#endif // DEBUG_CLX\r\n\r\nvoid ClxDraw(const Surface &out, Point position, ClxSprite clx)\r\n{\r\n\tDoRenderBackwards(out, position, clx.pixelData(), clx.pixelDataSize(), clx.width(), clx.height(), BlitDirect {});\r\n}\r\n\r\nvoid ClxDrawTRN(const Surface &out, Point position, ClxSprite clx, const uint8_t *trn)\r\n{\r\n\tDoRenderBackwards(out, position, clx.pixelData(), clx.pixelDataSize(), clx.width(), clx.height(), BlitWithMap { trn });\r\n}\r\n\r\nvoid ClxDrawWithLightmap(const Surface &out, Point position, ClxSprite clx, const Lightmap &lightmap)\r\n{\r\n\tDoRenderBackwards(out, position, clx.pixelData(), clx.pixelDataSize(), clx.width(), clx.height(), BlitWithLightmap { lightmap });\r\n}\r\n\r\nvoid ClxDrawBlended(const Surface &out, Point position, ClxSprite clx)\r\n{\r\n\tDoRenderBackwards(out, position, clx.pixelData(), clx.pixelDataSize(), clx.width(), clx.height(), BlitBlended {});\r\n}\r\n\r\nvoid ClxDrawBlendedTRN(const Surface &out, Point position, ClxSprite clx, const uint8_t *trn)\r\n{\r\n\tDoRenderBackwards(out, position, clx.pixelData(), clx.pixelDataSize(), clx.width(), clx.height(), BlitBlendedWithMap { trn });\r\n}\r\n\r\nvoid ClxDrawBlendedWithLightmap(const Surface &out, Point position, ClxSprite clx, const Lightmap &lightmap)\r\n{\r\n\tDoRenderBackwards(out, position, clx.pixelData(), clx.pixelDataSize(), clx.width(), clx.height(), BlitBlendedWithLightmap { lightmap });\r\n}\r\n\r\nvoid ClxDrawOutline(const Surface &out, uint8_t col, Point position, ClxSprite clx)\r\n{\r\n\tRenderClxOutline</*SkipColorIndexZero=*/false>(out, position, clx, col);\r\n}\r\n\r\nvoid ClxDrawOutlineSkipColorZero(const Surface &out, uint8_t col, Point position, ClxSprite clx)\r\n{\r\n\tRenderClxOutline</*SkipColorIndexZero=*/true>(out, position, clx, col);\r\n}\r\n\r\nvoid ClearClxDrawCache()\r\n{\r\n\tOutlinePixelsCache.spriteData = nullptr;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/clx_render.hpp",
    "content": "/**\r\n * @file clx_render.hpp\r\n *\r\n * CL2 rendering.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <utility>\r\n\r\n#ifdef DEBUG_CLX\r\n#include <string>\r\n#endif\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/light_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Apply the color swaps to a CLX sprite list;\r\n */\r\nvoid ClxApplyTrans(ClxSpriteList list, const uint8_t *trn);\r\nvoid ClxApplyTrans(ClxSpriteSheet sheet, const uint8_t *trn);\r\n\r\n/**\r\n * @brief Blit CL2 sprite, to the back buffer at the given coordianates\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n * @param frame CL2 frame number\r\n */\r\nvoid ClxDraw(const Surface &out, Point position, ClxSprite clx);\r\n\r\n/**\r\n * @brief Same as ClxDraw but position.y is the top of the sprite instead of the bottom.\r\n */\r\ninline void RenderClxSprite(const Surface &out, ClxSprite clx, Point position)\r\n{\r\n\tClxDraw(out, { position.x, position.y + static_cast<int>(clx.height()) - 1 }, clx);\r\n}\r\n\r\n/**\r\n * @brief Blit a solid colder shape one pixel larger than the given sprite shape, to the given buffer at the given coordinates\r\n * @param col Color index from current palette\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n */\r\nvoid ClxDrawOutline(const Surface &out, uint8_t col, Point position, ClxSprite clx);\r\n\r\n/**\r\n * @brief Same as `ClxDrawOutline` but considers colors with index 0 (usually shadows) to be transparent.\r\n *\r\n * @param col Color index from current palette\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n */\r\nvoid ClxDrawOutlineSkipColorZero(const Surface &out, uint8_t col, Point position, ClxSprite clx);\r\n\r\n/**\r\n * @brief Blit CL2 sprite, and apply given TRN to the given buffer at the given coordinates\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n * @param trn TRN to use\r\n */\r\nvoid ClxDrawTRN(const Surface &out, Point position, ClxSprite clx, const uint8_t *trn);\r\n\r\n/**\r\n * @brief Same as ClxDrawTRN but position.y is the top of the sprite instead of the bottom.\r\n */\r\ninline void RenderClxSpriteWithTRN(const Surface &out, ClxSprite clx, Point position, const uint8_t *trn)\r\n{\r\n\tClxDrawTRN(out, { position.x, position.y + static_cast<int>(clx.height()) - 1 }, clx, trn);\r\n}\r\n\r\nvoid ClxDrawBlendedTRN(const Surface &out, Point position, ClxSprite clx, const uint8_t *trn);\r\n\r\n/**\r\n * @brief Blit CLX sprite with 50% transparency to the given buffer at the given coordinates.\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n */\r\nvoid ClxDrawBlended(const Surface &out, Point position, ClxSprite clx);\r\n\r\n/**\r\n * @brief Blit CL2 sprite, and apply lighting, to the given buffer at the given coordinates\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n * @param lightmap Per-pixel light buffer\r\n */\r\nvoid ClxDrawWithLightmap(const Surface &out, Point position, ClxSprite clx, const Lightmap &lightmap);\r\n\r\n/**\r\n * @brief Blit CL2 sprite, and apply lighting and transparency blending, to the given buffer at the given coordinates\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n * @param lightmap Per-pixel light buffer\r\n */\r\nvoid ClxDrawBlendedWithLightmap(const Surface &out, Point position, ClxSprite clx, const Lightmap &lightmap);\r\n\r\n/**\r\n * Returns if cursor is within the CLX sprite (ignores shadow)\r\n */\r\nbool IsPointWithinClx(Point position, ClxSprite clx);\r\n\r\n/**\r\n * Returns a pair of X coordinates containing the start (inclusive) and end (exclusive)\r\n * of fully transparent columns in the sprite.\r\n */\r\nstd::pair<int, int> ClxMeasureSolidHorizontalBounds(ClxSprite clx);\r\n\r\n/**\r\n * @brief Clears the CLX draw cache.\r\n *\r\n * Must be called whenever CLX sprites are freed.\r\n */\r\nvoid ClearClxDrawCache();\r\n\r\n#ifdef DEBUG_CLX\r\nstd::string ClxDescribe(ClxSprite clx);\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/dun_render.cpp",
    "content": "/**\r\n * @file dun_render.cpp\r\n *\r\n * Implementation of functionality for rendering the level tiles.\r\n */\r\n\r\n// Debugging variables\r\n// #define DEBUG_STR\r\n// #define DEBUG_RENDER_COLOR\r\n// #define DEBUG_RENDER_OFFSET_X 5\r\n// #define DEBUG_RENDER_OFFSET_Y 5\r\n\r\n#include \"engine/render/dun_render.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include \"appfat.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/blit_impl.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/attributes.h\"\r\n#ifdef DEBUG_STR\r\n#include \"engine/render/text_render.hpp\"\r\n#endif\r\n#if defined(DEBUG_STR) || defined(DUN_RENDER_STATS)\r\n#include \"utils/str_cat.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n/** Width of a tile rendering primitive. */\r\nconstexpr int_fast16_t Width = DunFrameWidth;\r\n\r\n/** Height of a tile rendering primitive (except triangles). */\r\nconstexpr int_fast16_t Height = DunFrameHeight;\r\n\r\n/** Height of the lower triangle of a triangular or a trapezoid tile. */\r\nconstexpr int_fast16_t LowerHeight = DunFrameHeight / 2;\r\n\r\n/** Height of the upper triangle of a triangular tile. */\r\nconstexpr int_fast16_t TriangleUpperHeight = DunFrameHeight / 2 - 1;\r\n\r\n/** Height of the upper rectangle of a trapezoid tile. */\r\nconstexpr int_fast16_t TrapezoidUpperHeight = DunFrameHeight / 2;\r\n\r\nconstexpr int_fast16_t TriangleHeight = DunFrameTriangleHeight;\r\n\r\n/** For triangles, for each pixel drawn vertically, this many pixels are drawn horizontally. */\r\nconstexpr int_fast16_t XStep = 2;\r\n\r\n#ifdef DEBUG_STR\r\nstd::pair<std::string_view, UiFlags> GetTileDebugStr(TileType tile)\r\n{\r\n\t// clang-format off\r\n\tswitch (tile) {\r\n\t\tcase TileType::Square: return {\"S\", UiFlags::AlignCenter | UiFlags::VerticalCenter};\r\n\t\tcase TileType::TransparentSquare: return {\"T\", UiFlags::AlignCenter | UiFlags::VerticalCenter};\r\n\t\tcase TileType::LeftTriangle: return {\"<\", UiFlags::AlignRight | UiFlags::VerticalCenter};\r\n\t\tcase TileType::RightTriangle: return {\">\", UiFlags::VerticalCenter};\r\n\t\tcase TileType::LeftTrapezoid: return {\"\\\\\", UiFlags::AlignCenter};\r\n\t\tcase TileType::RightTrapezoid: return {\"/\", UiFlags::AlignCenter};\r\n\t\tdefault: return {\"\", {}};\r\n\t}\r\n\t// clang-format on\r\n}\r\n#endif\r\n\r\n#ifdef DEBUG_RENDER_COLOR\r\nint DBGCOLOR = 0;\r\n\r\nint GetTileDebugColor(TileType tile)\r\n{\r\n\t// clang-format off\r\n\tswitch (tile) {\r\n\t\tcase TileType::Square: return PAL16_YELLOW + 5;\r\n\t\tcase TileType::TransparentSquare: return PAL16_ORANGE + 5;\r\n\t\tcase TileType::LeftTriangle: return PAL16_GRAY + 5;\r\n\t\tcase TileType::RightTriangle: return PAL16_BEIGE;\r\n\t\tcase TileType::LeftTrapezoid: return PAL16_RED + 5;\r\n\t\tcase TileType::RightTrapezoid: return PAL16_BLUE + 5;\r\n\t\tdefault: return 0;\r\n\t}\r\n\t// clang-format on\r\n}\r\n#endif // DEBUG_RENDER_COLOR\r\n\r\n// How many pixels to increment the transparent (Left) or opaque (Right)\r\n// prefix width after each line (drawing bottom-to-top).\r\ntemplate <MaskType Mask>\r\nconstexpr int8_t PrefixIncrement = 0;\r\ntemplate <>\r\nconstexpr int8_t PrefixIncrement<MaskType::Left> = 2;\r\ntemplate <>\r\nconstexpr int8_t PrefixIncrement<MaskType::Right> = -2;\r\n\r\n// Initial value for the prefix.\r\ntemplate <MaskType Mask>\r\nint8_t InitialPrefix = PrefixIncrement<Mask> >= 0 ? -32 : 64;\r\n\r\n// The initial value for the prefix at y-th line (counting from the bottom).\r\ntemplate <MaskType Mask>\r\nDVL_ALWAYS_INLINE int8_t InitPrefix(int8_t y)\r\n{\r\n\treturn InitialPrefix<Mask> + PrefixIncrement<Mask> * y;\r\n}\r\n\r\nenum class LightType : uint8_t {\r\n\tFullyDark,\r\n\tPartiallyLit,\r\n\tFullyLit,\r\n\tPerPixel,\r\n};\r\n\r\ntemplate <LightType Light>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineOpaque(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap);\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineOpaque<LightType::FullyDark>(uint8_t *DVL_RESTRICT dst, [[maybe_unused]] const uint8_t *DVL_RESTRICT src, uint_fast8_t n, [[maybe_unused]] const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n\tBlitFillDirect(dst, n, 0);\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineOpaque<LightType::FullyLit>(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, [[maybe_unused]] const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n#ifndef DEBUG_RENDER_COLOR\r\n\tBlitPixelsDirect(dst, src, n);\r\n#else\r\n\tBlitFillDirect(dst, n, DBGCOLOR);\r\n#endif\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineOpaque<LightType::PartiallyLit>(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n#ifndef DEBUG_RENDER_COLOR\r\n\tBlitPixelsWithMap(dst, src, n, tbl);\r\n#else\r\n\tBlitFillDirect(dst, n, tbl[DBGCOLOR]);\r\n#endif\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineOpaque<LightType::PerPixel>(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n#ifndef DEBUG_RENDER_COLOR\r\n\tBlitPixelsWithLightmap(dst, src, n, *lightmap);\r\n#else\r\n\tBlitFillWithLightmap(dst, n, DBGCOLOR, *lightmap);\r\n#endif\r\n}\r\n\r\n#ifndef DEBUG_RENDER_COLOR\r\ntemplate <LightType Light>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparent(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap);\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparent<LightType::FullyDark>(uint8_t *DVL_RESTRICT dst, [[maybe_unused]] const uint8_t *DVL_RESTRICT src, uint_fast8_t n, [[maybe_unused]] const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n\tBlitFillBlended(dst, n, 0);\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparent<LightType::FullyLit>(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, [[maybe_unused]] const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n\tBlitPixelsBlended(dst, src, n);\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparent<LightType::PartiallyLit>(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n\tBlitPixelsBlendedWithMap(dst, src, n, tbl);\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparent<LightType::PerPixel>(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tBlitPixelsBlendedWithLightmap(dst, src, n, *lightmap);\r\n}\r\n#else // DEBUG_RENDER_COLOR\r\ntemplate <LightType Light>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparent(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n\tfor (size_t i = 0; i < n; i++) {\r\n\t\tdst[i] = paletteTransparencyLookup[dst[i]][tbl[DBGCOLOR + 4]];\r\n\t}\r\n}\r\n#endif\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparentOrOpaque(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t width, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tif constexpr (Transparent) {\r\n\t\tRenderLineTransparent<Light>(dst, src, width, tbl, lightmap);\r\n\t} else {\r\n\t\tRenderLineOpaque<Light>(dst, src, width, tbl, lightmap);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool OpaqueFirst>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLineTransparentAndOpaque(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t prefixWidth, uint_fast8_t width, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tif constexpr (OpaqueFirst) {\r\n\t\tRenderLineOpaque<Light>(dst, src, prefixWidth, tbl, &lightmap);\r\n\t\tRenderLineTransparent<Light>(dst + prefixWidth, src + prefixWidth, width - prefixWidth, tbl, &lightmap);\r\n\t} else {\r\n\t\tRenderLineTransparent<Light>(dst, src, prefixWidth, tbl, &lightmap);\r\n\t\tRenderLineOpaque<Light>(dst + prefixWidth, src + prefixWidth, width - prefixWidth, tbl, &lightmap);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLine(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, uint_fast8_t n, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, int8_t prefix)\r\n{\r\n\tif constexpr (Mask == MaskType::Solid || Mask == MaskType::Transparent) {\r\n\t\tRenderLineTransparentOrOpaque<Light, /*Transparent=*/Mask == MaskType::Transparent>(dst, src, n, tbl, &lightmap);\r\n\t} else if (prefix >= static_cast<int8_t>(n)) {\r\n\t\t// We std::clamp the prefix to (0, n] and avoid calling `RenderLineTransparent/Opaque` with width=0.\r\n\t\tif constexpr (Mask == MaskType::Right) {\r\n\t\t\tRenderLineOpaque<Light>(dst, src, n, tbl, &lightmap);\r\n\t\t} else {\r\n\t\t\tRenderLineTransparent<Light>(dst, src, n, tbl, &lightmap);\r\n\t\t}\r\n\t} else if (prefix <= 0) {\r\n\t\tif constexpr (Mask == MaskType::Left) {\r\n\t\t\tRenderLineOpaque<Light>(dst, src, n, tbl, &lightmap);\r\n\t\t} else {\r\n\t\t\tRenderLineTransparent<Light>(dst, src, n, tbl, &lightmap);\r\n\t\t}\r\n\t} else {\r\n\t\tRenderLineTransparentAndOpaque<Light, /*OpaqueFirst=*/Mask == MaskType::Right>(dst, src, prefix, n, tbl, lightmap);\r\n\t}\r\n}\r\n\r\nstruct Clip {\r\n\tint_fast16_t top;\r\n\tint_fast16_t bottom;\r\n\tint_fast16_t left;\r\n\tint_fast16_t right;\r\n\tint_fast16_t width;\r\n\tint_fast16_t height;\r\n};\r\n\r\nDVL_ALWAYS_INLINE Clip CalculateClip(int_fast16_t x, int_fast16_t y, int_fast16_t w, int_fast16_t h, const Surface &out)\r\n{\r\n\tClip clip;\r\n\tclip.top = y + 1 < h ? h - (y + 1) : 0;\r\n\tclip.bottom = y + 1 > out.h() ? (y + 1) - out.h() : 0;\r\n\tclip.left = x < 0 ? -x : 0;\r\n\tclip.right = x + w > out.w() ? x + w - out.w() : 0;\r\n\tclip.width = w - clip.left - clip.right;\r\n\tclip.height = h - clip.top - clip.bottom;\r\n\treturn clip;\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderSquareFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tfor (auto i = 0; i < Height; ++i, dst -= dstPitch) {\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, Width, tbl, &lightmap);\r\n\t\tsrc += Width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderSquareClipped(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tsrc += clip.bottom * Height + clip.left;\r\n\tfor (auto i = 0; i < clip.height; ++i, dst -= dstPitch) {\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, clip.width, tbl, &lightmap);\r\n\t\tsrc += Width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderSquare(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tif (clip.width == Width && clip.height == Height) {\r\n\t\tRenderSquareFull<Light, Transparent>(dst, dstPitch, src, tbl, lightmap);\r\n\t} else {\r\n\t\tRenderSquareClipped<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquareFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, unsigned height)\r\n{\r\n\tint8_t prefix = InitialPrefix<Mask>;\r\n\tDVL_ASSUME(height >= 16);\r\n\tDVL_ASSUME(height <= 32);\r\n\tfor (unsigned i = 0; i < height; ++i, dst -= dstPitch + Width) {\r\n\t\tuint_fast8_t drawWidth = Width;\r\n\t\twhile (drawWidth > 0) {\r\n\t\t\tauto v = static_cast<int8_t>(*src++);\r\n\t\t\tif (v > 0) {\r\n\t\t\t\tRenderLine<Light, Mask>(dst, src, v, tbl, lightmap, prefix - (Width - drawWidth));\r\n\t\t\t\tsrc += v;\r\n\t\t\t} else {\r\n\t\t\t\tv = -v;\r\n\t\t\t}\r\n\t\t\tdst += v;\r\n\t\t\tdrawWidth -= v;\r\n\t\t}\r\n\t\tprefix += PrefixIncrement<Mask>;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\n// NOLINTNEXTLINE(readability-function-cognitive-complexity): Actually complex and has to be fast.\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquareClipped(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tconst auto skipRestOfTheLine = [&src](int_fast16_t remainingWidth) {\r\n\t\twhile (remainingWidth > 0) {\r\n\t\t\tconst auto v = static_cast<int8_t>(*src++);\r\n\t\t\tif (v > 0) {\r\n\t\t\t\tsrc += v;\r\n\t\t\t\tremainingWidth -= v;\r\n\t\t\t} else {\r\n\t\t\t\tremainingWidth -= -v;\r\n\t\t\t}\r\n\t\t}\r\n\t\tassert(remainingWidth == 0);\r\n\t};\r\n\r\n\t// Skip the bottom clipped lines.\r\n\tfor (auto i = 0; i < clip.bottom; ++i) {\r\n\t\tskipRestOfTheLine(Width);\r\n\t}\r\n\r\n\tint8_t prefix = InitPrefix<Mask>(clip.bottom);\r\n\tfor (auto i = 0; i < clip.height; ++i, dst -= dstPitch + clip.width) {\r\n\t\tauto drawWidth = clip.width;\r\n\r\n\t\t// Skip initial src if clipping on the left.\r\n\t\t// Handles overshoot, i.e. when the RLE segment goes into the unclipped area.\r\n\t\tauto remainingLeftClip = clip.left;\r\n\t\twhile (remainingLeftClip > 0) {\r\n\t\t\tauto v = static_cast<int8_t>(*src++);\r\n\t\t\tif (v > 0) {\r\n\t\t\t\tif (v > remainingLeftClip) {\r\n\t\t\t\t\tconst auto overshoot = v - remainingLeftClip;\r\n\t\t\t\t\tRenderLine<Light, Mask>(dst, src + remainingLeftClip, overshoot, tbl, lightmap, prefix - (Width - remainingLeftClip));\r\n\t\t\t\t\tdst += overshoot;\r\n\t\t\t\t\tdrawWidth -= overshoot;\r\n\t\t\t\t}\r\n\t\t\t\tsrc += v;\r\n\t\t\t} else {\r\n\t\t\t\tv = -v;\r\n\t\t\t\tif (v > remainingLeftClip) {\r\n\t\t\t\t\tconst auto overshoot = v - remainingLeftClip;\r\n\t\t\t\t\tdst += overshoot;\r\n\t\t\t\t\tdrawWidth -= overshoot;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tremainingLeftClip -= v;\r\n\t\t}\r\n\r\n\t\t// Draw the non-clipped segment\r\n\t\twhile (drawWidth > 0) {\r\n\t\t\tauto v = static_cast<int8_t>(*src++);\r\n\t\t\tif (v > 0) {\r\n\t\t\t\tif (v > drawWidth) {\r\n\t\t\t\t\tRenderLine<Light, Mask>(dst, src, drawWidth, tbl, lightmap, prefix - (Width - drawWidth));\r\n\t\t\t\t\tsrc += v;\r\n\t\t\t\t\tdst += drawWidth;\r\n\t\t\t\t\tdrawWidth -= v;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tRenderLine<Light, Mask>(dst, src, v, tbl, lightmap, prefix - (Width - drawWidth));\r\n\t\t\t\tsrc += v;\r\n\t\t\t} else {\r\n\t\t\t\tv = -v;\r\n\t\t\t\tif (v > drawWidth) {\r\n\t\t\t\t\tdst += drawWidth;\r\n\t\t\t\t\tdrawWidth -= v;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tdst += v;\r\n\t\t\tdrawWidth -= v;\r\n\t\t}\r\n\r\n\t\t// Skip the rest of src line if clipping on the right\r\n\t\tassert(drawWidth <= 0);\r\n\t\tskipRestOfTheLine(clip.right + drawWidth);\r\n\t\tprefix += PrefixIncrement<Mask>;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTransparentSquare(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tif (clip.width == Width && clip.bottom == 0 && clip.top == 0) {\r\n\t\tRenderTransparentSquareFull<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip.height);\r\n\t} else {\r\n\t\tRenderTransparentSquareClipped<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\n/** Vertical clip for the lower and upper triangles of a diamond tile (L/RTRIANGLE).*/\r\nstruct DiamondClipY {\r\n\tint_fast16_t lowerBottom;\r\n\tint_fast16_t lowerTop;\r\n\tint_fast16_t upperBottom;\r\n\tint_fast16_t upperTop;\r\n};\r\n\r\ntemplate <int_fast16_t UpperHeight = TriangleUpperHeight>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT DiamondClipY CalculateDiamondClipY(const Clip &clip)\r\n{\r\n\tDiamondClipY result;\r\n\tif (clip.bottom > LowerHeight) {\r\n\t\tresult.lowerBottom = LowerHeight;\r\n\t\tresult.upperBottom = clip.bottom - LowerHeight;\r\n\t\tresult.lowerTop = result.upperTop = 0;\r\n\t} else if (clip.top > UpperHeight) {\r\n\t\tresult.upperTop = UpperHeight;\r\n\t\tresult.lowerTop = clip.top - UpperHeight;\r\n\t\tresult.upperBottom = result.lowerBottom = 0;\r\n\t} else {\r\n\t\tresult.upperTop = clip.top;\r\n\t\tresult.lowerBottom = clip.bottom;\r\n\t\tresult.lowerTop = result.upperBottom = 0;\r\n\t}\r\n\treturn result;\r\n}\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT std::size_t CalculateTriangleSourceSkipLowerBottom(int_fast16_t numLines)\r\n{\r\n\treturn XStep * numLines * (numLines + 1) / 2;\r\n}\r\n\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT std::size_t CalculateTriangleSourceSkipUpperBottom(int_fast16_t numLines)\r\n{\r\n\treturn 2 * TriangleUpperHeight * numLines - numLines * (numLines - 1);\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTriangleLower(uint8_t *DVL_RESTRICT &dst, ptrdiff_t dstLineOffset, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 0 * dstLineOffset, src + 0, 2, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 1 * dstLineOffset, src + 2, 4, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 2 * dstLineOffset, src + 6, 6, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 3 * dstLineOffset, src + 12, 8, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 4 * dstLineOffset, src + 20, 10, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 5 * dstLineOffset, src + 30, 12, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 6 * dstLineOffset, src + 42, 14, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 7 * dstLineOffset, src + 56, 16, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 8 * dstLineOffset, src + 72, 18, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 9 * dstLineOffset, src + 90, 20, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 10 * dstLineOffset, src + 110, 22, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 11 * dstLineOffset, src + 132, 24, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 12 * dstLineOffset, src + 156, 26, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 13 * dstLineOffset, src + 182, 28, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 14 * dstLineOffset, src + 210, 30, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 15 * dstLineOffset, src + 240, 32, tbl, lightmap);\r\n\tsrc += 272;\r\n\tdst -= 16 * dstLineOffset;\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTriangleLower<LightType::FullyDark, /*Transparent=*/false>(uint8_t *DVL_RESTRICT &dst, ptrdiff_t dstLineOffset, const uint8_t *DVL_RESTRICT &src, [[maybe_unused]] const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n\tunsigned width = XStep;\r\n\tfor (unsigned i = 0; i < LowerHeight; ++i) {\r\n\t\tBlitFillDirect(dst, width, 0);\r\n\t\tdst -= dstLineOffset;\r\n\t\twidth += XStep;\r\n\t}\r\n\tsrc += 272;\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTriangleUpper(uint8_t *DVL_RESTRICT dst, ptrdiff_t dstLineOffset, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 0 * dstLineOffset, src + 0, 30, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 1 * dstLineOffset, src + 30, 28, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 2 * dstLineOffset, src + 58, 26, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 3 * dstLineOffset, src + 84, 24, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 4 * dstLineOffset, src + 108, 22, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 5 * dstLineOffset, src + 130, 20, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 6 * dstLineOffset, src + 150, 18, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 7 * dstLineOffset, src + 168, 16, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 8 * dstLineOffset, src + 184, 14, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 9 * dstLineOffset, src + 198, 12, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 10 * dstLineOffset, src + 210, 10, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 11 * dstLineOffset, src + 220, 8, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 12 * dstLineOffset, src + 228, 6, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 13 * dstLineOffset, src + 234, 4, tbl, lightmap);\r\n\tRenderLineTransparentOrOpaque<Light, Transparent>(dst - 14 * dstLineOffset, src + 238, 2, tbl, lightmap);\r\n}\r\n\r\ntemplate <>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTriangleUpper<LightType::FullyDark, /*Transparent=*/false>(uint8_t *DVL_RESTRICT dst, ptrdiff_t dstLineOffset, [[maybe_unused]] const uint8_t *DVL_RESTRICT src, [[maybe_unused]] const uint8_t *DVL_RESTRICT tbl, [[maybe_unused]] const Lightmap *lightmap)\r\n{\r\n\tunsigned width = Width - XStep;\r\n\tfor (unsigned i = 0; i < TriangleUpperHeight; ++i) {\r\n\t\tBlitFillDirect(dst, width, 0);\r\n\t\tdst -= dstLineOffset;\r\n\t\twidth -= XStep;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleLower(uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tdst += XStep * (LowerHeight - 1);\r\n\tRenderTriangleLower<Light, Transparent>(dst, dstPitch + XStep, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleLowerClipVertical(const DiamondClipY &clipY, uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tsrc += CalculateTriangleSourceSkipLowerBottom(clipY.lowerBottom);\r\n\tdst += XStep * (LowerHeight - clipY.lowerBottom - 1);\r\n\tconst auto lowerMax = LowerHeight - clipY.lowerTop;\r\n\tfor (auto i = 1 + clipY.lowerBottom; i <= lowerMax; ++i, dst -= dstPitch + XStep) {\r\n\t\tconst auto width = XStep * i;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleLowerClipLeftAndVertical(int_fast16_t clipLeft, const DiamondClipY &clipY, uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tsrc += CalculateTriangleSourceSkipLowerBottom(clipY.lowerBottom);\r\n\tdst += XStep * (LowerHeight - clipY.lowerBottom - 1) - clipLeft;\r\n\tconst auto lowerMax = LowerHeight - clipY.lowerTop;\r\n\tfor (auto i = 1 + clipY.lowerBottom; i <= lowerMax; ++i, dst -= dstPitch + XStep) {\r\n\t\tconst auto width = XStep * i;\r\n\t\tconst auto startX = Width - XStep * i;\r\n\t\tconst auto skip = startX < clipLeft ? clipLeft - startX : 0;\r\n\t\tif (width > skip)\r\n\t\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst + skip, src + skip, width - skip, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleLowerClipRightAndVertical(int_fast16_t clipRight, const DiamondClipY &clipY, uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tsrc += CalculateTriangleSourceSkipLowerBottom(clipY.lowerBottom);\r\n\tdst += XStep * (LowerHeight - clipY.lowerBottom - 1);\r\n\tconst auto lowerMax = LowerHeight - clipY.lowerTop;\r\n\tfor (auto i = 1 + clipY.lowerBottom; i <= lowerMax; ++i, dst -= dstPitch + XStep) {\r\n\t\tconst auto width = XStep * i;\r\n\t\tif (width > clipRight)\r\n\t\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width - clipRight, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tRenderLeftTriangleLower<Light, Transparent>(dst, dstPitch, src, tbl, lightmap);\r\n\tdst += 2 * XStep;\r\n\tRenderTriangleUpper<Light, Transparent>(dst, dstPitch - XStep, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleClipVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY(clip);\r\n\tRenderLeftTriangleLowerClipVertical<Light, Transparent>(clipY, dst, dstPitch, src, tbl, lightmap);\r\n\tsrc += CalculateTriangleSourceSkipUpperBottom(clipY.upperBottom);\r\n\tdst += 2 * XStep + XStep * clipY.upperBottom;\r\n\tconst auto upperMax = TriangleUpperHeight - clipY.upperTop;\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch - XStep) {\r\n\t\tconst auto width = Width - XStep * i;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY(clip);\r\n\tconst int_fast16_t clipLeft = clip.left;\r\n\tRenderLeftTriangleLowerClipLeftAndVertical<Light, Transparent>(clipLeft, clipY, dst, dstPitch, src, tbl, lightmap);\r\n\tsrc += CalculateTriangleSourceSkipUpperBottom(clipY.upperBottom);\r\n\tdst += 2 * XStep + XStep * clipY.upperBottom;\r\n\tconst auto upperMax = TriangleUpperHeight - clipY.upperTop;\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch - XStep) {\r\n\t\tconst auto width = Width - XStep * i;\r\n\t\tconst auto startX = XStep * i;\r\n\t\tconst auto skip = startX < clipLeft ? clipLeft - startX : 0;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst + skip, src + skip, width > skip ? width - skip : 0, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangleClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY(clip);\r\n\tconst int_fast16_t clipRight = clip.right;\r\n\tRenderLeftTriangleLowerClipRightAndVertical<Light, Transparent>(clipRight, clipY, dst, dstPitch, src, tbl, lightmap);\r\n\tsrc += CalculateTriangleSourceSkipUpperBottom(clipY.upperBottom);\r\n\tdst += 2 * XStep + XStep * clipY.upperBottom;\r\n\tconst auto upperMax = TriangleUpperHeight - clipY.upperTop;\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch - XStep) {\r\n\t\tconst auto width = Width - XStep * i;\r\n\t\tif (width <= clipRight)\r\n\t\t\tbreak;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width - clipRight, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTriangle(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tif (clip.width == Width) {\r\n\t\tif (clip.height == TriangleHeight) {\r\n\t\t\tRenderLeftTriangleFull<Light, Transparent>(dst, dstPitch, src, tbl, lightmap);\r\n\t\t} else {\r\n\t\t\tRenderLeftTriangleClipVertical<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\t}\r\n\t} else if (clip.right == 0) {\r\n\t\tRenderLeftTriangleClipLeftAndVertical<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else {\r\n\t\tRenderLeftTriangleClipRightAndVertical<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleLower(uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tRenderTriangleLower<Light, Transparent>(dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleLowerClipVertical(const DiamondClipY &clipY, uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tsrc += CalculateTriangleSourceSkipLowerBottom(clipY.lowerBottom);\r\n\tconst auto lowerMax = LowerHeight - clipY.lowerTop;\r\n\tfor (auto i = 1 + clipY.lowerBottom; i <= lowerMax; ++i, dst -= dstPitch) {\r\n\t\tconst auto width = XStep * i;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleLowerClipLeftAndVertical(int_fast16_t clipLeft, const DiamondClipY &clipY, uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tsrc += CalculateTriangleSourceSkipLowerBottom(clipY.lowerBottom);\r\n\tconst auto lowerMax = LowerHeight - clipY.lowerTop;\r\n\tfor (auto i = 1 + clipY.lowerBottom; i <= lowerMax; ++i, dst -= dstPitch) {\r\n\t\tconst auto width = XStep * i;\r\n\t\tif (width > clipLeft)\r\n\t\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src + clipLeft, width - clipLeft, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleLowerClipRightAndVertical(int_fast16_t clipRight, const DiamondClipY &clipY, uint8_t *DVL_RESTRICT &dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT &src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tsrc += CalculateTriangleSourceSkipLowerBottom(clipY.lowerBottom);\r\n\tconst auto lowerMax = LowerHeight - clipY.lowerTop;\r\n\tfor (auto i = 1 + clipY.lowerBottom; i <= lowerMax; ++i, dst -= dstPitch) {\r\n\t\tconst auto width = XStep * i;\r\n\t\tconst auto skip = Width - width < clipRight ? clipRight - (Width - width) : 0;\r\n\t\tif (width > skip)\r\n\t\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width - skip, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap)\r\n{\r\n\tRenderRightTriangleLower<Light, Transparent>(dst, dstPitch, src, tbl, lightmap);\r\n\tRenderTriangleUpper<Light, Transparent>(dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleClipVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY(clip);\r\n\tRenderRightTriangleLowerClipVertical<Light, Transparent>(clipY, dst, dstPitch, src, tbl, lightmap);\r\n\tsrc += CalculateTriangleSourceSkipUpperBottom(clipY.upperBottom);\r\n\tconst auto upperMax = TriangleUpperHeight - clipY.upperTop;\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch) {\r\n\t\tconst auto width = Width - XStep * i;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY(clip);\r\n\tconst int_fast16_t clipLeft = clip.left;\r\n\tRenderRightTriangleLowerClipLeftAndVertical<Light, Transparent>(clipLeft, clipY, dst, dstPitch, src, tbl, lightmap);\r\n\tsrc += CalculateTriangleSourceSkipUpperBottom(clipY.upperBottom);\r\n\tconst auto upperMax = TriangleUpperHeight - clipY.upperTop;\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch) {\r\n\t\tconst auto width = Width - XStep * i;\r\n\t\tif (width <= clipLeft)\r\n\t\t\tbreak;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src + clipLeft, width - clipLeft, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangleClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY(clip);\r\n\tconst int_fast16_t clipRight = clip.right;\r\n\tRenderRightTriangleLowerClipRightAndVertical<Light, Transparent>(clipRight, clipY, dst, dstPitch, src, tbl, lightmap);\r\n\tsrc += CalculateTriangleSourceSkipUpperBottom(clipY.upperBottom);\r\n\tconst auto upperMax = TriangleUpperHeight - clipY.upperTop;\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch) {\r\n\t\tconst auto width = Width - XStep * i;\r\n\t\tconst auto skip = Width - width < clipRight ? clipRight - (Width - width) : 0;\r\n\t\tRenderLineTransparentOrOpaque<Light, Transparent>(dst, src, width > skip ? width - skip : 0, tbl, lightmap);\r\n\t\tsrc += width;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTriangle(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap *lightmap, Clip clip)\r\n{\r\n\tif (clip.width == Width) {\r\n\t\tif (clip.height == TriangleHeight) {\r\n\t\t\tRenderRightTriangleFull<Light, Transparent>(dst, dstPitch, src, tbl, lightmap);\r\n\t\t} else {\r\n\t\t\tRenderRightTriangleClipVertical<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\t}\r\n\t} else if (clip.right == 0) {\r\n\t\tRenderRightTriangleClipLeftAndVertical<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else {\r\n\t\tRenderRightTriangleClipRightAndVertical<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTrapezoidUpperHalf(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tif constexpr (Mask == MaskType::Left || Mask == MaskType::Right) {\r\n\t\t// The first line is always fully opaque.\r\n\t\t// We handle it specially to avoid calling the blitter with width=0.\r\n\t\tconst uint8_t *srcEnd = src + Width * TrapezoidUpperHeight;\r\n\t\tRenderLineOpaque<Light>(dst, src, Width, tbl, &lightmap);\r\n\t\tsrc += Width;\r\n\t\tdst -= dstPitch;\r\n\t\tuint8_t prefixWidth = (PrefixIncrement<Mask> < 0 ? 32 : 0) + PrefixIncrement<Mask>;\r\n\t\tdo {\r\n\t\t\tRenderLineTransparentAndOpaque<Light, /*OpaqueFirst=*/Mask == MaskType::Right>(dst, src, prefixWidth, Width, tbl, lightmap);\r\n\t\t\tprefixWidth += PrefixIncrement<Mask>;\r\n\t\t\tsrc += Width;\r\n\t\t\tdst -= dstPitch;\r\n\t\t} while (src != srcEnd);\r\n\t} else { // Mask == MaskType::Solid || Mask == MaskType::Transparent\r\n\t\tconst uint8_t *srcEnd = src + Width * TrapezoidUpperHeight;\r\n\t\tdo {\r\n\t\t\tRenderLineTransparentOrOpaque<Light, /*Transparent=*/Mask == MaskType::Transparent>(dst, src, Width, tbl, &lightmap);\r\n\t\t\tsrc += Width;\r\n\t\t\tdst -= dstPitch;\r\n\t\t} while (src != srcEnd);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTrapezoidUpperHalfClipVertical(const Clip &clip, const DiamondClipY &clipY, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tconst auto upperMax = TrapezoidUpperHeight - clipY.upperTop;\r\n\tint8_t prefix = InitPrefix<Mask>(clip.bottom);\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch) {\r\n\t\tRenderLine<Light, Mask>(dst, src, Width, tbl, lightmap, prefix);\r\n\t\tsrc += Width;\r\n\t\tprefix += PrefixIncrement<Mask>;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTrapezoidUpperHalfClipLeftAndVertical(const Clip &clip, const DiamondClipY &clipY, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tconst auto upperMax = TrapezoidUpperHeight - clipY.upperTop;\r\n\tint8_t prefix = InitPrefix<Mask>(clip.bottom);\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch) {\r\n\t\tRenderLine<Light, Mask>(dst, src, clip.width, tbl, lightmap, prefix - clip.left);\r\n\t\tsrc += Width;\r\n\t\tprefix += PrefixIncrement<Mask>;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTrapezoidUpperHalfClipRightAndVertical(const Clip &clip, const DiamondClipY &clipY, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tconst auto upperMax = TrapezoidUpperHeight - clipY.upperTop;\r\n\tint8_t prefix = InitPrefix<Mask>(clip.bottom);\r\n\tfor (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch) {\r\n\t\tRenderLine<Light, Mask>(dst, src, clip.width, tbl, lightmap, prefix);\r\n\t\tsrc += Width;\r\n\t\tprefix += PrefixIncrement<Mask>;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoidFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tRenderLeftTriangleLower<Light, /*Transparent=*/Mask == MaskType::Transparent>(dst, dstPitch, src, tbl, &lightmap);\r\n\tdst += XStep;\r\n\tRenderTrapezoidUpperHalf<Light, Mask>(dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoidClipVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY<TrapezoidUpperHeight>(clip);\r\n\tRenderLeftTriangleLowerClipVertical<Light, /*Transparent=*/Mask == MaskType::Transparent>(clipY, dst, dstPitch, src, tbl, &lightmap);\r\n\tsrc += clipY.upperBottom * Width;\r\n\tdst += XStep;\r\n\tRenderTrapezoidUpperHalfClipVertical<Light, Mask>(clip, clipY, dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoidClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY<TrapezoidUpperHeight>(clip);\r\n\tRenderLeftTriangleLowerClipLeftAndVertical<Light, /*Transparent=*/Mask == MaskType::Transparent>(clip.left, clipY, dst, dstPitch, src, tbl, &lightmap);\r\n\tsrc += clipY.upperBottom * Width + clip.left;\r\n\tdst += XStep + clip.left;\r\n\tRenderTrapezoidUpperHalfClipLeftAndVertical<Light, Mask>(clip, clipY, dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoidClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY<TrapezoidUpperHeight>(clip);\r\n\tRenderLeftTriangleLowerClipRightAndVertical<Light, /*Transparent=*/Mask == MaskType::Transparent>(clip.right, clipY, dst, dstPitch, src, tbl, &lightmap);\r\n\tsrc += clipY.upperBottom * Width;\r\n\tdst += XStep;\r\n\tRenderTrapezoidUpperHalfClipRightAndVertical<Light, Mask>(clip, clipY, dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoid(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tif (clip.width == Width) {\r\n\t\tif (clip.height == Height) {\r\n\t\t\tRenderLeftTrapezoidFull<Light, Mask>(dst, dstPitch, src, tbl, lightmap);\r\n\t\t} else {\r\n\t\t\tRenderLeftTrapezoidClipVertical<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\t}\r\n\t} else if (clip.right == 0) {\r\n\t\tRenderLeftTrapezoidClipLeftAndVertical<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else {\r\n\t\tRenderLeftTrapezoidClipRightAndVertical<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoidFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap)\r\n{\r\n\tRenderRightTriangleLower<Light, /*Transparent=*/Mask == MaskType::Transparent>(dst, dstPitch, src, tbl, &lightmap);\r\n\tRenderTrapezoidUpperHalf<Light, Mask>(dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoidClipVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY<TrapezoidUpperHeight>(clip);\r\n\tRenderRightTriangleLowerClipVertical<Light, /*Transparent=*/Mask == MaskType::Transparent>(clipY, dst, dstPitch, src, tbl, &lightmap);\r\n\tsrc += clipY.upperBottom * Width;\r\n\tRenderTrapezoidUpperHalfClipVertical<Light, Mask>(clip, clipY, dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoidClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY<TrapezoidUpperHeight>(clip);\r\n\tRenderRightTriangleLowerClipLeftAndVertical<Light, /*Transparent=*/Mask == MaskType::Transparent>(clip.left, clipY, dst, dstPitch, src, tbl, &lightmap);\r\n\tsrc += clipY.upperBottom * Width + clip.left;\r\n\tRenderTrapezoidUpperHalfClipLeftAndVertical<Light, Mask>(clip, clipY, dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoidClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tconst DiamondClipY clipY = CalculateDiamondClipY<TrapezoidUpperHeight>(clip);\r\n\tRenderRightTriangleLowerClipRightAndVertical<Light, /*Transparent=*/Mask == MaskType::Transparent>(clip.right, clipY, dst, dstPitch, src, tbl, &lightmap);\r\n\tsrc += clipY.upperBottom * Width;\r\n\tRenderTrapezoidUpperHalfClipRightAndVertical<Light, Mask>(clip, clipY, dst, dstPitch, src, tbl, lightmap);\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoid(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tif (clip.width == Width) {\r\n\t\tif (clip.height == Height) {\r\n\t\t\tRenderRightTrapezoidFull<Light, Mask>(dst, dstPitch, src, tbl, lightmap);\r\n\t\t} else {\r\n\t\t\tRenderRightTrapezoidClipVertical<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\t}\r\n\t} else if (clip.right == 0) {\r\n\t\tRenderRightTrapezoidClipLeftAndVertical<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else {\r\n\t\tRenderRightTrapezoidClipRightAndVertical<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTileType(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tswitch (tile) {\r\n\tcase TileType::Square:\r\n\t\tRenderSquare<Light, Transparent>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase TileType::TransparentSquare:\r\n\t\tRenderTransparentSquare<Light, Transparent ? MaskType::Transparent : MaskType::Solid>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase TileType::LeftTriangle:\r\n\t\tRenderLeftTriangle<Light, Transparent>(dst, dstPitch, src, tbl, &lightmap, clip);\r\n\t\tbreak;\r\n\tcase TileType::RightTriangle:\r\n\t\tRenderRightTriangle<Light, Transparent>(dst, dstPitch, src, tbl, &lightmap, clip);\r\n\t\tbreak;\r\n\tcase TileType::LeftTrapezoid:\r\n\t\tRenderLeftTrapezoid<Light, Transparent ? MaskType::Transparent : MaskType::Solid>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase TileType::RightTrapezoid:\r\n\t\tRenderRightTrapezoid<Light, Transparent ? MaskType::Transparent : MaskType::Solid>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoidOrTransparentSquare(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tswitch (tile) {\r\n\tcase TileType::TransparentSquare:\r\n\t\tRenderTransparentSquare<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase TileType::LeftTrapezoid:\r\n\t\tRenderLeftTrapezoid<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"Given mask can only be applied to TransparentSquare or LeftTrapezoid tiles\");\r\n\t}\r\n}\r\n\r\ntemplate <LightType Light, MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoidOrTransparentSquare(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tswitch (tile) {\r\n\tcase TileType::TransparentSquare:\r\n\t\tRenderTransparentSquare<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase TileType::RightTrapezoid:\r\n\t\tRenderRightTrapezoid<Light, Mask>(dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"Given mask can only be applied to TransparentSquare or LeftTrapezoid tiles\");\r\n\t}\r\n}\r\n\r\ntemplate <MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderLeftTrapezoidOrTransparentSquareDispatch(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tif (*GetOptions().Graphics.perPixelLighting) {\r\n\t\tRenderLeftTrapezoidOrTransparentSquare<LightType::PerPixel, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else if (lightmap.isFullyDarkLightTable(tbl)) {\r\n\t\tRenderLeftTrapezoidOrTransparentSquare<LightType::FullyDark, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else if (lightmap.isFullyLitLightTable(tbl)) {\r\n\t\tRenderLeftTrapezoidOrTransparentSquare<LightType::FullyLit, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else {\r\n\t\tRenderLeftTrapezoidOrTransparentSquare<LightType::PartiallyLit, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\ntemplate <MaskType Mask>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoidOrTransparentSquareDispatch(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tif (*GetOptions().Graphics.perPixelLighting) {\r\n\t\tRenderRightTrapezoidOrTransparentSquare<LightType::PerPixel, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else if (lightmap.isFullyDarkLightTable(tbl)) {\r\n\t\tRenderRightTrapezoidOrTransparentSquare<LightType::FullyDark, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else if (lightmap.isFullyLitLightTable(tbl)) {\r\n\t\tRenderRightTrapezoidOrTransparentSquare<LightType::FullyLit, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else {\r\n\t\tRenderRightTrapezoidOrTransparentSquare<LightType::PartiallyLit, Mask>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\ntemplate <bool Transparent>\r\nDVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTileDispatch(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, const Lightmap &lightmap, Clip clip)\r\n{\r\n\tif (*GetOptions().Graphics.perPixelLighting) {\r\n\t\tRenderTileType<LightType::PerPixel, Transparent>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else if (lightmap.isFullyDarkLightTable(tbl)) {\r\n\t\tRenderTileType<LightType::FullyDark, Transparent>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else if (lightmap.isFullyLitLightTable(tbl)) {\r\n\t\tRenderTileType<LightType::FullyLit, Transparent>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t} else {\r\n\t\tRenderTileType<LightType::PartiallyLit, Transparent>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\n#ifdef DUN_RENDER_STATS\r\nankerl::unordered_dense::map<DunRenderType, size_t, DunRenderTypeHash> DunRenderStats;\r\n\r\nstd::string_view TileTypeToString(TileType tileType)\r\n{\r\n\t// clang-format off\r\n\tswitch (tileType) {\r\n\tcase TileType::Square: return \"Square\";\r\n\tcase TileType::TransparentSquare: return \"TransparentSquare\";\r\n\tcase TileType::LeftTriangle: return \"LeftTriangle\";\r\n\tcase TileType::RightTriangle: return \"RightTriangle\";\r\n\tcase TileType::LeftTrapezoid: return \"LeftTrapezoid\";\r\n\tcase TileType::RightTrapezoid: return \"RightTrapezoid\";\r\n\tdefault: return \"???\";\r\n\t}\r\n\t// clang-format on\r\n}\r\n\r\nstd::string_view MaskTypeToString(MaskType maskType)\r\n{\r\n\t// clang-format off\r\n\tswitch (maskType) {\r\n\tcase MaskType::Solid: return \"Solid\";\r\n\tcase MaskType::Transparent: return \"Transparent\";\r\n\tcase MaskType::Right: return \"Right\";\r\n\tcase MaskType::Left: return \"Left\";\r\n\tcase MaskType::RightFoliage: return \"RightFoliage\";\r\n\tcase MaskType::LeftFoliage: return \"LeftFoliage\";\r\n\tdefault: return \"???\";\r\n\t}\r\n\t// clang-format on\r\n}\r\n#endif\r\n\r\nDVL_ATTRIBUTE_HOT void RenderTileFrame(const Surface &out, const Lightmap &lightmap, const Point &position, TileType tile, const uint8_t *src, int_fast16_t height,\r\n    MaskType maskType, const uint8_t *tbl)\r\n{\r\n#ifdef DEBUG_RENDER_OFFSET_X\r\n\tposition.x += DEBUG_RENDER_OFFSET_X;\r\n#endif\r\n#ifdef DEBUG_RENDER_OFFSET_Y\r\n\tposition.y += DEBUG_RENDER_OFFSET_Y;\r\n#endif\r\n\tconst Clip clip = CalculateClip(position.x, position.y, DunFrameWidth, height, out);\r\n\tif (clip.width <= 0 || clip.height <= 0) return;\r\n\r\n\tuint8_t *dst = out.at(static_cast<int>(position.x + clip.left), static_cast<int>(position.y - clip.bottom));\r\n\tconst uint16_t dstPitch = out.pitch();\r\n\r\n#ifdef DUN_RENDER_STATS\r\n\t++DunRenderStats[DunRenderType { tile, maskType }];\r\n#endif\r\n\r\n\tswitch (maskType) {\r\n\tcase MaskType::Solid:\r\n\t\tRenderTileDispatch</*Transparent=*/false>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase MaskType::Transparent:\r\n\t\tRenderTileDispatch</*Transparent=*/true>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase MaskType::Left:\r\n\t\tRenderLeftTrapezoidOrTransparentSquareDispatch<MaskType::Left>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\tcase MaskType::Right:\r\n\t\tRenderRightTrapezoidOrTransparentSquareDispatch<MaskType::Right>(tile, dst, dstPitch, src, tbl, lightmap, clip);\r\n\t\tbreak;\r\n\t}\r\n\r\n#ifdef DEBUG_STR\r\n\tconst auto [debugStr, flags] = GetTileDebugStr(tile);\r\n\tDrawString(out, debugStr, Rectangle { Point { position.x + 2, position.y - 29 }, Size { 28, 28 } }, { .flags = flags });\r\n#endif\r\n}\r\n\r\nvoid world_draw_black_tile(const Surface &out, int sx, int sy)\r\n{\r\n#ifdef DEBUG_RENDER_OFFSET_X\r\n\tsx += DEBUG_RENDER_OFFSET_X;\r\n#endif\r\n#ifdef DEBUG_RENDER_OFFSET_Y\r\n\tsy += DEBUG_RENDER_OFFSET_Y;\r\n#endif\r\n\tconst Clip clipLeft = CalculateClip(sx, sy, Width, TriangleHeight, out);\r\n\tif (clipLeft.height <= 0) return;\r\n\tClip clipRight;\r\n\tclipRight.top = clipLeft.top;\r\n\tclipRight.bottom = clipLeft.bottom;\r\n\tclipRight.left = (sx + Width) < 0 ? -(sx + Width) : 0;\r\n\tclipRight.right = sx + Width + Width > out.w() ? sx + Width + Width - out.w() : 0;\r\n\tclipRight.width = Width - clipRight.left - clipRight.right;\r\n\tclipRight.height = clipLeft.height;\r\n\r\n\tconst uint16_t dstPitch = out.pitch();\r\n\tif (clipLeft.width > 0) {\r\n\t\tuint8_t *dst = out.at(static_cast<int>(sx + clipLeft.left), static_cast<int>(sy - clipLeft.bottom));\r\n\t\tRenderLeftTriangle<LightType::FullyDark, /*Transparent=*/false>(dst, dstPitch, nullptr, nullptr, nullptr, clipLeft);\r\n\t}\r\n\tif (clipRight.width > 0) {\r\n\t\tuint8_t *dst = out.at(static_cast<int>(sx + Width + clipRight.left), static_cast<int>(sy - clipRight.bottom));\r\n\t\tRenderRightTriangle<LightType::FullyDark, /*Transparent=*/false>(dst, dstPitch, nullptr, nullptr, nullptr, clipRight);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/dun_render.hpp",
    "content": "/**\r\n * @file dun_render.hpp\r\n *\r\n * Interface of functionality for rendering the level tiles.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/light_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n\r\n// #define DUN_RENDER_STATS\r\n#ifdef DUN_RENDER_STATS\r\n#include <ankerl/unordered_dense.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Specifies the mask to use for rendering.\r\n */\r\nenum class MaskType : uint8_t {\r\n\t/** @brief The entire tile is opaque. */\r\n\tSolid,\r\n\r\n\t/** @brief The entire tile is blended with transparency. */\r\n\tTransparent,\r\n\r\n\t/**\r\n\t * @brief Upper-right triangle is blended with transparency.\r\n\t *\r\n\t * Can only be used with `TileType::LeftTrapezoid` and\r\n\t * `TileType::TransparentSquare`.\r\n\t *\r\n\t * The lower 16 rows are opaque.\r\n\t * The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = blended):\r\n\t *\r\n\t * 🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t */\r\n\tRight,\r\n\r\n\t/**\r\n\t * @brief Upper-left triangle is blended with transparency.\r\n\t *\r\n\t * Can only be used with `TileType::RightTrapezoid` and\r\n\t * `TileType::TransparentSquare`.\r\n\t *\r\n\t * The lower 16 rows are opaque.\r\n\t * The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = blended):\r\n\t *\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t * 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆\r\n\t */\r\n\tLeft,\r\n};\r\n\r\n#ifdef DUN_RENDER_STATS\r\nstruct DunRenderType {\r\n\tTileType tileType;\r\n\tMaskType maskType;\r\n\tbool operator==(const DunRenderType &other) const\r\n\t{\r\n\t\treturn tileType == other.tileType && maskType == other.maskType;\r\n\t}\r\n};\r\nstruct DunRenderTypeHash {\r\n\tsize_t operator()(DunRenderType t) const noexcept\r\n\t{\r\n\t\treturn std::hash<uint32_t> {}((1 < static_cast<uint8_t>(t.tileType)) | static_cast<uint8_t>(t.maskType));\r\n\t}\r\n};\r\nextern ankerl::unordered_dense::map<DunRenderType, size_t, DunRenderTypeHash> DunRenderStats;\r\n\r\nstd::string_view TileTypeToString(TileType tileType);\r\n\r\nstd::string_view MaskTypeToString(MaskType maskType);\r\n#endif\r\n\r\n/**\r\n * @brief Low-level tile rendering function.\r\n */\r\nvoid RenderTileFrame(const Surface &out, const Lightmap &lightmap, const Point &position, TileType tile, const uint8_t *src, int_fast16_t height,\r\n    MaskType maskType, const uint8_t *tbl);\r\n\r\n/**\r\n * @brief Returns the raw data for the given dungeon frame.\r\n */\r\nDVL_ALWAYS_INLINE const uint8_t *GetDunFrame(const std::byte *dungeonCelData, uint32_t frame)\r\n{\r\n\tconst auto *frameTable = reinterpret_cast<const uint32_t *>(dungeonCelData);\r\n\treturn reinterpret_cast<const uint8_t *>(&dungeonCelData[Swap32LE(frameTable[frame])]);\r\n}\r\n\r\n/**\r\n * @brief Returns the raw data for the given dungeon frame's foliage.\r\n */\r\nDVL_ALWAYS_INLINE const uint8_t *GetDunFrameFoliage(const std::byte *dungeonCelData, uint32_t frame)\r\n{\r\n\treturn GetDunFrame(dungeonCelData, frame) + ReencodedTriangleFrameSize;\r\n}\r\n\r\n/**\r\n * @brief Blit current world CEL to the given buffer\r\n * @param out Target buffer\r\n * @param lightmap Per-pixel light buffer\r\n * @param position Target buffer coordinates\r\n * @param dungeonCelData Dungeon CEL data.\r\n * @param levelCelBlock The MIN block of the level CEL file.\r\n * @param maskType The mask to use,\r\n * @param tbl LightTable or TRN for a tile.\r\n */\r\nDVL_ALWAYS_INLINE void RenderTile(const Surface &out, const Lightmap &lightmap, const Point &position,\r\n    const std::byte *dungeonCelData, LevelCelBlock levelCelBlock, MaskType maskType, const uint8_t *tbl)\r\n{\r\n\tconst TileType tileType = levelCelBlock.type();\r\n\tRenderTileFrame(out, lightmap, position, tileType,\r\n\t    GetDunFrame(dungeonCelData, levelCelBlock.frame()),\r\n\t    (tileType == TileType::LeftTriangle || tileType == TileType::RightTriangle)\r\n\t        ? DunFrameTriangleHeight\r\n\t        : DunFrameHeight,\r\n\t    maskType, tbl);\r\n}\r\n\r\n/**\r\n * @brief Renders a floor foliage tile.\r\n */\r\nDVL_ALWAYS_INLINE void RenderTileFoliage(const Surface &out, const Lightmap &lightmap, const Point &position,\r\n    const std::byte *dungeonCelData, LevelCelBlock levelCelBlock, const uint8_t *tbl)\r\n{\r\n\tRenderTileFrame(out, lightmap, Point { position.x, position.y - 16 }, TileType::TransparentSquare,\r\n\t    GetDunFrameFoliage(dungeonCelData, levelCelBlock.frame()), /*height=*/16, MaskType::Solid, tbl);\r\n}\r\n\r\n/**\r\n * @brief Render a black 64x31 tile ◆\r\n * @param out Target buffer\r\n * @param sx Target buffer coordinate (left corner of the tile)\r\n * @param sy Target buffer coordinate (bottom corner of the tile)\r\n */\r\nvoid world_draw_black_tile(const Surface &out, int sx, int sy);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/light_render.cpp",
    "content": "#include \"engine/render/light_render.hpp\"\r\n\r\n#include <algorithm>\r\n#include <cassert>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <span>\r\n#include <vector>\r\n\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/gendung_defs.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstd::vector<uint8_t> LightmapBuffer;\r\n\r\nvoid RenderFullTile(Point position, uint8_t lightLevel, uint8_t *lightmap, uint16_t pitch)\r\n{\r\n\tuint8_t *top = lightmap + (position.y + 1) * pitch + position.x - TILE_WIDTH / 2;\r\n\tuint8_t *bottom = top + (TILE_HEIGHT - 2) * pitch;\r\n\tfor (int y = 0, w = 4; y < TILE_HEIGHT / 2 - 1; y++, w += 4) {\r\n\t\tconst int x = (TILE_WIDTH - w) / 2;\r\n\t\tmemset(top + x, lightLevel, w);\r\n\t\tmemset(bottom + x, lightLevel, w);\r\n\t\ttop += pitch;\r\n\t\tbottom -= pitch;\r\n\t}\r\n\tmemset(top, lightLevel, TILE_WIDTH);\r\n}\r\n\r\nint DecrementTowardZero(int num)\r\n{\r\n\treturn num > 0 ? num - 1 : num + 1;\r\n}\r\n\r\n// Half-space method for drawing triangles\r\n// Points must be provided using counter-clockwise rotation\r\n// https://web.archive.org/web/20050408192410/http://sw-shader.sourceforge.net/rasterizer.html\r\nvoid RenderTriangle(Point p1, Point p2, Point p3, uint8_t lightLevel, uint8_t *lightmap, uint16_t pitch, uint16_t scanLines)\r\n{\r\n\t// Deltas (points are already 28.4 fixed-point)\r\n\tconst int dx12 = p1.x - p2.x;\r\n\tconst int dx23 = p2.x - p3.x;\r\n\tconst int dx31 = p3.x - p1.x;\r\n\r\n\tconst int dy12 = p1.y - p2.y;\r\n\tconst int dy23 = p2.y - p3.y;\r\n\tconst int dy31 = p3.y - p1.y;\r\n\r\n\t// 24.8 fixed-point deltas\r\n\tconst int fdx12 = dx12 << 4;\r\n\tconst int fdx23 = dx23 << 4;\r\n\tconst int fdx31 = dx31 << 4;\r\n\r\n\tconst int fdy12 = dy12 << 4;\r\n\tconst int fdy23 = dy23 << 4;\r\n\tconst int fdy31 = dy31 << 4;\r\n\r\n\t// Bounding rectangle\r\n\tconst int minx = std::max((std::min({ p1.x, p2.x, p3.x }) + 0xF) >> 4, 0);\r\n\tconst int maxx = std::min<int>((std::max({ p1.x, p2.x, p3.x }) + 0xF) >> 4, pitch);\r\n\tconst int xlen = maxx - minx;\r\n\tif (xlen <= 0) return;\r\n\tconst int miny = std::max((std::min({ p1.y, p2.y, p3.y }) + 0xF) >> 4, 0);\r\n\tconst int maxy = std::min<int>((std::max({ p1.y, p2.y, p3.y }) + 0xF) >> 4, scanLines);\r\n\tif (maxy <= miny) return;\r\n\r\n\tuint8_t *dst = lightmap + static_cast<ptrdiff_t>(miny * pitch);\r\n\r\n\t// Half-edge constants\r\n\tconstexpr auto CalcHalfEdge = [](const Point &p, int dx, int dy) {\r\n\t\treturn (dy * p.x) - (dx * p.y) +\r\n\t\t    // Correct for fill convention\r\n\t\t    (dy < 0 || (dy == 0 && dx > 0) ? 1 : 0);\r\n\t};\r\n\tconst int c1 = CalcHalfEdge(p1, dx12, dy12);\r\n\tconst int c2 = CalcHalfEdge(p2, dx23, dy23);\r\n\tconst int c3 = CalcHalfEdge(p3, dx31, dy31);\r\n\r\n\tconstexpr auto CalcCy = [](int minx, int miny, int dx, int dy) {\r\n\t\treturn (dx * (miny << 4)) - (dy * (minx << 4));\r\n\t};\r\n\r\n\tint cy1 = c1 + CalcCy(minx, miny, dx12, dy12);\r\n\tint cy2 = c2 + CalcCy(minx, miny, dx23, dy23);\r\n\tint cy3 = c3 + CalcCy(minx, miny, dx31, dy31);\r\n\r\n\tfor (int y = miny; y < maxy; y++) {\r\n\t\tconst int cxe1 = cy1 - (fdy12 * xlen);\r\n\t\tconst int cxe2 = cy2 - (fdy23 * xlen);\r\n\t\tconst int cxe3 = cy3 - (fdy31 * xlen);\r\n\r\n\t\tconstexpr auto CalcStartX = [](int xlen, int cx, int cxe, int fdy) -> int {\r\n\t\t\tif (cx > 0) return 0;\r\n\t\t\tif (cxe <= 0) return xlen;\r\n\t\t\treturn (cx + DecrementTowardZero(fdy)) / fdy;\r\n\t\t};\r\n\r\n\t\tconst int startx = minx + std::max({\r\n\t\t                       CalcStartX(xlen, cy1, cxe1, fdy12),\r\n\t\t                       CalcStartX(xlen, cy2, cxe2, fdy23),\r\n\t\t                       CalcStartX(xlen, cy3, cxe3, fdy31),\r\n\t\t                   });\r\n\r\n\t\tconstexpr auto CalcEndX = [](int xlen, int cx, int cxe, int fdy) -> int {\r\n\t\t\tif (cxe > 0) return xlen;\r\n\t\t\tif (cx <= 0) return 0;\r\n\t\t\treturn (cx + DecrementTowardZero(fdy)) / fdy;\r\n\t\t};\r\n\r\n\t\tconst int endx = minx + std::min({\r\n\t\t                     CalcEndX(xlen, cy1, cxe1, fdy12),\r\n\t\t                     CalcEndX(xlen, cy2, cxe2, fdy23),\r\n\t\t                     CalcEndX(xlen, cy3, cxe3, fdy31),\r\n\t\t                 });\r\n\r\n\t\tif (startx < endx)\r\n\t\t\tmemset(&dst[startx], lightLevel, endx - startx);\r\n\r\n\t\tcy1 += fdx12;\r\n\t\tcy2 += fdx23;\r\n\t\tcy3 += fdx31;\r\n\r\n\t\tdst += pitch;\r\n\t}\r\n}\r\n\r\nuint8_t GetLightLevel(const uint8_t tileLights[MAXDUNX][MAXDUNY], Point tile)\r\n{\r\n\tconst int x = std::clamp(tile.x, 0, MAXDUNX - 1);\r\n\tconst int y = std::clamp(tile.y, 0, MAXDUNY - 1);\r\n\treturn tileLights[x][y];\r\n}\r\n\r\nuint8_t Interpolate(int q1, int q2, int lightLevel)\r\n{\r\n\t// Result will be 28.4 fixed-point\r\n\tconst int numerator = (lightLevel - q1) << 4;\r\n\tconst int result = (numerator + 0x8) / (q2 - q1);\r\n\tassert(result >= 0);\r\n\treturn static_cast<uint8_t>(result);\r\n}\r\n\r\nvoid RenderCell(uint8_t quad[4], Point position, uint8_t lightLevel, uint8_t *lightmap, uint16_t pitch, uint16_t scanLines)\r\n{\r\n\tconst Point center0 = position;\r\n\tconst Point center1 = position + Displacement { TILE_WIDTH / 2, TILE_HEIGHT / 2 };\r\n\tconst Point center2 = position + Displacement { 0, TILE_HEIGHT };\r\n\tconst Point center3 = position + Displacement { -TILE_WIDTH / 2, TILE_HEIGHT / 2 };\r\n\r\n\t// 28.4 fixed-point coordinates\r\n\tconst Point fpCenter0 = center0 * (1 << 4);\r\n\tconst Point fpCenter1 = center1 * (1 << 4);\r\n\tconst Point fpCenter2 = center2 * (1 << 4);\r\n\tconst Point fpCenter3 = center3 * (1 << 4);\r\n\r\n\t// Marching squares\r\n\t// https://en.wikipedia.org/wiki/Marching_squares\r\n\tuint8_t shape = 0;\r\n\tshape |= quad[0] <= lightLevel ? 8 : 0;\r\n\tshape |= quad[1] <= lightLevel ? 4 : 0;\r\n\tshape |= quad[2] <= lightLevel ? 2 : 0;\r\n\tshape |= quad[3] <= lightLevel ? 1 : 0;\r\n\r\n\tswitch (shape) {\r\n\t// The whole cell is darker than lightLevel\r\n\tcase 0: break;\r\n\r\n\t// Fill in the bottom-left corner of the cell\r\n\t// In isometric view, only the west tile of the quad is lit\r\n\tcase 1: {\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[3], quad[2], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[3], quad[0], lightLevel);\r\n\t\tconst Point p1 = fpCenter3 + (center2 - center3) * bottomFactor;\r\n\t\tconst Point p2 = fpCenter3;\r\n\t\tconst Point p3 = fpCenter3 + (center0 - center3) * leftFactor;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the bottom-right corner of the cell\r\n\t// In isometric view, only the south tile of the quad is lit\r\n\tcase 2: {\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[2], quad[1], lightLevel);\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[2], quad[3], lightLevel);\r\n\t\tconst Point p1 = fpCenter2 + (center1 - center2) * rightFactor;\r\n\t\tconst Point p2 = fpCenter2;\r\n\t\tconst Point p3 = fpCenter2 + (center3 - center2) * bottomFactor;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the bottom half of the cell\r\n\t// In isometric view, the south and west tiles of the quad are lit\r\n\tcase 3: {\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[2], quad[1], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[3], quad[0], lightLevel);\r\n\t\tconst Point p1 = fpCenter2 + (center1 - center2) * rightFactor;\r\n\t\tconst Point p2 = fpCenter2;\r\n\t\tconst Point p3 = fpCenter3;\r\n\t\tconst Point p4 = fpCenter3 + (center1 - center2) * leftFactor;\r\n\t\tRenderTriangle(p1, p4, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p2, p4, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the top-right corner of the cell\r\n\t// In isometric view, only the east tile of the quad is lit\r\n\tcase 4: {\r\n\t\tconst uint8_t topFactor = Interpolate(quad[1], quad[0], lightLevel);\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[1], quad[2], lightLevel);\r\n\t\tconst Point p1 = fpCenter1 + (center0 - center1) * topFactor;\r\n\t\tconst Point p2 = fpCenter1;\r\n\t\tconst Point p3 = fpCenter1 + (center2 - center1) * rightFactor;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the top-right and bottom-left corners of the cell\r\n\t// Use the average of all values in the quad to determine whether to fill in the center\r\n\t// In isometric view, the east and west tiles of the quad are lit\r\n\tcase 5: {\r\n\t\tconst uint8_t cell = (quad[0] + quad[1] + quad[2] + quad[3] + 2) / 4;\r\n\t\tconst uint8_t topFactor = Interpolate(quad[1], quad[0], lightLevel);\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[1], quad[2], lightLevel);\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[3], quad[2], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[3], quad[0], lightLevel);\r\n\t\tconst Point p1 = fpCenter1 + (center0 - center1) * topFactor;\r\n\t\tconst Point p2 = fpCenter1;\r\n\t\tconst Point p3 = fpCenter1 + (center2 - center1) * rightFactor;\r\n\t\tconst Point p4 = fpCenter3 + (center2 - center3) * bottomFactor;\r\n\t\tconst Point p5 = fpCenter3;\r\n\t\tconst Point p6 = fpCenter3 + (center0 - center3) * leftFactor;\r\n\r\n\t\tif (cell <= lightLevel) {\r\n\t\t\tconst uint8_t midFactor0 = Interpolate(quad[0], cell, lightLevel);\r\n\t\t\tconst uint8_t midFactor2 = Interpolate(quad[2], cell, lightLevel);\r\n\t\t\tconst Point p7 = fpCenter0 + (center2 - center0) / 2 * midFactor0;\r\n\t\t\tconst Point p8 = fpCenter2 + (center0 - center2) / 2 * midFactor2;\r\n\t\t\tRenderTriangle(p1, p7, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p2, p7, p8, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p2, p8, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p4, p8, p5, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p5, p8, p7, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p5, p7, p6, lightLevel, lightmap, pitch, scanLines);\r\n\t\t} else {\r\n\t\t\tconst uint8_t midFactor1 = Interpolate(quad[1], cell, lightLevel);\r\n\t\t\tconst uint8_t midFactor3 = Interpolate(quad[3], cell, lightLevel);\r\n\t\t\tconst Point p7 = fpCenter1 + (center3 - center1) / 2 * midFactor1;\r\n\t\t\tconst Point p8 = fpCenter3 + (center1 - center3) / 2 * midFactor3;\r\n\t\t\tRenderTriangle(p1, p7, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p2, p7, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p4, p8, p5, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p5, p8, p6, lightLevel, lightmap, pitch, scanLines);\r\n\t\t}\r\n\t} break;\r\n\r\n\t// Fill in the right half of the cell\r\n\t// In isometric view, the south and east tiles of the quad are lit\r\n\tcase 6: {\r\n\t\tconst uint8_t topFactor = Interpolate(quad[1], quad[0], lightLevel);\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[2], quad[3], lightLevel);\r\n\t\tconst Point p1 = fpCenter1 + (center0 - center1) * topFactor;\r\n\t\tconst Point p2 = fpCenter1;\r\n\t\tconst Point p3 = fpCenter2;\r\n\t\tconst Point p4 = fpCenter2 + (center3 - center2) * bottomFactor;\r\n\t\tRenderTriangle(p1, p4, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p2, p4, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in everything except the top-left corner of the cell\r\n\t// In isometric view, the south, east, and west tiles of the quad are lit\r\n\tcase 7: {\r\n\t\tconst uint8_t topFactor = Interpolate(quad[1], quad[0], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[3], quad[0], lightLevel);\r\n\t\tconst Point p1 = fpCenter1 + (center0 - center1) * topFactor;\r\n\t\tconst Point p2 = fpCenter1;\r\n\t\tconst Point p3 = fpCenter2;\r\n\t\tconst Point p4 = fpCenter3;\r\n\t\tconst Point p5 = fpCenter3 + (center0 - center3) * leftFactor;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p1, p5, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p3, p5, p4, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the top-left corner of the cell\r\n\t// In isometric view, only the north tile of the quad is lit\r\n\tcase 8: {\r\n\t\tconst uint8_t topFactor = Interpolate(quad[0], quad[1], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[0], quad[3], lightLevel);\r\n\t\tconst Point p1 = fpCenter0;\r\n\t\tconst Point p2 = fpCenter0 + (center1 - center0) * topFactor;\r\n\t\tconst Point p3 = fpCenter0 + (center3 - center0) * leftFactor;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the left half of the cell\r\n\t// In isometric view, the north and west tiles of the quad are lit\r\n\tcase 9: {\r\n\t\tconst uint8_t topFactor = Interpolate(quad[0], quad[1], lightLevel);\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[3], quad[2], lightLevel);\r\n\t\tconst Point p1 = fpCenter0;\r\n\t\tconst Point p2 = fpCenter0 + (center1 - center0) * topFactor;\r\n\t\tconst Point p3 = fpCenter3 + (center2 - center3) * bottomFactor;\r\n\t\tconst Point p4 = fpCenter3;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p1, p4, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the top-left and bottom-right corners of the cell\r\n\t// Use the average of all values in the quad to determine whether to fill in the center\r\n\t// In isometric view, the north and south tiles of the quad are lit\r\n\tcase 10: {\r\n\t\tconst uint8_t cell = (quad[0] + quad[1] + quad[2] + quad[3] + 2) / 4;\r\n\t\tconst uint8_t topFactor = Interpolate(quad[0], quad[1], lightLevel);\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[2], quad[1], lightLevel);\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[2], quad[3], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[0], quad[3], lightLevel);\r\n\t\tconst Point p1 = fpCenter0;\r\n\t\tconst Point p2 = fpCenter0 + (center1 - center0) * topFactor;\r\n\t\tconst Point p3 = fpCenter2 + (center1 - center2) * rightFactor;\r\n\t\tconst Point p4 = fpCenter2;\r\n\t\tconst Point p5 = fpCenter2 + (center3 - center2) * bottomFactor;\r\n\t\tconst Point p6 = fpCenter0 + (center3 - center0) * leftFactor;\r\n\r\n\t\tif (cell <= lightLevel) {\r\n\t\t\tconst uint8_t midFactor1 = Interpolate(quad[1], cell, lightLevel);\r\n\t\t\tconst uint8_t midFactor3 = Interpolate(quad[3], cell, lightLevel);\r\n\t\t\tconst Point p7 = fpCenter1 + (center3 - center1) / 2 * midFactor1;\r\n\t\t\tconst Point p8 = fpCenter3 + (center1 - center3) / 2 * midFactor3;\r\n\t\t\tRenderTriangle(p1, p7, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p1, p6, p8, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p1, p8, p7, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p3, p7, p4, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p4, p8, p5, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p4, p7, p8, lightLevel, lightmap, pitch, scanLines);\r\n\t\t} else {\r\n\t\t\tconst uint8_t midFactor0 = Interpolate(quad[0], cell, lightLevel);\r\n\t\t\tconst uint8_t midFactor2 = Interpolate(quad[2], cell, lightLevel);\r\n\t\t\tconst Point p7 = fpCenter0 + (center2 - center0) / 2 * midFactor0;\r\n\t\t\tconst Point p8 = fpCenter2 + (center0 - center2) / 2 * midFactor2;\r\n\t\t\tRenderTriangle(p1, p7, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p1, p6, p7, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p3, p8, p4, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(p4, p8, p5, lightLevel, lightmap, pitch, scanLines);\r\n\t\t}\r\n\t} break;\r\n\r\n\t// Fill in everything except the top-right corner of the cell\r\n\t// In isometric view, the north, south, and west tiles of the quad are lit\r\n\tcase 11: {\r\n\t\tconst uint8_t topFactor = Interpolate(quad[0], quad[1], lightLevel);\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[2], quad[1], lightLevel);\r\n\t\tconst Point p1 = fpCenter0;\r\n\t\tconst Point p2 = fpCenter0 + (center1 - center0) * topFactor;\r\n\t\tconst Point p3 = fpCenter2 + (center1 - center2) * rightFactor;\r\n\t\tconst Point p4 = fpCenter2;\r\n\t\tconst Point p5 = fpCenter3;\r\n\t\tRenderTriangle(p1, p5, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p2, p5, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p3, p5, p4, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the top half of the cell\r\n\t// In isometric view, the north and east tiles of the quad are lit\r\n\tcase 12: {\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[1], quad[2], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[0], quad[3], lightLevel);\r\n\t\tconst Point p1 = fpCenter0;\r\n\t\tconst Point p2 = fpCenter1;\r\n\t\tconst Point p3 = fpCenter1 + (center2 - center1) * rightFactor;\r\n\t\tconst Point p4 = fpCenter0 + (center3 - center0) * leftFactor;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p1, p4, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in everything except the bottom-right corner of the cell\r\n\t// In isometric view, the north, east, and west tiles of the quad are lit\r\n\tcase 13: {\r\n\t\tconst uint8_t rightFactor = Interpolate(quad[1], quad[2], lightLevel);\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[3], quad[2], lightLevel);\r\n\t\tconst Point p1 = fpCenter0;\r\n\t\tconst Point p2 = fpCenter1;\r\n\t\tconst Point p3 = fpCenter1 + (center2 - center1) * rightFactor;\r\n\t\tconst Point p4 = fpCenter3 + (center2 - center3) * bottomFactor;\r\n\t\tconst Point p5 = fpCenter3;\r\n\t\tRenderTriangle(p1, p3, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p1, p4, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p1, p5, p4, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in everything except the bottom-left corner of the cell\r\n\t// In isometric view, the north, south, and east tiles of the quad are lit\r\n\tcase 14: {\r\n\t\tconst uint8_t bottomFactor = Interpolate(quad[2], quad[3], lightLevel);\r\n\t\tconst uint8_t leftFactor = Interpolate(quad[0], quad[3], lightLevel);\r\n\t\tconst Point p1 = fpCenter0;\r\n\t\tconst Point p2 = fpCenter1;\r\n\t\tconst Point p3 = fpCenter2;\r\n\t\tconst Point p4 = fpCenter2 + (center3 - center2) * bottomFactor;\r\n\t\tconst Point p5 = fpCenter0 + (center3 - center0) * leftFactor;\r\n\t\tRenderTriangle(p1, p5, p2, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p2, p5, p4, lightLevel, lightmap, pitch, scanLines);\r\n\t\tRenderTriangle(p2, p4, p3, lightLevel, lightmap, pitch, scanLines);\r\n\t} break;\r\n\r\n\t// Fill in the whole cell\r\n\t// All four tiles in the quad are lit\r\n\tcase 15: {\r\n\t\tif (center3.x < 0 || center1.x >= pitch || center0.y < 0 || center2.y >= scanLines) {\r\n\t\t\tRenderTriangle(fpCenter0, fpCenter2, fpCenter1, lightLevel, lightmap, pitch, scanLines);\r\n\t\t\tRenderTriangle(fpCenter0, fpCenter3, fpCenter2, lightLevel, lightmap, pitch, scanLines);\r\n\t\t} else {\r\n\t\t\t// Optimized rendering path if full tile is visible\r\n\t\t\tRenderFullTile(center0, lightLevel, lightmap, pitch);\r\n\t\t}\r\n\t} break;\r\n\t}\r\n}\r\n\r\nvoid BuildLightmap(Point tilePosition, Point targetBufferPosition, uint16_t viewportWidth, uint16_t viewportHeight,\r\n    int rows, int columns, const uint8_t tileLights[MAXDUNX][MAXDUNY], uint_fast8_t microTileLen)\r\n{\r\n\t// Since light may need to bleed up to the top of wall tiles,\r\n\t// expand the buffer space to include the full base diamond of the tallest tile graphics\r\n\tconst uint16_t bufferHeight = viewportHeight + TILE_HEIGHT * (microTileLen / 2 + 1);\r\n\trows += microTileLen + 2;\r\n\r\n\tconst size_t totalPixels = static_cast<size_t>(viewportWidth) * bufferHeight;\r\n\tLightmapBuffer.resize(totalPixels);\r\n\r\n\t// Since rendering occurs in cells between quads,\r\n\t// expand the rendering space to include tiles outside the viewport\r\n\ttilePosition += Displacement(Direction::NorthWest) * 2;\r\n\ttargetBufferPosition -= Displacement { TILE_WIDTH, TILE_HEIGHT };\r\n\trows += 3;\r\n\tcolumns++;\r\n\r\n\tuint8_t *lightmap = LightmapBuffer.data();\r\n\tmemset(lightmap, LightsMax, totalPixels);\r\n\tfor (int i = 0; i < rows; i++) {\r\n\t\tfor (int j = 0; j < columns; j++, tilePosition += Direction::East, targetBufferPosition.x += TILE_WIDTH) {\r\n\t\t\tconst Point center0 = targetBufferPosition + Displacement { TILE_WIDTH / 2, -TILE_HEIGHT / 2 };\r\n\r\n\t\t\tconst Point tile0 = tilePosition;\r\n\t\t\tconst Point tile1 = tilePosition + Displacement { 1, 0 };\r\n\t\t\tconst Point tile2 = tilePosition + Displacement { 1, 1 };\r\n\t\t\tconst Point tile3 = tilePosition + Displacement { 0, 1 };\r\n\r\n\t\t\tuint8_t quad[] = {\r\n\t\t\t\tGetLightLevel(tileLights, tile0),\r\n\t\t\t\tGetLightLevel(tileLights, tile1),\r\n\t\t\t\tGetLightLevel(tileLights, tile2),\r\n\t\t\t\tGetLightLevel(tileLights, tile3)\r\n\t\t\t};\r\n\r\n\t\t\tconst uint8_t maxLight = std::max({ quad[0], quad[1], quad[2], quad[3] });\r\n\t\t\tconst uint8_t minLight = std::min({ quad[0], quad[1], quad[2], quad[3] });\r\n\r\n\t\t\tfor (uint8_t i = 0; i < LightsMax; i++) {\r\n\t\t\t\tconst uint8_t lightLevel = LightsMax - i - 1;\r\n\t\t\t\tif (lightLevel > maxLight)\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (lightLevel < minLight)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tRenderCell(quad, center0, lightLevel, lightmap, viewportWidth, bufferHeight);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Return to start of row\r\n\t\ttilePosition += Displacement(Direction::West) * columns;\r\n\t\ttargetBufferPosition.x -= columns * TILE_WIDTH;\r\n\r\n\t\t// Jump to next row\r\n\t\ttargetBufferPosition.y += TILE_HEIGHT / 2;\r\n\t\tif ((i & 1) != 0) {\r\n\t\t\ttilePosition.x++;\r\n\t\t\tcolumns--;\r\n\t\t\ttargetBufferPosition.x += TILE_WIDTH / 2;\r\n\t\t} else {\r\n\t\t\ttilePosition.y++;\r\n\t\t\tcolumns++;\r\n\t\t\ttargetBufferPosition.x -= TILE_WIDTH / 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nLightmap::Lightmap(const uint8_t *outBuffer, uint16_t outPitch,\r\n    std::span<const uint8_t> lightmapBuffer, uint16_t lightmapPitch,\r\n    std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables,\r\n    const uint8_t *fullyLitLightTable, const uint8_t *fullyDarkLightTable)\r\n    : outBuffer(outBuffer)\r\n    , outPitch(outPitch)\r\n    , lightmapBuffer(lightmapBuffer)\r\n    , lightmapPitch(lightmapPitch)\r\n    , lightTables(lightTables)\r\n    , fullyLitLightTable_(fullyLitLightTable)\r\n    , fullyDarkLightTable_(fullyDarkLightTable)\r\n{\r\n}\r\n\r\nLightmap Lightmap::build(bool perPixelLighting, Point tilePosition, Point targetBufferPosition,\r\n    int viewportWidth, int viewportHeight, int rows, int columns,\r\n    const uint8_t *outBuffer, uint16_t outPitch,\r\n    std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables,\r\n    const uint8_t *fullyLitLightTable, const uint8_t *fullyDarkLightTable,\r\n    const uint8_t tileLights[MAXDUNX][MAXDUNY],\r\n    uint_fast8_t microTileLen)\r\n{\r\n\tif (perPixelLighting) {\r\n\t\tBuildLightmap(tilePosition, targetBufferPosition, viewportWidth, viewportHeight, rows, columns, tileLights, microTileLen);\r\n\t}\r\n\treturn Lightmap(outBuffer, outPitch, LightmapBuffer, viewportWidth, lightTables, fullyLitLightTable, fullyDarkLightTable);\r\n}\r\n\r\nLightmap Lightmap::bleedUp(bool perPixelLighting, const Lightmap &source, Point targetBufferPosition, std::span<uint8_t> lightmapBuffer)\r\n{\r\n\tassert(lightmapBuffer.size() >= TILE_WIDTH * TILE_HEIGHT);\r\n\r\n\tif (!perPixelLighting) return source;\r\n\r\n\tconst int sourceHeight = static_cast<int>(source.lightmapBuffer.size() / source.lightmapPitch);\r\n\tconst int clipLeft = std::max(0, -targetBufferPosition.x);\r\n\tconst int clipTop = std::max(0, -(targetBufferPosition.y - TILE_HEIGHT + 1));\r\n\tconst int clipRight = std::max(0, targetBufferPosition.x + TILE_WIDTH - source.lightmapPitch);\r\n\tconst int clipBottom = std::max(0, targetBufferPosition.y - sourceHeight + 1);\r\n\r\n\t// Nothing we can do if the tile is completely outside the bounds of the lightmap\r\n\tif (clipLeft + clipRight >= TILE_WIDTH)\r\n\t\treturn source;\r\n\tif (clipTop + clipBottom >= TILE_HEIGHT)\r\n\t\treturn source;\r\n\r\n\tconst uint16_t lightmapPitch = std::max(0, TILE_WIDTH - clipLeft - clipRight);\r\n\tconst uint16_t lightmapHeight = TILE_HEIGHT - clipTop - clipBottom;\r\n\r\n\t// Find the left edge of the last row in the tile\r\n\tconst int outOffset = std::max(0, (targetBufferPosition.y - clipBottom) * source.outPitch + targetBufferPosition.x + clipLeft);\r\n\tconst uint8_t *outLoc = source.outBuffer + outOffset;\r\n\tconst uint8_t *outBuffer = outLoc - (lightmapHeight - 1) * source.outPitch;\r\n\r\n\t// Start copying bytes from the bottom row of the tile\r\n\tconst uint8_t *src = source.getLightingAt(outLoc);\r\n\tuint8_t *dst = lightmapBuffer.data() + (lightmapHeight - 1) * lightmapPitch;\r\n\r\n\tint rowCount = clipBottom;\r\n\twhile (src >= source.lightmapBuffer.data() && dst >= lightmapBuffer.data()) {\r\n\t\tconst int bleed = std::max(0, (rowCount - TILE_HEIGHT / 2) * 2);\r\n\t\tconst int lightOffset = std::max(bleed, clipLeft) - clipLeft;\r\n\t\tconst int lightLength = std::max(0, TILE_WIDTH - clipLeft - std::max(bleed, clipRight) - lightOffset);\r\n\r\n\t\t// Bleed pixels up by copying data from the row below this one\r\n\t\tif (rowCount > clipBottom && lightLength < lightmapPitch)\r\n\t\t\tmemcpy(dst, dst + lightmapPitch, lightmapPitch);\r\n\r\n\t\t// Copy data from the source lightmap between the top edge of the base diamond\r\n\t\tassert(dst + lightOffset + lightLength <= lightmapBuffer.data() + TILE_WIDTH * TILE_HEIGHT);\r\n\t\tassert(src + lightOffset + lightLength <= source.lightmapBuffer.data() + source.lightmapBuffer.size());\r\n\t\tmemcpy(dst + lightOffset, src + lightOffset, lightLength);\r\n\r\n\t\tsrc -= source.lightmapPitch;\r\n\t\tdst -= lightmapPitch;\r\n\t\trowCount++;\r\n\t}\r\n\r\n\treturn Lightmap(outBuffer, source.outPitch,\r\n\t    lightmapBuffer, lightmapPitch,\r\n\t    source.lightTables, source.fullyLitLightTable_, source.fullyDarkLightTable_);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/light_render.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <span>\r\n\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"levels/gendung_defs.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nclass Lightmap {\r\npublic:\r\n\texplicit Lightmap(const uint8_t *outBuffer, std::span<const uint8_t> lightmapBuffer, uint16_t pitch,\r\n\t    std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables,\r\n\t    const uint8_t *fullyLitLightTable, const uint8_t *fullyDarkLightTable)\r\n\t    : Lightmap(outBuffer, pitch, lightmapBuffer, pitch, lightTables, fullyLitLightTable, fullyDarkLightTable)\r\n\t{\r\n\t}\r\n\r\n\texplicit Lightmap(const uint8_t *outBuffer, uint16_t outPitch,\r\n\t    std::span<const uint8_t> lightmapBuffer, uint16_t lightmapPitch,\r\n\t    std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables,\r\n\t    const uint8_t *fullyLitLightTable, const uint8_t *fullyDarkLightTable);\r\n\r\n\t[[nodiscard]] uint8_t adjustColor(uint8_t color, uint8_t lightLevel) const\r\n\t{\r\n\t\treturn lightTables[lightLevel][color];\r\n\t}\r\n\r\n\tconst uint8_t *getLightingAt(const uint8_t *outLoc) const\r\n\t{\r\n\t\tconst ptrdiff_t outDist = outLoc - outBuffer;\r\n\t\tconst ptrdiff_t rowOffset = outDist % outPitch;\r\n\r\n\t\tif (outDist < 0) {\r\n\t\t\t// In order to support \"bleed up\" for wall tiles,\r\n\t\t\t// reuse the first row whenever outLoc is out of bounds\r\n\t\t\tconst int modOffset = rowOffset < 0 ? outPitch : 0;\r\n\t\t\treturn lightmapBuffer.data() + rowOffset + modOffset;\r\n\t\t}\r\n\r\n\t\tconst ptrdiff_t row = outDist / outPitch;\r\n\t\treturn lightmapBuffer.data() + row * lightmapPitch + rowOffset;\r\n\t}\r\n\r\n\t[[nodiscard]] bool isFullyLitLightTable(const uint8_t *lightTable) const { return lightTable == fullyLitLightTable_; }\r\n\t[[nodiscard]] bool isFullyDarkLightTable(const uint8_t *lightTable) const { return lightTable == fullyDarkLightTable_; }\r\n\r\n\tstatic Lightmap build(bool perPixelLighting, Point tilePosition, Point targetBufferPosition,\r\n\t    int viewportWidth, int viewportHeight, int rows, int columns,\r\n\t    const uint8_t *outBuffer, uint16_t outPitch,\r\n\t    std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables,\r\n\t    const uint8_t *fullyLitLightTable, const uint8_t *fullyDarkLightTable,\r\n\t    const uint8_t tileLights[MAXDUNX][MAXDUNY],\r\n\t    uint_fast8_t microTileLen);\r\n\r\n\tstatic Lightmap bleedUp(bool perPixelLighting, const Lightmap &source, Point targetBufferPosition, std::span<uint8_t> lightmapBuffer);\r\n\r\nprivate:\r\n\tconst uint8_t *outBuffer;\r\n\tconst uint16_t outPitch;\r\n\r\n\tstd::span<const uint8_t> lightmapBuffer;\r\n\tconst uint16_t lightmapPitch;\r\n\r\n\tstd::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables;\r\n\tconst uint8_t *fullyLitLightTable_;\r\n\tconst uint8_t *fullyDarkLightTable_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/primitive_render.cpp",
    "content": "#include \"engine/render/primitive_render.hpp\"\r\n\r\n#include <cassert>\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/palette_blending.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nvoid DrawHalfTransparentUnalignedBlendedRectTo(const Surface &out, unsigned sx, unsigned sy, unsigned width, unsigned height, uint8_t color)\r\n{\r\n\tuint8_t *pix = out.at(static_cast<int>(sx), static_cast<int>(sy));\r\n\tconst uint8_t *const lookupTable = paletteTransparencyLookup[color];\r\n\tconst unsigned skipX = out.pitch() - width;\r\n\tfor (unsigned y = 0; y < height; ++y) {\r\n\t\tfor (unsigned x = 0; x < width; ++x, ++pix) {\r\n\t\t\t*pix = lookupTable[*pix];\r\n\t\t}\r\n\t\tpix += skipX;\r\n\t}\r\n}\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n// Expects everything to be 4-byte aligned.\r\nvoid DrawHalfTransparentAligned32BlendedRectTo(const Surface &out, unsigned sx, unsigned sy, unsigned width, unsigned height)\r\n{\r\n\tassert(out.pitch() % 4 == 0);\r\n\r\n\tauto *pix = reinterpret_cast<uint32_t *>(out.at(static_cast<int>(sx), static_cast<int>(sy)));\r\n\tassert(reinterpret_cast<intptr_t>(pix) % 4 == 0);\r\n\r\n\tconst uint16_t *lookupTable = paletteTransparencyLookupBlack16;\r\n\r\n\tconst unsigned skipX = (out.pitch() - width) / 4;\r\n\twidth /= 4;\r\n\twhile (height-- > 0) {\r\n\t\tfor (unsigned i = 0; i < width; ++i, ++pix) {\r\n\t\t\tconst uint32_t v = *pix;\r\n\t\t\t*pix = lookupTable[v & 0xFFFF] | (lookupTable[(v >> 16) & 0xFFFF] << 16);\r\n\t\t}\r\n\t\tpix += skipX;\r\n\t}\r\n}\r\n\r\nvoid DrawHalfTransparentBlendedRectTo(const Surface &out, unsigned sx, unsigned sy, unsigned width, unsigned height)\r\n{\r\n\t// All SDL surfaces are 4-byte aligned and divisible by 4.\r\n\t// However, our coordinates and widths may not be.\r\n\r\n\t// First, draw the leading unaligned part.\r\n\tif (sx % 4 != 0) {\r\n\t\tconst unsigned w = 4 - sx % 4;\r\n\t\tDrawHalfTransparentUnalignedBlendedRectTo(out, sx, sy, w, height, 0);\r\n\t\tsx += w;\r\n\t\twidth -= w;\r\n\t}\r\n\r\n\tif (static_cast<int>(sx + width) == out.w()) {\r\n\t\t// The pitch is 4-byte aligned, so we can simply extend the width to the pitch.\r\n\t\twidth = out.pitch() - sx;\r\n\t} else if (width % 4 != 0) {\r\n\t\t// Draw the trailing unaligned part.\r\n\t\tconst unsigned w = width % 4;\r\n\t\tDrawHalfTransparentUnalignedBlendedRectTo(out, sx + (width / 4) * 4, sy, w, height, 0);\r\n\t\twidth -= w;\r\n\t}\r\n\r\n\t// Now everything is divisible by 4. Draw the aligned part.\r\n\tDrawHalfTransparentAligned32BlendedRectTo(out, sx, sy, width, height);\r\n}\r\n#else\r\n#define DrawHalfTransparentBlendedRectTo DrawHalfTransparentUnalignedBlendedRectTo\r\n#endif\r\n\r\n} // namespace\r\n\r\nvoid FillRect(const Surface &out, int x, int y, int width, int height, uint8_t colorIndex)\r\n{\r\n\tfor (int j = 0; j < height; j++) {\r\n\t\tDrawHorizontalLine(out, { x, y + j }, width, colorIndex);\r\n\t}\r\n}\r\n\r\nvoid DrawHorizontalLine(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\tif (from.y < 0 || from.y >= out.h() || from.x >= out.w() || width <= 0 || from.x + width <= 0)\r\n\t\treturn;\r\n\tif (from.x < 0) {\r\n\t\twidth += from.x;\r\n\t\tfrom.x = 0;\r\n\t}\r\n\tif (from.x + width > out.w())\r\n\t\twidth = out.w() - from.x;\r\n\treturn UnsafeDrawHorizontalLine(out, from, width, colorIndex);\r\n}\r\n\r\nvoid UnsafeDrawHorizontalLine(const Surface &out, Point from, int width, std::uint8_t colorIndex)\r\n{\r\n\tstd::memset(&out[from], colorIndex, width);\r\n}\r\n\r\nvoid DrawVerticalLine(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\tif (from.x < 0 || from.x >= out.w() || from.y >= out.h() || height <= 0 || from.y + height <= 0)\r\n\t\treturn;\r\n\tif (from.y < 0) {\r\n\t\theight += from.y;\r\n\t\tfrom.y = 0;\r\n\t}\r\n\tif (from.y + height > out.h())\r\n\t\theight = (from.y + height) - out.h();\r\n\treturn UnsafeDrawVerticalLine(out, from, height, colorIndex);\r\n}\r\n\r\nvoid UnsafeDrawVerticalLine(const Surface &out, Point from, int height, std::uint8_t colorIndex)\r\n{\r\n\tauto *dst = &out[from];\r\n\tconst auto pitch = out.pitch();\r\n\twhile (height-- > 0) {\r\n\t\t*dst = colorIndex;\r\n\t\tdst += pitch;\r\n\t}\r\n}\r\n\r\nvoid DrawHalfTransparentHorizontalLine(const Surface &out, Point from, int width, uint8_t colorIndex)\r\n{\r\n\t// completely off-bounds?\r\n\tif (from.y < 0 || from.y >= out.h() || width <= 0 || from.x >= out.w() || from.x + width <= 0)\r\n\t\treturn;\r\n\r\n\tconst int x0 = std::max(0, from.x);\r\n\tconst int x1 = std::min(out.w(), from.x + width);\r\n\r\n\tfor (int x = x0; x < x1; ++x) {\r\n\t\tSetHalfTransparentPixel(out, { x, from.y }, colorIndex);\r\n\t}\r\n}\r\n\r\n// Draw a half-transparent vertical line of `height` pixels starting at `from`.\r\nvoid DrawHalfTransparentVerticalLine(const Surface &out, Point from, int height, uint8_t colorIndex)\r\n{\r\n\t// completely off-bounds?\r\n\tif (from.x < 0 || from.x >= out.w() || height <= 0 || from.y >= out.h() || from.y + height <= 0)\r\n\t\treturn;\r\n\r\n\tconst int y0 = std::max(0, from.y);\r\n\tconst int y1 = std::min(out.h(), from.y + height);\r\n\r\n\tfor (int y = y0; y < y1; ++y) {\r\n\t\tSetHalfTransparentPixel(out, { from.x, y }, colorIndex);\r\n\t}\r\n}\r\n\r\nvoid DrawHalfTransparentRectTo(const Surface &out, int sx, int sy, int width, int height)\r\n{\r\n\tif (sx + width < 0)\r\n\t\treturn;\r\n\tif (sy + height < 0)\r\n\t\treturn;\r\n\tif (sx >= out.w())\r\n\t\treturn;\r\n\tif (sy >= out.h())\r\n\t\treturn;\r\n\r\n\tif (sx < 0) {\r\n\t\twidth += sx;\r\n\t\tsx = 0;\r\n\t} else if (sx + width >= out.w()) {\r\n\t\twidth = out.w() - sx;\r\n\t}\r\n\r\n\tif (sy < 0) {\r\n\t\theight += sy;\r\n\t\tsy = 0;\r\n\t} else if (sy + height >= out.h()) {\r\n\t\theight = out.h() - sy;\r\n\t}\r\n\r\n\tDrawHalfTransparentBlendedRectTo(out, sx, sy, width, height);\r\n}\r\n\r\nvoid DrawHalfTransparentRectTo(const Surface &out, int sx, int sy, int width, int height, uint8_t color)\r\n{\r\n\tif (sx + width < 0)\r\n\t\treturn;\r\n\tif (sy + height < 0)\r\n\t\treturn;\r\n\tif (sx >= out.w())\r\n\t\treturn;\r\n\tif (sy >= out.h())\r\n\t\treturn;\r\n\r\n\tif (sx < 0) {\r\n\t\twidth += sx;\r\n\t\tsx = 0;\r\n\t} else if (sx + width >= out.w()) {\r\n\t\twidth = out.w() - sx;\r\n\t}\r\n\r\n\tif (sy < 0) {\r\n\t\theight += sy;\r\n\t\tsy = 0;\r\n\t} else if (sy + height >= out.h()) {\r\n\t\theight = out.h() - sy;\r\n\t}\r\n\r\n\tDrawHalfTransparentUnalignedBlendedRectTo(out, sx, sy, width, height, color);\r\n}\r\n\r\nvoid SetHalfTransparentPixel(const Surface &out, Point position, uint8_t color)\r\n{\r\n\tif (out.InBounds(position)) {\r\n\t\tuint8_t *pix = out.at(position.x, position.y);\r\n\t\tconst auto &lookupTable = paletteTransparencyLookup[color];\r\n\t\t*pix = lookupTable[*pix];\r\n\t}\r\n}\r\n\r\nvoid UnsafeDrawBorder2px(const Surface &out, Rectangle rect, uint8_t color)\r\n{\r\n\tconst size_t width = rect.size.width;\r\n\tconst size_t height = rect.size.height;\r\n\tuint8_t *buf = &out[rect.position];\r\n\tstd::memset(buf, color, width);\r\n\tbuf += out.pitch();\r\n\tstd::memset(buf, color, width);\r\n\tbuf += out.pitch();\r\n\tfor (size_t i = 4; i < height; ++i) {\r\n\t\tbuf[0] = buf[1] = color;\r\n\t\tbuf[width - 2] = buf[width - 1] = color;\r\n\t\tbuf += out.pitch();\r\n\t}\r\n\tstd::memset(buf, color, width);\r\n\tbuf += out.pitch();\r\n\tstd::memset(buf, color, width);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/primitive_render.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <cstdlib>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Fill a rectangle with the given color.\r\n */\r\nvoid FillRect(const Surface &out, int x, int y, int width, int height, uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a horizontal line segment in the target buffer (left to right)\r\n * @param out Target buffer\r\n * @param from Start of the line segment\r\n * @param width\r\n * @param colorIndex Color index from current palette\r\n */\r\nvoid DrawHorizontalLine(const Surface &out, Point from, int width, std::uint8_t colorIndex);\r\n\r\n/** Same as DrawHorizontalLine but without bounds clipping. */\r\nvoid UnsafeDrawHorizontalLine(const Surface &out, Point from, int width, std::uint8_t colorIndex);\r\n\r\n/**\r\n * @brief Draw a vertical line segment in the target buffer (top to bottom)\r\n * @param out Target buffer\r\n * @param from Start of the line segment\r\n * @param height\r\n * @param colorIndex Color index from current palette\r\n */\r\nvoid DrawVerticalLine(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\n\r\n/** Same as DrawVerticalLine but without bounds clipping. */\r\nvoid UnsafeDrawVerticalLine(const Surface &out, Point from, int height, std::uint8_t colorIndex);\r\n\r\nvoid DrawHalfTransparentHorizontalLine(const Surface &out, Point from, int width, uint8_t colorIndex);\r\nvoid DrawHalfTransparentVerticalLine(const Surface &out, Point from, int width, uint8_t colorIndex);\r\n\r\n/**\r\n * Draws a half-transparent rectangle by palette blending with black.\r\n *\r\n * @brief Render a transparent black rectangle\r\n * @param out Target buffer\r\n * @param sx Screen coordinate\r\n * @param sy Screen coordinate\r\n * @param width Rectangle width\r\n * @param height Rectangle height\r\n */\r\nvoid DrawHalfTransparentRectTo(const Surface &out, int sx, int sy, int width, int height);\r\n\r\nvoid DrawHalfTransparentRectTo(const Surface &out, int sx, int sy, int width, int height, uint8_t color);\r\n\r\n/**\r\n * Draws a half-transparent pixel\r\n *\r\n * @brief Render a transparent pixel\r\n * @param out Target buffer\r\n * @param position Screen coordinates\r\n * @param col Pixel color\r\n */\r\nvoid SetHalfTransparentPixel(const Surface &out, Point position, uint8_t color);\r\n\r\n/**\r\n * Draws a 2px inset border.\r\n *\r\n * @param out Target buffer\r\n * @param rect The rectangle that border pixels are rendered inside of.\r\n * @param color Border color.\r\n */\r\nvoid UnsafeDrawBorder2px(const Surface &out, Rectangle rect, uint8_t color);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/scrollrt.cpp",
    "content": "/**\r\n * @file scrollrt.cpp\r\n *\r\n * Implementation of functionality for rendering the dungeons, monsters and calling other render routines.\r\n */\r\n#include \"engine/render/scrollrt.h\"\r\n\r\n#include <cmath>\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"automap.h\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"dead.h\"\r\n#include \"diablo_msg.hpp\"\r\n#include \"doom.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/dun_render.hpp\"\r\n#include \"engine/render/light_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/trn.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"gmenu.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"help.h\"\r\n#include \"hwcursor.hpp\"\r\n#include \"init.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"lighting.h\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"minitext.h\"\r\n#include \"missiles.h\"\r\n#include \"nthread.h\"\r\n#include \"options.h\"\r\n#include \"panels/charpanel.hpp\"\r\n#include \"panels/console.hpp\"\r\n#include \"panels/partypanel.hpp\"\r\n#include \"panels/spell_list.hpp\"\r\n#include \"plrmsg.h\"\r\n#include \"qol/chatlog.h\"\r\n#include \"qol/floatingnumbers.h\"\r\n#include \"qol/itemlabels.h\"\r\n#include \"qol/monhealthbar.h\"\r\n#include \"qol/stash.h\"\r\n#include \"qol/xpbar.h\"\r\n#include \"stores.h\"\r\n#include \"towners.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifndef USE_SDL1\r\n#include \"controls/touch/renderers.h\"\r\n#endif\r\n\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n\r\n#ifdef DUN_RENDER_STATS\r\n#include \"utils/format_int.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nenum OutlineColors : uint8_t {\r\n\tOutlineColorsPlayer1 = (PAL16_ORANGE + 7),\r\n\tOutlineColorsPlayer2 = (PAL16_YELLOW + 7),\r\n\tOutlineColorsPlayer3 = (PAL16_RED + 7),\r\n\tOutlineColorsPlayer4 = (PAL16_BLUE + 7),\r\n\tOutlineColorsObject = (PAL16_YELLOW + 2),\r\n\tOutlineColorsTowner = (PAL16_BEIGE + 6),\r\n\tOutlineColorsMonster = (PAL16_RED + 9),\r\n};\r\n\r\nbool AutoMapShowItems;\r\n\r\n// DevilutionX extension.\r\nextern void DrawControllerModifierHints(const Surface &out);\r\n\r\nbool frameflag;\r\n\r\nnamespace {\r\n\r\nconstexpr auto RightFrameDisplacement = Displacement { DunFrameWidth, 0 };\r\n\r\n[[nodiscard]] DVL_ALWAYS_INLINE bool IsFloor(Point tilePosition)\r\n{\r\n\treturn !TileHasAny(tilePosition, TileProperties::Solid | TileProperties::BlockMissile);\r\n}\r\n\r\n[[nodiscard]] DVL_ALWAYS_INLINE bool IsWall(Point tilePosition)\r\n{\r\n\treturn !IsFloor(tilePosition) || dSpecial[tilePosition.x][tilePosition.y] != 0;\r\n}\r\n\r\n/**\r\n * @brief Contains all Missile at rendering position\r\n */\r\nankerl::unordered_dense::map<WorldTilePosition, std::vector<Missile *>> MissilesAtRenderingTile;\r\n\r\n/**\r\n * @brief Could the missile (at the next game tick) collide? This method is a simplified version of CheckMissileCol (for example without random).\r\n */\r\nbool CouldMissileCollide(Point tile, bool checkPlayerAndMonster)\r\n{\r\n\tif (!InDungeonBounds(tile))\r\n\t\treturn true;\r\n\tif (checkPlayerAndMonster) {\r\n\t\tif (dMonster[tile.x][tile.y] > 0)\r\n\t\t\treturn true;\r\n\t\tif (dPlayer[tile.x][tile.y] > 0)\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\treturn IsMissileBlockedByTile(tile);\r\n}\r\n\r\nvoid UpdateMissilePositionForRendering(Missile &m, int progress)\r\n{\r\n\tDisplacementOf<int64_t> velocity = m.position.velocity;\r\n\tvelocity *= progress;\r\n\tvelocity /= AnimationInfo::baseValueFraction;\r\n\tconst Displacement pixelsTravelled = (m.position.traveled + Displacement { static_cast<int>(velocity.deltaX), static_cast<int>(velocity.deltaY) }) >> 16;\r\n\tconst Displacement tileOffset = pixelsTravelled.screenToMissile();\r\n\r\n\t// calculate the future missile position\r\n\tm.position.tileForRendering = m.position.start + tileOffset;\r\n\tm.position.offsetForRendering = pixelsTravelled + tileOffset.worldToScreen();\r\n}\r\n\r\nvoid UpdateMissileRendererData(Missile &m)\r\n{\r\n\tm.position.tileForRendering = m.position.tile;\r\n\tm.position.offsetForRendering = m.position.offset;\r\n\r\n\tconst MissileMovementDistribution missileMovement = GetMissileData(m._mitype).movementDistribution;\r\n\t// don't calculate missile position if they don't move\r\n\tif (missileMovement == MissileMovementDistribution::Disabled || m.position.velocity == Displacement {})\r\n\t\treturn;\r\n\r\n\tint progress = ProgressToNextGameTick;\r\n\tUpdateMissilePositionForRendering(m, progress);\r\n\r\n\t// In some cases this calculated position is invalid.\r\n\t// For example a missile shouldn't move inside a wall.\r\n\t// In this case the game logic don't advance the missile position and removes the missile or shows an explosion animation at the old position.\r\n\t// For the animation distribution logic this means we are not allowed to move to a tile where the missile could collide, because this could be a invalid position.\r\n\r\n\t// If we are still at the current tile, this tile was already checked and is a valid tile\r\n\tif (m.position.tileForRendering == m.position.tile)\r\n\t\treturn;\r\n\r\n\t// If no collision can happen at the new tile we can advance\r\n\tif (!CouldMissileCollide(m.position.tileForRendering, missileMovement == MissileMovementDistribution::Blockable))\r\n\t\treturn;\r\n\r\n\t// The new tile could be invalid, so don't advance to it.\r\n\t// We search the last offset that is in the old (valid) tile.\r\n\t// Implementation note: If someone knows the correct math to calculate this without the loop, I would really appreciate it.\r\n\twhile (m.position.tile != m.position.tileForRendering) {\r\n\t\tprogress -= 1;\r\n\r\n\t\tif (progress <= 0) {\r\n\t\t\tm.position.tileForRendering = m.position.tile;\r\n\t\t\tm.position.offsetForRendering = m.position.offset;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tUpdateMissilePositionForRendering(m, progress);\r\n\t}\r\n}\r\n\r\nvoid UpdateMissilesRendererData()\r\n{\r\n\tMissilesAtRenderingTile.clear();\r\n\r\n\tfor (auto &m : Missiles) {\r\n\t\tUpdateMissileRendererData(m);\r\n\t\tMissilesAtRenderingTile[m.position.tileForRendering].push_back(&m);\r\n\t}\r\n}\r\n\r\nuint32_t lastFpsUpdateInMs;\r\n\r\nRectangle PrevCursorRect;\r\n\r\nvoid BlitCursor(uint8_t *dst, uint32_t dstPitch, uint8_t *src, uint32_t srcPitch, uint32_t srcWidth, uint32_t srcHeight)\r\n{\r\n\tfor (std::uint32_t i = 0; i < srcHeight; ++i, src += srcPitch, dst += dstPitch) {\r\n\t\tmemcpy(dst, src, srcWidth);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Remove the cursor from the buffer\r\n */\r\nvoid UndrawCursor(const Surface &out)\r\n{\r\n\tDrawnCursor &cursor = GetDrawnCursor();\r\n\tBlitCursor(&out[cursor.rect.position], out.pitch(), cursor.behindBuffer, cursor.rect.size.width, cursor.rect.size.width, cursor.rect.size.height);\r\n\tPrevCursorRect = cursor.rect;\r\n}\r\n\r\nbool ShouldShowCursor()\r\n{\r\n\tif (ControlMode == ControlTypes::KeyboardAndMouse)\r\n\t\treturn true;\r\n\tif (pcurs == CURSOR_TELEPORT)\r\n\t\treturn true;\r\n\tif (invflag)\r\n\t\treturn true;\r\n\tif (CharFlag && MyPlayer->_pStatPts > 0)\r\n\t\treturn true;\r\n\r\n\treturn false;\r\n}\r\n\r\n/**\r\n * @brief Blit CL2 sprite, and apply lighting, to the given buffer at the given coordinates\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n */\r\ninline void ClxDrawLight(const Surface &out, Point position, ClxSprite clx, int lightTableIndex)\r\n{\r\n\tif (lightTableIndex != 0) {\r\n\t\tClxDrawTRN(out, position, clx, LightTables[lightTableIndex].data());\r\n\t} else {\r\n\t\tClxDraw(out, position, clx);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Blit CL2 sprite, and apply lighting and transparency blending, to the given buffer at the given coordinates\r\n * @param out Output buffer\r\n * @param position Target buffer coordinate\r\n * @param clx CLX frame\r\n */\r\ninline void ClxDrawLightBlended(const Surface &out, Point position, ClxSprite clx, int lightTableIndex)\r\n{\r\n\tif (lightTableIndex != 0) {\r\n\t\tClxDrawBlendedTRN(out, position, clx, LightTables[lightTableIndex].data());\r\n\t} else {\r\n\t\tClxDrawBlended(out, position, clx);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Save the content behind the cursor to a temporary buffer, then draw the cursor.\r\n */\r\nvoid DrawCursor(const Surface &out)\r\n{\r\n\tDrawnCursor &cursor = GetDrawnCursor();\r\n\tif (IsHardwareCursor()) {\r\n\t\tSetHardwareCursorVisible(ShouldShowCursor());\r\n\t\tcursor.rect.size = { 0, 0 };\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (pcurs <= CURSOR_NONE || !ShouldShowCursor()) {\r\n\t\tcursor.rect.size = { 0, 0 };\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Size cursSize = GetInvItemSize(pcurs);\r\n\tif (cursSize.width == 0 || cursSize.height == 0) {\r\n\t\tcursor.rect.size = { 0, 0 };\r\n\t\treturn;\r\n\t}\r\n\r\n\tconstexpr auto Clip = [](int &pos, int &length, int posEnd) {\r\n\t\tif (pos + length <= 0 || pos >= posEnd) {\r\n\t\t\tpos = 0;\r\n\t\t\tlength = 0;\r\n\t\t} else if (pos < 0) {\r\n\t\t\tlength += pos;\r\n\t\t\tpos = 0;\r\n\t\t} else if (pos + length > posEnd) {\r\n\t\t\tlength = posEnd - pos;\r\n\t\t}\r\n\t};\r\n\r\n\t// Copy the buffer before the item cursor and its 1px outline are drawn to a temporary buffer.\r\n\tconst int outlineWidth = !MyPlayer->HoldItem.isEmpty() ? 1 : 0;\r\n\tconst Displacement offset = !MyPlayer->HoldItem.isEmpty() ? Displacement { cursSize / 2 } : Displacement { 0 };\r\n\tconst Point cursPosition = MousePosition - offset;\r\n\r\n\tRectangle &rect = cursor.rect;\r\n\trect.position.x = cursPosition.x - outlineWidth;\r\n\trect.size.width = cursSize.width + 2 * outlineWidth;\r\n\tClip(rect.position.x, rect.size.width, out.w());\r\n\r\n\trect.position.y = cursPosition.y - outlineWidth;\r\n\trect.size.height = cursSize.height + 2 * outlineWidth;\r\n\tClip(rect.position.y, rect.size.height, out.h());\r\n\r\n\tif (rect.size.width == 0 || rect.size.height == 0)\r\n\t\treturn;\r\n\r\n\tBlitCursor(cursor.behindBuffer, rect.size.width, &out[rect.position], out.pitch(), rect.size.width, rect.size.height);\r\n\tDrawSoftwareCursor(out, cursPosition + Displacement { 0, cursSize.height - 1 }, pcurs);\r\n}\r\n\r\n/**\r\n * @brief Render a missile sprite\r\n * @param out Output buffer\r\n * @param missile Pointer to Missile struct\r\n * @param targetBufferPosition Output buffer coordinate\r\n * @param pre Is the sprite in the background\r\n */\r\nvoid DrawMissilePrivate(const Surface &out, const Missile &missile, Point targetBufferPosition, bool pre, int lightTableIndex)\r\n{\r\n\tif (missile._miPreFlag != pre || !missile._miDrawFlag)\r\n\t\treturn;\r\n\r\n\tconst Point missileRenderPosition { targetBufferPosition + missile.position.offsetForRendering - Displacement { missile._miAnimWidth2, 0 } };\r\n\tconst ClxSprite sprite = (*missile._miAnimData)[missile._miAnimFrame - 1];\r\n\tif (missile._miUniqTrans != 0) {\r\n\t\tClxDrawTRN(out, missileRenderPosition, sprite, Monsters[missile._misource].uniqueMonsterTRN.get());\r\n\t} else if (missile._miLightFlag) {\r\n\t\tClxDrawLight(out, missileRenderPosition, sprite, lightTableIndex);\r\n\t} else {\r\n\t\tClxDraw(out, missileRenderPosition, sprite);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Render a missile sprites for a given tile\r\n * @param out Output buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Output buffer coordinates\r\n * @param pre Is the sprite in the background\r\n */\r\nvoid DrawMissile(const Surface &out, WorldTilePosition tilePosition, Point targetBufferPosition, bool pre, int lightTableIndex)\r\n{\r\n\tconst auto it = MissilesAtRenderingTile.find(tilePosition);\r\n\tif (it == MissilesAtRenderingTile.end()) return;\r\n\tfor (Missile *missile : it->second) {\r\n\t\tDrawMissilePrivate(out, *missile, targetBufferPosition, pre, lightTableIndex);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Render a monster sprite\r\n * @param out Output buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Output buffer coordinates\r\n * @param monster Monster reference\r\n */\r\nvoid DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosition, const Monster &monster, int lightTableIndex)\r\n{\r\n\tif (!monster.animInfo.sprites) {\r\n\t\tLog(\"Draw Monster \\\"{}\\\": NULL Cel Buffer\", monster.name());\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst ClxSprite sprite = monster.animInfo.currentSprite();\r\n\r\n\tif (!IsTileLit(tilePosition)) {\r\n\t\tClxDrawTRN(out, targetBufferPosition, sprite, GetInfravisionTRN());\r\n\t\treturn;\r\n\t}\r\n\tuint8_t *trn = nullptr;\r\n\tif (monster.isUnique())\r\n\t\ttrn = monster.uniqueMonsterTRN.get();\r\n\tif (monster.mode == MonsterMode::Petrified)\r\n\t\ttrn = GetStoneTRN();\r\n\tif (MyPlayer->_pInfraFlag && lightTableIndex > 8)\r\n\t\ttrn = GetInfravisionTRN();\r\n\tif (trn != nullptr)\r\n\t\tClxDrawTRN(out, targetBufferPosition, sprite, trn);\r\n\telse\r\n\t\tClxDrawLight(out, targetBufferPosition, sprite, lightTableIndex);\r\n}\r\n\r\n/**\r\n * @brief Helper for rendering a specific player icon (Mana Shield or Reflect)\r\n */\r\nvoid DrawPlayerIconHelper(const Surface &out, MissileGraphicID missileGraphicId, Point position, const Player &player, bool infraVision, int lightTableIndex)\r\n{\r\n\tconst bool lighting = &player != MyPlayer;\r\n\r\n\tif (player.isWalking())\r\n\t\tposition += GetOffsetForWalking(player.AnimInfo, player._pdir);\r\n\r\n\tposition.x -= GetMissileSpriteData(missileGraphicId).animWidth2;\r\n\r\n\tconst ClxSprite sprite = (*GetMissileSpriteData(missileGraphicId).sprites).list()[0];\r\n\r\n\tif (!lighting) {\r\n\t\tClxDraw(out, position, sprite);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (infraVision) {\r\n\t\tClxDrawTRN(out, position, sprite, GetInfravisionTRN());\r\n\t\treturn;\r\n\t}\r\n\r\n\tClxDrawLight(out, position, sprite, lightTableIndex);\r\n}\r\n\r\n/**\r\n * @brief Helper for rendering player icons (Mana Shield and Reflect)\r\n * @param out Output buffer\r\n * @param player Player reference\r\n * @param position Output buffer coordinates\r\n * @param infraVision Should infravision be applied\r\n */\r\nvoid DrawPlayerIcons(const Surface &out, const Player &player, Point position, bool infraVision, int lightTableIndex)\r\n{\r\n\tif (player.pManaShield)\r\n\t\tDrawPlayerIconHelper(out, MissileGraphicID::ManaShield, position, player, infraVision, lightTableIndex);\r\n\tif (player.wReflections > 0)\r\n\t\tDrawPlayerIconHelper(out, MissileGraphicID::Reflect, position + Displacement { 0, 16 }, player, infraVision, lightTableIndex);\r\n}\r\n\r\nuint8_t GetPlayerOutlineColor(int id)\r\n{\r\n\tstatic constexpr uint8_t PlayerOutlineColors[] = {\r\n\t\tOutlineColorsPlayer1,\r\n\t\tOutlineColorsPlayer2,\r\n\t\tOutlineColorsPlayer3,\r\n\t\tOutlineColorsPlayer4,\r\n\t};\r\n\r\n\tif (id < 0 || id >= static_cast<int>(SDL_arraysize(PlayerOutlineColors)))\r\n\t\treturn OutlineColorsPlayer1;\r\n\r\n\treturn PlayerOutlineColors[id];\r\n}\r\n\r\n/**\r\n * @brief Render a player sprite\r\n * @param out Output buffer\r\n * @param player Player reference\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Output buffer coordinates\r\n */\r\nvoid DrawPlayer(const Surface &out, const Player &player, Point tilePosition, Point targetBufferPosition, int lightTableIndex)\r\n{\r\n\tif (!IsTileLit(tilePosition) && !MyPlayer->_pInfraFlag && !MyPlayer->isOnArenaLevel() && leveltype != DTYPE_TOWN) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst ClxSprite sprite = player.currentSprite();\r\n\tconst Point spriteBufferPosition = targetBufferPosition + player.getRenderingOffset(sprite);\r\n\r\n\tif (&player == PlayerUnderCursor)\r\n\t\tClxDrawOutlineSkipColorZero(out, GetPlayerOutlineColor(player.getId()), spriteBufferPosition, sprite);\r\n\r\n\tif (&player == MyPlayer && IsNoneOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\tClxDraw(out, spriteBufferPosition, sprite);\r\n\t\tDrawPlayerIcons(out, player, targetBufferPosition, /*infraVision=*/false, lightTableIndex);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!IsTileLit(tilePosition) || ((MyPlayer->_pInfraFlag || MyPlayer->isOnArenaLevel()) && lightTableIndex > 8)) {\r\n\t\tClxDrawTRN(out, spriteBufferPosition, sprite, GetInfravisionTRN());\r\n\t\tDrawPlayerIcons(out, player, targetBufferPosition, /*infraVision=*/true, lightTableIndex);\r\n\t\treturn;\r\n\t}\r\n\r\n\tlightTableIndex = std::max(lightTableIndex - 5, 0);\r\n\tClxDrawLight(out, spriteBufferPosition, sprite, lightTableIndex);\r\n\tDrawPlayerIcons(out, player, targetBufferPosition, /*infraVision=*/false, lightTableIndex);\r\n}\r\n\r\n/**\r\n * @brief Render a player sprite\r\n * @param out Output buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Output buffer coordinates\r\n */\r\nvoid DrawDeadPlayer(const Surface &out, Point tilePosition, Point targetBufferPosition, int lightTableIndex)\r\n{\r\n\tdFlags[tilePosition.x][tilePosition.y] &= ~DungeonFlag::DeadPlayer;\r\n\r\n\tfor (const Player &player : Players) {\r\n\t\tif (player.plractive && player.hasNoLife() && player.isOnActiveLevel() && player.position.tile == tilePosition) {\r\n\t\t\tdFlags[tilePosition.x][tilePosition.y] |= DungeonFlag::DeadPlayer;\r\n\t\t\tconst Point playerRenderPosition { targetBufferPosition };\r\n\t\t\tDrawPlayer(out, player, tilePosition, playerRenderPosition, lightTableIndex);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Render an object sprite\r\n * @param out Output buffer\r\n * @param objectToDraw Dungeone object to draw\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Output buffer coordinates\r\n * @param pre Is the sprite in the background\r\n */\r\nvoid DrawObject(const Surface &out, const Object &objectToDraw, Point tilePosition, Point targetBufferPosition, int lightTableIndex)\r\n{\r\n\tconst ClxSprite sprite = objectToDraw.currentSprite();\r\n\r\n\tconst Point screenPosition = targetBufferPosition + objectToDraw.getRenderingOffset(sprite, tilePosition);\r\n\r\n\tif (&objectToDraw == ObjectUnderCursor) {\r\n\t\tClxDrawOutlineSkipColorZero(out, OutlineColorsObject, screenPosition, sprite);\r\n\t}\r\n\tif (objectToDraw.applyLighting) {\r\n\t\tClxDrawLight(out, screenPosition, sprite, lightTableIndex);\r\n\t} else {\r\n\t\tClxDraw(out, screenPosition, sprite);\r\n\t}\r\n}\r\n\r\nstatic void DrawDungeon(const Surface & /*out*/, const Lightmap & /*lightmap*/, Point /*tilePosition*/, Point /*targetBufferPosition*/);\r\n\r\n/**\r\n * @brief Render a cell\r\n * @param out Target buffer\r\n * @param lightmap Per-pixel light buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Target buffer coordinates\r\n */\r\nvoid DrawCell(const Surface &out, const Lightmap lightmap, Point tilePosition, Point targetBufferPosition, int lightTableIndex)\r\n{\r\n\tconst uint16_t levelPieceId = dPiece[tilePosition.x][tilePosition.y];\r\n\tconst MICROS *pMap = &DPieceMicros[levelPieceId];\r\n\r\n\tconst uint8_t *tbl = LightTables[lightTableIndex].data();\r\n\tconst uint8_t *foliageTbl = tbl;\r\n#ifdef _DEBUG\r\n\tint walkpathIdx = -1;\r\n\tPoint originalTargetBufferPosition;\r\n\tif (DebugPath) {\r\n\t\twalkpathIdx = MyPlayer->GetPositionPathIndex(tilePosition);\r\n\t\tif (walkpathIdx != -1) {\r\n\t\t\toriginalTargetBufferPosition = targetBufferPosition;\r\n\t\t\ttbl = GetPauseTRN();\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tbool transparency = TileHasAny(tilePosition, TileProperties::Transparent) && TransList[dTransVal[tilePosition.x][tilePosition.y]];\r\n#ifdef _DEBUG\r\n\tif ((SDL_GetModState() & SDL_KMOD_ALT) != 0) {\r\n\t\ttransparency = false;\r\n\t}\r\n#endif\r\n\r\n\tconst auto getFirstTileMaskLeft = [=](TileType tile) -> MaskType {\r\n\t\tif (transparency) {\r\n\t\t\tswitch (tile) {\r\n\t\t\tcase TileType::LeftTrapezoid:\r\n\t\t\tcase TileType::TransparentSquare:\r\n\t\t\t\treturn TileHasAny(tilePosition, TileProperties::TransparentLeft)\r\n\t\t\t\t    ? MaskType::Left\r\n\t\t\t\t    : MaskType::Solid;\r\n\t\t\tcase TileType::LeftTriangle:\r\n\t\t\t\treturn MaskType::Solid;\r\n\t\t\tdefault:\r\n\t\t\t\treturn MaskType::Transparent;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn MaskType::Solid;\r\n\t};\r\n\r\n\tconst auto getFirstTileMaskRight = [=](TileType tile) -> MaskType {\r\n\t\tif (transparency) {\r\n\t\t\tswitch (tile) {\r\n\t\t\tcase TileType::RightTrapezoid:\r\n\t\t\tcase TileType::TransparentSquare:\r\n\t\t\t\treturn TileHasAny(tilePosition, TileProperties::TransparentRight)\r\n\t\t\t\t    ? MaskType::Right\r\n\t\t\t\t    : MaskType::Solid;\r\n\t\t\tcase TileType::RightTriangle:\r\n\t\t\t\treturn MaskType::Solid;\r\n\t\t\tdefault:\r\n\t\t\t\treturn MaskType::Transparent;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn MaskType::Solid;\r\n\t};\r\n\r\n\t// Create a special lightmap buffer to bleed light up walls\r\n\tuint8_t lightmapBuffer[TILE_WIDTH * TILE_HEIGHT];\r\n\tconst Lightmap bleedLightmap = Lightmap::bleedUp(*GetOptions().Graphics.perPixelLighting, lightmap, targetBufferPosition, lightmapBuffer);\r\n\r\n\t// If the first micro tile is a floor tile, it may be followed\r\n\t// by foliage which should be rendered now.\r\n\tconst bool isFloor = IsFloor(tilePosition);\r\n\tif (const LevelCelBlock levelCelBlock { pMap->mt[0] }; levelCelBlock.hasValue()) {\r\n\t\tconst TileType tileType = levelCelBlock.type();\r\n\t\tif (!isFloor || tileType == TileType::TransparentSquare) {\r\n\t\t\tif (isFloor && tileType == TileType::TransparentSquare) {\r\n\t\t\t\tRenderTileFoliage(out, bleedLightmap, targetBufferPosition,\r\n\t\t\t\t    pDungeonCels.get(), levelCelBlock, foliageTbl);\r\n\t\t\t} else {\r\n\t\t\t\tRenderTile(out, bleedLightmap, targetBufferPosition,\r\n\t\t\t\t    pDungeonCels.get(), levelCelBlock, getFirstTileMaskLeft(tileType), tbl);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (const LevelCelBlock levelCelBlock { pMap->mt[1] }; levelCelBlock.hasValue()) {\r\n\t\tconst TileType tileType = levelCelBlock.type();\r\n\t\tif (!isFloor || tileType == TileType::TransparentSquare) {\r\n\t\t\tif (isFloor && tileType == TileType::TransparentSquare) {\r\n\t\t\t\tRenderTileFoliage(out, bleedLightmap, targetBufferPosition + RightFrameDisplacement,\r\n\t\t\t\t    pDungeonCels.get(), levelCelBlock, foliageTbl);\r\n\t\t\t} else {\r\n\t\t\t\tRenderTile(out, bleedLightmap, targetBufferPosition + RightFrameDisplacement,\r\n\t\t\t\t    pDungeonCels.get(), levelCelBlock, getFirstTileMaskRight(tileType), tbl);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttargetBufferPosition.y -= TILE_HEIGHT;\r\n\r\n\tfor (uint_fast8_t i = 2, n = MicroTileLen; i < n; i += 2) {\r\n\t\t{\r\n\t\t\tconst LevelCelBlock levelCelBlock { pMap->mt[i] };\r\n\t\t\tif (levelCelBlock.hasValue()) {\r\n\t\t\t\tRenderTile(out, bleedLightmap, targetBufferPosition,\r\n\t\t\t\t    pDungeonCels.get(), levelCelBlock,\r\n\t\t\t\t    transparency ? MaskType::Transparent : MaskType::Solid, foliageTbl);\r\n\t\t\t}\r\n\t\t}\r\n\t\t{\r\n\t\t\tconst LevelCelBlock levelCelBlock { pMap->mt[i + 1] };\r\n\t\t\tif (levelCelBlock.hasValue()) {\r\n\t\t\t\tRenderTile(out, bleedLightmap, targetBufferPosition + RightFrameDisplacement,\r\n\t\t\t\t    pDungeonCels.get(), levelCelBlock,\r\n\t\t\t\t    transparency ? MaskType::Transparent : MaskType::Solid, foliageTbl);\r\n\t\t\t}\r\n\t\t}\r\n\t\ttargetBufferPosition.y -= TILE_HEIGHT;\r\n\t}\r\n\r\n#ifdef _DEBUG\r\n\tif (DebugPath && walkpathIdx != -1) {\r\n\t\tDrawString(out, StrCat(walkpathIdx),\r\n\t\t    Rectangle(originalTargetBufferPosition + Displacement { 0, -TILE_HEIGHT }, Size { TILE_WIDTH, TILE_HEIGHT }),\r\n\t\t    TextRenderOptions {\r\n\t\t        .flags = UiFlags::AlignCenter | UiFlags::VerticalCenter\r\n\t\t            | (IsTileSolid(tilePosition) ? UiFlags::ColorYellow : UiFlags::ColorWhite) });\r\n\t}\r\n#endif\r\n}\r\n\r\n/**\r\n * @brief Render a floor tile.\r\n * @param out Target buffer\r\n * @param lightmap Per-pixel light buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Target buffer coordinate\r\n */\r\nvoid DrawFloorTile(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition)\r\n{\r\n\tconst int lightTableIndex = dLight[tilePosition.x][tilePosition.y];\r\n\r\n\tconst uint8_t *tbl = LightTables[lightTableIndex].data();\r\n#ifdef _DEBUG\r\n\tif (DebugPath && MyPlayer->GetPositionPathIndex(tilePosition) != -1)\r\n\t\ttbl = GetPauseTRN();\r\n#endif\r\n\r\n\tconst uint16_t levelPieceId = dPiece[tilePosition.x][tilePosition.y];\r\n\t{\r\n\t\tconst LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[0] };\r\n\t\tif (levelCelBlock.hasValue()) {\r\n\t\t\tRenderTileFrame(out, lightmap, targetBufferPosition, TileType::LeftTriangle,\r\n\t\t\t    GetDunFrame(pDungeonCels.get(), levelCelBlock.frame()), DunFrameTriangleHeight, MaskType::Solid, tbl);\r\n\t\t}\r\n\t}\r\n\t{\r\n\t\tconst LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[1] };\r\n\t\tif (levelCelBlock.hasValue()) {\r\n\t\t\tRenderTileFrame(out, lightmap, targetBufferPosition + RightFrameDisplacement, TileType::RightTriangle,\r\n\t\t\t    GetDunFrame(pDungeonCels.get(), levelCelBlock.frame()), DunFrameTriangleHeight, MaskType::Solid, tbl);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Draw item for a given tile\r\n * @param out Output buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Output buffer coordinates\r\n * @param pre Is the sprite in the background\r\n */\r\nvoid DrawItem(const Surface &out, int8_t itemIndex, Point targetBufferPosition, int lightTableIndex)\r\n{\r\n\tconst Item &item = Items[itemIndex];\r\n\tconst ClxSprite sprite = item.AnimInfo.currentSprite();\r\n\tconst Point position = targetBufferPosition + item.getRenderingOffset(sprite);\r\n\tif (!IsPlayerInStore() && (itemIndex == pcursitem || AutoMapShowItems)) {\r\n\t\tClxDrawOutlineSkipColorZero(out, GetOutlineColor(item, false), position, sprite);\r\n\t}\r\n\tClxDrawLight(out, position, sprite, lightTableIndex);\r\n\tif (item.AnimInfo.isLastFrame() || item._iCurs == ICURS_MAGIC_ROCK)\r\n\t\tAddItemToLabelQueue(itemIndex, position);\r\n}\r\n\r\n/**\r\n * @brief Check if and how a monster should be rendered\r\n * @param out Output buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Output buffer coordinates\r\n */\r\nvoid DrawMonsterHelper(const Surface &out, Point tilePosition, Point targetBufferPosition, int lightTableIndex)\r\n{\r\n\tint mi = dMonster[tilePosition.x][tilePosition.y];\r\n\r\n\tmi = std::abs(mi) - 1;\r\n\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tauto &towner = Towners[mi];\r\n\t\tconst Point position = targetBufferPosition + towner.getRenderingOffset();\r\n\t\tconst ClxSprite sprite = towner.currentSprite();\r\n\t\tif (mi == pcursmonst) {\r\n\t\t\tClxDrawOutlineSkipColorZero(out, OutlineColorsTowner, position, sprite);\r\n\t\t}\r\n\t\tClxDraw(out, position, sprite);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!IsTileLit(tilePosition) && !(MyPlayer->_pInfraFlag && IsFloor(tilePosition))) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (static_cast<size_t>(mi) >= MaxMonsters) {\r\n\t\tLog(\"Draw Monster: tried to draw illegal monster {}\", mi);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst auto &monster = Monsters[mi];\r\n\tif ((monster.flags & MFLAG_HIDDEN) != 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst ClxSprite sprite = monster.animInfo.currentSprite();\r\n\tconst Displacement offset = monster.getRenderingOffset(sprite);\r\n\r\n\tconst Point monsterRenderPosition = targetBufferPosition + offset;\r\n\tif (mi == pcursmonst) {\r\n\t\tClxDrawOutlineSkipColorZero(out, OutlineColorsMonster, monsterRenderPosition, sprite);\r\n\t}\r\n\tDrawMonster(out, tilePosition, monsterRenderPosition, monster, lightTableIndex);\r\n}\r\n\r\n/**\r\n * @brief Render object sprites\r\n * @param out Target buffer\r\n * @param lightmap Per-pixel light buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Target buffer coordinates\r\n */\r\nvoid DrawDungeon(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition)\r\n{\r\n\tassert(InDungeonBounds(tilePosition));\r\n\tconst int lightTableIndex = dLight[tilePosition.x][tilePosition.y];\r\n\r\n\tDrawCell(out, lightmap, tilePosition, targetBufferPosition, lightTableIndex);\r\n\r\n\tconst int8_t bDead = dCorpse[tilePosition.x][tilePosition.y];\r\n\tconst int8_t bMap = dTransVal[tilePosition.x][tilePosition.y];\r\n\r\n#ifdef _DEBUG\r\n\tif (DebugVision && IsTileLit(tilePosition)) {\r\n\t\tClxDraw(out, targetBufferPosition, (*pSquareCel)[0]);\r\n\t}\r\n#endif\r\n\r\n\tif (MissilePreFlag) {\r\n\t\tDrawMissile(out, tilePosition, targetBufferPosition, true, lightTableIndex);\r\n\t}\r\n\r\n\tif (lightTableIndex < LightsMax && bDead != 0) {\r\n\t\tconst Corpse &corpse = Corpses[(bDead & 0x1F) - 1];\r\n\t\tconst Point position { targetBufferPosition.x - CalculateSpriteTileCenterX(corpse.width), targetBufferPosition.y };\r\n\t\tconst ClxSprite sprite = corpse.spritesForDirection(static_cast<Direction>((bDead >> 5) & 7))[corpse.frame];\r\n\t\tif (corpse.translationPaletteIndex != 0) {\r\n\t\t\tconst uint8_t *trn = Monsters[corpse.translationPaletteIndex - 1].uniqueMonsterTRN.get();\r\n\t\t\tClxDrawTRN(out, position, sprite, trn);\r\n\t\t} else {\r\n\t\t\tClxDrawLight(out, position, sprite, lightTableIndex);\r\n\t\t}\r\n\t}\r\n\r\n\tconst int8_t bItem = dItem[tilePosition.x][tilePosition.y];\r\n\tconst Object *object = lightTableIndex < LightsMax\r\n\t    ? FindObjectAtPosition(tilePosition)\r\n\t    : nullptr;\r\n\tif (object != nullptr && object->_oPreFlag) {\r\n\t\tDrawObject(out, *object, tilePosition, targetBufferPosition, lightTableIndex);\r\n\t}\r\n\tif (bItem > 0 && !Items[bItem - 1]._iPostDraw) {\r\n\t\tDrawItem(out, static_cast<int8_t>(bItem - 1), targetBufferPosition, lightTableIndex);\r\n\t}\r\n\r\n\tif (TileContainsDeadPlayer(tilePosition)) {\r\n\t\tDrawDeadPlayer(out, tilePosition, targetBufferPosition, lightTableIndex);\r\n\t}\r\n\tPlayer *player = PlayerAtPosition(tilePosition);\r\n\tif (player != nullptr) {\r\n\t\tconst uint8_t pid = player->getId();\r\n\t\tassert(pid < MAX_PLRS);\r\n\t\tint playerId = static_cast<int>(pid) + 1;\r\n\t\t// If sprite is moving southwards or east, we want to draw it offset from the tile it's moving to, so we need negative ID\r\n\t\t// This respests the order that tiles are drawn. By using the negative id, we ensure that the sprite is drawn with priority\r\n\t\tif (player->_pmode == PM_WALK_SOUTHWARDS || (player->_pmode == PM_WALK_SIDEWAYS && player->_pdir == Direction::East))\r\n\t\t\tplayerId = -playerId;\r\n\t\tif (dPlayer[tilePosition.x][tilePosition.y] == playerId) {\r\n\t\t\tauto tempTilePosition = tilePosition;\r\n\t\t\tauto tempTargetBufferPosition = targetBufferPosition;\r\n\r\n\t\t\t// Offset the sprite to the tile it's moving from\r\n\t\t\tif (player->_pmode == PM_WALK_SOUTHWARDS) {\r\n\t\t\t\tswitch (player->_pdir) {\r\n\t\t\t\tcase Direction::SouthWest:\r\n\t\t\t\t\ttempTargetBufferPosition += { TILE_WIDTH / 2, -TILE_HEIGHT / 2 };\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase Direction::South:\r\n\t\t\t\t\ttempTargetBufferPosition += { 0, -TILE_HEIGHT };\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase Direction::SouthEast:\r\n\t\t\t\t\ttempTargetBufferPosition += { -TILE_WIDTH / 2, -TILE_HEIGHT / 2 };\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDVL_UNREACHABLE();\r\n\t\t\t\t}\r\n\t\t\t\ttempTilePosition += Opposite(player->_pdir);\r\n\t\t\t} else if (player->_pmode == PM_WALK_SIDEWAYS && player->_pdir == Direction::East) {\r\n\t\t\t\ttempTargetBufferPosition += { -TILE_WIDTH, 0 };\r\n\t\t\t\ttempTilePosition += Opposite(player->_pdir);\r\n\t\t\t}\r\n\t\t\tDrawPlayer(out, *player, tempTilePosition, tempTargetBufferPosition, lightTableIndex);\r\n\t\t}\r\n\t}\r\n\r\n\tMonster *monster = FindMonsterAtPosition(tilePosition);\r\n\tif (monster != nullptr) {\r\n\t\tauto mid = monster->getId();\r\n\t\tassert(mid < MaxMonsters);\r\n\t\tint monsterId = static_cast<int>(mid) + 1;\r\n\t\t// If sprite is moving southwards or east, we want to draw it offset from the tile it's moving to, so we need negative ID\r\n\t\t// This respests the order that tiles are drawn. By using the negative id, we ensure that the sprite is drawn with priority\r\n\t\tif (monster->mode == MonsterMode::MoveSouthwards || (monster->mode == MonsterMode::MoveSideways && monster->direction == Direction::East))\r\n\t\t\tmonsterId = -monsterId;\r\n\t\tif (dMonster[tilePosition.x][tilePosition.y] == monsterId) {\r\n\t\t\tauto tempTilePosition = tilePosition;\r\n\t\t\tauto tempTargetBufferPosition = targetBufferPosition;\r\n\r\n\t\t\t// Offset the sprite to the tile it's moving from\r\n\t\t\tif (monster->mode == MonsterMode::MoveSouthwards) {\r\n\t\t\t\tswitch (monster->direction) {\r\n\t\t\t\tcase Direction::SouthWest:\r\n\t\t\t\t\ttempTargetBufferPosition += { TILE_WIDTH / 2, -TILE_HEIGHT / 2 };\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase Direction::South:\r\n\t\t\t\t\ttempTargetBufferPosition += { 0, -TILE_HEIGHT };\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase Direction::SouthEast:\r\n\t\t\t\t\ttempTargetBufferPosition += { -TILE_WIDTH / 2, -TILE_HEIGHT / 2 };\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tDVL_UNREACHABLE();\r\n\t\t\t\t}\r\n\t\t\t\ttempTilePosition += Opposite(monster->direction);\r\n\t\t\t} else if (monster->mode == MonsterMode::MoveSideways && monster->direction == Direction::East) {\r\n\t\t\t\ttempTargetBufferPosition += { -TILE_WIDTH, 0 };\r\n\t\t\t\ttempTilePosition += Opposite(monster->direction);\r\n\t\t\t}\r\n\t\t\tDrawMonsterHelper(out, tempTilePosition, tempTargetBufferPosition, lightTableIndex);\r\n\t\t}\r\n\t}\r\n\r\n\tDrawMissile(out, tilePosition, targetBufferPosition, false, lightTableIndex);\r\n\r\n\tif (object != nullptr && !object->_oPreFlag) {\r\n\t\tDrawObject(out, *object, tilePosition, targetBufferPosition, lightTableIndex);\r\n\t}\r\n\tif (bItem > 0 && Items[bItem - 1]._iPostDraw) {\r\n\t\tDrawItem(out, static_cast<int8_t>(bItem - 1), targetBufferPosition, lightTableIndex);\r\n\t}\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tconst bool perPixelLighting = *GetOptions().Graphics.perPixelLighting;\r\n\t\tconst int8_t bArch = dSpecial[tilePosition.x][tilePosition.y] - 1;\r\n\t\tif (bArch >= 0) {\r\n\t\t\tbool transparency = TransList[bMap];\r\n#ifdef _DEBUG\r\n\t\t\t// Turn transparency off here for debugging\r\n\t\t\ttransparency = transparency && (SDL_GetModState() & SDL_KMOD_ALT) == 0;\r\n#endif\r\n\t\t\tif (perPixelLighting) {\r\n\t\t\t\t// Create a special lightmap buffer to bleed light up walls\r\n\t\t\t\tuint8_t lightmapBuffer[TILE_WIDTH * TILE_HEIGHT];\r\n\t\t\t\tconst Lightmap bleedLightmap = Lightmap::bleedUp(*GetOptions().Graphics.perPixelLighting, lightmap, targetBufferPosition, lightmapBuffer);\r\n\r\n\t\t\t\tif (transparency)\r\n\t\t\t\t\tClxDrawBlendedWithLightmap(out, targetBufferPosition, (*pSpecialCels)[bArch], bleedLightmap);\r\n\t\t\t\telse\r\n\t\t\t\t\tClxDrawWithLightmap(out, targetBufferPosition, (*pSpecialCels)[bArch], bleedLightmap);\r\n\t\t\t} else if (transparency) {\r\n\t\t\t\tClxDrawLightBlended(out, targetBufferPosition, (*pSpecialCels)[bArch], lightTableIndex);\r\n\t\t\t} else {\r\n\t\t\t\tClxDrawLight(out, targetBufferPosition, (*pSpecialCels)[bArch], lightTableIndex);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\t// Tree leaves should always cover player when entering or leaving the tile,\r\n\t\t// So delay the rendering until after the next row is being drawn.\r\n\t\t// This could probably have been better solved by sprites in screen space.\r\n\t\tif (tilePosition.x > 0 && tilePosition.y > 0 && targetBufferPosition.y > TILE_HEIGHT) {\r\n\t\t\tconst int8_t bArch = dSpecial[tilePosition.x - 1][tilePosition.y - 1] - 1;\r\n\t\t\tif (bArch >= 0)\r\n\t\t\t\tClxDraw(out, targetBufferPosition + Displacement { 0, -TILE_HEIGHT }, (*pSpecialCels)[bArch]);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Render a row of tiles\r\n * @param out Buffer to render to\r\n * @param lightmap Per-pixel light buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Target buffer coordinates\r\n * @param rows Number of rows\r\n * @param columns Tile in a row\r\n */\r\nvoid DrawFloor(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition, int rows, int columns)\r\n{\r\n\tfor (int i = 0; i < rows; i++) {\r\n\t\tfor (int j = 0; j < columns; j++, tilePosition += Direction::East, targetBufferPosition.x += TILE_WIDTH) {\r\n\t\t\tif (!InDungeonBounds(tilePosition))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (IsFloor(tilePosition)) {\r\n\t\t\t\tDrawFloorTile(out, lightmap, tilePosition, targetBufferPosition);\r\n\t\t\t}\r\n\t\t}\r\n\t\t// Return to start of row\r\n\t\ttilePosition += Displacement(Direction::West) * columns;\r\n\t\ttargetBufferPosition.x -= columns * TILE_WIDTH;\r\n\r\n\t\t// Jump to next row\r\n\t\ttargetBufferPosition.y += TILE_HEIGHT / 2;\r\n\t\tif ((i & 1) != 0) {\r\n\t\t\ttilePosition.x++;\r\n\t\t\tcolumns--;\r\n\t\t\ttargetBufferPosition.x += TILE_WIDTH / 2;\r\n\t\t} else {\r\n\t\t\ttilePosition.y++;\r\n\t\t\tcolumns++;\r\n\t\t\ttargetBufferPosition.x -= TILE_WIDTH / 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Renders the floor tiles\r\n * @param out Output buffer\r\n * @param lightmap Per-pixel light buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Buffer coordinates\r\n * @param rows Number of rows\r\n * @param columns Tile in a row\r\n */\r\nvoid DrawTileContent(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition, int rows, int columns)\r\n{\r\n\t// Keep evaluating until MicroTiles can't affect screen\r\n\trows += MicroTileLen;\r\n\r\n#ifdef _DEBUG\r\n\tDebugCoordsMap.reserve(rows * columns);\r\n#endif\r\n\r\n\tfor (int i = 0; i < rows; i++) {\r\n\t\tbool skip = false;\r\n\t\tfor (int j = 0; j < columns; j++) {\r\n\t\t\tif (InDungeonBounds(tilePosition)) {\r\n\t\t\t\tbool skipNext = false;\r\n#ifdef _DEBUG\r\n\t\t\t\tDebugCoordsMap[tilePosition.x + tilePosition.y * MAXDUNX] = targetBufferPosition;\r\n#endif\r\n\t\t\t\tif (tilePosition.x + 1 < MAXDUNX && tilePosition.y - 1 >= 0 && targetBufferPosition.x + TILE_WIDTH <= gnScreenWidth) {\r\n\t\t\t\t\t// Render objects behind walls first to prevent sprites, that are moving\r\n\t\t\t\t\t// between tiles, from poking through the walls as they exceed the tile bounds.\r\n\t\t\t\t\t// A proper fix for this would probably be to layout the scene and render by\r\n\t\t\t\t\t// sprite screen position rather than tile position.\r\n\t\t\t\t\tif (IsWall(tilePosition) && (IsWall(tilePosition + Displacement { 1, 0 }) || (tilePosition.x > 0 && IsWall(tilePosition + Displacement { -1, 0 })))) { // Part of a wall aligned on the x-axis\r\n\t\t\t\t\t\tif (IsTileNotSolid(tilePosition + Displacement { 1, -1 }) && IsTileNotSolid(tilePosition + Displacement { 0, -1 })) {                              // Has walkable area behind it\r\n\t\t\t\t\t\t\tDrawDungeon(out, lightmap, tilePosition + Direction::East, { targetBufferPosition.x + TILE_WIDTH, targetBufferPosition.y });\r\n\t\t\t\t\t\t\tskipNext = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (!skip) {\r\n\t\t\t\t\tDrawDungeon(out, lightmap, tilePosition, targetBufferPosition);\r\n\t\t\t\t}\r\n\t\t\t\tskip = skipNext;\r\n\t\t\t}\r\n\t\t\ttilePosition += Direction::East;\r\n\t\t\ttargetBufferPosition.x += TILE_WIDTH;\r\n\t\t}\r\n\t\t// Return to start of row\r\n\t\ttilePosition += Displacement(Direction::West) * columns;\r\n\t\ttargetBufferPosition.x -= columns * TILE_WIDTH;\r\n\r\n\t\t// Jump to next row\r\n\t\ttargetBufferPosition.y += TILE_HEIGHT / 2;\r\n\t\tif ((i & 1) != 0) {\r\n\t\t\ttilePosition.x++;\r\n\t\t\tcolumns--;\r\n\t\t\ttargetBufferPosition.x += TILE_WIDTH / 2;\r\n\t\t} else {\r\n\t\t\ttilePosition.y++;\r\n\t\t\tcolumns++;\r\n\t\t\ttargetBufferPosition.x -= TILE_WIDTH / 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DrawDirtTile(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition)\r\n{\r\n\t// This should be the *top-left* of the 2×2 dirt pattern in the actual dungeon.\r\n\t// You might need to tweak these to where your dirt patch actually lives.\r\n\tconstexpr Point base { 0, 0 };\r\n\r\n\t// Decide which of the 4 tiles of the 2×2 block to use,\r\n\t// based on where this OOB tile is in the world grid.\r\n\tconst int ox = (tilePosition.x & 1); // 0 or 1\r\n\tconst int oy = (tilePosition.y & 1); // 0 or 1\r\n\r\n\tPoint sample {\r\n\t\tbase.x + ox,\r\n\t\tbase.y + oy,\r\n\t};\r\n\r\n\t// Safety: clamp in case tilePosition is wildly outside and base+offset ever escapes\r\n\tsample.x = std::clamp(sample.x, 0, MAXDUNX - 1);\r\n\tsample.y = std::clamp(sample.y, 0, MAXDUNY - 1);\r\n\r\n\tif (!InDungeonBounds(sample) || dPiece[sample.x][sample.y] == 0) {\r\n\t\t// Failsafe: if our sample somehow isn't valid, fall back to black\r\n\t\tworld_draw_black_tile(out, targetBufferPosition.x, targetBufferPosition.y);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int lightTableIndex = dLight[sample.x][sample.y];\r\n\r\n\t// Let the normal dungeon tile renderer compose the full tile\r\n\tDrawCell(out, lightmap, sample, targetBufferPosition, lightTableIndex);\r\n}\r\n\r\n/**\r\n * @brief Render a row of tiles\r\n * @param out Buffer to render to\r\n * @param lightmap Per-pixel light buffer\r\n * @param tilePosition dPiece coordinates\r\n * @param targetBufferPosition Target buffer coordinates\r\n * @param rows Number of rows\r\n * @param columns Tile in a row\r\n */\r\nvoid DrawOOB(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition, int rows, int columns)\r\n{\r\n\tfor (int i = 0; i < rows + 5; i++) { // 5 extra rows needed to make sure everything gets rendered at the bottom half of the screen\r\n\t\tfor (int j = 0; j < columns; j++, tilePosition += Direction::East, targetBufferPosition.x += TILE_WIDTH) {\r\n\t\t\tif (!InDungeonBounds(tilePosition)) {\r\n\t\t\t\tif (leveltype == DTYPE_TOWN) {\r\n\t\t\t\t\tworld_draw_black_tile(out, targetBufferPosition.x, targetBufferPosition.y);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tDrawDirtTile(out, lightmap, tilePosition, targetBufferPosition);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t// Return to start of row\r\n\t\ttilePosition += Displacement(Direction::West) * columns;\r\n\t\ttargetBufferPosition.x -= columns * TILE_WIDTH;\r\n\r\n\t\t// Jump to next row\r\n\t\ttargetBufferPosition.y += TILE_HEIGHT / 2;\r\n\t\tif ((i & 1) != 0) {\r\n\t\t\ttilePosition.x++;\r\n\t\t\tcolumns--;\r\n\t\t\ttargetBufferPosition.x += TILE_WIDTH / 2;\r\n\t\t} else {\r\n\t\t\ttilePosition.y++;\r\n\t\t\tcolumns++;\r\n\t\t\ttargetBufferPosition.x -= TILE_WIDTH / 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Scale up the top left part of the buffer 2x.\r\n */\r\nvoid Zoom(const Surface &out)\r\n{\r\n\tint viewportWidth = out.w();\r\n\tint viewportOffsetX = 0;\r\n\tif (CanPanelsCoverView()) {\r\n\t\tif (IsLeftPanelOpen()) {\r\n\t\t\tviewportWidth -= SidePanelSize.width;\r\n\t\t\tviewportOffsetX = SidePanelSize.width;\r\n\t\t} else if (IsRightPanelOpen()) {\r\n\t\t\tviewportWidth -= SidePanelSize.width;\r\n\t\t}\r\n\t}\r\n\r\n\t// We round to even for the source width and height.\r\n\t// If the width / height was odd, we copy just one extra pixel / row later on.\r\n\tconst int srcWidth = (viewportWidth + 1) / 2;\r\n\tconst int doubleableWidth = viewportWidth / 2;\r\n\tconst int srcHeight = (out.h() + 1) / 2;\r\n\tconst int doubleableHeight = out.h() / 2;\r\n\r\n\tuint8_t *src = out.at(srcWidth - 1, srcHeight - 1);\r\n\tuint8_t *dst = out.at(viewportOffsetX + viewportWidth - 1, out.h() - 1);\r\n\tconst bool oddViewportWidth = (viewportWidth % 2) == 1;\r\n\r\n\tfor (int hgt = 0; hgt < doubleableHeight; hgt++) {\r\n\t\t// Double the pixels in the line.\r\n\t\tfor (int i = 0; i < doubleableWidth; i++) {\r\n\t\t\t*dst-- = *src;\r\n\t\t\t*dst-- = *src;\r\n\t\t\t--src;\r\n\t\t}\r\n\r\n\t\t// Copy a single extra pixel if the output width is odd.\r\n\t\tif (oddViewportWidth) {\r\n\t\t\t*dst-- = *src;\r\n\t\t\t--src;\r\n\t\t}\r\n\r\n\t\t// Skip the rest of the source line.\r\n\t\tsrc -= (out.pitch() - srcWidth);\r\n\r\n\t\t// Double the line.\r\n\t\tmemcpy(dst - out.pitch() + 1, dst + 1, viewportWidth);\r\n\r\n\t\t// Skip the rest of the destination line.\r\n\t\tdst -= 2 * out.pitch() - viewportWidth;\r\n\t}\r\n\tif ((out.h() % 2) == 1) {\r\n\t\tmemcpy(dst - out.pitch() + 1, dst + 1, viewportWidth);\r\n\t}\r\n}\r\n\r\nDisplacement tileOffset;\r\nDisplacement tileShift;\r\nint tileColumns;\r\nint tileRows;\r\n\r\nvoid CalcFirstTilePosition(Point &position, Displacement &offset)\r\n{\r\n\t// Adjust by player offset and tile grid alignment\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\toffset = tileOffset;\r\n\tif (myPlayer.isWalking())\r\n\t\toffset += GetOffsetForWalking(myPlayer.AnimInfo, myPlayer._pdir, true);\r\n\r\n\tposition += tileShift;\r\n\r\n\t// Skip rendering parts covered by the panels\r\n\tif (CanPanelsCoverView() && (IsLeftPanelOpen() || IsRightPanelOpen())) {\r\n\t\tconst int multiplier = (*GetOptions().Graphics.zoom) ? 1 : 2;\r\n\t\tposition += Displacement(Direction::East) * multiplier;\r\n\t\toffset.deltaX += -TILE_WIDTH * multiplier / 2 / 2;\r\n\r\n\t\tif (IsLeftPanelOpen() && !*GetOptions().Graphics.zoom) {\r\n\t\t\toffset.deltaX += SidePanelSize.width;\r\n\t\t\t// SidePanelSize.width accounted for in Zoom()\r\n\t\t}\r\n\t}\r\n\r\n\t// Draw areas moving in and out of the screen\r\n\tif (myPlayer.isWalking()) {\r\n\t\tswitch (myPlayer._pdir) {\r\n\t\tcase Direction::North:\r\n\t\tcase Direction::NorthEast:\r\n\t\t\toffset.deltaY -= TILE_HEIGHT;\r\n\t\t\tposition += Direction::North;\r\n\t\t\tbreak;\r\n\t\tcase Direction::SouthWest:\r\n\t\tcase Direction::West:\r\n\t\t\toffset.deltaX -= TILE_WIDTH;\r\n\t\t\tposition += Direction::West;\r\n\t\t\tbreak;\r\n\t\tcase Direction::NorthWest:\r\n\t\t\toffset.deltaX -= TILE_WIDTH / 2;\r\n\t\t\toffset.deltaY -= TILE_HEIGHT / 2;\r\n\t\t\tposition += Direction::NorthWest;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Configure render and process screen rows\r\n * @param fullOut Buffer to render to\r\n * @param position First tile of view in dPiece coordinate\r\n * @param offset Amount to offset the rendering in screen space\r\n */\r\nvoid DrawGame(const Surface &fullOut, Point position, Displacement offset)\r\n{\r\n\t// Limit rendering to the view area\r\n\tconst Surface &out = !*GetOptions().Graphics.zoom\r\n\t    ? fullOut.subregionY(0, gnViewportHeight)\r\n\t    : fullOut.subregionY(0, (gnViewportHeight + 1) / 2);\r\n\r\n\tint columns = tileColumns;\r\n\tint rows = tileRows;\r\n\r\n\t// Skip rendering parts covered by the panels\r\n\tif (CanPanelsCoverView() && (IsLeftPanelOpen() || IsRightPanelOpen())) {\r\n\t\tcolumns -= (*GetOptions().Graphics.zoom) ? 2 : 4;\r\n\t}\r\n\r\n\tUpdateMissilesRendererData();\r\n\r\n\t// Draw areas moving in and out of the screen\r\n\tif (MyPlayer->isWalking()) {\r\n\t\tswitch (MyPlayer->_pdir) {\r\n\t\tcase Direction::NoDirection:\r\n\t\t\tbreak;\r\n\t\tcase Direction::North:\r\n\t\tcase Direction::South:\r\n\t\t\trows += 2;\r\n\t\t\tbreak;\r\n\t\tcase Direction::NorthEast:\r\n\t\t\tcolumns++;\r\n\t\t\trows += 2;\r\n\t\t\tbreak;\r\n\t\tcase Direction::East:\r\n\t\tcase Direction::West:\r\n\t\t\tcolumns++;\r\n\t\t\tbreak;\r\n\t\tcase Direction::SouthEast:\r\n\t\tcase Direction::SouthWest:\r\n\t\tcase Direction::NorthWest:\r\n\t\t\tcolumns++;\r\n\t\t\trows++;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n#ifdef DUN_RENDER_STATS\r\n\tDunRenderStats.clear();\r\n#endif\r\n\r\n\tLightmap lightmap = Lightmap::build(*GetOptions().Graphics.perPixelLighting, position, Point {} + offset,\r\n\t    gnScreenWidth, gnViewportHeight, rows, columns,\r\n\t    out.at(0, 0), out.pitch(), LightTables, FullyLitLightTable, FullyDarkLightTable,\r\n\t    dLight, MicroTileLen);\r\n\r\n\tDrawFloor(out, lightmap, position, Point {} + offset, rows, columns);\r\n\tDrawTileContent(out, lightmap, position, Point {} + offset, rows, columns);\r\n\tDrawOOB(out, lightmap, position, Point {} + offset, rows, columns);\r\n\r\n\tif (*GetOptions().Graphics.zoom) {\r\n\t\tZoom(fullOut.subregionY(0, gnViewportHeight));\r\n\t}\r\n\r\n#ifdef DUN_RENDER_STATS\r\n\tstd::vector<std::pair<DunRenderType, size_t>> sortedStats(DunRenderStats.begin(), DunRenderStats.end());\r\n\tc_sort(sortedStats, [](const std::pair<DunRenderType, size_t> &a, const std::pair<DunRenderType, size_t> &b) {\r\n\t\treturn a.first.maskType == b.first.maskType\r\n\t\t    ? static_cast<uint8_t>(a.first.tileType) < static_cast<uint8_t>(b.first.tileType)\r\n\t\t    : static_cast<uint8_t>(a.first.maskType) < static_cast<uint8_t>(b.first.maskType);\r\n\t});\r\n\tPoint pos { 100, 20 };\r\n\tfor (size_t i = 0; i < sortedStats.size(); ++i) {\r\n\t\tconst auto &stat = sortedStats[i];\r\n\t\tDrawString(out, StrCat(i, \".\"), Rectangle(pos, Size { 20, 16 }), { .flags = UiFlags::AlignRight });\r\n\t\tDrawString(out, MaskTypeToString(stat.first.maskType), { pos.x + 24, pos.y });\r\n\t\tDrawString(out, TileTypeToString(stat.first.tileType), { pos.x + 184, pos.y });\r\n\t\tDrawString(out, FormatInteger(stat.second), Rectangle({ pos.x + 354, pos.y }, Size(40, 16)), { .flags = UiFlags::AlignRight });\r\n\t\tpos.y += 16;\r\n\t}\r\n#endif\r\n}\r\n\r\n/**\r\n * @brief Start rendering of screen, town variation\r\n * @param out Buffer to render to\r\n * @param startPosition Center of view in dPiece coordinates\r\n */\r\nvoid DrawView(const Surface &out, Point startPosition)\r\n{\r\n#ifdef _DEBUG\r\n\tDebugCoordsMap.clear();\r\n#endif\r\n\tDisplacement offset = {};\r\n\tCalcFirstTilePosition(startPosition, offset);\r\n\tDrawGame(out, startPosition, offset);\r\n\tif (AutomapActive) {\r\n\t\tDrawAutomap(out.subregionY(0, gnViewportHeight));\r\n\t}\r\n#ifdef _DEBUG\r\n\tbool debugGridTextNeeded = IsDebugGridTextNeeded();\r\n\tif (debugGridTextNeeded || DebugGrid) {\r\n\t\t// force redrawing or debug stuff stays on panel on 640x480 resolution\r\n\t\tRedrawEverything();\r\n\t\tstd::string debugGridText;\r\n\t\tbool megaTiles = IsDebugGridInMegatiles();\r\n\r\n\t\tfor (auto [dunCoordVal, pixelCoords] : DebugCoordsMap) {\r\n\t\t\tPoint dunCoords = { dunCoordVal % MAXDUNX, dunCoordVal / MAXDUNX };\r\n\t\t\tif (megaTiles && (dunCoords.x % 2 == 1 || dunCoords.y % 2 == 1))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (megaTiles)\r\n\t\t\t\tpixelCoords += Displacement { 0, TILE_HEIGHT / 2 };\r\n\t\t\tif (*GetOptions().Graphics.zoom)\r\n\t\t\t\tpixelCoords *= 2;\r\n\t\t\tif (debugGridTextNeeded && GetDebugGridText(dunCoords, debugGridText)) {\r\n\t\t\t\tSize tileSize = { TILE_WIDTH, TILE_HEIGHT };\r\n\t\t\t\tif (*GetOptions().Graphics.zoom)\r\n\t\t\t\t\ttileSize *= 2;\r\n\t\t\t\tDrawString(out, debugGridText, { pixelCoords - Displacement { 0, tileSize.height }, tileSize },\r\n\t\t\t\t    { .flags = UiFlags::ColorRed | UiFlags::AlignCenter | UiFlags::VerticalCenter });\r\n\t\t\t}\r\n\t\t\tif (DebugGrid) {\r\n\t\t\t\tint halfTileWidth = TILE_WIDTH / 2;\r\n\t\t\t\tint halfTileHeight = TILE_HEIGHT / 2;\r\n\t\t\t\tif (*GetOptions().Graphics.zoom) {\r\n\t\t\t\t\thalfTileWidth *= 2;\r\n\t\t\t\t\thalfTileHeight *= 2;\r\n\t\t\t\t}\r\n\t\t\t\tconst Point center { pixelCoords.x + halfTileWidth, pixelCoords.y - halfTileHeight };\r\n\r\n\t\t\t\tif (megaTiles) {\r\n\t\t\t\t\thalfTileWidth *= 2;\r\n\t\t\t\t\thalfTileHeight *= 2;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst uint8_t col = PAL16_BEIGE;\r\n\t\t\t\tfor (const auto &[originX, dx] : { std::pair(center.x - halfTileWidth, 1), std::pair(center.x + halfTileWidth, -1) }) {\r\n\t\t\t\t\t// We only need to draw half of the grid cell boundaries (one triangle).\r\n\t\t\t\t\t// The other triangle will be drawn when drawing the adjacent grid cells.\r\n\t\t\t\t\tconst int dy = 1;\r\n\t\t\t\t\tPoint from { originX, center.y };\r\n\t\t\t\t\tint height = halfTileHeight;\r\n\t\t\t\t\tif (out.InBounds(from) && out.InBounds(from + Displacement { 2 * dx * height, dy * height })) {\r\n\t\t\t\t\t\tuint8_t *dst = out.at(from.x, from.y);\r\n\t\t\t\t\t\tconst int pitch = out.pitch();\r\n\t\t\t\t\t\twhile (height-- > 0) {\r\n\t\t\t\t\t\t\t*dst = col;\r\n\t\t\t\t\t\t\tdst += dx;\r\n\t\t\t\t\t\t\t*dst = col;\r\n\t\t\t\t\t\t\tdst += dx;\r\n\t\t\t\t\t\t\tdst += static_cast<ptrdiff_t>(dy * pitch);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\twhile (height-- > 0) {\r\n\t\t\t\t\t\t\tout.SetPixel(from, col);\r\n\t\t\t\t\t\t\tfrom.x += dx;\r\n\t\t\t\t\t\t\tout.SetPixel(from, col);\r\n\t\t\t\t\t\t\tfrom.x += dx;\r\n\t\t\t\t\t\t\tfrom.y += dy;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n#endif\r\n\tDrawItemNameLabels(out);\r\n\tDrawMonsterHealthBar(out);\r\n\tDrawFloatingNumbers(out, startPosition, offset);\r\n\r\n\tif (IsPlayerInStore() && !qtextflag)\r\n\t\tDrawSText(out);\r\n\tif (invflag) {\r\n\t\tDrawInv(out);\r\n\t} else if (SpellbookFlag) {\r\n\t\tDrawSpellBook(out);\r\n\t}\r\n\r\n\tDrawDurIcon(out);\r\n\r\n\tif (CharFlag) {\r\n\t\tDrawChr(out);\r\n\t} else if (QuestLogIsOpen) {\r\n\t\tDrawQuestLog(out);\r\n\t} else if (IsStashOpen) {\r\n\t\tDrawStash(out);\r\n\t}\r\n\tDrawLevelButton(out);\r\n\tif (ShowUniqueItemInfoBox) {\r\n\t\tDrawUniqueInfo(out);\r\n\t}\r\n\tif (qtextflag) {\r\n\t\tDrawQText(out);\r\n\t}\r\n\tif (SpellSelectFlag) {\r\n\t\tDrawSpellList(out);\r\n\t}\r\n\tif (DropGoldFlag) {\r\n\t\tDrawGoldSplit(out);\r\n\t}\r\n\tDrawGoldWithdraw(out);\r\n\tif (HelpFlag) {\r\n\t\tDrawHelp(out);\r\n\t}\r\n\tif (ChatLogFlag) {\r\n\t\tDrawChatLog(out);\r\n\t}\r\n\tif (MyPlayerIsDead) {\r\n\t\tRedBack(out);\r\n\t\tDrawDeathText(out);\r\n\t} else if (PauseMode != 0) {\r\n\t\tgmenu_draw_pause(out);\r\n\t}\r\n\tif (IsDiabloMsgAvailable()) {\r\n\t\tDrawDiabloMsg(out.subregionY(0, out.h() - GetMainPanel().size.height));\r\n\t}\r\n\r\n\tDrawControllerModifierHints(out);\r\n\tDrawPlrMsg(out);\r\n\tgmenu_draw(out);\r\n\tdoom_draw(out);\r\n\tDrawInfoBox(out);\r\n\tUpdateLifeManaPercent(); // Update life/mana totals before rendering any portion of the flask.\r\n\tDrawLifeFlaskUpper(out);\r\n\tDrawManaFlaskUpper(out);\r\n}\r\n\r\n/**\r\n * @brief Display the current average FPS over 1 sec\r\n */\r\nvoid DrawFPS(const Surface &out)\r\n{\r\n\tstatic int framesSinceLastUpdate = 0;\r\n\tstatic std::string_view formatted {};\r\n\r\n\tif (!frameflag || !gbActive) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tframesSinceLastUpdate++;\r\n\tconst uint32_t runtimeInMs = SDL_GetTicks();\r\n\tconst uint32_t msSinceLastUpdate = runtimeInMs - lastFpsUpdateInMs;\r\n\tif (msSinceLastUpdate >= 1000) {\r\n\t\tlastFpsUpdateInMs = runtimeInMs;\r\n\t\tconstexpr int FpsPow10 = 10;\r\n\t\tconst uint32_t fps = 1000 * FpsPow10 * framesSinceLastUpdate / msSinceLastUpdate;\r\n\t\tframesSinceLastUpdate = 0;\r\n\r\n\t\tstatic char buf[15] {};\r\n\t\tconst char *end = fps >= 100 * FpsPow10\r\n\t\t    ? BufCopy(buf, fps / FpsPow10, \" FPS\")\r\n\t\t    : BufCopy(buf, fps / FpsPow10, \".\", fps % FpsPow10, \" FPS\");\r\n\t\tformatted = { buf, static_cast<std::string_view::size_type>(end - buf) };\r\n\t};\r\n\tDrawString(out, formatted, Point { 8, 8 }, { .flags = UiFlags::ColorRed });\r\n}\r\n\r\n/**\r\n * @brief Update part of the screen from the back buffer\r\n */\r\nvoid DoBlitScreen(Rectangle area)\r\n{\r\n#ifdef DEBUG_DO_BLIT_SCREEN\r\n\tconst Surface &out = GlobalBackBuffer();\r\n\tconst uint8_t debugColor = PAL8_RED;\r\n\tDrawHorizontalLine(out, area.position, area.size.width, debugColor);\r\n\tDrawHorizontalLine(out, area.position + Displacement { 0, area.size.height - 1 }, area.size.width, debugColor);\r\n\tDrawVerticalLine(out, area.position, area.size.height, debugColor);\r\n\tDrawVerticalLine(out, area.position + Displacement { area.size.width - 1, 0 }, area.size.height, debugColor);\r\n#endif\r\n\tSDL_Rect srcRect = MakeSdlRect(area);\r\n\tSDL_Rect dstRect = MakeSdlRect(area);\r\n\tBltFast(&srcRect, &dstRect);\r\n}\r\n\r\n/**\r\n * @brief Check render pipeline and update individual screen parts\r\n * @param out Output surface.\r\n * @param dwHgt Section of screen to update from top to bottom\r\n * @param drawDesc Render info box\r\n * @param drawHp Render health bar\r\n * @param drawMana Render mana bar\r\n * @param drawSbar Render belt\r\n * @param drawBtn Render panel buttons\r\n */\r\nvoid DrawMain(int dwHgt, bool drawDesc, bool drawHp, bool drawMana, bool drawSbar, bool drawBtn)\r\n{\r\n\tif (!gbActive || RenderDirectlyToOutputSurface) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tassert(dwHgt >= 0 && dwHgt <= gnScreenHeight);\r\n\r\n\tif (dwHgt > 0) {\r\n\t\tDoBlitScreen({ { 0, 0 }, { gnScreenWidth, dwHgt } });\r\n\t}\r\n\tif (dwHgt < gnScreenHeight) {\r\n\t\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\t\tif (drawSbar) {\r\n\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 204, 5 }, { 232, 28 } });\r\n\t\t}\r\n\t\tif (drawDesc) {\r\n\t\t\tif (ChatFlag) {\r\n\t\t\t\t// When chat input is displayed, the belt is hidden and the chat moves up.\r\n\t\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 171, 6 }, { 298, 116 } });\r\n\t\t\t} else {\r\n\t\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { InfoBoxRect.position.x, InfoBoxRect.position.y }, { InfoBoxRect.size } });\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (drawMana) {\r\n\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 460, 0 }, { 88, 72 } });\r\n\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 564, 64 }, { 56, 56 } });\r\n\t\t}\r\n\t\tif (drawHp) {\r\n\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 96, 0 }, { 88, 72 } });\r\n\t\t}\r\n\t\tif (drawBtn) {\r\n\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 8, 7 }, { 74, 114 } });\r\n\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 559, 7 }, { 74, 48 } });\r\n\t\t\tif (gbIsMultiplayer) {\r\n\t\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 86, 91 }, { 34, 32 } });\r\n\t\t\t\tDoBlitScreen({ mainPanelPosition + Displacement { 526, 91 }, { 34, 32 } });\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (PrevCursorRect.size.width != 0 && PrevCursorRect.size.height != 0) {\r\n\t\t\tDoBlitScreen(PrevCursorRect);\r\n\t\t}\r\n\t\tconst Rectangle &cursorRect = GetDrawnCursor().rect;\r\n\t\tif (cursorRect.size.width != 0 && cursorRect.size.height != 0) {\r\n\t\t\tDoBlitScreen(cursorRect);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid OptionShowFPSChanged()\r\n{\r\n\tif (*GetOptions().Graphics.showFPS)\r\n\t\tEnableFrameCount();\r\n\telse\r\n\t\tframeflag = false;\r\n}\r\nconst auto OptionChangeHandlerShowFPS = (GetOptions().Graphics.showFPS.SetValueChangedCallback(OptionShowFPSChanged), true);\r\n\r\n} // namespace\r\n\r\nDisplacement GetOffsetForWalking(const AnimationInfo &animationInfo, const Direction dir, bool cameraMode /*= false*/)\r\n{\r\n\t// clang-format off\r\n\t//                                           South,        SouthWest,    West,         NorthWest,    North,        NorthEast,     East,         SouthEast,\r\n\tconstexpr Displacement MovingOffset[8]   = { {   0,  32 }, { -32,  16 }, { -64,   0 }, { -32, -16 }, {   0, -32 }, {  32, -16 },  {  64,   0 }, {  32,  16 } };\r\n\t// clang-format on\r\n\r\n\tconst uint8_t animationProgress = animationInfo.getAnimationProgress();\r\n\tDisplacement offset = MovingOffset[static_cast<size_t>(dir)];\r\n\toffset *= animationProgress;\r\n\toffset /= AnimationInfo::baseValueFraction;\r\n\r\n\tif (cameraMode) {\r\n\t\toffset = -offset;\r\n\t}\r\n\r\n\treturn offset;\r\n}\r\n\r\nvoid ClearCursor() // CODE_FIX: this was supposed to be in cursor.cpp\r\n{\r\n\tPrevCursorRect = {};\r\n}\r\n\r\nvoid ShiftGrid(Point *offset, int horizontal, int vertical)\r\n{\r\n\toffset->x += vertical + horizontal;\r\n\toffset->y += vertical - horizontal;\r\n}\r\n\r\nint RowsCoveredByPanel()\r\n{\r\n\tconst auto &mainPanelSize = GetMainPanel().size;\r\n\tif (GetScreenWidth() <= mainPanelSize.width) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tint rows = mainPanelSize.height / TILE_HEIGHT;\r\n\tif (*GetOptions().Graphics.zoom) {\r\n\t\trows /= 2;\r\n\t}\r\n\r\n\treturn rows;\r\n}\r\n\r\nvoid CalcTileOffset(int *offsetX, int *offsetY)\r\n{\r\n\tconst uint16_t screenWidth = GetScreenWidth();\r\n\tconst uint16_t viewportHeight = GetViewportHeight();\r\n\r\n\tint x;\r\n\tint y;\r\n\r\n\tif (!*GetOptions().Graphics.zoom) {\r\n\t\tx = screenWidth % TILE_WIDTH;\r\n\t\ty = viewportHeight % TILE_HEIGHT;\r\n\t} else {\r\n\t\tx = (screenWidth / 2) % TILE_WIDTH;\r\n\t\ty = (viewportHeight / 2) % TILE_HEIGHT;\r\n\t}\r\n\r\n\tif (x != 0)\r\n\t\tx = (TILE_WIDTH - x) / 2;\r\n\tif (y != 0)\r\n\t\ty = (TILE_HEIGHT - y) / 2;\r\n\r\n\t*offsetX = x;\r\n\t*offsetY = y;\r\n}\r\n\r\nvoid TilesInView(int *rcolumns, int *rrows)\r\n{\r\n\tconst uint16_t screenWidth = GetScreenWidth();\r\n\tconst uint16_t viewportHeight = GetViewportHeight();\r\n\r\n\tint columns = screenWidth / TILE_WIDTH;\r\n\tif ((screenWidth % TILE_WIDTH) != 0) {\r\n\t\tcolumns++;\r\n\t}\r\n\tint rows = viewportHeight / TILE_HEIGHT;\r\n\tif ((viewportHeight % TILE_HEIGHT) != 0) {\r\n\t\trows++;\r\n\t}\r\n\r\n\tif (*GetOptions().Graphics.zoom) {\r\n\t\t// Half the number of tiles, rounded up\r\n\t\tif ((columns & 1) != 0) {\r\n\t\t\tcolumns++;\r\n\t\t}\r\n\t\tcolumns /= 2;\r\n\t\tif ((rows & 1) != 0) {\r\n\t\t\trows++;\r\n\t\t}\r\n\t\trows /= 2;\r\n\t}\r\n\r\n\t*rcolumns = columns;\r\n\t*rrows = rows;\r\n}\r\n\r\nvoid CalcViewportGeometry()\r\n{\r\n\tconst int zoomFactor = *GetOptions().Graphics.zoom ? 2 : 1;\r\n\tconst int screenWidth = GetScreenWidth() / zoomFactor;\r\n\tconst int screenHeight = GetScreenHeight() / zoomFactor;\r\n\tconst int panelHeight = GetMainPanel().size.height / zoomFactor;\r\n\tconst int pixelsToPanel = screenHeight - panelHeight;\r\n\tPoint playerPosition { screenWidth / 2, pixelsToPanel / 2 };\r\n\r\n\tif (*GetOptions().Graphics.zoom)\r\n\t\tplayerPosition.y += TILE_HEIGHT / 4;\r\n\r\n\tconst int tilesToTop = (playerPosition.y + TILE_HEIGHT - 1) / TILE_HEIGHT;\r\n\tconst int tilesToLeft = (playerPosition.x + TILE_WIDTH - 1) / TILE_WIDTH;\r\n\r\n\t// Location of the center of the tile from which to start rendering, relative to the viewport origin\r\n\tPoint startPosition = playerPosition - Displacement { tilesToLeft * TILE_WIDTH, tilesToTop * TILE_HEIGHT };\r\n\r\n\t// Position of the tile from which to start rendering in tile space,\r\n\t// relative to the tile the player character occupies\r\n\ttileShift = { 0, 0 };\r\n\ttileShift += Displacement(Direction::North) * tilesToTop;\r\n\ttileShift += Displacement(Direction::West) * tilesToLeft;\r\n\r\n\t// The rendering loop expects to start on a row with fewer columns\r\n\tif (tilesToLeft * TILE_WIDTH >= playerPosition.x) {\r\n\t\tstartPosition += Displacement { TILE_WIDTH / 2, -TILE_HEIGHT / 2 };\r\n\t\ttileShift += Displacement(Direction::NorthEast);\r\n\t} else if (tilesToTop * TILE_HEIGHT < playerPosition.y) {\r\n\t\t// There is one row above the current row that needs to be rendered,\r\n\t\t// but we skip to the row above it because it has too many columns\r\n\t\tstartPosition += Displacement { 0, -TILE_HEIGHT };\r\n\t\ttileShift += Displacement(Direction::North);\r\n\t}\r\n\r\n\t// Location of the bottom-left corner of the bounding box around the\r\n\t// tile from which to start rendering, relative to the viewport origin\r\n\ttileOffset = { startPosition.x - TILE_WIDTH / 2, startPosition.y + TILE_HEIGHT / 2 - 1 };\r\n\r\n\t// Compute the number of rows to be rendered as well as\r\n\t// the number of columns to be rendered in the first row\r\n\tconst int viewportHeight = GetViewportHeight() / zoomFactor;\r\n\tconst Point renderStart = startPosition - Displacement { TILE_WIDTH / 2, TILE_HEIGHT / 2 };\r\n\ttileRows = (viewportHeight - renderStart.y + TILE_HEIGHT / 2 - 1) / (TILE_HEIGHT / 2);\r\n\ttileColumns = (screenWidth - renderStart.x + TILE_WIDTH - 1) / TILE_WIDTH;\r\n}\r\n\r\nPoint GetScreenPosition(Point tile)\r\n{\r\n\tPoint firstTile = ViewPosition;\r\n\tDisplacement offset = {};\r\n\tCalcFirstTilePosition(firstTile, offset);\r\n\r\n\tconst Displacement delta = firstTile - tile;\r\n\r\n\tPoint position {};\r\n\tposition += delta.worldToScreen();\r\n\tposition += offset;\r\n\treturn position;\r\n}\r\n\r\nextern SDL_Surface *PalSurface;\r\n\r\nvoid ClearScreenBuffer()\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tassert(PalSurface != nullptr);\r\n\tSDL_FillSurfaceRect(PalSurface, nullptr, 0);\r\n}\r\n\r\n#ifdef _DEBUG\r\nvoid ScrollView()\r\n{\r\n\tif (!MyPlayer->HoldItem.isEmpty())\r\n\t\treturn;\r\n\r\n\tif (MousePosition.x < 20) {\r\n\t\tif (dmaxPosition.y - 1 <= ViewPosition.y || dminPosition.x >= ViewPosition.x) {\r\n\t\t\tif (dmaxPosition.y - 1 > ViewPosition.y) {\r\n\t\t\t\tViewPosition.y++;\r\n\t\t\t}\r\n\t\t\tif (dminPosition.x < ViewPosition.x) {\r\n\t\t\t\tViewPosition.x--;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tViewPosition.y++;\r\n\t\t\tViewPosition.x--;\r\n\t\t}\r\n\t}\r\n\tif (MousePosition.x > gnScreenWidth - 20) {\r\n\t\tif (dmaxPosition.x - 1 <= ViewPosition.x || dminPosition.y >= ViewPosition.y) {\r\n\t\t\tif (dmaxPosition.x - 1 > ViewPosition.x) {\r\n\t\t\t\tViewPosition.x++;\r\n\t\t\t}\r\n\t\t\tif (dminPosition.y < ViewPosition.y) {\r\n\t\t\t\tViewPosition.y--;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tViewPosition.y--;\r\n\t\t\tViewPosition.x++;\r\n\t\t}\r\n\t}\r\n\tif (MousePosition.y < 20) {\r\n\t\tif (dminPosition.y >= ViewPosition.y || dminPosition.x >= ViewPosition.x) {\r\n\t\t\tif (dminPosition.y < ViewPosition.y) {\r\n\t\t\t\tViewPosition.y--;\r\n\t\t\t}\r\n\t\t\tif (dminPosition.x < ViewPosition.x) {\r\n\t\t\t\tViewPosition.x--;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tViewPosition.x--;\r\n\t\t\tViewPosition.y--;\r\n\t\t}\r\n\t}\r\n\tif (MousePosition.y > gnScreenHeight - 20) {\r\n\t\tif (dmaxPosition.y - 1 <= ViewPosition.y || dmaxPosition.x - 1 <= ViewPosition.x) {\r\n\t\t\tif (dmaxPosition.y - 1 > ViewPosition.y) {\r\n\t\t\t\tViewPosition.y++;\r\n\t\t\t}\r\n\t\t\tif (dmaxPosition.x - 1 > ViewPosition.x) {\r\n\t\t\t\tViewPosition.x++;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tViewPosition.x++;\r\n\t\t\tViewPosition.y++;\r\n\t\t}\r\n\t}\r\n}\r\n#endif\r\n\r\nvoid EnableFrameCount()\r\n{\r\n\tframeflag = true;\r\n\tlastFpsUpdateInMs = SDL_GetTicks();\r\n}\r\n\r\nvoid scrollrt_draw_game_screen()\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tint hgt = 0;\r\n\r\n\tif (IsRedrawEverything()) {\r\n\t\tRedrawComplete();\r\n\t\thgt = gnScreenHeight;\r\n\t}\r\n\r\n\tconst Surface &out = GlobalBackBuffer();\r\n\tUndrawCursor(out);\r\n\tDrawCursor(out);\r\n\tDrawMain(hgt, false, false, false, false, false);\r\n\r\n\tRenderPresent();\r\n}\r\n\r\nvoid DrawAndBlit()\r\n{\r\n\tif (!gbRunGame || HeadlessMode) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tint hgt = 0;\r\n\tbool drawHealth = IsRedrawComponent(PanelDrawComponent::Health);\r\n\tbool drawMana = IsRedrawComponent(PanelDrawComponent::Mana);\r\n\tbool drawControlButtons = IsRedrawComponent(PanelDrawComponent::ControlButtons);\r\n\tbool drawBelt = IsRedrawComponent(PanelDrawComponent::Belt);\r\n\tconst bool drawChatInput = ChatFlag;\r\n\tbool drawInfoBox = false;\r\n\tbool drawCtrlPan = false;\r\n\r\n\tconst Rectangle &mainPanel = GetMainPanel();\r\n\r\n\tif (gnScreenWidth > mainPanel.size.width || IsRedrawEverything()) {\r\n\t\tdrawHealth = true;\r\n\t\tdrawMana = true;\r\n\t\tdrawControlButtons = true;\r\n\t\tdrawBelt = true;\r\n\t\tdrawInfoBox = false;\r\n\t\tdrawCtrlPan = true;\r\n\t\thgt = gnScreenHeight;\r\n\t} else if (IsRedrawViewport()) {\r\n\t\tdrawInfoBox = true;\r\n\t\tdrawCtrlPan = false;\r\n\t\thgt = gnViewportHeight;\r\n\t}\r\n\r\n\tconst Surface &out = GlobalBackBuffer();\r\n\tUndrawCursor(out);\r\n\r\n\tnthread_UpdateProgressToNextGameTick();\r\n\r\n\tDrawView(out, ViewPosition);\r\n\tif (drawCtrlPan) {\r\n\t\tDrawMainPanel(out);\r\n\t}\r\n\tif (drawHealth) {\r\n\t\tDrawLifeFlaskLower(out, !drawCtrlPan);\r\n\t}\r\n\tif (drawMana) {\r\n\t\tDrawManaFlaskLower(out, !drawCtrlPan);\r\n\r\n\t\tDrawSpell(out);\r\n\t}\r\n\tif (drawControlButtons) {\r\n\t\tDrawMainPanelButtons(out);\r\n\t}\r\n\tif (drawBelt) {\r\n\t\tDrawInvBelt(out);\r\n\t}\r\n\tif (drawChatInput) {\r\n\t\tDrawChatBox(out);\r\n\t}\r\n\tDrawXPBar(out);\r\n\tif (*GetOptions().Gameplay.showHealthValues)\r\n\t\tDrawFlaskValues(out, { mainPanel.position.x + 134, mainPanel.position.y + 28 }, MyPlayer->_pHitPoints >> 6, MyPlayer->_pMaxHP >> 6);\r\n\tif (*GetOptions().Gameplay.showManaValues)\r\n\t\tDrawFlaskValues(out, { mainPanel.position.x + mainPanel.size.width - 138, mainPanel.position.y + 28 },\r\n\t\t    (HasAnyOf(InspectPlayer->_pIFlags, ItemSpecialEffect::NoMana) || MyPlayer->hasNoMana()) ? 0 : MyPlayer->_pMana >> 6,\r\n\t\t    HasAnyOf(InspectPlayer->_pIFlags, ItemSpecialEffect::NoMana) ? 0 : MyPlayer->_pMaxMana >> 6);\r\n\tif (*GetOptions().Gameplay.floatingInfoBox)\r\n\t\tDrawFloatingInfoBox(out);\r\n\r\n\tif (*GetOptions().Gameplay.showMultiplayerPartyInfo && PartySidePanelOpen)\r\n\t\tDrawPartyMemberInfoPanel(out);\r\n\r\n\tDrawCursor(out);\r\n\r\n\tDrawFPS(out);\r\n\r\n\tlua::GameDrawComplete();\r\n\r\n\tDrawMain(hgt, drawInfoBox, drawHealth, drawMana, drawBelt, drawControlButtons);\r\n\r\n#ifdef _DEBUG\r\n\tDrawConsole(out);\r\n#endif\r\n\r\n\tRedrawComplete();\r\n\tfor (const PanelDrawComponent component : enum_values<PanelDrawComponent>()) {\r\n\t\tif (IsRedrawComponent(component)) {\r\n\t\t\tRedrawComponentComplete(component);\r\n\t\t}\r\n\t}\r\n\r\n\tRenderPresent();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/scrollrt.h",
    "content": "/**\r\n * @file scrollrt.h\r\n *\r\n * Interface of functionality for rendering the dungeons, monsters and calling other render routines.\r\n */\r\n#pragma once\r\n\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/direction.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern bool AutoMapShowItems;\r\nextern bool frameflag;\r\n\r\n/**\r\n * @brief Returns the offset for the walking animation\r\n * @param animationInfo the current active walking animation\r\n * @param dir walking direction\r\n * @param cameraMode Adjusts the offset relative to the camera\r\n */\r\nDisplacement GetOffsetForWalking(const AnimationInfo &animationInfo, Direction dir, bool cameraMode = false);\r\n\r\n/**\r\n * @brief Clear cursor state\r\n */\r\nvoid ClearCursor();\r\n\r\n/**\r\n * @brief Shifting the view area along the logical grid\r\n *        Note: this won't allow you to shift between even and odd rows\r\n * @param horizontal Shift the screen left or right\r\n * @param vertical Shift the screen up or down\r\n */\r\nvoid ShiftGrid(Point *offset, int horizontal, int vertical);\r\n\r\n/**\r\n * @brief Gets the number of rows covered by the main panel\r\n */\r\nint RowsCoveredByPanel();\r\n\r\n/**\r\n * @brief Calculate the offset needed for centering tiles in view area\r\n * @param offsetX Offset in pixels\r\n * @param offsetY Offset in pixels\r\n */\r\nvoid CalcTileOffset(int *offsetX, int *offsetY);\r\n\r\n/**\r\n * @brief Calculate the needed diamond tile to cover the view area\r\n * @param columns Tiles needed per row\r\n * @param rows Both even and odd rows\r\n */\r\nvoid TilesInView(int *columns, int *rows);\r\nvoid CalcViewportGeometry();\r\n\r\n/**\r\n * @brief Calculate the screen position of a given tile\r\n * @param tile Position of a dungeon tile\r\n */\r\nPoint GetScreenPosition(Point tile);\r\n\r\n/**\r\n * @brief Render the whole screen black\r\n */\r\nvoid ClearScreenBuffer();\r\n#ifdef _DEBUG\r\n\r\n/**\r\n * @brief Scroll the screen when mouse is close to the edge\r\n */\r\nvoid ScrollView();\r\n#endif\r\n\r\n/**\r\n * @brief Initialize the FPS meter\r\n */\r\nvoid EnableFrameCount();\r\n\r\n/**\r\n * @brief Redraw screen\r\n */\r\nvoid scrollrt_draw_game_screen();\r\n\r\n/**\r\n * @brief Render the game\r\n */\r\nvoid DrawAndBlit();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/text_render.cpp",
    "content": "/**\r\n * @file text_render.cpp\r\n *\r\n * Text rendering.\r\n */\r\n#include \"text_render.hpp\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string_view>\r\n#include <utility>\r\n#include <variant>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <fmt/core.h>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/load_pcx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"engine/ticks.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteList pSPentSpn2Cels;\r\n\r\nnamespace {\r\n\r\nconstexpr char32_t ZWSP = U'\\u200B'; // Zero-width space\r\n\r\nstruct OwnedFontStack {\r\n\tOptionalOwnedClxSpriteList baseFont;\r\n\tOptionalOwnedClxSpriteList overrideFont;\r\n};\r\n\r\nstruct FontStack {\r\n\tOptionalClxSpriteList baseFont;\r\n\tOptionalClxSpriteList overrideFont;\r\n\r\n\tFontStack() = default;\r\n\r\n\texplicit FontStack(const OwnedFontStack &owned)\r\n\t{\r\n\t\tif (owned.baseFont.has_value()) baseFont.emplace(*owned.baseFont);\r\n\t\tif (owned.overrideFont.has_value()) overrideFont.emplace(*owned.overrideFont);\r\n\t}\r\n\r\n\t[[nodiscard]] bool has_value() const // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\treturn baseFont.has_value() || overrideFont.has_value();\r\n\t}\r\n\r\n\t[[nodiscard]] ClxSprite glyph(size_t i) const\r\n\t{\r\n\t\tif (overrideFont.has_value()) {\r\n\t\t\tClxSprite overrideGlyph = (*overrideFont)[i];\r\n\t\t\tif (overrideGlyph.width() != 0) return overrideGlyph;\r\n\t\t}\r\n\t\treturn (*baseFont)[i];\r\n\t}\r\n};\r\n\r\nankerl::unordered_dense::map<uint32_t, OwnedFontStack> Fonts;\r\n\r\nstd::array<int, 6> FontSizes = { 12, 24, 30, 42, 46, 22 };\r\nconstexpr std::array<int, 6> LineHeights = { 12, 26, 38, 42, 50, 22 };\r\nconstexpr int SmallFontTallLineHeight = 16;\r\nstd::array<int, 6> BaseLineOffset = { -3, -2, -3, -6, -7, 3 };\r\n\r\nstd::array<const char *, 19> ColorTranslations = {\r\n\t\"fonts\\\\goldui.trn\",\r\n\t\"fonts\\\\grayui.trn\",\r\n\t\"fonts\\\\golduis.trn\",\r\n\t\"fonts\\\\grayuis.trn\",\r\n\r\n\tnullptr, // ColorDialogWhite\r\n\tnullptr, // ColorDialogRed\r\n\t\"fonts\\\\yellow.trn\",\r\n\r\n\tnullptr,\r\n\t\"fonts\\\\black.trn\",\r\n\r\n\t\"fonts\\\\white.trn\",\r\n\t\"fonts\\\\whitegold.trn\",\r\n\t\"fonts\\\\red.trn\",\r\n\t\"fonts\\\\blue.trn\",\r\n\t\"fonts\\\\orange.trn\",\r\n\r\n\t\"fonts\\\\buttonface.trn\",\r\n\t\"fonts\\\\buttonpushed.trn\",\r\n\t\"fonts\\\\gamedialogwhite.trn\",\r\n\t\"fonts\\\\gamedialogyellow.trn\",\r\n\t\"fonts\\\\gamedialogred.trn\",\r\n};\r\n\r\nstd::array<std::optional<std::array<uint8_t, 256>>, 19> ColorTranslationsData;\r\n\r\ntext_color GetColorFromFlags(UiFlags flags)\r\n{\r\n\tif (HasAnyOf(flags, UiFlags::ColorWhite))\r\n\t\treturn ColorWhite;\r\n\tif (HasAnyOf(flags, UiFlags::ColorBlue))\r\n\t\treturn ColorBlue;\r\n\tif (HasAnyOf(flags, UiFlags::ColorOrange))\r\n\t\treturn ColorOrange;\r\n\tif (HasAnyOf(flags, UiFlags::ColorRed))\r\n\t\treturn ColorRed;\r\n\tif (HasAnyOf(flags, UiFlags::ColorBlack))\r\n\t\treturn ColorBlack;\r\n\tif (HasAnyOf(flags, UiFlags::ColorGold))\r\n\t\treturn ColorGold;\r\n\tif (HasAnyOf(flags, UiFlags::ColorUiGold))\r\n\t\treturn ColorUiGold;\r\n\tif (HasAnyOf(flags, UiFlags::ColorUiSilver))\r\n\t\treturn ColorUiSilver;\r\n\tif (HasAnyOf(flags, UiFlags::ColorUiGoldDark))\r\n\t\treturn ColorUiGoldDark;\r\n\tif (HasAnyOf(flags, UiFlags::ColorUiSilverDark))\r\n\t\treturn ColorUiSilverDark;\r\n\tif (HasAnyOf(flags, UiFlags::ColorDialogWhite))\r\n\t\treturn gbRunGame ? ColorInGameDialogWhite : ColorDialogWhite;\r\n\tif (HasAnyOf(flags, UiFlags::ColorDialogYellow))\r\n\t\treturn ColorInGameDialogYellow;\r\n\tif (HasAnyOf(flags, UiFlags::ColorDialogRed))\r\n\t\treturn ColorInGameDialogRed;\r\n\tif (HasAnyOf(flags, UiFlags::ColorYellow))\r\n\t\treturn ColorYellow;\r\n\tif (HasAnyOf(flags, UiFlags::ColorButtonface))\r\n\t\treturn ColorButtonface;\r\n\tif (HasAnyOf(flags, UiFlags::ColorButtonpushed))\r\n\t\treturn ColorButtonpushed;\r\n\r\n\treturn ColorWhitegold;\r\n}\r\n\r\nuint16_t GetUnicodeRow(char32_t codePoint)\r\n{\r\n\treturn static_cast<uint32_t>(codePoint) >> 8;\r\n}\r\n\r\nbool IsCJK(uint16_t row)\r\n{\r\n\treturn row >= 0x30 && row <= 0x9f;\r\n}\r\n\r\nbool IsHangul(uint16_t row)\r\n{\r\n\treturn row >= 0xac && row <= 0xd7;\r\n}\r\n\r\nbool IsSmallFontTallRow(uint16_t row)\r\n{\r\n\treturn IsCJK(row) || IsHangul(row);\r\n}\r\n\r\nvoid GetFontPath(GameFontTables size, uint16_t row, std::string_view ext, char *out)\r\n{\r\n\t*BufCopy(out, \"fonts\\\\\", FontSizes[size], \"-\", AsHexPad2(row), ext) = '\\0';\r\n}\r\n\r\nvoid GetFontPath(std::string_view language_code, GameFontTables size, uint16_t row, std::string_view ext, char *out)\r\n{\r\n\t*BufCopy(out, \"fonts\\\\\", language_code, \"\\\\\", FontSizes[size], \"-\", AsHexPad2(row), ext) = '\\0';\r\n}\r\n\r\nuint32_t GetFontId(GameFontTables size, uint16_t row)\r\n{\r\n\treturn (size << 16) | row;\r\n}\r\n\r\nFontStack LoadFont(GameFontTables size, text_color color, uint16_t row)\r\n{\r\n\tif (ColorTranslations[color] != nullptr && !ColorTranslationsData[color]) {\r\n\t\tColorTranslationsData[color].emplace();\r\n\t\tLoadFileInMem(ColorTranslations[color], *ColorTranslationsData[color]);\r\n\t}\r\n\r\n\tconst uint32_t fontId = GetFontId(size, row);\r\n\tauto hotFont = Fonts.find(fontId);\r\n\tif (hotFont != Fonts.end()) {\r\n\t\treturn FontStack(hotFont->second);\r\n\t}\r\n\r\n\tOwnedFontStack &font = Fonts[fontId];\r\n\tchar path[32];\r\n\r\n\t// Load language-specific glyphs:\r\n\tconst std::string_view languageCode = GetLanguageCode();\r\n\tconst std::string_view lang = languageCode.substr(0, 2);\r\n\tif (lang == \"zh\" || lang == \"ja\" || lang == \"ko\"\r\n\t    || (lang == \"tr\" && row == 0)) {\r\n\t\tGetFontPath(languageCode, size, row, \".clx\", &path[0]);\r\n\t\tfont.overrideFont = LoadOptionalClx(path);\r\n\t}\r\n\r\n\t// Load the base glyphs:\r\n\tGetFontPath(size, row, \".clx\", &path[0]);\r\n\tfont.baseFont = LoadOptionalClx(path);\r\n\r\n#ifndef UNPACKED_MPQS\r\n\tif (!font.baseFont.has_value()) {\r\n\t\t// Could be an old devilutionx.mpq or fonts.mpq with PCX instead of CLX.\r\n\t\t//\r\n\t\t// We'll show an error elsewhere (in `CheckArchivesUpToDate`) and we need to load\r\n\t\t// the font files to display it.\r\n\t\tchar pcxPath[32];\r\n\t\tGetFontPath(size, row, \"\", &pcxPath[0]);\r\n\t\tfont.baseFont = LoadPcxSpriteList(pcxPath, /*numFramesOrFrameHeight=*/256, /*transparentColor=*/1);\r\n\t}\r\n#endif\r\n\r\n\tif (!font.baseFont.has_value()) {\r\n\t\tLogError(\"Error loading font: {}\", path);\r\n\t}\r\n\r\n\treturn FontStack(font);\r\n}\r\n\r\nclass CurrentFont {\r\npublic:\r\n\tFontStack fontStack;\r\n\r\n\t[[nodiscard]] ClxSprite glyph(size_t i) const\r\n\t{\r\n\t\treturn fontStack.glyph(i);\r\n\t}\r\n\r\n\tbool load(GameFontTables size, text_color color, char32_t next)\r\n\t{\r\n\t\tconst uint32_t unicodeRow = GetUnicodeRow(next);\r\n\t\tif (unicodeRow == currentUnicodeRow_ && hasAttemptedLoad_) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tfontStack = LoadFont(size, color, unicodeRow);\r\n\t\thasAttemptedLoad_ = true;\r\n\t\tcurrentUnicodeRow_ = unicodeRow;\r\n\r\n\t\treturn fontStack.has_value();\r\n\t}\r\n\r\n\tvoid clear()\r\n\t{\r\n\t\thasAttemptedLoad_ = false;\r\n\t}\r\n\r\nprivate:\r\n\tbool hasAttemptedLoad_ = false;\r\n\tuint32_t currentUnicodeRow_ = 0;\r\n};\r\n\r\nvoid DrawFont(const Surface &out, Point position, ClxSprite glyph, text_color color, bool outline)\r\n{\r\n\tif (outline) {\r\n\t\tClxDrawOutlineSkipColorZero(out, 0, { position.x, position.y + glyph.height() - 1 }, glyph);\r\n\t}\r\n\tif (ColorTranslationsData[color]) {\r\n\t\tRenderClxSpriteWithTRN(out, glyph, position, ColorTranslationsData[color]->data());\r\n\t} else {\r\n\t\tRenderClxSprite(out, glyph, position);\r\n\t}\r\n}\r\n\r\nbool IsFullWidthPunct(char32_t c)\r\n{\r\n\treturn IsAnyOf(c, U'，', U'、', U'。', U'？', U'！');\r\n}\r\n\r\nbool IsBreakAllowed(char32_t codepoint, char32_t nextCodepoint)\r\n{\r\n\treturn IsFullWidthPunct(codepoint) && !IsFullWidthPunct(nextCodepoint);\r\n}\r\n\r\nstd::size_t CountNewlines(std::string_view fmt, const DrawStringFormatArg *args, std::size_t argsLen)\r\n{\r\n\tstd::size_t result = c_count(fmt, '\\n');\r\n\tfor (std::size_t i = 0; i < argsLen; ++i) {\r\n\t\tif (std::holds_alternative<std::string_view>(args[i].value()))\r\n\t\t\tresult += c_count(args[i].GetFormatted(), '\\n');\r\n\t}\r\n\treturn result;\r\n}\r\n\r\nclass FmtArgParser {\r\npublic:\r\n\tFmtArgParser(std::string_view fmt,\r\n\t    DrawStringFormatArg *args,\r\n\t    size_t len,\r\n\t    size_t offset = 0)\r\n\t    : fmt_(fmt)\r\n\t    , args_(args)\r\n\t    , len_(len)\r\n\t    , next_(offset)\r\n\t{\r\n\t}\r\n\r\n\tstd::optional<std::size_t> operator()(std::string_view &rest)\r\n\t{\r\n\t\tstd::optional<std::size_t> result;\r\n\t\tif (rest[0] != '{')\r\n\t\t\treturn result;\r\n\r\n\t\tconst std::size_t closingBracePos = rest.find('}', 1);\r\n\t\tif (closingBracePos == std::string_view::npos) {\r\n\t\t\tLogError(\"Unclosed format argument: {}\", fmt_);\r\n\t\t\treturn result;\r\n\t\t}\r\n\r\n\t\tstd::size_t fmtLen;\r\n\t\tbool positional;\r\n\t\tif (closingBracePos == 2 && rest[1] >= '0' && rest[1] <= '9') {\r\n\t\t\tresult = rest[1] - '0';\r\n\t\t\tfmtLen = 3;\r\n\t\t\tpositional = true;\r\n\t\t} else {\r\n\t\t\tresult = next_++;\r\n\t\t\tfmtLen = closingBracePos + 1;\r\n\t\t\tpositional = false;\r\n\t\t}\r\n\t\tif (!result) {\r\n\t\t\tLogError(\"Unsupported format argument: {}\", rest);\r\n\t\t} else if (*result >= len_) {\r\n\t\t\tLogError(\"Not enough format arguments, {} given for: {}\", len_, fmt_);\r\n\t\t\tresult = std::nullopt;\r\n\t\t} else {\r\n\t\t\tif (!args_[*result].HasFormatted()) {\r\n\t\t\t\tconst auto fmtStr = positional ? \"{}\" : std::string_view(rest.data(), fmtLen);\r\n\t\t\t\targs_[*result].SetFormatted(fmt::format(fmt::runtime(fmtStr), std::get<int>(args_[*result].value())));\r\n\t\t\t}\r\n\t\t\trest.remove_prefix(fmtLen);\r\n\t\t}\r\n\t\treturn result;\r\n\t}\r\n\r\n\tsize_t offset() const\r\n\t{\r\n\t\treturn next_;\r\n\t}\r\n\r\nprivate:\r\n\tstd::string_view fmt_;\r\n\tDrawStringFormatArg *args_;\r\n\tstd::size_t len_;\r\n\tstd::size_t next_;\r\n};\r\n\r\nbool ContainsSmallFontTallCodepoints(std::string_view text)\r\n{\r\n\twhile (!text.empty()) {\r\n\t\tconst char32_t next = ConsumeFirstUtf8CodePoint(&text);\r\n\t\tif (next == Utf8DecodeError)\r\n\t\t\tbreak;\r\n\t\tif (next == ZWSP)\r\n\t\t\tcontinue;\r\n\t\tif (IsSmallFontTallRow(GetUnicodeRow(next)))\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nint GetLineHeight(std::string_view fmt, DrawStringFormatArg *args, std::size_t argsLen, GameFontTables fontIndex)\r\n{\r\n\tconstexpr std::array<int, 6> LineHeights = { 12, 26, 38, 42, 50, 22 };\r\n\tif (fontIndex == GameFont12 && IsSmallFontTall()) {\r\n\t\tFmtArgParser fmtArgParser { fmt, args, argsLen };\r\n\t\tstd::string_view rest = fmt;\r\n\t\twhile (!rest.empty()) {\r\n\t\t\tconst std::optional<std::size_t> fmtArgPos = fmtArgParser(rest);\r\n\t\t\tif (fmtArgPos) {\r\n\t\t\t\tif (ContainsSmallFontTallCodepoints(args[*fmtArgPos].GetFormatted())) {\r\n\t\t\t\t\treturn SmallFontTallLineHeight;\r\n\t\t\t\t}\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst char32_t cp = ConsumeFirstUtf8CodePoint(&rest);\r\n\t\t\tif (cp == Utf8DecodeError) break;\r\n\t\t\tif (cp == ZWSP) continue;\r\n\t\t\tif (IsSmallFontTallRow(GetUnicodeRow(cp))) return SmallFontTallLineHeight;\r\n\t\t}\r\n\t}\r\n\treturn LineHeights[fontIndex];\r\n}\r\n\r\nSurface ClipSurface(const Surface &out, Rectangle rect)\r\n{\r\n\tif (rect.size.height == 0) {\r\n\t\treturn out.subregion(0, 0, std::min(rect.position.x + rect.size.width, out.w()), out.h());\r\n\t}\r\n\treturn out.subregion(0, 0,\r\n\t    std::min(rect.position.x + rect.size.width, out.w()),\r\n\t    std::min(rect.position.y + rect.size.height, out.h()));\r\n}\r\n\r\nint AdjustSpacingToFitHorizontally(int &lineWidth, int maxSpacing, int charactersInLine, int availableWidth)\r\n{\r\n\tif (lineWidth <= availableWidth || charactersInLine < 2)\r\n\t\treturn maxSpacing;\r\n\r\n\tconst int overhang = lineWidth - availableWidth;\r\n\tconst int spacingRedux = (overhang + charactersInLine - 2) / (charactersInLine - 1);\r\n\tlineWidth -= spacingRedux * (charactersInLine - 1);\r\n\treturn maxSpacing - spacingRedux;\r\n}\r\n\r\nvoid MaybeWrap(Point &characterPosition, int characterWidth, int rightMargin, int initialX, int lineHeight)\r\n{\r\n\tif (characterPosition.x + characterWidth > rightMargin) {\r\n\t\tcharacterPosition.x = initialX;\r\n\t\tcharacterPosition.y += lineHeight;\r\n\t}\r\n}\r\n\r\nint GetLineStartX(UiFlags flags, const Rectangle &rect, int lineWidth)\r\n{\r\n\tif (HasAnyOf(flags, UiFlags::AlignCenter)) {\r\n\t\treturn std::max(rect.position.x, rect.position.x + (rect.size.width - lineWidth) / 2);\r\n\t}\r\n\tif (HasAnyOf(flags, UiFlags::AlignRight))\r\n\t\treturn rect.position.x + rect.size.width - lineWidth;\r\n\treturn rect.position.x;\r\n}\r\n\r\nvoid DrawLine(\r\n    const Surface &out,\r\n    std::string_view text,\r\n    Point characterPosition,\r\n    Rectangle rect,\r\n    UiFlags flags,\r\n    int curSpacing,\r\n    GameFontTables size,\r\n    text_color color,\r\n    bool outline,\r\n    const TextRenderOptions &opts,\r\n    size_t lineStartPos,\r\n    int totalWidth)\r\n{\r\n\tCurrentFont currentFont;\r\n\r\n\tstd::string_view lineCopy = text;\r\n\r\n\tsize_t currentPos = 0;\r\n\r\n\tsize_t cpLen;\r\n\r\n\tconst auto maybeDrawCursor = [&]() {\r\n\t\tconst auto byteIndex = static_cast<int>(lineStartPos + currentPos);\r\n\t\tPoint position = characterPosition;\r\n\t\tif (opts.cursorPosition == byteIndex) {\r\n\t\t\tif (GetAnimationFrame(2, 500) != 0 || opts.cursorStatic) {\r\n\t\t\t\tFontStack baseFont = LoadFont(size, color, 0);\r\n\t\t\t\tif (baseFont.has_value()) {\r\n\t\t\t\t\tDrawFont(out, position, baseFont.glyph('|'), color, outline);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (opts.renderedCursorPositionOut != nullptr) {\r\n\t\t\t\t*opts.renderedCursorPositionOut = position;\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n\r\n\t// Start from the beginning of the line\r\n\tcharacterPosition.x = GetLineStartX(flags, rect, totalWidth);\r\n\r\n\twhile (!lineCopy.empty()) {\r\n\t\tchar32_t c = DecodeFirstUtf8CodePoint(lineCopy, &cpLen);\r\n\t\tif (c == Utf8DecodeError) break;\r\n\t\tif (c == ZWSP) {\r\n\t\t\tcurrentPos += cpLen;\r\n\t\t\tlineCopy.remove_prefix(cpLen);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (!currentFont.load(size, color, c)) {\r\n\t\t\tc = U'?';\r\n\t\t\tif (!currentFont.load(size, color, c)) {\r\n\t\t\t\tapp_fatal(\"Missing fonts\");\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst uint8_t frame = c & 0xFF;\r\n\r\n\t\tconst ClxSprite glyph = currentFont.glyph(frame);\r\n\t\tconst int charWidth = glyph.width();\r\n\r\n\t\tconst auto byteIndex = static_cast<int>(lineStartPos + currentPos);\r\n\r\n\t\t// Draw highlight\r\n\t\tif (byteIndex >= opts.highlightRange.begin && byteIndex < opts.highlightRange.end) {\r\n\t\t\tconst bool lastInRange = static_cast<int>(byteIndex + cpLen) == opts.highlightRange.end;\r\n\t\t\tFillRect(out, characterPosition.x, characterPosition.y,\r\n\t\t\t    glyph.width() + (lastInRange ? 0 : curSpacing), glyph.height(),\r\n\t\t\t    opts.highlightColor);\r\n\t\t}\r\n\r\n\t\tDrawFont(out, characterPosition, glyph, color, outline);\r\n\t\tmaybeDrawCursor();\r\n\r\n\t\t// Move to the next position\r\n\t\tcharacterPosition.x += charWidth + curSpacing;\r\n\t\tcurrentPos += cpLen;\r\n\t\tlineCopy.remove_prefix(cpLen);\r\n\t}\r\n\tassert(currentPos == text.size());\r\n\tmaybeDrawCursor();\r\n}\r\n\r\nuint32_t DoDrawString(const Surface &out, std::string_view text, Rectangle rect, Point &characterPosition,\r\n    int lineWidth, int charactersInLine, int rightMargin, int bottomMargin, GameFontTables size, text_color color, bool outline,\r\n    TextRenderOptions &opts)\r\n{\r\n\tCurrentFont currentFont;\r\n\tint curSpacing = opts.spacing;\r\n\tif (HasAnyOf(opts.flags, UiFlags::KerningFitSpacing)) {\r\n\t\tcurSpacing = AdjustSpacingToFitHorizontally(lineWidth, opts.spacing, charactersInLine, rect.size.width);\r\n\t\tif (curSpacing != opts.spacing && HasAnyOf(opts.flags, UiFlags::AlignCenter | UiFlags::AlignRight)) {\r\n\t\t\tconst int adjustedLineWidth = GetLineWidth(text, size, curSpacing, &charactersInLine);\r\n\t\t\tcharacterPosition.x = GetLineStartX(opts.flags, rect, adjustedLineWidth);\r\n\t\t}\r\n\t}\r\n\r\n\tchar32_t next;\r\n\tstd::string_view remaining = text;\r\n\tsize_t cpLen;\r\n\r\n\t// Track line boundaries\r\n\tsize_t lineStartPos = 0;\r\n\tsize_t lineEndPos = 0;\r\n\r\n\tconst auto drawLine = [&]() {\r\n\t\tstd::string_view lineText = text.substr(lineStartPos, lineEndPos - lineStartPos);\r\n\t\tif (!lineText.empty()) {\r\n\t\t\tDrawLine(\r\n\t\t\t    out,\r\n\t\t\t    lineText,\r\n\t\t\t    characterPosition,\r\n\t\t\t    rect,\r\n\t\t\t    opts.flags,\r\n\t\t\t    curSpacing,\r\n\t\t\t    size,\r\n\t\t\t    color,\r\n\t\t\t    outline,\r\n\t\t\t    opts,\r\n\t\t\t    lineStartPos,\r\n\t\t\t    lineWidth);\r\n\t\t}\r\n\t};\r\n\r\n\tfor (; !remaining.empty() && remaining[0] != '\\0'\r\n\t     && (next = DecodeFirstUtf8CodePoint(remaining, &cpLen)) != Utf8DecodeError;\r\n\t     remaining.remove_prefix(cpLen)) {\r\n\t\tif (next == ZWSP)\r\n\t\t\tcontinue;\r\n\r\n\t\tif (!currentFont.load(size, color, next)) {\r\n\t\t\tnext = U'?';\r\n\t\t\tif (!currentFont.load(size, color, next)) {\r\n\t\t\t\tapp_fatal(\"Missing fonts\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst uint8_t frame = next & 0xFF;\r\n\t\tconst uint16_t width = currentFont.glyph(frame).width();\r\n\t\tif (next == U'\\n' || characterPosition.x + width > rightMargin) {\r\n\t\t\tlineEndPos = text.size() - remaining.size();\r\n\r\n\t\t\tdrawLine();\r\n\r\n\t\t\tconst int nextLineY = characterPosition.y + opts.lineHeight;\r\n\t\t\tif (nextLineY >= bottomMargin)\r\n\t\t\t\tbreak;\r\n\t\t\tcharacterPosition.y = nextLineY;\r\n\r\n\t\t\tif (HasAnyOf(opts.flags, UiFlags::KerningFitSpacing)) {\r\n\t\t\t\tint nextLineWidth = GetLineWidth(remaining.substr(cpLen), size, opts.spacing, &charactersInLine);\r\n\t\t\t\tcurSpacing = AdjustSpacingToFitHorizontally(nextLineWidth, opts.spacing, charactersInLine, rect.size.width);\r\n\t\t\t}\r\n\r\n\t\t\tif (HasAnyOf(opts.flags, UiFlags::AlignCenter | UiFlags::AlignRight)) {\r\n\t\t\t\tlineWidth = width;\r\n\t\t\t\tif (remaining.size() > cpLen)\r\n\t\t\t\t\tlineWidth += curSpacing + GetLineWidth(remaining.substr(cpLen), size, curSpacing);\r\n\t\t\t}\r\n\t\t\tcharacterPosition.x = GetLineStartX(opts.flags, rect, lineWidth);\r\n\r\n\t\t\t// Start a new line\r\n\t\t\tlineStartPos = next == U'\\n' ? (text.size() - remaining.size() + cpLen) : (text.size() - remaining.size());\r\n\t\t\tlineEndPos = lineStartPos;\r\n\r\n\t\t\tif (next == U'\\n')\r\n\t\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Update end position as we add characters\r\n\t\tlineEndPos = text.size() - remaining.size() + cpLen;\r\n\r\n\t\t// Update position for the next character\r\n\t\tcharacterPosition.x += width + curSpacing;\r\n\t}\r\n\r\n\t// Draw any remaining characters in the last line\r\n\tif (lineStartPos < lineEndPos) {\r\n\t\tdrawLine();\r\n\t}\r\n\r\n\treturn static_cast<uint32_t>(remaining.data() - text.data());\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadSmallSelectionSpinner()\r\n{\r\n\tpSPentSpn2Cels = LoadCel(\"data\\\\pentspn2\", 12);\r\n}\r\n\r\nvoid UnloadFonts()\r\n{\r\n\tFonts.clear();\r\n}\r\n\r\nint GetLineWidth(std::string_view text, GameFontTables size, int spacing, int *charactersInLine)\r\n{\r\n\tint lineWidth = 0;\r\n\tCurrentFont currentFont;\r\n\tuint32_t codepoints = 0;\r\n\tchar32_t next;\r\n\twhile (!text.empty()) {\r\n\t\tnext = ConsumeFirstUtf8CodePoint(&text);\r\n\t\tif (next == Utf8DecodeError)\r\n\t\t\tbreak;\r\n\t\tif (next == ZWSP)\r\n\t\t\tcontinue;\r\n\r\n\t\tif (next == U'\\n')\r\n\t\t\tbreak;\r\n\r\n\t\tif (!currentFont.load(size, text_color::ColorDialogWhite, next)) {\r\n\t\t\tnext = U'?';\r\n\t\t\tif (!currentFont.load(size, text_color::ColorDialogWhite, next)) {\r\n\t\t\t\tapp_fatal(\"Missing fonts\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst uint8_t frame = next & 0xFF;\r\n\t\tlineWidth += currentFont.glyph(frame).width() + spacing;\r\n\t\t++codepoints;\r\n\t}\r\n\tif (charactersInLine != nullptr)\r\n\t\t*charactersInLine = codepoints;\r\n\r\n\treturn lineWidth != 0 ? (lineWidth - spacing) : 0;\r\n}\r\n\r\nbool IsConsumed(std::string_view s) { return s.empty() || s[0] == '\\0'; };\r\n\r\nint GetLineWidth(std::string_view fmt, DrawStringFormatArg *args, std::size_t argsLen, size_t argsOffset, GameFontTables size, int spacing, int *charactersInLine,\r\n    std::optional<size_t> firstArgOffset)\r\n{\r\n\tint lineWidth = 0;\r\n\tCurrentFont currentFont;\r\n\r\n\tuint32_t codepoints = 0;\r\n\tchar32_t prev = U'\\0';\r\n\tchar32_t next;\r\n\tstd::string_view remaining = fmt;\r\n\tFmtArgParser fmtArgParser { fmt, args, argsLen, argsOffset };\r\n\tsize_t cpLen;\r\n\r\n\t// The current formatted argument value being processed.\r\n\tstd::string_view curFormatted;\r\n\r\n\t// The string that we're currently processing: either `remaining` or `curFormatted`.\r\n\tstd::string_view *str;\r\n\r\n\tif (firstArgOffset.has_value()) {\r\n\t\tcurFormatted = args[argsOffset - 1].GetFormatted().substr(*firstArgOffset);\r\n\t}\r\n\r\n\tfor (; !(IsConsumed(curFormatted) && IsConsumed(remaining));\r\n\t     str->remove_prefix(cpLen), prev = next) {\r\n\t\tconst bool isProcessingFormatArgValue = !IsConsumed(curFormatted);\r\n\t\tstr = isProcessingFormatArgValue ? &curFormatted : &remaining;\r\n\t\tnext = DecodeFirstUtf8CodePoint(*str, &cpLen);\r\n\t\tif (next == Utf8DecodeError) break;\r\n\r\n\t\t// {{ and }} escapes in fmt.\r\n\t\tif (!isProcessingFormatArgValue && (prev == U'{' || prev == U'}') && prev == next) continue;\r\n\t\t// ZWSP are line-breaking opportunities that can otherwise be skipped for rendering as they have 0-width.\r\n\t\tif (next == ZWSP) continue;\r\n\t\tif (next == U'\\n') break;\r\n\r\n\t\tif (!isProcessingFormatArgValue) {\r\n\t\t\tconst std::optional<std::size_t> fmtArgPos = fmtArgParser(*str);\r\n\t\t\tif (fmtArgPos.has_value()) {\r\n\t\t\t\t// `fmtArgParser` has already consumed `*str`. Ensure the loop doesn't consume any more.\r\n\t\t\t\tcpLen = 0;\r\n\t\t\t\t// The loop assigns `prev = next`.\r\n\t\t\t\t// We reset it to U'\\0' to ensure that {{ and }} escapes are not processed accross\r\n\t\t\t\t// the boundary of the format string and a formatted value.\r\n\t\t\t\tnext = U'\\0';\r\n\t\t\t\tcurrentFont.clear();\r\n\t\t\t\tconst DrawStringFormatArg &arg = args[*fmtArgPos];\r\n\t\t\t\tcurFormatted = arg.GetFormatted();\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!currentFont.load(size, text_color::ColorDialogWhite, next)) {\r\n\t\t\tnext = U'?';\r\n\t\t\tif (!currentFont.load(size, text_color::ColorDialogWhite, next)) {\r\n\t\t\t\tapp_fatal(\"Missing fonts\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst uint8_t frame = next & 0xFF;\r\n\t\tlineWidth += currentFont.glyph(frame).width() + spacing;\r\n\t\t++codepoints;\r\n\t}\r\n\tif (charactersInLine != nullptr)\r\n\t\t*charactersInLine = codepoints;\r\n\r\n\treturn lineWidth != 0 ? (lineWidth - spacing) : 0;\r\n}\r\n\r\nint GetLineHeight(std::string_view text, GameFontTables fontIndex)\r\n{\r\n\tif (fontIndex == GameFont12 && IsSmallFontTall() && ContainsSmallFontTallCodepoints(text)) {\r\n\t\treturn SmallFontTallLineHeight;\r\n\t}\r\n\treturn LineHeights[fontIndex];\r\n}\r\n\r\nstd::string WordWrapString(std::string_view text, unsigned width, GameFontTables size, int spacing)\r\n{\r\n\tstd::string output;\r\n\tif (text.empty() || text[0] == '\\0')\r\n\t\treturn output;\r\n\r\n\toutput.reserve(text.size());\r\n\tconst char *begin = text.data();\r\n\tconst char *processedEnd = text.data();\r\n\tstd::string_view::size_type lastBreakablePos = std::string_view::npos;\r\n\tstd::size_t lastBreakableLen = 0;\r\n\tunsigned lineWidth = 0;\r\n\tCurrentFont currentFont;\r\n\r\n\tchar32_t codepoint = U'\\0'; // the current codepoint\r\n\tchar32_t nextCodepoint;     // the next codepoint\r\n\tstd::size_t nextCodepointLen;\r\n\tstd::string_view remaining = text;\r\n\tnextCodepoint = DecodeFirstUtf8CodePoint(remaining, &nextCodepointLen);\r\n\tdo {\r\n\t\tcodepoint = nextCodepoint;\r\n\t\tconst std::size_t codepointLen = nextCodepointLen;\r\n\t\tif (codepoint == Utf8DecodeError)\r\n\t\t\tbreak;\r\n\t\tremaining.remove_prefix(codepointLen);\r\n\t\tnextCodepoint = !remaining.empty() ? DecodeFirstUtf8CodePoint(remaining, &nextCodepointLen) : U'\\0';\r\n\r\n\t\tif (codepoint == U'\\n') { // Existing line break, scan next line\r\n\t\t\tlastBreakablePos = std::string_view::npos;\r\n\t\t\tlineWidth = 0;\r\n\t\t\toutput.append(processedEnd, remaining.data());\r\n\t\t\tprocessedEnd = remaining.data();\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (codepoint != ZWSP) {\r\n\t\t\tconst uint8_t frame = codepoint & 0xFF;\r\n\t\t\tif (!currentFont.load(size, text_color::ColorDialogWhite, codepoint)) {\r\n\t\t\t\tcodepoint = U'?';\r\n\t\t\t\tif (!currentFont.load(size, text_color::ColorDialogWhite, codepoint)) {\r\n\t\t\t\t\tapp_fatal(\"Missing fonts\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tlineWidth += currentFont.glyph(frame).width() + spacing;\r\n\t\t}\r\n\r\n\t\tif (IsBreakableWhitespace(codepoint)) {\r\n\t\t\tlastBreakablePos = remaining.data() - begin - codepointLen;\r\n\t\t\tlastBreakableLen = codepointLen;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (lineWidth - spacing <= width) {\r\n\t\t\tif (IsBreakAllowed(codepoint, nextCodepoint)) {\r\n\t\t\t\tlastBreakablePos = remaining.data() - begin;\r\n\t\t\t\tlastBreakableLen = 0;\r\n\t\t\t}\r\n\r\n\t\t\tcontinue; // String is still within the limit, continue to the next symbol\r\n\t\t}\r\n\r\n\t\tif (lastBreakablePos == std::string_view::npos) { // Single word longer than width\r\n\t\t\tlastBreakablePos = remaining.data() - begin - codepointLen;\r\n\t\t\tlastBreakableLen = 0;\r\n\t\t}\r\n\r\n\t\t// Break line and continue to next line\r\n\t\tconst char *end = &text[lastBreakablePos];\r\n\t\toutput.append(processedEnd, end);\r\n\t\toutput += '\\n';\r\n\r\n\t\t// Restart from the beginning of the new line.\r\n\t\tremaining = text.substr(lastBreakablePos + lastBreakableLen);\r\n\t\tprocessedEnd = remaining.data();\r\n\t\tlastBreakablePos = std::string_view::npos;\r\n\t\tlineWidth = 0;\r\n\t\tnextCodepoint = !remaining.empty() ? DecodeFirstUtf8CodePoint(remaining, &nextCodepointLen) : U'\\0';\r\n\t} while (!remaining.empty() && remaining[0] != '\\0');\r\n\toutput.append(processedEnd, remaining.data());\r\n\treturn output;\r\n}\r\n\r\n/**\r\n * @todo replace Rectangle with cropped Surface\r\n */\r\nuint32_t DrawString(const Surface &out, std::string_view text, const Rectangle &rect, TextRenderOptions opts)\r\n{\r\n\tconst GameFontTables size = GetFontSizeFromUiFlags(opts.flags);\r\n\tconst text_color color = GetColorFromFlags(opts.flags);\r\n\r\n\tint charactersInLine = 0;\r\n\tint lineWidth = 0;\r\n\tif (HasAnyOf(opts.flags, (UiFlags::AlignCenter | UiFlags::AlignRight | UiFlags::KerningFitSpacing)))\r\n\t\tlineWidth = GetLineWidth(text, size, opts.spacing, &charactersInLine);\r\n\r\n\tPoint characterPosition { GetLineStartX(opts.flags, rect, lineWidth), rect.position.y };\r\n\tconst int initialX = characterPosition.x;\r\n\r\n\tconst int rightMargin = rect.position.x + rect.size.width;\r\n\tconst int bottomMargin = rect.size.height != 0 ? std::min(rect.position.y + rect.size.height + BaseLineOffset[size], out.h()) : out.h();\r\n\r\n\tif (opts.lineHeight == -1)\r\n\t\topts.lineHeight = GetLineHeight(text, size);\r\n\r\n\tif (HasAnyOf(opts.flags, UiFlags::VerticalCenter)) {\r\n\t\tconst int textHeight = static_cast<int>((c_count(text, '\\n') + 1) * opts.lineHeight);\r\n\t\tcharacterPosition.y += std::max(0, (rect.size.height - textHeight) / 2);\r\n\t}\r\n\r\n\tcharacterPosition.y += BaseLineOffset[size];\r\n\r\n\tconst bool outlined = HasAnyOf(opts.flags, UiFlags::Outlined);\r\n\r\n\tconst Surface clippedOut = ClipSurface(out, rect);\r\n\r\n\t// Only draw the PentaCursor if the cursor is not at the end.\r\n\tif (HasAnyOf(opts.flags, UiFlags::PentaCursor) && static_cast<size_t>(opts.cursorPosition) == text.size()) {\r\n\t\topts.cursorPosition = -1;\r\n\t}\r\n\r\n\tconst uint32_t bytesDrawn = DoDrawString(clippedOut, text, rect, characterPosition,\r\n\t    lineWidth, charactersInLine, rightMargin, bottomMargin, size, color, outlined, opts);\r\n\r\n\tif (HasAnyOf(opts.flags, UiFlags::PentaCursor)) {\r\n\t\tconst ClxSprite sprite = (*pSPentSpn2Cels)[PentSpn2Spin()];\r\n\t\tMaybeWrap(characterPosition, sprite.width(), rightMargin, initialX, opts.lineHeight);\r\n\t\tClxDraw(clippedOut, characterPosition + Displacement { 0, opts.lineHeight - BaseLineOffset[size] }, sprite);\r\n\t}\r\n\r\n\treturn bytesDrawn;\r\n}\r\n\r\nvoid DrawStringWithColors(const Surface &out, std::string_view fmt, DrawStringFormatArg *args, std::size_t argsLen, const Rectangle &rect, TextRenderOptions opts)\r\n{\r\n\tconst GameFontTables size = GetFontSizeFromUiFlags(opts.flags);\r\n\tconst text_color color = GetColorFromFlags(opts.flags);\r\n\r\n\tint charactersInLine = 0;\r\n\tint lineWidth = 0;\r\n\tif (HasAnyOf(opts.flags, (UiFlags::AlignCenter | UiFlags::AlignRight | UiFlags::KerningFitSpacing)))\r\n\t\tlineWidth = GetLineWidth(fmt, args, argsLen, 0, size, opts.spacing, &charactersInLine);\r\n\r\n\tPoint characterPosition { GetLineStartX(opts.flags, rect, lineWidth), rect.position.y };\r\n\tconst int initialX = characterPosition.x;\r\n\r\n\tconst int rightMargin = rect.position.x + rect.size.width;\r\n\tconst int bottomMargin = rect.size.height != 0 ? std::min(rect.position.y + rect.size.height + BaseLineOffset[size], out.h()) : out.h();\r\n\r\n\tif (opts.lineHeight == -1)\r\n\t\topts.lineHeight = GetLineHeight(fmt, args, argsLen, size);\r\n\r\n\tif (HasAnyOf(opts.flags, UiFlags::VerticalCenter)) {\r\n\t\tconst int textHeight = static_cast<int>((CountNewlines(fmt, args, argsLen) + 1) * opts.lineHeight);\r\n\t\tcharacterPosition.y += std::max(0, (rect.size.height - textHeight) / 2);\r\n\t}\r\n\r\n\tcharacterPosition.y += BaseLineOffset[size];\r\n\r\n\tconst bool outlined = HasAnyOf(opts.flags, UiFlags::Outlined);\r\n\r\n\tconst Surface clippedOut = ClipSurface(out, rect);\r\n\r\n\tCurrentFont currentFont;\r\n\tconst int originalSpacing = opts.spacing;\r\n\tif (HasAnyOf(opts.flags, UiFlags::KerningFitSpacing)) {\r\n\t\topts.spacing = AdjustSpacingToFitHorizontally(lineWidth, originalSpacing, charactersInLine, rect.size.width);\r\n\t\tif (opts.spacing != originalSpacing && HasAnyOf(opts.flags, UiFlags::AlignCenter | UiFlags::AlignRight)) {\r\n\t\t\tconst int adjustedLineWidth = GetLineWidth(fmt, args, argsLen, 0, size, opts.spacing, &charactersInLine);\r\n\t\t\tcharacterPosition.x = GetLineStartX(opts.flags, rect, adjustedLineWidth);\r\n\t\t}\r\n\t}\r\n\r\n\tchar32_t prev = U'\\0';\r\n\tchar32_t next;\r\n\tstd::string_view remaining = fmt;\r\n\tFmtArgParser fmtArgParser { fmt, args, argsLen };\r\n\tsize_t cpLen;\r\n\r\n\t// The current formatted argument value being processed.\r\n\tstd::string_view curFormatted;\r\n\ttext_color curFormattedColor;\r\n\r\n\t// The string that we're currently processing: either `remaining` or `curFormatted`.\r\n\tstd::string_view *str;\r\n\r\n\tfor (; !(IsConsumed(curFormatted) && IsConsumed(remaining));\r\n\t     str->remove_prefix(cpLen), prev = next) {\r\n\t\tconst bool isProcessingFormatArgValue = !IsConsumed(curFormatted);\r\n\t\tstr = isProcessingFormatArgValue ? &curFormatted : &remaining;\r\n\t\tnext = DecodeFirstUtf8CodePoint(*str, &cpLen);\r\n\t\tif (next == Utf8DecodeError) break;\r\n\r\n\t\t// {{ and }} escapes in fmt.\r\n\t\tif (!isProcessingFormatArgValue && (prev == U'{' || prev == U'}') && prev == next) continue;\r\n\t\t// ZWSP are line-breaking opportunities that can otherwise be skipped for rendering as they have 0-width.\r\n\t\tif (next == ZWSP) continue;\r\n\r\n\t\tif (!isProcessingFormatArgValue) {\r\n\t\t\tconst std::optional<std::size_t> fmtArgPos = fmtArgParser(*str);\r\n\t\t\tif (fmtArgPos.has_value()) {\r\n\t\t\t\t// `fmtArgParser` has already consumed `*str`. Ensure the loop doesn't consume any more.\r\n\t\t\t\tcpLen = 0;\r\n\t\t\t\t// The loop assigns `prev = next`.\r\n\t\t\t\t// We reset it to U'\\0' to ensure that {{ and }} escapes are not processed accross\r\n\t\t\t\t// the boundary of the format string and a formatted value.\r\n\t\t\t\tnext = U'\\0';\r\n\t\t\t\tcurrentFont.clear();\r\n\t\t\t\tconst DrawStringFormatArg &arg = args[*fmtArgPos];\r\n\t\t\t\tcurFormatted = arg.GetFormatted();\r\n\t\t\t\tcurFormattedColor = GetColorFromFlags(arg.GetFlags());\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst text_color curColor = isProcessingFormatArgValue ? curFormattedColor : color;\r\n\t\tif (!currentFont.load(size, curColor, next)) {\r\n\t\t\tnext = U'?';\r\n\t\t\tif (!currentFont.load(size, curColor, next)) {\r\n\t\t\t\tapp_fatal(\"Missing fonts\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst uint8_t frame = next & 0xFF;\r\n\t\tconst uint16_t width = currentFont.glyph(frame).width();\r\n\t\tif (next == U'\\n' || characterPosition.x + width > rightMargin) {\r\n\t\t\tconst int nextLineY = characterPosition.y + opts.lineHeight;\r\n\t\t\tif (nextLineY >= bottomMargin)\r\n\t\t\t\tbreak;\r\n\t\t\tcharacterPosition.y = nextLineY;\r\n\r\n\t\t\tif (HasAnyOf(opts.flags, UiFlags::KerningFitSpacing)) {\r\n\t\t\t\tint nextLineWidth = isProcessingFormatArgValue\r\n\t\t\t\t    ? GetLineWidth(remaining, args, argsLen, fmtArgParser.offset(), size, originalSpacing, &charactersInLine,\r\n\t\t\t\t          /*firstArgOffset=*/args[fmtArgParser.offset() - 1].GetFormatted().size() - (curFormatted.size() - cpLen))\r\n\t\t\t\t    : GetLineWidth(remaining.substr(cpLen), args, argsLen, fmtArgParser.offset(), size, originalSpacing, &charactersInLine);\r\n\t\t\t\topts.spacing = AdjustSpacingToFitHorizontally(nextLineWidth, originalSpacing, charactersInLine, rect.size.width);\r\n\t\t\t}\r\n\r\n\t\t\tif (HasAnyOf(opts.flags, UiFlags::AlignCenter | UiFlags::AlignRight)) {\r\n\t\t\t\tlineWidth = width;\r\n\t\t\t\tif (str->size() > cpLen) {\r\n\t\t\t\t\tlineWidth += opts.spacing\r\n\t\t\t\t\t    + (isProcessingFormatArgValue\r\n\t\t\t\t\t            ? GetLineWidth(remaining, args, argsLen, fmtArgParser.offset(), size, opts.spacing, &charactersInLine,\r\n\t\t\t\t\t                  /*firstArgOffset=*/args[fmtArgParser.offset() - 1].GetFormatted().size() - (curFormatted.size() - cpLen))\r\n\t\t\t\t\t            : GetLineWidth(remaining.substr(cpLen), args, argsLen, fmtArgParser.offset(), size, opts.spacing, &charactersInLine));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcharacterPosition.x = GetLineStartX(opts.flags, rect, lineWidth);\r\n\r\n\t\t\tif (next == U'\\n')\r\n\t\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tDrawFont(clippedOut, characterPosition, currentFont.glyph(frame), curColor, outlined);\r\n\t\tcharacterPosition.x += width + opts.spacing;\r\n\t}\r\n\r\n\tif (HasAnyOf(opts.flags, UiFlags::PentaCursor)) {\r\n\t\tconst ClxSprite sprite = (*pSPentSpn2Cels)[PentSpn2Spin()];\r\n\t\tMaybeWrap(characterPosition, sprite.width(), rightMargin, initialX, opts.lineHeight);\r\n\t\tClxDraw(clippedOut, characterPosition + Displacement { 0, opts.lineHeight - BaseLineOffset[size] }, sprite);\r\n\t}\r\n}\r\n\r\nuint8_t PentSpn2Spin()\r\n{\r\n\treturn GetAnimationFrame(8, 50);\r\n}\r\n\r\nbool IsBreakableWhitespace(char32_t c)\r\n{\r\n\treturn IsAnyOf(c, U' ', U'　', ZWSP);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/render/text_render.hpp",
    "content": "/**\r\n * @file text_render.hpp\r\n *\r\n * Text rendering.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <utility>\r\n#include <variant>\r\n#include <vector>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum GameFontTables : uint8_t {\r\n\tGameFont12,\r\n\tGameFont24,\r\n\tGameFont30,\r\n\tGameFont42,\r\n\tGameFont46,\r\n\tFontSizeDialog,\r\n};\r\n\r\nenum text_color : uint8_t {\r\n\tColorUiGold,\r\n\tColorUiSilver,\r\n\tColorUiGoldDark,\r\n\tColorUiSilverDark,\r\n\r\n\tColorDialogWhite, // Dialog white in main menu\r\n\tColorDialogRed,\r\n\tColorYellow,\r\n\r\n\tColorGold,\r\n\tColorBlack,\r\n\r\n\tColorWhite,\r\n\tColorWhitegold,\r\n\tColorRed,\r\n\tColorBlue,\r\n\tColorOrange,\r\n\r\n\tColorButtonface,\r\n\tColorButtonpushed,\r\n\r\n\tColorInGameDialogWhite,  // Dialog white in-game\r\n\tColorInGameDialogYellow, // Dialog yellow in-game\r\n\tColorInGameDialogRed,    // Dialog red in-game\r\n};\r\n\r\nconstexpr GameFontTables GetFontSizeFromUiFlags(UiFlags flags)\r\n{\r\n\tif (HasAnyOf(flags, UiFlags::FontSize24))\r\n\t\treturn GameFont24;\r\n\tif (HasAnyOf(flags, UiFlags::FontSize30))\r\n\t\treturn GameFont30;\r\n\tif (HasAnyOf(flags, UiFlags::FontSize42))\r\n\t\treturn GameFont42;\r\n\tif (HasAnyOf(flags, UiFlags::FontSize46))\r\n\t\treturn GameFont46;\r\n\tif (HasAnyOf(flags, UiFlags::FontSizeDialog))\r\n\t\treturn FontSizeDialog;\r\n\treturn GameFont12;\r\n}\r\n\r\n/**\r\n * @brief A format argument for `DrawStringWithColors`.\r\n */\r\nclass DrawStringFormatArg {\r\npublic:\r\n\tusing Value = std::variant<std::string_view, int>;\r\n\r\n\tDrawStringFormatArg(std::string_view value, UiFlags flags)\r\n\t    : value_(value)\r\n\t    , flags_(flags)\r\n\t{\r\n\t}\r\n\r\n\tDrawStringFormatArg(int value, UiFlags flags)\r\n\t    : value_(value)\r\n\t    , flags_(flags)\r\n\t{\r\n\t}\r\n\r\n\tstd::string_view GetFormatted() const\r\n\t{\r\n\t\tif (std::holds_alternative<std::string_view>(value_))\r\n\t\t\treturn std::get<std::string_view>(value_);\r\n\t\treturn formatted_;\r\n\t}\r\n\r\n\tvoid SetFormatted(std::string &&value)\r\n\t{\r\n\t\tformatted_ = std::move(value);\r\n\t}\r\n\r\n\tbool HasFormatted() const\r\n\t{\r\n\t\treturn std::holds_alternative<std::string_view>(value_) || !formatted_.empty();\r\n\t}\r\n\r\n\tconst Value &value() const\r\n\t{\r\n\t\treturn value_;\r\n\t}\r\n\r\n\tUiFlags GetFlags() const\r\n\t{\r\n\t\treturn flags_;\r\n\t}\r\n\r\nprivate:\r\n\tValue value_;\r\n\tUiFlags flags_;\r\n\tstd::string formatted_;\r\n};\r\n\r\n/** @brief Text rendering options. */\r\nstruct TextRenderOptions {\r\n\t/** @brief A combination of UiFlags to describe font size, color, alignment, etc. See ui_items.h for available options */\r\n\tUiFlags flags = UiFlags::None;\r\n\r\n\t/**\r\n\t * @brief Additional space to add between characters.\r\n\t *\r\n\t * This value may be adjusted if the flag UiFlags::KerningFitSpacing is set.\r\n\t */\r\n\tint spacing = 1;\r\n\r\n\t/** @brief Allows overriding the default line height, useful for multi-line strings. */\r\n\tint lineHeight = -1;\r\n\r\n\t/** @brief If non-negative, draws a blinking cursor after the given byte index.*/\r\n\tint cursorPosition = -1;\r\n\r\n\t/** @brief Highlight text background in this range. */\r\n\tstruct {\r\n\t\tint begin;\r\n\t\tint end;\r\n\t} highlightRange = { 0, 0 };\r\n\r\n\tuint8_t highlightColor = PAL8_RED + 6;\r\n\r\n\t/** @brief If a cursor is rendered, the surface coordinates are saved here. */\r\n\tstd::optional<Point> *renderedCursorPositionOut = nullptr;\r\n\r\n\tbool cursorStatic = false;\r\n};\r\n\r\n/**\r\n * @brief Small text selection cursor.\r\n *\r\n * Also used in the stores and the quest log.\r\n */\r\nextern OptionalOwnedClxSpriteList pSPentSpn2Cels;\r\n\r\nvoid LoadSmallSelectionSpinner();\r\n\r\n/**\r\n * @brief Calculate pixel width of first line of text, respecting kerning\r\n * @param text Text to check, will read until first eol or terminator\r\n * @param size Font size to use\r\n * @param spacing Extra spacing to add per character\r\n * @param charactersInLine Receives characters read until newline or terminator\r\n * @return Line width in pixels\r\n */\r\nint GetLineWidth(std::string_view text, GameFontTables size = GameFont12, int spacing = 1, int *charactersInLine = nullptr);\r\n\r\n/**\r\n * @brief Calculate pixel width of first line of text, respecting kerning\r\n * @param fmt An fmt::format string.\r\n * @param args Format arguments.\r\n * @param argsLen Number of format arguments.\r\n * @param argsOffset Index of the first unprocessed format argument.\r\n * @param size Font size to use\r\n * @param spacing Extra spacing to add per character\r\n * @param charactersInLine Receives characters read until newline or terminator\r\n * @param firstArgOffset If given, starts counting at `args[argsOffset - 1].GetFormatted().substr(*firstArgOffset)`.\r\n * @return Line width in pixels\r\n */\r\nint GetLineWidth(std::string_view fmt, DrawStringFormatArg *args, size_t argsLen, size_t argsOffset, GameFontTables size, int spacing, int *charactersInLine = nullptr,\r\n    std::optional<size_t> firstArgOffset = std::nullopt);\r\n\r\nint GetLineHeight(std::string_view text, GameFontTables fontIndex);\r\n\r\n/**\r\n * @brief Builds a multi-line version of the given text so it'll fit within the given width.\r\n *\r\n * This function will not break words, if the given width is smaller than the width of the longest word in the given\r\n * font then it will likely overflow the output region.\r\n *\r\n * @param text Source text\r\n * @param width Width in pixels of the output region\r\n * @param size Font size to use for the width calculation\r\n * @param spacing Any adjustment to apply between each character\r\n * @return A copy of the source text with newlines inserted where appropriate\r\n */\r\n[[nodiscard]] std::string WordWrapString(std::string_view text, unsigned width, GameFontTables size = GameFont12, int spacing = 1);\r\n\r\n/**\r\n * @brief Draws a line of text within a clipping rectangle (positioned relative to the origin of the output buffer).\r\n *\r\n * Specifying a small width (0 to less than two characters wide) should be avoided as this causes issues when laying\r\n * out the text. To wrap based on available space use the overload taking a Point. If the rect passed through has 0\r\n * height then the clipping area is extended to the bottom edge of the output buffer. If the clipping rectangle\r\n * dimensions extend past the edge of the output buffer text wrapping will be calculated using those dimensions (as if\r\n * the text was being rendered off screen). The text will not actually be drawn beyond the bounds of the output\r\n * buffer, this is purely to allow for clipping without wrapping.\r\n *\r\n * @param out The screen buffer to draw on.\r\n * @param text String to be drawn.\r\n * @param rect Clipping region relative to the output buffer describing where to draw the text and when to wrap long lines.\r\n * @param opts Rendering options.\r\n * @return The number of bytes rendered, including characters \"drawn\" outside the buffer.\r\n */\r\nuint32_t DrawString(const Surface &out, std::string_view text, const Rectangle &rect, TextRenderOptions opts = {});\r\n\r\n/**\r\n * @brief Draws a line of text at the given position relative to the origin of the output buffer.\r\n *\r\n * This method is provided as a convenience to pass through to DrawString(..., Rectangle, ...) when no explicit\r\n * clipping/wrapping is requested. Note that this will still wrap the rendered string if it would end up being drawn\r\n * beyond the right edge of the output buffer and clip it if it would extend beyond the bottom edge of the buffer.\r\n *\r\n * @param out The screen buffer to draw on.\r\n * @param text String to be drawn.\r\n * @param position Location of the top left corner of the string relative to the top left corner of the output buffer.\r\n * @param opts Rendering options.\r\n */\r\ninline void DrawString(const Surface &out, std::string_view text, const Point &position, TextRenderOptions opts = {})\r\n{\r\n\tDrawString(out, text, { position, { out.w() - position.x, 0 } }, opts);\r\n}\r\n\r\n/**\r\n * @brief Draws a line of text with different colors for certain parts of the text.\r\n *\r\n *     DrawStringWithColors(out, \"Press {} to start\", {{\"Ⓧ\", UiFlags::ColorBlue}}, {.flags = UiFlags::ColorWhite})\r\n *\r\n * @param out Output buffer to draw the text on.\r\n * @param fmt An fmt::format string.\r\n * @param args Format arguments.\r\n * @param argsLen Number of format arguments.\r\n * @param rect Clipping region relative to the output buffer describing where to draw the text and when to wrap long lines.\r\n * @param opts Rendering options.\r\n */\r\nvoid DrawStringWithColors(const Surface &out, std::string_view fmt, DrawStringFormatArg *args, std::size_t argsLen, const Rectangle &rect, TextRenderOptions opts = {});\r\n\r\ninline void DrawStringWithColors(const Surface &out, std::string_view fmt, std::vector<DrawStringFormatArg> args, const Rectangle &rect, TextRenderOptions opts = {})\r\n{\r\n\treturn DrawStringWithColors(out, fmt, args.data(), args.size(), rect, opts);\r\n}\r\n\r\nuint8_t PentSpn2Spin();\r\nvoid UnloadFonts();\r\n\r\n/** @brief Whether this character can be substituted by a newline when word-wrapping. */\r\nbool IsBreakableWhitespace(char32_t c);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/size.hpp",
    "content": "#pragma once\r\n\r\n#include \"utils/attributes.h\"\r\n\r\n#ifdef BUILD_TESTING\r\n#include <ostream>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename SizeT>\r\nstruct SizeOf {\r\n\tSizeT width;\r\n\tSizeT height;\r\n\r\n\tSizeOf() = default;\r\n\r\n\tDVL_ALWAYS_INLINE constexpr SizeOf(SizeT width, SizeT height)\r\n\t    : width(width)\r\n\t    , height(height)\r\n\t{\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE explicit constexpr SizeOf(SizeT size)\r\n\t    : width(size)\r\n\t    , height(size)\r\n\t{\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE bool operator==(const SizeOf<SizeT> &other) const\r\n\t{\r\n\t\treturn width == other.width && height == other.height;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE bool operator!=(const SizeOf<SizeT> &other) const\r\n\t{\r\n\t\treturn !(*this == other);\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr SizeOf<SizeT> &operator+=(SizeT factor)\r\n\t{\r\n\t\twidth += factor;\r\n\t\theight += factor;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr SizeOf<SizeT> &operator-=(SizeT factor)\r\n\t{\r\n\t\treturn *this += -factor;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr SizeOf<SizeT> &operator*=(SizeT factor)\r\n\t{\r\n\t\twidth *= factor;\r\n\t\theight *= factor;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr SizeOf<SizeT> &operator*=(float factor)\r\n\t{\r\n\t\twidth = static_cast<SizeT>(width * factor);\r\n\t\theight = static_cast<SizeT>(height * factor);\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr SizeOf<SizeT> &operator/=(SizeT factor)\r\n\t{\r\n\t\twidth /= factor;\r\n\t\theight /= factor;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr friend SizeOf<SizeT> operator+(SizeOf<SizeT> a, SizeT factor)\r\n\t{\r\n\t\ta += factor;\r\n\t\treturn a;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr friend SizeOf<SizeT> operator-(SizeOf<SizeT> a, SizeT factor)\r\n\t{\r\n\t\ta -= factor;\r\n\t\treturn a;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr friend SizeOf<SizeT> operator*(SizeOf<SizeT> a, SizeT factor)\r\n\t{\r\n\t\ta *= factor;\r\n\t\treturn a;\r\n\t}\r\n\r\n\tDVL_ALWAYS_INLINE constexpr friend SizeOf<SizeT> operator/(SizeOf<SizeT> a, SizeT factor)\r\n\t{\r\n\t\ta /= factor;\r\n\t\treturn a;\r\n\t}\r\n\r\n#ifdef BUILD_TESTING\r\n\t/**\r\n\t * @brief Format sizes nicely in test failure messages\r\n\t * @param stream output stream, expected to have overloads for int and char*\r\n\t * @param size Object to display\r\n\t * @return the stream, to allow chaining\r\n\t */\r\n\tfriend std::ostream &operator<<(std::ostream &stream, const SizeOf<SizeT> &size)\r\n\t{\r\n\t\treturn stream << \"(width: \" << size.width << \", height: \" << size.height << \")\";\r\n\t}\r\n#endif\r\n};\r\n\r\nusing Size = SizeOf<int>;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/sound.cpp",
    "content": "/**\r\n * @file sound.cpp\r\n *\r\n * Implementation of functions setting up the audio pipeline.\r\n */\r\n#include \"engine/sound.h\"\r\n\r\n#include <algorithm>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <list>\r\n#include <memory>\r\n#include <mutex>\r\n#include <optional>\r\n#include <string>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_audio.h>\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <Aulib/Stream.h>\r\n#include <SDL.h>\r\n#endif\r\n#include <expected.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/math.h\"\r\n#include \"utils/sdl_mutex.h\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/stdcompat/shared_ptr_array.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool gbSndInited;\r\n\r\n#ifdef USE_SDL3\r\nSDL_AudioDeviceID CurrentAudioDeviceId;\r\n#endif\r\n\r\n/** The active background music track id. */\r\n_music_id sgnMusicTrack = NUM_MUSIC;\r\n\r\nbool gbMusicOn = true;\r\n/** Specifies whether sound effects are enabled. */\r\nbool gbSoundOn = true;\r\n\r\nnamespace {\r\n\r\nSoundSample music;\r\n\r\nstd::string GetMp3Path(const char *path)\r\n{\r\n\tstd::string mp3Path = path;\r\n\tconst std::string::size_type dot = mp3Path.find_last_of('.');\r\n\tmp3Path.replace(dot + 1, mp3Path.size() - (dot + 1), \"mp3\");\r\n\treturn mp3Path;\r\n}\r\n\r\ntl::expected<void, std::string> LoadAudioFile(const char *path, bool stream, SoundSample &result)\r\n{\r\n\tbool isMp3 = true;\r\n\tstd::string foundPath = GetMp3Path(path);\r\n\tAssetRef ref = FindAsset(foundPath.c_str());\r\n\tif (!ref.ok()) {\r\n\t\tref = FindAsset(path);\r\n\t\tfoundPath = path;\r\n\t\tisMp3 = false;\r\n\t}\r\n\tif (!ref.ok()) {\r\n\t\treturn tl::make_unexpected(StrCat(\"Audio file not found\\n\", path, \"\\n\", SDL_GetError(), \"\\n\" __FILE__ \":\", __LINE__));\r\n\t}\r\n\r\n#ifdef STREAM_ALL_AUDIO_MIN_FILE_SIZE\r\n#if STREAM_ALL_AUDIO_MIN_FILE_SIZE == 0\r\n\tstream = true;\r\n#else\r\n\tsize_t size;\r\n\tif (!stream) {\r\n\t\tsize = ref.size();\r\n\t\tstream = size >= STREAM_ALL_AUDIO_MIN_FILE_SIZE;\r\n\t}\r\n#endif\r\n#endif\r\n\r\n\tif (stream) {\r\n\t\tif (result.SetChunkStream(foundPath, isMp3, /*logErrors=*/true) != 0) {\r\n\t\t\treturn tl::make_unexpected(StrCat(\"Failed to load audio file\\n\", foundPath, \"\\n\", SDL_GetError(), \"\\n\" __FILE__ \":\", __LINE__));\r\n\t\t}\r\n\t} else {\r\n#if !defined(STREAM_ALL_AUDIO_MIN_FILE_SIZE) || STREAM_ALL_AUDIO_MIN_FILE_SIZE == 0\r\n\t\tconst size_t size = ref.size();\r\n#endif\r\n\t\tAssetHandle handle = OpenAsset(std::move(ref));\r\n\t\tif (!handle.ok()) {\r\n\t\t\treturn tl::make_unexpected(StrCat(\"Failed to load audio file\\n\", foundPath, \"\\n\", SDL_GetError(), \"\\n\" __FILE__ \":\", __LINE__));\r\n\t\t}\r\n\t\tauto waveFile = MakeArraySharedPtr<std::uint8_t>(size);\r\n\t\tif (!handle.read(waveFile.get(), size)) {\r\n\t\t\treturn tl::make_unexpected(StrCat(\"Failed to read file\\n\", foundPath, \": \", SDL_GetError(), __FILE__ \":\", __LINE__));\r\n\t\t}\r\n\t\tconst int error = result.SetChunk(waveFile, size, isMp3);\r\n\t\tif (error != 0) {\r\n\t\t\treturn tl::make_unexpected(SDL_GetError());\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nstd::list<std::unique_ptr<SoundSample>> duplicateSounds;\r\nstd::optional<SdlMutex> duplicateSoundsMutex;\r\n\r\nSoundSample *DuplicateSound(const SoundSample &sound)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn nullptr;\r\n#else\r\n\tauto duplicate = std::make_unique<SoundSample>();\r\n\tif (duplicate->DuplicateFrom(sound) != 0)\r\n\t\treturn nullptr;\r\n\tauto *result = duplicate.get();\r\n\tdecltype(duplicateSounds.begin()) it;\r\n\t{\r\n\t\tconst std::lock_guard<SdlMutex> lock(*duplicateSoundsMutex);\r\n\t\tduplicateSounds.push_back(std::move(duplicate));\r\n\t\tit = duplicateSounds.end();\r\n\t\t--it;\r\n\t}\r\n\tresult->SetFinishCallback([it]([[maybe_unused]] Aulib::Stream &stream) {\r\n\t\tconst std::lock_guard<SdlMutex> lock(*duplicateSoundsMutex);\r\n\t\tduplicateSounds.erase(it);\r\n\t});\r\n\treturn result;\r\n#endif\r\n}\r\n\r\n/** Maps from track ID to track name in spawn. */\r\nconst char *const SpawnMusicTracks[NUM_MUSIC] = {\r\n\t\"music\\\\stowne.wav\",\r\n\t\"music\\\\slvla.wav\",\r\n\t\"music\\\\slvla.wav\",\r\n\t\"music\\\\slvla.wav\",\r\n\t\"music\\\\slvla.wav\",\r\n\t\"music\\\\dlvlf.wav\",\r\n\t\"music\\\\dlvle.wav\",\r\n\t\"music\\\\sintro.wav\",\r\n};\r\n/** Maps from track ID to track name. */\r\nconst char *const MusicTracks[NUM_MUSIC] = {\r\n\t\"music\\\\dtowne.wav\",\r\n\t\"music\\\\dlvla.wav\",\r\n\t\"music\\\\dlvlb.wav\",\r\n\t\"music\\\\dlvlc.wav\",\r\n\t\"music\\\\dlvld.wav\",\r\n\t\"music\\\\dlvlf.wav\",\r\n\t\"music\\\\dlvle.wav\",\r\n\t\"music\\\\dintro.wav\",\r\n};\r\n\r\nint CapVolume(int volume)\r\n{\r\n\treturn std::clamp(volume, VOLUME_MIN, VOLUME_MAX);\r\n}\r\n\r\nvoid OptionAudioChanged()\r\n{\r\n\teffects_cleanup_sfx(false);\r\n\tmusic_stop();\r\n\tsnd_deinit();\r\n\tsnd_init();\r\n\tmusic_start(TMUSIC_INTRO);\r\n\tif (gbRunGame)\r\n\t\tsound_init();\r\n\telse\r\n\t\tui_sound_init();\r\n}\r\n\r\nconst auto OptionChangeSampleRate = (GetOptions().Audio.sampleRate.SetValueChangedCallback(OptionAudioChanged), true);\r\nconst auto OptionChangeChannels = (GetOptions().Audio.channels.SetValueChangedCallback(OptionAudioChanged), true);\r\nconst auto OptionChangeBufferSize = (GetOptions().Audio.bufferSize.SetValueChangedCallback(OptionAudioChanged), true);\r\nconst auto OptionChangeResamplingQuality = (GetOptions().Audio.resamplingQuality.SetValueChangedCallback(OptionAudioChanged), true);\r\nconst auto OptionChangeResampler = (GetOptions().Audio.resampler.SetValueChangedCallback(OptionAudioChanged), true);\r\nconst auto OptionChangeDevice = (GetOptions().Audio.device.SetValueChangedCallback(OptionAudioChanged), true);\r\n\r\n} // namespace\r\n\r\nvoid ClearDuplicateSounds()\r\n{\r\n\t// Move sound samples to a temporary list,\r\n\t// avoiding a deadlock that involves SDL's\r\n\t// mixer lock being taken by finalizers\r\n\tstd::list<std::unique_ptr<SoundSample>> drain;\r\n\t{\r\n\t\tconst std::lock_guard<SdlMutex> lock(*duplicateSoundsMutex);\r\n\t\tdrain = std::move(duplicateSounds);\r\n\t\tduplicateSounds.clear();\r\n\t}\r\n}\r\n\r\nvoid snd_play_snd(TSnd *pSnd, int lVolume, int lPan, int userVolume)\r\n{\r\n\tif (pSnd == nullptr || !gbSoundOn) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst uint32_t tc = SDL_GetTicks();\r\n\tif (tc - pSnd->start_tc < 80) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tSoundSample *sound = &pSnd->DSB;\r\n\tif (sound->IsPlaying()) {\r\n\t\tsound = DuplicateSound(*sound);\r\n\t\tif (sound == nullptr)\r\n\t\t\treturn;\r\n\t}\r\n\r\n\tsound->PlayWithVolumeAndPan(lVolume, userVolume, lPan);\r\n\tpSnd->start_tc = tc;\r\n}\r\n\r\ntl::expected<std::unique_ptr<TSnd>, std::string> SoundFileLoadWithStatus(const char *path, bool stream)\r\n{\r\n\tauto snd = std::make_unique<TSnd>();\r\n\tsnd->start_tc = SDL_GetTicks() - 80 - 1;\r\n#ifndef NOSOUND\r\n\tRETURN_IF_ERROR(LoadAudioFile(path, stream, snd->DSB));\r\n#endif\r\n\treturn snd;\r\n}\r\n\r\nstd::unique_ptr<TSnd> sound_file_load(const char *path, bool stream)\r\n{\r\n\ttl::expected<std::unique_ptr<TSnd>, std::string> result = SoundFileLoadWithStatus(path, stream);\r\n\tif (!result.has_value()) app_fatal(result.error());\r\n\treturn std::move(result).value();\r\n}\r\n\r\nTSnd::~TSnd()\r\n{\r\n\tif (DSB.IsLoaded())\r\n\t\tDSB.Stop();\r\n\tDSB.Release();\r\n}\r\n\r\nvoid snd_init()\r\n{\r\n\tGetOptions().Audio.soundVolume.SetValue(CapVolume(*GetOptions().Audio.soundVolume));\r\n\tgbSoundOn = *GetOptions().Audio.soundVolume > VOLUME_MIN;\r\n\tsgbSaveSoundOn = gbSoundOn;\r\n\r\n\tGetOptions().Audio.musicVolume.SetValue(CapVolume(*GetOptions().Audio.musicVolume));\r\n\tgbMusicOn = *GetOptions().Audio.musicVolume > VOLUME_MIN;\r\n\r\n\t// Initialize the SDL_audiolib library. Set the output sample rate to\r\n\t// 22kHz, the audio format to 16-bit signed, use 2 output channels\r\n\t// (stereo), and a 2KiB output buffer.\r\n#ifdef USE_SDL3\r\n\tconst AudioOptions &audioOptions = GetOptions().Audio;\r\n\tSDL_AudioSpec specHint = {};\r\n\tspecHint.format = SDL_AUDIO_S16LE;\r\n\tspecHint.channels = *audioOptions.channels;\r\n\tspecHint.freq = static_cast<int>(*audioOptions.sampleRate);\r\n\tconst SDL_AudioDeviceID resolvedId = SDL_OpenAudioDevice(audioOptions.device.id(), &specHint);\r\n\tif (resolvedId == 0) {\r\n\t\tLogError(LogCategory::Audio, \"Failed to open audio device: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn;\r\n\t}\r\n\tCurrentAudioDeviceId = resolvedId;\r\n#else\r\n\tif (!Aulib::init(*GetOptions().Audio.sampleRate, AUDIO_S16, *GetOptions().Audio.channels, *GetOptions().Audio.bufferSize, *GetOptions().Audio.device)) {\r\n\t\tLogError(LogCategory::Audio, \"Failed to initialize audio (Aulib::init): {}\", SDL_GetError());\r\n\t\treturn;\r\n\t}\r\n\tLogVerbose(LogCategory::Audio, \"Aulib sampleRate={} channels={} frameSize={} format={:#x}\",\r\n\t    Aulib::sampleRate(), Aulib::channelCount(), Aulib::frameSize(), Aulib::sampleFormat());\r\n#endif\r\n\r\n\tduplicateSoundsMutex.emplace();\r\n\tgbSndInited = true;\r\n}\r\n\r\nvoid snd_deinit()\r\n{\r\n\tif (gbSndInited) {\r\n#ifdef USE_SDL3\r\n\t\tconst AudioOptions &audioOptions = GetOptions().Audio;\r\n\t\tSDL_CloseAudioDevice(audioOptions.device.id());\r\n#else\r\n\t\tAulib::quit();\r\n#endif\r\n\t\tduplicateSoundsMutex = std::nullopt;\r\n\t}\r\n\r\n\tgbSndInited = false;\r\n}\r\n\r\n_music_id GetLevelMusic(dungeon_type dungeonType)\r\n{\r\n\tswitch (dungeonType) {\r\n\tcase DTYPE_TOWN:\r\n\t\treturn TMUSIC_TOWN;\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\treturn TMUSIC_CATHEDRAL;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\treturn TMUSIC_CATACOMBS;\r\n\tcase DTYPE_CAVES:\r\n\t\treturn TMUSIC_CAVES;\r\n\tcase DTYPE_HELL:\r\n\t\treturn TMUSIC_HELL;\r\n\tcase DTYPE_NEST:\r\n\t\treturn TMUSIC_NEST;\r\n\tcase DTYPE_CRYPT:\r\n\t\treturn TMUSIC_CRYPT;\r\n\tdefault:\r\n\t\treturn TMUSIC_INTRO;\r\n\t}\r\n}\r\n\r\nvoid music_stop()\r\n{\r\n\tmusic.Release();\r\n\tsgnMusicTrack = NUM_MUSIC;\r\n}\r\n\r\nvoid music_start(_music_id nTrack)\r\n{\r\n\tconst char *trackPath;\r\n\r\n\tassert(nTrack < NUM_MUSIC);\r\n\tmusic_stop();\r\n\tif (!gbMusicOn)\r\n\t\treturn;\r\n\tif (HaveFullMusic())\r\n\t\ttrackPath = MusicTracks[nTrack];\r\n\telse\r\n\t\ttrackPath = SpawnMusicTracks[nTrack];\r\n\r\n#ifdef DISABLE_STREAMING_MUSIC\r\n\tconst bool stream = false;\r\n#else\r\n\tconst bool stream = true;\r\n#endif\r\n\tif (!LoadAudioFile(trackPath, stream, music).has_value()) {\r\n\t\tmusic_stop();\r\n\t\treturn;\r\n\t}\r\n\r\n\tmusic.SetVolume(*GetOptions().Audio.musicVolume, VOLUME_MIN, VOLUME_MAX);\r\n\tif (!music.Play(/*numIterations=*/0)) {\r\n\t\tLogError(LogCategory::Audio, \"Aulib::Stream::play (from music_start): {}\", SDL_GetError());\r\n\t\tmusic_stop();\r\n\t\treturn;\r\n\t}\r\n\r\n\tsgnMusicTrack = nTrack;\r\n}\r\n\r\nvoid sound_disable_music(bool disable)\r\n{\r\n\tif (disable) {\r\n\t\tmusic_stop();\r\n\t} else if (sgnMusicTrack != NUM_MUSIC) {\r\n\t\tmusic_start(sgnMusicTrack);\r\n\t}\r\n}\r\n\r\nint sound_get_or_set_music_volume(int volume)\r\n{\r\n\tif (volume == 1)\r\n\t\treturn *GetOptions().Audio.musicVolume;\r\n\r\n\tGetOptions().Audio.musicVolume.SetValue(volume);\r\n\r\n\tif (music.IsLoaded())\r\n\t\tmusic.SetVolume(*GetOptions().Audio.musicVolume, VOLUME_MIN, VOLUME_MAX);\r\n\r\n\treturn *GetOptions().Audio.musicVolume;\r\n}\r\n\r\nint sound_get_or_set_sound_volume(int volume)\r\n{\r\n\tif (volume == 1)\r\n\t\treturn *GetOptions().Audio.soundVolume;\r\n\r\n\tGetOptions().Audio.soundVolume.SetValue(volume);\r\n\r\n\treturn *GetOptions().Audio.soundVolume;\r\n}\r\n\r\nint SoundGetOrSetAudioCuesVolume(int volume)\r\n{\r\n\tif (volume == 1)\r\n\t\treturn *GetOptions().Audio.audioCuesVolume;\r\n\r\n\tGetOptions().Audio.audioCuesVolume.SetValue(volume);\r\n\r\n\treturn *GetOptions().Audio.audioCuesVolume;\r\n}\r\n\r\nvoid music_mute()\r\n{\r\n\tif (music.IsLoaded())\r\n\t\tmusic.Mute();\r\n}\r\n\r\nvoid music_unmute()\r\n{\r\n\tif (music.IsLoaded())\r\n\t\tmusic.Unmute();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/sound.h",
    "content": "/**\r\n * @file sound.h\r\n *\r\n * Interface of functions setting up the audio pipeline.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"levels/gendung.h\"\r\n#include \"utils/attributes.h\"\r\n\r\n#ifndef NOSOUND\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_audio.h>\r\n#endif\r\n\r\n#include \"utils/soundsample.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nenum _music_id : uint8_t {\r\n\tTMUSIC_TOWN,\r\n\tTMUSIC_CATHEDRAL,\r\n\tTMUSIC_CATACOMBS,\r\n\tTMUSIC_CAVES,\r\n\tTMUSIC_HELL,\r\n\tTMUSIC_NEST,\r\n\tTMUSIC_CRYPT,\r\n\tTMUSIC_INTRO,\r\n\tNUM_MUSIC,\r\n};\r\n\r\nstruct TSnd {\r\n\tuint32_t start_tc;\r\n\r\n#ifndef NOSOUND\r\n\tSoundSample DSB;\r\n\r\n\tbool isPlaying()\r\n\t{\r\n\t\treturn DSB.IsPlaying();\r\n\t}\r\n#else\r\n\tbool isPlaying()\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n#endif\r\n\r\n\t~TSnd();\r\n};\r\n\r\nextern bool gbSndInited;\r\n#ifdef USE_SDL3\r\nextern SDL_AudioDeviceID CurrentAudioDeviceId;\r\n#endif\r\n\r\nextern _music_id sgnMusicTrack;\r\n\r\nvoid ClearDuplicateSounds();\r\nvoid snd_play_snd(TSnd *pSnd, int lVolume, int lPan, int userVolume);\r\nstd::unique_ptr<TSnd> sound_file_load(const char *path, bool stream = false);\r\ntl::expected<std::unique_ptr<TSnd>, std::string> SoundFileLoadWithStatus(const char *path, bool stream = false);\r\nvoid snd_init();\r\nvoid snd_deinit();\r\n_music_id GetLevelMusic(dungeon_type dungeonType);\r\nvoid music_stop();\r\nvoid music_start(_music_id nTrack);\r\nvoid sound_disable_music(bool disable);\r\nint sound_get_or_set_music_volume(int volume);\r\nint sound_get_or_set_sound_volume(int volume);\r\nint SoundGetOrSetAudioCuesVolume(int volume);\r\nvoid music_mute();\r\nvoid music_unmute();\r\n\r\n/* data */\r\n\r\nextern DVL_API_FOR_TEST bool gbMusicOn;\r\nextern DVL_API_FOR_TEST bool gbSoundOn;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/sound_defs.hpp",
    "content": "#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL_version.h>\r\n#endif\r\n\r\n#define VOLUME_MIN -1600\r\n#define VOLUME_MAX 0\r\n#define VOLUME_STEPS 64\r\n\r\n#define ATTENUATION_MIN -6400\r\n#define ATTENUATION_MAX 0\r\n\r\n#define PAN_MIN -6400\r\n#define PAN_MAX 6400\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 7) && defined(DEVILUTIONX_RESAMPLER_SDL)\r\n#define DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n#endif\r\n"
  },
  {
    "path": "Source/engine/sound_position.cpp",
    "content": "#include \"engine/sound_position.hpp\"\r\n\r\n#include \"engine/sound_defs.hpp\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool CalculateSoundPosition(Point soundPosition, int *plVolume, int *plPan)\r\n{\r\n\tconst Point playerPosition { MyPlayer->position.tile };\r\n\tconst Displacement delta = soundPosition - playerPosition;\r\n\r\n\tconst int pan = (delta.deltaX - delta.deltaY) * 256;\r\n\t*plPan = std::clamp(pan, PAN_MIN, PAN_MAX);\r\n\r\n\tconst int volume = playerPosition.ApproxDistance(soundPosition) * -64;\r\n\r\n\tif (volume <= ATTENUATION_MIN)\r\n\t\treturn false;\r\n\r\n\t*plVolume = volume;\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/sound_position.hpp",
    "content": "#pragma once\r\n\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool CalculateSoundPosition(Point soundPosition, int *plVolume, int *plPan);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/sound_stubs.cpp",
    "content": "// Stubbed implementations of sound functions for the NOSOUND mode.\r\n#include \"engine/sound.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool gbSndInited;\r\nbool gbMusicOn;\r\nbool gbSoundOn;\r\n_music_id sgnMusicTrack = NUM_MUSIC;\r\n\r\nvoid ClearDuplicateSounds() { }\r\nvoid snd_play_snd(TSnd *pSnd, int lVolume, int lPan, int userVolume) { }\r\nstd::unique_ptr<TSnd> sound_file_load(const char *path, bool stream) { return nullptr; }\r\ntl::expected<std::unique_ptr<TSnd>, std::string> SoundFileLoadWithStatus(const char *path, bool stream) { return nullptr; }\r\nTSnd::~TSnd() { }\r\nvoid snd_init() { }\r\nvoid snd_deinit() { }\r\nvoid music_stop() { }\r\nvoid music_start(_music_id nTrack) { }\r\nvoid sound_disable_music(bool disable) { }\r\nint sound_get_or_set_music_volume(int volume) { return 0; }\r\nint sound_get_or_set_sound_volume(int volume) { return 0; }\r\nint SoundGetOrSetAudioCuesVolume(int volume) { return 0; }\r\nvoid music_mute() { }\r\nvoid music_unmute() { }\r\n_music_id GetLevelMusic(dungeon_type dungeonType) { return TMUSIC_TOWN; }\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/surface.cpp",
    "content": "#include \"engine/surface.hpp\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\ntemplate <bool SkipColorIndexZero>\r\nvoid SurfaceBlit(const Surface &src, SDL_Rect srcRect, const Surface &dst, Point dstPosition)\r\n{\r\n\t// We do not use `SDL_BlitSurface` here because the palettes may be different objects\r\n\t// and SDL would attempt to map them.\r\n\r\n\tdst.Clip(&srcRect, &dstPosition);\r\n\tif (srcRect.w <= 0 || srcRect.h <= 0)\r\n\t\treturn;\r\n\r\n\tconst std::uint8_t *srcBuf = src.at(srcRect.x, srcRect.y);\r\n\tconst auto srcPitch = src.pitch();\r\n\tstd::uint8_t *dstBuf = &dst[dstPosition];\r\n\tconst auto dstPitch = dst.pitch();\r\n\r\n\tfor (unsigned h = srcRect.h; h != 0; --h) {\r\n\t\tif (SkipColorIndexZero) {\r\n\t\t\tfor (unsigned w = srcRect.w; w != 0; --w) {\r\n\t\t\t\tif (*srcBuf != 0)\r\n\t\t\t\t\t*dstBuf = *srcBuf;\r\n\t\t\t\t++srcBuf, ++dstBuf;\r\n\t\t\t}\r\n\t\t\tsrcBuf += srcPitch - srcRect.w;\r\n\t\t\tdstBuf += dstPitch - srcRect.w;\r\n\t\t} else {\r\n\t\t\tstd::memcpy(dstBuf, srcBuf, srcRect.w);\r\n\t\t\tsrcBuf += srcPitch;\r\n\t\t\tdstBuf += dstPitch;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid Surface::BlitFrom(const Surface &src, SDL_Rect srcRect, Point targetPosition) const\r\n{\r\n\tSurfaceBlit</*SkipColorIndexZero=*/false>(src, srcRect, *this, targetPosition);\r\n}\r\n\r\nvoid Surface::BlitFromSkipColorIndexZero(const Surface &src, SDL_Rect srcRect, Point targetPosition) const\r\n{\r\n\tSurfaceBlit</*SkipColorIndexZero=*/true>(src, srcRect, *this, targetPosition);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/surface.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL_version.h>\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n#include <SDL_rect.h>\r\n#include <SDL_surface.h>\r\n#else\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#include <SDL_video.h>\r\n#endif\r\n#endif\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief 8-bit surface.\r\n */\r\nstruct Surface {\r\n\tSDL_Surface *surface;\r\n\tSDL_Rect region;\r\n\r\n\tSurface()\r\n\t    : surface(nullptr)\r\n\t    , region(SDL_Rect { 0, 0, 0, 0 })\r\n\t{\r\n\t}\r\n\r\n\texplicit Surface(SDL_Surface *surface)\r\n\t    : surface(surface)\r\n\t    , region(MakeSdlRect(0, 0, surface->w, surface->h))\r\n\t{\r\n\t}\r\n\r\n\tSurface(SDL_Surface *surface, SDL_Rect region)\r\n\t    : surface(surface)\r\n\t    , region(region)\r\n\t{\r\n\t}\r\n\r\n\tSurface(const Surface &other) = default;\r\n\tSurface &operator=(const Surface &other) = default;\r\n\r\n\tint w() const\r\n\t{\r\n\t\treturn region.w;\r\n\t}\r\n\tint h() const\r\n\t{\r\n\t\treturn region.h;\r\n\t}\r\n\r\n\tstd::uint8_t &operator[](Point p) const\r\n\t{\r\n\t\treturn *at(p.x, p.y);\r\n\t}\r\n\r\n\tstd::uint8_t *at(int x, int y) const\r\n\t{\r\n\t\treturn static_cast<uint8_t *>(surface->pixels) + region.x + x + surface->pitch * (region.y + y);\r\n\t}\r\n\r\n\tstd::uint8_t *begin() const\r\n\t{\r\n\t\treturn at(0, 0);\r\n\t}\r\n\tstd::uint8_t *end() const\r\n\t{\r\n\t\treturn at(0, region.h);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Set the value of a single pixel if it is in bounds.\r\n\t * @param position Target buffer coordinate\r\n\t * @param col Color index from current palette\r\n\t */\r\n\tvoid SetPixel(Point position, std::uint8_t col) const\r\n\t{\r\n\t\tif (InBounds(position))\r\n\t\t\t(*this)[position] = col;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Line width of the raw underlying byte buffer.\r\n\t * May be wider than its logical width (for power-of-2 alignment).\r\n\t */\r\n\t[[nodiscard]] uint16_t pitch() const\r\n\t{\r\n\t\treturn surface->pitch;\r\n\t}\r\n\r\n\tbool InBounds(Point position) const\r\n\t{\r\n\t\treturn position.x >= 0 && position.y >= 0 && position.x < region.w && position.y < region.h;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a subregion of the given buffer.\r\n\t */\r\n\tSurface subregion(int x, int y, int w, int h) const\r\n\t{\r\n\t\treturn Surface(surface, MakeSdlRect(region.x + x, region.y + y, w, h));\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a buffer that starts at `x` of width `w`.\r\n\t */\r\n\tSurface subregionX(int x, int w) const\r\n\t{\r\n\t\tSDL_Rect subregion = region;\r\n\t\tsubregion.x += static_cast<decltype(SDL_Rect {}.x)>(x);\r\n\t\tsubregion.w = static_cast<decltype(SDL_Rect {}.w)>(w);\r\n\t\treturn Surface(surface, subregion);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns a buffer that starts at `y` of height `h`.\r\n\t */\r\n\tSurface subregionY(int y, int h) const\r\n\t{\r\n\t\tSDL_Rect subregion = region;\r\n\t\tsubregion.y += static_cast<decltype(SDL_Rect {}.y)>(y);\r\n\t\tsubregion.h = static_cast<decltype(SDL_Rect {}.h)>(h);\r\n\t\treturn Surface(surface, subregion);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Clips srcRect and targetPosition to this output buffer.\r\n\t */\r\n\tvoid Clip(SDL_Rect *srcRect, Point *targetPosition) const\r\n\t{\r\n\t\tif (targetPosition->x < 0) {\r\n\t\t\tsrcRect->x -= targetPosition->x;\r\n\t\t\tsrcRect->w += targetPosition->x;\r\n\t\t\ttargetPosition->x = 0;\r\n\t\t}\r\n\t\tif (targetPosition->y < 0) {\r\n\t\t\tsrcRect->y -= targetPosition->y;\r\n\t\t\tsrcRect->h += targetPosition->y;\r\n\t\t\ttargetPosition->y = 0;\r\n\t\t}\r\n\t\tif (targetPosition->x + srcRect->w > region.w) {\r\n\t\t\tsrcRect->w = region.w - targetPosition->x;\r\n\t\t}\r\n\t\tif (targetPosition->y + srcRect->h > region.h) {\r\n\t\t\tsrcRect->h = region.h - targetPosition->y;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Copies the `srcRect` portion of the given buffer to this buffer at `targetPosition`.\r\n\t */\r\n\tvoid BlitFrom(const Surface &src, SDL_Rect srcRect, Point targetPosition) const;\r\n\r\n\t/**\r\n\t * @brief Copies the `srcRect` portion of the given buffer to this buffer at `targetPosition`.\r\n\t * Source pixels with index 0 are not copied.\r\n\t */\r\n\tvoid BlitFromSkipColorIndexZero(const Surface &src, SDL_Rect srcRect, Point targetPosition) const;\r\n};\r\n\r\nclass OwnedSurface : public Surface {\r\n\tSDLSurfaceUniquePtr pinnedSurface;\r\n\r\npublic:\r\n\texplicit OwnedSurface(SDLSurfaceUniquePtr surface)\r\n\t    : Surface(surface.get())\r\n\t    , pinnedSurface(std::move(surface))\r\n\t{\r\n\t}\r\n\r\n\tOwnedSurface(int width, int height)\r\n\t    : OwnedSurface(SDLWrap::CreateRGBSurfaceWithFormat(0, width, height, 8, SDL_PIXELFORMAT_INDEX8))\r\n\t{\r\n\t}\r\n\r\n\texplicit OwnedSurface(Size size)\r\n\t    : OwnedSurface(size.width, size.height)\r\n\t{\r\n\t}\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/ticks.cpp",
    "content": "#include \"engine/ticks.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nuint32_t GetAnimationFrame(uint32_t frames, uint32_t fps)\r\n{\r\n\treturn (SDL_GetTicks() / fps) % frames;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/ticks.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nuint32_t GetAnimationFrame(uint32_t frames, uint32_t fps = 60);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/trn.cpp",
    "content": "#include \"engine/trn.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#include <fmt/format.h>\r\n\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n#include \"engine/load_file.hpp\"\r\n#include \"lighting.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nuint8_t *GetInfravisionTRN()\r\n{\r\n\treturn InfravisionTable.data();\r\n}\r\n\r\nuint8_t *GetStoneTRN()\r\n{\r\n\treturn StoneTable.data();\r\n}\r\n\r\nuint8_t *GetPauseTRN()\r\n{\r\n\treturn PauseTable.data();\r\n}\r\n\r\nstd::optional<std::array<uint8_t, 256>> GetClassTRN(Player &player)\r\n{\r\n\tstd::array<uint8_t, 256> trn;\r\n\tchar path[64];\r\n\r\n\tconst PlayerSpriteData &spriteData = GetPlayerSpriteDataForClass(player._pClass);\r\n\t*BufCopy(path, \"plrgfx\\\\\", spriteData.trn, \".trn\") = '\\0';\r\n\r\n#ifdef _DEBUG\r\n\tif (!debugTRN.empty()) {\r\n\t\t*BufCopy(path, debugTRN.c_str()) = '\\0';\r\n\t}\r\n#endif\r\n\tif (LoadOptionalFileInMem(path, &trn[0], 256)) {\r\n\t\treturn trn;\r\n\t}\r\n\treturn std::nullopt;\r\n}\r\n\r\nstd::optional<std::array<uint8_t, 256>> GetPlayerGraphicTRN(const char *pszName)\r\n{\r\n\tchar path[MaxMpqPathSize];\r\n\t*BufCopy(path, pszName, \".trn\") = '\\0';\r\n\r\n\tstd::array<uint8_t, 256> trn;\r\n\tif (LoadOptionalFileInMem(path, &trn[0], 256)) {\r\n\t\treturn trn;\r\n\t}\r\n\treturn std::nullopt;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/trn.hpp",
    "content": "/**\r\n * @file trn.hpp\r\n *\r\n * Contains most of trn logic\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nuint8_t *GetInfravisionTRN();\r\nuint8_t *GetStoneTRN();\r\nuint8_t *GetPauseTRN();\r\nstd::optional<std::array<uint8_t, 256>> GetClassTRN(Player &player);\r\nstd::optional<std::array<uint8_t, 256>> GetPlayerGraphicTRN(const char *pszName);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/engine/world_tile.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/size.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nusing WorldTileCoord = uint8_t;\r\nusing WorldTilePosition = PointOf<WorldTileCoord>;\r\n\r\nusing WorldTileOffset = int8_t;\r\nusing WorldTileDisplacement = DisplacementOf<WorldTileOffset>;\r\n\r\nusing WorldTileSize = SizeOf<WorldTileCoord>;\r\nusing WorldTileRectangle = RectangleOf<WorldTileCoord>;\r\n\r\n} // namespace devilution\r\n\r\nnamespace std {\r\n\r\n/**\r\n * @brief Allows using WorldTilePosition as a map key for contexts where we want to lookup an entity by physical dungeon location\r\n */\r\ntemplate <>\r\nstruct hash<devilution::WorldTilePosition> {\r\n\tsize_t operator()(const devilution::WorldTilePosition &position) const noexcept\r\n\t{\r\n\t\treturn static_cast<size_t>(position.x) << 8 | position.y;\r\n\t}\r\n};\r\n\r\n} // namespace std\r\n"
  },
  {
    "path": "Source/game_mode.cpp",
    "content": "#include \"game_mode.hpp\"\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"options.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nvoid OptionSharewareChanged()\r\n{\r\n\tgbIsSpawn = *GetOptions().GameMode.shareware;\r\n}\r\nconst auto OptionChangeHandlerShareware = (GetOptions().GameMode.shareware.SetValueChangedCallback(OptionSharewareChanged), true);\r\n} // namespace\r\n\r\nbool gbRunGame;\r\nbool gbIsSpawn;\r\nbool gbIsHellfire;\r\nbool gbVanilla;\r\nbool forceHellfire;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/game_mode.hpp",
    "content": "#pragma once\r\n\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\n/* Are we in-game? If false, we're in the main menu. */\r\nextern DVL_API_FOR_TEST bool gbRunGame;\r\n/** Indicate if we only have access to demo data */\r\nextern DVL_API_FOR_TEST bool gbIsSpawn;\r\n/** Indicate if we have loaded the Hellfire expansion data */\r\nextern DVL_API_FOR_TEST bool gbIsHellfire;\r\n/** Indicate if we want vanilla savefiles */\r\nextern DVL_API_FOR_TEST bool gbVanilla;\r\n/** Whether the Hellfire mode is required (forced). */\r\nextern bool forceHellfire;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/gamemenu.cpp",
    "content": "/**\r\n * @file gamemenu.cpp\r\n *\r\n * Implementation of the in-game menu functions.\r\n */\r\n#include \"gamemenu.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#endif\r\n\r\n#include \"cursor.h\"\r\n#include \"diablo_msg.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/events.hpp\"\r\n#include \"engine/sound.h\"\r\n#include \"engine/sound_defs.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"gmenu.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"loadsave.h\"\r\n#include \"multi.h\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"qol/floatingnumbers.h\"\r\n#include \"utils/language.h\"\r\n\r\n#ifndef USE_SDL1\r\n#include \"controls/touch/renderers.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nbool isGameMenuOpen = false;\r\n\r\nnamespace {\r\n\r\n// Forward-declare menu handlers, used by the global menu structs below.\r\nvoid GamemenuPrevious(bool bActivate);\r\nvoid GamemenuNewGame(bool bActivate);\r\nvoid GamemenuOptions(bool bActivate);\r\nvoid GamemenuMusicVolume(bool bActivate);\r\nvoid GamemenuSoundVolume(bool bActivate);\r\nvoid GamemenuBrightness(bool bActivate);\r\nvoid GamemenuSpeed(bool bActivate);\r\n\r\n/** Contains the game menu items of the single player menu. */\r\nTMenuItem sgSingleMenu[] = {\r\n\t// clang-format off\r\n\t// dwFlags,      pszStr,                  fnMenu\r\n\t{ GMENU_ENABLED, N_(\"Options\"),           &GamemenuOptions    },\r\n\t{ GMENU_ENABLED, N_(\"Save Game\"),         &gamemenu_save_game },\r\n\t{ GMENU_ENABLED, N_(\"Load Game\"),         &gamemenu_load_game },\r\n\t{ GMENU_ENABLED, N_(\"Exit to Main Menu\"), &GamemenuNewGame    },\r\n\t{ GMENU_ENABLED, N_(\"Quit Game\"),         &gamemenu_quit_game },\r\n\t{ GMENU_ENABLED, nullptr,                 nullptr             },\r\n\t// clang-format on\r\n};\r\n/** Contains the game menu items of the multi player menu. */\r\nTMenuItem sgMultiMenu[] = {\r\n\t// clang-format off\r\n\t// dwFlags,      pszStr,                  fnMenu\r\n\t{ GMENU_ENABLED, N_(\"Options\"),           &GamemenuOptions    },\r\n\t{ GMENU_ENABLED, N_(\"Exit to Main Menu\"), &GamemenuNewGame    },\r\n\t{ GMENU_ENABLED, N_(\"Quit Game\"),         &gamemenu_quit_game },\r\n\t{ GMENU_ENABLED, nullptr,                 nullptr             },\r\n\t// clang-format on\r\n};\r\nTMenuItem sgOptionsMenu[] = {\r\n\t// clang-format off\r\n\t// dwFlags,                     pszStr,              fnMenu\r\n\t{ GMENU_ENABLED | GMENU_SLIDER, nullptr,             &GamemenuMusicVolume  },\r\n\t{ GMENU_ENABLED | GMENU_SLIDER, nullptr,             &GamemenuSoundVolume  },\r\n\t{ GMENU_ENABLED | GMENU_SLIDER, N_(\"Gamma\"),         &GamemenuBrightness   },\r\n\t{ GMENU_ENABLED | GMENU_SLIDER, N_(\"Speed\"),         &GamemenuSpeed        },\r\n\t{ GMENU_ENABLED               , N_(\"Previous Menu\"), &GamemenuPrevious     },\r\n\t{ GMENU_ENABLED               , nullptr,             nullptr               },\r\n\t// clang-format on\r\n};\r\n/** Specifies the menu names for music enabled and disabled. */\r\nconst char *const MusicToggleNames[] = {\r\n\tN_(\"Music\"),\r\n\tN_(\"Music Disabled\"),\r\n};\r\n/** Specifies the menu names for sound enabled and disabled. */\r\nconst char *const SoundToggleNames[] = {\r\n\tN_(\"Sound\"),\r\n\tN_(\"Sound Disabled\"),\r\n};\r\n\r\nvoid GamemenuUpdateSingle()\r\n{\r\n\tsgSingleMenu[2].setEnabled(gbValidSaveFile);\r\n\r\n\tconst bool enable = MyPlayer->_pmode != PM_DEATH && !MyPlayerIsDead;\r\n\r\n\tsgSingleMenu[0].setEnabled(enable);\r\n}\r\n\r\nvoid GamemenuPrevious(bool /*bActivate*/)\r\n{\r\n\tgamemenu_on();\r\n}\r\n\r\nvoid GamemenuNewGame(bool /*bActivate*/)\r\n{\r\n\tfor (Player &player : Players) {\r\n\t\tplayer._pmode = PM_QUIT;\r\n\t\tplayer._pInvincible = true;\r\n\t}\r\n\r\n\tMyPlayerIsDead = false;\r\n\tif (!HeadlessMode) {\r\n\t\tRedrawEverything();\r\n\t\tscrollrt_draw_game_screen();\r\n\t}\r\n\tCornerStone.activated = false;\r\n\tgbRunGame = false;\r\n\tgamemenu_off();\r\n}\r\n\r\nvoid GamemenuSoundMusicToggle(const char *const *names, TMenuItem *menuItem, int volume)\r\n{\r\n\tif (gbSndInited) {\r\n\t\tmenuItem->addFlags(GMENU_ENABLED | GMENU_SLIDER);\r\n\t\tmenuItem->pszStr = names[0];\r\n\t\tgmenu_slider_steps(menuItem, VOLUME_STEPS);\r\n\t\tgmenu_slider_set(menuItem, VOLUME_MIN, VOLUME_MAX, volume);\r\n\t\treturn;\r\n\t}\r\n\r\n\tmenuItem->removeFlags(GMENU_ENABLED | GMENU_SLIDER);\r\n\tmenuItem->pszStr = names[1];\r\n}\r\n\r\nint GamemenuSliderMusicSound(TMenuItem *menuItem)\r\n{\r\n\treturn gmenu_slider_get(menuItem, VOLUME_MIN, VOLUME_MAX);\r\n}\r\n\r\nvoid GamemenuGetMusic()\r\n{\r\n\tGamemenuSoundMusicToggle(MusicToggleNames, sgOptionsMenu, sound_get_or_set_music_volume(1));\r\n}\r\n\r\nvoid GamemenuGetSound()\r\n{\r\n\tGamemenuSoundMusicToggle(SoundToggleNames, &sgOptionsMenu[1], sound_get_or_set_sound_volume(1));\r\n}\r\n\r\nvoid GamemenuGetBrightness()\r\n{\r\n\tgmenu_slider_steps(&sgOptionsMenu[2], 21);\r\n\tgmenu_slider_set(&sgOptionsMenu[2], 0, 100, UpdateBrightness(-1));\r\n}\r\n\r\nvoid GamemenuGetSpeed()\r\n{\r\n\tif (gbIsMultiplayer) {\r\n\t\tsgOptionsMenu[3].removeFlags(GMENU_ENABLED | GMENU_SLIDER);\r\n\t\tif (sgGameInitInfo.nTickRate >= 50)\r\n\t\t\tsgOptionsMenu[3].pszStr = _(\"Speed: Fastest\").data();\r\n\t\telse if (sgGameInitInfo.nTickRate >= 40)\r\n\t\t\tsgOptionsMenu[3].pszStr = _(\"Speed: Faster\").data();\r\n\t\telse if (sgGameInitInfo.nTickRate >= 30)\r\n\t\t\tsgOptionsMenu[3].pszStr = _(\"Speed: Fast\").data();\r\n\t\telse if (sgGameInitInfo.nTickRate == 20)\r\n\t\t\tsgOptionsMenu[3].pszStr = _(\"Speed: Normal\").data();\r\n\t\treturn;\r\n\t}\r\n\r\n\tsgOptionsMenu[3].addFlags(GMENU_ENABLED | GMENU_SLIDER);\r\n\r\n\tsgOptionsMenu[3].pszStr = _(\"Speed\").data();\r\n\tgmenu_slider_steps(&sgOptionsMenu[3], 46);\r\n\tgmenu_slider_set(&sgOptionsMenu[3], 20, 50, sgGameInitInfo.nTickRate);\r\n}\r\n\r\nint GamemenuSliderBrightness()\r\n{\r\n\treturn gmenu_slider_get(&sgOptionsMenu[2], 0, 100);\r\n}\r\n\r\nvoid GamemenuOptions(bool /*bActivate*/)\r\n{\r\n\tGamemenuGetMusic();\r\n\tGamemenuGetSound();\r\n\tGamemenuGetBrightness();\r\n\tGamemenuGetSpeed();\r\n\tgmenu_set_items(sgOptionsMenu, nullptr);\r\n}\r\n\r\nvoid GamemenuMusicVolume(bool bActivate)\r\n{\r\n\tif (bActivate) {\r\n\t\tif (gbMusicOn) {\r\n\t\t\tgbMusicOn = false;\r\n\t\t\tmusic_stop();\r\n\t\t\tsound_get_or_set_music_volume(VOLUME_MIN);\r\n\t\t} else {\r\n\t\t\tgbMusicOn = true;\r\n\t\t\tsound_get_or_set_music_volume(VOLUME_MAX);\r\n\t\t\tmusic_start(GetLevelMusic(leveltype));\r\n\t\t}\r\n\t} else {\r\n\t\tconst int volume = GamemenuSliderMusicSound(&sgOptionsMenu[0]);\r\n\t\tsound_get_or_set_music_volume(volume);\r\n\t\tif (volume == VOLUME_MIN) {\r\n\t\t\tif (gbMusicOn) {\r\n\t\t\t\tgbMusicOn = false;\r\n\t\t\t\tmusic_stop();\r\n\t\t\t}\r\n\t\t} else if (!gbMusicOn) {\r\n\t\t\tgbMusicOn = true;\r\n\t\t\tmusic_start(GetLevelMusic(leveltype));\r\n\t\t}\r\n\t}\r\n\r\n\tGamemenuGetMusic();\r\n}\r\n\r\nvoid GamemenuSoundVolume(bool bActivate)\r\n{\r\n\tif (bActivate) {\r\n\t\tif (gbSoundOn) {\r\n\t\t\tgbSoundOn = false;\r\n\t\t\tsound_stop();\r\n\t\t\tsound_get_or_set_sound_volume(VOLUME_MIN);\r\n\t\t} else {\r\n\t\t\tgbSoundOn = true;\r\n\t\t\tsound_get_or_set_sound_volume(VOLUME_MAX);\r\n\t\t}\r\n\t} else {\r\n\t\tconst int volume = GamemenuSliderMusicSound(&sgOptionsMenu[1]);\r\n\t\tsound_get_or_set_sound_volume(volume);\r\n\t\tif (volume == VOLUME_MIN) {\r\n\t\t\tif (gbSoundOn) {\r\n\t\t\t\tgbSoundOn = false;\r\n\t\t\t\tsound_stop();\r\n\t\t\t}\r\n\t\t} else if (!gbSoundOn) {\r\n\t\t\tgbSoundOn = true;\r\n\t\t}\r\n\t}\r\n\tPlaySFX(SfxID::MenuMove);\r\n\tGamemenuGetSound();\r\n}\r\n\r\nvoid GamemenuBrightness(bool bActivate)\r\n{\r\n\tint brightness;\r\n\tif (bActivate) {\r\n\t\tbrightness = UpdateBrightness(-1);\r\n\t\tbrightness = (brightness == 0) ? 100 : 0;\r\n\t} else {\r\n\t\tbrightness = GamemenuSliderBrightness();\r\n\t}\r\n\r\n\tUpdateBrightness(brightness);\r\n\tGamemenuGetBrightness();\r\n}\r\n\r\nvoid GamemenuSpeed(bool bActivate)\r\n{\r\n\tif (bActivate) {\r\n\t\tif (sgGameInitInfo.nTickRate != 20)\r\n\t\t\tsgGameInitInfo.nTickRate = 20;\r\n\t\telse\r\n\t\t\tsgGameInitInfo.nTickRate = 50;\r\n\t\tgmenu_slider_set(&sgOptionsMenu[3], 20, 50, sgGameInitInfo.nTickRate);\r\n\t} else {\r\n\t\tsgGameInitInfo.nTickRate = gmenu_slider_get(&sgOptionsMenu[3], 20, 50);\r\n\t}\r\n\r\n\tGetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate);\r\n\tgnTickDelay = 1000 / sgGameInitInfo.nTickRate;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid gamemenu_exit_game(bool bActivate)\r\n{\r\n\tGamemenuNewGame(bActivate);\r\n}\r\n\r\nvoid gamemenu_quit_game(bool bActivate)\r\n{\r\n\tGamemenuNewGame(bActivate);\r\n#ifndef NOEXIT\r\n\tgbRunGameResult = false;\r\n#else\r\n\tReturnToMainMenu = true;\r\n#endif\r\n}\r\n\r\nvoid gamemenu_load_game(bool /*bActivate*/)\r\n{\r\n\tEventHandler saveProc = SetEventHandler(DisableInputEventHandler);\r\n\tgamemenu_off();\r\n\tClearFloatingNumbers();\r\n\tNewCursor(CURSOR_NONE);\r\n\tInitDiabloMsg(EMSG_LOADING);\r\n\tRedrawEverything();\r\n\tDrawAndBlit();\r\n\r\n\tconst std::array<SDL_Color, 256> prevPalette = logical_palette;\r\n#ifndef USE_SDL1\r\n\tDeactivateVirtualGamepad();\r\n\tFreeVirtualGamepadTextures();\r\n#endif\r\n\tif (tl::expected<void, std::string> result = LoadGame(false); !result.has_value()) {\r\n\t\tapp_fatal(result.error());\r\n\t}\r\n#if !defined(USE_SDL1) && !defined(__vita__)\r\n\tif (renderer != nullptr) {\r\n\t\tInitVirtualGamepadTextures(*renderer);\r\n\t}\r\n#endif\r\n\tClrDiabloMsg();\r\n\tPaletteFadeOut(8, prevPalette);\r\n\r\n\tLoadPWaterPalette();\r\n\tNewCursor(CURSOR_HAND);\r\n\tCornerStone.activated = false;\r\n\tMyPlayerIsDead = false;\r\n\tRedrawEverything();\r\n\tDrawAndBlit();\r\n\tPaletteFadeIn(8);\r\n\tNewCursor(CURSOR_HAND);\r\n\tinterface_msg_pump();\r\n\tSetEventHandler(saveProc);\r\n}\r\n\r\nvoid gamemenu_save_game(bool /*bActivate*/)\r\n{\r\n\tif (pcurs != CURSOR_HAND) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (MyPlayer->_pmode == PM_DEATH || MyPlayerIsDead) {\r\n\t\tgamemenu_off();\r\n\t\treturn;\r\n\t}\r\n\r\n\tEventHandler saveProc = SetEventHandler(DisableInputEventHandler);\r\n\tNewCursor(CURSOR_NONE);\r\n\tgamemenu_off();\r\n\tInitDiabloMsg(EMSG_SAVING);\r\n\tRedrawEverything();\r\n\tDrawAndBlit();\r\n\tconst uint32_t currentTime = SDL_GetTicks();\r\n\tSaveGame();\r\n\tClrDiabloMsg();\r\n\tInitDiabloMsg(EMSG_GAME_SAVED, currentTime + 1000 - SDL_GetTicks());\r\n\tRedrawEverything();\r\n\tNewCursor(CURSOR_HAND);\r\n\tif (CornerStone.activated) {\r\n\t\tCornerstoneSave();\r\n\t\tif (!demo::IsRunning()) SaveOptions();\r\n\t}\r\n\tinterface_msg_pump();\r\n\tSetEventHandler(saveProc);\r\n}\r\n\r\nvoid gamemenu_on()\r\n{\r\n\tisGameMenuOpen = true;\r\n\tif (!gbIsMultiplayer) {\r\n\t\tgmenu_set_items(sgSingleMenu, GamemenuUpdateSingle);\r\n\t} else {\r\n\t\tgmenu_set_items(sgMultiMenu, nullptr);\r\n\t}\r\n\tPressEscKey();\r\n}\r\n\r\nvoid gamemenu_off()\r\n{\r\n\tisGameMenuOpen = false;\r\n\tgmenu_set_items(nullptr, nullptr);\r\n}\r\n\r\nvoid gamemenu_handle_previous()\r\n{\r\n\tif (gmenu_is_active())\r\n\t\tgamemenu_off();\r\n\telse\r\n\t\tgamemenu_on();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/gamemenu.h",
    "content": "/**\r\n * @file gamemenu.h\r\n *\r\n * Interface of the in-game menu functions.\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\n\r\nvoid gamemenu_on();\r\nvoid gamemenu_off();\r\nvoid gamemenu_handle_previous();\r\nvoid gamemenu_exit_game(bool bActivate);\r\nvoid gamemenu_quit_game(bool bActivate);\r\nvoid gamemenu_load_game(bool bActivate);\r\nvoid gamemenu_save_game(bool bActivate);\r\n\r\nextern bool isGameMenuOpen;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/gmenu.cpp",
    "content": "/**\r\n * @file gmenu.cpp\r\n *\r\n * Implementation of the in-game navigation and interaction.\r\n */\r\n#include \"gmenu.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keycode.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"appfat.h\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/axis_direction.h\"\r\n#include \"controls/controller_motion.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"options.h\"\r\n#include \"stores.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n// Width of the slider menu item, including the label.\r\nconstexpr int SliderItemWidth = 490;\r\n\r\n// Horizontal dimensions of the slider value\r\nconstexpr int SliderValueBoxLeft = 16 + SliderItemWidth / 2;\r\nconstexpr int SliderValueBoxWidth = 287;\r\n\r\nconstexpr int SliderValueBorderWidth = 2;\r\nconstexpr int SliderValueLeft = SliderValueBoxLeft + SliderValueBorderWidth;\r\nconstexpr int SliderValueWidth = SliderValueBoxWidth - 2 * SliderValueBorderWidth;\r\nconstexpr int SliderValueHeight = 29;\r\nconstexpr int SliderValuePaddingTop = 10;\r\nconstexpr int SliderMarkerWidth = 27;\r\n\r\nconstexpr int SliderFillMin = SliderMarkerWidth / 2;\r\nconstexpr int SliderFillMax = SliderValueWidth - SliderMarkerWidth / 2 - 1;\r\n\r\nconstexpr int GMenuTop = 117;\r\nconstexpr int GMenuItemHeight = 45;\r\n\r\nOptionalOwnedClxSpriteList optbar_cel;\r\nOptionalOwnedClxSpriteList PentSpin_cel;\r\nOptionalOwnedClxSpriteList option_cel;\r\nOptionalOwnedClxSpriteList sgpLogo;\r\nbool isDraggingSlider;\r\nTMenuItem *sgpCurrItem;\r\nint LogoAnim_tick;\r\nuint8_t LogoAnim_frame;\r\nvoid (*gmenu_current_option)();\r\nint sgCurrentMenuIdx;\r\n\r\nvoid GmenuUpDown(bool isDown)\r\n{\r\n\tif (sgpCurrItem == nullptr) {\r\n\t\treturn;\r\n\t}\r\n\tisDraggingSlider = false;\r\n\tint i = sgCurrentMenuIdx;\r\n\tif (sgCurrentMenuIdx != 0) {\r\n\t\twhile (i != 0) {\r\n\t\t\ti--;\r\n\t\t\tif (isDown) {\r\n\t\t\t\tsgpCurrItem++;\r\n\t\t\t\tif (sgpCurrItem->fnMenu == nullptr)\r\n\t\t\t\t\tsgpCurrItem = &sgpCurrentMenu[0];\r\n\t\t\t} else {\r\n\t\t\t\tif (sgpCurrItem == sgpCurrentMenu)\r\n\t\t\t\t\tsgpCurrItem = &sgpCurrentMenu[sgCurrentMenuIdx];\r\n\t\t\t\tsgpCurrItem--;\r\n\t\t\t}\r\n\t\t\tif (sgpCurrItem->enabled()) {\r\n\t\t\t\tif (i != 0)\r\n\t\t\t\t\tPlaySFX(SfxID::MenuMove);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid GmenuLeftRight(bool isRight)\r\n{\r\n\tif (!sgpCurrItem->isSlider())\r\n\t\treturn;\r\n\r\n\tuint16_t step = sgpCurrItem->sliderStep();\r\n\tif (isRight) {\r\n\t\tif (step == sgpCurrItem->sliderSteps())\r\n\t\t\treturn;\r\n\t\tstep++;\r\n\t} else {\r\n\t\tif (step == 0)\r\n\t\t\treturn;\r\n\t\tstep--;\r\n\t}\r\n\tsgpCurrItem->setSliderStep(step);\r\n\tsgpCurrItem->fnMenu(false);\r\n}\r\n\r\nint GmenuGetLineWidth(TMenuItem *pItem)\r\n{\r\n\tif (pItem->isSlider())\r\n\t\treturn SliderItemWidth;\r\n\r\n\treturn GetLineWidth(_(pItem->pszStr), GameFont46, 2);\r\n}\r\n\r\nvoid GmenuDrawMenuItem(const Surface &out, TMenuItem *pItem, int y)\r\n{\r\n\tconst int w = GmenuGetLineWidth(pItem);\r\n\tif (pItem->isSlider()) {\r\n\t\tconst int uiPositionX = GetUIRectangle().position.x;\r\n\t\tClxDraw(out, { SliderValueBoxLeft + uiPositionX, y + 40 }, (*optbar_cel)[0]);\r\n\t\tconst uint16_t step = pItem->dwFlags & 0xFFF;\r\n\t\tconst uint16_t steps = std::max<uint16_t>(pItem->sliderSteps(), 2);\r\n\t\tconst uint16_t pos = SliderFillMin + step * (SliderFillMax - SliderFillMin) / steps;\r\n\t\tSDL_Rect rect = MakeSdlRect(SliderValueLeft + uiPositionX, y + SliderValuePaddingTop, pos, SliderValueHeight);\r\n\t\tSDL_FillSurfaceRect(out.surface, &rect, 205);\r\n\t\tClxDraw(out, { SliderValueLeft + pos - SliderMarkerWidth / 2 + uiPositionX, y + SliderValuePaddingTop + SliderValueHeight - 1 }, (*option_cel)[0]);\r\n\t}\r\n\r\n\tconst int x = (gnScreenWidth - w) / 2;\r\n\tconst UiFlags style = pItem->enabled() ? UiFlags::ColorGold : UiFlags::ColorBlack;\r\n\tDrawString(out, _(pItem->pszStr), Point { x, y },\r\n\t    { .flags = style | UiFlags::FontSize46, .spacing = 2 });\r\n\tif (pItem == sgpCurrItem) {\r\n\t\tconst ClxSprite sprite = (*PentSpin_cel)[PentSpn2Spin()];\r\n\t\tClxDraw(out, { x - 54, y + 51 }, sprite);\r\n\t\tClxDraw(out, { x + 4 + w, y + 51 }, sprite);\r\n\t}\r\n}\r\n\r\nvoid GameMenuMove()\r\n{\r\n\tstatic AxisDirectionRepeater repeater;\r\n\tconst AxisDirection moveDir = repeater.Get(GetLeftStickOrDpadDirection(false));\r\n\tif (moveDir.x != AxisDirectionX_NONE)\r\n\t\tGmenuLeftRight(moveDir.x == AxisDirectionX_RIGHT);\r\n\tif (moveDir.y != AxisDirectionY_NONE)\r\n\t\tGmenuUpDown(moveDir.y == AxisDirectionY_DOWN);\r\n}\r\n\r\nbool GmenuMouseIsOverSlider()\r\n{\r\n\tconst int uiPositionX = GetUIRectangle().position.x;\r\n\tif (MousePosition.x < SliderValueLeft + uiPositionX) {\r\n\t\treturn false;\r\n\t}\r\n\tif (MousePosition.x >= SliderValueLeft + SliderValueWidth + uiPositionX) {\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nint GmenuGetSliderFill()\r\n{\r\n\treturn std::clamp(MousePosition.x - SliderValueLeft - GetUIRectangle().position.x, SliderFillMin, SliderFillMax);\r\n}\r\n\r\n} // namespace\r\n\r\nTMenuItem *sgpCurrentMenu;\r\n\r\nvoid gmenu_draw_pause(const Surface &out)\r\n{\r\n\tif (leveltype != DTYPE_TOWN)\r\n\t\tRedBack(out);\r\n\tif (sgpCurrentMenu == nullptr) {\r\n\t\tDrawString(out, _(\"Pause\"), { { 0, 0 }, { gnScreenWidth, GetMainPanel().position.y } },\r\n\t\t    { .flags = UiFlags::FontSize46 | UiFlags::ColorGold | UiFlags::AlignCenter | UiFlags::VerticalCenter, .spacing = 2 });\r\n\t}\r\n}\r\n\r\nvoid FreeGMenu()\r\n{\r\n\tsgpLogo = std::nullopt;\r\n\tPentSpin_cel = std::nullopt;\r\n\toption_cel = std::nullopt;\r\n\toptbar_cel = std::nullopt;\r\n}\r\n\r\nvoid gmenu_init_menu()\r\n{\r\n\tLogoAnim_frame = 0;\r\n\tsgpCurrentMenu = nullptr;\r\n\tsgpCurrItem = nullptr;\r\n\tgmenu_current_option = nullptr;\r\n\tsgCurrentMenuIdx = 0;\r\n\tisDraggingSlider = false;\r\n\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tsgpLogo = LoadOptionalCel(\"data\\\\hf_logo3\", 430);\r\n\tif (!sgpLogo.has_value())\r\n\t\tsgpLogo = LoadCel(\"data\\\\diabsmal\", 296);\r\n\tPentSpin_cel = LoadCel(\"data\\\\pentspin\", 48);\r\n\toption_cel = LoadCel(\"data\\\\option\", SliderMarkerWidth);\r\n\toptbar_cel = LoadCel(\"data\\\\optbar\", SliderValueBoxWidth);\r\n}\r\n\r\nbool gmenu_is_active()\r\n{\r\n\treturn sgpCurrentMenu != nullptr;\r\n}\r\n\r\nvoid gmenu_set_items(TMenuItem *pItem, void (*gmFunc)())\r\n{\r\n\tPauseMode = 0;\r\n\tisDraggingSlider = false;\r\n\tsgpCurrentMenu = pItem;\r\n\tgmenu_current_option = gmFunc;\r\n\tif (gmenu_current_option != nullptr) {\r\n\t\tgmenu_current_option();\r\n\t}\r\n\tsgCurrentMenuIdx = 0;\r\n\tif (sgpCurrentMenu != nullptr) {\r\n\t\tfor (int i = 0; sgpCurrentMenu[i].fnMenu != nullptr; i++) {\r\n\t\t\tsgCurrentMenuIdx++;\r\n\t\t}\r\n\t}\r\n\t// BUGFIX: OOB access when sgCurrentMenuIdx is 0; should be set to NULL instead. (fixed)\r\n\tsgpCurrItem = sgCurrentMenuIdx > 0 ? &sgpCurrentMenu[sgCurrentMenuIdx - 1] : nullptr;\r\n\tGmenuUpDown(true);\r\n\tif (sgpCurrentMenu == nullptr && !demo::IsRunning()) {\r\n\t\tSaveOptions();\r\n\t}\r\n}\r\n\r\nvoid gmenu_draw(const Surface &out)\r\n{\r\n\tif (sgpCurrentMenu != nullptr) {\r\n\t\tGameMenuMove();\r\n\t\tif (gmenu_current_option != nullptr)\r\n\t\t\tgmenu_current_option();\r\n\t\tif (sgpLogo->numSprites() > 1) {\r\n\t\t\tconst uint32_t ticks = SDL_GetTicks();\r\n\t\t\tif ((int)(ticks - LogoAnim_tick) > 25) {\r\n\t\t\t\t++LogoAnim_frame;\r\n\t\t\t\tLogoAnim_frame = LogoAnim_frame % sgpLogo->numSprites();\r\n\t\t\t\tLogoAnim_tick = ticks;\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst int uiPositionY = GetUIRectangle().position.y;\r\n\t\tconst ClxSprite sprite = (*sgpLogo)[LogoAnim_frame];\r\n\t\tClxDraw(out, { (gnScreenWidth - sprite.width()) / 2, 102 + uiPositionY }, sprite);\r\n\t\tint y = 110 + uiPositionY;\r\n\t\tTMenuItem *i = sgpCurrentMenu;\r\n\t\tif (sgpCurrentMenu->fnMenu != nullptr) {\r\n\t\t\twhile (i->fnMenu != nullptr) {\r\n\t\t\t\tGmenuDrawMenuItem(out, i, y);\r\n\t\t\t\ti++;\r\n\t\t\t\ty += GMenuItemHeight;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool gmenu_presskeys(SDL_Keycode vkey)\r\n{\r\n\tif (sgpCurrentMenu == nullptr)\r\n\t\treturn false;\r\n\tswitch (vkey) {\r\n\tcase SDLK_KP_ENTER:\r\n\tcase SDLK_RETURN:\r\n\t\tif (sgpCurrItem->enabled()) {\r\n\t\t\tPlaySFX(SfxID::MenuMove);\r\n\t\t\tsgpCurrItem->fnMenu(true);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase SDLK_ESCAPE:\r\n\t\tPlaySFX(SfxID::MenuMove);\r\n\t\tgmenu_set_items(nullptr, nullptr);\r\n\t\tbreak;\r\n\tcase SDLK_SPACE:\r\n\t\treturn false;\r\n\tcase SDLK_LEFT:\r\n\t\tGmenuLeftRight(false);\r\n\t\tbreak;\r\n\tcase SDLK_RIGHT:\r\n\t\tGmenuLeftRight(true);\r\n\t\tbreak;\r\n\tcase SDLK_UP:\r\n\t\tGmenuUpDown(false);\r\n\t\tbreak;\r\n\tcase SDLK_DOWN:\r\n\t\tGmenuUpDown(true);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool gmenu_on_mouse_move()\r\n{\r\n\tif (!isDraggingSlider)\r\n\t\treturn false;\r\n\r\n\tconst uint16_t step = sgpCurrItem->sliderSteps() * (GmenuGetSliderFill() - SliderFillMin) / (SliderFillMax - SliderFillMin);\r\n\tsgpCurrItem->setSliderStep(step);\r\n\tsgpCurrItem->fnMenu(false);\r\n\r\n\treturn true;\r\n}\r\n\r\nbool gmenu_left_mouse(bool isDown)\r\n{\r\n\tif (!isDown) {\r\n\t\tif (isDraggingSlider) {\r\n\t\t\tisDraggingSlider = false;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (sgpCurrentMenu == nullptr) {\r\n\t\treturn false;\r\n\t}\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tif (MousePosition.y >= GetMainPanel().position.y) {\r\n\t\treturn false;\r\n\t}\r\n\tif (MousePosition.y - (GMenuTop + uiPosition.y) < 0) {\r\n\t\treturn true;\r\n\t}\r\n\tconst int i = (MousePosition.y - (GMenuTop + uiPosition.y)) / GMenuItemHeight;\r\n\tif (i >= sgCurrentMenuIdx) {\r\n\t\treturn true;\r\n\t}\r\n\tTMenuItem *pItem = &sgpCurrentMenu[i];\r\n\tif (!pItem->enabled()) {\r\n\t\treturn true;\r\n\t}\r\n\tconst int w = GmenuGetLineWidth(pItem);\r\n\tconst uint16_t screenWidth = GetScreenWidth();\r\n\tif (MousePosition.x < screenWidth / 2 - w / 2) {\r\n\t\treturn true;\r\n\t}\r\n\tif (MousePosition.x > screenWidth / 2 + w / 2) {\r\n\t\treturn true;\r\n\t}\r\n\tsgpCurrItem = pItem;\r\n\tPlaySFX(SfxID::MenuMove);\r\n\tif (pItem->isSlider()) {\r\n\t\tisDraggingSlider = GmenuMouseIsOverSlider();\r\n\t\tgmenu_on_mouse_move();\r\n\t} else {\r\n\t\tsgpCurrItem->fnMenu(true);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid gmenu_slider_set(TMenuItem *pItem, int min, int max, int value)\r\n{\r\n\tassert(pItem);\r\n\tconst uint16_t nSteps = std::max<uint16_t>(pItem->sliderSteps(), 2);\r\n\tpItem->setSliderStep(((max - min - 1) / 2 + (value - min) * nSteps) / (max - min));\r\n}\r\n\r\nint gmenu_slider_get(TMenuItem *pItem, int min, int max)\r\n{\r\n\tconst uint16_t step = pItem->sliderStep();\r\n\tconst uint16_t steps = std::max<uint16_t>(pItem->sliderSteps(), 2);\r\n\treturn min + (step * (max - min) + (steps - 1) / 2) / steps;\r\n}\r\n\r\nvoid gmenu_slider_steps(TMenuItem *pItem, int steps)\r\n{\r\n\tpItem->dwFlags &= 0xFF000FFF;\r\n\tpItem->setSliderSteps(steps);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/gmenu.h",
    "content": "/**\r\n * @file gmenu.h\r\n *\r\n * Interface of the in-game navigation and interaction.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#define GMENU_SLIDER 0x40000000\r\n#define GMENU_ENABLED 0x80000000\r\n\r\nstruct TMenuItem {\r\n\tuint32_t dwFlags;\r\n\tconst char *pszStr;\r\n\tvoid (*fnMenu)(bool);\r\n\r\n\t[[nodiscard]] bool enabled() const\r\n\t{\r\n\t\treturn (dwFlags & GMENU_ENABLED) != 0;\r\n\t}\r\n\r\n\t[[nodiscard]] bool isSlider() const\r\n\t{\r\n\t\treturn (dwFlags & GMENU_SLIDER) != 0;\r\n\t}\r\n\r\n\t[[nodiscard]] uint16_t sliderStep() const\r\n\t{\r\n\t\treturn dwFlags & 0xFFF;\r\n\t}\r\n\r\n\tvoid setSliderStep(uint16_t step)\r\n\t{\r\n\t\tdwFlags &= 0xFFFFF000;\r\n\t\tdwFlags |= step;\r\n\t}\r\n\r\n\t[[nodiscard]] uint16_t sliderSteps() const\r\n\t{\r\n\t\treturn (dwFlags & 0xFFF000) >> 12;\r\n\t}\r\n\r\n\tvoid setSliderSteps(uint16_t steps)\r\n\t{\r\n\t\tdwFlags |= (steps << 12) & 0xFFF000;\r\n\t}\r\n\r\n\tvoid addFlags(uint32_t flags)\r\n\t{\r\n\t\tdwFlags |= flags;\r\n\t}\r\n\r\n\tvoid removeFlags(uint32_t flags)\r\n\t{\r\n\t\tdwFlags &= ~flags;\r\n\t}\r\n\r\n\tvoid setEnabled(bool enabled)\r\n\t{\r\n\t\tif (enabled) {\r\n\t\t\taddFlags(GMENU_ENABLED);\r\n\t\t} else {\r\n\t\t\tremoveFlags(GMENU_ENABLED);\r\n\t\t}\r\n\t}\r\n};\r\n\r\nextern TMenuItem *sgpCurrentMenu;\r\n\r\nvoid gmenu_draw_pause(const Surface &out);\r\nvoid FreeGMenu();\r\nvoid gmenu_init_menu();\r\nbool gmenu_is_active();\r\nvoid gmenu_set_items(TMenuItem *pItem, void (*gmFunc)());\r\nvoid gmenu_draw(const Surface &out);\r\nbool gmenu_presskeys(SDL_Keycode vkey);\r\nbool gmenu_on_mouse_move();\r\nbool gmenu_left_mouse(bool isDown);\r\n\r\n/**\r\n * @brief Set the TMenuItem slider position based on the given value\r\n */\r\nvoid gmenu_slider_set(TMenuItem *pItem, int min, int max, int value);\r\n\r\n/**\r\n * @brief Get the current value for the slider\r\n */\r\nint gmenu_slider_get(TMenuItem *pItem, int min, int max);\r\n\r\n/**\r\n * @brief Set the number of steps for the slider\r\n */\r\nvoid gmenu_slider_steps(TMenuItem *pItem, int steps);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/headless_mode.cpp",
    "content": "#include \"headless_mode.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool HeadlessMode;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/headless_mode.hpp",
    "content": "#pragma once\r\n\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Don't load UI or show Messageboxes or other user-interaction. Needed for unit tests.\r\n */\r\nextern DVL_API_FOR_TEST bool HeadlessMode;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/help.cpp",
    "content": "/**\r\n * @file help.cpp\r\n *\r\n * Implementation of the in-game help text.\r\n */\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"minitext.h\"\r\n#include \"qol/chatlog.h\"\r\n#include \"stores.h\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool HelpFlag;\r\n\r\nnamespace {\r\n\r\nunsigned int SkipLines;\r\n\r\nconst char *const HelpText[] = {\r\n\tN_(\"$Keyboard Shortcuts:\"),\r\n\tN_(\"F1:    Open Help Screen\"),\r\n\tN_(\"Esc:   Display Main Menu\"),\r\n\tN_(\"Tab:   Display Auto-map\"),\r\n\tN_(\"Space: Hide all info screens\"),\r\n\tN_(\"S: Open Speedbook\"),\r\n\tN_(\"B: Open Spellbook\"),\r\n\tN_(\"I: Open Inventory screen\"),\r\n\tN_(\"C: Open Character screen\"),\r\n\tN_(\"Q: Open Quest log\"),\r\n\tN_(\"F: Reduce screen brightness\"),\r\n\tN_(\"G: Increase screen brightness\"),\r\n\tN_(\"Z: Zoom Game Screen\"),\r\n\tN_(\"+ / -: Zoom Automap\"),\r\n\tN_(\"1 - 8: Use Belt item\"),\r\n\tN_(\"F5, F6, F7, F8:     Set hotkey for skill or spell\"),\r\n\tN_(\"Shift + Left Mouse Button: Attack without moving\"),\r\n\tN_(\"Shift + Left Mouse Button (on character screen): Assign all stat points\"),\r\n\tN_(\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip item\"),\r\n\tN_(\"Shift + Left Mouse Button (on belt): Move item to inventory\"),\r\n\t\"\",\r\n\tN_(\"$Movement:\"),\r\n\tN_(\"If you hold the mouse button down while moving, the character \"\r\n\t   \"will continue to move in that direction.\"),\r\n\t\"\",\r\n\tN_(\"$Combat:\"),\r\n\tN_(\"Holding down the shift key and then left-clicking allows the \"\r\n\t   \"character to attack without moving.\"),\r\n\t\"\",\r\n\tN_(\"$Auto-map:\"),\r\n\tN_(\"To access the auto-map, click the 'MAP' button on the \"\r\n\t   \"Information Bar or press 'TAB' on the keyboard. Zooming in and \"\r\n\t   \"out of the map is done with the + and - keys. Scrolling the map \"\r\n\t   \"uses the arrow keys.\"),\r\n\t\"\",\r\n\tN_(\"$Picking up Objects:\"),\r\n\tN_(\"Useable items that are small in size, such as potions or scrolls, \"\r\n\t   \"are automatically placed in your 'belt' located at the top of \"\r\n\t   \"the Interface bar . When an item is placed in the belt, a small \"\r\n\t   \"number appears in that box. Items may be used by either pressing \"\r\n\t   \"the corresponding number or right-clicking on the item.\"),\r\n\t\"\",\r\n\tN_(\"$Gold:\"),\r\n\tN_(\"You can select a specific amount of gold to drop by \"\r\n\t   \"right-clicking on a pile of gold in your inventory.\"),\r\n\t\"\",\r\n\tN_(\"$Skills & Spells:\"),\r\n\tN_(\"You can access your list of skills and spells by left-clicking on \"\r\n\t   \"the 'SPELLS' button in the interface bar. Memorized spells and \"\r\n\t   \"those available through staffs are listed here. Left-clicking on \"\r\n\t   \"the spell you wish to cast will ready the spell. A readied spell \"\r\n\t   \"may be cast by simply right-clicking in the play area.\"),\r\n\t\"\",\r\n\tN_(\"$Using the Speedbook for Spells:\"),\r\n\tN_(\"Left-clicking on the 'readied spell' button will open the 'Speedbook' \"\r\n\t   \"which allows you to select a skill or spell for immediate use. \"\r\n\t   \"To use a readied skill or spell, simply right-click in the main play \"\r\n\t   \"area.\"),\r\n\tN_(\"Shift + Left-clicking on the 'select current spell' button will clear the readied spell.\"),\r\n\t\"\",\r\n\tN_(\"$Setting Spell Hotkeys:\"),\r\n\tN_(\"You can assign up to four Hotkeys for skills, spells or scrolls. \"\r\n\t   \"Start by opening the 'speedbook' as described in the section above. \"\r\n\t   \"Press the F5, F6, F7 or F8 keys after highlighting the spell you \"\r\n\t   \"wish to assign.\"),\r\n\t\"\",\r\n\tN_(\"$Spell Books:\"),\r\n\tN_(\"Reading more than one book increases your knowledge of that \"\r\n\t   \"spell, allowing you to cast the spell more effectively.\"),\r\n};\r\n\r\nstd::vector<std::string> HelpTextLines;\r\n\r\nconstexpr int PaddingTop = 32;\r\nconstexpr int PaddingLeft = 32;\r\n\r\nconstexpr int PanelHeight = 297;\r\nconstexpr int ContentTextWidth = 565;\r\n\r\nint LineHeight()\r\n{\r\n\treturn IsSmallFontTall() ? 18 : 14;\r\n}\r\n\r\nint BlankLineHeight()\r\n{\r\n\treturn 12;\r\n}\r\n\r\nint DividerLineMarginY()\r\n{\r\n\treturn BlankLineHeight() / 2;\r\n}\r\n\r\nint HeaderHeight()\r\n{\r\n\treturn PaddingTop + LineHeight() + 2 * BlankLineHeight() + DividerLineMarginY();\r\n}\r\n\r\nint ContentPaddingY()\r\n{\r\n\treturn BlankLineHeight();\r\n}\r\n\r\nint ContentsTextHeight()\r\n{\r\n\treturn PanelHeight - HeaderHeight() - DividerLineMarginY() - 2 * ContentPaddingY() - BlankLineHeight();\r\n}\r\n\r\nint NumVisibleLines()\r\n{\r\n\treturn (ContentsTextHeight() - 1) / LineHeight() + 1; // Ceil\r\n}\r\n\r\nvoid DrawHelpSlider(const Surface &out)\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tconst int sliderXPos = ContentTextWidth + uiPosition.x + 36;\r\n\tint sliderStart = uiPosition.y + HeaderHeight() + LineHeight() + 3;\r\n\tconst int sliderEnd = uiPosition.y + PaddingTop + PanelHeight - 12;\r\n\tClxDraw(out, { sliderXPos, sliderStart }, (*pSTextSlidCels)[11]);\r\n\tsliderStart += 12;\r\n\tint sliderCurrent = sliderStart;\r\n\tfor (; sliderCurrent < sliderEnd; sliderCurrent += 12) {\r\n\t\tClxDraw(out, { sliderXPos, sliderCurrent }, (*pSTextSlidCels)[13]);\r\n\t}\r\n\tClxDraw(out, { sliderXPos, sliderCurrent }, (*pSTextSlidCels)[10]);\r\n\t// Subtract visible lines from the total number of lines to get the actual\r\n\t// scroll range\r\n\tconst int scrollRange = static_cast<int>(HelpTextLines.size()) - NumVisibleLines();\r\n\t// Subtract the size of the arrow buttons to get the length of the interior\r\n\t// part of the slider\r\n\tconst int sliderLength = sliderCurrent - 12 - sliderStart;\r\n\tClxDraw(out, { sliderXPos, sliderStart + ((static_cast<int>(SkipLines) * sliderLength) / scrollRange) }, (*pSTextSlidCels)[12]);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InitHelp()\r\n{\r\n\tstatic bool Initialized = false;\r\n\tif (Initialized)\r\n\t\treturn;\r\n\r\n\tHelpFlag = false;\r\n\r\n\tfor (const auto *text : HelpText) {\r\n\t\tconst std::string paragraph = WordWrapString(_(text), ContentTextWidth);\r\n\r\n\t\tsize_t previous = 0;\r\n\t\twhile (true) {\r\n\t\t\tconst size_t next = paragraph.find('\\n', previous);\r\n\t\t\tHelpTextLines.emplace_back(paragraph.substr(previous, next - previous));\r\n\t\t\tif (next == std::string::npos)\r\n\t\t\t\tbreak;\r\n\t\t\tprevious = next + 1;\r\n\t\t}\r\n\t}\r\n\r\n\tInitialized = true;\r\n}\r\n\r\nvoid DrawHelp(const Surface &out)\r\n{\r\n\tDrawSTextHelp();\r\n\tDrawQTextBack(out);\r\n\r\n\tconst int lineHeight = LineHeight();\r\n\tconst int blankLineHeight = BlankLineHeight();\r\n\r\n\tstd::string_view title;\r\n\tif (gbIsHellfire)\r\n\t\ttitle = gbIsSpawn ? _(\"Shareware Hellfire Help\") : _(\"Hellfire Help\");\r\n\telse\r\n\t\ttitle = gbIsSpawn ? _(\"Shareware Diablo Help\") : _(\"Diablo Help\");\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tconst int sx = uiPosition.x + PaddingLeft;\r\n\tconst int sy = uiPosition.y;\r\n\r\n\tDrawString(out, title,\r\n\t    { { sx, sy + PaddingTop + blankLineHeight }, { ContentTextWidth, lineHeight } },\r\n\t    { .flags = UiFlags::ColorWhitegold | UiFlags::AlignCenter });\r\n\r\n\tconst int titleBottom = sy + HeaderHeight();\r\n\tDrawSLine(out, titleBottom);\r\n\r\n\tconst int numLines = NumVisibleLines();\r\n\tconst int contentY = titleBottom + DividerLineMarginY() + ContentPaddingY();\r\n\tfor (int i = 0; i < numLines; i++) {\r\n\t\tconst std::string_view line = HelpTextLines[i + SkipLines];\r\n\t\tif (line.empty()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tint offset = 0;\r\n\t\tUiFlags style = UiFlags::ColorWhite;\r\n\t\tif (line[0] == '$') {\r\n\t\t\toffset = 1;\r\n\t\t\tstyle = UiFlags::ColorBlue;\r\n\t\t}\r\n\r\n\t\tDrawString(out, line.substr(offset), { { sx, contentY + i * lineHeight }, { ContentTextWidth, lineHeight } },\r\n\t\t    { .flags = style, .lineHeight = lineHeight });\r\n\t}\r\n\r\n\tDrawString(out, _(\"Press ESC to end or the arrow keys to scroll.\"),\r\n\t    { { sx, contentY + ContentsTextHeight() + ContentPaddingY() + blankLineHeight }, { ContentTextWidth, lineHeight } },\r\n\t    { .flags = UiFlags::ColorWhitegold | UiFlags::AlignCenter });\r\n\r\n\tDrawHelpSlider(out);\r\n}\r\n\r\nvoid DisplayHelp()\r\n{\r\n\tSkipLines = 0;\r\n\tHelpFlag = true;\r\n\tChatLogFlag = false;\r\n}\r\n\r\nvoid HelpScrollUp()\r\n{\r\n\tif (SkipLines > 0)\r\n\t\tSkipLines--;\r\n}\r\n\r\nvoid HelpScrollDown()\r\n{\r\n\tif (SkipLines + NumVisibleLines() < HelpTextLines.size())\r\n\t\tSkipLines++;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/help.h",
    "content": "/**\r\n * @file help.h\r\n *\r\n * Interface of the in-game help text.\r\n */\r\n#pragma once\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern bool HelpFlag;\r\n\r\nvoid InitHelp();\r\nvoid DrawHelp(const Surface &out);\r\nvoid DisplayHelp();\r\nvoid HelpScrollUp();\r\nvoid HelpScrollDown();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/hwcursor.cpp",
    "content": "#include \"hwcursor.hpp\"\r\n\r\n#include <cstdint>\r\n#include <tuple>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_mouse.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL_version.h>\r\n\r\n#ifndef USE_SDL1\r\n#include <SDL_mouse.h>\r\n#include <SDL_render.h>\r\n#include <SDL_surface.h>\r\n#endif\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n\r\n#include \"appfat.h\"\r\n#include \"cursor.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/sdl_bilinear_scale.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nCursorInfo CurrentCursorInfo;\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nSDLCursorUniquePtr CurrentCursor;\r\n\r\nenum class HotpointPosition : uint8_t {\r\n\tTopLeft,\r\n\tCenter,\r\n};\r\n\r\nSize ScaledSize(Size size)\r\n{\r\n\tif (renderer != nullptr) {\r\n#ifdef USE_SDL3\r\n\t\tSDL_FRect logicalDstRect;\r\n\t\tint logicalWidth;\r\n\t\tint logicalHeight;\r\n\t\tif (!SDL_GetRenderLogicalPresentation(renderer, &logicalWidth, &logicalHeight, /*mode=*/nullptr)) {\r\n\t\t\tLogError(\"SDL_GetRenderOutputSize: {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t\treturn size;\r\n\t\t}\r\n\t\tif (!SDL_GetRenderLogicalPresentationRect(renderer, &logicalDstRect)) {\r\n\t\t\tLogError(\"SDL_GetRenderLogicalPresentationRect: {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t\treturn size;\r\n\t\t}\r\n\t\tconst float dispScale = SDL_GetWindowDisplayScale(ghMainWnd);\r\n\t\tif (dispScale == 0.0F) {\r\n\t\t\tLogError(\"SDL_GetWindowDisplayScale: {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t\treturn size;\r\n\t\t}\r\n\t\tconst float scaleX = logicalDstRect.w / static_cast<float>(logicalWidth);\r\n\t\tconst float scaleY = logicalDstRect.h / static_cast<float>(logicalHeight);\r\n\t\tsize.width = static_cast<int>(static_cast<float>(size.width) * scaleX / dispScale);\r\n\t\tsize.height = static_cast<int>(static_cast<float>(size.height) * scaleY / dispScale);\r\n#else\r\n\t\tfloat scaleX = 1.0F;\r\n\t\tfloat scaleY = 1.0F;\r\n\t\tif (!SDL_GetRenderScale(renderer, &scaleX, &scaleY)) {\r\n\t\t\tLogError(\"SDL_GetRenderScale: {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t}\r\n\t\tsize.width = static_cast<int>(size.width * scaleX);\r\n\t\tsize.height = static_cast<int>(size.height * scaleY);\r\n#endif\r\n\t}\r\n\treturn size;\r\n}\r\n\r\nbool IsCursorSizeAllowed(Size size)\r\n{\r\n\tif (*GetOptions().Graphics.hardwareCursorMaxSize <= 0)\r\n\t\treturn true;\r\n\tsize = ScaledSize(size);\r\n\treturn size.width <= *GetOptions().Graphics.hardwareCursorMaxSize\r\n\t    && size.height <= *GetOptions().Graphics.hardwareCursorMaxSize;\r\n}\r\n\r\nPoint GetHotpointPosition(const SDL_Surface &surface, HotpointPosition position)\r\n{\r\n\tswitch (position) {\r\n\tcase HotpointPosition::TopLeft:\r\n\t\treturn { 0, 0 };\r\n\tcase HotpointPosition::Center:\r\n\t\treturn { surface.w / 2, surface.h / 2 };\r\n\t}\r\n\tapp_fatal(\"Unhandled enum value\");\r\n}\r\n\r\nbool ShouldUseBilinearScaling()\r\n{\r\n\treturn *GetOptions().Graphics.scaleQuality != ScalingQuality::NearestPixel;\r\n}\r\n\r\nbool SetHardwareCursorFromSurface(SDL_Surface *surface, HotpointPosition hotpointPosition)\r\n{\r\n\tSDLCursorUniquePtr newCursor;\r\n\tconst Size size { surface->w, surface->h };\r\n\tconst Size scaledSize = ScaledSize(size);\r\n\r\n\tif (size == scaledSize) {\r\n#if LOG_HWCURSOR\r\n\t\tLog(\"hwcursor: SetHardwareCursorFromSurface {}x{}\", size.width, size.height);\r\n#endif\r\n\t\tconst Point hotpoint = GetHotpointPosition(*surface, hotpointPosition);\r\n\t\tnewCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(surface, hotpoint.x, hotpoint.y) };\r\n\t} else {\r\n\t\t// SDL does not support BlitScaled from 8-bit to RGBA.\r\n\t\tconst SDLSurfaceUniquePtr converted {\r\n#ifdef USE_SDL3\r\n\t\t\tSDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888)\r\n#else\r\n\t\t\tSDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0)\r\n#endif\r\n\t\t};\r\n\r\n\t\tconst SDLSurfaceUniquePtr scaledSurface = SDLWrap::CreateRGBSurfaceWithFormat(0, scaledSize.width, scaledSize.height, 32, SDL_PIXELFORMAT_ARGB8888);\r\n\t\tif (ShouldUseBilinearScaling()) {\r\n#if LOG_HWCURSOR\r\n\t\t\tLog(\"hwcursor: SetHardwareCursorFromSurface {}x{} scaled to {}x{} using bilinear scaling\",\r\n\t\t\t    size.width, size.height, scaledSize.width, scaledSize.height);\r\n#endif\r\n\t\t\tBilinearScale32(converted.get(), scaledSurface.get());\r\n\t\t} else {\r\n#if LOG_HWCURSOR\r\n\t\t\tLog(\"hwcursor: SetHardwareCursorFromSurface {}x{} scaled to {}x{} using nearest neighbour scaling\",\r\n\t\t\t    size.width, size.height, scaledSize.width, scaledSize.height);\r\n#endif\r\n#ifdef USE_SDL3\r\n\t\t\tSDL_BlitSurfaceScaled(converted.get(), nullptr, scaledSurface.get(), nullptr, SDL_SCALEMODE_PIXELART);\r\n#else\r\n\t\t\tSDL_BlitScaled(converted.get(), nullptr, scaledSurface.get(), nullptr);\r\n#endif\r\n\t\t}\r\n\t\tconst Point hotpoint = GetHotpointPosition(*scaledSurface, hotpointPosition);\r\n\t\tnewCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(scaledSurface.get(), hotpoint.x, hotpoint.y) };\r\n\t}\r\n\tif (newCursor == nullptr) {\r\n\t\tLogError(\"SDL_CreateColorCursor: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn false;\r\n\t}\r\n#ifdef USE_SDL3\r\n\tif (!SDL_SetCursor(newCursor.get())) {\r\n\t\tLogError(\"SDL_SetCursor: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn false;\r\n\t}\r\n#else\r\n\tSDL_SetCursor(newCursor.get());\r\n#endif\r\n\tCurrentCursor = std::move(newCursor);\r\n\treturn true;\r\n}\r\n\r\nbool SetHardwareCursorFromClxSprite(ClxSprite sprite, HotpointPosition hotpointPosition)\r\n{\r\n\tconst OwnedSurface surface { sprite.width(), sprite.height() };\r\n\tif (!SDLC_SetSurfacePalette(surface.surface, Palette.get())) {\r\n\t\tLogError(\"SDL_SetSurfacePalette: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn false;\r\n\t}\r\n\tif (!SDL_SetSurfaceColorKey(surface.surface, true, 0)) {\r\n\t\tLogError(\"SDL_SetSurfaceColorKey: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn false;\r\n\t}\r\n\tRenderClxSprite(surface, sprite, { 0, 0 });\r\n\treturn SetHardwareCursorFromSurface(surface.surface, hotpointPosition);\r\n}\r\n\r\nbool SetHardwareCursorFromSprite(int pcurs)\r\n{\r\n\tconst bool isItem = !MyPlayer->HoldItem.isEmpty();\r\n\tif (isItem && !*GetOptions().Graphics.hardwareCursorForItems)\r\n\t\treturn false;\r\n\r\n\tconst int outlineWidth = isItem ? 1 : 0;\r\n\r\n\tauto size = GetInvItemSize(pcurs);\r\n\tsize.width += 2 * outlineWidth;\r\n\tsize.height += 2 * outlineWidth;\r\n\r\n\tif (!IsCursorSizeAllowed(size))\r\n\t\treturn false;\r\n\r\n\tconst OwnedSurface out { size };\r\n\tSDL_SetSurfacePalette(out.surface, Palette.get());\r\n\r\n\t// Transparent color must not be used in the sprite itself.\r\n\t// Colors 1-127 are outside of the UI palette so are safe to use.\r\n\tconstexpr std::uint8_t TransparentColor = 1;\r\n\tif (!SDL_FillSurfaceRect(out.surface, nullptr, TransparentColor)) {\r\n\t\tLogError(\"SDL_FillSurfaceRect: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn false;\r\n\t}\r\n\tif (!SDL_SetSurfaceColorKey(out.surface, true, TransparentColor)) {\r\n\t\tLogError(\"SDL_SetSurfaceColorKey: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn false;\r\n\t}\r\n\tDrawSoftwareCursor(out, { outlineWidth, size.height - outlineWidth - 1 }, pcurs);\r\n\r\n\tconst bool result = SetHardwareCursorFromSurface(\r\n\t    out.surface, isItem ? HotpointPosition::Center : HotpointPosition::TopLeft);\r\n\treturn result;\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\nCursorInfo &GetCurrentCursorInfo()\r\n{\r\n\treturn CurrentCursorInfo;\r\n}\r\n\r\nvoid SetHardwareCursor(CursorInfo cursorInfo)\r\n{\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tCurrentCursorInfo = cursorInfo;\r\n\tCurrentCursorInfo.setNeedsReinitialization(false);\r\n\tswitch (cursorInfo.type()) {\r\n\tcase CursorType::Game:\r\n#if LOG_HWCURSOR\r\n\t\tLog(\"hwcursor: SetHardwareCursor Game\");\r\n#endif\r\n\t\tCurrentCursorInfo.SetEnabled(SetHardwareCursorFromSprite(cursorInfo.id()));\r\n\t\tbreak;\r\n\tcase CursorType::UserInterface:\r\n#if LOG_HWCURSOR\r\n\t\tLog(\"hwcursor: SetHardwareCursor UserInterface\");\r\n#endif\r\n\t\t// ArtCursor is null while loading the game on the progress screen,\r\n\t\t// called via palette fade from ShowProgress.\r\n\t\tCurrentCursorInfo.SetEnabled(\r\n\t\t    ArtCursor && IsCursorSizeAllowed(Size { (*ArtCursor)[0].width(), (*ArtCursor)[0].height() })\r\n\t\t    && SetHardwareCursorFromClxSprite((*ArtCursor)[0], HotpointPosition::TopLeft));\r\n\t\tbreak;\r\n\tcase CursorType::Unknown:\r\n#if LOG_HWCURSOR\r\n\t\tLog(\"hwcursor: SetHardwareCursor Unknown\");\r\n#endif\r\n\t\tCurrentCursorInfo.SetEnabled(false);\r\n\t\tbreak;\r\n\t}\r\n\tif (!CurrentCursorInfo.Enabled())\r\n\t\tSetHardwareCursorVisible(false);\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/hwcursor.hpp",
    "content": "/**\r\n * @file hwcursor.hpp\r\n *\r\n * Hardware cursor (SDL2 only).\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL_version.h>\r\n#endif\r\n\r\n#include \"options.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\n// Set this to 1 to log the hardware cursor state changes.\r\n#define LOG_HWCURSOR 0\r\n\r\nnamespace devilution {\r\n\r\n// Whether the hardware cursor is enabled in settings.\r\ninline bool IsHardwareCursorEnabled()\r\n{\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\treturn *GetOptions().Graphics.hardwareCursor && HardwareCursorSupported();\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\nenum class CursorType : uint8_t {\r\n\tUnknown,\r\n\tUserInterface,\r\n\tGame,\r\n};\r\n\r\nclass CursorInfo {\r\npublic:\r\n\tCursorInfo() = default;\r\n\r\n\tstatic CursorInfo UserInterfaceCursor()\r\n\t{\r\n\t\treturn CursorInfo { CursorType::UserInterface };\r\n\t}\r\n\r\n\tstatic CursorInfo GameCursor(int gameSpriteId)\r\n\t{\r\n\t\treturn CursorInfo { CursorType::Game, gameSpriteId };\r\n\t}\r\n\r\n\tstatic CursorInfo UnknownCursor()\r\n\t{\r\n\t\treturn CursorInfo { CursorType::Unknown };\r\n\t}\r\n\r\n\t[[nodiscard]] CursorType type() const\r\n\t{\r\n\t\treturn type_;\r\n\t}\r\n\r\n\t[[nodiscard]] int id() const\r\n\t{\r\n\t\treturn id_;\r\n\t}\r\n\r\n\t[[nodiscard]] bool Enabled() const\r\n\t{\r\n\t\treturn enabled_;\r\n\t}\r\n\r\n\tvoid SetEnabled(bool value)\r\n\t{\r\n#if LOG_HWCURSOR\r\n\t\tif (enabled_ != value) {\r\n\t\t\tLog(\"hwcursor: SetEnabled {}\", value);\r\n\t\t}\r\n#endif\r\n\t\tenabled_ = value;\r\n\t}\r\n\r\n\t[[nodiscard]] bool needsReinitialization() const\r\n\t{\r\n\t\treturn needs_reinitialization_;\r\n\t}\r\n\r\n\tvoid setNeedsReinitialization(bool value)\r\n\t{\r\n#if LOG_HWCURSOR\r\n\t\tif (needs_reinitialization_ != value) {\r\n\t\t\tLog(\"hwcursor: setNeedsReinitialization {}\", value);\r\n\t\t}\r\n#endif\r\n\t\tneeds_reinitialization_ = value;\r\n\t}\r\n\r\n\tbool operator==(const CursorInfo &other) const\r\n\t{\r\n\t\treturn type_ == other.type_ && (type_ != CursorType::Game || id_ == other.id_);\r\n\t}\r\n\tbool operator!=(const CursorInfo &other) const\r\n\t{\r\n\t\treturn !(*this == other);\r\n\t}\r\n\r\nprivate:\r\n\texplicit CursorInfo(CursorType type, int id = 0)\r\n\t    : type_(type)\r\n\t    , id_(id)\r\n\t    , enabled_(false)\r\n\t{\r\n\t}\r\n\r\n\tCursorType type_ = CursorType::Unknown;\r\n\r\n\t// ID for CursorType::Game\r\n\tint id_;\r\n\r\n\tbool enabled_ = false;\r\n\r\n\tbool needs_reinitialization_ = false;\r\n};\r\n\r\nCursorInfo &GetCurrentCursorInfo();\r\n\r\n// Whether the current cursor is a hardware cursor.\r\ninline bool IsHardwareCursor()\r\n{\r\n\treturn GetCurrentCursorInfo().Enabled();\r\n}\r\n\r\nvoid SetHardwareCursor(CursorInfo cursorInfo);\r\n\r\ninline void DoReinitializeHardwareCursor()\r\n{\r\n#if LOG_HWCURSOR\r\n\tLog(\"hwcursor: DoReinitializeHardwareCursor\");\r\n#endif\r\n\tSetHardwareCursor(GetCurrentCursorInfo());\r\n}\r\n\r\ninline bool IsHardwareCursorVisible()\r\n{\r\n#ifndef USE_SDL1\r\n\treturn SDL_CursorVisible();\r\n#else\r\n\treturn false;\r\n#endif\r\n}\r\n\r\ninline void SetHardwareCursorVisible(bool visible)\r\n{\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tif (IsHardwareCursorVisible() == visible)\r\n\t\treturn;\r\n\tif (visible && GetCurrentCursorInfo().needsReinitialization()) {\r\n\t\tDoReinitializeHardwareCursor();\r\n\t}\r\n#if LOG_HWCURSOR\r\n\tLog(\"hwcursor: SetHardwareCursorVisible {}\", visible);\r\n#endif\r\n\tif (!(visible ? SDLC_ShowCursor() : SDLC_HideCursor())) {\r\n\t\tLogError(\"{}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t}\r\n#endif\r\n}\r\n\r\ninline void ReinitializeHardwareCursor()\r\n{\r\n\tif (IsHardwareCursorVisible()) {\r\n\t\tDoReinitializeHardwareCursor();\r\n\t} else {\r\n\t\tGetCurrentCursorInfo().setNeedsReinitialization(true);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/init.cpp",
    "content": "/**\r\n * @file init.cpp\r\n *\r\n * Implementation of routines for initializing the environment, disable screen saver, load MPQ.\r\n */\r\n#include \"init.hpp\"\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_video.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <config.h>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/events.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/str_split.hpp\"\r\n#include \"utils/ui_fwd.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#ifndef UNPACKED_MPQS\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"mpq/mpq_reader.hpp\"\r\n#endif\r\n\r\n#ifdef __vita__\r\n// increase default allowed heap size on Vita\r\nint _newlib_heap_size_user = 100 * 1024 * 1024;\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nbool gbActive;\r\n\r\nnamespace {\r\n\r\nconstexpr char DevilutionXMpqVersion[] = \"1\\n\";\r\nconstexpr char ExtraFontsVersion[] = \"1\\n\";\r\n\r\nbool AssetContentsEq(AssetRef &&ref, std::string_view expected)\r\n{\r\n\tconst size_t size = ref.size();\r\n\tAssetHandle handle = OpenAsset(std::move(ref), false);\r\n\tif (!handle.ok()) return false;\r\n\tconst std::unique_ptr<char[]> contents { new char[size] };\r\n\tif (!handle.read(contents.get(), size)) return false;\r\n\treturn std::string_view { contents.get(), size } == expected;\r\n}\r\n\r\nbool CheckDevilutionXMpqVersion(AssetRef &&ref)\r\n{\r\n\treturn !AssetContentsEq(std::move(ref), DevilutionXMpqVersion);\r\n}\r\n\r\nbool CheckExtraFontsVersion(AssetRef &&ref)\r\n{\r\n\treturn !AssetContentsEq(std::move(ref), ExtraFontsVersion);\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsDevilutionXMpqOutOfDate()\r\n{\r\n\tAssetRef ref = FindAsset(\"ASSETS_VERSION\");\r\n\tif (!ref.ok())\r\n\t\treturn true;\r\n\treturn CheckDevilutionXMpqVersion(std::move(ref));\r\n}\r\n\r\n#ifdef UNPACKED_MPQS\r\nbool AreExtraFontsOutOfDate(std::string_view path)\r\n{\r\n\tconst std::string versionPath = StrCat(path, \"fonts\" DIRECTORY_SEPARATOR_STR \"VERSION\");\r\n\tif (versionPath.size() + 1 > AssetRef::PathBufSize)\r\n\t\tapp_fatal(\"Path too long\");\r\n\tAssetRef ref;\r\n\t*BufCopy(ref.path, versionPath) = '\\0';\r\n\treturn CheckExtraFontsVersion(std::move(ref));\r\n}\r\n#else\r\nbool AreExtraFontsOutOfDate(MpqArchive &archive)\r\n{\r\n\tconst char filename[] = \"fonts\\\\VERSION\";\r\n\tconst MpqFileHash fileHash = CalculateMpqFileHash(filename);\r\n\tuint32_t fileNumber;\r\n\tif (!archive.GetFileNumber(fileHash, fileNumber))\r\n\t\treturn true;\r\n\tAssetRef ref;\r\n\tref.archive = &archive;\r\n\tref.fileNumber = fileNumber;\r\n\tref.filename = filename;\r\n\treturn CheckExtraFontsVersion(std::move(ref));\r\n}\r\n#endif\r\n\r\nbool AreExtraFontsOutOfDate()\r\n{\r\n\tconst auto it = MpqArchives.find(FontMpqPriority);\r\n\treturn it != MpqArchives.end() && AreExtraFontsOutOfDate(it->second);\r\n}\r\n\r\nvoid init_cleanup()\r\n{\r\n\tif (gbIsMultiplayer && gbRunGame) {\r\n\t\tpfile_write_hero(/*writeGameData=*/false);\r\n\t\tsfile_write_stash();\r\n\t}\r\n\r\n\tMpqArchives.clear();\r\n\tHasHellfireMpq = false;\r\n\r\n\tNetClose();\r\n}\r\n\r\nvoid init_create_window()\r\n{\r\n\tif (!SpawnWindow(PROJECT_NAME))\r\n\t\tapp_fatal(_(\"Unable to create main window\"));\r\n\tdx_init();\r\n\tgbActive = true;\r\n#ifndef USE_SDL1\r\n\tSDL_DisableScreenSaver();\r\n#endif\r\n}\r\n\r\nvoid MainWndProc(const SDL_Event &event)\r\n{\r\n#ifndef USE_SDL1\r\n#ifdef USE_SDL3\r\n\tswitch (event.type)\r\n#else\r\n\tif (event.type != SDL_WINDOWEVENT) return;\r\n\tswitch (event.window.event)\r\n#endif\r\n\t{\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_HIDDEN:\r\n\tcase SDL_EVENT_WINDOW_MINIMIZED:\r\n#else\r\n\tcase SDL_WINDOWEVENT_HIDDEN:\r\n\tcase SDL_WINDOWEVENT_MINIMIZED:\r\n#endif\r\n\t\tgbActive = false;\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_SHOWN:\r\n\tcase SDL_EVENT_WINDOW_EXPOSED:\r\n\tcase SDL_EVENT_WINDOW_RESTORED:\r\n#else\r\n\tcase SDL_WINDOWEVENT_SHOWN:\r\n\tcase SDL_WINDOWEVENT_EXPOSED:\r\n\tcase SDL_WINDOWEVENT_RESTORED:\r\n#endif\r\n\t\tgbActive = true;\r\n\t\tRedrawEverything();\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:\r\n#else\r\n\tcase SDL_WINDOWEVENT_SIZE_CHANGED:\r\n#endif\r\n\t\tReinitializeHardwareCursor();\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_MOUSE_LEAVE:\r\n#else\r\n\tcase SDL_WINDOWEVENT_LEAVE:\r\n#endif\r\n\t\tsgbMouseDown = CLICK_NONE;\r\n\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\tRedrawEverything();\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_CLOSE_REQUESTED:\r\n#else\r\n\tcase SDL_WINDOWEVENT_CLOSE:\r\n#endif\r\n\t\tdiablo_quit(0);\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_FOCUS_LOST:\r\n#else\r\n\tcase SDL_WINDOWEVENT_FOCUS_LOST:\r\n#endif\r\n\t\tif (*GetOptions().Gameplay.pauseOnFocusLoss)\r\n\t\t\tdiablo_focus_pause();\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tcase SDL_EVENT_WINDOW_FOCUS_GAINED:\r\n#else\r\n\tcase SDL_WINDOWEVENT_FOCUS_GAINED:\r\n#endif\r\n\t\tif (*GetOptions().Gameplay.pauseOnFocusLoss)\r\n\t\t\tdiablo_focus_unpause();\r\n\t\tbreak;\r\n#ifdef USE_SDL3\r\n\tdefault:\r\n\t\tbreak;\r\n#else\r\n\tcase SDL_WINDOWEVENT_MOVED:\r\n\tcase SDL_WINDOWEVENT_RESIZED:\r\n\tcase SDL_WINDOWEVENT_MAXIMIZED:\r\n\tcase SDL_WINDOWEVENT_ENTER:\r\n\tcase SDL_WINDOWEVENT_TAKE_FOCUS:\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tLogVerbose(\"Unhandled SDL_WINDOWEVENT event: {:d}\", event.window.event);\r\n\t\tbreak;\r\n#endif\r\n\t}\r\n#else\r\n\tif (event.type != SDL_ACTIVEEVENT)\r\n\t\treturn;\r\n\tif ((event.active.state & SDL_APPINPUTFOCUS) != 0) {\r\n\t\tif (event.active.gain == 0)\r\n\t\t\tdiablo_focus_pause();\r\n\t\telse\r\n\t\t\tdiablo_focus_unpause();\r\n\t}\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/init.hpp",
    "content": "/**\r\n * @file init.hpp\r\n *\r\n * Interface of routines for initializing the environment, disable screen saver, load MPQ.\r\n */\r\n#pragma once\r\n\r\n// Unused here but must be included before SDL.h, see:\r\n// https://github.com/bebbo/amiga-gcc/issues/413\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#ifdef UNPACKED_MPQS\r\n#include <string_view>\r\n#else\r\n#include \"mpq/mpq_reader.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n/** True if the game is the current active window */\r\nextern bool gbActive;\r\n\r\n[[nodiscard]] bool IsDevilutionXMpqOutOfDate();\r\n\r\n#ifdef UNPACKED_MPQS\r\nbool AreExtraFontsOutOfDate(std::string_view path);\r\n#else\r\nbool AreExtraFontsOutOfDate(MpqArchive &archive);\r\n#endif\r\n\r\n[[nodiscard]] bool AreExtraFontsOutOfDate();\r\n\r\nvoid init_cleanup();\r\nvoid init_create_window();\r\nvoid MainWndProc(const SDL_Event &event);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/interfac.cpp",
    "content": "/**\r\n * @file interfac.cpp\r\n *\r\n * Implementation of load screens.\r\n */\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"controls/input.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/events.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"loadsave.h\"\r\n#include \"multi.h\"\r\n#include \"pfile.h\"\r\n#include \"plrmsg.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/sdl_thread.h\"\r\n\r\n#ifndef USE_SDL1\r\n#include \"controls/touch/renderers.h\"\r\n#endif\r\n\r\n#ifdef __DJGPP__\r\n#define LOAD_ON_MAIN_THREAD\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconstexpr uint32_t MaxProgress = 534;\r\nconstexpr uint32_t ProgressStepSize = 23;\r\n\r\nOptionalOwnedClxSpriteList sgpBackCel;\r\n\r\nbool IsProgress;\r\nuint32_t sgdwProgress;\r\nint progress_id;\r\n\r\n/** The color used for the progress bar as an index into the palette. */\r\nconst uint8_t BarColor[3] = { 138, 43, 254 };\r\n/** The screen position of the top left corner of the progress bar. */\r\nconst int BarPos[3][2] = { { 53, 37 }, { 53, 421 }, { 53, 37 } };\r\n\r\nOptionalOwnedClxSpriteList ArtCutsceneWidescreen;\r\n\r\nSdlEventType CustomEventType = SDL_EVENT_USER;\r\n\r\nCutscenes GetCutSceneFromLevelType(dungeon_type type)\r\n{\r\n\tswitch (type) {\r\n\tcase DTYPE_TOWN:\r\n\t\treturn CutTown;\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\treturn CutLevel1;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\treturn CutLevel2;\r\n\tcase DTYPE_CAVES:\r\n\t\treturn CutLevel3;\r\n\tcase DTYPE_HELL:\r\n\t\treturn CutLevel4;\r\n\tcase DTYPE_NEST:\r\n\t\treturn CutLevel6;\r\n\tcase DTYPE_CRYPT:\r\n\t\treturn CutLevel5;\r\n\tdefault:\r\n\t\treturn CutLevel1;\r\n\t}\r\n}\r\n\r\nCutscenes PickCutscene(interface_mode uMsg)\r\n{\r\n\tswitch (uMsg) {\r\n\tcase WM_DIABLOADGAME:\r\n\tcase WM_DIABNEWGAME:\r\n\t\treturn CutStart;\r\n\tcase WM_DIABRETOWN:\r\n\t\treturn CutTown;\r\n\tcase WM_DIABNEXTLVL:\r\n\tcase WM_DIABPREVLVL:\r\n\tcase WM_DIABTOWNWARP:\r\n\tcase WM_DIABTWARPUP: {\r\n\t\tconst int lvl = MyPlayer->plrlevel;\r\n\t\tif (lvl == 1 && uMsg == WM_DIABNEXTLVL)\r\n\t\t\treturn CutTown;\r\n\t\tif (lvl == 16 && uMsg == WM_DIABNEXTLVL)\r\n\t\t\treturn CutGate;\r\n\t\treturn GetCutSceneFromLevelType(GetLevelType(lvl));\r\n\t}\r\n\tcase WM_DIABWARPLVL:\r\n\t\treturn CutPortal;\r\n\tcase WM_DIABSETLVL:\r\n\tcase WM_DIABRTNLVL:\r\n\t\tif (setlvlnum == SL_BONECHAMB)\r\n\t\t\treturn CutLevel2;\r\n\t\tif (setlvlnum == SL_VILEBETRAYER)\r\n\t\t\treturn CutPortalRed;\r\n\t\tif (IsArenaLevel(setlvlnum)) {\r\n\t\t\tif (uMsg == WM_DIABSETLVL)\r\n\t\t\t\treturn GetCutSceneFromLevelType(setlvltype);\r\n\t\t\treturn CutTown;\r\n\t\t}\r\n\t\treturn CutLevel1;\r\n\tdefault:\r\n\t\tapp_fatal(\"Unknown progress mode\");\r\n\t}\r\n}\r\n\r\nvoid LoadCutsceneBackground(interface_mode uMsg)\r\n{\r\n\tconst char *celPath;\r\n\tconst char *palPath;\r\n\r\n\tswitch (PickCutscene(uMsg)) {\r\n\tcase CutStart:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cutstartw.clx\");\r\n\t\tcelPath = \"gendata\\\\cutstart\";\r\n\t\tpalPath = \"gendata\\\\cutstart.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutTown:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cutttw.clx\");\r\n\t\tcelPath = \"gendata\\\\cuttt\";\r\n\t\tpalPath = \"gendata\\\\cuttt.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutLevel1:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cutl1dw.clx\");\r\n\t\tcelPath = \"gendata\\\\cutl1d\";\r\n\t\tpalPath = \"gendata\\\\cutl1d.pal\";\r\n\t\tprogress_id = 0;\r\n\t\tbreak;\r\n\tcase CutLevel2:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cut2w.clx\");\r\n\t\tcelPath = \"gendata\\\\cut2\";\r\n\t\tpalPath = \"gendata\\\\cut2.pal\";\r\n\t\tprogress_id = 2;\r\n\t\tbreak;\r\n\tcase CutLevel3:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cut3w.clx\");\r\n\t\tcelPath = \"gendata\\\\cut3\";\r\n\t\tpalPath = \"gendata\\\\cut3.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutLevel4:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cut4w.clx\");\r\n\t\tcelPath = \"gendata\\\\cut4\";\r\n\t\tpalPath = \"gendata\\\\cut4.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutLevel5:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"nlevels\\\\cutl5w.clx\");\r\n\t\tcelPath = \"nlevels\\\\cutl5\";\r\n\t\tpalPath = \"nlevels\\\\cutl5.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutLevel6:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"nlevels\\\\cutl6w.clx\");\r\n\t\tcelPath = \"nlevels\\\\cutl6\";\r\n\t\tpalPath = \"nlevels\\\\cutl6.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutPortal:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cutportlw.clx\");\r\n\t\tcelPath = \"gendata\\\\cutportl\";\r\n\t\tpalPath = \"gendata\\\\cutportl.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutPortalRed:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cutportrw.clx\");\r\n\t\tcelPath = \"gendata\\\\cutportr\";\r\n\t\tpalPath = \"gendata\\\\cutportr.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\tcase CutGate:\r\n\t\tArtCutsceneWidescreen = LoadOptionalClx(\"gendata\\\\cutgatew.clx\");\r\n\t\tcelPath = \"gendata\\\\cutgate\";\r\n\t\tpalPath = \"gendata\\\\cutgate.pal\";\r\n\t\tprogress_id = 1;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tassert(!sgpBackCel);\r\n\tsgpBackCel = LoadCel(celPath, 640);\r\n\tLoadPalette(palPath);\r\n\tUpdateSystemPalette(logical_palette);\r\n\r\n\tsgdwProgress = 0;\r\n}\r\n\r\nvoid FreeCutsceneBackground()\r\n{\r\n\tsgpBackCel = std::nullopt;\r\n\tArtCutsceneWidescreen = std::nullopt;\r\n}\r\n\r\nvoid DrawCutsceneBackground()\r\n{\r\n\tconst Rectangle &uiRectangle = GetUIRectangle();\r\n\tconst Surface &out = GlobalBackBuffer();\r\n\tSDL_FillSurfaceRect(out.surface, nullptr, 0);\r\n\tif (ArtCutsceneWidescreen) {\r\n\t\tconst ClxSprite sprite = (*ArtCutsceneWidescreen)[0];\r\n\t\tRenderClxSprite(out, sprite, { uiRectangle.position.x - (sprite.width() - uiRectangle.size.width) / 2, uiRectangle.position.y });\r\n\t}\r\n\tClxDraw(out, { uiRectangle.position.x, 480 - 1 + uiRectangle.position.y }, (*sgpBackCel)[0]);\r\n}\r\n\r\nvoid DrawCutsceneForeground()\r\n{\r\n\tconst Rectangle &uiRectangle = GetUIRectangle();\r\n\tconst Surface &out = GlobalBackBuffer();\r\n\tconstexpr int ProgressHeight = 22;\r\n\tSDL_Rect rect = MakeSdlRect(\r\n\t    out.region.x + BarPos[progress_id][0] + uiRectangle.position.x,\r\n\t    out.region.y + BarPos[progress_id][1] + uiRectangle.position.y,\r\n\t    sgdwProgress,\r\n\t    ProgressHeight);\r\n\tSDL_FillSurfaceRect(out.surface, &rect, BarColor[progress_id]);\r\n\r\n\tif (DiabloUiSurface() == PalSurface)\r\n\t\tBltFast(&rect, &rect);\r\n\tRenderPresent();\r\n}\r\n\r\nstruct {\r\n\tuint32_t loadStartedAt;\r\n\tEventHandler prevHandler;\r\n\tbool skipRendering;\r\n\tbool done;\r\n\tuint32_t drawnProgress;\r\n\tstd::array<SDL_Color, 256> palette;\r\n} ProgressEventHandlerState;\r\n\r\nvoid InitRendering()\r\n{\r\n\t// Blit the background once and then free it.\r\n\tDrawCutsceneBackground();\r\n\tif (RenderDirectlyToOutputSurface && PalSurface != nullptr) {\r\n\t\t// Render into all the backbuffers if there are multiple.\r\n\t\tconst void *initialPixels = PalSurface->pixels;\r\n\t\tif (DiabloUiSurface() == PalSurface)\r\n\t\t\tBltFast(nullptr, nullptr);\r\n\t\tRenderPresent();\r\n\t\twhile (PalSurface->pixels != initialPixels) {\r\n\t\t\tDrawCutsceneBackground();\r\n\t\t\tif (DiabloUiSurface() == PalSurface)\r\n\t\t\t\tBltFast(nullptr, nullptr);\r\n\t\t\tRenderPresent();\r\n\t\t}\r\n\t}\r\n\tFreeCutsceneBackground();\r\n\r\n\t// The loading thread sets `logical_palette`, so we make sure to use\r\n\t// our own palette for the fade-in.\r\n\tPaletteFadeIn(8, ProgressEventHandlerState.palette);\r\n}\r\n\r\nvoid CheckShouldSkipRendering()\r\n{\r\n\tif (!ProgressEventHandlerState.skipRendering) return;\r\n\tconst bool shouldSkip = ProgressEventHandlerState.loadStartedAt + *GetOptions().Gameplay.skipLoadingScreenThresholdMs > SDL_GetTicks();\r\n\tif (shouldSkip) return;\r\n\tProgressEventHandlerState.skipRendering = false;\r\n\tif (!HeadlessMode) InitRendering();\r\n}\r\n\r\nbool HandleProgressBarUpdate()\r\n{\r\n\tCheckShouldSkipRendering();\r\n\tSDL_Event event;\r\n\t// We use the real `PollEvent` here instead of `FetchMessage`\r\n\t// to process real events rather than the recorded ones in demo mode.\r\n\twhile (PollEvent(&event)) {\r\n\t\tCheckShouldSkipRendering();\r\n\t\tif (event.type != SDL_EVENT_QUIT) {\r\n\t\t\tHandleMessage(event, SDL_GetModState());\r\n\t\t}\r\n\t\tif (ProgressEventHandlerState.done) return false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid DoLoad(interface_mode uMsg)\r\n{\r\n\tIncProgress();\r\n\tsound_init();\r\n\tIncProgress();\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\ttl::expected<void, std::string> loadResult;\r\n\tswitch (uMsg) {\r\n\tcase WM_DIABLOADGAME:\r\n\t\tIncProgress(2);\r\n\t\tloadResult = LoadGame(true);\r\n\t\tif (loadResult.has_value()) IncProgress(2);\r\n\t\tbreak;\r\n\tcase WM_DIABNEWGAME:\r\n\t\tmyPlayer.pOriginalCathedral = !gbIsHellfire;\r\n\t\tIncProgress();\r\n\t\tFreeGameMem();\r\n\t\tIncProgress();\r\n\t\tpfile_remove_temp_files();\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(true, ENTRY_MAIN);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABNEXTLVL:\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tFreeGameMem();\r\n\t\tsetlevel = false;\r\n\t\tcurrlevel = myPlayer.plrlevel;\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_MAIN);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABPREVLVL:\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tFreeGameMem();\r\n\t\tcurrlevel--;\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\t\tassert(myPlayer.isOnActiveLevel());\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_PREV);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABSETLVL:\r\n\t\t// Note: ReturnLevel, ReturnLevelType and ReturnLvlPosition is only set to ensure vanilla compatibility\r\n\t\tReturnLevel = GetMapReturnLevel();\r\n\t\tReturnLevelType = GetLevelType(ReturnLevel);\r\n\t\tReturnLvlPosition = GetMapReturnPosition();\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tsetlevel = true;\r\n\t\tleveltype = setlvltype;\r\n\t\tcurrlevel = static_cast<uint8_t>(setlvlnum);\r\n\t\tFreeGameMem();\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_SETLVL);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABRTNLVL:\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tsetlevel = false;\r\n\t\tFreeGameMem();\r\n\t\tIncProgress();\r\n\t\tcurrlevel = GetMapReturnLevel();\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_RTNLVL);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABWARPLVL:\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tFreeGameMem();\r\n\t\tGetPortalLevel();\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_WARPLVL);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABTOWNWARP:\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tFreeGameMem();\r\n\t\tsetlevel = false;\r\n\t\tcurrlevel = myPlayer.plrlevel;\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_TWARPDN);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABTWARPUP:\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tFreeGameMem();\r\n\t\tcurrlevel = myPlayer.plrlevel;\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_TWARPUP);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tcase WM_DIABRETOWN:\r\n\t\tIncProgress();\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tpfile_save_level();\r\n\t\t} else {\r\n\t\t\tDeltaSaveLevel();\r\n\t\t}\r\n\t\tIncProgress();\r\n\t\tFreeGameMem();\r\n\t\tsetlevel = false;\r\n\t\tcurrlevel = myPlayer.plrlevel;\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\t\tIncProgress();\r\n\t\tloadResult = LoadGameLevel(false, ENTRY_MAIN);\r\n\t\tif (loadResult.has_value()) IncProgress();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tloadResult = tl::make_unexpected<std::string>(\"Unknown progress mode\");\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (!loadResult.has_value()) {\r\n\t\tSDL_Event event;\r\n\t\tCustomEventToSdlEvent(event, WM_ERROR);\r\n\t\tevent.user.data1 = new std::string(std::move(loadResult).error());\r\n\t\tif (!SDLC_PushEvent(&event)) {\r\n\t\t\tLogError(\"Failed to send WM_ERROR {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t}\r\n#ifdef LOAD_ON_MAIN_THREAD\r\n\t\tHandleProgressBarUpdate();\r\n#endif\r\n\t\treturn;\r\n\t}\r\n\r\n\tSDL_Event event;\r\n\tCustomEventToSdlEvent(event, WM_DONE);\r\n\tif (!SDLC_PushEvent(&event)) {\r\n\t\tLogError(\"Failed to send WM_DONE {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t}\r\n#ifdef LOAD_ON_MAIN_THREAD\r\n\tHandleProgressBarUpdate();\r\n#endif\r\n}\r\n\r\nvoid ProgressEventHandler(const SDL_Event &event, uint16_t modState)\r\n{\r\n\tDisableInputEventHandler(event, modState);\r\n\tif (!IsCustomEvent(event.type)) return;\r\n\r\n\tconst interface_mode customEvent = GetCustomEvent(event);\r\n\tswitch (customEvent) {\r\n\tcase WM_PROGRESS:\r\n\t\tif (!HeadlessMode && ProgressEventHandlerState.drawnProgress != sgdwProgress && !ProgressEventHandlerState.skipRendering) {\r\n\t\t\tDrawCutsceneForeground();\r\n\t\t\tProgressEventHandlerState.drawnProgress = sgdwProgress;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase WM_ERROR:\r\n\t\tapp_fatal(*static_cast<std::string *>(event.user.data1));\r\n\t\tbreak;\r\n\tcase WM_DONE: {\r\n\t\tif (!ProgressEventHandlerState.skipRendering) {\r\n\t\t\tNewCursor(CURSOR_HAND);\r\n\r\n\t\t\tif (!HeadlessMode) {\r\n\t\t\t\tassert(ghMainWnd);\r\n\r\n\t\t\t\t// The loading thread sets `logical_palette`, so we make sure to use\r\n\t\t\t\t// our own palette for drawing the foreground.\r\n\t\t\t\tUpdateSystemPalette(ProgressEventHandlerState.palette);\r\n\r\n\t\t\t\t// Ensure that all back buffers have the full progress bar.\r\n\t\t\t\tconst void *initialPixels = PalSurface->pixels;\r\n\t\t\t\tdo {\r\n\t\t\t\t\tDrawCutsceneForeground();\r\n\t\t\t\t\tif (DiabloUiSurface() == PalSurface)\r\n\t\t\t\t\t\tBltFast(nullptr, nullptr);\r\n\t\t\t\t\tRenderPresent();\r\n\t\t\t\t} while (PalSurface->pixels != initialPixels);\r\n\r\n\t\t\t\t// The loading thread sets `logical_palette`, so we make sure to use\r\n\t\t\t\t// our own palette for the fade-out.\r\n\t\t\t\tPaletteFadeOut(8, ProgressEventHandlerState.palette);\r\n\r\n\t\t\t\t// Once the fade-out is done, restore the system palette.\r\n\t\t\t\tUpdateSystemPalette(logical_palette);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t[[maybe_unused]] EventHandler prevHandler = SetEventHandler(ProgressEventHandlerState.prevHandler);\r\n\t\tassert(prevHandler == ProgressEventHandler);\r\n\t\tProgressEventHandlerState.prevHandler = nullptr;\r\n\t\tIsProgress = false;\r\n\r\n\t\tconst Player &myPlayer = *MyPlayer;\r\n\t\tNetSendCmdLocParam2(true, CMD_PLAYER_JOINLEVEL, myPlayer.position.tile, myPlayer.plrlevel, myPlayer.plrIsOnSetLevel ? 1 : 0);\r\n\t\tDelayPlrMessages(SDL_GetTicks() - ProgressEventHandlerState.loadStartedAt);\r\n\r\n\t\tif (gbSomebodyWonGameKludge && myPlayer.isOnLevel(16)) {\r\n\t\t\tPrepDoEnding();\r\n\t\t}\r\n\r\n\t\tgbSomebodyWonGameKludge = false;\r\n\t\tProgressEventHandlerState.done = true;\r\n\r\n#if !defined(USE_SDL1) && !defined(__vita__)\r\n\t\tif (renderer != nullptr) {\r\n\t\t\tInitVirtualGamepadTextures(*renderer);\r\n\t\t}\r\n#endif\r\n\t} break;\r\n\tdefault:\r\n\t\tapp_fatal(\"Unknown progress mode\");\r\n\t\tbreak;\r\n\t}\r\n#ifdef LOAD_ON_MAIN_THREAD\r\n\tHandleProgressBarUpdate();\r\n#endif\r\n}\r\n\r\n} // namespace\r\n\r\nvoid RegisterCustomEvents()\r\n{\r\n#ifndef USE_SDL1\r\n\tCustomEventType = SDL_RegisterEvents(1);\r\n#endif\r\n}\r\n\r\nbool IsCustomEvent(SdlEventType eventType)\r\n{\r\n\treturn eventType == CustomEventType;\r\n}\r\n\r\ninterface_mode GetCustomEvent(const SDL_Event &event)\r\n{\r\n\treturn static_cast<interface_mode>(event.user.code);\r\n}\r\n\r\nvoid CustomEventToSdlEvent(SDL_Event &event, interface_mode eventType)\r\n{\r\n\tevent.type = CustomEventType;\r\n\tevent.user.code = static_cast<int>(eventType);\r\n}\r\n\r\nvoid interface_msg_pump()\r\n{\r\n\tSDL_Event event;\r\n\tuint16_t modState;\r\n\twhile (FetchMessage(&event, &modState)) {\r\n\t\tif (event.type != SDL_EVENT_QUIT) {\r\n\t\t\tHandleMessage(event, modState);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid IncProgress(uint32_t steps)\r\n{\r\n\tif (!IsProgress)\r\n\t\treturn;\r\n\tconst uint32_t prevProgress = sgdwProgress;\r\n\tsgdwProgress += ProgressStepSize * steps;\r\n\tif (sgdwProgress > MaxProgress)\r\n\t\tsgdwProgress = MaxProgress;\r\n\tif (!HeadlessMode && sgdwProgress != prevProgress) {\r\n\t\tSDL_Event event;\r\n\t\tCustomEventToSdlEvent(event, WM_PROGRESS);\r\n\t\tif (!SDLC_PushEvent(&event)) {\r\n\t\t\tLogError(\"Failed to send WM_PROGRESS {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t}\r\n#ifdef LOAD_ON_MAIN_THREAD\r\n\t\tHandleProgressBarUpdate();\r\n#endif\r\n\t}\r\n}\r\n\r\nvoid CompleteProgress()\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\tif (!IsProgress)\r\n\t\treturn;\r\n\tif (sgdwProgress < MaxProgress) {\r\n\t\tIncProgress((MaxProgress - sgdwProgress) / ProgressStepSize);\r\n\t}\r\n}\r\n\r\nvoid ShowProgress(interface_mode uMsg)\r\n{\r\n\tIsProgress = true;\r\n\tgbSomebodyWonGameKludge = false;\r\n\r\n\tProgressEventHandlerState.loadStartedAt = SDL_GetTicks();\r\n\tProgressEventHandlerState.prevHandler = SetEventHandler(ProgressEventHandler);\r\n\tProgressEventHandlerState.skipRendering = true;\r\n\tProgressEventHandlerState.done = false;\r\n\tProgressEventHandlerState.drawnProgress = 0;\r\n\r\n#ifndef USE_SDL1\r\n\tDeactivateVirtualGamepad();\r\n\tFreeVirtualGamepadTextures();\r\n#endif\r\n\r\n\tif (!HeadlessMode) {\r\n\t\tassert(ghMainWnd);\r\n\r\n\t\tinterface_msg_pump();\r\n\t\tClearScreenBuffer();\r\n\t\tscrollrt_draw_game_screen();\r\n\r\n\t\tif (IsHardwareCursor())\r\n\t\t\tSetHardwareCursorVisible(false);\r\n\r\n\t\tBlackPalette();\r\n\r\n\t\t// Always load the background (even if we end up skipping rendering it).\r\n\t\t// This is because the MPQ archive can only be read by a single thread at a time.\r\n\t\tLoadCutsceneBackground(uMsg);\r\n\r\n\t\t// Save the palette at this point because the loading process may replace it.\r\n\t\tProgressEventHandlerState.palette = logical_palette;\r\n\t}\r\n\r\n\t// Begin loading\r\n#ifdef LOAD_ON_MAIN_THREAD\r\n\tconst uint32_t start = SDL_GetTicks();\r\n\tDoLoad(uMsg);\r\n\tLogVerbose(\"Loading finished in {}ms\", SDL_GetTicks() - start);\r\n#else\r\n\tstatic interface_mode loadTarget;\r\n\tloadTarget = uMsg;\r\n\tSdlThread loadThread = SdlThread([]() {\r\n\t\tconst uint32_t start = SDL_GetTicks();\r\n\t\tDoLoad(loadTarget);\r\n\t\tLogVerbose(\"Load thread finished in {}ms\", SDL_GetTicks() - start);\r\n\t});\r\n\twhile (HandleProgressBarUpdate()) { }\r\n\tloadThread.join();\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/interfac.h",
    "content": "/**\r\n * @file interfac.h\r\n *\r\n * Interface of load screens.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Custom events.\r\n */\r\nenum interface_mode : uint8_t {\r\n\tWM_DIABNEXTLVL = 0,\r\n\tWM_DIABPREVLVL,\r\n\tWM_DIABRTNLVL,\r\n\tWM_DIABSETLVL,\r\n\tWM_DIABWARPLVL,\r\n\tWM_DIABTOWNWARP,\r\n\tWM_DIABTWARPUP,\r\n\tWM_DIABRETOWN,\r\n\tWM_DIABNEWGAME,\r\n\tWM_DIABLOADGAME,\r\n\r\n\t// Asynchronous loading events.\r\n\tWM_PROGRESS,\r\n\tWM_ERROR,\r\n\tWM_DONE,\r\n\r\n\tWM_FIRST = WM_DIABNEXTLVL,\r\n\tWM_LAST = WM_DONE,\r\n};\r\n\r\nvoid RegisterCustomEvents();\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nusing SdlEventType = uint16_t;\r\n#else\r\nusing SdlEventType = uint8_t;\r\n#endif\r\n\r\nbool IsCustomEvent(SdlEventType eventType);\r\n\r\ninterface_mode GetCustomEvent(const SDL_Event &event);\r\n\r\nvoid CustomEventToSdlEvent(SDL_Event &event, interface_mode eventType);\r\n\r\nenum Cutscenes : uint8_t {\r\n\tCutStart,\r\n\tCutTown,\r\n\tCutLevel1,\r\n\tCutLevel2,\r\n\tCutLevel3,\r\n\tCutLevel4,\r\n\tCutLevel5,\r\n\tCutLevel6,\r\n\tCutPortal,\r\n\tCutPortalRed,\r\n\tCutGate,\r\n};\r\n\r\nvoid interface_msg_pump();\r\nvoid IncProgress(uint32_t steps = 1);\r\nvoid CompleteProgress();\r\nvoid ShowProgress(interface_mode uMsg);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/inv.cpp",
    "content": "/**\r\n * @file inv.cpp\r\n *\r\n * Implementation of player inventory.\r\n */\r\n#include <algorithm>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"inv_iterators.hpp\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"levels/town.h\"\r\n#include \"minitext.h\"\r\n#include \"options.h\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"player.h\"\r\n#include \"plrmsg.h\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"towners.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool invflag;\r\n\r\n/**\r\n * Maps from inventory slot to screen position. The inventory slots are\r\n * arranged as follows:\r\n *\r\n * @code{.unparsed}\r\n *                          00 00\r\n *                          00 00   03\r\n *\r\n *              04 04       06 06       05 05\r\n *              04 04       06 06       05 05\r\n *              04 04       06 06       05 05\r\n *\r\n *                 01                   02\r\n *\r\n *              07 08 09 10 11 12 13 14 15 16\r\n *              17 18 19 20 21 22 23 24 25 26\r\n *              27 28 29 30 31 32 33 34 35 36\r\n *              37 38 39 40 41 42 43 44 45 46\r\n *\r\n * 47 48 49 50 51 52 53 54\r\n * @endcode\r\n */\r\nconst Rectangle InvRect[] = {\r\n\t// clang-format off\r\n\t//{   X,   Y }, {  W,  H }\r\n\t{ { 132,   2 }, { 58, 59 } }, // helmet\r\n\t{ {  47, 177 }, { 28, 29 } }, // left ring\r\n\t{ { 248, 177 }, { 28, 29 } }, // right ring\r\n\t{ { 205,  32 }, { 28, 29 } }, // amulet\r\n\t{ {  17,  75 }, { 58, 86 } }, // left hand\r\n\t{ { 248,  75 }, { 58, 87 } }, // right hand\r\n\t{ { 132,  75 }, { 58, 87 } }, // chest\r\n\t{ {  17, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ {  46, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ {  75, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ { 104, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ { 133, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ { 162, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ { 191, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ { 220, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ { 249, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ { 278, 222 }, { 29, 29 } }, // inv row 1\r\n\t{ {  17, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ {  46, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ {  75, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ { 104, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ { 133, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ { 162, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ { 191, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ { 220, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ { 249, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ { 278, 251 }, { 29, 29 } }, // inv row 2\r\n\t{ {  17, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ {  46, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ {  75, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ { 104, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ { 133, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ { 162, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ { 191, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ { 220, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ { 249, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ { 278, 280 }, { 29, 29 } }, // inv row 3\r\n\t{ {  17, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ {  46, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ {  75, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 104, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 133, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 162, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 191, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 220, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 249, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 278, 309 }, { 29, 29 } }, // inv row 4\r\n\t{ { 205,   5 }, { 29, 29 } }, // belt\r\n\t{ { 234,   5 }, { 29, 29 } }, // belt\r\n\t{ { 263,   5 }, { 29, 29 } }, // belt\r\n\t{ { 292,   5 }, { 29, 29 } }, // belt\r\n\t{ { 321,   5 }, { 29, 29 } }, // belt\r\n\t{ { 350,   5 }, { 29, 29 } }, // belt\r\n\t{ { 379,   5 }, { 29, 29 } }, // belt\r\n\t{ { 408,   5 }, { 29, 29 } }  // belt\r\n\t// clang-format on\r\n};\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList pInvCels;\r\n\r\n/**\r\n * @brief Adds an item to a player's InvGrid array\r\n * @param player The player reference\r\n * @param invGridIndex Item's position in InvGrid (this should be the item's topleft grid tile)\r\n * @param invListIndex The item's InvList index (it's expected this already has +1 added to it since InvGrid can't store a 0 index)\r\n * @param itemSize Size of item\r\n */\r\nvoid AddItemToInvGrid(Player &player, int invGridIndex, int invListIndex, Size itemSize, bool sendNetworkMessage)\r\n{\r\n\tconst int pitch = 10;\r\n\tfor (int y = 0; y < itemSize.height; y++) {\r\n\t\tconst int rowGridIndex = invGridIndex + pitch * y;\r\n\t\tfor (int x = 0; x < itemSize.width; x++) {\r\n\t\t\tif (x == 0 && y == itemSize.height - 1)\r\n\t\t\t\tplayer.InvGrid[rowGridIndex + x] = invListIndex;\r\n\t\t\telse\r\n\t\t\t\tplayer.InvGrid[rowGridIndex + x] = -invListIndex; // use negative index to denote it's occupied but it's not the top-left cell.\r\n\t\t}\r\n\t}\r\n\r\n\tif (sendNetworkMessage) {\r\n\t\tNetSendCmdChInvItem(false, invGridIndex);\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Checks whether the given item can fit in a belt slot (i.e. the item's size in inventory cells is 1x1).\r\n * @param item The item to be checked.\r\n * @return 'True' in case the item can fit a belt slot and 'False' otherwise.\r\n */\r\nbool FitsInBeltSlot(const Item &item)\r\n{\r\n\treturn GetInventorySize(item) == Size { 1, 1 };\r\n}\r\n\r\n/**\r\n * @brief Checks whether the given item can be equipped. Since this overload doesn't take player information, it only considers\r\n * general aspects about the item, like if its requirements are met and if the item's target location is valid for the body.\r\n * @param item The item to check.\r\n * @return 'True' in case the item could be equipped in a player, and 'False' otherwise.\r\n */\r\nbool CanEquip(const Item &item)\r\n{\r\n\treturn item.isEquipment()\r\n\t    && item._iStatFlag;\r\n}\r\n\r\n/**\r\n * @brief A specialized version of 'CanEquip(int, Item&, int)' that specifically checks whether the item can be equipped\r\n * in one/both of the player's hands.\r\n * @param player The player whose inventory will be checked for compatibility with the item.\r\n * @param item The item to check.\r\n * @return 'True' if the player can currently equip the item in either one of his hands (i.e. the required hands are empty and\r\n * allow the item), and 'False' otherwise.\r\n */\r\nbool CanWield(Player &player, const Item &item)\r\n{\r\n\tif (!CanEquip(item) || IsNoneOf(player.GetItemLocation(item), ILOC_ONEHAND, ILOC_TWOHAND))\r\n\t\treturn false;\r\n\r\n\tconst Item &leftHandItem = player.InvBody[INVLOC_HAND_LEFT];\r\n\tconst Item &rightHandItem = player.InvBody[INVLOC_HAND_RIGHT];\r\n\r\n\tif (leftHandItem.isEmpty() && rightHandItem.isEmpty()) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (!leftHandItem.isEmpty() && !rightHandItem.isEmpty()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst Item &occupiedHand = !leftHandItem.isEmpty() ? leftHandItem : rightHandItem;\r\n\r\n\t// Bard can dual wield swords and maces, so we allow equiping one-handed weapons in her free slot as long as her occupied\r\n\t// slot is another one-handed weapon.\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(player._pClass);\r\n\tif (HasAnyOf(classAttributes.classFlags, PlayerClassFlag::DualWield)) {\r\n\t\tconst bool occupiedHandIsOneHandedSwordOrMace = player.GetItemLocation(occupiedHand) == ILOC_ONEHAND\r\n\t\t    && IsAnyOf(occupiedHand._itype, ItemType::Sword, ItemType::Mace);\r\n\r\n\t\tconst bool weaponToEquipIsOneHandedSwordOrMace = player.GetItemLocation(item) == ILOC_ONEHAND\r\n\t\t    && IsAnyOf(item._itype, ItemType::Sword, ItemType::Mace);\r\n\r\n\t\tif (occupiedHandIsOneHandedSwordOrMace && weaponToEquipIsOneHandedSwordOrMace) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn player.GetItemLocation(item) == ILOC_ONEHAND\r\n\t    && player.GetItemLocation(occupiedHand) == ILOC_ONEHAND\r\n\t    && item._iClass != occupiedHand._iClass;\r\n}\r\n\r\n/**\r\n * @brief Checks whether the specified item can be equipped in the desired body location on the player.\r\n * @param player The player whose inventory will be checked for compatibility with the item.\r\n * @param item The item to check.\r\n * @param bodyLocation The location in the inventory to be checked against.\r\n * @return 'True' if the player can currently equip the item in the specified body location (i.e. the body location is empty and\r\n * allows the item), and 'False' otherwise.\r\n */\r\nbool CanEquip(Player &player, const Item &item, inv_body_loc bodyLocation)\r\n{\r\n\tif (!CanEquip(item) || player._pmode > PM_WALK_SIDEWAYS || !player.InvBody[bodyLocation].isEmpty()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tswitch (bodyLocation) {\r\n\tcase INVLOC_AMULET:\r\n\t\treturn item._iLoc == ILOC_AMULET;\r\n\r\n\tcase INVLOC_CHEST:\r\n\t\treturn item._iLoc == ILOC_ARMOR;\r\n\r\n\tcase INVLOC_HAND_LEFT:\r\n\tcase INVLOC_HAND_RIGHT:\r\n\t\treturn CanWield(player, item);\r\n\r\n\tcase INVLOC_HEAD:\r\n\t\treturn item._iLoc == ILOC_HELM;\r\n\r\n\tcase INVLOC_RING_LEFT:\r\n\tcase INVLOC_RING_RIGHT:\r\n\t\treturn item._iLoc == ILOC_RING;\r\n\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nvoid ChangeEquipment(Player &player, inv_body_loc bodyLocation, const Item &item, bool sendNetworkMessage)\r\n{\r\n\tplayer.InvBody[bodyLocation] = item;\r\n\r\n\tif (sendNetworkMessage) {\r\n\t\tNetSendCmdChItem(false, bodyLocation, true);\r\n\t}\r\n}\r\n\r\nbool AutoEquip(Player &player, const Item &item, inv_body_loc bodyLocation, bool persistItem, bool sendNetworkMessage)\r\n{\r\n\tif (!CanEquip(player, item, bodyLocation)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (persistItem) {\r\n\t\tChangeEquipment(player, bodyLocation, item, sendNetworkMessage);\r\n\r\n\t\tif (sendNetworkMessage && *GetOptions().Audio.autoEquipSound) {\r\n\t\t\tPlaySFX(ItemInvSnds[ItemCAnimTbl[item._iCurs]]);\r\n\t\t}\r\n\r\n\t\tCalcPlrInv(player, true);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nint FindTargetSlotUnderItemCursor(Point cursorPosition, Size itemSize)\r\n{\r\n\tDisplacement panelOffset = Point { 0, 0 } - GetRightPanel().position;\r\n\tfor (int r = SLOTXY_EQUIPPED_FIRST; r <= SLOTXY_EQUIPPED_LAST; r++) {\r\n\t\tif (InvRect[r].contains(cursorPosition + panelOffset))\r\n\t\t\treturn r;\r\n\t}\r\n\tfor (int r = SLOTXY_INV_FIRST; r <= SLOTXY_INV_LAST; r++) {\r\n\t\tif (InvRect[r].contains(cursorPosition + panelOffset)) {\r\n\t\t\t// When trying to paste into the inventory we need to determine the top left cell of the nearest area that could fit the item, not the slot under the center/hot pixel.\r\n\t\t\tif (itemSize.height <= 1 && itemSize.width <= 1) {\r\n\t\t\t\t// top left cell of a 1x1 item is the same cell as the hot pixel, no work to do\r\n\t\t\t\treturn r;\r\n\t\t\t}\r\n\t\t\t// Otherwise work out how far the central cell is from the top-left cell\r\n\t\t\tDisplacement hotPixelCellOffset = { (itemSize.width - 1) / 2, (itemSize.height - 1) / 2 };\r\n\t\t\t// For even dimension items we need to work out if the cursor is in the left/right (or top/bottom) half of the central cell and adjust the offset so the item lands in the area most covered by the cursor.\r\n\t\t\tif (itemSize.width % 2 == 0 && InvRect[r].contains(cursorPosition + panelOffset + Displacement { INV_SLOT_HALF_SIZE_PX, 0 })) {\r\n\t\t\t\t// hot pixel was in the left half of the cell, so we want to increase the offset to preference the column to the left\r\n\t\t\t\thotPixelCellOffset.deltaX++;\r\n\t\t\t}\r\n\t\t\tif (itemSize.height % 2 == 0 && InvRect[r].contains(cursorPosition + panelOffset + Displacement { 0, INV_SLOT_HALF_SIZE_PX })) {\r\n\t\t\t\t// hot pixel was in the top half of the cell, so we want to increase the offset to preference the row above\r\n\t\t\t\thotPixelCellOffset.deltaY++;\r\n\t\t\t}\r\n\t\t\t// Then work out the top left cell of the nearest area that could fit this item (as pasting on the edge of the inventory would otherwise put it out of bounds)\r\n\t\t\tconst int hotPixelCell = r - SLOTXY_INV_FIRST;\r\n\t\t\tconst int targetRow = std::clamp((hotPixelCell / InventorySizeInSlots.width) - hotPixelCellOffset.deltaY, 0, InventorySizeInSlots.height - itemSize.height);\r\n\t\t\tconst int targetColumn = std::clamp((hotPixelCell % InventorySizeInSlots.width) - hotPixelCellOffset.deltaX, 0, InventorySizeInSlots.width - itemSize.width);\r\n\t\t\treturn SLOTXY_INV_FIRST + targetRow * InventorySizeInSlots.width + targetColumn;\r\n\t\t}\r\n\t}\r\n\r\n\tpanelOffset = Point { 0, 0 } - GetMainPanel().position;\r\n\tfor (int r = SLOTXY_BELT_FIRST; r <= SLOTXY_BELT_LAST; r++) {\r\n\t\tif (InvRect[r].contains(cursorPosition + panelOffset))\r\n\t\t\treturn r;\r\n\t}\r\n\treturn NUM_XY_SLOTS;\r\n}\r\n\r\nvoid ChangeBodyEquipment(Player &player, int slot, item_equip_type location)\r\n{\r\n\tconst inv_body_loc bodyLocation = [&slot](item_equip_type location) {\r\n\t\tswitch (location) {\r\n\t\tcase ILOC_HELM:\r\n\t\t\treturn INVLOC_HEAD;\r\n\t\tcase ILOC_RING:\r\n\t\t\treturn (slot == SLOTXY_RING_LEFT ? INVLOC_RING_LEFT : INVLOC_RING_RIGHT);\r\n\t\tcase ILOC_AMULET:\r\n\t\t\treturn INVLOC_AMULET;\r\n\t\tcase ILOC_ARMOR:\r\n\t\t\treturn INVLOC_CHEST;\r\n\t\tdefault:\r\n\t\t\tapp_fatal(\"Unexpected equipment type\");\r\n\t\t}\r\n\t}(location);\r\n\tconst Item previouslyEquippedItem = player.InvBody[slot];\r\n\tChangeEquipment(player, bodyLocation, player.HoldItem.pop(), &player == MyPlayer);\r\n\tif (!previouslyEquippedItem.isEmpty()) {\r\n\t\tplayer.HoldItem = previouslyEquippedItem;\r\n\t}\r\n}\r\n\r\nvoid ChangeEquippedItem(Player &player, uint8_t slot)\r\n{\r\n\tconst inv_body_loc selectedHand = slot == SLOTXY_HAND_LEFT ? INVLOC_HAND_LEFT : INVLOC_HAND_RIGHT;\r\n\tconst inv_body_loc otherHand = slot == SLOTXY_HAND_LEFT ? INVLOC_HAND_RIGHT : INVLOC_HAND_LEFT;\r\n\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(player._pClass);\r\n\r\n\tconst bool pasteIntoSelectedHand = (player.InvBody[otherHand].isEmpty() || player.InvBody[otherHand]._iClass != player.HoldItem._iClass)\r\n\t    || (HasAnyOf(classAttributes.classFlags, PlayerClassFlag::DualWield) && player.InvBody[otherHand]._iClass == ICLASS_WEAPON && player.HoldItem._iClass == ICLASS_WEAPON);\r\n\r\n\tconst bool dequipTwoHandedWeapon = (!player.InvBody[otherHand].isEmpty() && player.GetItemLocation(player.InvBody[otherHand]) == ILOC_TWOHAND);\r\n\r\n\tconst inv_body_loc pasteHand = pasteIntoSelectedHand ? selectedHand : otherHand;\r\n\tconst Item previouslyEquippedItem = dequipTwoHandedWeapon ? player.InvBody[otherHand] : player.InvBody[pasteHand];\r\n\tif (dequipTwoHandedWeapon) {\r\n\t\tRemoveEquipment(player, otherHand, false);\r\n\t}\r\n\tChangeEquipment(player, pasteHand, player.HoldItem.pop(), &player == MyPlayer);\r\n\tif (!previouslyEquippedItem.isEmpty()) {\r\n\t\tplayer.HoldItem = previouslyEquippedItem;\r\n\t}\r\n}\r\n\r\nvoid ChangeTwoHandItem(Player &player)\r\n{\r\n\tif (!player.InvBody[INVLOC_HAND_LEFT].isEmpty() && !player.InvBody[INVLOC_HAND_RIGHT].isEmpty()) {\r\n\t\tinv_body_loc locationToUnequip = INVLOC_HAND_LEFT;\r\n\t\tif (player.InvBody[INVLOC_HAND_RIGHT]._itype == ItemType::Shield) {\r\n\t\t\tlocationToUnequip = INVLOC_HAND_RIGHT;\r\n\t\t}\r\n\t\tif (!AutoPlaceItemInInventory(player, player.InvBody[locationToUnequip])) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (locationToUnequip == INVLOC_HAND_RIGHT) {\r\n\t\t\tRemoveEquipment(player, INVLOC_HAND_RIGHT, false);\r\n\t\t} else {\r\n\t\t\tplayer.InvBody[INVLOC_HAND_LEFT].clear();\r\n\t\t}\r\n\t}\r\n\r\n\tif (player.InvBody[INVLOC_HAND_RIGHT].isEmpty()) {\r\n\t\tconst Item previouslyEquippedItem = player.InvBody[INVLOC_HAND_LEFT];\r\n\t\tChangeEquipment(player, INVLOC_HAND_LEFT, player.HoldItem.pop(), &player == MyPlayer);\r\n\t\tif (!previouslyEquippedItem.isEmpty()) {\r\n\t\t\tplayer.HoldItem = previouslyEquippedItem;\r\n\t\t}\r\n\t} else {\r\n\t\tconst Item previouslyEquippedItem = player.InvBody[INVLOC_HAND_RIGHT];\r\n\t\tRemoveEquipment(player, INVLOC_HAND_RIGHT, false);\r\n\t\tChangeEquipment(player, INVLOC_HAND_LEFT, player.HoldItem, &player == MyPlayer);\r\n\t\tplayer.HoldItem = previouslyEquippedItem;\r\n\t}\r\n}\r\n\r\nint8_t CheckOverlappingItems(int slot, const Player &player, Size itemSize)\r\n{\r\n\t// check that the item we're pasting only overlaps one other item (or is going into empty space)\r\n\tconst unsigned originCell = static_cast<unsigned>(slot - SLOTXY_INV_FIRST);\r\n\r\n\tint8_t overlappingId = 0;\r\n\tfor (unsigned rowOffset = 0; rowOffset < static_cast<unsigned>(itemSize.height * InventorySizeInSlots.width); rowOffset += InventorySizeInSlots.width) {\r\n\r\n\t\tfor (unsigned columnOffset = 0; columnOffset < static_cast<unsigned>(itemSize.width); columnOffset++) {\r\n\t\t\tconst unsigned testCell = originCell + rowOffset + columnOffset;\r\n\t\t\t// FindTargetSlotUnderItemCursor returns the top left slot of the inventory region that fits the item, we can be confident this calculation is not going to read out of range.\r\n\t\t\tassert(testCell < sizeof(player.InvGrid));\r\n\t\t\tif (player.InvGrid[testCell] != 0) {\r\n\t\t\t\tconst int8_t iv = std::abs(player.InvGrid[testCell]);\r\n\t\t\t\tif (overlappingId != 0) {\r\n\t\t\t\t\tif (overlappingId != iv) {\r\n\t\t\t\t\t\t// Found two different items that would be displaced by the held item, can't paste the item here.\r\n\t\t\t\t\t\treturn -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\toverlappingId = iv;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn overlappingId;\r\n}\r\n\r\nint8_t GetPrevItemId(int slot, const Player &player, const Size &itemSize)\r\n{\r\n\tif (player.HoldItem._itype != ItemType::Gold)\r\n\t\treturn CheckOverlappingItems(slot, player, itemSize);\r\n\tconst int8_t item_cell_begin = player.InvGrid[slot - SLOTXY_INV_FIRST];\r\n\tif (item_cell_begin == 0)\r\n\t\treturn 0;\r\n\tif (item_cell_begin <= 0)\r\n\t\treturn -item_cell_begin;\r\n\tif (player.InvList[item_cell_begin - 1]._itype != ItemType::Gold)\r\n\t\treturn item_cell_begin;\r\n\treturn 0;\r\n}\r\n\r\nbool ChangeInvItem(Player &player, int slot, Size itemSize)\r\n{\r\n\tint8_t prevItemId = GetPrevItemId(slot, player, itemSize);\r\n\tif (prevItemId < 0) return false;\r\n\r\n\tif (player.HoldItem._itype == ItemType::Gold && prevItemId == 0) {\r\n\t\tconst int ii = slot - SLOTXY_INV_FIRST;\r\n\t\tif (player.InvGrid[ii] > 0) {\r\n\t\t\tconst int invIndex = player.InvGrid[ii] - 1;\r\n\t\t\tconst int gt = player.InvList[invIndex]._ivalue;\r\n\t\t\tint ig = player.HoldItem._ivalue + gt;\r\n\t\t\tif (ig <= MaxGold) {\r\n\t\t\t\tplayer.InvList[invIndex]._ivalue = ig;\r\n\t\t\t\tSetPlrHandGoldCurs(player.InvList[invIndex]);\r\n\t\t\t\tplayer._pGold += player.HoldItem._ivalue;\r\n\t\t\t\tplayer.HoldItem.clear();\r\n\t\t\t} else {\r\n\t\t\t\tig = MaxGold - gt;\r\n\t\t\t\tplayer._pGold += ig;\r\n\t\t\t\tplayer.HoldItem._ivalue -= ig;\r\n\t\t\t\tSetPlrHandGoldCurs(player.HoldItem);\r\n\t\t\t\tplayer.InvList[invIndex]._ivalue = MaxGold;\r\n\t\t\t\tplayer.InvList[invIndex]._iCurs = ICURS_GOLD_LARGE;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst int invIndex = player._pNumInv;\r\n\t\t\tplayer._pGold += player.HoldItem._ivalue;\r\n\t\t\tplayer.InvList[invIndex] = player.HoldItem.pop();\r\n\t\t\tplayer._pNumInv++;\r\n\t\t\tplayer.InvGrid[ii] = player._pNumInv;\r\n\t\t}\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tNetSendCmdChInvItem(false, ii);\r\n\t\t}\r\n\t} else {\r\n\t\tif (prevItemId == 0) {\r\n\t\t\tplayer.InvList[player._pNumInv] = player.HoldItem.pop();\r\n\t\t\tplayer._pNumInv++;\r\n\t\t\tprevItemId = player._pNumInv;\r\n\t\t} else {\r\n\t\t\tconst int invIndex = prevItemId - 1;\r\n\t\t\tif (player.HoldItem._itype == ItemType::Gold)\r\n\t\t\t\tplayer._pGold += player.HoldItem._ivalue;\r\n\t\t\tstd::swap(player.InvList[invIndex], player.HoldItem);\r\n\t\t\tif (player.HoldItem._itype == ItemType::Gold)\r\n\t\t\t\tplayer._pGold = CalculateGold(player);\r\n\t\t\tfor (int8_t &itemIndex : player.InvGrid) {\r\n\t\t\t\tif (itemIndex == prevItemId)\r\n\t\t\t\t\titemIndex = 0;\r\n\t\t\t\tif (itemIndex == -prevItemId)\r\n\t\t\t\t\titemIndex = 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tAddItemToInvGrid(player, slot - SLOTXY_INV_FIRST, prevItemId, itemSize, &player == MyPlayer);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid ChangeBeltItem(Player &player, int slot)\r\n{\r\n\tconst int ii = slot - SLOTXY_BELT_FIRST;\r\n\tif (player.SpdList[ii].isEmpty()) {\r\n\t\tplayer.SpdList[ii] = player.HoldItem.pop();\r\n\t} else {\r\n\t\tstd::swap(player.SpdList[ii], player.HoldItem);\r\n\r\n\t\tif (player.HoldItem._itype == ItemType::Gold)\r\n\t\t\tplayer._pGold = CalculateGold(player);\r\n\t}\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdChBeltItem(false, ii);\r\n\t}\r\n\tRedrawComponent(PanelDrawComponent::Belt);\r\n}\r\n\r\nitem_equip_type GetItemEquipType(const Player &player, int slot, item_equip_type desiredLocation)\r\n{\r\n\tif (slot == SLOTXY_HEAD)\r\n\t\treturn ILOC_HELM;\r\n\tif (slot == SLOTXY_RING_LEFT || slot == SLOTXY_RING_RIGHT)\r\n\t\treturn ILOC_RING;\r\n\tif (slot == SLOTXY_AMULET)\r\n\t\treturn ILOC_AMULET;\r\n\tif (slot == SLOTXY_HAND_LEFT || slot == SLOTXY_HAND_RIGHT) {\r\n\t\tif (desiredLocation == ILOC_TWOHAND)\r\n\t\t\treturn ILOC_TWOHAND;\r\n\t\treturn ILOC_ONEHAND;\r\n\t}\r\n\tif (slot == SLOTXY_CHEST)\r\n\t\treturn ILOC_ARMOR;\r\n\tif (slot >= SLOTXY_BELT_FIRST && slot <= SLOTXY_BELT_LAST)\r\n\t\treturn ILOC_BELT;\r\n\r\n\treturn ILOC_UNEQUIPABLE;\r\n}\r\n\r\nvoid CheckInvPaste(Player &player, Point cursorPosition)\r\n{\r\n\tconst Size itemSize = GetInventorySize(player.HoldItem);\r\n\r\n\tconst int slot = FindTargetSlotUnderItemCursor(cursorPosition, itemSize);\r\n\tif (slot == NUM_XY_SLOTS)\r\n\t\treturn;\r\n\r\n\tconst item_equip_type desiredLocation = player.GetItemLocation(player.HoldItem);\r\n\tconst item_equip_type location = GetItemEquipType(player, slot, desiredLocation);\r\n\r\n\tif (location == ILOC_BELT) {\r\n\t\tif (!CanBePlacedOnBelt(player, player.HoldItem)) return;\r\n\t} else if (location != ILOC_UNEQUIPABLE) {\r\n\t\tif (desiredLocation != location) return;\r\n\t}\r\n\r\n\tif (IsNoneOf(location, ILOC_UNEQUIPABLE, ILOC_BELT)) {\r\n\t\tif (!player.CanUseItem(player.HoldItem)) {\r\n\t\t\tplayer.Say(HeroSpeech::ICantUseThisYet);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (player._pmode > PM_WALK_SIDEWAYS)\r\n\t\t\treturn;\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tPlaySFX(ItemInvSnds[ItemCAnimTbl[player.HoldItem._iCurs]]);\r\n\t}\r\n\r\n\t// Select the parameters that go into\r\n\t// ChangeEquipment and add it to post switch\r\n\tswitch (location) {\r\n\tcase ILOC_HELM:\r\n\tcase ILOC_RING:\r\n\tcase ILOC_AMULET:\r\n\tcase ILOC_ARMOR:\r\n\t\tChangeBodyEquipment(player, slot, location);\r\n\t\tbreak;\r\n\tcase ILOC_ONEHAND:\r\n\t\tChangeEquippedItem(player, slot);\r\n\t\tbreak;\r\n\tcase ILOC_TWOHAND:\r\n\t\tChangeTwoHandItem(player);\r\n\t\tbreak;\r\n\tcase ILOC_UNEQUIPABLE:\r\n\t\tif (!ChangeInvItem(player, slot, itemSize)) return;\r\n\t\tbreak;\r\n\tcase ILOC_BELT:\r\n\t\tChangeBeltItem(player, slot);\r\n\t\tbreak;\r\n\tcase ILOC_NONE:\r\n\tcase ILOC_INVALID:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n\tif (&player == MyPlayer) {\r\n\t\tNewCursor(player.HoldItem);\r\n\t}\r\n}\r\n\r\ninv_body_loc MapSlotToInvBodyLoc(inv_xy_slot slot)\r\n{\r\n\tassert(slot <= SLOTXY_CHEST);\r\n\treturn static_cast<inv_body_loc>(slot);\r\n}\r\n\r\nstd::optional<inv_xy_slot> FindSlotUnderCursor(Point cursorPosition)\r\n{\r\n\r\n\tPoint testPosition = static_cast<Point>(cursorPosition - GetRightPanel().position);\r\n\tfor (std::underlying_type_t<inv_xy_slot> r = SLOTXY_EQUIPPED_FIRST; r != SLOTXY_BELT_FIRST; r++) {\r\n\t\t// check which body/inventory rectangle the mouse is in, if any\r\n\t\tif (InvRect[r].contains(testPosition)) {\r\n\t\t\treturn static_cast<inv_xy_slot>(r);\r\n\t\t}\r\n\t}\r\n\r\n\ttestPosition = static_cast<Point>(cursorPosition - GetMainPanel().position);\r\n\tfor (std::underlying_type_t<inv_xy_slot> r = SLOTXY_BELT_FIRST; r != NUM_XY_SLOTS; r++) {\r\n\t\t// check which belt rectangle the mouse is in, if any\r\n\t\tif (InvRect[r].contains(testPosition)) {\r\n\t\t\treturn static_cast<inv_xy_slot>(r);\r\n\t\t}\r\n\t}\r\n\r\n\treturn {};\r\n}\r\n\r\n/**\r\n * @brief Checks whether an item of the given size can be placed on the specified player's inventory slot.\r\n * @param player The player whose inventory will be checked.\r\n * @param slotIndex The 0-based index of the slot to put the item on.\r\n * @param itemSize The size of the item to be checked.\r\n * @param itemIndexToIgnore can be used to check if an item of the given size would fit if the item with the given (positive) ID was removed.\r\n * @return 'True' in case the item can be placed on the specified player's inventory slot and 'False' otherwise.\r\n */\r\nbool CheckItemFitsInInventorySlot(const Player &player, int slotIndex, const Size &itemSize, int itemIndexToIgnore)\r\n{\r\n\tint yy = (slotIndex > 0) ? (10 * (slotIndex / 10)) : 0;\r\n\r\n\tfor (int j = 0; j < itemSize.height; j++) {\r\n\t\tif (yy >= InventoryGridCells) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tint xx = (slotIndex > 0) ? (slotIndex % 10) : 0;\r\n\t\tfor (int i = 0; i < itemSize.width; i++) {\r\n\t\t\tif (xx >= 10 || !(player.InvGrid[xx + yy] == 0 || std::abs(player.InvGrid[xx + yy]) - 1 == itemIndexToIgnore)) {\r\n\t\t\t\t// The item is too wide to fit in the specified column, or one of the cells is occupied (and not by the item we're planning on removing)\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\txx++;\r\n\t\t}\r\n\t\tyy += 10;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * @brief Finds the first slot that could fit an item of the given size\r\n * @param player Player whose inventory will be checked.\r\n * @param itemSize Dimensions of the item.\r\n * @param itemIndexToIgnore Can be used if you want to find whether the new item would fit with this item removed, without performing unnecessary actions.\r\n * @return The first slot that could fit the item or an empty optional.\r\n */\r\nstd::optional<int> FindSlotForItem(const Player &player, const Size &itemSize, int itemIndexToIgnore = -1)\r\n{\r\n\tif (itemSize.height == 1) {\r\n\t\tfor (int i = 30; i <= 39; i++) {\r\n\t\t\tif (CheckItemFitsInInventorySlot(player, i, itemSize, itemIndexToIgnore))\r\n\t\t\t\treturn i;\r\n\t\t}\r\n\t\tfor (int x = 9; x >= 0; x--) {\r\n\t\t\tfor (int y = 2; y >= 0; y--) {\r\n\t\t\t\tif (CheckItemFitsInInventorySlot(player, 10 * y + x, itemSize, itemIndexToIgnore))\r\n\t\t\t\t\treturn 10 * y + x;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\r\n\tif (itemSize.height == 2) {\r\n\t\tfor (int x = 10 - itemSize.width; x >= 0; x--) {\r\n\t\t\tfor (int y = 0; y < 3; y++) {\r\n\t\t\t\tif (CheckItemFitsInInventorySlot(player, 10 * y + x, itemSize, itemIndexToIgnore))\r\n\t\t\t\t\treturn 10 * y + x;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\r\n\tif (itemSize == Size { 1, 3 }) {\r\n\t\tfor (int i = 0; i < 20; i++) {\r\n\t\t\tif (CheckItemFitsInInventorySlot(player, i, itemSize, itemIndexToIgnore))\r\n\t\t\t\treturn i;\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\r\n\tif (itemSize == Size { 2, 3 }) {\r\n\t\tfor (int i = 0; i < 9; i++) {\r\n\t\t\tif (CheckItemFitsInInventorySlot(player, i, itemSize, itemIndexToIgnore))\r\n\t\t\t\treturn i;\r\n\t\t}\r\n\r\n\t\tfor (int i = 10; i < 19; i++) {\r\n\t\t\tif (CheckItemFitsInInventorySlot(player, i, itemSize, itemIndexToIgnore))\r\n\t\t\t\treturn i;\r\n\t\t}\r\n\t\treturn {};\r\n\t}\r\n\r\n\tapp_fatal(StrCat(\"Unknown item size: \", itemSize.width, \"x\", itemSize.height));\r\n}\r\n\r\n/**\r\n * @brief Checks if the given item could be placed on the specified players inventory if the other item was removed.\r\n * @param player The player whose inventory will be checked.\r\n * @param item The item to be checked.\r\n * @param itemIndexToIgnore The inventory index of the item that we assume will be removed.\r\n * @return 'True' if the item could fit with the other item removed and 'False' otherwise.\r\n */\r\nbool CouldFitItemInInventory(const Player &player, const Item &item, int itemIndexToIgnore)\r\n{\r\n\treturn static_cast<bool>(FindSlotForItem(player, GetInventorySize(item), itemIndexToIgnore));\r\n}\r\n\r\nvoid CheckInvCut(Player &player, Point cursorPosition, bool automaticMove, bool dropItem)\r\n{\r\n\tif (player._pmode > PM_WALK_SIDEWAYS) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tCloseGoldDrop();\r\n\r\n\tstd::optional<inv_xy_slot> maybeSlot = FindSlotUnderCursor(cursorPosition);\r\n\r\n\tif (!maybeSlot) {\r\n\t\t// not on an inventory slot rectangle\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst inv_xy_slot r = *maybeSlot;\r\n\r\n\tItem &holdItem = player.HoldItem;\r\n\tholdItem.clear();\r\n\r\n\tbool attemptedMove = false;\r\n\tbool automaticallyMoved = false;\r\n\tSfxID successSound = SfxID::None;\r\n\tHeroSpeech failedSpeech = HeroSpeech::ICantDoThat; // Default message if the player attempts to automove an item that can't go anywhere else\r\n\r\n\tif (r >= SLOTXY_HEAD && r <= SLOTXY_CHEST) {\r\n\t\tconst inv_body_loc invloc = MapSlotToInvBodyLoc(r);\r\n\t\tif (!player.InvBody[invloc].isEmpty()) {\r\n\t\t\tif (automaticMove) {\r\n\t\t\t\tattemptedMove = true;\r\n\t\t\t\tautomaticallyMoved = AutoPlaceItemInInventory(player, player.InvBody[invloc]);\r\n\t\t\t\tif (automaticallyMoved) {\r\n\t\t\t\t\tsuccessSound = ItemInvSnds[ItemCAnimTbl[player.InvBody[invloc]._iCurs]];\r\n\t\t\t\t\tRemoveEquipment(player, invloc, false);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tfailedSpeech = HeroSpeech::IHaveNoRoom;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tholdItem = player.InvBody[invloc];\r\n\t\t\t\tRemoveEquipment(player, invloc, false);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (r >= SLOTXY_INV_FIRST && r <= SLOTXY_INV_LAST) {\r\n\t\tconst unsigned ig = r - SLOTXY_INV_FIRST;\r\n\t\tconst int iv = std::abs(player.InvGrid[ig]) - 1;\r\n\t\tif (iv >= 0) {\r\n\t\t\tif (automaticMove) {\r\n\t\t\t\tattemptedMove = true;\r\n\t\t\t\tif (CanBePlacedOnBelt(player, player.InvList[iv])) {\r\n\t\t\t\t\tautomaticallyMoved = AutoPlaceItemInBelt(player, player.InvList[iv], true, &player == MyPlayer);\r\n\t\t\t\t\tif (automaticallyMoved) {\r\n\t\t\t\t\t\tsuccessSound = SfxID::GrabItem;\r\n\t\t\t\t\t\tplayer.RemoveInvItem(iv, false);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tfailedSpeech = HeroSpeech::IHaveNoRoom;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (CanEquip(player.InvList[iv])) {\r\n\t\t\t\t\tfailedSpeech = HeroSpeech::IHaveNoRoom; // Default to saying \"I have no room\" if auto-equip fails\r\n\r\n\t\t\t\t\t/*\r\n\t\t\t\t\t * If the player shift-clicks an item in the inventory we want to swap it with whatever item may be\r\n\t\t\t\t\t * equipped in the target slot. Lifting the item to the hand unconditionally would be ideal, except\r\n\t\t\t\t\t * we don't want to leave the item on the hand if the equip attempt failed. We would end up\r\n\t\t\t\t\t * generating wasteful network messages if we did the lift first. Instead we work out whatever slot\r\n\t\t\t\t\t * needs to be unequipped (if any):\r\n\t\t\t\t\t */\r\n\t\t\t\t\tint invloc = NUM_INVLOC;\r\n\t\t\t\t\tswitch (player.GetItemLocation(player.InvList[iv])) {\r\n\t\t\t\t\tcase ILOC_ARMOR:\r\n\t\t\t\t\t\tinvloc = INVLOC_CHEST;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ILOC_HELM:\r\n\t\t\t\t\t\tinvloc = INVLOC_HEAD;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ILOC_AMULET:\r\n\t\t\t\t\t\tinvloc = INVLOC_AMULET;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ILOC_ONEHAND:\r\n\t\t\t\t\t\tif (!player.InvBody[INVLOC_HAND_LEFT].isEmpty()\r\n\t\t\t\t\t\t    && (player.InvList[iv]._iClass == player.InvBody[INVLOC_HAND_LEFT]._iClass\r\n\t\t\t\t\t\t        || player.GetItemLocation(player.InvBody[INVLOC_HAND_LEFT]) == ILOC_TWOHAND)) {\r\n\t\t\t\t\t\t\t// The left hand is not empty and we're either trying to equip the same type of item or\r\n\t\t\t\t\t\t\t// it's holding a two handed weapon, so it must be unequipped\r\n\t\t\t\t\t\t\tinvloc = INVLOC_HAND_LEFT;\r\n\t\t\t\t\t\t} else if (!player.InvBody[INVLOC_HAND_RIGHT].isEmpty() && player.InvList[iv]._iClass == player.InvBody[INVLOC_HAND_RIGHT]._iClass) {\r\n\t\t\t\t\t\t\t// The right hand is not empty and we're trying to equip the same type of item, so we need\r\n\t\t\t\t\t\t\t// to unequip that item\r\n\t\t\t\t\t\t\tinvloc = INVLOC_HAND_RIGHT;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t// otherwise one hand is empty (and we can let the auto-equip code put the target item into\r\n\t\t\t\t\t\t// that hand) or we're playing a bard with two swords equipped and we're trying to auto-equip\r\n\t\t\t\t\t\t// a shield (in which case the attempt will fail).\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase ILOC_TWOHAND:\r\n\t\t\t\t\t\t// Moving a two-hand item from inventory to InvBody requires emptying both hands.\r\n\t\t\t\t\t\tif (player.InvBody[INVLOC_HAND_RIGHT].isEmpty()) {\r\n\t\t\t\t\t\t\t// If the right hand is empty then we can simply try equipping this item in the left hand,\r\n\t\t\t\t\t\t\t// we'll let the common code take care of unequipping anything held there.\r\n\t\t\t\t\t\t\tinvloc = INVLOC_HAND_LEFT;\r\n\t\t\t\t\t\t} else if (player.InvBody[INVLOC_HAND_LEFT].isEmpty()) {\r\n\t\t\t\t\t\t\t// We have an item in the right hand but nothing in the left, so let the common code\r\n\t\t\t\t\t\t\t// take care of unequipping whatever is held in the right hand. The auto-equip code\r\n\t\t\t\t\t\t\t// picks the most appropriate location for the item type (which in this case will be\r\n\t\t\t\t\t\t\t// the left hand), invloc isn't used there.\r\n\t\t\t\t\t\t\tinvloc = INVLOC_HAND_RIGHT;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t// Both hands are holding items, we must unequip one of the items and check that there's\r\n\t\t\t\t\t\t\t// space for the other before trying to auto-equip\r\n\t\t\t\t\t\t\tinv_body_loc mainHand = INVLOC_HAND_LEFT;\r\n\t\t\t\t\t\t\tinv_body_loc offHand = INVLOC_HAND_RIGHT;\r\n\t\t\t\t\t\t\tif (!AutoPlaceItemInInventory(player, player.InvBody[offHand])) {\r\n\t\t\t\t\t\t\t\t// No space to move right hand item to inventory, can we move the left instead?\r\n\t\t\t\t\t\t\t\tstd::swap(mainHand, offHand);\r\n\t\t\t\t\t\t\t\tif (!AutoPlaceItemInInventory(player, player.InvBody[offHand])) {\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (!CouldFitItemInInventory(player, player.InvBody[mainHand], iv)) {\r\n\t\t\t\t\t\t\t\t// No space for the main hand item. Move the other item back to the off hand and abort.\r\n\t\t\t\t\t\t\t\tplayer.InvBody[offHand] = player.InvList[player._pNumInv - 1];\r\n\t\t\t\t\t\t\t\tplayer.RemoveInvItem(player._pNumInv - 1, false);\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tRemoveEquipment(player, offHand, false);\r\n\t\t\t\t\t\t\tinvloc = mainHand;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t// If the player is trying to equip a ring we want to say \"I can't do that\" if they don't already have a ring slot free.\r\n\t\t\t\t\t\tfailedSpeech = HeroSpeech::ICantDoThat;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Then empty the identified InvBody slot (invloc) and hand over to AutoEquip\r\n\t\t\t\t\tif (invloc != NUM_INVLOC\r\n\t\t\t\t\t    && !player.InvBody[invloc].isEmpty()\r\n\t\t\t\t\t    && CouldFitItemInInventory(player, player.InvBody[invloc], iv)) {\r\n\t\t\t\t\t\tholdItem = player.InvBody[invloc].pop();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tautomaticallyMoved = AutoEquip(player, player.InvList[iv], true, &player == MyPlayer);\r\n\t\t\t\t\tif (automaticallyMoved) {\r\n\t\t\t\t\t\tsuccessSound = ItemInvSnds[ItemCAnimTbl[player.InvList[iv]._iCurs]];\r\n\t\t\t\t\t\tplayer.RemoveInvItem(iv, false);\r\n\r\n\t\t\t\t\t\t// If we're holding an item at this point we just lifted it from a body slot to make room for the original item, so we need to put it into the inv\r\n\t\t\t\t\t\tif (!holdItem.isEmpty() && AutoPlaceItemInInventory(player, holdItem)) {\r\n\t\t\t\t\t\t\tholdItem.clear();\r\n\t\t\t\t\t\t} // there should never be a situation where holdItem is not empty but we fail to place it into the inventory given the checks earlier... leave it on the hand in this case.\r\n\t\t\t\t\t} else if (!holdItem.isEmpty()) {\r\n\t\t\t\t\t\t// We somehow failed to equip the item in the slot we already checked should hold it? Better put this item back...\r\n\t\t\t\t\t\tplayer.InvBody[invloc] = holdItem.pop();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tholdItem = player.InvList[iv];\r\n\t\t\t\tplayer.RemoveInvItem(iv, false);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (r >= SLOTXY_BELT_FIRST) {\r\n\t\tconst Item &beltItem = player.SpdList[r - SLOTXY_BELT_FIRST];\r\n\t\tif (!beltItem.isEmpty()) {\r\n\t\t\tif (automaticMove) {\r\n\t\t\t\tattemptedMove = true;\r\n\t\t\t\tautomaticallyMoved = AutoPlaceItemInInventory(player, beltItem);\r\n\t\t\t\tif (automaticallyMoved) {\r\n\t\t\t\t\tsuccessSound = SfxID::GrabItem;\r\n\t\t\t\t\tplayer.RemoveSpdBarItem(r - SLOTXY_BELT_FIRST);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tfailedSpeech = HeroSpeech::IHaveNoRoom;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tholdItem = beltItem;\r\n\t\t\t\tplayer.RemoveSpdBarItem(r - SLOTXY_BELT_FIRST);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (!holdItem.isEmpty()) {\r\n\t\tif (holdItem._itype == ItemType::Gold) {\r\n\t\t\tplayer._pGold = CalculateGold(player);\r\n\t\t}\r\n\r\n\t\tCalcPlrInv(player, true);\r\n\t\tholdItem._iStatFlag = player.CanUseItem(holdItem);\r\n\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tPlaySFX(SfxID::GrabItem);\r\n\t\t\tNewCursor(holdItem);\r\n\t\t}\r\n\t\tif (dropItem) {\r\n\t\t\tTryDropItem();\r\n\t\t}\r\n\t} else if (automaticMove) {\r\n\t\tif (automaticallyMoved) {\r\n\t\t\tCalcPlrInv(player, true);\r\n\t\t}\r\n\t\tif (attemptedMove && &player == MyPlayer) {\r\n\t\t\tif (automaticallyMoved) {\r\n\t\t\t\tPlaySFX(successSound);\r\n\t\t\t} else {\r\n\t\t\t\tplayer.SaySpecific(failedSpeech);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid TryCombineNaKrulNotes(Player &player, Item &noteItem)\r\n{\r\n\tconst int idx = noteItem.IDidx;\r\n\tconst _item_indexes notes[] = { IDI_NOTE1, IDI_NOTE2, IDI_NOTE3 };\r\n\r\n\tif (IsNoneOf(idx, IDI_NOTE1, IDI_NOTE2, IDI_NOTE3)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (const _item_indexes note : notes) {\r\n\t\tif (idx != note && !HasInventoryItemWithId(player, note)) {\r\n\t\t\treturn; // the player doesn't have all notes\r\n\t\t}\r\n\t}\r\n\r\n\tMyPlayer->Say(HeroSpeech::JustWhatIWasLookingFor, 10);\r\n\r\n\tfor (const _item_indexes note : notes) {\r\n\t\tif (idx != note) {\r\n\t\t\tRemoveInventoryItemById(player, note);\r\n\t\t}\r\n\t}\r\n\r\n\tconst Point position = noteItem.position; // copy the position to restore it after re-initialising the item\r\n\tnoteItem = {};\r\n\tGetItemAttrs(noteItem, IDI_FULLNOTE, 16);\r\n\tSetupItem(noteItem);\r\n\tnoteItem.position = position; // this ensures CleanupItem removes the entry in the dropped items lookup table\r\n}\r\n\r\nvoid CheckQuestItem(Player &player, Item &questItem)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (Quests[Q_BLIND]._qactive == QUEST_ACTIVE\r\n\t    && (questItem.IDidx == IDI_OPTAMULET\r\n\t        || (Quests[Q_BLIND].IsAvailable() && questItem.position == (SetPiece.position.megaToWorld() + Displacement { 5, 5 })))) {\r\n\t\tQuests[Q_BLIND]._qactive = QUEST_DONE;\r\n\t\tNetSendCmdQuest(true, Quests[Q_BLIND]);\r\n\t}\r\n\r\n\tif (questItem.IDidx == IDI_MUSHROOM && Quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE && Quests[Q_MUSHROOM]._qvar1 == QS_MUSHSPAWNED) {\r\n\t\tplayer.Say(HeroSpeech::NowThatsOneBigMushroom, 10); // BUGFIX: Voice for this quest might be wrong in MP\r\n\t\tQuests[Q_MUSHROOM]._qvar1 = QS_MUSHPICKED;\r\n\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t}\r\n\r\n\tif (questItem.IDidx == IDI_ANVIL && Quests[Q_ANVIL]._qactive != QUEST_NOTAVAIL) {\r\n\t\tif (Quests[Q_ANVIL]._qactive == QUEST_INIT) {\r\n\t\t\tQuests[Q_ANVIL]._qactive = QUEST_ACTIVE;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_ANVIL]);\r\n\t\t}\r\n\t\tif (Quests[Q_ANVIL]._qlog) {\r\n\t\t\tmyPlayer.Say(HeroSpeech::INeedToGetThisToGriswold, 10);\r\n\t\t}\r\n\t}\r\n\r\n\tif (questItem.IDidx == IDI_GLDNELIX && Quests[Q_VEIL]._qactive != QUEST_NOTAVAIL) {\r\n\t\tmyPlayer.Say(HeroSpeech::INeedToGetThisToLachdanan, 30);\r\n\t}\r\n\r\n\tif (questItem.IDidx == IDI_ROCK && Quests[Q_ROCK]._qactive != QUEST_NOTAVAIL) {\r\n\t\tif (Quests[Q_ROCK]._qactive == QUEST_INIT) {\r\n\t\t\tQuests[Q_ROCK]._qactive = QUEST_ACTIVE;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_ROCK]);\r\n\t\t}\r\n\t\tif (Quests[Q_ROCK]._qlog) {\r\n\t\t\tmyPlayer.Say(HeroSpeech::ThisMustBeWhatGriswoldWanted, 10);\r\n\t\t}\r\n\t}\r\n\r\n\tif (Quests[Q_BLOOD]._qactive == QUEST_ACTIVE\r\n\t    && (questItem.IDidx == IDI_ARMOFVAL\r\n\t        || (Quests[Q_BLOOD].IsAvailable() && questItem.position == (SetPiece.position.megaToWorld() + Displacement { 9, 3 })))) {\r\n\t\tQuests[Q_BLOOD]._qactive = QUEST_DONE;\r\n\t\tNetSendCmdQuest(true, Quests[Q_BLOOD]);\r\n\t\tmyPlayer.Say(HeroSpeech::MayTheSpiritOfArkaineProtectMe, 20);\r\n\t}\r\n\r\n\tif (questItem.IDidx == IDI_MAPOFDOOM) {\r\n\t\tQuests[Q_GRAVE]._qactive = QUEST_ACTIVE;\r\n\t\tif (Quests[Q_GRAVE]._qvar1 != 1) {\r\n\t\t\tMyPlayer->Say(HeroSpeech::UhHuh, 10);\r\n\t\t\tQuests[Q_GRAVE]._qvar1 = 1;\r\n\t\t}\r\n\t}\r\n\r\n\tTryCombineNaKrulNotes(player, questItem);\r\n}\r\n\r\nvoid CleanupItems(int ii)\r\n{\r\n\tconst Item &item = Items[ii];\r\n\tdItem[item.position.x][item.position.y] = 0;\r\n\r\n\tif (CornerStone.isAvailable() && item.position == CornerStone.position) {\r\n\t\tCornerStone.item.clear();\r\n\t\tCornerStone.item.selectionRegion = SelectionRegion::None;\r\n\t\tCornerStone.item.position = { 0, 0 };\r\n\t\tCornerStone.item._iAnimFlag = false;\r\n\t\tCornerStone.item._iIdentified = false;\r\n\t\tCornerStone.item._iPostDraw = false;\r\n\t}\r\n\r\n\tint i = 0;\r\n\twhile (i < ActiveItemCount) {\r\n\t\tif (ActiveItems[i] == ii) {\r\n\t\t\tDeleteItem(i);\r\n\t\t\ti = 0;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\ti++;\r\n\t}\r\n}\r\n\r\nbool CanUseStaff(Item &staff, SpellID spell)\r\n{\r\n\treturn !staff.isEmpty()\r\n\t    && IsAnyOf(staff._iMiscId, IMISC_STAFF, IMISC_UNIQUE)\r\n\t    && staff._iSpell == spell\r\n\t    && staff._iCharges > 0;\r\n}\r\n\r\nvoid StartGoldDrop()\r\n{\r\n\tCloseGoldWithdraw();\r\n\r\n\tconst int8_t invIndex = pcursinvitem;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tconst int max = (invIndex <= INVITEM_INV_LAST)\r\n\t    ? myPlayer.InvList[invIndex - INVITEM_INV_FIRST]._ivalue\r\n\t    : myPlayer.SpdList[invIndex - INVITEM_BELT_FIRST]._ivalue;\r\n\r\n\tif (ChatFlag)\r\n\t\tResetChat();\r\n\r\n\tconst Point start = GetPanelPosition(UiPanels::Inventory, { 67, 128 });\r\n\tSDL_Rect rect = MakeSdlRect(start.x, start.y, 180, 20);\r\n\tSDL_SetTextInputArea(ghMainWnd, &rect, /*cursor=*/0);\r\n\tOpenGoldDrop(invIndex, max);\r\n}\r\n\r\nint CreateGoldItemInInventorySlot(Player &player, int slotIndex, int value)\r\n{\r\n\tif (player.InvGrid[slotIndex] != 0) {\r\n\t\treturn value;\r\n\t}\r\n\r\n\tItem &goldItem = player.InvList[player._pNumInv];\r\n\tMakeGoldStack(goldItem, std::min(value, MaxGold));\r\n\tplayer._pNumInv++;\r\n\tplayer.InvGrid[slotIndex] = player._pNumInv;\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdChInvItem(false, slotIndex);\r\n\t}\r\n\r\n\tvalue -= goldItem._ivalue;\r\n\r\n\treturn value;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InvDrawSlotBack(const Surface &out, Point targetPosition, Size size, item_quality itemQuality)\r\n{\r\n\tSDL_Rect srcRect = MakeSdlRect(0, 0, size.width, size.height);\r\n\tout.Clip(&srcRect, &targetPosition);\r\n\tif (size.width <= 0 || size.height <= 0)\r\n\t\treturn;\r\n\r\n\tuint8_t colorShift;\r\n\tswitch (itemQuality) {\r\n\tcase ITEM_QUALITY_MAGIC:\r\n\t\tcolorShift = PAL16_GRAY - (!IsInspectingPlayer() ? PAL16_BLUE : PAL16_ORANGE) - 1;\r\n\t\tbreak;\r\n\tcase ITEM_QUALITY_UNIQUE:\r\n\t\tcolorShift = PAL16_GRAY - (!IsInspectingPlayer() ? PAL16_YELLOW : PAL16_ORANGE) - 1;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tcolorShift = PAL16_GRAY - (!IsInspectingPlayer() ? PAL16_BEIGE : PAL16_ORANGE) - 1;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tuint8_t *dst = &out[targetPosition];\r\n\tconst auto dstPitch = out.pitch();\r\n\tfor (int y = size.height; y != 0; --y, dst -= dstPitch + size.width) {\r\n\t\tfor (const uint8_t *end = dst + size.width; dst < end; ++dst) {\r\n\t\t\tuint8_t &pix = *dst;\r\n\t\t\tif (pix >= PAL16_GRAY) {\r\n\t\t\t\tpix -= colorShift;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool CanBePlacedOnBelt(const Player &player, const Item &item)\r\n{\r\n\treturn FitsInBeltSlot(item)\r\n\t    && item._itype != ItemType::Gold\r\n\t    && player.CanUseItem(item)\r\n\t    && item.isUsable();\r\n}\r\n\r\nvoid FreeInvGFX()\r\n{\r\n\tpInvCels = std::nullopt;\r\n}\r\n\r\nvoid InitInv()\r\n{\r\n\tconst PlayerData &playerClassData = GetPlayerDataForClass(MyPlayer->_pClass);\r\n\tconst char *invName = playerClassData.inv.c_str();\r\n\tif (gbIsSpawn && (playerClassData.inv == \"inv_rog\" || playerClassData.inv == \"inv_sor\")) {\r\n\t\tinvName = \"inv\";\r\n\t}\r\n\tpInvCels = LoadCel(StrCat(\"data\\\\inv\\\\\", invName).c_str(), static_cast<uint16_t>(SidePanelSize.width));\r\n}\r\n\r\nvoid DrawInv(const Surface &out)\r\n{\r\n\tClxDraw(out, GetPanelPosition(UiPanels::Inventory, { 0, 351 }), (*pInvCels)[0]);\r\n\r\n\tconst Size slotSize[] = {\r\n\t\t{ 2, 2 }, // head\r\n\t\t{ 1, 1 }, // left ring\r\n\t\t{ 1, 1 }, // right ring\r\n\t\t{ 1, 1 }, // amulet\r\n\t\t{ 2, 3 }, // left hand\r\n\t\t{ 2, 3 }, // right hand\r\n\t\t{ 2, 3 }, // chest\r\n\t};\r\n\r\n\tconst Point slotPos[] = {\r\n\t\t{ 133, 59 },  // head\r\n\t\t{ 48, 205 },  // left ring\r\n\t\t{ 249, 205 }, // right ring\r\n\t\t{ 205, 60 },  // amulet\r\n\t\t{ 17, 160 },  // left hand\r\n\t\t{ 248, 160 }, // right hand\r\n\t\t{ 133, 160 }, // chest\r\n\t};\r\n\r\n\tconst Player &myPlayer = *InspectPlayer;\r\n\r\n\tfor (int slot = INVLOC_HEAD; slot < NUM_INVLOC; slot++) {\r\n\t\tif (!myPlayer.InvBody[slot].isEmpty()) {\r\n\t\t\tint screenX = slotPos[slot].x;\r\n\t\t\tint screenY = slotPos[slot].y;\r\n\t\t\tInvDrawSlotBack(out, GetPanelPosition(UiPanels::Inventory, { screenX, screenY }), { slotSize[slot].width * InventorySlotSizeInPixels.width, slotSize[slot].height * InventorySlotSizeInPixels.height }, myPlayer.InvBody[slot]._iMagical);\r\n\r\n\t\t\tconst int cursId = myPlayer.InvBody[slot]._iCurs + CURSOR_FIRSTITEM;\r\n\r\n\t\t\tconst Size frameSize = GetInvItemSize(cursId);\r\n\r\n\t\t\t// calc item offsets for weapons/armor smaller than 2x3 slots\r\n\t\t\tif (IsAnyOf(slot, INVLOC_HAND_LEFT, INVLOC_HAND_RIGHT, INVLOC_CHEST)) {\r\n\t\t\t\tscreenX += frameSize.width == InventorySlotSizeInPixels.width ? INV_SLOT_HALF_SIZE_PX : 0;\r\n\t\t\t\tscreenY += frameSize.height == (3 * InventorySlotSizeInPixels.height) ? 0 : -INV_SLOT_HALF_SIZE_PX;\r\n\t\t\t}\r\n\r\n\t\t\tconst ClxSprite sprite = GetInvItemSprite(cursId);\r\n\t\t\tconst Point position = GetPanelPosition(UiPanels::Inventory, { screenX, screenY });\r\n\r\n\t\t\tif (pcursinvitem == slot) {\r\n\t\t\t\tClxDrawOutline(out, GetOutlineColor(myPlayer.InvBody[slot], true), position, sprite);\r\n\t\t\t}\r\n\r\n\t\t\tDrawItem(myPlayer.InvBody[slot], out, position, sprite);\r\n\r\n\t\t\tif (slot == INVLOC_HAND_LEFT) {\r\n\t\t\t\tif (myPlayer.GetItemLocation(myPlayer.InvBody[slot]) == ILOC_TWOHAND) {\r\n\t\t\t\t\tInvDrawSlotBack(out, GetPanelPosition(UiPanels::Inventory, slotPos[INVLOC_HAND_RIGHT]), { slotSize[INVLOC_HAND_RIGHT].width * InventorySlotSizeInPixels.width, slotSize[INVLOC_HAND_RIGHT].height * InventorySlotSizeInPixels.height }, myPlayer.InvBody[slot]._iMagical);\r\n\t\t\t\t\tconst int dstX = GetRightPanel().position.x + slotPos[INVLOC_HAND_RIGHT].x + (frameSize.width == InventorySlotSizeInPixels.width ? INV_SLOT_HALF_SIZE_PX : 0) - 1;\r\n\t\t\t\t\tconst int dstY = GetRightPanel().position.y + slotPos[INVLOC_HAND_RIGHT].y;\r\n\t\t\t\t\tClxDrawBlended(out, { dstX, dstY }, sprite);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < InventoryGridCells; i++) {\r\n\t\tif (myPlayer.InvGrid[i] != 0) {\r\n\t\t\tInvDrawSlotBack(\r\n\t\t\t    out,\r\n\t\t\t    GetPanelPosition(UiPanels::Inventory, InvRect[i + SLOTXY_INV_FIRST].position) + Displacement { 0, InventorySlotSizeInPixels.height },\r\n\t\t\t    InventorySlotSizeInPixels,\r\n\t\t\t    myPlayer.InvList[std::abs(myPlayer.InvGrid[i]) - 1]._iMagical);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < InventoryGridCells; j++) {\r\n\t\tif (myPlayer.InvGrid[j] > 0) { // first slot of an item\r\n\t\t\tconst int ii = myPlayer.InvGrid[j] - 1;\r\n\t\t\tconst int cursId = myPlayer.InvList[ii]._iCurs + CURSOR_FIRSTITEM;\r\n\r\n\t\t\tconst ClxSprite sprite = GetInvItemSprite(cursId);\r\n\t\t\tconst Point position = GetPanelPosition(UiPanels::Inventory, InvRect[j + SLOTXY_INV_FIRST].position) + Displacement { 0, InventorySlotSizeInPixels.height };\r\n\t\t\tif (pcursinvitem == ii + INVITEM_INV_FIRST) {\r\n\t\t\t\tClxDrawOutline(out, GetOutlineColor(myPlayer.InvList[ii], true), position, sprite);\r\n\t\t\t}\r\n\r\n\t\t\tDrawItem(myPlayer.InvList[ii], out, position, sprite);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DrawInvBelt(const Surface &out)\r\n{\r\n\tif (ChatFlag) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\r\n\tDrawPanelBox(out, { 205, 21, 232, 28 }, mainPanelPosition + Displacement { 205, 5 });\r\n\r\n\tconst Player &myPlayer = *InspectPlayer;\r\n\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tif (myPlayer.SpdList[i].isEmpty()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst Point position { InvRect[i + SLOTXY_BELT_FIRST].position.x + mainPanelPosition.x, InvRect[i + SLOTXY_BELT_FIRST].position.y + mainPanelPosition.y + InventorySlotSizeInPixels.height };\r\n\t\tInvDrawSlotBack(out, position, InventorySlotSizeInPixels, myPlayer.SpdList[i]._iMagical);\r\n\t\tconst int cursId = myPlayer.SpdList[i]._iCurs + CURSOR_FIRSTITEM;\r\n\r\n\t\tconst ClxSprite sprite = GetInvItemSprite(cursId);\r\n\r\n\t\tif (pcursinvitem == i + INVITEM_BELT_FIRST) {\r\n\t\t\tif (ControlMode == ControlTypes::KeyboardAndMouse || invflag) {\r\n\t\t\t\tClxDrawOutline(out, GetOutlineColor(myPlayer.SpdList[i], true), position, sprite);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDrawItem(myPlayer.SpdList[i], out, position, sprite);\r\n\r\n\t\tif (myPlayer.SpdList[i].isUsable()\r\n\t\t    && myPlayer.SpdList[i]._itype != ItemType::Gold) {\r\n\t\t\tauto beltKey = StrCat(\"BeltItem\", i + 1);\r\n\t\t\tstd::string_view keyName = ControlMode == ControlTypes::Gamepad\r\n\t\t\t    ? GetOptions().Padmapper.InputNameForAction(beltKey, true)\r\n\t\t\t    : GetOptions().Keymapper.KeyNameForAction(beltKey);\r\n\r\n\t\t\tif (keyName.length() > 2)\r\n\t\t\t\tkeyName = {};\r\n\r\n\t\t\tDrawString(out, keyName, { position - Displacement { 0, 12 }, InventorySlotSizeInPixels },\r\n\t\t\t    { .flags = UiFlags::ColorWhite | UiFlags::AlignRight });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid RemoveEquipment(Player &player, inv_body_loc bodyLocation, bool hiPri)\r\n{\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdDelItem(hiPri, bodyLocation);\r\n\t}\r\n\r\n\tplayer.InvBody[bodyLocation].clear();\r\n}\r\n\r\nbool AutoPlaceItemInBelt(Player &player, const Item &item, bool persistItem, bool sendNetworkMessage)\r\n{\r\n\tif (!CanBePlacedOnBelt(player, item)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (Item &beltItem : player.SpdList) {\r\n\t\tif (beltItem.isEmpty()) {\r\n\t\t\tif (persistItem) {\r\n\t\t\t\tbeltItem = item;\r\n\t\t\t\tplayer.CalcScrolls();\r\n\t\t\t\tRedrawComponent(PanelDrawComponent::Belt);\r\n\t\t\t\tif (sendNetworkMessage) {\r\n\t\t\t\t\tconst auto beltIndex = static_cast<int>(std::distance<const Item *>(&player.SpdList[0], &beltItem));\r\n\t\t\t\t\tNetSendCmdChBeltItem(false, beltIndex);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool AutoEquip(Player &player, const Item &item, bool persistItem, bool sendNetworkMessage)\r\n{\r\n\tif (!CanEquip(item)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (int bodyLocation = INVLOC_HEAD; bodyLocation < NUM_INVLOC; bodyLocation++) {\r\n\t\tif (AutoEquip(player, item, (inv_body_loc)bodyLocation, persistItem, sendNetworkMessage)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool AutoEquipEnabled(const Player &player, const Item &item)\r\n{\r\n\tif (item.isWeapon()) {\r\n\t\t// Monk can use unarmed attack as an encouraged option, thus we do not automatically equip weapons on him so as to not\r\n\t\t// annoy players who prefer that playstyle.\r\n\t\treturn player._pClass != HeroClass::Monk && *GetOptions().Gameplay.autoEquipWeapons;\r\n\t}\r\n\r\n\tif (item.isArmor()) {\r\n\t\treturn *GetOptions().Gameplay.autoEquipArmor;\r\n\t}\r\n\r\n\tif (item.isHelm()) {\r\n\t\treturn *GetOptions().Gameplay.autoEquipHelms;\r\n\t}\r\n\r\n\tif (item.isShield()) {\r\n\t\treturn *GetOptions().Gameplay.autoEquipShields;\r\n\t}\r\n\r\n\tif (item.isJewelry()) {\r\n\t\treturn *GetOptions().Gameplay.autoEquipJewelry;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanFitItemInInventory(const Player &player, const Item &item)\r\n{\r\n\treturn static_cast<bool>(FindSlotForItem(player, GetInventorySize(item)));\r\n}\r\n\r\nbool AutoPlaceItemInInventory(Player &player, const Item &item, bool sendNetworkMessage)\r\n{\r\n\tconst Size itemSize = GetInventorySize(item);\r\n\tstd::optional<int> targetSlot = FindSlotForItem(player, itemSize);\r\n\r\n\tif (targetSlot) {\r\n\t\tplayer.InvList[player._pNumInv] = item;\r\n\t\tplayer._pNumInv++;\r\n\r\n\t\tAddItemToInvGrid(player, *targetSlot, player._pNumInv, itemSize, sendNetworkMessage);\r\n\t\tplayer.CalcScrolls();\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nstd::vector<int> SortItemsBySize(Player &player)\r\n{\r\n\tstd::vector<std::pair<Size, int>> itemSizes; // Pair of item size and its index in InvList\r\n\titemSizes.reserve(player._pNumInv);          // Reserves space for the number of items in the player's inventory\r\n\r\n\tfor (int i = 0; i < player._pNumInv; i++) {\r\n\t\tconst Size size = GetInventorySize(player.InvList[i]);\r\n\t\titemSizes.emplace_back(size, i);\r\n\t}\r\n\r\n\t// Sort items by height first, then by width\r\n\tstd::sort(itemSizes.begin(), itemSizes.end(), [](const auto &a, const auto &b) {\r\n\t\tif (a.first.height == b.first.height) return a.first.width > b.first.width;\r\n\t\treturn a.first.height > b.first.height;\r\n\t});\r\n\r\n\t// Extract sorted indices\r\n\tstd::vector<int> sortedIndices;\r\n\tsortedIndices.reserve(itemSizes.size()); // Pre-allocate the necessary capacity\r\n\r\n\tfor (const auto &itemSize : itemSizes) {\r\n\t\tsortedIndices.push_back(itemSize.second);\r\n\t}\r\n\r\n\treturn sortedIndices;\r\n}\r\n\r\nvoid ReorganizeInventory(Player &player)\r\n{\r\n\t// Sort items by size\r\n\tconst std::vector<int> sortedIndices = SortItemsBySize(player);\r\n\r\n\t// Temporary storage for items and a copy of InvGrid\r\n\tstd::vector<Item> tempStorage(player._pNumInv);\r\n\tstd::array<int8_t, 40> originalInvGrid;                                                       // Declare an array for InvGrid copy\r\n\tstd::copy(std::begin(player.InvGrid), std::end(player.InvGrid), std::begin(originalInvGrid)); // Copy InvGrid to originalInvGrid\r\n\r\n\t// Move items to temporary storage and clear inventory slots\r\n\tfor (int i = 0; i < player._pNumInv; ++i) {\r\n\t\ttempStorage[i] = player.InvList[i];\r\n\t\tplayer.InvList[i] = {};\r\n\t}\r\n\tplayer._pNumInv = 0;                                                // Reset inventory count\r\n\tstd::fill(std::begin(player.InvGrid), std::end(player.InvGrid), 0); // Clear InvGrid\r\n\r\n\t// Attempt to place items back, now from the temp storage\r\n\tbool reorganizationFailed = false;\r\n\tfor (const int index : sortedIndices) {\r\n\t\tconst Item &item = tempStorage[index];\r\n\t\tif (!AutoPlaceItemInInventory(player, item, false)) {\r\n\t\t\treorganizationFailed = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t// If reorganization failed, restore items and InvGrid from tempStorage and originalInvGrid\r\n\tif (reorganizationFailed) {\r\n\t\tfor (const Item &item : tempStorage) {\r\n\t\t\tif (!item.isEmpty()) {\r\n\t\t\t\tplayer.InvList[player._pNumInv++] = item;\r\n\t\t\t}\r\n\t\t}\r\n\t\tstd::copy(std::begin(originalInvGrid), std::end(originalInvGrid), std::begin(player.InvGrid)); // Restore InvGrid\r\n\t}\r\n}\r\n\r\nint RoomForGold()\r\n{\r\n\tint amount = 0;\r\n\tfor (const int8_t &itemIndex : MyPlayer->InvGrid) {\r\n\t\tif (itemIndex < 0) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (itemIndex == 0) {\r\n\t\t\tamount += MaxGold;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst Item &goldItem = MyPlayer->InvList[itemIndex - 1];\r\n\t\tif (goldItem._itype != ItemType::Gold || goldItem._ivalue == MaxGold) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tamount += MaxGold - goldItem._ivalue;\r\n\t}\r\n\r\n\treturn amount;\r\n}\r\n\r\nint AddGoldToInventory(Player &player, int value)\r\n{\r\n\t// Top off existing piles\r\n\tfor (int i = 0; i < player._pNumInv && value > 0; i++) {\r\n\t\tItem &goldItem = player.InvList[i];\r\n\t\tif (goldItem._itype != ItemType::Gold || goldItem._ivalue >= MaxGold) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (goldItem._ivalue + value > MaxGold) {\r\n\t\t\tvalue -= MaxGold - goldItem._ivalue;\r\n\t\t\tgoldItem._ivalue = MaxGold;\r\n\t\t} else {\r\n\t\t\tgoldItem._ivalue += value;\r\n\t\t\tvalue = 0;\r\n\t\t}\r\n\r\n\t\tNetSyncInvItem(player, i);\r\n\t\tSetPlrHandGoldCurs(goldItem);\r\n\t}\r\n\r\n\t// Last row right to left\r\n\tfor (int i = 39; i >= 30 && value > 0; i--) {\r\n\t\tvalue = CreateGoldItemInInventorySlot(player, i, value);\r\n\t}\r\n\r\n\t// Remaining inventory in columns, bottom to top, right to left\r\n\tfor (int x = 9; x >= 0 && value > 0; x--) {\r\n\t\tfor (int y = 2; y >= 0 && value > 0; y--) {\r\n\t\t\tvalue = CreateGoldItemInInventorySlot(player, 10 * y + x, value);\r\n\t\t}\r\n\t}\r\n\r\n\treturn value;\r\n}\r\n\r\nbool GoldAutoPlace(Player &player, Item &goldStack)\r\n{\r\n\tgoldStack._ivalue = AddGoldToInventory(player, goldStack._ivalue);\r\n\tSetPlrHandGoldCurs(goldStack);\r\n\r\n\tplayer._pGold = CalculateGold(player);\r\n\r\n\treturn goldStack._ivalue == 0;\r\n}\r\n\r\nvoid CheckInvSwap(Player &player, inv_body_loc bLoc)\r\n{\r\n\tconst Item &item = player.InvBody[bLoc];\r\n\r\n\tif (bLoc == INVLOC_HAND_LEFT && player.GetItemLocation(item) == ILOC_TWOHAND) {\r\n\t\tplayer.InvBody[INVLOC_HAND_RIGHT].clear();\r\n\t} else if (bLoc == INVLOC_HAND_RIGHT && player.GetItemLocation(item) == ILOC_TWOHAND) {\r\n\t\tplayer.InvBody[INVLOC_HAND_LEFT].clear();\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid inv_update_rem_item(Player &player, inv_body_loc iv)\r\n{\r\n\tplayer.InvBody[iv].clear();\r\n\r\n\tCalcPlrInv(player, player._pmode != PM_DEATH);\r\n}\r\n\r\nvoid CheckInvSwap(Player &player, const Item &item, int invGridIndex)\r\n{\r\n\tSize itemSize = GetInventorySize(item);\r\n\r\n\tconst int pitch = 10;\r\n\tconst int invListIndex = [&]() -> int {\r\n\t\tfor (int y = 0; y < itemSize.height; y++) {\r\n\t\t\tconst int rowGridIndex = invGridIndex + pitch * y;\r\n\t\t\tfor (int x = 0; x < itemSize.width; x++) {\r\n\t\t\t\tconst int gridIndex = rowGridIndex + x;\r\n\t\t\t\tif (player.InvGrid[gridIndex] != 0)\r\n\t\t\t\t\treturn std::abs(player.InvGrid[gridIndex]);\r\n\t\t\t}\r\n\t\t}\r\n\t\tplayer._pNumInv++;\r\n\t\treturn player._pNumInv;\r\n\t}();\r\n\r\n\tif (invListIndex < player._pNumInv) {\r\n\t\tfor (int8_t &itemIndex : player.InvGrid) {\r\n\t\t\tif (itemIndex == invListIndex)\r\n\t\t\t\titemIndex = 0;\r\n\t\t\tif (itemIndex == -invListIndex)\r\n\t\t\t\titemIndex = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tplayer.InvList[invListIndex - 1] = item;\r\n\r\n\tfor (int y = 0; y < itemSize.height; y++) {\r\n\t\tconst int rowGridIndex = invGridIndex + pitch * y;\r\n\t\tfor (int x = 0; x < itemSize.width; x++) {\r\n\t\t\tif (x == 0 && y == itemSize.height - 1)\r\n\t\t\t\tplayer.InvGrid[rowGridIndex + x] = invListIndex;\r\n\t\t\telse\r\n\t\t\t\tplayer.InvGrid[rowGridIndex + x] = -invListIndex;\r\n\t\t}\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid CheckInvRemove(Player &player, int invGridIndex)\r\n{\r\n\tconst int invListIndex = std::abs(player.InvGrid[invGridIndex]) - 1;\r\n\r\n\tif (invListIndex >= 0) {\r\n\t\tplayer.RemoveInvItem(invListIndex);\r\n\t}\r\n}\r\n\r\nvoid TransferItemToStash(Player &player, int location)\r\n{\r\n\tif (location == -1) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Item &item = GetInventoryItem(player, location);\r\n\tif (!AutoPlaceItemInStash(player, item, true)) {\r\n\t\tplayer.SaySpecific(HeroSpeech::WhereWouldIPutThis);\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySFX(ItemInvSnds[ItemCAnimTbl[item._iCurs]]);\r\n\r\n\tif (location < INVITEM_INV_FIRST) {\r\n\t\tRemoveEquipment(player, static_cast<inv_body_loc>(location), false);\r\n\t\tCalcPlrInv(player, true);\r\n\t} else if (location <= INVITEM_INV_LAST)\r\n\t\tplayer.RemoveInvItem(location - INVITEM_INV_FIRST);\r\n\telse\r\n\t\tplayer.RemoveSpdBarItem(location - INVITEM_BELT_FIRST);\r\n}\r\n\r\nvoid CheckInvItem(bool isShiftHeld, bool isCtrlHeld)\r\n{\r\n\tif (IsInspectingPlayer())\r\n\t\treturn;\r\n\tif (!MyPlayer->HoldItem.isEmpty()) {\r\n\t\tCheckInvPaste(*MyPlayer, MousePosition);\r\n\t} else if (IsStashOpen && isCtrlHeld) {\r\n\t\tTransferItemToStash(*MyPlayer, pcursinvitem);\r\n\t} else {\r\n\t\tCheckInvCut(*MyPlayer, MousePosition, isShiftHeld, isCtrlHeld);\r\n\t}\r\n}\r\n\r\nvoid CheckInvScrn(bool isShiftHeld, bool isCtrlHeld)\r\n{\r\n\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\tif (MousePosition.x > 190 + mainPanelPosition.x && MousePosition.x < 437 + mainPanelPosition.x\r\n\t    && MousePosition.y > mainPanelPosition.y && MousePosition.y < 33 + mainPanelPosition.y) {\r\n\t\tCheckInvItem(isShiftHeld, isCtrlHeld);\r\n\t}\r\n}\r\n\r\nvoid InvGetItem(Player &player, int ii)\r\n{\r\n\tItem &item = Items[ii];\r\n\tCloseGoldDrop();\r\n\r\n\tif (dItem[item.position.x][item.position.y] == 0)\r\n\t\treturn;\r\n\r\n\titem._iCreateInfo &= ~CF_PREGEN;\r\n\tCheckQuestItem(player, item);\r\n\titem.updateRequiredStatsCacheForPlayer(player);\r\n\r\n\tif (item._itype == ItemType::Gold && GoldAutoPlace(player, item)) {\r\n\t\tif (MyPlayer == &player) {\r\n\t\t\t// Non-gold items (or gold when you have a full inventory) go to the hand then provide audible feedback on\r\n\t\t\t//  paste. To give the same feedback for auto-placed gold we play the sound effect now.\r\n\t\t\tPlaySFX(SfxID::ItemGold);\r\n\t\t}\r\n\t} else {\r\n\t\t// The item needs to go into the players hand\r\n\t\tif (MyPlayer == &player && !player.HoldItem.isEmpty()) {\r\n\t\t\t// drop whatever the player is currently holding\r\n\t\t\tNetSendCmdPItem(true, CMD_SYNCPUTITEM, player.position.tile, player.HoldItem);\r\n\t\t}\r\n\r\n\t\t// need to copy here instead of move so CleanupItems still has access to the position\r\n\t\tplayer.HoldItem = item;\r\n\t\tNewCursor(player.HoldItem);\r\n\t}\r\n\r\n\t// This potentially moves items in memory so must be done after we've made a copy\r\n\tCleanupItems(ii);\r\n\tpcursitem = -1;\r\n}\r\n\r\nstd::optional<Point> FindAdjacentPositionForItem(Point origin, Direction facing)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn {};\r\n\r\n\tif (CanPut(origin + facing))\r\n\t\treturn origin + facing;\r\n\r\n\tif (CanPut(origin + Left(facing)))\r\n\t\treturn origin + Left(facing);\r\n\r\n\tif (CanPut(origin + Right(facing)))\r\n\t\treturn origin + Right(facing);\r\n\r\n\tif (CanPut(origin + Left(Left(facing))))\r\n\t\treturn origin + Left(Left(facing));\r\n\r\n\tif (CanPut(origin + Right(Right(facing))))\r\n\t\treturn origin + Right(Right(facing));\r\n\r\n\tif (CanPut(origin + Left(Left(Left(facing)))))\r\n\t\treturn origin + Left(Left(Left(facing)));\r\n\r\n\tif (CanPut(origin + Right(Right(Right(facing)))))\r\n\t\treturn origin + Right(Right(Right(facing)));\r\n\r\n\tif (CanPut(origin + Opposite(facing)))\r\n\t\treturn origin + Opposite(facing);\r\n\r\n\tif (CanPut(origin))\r\n\t\treturn origin;\r\n\r\n\treturn {};\r\n}\r\n\r\nvoid AutoGetItem(Player &player, Item *itemPointer, int ii)\r\n{\r\n\tItem &item = *itemPointer;\r\n\r\n\tCloseGoldDrop();\r\n\r\n\tif (dItem[item.position.x][item.position.y] == 0)\r\n\t\treturn;\r\n\r\n\titem._iCreateInfo &= ~CF_PREGEN;\r\n\tCheckQuestItem(player, item);\r\n\titem.updateRequiredStatsCacheForPlayer(player);\r\n\r\n\tbool done;\r\n\tbool autoEquipped = false;\r\n\r\n\tif (item._itype == ItemType::Gold) {\r\n\t\tdone = GoldAutoPlace(player, item);\r\n\t\tif (!done) {\r\n\t\t\tSetPlrHandGoldCurs(item);\r\n\t\t}\r\n\t} else {\r\n\t\tdone = AutoEquipEnabled(player, item) && AutoEquip(player, item, true, &player == MyPlayer);\r\n\t\tif (done) {\r\n\t\t\tautoEquipped = true;\r\n\t\t}\r\n\r\n\t\tif (!done) {\r\n\t\t\tdone = AutoPlaceItemInBelt(player, item, true, &player == MyPlayer);\r\n\t\t}\r\n\t\tif (!done) {\r\n\t\t\tdone = AutoPlaceItemInInventory(player, item, &player == MyPlayer);\r\n\t\t}\r\n\t}\r\n\r\n\tif (done) {\r\n\t\tif (!autoEquipped && *GetOptions().Audio.itemPickupSound && &player == MyPlayer) {\r\n\t\t\tPlaySFX(SfxID::GrabItem);\r\n\t\t}\r\n\r\n\t\tCleanupItems(ii);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tplayer.Say(HeroSpeech::ICantCarryAnymore);\r\n\t}\r\n\tRespawnItem(item, true);\r\n\tNetSendCmdPItem(true, CMD_SPAWNITEM, item.position, item);\r\n}\r\n\r\nint FindGetItem(uint32_t iseed, _item_indexes idx, uint16_t createInfo)\r\n{\r\n\tfor (uint8_t i = 0; i < ActiveItemCount; i++) {\r\n\t\tconst Item &item = Items[ActiveItems[i]];\r\n\t\tif (item.keyAttributesMatch(iseed, idx, createInfo)) {\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\r\n\treturn -1;\r\n}\r\n\r\nvoid SyncGetItem(Point position, uint32_t iseed, _item_indexes idx, uint16_t ci)\r\n{\r\n\t// Check what the local client has at the target position\r\n\tint ii = dItem[position.x][position.y] - 1;\r\n\r\n\tif (ii >= 0 && ii < MAXITEMS) {\r\n\t\t// If there was an item there, check that it's the same item as the remote player has\r\n\t\tif (!Items[ii].keyAttributesMatch(iseed, idx, ci)) {\r\n\t\t\t// Key attributes don't match so we must've desynced, ignore this index and try find a matching item via lookup\r\n\t\t\tii = -1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (ii == -1) {\r\n\t\t// Either there's no item at the expected position or it doesn't match what is being picked up, so look for an item that matches the key attributes\r\n\t\tii = FindGetItem(iseed, idx, ci);\r\n\r\n\t\tif (ii != -1) {\r\n\t\t\t// Translate to Items index for CleanupItems, FindGetItem returns an ActiveItems index\r\n\t\t\tii = ActiveItems[ii];\r\n\t\t}\r\n\t}\r\n\r\n\tif (ii == -1) {\r\n\t\t// Still can't find the expected item, assume it was collected earlier and this caused the desync\r\n\t\treturn;\r\n\t}\r\n\r\n\tCleanupItems(ii);\r\n}\r\n\r\nbool CanPut(Point position)\r\n{\r\n\tif (!InDungeonBounds(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (IsTileSolid(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (dItem[position.x][position.y] != 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tif (dMonster[position.x][position.y] != 0) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (dMonster[position.x + 1][position.y + 1] != 0) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsItemBlockingObjectAtPosition(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nint ClampDurability(const Item &item, int durability)\r\n{\r\n\tif (item._iMaxDur == 0)\r\n\t\treturn 0;\r\n\r\n\treturn std::clamp<int>(durability, 1, item._iMaxDur);\r\n}\r\n\r\nint16_t ClampToHit(const Item &item, int16_t toHit)\r\n{\r\n\tif (toHit < item._iPLToHit || toHit > 51)\r\n\t\treturn item._iPLToHit;\r\n\r\n\treturn toHit;\r\n}\r\n\r\nuint8_t ClampMaxDam(const Item &item, uint8_t maxDam)\r\n{\r\n\tif (maxDam < item._iMaxDam || maxDam - item._iMinDam > 30)\r\n\t\treturn item._iMaxDam;\r\n\r\n\treturn maxDam;\r\n}\r\n\r\nint SyncDropItem(Point position, _item_indexes idx, uint16_t icreateinfo, int iseed, int id, int dur, int mdur, int ch, int mch, int ivalue, uint32_t ibuff, int toHit, int maxDam)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn -1;\r\n\r\n\tItem item;\r\n\r\n\tRecreateItem(*MyPlayer, item, idx, icreateinfo, iseed, ivalue, ibuff);\r\n\tif (id != 0)\r\n\t\titem._iIdentified = true;\r\n\titem._iMaxDur = mdur;\r\n\titem._iDurability = ClampDurability(item, dur);\r\n\titem._iMaxCharges = std::clamp<int>(mch, 0, item._iMaxCharges);\r\n\titem._iCharges = std::clamp<int>(ch, 0, item._iMaxCharges);\r\n\tif (gbIsHellfire) {\r\n\t\titem._iPLToHit = ClampToHit(item, toHit);\r\n\t\titem._iMaxDam = ClampMaxDam(item, maxDam);\r\n\t}\r\n\r\n\treturn PlaceItemInWorld(std::move(item), position);\r\n}\r\n\r\nint SyncDropEar(Point position, uint16_t icreateinfo, uint32_t iseed, uint8_t cursval, std::string_view heroname)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn -1;\r\n\r\n\tItem item;\r\n\tRecreateEar(item, icreateinfo, iseed, cursval, heroname);\r\n\r\n\treturn PlaceItemInWorld(std::move(item), position);\r\n}\r\n\r\nint8_t CheckInvHLight()\r\n{\r\n\tint8_t r = 0;\r\n\tfor (; r < NUM_XY_SLOTS; r++) {\r\n\t\tint xo = GetRightPanel().position.x;\r\n\t\tint yo = GetRightPanel().position.y;\r\n\t\tif (r >= SLOTXY_BELT_FIRST) {\r\n\t\t\txo = GetMainPanel().position.x;\r\n\t\t\tyo = GetMainPanel().position.y;\r\n\t\t}\r\n\r\n\t\tif (InvRect[r].contains(MousePosition - Displacement(xo, yo))) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (r >= NUM_XY_SLOTS)\r\n\t\treturn -1;\r\n\r\n\tint8_t rv = -1;\r\n\tInfoColor = UiFlags::ColorWhite;\r\n\tItem *pi = nullptr;\r\n\tPlayer &myPlayer = *InspectPlayer;\r\n\r\n\tif (r == SLOTXY_HEAD) {\r\n\t\trv = INVLOC_HEAD;\r\n\t\tpi = &myPlayer.InvBody[rv];\r\n\t} else if (r == SLOTXY_RING_LEFT) {\r\n\t\trv = INVLOC_RING_LEFT;\r\n\t\tpi = &myPlayer.InvBody[rv];\r\n\t} else if (r == SLOTXY_RING_RIGHT) {\r\n\t\trv = INVLOC_RING_RIGHT;\r\n\t\tpi = &myPlayer.InvBody[rv];\r\n\t} else if (r == SLOTXY_AMULET) {\r\n\t\trv = INVLOC_AMULET;\r\n\t\tpi = &myPlayer.InvBody[rv];\r\n\t} else if (r == SLOTXY_HAND_LEFT) {\r\n\t\trv = INVLOC_HAND_LEFT;\r\n\t\tpi = &myPlayer.InvBody[rv];\r\n\t} else if (r == SLOTXY_HAND_RIGHT) {\r\n\t\tpi = &myPlayer.InvBody[INVLOC_HAND_LEFT];\r\n\t\tif (pi->isEmpty() || myPlayer.GetItemLocation(*pi) != ILOC_TWOHAND) {\r\n\t\t\trv = INVLOC_HAND_RIGHT;\r\n\t\t\tpi = &myPlayer.InvBody[rv];\r\n\t\t} else {\r\n\t\t\trv = INVLOC_HAND_LEFT;\r\n\t\t}\r\n\t} else if (r == SLOTXY_CHEST) {\r\n\t\trv = INVLOC_CHEST;\r\n\t\tpi = &myPlayer.InvBody[rv];\r\n\t} else if (r >= SLOTXY_INV_FIRST && r <= SLOTXY_INV_LAST) {\r\n\t\tconst int8_t itemId = std::abs(myPlayer.InvGrid[r - SLOTXY_INV_FIRST]);\r\n\t\tif (itemId == 0)\r\n\t\t\treturn -1;\r\n\t\tconst int ii = itemId - 1;\r\n\t\trv = ii + INVITEM_INV_FIRST;\r\n\t\tpi = &myPlayer.InvList[ii];\r\n\t} else if (r >= SLOTXY_BELT_FIRST) {\r\n\t\tr -= SLOTXY_BELT_FIRST;\r\n\t\tRedrawComponent(PanelDrawComponent::Belt);\r\n\t\tpi = &myPlayer.SpdList[r];\r\n\t\tif (pi->isEmpty())\r\n\t\t\treturn -1;\r\n\t\trv = r + INVITEM_BELT_FIRST;\r\n\t}\r\n\r\n\tif (pi->isEmpty())\r\n\t\treturn -1;\r\n\r\n\tif (pi->_itype == ItemType::Gold) {\r\n\t\tconst int nGold = pi->_ivalue;\r\n\t\tInfoString = fmt::format(fmt::runtime(ngettext(\"{:s} gold piece\", \"{:s} gold pieces\", nGold)), FormatInteger(nGold));\r\n\t\tFloatingInfoString = fmt::format(fmt::runtime(ngettext(\"{:s} gold piece\", \"{:s} gold pieces\", nGold)), FormatInteger(nGold));\r\n\t} else {\r\n\t\tInfoColor = pi->getTextColor();\r\n\t\tInfoString = pi->getName();\r\n\t\tFloatingInfoString = pi->getName();\r\n\t\tif (pi->_iIdentified) {\r\n\t\t\tPrintItemDetails(*pi);\r\n\t\t} else {\r\n\t\t\tPrintItemDur(*pi);\r\n\t\t}\r\n\t}\r\n\r\n\treturn rv;\r\n}\r\n\r\nvoid ConsumeScroll(Player &player)\r\n{\r\n\tconst SpellID spellId = player.executedSpell.spellId;\r\n\r\n\tconst auto isCurrentSpell = [spellId](const Item &item) -> bool {\r\n\t\treturn item.isScrollOf(spellId) || item.isRuneOf(spellId);\r\n\t};\r\n\r\n\t// Try to remove the scroll from selected inventory slot\r\n\tconst int8_t itemSlot = player.executedSpell.spellFrom;\r\n\tif (itemSlot >= INVITEM_INV_FIRST && itemSlot <= INVITEM_INV_LAST) {\r\n\t\tconst int itemIndex = itemSlot - INVITEM_INV_FIRST;\r\n\t\tconst Item *item = &player.InvList[itemIndex];\r\n\t\tif (!item->isEmpty() && isCurrentSpell(*item)) {\r\n\t\t\tplayer.RemoveInvItem(itemIndex);\r\n\t\t\treturn;\r\n\t\t}\r\n\t} else if (itemSlot >= INVITEM_BELT_FIRST && itemSlot <= INVITEM_BELT_LAST) {\r\n\t\tconst int itemIndex = itemSlot - INVITEM_BELT_FIRST;\r\n\t\tconst Item *item = &player.SpdList[itemIndex];\r\n\t\tif (!item->isEmpty() && isCurrentSpell(*item)) {\r\n\t\t\tplayer.RemoveSpdBarItem(itemIndex);\r\n\t\t\treturn;\r\n\t\t}\r\n\t} else if (itemSlot != 0) {\r\n\t\tapp_fatal(StrCat(\"ConsumeScroll: Invalid item index \", itemSlot));\r\n\t}\r\n\r\n\t// Didn't find it at the selected slot, take the first one we find\r\n\t// This path is always used when the scroll is consumed via spell selection\r\n\tRemoveInventoryOrBeltItem(player, isCurrentSpell);\r\n}\r\n\r\nbool CanUseScroll(Player &player, SpellID spell)\r\n{\r\n\tif (leveltype == DTYPE_TOWN && !GetSpellData(spell).isAllowedInTown())\r\n\t\treturn false;\r\n\r\n\treturn HasInventoryOrBeltItem(player, [spell](const Item &item) {\r\n\t\treturn item.isScrollOf(spell) || item.isRuneOf(spell);\r\n\t});\r\n}\r\n\r\nvoid ConsumeStaffCharge(Player &player)\r\n{\r\n\tItem &staff = player.InvBody[INVLOC_HAND_LEFT];\r\n\r\n\tif (!CanUseStaff(staff, player.executedSpell.spellId))\r\n\t\treturn;\r\n\r\n\tstaff._iCharges--;\r\n\tCalcPlrInv(player, false);\r\n}\r\n\r\nbool CanUseStaff(Player &player, SpellID spellId)\r\n{\r\n\treturn CanUseStaff(player.InvBody[INVLOC_HAND_LEFT], spellId);\r\n}\r\n\r\nItem &GetInventoryItem(Player &player, int location)\r\n{\r\n\tif (location < INVITEM_INV_FIRST)\r\n\t\treturn player.InvBody[location];\r\n\r\n\tif (location <= INVITEM_INV_LAST)\r\n\t\treturn player.InvList[location - INVITEM_INV_FIRST];\r\n\r\n\treturn player.SpdList[location - INVITEM_BELT_FIRST];\r\n}\r\n\r\nbool UseInvItem(int cii)\r\n{\r\n\tif (IsInspectingPlayer())\r\n\t\treturn false;\r\n\r\n\tPlayer &player = *MyPlayer;\r\n\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer)\r\n\t\treturn true;\r\n\tif (pcurs != CURSOR_HAND)\r\n\t\treturn true;\r\n\tif (IsPlayerInStore())\r\n\t\treturn true;\r\n\tif (cii < INVITEM_INV_FIRST)\r\n\t\treturn false;\r\n\r\n\tbool speedlist = false;\r\n\tint c;\r\n\tItem *item;\r\n\tif (cii <= INVITEM_INV_LAST) {\r\n\t\tc = cii - INVITEM_INV_FIRST;\r\n\t\titem = &player.InvList[c];\r\n\t} else {\r\n\t\tif (ChatFlag)\r\n\t\t\treturn true;\r\n\t\tc = cii - INVITEM_BELT_FIRST;\r\n\r\n\t\titem = &player.SpdList[c];\r\n\t\tspeedlist = true;\r\n\r\n\t\t// If selected speedlist item exists in InvList, use the InvList item.\r\n\t\tfor (int i = 0; i < player._pNumInv && *GetOptions().Gameplay.autoRefillBelt; i++) {\r\n\t\t\tif (player.InvList[i]._iMiscId == item->_iMiscId && player.InvList[i]._iSpell == item->_iSpell) {\r\n\t\t\t\tc = i;\r\n\t\t\t\titem = &player.InvList[c];\r\n\t\t\t\tcii = c + INVITEM_INV_FIRST;\r\n\t\t\t\tspeedlist = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If speedlist item is not inventory, use same item at the end of the speedlist if exists.\r\n\t\tif (speedlist && *GetOptions().Gameplay.autoRefillBelt) {\r\n\t\t\tfor (int i = INVITEM_BELT_LAST - INVITEM_BELT_FIRST; i > c; i--) {\r\n\t\t\t\tItem &candidate = player.SpdList[i];\r\n\r\n\t\t\t\tif (!candidate.isEmpty() && candidate._iMiscId == item->_iMiscId && candidate._iSpell == item->_iSpell) {\r\n\t\t\t\t\tc = i;\r\n\t\t\t\t\tcii = c + INVITEM_BELT_FIRST;\r\n\t\t\t\t\titem = &candidate;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconstexpr int SpeechDelay = 10;\r\n\tif (item->IDidx == IDI_MUSHROOM) {\r\n\t\tplayer.Say(HeroSpeech::NowThatsOneBigMushroom, SpeechDelay);\r\n\t\treturn true;\r\n\t}\r\n\tif (item->IDidx == IDI_FUNGALTM) {\r\n\r\n\t\tPlaySFX(SfxID::ItemBook);\r\n\t\tplayer.Say(HeroSpeech::ThatDidntDoAnything, SpeechDelay);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (player.isOnLevel(0)) {\r\n\t\tif (UseItemOpensHive(*item, player.position.tile)) {\r\n\t\t\tOpenHive();\r\n\t\t\tplayer.RemoveInvItem(c);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (UseItemOpensGrave(*item, player.position.tile)) {\r\n\t\t\tOpenGrave();\r\n\t\t\tplayer.RemoveInvItem(c);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!item->isUsable())\r\n\t\treturn false;\r\n\r\n\tif (!player.CanUseItem(*item)) {\r\n\t\tplayer.Say(HeroSpeech::ICantUseThisYet);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (item->_iMiscId == IMISC_NONE && item->_itype == ItemType::Gold) {\r\n\t\tStartGoldDrop();\r\n\t\treturn true;\r\n\t}\r\n\r\n\tCloseGoldDrop();\r\n\r\n\tif (item->isScroll() && leveltype == DTYPE_TOWN && !GetSpellData(item->_iSpell).isAllowedInTown()) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (item->_iMiscId > IMISC_RUNEFIRST && item->_iMiscId < IMISC_RUNELAST && leveltype == DTYPE_TOWN) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (item->_iMiscId == IMISC_ARENAPOT && !player.isOnArenaLevel()) {\r\n\t\tplayer.Say(HeroSpeech::ThatWontWorkHere);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconst int idata = ItemCAnimTbl[item->_iCurs];\r\n\tif (item->_iMiscId == IMISC_BOOK)\r\n\t\tPlaySFX(SfxID::ReadBook);\r\n\telse if (&player == MyPlayer)\r\n\t\tPlaySFX(ItemInvSnds[idata]);\r\n\r\n\tUseItem(player, item->_iMiscId, item->_iSpell, cii);\r\n\r\n\tif (speedlist) {\r\n\t\tif (player.SpdList[c]._iMiscId == IMISC_NOTE) {\r\n\t\t\tInitQTextMsg(TEXT_BOOK9);\r\n\t\t\tCloseInventory();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (!item->isScroll() && !item->isRune())\r\n\t\t\tplayer.RemoveSpdBarItem(c);\r\n\t\treturn true;\r\n\t}\r\n\tif (player.InvList[c]._iMiscId == IMISC_MAPOFDOOM)\r\n\t\treturn true;\r\n\tif (player.InvList[c]._iMiscId == IMISC_NOTE) {\r\n\t\tInitQTextMsg(TEXT_BOOK9);\r\n\t\tCloseInventory();\r\n\t\treturn true;\r\n\t}\r\n\tif (!item->isScroll() && !item->isRune())\r\n\t\tplayer.RemoveInvItem(c);\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid CloseInventory()\r\n{\r\n\tCloseGoldWithdraw();\r\n\tCloseStash();\r\n\tinvflag = false;\r\n}\r\n\r\nvoid CloseStash()\r\n{\r\n\tif (!IsStashOpen)\r\n\t\treturn;\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (!myPlayer.HoldItem.isEmpty()) {\r\n\t\tstd::optional<Point> itemTile = FindAdjacentPositionForItem(myPlayer.position.future, myPlayer._pdir);\r\n\t\tif (itemTile) {\r\n\t\t\tNetSendCmdPItem(true, CMD_PUTITEM, *itemTile, myPlayer.HoldItem);\r\n\t\t} else {\r\n\t\t\tif (!AutoPlaceItemInBelt(myPlayer, myPlayer.HoldItem, true, true)\r\n\t\t\t    && !AutoPlaceItemInInventory(myPlayer, myPlayer.HoldItem, true)\r\n\t\t\t    && !AutoPlaceItemInStash(myPlayer, myPlayer.HoldItem, true)) {\r\n\t\t\t\t// This can fail for max gold, arena potions and a stash that has been arranged\r\n\t\t\t\t// to not have room for the item all 3 cases are extremely unlikely\r\n\t\t\t\tapp_fatal(_(\"No room for item\"));\r\n\t\t\t}\r\n\t\t\tPlaySFX(ItemInvSnds[ItemCAnimTbl[myPlayer.HoldItem._iCurs]]);\r\n\t\t}\r\n\t\tmyPlayer.HoldItem.clear();\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t}\r\n\r\n\tIsStashOpen = false;\r\n}\r\n\r\nvoid DoTelekinesis()\r\n{\r\n\tif (ObjectUnderCursor != nullptr && !ObjectUnderCursor->IsDisabled())\r\n\t\tNetSendCmdLoc(MyPlayerId, true, CMD_OPOBJT, cursPosition);\r\n\tif (pcursitem != -1)\r\n\t\tNetSendCmdGItem(true, CMD_REQUESTAGITEM, *MyPlayer, pcursitem);\r\n\tif (pcursmonst != -1) {\r\n\t\tconst Monster &monter = Monsters[pcursmonst];\r\n\t\tif (!M_Talker(monter) && monter.talkMsg == TEXT_NONE)\r\n\t\t\tNetSendCmdParam1(true, CMD_KNOCKBACK, pcursmonst);\r\n\t}\r\n\tNewCursor(CURSOR_HAND);\r\n}\r\n\r\nint CalculateGold(Player &player)\r\n{\r\n\tint gold = 0;\r\n\r\n\tfor (int i = 0; i < player._pNumInv; i++) {\r\n\t\tif (player.InvList[i]._itype == ItemType::Gold)\r\n\t\t\tgold += player.InvList[i]._ivalue;\r\n\t}\r\n\r\n\treturn gold;\r\n}\r\n\r\nSize GetInventorySize(const Item &item)\r\n{\r\n\tconst Size size = GetInvItemSize(item._iCurs + CURSOR_FIRSTITEM);\r\n\r\n\treturn { size.width / InventorySlotSizeInPixels.width, size.height / InventorySlotSizeInPixels.height };\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/inv.h",
    "content": "/**\r\n * @file inv.h\r\n *\r\n * Interface of player inventory.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/palette.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"inv_iterators.hpp\"\r\n#include \"items.h\"\r\n#include \"player.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#define INV_SLOT_SIZE_PX 28\r\n#define INV_SLOT_HALF_SIZE_PX (INV_SLOT_SIZE_PX / 2)\r\nconstexpr Size InventorySizeInSlots { 10, 4 };\r\n#define INV_ROW_SLOT_SIZE InventorySizeInSlots.width\r\nconstexpr Size InventorySlotSizeInPixels { INV_SLOT_SIZE_PX };\r\n\r\nenum inv_item : int8_t {\r\n\t// clang-format off\r\n\tINVITEM_HEAD       = 0,\r\n\tINVITEM_RING_LEFT  = 1,\r\n\tINVITEM_RING_RIGHT = 2,\r\n\tINVITEM_AMULET     = 3,\r\n\tINVITEM_HAND_LEFT  = 4,\r\n\tINVITEM_HAND_RIGHT = 5,\r\n\tINVITEM_CHEST      = 6,\r\n\tINVITEM_INV_FIRST  = 7,\r\n\tINVITEM_INV_LAST   = 46,\r\n\tINVITEM_BELT_FIRST = 47,\r\n\tINVITEM_BELT_LAST  = 54,\r\n\t// clang-format on\r\n};\r\n\r\n/**\r\n * identifiers for each of the inventory squares\r\n * @see InvRect\r\n */\r\nenum inv_xy_slot : uint8_t {\r\n\t// clang-format off\r\n\tSLOTXY_HEAD           = 0,\r\n\tSLOTXY_EQUIPPED_FIRST = SLOTXY_HEAD,\r\n\tSLOTXY_RING_LEFT      = 1,\r\n\tSLOTXY_RING_RIGHT     = 2,\r\n\tSLOTXY_AMULET         = 3,\r\n\tSLOTXY_HAND_LEFT      = 4,\r\n\tSLOTXY_HAND_RIGHT     = 5,\r\n\tSLOTXY_CHEST          = 6,\r\n\tSLOTXY_EQUIPPED_LAST  = SLOTXY_CHEST,\r\n\r\n\t// regular inventory\r\n\tSLOTXY_INV_FIRST      = 7,\r\n\tSLOTXY_INV_ROW1_FIRST = SLOTXY_INV_FIRST,\r\n\tSLOTXY_INV_ROW1_LAST  = 16,\r\n\tSLOTXY_INV_ROW2_FIRST = 17,\r\n\tSLOTXY_INV_ROW2_LAST  = 26,\r\n\tSLOTXY_INV_ROW3_FIRST = 27,\r\n\tSLOTXY_INV_ROW3_LAST  = 36,\r\n\tSLOTXY_INV_ROW4_FIRST = 37,\r\n\tSLOTXY_INV_ROW4_LAST  = 46,\r\n\tSLOTXY_INV_LAST       = SLOTXY_INV_ROW4_LAST,\r\n\r\n\t// belt items\r\n\tSLOTXY_BELT_FIRST     = 47,\r\n\tSLOTXY_BELT_LAST      = 54,\r\n\tNUM_XY_SLOTS          = 55\r\n\t// clang-format on\r\n};\r\n\r\nenum item_color : uint8_t {\r\n\t// clang-format off\r\n\tICOL_YELLOW = PAL16_YELLOW + 5,\r\n\tICOL_WHITE  = PAL16_GRAY   + 5,\r\n\tICOL_BLUE   = PAL16_BLUE   + 5,\r\n\tICOL_RED    = PAL16_RED    + 5,\r\n\t// clang-format on\r\n};\r\n\r\nextern bool invflag;\r\nextern const Rectangle InvRect[NUM_XY_SLOTS];\r\n\r\nvoid InvDrawSlotBack(const Surface &out, Point targetPosition, Size size, item_quality itemQuality);\r\n/**\r\n * @brief Checks whether the given item can be placed on the belt. Takes item size as well as characteristics into account. Items\r\n * that cannot be placed on the belt have to be placed in the inventory instead.\r\n * @param item The item to be checked.\r\n * @return 'True' in case the item can be placed on the belt and 'False' otherwise.\r\n */\r\nbool CanBePlacedOnBelt(const Player &player, const Item &item);\r\n\r\n/**\r\n * @brief Function type which performs an operation on the given item.\r\n */\r\nusing ItemFunc = void (*)(Item &);\r\n\r\nvoid CloseInventory();\r\nvoid CloseStash();\r\nvoid FreeInvGFX();\r\nvoid InitInv();\r\n\r\n/**\r\n * @brief Render the inventory panel to the given buffer.\r\n */\r\nvoid DrawInv(const Surface &out);\r\n\r\nvoid DrawInvBelt(const Surface &out);\r\n\r\n/**\r\n * @brief Removes equipment from the specified location on the player's body.\r\n * @param player The player from which equipment will be removed.\r\n * @param bodyLocation The location from which equipment will be removed.\r\n * @param hiPri Priority of the network message to sync player equipment.\r\n */\r\nvoid RemoveEquipment(Player &player, inv_body_loc bodyLocation, bool hiPri);\r\n\r\n/**\r\n * @brief Checks whether or not auto-equipping behavior is enabled for the given player and item.\r\n * @param player The player to check.\r\n * @param item The item to check.\r\n * @return 'True' if auto-equipping behavior is enabled for the player and item and 'False' otherwise.\r\n */\r\nbool AutoEquipEnabled(const Player &player, const Item &item);\r\n\r\n/**\r\n * @brief Automatically attempts to equip the specified item in the most appropriate location in the player's body.\r\n * @note On success, this will broadcast an equipment_change event to let other players know about the equipment change.\r\n * @param player The player whose inventory will be checked for compatibility with the item.\r\n * @param item The item to equip.\r\n * @param persistItem Indicates whether or not the item should be persisted in the player's body. Pass 'False' to check\r\n * whether the player can equip the item but you don't want the item to actually be equipped. 'True' by default.\r\n * @param sendNetworkMessage Set to true if you want an equip sound and network message to be generated if the equipment\r\n * changes. Should only be set if a local player is equipping an item in a play session (not when creating a new game)\r\n * @return 'True' if the item was equipped and 'False' otherwise.\r\n */\r\nbool AutoEquip(Player &player, const Item &item, bool persistItem = true, bool sendNetworkMessage = false);\r\n\r\n/**\r\n * @brief Checks whether the given item can be placed on the specified player's inventory.\r\n * @param player The player whose inventory will be checked.\r\n * @param item The item to be checked.\r\n * @return 'True' in case the item can be placed on the player's inventory and 'False' otherwise.\r\n */\r\nbool CanFitItemInInventory(const Player &player, const Item &item);\r\n\r\n/**\r\n * @brief Attempts to place the given item in the specified player's inventory.\r\n * @param player The player whose inventory will be used.\r\n * @param item The item to be placed.\r\n * @param sendNetworkMessage Set to true if you want a network message to be generated if the item is persisted.\r\n * Should only be set if a local player is placing an item in a play session (not when creating a new game)\r\n * @return 'True' if the item was placed on the player's inventory and 'False' otherwise.\r\n */\r\nbool AutoPlaceItemInInventory(Player &player, const Item &item, bool sendNetworkMessage = false);\r\n\r\n/**\r\n * @brief Checks whether the given item can be placed on the specified player's belt. Returns 'True' when the item can be placed\r\n * on belt slots and the player has at least one empty slot in his belt.\r\n * If 'persistItem' is 'True', the item is also placed in the belt.\r\n * @param player The player on whose belt will be checked.\r\n * @param item The item to be checked.\r\n * @param persistItem Pass 'True' to actually place the item in the belt. The default is 'False'.\r\n * @param sendNetworkMessage Set to true if you want a network message to be generated if the item is persisted.\r\n * Should only be set if a local player is placing an item in a play session (not when creating a new game)\r\n * @return 'True' in case the item can be placed on the player's belt and 'False' otherwise.\r\n */\r\nbool AutoPlaceItemInBelt(Player &player, const Item &item, bool persistItem = false, bool sendNetworkMessage = false);\r\n\r\n/**\r\n * @brief Sort player inventory.\r\n */\r\nvoid ReorganizeInventory(Player &player);\r\n\r\n/**\r\n * @brief Calculate the maximum additional gold that may fit in the user's inventory\r\n */\r\nint RoomForGold();\r\n\r\n/**\r\n * @return The leftover amount that didn't fit, if any\r\n */\r\nint AddGoldToInventory(Player &player, int value);\r\nbool GoldAutoPlace(Player &player, Item &goldStack);\r\nvoid CheckInvSwap(Player &player, inv_body_loc bLoc);\r\nvoid inv_update_rem_item(Player &player, inv_body_loc iv);\r\nvoid CheckInvSwap(Player &player, const Item &item, int invGridIndex);\r\nvoid CheckInvRemove(Player &player, int invGridIndex);\r\nvoid TransferItemToStash(Player &player, int location);\r\nvoid CheckInvItem(bool isShiftHeld = false, bool isCtrlHeld = false);\r\n\r\n/**\r\n * Check for interactions with belt\r\n */\r\nvoid CheckInvScrn(bool isShiftHeld, bool isCtrlHeld);\r\nvoid InvGetItem(Player &player, int ii);\r\n\r\n/**\r\n * @brief Returns the first free space that can take an item preferencing tiles in front of the current position\r\n *\r\n * The search starts with the adjacent tile in the desired direction and alternates sides until it ends up checking the\r\n * opposite tile, before finally checking the origin tile\r\n *\r\n * @param origin center tile of the search space\r\n * @param facing direction of the adjacent tile to check first\r\n * @return the first valid point or an empty optional\r\n */\r\nstd::optional<Point> FindAdjacentPositionForItem(Point origin, Direction facing);\r\nvoid AutoGetItem(Player &player, Item *itemPointer, int ii);\r\n\r\n/**\r\n * @brief Searches for a dropped item with the same type/createInfo/seed\r\n * @param iseed The value used to initialise the RNG when generating the item\r\n * @param idx The overarching type of the target item\r\n * @param ci Flags used to describe the specific subtype of the target item\r\n * @return An index into ActiveItems or -1 if no matching item was found\r\n */\r\nint FindGetItem(uint32_t iseed, _item_indexes idx, uint16_t ci);\r\nvoid SyncGetItem(Point position, uint32_t iseed, _item_indexes idx, uint16_t ci);\r\n\r\n/**\r\n * @brief Checks if the tile has room for an item\r\n * @param position tile coordinates\r\n * @return True if the space is free of obstructions, false if blocked\r\n */\r\nbool CanPut(Point position);\r\n\r\nint ClampDurability(const Item &item, int durability);\r\nint16_t ClampToHit(const Item &item, int16_t toHit);\r\nuint8_t ClampMaxDam(const Item &item, uint8_t maxDam);\r\nint SyncDropItem(Point position, _item_indexes idx, uint16_t icreateinfo, int iseed, int id, int dur, int mdur, int ch, int mch, int ivalue, uint32_t ibuff, int toHit, int maxDam);\r\nint SyncDropEar(Point position, uint16_t icreateinfo, uint32_t iseed, uint8_t cursval, std::string_view heroname);\r\nint8_t CheckInvHLight();\r\nbool CanUseScroll(Player &player, SpellID spell);\r\nvoid ConsumeStaffCharge(Player &player);\r\nbool CanUseStaff(Player &player, SpellID spellId);\r\nItem &GetInventoryItem(Player &player, int location);\r\nbool UseInvItem(int cii);\r\nvoid DoTelekinesis();\r\nint CalculateGold(Player &player);\r\n\r\n/**\r\n * @brief Gets the size, in inventory cells, of the given item.\r\n * @param item The item whose size is to be determined.\r\n * @return The size, in inventory cells, of the item.\r\n */\r\nSize GetInventorySize(const Item &item);\r\n\r\n/**\r\n * @brief Checks whether the player has an inventory item matching the predicate.\r\n */\r\ntemplate <typename Predicate>\r\nbool HasInventoryItem(const Player &player, Predicate &&predicate)\r\n{\r\n\tconst InventoryPlayerItemsRange items { player };\r\n\treturn c_find_if(items, std::forward<Predicate>(predicate)) != items.end();\r\n}\r\n\r\n/**\r\n * @brief Checks whether the player has a belt item matching the predicate.\r\n */\r\ntemplate <typename Predicate>\r\nbool HasBeltItem(const Player &player, Predicate &&predicate)\r\n{\r\n\tconst BeltPlayerItemsRange items { player };\r\n\treturn c_find_if(items, std::forward<Predicate>(predicate)) != items.end();\r\n}\r\n\r\n/**\r\n * @brief Checks whether the player has an inventory or a belt item matching the predicate.\r\n */\r\ntemplate <typename Predicate>\r\nbool HasInventoryOrBeltItem(const Player &player, Predicate &&predicate)\r\n{\r\n\treturn HasInventoryItem(player, predicate) || HasBeltItem(player, predicate);\r\n}\r\n\r\n/**\r\n * @brief Checks whether the player has an inventory item with the given ID (IDidx).\r\n */\r\ninline bool HasInventoryItemWithId(const Player &player, _item_indexes id)\r\n{\r\n\treturn HasInventoryItem(player, [id](const Item &item) {\r\n\t\treturn item.IDidx == id;\r\n\t});\r\n}\r\n\r\n/**\r\n * @brief Checks whether the player has a belt item with the given ID (IDidx).\r\n */\r\ninline bool HasBeltItemWithId(const Player &player, _item_indexes id)\r\n{\r\n\treturn HasBeltItem(player, [id](const Item &item) {\r\n\t\treturn item.IDidx == id;\r\n\t});\r\n}\r\n\r\n/**\r\n * @brief Checks whether the player has an inventory or a belt item with the given ID (IDidx).\r\n */\r\ninline bool HasInventoryOrBeltItemWithId(const Player &player, _item_indexes id)\r\n{\r\n\treturn HasInventoryItemWithId(player, id) || HasBeltItemWithId(player, id);\r\n}\r\n\r\n/**\r\n * @brief Removes the first inventory item matching the predicate.\r\n *\r\n * @return Whether an item was found and removed.\r\n */\r\ntemplate <typename Predicate>\r\nbool RemoveInventoryItem(Player &player, Predicate &&predicate)\r\n{\r\n\tconst InventoryPlayerItemsRange items { player };\r\n\tconst auto it = c_find_if(items, std::forward<Predicate>(predicate));\r\n\tif (it == items.end())\r\n\t\treturn false;\r\n\tplayer.RemoveInvItem(static_cast<int>(it.index()));\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * @brief Removes the first belt item matching the predicate.\r\n *\r\n * @return Whether an item was found and removed.\r\n */\r\ntemplate <typename Predicate>\r\nbool RemoveBeltItem(Player &player, Predicate &&predicate)\r\n{\r\n\tconst BeltPlayerItemsRange items { player };\r\n\tconst auto it = c_find_if(items, std::forward<Predicate>(predicate));\r\n\tif (it == items.end())\r\n\t\treturn false;\r\n\tplayer.RemoveSpdBarItem(static_cast<int>(it.index()));\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * @brief Removes the first inventory or belt item matching the predicate.\r\n *\r\n * @return Whether an item was found and removed.\r\n */\r\ntemplate <typename Predicate>\r\nbool RemoveInventoryOrBeltItem(Player &player, Predicate &&predicate)\r\n{\r\n\treturn RemoveInventoryItem(player, predicate) || RemoveBeltItem(player, predicate);\r\n}\r\n\r\n/**\r\n * @brief Removes the first inventory item with the given id (IDidx).\r\n *\r\n * @return Whether an item was found and removed.\r\n */\r\ninline bool RemoveInventoryItemById(Player &player, _item_indexes id)\r\n{\r\n\treturn RemoveInventoryItem(player, [id](const Item &item) {\r\n\t\treturn item.IDidx == id;\r\n\t});\r\n}\r\n\r\n/**\r\n * @brief Removes the first belt item with the given id (IDidx).\r\n *\r\n * @return Whether an item was found and removed.\r\n */\r\ninline bool RemoveBeltItemById(Player &player, _item_indexes id)\r\n{\r\n\treturn RemoveBeltItem(player, [id](const Item &item) {\r\n\t\treturn item.IDidx == id;\r\n\t});\r\n}\r\n\r\n/**\r\n * @brief Removes the first inventory or belt item with the given id (IDidx).\r\n *\r\n * @return Whether an item was found and removed.\r\n */\r\ninline bool RemoveInventoryOrBeltItemById(Player &player, _item_indexes id)\r\n{\r\n\treturn RemoveInventoryItemById(player, id) || RemoveBeltItemById(player, id);\r\n}\r\n\r\n/**\r\n * @brief Removes the first inventory or belt scroll with the player's current spell.\r\n */\r\nvoid ConsumeScroll(Player &player);\r\n\r\n/* data */\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/inv_iterators.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <iterator>\r\n#include <type_traits>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#include \"items.h\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief A range over non-empty items in a container.\r\n */\r\ntemplate <typename ItemT>\r\nclass ItemsContainerRange {\r\n\tstatic_assert(std::is_same_v<ItemT, Item> || std::is_same_v<ItemT, const Item>,\r\n\t    \"The template argument must be `Item` or `const Item`\");\r\n\r\npublic:\r\n\tclass Iterator {\r\n\tpublic:\r\n\t\tusing iterator_category = std::forward_iterator_tag;\r\n\t\tusing difference_type = int;\r\n\t\tusing value_type = ItemT;\r\n\t\tusing pointer = value_type *;\r\n\t\tusing reference = value_type &;\r\n\r\n\t\tIterator() = default;\r\n\r\n\t\tIterator(ItemT *items, std::size_t count, std::size_t index)\r\n\t\t    : items_(items)\r\n\t\t    , count_(count)\r\n\t\t    , index_(index)\r\n\t\t{\r\n\t\t\tadvancePastEmpty();\r\n\t\t}\r\n\r\n\t\tpointer operator->() const\r\n\t\t{\r\n\t\t\treturn &items_[index_];\r\n\t\t}\r\n\r\n\t\treference operator*() const\r\n\t\t{\r\n\t\t\treturn items_[index_];\r\n\t\t}\r\n\r\n\t\tIterator &operator++()\r\n\t\t{\r\n\t\t\t++index_;\r\n\t\t\tadvancePastEmpty();\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tIterator operator++(int)\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\t++(*this);\r\n\t\t\treturn copy;\r\n\t\t}\r\n\r\n\t\tbool operator==(const Iterator &other) const\r\n\t\t{\r\n\t\t\treturn index_ == other.index_;\r\n\t\t}\r\n\r\n\t\tbool operator!=(const Iterator &other) const\r\n\t\t{\r\n\t\t\treturn !(*this == other);\r\n\t\t}\r\n\r\n\t\t[[nodiscard]] bool atEnd() const\r\n\t\t{\r\n\t\t\treturn index_ == count_;\r\n\t\t}\r\n\r\n\t\t[[nodiscard]] std::size_t index() const\r\n\t\t{\r\n\t\t\treturn index_;\r\n\t\t}\r\n\r\n\tprivate:\r\n\t\tvoid advancePastEmpty()\r\n\t\t{\r\n\t\t\twhile (index_ < count_ && items_[index_].isEmpty()) {\r\n\t\t\t\t++index_;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tItemT *items_ = nullptr;\r\n\t\tstd::size_t count_ = 0;\r\n\t\tstd::size_t index_ = 0;\r\n\t};\r\n\r\n\tItemsContainerRange(ItemT *items, std::size_t count)\r\n\t    : items_(items)\r\n\t    , count_(count)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator begin() const\r\n\t{\r\n\t\treturn Iterator { items_, count_, 0 };\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator end() const\r\n\t{\r\n\t\treturn Iterator { nullptr, count_, count_ };\r\n\t}\r\n\r\nprivate:\r\n\tItemT *items_;\r\n\tstd::size_t count_;\r\n};\r\n\r\n/**\r\n * @brief A range over non-empty items in a list of containers.\r\n */\r\ntemplate <typename ItemT>\r\nclass ItemsContainerListRange {\r\n\tstatic_assert(std::is_same_v<ItemT, Item> || std::is_same_v<ItemT, const Item>,\r\n\t    \"The template argument must be `Item` or `const Item`\");\r\n\r\npublic:\r\n\tclass Iterator {\r\n\tpublic:\r\n\t\tusing iterator_category = std::forward_iterator_tag;\r\n\t\tusing difference_type = int;\r\n\t\tusing value_type = ItemT;\r\n\t\tusing pointer = value_type *;\r\n\t\tusing reference = value_type &;\r\n\r\n\t\tIterator() = default;\r\n\r\n\t\texplicit Iterator(std::vector<typename ItemsContainerRange<ItemT>::Iterator> iterators)\r\n\t\t    : iterators_(std::move(iterators))\r\n\t\t{\r\n\t\t\tadvancePastEmpty();\r\n\t\t}\r\n\r\n\t\tpointer operator->() const\r\n\t\t{\r\n\t\t\treturn iterators_[current_].operator->();\r\n\t\t}\r\n\r\n\t\treference operator*() const\r\n\t\t{\r\n\t\t\treturn iterators_[current_].operator*();\r\n\t\t}\r\n\r\n\t\tIterator &operator++()\r\n\t\t{\r\n\t\t\t++iterators_[current_];\r\n\t\t\tadvancePastEmpty();\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tIterator operator++(int)\r\n\t\t{\r\n\t\t\tauto copy = *this;\r\n\t\t\t++(*this);\r\n\t\t\treturn copy;\r\n\t\t}\r\n\r\n\t\tbool operator==(const Iterator &other) const\r\n\t\t{\r\n\t\t\treturn current_ == other.current_ && iterators_[current_] == other.iterators_[current_];\r\n\t\t}\r\n\t\tbool operator!=(const Iterator &other) const\r\n\t\t{\r\n\t\t\treturn !(*this == other);\r\n\t\t}\r\n\r\n\tprivate:\r\n\t\tvoid advancePastEmpty()\r\n\t\t{\r\n\t\t\twhile (current_ + 1 < iterators_.size() && iterators_[current_].atEnd()) {\r\n\t\t\t\t++current_;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tstd::vector<typename ItemsContainerRange<ItemT>::Iterator> iterators_;\r\n\t\tstd::size_t current_ = 0;\r\n\t};\r\n};\r\n\r\n/**\r\n * @brief A range over equipped player items.\r\n */\r\ntemplate <typename PlayerT>\r\nclass EquippedPlayerItemsRange {\r\n\tstatic_assert(std::is_same_v<PlayerT, Player> || std::is_same_v<PlayerT, const Player>,\r\n\t    \"The template argument must be `Player` or `const Player`\");\r\n\tusing ItemT = std::conditional_t<std::is_const_v<PlayerT>, const Item, Item>;\r\n\tusing Iterator = typename ItemsContainerRange<ItemT>::Iterator;\r\n\r\npublic:\r\n\texplicit EquippedPlayerItemsRange(PlayerT &player)\r\n\t    : player_(&player)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator begin() const\r\n\t{\r\n\t\treturn Iterator { &player_->InvBody[0], containerSize(), 0 };\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator end() const\r\n\t{\r\n\t\treturn Iterator { nullptr, containerSize(), containerSize() };\r\n\t}\r\n\r\nprivate:\r\n\t[[nodiscard]] std::size_t containerSize() const\r\n\t{\r\n\t\treturn sizeof(player_->InvBody) / sizeof(player_->InvBody[0]);\r\n\t}\r\n\r\n\tPlayerT *player_;\r\n};\r\n\r\n/**\r\n * @brief A range over non-equipped inventory player items.\r\n */\r\ntemplate <typename PlayerT>\r\nclass InventoryPlayerItemsRange {\r\n\tstatic_assert(std::is_same_v<PlayerT, Player> || std::is_same_v<PlayerT, const Player>,\r\n\t    \"The template argument must be `Player` or `const Player`\");\r\n\tusing ItemT = std::conditional_t<std::is_const_v<PlayerT>, const Item, Item>;\r\n\tusing Iterator = typename ItemsContainerRange<ItemT>::Iterator;\r\n\r\npublic:\r\n\texplicit InventoryPlayerItemsRange(PlayerT &player)\r\n\t    : player_(&player)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator begin() const\r\n\t{\r\n\t\treturn Iterator { &player_->InvList[0], containerSize(), 0 };\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator end() const\r\n\t{\r\n\t\treturn Iterator { nullptr, containerSize(), containerSize() };\r\n\t}\r\n\r\nprivate:\r\n\t[[nodiscard]] std::size_t containerSize() const\r\n\t{\r\n\t\treturn static_cast<std::size_t>(player_->_pNumInv);\r\n\t}\r\n\r\n\tPlayerT *player_;\r\n};\r\n\r\n/**\r\n * @brief A range over belt player items.\r\n */\r\ntemplate <typename PlayerT>\r\nclass BeltPlayerItemsRange {\r\n\tstatic_assert(std::is_same_v<PlayerT, Player> || std::is_same_v<PlayerT, const Player>,\r\n\t    \"The template argument must be `Player` or `const Player`\");\r\n\tusing ItemT = std::conditional_t<std::is_const_v<PlayerT>, const Item, Item>;\r\n\tusing Iterator = typename ItemsContainerRange<ItemT>::Iterator;\r\n\r\npublic:\r\n\texplicit BeltPlayerItemsRange(PlayerT &player)\r\n\t    : player_(&player)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator begin() const\r\n\t{\r\n\t\treturn Iterator { &player_->SpdList[0], containerSize(), 0 };\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator end() const\r\n\t{\r\n\t\treturn Iterator { nullptr, containerSize(), containerSize() };\r\n\t}\r\n\r\nprivate:\r\n\t[[nodiscard]] std::size_t containerSize() const\r\n\t{\r\n\t\treturn sizeof(player_->SpdList) / sizeof(player_->SpdList[0]);\r\n\t}\r\n\r\n\tPlayerT *player_;\r\n};\r\n\r\n/**\r\n * @brief A range over non-equipped player items in the following order: Inventory, Belt.\r\n */\r\ntemplate <typename PlayerT>\r\nclass InventoryAndBeltPlayerItemsRange {\r\n\tstatic_assert(std::is_same_v<PlayerT, Player> || std::is_same_v<PlayerT, const Player>,\r\n\t    \"The template argument must be `Player` or `const Player`\");\r\n\tusing ItemT = std::conditional_t<std::is_const_v<PlayerT>, const Item, Item>;\r\n\tusing Iterator = typename ItemsContainerListRange<ItemT>::Iterator;\r\n\r\npublic:\r\n\texplicit InventoryAndBeltPlayerItemsRange(PlayerT &player)\r\n\t    : player_(&player)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator begin() const\r\n\t{\r\n\t\treturn Iterator({\r\n\t\t    InventoryPlayerItemsRange(*player_).begin(),\r\n\t\t    BeltPlayerItemsRange(*player_).begin(),\r\n\t\t});\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator end() const\r\n\t{\r\n\t\treturn Iterator({\r\n\t\t    InventoryPlayerItemsRange(*player_).end(),\r\n\t\t    BeltPlayerItemsRange(*player_).end(),\r\n\t\t});\r\n\t}\r\n\r\nprivate:\r\n\tPlayerT *player_;\r\n};\r\n\r\n/**\r\n * @brief A range over non-empty player items in the following order: Equipped, Inventory, Belt.\r\n */\r\ntemplate <typename PlayerT>\r\nclass PlayerItemsRange {\r\n\tstatic_assert(std::is_same_v<PlayerT, Player> || std::is_same_v<PlayerT, const Player>,\r\n\t    \"The template argument must be `Player` or `const Player`\");\r\n\tusing ItemT = std::conditional_t<std::is_const_v<PlayerT>, const Item, Item>;\r\n\tusing Iterator = typename ItemsContainerListRange<ItemT>::Iterator;\r\n\r\npublic:\r\n\texplicit PlayerItemsRange(PlayerT &player)\r\n\t    : player_(&player)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator begin() const\r\n\t{\r\n\t\treturn Iterator({\r\n\t\t    EquippedPlayerItemsRange(*player_).begin(),\r\n\t\t    InventoryPlayerItemsRange(*player_).begin(),\r\n\t\t    BeltPlayerItemsRange(*player_).begin(),\r\n\t\t});\r\n\t}\r\n\r\n\t[[nodiscard]] Iterator end() const\r\n\t{\r\n\t\treturn Iterator({\r\n\t\t    EquippedPlayerItemsRange(*player_).end(),\r\n\t\t    InventoryPlayerItemsRange(*player_).end(),\r\n\t\t    BeltPlayerItemsRange(*player_).end(),\r\n\t\t});\r\n\t}\r\n\r\nprivate:\r\n\tPlayerT *player_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/items/validation.cpp",
    "content": "/**\r\n * @file items/validation.cpp\r\n *\r\n * Implementation of functions for validation of player and item data.\r\n */\r\n\r\n#include \"items/validation.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"items.h\"\r\n#include \"msg.h\"\r\n#include \"player.h\"\r\n#include \"spells.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nbool hasMultipleFlags(uint16_t flags)\r\n{\r\n\treturn (flags & (flags - 1)) > 0;\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsCreationFlagComboValid(uint16_t iCreateInfo)\r\n{\r\n\tiCreateInfo = iCreateInfo & ~CF_LEVEL;\r\n\tconst bool isTownItem = (iCreateInfo & CF_TOWN) != 0;\r\n\tconst bool isPregenItem = (iCreateInfo & CF_PREGEN) != 0;\r\n\tconst bool isUsefulItem = (iCreateInfo & CF_USEFUL) == CF_USEFUL;\r\n\r\n\tif (isPregenItem) {\r\n\t\t// Pregen flags are discarded when an item is picked up, therefore impossible to have in the inventory\r\n\t\treturn false;\r\n\t}\r\n\tif (isUsefulItem && (iCreateInfo & ~CF_USEFUL) != 0)\r\n\t\treturn false;\r\n\tif (isTownItem && hasMultipleFlags(iCreateInfo)) {\r\n\t\t// Items from town can only have 1 towner flag\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IsTownItemValid(uint16_t iCreateInfo, const Player &player)\r\n{\r\n\tconst uint8_t level = iCreateInfo & CF_LEVEL;\r\n\tconst bool isBoyItem = (iCreateInfo & CF_BOY) != 0;\r\n\tconst uint8_t maxTownItemLevel = 30;\r\n\r\n\t// Wirt items in multiplayer are equal to the level of the player, therefore they cannot exceed the max character level\r\n\tif (isBoyItem && level <= player.getMaxCharacterLevel())\r\n\t\treturn true;\r\n\r\n\treturn level <= maxTownItemLevel;\r\n}\r\n\r\nbool IsShopPriceValid(const Item &item)\r\n{\r\n\tconst int boyPriceLimit = MaxBoyValue;\r\n\tif (!gbIsHellfire && (item._iCreateInfo & CF_BOY) != 0 && item._iIvalue > boyPriceLimit)\r\n\t\treturn false;\r\n\r\n\tconst int premiumPriceLimit = MaxVendorValue;\r\n\tif (!gbIsHellfire && (item._iCreateInfo & CF_SMITHPREMIUM) != 0 && item._iIvalue > premiumPriceLimit)\r\n\t\treturn false;\r\n\r\n\tconst uint16_t smithOrWitch = CF_SMITH | CF_WITCH;\r\n\tconst int smithAndWitchPriceLimit = gbIsHellfire ? MaxVendorValueHf : MaxVendorValue;\r\n\tif ((item._iCreateInfo & smithOrWitch) != 0 && item._iIvalue > smithAndWitchPriceLimit)\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool IsUniqueMonsterItemValid(uint16_t iCreateInfo, uint32_t dwBuff)\r\n{\r\n\tconst uint8_t level = iCreateInfo & CF_LEVEL;\r\n\r\n\t// Check all unique monster levels to see if they match the item level\r\n\tfor (const UniqueMonsterData &uniqueMonsterData : UniqueMonstersData) {\r\n\t\tif (IsAnyOf(uniqueMonsterData.mtype, MT_DEFILER, MT_NAKRUL, MT_HORKDMN)) {\r\n\t\t\t// These monsters don't use their mlvl for item generation\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst auto &uniqueMonsterLevel = static_cast<uint8_t>(MonstersData[uniqueMonsterData.mtype].level);\r\n\r\n\t\tif (level == uniqueMonsterLevel) {\r\n\t\t\t// If the ilvl matches the mlvl, we confirm the item is legitimate\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool IsDungeonItemValid(uint16_t iCreateInfo, uint32_t dwBuff)\r\n{\r\n\tconst uint8_t level = iCreateInfo & CF_LEVEL;\r\n\tconst bool isHellfireItem = (dwBuff & CF_HELLFIRE) != 0;\r\n\r\n\t// Check all monster levels to see if they match the item level\r\n\tint type = -1;\r\n\tfor (const MonsterData &monsterData : MonstersData) {\r\n\t\ttype++;\r\n\t\tauto monsterLevel = static_cast<uint8_t>(monsterData.level);\r\n\r\n\t\tif (type != MT_DIABLO && monsterData.availability == MonsterAvailability::Never) {\r\n\t\t\t// Skip monsters that are unable to appear in the game\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (type == MT_DIABLO && isHellfireItem) {\r\n\t\t\t// Adjust The Dark Lord's mlvl if the item is a Hellfire item to match the Diablo mlvl\r\n\t\t\tmonsterLevel += 15;\r\n\t\t}\r\n\r\n\t\tif (level == monsterLevel) {\r\n\t\t\t// If the ilvl matches the mlvl, we confirm the item is legitimate\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (isHellfireItem) {\r\n\t\tuint8_t hellfireMaxDungeonLevel = 24;\r\n\r\n\t\t// Hellfire adjusts the currlevel minus 7 in dungeon levels 20-24 for generating items\r\n\t\thellfireMaxDungeonLevel -= 7;\r\n\t\treturn level <= (hellfireMaxDungeonLevel * 2);\r\n\t}\r\n\r\n\tuint8_t diabloMaxDungeonLevel = 16;\r\n\r\n\t// Diablo doesn't have containers that drop items in dungeon level 16, therefore we decrement by 1\r\n\tdiabloMaxDungeonLevel--;\r\n\treturn level <= (diabloMaxDungeonLevel * 2);\r\n}\r\n\r\nbool IsHellfireSpellBookValid(const Item &spellBook)\r\n{\r\n\t// Hellfire uses the spell book level when generating items via CreateSpellBook()\r\n\tint spellBookLevel = GetSpellBookLevel(spellBook._iSpell);\r\n\r\n\t// CreateSpellBook() adds 1 to the spell level for ilvl\r\n\tspellBookLevel++;\r\n\r\n\tif (spellBookLevel >= 1 && (spellBook._iCreateInfo & CF_LEVEL) == spellBookLevel * 2) {\r\n\t\t// The ilvl matches the result for a spell book drop, so we confirm the item is legitimate\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn IsDungeonItemValid(spellBook._iCreateInfo, spellBook.dwBuff);\r\n}\r\n\r\nbool IsItemValid(const Player &player, const Item &item)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn true;\r\n\r\n\tif (item.IDidx == IDI_EAR)\r\n\t\treturn true;\r\n\tif (item.IDidx != IDI_GOLD && !IsCreationFlagComboValid(item._iCreateInfo))\r\n\t\treturn false;\r\n\tif ((item._iCreateInfo & CF_TOWN) != 0)\r\n\t\treturn IsTownItemValid(item._iCreateInfo, player) && IsShopPriceValid(item);\r\n\tif ((item._iCreateInfo & CF_USEFUL) == CF_UPER15)\r\n\t\treturn IsUniqueMonsterItemValid(item._iCreateInfo, item.dwBuff);\r\n\tif ((item.dwBuff & CF_HELLFIRE) != 0 && AllItemsList[item.IDidx].iMiscId == IMISC_BOOK)\r\n\t\treturn IsHellfireSpellBookValid(item);\r\n\r\n\treturn IsDungeonItemValid(item._iCreateInfo, item.dwBuff);\r\n}\r\n\r\nbool IsItemDeltaValid(const TCmdPItem &itemDelta)\r\n{\r\n\tif (itemDelta.bCmd == CMD_INVALID)\r\n\t\treturn true;\r\n\tif (IsNoneOf(itemDelta.bCmd, TCmdPItem::FloorItem, TCmdPItem::PickedUpItem, TCmdPItem::DroppedItem))\r\n\t\treturn false;\r\n\tif (!InDungeonBounds({ itemDelta.x, itemDelta.y }))\r\n\t\treturn false;\r\n\tconst _item_indexes idx = static_cast<_item_indexes>(Swap16LE(itemDelta.def.wIndx));\r\n\tif (idx == IDI_EAR)\r\n\t\treturn true;\r\n\tif (!IsItemAvailable(idx))\r\n\t\treturn false;\r\n\tItem item = {};\r\n\tRecreateItem(*MyPlayer, itemDelta.item, item);\r\n\treturn IsItemValid(*MyPlayer, item);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/items/validation.h",
    "content": "/**\r\n * @file items/validation.h\r\n *\r\n * Interface of functions for validation of player and item data.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\n// Forward declared structs to avoid circular dependencies\r\nstruct Item;\r\nstruct TCmdPItem;\r\nstruct Player;\r\n\r\nbool IsCreationFlagComboValid(uint16_t iCreateInfo);\r\nbool IsTownItemValid(uint16_t iCreateInfo, const Player &player);\r\nbool IsShopPriceValid(const Item &item);\r\nbool IsUniqueMonsterItemValid(uint16_t iCreateInfo, uint32_t dwBuff);\r\nbool IsDungeonItemValid(uint16_t iCreateInfo, uint32_t dwBuff);\r\nbool IsItemValid(const Player &player, const Item &item);\r\nbool IsItemDeltaValid(const TCmdPItem &itemDelta);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/items.cpp",
    "content": "/**\r\n * @file items.cpp\r\n *\r\n * Implementation of item functionality.\r\n */\r\n#include \"items.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cassert>\r\n#include <climits>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <type_traits>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/controller_buttons.h\"\r\n#include \"cursor.h\"\r\n#include \"diablo.h\"\r\n#include \"doom.h\"\r\n#include \"effects.h\"\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/path.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"function_ref.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"inv.h\"\r\n#include \"inv_iterators.hpp\"\r\n#include \"items/validation.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/gendung_defs.hpp\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"levels/town.h\"\r\n#include \"lighting.h\"\r\n#include \"minitext.h\"\r\n#include \"monster.h\"\r\n#include \"msg.h\"\r\n#include \"multi.h\"\r\n#include \"objects.h\"\r\n#include \"options.h\"\r\n#include \"pack.h\"\r\n#include \"panels/info_box.hpp\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"player.h\"\r\n#include \"qol/stash.h\"\r\n#include \"quests.h\"\r\n#include \"sound_effect_enums.h\"\r\n#include \"spells.h\"\r\n#include \"stores.h\"\r\n#include \"tables/itemdat.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"tables/spelldat.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/math.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/static_vector.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n#include \"utils/string_or_view.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nItem Items[MAXITEMS + 1];\r\nuint8_t ActiveItems[MAXITEMS];\r\nuint8_t ActiveItemCount;\r\nint8_t dItem[MAXDUNX][MAXDUNY];\r\nbool ShowUniqueItemInfoBox;\r\nCornerStoneStruct CornerStone;\r\nbool UniqueItemFlags[128];\r\nint MaxGold = GOLD_MAX_LIMIT;\r\n\r\n/** Maps from item_cursor_graphic to in-memory item type. */\r\nint8_t ItemCAnimTbl[] = {\r\n\t20, 16, 16, 16, 4, 4, 4, 12, 12, 12,\r\n\t12, 12, 12, 12, 12, 21, 21, 25, 12, 28,\r\n\t28, 28, 38, 38, 38, 32, 38, 38, 38, 24,\r\n\t24, 26, 2, 25, 22, 23, 24, 21, 27, 27,\r\n\t29, 0, 0, 0, 12, 12, 12, 12, 12, 0,\r\n\t8, 8, 0, 8, 8, 8, 8, 8, 8, 6,\r\n\t8, 8, 8, 6, 8, 8, 6, 8, 8, 6,\r\n\t6, 6, 8, 8, 8, 5, 9, 13, 13, 13,\r\n\t5, 5, 5, 15, 5, 5, 18, 18, 18, 30,\r\n\t5, 5, 14, 5, 14, 13, 16, 18, 5, 5,\r\n\t7, 1, 3, 17, 1, 15, 10, 14, 3, 11,\r\n\t8, 0, 1, 7, 0, 7, 15, 7, 3, 3,\r\n\t3, 6, 6, 11, 11, 11, 31, 14, 14, 14,\r\n\t6, 6, 7, 3, 8, 14, 0, 14, 14, 0,\r\n\t33, 1, 1, 1, 1, 1, 7, 7, 7, 14,\r\n\t14, 17, 17, 17, 0, 34, 1, 0, 3, 17,\r\n\t8, 8, 6, 1, 3, 3, 11, 3, 12, 12,\r\n\t12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\r\n\t12, 12, 12, 12, 12, 12, 12, 35, 39, 36,\r\n\t36, 36, 37, 38, 38, 38, 38, 38, 41, 42,\r\n\t8, 8, 8, 17, 0, 6, 8, 11, 11, 3,\r\n\t3, 1, 6, 6, 6, 1, 8, 6, 11, 3,\r\n\t6, 8, 1, 6, 6, 17, 40, 0, 0\r\n};\r\n\r\n/** Maps of drop sounds effect of placing the item in the inventory. */\r\nSfxID ItemInvSnds[] = {\r\n\tSfxID::ItemArmor,\r\n\tSfxID::ItemAxe,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemBow,\r\n\tSfxID::ItemGold,\r\n\tSfxID::ItemCap,\r\n\tSfxID::ItemSword,\r\n\tSfxID::ItemShield,\r\n\tSfxID::ItemSword,\r\n\tSfxID::ItemRock,\r\n\tSfxID::ItemAxe,\r\n\tSfxID::ItemStaff,\r\n\tSfxID::ItemRing,\r\n\tSfxID::ItemCap,\r\n\tSfxID::ItemLeather,\r\n\tSfxID::ItemShield,\r\n\tSfxID::ItemScroll,\r\n\tSfxID::ItemArmor,\r\n\tSfxID::ItemBook,\r\n\tSfxID::ItemArmor,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemPotion,\r\n\tSfxID::ItemBodyPart,\r\n\tSfxID::ItemBodyPart,\r\n\tSfxID::ItemMushroom,\r\n\tSfxID::ItemSign,\r\n\tSfxID::ItemBloodStone,\r\n\tSfxID::ItemAnvil,\r\n\tSfxID::ItemStaff,\r\n\tSfxID::ItemRock,\r\n\tSfxID::ItemScroll,\r\n\tSfxID::ItemScroll,\r\n\tSfxID::ItemRock,\r\n\tSfxID::ItemMushroom,\r\n\tSfxID::ItemArmor,\r\n\tSfxID::ItemLeather,\r\n\tSfxID::ItemLeather,\r\n};\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList itemanims[ITEMTYPES];\r\n\r\nenum class PlayerArmorGraphic : uint8_t {\r\n\t// clang-format off\r\n\tLight  = 0,\r\n\tMedium = 1 << 4,\r\n\tHeavy  = 1 << 5,\r\n\t// clang-format on\r\n};\r\n\r\nItem curruitem;\r\n\r\n/** Holds item get records, tracking items being recently looted. This is in an effort to prevent items being picked up more than once. */\r\nItemGetRecordStruct itemrecord[MAXITEMS];\r\n\r\nbool itemhold[3][3];\r\n\r\n/** Specifies the number of active item get records. */\r\nint gnNumGetRecords;\r\n\r\nint OilLevels[] = { 1, 10, 1, 10, 4, 1, 5, 17, 1, 10 };\r\nint OilValues[] = { 500, 2500, 500, 2500, 1500, 100, 2500, 15000, 500, 2500 };\r\nitem_misc_id OilMagic[] = {\r\n\tIMISC_OILACC,\r\n\tIMISC_OILMAST,\r\n\tIMISC_OILSHARP,\r\n\tIMISC_OILDEATH,\r\n\tIMISC_OILSKILL,\r\n\tIMISC_OILBSMTH,\r\n\tIMISC_OILFORT,\r\n\tIMISC_OILPERM,\r\n\tIMISC_OILHARD,\r\n\tIMISC_OILIMP,\r\n};\r\nchar OilNames[10][25] = {\r\n\tN_(\"Oil of Accuracy\"),\r\n\tN_(\"Oil of Mastery\"),\r\n\tN_(\"Oil of Sharpness\"),\r\n\tN_(\"Oil of Death\"),\r\n\tN_(\"Oil of Skill\"),\r\n\tN_(\"Blacksmith Oil\"),\r\n\tN_(\"Oil of Fortitude\"),\r\n\tN_(\"Oil of Permanence\"),\r\n\tN_(\"Oil of Hardening\"),\r\n\tN_(\"Oil of Imperviousness\")\r\n};\r\n\r\n/** Map of item type .cel file names. */\r\nconst char *const ItemDropNames[] = {\r\n\t\"armor2\",\r\n\t\"axe\",\r\n\t\"fbttle\",\r\n\t\"bow\",\r\n\t\"goldflip\",\r\n\t\"helmut\",\r\n\t\"mace\",\r\n\t\"shield\",\r\n\t\"swrdflip\",\r\n\t\"rock\",\r\n\t\"cleaver\",\r\n\t\"staff\",\r\n\t\"ring\",\r\n\t\"crownf\",\r\n\t\"larmor\",\r\n\t\"wshield\",\r\n\t\"scroll\",\r\n\t\"fplatear\",\r\n\t\"fbook\",\r\n\t\"food\",\r\n\t\"fbttlebb\",\r\n\t\"fbttledy\",\r\n\t\"fbttleor\",\r\n\t\"fbttlebr\",\r\n\t\"fbttlebl\",\r\n\t\"fbttleby\",\r\n\t\"fbttlewh\",\r\n\t\"fbttledb\",\r\n\t\"fear\",\r\n\t\"fbrain\",\r\n\t\"fmush\",\r\n\t\"innsign\",\r\n\t\"bldstn\",\r\n\t\"fanvil\",\r\n\t\"flazstaf\",\r\n\t\"bombs1\",\r\n\t\"halfps1\",\r\n\t\"wholeps1\",\r\n\t\"runes1\",\r\n\t\"teddys1\",\r\n\t\"cows1\",\r\n\t\"donkys1\",\r\n\t\"mooses1\",\r\n};\r\n/** Maps of item drop animation length. */\r\nint8_t ItemAnimLs[] = {\r\n\t15,\r\n\t13,\r\n\t16,\r\n\t13,\r\n\t10,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t20,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t1,\r\n\t16,\r\n\t16,\r\n\t16,\r\n\t16,\r\n\t16,\r\n\t16,\r\n\t16,\r\n\t16,\r\n\t13,\r\n\t12,\r\n\t12,\r\n\t13,\r\n\t13,\r\n\t13,\r\n\t8,\r\n\t10,\r\n\t16,\r\n\t16,\r\n\t10,\r\n\t10,\r\n\t15,\r\n\t15,\r\n\t15,\r\n};\r\n/** Maps of drop sounds effect of dropping the item on ground. */\r\nSfxID ItemDropSnds[] = {\r\n\tSfxID::ItemArmorFlip,\r\n\tSfxID::ItemAxeFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemBowFlip,\r\n\tSfxID::ItemGold,\r\n\tSfxID::ItemCapFlip,\r\n\tSfxID::ItemSwordFlip,\r\n\tSfxID::ItemShieldFlip,\r\n\tSfxID::ItemSwordFlip,\r\n\tSfxID::ItemRockFlip,\r\n\tSfxID::ItemAxeFlip,\r\n\tSfxID::ItemStaffFlip,\r\n\tSfxID::ItemRingFlip,\r\n\tSfxID::ItemCapFlip,\r\n\tSfxID::ItemLeatherFlip,\r\n\tSfxID::ItemShieldFlip,\r\n\tSfxID::ItemScrollFlip,\r\n\tSfxID::ItemArmorFlip,\r\n\tSfxID::ItemBookFlip,\r\n\tSfxID::ItemLeatherFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemPotionFlip,\r\n\tSfxID::ItemBodyPartFlip,\r\n\tSfxID::ItemBodyPartFlip,\r\n\tSfxID::ItemMushroomFlip,\r\n\tSfxID::ItemSignFlip,\r\n\tSfxID::ItemBloodStoneFlip,\r\n\tSfxID::ItemAnvilFlip,\r\n\tSfxID::ItemStaffFlip,\r\n\tSfxID::ItemRockFlip,\r\n\tSfxID::ItemScrollFlip,\r\n\tSfxID::ItemScrollFlip,\r\n\tSfxID::ItemRockFlip,\r\n\tSfxID::ItemMushroomFlip,\r\n\tSfxID::ItemArmorFlip,\r\n\tSfxID::ItemLeatherFlip,\r\n\tSfxID::ItemLeatherFlip,\r\n};\r\n/** Maps from Griswold premium item number to a quality level delta as added to the base quality level. */\r\nint itemLevelAdd[] = {\r\n\t// clang-format off\r\n\t-1,\r\n\t-1,\r\n\t 0,\r\n\t 0,\r\n\t 1,\r\n\t 2,\r\n\t// clang-format on\r\n};\r\n/** Maps from Griswold premium item number to a quality level delta as added to the base quality level. */\r\nint itemLevelAddHf[] = {\r\n\t// clang-format off\r\n\t-1,\r\n\t-1,\r\n\t-1,\r\n\t 0,\r\n\t 0,\r\n\t 0,\r\n\t 0,\r\n\t 1,\r\n\t 1,\r\n\t 1,\r\n\t 1,\r\n\t 2,\r\n\t 2,\r\n\t 3,\r\n\t 3,\r\n\t// clang-format on\r\n};\r\n\r\nint ItemsGetCurrlevel()\r\n{\r\n\tif (setlevel) {\r\n\t\tswitch (setlvlnum) {\r\n\t\tcase SL_SKELKING:\r\n\t\t\treturn Quests[Q_SKELKING]._qlevel;\r\n\t\tcase SL_BONECHAMB:\r\n\t\t\treturn Quests[Q_SCHAMB]._qlevel;\r\n\t\tcase SL_POISONWATER:\r\n\t\t\treturn Quests[Q_PWATER]._qlevel;\r\n\t\tcase SL_VILEBETRAYER:\r\n\t\t\treturn Quests[Q_BETRAYER]._qlevel;\r\n\t\tdefault:\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_NEST)\r\n\t\treturn currlevel - 8;\r\n\r\n\tif (leveltype == DTYPE_CRYPT)\r\n\t\treturn currlevel - 7;\r\n\r\n\treturn currlevel;\r\n}\r\n\r\nbool ItemPlace(Point position)\r\n{\r\n\tif (dMonster[position.x][position.y] != 0)\r\n\t\treturn false;\r\n\tif (dPlayer[position.x][position.y] != 0)\r\n\t\treturn false;\r\n\tif (dItem[position.x][position.y] != 0)\r\n\t\treturn false;\r\n\tif (IsObjectAtPosition(position))\r\n\t\treturn false;\r\n\tif (TileContainsSetPiece(position))\r\n\t\treturn false;\r\n\tif (IsTileSolid(position))\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nPoint GetRandomAvailableItemPosition()\r\n{\r\n\tPoint position = {};\r\n\tdo {\r\n\t\tposition = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 };\r\n\t} while (!ItemPlace(position));\r\n\r\n\treturn position;\r\n}\r\n\r\nvoid AddInitItems()\r\n{\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\tconst int rnd = GenerateRnd(3) + 3;\r\n\tfor (int j = 0; j < rnd; j++) {\r\n\t\tconst int ii = AllocateItem();\r\n\t\tauto &item = Items[ii];\r\n\r\n\t\tconst Point position = GetRandomAvailableItemPosition();\r\n\t\titem.position = position;\r\n\r\n\t\tdItem[position.x][position.y] = ii + 1;\r\n\r\n\t\titem._iSeed = AdvanceRndSeed();\r\n\t\tSetRndSeed(item._iSeed);\r\n\r\n\t\tGetItemAttrs(item, PickRandomlyAmong({ IDI_MANA, IDI_HEAL }), curlv);\r\n\r\n\t\titem._iCreateInfo = curlv | CF_PREGEN;\r\n\t\tSetupItem(item);\r\n\t\titem.AnimInfo.currentFrame = static_cast<int8_t>(item.AnimInfo.numberOfFrames - 1);\r\n\t\titem._iAnimFlag = false;\r\n\t\titem.selectionRegion = SelectionRegion::Bottom;\r\n\t\tDeltaAddItem(ii);\r\n\t}\r\n}\r\n\r\nvoid SpawnNote()\r\n{\r\n\t_item_indexes id;\r\n\r\n\tswitch (currlevel) {\r\n\tcase 22:\r\n\t\tid = IDI_NOTE2;\r\n\t\tbreak;\r\n\tcase 23:\r\n\t\tid = IDI_NOTE3;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tid = IDI_NOTE1;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tconst Point position = GetRandomAvailableItemPosition();\r\n\tSpawnQuestItem(id, position, 0, SelectionRegion::Bottom, false);\r\n}\r\n\r\nvoid CalcSelfItems(Player &player)\r\n{\r\n\tint sa = 0;\r\n\tint ma = 0;\r\n\tint da = 0;\r\n\r\n\t// first iteration is used for collecting stat bonuses from items\r\n\tfor (Item &equipment : EquippedPlayerItemsRange(player)) {\r\n\t\tequipment._iStatFlag = true;\r\n\t\tif (equipment._iIdentified) {\r\n\t\t\tsa += equipment._iPLStr;\r\n\t\t\tma += equipment._iPLMag;\r\n\t\t\tda += equipment._iPLDex;\r\n\t\t}\r\n\t}\r\n\r\n\tbool changeflag;\r\n\tdo {\r\n\t\t// cap stats to 0\r\n\t\tconst int currstr = std::max(0, sa + player._pBaseStr);\r\n\t\tconst int currmag = std::max(0, ma + player._pBaseMag);\r\n\t\tconst int currdex = std::max(0, da + player._pBaseDex);\r\n\r\n\t\tchangeflag = false;\r\n\t\t// Iterate over equipped items and remove stat bonuses if they are not valid\r\n\t\tfor (Item &equipment : EquippedPlayerItemsRange(player)) {\r\n\t\t\tif (!equipment._iStatFlag)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tbool isValid = IsItemValid(player, equipment);\r\n\r\n\t\t\tif (currstr < equipment._iMinStr\r\n\t\t\t    || currmag < equipment._iMinMag\r\n\t\t\t    || currdex < equipment._iMinDex)\r\n\t\t\t\tisValid = false;\r\n\r\n\t\t\tif (isValid)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tchangeflag = true;\r\n\t\t\tequipment._iStatFlag = false;\r\n\t\t\tif (equipment._iIdentified) {\r\n\t\t\t\tsa -= equipment._iPLStr;\r\n\t\t\t\tma -= equipment._iPLMag;\r\n\t\t\t\tda -= equipment._iPLDex;\r\n\t\t\t}\r\n\t\t}\r\n\t} while (changeflag);\r\n}\r\n\r\nbool GetItemSpace(Point position, int8_t inum)\r\n{\r\n\tint xx = 0;\r\n\tint yy = 0;\r\n\tfor (int j = position.y - 1; j <= position.y + 1; j++) {\r\n\t\txx = 0;\r\n\t\tfor (int i = position.x - 1; i <= position.x + 1; i++) {\r\n\t\t\titemhold[xx][yy] = ItemSpaceOk({ i, j });\r\n\t\t\txx++;\r\n\t\t}\r\n\t\tyy++;\r\n\t}\r\n\r\n\tbool savail = false;\r\n\tfor (int j = 0; j < 3; j++) {\r\n\t\tfor (int i = 0; i < 3; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\tif (itemhold[i][j])\r\n\t\t\t\tsavail = true;\r\n\t\t}\r\n\t}\r\n\r\n\tint rs = GenerateRnd(15) + 1;\r\n\r\n\tif (!savail)\r\n\t\treturn false;\r\n\r\n\txx = 0;\r\n\tyy = 0;\r\n\twhile (rs > 0) {\r\n\t\tif (itemhold[xx][yy])\r\n\t\t\trs--;\r\n\t\tif (rs <= 0)\r\n\t\t\tcontinue;\r\n\t\txx++;\r\n\t\tif (xx != 3)\r\n\t\t\tcontinue;\r\n\t\txx = 0;\r\n\t\tyy++;\r\n\t\tif (yy == 3)\r\n\t\t\tyy = 0;\r\n\t}\r\n\r\n\txx += position.x - 1;\r\n\tyy += position.y - 1;\r\n\tItems[inum].position = { xx, yy };\r\n\tdItem[xx][yy] = static_cast<int8_t>(inum + 1);\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid CalcItemValue(Item &item)\r\n{\r\n\tint v = item._iVMult1 + item._iVMult2;\r\n\tif (v > 0) {\r\n\t\tv *= item._ivalue;\r\n\t}\r\n\tif (v < 0) {\r\n\t\tv = item._ivalue / v;\r\n\t}\r\n\tv = item._iVAdd1 + item._iVAdd2 + v;\r\n\titem._iIvalue = std::max(v, 1);\r\n}\r\n\r\nvoid GetBookSpell(Item &item, int lvl)\r\n{\r\n\tif (lvl == 0)\r\n\t\tlvl = 1;\r\n\r\n\tint rv = GenerateRnd(static_cast<int32_t>(SpellsData.size())) + 1;\r\n\r\n\tif (gbIsSpawn && lvl > 5)\r\n\t\tlvl = 5;\r\n\r\n\tint s = static_cast<int8_t>(SpellID::Firebolt);\r\n\tSpellID bs = SpellID::Firebolt;\r\n\twhile (rv > 0) {\r\n\t\tconst int sLevel = GetSpellBookLevel(static_cast<SpellID>(s));\r\n\t\tif (sLevel != -1 && lvl >= sLevel) {\r\n\t\t\trv--;\r\n\t\t\tbs = static_cast<SpellID>(s);\r\n\t\t}\r\n\t\ts++;\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tif (s == static_cast<int8_t>(SpellID::Resurrect))\r\n\t\t\t\ts = static_cast<int8_t>(SpellID::Telekinesis);\r\n\t\t}\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tif (s == static_cast<int8_t>(SpellID::HealOther))\r\n\t\t\t\ts = static_cast<int8_t>(SpellID::BloodStar);\r\n\t\t}\r\n\t\tif (static_cast<size_t>(s) == SpellsData.size())\r\n\t\t\ts = 1;\r\n\t}\r\n\tconst std::string_view spellName = GetSpellData(bs).sNameText;\r\n\tconst size_t iNameLen = std::string_view(item._iName).size();\r\n\tconst size_t iINameLen = std::string_view(item._iIName).size();\r\n\tCopyUtf8(item._iName + iNameLen, spellName, ItemNameLength - iNameLen);\r\n\tCopyUtf8(item._iIName + iINameLen, spellName, ItemNameLength - iINameLen);\r\n\titem._iSpell = bs;\r\n\tconst SpellData &spellData = GetSpellData(bs);\r\n\titem._iMinMag = spellData.minInt;\r\n\titem._ivalue += static_cast<int32_t>(spellData.bookCost());\r\n\titem._iIvalue += static_cast<int32_t>(spellData.bookCost());\r\n\tswitch (spellData.type()) {\r\n\tcase MagicType::Fire:\r\n\t\titem._iCurs = ICURS_BOOK_RED;\r\n\t\tbreak;\r\n\tcase MagicType::Lightning:\r\n\t\titem._iCurs = ICURS_BOOK_BLUE;\r\n\t\tbreak;\r\n\tcase MagicType::Magic:\r\n\t\titem._iCurs = ICURS_BOOK_GREY;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nint RndPL(int param1, int param2)\r\n{\r\n\treturn param1 + GenerateRnd(param2 - param1 + 1);\r\n}\r\n\r\nint CalculateToHitBonus(int level)\r\n{\r\n\tswitch (level) {\r\n\tcase -50:\r\n\t\treturn -RndPL(6, 10);\r\n\tcase -25:\r\n\t\treturn -RndPL(1, 5);\r\n\tcase 20:\r\n\t\treturn RndPL(1, 5);\r\n\tcase 36:\r\n\t\treturn RndPL(6, 10);\r\n\tcase 51:\r\n\t\treturn RndPL(11, 15);\r\n\tcase 66:\r\n\t\treturn RndPL(16, 20);\r\n\tcase 81:\r\n\t\treturn RndPL(21, 30);\r\n\tcase 96:\r\n\t\treturn RndPL(31, 40);\r\n\tcase 111:\r\n\t\treturn RndPL(41, 50);\r\n\tcase 126:\r\n\t\treturn RndPL(51, 75);\r\n\tcase 151:\r\n\t\treturn RndPL(76, 100);\r\n\tdefault:\r\n\t\tapp_fatal(\"Unknown to hit bonus\");\r\n\t}\r\n}\r\n\r\nint SaveItemPower(const Player &player, Item &item, ItemPower &power)\r\n{\r\n\tint r = RndPL(power.param1, power.param2);\r\n\r\n\tswitch (power.type) {\r\n\tcase IPL_TOHIT:\r\n\t\titem._iPLToHit += static_cast<int16_t>(r);\r\n\t\tbreak;\r\n\tcase IPL_TOHIT_CURSE:\r\n\t\titem._iPLToHit -= static_cast<int16_t>(r);\r\n\t\tbreak;\r\n\tcase IPL_DAMP:\r\n\t\titem._iPLDam += static_cast<int16_t>(r);\r\n\t\tbreak;\r\n\tcase IPL_DAMP_CURSE:\r\n\t\titem._iPLDam -= static_cast<int16_t>(r);\r\n\t\tbreak;\r\n\tcase IPL_DOPPELGANGER:\r\n\t\titem._iDamAcFlags |= ItemSpecialEffectHf::Doppelganger;\r\n\t\t[[fallthrough]];\r\n\tcase IPL_TOHIT_DAMP:\r\n\t\tr = RndPL(power.param1, power.param2);\r\n\t\titem._iPLDam += static_cast<int16_t>(r);\r\n\t\titem._iPLToHit += CalculateToHitBonus(power.param1);\r\n\t\tbreak;\r\n\tcase IPL_TOHIT_DAMP_CURSE:\r\n\t\titem._iPLDam -= static_cast<int16_t>(r);\r\n\t\titem._iPLToHit += CalculateToHitBonus(-power.param1);\r\n\t\tbreak;\r\n\tcase IPL_ACP:\r\n\t\titem._iPLAC += r;\r\n\t\tbreak;\r\n\tcase IPL_ACP_CURSE:\r\n\t\titem._iPLAC -= r;\r\n\t\tbreak;\r\n\tcase IPL_SETAC:\r\n\t\titem._iAC = r;\r\n\t\tbreak;\r\n\tcase IPL_AC_CURSE:\r\n\t\titem._iAC -= r;\r\n\t\tbreak;\r\n\tcase IPL_FIRERES:\r\n\t\titem._iPLFR += r;\r\n\t\tbreak;\r\n\tcase IPL_LIGHTRES:\r\n\t\titem._iPLLR += r;\r\n\t\tbreak;\r\n\tcase IPL_MAGICRES:\r\n\t\titem._iPLMR += r;\r\n\t\tbreak;\r\n\tcase IPL_ALLRES:\r\n\t\titem._iPLFR = std::max(item._iPLFR + r, 0);\r\n\t\titem._iPLLR = std::max(item._iPLLR + r, 0);\r\n\t\titem._iPLMR = std::max(item._iPLMR + r, 0);\r\n\t\tbreak;\r\n\tcase IPL_SPLLVLADD:\r\n\t\titem._iSplLvlAdd = r;\r\n\t\tbreak;\r\n\tcase IPL_CHARGES:\r\n\t\titem._iCharges *= power.param1;\r\n\t\titem._iMaxCharges = item._iCharges;\r\n\t\tbreak;\r\n\tcase IPL_SPELL:\r\n\t\titem._iSpell = static_cast<SpellID>(power.param1);\r\n\t\titem._iCharges = power.param2;\r\n\t\titem._iMaxCharges = power.param2;\r\n\t\tbreak;\r\n\tcase IPL_FIREDAM:\r\n\t\titem._iFlags |= ItemSpecialEffect::FireDamage;\r\n\t\titem._iFlags &= ~ItemSpecialEffect::LightningDamage;\r\n\t\titem._iFMinDam = power.param1;\r\n\t\titem._iFMaxDam = power.param2;\r\n\t\titem._iLMinDam = 0;\r\n\t\titem._iLMaxDam = 0;\r\n\t\tbreak;\r\n\tcase IPL_LIGHTDAM:\r\n\t\titem._iFlags |= ItemSpecialEffect::LightningDamage;\r\n\t\titem._iFlags &= ~ItemSpecialEffect::FireDamage;\r\n\t\titem._iLMinDam = power.param1;\r\n\t\titem._iLMaxDam = power.param2;\r\n\t\titem._iFMinDam = 0;\r\n\t\titem._iFMaxDam = 0;\r\n\t\tbreak;\r\n\tcase IPL_STR:\r\n\t\titem._iPLStr += r;\r\n\t\tbreak;\r\n\tcase IPL_STR_CURSE:\r\n\t\titem._iPLStr -= r;\r\n\t\tbreak;\r\n\tcase IPL_MAG:\r\n\t\titem._iPLMag += r;\r\n\t\tbreak;\r\n\tcase IPL_MAG_CURSE:\r\n\t\titem._iPLMag -= r;\r\n\t\tbreak;\r\n\tcase IPL_DEX:\r\n\t\titem._iPLDex += r;\r\n\t\tbreak;\r\n\tcase IPL_DEX_CURSE:\r\n\t\titem._iPLDex -= r;\r\n\t\tbreak;\r\n\tcase IPL_VIT:\r\n\t\titem._iPLVit += r;\r\n\t\tbreak;\r\n\tcase IPL_VIT_CURSE:\r\n\t\titem._iPLVit -= r;\r\n\t\tbreak;\r\n\tcase IPL_ATTRIBS:\r\n\t\titem._iPLStr += r;\r\n\t\titem._iPLMag += r;\r\n\t\titem._iPLDex += r;\r\n\t\titem._iPLVit += r;\r\n\t\tbreak;\r\n\tcase IPL_ATTRIBS_CURSE:\r\n\t\titem._iPLStr -= r;\r\n\t\titem._iPLMag -= r;\r\n\t\titem._iPLDex -= r;\r\n\t\titem._iPLVit -= r;\r\n\t\tbreak;\r\n\tcase IPL_GETHIT_CURSE:\r\n\t\titem._iPLGetHit += r;\r\n\t\tbreak;\r\n\tcase IPL_GETHIT:\r\n\t\titem._iPLGetHit -= r;\r\n\t\tbreak;\r\n\tcase IPL_LIFE:\r\n\t\titem._iPLHP += r << 6;\r\n\t\tbreak;\r\n\tcase IPL_LIFE_CURSE:\r\n\t\titem._iPLHP -= r << 6;\r\n\t\tbreak;\r\n\tcase IPL_MANA:\r\n\t\titem._iPLMana += r << 6;\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\tbreak;\r\n\tcase IPL_MANA_CURSE:\r\n\t\titem._iPLMana -= r << 6;\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\tbreak;\r\n\tcase IPL_DUR: {\r\n\t\tconst int bonus = r * item._iMaxDur / 100;\r\n\t\titem._iMaxDur += bonus;\r\n\t\titem._iDurability += bonus;\r\n\t} break;\r\n\tcase IPL_CRYSTALLINE:\r\n\t\titem._iPLDam += 140 + r * 2;\r\n\t\t[[fallthrough]];\r\n\tcase IPL_DUR_CURSE:\r\n\t\titem._iMaxDur -= r * item._iMaxDur / 100;\r\n\t\titem._iMaxDur = std::max<uint8_t>(item._iMaxDur, 1);\r\n\t\titem._iDurability = item._iMaxDur;\r\n\t\tbreak;\r\n\tcase IPL_INDESTRUCTIBLE:\r\n\t\titem._iDurability = DUR_INDESTRUCTIBLE;\r\n\t\titem._iMaxDur = DUR_INDESTRUCTIBLE;\r\n\t\tbreak;\r\n\tcase IPL_LIGHT:\r\n\t\titem._iPLLight += power.param1;\r\n\t\tbreak;\r\n\tcase IPL_LIGHT_CURSE:\r\n\t\titem._iPLLight -= power.param1;\r\n\t\tbreak;\r\n\tcase IPL_MULT_ARROWS:\r\n\t\titem._iFlags |= ItemSpecialEffect::MultipleArrows;\r\n\t\tbreak;\r\n\tcase IPL_FIRE_ARROWS:\r\n\t\titem._iFlags |= (ItemSpecialEffect::FireArrows | ItemSpecialEffect::FireDamage);\r\n\t\titem._iFlags &= ~ItemSpecialEffect::LightningArrows;\r\n\t\titem._iFMinDam = power.param1;\r\n\t\titem._iFMaxDam = power.param2;\r\n\t\titem._iLMinDam = 0;\r\n\t\titem._iLMaxDam = 0;\r\n\t\tbreak;\r\n\tcase IPL_LIGHT_ARROWS:\r\n\t\titem._iFlags |= (ItemSpecialEffect::LightningArrows | ItemSpecialEffect::LightningDamage);\r\n\t\titem._iFlags &= ~ItemSpecialEffect::FireArrows;\r\n\t\titem._iLMinDam = power.param1;\r\n\t\titem._iLMaxDam = power.param2;\r\n\t\titem._iFMinDam = 0;\r\n\t\titem._iFMaxDam = 0;\r\n\t\tbreak;\r\n\tcase IPL_FIREBALL:\r\n\t\titem._iFlags |= (ItemSpecialEffect::LightningArrows | ItemSpecialEffect::FireArrows);\r\n\t\titem._iFMinDam = power.param1;\r\n\t\titem._iFMaxDam = power.param2;\r\n\t\titem._iLMinDam = 0;\r\n\t\titem._iLMaxDam = 0;\r\n\t\tbreak;\r\n\tcase IPL_THORNS:\r\n\t\titem._iFlags |= ItemSpecialEffect::Thorns;\r\n\t\tbreak;\r\n\tcase IPL_NOMANA:\r\n\t\titem._iFlags |= ItemSpecialEffect::NoMana;\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\tbreak;\r\n\tcase IPL_ABSHALFTRAP:\r\n\t\titem._iFlags |= ItemSpecialEffect::HalfTrapDamage;\r\n\t\tbreak;\r\n\tcase IPL_KNOCKBACK:\r\n\t\titem._iFlags |= ItemSpecialEffect::Knockback;\r\n\t\tbreak;\r\n\tcase IPL_3XDAMVDEM:\r\n\t\titem._iFlags |= ItemSpecialEffect::TripleDemonDamage;\r\n\t\tbreak;\r\n\tcase IPL_ALLRESZERO:\r\n\t\titem._iFlags |= ItemSpecialEffect::ZeroResistance;\r\n\t\tbreak;\r\n\tcase IPL_STEALMANA:\r\n\t\tif (power.param1 == 3)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::StealMana3;\r\n\t\tif (power.param1 == 5)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::StealMana5;\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\tbreak;\r\n\tcase IPL_STEALLIFE:\r\n\t\tif (power.param1 == 3)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::StealLife3;\r\n\t\tif (power.param1 == 5)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::StealLife5;\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t\tbreak;\r\n\tcase IPL_TARGAC:\r\n\t\tif (gbIsHellfire)\r\n\t\t\titem._iPLEnAc = power.param1;\r\n\t\telse\r\n\t\t\titem._iPLEnAc += r;\r\n\t\tbreak;\r\n\tcase IPL_FASTATTACK:\r\n\t\tif (power.param1 == 1)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::QuickAttack;\r\n\t\tif (power.param1 == 2)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::FastAttack;\r\n\t\tif (power.param1 == 3)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::FasterAttack;\r\n\t\tif (power.param1 == 4)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::FastestAttack;\r\n\t\tbreak;\r\n\tcase IPL_FASTRECOVER:\r\n\t\tif (power.param1 == 1)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::FastHitRecovery;\r\n\t\tif (power.param1 == 2)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::FasterHitRecovery;\r\n\t\tif (power.param1 == 3)\r\n\t\t\titem._iFlags |= ItemSpecialEffect::FastestHitRecovery;\r\n\t\tbreak;\r\n\tcase IPL_FASTBLOCK:\r\n\t\titem._iFlags |= ItemSpecialEffect::FastBlock;\r\n\t\tbreak;\r\n\tcase IPL_DAMMOD:\r\n\t\titem._iPLDamMod += r;\r\n\t\tbreak;\r\n\tcase IPL_RNDARROWVEL:\r\n\t\titem._iFlags |= ItemSpecialEffect::RandomArrowVelocity;\r\n\t\tbreak;\r\n\tcase IPL_SETDAM:\r\n\t\titem._iMinDam = power.param1;\r\n\t\titem._iMaxDam = power.param2;\r\n\t\tbreak;\r\n\tcase IPL_SETDUR:\r\n\t\titem._iDurability = power.param1;\r\n\t\titem._iMaxDur = power.param1;\r\n\t\tbreak;\r\n\tcase IPL_ONEHAND:\r\n\t\titem._iLoc = ILOC_ONEHAND;\r\n\t\tbreak;\r\n\tcase IPL_DRAINLIFE:\r\n\t\titem._iFlags |= ItemSpecialEffect::DrainLife;\r\n\t\tbreak;\r\n\tcase IPL_RNDSTEALLIFE:\r\n\t\titem._iFlags |= ItemSpecialEffect::RandomStealLife;\r\n\t\tbreak;\r\n\tcase IPL_NOMINSTR:\r\n\t\titem._iMinStr = 0;\r\n\t\tbreak;\r\n\tcase IPL_ADDACLIFE:\r\n\t\titem._iFlags |= (ItemSpecialEffect::LightningArrows | ItemSpecialEffect::FireArrows);\r\n\t\titem._iFMinDam = power.param1;\r\n\t\titem._iFMaxDam = power.param2;\r\n\t\titem._iLMinDam = 1;\r\n\t\titem._iLMaxDam = 0;\r\n\t\tbreak;\r\n\tcase IPL_ADDMANAAC:\r\n\t\titem._iFlags |= (ItemSpecialEffect::LightningDamage | ItemSpecialEffect::FireDamage);\r\n\t\titem._iFMinDam = power.param1;\r\n\t\titem._iFMaxDam = power.param2;\r\n\t\titem._iLMinDam = 2;\r\n\t\titem._iLMaxDam = 0;\r\n\t\tbreak;\r\n\tcase IPL_FIRERES_CURSE:\r\n\t\titem._iPLFR -= r;\r\n\t\tbreak;\r\n\tcase IPL_LIGHTRES_CURSE:\r\n\t\titem._iPLLR -= r;\r\n\t\tbreak;\r\n\tcase IPL_MAGICRES_CURSE:\r\n\t\titem._iPLMR -= r;\r\n\t\tbreak;\r\n\tcase IPL_DEVASTATION:\r\n\t\titem._iDamAcFlags |= ItemSpecialEffectHf::Devastation;\r\n\t\tbreak;\r\n\tcase IPL_DECAY:\r\n\t\titem._iDamAcFlags |= ItemSpecialEffectHf::Decay;\r\n\t\titem._iPLDam += r;\r\n\t\tbreak;\r\n\tcase IPL_PERIL:\r\n\t\titem._iDamAcFlags |= ItemSpecialEffectHf::Peril;\r\n\t\tbreak;\r\n\tcase IPL_JESTERS:\r\n\t\titem._iDamAcFlags |= ItemSpecialEffectHf::Jesters;\r\n\t\tbreak;\r\n\tcase IPL_ACDEMON:\r\n\t\titem._iDamAcFlags |= ItemSpecialEffectHf::ACAgainstDemons;\r\n\t\tbreak;\r\n\tcase IPL_ACUNDEAD:\r\n\t\titem._iDamAcFlags |= ItemSpecialEffectHf::ACAgainstUndead;\r\n\t\tbreak;\r\n\tcase IPL_MANATOLIFE: {\r\n\t\tconst int portion = ((player._pMaxManaBase >> 6) * 50 / 100) << 6;\r\n\t\titem._iPLMana -= portion;\r\n\t\titem._iPLHP += portion;\r\n\t} break;\r\n\tcase IPL_LIFETOMANA: {\r\n\t\tconst int portion = ((player._pMaxHPBase >> 6) * 40 / 100) << 6;\r\n\t\titem._iPLHP -= portion;\r\n\t\titem._iPLMana += portion;\r\n\t} break;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn r;\r\n}\r\n\r\nbool StringInPanel(const char *str)\r\n{\r\n\treturn GetLineWidth(str, GameFont12, 2) < 254;\r\n}\r\n\r\nint PLVal(int pv, int p1, int p2, int minv, int maxv)\r\n{\r\n\tif (p1 == p2)\r\n\t\treturn minv;\r\n\tif (minv == maxv)\r\n\t\treturn minv;\r\n\treturn minv + ((maxv - minv) * (100 * (pv - p1) / (p2 - p1)) / 100);\r\n}\r\n\r\nvoid SaveItemAffix(const Player &player, Item &item, const PLStruct &affix)\r\n{\r\n\tauto power = affix.power;\r\n\tint value = SaveItemPower(player, item, power);\r\n\r\n\tvalue = PLVal(value, power.param1, power.param2, affix.minVal, affix.maxVal);\r\n\tif (item._iVAdd1 != 0 || item._iVMult1 != 0) {\r\n\t\titem._iVAdd2 = value;\r\n\t\titem._iVMult2 = affix.multVal;\r\n\t} else {\r\n\t\titem._iVAdd1 = value;\r\n\t\titem._iVMult1 = affix.multVal;\r\n\t}\r\n}\r\n\r\nstd::optional<const PLStruct *> SelectAffix(\r\n    const std::vector<PLStruct> &affixList,\r\n    AffixItemType type,\r\n    int minlvl, int maxlvl,\r\n    bool onlygood,\r\n    goodorevil goe,\r\n    bool excludeChargesForStaffs)\r\n{\r\n\tStaticVector<const PLStruct *, 256> eligibleAffixes;\r\n\r\n\tfor (const PLStruct &affix : affixList) {\r\n\t\tif (!HasAnyOf(type, affix.PLIType))\r\n\t\t\tcontinue;\r\n\t\tif (affix.PLMinLvl < minlvl || affix.PLMinLvl > maxlvl)\r\n\t\t\tcontinue;\r\n\t\tif (onlygood && !affix.PLOk)\r\n\t\t\tcontinue;\r\n\t\tif ((goe == GOE_GOOD && affix.PLGOE == GOE_EVIL) || (goe == GOE_EVIL && affix.PLGOE == GOE_GOOD))\r\n\t\t\tcontinue;\r\n\t\tif (excludeChargesForStaffs && type == AffixItemType::Staff && affix.power.type == IPL_CHARGES)\r\n\t\t\tcontinue;\r\n\r\n\t\tfor (int i = 0; i < affix.PLChance; ++i) {\r\n\t\t\teligibleAffixes.push_back(&affix);\r\n\t\t}\r\n\t}\r\n\r\n\tif (eligibleAffixes.empty())\r\n\t\treturn std::nullopt;\r\n\r\n\treturn eligibleAffixes[GenerateRnd(static_cast<int>(eligibleAffixes.size()))];\r\n}\r\n\r\nstd::optional<const PLStruct *> GetStaffPrefix(int maxlvl, bool onlygood)\r\n{\r\n\tif (!FlipCoin(10) && !onlygood) {\r\n\t\treturn std::nullopt;\r\n\t}\r\n\r\n\treturn SelectAffix(ItemPrefixes, AffixItemType::Staff, 0, maxlvl, onlygood, GOE_ANY, false);\r\n}\r\n\r\nstd::string GenerateStaffName(const ItemData &baseItemData, SpellID spellId, bool translate)\r\n{\r\n\tstd::string_view baseName = translate ? _(baseItemData.iName) : baseItemData.iName;\r\n\tstd::string_view spellName = translate ? pgettext(\"spell\", GetSpellData(spellId).sNameText) : GetSpellData(spellId).sNameText;\r\n\tconst std::string_view normalFmt = translate ? pgettext(\"spell\", /* TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall */ \"{0} of {1}\") : \"{0} of {1}\";\r\n\tstd::string name = fmt::format(fmt::runtime(normalFmt), baseName, spellName);\r\n\tif (!StringInPanel(name.c_str())) {\r\n\t\tstd::string_view shortName = translate ? _(baseItemData.iSName) : baseItemData.iSName;\r\n\t\tname = fmt::format(fmt::runtime(normalFmt), shortName, spellName);\r\n\t}\r\n\treturn name;\r\n}\r\n\r\nstd::string GenerateStaffNameMagical(const ItemData &baseItemData, SpellID spellId, const PLStruct &power, bool translate, std::optional<bool> forceNameLengthCheck)\r\n{\r\n\tstd::string_view baseName = translate ? _(baseItemData.iName) : baseItemData.iName;\r\n\tconst std::string_view magicFmt = translate ? pgettext(\"spell\", /* TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall */ \"{0} {1} of {2}\") : \"{0} {1} of {2}\";\r\n\tstd::string_view spellName = translate ? pgettext(\"spell\", GetSpellData(spellId).sNameText) : GetSpellData(spellId).sNameText;\r\n\tstd::string_view prefixName = translate ? _(power.PLName) : power.PLName;\r\n\r\n\tstd::string identifiedName = fmt::format(fmt::runtime(magicFmt), prefixName, baseName, spellName);\r\n\tif (forceNameLengthCheck ? *forceNameLengthCheck : !StringInPanel(identifiedName.c_str())) {\r\n\t\tstd::string_view shortName = translate ? _(baseItemData.iSName) : baseItemData.iSName;\r\n\t\tidentifiedName = fmt::format(fmt::runtime(magicFmt), prefixName, shortName, spellName);\r\n\t}\r\n\treturn identifiedName;\r\n}\r\n\r\nvoid GetStaffPower(const Player &player, Item &item, int maxlvl, bool onlygood)\r\n{\r\n\tstd::optional<const PLStruct *> prefix = GetStaffPrefix(maxlvl, onlygood);\r\n\tif (prefix.has_value()) {\r\n\t\titem._iMagical = ITEM_QUALITY_MAGIC;\r\n\t\tSaveItemAffix(player, item, **prefix);\r\n\t\titem._iPrePower = (*prefix)->power.type;\r\n\t}\r\n\r\n\tconst ItemData &baseItemData = AllItemsList[item.IDidx];\r\n\tconst std::string staffName = GenerateStaffName(baseItemData, item._iSpell, false);\r\n\r\n\tCopyUtf8(item._iName, staffName, ItemNameLength);\r\n\tif (prefix.has_value()) {\r\n\t\tconst std::string staffNameMagical = GenerateStaffNameMagical(baseItemData, item._iSpell, **prefix, false, std::nullopt);\r\n\t\tCopyUtf8(item._iIName, staffNameMagical, ItemNameLength);\r\n\t} else {\r\n\t\tCopyUtf8(item._iIName, item._iName, ItemNameLength);\r\n\t}\r\n\r\n\tCalcItemValue(item);\r\n}\r\n\r\nstd::string GenerateMagicItemName(const std::string_view &baseNamel, const PLStruct *pPrefix, const PLStruct *pSufix, bool translate)\r\n{\r\n\tif (pPrefix != nullptr && pSufix != nullptr) {\r\n\t\tconst std::string_view fmt = translate ? _(/* TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale */ \"{0} {1} of {2}\") : \"{0} {1} of {2}\";\r\n\t\treturn fmt::format(fmt::runtime(fmt), translate ? _(pPrefix->PLName) : pPrefix->PLName, baseNamel, translate ? _(pSufix->PLName) : pSufix->PLName);\r\n\t}\r\n\tif (pPrefix != nullptr) {\r\n\t\tconst std::string_view fmt = translate ? _(/* TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword */ \"{0} {1}\") : \"{0} {1}\";\r\n\t\treturn fmt::format(fmt::runtime(fmt), translate ? _(pPrefix->PLName) : pPrefix->PLName, baseNamel);\r\n\t}\r\n\tif (pSufix != nullptr) {\r\n\t\tconst std::string_view fmt = translate ? _(/* TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale */ \"{0} of {1}\") : \"{0} of {1}\";\r\n\t\treturn fmt::format(fmt::runtime(fmt), baseNamel, translate ? _(pSufix->PLName) : pSufix->PLName);\r\n\t}\r\n\r\n\treturn std::string(baseNamel);\r\n}\r\n\r\nvoid GetItemPowerPrefixAndSuffix(\r\n    int minlvl, int maxlvl,\r\n    AffixItemType flgs,\r\n    bool onlygood,\r\n    tl::function_ref<void(const PLStruct &prefix)> prefixFound,\r\n    tl::function_ref<void(const PLStruct &suffix)> suffixFound)\r\n{\r\n\tbool allocatePrefix = FlipCoin(4);\r\n\tbool allocateSuffix = !FlipCoin(3);\r\n\tif (!allocatePrefix && !allocateSuffix) {\r\n\t\t// At least try and give each item a prefix or suffix\r\n\t\tif (FlipCoin())\r\n\t\t\tallocatePrefix = true;\r\n\t\telse\r\n\t\t\tallocateSuffix = true;\r\n\t}\r\n\tgoodorevil goe = GOE_ANY;\r\n\tif (!onlygood && !FlipCoin(3))\r\n\t\tonlygood = true;\r\n\r\n\tif (allocatePrefix) {\r\n\t\tstd::optional<const PLStruct *> prefix = SelectAffix(ItemPrefixes, flgs, minlvl, maxlvl, onlygood, goe, true);\r\n\t\tif (prefix.has_value()) {\r\n\t\t\tgoe = (*prefix)->PLGOE;\r\n\t\t\tprefixFound(**prefix);\r\n\t\t}\r\n\t}\r\n\r\n\tif (allocateSuffix) {\r\n\t\tstd::optional<const PLStruct *> suffix = SelectAffix(ItemSuffixes, flgs, minlvl, maxlvl, onlygood, goe, true);\r\n\t\tif (suffix.has_value()) {\r\n\t\t\tsuffixFound(**suffix);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid GetItemPower(const Player &player, Item &item, int minlvl, int maxlvl, AffixItemType flgs, bool onlygood)\r\n{\r\n\tconst PLStruct *pPrefix = nullptr;\r\n\tconst PLStruct *pSufix = nullptr;\r\n\tGetItemPowerPrefixAndSuffix(\r\n\t    minlvl, maxlvl, flgs, onlygood,\r\n\t    [&item, &player, &pPrefix](const PLStruct &prefix) {\r\n\t\t    item._iMagical = ITEM_QUALITY_MAGIC;\r\n\t\t    SaveItemAffix(player, item, prefix);\r\n\t\t    item._iPrePower = prefix.power.type;\r\n\t\t    pPrefix = &prefix;\r\n\t    },\r\n\t    [&item, &player, &pSufix](const PLStruct &suffix) {\r\n\t\t    item._iMagical = ITEM_QUALITY_MAGIC;\r\n\t\t    SaveItemAffix(player, item, suffix);\r\n\t\t    item._iSufPower = suffix.power.type;\r\n\t\t    pSufix = &suffix;\r\n\t    });\r\n\r\n\tCopyUtf8(item._iIName, GenerateMagicItemName(item._iName, pPrefix, pSufix, false), ItemNameLength);\r\n\tif (!StringInPanel(item._iIName)) {\r\n\t\tCopyUtf8(item._iIName, GenerateMagicItemName(AllItemsList[item.IDidx].iSName, pPrefix, pSufix, false), ItemNameLength);\r\n\t}\r\n\tif (pPrefix != nullptr || pSufix != nullptr)\r\n\t\tCalcItemValue(item);\r\n}\r\n\r\nvoid GetStaffSpell(const Player &player, Item &item, int lvl, bool onlygood)\r\n{\r\n\tif (!gbIsHellfire && FlipCoin(4)) {\r\n\t\tGetItemPower(player, item, lvl / 2, lvl, AffixItemType::Staff, onlygood);\r\n\t\treturn;\r\n\t}\r\n\r\n\tint l = lvl / 2;\r\n\tif (l == 0)\r\n\t\tl = 1;\r\n\tint rv = GenerateRnd(static_cast<int32_t>(SpellsData.size())) + 1;\r\n\r\n\tif (gbIsSpawn && lvl > 10)\r\n\t\tlvl = 10;\r\n\r\n\tint s = static_cast<int8_t>(SpellID::Firebolt);\r\n\tSpellID bs = SpellID::Null;\r\n\twhile (rv > 0) {\r\n\t\tconst int sLevel = GetSpellStaffLevel(static_cast<SpellID>(s));\r\n\t\tif (sLevel != -1 && l >= sLevel) {\r\n\t\t\trv--;\r\n\t\t\tbs = static_cast<SpellID>(s);\r\n\t\t}\r\n\t\ts++;\r\n\t\tif (!gbIsMultiplayer && s == static_cast<int8_t>(SpellID::Resurrect))\r\n\t\t\ts = static_cast<int8_t>(SpellID::Telekinesis);\r\n\t\tif (!gbIsMultiplayer && s == static_cast<int8_t>(SpellID::HealOther))\r\n\t\t\ts = static_cast<int8_t>(SpellID::BloodStar);\r\n\t\tif (static_cast<size_t>(s) == SpellsData.size())\r\n\t\t\ts = static_cast<int8_t>(SpellID::Firebolt);\r\n\t}\r\n\r\n\tconst int minc = GetSpellData(bs).sStaffMin;\r\n\tconst int maxc = GetSpellData(bs).sStaffMax - minc + 1;\r\n\titem._iSpell = bs;\r\n\titem._iCharges = minc + GenerateRnd(maxc);\r\n\titem._iMaxCharges = item._iCharges;\r\n\r\n\titem._iMinMag = GetSpellData(bs).minInt;\r\n\tconst int v = item._iCharges * GetSpellData(bs).staffCost() / 5;\r\n\titem._ivalue += v;\r\n\titem._iIvalue += v;\r\n\tGetStaffPower(player, item, lvl, onlygood);\r\n}\r\n\r\nvoid GetOilType(Item &item, int maxLvl)\r\n{\r\n\tint cnt = 2;\r\n\tint8_t rnd[32] = { 5, 6 };\r\n\r\n\tif (!gbIsMultiplayer) {\r\n\t\tif (maxLvl == 0)\r\n\t\t\tmaxLvl = 1;\r\n\r\n\t\tcnt = 0;\r\n\t\tfor (size_t j = 0; j < sizeof(OilLevels) / sizeof(OilLevels[0]); j++) {\r\n\t\t\tif (OilLevels[j] <= maxLvl) {\r\n\t\t\t\trnd[cnt] = static_cast<int8_t>(j);\r\n\t\t\t\tcnt++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconst int8_t t = rnd[GenerateRnd(cnt)];\r\n\r\n\tCopyUtf8(item._iName, OilNames[t], ItemNameLength);\r\n\tCopyUtf8(item._iIName, OilNames[t], ItemNameLength);\r\n\titem._iMiscId = OilMagic[t];\r\n\titem._ivalue = OilValues[t];\r\n\titem._iIvalue = OilValues[t];\r\n}\r\n\r\nvoid GetItemBonus(const Player &player, Item &item, int minlvl, int maxlvl, bool onlygood, bool allowspells)\r\n{\r\n\tminlvl = std::min(minlvl, 25);\r\n\r\n\tswitch (item._itype) {\r\n\tcase ItemType::Sword:\r\n\tcase ItemType::Axe:\r\n\tcase ItemType::Mace:\r\n\t\tGetItemPower(player, item, minlvl, maxlvl, AffixItemType::Weapon, onlygood);\r\n\t\tbreak;\r\n\tcase ItemType::Bow:\r\n\t\tGetItemPower(player, item, minlvl, maxlvl, AffixItemType::Bow, onlygood);\r\n\t\tbreak;\r\n\tcase ItemType::Shield:\r\n\t\tGetItemPower(player, item, minlvl, maxlvl, AffixItemType::Shield, onlygood);\r\n\t\tbreak;\r\n\tcase ItemType::LightArmor:\r\n\tcase ItemType::Helm:\r\n\tcase ItemType::MediumArmor:\r\n\tcase ItemType::HeavyArmor:\r\n\t\tGetItemPower(player, item, minlvl, maxlvl, AffixItemType::Armor, onlygood);\r\n\t\tbreak;\r\n\tcase ItemType::Staff:\r\n\t\tif (allowspells)\r\n\t\t\tGetStaffSpell(player, item, maxlvl, onlygood);\r\n\t\telse\r\n\t\t\tGetItemPower(player, item, minlvl, maxlvl, AffixItemType::Staff, onlygood);\r\n\t\tbreak;\r\n\tcase ItemType::Ring:\r\n\tcase ItemType::Amulet:\r\n\t\tGetItemPower(player, item, minlvl, maxlvl, AffixItemType::Misc, onlygood);\r\n\t\tbreak;\r\n\tcase ItemType::None:\r\n\tcase ItemType::Misc:\r\n\tcase ItemType::Gold:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nstruct WeightedItemIndex {\r\n\t_item_indexes index;\r\n\tunsigned cumulativeWeight;\r\n};\r\n\r\n_item_indexes GetItemIndexForDroppableItem(bool considerDropRate, tl::function_ref<bool(const ItemData &item)> isItemOkay)\r\n{\r\n\tstatic std::vector<WeightedItemIndex> ril;\r\n\tril.clear();\r\n\r\n\tunsigned cumulativeWeight = 0;\r\n\tfor (size_t i = 0; i < AllItemsList.size(); i++) {\r\n\t\tif (!IsItemAvailable(static_cast<int>(i)))\r\n\t\t\tcontinue;\r\n\t\tconst ItemData &item = AllItemsList[i];\r\n\t\tif (item.dropRate == 0)\r\n\t\t\tcontinue;\r\n\t\tif (IsAnyOf(item.iSpell, SpellID::Resurrect, SpellID::HealOther) && !gbIsMultiplayer)\r\n\t\t\tcontinue;\r\n\t\tif (!isItemOkay(item))\r\n\t\t\tcontinue;\r\n\t\tcumulativeWeight += considerDropRate ? item.dropRate : 1;\r\n\t\tril.push_back({ static_cast<_item_indexes>(i), cumulativeWeight });\r\n\t}\r\n\tconst auto targetWeight = static_cast<unsigned>(RandomIntLessThan(static_cast<int>(cumulativeWeight)));\r\n\treturn std::upper_bound(ril.begin(), ril.end(), targetWeight, [](unsigned target, const WeightedItemIndex &value) { return target < value.cumulativeWeight; })->index;\r\n}\r\n\r\n_item_indexes RndUItem(Monster *monster)\r\n{\r\n\tint itemMaxLevel = ItemsGetCurrlevel() * 2;\r\n\tif (monster != nullptr)\r\n\t\titemMaxLevel = monster->level(sgGameInitInfo.nDifficulty);\r\n\treturn GetItemIndexForDroppableItem(false, [&itemMaxLevel](const ItemData &item) {\r\n\t\tif (item.itype == ItemType::Misc && item.iMiscId == IMISC_BOOK)\r\n\t\t\treturn true;\r\n\t\tif (itemMaxLevel < item.iMinMLvl)\r\n\t\t\treturn false;\r\n\t\tif (IsAnyOf(item.itype, ItemType::Gold, ItemType::Misc))\r\n\t\t\treturn false;\r\n\t\treturn true;\r\n\t});\r\n}\r\n\r\n_item_indexes RndAllItems()\r\n{\r\n\tif (GenerateRnd(100) > 25)\r\n\t\treturn IDI_GOLD;\r\n\r\n\tint itemMaxLevel = ItemsGetCurrlevel() * 2;\r\n\treturn GetItemIndexForDroppableItem(false, [&itemMaxLevel](const ItemData &item) {\r\n\t\tif (itemMaxLevel < item.iMinMLvl)\r\n\t\t\treturn false;\r\n\t\treturn true;\r\n\t});\r\n}\r\n\r\n_item_indexes RndTypeItems(ItemType itemType, int imid, int lvl)\r\n{\r\n\tint itemMaxLevel = lvl * 2;\r\n\treturn GetItemIndexForDroppableItem(false, [&itemMaxLevel, &itemType, &imid](const ItemData &item) {\r\n\t\tif (itemMaxLevel < item.iMinMLvl)\r\n\t\t\treturn false;\r\n\t\tif (item.itype != itemType)\r\n\t\t\treturn false;\r\n\t\tif (imid != -1 && item.iMiscId != imid)\r\n\t\t\treturn false;\r\n\t\treturn true;\r\n\t});\r\n}\r\n\r\nstd::vector<uint8_t> GetValidUniques(int lvl, unique_base_item baseItemId)\r\n{\r\n\tstd::vector<uint8_t> validUniques;\r\n\tint index = 0;\r\n\tfor (const UniqueItem &itemData : UniqueItems) {\r\n\t\tif (itemData.UIItemId == baseItemId && lvl >= itemData.UIMinLvl) {\r\n\t\t\tvalidUniques.push_back(index);\r\n\t\t}\r\n\t\tindex++;\r\n\t}\r\n\treturn validUniques;\r\n}\r\n\r\n_unique_items CheckUnique(Item &item, int lvl, int uper, int uidOffset = 0)\r\n{\r\n\tif (GenerateRnd(100) > uper)\r\n\t\treturn UITEM_INVALID;\r\n\r\n\tauto validUniques = GetValidUniques(lvl, AllItemsList[item.IDidx].iItemId);\r\n\r\n\tif (validUniques.empty())\r\n\t\treturn UITEM_INVALID;\r\n\r\n\tDiscardRandomValues(1);\r\n\r\n\t// Check if uidOffset is out of bounds\r\n\tif (static_cast<size_t>(uidOffset) >= validUniques.size()) {\r\n\t\treturn UITEM_INVALID;\r\n\t}\r\n\r\n\tconst uint8_t selectedUniqueIndex = validUniques[validUniques.size() - 1 - uidOffset];\r\n\r\n\treturn static_cast<_unique_items>(selectedUniqueIndex);\r\n}\r\n\r\nvoid GetUniqueItem(const Player &player, Item &item, _unique_items uid)\r\n{\r\n\tconst auto &uniqueItemData = UniqueItems[uid];\r\n\r\n\tfor (auto power : uniqueItemData.powers) {\r\n\t\tif (power.type == IPL_INVALID)\r\n\t\t\tbreak;\r\n\t\tSaveItemPower(player, item, power);\r\n\t}\r\n\r\n\tCopyUtf8(item._iIName, uniqueItemData.UIName, ItemNameLength);\r\n\tif (uniqueItemData.UICurs != ICURS_DEFAULT)\r\n\t\titem._iCurs = uniqueItemData.UICurs;\r\n\titem._iIvalue = uniqueItemData.UIValue;\r\n\r\n\tif (item._iMiscId == IMISC_UNIQUE)\r\n\t\titem._iSeed = uid;\r\n\r\n\titem._iUid = uid;\r\n\titem._iMagical = ITEM_QUALITY_UNIQUE;\r\n\titem._iCreateInfo |= CF_UNIQUE;\r\n}\r\n\r\nvoid ItemRndDur(Item &item)\r\n{\r\n\tif (item._iDurability > 0 && item._iDurability != DUR_INDESTRUCTIBLE)\r\n\t\titem._iDurability = GenerateRnd(item._iMaxDur / 2) + (item._iMaxDur / 4) + 1;\r\n}\r\n\r\nint GetItemBLevel(int lvl, item_misc_id miscId, bool onlygood, bool uper15)\r\n{\r\n\tint iblvl = -1;\r\n\tif (GenerateRnd(100) <= 10\r\n\t    || GenerateRnd(100) <= lvl\r\n\t    || onlygood\r\n\t    || IsAnyOf(miscId, IMISC_STAFF, IMISC_RING, IMISC_AMULET)) {\r\n\t\tiblvl = lvl;\r\n\t}\r\n\tif (uper15)\r\n\t\tiblvl = lvl + 4;\r\n\treturn iblvl;\r\n}\r\n\r\nvoid SetupBaseItem(Point position, _item_indexes idx, bool onlygood, bool sendmsg, bool delta, bool spawn = false)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\tGetSuperItemSpace(position, ii);\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\r\n\tSetupAllItems(*MyPlayer, item, idx, AdvanceRndSeed(), 2 * curlv, 1, onlygood, delta);\r\n\tTryRandomUniqueItem(item, idx, 2 * curlv, 1, onlygood, delta);\r\n\tSetupItem(item);\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdPItem(false, CMD_DROPITEM, item.position, item);\r\n\tif (delta)\r\n\t\tDeltaAddItem(ii);\r\n\tif (spawn)\r\n\t\tNetSendCmdPItem(false, CMD_SPAWNITEM, item.position, item);\r\n}\r\n\r\nvoid SetupAllUseful(Item &item, int iseed, int lvl)\r\n{\r\n\titem._iSeed = iseed;\r\n\tSetRndSeed(iseed);\r\n\r\n\t_item_indexes idx;\r\n\r\n\tif (gbIsHellfire) {\r\n\t\tswitch (GenerateRnd(7)) {\r\n\t\tcase 0:\r\n\t\t\tidx = IDI_PORTAL;\r\n\t\t\tif (lvl <= 1)\r\n\t\t\t\tidx = IDI_HEAL;\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\tcase 2:\r\n\t\t\tidx = IDI_HEAL;\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tidx = IDI_PORTAL;\r\n\t\t\tif (lvl <= 1)\r\n\t\t\t\tidx = IDI_MANA;\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\tcase 5:\r\n\t\t\tidx = IDI_MANA;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tidx = IDI_OIL;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} else {\r\n\t\tidx = PickRandomlyAmong({ IDI_MANA, IDI_HEAL });\r\n\r\n\t\tif (lvl > 1 && FlipCoin(3))\r\n\t\t\tidx = IDI_PORTAL;\r\n\t}\r\n\r\n\tGetItemAttrs(item, idx, lvl);\r\n\titem._iCreateInfo = lvl | CF_USEFUL;\r\n\tSetupItem(item);\r\n}\r\n\r\nuint8_t Char2int(uint8_t input)\r\n{\r\n\tif (input >= '0' && input <= '9')\r\n\t\treturn input - '0';\r\n\tif (input >= 'A' && input <= 'F')\r\n\t\treturn input - 'A' + 10;\r\n\treturn 0;\r\n}\r\n\r\nvoid Hex2bin(const char *src, int bytes, uint8_t *target)\r\n{\r\n\tfor (int i = 0; i < bytes; i++, src += 2) {\r\n\t\ttarget[i] = (Char2int(src[0]) << 4) | Char2int(src[1]);\r\n\t}\r\n}\r\n\r\nvoid SpawnRock()\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst Object *stand = nullptr;\r\n\tfor (int i = 0; i < ActiveObjectCount; i++) {\r\n\t\tconst Object &object = Objects[ActiveObjects[i]];\r\n\t\tif (object._otype == OBJ_STAND) {\r\n\t\t\tstand = &object;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (stand == nullptr)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tItem &item = Items[ii];\r\n\r\n\titem.position = stand->position;\r\n\tdItem[item.position.x][item.position.y] = ii + 1;\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\tGetItemAttrs(item, IDI_ROCK, curlv);\r\n\tSetupItem(item);\r\n\titem.selectionRegion = SelectionRegion::Middle;\r\n\titem._iPostDraw = true;\r\n\titem.AnimInfo.currentFrame = 10;\r\n\titem._iAnimFlag = true;\r\n\titem._iCreateInfo |= CF_PREGEN;\r\n\r\n\tDeltaAddItem(ii);\r\n}\r\n\r\nvoid ItemDoppel()\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tstatic int idoppely = 16;\r\n\r\n\tfor (int idoppelx = 16; idoppelx < 96; idoppelx++) {\r\n\t\tif (dItem[idoppelx][idoppely] != 0) {\r\n\t\t\tItem *i = &Items[dItem[idoppelx][idoppely] - 1];\r\n\t\t\tif (i->position.x != idoppelx || i->position.y != idoppely)\r\n\t\t\t\tdItem[idoppelx][idoppely] = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tidoppely++;\r\n\tif (idoppely == 96)\r\n\t\tidoppely = 16;\r\n}\r\n\r\nvoid AddItemInfoBoxString(const std::string_view str)\r\n{\r\n\tconst bool floatingInfoBoxEnabled = *GetOptions().Gameplay.floatingInfoBox;\r\n\tAddInfoBoxString(str, floatingInfoBoxEnabled);\r\n}\r\n\r\nvoid AddItemInfoBoxString(std::string &&str)\r\n{\r\n\tconst bool floatingInfoBoxEnabled = *GetOptions().Gameplay.floatingInfoBox;\r\n\tAddInfoBoxString(std::move(str), floatingInfoBoxEnabled);\r\n}\r\n\r\nvoid PrintItemOil(char iDidx)\r\n{\r\n\tswitch (iDidx) {\r\n\tcase IMISC_OILACC:\r\n\t\tAddItemInfoBoxString(_(\"increases a weapon's\"));\r\n\t\tAddItemInfoBoxString(_(\"chance to hit\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILMAST:\r\n\t\tAddItemInfoBoxString(_(\"greatly increases a\"));\r\n\t\tAddItemInfoBoxString(_(\"weapon's chance to hit\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILSHARP:\r\n\t\tAddItemInfoBoxString(_(\"increases a weapon's\"));\r\n\t\tAddItemInfoBoxString(_(\"damage potential\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILDEATH:\r\n\t\tAddItemInfoBoxString(_(\"greatly increases a weapon's\"));\r\n\t\tAddItemInfoBoxString(_(\"damage potential - not bows\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILSKILL:\r\n\t\tAddItemInfoBoxString(_(\"reduces attributes needed\"));\r\n\t\tAddItemInfoBoxString(_(\"to use armor or weapons\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILBSMTH:\r\n\t\tAddItemInfoBoxString(/*xgettext:no-c-format*/ _(\"restores 20% of an\"));\r\n\t\tAddItemInfoBoxString(_(\"item's durability\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILFORT:\r\n\t\tAddItemInfoBoxString(_(\"increases an item's\"));\r\n\t\tAddItemInfoBoxString(_(\"current and max durability\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILPERM:\r\n\t\tAddItemInfoBoxString(_(\"makes an item indestructible\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILHARD:\r\n\t\tAddItemInfoBoxString(_(\"increases the armor class\"));\r\n\t\tAddItemInfoBoxString(_(\"of armor and shields\"));\r\n\t\tbreak;\r\n\tcase IMISC_OILIMP:\r\n\t\tAddItemInfoBoxString(_(\"greatly increases the armor\"));\r\n\t\tAddItemInfoBoxString(_(\"class of armor and shields\"));\r\n\t\tbreak;\r\n\tcase IMISC_RUNEF:\r\n\t\tAddItemInfoBoxString(_(\"sets fire trap\"));\r\n\t\tbreak;\r\n\tcase IMISC_RUNEL:\r\n\tcase IMISC_GR_RUNEL:\r\n\t\tAddItemInfoBoxString(_(\"sets lightning trap\"));\r\n\t\tbreak;\r\n\tcase IMISC_GR_RUNEF:\r\n\t\tAddItemInfoBoxString(_(\"sets fire trap\"));\r\n\t\tbreak;\r\n\tcase IMISC_RUNES:\r\n\t\tAddItemInfoBoxString(_(\"sets petrification trap\"));\r\n\t\tbreak;\r\n\tcase IMISC_FULLHEAL:\r\n\t\tAddItemInfoBoxString(_(\"restore all life\"));\r\n\t\tbreak;\r\n\tcase IMISC_HEAL:\r\n\t\tAddItemInfoBoxString(_(\"restore some life\"));\r\n\t\tbreak;\r\n\tcase IMISC_MANA:\r\n\t\tAddItemInfoBoxString(_(\"restore some mana\"));\r\n\t\tbreak;\r\n\tcase IMISC_FULLMANA:\r\n\t\tAddItemInfoBoxString(_(\"restore all mana\"));\r\n\t\tbreak;\r\n\tcase IMISC_ELIXSTR:\r\n\t\tAddItemInfoBoxString(_(\"increase strength\"));\r\n\t\tbreak;\r\n\tcase IMISC_ELIXMAG:\r\n\t\tAddItemInfoBoxString(_(\"increase magic\"));\r\n\t\tbreak;\r\n\tcase IMISC_ELIXDEX:\r\n\t\tAddItemInfoBoxString(_(\"increase dexterity\"));\r\n\t\tbreak;\r\n\tcase IMISC_ELIXVIT:\r\n\t\tAddItemInfoBoxString(_(\"increase vitality\"));\r\n\t\tbreak;\r\n\tcase IMISC_REJUV:\r\n\t\tAddItemInfoBoxString(_(\"restore some life and mana\"));\r\n\t\tbreak;\r\n\tcase IMISC_FULLREJUV:\r\n\t\tAddItemInfoBoxString(_(\"restore all life and mana\"));\r\n\t\tbreak;\r\n\tcase IMISC_ARENAPOT:\r\n\t\tAddItemInfoBoxString(_(\"restore all life and mana\"));\r\n\t\tAddItemInfoBoxString(_(\"(works only in arenas)\"));\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nPoint DrawUniqueInfoWindow(const Surface &out)\r\n{\r\n\tconst bool isInStash = IsStashOpen && GetLeftPanel().contains(MousePosition);\r\n\tint panelX, panelY;\r\n\tif (isInStash) {\r\n\t\tClxDraw(out, GetPanelPosition(UiPanels::Stash, { 24 + SidePanelSize.width, 327 }), (*pSTextBoxCels)[0]);\r\n\t\tpanelX = GetLeftPanel().position.x + SidePanelSize.width + 27;\r\n\t\tpanelY = GetLeftPanel().position.y + 28;\r\n\t} else {\r\n\t\tClxDraw(out, GetPanelPosition(UiPanels::Inventory, { 24 - SidePanelSize.width, 327 }), (*pSTextBoxCels)[0]);\r\n\t\tpanelX = GetRightPanel().position.x - SidePanelSize.width + 27;\r\n\t\tpanelY = GetRightPanel().position.y + 28;\r\n\t}\r\n\r\n\tconst Point rightInfoPos = GetRightPanel().position - Displacement { SidePanelSize.width, 0 };\r\n\tconst Point leftInfoPos = GetLeftPanel().position + Displacement { SidePanelSize.width, 0 };\r\n\r\n\tconst bool isInfoOverlapping = IsLeftPanelOpen() && IsRightPanelOpen() && GetLeftPanel().contains(rightInfoPos);\r\n\tconst int fadeLevel = isInfoOverlapping ? 3 : 1;\r\n\r\n\tfor (int i = 0; i < fadeLevel; ++i) {\r\n\t\tDrawHalfTransparentRectTo(out, panelX, panelY, 265, 297);\r\n\t}\r\n\r\n\treturn isInStash ? leftInfoPos : rightInfoPos;\r\n}\r\n\r\nvoid printItemMiscKBM(const Item &item, const bool isOil, const bool isCastOnTarget)\r\n{\r\n\tif (item._iMiscId == IMISC_MAPOFDOOM) {\r\n\t\tAddItemInfoBoxString(_(\"Right-click to view\"));\r\n\t} else if (isOil) {\r\n\t\tPrintItemOil(item._iMiscId);\r\n\t\tAddItemInfoBoxString(_(\"Right-click to use\"));\r\n\t} else if (isCastOnTarget) {\r\n\t\tAddItemInfoBoxString(_(\"Right-click to read, then\\nleft-click to target\"));\r\n\t} else if (IsAnyOf(item._iMiscId, IMISC_BOOK, IMISC_NOTE, IMISC_SCROLL, IMISC_SCROLLT)) {\r\n\t\tAddItemInfoBoxString(_(\"Right-click to read\"));\r\n\t}\r\n}\r\n\r\nvoid printItemMiscGenericGamepad(const Item &item, const bool isOil, bool isCastOnTarget)\r\n{\r\n\tif (item._iMiscId == IMISC_MAPOFDOOM) {\r\n\t\tAddItemInfoBoxString(_(\"Activate to view\"));\r\n\t} else if (isOil) {\r\n\t\tPrintItemOil(item._iMiscId);\r\n\t\tif (!invflag) {\r\n\t\t\tAddItemInfoBoxString(_(\"Open inventory to use\"));\r\n\t\t} else {\r\n\t\t\tAddItemInfoBoxString(_(\"Activate to use\"));\r\n\t\t}\r\n\t} else if (isCastOnTarget) {\r\n\t\tAddItemInfoBoxString(_(\"Select from spell book, then\\ncast spell to read\"));\r\n\t} else if (IsAnyOf(item._iMiscId, IMISC_BOOK, IMISC_NOTE, IMISC_SCROLL, IMISC_SCROLLT)) {\r\n\t\tAddItemInfoBoxString(_(\"Activate to read\"));\r\n\t}\r\n}\r\n\r\nvoid printItemMiscGamepad(const Item &item, bool isOil, bool isCastOnTarget)\r\n{\r\n\tif (GamepadType == GamepadLayout::Generic) {\r\n\t\tprintItemMiscGenericGamepad(item, isOil, isCastOnTarget);\r\n\t\treturn;\r\n\t}\r\n\tconst std::string_view activateButton = GetOptions().Padmapper.InputNameForAction(\"SecondaryAction\");\r\n\tconst std::string_view castButton = GetOptions().Padmapper.InputNameForAction(\"SpellAction\");\r\n\r\n\tif (item._iMiscId == IMISC_MAPOFDOOM) {\r\n\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"{} to view\")), activateButton));\r\n\t} else if (isOil) {\r\n\t\tPrintItemOil(item._iMiscId);\r\n\t\tif (!invflag) {\r\n\t\t\tAddItemInfoBoxString(_(\"Open inventory to use\"));\r\n\t\t} else {\r\n\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"{} to use\")), activateButton));\r\n\t\t}\r\n\t} else if (isCastOnTarget) {\r\n\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"Select from spell book,\\nthen {} to read\")), castButton));\r\n\t} else if (IsAnyOf(item._iMiscId, IMISC_BOOK, IMISC_NOTE, IMISC_SCROLL, IMISC_SCROLLT)) {\r\n\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"{} to read\")), activateButton));\r\n\t}\r\n}\r\n\r\nvoid PrintItemMisc(const Item &item)\r\n{\r\n\tif (item._iMiscId == IMISC_EAR) {\r\n\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(pgettext(\"player\", \"Level: {:d}\")), item._ivalue));\r\n\t\treturn;\r\n\t}\r\n\tif (item._iMiscId == IMISC_AURIC) {\r\n\t\tAddItemInfoBoxString(_(\"Doubles gold capacity\"));\r\n\t\treturn;\r\n\t}\r\n\tconst bool isOil = (item._iMiscId >= IMISC_USEFIRST && item._iMiscId <= IMISC_USELAST)\r\n\t    || (item._iMiscId > IMISC_OILFIRST && item._iMiscId < IMISC_OILLAST)\r\n\t    || (item._iMiscId > IMISC_RUNEFIRST && item._iMiscId < IMISC_RUNELAST)\r\n\t    || item._iMiscId == IMISC_ARENAPOT;\r\n\tconst bool mouseRequiresTarget = (item._iMiscId == IMISC_SCROLLT && item._iSpell != SpellID::Flash)\r\n\t    || (item._iMiscId == IMISC_SCROLL && IsAnyOf(item._iSpell, SpellID::TownPortal, SpellID::Identify));\r\n\tconst bool gamepadRequiresTarget = item.isScroll() && TargetsMonster(item._iSpell);\r\n\r\n\tswitch (ControlMode) {\r\n\tcase ControlTypes::None:\r\n\t\tbreak;\r\n\tcase ControlTypes::KeyboardAndMouse:\r\n\t\tprintItemMiscKBM(item, isOil, mouseRequiresTarget);\r\n\t\tbreak;\r\n\tcase ControlTypes::VirtualGamepad:\r\n\t\tprintItemMiscGenericGamepad(item, isOil, gamepadRequiresTarget);\r\n\t\tbreak;\r\n\tcase ControlTypes::Gamepad:\r\n\t\tprintItemMiscGamepad(item, isOil, gamepadRequiresTarget);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid PrintItemInfo(const Item &item)\r\n{\r\n\tPrintItemMisc(item);\r\n\tuint8_t str = item._iMinStr;\r\n\tuint8_t dex = item._iMinDex;\r\n\tuint8_t mag = item._iMinMag;\r\n\tif (str != 0 || mag != 0 || dex != 0) {\r\n\t\tstd::string text = std::string(_(\"Required:\"));\r\n\t\tif (str != 0)\r\n\t\t\ttext.append(fmt::format(fmt::runtime(_(\" {:d} Str\")), str));\r\n\t\tif (mag != 0)\r\n\t\t\ttext.append(fmt::format(fmt::runtime(_(\" {:d} Mag\")), mag));\r\n\t\tif (dex != 0)\r\n\t\t\ttext.append(fmt::format(fmt::runtime(_(\" {:d} Dex\")), dex));\r\n\t\tAddItemInfoBoxString(text);\r\n\t}\r\n}\r\n\r\nbool SmithItemOk(const Player & /*player*/, const ItemData &item)\r\n{\r\n\tif (item.itype == ItemType::Misc)\r\n\t\treturn false;\r\n\tif (item.itype == ItemType::Gold)\r\n\t\treturn false;\r\n\tif (item.itype == ItemType::Staff && (!gbIsHellfire || IsValidSpell(item.iSpell)))\r\n\t\treturn false;\r\n\tif (item.itype == ItemType::Ring)\r\n\t\treturn false;\r\n\tif (item.itype == ItemType::Amulet)\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\ntemplate <bool (*Ok)(const Player &, const ItemData &), bool ConsiderDropRate = false>\r\n_item_indexes RndVendorItem(const Player &player, int minlvl, int maxlvl)\r\n{\r\n\treturn GetItemIndexForDroppableItem(ConsiderDropRate, [&player, &minlvl, &maxlvl](const ItemData &item) {\r\n\t\tif (!Ok(player, item))\r\n\t\t\treturn false;\r\n\t\tif (item.iMinMLvl < minlvl || item.iMinMLvl > maxlvl)\r\n\t\t\treturn false;\r\n\t\treturn true;\r\n\t});\r\n}\r\n\r\n_item_indexes RndSmithItem(const Player &player, int lvl)\r\n{\r\n\treturn RndVendorItem<SmithItemOk, true>(player, 0, lvl);\r\n}\r\n\r\nvoid SortVendor(std::span<Item> itemList, size_t PinnedItemCount)\r\n{\r\n\tauto cmp = [](const Item &a, const Item &b) {\r\n\t\treturn a.IDidx < b.IDidx;\r\n\t};\r\n\r\n\tstd::sort(itemList.begin() + PinnedItemCount, itemList.end(), cmp);\r\n}\r\n\r\nbool PremiumItemOk(const Player & /*player*/, const ItemData &item)\r\n{\r\n\tif (item.itype == ItemType::Misc)\r\n\t\treturn false;\r\n\tif (item.itype == ItemType::Gold)\r\n\t\treturn false;\r\n\tif (!gbIsHellfire && item.itype == ItemType::Staff)\r\n\t\treturn false;\r\n\r\n\tif (gbIsMultiplayer) {\r\n\t\tif (item.iMiscId == IMISC_OILOF)\r\n\t\t\treturn false;\r\n\t\tif (item.itype == ItemType::Ring)\r\n\t\t\treturn false;\r\n\t\tif (item.itype == ItemType::Amulet)\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n_item_indexes RndPremiumItem(const Player &player, int minlvl, int maxlvl)\r\n{\r\n\treturn RndVendorItem<PremiumItemOk>(player, minlvl, maxlvl);\r\n}\r\n\r\nvoid SpawnOnePremium(Item &premiumItem, int plvl, const Player &player)\r\n{\r\n\tint strength = std::max(player.GetMaximumAttributeValue(CharacterAttribute::Strength), player._pStrength);\r\n\tint dexterity = std::max(player.GetMaximumAttributeValue(CharacterAttribute::Dexterity), player._pDexterity);\r\n\tint magic = std::max(player.GetMaximumAttributeValue(CharacterAttribute::Magic), player._pMagic);\r\n\tstrength += strength / 5;\r\n\tdexterity += dexterity / 5;\r\n\tmagic += magic / 5;\r\n\r\n\tplvl = std::clamp(plvl, 1, 30);\r\n\r\n\tconst int maxCount = 150;\r\n\tconst bool unlimited = !gbIsHellfire; // TODO: This could lead to an infinite loop if a suitable item can never be generated\r\n\tfor (int count = 0; unlimited || count < maxCount; count++) {\r\n\t\tpremiumItem = {};\r\n\t\tpremiumItem._iSeed = AdvanceRndSeed();\r\n\t\tSetRndSeed(premiumItem._iSeed);\r\n\t\tconst _item_indexes itemType = RndPremiumItem(player, plvl / 4, plvl);\r\n\t\tGetItemAttrs(premiumItem, itemType, plvl);\r\n\t\tGetItemBonus(player, premiumItem, plvl / 2, plvl, true, !gbIsHellfire);\r\n\r\n\t\tif (!gbIsHellfire) {\r\n\t\t\tif (premiumItem._iIvalue <= MaxVendorValue) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tint itemValue = 0;\r\n\t\t\tswitch (premiumItem._itype) {\r\n\t\t\tcase ItemType::LightArmor:\r\n\t\t\tcase ItemType::MediumArmor:\r\n\t\t\tcase ItemType::HeavyArmor: {\r\n\t\t\t\tconst auto *const mostValuablePlayerArmor = player.GetMostValuableItem(\r\n\t\t\t\t    [](const Item &item) {\r\n\t\t\t\t\t    return IsAnyOf(item._itype, ItemType::LightArmor, ItemType::MediumArmor, ItemType::HeavyArmor);\r\n\t\t\t\t    });\r\n\r\n\t\t\t\titemValue = mostValuablePlayerArmor == nullptr ? 0 : mostValuablePlayerArmor->_iIvalue;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase ItemType::Shield:\r\n\t\t\tcase ItemType::Axe:\r\n\t\t\tcase ItemType::Bow:\r\n\t\t\tcase ItemType::Mace:\r\n\t\t\tcase ItemType::Sword:\r\n\t\t\tcase ItemType::Helm:\r\n\t\t\tcase ItemType::Staff:\r\n\t\t\tcase ItemType::Ring:\r\n\t\t\tcase ItemType::Amulet: {\r\n\t\t\t\tconst auto *const mostValuablePlayerItem = player.GetMostValuableItem(\r\n\t\t\t\t    [filterType = premiumItem._itype](const Item &item) { return item._itype == filterType; });\r\n\r\n\t\t\t\titemValue = mostValuablePlayerItem == nullptr ? 0 : mostValuablePlayerItem->_iIvalue;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\titemValue = 0;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\titemValue = itemValue * 4 / 5; // avoids forced int > float > int conversion\r\n\t\t\tif (premiumItem._iIvalue <= MaxVendorValueHf\r\n\t\t\t    && premiumItem._iMinStr <= strength\r\n\t\t\t    && premiumItem._iMinMag <= magic\r\n\t\t\t    && premiumItem._iMinDex <= dexterity\r\n\t\t\t    && premiumItem._iIvalue >= itemValue) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tpremiumItem._iCreateInfo = plvl | CF_SMITHPREMIUM;\r\n\tpremiumItem._iIdentified = true;\r\n\tpremiumItem._iStatFlag = player.CanUseItem(premiumItem);\r\n}\r\n\r\nbool WitchItemOk(const Player & /*player*/, const ItemData &item)\r\n{\r\n\tif (IsNoneOf(item.itype, ItemType::Misc, ItemType::Staff))\r\n\t\treturn false;\r\n\tif (item.iMiscId == IMISC_MANA)\r\n\t\treturn false;\r\n\tif (item.iMiscId == IMISC_FULLMANA)\r\n\t\treturn false;\r\n\tif (item.iSpell == SpellID::TownPortal)\r\n\t\treturn false;\r\n\tif (item.iMiscId == IMISC_FULLHEAL)\r\n\t\treturn false;\r\n\tif (item.iMiscId == IMISC_HEAL)\r\n\t\treturn false;\r\n\tif (item.iMiscId > IMISC_OILFIRST && item.iMiscId < IMISC_OILLAST)\r\n\t\treturn false;\r\n\tif (item.iSpell == SpellID::Resurrect && !gbIsMultiplayer)\r\n\t\treturn false;\r\n\tif (item.iSpell == SpellID::HealOther && !gbIsMultiplayer)\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\n_item_indexes RndWitchItem(const Player &player, int lvl)\r\n{\r\n\treturn RndVendorItem<WitchItemOk>(player, 0, lvl);\r\n}\r\n\r\n_item_indexes RndBoyItem(const Player &player, int lvl)\r\n{\r\n\treturn RndVendorItem<PremiumItemOk>(player, 0, lvl);\r\n}\r\n\r\nbool HealerItemOk(const Player &player, const ItemData &item)\r\n{\r\n\tif (item.itype != ItemType::Misc)\r\n\t\treturn false;\r\n\r\n\tif (item.iMiscId == IMISC_SCROLL)\r\n\t\treturn item.iSpell == SpellID::Healing;\r\n\tif (item.iMiscId == IMISC_SCROLLT)\r\n\t\treturn item.iSpell == SpellID::HealOther && gbIsMultiplayer;\r\n\r\n\tif (!gbIsMultiplayer) {\r\n\t\tif (item.iMiscId == IMISC_ELIXSTR)\r\n\t\t\treturn !gbIsHellfire || player._pBaseStr < player.GetMaximumAttributeValue(CharacterAttribute::Strength);\r\n\t\tif (item.iMiscId == IMISC_ELIXMAG)\r\n\t\t\treturn !gbIsHellfire || player._pBaseMag < player.GetMaximumAttributeValue(CharacterAttribute::Magic);\r\n\t\tif (item.iMiscId == IMISC_ELIXDEX)\r\n\t\t\treturn !gbIsHellfire || player._pBaseDex < player.GetMaximumAttributeValue(CharacterAttribute::Dexterity);\r\n\t\tif (item.iMiscId == IMISC_ELIXVIT)\r\n\t\t\treturn !gbIsHellfire || player._pBaseVit < player.GetMaximumAttributeValue(CharacterAttribute::Vitality);\r\n\t}\r\n\r\n\tif (item.iMiscId == IMISC_REJUV)\r\n\t\treturn true;\r\n\tif (item.iMiscId == IMISC_FULLREJUV)\r\n\t\treturn true;\r\n\r\n\treturn false;\r\n}\r\n\r\n_item_indexes RndHealerItem(const Player &player, int lvl)\r\n{\r\n\treturn RndVendorItem<HealerItemOk>(player, 0, lvl);\r\n}\r\n\r\nvoid RecreateSmithItem(const Player &player, Item &item, int lvl, int iseed)\r\n{\r\n\tSetRndSeed(iseed);\r\n\tconst _item_indexes itype = RndSmithItem(player, lvl);\r\n\tGetItemAttrs(item, itype, lvl);\r\n\r\n\titem._iSeed = iseed;\r\n\titem._iCreateInfo = lvl | CF_SMITH;\r\n\titem._iIdentified = true;\r\n}\r\n\r\nvoid RecreatePremiumItem(const Player &player, Item &item, int plvl, int iseed)\r\n{\r\n\tSetRndSeed(iseed);\r\n\tconst _item_indexes itype = RndPremiumItem(player, plvl / 4, plvl);\r\n\tGetItemAttrs(item, itype, plvl);\r\n\tGetItemBonus(player, item, plvl / 2, plvl, true, !gbIsHellfire);\r\n\r\n\titem._iSeed = iseed;\r\n\titem._iCreateInfo = plvl | CF_SMITHPREMIUM;\r\n\titem._iIdentified = true;\r\n}\r\n\r\nvoid RecreateBoyItem(const Player &player, Item &item, int lvl, int iseed)\r\n{\r\n\tSetRndSeed(iseed);\r\n\tconst _item_indexes itype = RndBoyItem(player, lvl);\r\n\tGetItemAttrs(item, itype, lvl);\r\n\tGetItemBonus(player, item, lvl, 2 * lvl, true, true);\r\n\r\n\titem._iSeed = iseed;\r\n\titem._iCreateInfo = lvl | CF_BOY;\r\n\titem._iIdentified = true;\r\n}\r\n\r\nvoid RecreateWitchItem(const Player &player, Item &item, _item_indexes idx, int lvl, int iseed)\r\n{\r\n\tif (IsAnyOf(idx, IDI_MANA, IDI_FULLMANA, IDI_PORTAL)) {\r\n\t\tGetItemAttrs(item, idx, lvl);\r\n\t} else if (gbIsHellfire && idx >= 114 && idx <= 117) {\r\n\t\tSetRndSeed(iseed);\r\n\t\tDiscardRandomValues(1);\r\n\t\tGetItemAttrs(item, idx, lvl);\r\n\t} else {\r\n\t\tSetRndSeed(iseed);\r\n\t\tconst _item_indexes itype = RndWitchItem(player, lvl);\r\n\t\tGetItemAttrs(item, itype, lvl);\r\n\t\tint iblvl = -1;\r\n\t\tif (GenerateRnd(100) <= 5)\r\n\t\t\tiblvl = 2 * lvl;\r\n\t\tif (iblvl == -1 && item._iMiscId == IMISC_STAFF)\r\n\t\t\tiblvl = 2 * lvl;\r\n\t\tif (iblvl != -1)\r\n\t\t\tGetItemBonus(player, item, iblvl / 2, iblvl, true, true);\r\n\t}\r\n\r\n\titem._iSeed = iseed;\r\n\titem._iCreateInfo = lvl | CF_WITCH;\r\n\titem._iIdentified = true;\r\n}\r\n\r\nvoid RecreateHealerItem(const Player &player, Item &item, _item_indexes idx, int lvl, int iseed)\r\n{\r\n\tif (IsAnyOf(idx, IDI_HEAL, IDI_FULLHEAL, IDI_RESURRECT)) {\r\n\t\tGetItemAttrs(item, idx, lvl);\r\n\t} else {\r\n\t\tSetRndSeed(iseed);\r\n\t\tconst _item_indexes itype = RndHealerItem(player, lvl);\r\n\t\tGetItemAttrs(item, itype, lvl);\r\n\t}\r\n\r\n\titem._iSeed = iseed;\r\n\titem._iCreateInfo = lvl | CF_HEALER;\r\n\titem._iIdentified = true;\r\n}\r\n\r\nvoid RecreateTownItem(const Player &player, Item &item, _item_indexes idx, uint16_t icreateinfo, int iseed)\r\n{\r\n\tif ((icreateinfo & CF_SMITH) != 0)\r\n\t\tRecreateSmithItem(player, item, icreateinfo & CF_LEVEL, iseed);\r\n\telse if ((icreateinfo & CF_SMITHPREMIUM) != 0)\r\n\t\tRecreatePremiumItem(player, item, icreateinfo & CF_LEVEL, iseed);\r\n\telse if ((icreateinfo & CF_BOY) != 0)\r\n\t\tRecreateBoyItem(player, item, icreateinfo & CF_LEVEL, iseed);\r\n\telse if ((icreateinfo & CF_WITCH) != 0)\r\n\t\tRecreateWitchItem(player, item, idx, icreateinfo & CF_LEVEL, iseed);\r\n\telse if ((icreateinfo & CF_HEALER) != 0)\r\n\t\tRecreateHealerItem(player, item, idx, icreateinfo & CF_LEVEL, iseed);\r\n}\r\n\r\nvoid CreateMagicItem(Point position, int lvl, ItemType itemType, int imid, int icurs, bool sendmsg, bool delta, bool spawn = false)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\t_item_indexes idx = RndTypeItems(itemType, imid, lvl);\r\n\r\n\twhile (true) {\r\n\t\titem = {};\r\n\t\tSetupAllItems(*MyPlayer, item, idx, AdvanceRndSeed(), 2 * lvl, 1, true, delta);\r\n\t\tTryRandomUniqueItem(item, idx, 2 * lvl, 1, true, delta);\r\n\t\tSetupItem(item);\r\n\t\tif (item._iCurs == icurs)\r\n\t\t\tbreak;\r\n\r\n\t\tidx = RndTypeItems(itemType, imid, lvl);\r\n\t}\r\n\tGetSuperItemSpace(position, ii);\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdPItem(false, CMD_DROPITEM, item.position, item);\r\n\tif (delta)\r\n\t\tDeltaAddItem(ii);\r\n\tif (spawn)\r\n\t\tNetSendCmdPItem(false, CMD_SPAWNITEM, item.position, item);\r\n}\r\n\r\nvoid NextItemRecord(int i)\r\n{\r\n\tgnNumGetRecords--;\r\n\r\n\tif (gnNumGetRecords == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\titemrecord[i].dwTimestamp = itemrecord[gnNumGetRecords].dwTimestamp;\r\n\titemrecord[i].nSeed = itemrecord[gnNumGetRecords].nSeed;\r\n\titemrecord[i].wCI = itemrecord[gnNumGetRecords].wCI;\r\n\titemrecord[i].nIndex = itemrecord[gnNumGetRecords].nIndex;\r\n}\r\n\r\nStringOrView GetTranslatedItemName(const Item &item)\r\n{\r\n\tconst auto &baseItemData = AllItemsList[static_cast<size_t>(item.IDidx)];\r\n\r\n\tif (item._iCreateInfo == 0) {\r\n\t\treturn _(baseItemData.iName);\r\n\t}\r\n\tif (item._iMiscId == IMISC_BOOK) {\r\n\t\tconst std::string_view spellName = pgettext(\"spell\", GetSpellData(item._iSpell).sNameText);\r\n\t\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} will be a spell name */ \"Book of {:s}\")), spellName);\r\n\t}\r\n\tif (item._iMiscId == IMISC_EAR) {\r\n\t\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} will be a Character Name */ \"Ear of {:s}\")), item._iIName);\r\n\t}\r\n\tif (item._iMiscId > IMISC_OILFIRST && item._iMiscId < IMISC_OILLAST) {\r\n\t\tfor (size_t i = 0; i < 10; i++) {\r\n\t\t\tif (OilMagic[i] != item._iMiscId)\r\n\t\t\t\tcontinue;\r\n\t\t\treturn _(OilNames[i]);\r\n\t\t}\r\n\t\tapp_fatal(\"unknown oil\");\r\n\t} else if (item._itype == ItemType::Staff && item._iSpell != SpellID::Null && item._iMagical != ITEM_QUALITY_UNIQUE) {\r\n\t\treturn GenerateStaffName(baseItemData, item._iSpell, true);\r\n\t} else {\r\n\t\treturn _(baseItemData.iName);\r\n\t}\r\n}\r\n\r\nstd::string GetTranslatedItemNameMagical(const Item &item, bool hellfireItem, bool translate, std::optional<bool> forceNameLengthCheck)\r\n{\r\n\tstd::string identifiedName;\r\n\tconst auto &baseItemData = AllItemsList[static_cast<size_t>(item.IDidx)];\r\n\r\n\tconst int lvl = item._iCreateInfo & CF_LEVEL;\r\n\tconst bool onlygood = (item._iCreateInfo & (CF_ONLYGOOD | CF_SMITHPREMIUM | CF_BOY | CF_WITCH)) != 0;\r\n\r\n\tconst uint32_t currentSeed = GetLCGEngineState();\r\n\tSetRndSeed(item._iSeed);\r\n\r\n\tint minlvl;\r\n\tint maxlvl;\r\n\tif ((item._iCreateInfo & CF_SMITHPREMIUM) != 0) {\r\n\t\tDiscardRandomValues(2); // RndVendorItem and GetItemAttrs\r\n\t\tminlvl = lvl / 2;\r\n\t\tmaxlvl = lvl;\r\n\t} else if ((item._iCreateInfo & CF_BOY) != 0) {\r\n\t\tDiscardRandomValues(2); // RndVendorItem and GetItemAttrs\r\n\t\tminlvl = lvl;\r\n\t\tmaxlvl = lvl * 2;\r\n\t} else if ((item._iCreateInfo & CF_WITCH) != 0) {\r\n\t\tDiscardRandomValues(2); // RndVendorItem and GetItemAttrs\r\n\t\tint iblvl = -1;\r\n\t\tif (GenerateRnd(100) <= 5)\r\n\t\t\tiblvl = 2 * lvl;\r\n\t\tif (iblvl == -1 && item._iMiscId == IMISC_STAFF)\r\n\t\t\tiblvl = 2 * lvl;\r\n\t\tminlvl = iblvl / 2;\r\n\t\tmaxlvl = iblvl;\r\n\t} else {\r\n\t\tDiscardRandomValues(1); // GetItemAttrs\r\n\t\tconst int iblvl = GetItemBLevel(lvl, item._iMiscId, onlygood, (item._iCreateInfo & CF_UPER15) != 0);\r\n\t\tminlvl = iblvl / 2;\r\n\t\tmaxlvl = iblvl;\r\n\t\tDiscardRandomValues(1); // CheckUnique\r\n\t}\r\n\r\n\tminlvl = std::min(minlvl, 25);\r\n\r\n\tAffixItemType affixItemType = AffixItemType::None;\r\n\r\n\tswitch (item._itype) {\r\n\tcase ItemType::Sword:\r\n\tcase ItemType::Axe:\r\n\tcase ItemType::Mace:\r\n\t\taffixItemType = AffixItemType::Weapon;\r\n\t\tbreak;\r\n\tcase ItemType::Bow:\r\n\t\taffixItemType = AffixItemType::Bow;\r\n\t\tbreak;\r\n\tcase ItemType::Shield:\r\n\t\taffixItemType = AffixItemType::Shield;\r\n\t\tbreak;\r\n\tcase ItemType::LightArmor:\r\n\tcase ItemType::Helm:\r\n\tcase ItemType::MediumArmor:\r\n\tcase ItemType::HeavyArmor:\r\n\t\taffixItemType = AffixItemType::Armor;\r\n\t\tbreak;\r\n\tcase ItemType::Staff: {\r\n\t\tconst bool allowspells = !hellfireItem || ((item._iCreateInfo & CF_SMITHPREMIUM) == 0);\r\n\r\n\t\tif (!allowspells)\r\n\t\t\taffixItemType = AffixItemType::Staff;\r\n\t\telse if (!hellfireItem && FlipCoin(4)) {\r\n\t\t\taffixItemType = AffixItemType::Staff;\r\n\t\t\tminlvl = maxlvl / 2;\r\n\t\t} else {\r\n\t\t\tDiscardRandomValues(2); // Spell and Charges\r\n\r\n\t\t\tstd::optional<const PLStruct *> prefix = GetStaffPrefix(maxlvl, onlygood);\r\n\t\t\tif (!prefix.has_value() || item._iSpell == SpellID::Null) {\r\n\t\t\t\tif (forceNameLengthCheck) {\r\n\t\t\t\t\t// We generate names to check if it's a diablo or hellfire item. This checks fails => invalid item => don't generate a item name\r\n\t\t\t\t\tidentifiedName.clear();\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// This can happen, if the item is hacked or a bug in the logic exists\r\n\t\t\t\t\tLogWarn(\"GetTranslatedItemNameMagical failed for item '{}' with prefix '{}' and spellid '{}'\", item._iIName, prefix.has_value() ? (*prefix)->PLName : \"NULL\", static_cast<std::underlying_type_t<SpellID>>(item._iSpell));\r\n\t\t\t\t\tidentifiedName = item._iIName;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tidentifiedName = GenerateStaffNameMagical(baseItemData, item._iSpell, **prefix, translate, forceNameLengthCheck);\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\tcase ItemType::Ring:\r\n\tcase ItemType::Amulet:\r\n\t\taffixItemType = AffixItemType::Misc;\r\n\t\tbreak;\r\n\tcase ItemType::None:\r\n\tcase ItemType::Misc:\r\n\tcase ItemType::Gold:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (affixItemType != AffixItemType::None) {\r\n\t\tconst PLStruct *pPrefix = nullptr;\r\n\t\tconst PLStruct *pSufix = nullptr;\r\n\t\tGetItemPowerPrefixAndSuffix(\r\n\t\t    minlvl, maxlvl, affixItemType, onlygood,\r\n\t\t    [&pPrefix](const PLStruct &prefix) {\r\n\t\t\t    pPrefix = &prefix;\r\n\t\t\t    // GenerateRnd(prefix.power.param2 - prefix.power.param2 + 1)\r\n\t\t\t    DiscardRandomValues(1);\r\n\t\t\t    switch (pPrefix->power.type) {\r\n\t\t\t    case IPL_DOPPELGANGER:\r\n\t\t\t    case IPL_TOHIT_DAMP:\r\n\t\t\t\t    DiscardRandomValues(2);\r\n\t\t\t\t    break;\r\n\t\t\t    case IPL_TOHIT_DAMP_CURSE:\r\n\t\t\t\t    DiscardRandomValues(1);\r\n\t\t\t\t    break;\r\n\t\t\t    default:\r\n\t\t\t\t    break;\r\n\t\t\t    }\r\n\t\t    },\r\n\t\t    [&pSufix](const PLStruct &suffix) {\r\n\t\t\t    pSufix = &suffix;\r\n\t\t    });\r\n\r\n\t\tidentifiedName = GenerateMagicItemName(_(baseItemData.iName), pPrefix, pSufix, translate);\r\n\t\tif (forceNameLengthCheck ? *forceNameLengthCheck : !StringInPanel(identifiedName.c_str())) {\r\n\t\t\tidentifiedName = GenerateMagicItemName(_(baseItemData.iSName), pPrefix, pSufix, translate);\r\n\t\t}\r\n\t}\r\n\r\n\tSetRndSeed(currentSeed);\r\n\treturn identifiedName;\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsItemAvailable(int i)\r\n{\r\n\tif (i < 0 || i >= static_cast<int>(AllItemsList.size()))\r\n\t\treturn false;\r\n\r\n\tif (gbIsSpawn) {\r\n\t\tif (i >= 62 && i <= 70)\r\n\t\t\treturn false; // Medium and heavy armors\r\n\t\tif (IsAnyOf(i, 105, 107, 108, 110, 111, 113))\r\n\t\t\treturn false; // Unavailable scrolls\r\n\t}\r\n\r\n\tif (gbIsHellfire)\r\n\t\treturn true;\r\n\r\n\treturn (\r\n\t           i != IDI_MAPOFDOOM                   // Cathedral Map\r\n\t           && i != IDI_LGTFORGE                 // Bovine Plate\r\n\t           && (i < IDI_OIL || i > IDI_GREYSUIT) // Hellfire exclusive items\r\n\t           && (i < 83 || i > 86)                // Oils\r\n\t           && i != 92                           // Scroll of Search\r\n\t           && (i < 161 || i > 165)              // Runes\r\n\t           && i != IDI_SORCERER                 // Short Staff of Mana\r\n\t           )\r\n\t    || (\r\n\t        // Bard items are technically Hellfire-exclusive\r\n\t        // but are just normal items with adjusted stats.\r\n\t        *GetOptions().Gameplay.testBard && IsAnyOf(i, IDI_BARDSWORD, IDI_BARDDAGGER));\r\n}\r\n\r\nuint8_t GetOutlineColor(const Item &item, bool checkReq)\r\n{\r\n\tif (checkReq && !item._iStatFlag)\r\n\t\treturn ICOL_RED;\r\n\tif (item._itype == ItemType::Gold)\r\n\t\treturn ICOL_YELLOW;\r\n\tif (item._iMagical == ITEM_QUALITY_MAGIC)\r\n\t\treturn ICOL_BLUE;\r\n\tif (item._iMagical == ITEM_QUALITY_UNIQUE)\r\n\t\treturn ICOL_YELLOW;\r\n\r\n\treturn ICOL_WHITE;\r\n}\r\n\r\nvoid ClearUniqueItemFlags()\r\n{\r\n\tmemset(UniqueItemFlags, 0, sizeof(UniqueItemFlags));\r\n}\r\n\r\nvoid InitItemGFX()\r\n{\r\n\tchar arglist[64];\r\n\r\n\tconst int itemTypes = gbIsHellfire ? ITEMTYPES : 35;\r\n\tfor (int i = 0; i < itemTypes; i++) {\r\n\t\t*BufCopy(arglist, \"items\\\\\", ItemDropNames[i]) = '\\0';\r\n\t\titemanims[i] = LoadCel(arglist, ItemAnimWidth);\r\n\t}\r\n}\r\n\r\nvoid InitItems()\r\n{\r\n\tActiveItemCount = 0;\r\n\tmemset(dItem, 0, sizeof(dItem));\r\n\r\n\tfor (auto &item : Items) {\r\n\t\titem.clear();\r\n\t\titem.position = { 0, 0 };\r\n\t\titem._iAnimFlag = false;\r\n\t\titem.selectionRegion = SelectionRegion::None;\r\n\t\titem._iIdentified = false;\r\n\t\titem._iPostDraw = false;\r\n\t}\r\n\r\n\tfor (uint8_t i = 0; i < MAXITEMS; i++) {\r\n\t\tActiveItems[i] = i;\r\n\t}\r\n\r\n\tif (!setlevel) {\r\n\t\tDiscardRandomValues(1);\r\n\t\tif (Quests[Q_ROCK].IsAvailable())\r\n\t\t\tSpawnRock();\r\n\t\tif (Quests[Q_ANVIL].IsAvailable())\r\n\t\t\tSpawnQuestItem(IDI_ANVIL, SetPiece.position.megaToWorld() + Displacement { 11, 11 }, 0, SelectionRegion::Bottom, false);\r\n\t\tif (sgGameInitInfo.bCowQuest != 0 && currlevel == 20)\r\n\t\t\tSpawnQuestItem(IDI_BROWNSUIT, { 25, 25 }, 3, SelectionRegion::Bottom, false);\r\n\t\tif (sgGameInitInfo.bCowQuest != 0 && currlevel == 19)\r\n\t\t\tSpawnQuestItem(IDI_GREYSUIT, { 25, 25 }, 3, SelectionRegion::Bottom, false);\r\n\t\t// In multiplayer items spawn during level generation to avoid desyncs\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tif (Quests[Q_MUSHROOM].IsAvailable())\r\n\t\t\t\tSpawnQuestItem(IDI_FUNGALTM, { 0, 0 }, 5, SelectionRegion::Bottom, false);\r\n\t\t\tif (currlevel == Quests[Q_VEIL]._qlevel + 1 && Quests[Q_VEIL]._qactive != QUEST_NOTAVAIL)\r\n\t\t\t\tSpawnQuestItem(IDI_GLDNELIX, { 0, 0 }, 5, SelectionRegion::Bottom, false);\r\n\t\t}\r\n\t\tif (currlevel > 0 && currlevel < 16)\r\n\t\t\tAddInitItems();\r\n\t\tif (currlevel >= 21 && currlevel <= 23)\r\n\t\t\tSpawnNote();\r\n\t}\r\n\r\n\tShowUniqueItemInfoBox = false;\r\n\r\n\tinitItemGetRecords();\r\n}\r\n\r\nint GetBonusAC(const Item &item)\r\n{\r\n\tif (item._iPLAC != 0) {\r\n\t\tint tempAc = item._iAC;\r\n\t\ttempAc *= item._iPLAC;\r\n\t\ttempAc /= 100;\r\n\t\tif (tempAc == 0)\r\n\t\t\ttempAc = math::Sign(item._iPLAC);\r\n\t\treturn tempAc;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid CalcPlrDamage(Player &player, int minDamage, int maxDamage)\r\n{\r\n\tconst uint8_t playerLevel = player.getCharacterLevel();\r\n\r\n\tif (minDamage == 0 && maxDamage == 0) {\r\n\t\tminDamage = 1;\r\n\t\tmaxDamage = 1;\r\n\r\n\t\tif (player.isHoldingItem(ItemType::Shield)) {\r\n\t\t\tmaxDamage = 3;\r\n\t\t}\r\n\r\n\t\tif (player._pClass == HeroClass::Monk) {\r\n\t\t\tminDamage = std::max(minDamage, playerLevel / 2);\r\n\t\t\tmaxDamage = std::max<int>(maxDamage, playerLevel);\r\n\t\t}\r\n\t}\r\n\r\n\tplayer._pIMinDam = minDamage;\r\n\tplayer._pIMaxDam = maxDamage;\r\n}\r\n\r\nvoid CalcPlrPrimaryStats(Player &player, int strength, int &magic, int dexterity, int &vitality)\r\n{\r\n\tconst uint8_t playerLevel = player.getCharacterLevel();\r\n\r\n\tif (HasAnyOf(player._pSpellFlags, SpellFlag::RageActive)) {\r\n\t\tstrength += 2 * playerLevel;\r\n\t\tdexterity += playerLevel + playerLevel / 2;\r\n\t\tvitality += 2 * playerLevel;\r\n\t}\r\n\tif (HasAnyOf(player._pSpellFlags, SpellFlag::RageCooldown)) {\r\n\t\tstrength -= 2 * playerLevel;\r\n\t\tdexterity -= playerLevel + playerLevel / 2;\r\n\t\tvitality -= 2 * playerLevel;\r\n\t}\r\n\r\n\tplayer._pStrength = std::clamp(strength + player._pBaseStr, 0, 750);\r\n\tplayer._pMagic = std::clamp(magic + player._pBaseMag, 0, 750);\r\n\tplayer._pDexterity = std::clamp(dexterity + player._pBaseDex, 0, 750);\r\n\tplayer._pVitality = std::clamp(vitality + player._pBaseVit, 0, 750);\r\n}\r\n\r\nvoid CalcPlrLightRadius(Player &player, int lrad)\r\n{\r\n\tlrad = std::clamp(lrad, 2, 15);\r\n\r\n\tif (player._pLightRad != lrad) {\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tChangeLightRadius(player.lightId, lrad);\r\n\t\t\tChangeVisionRadius(player.getId(), lrad);\r\n\t\t}\r\n\t\tplayer._pLightRad = lrad;\r\n\t}\r\n}\r\n\r\nvoid CalcPlrDamageMod(Player &player)\r\n{\r\n\tconst uint8_t playerLevel = player.getCharacterLevel();\r\n\tconst Item &leftHandItem = player.InvBody[INVLOC_HAND_LEFT];\r\n\tconst Item &rightHandItem = player.InvBody[INVLOC_HAND_RIGHT];\r\n\tconst int strMod = playerLevel * player._pStrength;\r\n\tconst int strDexMod = playerLevel * (player._pStrength + player._pDexterity);\r\n\r\n\tswitch (player._pClass) {\r\n\tcase HeroClass::Rogue:\r\n\t\tplayer._pDamageMod = strDexMod / 200;\r\n\t\tbreak;\r\n\tcase HeroClass::Monk:\r\n\t\tif (player.isHoldingItem(ItemType::Staff) || (leftHandItem.isEmpty() && rightHandItem.isEmpty())) {\r\n\t\t\tplayer._pDamageMod = strDexMod / 150;\r\n\t\t} else {\r\n\t\t\tplayer._pDamageMod = strDexMod / 300;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase HeroClass::Bard:\r\n\t\tif (player.isHoldingItem(ItemType::Sword)) {\r\n\t\t\tplayer._pDamageMod = strDexMod / 150;\r\n\t\t} else if (player.isHoldingItem(ItemType::Bow)) {\r\n\t\t\tplayer._pDamageMod = strDexMod / 250;\r\n\t\t} else {\r\n\t\t\tplayer._pDamageMod = strMod / 100;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase HeroClass::Barbarian:\r\n\t\tif (player.isHoldingItem(ItemType::Axe) || player.isHoldingItem(ItemType::Mace)) {\r\n\t\t\tplayer._pDamageMod = strMod / 75;\r\n\t\t} else if (player.isHoldingItem(ItemType::Bow)) {\r\n\t\t\tplayer._pDamageMod = strMod / 300;\r\n\t\t} else {\r\n\t\t\tplayer._pDamageMod = strMod / 100;\r\n\t\t}\r\n\t\tif (player.isHoldingItem(ItemType::Shield)) {\r\n\t\t\tif (leftHandItem._itype == ItemType::Shield)\r\n\t\t\t\tplayer._pIAC -= leftHandItem._iAC / 2;\r\n\t\t\telse if (rightHandItem._itype == ItemType::Shield)\r\n\t\t\t\tplayer._pIAC -= rightHandItem._iAC / 2;\r\n\t\t} else if (!player.isHoldingItem(ItemType::Staff) && !player.isHoldingItem(ItemType::Bow)) {\r\n\t\t\tplayer._pDamageMod += playerLevel * player._pVitality / 100;\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tplayer._pDamageMod = strMod / 100;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(player._pClass);\r\n\tif (HasAnyOf(classAttributes.classFlags, PlayerClassFlag::IronSkin)) {\r\n\t\tplayer._pIAC += playerLevel / 4;\r\n\t}\r\n}\r\n\r\nvoid CalcPlrResistances(Player &player, ItemSpecialEffect iflgs, int fire, int lightning, int magic)\r\n{\r\n\tconst uint8_t playerLevel = player.getCharacterLevel();\r\n\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(player._pClass);\r\n\r\n\tif (HasAnyOf(classAttributes.classFlags, PlayerClassFlag::NaturalResistance)) {\r\n\t\tmagic += playerLevel;\r\n\t\tfire += playerLevel;\r\n\t\tlightning += playerLevel;\r\n\t}\r\n\r\n\tif (HasAnyOf(player._pSpellFlags, SpellFlag::RageCooldown)) {\r\n\t\tmagic -= playerLevel;\r\n\t\tfire -= playerLevel;\r\n\t\tlightning -= playerLevel;\r\n\t}\r\n\r\n\tif (HasAnyOf(iflgs, ItemSpecialEffect::ZeroResistance)) {\r\n\t\t// reset resistances to zero if the respective special effect is active\r\n\t\tmagic = 0;\r\n\t\tfire = 0;\r\n\t\tlightning = 0;\r\n\t}\r\n\r\n\tplayer._pMagResist = std::clamp(magic, 0, MaxResistance);\r\n\tplayer._pFireResist = std::clamp(fire, 0, MaxResistance);\r\n\tplayer._pLghtResist = std::clamp(lightning, 0, MaxResistance);\r\n}\r\n\r\nvoid CalcPlrLifeMana(Player &player, int vitality, int magic, int life, int mana)\r\n{\r\n\tconst ClassAttributes &playerClassAttributes = player.getClassAttributes();\r\n\tvitality = (vitality * playerClassAttributes.itmLife) >> 6;\r\n\tlife += (vitality << 6);\r\n\r\n\tmagic = (magic * playerClassAttributes.itmMana) >> 6;\r\n\tmana += (magic << 6);\r\n\r\n\tplayer._pMaxHP = std::clamp(life + player._pMaxHPBase, 1 << 6, 2000 << 6);\r\n\tplayer._pHitPoints = std::min(life + player._pHPBase, player._pMaxHP);\r\n\r\n\tif (&player == MyPlayer && player.hasNoLife()) {\r\n\t\tSetPlayerHitPoints(player, 0);\r\n\t}\r\n\r\n\tplayer._pMaxMana = std::clamp(mana + player._pMaxManaBase, 0, 2000 << 6);\r\n\tplayer._pMana = std::min(mana + player._pManaBase, player._pMaxMana);\r\n}\r\n\r\nvoid CalcPlrBlockFlag(Player &player)\r\n{\r\n\tconst auto &leftHandItem = player.InvBody[INVLOC_HAND_LEFT];\r\n\tconst auto &rightHandItem = player.InvBody[INVLOC_HAND_RIGHT];\r\n\r\n\tplayer._pBlockFlag = false;\r\n\r\n\tif (player._pClass == HeroClass::Monk) {\r\n\t\tif (player.isHoldingItem(ItemType::Staff)) {\r\n\t\t\tplayer._pBlockFlag = true;\r\n\t\t\tplayer._pIFlags |= ItemSpecialEffect::FastBlock;\r\n\t\t} else if ((leftHandItem.isEmpty() && rightHandItem.isEmpty()) || (leftHandItem._iClass == ICLASS_WEAPON && leftHandItem._iLoc != ILOC_TWOHAND && rightHandItem.isEmpty()) || (rightHandItem._iClass == ICLASS_WEAPON && rightHandItem._iLoc != ILOC_TWOHAND && leftHandItem.isEmpty())) {\r\n\t\t\tplayer._pBlockFlag = true;\r\n\t\t}\r\n\t}\r\n\r\n\tplayer._pBlockFlag = player._pBlockFlag || player.isHoldingItem(ItemType::Shield);\r\n}\r\n\r\nPlayerWeaponGraphic GetPlrAnimWeaponId(const Player &player)\r\n{\r\n\tconst Item &leftHandItem = player.InvBody[INVLOC_HAND_LEFT];\r\n\tconst Item &rightHandItem = player.InvBody[INVLOC_HAND_RIGHT];\r\n\tconst bool holdsShield = player.isHoldingItem(ItemType::Shield);\r\n\tconst bool leftHandUsable = player.CanUseItem(leftHandItem);\r\n\tconst bool rightHandUsable = player.CanUseItem(rightHandItem);\r\n\tItemType weaponItemType = ItemType::None;\r\n\r\n\tif (!leftHandItem.isEmpty() && leftHandItem._iClass == ICLASS_WEAPON && leftHandUsable) {\r\n\t\tweaponItemType = leftHandItem._itype;\r\n\t}\r\n\r\n\tif (!rightHandItem.isEmpty() && rightHandItem._iClass == ICLASS_WEAPON && rightHandUsable) {\r\n\t\tweaponItemType = rightHandItem._itype;\r\n\t}\r\n\r\n\tswitch (weaponItemType) {\r\n\tcase ItemType::Sword:\r\n\t\treturn holdsShield ? PlayerWeaponGraphic::SwordShield : PlayerWeaponGraphic::Sword;\r\n\tcase ItemType::Axe:\r\n\t\treturn PlayerWeaponGraphic::Axe;\r\n\tcase ItemType::Bow:\r\n\t\treturn PlayerWeaponGraphic::Bow;\r\n\tcase ItemType::Mace:\r\n\t\treturn holdsShield ? PlayerWeaponGraphic::MaceShield : PlayerWeaponGraphic::Mace;\r\n\tcase ItemType::Staff:\r\n\t\treturn PlayerWeaponGraphic::Staff;\r\n\tdefault:\r\n\t\treturn holdsShield ? PlayerWeaponGraphic::UnarmedShield : PlayerWeaponGraphic::Unarmed;\r\n\t}\r\n}\r\n\r\nPlayerArmorGraphic GetPlrAnimArmorId(Player &player)\r\n{\r\n\tconst Item &chestItem = player.InvBody[INVLOC_CHEST];\r\n\tconst bool chestUsable = player.CanUseItem(chestItem);\r\n\tconst uint8_t playerLevel = player.getCharacterLevel();\r\n\r\n\tif (chestUsable) {\r\n\t\tswitch (chestItem._itype) {\r\n\t\tcase ItemType::HeavyArmor:\r\n\t\t\tif (player._pClass == HeroClass::Monk) {\r\n\t\t\t\tif (chestItem._iMagical == ITEM_QUALITY_UNIQUE)\r\n\t\t\t\t\tplayer._pIAC += playerLevel / 2;\r\n\t\t\t}\r\n\t\t\treturn PlayerArmorGraphic::Heavy;\r\n\t\tcase ItemType::MediumArmor:\r\n\t\t\tif (player._pClass == HeroClass::Monk) {\r\n\t\t\t\tif (chestItem._iMagical == ITEM_QUALITY_UNIQUE)\r\n\t\t\t\t\tplayer._pIAC += playerLevel * 2;\r\n\t\t\t\telse\r\n\t\t\t\t\tplayer._pIAC += playerLevel / 2;\r\n\t\t\t}\r\n\t\t\treturn PlayerArmorGraphic::Medium;\r\n\t\tdefault:\r\n\t\t\tif (player._pClass == HeroClass::Monk)\r\n\t\t\t\tplayer._pIAC += playerLevel * 2;\r\n\t\t\treturn PlayerArmorGraphic::Light;\r\n\t\t}\r\n\t}\r\n\r\n\treturn PlayerArmorGraphic::Light;\r\n}\r\n\r\nvoid CalcPlrGraphics(Player &player, PlayerWeaponGraphic animWeaponId, PlayerArmorGraphic animArmorId, bool loadgfx)\r\n{\r\n\tconst uint8_t gfxNum = static_cast<uint8_t>(animWeaponId) | static_cast<uint8_t>(animArmorId);\r\n\tif (player._pgfxnum != gfxNum && loadgfx) {\r\n\t\tplayer._pgfxnum = gfxNum;\r\n\t\tResetPlayerGFX(player);\r\n\t\tSetPlrAnims(player);\r\n\t\tplayer.previewCelSprite = std::nullopt;\r\n\t\tconst player_graphic graphic = player.getGraphic();\r\n\t\tint8_t numberOfFrames;\r\n\t\tint8_t ticksPerFrame;\r\n\t\tplayer.getAnimationFramesAndTicksPerFrame(graphic, numberOfFrames, ticksPerFrame);\r\n\t\tLoadPlrGFX(player, graphic);\r\n\t\tOptionalClxSpriteList sprites;\r\n\t\tif (!HeadlessMode)\r\n\t\t\tsprites = player.AnimationData[static_cast<size_t>(graphic)].spritesForDirection(player._pdir);\r\n\t\tplayer.AnimInfo.changeAnimationData(sprites, numberOfFrames, ticksPerFrame);\r\n\t} else {\r\n\t\tplayer._pgfxnum = gfxNum;\r\n\t}\r\n}\r\n\r\nvoid CalcPlrAuricBonus(Player &player)\r\n\r\n{\r\n\tif (&player == MyPlayer) {\r\n\t\tif (player.InvBody[INVLOC_AMULET].isEmpty() || player.InvBody[INVLOC_AMULET].IDidx != IDI_AURIC) {\r\n\t\t\tconst int half = MaxGold;\r\n\t\t\tMaxGold = GOLD_MAX_LIMIT;\r\n\r\n\t\t\tif (half != MaxGold)\r\n\t\t\t\tStripTopGold(player);\r\n\t\t} else {\r\n\t\t\tMaxGold = GOLD_MAX_LIMIT * 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CalcPlrItemVals(Player &player, bool loadgfx)\r\n{\r\n\tint minDamage = 0;\r\n\tint maxDamage = 0;\r\n\tint ac = 0;\r\n\r\n\tint dam = 0;\r\n\tint toHit = 0;\r\n\tint bonusAc = 0;\r\n\r\n\tItemSpecialEffect flags = ItemSpecialEffect::None;\r\n\tItemSpecialEffectHf damAcFlags = ItemSpecialEffectHf::None;\r\n\r\n\tint strength = 0;\r\n\tint magic = 0;\r\n\tint dexterity = 0;\r\n\tint vitality = 0;\r\n\r\n\tuint64_t spells = 0;\r\n\r\n\tint fireRes = 0;\r\n\tint lightRes = 0;\r\n\tint magicRes = 0;\r\n\r\n\tint damMod = 0;\r\n\tint getHit = 0;\r\n\r\n\tint lightRadius = 10;\r\n\r\n\tint life = 0;\r\n\tint mana = 0;\r\n\r\n\tint8_t splLvlAdd = 0;\r\n\tint targetAc = 0;\r\n\r\n\tint minFireDam = 0;\r\n\tint maxFireDam = 0;\r\n\tint minLightDam = 0;\r\n\tint maxLightDam = 0;\r\n\r\n\tfor (const Item &item : player.InvBody) {\r\n\t\tif (!item.isEmpty() && item._iStatFlag) {\r\n\r\n\t\t\tminDamage += item._iMinDam;\r\n\t\t\tmaxDamage += item._iMaxDam;\r\n\t\t\tac += item._iAC;\r\n\r\n\t\t\tif (IsValidSpell(item._iSpell) && item._iCharges != 0) {\r\n\t\t\t\tspells |= GetSpellBitmask(item._iSpell);\r\n\t\t\t}\r\n\r\n\t\t\tif (item._iMagical == ITEM_QUALITY_NORMAL || item._iIdentified) {\r\n\t\t\t\tdam += item._iPLDam;\r\n\t\t\t\ttoHit += item._iPLToHit;\r\n\t\t\t\tbonusAc += GetBonusAC(item);\r\n\t\t\t\tflags |= item._iFlags;\r\n\t\t\t\tdamAcFlags |= item._iDamAcFlags;\r\n\t\t\t\tstrength += item._iPLStr;\r\n\t\t\t\tmagic += item._iPLMag;\r\n\t\t\t\tdexterity += item._iPLDex;\r\n\t\t\t\tvitality += item._iPLVit;\r\n\t\t\t\tfireRes += item._iPLFR;\r\n\t\t\t\tlightRes += item._iPLLR;\r\n\t\t\t\tmagicRes += item._iPLMR;\r\n\t\t\t\tdamMod += item._iPLDamMod;\r\n\t\t\t\tgetHit += item._iPLGetHit;\r\n\t\t\t\tlightRadius += item._iPLLight;\r\n\t\t\t\tlife += item._iPLHP;\r\n\t\t\t\tmana += item._iPLMana;\r\n\t\t\t\tsplLvlAdd += item._iSplLvlAdd;\r\n\t\t\t\ttargetAc += item._iPLEnAc;\r\n\t\t\t\tminFireDam += item._iFMinDam;\r\n\t\t\t\tmaxFireDam += item._iFMaxDam;\r\n\t\t\t\tminLightDam += item._iLMinDam;\r\n\t\t\t\tmaxLightDam += item._iLMaxDam;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tCalcPlrDamage(player, minDamage, maxDamage);\r\n\tCalcPlrPrimaryStats(player, strength, magic, dexterity, vitality);\r\n\tplayer._pIAC = ac;\r\n\tplayer._pIBonusDam = dam;\r\n\tplayer._pIBonusToHit = toHit;\r\n\tplayer._pIBonusAC = bonusAc;\r\n\tplayer._pIFlags = flags;\r\n\tplayer.pDamAcFlags = damAcFlags;\r\n\tplayer._pIBonusDamMod = damMod;\r\n\tplayer._pIGetHit = getHit;\r\n\tCalcPlrLightRadius(player, lightRadius);\r\n\tCalcPlrDamageMod(player);\r\n\tplayer._pISpells = spells;\r\n\tEnsureValidReadiedSpell(player);\r\n\tplayer._pISplLvlAdd = splLvlAdd;\r\n\tplayer._pIEnAc = targetAc;\r\n\tCalcPlrResistances(player, flags, fireRes, lightRes, magicRes);\r\n\tCalcPlrLifeMana(player, vitality, magic, life, mana);\r\n\tplayer._pIFMinDam = minFireDam;\r\n\tplayer._pIFMaxDam = maxFireDam;\r\n\tplayer._pILMinDam = minLightDam;\r\n\tplayer._pILMaxDam = maxLightDam;\r\n\r\n\tCalcPlrBlockFlag(player);\r\n\r\n\tCalcPlrGraphics(player, GetPlrAnimWeaponId(player), GetPlrAnimArmorId(player), loadgfx);\r\n\r\n\tCalcPlrAuricBonus(player);\r\n\tRedrawComponent(PanelDrawComponent::Mana);\r\n\tRedrawComponent(PanelDrawComponent::Health);\r\n}\r\n\r\nvoid CalcPlrInv(Player &player, bool loadgfx)\r\n{\r\n\t// Determine the players current stats, this updates the statFlag on all equipped items that became unusable after\r\n\t//  a change in equipment.\r\n\tCalcSelfItems(player);\r\n\r\n\t// Determine the current item bonuses gained from usable equipped items\r\n\tif (&player != MyPlayer && !player.isOnActiveLevel()) {\r\n\t\t// Ensure we don't load graphics for players that aren't on our level\r\n\t\tloadgfx = false;\r\n\t}\r\n\tCalcPlrItemVals(player, loadgfx);\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\t// Now that stat gains from equipped items have been calculated, mark unusable scrolls etc\r\n\t\tfor (Item &item : InventoryAndBeltPlayerItemsRange { player }) {\r\n\t\t\titem.updateRequiredStatsCacheForPlayer(player);\r\n\t\t}\r\n\t\tplayer.CalcScrolls();\r\n\t\tif (IsStashOpen) {\r\n\t\t\t// If stash is open, ensure the items are displayed correctly\r\n\t\t\tStash.RefreshItemStatFlags();\r\n\t\t}\r\n\t\tif (!player.HoldItem.isEmpty())\r\n\t\t\tplayer.HoldItem.updateRequiredStatsCacheForPlayer(player);\r\n\t}\r\n}\r\n\r\nvoid InitializeItem(Item &item, _item_indexes itemData)\r\n{\r\n\tauto &pAllItem = AllItemsList[static_cast<size_t>(itemData)];\r\n\r\n\t// zero-initialize struct\r\n\titem = {};\r\n\r\n\titem._itype = pAllItem.itype;\r\n\titem._iCurs = pAllItem.iCurs;\r\n\tCopyUtf8(item._iName, pAllItem.iName, ItemNameLength);\r\n\tCopyUtf8(item._iIName, pAllItem.iName, ItemNameLength);\r\n\titem._iLoc = pAllItem.iLoc;\r\n\titem._iClass = pAllItem.iClass;\r\n\titem._iMinDam = pAllItem.iMinDam;\r\n\titem._iMaxDam = pAllItem.iMaxDam;\r\n\titem._iAC = pAllItem.iMinAC;\r\n\titem._iMiscId = pAllItem.iMiscId;\r\n\titem._iSpell = pAllItem.iSpell;\r\n\r\n\tif (pAllItem.iMiscId == IMISC_STAFF) {\r\n\t\titem._iCharges = gbIsHellfire ? 18 : 40;\r\n\t}\r\n\r\n\titem._iMaxCharges = item._iCharges;\r\n\titem._iDurability = pAllItem.iDurability;\r\n\titem._iMaxDur = pAllItem.iDurability;\r\n\titem._iMinStr = pAllItem.iMinStr;\r\n\titem._iMinMag = pAllItem.iMinMag;\r\n\titem._iMinDex = pAllItem.iMinDex;\r\n\titem._ivalue = pAllItem.iValue;\r\n\titem._iIvalue = pAllItem.iValue;\r\n\titem._iPrePower = IPL_INVALID;\r\n\titem._iSufPower = IPL_INVALID;\r\n\titem._iMagical = ITEM_QUALITY_NORMAL;\r\n\titem.IDidx = itemData;\r\n\tif (gbIsHellfire)\r\n\t\titem.dwBuff |= CF_HELLFIRE;\r\n}\r\n\r\nvoid GenerateNewSeed(Item &item)\r\n{\r\n\titem._iSeed = AdvanceRndSeed();\r\n}\r\n\r\nint GetGoldCursor(int value)\r\n{\r\n\tif (value >= GOLD_MEDIUM_LIMIT)\r\n\t\treturn ICURS_GOLD_LARGE;\r\n\r\n\tif (value <= GOLD_SMALL_LIMIT)\r\n\t\treturn ICURS_GOLD_SMALL;\r\n\r\n\treturn ICURS_GOLD_MEDIUM;\r\n}\r\n\r\nvoid SetPlrHandGoldCurs(Item &gold)\r\n{\r\n\tgold._iCurs = GetGoldCursor(gold._ivalue);\r\n}\r\n\r\nnamespace {\r\nvoid CreateStartingItem(Player &player, _item_indexes itemData)\r\n{\r\n\tItem item;\r\n\tInitializeItem(item, itemData);\r\n\tGenerateNewSeed(item);\r\n\titem.updateRequiredStatsCacheForPlayer(player);\r\n\tAutoEquip(player, item) || AutoPlaceItemInBelt(player, item, true) || AutoPlaceItemInInventory(player, item);\r\n}\r\n} // namespace\r\n\r\nvoid CreatePlrItems(Player &player)\r\n{\r\n\tfor (auto &item : player.InvBody) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\t// converting this to a for loop creates a `rep stosd` instruction,\r\n\t// so this probably actually was a memset\r\n\tmemset(&player.InvGrid, 0, sizeof(player.InvGrid));\r\n\r\n\tfor (auto &item : player.InvList) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\tplayer._pNumInv = 0;\r\n\r\n\tfor (auto &item : player.SpdList) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\tconst PlayerStartingLoadoutData &loadout = GetPlayerStartingLoadoutForClass(player._pClass);\r\n\r\n\tif (loadout.spell != SpellID::Null && loadout.spellLevel > 0) {\r\n\t\tplayer._pMemSpells = GetSpellBitmask(loadout.spell);\r\n\t\tplayer._pRSplType = SpellType::Spell;\r\n\t\tplayer._pRSpell = loadout.spell;\r\n\t\tplayer._pSplLvl[static_cast<unsigned>(loadout.spell)] = loadout.spellLevel;\r\n\t} else {\r\n\t\tplayer._pMemSpells = 0;\r\n\t}\r\n\r\n\tif (loadout.skill != SpellID::Null) {\r\n\t\tplayer._pAblSpells = GetSpellBitmask(loadout.skill);\r\n\t\tif (player._pRSplType == SpellType::Invalid) {\r\n\t\t\tplayer._pRSplType = SpellType::Skill;\r\n\t\t\tplayer._pRSpell = loadout.skill;\r\n\t\t}\r\n\t}\r\n\r\n\tInitCursor();\r\n\tfor (const _item_indexes itemData : loadout.items) {\r\n\t\tif (itemData != _item_indexes::IDI_NONE)\r\n\t\t\tCreateStartingItem(player, itemData);\r\n\t}\r\n\tFreeCursor();\r\n\r\n\tif (loadout.gold > 0) {\r\n\t\tItem &goldItem = player.InvList[player._pNumInv];\r\n\t\tMakeGoldStack(goldItem, loadout.gold);\r\n\r\n\t\tplayer._pNumInv++;\r\n\t\tplayer.InvGrid[30] = player._pNumInv;\r\n\r\n\t\tplayer._pGold = goldItem._ivalue;\r\n\t}\r\n\r\n\tCalcPlrItemVals(player, false);\r\n}\r\n\r\nbool ItemSpaceOk(Point position)\r\n{\r\n\tif (!InDungeonBounds(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (IsTileSolid(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (dItem[position.x][position.y] != 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (dMonster[position.x][position.y] != 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (dPlayer[position.x][position.y] != 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (IsItemBlockingObjectAtPosition(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nint AllocateItem()\r\n{\r\n\tassert(ActiveItemCount < MAXITEMS);\r\n\r\n\tconst int inum = ActiveItems[ActiveItemCount];\r\n\tActiveItemCount++;\r\n\r\n\tItems[inum] = {};\r\n\r\n\treturn inum;\r\n}\r\n\r\nuint8_t PlaceItemInWorld(Item &&item, WorldTilePosition position)\r\n{\r\n\tassert(ActiveItemCount < MAXITEMS);\r\n\r\n\tconst uint8_t ii = ActiveItems[ActiveItemCount];\r\n\tActiveItemCount++;\r\n\r\n\tdItem[position.x][position.y] = static_cast<int8_t>(ii + 1);\r\n\tauto &newItem = Items[ii];\r\n\tnewItem = std::move(item);\r\n\tnewItem.position = position;\r\n\tRespawnItem(newItem, true);\r\n\r\n\tif (CornerStone.isAvailable() && position == CornerStone.position) {\r\n\t\tCornerStone.item = newItem;\r\n\t\tInitQTextMsg(TEXT_CORNSTN);\r\n\t\tQuests[Q_CORNSTN]._qactive = QUEST_DONE;\r\n\t}\r\n\r\n\treturn ii;\r\n}\r\n\r\nPoint GetSuperItemLoc(Point position)\r\n{\r\n\tconst std::optional<Point> itemPosition = FindClosestValidPosition(ItemSpaceOk, position, 1, 50);\r\n\r\n\treturn itemPosition.value_or(Point { 0, 0 }); // TODO handle no space for dropping items\r\n}\r\n\r\nvoid GetItemAttrs(Item &item, _item_indexes itemData, int lvl)\r\n{\r\n\tauto &baseItemData = AllItemsList[static_cast<size_t>(itemData)];\r\n\titem._itype = baseItemData.itype;\r\n\titem._iCurs = baseItemData.iCurs;\r\n\tCopyUtf8(item._iName, baseItemData.iName, ItemNameLength);\r\n\tCopyUtf8(item._iIName, baseItemData.iName, ItemNameLength);\r\n\titem._iLoc = baseItemData.iLoc;\r\n\titem._iClass = baseItemData.iClass;\r\n\titem._iMinDam = baseItemData.iMinDam;\r\n\titem._iMaxDam = baseItemData.iMaxDam;\r\n\titem._iAC = baseItemData.iMinAC + GenerateRnd(baseItemData.iMaxAC - baseItemData.iMinAC + 1);\r\n\titem._iFlags = baseItemData.iFlags;\r\n\titem._iMiscId = baseItemData.iMiscId;\r\n\titem._iSpell = baseItemData.iSpell;\r\n\titem._iMagical = ITEM_QUALITY_NORMAL;\r\n\titem._ivalue = baseItemData.iValue;\r\n\titem._iIvalue = baseItemData.iValue;\r\n\titem._iDurability = baseItemData.iDurability;\r\n\titem._iMaxDur = baseItemData.iDurability;\r\n\titem._iMinStr = baseItemData.iMinStr;\r\n\titem._iMinMag = baseItemData.iMinMag;\r\n\titem._iMinDex = baseItemData.iMinDex;\r\n\titem.IDidx = itemData;\r\n\tif (gbIsHellfire)\r\n\t\titem.dwBuff |= CF_HELLFIRE;\r\n\titem._iPrePower = IPL_INVALID;\r\n\titem._iSufPower = IPL_INVALID;\r\n\r\n\tif (item._iMiscId == IMISC_BOOK)\r\n\t\tGetBookSpell(item, lvl);\r\n\r\n\tif (gbIsHellfire && item._iMiscId == IMISC_OILOF)\r\n\t\tGetOilType(item, lvl);\r\n\r\n\tif (item._itype != ItemType::Gold)\r\n\t\treturn;\r\n\r\n\tint rndv;\r\n\tconst int itemlevel = ItemsGetCurrlevel();\r\n\tswitch (sgGameInitInfo.nDifficulty) {\r\n\tcase DIFF_NORMAL:\r\n\t\trndv = 5 * itemlevel + GenerateRnd(10 * itemlevel);\r\n\t\tbreak;\r\n\tcase DIFF_NIGHTMARE:\r\n\t\trndv = 5 * (itemlevel + 16) + GenerateRnd(10 * (itemlevel + 16));\r\n\t\tbreak;\r\n\tcase DIFF_HELL:\r\n\t\trndv = 5 * (itemlevel + 32) + GenerateRnd(10 * (itemlevel + 32));\r\n\t\tbreak;\r\n\t}\r\n\tif (leveltype == DTYPE_HELL)\r\n\t\trndv += rndv / 8;\r\n\r\n\titem._ivalue = std::min(rndv, GOLD_MAX_LIMIT);\r\n\tSetPlrHandGoldCurs(item);\r\n}\r\n\r\nvoid SetupItem(Item &item)\r\n{\r\n\titem.setNewAnimation(MyPlayer != nullptr && MyPlayer->pLvlLoad == 0);\r\n\titem._iIdentified = false;\r\n}\r\n\r\nItem *SpawnUnique(_unique_items uid, Point position, std::optional<int> level /*= std::nullopt*/, bool sendmsg /*= true*/, bool exactPosition /*= false*/)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn nullptr;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\tif (exactPosition && CanPut(position)) {\r\n\t\titem.position = position;\r\n\t\tdItem[position.x][position.y] = ii + 1;\r\n\t} else {\r\n\t\tGetSuperItemSpace(position, ii);\r\n\t}\r\n\tint curlv = ItemsGetCurrlevel();\r\n\r\n\tstd::underlying_type_t<_item_indexes> idx = 0;\r\n\twhile (AllItemsList[idx].iItemId != UniqueItems[uid].UIItemId)\r\n\t\tidx++;\r\n\r\n\tif (sgGameInitInfo.nDifficulty == DIFF_NORMAL) {\r\n\t\tGetItemAttrs(item, static_cast<_item_indexes>(idx), curlv);\r\n\t\tGetUniqueItem(*MyPlayer, item, uid);\r\n\t\tSetupItem(item);\r\n\t} else {\r\n\t\tif (level)\r\n\t\t\tcurlv = *level;\r\n\t\tconst ItemData &uniqueItemData = AllItemsList[idx];\r\n\t\tconst _item_indexes dropIdx = GetItemIndexForDroppableItem(false, [&uniqueItemData](const ItemData &item) {\r\n\t\t\treturn item.itype == uniqueItemData.itype;\r\n\t\t});\r\n\t\tSetupAllItems(*MyPlayer, item, dropIdx, AdvanceRndSeed(), curlv * 2, 15, true, false);\r\n\t\tTryRandomUniqueItem(item, dropIdx, curlv * 2, 15, true, false);\r\n\t\tSetupItem(item);\r\n\t}\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdPItem(false, CMD_SPAWNITEM, item.position, item);\r\n\r\n\treturn &item;\r\n}\r\n\r\nvoid GetSuperItemSpace(Point position, int8_t inum)\r\n{\r\n\tPoint positionToCheck = position;\r\n\tif (GetItemSpace(positionToCheck, inum))\r\n\t\treturn;\r\n\tfor (int k = 2; k < 50; k++) {\r\n\t\tfor (int j = -k; j <= k; j++) {\r\n\t\t\tfor (int i = -k; i <= k; i++) {\r\n\t\t\t\tconst Displacement offset = { i, j };\r\n\t\t\t\tpositionToCheck = position + offset;\r\n\t\t\t\tif (!ItemSpaceOk(positionToCheck))\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tItems[inum].position = positionToCheck;\r\n\t\t\t\tdItem[positionToCheck.x][positionToCheck.y] = inum + 1;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n_item_indexes RndItemForMonsterLevel(int8_t monsterLevel)\r\n{\r\n\tif (GenerateRnd(100) > 40)\r\n\t\treturn IDI_NONE;\r\n\r\n\tif (GenerateRnd(100) > 25)\r\n\t\treturn IDI_GOLD;\r\n\r\n\treturn GetItemIndexForDroppableItem(true, [&monsterLevel](const ItemData &item) {\r\n\t\treturn item.iMinMLvl <= monsterLevel;\r\n\t});\r\n}\r\n\r\nvoid SetupAllItems(const Player &player, Item &item, _item_indexes idx, uint32_t iseed, int lvl, int uper, bool onlygood, bool pregen, int uidOffset /*= 0*/, bool forceNotUnique /*= false*/)\r\n{\r\n\titem._iSeed = iseed;\r\n\tSetRndSeed(iseed);\r\n\tGetItemAttrs(item, idx, lvl / 2);\r\n\titem._iCreateInfo = lvl;\r\n\r\n\tif (pregen)\r\n\t\titem._iCreateInfo |= CF_PREGEN;\r\n\tif (onlygood)\r\n\t\titem._iCreateInfo |= CF_ONLYGOOD;\r\n\r\n\tif (uper == 15)\r\n\t\titem._iCreateInfo |= CF_UPER15;\r\n\telse if (uper == 1)\r\n\t\titem._iCreateInfo |= CF_UPER1;\r\n\r\n\tif (item._iMiscId != IMISC_UNIQUE) {\r\n\t\tconst int iblvl = GetItemBLevel(lvl, item._iMiscId, onlygood, uper == 15);\r\n\t\tif (iblvl != -1) {\r\n\t\t\t_unique_items uid = UITEM_INVALID;\r\n\t\t\tif (!forceNotUnique) {\r\n\t\t\t\tuid = CheckUnique(item, iblvl, uper, uidOffset);\r\n\t\t\t} else {\r\n\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t}\r\n\t\t\tif (uid == UITEM_INVALID) {\r\n\t\t\t\tGetItemBonus(player, item, iblvl / 2, iblvl, onlygood, true);\r\n\t\t\t} else {\r\n\t\t\t\tGetUniqueItem(player, item, uid);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (item._iMagical != ITEM_QUALITY_UNIQUE)\r\n\t\t\tItemRndDur(item);\r\n\t} else {\r\n\t\tif (item._iLoc != ILOC_UNEQUIPABLE) {\r\n\t\t\tif (iseed > 109 || AllItemsList[static_cast<size_t>(idx)].iItemId != UniqueItems[iseed].UIItemId) {\r\n\t\t\t\titem.clear();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tGetUniqueItem(player, item, (_unique_items)iseed); // uid is stored in iseed for uniques\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid TryRandomUniqueItem(Item &item, _item_indexes idx, int8_t mLevel, int uper, bool onlygood, bool pregen)\r\n{\r\n\t// If the item is a non-quest unique, find a random valid uid and force generate items to get an item with that uid.\r\n\tif ((item._iCreateInfo & CF_UNIQUE) == 0 || item._iMiscId == IMISC_UNIQUE)\r\n\t\treturn;\r\n\r\n\tSetRndSeed(item._iSeed);\r\n\r\n\t// Get item base level, which is used in CheckUnique to get the correct valid uniques for the base item.\r\n\tDiscardRandomValues(1); // GetItemAttrs\r\n\tconst int blvl = GetItemBLevel(mLevel, item._iMiscId, onlygood, uper == 15);\r\n\r\n\t// Gather all potential unique items. uid is the index into UniqueItems.\r\n\tauto validUniques = GetValidUniques(blvl, AllItemsList[static_cast<size_t>(idx)].iItemId);\r\n\tassert(!validUniques.empty());\r\n\tstd::vector<int> uids;\r\n\tfor (auto &possibleUid : validUniques) {\r\n\t\t// Verify item hasn't been dropped yet. We set this to true in MP, since uniques previously dropping shouldn't prevent further identical uniques from dropping.\r\n\t\tif (!UniqueItemFlags[possibleUid] || gbIsMultiplayer) {\r\n\t\t\tuids.emplace_back(possibleUid);\r\n\t\t}\r\n\t}\r\n\r\n\t// If we find at least one unique in uids that hasn't been obtained yet, we can proceed getting a random unique.\r\n\tif (uids.empty()) {\r\n\t\t// Set uper to 1 and make the level adjustment so we have better odds of not generating a unique item.\r\n\t\tif (uper == 15)\r\n\t\t\tmLevel += 4;\r\n\t\tuper = 1;\r\n\r\n\t\tconst Point itemPos = item.position;\r\n\r\n\t\t// Force generate a non-unique item.\r\n\t\tDiabloGenerator itemGenerator(item._iSeed);\r\n\t\tdo {\r\n\t\t\titem = {}; // Reset item data\r\n\t\t\titem.position = itemPos;\r\n\t\t\tSetupAllItems(*MyPlayer, item, idx, itemGenerator.advanceRndSeed(), mLevel, uper, onlygood, pregen);\r\n\t\t} while (item._iMagical == ITEM_QUALITY_UNIQUE);\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int32_t uidsIdx = std::max<int32_t>(0, GenerateRnd(static_cast<int32_t>(uids.size()))); // Index into uids, used to get a random uid from the uids vector.\r\n\tconst int uid = uids[uidsIdx];                                                                // Actual unique id.\r\n\tconst UniqueItem &uniqueItem = UniqueItems[uid];\r\n\r\n\t// If the selected unique was already generated, there is no need to fiddle with its parameters.\r\n\tif (item._iUid == uid) {\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tUniqueItemFlags[uid] = true;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Find our own id to calculate the offset in validUniques and check if we can generate a reverse-compatible version of the item.\r\n\tint uidOffset = -1;\r\n\tbool canGenerateReverseCompatible = true;\r\n\tfor (size_t i = 0; i < validUniques.size(); i++) {\r\n\t\tif (validUniques[i] == uid) {\r\n\t\t\t// Vanilla always picks the last unique, so the offset is calculated from the back of the valid unique list.\r\n\t\t\tuidOffset = static_cast<int>(validUniques.size() - i - 1);\r\n\t\t} else if (uidOffset != -1 && UniqueItems[validUniques[i]].UIMinLvl <= uniqueItem.UIMinLvl) {\r\n\t\t\t// Found an item with same or lower level as our desired unique after our unique.\r\n\t\t\t// This means that we cannot possibly generate the item in reverse compatible mode and must rely on an offset.\r\n\t\t\tcanGenerateReverseCompatible = false;\r\n\t\t}\r\n\t}\r\n\tassert(uidOffset != -1);\r\n\r\n\tconst Point itemPos = item.position;\r\n\tif (canGenerateReverseCompatible) {\r\n\t\tint targetLvl = 1; // Target level for reverse compatibility, since vanilla always takes the last applicable uid in the list.\r\n\r\n\t\t// Set target level. Ideally we use uper 15 to have a 16% chance of generating a unique item.\r\n\t\tif (uniqueItem.UIMinLvl - 4 > 0) { // Negative level will underflow. Lvl 0 items may have unintended consequences.\r\n\t\t\tuper = 15;\r\n\t\t\ttargetLvl = uniqueItem.UIMinLvl - 4;\r\n\t\t} else {\r\n\t\t\tuper = 1;\r\n\t\t\ttargetLvl = uniqueItem.UIMinLvl;\r\n\t\t}\r\n\r\n\t\t// Force generate items until we find a uid match.\r\n\t\tDiabloGenerator itemGenerator(item._iSeed);\r\n\t\tdo {\r\n\t\t\titem = {}; // Reset item data\r\n\t\t\titem.position = itemPos;\r\n\t\t\t// Set onlygood = true, to always get the required item base level for the unique.\r\n\t\t\tSetupAllItems(*MyPlayer, item, idx, itemGenerator.advanceRndSeed(), targetLvl, uper, true, pregen);\r\n\t\t} while (item._iUid != uid);\r\n\t} else {\r\n\t\t// Recreate the item with new offset, this creates the desired unique item but is not reverse compatible.\r\n\t\tconst int seed = item._iSeed;\r\n\t\titem = {}; // Reset item data\r\n\t\titem.position = itemPos;\r\n\t\tSetupAllItems(*MyPlayer, item, idx, seed, mLevel, uper, onlygood, pregen, uidOffset);\r\n\t\titem.dwBuff |= (uidOffset << 1) & CF_UIDOFFSET;\r\n\t\tassert(item._iUid == uid);\r\n\t}\r\n\r\n\t// Set item as obtained to prevent it from being dropped again in SP.\r\n\tif (!gbIsMultiplayer) {\r\n\t\tUniqueItemFlags[uid] = true;\r\n\t}\r\n}\r\n\r\nvoid SpawnItem(Monster &monster, Point position, bool sendmsg, bool spawn /*= false*/)\r\n{\r\n\t_item_indexes idx;\r\n\tbool onlygood = true;\r\n\r\n\tconst bool dropsSpecialTreasure = (monster.data().treasure & T_UNIQ) != 0;\r\n\tconst bool dropBrain = Quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE && Quests[Q_MUSHROOM]._qvar1 == QS_MUSHGIVEN;\r\n\r\n\tif (dropsSpecialTreasure && !UseMultiplayerQuests()) {\r\n\t\tItem *uniqueItem = SpawnUnique(static_cast<_unique_items>(monster.data().treasure & T_MASK), position, std::nullopt, false);\r\n\t\tif (uniqueItem != nullptr && sendmsg)\r\n\t\t\tNetSendCmdPItem(false, CMD_DROPITEM, uniqueItem->position, *uniqueItem);\r\n\t\treturn;\r\n\t}\r\n\tif (monster.isUnique() || dropsSpecialTreasure) {\r\n\t\t// Unique monster is killed => use better item base (for example no gold)\r\n\t\tidx = RndUItem(&monster);\r\n\t} else if (dropBrain && !gbIsMultiplayer) {\r\n\t\t// Normal monster is killed => need to drop brain to progress the quest\r\n\t\tQuests[Q_MUSHROOM]._qvar1 = QS_BRAINSPAWNED;\r\n\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t// brain replaces normal drop\r\n\t\tidx = IDI_BRAIN;\r\n\t} else {\r\n\t\tif (dropBrain && gbIsMultiplayer && sendmsg) {\r\n\t\t\tQuests[Q_MUSHROOM]._qvar1 = QS_BRAINSPAWNED;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t\t// Drop the brain as extra item to ensure that all clients see the brain drop\r\n\t\t\t// When executing SpawnItem is not reliable, because another client can already have the quest state updated before SpawnItem is executed\r\n\t\t\tconst Point posBrain = GetSuperItemLoc(position);\r\n\t\t\tSpawnQuestItem(IDI_BRAIN, posBrain, 0, SelectionRegion::None, true);\r\n\t\t}\r\n\t\t// Normal monster\r\n\t\tif ((monster.data().treasure & T_NODROP) != 0)\r\n\t\t\treturn;\r\n\t\tonlygood = false;\r\n\t\tidx = RndItemForMonsterLevel(static_cast<int8_t>(monster.level(sgGameInitInfo.nDifficulty)));\r\n\t}\r\n\r\n\tif (idx == IDI_NONE)\r\n\t\treturn;\r\n\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\tGetSuperItemSpace(position, ii);\r\n\tconst int uper = monster.isUnique() ? 15 : 1;\r\n\r\n\tconst int8_t mLevel = monster.data().level;\r\n\tSetupAllItems(*MyPlayer, item, idx, AdvanceRndSeed(), mLevel, uper, onlygood, false);\r\n\tTryRandomUniqueItem(item, idx, mLevel, uper, onlygood, false);\r\n\tSetupItem(item);\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdPItem(false, CMD_DROPITEM, item.position, item);\r\n\tif (spawn)\r\n\t\tNetSendCmdPItem(false, CMD_SPAWNITEM, item.position, item);\r\n}\r\n\r\nvoid CreateRndItem(Point position, bool onlygood, bool sendmsg, bool delta)\r\n{\r\n\tconst _item_indexes idx = onlygood ? RndUItem(nullptr) : RndAllItems();\r\n\r\n\tSetupBaseItem(position, idx, onlygood, sendmsg, delta);\r\n}\r\n\r\nvoid CreateRndUseful(Point position, bool sendmsg)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\tGetSuperItemSpace(position, ii);\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\r\n\tSetupAllUseful(item, AdvanceRndSeed(), curlv);\r\n\tif (sendmsg)\r\n\t\tNetSendCmdPItem(false, CMD_DROPITEM, item.position, item);\r\n}\r\n\r\nvoid CreateTypeItem(Point position, bool onlygood, ItemType itemType, int imisc, bool sendmsg, bool delta, bool spawn)\r\n{\r\n\t_item_indexes idx;\r\n\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\tif (itemType != ItemType::Gold)\r\n\t\tidx = RndTypeItems(itemType, imisc, curlv);\r\n\telse\r\n\t\tidx = IDI_GOLD;\r\n\r\n\tSetupBaseItem(position, idx, onlygood, sendmsg, delta, spawn);\r\n}\r\n\r\nvoid RecreateItem(const Player &player, Item &item, _item_indexes idx, uint16_t icreateinfo, uint32_t iseed, int ivalue, uint32_t dwBuff)\r\n{\r\n\tconst bool tmpIsHellfire = gbIsHellfire;\r\n\titem.dwBuff = dwBuff;\r\n\tgbIsHellfire = (item.dwBuff & CF_HELLFIRE) != 0;\r\n\r\n\tif (idx == IDI_GOLD) {\r\n\t\tInitializeItem(item, IDI_GOLD);\r\n\t\titem._iSeed = iseed;\r\n\t\titem._iCreateInfo = icreateinfo;\r\n\t\titem._ivalue = ivalue;\r\n\t\tSetPlrHandGoldCurs(item);\r\n\t\tgbIsHellfire = tmpIsHellfire;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (icreateinfo == 0) {\r\n\t\tInitializeItem(item, idx);\r\n\t\titem._iSeed = iseed;\r\n\t\tgbIsHellfire = tmpIsHellfire;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ((icreateinfo & CF_UNIQUE) == 0) {\r\n\t\tif ((icreateinfo & CF_TOWN) != 0) {\r\n\t\t\tRecreateTownItem(player, item, idx, icreateinfo, iseed);\r\n\t\t\tgbIsHellfire = tmpIsHellfire;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ((icreateinfo & CF_USEFUL) == CF_USEFUL) {\r\n\t\t\tSetupAllUseful(item, iseed, icreateinfo & CF_LEVEL);\r\n\t\t\tgbIsHellfire = tmpIsHellfire;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tconst int level = icreateinfo & CF_LEVEL;\r\n\r\n\tint uper = 0;\r\n\tif ((icreateinfo & CF_UPER1) != 0)\r\n\t\tuper = 1;\r\n\tif ((icreateinfo & CF_UPER15) != 0)\r\n\t\tuper = 15;\r\n\r\n\tconst bool onlygood = (icreateinfo & CF_ONLYGOOD) != 0;\r\n\tconst bool forceNotUnique = (icreateinfo & CF_UNIQUE) == 0;\r\n\tconst bool pregen = (icreateinfo & CF_PREGEN) != 0;\r\n\tauto uidOffset = static_cast<int>((item.dwBuff & CF_UIDOFFSET) >> 1);\r\n\r\n\tSetupAllItems(player, item, idx, iseed, level, uper, onlygood, pregen, uidOffset, forceNotUnique);\r\n\tSetupItem(item);\r\n\tgbIsHellfire = tmpIsHellfire;\r\n}\r\n\r\nvoid RecreateEar(Item &item, uint16_t ic, uint32_t iseed, uint8_t bCursval, std::string_view heroName)\r\n{\r\n\tInitializeItem(item, IDI_EAR);\r\n\r\n\tconst std::string itemName = fmt::format(fmt::runtime(\"Ear of {:s}\"), heroName);\r\n\r\n\tCopyUtf8(item._iName, itemName, ItemNameLength);\r\n\tCopyUtf8(item._iIName, heroName, ItemNameLength);\r\n\r\n\titem._iCurs = ((bCursval >> 6) & 3) + ICURS_EAR_SORCERER;\r\n\titem._ivalue = bCursval & 0x3F;\r\n\titem._iCreateInfo = ic;\r\n\titem._iSeed = iseed;\r\n}\r\n\r\nvoid CornerstoneSave()\r\n{\r\n\tif (!CornerStone.activated)\r\n\t\treturn;\r\n\tif (!CornerStone.item.isEmpty()) {\r\n\t\tItemPack id;\r\n\t\tPackItem(id, CornerStone.item, (CornerStone.item.dwBuff & CF_HELLFIRE) != 0);\r\n\t\tconst auto *buffer = reinterpret_cast<uint8_t *>(&id);\r\n\t\tfor (size_t i = 0; i < sizeof(ItemPack); i++) {\r\n\t\t\tBufCopy(&GetOptions().Hellfire.szItem[i * 2], AsHexPad2(buffer[i], /*uppercase=*/true));\r\n\t\t}\r\n\t\tGetOptions().Hellfire.szItem[sizeof(GetOptions().Hellfire.szItem) - 1] = '\\0';\r\n\t} else {\r\n\t\tGetOptions().Hellfire.szItem[0] = '\\0';\r\n\t}\r\n}\r\n\r\nvoid CornerstoneLoad(Point position)\r\n{\r\n\tItemPack pkSItem;\r\n\r\n\tif (CornerStone.activated || position.x == 0 || position.y == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tCornerStone.item.clear();\r\n\tCornerStone.activated = true;\r\n\tif (dItem[position.x][position.y] != 0) {\r\n\t\tconst int ii = dItem[position.x][position.y] - 1;\r\n\t\tfor (int i = 0; i < ActiveItemCount; i++) {\r\n\t\t\tif (ActiveItems[i] == ii) {\r\n\t\t\t\tDeleteItem(i);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tdItem[position.x][position.y] = 0;\r\n\t}\r\n\r\n\tif (strlen(GetOptions().Hellfire.szItem) < sizeof(ItemPack) * 2)\r\n\t\treturn;\r\n\r\n\tHex2bin(GetOptions().Hellfire.szItem, sizeof(ItemPack), reinterpret_cast<uint8_t *>(&pkSItem));\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\r\n\tdItem[position.x][position.y] = static_cast<int8_t>(ii + 1);\r\n\r\n\tUnPackItem(pkSItem, *MyPlayer, item, (pkSItem.dwBuff & CF_HELLFIRE) != 0);\r\n\titem.position = position;\r\n\tRespawnItem(item, false);\r\n\tCornerStone.item = item;\r\n}\r\n\r\nvoid SpawnQuestItem(_item_indexes itemid, Point position, int randarea, SelectionRegion selectionRegion, bool sendmsg)\r\n{\r\n\tif (randarea > 0) {\r\n\t\tint tries = 0;\r\n\t\twhile (true) {\r\n\t\t\ttries++;\r\n\t\t\tif (tries > 1000 && randarea > 1)\r\n\t\t\t\trandarea--;\r\n\r\n\t\t\tposition.x = GenerateRnd(MAXDUNX);\r\n\t\t\tposition.y = GenerateRnd(MAXDUNY);\r\n\r\n\t\t\tbool failed = false;\r\n\t\t\tfor (int i = 0; i < randarea && !failed; i++) {\r\n\t\t\t\tfor (int j = 0; j < randarea && !failed; j++) {\r\n\t\t\t\t\tfailed = !ItemSpaceOk(position + Displacement { i, j });\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!failed)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\r\n\titem.position = position;\r\n\r\n\tdItem[position.x][position.y] = ii + 1;\r\n\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\tGetItemAttrs(item, itemid, curlv);\r\n\r\n\tSetupItem(item);\r\n\titem._iSeed = AdvanceRndSeed();\r\n\tSetRndSeed(item._iSeed);\r\n\titem._iPostDraw = true;\r\n\tif (selectionRegion != SelectionRegion::None) {\r\n\t\titem.selectionRegion = selectionRegion;\r\n\t\titem.AnimInfo.currentFrame = item.AnimInfo.numberOfFrames - 1;\r\n\t\titem._iAnimFlag = false;\r\n\t}\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdPItem(true, CMD_SPAWNITEM, item.position, item);\r\n\telse {\r\n\t\titem._iCreateInfo |= CF_PREGEN;\r\n\t\tDeltaAddItem(ii);\r\n\t}\r\n}\r\n\r\nvoid SpawnRewardItem(_item_indexes itemid, Point position, bool sendmsg)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\r\n\titem.position = position;\r\n\tdItem[position.x][position.y] = ii + 1;\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\tGetItemAttrs(item, itemid, curlv);\r\n\titem.setNewAnimation(true);\r\n\titem.selectionRegion = SelectionRegion::Middle;\r\n\titem._iPostDraw = true;\r\n\titem._iIdentified = true;\r\n\tGenerateNewSeed(item);\r\n\r\n\tif (sendmsg) {\r\n\t\tNetSendCmdPItem(true, CMD_SPAWNITEM, item.position, item);\r\n\t}\r\n}\r\n\r\nvoid SpawnMapOfDoom(Point position, bool sendmsg)\r\n{\r\n\tSpawnRewardItem(IDI_MAPOFDOOM, position, sendmsg);\r\n}\r\n\r\nvoid SpawnRuneBomb(Point position, bool sendmsg)\r\n{\r\n\tSpawnRewardItem(IDI_RUNEBOMB, position, sendmsg);\r\n}\r\n\r\nvoid SpawnTheodore(Point position, bool sendmsg)\r\n{\r\n\tSpawnRewardItem(IDI_THEODORE, position, sendmsg);\r\n}\r\n\r\nvoid RespawnItem(Item &item, bool flipFlag)\r\n{\r\n\tconst int it = ItemCAnimTbl[item._iCurs];\r\n\titem.setNewAnimation(flipFlag);\r\n\titem._iRequest = false; // Item isn't being picked up by a player\r\n\r\n\tswitch (item._iCurs) {\r\n\tcase ICURS_TAVERN_SIGN:\r\n\tcase ICURS_ANVIL_OF_FURY:\r\n\t\titem.selectionRegion = SelectionRegion::Bottom;\r\n\t\tbreak;\r\n\tcase ICURS_MAP_OF_THE_STARS:\r\n\tcase ICURS_RUNE_BOMB:\r\n\tcase ICURS_THEODORE:\r\n\tcase ICURS_AURIC_AMULET:\r\n\t\titem.selectionRegion = SelectionRegion::Middle; // Item is selectable at elevated level\r\n\t\tbreak;\r\n\tcase ICURS_MAGIC_ROCK:\r\n\t\tObject *stand = FindObjectAtPosition(item.position);\r\n\t\tif (stand != nullptr && stand->_otype == OBJ_STAND) {\r\n\t\t\titem.selectionRegion = SelectionRegion::Middle; // Item is selectable at elevated level and renders at elevated level\r\n\t\t\titem._iPostDraw = true;                         // Draw in front of stand\r\n\t\t\titem.AnimInfo.currentFrame = 10;                // Frame 10 is the start of the elevated frames in the cel\r\n\t\t} else {\r\n\t\t\titem.selectionRegion = SelectionRegion::Bottom; // Item is selectable at floor level and renders at floor level\r\n\t\t}\r\n\t\tPlaySfxLoc(ItemDropSnds[it], item.position); // Play the drop sound (this item is perpetually in a dropping state, but can always be picked up)\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid DeleteItem(int i)\r\n{\r\n\tif (ActiveItemCount > 0)\r\n\t\tActiveItemCount--;\r\n\r\n\tassert(i >= 0 && i < MAXITEMS && ActiveItemCount < MAXITEMS);\r\n\r\n\tif (pcursitem == ActiveItems[i]) // Unselect item if player has it highlighted\r\n\t\tpcursitem = -1;\r\n\r\n\tif (i < ActiveItemCount) {\r\n\t\t// If the deleted item was not already at the end of the active list, swap the indexes around to make the next item allocation simpler.\r\n\t\tstd::swap(ActiveItems[i], ActiveItems[ActiveItemCount]);\r\n\t}\r\n}\r\n\r\nvoid ProcessItems()\r\n{\r\n\tfor (int i = 0; i < ActiveItemCount; i++) {\r\n\t\tconst int ii = ActiveItems[i];\r\n\t\tauto &item = Items[ii];\r\n\t\tif (!item._iAnimFlag)\r\n\t\t\tcontinue;\r\n\t\titem.AnimInfo.processAnimation();\r\n\t\tif (item._iCurs == ICURS_MAGIC_ROCK) {\r\n\t\t\tif (item.selectionRegion == SelectionRegion::Bottom && item.AnimInfo.currentFrame == 10) // Reached end of floor frames + 1, cycle back\r\n\t\t\t\titem.AnimInfo.currentFrame = 0;                                                      // Beginning of floor frames\r\n\t\t\tif (item.selectionRegion == SelectionRegion::Middle && item.AnimInfo.currentFrame == 19) // Reached end of elevated frames, cycle back\r\n\t\t\t\titem.AnimInfo.currentFrame = 10;                                                     // Beginning of elevated frames\r\n\t\t} else {\r\n\t\t\tif (item.AnimInfo.currentFrame == (item.AnimInfo.numberOfFrames - 1) / 2)\r\n\t\t\t\tPlaySfxLoc(ItemDropSnds[ItemCAnimTbl[item._iCurs]], item.position);\r\n\r\n\t\t\tif (item.AnimInfo.isLastFrame()) {\r\n\t\t\t\titem.AnimInfo.currentFrame = item.AnimInfo.numberOfFrames - 1;\r\n\t\t\t\titem._iAnimFlag = false;\r\n\t\t\t\titem.selectionRegion = SelectionRegion::Bottom;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tItemDoppel();\r\n}\r\n\r\nvoid FreeItemGFX()\r\n{\r\n\tfor (auto &itemanim : itemanims) {\r\n\t\titemanim = std::nullopt;\r\n\t}\r\n}\r\n\r\nvoid GetItemFrm(Item &item)\r\n{\r\n\tconst int it = ItemCAnimTbl[item._iCurs];\r\n\tif (itemanims[it])\r\n\t\titem.AnimInfo.sprites.emplace(*itemanims[it]);\r\n}\r\n\r\nvoid GetItemStr(Item &item)\r\n{\r\n\tif (item._itype != ItemType::Gold) {\r\n\t\tInfoString = item.getName();\r\n\t\tInfoColor = item.getTextColor();\r\n\t} else {\r\n\t\tconst int nGold = item._ivalue;\r\n\t\tInfoString = fmt::format(fmt::runtime(ngettext(\"{:s} gold piece\", \"{:s} gold pieces\", nGold)), FormatInteger(nGold));\r\n\t}\r\n}\r\n\r\nvoid CheckIdentify(Player &player, int cii)\r\n{\r\n\tItem *pi;\r\n\r\n\tif (cii >= NUM_INVLOC)\r\n\t\tpi = &player.InvList[cii - NUM_INVLOC];\r\n\telse\r\n\t\tpi = &player.InvBody[cii];\r\n\r\n\tpi->_iIdentified = true;\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid DoRepair(Player &player, int cii)\r\n{\r\n\tItem *pi;\r\n\r\n\tPlaySfxLoc(SfxID::SpellRepair, player.position.tile);\r\n\r\n\tif (cii >= NUM_INVLOC) {\r\n\t\tpi = &player.InvList[cii - NUM_INVLOC];\r\n\t} else {\r\n\t\tpi = &player.InvBody[cii];\r\n\t}\r\n\r\n\tRepairItem(*pi, player.getCharacterLevel());\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid DoRecharge(Player &player, int cii)\r\n{\r\n\tItem *pi;\r\n\r\n\tif (cii >= NUM_INVLOC) {\r\n\t\tpi = &player.InvList[cii - NUM_INVLOC];\r\n\t} else {\r\n\t\tpi = &player.InvBody[cii];\r\n\t}\r\n\r\n\tRechargeItem(*pi, player);\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nbool DoOil(Player &player, int cii)\r\n{\r\n\tItem *pi;\r\n\tif (cii >= NUM_INVLOC) {\r\n\t\tpi = &player.InvList[cii - NUM_INVLOC];\r\n\t} else {\r\n\t\tpi = &player.InvBody[cii];\r\n\t}\r\n\tif (!ApplyOilToItem(*pi, player))\r\n\t\treturn false;\r\n\tCalcPlrInv(player, true);\r\n\treturn true;\r\n}\r\n\r\n[[nodiscard]] StringOrView PrintItemPower(char plidx, const Item &item)\r\n{\r\n\tswitch (plidx) {\r\n\tcase IPL_TOHIT:\r\n\tcase IPL_TOHIT_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"chance to hit: {:+d}%\")), item._iPLToHit);\r\n\tcase IPL_DAMP:\r\n\tcase IPL_DAMP_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(/*xgettext:no-c-format*/ \"{:+d}% damage\")), item._iPLDam);\r\n\tcase IPL_TOHIT_DAMP:\r\n\tcase IPL_TOHIT_DAMP_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"to hit: {:+d}%, {:+d}% damage\")), item._iPLToHit, item._iPLDam);\r\n\tcase IPL_ACP:\r\n\tcase IPL_ACP_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(/*xgettext:no-c-format*/ \"{:+d}% armor\")), item._iPLAC);\r\n\tcase IPL_SETAC:\r\n\tcase IPL_AC_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"armor class: {:d}\")), item._iAC);\r\n\tcase IPL_FIRERES:\r\n\tcase IPL_FIRERES_CURSE:\r\n\t\tif (item._iPLFR < MaxResistance)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist Fire: {:+d}%\")), item._iPLFR);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist Fire: {:+d}% MAX\")), MaxResistance);\r\n\tcase IPL_LIGHTRES:\r\n\tcase IPL_LIGHTRES_CURSE:\r\n\t\tif (item._iPLLR < MaxResistance)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist Lightning: {:+d}%\")), item._iPLLR);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist Lightning: {:+d}% MAX\")), MaxResistance);\r\n\tcase IPL_MAGICRES:\r\n\tcase IPL_MAGICRES_CURSE:\r\n\t\tif (item._iPLMR < MaxResistance)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist Magic: {:+d}%\")), item._iPLMR);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist Magic: {:+d}% MAX\")), MaxResistance);\r\n\tcase IPL_ALLRES:\r\n\t\tif (item._iPLFR < MaxResistance)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist All: {:+d}%\")), item._iPLFR);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Resist All: {:+d}% MAX\")), MaxResistance);\r\n\tcase IPL_SPLLVLADD:\r\n\t\tif (item._iSplLvlAdd > 0)\r\n\t\t\treturn fmt::format(fmt::runtime(ngettext(\"spells are increased {:d} level\", \"spells are increased {:d} levels\", item._iSplLvlAdd)), item._iSplLvlAdd);\r\n\t\telse if (item._iSplLvlAdd < 0)\r\n\t\t\treturn fmt::format(fmt::runtime(ngettext(\"spells are decreased {:d} level\", \"spells are decreased {:d} levels\", -item._iSplLvlAdd)), -item._iSplLvlAdd);\r\n\t\telse\r\n\t\t\treturn _(\"spell levels unchanged (?)\");\r\n\tcase IPL_CHARGES:\r\n\t\treturn _(\"Extra charges\");\r\n\tcase IPL_SPELL:\r\n\t\treturn fmt::format(fmt::runtime(ngettext(\"{:d} {:s} charge\", \"{:d} {:s} charges\", item._iMaxCharges)), item._iMaxCharges, pgettext(\"spell\", GetSpellData(item._iSpell).sNameText));\r\n\tcase IPL_FIREDAM:\r\n\t\tif (item._iFMinDam == item._iFMaxDam)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Fire hit damage: {:d}\")), item._iFMinDam);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Fire hit damage: {:d}-{:d}\")), item._iFMinDam, item._iFMaxDam);\r\n\tcase IPL_LIGHTDAM:\r\n\t\tif (item._iLMinDam == item._iLMaxDam)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Lightning hit damage: {:d}\")), item._iLMinDam);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"Lightning hit damage: {:d}-{:d}\")), item._iLMinDam, item._iLMaxDam);\r\n\tcase IPL_STR:\r\n\tcase IPL_STR_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"{:+d} to strength\")), item._iPLStr);\r\n\tcase IPL_MAG:\r\n\tcase IPL_MAG_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"{:+d} to magic\")), item._iPLMag);\r\n\tcase IPL_DEX:\r\n\tcase IPL_DEX_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"{:+d} to dexterity\")), item._iPLDex);\r\n\tcase IPL_VIT:\r\n\tcase IPL_VIT_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"{:+d} to vitality\")), item._iPLVit);\r\n\tcase IPL_ATTRIBS:\r\n\tcase IPL_ATTRIBS_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"{:+d} to all attributes\")), item._iPLStr);\r\n\tcase IPL_GETHIT_CURSE:\r\n\tcase IPL_GETHIT:\r\n\t\treturn fmt::format(fmt::runtime(_(\"{:+d} damage from enemies\")), item._iPLGetHit);\r\n\tcase IPL_LIFE:\r\n\tcase IPL_LIFE_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"Hit Points: {:+d}\")), item._iPLHP >> 6);\r\n\tcase IPL_MANA:\r\n\tcase IPL_MANA_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(\"Mana: {:+d}\")), item._iPLMana >> 6);\r\n\tcase IPL_DUR:\r\n\t\treturn _(\"high durability\");\r\n\tcase IPL_DUR_CURSE:\r\n\t\treturn _(\"decreased durability\");\r\n\tcase IPL_INDESTRUCTIBLE:\r\n\t\treturn _(\"indestructible\");\r\n\tcase IPL_LIGHT:\r\n\t\treturn fmt::format(fmt::runtime(_(/*xgettext:no-c-format*/ \"+{:d}% light radius\")), 10 * item._iPLLight);\r\n\tcase IPL_LIGHT_CURSE:\r\n\t\treturn fmt::format(fmt::runtime(_(/*xgettext:no-c-format*/ \"-{:d}% light radius\")), -10 * item._iPLLight);\r\n\tcase IPL_MULT_ARROWS:\r\n\t\treturn _(\"multiple arrows per shot\");\r\n\tcase IPL_FIRE_ARROWS:\r\n\t\tif (item._iFMinDam == item._iFMaxDam)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"fire arrows damage: {:d}\")), item._iFMinDam);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"fire arrows damage: {:d}-{:d}\")), item._iFMinDam, item._iFMaxDam);\r\n\tcase IPL_LIGHT_ARROWS:\r\n\t\tif (item._iLMinDam == item._iLMaxDam)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"lightning arrows damage {:d}\")), item._iLMinDam);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"lightning arrows damage {:d}-{:d}\")), item._iLMinDam, item._iLMaxDam);\r\n\tcase IPL_FIREBALL:\r\n\t\tif (item._iFMinDam == item._iFMaxDam)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"fireball damage: {:d}\")), item._iFMinDam);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"fireball damage: {:d}-{:d}\")), item._iFMinDam, item._iFMaxDam);\r\n\tcase IPL_THORNS:\r\n\t\treturn _(\"attacker takes 1-3 damage\");\r\n\tcase IPL_NOMANA:\r\n\t\treturn _(\"user loses all mana\");\r\n\tcase IPL_ABSHALFTRAP:\r\n\t\treturn _(\"absorbs half of trap damage\");\r\n\tcase IPL_KNOCKBACK:\r\n\t\treturn _(\"knocks target back\");\r\n\tcase IPL_3XDAMVDEM:\r\n\t\treturn _(/*xgettext:no-c-format*/ \"+200% damage vs. demons\");\r\n\tcase IPL_ALLRESZERO:\r\n\t\treturn _(\"All Resistance equals 0\");\r\n\tcase IPL_STEALMANA:\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::StealMana3))\r\n\t\t\treturn _(/*xgettext:no-c-format*/ \"hit steals 3% mana\");\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::StealMana5))\r\n\t\t\treturn _(/*xgettext:no-c-format*/ \"hit steals 5% mana\");\r\n\t\treturn {};\r\n\tcase IPL_STEALLIFE:\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::StealLife3))\r\n\t\t\treturn _(/*xgettext:no-c-format*/ \"hit steals 3% life\");\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::StealLife5))\r\n\t\t\treturn _(/*xgettext:no-c-format*/ \"hit steals 5% life\");\r\n\t\treturn {};\r\n\tcase IPL_TARGAC:\r\n\t\treturn _(\"penetrates target's armor\");\r\n\tcase IPL_FASTATTACK:\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::QuickAttack))\r\n\t\t\treturn _(\"quick attack\");\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::FastAttack))\r\n\t\t\treturn _(\"fast attack\");\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::FasterAttack))\r\n\t\t\treturn _(\"faster attack\");\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::FastestAttack))\r\n\t\t\treturn _(\"fastest attack\");\r\n\t\treturn _(\"Another ability (NW)\");\r\n\tcase IPL_FASTRECOVER:\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::FastHitRecovery))\r\n\t\t\treturn _(\"fast hit recovery\");\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::FasterHitRecovery))\r\n\t\t\treturn _(\"faster hit recovery\");\r\n\t\tif (HasAnyOf(item._iFlags, ItemSpecialEffect::FastestHitRecovery))\r\n\t\t\treturn _(\"fastest hit recovery\");\r\n\t\treturn _(\"Another ability (NW)\");\r\n\tcase IPL_FASTBLOCK:\r\n\t\treturn _(\"fast block\");\r\n\tcase IPL_DAMMOD:\r\n\t\treturn fmt::format(fmt::runtime(ngettext(\"adds {:d} point to damage\", \"adds {:d} points to damage\", item._iPLDamMod)), item._iPLDamMod);\r\n\tcase IPL_RNDARROWVEL:\r\n\t\treturn _(\"fires random speed arrows\");\r\n\tcase IPL_SETDAM:\r\n\t\treturn _(\"unusual item damage\");\r\n\tcase IPL_SETDUR:\r\n\t\treturn _(\"altered durability\");\r\n\tcase IPL_ONEHAND:\r\n\t\treturn _(\"one handed sword\");\r\n\tcase IPL_DRAINLIFE:\r\n\t\treturn _(\"constantly lose hit points\");\r\n\tcase IPL_RNDSTEALLIFE:\r\n\t\treturn _(\"life stealing\");\r\n\tcase IPL_NOMINSTR:\r\n\t\treturn _(\"no strength requirement\");\r\n\tcase IPL_ADDACLIFE:\r\n\t\tif (item._iFMinDam == item._iFMaxDam)\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"lightning damage: {:d}\")), item._iFMinDam);\r\n\t\telse\r\n\t\t\treturn fmt::format(fmt::runtime(_(\"lightning damage: {:d}-{:d}\")), item._iFMinDam, item._iFMaxDam);\r\n\tcase IPL_ADDMANAAC:\r\n\t\treturn _(\"charged bolts on hits\");\r\n\tcase IPL_DEVASTATION:\r\n\t\treturn _(\"occasional triple damage\");\r\n\tcase IPL_DECAY:\r\n\t\treturn fmt::format(fmt::runtime(_(/*xgettext:no-c-format*/ \"decaying {:+d}% damage\")), item._iPLDam);\r\n\tcase IPL_PERIL:\r\n\t\treturn _(\"2x dmg to monst, 1x to you\");\r\n\tcase IPL_JESTERS:\r\n\t\treturn std::string(_(/*xgettext:no-c-format*/ \"Random 0 - 600% damage\"));\r\n\tcase IPL_CRYSTALLINE:\r\n\t\treturn fmt::format(fmt::runtime(_(/*xgettext:no-c-format*/ \"low dur, {:+d}% damage\")), item._iPLDam);\r\n\tcase IPL_DOPPELGANGER:\r\n\t\treturn fmt::format(fmt::runtime(_(\"to hit: {:+d}%, {:+d}% damage\")), item._iPLToHit, item._iPLDam);\r\n\tcase IPL_ACDEMON:\r\n\t\treturn _(\"extra AC vs demons\");\r\n\tcase IPL_ACUNDEAD:\r\n\t\treturn _(\"extra AC vs undead\");\r\n\tcase IPL_MANATOLIFE:\r\n\t\treturn _(\"50% Mana moved to Health\");\r\n\tcase IPL_LIFETOMANA:\r\n\t\treturn _(\"40% Health moved to Mana\");\r\n\tdefault:\r\n\t\treturn _(\"Another ability (NW)\");\r\n\t}\r\n}\r\n\r\nvoid DrawUniqueInfo(const Surface &out)\r\n{\r\n\tconst Point position = DrawUniqueInfoWindow(out);\r\n\r\n\tRectangle rect { position + Displacement { 32, 56 }, { 257, 0 } };\r\n\tconst UniqueItem &uitem = UniqueItems[curruitem._iUid];\r\n\tDrawString(out, _(uitem.UIName), rect, { .flags = UiFlags::AlignCenter });\r\n\r\n\tconst Rectangle dividerLineRect { position + Displacement { 26, 25 }, { 267, 3 } };\r\n\tout.BlitFrom(out, MakeSdlRect(dividerLineRect), dividerLineRect.position + Displacement { 0, (5 * 12) + 13 });\r\n\r\n\trect.position.y += (10 - uitem.UINumPL) * 12;\r\n\tassert(uitem.UINumPL <= sizeof(uitem.powers) / sizeof(*uitem.powers));\r\n\tconst TextRenderOptions textRenderOptions { .flags = UiFlags::ColorWhite | UiFlags::AlignCenter };\r\n\tconst GameFontTables fontSize = GetFontSizeFromUiFlags(textRenderOptions.flags);\r\n\tfor (const auto &power : uitem.powers) {\r\n\t\tif (power.type == IPL_INVALID)\r\n\t\t\tbreak;\r\n\t\trect.position.y += 2 * 12;\r\n\t\t// Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words.\r\n\t\tconst std::string wrapped = WordWrapString(PrintItemPower(power.type, curruitem), rect.size.width);\r\n\t\tDrawString(out, wrapped, rect, textRenderOptions);\r\n\t\tfor (const std::string_view line : SplitByChar(wrapped, '\\n')) {\r\n\t\t\tif (line.data() + line.size() == wrapped.data() + wrapped.size()) break;\r\n\t\t\trect.position.y += GetLineHeight(line, fontSize);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PrintItemDetails(const Item &item)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tif (item._iClass == ICLASS_WEAPON) {\r\n\t\tif (item._iMinDam == item._iMaxDam) {\r\n\t\t\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"damage: {:d}  Indestructible\")), item._iMinDam));\r\n\t\t\telse\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(/* TRANSLATORS: Dur: is durability */ \"damage: {:d}  Dur: {:d}/{:d}\")), item._iMinDam, item._iDurability, item._iMaxDur));\r\n\t\t} else {\r\n\t\t\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"damage: {:d}-{:d}  Indestructible\")), item._iMinDam, item._iMaxDam));\r\n\t\t\telse\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(/* TRANSLATORS: Dur: is durability */ \"damage: {:d}-{:d}  Dur: {:d}/{:d}\")), item._iMinDam, item._iMaxDam, item._iDurability, item._iMaxDur));\r\n\t\t}\r\n\t}\r\n\tif (item._iClass == ICLASS_ARMOR) {\r\n\t\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"armor: {:d}  Indestructible\")), item._iAC));\r\n\t\telse\r\n\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(/* TRANSLATORS: Dur: is durability */ \"armor: {:d}  Dur: {:d}/{:d}\")), item._iAC, item._iDurability, item._iMaxDur));\r\n\t}\r\n\tif (item._iMiscId == IMISC_STAFF && item._iMaxCharges != 0) {\r\n\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"Charges: {:d}/{:d}\")), item._iCharges, item._iMaxCharges));\r\n\t}\r\n\tif (item._iPrePower != -1) {\r\n\t\tAddItemInfoBoxString(PrintItemPower(item._iPrePower, item));\r\n\t}\r\n\tif (item._iSufPower != -1) {\r\n\t\tAddItemInfoBoxString(PrintItemPower(item._iSufPower, item));\r\n\t}\r\n\tif (item._iMagical == ITEM_QUALITY_UNIQUE) {\r\n\t\tAddItemInfoBoxString(_(\"unique item\"));\r\n\t\tShowUniqueItemInfoBox = true;\r\n\t\tcurruitem = item;\r\n\t}\r\n\tPrintItemInfo(item);\r\n}\r\n\r\nvoid PrintItemDur(const Item &item)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tif (item._iClass == ICLASS_WEAPON) {\r\n\t\tif (item._iMinDam == item._iMaxDam) {\r\n\t\t\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"damage: {:d}  Indestructible\")), item._iMinDam));\r\n\t\t\telse\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"damage: {:d}  Dur: {:d}/{:d}\")), item._iMinDam, item._iDurability, item._iMaxDur));\r\n\t\t} else {\r\n\t\t\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"damage: {:d}-{:d}  Indestructible\")), item._iMinDam, item._iMaxDam));\r\n\t\t\telse\r\n\t\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"damage: {:d}-{:d}  Dur: {:d}/{:d}\")), item._iMinDam, item._iMaxDam, item._iDurability, item._iMaxDur));\r\n\t\t}\r\n\t\tif (item._iMiscId == IMISC_STAFF && item._iMaxCharges > 0) {\r\n\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"Charges: {:d}/{:d}\")), item._iCharges, item._iMaxCharges));\r\n\t\t}\r\n\t\tif (item._iMagical != ITEM_QUALITY_NORMAL)\r\n\t\t\tAddItemInfoBoxString(_(\"Not Identified\"));\r\n\t}\r\n\tif (item._iClass == ICLASS_ARMOR) {\r\n\t\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"armor: {:d}  Indestructible\")), item._iAC));\r\n\t\telse\r\n\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"armor: {:d}  Dur: {:d}/{:d}\")), item._iAC, item._iDurability, item._iMaxDur));\r\n\t\tif (item._iMagical != ITEM_QUALITY_NORMAL)\r\n\t\t\tAddItemInfoBoxString(_(\"Not Identified\"));\r\n\t\tif (item._iMiscId == IMISC_STAFF && item._iMaxCharges > 0) {\r\n\t\t\tAddItemInfoBoxString(fmt::format(fmt::runtime(_(\"Charges: {:d}/{:d}\")), item._iCharges, item._iMaxCharges));\r\n\t\t}\r\n\t}\r\n\tif (IsAnyOf(item._itype, ItemType::Ring, ItemType::Amulet))\r\n\t\tAddItemInfoBoxString(_(\"Not Identified\"));\r\n\tPrintItemInfo(item);\r\n}\r\n\r\nvoid UseItem(Player &player, item_misc_id mid, SpellID spellID, int spellFrom)\r\n{\r\n\tstd::optional<SpellID> prepareSpellID;\r\n\r\n\tswitch (mid) {\r\n\tcase IMISC_HEAL:\r\n\t\tplayer.RestorePartialLife();\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_FULLHEAL:\r\n\t\tplayer.RestoreFullLife();\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_MANA:\r\n\t\tplayer.RestorePartialMana();\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_FULLMANA:\r\n\t\tplayer.RestoreFullMana();\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_ELIXSTR:\r\n\t\tModifyPlrStr(player, 1);\r\n\t\tbreak;\r\n\tcase IMISC_ELIXMAG:\r\n\t\tModifyPlrMag(player, 1);\r\n\t\tif (gbIsHellfire) {\r\n\t\t\tplayer.RestoreFullMana();\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_ELIXDEX:\r\n\t\tModifyPlrDex(player, 1);\r\n\t\tbreak;\r\n\tcase IMISC_ELIXVIT:\r\n\t\tModifyPlrVit(player, 1);\r\n\t\tif (gbIsHellfire) {\r\n\t\t\tplayer.RestoreFullLife();\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_REJUV: {\r\n\t\tplayer.RestorePartialLife();\r\n\t\tplayer.RestorePartialMana();\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\t}\r\n\t} break;\r\n\tcase IMISC_FULLREJUV:\r\n\tcase IMISC_ARENAPOT:\r\n\t\tplayer.RestoreFullLife();\r\n\t\tplayer.RestoreFullMana();\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_SCROLL:\r\n\tcase IMISC_SCROLLT:\r\n\t\tif (ControlMode == ControlTypes::KeyboardAndMouse && GetSpellData(spellID).isTargeted()) {\r\n\t\t\tprepareSpellID = spellID;\r\n\t\t} else {\r\n\t\t\t// Find a valid target for the spell because tile coords\r\n\t\t\t// will be validated when processing the network message\r\n\t\t\tPoint target = cursPosition;\r\n\t\t\tif (!InDungeonBounds(target))\r\n\t\t\t\ttarget = player.position.future + Displacement(player._pdir);\r\n\t\t\t// Use CMD_SPELLXY because it's the same behavior as normal casting\r\n\t\t\tassert(IsValidSpellFrom(spellFrom));\r\n\t\t\tNetSendCmdLocParam3(true, CMD_SPELLXY, target, static_cast<int8_t>(spellID), static_cast<uint8_t>(SpellType::Scroll), static_cast<uint16_t>(spellFrom));\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_BOOK: {\r\n\t\tconst uint8_t newSpellLevel = player._pSplLvl[static_cast<int8_t>(spellID)] + 1;\r\n\t\tif (newSpellLevel <= MaxSpellLevel) {\r\n\t\t\tplayer._pSplLvl[static_cast<int8_t>(spellID)] = newSpellLevel;\r\n\t\t\tNetSendCmdParam2(true, CMD_CHANGE_SPELL_LEVEL, static_cast<uint16_t>(spellID), newSpellLevel);\r\n\t\t}\r\n\t\tif (HasNoneOf(player._pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\t\tplayer._pMana += GetSpellData(spellID).sManaCost << 6;\r\n\t\t\tplayer._pMana = std::min(player._pMana, player._pMaxMana);\r\n\t\t\tplayer._pManaBase += GetSpellData(spellID).sManaCost << 6;\r\n\t\t\tplayer._pManaBase = std::min(player._pManaBase, player._pMaxManaBase);\r\n\t\t}\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tfor (Item &item : InventoryPlayerItemsRange { player }) {\r\n\t\t\t\titem.updateRequiredStatsCacheForPlayer(player);\r\n\t\t\t}\r\n\t\t\tif (IsStashOpen) {\r\n\t\t\t\tStash.RefreshItemStatFlags();\r\n\t\t\t}\r\n\t\t}\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t} break;\r\n\tcase IMISC_MAPOFDOOM:\r\n\t\tdoom_init();\r\n\t\tbreak;\r\n\tcase IMISC_OILACC:\r\n\tcase IMISC_OILMAST:\r\n\tcase IMISC_OILSHARP:\r\n\tcase IMISC_OILDEATH:\r\n\tcase IMISC_OILSKILL:\r\n\tcase IMISC_OILBSMTH:\r\n\tcase IMISC_OILFORT:\r\n\tcase IMISC_OILPERM:\r\n\tcase IMISC_OILHARD:\r\n\tcase IMISC_OILIMP:\r\n\t\tplayer._pOilType = mid;\r\n\t\tif (&player != MyPlayer) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (SpellbookFlag) {\r\n\t\t\tSpellbookFlag = false;\r\n\t\t}\r\n\t\tif (!invflag) {\r\n\t\t\tinvflag = true;\r\n\t\t}\r\n\t\tNewCursor(CURSOR_OIL);\r\n\t\tbreak;\r\n\tcase IMISC_SPECELIX:\r\n\t\tModifyPlrStr(player, 3);\r\n\t\tModifyPlrMag(player, 3);\r\n\t\tModifyPlrDex(player, 3);\r\n\t\tModifyPlrVit(player, 3);\r\n\t\tbreak;\r\n\tcase IMISC_RUNEF:\r\n\t\tprepareSpellID = SpellID::RuneOfFire;\r\n\t\tbreak;\r\n\tcase IMISC_RUNEL:\r\n\t\tprepareSpellID = SpellID::RuneOfLight;\r\n\t\tbreak;\r\n\tcase IMISC_GR_RUNEL:\r\n\t\tprepareSpellID = SpellID::RuneOfNova;\r\n\t\tbreak;\r\n\tcase IMISC_GR_RUNEF:\r\n\t\tprepareSpellID = SpellID::RuneOfImmolation;\r\n\t\tbreak;\r\n\tcase IMISC_RUNES:\r\n\t\tprepareSpellID = SpellID::RuneOfStone;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (prepareSpellID) {\r\n\t\tassert(IsValidSpellFrom(spellFrom));\r\n\t\tplayer.inventorySpell = *prepareSpellID;\r\n\t\tplayer.spellFrom = spellFrom;\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tNewCursor(CURSOR_TELEPORT);\r\n\t}\r\n}\r\n\r\nbool UseItemOpensHive(const Item &item, Point position)\r\n{\r\n\tif (item.IDidx != IDI_RUNEBOMB)\r\n\t\treturn false;\r\n\tfor (auto dir : PathDirs) {\r\n\t\tconst Point adjacentPosition = position + dir;\r\n\t\tif (OpensHive(adjacentPosition))\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool UseItemOpensGrave(const Item &item, Point position)\r\n{\r\n\tif (item.IDidx != IDI_MAPOFDOOM)\r\n\t\treturn false;\r\n\tfor (auto dir : PathDirs) {\r\n\t\tconst Point adjacentPosition = position + dir;\r\n\t\tif (OpensGrave(adjacentPosition))\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid SpawnSmith(int lvl)\r\n{\r\n\tconstexpr int PinnedItemCount = 0;\r\n\r\n\tint maxValue = MaxVendorValue;\r\n\tint maxItems = NumSmithBasicItems;\r\n\tif (gbIsHellfire) {\r\n\t\tmaxValue = MaxVendorValueHf;\r\n\t\tmaxItems = NumSmithBasicItemsHf;\r\n\t}\r\n\r\n\tconst size_t iCnt = RandomIntBetween(10, maxItems);\r\n\tSmithItems.clear();\r\n\r\n\twhile (SmithItems.size() < iCnt) {\r\n\t\tItem newItem;\r\n\t\tdo {\r\n\t\t\tnewItem = {};\r\n\t\t\tnewItem._iSeed = AdvanceRndSeed();\r\n\t\t\tSetRndSeed(newItem._iSeed);\r\n\t\t\tconst _item_indexes itemData = RndSmithItem(*MyPlayer, lvl);\r\n\t\t\tGetItemAttrs(newItem, itemData, lvl);\r\n\t\t} while (newItem._iIvalue > maxValue);\r\n\r\n\t\tnewItem._iCreateInfo = lvl | CF_SMITH;\r\n\t\tnewItem._iIdentified = true;\r\n\r\n\t\tSmithItems.push_back(newItem);\r\n\t}\r\n\r\n\tSortVendor(SmithItems, PinnedItemCount);\r\n}\r\n\r\nvoid ReplacePremium(const Player &player, int idx)\r\n{\r\n\tint plvl = gbIsHellfire ? itemLevelAddHf[idx] : itemLevelAdd[idx];\r\n\tplvl += player.getCharacterLevel();\r\n\tSpawnOnePremium(PremiumItems[idx], plvl, player);\r\n}\r\n\r\nvoid SpawnPremium(const Player &player)\r\n{\r\n\tconst int lvl = player.getCharacterLevel();\r\n\tconst size_t maxItems = gbIsHellfire ? NumSmithItemsHf : NumSmithItems;\r\n\r\n\twhile (PremiumItems.size() < maxItems) {\r\n\t\tint plvl = PremiumItemLevel + (gbIsHellfire ? itemLevelAddHf[PremiumItems.size()] : itemLevelAdd[PremiumItems.size()]);\r\n\t\tItem item = {};\r\n\t\tSpawnOnePremium(item, plvl, player);\r\n\t\tPremiumItems.push_back(item);\r\n\t}\r\n\r\n\twhile (PremiumItemLevel < lvl) {\r\n\t\tPremiumItemLevel++;\r\n\t\tItem *ptr = PremiumItems.begin();\r\n\t\tif (gbIsHellfire) {\r\n\t\t\tstd::move(ptr + 3, ptr + 13, ptr);\r\n\t\t\tPremiumItems[11] = PremiumItems[13];\r\n\t\t\tPremiumItems[13] = PremiumItems[14];\r\n\t\t\tSpawnOnePremium(PremiumItems[10], PremiumItemLevel + itemLevelAddHf[10], player);\r\n\t\t\tSpawnOnePremium(PremiumItems[12], PremiumItemLevel + itemLevelAddHf[12], player);\r\n\t\t\tSpawnOnePremium(PremiumItems[14], PremiumItemLevel + itemLevelAddHf[14], player);\r\n\t\t} else {\r\n\t\t\tstd::move(ptr + 2, ptr + 5, ptr);\r\n\t\t\tPremiumItems[4] = PremiumItems[5];\r\n\t\t\tSpawnOnePremium(PremiumItems[3], PremiumItemLevel + itemLevelAdd[3], player);\r\n\t\t\tSpawnOnePremium(PremiumItems[5], PremiumItemLevel + itemLevelAdd[5], player);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SpawnWitch(int lvl)\r\n{\r\n\tconstexpr int PinnedItemCount = NumWitchPinnedItems;\r\n\tconstexpr std::array<_item_indexes, PinnedItemCount> PinnedItemTypes = { IDI_MANA, IDI_FULLMANA, IDI_PORTAL };\r\n\tconstexpr int MaxPinnedBookCount = 4;\r\n\tconstexpr std::array<_item_indexes, MaxPinnedBookCount> PinnedBookTypes = { IDI_BOOK1, IDI_BOOK2, IDI_BOOK3, IDI_BOOK4 };\r\n\r\n\tint bookCount = 0;\r\n\tconst int pinnedBookCount = gbIsHellfire ? RandomIntLessThan(MaxPinnedBookCount) : 0;\r\n\tconst int itemCount = RandomIntBetween(10, gbIsHellfire ? NumWitchItemsHf : NumWitchItems);\r\n\tconst int maxValue = gbIsHellfire ? MaxVendorValueHf : MaxVendorValue;\r\n\tWitchItems.clear();\r\n\r\n\tfor (int i = 0; i < itemCount; i++) {\r\n\t\tItem item = {};\r\n\r\n\t\tif (i < PinnedItemCount) {\r\n\t\t\titem._iSeed = AdvanceRndSeed();\r\n\t\t\tGetItemAttrs(item, PinnedItemTypes[i], 1);\r\n\t\t\titem._iCreateInfo = lvl;\r\n\t\t\titem._iStatFlag = true;\r\n\t\t\tWitchItems.push_back(item);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (gbIsHellfire) {\r\n\t\t\tif (i < PinnedItemCount + MaxPinnedBookCount && bookCount < pinnedBookCount) {\r\n\t\t\t\tconst _item_indexes bookType = PinnedBookTypes[i - PinnedItemCount];\r\n\t\t\t\tif (lvl >= AllItemsList[bookType].iMinMLvl) {\r\n\t\t\t\t\titem._iSeed = AdvanceRndSeed();\r\n\t\t\t\t\tSetRndSeed(item._iSeed);\r\n\t\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\t\tGetItemAttrs(item, bookType, lvl);\r\n\t\t\t\t\titem._iCreateInfo = lvl | CF_WITCH;\r\n\t\t\t\t\titem._iIdentified = true;\r\n\t\t\t\t\tbookCount++;\r\n\t\t\t\t\tWitchItems.push_back(item);\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdo {\r\n\t\t\titem = {};\r\n\t\t\titem._iSeed = AdvanceRndSeed();\r\n\t\t\tSetRndSeed(item._iSeed);\r\n\t\t\tconst _item_indexes itemData = RndWitchItem(*MyPlayer, lvl);\r\n\t\t\tGetItemAttrs(item, itemData, lvl);\r\n\t\t\tint maxlvl = -1;\r\n\t\t\tif (GenerateRnd(100) <= 5)\r\n\t\t\t\tmaxlvl = 2 * lvl;\r\n\t\t\tif (maxlvl == -1 && item._iMiscId == IMISC_STAFF)\r\n\t\t\t\tmaxlvl = 2 * lvl;\r\n\t\t\tif (maxlvl != -1)\r\n\t\t\t\tGetItemBonus(*MyPlayer, item, maxlvl / 2, maxlvl, true, true);\r\n\t\t} while (item._iIvalue > maxValue);\r\n\r\n\t\titem._iCreateInfo = lvl | CF_WITCH;\r\n\t\titem._iIdentified = true;\r\n\r\n\t\tWitchItems.push_back(item);\r\n\t}\r\n\r\n\tSortVendor(WitchItems, PinnedItemCount);\r\n}\r\n\r\nvoid SpawnBoy(int lvl)\r\n{\r\n\tint ivalue = 0;\r\n\tbool keepgoing = false;\r\n\tint count = 0;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tconst HeroClass pc = myPlayer._pClass;\r\n\tint strength = std::max(myPlayer.GetMaximumAttributeValue(CharacterAttribute::Strength), myPlayer._pStrength);\r\n\tint dexterity = std::max(myPlayer.GetMaximumAttributeValue(CharacterAttribute::Dexterity), myPlayer._pDexterity);\r\n\tint magic = std::max(myPlayer.GetMaximumAttributeValue(CharacterAttribute::Magic), myPlayer._pMagic);\r\n\tstrength += strength / 5;\r\n\tdexterity += dexterity / 5;\r\n\tmagic += magic / 5;\r\n\r\n\tif (BoyItemLevel >= (lvl / 2) && !BoyItem.isEmpty())\r\n\t\treturn;\r\n\tdo {\r\n\t\tkeepgoing = false;\r\n\t\tBoyItem = {};\r\n\t\tBoyItem._iSeed = AdvanceRndSeed();\r\n\t\tSetRndSeed(BoyItem._iSeed);\r\n\t\tconst _item_indexes itype = RndBoyItem(*MyPlayer, lvl);\r\n\t\tGetItemAttrs(BoyItem, itype, lvl);\r\n\t\tGetItemBonus(*MyPlayer, BoyItem, lvl, 2 * lvl, true, true);\r\n\r\n\t\tif (!gbIsHellfire) {\r\n\t\t\tif (BoyItem._iIvalue > MaxBoyValue) {\r\n\t\t\t\tkeepgoing = true; // prevent breaking the do/while loop too early by failing hellfire's condition in while\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tivalue = 0;\r\n\r\n\t\tconst ItemType itemType = BoyItem._itype;\r\n\r\n\t\tswitch (itemType) {\r\n\t\tcase ItemType::LightArmor:\r\n\t\tcase ItemType::MediumArmor:\r\n\t\tcase ItemType::HeavyArmor: {\r\n\t\t\tconst auto *const mostValuablePlayerArmor = myPlayer.GetMostValuableItem(\r\n\t\t\t    [](const Item &item) {\r\n\t\t\t\t    return IsAnyOf(item._itype, ItemType::LightArmor, ItemType::MediumArmor, ItemType::HeavyArmor);\r\n\t\t\t    });\r\n\r\n\t\t\tivalue = mostValuablePlayerArmor == nullptr ? 0 : mostValuablePlayerArmor->_iIvalue;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase ItemType::Shield:\r\n\t\tcase ItemType::Axe:\r\n\t\tcase ItemType::Bow:\r\n\t\tcase ItemType::Mace:\r\n\t\tcase ItemType::Sword:\r\n\t\tcase ItemType::Helm:\r\n\t\tcase ItemType::Staff:\r\n\t\tcase ItemType::Ring:\r\n\t\tcase ItemType::Amulet: {\r\n\t\t\tconst auto *const mostValuablePlayerItem = myPlayer.GetMostValuableItem(\r\n\t\t\t    [itemType](const Item &item) { return item._itype == itemType; });\r\n\r\n\t\t\tivalue = mostValuablePlayerItem == nullptr ? 0 : mostValuablePlayerItem->_iIvalue;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\tapp_fatal(\"Invalid item spawn\");\r\n\t\t}\r\n\t\tivalue = ivalue * 4 / 5; // avoids forced int > float > int conversion\r\n\r\n\t\tcount++;\r\n\r\n\t\tif (count < 200) {\r\n\t\t\tswitch (pc) {\r\n\t\t\tcase HeroClass::Warrior:\r\n\t\t\t\tif (IsAnyOf(itemType, ItemType::Bow, ItemType::Staff))\r\n\t\t\t\t\tivalue = INT_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\tif (IsAnyOf(itemType, ItemType::Sword, ItemType::Staff, ItemType::Axe, ItemType::Mace, ItemType::Shield))\r\n\t\t\t\t\tivalue = INT_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\tif (IsAnyOf(itemType, ItemType::Staff, ItemType::Axe, ItemType::Bow, ItemType::Mace))\r\n\t\t\t\t\tivalue = INT_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Monk:\r\n\t\t\t\tif (IsAnyOf(itemType, ItemType::Bow, ItemType::MediumArmor, ItemType::Shield, ItemType::Mace))\r\n\t\t\t\t\tivalue = INT_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Bard:\r\n\t\t\t\tif (IsAnyOf(itemType, ItemType::Axe, ItemType::Mace, ItemType::Staff))\r\n\t\t\t\t\tivalue = INT_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\tif (IsAnyOf(itemType, ItemType::Bow, ItemType::Staff))\r\n\t\t\t\t\tivalue = INT_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t} while (keepgoing\r\n\t    || ((\r\n\t            BoyItem._iIvalue > MaxBoyValueHf\r\n\t            || BoyItem._iMinStr > strength\r\n\t            || BoyItem._iMinMag > magic\r\n\t            || BoyItem._iMinDex > dexterity\r\n\t            || BoyItem._iIvalue < ivalue)\r\n\t        && count < 250));\r\n\tBoyItem._iCreateInfo = lvl | CF_BOY;\r\n\tBoyItem._iIdentified = true;\r\n\tBoyItemLevel = lvl / 2;\r\n}\r\n\r\nvoid SpawnHealer(int lvl)\r\n{\r\n\tconstexpr size_t PinnedItemCount = NumHealerPinnedItems;\r\n\tconstexpr std::array<_item_indexes, PinnedItemCount + 1> PinnedItemTypes = { IDI_HEAL, IDI_FULLHEAL, IDI_RESURRECT };\r\n\tconst size_t itemCount = static_cast<size_t>(RandomIntBetween(10, gbIsHellfire ? NumHealerItemsHf : NumHealerItems));\r\n\tHealerItems.clear();\r\n\r\n\tfor (size_t i = 0; i < itemCount; i++) {\r\n\t\tItem item = {};\r\n\r\n\t\tif (i < PinnedItemCount || (gbIsMultiplayer && i < NumHealerPinnedItemsMp)) {\r\n\t\t\titem._iSeed = AdvanceRndSeed();\r\n\t\t\tGetItemAttrs(item, PinnedItemTypes[i], 1);\r\n\t\t\titem._iCreateInfo = lvl;\r\n\t\t\titem._iStatFlag = true;\r\n\t\t} else {\r\n\t\t\titem._iSeed = AdvanceRndSeed();\r\n\t\t\tSetRndSeed(item._iSeed);\r\n\t\t\tconst _item_indexes itype = RndHealerItem(*MyPlayer, lvl);\r\n\t\t\tGetItemAttrs(item, itype, lvl);\r\n\t\t\titem._iCreateInfo = lvl | CF_HEALER;\r\n\t\t\titem._iIdentified = true;\r\n\t\t}\r\n\r\n\t\tHealerItems.push_back(item);\r\n\t}\r\n\r\n\tSortVendor(HealerItems, PinnedItemCount);\r\n}\r\n\r\nvoid MakeGoldStack(Item &goldItem, int value)\r\n{\r\n\tInitializeItem(goldItem, IDI_GOLD);\r\n\tGenerateNewSeed(goldItem);\r\n\tgoldItem._iStatFlag = true;\r\n\tgoldItem._ivalue = value;\r\n\tSetPlrHandGoldCurs(goldItem);\r\n}\r\n\r\nint ItemNoFlippy()\r\n{\r\n\tconst int r = ActiveItems[ActiveItemCount - 1];\r\n\tItems[r].AnimInfo.currentFrame = Items[r].AnimInfo.numberOfFrames - 1;\r\n\tItems[r]._iAnimFlag = false;\r\n\tItems[r].selectionRegion = SelectionRegion::Bottom;\r\n\r\n\treturn r;\r\n}\r\n\r\nvoid CreateSpellBook(Point position, SpellID ispell, bool sendmsg, bool delta)\r\n{\r\n\tint lvl = currlevel;\r\n\r\n\tif (gbIsHellfire) {\r\n\t\tlvl = GetSpellBookLevel(ispell) + 1;\r\n\t\tif (lvl < 1) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tconst _item_indexes idx = RndTypeItems(ItemType::Misc, IMISC_BOOK, lvl);\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\r\n\twhile (true) {\r\n\t\titem = {};\r\n\t\tSetupAllItems(*MyPlayer, item, idx, AdvanceRndSeed(), 2 * lvl, 1, true, delta);\r\n\t\tSetupItem(item);\r\n\t\tif (item._iMiscId == IMISC_BOOK && item._iSpell == ispell)\r\n\t\t\tbreak;\r\n\t}\r\n\tGetSuperItemSpace(position, ii);\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdPItem(false, CMD_DROPITEM, item.position, item);\r\n\tif (delta)\r\n\t\tDeltaAddItem(ii);\r\n}\r\n\r\nvoid CreateMagicArmor(Point position, ItemType itemType, int icurs, bool sendmsg, bool delta)\r\n{\r\n\tconst int lvl = ItemsGetCurrlevel();\r\n\tCreateMagicItem(position, lvl, itemType, IMISC_NONE, icurs, sendmsg, delta);\r\n}\r\n\r\nvoid CreateAmulet(Point position, int lvl, bool sendmsg, bool delta, bool spawn /*= false*/)\r\n{\r\n\tCreateMagicItem(position, lvl, ItemType::Amulet, IMISC_AMULET, ICURS_AMULET, sendmsg, delta, spawn);\r\n}\r\n\r\nvoid CreateMagicWeapon(Point position, ItemType itemType, int icurs, bool sendmsg, bool delta)\r\n{\r\n\tint imid = IMISC_NONE;\r\n\tif (itemType == ItemType::Staff)\r\n\t\timid = IMISC_STAFF;\r\n\r\n\tconst int curlv = ItemsGetCurrlevel();\r\n\r\n\tCreateMagicItem(position, curlv, itemType, imid, icurs, sendmsg, delta);\r\n}\r\n\r\nbool GetItemRecord(uint32_t nSeed, uint16_t wCI, int nIndex)\r\n{\r\n\tconst uint32_t ticks = SDL_GetTicks();\r\n\r\n\tfor (int i = 0; i < gnNumGetRecords; i++) {\r\n\t\tif (ticks - itemrecord[i].dwTimestamp > 6000) {\r\n\t\t\t// BUGFIX: loot actions for multiple quest items with same seed (e.g. blood stone) performed within less than 6 seconds will be ignored.\r\n\t\t\tNextItemRecord(i);\r\n\t\t\ti--;\r\n\t\t} else if (nSeed == itemrecord[i].nSeed && wCI == itemrecord[i].wCI && nIndex == itemrecord[i].nIndex) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid SetItemRecord(uint32_t nSeed, uint16_t wCI, int nIndex)\r\n{\r\n\tconst uint32_t ticks = SDL_GetTicks();\r\n\r\n\tif (gnNumGetRecords == MAXITEMS) {\r\n\t\treturn;\r\n\t}\r\n\r\n\titemrecord[gnNumGetRecords].dwTimestamp = ticks;\r\n\titemrecord[gnNumGetRecords].nSeed = nSeed;\r\n\titemrecord[gnNumGetRecords].wCI = wCI;\r\n\titemrecord[gnNumGetRecords].nIndex = nIndex;\r\n\tgnNumGetRecords++;\r\n}\r\n\r\nvoid PutItemRecord(uint32_t nSeed, uint16_t wCI, int nIndex)\r\n{\r\n\tconst uint32_t ticks = SDL_GetTicks();\r\n\r\n\tfor (int i = 0; i < gnNumGetRecords; i++) {\r\n\t\tif (ticks - itemrecord[i].dwTimestamp > 6000) {\r\n\t\t\tNextItemRecord(i);\r\n\t\t\ti--;\r\n\t\t} else if (nSeed == itemrecord[i].nSeed && wCI == itemrecord[i].wCI && nIndex == itemrecord[i].nIndex) {\r\n\t\t\tNextItemRecord(i);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Item::isUsable() const\r\n{\r\n\tif (IDidx == IDI_SPECELIX && Quests[Q_MUSHROOM]._qactive != QUEST_DONE)\r\n\t\treturn false;\r\n\treturn AllItemsList[IDidx].iUsable;\r\n}\r\n\r\nvoid Item::setNewAnimation(bool showAnimation)\r\n{\r\n\tconst int8_t it = ItemCAnimTbl[_iCurs];\r\n\tconst int8_t numberOfFrames = ItemAnimLs[it];\r\n\tconst OptionalClxSpriteList sprite = itemanims[it] ? OptionalClxSpriteList { *itemanims[static_cast<size_t>(it)] } : std::nullopt;\r\n\tif (_iCurs != ICURS_MAGIC_ROCK)\r\n\t\tAnimInfo.setNewAnimation(sprite, numberOfFrames, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, numberOfFrames);\r\n\telse\r\n\t\tAnimInfo.setNewAnimation(sprite, numberOfFrames, 1);\r\n\t_iPostDraw = false;\r\n\t_iRequest = false;\r\n\tif (showAnimation) {\r\n\t\t_iAnimFlag = true;\r\n\t\tselectionRegion = SelectionRegion::None;\r\n\t} else {\r\n\t\tAnimInfo.currentFrame = AnimInfo.numberOfFrames - 1;\r\n\t\t_iAnimFlag = false;\r\n\t\tselectionRegion = SelectionRegion::Bottom;\r\n\t}\r\n}\r\n\r\nvoid Item::updateRequiredStatsCacheForPlayer(const Player &player)\r\n{\r\n\tif (_itype == ItemType::Misc && _iMiscId == IMISC_BOOK) {\r\n\t\t_iMinMag = GetSpellData(_iSpell).minInt;\r\n\t\tint8_t spellLevel = player._pSplLvl[static_cast<int8_t>(_iSpell)];\r\n\t\twhile (spellLevel != 0) {\r\n\t\t\t_iMinMag += 20 * _iMinMag / 100;\r\n\t\t\tspellLevel--;\r\n\t\t\tif (_iMinMag + 20 * _iMinMag / 100 > 255) {\r\n\t\t\t\t_iMinMag = 255;\r\n\t\t\t\tspellLevel = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t_iStatFlag = player.CanUseItem(*this);\r\n}\r\n\r\nStringOrView Item::getName() const\r\n{\r\n\tif (isEmpty()) {\r\n\t\treturn std::string_view(\"\");\r\n\t}\r\n\tif (!_iIdentified || _iCreateInfo == 0 || _iMagical == ITEM_QUALITY_NORMAL) {\r\n\t\treturn GetTranslatedItemName(*this);\r\n\t}\r\n\tif (_iMagical == ITEM_QUALITY_UNIQUE) {\r\n\t\treturn _(UniqueItems[_iUid].UIName);\r\n\t}\r\n\treturn GetTranslatedItemNameMagical(*this, dwBuff & CF_HELLFIRE, true, std::nullopt);\r\n}\r\n\r\nbool CornerStoneStruct::isAvailable()\r\n{\r\n\treturn currlevel == 21 && !gbIsMultiplayer;\r\n}\r\n\r\nvoid initItemGetRecords()\r\n{\r\n\tmemset(itemrecord, 0, sizeof(itemrecord));\r\n\tgnNumGetRecords = 0;\r\n}\r\n\r\nvoid RepairItem(Item &item, int lvl)\r\n{\r\n\tif (item._iDurability == item._iMaxDur) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (item._iMaxDur <= 0) {\r\n\t\titem.clear();\r\n\t\treturn;\r\n\t}\r\n\r\n\tint rep = 0;\r\n\tdo {\r\n\t\trep += lvl + GenerateRnd(lvl);\r\n\t\titem._iMaxDur -= std::max(item._iMaxDur / (lvl + 9), 1);\r\n\t\tif (item._iMaxDur == 0) {\r\n\t\t\titem.clear();\r\n\t\t\treturn;\r\n\t\t}\r\n\t} while (rep + item._iDurability < item._iMaxDur);\r\n\r\n\titem._iDurability = std::min<int>(item._iDurability + rep, item._iMaxDur);\r\n}\r\n\r\nvoid RechargeItem(Item &item, Player &player)\r\n{\r\n\tif (item._itype != ItemType::Staff || !IsValidSpell(item._iSpell))\r\n\t\treturn;\r\n\r\n\tif (item._iCharges == item._iMaxCharges)\r\n\t\treturn;\r\n\r\n\tconst int rechargeStrength = RandomIntBetween(1, player.getCharacterLevel() / GetSpellStaffLevel(item._iSpell));\r\n\r\n\tdo {\r\n\t\titem._iMaxCharges--;\r\n\t\tif (item._iMaxCharges == 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\titem._iCharges += rechargeStrength;\r\n\t} while (item._iCharges < item._iMaxCharges);\r\n\r\n\titem._iCharges = std::min(item._iCharges, item._iMaxCharges);\r\n\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\tif (&item == &player.InvBody[INVLOC_HAND_LEFT]) {\r\n\t\tNetSendCmdChItem(true, INVLOC_HAND_LEFT);\r\n\t\treturn;\r\n\t}\r\n\tif (&item == &player.InvBody[INVLOC_HAND_RIGHT]) {\r\n\t\tNetSendCmdChItem(true, INVLOC_HAND_RIGHT);\r\n\t\treturn;\r\n\t}\r\n\tfor (int i = 0; i < player._pNumInv; i++) {\r\n\t\tif (&item == &player.InvList[i]) {\r\n\t\t\tNetSyncInvItem(player, i);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool ApplyOilToItem(Item &item, Player &player)\r\n{\r\n\tint r;\r\n\r\n\tif (item._iClass == ICLASS_MISC) {\r\n\t\treturn false;\r\n\t}\r\n\tif (item._iClass == ICLASS_GOLD) {\r\n\t\treturn false;\r\n\t}\r\n\tif (item._iClass == ICLASS_QUEST) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tswitch (player._pOilType) {\r\n\tcase IMISC_OILACC:\r\n\tcase IMISC_OILMAST:\r\n\tcase IMISC_OILSHARP:\r\n\t\tif (item._iClass == ICLASS_ARMOR) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILDEATH:\r\n\t\tif (item._iClass == ICLASS_ARMOR) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (item._itype == ItemType::Bow) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILHARD:\r\n\tcase IMISC_OILIMP:\r\n\t\tif (item._iClass == ICLASS_WEAPON) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tswitch (player._pOilType) {\r\n\tcase IMISC_OILACC:\r\n\t\tif (item._iPLToHit < 50) {\r\n\t\t\titem._iPLToHit += RandomIntBetween(1, 2);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILMAST:\r\n\t\tif (item._iPLToHit < 100) {\r\n\t\t\titem._iPLToHit += RandomIntBetween(3, 5);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILSHARP:\r\n\t\tif (item._iMaxDam - item._iMinDam < 30 && item._iMaxDam < 255) {\r\n\t\t\titem._iMaxDam = item._iMaxDam + 1;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILDEATH:\r\n\t\tif (item._iMaxDam - item._iMinDam < 30 && item._iMaxDam < 254) {\r\n\t\t\titem._iMinDam = item._iMinDam + 1;\r\n\t\t\titem._iMaxDam = item._iMaxDam + 2;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILSKILL:\r\n\t\tr = RandomIntBetween(5, 10);\r\n\t\titem._iMinStr = std::max(0, item._iMinStr - r);\r\n\t\titem._iMinMag = std::max(0, item._iMinMag - r);\r\n\t\titem._iMinDex = std::max(0, item._iMinDex - r);\r\n\t\tbreak;\r\n\tcase IMISC_OILBSMTH:\r\n\t\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\t\treturn true;\r\n\t\tif (item._iDurability < item._iMaxDur) {\r\n\t\t\titem._iDurability = (item._iMaxDur + 4) / 5 + item._iDurability;\r\n\t\t\titem._iDurability = std::min<int>(item._iDurability, item._iMaxDur);\r\n\t\t} else {\r\n\t\t\tif (item._iMaxDur >= 100) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\titem._iMaxDur++;\r\n\t\t\titem._iDurability = item._iMaxDur;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILFORT:\r\n\t\tif (item._iMaxDur != DUR_INDESTRUCTIBLE && item._iMaxDur < 200) {\r\n\t\t\tr = RandomIntBetween(10, 50);\r\n\t\t\titem._iMaxDur += r;\r\n\t\t\titem._iDurability += r;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILPERM:\r\n\t\titem._iDurability = DUR_INDESTRUCTIBLE;\r\n\t\titem._iMaxDur = DUR_INDESTRUCTIBLE;\r\n\t\tbreak;\r\n\tcase IMISC_OILHARD:\r\n\t\tif (item._iAC < 60) {\r\n\t\t\titem._iAC += RandomIntBetween(1, 2);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase IMISC_OILIMP:\r\n\t\tif (item._iAC < 120) {\r\n\t\t\titem._iAC += RandomIntBetween(3, 5);\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid UpdateHellfireFlag(Item &item, const char *identifiedItemName)\r\n{\r\n\t// DevilutionX support vanilla and hellfire items in one save file and for that introduced CF_HELLFIRE\r\n\t// But vanilla hellfire items don't have CF_HELLFIRE set in Item::dwBuff\r\n\t// This functions tries to set this flag for vanilla hellfire items based on the item name\r\n\t// This ensures that Item::getName() returns the correct translated item name\r\n\tif ((item.dwBuff & CF_HELLFIRE) != 0U)\r\n\t\treturn; // Item is already a hellfire item\r\n\tif (item._iMagical != ITEM_QUALITY_MAGIC)\r\n\t\treturn; // Only magic item's name can differ between diablo and hellfire\r\n\tif (gbIsMultiplayer)\r\n\t\treturn; // Vanilla hellfire multiplayer is not supported in devilutionX, so there can't be items with missing dwBuff from there\r\n\t// We need to test both short and long name, because StringInPanel can return a different result (other font and some bugfixes)\r\n\tconst std::string diabloItemNameShort = GetTranslatedItemNameMagical(item, false, false, false);\r\n\tif (diabloItemNameShort == identifiedItemName)\r\n\t\treturn; // Diablo item name is identical => not a hellfire specific item\r\n\tconst std::string diabloItemNameLong = GetTranslatedItemNameMagical(item, false, false, true);\r\n\tif (diabloItemNameLong == identifiedItemName)\r\n\t\treturn; // Diablo item name is identical => not a hellfire specific item\r\n\tconst std::string hellfireItemNameShort = GetTranslatedItemNameMagical(item, true, false, false);\r\n\tconst std::string hellfireItemNameLong = GetTranslatedItemNameMagical(item, true, false, true);\r\n\tif (hellfireItemNameShort == identifiedItemName || hellfireItemNameLong == identifiedItemName) {\r\n\t\t// This item should be a vanilla hellfire item that has CF_HELLFIRE missing, cause only then the item name matches\r\n\t\titem.dwBuff |= CF_HELLFIRE;\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/items.h",
    "content": "/**\r\n * @file items.h\r\n *\r\n * Interface of item functionality.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"cursor.h\"\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"monster.h\"\r\n#include \"tables/itemdat.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/string_or_view.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#define MAXITEMS 127\r\n#define ITEMTYPES 43\r\n\r\n#define GOLD_SMALL_LIMIT 1000\r\n#define GOLD_MEDIUM_LIMIT 2500\r\n#define GOLD_MAX_LIMIT 5000\r\n\r\n// Item indestructible durability\r\n#define DUR_INDESTRUCTIBLE 255\r\n\r\nconstexpr int ItemNameLength = 64;\r\nconstexpr int MaxVendorValue = 140000;\r\nconstexpr int MaxVendorValueHf = 200000;\r\nconstexpr int MaxBoyValue = 90000;\r\nconstexpr int MaxBoyValueHf = 200000;\r\n\r\nenum item_quality : uint8_t {\r\n\tITEM_QUALITY_NORMAL,\r\n\tITEM_QUALITY_MAGIC,\r\n\tITEM_QUALITY_UNIQUE,\r\n};\r\n\r\nenum _unique_items : int32_t {\r\n\tUITEM_CLEAVER,\r\n\tUITEM_SKCROWN,\r\n\tUITEM_INFRARING,\r\n\tUITEM_OPTAMULET,\r\n\tUITEM_TRING,\r\n\tUITEM_HARCREST,\r\n\tUITEM_STEELVEIL,\r\n\tUITEM_ARMOFVAL,\r\n\tUITEM_GRISWOLD,\r\n\tUITEM_BOVINE,\r\n\tUITEM_RIFTBOW,\r\n\tUITEM_NEEDLER,\r\n\tUITEM_CELESTBOW,\r\n\tUITEM_DEADLYHUNT,\r\n\tUITEM_BOWOFDEAD,\r\n\tUITEM_BLKOAKBOW,\r\n\tUITEM_FLAMEDART,\r\n\tUITEM_FLESHSTING,\r\n\tUITEM_WINDFORCE,\r\n\tUITEM_EAGLEHORN,\r\n\tUITEM_GONNAGALDIRK,\r\n\tUITEM_DEFENDER,\r\n\tUITEM_GRYPHONCLAW,\r\n\tUITEM_BLACKRAZOR,\r\n\tUITEM_GIBBOUSMOON,\r\n\tUITEM_ICESHANK,\r\n\tUITEM_EXECUTIONER,\r\n\tUITEM_BONESAW,\r\n\tUITEM_SHADHAWK,\r\n\tUITEM_WIZSPIKE,\r\n\tUITEM_LGTSABRE,\r\n\tUITEM_FALCONTALON,\r\n\tUITEM_INFERNO,\r\n\tUITEM_DOOMBRINGER,\r\n\tUITEM_GRIZZLY,\r\n\tUITEM_GRANDFATHER,\r\n\tUITEM_MANGLER,\r\n\tUITEM_SHARPBEAK,\r\n\tUITEM_BLOODLSLAYER,\r\n\tUITEM_CELESTAXE,\r\n\tUITEM_WICKEDAXE,\r\n\tUITEM_STONECLEAV,\r\n\tUITEM_AGUHATCHET,\r\n\tUITEM_HELLSLAYER,\r\n\tUITEM_MESSERREAVER,\r\n\tUITEM_CRACKRUST,\r\n\tUITEM_JHOLMHAMM,\r\n\tUITEM_CIVERBS,\r\n\tUITEM_CELESTSTAR,\r\n\tUITEM_BARANSTAR,\r\n\tUITEM_GNARLROOT,\r\n\tUITEM_CRANBASH,\r\n\tUITEM_SCHAEFHAMM,\r\n\tUITEM_DREAMFLANGE,\r\n\tUITEM_STAFFOFSHAD,\r\n\tUITEM_IMMOLATOR,\r\n\tUITEM_STORMSPIRE,\r\n\tUITEM_GLEAMSONG,\r\n\tUITEM_THUNDERCALL,\r\n\tUITEM_PROTECTOR,\r\n\tUITEM_NAJPUZZLE,\r\n\tUITEM_MINDCRY,\r\n\tUITEM_RODOFONAN,\r\n\tUITEM_SPIRITSHELM,\r\n\tUITEM_THINKINGCAP,\r\n\tUITEM_OVERLORDHELM,\r\n\tUITEM_FOOLSCREST,\r\n\tUITEM_GOTTERDAM,\r\n\tUITEM_ROYCIRCLET,\r\n\tUITEM_TORNFLESH,\r\n\tUITEM_GLADBANE,\r\n\tUITEM_RAINCLOAK,\r\n\tUITEM_LEATHAUT,\r\n\tUITEM_WISDWRAP,\r\n\tUITEM_SPARKMAIL,\r\n\tUITEM_SCAVCARAP,\r\n\tUITEM_NIGHTSCAPE,\r\n\tUITEM_NAJPLATE,\r\n\tUITEM_DEMONSPIKE,\r\n\tUITEM_DEFLECTOR,\r\n\tUITEM_SKULLSHLD,\r\n\tUITEM_DRAGONBRCH,\r\n\tUITEM_BLKOAKSHLD,\r\n\tUITEM_HOLYDEF,\r\n\tUITEM_STORMSHLD,\r\n\tUITEM_BRAMBLE,\r\n\tUITEM_REGHA,\r\n\tUITEM_BLEEDER,\r\n\tUITEM_CONSTRICT,\r\n\tUITEM_ENGAGE,\r\n\tUITEM_INVALID = -1,\r\n};\r\n\r\n/*\r\nCF_LEVEL: Item Level (6 bits; value ranges from 0-63)\r\nCF_ONLYGOOD: Item is not able to have affixes with PLOK set to false\r\nCF_UPER15: Item is from a Unique Monster and has 15% chance of being a Unique Item\r\nCF_UPER1: Item is from the dungeon and has a 1% chance of being a Unique Item\r\nCF_UNIQUE: Item is a Unique Item\r\nCF_SMITH: Item is from Griswold (Basic)\r\nCF_SMITHPREMIUM: Item is from Griswold (Premium)\r\nCF_BOY: Item is from Wirt\r\nCF_WITCH: Item is from Adria\r\nCF_HEALER: Item is from Pepin\r\nCF_PREGEN: Item is pre-generated, mostly associated with Quest items found in the dungeon or potions on the dungeon floor\r\n\r\nItems that have both CF_UPER15 and CF_UPER1 are CF_USEFUL, which is used to generate Potions and Town Portal scrolls on the dungeon floor\r\nItems that have any of CF_SMITH, CF_SMITHPREMIUM, CF_BOY, CF_WICTH, and CF_HEALER are CF_TOWN, indicating the item is sourced from an NPC\r\n*/\r\nenum icreateinfo_flag {\r\n\t// clang-format off\r\n\tCF_LEVEL        = (1 << 6) - 1,\r\n\tCF_ONLYGOOD     = 1 << 6,\r\n\tCF_UPER15       = 1 << 7,\r\n\tCF_UPER1        = 1 << 8,\r\n\tCF_UNIQUE       = 1 << 9,\r\n\tCF_SMITH        = 1 << 10,\r\n\tCF_SMITHPREMIUM = 1 << 11,\r\n\tCF_BOY          = 1 << 12,\r\n\tCF_WITCH        = 1 << 13,\r\n\tCF_HEALER       = 1 << 14,\r\n\tCF_PREGEN       = 1 << 15,\r\n\r\n\tCF_USEFUL = CF_UPER15 | CF_UPER1,\r\n\tCF_TOWN   = CF_SMITH | CF_SMITHPREMIUM | CF_BOY | CF_WITCH | CF_HEALER,\r\n\t// clang-format on\r\n};\r\n\r\nenum icreateinfo_flag2 {\r\n\t// clang-format off\r\n\tCF_HELLFIRE = 1 << 0,\r\n\tCF_UIDOFFSET = ((1 << 4) - 1) << 1,\r\n\t// clang-format on\r\n};\r\n\r\n// All item animation frames have this width.\r\nconstexpr int ItemAnimWidth = 96;\r\n\r\n// Defined in player.h, forward declared here to allow for functions which operate in the context of a player.\r\nstruct Player;\r\n\r\nstruct Item {\r\n\t/** Randomly generated identifier */\r\n\tuint32_t _iSeed = 0;\r\n\tuint16_t _iCreateInfo = 0;\r\n\tItemType _itype = ItemType::None;\r\n\tbool _iAnimFlag = false;\r\n\tPoint position = { 0, 0 };\r\n\t/*\r\n\t * @brief Contains Information for current Animation\r\n\t */\r\n\tAnimationInfo AnimInfo;\r\n\tbool _iDelFlag = false; // set when item is flagged for deletion, deprecated in 1.02\r\n\tSelectionRegion selectionRegion = SelectionRegion::None;\r\n\tbool _iPostDraw = false;\r\n\tbool _iIdentified = false;\r\n\titem_quality _iMagical = ITEM_QUALITY_NORMAL;\r\n\tchar _iName[ItemNameLength] = {};\r\n\tchar _iIName[ItemNameLength] = {};\r\n\titem_equip_type _iLoc = ILOC_NONE;\r\n\titem_class _iClass = ICLASS_NONE;\r\n\tuint8_t _iCurs = 0;\r\n\tint _ivalue = 0;\r\n\tint _iIvalue = 0;\r\n\tuint8_t _iMinDam = 0;\r\n\tuint8_t _iMaxDam = 0;\r\n\tint16_t _iAC = 0;\r\n\tItemSpecialEffect _iFlags = ItemSpecialEffect::None;\r\n\titem_misc_id _iMiscId = IMISC_NONE;\r\n\tSpellID _iSpell = SpellID::Null;\r\n\t_item_indexes IDidx = IDI_NONE;\r\n\tint _iCharges = 0;\r\n\tint _iMaxCharges = 0;\r\n\tint _iDurability = 0;\r\n\tint _iMaxDur = 0;\r\n\tint16_t _iPLDam = 0;\r\n\tint16_t _iPLToHit = 0;\r\n\tint16_t _iPLAC = 0;\r\n\tint16_t _iPLStr = 0;\r\n\tint16_t _iPLMag = 0;\r\n\tint16_t _iPLDex = 0;\r\n\tint16_t _iPLVit = 0;\r\n\tint16_t _iPLFR = 0;\r\n\tint16_t _iPLLR = 0;\r\n\tint16_t _iPLMR = 0;\r\n\tint16_t _iPLMana = 0;\r\n\tint16_t _iPLHP = 0;\r\n\tint16_t _iPLDamMod = 0;\r\n\tint16_t _iPLGetHit = 0;\r\n\tint16_t _iPLLight = 0;\r\n\tint8_t _iSplLvlAdd = 0;\r\n\tbool _iRequest = false;\r\n\t/** Unique item ID, used as an index into UniqueItemList */\r\n\tint _iUid = 0;\r\n\tint16_t _iFMinDam = 0;\r\n\tint16_t _iFMaxDam = 0;\r\n\tint16_t _iLMinDam = 0;\r\n\tint16_t _iLMaxDam = 0;\r\n\tint16_t _iPLEnAc = 0;\r\n\tenum item_effect_type _iPrePower = IPL_INVALID;\r\n\tenum item_effect_type _iSufPower = IPL_INVALID;\r\n\tint _iVAdd1 = 0;\r\n\tint _iVMult1 = 0;\r\n\tint _iVAdd2 = 0;\r\n\tint _iVMult2 = 0;\r\n\tint8_t _iMinStr = 0;\r\n\tuint8_t _iMinMag = 0;\r\n\tint8_t _iMinDex = 0;\r\n\tbool _iStatFlag = false;\r\n\tItemSpecialEffectHf _iDamAcFlags = ItemSpecialEffectHf::None;\r\n\tuint32_t dwBuff = 0;\r\n\r\n\t/**\r\n\t * @brief Clears this item and returns the old value\r\n\t */\r\n\tItem pop() &\r\n\t{\r\n\t\tItem temp = std::move(*this);\r\n\t\tclear();\r\n\t\treturn temp;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Resets the item so isEmpty() returns true without needing to reinitialise the whole object\r\n\t */\r\n\tDVL_REINITIALIZES void clear()\r\n\t{\r\n\t\tthis->_itype = ItemType::None;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is empty or not.\r\n\t * @return 'True' in case the item is empty and 'False' otherwise.\r\n\t */\r\n\tbool isEmpty() const\r\n\t{\r\n\t\treturn this->_itype == ItemType::None;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is an equipment.\r\n\t * @return 'True' in case the item is an equipment and 'False' otherwise.\r\n\t */\r\n\tbool isEquipment() const\r\n\t{\r\n\t\tif (this->isEmpty()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tswitch (this->_iLoc) {\r\n\t\tcase ILOC_AMULET:\r\n\t\tcase ILOC_ARMOR:\r\n\t\tcase ILOC_HELM:\r\n\t\tcase ILOC_ONEHAND:\r\n\t\tcase ILOC_RING:\r\n\t\tcase ILOC_TWOHAND:\r\n\t\t\treturn true;\r\n\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is a weapon.\r\n\t * @return 'True' in case the item is a weapon and 'False' otherwise.\r\n\t */\r\n\tbool isWeapon() const\r\n\t{\r\n\t\tswitch (this->_itype) {\r\n\t\tcase ItemType::Axe:\r\n\t\tcase ItemType::Bow:\r\n\t\tcase ItemType::Mace:\r\n\t\tcase ItemType::Staff:\r\n\t\tcase ItemType::Sword:\r\n\t\t\treturn true;\r\n\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is an armor.\r\n\t * @return 'True' in case the item is an armor and 'False' otherwise.\r\n\t */\r\n\tbool isArmor() const\r\n\t{\r\n\t\tswitch (this->_itype) {\r\n\t\tcase ItemType::HeavyArmor:\r\n\t\tcase ItemType::LightArmor:\r\n\t\tcase ItemType::MediumArmor:\r\n\t\t\treturn true;\r\n\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is gold.\r\n\t * @return 'True' in case the item is gold and 'False' otherwise.\r\n\t */\r\n\tbool isGold() const\r\n\t{\r\n\t\treturn this->_itype == ItemType::Gold;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is a helm.\r\n\t * @return 'True' in case the item is a helm and 'False' otherwise.\r\n\t */\r\n\tbool isHelm() const\r\n\t{\r\n\t\treturn this->_itype == ItemType::Helm;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is a shield.\r\n\t * @return 'True' in case the item is a shield and 'False' otherwise.\r\n\t */\r\n\tbool isShield() const\r\n\t{\r\n\t\treturn this->_itype == ItemType::Shield;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Checks whether this item is a jewelry.\r\n\t * @return 'True' in case the item is a jewelry and 'False' otherwise.\r\n\t */\r\n\tbool isJewelry() const\r\n\t{\r\n\t\tswitch (this->_itype) {\r\n\t\tcase ItemType::Amulet:\r\n\t\tcase ItemType::Ring:\r\n\t\t\treturn true;\r\n\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t[[nodiscard]] bool isScroll() const\r\n\t{\r\n\t\treturn IsAnyOf(_iMiscId, IMISC_SCROLL, IMISC_SCROLLT);\r\n\t}\r\n\r\n\t[[nodiscard]] bool isScrollOf(SpellID spellId) const\r\n\t{\r\n\t\treturn isScroll() && _iSpell == spellId;\r\n\t}\r\n\r\n\t[[nodiscard]] bool isRune() const\r\n\t{\r\n\t\treturn _iMiscId > IMISC_RUNEFIRST && _iMiscId < IMISC_RUNELAST;\r\n\t}\r\n\r\n\t[[nodiscard]] bool isRuneOf(SpellID spellId) const\r\n\t{\r\n\t\tif (!isRune())\r\n\t\t\treturn false;\r\n\t\tswitch (_iMiscId) {\r\n\t\tcase IMISC_RUNEF:\r\n\t\t\treturn spellId == SpellID::RuneOfFire;\r\n\t\tcase IMISC_RUNEL:\r\n\t\t\treturn spellId == SpellID::RuneOfLight;\r\n\t\tcase IMISC_GR_RUNEL:\r\n\t\t\treturn spellId == SpellID::RuneOfNova;\r\n\t\tcase IMISC_GR_RUNEF:\r\n\t\t\treturn spellId == SpellID::RuneOfImmolation;\r\n\t\tcase IMISC_RUNES:\r\n\t\t\treturn spellId == SpellID::RuneOfStone;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t[[nodiscard]] bool isUsable() const;\r\n\r\n\t[[nodiscard]] bool keyAttributesMatch(uint32_t seed, _item_indexes itemIndex, uint16_t createInfo) const\r\n\t{\r\n\t\treturn _iSeed == seed && IDidx == itemIndex && _iCreateInfo == createInfo;\r\n\t}\r\n\r\n\tUiFlags getTextColor() const\r\n\t{\r\n\t\tswitch (_iMagical) {\r\n\t\tcase ITEM_QUALITY_MAGIC:\r\n\t\t\treturn UiFlags::ColorBlue;\r\n\t\tcase ITEM_QUALITY_UNIQUE:\r\n\t\t\treturn UiFlags::ColorWhitegold;\r\n\t\tdefault:\r\n\t\t\treturn UiFlags::ColorWhite;\r\n\t\t}\r\n\t}\r\n\r\n\tUiFlags getTextColorWithStatCheck() const\r\n\t{\r\n\t\tif (!_iStatFlag)\r\n\t\t\treturn UiFlags::ColorRed;\r\n\t\treturn getTextColor();\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Sets the current Animation for the Item\r\n\t * @param showAnimation Definies if the Animation (Flipping) is shown or if only the final Frame (item on the ground) is shown\r\n\t */\r\n\tvoid setNewAnimation(bool showAnimation);\r\n\r\n\t/**\r\n\t * @brief If this item is a spell book, calculates the magic requirement to learn a new level, then for all items sets _iStatFlag\r\n\t * @param player Player to compare stats against requirements\r\n\t */\r\n\tvoid updateRequiredStatsCacheForPlayer(const Player &player);\r\n\r\n\t/** @brief Returns the translated item name to display (respects identified flag) */\r\n\tStringOrView getName() const;\r\n\r\n\t[[nodiscard]] Displacement getRenderingOffset(const ClxSprite sprite) const\r\n\t{\r\n\t\treturn { -CalculateSpriteTileCenterX(sprite.width()), 0 };\r\n\t}\r\n};\r\n\r\nstruct ItemGetRecordStruct {\r\n\tuint32_t nSeed;\r\n\tuint16_t wCI;\r\n\tint nIndex;\r\n\tuint32_t dwTimestamp;\r\n};\r\n\r\nstruct CornerStoneStruct {\r\n\tPoint position;\r\n\tbool activated;\r\n\tItem item;\r\n\tbool isAvailable();\r\n};\r\n\r\n/** Contains the items on ground in the current game. */\r\nextern Item Items[MAXITEMS + 1];\r\nextern uint8_t ActiveItems[MAXITEMS];\r\nextern uint8_t ActiveItemCount;\r\n/** Contains the location of dropped items. */\r\nextern int8_t dItem[MAXDUNX][MAXDUNY];\r\nextern bool ShowUniqueItemInfoBox;\r\nextern CornerStoneStruct CornerStone;\r\nextern DVL_API_FOR_TEST bool UniqueItemFlags[128];\r\n\r\nuint8_t GetOutlineColor(const Item &item, bool checkReq);\r\nbool IsItemAvailable(int i);\r\nvoid ClearUniqueItemFlags();\r\nvoid InitItemGFX();\r\nvoid InitItems();\r\nvoid CalcPlrItemVals(Player &player, bool Loadgfx);\r\nvoid CalcPlrInv(Player &player, bool Loadgfx);\r\nvoid InitializeItem(Item &item, _item_indexes itemData);\r\nvoid GenerateNewSeed(Item &item);\r\nint GetGoldCursor(int value);\r\n\r\n/**\r\n * @brief Update the gold cursor on the given gold item\r\n * @param gold The item to update\r\n */\r\nvoid SetPlrHandGoldCurs(Item &gold);\r\nvoid CreatePlrItems(Player &player);\r\nbool ItemSpaceOk(Point position);\r\nint AllocateItem();\r\n/**\r\n * @brief Moves the item onto the floor of the current dungeon level\r\n * @param item The source of the item data, should not be used after calling this function\r\n * @param position Coordinates of the tile to place the item on\r\n * @return The index assigned to the item\r\n */\r\nuint8_t PlaceItemInWorld(Item &&item, WorldTilePosition position);\r\nPoint GetSuperItemLoc(Point position);\r\nvoid GetItemAttrs(Item &item, _item_indexes itemData, int lvl);\r\nvoid SetupItem(Item &item);\r\nItem *SpawnUnique(_unique_items uid, Point position, std::optional<int> level = std::nullopt, bool sendmsg = true, bool exactPosition = false);\r\nvoid GetSuperItemSpace(Point position, int8_t inum);\r\n_item_indexes RndItemForMonsterLevel(int8_t monsterLevel);\r\nvoid SetupAllItems(const Player &player, Item &item, _item_indexes idx, uint32_t iseed, int lvl, int uper, bool onlygood, bool pregen, int uidOffset = 0, bool forceNotUnique = false);\r\nvoid TryRandomUniqueItem(Item &item, _item_indexes idx, int8_t mLevel, int uper, bool onlygood, bool pregen);\r\nvoid SpawnItem(Monster &monster, Point position, bool sendmsg, bool spawn = false);\r\nvoid CreateRndItem(Point position, bool onlygood, bool sendmsg, bool delta);\r\nvoid CreateRndUseful(Point position, bool sendmsg);\r\nvoid CreateTypeItem(Point position, bool onlygood, ItemType itemType, int imisc, bool sendmsg, bool delta, bool spawn = false);\r\nvoid RecreateItem(const Player &player, Item &item, _item_indexes idx, uint16_t icreateinfo, uint32_t iseed, int ivalue, uint32_t dwBuff);\r\nvoid RecreateEar(Item &item, uint16_t ic, uint32_t iseed, uint8_t bCursval, std::string_view heroName);\r\nvoid CornerstoneSave();\r\nvoid CornerstoneLoad(Point position);\r\nvoid SpawnQuestItem(_item_indexes itemid, Point position, int randarea, SelectionRegion selectionRegion, bool sendmsg);\r\nvoid SpawnRewardItem(_item_indexes itemid, Point position, bool sendmsg);\r\nvoid SpawnMapOfDoom(Point position, bool sendmsg);\r\nvoid SpawnRuneBomb(Point position, bool sendmsg);\r\nvoid SpawnTheodore(Point position, bool sendmsg);\r\nvoid RespawnItem(Item &item, bool FlipFlag);\r\nvoid DeleteItem(int i);\r\nvoid ProcessItems();\r\nvoid FreeItemGFX();\r\nvoid GetItemFrm(Item &item);\r\nvoid GetItemStr(Item &item);\r\nvoid CheckIdentify(Player &player, int cii);\r\nvoid DoRepair(Player &player, int cii);\r\nvoid DoRecharge(Player &player, int cii);\r\nbool DoOil(Player &player, int cii);\r\n[[nodiscard]] StringOrView PrintItemPower(char plidx, const Item &item);\r\nvoid DrawUniqueInfo(const Surface &out);\r\nvoid PrintItemDetails(const Item &item);\r\nvoid PrintItemDur(const Item &item);\r\nvoid UseItem(Player &player, item_misc_id Mid, SpellID spellID, int spellFrom);\r\nbool UseItemOpensHive(const Item &item, Point position);\r\nbool UseItemOpensGrave(const Item &item, Point position);\r\nvoid SpawnSmith(int lvl);\r\nvoid ReplacePremium(const Player &player, int idx);\r\nvoid SpawnPremium(const Player &player);\r\nvoid SpawnWitch(int lvl);\r\nvoid SpawnBoy(int lvl);\r\nvoid SpawnHealer(int lvl);\r\nvoid MakeGoldStack(Item &goldItem, int value);\r\nint ItemNoFlippy();\r\nvoid CreateSpellBook(Point position, SpellID ispell, bool sendmsg, bool delta);\r\nvoid CreateMagicArmor(Point position, ItemType itemType, int icurs, bool sendmsg, bool delta);\r\nvoid CreateAmulet(Point position, int lvl, bool sendmsg, bool delta, bool spawn = false);\r\nvoid CreateMagicWeapon(Point position, ItemType itemType, int icurs, bool sendmsg, bool delta);\r\nbool GetItemRecord(uint32_t nSeed, uint16_t wCI, int nIndex);\r\nvoid SetItemRecord(uint32_t nSeed, uint16_t wCI, int nIndex);\r\nvoid PutItemRecord(uint32_t nSeed, uint16_t wCI, int nIndex);\r\n\r\n/**\r\n * @brief Resets item get records.\r\n */\r\nvoid initItemGetRecords();\r\n\r\nvoid RepairItem(Item &item, int lvl);\r\nvoid RechargeItem(Item &item, Player &player);\r\nbool ApplyOilToItem(Item &item, Player &player);\r\n/**\r\n * @brief Checks if the item is generated in vanilla hellfire. If yes it updates dwBuff to include CF_HELLFIRE.\r\n */\r\nvoid UpdateHellfireFlag(Item &item, const char *identifiedItemName);\r\n\r\n/* data */\r\n\r\nextern int MaxGold;\r\n\r\nextern int8_t ItemCAnimTbl[];\r\nextern SfxID ItemInvSnds[];\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/crypt.cpp",
    "content": "#include \"levels/crypt.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"items.h\"\r\n#include \"levels/drlg_l1.h\"\r\n#include \"lighting.h\"\r\n\r\nnamespace devilution {\r\n\r\nint UberRow;\r\nint UberCol;\r\nbool IsUberRoomOpened;\r\nbool IsUberLeverActivated;\r\nint UberDiabloMonsterIndex;\r\n\r\n/** Miniset: stairs up. */\r\nconst Miniset L5STAIRSUP {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 22, 22, 22, 22 },\r\n\t    { 2, 2, 2, 2 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 66, 23, 0 },\r\n\t    { 63, 64, 65, 0 },\r\n\t    { 0, 67, 68, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n\r\nnamespace {\r\n\r\nconst Miniset L5STAIRSUPHF {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 22, 22, 22, 22 },\r\n\t    { 22, 22, 22, 22 },\r\n\t    { 2, 2, 2, 2 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 54, 23, 0 },\r\n\t    { 0, 53, 18, 0 },\r\n\t    { 55, 56, 57, 0 },\r\n\t    { 58, 59, 60, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset L5STAIRSDOWN {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 52, 0 },\r\n\t    { 0, 48, 51, 0 },\r\n\t    { 0, 47, 50, 0 },\r\n\t    { 45, 46, 49, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset L5STAIRSTOWN {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 22, 22, 22, 22 },\r\n\t    { 22, 22, 22, 22 },\r\n\t    { 2, 2, 2, 2 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 62, 23, 0 },\r\n\t    { 0, 61, 18, 0 },\r\n\t    { 63, 64, 65, 0 },\r\n\t    { 66, 67, 68, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset VWallSection {\r\n\t{ 1, 3 },\r\n\t{\r\n\t    { 1 },\r\n\t    { 1 },\r\n\t    { 1 },\r\n\t},\r\n\t{\r\n\t    { 91 },\r\n\t    { 90 },\r\n\t    { 89 },\r\n\t}\r\n};\r\nconst Miniset HWallSection {\r\n\t{ 3, 1 },\r\n\t{ { 2, 2, 2 } },\r\n\t{ { 94, 93, 92 } }\r\n};\r\nconst Miniset CryptFloorLave {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 101, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset CryptPillar1 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 167, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset CryptPillar2 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 168, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset CryptPillar3 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 169, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset CryptPillar4 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 170, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset CryptPillar5 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 171, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset CryptStar {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t    { 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 172, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n\r\nenum Tile : uint8_t {\r\n\t// clang-format off\r\n\tVWall          =   1,\r\n\tHWall          =   2,\r\n\tCorner         =   3,\r\n\tDWall          =   4,\r\n\tDArch          =   5,\r\n\tVWallEnd       =   6,\r\n\tHWallEnd       =   7,\r\n\tHArchEnd       =   8,\r\n\tVArchEnd       =   9,\r\n\tHArchVWall     =  10,\r\n\tVArch          =  11,\r\n\tHArch          =  12,\r\n\tFloor          =  13,\r\n\tHWallVArch     =  14,\r\n\tPillar         =  15,\r\n\tPillar1        =  16,\r\n\tPillar2        =  17,\r\n\tDirtHwall      =  18,\r\n\tDirtVwall      =  19,\r\n\tDirtCorner     =  21,\r\n\tDirtHWallEnd   =  23,\r\n\tDirtVWallEnd   =  24,\r\n\tVDoor          =  25,\r\n\tHDoor          =  26,\r\n\tHFenceVWall    =  27,\r\n\tHDoorVDoor     =  28,\r\n\tDFence         =  29,\r\n\tVDoorEnd       =  30,\r\n\tHDoorEnd       =  31,\r\n\tVFenceEnd      =  32,\r\n\tVFence         =  35,\r\n\tHFence         =  36,\r\n\tHWallVFence    =  37,\r\n\tHArchVFence    =  38,\r\n\tHArchVDoor     =  39,\r\n\tEntranceStairs =  64,\r\n\tDirtHWall2     =  82,\r\n\tDirtVWall2     =  83,\r\n\tDirtCorner2    =  85,\r\n\tDirtHWallEnd2  =  87,\r\n\tDirtVWallEnd2  =  88,\r\n\tVWall5         =  89,\r\n\tVWall6         =  90,\r\n\tVWall7         =  91,\r\n\tHWall5         =  92,\r\n\tHWall6         =  93,\r\n\tHWall7         =  94,\r\n\tVArch5         =  95,\r\n\tHArch5         =  96,\r\n\tFloor6         =  97,\r\n\tFloor7         =  98,\r\n\tFloor8         =  99,\r\n\tFloor9         = 100,\r\n\tFloor10        = 101,\r\n\tVWall2         = 112,\r\n\tHWall2         = 113,\r\n\tCorner2        = 114,\r\n\tDWall2         = 115,\r\n\tDArch2         = 116,\r\n\tVWallEnd2      = 117,\r\n\tHWallEnd2      = 118,\r\n\tHArchEnd2      = 119,\r\n\tVArchEnd2      = 120,\r\n\tHArchVWall2    = 121,\r\n\tVArch2         = 122,\r\n\tHArch2         = 123,\r\n\tFloor2         = 124,\r\n\tHWallVArch2    = 125,\r\n\tPillar3        = 126,\r\n\tPillar4        = 127,\r\n\tPillar5        = 128,\r\n\tVWall3         = 129,\r\n\tHWall3         = 130,\r\n\tCorner3        = 131,\r\n\tDWall3         = 132,\r\n\tDArch3         = 133,\r\n\tVWallEnd3      = 134,\r\n\tHWallEnd3      = 135,\r\n\tHArchEnd3      = 136,\r\n\tVArchEnd3      = 137,\r\n\tHArchVWall3    = 138,\r\n\tVArch3         = 139,\r\n\tHArch3         = 140,\r\n\tFloor3         = 141,\r\n\tHWallVArch3    = 142,\r\n\tPillar6        = 143,\r\n\tPillar7        = 144,\r\n\tPillar8        = 145,\r\n\tVWall4         = 146,\r\n\tHWall4         = 147,\r\n\tCorner4        = 148,\r\n\tDWall4         = 149,\r\n\tDArch4         = 150,\r\n\tVWallEnd4      = 151,\r\n\tHWallEnd4      = 152,\r\n\tHArchEnd4      = 153,\r\n\tVArchEnd4      = 154,\r\n\tHArchVWall4    = 155,\r\n\tVArch4         = 156,\r\n\tHArch4         = 157,\r\n\tFloor4         = 158,\r\n\tHWallVArch4    = 159,\r\n\tPillar9        = 160,\r\n\tPillar10       = 161,\r\n\tPillar11       = 162,\r\n\tFloor11        = 163,\r\n\tFloor12        = 164,\r\n\tFloor13        = 165,\r\n\tFloor14        = 166,\r\n\tPillarHalf     = 167,\r\n\tVWall8         = 173,\r\n\tVWall9         = 174,\r\n\tVWall10        = 175,\r\n\tVWall11        = 176,\r\n\tVWall12        = 177,\r\n\tVWall13        = 178,\r\n\tHWall8         = 179,\r\n\tHWall9         = 180,\r\n\tHWall10        = 181,\r\n\tHWall11        = 182,\r\n\tHWall12        = 183,\r\n\tHWall13        = 184,\r\n\tVArch6         = 185,\r\n\tVArch7         = 186,\r\n\tHArch6         = 187,\r\n\tHArch7         = 188,\r\n\tFloor15        = 189,\r\n\tFloor16        = 190,\r\n\tFloor17        = 191,\r\n\tPillar12       = 192,\r\n\tFloor18        = 193,\r\n\tFloor19        = 194,\r\n\tFloor20        = 195,\r\n\tFloor21        = 196,\r\n\tFloor22        = 197,\r\n\tFloor23        = 198,\r\n\tVDemon         = 199,\r\n\tHDemon         = 200,\r\n\tVSuccubus      = 201,\r\n\tHSuccubus      = 202,\r\n\tShadow1        = 203,\r\n\tShadow2        = 204,\r\n\tShadow3        = 205,\r\n\tShadow4        = 206,\r\n\tShadow5        = 207,\r\n\tShadow6        = 208,\r\n\tShadow7        = 209,\r\n\tShadow8        = 210,\r\n\tShadow9        = 211,\r\n\tShadow10       = 212,\r\n\tShadow11       = 213,\r\n\tShadow12       = 214,\r\n\tShadow13       = 215,\r\n\tShadow14       = 216,\r\n\tShadow15       = 217,\r\n\t// clang-format on\r\n};\r\n\r\nstruct ReplaceTile {\r\n\tTile search;\r\n\tTile replace;\r\n};\r\n\r\nconst ReplaceTile Statues[] {\r\n\t// clang-format off\r\n\t{ VWall, VDemon    },\r\n\t{ VWall, VSuccubus },\r\n\t{ HWall, HDemon    },\r\n\t{ HWall, HSuccubus },\r\n\t// clang-format on\r\n};\r\n\r\nconst ReplaceTile CrackedTiles[] {\r\n\t// clang-format off\r\n\t{ VWall,      VWall2      },\r\n\t{ HWall,      HWall2      },\r\n\t{ Corner,     Corner2     },\r\n\t{ DWall,      DWall2      },\r\n\t{ DArch,      DArch2      },\r\n\t{ VWallEnd,   VWallEnd2   },\r\n\t{ HWallEnd,   HWallEnd2   },\r\n\t{ HArchEnd,   HArchEnd2   },\r\n\t{ VArchEnd,   VArchEnd2   },\r\n\t{ HArchVWall, HArchVWall2 },\r\n\t{ VArch,      VArch2      },\r\n\t{ HArch,      HArch2      },\r\n\t{ Floor,      Floor2      },\r\n\t{ HWallVArch, HWallVArch2 },\r\n\t{ Pillar,     Pillar3     },\r\n\t{ Pillar1,    Pillar4     },\r\n\t{ Pillar2,    Pillar5     },\r\n\t// clang-format on\r\n};\r\n\r\nconst ReplaceTile BrokenTiles[] {\r\n\t// clang-format off\r\n\t{ VWall,      VWall3      },\r\n\t{ HWall,      HWall3      },\r\n\t{ Corner,     Corner3     },\r\n\t{ DWall,      DWall3      },\r\n\t{ DArch,      DArch3      },\r\n\t{ VWallEnd,   VWallEnd3   },\r\n\t{ HWallEnd,   HWallEnd3   },\r\n\t{ HArchEnd,   HArchEnd3   },\r\n\t{ VArchEnd,   VArchEnd3   },\r\n\t{ HArchVWall, HArchVWall3 },\r\n\t{ VArch,      VArch3      },\r\n\t{ HArch,      HArch3      },\r\n\t{ Floor,      Floor3      },\r\n\t{ HWallVArch, HWallVArch3 },\r\n\t{ Pillar,     Pillar6     },\r\n\t{ Pillar1,    Pillar7     },\r\n\t{ Pillar2,    Pillar8     },\r\n\t// clang-format on\r\n};\r\n\r\nconst ReplaceTile LeakingTiles[] {\r\n\t// clang-format off\r\n\t{ VWall,      VWall4      },\r\n\t{ HWall,      HWall4      },\r\n\t{ Corner,     Corner4     },\r\n\t{ DWall,      DWall4      },\r\n\t{ DArch,      DArch4      },\r\n\t{ VWallEnd,   VWallEnd4   },\r\n\t{ HWallEnd,   HWallEnd4   },\r\n\t{ HArchEnd,   HArchEnd4   },\r\n\t{ VArchEnd,   VArchEnd4   },\r\n\t{ HArchVWall, HArchVWall4 },\r\n\t{ VArch,      VArch4      },\r\n\t{ HArch,      HArch4      },\r\n\t{ Floor,      Floor4      },\r\n\t{ HWallVArch, HWallVArch4 },\r\n\t{ Pillar,     Pillar9     },\r\n\t{ Pillar1,    Pillar10    },\r\n\t{ Pillar2,    Pillar11    },\r\n\t// clang-format on\r\n};\r\n\r\nconst ReplaceTile Substitions1Tiles[] {\r\n\t// clang-format off\r\n\t{ VArch,   VArch6   },\r\n\t{ HArch,   HArch6   },\r\n\t{ VArch,   VArch7   },\r\n\t{ HArch,   HArch7   },\r\n\t{ VWall5,  VWall8   },\r\n\t{ VWall5,  VWall9   },\r\n\t{ VWall6,  VWall10  },\r\n\t{ VWall6,  VWall11  },\r\n\t{ VWall7,  VWall12  },\r\n\t{ VWall7,  VWall13  },\r\n\t{ HWall5,  HWall8   },\r\n\t{ HWall5,  HWall9   },\r\n\t{ HWall5,  HWall10  },\r\n\t{ HWall5,  HWall11  },\r\n\t{ HWall5,  HWall12  },\r\n\t{ HWall5,  HWall13  },\r\n\t{ Floor7,  Floor15  },\r\n\t{ Floor7,  Floor16  },\r\n\t{ Floor6,  Floor17  },\r\n\t{ Pillar,  Pillar12 },\r\n\t{ Floor8,  Floor18  },\r\n\t{ Floor8,  Floor19  },\r\n\t{ Floor9,  Floor20  },\r\n\t{ Floor10, Floor21  },\r\n\t{ Floor10, Floor22  },\r\n\t{ Floor10, Floor23  },\r\n\t// clang-format on\r\n};\r\n\r\nconst ReplaceTile Substition1Floor[] {\r\n\t// clang-format off\r\n\t{ Floor, Floor11 },\r\n\t{ Floor, Floor12 },\r\n\t{ Floor, Floor13 },\r\n\t{ Floor, Floor14 },\r\n\t// clang-format on\r\n};\r\n\r\nconst ReplaceTile Substition2Floor[] {\r\n\t// clang-format off\r\n\t{ Floor, Floor6 },\r\n\t{ Floor, Floor7 },\r\n\t{ Floor, Floor8 },\r\n\t{ Floor, Floor9 },\r\n\t// clang-format on\r\n};\r\n\r\nvoid ApplyCryptShadowsPatterns()\r\n{\r\n\tfor (int j = 1; j < DMAXY; j++) {\r\n\t\tfor (int i = 1; i < DMAXX; i++) {\r\n\t\t\tswitch (dungeon[i][j]) {\r\n\t\t\tcase DArch:\r\n\t\t\tcase DArch2:\r\n\t\t\tcase DArch3:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow1;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow2;\r\n\t\t\t\tif (dungeon[i][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j - 1] = Shadow3;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HWallEnd:\r\n\t\t\tcase HWallEnd2:\r\n\t\t\tcase HWallEnd3:\r\n\t\t\tcase HWallEnd4:\r\n\t\t\tcase Pillar:\r\n\t\t\tcase Pillar2:\r\n\t\t\tcase Pillar3:\r\n\t\t\tcase Pillar5:\r\n\t\t\tcase Pillar9:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow4;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow5;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HArchEnd:\r\n\t\t\tcase HArchEnd2:\r\n\t\t\tcase HArchEnd3:\r\n\t\t\tcase HArchEnd4:\r\n\t\t\tcase HWallVArch:\r\n\t\t\tcase HWallVArch2:\r\n\t\t\tcase HWallVArch3:\r\n\t\t\tcase HWallVArch4:\r\n\t\t\tcase VArch:\r\n\t\t\tcase VArch4:\r\n\t\t\tcase VArch5:\r\n\t\t\tcase VArch6:\r\n\t\t\tcase VArch7:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow1;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow2;\r\n\t\t\t\tbreak;\r\n\t\t\tcase VArchEnd:\r\n\t\t\tcase VArchEnd2:\r\n\t\t\tcase VArchEnd4:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow4;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow5;\r\n\t\t\t\tif (dungeon[i][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j - 1] = Shadow3;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HArch:\r\n\t\t\tcase HArch2:\r\n\t\t\tcase HArchVWall:\r\n\t\t\tcase HArchVWall2:\r\n\t\t\tcase HArchVWall3:\r\n\t\t\tcase HArchVWall4:\r\n\t\t\t\tif (dungeon[i][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j - 1] = Shadow3;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HArch5:\r\n\t\t\tcase HArch6:\r\n\t\t\t\tif (dungeon[i][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j - 1] = Shadow6;\r\n\t\t\t\tbreak;\r\n\t\t\tcase VArch2:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow9;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow10;\r\n\t\t\t\tbreak;\r\n\t\t\tcase VArchEnd3:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow11;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow12;\r\n\t\t\t\tif (dungeon[i][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j - 1] = Shadow3;\r\n\t\t\t\tbreak;\r\n\t\t\tcase VArch3:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow13;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow14;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HArch3:\r\n\t\t\tcase HArch4:\r\n\t\t\t\tif (dungeon[i][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j - 1] = Shadow15;\r\n\t\t\t\tbreak;\r\n\t\t\tcase Pillar6:\r\n\t\t\tcase Pillar8:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow11;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow12;\r\n\t\t\t\tbreak;\r\n\t\t\tcase DArch4:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow1;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow2;\r\n\t\t\t\tif (dungeon[i][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j - 1] = Shadow15;\r\n\t\t\t\tbreak;\r\n\t\t\tcase Pillar11:\r\n\t\t\tcase Pillar12:\r\n\t\t\tcase PillarHalf:\r\n\t\t\t\tif (dungeon[i - 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j] = Shadow7;\r\n\t\t\t\tif (dungeon[i - 1][j - 1] == Floor)\r\n\t\t\t\t\tdungeon[i - 1][j - 1] = Shadow8;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlaceMiniSetRandom1x1(uint8_t search, uint8_t replace, int rndper)\r\n{\r\n\tPlaceMiniSetRandom({ { 1, 1 }, { { search } }, { { replace } } }, rndper);\r\n}\r\n\r\nvoid CryptCracked(int rndper)\r\n{\r\n\tfor (const ReplaceTile pair : CrackedTiles) {\r\n\t\tPlaceMiniSetRandom1x1(pair.search, pair.replace, rndper);\r\n\t}\r\n}\r\n\r\nvoid CryptBroken(int rndper)\r\n{\r\n\tfor (const ReplaceTile pair : BrokenTiles) {\r\n\t\tPlaceMiniSetRandom1x1(pair.search, pair.replace, rndper);\r\n\t}\r\n}\r\n\r\nvoid CryptLeaking(int rndper)\r\n{\r\n\tfor (const ReplaceTile pair : LeakingTiles) {\r\n\t\tPlaceMiniSetRandom1x1(pair.search, pair.replace, rndper);\r\n\t}\r\n}\r\n\r\nvoid CryptSubstitions1(int rndper)\r\n{\r\n\tfor (const ReplaceTile pair : Substitions1Tiles) {\r\n\t\tPlaceMiniSetRandom1x1(pair.search, pair.replace, rndper);\r\n\t}\r\n}\r\n\r\nvoid CryptSubstitions2(int rndper)\r\n{\r\n\tPlaceMiniSetRandom(CryptPillar1, rndper);\r\n\tPlaceMiniSetRandom(CryptPillar2, rndper);\r\n\tPlaceMiniSetRandom(CryptPillar3, rndper);\r\n\tPlaceMiniSetRandom(CryptPillar4, rndper);\r\n\tPlaceMiniSetRandom(CryptPillar5, rndper);\r\n\tPlaceMiniSetRandom(CryptStar, rndper);\r\n\r\n\tfor (const ReplaceTile pair : Substition1Floor) {\r\n\t\tPlaceMiniSetRandom1x1(pair.search, pair.replace, rndper);\r\n\t}\r\n}\r\n\r\nvoid CryptFloor(int rndper)\r\n{\r\n\tfor (const ReplaceTile pair : Substition2Floor) {\r\n\t\tPlaceMiniSetRandom1x1(pair.search, pair.replace, rndper);\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InitCryptPieces()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 76) {\r\n\t\t\t\tdSpecial[i][j] = 1;\r\n\t\t\t} else if (dPiece[i][j] == 79) {\r\n\t\t\t\tdSpecial[i][j] = 2;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SetCryptRoom()\r\n{\r\n\tconst Point position = SelectChamber();\r\n\r\n\tUberRow = 2 * position.x + 6;\r\n\tUberCol = 2 * position.y + 8;\r\n\tIsUberRoomOpened = false;\r\n\tIsUberLeverActivated = false;\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(\"nlevels\\\\l5data\\\\uberroom.dun\");\r\n\r\n\tSetPiece = { position, GetDunSize(dunData.get()) };\r\n\r\n\tPlaceDunTiles(dunData.get(), position, 0);\r\n}\r\n\r\nvoid SetCornerRoom()\r\n{\r\n\tconst Point position = SelectChamber();\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(\"nlevels\\\\l5data\\\\cornerstone.dun\");\r\n\r\n\tSetPiece = { position, GetDunSize(dunData.get()) };\r\n\r\n\tPlaceDunTiles(dunData.get(), position, 0);\r\n}\r\n\r\nvoid FixCryptDirtTiles()\r\n{\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\t\tif (dungeon[i][j] == DirtVwall)\r\n\t\t\t\tdungeon[i][j] = DirtVWall2;\r\n\t\t\tif (dungeon[i][j] == DirtCorner)\r\n\t\t\t\tdungeon[i][j] = DirtCorner2;\r\n\t\t\tif (dungeon[i][j] == DirtHWallEnd)\r\n\t\t\t\tdungeon[i][j] = DirtHWallEnd2;\r\n\t\t\tif (dungeon[i][j] == DirtVWallEnd)\r\n\t\t\t\tdungeon[i][j] = DirtVWallEnd2;\r\n\t\t\tif (dungeon[i][j] == DirtHwall)\r\n\t\t\t\tdungeon[i][j] = DirtHWall2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool PlaceCryptStairs(lvl_entry entry)\r\n{\r\n\tbool success = true;\r\n\tstd::optional<Point> position;\r\n\r\n\t// Place stairs up\r\n\tposition = PlaceMiniSet(currlevel != 21 ? L5STAIRSUPHF : L5STAIRSTOWN, DMAXX * DMAXY, true);\r\n\tif (!position) {\r\n\t\tsuccess = false;\r\n\t} else if (entry == ENTRY_MAIN || entry == ENTRY_TWARPDN) {\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 3, 5 };\r\n\t}\r\n\r\n\t// Place stairs down\r\n\tif (currlevel != 24) {\r\n\t\tposition = PlaceMiniSet(L5STAIRSDOWN, DMAXX * DMAXY, true);\r\n\t\tif (!position)\r\n\t\t\tsuccess = false;\r\n\t\telse if (entry == ENTRY_PREV)\r\n\t\t\tViewPosition = position->megaToWorld() + Displacement { 3, 7 };\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\nvoid CryptSubstitution()\r\n{\r\n\tfor (const ReplaceTile pair : Statues) {\r\n\t\tPlaceMiniSetRandom1x1(pair.search, pair.replace, 10);\r\n\t}\r\n\tPlaceMiniSetRandom1x1(VArch, VArch5, 95);\r\n\tPlaceMiniSetRandom1x1(HArch, HArch5, 95);\r\n\tPlaceMiniSetRandom(VWallSection, 100);\r\n\tPlaceMiniSetRandom(HWallSection, 100);\r\n\tPlaceMiniSetRandom(CryptFloorLave, 60);\r\n\tApplyCryptShadowsPatterns();\r\n\tswitch (currlevel) {\r\n\tcase 21:\r\n\t\tCryptCracked(30);\r\n\t\tCryptBroken(15);\r\n\t\tCryptLeaking(5);\r\n\t\tApplyCryptShadowsPatterns();\r\n\t\tCryptFloor(10);\r\n\t\tCryptSubstitions1(5);\r\n\t\tCryptSubstitions2(20);\r\n\t\tbreak;\r\n\tcase 22:\r\n\t\tCryptFloor(10);\r\n\t\tCryptSubstitions1(10);\r\n\t\tCryptSubstitions2(20);\r\n\t\tCryptCracked(30);\r\n\t\tCryptBroken(20);\r\n\t\tCryptLeaking(10);\r\n\t\tApplyCryptShadowsPatterns();\r\n\t\tbreak;\r\n\tcase 23:\r\n\t\tCryptFloor(10);\r\n\t\tCryptSubstitions1(15);\r\n\t\tCryptSubstitions2(30);\r\n\t\tCryptCracked(30);\r\n\t\tCryptBroken(20);\r\n\t\tCryptLeaking(15);\r\n\t\tApplyCryptShadowsPatterns();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tCryptFloor(10);\r\n\t\tCryptSubstitions1(20);\r\n\t\tCryptSubstitions2(30);\r\n\t\tCryptCracked(30);\r\n\t\tCryptBroken(20);\r\n\t\tCryptLeaking(20);\r\n\t\tApplyCryptShadowsPatterns();\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid SetCryptSetPieceRoom()\r\n{\r\n\tfor (int j = dminPosition.y; j < dmaxPosition.y; j++) {\r\n\t\tfor (int i = dminPosition.x; i < dmaxPosition.x; i++) {\r\n\t\t\tif (dPiece[i][j] == 289) {\r\n\t\t\t\tUberRow = i;\r\n\t\t\t\tUberCol = j;\r\n\t\t\t}\r\n\t\t\tif (dPiece[i][j] == 316) {\r\n\t\t\t\tCornerStone.position = { i, j };\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlaceCryptLights()\r\n{\r\n\tconstexpr int lavaTiles[] = {\r\n\t\t124, 128, 130, 132, 133, 134, 135, 139, 141, 143, 145, 156, 164, 166,\r\n\t\t167, 168, 169, 170, 182, 190, 192, 195, 196, 199, 200, 254, 266, 273,\r\n\t\t276, 281, 282, 283, 284, 285, 286, 287, 288, 290, 302, 316, 434, 435,\r\n\t\t436, 437, 445, 446, 447, 453, 457, 460, 466, 470, 477, 479, 484, 485,\r\n\t\t486, 490, 507, 537, 557, 559, 561, 563, 564, 568, 569, 572, 578, 580,\r\n\t\t584, 585, 589, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601\r\n\t};\r\n\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tfor (const int lavaTile : lavaTiles) {\r\n\t\t\t\tif (dPiece[i][j] == lavaTile) {\r\n\t\t\t\t\tDoLighting({ i, j }, 3, {});\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/crypt.h",
    "content": "/**\r\n * @file levels/crypt.h\r\n *\r\n * Interface of the cathedral level generation algorithms.\r\n */\r\n#pragma once\r\n\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern int UberRow;\r\nextern int UberCol;\r\nextern bool IsUberRoomOpened;\r\nextern bool IsUberLeverActivated;\r\nextern int UberDiabloMonsterIndex;\r\n\r\nextern const Miniset L5STAIRSUP;\r\n\r\nvoid InitCryptPieces();\r\nvoid SetCryptRoom();\r\nvoid SetCornerRoom();\r\nvoid FixCryptDirtTiles();\r\nbool PlaceCryptStairs(lvl_entry entry);\r\nvoid CryptSubstitution();\r\nvoid SetCryptSetPieceRoom();\r\nvoid PlaceCryptLights();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l1.cpp",
    "content": "#include \"levels/drlg_l1.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"levels/crypt.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"utils/bitset2d.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n/** Marks where walls may not be added to the level */\r\nBitset2d<DMAXX, DMAXY> Chamber;\r\n/** Specifies whether to generate a horizontal or vertical layout. */\r\nbool VerticalLayout;\r\n/** Specifies whether to generate a room at position 1 in the Cathedral. */\r\nbool HasChamber1;\r\n/** Specifies whether to generate a room at position 2 in the Cathedral. */\r\nbool HasChamber2;\r\n/** Specifies whether to generate a room at position 3 in the Cathedral. */\r\nbool HasChamber3;\r\n\r\n/** Miniset: stairs up on a corner wall. */\r\nconst Miniset STAIRSUP {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 2, 2, 2, 2 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 66, 6, 0 },\r\n\t    { 63, 64, 65, 0 },\r\n\t    { 0, 67, 68, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: stairs down. */\r\nconst Miniset STAIRSDOWN {\r\n\t{ 4, 3 },\r\n\t{\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 62, 57, 58, 0 },\r\n\t    { 61, 59, 60, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: candlestick. */\r\nconst Miniset LAMPS {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 13, 0 },\r\n\t    { 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 129, 0 },\r\n\t    { 130, 128 },\r\n\t}\r\n};\r\n/** Miniset: Poisoned Water Supply entrance. */\r\nconst Miniset PWATERIN {\r\n\t{ 6, 6 },\r\n\t{\r\n\t    { 13, 13, 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13, 13, 13 },\r\n\t    { 13, 13, 13, 13, 13, 13 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0, 0, 0 },\r\n\t    { 0, 202, 200, 200, 84, 0 },\r\n\t    { 0, 199, 203, 203, 83, 0 },\r\n\t    { 0, 85, 206, 80, 81, 0 },\r\n\t    { 0, 0, 134, 135, 0, 0 },\r\n\t    { 0, 0, 0, 0, 0, 0 },\r\n\t}\r\n};\r\n\r\nenum Tile : uint8_t {\r\n\t// clang-format off\r\n\tVWall          =   1,\r\n\tHWall          =   2,\r\n\tCorner         =   3,\r\n\tDWall          =   4,\r\n\tDArch          =   5,\r\n\tVWallEnd       =   6,\r\n\tHWallEnd       =   7,\r\n\tHArchEnd       =   8,\r\n\tVArchEnd       =   9,\r\n\tHArchVWall     =  10,\r\n\tVArch          =  11,\r\n\tHArch          =  12,\r\n\tFloor          =  13,\r\n\tHWallVArch     =  14,\r\n\tPillar         =  15,\r\n\tVCorner        =  16,\r\n\tHCorner        =  17,\r\n\tDirtHwall      =  18,\r\n\tDirtVwall      =  19,\r\n\tVDirtCorner    =  20,\r\n\tHDirtCorner    =  21,\r\n\tDirt           =  22,\r\n\tDirtHwallEnd   =  23,\r\n\tDirtVwallEnd   =  24,\r\n\tVDoor          =  25,\r\n\tHDoor          =  26,\r\n\tHFenceVWall    =  27,\r\n\tHDoorVDoor     =  28,\r\n\tDFence         =  29,\r\n\tVDoorEnd       =  30,\r\n\tHDoorEnd       =  31,\r\n\tVFenceEnd      =  32,\r\n\tVArchEnd2      =  33,\r\n\tHArchVWall2    =  34,\r\n\tVFence         =  35,\r\n\tHFence         =  36,\r\n\tHWallVFence    =  37,\r\n\tHArchVFence    =  38,\r\n\tHArchVDoor     =  39,\r\n\tHArchVWall3    =  40,\r\n\tDWall2         =  41,\r\n\tHWallVArch2    =  42,\r\n\tDWall3         =  43,\r\n\tEntranceStairs =  64,\r\n\tVWall2         =  79,\r\n\tHWall2         =  80,\r\n\tDWall4         =  82,\r\n\tVWallEnd2      =  84,\r\n\tVWall4         =  89,\r\n\tVWall5         =  90,\r\n\tHWall4         =  91,\r\n\tHWall5         =  92,\r\n\tVWall8         = 100,\r\n\tFloor12        = 139,\r\n\tFloor13        = 140,\r\n\tFloor14        = 141,\r\n\tFloor15        = 142,\r\n\tFloor16        = 143,\r\n\tFloor17        = 144,\r\n\tFloor18        = 145,\r\n\tVWall17        = 146,\r\n\tVArch5         = 147,\r\n\tHWallShadow    = 148,\r\n\tHArchShadow    = 149,\r\n\tFloor19        = 150,\r\n\tFloor20        = 151,\r\n\tFloor21        = 152,\r\n\tHArchShadow2   = 153,\r\n\tHWallShadow2   = 154,\r\n\tFloor22        = 162,\r\n\tFloor23        = 163,\r\n\tDirtHWall2     = 199,\r\n\tDirtVWall2     = 200,\r\n\tDirtCorner2    = 202,\r\n\tDirtHWallEnd2  = 204,\r\n\tDirtVWallEnd2  = 205,\r\n\t// clang-format on\r\n};\r\n\r\n/** Contains shadows for 2x2 blocks of base tile IDs in the Cathedral. */\r\nconst ShadowStruct ShadowPatterns[37] = {\r\n\t// clang-format off\r\n\t// strig,     s1,    s2,    s3,    nv1,         nv2,     nv3\r\n\t{ HWallEnd,   Floor, 0,     Floor, Floor17,     0,       Floor15     },\r\n\t{ VCorner,    Floor, 0,     Floor, Floor17,     0,       Floor15     },\r\n\t{ Pillar,     Floor, 0,     Floor, Floor18,     0,       Floor15     },\r\n\t{ DArch,      Floor, Floor, Floor, Floor21,     Floor13, Floor12     },\r\n\t{ DArch,      Floor, VWall, Floor, Floor16,     VWall17, Floor12     },\r\n\t{ DArch,      Floor, Floor, HWall, Floor16,     Floor13, HWallShadow },\r\n\t{ DArch,      0,     VWall, HWall, 0,           VWall17, HWallShadow },\r\n\t{ DArch,      Floor, VArch, Floor, Floor16,     VArch5,  Floor12     },\r\n\t{ DArch,      Floor, Floor, HArch, Floor16,     Floor13, HArchShadow },\r\n\t{ DArch,      Floor, VArch, HArch, Floor19,     VArch5,  HArchShadow },\r\n\t{ DArch,      Floor, VWall, HArch, Floor16,     VWall17, HArchShadow },\r\n\t{ DArch,      Floor, VArch, HWall, Floor16,     VArch5,  HWallShadow },\r\n\t{ VArchEnd,   Floor, Floor, Floor, Floor17,     Floor13, Floor15     },\r\n\t{ VArchEnd,   Floor, VWall, Floor, Floor17,     VWall17, Floor15     },\r\n\t{ VArchEnd,   Floor, VArch, Floor, Floor20,     VArch5,  Floor15     },\r\n\t{ HArchEnd,   Floor, 0,     Floor, Floor17,     0,       Floor12     },\r\n\t{ HArchEnd,   Floor, 0,     HArch, Floor16,     0,       HArchShadow },\r\n\t{ HArchEnd,   0,     0,     HWall, 0,           0,       HWallShadow },\r\n\t{ VArch,      0,     0,     Floor, 0,           0,       Floor12     },\r\n\t{ VArch,      Floor, 0,     Floor, Floor12,     0,       Floor12     },\r\n\t{ VArch,      HWall, 0,     Floor, HWallShadow, 0,       Floor12     },\r\n\t{ VArch,      HArch, 0,     Floor, HArchShadow, 0,       Floor12     },\r\n\t{ VArch,      Floor, VArch, HArch, Floor12,     0,       HArchShadow },\r\n\t{ HWallVArch, 0,     0,     Floor, 0,           0,       Floor12     },\r\n\t{ HWallVArch, Floor, 0,     Floor, Floor12,     0,       Floor12     },\r\n\t{ HWallVArch, HWall, 0,     Floor, HWallShadow, 0,       Floor12     },\r\n\t{ HWallVArch, HArch, 0,     Floor, HArchShadow, 0,       Floor12     },\r\n\t{ HWallVArch, Floor, VArch, HArch, Floor12,     0,       HArchShadow },\r\n\t{ HArchVWall, 0,     Floor, 0,     0,           Floor13, 0           },\r\n\t{ HArchVWall, Floor, Floor, 0,     Floor13,     Floor13, 0           },\r\n\t{ HArchVWall, 0,     VWall, 0,     0,           VWall17, 0           },\r\n\t{ HArchVWall, Floor, VArch, 0,     Floor13,     VArch5,  0           },\r\n\t{ HArch,      0,     Floor, 0,     0,           Floor13, 0           },\r\n\t{ HArch,      Floor, Floor, 0,     Floor13,     Floor13, 0           },\r\n\t{ HArch,      0,     VWall, 0,     0,           VWall17, 0           },\r\n\t{ HArch,      Floor, VArch, 0,     Floor13,     VArch5,  0           },\r\n\t{ Corner,     Floor, VArch, HArch, Floor19,     0,       0           }\r\n\t// clang-format on\r\n};\r\n\r\n/** Maps tile IDs to their corresponding base tile ID. */\r\nconst uint8_t BaseTypes[207] = {\r\n\t0,\r\n\tVWall, HWall, Corner, DWall, DArch, VWallEnd, HWallEnd, HArchEnd, VArchEnd,\r\n\tHArchVWall, VArch, HArch, Floor, HWallVArch, Pillar, VCorner, HCorner,\r\n\t0, 0, 0, 0, 0, 0, 0,\r\n\tVWall, HWall, HArchVWall, DWall, DArch, VWallEnd, HWallEnd, HArchEnd,\r\n\tVArchEnd, HArchVWall, VArch, HArch, HWallVArch, DArch, HWallVArch,\r\n\tHArchVWall, DWall, HWallVArch, DWall, DArch,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\tVWall, HWall, Corner, DWall, VWall, VWallEnd, HWallEnd, VCorner, HCorner,\r\n\tHWall, VWall, VWall, HWall, HWall, VWall, VWall, HWall, HWall, HWall, HWall,\r\n\tHWall, VWall, VWall, VArch, VWall, Floor, Floor, Floor, VWall, HWall, VWall,\r\n\tHWall, VWall, HWall, VWall, HWall, HWall, HWall, HWall, HArch,\r\n\t0, 0,\r\n\tVArch, VWall, VArch, VWall, Floor,\r\n\t0, 0, 0, 0, 0, 0, 0,\r\n\tFloor, Floor, Floor, Floor, Floor, Floor, Floor, Floor, Floor, Floor, Floor,\r\n\tFloor, Floor, VWall, VArch, HWall, HArch, Floor, Floor, Floor, HArch, HWall,\r\n\tVWall, HWall, HWall, DWall, HWallVArch, DWall, HArchVWall, Floor, Floor,\r\n\tDWall, DWall, VWall, VWall, DWall, HWall, HWall, Floor, Floor, Floor, Floor,\r\n\tVDoor, HDoor, HDoorVDoor, VDoorEnd, HDoorEnd, DWall2, DWall3, HArchVWall3,\r\n\tDWall2, HWallVArch2, DWall3, VDoor, DWall2, DWall3, HDoorVDoor, HDoorVDoor,\r\n\tVWall, HWall, VDoor, HDoor, Dirt, Dirt, VDoor, HDoor,\r\n\t0, 0, 0, 0, 0, 0, 0, 0\r\n};\r\n\r\n/** Maps tile IDs to their corresponding undecorated tile ID. */\r\nconst uint8_t TileDecorations[207] = {\r\n\t0,\r\n\tVWall, HWall, Corner, DWall, DArch, VWallEnd, HWallEnd, HArchEnd, VArchEnd,\r\n\tHArchVWall, VArch, HArch, Floor, HWallVArch, Pillar, VCorner, HCorner,\r\n\t0, 0, 0, 0, 0, 0, 0,\r\n\tVDoor, HDoor,\r\n\t0,\r\n\tHDoorVDoor,\r\n\t0,\r\n\tVDoorEnd, HDoorEnd,\r\n\t0, 0, 0, 0, 0, 0, 0, 0,\r\n\tHArchVWall3, DWall2, HWallVArch2, DWall3,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\tVWall2, HWall2,\r\n\t0,\r\n\tDWall4,\r\n\t0, 0, 0, 0, 0, 0,\r\n\tVWall2,\r\n\t0,\r\n\tHWall2,\r\n\t0, 0,\r\n\tVWall2, HWall2,\r\n\t0,\r\n\tHWall, HWall, HWall, VWall, VWall, VArch, VDoor, Floor, Floor, Floor, VWall,\r\n\tHWall, VWall, HWall, VWall, HWall, VWall, HWall, HWall, HWall, HWall, HArch,\r\n\t0, 0,\r\n\tVArch, VWall, VArch, VWall, Floor,\r\n\t0, 0, 0, 0, 0, 0, 0,\r\n\tFloor, Floor, Floor, Floor, Floor, Floor,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r\n};\r\n\r\nvoid ApplyShadowsPatterns()\r\n{\r\n\tuint8_t slice[2][2];\r\n\r\n\tfor (int y = 1; y < DMAXY; y++) {\r\n\t\tfor (int x = 1; x < DMAXX; x++) {\r\n\t\t\tslice[0][0] = BaseTypes[dungeon[x][y]];\r\n\t\t\tslice[1][0] = BaseTypes[dungeon[x - 1][y]];\r\n\t\t\tslice[0][1] = BaseTypes[dungeon[x][y - 1]];\r\n\t\t\tslice[1][1] = BaseTypes[dungeon[x - 1][y - 1]];\r\n\r\n\t\t\tfor (const auto &shadow : ShadowPatterns) {\r\n\t\t\t\tif (shadow.strig != slice[0][0])\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (shadow.s1 != 0 && shadow.s1 != slice[1][1])\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (shadow.s2 != 0 && shadow.s2 != slice[0][1])\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (shadow.s3 != 0 && shadow.s3 != slice[1][0])\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\tif (shadow.nv1 != 0 && !Protected.test(x - 1, y - 1)) {\r\n\t\t\t\t\tdungeon[x - 1][y - 1] = shadow.nv1;\r\n\t\t\t\t}\r\n\t\t\t\tif (shadow.nv2 != 0 && !Protected.test(x, y - 1)) {\r\n\t\t\t\t\tdungeon[x][y - 1] = shadow.nv2;\r\n\t\t\t\t}\r\n\t\t\t\tif (shadow.nv3 != 0 && !Protected.test(x - 1, y)) {\r\n\t\t\t\t\tdungeon[x - 1][y] = shadow.nv3;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int y = 1; y < DMAXY; y++) {\r\n\t\tfor (int x = 1; x < DMAXX; x++) {\r\n\t\t\tif (Protected.test(x - 1, y))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif (dungeon[x - 1][y] == Floor12) {\r\n\t\t\t\tTile tnv3 = Floor12;\r\n\t\t\t\tif (IsAnyOf(dungeon[x][y], DFence, VFenceEnd, VFence, HWallVFence, HArchVFence, HArchVDoor)) {\r\n\t\t\t\t\ttnv3 = Floor14;\r\n\t\t\t\t}\r\n\t\t\t\tdungeon[x - 1][y] = tnv3;\r\n\t\t\t}\r\n\t\t\tif (dungeon[x - 1][y] == HArchShadow) {\r\n\t\t\t\tTile tnv3 = HArchShadow;\r\n\t\t\t\tif (IsAnyOf(dungeon[x][y], DFence, VFenceEnd, VFence, HWallVFence, HArchVFence, HArchVDoor)) {\r\n\t\t\t\t\ttnv3 = HArchShadow2;\r\n\t\t\t\t}\r\n\t\t\t\tdungeon[x - 1][y] = tnv3;\r\n\t\t\t}\r\n\t\t\tif (dungeon[x - 1][y] == HWallShadow) {\r\n\t\t\t\tTile tnv3 = HWallShadow;\r\n\t\t\t\tif (IsAnyOf(dungeon[x][y], DFence, VFenceEnd, VFence, HWallVFence, HArchVFence, HArchVDoor)) {\r\n\t\t\t\t\ttnv3 = HWallShadow2;\r\n\t\t\t\t}\r\n\t\t\t\tdungeon[x - 1][y] = tnv3;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool CanReplaceTile(uint8_t replace, Point tile)\r\n{\r\n\tif (replace < VWallEnd2 || replace > VWall8) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// BUGFIX: p2 is a workaround for a bug, only p1 should have been used (fixing this breaks compatibility)\r\n\tconstexpr auto ComparisonWithBoundsCheck = [](Point p1, Point p2) {\r\n\t\treturn (p1.x >= 0 && p1.x < DMAXX && p1.y >= 0 && p1.y < DMAXY)\r\n\t\t    && (p2.x >= 0 && p2.x < DMAXX && p2.y >= 0 && p2.y < DMAXY)\r\n\t\t    && (dungeon[p1.x][p1.y] >= VWallEnd2 && dungeon[p2.x][p2.y] <= VWall8);\r\n\t};\r\n\tif (ComparisonWithBoundsCheck(tile + Direction::NorthWest, tile + Direction::NorthWest)\r\n\t    || ComparisonWithBoundsCheck(tile + Direction::SouthEast, tile + Direction::NorthWest)\r\n\t    || ComparisonWithBoundsCheck(tile + Direction::SouthWest, tile + Direction::NorthWest)\r\n\t    || ComparisonWithBoundsCheck(tile + Direction::NorthEast, tile + Direction::NorthWest)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid FillFloor()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] != Floor || Protected.test(i, j))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst int rv = RandomIntLessThan(3);\r\n\t\t\tif (rv == 1)\r\n\t\t\t\tdungeon[i][j] = Floor22;\r\n\t\t\telse if (rv == 2)\r\n\t\t\t\tdungeon[i][j] = Floor23;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitSetPiece()\r\n{\r\n\tstd::unique_ptr<uint16_t[]> setPieceData;\r\n\tif (Quests[Q_BUTCHER].IsAvailable()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l1data\\\\rnd6.dun\");\r\n\t} else if (Quests[Q_SKELKING].IsAvailable() && !UseMultiplayerQuests()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l1data\\\\skngdo.dun\");\r\n\t} else if (Quests[Q_LTBANNER].IsAvailable()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l1data\\\\banner2.dun\");\r\n\t} else {\r\n\t\treturn; // no setpiece needed for this level\r\n\t}\r\n\r\n\tconst WorldTilePosition setPiecePosition = SelectChamber();\r\n\tPlaceDunTiles(setPieceData.get(), setPiecePosition, Floor);\r\n\tSetPiece = { setPiecePosition, GetDunSize(setPieceData.get()) };\r\n}\r\n\r\nvoid InitDungeonPieces()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tint8_t pc;\r\n\t\t\tif (IsAnyOf(dPiece[i][j], 11, 70, 320, 210, 340, 417)) {\r\n\t\t\t\tpc = 1;\r\n\t\t\t} else if (IsAnyOf(dPiece[i][j], 10, 248, 324, 343, 330, 420)) {\r\n\t\t\t\tpc = 2;\r\n\t\t\t} else if (dPiece[i][j] == 252) {\r\n\t\t\t\tpc = 3;\r\n\t\t\t} else if (dPiece[i][j] == 254) {\r\n\t\t\t\tpc = 4;\r\n\t\t\t} else if (dPiece[i][j] == 258) {\r\n\t\t\t\tpc = 5;\r\n\t\t\t} else if (dPiece[i][j] == 266) {\r\n\t\t\t\tpc = 6;\r\n\t\t\t} else {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tdSpecial[i][j] = pc;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitDungeonFlags()\r\n{\r\n\tmemset(dungeon, Dirt, sizeof(dungeon));\r\n\tProtected.reset();\r\n\tChamber.reset();\r\n}\r\n\r\nvoid MapRoom(Rectangle room)\r\n{\r\n\tfor (int y = 0; y < room.size.height; y++) {\r\n\t\tfor (int x = 0; x < room.size.width; x++) {\r\n\t\t\tDungeonMask.set(room.position.x + x, room.position.y + y);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool CheckRoom(Rectangle room)\r\n{\r\n\tfor (int j = 0; j < room.size.height; j++) {\r\n\t\tfor (int i = 0; i < room.size.width; i++) {\r\n\t\t\tif (i + room.position.x < 0 || i + room.position.x >= DMAXX || j + room.position.y < 0 || j + room.position.y >= DMAXY) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tif (DungeonMask.test(i + room.position.x, j + room.position.y)) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid GenerateRoom(Rectangle area, bool verticalLayout)\r\n{\r\n\tconst bool rotate = FlipCoin(4);\r\n\tverticalLayout = (!verticalLayout && rotate) || (verticalLayout && !rotate);\r\n\r\n\tbool placeRoom1;\r\n\tRectangle room1;\r\n\r\n\tfor (int num = 0; num < 20; num++) {\r\n\t\tconst int32_t randomWidth = (GenerateRnd(5) + 2) & ~1;\r\n\t\tconst int32_t randomHeight = (GenerateRnd(5) + 2) & ~1;\r\n\t\troom1.size = { randomWidth, randomHeight };\r\n\t\troom1.position = area.position;\r\n\t\tif (verticalLayout) {\r\n\t\t\troom1.position += Displacement { -room1.size.width, area.size.height / 2 - room1.size.height / 2 };\r\n\t\t\tplaceRoom1 = CheckRoom({ room1.position + Displacement { -1, -1 }, { room1.size.height + 2, room1.size.width + 1 } }); /// BUGFIX: swap height and width ({ room1.size.width + 1, room1.size.height + 2 }) (workaround applied below)\r\n\t\t} else {\r\n\t\t\troom1.position += Displacement { area.size.width / 2 - room1.size.width / 2, -room1.size.height };\r\n\t\t\tplaceRoom1 = CheckRoom({ room1.position + Displacement { -1, -1 }, { room1.size.width + 2, room1.size.height + 1 } });\r\n\t\t}\r\n\t\tif (placeRoom1)\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (placeRoom1)\r\n\t\tMapRoom({ room1.position, { std::min(DMAXX - room1.position.x, room1.size.width), std::min(DMAXX - room1.position.y, room1.size.height) } });\r\n\r\n\tbool placeRoom2;\r\n\tRectangle room2 = room1;\r\n\tif (verticalLayout) {\r\n\t\troom2.position.x = area.position.x + area.size.width;\r\n\t\tplaceRoom2 = CheckRoom({ room2.position + Displacement { 0, -1 }, { room2.size.width + 1, room2.size.height + 2 } });\r\n\t} else {\r\n\t\troom2.position.y = area.position.y + area.size.height;\r\n\t\tplaceRoom2 = CheckRoom({ room2.position + Displacement { -1, 0 }, { room2.size.width + 2, room2.size.height + 1 } });\r\n\t}\r\n\r\n\tif (placeRoom2)\r\n\t\tMapRoom(room2);\r\n\tif (placeRoom1)\r\n\t\tGenerateRoom(room1, !verticalLayout);\r\n\tif (placeRoom2)\r\n\t\tGenerateRoom(room2, !verticalLayout);\r\n}\r\n\r\n/**\r\n * @brief Generate a boolean dungoen room layout\r\n */\r\nvoid FirstRoom()\r\n{\r\n\tDungeonMask.reset();\r\n\r\n\tVerticalLayout = FlipCoin();\r\n\tHasChamber1 = !FlipCoin();\r\n\tHasChamber2 = !FlipCoin();\r\n\tHasChamber3 = !FlipCoin();\r\n\r\n\tif (!HasChamber1 || !HasChamber3)\r\n\t\tHasChamber2 = true;\r\n\r\n\tRectangle chamber1 { { 1, 15 }, { 10, 10 } };\r\n\tconst Rectangle chamber2 { { 15, 15 }, { 10, 10 } };\r\n\tRectangle chamber3 { { 29, 15 }, { 10, 10 } };\r\n\tRectangle hallway { { 1, 17 }, { 38, 6 } };\r\n\tif (!HasChamber1) {\r\n\t\thallway.position.x += 17;\r\n\t\thallway.size.width -= 17;\r\n\t}\r\n\tif (!HasChamber3)\r\n\t\thallway.size.width -= 16;\r\n\tif (VerticalLayout) {\r\n\t\tstd::swap(chamber1.position.x, chamber1.position.y);\r\n\t\tstd::swap(chamber3.position.x, chamber3.position.y);\r\n\t\tstd::swap(hallway.position.x, hallway.position.y);\r\n\t\tstd::swap(hallway.size.width, hallway.size.height);\r\n\t}\r\n\r\n\tif (HasChamber1)\r\n\t\tMapRoom(chamber1);\r\n\tif (HasChamber2)\r\n\t\tMapRoom(chamber2);\r\n\tif (HasChamber3)\r\n\t\tMapRoom(chamber3);\r\n\r\n\tMapRoom(hallway);\r\n\r\n\tif (HasChamber1)\r\n\t\tGenerateRoom(chamber1, VerticalLayout);\r\n\tif (HasChamber2)\r\n\t\tGenerateRoom(chamber2, VerticalLayout);\r\n\tif (HasChamber3)\r\n\t\tGenerateRoom(chamber3, VerticalLayout);\r\n}\r\n\r\n/**\r\n * @brief Find the number of mega tiles used by layout\r\n */\r\ninline size_t FindArea()\r\n{\r\n\treturn DungeonMask.count();\r\n}\r\n\r\nvoid MakeDmt()\r\n{\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\t\tif (DungeonMask.test(i, j))\r\n\t\t\t\tdungeon[i][j] = Floor;\r\n\t\t\telse if (!DungeonMask.test(i + 1, j + 1) && DungeonMask.test(i, j + 1) && DungeonMask.test(i + 1, j))\r\n\t\t\t\tdungeon[i][j] = Floor; // Remove diagonal corners\r\n\t\t\telse if (DungeonMask.test(i + 1, j + 1) && DungeonMask.test(i, j + 1) && DungeonMask.test(i + 1, j))\r\n\t\t\t\tdungeon[i][j] = VCorner;\r\n\t\t\telse if (DungeonMask.test(i, j + 1))\r\n\t\t\t\tdungeon[i][j] = HWall;\r\n\t\t\telse if (DungeonMask.test(i + 1, j))\r\n\t\t\t\tdungeon[i][j] = VWall;\r\n\t\t\telse if (DungeonMask.test(i + 1, j + 1))\r\n\t\t\t\tdungeon[i][j] = DWall;\r\n\t\t\telse\r\n\t\t\t\tdungeon[i][j] = Dirt;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint HorizontalWallOk(Point position)\r\n{\r\n\tint length;\r\n\tfor (length = 1; dungeon[position.x + length][position.y] == Floor; length++) {\r\n\t\tif (dungeon[position.x + length][position.y - 1] != Floor || dungeon[position.x + length][position.y + 1] != Floor || Protected.test(position.x + length, position.y) || Chamber.test(position.x + length, position.y))\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (length == 1)\r\n\t\treturn -1;\r\n\r\n\tauto tileId = static_cast<Tile>(dungeon[position.x + length][position.y]);\r\n\r\n\tif (!IsAnyOf(tileId, Corner, DWall, DArch, VWallEnd, HWallEnd, VCorner, HCorner, DirtHwall, DirtVwall, VDirtCorner, HDirtCorner, DirtHwallEnd, DirtVwallEnd))\r\n\t\treturn -1;\r\n\r\n\treturn length;\r\n}\r\n\r\nint VerticalWallOk(Point position)\r\n{\r\n\tint length;\r\n\tfor (length = 1; dungeon[position.x][position.y + length] == Floor; length++) {\r\n\t\tif (dungeon[position.x - 1][position.y + length] != Floor || dungeon[position.x + 1][position.y + length] != Floor || Protected.test(position.x, position.y + length) || Chamber.test(position.x, position.y + length))\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (length == 1)\r\n\t\treturn -1;\r\n\r\n\tauto tileId = static_cast<Tile>(dungeon[position.x][position.y + length]);\r\n\r\n\tif (!IsAnyOf(tileId, Corner, DWall, DArch, VWallEnd, HWallEnd, VCorner, HCorner, DirtHwall, DirtVwall, VDirtCorner, HDirtCorner, DirtHwallEnd, DirtVwallEnd))\r\n\t\treturn -1;\r\n\r\n\treturn length;\r\n}\r\n\r\nvoid HorizontalWall(Point position, Tile start, int maxX)\r\n{\r\n\tTile wallTile = HWall;\r\n\tTile doorTile = HDoor;\r\n\r\n\tswitch (GenerateRnd(4)) {\r\n\tcase 2: // Add arch\r\n\t\twallTile = HArch;\r\n\t\tdoorTile = HArch;\r\n\t\tif (start == HWall)\r\n\t\t\tstart = HArch;\r\n\t\telse if (start == DWall)\r\n\t\t\tstart = HArchVWall;\r\n\t\tbreak;\r\n\tcase 3: // Add Fence\r\n\t\twallTile = HFence;\r\n\t\tif (start == HWall)\r\n\t\t\tstart = HFence;\r\n\t\telse if (start == DWall)\r\n\t\t\tstart = HFenceVWall;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (GenerateRnd(6) == 5)\r\n\t\tdoorTile = HArch;\r\n\r\n\tdungeon[position.x][position.y] = start;\r\n\r\n\tfor (int x = 1; x < maxX; x++) {\r\n\t\tdungeon[position.x + x][position.y] = wallTile;\r\n\t}\r\n\r\n\tconst int x = GenerateRnd(maxX - 1) + 1;\r\n\r\n\tdungeon[position.x + x][position.y] = doorTile;\r\n\tif (doorTile == HDoor) {\r\n\t\tProtected.set(position.x + x, position.y);\r\n\t}\r\n}\r\n\r\nvoid VerticalWall(Point position, Tile start, int maxY)\r\n{\r\n\tTile wallTile = VWall;\r\n\tTile doorTile = VDoor;\r\n\r\n\tswitch (GenerateRnd(4)) {\r\n\tcase 2: // Add arch\r\n\t\twallTile = VArch;\r\n\t\tdoorTile = VArch;\r\n\t\tif (start == VWall)\r\n\t\t\tstart = VArch;\r\n\t\telse if (start == DWall)\r\n\t\t\tstart = HWallVArch;\r\n\t\tbreak;\r\n\tcase 3: // Add Fence\r\n\t\twallTile = VFence;\r\n\t\tif (start == VWall)\r\n\t\t\tstart = VFence;\r\n\t\telse if (start == DWall)\r\n\t\t\tstart = HWallVFence;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (GenerateRnd(6) == 5)\r\n\t\tdoorTile = VArch;\r\n\r\n\tdungeon[position.x][position.y] = start;\r\n\r\n\tfor (int y = 1; y < maxY; y++) {\r\n\t\tdungeon[position.x][position.y + y] = wallTile;\r\n\t}\r\n\r\n\tconst int y = GenerateRnd(maxY - 1) + 1;\r\n\r\n\tdungeon[position.x][position.y + y] = doorTile;\r\n\tif (doorTile == VDoor) {\r\n\t\tProtected.set(position.x, position.y + y);\r\n\t}\r\n}\r\n\r\nvoid AddWall()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (Protected.test(i, j) || Chamber.test(i, j))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif (dungeon[i][j] == Corner) {\r\n\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\tconst int maxX = HorizontalWallOk({ i, j });\r\n\t\t\t\tif (maxX != -1) {\r\n\t\t\t\t\tHorizontalWall({ i, j }, HWall, maxX);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == Corner) {\r\n\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\tconst int maxY = VerticalWallOk({ i, j });\r\n\t\t\t\tif (maxY != -1) {\r\n\t\t\t\t\tVerticalWall({ i, j }, VWall, maxY);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == VWallEnd) {\r\n\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\tconst int maxX = HorizontalWallOk({ i, j });\r\n\t\t\t\tif (maxX != -1) {\r\n\t\t\t\t\tHorizontalWall({ i, j }, DWall, maxX);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == HWallEnd) {\r\n\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\tconst int maxY = VerticalWallOk({ i, j });\r\n\t\t\t\tif (maxY != -1) {\r\n\t\t\t\t\tVerticalWall({ i, j }, DWall, maxY);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == HWall) {\r\n\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\tconst int maxX = HorizontalWallOk({ i, j });\r\n\t\t\t\tif (maxX != -1) {\r\n\t\t\t\t\tHorizontalWall({ i, j }, HWall, maxX);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == VWall) {\r\n\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\tconst int maxY = VerticalWallOk({ i, j });\r\n\t\t\t\tif (maxY != -1) {\r\n\t\t\t\t\tVerticalWall({ i, j }, VWall, maxY);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid GenerateChamber(Point position, bool connectPrevious, bool connectNext, bool verticalLayout)\r\n{\r\n\tif (connectPrevious) {\r\n\t\tif (verticalLayout) {\r\n\t\t\tdungeon[position.x + 2][position.y] = HArch;\r\n\t\t\tdungeon[position.x + 3][position.y] = HArch;\r\n\t\t\tdungeon[position.x + 4][position.y] = Corner;\r\n\t\t\tdungeon[position.x + 7][position.y] = VArchEnd;\r\n\t\t\tdungeon[position.x + 8][position.y] = HArch;\r\n\t\t\tdungeon[position.x + 9][position.y] = HWall;\r\n\t\t} else {\r\n\t\t\tdungeon[position.x][position.y + 2] = VArch;\r\n\t\t\tdungeon[position.x][position.y + 3] = VArch;\r\n\t\t\tdungeon[position.x][position.y + 4] = Corner;\r\n\t\t\tdungeon[position.x][position.y + 7] = HArchEnd;\r\n\t\t\tdungeon[position.x][position.y + 8] = VArch;\r\n\t\t\tdungeon[position.x][position.y + 9] = VWall;\r\n\t\t}\r\n\t}\r\n\tif (connectNext) {\r\n\t\tif (verticalLayout) {\r\n\t\t\tposition.y += 11;\r\n\t\t\tdungeon[position.x + 2][position.y] = HArchVWall;\r\n\t\t\tdungeon[position.x + 3][position.y] = HArch;\r\n\t\t\tdungeon[position.x + 4][position.y] = HArchEnd;\r\n\t\t\tdungeon[position.x + 7][position.y] = DArch;\r\n\t\t\tdungeon[position.x + 8][position.y] = HArch;\r\n\t\t\tif (dungeon[position.x + 9][position.y] != DWall)\r\n\t\t\t\tdungeon[position.x + 9][position.y] = HDirtCorner;\r\n\t\t\tposition.y -= 11;\r\n\t\t} else {\r\n\t\t\tposition.x += 11;\r\n\t\t\tdungeon[position.x][position.y + 2] = HWallVArch;\r\n\t\t\tdungeon[position.x][position.y + 3] = VArch;\r\n\t\t\tdungeon[position.x][position.y + 4] = VArchEnd;\r\n\t\t\tdungeon[position.x][position.y + 7] = DArch;\r\n\t\t\tdungeon[position.x][position.y + 8] = VArch;\r\n\t\t\tif (dungeon[position.x][position.y + 9] != DWall)\r\n\t\t\t\tdungeon[position.x][position.y + 9] = HDirtCorner;\r\n\t\t\tposition.x -= 11;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int y = 1; y < 11; y++) {\r\n\t\tfor (int x = 1; x < 11; x++) {\r\n\t\t\tdungeon[position.x + x][position.y + y] = Floor;\r\n\t\t\tChamber.set(position.x + x, position.y + y);\r\n\t\t}\r\n\t}\r\n\r\n\tdungeon[position.x + 4][position.y + 4] = Pillar;\r\n\tdungeon[position.x + 7][position.y + 4] = Pillar;\r\n\tdungeon[position.x + 4][position.y + 7] = Pillar;\r\n\tdungeon[position.x + 7][position.y + 7] = Pillar;\r\n}\r\n\r\nvoid GenerateHall(Point start, int length, bool verticalLayout)\r\n{\r\n\tif (verticalLayout) {\r\n\t\tfor (int i = start.y; i < start.y + length; i++) {\r\n\t\t\tdungeon[start.x][i] = VArch;\r\n\t\t\tdungeon[start.x + 3][i] = VArch;\r\n\t\t}\r\n\t} else {\r\n\t\tfor (int i = start.x; i < start.x + length; i++) {\r\n\t\t\tdungeon[i][start.y] = HArch;\r\n\t\t\tdungeon[i][start.y + 3] = HArch;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FixTilesPatterns()\r\n{\r\n\t// BUGFIX: Bounds checks are required in all loop bodies.\r\n\t// See https://github.com/diasurgical/devilutionX/pull/401\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (i + 1 < DMAXX) {\r\n\t\t\t\tif (dungeon[i][j] == HWall && dungeon[i + 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i + 1][j] = DirtHwallEnd;\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i + 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i + 1][j] = DirtHwall;\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i + 1][j] == HWall)\r\n\t\t\t\t\tdungeon[i + 1][j] = HWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i + 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i + 1][j] = DirtVwallEnd;\r\n\t\t\t}\r\n\t\t\tif (j + 1 < DMAXY) {\r\n\t\t\t\tif (dungeon[i][j] == VWall && dungeon[i][j + 1] == Dirt)\r\n\t\t\t\t\tdungeon[i][j + 1] = DirtVwallEnd;\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i][j + 1] == VWall)\r\n\t\t\t\t\tdungeon[i][j + 1] = VWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i][j + 1] == Dirt)\r\n\t\t\t\t\tdungeon[i][j + 1] = DirtVwall;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (i + 1 < DMAXX) {\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i + 1][j] == DirtVwall)\r\n\t\t\t\t\tdungeon[i + 1][j] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i + 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i + 1][j] = VDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == HWallEnd && dungeon[i + 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i + 1][j] = DirtHwallEnd;\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i + 1][j] == DirtVwallEnd)\r\n\t\t\t\t\tdungeon[i + 1][j] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == DirtVwall && dungeon[i + 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i + 1][j] = VDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == HWall && dungeon[i + 1][j] == DirtVwall)\r\n\t\t\t\t\tdungeon[i + 1][j] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == DirtVwall && dungeon[i + 1][j] == VWall)\r\n\t\t\t\t\tdungeon[i + 1][j] = VWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == HWallEnd && dungeon[i + 1][j] == DirtVwall)\r\n\t\t\t\t\tdungeon[i + 1][j] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == HWall && dungeon[i + 1][j] == VWall)\r\n\t\t\t\t\tdungeon[i + 1][j] = VWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == Corner && dungeon[i + 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i + 1][j] = DirtVwallEnd;\r\n\t\t\t\tif (dungeon[i][j] == HDirtCorner && dungeon[i + 1][j] == VWall)\r\n\t\t\t\t\tdungeon[i + 1][j] = VWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == HWallEnd && dungeon[i + 1][j] == VWall)\r\n\t\t\t\t\tdungeon[i + 1][j] = VWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == HWallEnd && dungeon[i + 1][j] == DirtVwallEnd)\r\n\t\t\t\t\tdungeon[i + 1][j] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == DWall && dungeon[i + 1][j] == VCorner)\r\n\t\t\t\t\tdungeon[i + 1][j] = HCorner;\r\n\t\t\t\tif (dungeon[i][j] == HWallEnd && dungeon[i + 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i + 1][j] = HCorner;\r\n\t\t\t\tif (dungeon[i][j] == HWall && dungeon[i + 1][j] == DirtVwallEnd)\r\n\t\t\t\t\tdungeon[i + 1][j] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == HWall && dungeon[i + 1][j] == Floor)\r\n\t\t\t\t\tdungeon[i + 1][j] = HCorner;\r\n\t\t\t}\r\n\t\t\tif (i > 0) {\r\n\t\t\t\tif (dungeon[i][j] == DirtHwallEnd && dungeon[i - 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i - 1][j] = DirtVwall;\r\n\t\t\t\tif (dungeon[i][j] == DirtVwall && dungeon[i - 1][j] == DirtHwallEnd)\r\n\t\t\t\t\tdungeon[i - 1][j] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i - 1][j] == Dirt)\r\n\t\t\t\t\tdungeon[i - 1][j] = DirtVwallEnd;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i - 1][j] == DirtHwallEnd)\r\n\t\t\t\t\tdungeon[i - 1][j] = HDirtCorner;\r\n\t\t\t}\r\n\t\t\tif (j + 1 < DMAXY) {\r\n\t\t\t\tif (dungeon[i][j] == VWall && dungeon[i][j + 1] == HWall)\r\n\t\t\t\t\tdungeon[i][j + 1] = HWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i][j + 1] == DirtHwall)\r\n\t\t\t\t\tdungeon[i][j + 1] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == DirtHwall && dungeon[i][j + 1] == HWall)\r\n\t\t\t\t\tdungeon[i][j + 1] = HWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i][j + 1] == HWall)\r\n\t\t\t\t\tdungeon[i][j + 1] = HWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == HDirtCorner && dungeon[i][j + 1] == HWall)\r\n\t\t\t\t\tdungeon[i][j + 1] = HWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i][j + 1] == Dirt)\r\n\t\t\t\t\tdungeon[i][j + 1] = DirtVwallEnd;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i][j + 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j + 1] = VCorner;\r\n\t\t\t\tif (dungeon[i][j] == VWall && dungeon[i][j + 1] == Floor)\r\n\t\t\t\t\tdungeon[i][j + 1] = VCorner;\r\n\t\t\t\tif (dungeon[i][j] == Floor && dungeon[i][j + 1] == VCorner)\r\n\t\t\t\t\tdungeon[i][j + 1] = HCorner;\r\n\t\t\t}\r\n\t\t\tif (j > 0) {\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i][j - 1] == Dirt)\r\n\t\t\t\t\tdungeon[i][j - 1] = HWallEnd;\r\n\t\t\t\tif (dungeon[i][j] == VWallEnd && dungeon[i][j - 1] == Dirt)\r\n\t\t\t\t\tdungeon[i][j - 1] = DirtVwallEnd;\r\n\t\t\t\tif (dungeon[i][j] == HWallEnd && dungeon[i][j - 1] == DirtVwallEnd)\r\n\t\t\t\t\tdungeon[i][j - 1] = HDirtCorner;\r\n\t\t\t\tif (dungeon[i][j] == DirtHwall && dungeon[i][j - 1] == DirtVwallEnd)\r\n\t\t\t\t\tdungeon[i][j - 1] = HDirtCorner;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (j + 1 < DMAXY && dungeon[i][j] == DWall && dungeon[i][j + 1] == HWall)\r\n\t\t\t\tdungeon[i][j + 1] = HWallEnd;\r\n\t\t\tif (i + 1 < DMAXX && dungeon[i][j] == HWall && dungeon[i + 1][j] == DirtVwall)\r\n\t\t\t\tdungeon[i + 1][j] = HDirtCorner;\r\n\t\t\tif (j + 1 < DMAXY && dungeon[i][j] == DirtHwall && dungeon[i][j + 1] == Dirt)\r\n\t\t\t\tdungeon[i][j + 1] = VDirtCorner;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Substitution()\r\n{\r\n\tfor (int y = 0; y < DMAXY; y++) {\r\n\t\tfor (int x = 0; x < DMAXX; x++) {\r\n\t\t\tif (FlipCoin(4)) {\r\n\t\t\t\tconst uint8_t c = TileDecorations[dungeon[x][y]];\r\n\t\t\t\tif (c != 0 && !Protected.test(x, y)) {\r\n\t\t\t\t\tint rv = GenerateRnd(16);\r\n\t\t\t\t\tint i = -1;\r\n\t\t\t\t\twhile (rv >= 0) {\r\n\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\tif (i == sizeof(TileDecorations)) {\r\n\t\t\t\t\t\t\ti = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (c == TileDecorations[i]) {\r\n\t\t\t\t\t\t\trv--;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// BUGFIX: Add `&& y > 0` to the if statement. (fixed)\r\n\t\t\t\t\tif (i == VWall4 && y > 0) {\r\n\t\t\t\t\t\tif (TileDecorations[dungeon[x][y - 1]] != VWall2 || Protected.test(x, y - 1))\r\n\t\t\t\t\t\t\ti = VWall2;\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\tdungeon[x][y - 1] = VWall5;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// BUGFIX: Add `&& x + 1 < DMAXX` to the if statement. (fixed)\r\n\t\t\t\t\tif (i == HWall4 && x + 1 < DMAXX) {\r\n\t\t\t\t\t\tif (TileDecorations[dungeon[x + 1][y]] != HWall2 || Protected.test(x + 1, y))\r\n\t\t\t\t\t\t\ti = HWall2;\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\tdungeon[x + 1][y] = HWall5;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdungeon[x][y] = i;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FillChambers()\r\n{\r\n\tPoint chamber1 { 0, 14 };\r\n\tPoint chamber3 { 28, 14 };\r\n\tPoint hall1 { 12, 18 };\r\n\tPoint hall2 { 26, 18 };\r\n\tif (VerticalLayout) {\r\n\t\tstd::swap(chamber1.x, chamber1.y);\r\n\t\tstd::swap(chamber3.x, chamber3.y);\r\n\t\tstd::swap(hall1.x, hall1.y);\r\n\t\tstd::swap(hall2.x, hall2.y);\r\n\t}\r\n\r\n\tif (HasChamber1)\r\n\t\tGenerateChamber(chamber1, false, true, VerticalLayout);\r\n\tif (HasChamber2)\r\n\t\tGenerateChamber({ 14, 14 }, HasChamber1, HasChamber3, VerticalLayout);\r\n\tif (HasChamber3)\r\n\t\tGenerateChamber(chamber3, true, false, VerticalLayout);\r\n\r\n\tif (HasChamber2) {\r\n\t\tif (HasChamber1)\r\n\t\t\tGenerateHall(hall1, 2, VerticalLayout);\r\n\t\tif (HasChamber3)\r\n\t\t\tGenerateHall(hall2, 2, VerticalLayout);\r\n\t} else {\r\n\t\tGenerateHall(hall1, 16, VerticalLayout);\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tif (currlevel == 24) {\r\n\t\t\tSetCryptRoom();\r\n\t\t} else if (CornerStone.isAvailable()) {\r\n\t\t\tSetCornerRoom();\r\n\t\t}\r\n\t} else {\r\n\t\tInitSetPiece();\r\n\t}\r\n}\r\n\r\nvoid FixTransparency()\r\n{\r\n\tint yy = 16;\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tint xx = 16;\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\t// BUGFIX: Should check for `j > 0` first. (fixed)\r\n\t\t\tif (dungeon[i][j] == DirtHwallEnd && j > 0 && dungeon[i][j - 1] == DirtHwall) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Should check for `i + 1 < DMAXY` first. (fixed)\r\n\t\t\tif (dungeon[i][j] == DirtVwallEnd && i + 1 < DMAXY && dungeon[i + 1][j] == DirtVwall) {\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtHwall) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtVwall) {\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == VDirtCorner) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\txx += 2;\r\n\t\t}\r\n\t\tyy += 2;\r\n\t}\r\n}\r\n\r\nvoid FixDirtTiles()\r\n{\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\t\tif (dungeon[i][j] == HDirtCorner && dungeon[i + 1][j] != DirtVwall) {\r\n\t\t\t\tdungeon[i][j] = DirtCorner2;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtVwall && dungeon[i + 1][j] != DirtVwall) {\r\n\t\t\t\tdungeon[i][j] = DirtVWall2;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtVwallEnd && dungeon[i + 1][j] != DirtVwall) {\r\n\t\t\t\tdungeon[i][j] = DirtVWallEnd2;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtHwall && dungeon[i][j + 1] != DirtHwall) {\r\n\t\t\t\tdungeon[i][j] = DirtHWall2;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == HDirtCorner && dungeon[i][j + 1] != DirtHwall) {\r\n\t\t\t\tdungeon[i][j] = DirtCorner2;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtHwallEnd && dungeon[i][j + 1] != DirtHwall) {\r\n\t\t\t\tdungeon[i][j] = DirtHWallEnd2;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FixCornerTiles()\r\n{\r\n\tfor (int j = 1; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 1; i < DMAXX - 1; i++) {\r\n\t\t\tif (!Protected.test(i, j) && dungeon[i][j] == HCorner && dungeon[i - 1][j] == Floor && dungeon[i][j - 1] == VWall) {\r\n\t\t\t\tdungeon[i][j] = VCorner;\r\n\t\t\t\t// BUGFIX: Set tile as Protected\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtCorner2 && dungeon[i + 1][j] == Floor && dungeon[i][j + 1] == VWall) {\r\n\t\t\t\tdungeon[i][j] = HArchEnd;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == DirtCorner2 && dungeon[i][j + 1] == Floor && dungeon[i + 1][j] == HWall) {\r\n\t\t\t\tdungeon[i][j] = VArchEnd;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool PlaceCathedralStairs(lvl_entry entry)\r\n{\r\n\tbool success = true;\r\n\tstd::optional<Point> position;\r\n\r\n\t// Place poison water entrance\r\n\tif (Quests[Q_PWATER].IsAvailable()) {\r\n\t\tposition = PlaceMiniSet(PWATERIN, DMAXX * DMAXY, true);\r\n\t\tif (!position) {\r\n\t\t\tsuccess = false;\r\n\t\t} else {\r\n\t\t\tconst int8_t t = TransVal;\r\n\t\t\tTransVal = 0;\r\n\t\t\tconst Point miniPosition = *position;\r\n\t\t\tDRLG_MRectTrans({ miniPosition + Displacement { 0, 2 }, { 5, 2 } });\r\n\t\t\tTransVal = t;\r\n\t\t\tQuests[Q_PWATER].position = miniPosition.megaToWorld() + Displacement { 5, 6 };\r\n\t\t\tif (entry == ENTRY_RTNLVL)\r\n\t\t\t\tViewPosition = Quests[Q_PWATER].position;\r\n\t\t}\r\n\t}\r\n\r\n\t// Place stairs up\r\n\tposition = PlaceMiniSet(MyPlayer->pOriginalCathedral && !Quests[Q_LTBANNER].IsAvailable() ? L5STAIRSUP : STAIRSUP, DMAXX * DMAXY, true);\r\n\tif (!position) {\r\n\t\tif (MyPlayer->pOriginalCathedral)\r\n\t\t\treturn false;\r\n\t\tsuccess = false;\r\n\t} else if (entry == ENTRY_MAIN) {\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 3, 4 };\r\n\t}\r\n\r\n\t// Place stairs down\r\n\tif (Quests[Q_LTBANNER].IsAvailable()) {\r\n\t\tif (entry == ENTRY_PREV)\r\n\t\t\tViewPosition = SetPiece.position.megaToWorld() + Displacement { 3, 11 };\r\n\t} else {\r\n\t\tposition = PlaceMiniSet(STAIRSDOWN, DMAXX * DMAXY, true);\r\n\t\tif (!position) {\r\n\t\t\tsuccess = false;\r\n\t\t} else if (entry == ENTRY_PREV) {\r\n\t\t\tViewPosition = position->megaToWorld() + Displacement { 3, 3 };\r\n\t\t}\r\n\t}\r\n\r\n\treturn success;\r\n}\r\n\r\nbool PlaceStairs(lvl_entry entry)\r\n{\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\treturn PlaceCryptStairs(entry);\r\n\t}\r\n\r\n\treturn PlaceCathedralStairs(entry);\r\n}\r\n\r\nvoid GenerateLevel(lvl_entry entry)\r\n{\r\n\tif (LevelSeeds[currlevel])\r\n\t\tSetRndSeed(*LevelSeeds[currlevel]);\r\n\r\n\tsize_t minarea = 761;\r\n\tswitch (currlevel) {\r\n\tcase 1:\r\n\t\tminarea = 533;\r\n\t\tbreak;\r\n\tcase 2:\r\n\t\tminarea = 693;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\twhile (true) {\r\n\t\tDRLG_InitTrans();\r\n\r\n\t\tdo {\r\n\t\t\tLevelSeeds[currlevel] = GetLCGEngineState();\r\n\t\t\tFirstRoom();\r\n\t\t} while (FindArea() < minarea);\r\n\r\n\t\tInitDungeonFlags();\r\n\t\tMakeDmt();\r\n\t\tFillChambers();\r\n\t\tFixTilesPatterns();\r\n\t\tAddWall();\r\n\t\tFloodTransparencyValues(13);\r\n\t\tif (PlaceStairs(entry))\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == EntranceStairs) {\r\n\t\t\t\tconst int xx = 2 * i + 16; /* todo: fix loop */\r\n\t\t\t\tconst int yy = 2 * j + 16;\r\n\t\t\t\tDRLG_CopyTrans(xx, yy + 1, xx, yy);\r\n\t\t\t\tDRLG_CopyTrans(xx + 1, yy + 1, xx + 1, yy);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tFixTransparency();\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tFixCryptDirtTiles();\r\n\t} else {\r\n\t\tFixDirtTiles();\r\n\t}\r\n\tFixCornerTiles();\r\n\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tCryptSubstitution();\r\n\t} else {\r\n\t\tSubstitution();\r\n\t\tApplyShadowsPatterns();\r\n\r\n\t\tconst int numt = GenerateRnd(5) + 5;\r\n\t\tfor (int i = 0; i < numt; i++) {\r\n\t\t\tPlaceMiniSet(LAMPS, DMAXX * DMAXY, true);\r\n\t\t}\r\n\r\n\t\tFillFloor();\r\n\t}\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n\r\n\tDRLG_CheckQuests(SetPiece.position);\r\n}\r\n\r\nvoid Pass3()\r\n{\r\n\tDRLG_LPass3(Dirt - 1);\r\n\r\n\tif (leveltype == DTYPE_CRYPT)\r\n\t\tInitCryptPieces();\r\n\telse\r\n\t\tInitDungeonPieces();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid PlaceMiniSetRandom(const Miniset &miniset, int rndper)\r\n{\r\n\tconst WorldTileCoord sw = miniset.size.width;\r\n\tconst WorldTileCoord sh = miniset.size.height;\r\n\r\n\tfor (WorldTileCoord sy = 0; sy < DMAXY - sh; sy++) {\r\n\t\tfor (WorldTileCoord sx = 0; sx < DMAXX - sw; sx++) {\r\n\t\t\tif (!miniset.matches({ sx, sy }, false))\r\n\t\t\t\tcontinue;\r\n\t\t\t// BUGFIX: This code is copied from Cave and should not be applied for crypt\r\n\t\t\tif (!CanReplaceTile(miniset.replace[0][0], { sx, sy }))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (GenerateRnd(100) >= rndper)\r\n\t\t\t\tcontinue;\r\n\t\t\tminiset.place({ sx, sy });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nWorldTilePosition SelectChamber()\r\n{\r\n\tint chamber;\r\n\tif (HasChamber1 && HasChamber2 && HasChamber3) {\r\n\t\tchamber = GenerateRnd(3) + 1;\r\n\t} else if (HasChamber1 && HasChamber2) {\r\n\t\tchamber = PickRandomlyAmong({ 2, 1 }); // Reverse order to match vanilla\r\n\t} else if (HasChamber1 && HasChamber3) {\r\n\t\tchamber = PickRandomlyAmong({ 3, 1 }); // Reverse order to match vanilla\r\n\t} else if (HasChamber2 && HasChamber3) {\r\n\t\tchamber = PickRandomlyAmong({ 2, 3 });\r\n\t} else {\r\n\t\t// The dungeon generation logic ensures that chamber 2 is available if\r\n\t\t// either (or both of) 1 or 3 aren't, so if we ever end up with a single\r\n\t\t// chamber layout it's always chamber 2.\r\n\t\tchamber = 2;\r\n\t}\r\n\r\n\tswitch (chamber) {\r\n\tcase 1:\r\n\t\treturn VerticalLayout ? WorldTilePosition { 16, 2 } : WorldTilePosition { 2, 16 };\r\n\tcase 3:\r\n\t\treturn VerticalLayout ? WorldTilePosition { 16, 30 } : WorldTilePosition { 30, 16 };\r\n\tdefault:\r\n\t\treturn { 16, 16 };\r\n\t}\r\n}\r\n\r\nvoid CreateL5Dungeon(uint32_t rseed, lvl_entry entry)\r\n{\r\n\tSetRndSeed(rseed);\r\n\r\n\tUberRow = 0;\r\n\tUberCol = 0;\r\n\r\n\tGenerateLevel(entry);\r\n\r\n\tPass3();\r\n\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tPlaceCryptLights();\r\n\t\tSetCryptSetPieceRoom();\r\n\t}\r\n}\r\n\r\nvoid LoadPreL1Dungeon(const char *path)\r\n{\r\n\tInitDungeonFlags();\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\tPlaceDunTiles(dunData.get(), { 0, 0 }, Floor);\r\n\r\n\tif (setlvltype == DTYPE_CATHEDRAL)\r\n\t\tFillFloor();\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n}\r\n\r\nvoid LoadL1Dungeon(const char *path, Point spawn)\r\n{\r\n\tLoadDungeonBase(path, spawn, Floor, Dirt);\r\n\r\n\tif (setlvltype == DTYPE_CATHEDRAL)\r\n\t\tFillFloor();\r\n\r\n\tPass3();\r\n\r\n\tif (setlvltype == DTYPE_CRYPT) {\r\n\t\tAddCryptObjects(0, 0, MAXDUNX, MAXDUNY);\r\n\t\tPlaceCryptLights();\r\n\t} else {\r\n\t\tAddL1Objs(0, 0, MAXDUNX, MAXDUNY);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l1.h",
    "content": "/**\r\n * @file levels/drlg_l1.h\r\n *\r\n * Interface of the cathedral level generation algorithms.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/world_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid PlaceMiniSetRandom(const Miniset &miniset, int rndper);\r\nWorldTilePosition SelectChamber();\r\nvoid CreateL5Dungeon(uint32_t rseed, lvl_entry entry);\r\nvoid LoadPreL1Dungeon(const char *path);\r\nvoid LoadL1Dungeon(const char *path, Point spawn);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l2.cpp",
    "content": "/**\r\n * @file levels/drlg_l2.cpp\r\n *\r\n * Implementation of the catacombs level generation algorithms.\r\n */\r\n#include \"levels/drlg_l2.h\"\r\n\r\n#include <algorithm>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <list>\r\n#include <optional>\r\n\r\n#include \"diablo.h\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nenum class HallDirection : int8_t {\r\n\tNone,\r\n\tUp,\r\n\tRight,\r\n\tDown,\r\n\tLeft,\r\n};\r\n\r\nstruct HallNode {\r\n\tWorldTilePosition beginning;\r\n\tWorldTilePosition end;\r\n\tHallDirection direction;\r\n};\r\n\r\nstruct RoomNode {\r\n\tWorldTilePosition topLeft;\r\n\tWorldTilePosition bottomRight;\r\n};\r\n\r\nint nRoomCnt;\r\nRoomNode RoomList[81];\r\nstd::list<HallNode> HallList;\r\n// An ASCII representation of the level\r\nchar predungeon[DMAXX][DMAXY];\r\n\r\nconst Displacement DirAdd[5] = {\r\n\t{ 0, 0 },\r\n\t{ 0, -1 },\r\n\t{ 1, 0 },\r\n\t{ 0, 1 },\r\n\t{ -1, 0 }\r\n};\r\nconst ShadowStruct SPATSL2[2] = { { 6, 3, 0, 3, 48, 0, 50 }, { 9, 3, 0, 3, 48, 0, 50 } };\r\n// short word_48489A = 0;\r\n\r\nconst uint8_t BTYPESL2[161] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 17, 18, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 2, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r\nconst uint8_t BSTYPESL2[161] = { 0, 1, 2, 3, 0, 0, 6, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 6, 6, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 2, 2, 0, 0, 0, 1, 1, 1, 1, 6, 2, 2, 2, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 2, 2, 3, 3, 3, 3, 1, 1, 2, 2, 3, 3, 3, 3, 1, 1, 3, 3, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r\n\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH1 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 7 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH2 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 8 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH3 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 6 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH4 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 9 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH5 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 14 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH6 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 13 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH7 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 16 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH8 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 1 },\r\n\t    { 3, 4 },\r\n\t    { 0, 15 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH9 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 7 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH10 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 8 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH11 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 6 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH12 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 9 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH13 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 14 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH14 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 13 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH15 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 16 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - corner. */\r\nconst Miniset VARCH16 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 15 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH17 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 7 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH18 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 8 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH19 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 6 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH20 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 9 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH21 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 14 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH22 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 13 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH23 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 16 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - open wall. */\r\nconst Miniset VARCH24 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 2, 7 },\r\n\t    { 3, 4 },\r\n\t    { 0, 15 },\r\n\t},\r\n\t{\r\n\t    { 141, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH25 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 7 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH26 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 8 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH27 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 6 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH28 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 9 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH29 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 14 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH30 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 13 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH31 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 16 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical. */\r\nconst Miniset VARCH32 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 3, 0 },\r\n\t    { 3, 4 },\r\n\t    { 3, 1 },\r\n\t    { 0, 15 },\r\n\t},\r\n\t{\r\n\t    { 48, 0 },\r\n\t    { 51, 39 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH33 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 7 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH34 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 8 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH35 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 6 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH36 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 9 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH37 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 14 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH38 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 13 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH39 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 16 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch vertical - room west entrance. */\r\nconst Miniset VARCH40 {\r\n\t{ 2, 4 },\r\n\t{\r\n\t    { 2, 0 },\r\n\t    { 3, 8 },\r\n\t    { 3, 4 },\r\n\t    { 0, 15 },\r\n\t},\r\n\t{\r\n\t    { 142, 0 },\r\n\t    { 51, 42 },\r\n\t    { 47, 44 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH1 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 9 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH2 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 6 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH3 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 8 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH4 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 7 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH5 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 15 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH6 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 16 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH7 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 13 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH8 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 2, 5, 14 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH9 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 9 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH10 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 6 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH11 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 8 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH12 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 7 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH13 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 15 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH14 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 16 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH15 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 13 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - north corner. */\r\nconst Miniset HARCH16 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 8, 5, 14 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH17 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 9 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH18 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 6 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH19 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 8 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH20 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 7 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH21 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 15 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH22 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 16 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH23 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 13 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - wall. */\r\nconst Miniset HARCH24 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 8, 5, 14 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 43, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH25 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 9 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH26 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 6 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH27 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 8 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH28 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 7 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH29 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 15 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH30 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 16 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH31 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 13 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal. */\r\nconst Miniset HARCH32 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 3, 3, 0 },\r\n\t    { 5, 2, 14 },\r\n\t},\r\n\t{\r\n\t    { 49, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH33 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 9 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH34 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 6 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH35 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 8 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH36 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 7 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH37 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 15 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH38 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 16 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH39 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 13 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Arch horizontal - west corner. */\r\nconst Miniset HARCH40 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 1, 3, 0 },\r\n\t    { 9, 5, 14 },\r\n\t},\r\n\t{\r\n\t    { 140, 46, 0 },\r\n\t    { 40, 45, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stairs up. */\r\nconst Miniset USTAIRS {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 0, 72, 77, 0 },\r\n\t    { 0, 76, 0, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stairs down. */\r\nconst Miniset DSTAIRS {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 0, 48, 71, 0 },\r\n\t    { 0, 50, 78, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stairs to town. */\r\nconst Miniset WARPSTAIRS {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 0, 158, 160, 0 },\r\n\t    { 0, 159, 0, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Crumbled south pillar. */\r\nconst Miniset CRUSHCOL {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 2, 6, 3 },\r\n\t    { 3, 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 83, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Vertical oil spill. */\r\nconst Miniset BIG1 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 3, 3 },\r\n\t    { 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 113, 0 },\r\n\t    { 112, 0 },\r\n\t}\r\n};\r\n/** Miniset: Horizontal oil spill. */\r\nconst Miniset BIG2 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 3, 3 },\r\n\t    { 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 114, 115 },\r\n\t    { 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Horizontal platform. */\r\nconst Miniset BIG3 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 1 },\r\n\t    { 1 },\r\n\t},\r\n\t{\r\n\t    { 117 },\r\n\t    { 116 },\r\n\t}\r\n};\r\n/** Miniset: Vertical platform. */\r\nconst Miniset BIG4 {\r\n\t{ 2, 1 },\r\n\t{\r\n\t    { 2, 2 },\r\n\t},\r\n\t{\r\n\t    { 118, 119 },\r\n\t}\r\n};\r\n/** Miniset: Large oil spill. */\r\nconst Miniset BIG5 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 3, 3 },\r\n\t    { 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 120, 122 },\r\n\t    { 121, 123 },\r\n\t}\r\n};\r\n/** Miniset: Vertical wall with debris. */\r\nconst Miniset BIG6 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 1 },\r\n\t    { 1 },\r\n\t},\r\n\t{\r\n\t    { 125 },\r\n\t    { 124 },\r\n\t}\r\n};\r\n/** Miniset: Horizontal wall with debris. */\r\nconst Miniset BIG7 {\r\n\t{ 2, 1 },\r\n\t{\r\n\t    { 2, 2 },\r\n\t},\r\n\t{\r\n\t    { 126, 127 },\r\n\t}\r\n};\r\n/** Miniset: Rock pile. */\r\nconst Miniset BIG8 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 3, 3 },\r\n\t    { 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 128, 130 },\r\n\t    { 129, 131 },\r\n\t}\r\n};\r\n/** Miniset: Vertical wall collapsed. */\r\nconst Miniset BIG9 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 1, 3 },\r\n\t    { 1, 3 },\r\n\t},\r\n\t{\r\n\t    { 133, 135 },\r\n\t    { 132, 134 },\r\n\t}\r\n};\r\n/** Miniset: Horizontal wall collapsed. */\r\nconst Miniset BIG10 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 2, 2 },\r\n\t    { 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 136, 137 },\r\n\t    { 3, 3 },\r\n\t}\r\n};\r\n/** Miniset: Bloody gib 1. */\r\nconst Miniset PANCREAS1 {\r\n\t{ 5, 3 },\r\n\t{\r\n\t    { 3, 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t    { 0, 0, 108, 0, 0 },\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Bloody gib 2. */\r\nconst Miniset PANCREAS2 {\r\n\t{ 5, 3 },\r\n\t{\r\n\t    { 3, 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3, 3 },\r\n\t    { 3, 3, 3, 3, 3 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t    { 0, 0, 110, 0, 0 },\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 1. */\r\nconst Miniset CTRDOOR1 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 9, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 2. */\r\nconst Miniset CTRDOOR2 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 8, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 3. */\r\nconst Miniset CTRDOOR3 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 6, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 4. */\r\nconst Miniset CTRDOOR4 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 7, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 5. */\r\nconst Miniset CTRDOOR5 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 15, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 6. */\r\nconst Miniset CTRDOOR6 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 13, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 7. */\r\nconst Miniset CTRDOOR7 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 16, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Move vertical doors away from west pillar 8. */\r\nconst Miniset CTRDOOR8 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 3, 1, 3 },\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 14, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 4, 0 },\r\n\t    { 0, 1, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n\r\nint Patterns[100][10] = {\r\n\t{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },\r\n\t{ 0, 0, 0, 0, 2, 0, 0, 0, 0, 3 },\r\n\t{ 0, 7, 0, 0, 1, 0, 0, 5, 0, 2 },\r\n\t{ 0, 5, 0, 0, 1, 0, 0, 7, 0, 2 },\r\n\t{ 0, 0, 0, 7, 1, 5, 0, 0, 0, 1 },\r\n\t{ 0, 0, 0, 5, 1, 7, 0, 0, 0, 1 },\r\n\t{ 0, 1, 0, 0, 3, 0, 0, 1, 0, 4 },\r\n\t{ 0, 0, 0, 1, 3, 1, 0, 0, 0, 5 },\r\n\t{ 0, 6, 0, 6, 1, 0, 0, 0, 0, 6 },\r\n\t{ 0, 6, 0, 0, 1, 6, 0, 0, 0, 9 },\r\n\t{ 0, 0, 0, 6, 1, 0, 0, 6, 0, 7 },\r\n\t{ 0, 0, 0, 0, 1, 6, 0, 6, 0, 8 },\r\n\t{ 0, 6, 0, 6, 6, 0, 8, 6, 0, 7 },\r\n\t{ 0, 6, 8, 6, 6, 6, 0, 0, 0, 9 },\r\n\t{ 0, 6, 0, 0, 6, 6, 0, 6, 8, 8 },\r\n\t{ 6, 6, 6, 6, 6, 6, 0, 6, 0, 8 },\r\n\t{ 2, 6, 6, 6, 6, 6, 0, 6, 0, 8 },\r\n\t{ 7, 7, 7, 6, 6, 6, 0, 6, 0, 8 },\r\n\t{ 6, 6, 2, 6, 6, 6, 0, 6, 0, 8 },\r\n\t{ 6, 2, 6, 6, 6, 6, 0, 6, 0, 8 },\r\n\t{ 2, 6, 6, 6, 6, 6, 0, 6, 0, 8 },\r\n\t{ 6, 7, 7, 6, 6, 6, 0, 6, 0, 8 },\r\n\t{ 4, 4, 6, 6, 6, 6, 2, 6, 2, 8 },\r\n\t{ 2, 2, 2, 2, 6, 2, 2, 6, 2, 7 },\r\n\t{ 2, 2, 2, 2, 6, 2, 6, 6, 6, 7 },\r\n\t{ 2, 2, 6, 2, 6, 6, 2, 2, 6, 9 },\r\n\t{ 2, 6, 2, 2, 6, 2, 2, 2, 2, 6 },\r\n\t{ 2, 2, 2, 2, 6, 6, 2, 2, 2, 9 },\r\n\t{ 2, 2, 2, 6, 6, 2, 2, 2, 2, 6 },\r\n\t{ 2, 2, 0, 2, 6, 6, 2, 2, 0, 9 },\r\n\t{ 0, 0, 0, 0, 4, 0, 0, 0, 0, 12 },\r\n\t{ 0, 1, 0, 0, 1, 4, 0, 1, 0, 10 },\r\n\t{ 0, 0, 0, 1, 1, 1, 0, 4, 0, 11 },\r\n\t{ 0, 0, 0, 6, 1, 4, 0, 1, 0, 14 },\r\n\t{ 0, 6, 0, 1, 1, 0, 0, 4, 0, 16 },\r\n\t{ 0, 6, 0, 0, 1, 1, 0, 4, 0, 15 },\r\n\t{ 0, 0, 0, 0, 1, 1, 0, 1, 4, 13 },\r\n\t{ 8, 8, 8, 8, 1, 1, 0, 1, 1, 13 },\r\n\t{ 8, 8, 4, 8, 1, 1, 0, 1, 1, 10 },\r\n\t{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 11 },\r\n\t{ 1, 1, 1, 1, 1, 1, 2, 2, 8, 2 },\r\n\t{ 0, 1, 0, 1, 1, 4, 1, 1, 0, 16 },\r\n\t{ 0, 0, 0, 1, 1, 1, 1, 1, 4, 11 },\r\n\t{ 1, 1, 4, 1, 1, 1, 0, 2, 2, 2 },\r\n\t{ 1, 1, 1, 1, 1, 1, 6, 2, 6, 2 },\r\n\t{ 4, 1, 1, 1, 1, 1, 6, 2, 6, 2 },\r\n\t{ 2, 2, 2, 1, 1, 1, 4, 1, 1, 11 },\r\n\t{ 4, 1, 1, 1, 1, 1, 2, 2, 2, 2 },\r\n\t{ 1, 1, 4, 1, 1, 1, 2, 2, 1, 2 },\r\n\t{ 4, 1, 1, 1, 1, 1, 1, 2, 2, 2 },\r\n\t{ 2, 2, 6, 1, 1, 1, 4, 1, 1, 11 },\r\n\t{ 4, 1, 1, 1, 1, 1, 2, 2, 6, 2 },\r\n\t{ 1, 2, 2, 1, 1, 1, 4, 1, 1, 11 },\r\n\t{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 10 },\r\n\t{ 2, 1, 1, 3, 1, 1, 2, 1, 1, 14 },\r\n\t{ 1, 1, 0, 1, 1, 2, 1, 1, 0, 1 },\r\n\t{ 0, 4, 0, 1, 1, 1, 0, 1, 1, 14 },\r\n\t{ 4, 1, 0, 1, 1, 0, 1, 1, 0, 1 },\r\n\t{ 0, 1, 0, 4, 1, 1, 0, 1, 1, 15 },\r\n\t{ 1, 1, 1, 1, 1, 1, 0, 2, 2, 2 },\r\n\t{ 0, 1, 1, 2, 1, 1, 2, 1, 4, 10 },\r\n\t{ 2, 1, 1, 1, 1, 1, 0, 4, 0, 16 },\r\n\t{ 1, 1, 4, 1, 1, 2, 0, 1, 2, 1 },\r\n\t{ 2, 1, 1, 2, 1, 1, 1, 1, 4, 10 },\r\n\t{ 1, 1, 2, 1, 1, 2, 4, 1, 8, 1 },\r\n\t{ 2, 1, 4, 1, 1, 1, 4, 4, 1, 16 },\r\n\t{ 2, 1, 1, 1, 1, 1, 1, 1, 1, 16 },\r\n\t{ 1, 1, 2, 1, 1, 1, 1, 1, 1, 15 },\r\n\t{ 1, 1, 1, 1, 1, 1, 2, 1, 1, 14 },\r\n\t{ 4, 1, 1, 1, 1, 1, 2, 1, 1, 14 },\r\n\t{ 1, 1, 1, 1, 1, 1, 1, 1, 2, 8 },\r\n\t{ 0, 0, 0, 0, 255, 0, 0, 0, 0, 0 },\r\n};\r\n\r\nvoid ApplyShadowsPatterns()\r\n{\r\n\tuint8_t sd[2][2];\r\n\r\n\tfor (int y = 1; y < DMAXY; y++) {\r\n\t\tfor (int x = 1; x < DMAXX; x++) {\r\n\t\t\tsd[0][0] = BSTYPESL2[dungeon[x][y]];\r\n\t\t\tsd[1][0] = BSTYPESL2[dungeon[x - 1][y]];\r\n\t\t\tsd[0][1] = BSTYPESL2[dungeon[x][y - 1]];\r\n\t\t\tsd[1][1] = BSTYPESL2[dungeon[x - 1][y - 1]];\r\n\r\n\t\t\tfor (const auto &shadow : SPATSL2) {\r\n\t\t\t\tif (shadow.strig != sd[0][0])\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (shadow.s1 != 0 && shadow.s1 != sd[1][1])\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (shadow.s2 != 0 && shadow.s2 != sd[0][1])\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (shadow.s3 != 0 && shadow.s3 != sd[1][0])\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\tif (shadow.nv1 != 0) {\r\n\t\t\t\t\tdungeon[x - 1][y - 1] = shadow.nv1;\r\n\t\t\t\t}\r\n\t\t\t\tif (shadow.nv2 != 0) {\r\n\t\t\t\t\tdungeon[x][y - 1] = shadow.nv2;\r\n\t\t\t\t}\r\n\t\t\t\tif (shadow.nv3 != 0) {\r\n\t\t\t\t\tdungeon[x - 1][y] = shadow.nv3;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlaceMiniSetRandom(const Miniset &miniset, int rndper)\r\n{\r\n\tconst WorldTileCoord sw = miniset.size.width;\r\n\tconst WorldTileCoord sh = miniset.size.height;\r\n\r\n\tfor (WorldTileCoord sy = 0; sy < DMAXY - sh; sy++) {\r\n\t\tfor (WorldTileCoord sx = 0; sx < DMAXX - sw; sx++) {\r\n\t\t\tif (SetPieceRoom.contains(sx, sy))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (!miniset.matches({ sx, sy }))\r\n\t\t\t\tcontinue;\r\n\t\t\tbool found = true;\r\n\t\t\tfor (int yy = std::max(sy - sh, 0); yy < std::min(sy + 2 * sh, DMAXY) && found; yy++) {\r\n\t\t\t\tfor (int xx = std::max(sx - sw, 0); xx < std::min(sx + 2 * sw, DMAXX); xx++) {\r\n\t\t\t\t\tif (dungeon[xx][yy] == miniset.replace[0][0]) {\r\n\t\t\t\t\t\tfound = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!found)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (GenerateRnd(100) >= rndper)\r\n\t\t\t\tcontinue;\r\n\t\t\tminiset.place({ sx, sy });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlaceMiniSetRandom1x1(uint8_t search, uint8_t replace, int rndper)\r\n{\r\n\tPlaceMiniSetRandom({ { 1, 1 }, { { search } }, { { replace } } }, rndper);\r\n}\r\n\r\nvoid InitSetPiece()\r\n{\r\n\tstd::unique_ptr<uint16_t[]> setPieceData;\r\n\r\n\tif (Quests[Q_BLIND].IsAvailable()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\blind1.dun\");\r\n\t} else if (Quests[Q_BLOOD].IsAvailable()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\blood1.dun\");\r\n\t} else if (Quests[Q_SCHAMB].IsAvailable()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\bonestr2.dun\");\r\n\t} else {\r\n\t\treturn; // no setpiece needed for this level\r\n\t}\r\n\r\n\tconst WorldTilePosition setPiecePosition = SetPieceRoom.position;\r\n\tPlaceDunTiles(setPieceData.get(), setPiecePosition, 3);\r\n\tSetPiece = { setPiecePosition, GetDunSize(setPieceData.get()) };\r\n}\r\n\r\nvoid InitDungeonPieces()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tint8_t pc;\r\n\t\t\tif (IsAnyOf(dPiece[i][j], 540, 177, 550)) {\r\n\t\t\t\tpc = 5;\r\n\t\t\t} else if (IsAnyOf(dPiece[i][j], 541, 552)) {\r\n\t\t\t\tpc = 6;\r\n\t\t\t} else {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tdSpecial[i][j] = pc;\r\n\t\t}\r\n\t}\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 131) {\r\n\t\t\t\tdSpecial[i][j + 1] = 2;\r\n\t\t\t\tdSpecial[i][j + 2] = 1;\r\n\t\t\t} else if (dPiece[i][j] == 134 || dPiece[i][j] == 138) {\r\n\t\t\t\tdSpecial[i + 1][j] = 3;\r\n\t\t\t\tdSpecial[i + 2][j] = 4;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitDungeonFlags()\r\n{\r\n\tProtected.reset();\r\n\tmemset(predungeon, ' ', sizeof(predungeon));\r\n}\r\n\r\nvoid MapRoom(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int jj = y1; jj <= y2; jj++) {\r\n\t\tfor (int ii = x1; ii <= x2; ii++) {\r\n\t\t\tpredungeon[ii][jj] = '.';\r\n\t\t}\r\n\t}\r\n\tfor (int jj = y1; jj <= y2; jj++) {\r\n\t\tpredungeon[x1][jj] = '#';\r\n\t\tpredungeon[x2][jj] = '#';\r\n\t}\r\n\tfor (int ii = x1; ii <= x2; ii++) {\r\n\t\tpredungeon[ii][y1] = '#';\r\n\t\tpredungeon[ii][y2] = '#';\r\n\t}\r\n}\r\n\r\nvoid DefineRoom(Point topLeft, Point bottomRight, bool forceHW)\r\n{\r\n\tpredungeon[topLeft.x][topLeft.y] = 'C';\r\n\tpredungeon[topLeft.x][bottomRight.y] = 'E';\r\n\tpredungeon[bottomRight.x][topLeft.y] = 'B';\r\n\tpredungeon[bottomRight.x][bottomRight.y] = 'A';\r\n\r\n\tnRoomCnt++;\r\n\tRoomList[nRoomCnt] = { topLeft, bottomRight };\r\n\r\n\tif (forceHW) {\r\n\t\tfor (int i = topLeft.x; i < bottomRight.x; i++) {\r\n\t\t\t/// BUGFIX: Should loop j between nY1 and nY2 instead of always using nY1.\r\n\t\t\twhile (i < bottomRight.y) {\r\n\t\t\t\tProtected.set(i, topLeft.y);\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int i = topLeft.x + 1; i <= bottomRight.x - 1; i++) {\r\n\t\tpredungeon[i][topLeft.y] = '#';\r\n\t\tpredungeon[i][bottomRight.y] = '#';\r\n\t}\r\n\tbottomRight.y--;\r\n\tfor (int j = topLeft.y + 1; j <= bottomRight.y; j++) {\r\n\t\tpredungeon[topLeft.x][j] = '#';\r\n\t\tpredungeon[bottomRight.x][j] = '#';\r\n\t\tfor (int i = topLeft.x + 1; i < bottomRight.x; i++) {\r\n\t\t\tpredungeon[i][j] = '.';\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CreateDoorType(Point position)\r\n{\r\n\tif (predungeon[position.x - 1][position.y] == 'D')\r\n\t\treturn;\r\n\tif (predungeon[position.x + 1][position.y] == 'D')\r\n\t\treturn;\r\n\tif (predungeon[position.x][position.y - 1] == 'D')\r\n\t\treturn;\r\n\tif (predungeon[position.x][position.y + 1] == 'D')\r\n\t\treturn;\r\n\tif (IsAnyOf(predungeon[position.x][position.y], 'A', 'B', 'C', 'E'))\r\n\t\treturn;\r\n\r\n\tpredungeon[position.x][position.y] = 'D';\r\n}\r\n\r\nvoid PlaceHallExt(Point position)\r\n{\r\n\tif (predungeon[position.x][position.y] == ' ')\r\n\t\tpredungeon[position.x][position.y] = ',';\r\n}\r\n\r\n/**\r\n * Draws a random room rectangle, and then subdivides the rest of the passed in rectangle into 4 and recurses.\r\n * @param topLeft Lower X and Y boundaries of the area to draw into.\r\n * @param bottomRight Upper X and Y boundaries of the area to draw into.\r\n * @param nRDest The room number of the parent room this call was invoked for. Zero for empty\r\n * @param nHDir The direction of the hall from nRDest to this room.\r\n * @param size If set, is is used used for room size instead of random values.\r\n */\r\nvoid CreateRoom(WorldTilePosition topLeft, WorldTilePosition bottomRight, int nRDest, HallDirection nHDir, std::optional<WorldTileSize> size)\r\n{\r\n\tconstexpr int AreaMin = 2;\r\n\tif (nRoomCnt >= 80 || topLeft.x + AreaMin > bottomRight.x || topLeft.y + AreaMin > bottomRight.y)\r\n\t\treturn;\r\n\r\n\tconst WorldTileDisplacement areaDisplacement = bottomRight - topLeft;\r\n\tconst WorldTileSize area(areaDisplacement.deltaX, areaDisplacement.deltaY);\r\n\r\n\tconstexpr WorldTileCoord RoomMax = 10;\r\n\tconstexpr WorldTileCoord RoomMin = 4;\r\n\tWorldTileSize roomSize = area;\r\n\tif (area.width > RoomMin)\r\n\t\troomSize.width = GenerateRnd(std::min(area.width, RoomMax) - RoomMin) + RoomMin;\r\n\tif (area.height > RoomMin)\r\n\t\troomSize.height = GenerateRnd(std::min(area.height, RoomMax) - RoomMin) + RoomMin;\r\n\r\n\tif (size)\r\n\t\troomSize = *size;\r\n\r\n\tconst int32_t randomWidth = GenerateRnd(area.width);\r\n\tconst int32_t randomHeight = GenerateRnd(area.height);\r\n\r\n\tWorldTilePosition roomTopLeft = topLeft + WorldTileDisplacement(randomWidth, randomHeight);\r\n\tWorldTilePosition roomBottomRight = roomTopLeft + WorldTileDisplacement(roomSize);\r\n\tif (roomBottomRight.x > bottomRight.x) {\r\n\t\troomBottomRight.x = bottomRight.x;\r\n\t\troomTopLeft.x = bottomRight.x - roomSize.width;\r\n\t}\r\n\tif (roomBottomRight.y > bottomRight.y) {\r\n\t\troomBottomRight.y = bottomRight.y;\r\n\t\troomTopLeft.y = bottomRight.y - roomSize.height;\r\n\t}\r\n\r\n\troomTopLeft.x = std::clamp<WorldTileCoord>(roomTopLeft.x, 1, 38);\r\n\troomTopLeft.y = std::clamp<WorldTileCoord>(roomTopLeft.y, 1, 38);\r\n\troomBottomRight.x = std::clamp<WorldTileCoord>(roomBottomRight.x, 1, 38);\r\n\troomBottomRight.y = std::clamp<WorldTileCoord>(roomBottomRight.y, 1, 38);\r\n\r\n\tDefineRoom(roomTopLeft, roomBottomRight, static_cast<bool>(size));\r\n\r\n\tconstexpr WorldTileDisplacement standoff { 2, 2 };\r\n\tif (size)\r\n\t\tSetPieceRoom = { roomTopLeft + standoff, roomSize - 1 };\r\n\r\n\tconst int nRid = nRoomCnt;\r\n\r\n\tif (nRDest != 0) {\r\n\t\tWorldTileCoord nHx1 = 0;\r\n\t\tWorldTileCoord nHy1 = 0;\r\n\t\tWorldTileCoord nHx2 = 0;\r\n\t\tWorldTileCoord nHy2 = 0;\r\n\t\tif (nHDir == HallDirection::Up) {\r\n\t\t\tnHx1 = GenerateRnd(roomSize.width - 2) + roomTopLeft.x + 1;\r\n\t\t\tnHy1 = roomTopLeft.y;\r\n\t\t\tconst int nHw = RoomList[nRDest].bottomRight.x - RoomList[nRDest].topLeft.x - 2;\r\n\t\t\tnHx2 = GenerateRnd(nHw) + RoomList[nRDest].topLeft.x + 1;\r\n\t\t\tnHy2 = RoomList[nRDest].bottomRight.y;\r\n\t\t}\r\n\t\tif (nHDir == HallDirection::Down) {\r\n\t\t\tnHx1 = GenerateRnd(roomSize.width - 2) + roomTopLeft.x + 1;\r\n\t\t\tnHy1 = roomBottomRight.y;\r\n\t\t\tconst int nHw = RoomList[nRDest].bottomRight.x - RoomList[nRDest].topLeft.x - 2;\r\n\t\t\tnHx2 = GenerateRnd(nHw) + RoomList[nRDest].topLeft.x + 1;\r\n\t\t\tnHy2 = RoomList[nRDest].topLeft.y;\r\n\t\t}\r\n\t\tif (nHDir == HallDirection::Right) {\r\n\t\t\tnHx1 = roomBottomRight.x;\r\n\t\t\tnHy1 = GenerateRnd(roomSize.height - 2) + roomTopLeft.y + 1;\r\n\t\t\tnHx2 = RoomList[nRDest].topLeft.x;\r\n\t\t\tconst int nHh = RoomList[nRDest].bottomRight.y - RoomList[nRDest].topLeft.y - 2;\r\n\t\t\tnHy2 = GenerateRnd(nHh) + RoomList[nRDest].topLeft.y + 1;\r\n\t\t}\r\n\t\tif (nHDir == HallDirection::Left) {\r\n\t\t\tnHx1 = roomTopLeft.x;\r\n\t\t\tnHy1 = GenerateRnd(roomSize.height - 2) + roomTopLeft.y + 1;\r\n\t\t\tnHx2 = RoomList[nRDest].bottomRight.x;\r\n\t\t\tconst int nHh = RoomList[nRDest].bottomRight.y - RoomList[nRDest].topLeft.y - 2;\r\n\t\t\tnHy2 = GenerateRnd(nHh) + RoomList[nRDest].topLeft.y + 1;\r\n\t\t}\r\n\t\tHallList.push_back({ { nHx1, nHy1 }, { nHx2, nHy2 }, nHDir });\r\n\t}\r\n\r\n\tconst WorldTilePosition roomBottomLeft { roomTopLeft.x, roomBottomRight.y };\r\n\tconst WorldTilePosition roomTopRight { roomBottomRight.x, roomTopLeft.y };\r\n\tif (roomSize.height > roomSize.width) {\r\n\t\tCreateRoom(topLeft + standoff, roomBottomLeft - standoff, nRid, HallDirection::Right, {});\r\n\t\tCreateRoom(roomTopRight + standoff, bottomRight - standoff, nRid, HallDirection::Left, {});\r\n\t\tCreateRoom(WorldTilePosition { topLeft.x, roomBottomRight.y } + standoff, WorldTilePosition { roomBottomRight.x, bottomRight.y } - standoff, nRid, HallDirection::Up, {});\r\n\t\tCreateRoom(WorldTilePosition { roomTopLeft.x, topLeft.y } + standoff, WorldTilePosition { bottomRight.x, roomTopLeft.y } - standoff, nRid, HallDirection::Down, {});\r\n\t} else {\r\n\t\tCreateRoom(topLeft + standoff, roomTopRight - standoff, nRid, HallDirection::Down, {});\r\n\t\tCreateRoom(roomBottomLeft + standoff, bottomRight - standoff, nRid, HallDirection::Up, {});\r\n\t\tCreateRoom(WorldTilePosition { topLeft.x, roomTopLeft.y } + standoff, WorldTilePosition { roomTopLeft.x, bottomRight.y } - standoff, nRid, HallDirection::Right, {});\r\n\t\tCreateRoom(WorldTilePosition { roomBottomRight.x, topLeft.y } + standoff, WorldTilePosition { bottomRight.x, roomBottomRight.y } - standoff, nRid, HallDirection::Left, {});\r\n\t}\r\n}\r\n\r\nvoid ConnectHall(const HallNode &node)\r\n{\r\n\tPoint beginning = node.beginning;\r\n\tPoint end = node.end;\r\n\r\n\tconst bool fMinusFlag = GenerateRnd(100) < 50;\r\n\tconst bool fPlusFlag = GenerateRnd(100) < 50;\r\n\tCreateDoorType(beginning);\r\n\tCreateDoorType(end);\r\n\tHallDirection nCurrd = node.direction;\r\n\tend -= DirAdd[static_cast<uint8_t>(nCurrd)];\r\n\tpredungeon[end.x][end.y] = ',';\r\n\tbool fInroom = false;\r\n\r\n\tdo {\r\n\t\tif (beginning.x >= 38 && nCurrd == HallDirection::Right)\r\n\t\t\tnCurrd = HallDirection::Left;\r\n\t\tif (beginning.y >= 38 && nCurrd == HallDirection::Down)\r\n\t\t\tnCurrd = HallDirection::Up;\r\n\t\tif (beginning.x <= 1 && nCurrd == HallDirection::Left)\r\n\t\t\tnCurrd = HallDirection::Right;\r\n\t\tif (beginning.y <= 1 && nCurrd == HallDirection::Up)\r\n\t\t\tnCurrd = HallDirection::Down;\r\n\t\tif (predungeon[beginning.x][beginning.y] == 'C' && IsAnyOf(nCurrd, HallDirection::Up, HallDirection::Left))\r\n\t\t\tnCurrd = HallDirection::Right;\r\n\t\tif (predungeon[beginning.x][beginning.y] == 'B' && IsAnyOf(nCurrd, HallDirection::Up, HallDirection::Right))\r\n\t\t\tnCurrd = HallDirection::Down;\r\n\t\tif (predungeon[beginning.x][beginning.y] == 'E' && IsAnyOf(nCurrd, HallDirection::Left, HallDirection::Down))\r\n\t\t\tnCurrd = HallDirection::Up;\r\n\t\tif (predungeon[beginning.x][beginning.y] == 'A' && IsAnyOf(nCurrd, HallDirection::Right, HallDirection::Down))\r\n\t\t\tnCurrd = HallDirection::Left;\r\n\t\tbeginning += DirAdd[static_cast<uint8_t>(nCurrd)];\r\n\t\tif (predungeon[beginning.x][beginning.y] == ' ') {\r\n\t\t\tif (fInroom) {\r\n\t\t\t\tCreateDoorType(beginning - DirAdd[static_cast<uint8_t>(nCurrd)]);\r\n\t\t\t\tfInroom = false;\r\n\t\t\t} else {\r\n\t\t\t\tif (fMinusFlag) {\r\n\t\t\t\t\tif (IsNoneOf(nCurrd, HallDirection::Up, HallDirection::Down))\r\n\t\t\t\t\t\tPlaceHallExt(beginning + Displacement { 0, -1 }); // Up\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tPlaceHallExt(beginning + Displacement { -1, 0 }); // Left\r\n\t\t\t\t}\r\n\t\t\t\tif (fPlusFlag) {\r\n\t\t\t\t\tif (IsNoneOf(nCurrd, HallDirection::Up, HallDirection::Down))\r\n\t\t\t\t\t\tPlaceHallExt(beginning + Displacement { 0, 1 }); // Down\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tPlaceHallExt(beginning + Displacement { 1, 0 }); // Right\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tpredungeon[beginning.x][beginning.y] = ',';\r\n\t\t} else {\r\n\t\t\tif (!fInroom && predungeon[beginning.x][beginning.y] == '#')\r\n\t\t\t\tCreateDoorType(beginning);\r\n\t\t\tif (predungeon[beginning.x][beginning.y] != ',')\r\n\t\t\t\tfInroom = true;\r\n\t\t}\r\n\t\tconst int nDx = std::abs(end.x - beginning.x);\r\n\t\tconst int nDy = std::abs(end.y - beginning.y);\r\n\t\tif (nDx > nDy) {\r\n\t\t\tconst int nRp = std::min(2 * nDx, 30);\r\n\t\t\tif (GenerateRnd(100) < nRp) {\r\n\t\t\t\tif (end.x <= beginning.x || beginning.x >= DMAXX)\r\n\t\t\t\t\tnCurrd = HallDirection::Left;\r\n\t\t\t\telse\r\n\t\t\t\t\tnCurrd = HallDirection::Right;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst int nRp = std::min(5 * nDy, 80);\r\n\t\t\tif (GenerateRnd(100) < nRp) {\r\n\t\t\t\tif (end.y <= beginning.y || beginning.y >= DMAXY)\r\n\t\t\t\t\tnCurrd = HallDirection::Up;\r\n\t\t\t\telse\r\n\t\t\t\t\tnCurrd = HallDirection::Down;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (nDy < 10 && beginning.x == end.x && IsAnyOf(nCurrd, HallDirection::Right, HallDirection::Left)) {\r\n\t\t\tif (end.y <= beginning.y || beginning.y >= DMAXY)\r\n\t\t\t\tnCurrd = HallDirection::Up;\r\n\t\t\telse\r\n\t\t\t\tnCurrd = HallDirection::Down;\r\n\t\t}\r\n\t\tif (nDx < 10 && beginning.y == end.y && IsAnyOf(nCurrd, HallDirection::Up, HallDirection::Down)) {\r\n\t\t\tif (end.x <= beginning.x || beginning.x >= DMAXX)\r\n\t\t\t\tnCurrd = HallDirection::Left;\r\n\t\t\telse\r\n\t\t\t\tnCurrd = HallDirection::Right;\r\n\t\t}\r\n\t\tif (nDy == 1 && nDx > 1 && IsAnyOf(nCurrd, HallDirection::Up, HallDirection::Down)) {\r\n\t\t\tif (end.x <= beginning.x || beginning.x >= DMAXX)\r\n\t\t\t\tnCurrd = HallDirection::Left;\r\n\t\t\telse\r\n\t\t\t\tnCurrd = HallDirection::Right;\r\n\t\t}\r\n\t\tif (nDx == 1 && nDy > 1 && IsAnyOf(nCurrd, HallDirection::Right, HallDirection::Left)) {\r\n\t\t\tif (end.y <= beginning.y || beginning.x >= DMAXX)\r\n\t\t\t\tnCurrd = HallDirection::Up;\r\n\t\t\telse\r\n\t\t\t\tnCurrd = HallDirection::Down;\r\n\t\t}\r\n\t\tif (nDx == 0 && predungeon[beginning.x][beginning.y] != ' ' && IsAnyOf(nCurrd, HallDirection::Right, HallDirection::Left)) {\r\n\t\t\tif (end.x <= node.beginning.x || beginning.x >= DMAXX)\r\n\t\t\t\tnCurrd = HallDirection::Up;\r\n\t\t\telse\r\n\t\t\t\tnCurrd = HallDirection::Down;\r\n\t\t}\r\n\t\tif (nDy == 0 && predungeon[beginning.x][beginning.y] != ' ' && IsAnyOf(nCurrd, HallDirection::Up, HallDirection::Down)) {\r\n\t\t\tif (end.y <= node.beginning.y || beginning.y >= DMAXY)\r\n\t\t\t\tnCurrd = HallDirection::Left;\r\n\t\t\telse\r\n\t\t\t\tnCurrd = HallDirection::Right;\r\n\t\t}\r\n\t} while (beginning != end);\r\n}\r\n\r\nvoid DoPatternCheck(int i, int j)\r\n{\r\n\tfor (int k = 0; Patterns[k][4] != 255; k++) {\r\n\t\tint x = i - 1;\r\n\t\tint y = j - 1;\r\n\t\tint nOk = 254;\r\n\t\tfor (int l = 0; l < 9 && nOk == 254; l++) {\r\n\t\t\tnOk = 255;\r\n\t\t\tif (l == 3 || l == 6) {\r\n\t\t\t\ty++;\r\n\t\t\t\tx = i - 1;\r\n\t\t\t}\r\n\t\t\tif (x >= 0 && x < DMAXX && y >= 0 && y < DMAXY) {\r\n\t\t\t\tswitch (Patterns[k][l]) {\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tif (predungeon[x][y] == '#') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tif (predungeon[x][y] == '.') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\tif (predungeon[x][y] == ' ') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\tif (predungeon[x][y] == 'D') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 5:\r\n\t\t\t\t\tif (predungeon[x][y] == 'D' || predungeon[x][y] == '.') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 6:\r\n\t\t\t\t\tif (predungeon[x][y] == 'D' || predungeon[x][y] == '#') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 7:\r\n\t\t\t\t\tif (predungeon[x][y] == ' ' || predungeon[x][y] == '.') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 8:\r\n\t\t\t\t\tif (predungeon[x][y] == 'D' || predungeon[x][y] == '#' || predungeon[x][y] == '.') {\r\n\t\t\t\t\t\tnOk = 254;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tnOk = 254;\r\n\t\t\t}\r\n\t\t\tx++;\r\n\t\t}\r\n\t\tif (nOk == 254) {\r\n\t\t\tdungeon[i][j] = Patterns[k][9];\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FixTilesPatterns()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 3) {\r\n\t\t\t\tdungeon[i][j + 1] = 1;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 3 && dungeon[i][j + 1] == 1) {\r\n\t\t\t\tdungeon[i][j + 1] = 3;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 3 && dungeon[i + 1][j] == 7) {\r\n\t\t\t\tdungeon[i + 1][j] = 3;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 3) {\r\n\t\t\t\tdungeon[i + 1][j] = 2;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i + 1][j] == 14) {\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i][j + 1] == 1) {\r\n\t\t\t\tdungeon[i][j + 1] = 8;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Substitution()\r\n{\r\n\tfor (WorldTileCoord y = 0; y < DMAXY; y++) {\r\n\t\tfor (WorldTileCoord x = 0; x < DMAXX; x++) {\r\n\t\t\tif (SetPieceRoom.contains(x, y))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (!FlipCoin(4))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst uint8_t c = BTYPESL2[dungeon[x][y]];\r\n\t\t\tif (c != 0) {\r\n\t\t\t\tint rv = GenerateRnd(16);\r\n\t\t\t\tint i = -1;\r\n\t\t\t\twhile (rv >= 0) {\r\n\t\t\t\t\ti++;\r\n\t\t\t\t\tif (i == sizeof(BTYPESL2)) {\r\n\t\t\t\t\t\ti = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (c == BTYPESL2[i]) {\r\n\t\t\t\t\t\trv--;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tint j;\r\n\t\t\t\tfor (j = y - 2; j < y + 2; j++) {\r\n\t\t\t\t\tfor (int k = x - 2; k < x + 2; k++) {\r\n\t\t\t\t\t\tif (dungeon[k][j] == i) {\r\n\t\t\t\t\t\t\tj = y + 3;\r\n\t\t\t\t\t\t\tk = x + 2;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (j < y + 3) {\r\n\t\t\t\t\tdungeon[x][y] = i;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint CountEmptyTiles()\r\n{\r\n\tint t = 0;\r\n\tfor (int jj = 0; jj < DMAXY; jj++) {\r\n\t\tfor (int ii = 0; ii < DMAXX; ii++) { // NOLINT(modernize-loop-convert)\r\n\t\t\tif (predungeon[ii][jj] == ' ') {\r\n\t\t\t\tt++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn t;\r\n}\r\n\r\nvoid KnockWalls(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int ii = x1 + 1; ii < x2; ii++) {\r\n\t\tif (predungeon[ii][y1 - 1] == '.' && predungeon[ii][y1 + 1] == '.') {\r\n\t\t\tpredungeon[ii][y1] = '.';\r\n\t\t}\r\n\t\tif (predungeon[ii][y2 - 1] == '.' && predungeon[ii][y2 + 1] == '.') {\r\n\t\t\tpredungeon[ii][y2] = '.';\r\n\t\t}\r\n\t\tif (predungeon[ii][y1 - 1] == 'D') {\r\n\t\t\tpredungeon[ii][y1 - 1] = '.';\r\n\t\t}\r\n\t\tif (predungeon[ii][y2 + 1] == 'D') {\r\n\t\t\tpredungeon[ii][y2 + 1] = '.';\r\n\t\t}\r\n\t}\r\n\tfor (int jj = y1 + 1; jj < y2; jj++) {\r\n\t\tif (predungeon[x1 - 1][jj] == '.' && predungeon[x1 + 1][jj] == '.') {\r\n\t\t\tpredungeon[x1][jj] = '.';\r\n\t\t}\r\n\t\tif (predungeon[x2 - 1][jj] == '.' && predungeon[x2 + 1][jj] == '.') {\r\n\t\t\tpredungeon[x2][jj] = '.';\r\n\t\t}\r\n\t\tif (predungeon[x1 - 1][jj] == 'D') {\r\n\t\t\tpredungeon[x1 - 1][jj] = '.';\r\n\t\t}\r\n\t\tif (predungeon[x2 + 1][jj] == 'D') {\r\n\t\t\tpredungeon[x2 + 1][jj] = '.';\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FillVoid(bool xf1, bool yf1, bool xf2, bool yf2, int xx, int yy)\r\n{\r\n\tint x1 = xx;\r\n\tif (xf1) {\r\n\t\tx1--;\r\n\t}\r\n\tint x2 = xx;\r\n\tif (xf2) {\r\n\t\tx2++;\r\n\t}\r\n\tint y1 = yy;\r\n\tif (yf1) {\r\n\t\ty1--;\r\n\t}\r\n\tint y2 = yy;\r\n\tif (yf2) {\r\n\t\ty2++;\r\n\t}\r\n\tif (!xf1) {\r\n\t\twhile (yf1 || yf2) {\r\n\t\t\tif (y1 == 0) {\r\n\t\t\t\tyf1 = false;\r\n\t\t\t}\r\n\t\t\tif (y2 == DMAXY - 1) {\r\n\t\t\t\tyf2 = false;\r\n\t\t\t}\r\n\t\t\tif (y2 - y1 >= 14) {\r\n\t\t\t\tyf1 = false;\r\n\t\t\t\tyf2 = false;\r\n\t\t\t}\r\n\t\t\tif (yf1) {\r\n\t\t\t\ty1--;\r\n\t\t\t}\r\n\t\t\tif (yf2) {\r\n\t\t\t\ty2++;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x2][y1] != ' ') {\r\n\t\t\t\tyf1 = false;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x2][y2] != ' ') {\r\n\t\t\t\tyf2 = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\ty1 += 2;\r\n\t\ty2 -= 2;\r\n\t\tif (y2 - y1 > 5) {\r\n\t\t\twhile (xf2) {\r\n\t\t\t\tif (x2 == 39) {\r\n\t\t\t\t\txf2 = false;\r\n\t\t\t\t}\r\n\t\t\t\tif (x2 - x1 >= 12) {\r\n\t\t\t\t\txf2 = false;\r\n\t\t\t\t}\r\n\t\t\t\tfor (int jj = y1; jj <= y2; jj++) {\r\n\t\t\t\t\tif (predungeon[x2][jj] != ' ') {\r\n\t\t\t\t\t\txf2 = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (xf2) {\r\n\t\t\t\t\tx2++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tx2 -= 2;\r\n\t\t\tif (x2 - x1 > 5) {\r\n\t\t\t\tMapRoom(x1, y1, x2, y2);\r\n\t\t\t\tKnockWalls(x1, y1, x2, y2);\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (!xf2) {\r\n\t\twhile (yf1 || yf2) {\r\n\t\t\tif (y1 == 0) {\r\n\t\t\t\tyf1 = false;\r\n\t\t\t}\r\n\t\t\tif (y2 == DMAXY - 1) {\r\n\t\t\t\tyf2 = false;\r\n\t\t\t}\r\n\t\t\tif (y2 - y1 >= 14) {\r\n\t\t\t\tyf1 = false;\r\n\t\t\t\tyf2 = false;\r\n\t\t\t}\r\n\t\t\tif (yf1) {\r\n\t\t\t\ty1--;\r\n\t\t\t}\r\n\t\t\tif (yf2) {\r\n\t\t\t\ty2++;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x1][y1] != ' ') {\r\n\t\t\t\tyf1 = false;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x1][y2] != ' ') {\r\n\t\t\t\tyf2 = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\ty1 += 2;\r\n\t\ty2 -= 2;\r\n\t\tif (y2 - y1 > 5) {\r\n\t\t\twhile (xf1) {\r\n\t\t\t\tif (x1 == 0) {\r\n\t\t\t\t\txf1 = false;\r\n\t\t\t\t}\r\n\t\t\t\tif (x2 - x1 >= 12) {\r\n\t\t\t\t\txf1 = false;\r\n\t\t\t\t}\r\n\t\t\t\tfor (int jj = y1; jj <= y2; jj++) {\r\n\t\t\t\t\tif (predungeon[x1][jj] != ' ') {\r\n\t\t\t\t\t\txf1 = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (xf1) {\r\n\t\t\t\t\tx1--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tx1 += 2;\r\n\t\t\tif (x2 - x1 > 5) {\r\n\t\t\t\tMapRoom(x1, y1, x2, y2);\r\n\t\t\t\tKnockWalls(x1, y1, x2, y2);\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (!yf1) {\r\n\t\twhile (xf1 || xf2) {\r\n\t\t\tif (x1 == 0) {\r\n\t\t\t\txf1 = false;\r\n\t\t\t}\r\n\t\t\tif (x2 == DMAXX - 1) {\r\n\t\t\t\txf2 = false;\r\n\t\t\t}\r\n\t\t\tif (x2 - x1 >= 14) {\r\n\t\t\t\txf1 = false;\r\n\t\t\t\txf2 = false;\r\n\t\t\t}\r\n\t\t\tif (xf1) {\r\n\t\t\t\tx1--;\r\n\t\t\t}\r\n\t\t\tif (xf2) {\r\n\t\t\t\tx2++;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x1][y2] != ' ') {\r\n\t\t\t\txf1 = false;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x2][y2] != ' ') {\r\n\t\t\t\txf2 = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\tx1 += 2;\r\n\t\tx2 -= 2;\r\n\t\tif (x2 - x1 > 5) {\r\n\t\t\twhile (yf2) {\r\n\t\t\t\tif (y2 == DMAXY - 1) {\r\n\t\t\t\t\tyf2 = false;\r\n\t\t\t\t}\r\n\t\t\t\tif (y2 - y1 >= 12) {\r\n\t\t\t\t\tyf2 = false;\r\n\t\t\t\t}\r\n\t\t\t\tfor (int ii = x1; ii <= x2; ii++) {\r\n\t\t\t\t\tif (predungeon[ii][y2] != ' ') {\r\n\t\t\t\t\t\tyf2 = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (yf2) {\r\n\t\t\t\t\ty2++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ty2 -= 2;\r\n\t\t\tif (y2 - y1 > 5) {\r\n\t\t\t\tMapRoom(x1, y1, x2, y2);\r\n\t\t\t\tKnockWalls(x1, y1, x2, y2);\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (!yf2) {\r\n\t\twhile (xf1 || xf2) {\r\n\t\t\tif (x1 == 0) {\r\n\t\t\t\txf1 = false;\r\n\t\t\t}\r\n\t\t\tif (x2 == DMAXX - 1) {\r\n\t\t\t\txf2 = false;\r\n\t\t\t}\r\n\t\t\tif (x2 - x1 >= 14) {\r\n\t\t\t\txf1 = false;\r\n\t\t\t\txf2 = false;\r\n\t\t\t}\r\n\t\t\tif (xf1) {\r\n\t\t\t\tx1--;\r\n\t\t\t}\r\n\t\t\tif (xf2) {\r\n\t\t\t\tx2++;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x1][y1] != ' ') {\r\n\t\t\t\txf1 = false;\r\n\t\t\t}\r\n\t\t\tif (predungeon[x2][y1] != ' ') {\r\n\t\t\t\txf2 = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\tx1 += 2;\r\n\t\tx2 -= 2;\r\n\t\tif (x2 - x1 > 5) {\r\n\t\t\twhile (yf1) {\r\n\t\t\t\tif (y1 == 0) {\r\n\t\t\t\t\tyf1 = false;\r\n\t\t\t\t}\r\n\t\t\t\tif (y2 - y1 >= 12) {\r\n\t\t\t\t\tyf1 = false;\r\n\t\t\t\t}\r\n\t\t\t\tfor (int ii = x1; ii <= x2; ii++) {\r\n\t\t\t\t\tif (predungeon[ii][y1] != ' ') {\r\n\t\t\t\t\t\tyf1 = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (yf1) {\r\n\t\t\t\t\ty1--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ty1 += 2;\r\n\t\t\tif (y2 - y1 > 5) {\r\n\t\t\t\tMapRoom(x1, y1, x2, y2);\r\n\t\t\t\tKnockWalls(x1, y1, x2, y2);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool FillVoids()\r\n{\r\n\tint to = 0;\r\n\twhile (CountEmptyTiles() > 700 && to < 100) {\r\n\t\tconst int xx = GenerateRnd(38) + 1;\r\n\t\tconst int yy = GenerateRnd(38) + 1;\r\n\t\tif (predungeon[xx][yy] != '#') {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tbool xf1 = false;\r\n\t\tbool xf2 = false;\r\n\t\tbool yf1 = false;\r\n\t\tbool yf2 = false;\r\n\t\tif (predungeon[xx - 1][yy] == ' ' && predungeon[xx + 1][yy] == '.') {\r\n\t\t\tif (predungeon[xx + 1][yy - 1] == '.'\r\n\t\t\t    && predungeon[xx + 1][yy + 1] == '.'\r\n\t\t\t    && predungeon[xx - 1][yy - 1] == ' '\r\n\t\t\t    && predungeon[xx - 1][yy + 1] == ' ') {\r\n\t\t\t\txf1 = true;\r\n\t\t\t\tyf1 = true;\r\n\t\t\t\tyf2 = true;\r\n\t\t\t}\r\n\t\t} else if (predungeon[xx + 1][yy] == ' ' && predungeon[xx - 1][yy] == '.') {\r\n\t\t\tif (predungeon[xx - 1][yy - 1] == '.'\r\n\t\t\t    && predungeon[xx - 1][yy + 1] == '.'\r\n\t\t\t    && predungeon[xx + 1][yy - 1] == ' '\r\n\t\t\t    && predungeon[xx + 1][yy + 1] == ' ') {\r\n\t\t\t\txf2 = true;\r\n\t\t\t\tyf1 = true;\r\n\t\t\t\tyf2 = true;\r\n\t\t\t}\r\n\t\t} else if (predungeon[xx][yy - 1] == ' ' && predungeon[xx][yy + 1] == '.') {\r\n\t\t\tif (predungeon[xx - 1][yy + 1] == '.'\r\n\t\t\t    && predungeon[xx + 1][yy + 1] == '.'\r\n\t\t\t    && predungeon[xx - 1][yy - 1] == ' '\r\n\t\t\t    && predungeon[xx + 1][yy - 1] == ' ') {\r\n\t\t\t\tyf1 = true;\r\n\t\t\t\txf1 = true;\r\n\t\t\t\txf2 = true;\r\n\t\t\t}\r\n\t\t} else if (predungeon[xx][yy + 1] == ' ' && predungeon[xx][yy - 1] == '.') {\r\n\t\t\tif (predungeon[xx - 1][yy - 1] == '.'\r\n\t\t\t    && predungeon[xx + 1][yy - 1] == '.'\r\n\t\t\t    && predungeon[xx - 1][yy + 1] == ' '\r\n\t\t\t    && predungeon[xx + 1][yy + 1] == ' ') {\r\n\t\t\t\tyf2 = true;\r\n\t\t\t\txf1 = true;\r\n\t\t\t\txf2 = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (xf1 || yf1 || xf2 || yf2) {\r\n\t\t\tFillVoid(xf1, yf1, xf2, yf2, xx, yy);\r\n\t\t}\r\n\t\tto++;\r\n\t}\r\n\r\n\treturn CountEmptyTiles() <= 700;\r\n}\r\n\r\nbool CreateDungeon()\r\n{\r\n\tstd::optional<WorldTileSize> size;\r\n\r\n\tswitch (currlevel) {\r\n\tcase 5:\r\n\t\tif (Quests[Q_BLOOD]._qactive != QUEST_NOTAVAIL)\r\n\t\t\tsize = { 14, 20 };\r\n\t\tbreak;\r\n\tcase 6:\r\n\t\tif (Quests[Q_SCHAMB]._qactive != QUEST_NOTAVAIL)\r\n\t\t\tsize = { 10, 10 };\r\n\t\tbreak;\r\n\tcase 7:\r\n\t\tif (Quests[Q_BLIND]._qactive != QUEST_NOTAVAIL)\r\n\t\t\tsize = { 15, 15 };\r\n\t\tbreak;\r\n\tcase 8:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tCreateRoom({ 2, 2 }, { DMAXX - 1, DMAXY - 1 }, 0, HallDirection::None, size);\r\n\r\n\twhile (!HallList.empty()) {\r\n\t\tConnectHall(HallList.front());\r\n\t\tHallList.pop_front();\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {     /// BUGFIX: change '<=' to '<' (fixed)\r\n\t\tfor (int i = 0; i < DMAXX; i++) { /// BUGFIX: change '<=' to '<' (fixed)\r\n\t\t\tif (IsAnyOf(predungeon[i][j], 'A', 'B', 'C', 'E')) {\r\n\t\t\t\tpredungeon[i][j] = '#';\r\n\t\t\t}\r\n\t\t\tif (predungeon[i][j] == ',') {\r\n\t\t\t\tpredungeon[i][j] = '.';\r\n\t\t\t\tfor (int a = -1; a <= 1; a++) {\r\n\t\t\t\t\tfor (int b = -1; b <= 1; b++) {\r\n\t\t\t\t\t\tif (a == 0 && b == 0)\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tif (i + a < 0 || j + b < 0)\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tif (i + a >= DMAXX || j + b >= DMAXY)\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tif (predungeon[i + a][j + b] == ' ') {\r\n\t\t\t\t\t\t\tpredungeon[i + a][j + b] = '#';\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (!FillVoids()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tDoPatternCheck(i, j);\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid FixTransparency()\r\n{\r\n\tint yy = 16;\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tint xx = 16;\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\t// BUGFIX: Should check for `j > 0` first.\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i][j - 1] == 10) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Should check for `i + 1 < DMAXY` first.\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 11) {\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 10) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 11) {\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 16) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\txx += 2;\r\n\t\t}\r\n\t\tyy += 2;\r\n\t}\r\n}\r\n\r\nvoid FixDirtTiles()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i + 1][j] != 11) {\r\n\t\t\t\tdungeon[i][j] = 146;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i + 1][j] != 11) {\r\n\t\t\t\tdungeon[i][j] = 144;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] != 11) {\r\n\t\t\t\tdungeon[i][j] = 148;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 10 && dungeon[i][j + 1] != 10) {\r\n\t\t\t\tdungeon[i][j] = 143;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i][j + 1] != 10) {\r\n\t\t\t\tdungeon[i][j] = 146;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i][j + 1] != 15) {\r\n\t\t\t\tdungeon[i][j] = 147;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FixLockout()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 4 && dungeon[i - 1][j] != 3) {\r\n\t\t\t\tdungeon[i][j] = 1;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 5 && dungeon[i][j - 1] != 3) {\r\n\t\t\t\tdungeon[i][j] = 2;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int j = 1; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 1; i < DMAXX - 1; i++) {\r\n\t\t\tif (Protected.test(i, j)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif ((dungeon[i][j] == 2 || dungeon[i][j] == 5) && dungeon[i][j - 1] == 3 && dungeon[i][j + 1] == 3) {\r\n\t\t\t\tbool doorok = false;\r\n\t\t\t\twhile (true) {\r\n\t\t\t\t\tif (dungeon[i][j] != 2 && dungeon[i][j] != 5) {\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (dungeon[i][j - 1] != 3 || dungeon[i][j + 1] != 3) {\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (dungeon[i][j] == 5) {\r\n\t\t\t\t\t\tdoorok = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}\r\n\t\t\t\tif (!doorok && !Protected.test(i - 1, j)) {\r\n\t\t\t\t\tdungeon[i - 1][j] = 5;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int j = 1; j < DMAXX - 1; j++) { /* check: might be flipped */\r\n\t\tfor (int i = 1; i < DMAXY - 1; i++) {\r\n\t\t\tif (Protected.test(j, i)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif ((dungeon[j][i] == 1 || dungeon[j][i] == 4) && dungeon[j - 1][i] == 3 && dungeon[j + 1][i] == 3) {\r\n\t\t\t\tbool doorok = false;\r\n\t\t\t\twhile (true) {\r\n\t\t\t\t\tif (dungeon[j][i] != 1 && dungeon[j][i] != 4) {\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (dungeon[j - 1][i] != 3 || dungeon[j + 1][i] != 3) {\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (dungeon[j][i] == 4) {\r\n\t\t\t\t\t\tdoorok = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}\r\n\t\t\t\tif (!doorok && !Protected.test(j, i - 1)) {\r\n\t\t\t\t\tdungeon[j][i - 1] = 4;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FixDoors()\r\n{\r\n\tfor (int j = 1; j < DMAXY; j++) {\r\n\t\tfor (int i = 1; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 4 && dungeon[i][j - 1] == 3) {\r\n\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 5 && dungeon[i - 1][j] == 3) {\r\n\t\t\t\tdungeon[i][j] = 9;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool PlaceStairs(lvl_entry entry)\r\n{\r\n\tstd::optional<Point> position;\r\n\r\n\t// Place stairs up\r\n\tposition = PlaceMiniSet(USTAIRS);\r\n\tif (!position)\r\n\t\treturn false;\r\n\tif (entry == ENTRY_MAIN)\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 5, 4 };\r\n\r\n\t// Place stairs down\r\n\tposition = PlaceMiniSet(DSTAIRS);\r\n\tif (!position)\r\n\t\treturn false;\r\n\tif (entry == ENTRY_PREV)\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 4, 6 };\r\n\r\n\t// Place town warp stairs\r\n\tif (currlevel == 5) {\r\n\t\tposition = PlaceMiniSet(WARPSTAIRS);\r\n\t\tif (!position)\r\n\t\t\treturn false;\r\n\t\tif (entry == ENTRY_TWARPDN)\r\n\t\t\tViewPosition = position->megaToWorld() + Displacement { 5, 4 };\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid GenerateLevel(lvl_entry entry)\r\n{\r\n\tif (LevelSeeds[currlevel])\r\n\t\tSetRndSeed(*LevelSeeds[currlevel]);\r\n\r\n\twhile (true) {\r\n\t\tLevelSeeds[currlevel] = GetLCGEngineState();\r\n\t\tnRoomCnt = 0;\r\n\t\tInitDungeonFlags();\r\n\t\tDRLG_InitTrans();\r\n\t\tif (!CreateDungeon()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tFixTilesPatterns();\r\n\t\tInitSetPiece();\r\n\t\tFloodTransparencyValues(3);\r\n\t\tFixTransparency();\r\n\t\tif (PlaceStairs(entry))\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tFixLockout();\r\n\tFixDoors();\r\n\tFixDirtTiles();\r\n\r\n\tDRLG_PlaceThemeRooms(6, 10, 3, 0, false);\r\n\tPlaceMiniSetRandom(CTRDOOR1, 100);\r\n\tPlaceMiniSetRandom(CTRDOOR2, 100);\r\n\tPlaceMiniSetRandom(CTRDOOR3, 100);\r\n\tPlaceMiniSetRandom(CTRDOOR4, 100);\r\n\tPlaceMiniSetRandom(CTRDOOR5, 100);\r\n\tPlaceMiniSetRandom(CTRDOOR6, 100);\r\n\tPlaceMiniSetRandom(CTRDOOR7, 100);\r\n\tPlaceMiniSetRandom(CTRDOOR8, 100);\r\n\tPlaceMiniSetRandom(VARCH33, 100);\r\n\tPlaceMiniSetRandom(VARCH34, 100);\r\n\tPlaceMiniSetRandom(VARCH35, 100);\r\n\tPlaceMiniSetRandom(VARCH36, 100);\r\n\tPlaceMiniSetRandom(VARCH37, 100);\r\n\tPlaceMiniSetRandom(VARCH38, 100);\r\n\tPlaceMiniSetRandom(VARCH39, 100);\r\n\tPlaceMiniSetRandom(VARCH40, 100);\r\n\tPlaceMiniSetRandom(VARCH1, 100);\r\n\tPlaceMiniSetRandom(VARCH2, 100);\r\n\tPlaceMiniSetRandom(VARCH3, 100);\r\n\tPlaceMiniSetRandom(VARCH4, 100);\r\n\tPlaceMiniSetRandom(VARCH5, 100);\r\n\tPlaceMiniSetRandom(VARCH6, 100);\r\n\tPlaceMiniSetRandom(VARCH7, 100);\r\n\tPlaceMiniSetRandom(VARCH8, 100);\r\n\tPlaceMiniSetRandom(VARCH9, 100);\r\n\tPlaceMiniSetRandom(VARCH10, 100);\r\n\tPlaceMiniSetRandom(VARCH11, 100);\r\n\tPlaceMiniSetRandom(VARCH12, 100);\r\n\tPlaceMiniSetRandom(VARCH13, 100);\r\n\tPlaceMiniSetRandom(VARCH14, 100);\r\n\tPlaceMiniSetRandom(VARCH15, 100);\r\n\tPlaceMiniSetRandom(VARCH16, 100);\r\n\tPlaceMiniSetRandom(VARCH17, 100);\r\n\tPlaceMiniSetRandom(VARCH18, 100);\r\n\tPlaceMiniSetRandom(VARCH19, 100);\r\n\tPlaceMiniSetRandom(VARCH20, 100);\r\n\tPlaceMiniSetRandom(VARCH21, 100);\r\n\tPlaceMiniSetRandom(VARCH22, 100);\r\n\tPlaceMiniSetRandom(VARCH23, 100);\r\n\tPlaceMiniSetRandom(VARCH24, 100);\r\n\tPlaceMiniSetRandom(VARCH25, 100);\r\n\tPlaceMiniSetRandom(VARCH26, 100);\r\n\tPlaceMiniSetRandom(VARCH27, 100);\r\n\tPlaceMiniSetRandom(VARCH28, 100);\r\n\tPlaceMiniSetRandom(VARCH29, 100);\r\n\tPlaceMiniSetRandom(VARCH30, 100);\r\n\tPlaceMiniSetRandom(VARCH31, 100);\r\n\tPlaceMiniSetRandom(VARCH32, 100);\r\n\tPlaceMiniSetRandom(HARCH1, 100);\r\n\tPlaceMiniSetRandom(HARCH2, 100);\r\n\tPlaceMiniSetRandom(HARCH3, 100);\r\n\tPlaceMiniSetRandom(HARCH4, 100);\r\n\tPlaceMiniSetRandom(HARCH5, 100);\r\n\tPlaceMiniSetRandom(HARCH6, 100);\r\n\tPlaceMiniSetRandom(HARCH7, 100);\r\n\tPlaceMiniSetRandom(HARCH8, 100);\r\n\tPlaceMiniSetRandom(HARCH9, 100);\r\n\tPlaceMiniSetRandom(HARCH10, 100);\r\n\tPlaceMiniSetRandom(HARCH11, 100);\r\n\tPlaceMiniSetRandom(HARCH12, 100);\r\n\tPlaceMiniSetRandom(HARCH13, 100);\r\n\tPlaceMiniSetRandom(HARCH14, 100);\r\n\tPlaceMiniSetRandom(HARCH15, 100);\r\n\tPlaceMiniSetRandom(HARCH16, 100);\r\n\tPlaceMiniSetRandom(HARCH17, 100);\r\n\tPlaceMiniSetRandom(HARCH18, 100);\r\n\tPlaceMiniSetRandom(HARCH19, 100);\r\n\tPlaceMiniSetRandom(HARCH20, 100);\r\n\tPlaceMiniSetRandom(HARCH21, 100);\r\n\tPlaceMiniSetRandom(HARCH22, 100);\r\n\tPlaceMiniSetRandom(HARCH23, 100);\r\n\tPlaceMiniSetRandom(HARCH24, 100);\r\n\tPlaceMiniSetRandom(HARCH25, 100);\r\n\tPlaceMiniSetRandom(HARCH26, 100);\r\n\tPlaceMiniSetRandom(HARCH27, 100);\r\n\tPlaceMiniSetRandom(HARCH28, 100);\r\n\tPlaceMiniSetRandom(HARCH29, 100);\r\n\tPlaceMiniSetRandom(HARCH30, 100);\r\n\tPlaceMiniSetRandom(HARCH31, 100);\r\n\tPlaceMiniSetRandom(HARCH32, 100);\r\n\tPlaceMiniSetRandom(HARCH33, 100);\r\n\tPlaceMiniSetRandom(HARCH34, 100);\r\n\tPlaceMiniSetRandom(HARCH35, 100);\r\n\tPlaceMiniSetRandom(HARCH36, 100);\r\n\tPlaceMiniSetRandom(HARCH37, 100);\r\n\tPlaceMiniSetRandom(HARCH38, 100);\r\n\tPlaceMiniSetRandom(HARCH39, 100);\r\n\tPlaceMiniSetRandom(HARCH40, 100);\r\n\tPlaceMiniSetRandom(CRUSHCOL, 99);\r\n\tPlaceMiniSetRandom1x1(1, 80, 10);\r\n\tPlaceMiniSetRandom1x1(1, 81, 10);\r\n\tPlaceMiniSetRandom1x1(1, 82, 10);\r\n\tPlaceMiniSetRandom1x1(2, 84, 10);\r\n\tPlaceMiniSetRandom1x1(2, 85, 10);\r\n\tPlaceMiniSetRandom1x1(2, 86, 10);\r\n\tPlaceMiniSetRandom1x1(8, 87, 50);\r\n\tPlaceMiniSetRandom(PANCREAS1, 1);\r\n\tPlaceMiniSetRandom(PANCREAS2, 1);\r\n\tPlaceMiniSetRandom(BIG1, 3);\r\n\tPlaceMiniSetRandom(BIG2, 3);\r\n\tPlaceMiniSetRandom(BIG3, 3);\r\n\tPlaceMiniSetRandom(BIG4, 3);\r\n\tPlaceMiniSetRandom(BIG5, 3);\r\n\tPlaceMiniSetRandom(BIG6, 20);\r\n\tPlaceMiniSetRandom(BIG7, 20);\r\n\tPlaceMiniSetRandom(BIG8, 3);\r\n\tPlaceMiniSetRandom(BIG9, 20);\r\n\tPlaceMiniSetRandom(BIG10, 20);\r\n\tSubstitution();\r\n\tApplyShadowsPatterns();\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n\r\n\tDRLG_CheckQuests(SetPieceRoom.position);\r\n}\r\n\r\nvoid Pass3()\r\n{\r\n\tDRLG_LPass3(12 - 1);\r\n\r\n\tInitDungeonPieces();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid CreateL2Dungeon(uint32_t rseed, lvl_entry entry)\r\n{\r\n\tSetRndSeed(rseed);\r\n\r\n\tGenerateLevel(entry);\r\n\r\n\tPass3();\r\n}\r\n\r\nvoid LoadPreL2Dungeon(const char *path)\r\n{\r\n\tmemset(dungeon, 12, sizeof(dungeon));\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\tPlaceDunTiles(dunData.get(), { 0, 0 }, 3);\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n}\r\n\r\nvoid LoadL2Dungeon(const char *path, Point spawn)\r\n{\r\n\tLoadDungeonBase(path, spawn, 3, 12);\r\n\r\n\tPass3();\r\n\r\n\tAddL2Objs(0, 0, MAXDUNX, MAXDUNY);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l2.h",
    "content": "/**\r\n * @file levels/drlg_l2.h\r\n *\r\n * Interface of the catacombs level generation algorithms.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid CreateL2Dungeon(uint32_t rseed, lvl_entry entry);\r\nvoid LoadPreL2Dungeon(const char *path);\r\nvoid LoadL2Dungeon(const char *path, Point spawn);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l3.cpp",
    "content": "#include \"levels/drlg_l3.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"lighting.h\"\r\n#include \"monster.h\"\r\n#include \"objects.h\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nint lockoutcnt;\r\n\r\n/**\r\n * A lookup table for the 16 possible patterns of a 2x2 area,\r\n * where each cell either contains a SW wall or it doesn't.\r\n */\r\nconst uint8_t L3ConvTbl[16] = { 8, 11, 3, 10, 1, 9, 12, 12, 6, 13, 4, 13, 2, 14, 5, 7 };\r\n/** Miniset: Stairs up. */\r\nconst Miniset L3UP {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 8, 8, 0 },\r\n\t    { 10, 10, 0 },\r\n\t    { 7, 7, 0 },\r\n\t},\r\n\t{\r\n\t    { 51, 50, 0 },\r\n\t    { 48, 49, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset L6UP {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 8, 8, 0 },\r\n\t    { 10, 10, 0 },\r\n\t    { 7, 7, 0 },\r\n\t},\r\n\t{\r\n\t    { 20, 19, 0 },\r\n\t    { 17, 18, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stairs down. */\r\nconst Miniset L3DOWN {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 8, 9, 7 },\r\n\t    { 8, 9, 7 },\r\n\t    { 0, 0, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 47, 0 },\r\n\t    { 0, 46, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset L6DOWN {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 8, 9, 7 },\r\n\t    { 8, 9, 7 },\r\n\t    { 0, 0, 0 },\r\n\t},\r\n\t{\r\n\t    { 0, 16, 0 },\r\n\t    { 0, 15, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stairs up to town. */\r\nconst Miniset L3HOLDWARP {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 8, 8, 0 },\r\n\t    { 10, 10, 0 },\r\n\t    { 7, 7, 0 },\r\n\t},\r\n\t{\r\n\t    { 125, 125, 0 },\r\n\t    { 125, 125, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset L6HOLDWARP {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 8, 8, 0 },\r\n\t    { 10, 10, 0 },\r\n\t    { 7, 7, 0 },\r\n\t},\r\n\t{\r\n\t    { 24, 23, 0 },\r\n\t    { 21, 22, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite white stalactite 1. */\r\nconst Miniset L3TITE1 {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 0, 57, 58, 0 },\r\n\t    { 0, 56, 55, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite white stalactite 2. */\r\nconst Miniset L3TITE2 {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 0, 61, 62, 0 },\r\n\t    { 0, 60, 59, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite white stalactite 3. */\r\nconst Miniset L3TITE3 {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 0, 65, 66, 0 },\r\n\t    { 0, 64, 63, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite white stalactite horizontal. */\r\nconst Miniset L3TITE6 {\r\n\t{ 5, 4 },\r\n\t{\r\n\t    { 7, 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 0, 7 },\r\n\t    { 7, 7, 7, 0, 7 },\r\n\t    { 7, 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t    { 0, 77, 78, 0, 0 },\r\n\t    { 0, 76, 74, 75, 0 },\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite white stalactite vertical. */\r\nconst Miniset L3TITE7 {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 0, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 0, 83, 0, 0 },\r\n\t    { 0, 82, 80, 0 },\r\n\t    { 0, 81, 79, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite 1. */\r\nconst Miniset L3TITE8 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 52, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite 2. */\r\nconst Miniset L3TITE9 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 53, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite 3. */\r\nconst Miniset L3TITE10 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 54, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite 4. */\r\nconst Miniset L3TITE11 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 67, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stalagmite on vertical wall. */\r\nconst Miniset L3TITE12 {\r\n\t{ 2, 1 },\r\n\t{ { 9, 7 } },\r\n\t{ { 68, 0 } }\r\n};\r\n/** Miniset: Stalagmite on horizontal wall. */\r\nconst Miniset L3TITE13 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 10 },\r\n\t    { 7 },\r\n\t},\r\n\t{\r\n\t    { 69 },\r\n\t    { 0 },\r\n\t}\r\n};\r\n/** Miniset: Cracked vertical wall 1. */\r\nconst Miniset L3CREV1 {\r\n\t{ 2, 1 },\r\n\t{ { 8, 7 } },\r\n\t{ { 84, 85 } }\r\n};\r\n/** Miniset: Cracked vertical wall - north corner. */\r\nconst Miniset L3CREV2 {\r\n\t{ 2, 1 },\r\n\t{ { 8, 11 } },\r\n\t{ { 86, 87 } }\r\n};\r\n/** Miniset: Cracked horizontal wall 1. */\r\nconst Miniset L3CREV3 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 8 },\r\n\t    { 10 },\r\n\t},\r\n\t{\r\n\t    { 89 },\r\n\t    { 88 },\r\n\t}\r\n};\r\n/** Miniset: Cracked vertical wall 2. */\r\nconst Miniset L3CREV4 {\r\n\t{ 2, 1 },\r\n\t{ { 8, 7 } },\r\n\t{ { 90, 91 } }\r\n};\r\n/** Miniset: Cracked horizontal wall - north corner. */\r\nconst Miniset L3CREV5 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 8 },\r\n\t    { 11 },\r\n\t},\r\n\t{\r\n\t    { 92 },\r\n\t    { 93 },\r\n\t}\r\n};\r\n/** Miniset: Cracked horizontal wall 2. */\r\nconst Miniset L3CREV6 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 8 },\r\n\t    { 10 },\r\n\t},\r\n\t{\r\n\t    { 95 },\r\n\t    { 94 },\r\n\t}\r\n};\r\n/** Miniset: Cracked vertical wall - west corner. */\r\nconst Miniset L3CREV7 {\r\n\t{ 2, 1 },\r\n\t{ { 8, 7 } },\r\n\t{ { 96, 101 } }\r\n};\r\n/** Miniset: Cracked horizontal wall - north. */\r\nconst Miniset L3CREV8 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 2 },\r\n\t    { 8 },\r\n\t},\r\n\t{\r\n\t    { 102 },\r\n\t    { 97 },\r\n\t}\r\n};\r\n/** Miniset: Cracked vertical wall - east corner. */\r\nconst Miniset L3CREV9 {\r\n\t{ 2, 1 },\r\n\t{ { 3, 8 } },\r\n\t{ { 103, 98 } }\r\n};\r\n/** Miniset: Cracked vertical wall - west. */\r\nconst Miniset L3CREV10 {\r\n\t{ 2, 1 },\r\n\t{ { 4, 8 } },\r\n\t{ { 104, 99 } }\r\n};\r\n/** Miniset: Cracked horizontal wall - south corner. */\r\nconst Miniset L3CREV11 {\r\n\t{ 1, 2 },\r\n\t{\r\n\t    { 6 },\r\n\t    { 8 },\r\n\t},\r\n\t{\r\n\t    { 105 },\r\n\t    { 100 },\r\n\t}\r\n};\r\n/** Miniset: Replace broken wall with floor 1. */\r\nconst Miniset L3ISLE1 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 5, 14 },\r\n\t    { 4, 9 },\r\n\t    { 13, 12 },\r\n\t},\r\n\t{\r\n\t    { 7, 7 },\r\n\t    { 7, 7 },\r\n\t    { 7, 7 },\r\n\t}\r\n};\r\n/** Miniset: Replace small wall with floor 2. */\r\nconst Miniset L3ISLE2 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 5, 2, 14 },\r\n\t    { 13, 10, 12 },\r\n\t},\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t}\r\n};\r\n/** Miniset: Replace small wall with lava 1. */\r\nconst Miniset L3ISLE3 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 5, 14 },\r\n\t    { 4, 9 },\r\n\t    { 13, 12 },\r\n\t},\r\n\t{\r\n\t    { 29, 30 },\r\n\t    { 25, 28 },\r\n\t    { 31, 32 },\r\n\t}\r\n};\r\n/** Miniset: Replace small wall with lava 2. */\r\nconst Miniset L3ISLE4 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 5, 2, 14 },\r\n\t    { 13, 10, 12 },\r\n\t},\r\n\t{\r\n\t    { 29, 26, 30 },\r\n\t    { 31, 27, 32 },\r\n\t}\r\n};\r\n/** Miniset: Replace small wall with floor 3. */\r\nconst Miniset L3ISLE5 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 5, 14 },\r\n\t    { 13, 12 },\r\n\t},\r\n\t{\r\n\t    { 7, 7 },\r\n\t    { 7, 7 },\r\n\t}\r\n};\r\nconst Miniset HivePattern9 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 126, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern10 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0 },\r\n\t    { 0, 124, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern29 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 67, 0, 0 },\r\n\t    { 66, 51, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern30 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 69, 0, 0 },\r\n\t    { 68, 52, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern31 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 70, 0, 0 },\r\n\t    { 71, 53, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern32 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 73, 0, 0 },\r\n\t    { 72, 54, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern33 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 75, 0, 0 },\r\n\t    { 74, 55, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern34 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 77, 0, 0 },\r\n\t    { 76, 56, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern35 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 79, 0, 0 },\r\n\t    { 78, 57, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern36 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 81, 0, 0 },\r\n\t    { 80, 58, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern37 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 83, 0, 0 },\r\n\t    { 82, 59, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset HivePattern38 {\r\n\t{ 3, 3 },\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 84, 0, 0 },\r\n\t    { 85, 60, 0 },\r\n\t    { 0, 0, 0 },\r\n\t}\r\n};\r\nconst Miniset L6ISLE1 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 5, 14 },\r\n\t    { 4, 9 },\r\n\t    { 13, 12 },\r\n\t},\r\n\t{\r\n\t    { 7, 7 },\r\n\t    { 7, 7 },\r\n\t    { 7, 7 },\r\n\t}\r\n};\r\nconst Miniset L6ISLE2 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 5, 2, 14 },\r\n\t    { 13, 10, 12 },\r\n\t},\r\n\t{\r\n\t    { 7, 7, 7 },\r\n\t    { 7, 7, 7 },\r\n\t}\r\n};\r\nconst Miniset L6ISLE3 {\r\n\t{ 2, 3 },\r\n\t{\r\n\t    { 5, 14 },\r\n\t    { 4, 9 },\r\n\t    { 13, 12 },\r\n\t},\r\n\t{\r\n\t    { 107, 115 },\r\n\t    { 119, 122 },\r\n\t    { 131, 123 },\r\n\t}\r\n};\r\nconst Miniset L6ISLE4 {\r\n\t{ 3, 2 },\r\n\t{\r\n\t    { 5, 2, 14 },\r\n\t    { 13, 10, 12 },\r\n\t},\r\n\t{\r\n\t    { 107, 120, 115 },\r\n\t    { 131, 121, 123 },\r\n\t}\r\n};\r\nconst Miniset L6ISLE5 {\r\n\t{ 2, 2 },\r\n\t{\r\n\t    { 5, 14 },\r\n\t    { 13, 12 },\r\n\t},\r\n\t{\r\n\t    { 7, 7 },\r\n\t    { 7, 7 },\r\n\t}\r\n};\r\nconst Miniset HivePattern39 {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 107, 115, 7 },\r\n\t    { 7, 131, 123, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t}\r\n};\r\nconst Miniset HivePattern40 {\r\n\t{ 4, 4 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 108, 7 },\r\n\t    { 7, 109, 112, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t}\r\n};\r\nconst Miniset HivePattern41 {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 107, 115, 7 },\r\n\t    { 7, 119, 122, 7 },\r\n\t    { 7, 131, 123, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t}\r\n};\r\nconst Miniset HivePattern42 {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t},\r\n\t{\r\n\t    { 7, 7, 7, 7 },\r\n\t    { 7, 126, 108, 7 },\r\n\t    { 7, 7, 117, 7 },\r\n\t    { 7, 109, 112, 7 },\r\n\t    { 7, 7, 7, 7 },\r\n\t}\r\n};\r\n\r\nvoid InitDungeonFlags()\r\n{\r\n\tmemset(dungeon, 0, sizeof(dungeon));\r\n\tProtected.reset();\r\n}\r\n\r\nbool FillRoom(int x1, int y1, int x2, int y2)\r\n{\r\n\tif (x1 <= 1 || x2 >= 34 || y1 <= 1 || y2 >= 38) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint v = 0;\r\n\tfor (int j = y1; j <= y2; j++) {\r\n\t\tfor (int i = x1; i <= x2; i++) {\r\n\t\t\tv += dungeon[i][j];\r\n\t\t}\r\n\t}\r\n\r\n\tif (v != 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (int j = y1 + 1; j < y2; j++) {\r\n\t\tfor (int i = x1 + 1; i < x2; i++) {\r\n\t\t\tdungeon[i][j] = 1;\r\n\t\t}\r\n\t}\r\n\tfor (int j = y1; j <= y2; j++) {\r\n\t\tif (!FlipCoin()) {\r\n\t\t\tdungeon[x1][j] = 1;\r\n\t\t}\r\n\t\tif (!FlipCoin()) {\r\n\t\t\tdungeon[x2][j] = 1;\r\n\t\t}\r\n\t}\r\n\tfor (int i = x1; i <= x2; i++) {\r\n\t\tif (!FlipCoin()) {\r\n\t\t\tdungeon[i][y1] = 1;\r\n\t\t}\r\n\t\tif (!FlipCoin()) {\r\n\t\t\tdungeon[i][y2] = 1;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid CreateBlock(Point point, int obs, int dir)\r\n{\r\n\tint x1;\r\n\tint y1;\r\n\tint x2;\r\n\tint y2;\r\n\r\n\tconst int blksizex = RandomIntBetween(3, 4);\r\n\tconst int blksizey = RandomIntBetween(3, 4);\r\n\r\n\tif (dir == 0) {\r\n\t\ty2 = point.y - 1;\r\n\t\ty1 = y2 - blksizey;\r\n\t\tif (blksizex < obs) {\r\n\t\t\tx1 = GenerateRnd(blksizex) + point.x;\r\n\t\t}\r\n\t\tif (blksizex == obs) {\r\n\t\t\tx1 = point.x;\r\n\t\t}\r\n\t\tif (blksizex > obs) {\r\n\t\t\tx1 = point.x - GenerateRnd(blksizex);\r\n\t\t}\r\n\t\tx2 = blksizex + x1;\r\n\t}\r\n\tif (dir == 1) {\r\n\t\tx1 = point.x + 1;\r\n\t\tx2 = x1 + blksizex;\r\n\t\tif (blksizey < obs) {\r\n\t\t\ty1 = GenerateRnd(blksizey) + point.y;\r\n\t\t}\r\n\t\tif (blksizey == obs) {\r\n\t\t\ty1 = point.y;\r\n\t\t}\r\n\t\tif (blksizey > obs) {\r\n\t\t\ty1 = point.y - GenerateRnd(blksizey);\r\n\t\t}\r\n\t\ty2 = y1 + blksizey;\r\n\t}\r\n\tif (dir == 2) {\r\n\t\ty1 = point.y + 1;\r\n\t\ty2 = y1 + blksizey;\r\n\t\tif (blksizex < obs) {\r\n\t\t\tx1 = GenerateRnd(blksizex) + point.x;\r\n\t\t}\r\n\t\tif (blksizex == obs) {\r\n\t\t\tx1 = point.x;\r\n\t\t}\r\n\t\tif (blksizex > obs) {\r\n\t\t\tx1 = point.x - GenerateRnd(blksizex);\r\n\t\t}\r\n\t\tx2 = blksizex + x1;\r\n\t}\r\n\tif (dir == 3) {\r\n\t\tx2 = point.x - 1;\r\n\t\tx1 = x2 - blksizex;\r\n\t\tif (blksizey < obs) {\r\n\t\t\ty1 = GenerateRnd(blksizey) + point.y;\r\n\t\t}\r\n\t\tif (blksizey == obs) {\r\n\t\t\ty1 = point.y;\r\n\t\t}\r\n\t\tif (blksizey > obs) {\r\n\t\t\ty1 = point.y - GenerateRnd(blksizey);\r\n\t\t}\r\n\t\ty2 = y1 + blksizey;\r\n\t}\r\n\r\n\tif (FillRoom(x1, y1, x2, y2)) {\r\n\t\tif (FlipCoin(4))\r\n\t\t\treturn;\r\n\r\n\t\tif (dir != 2) {\r\n\t\t\tCreateBlock({ x1, y1 }, blksizey, 0);\r\n\t\t}\r\n\t\tif (dir != 3) {\r\n\t\t\tCreateBlock({ x2, y1 }, blksizex, 1);\r\n\t\t}\r\n\t\tif (dir != 0) {\r\n\t\t\tCreateBlock({ x1, y2 }, blksizey, 2);\r\n\t\t}\r\n\t\tif (dir != 1) {\r\n\t\t\tCreateBlock({ x1, y1 }, blksizex, 3);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FloorArea(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j <= y2; j++) {\r\n\t\tfor (int i = x1; i <= x2; i++) {\r\n\t\t\tdungeon[i][j] = 1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FillDiagonals()\r\n{\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\t\tconst int v = dungeon[i + 1][j + 1] + 2 * dungeon[i][j + 1] + 4 * dungeon[i + 1][j] + 8 * dungeon[i][j];\r\n\t\t\tif (v == 6) {\r\n\t\t\t\tif (FlipCoin()) {\r\n\t\t\t\t\tdungeon[i][j] = 1;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdungeon[i + 1][j + 1] = 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (v == 9) {\r\n\t\t\t\tif (FlipCoin()) {\r\n\t\t\t\t\tdungeon[i + 1][j] = 1;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdungeon[i][j + 1] = 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FillSingles()\r\n{\r\n\tfor (int j = 1; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 1; i < DMAXX - 1; i++) {\r\n\t\t\tif (dungeon[i][j] == 0\r\n\t\t\t    && dungeon[i][j - 1] + dungeon[i - 1][j - 1] + dungeon[i + 1][j - 1] == 3\r\n\t\t\t    && dungeon[i + 1][j] + dungeon[i - 1][j] == 2\r\n\t\t\t    && dungeon[i][j + 1] + dungeon[i - 1][j + 1] + dungeon[i + 1][j + 1] == 3) {\r\n\t\t\t\tdungeon[i][j] = 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FillStraights()\r\n{\r\n\tint xc;\r\n\tint yc;\r\n\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tint xs = 0;\r\n\t\tfor (int i = 0; i < 37; i++) {\r\n\t\t\tif (dungeon[i][j] == 0 && dungeon[i][j + 1] == 1) {\r\n\t\t\t\tif (xs == 0) {\r\n\t\t\t\t\txc = i;\r\n\t\t\t\t}\r\n\t\t\t\txs++;\r\n\t\t\t} else {\r\n\t\t\t\tif (xs > 3 && !FlipCoin()) {\r\n\t\t\t\t\tfor (int k = xc; k < i; k++) {\r\n\t\t\t\t\t\tconst int rv = GenerateRnd(2);\r\n\t\t\t\t\t\tdungeon[k][j] = rv;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\txs = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tint xs = 0;\r\n\t\tfor (int i = 0; i < 37; i++) {\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 0) {\r\n\t\t\t\tif (xs == 0) {\r\n\t\t\t\t\txc = i;\r\n\t\t\t\t}\r\n\t\t\t\txs++;\r\n\t\t\t} else {\r\n\t\t\t\tif (xs > 3 && !FlipCoin()) {\r\n\t\t\t\t\tfor (int k = xc; k < i; k++) {\r\n\t\t\t\t\t\tconst int rv = GenerateRnd(2);\r\n\t\t\t\t\t\tdungeon[k][j + 1] = rv;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\txs = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\tint ys = 0;\r\n\t\tfor (int j = 0; j < 37; j++) {\r\n\t\t\tif (dungeon[i][j] == 0 && dungeon[i + 1][j] == 1) {\r\n\t\t\t\tif (ys == 0) {\r\n\t\t\t\t\tyc = j;\r\n\t\t\t\t}\r\n\t\t\t\tys++;\r\n\t\t\t} else {\r\n\t\t\t\tif (ys > 3 && !FlipCoin()) {\r\n\t\t\t\t\tfor (int k = yc; k < j; k++) {\r\n\t\t\t\t\t\tconst int rv = GenerateRnd(2);\r\n\t\t\t\t\t\tdungeon[i][k] = rv;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tys = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\tint ys = 0;\r\n\t\tfor (int j = 0; j < 37; j++) {\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i + 1][j] == 0) {\r\n\t\t\t\tif (ys == 0) {\r\n\t\t\t\t\tyc = j;\r\n\t\t\t\t}\r\n\t\t\t\tys++;\r\n\t\t\t} else {\r\n\t\t\t\tif (ys > 3 && !FlipCoin()) {\r\n\t\t\t\t\tfor (int k = yc; k < j; k++) {\r\n\t\t\t\t\t\tconst int rv = GenerateRnd(2);\r\n\t\t\t\t\t\tdungeon[i + 1][k] = rv;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tys = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Edges()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tdungeon[DMAXX - 1][j] = 0;\r\n\t}\r\n\tfor (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\tdungeon[i][DMAXY - 1] = 0;\r\n\t}\r\n}\r\n\r\nint GetFloorArea()\r\n{\r\n\tint gfa = 0;\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\tgfa += dungeon[i][j];\r\n\t\t}\r\n\t}\r\n\r\n\treturn gfa;\r\n}\r\n\r\nvoid MakeMegas()\r\n{\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\t\tint v = dungeon[i + 1][j + 1] + 2 * dungeon[i][j + 1] + 4 * dungeon[i + 1][j] + 8 * dungeon[i][j];\r\n\t\t\tif (v == 6) {\r\n\t\t\t\tv = PickRandomlyAmong({ 12, 5 });\r\n\t\t\t}\r\n\t\t\tif (v == 9) {\r\n\t\t\t\tv = PickRandomlyAmong({ 13, 14 });\r\n\t\t\t}\r\n\t\t\tdungeon[i][j] = L3ConvTbl[v];\r\n\t\t}\r\n\t\tdungeon[DMAXX - 1][j] = 8;\r\n\t}\r\n\tfor (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\tdungeon[i][DMAXY - 1] = 8;\r\n\t}\r\n}\r\n\r\nvoid River()\r\n{\r\n\tint dir;\r\n\tint nodir;\r\n\tint river[3][100];\r\n\tint riveramt;\r\n\r\n\tint rivercnt = 0;\r\n\tint tries = 0;\r\n\t/// BUGFIX: pdir is uninitialized, add code `pdir = -1;`(fixed)\r\n\tint pdir = -1;\r\n\r\n\twhile (tries < 200 && rivercnt < 4) {\r\n\t\tbool bail = false;\r\n\t\twhile (!bail && tries < 200) {\r\n\t\t\ttries++;\r\n\t\t\tint rx = 0;\r\n\t\t\tint ry = 0;\r\n\t\t\tint i = 0;\r\n\t\t\t// BUGFIX: Replace with `(ry >= DMAXY || dungeon[rx][ry] < 25 || dungeon[rx][ry] > 28) && i < 100` (fixed)\r\n\t\t\twhile ((ry >= DMAXY || dungeon[rx][ry] < 25 || dungeon[rx][ry] > 28) && i < 100) {\r\n\t\t\t\trx = GenerateRnd(DMAXX);\r\n\t\t\t\try = GenerateRnd(DMAXY);\r\n\t\t\t\ti++;\r\n\t\t\t\t// BUGFIX: Move `ry < DMAXY` check before dungeon checks (fixed)\r\n\t\t\t\twhile (ry < DMAXY && (dungeon[rx][ry] < 25 || dungeon[rx][ry] > 28)) {\r\n\t\t\t\t\trx++;\r\n\t\t\t\t\tif (rx >= DMAXX) {\r\n\t\t\t\t\t\trx = 0;\r\n\t\t\t\t\t\try++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Continue if `ry >= DMAXY` (fixed)\r\n\t\t\tif (ry >= DMAXY)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (i >= 100) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tswitch (dungeon[rx][ry]) {\r\n\t\t\tcase 25:\r\n\t\t\t\tdir = 3;\r\n\t\t\t\tnodir = 2;\r\n\t\t\t\triver[2][0] = 40;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 26:\r\n\t\t\t\tdir = 0;\r\n\t\t\t\tnodir = 1;\r\n\t\t\t\triver[2][0] = 38;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 27:\r\n\t\t\t\tdir = 1;\r\n\t\t\t\tnodir = 0;\r\n\t\t\t\triver[2][0] = 41;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 28:\r\n\t\t\t\tdir = 2;\r\n\t\t\t\tnodir = 3;\r\n\t\t\t\triver[2][0] = 39;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\triver[0][0] = rx;\r\n\t\t\triver[1][0] = ry;\r\n\t\t\triveramt = 1;\r\n\t\t\tint nodir2 = 4;\r\n\t\t\tint dircheck = 0;\r\n\t\t\twhile (dircheck < 4 && riveramt < 100) {\r\n\t\t\t\tconst int px = rx;\r\n\t\t\t\tconst int py = ry;\r\n\t\t\t\tif (dircheck == 0) {\r\n\t\t\t\t\tdir = GenerateRnd(4);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdir = (dir + 1) & 3;\r\n\t\t\t\t}\r\n\t\t\t\tdircheck++;\r\n\t\t\t\twhile (dir == nodir || dir == nodir2) {\r\n\t\t\t\t\tdir = (dir + 1) & 3;\r\n\t\t\t\t\tdircheck++;\r\n\t\t\t\t}\r\n\t\t\t\tif (dir == 0 && ry > 0) {\r\n\t\t\t\t\try--;\r\n\t\t\t\t}\r\n\t\t\t\tif (dir == 1 && ry < DMAXY) {\r\n\t\t\t\t\try++;\r\n\t\t\t\t}\r\n\t\t\t\tif (dir == 2 && rx < DMAXX) {\r\n\t\t\t\t\trx++;\r\n\t\t\t\t}\r\n\t\t\t\tif (dir == 3 && rx > 0) {\r\n\t\t\t\t\trx--;\r\n\t\t\t\t}\r\n\t\t\t\tif (dungeon[rx][ry] == 7) {\r\n\t\t\t\t\tdircheck = 0;\r\n\t\t\t\t\tif (dir < 2) {\r\n\t\t\t\t\t\triver[2][riveramt] = PickRandomlyAmong({ 17, 18 });\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (dir > 1) {\r\n\t\t\t\t\t\triver[2][riveramt] = PickRandomlyAmong({ 15, 16 });\r\n\t\t\t\t\t}\r\n\t\t\t\t\triver[0][riveramt] = rx;\r\n\t\t\t\t\triver[1][riveramt] = ry;\r\n\t\t\t\t\triveramt++;\r\n\t\t\t\t\tif ((dir == 0 && pdir == 2) || (dir == 3 && pdir == 1)) {\r\n\t\t\t\t\t\tif (riveramt > 2) {\r\n\t\t\t\t\t\t\triver[2][riveramt - 2] = 22;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (dir == 0) {\r\n\t\t\t\t\t\t\tnodir2 = 1;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnodir2 = 2;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ((dir == 0 && pdir == 3) || (dir == 2 && pdir == 1)) {\r\n\t\t\t\t\t\tif (riveramt > 2) {\r\n\t\t\t\t\t\t\triver[2][riveramt - 2] = 21;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (dir == 0) {\r\n\t\t\t\t\t\t\tnodir2 = 1;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnodir2 = 3;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ((dir == 1 && pdir == 2) || (dir == 3 && pdir == 0)) {\r\n\t\t\t\t\t\tif (riveramt > 2) {\r\n\t\t\t\t\t\t\triver[2][riveramt - 2] = 20;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (dir == 1) {\r\n\t\t\t\t\t\t\tnodir2 = 0;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnodir2 = 2;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ((dir == 1 && pdir == 3) || (dir == 2 && pdir == 0)) {\r\n\t\t\t\t\t\tif (riveramt > 2) {\r\n\t\t\t\t\t\t\triver[2][riveramt - 2] = 19;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (dir == 1) {\r\n\t\t\t\t\t\t\tnodir2 = 0;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnodir2 = 3;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpdir = dir;\r\n\t\t\t\t} else {\r\n\t\t\t\t\trx = px;\r\n\t\t\t\t\try = py;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Check `ry >= 2` (fixed)\r\n\t\t\tif (dir == 0 && ry >= 2 && dungeon[rx][ry - 1] == 10 && dungeon[rx][ry - 2] == 8) {\r\n\t\t\t\triver[0][riveramt] = rx;\r\n\t\t\t\triver[1][riveramt] = ry - 1;\r\n\t\t\t\triver[2][riveramt] = 24;\r\n\t\t\t\tif (pdir == 2) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 22;\r\n\t\t\t\t}\r\n\t\t\t\tif (pdir == 3) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 21;\r\n\t\t\t\t}\r\n\t\t\t\tbail = true;\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Check `ry + 2 < DMAXY` (fixed)\r\n\t\t\tif (dir == 1 && ry + 2 < DMAXY && dungeon[rx][ry + 1] == 2 && dungeon[rx][ry + 2] == 8) {\r\n\t\t\t\triver[0][riveramt] = rx;\r\n\t\t\t\triver[1][riveramt] = ry + 1;\r\n\t\t\t\triver[2][riveramt] = 42;\r\n\t\t\t\tif (pdir == 2) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 20;\r\n\t\t\t\t}\r\n\t\t\t\tif (pdir == 3) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 19;\r\n\t\t\t\t}\r\n\t\t\t\tbail = true;\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Check `rx + 2 < DMAXX` (fixed)\r\n\t\t\tif (dir == 2 && rx + 2 < DMAXX && dungeon[rx + 1][ry] == 4 && dungeon[rx + 2][ry] == 8) {\r\n\t\t\t\triver[0][riveramt] = rx + 1;\r\n\t\t\t\triver[1][riveramt] = ry;\r\n\t\t\t\triver[2][riveramt] = 43;\r\n\t\t\t\tif (pdir == 0) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 19;\r\n\t\t\t\t}\r\n\t\t\t\tif (pdir == 1) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 21;\r\n\t\t\t\t}\r\n\t\t\t\tbail = true;\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Check `rx >= 2` (fixed)\r\n\t\t\tif (dir == 3 && rx >= 2 && dungeon[rx - 1][ry] == 9 && dungeon[rx - 2][ry] == 8) {\r\n\t\t\t\triver[0][riveramt] = rx - 1;\r\n\t\t\t\triver[1][riveramt] = ry;\r\n\t\t\t\triver[2][riveramt] = 23;\r\n\t\t\t\tif (pdir == 0) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 20;\r\n\t\t\t\t}\r\n\t\t\t\tif (pdir == 1) {\r\n\t\t\t\t\triver[2][riveramt - 1] = 22;\r\n\t\t\t\t}\r\n\t\t\t\tbail = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (bail && riveramt < 7) {\r\n\t\t\tbail = false;\r\n\t\t}\r\n\t\tif (bail) {\r\n\t\t\tint found = 0;\r\n\t\t\tint lpcnt = 0;\r\n\t\t\tint bridge;\r\n\t\t\twhile (found == 0 && lpcnt < 30) {\r\n\t\t\t\tlpcnt++;\r\n\t\t\t\tbridge = GenerateRnd(riveramt);\r\n\t\t\t\tif ((river[2][bridge] == 15 || river[2][bridge] == 16)\r\n\t\t\t\t    && dungeon[river[0][bridge]][river[1][bridge] - 1] == 7\r\n\t\t\t\t    && dungeon[river[0][bridge]][river[1][bridge] + 1] == 7) {\r\n\t\t\t\t\tfound = 1;\r\n\t\t\t\t}\r\n\t\t\t\tif ((river[2][bridge] == 17 || river[2][bridge] == 18)\r\n\t\t\t\t    && dungeon[river[0][bridge] - 1][river[1][bridge]] == 7\r\n\t\t\t\t    && dungeon[river[0][bridge] + 1][river[1][bridge]] == 7) {\r\n\t\t\t\t\tfound = 2;\r\n\t\t\t\t}\r\n\t\t\t\tfor (int i = 0; i < riveramt && found != 0; i++) {\r\n\t\t\t\t\tif (found == 1\r\n\t\t\t\t\t    && (river[1][bridge] - 1 == river[1][i] || river[1][bridge] + 1 == river[1][i])\r\n\t\t\t\t\t    && river[0][bridge] == river[0][i]) {\r\n\t\t\t\t\t\tfound = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (found == 2\r\n\t\t\t\t\t    && (river[0][bridge] - 1 == river[0][i] || river[0][bridge] + 1 == river[0][i])\r\n\t\t\t\t\t    && river[1][bridge] == river[1][i]) {\r\n\t\t\t\t\t\tfound = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (found != 0) {\r\n\t\t\t\tif (found == 1) {\r\n\t\t\t\t\triver[2][bridge] = 44;\r\n\t\t\t\t} else {\r\n\t\t\t\t\triver[2][bridge] = 45;\r\n\t\t\t\t}\r\n\t\t\t\trivercnt++;\r\n\t\t\t\tfor (bridge = 0; bridge <= riveramt; bridge++) {\r\n\t\t\t\t\tdungeon[river[0][bridge]][river[1][bridge]] = river[2][bridge];\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tbail = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Spawn(int x, int y, int *totarea);\r\n\r\nbool SpawnEdge(int x, int y, int *totarea)\r\n{\r\n\tconstexpr uint8_t spawntable[15] = { 0x00, 0x0A, 0x43, 0x05, 0x2c, 0x06, 0x09, 0x00, 0x00, 0x1c, 0x83, 0x06, 0x09, 0x0A, 0x05 };\r\n\r\n\tif (*totarea > 40) {\r\n\t\treturn true;\r\n\t}\r\n\tif (x < 0 || y < 0 || x >= DMAXX || y >= DMAXY) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((dungeon[x][y] & 0x80) != 0) {\r\n\t\treturn false;\r\n\t}\r\n\tif (dungeon[x][y] > 15) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconst uint8_t i = dungeon[x][y];\r\n\tdungeon[x][y] |= 0x80;\r\n\t*totarea += 1;\r\n\r\n\tif ((spawntable[i] & 8) != 0 && SpawnEdge(x, y - 1, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((spawntable[i] & 4) != 0 && SpawnEdge(x, y + 1, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((spawntable[i] & 2) != 0 && SpawnEdge(x + 1, y, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((spawntable[i] & 1) != 0 && SpawnEdge(x - 1, y, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((spawntable[i] & 0x80) != 0 && Spawn(x, y - 1, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((spawntable[i] & 0x40) != 0 && Spawn(x, y + 1, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((spawntable[i] & 0x20) != 0 && Spawn(x + 1, y, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((spawntable[i] & 0x10) != 0 && Spawn(x - 1, y, totarea)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool Spawn(int x, int y, int *totarea)\r\n{\r\n\tconstexpr uint8_t spawntable[15] = { 0x00, 0x0A, 0x03, 0x05, 0x0C, 0x06, 0x09, 0x00, 0x00, 0x0C, 0x03, 0x06, 0x09, 0x0A, 0x05 };\r\n\r\n\tif (*totarea > 40) {\r\n\t\treturn true;\r\n\t}\r\n\tif (x < 0 || y < 0 || x >= DMAXX || y >= DMAXY) {\r\n\t\treturn true;\r\n\t}\r\n\tif ((dungeon[x][y] & 0x80) != 0) {\r\n\t\treturn false;\r\n\t}\r\n\tif (dungeon[x][y] > 15) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconst uint8_t i = dungeon[x][y];\r\n\tdungeon[x][y] |= 0x80;\r\n\t*totarea += 1;\r\n\r\n\tif (i != 8) {\r\n\t\tif ((spawntable[i] & 8) != 0 && SpawnEdge(x, y - 1, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif ((spawntable[i] & 4) != 0 && SpawnEdge(x, y + 1, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif ((spawntable[i] & 2) != 0 && SpawnEdge(x + 1, y, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif ((spawntable[i] & 1) != 0 && SpawnEdge(x - 1, y, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t} else {\r\n\t\tif (Spawn(x + 1, y, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (Spawn(x - 1, y, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (Spawn(x, y + 1, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (Spawn(x, y - 1, totarea)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanReplaceTile(uint8_t replace, Point tile)\r\n{\r\n\tif (replace < 84 || replace > 100) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// BUGFIX: p2 is a workaround for a bug, only p1 should have been used (fixing this breaks compatibility)\r\n\tconstexpr auto ComparisonWithBoundsCheck = [](Point p1, Point p2) {\r\n\t\treturn (p1.x >= 0 && p1.x < DMAXX && p1.y >= 0 && p1.y < DMAXY)\r\n\t\t    && (p2.x >= 0 && p2.x < DMAXX && p2.y >= 0 && p2.y < DMAXY)\r\n\t\t    && (dungeon[p1.x][p1.y] >= 84 && dungeon[p2.x][p2.y] <= 100);\r\n\t};\r\n\tif (ComparisonWithBoundsCheck(tile + Direction::NorthWest, tile + Direction::NorthWest)\r\n\t    || ComparisonWithBoundsCheck(tile + Direction::SouthEast, tile + Direction::NorthWest)\r\n\t    || ComparisonWithBoundsCheck(tile + Direction::SouthWest, tile + Direction::NorthWest)\r\n\t    || ComparisonWithBoundsCheck(tile + Direction::NorthEast, tile + Direction::NorthWest)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * @brief Randomly places the given miniset throughout the dungeon wherever it would fit\r\n * @return true if at least one instance was placed\r\n */\r\nbool PlaceMiniSetRandom(const Miniset &miniset, int rndper)\r\n{\r\n\tconst WorldTileCoord sw = miniset.size.width;\r\n\tconst WorldTileCoord sh = miniset.size.height;\r\n\r\n\tbool placed = false;\r\n\tfor (WorldTileCoord sy = 0; sy < DMAXY - sh; sy++) {\r\n\t\tfor (WorldTileCoord sx = 0; sx < DMAXX - sw; sx++) {\r\n\t\t\tif (!miniset.matches({ sx, sy }))\r\n\t\t\t\tcontinue;\r\n\t\t\t// BUGFIX: This should not be applied to Nest levels\r\n\t\t\tif (!CanReplaceTile(miniset.replace[0][0], { sx, sy }))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (GenerateRnd(100) >= rndper)\r\n\t\t\t\tcontinue;\r\n\t\t\tminiset.place({ sx, sy });\r\n\t\t\tplaced = true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn placed;\r\n}\r\n\r\nvoid PlaceMiniSetRandom1x1(uint8_t search, uint8_t replace, int rndper)\r\n{\r\n\tPlaceMiniSetRandom({ { 1, 1 }, { { search } }, { { replace } } }, rndper);\r\n}\r\n\r\nbool PlaceSlimePool()\r\n{\r\n\tint lavapool = 0;\r\n\r\n\tif (PlaceMiniSetRandom(HivePattern41, 30))\r\n\t\tlavapool++;\r\n\tif (PlaceMiniSetRandom(HivePattern42, 40))\r\n\t\tlavapool++;\r\n\tif (PlaceMiniSetRandom(HivePattern39, 50))\r\n\t\tlavapool++;\r\n\tif (PlaceMiniSetRandom(HivePattern40, 60))\r\n\t\tlavapool++;\r\n\r\n\treturn lavapool >= 3;\r\n}\r\n\r\n/**\r\n * Flood fills dirt and wall tiles looking for\r\n * an area of at most 40 tiles and disconnected from the map edge.\r\n * If it finds one, converts it to lava tiles and return true.\r\n */\r\nbool PlaceLavaPool()\r\n{\r\n\tconstexpr uint8_t Poolsub[15] = { 0, 35, 26, 36, 25, 29, 34, 7, 33, 28, 27, 37, 32, 31, 30 };\r\n\r\n\tbool lavePoolPlaced = false;\r\n\r\n\tfor (int duny = 0; duny < DMAXY; duny++) {\r\n\t\tfor (int dunx = 0; dunx < DMAXY; dunx++) {\r\n\t\t\tif (dungeon[dunx][duny] != 8) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tdungeon[dunx][duny] |= 0x80;\r\n\t\t\tint totarea = 1;\r\n\t\t\tbool found = true;\r\n\t\t\tif (dunx + 1 < DMAXX) {\r\n\t\t\t\tfound = Spawn(dunx + 1, duny, &totarea);\r\n\t\t\t}\r\n\t\t\tif (dunx - 1 > 0 && !found) {\r\n\t\t\t\tfound = Spawn(dunx - 1, duny, &totarea);\r\n\t\t\t} else {\r\n\t\t\t\tfound = true;\r\n\t\t\t}\r\n\t\t\tif (duny + 1 < DMAXY && !found) {\r\n\t\t\t\tfound = Spawn(dunx, duny + 1, &totarea);\r\n\t\t\t} else {\r\n\t\t\t\tfound = true;\r\n\t\t\t}\r\n\t\t\tif (duny - 1 > 0 && !found) {\r\n\t\t\t\tfound = Spawn(dunx, duny - 1, &totarea);\r\n\t\t\t} else {\r\n\t\t\t\tfound = true;\r\n\t\t\t}\r\n\t\t\tconst bool placePool = GenerateRnd(100) < 25;\r\n\t\t\tfor (int j = std::max(duny - totarea, 0); j < std::min(duny + totarea, DMAXY); j++) {\r\n\t\t\t\tfor (int i = std::max(dunx - totarea, 0); i < std::min(dunx + totarea, DMAXX); i++) {\r\n\t\t\t\t\t// BUGFIX: In the following swap the order to first do the\r\n\t\t\t\t\t// index checks and only then access dungeon[i][j] (fixed)\r\n\t\t\t\t\tif ((dungeon[i][j] & 0x80) != 0) {\r\n\t\t\t\t\t\tdungeon[i][j] &= ~0x80;\r\n\t\t\t\t\t\tif (totarea > 4 && placePool && !found) {\r\n\t\t\t\t\t\t\tconst uint8_t k = Poolsub[dungeon[i][j]];\r\n\t\t\t\t\t\t\tif (k != 0 && k <= 37) {\r\n\t\t\t\t\t\t\t\tdungeon[i][j] = k;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tlavePoolPlaced = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn lavePoolPlaced;\r\n}\r\n\r\nbool PlacePool()\r\n{\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\treturn PlaceSlimePool();\r\n\t}\r\n\r\n\treturn PlaceLavaPool();\r\n}\r\n\r\n/**\r\n * @brief Fill lava pools correctly, because River() only generates the edges.\r\n */\r\nvoid PoolFix()\r\n{\r\n\tfor (const Point tile : PointsInRectangle(Rectangle { { 1, 1 }, { DMAXX - 2, DMAXY - 2 } })) {\r\n\t\t// Check if the tile is the default dirt ceiling tile\r\n\t\tif (dungeon[tile.x][tile.y] != 8)\r\n\t\t\tcontinue;\r\n\r\n\t\tfor (const Point adjacentTiles : PointsInRectangle(Rectangle { tile - Displacement(1, 1), { 3, 3 } })) {\r\n\t\t\tconst int tileId = dungeon[adjacentTiles.x][adjacentTiles.y];\r\n\t\t\t// Check if the adjacent tile is a ground lava tile\r\n\t\t\tif (tileId >= 25 && tileId <= 41) {\r\n\t\t\t\t// A ground lava tile can never be directly connected to our ceiling tile.\r\n\t\t\t\t// There must always be a kind of transition tile between (from ground to ceiling).\r\n\t\t\t\t// That means our tile is part of a lava pool (and was missed in River()), so we should change our tile to a ground lava tile.\r\n\t\t\t\tdungeon[tile.x][tile.y] = 33;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool FenceVerticalUp(int i, int y)\r\n{\r\n\tif ((dungeon[i + 1][y] > 152 || dungeon[i + 1][y] < 130)\r\n\t    && (dungeon[i - 1][y] > 152 || dungeon[i - 1][y] < 130)) {\r\n\t\tif (IsAnyOf(dungeon[i][y], 7, 10, 126, 129, 134, 136)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool FenceVerticalDown(int i, int y)\r\n{\r\n\tif ((dungeon[i + 1][y] > 152 || dungeon[i + 1][y] < 130)\r\n\t    && (dungeon[i - 1][y] > 152 || dungeon[i - 1][y] < 130)) {\r\n\t\tif (IsAnyOf(dungeon[i][y], 2, 7, 134, 136)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool FenceHorizontalLeft(int x, int j)\r\n{\r\n\tif ((dungeon[x][j + 1] > 152 || dungeon[x][j + 1] < 130)\r\n\t    && (dungeon[x][j - 1] > 152 || dungeon[x][j - 1] < 130)) {\r\n\t\tif (IsAnyOf(dungeon[x][j], 7, 9, 121, 124, 135, 137)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool FenceHorizontalRight(int x, int j)\r\n{\r\n\tif ((dungeon[x][j + 1] > 152 || dungeon[x][j + 1] < 130)\r\n\t    && (dungeon[x][j - 1] > 152 || dungeon[x][j - 1] < 130)) {\r\n\t\tif (IsAnyOf(dungeon[x][j], 4, 7, 135, 137)) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid AddFenceDoors()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 7) {\r\n\t\t\t\tif (dungeon[i - 1][j] <= 152 && dungeon[i - 1][j] >= 130\r\n\t\t\t\t    && dungeon[i + 1][j] <= 152 && dungeon[i + 1][j] >= 130) {\r\n\t\t\t\t\tdungeon[i][j] = 146;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 7) {\r\n\t\t\t\tif (dungeon[i][j - 1] <= 152 && dungeon[i][j - 1] >= 130\r\n\t\t\t\t    && dungeon[i][j + 1] <= 152 && dungeon[i][j + 1] >= 130) {\r\n\t\t\t\t\tdungeon[i][j] = 147;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FenceDoorFix()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 146) {\r\n\t\t\t\tif (dungeon[i + 1][j] > 152 || dungeon[i + 1][j] < 130\r\n\t\t\t\t    || dungeon[i - 1][j] > 152 || dungeon[i - 1][j] < 130) {\r\n\t\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 146) {\r\n\t\t\t\tif (IsNoneOf(dungeon[i + 1][j], 130, 132, 133, 134, 136, 138, 140) && IsNoneOf(dungeon[i - 1][j], 130, 132, 133, 134, 136, 138, 140)) {\r\n\t\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 147) {\r\n\t\t\t\tif (dungeon[i][j + 1] > 152 || dungeon[i][j + 1] < 130\r\n\t\t\t\t    || dungeon[i][j - 1] > 152 || dungeon[i][j - 1] < 130) {\r\n\t\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 147) {\r\n\t\t\t\tif (IsNoneOf(dungeon[i][j + 1], 131, 132, 133, 135, 137, 138, 139) && IsNoneOf(dungeon[i][j - 1], 131, 132, 133, 135, 137, 138, 139)) {\r\n\t\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Fence()\r\n{\r\n\tfor (int j = 1; j < DMAXY - 1; j++) {     // BUGFIX: Change '0' to '1' (fixed)\r\n\t\tfor (int i = 1; i < DMAXX - 1; i++) { // BUGFIX: Change '0' to '1' (fixed)\r\n\t\t\tif (dungeon[i][j] == 10 && !FlipCoin()) {\r\n\t\t\t\tint x = i;\r\n\t\t\t\twhile (dungeon[x][j] == 10) {\r\n\t\t\t\t\tx++;\r\n\t\t\t\t}\r\n\t\t\t\tx--;\r\n\t\t\t\tif (x - i > 0) {\r\n\t\t\t\t\tdungeon[i][j] = 127;\r\n\t\t\t\t\tfor (int xx = i + 1; xx < x; xx++) {\r\n\t\t\t\t\t\tdungeon[xx][j] = PickRandomlyAmong({ 129, 126 });\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdungeon[x][j] = 128;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 9 && !FlipCoin()) {\r\n\t\t\t\tint y = j;\r\n\t\t\t\twhile (dungeon[i][y] == 9) {\r\n\t\t\t\t\ty++;\r\n\t\t\t\t}\r\n\t\t\t\ty--;\r\n\t\t\t\tif (y - j > 0) {\r\n\t\t\t\t\tdungeon[i][j] = 123;\r\n\t\t\t\t\tfor (int yy = j + 1; yy < y; yy++) {\r\n\t\t\t\t\t\tdungeon[i][yy] = PickRandomlyAmong({ 124, 121 });\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdungeon[i][y] = 122;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i + 1][j] == 10 && dungeon[i][j + 1] == 9 && !FlipCoin()) {\r\n\t\t\t\tdungeon[i][j] = 125;\r\n\t\t\t\tint x = i + 1;\r\n\t\t\t\twhile (dungeon[x][j] == 10) {\r\n\t\t\t\t\tx++;\r\n\t\t\t\t}\r\n\t\t\t\tx--;\r\n\t\t\t\tfor (int xx = i + 1; xx < x; xx++) {\r\n\t\t\t\t\tdungeon[xx][j] = PickRandomlyAmong({ 129, 126 });\r\n\t\t\t\t}\r\n\t\t\t\tdungeon[x][j] = 128;\r\n\t\t\t\tint y = j + 1;\r\n\t\t\t\twhile (dungeon[i][y] == 9) {\r\n\t\t\t\t\ty++;\r\n\t\t\t\t}\r\n\t\t\t\ty--;\r\n\t\t\t\tfor (int yy = j + 1; yy < y; yy++) {\r\n\t\t\t\t\tdungeon[i][yy] = PickRandomlyAmong({ 124, 121 });\r\n\t\t\t\t}\r\n\t\t\t\tdungeon[i][y] = 122;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (WorldTileCoord j = 1; j < DMAXY; j++) {     // BUGFIX: Change '0' to '1' (fixed)\r\n\t\tfor (WorldTileCoord i = 1; i < DMAXX; i++) { // BUGFIX: Change '0' to '1' (fixed)\r\n\t\t\t// note the comma operator is used here to advance the RNG state\r\n\t\t\tif (dungeon[i][j] == 7 && (DiscardRandomValues(1), !IsNearThemeRoom({ i, j }))) {\r\n\t\t\t\tif (FlipCoin()) {\r\n\t\t\t\t\tint y1 = j;\r\n\t\t\t\t\t// BUGFIX: Check `y1 >= 0` first (fixed)\r\n\t\t\t\t\twhile (y1 >= 0 && FenceVerticalUp(i, y1)) {\r\n\t\t\t\t\t\ty1--;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ty1++;\r\n\t\t\t\t\tint y2 = j;\r\n\t\t\t\t\t// BUGFIX: Check `y2 < DMAXY` first (fixed)\r\n\t\t\t\t\twhile (y2 < DMAXY && FenceVerticalDown(i, y2)) {\r\n\t\t\t\t\t\ty2++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ty2--;\r\n\t\t\t\t\tbool skip = true;\r\n\t\t\t\t\tif (dungeon[i][y1] == 7) {\r\n\t\t\t\t\t\tskip = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (dungeon[i][y2] == 7) {\r\n\t\t\t\t\t\tskip = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (y2 - y1 > 1 && skip) {\r\n\t\t\t\t\t\tconst int rp = GenerateRnd(y2 - y1 - 1) + y1 + 1;\r\n\t\t\t\t\t\tfor (int y = y1; y <= y2; y++) {\r\n\t\t\t\t\t\t\tif (y == rp) {\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[i][y] == 7) {\r\n\t\t\t\t\t\t\t\tdungeon[i][y] = PickRandomlyAmong({ 137, 135 });\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[i][y] == 10) {\r\n\t\t\t\t\t\t\t\tdungeon[i][y] = 131;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[i][y] == 126) {\r\n\t\t\t\t\t\t\t\tdungeon[i][y] = 133;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[i][y] == 129) {\r\n\t\t\t\t\t\t\t\tdungeon[i][y] = 133;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[i][y] == 2) {\r\n\t\t\t\t\t\t\t\tdungeon[i][y] = 139;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[i][y] == 134) {\r\n\t\t\t\t\t\t\t\tdungeon[i][y] = 138;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[i][y] == 136) {\r\n\t\t\t\t\t\t\t\tdungeon[i][y] = 138;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tint x1 = i;\r\n\t\t\t\t\t// BUGFIX: Check `x1 >= 0` first (fixed)\r\n\t\t\t\t\twhile (x1 >= 0 && FenceHorizontalLeft(x1, j)) {\r\n\t\t\t\t\t\tx1--;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tx1++;\r\n\t\t\t\t\tint x2 = i;\r\n\t\t\t\t\t// BUGFIX: Check `x2 < DMAXX` first (fixed)\r\n\t\t\t\t\twhile (x2 < DMAXX && FenceHorizontalRight(x2, j)) {\r\n\t\t\t\t\t\tx2++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tx2--;\r\n\t\t\t\t\tbool skip = true;\r\n\t\t\t\t\tif (dungeon[x1][j] == 7) {\r\n\t\t\t\t\t\tskip = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (dungeon[x2][j] == 7) {\r\n\t\t\t\t\t\tskip = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (x2 - x1 > 1 && skip) {\r\n\t\t\t\t\t\tconst int rp = GenerateRnd(x2 - x1 - 1) + x1 + 1;\r\n\t\t\t\t\t\tfor (int x = x1; x <= x2; x++) {\r\n\t\t\t\t\t\t\tif (x == rp) {\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[x][j] == 7) {\r\n\t\t\t\t\t\t\t\tdungeon[x][j] = PickRandomlyAmong({ 136, 134 });\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[x][j] == 9) {\r\n\t\t\t\t\t\t\t\tdungeon[x][j] = 130;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[x][j] == 121) {\r\n\t\t\t\t\t\t\t\tdungeon[x][j] = 132;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[x][j] == 124) {\r\n\t\t\t\t\t\t\t\tdungeon[x][j] = 132;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[x][j] == 4) {\r\n\t\t\t\t\t\t\t\tdungeon[x][j] = 140;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[x][j] == 135) {\r\n\t\t\t\t\t\t\t\tdungeon[x][j] = 138;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (dungeon[x][j] == 137) {\r\n\t\t\t\t\t\t\t\tdungeon[x][j] = 138;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tAddFenceDoors();\r\n\tFenceDoorFix();\r\n}\r\n\r\nbool PlaceAnvil()\r\n{\r\n\tconst std::unique_ptr<uint16_t[]> setPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l3data\\\\anvil.dun\");\r\n\t// growing the size by 2 to allow a 1 tile border on all sides\r\n\tconst WorldTileSize areaSize = GetDunSize(setPieceData.get()) + 2;\r\n\tWorldTileCoord sx = GenerateRnd(DMAXX - areaSize.width);\r\n\tWorldTileCoord sy = GenerateRnd(DMAXY - areaSize.height);\r\n\r\n\tfor (int tries = 0;; tries++, sx++) {\r\n\t\tif (tries > 198)\r\n\t\t\treturn false;\r\n\r\n\t\tif (sx == DMAXX - areaSize.width) {\r\n\t\t\tsx = 0;\r\n\t\t\tsy++;\r\n\t\t\tif (sy == DMAXY - areaSize.height) {\r\n\t\t\t\tsy = 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tbool found = true;\r\n\t\tfor (const WorldTilePosition tile : PointsInRectangle(WorldTileRectangle { { sx, sy }, areaSize })) {\r\n\t\t\tif (Protected.test(tile.x, tile.y) || dungeon[tile.x][tile.y] != 7) {\r\n\t\t\t\tfound = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (found)\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tPlaceDunTiles(setPieceData.get(), { sx + 1, sy + 1 }, 7);\r\n\tSetPiece = { { sx, sy }, areaSize };\r\n\r\n\tfor (const WorldTilePosition tile : PointsInRectangle(SetPiece)) {\r\n\t\tProtected.set(tile.x, tile.y);\r\n\t}\r\n\r\n\t// Hack to avoid rivers entering the island, reversed later\r\n\tdungeon[SetPiece.position.x + 7][SetPiece.position.y + 5] = 2;\r\n\tdungeon[SetPiece.position.x + 8][SetPiece.position.y + 5] = 2;\r\n\tdungeon[SetPiece.position.x + 9][SetPiece.position.y + 5] = 2;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid Warp()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 125 && dungeon[i + 1][j] == 125 && dungeon[i][j + 1] == 125 && dungeon[i + 1][j + 1] == 125) {\r\n\t\t\t\tdungeon[i][j] = 156;\r\n\t\t\t\tdungeon[i + 1][j] = 155;\r\n\t\t\t\tdungeon[i][j + 1] = 153;\r\n\t\t\t\tdungeon[i + 1][j + 1] = 154;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 5 && dungeon[i + 1][j + 1] == 7) {\r\n\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid HallOfHeroes()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 5 && dungeon[i + 1][j + 1] == 7) {\r\n\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 5 && dungeon[i + 1][j + 1] == 12 && dungeon[i + 1][j] == 7) {\r\n\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t\tdungeon[i][j + 1] = 7;\r\n\t\t\t\tdungeon[i + 1][j + 1] = 7;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 5 && dungeon[i + 1][j + 1] == 12 && dungeon[i][j + 1] == 7) {\r\n\t\t\t\tdungeon[i][j] = 7;\r\n\t\t\t\tdungeon[i + 1][j] = 7;\r\n\t\t\t\tdungeon[i + 1][j + 1] = 7;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LockRectangle(int x, int y)\r\n{\r\n\tif (!DungeonMask.test(x, y)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tDungeonMask.reset(x, y);\r\n\tlockoutcnt++;\r\n\tLockRectangle(x, y - 1);\r\n\tLockRectangle(x, y + 1);\r\n\tLockRectangle(x - 1, y);\r\n\tLockRectangle(x + 1, y);\r\n}\r\n\r\nbool Lockout()\r\n{\r\n\tDungeonMask.reset();\r\n\r\n\tint fx;\r\n\tint fy;\r\n\r\n\tint t = 0;\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] != 0) {\r\n\t\t\t\tDungeonMask.set(i, j);\r\n\t\t\t\tfx = i;\r\n\t\t\t\tfy = j;\r\n\t\t\t\tt++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tlockoutcnt = 0;\r\n\tLockRectangle(fx, fy);\r\n\r\n\treturn t == lockoutcnt;\r\n}\r\n\r\nbool PlaceCaveStairs(lvl_entry entry)\r\n{\r\n\tstd::optional<Point> position;\r\n\r\n\t// Place stairs up\r\n\tposition = PlaceMiniSet(L3UP);\r\n\tif (!position)\r\n\t\treturn false;\r\n\tif (entry == ENTRY_MAIN)\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 1, 3 };\r\n\r\n\t// Place stairs down\r\n\tposition = PlaceMiniSet(L3DOWN);\r\n\tif (!position)\r\n\t\treturn false;\r\n\tif (entry == ENTRY_PREV)\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 3, 1 };\r\n\r\n\t// Place town warp stairs\r\n\tif (currlevel == 9) {\r\n\t\tposition = PlaceMiniSet(L3HOLDWARP);\r\n\t\tif (!position)\r\n\t\t\treturn false;\r\n\t\tif (entry == ENTRY_TWARPDN)\r\n\t\t\tViewPosition = position->megaToWorld() + Displacement { 1, 3 };\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool PlaceNestStairs(lvl_entry entry)\r\n{\r\n\tstd::optional<Point> position;\r\n\r\n\t// Place stairs up\r\n\tposition = PlaceMiniSet(currlevel != 17 ? L6UP : L6HOLDWARP);\r\n\tif (!position)\r\n\t\treturn false;\r\n\tif (entry == ENTRY_MAIN || entry == ENTRY_TWARPDN)\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 1, 3 };\r\n\r\n\t// Place stairs down\r\n\tif (currlevel != 20) {\r\n\t\tposition = PlaceMiniSet(L6DOWN);\r\n\t\tif (!position)\r\n\t\t\treturn false;\r\n\t\tif (entry == ENTRY_PREV)\r\n\t\t\tViewPosition = position->megaToWorld() + Displacement { 3, 1 };\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool PlaceStairs(lvl_entry entry)\r\n{\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\treturn PlaceNestStairs(entry);\r\n\t}\r\n\r\n\treturn PlaceCaveStairs(entry);\r\n}\r\n\r\nvoid GenerateLevel(lvl_entry entry)\r\n{\r\n\tif (LevelSeeds[currlevel])\r\n\t\tSetRndSeed(*LevelSeeds[currlevel]);\r\n\r\n\twhile (true) {\r\n\t\tLevelSeeds[currlevel] = GetLCGEngineState();\r\n\t\tInitDungeonFlags();\r\n\t\tint x1 = GenerateRnd(20) + 10;\r\n\t\tint y1 = GenerateRnd(20) + 10;\r\n\t\tint x2 = x1 + 2;\r\n\t\tint y2 = y1 + 2;\r\n\t\tFillRoom(x1, y1, x2, y2);\r\n\t\tCreateBlock({ x1, y1 }, 2, 0);\r\n\t\tCreateBlock({ x2, y1 }, 2, 1);\r\n\t\tCreateBlock({ x1, y2 }, 2, 2);\r\n\t\tCreateBlock({ x1, y1 }, 2, 3);\r\n\t\tif (Quests[Q_ANVIL].IsAvailable()) {\r\n\t\t\tx1 = GenerateRnd(10) + 10;\r\n\t\t\ty1 = GenerateRnd(10) + 10;\r\n\t\t\tx2 = x1 + 12;\r\n\t\t\ty2 = y1 + 12;\r\n\t\t\tFloorArea(x1, y1, x2, y2);\r\n\t\t}\r\n\t\tFillDiagonals();\r\n\t\tFillSingles();\r\n\t\tFillStraights();\r\n\t\tFillDiagonals();\r\n\t\tEdges();\r\n\t\tif (GetFloorArea() < 600 || !Lockout())\r\n\t\t\tcontinue;\r\n\t\tMakeMegas();\r\n\t\tif (!PlaceStairs(entry))\r\n\t\t\tcontinue;\r\n\t\tif (Quests[Q_ANVIL].IsAvailable() && !PlaceAnvil())\r\n\t\t\tcontinue;\r\n\t\tif (PlacePool())\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\tPlaceMiniSetRandom(L6ISLE1, 70);\r\n\t\tPlaceMiniSetRandom(L6ISLE2, 70);\r\n\t\tPlaceMiniSetRandom(L6ISLE3, 30);\r\n\t\tPlaceMiniSetRandom(L6ISLE4, 30);\r\n\t\tPlaceMiniSetRandom(L6ISLE1, 100);\r\n\t\tPlaceMiniSetRandom(L6ISLE2, 100);\r\n\t\tPlaceMiniSetRandom(L6ISLE5, 90);\r\n\t\tPlaceMiniSetRandom1x1(8, 25, 20);\r\n\t\tPlaceMiniSetRandom1x1(8, 26, 20);\r\n\t\tPlaceMiniSetRandom1x1(8, 27, 20);\r\n\t\tPlaceMiniSetRandom1x1(8, 28, 20);\r\n\t\tPlaceMiniSetRandom(HivePattern29, 10);\r\n\t\tPlaceMiniSetRandom(HivePattern30, 15);\r\n\t\tPlaceMiniSetRandom(HivePattern31, 20);\r\n\t\tPlaceMiniSetRandom(HivePattern32, 25);\r\n\t\tPlaceMiniSetRandom(HivePattern33, 30);\r\n\t\tPlaceMiniSetRandom(HivePattern34, 35);\r\n\t\tPlaceMiniSetRandom(HivePattern35, 40);\r\n\t\tPlaceMiniSetRandom(HivePattern36, 45);\r\n\t\tPlaceMiniSetRandom(HivePattern37, 50);\r\n\t\tPlaceMiniSetRandom(HivePattern38, 55);\r\n\t\tPlaceMiniSetRandom(HivePattern38, 10);\r\n\t\tPlaceMiniSetRandom(HivePattern37, 15);\r\n\t\tPlaceMiniSetRandom(HivePattern36, 20);\r\n\t\tPlaceMiniSetRandom(HivePattern35, 25);\r\n\t\tPlaceMiniSetRandom(HivePattern34, 30);\r\n\t\tPlaceMiniSetRandom(HivePattern33, 35);\r\n\t\tPlaceMiniSetRandom(HivePattern32, 40);\r\n\t\tPlaceMiniSetRandom(HivePattern31, 45);\r\n\t\tPlaceMiniSetRandom(HivePattern30, 50);\r\n\t\tPlaceMiniSetRandom(HivePattern29, 55);\r\n\t\tPlaceMiniSetRandom(HivePattern9, 40);\r\n\t\tPlaceMiniSetRandom(HivePattern10, 45);\r\n\t\tPlaceMiniSetRandom1x1(7, 29, 25);\r\n\t\tPlaceMiniSetRandom1x1(7, 30, 25);\r\n\t\tPlaceMiniSetRandom1x1(7, 31, 25);\r\n\t\tPlaceMiniSetRandom1x1(7, 32, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 33, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 34, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 35, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 36, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 37, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 39, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 40, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 41, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 42, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 43, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 45, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 46, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 47, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 48, 25);\r\n\t\tPlaceMiniSetRandom1x1(11, 38, 25);\r\n\t\tPlaceMiniSetRandom1x1(11, 44, 25);\r\n\t\tPlaceMiniSetRandom1x1(11, 49, 25);\r\n\t\tPlaceMiniSetRandom1x1(11, 50, 25);\r\n\t} else {\r\n\t\tPoolFix();\r\n\t\tWarp();\r\n\r\n\t\tPlaceMiniSetRandom(L3ISLE1, 70);\r\n\t\tPlaceMiniSetRandom(L3ISLE2, 70);\r\n\t\tPlaceMiniSetRandom(L3ISLE3, 30);\r\n\t\tPlaceMiniSetRandom(L3ISLE4, 30);\r\n\t\tPlaceMiniSetRandom(L3ISLE1, 100);\r\n\t\tPlaceMiniSetRandom(L3ISLE2, 100);\r\n\t\tPlaceMiniSetRandom(L3ISLE5, 90);\r\n\r\n\t\tHallOfHeroes();\r\n\t\tRiver();\r\n\r\n\t\tif (Quests[Q_ANVIL].IsAvailable()) {\r\n\t\t\tdungeon[SetPiece.position.x + 7][SetPiece.position.y + 5] = 7;\r\n\t\t\tdungeon[SetPiece.position.x + 8][SetPiece.position.y + 5] = 7;\r\n\t\t\tdungeon[SetPiece.position.x + 9][SetPiece.position.y + 5] = 7;\r\n\t\t\tif (dungeon[SetPiece.position.x + 10][SetPiece.position.y + 5] == 17 || dungeon[SetPiece.position.x + 10][SetPiece.position.y + 5] == 18) {\r\n\t\t\t\tdungeon[SetPiece.position.x + 10][SetPiece.position.y + 5] = 45;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDRLG_PlaceThemeRooms(5, 10, 7, 0, false);\r\n\t\tFence();\r\n\t\tPlaceMiniSetRandom(L3TITE1, 10);\r\n\t\tPlaceMiniSetRandom(L3TITE2, 10);\r\n\t\tPlaceMiniSetRandom(L3TITE3, 10);\r\n\t\tPlaceMiniSetRandom(L3TITE6, 20);\r\n\t\tPlaceMiniSetRandom(L3TITE7, 20);\r\n\t\tPlaceMiniSetRandom(L3TITE8, 20);\r\n\t\tPlaceMiniSetRandom(L3TITE9, 20);\r\n\t\tPlaceMiniSetRandom(L3TITE10, 20);\r\n\t\tPlaceMiniSetRandom(L3TITE11, 30);\r\n\t\tPlaceMiniSetRandom(L3TITE12, 20);\r\n\t\tPlaceMiniSetRandom(L3TITE13, 20);\r\n\t\tPlaceMiniSetRandom(L3CREV1, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV2, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV3, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV4, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV5, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV6, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV7, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV8, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV9, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV10, 30);\r\n\t\tPlaceMiniSetRandom(L3CREV11, 30);\r\n\t\tPlaceMiniSetRandom1x1(7, 106, 25);\r\n\t\tPlaceMiniSetRandom1x1(7, 107, 25);\r\n\t\tPlaceMiniSetRandom1x1(7, 108, 25);\r\n\t\tPlaceMiniSetRandom1x1(9, 109, 25);\r\n\t\tPlaceMiniSetRandom1x1(10, 110, 25);\r\n\t}\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n}\r\n\r\nvoid Pass3()\r\n{\r\n\tDRLG_LPass3(8 - 1);\r\n}\r\n\r\nvoid PlaceCaveLights()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] >= 55 && dPiece[i][j] <= 146) {\r\n\t\t\t\tDoLighting({ i, j }, 7, {});\r\n\t\t\t} else if (dPiece[i][j] >= 153 && dPiece[i][j] <= 160) {\r\n\t\t\t\tDoLighting({ i, j }, 7, {});\r\n\t\t\t} else if (IsAnyOf(dPiece[i][j], 149, 151)) {\r\n\t\t\t\tDoLighting({ i, j }, 7, {});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlaceHiveLights()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] >= 381 && dPiece[i][j] <= 456) {\r\n\t\t\t\tDoLighting({ i, j }, 9, {});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlaceLights()\r\n{\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\tPlaceHiveLights();\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaceCaveLights();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid CreateL3Dungeon(uint32_t rseed, lvl_entry entry)\r\n{\r\n\tSetRndSeed(rseed);\r\n\r\n\tGenerateLevel(entry);\r\n\r\n\tPass3();\r\n\tPlaceLights();\r\n}\r\n\r\nvoid LoadPreL3Dungeon(const char *path)\r\n{\r\n\tmemset(dungeon, 8, sizeof(dungeon));\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\tPlaceDunTiles(dunData.get(), { 0, 0 }, 7);\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n}\r\n\r\nvoid LoadL3Dungeon(const char *path, Point spawn)\r\n{\r\n\tLoadDungeonBase(path, spawn, 7, 8);\r\n\r\n\tPass3();\r\n\tPlaceLights();\r\n\r\n\tif (leveltype == DTYPE_CAVES)\r\n\t\tAddL3Objs(0, 0, MAXDUNX, MAXDUNY);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l3.h",
    "content": "/**\r\n * @file levels/drlg_l3.h\r\n *\r\n * Interface of the caves level generation algorithms.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid CreateL3Dungeon(uint32_t rseed, lvl_entry entry);\r\nvoid LoadPreL3Dungeon(const char *sFileName);\r\nvoid LoadL3Dungeon(const char *sFileName, Point spawn);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l4.cpp",
    "content": "/**\r\n * @file levels/drlg_l4.cpp\r\n *\r\n * Implementation of the hell level generation algorithms.\r\n */\r\n#include \"levels/drlg_l4.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"monster.h\"\r\n#include \"multi.h\"\r\n#include \"player.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nWorldTilePosition DiabloQuad1;\r\nWorldTilePosition DiabloQuad2;\r\nWorldTilePosition DiabloQuad3;\r\nWorldTilePosition DiabloQuad4;\r\n\r\nnamespace {\r\n\r\nbool hallok[20];\r\nWorldTilePosition L4Hold;\r\n\r\n/**\r\n * A lookup table for the 16 possible patterns of a 2x2 area,\r\n * where each cell either contains a SW wall or it doesn't.\r\n */\r\nconst uint8_t L4ConvTbl[16] = { 30, 6, 1, 6, 2, 6, 6, 6, 9, 6, 1, 6, 2, 6, 3, 6 };\r\n\r\n/** Miniset: Stairs up. */\r\nconst Miniset L4USTAIRS {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 36, 38, 35, 0 },\r\n\t    { 37, 34, 33, 32 },\r\n\t    { 0, 0, 31, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stairs up to town. */\r\nconst Miniset L4TWARP {\r\n\t{ 4, 5 },\r\n\t{\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0 },\r\n\t    { 134, 136, 133, 0 },\r\n\t    { 135, 132, 131, 130 },\r\n\t    { 0, 0, 129, 0 },\r\n\t    { 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Stairs down. */\r\nconst Miniset L4DSTAIRS {\r\n\t{ 5, 5 },\r\n\t{\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t    { 0, 0, 45, 41, 0 },\r\n\t    { 0, 44, 43, 40, 0 },\r\n\t    { 0, 46, 42, 39, 0 },\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Pentagram. */\r\nconst Miniset L4PENTA {\r\n\t{ 5, 5 },\r\n\t{\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t    { 0, 98, 100, 103, 0 },\r\n\t    { 0, 99, 102, 105, 0 },\r\n\t    { 0, 101, 104, 106, 0 },\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t}\r\n};\r\n/** Miniset: Pentagram portal. */\r\nconst Miniset L4PENTA2 {\r\n\t{ 5, 5 },\r\n\t{\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t    { 6, 6, 6, 6, 6 },\r\n\t},\r\n\t{\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t    { 0, 107, 109, 112, 0 },\r\n\t    { 0, 108, 111, 114, 0 },\r\n\t    { 0, 110, 113, 115, 0 },\r\n\t    { 0, 0, 0, 0, 0 },\r\n\t}\r\n};\r\n\r\n/** Maps tile IDs to their corresponding undecorated tile ID. */\r\nconst uint8_t L4BTYPES[140] = {\r\n\t0, 1, 2, 3, 4, 5, 6, 7, 8, 9,\r\n\t10, 11, 12, 13, 14, 15, 16, 17, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 6,\r\n\t6, 6, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 1, 2, 1, 2, 1, 2, 1, 1, 2,\r\n\t2, 0, 0, 0, 0, 0, 0, 15, 16, 9,\r\n\t12, 4, 5, 7, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r\n};\r\n\r\nvoid ApplyShadowsPatterns()\r\n{\r\n\tfor (int y = 1; y < DMAXY; y++) {\r\n\t\tfor (int x = 1; x < DMAXY; x++) {\r\n\t\t\tif (IsNoneOf(dungeon[x][y], 3, 4, 8, 15)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (dungeon[x - 1][y] == 6) {\r\n\t\t\t\tdungeon[x - 1][y] = 47;\r\n\t\t\t}\r\n\t\t\tif (dungeon[x - 1][y - 1] == 6) {\r\n\t\t\t\tdungeon[x - 1][y - 1] = 48;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitSetPiece()\r\n{\r\n\tstd::unique_ptr<uint16_t[]> setPieceData;\r\n\r\n\tif (Quests[Q_WARLORD].IsAvailable()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l4data\\\\warlord.dun\");\r\n\t} else if (currlevel == 15 && UseMultiplayerQuests()) {\r\n\t\tsetPieceData = LoadFileInMem<uint16_t>(\"levels\\\\l4data\\\\vile1.dun\");\r\n\t} else {\r\n\t\treturn; // no setpiece needed for this level\r\n\t}\r\n\r\n\tconst WorldTilePosition setPiecePosition = SetPieceRoom.position;\r\n\tPlaceDunTiles(setPieceData.get(), setPiecePosition, 6);\r\n\tSetPiece = { setPiecePosition, GetDunSize(setPieceData.get()) };\r\n}\r\n\r\nvoid InitDungeonFlags()\r\n{\r\n\tDungeonMask.reset();\r\n\tProtected.reset();\r\n\tmemset(dungeon, 30, sizeof(dungeon));\r\n}\r\n\r\nvoid MapRoom(WorldTileRectangle room)\r\n{\r\n\tfor (WorldTileCoord y = 0; y < room.size.height && y + room.position.y < DMAXY / 2; y++) {\r\n\t\tfor (WorldTileCoord x = 0; x < room.size.width && x + room.position.x < DMAXX / 2; x++) {\r\n\t\t\tDungeonMask.set(room.position.x + x, room.position.y + y);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool CheckRoom(WorldTileRectangle room)\r\n{\r\n\tif (room.position.x <= 0 || room.position.y <= 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (int y = 0; y < room.size.height; y++) {\r\n\t\tfor (int x = 0; x < room.size.width; x++) {\r\n\t\t\tif (x + room.position.x < 0 || x + room.position.x >= DMAXX / 2 || y + room.position.y < 0 || y + room.position.y >= DMAXY / 2) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tif (DungeonMask.test(room.position.x + x, room.position.y + y)) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid GenerateRoom(WorldTileRectangle area, bool verticalLayout)\r\n{\r\n\tconst bool rotate = !FlipCoin(4);\r\n\tverticalLayout = (!verticalLayout && rotate) || (verticalLayout && !rotate);\r\n\r\n\tbool placeRoom1;\r\n\tWorldTileRectangle room1;\r\n\r\n\tfor (int num = 0; num < 20; num++) {\r\n\t\tconst int32_t randomWidth = (GenerateRnd(5) + 2) & ~1;\r\n\t\tconst int32_t randomHeight = (GenerateRnd(5) + 2) & ~1;\r\n\t\troom1.size = WorldTileSize(randomWidth, randomHeight);\r\n\t\troom1.position = area.position;\r\n\t\tif (verticalLayout) {\r\n\t\t\troom1.position += WorldTileDisplacement(-room1.size.width, area.size.height / 2 - room1.size.height / 2);\r\n\t\t\tplaceRoom1 = CheckRoom({ room1.position + WorldTileDisplacement { -1, -1 }, WorldTileSize(room1.size.height + 2, room1.size.width + 1) }); /// BUGFIX: swap height and width ({ room1.size.width + 1, room1.size.height + 2 }) (workaround applied below)\r\n\t\t} else {\r\n\t\t\troom1.position += WorldTileDisplacement(area.size.width / 2 - room1.size.width / 2, -room1.size.height);\r\n\t\t\tplaceRoom1 = CheckRoom({ room1.position + WorldTileDisplacement { -1, -1 }, WorldTileSize(room1.size.width + 2, room1.size.height + 1) });\r\n\t\t}\r\n\t\tif (placeRoom1)\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (placeRoom1)\r\n\t\tMapRoom({ room1.position, WorldTileSize(std::min<int>(DMAXX - room1.position.x, room1.size.width), std::min<int>(DMAXX - room1.position.y, room1.size.height)) });\r\n\r\n\tbool placeRoom2;\r\n\tWorldTileRectangle room2 = room1;\r\n\tif (verticalLayout) {\r\n\t\troom2.position.x = area.position.x + area.size.width;\r\n\t\tplaceRoom2 = CheckRoom({ room2.position + WorldTileDisplacement { 0, -1 }, WorldTileSize(room2.size.width + 1, room2.size.height + 2) });\r\n\t} else {\r\n\t\troom2.position.y = area.position.y + area.size.height;\r\n\t\tplaceRoom2 = CheckRoom({ room2.position + WorldTileDisplacement { -1, 0 }, WorldTileSize(room2.size.width + 2, room2.size.height + 1) });\r\n\t}\r\n\r\n\tif (placeRoom2)\r\n\t\tMapRoom(room2);\r\n\tif (placeRoom1)\r\n\t\tGenerateRoom(room1, verticalLayout);\r\n\tif (placeRoom2)\r\n\t\tGenerateRoom(room2, verticalLayout);\r\n}\r\n\r\nvoid FirstRoom()\r\n{\r\n\tWorldTileRectangle room { { 0, 0 }, { 14, 14 } };\r\n\tif (currlevel != 16) {\r\n\t\tif (currlevel == Quests[Q_WARLORD]._qlevel && Quests[Q_WARLORD]._qactive != QUEST_NOTAVAIL) {\r\n\t\t\troom.size = { 11, 11 };\r\n\t\t} else if (currlevel == Quests[Q_BETRAYER]._qlevel && UseMultiplayerQuests()) {\r\n\t\t\troom.size = { 11, 11 };\r\n\t\t} else {\r\n\t\t\tconst int32_t randomWidth = GenerateRnd(5) + 2;\r\n\t\t\tconst int32_t randomHeight = GenerateRnd(5) + 2;\r\n\t\t\troom.size = WorldTileSize(randomWidth, randomHeight);\r\n\t\t}\r\n\t}\r\n\r\n\tconst int xmin = (DMAXX / 2 - room.size.width) / 2;\r\n\tconst int xmax = DMAXX / 2 - 1 - room.size.width;\r\n\tconst int ymin = (DMAXY / 2 - room.size.height) / 2;\r\n\tconst int ymax = DMAXY / 2 - 1 - room.size.height;\r\n\tconst int32_t randomX = GenerateRnd(xmax - xmin + 1) + xmin;\r\n\tconst int32_t randomY = GenerateRnd(ymax - ymin + 1) + ymin;\r\n\troom.position = WorldTilePosition(randomX, randomY);\r\n\r\n\tif (currlevel == 16) {\r\n\t\tL4Hold = room.position;\r\n\t}\r\n\tif (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && UseMultiplayerQuests())) {\r\n\t\tSetPieceRoom = { room.position + WorldTileDisplacement { 1, 1 }, WorldTileSize(room.size.width + 1, room.size.height + 1) };\r\n\t} else {\r\n\t\tSetPieceRoom = {};\r\n\t}\r\n\r\n\tMapRoom(room);\r\n\tGenerateRoom(room, !FlipCoin());\r\n}\r\n\r\n/**\r\n * @brief Mirrors the first quadrant to the rest of the map\r\n */\r\nvoid MirrorDungeonLayout()\r\n{\r\n\tfor (int y = 0; y < DMAXY / 2; y++) {\r\n\t\tfor (int x = 0; x < DMAXX / 2; x++) {\r\n\t\t\tif (DungeonMask.test(x, y)) {\r\n\t\t\t\tDungeonMask.set(x, DMAXY - 1 - y);\r\n\t\t\t\tDungeonMask.set(DMAXX - 1 - x, y);\r\n\t\t\t\tDungeonMask.set(DMAXX - 1 - x, DMAXY - 1 - y);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MakeDmt()\r\n{\r\n\tfor (int y = 0; y < DMAXY - 1; y++) {\r\n\t\tfor (int x = 0; x < DMAXX - 1; x++) {\r\n\t\t\tconst int val = (DungeonMask.test(x + 1, y + 1) << 3) | (DungeonMask.test(x, y + 1) << 2) | (DungeonMask.test(x + 1, y) << 1) | (DungeonMask.test(x, y) << 0);\r\n\t\t\tdungeon[x][y] = L4ConvTbl[val];\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint HorizontalWallOk(int i, int j)\r\n{\r\n\tint x;\r\n\tfor (x = 1; dungeon[i + x][j] == 6; x++) {\r\n\t\tif (Protected.test(i + x, j)) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (dungeon[i + x][j - 1] != 6) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (dungeon[i + x][j + 1] != 6) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsAnyOf(dungeon[i + x][j], 10, 12, 13, 15, 16, 21, 22) && x > 3)\r\n\t\treturn x;\r\n\r\n\treturn -1;\r\n}\r\n\r\nint VerticalWallOk(int i, int j)\r\n{\r\n\tint y;\r\n\tfor (y = 1; dungeon[i][j + y] == 6; y++) {\r\n\t\tif (Protected.test(i, j + y)) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (dungeon[i - 1][j + y] != 6) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (dungeon[i + 1][j + y] != 6) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsAnyOf(dungeon[i][j + y], 8, 9, 11, 14, 15, 16, 21, 23) && y > 3)\r\n\t\treturn y;\r\n\r\n\treturn -1;\r\n}\r\n\r\nvoid HorizontalWall(int i, int j, int dx)\r\n{\r\n\tif (dungeon[i][j] == 13) {\r\n\t\tdungeon[i][j] = 17;\r\n\t}\r\n\tif (dungeon[i][j] == 16) {\r\n\t\tdungeon[i][j] = 11;\r\n\t}\r\n\tif (dungeon[i][j] == 12) {\r\n\t\tdungeon[i][j] = 14;\r\n\t}\r\n\r\n\tfor (int xx = 1; xx < dx; xx++) {\r\n\t\tdungeon[i + xx][j] = 2;\r\n\t}\r\n\r\n\tif (dungeon[i + dx][j] == 15) {\r\n\t\tdungeon[i + dx][j] = 14;\r\n\t}\r\n\tif (dungeon[i + dx][j] == 10) {\r\n\t\tdungeon[i + dx][j] = 17;\r\n\t}\r\n\tif (dungeon[i + dx][j] == 21) {\r\n\t\tdungeon[i + dx][j] = 23;\r\n\t}\r\n\tif (dungeon[i + dx][j] == 22) {\r\n\t\tdungeon[i + dx][j] = 29;\r\n\t}\r\n\r\n\tconst int xx = GenerateRnd(dx - 3) + 1;\r\n\tdungeon[i + xx][j] = 57;\r\n\tdungeon[i + xx + 2][j] = 56;\r\n\tdungeon[i + xx + 1][j] = 60;\r\n\r\n\tif (dungeon[i + xx][j - 1] == 6) {\r\n\t\tdungeon[i + xx][j - 1] = 58;\r\n\t}\r\n\tif (dungeon[i + xx + 1][j - 1] == 6) {\r\n\t\tdungeon[i + xx + 1][j - 1] = 59;\r\n\t}\r\n}\r\n\r\nvoid VerticalWall(int i, int j, int dy)\r\n{\r\n\tif (dungeon[i][j] == 14) {\r\n\t\tdungeon[i][j] = 17;\r\n\t}\r\n\tif (dungeon[i][j] == 8) {\r\n\t\tdungeon[i][j] = 9;\r\n\t}\r\n\tif (dungeon[i][j] == 15) {\r\n\t\tdungeon[i][j] = 10;\r\n\t}\r\n\r\n\tfor (int yy = 1; yy < dy; yy++) {\r\n\t\tdungeon[i][j + yy] = 1;\r\n\t}\r\n\r\n\tif (dungeon[i][j + dy] == 11) {\r\n\t\tdungeon[i][j + dy] = 17;\r\n\t}\r\n\tif (dungeon[i][j + dy] == 9) {\r\n\t\tdungeon[i][j + dy] = 10;\r\n\t}\r\n\tif (dungeon[i][j + dy] == 16) {\r\n\t\tdungeon[i][j + dy] = 13;\r\n\t}\r\n\tif (dungeon[i][j + dy] == 21) {\r\n\t\tdungeon[i][j + dy] = 22;\r\n\t}\r\n\tif (dungeon[i][j + dy] == 23) {\r\n\t\tdungeon[i][j + dy] = 29;\r\n\t}\r\n\r\n\tconst int yy = GenerateRnd(dy - 3) + 1;\r\n\tdungeon[i][j + yy] = 53;\r\n\tdungeon[i][j + yy + 2] = 52;\r\n\tdungeon[i][j + yy + 1] = 6;\r\n\r\n\tif (dungeon[i - 1][j + yy] == 6) {\r\n\t\tdungeon[i - 1][j + yy] = 54;\r\n\t}\r\n\tif (dungeon[i - 1][j + yy - 1] == 6) {\r\n\t\tdungeon[i - 1][j + yy - 1] = 55;\r\n\t}\r\n}\r\n\r\nvoid AddWall()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (Protected.test(i, j)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tfor (auto d : { 10, 12, 13, 15, 16, 21, 22 }) {\r\n\t\t\t\tif (d == dungeon[i][j]) {\r\n\t\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\t\tconst int x = HorizontalWallOk(i, j);\r\n\t\t\t\t\tif (x != -1) {\r\n\t\t\t\t\t\tHorizontalWall(i, j, x);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfor (auto d : { 8, 9, 11, 14, 15, 16, 21, 23 }) {\r\n\t\t\t\tif (d == dungeon[i][j]) {\r\n\t\t\t\t\tDiscardRandomValues(1);\r\n\t\t\t\t\tconst int y = VerticalWallOk(i, j);\r\n\t\t\t\t\tif (y != -1) {\r\n\t\t\t\t\t\tVerticalWall(i, j, y);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FixTilesPatterns()\r\n{\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 5;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 13;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 14;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 2;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 9)\r\n\t\t\t\tdungeon[i + 1][j] = 11;\r\n\t\t\tif (dungeon[i][j] == 9 && dungeon[i + 1][j] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 13;\r\n\t\t\tif (dungeon[i][j] == 6 && dungeon[i + 1][j] == 14)\r\n\t\t\t\tdungeon[i + 1][j] = 15;\r\n\t\t\tif (dungeon[i][j] == 6 && dungeon[i][j + 1] == 13)\r\n\t\t\t\tdungeon[i][j + 1] = 16;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 10;\r\n\t\t\tif (dungeon[i][j] == 6 && dungeon[i][j - 1] == 1)\r\n\t\t\t\tdungeon[i][j - 1] = 1;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 27;\r\n\t\t\tif (dungeon[i][j] == 27 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 27;\r\n\t\t\tif (dungeon[i][j] == 27 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 27)\r\n\t\t\t\tdungeon[i + 1][j] = 26;\r\n\t\t\tif (dungeon[i][j] == 27 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 15)\r\n\t\t\t\tdungeon[i + 1][j] = 14;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 15)\r\n\t\t\t\tdungeon[i + 1][j] = 14;\r\n\t\t\tif (dungeon[i][j] == 22 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 27 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 6 && dungeon[i + 1][j] == 27 && dungeon[i + 1][j + 1] != 0) /* check */\r\n\t\t\t\tdungeon[i + 1][j] = 22;\r\n\t\t\tif (dungeon[i][j] == 22 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 1 && dungeon[i + 1][j - 1] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 13;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 30 && dungeon[i][j + 1] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 28;\r\n\t\t\tif (dungeon[i][j] == 16 && dungeon[i + 1][j] == 6 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 27;\r\n\t\t\tif (dungeon[i][j] == 16 && dungeon[i][j + 1] == 30 && dungeon[i + 1][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 27;\r\n\t\t\tif (dungeon[i][j] == 6 && dungeon[i + 1][j] == 30 && dungeon[i + 1][j - 1] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 21;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 27 && dungeon[i + 1][j + 1] == 9)\r\n\t\t\t\tdungeon[i + 1][j] = 29;\r\n\t\t\tif (dungeon[i][j] == 9 && dungeon[i + 1][j] == 15)\r\n\t\t\t\tdungeon[i + 1][j] = 14;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 27 && dungeon[i + 1][j + 1] == 2)\r\n\t\t\t\tdungeon[i + 1][j] = 29;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 18)\r\n\t\t\t\tdungeon[i + 1][j] = 24;\r\n\t\t\tif (dungeon[i][j] == 9 && dungeon[i + 1][j] == 15)\r\n\t\t\t\tdungeon[i + 1][j] = 14;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 19 && dungeon[i + 1][j - 1] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 24;\r\n\t\t\tif (dungeon[i][j] == 24 && dungeon[i][j - 1] == 30 && dungeon[i][j - 2] == 6)\r\n\t\t\t\tdungeon[i][j - 1] = 21;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 28;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 28;\r\n\t\t\tif (dungeon[i][j] == 28 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 28 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 2][j] == 2 && dungeon[i + 1][j - 1] == 18 && dungeon[i + 1][j + 1] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 2][j] == 2 && dungeon[i + 1][j - 1] == 22 && dungeon[i + 1][j + 1] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 2][j] == 2 && dungeon[i + 1][j - 1] == 18 && dungeon[i + 1][j + 1] == 13)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 2][j] == 2 && dungeon[i + 1][j - 1] == 18 && dungeon[i + 1][j + 1] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j + 1] == 1 && dungeon[i + 1][j - 1] == 22 && dungeon[i + 2][j] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 28 && dungeon[i + 2][j] == 30 && dungeon[i + 1][j - 1] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 28 && dungeon[i + 2][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 27 && dungeon[i + 1][j + 1] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 29;\r\n\t\t\tif (dungeon[i][j] == 28 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j - 1] == 21)\r\n\t\t\t\tdungeon[i + 1][j] = 24;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 27 && dungeon[i + 1][j + 1] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 29;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 18)\r\n\t\t\t\tdungeon[i + 1][j] = 25;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 9 && dungeon[i + 2][j] == 2)\r\n\t\t\t\tdungeon[i + 1][j] = 11;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 10)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i][j + 1] == 3)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 22 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 18 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 24 && dungeon[i - 1][j] == 30)\r\n\t\t\t\tdungeon[i - 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 10;\r\n\t\t\tif (dungeon[i][j] == 22 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 16 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 22 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 18 && dungeon[i + 2][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 24;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 9 && dungeon[i + 1][j + 1] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 27 && dungeon[i + 1][j + 1] == 2)\r\n\t\t\t\tdungeon[i + 1][j] = 29;\r\n\t\t\tif (dungeon[i][j] == 23 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 23 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 25 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 22 && dungeon[i + 1][j] == 9)\r\n\t\t\t\tdungeon[i + 1][j] = 11;\r\n\t\t\tif (dungeon[i][j] == 23 && dungeon[i + 1][j] == 9)\r\n\t\t\t\tdungeon[i + 1][j] = 11;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i + 1][j] == 15)\r\n\t\t\t\tdungeon[i + 1][j] = 14;\r\n\t\t\tif (dungeon[i][j] == 23 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 27)\r\n\t\t\t\tdungeon[i + 1][j] = 26;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 18)\r\n\t\t\t\tdungeon[i + 1][j] = 24;\r\n\t\t\tif (dungeon[i][j] == 26 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 29 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 29 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j - 1] == 15)\r\n\t\t\t\tdungeon[i][j - 1] = 10;\r\n\t\t\tif (dungeon[i][j] == 18 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 23 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 18 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 10;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 30 && dungeon[i + 1][j + 1] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 28 && dungeon[i + 1][j - 1] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 23 && dungeon[i + 1][j] == 18 && dungeon[i][j - 1] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 24;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 23 && dungeon[i + 2][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 28;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 28 && dungeon[i + 2][j] == 30 && dungeon[i + 1][j - 1] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 23 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 29 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 29 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 26 && dungeon[i + 1][j] == 30)\r\n\t\t\t\tdungeon[i + 1][j] = 19;\r\n\t\t\tif (dungeon[i][j] == 16 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 10;\r\n\t\t\tif (dungeon[i][j] == 25 && dungeon[i][j + 1] == 30)\r\n\t\t\t\tdungeon[i][j + 1] = 18;\r\n\t\t\tif (dungeon[i][j] == 18 && dungeon[i][j + 1] == 2)\r\n\t\t\t\tdungeon[i][j + 1] = 15;\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i + 1][j] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 5;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 9)\r\n\t\t\t\tdungeon[i + 1][j] = 11;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 13;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 13 && dungeon[i + 1][j - 1] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i][j + 1] == 24 && dungeon[i][j + 2] == 1)\r\n\t\t\t\tdungeon[i][j + 1] = 17;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j + 1] == 9 && dungeon[i + 1][j - 1] == 1 && dungeon[i + 2][j] == 16)\r\n\t\t\t\tdungeon[i + 1][j] = 29;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i - 1][j] == 6)\r\n\t\t\t\tdungeon[i - 1][j] = 8;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j - 1] == 6)\r\n\t\t\t\tdungeon[i][j - 1] = 7;\r\n\t\t\tif (dungeon[i][j] == 6 && dungeon[i + 1][j] == 15 && dungeon[i + 1][j + 1] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 10;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 3)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 6)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 9 && dungeon[i][j + 1] == 3)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 10 && dungeon[i][j + 1] == 3)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i][j + 1] == 3)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 5)\r\n\t\t\t\tdungeon[i][j + 1] = 12;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 16)\r\n\t\t\t\tdungeon[i][j + 1] = 13;\r\n\t\t\tif (dungeon[i][j] == 6 && dungeon[i][j + 1] == 13)\r\n\t\t\t\tdungeon[i][j + 1] = 16;\r\n\t\t\tif (dungeon[i][j] == 25 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 10;\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i][j + 1] == 5)\r\n\t\t\t\tdungeon[i][j + 1] = 12;\r\n\t\t\tif (dungeon[i][j] == 28 && dungeon[i][j - 1] == 6 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 10)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 9)\r\n\t\t\t\tdungeon[i + 1][j] = 11;\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i + 1][j] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 5;\r\n\t\t\tif (dungeon[i][j] == 10 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 27 && dungeon[i + 1][j] == 9)\r\n\t\t\t\tdungeon[i + 1][j] = 11;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 1)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 5;\r\n\t\t\tif (dungeon[i][j] == 9 && dungeon[i + 1][j] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 5;\r\n\t\t\tif (dungeon[i][j] == 14 && dungeon[i + 1][j] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 5;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 5;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 5 && dungeon[i + 1][j - 1] == 16)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 9 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j - 1] == 8)\r\n\t\t\t\tdungeon[i][j - 1] = 9;\r\n\t\t\tif (dungeon[i][j] == 28 && dungeon[i + 1][j] == 23 && dungeon[i + 1][j + 1] == 3)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 10)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 17 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 10 && dungeon[i + 1][j] == 4)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 17 && dungeon[i][j + 1] == 5)\r\n\t\t\t\tdungeon[i][j + 1] = 12;\r\n\t\t\tif (dungeon[i][j] == 29 && dungeon[i][j + 1] == 9)\r\n\t\t\t\tdungeon[i][j + 1] = 10;\r\n\t\t\tif (dungeon[i][j] == 13 && dungeon[i][j + 1] == 5)\r\n\t\t\t\tdungeon[i][j + 1] = 12;\r\n\t\t\tif (dungeon[i][j] == 9 && dungeon[i][j + 1] == 16)\r\n\t\t\t\tdungeon[i][j + 1] = 13;\r\n\t\t\tif (dungeon[i][j] == 10 && dungeon[i][j + 1] == 16)\r\n\t\t\t\tdungeon[i][j + 1] = 13;\r\n\t\t\tif (dungeon[i][j] == 16 && dungeon[i][j + 1] == 3)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 11 && dungeon[i][j + 1] == 5)\r\n\t\t\t\tdungeon[i][j + 1] = 12;\r\n\t\t\tif (dungeon[i][j] == 10 && dungeon[i + 1][j] == 3 && dungeon[i + 1][j - 1] == 16)\r\n\t\t\t\tdungeon[i + 1][j] = 12;\r\n\t\t\tif (dungeon[i][j] == 16 && dungeon[i][j + 1] == 5)\r\n\t\t\t\tdungeon[i][j + 1] = 12;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i][j + 1] == 6)\r\n\t\t\t\tdungeon[i][j + 1] = 4;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j] == 13 && dungeon[i][j + 1] == 10)\r\n\t\t\t\tdungeon[i + 1][j + 1] = 12;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 10)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 22 && dungeon[i][j + 1] == 11)\r\n\t\t\t\tdungeon[i][j + 1] = 17;\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 28 && dungeon[i + 2][j] == 16)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 28 && dungeon[i + 1][j] == 23 && dungeon[i + 1][j + 1] == 1 && dungeon[i + 2][j] == 6)\r\n\t\t\t\tdungeon[i + 1][j] = 16;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == 15 && dungeon[i + 1][j] == 28 && dungeon[i + 2][j] == 16)\r\n\t\t\t\tdungeon[i + 1][j] = 23;\r\n\t\t\tif (dungeon[i][j] == 21 && dungeon[i + 1][j - 1] == 21 && dungeon[i + 1][j + 1] == 13 && dungeon[i + 2][j] == 2)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t\tif (dungeon[i][j] == 19 && dungeon[i + 1][j] == 15 && dungeon[i + 1][j + 1] == 12)\r\n\t\t\t\tdungeon[i + 1][j] = 17;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Substitution()\r\n{\r\n\tfor (int y = 0; y < DMAXY; y++) {\r\n\t\tfor (int x = 0; x < DMAXX; x++) {\r\n\t\t\tif (FlipCoin(3)) {\r\n\t\t\t\tconst uint8_t c = L4BTYPES[dungeon[x][y]];\r\n\t\t\t\tif (c != 0 && !Protected.test(x, y)) {\r\n\t\t\t\t\tint rv = GenerateRnd(16);\r\n\t\t\t\t\tint i = -1;\r\n\t\t\t\t\twhile (rv >= 0) {\r\n\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\tif (i == sizeof(L4BTYPES)) {\r\n\t\t\t\t\t\t\ti = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (c == L4BTYPES[i]) {\r\n\t\t\t\t\t\t\trv--;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tdungeon[x][y] = i;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int y = 0; y < DMAXY; y++) {\r\n\t\tfor (int x = 0; x < DMAXX; x++) {\r\n\t\t\tif (FlipCoin(10)) {\r\n\t\t\t\tconst uint8_t c = dungeon[x][y];\r\n\t\t\t\tif (L4BTYPES[c] == 6 && !Protected.test(x, y)) {\r\n\t\t\t\t\tdungeon[x][y] = PickRandomlyAmong({ 95, 96, 97 });\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Sets up the inside borders of the first quadrant so there are valid paths after mirroring the layout\r\n */\r\nvoid PrepareInnerBorders()\r\n{\r\n\tfor (int y = DMAXY / 2 - 1; y >= 0; y--) {\r\n\t\tfor (int x = DMAXX / 2 - 1; x >= 0; x--) {\r\n\t\t\tif (!DungeonMask.test(x, y)) {\r\n\t\t\t\thallok[y] = false;\r\n\t\t\t} else {\r\n\t\t\t\tconst bool hasSouthWestRoom = y + 1 < DMAXY / 2 && DungeonMask.test(x, y + 1);\r\n\t\t\t\tconst bool hasSouthRoom = x + 1 < DMAXX / 2 && y + 1 < DMAXY / 2 && DungeonMask.test(x + 1, y + 1);\r\n\t\t\t\thallok[y] = hasSouthWestRoom && !hasSouthRoom;\r\n\t\t\t\tx = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tint ry = GenerateRnd(DMAXY / 2 - 1) + 1;\r\n\tdo {\r\n\t\tif (hallok[ry]) {\r\n\t\t\tfor (int x = DMAXX / 2 - 1; x >= 0; x--) {\r\n\t\t\t\tif (DungeonMask.test(x, ry)) {\r\n\t\t\t\t\tx = -1;\r\n\t\t\t\t\try = 0;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tDungeonMask.set(x, ry);\r\n\t\t\t\t\tDungeonMask.set(x, ry + 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\try++;\r\n\t\t\tif (ry == DMAXY / 2) {\r\n\t\t\t\try = 1;\r\n\t\t\t}\r\n\t\t}\r\n\t} while (ry != 0);\r\n\r\n\tfor (int x = DMAXX / 2 - 1; x >= 0; x--) {\r\n\t\tfor (int y = DMAXY / 2 - 1; y >= 0; y--) {\r\n\t\t\tif (!DungeonMask.test(x, y)) {\r\n\t\t\t\thallok[x] = false;\r\n\t\t\t} else {\r\n\t\t\t\tconst bool hasSouthEastRoom = x + 1 < DMAXX / 2 && DungeonMask.test(x + 1, y);\r\n\t\t\t\tconst bool hasSouthRoom = x + 1 < DMAXX / 2 && y + 1 < DMAXY / 2 && DungeonMask.test(x + 1, y + 1);\r\n\t\t\t\thallok[x] = hasSouthEastRoom && !hasSouthRoom;\r\n\t\t\t\ty = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tint rx = GenerateRnd(DMAXX / 2 - 1) + 1;\r\n\tdo {\r\n\t\tif (hallok[rx]) {\r\n\t\t\tfor (int y = DMAXY / 2 - 1; y >= 0; y--) {\r\n\t\t\t\tif (DungeonMask.test(rx, y)) {\r\n\t\t\t\t\ty = -1;\r\n\t\t\t\t\trx = 0;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tDungeonMask.set(rx, y);\r\n\t\t\t\t\tDungeonMask.set(rx + 1, y);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\trx++;\r\n\t\t\tif (rx == DMAXX / 2) {\r\n\t\t\t\trx = 1;\r\n\t\t\t}\r\n\t\t}\r\n\t} while (rx != 0);\r\n}\r\n\r\n/**\r\n * @brief Find the number of mega tiles used by layout\r\n */\r\ninline size_t FindArea()\r\n{\r\n\t// Hell layouts are mirrored based on a single quadrant, this function is called after the quadrant has been\r\n\t// generated but before mirroring the layout. We need to multiply by 4 to get the expected number of tiles\r\n\treturn DungeonMask.count() * 4;\r\n}\r\n\r\nvoid ProtectQuads()\r\n{\r\n\tfor (int y = 0; y < 14; y++) {\r\n\t\tfor (int x = 0; x < 14; x++) {\r\n\t\t\tProtected.set(L4Hold.x + x, L4Hold.y + y);\r\n\t\t\tProtected.set(DMAXX - 1 - x - L4Hold.x, L4Hold.y + y);\r\n\t\t\tProtected.set(L4Hold.x + x, DMAXY - 1 - y - L4Hold.y);\r\n\t\t\tProtected.set(DMAXX - 1 - x - L4Hold.x, DMAXY - 1 - y - L4Hold.y);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LoadDiabQuads(bool preflag)\r\n{\r\n\t{\r\n\t\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l4data\\\\diab1.dun\");\r\n\t\tDiabloQuad1 = L4Hold + WorldTileDisplacement { 4, 4 };\r\n\t\tPlaceDunTiles(dunData.get(), DiabloQuad1, 6);\r\n\t}\r\n\t{\r\n\t\tauto dunData = LoadFileInMem<uint16_t>(preflag ? \"levels\\\\l4data\\\\diab2b.dun\" : \"levels\\\\l4data\\\\diab2a.dun\");\r\n\t\tDiabloQuad2 = WorldTilePosition(27 - L4Hold.x, 1 + L4Hold.y);\r\n\t\tPlaceDunTiles(dunData.get(), DiabloQuad2, 6);\r\n\t}\r\n\t{\r\n\t\tauto dunData = LoadFileInMem<uint16_t>(preflag ? \"levels\\\\l4data\\\\diab3b.dun\" : \"levels\\\\l4data\\\\diab3a.dun\");\r\n\t\tDiabloQuad3 = WorldTilePosition(1 + L4Hold.x, 27 - L4Hold.y);\r\n\t\tPlaceDunTiles(dunData.get(), DiabloQuad3, 6);\r\n\t}\r\n\t{\r\n\t\tauto dunData = LoadFileInMem<uint16_t>(preflag ? \"levels\\\\l4data\\\\diab4b.dun\" : \"levels\\\\l4data\\\\diab4a.dun\");\r\n\t\tDiabloQuad4 = WorldTilePosition(28 - L4Hold.x, 28 - L4Hold.y);\r\n\t\tPlaceDunTiles(dunData.get(), DiabloQuad4, 6);\r\n\t}\r\n}\r\n\r\nbool IsDURightWall(char d)\r\n{\r\n\tif (d == 25) {\r\n\t\treturn true;\r\n\t}\r\n\tif (d == 28) {\r\n\t\treturn true;\r\n\t}\r\n\tif (d == 23) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool IsDLLeftWall(char dd)\r\n{\r\n\tif (dd == 27) {\r\n\t\treturn true;\r\n\t}\r\n\tif (dd == 26) {\r\n\t\treturn true;\r\n\t}\r\n\tif (dd == 22) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid FixTransparency()\r\n{\r\n\tint yy = 16;\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tint xx = 16;\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\t// BUGFIX: Should check for `j > 0` first.\r\n\t\t\tif (IsDURightWall(dungeon[i][j]) && dungeon[i][j - 1] == 18) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\t// BUGFIX: Should check for `i + 1 < DMAXY` first.\r\n\t\t\tif (IsDLLeftWall(dungeon[i][j]) && dungeon[i + 1][j] == 19) {\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 18) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 19) {\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 24) {\r\n\t\t\t\tdTransVal[xx + 1][yy] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t\tdTransVal[xx + 1][yy + 1] = dTransVal[xx][yy];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 57) {\r\n\t\t\t\tdTransVal[xx - 1][yy] = dTransVal[xx][yy + 1];\r\n\t\t\t\tdTransVal[xx][yy] = dTransVal[xx][yy + 1];\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 53) {\r\n\t\t\t\tdTransVal[xx][yy - 1] = dTransVal[xx + 1][yy];\r\n\t\t\t\tdTransVal[xx][yy] = dTransVal[xx + 1][yy];\r\n\t\t\t}\r\n\t\t\txx += 2;\r\n\t\t}\r\n\t\tyy += 2;\r\n\t}\r\n}\r\n\r\nvoid FixCornerTiles()\r\n{\r\n\tfor (int j = 1; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 1; i < DMAXX - 1; i++) {\r\n\t\t\tif (dungeon[i][j] >= 18 && dungeon[i][j] <= 30) {\r\n\t\t\t\tif (dungeon[i + 1][j] < 18 || dungeon[i][j + 1] < 18) {\r\n\t\t\t\t\tdungeon[i][j] += 98;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Marks the edge of the map as solid/not part of the dungeon layout\r\n */\r\nvoid CloseOuterBorders()\r\n{\r\n\tfor (int x = 0; x < DMAXX / 2; x++) { // NOLINT(modernize-loop-convert)\r\n\t\tDungeonMask.reset(x, 0);\r\n\t}\r\n\tfor (int y = 0; y < DMAXY / 2; y++) {\r\n\t\tDungeonMask.reset(0, y);\r\n\t}\r\n}\r\n\r\nvoid GeneralFix()\r\n{\r\n\tfor (int j = 0; j < DMAXY - 1; j++) {\r\n\t\tfor (int i = 0; i < DMAXX - 1; i++) {\r\n\t\t\tif ((dungeon[i][j] == 24 || dungeon[i][j] == 122) && dungeon[i + 1][j] == 2 && dungeon[i][j + 1] == 5) {\r\n\t\t\t\tdungeon[i][j] = 17;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool PlaceStairs(lvl_entry entry)\r\n{\r\n\tstd::optional<Point> position;\r\n\r\n\t// Place stairs up\r\n\tposition = PlaceMiniSet(L4USTAIRS);\r\n\tif (!position)\r\n\t\treturn false;\r\n\tif (entry == ENTRY_MAIN)\r\n\t\tViewPosition = position->megaToWorld() + Displacement { 6, 6 };\r\n\r\n\tif (currlevel != 15) {\r\n\t\t// Place stairs down\r\n\t\tif (currlevel != 16) {\r\n\t\t\tif (Quests[Q_WARLORD].IsAvailable()) {\r\n\t\t\t\tif (entry == ENTRY_PREV)\r\n\t\t\t\t\tViewPosition = SetPiece.position.megaToWorld() + Displacement { 7, 7 };\r\n\t\t\t} else {\r\n\t\t\t\tposition = PlaceMiniSet(L4DSTAIRS);\r\n\t\t\t\tif (!position)\r\n\t\t\t\t\treturn false;\r\n\t\t\t\tif (entry == ENTRY_PREV)\r\n\t\t\t\t\tViewPosition = position->megaToWorld() + Displacement { 7, 5 };\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Place town warp stairs\r\n\t\tif (currlevel == 13) {\r\n\t\t\tposition = PlaceMiniSet(L4TWARP);\r\n\t\t\tif (!position)\r\n\t\t\t\treturn false;\r\n\t\t\tif (entry == ENTRY_TWARPDN)\r\n\t\t\t\tViewPosition = position->megaToWorld() + Displacement { 6, 6 };\r\n\t\t}\r\n\t} else {\r\n\t\t// Place hell gate\r\n\t\tposition = PlaceMiniSet(L4PENTA2);\r\n\t\tif (!position)\r\n\t\t\treturn false;\r\n\t\tQuests[Q_DIABLO].position = *position;\r\n\t\tif (entry == ENTRY_PREV)\r\n\t\t\tViewPosition = position->megaToWorld() + Displacement { 6, 5 };\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid GenerateLevel(lvl_entry entry)\r\n{\r\n\tif (LevelSeeds[currlevel])\r\n\t\tSetRndSeed(*LevelSeeds[currlevel]);\r\n\r\n\twhile (true) {\r\n\t\tDRLG_InitTrans();\r\n\r\n\t\tconstexpr size_t Minarea = 692;\r\n\t\tdo {\r\n\t\t\tLevelSeeds[currlevel] = GetLCGEngineState();\r\n\t\t\tInitDungeonFlags();\r\n\t\t\tFirstRoom();\r\n\t\t\tCloseOuterBorders();\r\n\t\t} while (FindArea() < Minarea);\r\n\r\n\t\tPrepareInnerBorders();\r\n\t\tMirrorDungeonLayout();\r\n\r\n\t\tMakeDmt();\r\n\t\tFixTilesPatterns();\r\n\t\tif (currlevel == 16) {\r\n\t\t\tProtectQuads();\r\n\t\t}\r\n\t\tif (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && UseMultiplayerQuests())) {\r\n\t\t\tfor (int spi = SetPieceRoom.position.x; spi < SetPieceRoom.position.x + SetPieceRoom.size.width - 1; spi++) {\r\n\t\t\t\tfor (int spj = SetPieceRoom.position.y; spj < SetPieceRoom.position.y + SetPieceRoom.size.height - 1; spj++) {\r\n\t\t\t\t\tProtected.set(spi, spj);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tAddWall();\r\n\t\tFloodTransparencyValues(6);\r\n\t\tFixTransparency();\r\n\t\tInitSetPiece();\r\n\t\tif (currlevel == 16) {\r\n\t\t\tLoadDiabQuads(true);\r\n\t\t}\r\n\t\tif (PlaceStairs(entry))\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tGeneralFix();\r\n\r\n\tif (currlevel != 16) {\r\n\t\tDRLG_PlaceThemeRooms(7, 10, 6, 8, true);\r\n\t}\r\n\r\n\tApplyShadowsPatterns();\r\n\tFixCornerTiles();\r\n\tSubstitution();\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n\r\n\tDRLG_CheckQuests(SetPieceRoom.position);\r\n\r\n\tif (currlevel == 15) {\r\n\t\tconst bool isGateOpen = UseMultiplayerQuests() || IsAnyOf(Quests[Q_DIABLO]._qactive, QUEST_ACTIVE, QUEST_DONE);\r\n\t\tif (!isGateOpen)\r\n\t\t\tL4PENTA.place(Quests[Q_DIABLO].position);\r\n\r\n\t\tfor (WorldTileCoord j = 1; j < DMAXY; j++) {\r\n\t\t\tfor (WorldTileCoord i = 1; i < DMAXX; i++) {\r\n\t\t\t\tif (IsAnyOf(dungeon[i][j], 98, 107)) {\r\n\t\t\t\t\tMake_SetPC({ WorldTilePosition(i - 1, j - 1), { 5, 5 } });\r\n\t\t\t\t\t// Set the portal position to the location of the northmost pentagram tile.\r\n\t\t\t\t\tQuests[Q_BETRAYER].position = Point(i, j).megaToWorld();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (currlevel == 16) {\r\n\t\tLoadDiabQuads(false);\r\n\t}\r\n}\r\n\r\nvoid Pass3()\r\n{\r\n\tDRLG_LPass3(30 - 1);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid CreateL4Dungeon(uint32_t rseed, lvl_entry entry)\r\n{\r\n\tSetRndSeed(rseed);\r\n\r\n\tGenerateLevel(entry);\r\n\r\n\tPass3();\r\n}\r\n\r\nvoid LoadPreL4Dungeon(const char *path)\r\n{\r\n\tmemset(dungeon, 30, sizeof(dungeon));\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\tPlaceDunTiles(dunData.get(), { 0, 0 }, 6);\r\n\r\n\tmemcpy(pdungeon, dungeon, sizeof(pdungeon));\r\n}\r\n\r\nvoid LoadL4Dungeon(const char *path, Point spawn)\r\n{\r\n\tLoadDungeonBase(path, spawn, 6, 30);\r\n\r\n\tPass3();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/drlg_l4.h",
    "content": "/**\r\n * @file levels/drlg_l4.h\r\n *\r\n * Interface of the hell level generation algorithms.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/world_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern WorldTilePosition DiabloQuad1;\r\nextern WorldTilePosition DiabloQuad2;\r\nextern WorldTilePosition DiabloQuad3;\r\nextern WorldTilePosition DiabloQuad4;\r\n\r\nvoid CreateL4Dungeon(uint32_t rseed, lvl_entry entry);\r\nvoid LoadPreL4Dungeon(const char *path);\r\nvoid LoadL4Dungeon(const char *path, Point spawn);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/dun_tile.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"utils/enum_traits.h\"\r\n\r\n#define TILE_WIDTH 64\r\n#define TILE_HEIGHT 32\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * Level tile type.\r\n *\r\n * The tile type determines data encoding and the shape.\r\n *\r\n * Each tile type has its own encoding but they all encode data in the order\r\n * of bottom-to-top (bottom row first).\r\n */\r\nenum class TileType : uint8_t {\r\n\t/**\r\n\t * 🮆 A 32x32 square. Stored as an array of pixels.\r\n\t */\r\n\tSquare,\r\n\r\n\t/**\r\n\t * 🮆 A 32x32 square with transparency. RLE encoded.\r\n\t *\r\n\t * Each run starts with an int8_t value.\r\n\t * If positive, it is followed by this many pixels.\r\n\t * If negative, it indicates `-value` fully transparent pixels, which are omitted.\r\n\t *\r\n\t * Runs do not cross row boundaries.\r\n\t */\r\n\tTransparentSquare,\r\n\r\n\t/**\r\n\t *🭮 Left-pointing 32x31 triangle. Encoded as 31 varying-width rows with 2 padding bytes before every even row.\r\n\t * We remove the padding bytes in `ReencodeDungeonCels`.\r\n\t *\r\n\t * The smallest rows (bottom and top) are 2px wide, the largest row is 32px wide (middle row).\r\n\t *\r\n\t * Encoding:\r\n\t * for i in [0, 30]:\r\n\t * - 2 unused bytes if i is even\r\n\t * - row (only the pixels within the triangle)\r\n\t */\r\n\tLeftTriangle,\r\n\r\n\t/**\r\n\t * 🭬Right-pointing 32x31 triangle.  Encoded as 31 varying-width rows with 2 padding bytes after every even row.\r\n\t * We remove the padding bytes in `ReencodeDungeonCels`.\r\n\t *\r\n\t * The smallest rows (bottom and top) are 2px wide, the largest row is 32px wide (middle row).\r\n\t *\r\n\t * Encoding:\r\n\t * for i in [0, 30]:\r\n\t * - row (only the pixels within the triangle)\r\n\t * - 2 unused bytes if i is even\r\n\t */\r\n\tRightTriangle,\r\n\r\n\t/**\r\n\t * 🭓 Left-pointing 32x32 trapezoid: a 32x16 rectangle and the 16x16 bottom part of `LeftTriangle`.\r\n\t *\r\n\t * Begins with triangle part, which uses the `LeftTriangle` encoding,\r\n\t * and is followed by a flat array of pixels for the top rectangle part.\r\n\t */\r\n\tLeftTrapezoid,\r\n\r\n\t/**\r\n\t * 🭞 Right-pointing 32x32 trapezoid: 32x16 rectangle and the 16x16 bottom part of `RightTriangle`.\r\n\t *\r\n\t * Begins with the triangle part, which uses the `RightTriangle` encoding,\r\n\t * and is followed by a flat array of pixels for the top rectangle part.\r\n\t */\r\n\tRightTrapezoid,\r\n};\r\n\r\n/**\r\n * Specifies the current MIN block of the level CEL file, as used during rendering of the level tiles.\r\n */\r\nstruct LevelCelBlock {\r\n\tuint16_t data;\r\n\r\n\t[[nodiscard]] bool hasValue() const\r\n\t{\r\n\t\treturn data != 0;\r\n\t}\r\n\r\n\t[[nodiscard]] TileType type() const\r\n\t{\r\n\t\treturn static_cast<TileType>((data & 0x7000) >> 12);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns the 1-based index of the frame in `pDungeonCels`.\r\n\t */\r\n\t[[nodiscard]] uint16_t frame() const\r\n\t{\r\n\t\treturn data & 0xFFF;\r\n\t}\r\n};\r\n\r\nenum class TileProperties : uint8_t {\r\n\t// clang-format off\r\n\tNone             = 0,\r\n\tSolid            = 1 << 0,\r\n\tBlockLight       = 1 << 1,\r\n\tBlockMissile     = 1 << 2,\r\n\tTransparent      = 1 << 3,\r\n\tTransparentLeft  = 1 << 4,\r\n\tTransparentRight = 1 << 5,\r\n\tTrap             = 1 << 7,\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(TileProperties);\r\n\r\nstruct MICROS {\r\n\tLevelCelBlock mt[16];\r\n};\r\n\r\n/** Width of a tile rendering primitive. */\r\nconstexpr int_fast16_t DunFrameWidth = TILE_WIDTH / 2;\r\n\r\n/** Height of a tile rendering primitive (except triangles). */\r\nconstexpr int_fast16_t DunFrameHeight = TILE_HEIGHT;\r\n\r\nconstexpr int_fast16_t DunFrameTriangleHeight = 31;\r\n\r\nconstexpr size_t ReencodedTriangleFrameSize = 544 - 32;\r\nconstexpr size_t ReencodedTrapezoidFrameSize = 800 - 16;\r\n\r\n/**\r\n * @return Returns the center of the sprite relative to the center of the tile.\r\n */\r\nconstexpr int CalculateSpriteTileCenterX(int width)\r\n{\r\n\treturn (width - TILE_WIDTH) / 2;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/gendung.cpp",
    "content": "#include \"levels/gendung.h\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <stack>\r\n#include <string>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"items.h\"\r\n#include \"levels/drlg_l1.h\"\r\n#include \"levels/drlg_l2.h\"\r\n#include \"levels/drlg_l3.h\"\r\n#include \"levels/drlg_l4.h\"\r\n#include \"levels/reencode_dun_cels.hpp\"\r\n#include \"levels/town.h\"\r\n#include \"lighting.h\"\r\n#include \"monster.h\"\r\n#include \"objects.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/bitset2d.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nBitset2d<DMAXX, DMAXY> DungeonMask;\r\nuint8_t dungeon[DMAXX][DMAXY];\r\nuint8_t pdungeon[DMAXX][DMAXY];\r\nBitset2d<DMAXX, DMAXY> Protected;\r\nWorldTileRectangle SetPieceRoom;\r\nWorldTileRectangle SetPiece;\r\nOptionalOwnedClxSpriteList pSpecialCels;\r\nstd::unique_ptr<MegaTile[]> pMegaTiles;\r\nstd::unique_ptr<std::byte[]> pDungeonCels;\r\nTileProperties SOLData[MAXTILES];\r\nWorldTilePosition dminPosition;\r\nWorldTilePosition dmaxPosition;\r\ndungeon_type leveltype;\r\nuint8_t currlevel;\r\nbool setlevel;\r\n_setlevels setlvlnum;\r\ndungeon_type setlvltype;\r\nPoint ViewPosition;\r\nuint_fast8_t MicroTileLen;\r\nint8_t TransVal;\r\nstd::array<bool, 256> TransList;\r\nuint16_t dPiece[MAXDUNX][MAXDUNY];\r\nMICROS DPieceMicros[MAXTILES];\r\nint8_t dTransVal[MAXDUNX][MAXDUNY];\r\nuint8_t dLight[MAXDUNX][MAXDUNY];\r\nuint8_t dPreLight[MAXDUNX][MAXDUNY];\r\nDungeonFlag dFlags[MAXDUNX][MAXDUNY];\r\nint8_t dPlayer[MAXDUNX][MAXDUNY];\r\nint16_t dMonster[MAXDUNX][MAXDUNY];\r\nint8_t dCorpse[MAXDUNX][MAXDUNY];\r\nint8_t dObject[MAXDUNX][MAXDUNY];\r\nint8_t dSpecial[MAXDUNX][MAXDUNY];\r\nint themeCount;\r\nTHEME_LOC themeLoc[MAXTHEMES];\r\n\r\nnamespace {\r\n\r\nstd::unique_ptr<uint16_t[]> LoadMinData(size_t &tileCount)\r\n{\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_TOWN: {\r\n\t\tauto min = LoadFileInMemWithStatus<uint16_t>(\"nlevels\\\\towndata\\\\town.min\", &tileCount);\r\n\t\tif (!min.has_value()) {\r\n\t\t\treturn LoadFileInMem<uint16_t>(\"levels\\\\towndata\\\\town.min\", &tileCount);\r\n\t\t} else {\r\n\t\t\treturn std::move(*min);\r\n\t\t}\r\n\t}\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\treturn LoadFileInMem<uint16_t>(\"levels\\\\l1data\\\\l1.min\", &tileCount);\r\n\tcase DTYPE_CATACOMBS:\r\n\t\treturn LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\l2.min\", &tileCount);\r\n\tcase DTYPE_CAVES:\r\n\t\treturn LoadFileInMem<uint16_t>(\"levels\\\\l3data\\\\l3.min\", &tileCount);\r\n\tcase DTYPE_HELL:\r\n\t\treturn LoadFileInMem<uint16_t>(\"levels\\\\l4data\\\\l4.min\", &tileCount);\r\n\tcase DTYPE_NEST:\r\n\t\treturn LoadFileInMem<uint16_t>(\"nlevels\\\\l6data\\\\l6.min\", &tileCount);\r\n\tcase DTYPE_CRYPT:\r\n\t\treturn LoadFileInMem<uint16_t>(\"nlevels\\\\l5data\\\\l5.min\", &tileCount);\r\n\tdefault:\r\n\t\tapp_fatal(\"LoadMinData\");\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Starting from the origin point determine how much floor space is available with the given bounds\r\n *\r\n * Essentially looks for the widest/tallest rectangular area of at least the minimum size, but due to a weird/buggy\r\n * bounds check can return an area smaller than the available width/height.\r\n *\r\n * @param floor what value defines floor tiles within a dungeon\r\n * @param origin starting point for the search\r\n * @param minSize minimum allowable value for both dimensions\r\n * @param maxSize maximum allowable value for both dimensions\r\n * @return how much width/height is available for a theme room or an empty optional if there's not enough space\r\n */\r\nstd::optional<WorldTileSize> GetSizeForThemeRoom(uint8_t floor, WorldTilePosition origin, WorldTileCoord minSize, WorldTileCoord maxSize)\r\n{\r\n\tif (origin.x + maxSize > DMAXX && origin.y + maxSize > DMAXY) {\r\n\t\treturn {}; // Original broken bounds check, avoids lower right corner\r\n\t}\r\n\tif (IsNearThemeRoom(origin)) {\r\n\t\treturn {};\r\n\t}\r\n\r\n\tconst WorldTileCoord maxWidth = std::min<WorldTileCoord>(maxSize, DMAXX - origin.x);\r\n\tconst WorldTileCoord maxHeight = std::min<WorldTileCoord>(maxSize, DMAXY - origin.y);\r\n\r\n\tWorldTileSize room { maxWidth, maxHeight };\r\n\r\n\tfor (WorldTileCoord i = 0; i < maxSize; i++) {\r\n\t\tWorldTileCoord width = i < room.height ? i : 0;\r\n\t\tif (i < maxHeight) {\r\n\t\t\twhile (width < room.width) {\r\n\t\t\t\tif (dungeon[origin.x + width][origin.y + i] != floor)\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\twidth++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tWorldTileCoord height = i < room.width ? i : 0;\r\n\t\tif (i < maxWidth) {\r\n\t\t\twhile (height < room.height) {\r\n\t\t\t\tif (dungeon[origin.x + i][origin.y + height] != floor)\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\theight++;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (width < minSize || height < minSize) {\r\n\t\t\tif (i < minSize)\r\n\t\t\t\treturn {};\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\troom = { std::min(room.width, width), std::min(room.height, height) };\r\n\t}\r\n\r\n\treturn room - 2;\r\n}\r\n\r\nvoid CreateThemeRoom(int themeIndex)\r\n{\r\n\tconst int lx = themeLoc[themeIndex].room.position.x;\r\n\tconst int ly = themeLoc[themeIndex].room.position.y;\r\n\tconst int hx = lx + themeLoc[themeIndex].room.size.width;\r\n\tconst int hy = ly + themeLoc[themeIndex].room.size.height;\r\n\r\n\tfor (int yy = ly; yy < hy; yy++) {\r\n\t\tfor (int xx = lx; xx < hx; xx++) {\r\n\t\t\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\t\t\tif (yy == ly || yy == hy - 1) {\r\n\t\t\t\t\tdungeon[xx][yy] = 2;\r\n\t\t\t\t} else if (xx == lx || xx == hx - 1) {\r\n\t\t\t\t\tdungeon[xx][yy] = 1;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdungeon[xx][yy] = 3;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (IsAnyOf(leveltype, DTYPE_CAVES, DTYPE_NEST)) {\r\n\t\t\t\tif (yy == ly || yy == hy - 1) {\r\n\t\t\t\t\tdungeon[xx][yy] = 134;\r\n\t\t\t\t} else if (xx == lx || xx == hx - 1) {\r\n\t\t\t\t\tdungeon[xx][yy] = 137;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdungeon[xx][yy] = 7;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (leveltype == DTYPE_HELL) {\r\n\t\t\t\tif (yy == ly || yy == hy - 1) {\r\n\t\t\t\t\tdungeon[xx][yy] = 2;\r\n\t\t\t\t} else if (xx == lx || xx == hx - 1) {\r\n\t\t\t\t\tdungeon[xx][yy] = 1;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdungeon[xx][yy] = 6;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\tdungeon[lx][ly] = 8;\r\n\t\tdungeon[hx - 1][ly] = 7;\r\n\t\tdungeon[lx][hy - 1] = 9;\r\n\t\tdungeon[hx - 1][hy - 1] = 6;\r\n\t}\r\n\tif (IsAnyOf(leveltype, DTYPE_CAVES, DTYPE_NEST)) {\r\n\t\tdungeon[lx][ly] = 150;\r\n\t\tdungeon[hx - 1][ly] = 151;\r\n\t\tdungeon[lx][hy - 1] = 152;\r\n\t\tdungeon[hx - 1][hy - 1] = 138;\r\n\t}\r\n\tif (leveltype == DTYPE_HELL) {\r\n\t\tdungeon[lx][ly] = 9;\r\n\t\tdungeon[hx - 1][ly] = 16;\r\n\t\tdungeon[lx][hy - 1] = 15;\r\n\t\tdungeon[hx - 1][hy - 1] = 12;\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\tif (FlipCoin())\r\n\t\t\tdungeon[hx - 1][(ly + hy) / 2] = 4;\r\n\t\telse\r\n\t\t\tdungeon[(lx + hx) / 2][hy - 1] = 5;\r\n\t}\r\n\tif (IsAnyOf(leveltype, DTYPE_CAVES, DTYPE_NEST)) {\r\n\t\tif (FlipCoin())\r\n\t\t\tdungeon[hx - 1][(ly + hy) / 2] = 147;\r\n\t\telse\r\n\t\t\tdungeon[(lx + hx) / 2][hy - 1] = 146;\r\n\t}\r\n\tif (leveltype == DTYPE_HELL) {\r\n\t\tif (FlipCoin()) {\r\n\t\t\tconst int yy = (ly + hy) / 2;\r\n\t\t\tdungeon[hx - 1][yy - 1] = 53;\r\n\t\t\tdungeon[hx - 1][yy] = 6;\r\n\t\t\tdungeon[hx - 1][yy + 1] = 52;\r\n\t\t\tdungeon[hx - 2][yy - 1] = 54;\r\n\t\t} else {\r\n\t\t\tconst int xx = (lx + hx) / 2;\r\n\t\t\tdungeon[xx - 1][hy - 1] = 57;\r\n\t\t\tdungeon[xx][hy - 1] = 6;\r\n\t\t\tdungeon[xx + 1][hy - 1] = 56;\r\n\t\t\tdungeon[xx][hy - 2] = 59;\r\n\t\t\tdungeon[xx - 1][hy - 2] = 58;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool IsFloor(Point p, uint8_t floorID)\r\n{\r\n\tconst int i = (p.x - 16) / 2;\r\n\tconst int j = (p.y - 16) / 2;\r\n\tif (i < 0 || i >= DMAXX)\r\n\t\treturn false;\r\n\tif (j < 0 || j >= DMAXY)\r\n\t\treturn false;\r\n\treturn dungeon[i][j] == floorID;\r\n}\r\n\r\nvoid FillTransparencyValues(Point floor, uint8_t floorID)\r\n{\r\n\tconst Direction allDirections[] = {\r\n\t\tDirection::North,\r\n\t\tDirection::South,\r\n\t\tDirection::East,\r\n\t\tDirection::West,\r\n\t\tDirection::NorthEast,\r\n\t\tDirection::NorthWest,\r\n\t\tDirection::SouthEast,\r\n\t\tDirection::SouthWest,\r\n\t};\r\n\r\n\t// We only fill in the surrounding tiles if they are not floor tiles\r\n\t// because they would otherwise not be visited by the span filling algorithm\r\n\tfor (const Direction dir : allDirections) {\r\n\t\tconst Point adjacent = floor + dir;\r\n\t\tif (!IsFloor(adjacent, floorID))\r\n\t\t\tdTransVal[adjacent.x][adjacent.y] = TransVal;\r\n\t}\r\n\r\n\tdTransVal[floor.x][floor.y] = TransVal;\r\n}\r\n\r\nvoid FindTransparencyValues(Point floor, uint8_t floorID)\r\n{\r\n\t// Algorithm adapted from https://en.wikipedia.org/wiki/Flood_fill#Span_Filling\r\n\t// Modified to include diagonally adjacent tiles that would otherwise not be visited\r\n\t// Also, Wikipedia's selection for the initial seed is incorrect\r\n\tstruct Seed {\r\n\t\tint scanStart;\r\n\t\tint scanEnd;\r\n\t\tint y;\r\n\t\tint dy;\r\n\t};\r\n\tstd::stack<Seed, std::vector<Seed>> seedStack;\r\n\tseedStack.push({ floor.x, floor.x + 1, floor.y, 1 });\r\n\r\n\tconst auto isInside = [floorID](int x, int y) {\r\n\t\tif (dTransVal[x][y] != 0)\r\n\t\t\treturn false;\r\n\t\treturn IsFloor({ x, y }, floorID);\r\n\t};\r\n\r\n\tconst auto set = [floorID](int x, int y) {\r\n\t\tFillTransparencyValues({ x, y }, floorID);\r\n\t};\r\n\r\n\tconst Displacement left = { -1, 0 };\r\n\tconst Displacement right = { 1, 0 };\r\n\tconst auto checkDiagonals = [&](Point p, Displacement direction) {\r\n\t\tconst Point up = p + Displacement { 0, -1 };\r\n\t\tconst Point upOver = up + direction;\r\n\t\tif (!isInside(up.x, up.y) && isInside(upOver.x, upOver.y))\r\n\t\t\tseedStack.push({ upOver.x, upOver.x + 1, upOver.y, -1 });\r\n\r\n\t\tconst Point down = p + Displacement { 0, 1 };\r\n\t\tconst Point downOver = down + direction;\r\n\t\tif (!isInside(down.x, down.y) && isInside(downOver.x, downOver.y))\r\n\t\t\tseedStack.push(Seed { downOver.x, downOver.x + 1, downOver.y, 1 });\r\n\t};\r\n\r\n\twhile (!seedStack.empty()) {\r\n\t\tconst auto [scanStart, scanEnd, y, dy] = seedStack.top();\r\n\t\tseedStack.pop();\r\n\r\n\t\tint scanLeft = scanStart;\r\n\t\tif (isInside(scanLeft, y)) {\r\n\t\t\twhile (isInside(scanLeft - 1, y)) {\r\n\t\t\t\tset(scanLeft - 1, y);\r\n\t\t\t\tscanLeft--;\r\n\t\t\t}\r\n\t\t\tcheckDiagonals({ scanLeft, y }, left);\r\n\t\t}\r\n\t\tif (scanLeft < scanStart)\r\n\t\t\tseedStack.push(Seed { scanLeft, scanStart - 1, y - dy, -dy });\r\n\r\n\t\tint scanRight = scanStart;\r\n\t\twhile (scanRight < scanEnd) {\r\n\t\t\twhile (isInside(scanRight, y)) {\r\n\t\t\t\tset(scanRight, y);\r\n\t\t\t\tscanRight++;\r\n\t\t\t}\r\n\t\t\tseedStack.push(Seed { scanLeft, scanRight - 1, y + dy, dy });\r\n\t\t\tif (scanRight - 1 > scanEnd)\r\n\t\t\t\tseedStack.push(Seed { scanEnd + 1, scanRight - 1, y - dy, -dy });\r\n\t\t\tif (scanLeft < scanRight)\r\n\t\t\t\tcheckDiagonals({ scanRight - 1, y }, right);\r\n\r\n\t\t\twhile (scanRight < scanEnd && !isInside(scanRight, y))\r\n\t\t\t\tscanRight++;\r\n\t\t\tscanLeft = scanRight;\r\n\t\t\tif (scanLeft < scanEnd)\r\n\t\t\t\tcheckDiagonals({ scanLeft, y }, left);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitGlobals()\r\n{\r\n\tmemset(dFlags, 0, sizeof(dFlags));\r\n\tmemset(dPlayer, 0, sizeof(dPlayer));\r\n\tmemset(dMonster, 0, sizeof(dMonster));\r\n\tmemset(dCorpse, 0, sizeof(dCorpse));\r\n\tmemset(dItem, 0, sizeof(dItem));\r\n\tmemset(dObject, 0, sizeof(dObject));\r\n\tmemset(dSpecial, 0, sizeof(dSpecial));\r\n\tuint8_t defaultLight = leveltype == DTYPE_TOWN ? 0 : 15;\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\tdefaultLight = 0;\r\n#endif\r\n\tmemset(dLight, defaultLight, sizeof(dLight));\r\n\r\n\tDRLG_InitTrans();\r\n\r\n\tdminPosition = WorldTilePosition(0, 0).megaToWorld();\r\n\tdmaxPosition = WorldTilePosition(40, 40).megaToWorld();\r\n\tSetPieceRoom = { { 0, 0 }, { 0, 0 } };\r\n\tSetPiece = { { 0, 0 }, { 0, 0 } };\r\n}\r\n\r\n} // namespace\r\n\r\n#ifdef BUILD_TESTING\r\nstd::optional<WorldTileSize> GetSizeForThemeRoom()\r\n{\r\n\treturn GetSizeForThemeRoom(0, { 0, 0 }, 5, 10);\r\n}\r\n#endif\r\n\r\ndungeon_type GetLevelType(int level)\r\n{\r\n\tif (level == 0)\r\n\t\treturn DTYPE_TOWN;\r\n\tif (level <= 4)\r\n\t\treturn DTYPE_CATHEDRAL;\r\n\tif (level <= 8)\r\n\t\treturn DTYPE_CATACOMBS;\r\n\tif (level <= 12)\r\n\t\treturn DTYPE_CAVES;\r\n\tif (level <= 16)\r\n\t\treturn DTYPE_HELL;\r\n\tif (level <= 20)\r\n\t\treturn DTYPE_NEST;\r\n\tif (level <= 24)\r\n\t\treturn DTYPE_CRYPT;\r\n\r\n\treturn DTYPE_NONE;\r\n}\r\n\r\nvoid CreateDungeon(uint32_t rseed, lvl_entry entry)\r\n{\r\n\tInitGlobals();\r\n\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_TOWN:\r\n\t\tCreateTown(entry);\r\n\t\tbreak;\r\n\tcase DTYPE_CATHEDRAL:\r\n\tcase DTYPE_CRYPT:\r\n\t\tCreateL5Dungeon(rseed, entry);\r\n\t\tbreak;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\tCreateL2Dungeon(rseed, entry);\r\n\t\tbreak;\r\n\tcase DTYPE_CAVES:\r\n\tcase DTYPE_NEST:\r\n\t\tCreateL3Dungeon(rseed, entry);\r\n\t\tbreak;\r\n\tcase DTYPE_HELL:\r\n\t\tCreateL4Dungeon(rseed, entry);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"Invalid level type\");\r\n\t}\r\n\r\n\tMake_SetPC(SetPiece);\r\n}\r\n\r\ntl::expected<void, std::string> LoadLevelSOLData()\r\n{\r\n\tswitch (leveltype) {\r\n\tcase DTYPE_TOWN:\r\n\t\tif (!LoadFileInMemWithStatus(\"nlevels\\\\towndata\\\\town.sol\", SOLData).has_value()) {\r\n\t\t\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"levels\\\\towndata\\\\town.sol\", SOLData));\r\n\t\t}\r\n\t\tbreak;\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"levels\\\\l1data\\\\l1.sol\", SOLData));\r\n\t\t// Fix incorrectly marked arched tiles\r\n\t\tSOLData[9] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[15] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[16] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[20] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[21] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[27] |= TileProperties::BlockMissile;\r\n\t\tSOLData[28] |= TileProperties::BlockMissile;\r\n\t\tSOLData[51] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[56] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[58] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[61] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[63] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[65] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[72] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[208] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[247] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[253] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[257] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[323] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tSOLData[403] |= TileProperties::BlockLight;\r\n\t\t// Fix incorrectly marked pillar tile\r\n\t\tSOLData[24] |= TileProperties::BlockLight;\r\n\t\t// Fix incorrectly marked wall tile\r\n\t\tSOLData[450] |= TileProperties::BlockLight | TileProperties::BlockMissile;\r\n\t\tbreak;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"levels\\\\l2data\\\\l2.sol\", SOLData));\r\n\t\tbreak;\r\n\tcase DTYPE_CAVES:\r\n\t\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"levels\\\\l3data\\\\l3.sol\", SOLData));\r\n\t\t// The graphics for tile 48 sub-tile 171 frame 461 are partly incorrect, as they\r\n\t\t// have a few pixels that should belong to the solid tile 49 instead.\r\n\t\t// Marks the sub-tile as \"BlockMissile\" to avoid treating it as a floor during rendering.\r\n\t\tSOLData[170] |= TileProperties::BlockMissile;\r\n\t\t// Fence sub-tiles 481 and 487 are substitutes for solid sub-tiles 473 and 479\r\n\t\t// but are not marked as solid.\r\n\t\tSOLData[481] |= TileProperties::Solid;\r\n\t\tSOLData[487] |= TileProperties::Solid;\r\n\t\tbreak;\r\n\tcase DTYPE_HELL:\r\n\t\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"levels\\\\l4data\\\\l4.sol\", SOLData));\r\n\t\tSOLData[210] = TileProperties::None; // Tile is incorrectly marked as being solid\r\n\t\tbreak;\r\n\tcase DTYPE_NEST:\r\n\t\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"nlevels\\\\l6data\\\\l6.sol\", SOLData));\r\n\t\tbreak;\r\n\tcase DTYPE_CRYPT:\r\n\t\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"nlevels\\\\l5data\\\\l5.sol\", SOLData));\r\n\t\tSOLData[142] = TileProperties::None; // Tile is incorrectly marked as being solid\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn tl::make_unexpected(\"LoadLevelSOLData\");\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid SetDungeonMicros(std::unique_ptr<std::byte[]> &dungeonCels, uint_fast8_t &microTileLen)\r\n{\r\n\tmicroTileLen = 10;\r\n\tsize_t blocks = 10;\r\n\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tmicroTileLen = 16;\r\n\t\tblocks = 16;\r\n\t} else if (leveltype == DTYPE_HELL) {\r\n\t\tmicroTileLen = 12;\r\n\t\tblocks = 16;\r\n\t}\r\n\r\n\tsize_t tileCount;\r\n\tconst std::unique_ptr<uint16_t[]> levelPieces = LoadMinData(tileCount);\r\n\r\n\tankerl::unordered_dense::map<uint16_t, DunFrameInfo> frameToTypeMap;\r\n\tframeToTypeMap.reserve(4096);\r\n\tfor (size_t levelPieceId = 0; levelPieceId < tileCount / blocks; levelPieceId++) {\r\n\t\tuint16_t *pieces = &levelPieces[blocks * levelPieceId];\r\n\t\tfor (uint32_t block = 0; block < blocks; block++) {\r\n\t\t\tconst LevelCelBlock levelCelBlock { Swap16LE(pieces[blocks - 2 + (block & 1) - (block & 0xE)]) };\r\n\t\t\tDPieceMicros[levelPieceId].mt[block] = levelCelBlock;\r\n\t\t\tif (levelCelBlock.hasValue()) {\r\n\t\t\t\tif (const auto it = frameToTypeMap.find(levelCelBlock.frame()); it == frameToTypeMap.end()) {\r\n\t\t\t\t\tframeToTypeMap.emplace_hint(it, levelCelBlock.frame(),\r\n\t\t\t\t\t    DunFrameInfo { static_cast<uint8_t>(block), levelCelBlock.type(), SOLData[levelPieceId] });\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tstd::vector<std::pair<uint16_t, DunFrameInfo>> frameToTypeList = std::move(frameToTypeMap).extract();\r\n\tc_sort(frameToTypeList, [](const std::pair<uint16_t, DunFrameInfo> &a, const std::pair<uint16_t, DunFrameInfo> &b) {\r\n\t\treturn a.first < b.first;\r\n\t});\r\n\tReencodeDungeonCels(dungeonCels, frameToTypeList);\r\n\r\n\tstd::vector<std::pair<uint16_t, uint16_t>> celBlockAdjustments = ComputeCelBlockAdjustments(frameToTypeList);\r\n\tif (celBlockAdjustments.size() == 0) return;\r\n\tfor (size_t levelPieceId = 0; levelPieceId < tileCount / blocks; levelPieceId++) {\r\n\t\tfor (uint32_t block = 0; block < blocks; block++) {\r\n\t\t\tLevelCelBlock &levelCelBlock = DPieceMicros[levelPieceId].mt[block];\r\n\t\t\tconst uint16_t frame = levelCelBlock.frame();\r\n\t\t\tconst auto pair = std::make_pair(frame, frame);\r\n\t\t\tconst auto it = std::upper_bound(celBlockAdjustments.begin(), celBlockAdjustments.end(), pair,\r\n\t\t\t    [](std::pair<uint16_t, uint16_t> p1, std::pair<uint16_t, uint16_t> p2) { return p1.first < p2.first; });\r\n\t\t\tif (it != celBlockAdjustments.end()) {\r\n\t\t\t\tlevelCelBlock.data -= it->second;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DRLG_InitTrans()\r\n{\r\n\tmemset(dTransVal, 0, sizeof(dTransVal));\r\n\tTransList = {}; // TODO duplicate reset in InitLighting()\r\n\tTransVal = 1;\r\n}\r\n\r\nvoid DRLG_RectTrans(WorldTileRectangle area)\r\n{\r\n\tconst WorldTilePosition position = area.position;\r\n\tconst WorldTileSize size = area.size;\r\n\r\n\tfor (int j = position.y; j <= position.y + size.height; j++) {\r\n\t\tfor (int i = position.x; i <= position.x + size.width; i++) {\r\n\t\t\tdTransVal[i][j] = TransVal;\r\n\t\t}\r\n\t}\r\n\r\n\tTransVal++;\r\n}\r\n\r\nvoid DRLG_MRectTrans(WorldTileRectangle area)\r\n{\r\n\tDRLG_RectTrans({ area.position.megaToWorld() + WorldTileDisplacement { 1, 1 }, area.size * 2 - 1 });\r\n}\r\n\r\nvoid DRLG_MRectTrans(WorldTilePosition origin, WorldTilePosition extent)\r\n{\r\n\tDRLG_MRectTrans({ origin, WorldTileSize(extent.x - origin.x, extent.y - origin.y) });\r\n}\r\n\r\nvoid DRLG_CopyTrans(int sx, int sy, int dx, int dy)\r\n{\r\n\tdTransVal[dx][dy] = dTransVal[sx][sy];\r\n}\r\n\r\nvoid LoadTransparency(const uint16_t *dunData)\r\n{\r\n\tWorldTileSize size = GetDunSize(dunData);\r\n\r\n\tconst int layer2Offset = 2 + size.width * size.height;\r\n\r\n\t// The rest of the layers are at dPiece scale\r\n\tsize *= static_cast<WorldTileCoord>(2);\r\n\r\n\tconst uint16_t *transparentLayer = &dunData[layer2Offset + size.width * size.height * 3];\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tdTransVal[16 + i][16 + j] = static_cast<int8_t>(Swap16LE(*transparentLayer));\r\n\t\t\ttransparentLayer++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LoadDungeonBase(const char *path, Point spawn, int floorId, int dirtId)\r\n{\r\n\tViewPosition = spawn;\r\n\r\n\tInitGlobals();\r\n\r\n\tmemset(dungeon, dirtId, sizeof(dungeon));\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\tPlaceDunTiles(dunData.get(), { 0, 0 }, floorId);\r\n\tLoadTransparency(dunData.get());\r\n\r\n\tSetMapMonsters(dunData.get(), Point(0, 0).megaToWorld());\r\n\tInitAllMonsterGFX();\r\n\tSetMapObjects(dunData.get(), 0, 0);\r\n}\r\n\r\nvoid Make_SetPC(WorldTileRectangle area)\r\n{\r\n\tconst WorldTilePosition position = area.position.megaToWorld();\r\n\tconst WorldTileSize size = area.size * 2;\r\n\r\n\tfor (unsigned j = 0; j < size.height; j++) {\r\n\t\tfor (unsigned i = 0; i < size.width; i++) {\r\n\t\t\tdFlags[position.x + i][position.y + j] |= DungeonFlag::Populated;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nstd::optional<Point> PlaceMiniSet(const Miniset &miniset, int tries, bool drlg1Quirk)\r\n{\r\n\tconst int sw = miniset.size.width;\r\n\tconst int sh = miniset.size.height;\r\n\tPoint position { GenerateRnd(DMAXX - sw), GenerateRnd(DMAXY - sh) };\r\n\r\n\tfor (int i = 0; i < tries; i++, position.x++) {\r\n\t\tif (position.x == DMAXX - sw) {\r\n\t\t\tposition.x = 0;\r\n\t\t\tposition.y++;\r\n\t\t\tif (position.y == DMAXY - sh) {\r\n\t\t\t\tposition.y = 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Limit the position of SetPieces for compatibility with Diablo bug\r\n\t\tif (drlg1Quirk) {\r\n\t\t\tbool valid = true;\r\n\t\t\tif (position.x <= 12) {\r\n\t\t\t\tposition.x++;\r\n\t\t\t\tvalid = false;\r\n\t\t\t}\r\n\t\t\tif (position.y <= 12) {\r\n\t\t\t\tposition.y++;\r\n\t\t\t\tvalid = false;\r\n\t\t\t}\r\n\t\t\tif (!valid) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (SetPieceRoom.contains(position))\r\n\t\t\tcontinue;\r\n\t\tif (!miniset.matches(position))\r\n\t\t\tcontinue;\r\n\r\n\t\tminiset.place(position);\r\n\r\n\t\treturn position;\r\n\t}\r\n\r\n\treturn {};\r\n}\r\n\r\nvoid PlaceDunTiles(const uint16_t *dunData, Point position, int floorId)\r\n{\r\n\tconst WorldTileSize size = GetDunSize(dunData);\r\n\r\n\tconst uint16_t *tileLayer = &dunData[2];\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tauto tileId = static_cast<uint8_t>(Swap16LE(tileLayer[j * size.width + i]));\r\n\t\t\tif (tileId != 0) {\r\n\t\t\t\tdungeon[position.x + i][position.y + j] = tileId;\r\n\t\t\t\tProtected.set(position.x + i, position.y + j);\r\n\t\t\t} else if (floorId != 0) {\r\n\t\t\t\tdungeon[position.x + i][position.y + j] = floorId;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DRLG_PlaceThemeRooms(int minSize, int maxSize, int floor, int freq, bool rndSize)\r\n{\r\n\tthemeCount = 0;\r\n\tmemset(themeLoc, 0, sizeof(*themeLoc));\r\n\tfor (WorldTileCoord j = 0; j < DMAXY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == floor && FlipCoin(freq)) {\r\n\t\t\t\tstd::optional<WorldTileSize> themeSize = GetSizeForThemeRoom(floor, { i, j }, minSize, maxSize);\r\n\r\n\t\t\t\tif (!themeSize)\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\tif (rndSize) {\r\n\t\t\t\t\tconst int min = minSize - 2;\r\n\t\t\t\t\tconst int max = maxSize - 2;\r\n\t\t\t\t\tthemeSize->width = min + GenerateRnd(GenerateRnd(themeSize->width - min + 1));\r\n\t\t\t\t\tif (themeSize->width < min || themeSize->width > max)\r\n\t\t\t\t\t\tthemeSize->width = min;\r\n\t\t\t\t\tthemeSize->height = min + GenerateRnd(GenerateRnd(themeSize->height - min + 1));\r\n\t\t\t\t\tif (themeSize->height < min || themeSize->height > max)\r\n\t\t\t\t\t\tthemeSize->height = min;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tTHEME_LOC &theme = themeLoc[themeCount];\r\n\t\t\t\ttheme.room = { WorldTilePosition { i, j } + Direction::South, *themeSize };\r\n\t\t\t\tif (IsAnyOf(leveltype, DTYPE_CAVES, DTYPE_NEST)) {\r\n\t\t\t\t\tDRLG_RectTrans({ (theme.room.position + Direction::South).megaToWorld(), theme.room.size * 2 - 5 });\r\n\t\t\t\t} else {\r\n\t\t\t\t\tDRLG_MRectTrans({ theme.room.position, theme.room.size - 1 });\r\n\t\t\t\t}\r\n\t\t\t\ttheme.ttval = TransVal - 1;\r\n\t\t\t\tCreateThemeRoom(themeCount);\r\n\t\t\t\tthemeCount++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n} // namespace\r\n\r\nvoid DRLG_HoldThemeRooms()\r\n{\r\n\tfor (int i = 0; i < themeCount; i++) {\r\n\t\tfor (int y = themeLoc[i].room.position.y; y < themeLoc[i].room.position.y + themeLoc[i].room.size.height - 1; y++) {\r\n\t\t\tfor (int x = themeLoc[i].room.position.x; x < themeLoc[i].room.position.x + themeLoc[i].room.size.width - 1; x++) {\r\n\t\t\t\tconst int xx = 2 * x + 16;\r\n\t\t\t\tconst int yy = 2 * y + 16;\r\n\t\t\t\tdFlags[xx][yy] |= DungeonFlag::Populated;\r\n\t\t\t\tdFlags[xx + 1][yy] |= DungeonFlag::Populated;\r\n\t\t\t\tdFlags[xx][yy + 1] |= DungeonFlag::Populated;\r\n\t\t\t\tdFlags[xx + 1][yy + 1] |= DungeonFlag::Populated;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nWorldTileSize GetDunSize(const uint16_t *dunData)\r\n{\r\n\treturn WorldTileSize(static_cast<WorldTileCoord>(Swap16LE(dunData[0])), static_cast<WorldTileCoord>(Swap16LE(dunData[1])));\r\n}\r\n\r\nvoid DRLG_LPass3(int lv)\r\n{\r\n\t{\r\n\t\tconst MegaTile mega = pMegaTiles[lv];\r\n\t\tconst int v1 = Swap16LE(mega.micro1);\r\n\t\tconst int v2 = Swap16LE(mega.micro2);\r\n\t\tconst int v3 = Swap16LE(mega.micro3);\r\n\t\tconst int v4 = Swap16LE(mega.micro4);\r\n\r\n\t\tfor (int j = 0; j < MAXDUNY; j += 2) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i += 2) {\r\n\t\t\t\tdPiece[i + 0][j + 0] = v1;\r\n\t\t\t\tdPiece[i + 1][j + 0] = v2;\r\n\t\t\t\tdPiece[i + 0][j + 1] = v3;\r\n\t\t\t\tdPiece[i + 1][j + 1] = v4;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tint yy = 16;\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tint xx = 16;\r\n\t\tfor (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\tconst int tileId = dungeon[i][j] - 1;\r\n\t\t\tconst MegaTile mega = pMegaTiles[tileId];\r\n\t\t\tdPiece[xx + 0][yy + 0] = Swap16LE(mega.micro1);\r\n\t\t\tdPiece[xx + 1][yy + 0] = Swap16LE(mega.micro2);\r\n\t\t\tdPiece[xx + 0][yy + 1] = Swap16LE(mega.micro3);\r\n\t\t\tdPiece[xx + 1][yy + 1] = Swap16LE(mega.micro4);\r\n\t\t\txx += 2;\r\n\t\t}\r\n\t\tyy += 2;\r\n\t}\r\n}\r\n\r\nbool IsNearThemeRoom(WorldTilePosition testPosition)\r\n{\r\n\tfor (int i = 0; i < themeCount; i++) {\r\n\t\tif (WorldTileRectangle(themeLoc[i].room.position - WorldTileDisplacement { 2 }, themeLoc[i].room.size + 5).contains(testPosition))\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid InitLevels()\r\n{\r\n\tcurrlevel = 0;\r\n\tleveltype = DTYPE_TOWN;\r\n\tsetlevel = false;\r\n}\r\n\r\nvoid FloodTransparencyValues(uint8_t floorID)\r\n{\r\n\tint yy = 16;\r\n\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\tint xx = 16;\r\n\t\tfor (int i = 0; i < DMAXX; i++) {\r\n\t\t\tif (dungeon[i][j] == floorID && dTransVal[xx][yy] == 0) {\r\n\t\t\t\tFindTransparencyValues({ xx, yy }, floorID);\r\n\t\t\t\tTransVal++;\r\n\t\t\t}\r\n\t\t\txx += 2;\r\n\t\t}\r\n\t\tyy += 2;\r\n\t}\r\n}\r\n\r\ntl::expected<dungeon_type, std::string> ParseDungeonType(std::string_view value)\r\n{\r\n\tif (value.empty()) return DTYPE_NONE;\r\n\tif (value == \"DTYPE_TOWN\") return DTYPE_TOWN;\r\n\tif (value == \"DTYPE_CATHEDRAL\") return DTYPE_CATHEDRAL;\r\n\tif (value == \"DTYPE_CATACOMBS\") return DTYPE_CATACOMBS;\r\n\tif (value == \"DTYPE_CAVES\") return DTYPE_CAVES;\r\n\tif (value == \"DTYPE_HELL\") return DTYPE_HELL;\r\n\tif (value == \"DTYPE_NEST\") return DTYPE_NEST;\r\n\tif (value == \"DTYPE_CRYPT\") return DTYPE_CRYPT;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<_setlevels, std::string> ParseSetLevel(std::string_view value)\r\n{\r\n\tconst std::optional<_setlevels> enumValueOpt = magic_enum::enum_cast<_setlevels>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/gendung.h",
    "content": "/**\r\n * @file gendung.h\r\n *\r\n * Interface of general dungeon generation code.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/scrollrt.h\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/gendung_defs.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/bitset2d.hpp\"\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\n\r\n#define MAXTHEMES 50\r\n#define MAXTILES 1379\r\n\r\nenum _setlevels : int8_t {\r\n\tSL_NONE,\r\n\tSL_SKELKING,\r\n\tSL_BONECHAMB,\r\n\tSL_MAZE,\r\n\tSL_POISONWATER,\r\n\tSL_VILEBETRAYER,\r\n\r\n\tSL_ARENA_CHURCH,\r\n\tSL_ARENA_HELL,\r\n\tSL_ARENA_CIRCLE_OF_LIFE,\r\n\r\n\tSL_FIRST_ARENA = SL_ARENA_CHURCH,\r\n\tSL_LAST = SL_ARENA_CIRCLE_OF_LIFE,\r\n};\r\n\r\ninline bool IsArenaLevel(_setlevels setLevel)\r\n{\r\n\tswitch (setLevel) {\r\n\tcase SL_ARENA_CHURCH:\r\n\tcase SL_ARENA_HELL:\r\n\tcase SL_ARENA_CIRCLE_OF_LIFE:\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\ntl::expected<dungeon_type, std::string> ParseDungeonType(std::string_view value);\r\ntl::expected<_setlevels, std::string> ParseSetLevel(std::string_view value);\r\n\r\nenum class DungeonFlag : uint8_t {\r\n\t// clang-format off\r\n\tNone                  = 0, // Only used by lighting/automap\r\n\tMissile               = 1 << 0,\r\n\tVisible               = 1 << 1,\r\n\tDeadPlayer            = 1 << 2,\r\n\tPopulated             = 1 << 3,\r\n\tMissileFireWall       = 1 << 4,\r\n\tMissileLightningWall  = 1 << 5,\r\n\tLit                   = 1 << 6,\r\n\tExplored              = 1 << 7,\r\n\tSavedFlags            = (Populated | Lit | Explored), // ~(Missile | Visible | DeadPlayer)\r\n\tLoadedFlags           = (Missile | Visible | DeadPlayer | Populated | Lit | Explored)\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(DungeonFlag);\r\n\r\nenum _difficulty : uint8_t {\r\n\tDIFF_NORMAL,\r\n\tDIFF_NIGHTMARE,\r\n\tDIFF_HELL,\r\n\r\n\tDIFF_LAST = DIFF_HELL,\r\n};\r\n\r\nstruct THEME_LOC {\r\n\tRectangleOf<uint8_t> room;\r\n\tint8_t ttval;\r\n};\r\n\r\nstruct MegaTile {\r\n\tuint16_t micro1;\r\n\tuint16_t micro2;\r\n\tuint16_t micro3;\r\n\tuint16_t micro4;\r\n};\r\n\r\nstruct ShadowStruct {\r\n\tuint8_t strig;\r\n\tuint8_t s1;\r\n\tuint8_t s2;\r\n\tuint8_t s3;\r\n\tuint8_t nv1;\r\n\tuint8_t nv2;\r\n\tuint8_t nv3;\r\n};\r\n\r\n/** Reprecents what tiles are being utilized in the generated map. */\r\nextern Bitset2d<DMAXX, DMAXY> DungeonMask;\r\n/** Contains the tile IDs of the map. */\r\nextern DVL_API_FOR_TEST uint8_t dungeon[DMAXX][DMAXY];\r\n/** Contains a backup of the tile IDs of the map. */\r\nextern uint8_t pdungeon[DMAXX][DMAXY];\r\n/** Tile that may not be overwritten by the level generator */\r\nextern Bitset2d<DMAXX, DMAXY> Protected;\r\nextern WorldTileRectangle SetPieceRoom;\r\n/** Specifies the active set quest piece in coordinate. */\r\nextern WorldTileRectangle SetPiece;\r\nextern OptionalOwnedClxSpriteList pSpecialCels;\r\n/** Specifies the tile definitions of the active dungeon type; (e.g. levels/l1data/l1.til). */\r\nextern DVL_API_FOR_TEST std::unique_ptr<MegaTile[]> pMegaTiles;\r\nextern DVL_API_FOR_TEST std::unique_ptr<std::byte[]> pDungeonCels;\r\n/**\r\n * List tile properties\r\n */\r\nextern DVL_API_FOR_TEST TileProperties SOLData[MAXTILES];\r\n/** Specifies the minimum X,Y-coordinates of the map. */\r\nextern WorldTilePosition dminPosition;\r\n/** Specifies the maximum X,Y-coordinates of the map. */\r\nextern WorldTilePosition dmaxPosition;\r\n/** Specifies the active dungeon type of the current game. */\r\nextern DVL_API_FOR_TEST dungeon_type leveltype;\r\n/** Specifies the active dungeon level of the current game. */\r\nextern DVL_API_FOR_TEST uint8_t currlevel;\r\nextern bool setlevel;\r\n/** Specifies the active quest level of the current game. */\r\nextern _setlevels setlvlnum;\r\n/** Specifies the dungeon type of the active quest level of the current game. */\r\nextern dungeon_type setlvltype;\r\n/** Specifies the player viewpoint X,Y-coordinates of the map. */\r\nextern DVL_API_FOR_TEST Point ViewPosition;\r\nextern uint_fast8_t MicroTileLen;\r\nextern int8_t TransVal;\r\n/** Specifies the active transparency indices. */\r\nextern std::array<bool, 256> TransList;\r\n/** Contains the piece IDs of each tile on the map. */\r\nextern DVL_API_FOR_TEST uint16_t dPiece[MAXDUNX][MAXDUNY];\r\n/** Map of micros that comprises a full tile for any given dungeon piece. */\r\nextern DVL_API_FOR_TEST MICROS DPieceMicros[MAXTILES];\r\n/** Specifies the transparency at each coordinate of the map. */\r\nextern DVL_API_FOR_TEST int8_t dTransVal[MAXDUNX][MAXDUNY];\r\n/** Current realtime lighting. Per tile. */\r\nextern DVL_API_FOR_TEST uint8_t dLight[MAXDUNX][MAXDUNY];\r\n/** Precalculated static lights. dLight uses this as a base before applying lights. Per tile. */\r\nextern uint8_t dPreLight[MAXDUNX][MAXDUNY];\r\n/** Holds various information about dungeon tiles, @see DungeonFlag */\r\nextern DungeonFlag dFlags[MAXDUNX][MAXDUNY];\r\n/** Contains the player numbers (players array indices) of the map. negative id indicates player moving. */\r\nextern int8_t dPlayer[MAXDUNX][MAXDUNY];\r\n/**\r\n * Contains the NPC numbers of the map. The NPC number represents a\r\n * towner number (towners array index) in Tristram and a monster number\r\n * (monsters array index) in the dungeon.\r\n * Negative id indicates monsters moving.\r\n */\r\nextern int16_t dMonster[MAXDUNX][MAXDUNY];\r\n/**\r\n * Contains the dead numbers (deads array indices) and dead direction of\r\n * the map, encoded as specified by the pseudo-code below.\r\n * dDead[x][y] & 0x1F - index of dead\r\n * dDead[x][y] >> 0x5 - direction\r\n */\r\nextern DVL_API_FOR_TEST int8_t dCorpse[MAXDUNX][MAXDUNY];\r\n/**\r\n * Contains the object numbers (objects array indices) of the map.\r\n * Large objects have negative id for their extended area.\r\n */\r\nextern DVL_API_FOR_TEST int8_t dObject[MAXDUNX][MAXDUNY];\r\n/**\r\n * Contains the arch frame numbers of the map from the special tileset\r\n * (e.g. \"levels/l1data/l1s\"). Note, the special tileset of Tristram (i.e.\r\n * \"levels/towndata/towns\") contains trees rather than arches.\r\n */\r\nextern int8_t dSpecial[MAXDUNX][MAXDUNY];\r\nextern int themeCount;\r\nextern THEME_LOC themeLoc[MAXTHEMES];\r\n\r\n#ifdef BUILD_TESTING\r\nstd::optional<WorldTileSize> GetSizeForThemeRoom();\r\n#endif\r\n\r\ndungeon_type GetLevelType(int level);\r\nvoid CreateDungeon(uint32_t rseed, lvl_entry entry);\r\n\r\nDVL_ALWAYS_INLINE constexpr bool InDungeonBounds(Point position)\r\n{\r\n\treturn position.x >= 0 && position.x < MAXDUNX && position.y >= 0 && position.y < MAXDUNY;\r\n}\r\n\r\n/**\r\n * @brief Checks if a given tile contains at least one missile\r\n * @param position Coordinates of the dungeon tile to check\r\n * @return true if a missile exists at this position\r\n */\r\nconstexpr bool TileContainsMissile(Point position)\r\n{\r\n\treturn InDungeonBounds(position) && HasAnyOf(dFlags[position.x][position.y], DungeonFlag::Missile);\r\n}\r\n\r\n/**\r\n * @brief Checks if a given tile contains a player corpse\r\n * @param position Coordinates of the dungeon tile to check\r\n * @return true if a dead player exists at this position\r\n */\r\nconstexpr bool TileContainsDeadPlayer(Point position)\r\n{\r\n\treturn InDungeonBounds(position) && HasAnyOf(dFlags[position.x][position.y], DungeonFlag::DeadPlayer);\r\n}\r\n\r\n/**\r\n * @brief Check if a given tile contains a decorative object (or similar non-pathable set piece)\r\n *\r\n * This appears to include stairs so that monsters do not spawn or path onto them, but players can path to them to navigate between layers\r\n *\r\n * @param position Coordinates of the dungeon tile to check\r\n * @return true if a set piece was spawned at this position\r\n */\r\nconstexpr bool TileContainsSetPiece(Point position)\r\n{\r\n\treturn InDungeonBounds(position) && HasAnyOf(dFlags[position.x][position.y], DungeonFlag::Populated);\r\n}\r\n\r\n/**\r\n * @brief Checks if any player can currently see this tile\r\n *\r\n * Currently only used by monster AI routines so basic monsters out of sight can be ignored until they're likely to interact with the player\r\n *\r\n * @param position Coordinates of the dungeon tile to check\r\n * @return true if the tile is within at least one players vision\r\n */\r\nconstexpr bool IsTileVisible(Point position)\r\n{\r\n\treturn InDungeonBounds(position) && HasAnyOf(dFlags[position.x][position.y], DungeonFlag::Visible);\r\n}\r\n\r\n/**\r\n * @brief Checks if a light source is illuminating this tile\r\n * @param position Coordinates of the dungeon tile to check\r\n * @return true if the tile is within the radius of at least one light source\r\n */\r\nconstexpr bool IsTileLit(Point position)\r\n{\r\n\treturn InDungeonBounds(position) && HasAnyOf(dFlags[position.x][position.y], DungeonFlag::Lit);\r\n}\r\n\r\nstruct Miniset {\r\n\tWorldTileSize size;\r\n\t/* these are indexed as [y][x] */\r\n\tuint8_t search[6][6];\r\n\tuint8_t replace[6][6];\r\n\r\n\t/**\r\n\t * @param position Coordinates of the dungeon tile to check\r\n\t * @param respectProtected Match bug from Crypt levels if false\r\n\t */\r\n\tbool matches(WorldTilePosition position, bool respectProtected = true) const\r\n\t{\r\n\t\tfor (WorldTileCoord yy = 0; yy < size.height; yy++) {\r\n\t\t\tfor (WorldTileCoord xx = 0; xx < size.width; xx++) {\r\n\t\t\t\tif (search[yy][xx] != 0 && dungeon[xx + position.x][yy + position.y] != search[yy][xx])\r\n\t\t\t\t\treturn false;\r\n\t\t\t\tif (respectProtected && Protected.test(xx + position.x, yy + position.y))\r\n\t\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tvoid place(WorldTilePosition position, bool protect = false) const\r\n\t{\r\n\t\tfor (WorldTileCoord y = 0; y < size.height; y++) {\r\n\t\t\tfor (WorldTileCoord x = 0; x < size.width; x++) {\r\n\t\t\t\tif (replace[y][x] == 0)\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tdungeon[x + position.x][y + position.y] = replace[y][x];\r\n\t\t\t\tif (protect)\r\n\t\t\t\t\tProtected.set(x + position.x, y + position.y);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n};\r\n\r\n[[nodiscard]] DVL_ALWAYS_INLINE bool TileHasAny(Point coords, TileProperties property)\r\n{\r\n\treturn HasAnyOf(SOLData[dPiece[coords.x][coords.y]], property);\r\n}\r\n\r\ntl::expected<void, std::string> LoadLevelSOLData();\r\nvoid SetDungeonMicros(std::unique_ptr<std::byte[]> &dungeonCels, uint_fast8_t &microTileLen);\r\nvoid DRLG_InitTrans();\r\nvoid DRLG_MRectTrans(WorldTilePosition origin, WorldTilePosition extent);\r\nvoid DRLG_MRectTrans(WorldTileRectangle area);\r\nvoid DRLG_RectTrans(WorldTileRectangle area);\r\nvoid DRLG_CopyTrans(int sx, int sy, int dx, int dy);\r\nvoid LoadTransparency(const uint16_t *dunData);\r\nvoid LoadDungeonBase(const char *path, Point spawn, int floorId, int dirtId);\r\nvoid Make_SetPC(WorldTileRectangle area);\r\n/**\r\n * @param miniset The miniset to place\r\n * @param tries Tiles to try, 1600 will scan the full map\r\n * @param drlg1Quirk Match buggy behaviour of Diablo's Cathedral\r\n */\r\nstd::optional<Point> PlaceMiniSet(const Miniset &miniset, int tries = 199, bool drlg1Quirk = false);\r\nvoid PlaceDunTiles(const uint16_t *dunData, Point position, int floorId = 0);\r\nvoid DRLG_PlaceThemeRooms(int minSize, int maxSize, int floor, int freq, bool rndSize);\r\nvoid DRLG_HoldThemeRooms();\r\n/**\r\n * @brief Returns the size in tiles of the specified \".dun\" Data\r\n */\r\nWorldTileSize GetDunSize(const uint16_t *dunData);\r\nvoid DRLG_LPass3(int lv);\r\n\r\n/**\r\n * @brief Checks if a theme room is located near the target point\r\n * @param position Target location in dungeon coordinates\r\n * @return True if a theme room is near (within 2 tiles of) this point, false if it is free.\r\n */\r\nbool IsNearThemeRoom(WorldTilePosition position);\r\nvoid InitLevels();\r\nvoid FloodTransparencyValues(uint8_t floorID);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/gendung_defs.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#define DMAXX 40\r\n#define DMAXY 40\r\n\r\n#define MAXDUNX (16 + DMAXX * 2 + 16)\r\n#define MAXDUNY (16 + DMAXY * 2 + 16)\r\n\r\nnamespace devilution {\r\n\r\nenum dungeon_type : int8_t {\r\n\tDTYPE_TOWN,\r\n\tDTYPE_CATHEDRAL,\r\n\tDTYPE_CATACOMBS,\r\n\tDTYPE_CAVES,\r\n\tDTYPE_HELL,\r\n\tDTYPE_NEST,\r\n\tDTYPE_CRYPT,\r\n\r\n\tDTYPE_LAST = DTYPE_CRYPT,\r\n\tDTYPE_NONE = -1,\r\n};\r\n\r\nenum lvl_entry : uint8_t {\r\n\tENTRY_MAIN,\r\n\tENTRY_PREV,\r\n\tENTRY_SETLVL,\r\n\tENTRY_RTNLVL,\r\n\tENTRY_LOAD,\r\n\tENTRY_WARPLVL,\r\n\tENTRY_TWARPDN,\r\n\tENTRY_TWARPUP,\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/reencode_dun_cels.cpp",
    "content": "#include \"levels/reencode_dun_cels.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <limits>\r\n#include <memory>\r\n#include <span>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nDVL_ALWAYS_INLINE void ReencodeDungeonCelsLeftTriangleLower(uint8_t *&dst, const uint8_t *&src)\r\n{\r\n\tunsigned width = 0;\r\n\tfor (unsigned i = 0; i < 8; ++i) {\r\n\t\tsrc += 2; // Skips the two zero bytes (aka bloat).\r\n\t\twidth += 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width;\r\n\t\tdst += width;\r\n\t\twidth += 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width;\r\n\t\tdst += width;\r\n\t}\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ReencodeDungeonCelsLeftTriangle(uint8_t *&dst, const uint8_t *&src)\r\n{\r\n\tReencodeDungeonCelsLeftTriangleLower(dst, src);\r\n\tunsigned width = DunFrameWidth;\r\n\tfor (unsigned i = 0; i < 7; ++i) {\r\n\t\tsrc += 2; // Skips the two zero bytes (aka bloat).\r\n\t\twidth -= 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width;\r\n\t\tdst += width;\r\n\t\twidth -= 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width;\r\n\t\tdst += width;\r\n\t}\r\n\tsrc += 2; // Skips the two zero bytes (aka bloat).\r\n\twidth -= 2;\r\n\tstd::memcpy(dst, src, width);\r\n\tdst += width;\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ReencodeDungeonCelsRightTriangleLower(uint8_t *&dst, const uint8_t *&src)\r\n{\r\n\tunsigned width = 0;\r\n\tfor (unsigned i = 0; i < 8; ++i) {\r\n\t\twidth += 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width + 2; // Skips the two zero bytes (aka bloat).\r\n\t\tdst += width;\r\n\t\twidth += 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width;\r\n\t\tdst += width;\r\n\t}\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ReencodeDungeonCelsRightTriangle(uint8_t *&dst, const uint8_t *&src)\r\n{\r\n\tReencodeDungeonCelsRightTriangleLower(dst, src);\r\n\tunsigned width = DunFrameWidth;\r\n\tfor (unsigned i = 0; i < 7; ++i) {\r\n\t\twidth -= 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width + 2; // Skips the two zero bytes (aka bloat).\r\n\t\tdst += width;\r\n\t\twidth -= 2;\r\n\t\tstd::memcpy(dst, src, width);\r\n\t\tsrc += width;\r\n\t\tdst += width;\r\n\t}\r\n\twidth -= 2;\r\n\tstd::memcpy(dst, src, width);\r\n\tdst += width;\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ReencodeDungeonCelsLeftTrapezoid(uint8_t *&dst, const uint8_t *&src)\r\n{\r\n\tReencodeDungeonCelsLeftTriangleLower(dst, src);\r\n\tstd::memcpy(dst, src, DunFrameWidth * 16);\r\n\tdst += DunFrameWidth * 16;\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ReencodeDungeonCelsRightTrapezoid(uint8_t *&dst, const uint8_t *&src)\r\n{\r\n\tReencodeDungeonCelsRightTriangleLower(dst, src);\r\n\tstd::memcpy(dst, src, DunFrameWidth * 16);\r\n\tdst += DunFrameWidth * 16;\r\n}\r\n\r\nDVL_ALWAYS_INLINE void RenderTransparentSquare(uint8_t *dst, const uint8_t *src)\r\n{\r\n\tfor (unsigned i = 0; i < DunFrameHeight; ++i, dst -= 2 * DunFrameWidth) {\r\n\t\tuint_fast8_t drawWidth = DunFrameWidth;\r\n\t\twhile (drawWidth > 0) {\r\n\t\t\tauto v = static_cast<int8_t>(*src++);\r\n\t\t\tif (v > 0) {\r\n\t\t\t\tstd::memcpy(dst, src, v);\r\n\t\t\t\tsrc += v;\r\n\t\t\t} else {\r\n\t\t\t\tv = static_cast<int8_t>(-v);\r\n\t\t\t}\r\n\t\t\tdst += v;\r\n\t\t\tdrawWidth -= v;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ExtractFoliageLeftTriangle(uint8_t *&dst, uint8_t *src)\r\n{\r\n\tfor (int w = 2, y = 31; y >= 16; --y, w += 2, src -= DunFrameWidth) {\r\n\t\tstd::memcpy(dst, src + (DunFrameWidth - w), w);\r\n\t\tstd::memset(src + (DunFrameWidth - w), 0, w);\r\n\t\tdst += w;\r\n\t}\r\n\tfor (int w = 30, y = 15; y > 0; --y, w -= 2, src -= DunFrameWidth) {\r\n\t\tstd::memcpy(dst, src + (DunFrameWidth - w), w);\r\n\t\tstd::memset(src + (DunFrameWidth - w), 0, w);\r\n\t\tdst += w;\r\n\t}\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ExtractFoliageRightTriangle(uint8_t *&dst, uint8_t *src)\r\n{\r\n\tfor (int w = 2, y = 31; y >= 16; --y, w += 2, src -= DunFrameWidth) {\r\n\t\tstd::memcpy(dst, src, w);\r\n\t\tstd::memset(src, 0, w);\r\n\t\tdst += w;\r\n\t}\r\n\tfor (int w = 30, y = 15; y > 0; --y, w -= 2, src -= DunFrameWidth) {\r\n\t\tstd::memcpy(dst, src, w);\r\n\t\tstd::memset(src, 0, w);\r\n\t\tdst += w;\r\n\t}\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ExtractFoliageTransparentSquare(uint8_t *&dst, const uint8_t *src)\r\n{\r\n\t// The bottom 16 lines are always transparent, foliage only\r\n\t// applies to the upper half of the tile.\r\n\tsrc -= DunFrameHeight * 16;\r\n\tfor (int y = 16; y > 0; --y, src -= 2 * DunFrameWidth) {\r\n\t\tunsigned transparentRun = 0;\r\n\t\tunsigned solidRun = 0;\r\n\t\tfor (int x = 0; x < DunFrameWidth; ++x) {\r\n\t\t\tif (*src++ != 0) {\r\n\t\t\t\tif (transparentRun != 0) {\r\n\t\t\t\t\t*dst++ = static_cast<uint8_t>(-static_cast<int8_t>(transparentRun));\r\n\t\t\t\t\ttransparentRun = 0;\r\n\t\t\t\t}\r\n\t\t\t\t++solidRun;\r\n\t\t\t} else {\r\n\t\t\t\tif (solidRun != 0) {\r\n\t\t\t\t\t*dst++ = solidRun;\r\n\t\t\t\t\tstd::memcpy(dst, src - solidRun, solidRun);\r\n\t\t\t\t\tdst += solidRun;\r\n\t\t\t\t\tsolidRun = 0;\r\n\t\t\t\t}\r\n\t\t\t\t++transparentRun;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (transparentRun != 0) {\r\n\t\t\t*dst++ = static_cast<uint8_t>(-static_cast<int8_t>(transparentRun));\r\n\t\t} else if (solidRun != 0) {\r\n\t\t\t*dst++ = solidRun;\r\n\t\t\tstd::memcpy(dst, src - solidRun, solidRun);\r\n\t\t\tdst += solidRun;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nDVL_ALWAYS_INLINE void ReencodeFloorWithFoliage(uint8_t *&dst, const uint8_t *&src, TileType tileType)\r\n{\r\n\tuint8_t surface[DunFrameWidth * DunFrameHeight] {};\r\n\tuint8_t *surfaceLastLine = &surface[DunFrameWidth * (DunFrameHeight - 1)];\r\n\tRenderTransparentSquare(surfaceLastLine, src);\r\n\tif (tileType == TileType::LeftTriangle) {\r\n\t\tExtractFoliageLeftTriangle(dst, surfaceLastLine);\r\n\t} else {\r\n\t\tExtractFoliageRightTriangle(dst, surfaceLastLine);\r\n\t}\r\n\tExtractFoliageTransparentSquare(dst, surfaceLastLine);\r\n}\r\n\r\nsize_t GetReencodedSize(const uint8_t *dungeonCels, std::span<std::pair<uint16_t, DunFrameInfo>> frames)\r\n{\r\n\tsize_t result = (2 + frames.size()) * 4;\r\n\tconst auto *srcOffsets = reinterpret_cast<const uint32_t *>(dungeonCels);\r\n\tfor (const auto &[frame, info] : frames) {\r\n\t\tsize_t frameSize;\r\n\t\tswitch (info.type) {\r\n\t\tcase TileType::TransparentSquare: {\r\n\t\t\tconst uint32_t srcFrameBegin = Swap32LE(srcOffsets[frame]);\r\n\t\t\tif (info.isFloor()) {\r\n\t\t\t\tuint8_t out[1024];\r\n\t\t\t\tuint8_t *outIt = out;\r\n\t\t\t\tconst uint8_t *src = &dungeonCels[srcFrameBegin];\r\n\t\t\t\tconst TileType newType = info.isFloorLeft() ? TileType::LeftTriangle : TileType::RightTriangle;\r\n\t\t\t\tReencodeFloorWithFoliage(outIt, src, newType);\r\n\t\t\t\tframeSize = outIt - out;\r\n\t\t\t} else {\r\n\t\t\t\tconst uint32_t srcFrameEnd = Swap32LE(srcOffsets[frame + 1]);\r\n\t\t\t\tframeSize = srcFrameEnd - srcFrameBegin;\r\n\t\t\t}\r\n\t\t} break;\r\n\t\tcase TileType::Square: {\r\n\t\t\tframeSize = DunFrameWidth * DunFrameHeight;\r\n\t\t} break;\r\n\t\tcase TileType::LeftTriangle:\r\n\t\tcase TileType::RightTriangle:\r\n\t\t\tframeSize = ReencodedTriangleFrameSize;\r\n\t\t\tbreak;\r\n\t\tcase TileType::LeftTrapezoid:\r\n\t\tcase TileType::RightTrapezoid:\r\n\t\t\tframeSize = ReencodedTrapezoidFrameSize;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tresult += frameSize;\r\n\t}\r\n\treturn result;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid ReencodeDungeonCels(std::unique_ptr<std::byte[]> &dungeonCels, std::span<std::pair<uint16_t, DunFrameInfo>> frames)\r\n{\r\n\tconst auto *srcData = reinterpret_cast<const uint8_t *>(dungeonCels.get());\r\n\tconst auto *srcOffsets = reinterpret_cast<const uint32_t *>(srcData);\r\n\r\n\tint numFoliage = 0;\r\n\tLogVerbose(\"Re-encoding dungeon CELs: {} frames, {} bytes\",\r\n\t    FormatInteger(Swap32LE(srcOffsets[0])),\r\n\t    FormatInteger(Swap32LE(srcOffsets[Swap32LE(srcOffsets[0]) + 1])));\r\n\r\n\tconst size_t outSize = GetReencodedSize(srcData, frames);\r\n\tstd::unique_ptr<std::byte[]> result { new std::byte[outSize] };\r\n\tauto *const resultPtr = reinterpret_cast<uint8_t *>(result.get());\r\n\tWriteLE32(resultPtr, static_cast<uint32_t>(frames.size()));\r\n\tuint8_t *lookup = resultPtr + 4;\r\n\tuint8_t *out = resultPtr + (2 + frames.size()) * 4; // number of frames, frame offsets, file size\r\n\tfor (const auto &[frame, info] : frames) {\r\n\t\tWriteLE32(lookup, static_cast<uint32_t>(out - resultPtr));\r\n\t\tlookup += 4;\r\n\t\tconst uint32_t srcFrameBegin = Swap32LE(srcOffsets[frame]);\r\n\t\tconst uint8_t *src = &srcData[srcFrameBegin];\r\n\t\tswitch (info.type) {\r\n\t\tcase TileType::TransparentSquare: {\r\n\t\t\tif (info.isFloor()) {\r\n\t\t\t\tconst TileType newType = info.isFloorLeft() ? TileType::LeftTriangle : TileType::RightTriangle;\r\n\t\t\t\tReencodeFloorWithFoliage(out, src, newType);\r\n\t\t\t\t++numFoliage;\r\n\t\t\t} else {\r\n\t\t\t\tconst uint32_t srcFrameEnd = Swap32LE(srcOffsets[frame + 1]);\r\n\t\t\t\tconst uint32_t size = srcFrameEnd - srcFrameBegin;\r\n\t\t\t\tstd::memcpy(out, src, size);\r\n\t\t\t\tout += size;\r\n\t\t\t}\r\n\t\t} break;\r\n\t\tcase TileType::Square:\r\n\t\t\tstd::memcpy(out, src, DunFrameWidth * DunFrameHeight);\r\n\t\t\tout += DunFrameWidth * DunFrameHeight;\r\n\t\t\tbreak;\r\n\t\tcase TileType::LeftTriangle:\r\n\t\t\tReencodeDungeonCelsLeftTriangle(out, src);\r\n\t\t\tbreak;\r\n\t\tcase TileType::RightTriangle:\r\n\t\t\tReencodeDungeonCelsRightTriangle(out, src);\r\n\t\t\tbreak;\r\n\t\tcase TileType::LeftTrapezoid:\r\n\t\t\tReencodeDungeonCelsLeftTrapezoid(out, src);\r\n\t\t\tbreak;\r\n\t\tcase TileType::RightTrapezoid:\r\n\t\t\tReencodeDungeonCelsRightTrapezoid(out, src);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tWriteLE32(lookup, static_cast<uint32_t>(outSize));\r\n\r\n\tconst auto *dstOffsets = reinterpret_cast<const uint32_t *>(resultPtr);\r\n\tLogVerbose(\" Re-encoded dungeon CELs: {} frames, {} bytes. Extracted {} foliage tiles.\",\r\n\t    FormatInteger(Swap32LE(dstOffsets[0])),\r\n\t    FormatInteger(Swap32LE(dstOffsets[Swap32LE(dstOffsets[0]) + 1])),\r\n\t    FormatInteger(numFoliage));\r\n\r\n\tdungeonCels = std::move(result);\r\n}\r\n\r\nstd::vector<std::pair<uint16_t, uint16_t>> ComputeCelBlockAdjustments(std::span<std::pair<uint16_t, DunFrameInfo>> frames)\r\n{\r\n\tstd::vector<std::pair<uint16_t, uint16_t>> celBlockAdjustments;\r\n\tuint16_t lastFrameIndex = 0;\r\n\tuint16_t adjustment = 0;\r\n\tfor (auto &[frame, info] : frames) {\r\n\t\tconst uint16_t diff = frame - lastFrameIndex - 1;\r\n\t\tif (diff > 0) celBlockAdjustments.emplace_back(frame, adjustment);\r\n\t\tadjustment += diff;\r\n\t\tlastFrameIndex = frame;\r\n\t}\r\n\tif (adjustment > 0) {\r\n\t\tcelBlockAdjustments.emplace_back(std::numeric_limits<uint16_t>::max(), adjustment);\r\n\t}\r\n\treturn celBlockAdjustments;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/reencode_dun_cels.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <span>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#include \"levels/dun_tile.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstruct DunFrameInfo {\r\n\t// Only floor tiles have this.\r\n\tuint8_t microTileIndex;\r\n\r\n\tTileType type;\r\n\tTileProperties properties;\r\n\r\n\t[[nodiscard]] bool isFloor() const\r\n\t{\r\n\t\t// The BlockMissile check is for stairs in L3 and L4, e.g. tile 46 sub-tile 141 frame 386 in L4.\r\n\t\treturn !HasAnyOf(properties, TileProperties::Solid | TileProperties::BlockMissile)\r\n\t\t    && (microTileIndex == 0 || microTileIndex == 1);\r\n\t}\r\n\t[[nodiscard]] bool isFloorLeft() const { return microTileIndex == 0; }\r\n};\r\n\r\n/**\r\n * @brief Re-encodes dungeon cels.\r\n *\r\n * 1. Removing redundant padding bytes from triangles and trapezoids.\r\n * 2. Extracts floor tile foliage into a triangle with the floor frame and a separate 16-px tall `TransparentSquare`.\r\n *\r\n * This reduces memory usage and simplifies the rendering.\r\n */\r\nvoid ReencodeDungeonCels(std::unique_ptr<std::byte[]> &dungeonCels, std::span<std::pair<uint16_t, DunFrameInfo>> frames);\r\n\r\n/**\r\n * @brief Computes adjustments to apply to frame indexes in cel block data.\r\n *\r\n * Re-encoding the dungeon cels removes frames that are not referenced.\r\n * Indexes must also be adjusted to avoid errors when doing lookups.\r\n */\r\nstd::vector<std::pair<uint16_t, uint16_t>> ComputeCelBlockAdjustments(std::span<std::pair<uint16_t, DunFrameInfo>> frames);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/setmaps.cpp",
    "content": "#include \"levels/setmaps.h\"\r\n\r\n#include <cstdint>\r\n\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"levels/drlg_l1.h\"\r\n#include \"levels/drlg_l2.h\"\r\n#include \"levels/drlg_l3.h\"\r\n#include \"levels/drlg_l4.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"msg.h\"\r\n#include \"objects.h\"\r\n#include \"quests.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\n/** Maps from quest level to quest level names. */\r\nconst char *const QuestLevelNames[] = {\r\n\t\"\",\r\n\tN_(\"Skeleton King's Lair\"),\r\n\tN_(\"Chamber of Bone\"),\r\n\tN_(\"Maze\"),\r\n\tN_(\"Poisoned Water Supply\"),\r\n\tN_(\"Archbishop Lazarus' Lair\"),\r\n\tN_(\"Church Arena\"),\r\n\tN_(\"Hell Arena\"),\r\n\tN_(\"Circle of Life Arena\"),\r\n};\r\n\r\nnamespace {\r\n\r\nvoid AddSKingObjs()\r\n{\r\n\tconstexpr WorldTileRectangle SmallSecretRoom { { 20, 7 }, { 3, 3 } };\r\n\tObjectAtPosition({ 64, 34 }).InitializeLoadedObject(SmallSecretRoom, 1);\r\n\r\n\tconstexpr WorldTileRectangle Gate { { 20, 14 }, { 1, 2 } };\r\n\tObjectAtPosition({ 64, 59 }).InitializeLoadedObject(Gate, 2);\r\n\r\n\tconstexpr WorldTileRectangle LargeSecretRoom { { 8, 1 }, { 7, 10 } };\r\n\tObjectAtPosition({ 27, 37 }).InitializeLoadedObject(LargeSecretRoom, 3);\r\n\tObjectAtPosition({ 46, 35 }).InitializeLoadedObject(LargeSecretRoom, 3);\r\n\tObjectAtPosition({ 49, 53 }).InitializeLoadedObject(LargeSecretRoom, 3);\r\n\tObjectAtPosition({ 27, 53 }).InitializeLoadedObject(LargeSecretRoom, 3);\r\n}\r\n\r\nvoid AddSChamObjs()\r\n{\r\n\tObjectAtPosition({ 37, 30 }).InitializeLoadedObject({ { 17, 0 }, { 4, 5 } }, 1);\r\n\tObjectAtPosition({ 37, 46 }).InitializeLoadedObject({ { 13, 0 }, { 3, 5 } }, 2);\r\n}\r\n\r\nvoid AddVileObjs()\r\n{\r\n\tObjectAtPosition({ 26, 45 }).InitializeLoadedObject({ { 1, 1 }, { 8, 9 } }, 1);\r\n\tObjectAtPosition({ 45, 46 }).InitializeLoadedObject({ { 11, 1 }, { 9, 9 } }, 2);\r\n\tObjectAtPosition({ 35, 36 }).InitializeLoadedObject({ { 7, 11 }, { 6, 7 } }, 3);\r\n}\r\n\r\nvoid SetMapTransparency(const char *path)\r\n{\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\tLoadTransparency(dunData.get());\r\n}\r\n\r\nvoid LoadCustomMap(const char *path, Point viewPosition)\r\n{\r\n\tswitch (setlvltype) {\r\n\tcase DTYPE_CATHEDRAL:\r\n\tcase DTYPE_CRYPT:\r\n\t\tLoadL1Dungeon(path, viewPosition);\r\n\t\tbreak;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\tLoadL2Dungeon(path, viewPosition);\r\n\t\tbreak;\r\n\tcase DTYPE_CAVES:\r\n\tcase DTYPE_NEST:\r\n\t\tLoadL3Dungeon(path, viewPosition);\r\n\t\tbreak;\r\n\tcase DTYPE_HELL:\r\n\t\tLoadL4Dungeon(path, viewPosition);\r\n\t\tbreak;\r\n\tcase DTYPE_TOWN:\r\n\tcase DTYPE_NONE:\r\n\t\tbreak;\r\n\t}\r\n\tLoadRndLvlPal(setlvltype);\r\n}\r\n\r\nvoid LoadArenaMap(const char *path, Point viewPosition, Point exitTrigger)\r\n{\r\n\tLoadCustomMap(path, viewPosition);\r\n\ttrigflag = false;\r\n\tnumtrigs = 1;\r\n\ttrigs[0].position = exitTrigger;\r\n\ttrigs[0]._tmsg = WM_DIABRTNLVL;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadSetMap()\r\n{\r\n\tswitch (setlvlnum) {\r\n\tcase SL_SKELKING:\r\n\t\tif (Quests[Q_SKELKING]._qactive == QUEST_INIT) {\r\n\t\t\tQuests[Q_SKELKING]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_SKELKING]._qvar1 = 1;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_SKELKING]);\r\n\t\t}\r\n\t\tLoadPreL1Dungeon(\"levels\\\\l1data\\\\sklkng1.dun\");\r\n\t\tLoadL1Dungeon(\"levels\\\\l1data\\\\sklkng2.dun\", { 83, 44 });\r\n\t\tSetMapTransparency(\"levels\\\\l1data\\\\sklkngt.dun\");\r\n\t\tLoadPaletteAndInitBlending(\"levels\\\\l1data\\\\l1_2.pal\");\r\n\t\tAddSKingObjs();\r\n\t\tInitSKingTriggers();\r\n\t\tbreak;\r\n\tcase SL_BONECHAMB:\r\n\t\tLoadPreL2Dungeon(\"levels\\\\l2data\\\\bonecha2.dun\");\r\n\t\tLoadL2Dungeon(\"levels\\\\l2data\\\\bonecha1.dun\", { 70, 40 });\r\n\t\tSetMapTransparency(\"levels\\\\l2data\\\\bonechat.dun\");\r\n\t\tLoadPaletteAndInitBlending(\"levels\\\\l2data\\\\l2_2.pal\");\r\n\t\tAddSChamObjs();\r\n\t\tInitSChambTriggers();\r\n\t\tbreak;\r\n\tcase SL_MAZE:\r\n\t\tbreak;\r\n\tcase SL_POISONWATER:\r\n\t\tif (Quests[Q_PWATER]._qactive == QUEST_INIT)\r\n\t\t\tQuests[Q_PWATER]._qactive = QUEST_ACTIVE;\r\n\t\tLoadL3Dungeon(\"levels\\\\l3data\\\\foulwatr.dun\", { 31, 83 });\r\n\t\tLoadPaletteAndInitBlending(\"levels\\\\l3data\\\\l3pfoul.pal\");\r\n\t\tInitPWaterTriggers();\r\n\t\tbreak;\r\n\tcase SL_VILEBETRAYER:\r\n\t\tif (Quests[Q_BETRAYER]._qactive == QUEST_DONE) {\r\n\t\t\tQuests[Q_BETRAYER]._qvar2 = 4;\r\n\t\t} else if (Quests[Q_BETRAYER]._qactive == QUEST_ACTIVE) {\r\n\t\t\tQuests[Q_BETRAYER]._qvar2 = 3;\r\n\t\t}\r\n\t\tLoadPreL1Dungeon(\"levels\\\\l1data\\\\vile1.dun\");\r\n\t\tLoadL1Dungeon(\"levels\\\\l1data\\\\vile2.dun\", { 35, 36 });\r\n\t\tSetMapTransparency(\"levels\\\\l1data\\\\vile1.dun\");\r\n\t\tLoadPaletteAndInitBlending(\"levels\\\\l1data\\\\l1_2.pal\");\r\n\t\tAddVileObjs();\r\n\t\tInitNoTriggers();\r\n\t\tbreak;\r\n\tcase SL_ARENA_CHURCH:\r\n\t\tLoadArenaMap(\"arena\\\\church.dun\", { 29, 22 }, { 28, 20 });\r\n\t\tbreak;\r\n\tcase SL_ARENA_HELL:\r\n\t\tLoadArenaMap(\"arena\\\\hell.dun\", { 34, 26 }, { 33, 26 });\r\n\t\tbreak;\r\n\tcase SL_ARENA_CIRCLE_OF_LIFE:\r\n\t\tLoadArenaMap(\"arena\\\\circle_of_death.dun\", { 30, 26 }, { 29, 26 });\r\n\t\tbreak;\r\n\tcase SL_NONE:\r\n#ifdef _DEBUG\r\n\t\tLoadCustomMap(TestMapPath.c_str(), ViewPosition);\r\n\t\tInitNoTriggers();\r\n#endif\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/setmaps.h",
    "content": "/**\r\n * @file setmaps.cpp\r\n *\r\n * Interface of functionality for the special quest dungeons.\r\n */\r\n#pragma once\r\n\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Get the tile type used to render the given arena level\r\n */\r\ninline dungeon_type GetArenaLevelType(_setlevels arenaLevel)\r\n{\r\n\tconstexpr dungeon_type DungeonTypeForArena[] = {\r\n\t\tdungeon_type::DTYPE_CATHEDRAL, // SL_ARENA_CHURCH\r\n\t\tdungeon_type::DTYPE_HELL,      // SL_ARENA_HELL\r\n\t\tdungeon_type::DTYPE_HELL,      // SL_ARENA_CIRCLE_OF_LIFE\r\n\t};\r\n\r\n\tconstexpr size_t arenaCount = sizeof(DungeonTypeForArena) / sizeof(dungeon_type);\r\n\tconst size_t index = arenaLevel - SL_FIRST_ARENA;\r\n\treturn index < arenaCount ? DungeonTypeForArena[index] : DTYPE_NONE;\r\n}\r\n\r\n/**\r\n * @brief Load a quest map, the given map is specified via the global setlvlnum\r\n */\r\nvoid LoadSetMap();\r\n\r\n/* rdata */\r\nextern const char *const QuestLevelNames[];\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/themes.cpp",
    "content": "/**\r\n * @file themes.cpp\r\n *\r\n * Implementation of the theme room placing algorithms.\r\n */\r\n#include \"levels/themes.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"engine/path.h\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"items.h\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"levels/trigs.h\"\r\n#include \"monster.h\"\r\n#include \"objects.h\"\r\n#include \"quests.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nint numthemes;\r\nbool armorFlag;\r\nbool weaponFlag;\r\nint zharlib;\r\nThemeStruct themes[MAXTHEMES];\r\n\r\nnamespace {\r\n\r\nbool cauldronFlag;\r\nbool bFountainFlag;\r\nbool mFountainFlag;\r\nbool pFountainFlag;\r\nbool tFountainFlag;\r\nbool treasureFlag;\r\n\r\nint themex;\r\nint themey;\r\nsize_t themeVar1;\r\n\r\nbool TFit_Shrine(int i)\r\n{\r\n\tPoint position { 0, 0 };\r\n\tsize_t found = 0;\r\n\r\n\twhile (found == 0) {\r\n\t\tconst Point testPosition = position;\r\n\t\tif (dTransVal[position.x][position.y] == themes[i].ttval) {\r\n\t\t\tif (TileHasAny(position + Direction::NorthEast, TileProperties::Trap)\r\n\t\t\t    && IsTileNotSolid(testPosition + Direction::NorthWest)\r\n\t\t\t    && IsTileNotSolid(testPosition + Direction::SouthEast)\r\n\t\t\t    && dTransVal[position.x - 1][position.y] == themes[i].ttval\r\n\t\t\t    && dTransVal[position.x + 1][position.y] == themes[i].ttval\r\n\t\t\t    && !IsObjectAtPosition(testPosition + Direction::North)\r\n\t\t\t    && !IsObjectAtPosition(testPosition + Direction::East)) {\r\n\t\t\t\tfound = 1;\r\n\t\t\t}\r\n\t\t\tif (found == 0\r\n\t\t\t    && TileHasAny(position + Direction::NorthWest, TileProperties::Trap)\r\n\t\t\t    && IsTileNotSolid(testPosition + Direction::NorthEast)\r\n\t\t\t    && IsTileNotSolid(testPosition + Direction::SouthWest)\r\n\t\t\t    && dTransVal[position.x][position.y - 1] == themes[i].ttval\r\n\t\t\t    && dTransVal[position.x][position.y + 1] == themes[i].ttval\r\n\t\t\t    && !IsObjectAtPosition(testPosition + Direction::North)\r\n\t\t\t    && !IsObjectAtPosition(testPosition + Direction::West)) {\r\n\t\t\t\tfound = 2;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (found == 0) {\r\n\t\t\tposition.x++;\r\n\t\t\tif (position.x == MAXDUNX) {\r\n\t\t\t\tposition.x = 0;\r\n\t\t\t\tposition.y++;\r\n\t\t\t\tif (position.y == MAXDUNY)\r\n\t\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tthemex = position.x;\r\n\tthemey = position.y;\r\n\tthemeVar1 = found;\r\n\treturn true;\r\n}\r\n\r\nbool CheckThemeObj5(Point origin, int8_t regionId)\r\n{\r\n\treturn c_all_of(PointsInRectangle(Rectangle { origin, 2 }), [regionId](Point testPosition) {\r\n\t\t// note out-of-bounds tiles are not solid, this function relies on the guard in TFit_Obj5 and dungeon border\r\n\t\tif (IsTileSolid(testPosition)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// If the theme object would extend into a different region then it doesn't fit.\r\n\t\tif (dTransVal[testPosition.x][testPosition.y] != regionId) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t});\r\n}\r\n\r\nbool TFit_Obj5(int t)\r\n{\r\n\tconst int targetCandidates = GenerateRnd(5);\r\n\tif (targetCandidates < 0) {\r\n\t\t// vanilla rng can return -3 for GenerateRnd(5), default behaviour is to set the output to 0,0 and return true in this case...\r\n\t\tthemex = 0;\r\n\t\tthemey = 0;\r\n\t\treturn true;\r\n\t}\r\n\r\n\tint candidatesFound = 0;\r\n\tfor (const Point tile : PointsInRectangle(Rectangle { { 0, 0 }, { MAXDUNX, MAXDUNY } })) {\r\n\t\tif (dTransVal[tile.x][tile.y] == themes[t].ttval && IsTileNotSolid(tile) && CheckThemeObj5(tile, themes[t].ttval)) {\r\n\t\t\t// Use themex/y to keep track of the last candidate area found, in case we end up with fewer candidates than the target\r\n\t\t\tthemex = tile.x;\r\n\t\t\tthemey = tile.y;\r\n\t\t\tcandidatesFound++;\r\n\t\t\tif (candidatesFound > targetCandidates)\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn candidatesFound > 0;\r\n}\r\nbool TFit_SkelRoom(int t)\r\n{\r\n\tif (IsNoneOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CATACOMBS)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tif (IsSkel(LevelMonsterTypes[i].type)) {\r\n\t\t\tthemeVar1 = i;\r\n\t\t\treturn TFit_Obj5(t);\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool TFit_GoatShrine(int t)\r\n{\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tif (IsGoat(LevelMonsterTypes[i].type)) {\r\n\t\t\tthemeVar1 = i;\r\n\t\t\treturn TFit_Obj5(t);\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CheckThemeObj3(Point origin, int8_t regionId, unsigned frequency = 0)\r\n{\r\n\treturn c_all_of(PointsInRectangle(Rectangle { origin, 1 }), [regionId, frequency](Point testPosition) {\r\n\t\tif (!InDungeonBounds(testPosition)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (IsTileSolid(testPosition)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// If the theme object would extend into a different region then it doesn't fit.\r\n\t\tif (dTransVal[testPosition.x][testPosition.y] != regionId) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (IsObjectAtPosition(testPosition)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (frequency > 0 && FlipCoin(frequency)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t});\r\n}\r\n\r\nbool TFit_Obj3(int8_t regionId)\r\n{\r\n\tconstexpr unsigned objrnd[4] = { 4, 4, 3, 5 };\r\n\r\n\tfor (int yp = 1; yp < MAXDUNY - 1; yp++) {\r\n\t\tfor (int xp = 1; xp < MAXDUNX - 1; xp++) {\r\n\t\t\tif (CheckThemeObj3({ xp, yp }, regionId, objrnd[leveltype - 1])) {\r\n\t\t\t\tthemex = xp;\r\n\t\t\t\tthemey = yp;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CheckThemeReqs(theme_id t)\r\n{\r\n\tswitch (t) {\r\n\tcase THEME_SHRINE:\r\n\tcase THEME_SKELROOM:\r\n\tcase THEME_LIBRARY:\r\n\t\treturn IsNoneOf(leveltype, DTYPE_CAVES, DTYPE_HELL);\r\n\tcase THEME_ARMORSTAND:\r\n\tcase THEME_WEAPONRACK:\r\n\t\treturn IsNoneOf(leveltype, DTYPE_CATHEDRAL);\r\n\tcase THEME_CAULDRON:\r\n\t\treturn leveltype == DTYPE_HELL && cauldronFlag;\r\n\tcase THEME_BLOODFOUNTAIN:\r\n\t\treturn bFountainFlag;\r\n\tcase THEME_PURIFYINGFOUNTAIN:\r\n\t\treturn pFountainFlag;\r\n\tcase THEME_MURKYFOUNTAIN:\r\n\t\treturn mFountainFlag;\r\n\tcase THEME_TEARFOUNTAIN:\r\n\t\treturn tFountainFlag;\r\n\tcase THEME_TREASURE:\r\n\t\treturn treasureFlag;\r\n\tdefault:\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\nbool SpecialThemeFit(int i, theme_id t)\r\n{\r\n\tbool rv = CheckThemeReqs(t);\r\n\tswitch (t) {\r\n\tcase THEME_SHRINE:\r\n\tcase THEME_LIBRARY:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_Shrine(i);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_SKELROOM:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_SkelRoom(i);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_BLOODFOUNTAIN:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_Obj5(i);\r\n\t\t}\r\n\t\tif (rv) {\r\n\t\t\tbFountainFlag = false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_PURIFYINGFOUNTAIN:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_Obj5(i);\r\n\t\t}\r\n\t\tif (rv) {\r\n\t\t\tpFountainFlag = false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_MURKYFOUNTAIN:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_Obj5(i);\r\n\t\t}\r\n\t\tif (rv) {\r\n\t\t\tmFountainFlag = false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_TEARFOUNTAIN:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_Obj5(i);\r\n\t\t}\r\n\t\tif (rv) {\r\n\t\t\ttFountainFlag = false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_CAULDRON:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_Obj5(i);\r\n\t\t}\r\n\t\tif (rv) {\r\n\t\t\tcauldronFlag = false;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_GOATSHRINE:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_GoatShrine(i);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_TORTURE:\r\n\tcase THEME_DECAPITATED:\r\n\tcase THEME_ARMORSTAND:\r\n\tcase THEME_BRNCROSS:\r\n\tcase THEME_WEAPONRACK:\r\n\t\tif (rv) {\r\n\t\t\trv = TFit_Obj3(themes[i].ttval);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase THEME_TREASURE:\r\n\t\tif (rv) {\r\n\t\t\ttreasureFlag = false;\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn rv;\r\n}\r\n\r\nbool CheckThemeRoom(int8_t tv)\r\n{\r\n\tfor (int i = 0; i < numtrigs; i++) {\r\n\t\tif (dTransVal[trigs[i].position.x][trigs[i].position.y] == tv)\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tint tarea = 0;\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dTransVal[i][j] != tv)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (TileContainsSetPiece({ i, j }))\r\n\t\t\t\treturn false;\r\n\r\n\t\t\ttarea++;\r\n\t\t}\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_CATHEDRAL && (tarea < 9 || tarea > 100))\r\n\t\treturn false;\r\n\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dTransVal[i][j] != tv || TileHasAny({ i, j }, TileProperties::Solid))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dTransVal[i - 1][j] != tv && IsTileNotSolid({ i - 1, j }))\r\n\t\t\t\treturn false;\r\n\t\t\tif (dTransVal[i + 1][j] != tv && IsTileNotSolid({ i + 1, j }))\r\n\t\t\t\treturn false;\r\n\t\t\tif (dTransVal[i][j - 1] != tv && IsTileNotSolid({ i, j - 1 }))\r\n\t\t\t\treturn false;\r\n\t\t\tif (dTransVal[i][j + 1] != tv && IsTileNotSolid({ i, j + 1 }))\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * PlaceThemeMonsts places theme monsters with the specified frequency.\r\n *\r\n * @param t theme number (index into themes array).\r\n * @param f frequency (1/f likelihood of adding monster).\r\n */\r\nvoid PlaceThemeMonsts(int t, int f)\r\n{\r\n\tsize_t scattertypes[138];\r\n\r\n\tint numscattypes = 0;\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tif ((LevelMonsterTypes[i].placeFlags & PLACE_SCATTER) != 0) {\r\n\t\t\tscattertypes[numscattypes] = i;\r\n\t\t\tnumscattypes++;\r\n\t\t}\r\n\t}\r\n\tconst size_t mtype = scattertypes[GenerateRnd(numscattypes)];\r\n\tfor (int yp = 0; yp < MAXDUNY; yp++) {\r\n\t\tfor (int xp = 0; xp < MAXDUNX; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == themes[t].ttval && IsTileNotSolid({ xp, yp }) && dItem[xp][yp] == 0 && !IsObjectAtPosition({ xp, yp })) {\r\n\t\t\t\tif (FlipCoin(f)) {\r\n\t\t\t\t\tAddMonster({ xp, yp }, static_cast<Direction>(GenerateRnd(8)), mtype, true);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Theme_Barrel initializes the barrel theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_Barrel(int t)\r\n{\r\n\tconst int barrnd[4] = { 2, 6, 4, 8 };\r\n\tconst int monstrnd[4] = { 5, 7, 3, 9 };\r\n\r\n\tfor (int yp = 0; yp < MAXDUNY; yp++) {\r\n\t\tfor (int xp = 0; xp < MAXDUNX; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == themes[t].ttval && IsTileNotSolid({ xp, yp })) {\r\n\t\t\t\tif (FlipCoin(barrnd[leveltype - 1])) {\r\n\t\t\t\t\tconst _object_id r = FlipCoin(barrnd[leveltype - 1]) ? OBJ_BARREL : OBJ_BARRELEX;\r\n\t\t\t\t\tAddObject(r, { xp, yp });\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_Shrine initializes the shrine theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_Shrine(int t)\r\n{\r\n\tconst int monstrnd[4] = { 6, 6, 3, 9 };\r\n\r\n\tTFit_Shrine(t);\r\n\tif (themeVar1 == 1) {\r\n\t\tAddObject(OBJ_CANDLE2, { themex - 1, themey });\r\n\t\tAddObject(OBJ_SHRINER, { themex, themey });\r\n\t\tAddObject(OBJ_CANDLE2, { themex + 1, themey });\r\n\t} else {\r\n\t\tAddObject(OBJ_CANDLE2, { themex, themey - 1 });\r\n\t\tAddObject(OBJ_SHRINEL, { themex, themey });\r\n\t\tAddObject(OBJ_CANDLE2, { themex, themey + 1 });\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_MonstPit initializes the monster pit theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_MonstPit(int t)\r\n{\r\n\tconst int monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tint r = GenerateRnd(100) + 1;\r\n\tint ixp = 0;\r\n\tint iyp = 0;\r\n\twhile (r > 0) {\r\n\t\tif (dTransVal[ixp][iyp] == themes[t].ttval && IsTileNotSolid({ ixp, iyp })) {\r\n\t\t\t--r;\r\n\t\t}\r\n\t\tif (r <= 0)\r\n\t\t\tcontinue;\r\n\t\tixp++;\r\n\t\tif (ixp == MAXDUNX) {\r\n\t\t\tixp = 0;\r\n\t\t\tiyp++;\r\n\t\t\tif (iyp == MAXDUNY) {\r\n\t\t\t\tiyp = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tCreateRndItem({ ixp, iyp }, true, false, true);\r\n\tItemNoFlippy();\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\nvoid SpawnObjectOrSkeleton(unsigned frequency, _object_id objectType, Point tile)\r\n{\r\n\tif (FlipCoin(frequency)) {\r\n\t\tAddObject(objectType, tile);\r\n\t} else {\r\n\t\tMonster *skeleton = PreSpawnSkeleton();\r\n\t\tif (skeleton != nullptr)\r\n\t\t\tActivateSkeleton(*skeleton, tile);\r\n\t}\r\n}\r\n\r\n/**\r\n * Theme_SkelRoom initializes the skeleton room theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_SkelRoom(int t)\r\n{\r\n\tconstexpr unsigned monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tTFit_SkelRoom(t);\r\n\r\n\tconst int xp = themex;\r\n\tconst int yp = themey;\r\n\r\n\tAddObject(OBJ_SKFIRE, { xp, yp });\r\n\r\n\tSpawnObjectOrSkeleton(monstrnd[leveltype - 1], OBJ_BANNERL, { xp - 1, yp - 1 });\r\n\r\n\t{\r\n\t\tMonster *skeleton = PreSpawnSkeleton();\r\n\t\tif (skeleton != nullptr)\r\n\t\t\tActivateSkeleton(*skeleton, { xp, yp - 1 });\r\n\t}\r\n\r\n\tSpawnObjectOrSkeleton(monstrnd[leveltype - 1], OBJ_BANNERR, { xp + 1, yp - 1 });\r\n\r\n\tSpawnObjectOrSkeleton(monstrnd[leveltype - 1], OBJ_BANNERM, { xp - 1, yp });\r\n\r\n\tSpawnObjectOrSkeleton(monstrnd[leveltype - 1], OBJ_BANNERM, { xp + 1, yp });\r\n\r\n\tSpawnObjectOrSkeleton(monstrnd[leveltype - 1], OBJ_BANNERR, { xp - 1, yp + 1 });\r\n\r\n\t{\r\n\t\tMonster *skeleton = PreSpawnSkeleton();\r\n\t\tif (skeleton != nullptr)\r\n\t\t\tActivateSkeleton(*skeleton, { xp, yp + 1 });\r\n\t}\r\n\r\n\tSpawnObjectOrSkeleton(monstrnd[leveltype - 1], OBJ_BANNERL, { xp + 1, yp + 1 });\r\n\r\n\tif (!IsObjectAtPosition({ xp, yp - 3 })) {\r\n\t\tAddObject(OBJ_SKELBOOK, { xp, yp - 2 });\r\n\t}\r\n\tif (!IsObjectAtPosition({ xp, yp + 3 })) {\r\n\t\tAddObject(OBJ_SKELBOOK, { xp, yp + 2 });\r\n\t}\r\n}\r\n\r\n/**\r\n * Theme_Treasure initializes the treasure theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_Treasure(int t)\r\n{\r\n\tconst int treasrnd[4] = { 4, 9, 7, 10 };\r\n\tconst int monstrnd[4] = { 6, 8, 3, 7 };\r\n\r\n\tDiscardRandomValues(1);\r\n\tfor (int yp = 0; yp < MAXDUNY; yp++) {\r\n\t\tfor (int xp = 0; xp < MAXDUNX; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == themes[t].ttval && IsTileNotSolid({ xp, yp })) {\r\n\t\t\t\tconst int8_t treasureType = treasrnd[leveltype - 1];\r\n\t\t\t\tconst int rv = GenerateRnd(treasureType);\r\n\t\t\t\t// BUGFIX: this used to be `2*GenerateRnd(treasureType) == 0` however 2*0 has no effect, should probably be `FlipCoin(2*treasureType)`\r\n\t\t\t\tif (FlipCoin(treasureType)) {\r\n\t\t\t\t\tCreateTypeItem({ xp, yp }, false, ItemType::Gold, IMISC_NONE, false, true);\r\n\t\t\t\t\tItemNoFlippy();\r\n\t\t\t\t}\r\n\t\t\t\tif (rv == 0) {\r\n\t\t\t\t\tCreateRndItem({ xp, yp }, false, false, true);\r\n\t\t\t\t\tItemNoFlippy();\r\n\t\t\t\t}\r\n\t\t\t\t// BUGFIX: the following code is likely not working as intended.\r\n\t\t\t\t//    `rv >= treasureType - 2` is not connected to either\r\n\t\t\t\t//    of the item creation branches above, thus the last (unrelated)\r\n\t\t\t\t//    item spawned/dropped on ground would be halved in value.\r\n\t\t\t\tif (rv >= treasureType - 2 && leveltype != DTYPE_CATHEDRAL) {\r\n\t\t\t\t\tItem &item = Items[ActiveItems[ActiveItemCount - 1]];\r\n\t\t\t\t\tif (item.IDidx == IDI_GOLD) {\r\n\t\t\t\t\t\titem._ivalue = std::max(item._ivalue / 2, 1);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_Library initializes the library theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_Library(int t)\r\n{\r\n\tconstexpr unsigned librnd[4] = { 1, 2, 2, 5 };\r\n\tconst int monstrnd[4] = { 5, 7, 3, 9 };\r\n\r\n\tTFit_Shrine(t);\r\n\r\n\tif (themeVar1 == 1) {\r\n\t\tAddObject(OBJ_BOOKCANDLE, { themex - 1, themey });\r\n\t\tAddObject(OBJ_BOOKCASER, { themex, themey });\r\n\t\tAddObject(OBJ_BOOKCANDLE, { themex + 1, themey });\r\n\t} else {\r\n\t\tAddObject(OBJ_BOOKCANDLE, { themex, themey - 1 });\r\n\t\tAddObject(OBJ_BOOKCASEL, { themex, themey });\r\n\t\tAddObject(OBJ_BOOKCANDLE, { themex, themey + 1 });\r\n\t}\r\n\r\n\tfor (int yp = 1; yp < MAXDUNY - 1; yp++) {\r\n\t\tfor (int xp = 1; xp < MAXDUNX - 1; xp++) {\r\n\t\t\tif (CheckThemeObj3({ xp, yp }, themes[t].ttval) && dMonster[xp][yp] == 0 && FlipCoin(librnd[leveltype - 1])) {\r\n\t\t\t\tObject *bookstand = AddObject(OBJ_BOOKSTAND, { xp, yp });\r\n\t\t\t\tif (!FlipCoin(2 * librnd[leveltype - 1])) {\r\n\t\t\t\t\tif (bookstand != nullptr) {\r\n\t\t\t\t\t\tbookstand->selectionRegion = SelectionRegion::None;\r\n\t\t\t\t\t\tbookstand->_oAnimFrame += 2;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (Quests[Q_ZHAR].IsAvailable() && t == zharlib) {\r\n\t\treturn;\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_Torture initializes the torture theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_Torture(int t)\r\n{\r\n\tconstexpr unsigned tortrnd[4] = { 6, 8, 3, 8 };\r\n\tconst int monstrnd[4] = { 6, 8, 3, 9 };\r\n\r\n\tfor (int yp = 1; yp < MAXDUNY - 1; yp++) {\r\n\t\tfor (int xp = 1; xp < MAXDUNX - 1; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == themes[t].ttval && IsTileNotSolid({ xp, yp })) {\r\n\t\t\t\tif (CheckThemeObj3({ xp, yp }, themes[t].ttval)) {\r\n\t\t\t\t\tif (FlipCoin(tortrnd[leveltype - 1])) {\r\n\t\t\t\t\t\tAddObject(OBJ_TNUDEM2, { xp, yp });\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_BloodFountain initializes the blood fountain theme.\r\n * @param t Theme number (index into themes array).\r\n */\r\nvoid Theme_BloodFountain(int t)\r\n{\r\n\tconst int monstrnd[4] = { 6, 8, 3, 9 };\r\n\r\n\tTFit_Obj5(t);\r\n\tAddObject(OBJ_BLOODFTN, { themex, themey });\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_Decap initializes the decapitated theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_Decap(int t)\r\n{\r\n\tconstexpr unsigned decaprnd[4] = { 6, 8, 3, 8 };\r\n\tconst int monstrnd[4] = { 6, 8, 3, 9 };\r\n\r\n\tfor (int yp = 1; yp < MAXDUNY - 1; yp++) {\r\n\t\tfor (int xp = 1; xp < MAXDUNX - 1; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == themes[t].ttval && IsTileNotSolid({ xp, yp })) {\r\n\t\t\t\tif (CheckThemeObj3({ xp, yp }, themes[t].ttval)) {\r\n\t\t\t\t\tif (FlipCoin(decaprnd[leveltype - 1])) {\r\n\t\t\t\t\t\tAddObject(OBJ_DECAP, { xp, yp });\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_PurifyingFountain initializes the purifying fountain theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_PurifyingFountain(int t)\r\n{\r\n\tconst int monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tTFit_Obj5(t);\r\n\tAddObject(OBJ_PURIFYINGFTN, { themex, themey });\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_ArmorStand initializes the armor stand theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_ArmorStand(int t)\r\n{\r\n\tconstexpr unsigned armorrnd[4] = { 6, 8, 3, 8 };\r\n\tconst int monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tif (armorFlag) {\r\n\t\tTFit_Obj3(themes[t].ttval);\r\n\t\tAddObject(OBJ_ARMORSTAND, { themex, themey });\r\n\t}\r\n\tfor (int yp = 0; yp < MAXDUNY; yp++) {\r\n\t\tfor (int xp = 0; xp < MAXDUNX; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == themes[t].ttval && IsTileNotSolid({ xp, yp })) {\r\n\t\t\t\tif (CheckThemeObj3({ xp, yp }, themes[t].ttval)) {\r\n\t\t\t\t\tif (FlipCoin(armorrnd[leveltype - 1])) {\r\n\t\t\t\t\t\tAddObject(OBJ_ARMORSTANDN, { xp, yp });\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n\tarmorFlag = false;\r\n}\r\n\r\n/**\r\n * Theme_GoatShrine initializes the goat shrine theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_GoatShrine(int t)\r\n{\r\n\tTFit_GoatShrine(t);\r\n\tAddObject(OBJ_GOATSHRINE, { themex, themey });\r\n\tfor (int yy = themey - 1; yy <= themey + 1; yy++) {\r\n\t\tfor (int xx = themex - 1; xx <= themex + 1; xx++) {\r\n\t\t\tif (dTransVal[xx][yy] == themes[t].ttval && IsTileNotSolid({ xx, yy }) && (xx != themex || yy != themey)) {\r\n\t\t\t\tAddMonster({ xx, yy }, Direction::SouthWest, themeVar1, true);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Theme_Cauldron initializes the cauldron theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_Cauldron(int t)\r\n{\r\n\tconst int monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tTFit_Obj5(t);\r\n\tAddObject(OBJ_CAULDRON, { themex, themey });\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_MurkyFountain initializes the murky fountain theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_MurkyFountain(int t)\r\n{\r\n\tconst int monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tTFit_Obj5(t);\r\n\tAddObject(OBJ_MURKYFTN, { themex, themey });\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_TearFountain initializes the tear fountain theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_TearFountain(int t)\r\n{\r\n\tconst int monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tTFit_Obj5(t);\r\n\tAddObject(OBJ_TEARFTN, { themex, themey });\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_BrnCross initializes the burning cross theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_BrnCross(int t)\r\n{\r\n\tconst int8_t regionId = themes[t].ttval;\r\n\tconst int monstrnd[4] = { 6, 8, 3, 9 };\r\n\tconstexpr unsigned bcrossrnd[4] = { 5, 7, 3, 8 };\r\n\r\n\tfor (int yp = 0; yp < MAXDUNY; yp++) {\r\n\t\tfor (int xp = 0; xp < MAXDUNX; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == regionId && IsTileNotSolid({ xp, yp })) {\r\n\t\t\t\tif (CheckThemeObj3({ xp, yp }, regionId)) {\r\n\t\t\t\t\tif (FlipCoin(bcrossrnd[leveltype - 1])) {\r\n\t\t\t\t\t\tAddObject(OBJ_TBCROSS, { xp, yp });\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n}\r\n\r\n/**\r\n * Theme_WeaponRack initializes the weapon rack theme.\r\n *\r\n * @param t theme number (index into themes array).\r\n */\r\nvoid Theme_WeaponRack(int t)\r\n{\r\n\tconst int8_t regionId = themes[t].ttval;\r\n\tconstexpr unsigned weaponrnd[4] = { 6, 8, 5, 8 };\r\n\tconst int monstrnd[4] = { 6, 7, 3, 9 };\r\n\r\n\tif (weaponFlag) {\r\n\t\tTFit_Obj3(regionId);\r\n\t\tAddObject(OBJ_WEAPONRACK, { themex, themey });\r\n\t}\r\n\tfor (int yp = 0; yp < MAXDUNY; yp++) {\r\n\t\tfor (int xp = 0; xp < MAXDUNX; xp++) {\r\n\t\t\tif (dTransVal[xp][yp] == regionId && IsTileNotSolid({ xp, yp })) {\r\n\t\t\t\tif (CheckThemeObj3({ xp, yp }, regionId)) {\r\n\t\t\t\t\tif (FlipCoin(weaponrnd[leveltype - 1])) {\r\n\t\t\t\t\t\tAddObject(OBJ_WEAPONRACKN, { xp, yp });\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tPlaceThemeMonsts(t, monstrnd[leveltype - 1]);\r\n\tweaponFlag = false;\r\n}\r\n\r\n/**\r\n * UpdateL4Trans sets each value of the transparency map to 1.\r\n */\r\nvoid UpdateL4Trans()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\tif (dTransVal[i][j] != 0) {\r\n\t\t\t\tdTransVal[i][j] = 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InitThemes()\r\n{\r\n\tzharlib = -1;\r\n\tnumthemes = 0;\r\n\tarmorFlag = true;\r\n\tbFountainFlag = true;\r\n\tcauldronFlag = true;\r\n\tmFountainFlag = true;\r\n\tpFountainFlag = true;\r\n\ttFountainFlag = true;\r\n\ttreasureFlag = true;\r\n\tweaponFlag = true;\r\n\r\n\tif (currlevel == 16 || IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t/** Specifies the set of special theme IDs from which one will be selected at random. */\r\n\tconstexpr theme_id ThemeGood[4] = { THEME_GOATSHRINE, THEME_SHRINE, THEME_SKELROOM, THEME_LIBRARY };\r\n\r\n\tif (leveltype == DTYPE_CATHEDRAL) {\r\n\t\tfor (int8_t i = 0; numthemes < MAXTHEMES; i++) {\r\n\t\t\tif (CheckThemeRoom(i)) {\r\n\t\t\t\tthemes[numthemes].ttval = i;\r\n\t\t\t\ttheme_id j = ThemeGood[GenerateRnd(4)];\r\n\t\t\t\twhile (!SpecialThemeFit(numthemes, j)) {\r\n\t\t\t\t\tj = (theme_id)GenerateRnd(17);\r\n\t\t\t\t}\r\n\t\t\t\tthemes[numthemes].ttype = j;\r\n\t\t\t\tnumthemes++;\r\n\t\t\t}\r\n\t\t\tif (i > TransVal)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (int i = 0; i < themeCount; i++) {\r\n\t\tthemes[i].ttype = THEME_NONE;\r\n\t}\r\n\r\n\tif (Quests[Q_ZHAR].IsAvailable()) {\r\n\t\tfor (int j = 0; j < themeCount; j++) {\r\n\t\t\tthemes[j].ttval = themeLoc[j].ttval;\r\n\t\t\tif (SpecialThemeFit(j, THEME_LIBRARY)) {\r\n\t\t\t\tthemes[j].ttype = THEME_LIBRARY;\r\n\t\t\t\tzharlib = j;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int i = 0; i < themeCount; i++) {\r\n\t\tif (themes[i].ttype == THEME_NONE) {\r\n\t\t\tthemes[i].ttval = themeLoc[i].ttval;\r\n\t\t\ttheme_id j = ThemeGood[GenerateRnd(4)];\r\n\t\t\twhile (!SpecialThemeFit(i, j)) {\r\n\t\t\t\tj = (theme_id)GenerateRnd(17);\r\n\t\t\t}\r\n\t\t\tthemes[i].ttype = j;\r\n\t\t}\r\n\t}\r\n\tnumthemes += themeCount;\r\n}\r\n\r\nvoid HoldThemeRooms()\r\n{\r\n\tif (currlevel == 16 || IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (leveltype != DTYPE_CATHEDRAL) {\r\n\t\tDRLG_HoldThemeRooms();\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (int i = 0; i < numthemes; i++) {\r\n\t\tconst int8_t v = themes[i].ttval;\r\n\t\tfor (int y = 0; y < MAXDUNY; y++) {\r\n\t\t\tfor (int x = 0; x < MAXDUNX; x++) {\r\n\t\t\t\tif (dTransVal[x][y] == v) {\r\n\t\t\t\t\tdFlags[x][y] |= DungeonFlag::Populated;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CreateThemeRooms()\r\n{\r\n\tif (currlevel == 16 || IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (int i = 0; i < numthemes; i++) {\r\n\t\tthemex = 0;\r\n\t\tthemey = 0;\r\n\t\tswitch (themes[i].ttype) {\r\n\t\tcase THEME_BARREL:\r\n\t\t\tTheme_Barrel(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_SHRINE:\r\n\t\t\tTheme_Shrine(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_MONSTPIT:\r\n\t\t\tTheme_MonstPit(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_SKELROOM:\r\n\t\t\tTheme_SkelRoom(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_TREASURE:\r\n\t\t\tTheme_Treasure(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_LIBRARY:\r\n\t\t\tTheme_Library(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_TORTURE:\r\n\t\t\tTheme_Torture(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_BLOODFOUNTAIN:\r\n\t\t\tTheme_BloodFountain(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_DECAPITATED:\r\n\t\t\tTheme_Decap(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_PURIFYINGFOUNTAIN:\r\n\t\t\tTheme_PurifyingFountain(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_ARMORSTAND:\r\n\t\t\tTheme_ArmorStand(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_GOATSHRINE:\r\n\t\t\tTheme_GoatShrine(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_CAULDRON:\r\n\t\t\tTheme_Cauldron(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_MURKYFOUNTAIN:\r\n\t\t\tTheme_MurkyFountain(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_TEARFOUNTAIN:\r\n\t\t\tTheme_TearFountain(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_BRNCROSS:\r\n\t\t\tTheme_BrnCross(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_WEAPONRACK:\r\n\t\t\tTheme_WeaponRack(i);\r\n\t\t\tbreak;\r\n\t\tcase THEME_NONE:\r\n\t\t\tapp_fatal(StrCat(\"Unknown theme type: \", static_cast<int>(themes[i].ttype)));\r\n\t\t}\r\n\t}\r\n\tif (leveltype == DTYPE_HELL && themeCount > 0) {\r\n\t\tUpdateL4Trans();\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/themes.h",
    "content": "/**\r\n * @file themes.h\r\n *\r\n * Interface of the theme room placing algorithms.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"levels/gendung.h\"\r\n#include \"tables/objdat.h\"\r\n\r\nnamespace devilution {\r\n\r\nstruct ThemeStruct {\r\n\ttheme_id ttype;\r\n\tint8_t ttval;\r\n};\r\n\r\nextern int numthemes;\r\nextern bool armorFlag;\r\nextern bool weaponFlag;\r\nextern int zharlib;\r\nextern ThemeStruct themes[MAXTHEMES];\r\n\r\nvoid InitThemes();\r\n\r\n/**\r\n * @brief HoldThemeRooms marks theme rooms as populated.\r\n */\r\nvoid HoldThemeRooms();\r\n\r\n/**\r\n * CreateThemeRooms adds thematic elements to rooms.\r\n */\r\nvoid CreateThemeRooms();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/tile_properties.cpp",
    "content": "#include \"levels/tile_properties.hpp\"\r\n\r\n#include \"engine/direction.hpp\"\r\n#include \"engine/path.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"gendung.h\"\r\n#include \"objects.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool IsTileNotSolid(Point position)\r\n{\r\n\tif (!InDungeonBounds(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn !TileHasAny(position, TileProperties::Solid);\r\n}\r\n\r\nbool IsTileSolid(Point position)\r\n{\r\n\tif (!InDungeonBounds(position)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn TileHasAny(position, TileProperties::Solid);\r\n}\r\n\r\nbool IsTileWalkable(Point position, bool ignoreDoors)\r\n{\r\n\tObject *object = FindObjectAtPosition(position);\r\n\tif (object != nullptr) {\r\n\t\tif (ignoreDoors && object->isDoor()) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (object->_oSolidFlag) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn IsTileNotSolid(position);\r\n}\r\n\r\nbool IsTileOccupied(Point position)\r\n{\r\n\tif (!InDungeonBounds(position)) {\r\n\t\treturn true; // OOB positions are considered occupied.\r\n\t}\r\n\r\n\tif (IsTileSolid(position)) {\r\n\t\treturn true;\r\n\t}\r\n\tif (dMonster[position.x][position.y] != 0) {\r\n\t\treturn true;\r\n\t}\r\n\tif (dPlayer[position.x][position.y] != 0) {\r\n\t\treturn true;\r\n\t}\r\n\tif (IsObjectAtPosition(position)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanStep(Point startPosition, Point destinationPosition)\r\n{\r\n\t// These checks are written as if working backwards from the destination to the source, given\r\n\t// both tiles are expected to be adjacent this doesn't matter beyond being a bit confusing\r\n\tbool rv = true;\r\n\tswitch (GetPathDirection(startPosition, destinationPosition)) {\r\n\tcase 5: // Stepping north\r\n\t\trv = IsTileNotSolid(destinationPosition + Direction::SouthWest) && IsTileNotSolid(destinationPosition + Direction::SouthEast);\r\n\t\tbreak;\r\n\tcase 6: // Stepping east\r\n\t\trv = IsTileNotSolid(destinationPosition + Direction::SouthWest) && IsTileNotSolid(destinationPosition + Direction::NorthWest);\r\n\t\tbreak;\r\n\tcase 7: // Stepping south\r\n\t\trv = IsTileNotSolid(destinationPosition + Direction::NorthEast) && IsTileNotSolid(destinationPosition + Direction::NorthWest);\r\n\t\tbreak;\r\n\tcase 8: // Stepping west\r\n\t\trv = IsTileNotSolid(destinationPosition + Direction::SouthEast) && IsTileNotSolid(destinationPosition + Direction::NorthEast);\r\n\t\tbreak;\r\n\t}\r\n\treturn rv;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/tile_properties.hpp",
    "content": "#pragma once\r\n\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n[[nodiscard]] bool IsTileNotSolid(Point position);\r\n[[nodiscard]] bool IsTileSolid(Point position);\r\n\r\n/**\r\n * @brief Checks the position is solid or blocked by an object\r\n */\r\n[[nodiscard]] bool IsTileWalkable(Point position, bool ignoreDoors = false);\r\n\r\n/**\r\n * @brief Checks if the position contains an object, player, monster, or solid dungeon piece\r\n */\r\n[[nodiscard]] bool IsTileOccupied(Point position);\r\n\r\n/**\r\n * @brief check if stepping from a given position to a neighbouring tile cuts a corner.\r\n *\r\n * If you step from A to B, both Xs need to be clear:\r\n *\r\n *  AX\r\n *  XB\r\n *\r\n * @return true if step is allowed\r\n */\r\n[[nodiscard]] bool CanStep(Point startPosition, Point destinationPosition);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/town.cpp",
    "content": "#include \"levels/town.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"levels/drlg_l1.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"multi.h\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n/**\r\n * @brief Load level data into dPiece\r\n * @param path Path of dun file\r\n * @param xi upper left destination\r\n * @param yy upper left destination\r\n */\r\nvoid FillSector(const char *path, int xi, int yy)\r\n{\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\r\n\tconst WorldTileSize size = GetDunSize(dunData.get());\r\n\tconst uint16_t *tileLayer = &dunData[2];\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tint xx = xi;\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tint v1 = 218;\r\n\t\t\tint v2 = 218;\r\n\t\t\tint v3 = 218;\r\n\t\t\tint v4 = 218;\r\n\r\n\t\t\tconst int tileId = Swap16LE(tileLayer[j * size.width + i]) - 1;\r\n\t\t\tif (tileId >= 0) {\r\n\t\t\t\tconst MegaTile mega = pMegaTiles[tileId];\r\n\t\t\t\tv1 = Swap16LE(mega.micro1);\r\n\t\t\t\tv2 = Swap16LE(mega.micro2);\r\n\t\t\t\tv3 = Swap16LE(mega.micro3);\r\n\t\t\t\tv4 = Swap16LE(mega.micro4);\r\n\t\t\t}\r\n\r\n\t\t\tdPiece[xx + 0][yy + 0] = v1;\r\n\t\t\tdPiece[xx + 1][yy + 0] = v2;\r\n\t\t\tdPiece[xx + 0][yy + 1] = v3;\r\n\t\t\tdPiece[xx + 1][yy + 1] = v4;\r\n\t\t\txx += 2;\r\n\t\t}\r\n\t\tyy += 2;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Load a tile in to dPiece\r\n * @param xx upper left destination\r\n * @param yy upper left destination\r\n * @param t tile id\r\n */\r\nvoid FillTile(int xx, int yy, int t)\r\n{\r\n\tconst MegaTile mega = pMegaTiles[t - 1];\r\n\r\n\tdPiece[xx + 0][yy + 0] = Swap16LE(mega.micro1);\r\n\tdPiece[xx + 1][yy + 0] = Swap16LE(mega.micro2);\r\n\tdPiece[xx + 0][yy + 1] = Swap16LE(mega.micro3);\r\n\tdPiece[xx + 1][yy + 1] = Swap16LE(mega.micro4);\r\n}\r\n\r\n/**\r\n * @brief Update the map to show the closed hive\r\n */\r\nvoid TownCloseHive()\r\n{\r\n\tdungeon[35][27] = 18;\r\n\tdungeon[36][27] = 63;\r\n\r\n\tdPiece[78][60] = 0x489;\r\n\tdPiece[79][60] = 0x4ea;\r\n\tdPiece[78][61] = 0x4eb;\r\n\tdPiece[79][61] = 0x4ec;\r\n\tdPiece[78][62] = 0x4ed;\r\n\tdPiece[79][62] = 0x4ee;\r\n\tdPiece[78][63] = 0x4ef;\r\n\tdPiece[79][63] = 0x4f0;\r\n\tdPiece[78][64] = 0x4f1;\r\n\tdPiece[79][64] = 0x4f2;\r\n\tdPiece[78][65] = 0x4f3;\r\n\tdPiece[80][60] = 0x4f4;\r\n\tdPiece[81][60] = 0x4f5;\r\n\tdPiece[80][61] = 0x4f6;\r\n\tdPiece[81][61] = 0x4f7;\r\n\tdPiece[82][60] = 0x4f8;\r\n\tdPiece[83][60] = 0x4f9;\r\n\tdPiece[82][61] = 0x4fa;\r\n\tdPiece[83][61] = 0x4fb;\r\n\tdPiece[80][62] = 0x4fc;\r\n\tdPiece[81][62] = 0x4fd;\r\n\tdPiece[80][63] = 0x4fe;\r\n\tdPiece[81][63] = 0x4ff;\r\n\tdPiece[80][64] = 0x500;\r\n\tdPiece[81][64] = 0x501;\r\n\tdPiece[80][65] = 0x502;\r\n\tdPiece[81][65] = 0x503;\r\n\tdPiece[82][64] = 0x508;\r\n\tdPiece[83][64] = 0x509;\r\n\tdPiece[82][65] = 0x50a;\r\n\tdPiece[83][65] = 0x50b;\r\n\tdPiece[82][62] = 0x504;\r\n\tdPiece[83][62] = 0x505;\r\n\tdPiece[82][63] = 0x506;\r\n\tdPiece[83][63] = 0x507;\r\n\tdPiece[84][61] = 279;\r\n\tdPiece[84][62] = 280;\r\n\tdPiece[84][63] = 279;\r\n\tdPiece[84][64] = 10;\r\n\tdPiece[85][60] = 11;\r\n\tdPiece[85][61] = 12;\r\n\tdPiece[85][62] = 13;\r\n\tdPiece[85][63] = 14;\r\n\tdPiece[85][64] = 15;\r\n\tdPiece[86][60] = 16;\r\n\tdPiece[86][61] = 17;\r\n}\r\n\r\n/**\r\n * @brief Update the map to show the closed grave\r\n */\r\nvoid TownCloseGrave()\r\n{\r\n\tdPiece[36][21] = 0x52a;\r\n\tdPiece[37][21] = 0x52b;\r\n\tdPiece[36][22] = 0x52c;\r\n\tdPiece[37][22] = 0x52d;\r\n\tdPiece[36][23] = 0x52e;\r\n\tdPiece[37][23] = 0x52f;\r\n\tdPiece[36][24] = 0x530;\r\n\tdPiece[37][24] = 0x531;\r\n\tdPiece[35][21] = 0x53a;\r\n\tdPiece[34][21] = 0x53b;\r\n}\r\n\r\nvoid InitTownPieces()\r\n{\r\n\tfor (int y = 0; y < MAXDUNY; y++) {\r\n\t\tfor (int x = 0; x < MAXDUNX; x++) {\r\n\t\t\tif (dPiece[x][y] == 359) {\r\n\t\t\t\tdSpecial[x][y] = 1;\r\n\t\t\t} else if (dPiece[x][y] == 357) {\r\n\t\t\t\tdSpecial[x][y] = 2;\r\n\t\t\t} else if (dPiece[x][y] == 128) {\r\n\t\t\t\tdSpecial[x][y] = 6;\r\n\t\t\t} else if (dPiece[x][y] == 129) {\r\n\t\t\t\tdSpecial[x][y] = 7;\r\n\t\t\t} else if (dPiece[x][y] == 127) {\r\n\t\t\t\tdSpecial[x][y] = 8;\r\n\t\t\t} else if (dPiece[x][y] == 116) {\r\n\t\t\t\tdSpecial[x][y] = 9;\r\n\t\t\t} else if (dPiece[x][y] == 156) {\r\n\t\t\t\tdSpecial[x][y] = 10;\r\n\t\t\t} else if (dPiece[x][y] == 157) {\r\n\t\t\t\tdSpecial[x][y] = 11;\r\n\t\t\t} else if (dPiece[x][y] == 155) {\r\n\t\t\t\tdSpecial[x][y] = 12;\r\n\t\t\t} else if (dPiece[x][y] == 161) {\r\n\t\t\t\tdSpecial[x][y] = 13;\r\n\t\t\t} else if (dPiece[x][y] == 159) {\r\n\t\t\t\tdSpecial[x][y] = 14;\r\n\t\t\t} else if (dPiece[x][y] == 213) {\r\n\t\t\t\tdSpecial[x][y] = 15;\r\n\t\t\t} else if (dPiece[x][y] == 211) {\r\n\t\t\t\tdSpecial[x][y] = 16;\r\n\t\t\t} else if (dPiece[x][y] == 216) {\r\n\t\t\t\tdSpecial[x][y] = 17;\r\n\t\t\t} else if (dPiece[x][y] == 215) {\r\n\t\t\t\tdSpecial[x][y] = 18;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Initialize all of the levels data\r\n */\r\nvoid DrlgTPass3()\r\n{\r\n\tfor (int yy = 0; yy < MAXDUNY; yy += 2) {\r\n\t\tfor (int xx = 0; xx < MAXDUNX; xx += 2) {\r\n\t\t\tdPiece[xx][yy] = 426;\r\n\t\t\tdPiece[xx + 1][yy] = 426;\r\n\t\t\tdPiece[xx][yy + 1] = 426;\r\n\t\t\tdPiece[xx + 1][yy + 1] = 426;\r\n\t\t}\r\n\t}\r\n\r\n\tFillSector(\"levels\\\\towndata\\\\sector1s.dun\", 46, 46);\r\n\tFillSector(\"levels\\\\towndata\\\\sector2s.dun\", 46, 0);\r\n\tFillSector(\"levels\\\\towndata\\\\sector3s.dun\", 0, 46);\r\n\tFillSector(\"levels\\\\towndata\\\\sector4s.dun\", 0, 0);\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\towndata\\\\automap.dun\");\r\n\tPlaceDunTiles(dunData.get(), { 0, 0 });\r\n\r\n\tif (!IsWarpOpen(DTYPE_CATACOMBS)) {\r\n\t\tdungeon[20][7] = 10;\r\n\t\tdungeon[20][6] = 8;\r\n\t\tFillTile(48, 20, 320);\r\n\t}\r\n\tif (!IsWarpOpen(DTYPE_CAVES)) {\r\n\t\tdungeon[4][30] = 8;\r\n\t\tFillTile(16, 68, 332);\r\n\t\tFillTile(16, 70, 331);\r\n\t}\r\n\tif (!IsWarpOpen(DTYPE_HELL)) {\r\n\t\tdungeon[15][35] = 7;\r\n\t\tdungeon[16][35] = 7;\r\n\t\tdungeon[17][35] = 7;\r\n\t\tfor (int x = 36; x < 46; x++) {\r\n\t\t\tFillTile(x, 78, PickRandomlyAmong({ 1, 2, 3, 4 }));\r\n\t\t}\r\n\t}\r\n\tif (gbIsHellfire) {\r\n\t\tif (IsWarpOpen(DTYPE_NEST)) {\r\n\t\t\tTownOpenHive();\r\n\t\t} else {\r\n\t\t\tTownCloseHive();\r\n\t\t}\r\n\t\tif (IsWarpOpen(DTYPE_CRYPT))\r\n\t\t\tTownOpenGrave();\r\n\t\telse\r\n\t\t\tTownCloseGrave();\r\n\t}\r\n\r\n\tif (Quests[Q_PWATER]._qactive != QUEST_DONE && Quests[Q_PWATER]._qactive != QUEST_NOTAVAIL) {\r\n\t\tFillTile(60, 70, 342);\r\n\t} else {\r\n\t\tFillTile(60, 70, 71);\r\n\t}\r\n\r\n\tInitTownPieces();\r\n}\r\n\r\n} // namespace\r\n\r\nbool OpensHive(Point position)\r\n{\r\n\tconst int yp = position.y;\r\n\tconst int xp = position.x;\r\n\treturn xp >= 79 && xp <= 82 && yp >= 61 && yp <= 64;\r\n}\r\n\r\nbool OpensGrave(Point position)\r\n{\r\n\tconst int yp = position.y;\r\n\tconst int xp = position.x;\r\n\treturn xp >= 35 && xp <= 38 && yp >= 20 && yp <= 24;\r\n}\r\n\r\nvoid OpenHive()\r\n{\r\n\tNetSendCmd(false, CMD_OPENHIVE);\r\n\tauto &quest = Quests[Q_FARMER];\r\n\tquest._qactive = QUEST_DONE;\r\n\tif (gbIsMultiplayer)\r\n\t\tNetSendCmdQuest(true, quest);\r\n}\r\n\r\nvoid OpenGrave()\r\n{\r\n\tNetSendCmd(false, CMD_OPENGRAVE);\r\n\tauto &quest = Quests[Q_GRAVE];\r\n\tquest._qactive = QUEST_DONE;\r\n\tif (gbIsMultiplayer)\r\n\t\tNetSendCmdQuest(true, quest);\r\n}\r\n\r\nvoid TownOpenHive()\r\n{\r\n\tdungeon[36][27] = 47;\r\n\r\n\tdPiece[78][60] = 0x489;\r\n\tdPiece[79][60] = 0x48a;\r\n\tdPiece[78][61] = 0x48b;\r\n\tdPiece[79][61] = 0x50d;\r\n\tdPiece[78][62] = 0x4ed;\r\n\tdPiece[78][63] = 0x4ef;\r\n\tdPiece[79][62] = 0x50f;\r\n\tdPiece[79][63] = 0x510;\r\n\tdPiece[79][64] = 0x511;\r\n\tdPiece[78][64] = 0x119;\r\n\tdPiece[78][65] = 0x11b;\r\n\tdPiece[79][65] = 0x11c;\r\n\tdPiece[80][60] = 0x512;\r\n\tdPiece[80][61] = 0x514;\r\n\tdPiece[81][61] = 0x515;\r\n\tdPiece[82][60] = 0x516;\r\n\tdPiece[83][60] = 0x517;\r\n\tdPiece[82][61] = 0x518;\r\n\tdPiece[83][61] = 0x519;\r\n\tdPiece[80][62] = 0x51a;\r\n\tdPiece[81][62] = 0x51b;\r\n\tdPiece[80][63] = 0x51c;\r\n\tdPiece[81][63] = 0x51d;\r\n\tdPiece[80][64] = 0x51e;\r\n\tdPiece[81][64] = 0x51f;\r\n\tdPiece[80][65] = 0x520;\r\n\tdPiece[81][65] = 0x521;\r\n\tdPiece[82][64] = 0x526;\r\n\tdPiece[83][64] = 0x527;\r\n\tdPiece[82][65] = 0x528;\r\n\tdPiece[83][65] = 0x529;\r\n\tdPiece[82][62] = 0x522;\r\n\tdPiece[83][62] = 0x523;\r\n\tdPiece[82][63] = 0x524;\r\n\tdPiece[83][63] = 0x525;\r\n\tdPiece[84][61] = 279;\r\n\tdPiece[84][62] = 280;\r\n\tdPiece[84][63] = 279;\r\n\tdPiece[84][64] = 10;\r\n\tdPiece[85][60] = 11;\r\n\tdPiece[85][61] = 12;\r\n\tdPiece[85][62] = 13;\r\n\tdPiece[85][63] = 14;\r\n\tdPiece[85][64] = 15;\r\n\tdPiece[86][60] = 16;\r\n\tdPiece[86][61] = 17;\r\n}\r\n\r\nvoid TownOpenGrave()\r\n{\r\n\tdungeon[14][8] = 47;\r\n\tdungeon[14][7] = 47;\r\n\r\n\tdPiece[36][21] = 0x532;\r\n\tdPiece[37][21] = 0x533;\r\n\tdPiece[36][22] = 0x534;\r\n\tdPiece[37][22] = 0x535;\r\n\tdPiece[36][23] = 0x536;\r\n\tdPiece[37][23] = 0x537;\r\n\tdPiece[36][24] = 0x538;\r\n\tdPiece[37][24] = 0x539;\r\n\tdPiece[35][21] = 0x53a;\r\n\tdPiece[34][21] = 0x53b;\r\n}\r\n\r\nvoid CleanTownFountain()\r\n{\r\n\tif (!pMegaTiles)\r\n\t\treturn;\r\n\tFillTile(60, 70, 71);\r\n}\r\n\r\nvoid CreateTown(lvl_entry entry)\r\n{\r\n\tdminPosition = { 10, 10 };\r\n\tdmaxPosition = { 84, 84 };\r\n\r\n\tif (entry == ENTRY_MAIN) { // New game\r\n\t\tViewPosition = { 75, 68 };\r\n\t} else if (entry == ENTRY_PREV) { // Cathedral\r\n\t\tViewPosition = { 25, 31 };\r\n\t} else if (entry == ENTRY_TWARPUP) {\r\n\t\tif (TWarpFrom == 5) {\r\n\t\t\tViewPosition = { 49, 22 };\r\n\t\t}\r\n\t\tif (TWarpFrom == 9) {\r\n\t\t\tViewPosition = { 18, 69 };\r\n\t\t}\r\n\t\tif (TWarpFrom == 13) {\r\n\t\t\tViewPosition = { 41, 81 };\r\n\t\t}\r\n\t\tif (TWarpFrom == 21) {\r\n\t\t\tViewPosition = { 36, 25 };\r\n\t\t}\r\n\t\tif (TWarpFrom == 17) {\r\n\t\t\tViewPosition = { 79, 62 };\r\n\t\t}\r\n\t}\r\n\r\n\tDrlgTPass3();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/town.h",
    "content": "/**\r\n * @file town.h\r\n *\r\n * Interface of functionality for rendering the town, towners and calling other render routines.\r\n */\r\n#pragma once\r\n\r\n#include \"interfac.h\"\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Check if hive can be opened by dropping rune bomb on a tile\r\n * @param position The position of the tile\r\n * @return True if the bomb would open hive\r\n */\r\nbool OpensHive(Point position);\r\n\r\n/**\r\n * @brief Check if grave can be opened by dropping cathedral map on a tile\r\n * @param position The position of the tile\r\n * @return True if the map would open the grave\r\n */\r\nbool OpensGrave(Point position);\r\n\r\n/**\r\n * @brief Initiate opening of hive by sending network messages and updating quest state\r\n */\r\nvoid OpenHive();\r\n\r\n/**\r\n * @brief Initiate opening of grave by sending network messages and updating quest state\r\n */\r\nvoid OpenGrave();\r\n\r\n/**\r\n * @brief Update the map to show the open hive\r\n */\r\nvoid TownOpenHive();\r\n\r\n/**\r\n * @brief Update the map to show the open grave\r\n */\r\nvoid TownOpenGrave();\r\n\r\n/**\r\n * @brief Update town to show clean/not poisoned water fountain\r\n */\r\nvoid CleanTownFountain();\r\n\r\n/**\r\n * @brief Initialize town level\r\n * @param entry Method of entry\r\n */\r\nvoid CreateTown(lvl_entry entry);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/trigs.cpp",
    "content": "/**\r\n * @file trigs.cpp\r\n *\r\n * Implementation of functionality for triggering events when the player enters an area.\r\n */\r\n#include \"levels/trigs.h\"\r\n\r\n#include <cmath>\r\n#include <cstdint>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"diablo_msg.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"multi.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool trigflag;\r\nint numtrigs;\r\nTriggerStruct trigs[MAXTRIGGERS];\r\nint TWarpFrom;\r\n\r\nnamespace {\r\n/** Specifies the dungeon piece IDs which constitute stairways leading down to the cathedral from town. */\r\nconst uint16_t TownDownList[] = { 715, 714, 718, 719, 720, 722, 723, 724, 725, 726 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading down to the catacombs from town. */\r\nconst uint16_t TownWarp1List[] = { 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1180, 1182, 1184 };\r\nconst uint16_t TownCryptList[] = { 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337 };\r\nconst uint16_t TownHiveList[] = { 1306, 1307, 1308, 1309 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading up from the cathedral. */\r\nconst uint16_t L1UpList[] = { 126, 128, 129, 130, 131, 132, 134, 136, 137, 138, 139 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading down from the cathedral. */\r\nconst uint16_t L1DownList[] = { 105, 106, 107, 108, 109, 111, 113, 114, 117 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading up from the catacombs. */\r\nconst uint16_t L2UpList[] = { 265, 266 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading down from the catacombs. */\r\nconst uint16_t L2DownList[] = { 268, 269, 270, 271 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading up to town from the catacombs. */\r\nconst uint16_t L2TWarpUpList[] = { 557, 558 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading up from the caves. */\r\nconst uint16_t L3UpList[] = { 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading down from the caves. */\r\nconst uint16_t L3DownList[] = { 161, 162, 163, 164, 165, 166, 167, 168 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading up to town from the caves. */\r\nconst uint16_t L3TWarpUpList[] = { 181, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading up from hell. */\r\nconst uint16_t L4UpList[] = { 81, 82, 89 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading down from hell. */\r\nconst uint16_t L4DownList[] = { 119, 129, 130, 131, 132 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading up to town from hell. */\r\nconst uint16_t L4TWarpUpList[] = { 420, 421, 428 };\r\n/** Specifies the dungeon piece IDs which constitute stairways leading down to Diablo from hell. */\r\nconst uint16_t L4PentaList[] = { 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383 };\r\nconst uint16_t L5TWarpUpList[] = { 171, 172, 173, 174, 175, 176, 177, 178, 183 };\r\nconst uint16_t L5UpList[] = { 148, 149, 150, 151, 152, 153, 154, 156, 157, 158 };\r\nconst uint16_t L5DownList[] = { 124, 125, 128, 130, 131, 134, 135, 139, 141 };\r\nconst uint16_t L6TWarpUpList[] = { 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91 };\r\nconst uint16_t L6UpList[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 };\r\nconst uint16_t L6DownList[] = { 56, 57, 58, 59, 60, 61, 62, 63 };\r\n} // namespace\r\n\r\nvoid InitNoTriggers()\r\n{\r\n\tnumtrigs = 0;\r\n\ttrigflag = false;\r\n}\r\n\r\nbool IsWarpOpen(dungeon_type type)\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn false;\r\n\r\n\tif (gbIsMultiplayer && type != DTYPE_NEST) // Opening the nest is part of in town quest\r\n\t\treturn true;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (type == DTYPE_CATACOMBS && (myPlayer.pTownWarps & 1) != 0)\r\n\t\treturn true;\r\n\tif (type == DTYPE_CAVES && (myPlayer.pTownWarps & 2) != 0)\r\n\t\treturn true;\r\n\tif (type == DTYPE_HELL && (myPlayer.pTownWarps & 4) != 0)\r\n\t\treturn true;\r\n\r\n\tif (gbIsHellfire) {\r\n\t\tif (type == DTYPE_CATACOMBS && myPlayer.getCharacterLevel() >= 10)\r\n\t\t\treturn true;\r\n\t\tif (type == DTYPE_CAVES && myPlayer.getCharacterLevel() >= 15)\r\n\t\t\treturn true;\r\n\t\tif (type == DTYPE_HELL && myPlayer.getCharacterLevel() >= 20)\r\n\t\t\treturn true;\r\n\t\tif (type == DTYPE_NEST && IsAnyOf(Quests[Q_FARMER]._qactive, QUEST_DONE, QUEST_HIVE_DONE))\r\n\t\t\treturn true;\r\n\t\tif (type == DTYPE_CRYPT && Quests[Q_GRAVE]._qactive == QUEST_DONE)\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid InitTownTriggers()\r\n{\r\n\tnumtrigs = 0;\r\n\r\n\t// Cathedral\r\n\ttrigs[numtrigs].position = { 25, 29 };\r\n\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\tnumtrigs++;\r\n\r\n\tif (IsWarpOpen(DTYPE_CATACOMBS)) {\r\n\t\ttrigs[numtrigs].position = { 49, 21 };\r\n\t\ttrigs[numtrigs]._tmsg = WM_DIABTOWNWARP;\r\n\t\ttrigs[numtrigs]._tlvl = 5;\r\n\t\tnumtrigs++;\r\n\t}\r\n\tif (IsWarpOpen(DTYPE_CAVES)) {\r\n\t\ttrigs[numtrigs].position = { 17, 69 };\r\n\t\ttrigs[numtrigs]._tmsg = WM_DIABTOWNWARP;\r\n\t\ttrigs[numtrigs]._tlvl = 9;\r\n\t\tnumtrigs++;\r\n\t}\r\n\tif (IsWarpOpen(DTYPE_HELL)) {\r\n\t\ttrigs[numtrigs].position = { 41, 80 };\r\n\t\ttrigs[numtrigs]._tmsg = WM_DIABTOWNWARP;\r\n\t\ttrigs[numtrigs]._tlvl = 13;\r\n\t\tnumtrigs++;\r\n\t}\r\n\tif (IsWarpOpen(DTYPE_NEST)) {\r\n\t\ttrigs[numtrigs].position = { 80, 62 };\r\n\t\ttrigs[numtrigs]._tmsg = WM_DIABTOWNWARP;\r\n\t\ttrigs[numtrigs]._tlvl = 17;\r\n\t\tnumtrigs++;\r\n\t}\r\n\tif (IsWarpOpen(DTYPE_CRYPT)) {\r\n\t\ttrigs[numtrigs].position = { 36, 24 };\r\n\t\ttrigs[numtrigs]._tmsg = WM_DIABTOWNWARP;\r\n\t\ttrigs[numtrigs]._tlvl = 21;\r\n\t\tnumtrigs++;\r\n\t}\r\n\r\n\ttrigflag = false;\r\n}\r\n\r\nvoid InitL1Triggers()\r\n{\r\n\tnumtrigs = 0;\r\n\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 128) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABPREVLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t\tif (dPiece[i][j] == 114) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttrigflag = false;\r\n}\r\n\r\nvoid InitL2Triggers()\r\n{\r\n\tnumtrigs = 0;\r\n\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 266 && (!Quests[Q_SCHAMB].IsAvailable() || i != Quests[Q_SCHAMB].position.x || j != Quests[Q_SCHAMB].position.y)) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABPREVLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 558) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABTWARPUP;\r\n\t\t\t\ttrigs[numtrigs]._tlvl = 0;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 270) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttrigflag = false;\r\n}\r\n\r\nvoid InitL3Triggers()\r\n{\r\n\tnumtrigs = 0;\r\n\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 170) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABPREVLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 167) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 548) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABTWARPUP;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttrigflag = false;\r\n}\r\n\r\nvoid InitL4Triggers()\r\n{\r\n\tnumtrigs = 0;\r\n\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 82) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABPREVLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 421) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABTWARPUP;\r\n\t\t\t\ttrigs[numtrigs]._tlvl = 0;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 119) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 369 && Quests[Q_BETRAYER]._qactive == QUEST_DONE) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttrigflag = false;\r\n}\r\n\r\nvoid InitHiveTriggers()\r\n{\r\n\tnumtrigs = 0;\r\n\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 65) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABPREVLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 62) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\r\n\t\t\tif (dPiece[i][j] == 79) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABTWARPUP;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttrigflag = false;\r\n}\r\n\r\nvoid InitCryptTriggers()\r\n{\r\n\tnumtrigs = 0;\r\n\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\tif (dPiece[i][j] == 183) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABTWARPUP;\r\n\t\t\t\ttrigs[numtrigs]._tlvl = 0;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t\tif (dPiece[i][j] == 157) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABPREVLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t\tif (dPiece[i][j] == 125) {\r\n\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\tnumtrigs++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttrigflag = false;\r\n}\r\n\r\nvoid InitSKingTriggers()\r\n{\r\n\ttrigflag = false;\r\n\tnumtrigs = 1;\r\n\ttrigs[0].position = { 82, 42 };\r\n\ttrigs[0]._tmsg = WM_DIABRTNLVL;\r\n}\r\n\r\nvoid InitSChambTriggers()\r\n{\r\n\ttrigflag = false;\r\n\tnumtrigs = 1;\r\n\ttrigs[0].position = { 70, 39 };\r\n\ttrigs[0]._tmsg = WM_DIABRTNLVL;\r\n}\r\n\r\nvoid InitPWaterTriggers()\r\n{\r\n\ttrigflag = false;\r\n\tnumtrigs = 1;\r\n\ttrigs[0].position = { 30, 83 };\r\n\ttrigs[0]._tmsg = WM_DIABRTNLVL;\r\n}\r\n\r\nvoid InitVPTriggers()\r\n{\r\n\ttrigflag = false;\r\n\tnumtrigs = 1;\r\n\ttrigs[0].position = { 35, 32 };\r\n\ttrigs[0]._tmsg = WM_DIABRTNLVL;\r\n}\r\n\r\nbool ForceTownTrig()\r\n{\r\n\tfor (const uint16_t tileId : TownDownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = _(\"Down to dungeon\");\r\n\t\t\tcursPosition = { 25, 29 };\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsWarpOpen(DTYPE_CATACOMBS)) {\r\n\t\tfor (const uint16_t tileId : TownWarp1List) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tInfoString = _(\"Down to catacombs\");\r\n\t\t\t\tcursPosition = { 49, 21 };\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsWarpOpen(DTYPE_CAVES)) {\r\n\t\tfor (uint16_t i = 1198; i <= 1219; ++i) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == i) {\r\n\t\t\t\tInfoString = _(\"Down to caves\");\r\n\t\t\t\tcursPosition = { 17, 69 };\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsWarpOpen(DTYPE_HELL)) {\r\n\t\tfor (uint16_t i = 1239; i <= 1254; ++i) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == i) {\r\n\t\t\t\tInfoString = _(\"Down to hell\");\r\n\t\t\t\tcursPosition = { 41, 80 };\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsWarpOpen(DTYPE_NEST)) {\r\n\t\tfor (const uint16_t tileId : TownHiveList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tInfoString = _(\"Down to Hive\");\r\n\t\t\t\tcursPosition = { 80, 62 };\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsWarpOpen(DTYPE_CRYPT)) {\r\n\t\tfor (const uint16_t tileId : TownCryptList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tInfoString = _(\"Down to Crypt\");\r\n\t\t\t\tcursPosition = { 36, 24 };\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceL1Trig()\r\n{\r\n\tfor (const uint16_t tileId : L1UpList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tif (currlevel > 1)\r\n\t\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Up to level {:d}\")), currlevel - 1);\r\n\t\t\telse\r\n\t\t\t\tInfoString = _(\"Up to town\");\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABPREVLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (const uint16_t tileId : L1DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Down to level {:d}\")), currlevel + 1);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABNEXTLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceL2Trig()\r\n{\r\n\tfor (const uint16_t tileId : L2UpList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABPREVLVL) {\r\n\t\t\t\t\tconst int dx = std::abs(trigs[j].position.x - cursPosition.x);\r\n\t\t\t\t\tconst int dy = std::abs(trigs[j].position.y - cursPosition.y);\r\n\t\t\t\t\tif (dx < 4 && dy < 4) {\r\n\t\t\t\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Up to level {:d}\")), currlevel - 1);\r\n\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const uint16_t tileId : L2DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Down to level {:d}\")), currlevel + 1);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABNEXTLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (currlevel == 5) {\r\n\t\tfor (const uint16_t tileId : L2TWarpUpList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\t\tif (trigs[j]._tmsg == WM_DIABTWARPUP) {\r\n\t\t\t\t\t\tconst int dx = std::abs(trigs[j].position.x - cursPosition.x);\r\n\t\t\t\t\t\tconst int dy = std::abs(trigs[j].position.y - cursPosition.y);\r\n\t\t\t\t\t\tif (dx < 4 && dy < 4) {\r\n\t\t\t\t\t\t\tInfoString = _(\"Up to town\");\r\n\t\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceL3Trig()\r\n{\r\n\tfor (const uint16_t tileId : L3UpList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Up to level {:d}\")), currlevel - 1);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABPREVLVL) {\r\n\t\t\t\t\tconst int dx = std::abs(trigs[j].position.x - cursPosition.x);\r\n\t\t\t\t\tconst int dy = std::abs(trigs[j].position.y - cursPosition.y);\r\n\t\t\t\t\tif (dx < 4 && dy < 4) {\r\n\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (const uint16_t tileId : L3DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId\r\n\t\t    || dPiece[cursPosition.x + 1][cursPosition.y] == tileId\r\n\t\t    || dPiece[cursPosition.x + 2][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Down to level {:d}\")), currlevel + 1);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABNEXTLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (currlevel == 9) {\r\n\t\tfor (const uint16_t tileId : L3TWarpUpList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\t\tif (trigs[j]._tmsg == WM_DIABTWARPUP) {\r\n\t\t\t\t\t\tconst int dx = std::abs(trigs[j].position.x - cursPosition.x);\r\n\t\t\t\t\t\tconst int dy = std::abs(trigs[j].position.y - cursPosition.y);\r\n\t\t\t\t\t\tif (dx < 4 && dy < 4) {\r\n\t\t\t\t\t\t\tInfoString = _(\"Up to town\");\r\n\t\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceL4Trig()\r\n{\r\n\tfor (const uint16_t tileId : L4UpList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Up to level {:d}\")), currlevel - 1);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABPREVLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const uint16_t tileId : L4DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Down to level {:d}\")), currlevel + 1);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABNEXTLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (currlevel == 13) {\r\n\t\tfor (const uint16_t tileId : L4TWarpUpList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\t\tif (trigs[j]._tmsg == WM_DIABTWARPUP) {\r\n\t\t\t\t\t\tconst int dx = std::abs(trigs[j].position.x - cursPosition.x);\r\n\t\t\t\t\t\tconst int dy = std::abs(trigs[j].position.y - cursPosition.y);\r\n\t\t\t\t\t\tif (dx < 4 && dy < 4) {\r\n\t\t\t\t\t\t\tInfoString = _(\"Up to town\");\r\n\t\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (currlevel == 15) {\r\n\t\tfor (const uint16_t tileId : L4PentaList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tInfoString = _(\"Down to Diablo\");\r\n\t\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\t\tif (trigs[j]._tmsg == WM_DIABNEXTLVL) {\r\n\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceHiveTrig()\r\n{\r\n\tfor (const uint16_t tileId : L6UpList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Up to Nest level {:d}\")), currlevel - 17);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABPREVLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (const uint16_t tileId : L6DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId\r\n\t\t    || dPiece[cursPosition.x + 1][cursPosition.y] == tileId\r\n\t\t    || dPiece[cursPosition.x + 2][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Down to level {:d}\")), currlevel - 15);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABNEXTLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (currlevel == 17) {\r\n\t\tfor (const uint16_t tileId : L6TWarpUpList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\t\tif (trigs[j]._tmsg == WM_DIABTWARPUP) {\r\n\t\t\t\t\t\tconst int dx = std::abs(trigs[j].position.x - cursPosition.x);\r\n\t\t\t\t\t\tconst int dy = std::abs(trigs[j].position.y - cursPosition.y);\r\n\t\t\t\t\t\tif (dx < 4 && dy < 4) {\r\n\t\t\t\t\t\t\tInfoString = _(\"Up to town\");\r\n\t\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceCryptTrig()\r\n{\r\n\tfor (const uint16_t tileId : L5UpList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Up to Crypt level {:d}\")), currlevel - 21);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABPREVLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (dPiece[cursPosition.x][cursPosition.y] == 316) {\r\n\t\tInfoString = _(\"Cornerstone of the World\");\r\n\t\treturn true;\r\n\t}\r\n\tfor (const uint16_t tileId : L5DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Down to Crypt level {:d}\")), currlevel - 19);\r\n\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\tif (trigs[j]._tmsg == WM_DIABNEXTLVL) {\r\n\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (currlevel == 21) {\r\n\t\tfor (const uint16_t tileId : L5TWarpUpList) {\r\n\t\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\t\tfor (int j = 0; j < numtrigs; j++) {\r\n\t\t\t\t\tif (trigs[j]._tmsg == WM_DIABTWARPUP) {\r\n\t\t\t\t\t\tconst int dx = std::abs(trigs[j].position.x - cursPosition.x);\r\n\t\t\t\t\t\tconst int dy = std::abs(trigs[j].position.y - cursPosition.y);\r\n\t\t\t\t\t\tif (dx < 4 && dy < 4) {\r\n\t\t\t\t\t\t\tInfoString = _(\"Up to town\");\r\n\t\t\t\t\t\t\tcursPosition = trigs[j].position;\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid Freeupstairs()\r\n{\r\n\tfor (int i = 0; i < numtrigs; i++) {\r\n\t\tconst int tx = trigs[i].position.x;\r\n\t\tconst int ty = trigs[i].position.y;\r\n\r\n\t\tfor (int yy = -2; yy <= 2; yy++) {\r\n\t\t\tfor (int xx = -2; xx <= 2; xx++) {\r\n\t\t\t\tdFlags[tx + xx][ty + yy] |= DungeonFlag::Populated;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool ForceSKingTrig()\r\n{\r\n\tfor (const uint16_t tileId : L1UpList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Back to Level {:d}\")), Quests[Q_SKELKING]._qlevel);\r\n\t\t\tcursPosition = trigs[0].position;\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceSChambTrig()\r\n{\r\n\tfor (const uint16_t tileId : L2DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Back to Level {:d}\")), Quests[Q_SCHAMB]._qlevel);\r\n\t\t\tcursPosition = trigs[0].position;\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForcePWaterTrig()\r\n{\r\n\tfor (const uint16_t tileId : L3DownList) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == tileId) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Back to Level {:d}\")), Quests[Q_PWATER]._qlevel);\r\n\t\t\tcursPosition = trigs[0].position;\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool ForceArenaTrig()\r\n{\r\n\tconst uint16_t *checkList;\r\n\tsize_t len;\r\n\tswitch (setlvltype) {\r\n\tcase DTYPE_TOWN:\r\n\t\tcheckList = TownWarp1List;\r\n\t\tlen = sizeof(TownWarp1List) / sizeof(TownWarp1List[0]);\r\n\t\tbreak;\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\tcheckList = L1UpList;\r\n\t\tlen = sizeof(L1UpList) / sizeof(L1UpList[0]);\r\n\t\tbreak;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\tcheckList = L2TWarpUpList;\r\n\t\tlen = sizeof(L2TWarpUpList) / sizeof(L2TWarpUpList[0]);\r\n\t\tbreak;\r\n\tcase DTYPE_CAVES:\r\n\t\tcheckList = L3TWarpUpList;\r\n\t\tlen = sizeof(L3TWarpUpList) / sizeof(L3TWarpUpList[0]);\r\n\t\tbreak;\r\n\tcase DTYPE_HELL:\r\n\t\tcheckList = L4TWarpUpList;\r\n\t\tlen = sizeof(L4TWarpUpList) / sizeof(L4TWarpUpList[0]);\r\n\t\tbreak;\r\n\tcase DTYPE_NEST:\r\n\t\tcheckList = L5TWarpUpList;\r\n\t\tlen = sizeof(L5TWarpUpList) / sizeof(L5TWarpUpList[0]);\r\n\t\tbreak;\r\n\tcase DTYPE_CRYPT:\r\n\t\tcheckList = L6TWarpUpList;\r\n\t\tlen = sizeof(L6TWarpUpList) / sizeof(L6TWarpUpList[0]);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n\tfor (size_t i = 0; i < len; ++i) {\r\n\t\tif (dPiece[cursPosition.x][cursPosition.y] == checkList[i]) {\r\n\t\t\tInfoString = _(\"Up to town\");\r\n\t\t\tcursPosition = trigs[0].position;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid CheckTrigForce()\r\n{\r\n\ttrigflag = false;\r\n\r\n\tif (ControlMode == ControlTypes::KeyboardAndMouse && GetMainPanel().contains(MousePosition)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!setlevel) {\r\n\t\tswitch (leveltype) {\r\n\t\tcase DTYPE_TOWN:\r\n\t\t\ttrigflag = ForceTownTrig();\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_CATHEDRAL:\r\n\t\t\ttrigflag = ForceL1Trig();\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_CATACOMBS:\r\n\t\t\ttrigflag = ForceL2Trig();\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_CAVES:\r\n\t\t\ttrigflag = ForceL3Trig();\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_HELL:\r\n\t\t\ttrigflag = ForceL4Trig();\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_NEST:\r\n\t\t\ttrigflag = ForceHiveTrig();\r\n\t\t\tbreak;\r\n\t\tcase DTYPE_CRYPT:\r\n\t\t\ttrigflag = ForceCryptTrig();\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (leveltype != DTYPE_TOWN && !trigflag) {\r\n\t\t\ttrigflag = ForceQuests();\r\n\t\t}\r\n\t} else {\r\n\t\tswitch (setlvlnum) {\r\n\t\tcase SL_SKELKING:\r\n\t\t\ttrigflag = ForceSKingTrig();\r\n\t\t\tbreak;\r\n\t\tcase SL_BONECHAMB:\r\n\t\t\ttrigflag = ForceSChambTrig();\r\n\t\t\tbreak;\r\n\t\tcase SL_POISONWATER:\r\n\t\t\ttrigflag = ForcePWaterTrig();\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tif (IsArenaLevel(setlvlnum))\r\n\t\t\t\ttrigflag = ForceArenaTrig();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CheckTriggers()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer._pmode != PM_STAND)\r\n\t\treturn;\r\n\r\n\tfor (int i = 0; i < numtrigs; i++) {\r\n\t\tif (myPlayer.position.tile != trigs[i].position) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tswitch (trigs[i]._tmsg) {\r\n\t\tcase WM_DIABNEXTLVL:\r\n\t\t\tif (gbIsSpawn && currlevel >= 2) {\r\n\t\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, { myPlayer.position.tile.x, myPlayer.position.tile.y + 1 });\r\n\t\t\t\tmyPlayer.Say(HeroSpeech::NotAChance);\r\n\t\t\t\tInitDiabloMsg(EMSG_NOT_IN_SHAREWARE);\r\n\t\t\t} else {\r\n\t\t\t\tStartNewLvl(myPlayer, trigs[i]._tmsg, currlevel + 1);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase WM_DIABPREVLVL:\r\n\t\t\tStartNewLvl(myPlayer, trigs[i]._tmsg, currlevel - 1);\r\n\t\t\tbreak;\r\n\t\tcase WM_DIABRTNLVL:\r\n\t\t\tStartNewLvl(myPlayer, trigs[i]._tmsg, GetMapReturnLevel());\r\n\t\t\tbreak;\r\n\t\tcase WM_DIABTOWNWARP:\r\n\t\t\tif (gbIsMultiplayer) {\r\n\t\t\t\tbool abort = false;\r\n\t\t\t\tdiablo_message abortflag;\r\n\r\n\t\t\t\tauto position = myPlayer.position.tile;\r\n\t\t\t\tif (trigs[i]._tlvl == 5 && myPlayer.getCharacterLevel() < 8) {\r\n\t\t\t\t\tabort = true;\r\n\t\t\t\t\tposition.y += 1;\r\n\t\t\t\t\tabortflag = EMSG_REQUIRES_LVL_8;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (IsAnyOf(trigs[i]._tlvl, 9, 17) && myPlayer.getCharacterLevel() < 13) {\r\n\t\t\t\t\tabort = true;\r\n\t\t\t\t\tposition.x += 1;\r\n\t\t\t\t\tabortflag = EMSG_REQUIRES_LVL_13;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (IsAnyOf(trigs[i]._tlvl, 13, 21) && myPlayer.getCharacterLevel() < 17) {\r\n\t\t\t\t\tabort = true;\r\n\t\t\t\t\tposition.y += 1;\r\n\t\t\t\t\tabortflag = EMSG_REQUIRES_LVL_17;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (abort) {\r\n\t\t\t\t\tmyPlayer.Say(HeroSpeech::ICantGetThereFromHere);\r\n\r\n\t\t\t\t\tInitDiabloMsg(abortflag);\r\n\t\t\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, position);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tStartNewLvl(myPlayer, trigs[i]._tmsg, trigs[i]._tlvl);\r\n\t\t\tbreak;\r\n\t\tcase WM_DIABTWARPUP:\r\n\t\t\tTWarpFrom = currlevel;\r\n\t\t\tStartNewLvl(myPlayer, trigs[i]._tmsg, 0);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tapp_fatal(\"Unknown trigger msg\");\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool EntranceBoundaryContains(Point entrance, Point position)\r\n{\r\n\tconstexpr Displacement entranceOffsets[7] = { { 0, 0 }, { -1, 0 }, { 0, -1 }, { -1, -1 }, { -2, -1 }, { -1, -2 }, { -2, -2 } };\r\n\r\n\treturn c_any_of(\r\n\t    entranceOffsets,\r\n\t    [=](Displacement offset) { return entrance + offset == position; });\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/levels/trigs.h",
    "content": "/**\r\n * @file trigs.h\r\n *\r\n * Interface of functionality for triggering events when the player enters an area.\r\n */\r\n#pragma once\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"interfac.h\"\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\n#define MAXTRIGGERS 7\r\n\r\nstruct TriggerStruct {\r\n\tWorldTilePosition position;\r\n\tinterface_mode _tmsg;\r\n\tint _tlvl;\r\n};\r\n\r\nextern bool trigflag;\r\nextern int numtrigs;\r\nextern TriggerStruct trigs[MAXTRIGGERS];\r\nextern int TWarpFrom;\r\n\r\nvoid InitNoTriggers();\r\nbool IsWarpOpen(dungeon_type type);\r\nvoid InitTownTriggers();\r\nvoid InitL1Triggers();\r\nvoid InitL2Triggers();\r\nvoid InitL3Triggers();\r\nvoid InitL4Triggers();\r\nvoid InitHiveTriggers();\r\nvoid InitCryptTriggers();\r\nvoid InitSKingTriggers();\r\nvoid InitSChambTriggers();\r\nvoid InitPWaterTriggers();\r\nvoid InitVPTriggers();\r\nvoid Freeupstairs();\r\nvoid CheckTrigForce();\r\nvoid CheckTriggers();\r\n\r\n/**\r\n * @brief Check if the provided position is in the entrance boundary of the entrance.\r\n * @param entrance The entrance to check.\r\n * @param position The position to check against the entrance boundary.\r\n */\r\nbool EntranceBoundaryContains(Point entrance, Point position);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lighting.cpp",
    "content": "/**\r\n * @file lighting.cpp\r\n *\r\n * Implementation of light and vision.\r\n */\r\n#include \"lighting.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <numeric>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"automap.h\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"objects.h\"\r\n#include \"player.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"vision.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::array<bool, MAXVISION> VisionActive;\r\nLight VisionList[MAXVISION];\r\nLight Lights[MAXLIGHTS];\r\nstd::array<uint8_t, MAXLIGHTS> ActiveLights;\r\nint ActiveLightCount;\r\nstd::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> LightTables;\r\nuint8_t *FullyLitLightTable = nullptr;\r\nuint8_t *FullyDarkLightTable = nullptr;\r\nstd::array<uint8_t, 256> InfravisionTable;\r\nstd::array<uint8_t, 256> StoneTable;\r\nstd::array<uint8_t, 256> PauseTable;\r\n#ifdef _DEBUG\r\nbool DisableLighting;\r\n#endif\r\nbool UpdateLighting;\r\n\r\nnamespace {\r\n\r\n/** @brief Number of supported light radiuses (first radius starts with 0) */\r\nconstexpr size_t NumLightRadiuses = 16;\r\n/** Falloff tables for the light cone */\r\nuint8_t LightFalloffs[NumLightRadiuses][128];\r\nbool UpdateVision;\r\n/** interpolations of a 32x32 (16x16 mirrored) light circle moving between tiles in steps of 1/8 of a tile */\r\nuint8_t LightConeInterpolations[8][8][16][16];\r\n\r\nvoid RotateRadius(DisplacementOf<int8_t> &offset, DisplacementOf<int8_t> &dist, DisplacementOf<int8_t> &light, DisplacementOf<int8_t> &block)\r\n{\r\n\tdist = { static_cast<int8_t>(7 - dist.deltaY), dist.deltaX };\r\n\tlight = { static_cast<int8_t>(7 - light.deltaY), light.deltaX };\r\n\toffset = { static_cast<int8_t>(dist.deltaX - light.deltaX), static_cast<int8_t>(dist.deltaY - light.deltaY) };\r\n\r\n\tblock.deltaX = 0;\r\n\tif (offset.deltaX < 0) {\r\n\t\toffset.deltaX += 8;\r\n\t\tblock.deltaX = 1;\r\n\t}\r\n\tblock.deltaY = 0;\r\n\tif (offset.deltaY < 0) {\r\n\t\toffset.deltaY += 8;\r\n\t\tblock.deltaY = 1;\r\n\t}\r\n}\r\n\r\nDVL_ALWAYS_INLINE void SetLight(Point position, uint8_t v)\r\n{\r\n\tif (LoadingMapObjects)\r\n\t\tdPreLight[position.x][position.y] = v;\r\n\telse\r\n\t\tdLight[position.x][position.y] = v;\r\n}\r\n\r\nDVL_ALWAYS_INLINE uint8_t GetLight(Point position)\r\n{\r\n\tif (LoadingMapObjects)\r\n\t\treturn dPreLight[position.x][position.y];\r\n\r\n\treturn dLight[position.x][position.y];\r\n}\r\n\r\nbool TileAllowsLight(Point position)\r\n{\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn false;\r\n\treturn !TileHasAny(position, TileProperties::BlockLight);\r\n}\r\n\r\nvoid DoVisionFlags(Point position, MapExplorationType doAutomap, bool visible)\r\n{\r\n\tif (doAutomap != MAP_EXP_NONE) {\r\n\t\tif (dFlags[position.x][position.y] != DungeonFlag::None)\r\n\t\t\tSetAutomapView(position, doAutomap);\r\n\t\tdFlags[position.x][position.y] |= DungeonFlag::Explored;\r\n\t}\r\n\tif (visible)\r\n\t\tdFlags[position.x][position.y] |= DungeonFlag::Lit;\r\n\tdFlags[position.x][position.y] |= DungeonFlag::Visible;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DoUnLight(Point position, uint8_t radius)\r\n{\r\n\tradius++;\r\n\tradius++; // If lights moved at a diagonal it can result in some extra tiles being lit\r\n\r\n\tauto searchArea = PointsInRectangle(WorldTileRectangle { position, radius });\r\n\r\n\tfor (const WorldTilePosition targetPosition : searchArea) {\r\n\t\tif (InDungeonBounds(targetPosition))\r\n\t\t\tdLight[targetPosition.x][targetPosition.y] = dPreLight[targetPosition.x][targetPosition.y];\r\n\t}\r\n}\r\n\r\nvoid DoLighting(Point position, uint8_t radius, DisplacementOf<int8_t> offset)\r\n{\r\n\tassert(radius >= 0 && radius <= NumLightRadiuses);\r\n\tassert(InDungeonBounds(position));\r\n\r\n\tDisplacementOf<int8_t> light = {};\r\n\tDisplacementOf<int8_t> block = {};\r\n\r\n\tif (offset.deltaX < 0) {\r\n\t\toffset.deltaX += 8;\r\n\t\tposition -= { 1, 0 };\r\n\t}\r\n\tif (offset.deltaY < 0) {\r\n\t\toffset.deltaY += 8;\r\n\t\tposition -= { 0, 1 };\r\n\t}\r\n\r\n\tDisplacementOf<int8_t> dist = offset;\r\n\r\n\tint minX = 15;\r\n\tif (position.x - 15 < 0) {\r\n\t\tminX = position.x + 1;\r\n\t}\r\n\tint maxX = 15;\r\n\tif (position.x + 15 > MAXDUNX) {\r\n\t\tmaxX = MAXDUNX - position.x;\r\n\t}\r\n\tint minY = 15;\r\n\tif (position.y - 15 < 0) {\r\n\t\tminY = position.y + 1;\r\n\t}\r\n\tint maxY = 15;\r\n\tif (position.y + 15 > MAXDUNY) {\r\n\t\tmaxY = MAXDUNY - position.y;\r\n\t}\r\n\r\n\t// Allow for dim lights in crypt and nest\r\n\tif (IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\tif (GetLight(position) > LightFalloffs[radius][0])\r\n\t\t\tSetLight(position, LightFalloffs[radius][0]);\r\n\t} else {\r\n\t\tSetLight(position, 0);\r\n\t}\r\n\r\n\tfor (int i = 0; i < 4; i++) {\r\n\t\tconst int yBound = i > 0 && i < 3 ? maxY : minY;\r\n\t\tconst int xBound = i < 2 ? maxX : minX;\r\n\t\tfor (int y = 0; y < yBound; y++) {\r\n\t\t\tfor (int x = 1; x < xBound; x++) {\r\n\t\t\t\tconst int linearDistance = LightConeInterpolations[offset.deltaX][offset.deltaY][x + block.deltaX][y + block.deltaY];\r\n\t\t\t\tif (linearDistance >= 128)\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tconst Point temp = position + (Displacement { x, y }).Rotate(-i);\r\n\t\t\t\tconst uint8_t v = LightFalloffs[radius][linearDistance];\r\n\t\t\t\tif (!InDungeonBounds(temp))\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tif (v < GetLight(temp))\r\n\t\t\t\t\tSetLight(temp, v);\r\n\t\t\t}\r\n\t\t}\r\n\t\tRotateRadius(offset, dist, light, block);\r\n\t}\r\n}\r\n\r\nvoid DoUnVision(Point position, uint8_t radius)\r\n{\r\n\tradius++;\r\n\tradius++; // increasing the radius even further here prevents leaving stray vision tiles behind and doesn't seem to affect monster AI - applying new vision happens in the same tick\r\n\r\n\tauto searchArea = PointsInRectangle(WorldTileRectangle { position, radius });\r\n\r\n\tfor (const WorldTilePosition targetPosition : searchArea) {\r\n\t\tif (InDungeonBounds(targetPosition))\r\n\t\t\tdFlags[targetPosition.x][targetPosition.y] &= ~(DungeonFlag::Visible | DungeonFlag::Lit);\r\n\t}\r\n}\r\n\r\nvoid DoVision(Point position, uint8_t radius, MapExplorationType doAutomap, bool visible)\r\n{\r\n\tauto markVisibleFn = [doAutomap, visible](Point rayPoint) {\r\n\t\tDoVisionFlags(rayPoint, doAutomap, visible);\r\n\t};\r\n\tauto markTransparentFn = [](Point rayPoint) {\r\n\t\tconst int8_t trans = dTransVal[rayPoint.x][rayPoint.y];\r\n\t\tif (trans != 0)\r\n\t\t\tTransList[trans] = true;\r\n\t};\r\n\tauto passesLightFn = [](Point rayPoint) {\r\n\t\treturn TileAllowsLight(rayPoint);\r\n\t};\r\n\tauto inBoundsFn = [](Point rayPoint) {\r\n\t\treturn InDungeonBounds(rayPoint);\r\n\t};\r\n\r\n\tDoVision(position, radius, markVisibleFn, markTransparentFn, passesLightFn, inBoundsFn);\r\n}\r\n\r\ntl::expected<void, std::string> LoadTrns()\r\n{\r\n\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"plrgfx\\\\infra.trn\", InfravisionTable));\r\n\tRETURN_IF_ERROR(LoadFileInMemWithStatus(\"plrgfx\\\\stone.trn\", StoneTable));\r\n\treturn LoadFileInMemWithStatus(\"gendata\\\\pause.trn\", PauseTable);\r\n}\r\n\r\nvoid MakeLightTable()\r\n{\r\n\t// Generate 16 gradually darker translation tables for doing lighting\r\n\tuint8_t shade = 0;\r\n\tconstexpr uint8_t Black = 0;\r\n\tconstexpr uint8_t White = 255;\r\n\tfor (auto &lightTable : LightTables) {\r\n\t\tuint8_t colorIndex = 0;\r\n\t\tfor (const uint8_t steps : { 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16 }) {\r\n\t\t\tconst uint8_t shading = shade * steps / 16;\r\n\t\t\tconst uint8_t shadeStart = colorIndex;\r\n\t\t\tconst uint8_t shadeEnd = shadeStart + steps - 1;\r\n\t\t\tfor (uint8_t step = 0; step < steps; step++) {\r\n\t\t\t\tif (colorIndex == Black) {\r\n\t\t\t\t\tlightTable[colorIndex++] = Black;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tint color = shadeStart + step + shading;\r\n\t\t\t\tif (color > shadeEnd || color == White)\r\n\t\t\t\t\tcolor = Black;\r\n\t\t\t\tlightTable[colorIndex++] = color;\r\n\t\t\t}\r\n\t\t}\r\n\t\tshade++;\r\n\t}\r\n\r\n\tLightTables[15] = {}; // Make last shade pitch black\r\n\tFullyLitLightTable = LightTables[0].data();\r\n\tFullyDarkLightTable = LightTables[LightsMax].data();\r\n\r\n\tif (leveltype == DTYPE_HELL) {\r\n\t\t// Blood wall lighting\r\n\t\tconst auto shades = static_cast<int>(LightTables.size() - 1);\r\n\t\tfor (int i = 0; i < shades; i++) {\r\n\t\t\tauto &lightTable = LightTables[i];\r\n\t\t\tconstexpr int Range = 16;\r\n\t\t\tfor (int j = 0; j < Range; j++) {\r\n\t\t\t\tuint8_t color = ((Range - 1) << 4) / shades * (shades - i) / Range * (j + 1);\r\n\t\t\t\tcolor = 1 + (color >> 4);\r\n\t\t\t\tint idx = j + 1;\r\n\t\t\t\tlightTable[idx] = color;\r\n\t\t\t\tidx = 31 - j;\r\n\t\t\t\tlightTable[idx] = color;\r\n\t\t\t}\r\n\t\t}\r\n\t\tFullyLitLightTable = nullptr; // A color map is used for the ceiling animation, so even fully lit tiles have a color map\r\n\t} else if (IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\t// Make the lava fully bright\r\n\t\tfor (auto &lightTable : LightTables)\r\n\t\t\tstd::iota(lightTable.begin(), lightTable.begin() + 16, uint8_t { 0 });\r\n\t\tLightTables[15][0] = 0;\r\n\t\tstd::fill_n(LightTables[15].begin() + 1, 15, 1);\r\n\t\tFullyDarkLightTable = nullptr; // Tiles in Hellfire levels are never completely black\r\n\t}\r\n\r\n\t// Verify that fully lit and fully dark light table optimizations are correctly enabled/disabled (nullptr = disabled)\r\n\tassert((FullyLitLightTable != nullptr) == (LightTables[0][0] == 0 && std::adjacent_find(LightTables[0].begin(), LightTables[0].end() - 1, [](auto x, auto y) { return (x + 1) != y; }) == LightTables[0].end() - 1));\r\n\tassert((FullyDarkLightTable != nullptr) == (std::all_of(LightTables[LightsMax].begin(), LightTables[LightsMax].end(), [](auto x) { return x == 0; })));\r\n\r\n\t// Generate light falloffs ranges\r\n\tconst float maxDarkness = 15;\r\n\tconst float maxBrightness = 0;\r\n\tfor (unsigned radius = 0; radius < NumLightRadiuses; radius++) {\r\n\t\tconst unsigned maxDistance = (radius + 1) * 8;\r\n\t\tfor (unsigned distance = 0; distance < 128; distance++) {\r\n\t\t\tif (distance > maxDistance) {\r\n\t\t\t\tLightFalloffs[radius][distance] = 15;\r\n\t\t\t} else {\r\n\t\t\t\tconst float factor = static_cast<float>(distance) / static_cast<float>(maxDistance);\r\n\t\t\t\tfloat scaled;\r\n\t\t\t\tif (IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\t\t\t\t// quardratic falloff with over exposure\r\n\t\t\t\t\tconst float brightness = static_cast<float>(radius) * 1.25F;\r\n\t\t\t\t\tscaled = factor * factor * brightness + (maxDarkness - brightness);\r\n\t\t\t\t\tscaled = std::max(maxBrightness, scaled);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Leaner falloff\r\n\t\t\t\t\tscaled = factor * maxDarkness;\r\n\t\t\t\t}\r\n\t\t\t\tscaled += 0.5F; // Round up\r\n\t\t\t\tLightFalloffs[radius][distance] = static_cast<uint8_t>(scaled);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Generate the light cone interpolations\r\n\tfor (int offsetY = 0; offsetY < 8; offsetY++) {\r\n\t\tfor (int offsetX = 0; offsetX < 8; offsetX++) {\r\n\t\t\tfor (int y = 0; y < 16; y++) {\r\n\t\t\t\tfor (int x = 0; x < 16; x++) {\r\n\t\t\t\t\tconst int a = (8 * x - offsetX);\r\n\t\t\t\t\tconst int b = (8 * y - offsetY);\r\n\t\t\t\t\tLightConeInterpolations[offsetX][offsetY][x][y] = static_cast<uint8_t>(sqrt(a * a + b * b));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#ifdef _DEBUG\r\nvoid ToggleLighting()\r\n{\r\n\tDisableLighting = !DisableLighting;\r\n\r\n\tif (DisableLighting) {\r\n\t\tmemset(dLight, 0, sizeof(dLight));\r\n\t\treturn;\r\n\t}\r\n\r\n\tmemcpy(dLight, dPreLight, sizeof(dLight));\r\n\tfor (const Player &player : Players) {\r\n\t\tif (player.plractive && player.isOnActiveLevel()) {\r\n\t\t\tDoLighting(player.position.tile, player._pLightRad, {});\r\n\t\t}\r\n\t}\r\n}\r\n#endif\r\n\r\nvoid InitLighting()\r\n{\r\n\tActiveLightCount = 0;\r\n\tUpdateLighting = false;\r\n\tUpdateVision = false;\r\n#ifdef _DEBUG\r\n\tDisableLighting = false;\r\n#endif\r\n\r\n\tstd::iota(ActiveLights.begin(), ActiveLights.end(), uint8_t { 0 });\r\n\tVisionActive = {};\r\n\tTransList = {};\r\n}\r\n\r\nint AddLight(Point position, uint8_t radius)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn NO_LIGHT;\r\n#endif\r\n\tif (ActiveLightCount >= MAXLIGHTS)\r\n\t\treturn NO_LIGHT;\r\n\r\n\tconst int lid = ActiveLights[ActiveLightCount++];\r\n\tLight &light = Lights[lid];\r\n\tlight.position.tile = position;\r\n\tlight.radius = radius;\r\n\tlight.position.offset = { 0, 0 };\r\n\tlight.isInvalid = false;\r\n\tlight.hasChanged = false;\r\n\r\n\tUpdateLighting = true;\r\n\r\n\treturn lid;\r\n}\r\n\r\nvoid AddUnLight(int i)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn;\r\n#endif\r\n\tif (i == NO_LIGHT)\r\n\t\treturn;\r\n\r\n\tLights[i].isInvalid = true;\r\n\r\n\tUpdateLighting = true;\r\n}\r\n\r\nvoid ChangeLightRadius(int i, uint8_t radius)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn;\r\n#endif\r\n\tif (i == NO_LIGHT)\r\n\t\treturn;\r\n\r\n\tLight &light = Lights[i];\r\n\tlight.hasChanged = true;\r\n\tlight.position.old = light.position.tile;\r\n\tlight.oldRadius = light.radius;\r\n\tlight.radius = radius;\r\n\r\n\tUpdateLighting = true;\r\n}\r\n\r\nvoid ChangeLightXY(int i, Point position)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn;\r\n#endif\r\n\tif (i == NO_LIGHT)\r\n\t\treturn;\r\n\r\n\tLight &light = Lights[i];\r\n\tlight.hasChanged = true;\r\n\tlight.position.old = light.position.tile;\r\n\tlight.oldRadius = light.radius;\r\n\tlight.position.tile = position;\r\n\r\n\tUpdateLighting = true;\r\n}\r\n\r\nvoid ChangeLightOffset(int i, DisplacementOf<int8_t> offset)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn;\r\n#endif\r\n\tif (i == NO_LIGHT)\r\n\t\treturn;\r\n\r\n\tLight &light = Lights[i];\r\n\tif (light.position.offset == offset)\r\n\t\treturn;\r\n\r\n\tlight.hasChanged = true;\r\n\tlight.position.old = light.position.tile;\r\n\tlight.oldRadius = light.radius;\r\n\tlight.position.offset = offset;\r\n\r\n\tUpdateLighting = true;\r\n}\r\n\r\nvoid ChangeLight(int i, Point position, uint8_t radius)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn;\r\n#endif\r\n\tif (i == NO_LIGHT)\r\n\t\treturn;\r\n\r\n\tLight &light = Lights[i];\r\n\tlight.hasChanged = true;\r\n\tlight.position.old = light.position.tile;\r\n\tlight.oldRadius = light.radius;\r\n\tlight.position.tile = position;\r\n\tlight.radius = radius;\r\n\r\n\tUpdateLighting = true;\r\n}\r\n\r\nvoid ProcessLightList()\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn;\r\n#endif\r\n\tif (!UpdateLighting)\r\n\t\treturn;\r\n\tfor (int i = 0; i < ActiveLightCount; i++) {\r\n\t\tLight &light = Lights[ActiveLights[i]];\r\n\t\tif (light.isInvalid) {\r\n\t\t\tDoUnLight(light.position.tile, light.radius);\r\n\t\t}\r\n\t\tif (light.hasChanged) {\r\n\t\t\tDoUnLight(light.position.old, light.oldRadius);\r\n\t\t\tlight.hasChanged = false;\r\n\t\t}\r\n\t}\r\n\tfor (int i = 0; i < ActiveLightCount; i++) {\r\n\t\tconst Light &light = Lights[ActiveLights[i]];\r\n\t\tif (light.isInvalid) {\r\n\t\t\tActiveLightCount--;\r\n\t\t\tstd::swap(ActiveLights[ActiveLightCount], ActiveLights[i]);\r\n\t\t\ti--;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (TileHasAny(light.position.tile, TileProperties::Solid))\r\n\t\t\tcontinue; // Monster hidden in a wall, don't spoil the surprise\r\n\t\tDoLighting(light.position.tile, light.radius, light.position.offset);\r\n\t}\r\n\r\n\tUpdateLighting = false;\r\n}\r\n\r\nvoid SavePreLighting()\r\n{\r\n\tmemcpy(dPreLight, dLight, sizeof(dPreLight));\r\n}\r\n\r\nvoid ActivateVision(Point position, int r, size_t id)\r\n{\r\n\tauto &vision = VisionList[id];\r\n\tvision.position.tile = position;\r\n\tvision.radius = r;\r\n\tvision.isInvalid = false;\r\n\tvision.hasChanged = false;\r\n\tVisionActive[id] = true;\r\n\r\n\tUpdateVision = true;\r\n}\r\n\r\nvoid ChangeVisionRadius(size_t id, int r)\r\n{\r\n\tauto &vision = VisionList[id];\r\n\tvision.hasChanged = true;\r\n\tvision.position.old = vision.position.tile;\r\n\tvision.oldRadius = vision.radius;\r\n\tvision.radius = r;\r\n\tUpdateVision = true;\r\n}\r\n\r\nvoid ChangeVisionXY(size_t id, Point position)\r\n{\r\n\tauto &vision = VisionList[id];\r\n\tvision.hasChanged = true;\r\n\tvision.position.old = vision.position.tile;\r\n\tvision.oldRadius = vision.radius;\r\n\tvision.position.tile = position;\r\n\tUpdateVision = true;\r\n}\r\n\r\nvoid ProcessVisionList()\r\n{\r\n\tif (!UpdateVision)\r\n\t\treturn;\r\n\r\n\tTransList = {};\r\n\r\n\tfor (const Player &player : Players) {\r\n\t\tconst size_t id = player.getId();\r\n\t\tif (!VisionActive[id])\r\n\t\t\tcontinue;\r\n\t\tLight &vision = VisionList[id];\r\n\t\tif (!player.plractive || !player.isOnActiveLevel() || (player._pLvlChanging && &player != MyPlayer)) {\r\n\t\t\tDoUnVision(vision.position.tile, vision.radius);\r\n\t\t\tVisionActive[id] = false;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (vision.hasChanged) {\r\n\t\t\tDoUnVision(vision.position.old, vision.oldRadius);\r\n\t\t\tvision.hasChanged = false;\r\n\t\t}\r\n\t}\r\n\tfor (const Player &player : Players) {\r\n\t\tconst size_t id = player.getId();\r\n\t\tif (!VisionActive[id])\r\n\t\t\tcontinue;\r\n\t\tconst Light &vision = VisionList[id];\r\n\t\tMapExplorationType doautomap = MAP_EXP_SELF;\r\n\t\tif (&player != MyPlayer)\r\n\t\t\tdoautomap = player.friendlyMode ? MAP_EXP_OTHERS : MAP_EXP_NONE;\r\n\t\tDoVision(\r\n\t\t    vision.position.tile,\r\n\t\t    vision.radius,\r\n\t\t    doautomap,\r\n\t\t    &player == MyPlayer);\r\n\t}\r\n\r\n\tUpdateVision = false;\r\n}\r\n\r\nvoid lighting_color_cycling()\r\n{\r\n\tfor (auto &lightTable : LightTables) {\r\n\t\t// shift elements between indexes 1-31 to left\r\n\t\tstd::rotate(lightTable.begin() + 1, lightTable.begin() + 2, lightTable.begin() + 32);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lighting.h",
    "content": "/**\r\n * @file lighting.h\r\n *\r\n * Interface of light and vision.\r\n */\r\n#pragma once\r\n\r\n#include <array>\r\n#include <cstdint>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"automap.h\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nstruct LightPosition {\r\n\tWorldTilePosition tile;\r\n\t/** Pixel offset from tile. */\r\n\tDisplacementOf<int8_t> offset;\r\n\t/** Previous position. */\r\n\tWorldTilePosition old;\r\n};\r\n\r\nstruct Light {\r\n\tLightPosition position;\r\n\tuint8_t radius;\r\n\tuint8_t oldRadius;\r\n\tbool isInvalid;\r\n\tbool hasChanged;\r\n};\r\n\r\nextern Light VisionList[MAXVISION];\r\nextern std::array<bool, MAXVISION> VisionActive;\r\nextern Light Lights[MAXLIGHTS];\r\nextern std::array<uint8_t, MAXLIGHTS> ActiveLights;\r\nextern int ActiveLightCount;\r\nextern DVL_API_FOR_TEST std::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> LightTables;\r\n/** @brief Contains a pointer to a light table that is fully lit (no color mapping is required). Can be null in hell. */\r\nextern DVL_API_FOR_TEST uint8_t *FullyLitLightTable;\r\n/** @brief Contains a pointer to a light table that is fully dark (every color result to 0/black). Can be null in hellfire levels. */\r\nextern DVL_API_FOR_TEST uint8_t *FullyDarkLightTable;\r\nextern std::array<uint8_t, 256> InfravisionTable;\r\nextern std::array<uint8_t, 256> StoneTable;\r\nextern std::array<uint8_t, 256> PauseTable;\r\n#ifdef _DEBUG\r\nextern bool DisableLighting;\r\n#endif\r\nextern bool UpdateLighting;\r\n\r\nvoid DoUnLight(Point position, uint8_t radius);\r\nvoid DoLighting(Point position, uint8_t radius, DisplacementOf<int8_t> offset);\r\nvoid DoUnVision(Point position, uint8_t radius);\r\nvoid DoVision(Point position, uint8_t radius, MapExplorationType doAutomap, bool visible);\r\ntl::expected<void, std::string> LoadTrns();\r\nvoid MakeLightTable();\r\n#ifdef _DEBUG\r\nvoid ToggleLighting();\r\n#endif\r\nvoid InitLighting();\r\nint AddLight(Point position, uint8_t radius);\r\nvoid AddUnLight(int i);\r\nvoid ChangeLightRadius(int i, uint8_t radius);\r\nvoid ChangeLightXY(int i, Point position);\r\nvoid ChangeLightOffset(int i, DisplacementOf<int8_t> offset);\r\nvoid ChangeLight(int i, Point position, uint8_t radius);\r\nvoid ProcessLightList();\r\nvoid SavePreLighting();\r\nvoid ActivateVision(Point position, int r, size_t id);\r\nvoid ChangeVisionRadius(size_t id, int r);\r\nvoid ChangeVisionXY(size_t id, Point position);\r\nvoid ProcessVisionList();\r\nvoid lighting_color_cycling();\r\n\r\nconstexpr int MaxCrawlRadius = 18;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/loadsave.cpp",
    "content": "/**\r\n * @file loadsave.cpp\r\n *\r\n * Implementation of save game functionality.\r\n */\r\n#include \"loadsave.h\"\r\n\r\n#include <climits>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <numeric>\r\n#include <string>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n\r\n#include \"automap.h\"\r\n#include \"codec.h\"\r\n#include \"control/control.hpp\"\r\n#include \"cursor.h\"\r\n#include \"dead.h\"\r\n#include \"doom.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"lighting.h\"\r\n#include \"menu.h\"\r\n#include \"missiles.h\"\r\n#include \"monster.h\"\r\n#include \"monsters/validation.hpp\"\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"pfile.h\"\r\n#include \"plrmsg.h\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/status_macros.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool gbIsHellfireSaveGame;\r\nuint8_t giNumberOfLevels;\r\n\r\nnamespace {\r\n\r\nconstexpr size_t MaxMissilesForSaveGame = 125;\r\nconstexpr size_t PlayerWalkPathSizeForSaveGame = 25;\r\n\r\nuint8_t giNumberQuests;\r\nuint8_t giNumberOfSmithPremiumItems;\r\n\r\ntemplate <class T>\r\nT SwapLE(T in)\r\n{\r\n\tswitch (sizeof(T)) {\r\n\tcase 2:\r\n\t\treturn static_cast<T>(Swap16LE(static_cast<uint16_t>(in)));\r\n\tcase 4:\r\n\t\treturn static_cast<T>(Swap32LE(static_cast<uint32_t>(in)));\r\n\tcase 8:\r\n\t\treturn static_cast<T>(Swap64LE(in));\r\n\tdefault:\r\n\t\treturn in;\r\n\t}\r\n}\r\n\r\ntemplate <class T>\r\nT SwapBE(T in)\r\n{\r\n\tswitch (sizeof(T)) {\r\n\tcase 2:\r\n\t\treturn Swap16BE(in);\r\n\tcase 4:\r\n\t\treturn Swap32BE(in);\r\n\tcase 8:\r\n\t\treturn static_cast<T>(Swap64BE(in));\r\n\tdefault:\r\n\t\treturn in;\r\n\t}\r\n}\r\n\r\nvoid TerminateUtf8(char *str, size_t maxLength)\r\n{\r\n\tconst std::string_view inStr { str, maxLength };\r\n\tconst std::string_view truncStr = TruncateUtf8(inStr, maxLength - 1);\r\n\tconst size_t utf8Length = truncStr.size();\r\n\tstr[utf8Length] = '\\0';\r\n}\r\n\r\nclass LoadHelper {\r\n\tstd::unique_ptr<std::byte[]> m_buffer_;\r\n\tsize_t m_cur_ = 0;\r\n\tsize_t m_size_;\r\n\r\n\ttemplate <class T>\r\n\tT Next()\r\n\t{\r\n\t\tconst auto size = sizeof(T);\r\n\t\tif (!IsValid(size))\r\n\t\t\treturn 0;\r\n\r\n\t\tT value;\r\n\t\tmemcpy(&value, &m_buffer_[m_cur_], size);\r\n\t\tm_cur_ += size;\r\n\r\n\t\treturn value;\r\n\t}\r\n\r\npublic:\r\n\tLoadHelper(std::optional<SaveReader> archive, const char *szFileName)\r\n\t{\r\n\t\tif (archive)\r\n\t\t\tm_buffer_ = ReadArchive(*archive, szFileName, &m_size_);\r\n\t\telse\r\n\t\t\tm_buffer_ = nullptr;\r\n\t}\r\n\r\n\tbool IsValid(size_t size = 1)\r\n\t{\r\n\t\treturn m_buffer_ != nullptr\r\n\t\t    && m_size_ >= (m_cur_ + size);\r\n\t}\r\n\r\n\tsize_t Size() const\r\n\t{\r\n\t\treturn m_size_;\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\tconstexpr void Skip(size_t count = 1)\r\n\t{\r\n\t\tSkip(sizeof(T) * count);\r\n\t}\r\n\r\n\tvoid Skip(size_t size)\r\n\t{\r\n\t\tm_cur_ += size;\r\n\t}\r\n\r\n\tvoid NextBytes(void *bytes, size_t size)\r\n\t{\r\n\t\tif (!IsValid(size))\r\n\t\t\treturn;\r\n\r\n\t\tmemcpy(bytes, &m_buffer_[m_cur_], size);\r\n\t\tm_cur_ += size;\r\n\t}\r\n\r\n\ttemplate <class T>\r\n\tT NextLE()\r\n\t{\r\n\t\treturn SwapLE(Next<T>());\r\n\t}\r\n\r\n\ttemplate <class T>\r\n\tT NextBE()\r\n\t{\r\n\t\treturn SwapBE(Next<T>());\r\n\t}\r\n\r\n\ttemplate <class TSource, class TDesired>\r\n\tTDesired NextLENarrow(TSource modifier = 0)\r\n\t{\r\n\t\tstatic_assert(sizeof(TSource) > sizeof(TDesired), \"Can only narrow to a smaller type\");\r\n\t\tTSource value = SwapLE(Next<TSource>()) + modifier;\r\n\t\treturn static_cast<TDesired>(std::clamp<TSource>(value, std::numeric_limits<TDesired>::min(), std::numeric_limits<TDesired>::max()));\r\n\t}\r\n\r\n\tbool NextBool8()\r\n\t{\r\n\t\treturn Next<uint8_t>() != 0;\r\n\t}\r\n\r\n\tbool NextBool32()\r\n\t{\r\n\t\treturn Next<uint32_t>() != 0;\r\n\t}\r\n};\r\n\r\nclass SaveHelper {\r\n\tSaveWriter &m_mpqWriter;\r\n\tconst char *m_szFileName_;\r\n\tstd::unique_ptr<std::byte[]> m_buffer_;\r\n\tsize_t m_cur_ = 0;\r\n\tsize_t m_capacity_;\r\n\r\npublic:\r\n\tSaveHelper(SaveWriter &mpqWriter, const char *szFileName, size_t bufferLen)\r\n\t    : m_mpqWriter(mpqWriter)\r\n\t    , m_szFileName_(szFileName)\r\n\t    , m_buffer_(new std::byte[codec_get_encoded_len(bufferLen)])\r\n\t    , m_capacity_(bufferLen)\r\n\t{\r\n\t}\r\n\r\n\tbool IsValid(size_t len = 1)\r\n\t{\r\n\t\treturn m_buffer_ != nullptr\r\n\t\t    && m_capacity_ >= (m_cur_ + len);\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\tconstexpr void Skip(size_t count = 1)\r\n\t{\r\n\t\tSkip(sizeof(T) * count);\r\n\t}\r\n\r\n\tvoid Skip(size_t len)\r\n\t{\r\n\t\tstd::memset(&m_buffer_[m_cur_], 0, len);\r\n\t\tm_cur_ += len;\r\n\t}\r\n\r\n\tvoid WriteBytes(const void *bytes, size_t len)\r\n\t{\r\n\t\tif (!IsValid(len))\r\n\t\t\treturn;\r\n\r\n\t\tconst auto *src = static_cast<const std::byte *>(bytes);\r\n\t\tfor (size_t i = 0; i < len; ++i) {\r\n\t\t\tm_buffer_[m_cur_ + i] = src[i];\r\n\t\t}\r\n\t\tm_cur_ += len;\r\n\t}\r\n\r\n\ttemplate <class T>\r\n\tvoid WriteLE(T value)\r\n\t{\r\n\t\tvalue = SwapLE(value);\r\n\t\tWriteBytes(&value, sizeof(value));\r\n\t}\r\n\r\n\ttemplate <class T>\r\n\tvoid WriteBE(T value)\r\n\t{\r\n\t\tvalue = SwapBE(value);\r\n\t\tWriteBytes(&value, sizeof(value));\r\n\t}\r\n\r\n\t~SaveHelper()\r\n\t{\r\n\t\tconst auto encodedLen = codec_get_encoded_len(m_cur_);\r\n\t\tconst char *const password = pfile_get_password();\r\n\t\tcodec_encode(m_buffer_.get(), m_cur_, encodedLen, password);\r\n\t\tm_mpqWriter.WriteFile(m_szFileName_, m_buffer_.get(), encodedLen);\r\n\t}\r\n};\r\n\r\nstruct MonsterConversionData {\r\n\tint8_t monsterLevel;\r\n\tuint16_t experience;\r\n\tuint8_t toHit;\r\n\tuint8_t toHitSpecial;\r\n};\r\n\r\nstruct LevelConversionData {\r\n\tMonsterConversionData monsterConversionData[MaxMonsters];\r\n};\r\n\r\n[[nodiscard]] bool LoadItemData(LoadHelper &file, Item &item)\r\n{\r\n\titem._iSeed = file.NextLE<uint32_t>();\r\n\titem._iCreateInfo = file.NextLE<uint16_t>();\r\n\tfile.Skip(2); // Alignment\r\n\titem._itype = static_cast<ItemType>(file.NextLE<uint32_t>());\r\n\titem.position.x = file.NextLE<int32_t>();\r\n\titem.position.y = file.NextLE<int32_t>();\r\n\titem._iAnimFlag = file.NextBool32();\r\n\tfile.Skip(4); // Skip pointer _iAnimData\r\n\titem.AnimInfo = {};\r\n\titem.AnimInfo.numberOfFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\titem.AnimInfo.currentFrame = file.NextLENarrow<int32_t, int8_t>(-1);\r\n\tfile.Skip(8); // Skip _iAnimWidth and _iAnimWidth2\r\n\tfile.Skip(4); // Unused since 1.02\r\n\titem.selectionRegion = static_cast<SelectionRegion>(file.NextLE<uint8_t>());\r\n\tfile.Skip(3); // Alignment\r\n\titem._iPostDraw = file.NextBool32();\r\n\titem._iIdentified = file.NextBool32();\r\n\titem._iMagical = static_cast<item_quality>(file.NextLE<int8_t>());\r\n\tfile.NextBytes(item._iName, ItemNameLength);\r\n\tTerminateUtf8(item._iName, ItemNameLength);\r\n\tfile.NextBytes(item._iIName, ItemNameLength);\r\n\tTerminateUtf8(item._iIName, ItemNameLength);\r\n\titem._iLoc = static_cast<item_equip_type>(file.NextLE<int8_t>());\r\n\titem._iClass = static_cast<item_class>(file.NextLE<uint8_t>());\r\n\tfile.Skip(1); // Alignment\r\n\titem._iCurs = file.NextLE<int32_t>();\r\n\titem._ivalue = file.NextLE<int32_t>();\r\n\titem._iIvalue = file.NextLE<int32_t>();\r\n\titem._iMinDam = file.NextLE<int32_t>();\r\n\titem._iMaxDam = file.NextLE<int32_t>();\r\n\titem._iAC = file.NextLE<int32_t>();\r\n\titem._iFlags = static_cast<ItemSpecialEffect>(file.NextLE<uint32_t>());\r\n\titem._iMiscId = static_cast<item_misc_id>(file.NextLE<int32_t>());\r\n\titem._iSpell = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\titem._iCharges = file.NextLE<int32_t>();\r\n\titem._iMaxCharges = file.NextLE<int32_t>();\r\n\titem._iDurability = file.NextLE<int32_t>();\r\n\titem._iMaxDur = file.NextLE<int32_t>();\r\n\titem._iPLDam = file.NextLE<int32_t>();\r\n\titem._iPLToHit = file.NextLE<int32_t>();\r\n\titem._iPLAC = file.NextLE<int32_t>();\r\n\titem._iPLStr = file.NextLE<int32_t>();\r\n\titem._iPLMag = file.NextLE<int32_t>();\r\n\titem._iPLDex = file.NextLE<int32_t>();\r\n\titem._iPLVit = file.NextLE<int32_t>();\r\n\titem._iPLFR = file.NextLE<int32_t>();\r\n\titem._iPLLR = file.NextLE<int32_t>();\r\n\titem._iPLMR = file.NextLE<int32_t>();\r\n\titem._iPLMana = file.NextLE<int32_t>();\r\n\titem._iPLHP = file.NextLE<int32_t>();\r\n\titem._iPLDamMod = file.NextLE<int32_t>();\r\n\titem._iPLGetHit = file.NextLE<int32_t>();\r\n\titem._iPLLight = file.NextLE<int32_t>();\r\n\titem._iSplLvlAdd = file.NextLE<int8_t>();\r\n\titem._iRequest = file.NextBool8();\r\n\tfile.Skip(2); // Alignment\r\n\r\n\tconst int32_t uniqueMappingId = file.NextLE<int32_t>();\r\n\tif (item._iMagical == ITEM_QUALITY_UNIQUE) {\r\n\t\tconst auto findIt = UniqueItemMappingIdsToIndices.find(uniqueMappingId);\r\n\t\tif (findIt == UniqueItemMappingIdsToIndices.end()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst int uniqueIndex = findIt->second;\r\n\t\titem._iUid = uniqueIndex;\r\n\t} else {\r\n\t\titem._iUid = 0;\r\n\t}\r\n\r\n\titem._iFMinDam = file.NextLE<int32_t>();\r\n\titem._iFMaxDam = file.NextLE<int32_t>();\r\n\titem._iLMinDam = file.NextLE<int32_t>();\r\n\titem._iLMaxDam = file.NextLE<int32_t>();\r\n\titem._iPLEnAc = file.NextLE<int32_t>();\r\n\titem._iPrePower = static_cast<item_effect_type>(file.NextLE<int8_t>());\r\n\titem._iSufPower = static_cast<item_effect_type>(file.NextLE<int8_t>());\r\n\tfile.Skip(2); // Alignment\r\n\titem._iVAdd1 = file.NextLE<int32_t>();\r\n\titem._iVMult1 = file.NextLE<int32_t>();\r\n\titem._iVAdd2 = file.NextLE<int32_t>();\r\n\titem._iVMult2 = file.NextLE<int32_t>();\r\n\titem._iMinStr = file.NextLE<int8_t>();\r\n\titem._iMinMag = file.NextLE<uint8_t>();\r\n\titem._iMinDex = file.NextLE<int8_t>();\r\n\tfile.Skip(1); // Alignment\r\n\titem._iStatFlag = file.NextBool32();\r\n\r\n\tint32_t itemMappingId = file.NextLE<int32_t>();\r\n\tif (gbIsSpawn && itemMappingId < IDI_NUM_DEFAULT_ITEMS) {\r\n\t\titemMappingId = RemapItemIdxFromSpawn(static_cast<_item_indexes>(itemMappingId));\r\n\t}\r\n\tif (!gbIsHellfireSaveGame && itemMappingId < IDI_NUM_DEFAULT_ITEMS) {\r\n\t\titemMappingId = RemapItemIdxFromDiablo(static_cast<_item_indexes>(itemMappingId));\r\n\t}\r\n\tconst auto findIt = ItemMappingIdsToIndices.find(itemMappingId);\r\n\tif (findIt == ItemMappingIdsToIndices.end()) {\r\n\t\treturn false;\r\n\t}\r\n\tconst _item_indexes itemIndex = static_cast<_item_indexes>(findIt->second);\r\n\titem.IDidx = itemIndex;\r\n\r\n\titem.dwBuff = file.NextLE<uint32_t>();\r\n\tif (gbIsHellfireSaveGame)\r\n\t\titem._iDamAcFlags = static_cast<ItemSpecialEffectHf>(file.NextLE<uint32_t>());\r\n\telse\r\n\t\titem._iDamAcFlags = ItemSpecialEffectHf::None;\r\n\tUpdateHellfireFlag(item, item._iIName);\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid LoadAndValidateItemData(LoadHelper &file, Item &item)\r\n{\r\n\tconst bool success = LoadItemData(file, item);\r\n\tif (!success) {\r\n\t\titem.clear();\r\n\t\treturn;\r\n\t}\r\n\r\n\tRemoveInvalidItem(item);\r\n}\r\n\r\nvoid LoadPlayer(LoadHelper &file, Player &player)\r\n{\r\n\tplayer._pmode = static_cast<PLR_MODE>(file.NextLE<int32_t>());\r\n\r\n\tfor (size_t i = 0; i < PlayerWalkPathSizeForSaveGame; ++i) {\r\n\t\tplayer.walkpath[i] = file.NextLE<int8_t>();\r\n\t}\r\n\tplayer.walkpath[PlayerWalkPathSizeForSaveGame] = WALK_NONE;\r\n\r\n\tplayer.plractive = file.NextBool8();\r\n\tfile.Skip(2); // Alignment\r\n\tplayer.destAction = static_cast<action_id>(file.NextLE<int32_t>());\r\n\tplayer.destParam1 = file.NextLE<int32_t>();\r\n\tplayer.destParam2 = file.NextLE<int32_t>();\r\n\tplayer.destParam3 = file.NextLE<int32_t>();\r\n\tplayer.destParam4 = file.NextLE<int32_t>();\r\n\tplayer.setLevel(file.NextLE<uint32_t>());\r\n\tplayer.position.tile.x = file.NextLE<int32_t>();\r\n\tplayer.position.tile.y = file.NextLE<int32_t>();\r\n\tplayer.position.future.x = file.NextLE<int32_t>();\r\n\tplayer.position.future.y = file.NextLE<int32_t>();\r\n\tfile.Skip<uint32_t>(2); // Skip _ptargx and _ptargy\r\n\tplayer.position.last.x = file.NextLE<int32_t>();\r\n\tplayer.position.last.y = file.NextLE<int32_t>();\r\n\tplayer.position.old.x = file.NextLE<int32_t>();\r\n\tplayer.position.old.y = file.NextLE<int32_t>();\r\n\tfile.Skip<int32_t>(4); // Skip offset and velocity\r\n\tplayer._pdir = static_cast<Direction>(file.NextLE<int32_t>());\r\n\tfile.Skip(4); // Unused\r\n\tplayer._pgfxnum = file.NextLENarrow<uint32_t, uint8_t>();\r\n\tfile.Skip<uint32_t>(); // Skip pointer pData\r\n\tplayer.AnimInfo = {};\r\n\tplayer.AnimInfo.ticksPerFrame = file.NextLENarrow<int32_t, int8_t>(1);\r\n\tplayer.AnimInfo.tickCounterOfCurrentFrame = file.NextLENarrow<int32_t, int8_t>();\r\n\tplayer.AnimInfo.numberOfFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tplayer.AnimInfo.currentFrame = file.NextLENarrow<int32_t, int8_t>(-1);\r\n\tfile.Skip<uint32_t>(3); // Skip _pAnimWidth, _pAnimWidth2, _peflag\r\n\tplayer.lightId = file.NextLE<int32_t>();\r\n\tfile.Skip<int32_t>(); // _pvid\r\n\r\n\tplayer.queuedSpell.spellId = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\tplayer.queuedSpell.spellType = static_cast<SpellType>(file.NextLE<int8_t>());\r\n\tauto spellFrom = file.NextLE<int8_t>();\r\n\tif (!IsValidSpellFrom(spellFrom))\r\n\t\tspellFrom = 0;\r\n\tplayer.spellFrom = spellFrom;\r\n\tplayer.queuedSpell.spellFrom = spellFrom;\r\n\tfile.Skip(2); // Alignment\r\n\tplayer.inventorySpell = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\tfile.Skip<int8_t>(); // Skip _pTSplType\r\n\tfile.Skip(3);        // Alignment\r\n\tplayer._pRSpell = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\tplayer._pRSplType = static_cast<SpellType>(file.NextLE<int8_t>());\r\n\tfile.Skip(3); // Alignment\r\n\tplayer._pSBkSpell = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\tfile.Skip<int8_t>(); // Skip _pSBkSplType\r\n\r\n\t// Only read spell levels for learnable spells\r\n\tfor (int i = 0; i < static_cast<int>(SpellID::LAST); i++) {\r\n\t\tauto spl = static_cast<SpellID>(i);\r\n\t\tif (GetSpellBookLevel(spl) != -1)\r\n\t\t\tplayer._pSplLvl[i] = file.NextLE<uint8_t>();\r\n\t\telse\r\n\t\t\tfile.Skip<uint8_t>();\r\n\t}\r\n\t// Skip indices that are unused\r\n\tfor (int i = static_cast<int>(SpellID::LAST); i < 64; i++)\r\n\t\tfile.Skip<uint8_t>();\r\n\t// These spells are unavailable in Diablo as learnable spells\r\n\tif (!gbIsHellfire) {\r\n\t\tplayer._pSplLvl[static_cast<uint8_t>(SpellID::Apocalypse)] = 0;\r\n\t\tplayer._pSplLvl[static_cast<uint8_t>(SpellID::Nova)] = 0;\r\n\t}\r\n\r\n\tfile.Skip(7); // Alignment\r\n\tplayer._pMemSpells = file.NextLE<uint64_t>();\r\n\tplayer._pAblSpells = file.NextLE<uint64_t>();\r\n\tplayer._pScrlSpells = file.NextLE<uint64_t>();\r\n\tplayer._pSpellFlags = static_cast<SpellFlag>(file.NextLE<uint8_t>());\r\n\tfile.Skip(3); // Alignment\r\n\r\n\t// Extra hotkeys: to keep single player save compatibility, read only 4 hotkeys here, rely on LoadHotkeys for the rest\r\n\tfor (size_t i = 0; i < 4; i++) {\r\n\t\tplayer._pSplHotKey[i] = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\t}\r\n\tfor (size_t i = 0; i < 4; i++) {\r\n\t\tplayer._pSplTHotKey[i] = static_cast<SpellType>(file.NextLE<uint8_t>());\r\n\t}\r\n\r\n\tfile.Skip<int32_t>(); // Skip _pwtype\r\n\tplayer._pBlockFlag = file.NextBool8();\r\n\tplayer._pInvincible = file.NextBool8();\r\n\tplayer._pLightRad = file.NextLE<int8_t>();\r\n\tplayer._pLvlChanging = file.NextBool8();\r\n\r\n\tfile.NextBytes(player._pName, PlayerNameLength);\r\n\tTerminateUtf8(player._pName, PlayerNameLength);\r\n\tplayer._pClass = static_cast<HeroClass>(file.NextLE<int8_t>());\r\n\tfile.Skip(3); // Alignment\r\n\tplayer._pStrength = file.NextLE<int32_t>();\r\n\tplayer._pBaseStr = file.NextLE<int32_t>();\r\n\tplayer._pMagic = file.NextLE<int32_t>();\r\n\tplayer._pBaseMag = file.NextLE<int32_t>();\r\n\tplayer._pDexterity = file.NextLE<int32_t>();\r\n\tplayer._pBaseDex = file.NextLE<int32_t>();\r\n\tplayer._pVitality = file.NextLE<int32_t>();\r\n\tplayer._pBaseVit = file.NextLE<int32_t>();\r\n\tplayer._pStatPts = file.NextLE<int32_t>();\r\n\tplayer._pDamageMod = file.NextLE<int32_t>();\r\n\tfile.Skip<int32_t>(); // Skip _pBaseToBlk - always a copy of PlayerData.blockBonus\r\n\tplayer._pHPBase = file.NextLE<int32_t>();\r\n\tplayer._pMaxHPBase = file.NextLE<int32_t>();\r\n\tplayer._pHitPoints = file.NextLE<int32_t>();\r\n\tplayer._pMaxHP = file.NextLE<int32_t>();\r\n\tfile.Skip<int32_t>(); // Skip _pHPPer - always derived from hp and maxHP.\r\n\tplayer._pManaBase = file.NextLE<int32_t>();\r\n\tplayer._pMaxManaBase = file.NextLE<int32_t>();\r\n\tplayer._pMana = file.NextLE<int32_t>();\r\n\tplayer._pMaxMana = file.NextLE<int32_t>();\r\n\tfile.Skip<int32_t>(); // Skip _pManaPer - always derived from mana and maxMana\r\n\tplayer.setCharacterLevel(file.NextLE<uint8_t>());\r\n\tfile.Skip<uint8_t>(); // Skip _pMaxLevel - unused\r\n\tfile.Skip(2);         // Alignment\r\n\tplayer._pExperience = file.NextLE<uint32_t>();\r\n\tfile.Skip<uint32_t>(); // Skip _pMaxExp - unused\r\n\tfile.Skip<uint32_t>(); // Skip _pNextExper, we retrieve it when needed based on _pLevel\r\n\tplayer._pArmorClass = file.NextLE<int8_t>();\r\n\tplayer._pMagResist = file.NextLE<int8_t>();\r\n\tplayer._pFireResist = file.NextLE<int8_t>();\r\n\tplayer._pLghtResist = file.NextLE<int8_t>();\r\n\tplayer._pGold = file.NextLE<int32_t>();\r\n\tplayer._pInfraFlag = file.NextBool32();\r\n\r\n\tint32_t tempPositionX = file.NextLE<int32_t>();\r\n\tint32_t tempPositionY = file.NextLE<int32_t>();\r\n\tif (player._pmode == PM_WALK_NORTHWARDS) {\r\n\t\t// These values are saved as offsets to remain consistent with old savefiles\r\n\t\ttempPositionX += player.position.tile.x;\r\n\t\ttempPositionY += player.position.tile.y;\r\n\t}\r\n\tplayer.position.temp.x = static_cast<WorldTileCoord>(tempPositionX);\r\n\tplayer.position.temp.y = static_cast<WorldTileCoord>(tempPositionY);\r\n\r\n\tplayer.tempDirection = static_cast<Direction>(file.NextLE<int32_t>());\r\n\tplayer.queuedSpell.spellLevel = file.NextLE<int32_t>();\r\n\tfile.Skip<uint32_t>(); // skip _pVar5, was used for storing position of a tile which should have its HorizontalMovingPlayer flag removed after walking\r\n\tfile.Skip<int32_t>(2); // skip offset2;\r\n\tfile.Skip<uint32_t>(); // Skip actionFrame\r\n\r\n\tfor (uint8_t i = 0; i < giNumberOfLevels; i++)\r\n\t\tplayer._pLvlVisited[i] = file.NextBool8();\r\n\r\n\tfor (uint8_t i = 0; i < giNumberOfLevels; i++)\r\n\t\tplayer._pSLvlVisited[i] = file.NextBool8();\r\n\r\n\tfile.Skip(2);           // Alignment\r\n\tfile.Skip<uint32_t>();  // skip _pGFXLoad\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pNAnim\r\n\tplayer._pNFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>();  // skip _pNWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pWAnim\r\n\tplayer._pWFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>();  // skip _pWWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pAAnim\r\n\tplayer._pAFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>(); // skip _pAWidth\r\n\tplayer._pAFNum = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pLAnim\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pFAnim\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pTAnim\r\n\tplayer._pSFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>(); // skip _pSWidth\r\n\tplayer._pSFNum = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pHAnim\r\n\tplayer._pHFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>();  // skip _pHWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pDAnim\r\n\tplayer._pDFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>();  // skip _pDWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pBAnim\r\n\tplayer._pBFrames = file.NextLENarrow<int32_t, int8_t>();\r\n\tfile.Skip<uint32_t>(); // skip _pBWidth\r\n\r\n\tfor (Item &item : player.InvBody)\r\n\t\tLoadAndValidateItemData(file, item);\r\n\r\n\tfor (Item &item : player.InvList)\r\n\t\tLoadAndValidateItemData(file, item);\r\n\r\n\tplayer._pNumInv = file.NextLE<int32_t>();\r\n\r\n\tfor (int8_t &cell : player.InvGrid)\r\n\t\tcell = file.NextLE<int8_t>();\r\n\r\n\tfor (Item &item : player.SpdList)\r\n\t\tLoadAndValidateItemData(file, item);\r\n\r\n\tLoadAndValidateItemData(file, player.HoldItem);\r\n\r\n\tplayer._pIMinDam = file.NextLE<int32_t>();\r\n\tplayer._pIMaxDam = file.NextLE<int32_t>();\r\n\tplayer._pIAC = file.NextLE<int32_t>();\r\n\tplayer._pIBonusDam = file.NextLE<int32_t>();\r\n\tplayer._pIBonusToHit = file.NextLE<int32_t>();\r\n\tplayer._pIBonusAC = file.NextLE<int32_t>();\r\n\tplayer._pIBonusDamMod = file.NextLE<int32_t>();\r\n\tfile.Skip(4); // Alignment\r\n\r\n\tplayer._pISpells = file.NextLE<uint64_t>();\r\n\tplayer._pIFlags = static_cast<ItemSpecialEffect>(file.NextLE<int32_t>());\r\n\tplayer._pIGetHit = file.NextLE<int32_t>();\r\n\tplayer._pISplLvlAdd = file.NextLE<int8_t>();\r\n\tfile.Skip(1);         // Unused\r\n\tfile.Skip(2);         // Alignment\r\n\tfile.Skip<int32_t>(); // _pISplDur\r\n\tplayer._pIEnAc = file.NextLE<int32_t>();\r\n\tplayer._pIFMinDam = file.NextLE<int32_t>();\r\n\tplayer._pIFMaxDam = file.NextLE<int32_t>();\r\n\tplayer._pILMinDam = file.NextLE<int32_t>();\r\n\tplayer._pILMaxDam = file.NextLE<int32_t>();\r\n\tplayer._pOilType = static_cast<item_misc_id>(file.NextLE<int32_t>());\r\n\tplayer.pTownWarps = file.NextLE<uint8_t>();\r\n\tplayer.pDungMsgs = file.NextLE<uint8_t>();\r\n\tplayer.pLvlLoad = file.NextLE<uint8_t>();\r\n\r\n\tif (gbIsHellfireSaveGame) {\r\n\t\tplayer.pDungMsgs2 = file.NextLE<uint8_t>();\r\n\t} else {\r\n\t\tplayer.pDungMsgs2 = 0;\r\n\t\tfile.Skip(1); // pBattleNet\r\n\t}\r\n\tplayer.pManaShield = file.NextBool8();\r\n\tif (gbIsHellfireSaveGame) {\r\n\t\tplayer.pOriginalCathedral = file.NextBool8();\r\n\t} else {\r\n\t\tfile.Skip(1);\r\n\t\tplayer.pOriginalCathedral = true;\r\n\t}\r\n\tfile.Skip(2); // Available bytes\r\n\tplayer.wReflections = file.NextLE<uint16_t>();\r\n\tfile.Skip(14); // Available bytes\r\n\r\n\tplayer.pDiabloKillLevel = file.NextLE<uint32_t>();\r\n\tsgGameInitInfo.nDifficulty = static_cast<_difficulty>(file.NextLE<uint32_t>());\r\n\tplayer.pDamAcFlags = static_cast<ItemSpecialEffectHf>(file.NextLE<uint32_t>());\r\n\tfile.Skip(20); // Available bytes\r\n\tCalcPlrInv(player, false);\r\n\r\n\tplayer.executedSpell = player.queuedSpell; // Ensures backwards compatibility\r\n\r\n\t// Omit pointer _pNData\r\n\t// Omit pointer _pWData\r\n\t// Omit pointer _pAData\r\n\t// Omit pointer _pLData\r\n\t// Omit pointer _pFData\r\n\t// Omit pointer  _pTData\r\n\t// Omit pointer _pHData\r\n\t// Omit pointer _pDData\r\n\t// Omit pointer _pBData\r\n\t// Omit pointer pReserved\r\n\r\n\t// Ensure plrIsOnSetLevel and plrlevel is correctly initialized, because in vanilla sometimes plrlevel is not updated to setlvlnum\r\n\tif (setlevel)\r\n\t\tplayer.setLevel(setlvlnum);\r\n\telse\r\n\t\tplayer.setLevel(currlevel);\r\n}\r\n\r\nbool gbSkipSync = false;\r\n\r\n[[nodiscard]] bool LoadMonster(LoadHelper *file, Monster &monster, MonsterConversionData *monsterConversionData = nullptr)\r\n{\r\n\tmonster.levelType = file->NextLE<int32_t>();\r\n\tmonster.mode = static_cast<MonsterMode>(file->NextLE<int32_t>());\r\n\tmonster.goal = static_cast<MonsterGoal>(file->NextLE<uint8_t>());\r\n\tfile->Skip(3); // Alignment\r\n\tmonster.goalVar1 = file->NextLENarrow<int32_t, int16_t>();\r\n\tmonster.goalVar2 = file->NextLENarrow<int32_t, int8_t>();\r\n\tmonster.goalVar3 = file->NextLENarrow<int32_t, int8_t>();\r\n\tfile->Skip(4); // Unused\r\n\tmonster.pathCount = file->NextLE<uint8_t>();\r\n\tfile->Skip(3); // Alignment\r\n\tmonster.position.tile.x = file->NextLE<int32_t>();\r\n\tmonster.position.tile.y = file->NextLE<int32_t>();\r\n\tmonster.position.future.x = file->NextLE<int32_t>();\r\n\tmonster.position.future.y = file->NextLE<int32_t>();\r\n\tmonster.position.old.x = file->NextLE<int32_t>();\r\n\tmonster.position.old.y = file->NextLE<int32_t>();\r\n\tfile->Skip<int32_t>(4); // Skip offset and velocity\r\n\tmonster.direction = static_cast<Direction>(file->NextLE<int32_t>());\r\n\tmonster.enemy = file->NextLE<int32_t>();\r\n\tmonster.enemyPosition.x = file->NextLE<uint8_t>();\r\n\tmonster.enemyPosition.y = file->NextLE<uint8_t>();\r\n\tfile->Skip(2); // Unused\r\n\r\n\tfile->Skip(4); // Skip pointer _mAnimData\r\n\tmonster.animInfo = {};\r\n\tmonster.animInfo.ticksPerFrame = file->NextLENarrow<int32_t, int8_t>();\r\n\t// Ensure that we can increase the tickCounterOfCurrentFrame at least once without overflow (needed for backwards compatibility for sitting gargoyles)\r\n\tmonster.animInfo.tickCounterOfCurrentFrame = file->NextLENarrow<int32_t, int8_t>(1) - 1;\r\n\tmonster.animInfo.numberOfFrames = file->NextLENarrow<int32_t, int8_t>();\r\n\tmonster.animInfo.currentFrame = file->NextLENarrow<int32_t, int8_t>(-1);\r\n\tfile->Skip(4); // Skip _meflag\r\n\tmonster.isInvalid = file->NextBool32();\r\n\tmonster.var1 = file->NextLENarrow<int32_t, int16_t>();\r\n\tmonster.var2 = file->NextLENarrow<int32_t, int16_t>();\r\n\tmonster.var3 = file->NextLENarrow<int32_t, int8_t>();\r\n\tmonster.position.temp.x = file->NextLENarrow<int32_t, WorldTileCoord>();\r\n\tmonster.position.temp.y = file->NextLENarrow<int32_t, WorldTileCoord>();\r\n\tfile->Skip<int32_t>(2); // skip offset2;\r\n\tfile->Skip(4);          // Skip actionFrame\r\n\tmonster.maxHitPoints = file->NextLE<int32_t>();\r\n\tmonster.hitPoints = file->NextLE<int32_t>();\r\n\r\n\tmonster.ai = static_cast<MonsterAIID>(file->NextLE<uint8_t>());\r\n\tmonster.intelligence = file->NextLE<uint8_t>();\r\n\tfile->Skip(2); // Alignment\r\n\tmonster.flags = file->NextLE<uint32_t>();\r\n\tmonster.activeForTicks = file->NextLE<uint8_t>();\r\n\tfile->Skip(3); // Alignment\r\n\tfile->Skip(4); // Unused\r\n\tmonster.position.last.x = file->NextLE<int32_t>();\r\n\tmonster.position.last.y = file->NextLE<int32_t>();\r\n\tmonster.rndItemSeed = file->NextLE<uint32_t>();\r\n\tmonster.aiSeed = file->NextLE<uint32_t>();\r\n\tfile->Skip(4); // Unused\r\n\r\n\tmonster.uniqueType = static_cast<UniqueMonsterType>(file->NextLE<uint8_t>() - 1);\r\n\tmonster.uniqTrans = file->NextLE<uint8_t>();\r\n\tmonster.corpseId = file->NextLE<int8_t>();\r\n\r\n\tmonster.whoHit = file->NextLE<int8_t>();\r\n\tif (monsterConversionData != nullptr)\r\n\t\tmonsterConversionData->monsterLevel = file->NextLE<int8_t>();\r\n\telse\r\n\t\tfile->Skip(1); // Skip level - now calculated on the fly\r\n\tfile->Skip(1);     // Alignment\r\n\tif (monsterConversionData != nullptr)\r\n\t\tmonsterConversionData->experience = file->NextLE<uint16_t>();\r\n\telse\r\n\t\tfile->Skip(2); // Skip exp - now calculated from monstdat when the monster dies\r\n\r\n\tif (monsterConversionData != nullptr)\r\n\t\tmonsterConversionData->toHit = file->NextLE<uint8_t>();\r\n\telse if (monster.isPlayerMinion()) // Don't skip for golems\r\n\t\tmonster.golemToHit = file->NextLE<uint8_t>();\r\n\telse\r\n\t\tfile->Skip(1); // Skip toHit - now calculated on the fly\r\n\tmonster.minDamage = file->NextLE<uint8_t>();\r\n\tmonster.maxDamage = file->NextLE<uint8_t>();\r\n\tif (monsterConversionData != nullptr)\r\n\t\tmonsterConversionData->toHitSpecial = file->NextLE<uint8_t>();\r\n\telse\r\n\t\tfile->Skip(1); // Skip toHitSpecial - now calculated on the fly\r\n\tmonster.minDamageSpecial = file->NextLE<uint8_t>();\r\n\tmonster.maxDamageSpecial = file->NextLE<uint8_t>();\r\n\tmonster.armorClass = file->NextLE<uint8_t>();\r\n\tfile->Skip(1); // Alignment\r\n\tmonster.resistance = file->NextLE<uint16_t>();\r\n\tfile->Skip(2); // Alignment\r\n\r\n\tmonster.talkMsg = static_cast<_speech_id>(file->NextLE<int32_t>());\r\n\tif (monster.talkMsg == TEXT_KING1) // Fix original bad mapping of NONE for monsters\r\n\t\tmonster.talkMsg = TEXT_NONE;\r\n\tmonster.leader = file->NextLE<uint8_t>();\r\n\tif (monster.leader == 0)\r\n\t\tmonster.leader = Monster::NoLeader; // Golems shouldn't be leaders of other monsters\r\n\tmonster.leaderRelation = static_cast<LeaderRelation>(file->NextLE<uint8_t>());\r\n\tmonster.packSize = file->NextLE<uint8_t>();\r\n\tmonster.lightId = file->NextLE<int8_t>();\r\n\tif (monster.lightId == 0)\r\n\t\tmonster.lightId = NO_LIGHT; // Correct incorrect values in old saves\r\n\r\n\t// Omit pointer name;\r\n\r\n\tif (monster.mode == MonsterMode::Petrified)\r\n\t\tmonster.animInfo.isPetrified = true;\r\n\r\n\tif (monster.isUnique()) {\r\n\t\t// check if the unique monster is still valid (it could no longer be valid e.g. because the loaded mods changed and the unique monsters changed as a consequence)\r\n\t\tconst bool valid = IsMonsterValid(monster);\r\n\t\tif (!valid) {\r\n\t\t\tLogWarn(\"Monster no longer valid, skipping it.\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid LoadMonsters(LoadHelper &file, ankerl::unordered_dense::set<unsigned> &removedMonsterIds, const bool applyLight, LevelConversionData *levelConversionData)\r\n{\r\n\tfor (unsigned &monsterId : ActiveMonsters)\r\n\t\tmonsterId = file.NextBE<uint32_t>();\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount;) {\r\n\t\tMonster &monster = Monsters[ActiveMonsters[i]];\r\n\t\tMonsterConversionData *monsterConversionData = nullptr;\r\n\t\tif (levelConversionData != nullptr)\r\n\t\t\tmonsterConversionData = &levelConversionData->monsterConversionData[ActiveMonsters[i]];\r\n\t\tconst bool valid = LoadMonster(&file, monster, monsterConversionData);\r\n\t\tif (!valid) {\r\n\t\t\tMonsters[ActiveMonsters[i]] = {};\r\n\t\t\tremovedMonsterIds.insert(ActiveMonsters[i]);\r\n\t\t\tfor (size_t j = i + 1; j < ActiveMonsterCount; j++) {\r\n\t\t\t\tActiveMonsters[j - 1] = ActiveMonsters[j];\r\n\t\t\t}\r\n\t\t\t--ActiveMonsterCount;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (applyLight && monster.isUnique() && monster.lightId != NO_LIGHT)\r\n\t\t\tLights[monster.lightId].isInvalid = false;\r\n\r\n\t\ti++;\r\n\t}\r\n\r\n\tfor (const unsigned removedMonsterId : removedMonsterIds) {\r\n\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\t\tMonster &activeMonster = Monsters[ActiveMonsters[i]];\r\n\t\t\tif ((activeMonster.flags & MFLAG_TARGETS_MONSTER) != 0 && activeMonster.enemy == removedMonsterId) {\r\n\t\t\t\tactiveMonster.flags |= MFLAG_NO_ENEMY;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Recalculate the pack size of monster group that may have underflown\r\n */\r\nvoid SyncPackSize(Monster &leader)\r\n{\r\n\tif (!leader.isUnique())\r\n\t\treturn;\r\n\tif (leader.ai != MonsterAIID::Scavenger)\r\n\t\treturn;\r\n\r\n\tleader.packSize = 0;\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst Monster &minion = Monsters[ActiveMonsters[i]];\r\n\t\tif (minion.leaderRelation == LeaderRelation::Leashed && minion.getLeader() == &leader)\r\n\t\t\tleader.packSize++;\r\n\t}\r\n}\r\n\r\nvoid LoadMissile(LoadHelper *file)\r\n{\r\n\tMissile missile = {};\r\n\tmissile._mitype = static_cast<MissileID>(file->NextLE<int32_t>());\r\n\tmissile.position.tile.x = file->NextLE<int32_t>();\r\n\tmissile.position.tile.y = file->NextLE<int32_t>();\r\n\tmissile.position.offset.deltaX = file->NextLE<int32_t>();\r\n\tmissile.position.offset.deltaY = file->NextLE<int32_t>();\r\n\tmissile.position.velocity.deltaX = file->NextLE<int32_t>();\r\n\tmissile.position.velocity.deltaY = file->NextLE<int32_t>();\r\n\tmissile.position.start.x = file->NextLE<int32_t>();\r\n\tmissile.position.start.y = file->NextLE<int32_t>();\r\n\tmissile.position.traveled.deltaX = file->NextLE<int32_t>();\r\n\tmissile.position.traveled.deltaY = file->NextLE<int32_t>();\r\n\tmissile.setFrameGroupRaw(file->NextLE<int32_t>());\r\n\tmissile._mispllvl = file->NextLE<int32_t>();\r\n\tmissile._miDelFlag = file->NextBool32();\r\n\tmissile._miAnimType = static_cast<MissileGraphicID>(file->NextLE<uint8_t>());\r\n\tfile->Skip(3); // Alignment\r\n\tmissile._miAnimFlags = static_cast<MissileGraphicsFlags>(file->NextLE<int32_t>());\r\n\tfile->Skip(4); // Skip pointer _miAnimData\r\n\tmissile._miAnimDelay = file->NextLE<int32_t>();\r\n\tmissile._miAnimLen = file->NextLE<int32_t>();\r\n\tmissile._miAnimWidth = file->NextLE<int32_t>();\r\n\tmissile._miAnimWidth2 = file->NextLE<int32_t>();\r\n\tmissile._miAnimCnt = file->NextLE<int32_t>();\r\n\tmissile._miAnimAdd = file->NextLE<int32_t>();\r\n\tmissile._miAnimFrame = file->NextLE<int32_t>();\r\n\tmissile._miDrawFlag = file->NextBool32();\r\n\tmissile._miLightFlag = file->NextBool32();\r\n\tmissile._miPreFlag = file->NextBool32();\r\n\tmissile._miUniqTrans = file->NextLE<uint32_t>();\r\n\tmissile.duration = file->NextLE<int32_t>();\r\n\tmissile._misource = file->NextLE<int32_t>();\r\n\tmissile._micaster = static_cast<mienemy_type>(file->NextLE<int32_t>());\r\n\tmissile._midam = file->NextLE<int32_t>();\r\n\tmissile._miHitFlag = file->NextBool32();\r\n\tmissile._midist = file->NextLE<int32_t>();\r\n\tmissile._mlid = file->NextLE<int32_t>();\r\n\tmissile._mirnd = file->NextLE<int32_t>();\r\n\tmissile.var1 = file->NextLE<int32_t>();\r\n\tmissile.var2 = file->NextLE<int32_t>();\r\n\tmissile.var3 = file->NextLE<int32_t>();\r\n\tmissile.var4 = file->NextLE<int32_t>();\r\n\tmissile.var5 = file->NextLE<int32_t>();\r\n\tmissile.var6 = file->NextLE<int32_t>();\r\n\tmissile.var7 = file->NextLE<int32_t>();\r\n\tmissile.limitReached = file->NextBool32();\r\n\tmissile.lastCollisionTargetHash = 0;\r\n\tif (Missiles.size() < Missiles.max_size()) {\r\n\t\tMissiles.push_back(missile);\r\n\t}\r\n}\r\n\r\n_object_id ConvertFromHellfireObject(_object_id type)\r\n{\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\tswitch (type) {\r\n\t\tcase OBJ_BARREL:\r\n\t\t\treturn OBJ_POD;\r\n\t\tcase OBJ_BARRELEX:\r\n\t\t\treturn OBJ_PODEX;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tswitch (type) {\r\n\t\tcase OBJ_BARREL:\r\n\t\t\treturn OBJ_URN;\r\n\t\tcase OBJ_BARRELEX:\r\n\t\t\treturn OBJ_URNEX;\r\n\t\tcase OBJ_STORYBOOK:\r\n\t\t\treturn OBJ_L5BOOKS;\r\n\t\tcase OBJ_STORYCANDLE:\r\n\t\t\treturn OBJ_L5CANDLE;\r\n\t\tcase OBJ_L1LDOOR:\r\n\t\t\treturn OBJ_L5LDOOR;\r\n\t\tcase OBJ_L1RDOOR:\r\n\t\t\treturn OBJ_L5RDOOR;\r\n\t\tcase OBJ_LEVER:\r\n\t\t\treturn OBJ_L5LEVER;\r\n\t\tcase OBJ_SARC:\r\n\t\t\treturn OBJ_L5SARC;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn type;\r\n}\r\n\r\nvoid LoadObject(LoadHelper &file, Object &object)\r\n{\r\n\tobject._otype = ConvertFromHellfireObject(static_cast<_object_id>(file.NextLE<int32_t>()));\r\n\tobject.position.x = file.NextLE<int32_t>();\r\n\tobject.position.y = file.NextLE<int32_t>();\r\n\tobject.applyLighting = file.NextBool32();\r\n\tobject._oAnimFlag = file.NextBool32();\r\n\tfile.Skip(4); // Skip pointer _oAnimData\r\n\tobject._oAnimDelay = file.NextLE<int32_t>();\r\n\tobject._oAnimCnt = file.NextLE<int32_t>();\r\n\tobject._oAnimLen = file.NextLE<uint32_t>();\r\n\tobject._oAnimFrame = file.NextLE<uint32_t>();\r\n\tobject._oAnimWidth = static_cast<uint16_t>(file.NextLE<int32_t>());\r\n\tfile.Skip(4); // Skip _oAnimWidth2\r\n\tobject._oDelFlag = file.NextBool32();\r\n\tobject._oBreak = file.NextLE<int8_t>();\r\n\tfile.Skip(3); // Alignment\r\n\tobject._oSolidFlag = file.NextBool32();\r\n\tobject._oMissFlag = file.NextBool32();\r\n\r\n\tobject.selectionRegion = static_cast<SelectionRegion>(file.NextLE<int8_t>());\r\n\tfile.Skip(3); // Alignment\r\n\tobject._oPreFlag = file.NextBool32();\r\n\tobject._oTrapFlag = file.NextBool32();\r\n\tobject._oDoorFlag = file.NextBool32();\r\n\tobject._olid = file.NextLE<int32_t>();\r\n\tobject._oRndSeed = file.NextLE<uint32_t>();\r\n\tobject._oVar1 = file.NextLE<int32_t>();\r\n\tobject._oVar2 = file.NextLE<int32_t>();\r\n\tobject._oVar3 = file.NextLE<int32_t>();\r\n\tobject._oVar4 = file.NextLE<int32_t>();\r\n\tobject._oVar5 = file.NextLE<int32_t>();\r\n\tobject._oVar6 = file.NextLE<uint32_t>();\r\n\tobject.bookMessage = static_cast<_speech_id>(file.NextLE<int32_t>());\r\n\tobject._oVar8 = file.NextLE<int32_t>();\r\n}\r\n\r\nvoid LoadItem(LoadHelper &file, Item &item)\r\n{\r\n\tLoadAndValidateItemData(file, item);\r\n\tGetItemFrm(item);\r\n}\r\n\r\nvoid LoadPremium(LoadHelper &file, int i)\r\n{\r\n\tLoadAndValidateItemData(file, PremiumItems[i]);\r\n}\r\n\r\nvoid LoadQuest(LoadHelper *file, int i)\r\n{\r\n\tauto &quest = Quests[i];\r\n\r\n\tquest._qlevel = file->NextLE<uint8_t>();\r\n\tfile->Skip<uint8_t>(); // _qtype, identical to _qidx\r\n\tquest._qactive = static_cast<quest_state>(file->NextLE<uint8_t>());\r\n\tquest._qlvltype = static_cast<dungeon_type>(file->NextLE<uint8_t>());\r\n\tquest.position.x = file->NextLE<int32_t>();\r\n\tquest.position.y = file->NextLE<int32_t>();\r\n\tquest._qslvl = static_cast<_setlevels>(file->NextLE<uint8_t>());\r\n\tquest._qidx = static_cast<quest_id>(file->NextLE<uint8_t>());\r\n\tif (gbIsHellfireSaveGame) {\r\n\t\tfile->Skip(2); // Alignment\r\n\t\tquest._qmsg = static_cast<_speech_id>(file->NextLE<int32_t>());\r\n\t} else {\r\n\t\tquest._qmsg = static_cast<_speech_id>(file->NextLE<uint8_t>());\r\n\t}\r\n\tquest._qvar1 = file->NextLE<uint8_t>();\r\n\tquest._qvar2 = file->NextLE<uint8_t>();\r\n\tfile->Skip(2); // Alignment\r\n\tif (!gbIsHellfireSaveGame)\r\n\t\tfile->Skip(1); // Alignment\r\n\tquest._qlog = file->NextBool32();\r\n\r\n\tReturnLvlPosition.x = file->NextBE<int32_t>();\r\n\tReturnLvlPosition.y = file->NextBE<int32_t>();\r\n\tReturnLevel = file->NextBE<int32_t>();\r\n\tReturnLevelType = static_cast<dungeon_type>(file->NextBE<int32_t>());\r\n\tfile->Skip(sizeof(int32_t)); // Skip DoomQuestState\r\n}\r\n\r\nvoid LoadLighting(LoadHelper *file, Light *pLight)\r\n{\r\n\tpLight->position.tile.x = file->NextLE<int32_t>();\r\n\tpLight->position.tile.y = file->NextLE<int32_t>();\r\n\tpLight->radius = file->NextLE<int32_t>();\r\n\tfile->Skip<int32_t>(); // _lid\r\n\tpLight->isInvalid = file->NextBool32();\r\n\tpLight->hasChanged = file->NextBool32();\r\n\tfile->Skip(4); // Unused\r\n\tpLight->position.old.x = file->NextLE<int32_t>();\r\n\tpLight->position.old.y = file->NextLE<int32_t>();\r\n\tpLight->oldRadius = file->NextLE<int32_t>();\r\n\tpLight->position.offset.deltaX = file->NextLE<int32_t>();\r\n\tpLight->position.offset.deltaY = file->NextLE<int32_t>();\r\n\tfile->Skip<uint32_t>(); // _lflags\r\n}\r\n\r\nvoid LoadPortal(LoadHelper *file, int i)\r\n{\r\n\tPortal *pPortal = &Portals[i];\r\n\r\n\tpPortal->open = file->NextBool32();\r\n\tpPortal->position.x = file->NextLE<int32_t>();\r\n\tpPortal->position.y = file->NextLE<int32_t>();\r\n\tpPortal->level = file->NextLE<int32_t>();\r\n\tpPortal->ltype = static_cast<dungeon_type>(file->NextLE<int32_t>());\r\n\tpPortal->setlvl = file->NextBool32();\r\n\tif (!pPortal->setlvl)\r\n\t\tpPortal->ltype = GetLevelType(pPortal->level);\r\n}\r\n\r\nvoid GetLevelNames(std::string_view prefix, char *out)\r\n{\r\n\tchar suf;\r\n\tuint8_t num;\r\n\tif (setlevel) {\r\n\t\tsuf = 's';\r\n\t\tnum = static_cast<uint8_t>(setlvlnum);\r\n\t} else {\r\n\t\tsuf = 'l';\r\n\t\tnum = currlevel;\r\n\t}\r\n\t*BufCopy(out, prefix, std::string_view(&suf, 1), LeftPad(num, 2, '0')) = '\\0';\r\n}\r\n\r\nvoid GetTempLevelNames(char *szTemp)\r\n{\r\n\treturn GetLevelNames(\"temp\", szTemp);\r\n}\r\n\r\nvoid GetPermLevelNames(char *szPerm)\r\n{\r\n\treturn GetLevelNames(\"perm\", szPerm);\r\n}\r\n\r\nbool LevelFileExists(SaveWriter &archive)\r\n{\r\n\tchar szName[MaxMpqPathSize];\r\n\r\n\tGetTempLevelNames(szName);\r\n\tif (archive.HasFile(szName))\r\n\t\treturn true;\r\n\r\n\tGetPermLevelNames(szName);\r\n\treturn archive.HasFile(szName);\r\n}\r\n\r\nvoid LoadMatchingItems(LoadHelper &file, const Player &player, const int n, Item *pItem)\r\n{\r\n\tItem heroItem;\r\n\r\n\tfor (int i = 0; i < n; i++) {\r\n\t\tItem &unpackedItem = pItem[i];\r\n\t\tconst bool success = LoadItemData(file, heroItem);\r\n\t\tif (!success) {\r\n\t\t\theroItem.clear();\r\n\t\t\tunpackedItem = Item();\r\n\t\t}\r\n\t\tif (unpackedItem.isEmpty() || heroItem.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tif (unpackedItem._iSeed != heroItem._iSeed)\r\n\t\t\tcontinue;\r\n\t\tif (heroItem.IDidx == IDI_EAR)\r\n\t\t\tcontinue;\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\t// Ensure that the unpacked item was regenerated using the appropriate\r\n\t\t\t// game's item generation logic before attempting to use it for validation\r\n\t\t\tif ((heroItem.dwBuff & CF_HELLFIRE) != (unpackedItem.dwBuff & CF_HELLFIRE)) {\r\n\t\t\t\tunpackedItem = {};\r\n\t\t\t\tRecreateItem(player, unpackedItem, heroItem.IDidx, heroItem._iCreateInfo, heroItem._iSeed, heroItem._ivalue, heroItem.dwBuff);\r\n\t\t\t\tunpackedItem._iIdentified = heroItem._iIdentified;\r\n\t\t\t\tunpackedItem._iMaxDur = heroItem._iMaxDur;\r\n\t\t\t\tunpackedItem._iDurability = ClampDurability(unpackedItem, heroItem._iDurability);\r\n\t\t\t\tunpackedItem._iMaxCharges = std::clamp<int>(heroItem._iMaxCharges, 0, unpackedItem._iMaxCharges);\r\n\t\t\t\tunpackedItem._iCharges = std::clamp<int>(heroItem._iCharges, 0, unpackedItem._iMaxCharges);\r\n\t\t\t}\r\n\t\t\tif (gbIsHellfire) {\r\n\t\t\t\tunpackedItem._iPLToHit = ClampToHit(unpackedItem, heroItem._iPLToHit); // Oil of Accuracy\r\n\t\t\t\tunpackedItem._iMaxDam = ClampMaxDam(unpackedItem, heroItem._iMaxDam);  // Oil of Sharpness\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tunpackedItem = heroItem;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Loads items on the current dungeon floor\r\n * @param file interface to the save file\r\n * @param savedItemCount how many items to read from the save file\r\n */\r\nvoid LoadDroppedItems(LoadHelper &file, size_t savedItemCount)\r\n{\r\n\t// Skip loading ActiveItems and AvailableItems, the indices are initialised below based on the number of valid items\r\n\tfile.Skip<uint8_t>(MAXITEMS * 2);\r\n\r\n\t// Reset ActiveItems, the Items array will be populated from the start\r\n\tstd::iota(ActiveItems, ActiveItems + MAXITEMS, uint8_t { 0 });\r\n\tActiveItemCount = 0;\r\n\t// Clear dItem so we can populate valid drop locations\r\n\tmemset(dItem, 0, sizeof(dItem));\r\n\r\n\tfor (size_t i = 0; i < savedItemCount; i++) {\r\n\t\tItem &item = Items[ActiveItemCount];\r\n\t\tLoadItem(file, item);\r\n\r\n\t\tif (!item.isEmpty()) {\r\n\t\t\t// Loaded a valid item\r\n\t\t\tActiveItemCount++;\r\n\t\t\t// populate its location in the lookup table with the offset in the Items array + 1 (so 0 can be used for \"no item\")\r\n\t\t\tdItem[item.position.x][item.position.y] = ActiveItemCount;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint getHellfireLevelType(int type)\r\n{\r\n\tif (type == DTYPE_CRYPT)\r\n\t\treturn DTYPE_CATHEDRAL;\r\n\r\n\tif (type == DTYPE_NEST)\r\n\t\treturn DTYPE_CAVES;\r\n\r\n\treturn type;\r\n}\r\n\r\nvoid SaveItem(SaveHelper &file, const Item &item)\r\n{\r\n\tint32_t idx = item.IDidx != IDI_NONE ? AllItemsList[item.IDidx].iMappingId : -1;\r\n\tif (!gbIsHellfire && idx < IDI_NUM_DEFAULT_ITEMS)\r\n\t\tidx = RemapItemIdxToDiablo(static_cast<_item_indexes>(idx));\r\n\tif (gbIsSpawn && idx < IDI_NUM_DEFAULT_ITEMS)\r\n\t\tidx = RemapItemIdxToSpawn(static_cast<_item_indexes>(idx));\r\n\tItemType iType = item._itype;\r\n\tif (idx == -1) {\r\n\t\tidx = _item_indexes::IDI_GOLD;\r\n\t\tiType = ItemType::None;\r\n\t}\r\n\r\n\tfile.WriteLE<uint32_t>(item._iSeed);\r\n\tfile.WriteLE<int16_t>(item._iCreateInfo);\r\n\tfile.Skip(2); // Alignment\r\n\tfile.WriteLE<int32_t>(static_cast<int32_t>(iType));\r\n\tfile.WriteLE<int32_t>(item.position.x);\r\n\tfile.WriteLE<int32_t>(item.position.y);\r\n\tfile.WriteLE<uint32_t>(item._iAnimFlag ? 1 : 0);\r\n\tfile.Skip(4); // Skip pointer _iAnimData\r\n\tfile.WriteLE<int32_t>(item.AnimInfo.numberOfFrames);\r\n\tfile.WriteLE<int32_t>(item.AnimInfo.currentFrame + 1);\r\n\t// write _iAnimWidth for vanilla compatibility\r\n\tfile.WriteLE<int32_t>(ItemAnimWidth);\r\n\t// write _iAnimWidth2 for vanilla compatibility\r\n\tfile.WriteLE<int32_t>(CalculateSpriteTileCenterX(ItemAnimWidth));\r\n\tfile.Skip<uint32_t>(); // _delFlag, unused since 1.02\r\n\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(item.selectionRegion));\r\n\tfile.Skip(3); // Alignment\r\n\tfile.WriteLE<uint32_t>(item._iPostDraw ? 1 : 0);\r\n\tfile.WriteLE<uint32_t>(item._iIdentified ? 1 : 0);\r\n\tfile.WriteLE<int8_t>(item._iMagical);\r\n\tfile.WriteBytes(item._iName, ItemNameLength);\r\n\tfile.WriteBytes(item._iIName, ItemNameLength);\r\n\tfile.WriteLE<int8_t>(item._iLoc);\r\n\tfile.WriteLE<uint8_t>(item._iClass);\r\n\tfile.Skip(1); // Alignment\r\n\tfile.WriteLE<int32_t>(item._iCurs);\r\n\tfile.WriteLE<int32_t>(item._ivalue);\r\n\tfile.WriteLE<int32_t>(item._iIvalue);\r\n\tfile.WriteLE<int32_t>(item._iMinDam);\r\n\tfile.WriteLE<int32_t>(item._iMaxDam);\r\n\tfile.WriteLE<int32_t>(item._iAC);\r\n\tfile.WriteLE<uint32_t>(static_cast<uint32_t>(item._iFlags));\r\n\tfile.WriteLE<int32_t>(item._iMiscId);\r\n\tfile.WriteLE<int32_t>(static_cast<int8_t>(item._iSpell));\r\n\tfile.WriteLE<int32_t>(item._iCharges);\r\n\tfile.WriteLE<int32_t>(item._iMaxCharges);\r\n\tfile.WriteLE<int32_t>(item._iDurability);\r\n\tfile.WriteLE<int32_t>(item._iMaxDur);\r\n\tfile.WriteLE<int32_t>(item._iPLDam);\r\n\tfile.WriteLE<int32_t>(item._iPLToHit);\r\n\tfile.WriteLE<int32_t>(item._iPLAC);\r\n\tfile.WriteLE<int32_t>(item._iPLStr);\r\n\tfile.WriteLE<int32_t>(item._iPLMag);\r\n\tfile.WriteLE<int32_t>(item._iPLDex);\r\n\tfile.WriteLE<int32_t>(item._iPLVit);\r\n\tfile.WriteLE<int32_t>(item._iPLFR);\r\n\tfile.WriteLE<int32_t>(item._iPLLR);\r\n\tfile.WriteLE<int32_t>(item._iPLMR);\r\n\tfile.WriteLE<int32_t>(item._iPLMana);\r\n\tfile.WriteLE<int32_t>(item._iPLHP);\r\n\tfile.WriteLE<int32_t>(item._iPLDamMod);\r\n\tfile.WriteLE<int32_t>(item._iPLGetHit);\r\n\tfile.WriteLE<int32_t>(item._iPLLight);\r\n\tfile.WriteLE<int8_t>(item._iSplLvlAdd);\r\n\tfile.WriteLE<int8_t>(item._iRequest ? 1 : 0);\r\n\tfile.Skip(2); // Alignment\r\n\tfile.WriteLE<int32_t>(UniqueItems[item._iUid].mappingId);\r\n\tfile.WriteLE<int32_t>(item._iFMinDam);\r\n\tfile.WriteLE<int32_t>(item._iFMaxDam);\r\n\tfile.WriteLE<int32_t>(item._iLMinDam);\r\n\tfile.WriteLE<int32_t>(item._iLMaxDam);\r\n\tfile.WriteLE<int32_t>(item._iPLEnAc);\r\n\tfile.WriteLE<int8_t>(item._iPrePower);\r\n\tfile.WriteLE<int8_t>(item._iSufPower);\r\n\tfile.Skip(2); // Alignment\r\n\tfile.WriteLE<int32_t>(item._iVAdd1);\r\n\tfile.WriteLE<int32_t>(item._iVMult1);\r\n\tfile.WriteLE<int32_t>(item._iVAdd2);\r\n\tfile.WriteLE<int32_t>(item._iVMult2);\r\n\tfile.WriteLE<int8_t>(item._iMinStr);\r\n\tfile.WriteLE<uint8_t>(item._iMinMag);\r\n\tfile.WriteLE<int8_t>(item._iMinDex);\r\n\tfile.Skip(1); // Alignment\r\n\tfile.WriteLE<uint32_t>(item._iStatFlag ? 1 : 0);\r\n\tfile.WriteLE<int32_t>(idx);\r\n\tfile.WriteLE<uint32_t>(item.dwBuff);\r\n\tif (gbIsHellfire)\r\n\t\tfile.WriteLE<uint32_t>(static_cast<uint32_t>(item._iDamAcFlags));\r\n}\r\n\r\nvoid SavePlayer(SaveHelper &file, const Player &player)\r\n{\r\n\tfile.WriteLE<int32_t>(player._pmode);\r\n\tfor (size_t i = 0; i < PlayerWalkPathSizeForSaveGame; ++i) {\r\n\t\tfile.WriteLE<int8_t>(player.walkpath[i]);\r\n\t}\r\n\tfile.WriteLE<uint8_t>(player.plractive ? 1 : 0);\r\n\tfile.Skip(2); // Alignment\r\n\tfile.WriteLE<int32_t>(player.destAction);\r\n\tfile.WriteLE<int32_t>(player.destParam1);\r\n\tfile.WriteLE<int32_t>(player.destParam2);\r\n\tfile.WriteLE<int32_t>(static_cast<int32_t>(player.destParam3));\r\n\tfile.WriteLE<int32_t>(player.destParam4);\r\n\tfile.WriteLE<uint32_t>(player.plrlevel);\r\n\tfile.WriteLE<int32_t>(player.position.tile.x);\r\n\tfile.WriteLE<int32_t>(player.position.tile.y);\r\n\tfile.WriteLE<int32_t>(player.position.future.x);\r\n\tfile.WriteLE<int32_t>(player.position.future.y);\r\n\r\n\t// For backwards compatibility\r\n\tconst Point target = player.GetTargetPosition();\r\n\tfile.WriteLE<int32_t>(target.x);\r\n\tfile.WriteLE<int32_t>(target.y);\r\n\r\n\tfile.WriteLE<int32_t>(player.position.last.x);\r\n\tfile.WriteLE<int32_t>(player.position.last.y);\r\n\tfile.WriteLE<int32_t>(player.position.old.x);\r\n\tfile.WriteLE<int32_t>(player.position.old.y);\r\n\tDisplacementOf<int16_t> offset = {};\r\n\tDisplacementOf<int16_t> offset2 = {};\r\n\tDisplacementOf<int16_t> velocity = {};\r\n\tif (player.isWalking()) {\r\n\t\toffset = player.position.CalculateWalkingOffset(player._pdir, player.AnimInfo);\r\n\t\toffset2 = player.position.CalculateWalkingOffsetShifted8(player._pdir, player.AnimInfo);\r\n\t\tvelocity = player.position.GetWalkingVelocityShifted8(player._pdir, player.AnimInfo);\r\n\t}\r\n\tfile.WriteLE<int32_t>(offset.deltaX);\r\n\tfile.WriteLE<int32_t>(offset.deltaY);\r\n\tfile.WriteLE<int32_t>(velocity.deltaX);\r\n\tfile.WriteLE<int32_t>(velocity.deltaY);\r\n\tfile.WriteLE<int32_t>(static_cast<int32_t>(player._pdir));\r\n\tfile.Skip(4); // Unused\r\n\tfile.WriteLE<uint32_t>(player._pgfxnum);\r\n\tfile.Skip(4); // Skip pointer _pAnimData\r\n\tfile.WriteLE<int32_t>(std::max(0, player.AnimInfo.ticksPerFrame - 1));\r\n\tfile.WriteLE<int32_t>(player.AnimInfo.tickCounterOfCurrentFrame);\r\n\tfile.WriteLE<int32_t>(player.AnimInfo.numberOfFrames);\r\n\tfile.WriteLE<int32_t>(player.AnimInfo.currentFrame + 1);\r\n\t// write _pAnimWidth for vanilla compatibility\r\n\tconst int animWidth = player.getSpriteWidth();\r\n\tfile.WriteLE<int32_t>(animWidth);\r\n\t// write _pAnimWidth2 for vanilla compatibility\r\n\tfile.WriteLE<int32_t>(CalculateSpriteTileCenterX(animWidth));\r\n\tfile.Skip<uint32_t>(); // Skip _peflag\r\n\tfile.WriteLE<int32_t>(player.lightId);\r\n\tfile.WriteLE<int32_t>(1); // _pvid\r\n\r\n\tfile.WriteLE<int32_t>(static_cast<int8_t>(player.queuedSpell.spellId));\r\n\tfile.WriteLE<int8_t>(static_cast<int8_t>(player.queuedSpell.spellType));\r\n\tfile.WriteLE<int8_t>(player.queuedSpell.spellFrom);\r\n\tfile.Skip(2); // Alignment\r\n\tfile.WriteLE<int32_t>(static_cast<int8_t>(player.inventorySpell));\r\n\tfile.Skip<int8_t>(); // Skip _pTSplType\r\n\tfile.Skip(3);        // Alignment\r\n\tfile.WriteLE<int32_t>(static_cast<int8_t>(player._pRSpell));\r\n\tfile.WriteLE<int8_t>(static_cast<uint8_t>(player._pRSplType));\r\n\tfile.Skip(3); // Alignment\r\n\tfile.WriteLE<int32_t>(static_cast<int8_t>(player._pSBkSpell));\r\n\tfile.Skip<int8_t>(); // Skip _pSBkSplType\r\n\r\n\tfor (const uint8_t spellLevel : player._pSplLvl)\r\n\t\tfile.WriteLE<uint8_t>(spellLevel);\r\n\r\n\tfile.Skip(7); // Alignment\r\n\tfile.WriteLE<uint64_t>(player._pMemSpells);\r\n\tfile.WriteLE<uint64_t>(player._pAblSpells);\r\n\tfile.WriteLE<uint64_t>(player._pScrlSpells);\r\n\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(player._pSpellFlags));\r\n\tfile.Skip(3); // Alignment\r\n\r\n\t// Extra hotkeys: to keep single player save compatibility, write only 4 hotkeys here, rely on SaveHotkeys for the rest\r\n\tfor (size_t i = 0; i < 4; i++) {\r\n\t\tfile.WriteLE<int32_t>(static_cast<int8_t>(player._pSplHotKey[i]));\r\n\t}\r\n\tfor (size_t i = 0; i < 4; i++) {\r\n\t\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(player._pSplTHotKey[i]));\r\n\t}\r\n\r\n\tfile.WriteLE<int32_t>(player.UsesRangedWeapon() ? 1 : 0);\r\n\tfile.WriteLE<uint8_t>(player._pBlockFlag ? 1 : 0);\r\n\tfile.WriteLE<uint8_t>(player._pInvincible ? 1 : 0);\r\n\tfile.WriteLE<int8_t>(player._pLightRad);\r\n\tfile.WriteLE<uint8_t>(player._pLvlChanging ? 1 : 0);\r\n\r\n\tfile.WriteBytes(player._pName, PlayerNameLength);\r\n\tfile.WriteLE<int8_t>(static_cast<int8_t>(player._pClass));\r\n\tfile.Skip(3); // Alignment\r\n\tfile.WriteLE<int32_t>(player._pStrength);\r\n\tfile.WriteLE<int32_t>(player._pBaseStr);\r\n\tfile.WriteLE<int32_t>(player._pMagic);\r\n\tfile.WriteLE<int32_t>(player._pBaseMag);\r\n\tfile.WriteLE<int32_t>(player._pDexterity);\r\n\tfile.WriteLE<int32_t>(player._pBaseDex);\r\n\tfile.WriteLE<int32_t>(player._pVitality);\r\n\tfile.WriteLE<int32_t>(player._pBaseVit);\r\n\tfile.WriteLE<int32_t>(player._pStatPts);\r\n\tfile.WriteLE<int32_t>(player._pDamageMod);\r\n\r\n\tfile.WriteLE<int32_t>(player.getBaseToBlock()); // set _pBaseToBlk for backwards compatibility\r\n\tfile.WriteLE<int32_t>(player._pHPBase);\r\n\tfile.WriteLE<int32_t>(player._pMaxHPBase);\r\n\tfile.WriteLE<int32_t>(player._pHitPoints);\r\n\tfile.WriteLE<int32_t>(player._pMaxHP);\r\n\tfile.Skip<int32_t>(); // Skip _pHPPer\r\n\tfile.WriteLE<int32_t>(player._pManaBase);\r\n\tfile.WriteLE<int32_t>(player._pMaxManaBase);\r\n\tfile.WriteLE<int32_t>(player._pMana);\r\n\tfile.WriteLE<int32_t>(player._pMaxMana);\r\n\tfile.Skip<int32_t>(); // Skip _pManaPer\r\n\tfile.WriteLE<uint8_t>(player.getCharacterLevel());\r\n\tfile.Skip<uint8_t>(); // skip _pMaxLevel, this value is uninitialised in most cases in Diablo/Hellfire so there's no point setting it.\r\n\tfile.Skip(2);         // Alignment\r\n\tfile.WriteLE<uint32_t>(player._pExperience);\r\n\tfile.Skip<uint32_t>();                                       // Skip _pMaxExp\r\n\tfile.WriteLE<uint32_t>(player.getNextExperienceThreshold()); // set _pNextExper for backwards compatibility\r\n\tfile.WriteLE<int8_t>(player._pArmorClass);\r\n\tfile.WriteLE<int8_t>(player._pMagResist);\r\n\tfile.WriteLE<int8_t>(player._pFireResist);\r\n\tfile.WriteLE<int8_t>(player._pLghtResist);\r\n\tfile.WriteLE<int32_t>(player._pGold);\r\n\tfile.WriteLE<uint32_t>(player._pInfraFlag ? 1 : 0);\r\n\r\n\tint32_t tempPositionX = player.position.temp.x;\r\n\tint32_t tempPositionY = player.position.temp.y;\r\n\tif (player._pmode == PM_WALK_NORTHWARDS) {\r\n\t\t// For backwards compatibility, save this as an offset\r\n\t\ttempPositionX -= player.position.tile.x;\r\n\t\ttempPositionY -= player.position.tile.y;\r\n\t}\r\n\tfile.WriteLE<int32_t>(tempPositionX);\r\n\tfile.WriteLE<int32_t>(tempPositionY);\r\n\r\n\tfile.WriteLE<int32_t>(static_cast<int32_t>(player.tempDirection));\r\n\tfile.WriteLE<int32_t>(player.queuedSpell.spellLevel);\r\n\tfile.Skip<int32_t>(); // skip _pVar5, was used for storing position of a tile which should have its HorizontalMovingPlayer flag removed after walking\r\n\tfile.WriteLE<int32_t>(offset2.deltaX);\r\n\tfile.WriteLE<int32_t>(offset2.deltaY);\r\n\tfile.Skip<int32_t>(); // Skip _pVar8\r\n\tfor (uint8_t i = 0; i < giNumberOfLevels; i++)\r\n\t\tfile.WriteLE<uint8_t>(player._pLvlVisited[i] ? 1 : 0);\r\n\tfor (uint8_t i = 0; i < giNumberOfLevels; i++)\r\n\t\tfile.WriteLE<uint8_t>(player._pSLvlVisited[i] ? 1 : 0); // only 10 used\r\n\r\n\tfile.Skip(2); // Alignment\r\n\r\n\tfile.Skip<int32_t>();   // Skip _pGFXLoad\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pNAnim\r\n\tfile.WriteLE<int32_t>(player._pNFrames);\r\n\tfile.Skip<uint32_t>();  // Skip _pNWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pWAnim\r\n\tfile.WriteLE<int32_t>(player._pWFrames);\r\n\tfile.Skip<uint32_t>();  // Skip _pWWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pAAnim\r\n\tfile.WriteLE<int32_t>(player._pAFrames);\r\n\tfile.Skip<uint32_t>(); // Skip _pAWidth\r\n\tfile.WriteLE<int32_t>(player._pAFNum);\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pLAnim\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pFAnim\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pTAnim\r\n\tfile.WriteLE<int32_t>(player._pSFrames);\r\n\tfile.Skip<uint32_t>(); // Skip _pSWidth\r\n\tfile.WriteLE<int32_t>(player._pSFNum);\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pHAnim\r\n\tfile.WriteLE<int32_t>(player._pHFrames);\r\n\tfile.Skip<uint32_t>();  // Skip _pHWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pDAnim\r\n\tfile.WriteLE<int32_t>(player._pDFrames);\r\n\tfile.Skip<uint32_t>();  // Skip _pDWidth\r\n\tfile.Skip<uint32_t>(8); // Skip pointers _pBAnim\r\n\tfile.WriteLE<int32_t>(player._pBFrames);\r\n\tfile.Skip<uint32_t>(); // Skip _pBWidth\r\n\r\n\tfor (const Item &item : player.InvBody)\r\n\t\tSaveItem(file, item);\r\n\r\n\tfor (const Item &item : player.InvList)\r\n\t\tSaveItem(file, item);\r\n\r\n\tfile.WriteLE<int32_t>(player._pNumInv);\r\n\r\n\tfor (const int8_t cell : player.InvGrid)\r\n\t\tfile.WriteLE<int8_t>(cell);\r\n\r\n\tfor (const Item &item : player.SpdList)\r\n\t\tSaveItem(file, item);\r\n\r\n\tSaveItem(file, player.HoldItem);\r\n\r\n\tfile.WriteLE<int32_t>(player._pIMinDam);\r\n\tfile.WriteLE<int32_t>(player._pIMaxDam);\r\n\tfile.WriteLE<int32_t>(player._pIAC);\r\n\tfile.WriteLE<int32_t>(player._pIBonusDam);\r\n\tfile.WriteLE<int32_t>(player._pIBonusToHit);\r\n\tfile.WriteLE<int32_t>(player._pIBonusAC);\r\n\tfile.WriteLE<int32_t>(player._pIBonusDamMod);\r\n\tfile.Skip(4); // Alignment\r\n\r\n\tfile.WriteLE<uint64_t>(player._pISpells);\r\n\tfile.WriteLE<int32_t>(static_cast<int32_t>(player._pIFlags));\r\n\tfile.WriteLE<int32_t>(player._pIGetHit);\r\n\r\n\tfile.WriteLE<int8_t>(player._pISplLvlAdd);\r\n\tfile.Skip<uint8_t>(); // Skip _pISplCost\r\n\tfile.Skip(2);         // Alignment\r\n\tfile.Skip<int32_t>(); // _pISplDur\r\n\tfile.WriteLE<int32_t>(player._pIEnAc);\r\n\tfile.WriteLE<int32_t>(player._pIFMinDam);\r\n\tfile.WriteLE<int32_t>(player._pIFMaxDam);\r\n\tfile.WriteLE<int32_t>(player._pILMinDam);\r\n\tfile.WriteLE<int32_t>(player._pILMaxDam);\r\n\tfile.WriteLE<int32_t>(player._pOilType);\r\n\tfile.WriteLE<uint8_t>(player.pTownWarps);\r\n\tfile.WriteLE<uint8_t>(player.pDungMsgs);\r\n\tfile.WriteLE<uint8_t>(player.pLvlLoad);\r\n\tif (gbIsHellfire)\r\n\t\tfile.WriteLE<uint8_t>(player.pDungMsgs2);\r\n\telse\r\n\t\tfile.WriteLE<uint8_t>(0);\r\n\tfile.WriteLE<uint8_t>(player.pManaShield ? 1 : 0);\r\n\tfile.WriteLE<uint8_t>(player.pOriginalCathedral ? 1 : 0);\r\n\tfile.Skip(2); // Available bytes\r\n\tfile.WriteLE<uint16_t>(player.wReflections);\r\n\tfile.Skip(14); // Available bytes\r\n\r\n\tfile.WriteLE<uint32_t>(player.pDiabloKillLevel);\r\n\tfile.WriteLE<uint32_t>(sgGameInitInfo.nDifficulty);\r\n\tfile.WriteLE<uint32_t>(static_cast<uint32_t>(player.pDamAcFlags));\r\n\tfile.Skip(20); // Available bytes\r\n\r\n\t// Omit pointer _pNData\r\n\t// Omit pointer _pWData\r\n\t// Omit pointer _pAData\r\n\t// Omit pointer _pLData\r\n\t// Omit pointer _pFData\r\n\t// Omit pointer  _pTData\r\n\t// Omit pointer _pHData\r\n\t// Omit pointer _pDData\r\n\t// Omit pointer _pBData\r\n\t// Omit pointer pReserved\r\n}\r\n\r\nvoid SaveMonster(SaveHelper *file, Monster &monster, MonsterConversionData *monsterConversionData = nullptr)\r\n{\r\n\tfile->WriteLE<int32_t>(monster.levelType);\r\n\tfile->WriteLE<int32_t>(static_cast<int>(monster.mode));\r\n\tfile->WriteLE<uint8_t>(static_cast<uint8_t>(monster.goal));\r\n\tfile->Skip(3); // Alignment\r\n\tfile->WriteLE<int32_t>(monster.goalVar1);\r\n\tfile->WriteLE<int32_t>(monster.goalVar2);\r\n\tfile->WriteLE<int32_t>(monster.goalVar3);\r\n\tfile->Skip(4); // Unused\r\n\tfile->WriteLE<uint8_t>(monster.pathCount);\r\n\tfile->Skip(3); // Alignment\r\n\tfile->WriteLE<int32_t>(monster.position.tile.x);\r\n\tfile->WriteLE<int32_t>(monster.position.tile.y);\r\n\tfile->WriteLE<int32_t>(monster.position.future.x);\r\n\tfile->WriteLE<int32_t>(monster.position.future.y);\r\n\tfile->WriteLE<int32_t>(monster.position.old.x);\r\n\tfile->WriteLE<int32_t>(monster.position.old.y);\r\n\tDisplacementOf<int16_t> offset = {};\r\n\tDisplacementOf<int16_t> offset2 = {};\r\n\tDisplacementOf<int16_t> velocity = {};\r\n\tif (monster.isWalking()) {\r\n\t\toffset = monster.position.CalculateWalkingOffset(monster.direction, monster.animInfo);\r\n\t\toffset2 = monster.position.CalculateWalkingOffsetShifted4(monster.direction, monster.animInfo);\r\n\t\tvelocity = monster.position.GetWalkingVelocityShifted4(monster.direction, monster.animInfo);\r\n\t}\r\n\tfile->WriteLE<int32_t>(offset.deltaX);\r\n\tfile->WriteLE<int32_t>(offset.deltaY);\r\n\tfile->WriteLE<int32_t>(velocity.deltaX);\r\n\tfile->WriteLE<int32_t>(velocity.deltaY);\r\n\tfile->WriteLE<int32_t>(static_cast<int32_t>(monster.direction));\r\n\tfile->WriteLE<int32_t>(monster.enemy);\r\n\tfile->WriteLE<uint8_t>(monster.enemyPosition.x);\r\n\tfile->WriteLE<uint8_t>(monster.enemyPosition.y);\r\n\tfile->Skip(2); // Unused\r\n\r\n\tfile->Skip(4); // Skip pointer _mAnimData\r\n\tfile->WriteLE<int32_t>(monster.animInfo.ticksPerFrame);\r\n\tfile->WriteLE<int32_t>(monster.animInfo.tickCounterOfCurrentFrame);\r\n\tfile->WriteLE<int32_t>(monster.animInfo.numberOfFrames);\r\n\tfile->WriteLE<int32_t>(monster.animInfo.currentFrame + 1);\r\n\tfile->Skip<uint32_t>(); // Skip _meflag\r\n\tfile->WriteLE<uint32_t>(monster.isInvalid ? 1 : 0);\r\n\tfile->WriteLE<int32_t>(monster.var1);\r\n\tfile->WriteLE<int32_t>(monster.var2);\r\n\tfile->WriteLE<int32_t>(monster.var3);\r\n\tfile->WriteLE<int32_t>(monster.position.temp.x);\r\n\tfile->WriteLE<int32_t>(monster.position.temp.y);\r\n\tfile->WriteLE<int32_t>(offset2.deltaX);\r\n\tfile->WriteLE<int32_t>(offset2.deltaY);\r\n\tfile->Skip<int32_t>(); // Skip _mVar8\r\n\tfile->WriteLE<int32_t>(monster.maxHitPoints);\r\n\tfile->WriteLE<int32_t>(monster.hitPoints);\r\n\r\n\tfile->WriteLE<uint8_t>(static_cast<int8_t>(monster.ai));\r\n\tfile->WriteLE<uint8_t>(monster.intelligence);\r\n\tfile->Skip(2); // Alignment\r\n\tfile->WriteLE<uint32_t>(monster.flags);\r\n\tfile->WriteLE<uint8_t>(monster.activeForTicks);\r\n\tfile->Skip(3); // Alignment\r\n\tfile->Skip(4); // Unused\r\n\tfile->WriteLE<int32_t>(monster.position.last.x);\r\n\tfile->WriteLE<int32_t>(monster.position.last.y);\r\n\tfile->WriteLE<uint32_t>(monster.rndItemSeed);\r\n\tfile->WriteLE<uint32_t>(monster.aiSeed);\r\n\tfile->Skip(4); // Unused\r\n\r\n\tfile->WriteLE<uint8_t>(static_cast<uint8_t>(monster.uniqueType) + 1);\r\n\tfile->WriteLE<uint8_t>(monster.uniqTrans);\r\n\tfile->WriteLE<int8_t>(monster.corpseId);\r\n\r\n\tfile->WriteLE<int8_t>(monster.whoHit);\r\n\tif (monsterConversionData != nullptr)\r\n\t\tfile->WriteLE<int8_t>(monsterConversionData->monsterLevel);\r\n\telse\r\n\t\tfile->WriteLE<int8_t>(static_cast<int8_t>(monster.level(sgGameInitInfo.nDifficulty)));\r\n\tfile->Skip(1); // Alignment\r\n\tif (monsterConversionData != nullptr)\r\n\t\tfile->WriteLE<uint16_t>(monsterConversionData->experience);\r\n\telse\r\n\t\tfile->WriteLE<uint16_t>(static_cast<uint16_t>(std::min<unsigned>(std::numeric_limits<uint16_t>::max(), monster.exp(sgGameInitInfo.nDifficulty))));\r\n\r\n\tif (monsterConversionData != nullptr)\r\n\t\tfile->WriteLE<uint8_t>(monsterConversionData->toHit);\r\n\telse\r\n\t\tfile->WriteLE<uint8_t>(static_cast<uint8_t>(std::min<uint16_t>(monster.toHit(sgGameInitInfo.nDifficulty), std::numeric_limits<uint8_t>::max()))); // For backwards compatibility\r\n\tfile->WriteLE<uint8_t>(monster.minDamage);\r\n\tfile->WriteLE<uint8_t>(monster.maxDamage);\r\n\tif (monsterConversionData != nullptr)\r\n\t\tfile->WriteLE<uint8_t>(monsterConversionData->toHitSpecial);\r\n\telse\r\n\t\tfile->WriteLE<uint8_t>(static_cast<uint8_t>(std::min<uint16_t>(monster.toHitSpecial(sgGameInitInfo.nDifficulty), std::numeric_limits<uint8_t>::max()))); // For backwards compatibility\r\n\tfile->WriteLE<uint8_t>(monster.minDamageSpecial);\r\n\tfile->WriteLE<uint8_t>(monster.maxDamageSpecial);\r\n\tfile->WriteLE<uint8_t>(monster.armorClass);\r\n\tfile->Skip(1); // Alignment\r\n\tfile->WriteLE<uint16_t>(monster.resistance);\r\n\tfile->Skip(2); // Alignment\r\n\r\n\tfile->WriteLE<int32_t>(monster.talkMsg == TEXT_NONE ? 0 : monster.talkMsg);       // Replicate original bad mapping of none for monsters\r\n\tfile->WriteLE<uint8_t>(monster.leader == Monster::NoLeader ? 0 : monster.leader); // Vanilla uses 0 as the default leader which corresponds to player 0s golem\r\n\tfile->WriteLE<uint8_t>(static_cast<std::uint8_t>(monster.leaderRelation));\r\n\tfile->WriteLE<uint8_t>(monster.packSize);\r\n\t// vanilla compatibility\r\n\tif (monster.lightId == NO_LIGHT)\r\n\t\tfile->WriteLE<int8_t>(0);\r\n\telse\r\n\t\tfile->WriteLE<int8_t>(monster.lightId);\r\n\r\n\t// Omit pointer name;\r\n}\r\n\r\nvoid SaveMissile(SaveHelper *file, const Missile &missile)\r\n{\r\n\tfile->WriteLE<int32_t>(static_cast<int8_t>(missile._mitype));\r\n\tfile->WriteLE<int32_t>(missile.position.tile.x);\r\n\tfile->WriteLE<int32_t>(missile.position.tile.y);\r\n\tfile->WriteLE<int32_t>(missile.position.offset.deltaX);\r\n\tfile->WriteLE<int32_t>(missile.position.offset.deltaY);\r\n\tfile->WriteLE<int32_t>(missile.position.velocity.deltaX);\r\n\tfile->WriteLE<int32_t>(missile.position.velocity.deltaY);\r\n\tfile->WriteLE<int32_t>(missile.position.start.x);\r\n\tfile->WriteLE<int32_t>(missile.position.start.y);\r\n\tfile->WriteLE<int32_t>(missile.position.traveled.deltaX);\r\n\tfile->WriteLE<int32_t>(missile.position.traveled.deltaY);\r\n\tfile->WriteLE<int32_t>(missile.getFrameGroupRaw());\r\n\tfile->WriteLE<int32_t>(missile._mispllvl);\r\n\tfile->WriteLE<uint32_t>(missile._miDelFlag ? 1 : 0);\r\n\tfile->WriteLE<uint8_t>(static_cast<uint8_t>(missile._miAnimType));\r\n\tfile->Skip(3); // Alignment\r\n\tfile->WriteLE<int32_t>(static_cast<int32_t>(missile._miAnimFlags));\r\n\tfile->Skip(4); // Skip pointer _miAnimData\r\n\tfile->WriteLE<int32_t>(missile._miAnimDelay);\r\n\tfile->WriteLE<int32_t>(missile._miAnimLen);\r\n\tfile->WriteLE<int32_t>(missile._miAnimWidth);\r\n\tfile->WriteLE<int32_t>(missile._miAnimWidth2);\r\n\tfile->WriteLE<int32_t>(missile._miAnimCnt);\r\n\tfile->WriteLE<int32_t>(missile._miAnimAdd);\r\n\tfile->WriteLE<int32_t>(missile._miAnimFrame);\r\n\tfile->WriteLE<uint32_t>(missile._miDrawFlag ? 1 : 0);\r\n\tfile->WriteLE<uint32_t>(missile._miLightFlag ? 1 : 0);\r\n\tfile->WriteLE<uint32_t>(missile._miPreFlag ? 1 : 0);\r\n\tfile->WriteLE<uint32_t>(missile._miUniqTrans);\r\n\tfile->WriteLE<int32_t>(missile.duration);\r\n\tfile->WriteLE<int32_t>(missile._misource);\r\n\tfile->WriteLE<int32_t>(missile._micaster);\r\n\tfile->WriteLE<int32_t>(missile._midam);\r\n\tfile->WriteLE<uint32_t>(missile._miHitFlag ? 1 : 0);\r\n\tfile->WriteLE<int32_t>(missile._midist);\r\n\tfile->WriteLE<int32_t>(missile._mlid);\r\n\tfile->WriteLE<int32_t>(missile._mirnd);\r\n\tfile->WriteLE<int32_t>(missile.var1);\r\n\tfile->WriteLE<int32_t>(missile.var2);\r\n\tfile->WriteLE<int32_t>(missile.var3);\r\n\tfile->WriteLE<int32_t>(missile.var4);\r\n\tfile->WriteLE<int32_t>(missile.var5);\r\n\tfile->WriteLE<int32_t>(missile.var6);\r\n\tfile->WriteLE<int32_t>(missile.var7);\r\n\tfile->WriteLE<uint32_t>(missile.limitReached ? 1 : 0);\r\n}\r\n\r\n_object_id ConvertToHellfireObject(_object_id type)\r\n{\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\tswitch (type) {\r\n\t\tcase OBJ_POD:\r\n\t\t\treturn OBJ_BARREL;\r\n\t\tcase OBJ_PODEX:\r\n\t\t\treturn OBJ_BARRELEX;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tswitch (type) {\r\n\t\tcase OBJ_URN:\r\n\t\t\treturn OBJ_BARREL;\r\n\t\tcase OBJ_URNEX:\r\n\t\t\treturn OBJ_BARRELEX;\r\n\t\tcase OBJ_L5BOOKS:\r\n\t\t\treturn OBJ_STORYBOOK;\r\n\t\tcase OBJ_L5CANDLE:\r\n\t\t\treturn OBJ_STORYCANDLE;\r\n\t\tcase OBJ_L5LDOOR:\r\n\t\t\treturn OBJ_L1LDOOR;\r\n\t\tcase OBJ_L5RDOOR:\r\n\t\t\treturn OBJ_L1RDOOR;\r\n\t\tcase OBJ_L5LEVER:\r\n\t\t\treturn OBJ_LEVER;\r\n\t\tcase OBJ_L5SARC:\r\n\t\t\treturn OBJ_SARC;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn type;\r\n}\r\n\r\nvoid SaveObject(SaveHelper &file, const Object &object)\r\n{\r\n\tfile.WriteLE<int32_t>(ConvertToHellfireObject(object._otype));\r\n\tfile.WriteLE<int32_t>(object.position.x);\r\n\tfile.WriteLE<int32_t>(object.position.y);\r\n\tfile.WriteLE<uint32_t>(object.applyLighting ? 1 : 0);\r\n\tfile.WriteLE<uint32_t>(object._oAnimFlag ? 1 : 0);\r\n\tfile.Skip(4); // Skip pointer _oAnimData\r\n\tfile.WriteLE<int32_t>(object._oAnimDelay);\r\n\tfile.WriteLE<int32_t>(object._oAnimCnt);\r\n\tfile.WriteLE<uint32_t>(object._oAnimLen);\r\n\tfile.WriteLE<uint32_t>(object._oAnimFrame);\r\n\tfile.WriteLE<int32_t>(object._oAnimWidth);\r\n\tfile.WriteLE<int32_t>(CalculateSpriteTileCenterX(static_cast<int>(object._oAnimWidth))); // Write _oAnimWidth2 for vanilla compatibility\r\n\tfile.WriteLE<uint32_t>(object._oDelFlag ? 1 : 0);\r\n\tfile.WriteLE<int8_t>(object._oBreak);\r\n\tfile.Skip(3); // Alignment\r\n\tfile.WriteLE<uint32_t>(object._oSolidFlag ? 1 : 0);\r\n\tfile.WriteLE<uint32_t>(object._oMissFlag ? 1 : 0);\r\n\r\n\tfile.WriteLE<int8_t>(static_cast<uint8_t>(object.selectionRegion));\r\n\tfile.Skip(3); // Alignment\r\n\tfile.WriteLE<uint32_t>(object._oPreFlag ? 1 : 0);\r\n\tfile.WriteLE<uint32_t>(object._oTrapFlag ? 1 : 0);\r\n\tfile.WriteLE<uint32_t>(object._oDoorFlag ? 1 : 0);\r\n\tfile.WriteLE<int32_t>(object._olid);\r\n\tfile.WriteLE<uint32_t>(object._oRndSeed);\r\n\r\n\t/* Make dynamic light sources unseen when saving level data for level change */\r\n\tint32_t var1 = object._oVar1;\r\n\tswitch (object._otype) {\r\n\tcase OBJ_L1LIGHT:\r\n\tcase OBJ_SKFIRE:\r\n\tcase OBJ_CANDLE1:\r\n\tcase OBJ_CANDLE2:\r\n\tcase OBJ_BOOKCANDLE:\r\n\tcase OBJ_STORYCANDLE:\r\n\tcase OBJ_L5CANDLE:\r\n\tcase OBJ_TORCHL:\r\n\tcase OBJ_TORCHR:\r\n\tcase OBJ_TORCHL2:\r\n\tcase OBJ_TORCHR2:\r\n\tcase OBJ_BCROSS:\r\n\tcase OBJ_TBCROSS:\r\n\t\tif (var1 != -1)\r\n\t\t\tvar1 = 0;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\tfile.WriteLE<int32_t>(var1);\r\n\tfile.WriteLE<int32_t>(object._oVar2);\r\n\tfile.WriteLE<int32_t>(object._oVar3);\r\n\tfile.WriteLE<int32_t>(object._oVar4);\r\n\tfile.WriteLE<int32_t>(object._oVar5);\r\n\tfile.WriteLE<uint32_t>(object._oVar6);\r\n\tfile.WriteLE<int32_t>(object.bookMessage);\r\n\tfile.WriteLE<int32_t>(object._oVar8);\r\n}\r\n\r\nvoid SaveQuest(SaveHelper *file, int i)\r\n{\r\n\tauto &quest = Quests[i];\r\n\r\n\tfile->WriteLE<uint8_t>(quest._qlevel);\r\n\tfile->WriteLE<uint8_t>(quest._qidx); // _qtype for compatibility, used in DRLG_CheckQuests\r\n\tfile->WriteLE<uint8_t>(quest._qactive);\r\n\tfile->WriteLE<uint8_t>(quest._qlvltype);\r\n\tfile->WriteLE<int32_t>(quest.position.x);\r\n\tfile->WriteLE<int32_t>(quest.position.y);\r\n\tfile->WriteLE<uint8_t>(quest._qslvl);\r\n\tfile->WriteLE<uint8_t>(quest._qidx);\r\n\tif (gbIsHellfire) {\r\n\t\tfile->Skip(2); // Alignment\r\n\t\tfile->WriteLE<int32_t>(quest._qmsg);\r\n\t} else {\r\n\t\tfile->WriteLE<uint8_t>(quest._qmsg);\r\n\t}\r\n\tfile->WriteLE<uint8_t>(quest._qvar1);\r\n\tfile->WriteLE<uint8_t>(quest._qvar2);\r\n\tfile->Skip(2); // Alignment\r\n\tif (!gbIsHellfire)\r\n\t\tfile->Skip(1); // Alignment\r\n\tfile->WriteLE<uint32_t>(quest._qlog ? 1 : 0);\r\n\r\n\tfile->WriteBE<int32_t>(ReturnLvlPosition.x);\r\n\tfile->WriteBE<int32_t>(ReturnLvlPosition.y);\r\n\tfile->WriteBE<int32_t>(ReturnLevel);\r\n\tfile->WriteBE<int32_t>(ReturnLevelType);\r\n\tfile->Skip(sizeof(int32_t)); // Skip DoomQuestState\r\n}\r\n\r\nvoid SaveLighting(SaveHelper *file, Light *pLight, bool vision = false)\r\n{\r\n\tfile->WriteLE<int32_t>(pLight->position.tile.x);\r\n\tfile->WriteLE<int32_t>(pLight->position.tile.y);\r\n\tfile->WriteLE<int32_t>(pLight->radius);\r\n\tfile->WriteLE<int32_t>(vision ? 1 : 0); // _lid\r\n\tfile->WriteLE<uint32_t>(pLight->isInvalid ? 1 : 0);\r\n\tfile->WriteLE<uint32_t>(pLight->hasChanged ? 1 : 0);\r\n\tfile->Skip(4); // Unused\r\n\tfile->WriteLE<int32_t>(pLight->position.old.x);\r\n\tfile->WriteLE<int32_t>(pLight->position.old.y);\r\n\tfile->WriteLE<int32_t>(pLight->oldRadius);\r\n\tfile->WriteLE<int32_t>(pLight->position.offset.deltaX);\r\n\tfile->WriteLE<int32_t>(pLight->position.offset.deltaY);\r\n\tfile->WriteLE<uint32_t>(vision ? 1 : 0);\r\n}\r\n\r\nvoid SavePortal(SaveHelper *file, int i)\r\n{\r\n\tPortal *pPortal = &Portals[i];\r\n\r\n\tfile->WriteLE<uint32_t>(pPortal->open ? 1 : 0);\r\n\tfile->WriteLE<int32_t>(pPortal->position.x);\r\n\tfile->WriteLE<int32_t>(pPortal->position.y);\r\n\tfile->WriteLE<int32_t>(pPortal->level);\r\n\tfile->WriteLE<int32_t>(pPortal->setlvl ? pPortal->ltype : getHellfireLevelType(pPortal->ltype));\r\n\tfile->WriteLE<uint32_t>(pPortal->setlvl ? 1 : 0);\r\n}\r\n\r\n/**\r\n * @brief Saves items on the current dungeon floor\r\n * @param file interface to the save file\r\n * @return a map converting from runtime item indexes to the relative position in the save file, used by SaveDroppedItemLocations\r\n * @see SaveDroppedItemLocations\r\n */\r\nankerl::unordered_dense::map<uint8_t, uint8_t> SaveDroppedItems(SaveHelper &file)\r\n{\r\n\t// Vanilla Diablo/Hellfire initialise the ActiveItems and AvailableItems arrays based on saved data, so write valid values for compatibility\r\n\tfor (uint8_t i = 0; i < MAXITEMS; i++)\r\n\t\tfile.WriteLE<uint8_t>(i); // Strictly speaking everything from ActiveItemCount onwards is unused but no harm writing non-zero values here.\r\n\tfor (uint8_t i = 0; i < MAXITEMS; i++)\r\n\t\tfile.WriteLE<uint8_t>((i + ActiveItemCount) % MAXITEMS);\r\n\r\n\tankerl::unordered_dense::map<uint8_t, uint8_t> itemIndexes;\r\n\titemIndexes.reserve(ActiveItemCount + 1);\r\n\titemIndexes.emplace(0, 0);\r\n\tfor (uint8_t i = 0; i < ActiveItemCount; i++) {\r\n\t\titemIndexes[ActiveItems[i] + 1] = i + 1;\r\n\t\tSaveItem(file, Items[ActiveItems[i]]);\r\n\t}\r\n\treturn itemIndexes;\r\n}\r\n\r\n/**\r\n * @brief Saves the position of dropped items (in dItem)\r\n * @param file interface to the save file\r\n * @param itemIndexes a map converting from runtime item indexes to the relative position in the save file\r\n */\r\nvoid SaveDroppedItemLocations(SaveHelper &file, const ankerl::unordered_dense::map<uint8_t, uint8_t> &itemIndexes)\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tfile.WriteLE<uint8_t>(itemIndexes.at(dItem[i][j]));\r\n\t}\r\n}\r\n\r\nconstexpr uint32_t VersionAdditionalMissiles = 0;\r\n\r\nvoid SaveAdditionalMissiles(SaveWriter &saveWriter)\r\n{\r\n\tconstexpr size_t BytesWrittenBySaveMissile = 180;\r\n\tconst uint32_t missileCountAdditional = (Missiles.size() > MaxMissilesForSaveGame) ? static_cast<uint32_t>(Missiles.size() - MaxMissilesForSaveGame) : 0;\r\n\tSaveHelper file(saveWriter, \"additionalMissiles\", sizeof(uint32_t) + sizeof(uint32_t) + (missileCountAdditional * BytesWrittenBySaveMissile));\r\n\r\n\tfile.WriteLE<uint32_t>(VersionAdditionalMissiles);\r\n\tfile.WriteLE<uint32_t>(missileCountAdditional);\r\n\r\n\tif (missileCountAdditional > 0) {\r\n\t\tauto it = Missiles.cbegin();\r\n\t\t// std::list::const_iterator doesn't provide operator+() :/ using std::advance to get past the missiles we've already saved\r\n\t\tstd::advance(it, MaxMissilesForSaveGame);\r\n\t\tfor (; it != Missiles.cend(); it++) {\r\n\t\t\tSaveMissile(&file, *it);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LoadAdditionalMissiles()\r\n{\r\n\tLoadHelper file(OpenSaveArchive(gSaveNumber), \"additionalMissiles\");\r\n\r\n\tif (!file.IsValid()) {\r\n\t\t// no additional Missiles saved\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto loadedVersion = file.NextLE<uint32_t>();\r\n\tif (loadedVersion > VersionAdditionalMissiles) {\r\n\t\t// unknown version\r\n\t\treturn;\r\n\t}\r\n\tauto missileCountAdditional = file.NextLE<uint32_t>();\r\n\tfor (uint32_t i = 0U; i < missileCountAdditional; i++) {\r\n\t\tLoadMissile(&file);\r\n\t}\r\n}\r\n\r\nvoid SaveLevelSeeds(SaveWriter &saveWriter)\r\n{\r\n\tSaveHelper file(saveWriter, \"levelseeds\", giNumberOfLevels * (sizeof(uint8_t) + sizeof(uint32_t)));\r\n\r\n\tfor (int i = 0; i < giNumberOfLevels; i++) {\r\n\t\tfile.WriteLE<uint8_t>(LevelSeeds[i] ? 1 : 0);\r\n\t\tif (LevelSeeds[i]) {\r\n\t\t\tfile.WriteLE<uint32_t>(*LevelSeeds[i]);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LoadLevelSeeds()\r\n{\r\n\tLoadHelper file(OpenSaveArchive(gSaveNumber), \"levelseeds\");\r\n\tif (!file.IsValid())\r\n\t\treturn;\r\n\r\n\tfor (int i = 0; i < giNumberOfLevels; i++) {\r\n\t\tif (file.NextLE<uint8_t>() != 0) {\r\n\t\t\tLevelSeeds[i] = file.NextLE<uint32_t>();\r\n\t\t} else {\r\n\t\t\tLevelSeeds[i] = std::nullopt;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SaveLevel(SaveWriter &saveWriter, LevelConversionData *levelConversionData)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tDoUnVision(myPlayer.position.tile, myPlayer._pLightRad); // fix for vision staying on the level\r\n\r\n\tif (leveltype == DTYPE_TOWN)\r\n\t\tDungeonSeeds[0] = GenerateSeed();\r\n\r\n\tchar szName[MaxMpqPathSize];\r\n\tGetTempLevelNames(szName);\r\n\tSaveHelper file(saveWriter, szName, 256 * 1024);\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<int8_t>(dCorpse[i][j]);\r\n\t\t}\r\n\t}\r\n\r\n\tfile.WriteBE(static_cast<int32_t>(ActiveMonsterCount));\r\n\tfile.WriteBE<int32_t>(ActiveItemCount);\r\n\tfile.WriteBE<int32_t>(ActiveObjectCount);\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (const unsigned monsterId : ActiveMonsters)\r\n\t\t\tfile.WriteBE<uint32_t>(monsterId);\r\n\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\t\tMonsterConversionData *monsterConversionData = nullptr;\r\n\t\t\tif (levelConversionData != nullptr)\r\n\t\t\t\tmonsterConversionData = &levelConversionData->monsterConversionData[ActiveMonsters[i]];\r\n\t\t\tSaveMonster(&file, Monsters[ActiveMonsters[i]], monsterConversionData);\r\n\t\t}\r\n\t\tfor (const int objectId : ActiveObjects)\r\n\t\t\tfile.WriteLE<int8_t>(objectId);\r\n\t\tfor (const int objectId : AvailableObjects)\r\n\t\t\tfile.WriteLE<int8_t>(objectId);\r\n\t\tfor (int i = 0; i < ActiveObjectCount; i++) {\r\n\t\t\tSaveObject(file, Objects[ActiveObjects[i]]);\r\n\t\t}\r\n\t}\r\n\r\n\tauto itemIndexes = SaveDroppedItems(file);\r\n\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(dFlags[i][j] & DungeonFlag::SavedFlags));\r\n\t}\r\n\tSaveDroppedItemLocations(file, itemIndexes);\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteBE<int32_t>(dMonster[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<int8_t>(dObject[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<uint8_t>(dLight[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<uint8_t>(dPreLight[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\t\tfor (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<uint8_t>(AutomapView[i][j]);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!setlevel)\r\n\t\tmyPlayer._pLvlVisited[currlevel] = true;\r\n\telse\r\n\t\tmyPlayer._pSLvlVisited[setlvlnum] = true;\r\n}\r\n\r\ntl::expected<void, std::string> LoadLevel(LevelConversionData *levelConversionData)\r\n{\r\n\tchar szName[MaxMpqPathSize];\r\n\tstd::optional<SaveReader> archive = OpenSaveArchive(gSaveNumber);\r\n\tGetTempLevelNames(szName);\r\n\tif (!archive || !archive->HasFile(szName))\r\n\t\tGetPermLevelNames(szName);\r\n\tLoadHelper file(std::move(archive), szName);\r\n\tif (!file.IsValid())\r\n\t\treturn tl::make_unexpected(std::string(_(\"Unable to open save file archive\")));\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tdCorpse[i][j] = file.NextLE<int8_t>();\r\n\t\t}\r\n\t\tMoveLightsToCorpses();\r\n\t}\r\n\r\n\tActiveMonsterCount = file.NextBE<int32_t>();\r\n\tauto savedItemCount = file.NextBE<uint32_t>();\r\n\tActiveObjectCount = file.NextBE<int32_t>();\r\n\r\n\tankerl::unordered_dense::set<unsigned> removedMonsterIds;\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tLoadMonsters(file, removedMonsterIds, true, levelConversionData);\r\n\r\n\t\tif (!gbSkipSync) {\r\n\t\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++)\r\n\t\t\t\tRETURN_IF_ERROR(SyncMonsterAnim(Monsters[ActiveMonsters[i]]));\r\n\t\t}\r\n\t\tfor (int &objectId : ActiveObjects)\r\n\t\t\tobjectId = file.NextLE<int8_t>();\r\n\t\tfor (int &objectId : AvailableObjects)\r\n\t\t\tobjectId = file.NextLE<int8_t>();\r\n\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\tLoadObject(file, Objects[ActiveObjects[i]]);\r\n\t\tif (!gbSkipSync) {\r\n\t\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\t\tSyncObjectAnim(Objects[ActiveObjects[i]]);\r\n\t\t}\r\n\t}\r\n\r\n\tLoadDroppedItems(file, savedItemCount);\r\n\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tdFlags[i][j] = static_cast<DungeonFlag>(file.NextLE<uint8_t>()) & DungeonFlag::LoadedFlags;\r\n\t}\r\n\r\n\t// skip dItem indexes, this gets populated in LoadDroppedItems\r\n\tfile.Skip<uint8_t>(MAXDUNX * MAXDUNY);\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t{\r\n\t\t\t\tdMonster[i][j] = file.NextBE<int32_t>();\r\n\t\t\t\tif (dMonster[i][j] > 0 && removedMonsterIds.contains(std::abs(dMonster[i][j]) - 1)) {\r\n\t\t\t\t\tdMonster[i][j] = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tdObject[i][j] = file.NextLE<int8_t>();\r\n\t\t}\r\n\t\tfile.Skip<uint8_t>(MAXDUNY * MAXDUNX); // dLight\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tdPreLight[i][j] = file.NextLE<uint8_t>();\r\n\t\t}\r\n\t\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\t\tfor (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\t\tconst auto automapView = static_cast<MapExplorationType>(file.NextLE<uint8_t>());\r\n\t\t\t\tAutomapView[i][j] = automapView == MAP_EXP_OLD ? MAP_EXP_SELF : automapView;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// No need to load dLight, we can recreate it accurately from LightList\r\n\t\tmemcpy(dLight, dPreLight, sizeof(dLight));                                     // resets the light on entering a level to get rid of incorrect light\r\n\t\tChangeLightXY(Players[MyPlayerId].lightId, Players[MyPlayerId].position.tile); // forces player light refresh\r\n\t} else {\r\n\t\tmemset(dLight, 0, sizeof(dLight));\r\n\t}\r\n\r\n\tif (!gbSkipSync) {\r\n\t\tAutomapZoomReset();\r\n\t\tResyncQuests();\r\n\t\tRedoMissileFlags();\r\n\t\tUpdateLighting = true;\r\n\t}\r\n\r\n\tfor (const Player &player : Players) {\r\n\t\tif (player.plractive && player.isOnActiveLevel())\r\n\t\t\tLights[player.lightId].hasChanged = true;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nconst int DiabloItemSaveSize = 368;\r\nconst int HellfireItemSaveSize = 372;\r\n\r\nbool IsStashSizeValid(size_t stashSize, uint32_t pages, uint32_t itemCount)\r\n{\r\n\tconst size_t itemSize = (gbIsHellfire ? HellfireItemSaveSize : DiabloItemSaveSize);\r\n\r\n\tconst size_t expectedSize = sizeof(uint8_t)\r\n\t    + sizeof(uint32_t)\r\n\t    + sizeof(uint32_t)\r\n\t    + (sizeof(uint32_t) + 10 * 10 * sizeof(uint16_t)) * pages\r\n\t    + sizeof(uint32_t)\r\n\t    + itemSize * itemCount\r\n\t    + sizeof(uint32_t);\r\n\r\n\treturn stashSize == expectedSize;\r\n}\r\n\r\n} // namespace\r\n\r\ntl::expected<void, std::string> ConvertLevels(SaveWriter &saveWriter)\r\n{\r\n\t// Backup current level state\r\n\tconst bool tmpSetlevel = setlevel;\r\n\tconst _setlevels tmpSetlvlnum = setlvlnum;\r\n\tconst int tmpCurrlevel = currlevel;\r\n\tconst dungeon_type tmpLeveltype = leveltype;\r\n\r\n\tgbSkipSync = true;\r\n\r\n\tsetlevel = false; // Convert regular levels\r\n\tfor (int i = 0; i < giNumberOfLevels; i++) {\r\n\t\tcurrlevel = i;\r\n\t\tif (!LevelFileExists(saveWriter))\r\n\t\t\tcontinue;\r\n\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\r\n\t\tLevelConversionData levelConversionData;\r\n\t\tRETURN_IF_ERROR(LoadLevel(&levelConversionData));\r\n\t\tSaveLevel(saveWriter, &levelConversionData);\r\n\t}\r\n\r\n\tsetlevel = true; // Convert quest levels\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qactive == QUEST_NOTAVAIL) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tleveltype = quest._qlvltype;\r\n\t\tif (leveltype == DTYPE_NONE) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tsetlvlnum = quest._qslvl;\r\n\t\tif (!LevelFileExists(saveWriter))\r\n\t\t\tcontinue;\r\n\r\n\t\tLevelConversionData levelConversionData;\r\n\t\tRETURN_IF_ERROR(LoadLevel(&levelConversionData));\r\n\t\tSaveLevel(saveWriter, &levelConversionData);\r\n\t}\r\n\r\n\tgbSkipSync = false;\r\n\r\n\t// Restore current level state\r\n\tsetlevel = tmpSetlevel;\r\n\tsetlvlnum = tmpSetlvlnum;\r\n\tcurrlevel = tmpCurrlevel;\r\n\tleveltype = tmpLeveltype;\r\n\treturn {};\r\n}\r\n\r\nvoid RemoveInvalidItem(Item &item)\r\n{\r\n\tbool isInvalid = !IsItemAvailable(item.IDidx) || item._iUid >= static_cast<int>(UniqueItems.size());\r\n\r\n\tif (!gbIsHellfire) {\r\n\t\tisInvalid = isInvalid || (item._itype == ItemType::Staff && GetSpellStaffLevel(item._iSpell) == -1);\r\n\t\tisInvalid = isInvalid || (item._iMiscId == IMISC_BOOK && GetSpellBookLevel(item._iSpell) == -1);\r\n\t\tisInvalid = isInvalid || item._iDamAcFlags != ItemSpecialEffectHf::None;\r\n\t\tisInvalid = isInvalid || item._iPrePower > IPL_LASTDIABLO;\r\n\t\tisInvalid = isInvalid || item._iSufPower > IPL_LASTDIABLO;\r\n\t}\r\n\r\n\tif (isInvalid) {\r\n\t\titem.clear();\r\n\t}\r\n}\r\n\r\n_item_indexes RemapItemIdxFromDiablo(_item_indexes i)\r\n{\r\n\tconstexpr auto GetItemIdValue = [](int i) -> int {\r\n\t\tif (i == IDI_SORCERER) {\r\n\t\t\treturn IDI_SORCERER_DIABLO;\r\n\t\t}\r\n\t\tif (i >= 156) {\r\n\t\t\ti += 5; // Hellfire exclusive items\r\n\t\t}\r\n\t\tif (i >= 88) {\r\n\t\t\ti += 1; // Scroll of Search\r\n\t\t}\r\n\t\tif (i >= 83) {\r\n\t\t\ti += 4; // Oils\r\n\t\t}\r\n\r\n\t\treturn i;\r\n\t};\r\n\r\n\treturn static_cast<_item_indexes>(GetItemIdValue(i));\r\n}\r\n\r\n_item_indexes RemapItemIdxToDiablo(_item_indexes i)\r\n{\r\n\tconstexpr auto GetItemIdValue = [](int i) -> int {\r\n\t\tif (i == IDI_SORCERER_DIABLO) {\r\n\t\t\treturn IDI_SORCERER;\r\n\t\t}\r\n\t\tif ((i >= 83 && i <= 86) || i == 92 || i >= 161) {\r\n\t\t\treturn -1; // Hellfire exclusive items\r\n\t\t}\r\n\t\tif (i >= 93) {\r\n\t\t\ti -= 1; // Scroll of Search\r\n\t\t}\r\n\t\tif (i >= 87) {\r\n\t\t\ti -= 4; // Oils\r\n\t\t}\r\n\r\n\t\treturn i;\r\n\t};\r\n\r\n\treturn static_cast<_item_indexes>(GetItemIdValue(i));\r\n}\r\n\r\n_item_indexes RemapItemIdxFromSpawn(_item_indexes i)\r\n{\r\n\tconstexpr auto GetItemIdValue = [](int i) {\r\n\t\tif (i >= 62) {\r\n\t\t\ti += 9; // Medium and heavy armors\r\n\t\t}\r\n\t\tif (i >= 96) {\r\n\t\t\ti += 1; // Scroll of Stone Curse\r\n\t\t}\r\n\t\tif (i >= 98) {\r\n\t\t\ti += 1; // Scroll of Guardian\r\n\t\t}\r\n\t\tif (i >= 99) {\r\n\t\t\ti += 1; // Scroll of ...\r\n\t\t}\r\n\t\tif (i >= 101) {\r\n\t\t\ti += 1; // Scroll of Golem\r\n\t\t}\r\n\t\tif (i >= 102) {\r\n\t\t\ti += 1; // Scroll of None\r\n\t\t}\r\n\t\tif (i >= 104) {\r\n\t\t\ti += 1; // Scroll of Apocalypse\r\n\t\t}\r\n\r\n\t\treturn i;\r\n\t};\r\n\r\n\treturn static_cast<_item_indexes>(GetItemIdValue(i));\r\n}\r\n\r\n_item_indexes RemapItemIdxToSpawn(_item_indexes i)\r\n{\r\n\tconstexpr auto GetItemIdValue = [](int i) {\r\n\t\tif (i >= 104) {\r\n\t\t\ti -= 1; // Scroll of Apocalypse\r\n\t\t}\r\n\t\tif (i >= 102) {\r\n\t\t\ti -= 1; // Scroll of None\r\n\t\t}\r\n\t\tif (i >= 101) {\r\n\t\t\ti -= 1; // Scroll of Golem\r\n\t\t}\r\n\t\tif (i >= 99) {\r\n\t\t\ti -= 1; // Scroll of ...\r\n\t\t}\r\n\t\tif (i >= 98) {\r\n\t\t\ti -= 1; // Scroll of Guardian\r\n\t\t}\r\n\t\tif (i >= 96) {\r\n\t\t\ti -= 1; // Scroll of Stone Curse\r\n\t\t}\r\n\t\tif (i >= 71) {\r\n\t\t\ti -= 9; // Medium and heavy armors\r\n\t\t}\r\n\r\n\t\treturn i;\r\n\t};\r\n\r\n\treturn static_cast<_item_indexes>(GetItemIdValue(i));\r\n}\r\n\r\nbool IsHeaderValid(uint32_t magicNumber)\r\n{\r\n\tgbIsHellfireSaveGame = false;\r\n\tif (magicNumber == LoadLE32(\"SHAR\")) {\r\n\t\treturn true;\r\n\t}\r\n\tif (magicNumber == LoadLE32(\"SHLF\")) {\r\n\t\tgbIsHellfireSaveGame = true;\r\n\t\treturn true;\r\n\t}\r\n\tif (!gbIsSpawn && magicNumber == LoadLE32(\"RETL\")) {\r\n\t\treturn true;\r\n\t}\r\n\tif (!gbIsSpawn && magicNumber == LoadLE32(\"HELF\")) {\r\n\t\tgbIsHellfireSaveGame = true;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n// Returns the size of the hotkeys file with the number of hotkeys passed and if a header with the number of hotkeys is present in the file\r\nsize_t HotkeysSize(size_t nHotkeys = NumHotkeys)\r\n{\r\n\t//     header            spells                         spell types                    active spell      active spell type\r\n\treturn sizeof(uint8_t) + (nHotkeys * sizeof(int32_t)) + (nHotkeys * sizeof(uint8_t)) + sizeof(int32_t) + sizeof(uint8_t);\r\n}\r\n\r\nvoid LoadHotkeys()\r\n{\r\n\tLoadHelper file(OpenSaveArchive(gSaveNumber), \"hotkeys\");\r\n\tif (!file.IsValid())\r\n\t\treturn;\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tsize_t nHotkeys = 4; // Defaults to old save format number\r\n\r\n\t// Refill the spell arrays with no selection\r\n\tstd::fill(myPlayer._pSplHotKey, myPlayer._pSplHotKey + NumHotkeys, SpellID::Invalid);\r\n\tstd::fill(myPlayer._pSplTHotKey, myPlayer._pSplTHotKey + NumHotkeys, SpellType::Invalid);\r\n\r\n\t// Checking if the save file has the old format with only 4 hotkeys and no header\r\n\tif (file.IsValid(HotkeysSize(nHotkeys))) {\r\n\t\t// The file contains a header byte and at least 4 entries, so we can assume it's a new format save\r\n\t\tnHotkeys = file.NextLE<uint8_t>();\r\n\t}\r\n\r\n\t// Read all hotkeys in the file\r\n\tfor (size_t i = 0; i < nHotkeys; i++) {\r\n\t\t// Do not load hotkeys past the size of the spell types array, discard the rest\r\n\t\tif (i < NumHotkeys) {\r\n\t\t\tmyPlayer._pSplHotKey[i] = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\t\t} else {\r\n\t\t\tfile.Skip<int32_t>();\r\n\t\t}\r\n\t}\r\n\tfor (size_t i = 0; i < nHotkeys; i++) {\r\n\t\t// Do not load hotkeys past the size of the spells array, discard the rest\r\n\t\tif (i < NumHotkeys) {\r\n\t\t\tmyPlayer._pSplTHotKey[i] = static_cast<SpellType>(file.NextLE<uint8_t>());\r\n\t\t} else {\r\n\t\t\tfile.Skip<uint8_t>();\r\n\t\t}\r\n\t}\r\n\r\n\t// Load the selected spell last\r\n\tmyPlayer._pRSpell = static_cast<SpellID>(file.NextLE<int32_t>());\r\n\tmyPlayer._pRSplType = static_cast<SpellType>(file.NextLE<uint8_t>());\r\n}\r\n\r\nvoid SaveHotkeys(SaveWriter &saveWriter, const Player &player)\r\n{\r\n\tSaveHelper file(saveWriter, \"hotkeys\", HotkeysSize());\r\n\r\n\t// Write the number of spell hotkeys\r\n\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(NumHotkeys));\r\n\r\n\t// Write the spell hotkeys\r\n\tfor (const auto &spellId : player._pSplHotKey) {\r\n\t\tfile.WriteLE<int32_t>(static_cast<int8_t>(spellId));\r\n\t}\r\n\tfor (const auto &spellType : player._pSplTHotKey) {\r\n\t\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(spellType));\r\n\t}\r\n\r\n\t// Write the selected spell last\r\n\tfile.WriteLE<int32_t>(static_cast<int8_t>(player._pRSpell));\r\n\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(player._pRSplType));\r\n}\r\n\r\nvoid LoadHeroItems(Player &player)\r\n{\r\n\tLoadHelper file(OpenSaveArchive(gSaveNumber), \"heroitems\");\r\n\tif (!file.IsValid())\r\n\t\treturn;\r\n\r\n\tgbIsHellfireSaveGame = file.NextBool8();\r\n\r\n\tLoadMatchingItems(file, player, NUM_INVLOC, player.InvBody);\r\n\tLoadMatchingItems(file, player, InventoryGridCells, player.InvList);\r\n\tLoadMatchingItems(file, player, MaxBeltItems, player.SpdList);\r\n\r\n\tgbIsHellfireSaveGame = gbIsHellfire;\r\n}\r\n\r\nconstexpr uint8_t StashVersion = 0;\r\n\r\nvoid LoadStash()\r\n{\r\n\tconst char *filename;\r\n\tif (!gbIsMultiplayer)\r\n\t\tfilename = \"spstashitems\";\r\n\telse\r\n\t\tfilename = \"mpstashitems\";\r\n\r\n\tStash = {};\r\n\r\n\tLoadHelper file(OpenStashArchive(), filename);\r\n\tif (!file.IsValid())\r\n\t\treturn;\r\n\r\n\tauto version = file.NextLE<uint8_t>();\r\n\tif (version > StashVersion) {\r\n\t\tEventPlrMsg(_(\"Stash version invalid. If you attempt to access your stash, data will be overwritten!!\"), UiFlags::ColorRed);\r\n\t\treturn;\r\n\t}\r\n\r\n\tStash.gold = file.NextLE<uint32_t>();\r\n\r\n\tauto pages = file.NextLE<uint32_t>();\r\n\tfor (unsigned i = 0; i < pages; i++) {\r\n\t\tauto page = file.NextLE<uint32_t>();\r\n\t\tfor (auto &row : Stash.stashGrids[page]) {\r\n\t\t\tfor (uint16_t &cell : row) {\r\n\t\t\t\tcell = file.NextLE<uint16_t>();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tauto itemCount = file.NextLE<uint32_t>();\r\n\tif (!IsStashSizeValid(file.Size(), pages, itemCount)) {\r\n\t\tStash = {};\r\n\t\tEventPlrMsg(_(\"Stash size invalid. If you attempt to access your stash, data will be overwritten!!\"), UiFlags::ColorRed);\r\n\t\treturn;\r\n\t}\r\n\tStash.stashList.resize(itemCount);\r\n\tfor (unsigned i = 0; i < itemCount; i++) {\r\n\t\tLoadAndValidateItemData(file, Stash.stashList[i]);\r\n\t}\r\n\r\n\tStash.SetPage(file.NextLE<uint32_t>());\r\n}\r\n\r\nvoid RemoveEmptyInventory(Player &player)\r\n{\r\n\tfor (int i = InventoryGridCells; i > 0; i--) {\r\n\t\tconst int8_t idx = player.InvGrid[i - 1];\r\n\t\tif (idx > 0 && player.InvList[idx - 1].isEmpty()) {\r\n\t\t\tplayer.RemoveInvItem(idx - 1);\r\n\t\t}\r\n\t}\r\n}\r\n\r\ntl::expected<void, std::string> LoadGame(bool firstflag)\r\n{\r\n\tFreeGameMem();\r\n\r\n\tLoadHelper file(OpenSaveArchive(gSaveNumber), \"game\");\r\n\tif (!file.IsValid()) {\r\n\t\treturn tl::make_unexpected(std::string(_(\"Unable to open save file archive\")));\r\n\t}\r\n\r\n\tif (!IsHeaderValid(file.NextLE<uint32_t>())) {\r\n\t\treturn tl::make_unexpected(std::string(_(\"Invalid save file\")));\r\n\t}\r\n\r\n\tif (gbIsHellfireSaveGame) {\r\n\t\tgiNumberOfLevels = 25;\r\n\t\tgiNumberQuests = 24;\r\n\t\tgiNumberOfSmithPremiumItems = 15;\r\n\t} else {\r\n\t\t// Todo initialize additional levels and quests if we are running Hellfire\r\n\t\tgiNumberOfLevels = 17;\r\n\t\tgiNumberQuests = 16;\r\n\t\tgiNumberOfSmithPremiumItems = 6;\r\n\t}\r\n\r\n\tpfile_remove_temp_files();\r\n\r\n\tsetlevel = file.NextBool8();\r\n\tsetlvlnum = static_cast<_setlevels>(file.NextBE<uint32_t>());\r\n\tcurrlevel = file.NextBE<uint32_t>();\r\n\tleveltype = static_cast<dungeon_type>(file.NextBE<uint32_t>());\r\n\tif (!setlevel)\r\n\t\tleveltype = GetLevelType(currlevel);\r\n\tconst int viewX = file.NextBE<int32_t>();\r\n\tconst int viewY = file.NextBE<int32_t>();\r\n\tinvflag = file.NextBool8();\r\n\tCharFlag = file.NextBool8();\r\n\tconst int tmpNummonsters = file.NextBE<int32_t>();\r\n\tauto savedItemCount = file.NextBE<uint32_t>();\r\n\tconst int tmpNummissiles = file.NextBE<int32_t>();\r\n\tconst int tmpNobjects = file.NextBE<int32_t>();\r\n\r\n\tif (!gbIsHellfire && IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {\r\n\t\treturn tl::make_unexpected(std::string(_(\"Player is on a Hellfire only level\")));\r\n\t}\r\n\r\n\tfor (uint8_t i = 0; i < giNumberOfLevels; i++) {\r\n\t\tDungeonSeeds[i] = file.NextBE<uint32_t>();\r\n\t\tLevelSeeds[i] = std::nullopt;\r\n\t\tfile.Skip(4); // Skip loading gnLevelTypeTbl\r\n\t}\r\n\tLoadLevelSeeds();\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tLoadPlayer(file, myPlayer);\r\n\r\n\tif (sgGameInitInfo.nDifficulty < DIFF_NORMAL || sgGameInitInfo.nDifficulty > DIFF_HELL)\r\n\t\tsgGameInitInfo.nDifficulty = DIFF_NORMAL;\r\n\r\n\tfor (int i = 0; i < giNumberQuests; i++)\r\n\t\tLoadQuest(&file, i);\r\n\tfor (int i = 0; i < MAXPORTAL; i++)\r\n\t\tLoadPortal(&file, i);\r\n\r\n\tif (gbIsHellfireSaveGame != gbIsHellfire) {\r\n\t\tRETURN_IF_ERROR(pfile_convert_levels());\r\n\t\tRemoveEmptyInventory(myPlayer);\r\n\t}\r\n\r\n\tRETURN_IF_ERROR(LoadGameLevel(firstflag, ENTRY_LOAD));\r\n\tSetPlrAnims(myPlayer);\r\n\tSyncPlrAnim(myPlayer);\r\n\r\n\tViewPosition = { viewX, viewY };\r\n\tActiveMonsterCount = tmpNummonsters;\r\n\tActiveObjectCount = tmpNobjects;\r\n\r\n\tfor (size_t i = 0; i < MonstersData.size(); ++i) {\r\n\t\tint &monstkill = MonsterKillCounts[i];\r\n\t\tmonstkill = file.NextBE<int32_t>();\r\n\t}\r\n\r\n\tankerl::unordered_dense::set<unsigned> removedMonsterIds;\r\n\r\n\t// skip ahead for vanilla save compatibility (Related to bugfix where MonsterKillCounts[MaxMonsters] was changed to MonsterKillCounts[NUM_MTYPES]\r\n\tfile.Skip(4 * (MaxMonsters - MonstersData.size()));\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tLoadMonsters(file, removedMonsterIds, false, nullptr);\r\n\r\n\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++)\r\n\t\t\tSyncPackSize(Monsters[ActiveMonsters[i]]);\r\n\t\t// Skip ActiveMissiles\r\n\t\tfile.Skip<int8_t>(MaxMissilesForSaveGame);\r\n\t\t// Skip AvailableMissiles\r\n\t\tfile.Skip<int8_t>(MaxMissilesForSaveGame);\r\n\t\tfor (int i = 0; i < tmpNummissiles; i++)\r\n\t\t\tLoadMissile(&file);\r\n\t\t// For petrified monsters, the data in missile.var1 must be used to\r\n\t\t// load the appropriate animation data for the monster in missile.var2\r\n\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++)\r\n\t\t\tRETURN_IF_ERROR(SyncMonsterAnim(Monsters[ActiveMonsters[i]]));\r\n\t\tfor (int &objectId : ActiveObjects)\r\n\t\t\tobjectId = file.NextLE<int8_t>();\r\n\t\tfor (int &objectId : AvailableObjects)\r\n\t\t\tobjectId = file.NextLE<int8_t>();\r\n\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\tLoadObject(file, Objects[ActiveObjects[i]]);\r\n\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\tSyncObjectAnim(Objects[ActiveObjects[i]]);\r\n\r\n\t\tActiveLightCount = file.NextBE<int32_t>();\r\n\r\n\t\tfor (uint8_t &lightId : ActiveLights)\r\n\t\t\tlightId = file.NextLE<uint8_t>();\r\n\t\tfor (int i = 0; i < ActiveLightCount; i++)\r\n\t\t\tLoadLighting(&file, &Lights[ActiveLights[i]]);\r\n\r\n\t\tfile.Skip<int32_t>(); // VisionId\r\n\t\tconst int visionCount = file.NextBE<int32_t>();\r\n\r\n\t\tfor (int i = 0; i < visionCount; i++) {\r\n\t\t\tLoadLighting(&file, &VisionList[i]);\r\n\t\t\tVisionActive[i] = true;\r\n\t\t}\r\n\t}\r\n\r\n\tLoadDroppedItems(file, savedItemCount);\r\n\r\n\tLoadAdditionalMissiles();\r\n\r\n\tfor (bool &uniqueItemFlag : UniqueItemFlags)\r\n\t\tuniqueItemFlag = file.NextBool8();\r\n\r\n\tfile.Skip<uint8_t>(MAXDUNY * MAXDUNX); // dLight\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tdFlags[i][j] = static_cast<DungeonFlag>(file.NextLE<uint8_t>()) & DungeonFlag::LoadedFlags;\r\n\t}\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tdPlayer[i][j] = file.NextLE<int8_t>();\r\n\t}\r\n\r\n\t// skip dItem indexes, this gets populated in LoadDroppedItems\r\n\tfile.Skip<uint8_t>(MAXDUNX * MAXDUNY);\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t{\r\n\t\t\t\tdMonster[i][j] = file.NextBE<int32_t>();\r\n\t\t\t\tif (dMonster[i][j] > 0 && removedMonsterIds.contains(std::abs(dMonster[i][j]) - 1)) {\r\n\t\t\t\t\tdMonster[i][j] = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tdCorpse[i][j] = file.NextLE<int8_t>();\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tdObject[i][j] = file.NextLE<int8_t>();\r\n\t\t}\r\n\t\tfile.Skip<uint8_t>(MAXDUNY * MAXDUNX); // dLight\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tdPreLight[i][j] = file.NextLE<uint8_t>();\r\n\t\t}\r\n\t\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\t\tfor (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\t\tconst auto automapView = static_cast<MapExplorationType>(file.NextLE<uint8_t>());\r\n\t\t\t\tAutomapView[i][j] = automapView == MAP_EXP_OLD ? MAP_EXP_SELF : automapView;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfile.Skip(MAXDUNX * MAXDUNY); // dMissile\r\n\r\n\t\t// No need to load dLight, we can recreate it accurately from LightList\r\n\t\tmemcpy(dLight, dPreLight, sizeof(dLight));               // resets the light on entering a level to get rid of incorrect light\r\n\t\tChangeLightXY(myPlayer.lightId, myPlayer.position.tile); // forces player light refresh\r\n\t} else {\r\n\t\tmemset(dLight, 0, sizeof(dLight));\r\n\t}\r\n\r\n\tPremiumItemCount = file.NextBE<int32_t>();\r\n\tPremiumItemLevel = file.NextBE<int32_t>();\r\n\r\n\tfor (int i = 0; i < giNumberOfSmithPremiumItems; i++)\r\n\t\tLoadPremium(file, i);\r\n\tif (gbIsHellfire && !gbIsHellfireSaveGame)\r\n\t\tSpawnPremium(myPlayer);\r\n\r\n\tAutomapActive = file.NextBool8();\r\n\tAutoMapScale = file.NextBE<int32_t>();\r\n\tAutomapZoomReset();\r\n\tResyncQuests();\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tRedoPlayerVision();\r\n\t\tProcessVisionList();\r\n\t\tProcessLightList();\r\n\t}\r\n\r\n\t// convert stray manashield missiles into pManaShield flag\r\n\tfor (auto &missile : Missiles) {\r\n\t\tif (missile._mitype == MissileID::ManaShield && !missile._miDelFlag) {\r\n\t\t\tPlayers[missile._misource].pManaShield = true;\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t}\r\n\t}\r\n\r\n\tSetUpMissileAnimationData();\r\n\tRedoMissileFlags();\r\n\tgbProcessPlayers = IsDiabloAlive(!firstflag);\r\n\r\n\tif (gbIsHellfireSaveGame != gbIsHellfire) {\r\n\t\tSaveGame();\r\n\t}\r\n\r\n\tgbIsHellfireSaveGame = gbIsHellfire;\r\n\treturn {};\r\n}\r\n\r\nvoid SaveHeroItems(SaveWriter &saveWriter, Player &player)\r\n{\r\n\tconst size_t itemCount = static_cast<size_t>(NUM_INVLOC) + InventoryGridCells + MaxBeltItems;\r\n\tSaveHelper file(saveWriter, \"heroitems\", itemCount * (gbIsHellfire ? HellfireItemSaveSize : DiabloItemSaveSize) + sizeof(uint8_t));\r\n\r\n\tfile.WriteLE<uint8_t>(gbIsHellfire ? 1 : 0);\r\n\r\n\tfor (const Item &item : player.InvBody)\r\n\t\tSaveItem(file, item);\r\n\tfor (const Item &item : player.InvList)\r\n\t\tSaveItem(file, item);\r\n\tfor (const Item &item : player.SpdList)\r\n\t\tSaveItem(file, item);\r\n}\r\n\r\nvoid SaveStash(SaveWriter &stashWriter)\r\n{\r\n\tconst char *filename;\r\n\tif (!gbIsMultiplayer)\r\n\t\tfilename = \"spstashitems\";\r\n\telse\r\n\t\tfilename = \"mpstashitems\";\r\n\r\n\tconst int itemSize = (gbIsHellfire ? HellfireItemSaveSize : DiabloItemSaveSize);\r\n\r\n\tSaveHelper file(\r\n\t    stashWriter,\r\n\t    filename,\r\n\t    sizeof(uint8_t)\r\n\t        + sizeof(uint32_t)\r\n\t        + sizeof(uint32_t)\r\n\t        + (sizeof(uint32_t) + 10 * 10 * sizeof(uint16_t)) * Stash.stashGrids.size()\r\n\t        + sizeof(uint32_t)\r\n\t        + itemSize * Stash.stashList.size()\r\n\t        + sizeof(uint32_t));\r\n\r\n\tfile.WriteLE<uint8_t>(StashVersion);\r\n\r\n\tfile.WriteLE<uint32_t>(Stash.gold);\r\n\r\n\tstd::vector<unsigned> pagesToSave;\r\n\tfor (const auto &[page, grid] : Stash.stashGrids) {\r\n\t\tif (c_any_of(grid, [](const auto &row) {\r\n\t\t\t    return c_any_of(row, [](StashStruct::StashCell cell) {\r\n\t\t\t\t    return cell > 0;\r\n\t\t\t    });\r\n\t\t    })) {\r\n\t\t\t// found a page that contains at least one item\r\n\t\t\tpagesToSave.push_back(page);\r\n\t\t}\r\n\t};\r\n\r\n\t// Current stash size is 100 pages. Will definitely fit in a 32 bit value.\r\n\tfile.WriteLE<uint32_t>(static_cast<uint32_t>(pagesToSave.size()));\r\n\tfor (const auto &page : pagesToSave) {\r\n\t\tfile.WriteLE<uint32_t>(page);\r\n\t\tfor (const auto &row : Stash.stashGrids[page]) {\r\n\t\t\tfor (const uint16_t cell : row) {\r\n\t\t\t\tfile.WriteLE<uint16_t>(cell);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// 100 pages of 100 items is still only 10 000, as with the page count will definitely fit in 32 bits even in the worst case.\r\n\tfile.WriteLE<uint32_t>(static_cast<uint32_t>(Stash.stashList.size()));\r\n\tfor (const Item &item : Stash.stashList) {\r\n\t\tSaveItem(file, item);\r\n\t}\r\n\r\n\tfile.WriteLE<uint32_t>(static_cast<uint32_t>(Stash.GetPage()));\r\n}\r\n\r\nvoid SaveGameData(SaveWriter &saveWriter)\r\n{\r\n\tSaveHelper file(saveWriter, \"game\", 320 * 1024);\r\n\r\n\tif (gbIsSpawn && !gbIsHellfire)\r\n\t\tfile.WriteLE<uint32_t>(LoadLE32(\"SHAR\"));\r\n\telse if (gbIsSpawn && gbIsHellfire)\r\n\t\tfile.WriteLE<uint32_t>(LoadLE32(\"SHLF\"));\r\n\telse if (!gbIsSpawn && gbIsHellfire)\r\n\t\tfile.WriteLE<uint32_t>(LoadLE32(\"HELF\"));\r\n\telse if (!gbIsSpawn && !gbIsHellfire)\r\n\t\tfile.WriteLE<uint32_t>(LoadLE32(\"RETL\"));\r\n\telse\r\n\t\tapp_fatal(_(\"Invalid game state\"));\r\n\r\n\tif (gbIsHellfire) {\r\n\t\tgiNumberOfLevels = 25;\r\n\t\tgiNumberQuests = 24;\r\n\t\tgiNumberOfSmithPremiumItems = 15;\r\n\t} else {\r\n\t\tgiNumberOfLevels = 17;\r\n\t\tgiNumberQuests = 16;\r\n\t\tgiNumberOfSmithPremiumItems = 6;\r\n\t}\r\n\r\n\tfile.WriteLE<uint8_t>(setlevel ? 1 : 0);\r\n\tfile.WriteBE<uint32_t>(setlvlnum);\r\n\tfile.WriteBE<uint32_t>(currlevel);\r\n\tfile.WriteBE<uint32_t>(getHellfireLevelType(leveltype));\r\n\tfile.WriteBE<int32_t>(ViewPosition.x);\r\n\tfile.WriteBE<int32_t>(ViewPosition.y);\r\n\tfile.WriteLE<uint8_t>(invflag ? 1 : 0);\r\n\tfile.WriteLE<uint8_t>(CharFlag ? 1 : 0);\r\n\tfile.WriteBE(static_cast<int32_t>(ActiveMonsterCount));\r\n\tfile.WriteBE<int32_t>(ActiveItemCount);\r\n\t// ActiveMissileCount will be a value from 0-125 (for vanilla compatibility). Writing an unsigned value here to avoid\r\n\t// warnings about casting from unsigned to signed, but there's no sign extension issues when reading this as a signed\r\n\t// value later so it doesn't have to match in LoadGameData().\r\n\tfile.WriteBE<uint32_t>(static_cast<uint32_t>(std::min(Missiles.size(), MaxMissilesForSaveGame)));\r\n\tfile.WriteBE<int32_t>(ActiveObjectCount);\r\n\r\n\tfor (uint8_t i = 0; i < giNumberOfLevels; i++) {\r\n\t\tfile.WriteBE<uint32_t>(DungeonSeeds[i]);\r\n\t\tfile.WriteBE<int32_t>(getHellfireLevelType(GetLevelType(i)));\r\n\t}\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tSavePlayer(file, myPlayer);\r\n\r\n\tfor (int i = 0; i < giNumberQuests; i++)\r\n\t\tSaveQuest(&file, i);\r\n\tfor (int i = 0; i < MAXPORTAL; i++)\r\n\t\tSavePortal(&file, i);\r\n\tfor (size_t i = 0; i < MonstersData.size(); ++i) {\r\n\t\tconst int monstkill = MonsterKillCounts[i];\r\n\t\tfile.WriteBE<int32_t>(monstkill);\r\n\t}\r\n\t// add padding for vanilla save compatibility (Related to bugfix where MonsterKillCounts[MaxMonsters] was changed to MonsterKillCounts[NUM_MTYPES]\r\n\tfile.Skip(4 * (MaxMonsters - MonstersData.size()));\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (const unsigned monsterId : ActiveMonsters)\r\n\t\t\tfile.WriteBE<uint32_t>(monsterId);\r\n\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++)\r\n\t\t\tSaveMonster(&file, Monsters[ActiveMonsters[i]]);\r\n\t\t// Write ActiveMissiles\r\n\t\tfor (uint8_t activeMissile = 0; activeMissile < MaxMissilesForSaveGame; activeMissile++)\r\n\t\t\tfile.WriteLE<uint8_t>(activeMissile);\r\n\t\t// Write AvailableMissiles\r\n\t\tfor (size_t availableMissiles = Missiles.size(); availableMissiles < MaxMissilesForSaveGame; availableMissiles++)\r\n\t\t\tfile.WriteLE(static_cast<uint8_t>(availableMissiles));\r\n\t\tconst size_t savedMissiles = std::min(Missiles.size(), MaxMissilesForSaveGame);\r\n\t\tfile.Skip<uint8_t>(savedMissiles);\r\n\t\t// Write Missile Data\r\n\t\t{\r\n\t\t\tauto missilesEnd = Missiles.cbegin();\r\n\t\t\tstd::advance(missilesEnd, savedMissiles);\r\n\t\t\tfor (auto it = Missiles.cbegin(); it != missilesEnd; it++) {\r\n\t\t\t\tSaveMissile(&file, *it);\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (const int objectId : ActiveObjects)\r\n\t\t\tfile.WriteLE(static_cast<int8_t>(objectId));\r\n\t\tfor (const int objectId : AvailableObjects)\r\n\t\t\tfile.WriteLE(static_cast<int8_t>(objectId));\r\n\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\tSaveObject(file, Objects[ActiveObjects[i]]);\r\n\r\n\t\tfile.WriteBE<int32_t>(ActiveLightCount);\r\n\r\n\t\tfor (const uint8_t lightId : ActiveLights)\r\n\t\t\tfile.WriteLE<uint8_t>(lightId);\r\n\t\tfor (int i = 0; i < ActiveLightCount; i++)\r\n\t\t\tSaveLighting(&file, &Lights[ActiveLights[i]]);\r\n\r\n\t\tconst auto visionCount = static_cast<int32_t>(Players.size());\r\n\t\tfile.WriteBE<int32_t>(visionCount + 1); // VisionId\r\n\t\tfile.WriteBE<int32_t>(visionCount);\r\n\r\n\t\tfor (const Player &player : Players)\r\n\t\t\tSaveLighting(&file, &VisionList[player.getId()], true);\r\n\t}\r\n\r\n\tauto itemIndexes = SaveDroppedItems(file);\r\n\r\n\tfor (const bool uniqueItemFlag : UniqueItemFlags)\r\n\t\tfile.WriteLE<uint8_t>(uniqueItemFlag ? 1 : 0);\r\n\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tfile.WriteLE<uint8_t>(dLight[i][j]);\r\n\t}\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tfile.WriteLE<uint8_t>(static_cast<uint8_t>(dFlags[i][j] & DungeonFlag::SavedFlags));\r\n\t}\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\tfile.WriteLE<int8_t>(dPlayer[i][j]);\r\n\t}\r\n\r\n\tSaveDroppedItemLocations(file, itemIndexes);\r\n\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteBE<int32_t>(dMonster[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<int8_t>(dCorpse[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<int8_t>(dObject[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++)        // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<uint8_t>(dLight[i][j]); // BUGFIX: dLight got saved already\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<uint8_t>(dPreLight[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < DMAXY; j++) {\r\n\t\t\tfor (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<uint8_t>(AutomapView[i][j]);\r\n\t\t}\r\n\t\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\t\tfor (int i = 0; i < MAXDUNX; i++)                                 // NOLINT(modernize-loop-convert)\r\n\t\t\t\tfile.WriteLE<int8_t>(TileContainsMissile({ i, j }) ? -1 : 0); // For backwards compatibility\r\n\t\t}\r\n\t}\r\n\r\n\tfile.WriteBE<int32_t>(PremiumItemCount);\r\n\tfile.WriteBE<int32_t>(PremiumItemLevel);\r\n\r\n\tfor (int i = 0; i < giNumberOfSmithPremiumItems; i++)\r\n\t\tSaveItem(file, PremiumItems[i]);\r\n\r\n\tfile.WriteLE<uint8_t>(AutomapActive ? 1 : 0);\r\n\tfile.WriteBE<int32_t>(AutoMapScale);\r\n\r\n\tSaveAdditionalMissiles(saveWriter);\r\n\tSaveLevelSeeds(saveWriter);\r\n}\r\n\r\nvoid SaveGame()\r\n{\r\n\tgbValidSaveFile = true;\r\n\tpfile_write_hero(/*writeGameData=*/true);\r\n\tsfile_write_stash();\r\n}\r\n\r\nvoid SaveLevel(SaveWriter &saveWriter)\r\n{\r\n\tSaveLevel(saveWriter, nullptr);\r\n}\r\n\r\ntl::expected<void, std::string> LoadLevel()\r\n{\r\n\treturn LoadLevel(nullptr);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/loadsave.h",
    "content": "/**\r\n * @file loadsave.h\r\n *\r\n * Interface of save game functionality.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"pfile.h\"\r\n#include \"player.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern DVL_API_FOR_TEST bool gbIsHellfireSaveGame;\r\nextern DVL_API_FOR_TEST uint8_t giNumberOfLevels;\r\n\r\nvoid RemoveInvalidItem(Item &pItem);\r\n_item_indexes RemapItemIdxFromDiablo(_item_indexes i);\r\n_item_indexes RemapItemIdxToDiablo(_item_indexes i);\r\n_item_indexes RemapItemIdxFromSpawn(_item_indexes i);\r\n_item_indexes RemapItemIdxToSpawn(_item_indexes i);\r\nbool IsHeaderValid(uint32_t magicNumber);\r\nvoid LoadHotkeys();\r\nvoid LoadHeroItems(Player &player);\r\n/**\r\n * @brief Remove invalid inventory items from the inventory grid\r\n * @param player The player to remove invalid items from\r\n */\r\nvoid RemoveEmptyInventory(Player &player);\r\n\r\n/**\r\n * @brief Load game state\r\n * @param firstflag Can be set to false if we are simply reloading the current game\r\n */\r\ntl::expected<void, std::string> LoadGame(bool firstflag);\r\nvoid SaveHotkeys(SaveWriter &saveWriter, const Player &player);\r\nvoid SaveHeroItems(SaveWriter &saveWriter, Player &player);\r\nvoid SaveGameData(SaveWriter &saveWriter);\r\nvoid SaveGame();\r\nvoid SaveLevel(SaveWriter &saveWriter);\r\ntl::expected<void, std::string> LoadLevel();\r\ntl::expected<void, std::string> ConvertLevels(SaveWriter &saveWriter);\r\nvoid LoadStash();\r\nvoid SaveStash(SaveWriter &stashWriter);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/autocomplete.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/autocomplete.hpp\"\r\n\r\n#include <algorithm>\r\n#include <cstddef>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <sol/sol.hpp>\r\n#include <sol/utility/to_string.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"lua/lua_global.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstd::string_view GetLastToken(std::string_view text)\r\n{\r\n\tif (text.empty())\r\n\t\treturn {};\r\n\tsize_t i = text.size();\r\n\twhile (i > 0 && text[i - 1] != ' ' && text[i - 1] != '(' && text[i - 1] != ',')\r\n\t\t--i;\r\n\treturn text.substr(i);\r\n}\r\n\r\nstruct ValueInfo {\r\n\tbool callable = false;\r\n\tstd::string signature;\r\n\tstd::string docstring;\r\n};\r\n\r\nsol::protected_function LoadLuaFunctionSignatureGetter(sol::state &lua)\r\n{\r\n\ttl::expected<AssetData, std::string> src = LoadAsset(\"lua_internal\\\\get_lua_function_signature.lua\");\r\n\tif (!src.has_value()) {\r\n\t\tapp_fatal(src.error());\r\n\t}\r\n\tconst sol::object obj = SafeCallResult(lua.safe_script(std::string_view(src.value())), /*optional=*/false);\r\n\tif (obj.get_type() != sol::type::function) {\r\n\t\tapp_fatal(\"Lua: expected a function\");\r\n\t}\r\n\treturn obj.as<sol::protected_function>();\r\n}\r\n\r\nstd::string GetNativeLuaFunctionSignature(const sol::object &fn)\r\n{\r\n\tsol::state &lua = GetLuaState();\r\n\tconstexpr std::string_view LuaFunctionSignatureGetterKey = \"__DEVILUTIONX_GET_LUA_SIGNATURE\";\r\n\tsol::object getter = lua[LuaFunctionSignatureGetterKey];\r\n\tif (getter.get_type() == sol::type::lua_nil) {\r\n\t\tgetter = lua[LuaFunctionSignatureGetterKey] = LoadLuaFunctionSignatureGetter(lua);\r\n\t}\r\n\tconst sol::object obj = SafeCallResult(getter.as<sol::protected_function>()(fn), /*optional=*/false);\r\n\tif (obj.get_type() != sol::type::string) {\r\n\t\tapp_fatal(StrCat(\"Lua: Expected a string, got \", sol::utility::to_string(obj)));\r\n\t}\r\n\treturn obj.as<std::string>();\r\n}\r\n\r\nstd::string GetFunctionSignature(const sol::object &value)\r\n{\r\n\tvalue.push(value.lua_state());\r\n\tconst bool isC = lua_iscfunction(value.lua_state(), -1) != 0;\r\n\tlua_pop(value.lua_state(), 1);\r\n\treturn isC ? \"(...)\" : GetNativeLuaFunctionSignature(value);\r\n}\r\n\r\nvoid RemoveFirstArgumentFromFunctionSignature(std::string &signature)\r\n{\r\n\tif (signature == \"(...)\") return;\r\n\tsize_t firstArgEnd = signature.find_first_of(\",)\");\r\n\tif (firstArgEnd == std::string::npos) return;\r\n\t++firstArgEnd;\r\n\tif (firstArgEnd == signature.size()) {\r\n\t\tsignature = \"()\";\r\n\t\treturn;\r\n\t}\r\n\tif (signature[firstArgEnd] == ' ') ++firstArgEnd;\r\n\tsignature.replace(0, firstArgEnd, \"(\");\r\n}\r\n\r\nValueInfo GetValueInfo(const sol::table &table, std::string_view key, const sol::object &value)\r\n{\r\n\tValueInfo info;\r\n\tif (std::optional<std::string> signature = GetSignature(table, key); signature.has_value()) {\r\n\t\tinfo.signature = *std::move(signature);\r\n\t}\r\n\tif (std::optional<std::string> docstring = GetDocstring(table, key); docstring.has_value()) {\r\n\t\tinfo.docstring = *std::move(docstring);\r\n\t}\r\n\tif (value.get_type() == sol::type::function) {\r\n\t\tinfo.callable = true;\r\n\t\tif (info.signature.empty()) info.signature = GetFunctionSignature(value);\r\n\t\treturn info;\r\n\t}\r\n\tif (!value.is<sol::table>()) return info;\r\n\tconst auto valueAsTable = value.as<sol::table>();\r\n\tconst auto metatable = valueAsTable.get<std::optional<sol::object>>(sol::metatable_key);\r\n\tif (!metatable || !metatable->is<sol::table>())\r\n\t\treturn info;\r\n\tconst auto metatableTbl = metatable->as<sol::table>();\r\n\tconst auto callFn = metatableTbl.get<std::optional<sol::object>>(sol::meta_function::call);\r\n\tinfo.callable = callFn.has_value();\r\n\tif (info.callable && info.signature.empty()) {\r\n\t\tif (info.signature.empty()) {\r\n\t\t\tinfo.signature = GetFunctionSignature(*callFn);\r\n\t\t\t// Remove the first argument (the table passed to `__call`):\r\n\t\t\tRemoveFirstArgumentFromFunctionSignature(info.signature);\r\n\t\t}\r\n\t}\r\n\treturn info;\r\n}\r\n\r\nValueInfo GetValueInfoForUserdata(const sol::userdata &obj, std::string_view key, const sol::object &value, std::optional<LuaUserdataMemberType> memberType)\r\n{\r\n\tValueInfo info;\r\n\tif (value.get_type() == sol::type::userdata) {\r\n\t\tinfo.callable = false;\r\n\t\treturn info;\r\n\t}\r\n\r\n\tif (std::optional<std::string> signature = GetLuaUserdataSignature(obj, key); signature.has_value()) {\r\n\t\tinfo.signature = *std::move(signature);\r\n\t}\r\n\tif (std::optional<std::string> docstring = GetLuaUserdataDocstring(obj, key); docstring.has_value()) {\r\n\t\tinfo.docstring = *std::move(docstring);\r\n\t}\r\n\tif (memberType.has_value()) {\r\n\t\tinfo.callable = *memberType == LuaUserdataMemberType::MemberFunction;\r\n\t} else {\r\n\t\tinfo.callable = value.get_type() == sol::type::function;\r\n\t}\r\n\treturn info;\r\n}\r\n\r\nstruct UserdataQuery {\r\n\tconst sol::userdata *obj;\r\n\tbool colonAccess;\r\n};\r\n\r\nvoid SuggestionsFromTable(const sol::table &table, std::string_view prefix,\r\n    size_t maxSuggestions, ankerl::unordered_dense::set<LuaAutocompleteSuggestion> &out,\r\n    std::optional<UserdataQuery> userdataQuery = std::nullopt)\r\n{\r\n\tfor (const auto &[key, value] : table) {\r\n\t\tif (key.get_type() == sol::type::string) {\r\n\t\t\tstd::string keyStr = key.as<std::string>();\r\n\t\t\tif (!keyStr.starts_with(prefix) || keyStr.size() == prefix.size())\r\n\t\t\t\tcontinue;\r\n\t\t\tif (keyStr.starts_with(\"__\") && !prefix.starts_with(\"__\"))\r\n\t\t\t\tcontinue;\r\n\t\t\t// sol-internal keys -- we don't have fonts for these so skip them.\r\n\t\t\tif (keyStr.find(\"♻\") != std::string::npos\r\n\t\t\t    || keyStr.find(\"☢\") != std::string::npos\r\n\t\t\t    || keyStr.find(\"🔩\") != std::string::npos)\r\n\t\t\t\tcontinue;\r\n\t\t\tValueInfo info;\r\n\t\t\tstd::optional<LuaUserdataMemberType> memberType;\r\n\t\t\tif (userdataQuery.has_value()) {\r\n\t\t\t\tmemberType = GetLuaUserdataMemberType(*userdataQuery->obj, keyStr, value);\r\n\t\t\t\tconst bool requiresColonAccess = memberType.has_value()\r\n\t\t\t\t    ? *memberType == LuaUserdataMemberType::MemberFunction\r\n\t\t\t\t    : value.get_type() == sol::type::function;\r\n\t\t\t\tif (userdataQuery->colonAccess != requiresColonAccess) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tinfo = GetValueInfoForUserdata(*userdataQuery->obj, keyStr, value, memberType);\r\n\t\t\t} else {\r\n\t\t\t\tinfo = GetValueInfo(table, keyStr, value);\r\n\t\t\t}\r\n\t\t\tstd::string completionText = keyStr.substr(prefix.size());\r\n\t\t\tLuaAutocompleteSuggestion suggestion { std::move(keyStr), std::move(completionText) };\r\n\t\t\tif (info.callable) {\r\n\t\t\t\tsuggestion.completionText.append(\"()\");\r\n\t\t\t\tsuggestion.cursorAdjust = -1;\r\n\t\t\t}\r\n\t\t\tif (!info.signature.empty()) {\r\n\t\t\t\tif (memberType.has_value() && memberType != LuaUserdataMemberType::MemberFunction) {\r\n\t\t\t\t\tStrAppend(suggestion.displayText, \": \");\r\n\t\t\t\t}\r\n\t\t\t\tStrAppend(suggestion.displayText, info.signature);\r\n\t\t\t}\r\n\t\t\tif (!info.docstring.empty()) {\r\n\t\t\t\tstd::string_view firstLine = info.docstring;\r\n\t\t\t\tif (const size_t newlinePos = firstLine.find('\\n'); newlinePos != std::string_view::npos) {\r\n\t\t\t\t\tfirstLine = firstLine.substr(0, newlinePos);\r\n\t\t\t\t}\r\n\t\t\t\tStrAppend(suggestion.displayText, \" - \", firstLine);\r\n\t\t\t}\r\n\t\t\tout.insert(std::move(suggestion));\r\n\t\t\tif (out.size() == maxSuggestions)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tconst auto fallback = table.get<std::optional<sol::object>>(sol::metatable_key);\r\n\tif (fallback.has_value() && fallback->get_type() == sol::type::table) {\r\n\t\tSuggestionsFromTable(fallback->as<sol::table>(), prefix, maxSuggestions, out);\r\n\t}\r\n}\r\n\r\nvoid SuggestionsFromUserdata(UserdataQuery query, std::string_view prefix,\r\n    size_t maxSuggestions, ankerl::unordered_dense::set<LuaAutocompleteSuggestion> &out)\r\n{\r\n\tconst auto &meta = query.obj->get<std::optional<sol::object>>(sol::metatable_key);\r\n\tif (meta.has_value() && meta->get_type() == sol::type::table) {\r\n\t\tSuggestionsFromTable(meta->as<sol::table>(), prefix, maxSuggestions, out, query);\r\n\t}\r\n}\r\n\r\nbool IsAlnum(char c)\r\n{\r\n\treturn (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');\r\n}\r\n\r\nbool IsIdentifierChar(char c)\r\n{\r\n\treturn IsAlnum(c) || c == '_';\r\n}\r\n\r\nbool IsIdentifierOrExprChar(char c)\r\n{\r\n\treturn IsIdentifierChar(c) || c == '-' || c == '+' || c == '*' || c == '/' || c == '=';\r\n}\r\n\r\n} // namespace\r\n\r\nvoid GetLuaAutocompleteSuggestions(std::string_view text, size_t cursorPos, const sol::environment &lua,\r\n    size_t maxSuggestions, std::vector<LuaAutocompleteSuggestion> &out)\r\n{\r\n\tout.clear();\r\n\tconst std::string_view textPrefix = text.substr(0, cursorPos);\r\n\tif (textPrefix.empty()) return;\r\n\tconst std::string_view textSuffix = text.substr(cursorPos);\r\n\tif (!textSuffix.empty()) {\r\n\t\tconst char c = textSuffix[0];\r\n\t\tif (IsIdentifierOrExprChar(c) || (c == ' ' && textSuffix.size() > 1)) return;\r\n\t}\r\n\tif (textPrefix.size() >= 2 && textPrefix.back() == ' ' && IsIdentifierChar(textPrefix[textPrefix.size() - 2])) {\r\n\t\treturn;\r\n\t}\r\n\tstd::string_view token = GetLastToken(textPrefix);\r\n\tconst char prevChar = token.data() == textPrefix.data() ? '\\0' : *(token.data() - 1);\r\n\tif (prevChar == '(' || prevChar == ',') return;\r\n\tconst size_t dotPos = token.find_last_of(\".:\");\r\n\tconst std::string_view prefix = token.substr(dotPos + 1);\r\n\tconst char completionChar = dotPos != std::string_view::npos ? token[dotPos] : '\\0';\r\n\ttoken.remove_suffix(token.size() - (dotPos == std::string_view::npos ? 0 : dotPos));\r\n\r\n\tankerl::unordered_dense::set<LuaAutocompleteSuggestion> suggestions;\r\n\tconst auto addSuggestions = [&](const sol::table &table) {\r\n\t\tSuggestionsFromTable(table, prefix, maxSuggestions, suggestions);\r\n\t};\r\n\r\n\tif (token.empty()) {\r\n\t\tif (prevChar == '.') return;\r\n\t\taddSuggestions(lua);\r\n\t\tconst auto fallback = lua.get<std::optional<sol::object>>(\"_G\");\r\n\t\tif (fallback.has_value() && fallback->get_type() == sol::type::table) {\r\n\t\t\taddSuggestions(fallback->as<sol::table>());\r\n\t\t}\r\n\t} else {\r\n\t\tstd::optional<sol::object> obj = lua;\r\n\t\tfor (const std::string_view partDot : SplitByChar(token, '.')) {\r\n\t\t\tfor (const std::string_view part : SplitByChar(partDot, ':')) {\r\n\t\t\t\tobj = obj->as<sol::table>().get<std::optional<sol::object>>(part);\r\n\t\t\t\tif (!obj.has_value() || !(obj->get_type() == sol::type::table || obj->get_type() == sol::type::userdata)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (obj->get_type() == sol::type::table) {\r\n\t\t\taddSuggestions(obj->as<sol::table>());\r\n\t\t} else if (obj->get_type() == sol::type::userdata) {\r\n\t\t\tconst sol::userdata &data = obj->as<sol::userdata>();\r\n\t\t\tSuggestionsFromUserdata(UserdataQuery { .obj = &data, .colonAccess = completionChar == ':' },\r\n\t\t\t    prefix, maxSuggestions, suggestions);\r\n\t\t}\r\n\t}\r\n\r\n\tout.insert(out.end(), suggestions.begin(), suggestions.end());\r\n\tc_sort(out);\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/autocomplete.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <cstddef>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <sol/forward.hpp>\r\n\r\nnamespace devilution {\r\n\r\nstruct LuaAutocompleteSuggestion {\r\n\tstd::string displayText;\r\n\tstd::string completionText;\r\n\tint cursorAdjust = 0;\r\n\r\n\tbool operator==(const LuaAutocompleteSuggestion &other) const\r\n\t{\r\n\t\treturn displayText == other.displayText;\r\n\t}\r\n\r\n\tbool operator<(const LuaAutocompleteSuggestion &other) const\r\n\t{\r\n\t\treturn displayText < other.displayText;\r\n\t}\r\n};\r\n\r\nvoid GetLuaAutocompleteSuggestions(\r\n    std::string_view text, size_t cursorPos, const sol::environment &lua,\r\n    size_t maxSuggestions, std::vector<LuaAutocompleteSuggestion> &out);\r\n\r\n} // namespace devilution\r\n\r\nnamespace std {\r\ntemplate <>\r\nstruct hash<devilution::LuaAutocompleteSuggestion> {\r\n\tsize_t operator()(const devilution::LuaAutocompleteSuggestion &suggestion) const\r\n\t{\r\n\t\treturn hash<std::string>()(suggestion.displayText);\r\n\t}\r\n};\r\n} // namespace std\r\n\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/lua_event.cpp",
    "content": "#include \"lua/lua_event.hpp\"\r\n\r\n#include <optional>\r\n#include <string_view>\r\n#include <utility>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"lua/lua_global.hpp\"\r\n#include \"monster.h\"\r\n#include \"player.h\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace lua {\r\n\r\ntemplate <typename... Args>\r\nvoid CallLuaEvent(std::string_view name, Args &&...args)\r\n{\r\n\tsol::table *events = GetLuaEvents();\r\n\tif (events == nullptr) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst auto trigger = events->traverse_get<std::optional<sol::object>>(name, \"trigger\");\r\n\tif (!trigger.has_value() || !trigger->is<sol::protected_function>()) {\r\n\t\tLogError(\"events.{}.trigger is not a function\", name);\r\n\t\treturn;\r\n\t}\r\n\tconst sol::protected_function fn = trigger->as<sol::protected_function>();\r\n\tSafeCallResult(fn(std::forward<Args>(args)...), /*optional=*/true);\r\n}\r\n\r\ntemplate <typename T, typename... Args>\r\nT CallLuaEventReturn(T defaultValue, std::string_view name, Args &&...args)\r\n{\r\n\tsol::table *events = GetLuaEvents();\r\n\tif (events == nullptr) {\r\n\t\treturn defaultValue;\r\n\t}\r\n\r\n\tconst auto trigger = events->traverse_get<std::optional<sol::object>>(name, \"trigger\");\r\n\tif (!trigger.has_value() || !trigger->is<sol::protected_function>()) {\r\n\t\treturn defaultValue;\r\n\t}\r\n\tconst sol::protected_function fn = trigger->as<sol::protected_function>();\r\n\tsol::object result = SafeCallResult(fn(std::forward<Args>(args)...), /*optional=*/true);\r\n\tif (result.is<T>()) {\r\n\t\treturn result.as<T>();\r\n\t}\r\n\treturn defaultValue;\r\n}\r\n\r\nvoid MonsterDataLoaded()\r\n{\r\n\tCallLuaEvent(\"MonsterDataLoaded\");\r\n}\r\nvoid UniqueMonsterDataLoaded()\r\n{\r\n\tCallLuaEvent(\"UniqueMonsterDataLoaded\");\r\n}\r\nvoid ItemDataLoaded()\r\n{\r\n\tCallLuaEvent(\"ItemDataLoaded\");\r\n}\r\nvoid UniqueItemDataLoaded()\r\n{\r\n\tCallLuaEvent(\"UniqueItemDataLoaded\");\r\n}\r\n\r\nvoid StoreOpened(std::string_view name)\r\n{\r\n\tCallLuaEvent(\"StoreOpened\", name);\r\n}\r\n\r\nvoid OnMonsterTakeDamage(const Monster *monster, int damage, int damageType)\r\n{\r\n\tCallLuaEvent(\"OnMonsterTakeDamage\", monster, damage, damageType);\r\n}\r\n\r\nvoid OnPlayerGainExperience(const Player *player, uint32_t exp)\r\n{\r\n\tCallLuaEvent(\"OnPlayerGainExperience\", player, exp);\r\n}\r\nvoid OnPlayerTakeDamage(const Player *player, int damage, int damageType)\r\n{\r\n\tCallLuaEvent(\"OnPlayerTakeDamage\", player, damage, damageType);\r\n}\r\n\r\nvoid LoadModsComplete()\r\n{\r\n\tCallLuaEvent(\"LoadModsComplete\");\r\n}\r\nvoid GameDrawComplete()\r\n{\r\n\tCallLuaEvent(\"GameDrawComplete\");\r\n}\r\nvoid GameStart()\r\n{\r\n\tCallLuaEvent(\"GameStart\");\r\n}\r\n\r\n} // namespace lua\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/lua_event.hpp",
    "content": "#pragma once\n\n#include <cstdint>\n#include <string_view>\n\nnamespace devilution {\n\nstruct Player;\nstruct Monster;\n\nnamespace lua {\n\nvoid MonsterDataLoaded();\nvoid UniqueMonsterDataLoaded();\nvoid ItemDataLoaded();\nvoid UniqueItemDataLoaded();\n\nvoid StoreOpened(std::string_view name);\n\nvoid OnMonsterTakeDamage(const Monster *monster, int damage, int damageType);\n\nvoid OnPlayerGainExperience(const Player *player, uint32_t exp);\nvoid OnPlayerTakeDamage(const Player *player, int damage, int damageType);\n\nvoid LoadModsComplete();\nvoid GameDrawComplete();\nvoid GameStart();\n\n} // namespace lua\n\n} // namespace devilution\n"
  },
  {
    "path": "Source/lua/lua_global.cpp",
    "content": "#include \"lua/lua_global.hpp\"\r\n\r\n#include <optional>\r\n#include <string_view>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <sol/debug.hpp>\r\n#include <sol/sol.hpp>\r\n\r\n#include <config.h>\r\n\r\n#include \"appfat.h\"\r\n#include \"effects.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"lua/modules/audio.hpp\"\r\n#include \"lua/modules/floatingnumbers.hpp\"\r\n#include \"lua/modules/hellfire.hpp\"\r\n#include \"lua/modules/i18n.hpp\"\r\n#include \"lua/modules/items.hpp\"\r\n#include \"lua/modules/log.hpp\"\r\n#include \"lua/modules/monsters.hpp\"\r\n#include \"lua/modules/player.hpp\"\r\n#include \"lua/modules/render.hpp\"\r\n#include \"lua/modules/system.hpp\"\r\n#include \"lua/modules/towners.hpp\"\r\n#include \"monster.h\"\r\n#include \"options.h\"\r\n#include \"player.h\"\r\n#include \"plrmsg.h\"\r\n#include \"utils/console.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef _DEBUG\r\n#include \"lua/modules/dev.hpp\"\r\n#include \"lua/repl.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct LuaState {\r\n\tsol::state sol = {};\r\n\tsol::table commonPackages = {};\r\n\tankerl::unordered_dense::segmented_map<std::string, sol::bytecode> compiledScripts = {};\r\n\tsol::environment sandbox = {};\r\n\tsol::table events = {};\r\n};\r\n\r\nstd::optional<LuaState> CurrentLuaState;\r\n\r\nstd::vector<tl::function_ref<void()>> IsModChangeHandlers;\r\n\r\n// A Lua function that we use to generate a `require` implementation.\r\nconstexpr std::string_view RequireGenSrc = R\"lua(\r\nfunction requireGen(env, loaded, loadFn)\r\n  return function(packageName)\r\n      local p = loaded[packageName]\r\n      if p == nil then\r\n          local loader = loadFn(packageName)\r\n          if type(loader) == \"string\" then\r\n            error(loader)\r\n          end\r\n          setEnvironment(env, loader)\r\n          p = loader(packageName)\r\n          loaded[packageName] = p\r\n      end\r\n      return p\r\n  end\r\nend\r\n)lua\";\r\n\r\nsol::object LuaLoadScriptFromAssets(std::string_view packageName)\r\n{\r\n\tLuaState &luaState = *CurrentLuaState;\r\n\tconstexpr std::string_view PathPrefix = \"lua\\\\\";\r\n\tconstexpr std::string_view PathSuffix = \".lua\";\r\n\tstd::string path;\r\n\tpath.reserve(PathPrefix.size() + packageName.size() + PathSuffix.size());\r\n\tStrAppend(path, PathPrefix, packageName, PathSuffix);\r\n\tstd::replace(path.begin() + PathPrefix.size(), path.end() - PathSuffix.size(), '.', '\\\\');\r\n\r\n\tauto iter = luaState.compiledScripts.find(path);\r\n\tif (iter != luaState.compiledScripts.end()) {\r\n\t\treturn luaState.sol.load(iter->second.as_string_view(), path, sol::load_mode::binary);\r\n\t}\r\n\r\n\ttl::expected<AssetData, std::string> assetData = LoadAsset(path);\r\n\tif (!assetData.has_value()) {\r\n\t\tsol::stack::push(luaState.sol.lua_state(), assetData.error());\r\n\t\treturn sol::stack_object(luaState.sol.lua_state(), -1);\r\n\t}\r\n\tconst sol::load_result result = luaState.sol.load(std::string_view(*assetData), path, sol::load_mode::text);\r\n\tif (!result.valid()) {\r\n\t\tsol::stack::push(luaState.sol.lua_state(),\r\n\t\t    StrCat(\"Lua error when loading \", path, \": \", result.get<std::string>()));\r\n\t\treturn sol::stack_object(luaState.sol.lua_state(), -1);\r\n\t}\r\n\tconst sol::function fn = result;\r\n\tluaState.compiledScripts[path] = fn.dump();\r\n\treturn result;\r\n}\r\n\r\nint LuaPrint(lua_State *state)\r\n{\r\n\tconst int n = lua_gettop(state);\r\n\tfor (int i = 1; i <= n; i++) {\r\n\t\tsize_t l;\r\n\t\tconst char *s = luaL_tolstring(state, i, &l);\r\n\t\tif (i > 1)\r\n\t\t\tprintInConsole(\"\\t\");\r\n\t\tprintInConsole(std::string_view(s, l));\r\n\t\tlua_pop(state, 1);\r\n\t}\r\n\tprintNewlineInConsole();\r\n\treturn 0;\r\n}\r\n\r\nvoid LuaWarn(void *userData, const char *message, int continued)\r\n{\r\n\tstatic std::string warnBuffer;\r\n\twarnBuffer.append(message);\r\n\tif (continued != 0)\r\n\t\treturn;\r\n\tLogWarn(\"{}\", warnBuffer);\r\n\twarnBuffer.clear();\r\n}\r\n\r\nsol::object RunScript(std::optional<sol::environment> env, std::string_view packageName, bool optional)\r\n{\r\n\tconst sol::object result = LuaLoadScriptFromAssets(packageName);\r\n\t// We return a string on error:\r\n\tif (result.get_type() == sol::type::string) {\r\n\t\tif (!optional)\r\n\t\t\tapp_fatal(result.as<std::string>());\r\n\t\tLogInfo(\"{}\", result.as<std::string>());\r\n\t\treturn sol::lua_nil;\r\n\t}\r\n\tauto fn = result.as<sol::protected_function>();\r\n\tif (env.has_value()) {\r\n\t\tsol::set_environment(*env, fn);\r\n\t}\r\n\treturn SafeCallResult(fn(), optional);\r\n}\r\n\r\nvoid LuaPanic(sol::optional<std::string> message)\r\n{\r\n\tLogError(\"Lua is in a panic state and will now abort() the application:\\n{}\",\r\n\t    message.value_or(\"unknown error\"));\r\n}\r\n\r\n} // namespace\r\n\r\nvoid Sol2DebugPrintStack(lua_State *state)\r\n{\r\n\tLogDebug(\"{}\", sol::detail::debug::dump_types(state));\r\n}\r\n\r\nvoid Sol2DebugPrintSection(const std::string &message, lua_State *state)\r\n{\r\n\tLogDebug(\"-- {} -- [ {} ]\", message, sol::detail::debug::dump_types(state));\r\n}\r\n\r\nsol::environment CreateLuaSandbox()\r\n{\r\n\tsol::state &lua = CurrentLuaState->sol;\r\n\tsol::environment sandbox(CurrentLuaState->sol, sol::create);\r\n\r\n\t// Registering globals\r\n\tsandbox.set(\r\n\t    \"print\", LuaPrint,\r\n\t    \"_DEBUG\",\r\n#ifdef _DEBUG\r\n\t    true,\r\n#else\r\n\t    false,\r\n#endif\r\n\t    \"_VERSION\", LUA_VERSION);\r\n\r\n\t// Register safe built-in globals.\r\n\tfor (const std::string_view global : {\r\n\t         // Built-ins:\r\n\t         \"assert\", \"warn\", \"error\", \"ipairs\", \"next\", \"pairs\", \"pcall\",\r\n\t         \"select\", \"tonumber\", \"tostring\", \"type\", \"xpcall\",\r\n\t         \"rawequal\", \"rawget\", \"rawset\", \"setmetatable\",\r\n\t// Built-in packages:\r\n#ifdef _DEBUG\r\n\t         \"debug\",\r\n#endif\r\n\t         \"base\", \"coroutine\", \"table\", \"string\", \"math\", \"utf8\" }) {\r\n\t\tconst sol::object obj = lua[global];\r\n\t\tif (obj.get_type() == sol::type::lua_nil) {\r\n\t\t\tapp_fatal(StrCat(\"Missing Lua global [\", global, \"]\"));\r\n\t\t}\r\n\t\tsandbox[global] = obj;\r\n\t}\r\n\r\n\t// We only allow datetime-related functions from `os`:\r\n\tconst sol::table os = lua[\"os\"];\r\n\tsandbox.create_named(\"os\",\r\n\t    \"date\", os[\"date\"],\r\n\t    \"difftime\", os[\"difftime\"],\r\n\t    \"time\", os[\"time\"]);\r\n\r\n\tsandbox[\"require\"] = lua[\"requireGen\"](sandbox, CurrentLuaState->commonPackages, LuaLoadScriptFromAssets);\r\n\r\n\t// Expose commonly used enums globally for mods\r\n\tsandbox[\"SfxID\"] = lua[\"SfxID\"];\r\n\r\n\treturn sandbox;\r\n}\r\n\r\nvoid AddModsChangedHandler(tl::function_ref<void()> callback)\r\n{\r\n\tIsModChangeHandlers.push_back(callback);\r\n}\r\n\r\nvoid LuaReloadActiveMods()\r\n{\r\n\t// Loaded without a sandbox.\r\n\tCurrentLuaState->events = RunScript(/*env=*/std::nullopt, \"devilutionx.events\", /*optional=*/false);\r\n\tCurrentLuaState->commonPackages[\"devilutionx.events\"] = CurrentLuaState->events;\r\n\r\n\tgbIsHellfire = false;\r\n\tUnloadModArchives();\r\n\r\n\tstd::vector<std::string_view> modnames = GetOptions().Mods.GetActiveModList();\r\n\tLoadModArchives(modnames);\r\n\r\n\tfor (const std::string_view modname : modnames) {\r\n\t\tconst std::string packageName = StrCat(\"mods.\", modname, \".init\");\r\n\t\tRunScript(CreateLuaSandbox(), packageName, /*optional=*/true);\r\n\t}\r\n\r\n\tfor (const tl::function_ref<void()> handler : IsModChangeHandlers) {\r\n\t\thandler();\r\n\t}\r\n\r\n\t// Reload sound effects in case a mod archive overrides effects.tsv\r\n\teffects_cleanup_sfx();\r\n\tif (gbRunGame)\r\n\t\tsound_init();\r\n\telse\r\n\t\tui_sound_init();\r\n\r\n\t// Reload game data (this can probably be done later in the process to avoid having to reload it)\r\n\tLoadTextData();\r\n\tLoadPlayerDataFiles();\r\n\tLoadSpellData();\r\n\tLoadMissileData();\r\n\tLoadMonsterData();\r\n\tLoadItemData();\r\n\tLoadObjectData();\r\n\tLoadQuestData();\r\n\r\n\tlua::LoadModsComplete();\r\n}\r\n\r\nvoid LuaInitialize()\r\n{\r\n\tCurrentLuaState.emplace(LuaState { .sol = { sol::c_call<decltype(&LuaPanic), &LuaPanic> } });\r\n\tsol::state &lua = CurrentLuaState->sol;\r\n\tlua_setwarnf(lua.lua_state(), LuaWarn, /*ud=*/nullptr);\r\n\tlua.open_libraries(\r\n\t    sol::lib::base,\r\n\t    sol::lib::coroutine,\r\n\t    sol::lib::debug,\r\n\t    sol::lib::math,\r\n\t    sol::lib::os,\r\n\t    sol::lib::package,\r\n\t    sol::lib::string,\r\n\t    sol::lib::table,\r\n\t    sol::lib::utf8);\r\n\r\n\t// Registering devilutionx object table\r\n\tSafeCallResult(lua.safe_script(RequireGenSrc), /*optional=*/false);\r\n\r\n\tCurrentLuaState->commonPackages = lua.create_table_with(\r\n#ifdef _DEBUG\r\n\t    \"devilutionx.dev\", LuaDevModule(lua),\r\n#endif\r\n\t    \"devilutionx.version\", PROJECT_VERSION,\r\n\t    \"devilutionx.i18n\", LuaI18nModule(lua),\r\n\t    \"devilutionx.items\", LuaItemModule(lua),\r\n\t    \"devilutionx.log\", LuaLogModule(lua),\r\n\t    \"devilutionx.audio\", LuaAudioModule(lua),\r\n\t    \"devilutionx.monsters\", LuaMonstersModule(lua),\r\n\t    \"devilutionx.player\", LuaPlayerModule(lua),\r\n\t    \"devilutionx.render\", LuaRenderModule(lua),\r\n\t    \"devilutionx.towners\", LuaTownersModule(lua),\r\n\t    \"devilutionx.hellfire\", LuaHellfireModule(lua),\r\n\t    \"devilutionx.system\", LuaSystemModule(lua),\r\n\t    \"devilutionx.floatingnumbers\", LuaFloatingNumbersModule(lua),\r\n\t    \"devilutionx.message\", [](std::string_view text) { EventPlrMsg(text, UiFlags::ColorRed); },\r\n\t    // This package is loaded without a sandbox:\r\n\t    \"inspect\", RunScript(/*env=*/std::nullopt, \"inspect\", /*optional=*/false));\r\n\r\n\t// Used by the custom require implementation.\r\n\tlua[\"setEnvironment\"] = [](const sol::environment &env, const sol::function &fn) { sol::set_environment(env, fn); };\r\n\r\n\tfor (OptionEntryBase *mod : GetOptions().Mods.GetEntries()) {\r\n\t\tmod->SetValueChangedCallback(LuaReloadActiveMods);\r\n\t}\r\n\r\n\tLuaReloadActiveMods();\r\n}\r\n\r\nvoid LuaShutdown()\r\n{\r\n#ifdef _DEBUG\r\n\tLuaReplShutdown();\r\n#endif\r\n\tCurrentLuaState = std::nullopt;\r\n}\r\n\r\nsol::table *GetLuaEvents()\r\n{\r\n\treturn CurrentLuaState ? &CurrentLuaState->events : nullptr;\r\n}\r\n\r\nsol::state &GetLuaState()\r\n{\r\n\treturn CurrentLuaState->sol;\r\n}\r\n\r\nsol::object SafeCallResult(sol::protected_function_result result, bool optional)\r\n{\r\n\tconst bool valid = result.valid();\r\n\tif (!valid) {\r\n\t\tconst std::string error = result.get_type() == sol::type::string\r\n\t\t    ? StrCat(\"Lua error: \", result.get<std::string>())\r\n\t\t    : \"Unknown Lua error\";\r\n\t\tif (!optional)\r\n\t\t\tapp_fatal(error);\r\n\t\tLogError(error);\r\n\t}\r\n\treturn result;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/lua_global.hpp",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\n#include <expected.hpp>\r\n#include <function_ref.hpp>\r\n#include <sol/forward.hpp>\r\n\r\nnamespace devilution {\r\n\r\nvoid LuaInitialize();\r\nvoid LuaReloadActiveMods();\r\nvoid LuaShutdown();\r\n\r\nsol::state &GetLuaState();\r\nsol::environment CreateLuaSandbox();\r\nsol::object SafeCallResult(sol::protected_function_result result, bool optional);\r\nsol::table *GetLuaEvents();\r\n\r\n/** Adds a handler to be called when mods status changes after the initial startup. */\r\nvoid AddModsChangedHandler(tl::function_ref<void()> callback);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/metadoc.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nenum class LuaUserdataMemberType : uint8_t {\r\n\tReadonlyProperty,\r\n\tProperty,\r\n\tMemberFunction,\r\n\tConstructor,\r\n};\r\n\r\ninline std::string LuaSignatureKey(std::string_view key)\r\n{\r\n\treturn StrCat(\"__sig_\", key);\r\n}\r\n\r\ninline std::string LuaDocstringKey(std::string_view key)\r\n{\r\n\treturn StrCat(\"__doc_\", key);\r\n}\r\n\r\ninline std::string LuaUserdataMemberTypeKey(std::string_view key)\r\n{\r\n\treturn StrCat(\"__udt_\", key);\r\n}\r\n\r\nnamespace lua_metadoc_internal {\r\ntemplate <typename U>\r\nvoid SetUsertypeSignatureAndDocstring(sol::usertype<U> &table, std::string_view key, const char *signature, const char *doc, LuaUserdataMemberType memberType)\r\n{\r\n\ttable.set(LuaSignatureKey(key), sol::var(signature));\r\n\ttable.set(LuaDocstringKey(key), sol::var(doc));\r\n\ttable.set(LuaUserdataMemberTypeKey(key), sol::var(static_cast<uint8_t>(memberType)));\r\n}\r\n\r\ninline void SetSignatureAndDocstring(sol::table &table, std::string_view key, const char *signature, const char *doc)\r\n{\r\n\ttable.set(LuaSignatureKey(key), signature);\r\n\ttable.set(LuaDocstringKey(key), doc);\r\n}\r\n} // namespace lua_metadoc_internal\r\n\r\ntemplate <typename U, typename T>\r\nvoid LuaSetDocFn(sol::usertype<U> &table, std::string_view key, const char *signature, const char *doc, T &&value)\r\n{\r\n\ttable.set_function(key, std::forward<T>(value));\r\n\tlua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, signature, doc, LuaUserdataMemberType::MemberFunction);\r\n}\r\n\r\ntemplate <typename U, typename G>\r\nvoid LuaSetDocReadonlyProperty(sol::usertype<U> &table, std::string_view key, const char *type, const char *doc, G &&getter)\r\n{\r\n\ttable.set(key, sol::readonly_property(std::forward<G>(getter)));\r\n\tlua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::ReadonlyProperty);\r\n}\r\n\r\ntemplate <typename U, typename G, typename S>\r\nvoid LuaSetDocProperty(sol::usertype<U> &table, std::string_view key, const char *type, const char *doc, G &&getter, S &&setter)\r\n{\r\n\ttable.set(key, sol::property(std::forward<G>(getter), std::forward<S>(setter)));\r\n\tlua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::Property);\r\n}\r\n\r\ntemplate <typename U, typename F>\r\nvoid LuaSetDocProperty(sol::usertype<U> &table, std::string_view key, const char *type, const char *doc, F U::*&&value)\r\n{\r\n\ttable.set(key, value);\r\n\tlua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::Property);\r\n}\r\n\r\ntemplate <typename T>\r\nvoid LuaSetDoc(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value)\r\n{\r\n\ttable.set(key, std::forward<T>(value));\r\n\tlua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc);\r\n}\r\n\r\ntemplate <typename T>\r\nvoid LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value)\r\n{\r\n\ttable.set_function(key, std::forward<T>(value));\r\n\tlua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc);\r\n}\r\n\r\ntemplate <typename T>\r\nvoid LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, T &&value)\r\n{\r\n\ttable.set_function(key, std::forward<T>(value));\r\n\ttable.set(LuaSignatureKey(key), signature);\r\n}\r\n\r\ninline std::optional<std::string> GetSignature(const sol::table &table, std::string_view key)\r\n{\r\n\treturn table.get<std::optional<std::string>>(LuaSignatureKey(key));\r\n}\r\n\r\ninline std::optional<std::string> GetDocstring(const sol::table &table, std::string_view key)\r\n{\r\n\treturn table.get<std::optional<std::string>>(LuaDocstringKey(key));\r\n}\r\n\r\ninline std::optional<std::string> GetLuaUserdataSignature(const sol::userdata &obj, std::string_view key)\r\n{\r\n\treturn obj.get<std::optional<std::string>>(LuaSignatureKey(key));\r\n}\r\n\r\ninline std::optional<std::string> GetLuaUserdataDocstring(const sol::userdata &obj, std::string_view key)\r\n{\r\n\treturn obj.get<std::optional<std::string>>(LuaDocstringKey(key));\r\n}\r\n\r\ninline std::optional<LuaUserdataMemberType> GetLuaUserdataMemberType(const sol::userdata &obj, std::string_view key, const sol::object &value)\r\n{\r\n\tstd::optional<uint8_t> result = obj.get<std::optional<uint8_t>>(LuaUserdataMemberTypeKey(key));\r\n\tif (!result.has_value()) {\r\n\t\tif (value.get_type() == sol::type::userdata) return LuaUserdataMemberType::Property;\r\n\t\tif (value.get_type() == sol::type::function && key == \"new\") return LuaUserdataMemberType::Constructor;\r\n\t\treturn std::nullopt;\r\n\t}\r\n\treturn static_cast<LuaUserdataMemberType>(*result);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/audio.cpp",
    "content": "#include \"lua/modules/audio.hpp\"\r\n\r\n#include <magic_enum/magic_enum.hpp>\r\n#include <sol/sol.hpp>\r\n\r\n#include \"effects.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"sound_effect_enums.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nbool IsValidSfx(int16_t psfx)\r\n{\r\n\treturn psfx >= 0 && psfx <= static_cast<int16_t>(SfxID::LAST);\r\n}\r\n\r\nvoid RegisterSfxIDEnum(sol::state_view &lua)\r\n{\r\n\tconstexpr auto enumValues = magic_enum::enum_values<SfxID>();\r\n\tsol::table enumTable = lua.create_table();\r\n\tfor (const auto enumValue : enumValues) {\r\n\t\tconst std::string_view name = magic_enum::enum_name(enumValue);\r\n\t\tif (!name.empty() && name != \"LAST\" && name != \"None\") {\r\n\t\t\tenumTable[name] = static_cast<int16_t>(enumValue);\r\n\t\t}\r\n\t}\r\n\t// Add LAST and None explicitly\r\n\tenumTable[\"LAST\"] = static_cast<int16_t>(SfxID::LAST);\r\n\tenumTable[\"None\"] = static_cast<int16_t>(SfxID::None);\r\n\tlua[\"SfxID\"] = enumTable;\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaAudioModule(sol::state_view &lua)\r\n{\r\n\tRegisterSfxIDEnum(lua);\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table,\r\n\t    \"playSfx\", \"(id: number)\",\r\n\t    [](int16_t psfx) { if (IsValidSfx(psfx)) PlaySFX(static_cast<SfxID>(psfx)); });\r\n\tLuaSetDocFn(table,\r\n\t    \"playSfxLoc\", \"(id: number, x: number, y: number)\",\r\n\t    [](int16_t psfx, int x, int y) { if (IsValidSfx(psfx)) PlaySfxLoc(static_cast<SfxID>(psfx), { x, y }); });\r\n\t// Expose SfxID enum through the module table\r\n\ttable[\"SfxID\"] = lua[\"SfxID\"];\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/audio.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaAudioModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/dev/display.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/display.hpp\"\r\n\r\n#include <array>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"debug.h\"\r\n#include \"lighting.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstd::string DebugCmdShowGrid(std::optional<bool> on)\r\n{\r\n\tDebugGrid = on.value_or(!DebugGrid);\r\n\treturn StrCat(\"Tile grid highlighting: \", DebugGrid ? \"On\" : \"Off\");\r\n}\r\n\r\nstd::string DebugCmdVision(std::optional<bool> on)\r\n{\r\n\tDebugVision = on.value_or(!DebugVision);\r\n\treturn StrCat(\"Vision highlighting: \", DebugVision ? \"On\" : \"Off\");\r\n}\r\n\r\nstd::string DebugCmdPath(std::optional<bool> on)\r\n{\r\n\tDebugPath = on.value_or(!DebugPath);\r\n\treturn StrCat(\"Path highlighting: \", DebugPath ? \"On\" : \"Off\");\r\n}\r\n\r\nstd::string DebugCmdFullbright(std::optional<bool> on)\r\n{\r\n\tToggleLighting();\r\n\treturn StrCat(\"Fullbright: \", DisableLighting ? \"On\" : \"Off\");\r\n}\r\n\r\nstd::string DebugCmdShowTileData(std::optional<std::string_view> dataType)\r\n{\r\n\tstatic const std::array<std::string_view, 23> DataTypes {\r\n\t\t\"microTiles\",\r\n\t\t\"dPiece\",\r\n\t\t\"dTransVal\",\r\n\t\t\"dLight\",\r\n\t\t\"dPreLight\",\r\n\t\t\"dFlags\",\r\n\t\t\"dPlayer\",\r\n\t\t\"dMonster\",\r\n\t\t\"missiles\",\r\n\t\t\"dCorpse\",\r\n\t\t\"dObject\",\r\n\t\t\"dItem\",\r\n\t\t\"dSpecial\",\r\n\t\t\"coords\",\r\n\t\t\"cursorcoords\",\r\n\t\t\"objectindex\",\r\n\t\t\"solid\",\r\n\t\t\"transparent\",\r\n\t\t\"trap\",\r\n\t\t\"AutomapView\",\r\n\t\t\"dungeon\",\r\n\t\t\"pdungeon\",\r\n\t\t\"Protected\",\r\n\t};\r\n\tif (!dataType.has_value()) {\r\n\t\tstd::string result = \"Valid values for the first argument:\\nclear\";\r\n\t\tfor (const std::string_view &str : DataTypes)\r\n\t\t\tStrAppend(result, \", \", str);\r\n\t\treturn result;\r\n\t}\r\n\tif (*dataType == \"clear\") {\r\n\t\tSetDebugGridTextType(DebugGridTextItem::None);\r\n\t\treturn \"Tile data cleared.\";\r\n\t}\r\n\tbool found = false;\r\n\tint index = 0;\r\n\tfor (const std::string_view &param : DataTypes) {\r\n\t\tindex++;\r\n\t\tif (*dataType != param)\r\n\t\t\tcontinue;\r\n\t\tfound = true;\r\n\t\tauto newGridText = static_cast<DebugGridTextItem>(index);\r\n\t\tif (newGridText == GetDebugGridTextType()) {\r\n\t\t\tSetDebugGridTextType(DebugGridTextItem::None);\r\n\t\t\treturn \"Tile data: Off\";\r\n\t\t}\r\n\t\tSetDebugGridTextType(newGridText);\r\n\t\tbreak;\r\n\t}\r\n\tif (!found) {\r\n\t\tstd::string result = \"Invalid name! Valid names are:\\nclear\";\r\n\t\tfor (const std::string_view &str : DataTypes)\r\n\t\t\tStrAppend(result, \", \", str);\r\n\t\treturn result;\r\n\t}\r\n\r\n\treturn \"Tile data: On\";\r\n}\r\n\r\nstd::string DebugCmdScrollView(std::optional<bool> on)\r\n{\r\n\tDebugScrollViewEnabled = on.value_or(!DebugScrollViewEnabled);\r\n\tif (!DebugScrollViewEnabled)\r\n\t\tInitMultiView();\r\n\treturn StrCat(\"Scroll view: \", DebugScrollViewEnabled ? \"On\" : \"Off\");\r\n}\r\n\r\nstd::string DebugCmdToggleFPS(std::optional<bool> on)\r\n{\r\n\tframeflag = on.value_or(!frameflag);\r\n\treturn StrCat(\"FPS counter: \", frameflag ? \"On\" : \"Off\");\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevDisplayModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"fps\", \"(name: string = nil)\", \"Toggle FPS display.\", &DebugCmdToggleFPS);\r\n\tLuaSetDocFn(table, \"fullbright\", \"(on: boolean = nil)\", \"Toggle light shading.\", &DebugCmdFullbright);\r\n\tLuaSetDocFn(table, \"grid\", \"(on: boolean = nil)\", \"Toggle showing the grid.\", &DebugCmdShowGrid);\r\n\tLuaSetDocFn(table, \"path\", \"(on: boolean = nil)\", \"Toggle path debug rendering.\", &DebugCmdPath);\r\n\tLuaSetDocFn(table, \"scrollView\", \"(on: boolean = nil)\", \"Toggle view scrolling via Shift+Mouse.\", &DebugCmdScrollView);\r\n\tLuaSetDocFn(table, \"tileData\", \"(name: string = nil)\", \"Toggle showing tile data.\", &DebugCmdShowTileData);\r\n\tLuaSetDocFn(table, \"vision\", \"(on: boolean = nil)\", \"Toggle vision debug rendering.\", &DebugCmdVision);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/display.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevDisplayModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/items.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/items.hpp\"\r\n\r\n#include <random>\r\n#include <string>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"cursor.h\"\r\n#include \"engine/random.hpp\"\r\n#include \"items.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"pack.h\"\r\n#include \"player.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/str_case.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconst Item *DebugCmdGetItem()\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tif (!myPlayer.HoldItem.isEmpty()) return &myPlayer.HoldItem;\r\n\tif (pcursinvitem != -1) {\r\n\t\tif (pcursinvitem < INVITEM_INV_FIRST) return &myPlayer.InvBody[pcursinvitem];\r\n\t\tif (pcursinvitem <= INVITEM_INV_LAST) return &myPlayer.InvList[pcursinvitem - INVITEM_INV_FIRST];\r\n\t\treturn &myPlayer.SpdList[pcursinvitem - INVITEM_BELT_FIRST];\r\n\t}\r\n\tif (pcursitem != -1) return &Items[pcursitem];\r\n\treturn nullptr;\r\n}\r\n\r\nstd::string DebugCmdItemInfo()\r\n{\r\n\tconst Item *pItem = DebugCmdGetItem();\r\n\tif (pItem != nullptr) {\r\n\t\tconst Player &myPlayer = *MyPlayer;\r\n\t\tstd::string_view netPackValidation { \"N/A\" };\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tItemNetPack itemPack;\r\n\t\t\tItem unpacked;\r\n\t\t\tPackNetItem(*pItem, itemPack);\r\n\t\t\tnetPackValidation = UnPackNetItem(myPlayer, itemPack, unpacked) ? \"Success\" : \"Failure\";\r\n\t\t}\r\n\t\treturn StrCat(\"Name: \", pItem->_iIName,\r\n\t\t    \"\\nIDidx: \", pItem->IDidx, \" (\", AllItemsList[pItem->IDidx].iName, \")\",\r\n\t\t    \"\\nSeed: \", pItem->_iSeed,\r\n\t\t    \"\\nCreateInfo: \", pItem->_iCreateInfo,\r\n\t\t    \"\\nLevel: \", pItem->_iCreateInfo & CF_LEVEL,\r\n\t\t    \"\\nOnly Good: \", ((pItem->_iCreateInfo & CF_ONLYGOOD) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nUnique Monster: \", ((pItem->_iCreateInfo & CF_UPER15) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nDungeon Item: \", ((pItem->_iCreateInfo & CF_UPER1) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nUnique Item: \", ((pItem->_iCreateInfo & CF_UNIQUE) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nSmith: \", ((pItem->_iCreateInfo & CF_SMITH) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nSmith Premium: \", ((pItem->_iCreateInfo & CF_SMITHPREMIUM) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nBoy: \", ((pItem->_iCreateInfo & CF_BOY) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nWitch: \", ((pItem->_iCreateInfo & CF_WITCH) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nHealer: \", ((pItem->_iCreateInfo & CF_HEALER) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nPregen: \", ((pItem->_iCreateInfo & CF_PREGEN) == 0) ? \"False\" : \"True\",\r\n\t\t    \"\\nNet Validation: \", netPackValidation);\r\n\t}\r\n\treturn StrCat(\"Num items: \", ActiveItemCount);\r\n}\r\n\r\nstd::mt19937 BetterRng;\r\nstd::string DebugSpawnItem(std::string itemName)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS) return \"No space to generate the item!\";\r\n\r\n\tconst int max_time = 3000;\r\n\tconst int max_iter = 1000000;\r\n\r\n\tAsciiStrToLower(itemName);\r\n\r\n\tItem testItem;\r\n\r\n\tuint32_t begin = SDL_GetTicks();\r\n\tint i = 0;\r\n\tfor (;; i++) {\r\n\t\t// using a better rng here to seed the item to prevent getting stuck repeating same values using old one\r\n\t\tstd::uniform_int_distribution<int32_t> dist(0, INT_MAX);\r\n\t\tSetRndSeed(dist(BetterRng));\r\n\t\tif (SDL_GetTicks() - begin > max_time)\r\n\t\t\treturn StrCat(\"Item not found in \", max_time / 1000, \" seconds!\");\r\n\r\n\t\tif (i > max_iter)\r\n\t\t\treturn StrCat(\"Item not found in \", max_iter, \" tries!\");\r\n\r\n\t\tconst int8_t monsterLevel = dist(BetterRng) % CF_LEVEL + 1;\r\n\t\t_item_indexes idx = RndItemForMonsterLevel(monsterLevel);\r\n\t\tif (IsAnyOf(idx, IDI_NONE, IDI_GOLD))\r\n\t\t\tcontinue;\r\n\r\n\t\ttestItem = {};\r\n\t\tSetupAllItems(*MyPlayer, testItem, idx, AdvanceRndSeed(), monsterLevel, 1, false, false);\r\n\t\tTryRandomUniqueItem(testItem, idx, monsterLevel, 1, false, false);\r\n\t\tSetupItem(testItem);\r\n\r\n\t\tstd::string tmp = AsciiStrToLower(testItem._iIName);\r\n\t\tif (tmp.find(itemName) != std::string::npos)\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tint ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\titem = testItem.pop();\r\n\titem._iIdentified = true;\r\n\tPoint pos = MyPlayer->position.tile;\r\n\tGetSuperItemSpace(pos, ii);\r\n\tNetSendCmdPItem(false, CMD_SPAWNITEM, item.position, item);\r\n\treturn StrCat(\"Item generated successfully - iterations: \", i);\r\n}\r\n\r\nstd::string DebugSpawnUniqueItem(std::string itemName)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS) return \"No space to generate the item!\";\r\n\r\n\tAsciiStrToLower(itemName);\r\n\tUniqueItem uniqueItem;\r\n\tbool foundUnique = false;\r\n\tint uniqueIndex = 0;\r\n\tfor (const auto &item : UniqueItems) {\r\n\t\tconst std::string tmp = AsciiStrToLower(std::string_view(item.UIName));\r\n\t\tif (tmp.find(itemName) != std::string::npos) {\r\n\t\t\titemName = tmp;\r\n\t\t\tuniqueItem = item;\r\n\t\t\tfoundUnique = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t++uniqueIndex;\r\n\t}\r\n\tif (!foundUnique) return \"No unique item found!\";\r\n\r\n\t_item_indexes uniqueBaseIndex = IDI_GOLD;\r\n\tfor (size_t j = 0; j < AllItemsList.size(); j++) {\r\n\t\tif (!IsItemAvailable(static_cast<int>(j)))\r\n\t\t\tcontinue;\r\n\t\tif (AllItemsList[j].iItemId == uniqueItem.UIItemId) {\r\n\t\t\tuniqueBaseIndex = static_cast<_item_indexes>(j);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (uniqueBaseIndex == IDI_GOLD) return \"Base item not available!\";\r\n\r\n\tauto &baseItemData = AllItemsList[static_cast<size_t>(uniqueBaseIndex)];\r\n\r\n\tItem testItem;\r\n\r\n\tint i = 0;\r\n\tfor (uint32_t begin = SDL_GetTicks();; i++) {\r\n\t\tconstexpr int max_time = 3000;\r\n\t\tif (SDL_GetTicks() - begin > max_time)\r\n\t\t\treturn StrCat(\"Item not found in \", max_time / 1000, \" seconds!\");\r\n\r\n\t\tconstexpr int max_iter = 1000000;\r\n\t\tif (i > max_iter)\r\n\t\t\treturn StrCat(\"Item not found in \", max_iter, \" tries!\");\r\n\r\n\t\ttestItem = {};\r\n\t\ttestItem._iMiscId = baseItemData.iMiscId;\r\n\t\tstd::uniform_int_distribution<int32_t> dist(0, INT_MAX);\r\n\t\tSetRndSeed(dist(BetterRng));\r\n\t\tfor (auto &flag : UniqueItemFlags)\r\n\t\t\tflag = true;\r\n\t\tUniqueItemFlags[uniqueIndex] = false;\r\n\t\tSetupAllItems(*MyPlayer, testItem, uniqueBaseIndex, testItem._iMiscId == IMISC_UNIQUE ? uniqueIndex : AdvanceRndSeed(), uniqueItem.UIMinLvl, 1, false, false);\r\n\t\tTryRandomUniqueItem(testItem, uniqueBaseIndex, uniqueItem.UIMinLvl, 1, false, false);\r\n\t\tSetupItem(testItem);\r\n\t\tfor (auto &flag : UniqueItemFlags)\r\n\t\t\tflag = false;\r\n\r\n\t\tif (testItem._iMagical != ITEM_QUALITY_UNIQUE)\r\n\t\t\tcontinue;\r\n\r\n\t\tconst std::string tmp = AsciiStrToLower(testItem._iIName);\r\n\t\tif (tmp.find(itemName) != std::string::npos)\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tint ii = AllocateItem();\r\n\tauto &item = Items[ii];\r\n\titem = testItem.pop();\r\n\tPoint pos = MyPlayer->position.tile;\r\n\tGetSuperItemSpace(pos, ii);\r\n\titem._iIdentified = true;\r\n\tNetSendCmdPItem(false, CMD_SPAWNITEM, item.position, item);\r\n\r\n\treturn StrCat(\"Item generated successfully - iterations: \", i);\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevItemsModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"get\", \"() -> Item\", \"Get the currently selected item.\", &DebugCmdGetItem);\r\n\tLuaSetDocFn(table, \"info\", \"()\", \"Show info of currently selected item.\", &DebugCmdItemInfo);\r\n\tLuaSetDocFn(table, \"spawn\", \"(name: string)\", \"Attempt to generate an item.\", &DebugSpawnItem);\r\n\tLuaSetDocFn(table, \"spawnUnique\", \"(name: string)\", \"Attempt to generate a unique item.\", &DebugSpawnUniqueItem);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/items.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevItemsModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/level/map.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/level/map.hpp\"\r\n\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"automap.h\"\r\n#include \"lua/metadoc.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstd::string DebugCmdMapReveal()\r\n{\r\n\tfor (int x = 0; x < DMAXX; x++)\r\n\t\tfor (int y = 0; y < DMAXY; y++)\r\n\t\t\tUpdateAutomapExplorer({ x, y }, MAP_EXP_SHRINE);\r\n\treturn \"Automap fully explored.\";\r\n}\r\n\r\nstd::string DebugCmdMapHide()\r\n{\r\n\tfor (int x = 0; x < DMAXX; x++)\r\n\t\tfor (int y = 0; y < DMAXY; y++)\r\n\t\t\tAutomapView[x][y] = MAP_EXP_NONE;\r\n\treturn \"Automap exploration removed.\";\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevLevelMapModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"hide\", \"()\", \"Hide the map.\", &DebugCmdMapHide);\r\n\tLuaSetDocFn(table, \"reveal\", \"()\", \"Reveal the map.\", &DebugCmdMapReveal);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/level/map.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevLevelMapModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/level/warp.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/level/warp.hpp\"\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"debug.h\"\r\n#include \"interfac.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstd::string DebugCmdWarpToDungeonLevel(uint8_t level)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (level > (gbIsHellfire ? 24 : 16))\r\n\t\treturn StrCat(\"Level \", level, \" does not exist!\");\r\n\tif (!setlevel && myPlayer.isOnLevel(level))\r\n\t\treturn StrCat(\"You are already on level \", level, \"!\");\r\n\r\n\tStartNewLvl(myPlayer, (level != 21) ? interface_mode::WM_DIABNEXTLVL : interface_mode::WM_DIABTOWNWARP, level);\r\n\treturn StrCat(\"Moved you to level \", level, \".\");\r\n}\r\n\r\nstd::string DebugCmdWarpToQuestLevel(uint8_t level)\r\n{\r\n\tif (level < 1)\r\n\t\treturn StrCat(\"Quest level number must be 1 or higher!\");\r\n\tif (setlevel && setlvlnum == level)\r\n\t\treturn StrCat(\"You are already on quest level\", level, \"!\");\r\n\r\n\tfor (Quest &quest : Quests) {\r\n\t\tif (level != quest._qslvl)\r\n\t\t\tcontinue;\r\n\r\n\t\tsetlvltype = quest._qlvltype;\r\n\t\tStartNewLvl(*MyPlayer, WM_DIABSETLVL, level);\r\n\r\n\t\treturn StrCat(\"Moved you to quest level \", QuestLevelNames[level], \".\");\r\n\t}\r\n\r\n\treturn StrCat(\"Quest level \", level, \" does not exist!\");\r\n}\r\n\r\nstd::string DebugCmdWarpToCustomMap(std::string_view path, int dunType, int x, int y)\r\n{\r\n\tif (path.empty()) return \"path is required\";\r\n\tif (dunType < DTYPE_CATHEDRAL || dunType > DTYPE_LAST) return \"invalid dunType\";\r\n\r\n\tconst Point spawn { x, y };\r\n\tif (!InDungeonBounds(spawn)) return \"spawn location is out of bounds\";\r\n\r\n\tTestMapPath = StrCat(path, \".dun\");\r\n\tsetlvltype = static_cast<dungeon_type>(dunType);\r\n\tViewPosition = spawn;\r\n\r\n\tStartNewLvl(*MyPlayer, WM_DIABSETLVL, SL_NONE);\r\n\r\n\treturn StrCat(\"Moved you to \", TestMapPath, \".\");\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevLevelWarpModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"dungeon\", \"(n: number)\", \"Go to dungeon level (0 for town).\", &DebugCmdWarpToDungeonLevel);\r\n\tLuaSetDocFn(table, \"map\", \"(path: string, dunType: number, x: number, y: number)\", \"Go to custom {path}.dun level\", &DebugCmdWarpToCustomMap);\r\n\tLuaSetDocFn(table, \"quest\", \"(n: number)\", \"Go to quest level.\", &DebugCmdWarpToQuestLevel);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/level/warp.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevLevelWarpModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/level.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/level.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdio>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"diablo.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"lua/modules/dev/level/map.hpp\"\r\n#include \"lua/modules/dev/level/warp.hpp\"\r\n#include \"monster.h\"\r\n#include \"objects.h\"\r\n#include \"player.h\"\r\n#include \"utils/endian_stream.hpp\"\r\n#include \"utils/file_util.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstd::string ExportDun()\r\n{\r\n\tconst std::string levelName = StrCat(currlevel, \"-\", DungeonSeeds[currlevel], \".dun\");\r\n\tFILE *dunFile = OpenFile(levelName.c_str(), \"ab\");\r\n\r\n\tWriteLE16(dunFile, DMAXX);\r\n\tWriteLE16(dunFile, DMAXY);\r\n\r\n\t/** Tiles. */\r\n\tfor (int y = 0; y < DMAXY; y++) {\r\n\t\tfor (int x = 0; x < DMAXX; x++) {\r\n\t\t\tWriteLE16(dunFile, dungeon[x][y]);\r\n\t\t}\r\n\t}\r\n\r\n\t/** Padding */\r\n\tfor (int y = 16; y < MAXDUNY - 16; y++) {\r\n\t\tfor (int x = 16; x < MAXDUNX - 16; x++) {\r\n\t\t\tWriteLE16(dunFile, 0);\r\n\t\t}\r\n\t}\r\n\r\n\t/** Monsters */\r\n\tfor (int y = 16; y < MAXDUNY - 16; y++) {\r\n\t\tfor (int x = 16; x < MAXDUNX - 16; x++) {\r\n\t\t\tuint16_t monsterId = 0;\r\n\t\t\tif (dMonster[x][y] > 0) {\r\n\t\t\t\tfor (int i = 0; i < 157; i++) {\r\n\t\t\t\t\tif (MonstConvTbl[i] == Monsters[std::abs(dMonster[x][y]) - 1].type().type) {\r\n\t\t\t\t\t\tmonsterId = i + 1;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tWriteLE16(dunFile, monsterId);\r\n\t\t}\r\n\t}\r\n\r\n\t/** Objects */\r\n\tfor (int y = 16; y < MAXDUNY - 16; y++) {\r\n\t\tfor (int x = 16; x < MAXDUNX - 16; x++) {\r\n\t\t\tuint16_t objectId = 0;\r\n\t\t\tObject *object = FindObjectAtPosition({ x, y }, false);\r\n\t\t\tif (object != nullptr) {\r\n\t\t\t\tfor (int i = 0; i < 147; i++) {\r\n\t\t\t\t\tif (ObjTypeConv[i] == object->_otype) {\r\n\t\t\t\t\t\tobjectId = i;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tWriteLE16(dunFile, objectId);\r\n\t\t}\r\n\t}\r\n\r\n\t/** Transparency */\r\n\tfor (int y = 16; y < MAXDUNY - 16; y++) {\r\n\t\tfor (int x = 16; x < MAXDUNX - 16; x++) {\r\n\t\t\tWriteLE16(dunFile, dTransVal[x][y]);\r\n\t\t}\r\n\t}\r\n\tstd::fclose(dunFile);\r\n\r\n\treturn StrCat(\"Successfully exported \", levelName, \".\");\r\n}\r\n\r\nstd::string DebugCmdResetLevel(uint8_t level, std::optional<int> seed)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (level > (gbIsHellfire ? 24 : 16))\r\n\t\treturn StrCat(\"Level \", level, \" does not exist!\");\r\n\tif (myPlayer.isOnLevel(level))\r\n\t\treturn \"Unable to reset dungeon levels occupied by players!\";\r\n\r\n\tmyPlayer._pLvlVisited[level] = false;\r\n\tDeltaClearLevel(level);\r\n\r\n\tif (seed.has_value()) {\r\n\t\tDungeonSeeds[level] = *seed;\r\n\t\tLevelSeeds[level] = std::nullopt;\r\n\t\treturn StrCat(\"Successfully reset level \", level, \" with seed \", *seed, \".\");\r\n\t}\r\n\treturn StrCat(\"Successfully reset level \", level, \".\");\r\n}\r\n\r\nstd::string DebugCmdLevelSeed(std::optional<uint8_t> level)\r\n{\r\n\tconstexpr size_t NumLevels = sizeof(DungeonSeeds) / sizeof(DungeonSeeds[0]);\r\n\tif (level.has_value() && *level >= NumLevels) {\r\n\t\treturn StrCat(\"level out of range, max: \", NumLevels - 1);\r\n\t}\r\n\treturn StrCat(DungeonSeeds[level.value_or(currlevel)]);\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevLevelModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"exportDun\", \"()\", \"Save the current level as a dun-file.\", &ExportDun);\r\n\tLuaSetDocFn(table, \"map\", \"\", \"Automap-related commands.\", LuaDevLevelMapModule(lua));\r\n\tLuaSetDocFn(table, \"reset\", \"(n: number, seed: number = nil)\", \"Resets specified level.\", &DebugCmdResetLevel);\r\n\tLuaSetDocFn(table, \"seed\", \"(level: number = nil)\", \"Get the seed of the current or given level.\", &DebugCmdLevelSeed);\r\n\tLuaSetDocFn(table, \"warp\", \"\", \"Warp to a level or a custom map.\", LuaDevLevelWarpModule(lua));\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/level.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevLevelModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/monsters.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/monsters.hpp\"\r\n\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"crawl.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"lighting.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"monster.h\"\r\n#include \"player.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"utils/str_case.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstd::string DebugCmdSpawnUniqueMonster(std::string name, std::optional<unsigned> countOpt)\r\n{\r\n\tif (leveltype == DTYPE_TOWN) return \"Can't spawn monsters in town\";\r\n\tif (name.empty()) return \"name is required\";\r\n\tconst unsigned count = countOpt.value_or(1);\r\n\tif (count < 1) return \"count must be positive\";\r\n\r\n\tAsciiStrToLower(name);\r\n\r\n\tint mtype = -1;\r\n\tUniqueMonsterType uniqueIndex = UniqueMonsterType::None;\r\n\tfor (size_t i = 0; i < UniqueMonstersData.size(); ++i) {\r\n\t\tconst auto &mondata = UniqueMonstersData[i];\r\n\t\tconst std::string monsterName = AsciiStrToLower(std::string_view(mondata.mName));\r\n\t\tif (monsterName.find(name) == std::string::npos)\r\n\t\t\tcontinue;\r\n\t\tmtype = mondata.mtype;\r\n\t\tuniqueIndex = static_cast<UniqueMonsterType>(i);\r\n\t\tif (monsterName == name) // to support partial name matching but always choose the correct monster if full name is given\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (mtype == -1) return \"Monster not found\";\r\n\r\n\tsize_t id = MaxLvlMTypes - 1;\r\n\tbool found = false;\r\n\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tif (LevelMonsterTypes[i].type == mtype) {\r\n\t\t\tid = i;\r\n\t\t\tfound = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!found) {\r\n\t\tif (LevelMonsterTypeCount == MaxLvlMTypes)\r\n\t\t\tLevelMonsterTypeCount--; // we are running out of monster types, so override last used monster type\r\n\t\ttl::expected<size_t, std::string> idResult = AddMonsterType(uniqueIndex, PLACE_SCATTER);\r\n\t\tif (!idResult.has_value()) return std::move(idResult).error();\r\n\t\tid = idResult.value();\r\n\t\tCMonster &monsterType = LevelMonsterTypes[id];\r\n\t\tInitMonsterGFX(monsterType);\r\n\t\tmonsterType.corpseId = 1;\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tunsigned spawnedMonster = 0;\r\n\r\n\tauto ret = Crawl(0, MaxCrawlRadius, [&](Displacement displacement) -> std::optional<std::string> {\r\n\t\tPoint pos = myPlayer.position.tile + displacement;\r\n\t\tif (dPlayer[pos.x][pos.y] != 0 || dMonster[pos.x][pos.y] != 0)\r\n\t\t\treturn {};\r\n\t\tif (!IsTileWalkable(pos))\r\n\t\t\treturn {};\r\n\r\n\t\tMonster *monster = AddMonster(pos, myPlayer._pdir, id, true);\r\n\t\tif (monster == nullptr)\r\n\t\t\treturn StrCat(\"Spawned \", spawnedMonster, \" monsters. (Unable to spawn more)\");\r\n\t\tPrepareUniqueMonst(*monster, uniqueIndex, 0, 0, UniqueMonstersData[static_cast<size_t>(uniqueIndex)]);\r\n\t\tmonster->corpseId = 1;\r\n\t\tspawnedMonster += 1;\r\n\r\n\t\tif (spawnedMonster >= count)\r\n\t\t\treturn StrCat(\"Spawned \", spawnedMonster, \" monsters.\");\r\n\r\n\t\treturn {};\r\n\t});\r\n\r\n\tif (!ret.has_value())\r\n\t\tret = StrCat(\"Spawned \", spawnedMonster, \" monsters. (Unable to spawn more)\");\r\n\treturn *ret;\r\n}\r\n\r\nstd::string DebugCmdSpawnMonster(std::string name, std::optional<unsigned> countOpt)\r\n{\r\n\tif (leveltype == DTYPE_TOWN) return \"Can't spawn monsters in town\";\r\n\tif (name.empty()) return \"name is required\";\r\n\tconst unsigned count = countOpt.value_or(1);\r\n\tif (count < 1) return \"count must be positive\";\r\n\r\n\tAsciiStrToLower(name);\r\n\r\n\tint mtype = -1;\r\n\r\n\tfor (size_t i = 0; i < MonstersData.size(); i++) {\r\n\t\tconst auto &mondata = MonstersData[i];\r\n\t\tconst std::string monsterName = AsciiStrToLower(std::string_view(mondata.name));\r\n\t\tif (monsterName.find(name) == std::string::npos)\r\n\t\t\tcontinue;\r\n\t\tmtype = static_cast<int>(i);\r\n\t\tif (monsterName == name) // to support partial name matching but always choose the correct monster if full name is given\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (mtype == -1) return \"Monster not found\";\r\n\tif (!MyPlayer->isLevelOwnedByLocalClient()) return \"You are not the level owner.\";\r\n\r\n\tsize_t id = MaxLvlMTypes - 1;\r\n\tbool found = false;\r\n\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tif (LevelMonsterTypes[i].type == mtype) {\r\n\t\t\tid = i;\r\n\t\t\tfound = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!found) {\r\n\t\tif (LevelMonsterTypeCount == MaxLvlMTypes)\r\n\t\t\tLevelMonsterTypeCount--; // we are running out of monster types, so override last used monster type\r\n\t\ttl::expected<size_t, std::string> idResult = AddMonsterType(static_cast<_monster_id>(mtype), PLACE_SCATTER);\r\n\t\tif (!idResult.has_value()) return std::move(idResult).error();\r\n\t\tid = idResult.value();\r\n\t\tCMonster &monsterType = LevelMonsterTypes[id];\r\n\t\tInitMonsterGFX(monsterType);\r\n\t\tmonsterType.corpseId = 1;\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tsize_t monstersToSpawn = std::min<size_t>(MaxMonsters - ActiveMonsterCount, count);\r\n\tif (monstersToSpawn == 0)\r\n\t\treturn \"Can't spawn any monsters\";\r\n\r\n\tsize_t spawnedMonster = 0;\r\n\tCrawl(0, MaxCrawlRadius, [&](Displacement displacement) {\r\n\t\tPoint pos = myPlayer.position.tile + displacement;\r\n\t\tif (dPlayer[pos.x][pos.y] != 0 || dMonster[pos.x][pos.y] != 0)\r\n\t\t\treturn false;\r\n\t\tif (!IsTileWalkable(pos))\r\n\t\t\treturn false;\r\n\r\n\t\tSpawnMonster(pos, myPlayer._pdir, id);\r\n\t\tspawnedMonster += 1;\r\n\r\n\t\treturn spawnedMonster == monstersToSpawn;\r\n\t});\r\n\r\n\tif (monstersToSpawn != count)\r\n\t\treturn StrCat(\"Spawned \", spawnedMonster, \" monsters. (Unable to spawn more)\");\r\n\treturn StrCat(\"Spawned \", spawnedMonster, \" monsters.\");\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevMonstersModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"spawn\", \"(name: string, count: number = 1)\", \"Spawn monster(s)\", &DebugCmdSpawnMonster);\r\n\tLuaSetDocFn(table, \"spawnUnique\", \"(name: string, count: number = 1)\", \"Spawn unique monster(s)\", &DebugCmdSpawnUniqueMonster);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/monsters.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevMonstersModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player/gold.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/player/gold.hpp\"\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"items.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstd::string DebugCmdGiveGoldCheat(std::optional<int> amount)\r\n{\r\n\tint goldToAdd = amount.value_or(GOLD_MAX_LIMIT * InventoryGridCells);\r\n\tif (goldToAdd <= 0) return \"amount must be positive\";\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tconst int goldAmountBefore = myPlayer._pGold;\r\n\tfor (int8_t &itemIndex : myPlayer.InvGrid) {\r\n\t\tif (itemIndex < 0)\r\n\t\t\tcontinue;\r\n\r\n\t\tItem &item = myPlayer.InvList[itemIndex != 0 ? itemIndex - 1 : myPlayer._pNumInv];\r\n\r\n\t\tif (itemIndex != 0) {\r\n\t\t\tif ((!item.isGold() && !item.isEmpty()) || (item.isGold() && item._ivalue == GOLD_MAX_LIMIT))\r\n\t\t\t\tcontinue;\r\n\t\t} else {\r\n\t\t\tif (item.isEmpty()) {\r\n\t\t\t\tMakeGoldStack(item, 0);\r\n\t\t\t\tmyPlayer._pNumInv++;\r\n\t\t\t\titemIndex = myPlayer._pNumInv;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tint goldThatCanBeAdded = (GOLD_MAX_LIMIT - item._ivalue);\r\n\t\tif (goldThatCanBeAdded >= goldToAdd) {\r\n\t\t\titem._ivalue += goldToAdd;\r\n\t\t\tmyPlayer._pGold += goldToAdd;\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\titem._ivalue += goldThatCanBeAdded;\r\n\t\tgoldToAdd -= goldThatCanBeAdded;\r\n\t\tmyPlayer._pGold += goldThatCanBeAdded;\r\n\t}\r\n\r\n\tCalcPlrInv(myPlayer, true);\r\n\r\n\treturn StrCat(\"Set your gold to \", myPlayer._pGold, \", added \", myPlayer._pGold - goldAmountBefore, \".\");\r\n}\r\n\r\nstd::string DebugCmdTakeGoldCheat(std::optional<int> amount)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tint goldToRemove = amount.value_or(GOLD_MAX_LIMIT * InventoryGridCells);\r\n\tif (goldToRemove <= 0) return \"amount must be positive\";\r\n\r\n\tconst int goldAmountBefore = myPlayer._pGold;\r\n\tfor (auto itemIndex : myPlayer.InvGrid) {\r\n\t\titemIndex -= 1;\r\n\r\n\t\tif (itemIndex < 0)\r\n\t\t\tcontinue;\r\n\r\n\t\tItem &item = myPlayer.InvList[itemIndex];\r\n\t\tif (!item.isGold())\r\n\t\t\tcontinue;\r\n\r\n\t\tif (item._ivalue >= goldToRemove) {\r\n\t\t\tmyPlayer._pGold -= goldToRemove;\r\n\t\t\titem._ivalue -= goldToRemove;\r\n\t\t\tif (item._ivalue == 0)\r\n\t\t\t\tmyPlayer.RemoveInvItem(itemIndex);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tmyPlayer._pGold -= item._ivalue;\r\n\t\tgoldToRemove -= item._ivalue;\r\n\t\tmyPlayer.RemoveInvItem(itemIndex);\r\n\t}\r\n\r\n\treturn StrCat(\"Set your gold to \", myPlayer._pGold, \", removed \", goldAmountBefore - myPlayer._pGold, \".\");\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevPlayerGoldModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"give\", \"(amount: number = MAX)\", \"Gives the player gold.\", &DebugCmdGiveGoldCheat);\r\n\tLuaSetDocFn(table, \"take\", \"(amount: number = MAX)\", \"Takes the player's gold away.\", &DebugCmdTakeGoldCheat);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player/gold.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevPlayerGoldModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player/spells.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/player/spells.hpp\"\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"lua/metadoc.hpp\"\r\n#include \"msg.h\"\r\n#include \"spells.h\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nstd::string DebugCmdSetSpellsLevel(uint8_t level)\r\n{\r\n\tfor (uint8_t i = static_cast<uint8_t>(SpellID::Firebolt); i < SpellsData.size(); i++) {\r\n\t\tif (GetSpellBookLevel(static_cast<SpellID>(i)) != -1) {\r\n\t\t\tNetSendCmdParam2(true, CMD_CHANGE_SPELL_LEVEL, i, level);\r\n\t\t}\r\n\t}\r\n\tif (level == 0)\r\n\t\tMyPlayer->_pMemSpells = 0;\r\n\r\n\treturn StrCat(\"Set all spell levels to \", level);\r\n}\r\n} // namespace\r\n\r\nsol::table LuaDevPlayerSpellsModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"setLevel\", \"(level: number)\", \"Set spell level for all spells.\", &DebugCmdSetSpellsLevel);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player/spells.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevPlayerSpellsModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player/stats.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/player/stats.hpp\"\r\n\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstd::string DebugCmdLevelUp(std::optional<int> levels)\r\n{\r\n\tconst int levelsToAdd = levels.value_or(1);\r\n\tif (levelsToAdd <= 0) return \"amount must be positive\";\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tfor (int i = 0; i < levelsToAdd; i++)\r\n\t\tNetSendCmd(true, CMD_CHEAT_EXPERIENCE);\r\n\treturn StrCat(\"New character level: \", myPlayer.getCharacterLevel() + levelsToAdd);\r\n}\r\n\r\nstd::string DebugCmdMaxStats()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tModifyPlrStr(myPlayer, myPlayer.GetMaximumAttributeValue(CharacterAttribute::Strength) - myPlayer._pBaseStr);\r\n\tModifyPlrMag(myPlayer, myPlayer.GetMaximumAttributeValue(CharacterAttribute::Magic) - myPlayer._pBaseMag);\r\n\tModifyPlrDex(myPlayer, myPlayer.GetMaximumAttributeValue(CharacterAttribute::Dexterity) - myPlayer._pBaseDex);\r\n\tModifyPlrVit(myPlayer, myPlayer.GetMaximumAttributeValue(CharacterAttribute::Vitality) - myPlayer._pBaseVit);\r\n\treturn \"Set all character base attributes to maximum.\";\r\n}\r\n\r\nstd::string DebugCmdMinStats()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tModifyPlrStr(myPlayer, -myPlayer._pBaseStr);\r\n\tModifyPlrMag(myPlayer, -myPlayer._pBaseMag);\r\n\tModifyPlrDex(myPlayer, -myPlayer._pBaseDex);\r\n\tModifyPlrVit(myPlayer, -myPlayer._pBaseVit);\r\n\treturn \"Set all character base attributes to minimum.\";\r\n}\r\n\r\nstd::string DebugCmdRefillHealthMana()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tmyPlayer.RestoreFullLife();\r\n\tmyPlayer.RestoreFullMana();\r\n\tRedrawComponent(PanelDrawComponent::Health);\r\n\tRedrawComponent(PanelDrawComponent::Mana);\r\n\treturn StrCat(\"Restored life and mana to full.\");\r\n}\r\n\r\nstd::string DebugCmdChangeHealth(int change)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (change == 0)\r\n\t\treturn StrCat(\"Enter a value not equal to 0 to change life!\");\r\n\r\n\tint newHealth = myPlayer._pHitPoints + (change * 64);\r\n\tSetPlayerHitPoints(myPlayer, newHealth);\r\n\tif (newHealth <= 0)\r\n\t\tSyncPlrKill(myPlayer, DeathReason::MonsterOrTrap);\r\n\r\n\treturn StrCat(\"Changed life by \", change);\r\n}\r\n\r\nstd::string DebugCmdChangeMana(int change)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (change == 0)\r\n\t\treturn StrCat(\"Enter a value not equal to 0 to change mana!\");\r\n\r\n\tint newMana = myPlayer._pMana + (change * 64);\r\n\tmyPlayer._pMana = newMana;\r\n\tmyPlayer._pManaBase = myPlayer._pMana + myPlayer._pMaxManaBase - myPlayer._pMaxMana;\r\n\tRedrawComponent(PanelDrawComponent::Mana);\r\n\r\n\treturn StrCat(\"Changed mana by \", change);\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevPlayerStatsModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"adjustHealth\", \"(amount: number)\", \"Adjust HP (amount can be negative)\", &DebugCmdChangeHealth);\r\n\tLuaSetDocFn(table, \"adjustMana\", \"(amount: number)\", \"Adjust mana (amount can be negative)\", &DebugCmdChangeMana);\r\n\tLuaSetDocFn(table, \"levelUp\", \"(amount: number = 1)\", \"Level the player up.\", &DebugCmdLevelUp);\r\n\tLuaSetDocFn(table, \"rejuvenate\", \"()\", \"Refill health\", &DebugCmdRefillHealthMana);\r\n\tLuaSetDocFn(table, \"setAttrToMax\", \"()\", \"Set Str, Mag, Dex, and Vit to maximum.\", &DebugCmdMaxStats);\r\n\tLuaSetDocFn(table, \"setAttrToMin\", \"()\", \"Set Str, Mag, Dex, and Vit to minimum.\", &DebugCmdMinStats);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player/stats.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevPlayerStatsModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/player.hpp\"\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"debug.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"lua/modules/dev/player/gold.hpp\"\r\n#include \"lua/modules/dev/player/spells.hpp\"\r\n#include \"lua/modules/dev/player/stats.hpp\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstd::string DebugCmdArrow(std::string_view effect)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tmyPlayer._pIFlags &= ~ItemSpecialEffect::FireArrows;\r\n\tmyPlayer._pIFlags &= ~ItemSpecialEffect::LightningArrows;\r\n\r\n\tif (effect == \"normal\") {\r\n\t\t// we removed the parameter at the top\r\n\t} else if (effect == \"fire\") {\r\n\t\tmyPlayer._pIFlags |= ItemSpecialEffect::FireArrows;\r\n\t} else if (effect == \"lightning\") {\r\n\t\tmyPlayer._pIFlags |= ItemSpecialEffect::LightningArrows;\r\n\t} else if (effect == \"spectral\") {\r\n\t\tmyPlayer._pIFlags |= (ItemSpecialEffect::FireArrows | ItemSpecialEffect::LightningArrows);\r\n\t} else {\r\n\t\treturn \"Invalid effect!\";\r\n\t}\r\n\r\n\treturn StrCat(\"Arrows changed to: \", effect);\r\n}\r\n\r\nstd::string DebugCmdGodMode(std::optional<bool> on)\r\n{\r\n\tDebugGodMode = on.value_or(!DebugGodMode);\r\n\treturn StrCat(\"God mode: \", DebugGodMode ? \"On\" : \"Off\");\r\n}\r\n\r\nstd::string DebugCmdPlayerInfo(std::optional<uint8_t> id)\r\n{\r\n\tconst uint8_t playerId = id.value_or(0);\r\n\tif (playerId >= Players.size())\r\n\t\treturn StrCat(\"Invalid player ID (max: \", Players.size() - 1, \")\");\r\n\tPlayer &player = Players[playerId];\r\n\tif (!player.plractive)\r\n\t\treturn StrCat(\"Player \", playerId, \" is not active!\");\r\n\r\n\tconst Point target = player.GetTargetPosition();\r\n\treturn StrCat(\"Plr \", playerId, \" is \", player._pName,\r\n\t    \"\\nLvl: \", player.plrlevel, \" Changing: \", player._pLvlChanging,\r\n\t    \"\\nTile.x: \", player.position.tile.x, \" Tile.y: \", player.position.tile.y, \" Target.x: \", target.x, \" Target.y: \", target.y,\r\n\t    \"\\nMode: \", player._pmode, \" destAction: \", player.destAction, \" walkpath[0]: \", player.walkpath[0],\r\n\t    \"\\nInvincible: \", player._pInvincible ? 1 : 0, \" HitPoints: \", player._pHitPoints);\r\n}\r\n\r\nstd::string DebugSetPlayerTrn(std::string_view path)\r\n{\r\n\tif (!path.empty()) {\r\n\t\tif (const AssetRef ref = FindAsset(path); !ref.ok()) {\r\n\t\t\tconst char *error = ref.error();\r\n\t\t\treturn error == nullptr || *error == '\\0' ? StrCat(\"File not found: \", path) : error;\r\n\t\t}\r\n\t}\r\n\tdebugTRN = path;\r\n\tPlayer &player = *MyPlayer;\r\n\tInitPlayerGFX(player);\r\n\tStartStand(player, player._pdir);\r\n\treturn path.empty() ? \"TRN unset\" : \"TRN set\";\r\n}\r\n\r\nsol::table LuaDevPlayerTrnModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"mon\", \"(name: string)\", \"Set player TRN to monsters\\\\${name}.trn\",\r\n\t    [](std::string_view name) { return DebugSetPlayerTrn(StrCat(\"monsters\\\\\", name, \".trn\")); });\r\n\tLuaSetDocFn(table, \"plr\", \"(name: string)\", \"Set player TRN to plrgfx\\\\${name}.trn\",\r\n\t    [](std::string_view name) { return DebugSetPlayerTrn(StrCat(\"plrgfx\\\\\", name, \".trn\")); });\r\n\tLuaSetDocFn(table, \"clear\", \"()\", \"Unset player TRN\",\r\n\t    []() { return DebugSetPlayerTrn(\"\"); });\r\n\treturn table;\r\n}\r\n\r\nstd::string DebugCmdInvisible(std::optional<bool> on)\r\n{\r\n\tDebugInvisible = on.value_or(!DebugInvisible);\r\n\treturn StrCat(\"Invisible: \", DebugInvisible ? \"On\" : \"Off\");\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevPlayerModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"arrow\", \"(effect: 'normal'|'fire'|'lightning'|'explosion')\", \"Set arrow effect.\", &DebugCmdArrow);\r\n\tLuaSetDocFn(table, \"god\", \"(on: boolean = nil)\", \"Toggle god mode.\", &DebugCmdGodMode);\r\n\tLuaSetDoc(table, \"gold\", \"\", \"Adjust player gold.\", LuaDevPlayerGoldModule(lua));\r\n\tLuaSetDocFn(table, \"info\", \"(id: number = 0)\", \"Show player info.\", &DebugCmdPlayerInfo);\r\n\tLuaSetDoc(table, \"spells\", \"\", \"Adjust player spells.\", LuaDevPlayerSpellsModule(lua));\r\n\tLuaSetDoc(table, \"stats\", \"\", \"Adjust player stats (Strength, HP, etc).\", LuaDevPlayerStatsModule(lua));\r\n\tLuaSetDoc(table, \"trn\", \"\", \"Set player TRN to '${name}.trn'\", LuaDevPlayerTrnModule(lua));\r\n\tLuaSetDocFn(table, \"invisible\", \"(on: boolean = nil)\", \"Toggle invisibility.\", &DebugCmdInvisible);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/player.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevPlayerModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/quests.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/quests.hpp\"\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"quests.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstd::string DebugCmdEnableQuest(uint8_t questId)\r\n{\r\n\tif (questId >= MAXQUESTS) return StrCat(\"Quest \", questId, \" does not exist!\");\r\n\tQuest &quest = Quests[questId];\r\n\r\n\tif (IsNoneOf(quest._qactive, QUEST_NOTAVAIL, QUEST_INIT))\r\n\t\treturn StrCat(QuestsData[questId]._qlstr, \" is already active!\");\r\n\r\n\tquest._qactive = QUEST_ACTIVE;\r\n\tquest._qlog = true;\r\n\r\n\treturn StrCat(QuestsData[questId]._qlstr, \" activated.\");\r\n}\r\n\r\nstd::string DebugCmdEnableQuests()\r\n{\r\n\tfor (Quest &quest : Quests) {\r\n\t\tif (IsNoneOf(quest._qactive, QUEST_NOTAVAIL, QUEST_INIT)) continue;\r\n\t\tquest._qactive = QUEST_ACTIVE;\r\n\t\tquest._qlog = true;\r\n\t}\r\n\treturn \"Activated all quests.\";\r\n}\r\n\r\nstd::string DebugCmdQuestInfo(const uint8_t questId)\r\n{\r\n\tif (questId >= MAXQUESTS) return StrCat(\"Quest \", questId, \" does not exist!\");\r\n\tconst Quest &quest = Quests[questId];\r\n\treturn StrCat(\"Quest id=\", quest._qidx, \" \", QuestsData[quest._qidx]._qlstr,\r\n\t    \" active=\", quest._qactive, \" var1=\", quest._qvar1, \" var2=\", quest._qvar2);\r\n}\r\n\r\nstd::string DebugCmdQuestsInfo()\r\n{\r\n\tstd::string ret;\r\n\tfor (const Quest &quest : Quests) {\r\n\t\tStrAppend(ret, \"Quest id=\", quest._qidx, \" \", QuestsData[quest._qidx]._qlstr,\r\n\t\t    \" active=\", quest._qactive, \" var1=\", quest._qvar1, \" var2=\", quest._qvar2, \"\\n\");\r\n\t}\r\n\tif (!ret.empty()) ret.pop_back();\r\n\treturn ret;\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevQuestsModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"activate\", \"(id: number)\", \"Activate the given quest.\", &DebugCmdEnableQuest);\r\n\tLuaSetDocFn(table, \"activateAll\", \"()\", \"Activate all available quests.\", &DebugCmdEnableQuests);\r\n\tLuaSetDocFn(table, \"all\", \"()\", \"Information on all available quest.\", &DebugCmdQuestsInfo);\r\n\tLuaSetDocFn(table, \"info\", \"(id: number)\", \"Information on the given quest.\", &DebugCmdQuestInfo);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/quests.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevQuestsModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/search.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/quests.hpp\"\r\n\r\n#include <string>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"debug.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"utils/str_case.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstd::string DebugCmdSearchMonster(std::string_view name)\r\n{\r\n\tif (name.empty()) return \"Missing monster name!\";\r\n\tAddDebugAutomapMonsterHighlight(AsciiStrToLower(name));\r\n\treturn StrCat(\"Added automap marker for monster \", name, \".\");\r\n}\r\n\r\nstd::string DebugCmdSearchItem(std::string_view name)\r\n{\r\n\tif (name.empty()) return \"Missing item name!\";\r\n\tAddDebugAutomapItemHighlight(AsciiStrToLower(name));\r\n\treturn StrCat(\"Added automap marker for item \", name, \".\");\r\n}\r\n\r\nstd::string DebugCmdSearchObject(std::string_view name)\r\n{\r\n\tif (name.empty()) return \"Missing object name!\";\r\n\tAddDebugAutomapObjectHighlight(AsciiStrToLower(name));\r\n\treturn StrCat(\"Added automap marker for object \", name, \".\");\r\n}\r\n\r\nstd::string DebugCmdClearSearch()\r\n{\r\n\tClearDebugAutomapHighlights();\r\n\treturn \"Removed all automap search markers.\";\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevSearchModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"clear\", \"()\", \"Clear search results from the map.\", &DebugCmdClearSearch);\r\n\tLuaSetDocFn(table, \"item\", \"(name: string)\", \"Search the map for an item.\", &DebugCmdSearchItem);\r\n\tLuaSetDocFn(table, \"monster\", \"(name: string)\", \"Search the map for a monster.\", &DebugCmdSearchMonster);\r\n\tLuaSetDocFn(table, \"object\", \"(name: string)\", \"Search the map for an object.\", &DebugCmdSearchObject);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/search.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevSearchModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/towners.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev/towners.hpp\"\r\n\r\n#include <string>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <sol/sol.hpp>\r\n\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n#include \"spells.h\"\r\n#include \"towners.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nankerl::unordered_dense::map<std::string_view, _talker_id> TownerShortNameToTownerId = {\r\n\t{ \"griswold\", _talker_id::TOWN_SMITH },\r\n\t{ \"smith\", _talker_id::TOWN_SMITH },\r\n\t{ \"pepin\", _talker_id::TOWN_HEALER },\r\n\t{ \"healer\", _talker_id::TOWN_HEALER },\r\n\t{ \"ogden\", _talker_id::TOWN_TAVERN },\r\n\t{ \"tavern\", _talker_id::TOWN_TAVERN },\r\n\t{ \"cain\", _talker_id::TOWN_STORY },\r\n\t{ \"story\", _talker_id::TOWN_STORY },\r\n\t{ \"farnham\", _talker_id::TOWN_DRUNK },\r\n\t{ \"drunk\", _talker_id::TOWN_DRUNK },\r\n\t{ \"adria\", _talker_id::TOWN_WITCH },\r\n\t{ \"witch\", _talker_id::TOWN_WITCH },\r\n\t{ \"gillian\", _talker_id::TOWN_BMAID },\r\n\t{ \"bmaid\", _talker_id::TOWN_BMAID },\r\n\t{ \"wirt\", _talker_id ::TOWN_PEGBOY },\r\n\t{ \"pegboy\", _talker_id ::TOWN_PEGBOY },\r\n\t{ \"lester\", _talker_id ::TOWN_FARMER },\r\n\t{ \"farmer\", _talker_id ::TOWN_FARMER },\r\n\t{ \"girl\", _talker_id ::TOWN_GIRL },\r\n\t{ \"nut\", _talker_id::TOWN_COWFARM },\r\n\t{ \"cowfarm\", _talker_id::TOWN_COWFARM },\r\n};\r\n\r\nstd::string DebugCmdVisitTowner(std::string_view name)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (setlevel || !myPlayer.isOnLevel(0))\r\n\t\treturn StrCat(\"This command is only available in Town!\");\r\n\r\n\tif (name.empty()) {\r\n\t\tstd::string ret;\r\n\t\tret = StrCat(\"Please provide the name of a Towner: \");\r\n\t\tfor (const auto &[name, _] : TownerShortNameToTownerId) {\r\n\t\t\tret += ' ';\r\n\t\t\tret.append(name);\r\n\t\t}\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tauto it = TownerShortNameToTownerId.find(name);\r\n\tif (it == TownerShortNameToTownerId.end())\r\n\t\treturn StrCat(name, \" is invalid!\");\r\n\r\n\tfor (const Towner &towner : Towners) {\r\n\t\tif (towner._ttype != it->second) continue;\r\n\t\tCastSpell(\r\n\t\t    *MyPlayer,\r\n\t\t    SpellID::Teleport,\r\n\t\t    myPlayer.position.tile,\r\n\t\t    towner.position,\r\n\t\t    /*spllvl=*/1);\r\n\t\treturn StrCat(\"Moved you to \", name, \".\");\r\n\t}\r\n\r\n\treturn StrCat(\"Unable to locate \", name, \"!\");\r\n}\r\n\r\nstd::string DebugCmdTalkToTowner(std::string_view name)\r\n{\r\n\tif (name.empty()) {\r\n\t\tstd::string ret;\r\n\t\tret = StrCat(\"Please provide the name of a Towner: \");\r\n\t\tfor (const auto &[name, _] : TownerShortNameToTownerId) {\r\n\t\t\tret += ' ';\r\n\t\t\tret.append(name);\r\n\t\t}\r\n\t\treturn ret;\r\n\t}\r\n\r\n\tauto it = TownerShortNameToTownerId.find(name);\r\n\tif (it == TownerShortNameToTownerId.end())\r\n\t\treturn StrCat(name, \" is invalid!\");\r\n\r\n\tif (!DebugTalkToTowner(it->second)) return StrCat(\"Towner not found!\");\r\n\treturn StrCat(\"Opened \", name, \" talk window.\");\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaDevTownersModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"talk\", \"(name: string)\", \"Talk to towner.\", &DebugCmdTalkToTowner);\r\n\tLuaSetDocFn(table, \"visit\", \"(name: string)\", \"Teleport to towner.\", &DebugCmdVisitTowner);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev/towners.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevTownersModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/modules/dev.hpp\"\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"lua/metadoc.hpp\"\r\n#include \"lua/modules/dev/display.hpp\"\r\n#include \"lua/modules/dev/items.hpp\"\r\n#include \"lua/modules/dev/level.hpp\"\r\n#include \"lua/modules/dev/monsters.hpp\"\r\n#include \"lua/modules/dev/player.hpp\"\r\n#include \"lua/modules/dev/quests.hpp\"\r\n#include \"lua/modules/dev/search.hpp\"\r\n#include \"lua/modules/dev/towners.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDoc(table, \"display\", \"\", \"Debugging HUD and rendering commands.\", LuaDevDisplayModule(lua));\r\n\tLuaSetDoc(table, \"items\", \"\", \"Item-related commands.\", LuaDevItemsModule(lua));\r\n\tLuaSetDoc(table, \"level\", \"\", \"Level-related commands.\", LuaDevLevelModule(lua));\r\n\tLuaSetDoc(table, \"monsters\", \"\", \"Monster-related commands.\", LuaDevMonstersModule(lua));\r\n\tLuaSetDoc(table, \"player\", \"\", \"Player-related commands.\", LuaDevPlayerModule(lua));\r\n\tLuaSetDoc(table, \"quests\", \"\", \"Quest-related commands.\", LuaDevQuestsModule(lua));\r\n\tLuaSetDoc(table, \"search\", \"\", \"Search the map for monsters / items / objects.\", LuaDevSearchModule(lua));\r\n\tLuaSetDoc(table, \"towners\", \"\", \"Town NPC commands.\", LuaDevTownersModule(lua));\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/dev.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaDevModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/modules/floatingnumbers.cpp",
    "content": "#include \"lua/modules/floatingnumbers.hpp\"\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"qol/floatingnumbers.h\"\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaFloatingNumbersModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\r\n\tLuaSetDocFn(table, \"add\", \"(text: string, pos: Point, style: UiFlags, id: integer = 0, reverseDirection: boolean = false)\",\r\n\t    \"Add a floating number\",\r\n\t    [](const std::string &text, Point pos, UiFlags style, std::optional<int> id, std::optional<bool> reverseDirection) {\r\n\t\t    AddFloatingNumber(pos, { 0, 0 }, text, style, id.value_or(0), reverseDirection.value_or(false));\r\n\t    });\r\n\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/floatingnumbers.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/forward.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaFloatingNumbersModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/hellfire.cpp",
    "content": "#include \"lua/modules/hellfire.hpp\"\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaHellfireModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"loadData\", \"()\", LoadHellfireArchives);\r\n\tLuaSetDocFn(table, \"enable\", \"()\", []() { gbIsHellfire = true; });\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/hellfire.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaHellfireModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/i18n.cpp",
    "content": "#include \"lua/modules/i18n.hpp\"\r\n\r\n#include <string_view>\r\n\r\n#include <fmt/format.h>\r\n#include <sol/sol.hpp>\r\n\r\n#include \"lua/metadoc.hpp\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaI18nModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"language_code\", \"()\",\r\n\t    \"Returns the current language code\", GetLanguageCode);\r\n\tLuaSetDocFn(table, \"translate\", \"(text: string)\",\r\n\t    \"Translates the given string\", [](const char *key) { return LanguageTranslate(key); });\r\n\tLuaSetDocFn(table, \"plural_translate\", \"(singular: string, plural: string, count: integer)\",\r\n\t    \"Returns a singular or plural translation for the given keys and count\", [](const char *singular, std::string_view plural, int count) {\r\n\t\t    return fmt::format(fmt::runtime(LanguagePluralTranslate(singular, plural, count)), count);\r\n\t    });\r\n\tLuaSetDocFn(table, \"particular_translate\", \"(context: string, text: string)\",\r\n\t    \"Returns the translation for the given context identifier and key.\", LanguageParticularTranslate);\r\n\tLuaSetDocFn(table, \"is_small_font_tall\", \"()\",\r\n\t    \"Whether the language's small font is tall (16px)\", IsSmallFontTall);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/i18n.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaI18nModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/items.cpp",
    "content": "#include \"lua/modules/items.hpp\"\r\n\r\n#include <string_view>\r\n\r\n#include <fmt/format.h>\r\n#include <sol/sol.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"items.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n#include \"tables/itemdat.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid InitItemUserType(sol::state_view &lua)\r\n{\r\n\t// Create a new usertype for Item with no constructor\r\n\tsol::usertype<Item> itemType = lua.new_usertype<Item>(sol::no_constructor);\r\n\r\n\t// Member variables\r\n\tLuaSetDocProperty(itemType, \"seed\", \"number\", \"Randomly generated identifier\", &Item::_iSeed);\r\n\tLuaSetDocProperty(itemType, \"createInfo\", \"number\", \"Creation flags\", &Item::_iCreateInfo);\r\n\tLuaSetDocProperty(itemType, \"type\", \"ItemType\", \"Item type\", &Item::_itype);\r\n\tLuaSetDocProperty(itemType, \"animFlag\", \"boolean\", \"Animation flag\", &Item::_iAnimFlag);\r\n\tLuaSetDocProperty(itemType, \"position\", \"Point\", \"Item world position\", &Item::position);\r\n\t// TODO: Add AnimationInfo usertype\r\n\t// LuaSetDocProperty(itemType, \"animInfo\", \"AnimationInfo\", \"Animation information\", &Item::AnimInfo);\r\n\tLuaSetDocProperty(itemType, \"delFlag\", \"boolean\", \"Deletion flag\", &Item::_iDelFlag);\r\n\tLuaSetDocProperty(itemType, \"selectionRegion\", \"number\", \"Selection region\", &Item::selectionRegion);\r\n\tLuaSetDocProperty(itemType, \"postDraw\", \"boolean\", \"Post-draw flag\", &Item::_iPostDraw);\r\n\tLuaSetDocProperty(itemType, \"identified\", \"boolean\", \"Identified flag\", &Item::_iIdentified);\r\n\tLuaSetDocProperty(itemType, \"magical\", \"number\", \"Item quality\", &Item::_iMagical);\r\n\tLuaSetDocProperty(itemType, \"name\", \"string\", \"Item name\", [](const Item &i) { return std::string_view(i._iName); }, [](Item &i, std::string_view val) { CopyUtf8(i._iName, val, sizeof(i._iName)); });\r\n\tLuaSetDocProperty(itemType, \"iName\", \"string\", \"Identified item name\", [](const Item &i) { return std::string_view(i._iIName); }, [](Item &i, std::string_view val) { CopyUtf8(i._iIName, val, sizeof(i._iIName)); });\r\n\tLuaSetDocProperty(itemType, \"loc\", \"ItemEquipType\", \"Equipment location\", &Item::_iLoc);\r\n\tLuaSetDocProperty(itemType, \"class\", \"ItemClass\", \"Item class\", &Item::_iClass);\r\n\tLuaSetDocProperty(itemType, \"curs\", \"number\", \"Cursor index\", &Item::_iCurs);\r\n\tLuaSetDocProperty(itemType, \"value\", \"number\", \"Item value\", &Item::_ivalue);\r\n\tLuaSetDocProperty(itemType, \"ivalue\", \"number\", \"Identified item value\", &Item::_iIvalue);\r\n\tLuaSetDocProperty(itemType, \"minDam\", \"number\", \"Minimum damage\", &Item::_iMinDam);\r\n\tLuaSetDocProperty(itemType, \"maxDam\", \"number\", \"Maximum damage\", &Item::_iMaxDam);\r\n\tLuaSetDocProperty(itemType, \"AC\", \"number\", \"Armor class\", &Item::_iAC);\r\n\tLuaSetDocProperty(itemType, \"flags\", \"ItemSpecialEffect\", \"Special effect flags\", &Item::_iFlags);\r\n\tLuaSetDocProperty(itemType, \"miscId\", \"ItemMiscID\", \"Miscellaneous ID\", &Item::_iMiscId);\r\n\tLuaSetDocProperty(itemType, \"spell\", \"SpellID\", \"Spell\", &Item::_iSpell);\r\n\tLuaSetDocProperty(itemType, \"IDidx\", \"ItemIndex\", \"Base item index\", &Item::IDidx);\r\n\tLuaSetDocProperty(itemType, \"charges\", \"number\", \"Number of charges\", &Item::_iCharges);\r\n\tLuaSetDocProperty(itemType, \"maxCharges\", \"number\", \"Maximum charges\", &Item::_iMaxCharges);\r\n\tLuaSetDocProperty(itemType, \"durability\", \"number\", \"Durability\", &Item::_iDurability);\r\n\tLuaSetDocProperty(itemType, \"maxDur\", \"number\", \"Maximum durability\", &Item::_iMaxDur);\r\n\tLuaSetDocProperty(itemType, \"PLDam\", \"number\", \"Damage % bonus\", &Item::_iPLDam);\r\n\tLuaSetDocProperty(itemType, \"PLToHit\", \"number\", \"Chance to hit bonus\", &Item::_iPLToHit);\r\n\tLuaSetDocProperty(itemType, \"PLAC\", \"number\", \"Armor class % bonus\", &Item::_iPLAC);\r\n\tLuaSetDocProperty(itemType, \"PLStr\", \"number\", \"Strength bonus\", &Item::_iPLStr);\r\n\tLuaSetDocProperty(itemType, \"PLMag\", \"number\", \"Magic bonus\", &Item::_iPLMag);\r\n\tLuaSetDocProperty(itemType, \"PLDex\", \"number\", \"Dexterity bonus\", &Item::_iPLDex);\r\n\tLuaSetDocProperty(itemType, \"PLVit\", \"number\", \"Vitality bonus\", &Item::_iPLVit);\r\n\tLuaSetDocProperty(itemType, \"PLFR\", \"number\", \"Fire resistance bonus\", &Item::_iPLFR);\r\n\tLuaSetDocProperty(itemType, \"PLLR\", \"number\", \"Lightning resistance bonus\", &Item::_iPLLR);\r\n\tLuaSetDocProperty(itemType, \"PLMR\", \"number\", \"Magic resistance bonus\", &Item::_iPLMR);\r\n\tLuaSetDocProperty(itemType, \"PLMana\", \"number\", \"Mana bonus\", &Item::_iPLMana);\r\n\tLuaSetDocProperty(itemType, \"PLHP\", \"number\", \"Life bonus\", &Item::_iPLHP);\r\n\tLuaSetDocProperty(itemType, \"PLDamMod\", \"number\", \"Damage modifier bonus\", &Item::_iPLDamMod);\r\n\tLuaSetDocProperty(itemType, \"PLGetHit\", \"number\", \"Damage from enemies bonus\", &Item::_iPLGetHit);\r\n\tLuaSetDocProperty(itemType, \"PLLight\", \"number\", \"Light bonus\", &Item::_iPLLight);\r\n\tLuaSetDocProperty(itemType, \"splLvlAdd\", \"number\", \"Spell level bonus\", &Item::_iSplLvlAdd);\r\n\tLuaSetDocProperty(itemType, \"request\", \"boolean\", \"Request flag\", &Item::_iRequest);\r\n\tLuaSetDocProperty(itemType, \"uid\", \"number\", \"Unique item ID\", &Item::_iUid);\r\n\tLuaSetDocProperty(itemType, \"fMinDam\", \"number\", \"Fire minimum damage\", &Item::_iFMinDam);\r\n\tLuaSetDocProperty(itemType, \"fMaxDam\", \"number\", \"Fire maximum damage\", &Item::_iFMaxDam);\r\n\tLuaSetDocProperty(itemType, \"lMinDam\", \"number\", \"Lightning minimum damage\", &Item::_iLMinDam);\r\n\tLuaSetDocProperty(itemType, \"lMaxDam\", \"number\", \"Lightning maximum damage\", &Item::_iLMaxDam);\r\n\tLuaSetDocProperty(itemType, \"PLEnAc\", \"number\", \"Damage target AC bonus\", &Item::_iPLEnAc);\r\n\tLuaSetDocProperty(itemType, \"prePower\", \"ItemEffectType\", \"Prefix power\", &Item::_iPrePower);\r\n\tLuaSetDocProperty(itemType, \"sufPower\", \"ItemEffectType\", \"Suffix power\", &Item::_iSufPower);\r\n\tLuaSetDocProperty(itemType, \"vAdd1\", \"number\", \"Value addition 1\", &Item::_iVAdd1);\r\n\tLuaSetDocProperty(itemType, \"vMult1\", \"number\", \"Value multiplier 1\", &Item::_iVMult1);\r\n\tLuaSetDocProperty(itemType, \"vAdd2\", \"number\", \"Value addition 2\", &Item::_iVAdd2);\r\n\tLuaSetDocProperty(itemType, \"vMult2\", \"number\", \"Value multiplier 2\", &Item::_iVMult2);\r\n\tLuaSetDocProperty(itemType, \"minStr\", \"number\", \"Minimum strength required\", &Item::_iMinStr);\r\n\tLuaSetDocProperty(itemType, \"minMag\", \"number\", \"Minimum magic required\", &Item::_iMinMag);\r\n\tLuaSetDocProperty(itemType, \"minDex\", \"number\", \"Minimum dexterity required\", &Item::_iMinDex);\r\n\tLuaSetDocProperty(itemType, \"statFlag\", \"boolean\", \"Equippable flag\", &Item::_iStatFlag);\r\n\tLuaSetDocProperty(itemType, \"damAcFlags\", \"ItemSpecialEffectHf\", \"Secondary special effect flags\", &Item::_iDamAcFlags);\r\n\tLuaSetDocProperty(itemType, \"buff\", \"number\", \"Secondary creation flags\", &Item::dwBuff);\r\n\r\n\t// Member functions\r\n\tLuaSetDocFn(itemType, \"pop\", \"() -> Item\", \"Clears this item and returns the old value\", &Item::pop);\r\n\tLuaSetDocFn(itemType, \"clear\", \"() -> void\", \"Resets the item\", &Item::clear);\r\n\tLuaSetDocFn(itemType, \"isEmpty\", \"() -> boolean\", \"Checks whether this item is empty\", &Item::isEmpty);\r\n\tLuaSetDocFn(itemType, \"isEquipment\", \"() -> boolean\", \"Checks if item is equipment\", &Item::isEquipment);\r\n\tLuaSetDocFn(itemType, \"isWeapon\", \"() -> boolean\", \"Checks if item is a weapon\", &Item::isWeapon);\r\n\tLuaSetDocFn(itemType, \"isArmor\", \"() -> boolean\", \"Checks if item is armor\", &Item::isArmor);\r\n\tLuaSetDocFn(itemType, \"isGold\", \"() -> boolean\", \"Checks if item is gold\", &Item::isGold);\r\n\tLuaSetDocFn(itemType, \"isHelm\", \"() -> boolean\", \"Checks if item is a helm\", &Item::isHelm);\r\n\tLuaSetDocFn(itemType, \"isShield\", \"() -> boolean\", \"Checks if item is a shield\", &Item::isShield);\r\n\tLuaSetDocFn(itemType, \"isJewelry\", \"() -> boolean\", \"Checks if item is jewelry\", &Item::isJewelry);\r\n\tLuaSetDocFn(itemType, \"isScroll\", \"() -> boolean\", \"Checks if item is a scroll\", &Item::isScroll);\r\n\tLuaSetDocFn(itemType, \"isScrollOf\", \"(spell: SpellID) -> boolean\", \"Checks if item is a scroll of a given spell\", &Item::isScrollOf);\r\n\tLuaSetDocFn(itemType, \"isRune\", \"() -> boolean\", \"Checks if item is a rune\", &Item::isRune);\r\n\tLuaSetDocFn(itemType, \"isRuneOf\", \"(spell: SpellID) -> boolean\", \"Checks if item is a rune of a given spell\", &Item::isRuneOf);\r\n\tLuaSetDocFn(itemType, \"isUsable\", \"() -> boolean\", \"Checks if item is usable\", &Item::isUsable);\r\n\tLuaSetDocFn(itemType, \"keyAttributesMatch\", \"(seed: number, idx: number, createInfo: number) -> boolean\", \"Checks if key attributes match\", &Item::keyAttributesMatch);\r\n\tLuaSetDocFn(itemType, \"getTextColor\", \"() -> UiFlags\", \"Gets the text color\", &Item::getTextColor);\r\n\tLuaSetDocFn(itemType, \"getTextColorWithStatCheck\", \"() -> UiFlags\", \"Gets the text color with stat check\", &Item::getTextColorWithStatCheck);\r\n\tLuaSetDocFn(itemType, \"setNewAnimation\", \"(showAnimation: boolean) -> void\", \"Sets the new animation\", &Item::setNewAnimation);\r\n\tLuaSetDocFn(itemType, \"updateRequiredStatsCacheForPlayer\", \"(player: Player) -> void\", \"Updates the required stats cache\", &Item::updateRequiredStatsCacheForPlayer);\r\n\tLuaSetDocFn(itemType, \"getName\", \"() -> string\", \"Gets the translated item name\", &Item::getName);\r\n}\r\n\r\nvoid RegisterItemTypeEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<ItemType>(\"ItemType\",\r\n\t    {\r\n\t        { \"Misc\", ItemType::Misc },\r\n\t        { \"Sword\", ItemType::Sword },\r\n\t        { \"Axe\", ItemType::Axe },\r\n\t        { \"Bow\", ItemType::Bow },\r\n\t        { \"Mace\", ItemType::Mace },\r\n\t        { \"Shield\", ItemType::Shield },\r\n\t        { \"LightArmor\", ItemType::LightArmor },\r\n\t        { \"Helm\", ItemType::Helm },\r\n\t        { \"MediumArmor\", ItemType::MediumArmor },\r\n\t        { \"HeavyArmor\", ItemType::HeavyArmor },\r\n\t        { \"Staff\", ItemType::Staff },\r\n\t        { \"Gold\", ItemType::Gold },\r\n\t        { \"Ring\", ItemType::Ring },\r\n\t        { \"Amulet\", ItemType::Amulet },\r\n\t        { \"None\", ItemType::None },\r\n\t    });\r\n}\r\n\r\nvoid RegisterItemEquipTypeEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<item_equip_type>(\"ItemEquipType\",\r\n\t    {\r\n\t        { \"None\", ILOC_NONE },\r\n\t        { \"OneHand\", ILOC_ONEHAND },\r\n\t        { \"TwoHand\", ILOC_TWOHAND },\r\n\t        { \"Armor\", ILOC_ARMOR },\r\n\t        { \"Helm\", ILOC_HELM },\r\n\t        { \"Ring\", ILOC_RING },\r\n\t        { \"Amulet\", ILOC_AMULET },\r\n\t        { \"Unequipable\", ILOC_UNEQUIPABLE },\r\n\t        { \"Belt\", ILOC_BELT },\r\n\t        { \"Invalid\", ILOC_INVALID },\r\n\t    });\r\n}\r\n\r\nvoid RegisterItemClassEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<item_class>(\"ItemClass\",\r\n\t    {\r\n\t        { \"None\", ICLASS_NONE },\r\n\t        { \"Weapon\", ICLASS_WEAPON },\r\n\t        { \"Armor\", ICLASS_ARMOR },\r\n\t        { \"Misc\", ICLASS_MISC },\r\n\t        { \"Gold\", ICLASS_GOLD },\r\n\t        { \"Quest\", ICLASS_QUEST },\r\n\t    });\r\n}\r\n\r\nvoid RegisterItemSpecialEffectEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<ItemSpecialEffect>(\"ItemSpecialEffect\",\r\n\t    {\r\n\t        { \"None\", ItemSpecialEffect::None },\r\n\t        { \"RandomStealLife\", ItemSpecialEffect::RandomStealLife },\r\n\t        { \"RandomArrowVelocity\", ItemSpecialEffect::RandomArrowVelocity },\r\n\t        { \"FireArrows\", ItemSpecialEffect::FireArrows },\r\n\t        { \"FireDamage\", ItemSpecialEffect::FireDamage },\r\n\t        { \"LightningDamage\", ItemSpecialEffect::LightningDamage },\r\n\t        { \"DrainLife\", ItemSpecialEffect::DrainLife },\r\n\t        { \"MultipleArrows\", ItemSpecialEffect::MultipleArrows },\r\n\t        { \"Knockback\", ItemSpecialEffect::Knockback },\r\n\t        { \"StealMana3\", ItemSpecialEffect::StealMana3 },\r\n\t        { \"StealMana5\", ItemSpecialEffect::StealMana5 },\r\n\t        { \"StealLife3\", ItemSpecialEffect::StealLife3 },\r\n\t        { \"StealLife5\", ItemSpecialEffect::StealLife5 },\r\n\t        { \"QuickAttack\", ItemSpecialEffect::QuickAttack },\r\n\t        { \"FastAttack\", ItemSpecialEffect::FastAttack },\r\n\t        { \"FasterAttack\", ItemSpecialEffect::FasterAttack },\r\n\t        { \"FastestAttack\", ItemSpecialEffect::FastestAttack },\r\n\t        { \"FastHitRecovery\", ItemSpecialEffect::FastHitRecovery },\r\n\t        { \"FasterHitRecovery\", ItemSpecialEffect::FasterHitRecovery },\r\n\t        { \"FastestHitRecovery\", ItemSpecialEffect::FastestHitRecovery },\r\n\t        { \"FastBlock\", ItemSpecialEffect::FastBlock },\r\n\t        { \"LightningArrows\", ItemSpecialEffect::LightningArrows },\r\n\t        { \"Thorns\", ItemSpecialEffect::Thorns },\r\n\t        { \"NoMana\", ItemSpecialEffect::NoMana },\r\n\t        { \"HalfTrapDamage\", ItemSpecialEffect::HalfTrapDamage },\r\n\t        { \"TripleDemonDamage\", ItemSpecialEffect::TripleDemonDamage },\r\n\t        { \"ZeroResistance\", ItemSpecialEffect::ZeroResistance },\r\n\t    });\r\n}\r\n\r\nvoid RegisterItemMiscIDEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<item_misc_id>(\"ItemMiscID\",\r\n\t    {\r\n\t        { \"None\", IMISC_NONE },\r\n\t        { \"FullHeal\", IMISC_FULLHEAL },\r\n\t        { \"Heal\", IMISC_HEAL },\r\n\t        { \"Mana\", IMISC_MANA },\r\n\t        { \"FullMana\", IMISC_FULLMANA },\r\n\t        { \"ElixirStr\", IMISC_ELIXSTR },\r\n\t        { \"ElixirMag\", IMISC_ELIXMAG },\r\n\t        { \"ElixirDex\", IMISC_ELIXDEX },\r\n\t        { \"ElixirVit\", IMISC_ELIXVIT },\r\n\t        { \"Rejuv\", IMISC_REJUV },\r\n\t        { \"FullRejuv\", IMISC_FULLREJUV },\r\n\t        { \"Scroll\", IMISC_SCROLL },\r\n\t        { \"ScrollT\", IMISC_SCROLLT },\r\n\t        { \"Staff\", IMISC_STAFF },\r\n\t        { \"Book\", IMISC_BOOK },\r\n\t        { \"Ring\", IMISC_RING },\r\n\t        { \"Amulet\", IMISC_AMULET },\r\n\t        { \"Unique\", IMISC_UNIQUE },\r\n\t    });\r\n}\r\n\r\nvoid RegisterSpellIDEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<SpellID>(\"SpellID\",\r\n\t    {\r\n\t        { \"Null\", SpellID::Null },\r\n\t        { \"Firebolt\", SpellID::Firebolt },\r\n\t        { \"Healing\", SpellID::Healing },\r\n\t        { \"Lightning\", SpellID::Lightning },\r\n\t        { \"Flash\", SpellID::Flash },\r\n\t        { \"Identify\", SpellID::Identify },\r\n\t        { \"FireWall\", SpellID::FireWall },\r\n\t        { \"TownPortal\", SpellID::TownPortal },\r\n\t        { \"StoneCurse\", SpellID::StoneCurse },\r\n\t        { \"Infravision\", SpellID::Infravision },\r\n\t        { \"Phasing\", SpellID::Phasing },\r\n\t        { \"ManaShield\", SpellID::ManaShield },\r\n\t        { \"Fireball\", SpellID::Fireball },\r\n\t        { \"Guardian\", SpellID::Guardian },\r\n\t        { \"ChainLightning\", SpellID::ChainLightning },\r\n\t        { \"FlameWave\", SpellID::FlameWave },\r\n\t        { \"DoomSerpents\", SpellID::DoomSerpents },\r\n\t        { \"BloodRitual\", SpellID::BloodRitual },\r\n\t        { \"Nova\", SpellID::Nova },\r\n\t        { \"Invisibility\", SpellID::Invisibility },\r\n\t        { \"Inferno\", SpellID::Inferno },\r\n\t        { \"Golem\", SpellID::Golem },\r\n\t        { \"Rage\", SpellID::Rage },\r\n\t        { \"Teleport\", SpellID::Teleport },\r\n\t        { \"Apocalypse\", SpellID::Apocalypse },\r\n\t        { \"Etherealize\", SpellID::Etherealize },\r\n\t        { \"ItemRepair\", SpellID::ItemRepair },\r\n\t        { \"StaffRecharge\", SpellID::StaffRecharge },\r\n\t        { \"TrapDisarm\", SpellID::TrapDisarm },\r\n\t        { \"Elemental\", SpellID::Elemental },\r\n\t        { \"ChargedBolt\", SpellID::ChargedBolt },\r\n\t        { \"HolyBolt\", SpellID::HolyBolt },\r\n\t        { \"Resurrect\", SpellID::Resurrect },\r\n\t        { \"Telekinesis\", SpellID::Telekinesis },\r\n\t        { \"HealOther\", SpellID::HealOther },\r\n\t        { \"BloodStar\", SpellID::BloodStar },\r\n\t        { \"BoneSpirit\", SpellID::BoneSpirit },\r\n\t        { \"Mana\", SpellID::Mana },\r\n\t        { \"Magi\", SpellID::Magi },\r\n\t        { \"Jester\", SpellID::Jester },\r\n\t        { \"LightningWall\", SpellID::LightningWall },\r\n\t        { \"Immolation\", SpellID::Immolation },\r\n\t        { \"Warp\", SpellID::Warp },\r\n\t        { \"Reflect\", SpellID::Reflect },\r\n\t        { \"Berserk\", SpellID::Berserk },\r\n\t        { \"RingOfFire\", SpellID::RingOfFire },\r\n\t        { \"Search\", SpellID::Search },\r\n\t        { \"RuneOfFire\", SpellID::RuneOfFire },\r\n\t        { \"RuneOfLight\", SpellID::RuneOfLight },\r\n\t        { \"RuneOfNova\", SpellID::RuneOfNova },\r\n\t        { \"RuneOfImmolation\", SpellID::RuneOfImmolation },\r\n\t        { \"RuneOfStone\", SpellID::RuneOfStone },\r\n\t        { \"Invalid\", SpellID::Invalid },\r\n\t    });\r\n}\r\n\r\nvoid RegisterItemIndexEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<_item_indexes>(\"ItemIndex\",\r\n\t    {\r\n\t        { \"Gold\", IDI_GOLD },\r\n\t        { \"Warrior\", IDI_WARRIOR },\r\n\t        { \"WarriorShield\", IDI_WARRSHLD },\r\n\t        { \"WarriorClub\", IDI_WARRCLUB },\r\n\t        { \"Rogue\", IDI_ROGUE },\r\n\t        { \"Sorcerer\", IDI_SORCERER },\r\n\t        { \"Cleaver\", IDI_CLEAVER },\r\n\t        { \"FirstQuest\", IDI_FIRSTQUEST },\r\n\t        { \"SkeletonKingCrown\", IDI_SKCROWN },\r\n\t        { \"InfravisionRing\", IDI_INFRARING },\r\n\t        { \"Rock\", IDI_ROCK },\r\n\t        { \"OpticAmulet\", IDI_OPTAMULET },\r\n\t        { \"TruthRing\", IDI_TRING },\r\n\t        { \"Banner\", IDI_BANNER },\r\n\t        { \"HarlequinCrest\", IDI_HARCREST },\r\n\t        { \"SteelVeil\", IDI_STEELVEIL },\r\n\t        { \"GoldenElixir\", IDI_GLDNELIX },\r\n\t        { \"Anvil\", IDI_ANVIL },\r\n\t        { \"Mushroom\", IDI_MUSHROOM },\r\n\t        { \"Brain\", IDI_BRAIN },\r\n\t        { \"FungalTome\", IDI_FUNGALTM },\r\n\t        { \"SpectralElixir\", IDI_SPECELIX },\r\n\t        { \"BloodStone\", IDI_BLDSTONE },\r\n\t        { \"MapOfDoom\", IDI_MAPOFDOOM },\r\n\t        { \"LastQuest\", IDI_LASTQUEST },\r\n\t        { \"Ear\", IDI_EAR },\r\n\t        { \"Heal\", IDI_HEAL },\r\n\t        { \"Mana\", IDI_MANA },\r\n\t        { \"Identify\", IDI_IDENTIFY },\r\n\t        { \"Portal\", IDI_PORTAL },\r\n\t        { \"ArmorOfValor\", IDI_ARMOFVAL },\r\n\t        { \"FullHeal\", IDI_FULLHEAL },\r\n\t        { \"FullMana\", IDI_FULLMANA },\r\n\t        { \"Griswold\", IDI_GRISWOLD },\r\n\t        { \"Lightforge\", IDI_LGTFORGE },\r\n\t        { \"LazarusStaff\", IDI_LAZSTAFF },\r\n\t        { \"Resurrect\", IDI_RESURRECT },\r\n\t        { \"Oil\", IDI_OIL },\r\n\t        { \"ShortStaff\", IDI_SHORTSTAFF },\r\n\t        { \"BardSword\", IDI_BARDSWORD },\r\n\t        { \"BardDagger\", IDI_BARDDAGGER },\r\n\t        { \"RuneBomb\", IDI_RUNEBOMB },\r\n\t        { \"Theodore\", IDI_THEODORE },\r\n\t        { \"Auric\", IDI_AURIC },\r\n\t        { \"Note1\", IDI_NOTE1 },\r\n\t        { \"Note2\", IDI_NOTE2 },\r\n\t        { \"Note3\", IDI_NOTE3 },\r\n\t        { \"FullNote\", IDI_FULLNOTE },\r\n\t        { \"BrownSuit\", IDI_BROWNSUIT },\r\n\t        { \"GreySuit\", IDI_GREYSUIT },\r\n\t        { \"Book1\", IDI_BOOK1 },\r\n\t        { \"Book2\", IDI_BOOK2 },\r\n\t        { \"Book3\", IDI_BOOK3 },\r\n\t        { \"Book4\", IDI_BOOK4 },\r\n\t        { \"Barbarian\", IDI_BARBARIAN },\r\n\t        { \"ShortBattleBow\", IDI_SHORT_BATTLE_BOW },\r\n\t        { \"RuneOfStone\", IDI_RUNEOFSTONE },\r\n\t        { \"SorcererDiablo\", IDI_SORCERER_DIABLO },\r\n\t        { \"ArenaPotion\", IDI_ARENAPOT },\r\n\t        { \"None\", IDI_NONE },\r\n\t    });\r\n}\r\n\r\nvoid RegisterItemEffectTypeEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<item_effect_type>(\"ItemEffectType\",\r\n\t    {\r\n\t        { \"ToHit\", IPL_TOHIT },\r\n\t        { \"ToHitCurse\", IPL_TOHIT_CURSE },\r\n\t        { \"DamagePercent\", IPL_DAMP },\r\n\t        { \"DamagePercentCurse\", IPL_DAMP_CURSE },\r\n\t        { \"ToHitDamagePercent\", IPL_TOHIT_DAMP },\r\n\t        { \"ToHitDamagePercentCurse\", IPL_TOHIT_DAMP_CURSE },\r\n\t        { \"ArmorClassPercent\", IPL_ACP },\r\n\t        { \"ArmorClassPercentCurse\", IPL_ACP_CURSE },\r\n\t        { \"FireResist\", IPL_FIRERES },\r\n\t        { \"LightningResist\", IPL_LIGHTRES },\r\n\t        { \"MagicResist\", IPL_MAGICRES },\r\n\t        { \"AllResist\", IPL_ALLRES },\r\n\t        { \"SpellLevelAdd\", IPL_SPLLVLADD },\r\n\t        { \"Charges\", IPL_CHARGES },\r\n\t        { \"FireDamage\", IPL_FIREDAM },\r\n\t        { \"LightningDamage\", IPL_LIGHTDAM },\r\n\t        { \"Strength\", IPL_STR },\r\n\t        { \"StrengthCurse\", IPL_STR_CURSE },\r\n\t        { \"Magic\", IPL_MAG },\r\n\t        { \"MagicCurse\", IPL_MAG_CURSE },\r\n\t        { \"Dexterity\", IPL_DEX },\r\n\t        { \"DexterityCurse\", IPL_DEX_CURSE },\r\n\t        { \"Vitality\", IPL_VIT },\r\n\t        { \"VitalityCurse\", IPL_VIT_CURSE },\r\n\t        { \"Attributes\", IPL_ATTRIBS },\r\n\t        { \"AttributesCurse\", IPL_ATTRIBS_CURSE },\r\n\t        { \"GetHitCurse\", IPL_GETHIT_CURSE },\r\n\t        { \"GetHit\", IPL_GETHIT },\r\n\t        { \"Life\", IPL_LIFE },\r\n\t        { \"LifeCurse\", IPL_LIFE_CURSE },\r\n\t        { \"Mana\", IPL_MANA },\r\n\t        { \"ManaCurse\", IPL_MANA_CURSE },\r\n\t        { \"Durability\", IPL_DUR },\r\n\t        { \"DurabilityCurse\", IPL_DUR_CURSE },\r\n\t        { \"Indestructible\", IPL_INDESTRUCTIBLE },\r\n\t        { \"Light\", IPL_LIGHT },\r\n\t        { \"LightCurse\", IPL_LIGHT_CURSE },\r\n\t        { \"MultipleArrows\", IPL_MULT_ARROWS },\r\n\t        { \"FireArrows\", IPL_FIRE_ARROWS },\r\n\t        { \"LightningArrows\", IPL_LIGHT_ARROWS },\r\n\t        { \"Thorns\", IPL_THORNS },\r\n\t        { \"NoMana\", IPL_NOMANA },\r\n\t        { \"Fireball\", IPL_FIREBALL },\r\n\t        { \"AbsorbHalfTrap\", IPL_ABSHALFTRAP },\r\n\t        { \"Knockback\", IPL_KNOCKBACK },\r\n\t        { \"StealMana\", IPL_STEALMANA },\r\n\t        { \"StealLife\", IPL_STEALLIFE },\r\n\t        { \"TargetArmorClass\", IPL_TARGAC },\r\n\t        { \"FastAttack\", IPL_FASTATTACK },\r\n\t        { \"FastRecover\", IPL_FASTRECOVER },\r\n\t        { \"FastBlock\", IPL_FASTBLOCK },\r\n\t        { \"DamageModifier\", IPL_DAMMOD },\r\n\t        { \"RandomArrowVelocity\", IPL_RNDARROWVEL },\r\n\t        { \"SetDamage\", IPL_SETDAM },\r\n\t        { \"SetDurability\", IPL_SETDUR },\r\n\t        { \"NoMinimumStrength\", IPL_NOMINSTR },\r\n\t        { \"Spell\", IPL_SPELL },\r\n\t        { \"OneHand\", IPL_ONEHAND },\r\n\t        { \"3xDamageVsDemons\", IPL_3XDAMVDEM },\r\n\t        { \"AllResistZero\", IPL_ALLRESZERO },\r\n\t        { \"DrainLife\", IPL_DRAINLIFE },\r\n\t        { \"RandomStealLife\", IPL_RNDSTEALLIFE },\r\n\t        { \"SetArmorClass\", IPL_SETAC },\r\n\t        { \"AddArmorClassLife\", IPL_ADDACLIFE },\r\n\t        { \"AddManaArmorClass\", IPL_ADDMANAAC },\r\n\t        { \"ArmorClassCurse\", IPL_AC_CURSE },\r\n\t        { \"LastDiablo\", IPL_LASTDIABLO },\r\n\t        { \"FireResistCurse\", IPL_FIRERES_CURSE },\r\n\t        { \"LightResistCurse\", IPL_LIGHTRES_CURSE },\r\n\t        { \"MagicResistCurse\", IPL_MAGICRES_CURSE },\r\n\t        { \"Devastation\", IPL_DEVASTATION },\r\n\t        { \"Decay\", IPL_DECAY },\r\n\t        { \"Peril\", IPL_PERIL },\r\n\t        { \"Jesters\", IPL_JESTERS },\r\n\t        { \"Crystalline\", IPL_CRYSTALLINE },\r\n\t        { \"Doppelganger\", IPL_DOPPELGANGER },\r\n\t        { \"ArmorClassDemon\", IPL_ACDEMON },\r\n\t        { \"ArmorClassUndead\", IPL_ACUNDEAD },\r\n\t        { \"ManaToLife\", IPL_MANATOLIFE },\r\n\t        { \"LifeToMana\", IPL_LIFETOMANA },\r\n\t        { \"Invalid\", IPL_INVALID },\r\n\t    });\r\n}\r\n\r\nvoid RegisterItemSpecialEffectHfEnum(sol::state_view &lua)\r\n{\r\n\tlua.new_enum<ItemSpecialEffectHf>(\"ItemSpecialEffectHf\",\r\n\t    {\r\n\t        { \"None\", ItemSpecialEffectHf::None },\r\n\t        { \"Devastation\", ItemSpecialEffectHf::Devastation },\r\n\t        { \"Decay\", ItemSpecialEffectHf::Decay },\r\n\t        { \"Peril\", ItemSpecialEffectHf::Peril },\r\n\t        { \"Jesters\", ItemSpecialEffectHf::Jesters },\r\n\t        { \"Doppelganger\", ItemSpecialEffectHf::Doppelganger },\r\n\t        { \"ACAgainstDemons\", ItemSpecialEffectHf::ACAgainstDemons },\r\n\t        { \"ACAgainstUndead\", ItemSpecialEffectHf::ACAgainstUndead },\r\n\t    });\r\n}\r\n\r\nvoid AddItemDataFromTsv(const std::string_view path, const int32_t baseMappingId)\r\n{\r\n\tDataFile dataFile = DataFile::loadOrDie(path);\r\n\tLoadItemDatFromFile(dataFile, path, baseMappingId);\r\n}\r\n\r\nvoid AddUniqueItemDataFromTsv(const std::string_view path, const int32_t baseMappingId)\r\n{\r\n\tDataFile dataFile = DataFile::loadOrDie(path);\r\n\tLoadUniqueItemDatFromFile(dataFile, path, baseMappingId);\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaItemModule(sol::state_view &lua)\r\n{\r\n\tInitItemUserType(lua);\r\n\tRegisterItemTypeEnum(lua);\r\n\tRegisterItemEquipTypeEnum(lua);\r\n\tRegisterItemClassEnum(lua);\r\n\tRegisterItemSpecialEffectEnum(lua);\r\n\tRegisterItemMiscIDEnum(lua);\r\n\tRegisterSpellIDEnum(lua);\r\n\tRegisterItemIndexEnum(lua);\r\n\tRegisterItemEffectTypeEnum(lua);\r\n\tRegisterItemSpecialEffectHfEnum(lua);\r\n\r\n\tsol::table table = lua.create_table();\r\n\r\n\tLuaSetDocFn(table, \"addItemDataFromTsv\", \"(path: string, baseMappingId: number)\", AddItemDataFromTsv);\r\n\tLuaSetDocFn(table, \"addUniqueItemDataFromTsv\", \"(path: string, baseMappingId: number)\", AddUniqueItemDataFromTsv);\r\n\r\n\t// Expose enums through the module table\r\n\ttable[\"ItemIndex\"] = lua[\"ItemIndex\"];\r\n\ttable[\"ItemType\"] = lua[\"ItemType\"];\r\n\ttable[\"ItemClass\"] = lua[\"ItemClass\"];\r\n\ttable[\"ItemEquipType\"] = lua[\"ItemEquipType\"];\r\n\ttable[\"ItemMiscID\"] = lua[\"ItemMiscID\"];\r\n\ttable[\"SpellID\"] = lua[\"SpellID\"];\r\n\ttable[\"ItemEffectType\"] = lua[\"ItemEffectType\"];\r\n\ttable[\"ItemSpecialEffect\"] = lua[\"ItemSpecialEffect\"];\r\n\ttable[\"ItemSpecialEffectHf\"] = lua[\"ItemSpecialEffectHf\"];\r\n\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/items.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaItemModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/log.cpp",
    "content": "#include \"lua/modules/log.hpp\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_log.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/args.h>\r\n#include <fmt/format.h>\r\n#include <sol/sol.hpp>\r\n#include <sol/utility/to_string.hpp>\r\n\r\n#include \"utils/log.hpp\"\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid LuaLogMessage(LogPriority priority, std::string_view fmt, sol::variadic_args args)\r\n{\r\n\tstd::string formatted;\r\n\tFMT_TRY\r\n\t{\r\n\t\tfmt::dynamic_format_arg_store<fmt::format_context> store;\r\n\t\tfor (const sol::stack_proxy arg : args) {\r\n\t\t\tswitch (arg.get_type()) {\r\n\t\t\tcase sol::type::boolean:\r\n\t\t\t\tstore.push_back(arg.as<bool>());\r\n\t\t\t\tbreak;\r\n\t\t\tcase sol::type::number:\r\n\t\t\t\tif (lua_isinteger(arg.lua_state(), arg.stack_index())) {\r\n\t\t\t\t\tstore.push_back(lua_tointeger(arg.lua_state(), arg.stack_index()));\r\n\t\t\t\t} else {\r\n\t\t\t\t\tstore.push_back(lua_tonumber(arg.lua_state(), arg.stack_index()));\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase sol::type::string:\r\n\t\t\t\tstore.push_back(arg.as<std::string>());\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tstore.push_back(sol::utility::to_string(sol::stack_object(arg)));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tformatted = fmt::vformat(fmt, store);\r\n\t}\r\n#if FMT_EXCEPTIONS\r\n\tFMT_CATCH(const fmt::format_error &e)\r\n\t{\r\n\t\t// e.what() is undefined if exceptions are disabled, so we wrap it\r\n\t\t// with an `FMT_EXCEPTIONS` check.\r\n\t\tstd::string error = e.what();\r\n#else\r\n\tFMT_CATCH(const fmt::format_error &)\r\n\t{\r\n\t\tstd::string error = \"unknown (FMT_EXCEPTIONS disabled)\";\r\n#endif\r\n\t\tstd::string fullError = StrCat(\"Format error, fmt: \", fmt, \" error: \", error);\r\n\t\tSDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, \"%s\", fullError.c_str());\r\n\t\treturn;\r\n\t}\r\n\tSDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, static_cast<SDL_LogPriority>(priority), \"%s\", formatted.c_str());\r\n}\r\n\r\nvoid LuaLogInfo(std::string_view fmt, sol::variadic_args args)\r\n{\r\n\tLuaLogMessage(LogPriority::Info, fmt, std::move(args));\r\n}\r\nvoid LuaLogVerbose(std::string_view fmt, sol::variadic_args args)\r\n{\r\n\tLuaLogMessage(LogPriority::Verbose, fmt, std::move(args));\r\n}\r\nvoid LuaLogDebug(std::string_view fmt, sol::variadic_args args)\r\n{\r\n\tLuaLogMessage(LogPriority::Debug, fmt, std::move(args));\r\n}\r\nvoid LuaLogWarn(std::string_view fmt, sol::variadic_args args)\r\n{\r\n\tLuaLogMessage(LogPriority::Warn, fmt, std::move(args));\r\n}\r\nvoid LuaLogError(std::string_view fmt, sol::variadic_args args)\r\n{\r\n\tLuaLogMessage(LogPriority::Error, fmt, std::move(args));\r\n}\r\n} // namespace\r\n\r\nsol::table LuaLogModule(sol::state_view &lua)\r\n{\r\n\treturn lua.create_table_with(\r\n\t    \"info\", LuaLogInfo,\r\n\t    \"verbose\", LuaLogVerbose,\r\n\t    \"debug\", LuaLogDebug,\r\n\t    \"warn\", LuaLogWarn,\r\n\t    \"error\", LuaLogError);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/log.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaLogModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/monsters.cpp",
    "content": "#include \"lua/modules/monsters.hpp\"\r\n\r\n#include <string_view>\r\n\r\n#include <fmt/format.h>\r\n#include <sol/sol.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"monster.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_split.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid AddMonsterDataFromTsv(const std::string_view path)\r\n{\r\n\tDataFile dataFile = DataFile::loadOrDie(path);\r\n\tLoadMonstDatFromFile(dataFile, path, true);\r\n}\r\n\r\nvoid AddUniqueMonsterDataFromTsv(const std::string_view path)\r\n{\r\n\tDataFile dataFile = DataFile::loadOrDie(path);\r\n\tLoadUniqueMonstDatFromFile(dataFile, path);\r\n}\r\n\r\nvoid InitMonsterUserType(sol::state_view &lua)\r\n{\r\n\tsol::usertype<Monster> monsterType = lua.new_usertype<Monster>(sol::no_constructor);\r\n\tLuaSetDocReadonlyProperty(monsterType, \"position\", \"Point\",\r\n\t    \"Monster's current position (readonly)\",\r\n\t    [](const Monster &monster) {\r\n\t\t    return Point { monster.position.tile };\r\n\t    });\r\n\tLuaSetDocReadonlyProperty(monsterType, \"id\", \"integer\",\r\n\t    \"Monster's unique ID (readonly)\",\r\n\t    [](const Monster &monster) {\r\n\t\t    return static_cast<int>(reinterpret_cast<uintptr_t>(&monster));\r\n\t    });\r\n}\r\n\r\n} // namespace\r\n\r\nsol::table LuaMonstersModule(sol::state_view &lua)\r\n{\r\n\tInitMonsterUserType(lua);\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"addMonsterDataFromTsv\", \"(path: string)\", AddMonsterDataFromTsv);\r\n\tLuaSetDocFn(table, \"addUniqueMonsterDataFromTsv\", \"(path: string)\", AddUniqueMonsterDataFromTsv);\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/monsters.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaMonstersModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/player.cpp",
    "content": "#include \"lua/modules/player.hpp\"\r\n\r\n#include <optional>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"effects.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"inv.h\"\r\n#include \"items.h\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nvoid InitPlayerUserType(sol::state_view &lua)\r\n{\r\n\tsol::usertype<Player> playerType = lua.new_usertype<Player>(sol::no_constructor);\r\n\tLuaSetDocReadonlyProperty(playerType, \"name\", \"string\",\r\n\t    \"Player's name (readonly)\",\r\n\t    &Player::name);\r\n\tLuaSetDocReadonlyProperty(playerType, \"id\", \"integer\",\r\n\t    \"Player's unique ID (readonly)\",\r\n\t    [](const Player &player) {\r\n\t\t    return static_cast<int>(reinterpret_cast<uintptr_t>(&player));\r\n\t    });\r\n\tLuaSetDocReadonlyProperty(playerType, \"position\", \"Point\",\r\n\t    \"Player's current position (readonly)\",\r\n\t    [](const Player &player) -> Point {\r\n\t\t    return Point { player.position.tile };\r\n\t    });\r\n\tLuaSetDocFn(playerType, \"addExperience\", \"(experience: integer, monsterLevel: integer = nil)\",\r\n\t    \"Adds experience to this player based on the current game mode\",\r\n\t    [](Player &player, uint32_t experience, std::optional<int> monsterLevel) {\r\n\t\t    if (monsterLevel.has_value()) {\r\n\t\t\t    player.addExperience(experience, *monsterLevel);\r\n\t\t    } else {\r\n\t\t\t    player.addExperience(experience);\r\n\t\t    }\r\n\t    });\r\n\tLuaSetDocProperty(playerType, \"characterLevel\", \"number\",\r\n\t    \"Character level (writeable)\",\r\n\t    &Player::getCharacterLevel, &Player::setCharacterLevel);\r\n\tLuaSetDocFn(playerType, \"addItem\", \"(itemId: integer, count: integer = 1)\",\r\n\t    \"Add an item to the player's inventory\",\r\n\t    [](Player &player, int itemId, std::optional<int> count) -> bool {\r\n\t\t    const _item_indexes itemIndex = static_cast<_item_indexes>(itemId);\r\n\t\t    const int itemCount = count.value_or(1);\r\n\t\t    for (int i = 0; i < itemCount; i++) {\r\n\t\t\t    Item tempItem {};\r\n\t\t\t    SetupAllItems(player, tempItem, itemIndex, AdvanceRndSeed(), 1, 1, true, false);\r\n\t\t\t    if (!AutoPlaceItemInInventory(player, tempItem, true)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t    }\r\n\t\t    CalcPlrInv(player, true);\r\n\t\t    return true;\r\n\t    });\r\n\tLuaSetDocFn(playerType, \"hasItem\", \"(itemId: integer)\",\r\n\t    \"Check if the player has an item with the given ID\",\r\n\t    [](const Player &player, int itemId) -> bool {\r\n\t\t    return HasInventoryOrBeltItemWithId(player, static_cast<_item_indexes>(itemId));\r\n\t    });\r\n\tLuaSetDocFn(playerType, \"removeItem\", \"(itemId: integer, count: integer = 1)\",\r\n\t    \"Remove an item from the player's inventory\",\r\n\t    [](Player &player, int itemId, std::optional<int> count) -> int {\r\n\t\t    const _item_indexes targetId = static_cast<_item_indexes>(itemId);\r\n\t\t    const int itemCount = count.value_or(1);\r\n\t\t    int removed = 0;\r\n\r\n\t\t    // Remove from inventory\r\n\t\t    for (int i = player._pNumInv - 1; i >= 0 && removed < itemCount; i--) {\r\n\t\t\t    if (player.InvList[i].IDidx == targetId) {\r\n\t\t\t\t    player.RemoveInvItem(i);\r\n\t\t\t\t    removed++;\r\n\t\t\t    }\r\n\t\t    }\r\n\r\n\t\t    // Remove from belt if needed\r\n\t\t    for (int i = MaxBeltItems - 1; i >= 0 && removed < itemCount; i--) {\r\n\t\t\t    if (!player.SpdList[i].isEmpty() && player.SpdList[i].IDidx == targetId) {\r\n\t\t\t\t    player.RemoveSpdBarItem(i);\r\n\t\t\t\t    removed++;\r\n\t\t\t    }\r\n\t\t    }\r\n\r\n\t\t    if (removed > 0) {\r\n\t\t\t    CalcPlrInv(player, true);\r\n\t\t    }\r\n\r\n\t\t    return removed;\r\n\t    });\r\n\tLuaSetDocFn(playerType, \"restoreFullLife\", \"()\",\r\n\t    \"Restore player's HP to maximum\",\r\n\t    [](Player &player) {\r\n\t\t    player._pHitPoints = player._pMaxHP;\r\n\t\t    player._pHPBase = player._pMaxHPBase;\r\n\t    });\r\n\tLuaSetDocFn(playerType, \"restoreFullMana\", \"()\",\r\n\t    \"Restore player's mana to maximum\",\r\n\t    [](Player &player) {\r\n\t\t    player._pMana = player._pMaxMana;\r\n\t\t    player._pManaBase = player._pMaxManaBase;\r\n\t    });\r\n\tLuaSetDocReadonlyProperty(playerType, \"mana\", \"number\",\r\n\t    \"Current mana (readonly)\",\r\n\t    [](Player &player) { return player._pMana >> 6; });\r\n\tLuaSetDocReadonlyProperty(playerType, \"maxMana\", \"number\",\r\n\t    \"Maximum mana (readonly)\",\r\n\t    [](Player &player) { return player._pMaxMana >> 6; });\r\n}\r\n} // namespace\r\n\r\nsol::table LuaPlayerModule(sol::state_view &lua)\r\n{\r\n\tInitPlayerUserType(lua);\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"self\", \"()\",\r\n\t    \"The current player\",\r\n\t    []() {\r\n\t\t    return MyPlayer;\r\n\t    });\r\n\tLuaSetDocFn(table, \"walk_to\", \"(x: integer, y: integer)\",\r\n\t    \"Walk to the given coordinates\",\r\n\t    [](int x, int y) {\r\n\t\t    NetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, Point { x, y });\r\n\t    });\r\n\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/player.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaPlayerModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/render.cpp",
    "content": "#include \"lua/modules/render.hpp\"\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"utils/display.h\"\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaRenderModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\tLuaSetDocFn(table, \"string\", \"(text: string, x: integer, y: integer)\",\r\n\t    \"Renders a string at the given coordinates\",\r\n\t    [](std::string_view text, int x, int y) { DrawString(GlobalBackBuffer(), text, { x, y }); });\r\n\tLuaSetDocFn(table, \"screen_width\", \"()\",\r\n\t    \"Returns the screen width\", []() { return gnScreenWidth; });\r\n\tLuaSetDocFn(table, \"screen_height\", \"()\",\r\n\t    \"Returns the screen height\", []() { return gnScreenHeight; });\r\n\r\n\tauto uiFlags = lua.create_table();\r\n\tuiFlags[\"None\"] = UiFlags::None;\r\n\r\n\tuiFlags[\"FontSize12\"] = UiFlags::FontSize12;\r\n\tuiFlags[\"FontSize24\"] = UiFlags::FontSize24;\r\n\tuiFlags[\"FontSize30\"] = UiFlags::FontSize30;\r\n\tuiFlags[\"FontSize42\"] = UiFlags::FontSize42;\r\n\tuiFlags[\"FontSize46\"] = UiFlags::FontSize46;\r\n\tuiFlags[\"FontSizeDialog\"] = UiFlags::FontSizeDialog;\r\n\r\n\tuiFlags[\"ColorUiGold\"] = UiFlags::ColorUiGold;\r\n\tuiFlags[\"ColorUiSilver\"] = UiFlags::ColorUiSilver;\r\n\tuiFlags[\"ColorUiGoldDark\"] = UiFlags::ColorUiGoldDark;\r\n\tuiFlags[\"ColorUiSilverDark\"] = UiFlags::ColorUiSilverDark;\r\n\tuiFlags[\"ColorDialogWhite\"] = UiFlags::ColorDialogWhite;\r\n\tuiFlags[\"ColorDialogYellow\"] = UiFlags::ColorDialogYellow;\r\n\tuiFlags[\"ColorDialogRed\"] = UiFlags::ColorDialogRed;\r\n\tuiFlags[\"ColorYellow\"] = UiFlags::ColorYellow;\r\n\tuiFlags[\"ColorGold\"] = UiFlags::ColorGold;\r\n\tuiFlags[\"ColorBlack\"] = UiFlags::ColorBlack;\r\n\tuiFlags[\"ColorWhite\"] = UiFlags::ColorWhite;\r\n\tuiFlags[\"ColorWhitegold\"] = UiFlags::ColorWhitegold;\r\n\tuiFlags[\"ColorRed\"] = UiFlags::ColorRed;\r\n\tuiFlags[\"ColorBlue\"] = UiFlags::ColorBlue;\r\n\tuiFlags[\"ColorOrange\"] = UiFlags::ColorOrange;\r\n\tuiFlags[\"ColorButtonface\"] = UiFlags::ColorButtonface;\r\n\tuiFlags[\"ColorButtonpushed\"] = UiFlags::ColorButtonpushed;\r\n\r\n\tuiFlags[\"AlignCenter\"] = UiFlags::AlignCenter;\r\n\tuiFlags[\"AlignRight\"] = UiFlags::AlignRight;\r\n\tuiFlags[\"VerticalCenter\"] = UiFlags::VerticalCenter;\r\n\r\n\tuiFlags[\"KerningFitSpacing\"] = UiFlags::KerningFitSpacing;\r\n\r\n\tuiFlags[\"ElementDisabled\"] = UiFlags::ElementDisabled;\r\n\tuiFlags[\"ElementHidden\"] = UiFlags::ElementHidden;\r\n\r\n\tuiFlags[\"PentaCursor\"] = UiFlags::PentaCursor;\r\n\tuiFlags[\"Outlined\"] = UiFlags::Outlined;\r\n\r\n\tuiFlags[\"NeedsNextElement\"] = UiFlags::NeedsNextElement;\r\n\r\n\ttable[\"UiFlags\"] = uiFlags;\r\n\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/render.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaRenderModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/system.cpp",
    "content": "#include \"lua/modules/system.hpp\"\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"lua/metadoc.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaSystemModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\r\n\tLuaSetDocFn(table, \"get_ticks\", \"() -> integer\", \"Returns the number of milliseconds since the game started.\",\r\n\t    []() { return static_cast<int>(SDL_GetTicks()); });\r\n\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/system.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaSystemModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/towners.cpp",
    "content": "#include \"lua/modules/towners.hpp\"\r\n\r\n#include <optional>\r\n#include <unordered_map>\r\n#include <utility>\r\n\r\n#include <sol/sol.hpp>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"lua/metadoc.hpp\"\r\n#include \"player.h\"\r\n#include \"towners.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\n// Map from towner type enum to Lua table name\r\nconst std::unordered_map<_talker_id, const char *> TownerTableNames = {\r\n\t{ TOWN_SMITH, \"griswold\" },\r\n\t{ TOWN_HEALER, \"pepin\" },\r\n\t{ TOWN_DEADGUY, \"deadguy\" },\r\n\t{ TOWN_TAVERN, \"ogden\" },\r\n\t{ TOWN_STORY, \"cain\" },\r\n\t{ TOWN_DRUNK, \"farnham\" },\r\n\t{ TOWN_WITCH, \"adria\" },\r\n\t{ TOWN_BMAID, \"gillian\" },\r\n\t{ TOWN_PEGBOY, \"wirt\" },\r\n\t{ TOWN_COW, \"cow\" },\r\n\t{ TOWN_FARMER, \"lester\" },\r\n\t{ TOWN_GIRL, \"celia\" },\r\n\t{ TOWN_COWFARM, \"nut\" },\r\n};\r\n\r\nvoid PopulateTownerTable(_talker_id townerId, sol::table &out)\r\n{\r\n\tLuaSetDocFn(out, \"position\", \"()\",\r\n\t    \"Returns towner coordinates\",\r\n\t    [townerId]() -> std::optional<std::pair<int, int>> {\r\n\t\t    const Towner *towner = GetTowner(townerId);\r\n\t\t    if (towner == nullptr) return std::nullopt;\r\n\t\t    return std::make_pair(towner->position.x, towner->position.y);\r\n\t    });\r\n}\r\n} // namespace\r\n\r\nsol::table LuaTownersModule(sol::state_view &lua)\r\n{\r\n\tsol::table table = lua.create_table();\r\n\t// Iterate over all towner types found in TSV data\r\n\tfor (const auto &[townerId, name] : TownerLongNames) {\r\n\t\tauto tableNameIt = TownerTableNames.find(townerId);\r\n\t\tif (tableNameIt == TownerTableNames.end())\r\n\t\t\tcontinue; // Skip if no table name mapping\r\n\r\n\t\tsol::table townerTable = lua.create_table();\r\n\t\tPopulateTownerTable(townerId, townerTable);\r\n\t\tLuaSetDoc(table, tableNameIt->second, /*signature=*/\"\", name.c_str(), std::move(townerTable));\r\n\t}\r\n\treturn table;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/modules/towners.hpp",
    "content": "#pragma once\r\n\r\n#include <sol/sol.hpp>\r\n\r\nnamespace devilution {\r\n\r\nsol::table LuaTownersModule(sol::state_view &lua);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/lua/repl.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"lua/repl.hpp\"\r\n\r\n#include <cstddef>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <expected.hpp>\r\n#include <sol/sol.hpp>\r\n#include <sol/utility/to_string.hpp>\r\n\r\n#include \"lua/lua_global.hpp\"\r\n#include \"panels/console.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstd::optional<sol::environment> replEnv;\r\n\r\nvoid LuaConsoleWarn(void *userData, const char *message, int continued)\r\n{\r\n\tstatic std::string warnBuffer;\r\n\twarnBuffer.append(message);\r\n\tif (continued != 0)\r\n\t\treturn;\r\n\tPrintWarningToConsole(warnBuffer);\r\n\twarnBuffer.clear();\r\n}\r\n\r\nint LuaPrintToConsole(lua_State *state)\r\n{\r\n\tstd::string result;\r\n\tconst int n = lua_gettop(state);\r\n\tfor (int i = 1; i <= n; i++) {\r\n\t\tsize_t l;\r\n\t\tconst char *s = luaL_tolstring(state, i, &l);\r\n\t\tif (i > 1)\r\n\t\t\tresult += '\\t';\r\n\t\tresult.append(s, l);\r\n\t\tlua_pop(state, 1);\r\n\t}\r\n\tPrintToConsole(result);\r\n\treturn 0;\r\n}\r\n\r\nvoid CreateReplEnvironment()\r\n{\r\n\tsol::environment env = CreateLuaSandbox();\r\n\tenv[\"print\"] = LuaPrintToConsole;\r\n\tlua_setwarnf(env.lua_state(), LuaConsoleWarn, /*ud=*/nullptr);\r\n\treplEnv.emplace(env);\r\n}\r\n\r\nsol::protected_function_result TryRunLuaAsExpressionThenStatement(std::string_view code)\r\n{\r\n\t// Try to compile as an expression first. This also how the `lua` repl is implemented.\r\n\tsol::state &lua = GetLuaState();\r\n\tstd::string expression = StrCat(\"return \", code, \";\");\r\n\tsol::detail::typical_chunk_name_t basechunkname = {};\r\n\tsol::load_status status = static_cast<sol::load_status>(\r\n\t    luaL_loadbufferx(lua.lua_state(), expression.data(), expression.size(),\r\n\t        sol::detail::make_chunk_name(expression, sol::detail::default_chunk_name(), basechunkname), \"text\"));\r\n\tif (status != sol::load_status::ok) {\r\n\t\t// Try as a statement:\r\n\t\tstatus = static_cast<sol::load_status>(\r\n\t\t    luaL_loadbufferx(lua.lua_state(), code.data(), code.size(),\r\n\t\t        sol::detail::make_chunk_name(code, sol::detail::default_chunk_name(), basechunkname), \"text\"));\r\n\t\tif (status != sol::load_status::ok) {\r\n\t\t\treturn sol::protected_function_result(\r\n\t\t\t    lua.lua_state(), sol::absolute_index(lua.lua_state(), -1), 0, 1, static_cast<sol::call_status>(status));\r\n\t\t}\r\n\t}\r\n\tsol::stack_aligned_protected_function fn(lua.lua_state(), -1);\r\n\tsol::set_environment(GetLuaReplEnvironment(), fn);\r\n\treturn fn();\r\n}\r\n\r\n} // namespace\r\n\r\nsol::environment &GetLuaReplEnvironment()\r\n{\r\n\tif (!replEnv.has_value())\r\n\t\tCreateReplEnvironment();\r\n\treturn *replEnv;\r\n}\r\n\r\ntl::expected<std::string, std::string> RunLuaReplLine(std::string_view code)\r\n{\r\n\tconst sol::protected_function_result result = TryRunLuaAsExpressionThenStatement(code);\r\n\tif (!result.valid()) {\r\n\t\tif (result.get_type() == sol::type::string) {\r\n\t\t\treturn tl::make_unexpected(result.get<std::string>());\r\n\t\t}\r\n\t\treturn tl::make_unexpected(\"Unknown Lua error\");\r\n\t}\r\n\tif (result.get_type() == sol::type::none) {\r\n\t\treturn std::string {};\r\n\t}\r\n\treturn sol::utility::to_string(sol::stack_object(result));\r\n}\r\n\r\nvoid LuaReplShutdown()\r\n{\r\n\treplEnv = std::nullopt;\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/lua/repl.hpp",
    "content": "#pragma once\r\n#ifdef _DEBUG\r\n\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <expected.hpp>\r\n#include <sol/forward.hpp>\r\n\r\nnamespace devilution {\r\n\r\ntl::expected<std::string, std::string> RunLuaReplLine(std::string_view code);\r\n\r\nsol::environment &GetLuaReplEnvironment();\r\n\r\nvoid LuaReplShutdown();\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/main.cpp",
    "content": "#ifdef USE_SDL3\r\n#include <SDL3/SDL.h>\r\n#else\r\n#include <SDL.h>\r\n#include <SDL_main.h>\r\n#endif\r\n\r\n#ifdef __SWITCH__\r\n#include \"platform/switch/network.h\"\r\n#include \"platform/switch/random.hpp\"\r\n#include \"platform/switch/romfs.hpp\"\r\n#endif\r\n#ifdef __3DS__\r\n#include \"platform/ctr/system.h\"\r\n#endif\r\n#ifdef __vita__\r\n#include \"platform/vita/network.h\"\r\n#include \"platform/vita/random.hpp\"\r\n#endif\r\n#ifdef NXDK\r\n#include <nxdk/mount.h>\r\n#endif\r\n#ifdef GPERF_HEAP_MAIN\r\n#include <gperftools/heap-profiler.h>\r\n#endif\r\n\r\n#include \"diablo.h\"\r\n\r\n#if !defined(__APPLE__)\r\nextern \"C\" const char *__asan_default_options() // NOLINT(bugprone-reserved-identifier, readability-identifier-naming)\r\n{\r\n\treturn \"halt_on_error=0\";\r\n}\r\n#endif\r\n\r\nextern \"C\" int main(int argc, char **argv)\r\n{\r\n#ifdef __SWITCH__\r\n\tswitch_romfs_init();\r\n\tswitch_enable_network();\r\n#ifdef PACKET_ENCRYPTION\r\n\trandombytes_switchrandom_init();\r\n#endif\r\n#endif\r\n#ifdef __3DS__\r\n\tctr_sys_init();\r\n#endif\r\n#ifdef __vita__\r\n\tvita_enable_network();\r\n#ifdef PACKET_ENCRYPTION\r\n\trandombytes_vitarandom_init();\r\n#endif\r\n#endif\r\n#ifdef NXDK\r\n\tnxMountDrive('E', \"\\\\Device\\\\Harddisk0\\\\Partition1\\\\\");\r\n#endif\r\n#ifdef GPERF_HEAP_MAIN\r\n\tHeapProfilerStart(\"main\");\r\n#endif\r\n\tconst int result = devilution::DiabloMain(argc, argv);\r\n#ifdef GPERF_HEAP_MAIN\r\n\tHeapProfilerStop();\r\n#endif\r\n\treturn result;\r\n}\r\n"
  },
  {
    "path": "Source/menu.cpp",
    "content": "/**\r\n * @file mainmenu.cpp\r\n *\r\n * Implementation of functions for interacting with the main menu.\r\n */\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"DiabloUI/settingsmenu.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"game_mode.hpp\"\r\n#include \"init.hpp\"\r\n#include \"movie.h\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nuint32_t gSaveNumber;\r\n\r\nnamespace {\r\n\r\n_music_id NextTrack()\r\n{\r\n\tif (gbIsSpawn) {\r\n\t\treturn TMUSIC_INTRO;\r\n\t}\r\n\r\n\tswitch (sgnMusicTrack) {\r\n\tcase TMUSIC_INTRO:\r\n\t\treturn TMUSIC_CATACOMBS;\r\n\tcase TMUSIC_CATACOMBS:\r\n\t\treturn TMUSIC_CAVES;\r\n\tcase TMUSIC_CAVES:\r\n\t\treturn TMUSIC_HELL;\r\n\tcase TMUSIC_HELL:\r\n\t\treturn gbIsHellfire ? TMUSIC_NEST : TMUSIC_INTRO;\r\n\tcase TMUSIC_NEST:\r\n\t\treturn gbIsHellfire ? TMUSIC_CRYPT : TMUSIC_INTRO;\r\n\tdefault:\r\n\t\treturn TMUSIC_INTRO;\r\n\t}\r\n}\r\n\r\nvoid RefreshMusic()\r\n{\r\n\tmusic_start(NextTrack());\r\n}\r\n\r\nbool InitMenu(_selhero_selections type)\r\n{\r\n\tbool success;\r\n\r\n\tif (type == SELHERO_PREVIOUS)\r\n\t\treturn true;\r\n\r\n\tsuccess = StartGame(type != SELHERO_CONTINUE, type != SELHERO_CONNECT);\r\n\tif (success)\r\n\t\tRefreshMusic();\r\n\r\n\treturn success;\r\n}\r\n\r\nbool InitSinglePlayerMenu()\r\n{\r\n\tgbIsMultiplayer = false;\r\n\treturn InitMenu(SELHERO_NEW_DUNGEON);\r\n}\r\n\r\nbool InitMultiPlayerMenu()\r\n{\r\n\tgbIsMultiplayer = true;\r\n\treturn InitMenu(SELHERO_CONNECT);\r\n}\r\n\r\nvoid PlayIntro()\r\n{\r\n\tmusic_stop();\r\n\tif (gbIsHellfire)\r\n\t\tplay_movie(\"gendata\\\\Hellfire.smk\", true);\r\n\telse\r\n\t\tplay_movie(\"gendata\\\\diablo1.smk\", true);\r\n\tRefreshMusic();\r\n}\r\n\r\nbool DummyGetHeroInfo(_uiheroinfo * /*pInfo*/)\r\n{\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nbool mainmenu_select_hero_dialog(GameData *gameData)\r\n{\r\n\tOptionEntryInt<uint32_t> *pSaveNumberFromOptions = nullptr;\r\n\t_selhero_selections dlgresult = SELHERO_NEW_DUNGEON;\r\n\tif (demo::IsRunning()) {\r\n\t\tpfile_ui_set_hero_infos(DummyGetHeroInfo);\r\n\t\tgbLoadGame = true;\r\n\t} else if (!gbIsMultiplayer) {\r\n\t\tpSaveNumberFromOptions = gbIsHellfire ? &GetOptions().Hellfire.lastSinglePlayerHero : &GetOptions().Diablo.lastSinglePlayerHero;\r\n\t\tgSaveNumber = **pSaveNumberFromOptions;\r\n\t\tUiSelHeroSingDialog(\r\n\t\t    pfile_ui_set_hero_infos,\r\n\t\t    pfile_ui_save_create,\r\n\t\t    pfile_delete_save,\r\n\t\t    pfile_ui_set_class_stats,\r\n\t\t    &dlgresult,\r\n\t\t    &gSaveNumber,\r\n\t\t    &gameData->nDifficulty);\r\n\r\n\t\tgbLoadGame = (dlgresult == SELHERO_CONTINUE);\r\n\t} else {\r\n\t\tpSaveNumberFromOptions = gbIsHellfire ? &GetOptions().Hellfire.lastMultiplayerHero : &GetOptions().Diablo.lastMultiplayerHero;\r\n\t\tgSaveNumber = **pSaveNumberFromOptions;\r\n\t\tUiSelHeroMultDialog(\r\n\t\t    pfile_ui_set_hero_infos,\r\n\t\t    pfile_ui_save_create,\r\n\t\t    pfile_delete_save,\r\n\t\t    pfile_ui_set_class_stats,\r\n\t\t    &dlgresult,\r\n\t\t    &gSaveNumber);\r\n\t}\r\n\tif (dlgresult == SELHERO_PREVIOUS) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (pSaveNumberFromOptions != nullptr)\r\n\t\tpSaveNumberFromOptions->SetValue(gSaveNumber);\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid mainmenu_wait_for_button_sound()\r\n{\r\n\tSDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);\r\n\tUiFadeIn();\r\n\tSDL_Delay(350); // delay to let button pressed sound finish playing\r\n}\r\n\r\nvoid mainmenu_loop()\r\n{\r\n\tbool done;\r\n\r\n\tRefreshMusic();\r\n\tdone = false;\r\n\r\n\tdo {\r\n\t\t_mainmenu_selections menu = MAINMENU_NONE;\r\n\t\tif (demo::IsRunning())\r\n\t\t\tmenu = MAINMENU_SINGLE_PLAYER;\r\n\t\telse if (!UiMainMenuDialog(gszProductName, &menu, 30))\r\n\t\t\tapp_fatal(_(\"Unable to display mainmenu\"));\r\n\r\n\t\tswitch (menu) {\r\n\t\tcase MAINMENU_NONE:\r\n\t\t\tbreak;\r\n\t\tcase MAINMENU_SINGLE_PLAYER:\r\n\t\t\tif (!InitSinglePlayerMenu())\r\n\t\t\t\tdone = true;\r\n\t\t\tbreak;\r\n\t\tcase MAINMENU_MULTIPLAYER:\r\n\t\t\tif (!InitMultiPlayerMenu())\r\n\t\t\t\tdone = true;\r\n\t\t\tbreak;\r\n\t\tcase MAINMENU_ATTRACT_MODE:\r\n\t\t\tif (gbIsSpawn && !HaveIntro())\r\n\t\t\t\tdone = false;\r\n\t\t\telse if (gbActive)\r\n\t\t\t\tPlayIntro();\r\n\t\t\tbreak;\r\n\t\tcase MAINMENU_SHOW_CREDITS:\r\n\t\t\tUiCreditsDialog();\r\n\t\t\tbreak;\r\n\t\tcase MAINMENU_SHOW_SUPPORT:\r\n\t\t\tUiSupportDialog();\r\n\t\t\tbreak;\r\n\t\tcase MAINMENU_EXIT_DIABLO:\r\n\t\t\tmainmenu_wait_for_button_sound();\r\n\t\t\tdone = true;\r\n\t\t\tbreak;\r\n\t\tcase MAINMENU_SETTINGS:\r\n\t\t\tUiSettingsMenu();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} while (!done);\r\n\r\n\tmusic_stop();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/menu.h",
    "content": "/**\r\n * @file menu.h\r\n *\r\n * Interface of functions for interacting with the main menu.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"multi.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern uint32_t gSaveNumber;\r\n\r\nbool mainmenu_select_hero_dialog(GameData *gameData);\r\nvoid mainmenu_loop();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/minitext.cpp",
    "content": "/**\r\n * @file minitext.cpp\r\n *\r\n * Implementation of scrolling dialog text.\r\n */\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"control/control.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/timer.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool qtextflag;\r\n\r\nnamespace {\r\n\r\n/** Vertical speed of the scrolling text in ms/px */\r\nint qtextSpd;\r\n/** Start time of scrolling */\r\nuint32_t ScrollStart;\r\n/** Graphics for the window border */\r\nOptionalOwnedClxSpriteList pTextBoxCels;\r\n\r\n/** Pixels for a line of text and the empty space under it. */\r\nconst int LineHeight = 38;\r\n\r\nstd::vector<std::string> TextLines;\r\n\r\nvoid LoadText(std::string_view text)\r\n{\r\n\tTextLines.clear();\r\n\r\n\tconst std::string paragraphs = WordWrapString(text, 543, GameFont30);\r\n\r\n\tsize_t previous = 0;\r\n\twhile (true) {\r\n\t\tconst size_t next = paragraphs.find('\\n', previous);\r\n\t\tTextLines.emplace_back(paragraphs.substr(previous, next - previous));\r\n\t\tif (next == std::string::npos)\r\n\t\t\tbreak;\r\n\t\tprevious = next + 1;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Calculate the speed the current text should scroll to match the given audio\r\n * @param nSFX The index of the sound in the sgSFX table\r\n * @return ms/px\r\n */\r\nuint32_t CalculateTextSpeed(SfxID nSFX)\r\n{\r\n\tconst auto numLines = static_cast<uint32_t>(TextLines.size());\r\n\r\n#ifndef NOSOUND\r\n\tuint32_t sfxFrames = GetSFXLength(nSFX);\r\n#else\r\n\t// Sound is disabled -- estimate length from the number of lines.\r\n\tuint32_t sfxFrames = numLines * 3000;\r\n#endif\r\n\tassert(sfxFrames != 0);\r\n\r\n\tuint32_t textHeight = LineHeight * numLines;\r\n\ttextHeight += LineHeight * 5; // adjust so when speaker is done two line are left\r\n\tassert(textHeight != 0);\r\n\r\n\treturn sfxFrames / textHeight;\r\n}\r\n\r\nint CalculateTextPosition()\r\n{\r\n\tconst uint32_t currTime = GetMillisecondsSinceStartup();\r\n\r\n\tconst int y = (currTime - ScrollStart) / qtextSpd - 260;\r\n\r\n\tconst auto textHeight = static_cast<int>(LineHeight * TextLines.size());\r\n\tif (y >= textHeight)\r\n\t\tqtextflag = false;\r\n\r\n\treturn y;\r\n}\r\n\r\n/**\r\n * @brief Draw the current text in the quest dialog window\r\n */\r\nvoid DrawQTextContent(const Surface &out)\r\n{\r\n\tconst int y = CalculateTextPosition();\r\n\r\n\tconst int sx = GetUIRectangle().position.x + 48;\r\n\tconst int sy = 0 - (y % LineHeight);\r\n\r\n\tconst unsigned int skipLines = y / LineHeight;\r\n\r\n\tfor (int i = 0; i < 8; i++) {\r\n\t\tconst unsigned int lineNumber = skipLines + i;\r\n\t\tif (lineNumber >= TextLines.size()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst std::string &line = TextLines[lineNumber];\r\n\t\tif (line.empty()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tDrawString(out, line, { { sx, sy + i * LineHeight }, { 543, LineHeight } },\r\n\t\t    { .flags = UiFlags::FontSize30 | UiFlags::ColorGold });\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid FreeQuestText()\r\n{\r\n\tpTextBoxCels = std::nullopt;\r\n}\r\n\r\nvoid InitQuestText()\r\n{\r\n\tpTextBoxCels = LoadCel(\"data\\\\textbox\", 591);\r\n}\r\n\r\nvoid InitQTextMsg(_speech_id m)\r\n{\r\n\tSfxID sfxnr = Speeches[m].sfxnr;\r\n\tswitch (sfxnr) {\r\n\tcase SfxID::Warrior1:\r\n\t\tsfxnr = GetHeroSound(MyPlayer->_pClass, HeroSpeech::ChamberOfBoneLore);\r\n\t\tbreak;\r\n\tcase SfxID::Warrior10:\r\n\t\tsfxnr = GetHeroSound(MyPlayer->_pClass, HeroSpeech::ValorLore);\r\n\t\tbreak;\r\n\tcase SfxID::Warrior11:\r\n\t\tsfxnr = GetHeroSound(MyPlayer->_pClass, HeroSpeech::HallsOfTheBlindLore);\r\n\t\tbreak;\r\n\tcase SfxID::Warrior12:\r\n\t\tsfxnr = GetHeroSound(MyPlayer->_pClass, HeroSpeech::WarlordOfBloodLore);\r\n\t\tbreak;\r\n\tcase SfxID::Warrior54:\r\n\t\tsfxnr = GetHeroSound(MyPlayer->_pClass, HeroSpeech::InSpirituSanctum);\r\n\t\tbreak;\r\n\tcase SfxID::Warrior55:\r\n\t\tsfxnr = GetHeroSound(MyPlayer->_pClass, HeroSpeech::PraedictumOtium);\r\n\t\tbreak;\r\n\tcase SfxID::Warrior56:\r\n\t\tsfxnr = GetHeroSound(MyPlayer->_pClass, HeroSpeech::EfficioObitusUtInimicus);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\tif (Speeches[m].scrlltxt) {\r\n\t\tQuestLogIsOpen = false;\r\n\t\tLoadText(_(Speeches[m].txtstr));\r\n\t\tqtextflag = true;\r\n\t\tqtextSpd = CalculateTextSpeed(sfxnr);\r\n\t\tScrollStart = GetMillisecondsSinceStartup();\r\n\t}\r\n\tPlaySFX(sfxnr);\r\n}\r\n\r\nvoid DrawQTextBack(const Surface &out)\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tClxDraw(out, uiPosition + Displacement { 24, 327 }, (*pTextBoxCels)[0]);\r\n\tDrawHalfTransparentRectTo(out, uiPosition.x + 27, uiPosition.y + 28, 585, 297);\r\n}\r\n\r\nvoid DrawQText(const Surface &out)\r\n{\r\n\tDrawQTextBack(out);\r\n\tDrawQTextContent(out.subregionY(GetUIRectangle().position.y + 49, 260));\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/minitext.h",
    "content": "/**\r\n * @file minitext.h\r\n *\r\n * Interface of scrolling dialog text.\r\n */\r\n#pragma once\r\n\r\n#include \"engine/surface.hpp\"\r\n#include \"tables/textdat.h\"\r\n\r\nnamespace devilution {\r\n\r\n/** Specify if the quest dialog window is being shown */\r\nextern bool qtextflag;\r\n\r\n/**\r\n * @brief Free the resources used by the quest dialog window\r\n */\r\nvoid FreeQuestText();\r\n\r\n/**\r\n * @brief Load the resources used by the quest dialog window, and initialize it's state\r\n */\r\nvoid InitQuestText();\r\n\r\n/**\r\n * @brief Start the given naration\r\n * @param m Index of narration from the Texts table\r\n */\r\nvoid InitQTextMsg(_speech_id m);\r\n\r\n/**\r\n * @brief Draw the quest dialog window decoration and background.\r\n */\r\nvoid DrawQTextBack(const Surface &out);\r\n\r\n/**\r\n * @brief Draw the quest dialog window text.\r\n */\r\nvoid DrawQText(const Surface &out);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/missiles.cpp",
    "content": "/**\r\n * @file missiles.cpp\r\n *\r\n * Implementation of missile functionality.\r\n */\r\n#include \"missiles.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cassert>\r\n#include <climits>\r\n#include <cmath>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <limits>\r\n#include <list>\r\n#include <optional>\r\n#include <type_traits>\r\n#include <utility>\r\n\r\n#include \"appfat.h\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"crawl.hpp\"\r\n#include \"cursor.h\"\r\n#include \"dead.h\"\r\n#include \"diablo.h\"\r\n#include \"effects.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/direction.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/path.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/scrollrt.h\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"function_ref.hpp\"\r\n#include \"interfac.h\"\r\n#include \"items.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/gendung_defs.hpp\"\r\n#include \"msg.h\"\r\n#include \"multi.h\"\r\n#include \"objects.h\"\r\n#include \"player.h\"\r\n#include \"sound_effect_enums.h\"\r\n#include \"tables/itemdat.h\"\r\n#include \"tables/misdat.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/enum_traits.h\"\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"inv.h\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"levels/trigs.h\"\r\n#include \"lighting.h\"\r\n#include \"monster.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::list<Missile> Missiles;\r\nbool MissilePreFlag;\r\n\r\nvoid Missile::setAnimation(MissileGraphicID animtype)\r\n{\r\n\tconst int dir = _mimfnum;\r\n\r\n\tif (animtype >= MissileGraphicID::None) {\r\n\t\t_miAnimType = MissileGraphicID::None;\r\n\t\t_miAnimData = std::nullopt;\r\n\t\t_miAnimWidth = 0;\r\n\t\t_miAnimWidth2 = 0;\r\n\t\t_miAnimFlags = MissileGraphicsFlags::None;\r\n\t\t_miAnimDelay = 0;\r\n\t\t_miAnimLen = 0;\r\n\t\t_miAnimCnt = 0;\r\n\t\t_miAnimFrame = 1;\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst MissileFileData &missileData = GetMissileSpriteData(animtype);\r\n\r\n\t_miAnimType = animtype;\r\n\t_miAnimFlags = missileData.flags;\r\n\tif (!HeadlessMode) {\r\n\t\t_miAnimData = missileData.spritesForDirection(static_cast<Direction16>(dir));\r\n\t}\r\n\t_miAnimDelay = missileData.animDelay(dir);\r\n\t_miAnimLen = missileData.animLen(dir);\r\n\t_miAnimWidth = missileData.animWidth;\r\n\t_miAnimWidth2 = missileData.animWidth2;\r\n\t_miAnimCnt = 0;\r\n\t_miAnimFrame = 1;\r\n}\r\n\r\nnamespace {\r\n\r\nint AddClassHealingBonus(int hp, HeroClass heroClass)\r\n{\r\n\tswitch (heroClass) {\r\n\tcase HeroClass::Warrior:\r\n\tcase HeroClass::Monk:\r\n\tcase HeroClass::Barbarian:\r\n\t\treturn hp * 2;\r\n\tcase HeroClass::Rogue:\r\n\tcase HeroClass::Bard:\r\n\t\treturn hp + (hp / 2);\r\n\tdefault:\r\n\t\treturn hp;\r\n\t}\r\n}\r\n\r\nint ScaleSpellEffect(int base, int spellLevel)\r\n{\r\n\tfor (int i = 0; i < spellLevel; i++) {\r\n\t\tbase += base / 8;\r\n\t}\r\n\r\n\treturn base;\r\n}\r\n\r\nint GenerateRndSum(int range, int iterations)\r\n{\r\n\tint value = 0;\r\n\tfor (int i = 0; i < iterations; i++) {\r\n\t\tvalue += GenerateRnd(range);\r\n\t}\r\n\r\n\treturn value;\r\n}\r\n\r\nbool CheckBlock(Point from, Point to)\r\n{\r\n\twhile (from != to) {\r\n\t\tfrom += GetDirection(from, to);\r\n\t\tif (TileHasAny(from, TileProperties::Solid))\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nMonster *FindClosest(Point source, int rad)\r\n{\r\n\tstd::optional<Point> monsterPosition = FindClosestValidPosition(\r\n\t    [&source](Point target) {\r\n\t\t    // search for a monster with clear line of sight\r\n\t\t    return InDungeonBounds(target) && dMonster[target.x][target.y] > 0 && !CheckBlock(source, target);\r\n\t    },\r\n\t    source, 1, rad);\r\n\r\n\tif (monsterPosition) {\r\n\t\tconst int mid = dMonster[monsterPosition->x][monsterPosition->y];\r\n\t\treturn &Monsters[mid - 1];\r\n\t}\r\n\r\n\treturn nullptr;\r\n}\r\n\r\nconstexpr Direction16 Direction16Flip(Direction16 x, Direction16 pivot)\r\n{\r\n\tconst std::underlying_type_t<Direction16> ret = (2 * static_cast<std::underlying_type_t<Direction16>>(pivot) + 16 - static_cast<std::underlying_type_t<Direction16>>(x)) % 16;\r\n\r\n\treturn static_cast<Direction16>(ret);\r\n}\r\n\r\nvoid UpdateMissileVelocity(Missile &missile, WorldTilePosition destination, int velocityInPixels)\r\n{\r\n\tmissile.position.velocity = { 0, 0 };\r\n\r\n\tif (missile.position.tile == destination)\r\n\t\treturn;\r\n\r\n\t// Get the normalized vector in isometric projection\r\n\tconst Displacement fixed16NormalVector = (Point { missile.position.tile } - Point { destination }).worldToNormalScreen();\r\n\r\n\t// Multiplying by the target velocity gives us a scaled velocity vector.\r\n\tmissile.position.velocity = fixed16NormalVector * velocityInPixels;\r\n}\r\n\r\n/**\r\n * @brief Add the missile to the lookup tables\r\n * @param missile The missile to add\r\n */\r\nvoid PutMissile(Missile &missile)\r\n{\r\n\tconst Point position = missile.position.tile;\r\n\r\n\tif (!InDungeonBounds(position))\r\n\t\tmissile._miDelFlag = true;\r\n\r\n\tif (missile._miDelFlag) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tDungeonFlag &flags = dFlags[position.x][position.y];\r\n\tflags |= DungeonFlag::Missile;\r\n\tif (missile._mitype == MissileID::FireWall)\r\n\t\tflags |= DungeonFlag::MissileFireWall;\r\n\tif (missile._mitype == MissileID::LightningWall)\r\n\t\tflags |= DungeonFlag::MissileLightningWall;\r\n\r\n\tif (missile._miPreFlag)\r\n\t\tMissilePreFlag = true;\r\n}\r\n\r\nvoid UpdateMissilePos(Missile &missile)\r\n{\r\n\tconst Displacement pixelsTravelled = missile.position.traveled >> 16;\r\n\r\n\tconst Displacement tileOffset = pixelsTravelled.screenToMissile();\r\n\tmissile.position.tile = missile.position.start + tileOffset;\r\n\r\n\tmissile.position.offset = pixelsTravelled + tileOffset.worldToScreen();\r\n\r\n\tconst Displacement absoluteLightOffset = pixelsTravelled.screenToLight();\r\n\tChangeLightOffset(missile._mlid, absoluteLightOffset - tileOffset * 8);\r\n}\r\n\r\n/**\r\n * @brief Dodgy hack used to correct the position for charging monsters.\r\n *\r\n * If the monster represented by this missile is *not* facing north in some way it gets shifted to the south.\r\n * This appears to compensate for some visual oddity or invalid calculation earlier in the ProcessRhino logic.\r\n * @param missile MissileStruct representing a charging monster.\r\n */\r\nvoid MoveMissilePos(Missile &missile)\r\n{\r\n\tDirection moveDirection;\r\n\r\n\tswitch (missile.getDirection()) {\r\n\tcase Direction::East:\r\n\t\tmoveDirection = Direction::SouthEast;\r\n\t\tbreak;\r\n\tcase Direction::West:\r\n\t\tmoveDirection = Direction::SouthWest;\r\n\t\tbreak;\r\n\tcase Direction::South:\r\n\tcase Direction::SouthWest:\r\n\tcase Direction::SouthEast:\r\n\t\tmoveDirection = Direction::South;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto target = missile.position.tile + moveDirection;\r\n\tif (IsTileAvailable(*missile.sourceMonster(), target)) {\r\n\t\tmissile.position.tile = target;\r\n\t\tmissile.position.offset += Displacement(moveDirection).worldToScreen();\r\n\t}\r\n}\r\n\r\nint ProjectileMonsterDamage(Missile &missile)\r\n{\r\n\tconst Monster &monster = *missile.sourceMonster();\r\n\treturn RandomIntBetween(monster.minDamage, monster.maxDamage);\r\n}\r\n\r\nint ProjectileTrapDamage()\r\n{\r\n\treturn currlevel + GenerateRnd(2 * currlevel);\r\n}\r\n\r\nbool MonsterMHit(const Player &player, Monster &monster, int mindam, int maxdam, int dist, MissileID t, WorldTilePosition startPos, DamageType damageType, bool shift)\r\n{\r\n\tif (!monster.isPossibleToHit() || monster.isImmune(t, damageType))\r\n\t\treturn false;\r\n\r\n\tint hit = RandomIntLessThan(100);\r\n\tint hper = 0;\r\n\tconst MissileData &missileData = GetMissileData(t);\r\n\tif (missileData.isArrow()) {\r\n\t\thper = player.GetRangedPiercingToHit();\r\n\t\thper -= player.CalculateArmorPierce(monster.armorClass, false);\r\n\t\thper -= (dist * dist) / 2;\r\n\t} else {\r\n\t\thper = player.GetMagicToHit() - (monster.level(sgGameInitInfo.nDifficulty) * 2) - dist;\r\n\t}\r\n\r\n\thper = std::clamp(hper, 5, 95);\r\n\r\n\tif (monster.mode == MonsterMode::Petrified)\r\n\t\thit = 0;\r\n\r\n\tif (monster.tryLiftGargoyle())\r\n\t\treturn true;\r\n\r\n\tif (hit >= hper) {\r\n#ifdef _DEBUG\r\n\t\tif (!DebugGodMode)\r\n#endif\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tint dam;\r\n\tif (t == MissileID::BoneSpirit) {\r\n\t\tdam = monster.hitPoints / 3 >> 6;\r\n\t} else {\r\n\t\tdam = RandomIntBetween(mindam, maxdam);\r\n\t}\r\n\r\n\tif (missileData.isArrow() && damageType == DamageType::Physical) {\r\n\t\tdam = player._pIBonusDamMod + dam * player._pIBonusDam / 100 + dam;\r\n\t\tif (player._pClass == HeroClass::Rogue)\r\n\t\t\tdam += player._pDamageMod;\r\n\t\telse\r\n\t\t\tdam += player._pDamageMod / 2;\r\n\t\tif (monster.data().monsterClass == MonsterClass::Demon && HasAnyOf(player._pIFlags, ItemSpecialEffect::TripleDemonDamage))\r\n\t\t\tdam *= 3;\r\n\t}\r\n\tconst bool resist = monster.isResistant(t, damageType);\r\n\tif (!shift)\r\n\t\tdam <<= 6;\r\n\tif (resist)\r\n\t\tdam >>= 2;\r\n\r\n\tif (&player == MyPlayer)\r\n\t\tApplyMonsterDamage(damageType, monster, dam);\r\n\r\n\tif (monster.hasNoLife()) {\r\n\t\tM_StartKill(monster, player);\r\n\t} else if (resist) {\r\n\t\tmonster.tag(player);\r\n\t\tPlayEffect(monster, MonsterSound::Hit);\r\n\t} else {\r\n\t\tif (monster.mode != MonsterMode::Petrified && missileData.isArrow() && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))\r\n\t\t\tM_GetKnockback(monster, startPos);\r\n\t\tif (monster.type().type != MT_GOLEM)\r\n\t\t\tM_StartHit(monster, player, dam);\r\n\t}\r\n\r\n\tif (monster.activeForTicks == 0) {\r\n\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\tmonster.position.last = player.position.tile;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool Plr2PlrMHit(const Player &player, Player &target, int mindam, int maxdam, int dist, MissileID mtype, DamageType damageType, bool shift, bool *blocked)\r\n{\r\n\tif (sgGameInitInfo.bFriendlyFire == 0 && player.friendlyMode)\r\n\t\treturn false;\r\n\r\n\t*blocked = false;\r\n\r\n\tif (target.isOnArenaLevel() && target._pmode == PM_WALK_SIDEWAYS)\r\n\t\treturn false;\r\n\r\n\tif (target._pInvincible) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (mtype == MissileID::HolyBolt) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst MissileData &missileData = GetMissileData(mtype);\r\n\r\n\tif (HasAnyOf(target._pSpellFlags, SpellFlag::Etherealize) && missileData.isArrow()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint8_t resper;\r\n\tswitch (damageType) {\r\n\tcase DamageType::Fire:\r\n\t\tresper = target._pFireResist;\r\n\t\tbreak;\r\n\tcase DamageType::Lightning:\r\n\t\tresper = target._pLghtResist;\r\n\t\tbreak;\r\n\tcase DamageType::Magic:\r\n\tcase DamageType::Acid:\r\n\t\tresper = target._pMagResist;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tresper = 0;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tconst int hper = GenerateRnd(100);\r\n\r\n\tint hit;\r\n\tif (missileData.isArrow()) {\r\n\t\thit = player.GetRangedToHit()\r\n\t\t    - (dist * dist / 2)\r\n\t\t    - target.GetArmor();\r\n\t} else {\r\n\t\thit = player.GetMagicToHit()\r\n\t\t    - (target.getCharacterLevel() * 2)\r\n\t\t    - dist;\r\n\t}\r\n\r\n\thit = std::clamp(hit, 5, 95);\r\n\r\n\tif (hper >= hit) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint blkper = 100;\r\n\tif (!shift && (target._pmode == PM_STAND || target._pmode == PM_ATTACK) && target._pBlockFlag) {\r\n\t\tblkper = GenerateRnd(100);\r\n\t}\r\n\r\n\tint blk = target.GetBlockChance() - (player.getCharacterLevel() * 2);\r\n\tblk = std::clamp(blk, 0, 100);\r\n\r\n\tint dam;\r\n\tif (mtype == MissileID::BoneSpirit) {\r\n\t\tdam = target._pHitPoints / 3;\r\n\t} else {\r\n\t\tdam = RandomIntBetween(mindam, maxdam);\r\n\t\tif (missileData.isArrow() && damageType == DamageType::Physical) {\r\n\t\t\tconst int damMod = IsAnyOf(player._pClass, HeroClass::Rogue) ? player._pDamageMod : player._pDamageMod / 2;\r\n\t\t\tdam += player._pIBonusDamMod + damMod + dam * player._pIBonusDam / 100;\r\n\t\t}\r\n\t\tif (!shift)\r\n\t\t\tdam <<= 6;\r\n\t}\r\n\tif (!missileData.isArrow())\r\n\t\tdam /= 2;\r\n\tif (resper > 0) {\r\n\t\tdam -= (dam * resper) / 100;\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tNetSendCmdDamage(true, target, dam, damageType);\r\n\t\ttarget.Say(HeroSpeech::ArghClang);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (blkper < blk) {\r\n\t\tStartPlrBlock(target, GetDirection(target.position.tile, player.position.tile));\r\n\t\t*blocked = true;\r\n\t} else {\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tNetSendCmdDamage(true, target, dam, damageType);\r\n\t\tStartPlrHit(target, dam, false);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid RotateBlockedMissile(Missile &missile)\r\n{\r\n\tconst int rotation = PickRandomlyAmong({ -1, 1 });\r\n\r\n\tif (missile._miAnimType == MissileGraphicID::Arrow) {\r\n\t\tconst int dir = missile._miAnimFrame + rotation;\r\n\t\tmissile._miAnimFrame = (dir + 15) % 16 + 1;\r\n\t\treturn;\r\n\t}\r\n\r\n\tint dir = missile.getFrameGroupRaw() + rotation;\r\n\tconst int mAnimFAmt = GetMissileSpriteData(missile._miAnimType).animFAmt;\r\n\tif (dir < 0)\r\n\t\tdir = mAnimFAmt - 1;\r\n\telse if (dir >= mAnimFAmt)\r\n\t\tdir = 0;\r\n\r\n\tmissile.setFrameGroupRaw(dir);\r\n}\r\n\r\nbool CheckCanHitOnlyWalking(const Missile &missile, const ActorPosition &position, Direction wallDir)\r\n{\r\n\tPoint other = missile.position.tile + wallDir;\r\n\tif (missile.position.tile == position.tile && other == position.future)\r\n\t\treturn true;\r\n\tif (missile.position.tile == position.future && other == position.tile)\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\nvoid CheckMissileCol(Missile &missile, DamageType damageType, int minDamage, int maxDamage, bool isDamageShifted, Point position, bool dontDeleteOnCollision, std::optional<Direction> onlyHitWalking = {})\r\n{\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn;\r\n\r\n\tbool isMonsterHit = false;\r\n\tint mid = dMonster[position.x][position.y];\r\n\tif (mid != 0) {\r\n\t\tMonster &monster = Monsters[std::abs(mid) - 1];\r\n\t\tif (onlyHitWalking.has_value() ? (monster.isWalking() && CheckCanHitOnlyWalking(missile, monster.position, *onlyHitWalking)) : (mid > 0 || monster.mode == MonsterMode::Petrified)) {\r\n\t\t\tif (missile.IsTrap()\r\n\t\t\t    || (missile._micaster == TARGET_PLAYERS && (                                     // or was fired by a monster and\r\n\t\t\t            monster.isPlayerMinion() != Monsters[missile._misource].isPlayerMinion() //  the monsters are on opposing factions\r\n\t\t\t            || (Monsters[missile._misource].flags & MFLAG_BERSERK) != 0              //  or the attacker is berserked\r\n\t\t\t            || (monster.flags & MFLAG_BERSERK) != 0                                  //  or the target is berserked\r\n\t\t\t            ))) {\r\n\t\t\t\t// then the missile can potentially hit this target\r\n\t\t\t\tisMonsterHit = MonsterTrapHit(monster, minDamage, maxDamage, missile._midist, missile._mitype, damageType, isDamageShifted);\r\n\t\t\t} else if (IsAnyOf(missile._micaster, TARGET_BOTH, TARGET_MONSTERS)) {\r\n\t\t\t\tisMonsterHit = MonsterMHit(*missile.sourcePlayer(), monster, minDamage, maxDamage, missile._midist, missile._mitype, missile.position.start, damageType, isDamageShifted);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (isMonsterHit) {\r\n\t\tif (!dontDeleteOnCollision)\r\n\t\t\tmissile.duration = 0;\r\n\t\tmissile._miHitFlag = true;\r\n\t}\r\n\r\n\tbool isPlayerHit = false;\r\n\tbool blocked = false;\r\n\tPlayer *player = PlayerAtPosition(position, !onlyHitWalking.has_value());\r\n\tif (player != nullptr && (onlyHitWalking.has_value() ? (player->isWalking() && CheckCanHitOnlyWalking(missile, player->position, *onlyHitWalking)) : true)) {\r\n\t\tif (missile._micaster != TARGET_BOTH && !missile.IsTrap()) {\r\n\t\t\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\t\t\tif (player->getId() != missile._misource)\r\n\t\t\t\t\tisPlayerHit = Plr2PlrMHit(Players[missile._misource], *player, minDamage, maxDamage, missile._midist, missile._mitype, damageType, isDamageShifted, &blocked);\r\n\t\t\t} else {\r\n\t\t\t\tMonster &monster = Monsters[missile._misource];\r\n\t\t\t\tisPlayerHit = PlayerMHit(*player, &monster, missile._midist, minDamage, maxDamage, missile._mitype, damageType, isDamageShifted, DeathReason::MonsterOrTrap, &blocked);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst DeathReason deathReason = missile.sourceType() == MissileSource::Player ? DeathReason::Player : DeathReason::MonsterOrTrap;\r\n\t\t\tisPlayerHit = PlayerMHit(*player, nullptr, missile._midist, minDamage, maxDamage, missile._mitype, damageType, isDamageShifted, deathReason, &blocked);\r\n\t\t}\r\n\t}\r\n\r\n\tif (isPlayerHit) {\r\n\t\tif (gbIsHellfire && blocked) {\r\n\t\t\tRotateBlockedMissile(missile);\r\n\t\t} else if (!dontDeleteOnCollision) {\r\n\t\t\tmissile.duration = 0;\r\n\t\t}\r\n\t\tmissile._miHitFlag = true;\r\n\t}\r\n\r\n\tif (IsMissileBlockedByTile(position)) {\r\n\t\tObject *object = FindObjectAtPosition(position);\r\n\t\tif (object != nullptr && object->IsBreakable()) {\r\n\t\t\tBreakObjectMissile(missile.sourcePlayer(), *object);\r\n\t\t}\r\n\r\n\t\tif (!dontDeleteOnCollision)\r\n\t\t\tmissile.duration = 0;\r\n\t\tmissile._miHitFlag = false;\r\n\t}\r\n\r\n\tconst MissileData &missileData = GetMissileData(missile._mitype);\r\n\tif (missile.duration == 0 && missileData.hitSound != SfxID::None)\r\n\t\tPlaySfxLoc(missileData.hitSound, missile.position.tile);\r\n}\r\n\r\nbool MoveMissile(Missile &missile, tl::function_ref<bool(Point)> checkTile, bool ifCheckTileFailsDontMoveToTile = false)\r\n{\r\n\tPoint prevTile = missile.position.tile;\r\n\tmissile.position.traveled += missile.position.velocity;\r\n\tUpdateMissilePos(missile);\r\n\r\n\tint possibleVisitTiles;\r\n\tif (missile.position.velocity.deltaX == 0 || missile.position.velocity.deltaY == 0)\r\n\t\tpossibleVisitTiles = prevTile.WalkingDistance(missile.position.tile);\r\n\telse\r\n\t\tpossibleVisitTiles = prevTile.ManhattanDistance(missile.position.tile);\r\n\r\n\tif (possibleVisitTiles == 0)\r\n\t\treturn false;\r\n\r\n\t// Did the missile skip a tile?\r\n\tif (possibleVisitTiles > 1) {\r\n\t\tauto speed = abs(missile.position.velocity);\r\n\t\tconst auto denominator = static_cast<float>((2 * speed.deltaY >= speed.deltaX) ? 2 * speed.deltaY : speed.deltaX);\r\n\t\tauto incVelocity = missile.position.velocity * ((32 << 16) / denominator);\r\n\t\tauto traveled = missile.position.traveled - missile.position.velocity;\r\n\t\t// Adjust the traveled vector to start on the next smallest multiple of incVelocity\r\n\t\tif (incVelocity.deltaY != 0)\r\n\t\t\ttraveled.deltaY = (traveled.deltaY / incVelocity.deltaY) * incVelocity.deltaY;\r\n\t\tif (incVelocity.deltaX != 0)\r\n\t\t\ttraveled.deltaX = (traveled.deltaX / incVelocity.deltaX) * incVelocity.deltaX;\r\n\t\tdo {\r\n\t\t\tauto initialDiff = missile.position.traveled - traveled;\r\n\t\t\ttraveled += incVelocity;\r\n\t\t\tauto incDiff = missile.position.traveled - traveled;\r\n\r\n\t\t\t// we are at the original calculated position => resume with normal logic\r\n\t\t\tif ((initialDiff.deltaX < 0) != (incDiff.deltaX < 0))\r\n\t\t\t\tbreak;\r\n\t\t\tif ((initialDiff.deltaY < 0) != (incDiff.deltaY < 0))\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t// calculate in-between tile\r\n\t\t\tconst Displacement pixelsTraveled = traveled >> 16;\r\n\t\t\tconst Displacement tileOffset = pixelsTraveled.screenToMissile();\r\n\t\t\tconst Point tile = missile.position.start + tileOffset;\r\n\r\n\t\t\t// we haven't quite reached the missile's current position,\r\n\t\t\t// but we can break early to avoid checking collisions in this tile twice\r\n\t\t\tif (tile == missile.position.tile)\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t// skip collision logic if the missile is on a corner between tiles\r\n\t\t\tif (pixelsTraveled.deltaY % 16 == 0\r\n\t\t\t    && pixelsTraveled.deltaX % 32 == 0\r\n\t\t\t    && std::abs(pixelsTraveled.deltaY / 16) % 2 != std::abs(pixelsTraveled.deltaX / 32) % 2) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// don't call checkTile more than once for a tile\r\n\t\t\tif (prevTile == tile)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tprevTile = tile;\r\n\r\n\t\t\tif (!checkTile(tile)) {\r\n\t\t\t\tmissile.position.traveled = traveled;\r\n\t\t\t\tif (ifCheckTileFailsDontMoveToTile) {\r\n\t\t\t\t\tmissile.position.traveled -= incVelocity;\r\n\t\t\t\t\tUpdateMissilePos(missile);\r\n\t\t\t\t\tmissile.position.StopMissile();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tUpdateMissilePos(missile);\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\r\n\t\t} while (true);\r\n\t}\r\n\r\n\tif (!checkTile(missile.position.tile) && ifCheckTileFailsDontMoveToTile) {\r\n\t\tmissile.position.traveled -= missile.position.velocity;\r\n\t\tUpdateMissilePos(missile);\r\n\t\tmissile.position.StopMissile();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid MoveMissileAndCheckMissileCol(Missile &missile, DamageType damageType, int mindam, int maxdam, bool ignoreStart, bool ifCollidesDontMoveToHitTile)\r\n{\r\n\tauto checkTile = [&](Point tile) {\r\n\t\tif (ignoreStart && missile.position.start == tile)\r\n\t\t\treturn true;\r\n\r\n\t\tCheckMissileCol(missile, damageType, mindam, maxdam, false, tile, false);\r\n\r\n\t\t// Did missile hit anything?\r\n\t\tif (missile.duration != 0)\r\n\t\t\treturn true;\r\n\r\n\t\tif (missile._miHitFlag && GetMissileData(missile._mitype).movementDistribution == MissileMovementDistribution::Blockable)\r\n\t\t\treturn false;\r\n\r\n\t\treturn !IsMissileBlockedByTile(tile);\r\n\t};\r\n\r\n\tconst bool tileChanged = MoveMissile(missile, checkTile, ifCollidesDontMoveToHitTile);\r\n\r\n\tconst int16_t tileTargetHash = dMonster[missile.position.tile.x][missile.position.tile.y] ^ dPlayer[missile.position.tile.x][missile.position.tile.y];\r\n\r\n\t// missile didn't change the tile... check that we perform CheckMissileCol only once for any monster/player to avoid multiple hits for slow missiles\r\n\tif (!tileChanged && missile.lastCollisionTargetHash != tileTargetHash) {\r\n\t\tCheckMissileCol(missile, damageType, mindam, maxdam, false, missile.position.tile, false);\r\n\t}\r\n\r\n\t// remember what target CheckMissileCol was checked against\r\n\tmissile.lastCollisionTargetHash = tileTargetHash;\r\n}\r\n\r\nvoid AddRune(Missile &missile, Point dst, MissileID missileID)\r\n{\r\n\tif (LineClearMissile(missile.position.start, dst)) {\r\n\t\tstd::optional<Point> runePosition = FindClosestValidPosition(\r\n\t\t    [](Point target) {\r\n\t\t\t    if (!InDungeonBounds(target)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    if (IsObjectAtPosition(target)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    if (TileContainsMissile(target)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    if (TileHasAny(target, TileProperties::Solid)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    return true;\r\n\t\t    },\r\n\t\t    dst, 0, 9);\r\n\r\n\t\tif (runePosition) {\r\n\t\t\tmissile.position.tile = *runePosition;\r\n\t\t\tmissile.var1 = static_cast<int8_t>(missileID);\r\n\t\t\tmissile._mlid = AddLight(missile.position.tile, 8);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nbool CheckIfTrig(Point position)\r\n{\r\n\tfor (int i = 0; i < numtrigs; i++) {\r\n\t\tif (trigs[i].position.WalkingDistance(position) < 2)\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool GuardianTryFireAt(Missile &missile, Point target)\r\n{\r\n\tconst Point position = missile.position.tile;\r\n\r\n\tif (!LineClearMovingMissile(position, target))\r\n\t\treturn false;\r\n\tconst int mid = dMonster[target.x][target.y] - 1;\r\n\tif (mid < 0)\r\n\t\treturn false;\r\n\tconst Monster &monster = Monsters[mid];\r\n\tif (monster.isPlayerMinion())\r\n\t\treturn false;\r\n\tif (monster.hasNoLife())\r\n\t\treturn false;\r\n\r\n\tconst Player &player = Players[missile._misource];\r\n\tint dmg = GenerateRnd(10) + (player.getCharacterLevel() / 2) + 1;\r\n\tdmg = ScaleSpellEffect(dmg, missile._mispllvl);\r\n\r\n\tconst Direction dir = GetDirection(position, target);\r\n\tAddMissile(position, target, dir, MissileID::Firebolt, TARGET_MONSTERS, missile._misource, missile._midam, missile.sourcePlayer()->GetSpellLevel(SpellID::Guardian), &missile);\r\n\tmissile.setFrameGroup<GuardianFrame>(GuardianFrame::Attack);\r\n\tmissile.var2 = 3;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanPlaceWall(Point position)\r\n{\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn false;\r\n\r\n\t[[maybe_unused]] const int dp = dPiece[position.x][position.y];\r\n\tassert(dp <= MAXTILES && dp >= 0);\r\n\r\n\treturn !TileHasAny(position, TileProperties::BlockMissile);\r\n}\r\n\r\nMissile *PlaceWall(int id, MissileID type, Point position, Direction direction, int spellLevel, int damage)\r\n{\r\n\treturn AddMissile(position, position + direction, direction, type, TARGET_BOTH, id, damage, spellLevel);\r\n}\r\n\r\nbool TryGrowWall(int id, MissileID type, Point position, Direction growDirection, Direction direction, int spellLevel, int damage)\r\n{\r\n\tswitch (growDirection) {\r\n\tcase Direction::South:\r\n\tcase Direction::West:\r\n\tcase Direction::North:\r\n\tcase Direction::East: {\r\n\t\tPoint gapPos = position + Displacement(Right(growDirection)) - Displacement(growDirection);\r\n\t\tif (CanPlaceWall(gapPos)) {\r\n\t\t\tMissile *missile = PlaceWall(id, type, gapPos, direction, spellLevel, damage);\r\n\t\t\tif (missile != nullptr) {\r\n\t\t\t\tDisplacement travelled = Displacement(Right(Right(growDirection))).worldToNormalScreen() * 30; // Move the wall to the edge to the next tile, but not over it\r\n\t\t\t\tmissile->position.traveled += travelled;\r\n\t\t\t\tmissile->_miDrawFlag = false;\r\n\t\t\t\tmissile->var3 = static_cast<int>(Left(Left(growDirection))) + 1;\r\n\t\t\t\tUpdateMissilePos(*missile);\r\n\t\t\t\tassert(gapPos == missile->position.tile); // Check that the tile we checked against (CanPlaceWall) didn't change\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (!CanPlaceWall(position))\r\n\t\treturn false;\r\n\tPlaceWall(id, type, position, direction, spellLevel, damage);\r\n\treturn true;\r\n}\r\n\r\nstd::optional<Point> MoveWallToNextPosition(Point position, Direction growDirection)\r\n{\r\n\tPoint nextPosition = position + growDirection;\r\n\tif (!InDungeonBounds(nextPosition))\r\n\t\treturn std::nullopt;\r\n\treturn nextPosition;\r\n}\r\n\r\n/** @brief Sync missile position with parent missile */\r\nvoid SyncPositionWithParent(Missile &missile, const AddMissileParameter &parameter)\r\n{\r\n\tconst Missile *parent = parameter.pParent;\r\n\tif (parent == nullptr)\r\n\t\treturn;\r\n\r\n\tmissile.position.offset = parent->position.offset;\r\n\tmissile.position.traveled = parent->position.traveled;\r\n}\r\n\r\nvoid SpawnLightning(Missile &missile, int dam)\r\n{\r\n\tmissile.duration--;\r\n\tMoveMissile(\r\n\t    missile, [&](Point tile) {\r\n\t\t    assert(InDungeonBounds(tile));\r\n\t\t    [[maybe_unused]] const int pn = dPiece[tile.x][tile.y];\r\n\t\t    assert(pn >= 0 && pn <= MAXTILES);\r\n\r\n\t\t    if (!missile.IsTrap() || tile != missile.position.start) {\r\n\t\t\t    if (TileHasAny(tile, TileProperties::BlockMissile)) {\r\n\t\t\t\t    missile.duration = 0;\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t    }\r\n\r\n\t\t    return true;\r\n\t    });\r\n\r\n\tauto position = missile.position.tile;\r\n\tif (!TileHasAny(position, TileProperties::BlockMissile)) {\r\n\t\tif (position != Point { missile.var1, missile.var2 } && InDungeonBounds(position)) {\r\n\t\t\tMissileID type = MissileID::Lightning;\r\n\t\t\tif (missile.sourceType() == MissileSource::Monster\r\n\t\t\t    && IsAnyOf(missile.sourceMonster()->type().type, MT_STORM, MT_RSTORM, MT_STORML, MT_MAEL)) {\r\n\t\t\t\ttype = MissileID::ThinLightning;\r\n\t\t\t}\r\n\t\t\tAddMissile(\r\n\t\t\t    position,\r\n\t\t\t    missile.position.start,\r\n\t\t\t    Direction::South,\r\n\t\t\t    type,\r\n\t\t\t    missile._micaster,\r\n\t\t\t    missile._misource,\r\n\t\t\t    dam,\r\n\t\t\t    missile._mispllvl,\r\n\t\t\t    &missile);\r\n\t\t\tmissile.var1 = position.x;\r\n\t\t\tmissile.var2 = position.y;\r\n\t\t}\r\n\t}\r\n\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\n#ifdef BUILD_TESTING\r\nvoid TestRotateBlockedMissile(Missile &missile)\r\n{\r\n\tRotateBlockedMissile(missile);\r\n}\r\n#endif\r\n\r\nbool IsMissileBlockedByTile(Point tile)\r\n{\r\n\tif (!InDungeonBounds(tile)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (TileHasAny(tile, TileProperties::BlockMissile)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tObject *object = FindObjectAtPosition(tile);\r\n\t// _oMissFlag is true if the object allows missiles to pass through so we need to invert the check here...\r\n\treturn object != nullptr && !object->_oMissFlag;\r\n}\r\n\r\nDamageRange GetDamageAmt(SpellID spell, int spellLevel)\r\n{\r\n\tassert(MyPlayer != nullptr);\r\n\tassert(spell >= SpellID::FIRST && spell <= SpellID::LAST);\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tswitch (spell) {\r\n\tcase SpellID::Firebolt: {\r\n\t\tconst int min = (myPlayer._pMagic / 8) + spellLevel + 1;\r\n\t\treturn { min, min + 9 };\r\n\t}\r\n\tcase SpellID::Healing:\r\n\tcase SpellID::HealOther:\r\n\t\t/// BUGFIX: healing calculation is unused\r\n\t\treturn {\r\n\t\t\tAddClassHealingBonus(myPlayer.getCharacterLevel() + spellLevel + 1, myPlayer._pClass) - 1,\r\n\t\t\tAddClassHealingBonus((4 * myPlayer.getCharacterLevel()) + (6 * spellLevel) + 10, myPlayer._pClass) - 1\r\n\t\t};\r\n\tcase SpellID::RuneOfLight:\r\n\tcase SpellID::Lightning:\r\n\t\treturn { 2, 2 + myPlayer.getCharacterLevel() };\r\n\tcase SpellID::Flash: {\r\n\t\tint min = ScaleSpellEffect(myPlayer.getCharacterLevel(), spellLevel);\r\n\t\tmin += min / 2;\r\n\t\treturn { min, min * 2 };\r\n\t};\r\n\tcase SpellID::Identify:\r\n\tcase SpellID::TownPortal:\r\n\tcase SpellID::StoneCurse:\r\n\tcase SpellID::Infravision:\r\n\tcase SpellID::Phasing:\r\n\tcase SpellID::ManaShield:\r\n\tcase SpellID::DoomSerpents:\r\n\tcase SpellID::BloodRitual:\r\n\tcase SpellID::Invisibility:\r\n\tcase SpellID::Rage:\r\n\tcase SpellID::Teleport:\r\n\tcase SpellID::Etherealize:\r\n\tcase SpellID::ItemRepair:\r\n\tcase SpellID::StaffRecharge:\r\n\tcase SpellID::TrapDisarm:\r\n\tcase SpellID::Resurrect:\r\n\tcase SpellID::Telekinesis:\r\n\tcase SpellID::BoneSpirit:\r\n\tcase SpellID::Warp:\r\n\tcase SpellID::Reflect:\r\n\tcase SpellID::Berserk:\r\n\tcase SpellID::Search:\r\n\tcase SpellID::RuneOfStone:\r\n\t\treturn { -1, -1 };\r\n\tcase SpellID::FireWall:\r\n\tcase SpellID::LightningWall:\r\n\tcase SpellID::RingOfFire: {\r\n\t\tconst int min = 2 * myPlayer.getCharacterLevel() + 4;\r\n\t\treturn { min, min + 36 };\r\n\t}\r\n\tcase SpellID::Fireball:\r\n\tcase SpellID::RuneOfFire: {\r\n\t\tconst int base = (2 * myPlayer.getCharacterLevel()) + 4;\r\n\t\treturn {\r\n\t\t\tScaleSpellEffect(base, spellLevel),\r\n\t\t\tScaleSpellEffect(base + 36, spellLevel)\r\n\t\t};\r\n\t} break;\r\n\tcase SpellID::Guardian: {\r\n\t\tconst int base = (myPlayer.getCharacterLevel() / 2) + 1;\r\n\t\treturn {\r\n\t\t\tScaleSpellEffect(base, spellLevel),\r\n\t\t\tScaleSpellEffect(base + 9, spellLevel)\r\n\t\t};\r\n\t} break;\r\n\tcase SpellID::ChainLightning:\r\n\t\treturn { 4, 4 + (2 * myPlayer.getCharacterLevel()) };\r\n\tcase SpellID::FlameWave: {\r\n\t\tconst int min = 6 * (myPlayer.getCharacterLevel() + 1);\r\n\t\treturn { min, min + 54 };\r\n\t}\r\n\tcase SpellID::Nova:\r\n\tcase SpellID::Immolation:\r\n\tcase SpellID::RuneOfImmolation:\r\n\tcase SpellID::RuneOfNova:\r\n\t\treturn {\r\n\t\t\tScaleSpellEffect((myPlayer.getCharacterLevel() + 5) / 2, spellLevel) * 5,\r\n\t\t\tScaleSpellEffect((myPlayer.getCharacterLevel() + 30) / 2, spellLevel) * 5\r\n\t\t};\r\n\tcase SpellID::Inferno: {\r\n\t\tint max = myPlayer.getCharacterLevel() + 4;\r\n\t\tmax += max / 2;\r\n\t\treturn { 3, max };\r\n\t}\r\n\tcase SpellID::Golem:\r\n\t\treturn { 11, 17 };\r\n\tcase SpellID::Apocalypse:\r\n\t\treturn { myPlayer.getCharacterLevel(), myPlayer.getCharacterLevel() * 6 };\r\n\tcase SpellID::Elemental:\r\n\t\t/// BUGFIX: Divide min and max by 2\r\n\t\treturn {\r\n\t\t\tScaleSpellEffect(2 * myPlayer.getCharacterLevel() + 4, spellLevel),\r\n\t\t\tScaleSpellEffect(2 * myPlayer.getCharacterLevel() + 40, spellLevel)\r\n\t\t};\r\n\tcase SpellID::ChargedBolt:\r\n\t\treturn { 1, 1 + (myPlayer._pMagic / 4) };\r\n\tcase SpellID::HolyBolt:\r\n\t\treturn { myPlayer.getCharacterLevel() + 9, myPlayer.getCharacterLevel() + 18 };\r\n\tcase SpellID::BloodStar: {\r\n\t\tconst int min = (myPlayer._pMagic / 2) + 3 * spellLevel - (myPlayer._pMagic / 8);\r\n\t\treturn { min, min };\r\n\t}\r\n\tdefault:\r\n\t\treturn { -1, -1 };\r\n\t}\r\n}\r\n\r\nDirection16 GetDirection16(Point p1, Point p2)\r\n{\r\n\tconst Displacement offset = p2 - p1;\r\n\tDisplacement absolute = abs(offset);\r\n\r\n\tconst bool flipY = offset.deltaX != absolute.deltaX;\r\n\tconst bool flipX = offset.deltaY != absolute.deltaY;\r\n\r\n\tbool flipMedian = false;\r\n\tif (absolute.deltaX > absolute.deltaY) {\r\n\t\tstd::swap(absolute.deltaX, absolute.deltaY);\r\n\t\tflipMedian = true;\r\n\t}\r\n\r\n\tDirection16 ret = Direction16::South;\r\n\tif (3 * absolute.deltaX <= (absolute.deltaY * 2)) { // mx/my <= 2/3, approximation of tan(33.75)\r\n\t\tif (5 * absolute.deltaX < absolute.deltaY)      // mx/my < 0.2, approximation of tan(11.25)\r\n\t\t\tret = Direction16::SouthWest;\r\n\t\telse\r\n\t\t\tret = Direction16::South_SouthWest;\r\n\t}\r\n\r\n\tDirection16 medianPivot = Direction16::South;\r\n\tif (flipY) {\r\n\t\tret = Direction16Flip(ret, Direction16::SouthWest);\r\n\t\tmedianPivot = Direction16Flip(medianPivot, Direction16::SouthWest);\r\n\t}\r\n\tif (flipX) {\r\n\t\tret = Direction16Flip(ret, Direction16::SouthEast);\r\n\t\tmedianPivot = Direction16Flip(medianPivot, Direction16::SouthEast);\r\n\t}\r\n\tif (flipMedian)\r\n\t\tret = Direction16Flip(ret, medianPivot);\r\n\treturn ret;\r\n}\r\n\r\nbool MonsterTrapHit(Monster &monster, int mindam, int maxdam, int dist, MissileID t, DamageType damageType, bool shift)\r\n{\r\n\tif (!monster.isPossibleToHit() || monster.isImmune(t, damageType))\r\n\t\treturn false;\r\n\r\n\tconst int hit = GenerateRnd(100);\r\n\tint hper = 90 - monster.armorClass - dist;\r\n\thper = std::clamp(hper, 5, 95);\r\n\tif (monster.tryLiftGargoyle())\r\n\t\treturn true;\r\n\tif (hit >= hper && monster.mode != MonsterMode::Petrified) {\r\n#ifdef _DEBUG\r\n\t\tif (!DebugGodMode)\r\n#endif\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tconst bool resist = monster.isResistant(t, damageType);\r\n\tint dam = RandomIntBetween(mindam, maxdam);\r\n\tif (!shift)\r\n\t\tdam <<= 6;\r\n\tif (resist)\r\n\t\tdam /= 4;\r\n\tApplyMonsterDamage(damageType, monster, dam);\r\n#ifdef _DEBUG\r\n\tif (DebugGodMode)\r\n\t\tmonster.hitPoints = 0;\r\n#endif\r\n\tif (monster.hasNoLife()) {\r\n\t\tMonsterDeath(monster, monster.direction, true);\r\n\t} else if (resist) {\r\n\t\tPlayEffect(monster, MonsterSound::Hit);\r\n\t} else if (monster.type().type != MT_GOLEM) {\r\n\t\tM_StartHit(monster, dam);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool PlayerMHit(Player &player, Monster *monster, int dist, int mind, int maxd, MissileID mtype, DamageType damageType, bool shift, DeathReason deathReason, bool *blocked)\r\n{\r\n\t*blocked = false;\r\n\r\n\tif (player.hasNoLife()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (player._pInvincible) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst MissileData &missileData = GetMissileData(mtype);\r\n\r\n\tif (HasAnyOf(player._pSpellFlags, SpellFlag::Etherealize) && missileData.isArrow()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint hit = GenerateRnd(100);\r\n#ifdef _DEBUG\r\n\tif (DebugGodMode)\r\n\t\thit = 1000;\r\n#endif\r\n\tint hper = 40;\r\n\tif (missileData.isArrow()) {\r\n\t\tconst int tac = player.GetArmor();\r\n\t\tif (monster != nullptr) {\r\n\t\t\thper = monster->toHit(sgGameInitInfo.nDifficulty)\r\n\t\t\t    + ((monster->level(sgGameInitInfo.nDifficulty) - player.getCharacterLevel()) * 2)\r\n\t\t\t    + 30\r\n\t\t\t    - (dist * 2) - tac;\r\n\t\t} else {\r\n\t\t\thper = 100 - (tac / 2) - (dist * 2);\r\n\t\t}\r\n\t} else if (monster != nullptr) {\r\n\t\thper += (monster->level(sgGameInitInfo.nDifficulty) * 2) - (player.getCharacterLevel() * 2) - (dist * 2);\r\n\t}\r\n\r\n\tint minhit = 10;\r\n\tif (currlevel == 14)\r\n\t\tminhit = 20;\r\n\tif (currlevel == 15)\r\n\t\tminhit = 25;\r\n\tif (currlevel == 16)\r\n\t\tminhit = 30;\r\n\thper = std::max(hper, minhit);\r\n\r\n\tint blk = 100;\r\n\tif ((player._pmode == PM_STAND || player._pmode == PM_ATTACK) && player._pBlockFlag) {\r\n\t\tblk = GenerateRnd(100);\r\n\t}\r\n\r\n\tif (shift)\r\n\t\tblk = 100;\r\n\tif (mtype == MissileID::AcidPuddle)\r\n\t\tblk = 100;\r\n\r\n\tint blkper = player.GetBlockChance(false);\r\n\tif (monster != nullptr)\r\n\t\tblkper -= (monster->level(sgGameInitInfo.nDifficulty) - player.getCharacterLevel()) * 2;\r\n\tblkper = std::clamp(blkper, 0, 100);\r\n\r\n\tint8_t resper;\r\n\tswitch (damageType) {\r\n\tcase DamageType::Fire:\r\n\t\tresper = player._pFireResist;\r\n\t\tbreak;\r\n\tcase DamageType::Lightning:\r\n\t\tresper = player._pLghtResist;\r\n\t\tbreak;\r\n\tcase DamageType::Magic:\r\n\tcase DamageType::Acid:\r\n\t\tresper = player._pMagResist;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tresper = 0;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (hit >= hper) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint dam;\r\n\tif (mtype == MissileID::BoneSpirit) {\r\n\t\tdam = player._pHitPoints / 3;\r\n\t} else {\r\n\t\tif (!shift) {\r\n\t\t\t// New method fixes a bug which caused the maximum possible damage value to be 63/64ths too low.\r\n\t\t\tdam = RandomIntBetween(mind << 6, maxd << 6);\r\n\t\t\tif (monster == nullptr)\r\n\t\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::HalfTrapDamage))\r\n\t\t\t\t\tdam /= 2;\r\n\t\t\tdam += player._pIGetHit * 64;\r\n\t\t} else {\r\n\t\t\tdam = RandomIntBetween(mind, maxd);\r\n\t\t\tif (monster == nullptr)\r\n\t\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::HalfTrapDamage))\r\n\t\t\t\t\tdam /= 2;\r\n\t\t\tdam += player._pIGetHit;\r\n\t\t}\r\n\r\n\t\tdam = std::max(dam, 64);\r\n\t}\r\n\r\n\tif ((resper <= 0 || gbIsHellfire) && blk < blkper) {\r\n\t\tDirection dir = player._pdir;\r\n\t\tif (monster != nullptr) {\r\n\t\t\tdir = GetDirection(player.position.tile, monster->position.tile);\r\n\t\t}\r\n\t\t*blocked = true;\r\n\t\tStartPlrBlock(player, dir);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (monster != nullptr) {\r\n\t\tMonsterReducePlayerAttribute(*monster, player);\r\n\t}\r\n\r\n\tif (resper > 0) {\r\n\t\tdam -= dam * resper / 100;\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tApplyPlrDamage(damageType, player, 0, 0, dam, deathReason);\r\n\t\t}\r\n\r\n\t\tif (!player.hasNoLife()) {\r\n\t\t\tplayer.Say(HeroSpeech::ArghClang);\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tApplyPlrDamage(damageType, player, 0, 0, dam, deathReason);\r\n\t}\r\n\r\n\tif (!player.hasNoLife()) {\r\n\t\tStartPlrHit(player, dam, false);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid InitMissiles()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tAutoMapShowItems = false;\r\n\tmyPlayer._pSpellFlags &= ~SpellFlag::Etherealize;\r\n\tif (myPlayer._pInfraFlag) {\r\n\t\tfor (auto &missile : Missiles) {\r\n\t\t\tif (missile._mitype == MissileID::Infravision) {\r\n\t\t\t\tif (missile.sourcePlayer() == MyPlayer)\r\n\t\t\t\t\tCalcPlrItemVals(myPlayer, true);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (HasAnyOf(myPlayer._pSpellFlags, SpellFlag::RageActive | SpellFlag::RageCooldown)) {\r\n\t\tmyPlayer._pSpellFlags &= ~SpellFlag::RageActive;\r\n\t\tmyPlayer._pSpellFlags &= ~SpellFlag::RageCooldown;\r\n\t\tfor (auto &missile : Missiles) {\r\n\t\t\tif (missile._mitype == MissileID::Rage) {\r\n\t\t\t\tif (missile.sourcePlayer() == MyPlayer) {\r\n\t\t\t\t\tCalcPlrItemVals(myPlayer, true);\r\n\t\t\t\t\tApplyPlrDamage(DamageType::Physical, myPlayer, missile._midam, 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tMissiles.clear();\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\tdFlags[i][j] &= ~(DungeonFlag::Missile | DungeonFlag::MissileFireWall | DungeonFlag::MissileLightningWall);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddOpenNest(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tfor (const WorldTileCoord x : { 80, 81 }) {\r\n\t\tfor (const WorldTileCoord y : { 62, 63 }) {\r\n\t\t\tAddMissile({ x, y }, { 80, 62 }, parameter.midir, MissileID::BigExplosion, missile._micaster, missile._misource, missile._midam, 0);\r\n\t\t}\r\n\t}\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid AddRuneOfFire(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tAddRune(missile, parameter.dst, MissileID::BigExplosion);\r\n}\r\n\r\nvoid AddRuneOfLight(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tconst int lvl = (missile.sourceType() == MissileSource::Player) ? missile.sourcePlayer()->getCharacterLevel() : 0;\r\n\tconst int dmg = 16 * (GenerateRndSum(10, 2) + lvl + 2);\r\n\tmissile._midam = dmg;\r\n\tAddRune(missile, parameter.dst, MissileID::LightningWall);\r\n}\r\n\r\nvoid AddRuneOfNova(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tAddRune(missile, parameter.dst, MissileID::Nova);\r\n}\r\n\r\nvoid AddRuneOfImmolation(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tAddRune(missile, parameter.dst, MissileID::Immolation);\r\n}\r\n\r\nvoid AddRuneOfStone(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tAddRune(missile, parameter.dst, MissileID::StoneCurse);\r\n}\r\n\r\nvoid AddReflect(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tmissile._miDelFlag = true;\r\n\r\n\tif (missile.sourceType() != MissileSource::Player)\r\n\t\treturn;\r\n\r\n\tPlayer &player = *missile.sourcePlayer();\r\n\r\n\tint add = (missile._mispllvl != 0 ? missile._mispllvl : 2) * player.getCharacterLevel();\r\n\tif (player.wReflections + add >= std::numeric_limits<uint16_t>::max())\r\n\t\tadd = 0;\r\n\tplayer.wReflections += add;\r\n\tif (&player == MyPlayer)\r\n\t\tNetSendCmdParam1(true, CMD_SETREFLECT, player.wReflections);\r\n}\r\n\r\nvoid AddBerserk(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile._miDelFlag = true;\r\n\tparameter.spellFizzled = true;\r\n\r\n\tif (missile.sourceType() == MissileSource::Trap)\r\n\t\treturn;\r\n\r\n\tstd::optional<Point> targetMonsterPosition = FindClosestValidPosition(\r\n\t    [](Point target) {\r\n\t\t    if (!InDungeonBounds(target)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\r\n\t\t    const int monsterId = std::abs(dMonster[target.x][target.y]) - 1;\r\n\t\t    if (monsterId < 0)\r\n\t\t\t    return false;\r\n\r\n\t\t    const Monster &monster = Monsters[monsterId];\r\n\t\t    if (monster.isPlayerMinion())\r\n\t\t\t    return false;\r\n\t\t    if ((monster.flags & MFLAG_BERSERK) != 0)\r\n\t\t\t    return false;\r\n\t\t    if (monster.isUnique() || monster.ai == MonsterAIID::Diablo)\r\n\t\t\t    return false;\r\n\t\t    if (IsAnyOf(monster.mode, MonsterMode::FadeIn, MonsterMode::FadeOut, MonsterMode::Charge))\r\n\t\t\t    return false;\r\n\t\t    if ((monster.resistance & IMMUNE_MAGIC) != 0)\r\n\t\t\t    return false;\r\n\t\t    if ((monster.resistance & RESIST_MAGIC) != 0 && ((monster.resistance & RESIST_MAGIC) != 1 || !FlipCoin()))\r\n\t\t\t    return false;\r\n\r\n\t\t    return true;\r\n\t    },\r\n\t    parameter.dst, 0, 5);\r\n\r\n\tif (targetMonsterPosition) {\r\n\t\tMonster &monster = Monsters[std::abs(dMonster[targetMonsterPosition->x][targetMonsterPosition->y]) - 1];\r\n\t\tconst Player &player = *missile.sourcePlayer();\r\n\t\tconst int slvl = player.GetSpellLevel(SpellID::Berserk);\r\n\t\tmonster.flags |= MFLAG_BERSERK | MFLAG_GOLEM;\r\n\t\tmonster.minDamage = (GenerateRnd(10) + 120) * monster.minDamage / 100 + slvl;\r\n\t\tmonster.maxDamage = (GenerateRnd(10) + 120) * monster.maxDamage / 100 + slvl;\r\n\t\tmonster.minDamageSpecial = (GenerateRnd(10) + 120) * monster.minDamageSpecial / 100 + slvl;\r\n\t\tmonster.maxDamageSpecial = (GenerateRnd(10) + 120) * monster.maxDamageSpecial / 100 + slvl;\r\n\t\tconst int lightRadius = leveltype == DTYPE_NEST ? 9 : 3;\r\n\t\tmonster.lightId = AddLight(monster.position.tile, lightRadius);\r\n\t\tparameter.spellFizzled = false;\r\n\t}\r\n}\r\n\r\nvoid AddHorkSpawn(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tUpdateMissileVelocity(missile, parameter.dst, 8);\r\n\tmissile.duration = 9;\r\n\tmissile.var1 = static_cast<int32_t>(parameter.midir);\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid AddJester(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tMissileID spell = MissileID::Firebolt;\r\n\tswitch (RandomIntLessThan(10)) {\r\n\tcase 0:\r\n\tcase 1:\r\n\t\tspell = MissileID::Firebolt;\r\n\t\tbreak;\r\n\tcase 2:\r\n\t\tspell = MissileID::Fireball;\r\n\t\tbreak;\r\n\tcase 3:\r\n\t\tspell = MissileID::FireWallControl;\r\n\t\tbreak;\r\n\tcase 4:\r\n\t\tspell = MissileID::Guardian;\r\n\t\tbreak;\r\n\tcase 5:\r\n\t\tspell = MissileID::ChainLightning;\r\n\t\tbreak;\r\n\tcase 6:\r\n\t\tspell = MissileID::TownPortal;\r\n\t\tbreak;\r\n\tcase 7:\r\n\t\tspell = MissileID::Teleport;\r\n\t\tbreak;\r\n\tcase 8:\r\n\t\tspell = MissileID::Apocalypse;\r\n\t\tbreak;\r\n\tcase 9:\r\n\t\tspell = MissileID::StoneCurse;\r\n\t\tbreak;\r\n\t}\r\n\tMissile *randomMissile = AddMissile(missile.position.start, parameter.dst, parameter.midir, spell, missile._micaster, missile._misource, 0, missile._mispllvl);\r\n\tparameter.spellFizzled = randomMissile == nullptr;\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid AddStealPotions(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tCrawl(0, 2, [&](Displacement displacement) {\r\n\t\tconst Point target = missile.position.start + displacement;\r\n\t\tif (!InDungeonBounds(target))\r\n\t\t\treturn false;\r\n\t\tPlayer *player = PlayerAtPosition(target);\r\n\t\tif (player == nullptr)\r\n\t\t\treturn false;\r\n\r\n\t\tbool hasPlayedSFX = false;\r\n\t\tfor (int si = 0; si < MaxBeltItems; si++) {\r\n\t\t\tItem &beltItem = player->SpdList[si];\r\n\t\t\t_item_indexes ii = IDI_NONE;\r\n\t\t\tif (beltItem._itype == ItemType::Misc) {\r\n\t\t\t\tif (FlipCoin())\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tswitch (beltItem._iMiscId) {\r\n\t\t\t\tcase IMISC_FULLHEAL:\r\n\t\t\t\t\tii = ItemMiscIdIdx(IMISC_HEAL);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase IMISC_HEAL:\r\n\t\t\t\tcase IMISC_MANA:\r\n\t\t\t\t\tplayer->RemoveSpdBarItem(si);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase IMISC_FULLMANA:\r\n\t\t\t\t\tii = ItemMiscIdIdx(IMISC_MANA);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase IMISC_REJUV:\r\n\t\t\t\t\tii = ItemMiscIdIdx(PickRandomlyAmong({ IMISC_HEAL, IMISC_MANA }));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase IMISC_FULLREJUV:\r\n\t\t\t\t\tswitch (GenerateRnd(3)) {\r\n\t\t\t\t\tcase 0:\r\n\t\t\t\t\t\tii = ItemMiscIdIdx(IMISC_FULLMANA);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\tii = ItemMiscIdIdx(IMISC_FULLHEAL);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tii = ItemMiscIdIdx(IMISC_REJUV);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (ii != IDI_NONE) {\r\n\t\t\t\tauto seed = beltItem._iSeed;\r\n\t\t\t\tInitializeItem(beltItem, ii);\r\n\t\t\t\tbeltItem._iSeed = seed;\r\n\t\t\t\tbeltItem._iStatFlag = true;\r\n\t\t\t}\r\n\t\t\tif (!hasPlayedSFX) {\r\n\t\t\t\tPlaySfxLoc(SfxID::PodPop, target);\r\n\t\t\t\thasPlayedSFX = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tRedrawEverything();\r\n\r\n\t\treturn false;\r\n\t});\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid AddStealMana(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tstd::optional<Point> trappedPlayerPosition = FindClosestValidPosition(\r\n\t    [](Point target) {\r\n\t\t    return InDungeonBounds(target) && dPlayer[target.x][target.y] != 0;\r\n\t    },\r\n\t    missile.position.start, 0, 2);\r\n\r\n\tif (trappedPlayerPosition) {\r\n\t\tPlayer &player = Players[std::abs(dPlayer[trappedPlayerPosition->x][trappedPlayerPosition->y]) - 1];\r\n\r\n\t\tplayer._pMana = 0;\r\n\t\tplayer._pManaBase = player._pMana + player._pMaxManaBase - player._pMaxMana;\r\n\t\tCalcPlrInv(player, false);\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\tPlaySfxLoc(SfxID::Pig, *trappedPlayerPosition);\r\n\t}\r\n\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid AddSpectralArrow(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tint av = 0;\r\n\r\n\tif (missile.sourceType() == MissileSource::Player) {\r\n\t\tconst Player &player = *missile.sourcePlayer();\r\n\r\n\t\tif (player._pClass == HeroClass::Rogue)\r\n\t\t\tav += (player.getCharacterLevel() - 1) / 4;\r\n\t\telse if (player._pClass == HeroClass::Warrior || player._pClass == HeroClass::Bard)\r\n\t\t\tav += (player.getCharacterLevel() - 1) / 8;\r\n\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::QuickAttack))\r\n\t\t\tav++;\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastAttack))\r\n\t\t\tav += 2;\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FasterAttack))\r\n\t\t\tav += 4;\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastestAttack))\r\n\t\t\tav += 8;\r\n\t}\r\n\r\n\tmissile.duration = 1;\r\n\tmissile.var1 = parameter.dst.x;\r\n\tmissile.var2 = parameter.dst.y;\r\n\tmissile.var3 = av;\r\n}\r\n\r\nvoid AddWarp(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tint minDistanceSq = std::numeric_limits<int>::max();\r\n\r\n\tconst int id = missile._misource;\r\n\tPlayer &player = Players[id];\r\n\tPoint tile = player.position.tile;\r\n\r\n\tfor (int i = 0; i < numtrigs && i < MAXTRIGGERS; i++) {\r\n\t\tTriggerStruct *trg = &trigs[i];\r\n\t\tif (IsNoneOf(trg->_tmsg, WM_DIABTWARPUP, WM_DIABPREVLVL, WM_DIABNEXTLVL, WM_DIABRTNLVL))\r\n\t\t\tcontinue;\r\n\t\tPoint candidate = trg->position;\r\n\t\tauto getTriggerOffset = [](TriggerStruct *trg) {\r\n\t\t\tswitch (leveltype) {\r\n\t\t\tcase DTYPE_CATHEDRAL:\r\n\t\t\t\tif (setlevel && setlvlnum == SL_VILEBETRAYER)\r\n\t\t\t\t\treturn Displacement { 1, 1 }; // Portal\r\n\t\t\t\tif (IsAnyOf(trg->_tmsg, WM_DIABTWARPUP, WM_DIABPREVLVL, WM_DIABRTNLVL))\r\n\t\t\t\t\treturn Displacement { 1, 2 };\r\n\t\t\t\treturn Displacement { 0, 1 }; // WM_DIABNEXTLVL\r\n\t\t\tcase DTYPE_CATACOMBS:\r\n\t\t\t\tif (IsAnyOf(trg->_tmsg, WM_DIABTWARPUP, WM_DIABPREVLVL))\r\n\t\t\t\t\treturn Displacement { 1, 1 };\r\n\t\t\t\treturn Displacement { 0, 1 }; // WM_DIABRTNLVL, WM_DIABNEXTLVL\r\n\t\t\tcase DTYPE_CAVES:\r\n\t\t\t\tif (IsAnyOf(trg->_tmsg, WM_DIABTWARPUP, WM_DIABPREVLVL))\r\n\t\t\t\t\treturn Displacement { 0, 1 };\r\n\t\t\t\treturn Displacement { 1, 0 }; // WM_DIABRTNLVL, WM_DIABNEXTLVL\r\n\t\t\tcase DTYPE_HELL:\r\n\t\t\t\treturn Displacement { 1, 0 };\r\n\t\t\tcase DTYPE_NEST:\r\n\t\t\t\tif (IsAnyOf(trg->_tmsg, WM_DIABTWARPUP, WM_DIABPREVLVL, WM_DIABRTNLVL))\r\n\t\t\t\t\treturn Displacement { 0, 1 };\r\n\t\t\t\treturn Displacement { 1, 0 }; // WM_DIABNEXTLVL\r\n\t\t\tcase DTYPE_CRYPT:\r\n\t\t\t\tif (IsAnyOf(trg->_tmsg, WM_DIABTWARPUP, WM_DIABPREVLVL, WM_DIABRTNLVL))\r\n\t\t\t\t\treturn Displacement { 1, 1 };\r\n\t\t\t\treturn Displacement { 0, 1 }; // WM_DIABNEXTLVL\r\n\t\t\tcase DTYPE_TOWN:\r\n\t\t\t\tapp_fatal(\"invalid leveltype: DTYPE_TOWN\");\r\n\t\t\tcase DTYPE_NONE:\r\n\t\t\t\tapp_fatal(\"leveltype not set\");\r\n\t\t\t}\r\n\t\t\tapp_fatal(StrCat(\"invalid leveltype\", static_cast<int>(leveltype)));\r\n\t\t};\r\n\t\tconst Displacement triggerOffset = getTriggerOffset(trg);\r\n\t\tcandidate += triggerOffset;\r\n\t\tconst Displacement off = Point { player.position.tile } - candidate;\r\n\t\tconst int distanceSq = (off.deltaY * off.deltaY) + (off.deltaX * off.deltaX);\r\n\t\tif (distanceSq < minDistanceSq) {\r\n\t\t\tminDistanceSq = distanceSq;\r\n\t\t\ttile = candidate;\r\n\t\t}\r\n\t}\r\n\tmissile.duration = 2;\r\n\tstd::optional<Point> teleportDestination = FindClosestValidPosition(\r\n\t    [&player](Point target) {\r\n\t\t    for (int i = 0; i < numtrigs; i++) {\r\n\t\t\t    if (trigs[i].position == target)\r\n\t\t\t\t    return false;\r\n\t\t    }\r\n\t\t    return PosOkPlayer(player, target);\r\n\t    },\r\n\t    tile, 0, 5);\r\n\r\n\tif (teleportDestination) {\r\n\t\tmissile.position.tile = *teleportDestination;\r\n\t} else {\r\n\t\t// No valid teleport destination found\r\n\t\tmissile._miDelFlag = true;\r\n\t\tparameter.spellFizzled = true;\r\n\t}\r\n}\r\n\r\nvoid AddLightningWall(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tUpdateMissileVelocity(missile, parameter.dst, 16);\r\n\tmissile._miAnimFrame = RandomIntBetween(1, 8);\r\n\tmissile.duration = 255 * (missile._mispllvl + 1);\r\n\tswitch (missile.sourceType()) {\r\n\tcase MissileSource::Trap:\r\n\t\tmissile.var1 = missile.position.start.x;\r\n\t\tmissile.var2 = missile.position.start.y;\r\n\t\tbreak;\r\n\tcase MissileSource::Player: {\r\n\t\tconst Player &player = *missile.sourcePlayer();\r\n\t\tmissile.var1 = player.position.tile.x;\r\n\t\tmissile.var2 = player.position.tile.y;\r\n\t} break;\r\n\tcase MissileSource::Monster:\r\n\t\tassert(missile.sourceType() != MissileSource::Monster);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid AddBigExplosion(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tif (missile.sourceType() == MissileSource::Player) {\r\n\t\tint dmg = (2 * (missile.sourcePlayer()->getCharacterLevel() + GenerateRndSum(10, 2))) + 4;\r\n\t\tdmg = ScaleSpellEffect(dmg, missile._mispllvl);\r\n\r\n\t\tmissile._midam = dmg;\r\n\r\n\t\tconst DamageType damageType = GetMissileData(missile._mitype).damageType();\r\n\t\tfor (const Point position : PointsInRectangleColMajor(Rectangle { missile.position.tile, 1 }))\r\n\t\t\tCheckMissileCol(missile, damageType, dmg, dmg, false, position, true);\r\n\t}\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n\tmissile.setDefaultFrameGroup();\r\n\tmissile.duration = missile._miAnimLen - 1;\r\n}\r\n\r\nvoid AddImmolation(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == parameter.dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tint sp = 16;\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tsp += std::min(missile._mispllvl, 34);\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, sp);\r\n\tmissile.setDirection(GetDirection16(missile.position.start, dst));\r\n\tmissile.duration = 256;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n}\r\n\r\nvoid AddLightningBow(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == parameter.dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, 32);\r\n\tmissile._miAnimFrame = RandomIntBetween(1, 8);\r\n\tmissile.duration = 255;\r\n\tif (missile._misource < 0) {\r\n\t\tmissile.var1 = missile.position.start.x;\r\n\t\tmissile.var2 = missile.position.start.y;\r\n\t} else {\r\n\t\tmissile.var1 = Players[missile._misource].position.tile.x;\r\n\t\tmissile.var2 = Players[missile._misource].position.tile.y;\r\n\t}\r\n\tmissile._midam <<= 6;\r\n}\r\n\r\nvoid AddMana(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tint manaAmount = (GenerateRnd(10) + 1) << 6;\r\n\tfor (int i = 0; i < player.getCharacterLevel(); i++) {\r\n\t\tmanaAmount += RandomIntBetween(1, 4) << 6;\r\n\t}\r\n\tfor (int i = 0; i < missile._mispllvl; i++) {\r\n\t\tmanaAmount += (GenerateRnd(6) + 1) << 6;\r\n\t}\r\n\tif (player._pClass == HeroClass::Sorcerer)\r\n\t\tmanaAmount *= 2;\r\n\tif (player._pClass == HeroClass::Rogue || player._pClass == HeroClass::Bard)\r\n\t\tmanaAmount += manaAmount / 2;\r\n\tplayer._pMana += manaAmount;\r\n\tplayer._pMana = std::min(player._pMana, player._pMaxMana);\r\n\tplayer._pManaBase += manaAmount;\r\n\tplayer._pManaBase = std::min(player._pManaBase, player._pMaxManaBase);\r\n\tmissile._miDelFlag = true;\r\n\tRedrawComponent(PanelDrawComponent::Mana);\r\n}\r\n\r\nvoid AddMagi(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tplayer._pMana = player._pMaxMana;\r\n\tplayer._pManaBase = player._pMaxManaBase;\r\n\tmissile._miDelFlag = true;\r\n\tRedrawComponent(PanelDrawComponent::Mana);\r\n}\r\n\r\nvoid AddRingOfFire(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile.duration = 7;\r\n}\r\n\r\nvoid AddSearch(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tif (&player == MyPlayer)\r\n\t\tAutoMapShowItems = true;\r\n\tint lvl = 2;\r\n\tif (missile._misource >= 0)\r\n\t\tlvl = player.getCharacterLevel() * 2;\r\n\tmissile.duration = lvl + 10 * missile._mispllvl + 245;\r\n\r\n\tfor (auto &other : Missiles) {\r\n\t\tif (&other != &missile && missile.isSameSource(other) && other._mitype == MissileID::Search) {\r\n\t\t\tconst int r1 = missile.duration;\r\n\t\t\tconst int r2 = other.duration;\r\n\t\t\tif (r2 < INT_MAX - r1)\r\n\t\t\t\tother.duration = r1 + r2;\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddChargedBoltBow(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tmissile._mirnd = GenerateRnd(15) + 1;\r\n\tif (missile._micaster != TARGET_MONSTERS) {\r\n\t\tmissile._midam = 15;\r\n\t}\r\n\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tmissile._miAnimFrame = RandomIntBetween(1, 8);\r\n\tmissile._mlid = AddLight(missile.position.start, 5);\r\n\tUpdateMissileVelocity(missile, dst, 8);\r\n\tmissile.var1 = 5;\r\n\tmissile.var2 = static_cast<int32_t>(parameter.midir);\r\n\tmissile.duration = 256;\r\n}\r\n\r\nvoid AddElementalArrow(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tint av = 32;\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tconst Player &player = Players[missile._misource];\r\n\t\tif (player._pClass == HeroClass::Rogue)\r\n\t\t\tav += (player.getCharacterLevel()) / 4;\r\n\t\telse if (IsAnyOf(player._pClass, HeroClass::Warrior, HeroClass::Bard))\r\n\t\t\tav += (player.getCharacterLevel()) / 8;\r\n\r\n\t\tif (gbIsHellfire) {\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::QuickAttack))\r\n\t\t\t\tav++;\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastAttack))\r\n\t\t\t\tav += 2;\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FasterAttack))\r\n\t\t\t\tav += 4;\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastestAttack))\r\n\t\t\t\tav += 8;\r\n\t\t} else {\r\n\t\t\tif (IsAnyOf(player._pClass, HeroClass::Rogue, HeroClass::Warrior, HeroClass::Bard))\r\n\t\t\t\tav -= 1;\r\n\t\t}\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, av);\r\n\r\n\tmissile.setDirection(GetDirection16(missile.position.start, dst));\r\n\tmissile.duration = 256;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 5);\r\n}\r\n\r\nvoid AddArrow(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tint av = 32;\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tconst Player &player = Players[missile._misource];\r\n\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::RandomArrowVelocity)) {\r\n\t\t\tav = RandomIntBetween(16, 47);\r\n\t\t}\r\n\t\tif (player._pClass == HeroClass::Rogue)\r\n\t\t\tav += (player.getCharacterLevel() - 1) / 4;\r\n\t\telse if (player._pClass == HeroClass::Warrior || player._pClass == HeroClass::Bard)\r\n\t\t\tav += (player.getCharacterLevel() - 1) / 8;\r\n\r\n\t\tif (gbIsHellfire) {\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::QuickAttack))\r\n\t\t\t\tav++;\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastAttack))\r\n\t\t\t\tav += 2;\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FasterAttack))\r\n\t\t\t\tav += 4;\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastestAttack))\r\n\t\t\t\tav += 8;\r\n\t\t}\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, av);\r\n\tmissile._miAnimFrame = static_cast<int>(GetDirection16(missile.position.start, dst)) + 1;\r\n\tmissile.duration = 256;\r\n}\r\n\r\nvoid UpdateVileMissPos(Missile &missile, Point dst)\r\n{\r\n\tfor (int k = 1; k < 50; k++) {\r\n\t\tfor (int j = -k; j <= k; j++) {\r\n\t\t\tconst int yy = j + dst.y;\r\n\t\t\tfor (int i = -k; i <= k; i++) {\r\n\t\t\t\tconst int xx = i + dst.x;\r\n\t\t\t\tif (PosOkPlayer(*MyPlayer, { xx, yy })) {\r\n\t\t\t\t\tmissile.position.tile = WorldTilePosition(xx, yy);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddPhasing(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.duration = 2;\r\n\r\n\tconst Player &player = Players[missile._misource];\r\n\r\n\tif (missile._micaster == TARGET_BOTH) {\r\n\t\tmissile.position.tile = parameter.dst;\r\n\t\tif (!PosOkPlayer(player, parameter.dst))\r\n\t\t\tUpdateVileMissPos(missile, parameter.dst);\r\n\t\treturn;\r\n\t}\r\n\r\n\tstd::array<Point, static_cast<std::size_t>(4 * 9)> targets;\r\n\r\n\tint count = 0;\r\n\tfor (int y = -6; y <= 6; y++) {\r\n\t\tfor (int x = -6; x <= 6; x++) {\r\n\t\t\tif ((x >= -3 && x <= 3) || (y >= -3 && y <= 3))\r\n\t\t\t\tcontinue; // Skip center\r\n\r\n\t\t\tconst Point target = missile.position.start + Displacement { x, y };\r\n\t\t\tif (!PosOkPlayer(player, target))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\ttargets[count] = target;\r\n\t\t\tcount++;\r\n\t\t}\r\n\t}\r\n\r\n\tif (count == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tmissile.position.tile = targets[std::max<int32_t>(GenerateRnd(count), 0)];\r\n}\r\n\r\nvoid AddFirebolt(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tint sp = 26;\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tsp = 16;\r\n\t\tif (!missile.IsTrap()) {\r\n\t\t\tsp += std::min(missile._mispllvl * 2, 47);\r\n\t\t}\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, sp);\r\n\tmissile.setDirection(GetDirection16(missile.position.start, dst));\r\n\tmissile.duration = 256;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n\tif (missile._midam == 0) {\r\n\t\tswitch (missile.sourceType()) {\r\n\t\tcase MissileSource::Player: {\r\n\t\t\tconst Player &player = *missile.sourcePlayer();\r\n\t\t\tmissile._midam = GenerateRnd(10) + (player._pMagic / 8) + missile._mispllvl + 1;\r\n\t\t} break;\r\n\r\n\t\tcase MissileSource::Monster:\r\n\t\t\tmissile._midam = ProjectileMonsterDamage(missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileSource::Trap:\r\n\t\t\tmissile._midam = ProjectileTrapDamage();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddMagmaBall(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tUpdateMissileVelocity(missile, parameter.dst, 16);\r\n\tmissile.position.traveled.deltaX += 3 * missile.position.velocity.deltaX;\r\n\tmissile.position.traveled.deltaY += 3 * missile.position.velocity.deltaY;\r\n\tUpdateMissilePos(missile);\r\n\tif (!gbIsHellfire || (missile.position.velocity.deltaX & 0xFFFF0000) != 0 || (missile.position.velocity.deltaY & 0xFFFF0000) != 0)\r\n\t\tmissile.duration = 256;\r\n\telse\r\n\t\tmissile.duration = 1;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n\tif (missile._midam == 0) {\r\n\t\tswitch (missile.sourceType()) {\r\n\t\tcase MissileSource::Player:\r\n\t\t\t// Not typically created by Players\r\n\t\t\tbreak;\r\n\t\tcase MissileSource::Monster:\r\n\t\t\tmissile._midam = ProjectileMonsterDamage(missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileSource::Trap:\r\n\t\t\tmissile._midam = ProjectileTrapDamage();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddTeleport(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tstd::optional<Point> teleportDestination = FindClosestValidPosition(\r\n\t    [&player](Point target) {\r\n\t\t    return PosOkPlayer(player, target);\r\n\t    },\r\n\t    parameter.dst, 0, 5);\r\n\r\n\tif (teleportDestination) {\r\n\t\tmissile.position.tile = *teleportDestination;\r\n\t\tmissile.position.start = *teleportDestination;\r\n\t\tmissile.duration = 2;\r\n\t} else {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tparameter.spellFizzled = true;\r\n\t}\r\n}\r\n\r\nvoid AddNovaBall(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tUpdateMissileVelocity(missile, parameter.dst, 16);\r\n\tmissile._miAnimFrame = RandomIntBetween(1, 8);\r\n\tmissile.duration = 255;\r\n\tconst WorldTilePosition position = missile._misource < 0 ? missile.position.start : Players[missile._misource].position.tile;\r\n\tmissile.var1 = position.x;\r\n\tmissile.var2 = position.y;\r\n}\r\n\r\nvoid AddFireWall(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile._midam = GenerateRndSum(10, 2) + 2;\r\n\tmissile._midam += missile._misource >= 0 ? Players[missile._misource].getCharacterLevel() : currlevel; // BUGFIX: missing parenthesis around ternary (fixed)\r\n\tmissile._midam <<= 3;\r\n\tUpdateMissileVelocity(missile, parameter.dst, 16);\r\n\tconst int i = missile._mispllvl;\r\n\tmissile.duration = 10;\r\n\tif (i > 0)\r\n\t\tmissile.duration *= i + 1;\r\n\tif (missile._micaster == TARGET_PLAYERS || missile._misource < 0)\r\n\t\tmissile.duration += currlevel;\r\n\tmissile.duration *= 16;\r\n\tmissile.var1 = missile.duration - missile._miAnimLen;\r\n}\r\n\r\nvoid AddFireball(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tint sp = 16;\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tsp += std::min(missile._mispllvl * 2, 34);\r\n\t\tconst Player &player = Players[missile._misource];\r\n\r\n\t\tconst int dmg = (2 * (player.getCharacterLevel() + GenerateRndSum(10, 2))) + 4;\r\n\t\tmissile._midam = ScaleSpellEffect(dmg, missile._mispllvl);\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, sp);\r\n\tmissile.setDirection(GetDirection16(missile.position.start, dst));\r\n\tmissile.duration = 256;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n}\r\n\r\nvoid AddLightningControl(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tUpdateMissileVelocity(missile, parameter.dst, 32);\r\n\tmissile._miAnimFrame = RandomIntBetween(1, 8);\r\n\tmissile.duration = 256;\r\n}\r\n\r\nvoid AddLightning(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.position.start = parameter.dst;\r\n\r\n\tSyncPositionWithParent(missile, parameter);\r\n\r\n\tmissile._miAnimFrame = RandomIntBetween(1, 8);\r\n\r\n\tif (missile._micaster == TARGET_PLAYERS || missile.IsTrap()) {\r\n\t\tif (missile.IsTrap() || Monsters[missile._misource].type().type == MT_FAMILIAR)\r\n\t\t\tmissile.duration = 8;\r\n\t\telse\r\n\t\t\tmissile.duration = 10;\r\n\t} else {\r\n\t\tmissile.duration = (missile._mispllvl / 2) + 6;\r\n\t}\r\n\tmissile._mlid = AddLight(missile.position.tile, 4);\r\n}\r\n\r\nvoid AddMissileExplosion(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tif (missile._micaster != TARGET_MONSTERS && missile._misource >= 0) {\r\n\t\tswitch (Monsters[missile._misource].type().type) {\r\n\t\tcase MT_SUCCUBUS:\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStarExplosion);\r\n\t\t\tbreak;\r\n\t\tcase MT_SNOWWICH:\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStarBlueExplosion);\r\n\t\t\tbreak;\r\n\t\tcase MT_HLSPWN:\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStarRedExplosion);\r\n\t\t\tbreak;\r\n\t\tcase MT_SOLBRNR:\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStarYellowExplosion);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tassert(parameter.pParent != nullptr); // AddMissileExplosion will always be called with a parent associated to the missile.\r\n\tauto &parent = *parameter.pParent;\r\n\tmissile.position.tile = parent.position.tile;\r\n\tmissile.position.start = parent.position.start;\r\n\tmissile.position.offset = parent.position.offset;\r\n\tmissile.position.traveled = parent.position.traveled;\r\n\tmissile.duration = missile._miAnimLen;\r\n}\r\n\r\nvoid AddWeaponExplosion(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.var2 = parameter.dst.x;\r\n\tif (parameter.dst.x == 1)\r\n\t\tmissile.setAnimation(MissileGraphicID::MagmaBallExplosion);\r\n\telse\r\n\t\tmissile.setAnimation(MissileGraphicID::ChargedBolt);\r\n\tmissile.duration = missile._miAnimLen - 1;\r\n}\r\n\r\nvoid AddTownPortal(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tmissile.position.tile = parameter.dst;\r\n\t\tmissile.position.start = parameter.dst;\r\n\t} else {\r\n\t\tstd::optional<Point> targetPosition = FindClosestValidPosition(\r\n\t\t    [](Point target) {\r\n\t\t\t    if (!InDungeonBounds(target)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    if (IsObjectAtPosition(target)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    if (dPlayer[target.x][target.y] != 0) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    if (TileContainsMissile(target)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    if (TileHasAny(target, TileProperties::Solid | TileProperties::BlockMissile)) {\r\n\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    return !CheckIfTrig(target);\r\n\t\t    },\r\n\t\t    parameter.dst, 0, 5);\r\n\r\n\t\tif (targetPosition) {\r\n\t\t\tmissile.position.tile = *targetPosition;\r\n\t\t\tmissile.position.start = *targetPosition;\r\n\t\t\tmissile._miDelFlag = false;\r\n\t\t} else {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t}\r\n\t}\r\n\r\n\tmissile.duration = 100;\r\n\tmissile.var1 = missile.duration - missile._miAnimLen;\r\n\tfor (auto &other : Missiles) {\r\n\t\tif (other._mitype == MissileID::TownPortal && &other != &missile && missile.isSameSource(other))\r\n\t\t\tother.duration = 0;\r\n\t}\r\n\tPutMissile(missile);\r\n\tif (missile.sourcePlayer() == MyPlayer && !missile._miDelFlag && leveltype != DTYPE_TOWN) {\r\n\t\tif (!setlevel) {\r\n\t\t\tNetSendCmdLocParam3(true, CMD_ACTIVATEPORTAL, missile.position.tile, currlevel, leveltype, 0);\r\n\t\t} else {\r\n\t\t\tNetSendCmdLocParam3(true, CMD_ACTIVATEPORTAL, missile.position.tile, setlvlnum, leveltype, 1);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddFlashBottom(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tswitch (missile.sourceType()) {\r\n\tcase MissileSource::Player: {\r\n\t\tconst Player &player = *missile.sourcePlayer();\r\n\t\tconst int dmg = GenerateRndSum(20, player.getCharacterLevel() + 1) + player.getCharacterLevel() + 1;\r\n\t\tmissile._midam = ScaleSpellEffect(dmg, missile._mispllvl);\r\n\t\tmissile._midam += missile._midam / 2;\r\n\t} break;\r\n\tcase MissileSource::Monster:\r\n\t\tmissile._midam = missile.sourceMonster()->level(sgGameInitInfo.nDifficulty) * 2;\r\n\t\tbreak;\r\n\tcase MissileSource::Trap:\r\n\t\tmissile._midam = currlevel / 2;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tmissile.duration = 19;\r\n}\r\n\r\nvoid AddFlashTop(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tif (!missile.IsTrap()) {\r\n\t\t\tint dmg = Players[missile._misource].getCharacterLevel() + 1;\r\n\t\t\tdmg += GenerateRndSum(20, dmg);\r\n\t\t\tmissile._midam = ScaleSpellEffect(dmg, missile._mispllvl);\r\n\t\t\tmissile._midam += missile._midam / 2;\r\n\t\t} else {\r\n\t\t\tmissile._midam = currlevel / 2;\r\n\t\t}\r\n\t}\r\n\tmissile._miPreFlag = true;\r\n\tmissile.duration = 19;\r\n}\r\n\r\nvoid AddManaShield(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile._miDelFlag = true;\r\n\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tif (player.pManaShield) {\r\n\t\tparameter.spellFizzled = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tplayer.pManaShield = true;\r\n\tif (&player == MyPlayer)\r\n\t\tNetSendCmd(true, CMD_SETSHIELD);\r\n}\r\n\r\nvoid AddFlameWave(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile._midam = GenerateRnd(10) + Players[missile._misource].getCharacterLevel() + 1;\r\n\tUpdateMissileVelocity(missile, parameter.dst, 16);\r\n\tmissile.duration = 255;\r\n\r\n\t// Adjust missile's position for rendering\r\n\tmissile.position.tile += Direction::South;\r\n\tmissile.position.offset.deltaY -= 32;\r\n}\r\n\r\nvoid AddGuardian(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tconst Player &player = Players[missile._misource];\r\n\r\n\tstd::optional<Point> spawnPosition = FindClosestValidPosition(\r\n\t    [start = missile.position.start](Point target) {\r\n\t\t    if (!InDungeonBounds(target)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\t\t    if (dMonster[target.x][target.y] != 0) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\t\t    if (IsObjectAtPosition(target)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\t\t    if (TileContainsMissile(target)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\r\n\t\t    if (TileHasAny(target, TileProperties::Solid | TileProperties::BlockMissile)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\r\n\t\t    return LineClearMissile(start, target);\r\n\t    },\r\n\t    parameter.dst, 0, 5);\r\n\r\n\tif (!spawnPosition) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tparameter.spellFizzled = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tmissile._miDelFlag = false;\r\n\tmissile.position.tile = *spawnPosition;\r\n\tmissile.position.start = *spawnPosition;\r\n\r\n\tmissile._mlid = AddLight(missile.position.tile, 1);\r\n\tmissile.duration = missile._mispllvl + (player.getCharacterLevel() / 2);\r\n\r\n\tmissile.duration = std::min(missile.duration, 30);\r\n\tmissile.duration <<= 4;\r\n\tmissile.duration = std::max(missile.duration, 30);\r\n\r\n\tmissile.var1 = missile.duration - missile._miAnimLen;\r\n\tmissile.var3 = 1;\r\n}\r\n\r\nvoid AddChainLightning(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.var1 = parameter.dst.x;\r\n\tmissile.var2 = parameter.dst.y;\r\n\tmissile.duration = 1;\r\n}\r\n\r\nnamespace {\r\nvoid InitMissileAnimationFromMonster(Missile &mis, Direction midir, const Monster &mon, MonsterGraphic graphic)\r\n{\r\n\tconst AnimStruct &anim = mon.type().getAnimData(graphic);\r\n\tmis.setDirection(midir);\r\n\tmis._miAnimFlags = MissileGraphicsFlags::None;\r\n\tconst ClxSpriteList sprites = *anim.spritesForDirection(midir);\r\n\tconst uint16_t width = sprites[0].width();\r\n\tmis._miAnimData.emplace(sprites);\r\n\tmis._miAnimDelay = anim.rate;\r\n\tmis._miAnimLen = anim.frames;\r\n\tmis._miAnimWidth = width;\r\n\tmis._miAnimWidth2 = CalculateSpriteTileCenterX(width);\r\n\tmis._miAnimAdd = 1;\r\n\tmis.var1 = 0;\r\n\tmis.var2 = 0;\r\n\tmis._miLightFlag = true;\r\n\tmis.duration = 256;\r\n}\r\n} // namespace\r\n\r\nvoid AddRhino(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tconst Monster &monster = Monsters[missile._misource];\r\n\r\n\tMonsterGraphic graphic = MonsterGraphic::Walk;\r\n\tif (IsAnyOf(monster.type().type, MT_HORNED, MT_MUDRUN, MT_FROSTC, MT_OBLORD)) {\r\n\t\tgraphic = MonsterGraphic::Special;\r\n\t} else if (IsAnyOf(monster.type().type, MT_NSNAKE, MT_RSNAKE, MT_BSNAKE, MT_GSNAKE)) {\r\n\t\tgraphic = MonsterGraphic::Attack;\r\n\t}\r\n\tUpdateMissileVelocity(missile, parameter.dst, 18);\r\n\tInitMissileAnimationFromMonster(missile, parameter.midir, monster, graphic);\r\n\tif (IsAnyOf(monster.type().type, MT_NSNAKE, MT_RSNAKE, MT_BSNAKE, MT_GSNAKE))\r\n\t\tmissile._miAnimFrame = 7;\r\n\tif (monster.isUnique()) {\r\n\t\tmissile._mlid = monster.lightId;\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid AddGenericMagicMissile(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, 16);\r\n\tmissile.duration = 256;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n\tif (missile._micaster != TARGET_MONSTERS && missile._misource > 0) {\r\n\t\tconst Monster &monster = Monsters[missile._misource];\r\n\t\tif (monster.type().type == MT_SUCCUBUS)\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStar);\r\n\t\tif (monster.type().type == MT_SNOWWICH)\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStarBlue);\r\n\t\tif (monster.type().type == MT_HLSPWN)\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStarRed);\r\n\t\tif (monster.type().type == MT_SOLBRNR)\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BloodStarYellow);\r\n\t}\r\n\r\n\tif (GetMissileSpriteData(missile._miAnimType).animFAmt == 16) {\r\n\t\tmissile.setDirection(GetDirection16(missile.position.start, dst));\r\n\t}\r\n\r\n\tif (missile._midam == 0) {\r\n\t\tswitch (missile.sourceType()) {\r\n\t\tcase MissileSource::Player: {\r\n\t\t\tconst Player &player = *missile.sourcePlayer();\r\n\t\t\tmissile._midam = 3 * missile._mispllvl - (player._pMagic / 8) + (player._pMagic / 2);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase MissileSource::Monster:\r\n\t\t\tmissile._midam = ProjectileMonsterDamage(missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileSource::Trap:\r\n\t\t\tmissile._midam = ProjectileTrapDamage();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddAcid(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tUpdateMissileVelocity(missile, parameter.dst, 16);\r\n\tmissile.setDirection(GetDirection16(missile.position.start, parameter.dst));\r\n\tif (!gbIsHellfire || (missile.position.velocity.deltaX & 0xFFFF0000) != 0 || (missile.position.velocity.deltaY & 0xFFFF0000) != 0)\r\n\t\tmissile.duration = 5 * (Monsters[missile._misource].intelligence + 4);\r\n\telse\r\n\t\tmissile.duration = 1;\r\n\tmissile._mlid = NO_LIGHT;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tif (missile._midam == 0) {\r\n\t\tswitch (missile.sourceType()) {\r\n\t\tcase MissileSource::Player:\r\n\t\t\t// Not typically created by Players\r\n\t\t\tbreak;\r\n\t\tcase MissileSource::Monster:\r\n\t\t\tmissile._midam = ProjectileMonsterDamage(missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileSource::Trap:\r\n\t\t\tmissile._midam = ProjectileTrapDamage();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid AddAcidPuddle(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tmissile._miLightFlag = true;\r\n\tconst int monst = missile._misource;\r\n\tmissile.duration = GenerateRnd(15) + 40 * (Monsters[monst].intelligence + 1);\r\n\tmissile._miPreFlag = true;\r\n}\r\n\r\nvoid AddStoneCurse(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tstd::optional<Point> targetMonsterPosition = FindClosestValidPosition(\r\n\t    [](Point target) {\r\n\t\t    if (!InDungeonBounds(target)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\r\n\t\t    const int monsterId = std::abs(dMonster[target.x][target.y]) - 1;\r\n\t\t    if (monsterId < 0) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\r\n\t\t    const Monster &monster = Monsters[monsterId];\r\n\r\n\t\t    if (IsAnyOf(monster.type().type, MT_GOLEM, MT_DIABLO, MT_NAKRUL)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\t\t    if (IsAnyOf(monster.mode, MonsterMode::FadeIn, MonsterMode::FadeOut, MonsterMode::Charge)) {\r\n\t\t\t    return false;\r\n\t\t    }\r\n\r\n\t\t    return true;\r\n\t    },\r\n\t    parameter.dst, 0, 5);\r\n\r\n\tif (!targetMonsterPosition) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tparameter.spellFizzled = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Petrify the targeted monster\r\n\tconst int monsterId = std::abs(dMonster[targetMonsterPosition->x][targetMonsterPosition->y]) - 1;\r\n\tMonster &monster = Monsters[monsterId];\r\n\r\n\tif (monster.mode == MonsterMode::Petrified) {\r\n\t\t// Monster is already petrified and StoneCurse doesn't stack\r\n\t\tmissile._miDelFlag = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tmissile.var1 = static_cast<int>(monster.mode);\r\n\tmissile.var2 = monsterId;\r\n\tmonster.petrify();\r\n\r\n\t// And set up the missile to unpetrify it in the future\r\n\tmissile.position.tile = *targetMonsterPosition;\r\n\tmissile.position.start = missile.position.tile;\r\n\tmissile.duration = missile._mispllvl + 6;\r\n\r\n\tmissile.duration = std::min(missile.duration, 15);\r\n\tmissile.duration <<= 4;\r\n}\r\n\r\nvoid AddGolem(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile._miDelFlag = true;\r\n\r\n\tconst int playerId = missile._misource;\r\n\tPlayer &player = Players[playerId];\r\n\tMonster *golem = FindGolemForPlayer(player);\r\n\r\n\t// Is Golem alive?\r\n\tif (golem != nullptr) {\r\n\t\tKillGolem(*golem);\r\n\t\treturn;\r\n\t}\r\n\r\n\tstd::optional<Point> spawnPosition = FindClosestValidPosition(\r\n\t    [start = missile.position.start](Point target) {\r\n\t\t    return !IsTileOccupied(target) && LineClearMissile(start, target);\r\n\t    },\r\n\t    parameter.dst, 0, 5);\r\n\r\n\tif (!spawnPosition)\r\n\t\treturn;\r\n\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tconst auto spellLevel = static_cast<uint8_t>(missile._mispllvl);\r\n\r\n\t// The command is only executed for the level owner, to prevent desyncs in multiplayer.\r\n\tif (!MyPlayer->isLevelOwnedByLocalClient()) {\r\n\t\t// If we are not the level owner, request the level owner to spawn the golem for us\r\n\t\tNetSendCmdLocParam1(true, CMD_REQUESTSPAWNGOLEM, *spawnPosition, spellLevel);\r\n\t\treturn;\r\n\t}\r\n\tSpawnGolem(player, *spawnPosition, spellLevel);\r\n}\r\n\r\nvoid AddApocalypseBoom(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.position.tile = parameter.dst;\r\n\tmissile.position.start = parameter.dst;\r\n\tmissile.duration = missile._miAnimLen;\r\n}\r\n\r\nvoid AddHealing(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tint hp = GenerateRnd(10) + 1;\r\n\thp += GenerateRndSum(4, player.getCharacterLevel()) + player.getCharacterLevel();\r\n\thp += GenerateRndSum(6, missile._mispllvl) + missile._mispllvl;\r\n\thp <<= 6;\r\n\r\n\tif (player._pClass == HeroClass::Warrior || player._pClass == HeroClass::Barbarian || player._pClass == HeroClass::Monk) {\r\n\t\thp *= 2;\r\n\t} else if (player._pClass == HeroClass::Rogue || player._pClass == HeroClass::Bard) {\r\n\t\thp += hp / 2;\r\n\t}\r\n\r\n\tplayer._pHitPoints = std::min(player._pHitPoints + hp, player._pMaxHP);\r\n\tplayer._pHPBase = std::min(player._pHPBase + hp, player._pMaxHPBase);\r\n\r\n\tmissile._miDelFlag = true;\r\n\tRedrawComponent(PanelDrawComponent::Health);\r\n}\r\n\r\nvoid AddHealOther(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tmissile._miDelFlag = true;\r\n\tif (&player == MyPlayer) {\r\n\t\tNewCursor(CURSOR_HEALOTHER);\r\n\t\tif (ControlMode != ControlTypes::KeyboardAndMouse)\r\n\t\t\tTryIconCurs();\r\n\t}\r\n}\r\n\r\nvoid AddElemental(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\r\n\tconst Player &player = Players[missile._misource];\r\n\r\n\tconst int dmg = (2 * (player.getCharacterLevel() + GenerateRndSum(10, 2))) + 4;\r\n\tmissile._midam = ScaleSpellEffect(dmg, missile._mispllvl) / 2;\r\n\r\n\tUpdateMissileVelocity(missile, dst, 16);\r\n\tmissile.setDirection(GetDirection(missile.position.start, dst));\r\n\tmissile.duration = 256;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile.var4 = dst.x;\r\n\tmissile.var5 = dst.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n}\r\n\r\nvoid AddIdentify(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tmissile._miDelFlag = true;\r\n\tif (&player == MyPlayer) {\r\n\t\tif (SpellbookFlag)\r\n\t\t\tSpellbookFlag = false;\r\n\t\tif (!invflag) {\r\n\t\t\tinvflag = true;\r\n\t\t\tif (ControlMode != ControlTypes::KeyboardAndMouse)\r\n\t\t\t\tFocusOnInventory();\r\n\t\t}\r\n\t\tNewCursor(CURSOR_IDENTIFY);\r\n\t}\r\n}\r\n\r\nvoid AddWallControl(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tstd::optional<Point> spreadPosition = FindClosestValidPosition(\r\n\t    [start = missile.position.start](Point target) {\r\n\t\t    return start != target && !TileHasAny(target, TileProperties::BlockMissile) && LineClearMissile(start, target);\r\n\t    },\r\n\t    parameter.dst, 0, 5);\r\n\r\n\tif (!spreadPosition) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tparameter.spellFizzled = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tmissile._miDelFlag = false;\r\n\tmissile.var1 = spreadPosition->x;\r\n\tmissile.var2 = spreadPosition->y;\r\n\tmissile.var5 = spreadPosition->x;\r\n\tmissile.var6 = spreadPosition->y;\r\n\tmissile.var3 = static_cast<int>(Left(Left(parameter.midir)));\r\n\tmissile.var4 = static_cast<int>(Right(Right(parameter.midir)));\r\n\tmissile.duration = 7;\r\n}\r\n\r\nvoid AddInfravision(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tmissile.duration = ScaleSpellEffect(1584, missile._mispllvl);\r\n}\r\n\r\nvoid AddFlameWaveControl(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.var1 = parameter.dst.x;\r\n\tmissile.var2 = parameter.dst.y;\r\n\tmissile.duration = 1;\r\n\tmissile._miAnimFrame = 4;\r\n}\r\n\r\nvoid AddNova(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.var1 = parameter.dst.x;\r\n\tmissile.var2 = parameter.dst.y;\r\n\r\n\tif (!missile.IsTrap()) {\r\n\t\tconst Player &player = Players[missile._misource];\r\n\t\tconst int dmg = GenerateRndSum(6, 5) + player.getCharacterLevel() + 5;\r\n\t\tmissile._midam = ScaleSpellEffect(dmg / 2, missile._mispllvl);\r\n\t} else {\r\n\t\tmissile._midam = (currlevel / 2) + GenerateRndSum(3, 3);\r\n\t}\r\n\r\n\tmissile.duration = 1;\r\n}\r\n\r\nvoid AddRage(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tif (HasAnyOf(player._pSpellFlags, SpellFlag::RageActive | SpellFlag::RageCooldown) || player._pHitPoints <= player.getCharacterLevel() << 6) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tparameter.spellFizzled = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tmissile._midam = player.getCharacterLevel() * 6;\r\n\tmissile.duration = 245 + (player.getCharacterLevel() * 2);\r\n\tmissile.var1 = missile.duration;\r\n\r\n\tplayer._pSpellFlags |= SpellFlag::RageActive;\r\n\tCalcPlrItemVals(player, true);\r\n\tplayer.Say(HeroSpeech::Aaaaargh);\r\n}\r\n\r\nvoid AddItemRepair(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tmissile._miDelFlag = true;\r\n\tif (&player == MyPlayer) {\r\n\t\tif (SpellbookFlag)\r\n\t\t\tSpellbookFlag = false;\r\n\t\tif (!invflag) {\r\n\t\t\tinvflag = true;\r\n\t\t\tif (ControlMode != ControlTypes::KeyboardAndMouse)\r\n\t\t\t\tFocusOnInventory();\r\n\t\t}\r\n\t\tNewCursor(CURSOR_REPAIR);\r\n\t}\r\n}\r\n\r\nvoid AddStaffRecharge(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tmissile._miDelFlag = true;\r\n\tif (&player == MyPlayer) {\r\n\t\tif (SpellbookFlag)\r\n\t\t\tSpellbookFlag = false;\r\n\t\tif (!invflag) {\r\n\t\t\tinvflag = true;\r\n\t\t\tif (ControlMode != ControlTypes::KeyboardAndMouse)\r\n\t\t\t\tFocusOnInventory();\r\n\t\t}\r\n\t\tNewCursor(CURSOR_RECHARGE);\r\n\t}\r\n}\r\n\r\nvoid AddTrapDisarm(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tmissile._miDelFlag = true;\r\n\tif (&player == MyPlayer) {\r\n\t\tNewCursor(CURSOR_DISARM);\r\n\t\tif (ControlMode != ControlTypes::KeyboardAndMouse) {\r\n\t\t\tif (ObjectUnderCursor != nullptr)\r\n\t\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_DISARMXY, cursPosition);\r\n\t\t\telse\r\n\t\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddApocalypse(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tconst Player &player = Players[missile._misource];\r\n\r\n\tmissile.var1 = 8;\r\n\tmissile.var2 = std::max(missile.position.start.y - 8, 1);\r\n\tmissile.var3 = std::min(missile.position.start.y + 8, MAXDUNY - 1);\r\n\tmissile.var4 = std::max(missile.position.start.x - 8, 1);\r\n\tmissile.var5 = std::min(missile.position.start.x + 8, MAXDUNX - 1);\r\n\tmissile.var6 = missile.var4;\r\n\tconst int playerLevel = player.getCharacterLevel();\r\n\tmissile._midam = GenerateRndSum(6, playerLevel) + playerLevel;\r\n\tmissile.duration = 255;\r\n}\r\n\r\nvoid AddInferno(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.var2 = 5 * missile._midam;\r\n\tmissile.position.start = parameter.dst;\r\n\r\n\tSyncPositionWithParent(missile, parameter);\r\n\r\n\tmissile.duration = missile.var2 + 20;\r\n\tmissile._mlid = AddLight(missile.position.start, 1);\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tconst int i = GenerateRnd(Players[missile._misource].getCharacterLevel()) + GenerateRnd(2);\r\n\t\tmissile._midam = 8 * i + 16 + ((8 * i + 16) / 2);\r\n\t} else {\r\n\t\tconst Monster &monster = Monsters[missile._misource];\r\n\t\tmissile._midam = RandomIntBetween(monster.minDamage, monster.maxDamage);\r\n\t}\r\n}\r\n\r\nvoid AddInfernoControl(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == parameter.dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, 32);\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile.duration = 256;\r\n}\r\n\r\nvoid AddChargedBolt(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tmissile._mirnd = GenerateRnd(15) + 1;\r\n\tmissile._midam = (missile._micaster == TARGET_MONSTERS) ? (GenerateRnd(Players[missile._misource]._pMagic / 4) + 1) : 15;\r\n\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tmissile._miAnimFrame = RandomIntBetween(1, 8);\r\n\tmissile._mlid = AddLight(missile.position.start, 5);\r\n\r\n\tUpdateMissileVelocity(missile, dst, 8);\r\n\tmissile.var1 = 5;\r\n\tmissile.var2 = static_cast<int>(parameter.midir);\r\n\tmissile.duration = 256;\r\n}\r\n\r\nvoid AddHolyBolt(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tint sp = 16;\r\n\tif (!missile.IsTrap()) {\r\n\t\tsp += std::min(missile._mispllvl * 2, 47);\r\n\t}\r\n\r\n\tconst Player &player = Players[missile._misource];\r\n\r\n\tUpdateMissileVelocity(missile, dst, sp);\r\n\tmissile.setDirection(GetDirection16(missile.position.start, dst));\r\n\tmissile.duration = 256;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n\tmissile._midam = GenerateRnd(10) + player.getCharacterLevel() + 9;\r\n}\r\n\r\nvoid AddResurrect(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tNewCursor(CURSOR_RESURRECT);\r\n\t\tif (ControlMode != ControlTypes::KeyboardAndMouse)\r\n\t\t\tTryIconCurs();\r\n\t}\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid AddResurrectBeam(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tmissile.position.tile = parameter.dst;\r\n\tmissile.position.start = parameter.dst;\r\n\tmissile.duration = GetMissileSpriteData(MissileGraphicID::Resurrect).animLen(0);\r\n}\r\n\r\nvoid AddTelekinesis(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tmissile._miDelFlag = true;\r\n\tif (&player == MyPlayer)\r\n\t\tNewCursor(CURSOR_TELEKINESIS);\r\n}\r\n\r\nvoid AddBoneSpirit(Missile &missile, AddMissileParameter &parameter)\r\n{\r\n\tWorldTilePosition dst = parameter.dst;\r\n\tif (missile.position.start == dst) {\r\n\t\tdst += parameter.midir;\r\n\t}\r\n\tUpdateMissileVelocity(missile, dst, 16);\r\n\tmissile.setDirection(GetDirection(missile.position.start, dst));\r\n\tmissile.duration = 256;\r\n\tmissile.var1 = missile.position.start.x;\r\n\tmissile.var2 = missile.position.start.y;\r\n\tmissile.var4 = dst.x;\r\n\tmissile.var5 = dst.y;\r\n\tmissile._mlid = AddLight(missile.position.start, 8);\r\n}\r\n\r\nvoid AddRedPortal(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tmissile.duration = 100;\r\n\tmissile.var1 = 100 - missile._miAnimLen;\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid AddDiabloApocalypse(Missile &missile, AddMissileParameter & /*parameter*/)\r\n{\r\n\tfor (const Player &player : Players) {\r\n\t\tif (!player.plractive)\r\n\t\t\tcontinue;\r\n\t\tif (!LineClearMissile(missile.position.start, player.position.future))\r\n\t\t\tcontinue;\r\n\r\n\t\tAddMissile({ 0, 0 }, player.position.future, Direction::South, MissileID::DiabloApocalypseBoom, missile._micaster, missile._misource, missile._midam, 0);\r\n\t}\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nMissile *AddMissile(WorldTilePosition src, WorldTilePosition dst, Direction midir, MissileID mitype,\r\n    mienemy_type micaster, int id, int midam, int spllvl,\r\n    Missile *parent, std::optional<SfxID> lSFX)\r\n{\r\n\tif (Missiles.size() >= Missiles.max_size()) {\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tMissiles.emplace_back();\r\n\tauto &missile = Missiles.back();\r\n\r\n\tconst MissileData &missileData = GetMissileData(mitype);\r\n\r\n\tmissile._mitype = mitype;\r\n\tmissile._micaster = micaster;\r\n\tmissile._misource = id;\r\n\tmissile._midam = midam;\r\n\tmissile._mispllvl = spllvl;\r\n\tmissile.position.tile = src;\r\n\tmissile.position.start = src;\r\n\tmissile._miAnimAdd = 1;\r\n\tmissile._miAnimType = missileData.graphic;\r\n\tmissile._miDrawFlag = missileData.isDrawn();\r\n\tmissile._mlid = NO_LIGHT;\r\n\tmissile.lastCollisionTargetHash = 0;\r\n\r\n\tif (!missile.IsTrap() && micaster == TARGET_PLAYERS) {\r\n\t\tconst Monster &monster = Monsters[id];\r\n\t\tif (monster.isUnique()) {\r\n\t\t\tmissile._miUniqTrans = monster.uniqTrans + 1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (missile._miAnimType == MissileGraphicID::None || GetMissileSpriteData(missile._miAnimType).animFAmt < 8)\r\n\t\tmissile.setDefaultFrameGroup();\r\n\telse\r\n\t\tmissile.setDirection(midir);\r\n\r\n\tif (!lSFX) {\r\n\t\tlSFX = missileData.castSound;\r\n\t}\r\n\r\n\tif (*lSFX != SfxID::None) {\r\n\t\tPlaySfxLoc(*lSFX, missile.position.start);\r\n\t}\r\n\r\n\tAddMissileParameter parameter = { dst, midir, parent, false };\r\n\tmissileData.addFn(missile, parameter);\r\n\tif (parameter.spellFizzled) {\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\treturn &missile;\r\n}\r\n\r\nvoid ProcessElementalArrow(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile._miAnimType == MissileGraphicID::ChargedBolt || missile._miAnimType == MissileGraphicID::MagmaBallExplosion) {\r\n\t\tChangeLight(missile._mlid, missile.position.tile, missile._miAnimFrame + 5);\r\n\t} else {\r\n\t\tint mind;\r\n\t\tint maxd;\r\n\t\tconst int p = missile._misource;\r\n\t\tmissile._midist++;\r\n\t\tif (!missile.IsTrap()) {\r\n\t\t\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\t\t\t// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.\r\n\t\t\t\tconst Player &player = Players[p];\r\n\t\t\t\tmind = player._pIMinDam;\r\n\t\t\t\tmaxd = player._pIMaxDam;\r\n\t\t\t} else {\r\n\t\t\t\t// BUGFIX: damage of missile should be encoded in missile struct; monster can be dead before missile arrives.\r\n\t\t\t\tconst Monster &monster = Monsters[p];\r\n\t\t\t\tmind = monster.minDamage;\r\n\t\t\t\tmaxd = monster.maxDamage;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tmind = GenerateRnd(10) + 1 + currlevel;\r\n\t\t\tmaxd = GenerateRnd(10) + 1 + currlevel * 2;\r\n\t\t}\r\n\t\tMoveMissileAndCheckMissileCol(missile, DamageType::Physical, mind, maxd, true, false);\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile.setDefaultFrameGroup();\r\n\t\t\tmissile.duration = missile._miAnimLen - 1;\r\n\t\t\tmissile.position.StopMissile();\r\n\r\n\t\t\tint eMind;\r\n\t\t\tint eMaxd;\r\n\t\t\tMissileGraphicID eAnim;\r\n\t\t\tDamageType damageType;\r\n\t\t\tswitch (missile._mitype) {\r\n\t\t\tcase MissileID::LightningArrow:\r\n\t\t\t\tif (!missile.IsTrap()) {\r\n\t\t\t\t\t// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.\r\n\t\t\t\t\tconst Player &player = Players[p];\r\n\t\t\t\t\teMind = player._pILMinDam;\r\n\t\t\t\t\teMaxd = player._pILMaxDam;\r\n\t\t\t\t} else {\r\n\t\t\t\t\teMind = GenerateRnd(10) + 1 + currlevel;\r\n\t\t\t\t\teMaxd = GenerateRnd(10) + 1 + currlevel * 2;\r\n\t\t\t\t}\r\n\t\t\t\teAnim = MissileGraphicID::ChargedBolt;\r\n\t\t\t\tdamageType = DamageType::Lightning;\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissileID::FireArrow:\r\n\t\t\t\tif (!missile.IsTrap()) {\r\n\t\t\t\t\t// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.\r\n\t\t\t\t\tconst Player &player = Players[p];\r\n\t\t\t\t\teMind = player._pIFMinDam;\r\n\t\t\t\t\teMaxd = player._pIFMaxDam;\r\n\t\t\t\t} else {\r\n\t\t\t\t\teMind = GenerateRnd(10) + 1 + currlevel;\r\n\t\t\t\t\teMaxd = GenerateRnd(10) + 1 + currlevel * 2;\r\n\t\t\t\t}\r\n\t\t\t\teAnim = MissileGraphicID::MagmaBallExplosion;\r\n\t\t\t\tdamageType = DamageType::Fire;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tapp_fatal(StrCat(\"wrong missile ID \", static_cast<int>(missile._mitype)));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tmissile.setAnimation(eAnim);\r\n\t\t\tCheckMissileCol(missile, damageType, eMind, eMaxd, false, missile.position.tile, true);\r\n\t\t} else {\r\n\t\t\tif (missile.position.tile != Point { missile.var1, missile.var2 }) {\r\n\t\t\t\tmissile.var1 = missile.position.tile.x;\r\n\t\t\t\tmissile.var2 = missile.position.tile.y;\r\n\t\t\t\tChangeLight(missile._mlid, missile.position.tile, 5);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessArrow(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tmissile._midist++;\r\n\r\n\tint mind;\r\n\tint maxd;\r\n\tswitch (missile.sourceType()) {\r\n\tcase MissileSource::Player: {\r\n\t\t// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.\r\n\t\tconst Player &player = *missile.sourcePlayer();\r\n\t\tmind = player._pIMinDam;\r\n\t\tmaxd = player._pIMaxDam;\r\n\t} break;\r\n\tcase MissileSource::Monster: {\r\n\t\t// BUGFIX: damage of missile should be encoded in missile struct; monster can be dead before missile arrives.\r\n\t\tconst Monster &monster = *missile.sourceMonster();\r\n\t\tmind = monster.minDamage;\r\n\t\tmaxd = monster.maxDamage;\r\n\t} break;\r\n\tcase MissileSource::Trap:\r\n\t\tmind = currlevel;\r\n\t\tmaxd = 2 * currlevel;\r\n\t\tbreak;\r\n\t}\r\n\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), mind, maxd, true, false);\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessGenericProjectile(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\r\n\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, true);\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tconst Point dst = { 0, 0 };\r\n\t\tconst Direction dir = missile.getDirection();\r\n\t\tswitch (missile._mitype) {\r\n\t\tcase MissileID::Firebolt:\r\n\t\tcase MissileID::MagmaBall:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::MagmaBallExplosion, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileID::BloodStar:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::BloodStarExplosion, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileID::Acid:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::AcidSplat, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileID::OrangeFlare:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::OrangeExplosion, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileID::BlueFlare:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::BlueExplosion, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileID::RedFlare:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::RedExplosion, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileID::YellowFlare:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::YellowExplosion, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tcase MissileID::BlueFlare2:\r\n\t\t\tAddMissile(missile.position.tile, dst, dir, MissileID::BlueExplosion2, missile._micaster, missile._misource, 0, 0, &missile);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (missile._mlid != NO_LIGHT)\r\n\t\t\tAddUnLight(missile._mlid);\r\n\t\tPutMissile(missile);\r\n\t} else {\r\n\t\tif (missile.position.tile != Point { missile.var1, missile.var2 }) {\r\n\t\t\tmissile.var1 = missile.position.tile.x;\r\n\t\t\tmissile.var2 = missile.position.tile.y;\r\n\t\t\tif (missile._mlid != NO_LIGHT)\r\n\t\t\t\tChangeLight(missile._mlid, missile.position.tile, 8);\r\n\t\t}\r\n\t\tPutMissile(missile);\r\n\t}\r\n}\r\n\r\nvoid ProcessNovaBall(Missile &missile)\r\n{\r\n\tconst Point targetPosition = { missile.var1, missile.var2 };\r\n\tmissile.duration--;\r\n\tconst int j = missile.duration;\r\n\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, false, false);\r\n\tif (missile._miHitFlag)\r\n\t\tmissile.duration = j;\r\n\r\n\tif (missile.position.tile == targetPosition) {\r\n\t\tObject *object = FindObjectAtPosition(targetPosition);\r\n\t\tif (object != nullptr && object->IsShrine()) {\r\n\t\t\tmissile.duration = j;\r\n\t\t}\r\n\t}\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessAcidPuddle(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tconst int range = missile.duration;\r\n\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, missile.position.tile, false);\r\n\tmissile.duration = range;\r\n\tif (range == 0) {\r\n\t\tif (missile.getFrameGroup<AcidPuddleFrame>() != AcidPuddleFrame::Idle) {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t} else {\r\n\t\t\tmissile.setFrameGroup<AcidPuddleFrame>(AcidPuddleFrame::End);\r\n\t\t\tmissile.duration = missile._miAnimLen;\r\n\t\t}\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessFireWall(Missile &missile)\r\n{\r\n\tconstexpr int ExpLightLen = 12;\r\n\tconstexpr int ExpLight[ExpLightLen] = { 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12 };\r\n\r\n\tmissile.duration--;\r\n\tif (missile.duration == missile.var1) {\r\n\t\tmissile.setFrameGroup<FireWallFrame>(FireWallFrame::Idle);\r\n\t\tmissile._miAnimFrame = GenerateRnd(11) + 1;\r\n\t}\r\n\tif (missile.duration == missile._miAnimLen - 1) {\r\n\t\tmissile.setFrameGroup<FireWallFrame>(FireWallFrame::Start);\r\n\t\tmissile._miAnimFrame = 13;\r\n\t\tmissile._miAnimAdd = -1;\r\n\t}\r\n\tstd::optional<Direction> onlyHitWalking = {};\r\n\tif (missile.var3 != 0)\r\n\t\tonlyHitWalking = static_cast<Direction>(missile.var3 - 1);\r\n\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, missile.position.tile, true, onlyHitWalking);\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tconstexpr int MaxExpLightIndex = ExpLightLen - 1;\r\n\tif (missile.getFrameGroup<FireWallFrame>() == FireWallFrame::Start && missile.duration != 0 && missile.var2 <= MaxExpLightIndex * 2) {\r\n\t\tif (missile.var2 == 0)\r\n\t\t\tmissile._mlid = AddLight(missile.position.tile, ExpLight[0]);\r\n\t\tconst int expLightIndex = MaxExpLightIndex - std::abs(missile.var2 - MaxExpLightIndex);\r\n\t\tChangeLight(missile._mlid, missile.position.tile, ExpLight[expLightIndex]);\r\n\t\tmissile.var2++;\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessFireball(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\r\n\tif (missile._miAnimType == MissileGraphicID::BigExplosion) {\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t\tAddUnLight(missile._mlid);\r\n\t\t}\r\n\t} else {\r\n\t\tint minDam = missile._midam;\r\n\t\tint maxDam = missile._midam;\r\n\r\n\t\tif (missile._micaster != TARGET_MONSTERS) {\r\n\t\t\tconst Monster &monster = Monsters[missile._misource];\r\n\t\t\tminDam = monster.minDamage;\r\n\t\t\tmaxDam = monster.maxDamage;\r\n\t\t}\r\n\t\tconst DamageType damageType = GetMissileData(missile._mitype).damageType();\r\n\t\tMoveMissileAndCheckMissileCol(missile, damageType, minDam, maxDam, true, false);\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tconst Point missilePosition = missile.position.tile;\r\n\t\t\tChangeLight(missile._mlid, missile.position.tile, missile._miAnimFrame);\r\n\r\n\t\t\tconstexpr Direction Offsets[] = {\r\n\t\t\t\tDirection::NoDirection,\r\n\t\t\t\tDirection::SouthWest,\r\n\t\t\t\tDirection::NorthEast,\r\n\t\t\t\tDirection::SouthEast,\r\n\t\t\t\tDirection::East,\r\n\t\t\t\tDirection::South,\r\n\t\t\t\tDirection::NorthWest,\r\n\t\t\t\tDirection::West,\r\n\t\t\t\tDirection::North\r\n\t\t\t};\r\n\t\t\tfor (const Direction offset : Offsets) {\r\n\t\t\t\tif (!CheckBlock(missile.position.start, missilePosition + offset))\r\n\t\t\t\t\tCheckMissileCol(missile, damageType, minDam, maxDam, false, missilePosition + offset, true);\r\n\t\t\t}\r\n\r\n\t\t\tif (!TransList[dTransVal[missilePosition.x][missilePosition.y]]\r\n\t\t\t    || (missile.position.velocity.deltaX < 0 && ((TransList[dTransVal[missilePosition.x][missilePosition.y + 1]] && TileHasAny(missilePosition + Direction::SouthWest, TileProperties::Solid)) || (TransList[dTransVal[missilePosition.x][missilePosition.y - 1]] && TileHasAny(missilePosition + Direction::NorthEast, TileProperties::Solid))))) {\r\n\t\t\t\tmissile.position.tile += Direction::South;\r\n\t\t\t\tmissile.position.offset.deltaY -= 32;\r\n\t\t\t}\r\n\t\t\tif (missile.position.velocity.deltaY > 0\r\n\t\t\t    && ((TransList[dTransVal[missilePosition.x + 1][missilePosition.y]] && TileHasAny(missilePosition + Direction::SouthEast, TileProperties::Solid))\r\n\t\t\t        || (TransList[dTransVal[missilePosition.x - 1][missilePosition.y]] && TileHasAny(missilePosition + Direction::NorthWest, TileProperties::Solid)))) {\r\n\t\t\t\tmissile.position.offset.deltaY -= 32;\r\n\t\t\t}\r\n\t\t\tif (missile.position.velocity.deltaX > 0\r\n\t\t\t    && ((TransList[dTransVal[missilePosition.x][missilePosition.y + 1]] && TileHasAny(missilePosition + Direction::SouthWest, TileProperties::Solid))\r\n\t\t\t        || (TransList[dTransVal[missilePosition.x][missilePosition.y - 1]] && TileHasAny(missilePosition + Direction::NorthEast, TileProperties::Solid)))) {\r\n\t\t\t\tmissile.position.offset.deltaX -= 32;\r\n\t\t\t}\r\n\t\t\tmissile.setDefaultFrameGroup();\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BigExplosion);\r\n\t\t\tmissile.duration = missile._miAnimLen - 1;\r\n\t\t\tmissile.position.velocity = {};\r\n\t\t} else if (missile.position.tile != Point { missile.var1, missile.var2 }) {\r\n\t\t\tmissile.var1 = missile.position.tile.x;\r\n\t\t\tmissile.var2 = missile.position.tile.y;\r\n\t\t\tChangeLight(missile._mlid, missile.position.tile, 8);\r\n\t\t}\r\n\t}\r\n\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessHorkSpawn(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), 0, 0, false, missile.position.tile, false);\r\n\tif (missile.duration <= 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\r\n\t\tstd::optional<Point> spawnPosition = FindClosestValidPosition(\r\n\t\t    [](Point target) {\r\n\t\t\t    return !IsTileOccupied(target);\r\n\t\t    },\r\n\t\t    missile.position.tile, 0, 1);\r\n\r\n\t\tif (spawnPosition) {\r\n\t\t\tauto facing = static_cast<Direction>(missile.var1);\r\n\t\t\tSpawnMonster(*spawnPosition, facing, 1);\r\n\t\t}\r\n\t} else {\r\n\t\tmissile._midist++;\r\n\t\tmissile.position.traveled += missile.position.velocity;\r\n\t\tUpdateMissilePos(missile);\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessRune(Missile &missile)\r\n{\r\n\tconst Point position = missile.position.tile;\r\n\tconst int mid = dMonster[position.x][position.y];\r\n\tPlayer *player = PlayerAtPosition(position);\r\n\tif (mid != 0 || player != nullptr) {\r\n\t\tconst Point targetPosition = mid != 0 ? Monsters[std::abs(mid) - 1].position.tile : player->position.tile;\r\n\t\tconst Direction dir = GetDirection(position, targetPosition);\r\n\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\r\n\t\tAddMissile(position, position, dir, static_cast<MissileID>(missile.var1), TARGET_BOTH, missile._misource, missile._midam, missile._mispllvl);\r\n\t}\r\n\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessLightningWall(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tconst int range = missile.duration;\r\n\tstd::optional<Direction> onlyHitWalking = {};\r\n\tif (missile.var3 != 0)\r\n\t\tonlyHitWalking = static_cast<Direction>(missile.var3 - 1);\r\n\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, missile.position.tile, false, onlyHitWalking);\r\n\tif (missile._miHitFlag)\r\n\t\tmissile.duration = range;\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessBigExplosion(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile.duration <= 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessLightningBow(Missile &missile)\r\n{\r\n\tSpawnLightning(missile, missile._midam);\r\n}\r\n\r\nvoid ProcessRingOfFire(Missile &missile)\r\n{\r\n\tmissile._miDelFlag = true;\r\n\tint8_t src = missile._misource;\r\n\tconst uint8_t lvl = missile._micaster == TARGET_MONSTERS ? Players[src].getCharacterLevel() : currlevel;\r\n\tint dmg = 16 * (GenerateRndSum(10, 2) + lvl + 2) / 2;\r\n\r\n\tif (missile.limitReached)\r\n\t\treturn;\r\n\r\n\tCrawl(3, [&](Displacement displacement) {\r\n\t\tconst Point target = Point { missile.var1, missile.var2 } + displacement;\r\n\t\tif (!InDungeonBounds(target))\r\n\t\t\treturn false;\r\n\t\tif (TileHasAny(target, TileProperties::Solid))\r\n\t\t\treturn false;\r\n\t\tif (IsObjectAtPosition(target))\r\n\t\t\treturn false;\r\n\t\tif (!LineClearMissile(missile.position.tile, target))\r\n\t\t\treturn false;\r\n\t\tif (TileHasAny(target, TileProperties::BlockMissile)) {\r\n\t\t\tmissile.limitReached = true;\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tAddMissile(target, target, Direction::South, MissileID::FireWall, TARGET_BOTH, src, dmg, missile._mispllvl);\r\n\t\treturn false;\r\n\t});\r\n}\r\n\r\nvoid ProcessSearch(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile.duration != 0)\r\n\t\treturn;\r\n\r\n\tconst Player &player = Players[missile._misource];\r\n\r\n\tmissile._miDelFlag = true;\r\n\tPlaySfxLoc(SfxID::SpellEnd, player.position.tile);\r\n\tif (&player == MyPlayer)\r\n\t\tAutoMapShowItems = false;\r\n}\r\n\r\nvoid ProcessNovaCommon(Missile &missile, MissileID projectileType)\r\n{\r\n\tconst int id = missile._misource;\r\n\tconst int dam = missile._midam;\r\n\tconst Point src = missile.position.tile;\r\n\tDirection dir = Direction::South;\r\n\tmienemy_type en = TARGET_PLAYERS;\r\n\tif (!missile.IsTrap()) {\r\n\t\tdir = Players[id]._pdir;\r\n\t\ten = TARGET_MONSTERS;\r\n\t}\r\n\r\n\tconstexpr std::array<WorldTileDisplacement, 9> quarterRadius = { { { 4, 0 }, { 4, 1 }, { 4, 2 }, { 4, 3 }, { 4, 4 }, { 3, 4 }, { 2, 4 }, { 1, 4 }, { 0, 4 } } };\r\n\tfor (const WorldTileDisplacement quarterOffset : quarterRadius) {\r\n\t\t// This ends up with two missiles targeting offsets 4,0, 0,4, -4,0, 0,-4.\r\n\t\tconst std::array<WorldTileDisplacement, 4> offsets { quarterOffset, quarterOffset.flipXY(), quarterOffset.flipX(), quarterOffset.flipY() };\r\n\t\tfor (const WorldTileDisplacement offset : offsets)\r\n\t\t\tAddMissile(src, src + offset, dir, projectileType, en, id, dam, missile._mispllvl);\r\n\t}\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid ProcessImmolation(Missile &missile)\r\n{\r\n\tProcessNovaCommon(missile, MissileID::FireballBow);\r\n}\r\n\r\nvoid ProcessNova(Missile &missile)\r\n{\r\n\tProcessNovaCommon(missile, MissileID::NovaBall);\r\n}\r\n\r\nvoid ProcessSpectralArrow(Missile &missile)\r\n{\r\n\tconst int id = missile._misource;\r\n\tconst int dam = missile._midam;\r\n\tconst Point src = missile.position.tile;\r\n\tconst Point dst = { missile.var1, missile.var2 };\r\n\tconst int spllvl = missile.var3;\r\n\tMissileID mitype = MissileID::Arrow;\r\n\tDirection dir = Direction::South;\r\n\tmienemy_type micaster = TARGET_PLAYERS;\r\n\tif (!missile.IsTrap()) {\r\n\t\tconst Player &player = Players[id];\r\n\t\tdir = player._pdir;\r\n\t\tmicaster = TARGET_MONSTERS;\r\n\r\n\t\tswitch (player._pILMinDam) {\r\n\t\tcase 0:\r\n\t\t\tmitype = MissileID::FireballBow;\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tmitype = MissileID::LightningBow;\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tmitype = MissileID::ChargedBoltBow;\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tmitype = MissileID::HolyBoltBow;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tAddMissile(src, dst, dir, mitype, micaster, id, dam, spllvl);\r\n\tif (mitype == MissileID::ChargedBoltBow) {\r\n\t\tAddMissile(src, dst, dir, mitype, micaster, id, dam, spllvl);\r\n\t\tAddMissile(src, dst, dir, mitype, micaster, id, dam, spllvl);\r\n\t}\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid ProcessLightningControl(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\r\n\tint dam;\r\n\tif (missile.IsTrap()) {\r\n\t\t// BUGFIX: damage of missile should be encoded in missile struct; monster can be dead before missile arrives.\r\n\t\tdam = GenerateRnd(currlevel) + 2 * currlevel;\r\n\t} else if (missile._micaster == TARGET_MONSTERS) {\r\n\t\t// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.\r\n\t\tdam = (GenerateRnd(2) + GenerateRnd(Players[missile._misource].getCharacterLevel()) + 2) << 6;\r\n\t} else {\r\n\t\tconst Monster &monster = Monsters[missile._misource];\r\n\t\tdam = 2 * RandomIntBetween(monster.minDamage, monster.maxDamage);\r\n\t}\r\n\r\n\tSpawnLightning(missile, dam);\r\n}\r\n\r\nvoid ProcessLightning(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tconst int j = missile.duration;\r\n\tif (missile.position.tile != missile.position.start)\r\n\t\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, missile.position.tile, false);\r\n\tif (missile._miHitFlag)\r\n\t\tmissile.duration = j;\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessTownPortal(Missile &missile)\r\n{\r\n\tconst int expLight[17] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15 };\r\n\r\n\tif (missile.duration > 1)\r\n\t\tmissile.duration--;\r\n\tif (missile.duration == missile.var1)\r\n\t\tmissile.setFrameGroup<PortalFrame>(PortalFrame::Idle);\r\n\tif (leveltype != DTYPE_TOWN && missile.getFrameGroup<PortalFrame>() != PortalFrame::Idle && missile.duration != 0) {\r\n\t\tif (missile.var2 == 0)\r\n\t\t\tmissile._mlid = AddLight(missile.position.tile, 1);\r\n\t\tChangeLight(missile._mlid, missile.position.tile, expLight[missile.var2]);\r\n\t\tmissile.var2++;\r\n\t}\r\n\r\n\tfor (Player &player : Players) {\r\n\t\tif (player.plractive && player.isOnActiveLevel() && !player._pLvlChanging && player._pmode == PM_STAND && player.position.tile == missile.position.tile) {\r\n\t\t\tClrPlrPath(player);\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tNetSendCmdParam1(true, CMD_WARP, missile._misource);\r\n\t\t\t\tplayer._pmode = PM_NEWLVL;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessFlashBottom(Missile &missile)\r\n{\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tif (!missile.IsTrap())\r\n\t\t\tPlayers[missile._misource]._pInvincible = true;\r\n\t}\r\n\tmissile.duration--;\r\n\r\n\tconstexpr Direction Offsets[] = {\r\n\t\tDirection::NorthWest,\r\n\t\tDirection::NoDirection,\r\n\t\tDirection::SouthEast,\r\n\t\tDirection::West,\r\n\t\tDirection::SouthWest,\r\n\t\tDirection::South\r\n\t};\r\n\tfor (const Direction offset : Offsets)\r\n\t\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, missile.position.tile + offset, true);\r\n\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\t\tif (!missile.IsTrap())\r\n\t\t\t\tPlayers[missile._misource]._pInvincible = false;\r\n\t\t}\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessFlashTop(Missile &missile)\r\n{\r\n\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\tif (!missile.IsTrap())\r\n\t\t\tPlayers[missile._misource]._pInvincible = true;\r\n\t}\r\n\tmissile.duration--;\r\n\r\n\tconstexpr Direction Offsets[] = {\r\n\t\tDirection::North,\r\n\t\tDirection::NorthEast,\r\n\t\tDirection::East\r\n\t};\r\n\tfor (const Direction offset : Offsets)\r\n\t\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, missile.position.tile + offset, true);\r\n\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tif (missile._micaster == TARGET_MONSTERS) {\r\n\t\t\tif (!missile.IsTrap())\r\n\t\t\t\tPlayers[missile._misource]._pInvincible = false;\r\n\t\t}\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessFlameWave(Missile &missile)\r\n{\r\n\tconstexpr int ExpLightLen = 12;\r\n\tconstexpr int ExpLight[ExpLightLen] = { 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12 };\r\n\r\n\t// Adjust missile's position for processing\r\n\tmissile.position.tile += Direction::North;\r\n\tmissile.position.offset.deltaY += 32;\r\n\r\n\tmissile.var1++;\r\n\tif (missile.var1 == missile._miAnimLen) {\r\n\t\tmissile.setFrameGroup<FireWallFrame>(FireWallFrame::Idle);\r\n\t\tmissile._miAnimFrame = GenerateRnd(11) + 1;\r\n\t}\r\n\tconst int j = missile.duration;\r\n\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, false, false);\r\n\tif (missile._miHitFlag)\r\n\t\tmissile.duration = j;\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t} else {\r\n\t\tif (missile.var2 == 0)\r\n\t\t\tmissile._mlid = AddLight(missile.position.tile, ExpLight[0]);\r\n\t\tChangeLight(missile._mlid, missile.position.tile, ExpLight[missile.var2]);\r\n\t\tif (missile.var2 < ExpLightLen - 1)\r\n\t\t\tmissile.var2++;\r\n\t}\r\n\t// Adjust missile's position for rendering\r\n\tmissile.position.tile += Direction::South;\r\n\tmissile.position.offset.deltaY -= 32;\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessGuardian(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\r\n\tif (missile.var2 > 0) {\r\n\t\tmissile.var2--;\r\n\t}\r\n\tif (missile.duration == missile.var1 || (missile.getFrameGroup<GuardianFrame>() == GuardianFrame::Attack && missile.var2 == 0)) {\r\n\t\tmissile.setFrameGroup<GuardianFrame>(GuardianFrame::Idle);\r\n\t}\r\n\r\n\tconst Point position = missile.position.tile;\r\n\r\n\tif ((missile.duration % 16) == 0) {\r\n\t\t// Guardians pick a target by working backwards along lines originally based on VisionCrawlTable.\r\n\t\t// Because of their rather unique behaviour the points checked have been unrolled here\r\n\t\tconstexpr std::array<WorldTileDisplacement, 48> guardianArc {\r\n\t\t\t{\r\n\t\t\t    // clang-format off\r\n\t\t\t    { 6, 0 }, { 5, 0 }, { 4, 0 }, { 3, 0 }, { 2, 0 }, { 1, 0 },\r\n\t\t\t    { 6, 1 }, { 5, 1 }, { 4, 1 }, { 3, 1 },\r\n\t\t\t    { 6, 2 }, { 2, 1 },\r\n\t\t\t    { 5, 2 },\r\n\t\t\t    { 6, 3 }, { 4, 2 },\r\n\t\t\t    { 5, 3 }, { 3, 2 }, { 1, 1 },\r\n\t\t\t    { 6, 4 },\r\n\t\t\t    { 6, 5 }, { 5, 4 }, { 4, 3 }, { 2, 2 },\r\n\t\t\t    { 5, 5 }, { 4, 4 }, { 3, 3 },\r\n\t\t\t    { 6, 6 }, { 5, 6 }, { 4, 5 }, { 3, 4 }, { 2, 3 },\r\n\t\t\t    { 4, 6 }, { 3, 5 }, { 2, 4 }, { 1, 2 },\r\n\t\t\t    { 3, 6 }, { 2, 5 }, { 1, 3 }, { 0, 1 },\r\n\t\t\t    { 2, 6 }, { 1, 4 },\r\n\t\t\t    { 1, 5 },\r\n\t\t\t    { 1, 6 },\r\n\t\t\t    { 0, 2 },\r\n\t\t\t    { 0, 3 },\r\n\t\t\t    { 0, 6 }, { 0, 5 }, { 0, 4 },\r\n\t\t\t    // clang-format on\r\n\t\t\t}\r\n\t\t};\r\n\t\tfor (const WorldTileDisplacement offset : guardianArc) {\r\n\t\t\tif (GuardianTryFireAt(missile, position + offset)\r\n\t\t\t    || GuardianTryFireAt(missile, position + offset.flipXY())\r\n\t\t\t    || GuardianTryFireAt(missile, position + offset.flipY())\r\n\t\t\t    || GuardianTryFireAt(missile, position + offset.flipX()))\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (missile.duration == 14) {\r\n\t\tmissile.setFrameGroup<GuardianFrame>(GuardianFrame::Start);\r\n\t\tmissile._miAnimFrame = 15;\r\n\t\tmissile._miAnimAdd = -1;\r\n\t}\r\n\r\n\tmissile.var3 += missile._miAnimAdd;\r\n\r\n\tif (missile.var3 > 15) {\r\n\t\tmissile.var3 = 15;\r\n\t} else if (missile.var3 > 0) {\r\n\t\tChangeLight(missile._mlid, position, missile.var3);\r\n\t}\r\n\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessChainLightning(Missile &missile)\r\n{\r\n\tint id = missile._misource;\r\n\tPoint position = missile.position.tile;\r\n\tconst Point dst { missile.var1, missile.var2 };\r\n\tDirection dir = GetDirection(position, dst);\r\n\tAddMissile(position, dst, dir, MissileID::LightningControl, TARGET_MONSTERS, id, 1, missile._mispllvl);\r\n\tconst int rad = std::min<int>(missile._mispllvl + 3, MaxCrawlRadius);\r\n\tCrawl(1, rad, [&](Displacement displacement) {\r\n\t\tconst Point target = position + displacement;\r\n\t\tif (InDungeonBounds(target) && dMonster[target.x][target.y] > 0) {\r\n\t\t\tdir = GetDirection(position, target);\r\n\t\t\tAddMissile(position, target, dir, MissileID::LightningControl, TARGET_MONSTERS, id, 1, missile._mispllvl);\r\n\t\t}\r\n\t\treturn false;\r\n\t});\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid ProcessWeaponExplosion(Missile &missile)\r\n{\r\n\tconstexpr int ExpLight[10] = { 9, 10, 11, 12, 11, 10, 8, 6, 4, 2 };\r\n\r\n\tmissile.duration--;\r\n\tconst Player &player = Players[missile._misource];\r\n\tint mind;\r\n\tint maxd;\r\n\tDamageType damageType;\r\n\tif (missile.var2 == 1) {\r\n\t\t// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.\r\n\t\tmind = player._pIFMinDam;\r\n\t\tmaxd = player._pIFMaxDam;\r\n\t\tdamageType = DamageType::Fire;\r\n\t} else {\r\n\t\t// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.\r\n\t\tmind = player._pILMinDam;\r\n\t\tmaxd = player._pILMaxDam;\r\n\t\tdamageType = DamageType::Lightning;\r\n\t}\r\n\tCheckMissileCol(missile, damageType, mind, maxd, false, missile.position.tile, false);\r\n\tif (missile.var1 == 0) {\r\n\t\tmissile._mlid = AddLight(missile.position.tile, 9);\r\n\t} else {\r\n\t\tif (missile.duration != 0)\r\n\t\t\tChangeLight(missile._mlid, missile.position.tile, ExpLight[missile.var1]);\r\n\t}\r\n\tmissile.var1++;\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t} else {\r\n\t\tPutMissile(missile);\r\n\t}\r\n}\r\n\r\nvoid ProcessMissileExplosion(Missile &missile)\r\n{\r\n\tconstexpr int ExpLight[] = { 9, 10, 11, 12, 11, 10, 8, 6, 4, 2, 1, 0, 0, 0, 0 };\r\n\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t} else {\r\n\t\tif (missile.var1 == 0)\r\n\t\t\tmissile._mlid = AddLight(missile.position.tile, 9);\r\n\t\telse\r\n\t\t\tChangeLight(missile._mlid, missile.position.tile, ExpLight[missile.var1]);\r\n\t\tmissile.var1++;\r\n\t\tPutMissile(missile);\r\n\t}\r\n}\r\n\r\nvoid ProcessAcidSplate(Missile &missile)\r\n{\r\n\tif (missile.duration == missile._miAnimLen) {\r\n\t\tmissile.position.tile += Displacement { 1, 1 };\r\n\t\tmissile.position.offset.deltaY -= 32;\r\n\t}\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tconst int monst = missile._misource;\r\n\t\tconst int dam = (Monsters[monst].data().level >= 2 ? 2 : 1);\r\n\t\tAddMissile(missile.position.tile, { 0, 0 }, Direction::South, MissileID::AcidPuddle, TARGET_PLAYERS, monst, dam, missile._mispllvl);\r\n\t} else {\r\n\t\tPutMissile(missile);\r\n\t}\r\n}\r\n\r\nvoid ProcessTeleport(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile.duration <= 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int id = missile._misource;\r\n\tPlayer &player = Players[id];\r\n\r\n\tstd::optional<Point> teleportDestination = FindClosestValidPosition(\r\n\t    [&player](Point target) {\r\n\t\t    return PosOkPlayer(player, target);\r\n\t    },\r\n\t    missile.position.tile, 0, 5);\r\n\r\n\tif (!teleportDestination)\r\n\t\treturn;\r\n\r\n\tdPlayer[player.position.tile.x][player.position.tile.y] = 0;\r\n\tPlrClrTrans(player.position.tile);\r\n\tplayer.position.tile = *teleportDestination;\r\n\tplayer.position.future = player.position.tile;\r\n\tplayer.position.old = player.position.tile;\r\n\tPlrDoTrans(player.position.tile);\r\n\tmissile.var1 = 1;\r\n\tplayer.occupyTile(player.position.tile, false);\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tChangeLightXY(player.lightId, player.position.tile);\r\n\t\tChangeVisionXY(player.getId(), player.position.tile);\r\n\t}\r\n\tif (&player == MyPlayer) {\r\n\t\tViewPosition = player.position.tile;\r\n\t}\r\n}\r\n\r\nvoid ProcessStoneCurse(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tMonster &monster = Monsters[missile.var2];\r\n\tif (monster.hitPoints == 0 && missile._miAnimType != MissileGraphicID::StoneCurseShatter) {\r\n\t\tmissile.setDefaultFrameGroup();\r\n\t\tmissile._miDrawFlag = true;\r\n\t\tmissile.setAnimation(MissileGraphicID::StoneCurseShatter);\r\n\t\tmissile.duration = 11;\r\n\t}\r\n\tif (monster.mode != MonsterMode::Petrified) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tif (monster.hitPoints > 0) {\r\n\t\t\tmonster.mode = static_cast<MonsterMode>(missile.var1);\r\n\t\t\tmonster.animInfo.isPetrified = false;\r\n\t\t} else {\r\n\t\t\tAddCorpse(monster.position.tile, stonendx, monster.direction);\r\n\t\t}\r\n\t}\r\n\tif (missile._miAnimType == MissileGraphicID::StoneCurseShatter)\r\n\t\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessApocalypseBoom(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile.var1 == 0)\r\n\t\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, false, missile.position.tile, true);\r\n\tif (missile._miHitFlag)\r\n\t\tmissile.var1 = 1;\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessRhino(Missile &missile)\r\n{\r\n\tconst int monst = missile._misource;\r\n\tMonster &monster = Monsters[monst];\r\n\tif (monster.mode != MonsterMode::Charge) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\treturn;\r\n\t}\r\n\tUpdateMissilePos(missile);\r\n\tconst Point prevPos = missile.position.tile;\r\n\tPoint newPosSnake;\r\n\tdMonster[prevPos.x][prevPos.y] = 0;\r\n\tif (monster.ai == MonsterAIID::Snake) {\r\n\t\tmissile.position.traveled += missile.position.velocity * 2;\r\n\t\tUpdateMissilePos(missile);\r\n\t\tnewPosSnake = missile.position.tile;\r\n\t\tmissile.position.traveled -= missile.position.velocity;\r\n\t} else {\r\n\t\tmissile.position.traveled += missile.position.velocity;\r\n\t}\r\n\tUpdateMissilePos(missile);\r\n\tconst Point newPos = missile.position.tile;\r\n\tif (!IsTileAvailable(monster, newPos) || (monster.ai == MonsterAIID::Snake && (!IsTileAvailable(monster, newPosSnake) || missile._miAnimFrame >= missile._miAnimLen))) {\r\n\t\tMissToMonst(missile, prevPos);\r\n\t\tmissile._miDelFlag = true;\r\n\t\treturn;\r\n\t}\r\n\tmonster.position.future = newPos;\r\n\tmonster.position.old = newPos;\r\n\tmonster.position.tile = newPos;\r\n\tmonster.occupyTile(newPos, true);\r\n\tif (monster.isUnique())\r\n\t\tChangeLightXY(missile._mlid, newPos);\r\n\tMoveMissilePos(missile);\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessWallControl(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tMissileID type;\r\n\tconst int sourceIdx = missile._misource;\r\n\tint lvl = 0;\r\n\tint dmg = 0;\r\n\r\n\tswitch (missile._mitype) {\r\n\tcase MissileID::FireWallControl:\r\n\t\ttype = MissileID::FireWall;\r\n\t\tbreak;\r\n\tcase MissileID::LightningWallControl:\r\n\t\ttype = MissileID::LightningWall;\r\n\t\tlvl = !missile.IsTrap() ? Players[sourceIdx].getCharacterLevel() : 0;\r\n\t\tdmg = 16 * (GenerateRndSum(10, 2) + lvl + 2);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"ProcessWallControl: Invalid missile type for control missile\");\r\n\t}\r\n\r\n\tconst Point leftPosition = { missile.var1, missile.var2 };\r\n\tconst Point rightPosition = { missile.var5, missile.var6 };\r\n\tconst Direction leftDirection = static_cast<Direction>(missile.var3);\r\n\tconst Direction rightDirection = static_cast<Direction>(missile.var4);\r\n\r\n\tbool isStart = leftPosition == rightPosition;\r\n\r\n\tstd::optional<Point> nextLeftPosition = std::nullopt;\r\n\tstd::optional<Point> nextRightPosition = std::nullopt;\r\n\r\n\tif (isStart) {\r\n\t\tif (!CanPlaceWall(leftPosition)) {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tPlaceWall(missile._misource, type, leftPosition, leftDirection, missile._mispllvl, dmg);\r\n\t\tnextLeftPosition = MoveWallToNextPosition(leftPosition, leftDirection);\r\n\t\tnextRightPosition = MoveWallToNextPosition(rightPosition, rightDirection);\r\n\t} else {\r\n\t\tif (!missile.limitReached && TryGrowWall(missile._misource, type, leftPosition, leftDirection, Direction::South, missile._mispllvl, dmg)) {\r\n\t\t\tnextLeftPosition = MoveWallToNextPosition(leftPosition, leftDirection);\r\n\t\t}\r\n\t\tif (missile.var7 == 0 && TryGrowWall(missile._misource, type, rightPosition, rightDirection, Direction::South, missile._mispllvl, dmg)) {\r\n\t\t\tnextRightPosition = MoveWallToNextPosition(rightPosition, rightDirection);\r\n\t\t}\r\n\t}\r\n\r\n\tif (nextLeftPosition) {\r\n\t\tmissile.var1 = nextLeftPosition->x;\r\n\t\tmissile.var2 = nextLeftPosition->y;\r\n\t} else {\r\n\t\tmissile.limitReached = true;\r\n\t}\r\n\tif (nextRightPosition) {\r\n\t\tmissile.var5 = nextRightPosition->x;\r\n\t\tmissile.var6 = nextRightPosition->y;\r\n\t} else {\r\n\t\tmissile.var7 = 1;\r\n\t}\r\n}\r\n\r\nvoid ProcessInfravision(Missile &missile)\r\n{\r\n\tPlayer &player = Players[missile._misource];\r\n\tmissile.duration--;\r\n\tplayer._pInfraFlag = true;\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tCalcPlrItemVals(player, true);\r\n\t}\r\n}\r\n\r\nvoid ProcessApocalypse(Missile &missile)\r\n{\r\n\tfor (int j = missile.var2; j < missile.var3; j++) {\r\n\t\tfor (int k = missile.var4; k < missile.var5; k++) {\r\n\t\t\tconst int mid = dMonster[k][j] - 1;\r\n\t\t\tif (mid < 0)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (Monsters[mid].isPlayerMinion())\r\n\t\t\t\tcontinue;\r\n\t\t\tif (TileHasAny(PointOf { k, j }, TileProperties::Solid))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (gbIsHellfire && !LineClearMissile(missile.position.tile, { k, j }))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst int id = missile._misource;\r\n\t\t\tAddMissile(WorldTilePosition(k, j), WorldTilePosition(k, j), Players[id]._pdir, MissileID::ApocalypseBoom, TARGET_MONSTERS, id, missile._midam, 0);\r\n\t\t\tmissile.var2 = j;\r\n\t\t\tmissile.var4 = k + 1;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tmissile.var4 = missile.var6;\r\n\t}\r\n\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid ProcessFlameWaveControl(Missile &missile)\r\n{\r\n\tconst int id = missile._misource;\r\n\tconst Direction pdir = Players[id]._pdir;\r\n\tconst Point src = missile.position.tile;\r\n\tconst Direction sd = GetDirection(src, { missile.var1, missile.var2 });\r\n\tconst Point start = src + sd;\r\n\tif (CanPlaceWall(start)) {\r\n\t\tPlaceWall(id, MissileID::FlameWave, start, pdir, missile._mispllvl, 0);\r\n\t\tint segmentsToAdd = (missile._mispllvl / 2) + 2;\r\n\t\tPoint left = start;\r\n\t\tconst Direction dirLeft = Left(Left(sd));\r\n\t\tfor (int j = 0; j < segmentsToAdd; j++) {\r\n\t\t\tleft += dirLeft;\r\n\t\t\tif (!TryGrowWall(id, MissileID::FlameWave, left, dirLeft, pdir, missile._mispllvl, 0))\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tPoint right = start;\r\n\t\tconst Direction dirRight = Right(Right(sd));\r\n\t\tfor (int j = 0; j < segmentsToAdd; j++) {\r\n\t\t\tright += dirRight;\r\n\t\t\tif (!TryGrowWall(id, MissileID::FlameWave, right, dirRight, pdir, missile._mispllvl, 0))\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid ProcessRage(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\r\n\tif (missile.duration != 0)\r\n\t\treturn;\r\n\r\n\tPlayer &player = Players[missile._misource];\r\n\r\n\tif (HasAnyOf(player._pSpellFlags, SpellFlag::RageActive)) {\r\n\t\tplayer._pSpellFlags &= ~SpellFlag::RageActive;\r\n\t\tplayer._pSpellFlags |= SpellFlag::RageCooldown;\r\n\t\tmissile.duration = missile.var1; // Start timer over\r\n\t} else if (HasAnyOf(player._pSpellFlags, SpellFlag::RageCooldown)) {\r\n\t\tplayer._pSpellFlags &= ~SpellFlag::RageCooldown;\r\n\t\tmissile._miDelFlag = true;\r\n\t}\r\n\r\n\tCalcPlrItemVals(player, true);\r\n\r\n\t// Prevent the player from dying as a result of recalculating their current life\r\n\tif (player.hasNoLife())\r\n\t\tSetPlayerHitPoints(player, 64);\r\n\r\n\tRedrawEverything();\r\n\tplayer.Say(HeroSpeech::HeavyBreathing);\r\n\r\n\tif (missile._miDelFlag)\r\n\t\tApplyPlrDamage(DamageType::Physical, player, missile._midam, 1); // Prevent penalty from killing the player\r\n}\r\n\r\nvoid ProcessInferno(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tmissile.var2--;\r\n\tint k = missile.duration;\r\n\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, true, missile.position.tile, false);\r\n\tif (missile.duration == 0 && missile._miHitFlag)\r\n\t\tmissile.duration = k;\r\n\tif (missile.var2 == 0)\r\n\t\tmissile._miAnimFrame = 20;\r\n\tif (missile.var2 <= 0) {\r\n\t\tk = missile._miAnimFrame;\r\n\t\tif (k > 11)\r\n\t\t\tk = 24 - k;\r\n\t\tChangeLight(missile._mlid, missile.position.tile, k);\r\n\t}\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tif (missile.var2 <= 0)\r\n\t\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessInfernoControl(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tmissile.position.traveled += missile.position.velocity;\r\n\tUpdateMissilePos(missile);\r\n\tif (missile.position.tile != Point { missile.var1, missile.var2 }) {\r\n\t\tif (!TileHasAny(missile.position.tile, TileProperties::BlockMissile)) {\r\n\t\t\tAddMissile(\r\n\t\t\t    missile.position.tile,\r\n\t\t\t    missile.position.start,\r\n\t\t\t    Direction::South,\r\n\t\t\t    MissileID::Inferno,\r\n\t\t\t    missile._micaster,\r\n\t\t\t    missile._misource,\r\n\t\t\t    missile.var3,\r\n\t\t\t    missile._mispllvl,\r\n\t\t\t    &missile);\r\n\t\t} else {\r\n\t\t\tmissile.duration = 0;\r\n\t\t}\r\n\t\tmissile.var1 = missile.position.tile.x;\r\n\t\tmissile.var2 = missile.position.tile.y;\r\n\t\tmissile.var3++;\r\n\t}\r\n\tif (missile.duration == 0 || missile.var3 == 3)\r\n\t\tmissile._miDelFlag = true;\r\n}\r\n\r\nvoid ProcessChargedBolt(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile._miAnimType != MissileGraphicID::Lightning) {\r\n\t\tif (missile.var3 == 0) {\r\n\t\t\tconstexpr int BPath[16] = { -1, 0, 1, -1, 0, 1, -1, -1, 0, 0, 1, 1, 0, 1, -1, 0 };\r\n\r\n\t\t\tauto md = static_cast<Direction>(missile.var2);\r\n\t\t\tswitch (BPath[missile._mirnd]) {\r\n\t\t\tcase -1:\r\n\t\t\t\tmd = Left(md);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tmd = Right(md);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tmissile._mirnd = (missile._mirnd + 1) & 0xF;\r\n\t\t\tUpdateMissileVelocity(missile, missile.position.tile + md, 8);\r\n\t\t\tmissile.var3 = 16;\r\n\t\t} else {\r\n\t\t\tmissile.var3--;\r\n\t\t}\r\n\t\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), missile._midam, missile._midam, false, false);\r\n\t\tif (missile._miHitFlag) {\r\n\t\t\tmissile.var1 = 8;\r\n\t\t\tmissile.setDefaultFrameGroup();\r\n\t\t\tmissile.position.offset = { 0, 0 };\r\n\t\t\tmissile.position.velocity = {};\r\n\t\t\tmissile.setAnimation(MissileGraphicID::Lightning);\r\n\t\t\tmissile.duration = missile._miAnimLen;\r\n\t\t}\r\n\t\tChangeLight(missile._mlid, missile.position.tile, missile.var1);\r\n\t}\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessHolyBolt(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile._miAnimType != MissileGraphicID::HolyBoltExplosion) {\r\n\t\tconst int dam = missile._midam;\r\n\t\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), dam, dam, true, true);\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile.setDefaultFrameGroup();\r\n\t\t\tmissile.setAnimation(MissileGraphicID::HolyBoltExplosion);\r\n\t\t\tmissile.duration = missile._miAnimLen - 1;\r\n\t\t\tmissile.position.StopMissile();\r\n\t\t} else {\r\n\t\t\tif (missile.position.tile != Point { missile.var1, missile.var2 }) {\r\n\t\t\t\tmissile.var1 = missile.position.tile.x;\r\n\t\t\t\tmissile.var2 = missile.position.tile.y;\r\n\t\t\t\tChangeLight(missile._mlid, missile.position.tile, 8);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tChangeLight(missile._mlid, missile.position.tile, missile._miAnimFrame + 7);\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t\tAddUnLight(missile._mlid);\r\n\t\t}\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessElemental(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tconst int dam = missile._midam;\r\n\tconst Point missilePosition = missile.position.tile;\r\n\tif (missile._miAnimType == MissileGraphicID::BigExplosion) {\r\n\t\tChangeLight(missile._mlid, missile.position.tile, missile._miAnimFrame);\r\n\r\n\t\tconst Point startPoint = missile.var3 == 2 ? Point { missile.var4, missile.var5 } : Point(missile.position.start);\r\n\t\tconstexpr Direction Offsets[] = {\r\n\t\t\tDirection::NoDirection,\r\n\t\t\tDirection::SouthWest,\r\n\t\t\tDirection::NorthEast,\r\n\t\t\tDirection::SouthEast,\r\n\t\t\tDirection::East,\r\n\t\t\tDirection::South,\r\n\t\t\tDirection::NorthWest,\r\n\t\t\tDirection::West,\r\n\t\t\tDirection::North\r\n\t\t};\r\n\t\tfor (const Direction offset : Offsets) {\r\n\t\t\tif (!CheckBlock(startPoint, missilePosition + offset))\r\n\t\t\t\tCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), dam, dam, true, missilePosition + offset, true);\r\n\t\t}\r\n\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t\tAddUnLight(missile._mlid);\r\n\t\t}\r\n\t} else {\r\n\t\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), dam, dam, false, false);\r\n\t\tif (missile.var3 == 0 && missilePosition == Point { missile.var4, missile.var5 })\r\n\t\t\tmissile.var3 = 1;\r\n\t\tif (missile.var3 == 1) {\r\n\t\t\tmissile.var3 = 2;\r\n\t\t\tmissile.duration = 255;\r\n\t\t\tauto *nextMonster = FindClosest(missilePosition, 19);\r\n\t\t\tif (nextMonster != nullptr) {\r\n\t\t\t\tconst Direction sd = GetDirection(missilePosition, nextMonster->position.tile);\r\n\t\t\t\tmissile.setDirection(sd);\r\n\t\t\t\tUpdateMissileVelocity(missile, nextMonster->position.tile, 16);\r\n\t\t\t} else {\r\n\t\t\t\tconst Direction sd = Players[missile._misource]._pdir;\r\n\t\t\t\tmissile.setDirection(sd);\r\n\t\t\t\tUpdateMissileVelocity(missile, missilePosition + sd, 16);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (missilePosition != Point { missile.var1, missile.var2 }) {\r\n\t\t\tmissile.var1 = missilePosition.x;\r\n\t\t\tmissile.var2 = missilePosition.y;\r\n\t\t\tChangeLight(missile._mlid, missilePosition, 8);\r\n\t\t}\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile.setDefaultFrameGroup();\r\n\t\t\tmissile.setAnimation(MissileGraphicID::BigExplosion);\r\n\t\t\tmissile.duration = missile._miAnimLen - 1;\r\n\t\t\tmissile.position.StopMissile();\r\n\t\t}\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessBoneSpirit(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tconst int dam = missile._midam;\r\n\tif (missile.getDirection() == Direction::NoDirection) {\r\n\t\tChangeLight(missile._mlid, missile.position.tile, missile._miAnimFrame);\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t\tAddUnLight(missile._mlid);\r\n\t\t}\r\n\t\tPutMissile(missile);\r\n\t} else {\r\n\t\tMoveMissileAndCheckMissileCol(missile, GetMissileData(missile._mitype).damageType(), dam, dam, false, false);\r\n\t\tconst Point c = missile.position.tile;\r\n\t\tif (missile.var3 == 0 && c == Point { missile.var4, missile.var5 })\r\n\t\t\tmissile.var3 = 1;\r\n\t\tif (missile.var3 == 1) {\r\n\t\t\tmissile.var3 = 2;\r\n\t\t\tmissile.duration = 255;\r\n\t\t\tauto *monster = FindClosest(c, 19);\r\n\t\t\tif (monster != nullptr) {\r\n\t\t\t\tmissile._midam = monster->hitPoints >> 7;\r\n\t\t\t\tmissile.setDirection(GetDirection(c, monster->position.tile));\r\n\t\t\t\tUpdateMissileVelocity(missile, monster->position.tile, 16);\r\n\t\t\t} else {\r\n\t\t\t\tconst Direction sd = Players[missile._misource]._pdir;\r\n\t\t\t\tmissile.setDirection(sd);\r\n\t\t\t\tUpdateMissileVelocity(missile, c + sd, 16);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (c != Point { missile.var1, missile.var2 }) {\r\n\t\t\tmissile.var1 = c.x;\r\n\t\t\tmissile.var2 = c.y;\r\n\t\t\tChangeLight(missile._mlid, c, 8);\r\n\t\t}\r\n\t\tif (missile.duration == 0) {\r\n\t\t\tmissile.setDirection(Direction::NoDirection);\r\n\t\t\tmissile.position.velocity = {};\r\n\t\t\tmissile.duration = 7;\r\n\t\t}\r\n\t\tPutMissile(missile);\r\n\t}\r\n}\r\n\r\nvoid ProcessResurrectBeam(Missile &missile)\r\n{\r\n\tmissile.duration--;\r\n\tif (missile.duration == 0)\r\n\t\tmissile._miDelFlag = true;\r\n\tPutMissile(missile);\r\n}\r\n\r\nvoid ProcessRedPortal(Missile &missile)\r\n{\r\n\tconst int expLight[17] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15 };\r\n\r\n\tif (missile.duration > 1)\r\n\t\tmissile.duration--;\r\n\tif (missile.duration == missile.var1)\r\n\t\tmissile.setFrameGroup<RedPortalFrame>(RedPortalFrame::Idle);\r\n\r\n\tif (leveltype != DTYPE_TOWN && missile.getFrameGroup<RedPortalFrame>() != RedPortalFrame::Idle && missile.duration != 0) {\r\n\t\tif (missile.var2 == 0)\r\n\t\t\tmissile._mlid = AddLight(missile.position.tile, 1);\r\n\t\tChangeLight(missile._mlid, missile.position.tile, expLight[missile.var2]);\r\n\t\tmissile.var2++;\r\n\t}\r\n\tif (missile.duration == 0) {\r\n\t\tmissile._miDelFlag = true;\r\n\t\tAddUnLight(missile._mlid);\r\n\t}\r\n\tPutMissile(missile);\r\n}\r\n\r\nstatic void DeleteMissiles()\r\n{\r\n\tMissiles.remove_if([](Missile &missile) { return missile._miDelFlag; });\r\n}\r\n\r\nvoid ProcessManaShield()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (myPlayer.pManaShield && myPlayer.hasNoMana()) {\r\n\t\tmyPlayer.pManaShield = false;\r\n\t\tNetSendCmd(true, CMD_REMSHIELD);\r\n\t}\r\n}\r\n\r\nvoid ProcessMissiles()\r\n{\r\n\tfor (auto &missile : Missiles) {\r\n\t\tconst auto &position = missile.position.tile;\r\n\t\tif (InDungeonBounds(position)) {\r\n\t\t\tdFlags[position.x][position.y] &= ~(DungeonFlag::Missile | DungeonFlag::MissileFireWall | DungeonFlag::MissileLightningWall);\r\n\t\t} else {\r\n\t\t\tmissile._miDelFlag = true;\r\n\t\t}\r\n\t}\r\n\r\n\tDeleteMissiles();\r\n\r\n\tMissilePreFlag = false;\r\n\r\n\tfor (auto &missile : Missiles) {\r\n\t\tconst MissileData &missileData = GetMissileData(missile._mitype);\r\n\t\tif (missileData.processFn != nullptr)\r\n\t\t\tmissileData.processFn(missile);\r\n\t\tif (missile._miAnimFlags == MissileGraphicsFlags::NotAnimated)\r\n\t\t\tcontinue;\r\n\r\n\t\tmissile._miAnimCnt++;\r\n\t\tif (missile._miAnimCnt < missile._miAnimDelay)\r\n\t\t\tcontinue;\r\n\r\n\t\tmissile._miAnimCnt = 0;\r\n\t\tmissile._miAnimFrame += missile._miAnimAdd;\r\n\t\tif (missile._miAnimFrame > missile._miAnimLen)\r\n\t\t\tmissile._miAnimFrame = 1;\r\n\t\telse if (missile._miAnimFrame < 1)\r\n\t\t\tmissile._miAnimFrame = missile._miAnimLen;\r\n\t}\r\n\r\n\tProcessManaShield();\r\n\tDeleteMissiles();\r\n}\r\n\r\nvoid SetUpMissileAnimationData()\r\n{\r\n\tfor (auto &missile : Missiles) {\r\n\t\tif (missile._miAnimType == MissileGraphicID::None)\r\n\t\t\tcontinue;\r\n\r\n\t\tif (missile._mitype != MissileID::Rhino) {\r\n\t\t\tmissile._miAnimData = GetMissileSpriteData(missile._miAnimType).spritesForDirection(missile.getDirection16());\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst CMonster &mon = Monsters[missile._misource].type();\r\n\r\n\t\tMonsterGraphic graphic;\r\n\t\tif (IsAnyOf(mon.type, MT_HORNED, MT_MUDRUN, MT_FROSTC, MT_OBLORD)) {\r\n\t\t\tgraphic = MonsterGraphic::Special;\r\n\t\t} else if (IsAnyOf(mon.type, MT_NSNAKE, MT_RSNAKE, MT_BSNAKE, MT_GSNAKE)) {\r\n\t\t\tgraphic = MonsterGraphic::Attack;\r\n\t\t} else {\r\n\t\t\tgraphic = MonsterGraphic::Walk;\r\n\t\t}\r\n\t\tmissile._miAnimData = mon.getAnimData(graphic).spritesForDirection(missile.getDirection());\r\n\t}\r\n}\r\n\r\nvoid RedoMissileFlags()\r\n{\r\n\tfor (auto &missile : Missiles) {\r\n\t\tPutMissile(missile);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/missiles.h",
    "content": "/**\r\n * @file missiles.h\r\n *\r\n * Interface of missile functionality.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <list>\r\n#include <optional>\r\n\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"monster.h\"\r\n#include \"player.h\"\r\n#include \"tables/misdat.h\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr WorldTilePosition GolemHoldingCell = Point { 1, 0 };\r\n\r\nstruct MissilePosition {\r\n\t/** Sprite's pixel offset from tile. */\r\n\tDisplacement offset;\r\n\t/** Pixel velocity while moving */\r\n\tDisplacement velocity;\r\n\t/** Pixels traveled as a numerator of 65,536. */\r\n\tDisplacement traveled;\r\n\r\n\tWorldTilePosition tile;\r\n\t/** Start position */\r\n\tWorldTilePosition start;\r\n\r\n\t/**\r\n\t * @brief Specifies the location (tile) while rendering\r\n\t */\r\n\tWorldTilePosition tileForRendering;\r\n\t/**\r\n\t * @brief Specifies the location (offset) while rendering\r\n\t */\r\n\tDisplacement offsetForRendering;\r\n\r\n\t/**\r\n\t * @brief Stops the missile (set velocity to zero and set offset to last renderer location; shouldn't matter because the missile doesn't move anymore)\r\n\t */\r\n\tvoid StopMissile()\r\n\t{\r\n\t\tvelocity = {};\r\n\t\tif (tileForRendering == tile)\r\n\t\t\toffset = offsetForRendering;\r\n\t}\r\n};\r\n\r\nenum class MissileSource : uint8_t {\r\n\tPlayer,\r\n\tMonster,\r\n\tTrap,\r\n};\r\n\r\nenum class GuardianFrame : uint8_t {\r\n\tStart = 0,\r\n\tIdle = 1,\r\n\tAttack = 2,\r\n};\r\n\r\nenum class AcidPuddleFrame : uint8_t {\r\n\tIdle = 0,\r\n\tEnd = 1,\r\n};\r\n\r\nenum class FireWallFrame : uint8_t {\r\n\tStart = 0,\r\n\tIdle = 1,\r\n};\r\n\r\nenum class PortalFrame : uint8_t {\r\n\tStart = 0,\r\n\tIdle = 1,\r\n};\r\n\r\nenum class RedPortalFrame : uint8_t {\r\n\tStart = 0,\r\n\tIdle = 1,\r\n};\r\n\r\nstruct Missile {\r\n\t/** Type of projectile */\r\n\tMissileID _mitype;\r\n\tMissilePosition position;\r\n\r\nprivate:\r\n\tint _mimfnum; // The direction of the missile (direction enum)\r\n\r\npublic:\r\n\tint _mispllvl;\r\n\tbool _miDelFlag; // Indicate whether the missile should be deleted\r\n\tMissileGraphicID _miAnimType;\r\n\tMissileGraphicsFlags _miAnimFlags;\r\n\tOptionalClxSpriteList _miAnimData;\r\n\tint _miAnimDelay; // Tick length of each frame in the current animation\r\n\tint _miAnimLen;   // Number of frames in current animation\r\n\r\n\t// TODO: This field is no longer used and is always equal to\r\n\t// (*_miAnimData)[0].width()\r\n\tuint16_t _miAnimWidth;\r\n\r\n\tint16_t _miAnimWidth2;\r\n\tint _miAnimCnt; // Increases by one each game tick, counting how close we are to _pAnimDelay\r\n\tint _miAnimAdd;\r\n\tint _miAnimFrame; // Current frame of animation + 1.\r\n\tbool _miDrawFlag;\r\n\tbool _miLightFlag;\r\n\tbool _miPreFlag;\r\n\tuint32_t _miUniqTrans;\r\n\t/** @brief Time to live for the missile in game ticks; once 0, the missile will be marked for deletion via _miDelFlag */\r\n\tint duration;\r\n\tint _misource;\r\n\tmienemy_type _micaster;\r\n\tint _midam;\r\n\tbool _miHitFlag;\r\n\tint _midist; // Used for arrows to measure distance travelled (increases by 1 each game tick). Higher value is a penalty for accuracy calculation when hitting enemy\r\n\tint _mlid;\r\n\tint _mirnd;\r\n\tint var1;\r\n\tint var2;\r\n\tint var3;\r\n\tint var4;\r\n\tint var5;\r\n\tint var6;\r\n\tint var7;\r\n\tbool limitReached;\r\n\t/**\r\n\t * @brief For moving missiles lastCollisionTargetHash contains the last entity (player or monster) that was checked in CheckMissileCol (needed to avoid multiple hits for a entity at the same tile).\r\n\t */\r\n\tint16_t lastCollisionTargetHash;\r\n\r\n\t/** @brief Was the missile generated by a trap? */\r\n\t[[nodiscard]] bool IsTrap() const\r\n\t{\r\n\t\treturn _misource == -1;\r\n\t}\r\n\r\n\t[[nodiscard]] Player *sourcePlayer()\r\n\t{\r\n\t\tif (IsNoneOf(_micaster, TARGET_BOTH, TARGET_MONSTERS) || _misource == -1)\r\n\t\t\treturn nullptr;\r\n\t\treturn &Players[_misource];\r\n\t}\r\n\r\n\t[[nodiscard]] Monster *sourceMonster()\r\n\t{\r\n\t\tif (_micaster != TARGET_PLAYERS || _misource == -1)\r\n\t\t\treturn nullptr;\r\n\t\treturn &Monsters[_misource];\r\n\t}\r\n\r\n\t[[nodiscard]] bool isSameSource(Missile &missile)\r\n\t{\r\n\t\treturn sourceType() == missile.sourceType() && _misource == missile._misource;\r\n\t}\r\n\r\n\tMissileSource sourceType()\r\n\t{\r\n\t\tif (_misource == -1)\r\n\t\t\treturn MissileSource::Trap;\r\n\t\tif (_micaster == TARGET_PLAYERS)\r\n\t\t\treturn MissileSource::Monster;\r\n\t\treturn MissileSource::Player;\r\n\t}\r\n\r\n\tvoid setAnimation(MissileGraphicID animtype);\r\n\r\n\t/**\r\n\t * @brief Sets the missile sprite to the given sheet frame\r\n\t * @param dir Sprite frame\r\n\t */\r\n\tvoid setFrameGroupRaw(int frameGroup)\r\n\t{\r\n\t\t_mimfnum = frameGroup;\r\n\t\tsetAnimation(_miAnimType);\r\n\t}\r\n\r\n\tvoid setDefaultFrameGroup()\r\n\t{\r\n\t\tsetFrameGroupRaw(0);\r\n\t}\r\n\r\n\ttemplate <typename FrameEnum>\r\n\tvoid setFrameGroup(FrameEnum frameGroup)\r\n\t{\r\n\t\tsetFrameGroupRaw(static_cast<int>(frameGroup));\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Sets the sprite for this missile so it matches the given Direction\r\n\t * @param dir Desired facing\r\n\t */\r\n\tvoid setDirection(Direction dir)\r\n\t{\r\n\t\tsetFrameGroupRaw(static_cast<int>(dir));\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Sets the sprite for this missile so it matches the given Direction16\r\n\t * @param dir Desired facing at a 22.8125 degree resolution\r\n\t */\r\n\tvoid setDirection(Direction16 dir)\r\n\t{\r\n\t\tsetFrameGroupRaw(static_cast<int>(dir));\r\n\t}\r\n\r\n\tint getFrameGroupRaw() const\r\n\t{\r\n\t\treturn _mimfnum;\r\n\t}\r\n\r\n\ttemplate <typename FrameEnum>\r\n\tFrameEnum getFrameGroup() const\r\n\t{\r\n\t\tstatic_assert(std::is_enum_v<FrameEnum>, \"Frame group must be an enum\");\r\n\t\treturn static_cast<FrameEnum>(_mimfnum);\r\n\t}\r\n\r\n\t[[nodiscard]] Direction getDirection() const\r\n\t{\r\n\t\treturn static_cast<Direction>(_mimfnum);\r\n\t}\r\n\r\n\t[[nodiscard]] Direction16 getDirection16() const\r\n\t{\r\n\t\treturn static_cast<Direction16>(_mimfnum);\r\n\t}\r\n};\r\n\r\nextern std::list<Missile> Missiles;\r\nextern bool MissilePreFlag;\r\n\r\nstruct DamageRange {\r\n\tint min;\r\n\tint max;\r\n};\r\nDamageRange GetDamageAmt(SpellID spell, int spellLevel);\r\n\r\n/**\r\n * @brief Returns the direction a vector from p1(x1, y1) to p2(x2, y2) is pointing to.\r\n *\r\n * @code{.unparsed}\r\n *      W  sW  SW   Sw  S\r\n *              ^\r\n *     nW       |       Se\r\n *              |\r\n *     NW ------+-----> SE\r\n *              |\r\n *     Nw       |       sE\r\n *              |\r\n *      N  Ne  NE   nE  E\r\n * @endcode\r\n *\r\n * @param p1 The point from which the vector starts.\r\n * @param p2 The point from which the vector ends.\r\n * @return the direction of the p1->p2 vector\r\n */\r\nDirection16 GetDirection16(Point p1, Point p2);\r\nbool MonsterTrapHit(Monster &monster, int mindam, int maxdam, int dist, MissileID t, DamageType damageType, bool shift);\r\nbool PlayerMHit(Player &player, Monster *monster, int dist, int mind, int maxd, MissileID mtype, DamageType damageType, bool shift, DeathReason deathReason, bool *blocked);\r\n\r\n/**\r\n * @brief Could the missile collide with solid objects? (like walls or closed doors)\r\n */\r\nbool IsMissileBlockedByTile(Point tile);\r\n\r\nvoid InitMissiles();\r\n\r\nstruct AddMissileParameter {\r\n\tWorldTilePosition dst;\r\n\tDirection midir;\r\n\tMissile *pParent;\r\n\tbool spellFizzled;\r\n};\r\n\r\nvoid AddOpenNest(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRuneOfFire(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRuneOfLight(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRuneOfNova(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRuneOfImmolation(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRuneOfStone(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddReflect(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddBerserk(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: Direction to place the spawn\r\n */\r\nvoid AddHorkSpawn(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddJester(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddStealPotions(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddStealMana(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddSpectralArrow(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddWarp(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddLightningWall(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddBigExplosion(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddImmolation(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddLightningBow(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddMana(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddMagi(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRingOfFire(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddSearch(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddChargedBoltBow(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddElementalArrow(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddArrow(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddPhasing(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddFirebolt(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddMagmaBall(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddTeleport(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddNovaBall(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddFireWall(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the missile-light\r\n * var2: Y coordinate of the missile-light\r\n * var4: X coordinate of the missile-light\r\n * var5: Y coordinate of the missile-light\r\n */\r\nvoid AddFireball(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the missile\r\n * var2: Y coordinate of the missile\r\n */\r\nvoid AddLightningControl(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddLightning(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddMissileExplosion(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddWeaponExplosion(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: Animation\r\n */\r\nvoid AddTownPortal(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddFlashBottom(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddFlashTop(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddManaShield(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddFlameWave(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: Animation\r\n * var3: Light strength\r\n */\r\nvoid AddGuardian(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the destination\r\n * var2: Y coordinate of the destination\r\n */\r\nvoid AddChainLightning(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRhino(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the missile-light\r\n * var2: Y coordinate of the missile-light\r\n */\r\nvoid AddGenericMagicMissile(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the missile-light\r\n * var2: Y coordinate of the missile-light\r\n */\r\nvoid AddAcid(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddAcidPuddle(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: mmode of the monster\r\n * var2: mnum of the monster\r\n */\r\nvoid AddStoneCurse(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddGolem(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddApocalypseBoom(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddHealing(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddHealOther(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the missile-light\r\n * var2: Y coordinate of the missile-light\r\n * var4: X coordinate of the destination\r\n * var5: Y coordinate of the destination\r\n */\r\nvoid AddElemental(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddIdentify(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the first wave\r\n * var2: Y coordinate of the first wave\r\n * var3: Direction of the first wave\r\n * var4: Direction of the second wave\r\n * var5: X coordinate of the second wave\r\n * var6: Y coordinate of the second wave\r\n */\r\nvoid AddWallControl(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddInfravision(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: X coordinate of the destination\r\n * var2: Y coordinate of the destination\r\n */\r\nvoid AddFlameWaveControl(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddNova(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRage(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddItemRepair(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddStaffRecharge(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddTrapDisarm(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddApocalypse(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddInferno(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddInfernoControl(Missile &missile, AddMissileParameter &parameter);\r\n\r\n/**\r\n * var1: Light strength\r\n * var2: Base direction\r\n */\r\nvoid AddChargedBolt(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddHolyBolt(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddResurrect(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddResurrectBeam(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddTelekinesis(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddBoneSpirit(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddRedPortal(Missile &missile, AddMissileParameter &parameter);\r\nvoid AddDiabloApocalypse(Missile &missile, AddMissileParameter &parameter);\r\nMissile *AddMissile(WorldTilePosition src, WorldTilePosition dst, Direction midir, MissileID mitype,\r\n    mienemy_type micaster, int id, int midam, int spllvl,\r\n    Missile *parent = nullptr, std::optional<SfxID> lSFX = std::nullopt);\r\ninline Missile *AddMissile(WorldTilePosition src, WorldTilePosition dst, Direction midir, MissileID mitype,\r\n    mienemy_type micaster, const Player &player, int midam, int spllvl,\r\n    Missile *parent = nullptr, std::optional<SfxID> lSFX = std::nullopt)\r\n{\r\n\treturn AddMissile(src, dst, midir, mitype, micaster, player.getId(), midam, spllvl, parent, lSFX);\r\n}\r\ninline Missile *AddMissile(WorldTilePosition src, WorldTilePosition dst, Direction midir, MissileID mitype,\r\n    mienemy_type micaster, const Monster &monster, int midam, int spllvl,\r\n    Missile *parent = nullptr, std::optional<SfxID> lSFX = std::nullopt)\r\n{\r\n\treturn AddMissile(src, dst, midir, mitype, micaster, static_cast<int>(monster.getId()), midam, spllvl, parent, lSFX);\r\n}\r\nvoid ProcessElementalArrow(Missile &missile);\r\nvoid ProcessArrow(Missile &missile);\r\nvoid ProcessGenericProjectile(Missile &missile);\r\nvoid ProcessNovaBall(Missile &missilei);\r\nvoid ProcessAcidPuddle(Missile &missile);\r\nvoid ProcessFireWall(Missile &missile);\r\nvoid ProcessFireball(Missile &missile);\r\nvoid ProcessHorkSpawn(Missile &missile);\r\nvoid ProcessRune(Missile &missile);\r\nvoid ProcessLightningWall(Missile &missile);\r\nvoid ProcessBigExplosion(Missile &missile);\r\nvoid ProcessLightningBow(Missile &missile);\r\nvoid ProcessRingOfFire(Missile &missile);\r\nvoid ProcessSearch(Missile &missile);\r\nvoid ProcessImmolation(Missile &missile);\r\nvoid ProcessSpectralArrow(Missile &missile);\r\nvoid ProcessLightningControl(Missile &missile);\r\nvoid ProcessLightning(Missile &missile);\r\nvoid ProcessTownPortal(Missile &missile);\r\nvoid ProcessFlashBottom(Missile &missile);\r\nvoid ProcessFlashTop(Missile &missile);\r\nvoid ProcessFlameWave(Missile &missile);\r\nvoid ProcessGuardian(Missile &missile);\r\nvoid ProcessChainLightning(Missile &missile);\r\nvoid ProcessWeaponExplosion(Missile &missile);\r\nvoid ProcessMissileExplosion(Missile &missile);\r\nvoid ProcessAcidSplate(Missile &missile);\r\nvoid ProcessTeleport(Missile &missile);\r\nvoid ProcessStoneCurse(Missile &missile);\r\nvoid ProcessApocalypseBoom(Missile &missile);\r\nvoid ProcessRhino(Missile &missile);\r\nvoid ProcessWallControl(Missile &missile);\r\nvoid ProcessInfravision(Missile &missile);\r\nvoid ProcessApocalypse(Missile &missile);\r\nvoid ProcessFlameWaveControl(Missile &missile);\r\nvoid ProcessNova(Missile &missile);\r\nvoid ProcessRage(Missile &missile);\r\nvoid ProcessInferno(Missile &missile);\r\nvoid ProcessInfernoControl(Missile &missile);\r\nvoid ProcessChargedBolt(Missile &missile);\r\nvoid ProcessHolyBolt(Missile &missile);\r\nvoid ProcessElemental(Missile &missile);\r\nvoid ProcessBoneSpirit(Missile &missile);\r\nvoid ProcessResurrectBeam(Missile &missile);\r\nvoid ProcessRedPortal(Missile &missile);\r\nvoid ProcessMissiles();\r\nvoid SetUpMissileAnimationData();\r\nvoid RedoMissileFlags();\r\n\r\n#ifdef BUILD_TESTING\r\nvoid TestRotateBlockedMissile(Missile &missile);\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/monster.cpp",
    "content": "/**\r\n * @file monster.cpp\r\n *\r\n * Implementation of monster functionality, AI, actions, spawning, loading, etc.\r\n */\r\n#include \"monster.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <bitset>\r\n#include <cassert>\r\n#include <climits>\r\n#include <cmath>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <iterator>\r\n#include <limits>\r\n#include <memory>\r\n#include <numeric>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n#include <fmt/core.h>\r\n\r\n#include \"automap.h\"\r\n#include \"control/control.hpp\"\r\n#include \"crawl.hpp\"\r\n#include \"cursor.h\"\r\n#include \"dead.h\"\r\n#include \"diablo.h\"\r\n#include \"dvlnet/leaveinfo.hpp\"\r\n#include \"effects.h\"\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/direction.hpp\"\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/load_cl2.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/path.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/sound.h\"\r\n#include \"engine/sound_position.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"function_ref.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"inv.h\"\r\n#include \"items.h\"\r\n#include \"levels/crypt.h\"\r\n#include \"levels/drlg_l4.h\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/gendung_defs.hpp\"\r\n#include \"levels/themes.h\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"levels/trigs.h\"\r\n#include \"lighting.h\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"minitext.h\"\r\n#include \"missiles.h\"\r\n#include \"movie.h\"\r\n#include \"msg.h\"\r\n#include \"multi.h\"\r\n#include \"objects.h\"\r\n#include \"options.h\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"sound_effect_enums.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"tables/itemdat.h\"\r\n#include \"tables/misdat.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"tables/spelldat.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/cl2_to_clx.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/file_name_generator.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/pointer_value_union.hpp\"\r\n#include \"utils/static_vector.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nCMonster LevelMonsterTypes[MaxLvlMTypes];\r\nsize_t LevelMonsterTypeCount;\r\nMonster Monsters[MaxMonsters];\r\nunsigned ActiveMonsters[MaxMonsters];\r\nsize_t ActiveMonsterCount;\r\n/** Tracks the total number of monsters killed per monster_id. */\r\nint MonsterKillCounts[NUM_MAX_MTYPES];\r\nbool sgbSaveSoundOn;\r\n\r\nnamespace {\r\n\r\nconstexpr int NightmareToHitBonus = 85;\r\nconstexpr int HellToHitBonus = 120;\r\n\r\nconstexpr int NightmareAcBonus = 50;\r\nconstexpr int HellAcBonus = 80;\r\n\r\n/** @brief Reserved some entries in @Monster for golems. For vanilla compatibility, this must remain 4. */\r\nconstexpr int ReservedMonsterSlotsForGolems = 4;\r\n\r\n/** Tracks which missile files are already loaded */\r\nsize_t totalmonsters;\r\nint monstimgtot;\r\nint uniquetrans;\r\n\r\nconstexpr const std::array<_monster_id, 12> SkeletonTypes {\r\n\tMT_WSKELAX,\r\n\tMT_TSKELAX,\r\n\tMT_RSKELAX,\r\n\tMT_XSKELAX,\r\n\tMT_WSKELBW,\r\n\tMT_TSKELBW,\r\n\tMT_RSKELBW,\r\n\tMT_XSKELBW,\r\n\tMT_WSKELSD,\r\n\tMT_TSKELSD,\r\n\tMT_RSKELSD,\r\n\tMT_XSKELSD,\r\n};\r\n\r\n/** Maps from monster action to monster animation letter. */\r\nconstexpr char Animletter[7] = \"nwahds\";\r\n\r\nsize_t GetNumAnims(const MonsterData &monsterData)\r\n{\r\n\treturn monsterData.hasSpecial ? 6 : 5;\r\n}\r\n\r\nsize_t GetNumAnimsWithGraphics(const MonsterData &monsterData)\r\n{\r\n\t// Monster graphics can be missing for certain actions,\r\n\t// e.g. Golem has no standing graphics.\r\n\tconst size_t numAnims = GetNumAnims(monsterData);\r\n\tsize_t result = 0;\r\n\tfor (size_t i = 0; i < numAnims; ++i) {\r\n\t\tif (monsterData.hasAnim(i))\r\n\t\t\t++result;\r\n\t}\r\n\treturn result;\r\n}\r\n\r\nvoid InitMonsterTRN(CMonster &monst)\r\n{\r\n\tchar path[64];\r\n\t*BufCopy(path, \"monsters\\\\\", monst.data().trnFile, \".trn\") = '\\0';\r\n\tstd::array<uint8_t, 256> colorTranslations;\r\n\tLoadFileInMem(path, colorTranslations);\r\n\tstd::replace(colorTranslations.begin(), colorTranslations.end(), 255, 0);\r\n\r\n\tconst size_t numAnims = GetNumAnims(monst.data());\r\n\tfor (size_t i = 0; i < numAnims; i++) {\r\n\t\tif (i == 1 && IsAnyOf(monst.type, MT_COUNSLR, MT_MAGISTR, MT_CABALIST, MT_ADVOCATE)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tAnimStruct &anim = monst.anims[i];\r\n\t\tif (anim.sprites->isSheet()) {\r\n\t\t\tClxApplyTrans(ClxSpriteSheet { anim.sprites->sheet() }, colorTranslations.data());\r\n\t\t} else {\r\n\t\t\tClxApplyTrans(ClxSpriteList { anim.sprites->list() }, colorTranslations.data());\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point position)\r\n{\r\n\tmonster.direction = rd;\r\n\tmonster.position.tile = position;\r\n\tmonster.position.future = position;\r\n\tmonster.position.old = position;\r\n\tmonster.levelType = static_cast<uint8_t>(typeIndex);\r\n\tmonster.mode = MonsterMode::Stand;\r\n\tmonster.animInfo = {};\r\n\tmonster.changeAnimationData(MonsterGraphic::Stand);\r\n\tmonster.animInfo.tickCounterOfCurrentFrame = GenerateRnd(monster.animInfo.ticksPerFrame - 1);\r\n\tmonster.animInfo.currentFrame = GenerateRnd(monster.animInfo.numberOfFrames - 1);\r\n\r\n\tconst int maxhp = RandomIntBetween(monster.data().hitPointsMinimum, monster.data().hitPointsMaximum);\r\n\tmonster.maxHitPoints = maxhp << 6;\r\n\r\n\tif (!gbIsMultiplayer)\r\n\t\tmonster.maxHitPoints = std::max(monster.maxHitPoints / 2, 64);\r\n\r\n\tmonster.hitPoints = monster.maxHitPoints;\r\n\tmonster.ai = monster.data().ai;\r\n\tmonster.intelligence = monster.data().intelligence;\r\n\tmonster.goal = MonsterGoal::Normal;\r\n\tmonster.goalVar1 = 0;\r\n\tmonster.goalVar2 = 0;\r\n\tmonster.goalVar3 = 0;\r\n\tmonster.pathCount = 0;\r\n\tmonster.enemy = 0;\r\n\tmonster.isInvalid = false;\r\n\tmonster.uniqueType = UniqueMonsterType::None;\r\n\tmonster.activeForTicks = 0;\r\n\tmonster.lightId = NO_LIGHT;\r\n\tmonster.rndItemSeed = AdvanceRndSeed();\r\n\tmonster.aiSeed = AdvanceRndSeed();\r\n\tmonster.whoHit = 0;\r\n\tmonster.minDamage = monster.data().minDamage;\r\n\tmonster.maxDamage = monster.data().maxDamage;\r\n\tmonster.minDamageSpecial = monster.data().minDamageSpecial;\r\n\tmonster.maxDamageSpecial = monster.data().maxDamageSpecial;\r\n\tmonster.armorClass = monster.data().armorClass;\r\n\tmonster.reducePlayerStrength = monster.data().reducePlayerStrength;\r\n\tmonster.reducePlayerMagic = monster.data().reducePlayerMagic;\r\n\tmonster.reducePlayerDexterity = monster.data().reducePlayerDexterity;\r\n\tmonster.reducePlayerVitality = monster.data().reducePlayerVitality;\r\n\tmonster.reducePlayerMaxHP = monster.data().reducePlayerMaxHP;\r\n\tmonster.reducePlayerMaxMana = monster.data().reducePlayerMaxMana;\r\n\tmonster.resistance = monster.data().resistance;\r\n\tmonster.leader = Monster::NoLeader;\r\n\tmonster.leaderRelation = LeaderRelation::None;\r\n\tmonster.flags = monster.data().abilityFlags;\r\n\tmonster.talkMsg = TEXT_NONE;\r\n\r\n\tif (monster.ai == MonsterAIID::Gargoyle) {\r\n\t\tmonster.changeAnimationData(MonsterGraphic::Special);\r\n\t\tmonster.animInfo.currentFrame = 0;\r\n\t\tmonster.flags |= MFLAG_ALLOW_SPECIAL;\r\n\t\tmonster.mode = MonsterMode::SpecialMeleeAttack;\r\n\t}\r\n\r\n\tif (sgGameInitInfo.nDifficulty == DIFF_NIGHTMARE) {\r\n\t\tmonster.maxHitPoints = 3 * monster.maxHitPoints;\r\n\t\tif (gbIsHellfire)\r\n\t\t\tmonster.maxHitPoints += (gbIsMultiplayer ? 100 : 50) << 6;\r\n\t\telse\r\n\t\t\tmonster.maxHitPoints += 100 << 6;\r\n\t\tmonster.hitPoints = monster.maxHitPoints;\r\n\t\tmonster.minDamage = 2 * (monster.minDamage + 2);\r\n\t\tmonster.maxDamage = 2 * (monster.maxDamage + 2);\r\n\t\tmonster.minDamageSpecial = 2 * (monster.minDamageSpecial + 2);\r\n\t\tmonster.maxDamageSpecial = 2 * (monster.maxDamageSpecial + 2);\r\n\t\tmonster.armorClass += NightmareAcBonus;\r\n\t} else if (sgGameInitInfo.nDifficulty == DIFF_HELL) {\r\n\t\tmonster.maxHitPoints = 4 * monster.maxHitPoints;\r\n\t\tif (gbIsHellfire)\r\n\t\t\tmonster.maxHitPoints += (gbIsMultiplayer ? 200 : 100) << 6;\r\n\t\telse\r\n\t\t\tmonster.maxHitPoints += 200 << 6;\r\n\t\tmonster.hitPoints = monster.maxHitPoints;\r\n\t\tmonster.minDamage = 4 * monster.minDamage + 6;\r\n\t\tmonster.maxDamage = 4 * monster.maxDamage + 6;\r\n\t\tmonster.minDamageSpecial = 4 * monster.minDamageSpecial + 6;\r\n\t\tmonster.maxDamageSpecial = 4 * monster.maxDamageSpecial + 6;\r\n\t\tmonster.armorClass += HellAcBonus;\r\n\t\tmonster.resistance = monster.data().resistanceHell;\r\n\t}\r\n}\r\n\r\nbool CanPlaceMonster(Point position)\r\n{\r\n\treturn InDungeonBounds(position)\r\n\t    && dMonster[position.x][position.y] == 0\r\n\t    && dPlayer[position.x][position.y] == 0\r\n\t    && !IsTileVisible(position)\r\n\t    && !TileContainsSetPiece(position)\r\n\t    && !IsTileOccupied(position);\r\n}\r\n\r\nvoid PlaceMonster(size_t i, size_t typeIndex, Point position)\r\n{\r\n\tif (LevelMonsterTypes[typeIndex].type == MT_NAKRUL) {\r\n\t\tfor (size_t j = 0; j < ActiveMonsterCount; j++) {\r\n\t\t\tif (Monsters[j].levelType == typeIndex) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tMonster &monster = Monsters[i];\r\n\tmonster.occupyTile(position, false);\r\n\r\n\tauto rd = static_cast<Direction>(GenerateRnd(8));\r\n\tInitMonster(monster, rd, typeIndex, position);\r\n}\r\n\r\nvoid PlaceGroup(size_t typeIndex, size_t num, Monster *leader = nullptr, bool leashed = false)\r\n{\r\n\tuint8_t placed = 0;\r\n\r\n\tfor (int try1 = 0; try1 < 10; try1++) {\r\n\t\twhile (placed != 0) {\r\n\t\t\tActiveMonsterCount--;\r\n\t\t\tplaced--;\r\n\t\t\tconst Point &position = Monsters[ActiveMonsterCount].position.tile;\r\n\t\t\tdMonster[position.x][position.y] = 0;\r\n\t\t}\r\n\r\n\t\tint xp;\r\n\t\tint yp;\r\n\t\tif (leader != nullptr) {\r\n\t\t\tconst int offset = GenerateRnd(8);\r\n\t\t\tauto position = leader->position.tile + static_cast<Direction>(offset);\r\n\t\t\txp = position.x;\r\n\t\t\typ = position.y;\r\n\t\t} else {\r\n\t\t\tdo {\r\n\t\t\t\txp = GenerateRnd(80) + 16;\r\n\t\t\t\typ = GenerateRnd(80) + 16;\r\n\t\t\t} while (!CanPlaceMonster({ xp, yp }));\r\n\t\t}\r\n\t\tconst int x1 = xp;\r\n\t\tconst int y1 = yp;\r\n\r\n\t\tif (num + ActiveMonsterCount > totalmonsters) {\r\n\t\t\tnum = totalmonsters - ActiveMonsterCount;\r\n\t\t}\r\n\r\n\t\tunsigned j = 0;\r\n\t\tfor (unsigned try2 = 0; j < num && try2 < 100; xp += Displacement(static_cast<Direction>(GenerateRnd(8))).deltaX, yp += Displacement(static_cast<Direction>(GenerateRnd(8))).deltaX) { /// BUGFIX: `yp += Point.y`\r\n\t\t\tif (!CanPlaceMonster({ xp, yp })\r\n\t\t\t    || (dTransVal[xp][yp] != dTransVal[x1][y1])\r\n\t\t\t    || (leashed && (std::abs(xp - x1) >= 4 || std::abs(yp - y1) >= 4))) {\r\n\t\t\t\ttry2++;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tPlaceMonster(ActiveMonsterCount, typeIndex, { xp, yp });\r\n\t\t\tif (leader != nullptr) {\r\n\t\t\t\tMonster &minion = Monsters[ActiveMonsterCount];\r\n\t\t\t\tminion.maxHitPoints *= 2;\r\n\t\t\t\tminion.hitPoints = minion.maxHitPoints;\r\n\t\t\t\tminion.intelligence = leader->intelligence;\r\n\r\n\t\t\t\tif (leashed) {\r\n\t\t\t\t\tminion.setLeader(leader);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (minion.ai != MonsterAIID::Gargoyle) {\r\n\t\t\t\t\tminion.changeAnimationData(MonsterGraphic::Stand);\r\n\t\t\t\t\tminion.animInfo.currentFrame = GenerateRnd(minion.animInfo.numberOfFrames - 1);\r\n\t\t\t\t\tminion.flags &= ~MFLAG_ALLOW_SPECIAL;\r\n\t\t\t\t\tminion.mode = MonsterMode::Stand;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tActiveMonsterCount++;\r\n\t\t\tplaced++;\r\n\t\t\tj++;\r\n\t\t}\r\n\r\n\t\tif (placed >= num) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (leashed) {\r\n\t\tleader->packSize = placed;\r\n\t}\r\n}\r\n\r\nsize_t GetMonsterTypeIndex(_monster_id type)\r\n{\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tif (LevelMonsterTypes[i].type == type)\r\n\t\t\treturn i;\r\n\t}\r\n\treturn LevelMonsterTypeCount;\r\n}\r\n\r\nPoint GetUniqueMonstPosition(UniqueMonsterType uniqindex)\r\n{\r\n\tif (setlevel) {\r\n\t\tswitch (uniqindex) {\r\n\t\tcase UniqueMonsterType::Lazarus:\r\n\t\t\treturn { 32, 46 };\r\n\t\tcase UniqueMonsterType::RedVex:\r\n\t\t\treturn { 40, 45 };\r\n\t\tcase UniqueMonsterType::BlackJade:\r\n\t\t\treturn { 38, 49 };\r\n\t\tcase UniqueMonsterType::SkeletonKing:\r\n\t\t\treturn { 35, 47 };\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tswitch (uniqindex) {\r\n\tcase UniqueMonsterType::SnotSpill:\r\n\t\treturn SetPiece.position.megaToWorld() + Displacement { 8, 12 };\r\n\tcase UniqueMonsterType::WarlordOfBlood:\r\n\t\treturn SetPiece.position.megaToWorld() + Displacement { 6, 7 };\r\n\tcase UniqueMonsterType::Zhar:\r\n\t\tfor (int i = 0; i < themeCount; i++) {\r\n\t\t\tif (i == zharlib) {\r\n\t\t\t\treturn themeLoc[i].room.position.megaToWorld() + Displacement { 4, 4 };\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase UniqueMonsterType::Lazarus:\r\n\t\treturn SetPiece.position.megaToWorld() + Displacement { 3, 6 };\r\n\tcase UniqueMonsterType::RedVex:\r\n\t\treturn SetPiece.position.megaToWorld() + Displacement { 5, 3 };\r\n\tcase UniqueMonsterType::BlackJade:\r\n\t\treturn SetPiece.position.megaToWorld() + Displacement { 5, 9 };\r\n\tcase UniqueMonsterType::Butcher:\r\n\t\treturn SetPiece.position.megaToWorld() + Displacement { 4, 4 };\r\n\tcase UniqueMonsterType::NaKrul:\r\n\t\tif (UberRow == 0 || UberCol == 0) {\r\n\t\t\tUberDiabloMonsterIndex = -1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tUberDiabloMonsterIndex = static_cast<int>(ActiveMonsterCount);\r\n\t\treturn { UberRow - 2, UberCol };\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tPoint position;\r\n\tint count = 0;\r\n\tdo {\r\n\t\tposition = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 };\r\n\t\tint count2 = 0;\r\n\t\tfor (int x = position.x - 3; x < position.x + 3; x++) {\r\n\t\t\tfor (int y = position.y - 3; y < position.y + 3; y++) {\r\n\t\t\t\tif (InDungeonBounds({ x, y }) && CanPlaceMonster({ x, y })) {\r\n\t\t\t\t\tcount2++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (count2 < 9) {\r\n\t\t\tcount++;\r\n\t\t\tif (count < 1000) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t} while (!CanPlaceMonster(position));\r\n\r\n\treturn position;\r\n}\r\n\r\ntl::expected<void, std::string> PlaceUniqueMonst(UniqueMonsterType uniqindex, size_t minionType, int bosspacksize)\r\n{\r\n\tconst auto &uniqueMonsterData = UniqueMonstersData[static_cast<size_t>(uniqindex)];\r\n\tconst size_t typeIndex = GetMonsterTypeIndex(uniqueMonsterData.mtype);\r\n\tconst Point position = GetUniqueMonstPosition(uniqindex);\r\n\tPlaceMonster(ActiveMonsterCount, typeIndex, position);\r\n\r\n\tMonster &monster = Monsters[ActiveMonsterCount];\r\n\tActiveMonsterCount++;\r\n\treturn PrepareUniqueMonst(monster, uniqindex, minionType, bosspacksize, uniqueMonsterData);\r\n}\r\n\r\nvoid ClearMVars(Monster &monster)\r\n{\r\n\tmonster.var1 = 0;\r\n\tmonster.var2 = 0;\r\n\tmonster.var3 = 0;\r\n\tmonster.position.temp = { 0, 0 };\r\n}\r\n\r\nvoid ClrAllMonsters()\r\n{\r\n\tfor (auto &monster : Monsters) {\r\n\t\tClearMVars(monster);\r\n\t\tmonster.goal = MonsterGoal::None;\r\n\t\tmonster.mode = MonsterMode::Stand;\r\n\t\tmonster.var1 = 0;\r\n\t\tmonster.var2 = 0;\r\n\t\tmonster.position.tile = { 0, 0 };\r\n\t\tmonster.position.future = { 0, 0 };\r\n\t\tmonster.position.old = { 0, 0 };\r\n\t\tmonster.direction = static_cast<Direction>(GenerateRnd(8));\r\n\t\tmonster.animInfo = {};\r\n\t\tmonster.flags = MFLAG_NO_ENEMY;\r\n\t\tmonster.isInvalid = false;\r\n\t\tmonster.enemy = 0;\r\n\t\tmonster.enemyPosition = {};\r\n\t\tDiscardRandomValues(1);\r\n\t}\r\n}\r\n\r\ntl::expected<void, std::string> PlaceUniqueMonsters()\r\n{\r\n\tfor (size_t u = 0; u < UniqueMonstersData.size(); ++u) {\r\n\t\tif (UniqueMonstersData[u].mlevel != currlevel)\r\n\t\t\tcontinue;\r\n\r\n\t\tconst size_t minionType = GetMonsterTypeIndex(UniqueMonstersData[u].mtype);\r\n\t\tif (minionType == LevelMonsterTypeCount)\r\n\t\t\tcontinue;\r\n\r\n\t\tconst auto uniqueType = static_cast<UniqueMonsterType>(u);\r\n\t\tif (uniqueType == UniqueMonsterType::Garbud && Quests[Q_GARBUD]._qactive == QUEST_NOTAVAIL)\r\n\t\t\tcontinue;\r\n\t\tif (uniqueType == UniqueMonsterType::Zhar && Quests[Q_ZHAR]._qactive == QUEST_NOTAVAIL)\r\n\t\t\tcontinue;\r\n\t\tif (uniqueType == UniqueMonsterType::SnotSpill && Quests[Q_LTBANNER]._qactive == QUEST_NOTAVAIL)\r\n\t\t\tcontinue;\r\n\t\tif (uniqueType == UniqueMonsterType::Lachdan && Quests[Q_VEIL]._qactive == QUEST_NOTAVAIL)\r\n\t\t\tcontinue;\r\n\t\tif (uniqueType == UniqueMonsterType::WarlordOfBlood && Quests[Q_WARLORD]._qactive == QUEST_NOTAVAIL)\r\n\t\t\tcontinue;\r\n\r\n\t\tRETURN_IF_ERROR(PlaceUniqueMonst(uniqueType, minionType, 8));\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> PlaceQuestMonsters()\r\n{\r\n\tif (!setlevel) {\r\n\t\tif (Quests[Q_BUTCHER].IsAvailable()) {\r\n\t\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::Butcher, 0, 0));\r\n\t\t}\r\n\r\n\t\tif (currlevel == Quests[Q_SKELKING]._qlevel && UseMultiplayerQuests()) {\r\n\t\t\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\t\t\tif (IsSkel(LevelMonsterTypes[i].type)) {\r\n\t\t\t\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::SkeletonKing, i, 30));\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (Quests[Q_LTBANNER].IsAvailable()) {\r\n\t\t\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l1data\\\\banner1.dun\");\r\n\t\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), SetPiece.position.megaToWorld()));\r\n\t\t}\r\n\t\tif (Quests[Q_BLOOD].IsAvailable()) {\r\n\t\t\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\blood2.dun\");\r\n\t\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), SetPiece.position.megaToWorld()));\r\n\t\t}\r\n\t\tif (Quests[Q_BLIND].IsAvailable()) {\r\n\t\t\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\blind2.dun\");\r\n\t\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), SetPiece.position.megaToWorld()));\r\n\t\t}\r\n\t\tif (Quests[Q_ANVIL].IsAvailable()) {\r\n\t\t\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l3data\\\\anvil.dun\");\r\n\t\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), SetPiece.position.megaToWorld() + Displacement { 2, 2 }));\r\n\t\t}\r\n\t\tif (Quests[Q_WARLORD].IsAvailable()) {\r\n\t\t\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l4data\\\\warlord.dun\");\r\n\t\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), SetPiece.position.megaToWorld()));\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::WarlordOfBlood, PLACE_SCATTER));\r\n\t\t}\r\n\t\tif (Quests[Q_VEIL].IsAvailable()) {\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::Lachdan, PLACE_SCATTER));\r\n\t\t}\r\n\t\tif (Quests[Q_ZHAR].IsAvailable() && zharlib == -1) {\r\n\t\t\tQuests[Q_ZHAR]._qactive = QUEST_NOTAVAIL;\r\n\t\t}\r\n\r\n\t\tif (currlevel == Quests[Q_BETRAYER]._qlevel && UseMultiplayerQuests()) {\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::Lazarus, PLACE_UNIQUE));\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::RedVex, PLACE_UNIQUE));\r\n\t\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::Lazarus, 0, 0));\r\n\t\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::RedVex, 0, 0));\r\n\t\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::BlackJade, 0, 0));\r\n\t\t\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l4data\\\\vile1.dun\");\r\n\t\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), SetPiece.position.megaToWorld()));\r\n\t\t}\r\n\r\n\t\tif (currlevel == 24) {\r\n\t\t\tUberDiabloMonsterIndex = -1;\r\n\t\t\tconst size_t typeIndex = GetMonsterTypeIndex(MT_NAKRUL);\r\n\t\t\tif (typeIndex < LevelMonsterTypeCount) {\r\n\t\t\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\t\t\t\tconst Monster &monster = Monsters[i];\r\n\t\t\t\t\tif (monster.isUnique() || monster.levelType == typeIndex) {\r\n\t\t\t\t\t\tUberDiabloMonsterIndex = static_cast<int>(i);\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (UberDiabloMonsterIndex == -1)\r\n\t\t\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::NaKrul, 0, 0));\r\n\t\t}\r\n\t} else if (setlvlnum == SL_SKELKING) {\r\n\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::SkeletonKing, 0, 0));\r\n\t} else if (setlvlnum == SL_VILEBETRAYER) {\r\n\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::Lazarus, PLACE_UNIQUE));\r\n\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::RedVex, PLACE_UNIQUE));\r\n\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::BlackJade, PLACE_UNIQUE));\r\n\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::Lazarus, 0, 0));\r\n\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::RedVex, 0, 0));\r\n\t\tRETURN_IF_ERROR(PlaceUniqueMonst(UniqueMonsterType::BlackJade, 0, 0));\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> LoadDiabMonsts()\r\n{\r\n\t{\r\n\t\tASSIGN_OR_RETURN(auto dunData, LoadFileInMemWithStatus<uint16_t>(\"levels\\\\l4data\\\\diab1.dun\"));\r\n\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), DiabloQuad1.megaToWorld()));\r\n\t}\r\n\t{\r\n\t\tASSIGN_OR_RETURN(auto dunData, LoadFileInMemWithStatus<uint16_t>(\"levels\\\\l4data\\\\diab2a.dun\"));\r\n\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), DiabloQuad2.megaToWorld()));\r\n\t}\r\n\t{\r\n\t\tASSIGN_OR_RETURN(auto dunData, LoadFileInMemWithStatus<uint16_t>(\"levels\\\\l4data\\\\diab3a.dun\"));\r\n\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), DiabloQuad3.megaToWorld()));\r\n\t}\r\n\t{\r\n\t\tASSIGN_OR_RETURN(auto dunData, LoadFileInMemWithStatus<uint16_t>(\"levels\\\\l4data\\\\diab4a.dun\"));\r\n\t\tRETURN_IF_ERROR(SetMapMonsters(dunData.get(), DiabloQuad4.megaToWorld()));\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid DeleteMonster(size_t activeIndex)\r\n{\r\n\tconst unsigned monsterId = ActiveMonsters[activeIndex];\r\n\tconst Monster &monster = Monsters[monsterId];\r\n\tif ((monster.flags & MFLAG_BERSERK) != 0) {\r\n\t\tAddUnLight(monster.lightId);\r\n\t}\r\n\r\n\tActiveMonsterCount--;\r\n\tstd::swap(ActiveMonsters[activeIndex], ActiveMonsters[ActiveMonsterCount]); // This ensures alive monsters are before ActiveMonsterCount in the array and any deleted monster after\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tMonster &activeMonster = Monsters[ActiveMonsters[i]];\r\n\t\tif ((activeMonster.flags & MFLAG_TARGETS_MONSTER) != 0 && activeMonster.enemy == monsterId) {\r\n\t\t\tactiveMonster.flags |= MFLAG_NO_ENEMY;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NewMonsterAnim(Monster &monster, MonsterGraphic graphic, Direction md, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int8_t numSkippedFrames = 0, int8_t distributeFramesBeforeFrame = 0)\r\n{\r\n\tconst auto &animData = monster.type().getAnimData(graphic);\r\n\tmonster.animInfo.setNewAnimation(animData.spritesForDirection(md), animData.frames, animData.rate, flags, numSkippedFrames, distributeFramesBeforeFrame);\r\n\tmonster.flags &= ~(MFLAG_LOCK_ANIMATION | MFLAG_ALLOW_SPECIAL);\r\n\tmonster.direction = md;\r\n}\r\n\r\nvoid StartMonsterGotHit(Monster &monster)\r\n{\r\n\tif (monster.type().type != MT_GOLEM) {\r\n\t\tauto animationFlags = gGameLogicStep < GameLogicStep::ProcessMonsters ? AnimationDistributionFlags::ProcessAnimationPending : AnimationDistributionFlags::None;\r\n\t\tNewMonsterAnim(monster, MonsterGraphic::GotHit, monster.direction, animationFlags);\r\n\t\tmonster.mode = MonsterMode::HitRecovery;\r\n\t}\r\n\tmonster.position.tile = monster.position.old;\r\n\tmonster.position.future = monster.position.old;\r\n\tM_ClearSquares(monster);\r\n\tmonster.occupyTile(monster.position.tile, false);\r\n}\r\n\r\nDVL_ALWAYS_INLINE bool IsRanged(Monster &monster)\r\n{\r\n\treturn IsAnyOf(monster.ai, MonsterAIID::SkeletonRanged, MonsterAIID::GoatRanged, MonsterAIID::Succubus, MonsterAIID::LazarusSuccubus);\r\n}\r\n\r\nvoid UpdateEnemy(Monster &monster)\r\n{\r\n\tWorldTilePosition target;\r\n\tint menemy = -1;\r\n\tint bestDist = -1;\r\n\tbool bestsameroom = false;\r\n\tconst WorldTilePosition position = monster.position.tile;\r\n\tconst bool isPlayerMinion = monster.isPlayerMinion();\r\n\tif (!isPlayerMinion) {\r\n\t\tfor (size_t pnum = 0; pnum < Players.size(); pnum++) {\r\n\t\t\tconst Player &player = Players[pnum];\r\n\t\t\tif (!player.plractive || !player.isOnActiveLevel() || player._pLvlChanging\r\n\t\t\t    || (player.hasNoLife() && gbIsMultiplayer))\r\n\t\t\t\tcontinue;\r\n\t\t\tconst bool sameroom = (dTransVal[position.x][position.y] == dTransVal[player.position.tile.x][player.position.tile.y]);\r\n\t\t\tconst int dist = position.WalkingDistance(player.position.tile);\r\n\t\t\tif ((sameroom && !bestsameroom)\r\n\t\t\t    || ((sameroom || !bestsameroom) && dist < bestDist)\r\n\t\t\t    || (menemy == -1)) {\r\n\t\t\t\tmonster.flags &= ~MFLAG_TARGETS_MONSTER;\r\n\t\t\t\tmenemy = static_cast<int>(pnum);\r\n\t\t\t\ttarget = player.position.future;\r\n\t\t\t\tbestDist = dist;\r\n\t\t\t\tbestsameroom = sameroom;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst unsigned monsterId = ActiveMonsters[i];\r\n\t\tMonster &otherMonster = Monsters[monsterId];\r\n\t\tif (&otherMonster == &monster)\r\n\t\t\tcontinue;\r\n\t\tif (otherMonster.hasNoLife())\r\n\t\t\tcontinue;\r\n\t\tif (otherMonster.position.tile == GolemHoldingCell)\r\n\t\t\tcontinue;\r\n\t\tif (otherMonster.talkMsg != TEXT_NONE && M_Talker(otherMonster))\r\n\t\t\tcontinue;\r\n\t\tif (isPlayerMinion && otherMonster.isPlayerMinion()) // prevent golems from fighting each other\r\n\t\t\tcontinue;\r\n\r\n\t\tconst int dist = otherMonster.position.tile.WalkingDistance(position);\r\n\t\tif (((monster.flags & MFLAG_GOLEM) == 0\r\n\t\t        && (monster.flags & MFLAG_BERSERK) == 0\r\n\t\t        && dist >= 2\r\n\t\t        && !IsRanged(monster))\r\n\t\t    || ((monster.flags & MFLAG_GOLEM) == 0\r\n\t\t        && (monster.flags & MFLAG_BERSERK) == 0\r\n\t\t        && (otherMonster.flags & MFLAG_GOLEM) == 0)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst bool sameroom = dTransVal[position.x][position.y] == dTransVal[otherMonster.position.tile.x][otherMonster.position.tile.y];\r\n\t\tif ((sameroom && !bestsameroom)\r\n\t\t    || ((sameroom || !bestsameroom) && dist < bestDist)\r\n\t\t    || (menemy == -1)) {\r\n\t\t\tmonster.flags |= MFLAG_TARGETS_MONSTER;\r\n\t\t\tmenemy = static_cast<int>(monsterId);\r\n\t\t\ttarget = otherMonster.position.future;\r\n\t\t\tbestDist = dist;\r\n\t\t\tbestsameroom = sameroom;\r\n\t\t}\r\n\t}\r\n\tif (menemy != -1) {\r\n\t\tmonster.flags &= ~MFLAG_NO_ENEMY;\r\n\t\tmonster.enemy = menemy;\r\n\t\tmonster.enemyPosition = target;\r\n\t} else {\r\n\t\tmonster.flags |= MFLAG_NO_ENEMY;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Make the AI wait a bit before thinking again\r\n * @param monster The monster that will wait\r\n * @param len\r\n */\r\nvoid AiDelay(Monster &monster, int len)\r\n{\r\n\tif (len <= 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.ai == MonsterAIID::Lazarus) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tmonster.var2 = len;\r\n\tmonster.mode = MonsterMode::Delay;\r\n}\r\n\r\n/**\r\n * @brief Get the direction from the monster to its current enemy\r\n */\r\nDirection GetMonsterDirection(Monster &monster)\r\n{\r\n\treturn GetDirection(monster.position.tile, monster.enemyPosition);\r\n}\r\n\r\nvoid StartSpecialStand(Monster &monster, Direction md)\r\n{\r\n\tNewMonsterAnim(monster, MonsterGraphic::Special, md);\r\n\tmonster.mode = MonsterMode::SpecialStand;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n}\r\n\r\nvoid WalkInDirection(Monster &monster, Direction endDir)\r\n{\r\n\tPoint dir = { 0, 0 };\r\n\tdir += endDir;\r\n\r\n\tconst auto fx = static_cast<WorldTileCoord>(monster.position.tile.x + dir.x);\r\n\tconst auto fy = static_cast<WorldTileCoord>(monster.position.tile.y + dir.y);\r\n\r\n\tMonsterMode mode;\r\n\tswitch (endDir) {\r\n\tcase Direction::NorthWest:\r\n\tcase Direction::North:\r\n\tcase Direction::NorthEast:\r\n\t\tmode = MonsterMode::MoveNorthwards;\r\n\t\tbreak;\r\n\tcase Direction::West:\r\n\tcase Direction::East:\r\n\t\tmode = MonsterMode::MoveSideways;\r\n\t\tbreak;\r\n\tcase Direction::SouthWest:\r\n\tcase Direction::South:\r\n\tcase Direction::SouthEast:\r\n\t\tmode = MonsterMode::MoveSouthwards;\r\n\t\tbreak;\r\n\tcase Direction::NoDirection:\r\n\t\tDVL_UNREACHABLE();\r\n\t\tbreak;\r\n\t}\r\n\tmonster.mode = mode;\r\n\tmonster.position.old = monster.position.tile;\r\n\tmonster.position.future = { fx, fy };\r\n\tmonster.occupyTile(monster.position.future, true);\r\n\tmonster.var1 = dir.x;\r\n\tmonster.var2 = dir.y;\r\n\tmonster.var3 = static_cast<int8_t>(endDir);\r\n\tNewMonsterAnim(monster, MonsterGraphic::Walk, endDir, AnimationDistributionFlags::ProcessAnimationPending, -1);\r\n}\r\n\r\nvoid StartAttack(Monster &monster)\r\n{\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tNewMonsterAnim(monster, MonsterGraphic::Attack, md, AnimationDistributionFlags::ProcessAnimationPending);\r\n\tmonster.mode = MonsterMode::MeleeAttack;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n}\r\n\r\nvoid StartRangedAttack(Monster &monster, MissileID missileType, int dam)\r\n{\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tNewMonsterAnim(monster, MonsterGraphic::Attack, md, AnimationDistributionFlags::ProcessAnimationPending);\r\n\tmonster.mode = MonsterMode::RangedAttack;\r\n\tmonster.var1 = static_cast<int8_t>(missileType);\r\n\tmonster.var2 = dam;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n}\r\n\r\nvoid StartRangedSpecialAttack(Monster &monster, MissileID missileType, int dam)\r\n{\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tint8_t distributeFramesBeforeFrame = 0;\r\n\tif (monster.ai == MonsterAIID::Mega)\r\n\t\tdistributeFramesBeforeFrame = monster.data().animFrameNumSpecial;\r\n\tNewMonsterAnim(monster, MonsterGraphic::Special, md, AnimationDistributionFlags::ProcessAnimationPending, 0, distributeFramesBeforeFrame);\r\n\tmonster.mode = MonsterMode::SpecialRangedAttack;\r\n\tmonster.var1 = static_cast<int8_t>(missileType);\r\n\tmonster.var2 = 0;\r\n\tmonster.var3 = dam;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n}\r\n\r\nvoid StartSpecialAttack(Monster &monster)\r\n{\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tNewMonsterAnim(monster, MonsterGraphic::Special, md);\r\n\tmonster.mode = MonsterMode::SpecialMeleeAttack;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n}\r\n\r\nvoid StartEating(Monster &monster)\r\n{\r\n\tNewMonsterAnim(monster, MonsterGraphic::Special, monster.direction);\r\n\tmonster.mode = MonsterMode::SpecialMeleeAttack;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n}\r\n\r\nvoid DiabloDeath(Monster &diablo, bool sendmsg)\r\n{\r\n\tPlaySFX(SfxID::DiabloDeath);\r\n\tauto &quest = Quests[Q_DIABLO];\r\n\tquest._qactive = QUEST_DONE;\r\n\tif (sendmsg)\r\n\t\tNetSendCmdQuest(true, quest);\r\n\tsgbSaveSoundOn = gbSoundOn;\r\n\tgbProcessPlayers = false;\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst int monsterId = ActiveMonsters[i];\r\n\t\tMonster &monster = Monsters[monsterId];\r\n\t\tif (monster.type().type == MT_DIABLO || diablo.activeForTicks == 0)\r\n\t\t\tcontinue;\r\n\r\n\t\tNewMonsterAnim(monster, MonsterGraphic::Death, monster.direction);\r\n\t\tmonster.mode = MonsterMode::Death;\r\n\t\tmonster.var1 = 0;\r\n\t\tmonster.position.tile = monster.position.old;\r\n\t\tmonster.position.future = monster.position.tile;\r\n\t\tM_ClearSquares(monster);\r\n\t\tmonster.occupyTile(monster.position.tile, false);\r\n\t}\r\n\tAddLight(diablo.position.tile, 8);\r\n\tDoVision(diablo.position.tile, 8, MAP_EXP_NONE, true);\r\n\tint dist = diablo.position.tile.WalkingDistance(ViewPosition);\r\n\tdist = std::min(dist, 20);\r\n\tdiablo.var3 = ViewPosition.x << 16;\r\n\tdiablo.position.temp.x = ViewPosition.y << 16;\r\n\tdiablo.position.temp.y = (int)((diablo.var3 - (diablo.position.tile.x << 16)) / (float)dist);\r\n\tif (!gbIsMultiplayer) {\r\n\t\tPlayer &myPlayer = *MyPlayer;\r\n\t\tmyPlayer.pDiabloKillLevel = std::max(myPlayer.pDiabloKillLevel, static_cast<uint8_t>(sgGameInitInfo.nDifficulty + 1));\r\n\t}\r\n}\r\n\r\nvoid SpawnLoot(Monster &monster, bool sendmsg)\r\n{\r\n\tif (monster.type().type == MT_HORKSPWN) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (Quests[Q_GARBUD].IsAvailable() && monster.uniqueType == UniqueMonsterType::Garbud) {\r\n\t\tCreateTypeItem(monster.position.tile + Displacement { 1, 1 }, true, ItemType::Mace, IMISC_NONE, sendmsg, false);\r\n\t} else if (monster.uniqueType == UniqueMonsterType::Defiler) {\r\n\t\tif (effect_is_playing(SfxID::Defiler8))\r\n\t\t\tstream_stop();\r\n\t\tSpawnMapOfDoom(monster.position.tile, sendmsg);\r\n\t\tQuests[Q_DEFILER]._qactive = QUEST_DONE;\r\n\t\tNetSendCmdQuest(true, Quests[Q_DEFILER]);\r\n\t} else if (monster.uniqueType == UniqueMonsterType::HorkDemon) {\r\n\t\tif (sgGameInitInfo.bTheoQuest != 0) {\r\n\t\t\tSpawnTheodore(monster.position.tile, sendmsg);\r\n\t\t} else {\r\n\t\t\tCreateAmulet(monster.position.tile, 13, sendmsg, false);\r\n\t\t}\r\n\t} else if (monster.type().type == MT_NAKRUL) {\r\n\t\tSfxID nSFX = IsUberRoomOpened ? SfxID::NaKrul4 : SfxID::NaKrul5;\r\n\t\tif (sgGameInitInfo.bCowQuest != 0)\r\n\t\t\tnSFX = SfxID::NaKrul6;\r\n\t\tif (effect_is_playing(nSFX))\r\n\t\t\tstream_stop();\r\n\t\tUberDiabloMonsterIndex = -2;\r\n\t\tCreateMagicWeapon(monster.position.tile, ItemType::Sword, ICURS_GREAT_SWORD, sendmsg, false);\r\n\t\tCreateMagicWeapon(monster.position.tile, ItemType::Staff, ICURS_WAR_STAFF, sendmsg, false);\r\n\t\tCreateMagicWeapon(monster.position.tile, ItemType::Bow, ICURS_LONG_WAR_BOW, sendmsg, false);\r\n\t\tCreateSpellBook(monster.position.tile, SpellID::Apocalypse, sendmsg, false);\r\n\t} else if (!monster.isPlayerMinion()) {\r\n\t\tSpawnItem(monster, monster.position.tile, sendmsg);\r\n\t}\r\n}\r\n\r\nstd::optional<Point> GetTeleportTile(const Monster &monster)\r\n{\r\n\tconst int mx = monster.enemyPosition.x;\r\n\tconst int my = monster.enemyPosition.y;\r\n\tconst int rx = PickRandomlyAmong({ -1, 1 });\r\n\tconst int ry = PickRandomlyAmong({ -1, 1 });\r\n\r\n\tfor (int j = -1; j <= 1; j++) {\r\n\t\tfor (int k = -1; k < 1; k++) {\r\n\t\t\tif (j == 0 && k == 0)\r\n\t\t\t\tcontinue;\r\n\t\t\tconst int x = mx + (rx * j);\r\n\t\t\tconst int y = my + (ry * k);\r\n\t\t\tif (!InDungeonBounds({ x, y }) || x == monster.position.tile.x || y == monster.position.tile.y)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (IsTileAvailable(monster, { x, y }))\r\n\t\t\t\treturn Point { x, y };\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid Teleport(Monster &monster)\r\n{\r\n\tif (monster.mode == MonsterMode::Petrified)\r\n\t\treturn;\r\n\r\n\tstd::optional<Point> position = GetTeleportTile(monster);\r\n\tif (!position)\r\n\t\treturn;\r\n\r\n\tM_ClearSquares(monster);\r\n\tdMonster[monster.position.tile.x][monster.position.tile.y] = 0;\r\n\tmonster.occupyTile(*position, false);\r\n\tmonster.position.old = *position;\r\n\tmonster.direction = GetMonsterDirection(monster);\r\n\tChangeLightXY(monster.lightId, *position);\r\n}\r\n\r\nbool IsHardHit(Monster &target, unsigned dam)\r\n{\r\n\tswitch (target.type().type) {\r\n\tcase MT_SNEAK:\r\n\tcase MT_STALKER:\r\n\tcase MT_UNSEEN:\r\n\tcase MT_ILLWEAV:\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn (dam >> 6) >= target.level(sgGameInitInfo.nDifficulty) + 3;\r\n\t}\r\n}\r\n\r\nvoid MonsterHitMonster(Monster &attacker, Monster &target, int dam)\r\n{\r\n\tif (IsHardHit(target, dam)) {\r\n\t\ttarget.direction = Opposite(attacker.direction);\r\n\t}\r\n\r\n\tM_StartHit(target, dam);\r\n}\r\n\r\nvoid StartDeathFromMonster(Monster &attacker, Monster &target)\r\n{\r\n\tconst Direction md = GetDirection(target.position.tile, attacker.position.tile);\r\n\tMonsterDeath(target, md, true);\r\n\r\n\tif (gbIsHellfire)\r\n\t\tM_StartStand(attacker, attacker.direction);\r\n}\r\n\r\nvoid StartFadein(Monster &monster, Direction md, bool backwards)\r\n{\r\n\tNewMonsterAnim(monster, MonsterGraphic::Special, md);\r\n\tmonster.mode = MonsterMode::FadeIn;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n\tmonster.flags &= ~MFLAG_HIDDEN;\r\n\tif (backwards) {\r\n\t\tmonster.flags |= MFLAG_LOCK_ANIMATION;\r\n\t\tmonster.animInfo.currentFrame = monster.animInfo.numberOfFrames - 1;\r\n\t}\r\n}\r\n\r\nvoid StartFadeout(Monster &monster, Direction md, bool backwards)\r\n{\r\n\tNewMonsterAnim(monster, MonsterGraphic::Special, md);\r\n\tmonster.mode = MonsterMode::FadeOut;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n\tif (backwards) {\r\n\t\tmonster.flags |= MFLAG_LOCK_ANIMATION;\r\n\t\tmonster.animInfo.currentFrame = monster.animInfo.numberOfFrames - 1;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Starts the monster healing procedure.\r\n *\r\n * The monster will be healed between 1.47% and 25% of its max HP. The healing amount is stored in _mVar1.\r\n *\r\n * This is only used by Gargoyles.\r\n *\r\n * @param monster The monster that will be healed.\r\n */\r\nvoid StartHeal(Monster &monster)\r\n{\r\n\tmonster.changeAnimationData(MonsterGraphic::Special);\r\n\tmonster.animInfo.currentFrame = monster.type().getAnimData(MonsterGraphic::Special).frames - 1;\r\n\tmonster.flags |= MFLAG_LOCK_ANIMATION;\r\n\tmonster.mode = MonsterMode::Heal;\r\n\tmonster.var1 = monster.maxHitPoints / (16 * (GenerateRnd(5) + 4));\r\n}\r\n\r\nvoid SyncLightPosition(Monster &monster)\r\n{\r\n\tif (monster.lightId == NO_LIGHT)\r\n\t\treturn;\r\n\r\n\tconst WorldTileDisplacement offset = monster.isWalking() ? monster.position.CalculateWalkingOffset(monster.direction, monster.animInfo) : WorldTileDisplacement {};\r\n\tChangeLightOffset(monster.lightId, offset.screenToLight());\r\n}\r\n\r\nvoid MonsterIdle(Monster &monster)\r\n{\r\n\tif (monster.type().type == MT_GOLEM)\r\n\t\tmonster.changeAnimationData(MonsterGraphic::Walk);\r\n\telse\r\n\t\tmonster.changeAnimationData(MonsterGraphic::Stand);\r\n\r\n\tif (monster.animInfo.isLastFrame())\r\n\t\tUpdateEnemy(monster);\r\n\r\n\tif (monster.var2 < std::numeric_limits<int16_t>::max())\r\n\t\tmonster.var2++;\r\n}\r\n\r\n/**\r\n * @brief Continue movement towards new tile\r\n */\r\nbool MonsterWalk(Monster &monster)\r\n{\r\n\t// Check if we reached new tile\r\n\tconst bool isAnimationEnd = monster.animInfo.isLastFrame();\r\n\tif (isAnimationEnd) {\r\n\t\tdMonster[monster.position.tile.x][monster.position.tile.y] = 0;\r\n\t\tmonster.position.tile.x += monster.var1;\r\n\t\tmonster.position.tile.y += monster.var2;\r\n\t\t// dMonster is set here for backwards compatibility; without it, the monster would be invisible if loaded from a vanilla save.\r\n\t\tmonster.occupyTile(monster.position.tile, false);\r\n\t\tChangeLightXY(monster.lightId, monster.position.tile);\r\n\t\tM_StartStand(monster, monster.direction);\r\n\t} else { // We didn't reach new tile so update monster's \"sub-tile\" position\r\n\t\tif (monster.animInfo.tickCounterOfCurrentFrame == 0) {\r\n\t\t\tif (monster.animInfo.currentFrame == 0 && monster.type().type == MT_FLESTHNG)\r\n\t\t\t\tPlayEffect(monster, MonsterSound::Special);\r\n\t\t}\r\n\t}\r\n\r\n\tSyncLightPosition(monster);\r\n\r\n\treturn isAnimationEnd;\r\n}\r\n\r\nvoid MonsterAttackMonster(Monster &attacker, Monster &target, int hper, int mind, int maxd)\r\n{\r\n\tif (!target.isPossibleToHit())\r\n\t\treturn;\r\n\r\n\tint hit = GenerateRnd(100);\r\n\tif (target.mode == MonsterMode::Petrified)\r\n\t\thit = 0;\r\n\tif (target.tryLiftGargoyle())\r\n\t\treturn;\r\n\tif (hit >= hper)\r\n\t\treturn;\r\n\r\n\tconst int dam = RandomIntBetween(mind, maxd) << 6;\r\n\tApplyMonsterDamage(DamageType::Physical, target, dam);\r\n\r\n\tif (attacker.isPlayerMinion()) {\r\n\t\tconst auto playerId = static_cast<size_t>(attacker.goalVar3);\r\n\t\tconst Player &player = Players[playerId];\r\n\t\ttarget.tag(player);\r\n\t}\r\n\r\n\tif (target.hasNoLife()) {\r\n\t\tStartDeathFromMonster(attacker, target);\r\n\t} else {\r\n\t\tMonsterHitMonster(attacker, target, dam);\r\n\t}\r\n\r\n\tif (target.activeForTicks == 0) {\r\n\t\ttarget.activeForTicks = UINT8_MAX;\r\n\t\ttarget.position.last = attacker.position.tile;\r\n\t}\r\n}\r\n\r\nint CheckReflect(Monster &monster, Player &player, int dam)\r\n{\r\n\tplayer.wReflections--;\r\n\tif (player.wReflections <= 0)\r\n\t\tNetSendCmdParam1(true, CMD_SETREFLECT, 0);\r\n\t// reflects 20-30% damage\r\n\tconst int mdam = dam * RandomIntBetween(20, 30, true) / 100;\r\n\tApplyMonsterDamage(DamageType::Physical, monster, mdam);\r\n\tif (monster.hasNoLife())\r\n\t\tM_StartKill(monster, player);\r\n\telse\r\n\t\tM_StartHit(monster, player, mdam);\r\n\r\n\treturn mdam;\r\n}\r\n\r\nint GetMinHit()\r\n{\r\n\tswitch (currlevel) {\r\n\tcase 16:\r\n\t\treturn 30;\r\n\tcase 15:\r\n\t\treturn 25;\r\n\tcase 14:\r\n\t\treturn 20;\r\n\tdefault:\r\n\t\treturn 15;\r\n\t}\r\n}\r\n\r\nvoid MonsterAttackPlayer(Monster &monster, Player &player, int hit, int minDam, int maxDam)\r\n{\r\n\tif (player.hasNoLife() || player._pInvincible || HasAnyOf(player._pSpellFlags, SpellFlag::Etherealize))\r\n\t\treturn;\r\n\tif (monster.position.tile.WalkingDistance(player.position.tile) >= 2)\r\n\t\treturn;\r\n\r\n\tint hper = GenerateRnd(100);\r\n#ifdef _DEBUG\r\n\tif (DebugGodMode)\r\n\t\thper = 1000;\r\n#endif\r\n\tint ac = player.GetArmor();\r\n\tif (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::ACAgainstDemons) && monster.data().monsterClass == MonsterClass::Demon)\r\n\t\tac += 40;\r\n\tif (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::ACAgainstUndead) && monster.data().monsterClass == MonsterClass::Undead)\r\n\t\tac += 20;\r\n\thit += 2 * (monster.level(sgGameInitInfo.nDifficulty) - player.getCharacterLevel())\r\n\t    + 30\r\n\t    - ac;\r\n\tconst int minhit = GetMinHit();\r\n\thit = std::max(hit, minhit);\r\n\tint blkper = 100;\r\n\tif ((player._pmode == PM_STAND || player._pmode == PM_ATTACK) && player._pBlockFlag) {\r\n\t\tblkper = GenerateRnd(100);\r\n\t}\r\n\tint blk = player.GetBlockChance() - (monster.level(sgGameInitInfo.nDifficulty) * 2);\r\n\tblk = std::clamp(blk, 0, 100);\r\n\tif (hper >= hit)\r\n\t\treturn;\r\n\tif (blkper < blk) {\r\n\t\tconst Direction dir = GetDirection(player.position.tile, monster.position.tile);\r\n\t\tStartPlrBlock(player, dir);\r\n\t\tif (&player == MyPlayer && player.wReflections > 0) {\r\n\t\t\tint dam = GenerateRnd(((maxDam - minDam) << 6) + 1) + (minDam << 6);\r\n\t\t\tdam = std::max(dam + (player._pIGetHit << 6), 64);\r\n\t\t\tCheckReflect(monster, player, dam);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tMonsterReducePlayerAttribute(monster, player);\r\n\r\n\t// New method fixes a bug which caused the maximum possible damage value to be 63/64ths too low.\r\n\tint dam = RandomIntBetween(minDam << 6, maxDam << 6);\r\n\tdam = std::max(dam + (player._pIGetHit << 6), 64);\r\n\tif (&player == MyPlayer) {\r\n\t\tif (player.wReflections > 0) {\r\n\t\t\tconst int reflectedDamage = CheckReflect(monster, player, dam);\r\n\t\t\tdam = std::max(dam - reflectedDamage, 0);\r\n\t\t}\r\n\t\tApplyPlrDamage(DamageType::Physical, player, 0, 0, dam);\r\n\t}\r\n\r\n\t// Reflect can also kill a monster, so make sure the monster is still alive\r\n\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::Thorns) && monster.mode != MonsterMode::Death) {\r\n\t\tconst int mdam = (GenerateRnd(3) + 1) << 6;\r\n\t\tApplyMonsterDamage(DamageType::Physical, monster, mdam);\r\n\t\tif (monster.hasNoLife())\r\n\t\t\tM_StartKill(monster, player);\r\n\t\telse\r\n\t\t\tM_StartHit(monster, player, mdam);\r\n\t}\r\n\r\n\tif ((monster.flags & MFLAG_NOLIFESTEAL) == 0 && monster.type().type == MT_SKING && gbIsMultiplayer)\r\n\t\tmonster.hitPoints += dam;\r\n\tif (player.hasNoLife()) {\r\n\t\tif (gbIsHellfire)\r\n\t\t\tM_StartStand(monster, monster.direction);\r\n\t\treturn;\r\n\t}\r\n\tStartPlrHit(player, dam, false);\r\n\tif ((monster.flags & MFLAG_KNOCKBACK) != 0) {\r\n\t\tif (player._pmode != PM_GOTHIT)\r\n\t\t\tStartPlrHit(player, 0, true);\r\n\r\n\t\tconst Point newPosition = player.position.tile + monster.direction;\r\n\t\tif (PosOkPlayer(player, newPosition)) {\r\n\t\t\tplayer.position.tile = newPosition;\r\n\t\t\tFixPlayerLocation(player, player._pdir);\r\n\t\t\tFixPlrWalkTags(player);\r\n\t\t\tplayer.occupyTile(newPosition, false);\r\n\t\t\tSetPlayerOld(player);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MonsterAttackEnemy(Monster &monster, int hit, int minDam, int maxDam)\r\n{\r\n\tif ((monster.flags & MFLAG_NO_ENEMY) == 0) {\r\n\t\tif ((monster.flags & MFLAG_TARGETS_MONSTER) != 0)\r\n\t\t\tMonsterAttackMonster(monster, Monsters[monster.enemy], hit, minDam, maxDam);\r\n\t\telse\r\n\t\t\tMonsterAttackPlayer(monster, Players[monster.enemy], hit, minDam, maxDam);\r\n\t}\r\n}\r\n\r\nbool MonsterAttack(Monster &monster)\r\n{\r\n\tif (monster.animInfo.currentFrame == monster.data().animFrameNum - 1) {\r\n\t\tMonsterAttackEnemy(monster, monster.toHit(sgGameInitInfo.nDifficulty), monster.minDamage, monster.maxDamage);\r\n\t\tif (monster.ai != MonsterAIID::Snake)\r\n\t\t\tPlayEffect(monster, MonsterSound::Attack);\r\n\t}\r\n\tif (IsAnyOf(monster.type().type, MT_NMAGMA, MT_YMAGMA, MT_BMAGMA, MT_WMAGMA) && monster.animInfo.currentFrame == 8) {\r\n\t\tMonsterAttackEnemy(monster, monster.toHit(sgGameInitInfo.nDifficulty) + 10, monster.minDamage - 2, monster.maxDamage - 2);\r\n\r\n\t\tPlayEffect(monster, MonsterSound::Attack);\r\n\t}\r\n\tif (IsAnyOf(monster.type().type, MT_STORM, MT_RSTORM, MT_STORML, MT_MAEL) && monster.animInfo.currentFrame == 12) {\r\n\t\tMonsterAttackEnemy(monster, monster.toHit(sgGameInitInfo.nDifficulty) - 20, monster.minDamage + 4, monster.maxDamage + 4);\r\n\r\n\t\tPlayEffect(monster, MonsterSound::Attack);\r\n\t}\r\n\tif (monster.ai == MonsterAIID::Snake && monster.animInfo.currentFrame == 0)\r\n\t\tPlayEffect(monster, MonsterSound::Attack);\r\n\tif (monster.animInfo.isLastFrame()) {\r\n\t\tM_StartStand(monster, monster.direction);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool MonsterRangedAttack(Monster &monster)\r\n{\r\n\tif (monster.animInfo.currentFrame == monster.data().animFrameNum - 1) {\r\n\t\tconst auto &missileType = static_cast<MissileID>(monster.var1);\r\n\t\tif (missileType != MissileID::Null) {\r\n\t\t\tint multimissiles = 1;\r\n\t\t\tif (missileType == MissileID::ChargedBolt)\r\n\t\t\t\tmultimissiles = 3;\r\n\t\t\tfor (int mi = 0; mi < multimissiles; mi++) {\r\n\t\t\t\tAddMissile(\r\n\t\t\t\t    monster.position.tile,\r\n\t\t\t\t    monster.enemyPosition,\r\n\t\t\t\t    monster.direction,\r\n\t\t\t\t    missileType,\r\n\t\t\t\t    TARGET_PLAYERS,\r\n\t\t\t\t    monster,\r\n\t\t\t\t    monster.var2,\r\n\t\t\t\t    0);\r\n\t\t\t}\r\n\t\t}\r\n\t\tPlayEffect(monster, MonsterSound::Attack);\r\n\t}\r\n\r\n\tif (monster.animInfo.isLastFrame()) {\r\n\t\tM_StartStand(monster, monster.direction);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool MonsterRangedSpecialAttack(Monster &monster)\r\n{\r\n\tif (monster.animInfo.currentFrame == monster.data().animFrameNumSpecial - 1 && monster.animInfo.tickCounterOfCurrentFrame == 0 && (monster.ai != MonsterAIID::Mega || monster.var2 == 0)) {\r\n\t\tif (AddMissile(\r\n\t\t        monster.position.tile,\r\n\t\t        monster.enemyPosition,\r\n\t\t        monster.direction,\r\n\t\t        static_cast<MissileID>(monster.var1),\r\n\t\t        TARGET_PLAYERS,\r\n\t\t        monster,\r\n\t\t        monster.var3,\r\n\t\t        0)\r\n\t\t    != nullptr) {\r\n\t\t\tPlayEffect(monster, MonsterSound::Special);\r\n\t\t}\r\n\t}\r\n\r\n\tif (monster.ai == MonsterAIID::Mega && monster.animInfo.currentFrame == monster.data().animFrameNumSpecial - 1) {\r\n\t\tif (monster.var2++ == 0) {\r\n\t\t\tmonster.flags |= MFLAG_ALLOW_SPECIAL;\r\n\t\t} else if (monster.var2 == 15) {\r\n\t\t\tmonster.flags &= ~MFLAG_ALLOW_SPECIAL;\r\n\t\t}\r\n\t}\r\n\r\n\tif (monster.animInfo.isLastFrame()) {\r\n\t\tM_StartStand(monster, monster.direction);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool MonsterSpecialAttack(Monster &monster)\r\n{\r\n\tif (monster.animInfo.currentFrame == monster.data().animFrameNumSpecial - 1) {\r\n\t\tMonsterAttackEnemy(monster, monster.toHitSpecial(sgGameInitInfo.nDifficulty), monster.minDamageSpecial, monster.maxDamageSpecial);\r\n\t}\r\n\r\n\tif (monster.animInfo.isLastFrame()) {\r\n\t\tM_StartStand(monster, monster.direction);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool MonsterFadein(Monster &monster)\r\n{\r\n\tif (((monster.flags & MFLAG_LOCK_ANIMATION) == 0 || monster.animInfo.currentFrame != 0)\r\n\t    && ((monster.flags & MFLAG_LOCK_ANIMATION) != 0 || monster.animInfo.currentFrame != monster.animInfo.numberOfFrames - 1)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tM_StartStand(monster, monster.direction);\r\n\tmonster.flags &= ~MFLAG_LOCK_ANIMATION;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool MonsterFadeout(Monster &monster)\r\n{\r\n\tif (((monster.flags & MFLAG_LOCK_ANIMATION) == 0 || monster.animInfo.currentFrame != 0)\r\n\t    && ((monster.flags & MFLAG_LOCK_ANIMATION) != 0 || monster.animInfo.currentFrame != monster.animInfo.numberOfFrames - 1)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tmonster.flags &= ~MFLAG_LOCK_ANIMATION;\r\n\tmonster.flags |= MFLAG_HIDDEN;\r\n\r\n\tM_StartStand(monster, monster.direction);\r\n\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * @brief Applies the healing effect on the monster.\r\n *\r\n * This is triggered by StartHeal()\r\n *\r\n * @param monster The monster that will be healed.\r\n * @return\r\n */\r\nvoid MonsterHeal(Monster &monster)\r\n{\r\n\tif (monster.animInfo.currentFrame == 0) {\r\n\t\tmonster.flags &= ~MFLAG_LOCK_ANIMATION;\r\n\t\tmonster.flags |= MFLAG_ALLOW_SPECIAL;\r\n\t\tif (monster.var1 + monster.hitPoints < monster.maxHitPoints) {\r\n\t\t\tmonster.hitPoints = monster.var1 + monster.hitPoints;\r\n\t\t} else {\r\n\t\t\tmonster.hitPoints = monster.maxHitPoints;\r\n\t\t\tmonster.flags &= ~MFLAG_ALLOW_SPECIAL;\r\n\t\t\tmonster.mode = MonsterMode::SpecialMeleeAttack;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MonsterTalk(Monster &monster)\r\n{\r\n\tM_StartStand(monster, monster.direction);\r\n\tmonster.goal = MonsterGoal::Talking;\r\n\tif (effect_is_playing(Speeches[monster.talkMsg].sfxnr))\r\n\t\treturn;\r\n\tInitQTextMsg(monster.talkMsg);\r\n\tif (monster.uniqueType == UniqueMonsterType::SnotSpill) {\r\n\t\tif (monster.talkMsg == TEXT_BANNER10 && (monster.flags & MFLAG_QUEST_COMPLETE) == 0) {\r\n\t\t\tObjChangeMap(SetPiece.position.x, SetPiece.position.y, SetPiece.position.x + (SetPiece.size.width / 2) + 2, SetPiece.position.y + (SetPiece.size.height / 2) - 2);\r\n\t\t\tauto tren = TransVal;\r\n\t\t\tTransVal = 9;\r\n\t\t\tDRLG_MRectTrans({ SetPiece.position, WorldTileSize((SetPiece.size.width / 2) + 4, SetPiece.size.height / 2) });\r\n\t\t\tTransVal = tren;\r\n\t\t\tQuests[Q_LTBANNER]._qvar1 = 2;\r\n\t\t\tif (Quests[Q_LTBANNER]._qactive == QUEST_INIT)\r\n\t\t\t\tQuests[Q_LTBANNER]._qactive = QUEST_ACTIVE;\r\n\t\t\tmonster.flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_LTBANNER]);\r\n\t\t}\r\n\t\tif (Quests[Q_LTBANNER]._qvar1 < 2) {\r\n\t\t\tapp_fatal(StrCat(\"SS Talk = \", monster.talkMsg, \", Flags = \", monster.flags));\r\n\t\t}\r\n\t}\r\n\tif (monster.uniqueType == UniqueMonsterType::Lachdan) {\r\n\t\tif (monster.talkMsg == TEXT_VEIL9) {\r\n\t\t\tQuests[Q_VEIL]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_VEIL]._qlog = true;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_VEIL]);\r\n\t\t}\r\n\t}\r\n\tif (monster.uniqueType == UniqueMonsterType::WarlordOfBlood) {\r\n\t\tQuests[Q_WARLORD]._qvar1 = QS_WARLORD_TALKING;\r\n\t\tNetSendCmdQuest(true, Quests[Q_WARLORD]);\r\n\t}\r\n\tif (monster.uniqueType == UniqueMonsterType::Lazarus && UseMultiplayerQuests()) {\r\n\t\tQuests[Q_BETRAYER]._qvar1 = 6;\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\tmonster.talkMsg = TEXT_NONE;\r\n\t}\r\n}\r\n\r\nbool MonsterGotHit(Monster &monster)\r\n{\r\n\tif (monster.animInfo.isLastFrame()) {\r\n\t\tM_StartStand(monster, monster.direction);\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid ReleaseMinions(const Monster &leader)\r\n{\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tMonster &minion = Monsters[ActiveMonsters[i]];\r\n\t\tif (minion.leaderRelation == LeaderRelation::Leashed && minion.getLeader() == &leader) {\r\n\t\t\tminion.setLeader(nullptr);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ShrinkLeaderPacksize(const Monster &monster)\r\n{\r\n\tif (monster.leaderRelation == LeaderRelation::Leashed) {\r\n\t\tmonster.getLeader()->packSize--;\r\n\t}\r\n}\r\n\r\nvoid MonsterDeath(Monster &monster)\r\n{\r\n\tmonster.var1++;\r\n\tif (monster.type().type == MT_DIABLO) {\r\n\t\tif (monster.position.tile.x < ViewPosition.x) {\r\n\t\t\tViewPosition.x--;\r\n\t\t} else if (monster.position.tile.x > ViewPosition.x) {\r\n\t\t\tViewPosition.x++;\r\n\t\t}\r\n\r\n\t\tif (monster.position.tile.y < ViewPosition.y) {\r\n\t\t\tViewPosition.y--;\r\n\t\t} else if (monster.position.tile.y > ViewPosition.y) {\r\n\t\t\tViewPosition.y++;\r\n\t\t}\r\n\r\n\t\tif (monster.var1 == 140)\r\n\t\t\tPrepDoEnding();\r\n\t} else if (monster.animInfo.isLastFrame()) {\r\n\t\tif (monster.isUnique())\r\n\t\t\tAddCorpse(monster.position.tile, monster.corpseId, monster.direction);\r\n\t\telse\r\n\t\t\tAddCorpse(monster.position.tile, monster.type().corpseId, monster.direction);\r\n\r\n\t\tdMonster[monster.position.tile.x][monster.position.tile.y] = 0;\r\n\t\tmonster.isInvalid = true;\r\n\r\n\t\tM_UpdateRelations(monster);\r\n\t}\r\n}\r\n\r\nbool MonsterSpecialStand(Monster &monster)\r\n{\r\n\tif (monster.animInfo.currentFrame == monster.data().animFrameNumSpecial - 1)\r\n\t\tPlayEffect(monster, MonsterSound::Special);\r\n\r\n\tif (monster.animInfo.isLastFrame()) {\r\n\t\tM_StartStand(monster, monster.direction);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool MonsterDelay(Monster &monster)\r\n{\r\n\tmonster.changeAnimationData(MonsterGraphic::Stand, GetMonsterDirection(monster));\r\n\tif (monster.ai == MonsterAIID::Lazarus) {\r\n\t\tif (monster.var2 > 8 || monster.var2 < 0)\r\n\t\t\tmonster.var2 = 8;\r\n\t}\r\n\r\n\tif (monster.var2-- == 0) {\r\n\t\tconst int oFrame = monster.animInfo.currentFrame;\r\n\t\tM_StartStand(monster, monster.direction);\r\n\t\tmonster.animInfo.currentFrame = oFrame;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid MonsterPetrified(Monster &monster)\r\n{\r\n\tif (monster.hitPoints <= 0) {\r\n\t\tdMonster[monster.position.tile.x][monster.position.tile.y] = 0;\r\n\t\tmonster.isInvalid = true;\r\n\t}\r\n}\r\n\r\nstd::optional<size_t> GetRandomSkeletonTypeIndex()\r\n{\r\n\tint32_t typeCount = 0;\r\n\tsize_t skeletonIndexes[SkeletonTypes.size()];\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\tif (IsSkel(LevelMonsterTypes[i].type)) {\r\n\t\t\tskeletonIndexes[typeCount++] = i;\r\n\t\t}\r\n\t}\r\n\r\n\tif (typeCount == 0) {\r\n\t\treturn {};\r\n\t}\r\n\r\n\tconst size_t typeIndex = skeletonIndexes[GenerateRnd(typeCount)];\r\n\treturn typeIndex;\r\n}\r\n\r\nMonster *AddSkeleton(Point position, Direction dir, bool inMap)\r\n{\r\n\tauto typeIndex = GetRandomSkeletonTypeIndex();\r\n\tif (!typeIndex)\r\n\t\treturn nullptr;\r\n\r\n\treturn AddMonster(position, dir, *typeIndex, inMap);\r\n}\r\n\r\nbool LineClear(tl::function_ref<bool(Point)> clear, Point startPoint, Point endPoint)\r\n{\r\n\tPoint position = startPoint;\r\n\r\n\tint dx = endPoint.x - position.x;\r\n\tint dy = endPoint.y - position.y;\r\n\tif (std::abs(dx) > std::abs(dy)) {\r\n\t\tif (dx < 0) {\r\n\t\t\tstd::swap(position, endPoint);\r\n\t\t\tdx = -dx;\r\n\t\t\tdy = -dy;\r\n\t\t}\r\n\t\tint d;\r\n\t\tint yincD;\r\n\t\tint dincD;\r\n\t\tint dincH;\r\n\t\tif (dy > 0) {\r\n\t\t\td = 2 * dy - dx;\r\n\t\t\tdincD = 2 * dy;\r\n\t\t\tdincH = 2 * (dy - dx);\r\n\t\t\tyincD = 1;\r\n\t\t} else {\r\n\t\t\td = 2 * dy + dx;\r\n\t\t\tdincD = 2 * dy;\r\n\t\t\tdincH = 2 * (dx + dy);\r\n\t\t\tyincD = -1;\r\n\t\t}\r\n\t\tbool done = false;\r\n\t\twhile (!done && position != endPoint) {\r\n\t\t\tif ((d <= 0) ^ (yincD < 0)) {\r\n\t\t\t\td += dincD;\r\n\t\t\t} else {\r\n\t\t\t\td += dincH;\r\n\t\t\t\tposition.y += yincD;\r\n\t\t\t}\r\n\t\t\tposition.x++;\r\n\t\t\tdone = position != startPoint && !clear(position);\r\n\t\t}\r\n\t} else {\r\n\t\tif (dy < 0) {\r\n\t\t\tstd::swap(position, endPoint);\r\n\t\t\tdy = -dy;\r\n\t\t\tdx = -dx;\r\n\t\t}\r\n\t\tint d;\r\n\t\tint xincD;\r\n\t\tint dincD;\r\n\t\tint dincH;\r\n\t\tif (dx > 0) {\r\n\t\t\td = 2 * dx - dy;\r\n\t\t\tdincD = 2 * dx;\r\n\t\t\tdincH = 2 * (dx - dy);\r\n\t\t\txincD = 1;\r\n\t\t} else {\r\n\t\t\td = 2 * dx + dy;\r\n\t\t\tdincD = 2 * dx;\r\n\t\t\tdincH = 2 * (dy + dx);\r\n\t\t\txincD = -1;\r\n\t\t}\r\n\t\tbool done = false;\r\n\t\twhile (!done && position != endPoint) {\r\n\t\t\tif ((d <= 0) ^ (xincD < 0)) {\r\n\t\t\t\td += dincD;\r\n\t\t\t} else {\r\n\t\t\t\td += dincH;\r\n\t\t\t\tposition.x += xincD;\r\n\t\t\t}\r\n\t\t\tposition.y++;\r\n\t\t\tdone = position != startPoint && !clear(position);\r\n\t\t}\r\n\t}\r\n\treturn position == endPoint;\r\n}\r\n\r\nbool IsLineNotSolid(Point startPoint, Point endPoint)\r\n{\r\n\treturn LineClear(IsTileNotSolid, startPoint, endPoint);\r\n}\r\n\r\nvoid FollowTheLeader(Monster &monster)\r\n{\r\n\tif (monster.leaderRelation != LeaderRelation::Leashed)\r\n\t\treturn;\r\n\r\n\tMonster *leader = monster.getLeader();\r\n\tif (leader == nullptr)\r\n\t\treturn;\r\n\r\n\tif (leader->activeForTicks > monster.activeForTicks) {\r\n\t\tmonster.position.last = leader->position.tile;\r\n\t\tmonster.activeForTicks = leader->activeForTicks - 1;\r\n\t}\r\n\r\n\tif (monster.ai != MonsterAIID::Gargoyle || (monster.flags & MFLAG_ALLOW_SPECIAL) == 0)\r\n\t\treturn;\r\n\tif (leader->mode == MonsterMode::SpecialMeleeAttack)\r\n\t\treturn;\r\n\tmonster.flags &= ~MFLAG_ALLOW_SPECIAL;\r\n\tmonster.mode = MonsterMode::SpecialMeleeAttack;\r\n}\r\n\r\nvoid GroupUnity(Monster &monster)\r\n{\r\n\tif (monster.leaderRelation == LeaderRelation::None)\r\n\t\treturn;\r\n\r\n\t// No unique monster would be a minion of someone else!\r\n\tassert(!monster.isUnique());\r\n\r\n\t// Someone with a leaderRelation should have a leader, if we end up trying to access a nullptr then the relation was already broken...\r\n\r\n\tauto &leader = *monster.getLeader();\r\n\tif (IsLineNotSolid(monster.position.tile, leader.position.future)) {\r\n\t\tif (monster.leaderRelation == LeaderRelation::Separated\r\n\t\t    && monster.position.tile.WalkingDistance(leader.position.future) < 4) {\r\n\t\t\t// Reunite the separated monster with the pack\r\n\t\t\tleader.packSize++;\r\n\t\t\tmonster.leaderRelation = LeaderRelation::Leashed;\r\n\t\t}\r\n\t} else if (monster.leaderRelation == LeaderRelation::Leashed) {\r\n\t\tleader.packSize--;\r\n\t\tmonster.leaderRelation = LeaderRelation::Separated;\r\n\t}\r\n\r\n\tif (monster.leaderRelation == LeaderRelation::Leashed) {\r\n\t\tif (monster.activeForTicks > leader.activeForTicks) {\r\n\t\t\tleader.position.last = monster.position.tile;\r\n\t\t\tleader.activeForTicks = monster.activeForTicks - 1;\r\n\t\t}\r\n\t\tif (leader.ai == MonsterAIID::Gargoyle && (leader.flags & MFLAG_ALLOW_SPECIAL) != 0) {\r\n\t\t\tleader.flags &= ~MFLAG_ALLOW_SPECIAL;\r\n\t\t\tleader.mode = MonsterMode::SpecialMeleeAttack;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool RandomWalk(Monster &monster, Direction md)\r\n{\r\n\tconst Direction mdtemp = md;\r\n\r\n\tbool ok = DirOK(monster, md);\r\n\tif (FlipCoin())\r\n\t\tok = ok || (md = Right(mdtemp), DirOK(monster, md)) || (md = Left(mdtemp), DirOK(monster, md));\r\n\telse\r\n\t\tok = ok || (md = Left(mdtemp), DirOK(monster, md)) || (md = Right(mdtemp), DirOK(monster, md));\r\n\tif (FlipCoin()) {\r\n\t\tok = ok\r\n\t\t    || (md = Left(Left(mdtemp)), DirOK(monster, md))\r\n\t\t    || (md = Right(Right(mdtemp)), DirOK(monster, md));\r\n\t} else {\r\n\t\tok = ok\r\n\t\t    || (md = Right(Right(mdtemp)), DirOK(monster, md))\r\n\t\t    || (md = Left(Left(mdtemp)), DirOK(monster, md));\r\n\t}\r\n\tif (ok)\r\n\t\tWalk(monster, md);\r\n\treturn ok;\r\n}\r\n\r\nbool RandomWalk2(Monster &monster, Direction md)\r\n{\r\n\tDirection mdtemp = md;\r\n\tbool ok = DirOK(monster, md); // Can we continue in the same direction\r\n\r\n\t// Randomly go left or right\r\n\tif (FlipCoin()) {\r\n\t\tok = ok || (mdtemp = Right(md), DirOK(monster, Right(md))) || (mdtemp = Left(md), DirOK(monster, Left(md)));\r\n\t} else {\r\n\t\tok = ok || (mdtemp = Left(md), DirOK(monster, Left(md))) || (mdtemp = Right(md), DirOK(monster, Right(md)));\r\n\t}\r\n\r\n\tif (ok)\r\n\t\tWalk(monster, mdtemp);\r\n\r\n\treturn ok;\r\n}\r\n\r\n/**\r\n * @brief Check if a tile is affected by a spell we are vulnerable to\r\n */\r\nbool IsTileSafe(const Monster &monster, Point position)\r\n{\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn false;\r\n\r\n\tconst bool fearsFire = (monster.resistance & IMMUNE_FIRE) == 0 || monster.type().type == MT_DIABLO;\r\n\tconst bool fearsLightning = (monster.resistance & IMMUNE_LIGHTNING) == 0 || monster.type().type == MT_DIABLO;\r\n\r\n\treturn !(fearsFire && HasAnyOf(dFlags[position.x][position.y], DungeonFlag::MissileFireWall))\r\n\t    && !(fearsLightning && HasAnyOf(dFlags[position.x][position.y], DungeonFlag::MissileLightningWall));\r\n}\r\n\r\n/**\r\n * @brief Check that the given tile is not currently blocked\r\n */\r\nbool IsTileAvailable(Point position)\r\n{\r\n\tif (dPlayer[position.x][position.y] != 0 || dMonster[position.x][position.y] != 0)\r\n\t\treturn false;\r\n\r\n\tif (!IsTileWalkable(position))\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * @brief If a monster can access the given tile (possibly by opening a door)\r\n */\r\nbool IsTileAccessible(const Monster &monster, Point position)\r\n{\r\n\tif (dPlayer[position.x][position.y] != 0 || dMonster[position.x][position.y] != 0)\r\n\t\treturn false;\r\n\r\n\tif (!IsTileWalkable(position, (monster.flags & MFLAG_CAN_OPEN_DOOR) != 0))\r\n\t\treturn false;\r\n\r\n\treturn IsTileSafe(monster, position);\r\n}\r\n\r\nbool AiPlanWalk(Monster &monster)\r\n{\r\n\tint8_t path[MaxPathLengthMonsters];\r\n\r\n\t/** Maps from walking path step to facing direction. */\r\n\tconst Direction plr2monst[9] = { Direction::South, Direction::NorthEast, Direction::NorthWest, Direction::SouthEast, Direction::SouthWest, Direction::North, Direction::East, Direction::South, Direction::West };\r\n\r\n\tif (FindPath(CanStep, [&monster](Point position) { return IsTileAccessible(monster, position); }, monster.position.tile, monster.enemyPosition, path, MaxPathLengthMonsters) == 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tRandomWalk(monster, plr2monst[path[0]]);\r\n\treturn true;\r\n}\r\n\r\nDirection Turn(Direction direction, bool turnLeft)\r\n{\r\n\treturn turnLeft ? Left(direction) : Right(direction);\r\n}\r\n\r\nbool RoundWalk(Monster &monster, Direction direction, int8_t *dir)\r\n{\r\n\tconst Direction turn45deg = Turn(direction, *dir != 0);\r\n\tconst Direction turn90deg = Turn(turn45deg, *dir != 0);\r\n\r\n\t// Turn 90 degrees\r\n\tif (Walk(monster, turn90deg)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Only do a small turn\r\n\tif (Walk(monster, turn45deg)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Continue straight\r\n\tif (Walk(monster, direction)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Try 90 degrees in the opposite than desired direction\r\n\t*dir = (*dir == 0) ? 1 : 0;\r\n\treturn RandomWalk(monster, Opposite(turn90deg));\r\n}\r\n\r\nbool AiPlanPath(Monster &monster)\r\n{\r\n\tif (monster.type().type != MT_GOLEM) {\r\n\t\tif (monster.activeForTicks == 0)\r\n\t\t\treturn false;\r\n\t\tif (monster.mode != MonsterMode::Stand)\r\n\t\t\treturn false;\r\n\t\tif (IsNoneOf(monster.goal, MonsterGoal::Normal, MonsterGoal::Move, MonsterGoal::Attack))\r\n\t\t\treturn false;\r\n\t\tif (monster.position.tile == GolemHoldingCell)\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tconst bool clear = LineClear(\r\n\t    [&monster](Point position) { return (IsTileWalkable(position) && IsTileSafe(monster, position)); },\r\n\t    monster.position.tile,\r\n\t    monster.enemyPosition);\r\n\tif (!clear || (monster.pathCount >= 5 && monster.pathCount < 8)) {\r\n\t\tif ((monster.flags & MFLAG_CAN_OPEN_DOOR) != 0)\r\n\t\t\tMonstCheckDoors(monster);\r\n\t\tmonster.pathCount++;\r\n\t\tif (monster.pathCount < 5)\r\n\t\t\treturn false;\r\n\t\tif (AiPlanWalk(monster))\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\tif (monster.type().type != MT_GOLEM)\r\n\t\tmonster.pathCount = 0;\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid AiAvoidance(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tif (monster.activeForTicks < UINT8_MAX)\r\n\t\tMonstCheckDoors(monster);\r\n\tconst int v = GenerateRnd(100);\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (distanceToEnemy >= 2 && monster.activeForTicks == UINT8_MAX && dTransVal[monster.position.tile.x][monster.position.tile.y] == dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\tif (monster.goal == MonsterGoal::Move || (distanceToEnemy >= 4 && FlipCoin(4))) {\r\n\t\t\tif (monster.goal != MonsterGoal::Move) {\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tmonster.goalVar2 = GenerateRnd(2);\r\n\t\t\t}\r\n\t\t\tmonster.goal = MonsterGoal::Move;\r\n\t\t\tif ((monster.goalVar1++ >= static_cast<int>(2 * distanceToEnemy) && DirOK(monster, md)) || dTransVal[monster.position.tile.x][monster.position.tile.y] != dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t} else if (!RoundWalk(monster, md, &monster.goalVar2)) {\r\n\t\t\t\tAiDelay(monster, GenerateRnd(10) + 10);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t}\r\n\tif (monster.goal == MonsterGoal::Normal) {\r\n\t\tif (distanceToEnemy >= 2) {\r\n\t\t\tif ((monster.var2 > 20 && v < 2 * monster.intelligence + 28)\r\n\t\t\t    || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t\t        && monster.var2 == 0\r\n\t\t\t        && v < 2 * monster.intelligence + 78)) {\r\n\t\t\t\tRandomWalk(monster, md);\r\n\t\t\t}\r\n\t\t} else if (v < 2 * monster.intelligence + 23) {\r\n\t\t\tmonster.direction = md;\r\n\t\t\tif (IsAnyOf(monster.ai, MonsterAIID::GoatMelee, MonsterAIID::Gharbad) && monster.hitPoints < (monster.maxHitPoints / 2) && !FlipCoin())\r\n\t\t\t\tStartSpecialAttack(monster);\r\n\t\t\telse\r\n\t\t\t\tStartAttack(monster);\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nMissileID GetMissileType(MonsterAIID ai)\r\n{\r\n\tswitch (ai) {\r\n\tcase MonsterAIID::GoatRanged:\r\n\t\treturn MissileID::Arrow;\r\n\tcase MonsterAIID::Succubus:\r\n\tcase MonsterAIID::LazarusSuccubus:\r\n\t\treturn MissileID::BloodStar;\r\n\tcase MonsterAIID::Acid:\r\n\tcase MonsterAIID::AcidUnique:\r\n\t\treturn MissileID::Acid;\r\n\tcase MonsterAIID::FireBat:\r\n\t\treturn MissileID::Firebolt;\r\n\tcase MonsterAIID::Torchant:\r\n\t\treturn MissileID::Fireball;\r\n\tcase MonsterAIID::Lich:\r\n\t\treturn MissileID::OrangeFlare;\r\n\tcase MonsterAIID::ArchLich:\r\n\t\treturn MissileID::YellowFlare;\r\n\tcase MonsterAIID::Psychorb:\r\n\t\treturn MissileID::BlueFlare;\r\n\tcase MonsterAIID::Necromorb:\r\n\t\treturn MissileID::RedFlare;\r\n\tcase MonsterAIID::Magma:\r\n\t\treturn MissileID::MagmaBall;\r\n\tcase MonsterAIID::Storm:\r\n\t\treturn MissileID::ThinLightningControl;\r\n\tcase MonsterAIID::Diablo:\r\n\t\treturn MissileID::DiabloApocalypse;\r\n\tcase MonsterAIID::BoneDemon:\r\n\t\treturn MissileID::BlueFlare2;\r\n\tdefault:\r\n\t\treturn MissileID::Arrow;\r\n\t}\r\n}\r\n\r\nvoid AiRanged(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.activeForTicks == UINT8_MAX || (monster.flags & MFLAG_TARGETS_MONSTER) != 0) {\r\n\t\tconst Direction md = GetMonsterDirection(monster);\r\n\t\tif (monster.activeForTicks < UINT8_MAX)\r\n\t\t\tMonstCheckDoors(monster);\r\n\t\tmonster.direction = md;\r\n\t\tif (static_cast<MonsterMode>(monster.var1) == MonsterMode::RangedAttack) {\r\n\t\t\tAiDelay(monster, GenerateRnd(20));\r\n\t\t} else if (monster.distanceToEnemy() < 4) {\r\n\t\t\tif (GenerateRnd(100) < 10 * (monster.intelligence + 7))\r\n\t\t\t\tRandomWalk(monster, Opposite(md));\r\n\t\t}\r\n\t\tif (monster.mode == MonsterMode::Stand) {\r\n\t\t\tif (LineClearMovingMissile(monster.position.tile, monster.enemyPosition)) {\r\n\t\t\t\tconst MissileID missileType = GetMissileType(monster.ai);\r\n\t\t\t\tif (monster.ai == MonsterAIID::AcidUnique)\r\n\t\t\t\t\tStartRangedSpecialAttack(monster, missileType, 0);\r\n\t\t\t\telse\r\n\t\t\t\t\tStartRangedAttack(monster, missileType, 0);\r\n\t\t\t} else {\r\n\t\t\t\tmonster.checkStandAnimationIsLoaded(md);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.activeForTicks != 0) {\r\n\t\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\t\tRandomWalk(monster, md);\r\n\t}\r\n}\r\n\r\nvoid AiRangedAvoidance(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tif (IsAnyOf(monster.ai, MonsterAIID::Magma, MonsterAIID::Storm, MonsterAIID::BoneDemon) && monster.activeForTicks < UINT8_MAX)\r\n\t\tMonstCheckDoors(monster);\r\n\tconst int lessmissiles = (monster.ai == MonsterAIID::Acid) ? 1 : 0;\r\n\tconst int dam = (monster.ai == MonsterAIID::Diablo) ? 40 : 0;\r\n\tconst MissileID missileType = GetMissileType(monster.ai);\r\n\tint v = GenerateRnd(10000);\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (distanceToEnemy >= 2 && monster.activeForTicks == UINT8_MAX && dTransVal[monster.position.tile.x][monster.position.tile.y] == dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\tif (monster.goal == MonsterGoal::Move || (distanceToEnemy >= 3 && FlipCoin(4 << lessmissiles))) {\r\n\t\t\tif (monster.goal != MonsterGoal::Move) {\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tmonster.goalVar2 = GenerateRnd(2);\r\n\t\t\t}\r\n\t\t\tmonster.goal = MonsterGoal::Move;\r\n\t\t\tif (monster.goalVar1++ >= static_cast<int>(2 * distanceToEnemy) && DirOK(monster, md)) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t} else if (v < (500 * (monster.intelligence + 1) >> lessmissiles)\r\n\t\t\t    && (LineClearMovingMissile(monster.position.tile, monster.enemyPosition))) {\r\n\t\t\t\tStartRangedSpecialAttack(monster, missileType, dam);\r\n\t\t\t} else {\r\n\t\t\t\tRoundWalk(monster, md, &monster.goalVar2);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t}\r\n\tif (monster.goal == MonsterGoal::Normal) {\r\n\t\tif (((distanceToEnemy >= 3 && v < ((500 * (monster.intelligence + 2)) >> lessmissiles))\r\n\t\t        || v < ((500 * (monster.intelligence + 1)) >> lessmissiles))\r\n\t\t    && LineClearMovingMissile(monster.position.tile, monster.enemyPosition)) {\r\n\t\t\tStartRangedSpecialAttack(monster, missileType, dam);\r\n\t\t} else if (distanceToEnemy >= 2) {\r\n\t\t\tv = GenerateRnd(100);\r\n\t\t\tif (v < 1000 * (monster.intelligence + 5)\r\n\t\t\t    || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t\t        && monster.var2 == 0\r\n\t\t\t        && v < 1000 * (monster.intelligence + 8))) {\r\n\t\t\t\tRandomWalk(monster, md);\r\n\t\t\t}\r\n\t\t} else if (v < 1000 * (monster.intelligence + 6)) {\r\n\t\t\tmonster.direction = md;\r\n\t\t\tStartAttack(monster);\r\n\t\t}\r\n\t}\r\n\tif (monster.mode == MonsterMode::Stand) {\r\n\t\tAiDelay(monster, GenerateRnd(10) + 5);\r\n\t}\r\n}\r\n\r\nvoid ZombieAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!IsTileVisible(monster.position.tile)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (GenerateRnd(100) < 2 * monster.intelligence + 10) {\r\n\t\tconst int dist = monster.enemyPosition.WalkingDistance(monster.position.tile);\r\n\t\tif (dist >= 2) {\r\n\t\t\tif (dist >= 2 * monster.intelligence + 4) {\r\n\t\t\t\tDirection md = monster.direction;\r\n\t\t\t\tif (GenerateRnd(100) < 2 * monster.intelligence + 20) {\r\n\t\t\t\t\tmd = static_cast<Direction>(GenerateRnd(8));\r\n\t\t\t\t}\r\n\t\t\t\tWalk(monster, md);\r\n\t\t\t} else {\r\n\t\t\t\tRandomWalk(monster, GetMonsterDirection(monster));\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tStartAttack(monster);\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(monster.direction);\r\n}\r\n\r\nvoid OverlordAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tmonster.direction = md;\r\n\tconst int v = GenerateRnd(100);\r\n\tif (monster.distanceToEnemy() >= 2) {\r\n\t\tif ((monster.var2 > 20 && v < 4 * monster.intelligence + 20)\r\n\t\t    || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t        && monster.var2 == 0\r\n\t\t        && v < 4 * monster.intelligence + 70)) {\r\n\t\t\tRandomWalk(monster, md);\r\n\t\t}\r\n\t} else if (v < 4 * monster.intelligence + 15) {\r\n\t\tStartAttack(monster);\r\n\t} else if (v < 4 * monster.intelligence + 20) {\r\n\t\tStartSpecialAttack(monster);\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid SkeletonAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tmonster.direction = md;\r\n\tif (monster.distanceToEnemy() >= 2) {\r\n\t\tif (static_cast<MonsterMode>(monster.var1) == MonsterMode::Delay || (GenerateRnd(100) >= 35 - 4 * monster.intelligence)) {\r\n\t\t\tRandomWalk(monster, md);\r\n\t\t} else {\r\n\t\t\tAiDelay(monster, 15 - (2 * monster.intelligence) + GenerateRnd(10));\r\n\t\t}\r\n\t} else {\r\n\t\tif (static_cast<MonsterMode>(monster.var1) == MonsterMode::Delay || (GenerateRnd(100) < 2 * monster.intelligence + 20)) {\r\n\t\t\tStartAttack(monster);\r\n\t\t} else {\r\n\t\t\tAiDelay(monster, (2 * (5 - monster.intelligence)) + GenerateRnd(10));\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid SkeletonBowAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tmonster.direction = md;\r\n\tconst int v = GenerateRnd(100);\r\n\r\n\tbool walking = false;\r\n\r\n\tif (monster.distanceToEnemy() < 4) {\r\n\t\tif ((monster.var2 > 20 && v < 2 * monster.intelligence + 13)\r\n\t\t    || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t        && monster.var2 == 0\r\n\t\t        && v < 2 * monster.intelligence + 63)) {\r\n\t\t\twalking = Walk(monster, Opposite(md));\r\n\t\t}\r\n\t}\r\n\r\n\tif (!walking) {\r\n\t\tif (GenerateRnd(100) < 2 * monster.intelligence + 3) {\r\n\t\t\tif (LineClearMovingMissile(monster.position.tile, monster.enemyPosition))\r\n\t\t\t\tStartRangedAttack(monster, MissileID::Arrow, 4);\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nstd::optional<Point> ScavengerFindCorpse(const Monster &scavenger)\r\n{\r\n\tconst bool reverseSearch = FlipCoin();\r\n\tconst int first = reverseSearch ? 4 : -4;\r\n\tconst int last = reverseSearch ? -4 : 4;\r\n\tconst int increment = reverseSearch ? -1 : 1;\r\n\r\n\tfor (int y = first; y <= last; y += increment) {\r\n\t\tfor (int x = first; x <= last; x += increment) {\r\n\t\t\tPoint position = scavenger.position.tile + Displacement { x, y };\r\n\t\t\tif (!InDungeonBounds(position))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dCorpse[position.x][position.y] == 0)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (!IsLineNotSolid(scavenger.position.tile, position))\r\n\t\t\t\tcontinue;\r\n\t\t\treturn position;\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid ScavengerAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand)\r\n\t\treturn;\r\n\tif (monster.hitPoints < (monster.maxHitPoints / 2) && monster.goal != MonsterGoal::Healing) {\r\n\t\tif (monster.leaderRelation != LeaderRelation::None) {\r\n\t\t\tShrinkLeaderPacksize(monster);\r\n\t\t\tmonster.leaderRelation = LeaderRelation::None;\r\n\t\t}\r\n\t\tmonster.goal = MonsterGoal::Healing;\r\n\t\tmonster.goalVar3 = 10;\r\n\t}\r\n\tif (monster.goal == MonsterGoal::Healing && monster.goalVar3 != 0) {\r\n\t\tmonster.goalVar3--;\r\n\t\tif (dCorpse[monster.position.tile.x][monster.position.tile.y] != 0) {\r\n\t\t\tStartEating(monster);\r\n\t\t\tif (gbIsHellfire) {\r\n\t\t\t\tconst int mMaxHP = monster.maxHitPoints;\r\n\t\t\t\tmonster.hitPoints += mMaxHP / 8;\r\n\t\t\t\tmonster.hitPoints = std::min(monster.hitPoints, monster.maxHitPoints);\r\n\t\t\t\tif (monster.goalVar3 <= 0 || monster.hitPoints == monster.maxHitPoints)\r\n\t\t\t\t\tdCorpse[monster.position.tile.x][monster.position.tile.y] = 0;\r\n\t\t\t} else {\r\n\t\t\t\tmonster.hitPoints += 64;\r\n\t\t\t}\r\n\t\t\tint targetHealth = monster.maxHitPoints;\r\n\t\t\tif (!gbIsHellfire)\r\n\t\t\t\ttargetHealth = (monster.maxHitPoints / 2) + (monster.maxHitPoints / 4);\r\n\t\t\tif (monster.hitPoints >= targetHealth) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tmonster.goalVar2 = 0;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (monster.goalVar1 == 0) {\r\n\t\t\t\tstd::optional<Point> position = ScavengerFindCorpse(monster);\r\n\t\t\t\tif (position) {\r\n\t\t\t\t\tmonster.goalVar1 = position->x + 1;\r\n\t\t\t\t\tmonster.goalVar2 = position->y + 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (monster.goalVar1 != 0) {\r\n\t\t\t\tconst int x = monster.goalVar1 - 1;\r\n\t\t\t\tconst int y = monster.goalVar2 - 1;\r\n\t\t\t\tmonster.direction = GetDirection(monster.position.tile, { x, y });\r\n\t\t\t\tRandomWalk(monster, monster.direction);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (monster.mode == MonsterMode::Stand)\r\n\t\tSkeletonAi(monster);\r\n}\r\n\r\nvoid RhinoAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tif (monster.activeForTicks < UINT8_MAX)\r\n\t\tMonstCheckDoors(monster);\r\n\tint v = GenerateRnd(100);\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (distanceToEnemy >= 2) {\r\n\t\tif (monster.goal == MonsterGoal::Move || (distanceToEnemy >= 5 && !FlipCoin(4))) {\r\n\t\t\tif (monster.goal != MonsterGoal::Move) {\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tmonster.goalVar2 = GenerateRnd(2);\r\n\t\t\t}\r\n\t\t\tmonster.goal = MonsterGoal::Move;\r\n\t\t\tif (monster.goalVar1++ >= static_cast<int>(2 * distanceToEnemy) || dTransVal[monster.position.tile.x][monster.position.tile.y] != dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t} else if (!RoundWalk(monster, md, &monster.goalVar2)) {\r\n\t\t\t\tAiDelay(monster, GenerateRnd(10) + 10);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t}\r\n\tif (monster.goal == MonsterGoal::Normal) {\r\n\t\tif (distanceToEnemy >= 5\r\n\t\t    && v < 2 * monster.intelligence + 43\r\n\t\t    && LineClear([&monster](Point position) { return IsTileAvailable(monster, position); }, monster.position.tile, monster.enemyPosition)) {\r\n\t\t\tif (AddMissile(monster.position.tile, monster.enemyPosition, md, MissileID::Rhino, TARGET_PLAYERS, monster, 0, 0) != nullptr) {\r\n\t\t\t\tif (monster.data().hasSpecialSound)\r\n\t\t\t\t\tPlayEffect(monster, MonsterSound::Special);\r\n\t\t\t\tmonster.occupyTile(monster.position.tile, true);\r\n\t\t\t\tmonster.mode = MonsterMode::Charge;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (distanceToEnemy >= 2) {\r\n\t\t\t\tv = GenerateRnd(100);\r\n\t\t\t\tif (v >= 2 * monster.intelligence + 33\r\n\t\t\t\t    && (IsNoneOf(static_cast<MonsterMode>(monster.var1), MonsterMode::MoveNorthwards, MonsterMode::MoveSouthwards, MonsterMode::MoveSideways)\r\n\t\t\t\t        || monster.var2 != 0\r\n\t\t\t\t        || v >= 2 * monster.intelligence + 83)) {\r\n\t\t\t\t\tAiDelay(monster, GenerateRnd(10) + 10);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tRandomWalk(monster, md);\r\n\t\t\t\t}\r\n\t\t\t} else if (v < 2 * monster.intelligence + 28) {\r\n\t\t\t\tmonster.direction = md;\r\n\t\t\t\tStartAttack(monster);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(monster.direction);\r\n}\r\n\r\nvoid FallenAi(Monster &monster)\r\n{\r\n\tif (monster.goal == MonsterGoal::Attack) {\r\n\t\tif (monster.goalVar1 != 0)\r\n\t\t\tmonster.goalVar1--;\r\n\t\telse\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t}\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.goal == MonsterGoal::Retreat) {\r\n\t\tif (monster.goalVar1-- == 0) {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\tM_StartStand(monster, Opposite(static_cast<Direction>(monster.goalVar2)));\r\n\t\t}\r\n\t}\r\n\r\n\tif (monster.animInfo.isLastFrame()) {\r\n\t\tif (!FlipCoin(4)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tStartSpecialStand(monster, monster.direction);\r\n\t\tif (monster.maxHitPoints - (2 * monster.intelligence + 2) >= monster.hitPoints)\r\n\t\t\tmonster.hitPoints += 2 * monster.intelligence + 2;\r\n\t\telse\r\n\t\t\tmonster.hitPoints = monster.maxHitPoints;\r\n\t\tconst int rad = (2 * monster.intelligence) + 4;\r\n\t\tfor (int y = -rad; y <= rad; y++) {\r\n\t\t\tfor (int x = -rad; x <= rad; x++) {\r\n\t\t\t\tconst int xpos = monster.position.tile.x + x;\r\n\t\t\t\tconst int ypos = monster.position.tile.y + y;\r\n\t\t\t\tif (InDungeonBounds({ xpos, ypos })) {\r\n\t\t\t\t\tconst int m = dMonster[xpos][ypos];\r\n\t\t\t\t\tif (m <= 0)\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\tMonster &otherMonster = Monsters[m - 1];\r\n\t\t\t\t\tif (otherMonster.ai != MonsterAIID::Fallen)\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\totherMonster.goal = MonsterGoal::Attack;\r\n\t\t\t\t\totherMonster.goalVar1 = 30 * monster.intelligence + 105;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (monster.goal == MonsterGoal::Retreat) {\r\n\t\tmonster.direction = static_cast<Direction>(monster.goalVar2);\r\n\t\tRandomWalk(monster, monster.direction);\r\n\t} else if (monster.goal == MonsterGoal::Attack) {\r\n\t\tif (monster.distanceToEnemy() < 2)\r\n\t\t\tStartAttack(monster);\r\n\t\telse\r\n\t\t\tRandomWalk(monster, GetMonsterDirection(monster));\r\n\t} else {\r\n\t\tSkeletonAi(monster);\r\n\t}\r\n}\r\n\r\nvoid LeoricAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tif (monster.activeForTicks < UINT8_MAX)\r\n\t\tMonstCheckDoors(monster);\r\n\tint v = GenerateRnd(100);\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (distanceToEnemy >= 2 && monster.activeForTicks == UINT8_MAX && dTransVal[monster.position.tile.x][monster.position.tile.y] == dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\tif (monster.goal == MonsterGoal::Move || (distanceToEnemy >= 3 && FlipCoin(4))) {\r\n\t\t\tif (monster.goal != MonsterGoal::Move) {\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tmonster.goalVar2 = GenerateRnd(2);\r\n\t\t\t}\r\n\t\t\tmonster.goal = MonsterGoal::Move;\r\n\t\t\tif ((monster.goalVar1++ >= static_cast<int>(2 * distanceToEnemy) && DirOK(monster, md)) || dTransVal[monster.position.tile.x][monster.position.tile.y] != dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t} else if (!RoundWalk(monster, md, &monster.goalVar2)) {\r\n\t\t\t\tAiDelay(monster, GenerateRnd(10) + 10);\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t}\r\n\tif (monster.goal == MonsterGoal::Normal) {\r\n\t\tif (!UseMultiplayerQuests()\r\n\t\t    && ((distanceToEnemy >= 3 && v < 4 * monster.intelligence + 35) || v < 6)\r\n\t\t    && LineClearMissile(monster.position.tile, monster.enemyPosition)) {\r\n\t\t\tconst Point newPosition = monster.position.tile + md;\r\n\t\t\tif (IsTileAvailable(monster, newPosition) && ActiveMonsterCount < MaxMonsters) {\r\n\t\t\t\tauto typeIndex = GetRandomSkeletonTypeIndex();\r\n\t\t\t\tif (typeIndex) {\r\n\t\t\t\t\tSpawnMonster(newPosition, md, *typeIndex);\r\n\t\t\t\t}\r\n\t\t\t\tStartSpecialStand(monster, md);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (distanceToEnemy >= 2) {\r\n\t\t\t\tv = GenerateRnd(100);\r\n\t\t\t\tif (v >= monster.intelligence + 25\r\n\t\t\t\t    && (IsNoneOf(static_cast<MonsterMode>(monster.var1), MonsterMode::MoveNorthwards, MonsterMode::MoveSouthwards, MonsterMode::MoveSideways) || monster.var2 != 0 || (v >= monster.intelligence + 75))) {\r\n\t\t\t\t\tAiDelay(monster, GenerateRnd(10) + 10);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tRandomWalk(monster, md);\r\n\t\t\t\t}\r\n\t\t\t} else if (v < monster.intelligence + 20) {\r\n\t\t\t\tmonster.direction = md;\r\n\t\t\t\tStartAttack(monster);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid BatAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tmonster.direction = md;\r\n\tconst int v = GenerateRnd(100);\r\n\tif (monster.goal == MonsterGoal::Retreat) {\r\n\t\tif (monster.goalVar1 == 0) {\r\n\t\t\tRandomWalk(monster, Opposite(md));\r\n\t\t\tmonster.goalVar1++;\r\n\t\t} else {\r\n\t\t\tRandomWalk(monster, PickRandomlyAmong({ Right(md), Left(md) }));\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (monster.type().type == MT_GLOOM\r\n\t    && distanceToEnemy >= 5\r\n\t    && v < 4 * monster.intelligence + 33\r\n\t    && LineClear([&monster](Point position) { return IsTileAvailable(monster, position); }, monster.position.tile, monster.enemyPosition)) {\r\n\t\tif (AddMissile(monster.position.tile, monster.enemyPosition, md, MissileID::Rhino, TARGET_PLAYERS, monster, 0, 0) != nullptr) {\r\n\t\t\tmonster.occupyTile(monster.position.tile, true);\r\n\t\t\tmonster.mode = MonsterMode::Charge;\r\n\t\t}\r\n\t} else if (distanceToEnemy >= 2) {\r\n\t\tif ((monster.var2 > 20 && v < monster.intelligence + 13)\r\n\t\t    || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t        && monster.var2 == 0\r\n\t\t        && v < monster.intelligence + 63)) {\r\n\t\t\tRandomWalk(monster, md);\r\n\t\t}\r\n\t} else if (v < 4 * monster.intelligence + 8) {\r\n\t\tStartAttack(monster);\r\n\t\tmonster.goal = MonsterGoal::Retreat;\r\n\t\tmonster.goalVar1 = 0;\r\n\t\tif (monster.type().type == MT_FAMILIAR) {\r\n\t\t\tAddMissile(monster.enemyPosition, monster.enemyPosition + Direction::SouthEast, Direction::South, MissileID::Lightning, TARGET_PLAYERS, monster, GenerateRnd(10) + 1, 0);\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid GargoyleAi(Monster &monster)\r\n{\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (monster.activeForTicks != 0 && (monster.flags & MFLAG_ALLOW_SPECIAL) != 0) {\r\n\t\tUpdateEnemy(monster);\r\n\t\tif (distanceToEnemy < monster.intelligence + 2U) {\r\n\t\t\tmonster.flags &= ~MFLAG_ALLOW_SPECIAL;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.hitPoints < (monster.maxHitPoints / 2))\r\n\t\tmonster.goal = MonsterGoal::Retreat;\r\n\tif (monster.goal == MonsterGoal::Retreat) {\r\n\t\tif (distanceToEnemy >= monster.intelligence + 2U) {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\tStartHeal(monster);\r\n\t\t} else if (!RandomWalk(monster, Opposite(md))) {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t}\r\n\t}\r\n\tAiAvoidance(monster);\r\n}\r\n\r\nvoid ButcherAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tmonster.direction = md;\r\n\r\n\tif (monster.distanceToEnemy() >= 2)\r\n\t\tRandomWalk(monster, md);\r\n\telse\r\n\t\tStartAttack(monster);\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid SneakAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst unsigned dist = 5 - monster.intelligence;\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (static_cast<MonsterMode>(monster.var1) == MonsterMode::HitRecovery) {\r\n\t\tmonster.goal = MonsterGoal::Retreat;\r\n\t\tmonster.goalVar1 = 0;\r\n\t} else if (distanceToEnemy >= dist + 3 || monster.goalVar1 > 8) {\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\tmonster.goalVar1 = 0;\r\n\t}\r\n\tDirection md = GetMonsterDirection(monster);\r\n\tif (monster.goal == MonsterGoal::Retreat && (monster.flags & MFLAG_NO_ENEMY) == 0) {\r\n\t\tif ((monster.flags & MFLAG_TARGETS_MONSTER) != 0)\r\n\t\t\tmd = GetDirection(monster.position.tile, Monsters[monster.enemy].position.tile);\r\n\t\telse\r\n\t\t\tmd = GetDirection(monster.position.tile, Players[monster.enemy].position.last);\r\n\t\tmd = Opposite(md);\r\n\t\tif (monster.type().type == MT_UNSEEN) {\r\n\t\t\tmd = PickRandomlyAmong({ Right(md), Left(md) });\r\n\t\t}\r\n\t}\r\n\tmonster.direction = md;\r\n\tconst int v = GenerateRnd(100);\r\n\tif (distanceToEnemy < dist && (monster.flags & MFLAG_HIDDEN) != 0) {\r\n\t\tStartFadein(monster, md, false);\r\n\t} else {\r\n\t\tif ((distanceToEnemy >= dist + 1) && (monster.flags & MFLAG_HIDDEN) == 0) {\r\n\t\t\tStartFadeout(monster, md, true);\r\n\t\t} else {\r\n\t\t\tif (monster.goal == MonsterGoal::Retreat\r\n\t\t\t    || (distanceToEnemy >= 2\r\n\t\t\t        && ((monster.var2 > 20 && v < 4 * monster.intelligence + 14)\r\n\t\t\t            || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t\t                && monster.var2 == 0 && v < 4 * monster.intelligence + 64)))) {\r\n\t\t\t\tmonster.goalVar1++;\r\n\t\t\t\tRandomWalk(monster, md);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (monster.mode == MonsterMode::Stand) {\r\n\t\tif (distanceToEnemy >= 2 || v >= 4 * monster.intelligence + 10)\r\n\t\t\tmonster.changeAnimationData(MonsterGraphic::Stand);\r\n\t\telse\r\n\t\t\tStartAttack(monster);\r\n\t}\r\n}\r\n\r\nvoid GharbadAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\r\n\tif (monster.talkMsg >= TEXT_GARBUD1\r\n\t    && monster.talkMsg <= TEXT_GARBUD3\r\n\t    && !IsTileVisible(monster.position.tile)\r\n\t    && monster.goal == MonsterGoal::Talking) {\r\n\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t\tswitch (monster.talkMsg) {\r\n\t\tcase TEXT_GARBUD1:\r\n\t\t\tmonster.talkMsg = TEXT_GARBUD2;\r\n\t\t\tQuests[Q_GARBUD]._qvar1 = QS_GHARBAD_FIRST_ITEM_READY;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_GARBUD]);\r\n\t\t\tbreak;\r\n\t\tcase TEXT_GARBUD2:\r\n\t\t\tmonster.talkMsg = TEXT_GARBUD3;\r\n\t\t\tQuests[Q_GARBUD]._qvar1 = QS_GHARBAD_SECOND_ITEM_NEARLY_DONE;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_GARBUD]);\r\n\t\t\tbreak;\r\n\t\tcase TEXT_GARBUD3:\r\n\t\t\tmonster.talkMsg = TEXT_GARBUD4;\r\n\t\t\tQuests[Q_GARBUD]._qvar1 = QS_GHARBAD_SECOND_ITEM_READY;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_GARBUD]);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsTileVisible(monster.position.tile)) {\r\n\t\tif (monster.talkMsg == TEXT_GARBUD4) {\r\n\t\t\tif (!effect_is_playing(SfxID::Gharbad4) && monster.goal == MonsterGoal::Talking) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\t\t\tQuests[Q_GARBUD]._qvar1 = QS_GHARBAD_ATTACKING;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_GARBUD]);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsAnyOf(monster.goal, MonsterGoal::Normal, MonsterGoal::Move))\r\n\t\tAiAvoidance(monster);\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid SnotSpilAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\r\n\tif (monster.talkMsg == TEXT_BANNER10 && !IsTileVisible(monster.position.tile) && monster.goal == MonsterGoal::Talking) {\r\n\t\tmonster.talkMsg = TEXT_BANNER11;\r\n\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t}\r\n\r\n\tif (monster.talkMsg == TEXT_BANNER11 && Quests[Q_LTBANNER]._qvar1 == 3) {\r\n\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t}\r\n\r\n\tif (IsTileVisible(monster.position.tile)) {\r\n\t\tif (monster.talkMsg == TEXT_BANNER12) {\r\n\t\t\tif (!effect_is_playing(SfxID::Snotspill3) && monster.goal == MonsterGoal::Talking) {\r\n\t\t\t\tObjChangeMap(SetPiece.position.x, SetPiece.position.y, SetPiece.position.x + SetPiece.size.width + 1, SetPiece.position.y + SetPiece.size.height + 1);\r\n\t\t\t\tQuests[Q_LTBANNER]._qvar1 = 3;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_LTBANNER]);\r\n\t\t\t\tRedoPlayerVision();\r\n\t\t\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (Quests[Q_LTBANNER]._qvar1 == 3) {\r\n\t\t\tif (IsAnyOf(monster.goal, MonsterGoal::Normal, MonsterGoal::Attack))\r\n\t\t\t\tFallenAi(monster);\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid SnakeAi(Monster &monster)\r\n{\r\n\tconst int8_t pattern[6] = { 1, 1, 0, -1, -1, 0 };\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0)\r\n\t\treturn;\r\n\tDirection md = GetDirection(monster.position.tile, monster.position.last);\r\n\tmonster.direction = md;\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (distanceToEnemy >= 2) {\r\n\t\tif (distanceToEnemy < 3 && LineClear([&monster](Point position) { return IsTileAvailable(monster, position); }, monster.position.tile, monster.enemyPosition) && static_cast<MonsterMode>(monster.var1) != MonsterMode::Charge) {\r\n\t\t\tif (AddMissile(monster.position.tile, monster.enemyPosition, md, MissileID::Rhino, TARGET_PLAYERS, monster, 0, 0) != nullptr) {\r\n\t\t\t\tPlayEffect(monster, MonsterSound::Attack);\r\n\t\t\t\tmonster.occupyTile(monster.position.tile, true);\r\n\t\t\t\tmonster.mode = MonsterMode::Charge;\r\n\t\t\t}\r\n\t\t} else if (static_cast<MonsterMode>(monster.var1) == MonsterMode::Delay || GenerateRnd(100) >= 35 - 2 * monster.intelligence) {\r\n\t\t\tif (pattern[monster.goalVar1] == -1)\r\n\t\t\t\tmd = Left(md);\r\n\t\t\telse if (pattern[monster.goalVar1] == 1)\r\n\t\t\t\tmd = Right(md);\r\n\r\n\t\t\tmonster.goalVar1++;\r\n\t\t\tif (monster.goalVar1 > 5)\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\r\n\t\t\tconst auto targetDirection = static_cast<Direction>(monster.goalVar2);\r\n\t\t\tif (md != targetDirection) {\r\n\t\t\t\tint drift = static_cast<int>(md) - monster.goalVar2;\r\n\t\t\t\tif (drift < 0)\r\n\t\t\t\t\tdrift += 8;\r\n\r\n\t\t\t\tif (drift < 4)\r\n\t\t\t\t\tmd = Right(targetDirection);\r\n\t\t\t\telse if (drift > 4)\r\n\t\t\t\t\tmd = Left(targetDirection);\r\n\t\t\t\tmonster.goalVar2 = static_cast<int>(md);\r\n\t\t\t}\r\n\r\n\t\t\tif (!Walk(monster, md))\r\n\t\t\t\tRandomWalk2(monster, monster.direction);\r\n\t\t} else {\r\n\t\t\tAiDelay(monster, 15 - monster.intelligence + GenerateRnd(10));\r\n\t\t}\r\n\t} else {\r\n\t\tif (IsAnyOf(static_cast<MonsterMode>(monster.var1), MonsterMode::Delay, MonsterMode::Charge)\r\n\t\t    || (GenerateRnd(100) < monster.intelligence + 20)) {\r\n\t\t\tStartAttack(monster);\r\n\t\t} else {\r\n\t\t\tAiDelay(monster, 10 - monster.intelligence + GenerateRnd(10));\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(monster.direction);\r\n}\r\n\r\nvoid CounselorAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tif (monster.activeForTicks < UINT8_MAX)\r\n\t\tMonstCheckDoors(monster);\r\n\tconst int v = GenerateRnd(100);\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (monster.goal == MonsterGoal::Retreat) {\r\n\t\tif (monster.goalVar1++ <= 3)\r\n\t\t\tRandomWalk(monster, Opposite(md));\r\n\t\telse {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\tStartFadein(monster, md, true);\r\n\t\t}\r\n\t} else if (monster.goal == MonsterGoal::Move) {\r\n\t\tif (distanceToEnemy >= 2 && monster.activeForTicks == UINT8_MAX && dTransVal[monster.position.tile.x][monster.position.tile.y] == dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\t\tif (monster.goalVar1++ < static_cast<int>(2 * distanceToEnemy) || !DirOK(monster, md)) {\r\n\t\t\t\tRoundWalk(monster, md, &monster.goalVar2);\r\n\t\t\t} else {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t\tStartFadein(monster, md, true);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\tStartFadein(monster, md, true);\r\n\t\t}\r\n\t} else if (monster.goal == MonsterGoal::Normal) {\r\n\t\tif (distanceToEnemy >= 2) {\r\n\t\t\tif (v < 5 * (monster.intelligence + 10) && LineClearMovingMissile(monster.position.tile, monster.enemyPosition)) {\r\n\t\t\t\tconstexpr MissileID MissileTypes[4] = { MissileID::Firebolt, MissileID::ChargedBolt, MissileID::LightningControl, MissileID::Fireball };\r\n\t\t\t\tStartRangedAttack(monster, MissileTypes[monster.intelligence], RandomIntBetween(monster.minDamage, monster.maxDamage));\r\n\t\t\t} else if (GenerateRnd(100) < 30) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Move;\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tStartFadeout(monster, md, false);\r\n\t\t\t} else {\r\n\t\t\t\tAiDelay(monster, GenerateRnd(10) + (2 * (5 - monster.intelligence)));\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tmonster.direction = md;\r\n\t\t\tif (monster.hitPoints < (monster.maxHitPoints / 2)) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Retreat;\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tStartFadeout(monster, md, false);\r\n\t\t\t} else if (static_cast<MonsterMode>(monster.var1) == MonsterMode::Delay\r\n\t\t\t    || GenerateRnd(100) < 2 * monster.intelligence + 20) {\r\n\t\t\t\tStartRangedAttack(monster, MissileID::Null, 0);\r\n\t\t\t\tAddMissile(monster.position.tile, { 0, 0 }, monster.direction, MissileID::FlashBottom, TARGET_PLAYERS, monster, 4, 0);\r\n\t\t\t\tAddMissile(monster.position.tile, { 0, 0 }, monster.direction, MissileID::FlashTop, TARGET_PLAYERS, monster, 4, 0);\r\n\t\t\t} else {\r\n\t\t\t\tAiDelay(monster, GenerateRnd(10) + (2 * (5 - monster.intelligence)));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (monster.mode == MonsterMode::Stand) {\r\n\t\tAiDelay(monster, GenerateRnd(10) + 5);\r\n\t}\r\n}\r\n\r\nvoid ZharAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tif (monster.talkMsg == TEXT_ZHAR1 && !IsTileVisible(monster.position.tile) && monster.goal == MonsterGoal::Talking) {\r\n\t\tmonster.talkMsg = TEXT_ZHAR2;\r\n\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t\tQuests[Q_ZHAR]._qvar1 = QS_ZHAR_ANGRY;\r\n\t\tNetSendCmdQuest(true, Quests[Q_ZHAR]);\r\n\t}\r\n\r\n\tif (IsTileVisible(monster.position.tile)) {\r\n\t\tif (monster.talkMsg == TEXT_ZHAR2) {\r\n\t\t\tif (!effect_is_playing(SfxID::Zhar2) && monster.goal == MonsterGoal::Talking) {\r\n\t\t\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t\tQuests[Q_ZHAR]._qvar1 = QS_ZHAR_ATTACKING;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_ZHAR]);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsAnyOf(monster.goal, MonsterGoal::Normal, MonsterGoal::Retreat, MonsterGoal::Move))\r\n\t\tCounselorAi(monster);\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid MegaAi(Monster &monster)\r\n{\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (distanceToEnemy >= 5) {\r\n\t\tSkeletonAi(monster);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\tif (monster.activeForTicks < UINT8_MAX)\r\n\t\tMonstCheckDoors(monster);\r\n\tint v = GenerateRnd(100);\r\n\tif (distanceToEnemy >= 2 && monster.activeForTicks == UINT8_MAX && dTransVal[monster.position.tile.x][monster.position.tile.y] == dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\tif (monster.goal == MonsterGoal::Move || distanceToEnemy >= 3) {\r\n\t\t\tif (monster.goal != MonsterGoal::Move) {\r\n\t\t\t\tmonster.goalVar1 = 0;\r\n\t\t\t\tmonster.goalVar2 = GenerateRnd(2);\r\n\t\t\t}\r\n\t\t\tmonster.goal = MonsterGoal::Move;\r\n\t\t\tmonster.goalVar3 = 4;\r\n\t\t\tif (monster.goalVar1++ < static_cast<int>(2 * distanceToEnemy) || !DirOK(monster, md)) {\r\n\t\t\t\tif (v < 5 * (monster.intelligence + 16))\r\n\t\t\t\t\tRoundWalk(monster, md, &monster.goalVar2);\r\n\t\t\t} else {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t}\r\n\tif (monster.goal == MonsterGoal::Normal) {\r\n\t\tif (((distanceToEnemy >= 3 && v < 5 * (monster.intelligence + 2)) || v < 5 * (monster.intelligence + 1) || monster.goalVar3 == 4) && LineClearMissile(monster.position.tile, monster.enemyPosition)) {\r\n\t\t\tStartRangedSpecialAttack(monster, MissileID::InfernoControl, 0);\r\n\t\t} else if (distanceToEnemy >= 2) {\r\n\t\t\tv = GenerateRnd(100);\r\n\t\t\tif (v < 2 * (5 * monster.intelligence + 25)\r\n\t\t\t    || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t\t        && monster.var2 == 0\r\n\t\t\t        && v < 2 * (5 * monster.intelligence + 40))) {\r\n\t\t\t\tRandomWalk(monster, md);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (GenerateRnd(100) < 10 * (monster.intelligence + 4)) {\r\n\t\t\t\tmonster.direction = md;\r\n\t\t\t\tif (FlipCoin())\r\n\t\t\t\t\tStartRangedSpecialAttack(monster, MissileID::InfernoControl, 0);\r\n\t\t\t\telse\r\n\t\t\t\t\tStartAttack(monster);\r\n\t\t\t}\r\n\t\t}\r\n\t\tmonster.goalVar3 = 1;\r\n\t}\r\n\tif (monster.mode == MonsterMode::Stand) {\r\n\t\tAiDelay(monster, GenerateRnd(10) + 5);\r\n\t}\r\n}\r\n\r\nvoid LazarusAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tif (IsTileVisible(monster.position.tile)) {\r\n\t\tif (!UseMultiplayerQuests()) {\r\n\t\t\tconst Player &myPlayer = *MyPlayer;\r\n\t\t\tif (monster.talkMsg == TEXT_VILE13 && monster.goal == MonsterGoal::Inquiring && myPlayer.position.tile == Point { 35, 46 }) {\r\n\t\t\t\tif (!gbIsMultiplayer) {\r\n\t\t\t\t\t// Playing ingame movies is currently not supported in multiplayer\r\n\t\t\t\t\tPlayInGameMovie(\"gendata\\\\fprst3.smk\");\r\n\t\t\t\t}\r\n\t\t\t\tmonster.mode = MonsterMode::Talk;\r\n\t\t\t\tQuests[Q_BETRAYER]._qvar1 = 5;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_BETRAYER]);\r\n\t\t\t}\r\n\r\n\t\t\tif (monster.talkMsg == TEXT_VILE13 && !effect_is_playing(SfxID::LazarusGreeting) && monster.goal == MonsterGoal::Talking) {\r\n\t\t\t\tObjChangeMap(1, 18, 20, 24);\r\n\t\t\t\tRedoPlayerVision();\r\n\t\t\t\tQuests[Q_BETRAYER]._qvar1 = 6;\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_BETRAYER]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (UseMultiplayerQuests() && monster.talkMsg == TEXT_VILE13 && monster.goal == MonsterGoal::Inquiring && Quests[Q_BETRAYER]._qvar1 <= 3) {\r\n\t\t\tmonster.mode = MonsterMode::Talk;\r\n\t\t}\r\n\t}\r\n\r\n\tif (IsAnyOf(monster.goal, MonsterGoal::Normal, MonsterGoal::Retreat, MonsterGoal::Move)) {\r\n\t\tif (!UseMultiplayerQuests() && Quests[Q_BETRAYER]._qvar1 == 4 && monster.talkMsg == TEXT_NONE) { // Fix save games affected by teleport bug\r\n\t\t\tObjChangeMapResync(1, 18, 20, 24);\r\n\t\t\tRedoPlayerVision();\r\n\t\t\tQuests[Q_BETRAYER]._qvar1 = 6;\r\n\t\t}\r\n\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\tCounselorAi(monster);\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid LazarusMinionAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand)\r\n\t\treturn;\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\r\n\tif (IsTileVisible(monster.position.tile)) {\r\n\t\tif (!UseMultiplayerQuests()) {\r\n\t\t\tif (Quests[Q_BETRAYER]._qvar1 <= 5) {\r\n\t\t\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t\t\t} else {\r\n\t\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t}\r\n\t}\r\n\tif (monster.goal == MonsterGoal::Normal)\r\n\t\tAiRanged(monster);\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid LachdananAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\r\n\tif (monster.talkMsg == TEXT_VEIL9 && !IsTileVisible(monster.position.tile) && monster.goal == MonsterGoal::Talking) {\r\n\t\tmonster.talkMsg = TEXT_VEIL10;\r\n\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t\tQuests[Q_VEIL]._qvar2 = QS_VEIL_EARLY_RETURN;\r\n\t\tNetSendCmdQuest(true, Quests[Q_VEIL]);\r\n\t}\r\n\r\n\tif (IsTileVisible(monster.position.tile)) {\r\n\t\tif (monster.talkMsg == TEXT_VEIL11) {\r\n\t\t\tif (!effect_is_playing(SfxID::Lachdanan3) && monster.goal == MonsterGoal::Talking) {\r\n\t\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\t\t\tQuests[Q_VEIL]._qactive = QUEST_DONE;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_VEIL]);\r\n\t\t\t\tMonsterDeath(monster, monster.direction, true);\r\n\t\t\t\tdelta_kill_monster(monster, monster.position.tile, *MyPlayer);\r\n\t\t\t\tNetSendCmdLocParam1(false, CMD_MONSTDEATH, monster.position.tile, static_cast<uint16_t>(monster.getId()));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid WarlordAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetMonsterDirection(monster);\r\n\tif (IsTileVisible(monster.position.tile)) {\r\n\t\tif (monster.talkMsg == TEXT_WARLRD9 && monster.goal == MonsterGoal::Inquiring)\r\n\t\t\tmonster.mode = MonsterMode::Talk;\r\n\t\tif (monster.talkMsg == TEXT_WARLRD9 && !effect_is_playing(SfxID::Warlord) && monster.goal == MonsterGoal::Talking) {\r\n\t\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\tQuests[Q_WARLORD]._qvar1 = QS_WARLORD_ATTACKING;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_WARLORD]);\r\n\t\t}\r\n\t}\r\n\r\n\tif (monster.goal == MonsterGoal::Normal)\r\n\t\tSkeletonAi(monster);\r\n\r\n\tmonster.checkStandAnimationIsLoaded(md);\r\n}\r\n\r\nvoid HorkDemonAi(Monster &monster)\r\n{\r\n\tif (monster.mode != MonsterMode::Stand || monster.activeForTicks == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction md = GetDirection(monster.position.tile, monster.position.last);\r\n\r\n\tif (monster.activeForTicks < 255) {\r\n\t\tMonstCheckDoors(monster);\r\n\t}\r\n\r\n\tint v = GenerateRnd(100);\r\n\r\n\tconst unsigned distanceToEnemy = monster.distanceToEnemy();\r\n\tif (distanceToEnemy < 2) {\r\n\t\tmonster.goal = MonsterGoal::Normal;\r\n\t} else if (monster.goal == MonsterGoal::Move || (distanceToEnemy >= 5 && !FlipCoin(4))) {\r\n\t\tif (monster.goal != MonsterGoal::Move) {\r\n\t\t\tmonster.goalVar1 = 0;\r\n\t\t\tmonster.goalVar2 = GenerateRnd(2);\r\n\t\t}\r\n\t\tmonster.goal = MonsterGoal::Move;\r\n\t\tif (monster.goalVar1++ >= static_cast<int>(2 * distanceToEnemy) || dTransVal[monster.position.tile.x][monster.position.tile.y] != dTransVal[monster.enemyPosition.x][monster.enemyPosition.y]) {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t} else if (!RoundWalk(monster, md, &monster.goalVar2)) {\r\n\t\t\tAiDelay(monster, GenerateRnd(10) + 10);\r\n\t\t}\r\n\t}\r\n\r\n\tif (monster.goal == MonsterGoal::Normal) {\r\n\t\tif ((distanceToEnemy >= 3) && v < 2 * monster.intelligence + 43) {\r\n\t\t\tconst Point position = monster.position.tile + monster.direction;\r\n\t\t\tif (IsTileAvailable(monster, position) && ActiveMonsterCount < MaxMonsters) {\r\n\t\t\t\tStartRangedSpecialAttack(monster, MissileID::HorkSpawn, 0);\r\n\t\t\t}\r\n\t\t} else if (distanceToEnemy < 2) {\r\n\t\t\tif (v < 2 * monster.intelligence + 28) {\r\n\t\t\t\tmonster.direction = md;\r\n\t\t\t\tStartAttack(monster);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tv = GenerateRnd(100);\r\n\t\t\tif (v < 2 * monster.intelligence + 33\r\n\t\t\t    || (IsMonsterModeMove(static_cast<MonsterMode>(monster.var1))\r\n\t\t\t        && monster.var2 == 0\r\n\t\t\t        && v < 2 * monster.intelligence + 83)) {\r\n\t\t\t\tRandomWalk(monster, md);\r\n\t\t\t} else {\r\n\t\t\t\tAiDelay(monster, GenerateRnd(10) + 10);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tmonster.checkStandAnimationIsLoaded(monster.direction);\r\n}\r\n\r\nstd::string_view GetMonsterTypeText(const MonsterData &monsterData)\r\n{\r\n\tswitch (monsterData.monsterClass) {\r\n\tcase MonsterClass::Animal:\r\n\t\treturn _(\"Animal\");\r\n\tcase MonsterClass::Demon:\r\n\t\treturn _(\"Demon\");\r\n\tcase MonsterClass::Undead:\r\n\t\treturn _(\"Undead\");\r\n\t}\r\n\r\n\tapp_fatal(StrCat(\"Unknown monsterClass \", static_cast<int>(monsterData.monsterClass)));\r\n}\r\n\r\nvoid ActivateSpawn(Monster &monster, Point position, Direction dir)\r\n{\r\n\tmonster.occupyTile(position, false);\r\n\tmonster.position.tile = position;\r\n\tmonster.position.future = position;\r\n\tmonster.position.old = position;\r\n\tStartSpecialStand(monster, dir);\r\n}\r\n\r\n/** Maps from monster AI ID to monster AI function. */\r\nvoid (*AiProc[])(Monster &monster) = {\r\n\t/*MonsterAIID::Zombie         */ &ZombieAi,\r\n\t/*MonsterAIID::Fat            */ &OverlordAi,\r\n\t/*MonsterAIID::SkeletonMelee  */ &SkeletonAi,\r\n\t/*MonsterAIID::SkeletonRanged */ &SkeletonBowAi,\r\n\t/*MonsterAIID::Scavenger      */ &ScavengerAi,\r\n\t/*MonsterAIID::Rhino          */ &RhinoAi,\r\n\t/*MonsterAIID::GoatMelee      */ &AiAvoidance,\r\n\t/*MonsterAIID::GoatRanged     */ &AiRanged,\r\n\t/*MonsterAIID::Fallen         */ &FallenAi,\r\n\t/*MonsterAIID::Magma          */ &AiRangedAvoidance,\r\n\t/*MonsterAIID::SkeletonKing   */ &LeoricAi,\r\n\t/*MonsterAIID::Bat            */ &BatAi,\r\n\t/*MonsterAIID::Gargoyle       */ &GargoyleAi,\r\n\t/*MonsterAIID::Butcher        */ &ButcherAi,\r\n\t/*MonsterAIID::Succubus       */ &AiRanged,\r\n\t/*MonsterAIID::Sneak          */ &SneakAi,\r\n\t/*MonsterAIID::Storm          */ &AiRangedAvoidance,\r\n\t/*MonsterAIID::FireMan        */ nullptr,\r\n\t/*MonsterAIID::Gharbad        */ &GharbadAi,\r\n\t/*MonsterAIID::Acid           */ &AiRangedAvoidance,\r\n\t/*MonsterAIID::AcidUnique     */ &AiRanged,\r\n\t/*MonsterAIID::Golem          */ &GolumAi,\r\n\t/*MonsterAIID::Zhar           */ &ZharAi,\r\n\t/*MonsterAIID::Snotspill      */ &SnotSpilAi,\r\n\t/*MonsterAIID::Snake          */ &SnakeAi,\r\n\t/*MonsterAIID::Counselor      */ &CounselorAi,\r\n\t/*MonsterAIID::Mega           */ &MegaAi,\r\n\t/*MonsterAIID::Diablo         */ &AiRangedAvoidance,\r\n\t/*MonsterAIID::Lazarus        */ &LazarusAi,\r\n\t/*MonsterAIID::LazarusSuccubus*/ &LazarusMinionAi,\r\n\t/*MonsterAIID::Lachdanan      */ &LachdananAi,\r\n\t/*MonsterAIID::Warlord        */ &WarlordAi,\r\n\t/*MonsterAIID::FireBat        */ &AiRanged,\r\n\t/*MonsterAIID::Torchant       */ &AiRanged,\r\n\t/*MonsterAIID::HorkDemon      */ &HorkDemonAi,\r\n\t/*MonsterAIID::Lich           */ &AiRanged,\r\n\t/*MonsterAIID::ArchLich       */ &AiRanged,\r\n\t/*MonsterAIID::Psychorb       */ &AiRanged,\r\n\t/*MonsterAIID::Necromorb      */ &AiRanged,\r\n\t/*MonsterAIID::BoneDemon      */ &AiRangedAvoidance\r\n};\r\n\r\nbool IsRelativeMoveOK(const Monster &monster, Point position, Direction mdir)\r\n{\r\n\tconst Point futurePosition = position + mdir;\r\n\tif (!InDungeonBounds(futurePosition) || !IsTileAvailable(monster, futurePosition))\r\n\t\treturn false;\r\n\tif (mdir == Direction::East) {\r\n\t\tif (IsTileSolid(position + Direction::SouthEast))\r\n\t\t\treturn false;\r\n\t} else if (mdir == Direction::West) {\r\n\t\tif (IsTileSolid(position + Direction::SouthWest))\r\n\t\t\treturn false;\r\n\t} else if (mdir == Direction::North) {\r\n\t\tif (IsTileSolid(position + Direction::NorthEast) || IsTileSolid(position + Direction::NorthWest))\r\n\t\t\treturn false;\r\n\t} else if (mdir == Direction::South) {\r\n\t\tif (IsTileSolid(position + Direction::SouthWest) || IsTileSolid(position + Direction::SouthEast))\r\n\t\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IsMonsterAvailable(const MonsterData &monsterData)\r\n{\r\n\tif (monsterData.availability == MonsterAvailability::Never)\r\n\t\treturn false;\r\n\r\n\tif (gbIsSpawn && monsterData.availability == MonsterAvailability::Retail)\r\n\t\treturn false;\r\n\r\n\treturn currlevel >= monsterData.minDunLvl && currlevel <= monsterData.maxDunLvl;\r\n}\r\n\r\nbool UpdateModeStance(Monster &monster)\r\n{\r\n\tswitch (monster.mode) {\r\n\tcase MonsterMode::Stand:\r\n\t\tMonsterIdle(monster);\r\n\t\treturn false;\r\n\tcase MonsterMode::MoveNorthwards:\r\n\tcase MonsterMode::MoveSouthwards:\r\n\tcase MonsterMode::MoveSideways:\r\n\t\treturn MonsterWalk(monster);\r\n\tcase MonsterMode::MeleeAttack:\r\n\t\treturn MonsterAttack(monster);\r\n\tcase MonsterMode::HitRecovery:\r\n\t\treturn MonsterGotHit(monster);\r\n\tcase MonsterMode::Death:\r\n\t\tMonsterDeath(monster);\r\n\t\treturn false;\r\n\tcase MonsterMode::SpecialMeleeAttack:\r\n\t\treturn MonsterSpecialAttack(monster);\r\n\tcase MonsterMode::FadeIn:\r\n\t\treturn MonsterFadein(monster);\r\n\tcase MonsterMode::FadeOut:\r\n\t\treturn MonsterFadeout(monster);\r\n\tcase MonsterMode::RangedAttack:\r\n\t\treturn MonsterRangedAttack(monster);\r\n\tcase MonsterMode::SpecialStand:\r\n\t\treturn MonsterSpecialStand(monster);\r\n\tcase MonsterMode::SpecialRangedAttack:\r\n\t\treturn MonsterRangedSpecialAttack(monster);\r\n\tcase MonsterMode::Delay:\r\n\t\treturn MonsterDelay(monster);\r\n\tcase MonsterMode::Petrified:\r\n\t\tMonsterPetrified(monster);\r\n\t\treturn false;\r\n\tcase MonsterMode::Heal:\r\n\t\tMonsterHeal(monster);\r\n\t\treturn false;\r\n\tcase MonsterMode::Talk:\r\n\t\tMonsterTalk(monster);\r\n\t\treturn false;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nMonsterSpritesData LoadMonsterSpritesData(const MonsterData &monsterData)\r\n{\r\n\tconst size_t numAnims = GetNumAnims(monsterData);\r\n\r\n\tMonsterSpritesData result;\r\n\tresult.data = MultiFileLoader<MonsterSpritesData::MaxAnims> {}(\r\n\t    numAnims,\r\n\t    FileNameWithCharAffixGenerator({ \"monsters\\\\\", monsterData.spritePath() }, DEVILUTIONX_CL2_EXT, Animletter),\r\n\t    result.offsets.data(),\r\n\t    [&monsterData](size_t index) { return monsterData.hasAnim(index); });\r\n\r\n#ifndef UNPACKED_MPQS\r\n\t// Convert CL2 to CLX:\r\n\tstd::vector<std::vector<uint8_t>> clxData;\r\n\tsize_t accumulatedSize = 0;\r\n\tfor (size_t i = 0, j = 0; i < numAnims; ++i) {\r\n\t\tif (!monsterData.hasAnim(i))\r\n\t\t\tcontinue;\r\n\t\tconst uint32_t begin = result.offsets[j];\r\n\t\tconst uint32_t end = result.offsets[j + 1];\r\n\t\tclxData.emplace_back();\r\n\t\tCl2ToClx(reinterpret_cast<uint8_t *>(&result.data[begin]), end - begin,\r\n\t\t    PointerOrValue<uint16_t> { monsterData.width }, clxData.back());\r\n\t\tresult.offsets[j] = static_cast<uint32_t>(accumulatedSize);\r\n\t\taccumulatedSize += clxData.back().size();\r\n\t\t++j;\r\n\t}\r\n\tresult.offsets[clxData.size()] = static_cast<uint32_t>(accumulatedSize);\r\n\tresult.data = nullptr;\r\n\tresult.data = std::unique_ptr<std::byte[]>(new std::byte[accumulatedSize]);\r\n\tfor (size_t i = 0; i < clxData.size(); ++i) {\r\n\t\tmemcpy(&result.data[result.offsets[i]], clxData[i].data(), clxData[i].size());\r\n\t}\r\n#endif\r\n\r\n\treturn result;\r\n}\r\n\r\nvoid EnsureMonsterIndexIsActive(size_t monsterId)\r\n{\r\n\tassert(monsterId < MaxMonsters);\r\n\tfor (size_t index = 0; index < MaxMonsters; index++) {\r\n\t\tif (ActiveMonsters[index] != monsterId)\r\n\t\t\tcontinue;\r\n\t\tif (index < ActiveMonsterCount)\r\n\t\t\treturn; // monster is already active\r\n\t\tconst unsigned oldId = ActiveMonsters[ActiveMonsterCount];\r\n\t\tActiveMonsters[ActiveMonsterCount] = static_cast<unsigned>(monsterId);\r\n\t\tActiveMonsters[index] = oldId;\r\n\t\tActiveMonsterCount += 1;\r\n\t}\r\n}\r\n\r\nvoid InitGolem(devilution::Monster &monster, uint8_t golemOwnerPlayerId, int16_t golemSpellLevel)\r\n{\r\n\tmonster.flags |= MFLAG_GOLEM;\r\n\tmonster.goalVar3 = static_cast<int8_t>(golemOwnerPlayerId);\r\n\tconst Player &player = Players[golemOwnerPlayerId];\r\n\tmonster.maxHitPoints = 2 * (320 * golemSpellLevel + player._pMaxMana / 3);\r\n\tmonster.hitPoints = monster.maxHitPoints;\r\n\tmonster.armorClass = 25;\r\n\tmonster.golemToHit = 5 * (golemSpellLevel + 8) + 2 * player.getCharacterLevel();\r\n\tmonster.minDamage = 2 * (golemSpellLevel + 4);\r\n\tmonster.maxDamage = 2 * (golemSpellLevel + 8);\r\n\tUpdateEnemy(monster);\r\n}\r\n\r\nbool PosOkMissile(Point position)\r\n{\r\n\treturn !TileHasAny(position, TileProperties::BlockMissile);\r\n}\r\n\r\nbool PosOkMovingMissile(Point position)\r\n{\r\n\treturn !IsMissileBlockedByTile(position);\r\n}\r\n\r\n} // namespace\r\n\r\ntl::expected<size_t, std::string> AddMonsterType(_monster_id type, placeflag placeflag)\r\n{\r\n\tconst size_t typeIndex = GetMonsterTypeIndex(type);\r\n\tCMonster &monsterType = LevelMonsterTypes[typeIndex];\r\n\r\n\tif (typeIndex == LevelMonsterTypeCount) {\r\n\t\tLevelMonsterTypeCount++;\r\n\t\tmonsterType.type = type;\r\n\t\tconst MonsterData &monsterData = MonstersData[type];\r\n\t\tmonstimgtot += monsterData.image;\r\n\r\n\t\tconst size_t numAnims = GetNumAnims(monsterData);\r\n\t\tfor (size_t i = 0; i < numAnims; ++i) {\r\n\t\t\tAnimStruct &anim = monsterType.anims[i];\r\n\t\t\tanim.frames = monsterData.frames[i];\r\n\t\t\tif (monsterData.hasAnim(i)) {\r\n\t\t\t\tanim.rate = monsterData.rate[i];\r\n\t\t\t\tanim.width = monsterData.width;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tRETURN_IF_ERROR(InitMonsterSND(monsterType));\r\n\t}\r\n\r\n\tmonsterType.placeFlags |= placeflag;\r\n\treturn typeIndex;\r\n}\r\n\r\ntl::expected<void, std::string> InitTRNForUniqueMonster(Monster &monster)\r\n{\r\n\tchar filestr[64];\r\n\t*BufCopy(filestr, R\"(monsters\\monsters\\)\", UniqueMonstersData[static_cast<size_t>(monster.uniqueType)].mTrnName, \".trn\") = '\\0';\r\n\tASSIGN_OR_RETURN(monster.uniqueMonsterTRN, LoadFileInMemWithStatus<uint8_t>(filestr));\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t minionType, int bosspacksize, const UniqueMonsterData &uniqueMonsterData)\r\n{\r\n\tmonster.uniqueType = monsterType;\r\n\tmonster.maxHitPoints = uniqueMonsterData.mmaxhp << 6;\r\n\r\n\tif (!gbIsMultiplayer)\r\n\t\tmonster.maxHitPoints = std::max(monster.maxHitPoints / 2, 64);\r\n\r\n\tmonster.hitPoints = monster.maxHitPoints;\r\n\tmonster.ai = uniqueMonsterData.mAi;\r\n\tmonster.intelligence = uniqueMonsterData.mint;\r\n\tmonster.minDamage = uniqueMonsterData.mMinDamage;\r\n\tmonster.maxDamage = uniqueMonsterData.mMaxDamage;\r\n\tmonster.minDamageSpecial = uniqueMonsterData.mMinDamage;\r\n\tmonster.maxDamageSpecial = uniqueMonsterData.mMaxDamage;\r\n\tmonster.reducePlayerStrength = uniqueMonsterData.reducePlayerStrength;\r\n\tmonster.reducePlayerMagic = uniqueMonsterData.reducePlayerMagic;\r\n\tmonster.reducePlayerDexterity = uniqueMonsterData.reducePlayerDexterity;\r\n\tmonster.reducePlayerVitality = uniqueMonsterData.reducePlayerVitality;\r\n\tmonster.reducePlayerMaxHP = uniqueMonsterData.reducePlayerMaxHP;\r\n\tmonster.reducePlayerMaxMana = uniqueMonsterData.reducePlayerMaxMana;\r\n\tmonster.resistance = uniqueMonsterData.mMagicRes;\r\n\tmonster.talkMsg = uniqueMonsterData.mtalkmsg;\r\n\tif (monsterType == UniqueMonsterType::HorkDemon)\r\n\t\tmonster.lightId = NO_LIGHT;\r\n\telse\r\n\t\tmonster.lightId = AddLight(monster.position.tile, 3);\r\n\r\n\tif (UseMultiplayerQuests()) {\r\n\t\tif (monster.ai == MonsterAIID::LazarusSuccubus)\r\n\t\t\tmonster.talkMsg = TEXT_NONE;\r\n\t\tif (monster.ai == MonsterAIID::Lazarus && Quests[Q_BETRAYER]._qvar1 > 3) {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t} else if (monster.talkMsg != TEXT_NONE) {\r\n\t\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t\t}\r\n\t} else if (monster.talkMsg != TEXT_NONE) {\r\n\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t}\r\n\r\n\tif (sgGameInitInfo.nDifficulty == DIFF_NIGHTMARE) {\r\n\t\tmonster.maxHitPoints = 3 * monster.maxHitPoints;\r\n\t\tif (gbIsHellfire)\r\n\t\t\tmonster.maxHitPoints += (gbIsMultiplayer ? 100 : 50) << 6;\r\n\t\telse\r\n\t\t\tmonster.maxHitPoints += 100 << 6;\r\n\t\tmonster.hitPoints = monster.maxHitPoints;\r\n\t\tmonster.minDamage = 2 * (monster.minDamage + 2);\r\n\t\tmonster.maxDamage = 2 * (monster.maxDamage + 2);\r\n\t\tmonster.minDamageSpecial = 2 * (monster.minDamageSpecial + 2);\r\n\t\tmonster.maxDamageSpecial = 2 * (monster.maxDamageSpecial + 2);\r\n\t} else if (sgGameInitInfo.nDifficulty == DIFF_HELL) {\r\n\t\tmonster.maxHitPoints = 4 * monster.maxHitPoints;\r\n\t\tif (gbIsHellfire)\r\n\t\t\tmonster.maxHitPoints += (gbIsMultiplayer ? 200 : 100) << 6;\r\n\t\telse\r\n\t\t\tmonster.maxHitPoints += 200 << 6;\r\n\t\tmonster.hitPoints = monster.maxHitPoints;\r\n\t\tmonster.minDamage = 4 * monster.minDamage + 6;\r\n\t\tmonster.maxDamage = 4 * monster.maxDamage + 6;\r\n\t\tmonster.minDamageSpecial = 4 * monster.minDamageSpecial + 6;\r\n\t\tmonster.maxDamageSpecial = 4 * monster.maxDamageSpecial + 6;\r\n\t}\r\n\r\n\tRETURN_IF_ERROR(InitTRNForUniqueMonster(monster));\r\n\tmonster.uniqTrans = uniquetrans++;\r\n\r\n\tif (uniqueMonsterData.customArmorClass != 0) {\r\n\t\tmonster.armorClass = uniqueMonsterData.customArmorClass;\r\n\r\n\t\tif (sgGameInitInfo.nDifficulty == DIFF_NIGHTMARE) {\r\n\t\t\tmonster.armorClass += NightmareAcBonus;\r\n\t\t} else if (sgGameInitInfo.nDifficulty == DIFF_HELL) {\r\n\t\t\tmonster.armorClass += HellAcBonus;\r\n\t\t}\r\n\t}\r\n\r\n\tif (uniqueMonsterData.monsterPack != UniqueMonsterPack::None) {\r\n\t\tPlaceGroup(minionType, bosspacksize, &monster, uniqueMonsterData.monsterPack == UniqueMonsterPack::Leashed);\r\n\t}\r\n\r\n\tif (monster.ai != MonsterAIID::Gargoyle) {\r\n\t\tmonster.changeAnimationData(MonsterGraphic::Stand);\r\n\t\tmonster.animInfo.currentFrame = GenerateRnd(monster.animInfo.numberOfFrames - 1);\r\n\t\tmonster.flags &= ~MFLAG_ALLOW_SPECIAL;\r\n\t\tmonster.mode = MonsterMode::Stand;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid InitLevelMonsters()\r\n{\r\n\tLevelMonsterTypeCount = 0;\r\n\tmonstimgtot = 0;\r\n\r\n\tfor (CMonster &levelMonsterType : LevelMonsterTypes) {\r\n\t\tlevelMonsterType.placeFlags = 0;\r\n\t}\r\n\r\n\tClrAllMonsters();\r\n\tActiveMonsterCount = 0;\r\n\ttotalmonsters = MaxMonsters;\r\n\r\n\tstd::iota(std::begin(ActiveMonsters), std::end(ActiveMonsters), 0U);\r\n\tuniquetrans = 0;\r\n}\r\n\r\ntl::expected<void, std::string> GetLevelMTypes()\r\n{\r\n\tRETURN_IF_ERROR(AddMonsterType(MT_GOLEM, PLACE_SPECIAL));\r\n\tif (currlevel == 16) {\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_ADVOCATE, PLACE_SCATTER));\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_RBLACK, PLACE_SCATTER));\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_DIABLO, PLACE_SPECIAL));\r\n\t\treturn {};\r\n\t}\r\n\r\n\tif (currlevel == 18)\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_HORKSPWN, PLACE_SCATTER));\r\n\tif (currlevel == 19) {\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_HORKSPWN, PLACE_SCATTER));\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_HORKDMN, PLACE_UNIQUE));\r\n\t}\r\n\tif (currlevel == 20)\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_DEFILER, PLACE_UNIQUE));\r\n\tif (currlevel == 24) {\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_ARCHLICH, PLACE_SCATTER));\r\n\t\tRETURN_IF_ERROR(AddMonsterType(MT_NAKRUL, PLACE_SPECIAL));\r\n\t}\r\n\r\n\tif (!setlevel) {\r\n\t\tif (Quests[Q_BUTCHER].IsAvailable())\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(MT_CLEAVER, PLACE_SPECIAL));\r\n\t\tif (Quests[Q_GARBUD].IsAvailable())\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::Garbud, PLACE_UNIQUE));\r\n\t\tif (Quests[Q_ZHAR].IsAvailable())\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::Zhar, PLACE_UNIQUE));\r\n\t\tif (Quests[Q_LTBANNER].IsAvailable())\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::SnotSpill, PLACE_UNIQUE));\r\n\t\tif (Quests[Q_VEIL].IsAvailable())\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::Lachdan, PLACE_UNIQUE));\r\n\t\tif (Quests[Q_WARLORD].IsAvailable())\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(UniqueMonsterType::WarlordOfBlood, PLACE_UNIQUE));\r\n\r\n\t\tif (UseMultiplayerQuests() && currlevel == Quests[Q_SKELKING]._qlevel) {\r\n\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(MT_SKING, PLACE_UNIQUE));\r\n\r\n\t\t\tint skeletonTypeCount = 0;\r\n\t\t\t_monster_id skeltypes[NUM_MAX_MTYPES];\r\n\t\t\tfor (const _monster_id skeletonType : SkeletonTypes) {\r\n\t\t\t\tif (!IsMonsterAvailable(MonstersData[skeletonType]))\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\tskeltypes[skeletonTypeCount++] = skeletonType;\r\n\t\t\t}\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(skeltypes[GenerateRnd(skeletonTypeCount)], PLACE_SCATTER));\r\n\t\t}\r\n\r\n\t\t_monster_id typelist[MaxMonsters];\r\n\r\n\t\tint nt = 0;\r\n\t\tfor (size_t i = 0; i < MonstersData.size(); i++) {\r\n\t\t\tif (!IsMonsterAvailable(MonstersData[i]))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\ttypelist[nt++] = (_monster_id)i;\r\n\t\t}\r\n\r\n\t\twhile (nt > 0 && LevelMonsterTypeCount < MaxLvlMTypes && monstimgtot < 4000) {\r\n\t\t\tfor (int i = 0; i < nt;) {\r\n\t\t\t\tif (MonstersData[typelist[i]].image > 4000 - monstimgtot) {\r\n\t\t\t\t\ttypelist[i] = typelist[--nt];\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\r\n\t\t\tif (nt != 0) {\r\n\t\t\t\tconst int i = GenerateRnd(nt);\r\n\t\t\t\tRETURN_IF_ERROR(AddMonsterType(typelist[i], PLACE_SCATTER));\r\n\t\t\t\ttypelist[i] = typelist[--nt];\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tif (setlvlnum == SL_SKELKING) {\r\n\t\t\tRETURN_IF_ERROR(AddMonsterType(MT_SKING, PLACE_UNIQUE));\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> InitMonsterSND(CMonster &monsterType)\r\n{\r\n\tif (!gbSndInited)\r\n\t\treturn {};\r\n\r\n\tconst char *prefixes[] {\r\n\t\t\"a\", // Attack\r\n\t\t\"h\", // Hit\r\n\t\t\"d\", // Death\r\n\t\t\"s\", // Special\r\n\t};\r\n\r\n\tconst MonsterData &data = MonstersData[monsterType.type];\r\n\tconst std::string_view soundSuffix = data.soundPath();\r\n\r\n\tfor (int i = 0; i < 4; i++) {\r\n\t\tconst std::string_view prefix = prefixes[i];\r\n\t\tif (prefix == \"s\" && !data.hasSpecialSound)\r\n\t\t\tcontinue;\r\n\r\n\t\tfor (int j = 0; j < 2; j++) {\r\n\t\t\tchar path[64];\r\n\t\t\t*BufCopy(path, \"monsters\\\\\", soundSuffix, prefix, j + 1, \".wav\") = '\\0';\r\n\t\t\tASSIGN_OR_RETURN(monsterType.sounds[i][j], SoundFileLoadWithStatus(path));\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> InitMonsterGFX(CMonster &monsterType, MonsterSpritesData &&spritesData)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn {};\r\n\r\n\tconst _monster_id mtype = monsterType.type;\r\n\tconst MonsterData &monsterData = MonstersData[mtype];\r\n\tif (spritesData.data == nullptr)\r\n\t\tspritesData = LoadMonsterSpritesData(monsterData);\r\n\tmonsterType.animData = std::move(spritesData.data);\r\n\r\n\tconst size_t numAnims = GetNumAnims(monsterData);\r\n\tfor (size_t i = 0, j = 0; i < numAnims; ++i) {\r\n\t\tif (!monsterData.hasAnim(i)) {\r\n\t\t\tmonsterType.anims[i].sprites = std::nullopt;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst uint32_t begin = spritesData.offsets[j];\r\n\t\tconst uint32_t end = spritesData.offsets[j + 1];\r\n\t\tauto *animSpritesData = reinterpret_cast<uint8_t *>(&monsterType.animData[begin]);\r\n\t\tconst uint16_t numLists = GetNumListsFromClxListOrSheetBuffer(animSpritesData, end - begin);\r\n\t\tmonsterType.anims[i].sprites = ClxSpriteListOrSheet { animSpritesData, numLists };\r\n\t\t++j;\r\n\t}\r\n\r\n\tif (!monsterData.trnFile.empty()) {\r\n\t\tInitMonsterTRN(monsterType);\r\n\t}\r\n\r\n\tif (IsAnyOf(mtype, MT_NMAGMA, MT_YMAGMA, MT_BMAGMA, MT_WMAGMA))\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::MagmaBall).LoadGFX());\r\n\tif (IsAnyOf(mtype, MT_STORM, MT_RSTORM, MT_STORML, MT_MAEL))\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::ThinLightning).LoadGFX());\r\n\tif (mtype == MT_SNOWWICH) {\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BloodStarBlue).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BloodStarBlueExplosion).LoadGFX());\r\n\t}\r\n\tif (mtype == MT_HLSPWN) {\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BloodStarRed).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BloodStarRedExplosion).LoadGFX());\r\n\t}\r\n\tif (mtype == MT_SOLBRNR) {\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BloodStarYellow).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BloodStarYellowExplosion).LoadGFX());\r\n\t}\r\n\tif (IsAnyOf(mtype, MT_NACID, MT_RACID, MT_BACID, MT_XACID, MT_SPIDLORD)) {\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::Acid).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::AcidSplat).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::AcidPuddle).LoadGFX());\r\n\t}\r\n\tif (mtype == MT_LICH) {\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::OrangeFlare).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::OrangeFlareExplosion).LoadGFX());\r\n\t}\r\n\tif (mtype == MT_ARCHLICH) {\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::YellowFlare).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::YellowFlareExplosion).LoadGFX());\r\n\t}\r\n\tif (IsAnyOf(mtype, MT_PSYCHORB, MT_BONEDEMN))\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BlueFlare2).LoadGFX());\r\n\tif (mtype == MT_NECRMORB) {\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::RedFlare).LoadGFX());\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::RedFlareExplosion).LoadGFX());\r\n\t}\r\n\tif (mtype == MT_PSYCHORB)\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BlueFlareExplosion).LoadGFX());\r\n\tif (mtype == MT_BONEDEMN)\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::BlueFlareExplosion2).LoadGFX());\r\n\tif (mtype == MT_DIABLO)\r\n\t\tRETURN_IF_ERROR(GetMissileSpriteData(MissileGraphicID::DiabloApocalypseBoom).LoadGFX());\r\n\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> InitAllMonsterGFX()\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn {};\r\n\r\n\tusing LevelMonsterTypeIndices = StaticVector<size_t, 8>;\r\n\tstd::vector<LevelMonsterTypeIndices> monstersBySprite(GetNumMonsterSprites());\r\n\tfor (size_t i = 0; i < LevelMonsterTypeCount; ++i) {\r\n\t\tmonstersBySprite[static_cast<size_t>(LevelMonsterTypes[i].data().spriteId)].emplace_back(i);\r\n\t}\r\n\tsize_t totalUniqueBytes = 0;\r\n\tsize_t totalBytes = 0;\r\n\tfor (const LevelMonsterTypeIndices &monsterTypes : monstersBySprite) {\r\n\t\tif (monsterTypes.empty())\r\n\t\t\tcontinue;\r\n\t\tCMonster &firstMonster = LevelMonsterTypes[monsterTypes[0]];\r\n\t\tif (firstMonster.animData != nullptr)\r\n\t\t\tcontinue;\r\n\t\tMonsterSpritesData spritesData = LoadMonsterSpritesData(firstMonster.data());\r\n\t\tconst size_t spritesDataSize = spritesData.offsets[GetNumAnimsWithGraphics(firstMonster.data())];\r\n\t\tfor (size_t i = 1; i < monsterTypes.size(); ++i) {\r\n\t\t\tMonsterSpritesData spritesDataCopy { std::unique_ptr<std::byte[]> { new std::byte[spritesDataSize] }, spritesData.offsets };\r\n\t\t\tmemcpy(spritesDataCopy.data.get(), spritesData.data.get(), spritesDataSize);\r\n\t\t\tRETURN_IF_ERROR(InitMonsterGFX(LevelMonsterTypes[monsterTypes[i]], std::move(spritesDataCopy)));\r\n\t\t}\r\n\t\tLogVerbose(\"Loaded monster graphics: {:15s} {:>4d} KiB   x{:d}\", firstMonster.data().spritePath(), spritesDataSize / 1024, monsterTypes.size());\r\n\t\ttotalUniqueBytes += spritesDataSize;\r\n\t\ttotalBytes += spritesDataSize * monsterTypes.size();\r\n\t\tRETURN_IF_ERROR(InitMonsterGFX(firstMonster, std::move(spritesData)));\r\n\t}\r\n\tLogVerbose(\" Total monster graphics:                 {:>4d} KiB {:>4d} KiB\", totalUniqueBytes / 1024, totalBytes / 1024);\r\n\r\n\tif (totalUniqueBytes > 0) {\r\n\t\t// we loaded new sprites, check if we need to update existing monsters\r\n\t\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\t\tMonster &monster = Monsters[ActiveMonsters[i]];\r\n\t\t\tif (!monster.animInfo.sprites)\r\n\t\t\t\tRETURN_IF_ERROR(SyncMonsterAnim(monster));\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid WeakenNaKrul()\r\n{\r\n\tif (currlevel != 24 || static_cast<size_t>(UberDiabloMonsterIndex) >= ActiveMonsterCount)\r\n\t\treturn;\r\n\r\n\tMonster &monster = Monsters[UberDiabloMonsterIndex];\r\n\tPlayEffect(monster, MonsterSound::Death);\r\n\tmonster.armorClass -= 50;\r\n\tconst int hp = monster.maxHitPoints / 2;\r\n\tmonster.resistance = 0;\r\n\tmonster.hitPoints = hp;\r\n\tmonster.maxHitPoints = hp;\r\n}\r\n\r\nvoid InitGolems()\r\n{\r\n\tif (!setlevel) {\r\n\t\tfor (int i = 0; i < ReservedMonsterSlotsForGolems; i++)\r\n\t\t\tAddMonster(GolemHoldingCell, Direction::South, 0, false);\r\n\t}\r\n}\r\n\r\ntl::expected<void, std::string> InitMonsters()\r\n{\r\n\tif (!gbIsSpawn && !setlevel && currlevel == 16)\r\n\t\tLoadDiabMonsts();\r\n\r\n\tint nt = numtrigs;\r\n\tif (currlevel == 15)\r\n\t\tnt = 1;\r\n\tfor (int i = 0; i < nt; i++) {\r\n\t\tfor (int s = -2; s < 2; s++) {\r\n\t\t\tfor (int t = -2; t < 2; t++)\r\n\t\t\t\tDoVision(trigs[i].position + Displacement { s, t }, 15, MAP_EXP_NONE, false);\r\n\t\t}\r\n\t}\r\n\tif (!gbIsSpawn)\r\n\t\tRETURN_IF_ERROR(PlaceQuestMonsters());\r\n\tif (!setlevel) {\r\n\t\tif (!gbIsSpawn)\r\n\t\t\tRETURN_IF_ERROR(PlaceUniqueMonsters());\r\n\t\tsize_t na = 0;\r\n\t\tfor (int s = 16; s < 96; s++) {\r\n\t\t\tfor (int t = 16; t < 96; t++) {\r\n\t\t\t\tif (!IsTileSolid({ s, t }))\r\n\t\t\t\t\tna++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tsize_t numplacemonsters = na / 30;\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tnumplacemonsters += numplacemonsters / 2;\r\n\t\tif (ActiveMonsterCount + numplacemonsters > MaxMonsters - 10)\r\n\t\t\tnumplacemonsters = MaxMonsters - 10 - ActiveMonsterCount;\r\n\t\ttotalmonsters = ActiveMonsterCount + numplacemonsters;\r\n\t\tint numscattypes = 0;\r\n\t\tsize_t scattertypes[NUM_MAX_MTYPES];\r\n\t\tfor (size_t i = 0; i < LevelMonsterTypeCount; i++) {\r\n\t\t\tif ((LevelMonsterTypes[i].placeFlags & PLACE_SCATTER) != 0) {\r\n\t\t\t\tscattertypes[numscattypes] = i;\r\n\t\t\t\tnumscattypes++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (numscattypes > 0) {\r\n\t\t\twhile (ActiveMonsterCount < totalmonsters) {\r\n\t\t\t\tconst size_t typeIndex = scattertypes[GenerateRnd(numscattypes)];\r\n\t\t\t\tif (currlevel == 1 || FlipCoin())\r\n\t\t\t\t\tna = 1;\r\n\t\t\t\telse if (currlevel == 2 || leveltype == DTYPE_CRYPT)\r\n\t\t\t\t\tna = GenerateRnd(2) + 2;\r\n\t\t\t\telse\r\n\t\t\t\t\tna = GenerateRnd(3) + 3;\r\n\t\t\t\tPlaceGroup(typeIndex, na);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor (int i = 0; i < nt; i++) {\r\n\t\tfor (int s = -2; s < 2; s++) {\r\n\t\t\tfor (int t = -2; t < 2; t++)\r\n\t\t\t\tDoUnVision(trigs[i].position + Displacement { s, t }, 15);\r\n\t\t}\r\n\t}\r\n\r\n\treturn InitAllMonsterGFX();\r\n}\r\n\r\ntl::expected<void, std::string> SetMapMonsters(const uint16_t *dunData, Point startPosition)\r\n{\r\n\tRETURN_IF_ERROR(AddMonsterType(MT_GOLEM, PLACE_SPECIAL));\r\n\tif (setlevel)\r\n\t\tfor (int i = 0; i < ReservedMonsterSlotsForGolems; i++)\r\n\t\t\tAddMonster(GolemHoldingCell, Direction::South, 0, false);\r\n\r\n\tWorldTileSize size = GetDunSize(dunData);\r\n\r\n\tconst int layer2Offset = 2 + (size.width * size.height);\r\n\r\n\t// The rest of the layers are at dPiece scale\r\n\tsize *= static_cast<WorldTileCoord>(2);\r\n\r\n\tconst uint16_t *monsterLayer = &dunData[layer2Offset + (size.width * size.height)];\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tauto monsterId = static_cast<uint8_t>(Swap16LE(monsterLayer[j * size.width + i]));\r\n\t\t\tif (monsterId != 0) {\r\n\t\t\t\tASSIGN_OR_RETURN(const size_t typeIndex, AddMonsterType(MonstConvTbl[monsterId - 1], PLACE_SPECIAL));\r\n\t\t\t\tPlaceMonster(ActiveMonsterCount++, typeIndex, startPosition + Displacement { i, j });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nMonster *AddMonster(Point position, Direction dir, size_t typeIndex, bool inMap)\r\n{\r\n\tif (ActiveMonsterCount < MaxMonsters) {\r\n\t\tMonster &monster = Monsters[ActiveMonsters[ActiveMonsterCount++]];\r\n\t\tif (inMap)\r\n\t\t\tmonster.occupyTile(position, false);\r\n\t\tInitMonster(monster, dir, typeIndex, position);\r\n\t\treturn &monster;\r\n\t}\r\n\r\n\treturn nullptr;\r\n}\r\n\r\nvoid SpawnMonster(Point position, Direction dir, size_t typeIndex)\r\n{\r\n\tif (ActiveMonsterCount >= MaxMonsters)\r\n\t\treturn;\r\n\r\n\t// The command is only executed for the level owner, to prevent desyncs in multiplayer.\r\n\tif (!MyPlayer->isLevelOwnedByLocalClient())\r\n\t\treturn;\r\n\r\n\tconst size_t monsterIndex = ActiveMonsters[ActiveMonsterCount];\r\n\tActiveMonsterCount += 1;\r\n\tconst uint32_t seed = GetLCGEngineState();\r\n\t// Update local state immediately to increase ActiveMonsterCount instantly (this allows multiple monsters to be spawned in one game tick)\r\n\tInitializeSpawnedMonster(position, dir, typeIndex, monsterIndex, seed, 0, 0);\r\n\tNetSendCmdSpawnMonster(position, dir, static_cast<uint16_t>(typeIndex), static_cast<uint16_t>(monsterIndex), seed, 0, 0);\r\n}\r\n\r\nvoid LoadDeltaSpawnedMonster(size_t typeIndex, size_t monsterId, uint32_t seed, uint8_t golemOwnerPlayerId, int16_t golemSpellLevel)\r\n{\r\n\tSetRndSeed(seed);\r\n\tEnsureMonsterIndexIsActive(monsterId);\r\n\tconst WorldTilePosition position = GolemHoldingCell;\r\n\tMonster &monster = Monsters[monsterId];\r\n\tM_ClearSquares(monster);\r\n\tInitMonster(monster, Direction::South, typeIndex, position);\r\n\tif (monster.type().type == MT_GOLEM) {\r\n\t\tInitGolem(monster, golemOwnerPlayerId, golemSpellLevel);\r\n\t}\r\n}\r\n\r\nvoid InitializeSpawnedMonster(Point position, Direction dir, size_t typeIndex, size_t monsterId, uint32_t seed, uint8_t golemOwnerPlayerId, int16_t golemSpellLevel)\r\n{\r\n\tSetRndSeed(seed);\r\n\tEnsureMonsterIndexIsActive(monsterId);\r\n\tMonster &monster = Monsters[monsterId];\r\n\tM_ClearSquares(monster);\r\n\r\n\t// When we receive a network message, the position we got for the new monster may already be occupied.\r\n\t// That's why we check for the next free tile for the monster.\r\n\tauto freePosition = Crawl(0, MaxCrawlRadius, [&](Displacement displacement) -> std::optional<Point> {\r\n\t\tPoint posToCheck = position + displacement;\r\n\t\tif (IsTileAvailable(posToCheck))\r\n\t\t\treturn posToCheck;\r\n\t\treturn {};\r\n\t});\r\n\r\n\tassert(freePosition);\r\n\tassert(!MyPlayer->isLevelOwnedByLocalClient() || (freePosition && position == *freePosition));\r\n\tposition = freePosition.value_or(position);\r\n\r\n\tmonster.occupyTile(position, false);\r\n\tInitMonster(monster, dir, typeIndex, position);\r\n\r\n\tif (monster.type().type == MT_GOLEM) {\r\n\t\tInitGolem(monster, golemOwnerPlayerId, golemSpellLevel);\r\n\t\tStartSpecialStand(monster, dir);\r\n\t} else if (IsSkel(monster.type().type)) {\r\n\t\tStartSpecialStand(monster, dir);\r\n\t} else {\r\n\t\tM_StartStand(monster, dir);\r\n\t}\r\n}\r\n\r\nvoid AddDoppelganger(Monster &monster)\r\n{\r\n\tPoint target = { 0, 0 };\r\n\tfor (int d = 0; d < 8; d++) {\r\n\t\tconst Point position = monster.position.tile + static_cast<Direction>(d);\r\n\t\tif (!IsTileAvailable(position))\r\n\t\t\tcontinue;\r\n\t\ttarget = position;\r\n\t}\r\n\tif (target != Point { 0, 0 }) {\r\n\t\tconst size_t typeIndex = GetMonsterTypeIndex(monster.type().type);\r\n\t\tSpawnMonster(target, monster.direction, typeIndex);\r\n\t}\r\n}\r\n\r\nvoid ApplyMonsterDamage(DamageType damageType, Monster &monster, int damage)\r\n{\r\n\tlua::OnMonsterTakeDamage(&monster, damage, static_cast<int>(damageType));\r\n\r\n\tmonster.hitPoints -= damage;\r\n\r\n\tif (monster.hasNoLife()) {\r\n\t\tdelta_kill_monster(monster, monster.position.tile, *MyPlayer);\r\n\t\tNetSendCmdLocParam1(false, CMD_MONSTDEATH, monster.position.tile, static_cast<uint16_t>(monster.getId()));\r\n\t\treturn;\r\n\t}\r\n\r\n\tdelta_monster_hp(monster, *MyPlayer);\r\n\tNetSendCmdMonDmg(false, static_cast<uint16_t>(monster.getId()), damage);\r\n}\r\n\r\nvoid MonsterReducePlayerAttribute(Monster &monster, Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tif (monster.reducePlayerStrength > 0) {\r\n\t\tModifyPlrStr(player, -static_cast<int>(monster.reducePlayerStrength));\r\n\t}\r\n\tif (monster.reducePlayerMagic > 0) {\r\n\t\tModifyPlrMag(player, -static_cast<int>(monster.reducePlayerMagic));\r\n\t}\r\n\tif (monster.reducePlayerDexterity > 0) {\r\n\t\tModifyPlrDex(player, -static_cast<int>(monster.reducePlayerDexterity));\r\n\t}\r\n\tif (monster.reducePlayerVitality > 0) {\r\n\t\tModifyPlrVit(player, -static_cast<int>(monster.reducePlayerVitality));\r\n\t}\r\n\tif (monster.reducePlayerMaxHP > 0) {\r\n\t\tconst int reduceAmount = std::min(player._pMaxHPBase - 64, monster.reducePlayerMaxHP * 64);\r\n\t\tplayer._pMaxHP = std::max(64, player._pMaxHP - reduceAmount);\r\n\t\tplayer._pHitPoints = std::min(player._pHitPoints, player._pMaxHP);\r\n\t\tplayer._pMaxHPBase -= reduceAmount;\r\n\t\tplayer._pHPBase = std::min(player._pHPBase, player._pMaxHPBase);\r\n\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t}\r\n\tif (monster.reducePlayerMaxMana > 0) {\r\n\t\tconst int reduceAmount = std::min(player._pMaxManaBase, monster.reducePlayerMaxMana * 64);\r\n\t\tplayer._pMaxMana = std::max(0, player._pMaxMana - reduceAmount);\r\n\t\tplayer._pMana = std::min(player._pMana, player._pMaxMana);\r\n\t\tplayer._pMaxManaBase -= reduceAmount;\r\n\t\tplayer._pManaBase = std::min(player._pManaBase, player._pMaxManaBase);\r\n\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t}\r\n}\r\n\r\nbool M_Talker(const Monster &monster)\r\n{\r\n\treturn IsAnyOf(monster.ai, MonsterAIID::Lazarus, MonsterAIID::Warlord, MonsterAIID::Gharbad, MonsterAIID::Zhar, MonsterAIID::Snotspill, MonsterAIID::Lachdanan, MonsterAIID::LazarusSuccubus);\r\n}\r\n\r\nvoid M_StartStand(Monster &monster, Direction md)\r\n{\r\n\tClearMVars(monster);\r\n\tif (monster.type().type == MT_GOLEM)\r\n\t\tNewMonsterAnim(monster, MonsterGraphic::Walk, md);\r\n\telse\r\n\t\tNewMonsterAnim(monster, MonsterGraphic::Stand, md);\r\n\tmonster.var1 = static_cast<int>(monster.mode);\r\n\tmonster.var2 = 0;\r\n\tmonster.mode = MonsterMode::Stand;\r\n\tmonster.position.future = monster.position.tile;\r\n\tmonster.position.old = monster.position.tile;\r\n\tUpdateEnemy(monster);\r\n}\r\n\r\nvoid M_ClearSquares(const Monster &monster)\r\n{\r\n\tfor (const Point searchTile : PointsInRectangle(Rectangle { monster.position.old, 1 })) {\r\n\t\tif (FindMonsterAtPosition(searchTile) == &monster)\r\n\t\t\tdMonster[searchTile.x][searchTile.y] = 0;\r\n\t}\r\n}\r\n\r\nvoid M_GetKnockback(Monster &monster, WorldTilePosition attackerStartPos)\r\n{\r\n\tconst Direction dir = GetDirection(attackerStartPos, monster.position.tile);\r\n\tif (!IsRelativeMoveOK(monster, monster.position.old, dir)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tM_ClearSquares(monster);\r\n\tmonster.position.old += dir;\r\n\tStartMonsterGotHit(monster);\r\n\tChangeLightXY(monster.lightId, monster.position.tile);\r\n}\r\n\r\nvoid M_StartHit(Monster &monster, int dam)\r\n{\r\n\tPlayEffect(monster, MonsterSound::Hit);\r\n\r\n\tif (IsHardHit(monster, dam)) {\r\n\t\tif (monster.type().type == MT_BLINK) {\r\n\t\t\tTeleport(monster);\r\n\t\t} else if (IsAnyOf(monster.type().type, MT_NSCAV, MT_BSCAV, MT_WSCAV, MT_YSCAV, MT_GRAVEDIG)) {\r\n\t\t\tmonster.goal = MonsterGoal::Normal;\r\n\t\t\tmonster.goalVar1 = 0;\r\n\t\t\tmonster.goalVar2 = 0;\r\n\t\t}\r\n\t\tif (monster.mode != MonsterMode::Petrified) {\r\n\t\t\tStartMonsterGotHit(monster);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid M_StartHit(Monster &monster, const Player &player, int dam)\r\n{\r\n\tmonster.tag(player);\r\n\tif (IsHardHit(monster, dam)) {\r\n\t\tmonster.enemy = player.getId();\r\n\t\tmonster.enemyPosition = player.position.future;\r\n\t\tmonster.flags &= ~MFLAG_TARGETS_MONSTER;\r\n\t\tif (monster.mode != MonsterMode::Petrified) {\r\n\t\t\tmonster.direction = GetMonsterDirection(monster);\r\n\t\t}\r\n\t}\r\n\r\n\tM_StartHit(monster, dam);\r\n}\r\n\r\nvoid MonsterDeath(Monster &monster, Direction md, bool sendmsg)\r\n{\r\n\tif (!monster.isPlayerMinion())\r\n\t\tAddPlrMonstExper(monster.level(sgGameInitInfo.nDifficulty), monster.exp(sgGameInitInfo.nDifficulty), monster.whoHit);\r\n\r\n\tMonsterKillCounts[monster.type().type]++;\r\n\tmonster.hitPoints = 0;\r\n\tmonster.flags &= ~MFLAG_HIDDEN;\r\n\tSetRndSeed(monster.rndItemSeed);\r\n\r\n\tSpawnLoot(monster, sendmsg);\r\n\r\n\tif (monster.type().type == MT_DIABLO)\r\n\t\tDiabloDeath(monster, true);\r\n\telse\r\n\t\tPlayEffect(monster, MonsterSound::Death);\r\n\r\n\tif (monster.mode != MonsterMode::Petrified) {\r\n\t\tif (monster.type().type == MT_GOLEM)\r\n\t\t\tmd = Direction::South;\r\n\t\tNewMonsterAnim(monster, MonsterGraphic::Death, md, gGameLogicStep < GameLogicStep::ProcessMonsters ? AnimationDistributionFlags::ProcessAnimationPending : AnimationDistributionFlags::None);\r\n\t\tmonster.mode = MonsterMode::Death;\r\n\t} else if (monster.isUnique()) {\r\n\t\tAddUnLight(monster.lightId);\r\n\t}\r\n\tmonster.goal = MonsterGoal::None;\r\n\tmonster.var1 = 0;\r\n\tmonster.position.tile = monster.position.old;\r\n\tmonster.position.future = monster.position.old;\r\n\tM_ClearSquares(monster);\r\n\tmonster.occupyTile(monster.position.tile, false);\r\n\tCheckQuestKill(monster, sendmsg);\r\n\tM_FallenFear(monster.position.tile);\r\n\tif (IsAnyOf(monster.type().type, MT_NACID, MT_RACID, MT_BACID, MT_XACID, MT_SPIDLORD))\r\n\t\tAddMissile(monster.position.tile, { 0, 0 }, Direction::South, MissileID::AcidPuddle, TARGET_PLAYERS, monster, monster.intelligence + 1, 0);\r\n}\r\n\r\nvoid StartMonsterDeath(Monster &monster, const Player &player, bool sendmsg)\r\n{\r\n\tmonster.tag(player);\r\n\tconst Direction md = GetDirection(monster.position.tile, player.position.tile);\r\n\tMonsterDeath(monster, md, sendmsg);\r\n}\r\n\r\nvoid KillGolem(Monster &golem)\r\n{\r\n\tdelta_kill_monster(golem, golem.position.tile, *MyPlayer);\r\n\tNetSendCmdLocParam1(false, CMD_MONSTDEATH, golem.position.tile, static_cast<uint16_t>(golem.getId()));\r\n\tM_StartKill(golem, *MyPlayer);\r\n}\r\n\r\nvoid M_StartKill(Monster &monster, const Player &player)\r\n{\r\n\tStartMonsterDeath(monster, player, true);\r\n}\r\n\r\nvoid M_SyncStartKill(Monster &monster, Point position, const Player &player)\r\n{\r\n\tif (monster.hitPoints == 0 || monster.mode == MonsterMode::Death) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (dMonster[position.x][position.y] == 0) {\r\n\t\tM_ClearSquares(monster);\r\n\t\tmonster.position.tile = position;\r\n\t\tmonster.position.old = position;\r\n\t}\r\n\r\n\tStartMonsterDeath(monster, player, false);\r\n}\r\n\r\nvoid M_UpdateRelations(const Monster &monster)\r\n{\r\n\tif (monster.hasLeashedMinions())\r\n\t\tReleaseMinions(monster);\r\n\r\n\tShrinkLeaderPacksize(monster);\r\n}\r\n\r\nvoid DoEnding()\r\n{\r\n\tif (gbIsMultiplayer) {\r\n\t\tSNetLeaveGame(leaveinfo_t::LEAVE_ENDING);\r\n\t}\r\n\r\n\tmusic_stop();\r\n\r\n\tif (gbIsMultiplayer) {\r\n\t\tSDL_Delay(1000);\r\n\t}\r\n\r\n\tif (gbIsSpawn)\r\n\t\treturn;\r\n\r\n\tswitch (MyPlayer->_pClass) {\r\n\tcase HeroClass::Sorcerer:\r\n\tcase HeroClass::Monk:\r\n\t\tplay_movie(\"gendata\\\\diabvic1.smk\", false);\r\n\t\tbreak;\r\n\tcase HeroClass::Warrior:\r\n\tcase HeroClass::Barbarian:\r\n\t\tplay_movie(\"gendata\\\\diabvic2.smk\", false);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tplay_movie(\"gendata\\\\diabvic3.smk\", false);\r\n\t\tbreak;\r\n\t}\r\n\tplay_movie(\"gendata\\\\diabend.smk\", false);\r\n\r\n\tconst bool bMusicOn = gbMusicOn;\r\n\tgbMusicOn = true;\r\n\r\n\tconst int musicVolume = sound_get_or_set_music_volume(1);\r\n\tsound_get_or_set_music_volume(0);\r\n\r\n\tmusic_start(TMUSIC_CATACOMBS);\r\n\tloop_movie = true;\r\n\tplay_movie(\"gendata\\\\loopdend.smk\", true);\r\n\tloop_movie = false;\r\n\tmusic_stop();\r\n\r\n\tsound_get_or_set_music_volume(musicVolume);\r\n\tgbMusicOn = bMusicOn;\r\n}\r\n\r\nvoid PrepDoEnding()\r\n{\r\n\tgbSoundOn = sgbSaveSoundOn;\r\n\tgbRunGame = false;\r\n\tMyPlayerIsDead = false;\r\n\tcineflag = true;\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tmyPlayer.pDiabloKillLevel = std::max(myPlayer.pDiabloKillLevel, static_cast<uint8_t>(sgGameInitInfo.nDifficulty + 1));\r\n\r\n\tfor (Player &player : Players) {\r\n\t\tplayer._pmode = PM_QUIT;\r\n\t\tplayer._pInvincible = true;\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tif (player.hasNoLife())\r\n\t\t\t\tplayer._pHitPoints = 64;\r\n\t\t\tif (player.hasNoMana())\r\n\t\t\t\tplayer._pMana = 64;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Walk(Monster &monster, Direction md)\r\n{\r\n\tif (!DirOK(monster, md)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (md == Direction::NoDirection)\r\n\t\treturn true;\r\n\r\n\tWalkInDirection(monster, md);\r\n\treturn true;\r\n}\r\n\r\nvoid GolumAi(Monster &golem)\r\n{\r\n\tif (golem.position.tile.x == 1 && golem.position.tile.y == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (IsAnyOf(golem.mode, MonsterMode::Death, MonsterMode::SpecialStand) || golem.isWalking()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ((golem.flags & MFLAG_TARGETS_MONSTER) == 0)\r\n\t\tUpdateEnemy(golem);\r\n\r\n\tif (golem.mode == MonsterMode::MeleeAttack) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ((golem.flags & MFLAG_NO_ENEMY) == 0) {\r\n\t\tMonster &enemy = Monsters[golem.enemy];\r\n\t\tconst int mex = golem.position.tile.x - enemy.position.future.x;\r\n\t\tconst int mey = golem.position.tile.y - enemy.position.future.y;\r\n\t\tgolem.direction = GetDirection(golem.position.tile, enemy.position.tile);\r\n\t\tif (std::abs(mex) < 2 && std::abs(mey) < 2) {\r\n\t\t\tgolem.enemyPosition = enemy.position.tile;\r\n\t\t\tif (enemy.activeForTicks == 0) {\r\n\t\t\t\tenemy.activeForTicks = UINT8_MAX;\r\n\t\t\t\tenemy.position.last = golem.position.tile;\r\n\t\t\t\tfor (int j = 0; j < 5; j++) {\r\n\t\t\t\t\tfor (int k = 0; k < 5; k++) {\r\n\t\t\t\t\t\tconst int mx = golem.position.tile.x + k - 2;\r\n\t\t\t\t\t\tconst int my = golem.position.tile.y + j - 2;\r\n\t\t\t\t\t\tif (!InDungeonBounds({ mx, my }))\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tconst int enemyId = dMonster[mx][my];\r\n\t\t\t\t\t\tif (enemyId > 0)\r\n\t\t\t\t\t\t\tMonsters[enemyId - 1].activeForTicks = UINT8_MAX;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tStartAttack(golem);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (AiPlanPath(golem))\r\n\t\t\treturn;\r\n\t}\r\n\r\n\tgolem.pathCount++;\r\n\tif (golem.pathCount > 8)\r\n\t\tgolem.pathCount = 5;\r\n\r\n\tif (RandomWalk(golem, Players[golem.goalVar3]._pdir))\r\n\t\treturn;\r\n\r\n\tDirection md = Left(golem.direction);\r\n\tfor (int j = 0; j < 8; j++) {\r\n\t\tmd = Right(md);\r\n\t\tif (Walk(golem, md)) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DeleteMonsterList()\r\n{\r\n\tfor (int i = 0; i < ReservedMonsterSlotsForGolems; i++) {\r\n\t\tMonster &golem = Monsters[i];\r\n\t\tif (!golem.isInvalid)\r\n\t\t\tcontinue;\r\n\r\n\t\tgolem.position.tile = GolemHoldingCell;\r\n\t\tgolem.position.future = { 0, 0 };\r\n\t\tgolem.position.old = { 0, 0 };\r\n\t\tgolem.isInvalid = false;\r\n\t}\r\n\r\n\tfor (size_t i = ReservedMonsterSlotsForGolems; i < ActiveMonsterCount;) {\r\n\t\tif (Monsters[ActiveMonsters[i]].isInvalid) {\r\n\t\t\tif (pcursmonst == static_cast<int>(ActiveMonsters[i])) // Unselect monster if player highlighted it\r\n\t\t\t\tpcursmonst = -1;\r\n\t\t\tDeleteMonster(i);\r\n\t\t} else {\r\n\t\t\ti++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid RemoveEnemyReferences(const Player &player)\r\n{\r\n\tif (&player == MyPlayer || !player.isOnActiveLevel())\r\n\t\treturn;\r\n\r\n\tconst size_t playerId = player.getId();\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tMonster &activeMonster = Monsters[ActiveMonsters[i]];\r\n\t\tif ((activeMonster.flags & MFLAG_TARGETS_MONSTER) == 0 && activeMonster.enemy == playerId) {\r\n\t\t\tactiveMonster.flags |= MFLAG_NO_ENEMY;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ProcessMonsters()\r\n{\r\n\tDeleteMonsterList();\r\n\r\n\tassert(ActiveMonsterCount <= MaxMonsters);\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tMonster &monster = Monsters[ActiveMonsters[i]];\r\n\t\tFollowTheLeader(monster);\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tSetRndSeed(monster.aiSeed);\r\n\t\t\tmonster.aiSeed = AdvanceRndSeed();\r\n\t\t}\r\n\t\tif (monster.hitPoints < monster.maxHitPoints && !monster.hasNoLife()) {\r\n\t\t\tif (monster.level(sgGameInitInfo.nDifficulty) > 1) {\r\n\t\t\t\tmonster.hitPoints += monster.level(sgGameInitInfo.nDifficulty) / 2;\r\n\t\t\t} else {\r\n\t\t\t\tmonster.hitPoints += monster.level(sgGameInitInfo.nDifficulty);\r\n\t\t\t}\r\n\t\t\tmonster.hitPoints = std::min(monster.hitPoints, monster.maxHitPoints); // prevent going over max HP with part of a single regen tick\r\n\t\t}\r\n\r\n\t\tconst bool isMonsterVisible = IsTileVisible(monster.position.tile);\r\n\t\tif (isMonsterVisible && monster.activeForTicks == 0) {\r\n\t\t\tif (monster.type().type == MT_CLEAVER) {\r\n\t\t\t\tPlaySFX(SfxID::ButcherGreeting);\r\n\t\t\t}\r\n\t\t\tif (monster.type().type == MT_NAKRUL) {\r\n\t\t\t\tif (sgGameInitInfo.bCowQuest != 0) {\r\n\t\t\t\t\tPlaySFX(SfxID::NaKrul6);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (IsUberRoomOpened)\r\n\t\t\t\t\t\tPlaySFX(SfxID::NaKrul4);\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tPlaySFX(SfxID::NaKrul5);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (monster.type().type == MT_DEFILER)\r\n\t\t\t\tPlaySFX(SfxID::Defiler8);\r\n\t\t\tUpdateEnemy(monster);\r\n\t\t}\r\n\r\n\t\tif ((monster.flags & MFLAG_NO_ENEMY) == 0) {\r\n\t\t\tif ((monster.flags & MFLAG_TARGETS_MONSTER) != 0) {\r\n\t\t\t\tassert(monster.enemy >= 0 && monster.enemy < MaxMonsters);\r\n\t\t\t\tmonster.position.last = Monsters[monster.enemy].position.future;\r\n\t\t\t\tmonster.enemyPosition = monster.position.last;\r\n\t\t\t} else {\r\n\t\t\t\tassert(monster.enemy >= 0 && monster.enemy < MAX_PLRS);\r\n\t\t\t\tconst Player &player = Players[monster.enemy];\r\n\t\t\t\tmonster.enemyPosition = player.position.future;\r\n\t\t\t\tif (isMonsterVisible) {\r\n\t\t\t\t\tmonster.position.last = player.position.future;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ((monster.flags & MFLAG_TARGETS_MONSTER) == 0) {\r\n\t\t\tif (isMonsterVisible) {\r\n\t\t\t\tmonster.activeForTicks = UINT8_MAX;\r\n\t\t\t} else if (monster.activeForTicks != 0 && monster.type().type != MT_DIABLO) {\r\n\t\t\t\tmonster.activeForTicks--;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\twhile (true) {\r\n\t\t\tif ((monster.flags & MFLAG_SEARCH) == 0 || !AiPlanPath(monster)) {\r\n\t\t\t\tAiProc[static_cast<int8_t>(monster.ai)](monster);\r\n\t\t\t}\r\n\r\n\t\t\tif (!UpdateModeStance(monster))\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tGroupUnity(monster);\r\n\t\t}\r\n\t\tif (monster.mode != MonsterMode::Petrified && (monster.flags & MFLAG_ALLOW_SPECIAL) == 0) {\r\n\t\t\tmonster.animInfo.processAnimation((monster.flags & MFLAG_LOCK_ANIMATION) != 0);\r\n\t\t}\r\n\t}\r\n\r\n\tDeleteMonsterList();\r\n}\r\n\r\nvoid FreeMonsters()\r\n{\r\n\tfor (CMonster &monsterType : LevelMonsterTypes) {\r\n\t\tmonsterType.animData = nullptr;\r\n\t\tmonsterType.corpseId = 0;\r\n\t\tfor (AnimStruct &animData : monsterType.anims) {\r\n\t\t\tanimData.sprites = std::nullopt;\r\n\t\t}\r\n\r\n\t\tfor (auto &variants : monsterType.sounds) {\r\n\t\t\tfor (auto &sound : variants) {\r\n\t\t\t\tsound = nullptr;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool DirOK(const Monster &monster, Direction mdir)\r\n{\r\n\tconst Point position = monster.position.tile;\r\n\tconst Point futurePosition = position + mdir;\r\n\tif (!IsRelativeMoveOK(monster, position, mdir))\r\n\t\treturn false;\r\n\tif (monster.leaderRelation == LeaderRelation::Leashed) {\r\n\t\treturn futurePosition.WalkingDistance(monster.getLeader()->position.future) < 4;\r\n\t}\r\n\tif (!monster.hasLeashedMinions())\r\n\t\treturn true;\r\n\tint mcount = 0;\r\n\tfor (int x = futurePosition.x - 3; x <= futurePosition.x + 3; x++) {\r\n\t\tfor (int y = futurePosition.y - 3; y <= futurePosition.y + 3; y++) {\r\n\t\t\tif (!InDungeonBounds({ x, y }))\r\n\t\t\t\tcontinue;\r\n\t\t\tMonster *minion = FindMonsterAtPosition({ x, y }, true);\r\n\t\t\tif (minion == nullptr)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif (minion->leaderRelation == LeaderRelation::Leashed && minion->getLeader() == &monster) {\r\n\t\t\t\tmcount++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn mcount == monster.packSize;\r\n}\r\n\r\nbool LineClearMissile(Point startPoint, Point endPoint)\r\n{\r\n\treturn LineClear(PosOkMissile, startPoint, endPoint);\r\n}\r\n\r\nbool LineClearMovingMissile(Point startPoint, Point endPoint)\r\n{\r\n\treturn LineClear(PosOkMovingMissile, startPoint, endPoint);\r\n}\r\n\r\ntl::expected<void, std::string> SyncMonsterAnim(Monster &monster)\r\n{\r\n#ifdef _DEBUG\r\n\t// fix for saves with debug monsters having type originally not on the level\r\n\tCMonster &monsterType = LevelMonsterTypes[monster.levelType];\r\n\tif (monsterType.corpseId == 0) {\r\n\t\tRETURN_IF_ERROR(InitMonsterGFX(monsterType));\r\n\t\tmonsterType.corpseId = 1;\r\n\t}\r\n#endif\r\n\tif (monster.isUnique()) {\r\n\t\tRETURN_IF_ERROR(InitTRNForUniqueMonster(monster));\r\n\t}\r\n\tMonsterGraphic graphic = MonsterGraphic::Stand;\r\n\r\n\tswitch (monster.getVisualMonsterMode()) {\r\n\tcase MonsterMode::Stand:\r\n\tcase MonsterMode::Delay:\r\n\tcase MonsterMode::Talk:\r\n\t\tbreak;\r\n\tcase MonsterMode::MoveNorthwards:\r\n\tcase MonsterMode::MoveSouthwards:\r\n\tcase MonsterMode::MoveSideways:\r\n\t\tgraphic = MonsterGraphic::Walk;\r\n\t\tbreak;\r\n\tcase MonsterMode::MeleeAttack:\r\n\tcase MonsterMode::RangedAttack:\r\n\t\tgraphic = MonsterGraphic::Attack;\r\n\t\tbreak;\r\n\tcase MonsterMode::HitRecovery:\r\n\t\tgraphic = MonsterGraphic::GotHit;\r\n\t\tbreak;\r\n\tcase MonsterMode::Death:\r\n\t\tgraphic = MonsterGraphic::Death;\r\n\t\tbreak;\r\n\tcase MonsterMode::SpecialMeleeAttack:\r\n\tcase MonsterMode::FadeIn:\r\n\tcase MonsterMode::FadeOut:\r\n\tcase MonsterMode::SpecialStand:\r\n\tcase MonsterMode::SpecialRangedAttack:\r\n\tcase MonsterMode::Heal:\r\n\t\tgraphic = MonsterGraphic::Special;\r\n\t\tbreak;\r\n\tcase MonsterMode::Charge:\r\n\t\tgraphic = MonsterGraphic::Attack;\r\n\t\tmonster.animInfo.currentFrame = 0;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tmonster.animInfo.currentFrame = 0;\r\n\t\tbreak;\r\n\t}\r\n\r\n\tmonster.changeAnimationData(graphic);\r\n\treturn {};\r\n}\r\n\r\nvoid M_FallenFear(Point position)\r\n{\r\n\tconst Rectangle fearArea = Rectangle { position, 4 };\r\n\tfor (const Point tile : PointsInRectangle(fearArea)) {\r\n\t\tif (!InDungeonBounds(tile))\r\n\t\t\tcontinue;\r\n\t\tconst int m = dMonster[tile.x][tile.y];\r\n\t\tif (m == 0)\r\n\t\t\tcontinue;\r\n\t\tMonster &monster = Monsters[std::abs(m) - 1];\r\n\t\tif (monster.ai != MonsterAIID::Fallen || monster.hasNoLife())\r\n\t\t\tcontinue;\r\n\r\n\t\tconst int runDistance = std::max((8 - monster.data().level), 2);\r\n\t\tmonster.goal = MonsterGoal::Retreat;\r\n\t\tmonster.goalVar1 = runDistance;\r\n\t\tmonster.goalVar2 = static_cast<int>(GetDirection(position, monster.position.tile));\r\n\t}\r\n}\r\n\r\nvoid PrintMonstHistory(int mt)\r\n{\r\n\tif (*GetOptions().Gameplay.showMonsterType) {\r\n\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Type: {:s}  Kills: {:d}\")), GetMonsterTypeText(MonstersData[mt]), MonsterKillCounts[mt]));\r\n\t} else {\r\n\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Total kills: {:d}\")), MonsterKillCounts[mt]));\r\n\t}\r\n\r\n\tif (MonsterKillCounts[mt] >= 30) {\r\n\t\tint minHP = MonstersData[mt].hitPointsMinimum;\r\n\t\tint maxHP = MonstersData[mt].hitPointsMaximum;\r\n\t\tif (!gbIsMultiplayer) {\r\n\t\t\tminHP /= 2;\r\n\t\t\tmaxHP /= 2;\r\n\t\t}\r\n\t\tminHP = std::max(minHP, 1);\r\n\t\tmaxHP = std::max(maxHP, 1);\r\n\r\n\t\tint hpBonusNightmare = 100;\r\n\t\tint hpBonusHell = 200;\r\n\t\tif (gbIsHellfire) {\r\n\t\t\thpBonusNightmare = (!gbIsMultiplayer ? 50 : 100);\r\n\t\t\thpBonusHell = (!gbIsMultiplayer ? 100 : 200);\r\n\t\t}\r\n\t\tif (sgGameInitInfo.nDifficulty == DIFF_NIGHTMARE) {\r\n\t\t\tminHP = 3 * minHP + hpBonusNightmare;\r\n\t\t\tmaxHP = 3 * maxHP + hpBonusNightmare;\r\n\t\t} else if (sgGameInitInfo.nDifficulty == DIFF_HELL) {\r\n\t\t\tminHP = 4 * minHP + hpBonusHell;\r\n\t\t\tmaxHP = 4 * maxHP + hpBonusHell;\r\n\t\t}\r\n\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Hit Points: {:d}-{:d}\")), minHP, maxHP));\r\n\t}\r\n\tif (MonsterKillCounts[mt] >= 15) {\r\n\t\tconst int res = (sgGameInitInfo.nDifficulty != DIFF_HELL) ? MonstersData[mt].resistance : MonstersData[mt].resistanceHell;\r\n\t\tif ((res & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING)) == 0) {\r\n\t\t\tAddInfoBoxString(_(\"No magic resistance\"));\r\n\t\t} else {\r\n\t\t\tif ((res & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING)) != 0) {\r\n\t\t\t\tstd::string resists = std::string(_(\"Resists:\"));\r\n\t\t\t\tif ((res & RESIST_MAGIC) != 0)\r\n\t\t\t\t\tresists.append(_(\" Magic\"));\r\n\t\t\t\tif ((res & RESIST_FIRE) != 0)\r\n\t\t\t\t\tresists.append(_(\" Fire\"));\r\n\t\t\t\tif ((res & RESIST_LIGHTNING) != 0)\r\n\t\t\t\t\tresists.append(_(\" Lightning\"));\r\n\t\t\t\tAddInfoBoxString(resists);\r\n\t\t\t}\r\n\t\t\tif ((res & (IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING)) != 0) {\r\n\t\t\t\tstd::string immune = std::string(_(\"Immune:\"));\r\n\t\t\t\tif ((res & IMMUNE_MAGIC) != 0)\r\n\t\t\t\t\timmune.append(_(\" Magic\"));\r\n\t\t\t\tif ((res & IMMUNE_FIRE) != 0)\r\n\t\t\t\t\timmune.append(_(\" Fire\"));\r\n\t\t\t\tif ((res & IMMUNE_LIGHTNING) != 0)\r\n\t\t\t\t\timmune.append(_(\" Lightning\"));\r\n\t\t\t\tAddInfoBoxString(immune);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PrintUniqueHistory()\r\n{\r\n\tconst Monster &monster = Monsters[pcursmonst];\r\n\tif (*GetOptions().Gameplay.showMonsterType) {\r\n\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Type: {:s}\")), GetMonsterTypeText(monster.data())));\r\n\t}\r\n\r\n\tconst int res = monster.resistance & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING);\r\n\tif (res == 0) {\r\n\t\tAddInfoBoxString(_(\"No resistances\"));\r\n\t\tAddInfoBoxString(_(\"No Immunities\"));\r\n\t} else {\r\n\t\tif ((res & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING)) != 0)\r\n\t\t\tAddInfoBoxString(_(\"Some Magic Resistances\"));\r\n\t\telse\r\n\t\t\tAddInfoBoxString(_(\"No resistances\"));\r\n\t\tif ((res & (IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING)) != 0) {\r\n\t\t\tAddInfoBoxString(_(\"Some Magic Immunities\"));\r\n\t\t} else {\r\n\t\t\tAddInfoBoxString(_(\"No Immunities\"));\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlayEffect(Monster &monster, MonsterSound mode)\r\n{\r\n\tif (MyPlayer->pLvlLoad != 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int sndIdx = GenerateRnd(2);\r\n\tif (!gbSndInited || !gbSoundOn || gbBufferMsgs != 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tTSnd *snd = monster.type().sounds[static_cast<size_t>(mode)][sndIdx].get();\r\n\tif (snd == nullptr || snd->isPlaying()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tint lVolume = 0;\r\n\tint lPan = 0;\r\n\tif (!CalculateSoundPosition(monster.position.tile, &lVolume, &lPan))\r\n\t\treturn;\r\n\r\n\tsnd_play_snd(snd, lVolume, lPan, *GetOptions().Audio.soundVolume);\r\n}\r\n\r\nvoid MissToMonst(Missile &missile, Point position)\r\n{\r\n\tassert(static_cast<size_t>(missile._misource) < MaxMonsters);\r\n\tMonster &monster = Monsters[missile._misource];\r\n\r\n\tconst Point oldPosition = missile.position.tile;\r\n\tmonster.occupyTile(position, false);\r\n\tmonster.direction = missile.getDirection();\r\n\tmonster.position.tile = position;\r\n\tM_StartStand(monster, monster.direction);\r\n\tM_StartHit(monster, 0);\r\n\r\n\tif (monster.type().type == MT_GLOOM)\r\n\t\treturn;\r\n\r\n\tif ((monster.flags & MFLAG_TARGETS_MONSTER) == 0) {\r\n\t\tPlayer *player = PlayerAtPosition(oldPosition, true);\r\n\t\tif (player == nullptr)\r\n\t\t\treturn;\r\n\r\n\t\tMonsterAttackPlayer(monster, *player, 500, monster.minDamageSpecial, monster.maxDamageSpecial);\r\n\r\n\t\tif (IsAnyOf(monster.type().type, MT_NSNAKE, MT_RSNAKE, MT_BSNAKE, MT_GSNAKE))\r\n\t\t\treturn;\r\n\r\n\t\tif (player->_pmode != PM_GOTHIT && player->_pmode != PM_DEATH)\r\n\t\t\tStartPlrHit(*player, 0, true);\r\n\t\tconst Point newPosition = oldPosition + GetDirection(missile.position.start, oldPosition);\r\n\t\tif (PosOkPlayer(*player, newPosition)) {\r\n\t\t\tplayer->position.tile = newPosition;\r\n\t\t\tFixPlayerLocation(*player, player->_pdir);\r\n\t\t\tFixPlrWalkTags(*player);\r\n\t\t\tplayer->occupyTile(newPosition, false);\r\n\t\t\tSetPlayerOld(*player);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tMonster *target = FindMonsterAtPosition(oldPosition, true);\r\n\r\n\tif (target == nullptr)\r\n\t\treturn;\r\n\r\n\tMonsterAttackMonster(monster, *target, 500, monster.minDamageSpecial, monster.maxDamageSpecial);\r\n\r\n\tif (IsAnyOf(monster.type().type, MT_NSNAKE, MT_RSNAKE, MT_BSNAKE, MT_GSNAKE))\r\n\t\treturn;\r\n\r\n\tconst Point newPosition = oldPosition + GetDirection(missile.position.start, oldPosition);\r\n\tif (IsTileAvailable(*target, newPosition)) {\r\n\t\tmonster.occupyTile(newPosition, false);\r\n\t\tdMonster[oldPosition.x][oldPosition.y] = 0;\r\n\t\tmonster.position.tile = newPosition;\r\n\t\tmonster.position.future = newPosition;\r\n\t}\r\n}\r\n\r\nMonster *FindMonsterAtPosition(Point position, bool ignoreMovingMonsters)\r\n{\r\n\tif (!InDungeonBounds(position)) {\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tauto monsterId = dMonster[position.x][position.y];\r\n\r\n\tif (monsterId == 0 || (ignoreMovingMonsters && monsterId < 0)) {\r\n\t\t// nothing at this position, return a nullptr\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\treturn &Monsters[std::abs(monsterId) - 1];\r\n}\r\n\r\nMonster *FindUniqueMonster(UniqueMonsterType monsterType)\r\n{\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst int monsterId = ActiveMonsters[i];\r\n\t\tMonster &monster = Monsters[monsterId];\r\n\t\tif (monster.uniqueType == monsterType)\r\n\t\t\treturn &monster;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nMonster *FindGolemForPlayer(const Player &player)\r\n{\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst int monsterId = ActiveMonsters[i];\r\n\t\tMonster &monster = Monsters[monsterId];\r\n\t\tif (monster.type().type != MT_GOLEM)\r\n\t\t\tcontinue;\r\n\t\tif (monster.position.tile == GolemHoldingCell)\r\n\t\t\tcontinue;\r\n\t\tif (monster.goalVar3 != player.getId())\r\n\t\t\tcontinue;\r\n\t\tif (monster.hitPoints == 0)\r\n\t\t\tcontinue;\r\n\t\treturn &monster;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nbool IsTileAvailable(const Monster &monster, Point position)\r\n{\r\n\tif (!IsTileAvailable(position))\r\n\t\treturn false;\r\n\r\n\treturn IsTileSafe(monster, position);\r\n}\r\n\r\nbool IsSkel(_monster_id mt)\r\n{\r\n\treturn c_find(SkeletonTypes, mt) != SkeletonTypes.end();\r\n}\r\n\r\nbool IsGoat(_monster_id mt)\r\n{\r\n\treturn IsAnyOf(mt,\r\n\t    MT_NGOATMC, MT_BGOATMC, MT_RGOATMC, MT_GGOATMC,\r\n\t    MT_NGOATBW, MT_BGOATBW, MT_RGOATBW, MT_GGOATBW);\r\n}\r\n\r\nvoid ActivateSkeleton(Monster &monster, Point position)\r\n{\r\n\tif (IsTileAvailable(position)) {\r\n\t\tActivateSpawn(monster, position, Direction::SouthWest);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconstexpr std::array<Direction, 8> spawnDirections {\r\n\t\tDirection::North, Direction::NorthEast, Direction::East, Direction::NorthWest, Direction::SouthEast, Direction::West, Direction::SouthWest, Direction::South\r\n\t};\r\n\tstd::bitset<8> spawnOk;\r\n\r\n\tfor (size_t i = 0; i < spawnDirections.size(); i++) {\r\n\t\tif (IsTileAvailable(position + spawnDirections[i]))\r\n\t\t\tspawnOk.set(i);\r\n\t}\r\n\tif (spawnOk.none())\r\n\t\treturn;\r\n\r\n\t// this is used in the following loop to find the nth set bit.\r\n\tint spawnChoice = GenerateRnd(15) % spawnOk.count();\r\n\r\n\tfor (size_t i = 0; i < spawnOk.size(); i++) {\r\n\t\tif (!spawnOk.test(i))\r\n\t\t\tcontinue;\r\n\r\n\t\tif (spawnChoice > 0) {\r\n\t\t\tspawnChoice--;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tActivateSpawn(monster, position + spawnDirections[i], Opposite(spawnDirections[i]));\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\nMonster *PreSpawnSkeleton()\r\n{\r\n\tMonster *skeleton = AddSkeleton({ 0, 0 }, Direction::South, false);\r\n\tif (skeleton != nullptr)\r\n\t\tM_StartStand(*skeleton, Direction::South);\r\n\r\n\treturn skeleton;\r\n}\r\n\r\nvoid TalktoMonster(Player &player, Monster &monster)\r\n{\r\n\tif (&player == MyPlayer)\r\n\t\tmonster.mode = MonsterMode::Talk;\r\n\r\n\tif (monster.uniqueType == UniqueMonsterType::SnotSpill\r\n\t    && Quests[Q_LTBANNER].IsAvailable() && Quests[Q_LTBANNER]._qvar1 == 2) {\r\n\t\tif (RemoveInventoryItemById(player, IDI_BANNER)) {\r\n\t\t\tQuests[Q_LTBANNER]._qactive = QUEST_DONE;\r\n\t\t\tmonster.talkMsg = TEXT_BANNER12;\r\n\t\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_LTBANNER]);\r\n\t\t}\r\n\t}\r\n\tif (monster.uniqueType == UniqueMonsterType::Lachdan\r\n\t    && Quests[Q_VEIL].IsAvailable() && monster.talkMsg >= TEXT_VEIL9) {\r\n\t\tif (RemoveInventoryItemById(player, IDI_GLDNELIX) && (monster.flags & MFLAG_QUEST_COMPLETE) == 0) {\r\n\t\t\tmonster.talkMsg = TEXT_VEIL11;\r\n\t\t\tmonster.goal = MonsterGoal::Inquiring;\r\n\t\t\tmonster.flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\tif (MyPlayer == &player) {\r\n\t\t\t\tSpawnUnique(UITEM_STEELVEIL, monster.position.tile + Direction::South);\r\n\t\t\t\tQuests[Q_VEIL]._qvar2 = QS_VEIL_ITEM_SPAWNED;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_VEIL]);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (monster.uniqueType == UniqueMonsterType::Zhar\r\n\t    && monster.talkMsg == TEXT_ZHAR1\r\n\t    && (monster.flags & MFLAG_QUEST_COMPLETE) == 0) {\r\n\t\tif (MyPlayer == &player) {\r\n\t\t\tQuests[Q_ZHAR]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_ZHAR]._qlog = true;\r\n\t\t\tQuests[Q_ZHAR]._qvar1 = QS_ZHAR_ITEM_SPAWNED;\r\n\t\t\tSetRndSeed(monster.rndItemSeed);\r\n\t\t\tDiscardRandomValues(10);\r\n\t\t\tCreateTypeItem(monster.position.tile + Displacement { 1, 1 }, false, ItemType::Misc, IMISC_BOOK, false, false, true);\r\n\t\t\tmonster.flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_ZHAR]);\r\n\t\t}\r\n\t}\r\n\r\n\tif (monster.uniqueType == UniqueMonsterType::Garbud && MyPlayer == &player) {\r\n\t\tif (monster.talkMsg == TEXT_GARBUD1) {\r\n\t\t\tQuests[Q_GARBUD]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_GARBUD]._qlog = true;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_GARBUD]);\r\n\t\t}\r\n\t\tif (monster.talkMsg == TEXT_GARBUD2 && (monster.flags & MFLAG_QUEST_COMPLETE) == 0) {\r\n\t\t\tSetRndSeed(monster.rndItemSeed);\r\n\t\t\tDiscardRandomValues(10);\r\n\t\t\tSpawnItem(monster, monster.position.tile + Displacement { 1, 1 }, false, true);\r\n\t\t\tmonster.flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\tQuests[Q_GARBUD]._qvar1 = QS_GHARBAD_FIRST_ITEM_SPAWNED;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_GARBUD]);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SpawnGolem(const Player &player, Point position, uint8_t spellLevel)\r\n{\r\n\t// Search monster index to use for the new golem\r\n\tMonster *golem = nullptr;\r\n\t// 1. Prefer MonsterIndex = PlayerIndex for vanilla compatibility\r\n\tif (player.getId() < ReservedMonsterSlotsForGolems) {\r\n\t\tMonster &reservedGolem = Monsters[player.getId()];\r\n\t\tif (reservedGolem.position.tile == GolemHoldingCell || reservedGolem.hitPoints == 0)\r\n\t\t\tgolem = &reservedGolem;\r\n\t}\r\n\t// 2. Use reserved slots, so additional Monsters can spawn\r\n\tif (golem == nullptr) {\r\n\t\tfor (int i = 0; i < ReservedMonsterSlotsForGolems; i++) {\r\n\t\t\tMonster &reservedGolem = Monsters[i];\r\n\t\t\tif (reservedGolem.position.tile == GolemHoldingCell || reservedGolem.hitPoints == 0) {\r\n\t\t\t\tgolem = &reservedGolem;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t// 3. Use normal monster slot\r\n\tif (golem == nullptr) {\r\n\t\tif (ActiveMonsterCount >= MaxMonsters)\r\n\t\t\treturn;\r\n\t\tconst size_t monsterIndex = ActiveMonsters[ActiveMonsterCount];\r\n\t\tActiveMonsterCount += 1;\r\n\t\tgolem = &Monsters[monsterIndex];\r\n\t}\r\n\r\n\tif (golem == nullptr)\r\n\t\treturn;\r\n\r\n\tconst size_t monsterIndex = golem->getId();\r\n\tconst uint32_t seed = GetLCGEngineState();\r\n\r\n\t// Update local state immediately to increase ActiveMonsterCount instantly (this allows multiple monsters to be spawned in one game tick)\r\n\tInitializeSpawnedMonster(position, Direction::South, 0, monsterIndex, seed, player.getId(), spellLevel);\r\n\tNetSendCmdSpawnMonster(position, Direction::South, 0, static_cast<uint16_t>(monsterIndex), seed, player.getId(), spellLevel);\r\n}\r\n\r\nbool CanTalkToMonst(const Monster &monster)\r\n{\r\n\treturn IsAnyOf(monster.goal, MonsterGoal::Inquiring, MonsterGoal::Talking);\r\n}\r\n\r\nuint8_t encode_enemy(Monster &monster)\r\n{\r\n\tif ((monster.flags & MFLAG_TARGETS_MONSTER) != 0)\r\n\t\treturn monster.enemy;\r\n\r\n\treturn monster.enemy + MaxMonsters;\r\n}\r\n\r\nvoid decode_enemy(Monster &monster, uint8_t enemyId)\r\n{\r\n\tif (enemyId >= MaxMonsters) {\r\n\t\tenemyId -= MaxMonsters;\r\n\t\tmonster.flags &= ~MFLAG_TARGETS_MONSTER;\r\n\t\tmonster.enemy = enemyId;\r\n\t\tmonster.enemyPosition = Players[enemyId].position.future;\r\n\t} else {\r\n\t\tmonster.flags |= MFLAG_TARGETS_MONSTER;\r\n\t\tmonster.enemy = enemyId;\r\n\t\tmonster.enemyPosition = Monsters[enemyId].position.future;\r\n\t}\r\n}\r\n\r\n[[nodiscard]] size_t Monster::getId() const\r\n{\r\n\treturn std::distance<const Monster *>(&Monsters[0], this);\r\n}\r\n\r\nMonster *Monster::getLeader() const\r\n{\r\n\tif (leader == Monster::NoLeader)\r\n\t\treturn nullptr;\r\n\r\n\treturn &Monsters[leader];\r\n}\r\n\r\nvoid Monster::setLeader(const Monster *newLeader)\r\n{\r\n\tif (newLeader == nullptr) {\r\n\t\t// really we should update this->leader to NoLeader to avoid leaving a dangling reference to a dead monster\r\n\t\t// when passed nullptr. So that buffed minions are drawn with a distinct colour in monhealthbar we leave the\r\n\t\t// reference and hope that no code tries to modify the leader through this instance later.\r\n\t\tleaderRelation = LeaderRelation::None;\r\n\t\treturn;\r\n\t}\r\n\r\n\tthis->leader = static_cast<uint8_t>(newLeader->getId());\r\n\tleaderRelation = LeaderRelation::Leashed;\r\n\tai = newLeader->ai;\r\n}\r\n\r\n[[nodiscard]] unsigned Monster::distanceToEnemy() const\r\n{\r\n\tconst int mx = position.tile.x - enemyPosition.x;\r\n\tconst int my = position.tile.y - enemyPosition.y;\r\n\treturn std::max(std::abs(mx), std::abs(my));\r\n}\r\n\r\nvoid Monster::checkStandAnimationIsLoaded(Direction mdir)\r\n{\r\n\tif (IsAnyOf(mode, MonsterMode::Stand, MonsterMode::Talk)) {\r\n\t\tdirection = mdir;\r\n\t\tchangeAnimationData(MonsterGraphic::Stand);\r\n\t}\r\n}\r\n\r\nvoid Monster::petrify()\r\n{\r\n\tmode = MonsterMode::Petrified;\r\n\tanimInfo.isPetrified = true;\r\n}\r\n\r\nbool Monster::isWalking() const\r\n{\r\n\tswitch (getVisualMonsterMode()) {\r\n\tcase MonsterMode::MoveNorthwards:\r\n\tcase MonsterMode::MoveSouthwards:\r\n\tcase MonsterMode::MoveSideways:\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nbool Monster::isImmune(MissileID missileType, DamageType missileElement) const\r\n{\r\n\tif (((resistance & IMMUNE_MAGIC) != 0 && missileElement == DamageType::Magic)\r\n\t    || ((resistance & IMMUNE_FIRE) != 0 && missileElement == DamageType::Fire)\r\n\t    || ((resistance & IMMUNE_LIGHTNING) != 0 && missileElement == DamageType::Lightning)\r\n\t    || ((resistance & IMMUNE_ACID) != 0 && missileElement == DamageType::Acid))\r\n\t\treturn true;\r\n\tif (missileType == MissileID::HolyBolt && type().type != MT_DIABLO && data().monsterClass != MonsterClass::Undead)\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\nbool Monster::isResistant(MissileID missileType, DamageType missileElement) const\r\n{\r\n\tif (((resistance & RESIST_MAGIC) != 0 && missileElement == DamageType::Magic)\r\n\t    || ((resistance & RESIST_FIRE) != 0 && missileElement == DamageType::Fire)\r\n\t    || ((resistance & RESIST_LIGHTNING) != 0 && missileElement == DamageType::Lightning))\r\n\t\treturn true;\r\n\tif (gbIsHellfire && missileType == MissileID::HolyBolt && IsAnyOf(type().type, MT_DIABLO, MT_BONEDEMN))\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\nbool Monster::isPlayerMinion() const\r\n{\r\n\treturn (flags & MFLAG_GOLEM) != 0 && (flags & MFLAG_BERSERK) == 0;\r\n}\r\n\r\nbool Monster::isPossibleToHit() const\r\n{\r\n\treturn !hasNoLife()\r\n\t    && talkMsg == TEXT_NONE\r\n\t    && (type().type != MT_ILLWEAV || goal != MonsterGoal::Retreat)\r\n\t    && !(IsAnyOf(mode, MonsterMode::Charge, MonsterMode::Death))\r\n\t    && (!IsAnyOf(type().type, MT_COUNSLR, MT_MAGISTR, MT_CABALIST, MT_ADVOCATE) || goal == MonsterGoal::Normal);\r\n}\r\n\r\nvoid Monster::tag(const Player &tagger)\r\n{\r\n\twhoHit |= 1 << tagger.getId();\r\n}\r\n\r\nbool Monster::tryLiftGargoyle()\r\n{\r\n\tif (ai == MonsterAIID::Gargoyle && (flags & MFLAG_ALLOW_SPECIAL) != 0) {\r\n\t\tflags &= ~MFLAG_ALLOW_SPECIAL;\r\n\t\tmode = MonsterMode::SpecialMeleeAttack;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nMonsterMode Monster::getVisualMonsterMode() const\r\n{\r\n\tif (mode != MonsterMode::Petrified)\r\n\t\treturn mode;\r\n\tconst size_t monsterId = this->getId();\r\n\tfor (auto &missile : Missiles) {\r\n\t\t// Search the missile that will restore the original monster mode and use the saved/original monster mode from it\r\n\t\tif (missile._mitype == MissileID::StoneCurse && static_cast<size_t>(missile.var2) == monsterId) {\r\n\t\t\treturn static_cast<MonsterMode>(missile.var1);\r\n\t\t}\r\n\t}\r\n\treturn MonsterMode::Petrified;\r\n}\r\n\r\nunsigned int Monster::toHit(_difficulty difficulty) const\r\n{\r\n\tif (isPlayerMinion())\r\n\t\treturn golemToHit;\r\n\r\n\tunsigned int baseToHit = data().toHit;\r\n\tif (isUnique() && UniqueMonstersData[static_cast<size_t>(uniqueType)].customToHit != 0) {\r\n\t\tbaseToHit = UniqueMonstersData[static_cast<size_t>(uniqueType)].customToHit;\r\n\t}\r\n\r\n\tif (difficulty == DIFF_NIGHTMARE) {\r\n\t\tbaseToHit += NightmareToHitBonus;\r\n\t} else if (difficulty == DIFF_HELL) {\r\n\t\tbaseToHit += HellToHitBonus;\r\n\t}\r\n\r\n\treturn baseToHit;\r\n}\r\n\r\nunsigned int Monster::toHitSpecial(_difficulty difficulty) const\r\n{\r\n\tunsigned int baseToHitSpecial = data().toHitSpecial;\r\n\tif (isUnique() && UniqueMonstersData[static_cast<size_t>(uniqueType)].customToHit != 0) {\r\n\t\tbaseToHitSpecial = UniqueMonstersData[static_cast<size_t>(uniqueType)].customToHit;\r\n\t}\r\n\r\n\tif (difficulty == DIFF_NIGHTMARE) {\r\n\t\tbaseToHitSpecial += NightmareToHitBonus;\r\n\t} else if (difficulty == DIFF_HELL) {\r\n\t\tbaseToHitSpecial += HellToHitBonus;\r\n\t}\r\n\r\n\treturn baseToHitSpecial;\r\n}\r\n\r\nvoid Monster::occupyTile(Point tile, bool isMoving) const\r\n{\r\n\tconst auto id = static_cast<int16_t>(this->getId() + 1);\r\n\tdMonster[tile.x][tile.y] = isMoving ? -id : id;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/monster.h",
    "content": "/**\r\n * @file monster.h\r\n *\r\n * Interface of monster functionality, AI, actions, spawning, loading, etc.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include <array>\r\n#include <functional>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/actor_position.hpp\"\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/sound.h\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"tables/misdat.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"tables/spelldat.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nstruct Missile;\r\nstruct Player;\r\n\r\nconstexpr size_t MaxMonsters = 200;\r\nconstexpr size_t MaxLvlMTypes = 24;\r\n\r\nenum monster_flag : uint16_t {\r\n\t// clang-format off\r\n\tMFLAG_HIDDEN          = 1 << 0,\r\n\tMFLAG_LOCK_ANIMATION  = 1 << 1,\r\n\tMFLAG_ALLOW_SPECIAL   = 1 << 2,\r\n\tMFLAG_TARGETS_MONSTER = 1 << 4,\r\n\tMFLAG_GOLEM           = 1 << 5,\r\n\tMFLAG_QUEST_COMPLETE  = 1 << 6,\r\n\tMFLAG_KNOCKBACK       = 1 << 7,\r\n\tMFLAG_SEARCH          = 1 << 8,\r\n\tMFLAG_CAN_OPEN_DOOR   = 1 << 9,\r\n\tMFLAG_NO_ENEMY        = 1 << 10,\r\n\tMFLAG_BERSERK         = 1 << 11,\r\n\tMFLAG_NOLIFESTEAL     = 1 << 12,\r\n\t// clang-format on\r\n};\r\n\r\n/** Indexes from UniqueMonstersData array for special unique monsters (usually quest related) */\r\nenum class UniqueMonsterType : uint8_t {\r\n\tGarbud,\r\n\tSkeletonKing,\r\n\tZhar,\r\n\tSnotSpill,\r\n\tLazarus,\r\n\tRedVex,\r\n\tBlackJade,\r\n\tLachdan,\r\n\tWarlordOfBlood,\r\n\tButcher,\r\n\tHorkDemon,\r\n\tDefiler,\r\n\tNaKrul,\r\n\tNone = static_cast<uint8_t>(-1),\r\n};\r\n\r\nenum class MonsterMode : uint8_t {\r\n\tStand,\r\n\t/** Movement towards N, NW, or NE */\r\n\tMoveNorthwards,\r\n\t/** Movement towards S, SW, or SE */\r\n\tMoveSouthwards,\r\n\t/** Movement towards W or E */\r\n\tMoveSideways,\r\n\tMeleeAttack,\r\n\tHitRecovery,\r\n\tDeath,\r\n\tSpecialMeleeAttack,\r\n\tFadeIn,\r\n\tFadeOut,\r\n\tRangedAttack,\r\n\tSpecialStand,\r\n\tSpecialRangedAttack,\r\n\tDelay,\r\n\tCharge,\r\n\tPetrified,\r\n\tHeal,\r\n\tTalk,\r\n};\r\n\r\ninline bool IsMonsterModeMove(MonsterMode mode)\r\n{\r\n\tswitch (mode) {\r\n\tcase MonsterMode::MoveNorthwards:\r\n\tcase MonsterMode::MoveSouthwards:\r\n\tcase MonsterMode::MoveSideways:\r\n\t\treturn true;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nenum class MonsterGraphic : uint8_t {\r\n\tStand,\r\n\tWalk,\r\n\tAttack,\r\n\tGotHit,\r\n\tDeath,\r\n\tSpecial,\r\n};\r\n\r\nenum class MonsterGoal : uint8_t {\r\n\tNone,\r\n\tNormal,\r\n\tRetreat,\r\n\tHealing,\r\n\tMove,\r\n\tAttack,\r\n\tInquiring,\r\n\tTalking,\r\n};\r\n\r\nenum placeflag : uint8_t {\r\n\t// clang-format off\r\n\tPLACE_SCATTER = 1 << 0,\r\n\tPLACE_SPECIAL = 1 << 1,\r\n\tPLACE_UNIQUE  = 1 << 2,\r\n\t// clang-format on\r\n};\r\n\r\n/**\r\n * @brief Defines the relation of the monster to a monster pack.\r\n *        If value is different from Individual Monster, the leader must also be set\r\n */\r\nenum class LeaderRelation : uint8_t {\r\n\tNone,\r\n\t/**\r\n\t * @brief Minion that sticks to the leader\r\n\t */\r\n\tLeashed,\r\n\t/**\r\n\t * @brief Minion that was separated from the leader and acts individually until it reaches the leader again\r\n\t */\r\n\tSeparated,\r\n};\r\n\r\nstruct AnimStruct {\r\n\t/**\r\n\t * @brief Sprite lists for each of the 8 directions.\r\n\t */\r\n\tOptionalClxSpriteListOrSheet sprites;\r\n\r\n\t[[nodiscard]] OptionalClxSpriteList spritesForDirection(Direction direction) const\r\n\t{\r\n\t\tif (!sprites)\r\n\t\t\treturn std::nullopt;\r\n\t\treturn sprites->isSheet() ? (*sprites).sheet()[static_cast<size_t>(direction)] : (*sprites).list();\r\n\t}\r\n\r\n\tuint16_t width;\r\n\tint8_t frames;\r\n\tint8_t rate;\r\n};\r\n\r\nenum class MonsterSound : uint8_t {\r\n\tAttack,\r\n\tHit,\r\n\tDeath,\r\n\tSpecial\r\n};\r\n\r\nstruct MonsterSpritesData {\r\n\tstatic constexpr size_t MaxAnims = 6;\r\n\tstd::unique_ptr<std::byte[]> data;\r\n\tstd::array<uint32_t, MaxAnims + 1> offsets;\r\n};\r\n\r\nstruct CMonster {\r\n\tstd::unique_ptr<std::byte[]> animData;\r\n\tAnimStruct anims[6];\r\n\tstd::unique_ptr<TSnd> sounds[4][2];\r\n\r\n\t_monster_id type;\r\n\t/** placeflag enum as a flags*/\r\n\tuint8_t placeFlags;\r\n\tint8_t corpseId = 0;\r\n\r\n\tconst MonsterData &data() const\r\n\t{\r\n\t\treturn MonstersData[type];\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns AnimStruct for specified graphic\r\n\t */\r\n\t[[nodiscard]] const AnimStruct &getAnimData(MonsterGraphic graphic) const\r\n\t{\r\n\t\treturn anims[static_cast<int>(graphic)];\r\n\t}\r\n};\r\n\r\nextern CMonster LevelMonsterTypes[MaxLvlMTypes];\r\n\r\nstruct Monster { // note: missing field _mAFNum\r\n\tstd::unique_ptr<uint8_t[]> uniqueMonsterTRN;\r\n\t/**\r\n\t * @brief Contains information for current animation\r\n\t */\r\n\tAnimationInfo animInfo;\r\n\tint maxHitPoints;\r\n\tint hitPoints;\r\n\tuint32_t flags;\r\n\t/** Seed used to determine item drops on death */\r\n\tuint32_t rndItemSeed;\r\n\t/** Seed used to determine AI behaviour/sync sounds in multiplayer games? */\r\n\tuint32_t aiSeed;\r\n\tuint16_t golemToHit;\r\n\tuint16_t resistance;\r\n\t_speech_id talkMsg;\r\n\r\n\t/** @brief Specifies monster's behaviour regarding moving and changing goals. */\r\n\tint16_t goalVar1;\r\n\r\n\t/**\r\n\t * @brief Specifies turning direction for @p RoundWalk in most cases.\r\n\t * Used in custom way by @p FallenAi, @p SnakeAi, @p M_FallenFear and @p FallenAi.\r\n\t */\r\n\tint8_t goalVar2;\r\n\r\n\t/**\r\n\t * @brief Controls monster's behaviour regarding special actions.\r\n\t * Used only by @p ScavengerAi, @p MegaAi and @p GolemAi.\r\n\t */\r\n\tint8_t goalVar3;\r\n\r\n\tint16_t var1;\r\n\tint16_t var2;\r\n\tint8_t var3;\r\n\r\n\tActorPosition position;\r\n\r\n\t/** Specifies current goal of the monster */\r\n\tMonsterGoal goal;\r\n\r\n\t/** Usually corresponds to the enemy's future position */\r\n\tWorldTilePosition enemyPosition;\r\n\tuint8_t levelType;\r\n\tMonsterMode mode;\r\n\tuint8_t pathCount;\r\n\t/** Direction faced by monster (direction enum) */\r\n\tDirection direction;\r\n\t/** The current target of the monster. An index in to either the player or monster array based on the _meflag value. */\r\n\tuint8_t enemy;\r\n\tbool isInvalid;\r\n\tMonsterAIID ai;\r\n\t/**\r\n\t * @brief Specifies monster's behaviour across various actions.\r\n\t * Generally, when monster thinks it decides what to do based on this value, among other things.\r\n\t * Higher values should result in more aggressive behaviour (e.g. some monsters use this to calculate the @p AiDelay).\r\n\t */\r\n\tuint8_t intelligence;\r\n\t/** Stores information for how many ticks the monster will remain active */\r\n\tuint8_t activeForTicks;\r\n\tUniqueMonsterType uniqueType;\r\n\tuint8_t uniqTrans;\r\n\tint8_t corpseId;\r\n\tint8_t whoHit;\r\n\tuint8_t minDamage;\r\n\tuint8_t maxDamage;\r\n\tuint8_t minDamageSpecial;\r\n\tuint8_t maxDamageSpecial;\r\n\tuint8_t armorClass;\r\n\tuint8_t reducePlayerStrength;\r\n\tuint8_t reducePlayerMagic;\r\n\tuint8_t reducePlayerDexterity;\r\n\tuint8_t reducePlayerVitality;\r\n\tuint8_t reducePlayerMaxHP;\r\n\tuint8_t reducePlayerMaxMana;\r\n\tuint8_t leader;\r\n\tLeaderRelation leaderRelation;\r\n\tuint8_t packSize;\r\n\tint8_t lightId;\r\n\r\n\tstatic constexpr uint8_t NoLeader = -1;\r\n\r\n\t/**\r\n\t * @brief Sets the current cell sprite to match the desired desiredDirection and animation sequence\r\n\t * @param graphic Animation sequence of interest\r\n\t * @param desiredDirection Desired desiredDirection the monster should be visually facing\r\n\t */\r\n\tvoid changeAnimationData(MonsterGraphic graphic, Direction desiredDirection)\r\n\t{\r\n\t\tconst AnimStruct &animationData = type().getAnimData(graphic);\r\n\r\n\t\t// Passing the frames and rate properties here is only relevant when initialising a monster, but doesn't cause any harm when switching animations.\r\n\t\tthis->animInfo.changeAnimationData(animationData.spritesForDirection(desiredDirection), animationData.frames, animationData.rate);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Sets the current cell sprite to match the desired animation sequence using the direction the monster is currently facing\r\n\t * @param graphic Animation sequence of interest\r\n\t */\r\n\tvoid changeAnimationData(MonsterGraphic graphic)\r\n\t{\r\n\t\tthis->changeAnimationData(graphic, this->direction);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if the correct stand Animation is loaded. This is needed if direction is changed (monster stands and looks at the player).\r\n\t * @param dir direction of the monster\r\n\t */\r\n\tvoid checkStandAnimationIsLoaded(Direction dir);\r\n\r\n\t/**\r\n\t * @brief Sets mode to MonsterMode::Petrified\r\n\t */\r\n\tvoid petrify();\r\n\r\n\tconst CMonster &type() const\r\n\t{\r\n\t\treturn LevelMonsterTypes[levelType];\r\n\t}\r\n\r\n\tconst MonsterData &data() const\r\n\t{\r\n\t\treturn type().data();\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns monster's name\r\n\t * Internally it returns a name stored in global array of monsters' data.\r\n\t * @return Monster's name\r\n\t */\r\n\tstd::string_view name() const\r\n\t{\r\n\t\tif (uniqueType != UniqueMonsterType::None)\r\n\t\t\treturn pgettext(\"monster\", UniqueMonstersData[static_cast<size_t>(uniqueType)].mName);\r\n\r\n\t\treturn pgettext(\"monster\", data().name);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Calculates monster's experience points.\r\n\t * Fetches base exp value from @p MonstersData array.\r\n\t * @param difficulty - difficulty on which calculation is performed\r\n\t * @return Monster's experience points, including bonuses from difficulty and monster being unique\r\n\t */\r\n\tunsigned int exp(_difficulty difficulty) const\r\n\t{\r\n\t\tunsigned int monsterExp = data().exp;\r\n\r\n\t\tif (difficulty == DIFF_NIGHTMARE) {\r\n\t\t\tmonsterExp = 2 * (monsterExp + 1000);\r\n\t\t} else if (difficulty == DIFF_HELL) {\r\n\t\t\tmonsterExp = 4 * (monsterExp + 1000);\r\n\t\t}\r\n\r\n\t\tif (isUnique()) {\r\n\t\t\tmonsterExp *= 2;\r\n\t\t}\r\n\r\n\t\treturn monsterExp;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Calculates monster's chance to hit with normal attack.\r\n\t * Fetches base value from @p MonstersData array or @p UniqueMonstersData.\r\n\t * @param difficulty - difficulty on which calculation is performed\r\n\t * @return Monster's chance to hit with normal attack, including bonuses from difficulty and monster being unique\r\n\t */\r\n\tunsigned int toHit(_difficulty difficulty) const;\r\n\r\n\t/**\r\n\t * @brief Calculates monster's chance to hit with special attack.\r\n\t * Fetches base value from @p MonstersData array or @p UniqueMonstersData.\r\n\t * @param difficulty - difficulty on which calculation is performed\r\n\t * @return Monster's chance to hit with special attack, including bonuses from difficulty and monster being unique\r\n\t */\r\n\tunsigned int toHitSpecial(_difficulty difficulty) const;\r\n\r\n\t/**\r\n\t * @brief Calculates monster's level.\r\n\t * Fetches base level value from @p MonstersData array or @p UniqueMonstersData.\r\n\t * @param difficulty - difficulty on which calculation is performed\r\n\t * @return Monster's level, including bonuses from difficulty and monster being unique\r\n\t */\r\n\tunsigned int level(_difficulty difficulty) const\r\n\t{\r\n\t\tunsigned int baseLevel = data().level;\r\n\t\tif (isUnique()) {\r\n\t\t\tbaseLevel = UniqueMonstersData[static_cast<size_t>(uniqueType)].mlevel;\r\n\t\t\tif (baseLevel != 0) {\r\n\t\t\t\tbaseLevel *= 2;\r\n\t\t\t} else {\r\n\t\t\t\tbaseLevel = data().level + 5;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (difficulty == DIFF_NIGHTMARE) {\r\n\t\t\tbaseLevel += 15;\r\n\t\t} else if (difficulty == DIFF_HELL) {\r\n\t\t\tbaseLevel += 30;\r\n\t\t}\r\n\r\n\t\treturn baseLevel;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns the network identifier for this monster\r\n\t *\r\n\t * This is currently the index into the Monsters array, but may change in the future.\r\n\t */\r\n\t[[nodiscard]] size_t getId() const;\r\n\r\n\t[[nodiscard]] Monster *getLeader() const;\r\n\tvoid setLeader(const Monster *leader);\r\n\r\n\t[[nodiscard]] bool hasLeashedMinions() const\r\n\t{\r\n\t\treturn isUnique() && UniqueMonstersData[static_cast<size_t>(uniqueType)].monsterPack == UniqueMonsterPack::Leashed;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Calculates the distance in tiles between this monster and its current target\r\n\t *\r\n\t * The distance is not calculated as the euclidean distance, but rather as\r\n\t * the longest number of tiles in the coordinate system.\r\n\t *\r\n\t * @return The distance in tiles\r\n\t */\r\n\t[[nodiscard]] unsigned distanceToEnemy() const;\r\n\r\n\t/**\r\n\t * @brief Is the monster currently walking?\r\n\t */\r\n\t[[nodiscard]] bool isWalking() const;\r\n\t[[nodiscard]] bool isImmune(MissileID mitype, DamageType missileElement) const;\r\n\t[[nodiscard]] bool isResistant(MissileID mitype, DamageType missileElement) const;\r\n\r\n\t/**\r\n\t * Is this a player's golem?\r\n\t */\r\n\t[[nodiscard]] bool isPlayerMinion() const;\r\n\r\n\tbool isPossibleToHit() const;\r\n\tvoid tag(const Player &tagger);\r\n\r\n\t[[nodiscard]] bool isUnique() const\r\n\t{\r\n\t\treturn uniqueType != UniqueMonsterType::None;\r\n\t}\r\n\r\n\tbool tryLiftGargoyle();\r\n\r\n\t/**\r\n\t * @brief Gets the visual/shown monster mode.\r\n\t *\r\n\t * When a monster is petrified it's monster mode is changed to MonsterMode::Petrified.\r\n\t * But for graphics and rendering we show the old/real mode.\r\n\t */\r\n\t[[nodiscard]] MonsterMode getVisualMonsterMode() const;\r\n\r\n\t[[nodiscard]] Displacement getRenderingOffset(const ClxSprite sprite) const\r\n\t{\r\n\t\tDisplacement offset = { -CalculateSpriteTileCenterX(sprite.width()), 0 };\r\n\t\tif (isWalking())\r\n\t\t\toffset += GetOffsetForWalking(animInfo, direction);\r\n\t\treturn offset;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Sets a tile/dMonster to be occupied by the monster\r\n\t * @param position tile to update\r\n\t * @param isMoving specifies whether the monster is moving or not (true/moving results in a negative index in dMonster)\r\n\t */\r\n\tvoid occupyTile(Point tile, bool isMoving) const;\r\n\r\n\tbool hasNoLife() const\r\n\t{\r\n\t\treturn hitPoints >> 6 <= 0;\r\n\t}\r\n};\r\n\r\nextern size_t LevelMonsterTypeCount;\r\nextern Monster Monsters[MaxMonsters];\r\nextern unsigned ActiveMonsters[MaxMonsters];\r\nextern size_t ActiveMonsterCount;\r\nextern int MonsterKillCounts[NUM_MAX_MTYPES];\r\nextern bool sgbSaveSoundOn;\r\n\r\ntl::expected<void, std::string> PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t miniontype, int bosspacksize, const UniqueMonsterData &uniqueMonsterData);\r\nvoid InitLevelMonsters();\r\ntl::expected<void, std::string> GetLevelMTypes();\r\ntl::expected<size_t, std::string> AddMonsterType(_monster_id type, placeflag placeflag);\r\ninline tl::expected<size_t, std::string> AddMonsterType(UniqueMonsterType uniqueType, placeflag placeflag)\r\n{\r\n\treturn AddMonsterType(UniqueMonstersData[static_cast<size_t>(uniqueType)].mtype, placeflag);\r\n}\r\ntl::expected<void, std::string> InitMonsterSND(CMonster &monsterType);\r\ntl::expected<void, std::string> InitMonsterGFX(CMonster &monsterType, MonsterSpritesData &&spritesData = {});\r\ntl::expected<void, std::string> InitAllMonsterGFX();\r\nvoid WeakenNaKrul();\r\nvoid InitGolems();\r\ntl::expected<void, std::string> InitMonsters();\r\ntl::expected<void, std::string> SetMapMonsters(const uint16_t *dunData, Point startPosition);\r\nMonster *AddMonster(Point position, Direction dir, size_t typeIndex, bool inMap);\r\n/**\r\n * @brief Spawns a new monsters (dynamically/not on level load).\r\n * The command is only executed for the level owner, to prevent desyncs in multiplayer.\r\n * The level owner sends a CMD_SPAWNMONSTER-message to the other players.\r\n */\r\nvoid SpawnMonster(Point position, Direction dir, size_t typeIndex);\r\n/**\r\n * @brief Loads data for a dynamically spawned monster when entering a level in multiplayer.\r\n */\r\nvoid LoadDeltaSpawnedMonster(size_t typeIndex, size_t monsterId, uint32_t seed, uint8_t golemOwnerPlayerId, int16_t golemSpellLevel);\r\n/**\r\n * @brief Initialize a spanwed monster (from a network message or from SpawnMonster-function).\r\n */\r\nvoid InitializeSpawnedMonster(Point position, Direction dir, size_t typeIndex, size_t monsterId, uint32_t seed, uint8_t golemOwnerPlayerId, int16_t golemSpellLevel);\r\nvoid AddDoppelganger(Monster &monster);\r\nvoid ApplyMonsterDamage(DamageType damageType, Monster &monster, int damage);\r\nvoid MonsterReducePlayerAttribute(Monster &monster, Player &player);\r\nbool M_Talker(const Monster &monster);\r\nvoid M_StartStand(Monster &monster, Direction md);\r\nvoid M_ClearSquares(const Monster &monster);\r\nvoid M_GetKnockback(Monster &monster, WorldTilePosition attackerStartPos);\r\nvoid M_StartHit(Monster &monster, int dam);\r\nvoid M_StartHit(Monster &monster, const Player &player, int dam);\r\nvoid StartMonsterDeath(Monster &monster, const Player &player, bool sendmsg);\r\nvoid MonsterDeath(Monster &monster, Direction md, bool sendmsg);\r\nvoid KillGolem(Monster &golem);\r\nvoid M_StartKill(Monster &monster, const Player &player);\r\nvoid M_SyncStartKill(Monster &monster, Point position, const Player &player);\r\nvoid M_UpdateRelations(const Monster &monster);\r\nvoid DoEnding();\r\nvoid PrepDoEnding();\r\nbool Walk(Monster &monster, Direction md);\r\nvoid GolumAi(Monster &golem);\r\nvoid DeleteMonsterList();\r\nvoid RemoveEnemyReferences(const Player &player);\r\nvoid ProcessMonsters();\r\nvoid FreeMonsters();\r\nbool DirOK(const Monster &monster, Direction mdir);\r\nbool LineClearMissile(Point startPoint, Point endPoint);\r\n/**\r\n * @brief Checks for same missile obstructions as CheckMissileCol() for missiles that move along a path between two points\r\n */\r\nbool LineClearMovingMissile(Point startPoint, Point endPoint);\r\ntl::expected<void, std::string> SyncMonsterAnim(Monster &monster);\r\nvoid M_FallenFear(Point position);\r\nvoid PrintMonstHistory(int mt);\r\nvoid PrintUniqueHistory();\r\nvoid PlayEffect(Monster &monster, MonsterSound mode);\r\nvoid MissToMonst(Missile &missile, Point position);\r\n\r\nMonster *FindMonsterAtPosition(Point position, bool ignoreMovingMonsters = false);\r\nMonster *FindUniqueMonster(UniqueMonsterType monsterType);\r\nMonster *FindGolemForPlayer(const Player &player);\r\n\r\n/**\r\n * @brief Check that the given tile is available to the monster\r\n */\r\nbool IsTileAvailable(const Monster &monster, Point position);\r\nbool IsSkel(_monster_id mt);\r\nbool IsGoat(_monster_id mt);\r\n/**\r\n * @brief Reveals a monster that was hiding in a container\r\n * @param monster instance returned from a previous call to PreSpawnSkeleton\r\n * @param position tile to try spawn the monster at, neighboring tiles will be used as a fallback\r\n */\r\nvoid ActivateSkeleton(Monster &monster, Point position);\r\nMonster *PreSpawnSkeleton();\r\nvoid TalktoMonster(Player &player, Monster &monster);\r\nvoid SpawnGolem(const Player &player, Point position, uint8_t spellLevel);\r\nbool CanTalkToMonst(const Monster &monster);\r\nuint8_t encode_enemy(Monster &monster);\r\nvoid decode_enemy(Monster &monster, uint8_t enemyId);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/monsters/validation.cpp",
    "content": "/**\r\n * @file monsters/validation.cpp\r\n *\r\n * Implementation of functions for validation of monster data.\r\n */\r\n\r\n#include \"monsters/validation.hpp\"\r\n\r\n#include <cstddef>\r\n\r\n#include \"monster.h\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nbool IsEnemyValid(size_t enemyId, bool checkMonsterTable)\r\n{\r\n\tif (enemyId < MaxMonsters)\r\n\t\treturn !checkMonsterTable || Monsters[enemyId].hitPoints > 0;\r\n\tconst size_t playerId = enemyId - MaxMonsters;\r\n\treturn playerId < Players.size() && Players[playerId].plractive;\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsEnemyIdValid(size_t enemyId)\r\n{\r\n\treturn IsEnemyValid(enemyId, false);\r\n}\r\n\r\nbool IsEnemyValid(size_t monsterId, size_t enemyId)\r\n{\r\n\tif (monsterId >= MaxMonsters)\r\n\t\treturn false;\r\n\tif (monsterId == enemyId)\r\n\t\treturn false;\r\n\treturn IsEnemyValid(enemyId, true);\r\n}\r\n\r\nbool IsMonsterValid(const Monster &monster)\r\n{\r\n\tconst CMonster &monsterType = LevelMonsterTypes[monster.levelType];\r\n\tconst _monster_id monsterId = monsterType.type;\r\n\tconst size_t monsterIndex = static_cast<size_t>(monsterId);\r\n\r\n\tif (monsterIndex >= MonstersData.size()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (monster.isUnique() && !IsUniqueMonsterValid(monster)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool IsUniqueMonsterValid(const Monster &monster)\r\n{\r\n\tassert(monster.isUnique());\r\n\r\n\tconst size_t uniqueMonsterIndex = static_cast<size_t>(monster.uniqueType);\r\n\tif (uniqueMonsterIndex >= UniqueMonstersData.size()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst CMonster &monsterType = LevelMonsterTypes[monster.levelType];\r\n\tconst _monster_id monsterId = monsterType.type;\r\n\tconst UniqueMonsterData &uniqueMonsterData = UniqueMonstersData.at(uniqueMonsterIndex);\r\n\tif (monsterId != uniqueMonsterData.mtype) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/monsters/validation.hpp",
    "content": "/**\r\n * @file monsters/validation.hpp\r\n *\r\n * Interface of functions for validation of monster data.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n\r\nnamespace devilution {\r\n\r\nstruct Monster;\r\n\r\nbool IsEnemyIdValid(size_t enemyId);\r\nbool IsEnemyValid(size_t monsterId, size_t enemyId);\r\nbool IsMonsterValid(const Monster &monster);\r\nbool IsUniqueMonsterValid(const Monster &monster);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/movie.cpp",
    "content": "/**\r\n * @file movie.cpp\r\n *\r\n * Implementation of video playback.\r\n */\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"diablo.h\"\r\n#include \"effects.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/events.hpp\"\r\n#include \"engine/sound.h\"\r\n#include \"hwcursor.hpp\"\r\n#include \"storm/storm_svid.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\n/** Should the movie continue playing. */\r\nbool movie_playing;\r\n/** Should the movie play in a loop. */\r\nbool loop_movie;\r\n\r\nvoid play_movie(const char *pszMovie, bool userCanClose)\r\n{\r\n\tif (demo::IsRunning())\r\n\t\treturn;\r\n\r\n\tmovie_playing = true;\r\n\r\n\tsound_disable_music(true);\r\n\tstream_stop();\r\n\r\n\tif (IsHardwareCursorEnabled() && ControlDevice == ControlTypes::KeyboardAndMouse) {\r\n\t\tSetHardwareCursorVisible(false);\r\n\t}\r\n\r\n\tif (SVidPlayBegin(pszMovie, loop_movie ? 0x100C0808 : 0x10280808)) {\r\n\t\tSDL_Event event;\r\n\t\tuint16_t modState;\r\n\t\twhile (movie_playing) {\r\n\t\t\twhile (movie_playing && FetchMessage(&event, &modState)) {\r\n\t\t\t\tif (userCanClose) {\r\n\t\t\t\t\tfor (const ControllerButtonEvent ctrlEvent : ToControllerButtonEvents(event)) {\r\n\t\t\t\t\t\tif (!SkipsMovie(ctrlEvent))\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tmovie_playing = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tswitch (event.type) {\r\n\t\t\t\tcase SDL_EVENT_KEY_DOWN:\r\n\t\t\t\tcase SDL_EVENT_MOUSE_BUTTON_UP:\r\n\t\t\t\t\tif (userCanClose || (event.type == SDL_EVENT_KEY_DOWN && SDLC_EventKey(event) == SDLK_ESCAPE))\r\n\t\t\t\t\t\tmovie_playing = false;\r\n\t\t\t\t\tbreak;\r\n#ifdef USE_SDL3\r\n\t\t\t\tcase SDL_EVENT_WINDOW_FOCUS_LOST:\r\n\t\t\t\t\tif (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_pause();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SDL_EVENT_WINDOW_FOCUS_GAINED:\r\n\t\t\t\t\tif (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_unpause();\r\n\t\t\t\t\tbreak;\r\n#elif !defined(USE_SDL1)\r\n\t\t\t\tcase SDL_WINDOWEVENT:\r\n\t\t\t\t\tif (*GetOptions().Gameplay.pauseOnFocusLoss) {\r\n\t\t\t\t\t\tif (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)\r\n\t\t\t\t\t\t\tdiablo_focus_pause();\r\n\t\t\t\t\t\telse if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)\r\n\t\t\t\t\t\t\tdiablo_focus_unpause();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n#else\r\n\t\t\t\tcase SDL_ACTIVEEVENT:\r\n\t\t\t\t\tif ((event.active.state & SDL_APPINPUTFOCUS) != 0) {\r\n\t\t\t\t\t\tif (event.active.gain == 0)\r\n\t\t\t\t\t\t\tdiablo_focus_pause();\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\tdiablo_focus_unpause();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n#endif\r\n\t\t\t\tcase SDL_EVENT_QUIT:\r\n\t\t\t\t\tSVidPlayEnd();\r\n\t\t\t\t\tdiablo_quit(0);\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!SVidPlayContinue())\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tSVidPlayEnd();\r\n\t}\r\n\r\n\tsound_disable_music(false);\r\n\r\n\tmovie_playing = false;\r\n\r\n#ifdef USE_SDL3\r\n\tfloat x, y;\r\n\tSDL_GetMouseState(&x, &y);\r\n\tMousePosition.x = static_cast<int>(x);\r\n\tMousePosition.y = static_cast<int>(y);\r\n#else\r\n\tSDL_GetMouseState(&MousePosition.x, &MousePosition.y);\r\n#endif\r\n\tOutputToLogical(&MousePosition.x, &MousePosition.y);\r\n\tInitBackbufferState();\r\n}\r\n\r\nvoid PlayInGameMovie(const char *pszMovie)\r\n{\r\n\tPaletteFadeOut(8);\r\n\tplay_movie(pszMovie, false);\r\n\tClearScreenBuffer();\r\n\tRedrawEverything();\r\n\tscrollrt_draw_game_screen();\r\n\tPaletteFadeIn(8);\r\n\tRedrawEverything();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/movie.h",
    "content": "/**\r\n * @file movie.h\r\n *\r\n * Interface of video playback.\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\n\r\nextern bool movie_playing;\r\nextern bool loop_movie;\r\n\r\n/**\r\n * @brief Start playback of a given video.\r\n * @param pszMovie The file name of the video\r\n * @param user_can_close Set to false to make the video unskippable.\r\n */\r\nvoid play_movie(const char *pszMovie, bool user_can_close);\r\n\r\n/**\r\n * @brief Fade to black and play a video\r\n * @param pszMovie file path of movie\r\n */\r\nvoid PlayInGameMovie(const char *pszMovie);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_common.cpp",
    "content": "#include \"mpq/mpq_common.hpp\"\r\n\r\n#include <string_view>\r\n\r\n#include <libmpq/mpq.h>\r\n\r\nnamespace devilution {\r\n\r\n#if !defined(UNPACKED_MPQS) || !defined(UNPACKED_SAVES)\r\nMpqFileHash CalculateMpqFileHash(std::string_view filename)\r\n{\r\n\tMpqFileHash fileHash;\r\n\tlibmpq__file_hash_s(filename.data(), filename.size(), &fileHash[0], &fileHash[1], &fileHash[2]);\r\n\treturn fileHash;\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_common.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#include \"utils/endian_read.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr size_t MaxMpqPathSize = 256;\r\n\r\n#pragma pack(push, 1)\r\nstruct MpqFileHeader {\r\n\tstatic constexpr uint32_t DiabloSignature = LoadLE32(\"MPQ\\x1A\");\r\n\tstatic constexpr uint32_t DiabloSize = 32;\r\n\r\n\t// The signature, always 0x1A51504D ('MPQ\\x1A') for Diablo MPQs.\r\n\tuint32_t signature;\r\n\r\n\t// The size of this header in bytes, always 32 for Diablo MPQs.\r\n\tuint32_t headerSize;\r\n\r\n\t// The size of the MPQ file in bytes.\r\n\tuint32_t fileSize;\r\n\r\n\t// Version, always 0 for Diablo MPQs.\r\n\tuint16_t version;\r\n\r\n\t// Block size is `512 * 2 ^ blockSizeFactor`.\r\n\t// e.g. if `blockSizeFactor` is 3, the block size is 4096 (512 << 3).\r\n\tuint16_t blockSizeFactor;\r\n\r\n\t// Location of the hash entries table.\r\n\tuint32_t hashEntriesOffset;\r\n\r\n\t// Location of the block entries table.\r\n\tuint32_t blockEntriesOffset;\r\n\r\n\t// Size of the hash entries table (number of entries).\r\n\tuint32_t hashEntriesCount;\r\n\r\n\t// Size of the block entries table (number of entries).\r\n\tuint32_t blockEntriesCount;\r\n\r\n\t// Empty space after the header. Not included into `headerSize`.\r\n\tuint8_t pad[72];\r\n};\r\n\r\nstruct MpqHashEntry {\r\n\t// Special values for the `block` field.\r\n\t// Does not point to a block (unassigned hash entry)\r\n\tstatic constexpr uint32_t NullBlock = -1;\r\n\r\n\t// Used to point to a block but is now deleted (can be reclaimed)\r\n\tstatic constexpr uint32_t DeletedBlock = -2;\r\n\r\n\t// `hashA` and `hashB` are used for resolving hash index collisions.\r\n\tuint32_t hashA;\r\n\tuint32_t hashB;\r\n\r\n\t// Always `0` in Diablo.\r\n\tuint16_t locale;\r\n\r\n\t// Always `0` in Diablo.\r\n\tuint16_t platform;\r\n\r\n\t// Index of the first block in the block entries table, or\r\n\t// -1 for an unused entry, -2 for a deleted entry.\r\n\tuint32_t block;\r\n};\r\n\r\nstruct MpqBlockEntry {\r\n\tstatic constexpr uint32_t FlagExists = 0x80000000;\r\n\tstatic constexpr uint32_t CompressPkZip = 0x00000100;\r\n\r\n\t// Offset to the start of this block.\r\n\tuint32_t offset;\r\n\r\n\t// Size in the MPQ.\r\n\tuint32_t packedSize;\r\n\r\n\t// Uncompressed size.\r\n\tuint32_t unpackedSize;\r\n\r\n\t// Flags indicating compression type, encryption, etc.\r\n\tuint32_t flags;\r\n};\r\n#pragma pack(pop)\r\n\r\nusing MpqFileHash = std::array<std::uint32_t, 3>;\r\n\r\n#if !defined(UNPACKED_MPQS) || !defined(UNPACKED_SAVES)\r\nMpqFileHash CalculateMpqFileHash(std::string_view filename);\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_reader.cpp",
    "content": "#include \"mpq/mpq_reader.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string_view>\r\n\r\n#include <libmpq/mpq.h>\r\n\r\nnamespace devilution {\r\n\r\nstd::optional<MpqArchive> MpqArchive::Open(const char *path, int32_t &error)\r\n{\r\n\tmpq_archive_s *archive;\r\n\terror = libmpq__archive_open(&archive, path, -1);\r\n\tif (error != 0) {\r\n\t\tif (error == LIBMPQ_ERROR_EXIST)\r\n\t\t\terror = 0;\r\n\t\treturn std::nullopt;\r\n\t}\r\n\treturn MpqArchive { std::string(path), archive };\r\n}\r\n\r\nstd::optional<MpqArchive> MpqArchive::Clone(int32_t &error)\r\n{\r\n\tmpq_archive_s *copy;\r\n\terror = libmpq__archive_dup(archive_, path_.c_str(), &copy);\r\n\tif (error != 0)\r\n\t\treturn std::nullopt;\r\n\treturn MpqArchive { path_, copy };\r\n}\r\n\r\nconst char *MpqArchive::ErrorMessage(int32_t errorCode)\r\n{\r\n\treturn libmpq__strerror(errorCode);\r\n}\r\n\r\nMpqArchive &MpqArchive::operator=(MpqArchive &&other) noexcept\r\n{\r\n\tpath_ = std::move(other.path_);\r\n\tif (archive_ != nullptr)\r\n\t\tlibmpq__archive_close(archive_);\r\n\tarchive_ = other.archive_;\r\n\tother.archive_ = nullptr;\r\n\ttmp_buf_ = std::move(other.tmp_buf_);\r\n\treturn *this;\r\n}\r\n\r\nMpqArchive::~MpqArchive()\r\n{\r\n\tif (archive_ != nullptr)\r\n\t\tlibmpq__archive_close(archive_);\r\n}\r\n\r\nbool MpqArchive::GetFileNumber(MpqFileHash fileHash, uint32_t &fileNumber)\r\n{\r\n\treturn libmpq__file_number_from_hash(archive_, fileHash[0], fileHash[1], fileHash[2], &fileNumber) == 0;\r\n}\r\n\r\nstd::unique_ptr<std::byte[]> MpqArchive::ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error)\r\n{\r\n\tstd::unique_ptr<std::byte[]> result;\r\n\tstd::uint32_t fileNumber;\r\n\terror = libmpq__file_number_s(archive_, filename.data(), filename.size(), &fileNumber);\r\n\tif (error != 0)\r\n\t\treturn result;\r\n\r\n\tlibmpq__off_t unpackedSize;\r\n\terror = libmpq__file_size_unpacked(archive_, fileNumber, &unpackedSize);\r\n\tif (error != 0)\r\n\t\treturn result;\r\n\r\n\terror = OpenBlockOffsetTable(fileNumber, filename);\r\n\tif (error != 0)\r\n\t\treturn result;\r\n\r\n\tresult = std::make_unique<std::byte[]>(static_cast<size_t>(unpackedSize));\r\n\r\n\tconst std::size_t blockSize = GetBlockSize(fileNumber, 0, error);\r\n\tif (error != 0)\r\n\t\treturn result;\r\n\r\n\tstd::vector<std::uint8_t> &tmp = GetTemporaryBuffer(blockSize);\r\n\tif (error != 0)\r\n\t\treturn result;\r\n\r\n\terror = libmpq__file_read_with_filename_and_temporary_buffer_s(\r\n\t    archive_, fileNumber, filename.data(), filename.size(), reinterpret_cast<std::uint8_t *>(result.get()), unpackedSize,\r\n\t    tmp.data(), static_cast<libmpq__off_t>(blockSize), nullptr);\r\n\tif (error != 0) {\r\n\t\tresult = nullptr;\r\n\t\tCloseBlockOffsetTable(fileNumber);\r\n\t\treturn result;\r\n\t}\r\n\tCloseBlockOffsetTable(fileNumber);\r\n\r\n\tfileSize = static_cast<size_t>(unpackedSize);\r\n\treturn result;\r\n}\r\n\r\nint32_t MpqArchive::ReadBlock(uint32_t fileNumber, uint32_t blockNumber, uint8_t *out, size_t outSize)\r\n{\r\n\tstd::vector<std::uint8_t> &tmpBuf = GetTemporaryBuffer(outSize);\r\n\treturn libmpq__block_read_with_temporary_buffer(\r\n\t    archive_, fileNumber, blockNumber, out, static_cast<libmpq__off_t>(outSize),\r\n\t    tmpBuf.data(), outSize,\r\n\t    /*transferred=*/nullptr);\r\n}\r\n\r\nstd::size_t MpqArchive::GetUnpackedFileSize(uint32_t fileNumber, int32_t &error)\r\n{\r\n\tlibmpq__off_t unpackedSize;\r\n\terror = libmpq__file_size_unpacked(archive_, fileNumber, &unpackedSize);\r\n\treturn static_cast<size_t>(unpackedSize);\r\n}\r\n\r\nuint32_t MpqArchive::GetNumBlocks(uint32_t fileNumber, int32_t &error)\r\n{\r\n\tuint32_t numBlocks;\r\n\terror = libmpq__file_blocks(archive_, fileNumber, &numBlocks);\r\n\treturn numBlocks;\r\n}\r\n\r\nint32_t MpqArchive::OpenBlockOffsetTable(uint32_t fileNumber, std::string_view filename)\r\n{\r\n\treturn libmpq__block_open_offset_with_filename_s(archive_, fileNumber, filename.data(), filename.size());\r\n}\r\n\r\nint32_t MpqArchive::CloseBlockOffsetTable(uint32_t fileNumber)\r\n{\r\n\treturn libmpq__block_close_offset(archive_, fileNumber);\r\n}\r\n\r\n// Requires the block offset table to be open\r\nstd::size_t MpqArchive::GetBlockSize(uint32_t fileNumber, uint32_t blockNumber, int32_t &error)\r\n{\r\n\tlibmpq__off_t blockSize;\r\n\terror = libmpq__block_size_unpacked(archive_, fileNumber, blockNumber, &blockSize);\r\n\treturn static_cast<size_t>(blockSize);\r\n}\r\n\r\nbool MpqArchive::HasFile(std::string_view filename) const\r\n{\r\n\tstd::uint32_t fileNumber;\r\n\tconst int32_t error = libmpq__file_number_s(archive_, filename.data(), filename.size(), &fileNumber);\r\n\treturn error == 0;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_reader.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#include \"mpq/mpq_common.hpp\"\r\n\r\n// Forward-declare so that we can avoid exposing libmpq.\r\nstruct mpq_archive;\r\nusing mpq_archive_s = struct mpq_archive;\r\n\r\nnamespace devilution {\r\n\r\nclass MpqArchive {\r\npublic:\r\n\t// If the file does not exist, returns nullopt without an error.\r\n\tstatic std::optional<MpqArchive> Open(const char *path, int32_t &error);\r\n\r\n\tstd::optional<MpqArchive> Clone(int32_t &error);\r\n\r\n\tstatic const char *ErrorMessage(int32_t errorCode);\r\n\r\n\tMpqArchive(MpqArchive &&other) noexcept\r\n\t    : path_(std::move(other.path_))\r\n\t    , archive_(other.archive_)\r\n\t    , tmp_buf_(std::move(other.tmp_buf_))\r\n\t{\r\n\t\tother.archive_ = nullptr;\r\n\t}\r\n\r\n\tMpqArchive &operator=(MpqArchive &&other) noexcept;\r\n\r\n\t~MpqArchive();\r\n\r\n\t// Returns false if the file does not exit.\r\n\tbool GetFileNumber(MpqFileHash fileHash, uint32_t &fileNumber);\r\n\r\n\tstd::unique_ptr<std::byte[]> ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error);\r\n\r\n\t// Returns error code.\r\n\tint32_t ReadBlock(uint32_t fileNumber, uint32_t blockNumber, uint8_t *out, size_t outSize);\r\n\r\n\tstd::size_t GetUnpackedFileSize(uint32_t fileNumber, int32_t &error);\r\n\r\n\tuint32_t GetNumBlocks(uint32_t fileNumber, int32_t &error);\r\n\r\n\tint32_t OpenBlockOffsetTable(uint32_t fileNumber, std::string_view filename);\r\n\r\n\tint32_t CloseBlockOffsetTable(uint32_t fileNumber);\r\n\r\n\t// Requires the block offset table to be open\r\n\tstd::size_t GetBlockSize(uint32_t fileNumber, uint32_t blockNumber, int32_t &error);\r\n\r\n\tbool HasFile(std::string_view filename) const;\r\n\r\nprivate:\r\n\tMpqArchive(std::string path, mpq_archive_s *archive)\r\n\t    : path_(std::move(path))\r\n\t    , archive_(archive)\r\n\t{\r\n\t}\r\n\r\n\tstd::vector<std::uint8_t> &GetTemporaryBuffer(std::size_t size)\r\n\t{\r\n\t\tif (tmp_buf_.size() < size)\r\n\t\t\ttmp_buf_.resize(size);\r\n\t\treturn tmp_buf_;\r\n\t}\r\n\r\n\tstd::string path_;\r\n\tmpq_archive_s *archive_;\r\n\tstd::vector<std::uint8_t> tmp_buf_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_sdl_rwops.cpp",
    "content": "#include \"mpq/mpq_sdl_rwops.hpp\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl_compat.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct Data {\r\n\t// File information:\r\n\tstd::optional<MpqArchive> ownedArchive;\r\n\tMpqArchive *mpqArchive;\r\n\tuint32_t fileNumber;\r\n\tsize_t blockSize;\r\n\tsize_t lastBlockSize;\r\n\tuint32_t numBlocks;\r\n\tsize_t size;\r\n\r\n\t// State:\r\n\tsize_t position;\r\n\tbool blockRead;\r\n\tstd::unique_ptr<uint8_t[]> blockData;\r\n};\r\n\r\n#ifdef USE_SDL3\r\nData *GetData(void *userdata) { return reinterpret_cast<Data *>(userdata); }\r\n#else\r\nData *GetData(struct SDL_RWops *context)\r\n{\r\n\treturn reinterpret_cast<Data *>(context->hidden.unknown.data1);\r\n}\r\n\r\nvoid SetData(struct SDL_RWops *context, Data *data)\r\n{\r\n\tcontext->hidden.unknown.data1 = data;\r\n}\r\n#endif\r\n\r\n#ifndef USE_SDL1\r\nusing OffsetType = Sint64;\r\nusing SizeType = size_t;\r\n#else\r\nusing OffsetType = int;\r\nusing SizeType = int;\r\n#endif\r\n\r\nextern \"C\" {\r\n\r\n#ifndef USE_SDL1\r\nstatic Sint64 MpqFileRwSize(\r\n#ifdef USE_SDL3\r\n    void *\r\n#else\r\n    struct SDL_RWops *\r\n#endif\r\n        context)\r\n{\r\n\treturn static_cast<Sint64>(GetData(context)->size);\r\n}\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\nstatic Sint64 MpqFileRwSeek(void *context, Sint64 offset, SDL_IOWhence whence)\r\n#else\r\nstatic OffsetType MpqFileRwSeek(struct SDL_RWops *context, OffsetType offset, int whence)\r\n#endif\r\n{\r\n\tData &data = *GetData(context);\r\n\tOffsetType newPosition;\r\n\tswitch (whence) {\r\n\tcase SDL_IO_SEEK_SET:\r\n\t\tnewPosition = offset;\r\n\t\tbreak;\r\n\tcase SDL_IO_SEEK_CUR:\r\n\t\tnewPosition = static_cast<OffsetType>(data.position + offset);\r\n\t\tbreak;\r\n\tcase SDL_IO_SEEK_END:\r\n\t\tnewPosition = static_cast<OffsetType>(data.size + offset);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tif (newPosition == static_cast<OffsetType>(data.position))\r\n\t\treturn newPosition;\r\n\r\n\tif (newPosition > static_cast<OffsetType>(data.size)) {\r\n\t\tSDL_SetError(\"MpqFileRwSeek beyond EOF (%d > %u)\", static_cast<int>(newPosition), static_cast<unsigned>(data.size));\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tif (newPosition < 0) {\r\n\t\tSDL_SetError(\"MpqFileRwSeek beyond BOF (%d < 0)\", static_cast<int>(newPosition));\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tif (data.position / data.blockSize != static_cast<size_t>(newPosition) / data.blockSize)\r\n\t\tdata.blockRead = false;\r\n\r\n\tdata.position = static_cast<size_t>(newPosition);\r\n\r\n\treturn newPosition;\r\n}\r\n\r\n#ifdef USE_SDL3\r\nstatic SizeType MpqFileRwRead(void *context, void *ptr, size_t size, SDL_IOStatus *status)\r\n#else\r\nstatic SizeType MpqFileRwRead(struct SDL_RWops *context, void *ptr, SizeType size, SizeType maxnum)\r\n#endif\r\n{\r\n#ifdef USE_SDL3\r\n\tconst size_t maxnum = 1;\r\n#endif\r\n\tData &data = *GetData(context);\r\n\tconst size_t totalSize = size * maxnum;\r\n\tsize_t remainingSize = totalSize;\r\n\r\n\tauto *out = static_cast<uint8_t *>(ptr);\r\n\r\n\tif (data.blockData == nullptr) {\r\n\t\tdata.blockData = std::unique_ptr<uint8_t[]> { new uint8_t[data.blockSize] };\r\n\t}\r\n\r\n\tauto blockNumber = static_cast<uint32_t>(data.position / data.blockSize);\r\n\twhile (remainingSize > 0) {\r\n\t\tif (data.position == data.size) {\r\n#ifdef USE_SDL3\r\n\t\t\t*status = SDL_IO_STATUS_EOF;\r\n#endif\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tconst size_t currentBlockSize = blockNumber + 1 == data.numBlocks ? data.lastBlockSize : data.blockSize;\r\n\r\n\t\tif (!data.blockRead) {\r\n\t\t\tconst int32_t error = data.mpqArchive->ReadBlock(data.fileNumber, blockNumber, data.blockData.get(), currentBlockSize);\r\n\t\t\tif (error != 0) {\r\n\t\t\t\tSDL_SetError(\"MpqFileRwRead ReadBlock: %s\", MpqArchive::ErrorMessage(error));\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t\tdata.blockRead = true;\r\n\t\t}\r\n\r\n\t\tconst size_t blockPosition = data.position - (blockNumber * data.blockSize);\r\n\t\tconst size_t remainingBlockSize = currentBlockSize - blockPosition;\r\n\r\n\t\tif (remainingSize < remainingBlockSize) {\r\n\t\t\tstd::memcpy(out, data.blockData.get() + blockPosition, remainingSize);\r\n\t\t\tdata.position += remainingSize;\r\n#ifdef USE_SDL3\r\n\t\t\treturn size;\r\n#else\r\n\t\t\treturn maxnum;\r\n#endif\r\n\t\t}\r\n\r\n\t\tstd::memcpy(out, data.blockData.get() + blockPosition, remainingBlockSize);\r\n\t\tout += remainingBlockSize;\r\n\t\tdata.position += remainingBlockSize;\r\n\t\tremainingSize -= remainingBlockSize;\r\n\t\t++blockNumber;\r\n\t\tdata.blockRead = false;\r\n\t}\r\n\r\n#ifdef USE_SDL3\r\n\treturn static_cast<SizeType>(totalSize - remainingSize);\r\n#else\r\n\treturn static_cast<SizeType>((totalSize - remainingSize) / size);\r\n#endif\r\n}\r\n\r\n#ifdef USE_SDL3\r\nstatic bool MpqFileRwClose(void *context)\r\n#else\r\nstatic int MpqFileRwClose(struct SDL_RWops *context)\r\n#endif\r\n{\r\n\tData *data = GetData(context);\r\n\tdata->mpqArchive->CloseBlockOffsetTable(data->fileNumber);\r\n\tdelete data;\r\n#ifdef USE_SDL3\r\n\treturn true;\r\n#else\r\n\tdelete context;\r\n\treturn 0;\r\n#endif\r\n}\r\n\r\n} // extern \"C\"\r\n\r\n} // namespace\r\n\r\nSDL_IOStream *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe)\r\n{\r\n#ifdef USE_SDL3\r\n\tSDL_IOStreamInterface interface;\r\n\tSDL_INIT_INTERFACE(&interface);\r\n\tSDL_IOStreamInterface *result = &interface;\r\n#else\r\n\tauto result = std::make_unique<SDL_RWops>();\r\n\tstd::memset(result.get(), 0, sizeof(*result));\r\n#endif\r\n\r\n#ifndef USE_SDL1\r\n\tresult->size = &MpqFileRwSize;\r\n#ifndef USE_SDL3\r\n\tresult->type = SDL_RWOPS_UNKNOWN;\r\n#endif\r\n#else\r\n\tresult->type = 0;\r\n#endif\r\n\r\n\tresult->seek = &MpqFileRwSeek;\r\n\tresult->read = &MpqFileRwRead;\r\n\tresult->write = nullptr;\r\n\tresult->close = &MpqFileRwClose;\r\n#ifdef USE_SDL3\r\n\tresult->flush = nullptr;\r\n#endif\r\n\r\n\tauto data = std::make_unique<Data>();\r\n\tint32_t error = 0;\r\n\r\n\tif (threadsafe) {\r\n\t\tdata->ownedArchive = mpqArchive.Clone(error);\r\n\t\tif (error != 0) {\r\n\t\t\tSDL_SetError(\"MpqFileRwRead Clone: %s\", MpqArchive::ErrorMessage(error));\r\n\t\t\treturn nullptr;\r\n\t\t}\r\n\t\tdata->mpqArchive = &*data->ownedArchive;\r\n\t} else {\r\n\t\tdata->mpqArchive = &mpqArchive;\r\n\t}\r\n\tdata->fileNumber = fileNumber;\r\n\tMpqArchive &archive = *data->mpqArchive;\r\n\r\n\terror = archive.OpenBlockOffsetTable(fileNumber, filename);\r\n\tif (error != 0) {\r\n\t\tSDL_SetError(\"MpqFileRwRead OpenBlockOffsetTable: %s\", MpqArchive::ErrorMessage(error));\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tdata->size = archive.GetUnpackedFileSize(fileNumber, error);\r\n\tif (error != 0) {\r\n\t\tSDL_SetError(\"MpqFileRwRead GetUnpackedFileSize: %s\", MpqArchive::ErrorMessage(error));\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tconst std::uint32_t numBlocks = archive.GetNumBlocks(fileNumber, error);\r\n\tif (error != 0) {\r\n\t\tSDL_SetError(\"MpqFileRwRead GetNumBlocks: %s\", MpqArchive::ErrorMessage(error));\r\n\t\treturn nullptr;\r\n\t}\r\n\tdata->numBlocks = numBlocks;\r\n\r\n\tconst size_t blockSize = archive.GetBlockSize(fileNumber, 0, error);\r\n\tif (error != 0) {\r\n\t\tSDL_SetError(\"MpqFileRwRead GetBlockSize: %s\", MpqArchive::ErrorMessage(error));\r\n\t\treturn nullptr;\r\n\t}\r\n\tdata->blockSize = blockSize;\r\n\r\n\tif (numBlocks > 1) {\r\n\t\tdata->lastBlockSize = archive.GetBlockSize(fileNumber, numBlocks - 1, error);\r\n\t\tif (error != 0) {\r\n\t\t\tSDL_SetError(\"MpqFileRwRead GetBlockSize: %s\", MpqArchive::ErrorMessage(error));\r\n\t\t\treturn nullptr;\r\n\t\t}\r\n\t} else {\r\n\t\tdata->lastBlockSize = blockSize;\r\n\t}\r\n\r\n\tdata->position = 0;\r\n\tdata->blockRead = false;\r\n\r\n#ifdef USE_SDL3\r\n\treturn SDL_OpenIO(&interface, data.release());\r\n#else\r\n\tSetData(result.get(), data.release());\r\n\treturn result.release();\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_sdl_rwops.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl_compat.h\"\r\n#endif\r\n\r\n#include \"mpq/mpq_reader.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nSDL_IOStream *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_writer.cpp",
    "content": "#include \"mpq/mpq_writer.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n#include <type_traits>\r\n\r\n#include <libmpq/mpq.h>\r\n\r\n#include \"appfat.h\"\r\n#include \"encrypt.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n// Validates that a Type is of a particular size and that its alignment is <= the size of the type.\r\n// Done with templates so that error messages include actual size.\r\ntemplate <size_t A, size_t B>\r\nstruct AssertEq : std::true_type {\r\n\tstatic_assert(A == B, \"A == B not satisfied\");\r\n};\r\ntemplate <size_t A, size_t B>\r\nstruct AssertLte : std::true_type {\r\n\tstatic_assert(A <= B, \"A <= B not satisfied\");\r\n};\r\ntemplate <typename T, size_t S>\r\nstruct CheckSize : AssertEq<sizeof(T), S>, AssertLte<alignof(T), sizeof(T)> {\r\n};\r\n\r\n// Check sizes and alignments of the structs that we decrypt and encrypt.\r\n// The decryption algorithm treats them as a stream of 32-bit uints, so the\r\n// sizes must be exact as there cannot be any padding.\r\nstatic_assert(CheckSize<MpqHashEntry, static_cast<size_t>(4 * 4)>::value, \"sizeof(MpqHashEntry) == 4 * 4 && alignof(MpqHashEntry) <= 4 * 4 not satisfied\");\r\nstatic_assert(CheckSize<MpqBlockEntry, static_cast<size_t>(4 * 4)>::value, \"sizeof(MpqBlockEntry) == 4 * 4 && alignof(MpqBlockEntry) <= 4 * 4 not satisfied\");\r\n\r\n// We use fixed size block and hash entry tables.\r\nconstexpr uint32_t HashEntriesCount = 2048;\r\nconstexpr uint32_t BlockEntriesCount = 2048;\r\nconstexpr uint32_t BlockEntrySize = HashEntriesCount * sizeof(MpqBlockEntry);\r\nconstexpr uint32_t HashEntrySize = BlockEntriesCount * sizeof(MpqHashEntry);\r\n\r\n// We store the block and the hash entry tables immediately after the header.\r\n// This is unlike most other MPQ archives, that store these at the end of the file.\r\nconstexpr long MpqBlockEntryOffset = sizeof(MpqFileHeader);\r\nconstexpr long MpqHashEntryOffset = MpqBlockEntryOffset + BlockEntrySize;\r\n\r\n// Special return value for `GetHashIndex` and `GetHandle`.\r\nconstexpr uint32_t HashEntryNotFound = -1;\r\n\r\n// We use 4096-byte blocks, generally.\r\nconstexpr uint16_t BlockSizeFactor = 3;\r\nconstexpr uint32_t BlockSize = 512 << BlockSizeFactor; // 4096\r\n\r\n// Sometimes we can end up with smaller blocks.\r\nconstexpr uint32_t MinBlockSize = 1024;\r\n\r\nvoid ByteSwapHdr(MpqFileHeader *hdr)\r\n{\r\n\thdr->signature = Swap32LE(hdr->signature);\r\n\thdr->headerSize = Swap32LE(hdr->headerSize);\r\n\thdr->fileSize = Swap32LE(hdr->fileSize);\r\n\thdr->version = Swap16LE(hdr->version);\r\n\thdr->blockSizeFactor = Swap16LE(hdr->blockSizeFactor);\r\n\thdr->hashEntriesOffset = Swap32LE(hdr->hashEntriesOffset);\r\n\thdr->blockEntriesOffset = Swap32LE(hdr->blockEntriesOffset);\r\n\thdr->hashEntriesCount = Swap32LE(hdr->hashEntriesCount);\r\n\thdr->blockEntriesCount = Swap32LE(hdr->blockEntriesCount);\r\n}\r\n\r\nbool IsAllocatedUnusedBlock(const MpqBlockEntry *block)\r\n{\r\n\treturn block->offset != 0 && block->flags == 0 && block->unpackedSize == 0;\r\n}\r\n\r\nbool IsUnallocatedBlock(const MpqBlockEntry *block)\r\n{\r\n\treturn block->offset == 0 && block->packedSize == 0 && block->unpackedSize == 0 && block->flags == 0;\r\n}\r\n\r\n} // namespace\r\n\r\nMpqWriter::MpqWriter(const char *path)\r\n{\r\n\tconst std::string dir = std::string(Dirname(path));\r\n\tif (!dir.empty()) {\r\n\t\tRecursivelyCreateDir(dir.c_str());\r\n\t}\r\n\tLogVerbose(\"Opening {}\", path);\r\n\tbool isNewFile = false;\r\n\tstd::string error;\r\n\tif (!FileExists(path)) {\r\n\t\t// FileExists() may return false in the case of an error\r\n\t\t// so we use \"ab\" instead of \"wb\" to avoid accidentally\r\n\t\t// truncating an existing file\r\n\t\tstream_.Open(path, \"ab\");\r\n\r\n\t\t// However, we cannot actually use a file handle that was\r\n\t\t// opened in \"ab\" mode because we need to be able to seek\r\n\t\t// and write to the middle of the file\r\n\t\tstream_.Close();\r\n\t}\r\n\r\n\tstd::uintmax_t fileSize;\r\n\tif (!GetFileSize(path, &fileSize)) {\r\n\t\terror = R\"(GetFileSize failed: \"{}\")\";\r\n\t\tLogError(error, path, std::strerror(errno));\r\n\t\tgoto on_error;\r\n\t}\r\n\tsize_ = static_cast<uint32_t>(fileSize);\r\n\tisNewFile = size_ == 0;\r\n\tLogVerbose(\"GetFileSize(\\\"{}\\\") = {}\", path, size_);\r\n\r\n\tif (!stream_.Open(path, \"r+b\")) {\r\n\t\tstream_.Close();\r\n\t\terror = \"Failed to open file\";\r\n\t\tgoto on_error;\r\n\t}\r\n\r\n\tname_ = path;\r\n\r\n\tif (blockTable_ == nullptr || hashTable_ == nullptr) {\r\n\t\tMpqFileHeader fhdr;\r\n\t\tif (isNewFile) {\r\n\t\t\tInitDefaultMpqHeader(&fhdr);\r\n\t\t} else if (!ReadMPQHeader(&fhdr)) {\r\n\t\t\terror = \"Failed to read MPQ header\";\r\n\t\t\tgoto on_error;\r\n\t\t}\r\n\t\tblockTable_ = std::make_unique<MpqBlockEntry[]>(BlockEntriesCount);\r\n\t\tstd::memset(blockTable_.get(), 0, BlockEntriesCount * sizeof(MpqBlockEntry));\r\n\t\tif (fhdr.blockEntriesCount > 0) {\r\n\t\t\tif (!stream_.Read(reinterpret_cast<char *>(blockTable_.get()), static_cast<size_t>(fhdr.blockEntriesCount * sizeof(MpqBlockEntry)))) {\r\n\t\t\t\terror = \"Failed to read block table\";\r\n\t\t\t\tgoto on_error;\r\n\t\t\t}\r\n\t\t\tlibmpq__decrypt_block(reinterpret_cast<uint32_t *>(blockTable_.get()), fhdr.blockEntriesCount * sizeof(MpqBlockEntry), LIBMPQ_BLOCK_TABLE_HASH_KEY);\r\n\t\t}\r\n\t\thashTable_ = std::make_unique<MpqHashEntry[]>(HashEntriesCount);\r\n\r\n\t\t// We fill with 0xFF so that the `block` field defaults to -1 (a null block pointer).\r\n\t\tstd::memset(hashTable_.get(), 0xFF, HashEntriesCount * sizeof(MpqHashEntry));\r\n\r\n\t\tif (fhdr.hashEntriesCount > 0) {\r\n\t\t\tif (!stream_.Read(reinterpret_cast<char *>(hashTable_.get()), static_cast<size_t>(fhdr.hashEntriesCount * sizeof(MpqHashEntry)))) {\r\n\t\t\t\terror = \"Failed to read hash entries\";\r\n\t\t\t\tgoto on_error;\r\n\t\t\t}\r\n\t\t\tlibmpq__decrypt_block(reinterpret_cast<uint32_t *>(hashTable_.get()), fhdr.hashEntriesCount * sizeof(MpqHashEntry), LIBMPQ_HASH_TABLE_HASH_KEY);\r\n\t\t}\r\n\r\n#ifndef CAN_SEEKP_BEYOND_EOF\r\n\t\tif (!stream_.Seekp(0, SEEK_SET))\r\n\t\t\tgoto on_error;\r\n\r\n\t\t// Memorize stream begin, we'll need it for calculations later.\r\n\t\tif (!stream_.Tellp(&streamBegin_))\r\n\t\t\tgoto on_error;\r\n\r\n\t\t// Write garbage header and tables because some platforms cannot `Seekp` beyond EOF.\r\n\t\t// The data is incorrect at this point, it will be overwritten on Close.\r\n\t\tif (isNewFile)\r\n\t\t\tWriteHeaderAndTables();\r\n#endif\r\n\t}\r\n\treturn;\r\non_error:\r\n\tapp_fatal(StrCat(_(\"Failed to open archive for writing.\"), \"\\n\", path, \"\\n\", error));\r\n}\r\n\r\nMpqWriter::~MpqWriter()\r\n{\r\n\tif (!stream_.IsOpen())\r\n\t\treturn;\r\n\tLogVerbose(\"Closing {}\", name_);\r\n\r\n\tbool result = true;\r\n\tif (!(stream_.Seekp(0, SEEK_SET) && WriteHeaderAndTables()))\r\n\t\tresult = false;\r\n\tstream_.Close();\r\n\tif (result && size_ != 0) {\r\n\t\tLogVerbose(\"ResizeFile(\\\"{}\\\", {})\", name_, size_);\r\n\t\tresult = ResizeFile(name_.c_str(), size_);\r\n\t}\r\n\tif (!result)\r\n\t\tLogVerbose(\"Closing failed {}\", name_);\r\n}\r\n\r\nuint32_t MpqWriter::FetchHandle(std::string_view filename) const\r\n{\r\n\treturn GetHashIndex(CalculateMpqFileHash(filename));\r\n}\r\n\r\nvoid MpqWriter::InitDefaultMpqHeader(MpqFileHeader *hdr)\r\n{\r\n\tstd::memset(hdr, 0, sizeof(*hdr));\r\n\thdr->signature = MpqFileHeader::DiabloSignature;\r\n\thdr->headerSize = MpqFileHeader::DiabloSize;\r\n\thdr->blockSizeFactor = BlockSizeFactor;\r\n\thdr->version = 0;\r\n\tsize_ = MpqHashEntryOffset + HashEntrySize;\r\n}\r\n\r\nbool MpqWriter::IsValidMpqHeader(MpqFileHeader *hdr) const\r\n{\r\n\treturn hdr->signature == MpqFileHeader::DiabloSignature\r\n\t    && hdr->headerSize == MpqFileHeader::DiabloSize\r\n\t    && hdr->version <= 0\r\n\t    && hdr->blockSizeFactor == BlockSizeFactor\r\n\t    && hdr->fileSize == size_\r\n\t    && hdr->hashEntriesOffset == MpqHashEntryOffset\r\n\t    && hdr->blockEntriesOffset == sizeof(MpqFileHeader)\r\n\t    && hdr->hashEntriesCount == HashEntriesCount\r\n\t    && hdr->blockEntriesCount == BlockEntriesCount;\r\n}\r\n\r\nbool MpqWriter::ReadMPQHeader(MpqFileHeader *hdr)\r\n{\r\n\tconst bool hasHdr = size_ >= sizeof(*hdr);\r\n\tif (hasHdr) {\r\n\t\tif (!stream_.Read(reinterpret_cast<char *>(hdr), sizeof(*hdr)))\r\n\t\t\treturn false;\r\n\t\tByteSwapHdr(hdr);\r\n\t}\r\n\tif (!hasHdr || !IsValidMpqHeader(hdr)) {\r\n\t\tInitDefaultMpqHeader(hdr);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nMpqBlockEntry *MpqWriter::NewBlock(uint32_t *blockIndex)\r\n{\r\n\tMpqBlockEntry *blockEntry = blockTable_.get();\r\n\r\n\tfor (unsigned i = 0; i < BlockEntriesCount; ++i, ++blockEntry) {\r\n\t\tif (!IsUnallocatedBlock(blockEntry))\r\n\t\t\tcontinue;\r\n\r\n\t\tif (blockIndex != nullptr)\r\n\t\t\t*blockIndex = i;\r\n\r\n\t\treturn blockEntry;\r\n\t}\r\n\r\n\tapp_fatal(\"Out of free block entries\");\r\n}\r\n\r\nvoid MpqWriter::AllocBlock(uint32_t blockOffset, uint32_t blockSize)\r\n{\r\n\tMpqBlockEntry *block;\r\n\tbool expand;\r\n\tdo {\r\n\t\tblock = blockTable_.get();\r\n\t\texpand = false;\r\n\t\tfor (unsigned i = BlockEntriesCount; i-- != 0; ++block) {\r\n\t\t\t// Expand to adjacent blocks.\r\n\t\t\tif (!IsAllocatedUnusedBlock(block))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (block->offset + block->packedSize == blockOffset) {\r\n\t\t\t\tblockOffset = block->offset;\r\n\t\t\t\tblockSize += block->packedSize;\r\n\t\t\t\tmemset(block, 0, sizeof(MpqBlockEntry));\r\n\t\t\t\texpand = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif (blockOffset + blockSize == block->offset) {\r\n\t\t\t\tblockSize += block->packedSize;\r\n\t\t\t\tmemset(block, 0, sizeof(MpqBlockEntry));\r\n\t\t\t\texpand = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t} while (expand);\r\n\tif (blockOffset + blockSize > size_) {\r\n\t\t// Expanded beyond EOF, this should never happen.\r\n\t\tapp_fatal(\"MPQ free list error\");\r\n\t}\r\n\tif (blockOffset + blockSize == size_) {\r\n\t\tsize_ = blockOffset;\r\n\t} else {\r\n\t\tblock = NewBlock();\r\n\t\tblock->offset = blockOffset;\r\n\t\tblock->packedSize = blockSize;\r\n\t\tblock->unpackedSize = 0;\r\n\t\tblock->flags = 0;\r\n\t}\r\n}\r\n\r\nuint32_t MpqWriter::FindFreeBlock(uint32_t size)\r\n{\r\n\tuint32_t result;\r\n\r\n\tMpqBlockEntry *block = blockTable_.get();\r\n\tfor (unsigned i = 0; i < BlockEntriesCount; ++i, ++block) {\r\n\t\t// Find a block entry to use space from.\r\n\t\tif (!IsAllocatedUnusedBlock(block) || block->packedSize < size)\r\n\t\t\tcontinue;\r\n\r\n\t\tresult = block->offset;\r\n\t\tblock->offset += size;\r\n\t\tblock->packedSize -= size;\r\n\r\n\t\t// Clear the block entry if we used its entire capacity.\r\n\t\tif (block->packedSize == 0)\r\n\t\t\tmemset(block, 0, sizeof(*block));\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tresult = size_;\r\n\tsize_ += size;\r\n\treturn result;\r\n}\r\n\r\nuint32_t MpqWriter::GetHashIndex(MpqFileHash fileHash) const // NOLINT(bugprone-easily-swappable-parameters)\r\n{\r\n\tuint32_t i = HashEntriesCount;\r\n\tfor (unsigned idx = fileHash[0] & 0x7FF; hashTable_[idx].block != MpqHashEntry::NullBlock; idx = (idx + 1) & 0x7FF) {\r\n\t\tif (i-- == 0)\r\n\t\t\tbreak;\r\n\t\tif (hashTable_[idx].hashA != fileHash[1])\r\n\t\t\tcontinue;\r\n\t\tif (hashTable_[idx].hashB != fileHash[2])\r\n\t\t\tcontinue;\r\n\t\tif (hashTable_[idx].block == MpqHashEntry::DeletedBlock)\r\n\t\t\tcontinue;\r\n\r\n\t\treturn idx;\r\n\t}\r\n\r\n\treturn HashEntryNotFound;\r\n}\r\n\r\nbool MpqWriter::WriteHeaderAndTables()\r\n{\r\n\treturn WriteHeader() && WriteBlockTable() && WriteHashTable();\r\n}\r\n\r\nMpqBlockEntry *MpqWriter::AddFile(std::string_view filename, MpqBlockEntry *block, uint32_t blockIndex)\r\n{\r\n\tconst MpqFileHash fileHash = CalculateMpqFileHash(filename);\r\n\tif (GetHashIndex(fileHash) != HashEntryNotFound)\r\n\t\tapp_fatal(StrCat(\"Hash collision between \\\"\", filename, \"\\\" and existing file\\n\"));\r\n\tunsigned int hIdx = fileHash[0] & 0x7FF;\r\n\r\n\tbool hasSpace = false;\r\n\tfor (unsigned i = 0; i < HashEntriesCount; ++i) {\r\n\t\tif (hashTable_[hIdx].block == MpqHashEntry::NullBlock || hashTable_[hIdx].block == MpqHashEntry::DeletedBlock) {\r\n\t\t\thasSpace = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\thIdx = (hIdx + 1) & 0x7FF;\r\n\t}\r\n\tif (!hasSpace)\r\n\t\tapp_fatal(\"Out of hash space\");\r\n\r\n\tif (block == nullptr)\r\n\t\tblock = NewBlock(&blockIndex);\r\n\r\n\tMpqHashEntry &entry = hashTable_[hIdx];\r\n\tentry.hashA = fileHash[1];\r\n\tentry.hashB = fileHash[2];\r\n\tentry.locale = 0;\r\n\tentry.platform = 0;\r\n\tentry.block = blockIndex;\r\n\r\n\treturn block;\r\n}\r\n\r\nbool MpqWriter::WriteFileContents(const std::byte *fileData, uint32_t fileSize, MpqBlockEntry *block)\r\n{\r\n\tconst uint32_t numSectors = (fileSize + (BlockSize - 1)) / BlockSize;\r\n\tconst uint32_t offsetTableByteSize = sizeof(uint32_t) * (numSectors + 1);\r\n\tblock->offset = FindFreeBlock(fileSize + offsetTableByteSize);\r\n\t// `packedSize` is reduced at the end of the function if it turns out to be smaller.\r\n\tblock->packedSize = fileSize + offsetTableByteSize;\r\n\tblock->unpackedSize = fileSize;\r\n\tblock->flags = MpqBlockEntry::FlagExists | MpqBlockEntry::CompressPkZip;\r\n\r\n\t// We populate the table of sector offsets while we write the data.\r\n\t// We can't pre-populate it because we don't know the compressed sector sizes yet.\r\n\t// First offset is the start of the first sector, last offset is the end of the last sector.\r\n\tconst std::unique_ptr<uint32_t[]> offsetTable { new uint32_t[numSectors + 1] };\r\n\r\n#ifdef CAN_SEEKP_BEYOND_EOF\r\n\tif (!stream_.Seekp(block->offset + offsetTableByteSize, SEEK_SET))\r\n\t\treturn false;\r\n#else\r\n\t// Ensure we do not Seekp beyond EOF by filling the missing space.\r\n\tlong stream_end;\r\n\tif (!stream_.Seekp(0, SEEK_END) || !stream_.Tellp(&stream_end))\r\n\t\treturn false;\r\n\tconst std::uintmax_t cur_size = stream_end - streamBegin_;\r\n\tif (cur_size < block->offset + offsetTableByteSize) {\r\n\t\tif (cur_size < block->offset) {\r\n\t\t\tstd::unique_ptr<char[]> filler { new char[block->offset - cur_size] };\r\n\t\t\tif (!stream_.Write(filler.get(), block->offset - cur_size))\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t\tif (!stream_.Write(reinterpret_cast<const char *>(offsetTable.get()), offsetTableByteSize))\r\n\t\t\treturn false;\r\n\t} else {\r\n\t\tif (!stream_.Seekp(block->offset + offsetTableByteSize, SEEK_SET))\r\n\t\t\treturn false;\r\n\t}\r\n#endif\r\n\r\n\tuint32_t destSize = offsetTableByteSize;\r\n\tstd::byte mpqBuf[BlockSize];\r\n\tsize_t curSector = 0;\r\n\twhile (true) {\r\n\t\tuint32_t len = std::min<uint32_t>(fileSize, BlockSize);\r\n\t\tmemcpy(mpqBuf, fileData, len);\r\n\t\tfileData += len;\r\n\t\tlen = PkwareCompress(mpqBuf, len);\r\n\t\tif (!stream_.Write(reinterpret_cast<const char *>(&mpqBuf[0]), len))\r\n\t\t\treturn false;\r\n\t\toffsetTable[curSector++] = Swap32LE(destSize);\r\n\t\tdestSize += len; // compressed length\r\n\t\tif (fileSize <= BlockSize)\r\n\t\t\tbreak;\r\n\r\n\t\tfileSize -= BlockSize;\r\n\t}\r\n\r\n\toffsetTable[numSectors] = Swap32LE(destSize);\r\n\tif (!stream_.Seekp(block->offset, SEEK_SET))\r\n\t\treturn false;\r\n\tif (!stream_.Write(reinterpret_cast<const char *>(offsetTable.get()), offsetTableByteSize))\r\n\t\treturn false;\r\n\tif (!stream_.Seekp(destSize - offsetTableByteSize, SEEK_CUR))\r\n\t\treturn false;\r\n\r\n\tif (destSize < block->packedSize) {\r\n\t\tconst uint32_t remainingBlockSize = block->packedSize - destSize;\r\n\t\tif (remainingBlockSize >= MinBlockSize) {\r\n\t\t\t// Allocate another block if we didn't use all of this one.\r\n\t\t\tblock->packedSize = destSize;\r\n\t\t\tAllocBlock(block->packedSize + block->offset, remainingBlockSize);\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool MpqWriter::WriteHeader()\r\n{\r\n\tMpqFileHeader fhdr;\r\n\r\n\tmemset(&fhdr, 0, sizeof(fhdr));\r\n\tfhdr.signature = MpqFileHeader::DiabloSignature;\r\n\tfhdr.headerSize = MpqFileHeader::DiabloSize;\r\n\tfhdr.fileSize = size_;\r\n\tfhdr.version = 0;\r\n\tfhdr.blockSizeFactor = BlockSizeFactor;\r\n\tfhdr.hashEntriesOffset = MpqHashEntryOffset;\r\n\tfhdr.blockEntriesOffset = MpqBlockEntryOffset;\r\n\tfhdr.hashEntriesCount = HashEntriesCount;\r\n\tfhdr.blockEntriesCount = BlockEntriesCount;\r\n\tByteSwapHdr(&fhdr);\r\n\r\n\treturn stream_.Write(reinterpret_cast<const char *>(&fhdr), sizeof(fhdr));\r\n}\r\n\r\nbool MpqWriter::WriteBlockTable()\r\n{\r\n\tlibmpq__encrypt_block(reinterpret_cast<uint32_t *>(blockTable_.get()), BlockEntrySize, LIBMPQ_BLOCK_TABLE_HASH_KEY);\r\n\tconst bool success = stream_.Write(reinterpret_cast<const char *>(blockTable_.get()), BlockEntrySize);\r\n\tlibmpq__decrypt_block(reinterpret_cast<uint32_t *>(blockTable_.get()), BlockEntrySize, LIBMPQ_BLOCK_TABLE_HASH_KEY);\r\n\treturn success;\r\n}\r\n\r\nbool MpqWriter::WriteHashTable()\r\n{\r\n\tlibmpq__encrypt_block(reinterpret_cast<uint32_t *>(hashTable_.get()), HashEntrySize, LIBMPQ_HASH_TABLE_HASH_KEY);\r\n\tconst bool success = stream_.Write(reinterpret_cast<const char *>(hashTable_.get()), HashEntrySize);\r\n\tlibmpq__decrypt_block(reinterpret_cast<uint32_t *>(hashTable_.get()), HashEntrySize, LIBMPQ_HASH_TABLE_HASH_KEY);\r\n\treturn success;\r\n}\r\n\r\nvoid MpqWriter::RemoveHashEntry(std::string_view filename)\r\n{\r\n\tconst uint32_t hIdx = FetchHandle(filename);\r\n\tif (hIdx == HashEntryNotFound) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tMpqHashEntry *hashEntry = &hashTable_[hIdx];\r\n\tMpqBlockEntry *block = &blockTable_[hashEntry->block];\r\n\thashEntry->block = MpqHashEntry::DeletedBlock;\r\n\tconst uint32_t blockOffset = block->offset;\r\n\tconst uint32_t blockSize = block->packedSize;\r\n\tmemset(block, 0, sizeof(*block));\r\n\tAllocBlock(blockOffset, blockSize);\r\n}\r\n\r\nvoid MpqWriter::RemoveHashEntries(bool (*fnGetName)(uint8_t, char *))\r\n{\r\n\tchar pszFileName[MaxMpqPathSize];\r\n\r\n\tfor (uint8_t i = 0; fnGetName(i, pszFileName); i++) {\r\n\t\tRemoveHashEntry(pszFileName);\r\n\t}\r\n}\r\n\r\nbool MpqWriter::WriteFile(std::string_view filename, const std::byte *data, size_t size)\r\n{\r\n\tMpqBlockEntry *blockEntry;\r\n\r\n\tRemoveHashEntry(filename);\r\n\tblockEntry = AddFile(filename, nullptr, 0);\r\n\tif (!WriteFileContents(data, static_cast<uint32_t>(size), blockEntry)) {\r\n\t\tRemoveHashEntry(filename);\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid MpqWriter::RenameFile(std::string_view name, std::string_view newName) // NOLINT(bugprone-easily-swappable-parameters)\r\n{\r\n\tconst uint32_t index = FetchHandle(name);\r\n\tif (index == HashEntryNotFound) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tMpqHashEntry *hashEntry = &hashTable_[index];\r\n\tconst uint32_t block = hashEntry->block;\r\n\tMpqBlockEntry *blockEntry = &blockTable_[block];\r\n\thashEntry->block = MpqHashEntry::DeletedBlock;\r\n\tAddFile(newName, blockEntry, block);\r\n}\r\n\r\nbool MpqWriter::HasFile(std::string_view name) const\r\n{\r\n\treturn FetchHandle(name) != HashEntryNotFound;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/mpq/mpq_writer.hpp",
    "content": "/**\r\n * @file mpq/mpq_writer.hpp\r\n *\r\n * Interface of functions for creating and editing MPQ files.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"utils/logged_fstream.hpp\"\r\n\r\nnamespace devilution {\r\nclass MpqWriter {\r\npublic:\r\n\texplicit MpqWriter(const char *path);\r\n\texplicit MpqWriter(const std::string &path)\r\n\t    : MpqWriter(path.c_str())\r\n\t{\r\n\t}\r\n\tMpqWriter(MpqWriter &&other) = default;\r\n\tMpqWriter &operator=(MpqWriter &&other) = default;\r\n\t~MpqWriter();\r\n\r\n\tbool HasFile(std::string_view name) const;\r\n\r\n\tvoid RemoveHashEntry(std::string_view filename);\r\n\tvoid RemoveHashEntries(bool (*fnGetName)(uint8_t, char *));\r\n\tbool WriteFile(std::string_view filename, const std::byte *data, size_t size);\r\n\tvoid RenameFile(std::string_view name, std::string_view newName);\r\n\r\nprivate:\r\n\tbool IsValidMpqHeader(MpqFileHeader *hdr) const;\r\n\tuint32_t GetHashIndex(MpqFileHash fileHash) const;\r\n\tuint32_t FetchHandle(std::string_view filename) const;\r\n\r\n\tbool ReadMPQHeader(MpqFileHeader *hdr);\r\n\tMpqBlockEntry *AddFile(std::string_view filename, MpqBlockEntry *block, uint32_t blockIndex);\r\n\tbool WriteFileContents(const std::byte *fileData, uint32_t fileSize, MpqBlockEntry *block);\r\n\r\n\t// Returns an unused entry in the block entry table.\r\n\tMpqBlockEntry *NewBlock(uint32_t *blockIndex = nullptr);\r\n\r\n\t// Marks space at `blockOffset` of size `blockSize` as free (unused) space.\r\n\tvoid AllocBlock(uint32_t blockOffset, uint32_t blockSize);\r\n\r\n\t// Returns the file offset that is followed by empty space of at least the given size.\r\n\tuint32_t FindFreeBlock(uint32_t size);\r\n\r\n\tbool WriteHeaderAndTables();\r\n\tbool WriteHeader();\r\n\tbool WriteBlockTable();\r\n\tbool WriteHashTable();\r\n\tvoid InitDefaultMpqHeader(MpqFileHeader *hdr);\r\n\r\n\tLoggedFStream stream_;\r\n\tstd::string name_;\r\n\tuint32_t size_ {};\r\n\tstd::unique_ptr<MpqHashEntry[]> hashTable_;\r\n\tstd::unique_ptr<MpqBlockEntry[]> blockTable_;\r\n\r\n// Amiga cannot Seekp beyond EOF.\r\n// See https://github.com/bebbo/libnix/issues/30\r\n#ifndef __AMIGA__\r\n#define CAN_SEEKP_BEYOND_EOF\r\n#endif\r\n\r\n#ifndef CAN_SEEKP_BEYOND_EOF\r\n\tlong streamBegin_;\r\n#endif\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/msg.cpp",
    "content": "/**\r\n * @file msg.cpp\r\n *\r\n * Implementation of function for sending and receiving network messages.\r\n */\r\n#include \"msg.h\"\r\n\r\n#include <climits>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <list>\r\n#include <memory>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <fmt/format.h>\r\n\r\n#if !defined(UNPACKED_MPQS) || !defined(UNPACKED_SAVES) || !defined(NONET)\r\n#define USE_PKWARE\r\n#include \"encrypt.h\"\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"automap.h\"\r\n#include \"config.h\"\r\n#include \"control/control.hpp\"\r\n#include \"dead.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"gamemenu.h\"\r\n#include \"items/validation.h\"\r\n#include \"levels/crypt.h\"\r\n#include \"levels/town.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"lighting.h\"\r\n#include \"missiles.h\"\r\n#include \"monster.h\"\r\n#include \"monsters/validation.hpp\"\r\n#include \"nthread.h\"\r\n#include \"objects.h\"\r\n#include \"options.h\"\r\n#include \"pack.h\"\r\n#include \"pfile.h\"\r\n#include \"player.h\"\r\n#include \"plrmsg.h\"\r\n#include \"portals/validation.hpp\"\r\n#include \"quests/validation.hpp\"\r\n#include \"spells.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"sync.h\"\r\n#include \"tmsg.h\"\r\n#include \"towners.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#define ValidateField(logValue, condition)                    \\\r\n\tdo {                                                      \\\r\n\t\tif (!(condition)) {                                   \\\r\n\t\t\tLogFailedPacket(#condition, #logValue, logValue); \\\r\n\t\t\tEventFailedPacket(player._pName);                 \\\r\n\t\t\treturn false;                                     \\\r\n\t\t}                                                     \\\r\n\t} while (0)\r\n\r\n#define ValidateFields(logValue1, logValue2, condition)                                \\\r\n\tdo {                                                                               \\\r\n\t\tif (!(condition)) {                                                            \\\r\n\t\t\tLogFailedPacket(#condition, #logValue1, logValue1, #logValue2, logValue2); \\\r\n\t\t\tEventFailedPacket(player._pName);                                          \\\r\n\t\t\treturn false;                                                              \\\r\n\t\t}                                                                              \\\r\n\t} while (0)\r\n\r\nnamespace devilution {\r\n\r\nvoid EventFailedPacket(const char *playerName)\r\n{\r\n\tconst std::string message = fmt::format(\"Player '{}' sent an invalid packet.\", playerName);\r\n\tEventPlrMsg(message);\r\n}\r\n\r\ntemplate <typename T>\r\nvoid LogFailedPacket(const char *condition, const char *name, T value)\r\n{\r\n\tLogDebug(\"Remote player packet validation failed: ValidateField({}: {}, {})\", name, value, condition);\r\n}\r\n\r\ntemplate <typename T1, typename T2>\r\nvoid LogFailedPacket(const char *condition, const char *name1, T1 value1, const char *name2, T2 value2)\r\n{\r\n\tLogDebug(\"Remote player packet validation failed: ValidateFields({}: {}, {}: {}, {})\", name1, value1, name2, value2, condition);\r\n}\r\n\r\n// #define LOG_RECEIVED_MESSAGES\r\n\r\nuint8_t gbBufferMsgs;\r\nint dwRecCount;\r\n\r\nnamespace {\r\n\r\n#ifdef LOG_RECEIVED_MESSAGES\r\nstd::string_view CmdIdString(_cmd_id cmd)\r\n{\r\n\t// clang-format off\r\n\tswitch (cmd) {\r\n\tcase CMD_STAND: return \"CMD_STAND\";\r\n\tcase CMD_WALKXY: return \"CMD_WALKXY\";\r\n\tcase CMD_ACK_PLRINFO: return \"CMD_ACK_PLRINFO\";\r\n\tcase CMD_ADDSTR: return \"CMD_ADDSTR\";\r\n\tcase CMD_ADDMAG: return \"CMD_ADDMAG\";\r\n\tcase CMD_ADDDEX: return \"CMD_ADDDEX\";\r\n\tcase CMD_ADDVIT: return \"CMD_ADDVIT\";\r\n\tcase CMD_GETITEM: return \"CMD_GETITEM\";\r\n\tcase CMD_AGETITEM: return \"CMD_AGETITEM\";\r\n\tcase CMD_PUTITEM: return \"CMD_PUTITEM\";\r\n\tcase CMD_SPAWNITEM: return \"CMD_SPAWNITEM\";\r\n\tcase CMD_ATTACKXY: return \"CMD_ATTACKXY\";\r\n\tcase CMD_RATTACKXY: return \"CMD_RATTACKXY\";\r\n\tcase CMD_SPELLXY: return \"CMD_SPELLXY\";\r\n\tcase CMD_OPOBJXY: return \"CMD_OPOBJXY\";\r\n\tcase CMD_DISARMXY: return \"CMD_DISARMXY\";\r\n\tcase CMD_ATTACKID: return \"CMD_ATTACKID\";\r\n\tcase CMD_ATTACKPID: return \"CMD_ATTACKPID\";\r\n\tcase CMD_RATTACKID: return \"CMD_RATTACKID\";\r\n\tcase CMD_RATTACKPID: return \"CMD_RATTACKPID\";\r\n\tcase CMD_SPELLID: return \"CMD_SPELLID\";\r\n\tcase CMD_SPELLPID: return \"CMD_SPELLPID\";\r\n\tcase CMD_RESURRECT: return \"CMD_RESURRECT\";\r\n\tcase CMD_OPOBJT: return \"CMD_OPOBJT\";\r\n\tcase CMD_KNOCKBACK: return \"CMD_KNOCKBACK\";\r\n\tcase CMD_TALKXY: return \"CMD_TALKXY\";\r\n\tcase CMD_NEWLVL: return \"CMD_NEWLVL\";\r\n\tcase CMD_WARP: return \"CMD_WARP\";\r\n\tcase CMD_CHEAT_EXPERIENCE: return \"CMD_CHEAT_EXPERIENCE\";\r\n\tcase CMD_CHANGE_SPELL_LEVEL: return \"CMD_CHANGE_SPELL_LEVEL\";\r\n\tcase CMD_DEBUG: return \"CMD_DEBUG\";\r\n\tcase CMD_SYNCDATA: return \"CMD_SYNCDATA\";\r\n\tcase CMD_MONSTDEATH: return \"CMD_MONSTDEATH\";\r\n\tcase CMD_MONSTDAMAGE: return \"CMD_MONSTDAMAGE\";\r\n\tcase CMD_PLRDEAD: return \"CMD_PLRDEAD\";\r\n\tcase CMD_REQUESTGITEM: return \"CMD_REQUESTGITEM\";\r\n\tcase CMD_REQUESTAGITEM: return \"CMD_REQUESTAGITEM\";\r\n\tcase CMD_GOTOGETITEM: return \"CMD_GOTOGETITEM\";\r\n\tcase CMD_GOTOAGETITEM: return \"CMD_GOTOAGETITEM\";\r\n\tcase CMD_OPENDOOR: return \"CMD_OPENDOOR\";\r\n\tcase CMD_CLOSEDOOR: return \"CMD_CLOSEDOOR\";\r\n\tcase CMD_OPERATEOBJ: return \"CMD_OPERATEOBJ\";\r\n\tcase CMD_BREAKOBJ: return \"CMD_BREAKOBJ\";\r\n\tcase CMD_CHANGEPLRITEMS: return \"CMD_CHANGEPLRITEMS\";\r\n\tcase CMD_DELPLRITEMS: return \"CMD_DELPLRITEMS\";\r\n\tcase CMD_CHANGEINVITEMS: return \"CMD_CHANGEINVITEMS\";\r\n\tcase CMD_DELINVITEMS: return \"CMD_DELINVITEMS\";\r\n\tcase CMD_CHANGEBELTITEMS: return \"CMD_CHANGEBELTITEMS\";\r\n\tcase CMD_DELBELTITEMS: return \"CMD_DELBELTITEMS\";\r\n\tcase CMD_PLRDAMAGE: return \"CMD_PLRDAMAGE\";\r\n\tcase CMD_PLRLEVEL: return \"CMD_PLRLEVEL\";\r\n\tcase CMD_DROPITEM: return \"CMD_DROPITEM\";\r\n\tcase CMD_PLAYER_JOINLEVEL: return \"CMD_PLAYER_JOINLEVEL\";\r\n\tcase CMD_SEND_PLRINFO: return \"CMD_SEND_PLRINFO\";\r\n\tcase CMD_SATTACKXY: return \"CMD_SATTACKXY\";\r\n\tcase CMD_ACTIVATEPORTAL: return \"CMD_ACTIVATEPORTAL\";\r\n\tcase CMD_DEACTIVATEPORTAL: return \"CMD_DEACTIVATEPORTAL\";\r\n\tcase CMD_DLEVEL: return \"CMD_DLEVEL\";\r\n\tcase CMD_DLEVEL_JUNK: return \"CMD_DLEVEL_JUNK\";\r\n\tcase CMD_DLEVEL_END: return \"CMD_DLEVEL_END\";\r\n\tcase CMD_HEALOTHER: return \"CMD_HEALOTHER\";\r\n\tcase CMD_STRING: return \"CMD_STRING\";\r\n\tcase CMD_FRIENDLYMODE: return \"CMD_FRIENDLYMODE\";\r\n\tcase CMD_SETSTR: return \"CMD_SETSTR\";\r\n\tcase CMD_SETMAG: return \"CMD_SETMAG\";\r\n\tcase CMD_SETDEX: return \"CMD_SETDEX\";\r\n\tcase CMD_SETVIT: return \"CMD_SETVIT\";\r\n\tcase CMD_RETOWN: return \"CMD_RETOWN\";\r\n\tcase CMD_SPELLXYD: return \"CMD_SPELLXYD\";\r\n\tcase CMD_ITEMEXTRA: return \"CMD_ITEMEXTRA\";\r\n\tcase CMD_SYNCPUTITEM: return \"CMD_SYNCPUTITEM\";\r\n\tcase CMD_SYNCQUEST: return \"CMD_SYNCQUEST\";\r\n\tcase CMD_REQUESTSPAWNGOLEM: return \"CMD_REQUESTSPAWNGOLEM\";\r\n\tcase CMD_SETSHIELD: return \"CMD_SETSHIELD\";\r\n\tcase CMD_REMSHIELD: return \"CMD_REMSHIELD\";\r\n\tcase CMD_SETREFLECT: return \"CMD_SETREFLECT\";\r\n\tcase CMD_NAKRUL: return \"CMD_NAKRUL\";\r\n\tcase CMD_OPENHIVE: return \"CMD_OPENHIVE\";\r\n\tcase CMD_OPENGRAVE: return \"CMD_OPENGRAVE\";\r\n\tcase CMD_SPAWNMONSTER: return \"CMD_SPAWNMONSTER\";\r\n\tcase FAKE_CMD_SETID: return \"FAKE_CMD_SETID\";\r\n\tcase FAKE_CMD_DROPID: return \"FAKE_CMD_DROPID\";\r\n\tcase CMD_INVALID: return \"CMD_INVALID\";\r\n\tdefault: return \"\";\r\n\t}\r\n\t// clang-format on\r\n}\r\n#endif // LOG_RECEIVED_MESSAGES\r\n\r\nstruct TMegaPkt {\r\n\tsize_t spaceLeft;\r\n\tstd::byte data[32000];\r\n\r\n\tTMegaPkt()\r\n\t    : spaceLeft(sizeof(data))\r\n\t{\r\n\t}\r\n};\r\n\r\n#pragma pack(push, 1)\r\nstruct DMonsterStr {\r\n\tWorldTilePosition position;\r\n\tuint8_t menemy;\r\n\tuint8_t mactive;\r\n\tint32_t hitPoints;\r\n\tint8_t mWhoHit;\r\n};\r\n#pragma pack(pop)\r\n\r\nstruct DObjectStr {\r\n\t_cmd_id bCmd;\r\n};\r\n\r\nstruct DSpawnedMonster {\r\n\tsize_t typeIndex;\r\n\tuint32_t seed;\r\n\tuint8_t golemOwnerPlayerId;\r\n\tint16_t golemSpellLevel;\r\n};\r\n\r\nstruct DLevel {\r\n\tTCmdPItem item[MAXITEMS];\r\n\tankerl::unordered_dense::map<WorldTilePosition, DObjectStr> object;\r\n\tankerl::unordered_dense::map<size_t, DSpawnedMonster> spawnedMonsters;\r\n\tDMonsterStr monster[MaxMonsters];\r\n};\r\n\r\n#pragma pack(push, 1)\r\nstruct LocalLevel {\r\n\tLocalLevel(const uint8_t (&other)[DMAXX][DMAXY])\r\n\t{\r\n\t\tmemcpy(&automapsv, &other, sizeof(automapsv));\r\n\t}\r\n\tuint8_t automapsv[DMAXX][DMAXY];\r\n};\r\n\r\nstruct DPortal {\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\tuint8_t level;\r\n\tuint8_t ltype;\r\n\tuint8_t setlvl;\r\n};\r\n\r\nstruct MultiQuests {\r\n\tquest_state qstate;\r\n\tuint8_t qlog;\r\n\tuint8_t qvar1;\r\n\tuint8_t qvar2;\r\n\tint16_t qmsg;\r\n};\r\n\r\nstruct DJunk {\r\n\tDPortal portal[MAXPORTAL];\r\n\tMultiQuests quests[MAXQUESTS];\r\n};\r\n#pragma pack(pop)\r\n\r\nconstexpr size_t MaxMultiplayerLevels = NUMLEVELS + SL_LAST;\r\nconstexpr size_t MaxChunks = MaxMultiplayerLevels + 4;\r\n\r\nuint32_t sgdwOwnerWait;\r\nuint32_t sgdwRecvOffset;\r\nint sgnCurrMegaPlayer;\r\nankerl::unordered_dense::map<uint8_t, DLevel> DeltaLevels;\r\nuint8_t sbLastCmd;\r\n\r\n/**\r\n * @brief buffer used to receive level deltas, size is the worst expected case assuming every object on a level was touched\r\n */\r\nstd::byte sgRecvBuf[1U                                             /* marker byte, always 0 */\r\n    + sizeof(uint8_t)                                              /* level id */\r\n    + sizeof(DLevel::item)                                         /* items spawned during dungeon generation which have been picked up, and items dropped by a player during a game */\r\n    + sizeof(uint8_t)                                              /* count of object interactions which caused a state change since dungeon generation */\r\n    + (sizeof(WorldTilePosition) + sizeof(_cmd_id)) * MAXOBJECTS   /* location/action pairs for the object interactions */\r\n    + sizeof(DLevel::monster)                                      /* latest monster state */\r\n    + sizeof(uint16_t)                                             /* spawned monster count */\r\n    + (sizeof(uint16_t) + sizeof(DSpawnedMonster)) * MaxMonsters]; /* spawned monsters */\r\n\r\n_cmd_id sgbRecvCmd;\r\nankerl::unordered_dense::map<uint8_t, LocalLevel> LocalLevels;\r\nDJunk sgJunk;\r\nuint8_t sgbDeltaChunks;\r\nstd::list<TMegaPkt> MegaPktList;\r\nItem ItemLimbo;\r\n\r\n/** @brief Last sent player command for the local player. */\r\nTCmdLocParam5 lastSentPlayerCmd;\r\n\r\nvoid RecreateItem(const Player &player, const TCmdPItem &message, Item &item);\r\n\r\nbool IsMonsterDeltaValid(const DMonsterStr &monster)\r\n{\r\n\treturn InDungeonBounds(monster.position) && monster.hitPoints >= 0;\r\n}\r\n\r\nbool IsPortalDeltaValid(const DPortal &portal)\r\n{\r\n\tconst WorldTilePosition position { portal.x, portal.y };\r\n\treturn IsPortalDeltaValid(position, portal.level, portal.ltype, portal.setlvl != 0);\r\n}\r\n\r\nbool IsQuestDeltaValid(quest_id qidx, const MultiQuests &quest)\r\n{\r\n\treturn IsQuestDeltaValid(qidx, quest.qstate, quest.qlog, quest.qmsg);\r\n}\r\n\r\nuint8_t GetLevelForMultiplayer(uint8_t level, bool isSetLevel)\r\n{\r\n\tif (isSetLevel)\r\n\t\treturn level + NUMLEVELS;\r\n\treturn level;\r\n}\r\n\r\n/** @brief Gets a delta level. */\r\nDLevel &GetDeltaLevel(uint8_t level)\r\n{\r\n\tauto keyIt = DeltaLevels.find(level);\r\n\tif (keyIt != DeltaLevels.end())\r\n\t\treturn keyIt->second;\r\n\tDLevel &deltaLevel = DeltaLevels[level];\r\n\tmemset(&deltaLevel.item, 0xFF, sizeof(deltaLevel.item));\r\n\tmemset(&deltaLevel.monster, 0xFF, sizeof(deltaLevel.monster));\r\n\treturn deltaLevel;\r\n}\r\n\r\n/** @brief Gets a delta level. */\r\nDLevel &GetDeltaLevel(const Player &player)\r\n{\r\n\tconst uint8_t level = GetLevelForMultiplayer(player);\r\n\treturn GetDeltaLevel(level);\r\n}\r\n\r\nPoint GetItemPosition(Point position)\r\n{\r\n\tif (CanPut(position))\r\n\t\treturn position;\r\n\r\n\tfor (int k = 1; k < 50; k++) {\r\n\t\tfor (int j = -k; j <= k; j++) {\r\n\t\t\tconst int yy = position.y + j;\r\n\t\t\tfor (int l = -k; l <= k; l++) {\r\n\t\t\t\tconst int xx = position.x + l;\r\n\t\t\t\tif (CanPut({ xx, yy }))\r\n\t\t\t\t\treturn { xx, yy };\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn position;\r\n}\r\n\r\n/**\r\n * @brief Throttles that a player command is only sent once per game tick.\r\n * This is a workaround for a desync that happens when a command is processed in different game ticks for different clients. See https://github.com/diasurgical/devilutionX/issues/2681 for details.\r\n * When a proper fix is implemented this workaround can be removed.\r\n */\r\nbool WasPlayerCmdAlreadyRequested(_cmd_id bCmd, Point position = {}, uint16_t wParam1 = 0, uint16_t wParam2 = 0, uint16_t wParam3 = 0, uint16_t wParam4 = 0, uint16_t wParam5 = 0)\r\n{\r\n\tswitch (bCmd) {\r\n\t// All known commands that result in a changed player action (player.destAction)\r\n\tcase _cmd_id::CMD_RATTACKID:\r\n\tcase _cmd_id::CMD_SPELLID:\r\n\tcase _cmd_id::CMD_ATTACKID:\r\n\tcase _cmd_id::CMD_RATTACKPID:\r\n\tcase _cmd_id::CMD_SPELLPID:\r\n\tcase _cmd_id::CMD_ATTACKPID:\r\n\tcase _cmd_id::CMD_SATTACKXY:\r\n\tcase _cmd_id::CMD_RATTACKXY:\r\n\tcase _cmd_id::CMD_SPELLXY:\r\n\tcase _cmd_id::CMD_SPELLXYD:\r\n\tcase _cmd_id::CMD_WALKXY:\r\n\tcase _cmd_id::CMD_TALKXY:\r\n\tcase _cmd_id::CMD_DISARMXY:\r\n\tcase _cmd_id::CMD_OPOBJXY:\r\n\tcase _cmd_id::CMD_GOTOGETITEM:\r\n\tcase _cmd_id::CMD_GOTOAGETITEM:\r\n\t\tbreak;\r\n\tdefault:\r\n\t\t// None player actions should work normally\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst TCmdLocParam5 newSendParam = { bCmd, static_cast<uint8_t>(position.x), static_cast<uint8_t>(position.y),\r\n\t\tSwap16LE(wParam1), Swap16LE(wParam2), Swap16LE(wParam3), Swap16LE(wParam4), Swap16LE(wParam5) };\r\n\r\n\tif (lastSentPlayerCmd.bCmd == newSendParam.bCmd && lastSentPlayerCmd.x == newSendParam.x && lastSentPlayerCmd.y == newSendParam.y\r\n\t    && lastSentPlayerCmd.wParam1 == newSendParam.wParam1 && lastSentPlayerCmd.wParam2 == newSendParam.wParam2\r\n\t    && lastSentPlayerCmd.wParam3 == newSendParam.wParam3 && lastSentPlayerCmd.wParam4 == newSendParam.wParam4\r\n\t    && lastSentPlayerCmd.wParam5 == newSendParam.wParam5) {\r\n\t\t// Command already send in this game tick => don't send again / throttle\r\n\t\treturn true;\r\n\t}\r\n\r\n\tlastSentPlayerCmd = newSendParam;\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid GetNextPacket()\r\n{\r\n\tMegaPktList.emplace_back();\r\n}\r\n\r\nvoid FreePackets()\r\n{\r\n\tMegaPktList.clear();\r\n}\r\n\r\nvoid PrePacket()\r\n{\r\n\tuint8_t playerId = std::numeric_limits<uint8_t>::max();\r\n\tfor (TMegaPkt &pkt : MegaPktList) {\r\n\t\tstd::byte *data = pkt.data;\r\n\t\tsize_t remainingBytes = sizeof(pkt.data) - pkt.spaceLeft;\r\n\t\twhile (remainingBytes > 0) {\r\n\t\t\tauto cmdId = static_cast<_cmd_id>(*data);\r\n\r\n\t\t\tif (cmdId == FAKE_CMD_SETID) {\r\n\t\t\t\tauto *cmd = reinterpret_cast<TFakeCmdPlr *>(data);\r\n\t\t\t\tdata += sizeof(*cmd);\r\n\t\t\t\tremainingBytes -= sizeof(*cmd);\r\n\t\t\t\tplayerId = cmd->bPlr;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (cmdId == FAKE_CMD_DROPID) {\r\n\t\t\t\tauto *cmd = reinterpret_cast<TFakeDropPlr *>(data);\r\n\t\t\t\tdata += sizeof(*cmd);\r\n\t\t\t\tremainingBytes -= sizeof(*cmd);\r\n\t\t\t\tmulti_player_left(cmd->bPlr, static_cast<leaveinfo_t>(Swap32LE(cmd->dwReason)));\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (playerId >= Players.size()) {\r\n\t\t\t\tLog(\"Missing source of network message\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tconst size_t size = ParseCmd(playerId, reinterpret_cast<TCmd *>(data), remainingBytes);\r\n\t\t\tif (size == 0) {\r\n\t\t\t\tLog(\"Discarding bad network message\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tdata += size;\r\n\t\t\tremainingBytes -= size;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid BufferMessage(const void *message, size_t messageSize)\r\n{\r\n\tif (MegaPktList.back().spaceLeft < messageSize)\r\n\t\tGetNextPacket();\r\n\r\n\tTMegaPkt &currMegaPkt = MegaPktList.back();\r\n\tmemcpy(currMegaPkt.data + sizeof(currMegaPkt.data) - currMegaPkt.spaceLeft, message, messageSize);\r\n\tcurrMegaPkt.spaceLeft -= messageSize;\r\n}\r\n\r\nvoid BufferMessage(uint8_t pnum, const void *message, size_t messageSize)\r\n{\r\n\tif (messageSize > sizeof(TMegaPkt::data)) {\r\n\t\tLog(\"Discarding enormous network message\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (pnum != sgnCurrMegaPlayer) {\r\n\t\tsgnCurrMegaPlayer = pnum;\r\n\r\n\t\tTFakeCmdPlr cmd;\r\n\t\tcmd.bCmd = FAKE_CMD_SETID;\r\n\t\tcmd.bPlr = pnum;\r\n\t\tBufferMessage(&cmd, sizeof(cmd));\r\n\t}\r\n\r\n\tBufferMessage(message, messageSize);\r\n}\r\n\r\nvoid BufferMessage(const Player &player, const void *message, size_t messageSize)\r\n{\r\n\tBufferMessage(player.getId(), message, messageSize);\r\n}\r\n\r\nint WaitForTurns()\r\n{\r\n\tuint32_t turns;\r\n\r\n\tif (sgbDeltaChunks == 0) {\r\n\t\tnthread_send_and_recv_turn(0, 0);\r\n\t\tSNetGetOwnerTurnsWaiting(&turns);\r\n\t\tif (SDL_GetTicks() - sgdwOwnerWait <= 2000 && turns < gdwTurnsInTransit)\r\n\t\t\treturn 0;\r\n\t\tsgbDeltaChunks++;\r\n\t}\r\n\tProcessGameMessagePackets();\r\n\tnthread_send_and_recv_turn(0, 0);\r\n\tif (nthread_has_500ms_passed()) {\r\n\t\tnthread_recv_turns();\r\n\t}\r\n\r\n\tif (gbGameDestroyed)\r\n\t\treturn 100;\r\n\tif (gbDeltaSender >= Players.size()) {\r\n\t\tsgbDeltaChunks = 0;\r\n\t\tsgbRecvCmd = CMD_DLEVEL_END;\r\n\t\tgbDeltaSender = MyPlayerId;\r\n\t\tnthread_set_turn_upper_bit();\r\n\t}\r\n\tif (sgbDeltaChunks == MaxChunks - 1) {\r\n\t\tsgbDeltaChunks = MaxChunks;\r\n\t\treturn 99;\r\n\t}\r\n\treturn 100 * sgbDeltaChunks / static_cast<int>(MaxChunks);\r\n}\r\n\r\nstd::byte *DeltaExportItem(std::byte *dst, const TCmdPItem *src)\r\n{\r\n\tfor (int i = 0; i < MAXITEMS; i++, src++) {\r\n\t\tif (src->bCmd == CMD_INVALID) {\r\n\t\t\t*dst++ = std::byte { 0xFF };\r\n\t\t} else {\r\n\t\t\tmemcpy(dst, src, sizeof(TCmdPItem));\r\n\t\t\tdst += sizeof(TCmdPItem);\r\n\t\t}\r\n\t}\r\n\r\n\treturn dst;\r\n}\r\n\r\nconst std::byte *DeltaImportItem(const std::byte *src, const std::byte *end, TCmdPItem *dst)\r\n{\r\n\tsize_t size = 0;\r\n\tfor (int i = 0; i < MAXITEMS; i++, dst++) {\r\n\t\tif (&src[size] >= end)\r\n\t\t\treturn nullptr;\r\n\t\tif (src[size] == std::byte { 0xFF }) {\r\n\t\t\tmemset(dst, 0xFF, sizeof(TCmdPItem));\r\n\t\t\tsize++;\r\n\t\t} else {\r\n\t\t\tif (&src[size] + sizeof(TCmdPItem) > end)\r\n\t\t\t\treturn nullptr;\r\n\t\t\tmemcpy(dst, &src[size], sizeof(TCmdPItem));\r\n\t\t\tif (!IsItemDeltaValid(*dst))\r\n\t\t\t\tmemset(dst, 0xFF, sizeof(TCmdPItem));\r\n\t\t\tsize += sizeof(TCmdPItem);\r\n\t\t}\r\n\t}\r\n\r\n\treturn src + size;\r\n}\r\n\r\nstd::byte *DeltaExportObject(std::byte *dst, const ankerl::unordered_dense::map<WorldTilePosition, DObjectStr> &src)\r\n{\r\n\t*dst++ = static_cast<std::byte>(src.size());\r\n\tfor (const auto &[position, obj] : src) {\r\n\t\t*dst++ = static_cast<std::byte>(position.x);\r\n\t\t*dst++ = static_cast<std::byte>(position.y);\r\n\t\t*dst++ = static_cast<std::byte>(obj.bCmd);\r\n\t}\r\n\r\n\treturn dst;\r\n}\r\n\r\nconst std::byte *DeltaImportObjects(const std::byte *src, const std::byte *end, ankerl::unordered_dense::map<WorldTilePosition, DObjectStr> &dst)\r\n{\r\n\tdst.clear();\r\n\r\n\tif (src == nullptr || src == end)\r\n\t\treturn nullptr;\r\n\r\n\tauto numDeltas = static_cast<uint8_t>(*src++);\r\n\tif (numDeltas > MAXOBJECTS)\r\n\t\treturn nullptr;\r\n\r\n\tconst size_t numBytes = (sizeof(WorldTilePosition) + sizeof(_cmd_id)) * numDeltas;\r\n\tif (src + numBytes > end)\r\n\t\treturn nullptr;\r\n\r\n\tdst.reserve(numDeltas);\r\n\r\n\tfor (unsigned i = 0; i < numDeltas; i++) {\r\n\t\tconst WorldTilePosition objectPosition { static_cast<WorldTileCoord>(src[0]), static_cast<WorldTileCoord>(src[1]) };\r\n\t\tsrc += 2;\r\n\t\tdst[objectPosition] = DObjectStr { static_cast<_cmd_id>(*src++) };\r\n\t}\r\n\r\n\treturn src;\r\n}\r\n\r\nstd::byte *DeltaExportMonster(std::byte *dst, const DMonsterStr *src)\r\n{\r\n\tfor (size_t i = 0; i < MaxMonsters; i++, src++) {\r\n\t\tif (src->position.x == 0xFF) {\r\n\t\t\t*dst++ = std::byte { 0xFF };\r\n\t\t} else {\r\n\t\t\tmemcpy(dst, src, sizeof(DMonsterStr));\r\n\t\t\tdst += sizeof(DMonsterStr);\r\n\t\t}\r\n\t}\r\n\r\n\treturn dst;\r\n}\r\n\r\nconst std::byte *DeltaImportMonster(const std::byte *src, const std::byte *end, DMonsterStr *dst)\r\n{\r\n\tif (src == nullptr)\r\n\t\treturn nullptr;\r\n\r\n\tsize_t size = 0;\r\n\tfor (size_t i = 0; i < MaxMonsters; i++, dst++) {\r\n\t\tif (&src[size] >= end)\r\n\t\t\treturn nullptr;\r\n\t\tif (src[size] == std::byte { 0xFF }) {\r\n\t\t\tmemset(dst, 0xFF, sizeof(DMonsterStr));\r\n\t\t\tsize++;\r\n\t\t} else {\r\n\t\t\tif (&src[size] + sizeof(DMonsterStr) > end)\r\n\t\t\t\treturn nullptr;\r\n\t\t\tmemcpy(dst, &src[size], sizeof(DMonsterStr));\r\n\t\t\tsize += sizeof(DMonsterStr);\r\n\t\t}\r\n\t}\r\n\r\n\treturn src + size;\r\n}\r\n\r\nstd::byte *DeltaExportSpawnedMonsters(std::byte *dst, const ankerl::unordered_dense::map<size_t, DSpawnedMonster> &spawnedMonsters)\r\n{\r\n\tuint16_t size = Swap16LE(static_cast<uint16_t>(spawnedMonsters.size()));\r\n\tmemcpy(dst, &size, sizeof(uint16_t));\r\n\tdst += sizeof(uint16_t);\r\n\r\n\tfor (const auto &deltaSpawnedMonster : spawnedMonsters) {\r\n\t\tuint16_t monsterId = Swap16LE(static_cast<uint16_t>(deltaSpawnedMonster.first));\r\n\t\tmemcpy(dst, &monsterId, sizeof(uint16_t));\r\n\t\tdst += sizeof(uint16_t);\r\n\r\n\t\tmemcpy(dst, &deltaSpawnedMonster.second, sizeof(DSpawnedMonster));\r\n\t\tdst += sizeof(DSpawnedMonster);\r\n\t}\r\n\r\n\treturn dst;\r\n}\r\n\r\nconst std::byte *DeltaImportSpawnedMonsters(const std::byte *src, const std::byte *end, ankerl::unordered_dense::map<size_t, DSpawnedMonster> &spawnedMonsters)\r\n{\r\n\tif (src == nullptr || src + sizeof(uint16_t) > end)\r\n\t\treturn nullptr;\r\n\r\n\tuint16_t size;\r\n\tmemcpy(&size, src, sizeof(uint16_t));\r\n\tsize = Swap16LE(size);\r\n\tsrc += sizeof(uint16_t);\r\n\tif (size > MaxMonsters)\r\n\t\treturn nullptr;\r\n\r\n\tconst size_t requiredBytes = (sizeof(uint16_t) + sizeof(DSpawnedMonster)) * size;\r\n\tif (src + requiredBytes > end)\r\n\t\treturn nullptr;\r\n\r\n\tfor (size_t i = 0; i < size; i++) {\r\n\t\tuint16_t monsterId;\r\n\t\tmemcpy(&monsterId, src, sizeof(uint16_t));\r\n\t\tmonsterId = Swap16LE(monsterId);\r\n\t\tsrc += sizeof(uint16_t);\r\n\r\n\t\tDSpawnedMonster spawnedMonster;\r\n\t\tmemcpy(&spawnedMonster, src, sizeof(DSpawnedMonster));\r\n\t\tsrc += sizeof(DSpawnedMonster);\r\n\t\tspawnedMonsters.emplace(monsterId, spawnedMonster);\r\n\t}\r\n\r\n\treturn src;\r\n}\r\n\r\nstd::byte *DeltaExportJunk(std::byte *dst)\r\n{\r\n\tfor (auto &portal : sgJunk.portal) {\r\n\t\tif (portal.x == 0xFF) {\r\n\t\t\t*dst++ = std::byte { 0xFF };\r\n\t\t} else {\r\n\t\t\tmemcpy(dst, &portal, sizeof(DPortal));\r\n\t\t\tdst += sizeof(DPortal);\r\n\t\t}\r\n\t}\r\n\r\n\tint q = 0;\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (QuestsData[quest._qidx].isSinglePlayerOnly && UseMultiplayerQuests()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tsgJunk.quests[q].qlog = quest._qlog ? 1 : 0;\r\n\t\tsgJunk.quests[q].qstate = quest._qactive;\r\n\t\tsgJunk.quests[q].qvar1 = quest._qvar1;\r\n\t\tsgJunk.quests[q].qvar2 = quest._qvar2;\r\n\t\tsgJunk.quests[q].qmsg = Swap16LE(static_cast<int16_t>(quest._qmsg));\r\n\t\tmemcpy(dst, &sgJunk.quests[q], sizeof(MultiQuests));\r\n\t\tdst += sizeof(MultiQuests);\r\n\t\tq++;\r\n\t}\r\n\r\n\treturn dst;\r\n}\r\n\r\nconst std::byte *DeltaImportJunk(const std::byte *src, const std::byte *end)\r\n{\r\n\tfor (DPortal &portal : sgJunk.portal) {\r\n\t\tif (src >= end)\r\n\t\t\treturn nullptr;\r\n\t\tif (*src == std::byte { 0xFF }) {\r\n\t\t\tmemset(&portal, 0xFF, sizeof(DPortal));\r\n\t\t\tsrc++;\r\n\t\t} else {\r\n\t\t\tif (src + sizeof(DPortal) > end)\r\n\t\t\t\treturn nullptr;\r\n\t\t\tmemcpy(&portal, src, sizeof(DPortal));\r\n\t\t\tif (!IsPortalDeltaValid(portal))\r\n\t\t\t\tmemset(&portal, 0xFF, sizeof(DPortal));\r\n\t\t\tsrc += sizeof(DPortal);\r\n\t\t}\r\n\t}\r\n\r\n\tint q = 0;\r\n\tfor (int qidx = 0; qidx < MAXQUESTS; qidx++) {\r\n\t\tif (QuestsData[qidx].isSinglePlayerOnly && UseMultiplayerQuests()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (src + sizeof(MultiQuests) > end) {\r\n\t\t\treturn nullptr;\r\n\t\t}\r\n\t\tmemcpy(&sgJunk.quests[q], src, sizeof(MultiQuests));\r\n\t\tif (!IsQuestDeltaValid(static_cast<quest_id>(qidx), sgJunk.quests[q])) {\r\n\t\t\tsgJunk.quests[q].qstate = QUEST_INVALID;\r\n\t\t}\r\n\t\tsrc += sizeof(MultiQuests);\r\n\t\tq++;\r\n\t}\r\n\r\n\treturn src;\r\n}\r\n\r\nuint32_t CompressData(std::byte *buffer, std::byte *end)\r\n{\r\n#ifdef USE_PKWARE\r\n\tconst auto size = static_cast<uint32_t>(end - buffer - 1);\r\n\tconst uint32_t pkSize = PkwareCompress(buffer + 1, size);\r\n\r\n\t*buffer = size != pkSize ? std::byte { 1 } : std::byte { 0 };\r\n\r\n\treturn pkSize + 1;\r\n#else\r\n\t*buffer = std::byte { 0 };\r\n\treturn end - buffer;\r\n#endif\r\n}\r\n\r\nvoid DeltaImportData(_cmd_id cmd, uint32_t recvOffset, int pnum)\r\n{\r\n\tsize_t deltaSize = recvOffset;\r\n\r\n#ifdef USE_PKWARE\r\n\tif (sgRecvBuf[0] != std::byte { 0 }) {\r\n\t\tdeltaSize = PkwareDecompress(&sgRecvBuf[1], static_cast<uint32_t>(deltaSize), sizeof(sgRecvBuf) - 1);\r\n\t\tif (deltaSize == 0) {\r\n\t\t\tLog(\"PKWare decompression failure, dropping player {}\", pnum);\r\n\t\t\tSNetDropPlayer(pnum, leaveinfo_t::LEAVE_DROP);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tconst std::byte *src = &sgRecvBuf[1];\r\n\tconst std::byte *end = src + deltaSize;\r\n\tif (cmd == CMD_DLEVEL_JUNK) {\r\n\t\tsrc = DeltaImportJunk(src, end);\r\n\t} else if (cmd == CMD_DLEVEL) {\r\n\t\tauto i = static_cast<uint8_t>(src[0]);\r\n\t\tsrc += sizeof(uint8_t);\r\n\t\tDLevel &deltaLevel = GetDeltaLevel(i);\r\n\t\tsrc = DeltaImportItem(src, end, deltaLevel.item);\r\n\t\tsrc = DeltaImportObjects(src, end, deltaLevel.object);\r\n\t\tsrc = DeltaImportMonster(src, end, deltaLevel.monster);\r\n\t\tsrc = DeltaImportSpawnedMonsters(src, end, deltaLevel.spawnedMonsters);\r\n\t} else {\r\n\t\tLog(\"Received invalid deltas, dropping player {}\", pnum);\r\n\t\tSNetDropPlayer(pnum, leaveinfo_t::LEAVE_DROP);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (src == nullptr) {\r\n\t\tLog(\"Received invalid deltas, dropping player {}\", pnum);\r\n\t\tSNetDropPlayer(pnum, leaveinfo_t::LEAVE_DROP);\r\n\t\treturn;\r\n\t}\r\n\r\n\tsgbDeltaChunks++;\r\n}\r\n\r\nvoid DeltaLoadSpawnedMonsters(const DLevel &deltaLevel)\r\n{\r\n\tfor (const auto &deltaSpawnedMonster : deltaLevel.spawnedMonsters) {\r\n\t\tconst auto &monsterData = deltaSpawnedMonster.second;\r\n\t\tLoadDeltaSpawnedMonster(deltaSpawnedMonster.second.typeIndex, deltaSpawnedMonster.first, monsterData.seed, monsterData.golemOwnerPlayerId, monsterData.golemSpellLevel);\r\n\t\tassert(deltaLevel.monster[deltaSpawnedMonster.first].position.x != 0xFF);\r\n\t}\r\n}\r\n\r\nvoid DeltaLoadEnemies(const DLevel &deltaLevel)\r\n{\r\n\tfor (size_t i = 0; i < MaxMonsters; i++) {\r\n\t\tconst DMonsterStr &deltaMonster = deltaLevel.monster[i];\r\n\t\tif (!IsMonsterDeltaValid(deltaMonster))\r\n\t\t\tcontinue;\r\n\t\tif (deltaMonster.hitPoints == 0)\r\n\t\t\tcontinue;\r\n\t\tMonster &monster = Monsters[i];\r\n\t\tif (IsEnemyValid(i, deltaMonster.menemy))\r\n\t\t\tdecode_enemy(monster, deltaMonster.menemy);\r\n\t\tif (monster.position.tile != Point { 0, 0 } && monster.position.tile != GolemHoldingCell)\r\n\t\t\tmonster.occupyTile(monster.position.tile, false);\r\n\t\tif (monster.type().type == MT_GOLEM) {\r\n\t\t\tGolumAi(monster);\r\n\t\t\tmonster.flags |= (MFLAG_TARGETS_MONSTER | MFLAG_GOLEM);\r\n\t\t} else {\r\n\t\t\tM_StartStand(monster, monster.direction);\r\n\t\t}\r\n\t\tmonster.activeForTicks = deltaMonster.mactive;\r\n\t}\r\n}\r\n\r\nvoid DeltaLoadMonsters(const DLevel &deltaLevel)\r\n{\r\n\tfor (size_t i = 0; i < MaxMonsters; i++) {\r\n\t\tconst DMonsterStr &deltaMonster = deltaLevel.monster[i];\r\n\t\tif (!IsMonsterDeltaValid(deltaMonster))\r\n\t\t\tcontinue;\r\n\r\n\t\tMonster &monster = Monsters[i];\r\n\t\tM_ClearSquares(monster);\r\n\t\t{\r\n\t\t\tconst WorldTilePosition position = deltaMonster.position;\r\n\t\t\tmonster.position.tile = position;\r\n\t\t\tmonster.position.old = position;\r\n\t\t\tmonster.position.future = position;\r\n\t\t\tif (monster.lightId != NO_LIGHT)\r\n\t\t\t\tChangeLightXY(monster.lightId, position);\r\n\t\t}\r\n\r\n\t\tmonster.hitPoints = Swap32LE(deltaMonster.hitPoints);\r\n\t\tmonster.whoHit = deltaMonster.mWhoHit;\r\n\t\tif (deltaMonster.hitPoints != 0)\r\n\t\t\tcontinue;\r\n\r\n\t\tM_ClearSquares(monster);\r\n\t\tif (monster.ai != MonsterAIID::Diablo) {\r\n\t\t\tif (monster.isUnique()) {\r\n\t\t\t\tAddCorpse(monster.position.tile, monster.corpseId, monster.direction);\r\n\t\t\t} else {\r\n\t\t\t\tAddCorpse(monster.position.tile, monster.type().corpseId, monster.direction);\r\n\t\t\t}\r\n\t\t}\r\n\t\tmonster.isInvalid = true;\r\n\t\tM_UpdateRelations(monster);\r\n\t}\r\n\r\n\t// Calling this here ensures that monster hitpoints\r\n\t// are synced before attempting to validate enemy IDs\r\n\tDeltaLoadEnemies(deltaLevel);\r\n}\r\n\r\nvoid DeltaLoadObjects(DLevel &deltaLevel)\r\n{\r\n\tfor (auto it = deltaLevel.object.begin(); it != deltaLevel.object.end();) {\r\n\t\tObject *object = FindObjectAtPosition(it->first);\r\n\t\tif (object == nullptr) {\r\n\t\t\tit = deltaLevel.object.erase(it);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tswitch (it->second.bCmd) {\r\n\t\tcase CMD_OPENDOOR:\r\n\t\tcase CMD_OPERATEOBJ:\r\n\t\t\tDeltaSyncOpObject(*object);\r\n\t\t\tit++;\r\n\t\t\tbreak;\r\n\t\tcase CMD_CLOSEDOOR:\r\n\t\t\tDeltaSyncCloseObj(*object);\r\n\t\t\tit++;\r\n\t\t\tbreak;\r\n\t\tcase CMD_BREAKOBJ:\r\n\t\t\tDeltaSyncBreakObj(*object);\r\n\t\t\tit++;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tit = deltaLevel.object.erase(it); // discard invalid commands\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < ActiveObjectCount; i++) {\r\n\t\tObject &object = Objects[ActiveObjects[i]];\r\n\t\tif (object.IsTrap()) {\r\n\t\t\tUpdateTrapState(object);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DeltaLoadItems(const DLevel &deltaLevel)\r\n{\r\n\tfor (const TCmdPItem &deltaItem : deltaLevel.item) {\r\n\t\tif (deltaItem.bCmd == CMD_INVALID)\r\n\t\t\tcontinue;\r\n\r\n\t\tif (deltaItem.bCmd == TCmdPItem::PickedUpItem) {\r\n\t\t\tconst int activeItemIndex = FindGetItem(\r\n\t\t\t    Swap32LE(deltaItem.def.dwSeed),\r\n\t\t\t    static_cast<_item_indexes>(Swap16LE(deltaItem.def.wIndx)),\r\n\t\t\t    Swap16LE(deltaItem.def.wCI));\r\n\t\t\tif (activeItemIndex != -1) {\r\n\t\t\t\tconst auto &position = Items[ActiveItems[activeItemIndex]].position;\r\n\t\t\t\tif (dItem[position.x][position.y] == ActiveItems[activeItemIndex] + 1)\r\n\t\t\t\t\tdItem[position.x][position.y] = 0;\r\n\t\t\t\tDeleteItem(activeItemIndex);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (deltaItem.bCmd == TCmdPItem::DroppedItem) {\r\n\t\t\tconst int ii = AllocateItem();\r\n\t\t\tauto &item = Items[ii];\r\n\t\t\tRecreateItem(*MyPlayer, deltaItem, item);\r\n\r\n\t\t\tconst int x = deltaItem.x;\r\n\t\t\tconst int y = deltaItem.y;\r\n\t\t\titem.position = GetItemPosition({ x, y });\r\n\t\t\tdItem[item.position.x][item.position.y] = static_cast<int8_t>(ii + 1);\r\n\t\t\tRespawnItem(Items[ii], false);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nsize_t OnLevelData(const TCmdPlrInfoHdr &message, size_t maxCmdSize, const Player &player)\r\n{\r\n\tconst uint16_t wBytes = Swap16LE(message.wBytes);\r\n\tconst uint16_t wOffset = Swap16LE(message.wOffset);\r\n\r\n\tif (!ValidateCmdSize(wBytes + sizeof(message), maxCmdSize, player.getId()))\r\n\t\treturn maxCmdSize;\r\n\r\n\tif (gbDeltaSender != player.getId()) {\r\n\t\tif (message.bCmd != CMD_DLEVEL_END && (message.bCmd != CMD_DLEVEL || wOffset != 0)) {\r\n\t\t\treturn wBytes + sizeof(message);\r\n\t\t}\r\n\r\n\t\tgbDeltaSender = player.getId();\r\n\t\tsgbRecvCmd = CMD_DLEVEL_END;\r\n\t}\r\n\r\n\tif (sgbRecvCmd == CMD_DLEVEL_END) {\r\n\t\tif (message.bCmd == CMD_DLEVEL_END) {\r\n\t\t\tsgbDeltaChunks = MaxChunks - 1;\r\n\t\t\treturn wBytes + sizeof(message);\r\n\t\t}\r\n\t\tif (message.bCmd != CMD_DLEVEL || wOffset != 0) {\r\n\t\t\treturn wBytes + sizeof(message);\r\n\t\t}\r\n\r\n\t\tsgdwRecvOffset = 0;\r\n\t\tsgbRecvCmd = message.bCmd;\r\n\t} else if (sgbRecvCmd != message.bCmd || wOffset == 0) {\r\n\t\tDeltaImportData(sgbRecvCmd, sgdwRecvOffset, player.getId());\r\n\t\tif (message.bCmd == CMD_DLEVEL_END) {\r\n\t\t\tsgbDeltaChunks = MaxChunks - 1;\r\n\t\t\tsgbRecvCmd = CMD_DLEVEL_END;\r\n\t\t\treturn wBytes + sizeof(message);\r\n\t\t}\r\n\t\tsgdwRecvOffset = 0;\r\n\t\tsgbRecvCmd = message.bCmd;\r\n\t}\r\n\r\n\tif (sgdwRecvOffset + wBytes > sizeof(sgRecvBuf)) {\r\n\t\tLog(\"Received too many deltas, dropping player {}\", player.getId());\r\n\t\tSNetDropPlayer(player.getId(), leaveinfo_t::LEAVE_DROP);\r\n\t\treturn wBytes + sizeof(message);\r\n\t}\r\n\r\n\tassert(wOffset == sgdwRecvOffset);\r\n\tmemcpy(&sgRecvBuf[sgdwRecvOffset], &message + 1, wBytes);\r\n\tsgdwRecvOffset += wBytes;\r\n\treturn wBytes + sizeof(message);\r\n}\r\n\r\nvoid DeltaLeaveSync(uint8_t bLevel)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tDungeonSeeds[0] = GenerateSeed();\r\n\t\treturn;\r\n\t}\r\n\r\n\tDLevel &deltaLevel = GetDeltaLevel(bLevel);\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst unsigned ma = ActiveMonsters[i];\r\n\t\tMonster &monster = Monsters[ma];\r\n\t\tif (monster.hitPoints == 0)\r\n\t\t\tcontinue;\r\n\t\tDMonsterStr &delta = deltaLevel.monster[ma];\r\n\t\tdelta.position = monster.position.tile;\r\n\t\tdelta.menemy = encode_enemy(monster);\r\n\t\tdelta.hitPoints = monster.hitPoints;\r\n\t\tdelta.mactive = monster.activeForTicks;\r\n\t\tdelta.mWhoHit = monster.whoHit;\r\n\t}\r\n\tLocalLevels.insert_or_assign(bLevel, AutomapView);\r\n}\r\n\r\nvoid DeltaSyncObject(WorldTilePosition position, _cmd_id bCmd, const Player &player)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tauto &objectDeltas = GetDeltaLevel(player).object;\r\n\tobjectDeltas[position].bCmd = bCmd;\r\n}\r\n\r\nbool DeltaGetItem(const TCmdGItem &message, uint8_t bLevel)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn true;\r\n\r\n\tDLevel &deltaLevel = GetDeltaLevel(bLevel);\r\n\r\n\tfor (TCmdPItem &item : deltaLevel.item) {\r\n\t\tif (item.bCmd == CMD_INVALID || item.def.wIndx != message.def.wIndx\r\n\t\t    || item.def.wCI != message.def.wCI || item.def.dwSeed != message.def.dwSeed) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (item.bCmd == TCmdPItem::PickedUpItem) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (item.bCmd == TCmdPItem::FloorItem) {\r\n\t\t\titem.bCmd = TCmdPItem::PickedUpItem;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (item.bCmd == TCmdPItem::DroppedItem) {\r\n\t\t\titem.bCmd = CMD_INVALID;\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n#ifdef _DEBUG\r\n\t\tapp_fatal(\"delta:1\");\r\n#endif\r\n\t}\r\n\r\n\tif ((message.def.wCI & CF_PREGEN) == 0)\r\n\t\treturn false;\r\n\r\n\tfor (TCmdPItem &delta : deltaLevel.item) {\r\n\t\tif (delta.bCmd == CMD_INVALID) {\r\n\t\t\tdelta.bCmd = TCmdPItem::PickedUpItem;\r\n\t\t\tdelta.x = message.x;\r\n\t\t\tdelta.y = message.y;\r\n\t\t\tdelta.def.wIndx = message.def.wIndx;\r\n\t\t\tdelta.def.wCI = message.def.wCI;\r\n\t\t\tdelta.def.dwSeed = message.def.dwSeed;\r\n\t\t\tif (message.def.wIndx == IDI_EAR) {\r\n\t\t\t\tdelta.ear.bCursval = message.ear.bCursval;\r\n\t\t\t\tCopyUtf8(delta.ear.heroname, message.ear.heroname, sizeof(delta.ear.heroname));\r\n\t\t\t} else {\r\n\t\t\t\tdelta.item.bId = message.item.bId;\r\n\t\t\t\tdelta.item.bDur = message.item.bDur;\r\n\t\t\t\tdelta.item.bMDur = message.item.bMDur;\r\n\t\t\t\tdelta.item.bCh = message.item.bCh;\r\n\t\t\t\tdelta.item.bMCh = message.item.bMCh;\r\n\t\t\t\tdelta.item.wValue = message.item.wValue;\r\n\t\t\t\tdelta.item.dwBuff = message.item.dwBuff;\r\n\t\t\t\tdelta.item.wToHit = message.item.wToHit;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid DeltaPutItem(const TCmdPItem &message, Point position, const Player &player)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tDLevel &deltaLevel = GetDeltaLevel(player);\r\n\r\n\tfor (const TCmdPItem &item : deltaLevel.item) {\r\n\t\tif (item.bCmd != TCmdPItem::PickedUpItem\r\n\t\t    && item.bCmd != CMD_INVALID\r\n\t\t    && item.def.wIndx == message.def.wIndx\r\n\t\t    && item.def.wCI == message.def.wCI\r\n\t\t    && item.def.dwSeed == message.def.dwSeed) {\r\n\t\t\tif (item.bCmd != TCmdPItem::DroppedItem) {\r\n\t\t\t\tLog(\"Suspicious floor item duplication, dropping player {}\", player.getId());\r\n\t\t\t\tSNetDropPlayer(player.getId(), leaveinfo_t::LEAVE_DROP);\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (TCmdPItem &item : deltaLevel.item) {\r\n\t\tif (item.bCmd == CMD_INVALID) {\r\n\t\t\tmemcpy(&item, &message, sizeof(TCmdPItem));\r\n\t\t\titem.bCmd = TCmdPItem::DroppedItem;\r\n\t\t\titem.x = position.x;\r\n\t\t\titem.y = position.y;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DeltaOpenPortal(size_t pnum, Point position, uint8_t bLevel, dungeon_type bLType, bool bSetLvl)\r\n{\r\n\tsgJunk.portal[pnum].x = position.x;\r\n\tsgJunk.portal[pnum].y = position.y;\r\n\tsgJunk.portal[pnum].level = bLevel;\r\n\tsgJunk.portal[pnum].ltype = bLType;\r\n\tsgJunk.portal[pnum].setlvl = bSetLvl ? 1 : 0;\r\n}\r\n\r\nvoid NetSendCmdGItem2(bool usonly, _cmd_id bCmd, uint8_t mast, uint8_t pnum, const TCmdGItem &item)\r\n{\r\n\tTCmdGItem cmd;\r\n\r\n\tmemcpy(&cmd, &item, sizeof(cmd));\r\n\tcmd.bPnum = pnum;\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.bMaster = mast;\r\n\r\n\tif (!usonly) {\r\n\t\tcmd.dwTime = 0;\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto ticks = static_cast<int32_t>(SDL_GetTicks());\r\n\tif (cmd.dwTime == 0) {\r\n\t\tcmd.dwTime = Swap32LE(ticks);\r\n\t} else if (ticks - Swap32LE(cmd.dwTime) > 5000) {\r\n\t\treturn;\r\n\t}\r\n\r\n\ttmsg_add(reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nbool NetSendCmdReq2(_cmd_id bCmd, const Player &player, uint8_t pnum, const TCmdGItem &item)\r\n{\r\n\tTCmdGItem cmd;\r\n\r\n\tmemcpy(&cmd, &item, sizeof(cmd));\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.bPnum = pnum;\r\n\tcmd.bMaster = player.getId();\r\n\r\n\tauto ticks = static_cast<int32_t>(SDL_GetTicks());\r\n\tif (cmd.dwTime == 0)\r\n\t\tcmd.dwTime = Swap32LE(ticks);\r\n\telse if (ticks - Swap32LE(cmd.dwTime) > 5000)\r\n\t\treturn false;\r\n\r\n\ttmsg_add(reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid NetSendCmdExtra(const TCmdGItem &item)\r\n{\r\n\tTCmdGItem cmd;\r\n\r\n\tmemcpy(&cmd, &item, sizeof(cmd));\r\n\tcmd.dwTime = 0;\r\n\tcmd.bCmd = CMD_ITEMEXTRA;\r\n\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nsize_t OnWalk(const TCmdLoc &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position)) {\r\n\t\tClrPlrPath(player);\r\n\t\tMakePlrPath(player, position, true);\r\n\t\tplayer.destAction = ACTION_NONE;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnAddStrength(const TCmdParam1 &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\telse if (message.wParam1 <= 256)\r\n\t\tModifyPlrStr(player, Swap16LE(message.wParam1));\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnAddMagic(const TCmdParam1 &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\telse if (message.wParam1 <= 256)\r\n\t\tModifyPlrMag(player, Swap16LE(message.wParam1));\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnAddDexterity(const TCmdParam1 &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\telse if (message.wParam1 <= 256)\r\n\t\tModifyPlrDex(player, Swap16LE(message.wParam1));\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnAddVitality(const TCmdParam1 &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\telse if (message.wParam1 <= 256)\r\n\t\tModifyPlrVit(player, Swap16LE(message.wParam1));\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnGotoGetItem(const TCmdLocParam1 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && Swap16LE(message.wParam1) < MAXITEMS + 1) {\r\n\t\tMakePlrPath(player, position, false);\r\n\t\tplayer.destAction = ACTION_PICKUPITEM;\r\n\t\tplayer.destParam1 = Swap16LE(message.wParam1);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nbool IsGItemValid(const TCmdGItem &message)\r\n{\r\n\tif (message.bMaster >= Players.size())\r\n\t\treturn false;\r\n\tif (message.bPnum >= Players.size())\r\n\t\treturn false;\r\n\tif (message.bCursitem >= MAXITEMS + 1)\r\n\t\treturn false;\r\n\tif (!IsValidLevelForMultiplayer(message.bLevel))\r\n\t\treturn false;\r\n\r\n\tif (!InDungeonBounds({ message.x, message.y }))\r\n\t\treturn false;\r\n\r\n\treturn IsItemAvailable(static_cast<_item_indexes>(Swap16LE(message.def.wIndx)));\r\n}\r\n\r\nbool IsPItemValid(const TCmdPItem &message, const Player &player)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn true;\r\n\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn false;\r\n\r\n\tauto idx = static_cast<_item_indexes>(Swap16LE(message.def.wIndx));\r\n\r\n\tif (idx != IDI_EAR) {\r\n\t\tconst uint16_t creationFlags = Swap16LE(message.item.wCI);\r\n\t\tconst uint32_t dwBuff = Swap16LE(message.item.dwBuff);\r\n\r\n\t\tif (idx != IDI_GOLD)\r\n\t\t\tValidateField(creationFlags, IsCreationFlagComboValid(creationFlags));\r\n\t\tif ((creationFlags & CF_TOWN) != 0)\r\n\t\t\tValidateField(creationFlags, IsTownItemValid(creationFlags, player));\r\n\t\telse if ((creationFlags & CF_USEFUL) == CF_UPER15)\r\n\t\t\tValidateFields(creationFlags, dwBuff, IsUniqueMonsterItemValid(creationFlags, dwBuff));\r\n\t\telse if ((dwBuff & CF_HELLFIRE) != 0 && AllItemsList[idx].iMiscId == IMISC_BOOK)\r\n\t\t\treturn RecreateHellfireSpellBook(player, message.item);\r\n\t\telse\r\n\t\t\tValidateFields(creationFlags, dwBuff, IsDungeonItemValid(creationFlags, dwBuff));\r\n\t}\r\n\r\n\treturn IsItemAvailable(idx);\r\n}\r\n\r\nvoid PrepareItemForNetwork(const Item &item, TCmdGItem &message)\r\n{\r\n\tmessage.def.wIndx = static_cast<_item_indexes>(Swap16LE(item.IDidx));\r\n\tmessage.def.wCI = Swap16LE(item._iCreateInfo);\r\n\tmessage.def.dwSeed = Swap32LE(item._iSeed);\r\n\r\n\tif (item.IDidx == IDI_EAR)\r\n\t\tPrepareEarForNetwork(item, message.ear);\r\n\telse\r\n\t\tPrepareItemForNetwork(item, message.item);\r\n}\r\n\r\nvoid PrepareItemForNetwork(const Item &item, TCmdPItem &message)\r\n{\r\n\tmessage.def.wIndx = static_cast<_item_indexes>(Swap16LE(item.IDidx));\r\n\tmessage.def.wCI = Swap16LE(item._iCreateInfo);\r\n\tmessage.def.dwSeed = Swap32LE(item._iSeed);\r\n\r\n\tif (item.IDidx == IDI_EAR)\r\n\t\tPrepareEarForNetwork(item, message.ear);\r\n\telse\r\n\t\tPrepareItemForNetwork(item, message.item);\r\n}\r\n\r\nvoid PrepareItemForNetwork(const Item &item, TCmdChItem &message)\r\n{\r\n\tmessage.def.wIndx = static_cast<_item_indexes>(Swap16LE(item.IDidx));\r\n\tmessage.def.wCI = Swap16LE(item._iCreateInfo);\r\n\tmessage.def.dwSeed = Swap32LE(item._iSeed);\r\n\r\n\tif (item.IDidx == IDI_EAR)\r\n\t\tPrepareEarForNetwork(item, message.ear);\r\n\telse\r\n\t\tPrepareItemForNetwork(item, message.item);\r\n}\r\n\r\nvoid RecreateItem(const Player &player, const TCmdPItem &message, Item &item)\r\n{\r\n\tif (message.def.wIndx == Swap16LE(IDI_EAR))\r\n\t\tRecreateEar(item, Swap16LE(message.ear.wCI), Swap32LE(message.ear.dwSeed), message.ear.bCursval, message.ear.heroname);\r\n\telse\r\n\t\tRecreateItem(player, message.item, item);\r\n}\r\n\r\nvoid RecreateItem(const Player &player, const TCmdChItem &message, Item &item)\r\n{\r\n\tif (message.def.wIndx == Swap16LE(IDI_EAR))\r\n\t\tRecreateEar(item, Swap16LE(message.ear.wCI), Swap32LE(message.ear.dwSeed), message.ear.bCursval, message.ear.heroname);\r\n\telse\r\n\t\tRecreateItem(player, message.item, item);\r\n}\r\n\r\nint SyncDropItem(Point position, const TItem &item)\r\n{\r\n\treturn SyncDropItem(\r\n\t    position,\r\n\t    static_cast<_item_indexes>(Swap16LE(item.wIndx)),\r\n\t    Swap16LE(item.wCI),\r\n\t    Swap32LE(item.dwSeed),\r\n\t    item.bId,\r\n\t    item.bDur,\r\n\t    item.bMDur,\r\n\t    item.bCh,\r\n\t    item.bMCh,\r\n\t    Swap16LE(item.wValue),\r\n\t    Swap32LE(item.dwBuff),\r\n\t    Swap16LE(item.wToHit),\r\n\t    Swap16LE(item.wMaxDam));\r\n}\r\n\r\nint SyncDropEar(Point position, const TEar &ear)\r\n{\r\n\treturn SyncDropEar(\r\n\t    position,\r\n\t    Swap16LE(ear.wCI),\r\n\t    Swap32LE(ear.dwSeed),\r\n\t    ear.bCursval,\r\n\t    ear.heroname);\r\n}\r\n\r\nint SyncDropItem(const TCmdGItem &message)\r\n{\r\n\tconst Point position = GetItemPosition({ message.x, message.y });\r\n\tif (message.def.wIndx == IDI_EAR) {\r\n\t\treturn SyncDropEar(\r\n\t\t    position,\r\n\t\t    message.ear);\r\n\t}\r\n\r\n\treturn SyncDropItem(\r\n\t    position,\r\n\t    message.item);\r\n}\r\n\r\nint SyncDropItem(const TCmdPItem &message)\r\n{\r\n\tconst Point position = GetItemPosition({ message.x, message.y });\r\n\tif (message.def.wIndx == IDI_EAR) {\r\n\t\treturn SyncDropEar(\r\n\t\t    position,\r\n\t\t    message.ear);\r\n\t}\r\n\r\n\treturn SyncDropItem(\r\n\t    position,\r\n\t    message.item);\r\n}\r\n\r\nsize_t OnRequestGetItem(const TCmdGItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1 || !player.isLevelOwnedByLocalClient() || !IsGItemValid(message))\r\n\t\treturn sizeof(message);\r\n\r\n\tconst Point position { message.x, message.y };\r\n\tconst uint32_t dwSeed = Swap32LE(message.def.dwSeed);\r\n\tconst uint16_t wCI = Swap16LE(message.def.wCI);\r\n\tconst auto wIndx = static_cast<_item_indexes>(Swap16LE(message.def.wIndx));\r\n\tif (!GetItemRecord(dwSeed, wCI, wIndx))\r\n\t\treturn sizeof(message);\r\n\r\n\tint ii = -1;\r\n\tif (InDungeonBounds(position)) {\r\n\t\tii = std::abs(dItem[position.x][position.y]) - 1;\r\n\t\tif (ii >= 0 && !Items[ii].keyAttributesMatch(dwSeed, wIndx, wCI)) {\r\n\t\t\tii = -1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (ii == -1) {\r\n\t\t// No item at the target position or the key attributes don't match, so try find a matching item.\r\n\t\tconst int activeItemIndex = FindGetItem(dwSeed, wIndx, wCI);\r\n\t\tif (activeItemIndex != -1) {\r\n\t\t\tii = ActiveItems[activeItemIndex];\r\n\t\t}\r\n\t}\r\n\r\n\tif (ii != -1) {\r\n\t\tNetSendCmdGItem2(false, CMD_GETITEM, MyPlayerId, message.bPnum, message);\r\n\t\tif (message.bPnum != MyPlayerId)\r\n\t\t\tSyncGetItem(position, dwSeed, wIndx, wCI);\r\n\t\telse\r\n\t\t\tInvGetItem(*MyPlayer, ii);\r\n\t\tSetItemRecord(dwSeed, wCI, wIndx);\r\n\t} else if (!NetSendCmdReq2(CMD_REQUESTGITEM, *MyPlayer, message.bPnum, message)) {\r\n\t\tNetSendCmdExtra(message);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnGetItem(const TCmdGItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tif (!IsGItemValid(message))\r\n\t\treturn sizeof(message);\r\n\r\n\tconst Point position { message.x, message.y };\r\n\tconst uint32_t dwSeed = Swap32LE(message.def.dwSeed);\r\n\tconst uint16_t wCI = Swap16LE(message.def.wCI);\r\n\tconst auto wIndx = static_cast<_item_indexes>(Swap16LE(message.def.wIndx));\r\n\tif (!DeltaGetItem(message, message.bLevel)) {\r\n\t\tNetSendCmdGItem2(true, CMD_GETITEM, message.bMaster, message.bPnum, message);\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tconst bool isOnActiveLevel = GetLevelForMultiplayer(*MyPlayer) == message.bLevel;\r\n\tif ((!isOnActiveLevel && message.bPnum != MyPlayerId) || message.bMaster == MyPlayerId)\r\n\t\treturn sizeof(message);\r\n\r\n\tif (message.bPnum != MyPlayerId) {\r\n\t\tSyncGetItem(position, dwSeed, wIndx, wCI);\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tif (!isOnActiveLevel) {\r\n\t\tconst int ii = SyncDropItem(message);\r\n\t\tif (ii != -1)\r\n\t\t\tInvGetItem(*MyPlayer, ii);\r\n\t} else {\r\n\t\tconst int activeItemIndex = FindGetItem(dwSeed, wIndx, wCI);\r\n\t\tInvGetItem(*MyPlayer, ActiveItems[activeItemIndex]);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnGotoAutoGetItem(const TCmdLocParam1 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tconst uint16_t itemIdx = Swap16LE(message.wParam1);\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && itemIdx < MAXITEMS + 1) {\r\n\t\tMakePlrPath(player, position, false);\r\n\t\tplayer.destAction = ACTION_PICKUPAITEM;\r\n\t\tplayer.destParam1 = itemIdx;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnRequestAutoGetItem(const TCmdGItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs != 1 && player.isLevelOwnedByLocalClient() && IsGItemValid(message)) {\r\n\t\tconst Point position { message.x, message.y };\r\n\t\tconst uint32_t dwSeed = Swap32LE(message.def.dwSeed);\r\n\t\tconst uint16_t wCI = Swap16LE(message.def.wCI);\r\n\t\tconst auto wIndx = static_cast<_item_indexes>(Swap16LE(message.def.wIndx));\r\n\t\tif (GetItemRecord(dwSeed, wCI, wIndx)) {\r\n\t\t\tif (FindGetItem(dwSeed, wIndx, wCI) != -1) {\r\n\t\t\t\tNetSendCmdGItem2(false, CMD_AGETITEM, MyPlayerId, message.bPnum, message);\r\n\t\t\t\tif (message.bPnum != MyPlayerId)\r\n\t\t\t\t\tSyncGetItem(position, dwSeed, wIndx, wCI);\r\n\t\t\t\telse\r\n\t\t\t\t\tAutoGetItem(*MyPlayer, &Items[message.bCursitem], message.bCursitem);\r\n\t\t\t\tSetItemRecord(dwSeed, wCI, wIndx);\r\n\t\t\t} else if (!NetSendCmdReq2(CMD_REQUESTAGITEM, *MyPlayer, message.bPnum, message)) {\r\n\t\t\t\tNetSendCmdExtra(message);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnAutoGetItem(const TCmdGItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tif (!IsGItemValid(message))\r\n\t\treturn sizeof(message);\r\n\r\n\tconst Point position { message.x, message.y };\r\n\tif (!DeltaGetItem(message, message.bLevel)) {\r\n\t\tNetSendCmdGItem2(true, CMD_AGETITEM, message.bMaster, message.bPnum, message);\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tconst bool isOnActiveLevel = GetLevelForMultiplayer(*MyPlayer) == message.bLevel;\r\n\tif ((!isOnActiveLevel && message.bPnum != MyPlayerId) || message.bMaster == MyPlayerId)\r\n\t\treturn sizeof(message);\r\n\r\n\tif (message.bPnum != MyPlayerId) {\r\n\t\tSyncGetItem(position, Swap32LE(message.def.dwSeed), static_cast<_item_indexes>(Swap16LE(message.def.wIndx)), Swap16LE(message.def.wCI));\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tif (!isOnActiveLevel) {\r\n\t\tconst int ii = SyncDropItem(message);\r\n\t\tif (ii != -1)\r\n\t\t\tAutoGetItem(*MyPlayer, &Items[ii], ii);\r\n\t} else {\r\n\t\tAutoGetItem(*MyPlayer, &Items[message.bCursitem], message.bCursitem);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnItemExtra(const TCmdGItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (IsGItemValid(message)) {\r\n\t\tDeltaGetItem(message, message.bLevel);\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tconst Point position { message.x, message.y };\r\n\t\t\tSyncGetItem(position, Swap32LE(message.def.dwSeed), static_cast<_item_indexes>(Swap16LE(message.def.wIndx)), Swap16LE(message.def.wCI));\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnPutItem(const TCmdPItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (IsPItemValid(message, player)) {\r\n\t\tconst Point position { message.x, message.y };\r\n\t\tconst bool isSelf = &player == MyPlayer;\r\n\t\tconst int32_t dwSeed = Swap32LE(message.def.dwSeed);\r\n\t\tconst uint16_t wCI = Swap16LE(message.def.wCI);\r\n\t\tconst auto wIndx = static_cast<_item_indexes>(Swap16LE(message.def.wIndx));\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tint ii;\r\n\t\t\tif (isSelf) {\r\n\t\t\t\tstd::optional<Point> itemTile = FindAdjacentPositionForItem(player.position.tile, GetDirection(player.position.tile, position));\r\n\t\t\t\tif (itemTile)\r\n\t\t\t\t\tii = PlaceItemInWorld(std::move(ItemLimbo), *itemTile);\r\n\t\t\t\telse\r\n\t\t\t\t\tii = -1;\r\n\t\t\t} else\r\n\t\t\t\tii = SyncDropItem(message);\r\n\t\t\tif (ii != -1) {\r\n\t\t\t\tPutItemRecord(dwSeed, wCI, wIndx);\r\n\t\t\t\tDeltaPutItem(message, Items[ii].position, player);\r\n\t\t\t\tif (isSelf)\r\n\t\t\t\t\tpfile_update(true);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tPutItemRecord(dwSeed, wCI, wIndx);\r\n\t\t\tDeltaPutItem(message, position, player);\r\n\t\t\tif (isSelf)\r\n\t\t\t\tpfile_update(true);\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSyncPutItem(const TCmdPItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\telse if (IsPItemValid(message, player)) {\r\n\t\tconst int32_t dwSeed = Swap32LE(message.def.dwSeed);\r\n\t\tconst uint16_t wCI = Swap16LE(message.def.wCI);\r\n\t\tconst auto wIndx = static_cast<_item_indexes>(Swap16LE(message.def.wIndx));\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tconst int ii = SyncDropItem(message);\r\n\t\t\tif (ii != -1) {\r\n\t\t\t\tPutItemRecord(dwSeed, wCI, wIndx);\r\n\t\t\t\tDeltaPutItem(message, Items[ii].position, player);\r\n\t\t\t\tif (&player == MyPlayer)\r\n\t\t\t\t\tpfile_update(true);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tPutItemRecord(dwSeed, wCI, wIndx);\r\n\t\t\tDeltaPutItem(message, { message.x, message.y }, player);\r\n\t\t\tif (&player == MyPlayer)\r\n\t\t\t\tpfile_update(true);\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnStandingAttackTile(const TCmdLoc &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && leveltype != DTYPE_TOWN && InDungeonBounds(position)) {\r\n\t\tClrPlrPath(player);\r\n\t\tplayer.destAction = ACTION_ATTACK;\r\n\t\tplayer.destParam1 = position.x;\r\n\t\tplayer.destParam2 = position.y;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnRangedAttackTile(const TCmdLoc &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && leveltype != DTYPE_TOWN && InDungeonBounds(position)) {\r\n\t\tClrPlrPath(player);\r\n\t\tplayer.destAction = ACTION_RATTACK;\r\n\t\tplayer.destParam1 = position.x;\r\n\t\tplayer.destParam2 = position.y;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nbool InitNewSpell(Player &player, uint16_t wParamSpellID, uint16_t wParamSpellType, uint16_t wParamSpellFrom)\r\n{\r\n\twParamSpellID = Swap16LE(wParamSpellID);\r\n\twParamSpellType = Swap16LE(wParamSpellType);\r\n\twParamSpellFrom = Swap16LE(wParamSpellFrom);\r\n\r\n\tif (wParamSpellID > static_cast<int8_t>(SpellID::LAST))\r\n\t\treturn false;\r\n\tauto spellID = static_cast<SpellID>(wParamSpellID);\r\n\tif (!IsValidSpell(spellID)) {\r\n\t\tLogError(_(\"{:s} has cast an invalid spell.\"), player._pName);\r\n\t\treturn false;\r\n\t}\r\n\tif (leveltype == DTYPE_TOWN && !GetSpellData(spellID).isAllowedInTown()) {\r\n\t\tLogError(_(\"{:s} has cast an illegal spell.\"), player._pName);\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (wParamSpellType > static_cast<uint8_t>(SpellType::Invalid))\r\n\t\treturn false;\r\n\r\n\tif (wParamSpellFrom > INVITEM_BELT_LAST)\r\n\t\treturn false;\r\n\tauto spellFrom = static_cast<int8_t>(wParamSpellFrom);\r\n\tif (!IsValidSpellFrom(spellFrom))\r\n\t\treturn false;\r\n\r\n\tplayer.queuedSpell.spellId = spellID;\r\n\tplayer.queuedSpell.spellType = static_cast<SpellType>(wParamSpellType);\r\n\tplayer.queuedSpell.spellFrom = spellFrom;\r\n\r\n\treturn true;\r\n}\r\n\r\nsize_t OnSpellWall(const TCmdLocParam4 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (gbBufferMsgs == 1)\r\n\t\treturn sizeof(message);\r\n\tif (!player.isOnActiveLevel())\r\n\t\treturn sizeof(message);\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn sizeof(message);\r\n\tconst int16_t wParamDirection = Swap16LE(message.wParam3);\r\n\tif (wParamDirection > static_cast<uint16_t>(Direction::SouthEast))\r\n\t\treturn sizeof(message);\r\n\r\n\tif (!InitNewSpell(player, message.wParam1, message.wParam2, message.wParam4))\r\n\t\treturn sizeof(message);\r\n\r\n\tClrPlrPath(player);\r\n\tplayer.destAction = ACTION_SPELLWALL;\r\n\tplayer.destParam1 = position.x;\r\n\tplayer.destParam2 = position.y;\r\n\tplayer.destParam3 = wParamDirection;\r\n\tplayer.destParam4 = player.GetSpellLevel(player.queuedSpell.spellId);\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSpellTile(const TCmdLocParam3 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (gbBufferMsgs == 1)\r\n\t\treturn sizeof(message);\r\n\tif (!player.isOnActiveLevel())\r\n\t\treturn sizeof(message);\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn sizeof(message);\r\n\r\n\tif (!InitNewSpell(player, message.wParam1, message.wParam2, message.wParam3))\r\n\t\treturn sizeof(message);\r\n\r\n\tClrPlrPath(player);\r\n\tplayer.destAction = ACTION_SPELL;\r\n\tplayer.destParam1 = position.x;\r\n\tplayer.destParam2 = position.y;\r\n\tplayer.destParam3 = player.GetSpellLevel(player.queuedSpell.spellId);\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnObjectTileAction(const TCmdLoc &message, Player &player, action_id action, bool pathToObject = true)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\tconst Object *object = FindObjectAtPosition(position);\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && object != nullptr) {\r\n\t\tif (pathToObject)\r\n\t\t\tMakePlrPath(player, position, !object->_oSolidFlag && !object->_oDoorFlag);\r\n\r\n\t\tplayer.destAction = action;\r\n\t\tplayer.destParam1 = static_cast<int>(object->GetId());\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnObjectTileAction(const TCmdLoc &message, Player &player)\r\n{\r\n\tswitch (message.bCmd) {\r\n\tcase CMD_OPOBJXY:\r\n\t\treturn OnObjectTileAction(message, player, ACTION_OPERATE);\r\n\tcase CMD_DISARMXY:\r\n\t\treturn OnObjectTileAction(message, player, ACTION_DISARM);\r\n\tcase CMD_OPOBJT:\r\n\t\treturn OnObjectTileAction(message, player, ACTION_OPERATETK, false);\r\n\tdefault:\r\n\t\treturn sizeof(message);\r\n\t}\r\n}\r\n\r\nsize_t OnAttackMonster(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t monsterIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && leveltype != DTYPE_TOWN && monsterIdx < MaxMonsters) {\r\n\t\tconst Point position = Monsters[monsterIdx].position.future;\r\n\t\tif (player.position.tile.WalkingDistance(position) > 1)\r\n\t\t\tMakePlrPath(player, position, false);\r\n\t\tplayer.destAction = ACTION_ATTACKMON;\r\n\t\tplayer.destParam1 = monsterIdx;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnAttackPlayer(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t playerIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && leveltype != DTYPE_TOWN && playerIdx < Players.size()) {\r\n\t\tMakePlrPath(player, Players[playerIdx].position.future, false);\r\n\t\tplayer.destAction = ACTION_ATTACKPLR;\r\n\t\tplayer.destParam1 = playerIdx;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnRangedAttackMonster(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t monsterIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && leveltype != DTYPE_TOWN && monsterIdx < MaxMonsters) {\r\n\t\tClrPlrPath(player);\r\n\t\tplayer.destAction = ACTION_RATTACKMON;\r\n\t\tplayer.destParam1 = monsterIdx;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnRangedAttackPlayer(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t playerIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && leveltype != DTYPE_TOWN && playerIdx < Players.size()) {\r\n\t\tClrPlrPath(player);\r\n\t\tplayer.destAction = ACTION_RATTACKPLR;\r\n\t\tplayer.destParam1 = playerIdx;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSpellMonster(const TCmdParam4 &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\treturn sizeof(message);\r\n\tif (!player.isOnActiveLevel())\r\n\t\treturn sizeof(message);\r\n\tif (leveltype == DTYPE_TOWN)\r\n\t\treturn sizeof(message);\r\n\tconst uint16_t monsterIdx = Swap16LE(message.wParam1);\r\n\tif (monsterIdx >= MaxMonsters)\r\n\t\treturn sizeof(message);\r\n\r\n\tif (!InitNewSpell(player, message.wParam2, message.wParam3, message.wParam4))\r\n\t\treturn sizeof(message);\r\n\r\n\tClrPlrPath(player);\r\n\tplayer.destAction = ACTION_SPELLMON;\r\n\tplayer.destParam1 = monsterIdx;\r\n\tplayer.destParam2 = player.GetSpellLevel(player.queuedSpell.spellId);\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSpellPlayer(const TCmdParam4 &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\treturn sizeof(message);\r\n\tif (!player.isOnActiveLevel())\r\n\t\treturn sizeof(message);\r\n\tconst uint16_t playerIdx = Swap16LE(message.wParam1);\r\n\tif (playerIdx >= Players.size())\r\n\t\treturn sizeof(message);\r\n\r\n\tif (!InitNewSpell(player, message.wParam2, message.wParam3, message.wParam4))\r\n\t\treturn sizeof(message);\r\n\r\n\tClrPlrPath(player);\r\n\tplayer.destAction = ACTION_SPELLPLR;\r\n\tplayer.destParam1 = playerIdx;\r\n\tplayer.destParam2 = player.GetSpellLevel(player.queuedSpell.spellId);\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnKnockback(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t monsterIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && leveltype != DTYPE_TOWN && monsterIdx < MaxMonsters) {\r\n\t\tMonster &monster = Monsters[monsterIdx];\r\n\t\tM_GetKnockback(monster, player.position.tile);\r\n\t\tM_StartHit(monster, player, 0);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnResurrect(const TCmdParam1 &message, Player &caster)\r\n{\r\n\tconst uint16_t playerIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(caster, &message, sizeof(message));\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tif (playerIdx >= Players.size())\r\n\t\treturn sizeof(message);\r\n\r\n\tPlayer &target = Players[playerIdx];\r\n\r\n\tSpawnResurrectBeam(caster, target);\r\n\r\n\tif (&target == MyPlayer && target._pHitPoints <= 0) {\r\n\t\tNetSendCmd(true, CMD_PLRALIVE);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnPlayerAlive(const TCmd &message, Player &target)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(target, &message, sizeof(message));\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tApplyResurrect(target);\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnHealOther(const TCmdParam1 &message, const Player &caster)\r\n{\r\n\tconst uint16_t playerIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (caster.isOnActiveLevel() && playerIdx < Players.size()) {\r\n\t\t\tDoHealOther(caster, Players[playerIdx]);\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnTalkXY(const TCmdLocParam1 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\tconst uint16_t townerIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && townerIdx < GetNumTowners()) {\r\n\t\tMakePlrPath(player, position, false);\r\n\t\tplayer.destAction = ACTION_TALK;\r\n\t\tplayer.destParam1 = townerIdx;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnNewLevel(const TCmdParam2 &message, Player &player)\r\n{\r\n\tconst uint16_t eventIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (&player != MyPlayer) {\r\n\t\tif (eventIdx < WM_FIRST || eventIdx > WM_LAST)\r\n\t\t\treturn sizeof(message);\r\n\r\n\t\tauto mode = static_cast<interface_mode>(eventIdx);\r\n\r\n\t\tconst auto levelId = static_cast<uint8_t>(Swap16LE(message.wParam2));\r\n\t\tif (!IsValidLevel(levelId, mode == WM_DIABSETLVL)) {\r\n\t\t\treturn sizeof(message);\r\n\t\t}\r\n\r\n\t\tStartNewLvl(player, mode, levelId);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnWarp(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t portalIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (portalIdx < MAXPORTAL) {\r\n\t\tStartWarpLvl(player, portalIdx);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnMonstDeath(const TCmdLocParam1 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\tconst uint16_t monsterIdx = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (&player != MyPlayer && player.plrlevel > 0 && InDungeonBounds(position) && monsterIdx < MaxMonsters) {\r\n\t\t\tMonster &monster = Monsters[monsterIdx];\r\n\t\t\tif (player.isOnActiveLevel())\r\n\t\t\t\tM_SyncStartKill(monster, position, player);\r\n\t\t\tdelta_kill_monster(monster, position, player);\r\n\t\t}\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnRequestSpawnGolem(const TCmdLocParam1 &message, const Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\treturn sizeof(message);\r\n\r\n\tconst WorldTilePosition position { message.x, message.y };\r\n\r\n\tif (player.plrlevel > 0 && player.isLevelOwnedByLocalClient() && InDungeonBounds(position))\r\n\t\tSpawnGolem(player, position, static_cast<uint8_t>(message.wParam1));\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnMonstDamage(const TCmdMonDamage &message, Player &player)\r\n{\r\n\tconst uint16_t monsterIdx = Swap16LE(message.wMon);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (&player != MyPlayer) {\r\n\t\t\tif (player.isOnActiveLevel() && leveltype != DTYPE_TOWN && monsterIdx < MaxMonsters) {\r\n\t\t\t\tMonster &monster = Monsters[monsterIdx];\r\n\t\t\t\tmonster.tag(player);\r\n\t\t\t\tif (monster.hitPoints > 0) {\r\n\t\t\t\t\tmonster.hitPoints -= Swap32LE(message.dwDam);\r\n\t\t\t\t\tif ((monster.hitPoints >> 6) < 1)\r\n\t\t\t\t\t\tmonster.hitPoints = 1 << 6;\r\n\t\t\t\t\tdelta_monster_hp(monster, player);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnPlayerDeath(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst auto deathReason = static_cast<DeathReason>(Swap16LE(message.wParam1));\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (&player != MyPlayer)\r\n\t\t\tStartPlayerKill(player, deathReason);\r\n\t\telse\r\n\t\t\tpfile_update(true);\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnPlayerDamage(const TCmdDamage &message, Player &player)\r\n{\r\n\tconst uint32_t damage = Swap32LE(message.dwDam);\r\n\r\n\tPlayer &target = Players[message.bPlr];\r\n\tif (&target == MyPlayer && leveltype != DTYPE_TOWN && gbBufferMsgs != 1) {\r\n\t\tif (player.isOnActiveLevel() && damage <= 192000 && !target.hasNoLife()) {\r\n\t\t\tApplyPlrDamage(message.damageType, target, 0, 0, static_cast<int>(damage), DeathReason::Player);\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnOperateObject(const TCmdLoc &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else {\r\n\t\tconst WorldTilePosition position { message.x, message.y };\r\n\t\tassert(InDungeonBounds(position));\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tObject *object = FindObjectAtPosition(position);\r\n\t\t\tif (object != nullptr)\r\n\t\t\t\tSyncOpObject(player, message.bCmd, *object);\r\n\t\t}\r\n\t\tif (player.plrlevel > 0) {\r\n\t\t\tDeltaSyncObject(position, message.bCmd, player);\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnBreakObject(const TCmdLoc &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else {\r\n\t\tconst WorldTilePosition position { message.x, message.y };\r\n\t\tassert(InDungeonBounds(position));\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tObject *object = FindObjectAtPosition(position);\r\n\t\t\tif (object != nullptr)\r\n\t\t\t\tSyncBreakObj(player, *object);\r\n\t\t}\r\n\t\tif (player.plrlevel > 0) {\r\n\t\t\tDeltaSyncObject(position, CMD_BREAKOBJ, player);\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnChangePlayerItems(const TCmdChItem &message, Player &player)\r\n{\r\n\tif (message.bLoc >= NUM_INVLOC)\r\n\t\treturn sizeof(message);\r\n\r\n\tauto bodyLocation = static_cast<inv_body_loc>(message.bLoc);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (&player != MyPlayer && IsItemAvailable(static_cast<_item_indexes>(Swap16LE(message.def.wIndx)))) {\r\n\t\tItem &item = player.InvBody[message.bLoc];\r\n\t\titem = {};\r\n\t\tRecreateItem(player, message, item);\r\n\t\tCheckInvSwap(player, bodyLocation);\r\n\t}\r\n\r\n\tplayer.ReadySpellFromEquipment(bodyLocation, message.forceSpell);\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnDeletePlayerItems(const TCmdDelItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (&player != MyPlayer && message.bLoc < NUM_INVLOC)\r\n\t\t\tinv_update_rem_item(player, static_cast<inv_body_loc>(message.bLoc));\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnChangeInventoryItems(const TCmdChItem &message, Player &player)\r\n{\r\n\tif (message.bLoc >= InventoryGridCells)\r\n\t\treturn sizeof(message);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (&player != MyPlayer && IsItemAvailable(static_cast<_item_indexes>(Swap16LE(message.def.wIndx)))) {\r\n\t\tItem item {};\r\n\t\tRecreateItem(player, message, item);\r\n\t\tCheckInvSwap(player, item, message.bLoc);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnDeleteInventoryItems(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t invGridIndex = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (&player != MyPlayer && invGridIndex < InventoryGridCells) {\r\n\t\tCheckInvRemove(player, invGridIndex);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnChangeBeltItems(const TCmdChItem &message, Player &player)\r\n{\r\n\tif (message.bLoc >= MaxBeltItems)\r\n\t\treturn sizeof(message);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (&player != MyPlayer && IsItemAvailable(static_cast<_item_indexes>(Swap16LE(message.def.wIndx)))) {\r\n\t\tItem &item = player.SpdList[message.bLoc];\r\n\t\titem = {};\r\n\t\tRecreateItem(player, message, item);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnDeleteBeltItems(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t spdBarIndex = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (&player != MyPlayer && spdBarIndex < MaxBeltItems) {\r\n\t\tplayer.RemoveSpdBarItem(spdBarIndex);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnPlayerLevel(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t playerLevel = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (playerLevel <= player.getMaxCharacterLevel() && &player != MyPlayer)\r\n\t\t\tplayer.setCharacterLevel(static_cast<uint8_t>(playerLevel));\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnDropItem(const TCmdPItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (IsPItemValid(message, player)) {\r\n\t\tDeltaPutItem(message, { message.x, message.y }, player);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSpawnItem(const TCmdPItem &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (IsPItemValid(message, player)) {\r\n\t\tif (player.isOnActiveLevel() && &player != MyPlayer) {\r\n\t\t\tSyncDropItem(message);\r\n\t\t}\r\n\t\tPutItemRecord(Swap32LE(message.def.dwSeed), Swap16LE(message.def.wCI), static_cast<_item_indexes>(Swap16LE(message.def.wIndx)));\r\n\t\tDeltaPutItem(message, { message.x, message.y }, player);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSendPlayerInfo(const TCmdPlrInfoHdr &header, size_t maxCmdSize, Player &player)\r\n{\r\n\tconst uint16_t wBytes = Swap16LE(header.wBytes);\r\n\r\n\tif (!ValidateCmdSize(wBytes + sizeof(header), maxCmdSize, player.getId()))\r\n\t\treturn maxCmdSize;\r\n\r\n\tif (gbBufferMsgs == 1)\r\n\t\tBufferMessage(player, &header, wBytes + sizeof(header));\r\n\telse\r\n\t\trecv_plrinfo(player, header, header.bCmd == CMD_ACK_PLRINFO);\r\n\r\n\treturn wBytes + sizeof(header);\r\n}\r\n\r\nsize_t OnPlayerJoinLevel(const TCmdLocParam2 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tconst auto playerLevel = static_cast<uint8_t>(Swap16LE(message.wParam1));\r\n\tconst bool isSetLevel = message.wParam2 != 0;\r\n\tif (!IsValidLevel(playerLevel, isSetLevel) || !InDungeonBounds(position)) {\r\n\t\treturn sizeof(message);\r\n\t}\r\n\r\n\tplayer._pLvlChanging = false;\r\n\tif (player._pName[0] != '\\0' && !player.plractive) {\r\n\t\tResetPlayerGFX(player);\r\n\t\tplayer.plractive = true;\r\n\t\tgbActivePlayers++;\r\n\t\tEventPlrMsg(fmt::format(fmt::runtime(_(\"Player '{:s}' (level {:d}) just joined the game\")), player._pName, player.getCharacterLevel()));\r\n\t}\r\n\r\n\tif (player.plractive && &player != MyPlayer) {\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tRemoveEnemyReferences(player);\r\n\t\t\tRemovePlrMissiles(player);\r\n\t\t\tFixPlrWalkTags(player);\r\n\t\t}\r\n\t\tplayer.position.tile = position;\r\n\t\tSetPlayerOld(player);\r\n\t\tif (isSetLevel)\r\n\t\t\tplayer.setLevel(static_cast<_setlevels>(playerLevel));\r\n\t\telse\r\n\t\t\tplayer.setLevel(playerLevel);\r\n\t\tResetPlayerGFX(player);\r\n\t\tif (player.isOnActiveLevel()) {\r\n\t\t\tSyncInitPlr(player);\r\n\t\t\tif (!player.hasNoLife()) {\r\n\t\t\t\tStartStand(player, Direction::South);\r\n\t\t\t} else {\r\n\t\t\t\tplayer._pgfxnum &= ~0xFU;\r\n\t\t\t\tplayer._pmode = PM_DEATH;\r\n\t\t\t\tNewPlrAnim(player, player_graphic::Death, Direction::South);\r\n\t\t\t\tplayer.AnimInfo.currentFrame = static_cast<int8_t>(player.AnimInfo.numberOfFrames - 2);\r\n\t\t\t\tdFlags[player.position.tile.x][player.position.tile.y] |= DungeonFlag::DeadPlayer;\r\n\t\t\t}\r\n\r\n\t\t\tActivateVision(player.position.tile, player._pLightRad, player.getId());\r\n\t\t}\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnActivatePortal(const TCmdLocParam3 &message, Player &player)\r\n{\r\n\tconst Point position { message.x, message.y };\r\n\tconst auto level = static_cast<uint8_t>(Swap16LE(message.wParam1));\r\n\tconst uint16_t dungeonTypeIdx = Swap16LE(message.wParam2);\r\n\tconst bool isSetLevel = message.wParam3 != 0;\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else if (InDungeonBounds(position) && IsValidLevel(level, isSetLevel) && dungeonTypeIdx <= DTYPE_LAST) {\r\n\t\tauto dungeonType = static_cast<dungeon_type>(dungeonTypeIdx);\r\n\r\n\t\tActivatePortal(player, position, level, dungeonType, isSetLevel);\r\n\t\tif (&player != MyPlayer) {\r\n\t\t\tif (leveltype == DTYPE_TOWN) {\r\n\t\t\t\tAddPortalInTown(player);\r\n\t\t\t} else if (player.isOnActiveLevel()) {\r\n\t\t\t\tbool addPortal = true;\r\n\t\t\t\tfor (auto &missile : Missiles) {\r\n\t\t\t\t\tif (missile._mitype == MissileID::TownPortal && &Players[missile._misource] == &player) {\r\n\t\t\t\t\t\taddPortal = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (addPortal) {\r\n\t\t\t\t\tAddPortalMissile(player, position, false);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tRemovePortalMissile(player);\r\n\t\t\t}\r\n\t\t}\r\n\t\tDeltaOpenPortal(player.getId(), position, level, dungeonType, isSetLevel);\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnDeactivatePortal(const TCmd &cmd, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &cmd, sizeof(cmd));\r\n\t} else {\r\n\t\tif (PortalOnLevel(player))\r\n\t\t\tRemovePortalMissile(player);\r\n\t\tDeactivatePortal(player);\r\n\t\tdelta_close_portal(player);\r\n\t}\r\n\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnRestartTown(const TCmd &cmd, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &cmd, sizeof(cmd));\r\n\t} else {\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tMyPlayerIsDead = false;\r\n\t\t\tgamemenu_off();\r\n\t\t}\r\n\t\tRestartTownLvl(player);\r\n\t}\r\n\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnSetStrength(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t value = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (value <= 750 && &player != MyPlayer)\r\n\t\t\tSetPlrStr(player, value);\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSetDexterity(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t value = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (value <= 750 && &player != MyPlayer)\r\n\t\t\tSetPlrDex(player, value);\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSetMagic(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t value = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (value <= 750 && &player != MyPlayer)\r\n\t\t\tSetPlrMag(player, value);\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnSetVitality(const TCmdParam1 &message, Player &player)\r\n{\r\n\tconst uint16_t value = Swap16LE(message.wParam1);\r\n\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (value <= 750 && &player != MyPlayer)\r\n\t\t\tSetPlrVit(player, value);\r\n\t} else {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnString(const TCmd &cmd, size_t maxCmdSize, Player &player)\r\n{\r\n\tconst auto &message = reinterpret_cast<const TCmdString &>(cmd);\r\n\tconst size_t headerSize = sizeof(message) - sizeof(message.str);\r\n\tconst size_t maxLength = std::min<size_t>(MAX_SEND_STR_LEN, maxCmdSize - headerSize);\r\n\tconst std::string_view str { message.str, maxLength };\r\n\tconst auto tokens = SplitByChar(str, '\\0');\r\n\tconst std::string_view playerMessage = *tokens.begin();\r\n\r\n\tif (gbBufferMsgs == 0)\r\n\t\tSendPlrMsg(player, playerMessage);\r\n\r\n\tconst size_t nullSize = str.size() != playerMessage.size() ? 1 : 0;\r\n\treturn headerSize + playerMessage.size() + nullSize;\r\n}\r\n\r\nsize_t OnFriendlyMode(const TCmd &cmd, Player &player) // NOLINT(misc-unused-parameters)\r\n{\r\n\tplayer.friendlyMode = !player.friendlyMode;\r\n\tRedrawEverything();\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnSyncQuest(const TCmdQuest &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else {\r\n\t\tif (&player != MyPlayer && message.q < MAXQUESTS && message.qstate <= QUEST_HIVE_DONE)\r\n\t\t\tSetMultiQuest(message.q, message.qstate, message.qlog != 0, message.qvar1, message.qvar2, Swap16LE(message.qmsg));\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnCheatExperience(const TCmd &cmd, Player &player) // NOLINT(misc-unused-parameters)\r\n{\r\n#ifdef _DEBUG\r\n\tif (gbBufferMsgs == 1)\r\n\t\tBufferMessage(player, &cmd, sizeof(cmd));\r\n\telse if (!player.isMaxCharacterLevel()) {\r\n\t\tplayer._pExperience = player.getNextExperienceThreshold();\r\n\t\tif (*GetOptions().Gameplay.experienceBar) {\r\n\t\t\tRedrawEverything();\r\n\t\t}\r\n\t\tNextPlrLevel(player);\r\n\t}\r\n#endif\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnChangeSpellLevel(const TCmdParam2 &message, Player &player) // NOLINT(misc-unused-parameters)\r\n{\r\n\tconst auto spellID = static_cast<SpellID>(Swap16LE(message.wParam1));\r\n\tconst uint8_t spellLevel = std::min(static_cast<uint8_t>(Swap16LE(message.wParam2)), MaxSpellLevel);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\tBufferMessage(player, &message, sizeof(message));\r\n\t} else {\r\n\t\tplayer._pMemSpells |= GetSpellBitmask(spellID);\r\n\t\tplayer._pSplLvl[static_cast<size_t>(spellID)] = spellLevel;\r\n\t}\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnDebug(const TCmd &pCmd)\r\n{\r\n\treturn sizeof(pCmd);\r\n}\r\n\r\nsize_t OnSetShield(const TCmd &cmd, Player &player)\r\n{\r\n\tif (gbBufferMsgs != 1)\r\n\t\tplayer.pManaShield = true;\r\n\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnRemoveShield(const TCmd &cmd, Player &player)\r\n{\r\n\tif (gbBufferMsgs != 1)\r\n\t\tplayer.pManaShield = false;\r\n\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnSetReflect(const TCmdParam1 &message, Player &player)\r\n{\r\n\tif (gbBufferMsgs != 1)\r\n\t\tplayer.wReflections = Swap16LE(message.wParam1);\r\n\r\n\treturn sizeof(message);\r\n}\r\n\r\nsize_t OnNakrul(const TCmd &cmd)\r\n{\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tif (currlevel == 24) {\r\n\t\t\tPlaySfxLoc(SfxID::CryptDoorOpen, { UberRow, UberCol });\r\n\t\t\tSyncNakrulRoom();\r\n\t\t}\r\n\t\tIsUberRoomOpened = true;\r\n\t\tQuests[Q_NAKRUL]._qactive = QUEST_DONE;\r\n\t\tWeakenNaKrul();\r\n\t}\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnOpenHive(const TCmd &cmd, Player &player)\r\n{\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tAddMissile({ 0, 0 }, { 0, 0 }, Direction::South, MissileID::OpenNest, TARGET_MONSTERS, player, 0, 0);\r\n\t\tTownOpenHive();\r\n\t\tInitTownTriggers();\r\n\t}\r\n\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnOpenGrave(const TCmd &cmd)\r\n{\r\n\tif (gbBufferMsgs != 1) {\r\n\t\tTownOpenGrave();\r\n\t\tInitTownTriggers();\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\tPlaySFX(SfxID::Sarcophagus);\r\n\t}\r\n\treturn sizeof(cmd);\r\n}\r\n\r\nsize_t OnSpawnMonster(const TCmdSpawnMonster &message, const Player &player)\r\n{\r\n\tif (gbBufferMsgs == 1)\r\n\t\treturn sizeof(message);\r\n\tif (player.plrlevel == 0)\r\n\t\treturn sizeof(message);\r\n\r\n\tconst WorldTilePosition position { message.x, message.y };\r\n\r\n\tauto typeIndex = static_cast<size_t>(Swap16LE(message.typeIndex));\r\n\tauto monsterId = static_cast<size_t>(Swap16LE(message.monsterId));\r\n\tconst uint8_t golemOwnerPlayerId = message.golemOwnerPlayerId;\r\n\tif (golemOwnerPlayerId >= Players.size()) {\r\n\t\treturn sizeof(message);\r\n\t}\r\n\tconst uint8_t golemSpellLevel = std::min(message.golemSpellLevel, static_cast<uint8_t>(MaxSpellLevel + Players[golemOwnerPlayerId]._pISplLvlAdd));\r\n\r\n\tDLevel &deltaLevel = GetDeltaLevel(player);\r\n\r\n\tdeltaLevel.spawnedMonsters[monsterId] = { typeIndex, message.seed, golemOwnerPlayerId, golemSpellLevel };\r\n\t// Override old monster delta information\r\n\tauto &deltaMonster = deltaLevel.monster[monsterId];\r\n\tdeltaMonster.position = position;\r\n\tdeltaMonster.hitPoints = -1;\r\n\tdeltaMonster.menemy = 0;\r\n\tdeltaMonster.mactive = 0;\r\n\r\n\tif (player.isOnActiveLevel() && &player != MyPlayer)\r\n\t\tInitializeSpawnedMonster(position, message.dir, typeIndex, monsterId, message.seed, golemOwnerPlayerId, golemSpellLevel);\r\n\treturn sizeof(message);\r\n}\r\n\r\ntemplate <typename TCmdImpl>\r\nsize_t HandleCmd(size_t (*handler)(const TCmdImpl &, size_t, Player &), Player &player, const TCmd *pCmd, size_t maxCmdSize)\r\n{\r\n\tif (!ValidateCmdSize(sizeof(TCmdImpl), maxCmdSize, player.getId()))\r\n\t\treturn maxCmdSize;\r\n\r\n\tconst auto *message = reinterpret_cast<const TCmdImpl *>(pCmd);\r\n\treturn handler(*message, maxCmdSize, player);\r\n}\r\n\r\ntemplate <typename TCmdImpl>\r\nsize_t HandleCmd(size_t (*handler)(const TCmdImpl &, size_t, const Player &), const Player &player, const TCmd *pCmd, size_t maxCmdSize)\r\n{\r\n\tif (!ValidateCmdSize(sizeof(TCmdImpl), maxCmdSize, player.getId()))\r\n\t\treturn maxCmdSize;\r\n\r\n\tconst auto *message = reinterpret_cast<const TCmdImpl *>(pCmd);\r\n\treturn handler(*message, maxCmdSize, player);\r\n}\r\n\r\ntemplate <typename TCmdImpl>\r\nsize_t HandleCmd(size_t (*handler)(const TCmdImpl &, Player &), Player &player, const TCmd *pCmd, size_t maxCmdSize)\r\n{\r\n\tif (!ValidateCmdSize(sizeof(TCmdImpl), maxCmdSize, player.getId()))\r\n\t\treturn maxCmdSize;\r\n\r\n\tconst auto *message = reinterpret_cast<const TCmdImpl *>(pCmd);\r\n\treturn handler(*message, player);\r\n}\r\n\r\ntemplate <typename TCmdImpl>\r\nsize_t HandleCmd(size_t (*handler)(const TCmdImpl &, const Player &), const Player &player, const TCmd *pCmd, size_t maxCmdSize)\r\n{\r\n\tif (!ValidateCmdSize(sizeof(TCmdImpl), maxCmdSize, player.getId()))\r\n\t\treturn maxCmdSize;\r\n\r\n\tconst auto *message = reinterpret_cast<const TCmdImpl *>(pCmd);\r\n\treturn handler(*message, player);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid PrepareItemForNetwork(const Item &item, TItem &messageItem)\r\n{\r\n\tmessageItem.bId = item._iIdentified ? 1 : 0;\r\n\tmessageItem.bDur = item._iDurability;\r\n\tmessageItem.bMDur = item._iMaxDur;\r\n\tmessageItem.bCh = item._iCharges;\r\n\tmessageItem.bMCh = item._iMaxCharges;\r\n\tmessageItem.wValue = Swap16LE(item._ivalue);\r\n\tmessageItem.wToHit = Swap16LE(item._iPLToHit);\r\n\tmessageItem.wMaxDam = Swap16LE(item._iMaxDam);\r\n\tmessageItem.dwBuff = Swap32LE(item.dwBuff);\r\n}\r\n\r\nvoid PrepareEarForNetwork(const Item &item, TEar &ear)\r\n{\r\n\tear.bCursval = item._ivalue | ((item._iCurs - ICURS_EAR_SORCERER) << 6);\r\n\tCopyUtf8(ear.heroname, item._iIName, sizeof(ear.heroname));\r\n}\r\n\r\nvoid RecreateItem(const Player &player, const TItem &messageItem, Item &item)\r\n{\r\n\tconst uint32_t dwBuff = Swap32LE(messageItem.dwBuff);\r\n\tRecreateItem(player, item,\r\n\t    static_cast<_item_indexes>(Swap16LE(messageItem.wIndx)), Swap16LE(messageItem.wCI),\r\n\t    Swap32LE(messageItem.dwSeed), Swap16LE(messageItem.wValue), dwBuff);\r\n\tif (messageItem.bId != 0)\r\n\t\titem._iIdentified = true;\r\n\titem._iMaxDur = messageItem.bMDur;\r\n\titem._iDurability = ClampDurability(item, messageItem.bDur);\r\n\titem._iMaxCharges = std::clamp<int>(messageItem.bMCh, 0, item._iMaxCharges);\r\n\titem._iCharges = std::clamp<int>(messageItem.bCh, 0, item._iMaxCharges);\r\n\tif (gbIsHellfire) {\r\n\t\titem._iPLToHit = ClampToHit(item, static_cast<uint8_t>(Swap16LE(messageItem.wToHit)));\r\n\t\titem._iMaxDam = ClampMaxDam(item, static_cast<uint8_t>(Swap16LE(messageItem.wMaxDam)));\r\n\t}\r\n}\r\n\r\nvoid ClearLastSentPlayerCmd()\r\n{\r\n\tlastSentPlayerCmd = {};\r\n}\r\n\r\nvoid msg_send_drop_pkt(uint8_t pnum, leaveinfo_t reason)\r\n{\r\n\tTFakeDropPlr cmd;\r\n\r\n\tcmd.dwReason = Swap32LE(static_cast<uint32_t>(reason));\r\n\tcmd.bCmd = FAKE_CMD_DROPID;\r\n\tcmd.bPlr = pnum;\r\n\tBufferMessage(pnum, &cmd, sizeof(cmd));\r\n}\r\n\r\nbool msg_wait_resync()\r\n{\r\n\tbool success;\r\n\r\n\tGetNextPacket();\r\n\tsgbDeltaChunks = 0;\r\n\tsgnCurrMegaPlayer = -1;\r\n\tsgbRecvCmd = CMD_DLEVEL_END;\r\n\tgbBufferMsgs = 1;\r\n\tsgdwOwnerWait = SDL_GetTicks();\r\n\tsuccess = UiProgressDialog(WaitForTurns);\r\n\tgbBufferMsgs = 0;\r\n\tif (!success) {\r\n\t\tFreePackets();\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (gbGameDestroyed) {\r\n\t\tUiErrorOkDialog(PROJECT_NAME, _(\"The game ended\"), /*error=*/false);\r\n\t\tFreePackets();\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (sgbDeltaChunks != MaxChunks) {\r\n\t\tUiErrorOkDialog(PROJECT_NAME, _(\"Unable to get level data\"), /*error=*/false);\r\n\t\tFreePackets();\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid run_delta_info()\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tgbBufferMsgs = 2;\r\n\tPrePacket();\r\n\tgbBufferMsgs = 0;\r\n\tFreePackets();\r\n}\r\n\r\nvoid DeltaExportData(uint8_t pnum)\r\n{\r\n\tfor (const auto &[levelNum, deltaLevel] : DeltaLevels) {\r\n\t\tconst size_t bufferSize = 1U                                                            /* marker byte, always 0 */\r\n\t\t    + sizeof(uint8_t)                                                                   /* level id */\r\n\t\t    + sizeof(deltaLevel.item)                                                           /* items spawned during dungeon generation which have been picked up, and items dropped by a player during a game */\r\n\t\t    + sizeof(uint8_t)                                                                   /* count of object interactions which caused a state change since dungeon generation */\r\n\t\t    + (sizeof(WorldTilePosition) + sizeof(DObjectStr)) * deltaLevel.object.size()       /* location/action pairs for the object interactions */\r\n\t\t    + sizeof(deltaLevel.monster)                                                        /* latest monster state */\r\n\t\t    + sizeof(uint16_t)                                                                  /* spawned monster count */\r\n\t\t    + (sizeof(uint16_t) + sizeof(DSpawnedMonster)) * deltaLevel.spawnedMonsters.size(); /* spawned monsters */\r\n\t\tconst std::unique_ptr<std::byte[]> dst { new std::byte[bufferSize] };\r\n\r\n\t\tstd::byte *dstEnd = &dst.get()[1];\r\n\t\t*dstEnd = static_cast<std::byte>(levelNum);\r\n\t\tdstEnd += sizeof(uint8_t);\r\n\t\tdstEnd = DeltaExportItem(dstEnd, deltaLevel.item);\r\n\t\tdstEnd = DeltaExportObject(dstEnd, deltaLevel.object);\r\n\t\tdstEnd = DeltaExportMonster(dstEnd, deltaLevel.monster);\r\n\t\tdstEnd = DeltaExportSpawnedMonsters(dstEnd, deltaLevel.spawnedMonsters);\r\n\t\tconst uint32_t size = CompressData(dst.get(), dstEnd);\r\n\t\tmulti_send_zero_packet(pnum, CMD_DLEVEL, dst.get(), size);\r\n\t}\r\n\r\n\tstd::byte dst[sizeof(DJunk) + 1];\r\n\tstd::byte *dstEnd = &dst[1];\r\n\tdstEnd = DeltaExportJunk(dstEnd);\r\n\tconst uint32_t size = CompressData(dst, dstEnd);\r\n\tmulti_send_zero_packet(pnum, CMD_DLEVEL_JUNK, dst, size);\r\n\r\n\tstd::byte src[1] = { static_cast<std::byte>(0) };\r\n\tmulti_send_zero_packet(pnum, CMD_DLEVEL_END, src, 1);\r\n}\r\n\r\nvoid delta_init()\r\n{\r\n\tmemset(&sgJunk, 0xFF, sizeof(sgJunk));\r\n\tDeltaLevels.clear();\r\n\tLocalLevels.clear();\r\n}\r\n\r\nvoid DeltaClearLevel(uint8_t level)\r\n{\r\n\tDeltaLevels.erase(level);\r\n\tLocalLevels.erase(level);\r\n}\r\n\r\nvoid delta_kill_monster(const Monster &monster, Point position, const Player &player)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tDMonsterStr *pD = &GetDeltaLevel(player).monster[monster.getId()];\r\n\tpD->position = position;\r\n\tpD->hitPoints = 0;\r\n}\r\n\r\nvoid delta_monster_hp(const Monster &monster, const Player &player)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tDMonsterStr *pD = &GetDeltaLevel(player).monster[monster.getId()];\r\n\tif (SwapSigned32LE(pD->hitPoints) > monster.hitPoints)\r\n\t\tpD->hitPoints = SwapSigned32LE(monster.hitPoints);\r\n}\r\n\r\nvoid delta_sync_monster(const TSyncMonster &monsterSync, uint8_t level)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tassert(level <= MaxMultiplayerLevels);\r\n\r\n\tDMonsterStr &monster = GetDeltaLevel(level).monster[monsterSync._mndx];\r\n\tif (monster.hitPoints == 0)\r\n\t\treturn;\r\n\r\n\tmonster.position.x = monsterSync._mx;\r\n\tmonster.position.y = monsterSync._my;\r\n\tmonster.mactive = UINT8_MAX;\r\n\tmonster.menemy = monsterSync._menemy;\r\n\tmonster.hitPoints = monsterSync._mhitpoints;\r\n\tmonster.mWhoHit = monsterSync.mWhoHit;\r\n}\r\n\r\nvoid DeltaSyncJunk()\r\n{\r\n\tfor (int i = 0; i < MAXPORTAL; i++) {\r\n\t\tif (sgJunk.portal[i].x == 0xFF) {\r\n\t\t\tSetPortalStats(i, false, { 0, 0 }, 0, DTYPE_TOWN, false);\r\n\t\t} else {\r\n\t\t\tSetPortalStats(\r\n\t\t\t    i,\r\n\t\t\t    true,\r\n\t\t\t    { sgJunk.portal[i].x, sgJunk.portal[i].y },\r\n\t\t\t    sgJunk.portal[i].level,\r\n\t\t\t    (dungeon_type)sgJunk.portal[i].ltype,\r\n\t\t\t    sgJunk.portal[i].setlvl != 0);\r\n\t\t}\r\n\t}\r\n\r\n\tint q = 0;\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (QuestsData[quest._qidx].isSinglePlayerOnly && UseMultiplayerQuests()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (sgJunk.quests[q].qstate != QUEST_INVALID) {\r\n\t\t\tquest._qlog = sgJunk.quests[q].qlog != 0;\r\n\t\t\tquest._qactive = sgJunk.quests[q].qstate;\r\n\t\t\tquest._qvar1 = sgJunk.quests[q].qvar1;\r\n\t\t\tquest._qvar2 = sgJunk.quests[q].qvar2;\r\n\t\t\tquest._qmsg = static_cast<_speech_id>(Swap16LE(sgJunk.quests[q].qmsg));\r\n\t\t}\r\n\t\tq++;\r\n\t}\r\n}\r\n\r\nvoid DeltaAddItem(int ii)\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tconst uint8_t localLevel = GetLevelForMultiplayer(*MyPlayer);\r\n\tDLevel &deltaLevel = GetDeltaLevel(localLevel);\r\n\r\n\tfor (const TCmdPItem &item : deltaLevel.item) {\r\n\t\tif (item.bCmd != CMD_INVALID\r\n\t\t    && static_cast<_item_indexes>(Swap16LE(item.def.wIndx)) == Items[ii].IDidx\r\n\t\t    && Swap16LE(item.def.wCI) == Items[ii]._iCreateInfo\r\n\t\t    && static_cast<uint32_t>(Swap32LE(item.def.dwSeed)) == Items[ii]._iSeed\r\n\t\t    && IsAnyOf(item.bCmd, TCmdPItem::PickedUpItem, TCmdPItem::FloorItem)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (TCmdPItem &delta : deltaLevel.item) {\r\n\t\tif (delta.bCmd != CMD_INVALID)\r\n\t\t\tcontinue;\r\n\r\n\t\tdelta.bCmd = TCmdPItem::FloorItem;\r\n\t\tdelta.x = Items[ii].position.x;\r\n\t\tdelta.y = Items[ii].position.y;\r\n\t\tPrepareItemForNetwork(Items[ii], delta);\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\nvoid DeltaSaveLevel()\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tfor (Player &player : Players) {\r\n\t\tif (&player != MyPlayer)\r\n\t\t\tResetPlayerGFX(player);\r\n\t}\r\n\tuint8_t localLevel;\r\n\tif (setlevel) {\r\n\t\tlocalLevel = GetLevelForMultiplayer(static_cast<uint8_t>(setlvlnum), setlevel);\r\n\t\tMyPlayer->_pSLvlVisited[static_cast<uint8_t>(setlvlnum)] = true;\r\n\t} else {\r\n\t\tlocalLevel = GetLevelForMultiplayer(currlevel, setlevel);\r\n\t\tMyPlayer->_pLvlVisited[currlevel] = true;\r\n\t}\r\n\tDeltaLeaveSync(localLevel);\r\n}\r\n\r\nuint8_t GetLevelForMultiplayer(const Player &player)\r\n{\r\n\treturn GetLevelForMultiplayer(player.plrlevel, player.plrIsOnSetLevel);\r\n}\r\n\r\nbool IsValidLevelForMultiplayer(uint8_t level)\r\n{\r\n\treturn level <= MaxMultiplayerLevels;\r\n}\r\n\r\nbool IsValidLevel(uint8_t level, bool isSetLevel)\r\n{\r\n\tif (isSetLevel)\r\n\t\treturn level <= SL_LAST;\r\n\treturn level < NUMLEVELS;\r\n}\r\n\r\nvoid DeltaLoadLevel()\r\n{\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tconst uint8_t localLevel = GetLevelForMultiplayer(*MyPlayer);\r\n\tDLevel &deltaLevel = GetDeltaLevel(localLevel);\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tDeltaLoadSpawnedMonsters(deltaLevel);\r\n\t\tDeltaLoadMonsters(deltaLevel);\r\n\r\n\t\tauto localLevelIt = LocalLevels.find(localLevel);\r\n\t\tif (localLevelIt != LocalLevels.end())\r\n\t\t\tmemcpy(AutomapView, &localLevelIt->second, sizeof(AutomapView));\r\n\t\telse\r\n\t\t\tmemset(AutomapView, 0, sizeof(AutomapView));\r\n\r\n\t\tDeltaLoadObjects(deltaLevel);\r\n\t}\r\n\r\n\tDeltaLoadItems(deltaLevel);\r\n}\r\n\r\nvoid NetSendCmd(bool bHiPri, _cmd_id bCmd)\r\n{\r\n\tTCmd cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdSpawnMonster(Point position, Direction dir, uint16_t typeIndex, uint16_t monsterId, uint32_t seed, uint8_t golemOwnerPlayerId, uint8_t golemSpellLevel)\r\n{\r\n\tTCmdSpawnMonster cmd;\r\n\r\n\tcmd.bCmd = CMD_SPAWNMONSTER;\r\n\tcmd.x = position.x;\r\n\tcmd.y = position.y;\r\n\tcmd.dir = dir;\r\n\tcmd.typeIndex = Swap16LE(typeIndex);\r\n\tcmd.monsterId = Swap16LE(monsterId);\r\n\tcmd.seed = Swap32LE(seed);\r\n\tcmd.golemOwnerPlayerId = golemOwnerPlayerId;\r\n\tcmd.golemSpellLevel = golemSpellLevel;\r\n\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdLoc(uint8_t playerId, bool bHiPri, _cmd_id bCmd, Point position)\r\n{\r\n\tif (playerId == MyPlayerId && WasPlayerCmdAlreadyRequested(bCmd, position))\r\n\t\treturn;\r\n\r\n\tTCmdLoc cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.x = position.x;\r\n\tcmd.y = position.y;\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(playerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(playerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\tMyPlayer->UpdatePreviewCelSprite(bCmd, position, 0, 0);\r\n}\r\n\r\nvoid NetSendCmdLocParam1(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1)\r\n{\r\n\tif (WasPlayerCmdAlreadyRequested(bCmd, position, wParam1))\r\n\t\treturn;\r\n\r\n\tTCmdLocParam1 cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.x = position.x;\r\n\tcmd.y = position.y;\r\n\tcmd.wParam1 = Swap16LE(wParam1);\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\tMyPlayer->UpdatePreviewCelSprite(bCmd, position, wParam1, 0);\r\n}\r\n\r\nvoid NetSendCmdLocParam2(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1, uint16_t wParam2)\r\n{\r\n\tif (WasPlayerCmdAlreadyRequested(bCmd, position, wParam1, wParam2))\r\n\t\treturn;\r\n\r\n\tTCmdLocParam2 cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.x = position.x;\r\n\tcmd.y = position.y;\r\n\tcmd.wParam1 = Swap16LE(wParam1);\r\n\tcmd.wParam2 = Swap16LE(wParam2);\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\tMyPlayer->UpdatePreviewCelSprite(bCmd, position, wParam1, wParam2);\r\n}\r\n\r\nvoid NetSendCmdLocParam3(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1, uint16_t wParam2, uint16_t wParam3)\r\n{\r\n\tif (WasPlayerCmdAlreadyRequested(bCmd, position, wParam1, wParam2, wParam3))\r\n\t\treturn;\r\n\r\n\tTCmdLocParam3 cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.x = position.x;\r\n\tcmd.y = position.y;\r\n\tcmd.wParam1 = Swap16LE(wParam1);\r\n\tcmd.wParam2 = Swap16LE(wParam2);\r\n\tcmd.wParam3 = Swap16LE(wParam3);\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\tMyPlayer->UpdatePreviewCelSprite(bCmd, position, wParam1, wParam2);\r\n}\r\n\r\nvoid NetSendCmdLocParam4(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1, uint16_t wParam2, uint16_t wParam3, uint16_t wParam4)\r\n{\r\n\tif (WasPlayerCmdAlreadyRequested(bCmd, position, wParam1, wParam2, wParam3, wParam4))\r\n\t\treturn;\r\n\r\n\tTCmdLocParam4 cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.x = position.x;\r\n\tcmd.y = position.y;\r\n\tcmd.wParam1 = Swap16LE(wParam1);\r\n\tcmd.wParam2 = Swap16LE(wParam2);\r\n\tcmd.wParam3 = Swap16LE(wParam3);\r\n\tcmd.wParam4 = Swap16LE(wParam4);\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\tMyPlayer->UpdatePreviewCelSprite(bCmd, position, wParam1, wParam3);\r\n}\r\n\r\nvoid NetSendCmdParam1(bool bHiPri, _cmd_id bCmd, uint16_t wParam1)\r\n{\r\n\tif (WasPlayerCmdAlreadyRequested(bCmd, {}, wParam1))\r\n\t\treturn;\r\n\r\n\tTCmdParam1 cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.wParam1 = Swap16LE(wParam1);\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\tMyPlayer->UpdatePreviewCelSprite(bCmd, {}, wParam1, 0);\r\n}\r\n\r\nvoid NetSendCmdParam2(bool bHiPri, _cmd_id bCmd, uint16_t wParam1, uint16_t wParam2)\r\n{\r\n\tTCmdParam2 cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.wParam1 = Swap16LE(wParam1);\r\n\tcmd.wParam2 = Swap16LE(wParam2);\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdParam4(bool bHiPri, _cmd_id bCmd, uint16_t wParam1, uint16_t wParam2, uint16_t wParam3, uint16_t wParam4)\r\n{\r\n\tif (WasPlayerCmdAlreadyRequested(bCmd, {}, wParam1, wParam2, wParam3, wParam4))\r\n\t\treturn;\r\n\r\n\tTCmdParam4 cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.wParam1 = Swap16LE(wParam1);\r\n\tcmd.wParam2 = Swap16LE(wParam2);\r\n\tcmd.wParam3 = Swap16LE(wParam3);\r\n\tcmd.wParam4 = Swap16LE(wParam4);\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\r\n\tMyPlayer->UpdatePreviewCelSprite(bCmd, {}, wParam1, wParam2);\r\n}\r\n\r\nvoid NetSendCmdQuest(bool bHiPri, const Quest &quest)\r\n{\r\n\tTCmdQuest cmd;\r\n\tcmd.bCmd = CMD_SYNCQUEST;\r\n\tcmd.q = quest._qidx,\r\n\tcmd.qstate = quest._qactive;\r\n\tcmd.qlog = quest._qlog ? 1 : 0;\r\n\tcmd.qvar1 = quest._qvar1;\r\n\tcmd.qvar2 = quest._qvar2;\r\n\tcmd.qmsg = Swap16LE(quest._qmsg);\r\n\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdGItem(bool bHiPri, _cmd_id bCmd, const Player &player, uint8_t ii)\r\n{\r\n\tconst uint8_t pnum = player.getId();\r\n\r\n\tTCmdGItem cmd;\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.bPnum = pnum;\r\n\tcmd.bMaster = pnum;\r\n\tcmd.bLevel = GetLevelForMultiplayer(*MyPlayer);\r\n\tcmd.bCursitem = ii;\r\n\tcmd.dwTime = 0;\r\n\tcmd.x = Items[ii].position.x;\r\n\tcmd.y = Items[ii].position.y;\r\n\tPrepareItemForNetwork(Items[ii], cmd);\r\n\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdPItem(bool bHiPri, _cmd_id bCmd, Point position, const Item &item)\r\n{\r\n\tTCmdPItem cmd {};\r\n\r\n\tcmd.bCmd = bCmd;\r\n\tcmd.x = position.x;\r\n\tcmd.y = position.y;\r\n\tPrepareItemForNetwork(item, cmd);\r\n\r\n\tItemLimbo = item;\r\n\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdChItem(bool bHiPri, uint8_t bLoc, bool forceSpellChange)\r\n{\r\n\tTCmdChItem cmd {};\r\n\r\n\tconst Item &item = MyPlayer->InvBody[bLoc];\r\n\r\n\tcmd.bCmd = CMD_CHANGEPLRITEMS;\r\n\tcmd.bLoc = bLoc;\r\n\tcmd.forceSpell = forceSpellChange;\r\n\tPrepareItemForNetwork(item, cmd);\r\n\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdDelItem(bool bHiPri, uint8_t bLoc)\r\n{\r\n\tTCmdDelItem cmd;\r\n\r\n\tcmd.bLoc = bLoc;\r\n\tcmd.bCmd = CMD_DELPLRITEMS;\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSyncInvItem(const Player &player, int invListIndex)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tfor (int j = 0; j < InventoryGridCells; j++) {\r\n\t\tif (player.InvGrid[j] == invListIndex + 1) {\r\n\t\t\tNetSendCmdChInvItem(false, j);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NetSendCmdChInvItem(bool bHiPri, int invGridIndex)\r\n{\r\n\tTCmdChItem cmd {};\r\n\r\n\tconst int invListIndex = std::abs(MyPlayer->InvGrid[invGridIndex]) - 1;\r\n\tconst Item &item = MyPlayer->InvList[invListIndex];\r\n\r\n\tcmd.bCmd = CMD_CHANGEINVITEMS;\r\n\tcmd.bLoc = invGridIndex;\r\n\tPrepareItemForNetwork(item, cmd);\r\n\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdChBeltItem(bool bHiPri, int beltIndex)\r\n{\r\n\tTCmdChItem cmd {};\r\n\r\n\tconst Item &item = MyPlayer->SpdList[beltIndex];\r\n\r\n\tcmd.bCmd = CMD_CHANGEBELTITEMS;\r\n\tcmd.bLoc = beltIndex;\r\n\tPrepareItemForNetwork(item, cmd);\r\n\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdDamage(bool bHiPri, const Player &player, uint32_t dwDam, DamageType damageType)\r\n{\r\n\tTCmdDamage cmd;\r\n\r\n\tcmd.bCmd = CMD_PLRDAMAGE;\r\n\tcmd.bPlr = player.getId();\r\n\tcmd.dwDam = dwDam;\r\n\tcmd.damageType = damageType;\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdMonDmg(bool bHiPri, uint16_t wMon, uint32_t dwDam)\r\n{\r\n\tTCmdMonDamage cmd;\r\n\r\n\tcmd.bCmd = CMD_MONSTDAMAGE;\r\n\tcmd.wMon = wMon;\r\n\tcmd.dwDam = dwDam;\r\n\tif (bHiPri)\r\n\t\tNetSendHiPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n\telse\r\n\t\tNetSendLoPri(MyPlayerId, reinterpret_cast<std::byte *>(&cmd), sizeof(cmd));\r\n}\r\n\r\nvoid NetSendCmdString(uint32_t pmask, const char *pszStr)\r\n{\r\n\tTCmdString cmd;\r\n\r\n\tcmd.bCmd = CMD_STRING;\r\n\tCopyUtf8(cmd.str, pszStr, sizeof(cmd.str));\r\n\tmulti_send_msg_packet(pmask, reinterpret_cast<std::byte *>(&cmd), strlen(cmd.str) + 2);\r\n}\r\n\r\nvoid delta_close_portal(const Player &player)\r\n{\r\n\tmemset(&sgJunk.portal[player.getId()], 0xFF, sizeof(sgJunk.portal[player.getId()]));\r\n}\r\n\r\nbool ValidateCmdSize(size_t requiredCmdSize, size_t maxCmdSize, size_t playerId)\r\n{\r\n\tif (requiredCmdSize <= maxCmdSize)\r\n\t\treturn true;\r\n\r\n\tLog(\"Suspiciously small packet size, dropping player {}\", playerId);\r\n\tSNetDropPlayer(static_cast<uint8_t>(playerId), leaveinfo_t::LEAVE_DROP);\r\n\treturn false;\r\n}\r\n\r\nsize_t ParseCmd(uint8_t pnum, const TCmd *pCmd, size_t maxCmdSize)\r\n{\r\n\tsbLastCmd = pCmd->bCmd;\r\n\tif (sgwPackPlrOffsetTbl[pnum] != 0 && sbLastCmd != CMD_ACK_PLRINFO && sbLastCmd != CMD_SEND_PLRINFO)\r\n\t\treturn 0;\r\n\r\n\tPlayer &player = Players[pnum];\r\n\r\n#ifdef LOG_RECEIVED_MESSAGES\r\n\tLog(\"📥 {}\", CmdIdString(pCmd->bCmd));\r\n#endif\r\n\r\n\tswitch (pCmd->bCmd) {\r\n\tcase CMD_SYNCDATA:\r\n\t\treturn HandleCmd(OnSyncData, player, pCmd, maxCmdSize);\r\n\tcase CMD_WALKXY:\r\n\t\treturn HandleCmd(OnWalk, player, pCmd, maxCmdSize);\r\n\tcase CMD_ADDSTR:\r\n\t\treturn HandleCmd(OnAddStrength, player, pCmd, maxCmdSize);\r\n\tcase CMD_ADDDEX:\r\n\t\treturn HandleCmd(OnAddDexterity, player, pCmd, maxCmdSize);\r\n\tcase CMD_ADDMAG:\r\n\t\treturn HandleCmd(OnAddMagic, player, pCmd, maxCmdSize);\r\n\tcase CMD_ADDVIT:\r\n\t\treturn HandleCmd(OnAddVitality, player, pCmd, maxCmdSize);\r\n\tcase CMD_GOTOGETITEM:\r\n\t\treturn HandleCmd(OnGotoGetItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_REQUESTGITEM:\r\n\t\treturn HandleCmd(OnRequestGetItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_GETITEM:\r\n\t\treturn HandleCmd(OnGetItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_GOTOAGETITEM:\r\n\t\treturn HandleCmd(OnGotoAutoGetItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_REQUESTAGITEM:\r\n\t\treturn HandleCmd(OnRequestAutoGetItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_AGETITEM:\r\n\t\treturn HandleCmd(OnAutoGetItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_ITEMEXTRA:\r\n\t\treturn HandleCmd(OnItemExtra, player, pCmd, maxCmdSize);\r\n\tcase CMD_PUTITEM:\r\n\t\treturn HandleCmd(OnPutItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_SYNCPUTITEM:\r\n\t\treturn HandleCmd(OnSyncPutItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_SPAWNITEM:\r\n\t\treturn HandleCmd(OnSpawnItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_SATTACKXY:\r\n\t\treturn HandleCmd(OnStandingAttackTile, player, pCmd, maxCmdSize);\r\n\tcase CMD_RATTACKXY:\r\n\t\treturn HandleCmd(OnRangedAttackTile, player, pCmd, maxCmdSize);\r\n\tcase CMD_SPELLXYD:\r\n\t\treturn HandleCmd(OnSpellWall, player, pCmd, maxCmdSize);\r\n\tcase CMD_SPELLXY:\r\n\t\treturn HandleCmd(OnSpellTile, player, pCmd, maxCmdSize);\r\n\tcase CMD_OPOBJXY:\r\n\tcase CMD_DISARMXY:\r\n\tcase CMD_OPOBJT:\r\n\t\treturn HandleCmd(OnObjectTileAction, player, pCmd, maxCmdSize);\r\n\tcase CMD_ATTACKID:\r\n\t\treturn HandleCmd(OnAttackMonster, player, pCmd, maxCmdSize);\r\n\tcase CMD_ATTACKPID:\r\n\t\treturn HandleCmd(OnAttackPlayer, player, pCmd, maxCmdSize);\r\n\tcase CMD_RATTACKID:\r\n\t\treturn HandleCmd(OnRangedAttackMonster, player, pCmd, maxCmdSize);\r\n\tcase CMD_RATTACKPID:\r\n\t\treturn HandleCmd(OnRangedAttackPlayer, player, pCmd, maxCmdSize);\r\n\tcase CMD_SPELLID:\r\n\t\treturn HandleCmd(OnSpellMonster, player, pCmd, maxCmdSize);\r\n\tcase CMD_SPELLPID:\r\n\t\treturn HandleCmd(OnSpellPlayer, player, pCmd, maxCmdSize);\r\n\tcase CMD_KNOCKBACK:\r\n\t\treturn HandleCmd(OnKnockback, player, pCmd, maxCmdSize);\r\n\tcase CMD_RESURRECT:\r\n\t\treturn HandleCmd(OnResurrect, player, pCmd, maxCmdSize);\r\n\tcase CMD_HEALOTHER:\r\n\t\treturn HandleCmd(OnHealOther, player, pCmd, maxCmdSize);\r\n\tcase CMD_TALKXY:\r\n\t\treturn HandleCmd(OnTalkXY, player, pCmd, maxCmdSize);\r\n\tcase CMD_DEBUG:\r\n\t\treturn OnDebug(*pCmd);\r\n\tcase CMD_NEWLVL:\r\n\t\treturn HandleCmd(OnNewLevel, player, pCmd, maxCmdSize);\r\n\tcase CMD_WARP:\r\n\t\treturn HandleCmd(OnWarp, player, pCmd, maxCmdSize);\r\n\tcase CMD_MONSTDEATH:\r\n\t\treturn HandleCmd(OnMonstDeath, player, pCmd, maxCmdSize);\r\n\tcase CMD_REQUESTSPAWNGOLEM:\r\n\t\treturn HandleCmd(OnRequestSpawnGolem, player, pCmd, maxCmdSize);\r\n\tcase CMD_MONSTDAMAGE:\r\n\t\treturn HandleCmd(OnMonstDamage, player, pCmd, maxCmdSize);\r\n\tcase CMD_PLRDEAD:\r\n\t\treturn HandleCmd(OnPlayerDeath, player, pCmd, maxCmdSize);\r\n\tcase CMD_PLRALIVE:\r\n\t\treturn HandleCmd(OnPlayerAlive, player, pCmd, maxCmdSize);\r\n\tcase CMD_PLRDAMAGE:\r\n\t\treturn HandleCmd(OnPlayerDamage, player, pCmd, maxCmdSize);\r\n\tcase CMD_OPENDOOR:\r\n\tcase CMD_CLOSEDOOR:\r\n\tcase CMD_OPERATEOBJ:\r\n\t\treturn HandleCmd(OnOperateObject, player, pCmd, maxCmdSize);\r\n\tcase CMD_BREAKOBJ:\r\n\t\treturn HandleCmd(OnBreakObject, player, pCmd, maxCmdSize);\r\n\tcase CMD_CHANGEPLRITEMS:\r\n\t\treturn HandleCmd(OnChangePlayerItems, player, pCmd, maxCmdSize);\r\n\tcase CMD_DELPLRITEMS:\r\n\t\treturn HandleCmd(OnDeletePlayerItems, player, pCmd, maxCmdSize);\r\n\tcase CMD_CHANGEINVITEMS:\r\n\t\treturn HandleCmd(OnChangeInventoryItems, player, pCmd, maxCmdSize);\r\n\tcase CMD_DELINVITEMS:\r\n\t\treturn HandleCmd(OnDeleteInventoryItems, player, pCmd, maxCmdSize);\r\n\tcase CMD_CHANGEBELTITEMS:\r\n\t\treturn HandleCmd(OnChangeBeltItems, player, pCmd, maxCmdSize);\r\n\tcase CMD_DELBELTITEMS:\r\n\t\treturn HandleCmd(OnDeleteBeltItems, player, pCmd, maxCmdSize);\r\n\tcase CMD_PLRLEVEL:\r\n\t\treturn HandleCmd(OnPlayerLevel, player, pCmd, maxCmdSize);\r\n\tcase CMD_DROPITEM:\r\n\t\treturn HandleCmd(OnDropItem, player, pCmd, maxCmdSize);\r\n\tcase CMD_ACK_PLRINFO:\r\n\tcase CMD_SEND_PLRINFO:\r\n\t\treturn HandleCmd(OnSendPlayerInfo, player, pCmd, maxCmdSize);\r\n\tcase CMD_PLAYER_JOINLEVEL:\r\n\t\treturn HandleCmd(OnPlayerJoinLevel, player, pCmd, maxCmdSize);\r\n\tcase CMD_ACTIVATEPORTAL:\r\n\t\treturn HandleCmd(OnActivatePortal, player, pCmd, maxCmdSize);\r\n\tcase CMD_DEACTIVATEPORTAL:\r\n\t\treturn OnDeactivatePortal(*pCmd, player);\r\n\tcase CMD_RETOWN:\r\n\t\treturn OnRestartTown(*pCmd, player);\r\n\tcase CMD_SETSTR:\r\n\t\treturn HandleCmd(OnSetStrength, player, pCmd, maxCmdSize);\r\n\tcase CMD_SETMAG:\r\n\t\treturn HandleCmd(OnSetMagic, player, pCmd, maxCmdSize);\r\n\tcase CMD_SETDEX:\r\n\t\treturn HandleCmd(OnSetDexterity, player, pCmd, maxCmdSize);\r\n\tcase CMD_SETVIT:\r\n\t\treturn HandleCmd(OnSetVitality, player, pCmd, maxCmdSize);\r\n\tcase CMD_STRING:\r\n\t\treturn OnString(*pCmd, maxCmdSize, player);\r\n\tcase CMD_FRIENDLYMODE:\r\n\t\treturn OnFriendlyMode(*pCmd, player);\r\n\tcase CMD_SYNCQUEST:\r\n\t\treturn HandleCmd(OnSyncQuest, player, pCmd, maxCmdSize);\r\n\tcase CMD_CHEAT_EXPERIENCE:\r\n\t\treturn OnCheatExperience(*pCmd, player);\r\n\tcase CMD_CHANGE_SPELL_LEVEL:\r\n\t\treturn HandleCmd(OnChangeSpellLevel, player, pCmd, maxCmdSize);\r\n\tcase CMD_SETSHIELD:\r\n\t\treturn OnSetShield(*pCmd, player);\r\n\tcase CMD_REMSHIELD:\r\n\t\treturn OnRemoveShield(*pCmd, player);\r\n\tcase CMD_SETREFLECT:\r\n\t\treturn HandleCmd(OnSetReflect, player, pCmd, maxCmdSize);\r\n\tcase CMD_NAKRUL:\r\n\t\treturn OnNakrul(*pCmd);\r\n\tcase CMD_OPENHIVE:\r\n\t\treturn OnOpenHive(*pCmd, player);\r\n\tcase CMD_OPENGRAVE:\r\n\t\treturn OnOpenGrave(*pCmd);\r\n\tcase CMD_SPAWNMONSTER:\r\n\t\treturn HandleCmd(OnSpawnMonster, player, pCmd, maxCmdSize);\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (pCmd->bCmd < CMD_DLEVEL || pCmd->bCmd > CMD_DLEVEL_END) {\r\n\t\tLog(\"Unrecognized network message {}, dropping player {}\", static_cast<uint8_t>(pCmd->bCmd), pnum);\r\n\t\tSNetDropPlayer(pnum, leaveinfo_t::LEAVE_DROP);\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn HandleCmd(OnLevelData, player, pCmd, maxCmdSize);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/msg.h",
    "content": "/**\r\n * @file msg.h\r\n *\r\n * Interface of function for sending and receiving network messages.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"dvlnet/leaveinfo.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"items.h\"\r\n#include \"monster.h\"\r\n#include \"objects.h\"\r\n#include \"portal.h\"\r\n#include \"quests.h\"\r\n\r\nnamespace devilution {\r\n\r\nusing net::leaveinfo_t;\r\n\r\n#define MAX_SEND_STR_LEN 80\r\n\r\nenum _cmd_id : uint8_t {\r\n\t// Player mode standing.\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_STAND,\r\n\t// Walk to location.\r\n\t//\r\n\t// body (TCmdLoc)\r\n\tCMD_WALKXY,\r\n\t// Acknowledge receive of player info.\r\n\t//\r\n\t// body (TCmdPlrInfoHdr)\r\n\tCMD_ACK_PLRINFO,\r\n\t// Increment player strength.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t delta\r\n\tCMD_ADDSTR,\r\n\t// Increment player magic.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t delta\r\n\tCMD_ADDMAG,\r\n\t// Increment player dexterity.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t delta\r\n\tCMD_ADDDEX,\r\n\t// Increment player vitality.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t delta\r\n\tCMD_ADDVIT,\r\n\t// Lift item to hand.\r\n\t//\r\n\t// body (TCmdGItem)\r\n\tCMD_GETITEM,\r\n\t// Loot item to inventory.\r\n\t//\r\n\t// body (TCmdGItem)\r\n\tCMD_AGETITEM,\r\n\t// Drop item from hand on ground.\r\n\t//\r\n\t// body (TCmdPItem)\r\n\tCMD_PUTITEM,\r\n\t// Spawn item on ground (place quest items, drop dead player item, or drop\r\n\t// attempted loot item when inventory is full).\r\n\t// body (TCmdPItem)\r\n\tCMD_SPAWNITEM,\r\n\t// Range attack target location.\r\n\t//\r\n\t// body (TCmdLoc)\r\n\tCMD_RATTACKXY,\r\n\t// Cast spell at target location.\r\n\t//\r\n\t// body (TCmdLocParam4):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t spellID\r\n\t//    int16_t spellType\r\n\t//    int16_t spellLevel\r\n\t//    int16_t spellFrom\r\n\tCMD_SPELLXY,\r\n\t// Operate object at location.\r\n\t//\r\n\t// body (TCmdLoc):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\tCMD_OPOBJXY,\r\n\t// Disarm trap at location.\r\n\t//\r\n\t// body (TCmdLoc):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\tCMD_DISARMXY,\r\n\t// Attack target monster.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t monster_num\r\n\tCMD_ATTACKID,\r\n\t// Attack target player.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t player_num\r\n\tCMD_ATTACKPID,\r\n\t// Range attack target monster.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t monster_num\r\n\tCMD_RATTACKID,\r\n\t// Range attack target player.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t player_num\r\n\tCMD_RATTACKPID,\r\n\t// Cast spell on target monster.\r\n\t//\r\n\t// body (TCmdParam5):\r\n\t//    int16_t monster_num\r\n\t//    int16_t spellID\r\n\t//    int16_t spellType\r\n\t//    int16_t spellLevel\r\n\t//    int16_t spellFrom\r\n\tCMD_SPELLID,\r\n\t// Cast spell on target player.\r\n\t//\r\n\t// body (TCmdParam5):\r\n\t//    int16_t player_num\r\n\t//    int16_t spellID\r\n\t//    int16_t spellType\r\n\t//    int16_t spellLevel\r\n\t//    int16_t spellFrom\r\n\tCMD_SPELLPID,\r\n\t// Cast resurrect spell on target player.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t player_num\r\n\tCMD_RESURRECT,\r\n\t// Operate object using telekinesis.\r\n\t//\r\n\t// body (TCmdLoc):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\tCMD_OPOBJT,\r\n\t// Knockback target monster using telekinesis.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t monster_num\r\n\tCMD_KNOCKBACK,\r\n\t// Talk with towner at location.\r\n\t//\r\n\t// body (TCmdLocParam1):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t towner_num\r\n\tCMD_TALKXY,\r\n\t// Enter new dungeon level.\r\n\t//\r\n\t// body (TCmdParam2):\r\n\t//    int16_t trig_msg\r\n\t//    int16_t level\r\n\tCMD_NEWLVL,\r\n\t// Enter target portal.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t portal_num\r\n\tCMD_WARP,\r\n\t// Cheat: give player level up.\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_CHEAT_EXPERIENCE,\r\n\t// Change spell level of player.\r\n\t//\r\n\t// body (TCmdParam2)\r\n\t//    int16_t spellID\r\n\t//    int16_t spellLevel\r\n\tCMD_CHANGE_SPELL_LEVEL,\r\n\t// Debug command (nop).\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_DEBUG,\r\n\t// Synchronize data of unvisited dungeon level (state of objects, items and\r\n\t// monsters).\r\n\t//\r\n\t// body (TSyncHeader, TSyncMonster+)\r\n\tCMD_SYNCDATA,\r\n\t// Monster death at location.\r\n\t//\r\n\t// body (TCmdLocParam1):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t monster_num\r\n\tCMD_MONSTDEATH,\r\n\t// Damage target monster.\r\n\t//\r\n\t// body (TCmdParam2):\r\n\t//    int16_t monster_num\r\n\t//    int16_t damage\r\n\tCMD_MONSTDAMAGE,\r\n\t// Player death.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t ear_flag\r\n\tCMD_PLRDEAD,\r\n\t// Player resurrection.\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_PLRALIVE,\r\n\t// Lift item to hand request.\r\n\t//\r\n\t// body (TCmdGItem)\r\n\tCMD_REQUESTGITEM,\r\n\t// Loot item to inventory request.\r\n\t//\r\n\t// body (TCmdGItem)\r\n\tCMD_REQUESTAGITEM,\r\n\t// Lift item to hand at location.\r\n\t//\r\n\t// body (TCmdLocParam1):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t item_num\r\n\tCMD_GOTOGETITEM,\r\n\t// Loot item to inventory at location.\r\n\t//\r\n\t// body (TCmdLocParam1):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t item_num\r\n\tCMD_GOTOAGETITEM,\r\n\t// Open target door.\r\n\t//\r\n\t// body (TCmdLoc):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\tCMD_OPENDOOR,\r\n\t// Close target door.\r\n\t//\r\n\t// body (TCmdLoc):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\tCMD_CLOSEDOOR,\r\n\t// Operate object.\r\n\t//\r\n\t// body (TCmdLoc):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\tCMD_OPERATEOBJ,\r\n\t// Break object.\r\n\t//\r\n\t// body (TCmdLoc):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\tCMD_BREAKOBJ,\r\n\t// Equip item for player.\r\n\t//\r\n\t// body (TCmdChItem)\r\n\tCMD_CHANGEPLRITEMS,\r\n\t// Remove equipped item (destroy equipped item, swap equipped item, unequip\r\n\t// equipped item).\r\n\t//\r\n\t// body (TCmdDelItem)\r\n\tCMD_DELPLRITEMS,\r\n\t// Put item into player's backpack.\r\n\t//\r\n\t// body (TCmdChItem)\r\n\tCMD_CHANGEINVITEMS,\r\n\t// Remove item from player's backpack.\r\n\t//\r\n\t// body (TCmdParam1)\r\n\tCMD_DELINVITEMS,\r\n\t// Put item into player's belt.\r\n\t//\r\n\t// body (TCmdChItem)\r\n\tCMD_CHANGEBELTITEMS,\r\n\t// Remove item from player's belt.\r\n\t//\r\n\t// body (TCmdParam1)\r\n\tCMD_DELBELTITEMS,\r\n\t// Damage target player.\r\n\t//\r\n\t// body (TCmdDamage)\r\n\tCMD_PLRDAMAGE,\r\n\t// Set player level.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t clvl\r\n\tCMD_PLRLEVEL,\r\n\t// Place item on ground (e.g. monster item drop, chest/barrel/sarcophagus\r\n\t// item drop, etc).\r\n\t//\r\n\t// body (TCmdPItem)\r\n\tCMD_DROPITEM,\r\n\t// Player join dungeon level at location.\r\n\t//\r\n\t// body (TCmdLocParam1):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t dlvl\r\n\tCMD_PLAYER_JOINLEVEL,\r\n\t// Acknowledge receive of player info.\r\n\t//\r\n\t// body (TCmdPlrInfoHdr)\r\n\tCMD_SEND_PLRINFO,\r\n\t// Shift attack target location.\r\n\t//\r\n\t// body (TCmdLoc)\r\n\tCMD_SATTACKXY,\r\n\t// Activate town portal at location.\r\n\t//\r\n\t// body (TCmdLocParam3):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t level\r\n\t//    int16_t dtype\r\n\t//    int16_t is_setlevel\r\n\tCMD_ACTIVATEPORTAL,\r\n\t// Deactivate portal of player.\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_DEACTIVATEPORTAL,\r\n\t// Delta information for a dungeon level.\r\n\t//\r\n\t// body (TCmdPlrInfoHdr)\r\n\tCMD_DLEVEL,\r\n\t// Delta information of quest and portal states.\r\n\t//\r\n\t// body (TCmdPlrInfoHdr)\r\n\tCMD_DLEVEL_JUNK,\r\n\t// Delta information end marker.\r\n\t//\r\n\t// body (TCmdPlrInfoHdr)\r\n\tCMD_DLEVEL_END,\r\n\t// Cast heal other spell on target player.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t player_num\r\n\tCMD_HEALOTHER,\r\n\t// Chat message.\r\n\t//\r\n\t// body (TCmdString)\r\n\tCMD_STRING,\r\n\t// Toggles friendly Mode\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_FRIENDLYMODE,\r\n\t// Set player strength.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t str\r\n\tCMD_SETSTR,\r\n\t// Set player magic.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t mag\r\n\tCMD_SETMAG,\r\n\t// Set player dexterity.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t dex\r\n\tCMD_SETDEX,\r\n\t// Set player vitality.\r\n\t//\r\n\t// body (TCmdParam1):\r\n\t//    int16_t vit\r\n\tCMD_SETVIT,\r\n\t// Restart in town.\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_RETOWN,\r\n\t// Cast spell with direction at target location (e.g. firewall).\r\n\t//\r\n\t// body (TCmdLocParam5):\r\n\t//    int8_t x\r\n\t//    int8_t y\r\n\t//    int16_t spellID\r\n\t//    int16_t spellType\r\n\t//    int16_t direction\r\n\t//    int16_t spellLevel\r\n\t//    int16_t spellFrom\r\n\tCMD_SPELLXYD,\r\n\t// Track (dungeon generated) item looted by other player on dungeon level not\r\n\t// yet visited by player. The item is tracked as \"already taken\" in the delta\r\n\t// table, so it is not generated twice on the same dungeon level.\r\n\t//\r\n\t// body (TCmdGItem)\r\n\tCMD_ITEMEXTRA,\r\n\t// Synchronize item drop state.\r\n\t//\r\n\t// body (TCmdPItem)\r\n\tCMD_SYNCPUTITEM,\r\n\t// Synchronize quest state.\r\n\t//\r\n\t// body (TCmdQuest)\r\n\tCMD_SYNCQUEST,\r\n\t// Request to spawn a golem at target location.\r\n\t//\r\n\t// body (TCmdLocParam1)\r\n\tCMD_REQUESTSPAWNGOLEM,\r\n\t// Enable mana shield of player (render).\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_SETSHIELD,\r\n\t// Disable mana shield of player (don't render).\r\n\t//\r\n\t// body (TCmd)\r\n\tCMD_REMSHIELD,\r\n\tCMD_SETREFLECT,\r\n\tCMD_NAKRUL,\r\n\tCMD_OPENHIVE,\r\n\tCMD_OPENGRAVE,\r\n\t// Spawn a monster at target location.\r\n\t//\r\n\t// body (TCmdSpawnMonster)\r\n\tCMD_SPAWNMONSTER,\r\n\t// Fake command; set current player for succeeding mega pkt buffer messages.\r\n\t//\r\n\t// body (TFakeCmdPlr)\r\n\tFAKE_CMD_SETID,\r\n\t// Fake command; drop mega pkt buffer messages of specified player.\r\n\t//\r\n\t// body (TFakeDropPlr)\r\n\tFAKE_CMD_DROPID,\r\n\tNUM_CMDS,\r\n\tCMD_INVALID = 0xFF,\r\n};\r\n\r\n#pragma pack(push, 1)\r\nstruct TCmd {\r\n\t_cmd_id bCmd;\r\n};\r\n\r\nstruct TCmdLoc {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n};\r\n\r\nstruct TCmdLocParam1 {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\tuint16_t wParam1;\r\n};\r\n\r\nstruct TCmdLocParam2 {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\tuint16_t wParam1;\r\n\tuint16_t wParam2;\r\n};\r\n\r\nstruct TCmdLocParam3 {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\tuint16_t wParam1;\r\n\tuint16_t wParam2;\r\n\tuint16_t wParam3;\r\n};\r\n\r\nstruct TCmdLocParam4 {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\tuint16_t wParam1;\r\n\tuint16_t wParam2;\r\n\tuint16_t wParam3;\r\n\tuint16_t wParam4;\r\n};\r\n\r\nstruct TCmdLocParam5 {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\tuint16_t wParam1;\r\n\tuint16_t wParam2;\r\n\tuint16_t wParam3;\r\n\tuint16_t wParam4;\r\n\tuint16_t wParam5;\r\n};\r\n\r\nstruct TCmdParam1 {\r\n\t_cmd_id bCmd;\r\n\tuint16_t wParam1;\r\n};\r\n\r\nstruct TCmdParam2 {\r\n\t_cmd_id bCmd;\r\n\tuint16_t wParam1;\r\n\tuint16_t wParam2;\r\n};\r\n\r\nstruct TCmdParam4 {\r\n\t_cmd_id bCmd;\r\n\tuint16_t wParam1;\r\n\tuint16_t wParam2;\r\n\tuint16_t wParam3;\r\n\tuint16_t wParam4;\r\n};\r\n\r\nstruct TCmdSpawnMonster {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\tDirection dir;\r\n\tuint16_t typeIndex;\r\n\tuint16_t monsterId;\r\n\tuint32_t seed;\r\n\tuint8_t golemOwnerPlayerId;\r\n\tuint8_t golemSpellLevel;\r\n};\r\n\r\nstruct TCmdQuest {\r\n\t_cmd_id bCmd;\r\n\tint8_t q;\r\n\tquest_state qstate;\r\n\tuint8_t qlog;\r\n\tuint8_t qvar1;\r\n\tuint8_t qvar2;\r\n\tint16_t qmsg;\r\n};\r\n\r\nstruct TItemDef {\r\n\t_item_indexes wIndx;\r\n\tuint16_t wCI;\r\n\tuint32_t dwSeed;\r\n};\r\n\r\nstruct TItem {\r\n\t_item_indexes wIndx;\r\n\tuint16_t wCI;\r\n\tuint32_t dwSeed;\r\n\tuint8_t bId;\r\n\tuint8_t bDur;\r\n\tuint8_t bMDur;\r\n\tuint8_t bCh;\r\n\tuint8_t bMCh;\r\n\tuint16_t wValue;\r\n\tuint32_t dwBuff;\r\n\tuint16_t wToHit;\r\n\tuint16_t wMaxDam;\r\n};\r\n\r\nstruct TEar {\r\n\t_item_indexes wIndx;\r\n\tuint16_t wCI;\r\n\tuint32_t dwSeed;\r\n\tuint8_t bCursval;\r\n\tchar heroname[17];\r\n};\r\n\r\n/**\r\n * Represents an item being picked up from the ground\r\n */\r\nstruct TCmdGItem {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\r\n\tunion {\r\n\t\tTItemDef def;\r\n\t\tTItem item;\r\n\t\tTEar ear;\r\n\t};\r\n\r\n\tuint8_t bMaster;\r\n\tuint8_t bPnum;\r\n\tuint8_t bCursitem;\r\n\tuint8_t bLevel;\r\n\tint32_t dwTime;\r\n};\r\n\r\n/**\r\n * Represents an item being dropped onto the ground\r\n */\r\nstruct TCmdPItem {\r\n\t_cmd_id bCmd;\r\n\tuint8_t x;\r\n\tuint8_t y;\r\n\r\n\tunion {\r\n\t\tTItemDef def;\r\n\t\tTItem item;\r\n\t\tTEar ear;\r\n\t};\r\n\r\n\t/**\r\n\t * Items placed during dungeon generation\r\n\t */\r\n\tstatic constexpr _cmd_id FloorItem = CMD_STAND;\r\n\r\n\t/**\r\n\t * Floor items that have already been picked up\r\n\t */\r\n\tstatic constexpr _cmd_id PickedUpItem = CMD_WALKXY;\r\n\r\n\t/**\r\n\t * Items dropped by players, monsters, or objects and left on the floor of the dungeon\r\n\t */\r\n\tstatic constexpr _cmd_id DroppedItem = CMD_ACK_PLRINFO;\r\n};\r\n\r\nstruct TCmdChItem {\r\n\t_cmd_id bCmd;\r\n\tuint8_t bLoc;\r\n\tbool forceSpell;\r\n\r\n\tunion {\r\n\t\tTItemDef def;\r\n\t\tTItem item;\r\n\t\tTEar ear;\r\n\t};\r\n};\r\n\r\nstruct TCmdDelItem {\r\n\t_cmd_id bCmd;\r\n\tuint8_t bLoc;\r\n};\r\n\r\nstruct TCmdDamage {\r\n\t_cmd_id bCmd;\r\n\tuint8_t bPlr;\r\n\tuint32_t dwDam;\r\n\tDamageType damageType;\r\n};\r\n\r\nstruct TCmdMonDamage {\r\n\t_cmd_id bCmd;\r\n\tuint16_t wMon;\r\n\tuint32_t dwDam;\r\n};\r\n\r\nstruct TCmdPlrInfoHdr {\r\n\t_cmd_id bCmd;\r\n\tuint16_t wOffset;\r\n\tuint16_t wBytes;\r\n};\r\n\r\nstruct TCmdString {\r\n\t_cmd_id bCmd;\r\n\tchar str[MAX_SEND_STR_LEN];\r\n};\r\n\r\nstruct TFakeCmdPlr {\r\n\t_cmd_id bCmd;\r\n\tuint8_t bPlr;\r\n};\r\n\r\nstruct TFakeDropPlr {\r\n\t_cmd_id bCmd;\r\n\tuint8_t bPlr;\r\n\tuint32_t dwReason;\r\n};\r\n\r\nstruct TSyncHeader {\r\n\t_cmd_id bCmd;\r\n\tuint8_t bLevel;\r\n\tuint16_t wLen;\r\n\tuint8_t bItemI;\r\n\tuint8_t bItemX;\r\n\tuint8_t bItemY;\r\n\tuint16_t wItemIndx;\r\n\tuint16_t wItemCI;\r\n\tuint32_t dwItemSeed;\r\n\tuint8_t bItemId;\r\n\tuint8_t bItemDur;\r\n\tuint8_t bItemMDur;\r\n\tuint8_t bItemCh;\r\n\tuint8_t bItemMCh;\r\n\tuint16_t wItemVal;\r\n\tuint32_t dwItemBuff;\r\n\tuint8_t bPInvLoc;\r\n\tuint16_t wPInvIndx;\r\n\tuint16_t wPInvCI;\r\n\tuint32_t dwPInvSeed;\r\n\tuint8_t bPInvId;\r\n};\r\n\r\nstruct TSyncMonster {\r\n\tuint8_t _mndx;\r\n\tuint8_t _mx;\r\n\tuint8_t _my;\r\n\tuint8_t _menemy;\r\n\tuint8_t _mdelta;\r\n\tint32_t _mhitpoints;\r\n\tint8_t mWhoHit;\r\n};\r\n\r\nstruct TPktHdr {\r\n\tuint8_t px;\r\n\tuint8_t py;\r\n\tuint8_t targx;\r\n\tuint8_t targy;\r\n\tint32_t php;\r\n\tint32_t pmhp;\r\n\tint32_t mana;\r\n\tint32_t maxmana;\r\n\tuint8_t bstr;\r\n\tuint8_t bmag;\r\n\tuint8_t bdex;\r\n\tuint8_t pdir;\r\n\tuint16_t wCheck;\r\n\tuint16_t wLen;\r\n};\r\n\r\nstruct TPkt {\r\n\tTPktHdr hdr;\r\n\tstd::byte body[493];\r\n};\r\n#pragma pack(pop)\r\n\r\nextern uint8_t gbBufferMsgs;\r\nextern int dwRecCount;\r\n\r\nvoid PrepareItemForNetwork(const Item &item, TItem &messageItem);\r\nvoid PrepareEarForNetwork(const Item &item, TEar &ear);\r\nvoid RecreateItem(const Player &player, const TItem &messageItem, Item &item);\r\nvoid msg_send_drop_pkt(uint8_t pnum, leaveinfo_t reason);\r\nbool msg_wait_resync();\r\nvoid run_delta_info();\r\nvoid DeltaExportData(uint8_t pnum);\r\nvoid DeltaSyncJunk();\r\nvoid delta_init();\r\nvoid DeltaClearLevel(uint8_t level);\r\nvoid delta_kill_monster(const Monster &monster, Point position, const Player &player);\r\nvoid delta_monster_hp(const Monster &monster, const Player &player);\r\nvoid delta_sync_monster(const TSyncMonster &monsterSync, uint8_t level);\r\nuint8_t GetLevelForMultiplayer(const Player &player);\r\nbool IsValidLevelForMultiplayer(uint8_t level);\r\nbool IsValidLevel(uint8_t level, bool isSetLevel);\r\nvoid DeltaAddItem(int ii);\r\nvoid DeltaSaveLevel();\r\nvoid DeltaLoadLevel();\r\n/** @brief Clears last sent player command for the local player. This is used when a game tick changes. */\r\nvoid ClearLastSentPlayerCmd();\r\nvoid NetSendCmd(bool bHiPri, _cmd_id bCmd);\r\nvoid NetSendCmdSpawnMonster(Point position, Direction dir, uint16_t typeIndex, uint16_t monsterId, uint32_t seed, uint8_t golemOwnerPlayerId, uint8_t golemSpellLevel);\r\nvoid NetSendCmdLoc(uint8_t playerId, bool bHiPri, _cmd_id bCmd, Point position);\r\nvoid NetSendCmdLocParam1(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1);\r\nvoid NetSendCmdLocParam2(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1, uint16_t wParam2);\r\nvoid NetSendCmdLocParam3(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1, uint16_t wParam2, uint16_t wParam3);\r\nvoid NetSendCmdLocParam4(bool bHiPri, _cmd_id bCmd, Point position, uint16_t wParam1, uint16_t wParam2, uint16_t wParam3, uint16_t wParam4);\r\nvoid NetSendCmdParam1(bool bHiPri, _cmd_id bCmd, uint16_t wParam1);\r\nvoid NetSendCmdParam2(bool bHiPri, _cmd_id bCmd, uint16_t wParam1, uint16_t wParam2);\r\nvoid NetSendCmdParam4(bool bHiPri, _cmd_id bCmd, uint16_t wParam1, uint16_t wParam2, uint16_t wParam3, uint16_t wParam4);\r\nvoid NetSendCmdQuest(bool bHiPri, const Quest &quest);\r\nvoid NetSendCmdGItem(bool bHiPri, _cmd_id bCmd, const Player &player, uint8_t ii);\r\nvoid NetSendCmdPItem(bool bHiPri, _cmd_id bCmd, Point position, const Item &item);\r\nvoid NetSyncInvItem(const Player &player, int invListIndex);\r\nvoid NetSendCmdChItem(bool bHiPri, uint8_t bLoc, bool forceSpellChange = false);\r\nvoid NetSendCmdDelItem(bool bHiPri, uint8_t bLoc);\r\nvoid NetSendCmdChInvItem(bool bHiPri, int invGridIndex);\r\nvoid NetSendCmdChBeltItem(bool bHiPri, int beltIndex);\r\nvoid NetSendCmdDamage(bool bHiPri, const Player &player, uint32_t dwDam, DamageType damageType);\r\nvoid NetSendCmdMonDmg(bool bHiPri, uint16_t wMon, uint32_t dwDam);\r\nvoid NetSendCmdString(uint32_t pmask, const char *pszStr);\r\nvoid delta_close_portal(const Player &player);\r\nbool ValidateCmdSize(size_t requiredCmdSize, size_t maxCmdSize, size_t playerId);\r\nsize_t ParseCmd(uint8_t pnum, const TCmd *pCmd, size_t maxCmdSize);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/multi.cpp",
    "content": "/**\r\n * @file multi.cpp\r\n *\r\n * Implementation of functions for keeping multiplaye games in sync.\r\n */\r\n#include \"multi.h\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_endian.h>\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <config.h>\r\n#include <fmt/format.h>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"diablo.h\"\r\n#include \"engine/demomode.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"menu.h\"\r\n#include \"monster.h\"\r\n#include \"msg.h\"\r\n#include \"nthread.h\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"player.h\"\r\n#include \"plrmsg.h\"\r\n#include \"qol/chatlog.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"sync.h\"\r\n#include \"tmsg.h\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool gbSomebodyWonGameKludge;\r\nuint16_t sgwPackPlrOffsetTbl[MAX_PLRS];\r\nbool sgbPlayerTurnBitTbl[MAX_PLRS];\r\nbool sgbPlayerLeftGameTbl[MAX_PLRS];\r\nbool shareNextHighPriorityMessage;\r\nuint8_t gbActivePlayers;\r\nbool gbGameDestroyed;\r\nbool sgbSendDeltaTbl[MAX_PLRS];\r\nGameData sgGameInitInfo;\r\nbool gbSelectProvider;\r\nint sglTimeoutStart;\r\nleaveinfo_t sgdwPlayerLeftReasonTbl[MAX_PLRS];\r\nuint32_t sgdwGameLoops;\r\n/**\r\n * Specifies the maximum number of players in a game, where 1\r\n * represents a single player game and 4 represents a multi player game.\r\n */\r\nbool gbIsMultiplayer;\r\nbool sgbTimeout;\r\nstd::string GameName;\r\nstd::string GamePassword;\r\nbool PublicGame;\r\nuint8_t gbDeltaSender;\r\nbool sgbNetInited;\r\nuint32_t player_state[MAX_PLRS];\r\nUint32 playerInfoTimers[MAX_PLRS];\r\nbool IsLoopback;\r\n\r\n/**\r\n * Contains the set of supported event types supported by the multiplayer\r\n * event handler.\r\n */\r\nconst event_type EventTypes[3] = {\r\n\tEVENT_TYPE_PLAYER_LEAVE_GAME,\r\n\tEVENT_TYPE_PLAYER_CREATE_GAME,\r\n\tEVENT_TYPE_PLAYER_MESSAGE\r\n};\r\n\r\nvoid GameData::swapLE()\r\n{\r\n\tsize = Swap32LE(size);\r\n\tprogramid = Swap32LE(programid);\r\n\tgameSeed[0] = Swap32LE(gameSeed[0]);\r\n\tgameSeed[1] = Swap32LE(gameSeed[1]);\r\n\tgameSeed[2] = Swap32LE(gameSeed[2]);\r\n\tgameSeed[3] = Swap32LE(gameSeed[3]);\r\n}\r\n\r\nnamespace {\r\n\r\nstruct TBuffer {\r\n\tsize_t dwNextWriteOffset;\r\n\tstd::byte bData[4096];\r\n};\r\n\r\nTBuffer highPriorityBuffer;\r\nTBuffer lowPriorityBuffer;\r\n\r\nconstexpr uint16_t HeaderCheckVal =\r\n#if SDL_BYTEORDER == SDL_LIL_ENDIAN\r\n    LoadBE16(\"ip\");\r\n#else\r\n    LoadLE16(\"ip\");\r\n#endif\r\n\r\nuint32_t sgbSentThisCycle;\r\n\r\nvoid BufferInit(TBuffer *pBuf)\r\n{\r\n\tpBuf->dwNextWriteOffset = 0;\r\n\tpBuf->bData[0] = std::byte { 0 };\r\n}\r\n\r\nvoid CopyPacket(TBuffer *buf, const std::byte *packet, size_t size)\r\n{\r\n\tif (buf->dwNextWriteOffset + size + 2 > 0x1000) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tstd::byte *p = &buf->bData[buf->dwNextWriteOffset];\r\n\tbuf->dwNextWriteOffset += size + 1;\r\n\t*p = static_cast<std::byte>(size);\r\n\tp++;\r\n\tmemcpy(p, packet, size);\r\n\tp[size] = std::byte { 0 };\r\n}\r\n\r\nstd::byte *CopyBufferedPackets(std::byte *destination, TBuffer *source, size_t *size)\r\n{\r\n\tif (source->dwNextWriteOffset != 0) {\r\n\t\tstd::byte *srcPtr = source->bData;\r\n\t\twhile (true) {\r\n\t\t\tauto chunkSize = static_cast<uint8_t>(*srcPtr);\r\n\t\t\tif (chunkSize == 0)\r\n\t\t\t\tbreak;\r\n\t\t\tif (chunkSize > *size)\r\n\t\t\t\tbreak;\r\n\t\t\tsrcPtr++;\r\n\t\t\tmemcpy(destination, srcPtr, chunkSize);\r\n\t\t\tdestination += chunkSize;\r\n\t\t\tsrcPtr += chunkSize;\r\n\t\t\t*size -= chunkSize;\r\n\t\t}\r\n\t\tmemmove(source->bData, srcPtr, (source->bData - srcPtr) + source->dwNextWriteOffset + 1);\r\n\t\tsource->dwNextWriteOffset += source->bData - srcPtr;\r\n\t\treturn destination;\r\n\t}\r\n\treturn destination;\r\n}\r\n\r\nvoid NetReceivePlayerData(TPkt *pkt)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tPoint target = myPlayer.GetTargetPosition();\r\n\t// Don't send desired target position when we will change our position soon.\r\n\t// This prevents a desync where the remote client starts a walking to the old target position when the teleport is finished but the the new position isn't received yet.\r\n\tif (myPlayer._pmode == PM_SPELL && IsAnyOf(myPlayer.executedSpell.spellId, SpellID::Teleport, SpellID::Phasing, SpellID::Warp))\r\n\t\ttarget = {};\r\n\r\n\tpkt->hdr.wCheck = HeaderCheckVal;\r\n\tpkt->hdr.px = myPlayer.position.tile.x;\r\n\tpkt->hdr.py = myPlayer.position.tile.y;\r\n\tpkt->hdr.targx = target.x;\r\n\tpkt->hdr.targy = target.y;\r\n\tpkt->hdr.php = Swap32LE(myPlayer._pHitPoints);\r\n\tpkt->hdr.pmhp = Swap32LE(myPlayer._pMaxHP);\r\n\tpkt->hdr.mana = Swap32LE(myPlayer._pMana);\r\n\tpkt->hdr.maxmana = Swap32LE(myPlayer._pMaxMana);\r\n\tpkt->hdr.bstr = myPlayer._pBaseStr;\r\n\tpkt->hdr.bmag = myPlayer._pBaseMag;\r\n\tpkt->hdr.bdex = myPlayer._pBaseDex;\r\n\tpkt->hdr.pdir = static_cast<uint8_t>(myPlayer._pdir);\r\n}\r\n\r\nbool IsNetPlayerValid(const Player &player)\r\n{\r\n\t// we no longer check character level here, players with out-of-range clevels are not allowed to join the game and we don't observe change clevel messages that would set it out of range\r\n\t// (there's no code path that would result in _pLevel containing an out of range value in the DevilutionX code)\r\n\treturn static_cast<uint8_t>(player._pClass) < GetNumPlayerClasses()\r\n\t    && player.plrlevel < NUMLEVELS\r\n\t    && InDungeonBounds(player.position.tile)\r\n\t    && !std::string_view(player._pName).empty();\r\n}\r\n\r\nvoid CheckPlayerInfoTimeouts()\r\n{\r\n\tfor (uint8_t i = 0; i < Players.size(); i++) {\r\n\t\tPlayer &player = Players[i];\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tUint32 &timerStart = playerInfoTimers[i];\r\n\t\tconst bool isPlayerConnected = (player_state[i] & PS_CONNECTED) != 0;\r\n\t\tconst bool isPlayerValid = isPlayerConnected && IsNetPlayerValid(player);\r\n\t\tif (isPlayerConnected && !isPlayerValid && timerStart == 0) {\r\n\t\t\ttimerStart = SDL_GetTicks();\r\n\t\t}\r\n\t\tif (!isPlayerConnected || isPlayerValid) {\r\n\t\t\ttimerStart = 0;\r\n\t\t}\r\n\r\n\t\tif (timerStart == 0) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// Time the player out after 15 seconds\r\n\t\t// if we do not receive valid player info\r\n\t\tif (SDL_GetTicks() - timerStart >= 15000) {\r\n\t\t\tSNetDropPlayer(i, leaveinfo_t::LEAVE_DROP);\r\n\t\t\ttimerStart = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SendPacket(uint8_t playerId, const std::byte *packet, size_t size)\r\n{\r\n\tTPkt pkt;\r\n\r\n\tNetReceivePlayerData(&pkt);\r\n\tconst size_t sizeWithheader = size + sizeof(pkt.hdr);\r\n\tpkt.hdr.wLen = Swap16LE(static_cast<uint16_t>(sizeWithheader));\r\n\tmemcpy(pkt.body, packet, size);\r\n\tif (!SNetSendMessage(playerId, &pkt.hdr, sizeWithheader))\r\n\t\tnthread_terminate_game(\"SNetSendMessage0\");\r\n}\r\n\r\nvoid MonsterSeeds()\r\n{\r\n\tsgdwGameLoops++;\r\n\tconst uint32_t seed = (sgdwGameLoops >> 8) | (sgdwGameLoops << 24);\r\n\tfor (uint32_t i = 0; i < MaxMonsters; i++)\r\n\t\tMonsters[i].aiSeed = seed + i;\r\n}\r\n\r\nvoid HandleTurnUpperBit(uint8_t pnum)\r\n{\r\n\tuint8_t i;\r\n\r\n\tfor (i = 0; i < Players.size(); i++) {\r\n\t\tif ((player_state[i] & PS_CONNECTED) != 0 && i != pnum)\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif (MyPlayerId == i) {\r\n\t\tsgbSendDeltaTbl[pnum] = true;\r\n\t} else if (pnum == MyPlayerId) {\r\n\t\tgbDeltaSender = i;\r\n\t}\r\n}\r\n\r\nvoid ParseTurn(uint8_t pnum, uint32_t turn)\r\n{\r\n\tif ((turn & 0x80000000) != 0)\r\n\t\tHandleTurnUpperBit(pnum);\r\n\tuint32_t absTurns = turn & 0x7FFFFFFF;\r\n\tif (sgbSentThisCycle < gdwTurnsInTransit + absTurns) {\r\n\t\tif (absTurns >= 0x7FFFFFFF)\r\n\t\t\tabsTurns &= 0xFFFF;\r\n\t\tsgbSentThisCycle = absTurns + gdwTurnsInTransit;\r\n\t\tsgdwGameLoops = 4 * absTurns * sgbNetUpdateRate;\r\n\t}\r\n}\r\n\r\nvoid PlayerLeftMsg(Player &player, bool left)\r\n{\r\n\tif (&player == InspectPlayer)\r\n\t\tInspectPlayer = MyPlayer;\r\n\r\n\tif (&player == MyPlayer)\r\n\t\treturn;\r\n\tif (!player.plractive)\r\n\t\treturn;\r\n\r\n\tFixPlrWalkTags(player);\r\n\tRemovePortalMissile(player);\r\n\tDeactivatePortal(player);\r\n\tdelta_close_portal(player);\r\n\tRemoveEnemyReferences(player);\r\n\tRemovePlrMissiles(player);\r\n\tif (left) {\r\n\t\tconst leaveinfo_t leaveReason = sgdwPlayerLeftReasonTbl[player.getId()];\r\n\t\tconst std::string reasonDescription = DescribeLeaveReason(leaveReason);\r\n\t\tstd::string_view pszFmt = _(\"Player '{:s}' just left the game\");\r\n\t\tswitch (leaveReason) {\r\n\t\tcase leaveinfo_t::LEAVE_EXIT:\r\n\t\t\tbreak;\r\n\t\tcase leaveinfo_t::LEAVE_ENDING:\r\n\t\t\tpszFmt = _(\"Player '{:s}' killed Diablo and left the game!\");\r\n\t\t\tgbSomebodyWonGameKludge = true;\r\n\t\t\tbreak;\r\n\t\tcase leaveinfo_t::LEAVE_DROP:\r\n\t\t\tpszFmt = _(\"Player '{:s}' dropped due to timeout\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (!IsLoopback) {\r\n\t\t\tconst uint8_t remainingPlayers = gbActivePlayers > 0 ? gbActivePlayers - 1 : 0;\r\n\t\t\tif (player._pName[0] != '\\0')\r\n\t\t\t\tLogInfo(\"Player '{}' left the {} game ({}, {}/{} players)\", player._pName, ConnectionNames[provider], reasonDescription, remainingPlayers, MAX_PLRS);\r\n\t\t\telse\r\n\t\t\t\tLogInfo(\"Player left the {} game ({}, {}/{} players)\", ConnectionNames[provider], reasonDescription, remainingPlayers, MAX_PLRS);\r\n\t\t}\r\n\t\tEventPlrMsg(fmt::format(fmt::runtime(pszFmt), player._pName));\r\n\t}\r\n\tplayer.plractive = false;\r\n\tplayer._pName[0] = '\\0';\r\n\tResetPlayerGFX(player);\r\n\tgbActivePlayers--;\r\n}\r\n\r\nvoid ClearPlayerLeftState()\r\n{\r\n\tfor (uint8_t i = 0; i < Players.size(); i++) {\r\n\t\tif (sgbPlayerLeftGameTbl[i]) {\r\n\t\t\tif (gbBufferMsgs == 1)\r\n\t\t\t\tmsg_send_drop_pkt(i, sgdwPlayerLeftReasonTbl[i]);\r\n\t\t\telse\r\n\t\t\t\tPlayerLeftMsg(Players[i], true);\r\n\r\n\t\t\tsgbPlayerLeftGameTbl[i] = false;\r\n\t\t\tsgdwPlayerLeftReasonTbl[i] = static_cast<leaveinfo_t>(0);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CheckDropPlayer()\r\n{\r\n\tfor (uint8_t i = 0; i < Players.size(); i++) {\r\n\t\tif ((player_state[i] & PS_ACTIVE) == 0 && (player_state[i] & PS_CONNECTED) != 0) {\r\n\t\t\tSNetDropPlayer(i, leaveinfo_t::LEAVE_DROP);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid BeginTimeout()\r\n{\r\n\tif (!sgbTimeout) {\r\n\t\treturn;\r\n\t}\r\n#ifdef _DEBUG\r\n\tif (DebugDisableNetworkTimeout) {\r\n\t\treturn;\r\n\t}\r\n#endif\r\n\r\n\tuint32_t nTicks = SDL_GetTicks() - sglTimeoutStart;\r\n\tif (nTicks > 20000) {\r\n\t\tgbRunGame = false;\r\n\t\treturn;\r\n\t}\r\n\tif (nTicks < 10000) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tCheckDropPlayer();\r\n}\r\n\r\nvoid HandleAllPackets(uint8_t pnum, const std::byte *data, size_t size)\r\n{\r\n\tfor (size_t offset = 0; offset < size;) {\r\n\t\tconst size_t messageSize = ParseCmd(pnum, reinterpret_cast<const TCmd *>(&data[offset]), size - offset);\r\n\t\tif (messageSize == 0) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\toffset += messageSize;\r\n\t}\r\n}\r\n\r\nvoid ProcessTmsgs()\r\n{\r\n\twhile (true) {\r\n\t\tstd::unique_ptr<std::byte[]> msg;\r\n\t\tconst uint8_t size = tmsg_get(&msg);\r\n\t\tif (size == 0)\r\n\t\t\tbreak;\r\n\r\n\t\tHandleAllPackets(MyPlayerId, msg.get(), size);\r\n\t}\r\n}\r\n\r\nvoid SendPlayerInfo(uint8_t pnum, _cmd_id cmd)\r\n{\r\n\tPlayerNetPack packed;\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tPackNetPlayer(packed, myPlayer);\r\n\tmulti_send_zero_packet(pnum, cmd, reinterpret_cast<std::byte *>(&packed), sizeof(PlayerNetPack));\r\n}\r\n\r\nvoid SetupLocalPositions()\r\n{\r\n\tcurrlevel = 0;\r\n\tleveltype = DTYPE_TOWN;\r\n\tsetlevel = false;\r\n\r\n\tconst WorldTilePosition spawns[9] = { { 75, 68 }, { 77, 70 }, { 75, 70 }, { 77, 68 }, { 76, 69 }, { 75, 69 }, { 76, 68 }, { 77, 69 }, { 76, 70 } };\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tmyPlayer.position.tile = spawns[MyPlayerId];\r\n\tmyPlayer.position.future = myPlayer.position.tile;\r\n\tmyPlayer.setLevel(currlevel);\r\n\tmyPlayer._pLvlChanging = true;\r\n\tmyPlayer.pLvlLoad = 0;\r\n\tmyPlayer._pmode = PM_NEWLVL;\r\n\tmyPlayer.destAction = ACTION_NONE;\r\n}\r\n\r\nvoid HandleEvents(_SNETEVENT *pEvt)\r\n{\r\n\tconst uint32_t playerId = pEvt->playerid;\r\n\tswitch (pEvt->eventid) {\r\n\tcase EVENT_TYPE_PLAYER_CREATE_GAME: {\r\n\t\tGameData gameData;\r\n\t\tif (pEvt->databytes < sizeof(GameData))\r\n\t\t\tapp_fatal(StrCat(\"Invalid packet size (<sizeof(GameData)): \", pEvt->databytes));\r\n\t\tstd::memcpy(&gameData, pEvt->data, sizeof(gameData));\r\n\t\tgameData.swapLE();\r\n\t\tif (gameData.size != sizeof(GameData))\r\n\t\t\tapp_fatal(StrCat(\"Invalid size of game data: \", gameData.size));\r\n\t\tsgGameInitInfo = gameData;\r\n\t\tsgbPlayerTurnBitTbl[playerId] = true;\r\n\t} break;\r\n\tcase EVENT_TYPE_PLAYER_LEAVE_GAME: {\r\n\t\tsgbPlayerLeftGameTbl[playerId] = true;\r\n\t\tsgbPlayerTurnBitTbl[playerId] = false;\r\n\r\n\t\tuint32_t leftReasonRaw = 0;\r\n\t\tif (pEvt->data != nullptr && pEvt->databytes >= sizeof(leftReasonRaw)) {\r\n\t\t\tstd::memcpy(&leftReasonRaw, pEvt->data, sizeof(leftReasonRaw));\r\n\t\t\tleftReasonRaw = Swap32LE(leftReasonRaw);\r\n\t\t}\r\n\t\tleaveinfo_t leftReason = static_cast<leaveinfo_t>(leftReasonRaw);\r\n\t\tsgdwPlayerLeftReasonTbl[playerId] = leftReason;\r\n\t\tif (leftReason == leaveinfo_t::LEAVE_ENDING)\r\n\t\t\tgbSomebodyWonGameKludge = true;\r\n\r\n\t\tsgbSendDeltaTbl[playerId] = false;\r\n\r\n\t\tif (gbDeltaSender == playerId)\r\n\t\t\tgbDeltaSender = MAX_PLRS;\r\n\t} break;\r\n\tcase EVENT_TYPE_PLAYER_MESSAGE: {\r\n\t\tstd::string_view data(static_cast<const char *>(pEvt->data), pEvt->databytes);\r\n\t\tif (const size_t nullPos = data.find('\\0'); nullPos != std::string_view::npos) {\r\n\t\t\tdata.remove_suffix(data.size() - nullPos);\r\n\t\t}\r\n\t\tEventPlrMsg(data);\r\n\t} break;\r\n\t}\r\n}\r\n\r\nvoid RegisterNetEventHandlers()\r\n{\r\n\tfor (auto eventType : EventTypes) {\r\n\t\tif (!SNetRegisterEventHandler(eventType, HandleEvents)) {\r\n\t\t\tapp_fatal(StrCat(\"SNetRegisterEventHandler:\\n\", SDL_GetError()));\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid UnregisterNetEventHandlers()\r\n{\r\n\tfor (auto eventType : EventTypes) {\r\n\t\tSNetUnregisterEventHandler(eventType);\r\n\t}\r\n}\r\n\r\nbool InitSingle(GameData *gameData)\r\n{\r\n\tPlayers.resize(1);\r\n\r\n\tif (!SNetInitializeProvider(SELCONN_LOOPBACK, gameData)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint unused = 0;\r\n\tGameData gameInitInfo = sgGameInitInfo;\r\n\tgameInitInfo.swapLE();\r\n\tif (!SNetCreateGame(\"local\", \"local\", reinterpret_cast<char *>(&gameInitInfo), sizeof(gameInitInfo), &unused)) {\r\n\t\tapp_fatal(StrCat(\"SNetCreateGame1:\\n\", SDL_GetError()));\r\n\t}\r\n\r\n\tMyPlayerId = 0;\r\n\tMyPlayer = &Players[MyPlayerId];\r\n\tInspectPlayer = MyPlayer;\r\n\tgbIsMultiplayer = false;\r\n\r\n\tpfile_read_player_from_save(gSaveNumber, *MyPlayer);\r\n\r\n\treturn true;\r\n}\r\n\r\nbool InitMulti(GameData *gameData)\r\n{\r\n\tPlayers.resize(MAX_PLRS);\r\n\r\n\tint playerId;\r\n\r\n\twhile (true) {\r\n\t\tif (gbSelectProvider && !UiSelectProvider(gameData)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tRegisterNetEventHandlers();\r\n\t\tif (UiSelectGame(gameData, &playerId))\r\n\t\t\tbreak;\r\n\r\n\t\tgbSelectProvider = true;\r\n\t}\r\n\r\n\tif (static_cast<size_t>(playerId) >= Players.size()) {\r\n\t\treturn false;\r\n\t}\r\n\tMyPlayerId = playerId;\r\n\tMyPlayer = &Players[MyPlayerId];\r\n\tInspectPlayer = MyPlayer;\r\n\tgbIsMultiplayer = true;\r\n\r\n\tpfile_read_player_from_save(gSaveNumber, *MyPlayer);\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nDVL_API_FOR_TEST std::string DescribeLeaveReason(leaveinfo_t leaveReason)\r\n{\r\n\tswitch (leaveReason) {\r\n\tcase leaveinfo_t::LEAVE_EXIT:\r\n\t\treturn \"normal exit\";\r\n\tcase leaveinfo_t::LEAVE_ENDING:\r\n\t\treturn \"Diablo defeated\";\r\n\tcase leaveinfo_t::LEAVE_DROP:\r\n\t\treturn \"connection timeout\";\r\n\tdefault:\r\n\t\treturn fmt::format(\"code 0x{:08X}\", static_cast<uint32_t>(leaveReason));\r\n\t}\r\n}\r\n\r\nstd::string FormatGameSeed(const uint32_t gameSeed[4])\r\n{\r\n\treturn fmt::format(\"{:08X}{:08X}{:08X}{:08X}\",\r\n\t    gameSeed[0], gameSeed[1], gameSeed[2], gameSeed[3]);\r\n}\r\n\r\nvoid InitGameInfo()\r\n{\r\n\tconst xoshiro128plusplus gameGenerator = ReserveSeedSequence();\r\n\tgameGenerator.save(sgGameInitInfo.gameSeed);\r\n\r\n\tsgGameInitInfo.size = sizeof(sgGameInitInfo);\r\n\tsgGameInitInfo.programid = GAME_ID;\r\n\tsgGameInitInfo.versionMajor = PROJECT_VERSION_MAJOR;\r\n\tsgGameInitInfo.versionMinor = PROJECT_VERSION_MINOR;\r\n\tsgGameInitInfo.versionPatch = PROJECT_VERSION_PATCH;\r\n\tconst Options &options = GetOptions();\r\n\tsgGameInitInfo.nTickRate = *options.Gameplay.tickRate;\r\n\tsgGameInitInfo.bRunInTown = *options.Gameplay.runInTown ? 1 : 0;\r\n\tsgGameInitInfo.bTheoQuest = *options.Gameplay.theoQuest ? 1 : 0;\r\n\tsgGameInitInfo.bCowQuest = *options.Gameplay.cowQuest ? 1 : 0;\r\n\tsgGameInitInfo.bFriendlyFire = *options.Gameplay.friendlyFire ? 1 : 0;\r\n\tsgGameInitInfo.fullQuests = (!gbIsMultiplayer || *options.Gameplay.multiplayerFullQuests) ? 1 : 0;\r\n}\r\n\r\nvoid NetSendLoPri(uint8_t playerId, const std::byte *data, size_t size)\r\n{\r\n\tif (data != nullptr && size != 0) {\r\n\t\tCopyPacket(&lowPriorityBuffer, data, size);\r\n\t\tSendPacket(playerId, data, size);\r\n\t}\r\n}\r\n\r\nvoid NetSendHiPri(uint8_t playerId, const std::byte *data, size_t size)\r\n{\r\n\tif (data != nullptr && size != 0) {\r\n\t\tCopyPacket(&highPriorityBuffer, data, size);\r\n\t\tSendPacket(playerId, data, size);\r\n\t}\r\n\tif (shareNextHighPriorityMessage) {\r\n\t\tshareNextHighPriorityMessage = false;\r\n\t\tTPkt pkt;\r\n\t\tNetReceivePlayerData(&pkt);\r\n\t\tstd::byte *destination = pkt.body;\r\n\t\tsize_t remainingSpace = gdwNormalMsgSize - sizeof(TPktHdr);\r\n\t\tdestination = CopyBufferedPackets(destination, &highPriorityBuffer, &remainingSpace);\r\n\t\tdestination = CopyBufferedPackets(destination, &lowPriorityBuffer, &remainingSpace);\r\n\t\tremainingSpace = sync_all_monsters(destination, remainingSpace);\r\n\t\tconst size_t len = gdwNormalMsgSize - remainingSpace;\r\n\t\tpkt.hdr.wLen = Swap16LE(static_cast<uint16_t>(len));\r\n\t\tif (!SNetSendMessage(SNPLAYER_OTHERS, &pkt.hdr, len))\r\n\t\t\tnthread_terminate_game(\"SNetSendMessage\");\r\n\t}\r\n}\r\n\r\nvoid multi_send_msg_packet(uint32_t pmask, const std::byte *data, size_t size)\r\n{\r\n\tTPkt pkt;\r\n\tNetReceivePlayerData(&pkt);\r\n\tconst size_t len = size + sizeof(pkt.hdr);\r\n\tpkt.hdr.wLen = Swap16LE(static_cast<uint16_t>(len));\r\n\tmemcpy(pkt.body, data, size);\r\n\tuint8_t playerID = 0;\r\n\tfor (uint32_t v = 1; playerID < Players.size(); playerID++, v <<= 1) {\r\n\t\tif ((v & pmask) != 0) {\r\n\t\t\tif (!SNetSendMessage(playerID, &pkt.hdr, len)) {\r\n\t\t\t\tnthread_terminate_game(\"SNetSendMessage\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid multi_msg_countdown()\r\n{\r\n\tfor (uint8_t i = 0; i < Players.size(); i++) {\r\n\t\tif ((player_state[i] & PS_TURN_ARRIVED) != 0) {\r\n\t\t\tif (gdwMsgLenTbl[i] == sizeof(int32_t))\r\n\t\t\t\tParseTurn(i, *(int32_t *)glpMsgTbl[i]);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid multi_player_left(uint8_t pnum, leaveinfo_t reason)\r\n{\r\n\tsgbPlayerLeftGameTbl[pnum] = true;\r\n\tsgdwPlayerLeftReasonTbl[pnum] = reason;\r\n\tClearPlayerLeftState();\r\n}\r\n\r\nvoid multi_net_ping()\r\n{\r\n\tsgbTimeout = true;\r\n\tsglTimeoutStart = SDL_GetTicks();\r\n}\r\n\r\nbool multi_handle_delta()\r\n{\r\n\tif (gbGameDestroyed) {\r\n\t\tgbRunGame = false;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (uint8_t i = 0; i < Players.size(); i++) {\r\n\t\tif (sgbSendDeltaTbl[i]) {\r\n\t\t\tsgbSendDeltaTbl[i] = false;\r\n\t\t\tDeltaExportData(i);\r\n\t\t}\r\n\t}\r\n\r\n\tsgbSentThisCycle = nthread_send_and_recv_turn(sgbSentThisCycle, 1);\r\n\tbool received;\r\n\tif (!nthread_recv_turns(&received)) {\r\n\t\tBeginTimeout();\r\n\t\treturn false;\r\n\t}\r\n\r\n\tsgbTimeout = false;\r\n\tif (received) {\r\n\t\tif (!shareNextHighPriorityMessage) {\r\n\t\t\t// If there are any high priority messages pending,\r\n\t\t\t// share them with other players now\r\n\t\t\tshareNextHighPriorityMessage = true;\r\n\t\t\tif (highPriorityBuffer.dwNextWriteOffset != 0)\r\n\t\t\t\tNetSendHiPri(MyPlayerId, nullptr, 0);\r\n\t\t} else {\r\n\t\t\t// If there were no high priority messages in at least two consecutive game\r\n\t\t\t// ticks, this shares the low priority messages and monster sync data\r\n\t\t\tNetSendHiPri(MyPlayerId, nullptr, 0);\r\n\t\t\tshareNextHighPriorityMessage = true;\r\n\t\t}\r\n\t}\r\n\tMonsterSeeds();\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid ProcessGameMessagePackets()\r\n{\r\n\tClearPlayerLeftState();\r\n\tProcessTmsgs();\r\n\r\n\tuint8_t playerId = std::numeric_limits<uint8_t>::max();\r\n\tTPktHdr *pkt;\r\n\tsize_t dwMsgSize = 0;\r\n\twhile (SNetReceiveMessage(&playerId, (void **)&pkt, &dwMsgSize)) {\r\n\t\tdwRecCount++;\r\n\t\tClearPlayerLeftState();\r\n\t\tif (dwMsgSize < sizeof(TPktHdr))\r\n\t\t\tcontinue;\r\n\t\tif (playerId >= Players.size())\r\n\t\t\tcontinue;\r\n\t\tif (pkt->wCheck != HeaderCheckVal)\r\n\t\t\tcontinue;\r\n\t\tif (Swap16LE(pkt->wLen) != dwMsgSize)\r\n\t\t\tcontinue;\r\n\t\tPlayer &player = Players[playerId];\r\n\t\tif (!IsNetPlayerValid(player)) {\r\n\t\t\tconst _cmd_id cmd = *(const _cmd_id *)(pkt + 1);\r\n\t\t\tif (gbBufferMsgs == 0 && IsNoneOf(cmd, CMD_SEND_PLRINFO, CMD_ACK_PLRINFO)) {\r\n\t\t\t\t// Distrust all messages until\r\n\t\t\t\t// player info is received\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst Point syncPosition = { pkt->px, pkt->py };\r\n\t\tplayer.position.last = syncPosition;\r\n\t\tif (&player != MyPlayer) {\r\n\t\t\tassert(gbBufferMsgs != 2);\r\n\t\t\tplayer._pHitPoints = Swap32LE(pkt->php);\r\n\t\t\tplayer._pMaxHP = Swap32LE(pkt->pmhp);\r\n\t\t\tplayer._pMana = Swap32LE(pkt->mana);\r\n\t\t\tplayer._pMaxMana = Swap32LE(pkt->maxmana);\r\n\t\t\tconst bool cond = gbBufferMsgs == 1;\r\n\t\t\tplayer._pBaseStr = pkt->bstr;\r\n\t\t\tplayer._pBaseMag = pkt->bmag;\r\n\t\t\tplayer._pBaseDex = pkt->bdex;\r\n\r\n\t\t\tconst uint8_t rawDir = pkt->pdir;\r\n\t\t\tif (rawDir <= static_cast<uint8_t>(Direction::SouthEast)) {\r\n\t\t\t\tconst Direction newDir = static_cast<Direction>(rawDir);\r\n\t\t\t\tif (player._pdir != newDir && player._pmode == PM_STAND) {\r\n\t\t\t\t\tplayer._pdir = newDir;\r\n\t\t\t\t\tStartStand(player, newDir);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (!cond && player.plractive && !player.hasNoLife()) {\r\n\t\t\t\tif (player.isOnActiveLevel() && !player._pLvlChanging) {\r\n\t\t\t\t\tif (player.position.tile.WalkingDistance(syncPosition) > 3 && PosOkPlayer(player, syncPosition)) {\r\n\t\t\t\t\t\t// got out of sync, clear the tiles around where we last thought the player was located\r\n\t\t\t\t\t\tFixPlrWalkTags(player);\r\n\r\n\t\t\t\t\t\tplayer.position.old = player.position.tile;\r\n\t\t\t\t\t\t// then just in case clear the tiles around the current position (probably unnecessary)\r\n\t\t\t\t\t\tFixPlrWalkTags(player);\r\n\t\t\t\t\t\tplayer.position.tile = syncPosition;\r\n\t\t\t\t\t\tplayer.position.future = syncPosition;\r\n\t\t\t\t\t\tif (player.isWalking())\r\n\t\t\t\t\t\t\tplayer.position.temp = syncPosition;\r\n\t\t\t\t\t\tSetPlayerOld(player);\r\n\t\t\t\t\t\tplayer.occupyTile(player.position.tile, false);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (player.position.future.WalkingDistance(player.position.tile) > 1) {\r\n\t\t\t\t\t\tplayer.position.future = player.position.tile;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst Point target = { pkt->targx, pkt->targy };\r\n\t\t\t\t\tif (target != Point {}) // does the client send a desired (future) position of remote player?\r\n\t\t\t\t\t\tMakePlrPath(player, target, true);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tplayer.position.tile = syncPosition;\r\n\t\t\t\t\tplayer.position.future = syncPosition;\r\n\t\t\t\t\tSetPlayerOld(player);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tHandleAllPackets(playerId, (const std::byte *)(pkt + 1), dwMsgSize - sizeof(TPktHdr));\r\n\t}\r\n\tCheckPlayerInfoTimeouts();\r\n}\r\n\r\nvoid multi_send_zero_packet(uint8_t pnum, _cmd_id bCmd, const std::byte *data, size_t size)\r\n{\r\n\tassert(pnum != MyPlayerId);\r\n\tassert(data != nullptr);\r\n\tassert(size <= 0x0ffff);\r\n\r\n\tfor (size_t offset = 0; offset < size;) {\r\n\t\tTPkt pkt {};\r\n\t\tpkt.hdr.wCheck = HeaderCheckVal;\r\n\t\tauto &message = *reinterpret_cast<TCmdPlrInfoHdr *>(pkt.body);\r\n\t\tmessage.bCmd = bCmd;\r\n\t\tassert(offset <= 0x0ffff);\r\n\t\tmessage.wOffset = Swap16LE(static_cast<uint16_t>(offset));\r\n\r\n\t\tsize_t dwBody = gdwLargestMsgSize - sizeof(pkt.hdr) - sizeof(message);\r\n\t\tdwBody = std::min(dwBody, size - offset);\r\n\t\tassert(dwBody <= 0x0ffff);\r\n\t\tmessage.wBytes = Swap16LE(static_cast<uint16_t>(dwBody));\r\n\r\n\t\tmemcpy(&pkt.body[sizeof(message)], &data[offset], dwBody);\r\n\r\n\t\tconst size_t dwMsg = sizeof(pkt.hdr) + sizeof(message) + dwBody;\r\n\t\tassert(dwMsg <= 0x0ffff);\r\n\t\tpkt.hdr.wLen = Swap16LE(static_cast<uint16_t>(dwMsg));\r\n\r\n\t\tif (!SNetSendMessage(pnum, &pkt, dwMsg)) {\r\n\t\t\tnthread_terminate_game(\"SNetSendMessage2\");\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\toffset += dwBody;\r\n\t}\r\n}\r\n\r\nvoid NetClose()\r\n{\r\n\tif (!sgbNetInited) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tsgbNetInited = false;\r\n\tnthread_cleanup();\r\n\ttmsg_cleanup();\r\n\tUnregisterNetEventHandlers();\r\n\tSNetLeaveGame(leaveinfo_t::LEAVE_EXIT);\r\n\tif (gbIsMultiplayer)\r\n\t\tSDL_Delay(2000);\r\n\tif (!demo::IsRunning()) {\r\n\t\tPlayers.clear();\r\n\t\tMyPlayer = nullptr;\r\n\t}\r\n}\r\n\r\nbool NetInit(bool bSinglePlayer)\r\n{\r\n\twhile (true) {\r\n\t\tSetRndSeed(0);\r\n\t\tInitGameInfo();\r\n\t\tmemset(sgbPlayerTurnBitTbl, 0, sizeof(sgbPlayerTurnBitTbl));\r\n\t\tgbGameDestroyed = false;\r\n\t\tmemset(sgbPlayerLeftGameTbl, 0, sizeof(sgbPlayerLeftGameTbl));\r\n\t\tmemset(sgdwPlayerLeftReasonTbl, 0, sizeof(sgdwPlayerLeftReasonTbl));\r\n\t\tmemset(sgbSendDeltaTbl, 0, sizeof(sgbSendDeltaTbl));\r\n\t\tPlayers.clear();\r\n\t\tMyPlayer = nullptr;\r\n\t\tmemset(sgwPackPlrOffsetTbl, 0, sizeof(sgwPackPlrOffsetTbl));\r\n\t\tSNetSetBasePlayer(0);\r\n\t\tif (bSinglePlayer) {\r\n\t\t\tif (!InitSingle(&sgGameInitInfo))\r\n\t\t\t\treturn false;\r\n\t\t} else {\r\n\t\t\tif (!InitMulti(&sgGameInitInfo))\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t\tsgbNetInited = true;\r\n\t\tsgbTimeout = false;\r\n\t\tdelta_init();\r\n\t\tInitPlrMsg();\r\n\t\tBufferInit(&highPriorityBuffer);\r\n\t\tBufferInit(&lowPriorityBuffer);\r\n\t\tshareNextHighPriorityMessage = true;\r\n\t\tsync_init();\r\n\t\tnthread_start(sgbPlayerTurnBitTbl[MyPlayerId]);\r\n\t\ttmsg_start();\r\n\t\tsgdwGameLoops = 0;\r\n\t\tsgbSentThisCycle = 0;\r\n\t\tgbDeltaSender = MyPlayerId;\r\n\t\tgbSomebodyWonGameKludge = false;\r\n\t\tnthread_send_and_recv_turn(0, 0);\r\n\t\tSetupLocalPositions();\r\n\t\tSendPlayerInfo(SNPLAYER_OTHERS, CMD_SEND_PLRINFO);\r\n\r\n\t\tPlayer &myPlayer = *MyPlayer;\r\n\t\tResetPlayerGFX(myPlayer);\r\n\t\tmyPlayer.plractive = true;\r\n\t\tgbActivePlayers = 1;\r\n\r\n\t\tif (!sgbPlayerTurnBitTbl[MyPlayerId] || msg_wait_resync())\r\n\t\t\tbreak;\r\n\t\tNetClose();\r\n\t\tgbSelectProvider = false;\r\n\t}\r\n\txoshiro128plusplus gameGenerator(sgGameInitInfo.gameSeed);\r\n\tgnTickDelay = 1000 / sgGameInitInfo.nTickRate;\r\n\r\n\tfor (int i = 0; i < NUMLEVELS; i++) {\r\n\t\tDungeonSeeds[i] = gameGenerator.next();\r\n\t\tLevelSeeds[i] = std::nullopt;\r\n\t}\r\n\t// explicitly randomize the town seed to divorce shops from the game seed\r\n\tDungeonSeeds[0] = GenerateSeed();\r\n\tPublicGame = DvlNet_IsPublicGame();\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\t// separator for marking messages from a different game\r\n\tAddMessageToChatLog(_(\"New Game\"), nullptr, UiFlags::ColorRed);\r\n\tAddMessageToChatLog(fmt::format(fmt::runtime(_(\"Player '{:s}' (level {:d}) just joined the game\")), myPlayer._pName, myPlayer.getCharacterLevel()));\r\n\r\n\t// Log join message with seed for joining players (creator already logged it in SNetCreateGame)\r\n\tif (gbIsMultiplayer && !IsLoopback && MyPlayerId != 0) {\r\n\t\tstd::string upperGameName = GameName;\r\n\t\tstd::transform(upperGameName.begin(), upperGameName.end(), upperGameName.begin(), ::toupper);\r\n\t\tconst char *privacy = PublicGame ? \"public\" : \"private\";\r\n\t\tLogInfo(\"Joined {} {} multiplayer game '{}' (player id: {}, seed: {})\",\r\n\t\t    privacy, ConnectionNames[provider], upperGameName, MyPlayerId,\r\n\t\t    FormatGameSeed(sgGameInitInfo.gameSeed));\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid recv_plrinfo(Player &player, const TCmdPlrInfoHdr &header, bool recv)\r\n{\r\n\tstatic PlayerNetPack PackedPlayerBuffer[MAX_PLRS];\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\treturn;\r\n\t}\r\n\tconst uint8_t pnum = player.getId();\r\n\tauto &packedPlayer = PackedPlayerBuffer[pnum];\r\n\r\n\tif (sgwPackPlrOffsetTbl[pnum] != Swap16LE(header.wOffset)) {\r\n\t\tsgwPackPlrOffsetTbl[pnum] = 0;\r\n\t\tif (header.wOffset != 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tif (!recv && sgwPackPlrOffsetTbl[pnum] == 0) {\r\n\t\tSendPlayerInfo(pnum, CMD_ACK_PLRINFO);\r\n\t}\r\n\r\n\tmemcpy(reinterpret_cast<uint8_t *>(&packedPlayer) + Swap16LE(header.wOffset), reinterpret_cast<const uint8_t *>(&header) + sizeof(header), Swap16LE(header.wBytes));\r\n\r\n\tsgwPackPlrOffsetTbl[pnum] += Swap16LE(header.wBytes);\r\n\tif (sgwPackPlrOffsetTbl[pnum] != sizeof(packedPlayer)) {\r\n\t\treturn;\r\n\t}\r\n\tsgwPackPlrOffsetTbl[pnum] = 0;\r\n\r\n\tPlayerLeftMsg(player, false);\r\n\tif (!UnPackNetPlayer(packedPlayer, player)) {\r\n\t\tplayer = {};\r\n\t\tSNetDropPlayer(pnum, leaveinfo_t::LEAVE_DROP);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!recv) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tResetPlayerGFX(player);\r\n\tplayer.plractive = true;\r\n\tgbActivePlayers++;\r\n\r\n\tstd::string_view szEvent;\r\n\tif (sgbPlayerTurnBitTbl[pnum]) {\r\n\t\tszEvent = _(\"Player '{:s}' (level {:d}) just joined the game\");\r\n\t\tif (!IsLoopback)\r\n\t\t\tLogInfo(\"Player '{}' joined the {} game (level {}, {}/{} players)\", player._pName, ConnectionNames[provider], player.getCharacterLevel(), gbActivePlayers, MAX_PLRS);\r\n\t} else {\r\n\t\tszEvent = _(\"Player '{:s}' (level {:d}) is already in the game\");\r\n\t}\r\n\tEventPlrMsg(fmt::format(fmt::runtime(szEvent), player._pName, player.getCharacterLevel()));\r\n\r\n\tSyncInitPlr(player);\r\n\r\n\tif (!player.isOnActiveLevel()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!player.hasNoLife()) {\r\n\t\tStartStand(player, player._pdir);\r\n\t\treturn;\r\n\t}\r\n\r\n\tplayer._pgfxnum &= ~0xFU;\r\n\tplayer._pmode = PM_DEATH;\r\n\tNewPlrAnim(player, player_graphic::Death, player._pdir);\r\n\tplayer.AnimInfo.currentFrame = player.AnimInfo.numberOfFrames - 2;\r\n\tdFlags[player.position.tile.x][player.position.tile.y] |= DungeonFlag::DeadPlayer;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/multi.h",
    "content": "/**\r\n * @file multi.h\r\n *\r\n * Interface of functions for keeping multiplayer games in sync.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <vector>\r\n\r\n#include \"dvlnet/leaveinfo.hpp\"\r\n#include \"msg.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nusing net::leaveinfo_t;\r\n\r\n// Defined in player.h, forward declared here to allow for functions which operate in the context of a player.\r\nstruct Player;\r\n\r\n// must be unsigned to generate unsigned comparisons with pnum\r\n#define MAX_PLRS 4\r\n\r\nstruct GameData {\r\n\tint32_t size;\r\n\tuint8_t reserved[4];\r\n\tuint32_t programid;\r\n\tuint8_t versionMajor;\r\n\tuint8_t versionMinor;\r\n\tuint8_t versionPatch;\r\n\t_difficulty nDifficulty;\r\n\tuint8_t nTickRate;\r\n\tuint8_t bRunInTown;\r\n\tuint8_t bTheoQuest;\r\n\tuint8_t bCowQuest;\r\n\tuint8_t bFriendlyFire;\r\n\tuint8_t fullQuests;\r\n\t/** Used to initialise the seed table for dungeon levels so players in multiplayer games generate the same layout */\r\n\tuint32_t gameSeed[4];\r\n\r\n\tvoid swapLE();\r\n};\r\n\r\n/* @brief Contains info of running public game (for game list browsing) */\r\nstruct GameInfo {\r\n\tstd::string name;\r\n\tGameData gameData;\r\n\tstd::vector<std::string> players;\r\n\tstd::optional<int> latency;\r\n\tstd::optional<bool> peerIsRelayed;\r\n};\r\n\r\nextern bool gbSomebodyWonGameKludge;\r\nextern uint16_t sgwPackPlrOffsetTbl[MAX_PLRS];\r\nextern uint8_t gbActivePlayers;\r\nextern bool gbGameDestroyed;\r\nextern DVL_API_FOR_TEST GameData sgGameInitInfo;\r\nextern bool gbSelectProvider;\r\nextern DVL_API_FOR_TEST bool gbIsMultiplayer;\r\nextern std::string GameName;\r\nextern std::string GamePassword;\r\nextern bool PublicGame;\r\nextern uint8_t gbDeltaSender;\r\nextern uint32_t player_state[MAX_PLRS];\r\nextern bool IsLoopback;\r\n\r\nDVL_API_FOR_TEST std::string DescribeLeaveReason(leaveinfo_t leaveReason);\r\nstd::string FormatGameSeed(const uint32_t gameSeed[4]);\r\n\r\nvoid InitGameInfo();\r\nvoid NetSendLoPri(uint8_t playerId, const std::byte *data, size_t size);\r\nvoid NetSendHiPri(uint8_t playerId, const std::byte *data, size_t size);\r\nvoid multi_send_msg_packet(uint32_t pmask, const std::byte *data, size_t size);\r\nvoid multi_msg_countdown();\r\nvoid multi_player_left(uint8_t pnum, leaveinfo_t reason);\r\nvoid multi_net_ping();\r\n\r\n/**\r\n * @return Always true for singleplayer\r\n */\r\nbool multi_handle_delta();\r\nvoid ProcessGameMessagePackets();\r\nvoid multi_send_zero_packet(uint8_t pnum, _cmd_id bCmd, const std::byte *data, size_t size);\r\nvoid NetClose();\r\nbool NetInit(bool bSinglePlayer);\r\nvoid recv_plrinfo(Player &player, const TCmdPlrInfoHdr &header, bool recv);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/nthread.cpp",
    "content": "/**\r\n * @file nthread.cpp\r\n *\r\n * Implementation of functions for managing game ticks.\r\n */\r\n#include \"nthread.h\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"diablo.h\"\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/demomode.h\"\r\n#include \"game_mode.hpp\"\r\n#include \"gmenu.h\"\r\n#include \"storm/storm_net.hpp\"\r\n#include \"utils/sdl_mutex.h\"\r\n#include \"utils/sdl_thread.h\"\r\n\r\nnamespace devilution {\r\n\r\nuint8_t sgbNetUpdateRate;\r\nsize_t gdwMsgLenTbl[MAX_PLRS];\r\nuint32_t gdwTurnsInTransit;\r\nuintptr_t glpMsgTbl[MAX_PLRS];\r\nuint32_t gdwLargestMsgSize;\r\nuint32_t gdwNormalMsgSize;\r\nint last_tick;\r\nuint8_t ProgressToNextGameTick = 0;\r\n\r\nnamespace {\r\n\r\nSdlMutex MemCrit;\r\nbool nthread_should_run;\r\nint8_t sgbSyncCountdown;\r\nuint32_t turn_upper_bit;\r\nbool sgbTicsOutOfSync;\r\nint8_t sgbPacketCountdown;\r\nbool sgbThreadIsRunning;\r\nSdlThread Thread;\r\n\r\nvoid NthreadHandler()\r\n{\r\n\tif (!nthread_should_run) {\r\n\t\treturn;\r\n\t}\r\n\r\n\twhile (true) {\r\n\t\tMemCrit.lock();\r\n\t\tif (!nthread_should_run) {\r\n\t\t\tMemCrit.unlock();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tnthread_send_and_recv_turn(0, 0);\r\n\t\tint delta = gnTickDelay;\r\n\t\tif (nthread_recv_turns())\r\n\t\t\tdelta = last_tick - SDL_GetTicks();\r\n\t\tMemCrit.unlock();\r\n\t\tif (delta > 0)\r\n\t\t\tSDL_Delay(delta);\r\n\t\tif (!nthread_should_run)\r\n\t\t\treturn;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid nthread_terminate_game(const char *pszFcn)\r\n{\r\n\tapp_fatal(pszFcn);\r\n\tgbGameDestroyed = true;\r\n}\r\n\r\nuint32_t nthread_send_and_recv_turn(uint32_t curTurn, int turnDelta)\r\n{\r\n\tuint32_t curTurnsInTransit;\r\n\tif (!SNetGetTurnsInTransit(&curTurnsInTransit)) {\r\n\t\tnthread_terminate_game(\"SNetGetTurnsInTransit\");\r\n\t\treturn 0;\r\n\t}\r\n\twhile (curTurnsInTransit++ < gdwTurnsInTransit) {\r\n\r\n\t\tconst uint32_t turnTmp = turn_upper_bit | (curTurn & 0x7FFFFFFF);\r\n\t\tturn_upper_bit = 0;\r\n\t\tuint32_t turn = turnTmp;\r\n\r\n\t\tif (!SNetSendTurn((char *)&turn, sizeof(turn))) {\r\n\t\t\tnthread_terminate_game(\"SNetSendTurn\");\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\tcurTurn += turnDelta;\r\n\t\tif (curTurn >= 0x7FFFFFFF)\r\n\t\t\tcurTurn &= 0xFFFF;\r\n\t}\r\n\treturn curTurn;\r\n}\r\n\r\nbool nthread_recv_turns(bool *pfSendAsync)\r\n{\r\n\tif (pfSendAsync != nullptr)\r\n\t\t*pfSendAsync = false;\r\n\tsgbPacketCountdown--;\r\n\tif (sgbPacketCountdown > 0) {\r\n\t\tlast_tick += gnTickDelay;\r\n\t\treturn true;\r\n\t}\r\n\tsgbSyncCountdown--;\r\n\tsgbPacketCountdown = sgbNetUpdateRate;\r\n\tif (sgbSyncCountdown != 0) {\r\n\t\tif (pfSendAsync != nullptr)\r\n\t\t\t*pfSendAsync = true;\r\n\t\tlast_tick += gnTickDelay;\r\n\t\treturn true;\r\n\t}\r\n\tif (!SNetReceiveTurns(MAX_PLRS, (char **)glpMsgTbl, gdwMsgLenTbl, &player_state[0])) {\r\n\t\tsgbTicsOutOfSync = false;\r\n\t\tsgbSyncCountdown = 1;\r\n\t\tsgbPacketCountdown = 1;\r\n\t\treturn false;\r\n\t}\r\n\tif (!sgbTicsOutOfSync) {\r\n\t\tsgbTicsOutOfSync = true;\r\n\t\tlast_tick = SDL_GetTicks();\r\n\t}\r\n\tsgbSyncCountdown = 4;\r\n\tmulti_msg_countdown();\r\n\tif (pfSendAsync != nullptr)\r\n\t\t*pfSendAsync = true;\r\n\tlast_tick += gnTickDelay;\r\n\treturn true;\r\n}\r\n\r\nvoid nthread_set_turn_upper_bit()\r\n{\r\n\tturn_upper_bit = 0x80000000;\r\n}\r\n\r\nvoid nthread_start(bool setTurnUpperBit)\r\n{\r\n\tlast_tick = SDL_GetTicks();\r\n\tsgbPacketCountdown = 1;\r\n\tsgbSyncCountdown = 1;\r\n\tsgbTicsOutOfSync = true;\r\n\tif (setTurnUpperBit)\r\n\t\tnthread_set_turn_upper_bit();\r\n\telse\r\n\t\tturn_upper_bit = 0;\r\n\t_SNETCAPS caps;\r\n\tcaps.size = 36;\r\n\tSNetGetProviderCaps(&caps);\r\n\tgdwTurnsInTransit = caps.defaultturnsintransit;\r\n\tif (gdwTurnsInTransit == 0)\r\n\t\tgdwTurnsInTransit = 1;\r\n\tif (caps.defaultturnssec <= 20 && caps.defaultturnssec != 0)\r\n\t\tsgbNetUpdateRate = 20 / caps.defaultturnssec;\r\n\telse\r\n\t\tsgbNetUpdateRate = 1;\r\n\tuint32_t largestMsgSize = 512;\r\n\tif (caps.maxmessagesize < 0x200)\r\n\t\tlargestMsgSize = caps.maxmessagesize;\r\n\tgdwLargestMsgSize = largestMsgSize;\r\n\tgdwNormalMsgSize = caps.bytessec * sgbNetUpdateRate / 20;\r\n\tgdwNormalMsgSize *= 3;\r\n\tgdwNormalMsgSize >>= 2;\r\n\tif (caps.maxplayers > MAX_PLRS)\r\n\t\tcaps.maxplayers = MAX_PLRS;\r\n\tgdwNormalMsgSize /= caps.maxplayers;\r\n\twhile (gdwNormalMsgSize < 0x80) {\r\n\t\tgdwNormalMsgSize *= 2;\r\n\t\tsgbNetUpdateRate *= 2;\r\n\t}\r\n\tif (gdwNormalMsgSize > largestMsgSize)\r\n\t\tgdwNormalMsgSize = largestMsgSize;\r\n\tif (gbIsMultiplayer) {\r\n\t\tsgbThreadIsRunning = false;\r\n\t\tMemCrit.lock();\r\n\t\tnthread_should_run = true;\r\n\t\tThread = SdlThread { NthreadHandler };\r\n\t}\r\n}\r\n\r\nvoid nthread_cleanup()\r\n{\r\n\tnthread_should_run = false;\r\n\tgdwTurnsInTransit = 0;\r\n\tgdwNormalMsgSize = 0;\r\n\tgdwLargestMsgSize = 0;\r\n\tif (Thread.joinable() && Thread.get_id() != this_sdl_thread::get_id()) {\r\n\t\tif (!sgbThreadIsRunning)\r\n\t\t\tMemCrit.unlock();\r\n\t\tThread.join();\r\n\t}\r\n}\r\n\r\nvoid nthread_ignore_mutex(bool bStart)\r\n{\r\n\tif (!Thread.joinable())\r\n\t\treturn;\r\n\r\n\tif (bStart)\r\n\t\tMemCrit.unlock();\r\n\telse\r\n\t\tMemCrit.lock();\r\n\tsgbThreadIsRunning = bStart;\r\n}\r\n\r\nbool nthread_has_500ms_passed(bool *drawGame /*= nullptr*/)\r\n{\r\n\tconst int currentTickCount = SDL_GetTicks();\r\n\tint ticksElapsed = currentTickCount - last_tick;\r\n\t// Check if we missed multiple game ticks (> 10)\r\n\tif (ticksElapsed > gnTickDelay * 10) {\r\n\t\tbool resetLastTick = true;\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tfor (size_t i = 0; i < Players.size(); i++) {\r\n\t\t\t\tif ((player_state[i] & PS_CONNECTED) != 0 && i != MyPlayerId) {\r\n\t\t\t\t\t// Reset last tick is not allowed when other players are connected, because the elapsed time is needed to sync the game ticks between the clients\r\n\t\t\t\t\tresetLastTick = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (resetLastTick) {\r\n\t\t\t// Reset last tick to avoid catching up with all missed game ticks (game speed is dramatically increased for a short time)\r\n\t\t\tlast_tick = currentTickCount;\r\n\t\t\tticksElapsed = 0;\r\n\t\t}\r\n\t}\r\n\tif (drawGame != nullptr) {\r\n\t\t// Check if we missed a game tick.\r\n\t\t// This can happen when we run a low-end device that can't render fast enough (typically 20fps).\r\n\t\t// If this happens, try to speed-up the game by skipping the rendering.\r\n\t\t// This avoids desyncs and hourglasses when running multiplayer and slowdowns in singleplayer.\r\n\t\t*drawGame = ticksElapsed <= gnTickDelay;\r\n\t}\r\n\treturn ticksElapsed >= 0;\r\n}\r\n\r\nvoid nthread_UpdateProgressToNextGameTick()\r\n{\r\n\tif (!gbRunGame || PauseMode != 0 || (!gbIsMultiplayer && gmenu_is_active()) || !gbProcessPlayers || demo::IsRunning()) // if game is not running or paused there is no next gametick in the near future\r\n\t\treturn;\r\n\tconst int currentTickCount = SDL_GetTicks();\r\n\tconst int ticksMissing = last_tick - currentTickCount;\r\n\tif (ticksMissing <= 0) {\r\n\t\tProgressToNextGameTick = AnimationInfo::baseValueFraction; // game tick is due\r\n\t\treturn;\r\n\t}\r\n\tconst int ticksAdvanced = gnTickDelay - ticksMissing;\r\n\tint32_t fraction = ticksAdvanced * AnimationInfo::baseValueFraction / gnTickDelay;\r\n\tfraction = std::clamp<int32_t>(fraction, 0, AnimationInfo::baseValueFraction);\r\n\tProgressToNextGameTick = static_cast<uint8_t>(fraction);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/nthread.h",
    "content": "/**\r\n * @file nthread.h\r\n *\r\n * Interface of functions for managing game ticks.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"player.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern uint8_t sgbNetUpdateRate;\r\nextern size_t gdwMsgLenTbl[MAX_PLRS];\r\nextern uint32_t gdwTurnsInTransit;\r\nextern uintptr_t glpMsgTbl[MAX_PLRS];\r\nextern uint32_t gdwLargestMsgSize;\r\nextern uint32_t gdwNormalMsgSize;\r\n/** @brief the progress as a fraction (see AnimationInfo::baseValueFraction) in time to the next game tick */\r\nextern DVL_API_FOR_TEST uint8_t ProgressToNextGameTick;\r\nextern int last_tick;\r\n\r\nvoid nthread_terminate_game(const char *pszFcn);\r\nuint32_t nthread_send_and_recv_turn(uint32_t curTurn, int turnDelta);\r\nbool nthread_recv_turns(bool *pfSendAsync = nullptr);\r\nvoid nthread_set_turn_upper_bit();\r\nvoid nthread_start(bool setTurnUpperBit);\r\nvoid nthread_cleanup();\r\nvoid nthread_ignore_mutex(bool bStart);\r\n\r\n/**\r\n * @brief Checks if it's time for the logic to advance\r\n * @return True if the engine should tick\r\n */\r\nbool nthread_has_500ms_passed(bool *drawGame = nullptr);\r\n/**\r\n * @brief Updates the progress in time to the next game tick\r\n */\r\nvoid nthread_UpdateProgressToNextGameTick();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/objects.cpp",
    "content": "/**\r\n * @file objects.cpp\r\n *\r\n * Implementation of object functionality, interaction, spawning, loading, etc.\r\n */\r\n#include <climits>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <ctime>\r\n#include <string>\r\n\r\n#include <algorithm>\r\n\r\n#include <expected.hpp>\r\n#include <fmt/core.h>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"automap.h\"\r\n#include \"cursor.h\"\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n#include \"diablo_msg.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"inv.h\"\r\n#include \"inv_iterators.hpp\"\r\n#include \"levels/crypt.h\"\r\n#include \"levels/drlg_l4.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"levels/themes.h\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"lighting.h\"\r\n#include \"minitext.h\"\r\n#include \"missiles.h\"\r\n#include \"monster.h\"\r\n#include \"options.h\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"towners.h\"\r\n#include \"track.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nObject Objects[MAXOBJECTS];\r\nint AvailableObjects[MAXOBJECTS];\r\nint ActiveObjects[MAXOBJECTS];\r\nint ActiveObjectCount;\r\nbool LoadingMapObjects;\r\nint NaKrulTomeSequence;\r\n\r\nnamespace {\r\n\r\nenum shrine_type : uint8_t {\r\n\tShrineMysterious,\r\n\tShrineHidden,\r\n\tShrineGloomy,\r\n\tShrineWeird,\r\n\tShrineMagical,\r\n\tShrineStone,\r\n\tShrineReligious,\r\n\tShrineEnchanted,\r\n\tShrineThaumaturgic,\r\n\tShrineFascinating,\r\n\tShrineCryptic,\r\n\tShrineMagicaL2,\r\n\tShrineEldritch,\r\n\tShrineEerie,\r\n\tShrineDivine,\r\n\tShrineHoly,\r\n\tShrineSacred,\r\n\tShrineSpiritual,\r\n\tShrineSpooky,\r\n\tShrineAbandoned,\r\n\tShrineCreepy,\r\n\tShrineQuiet,\r\n\tShrineSecluded,\r\n\tShrineOrnate,\r\n\tShrineGlimmering,\r\n\tShrineTainted,\r\n\tShrineOily,\r\n\tShrineGlowing,\r\n\tShrineMendicant,\r\n\tShrineSparkling,\r\n\tShrineTown,\r\n\tShrineShimmering,\r\n\tShrineSolar,\r\n\tShrineMurphys,\r\n\tNumberOfShrineTypes\r\n};\r\n\r\nenum {\r\n\t// clang-format off\r\n\tDOOR_CLOSED  =  0,\r\n\tDOOR_OPEN    =  1,\r\n\tDOOR_BLOCKED =  2,\r\n\t// clang-format on\r\n};\r\n\r\nint trapid;\r\nint trapdir;\r\nOptionalOwnedClxSpriteList pObjCels[40];\r\nobject_graphic_id ObjFileList[40];\r\n/** Specifies the number of active objects. */\r\nint leverid;\r\nint numobjfiles;\r\n\r\n/** Specifies the X-coordinate delta between barrels. */\r\nint bxadd[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };\r\n/** Specifies the Y-coordinate delta between barrels. */\r\nint byadd[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };\r\n/** Maps from shrine_id to shrine name. */\r\nconst char *const ShrineNames[] = {\r\n\t// TRANSLATORS: Shrine Name Block\r\n\tN_(\"Mysterious\"),\r\n\tN_(\"Hidden\"),\r\n\tN_(\"Gloomy\"),\r\n\tN_(\"Weird\"),\r\n\tN_(\"Magical\"),\r\n\tN_(\"Stone\"),\r\n\tN_(\"Religious\"),\r\n\tN_(\"Enchanted\"),\r\n\tN_(\"Thaumaturgic\"),\r\n\tN_(\"Fascinating\"),\r\n\tN_(\"Cryptic\"),\r\n\tN_(\"Magical\"),\r\n\tN_(\"Eldritch\"),\r\n\tN_(\"Eerie\"),\r\n\tN_(\"Divine\"),\r\n\tN_(\"Holy\"),\r\n\tN_(\"Sacred\"),\r\n\tN_(\"Spiritual\"),\r\n\tN_(\"Spooky\"),\r\n\tN_(\"Abandoned\"),\r\n\tN_(\"Creepy\"),\r\n\tN_(\"Quiet\"),\r\n\tN_(\"Secluded\"),\r\n\tN_(\"Ornate\"),\r\n\tN_(\"Glimmering\"),\r\n\tN_(\"Tainted\"),\r\n\tN_(\"Oily\"),\r\n\tN_(\"Glowing\"),\r\n\tN_(\"Mendicant's\"),\r\n\tN_(\"Sparkling\"),\r\n\tN_(\"Town\"),\r\n\tN_(\"Shimmering\"),\r\n\tN_(\"Solar\"),\r\n\t// TRANSLATORS: Shrine Name Block end\r\n\tN_(\"Murphy's\"),\r\n};\r\n\r\n/**\r\n * Specifies the game type for which each shrine may appear.\r\n * ShrineTypeAny - sp & mp\r\n * ShrineTypeSingle - sp only\r\n * ShrineTypeMulti - mp only\r\n */\r\nenum shrine_gametype : uint8_t {\r\n\tShrineTypeAny,\r\n\tShrineTypeSingle,\r\n\tShrineTypeMulti,\r\n};\r\n\r\nshrine_gametype shrineavail[] = {\r\n\tShrineTypeAny,    // Mysterious\r\n\tShrineTypeAny,    // Hidden\r\n\tShrineTypeSingle, // Gloomy\r\n\tShrineTypeSingle, // Weird\r\n\tShrineTypeAny,    // Magical\r\n\tShrineTypeAny,    // Stone\r\n\tShrineTypeAny,    // Religious\r\n\tShrineTypeAny,    // Enchanted\r\n\tShrineTypeSingle, // Thaumaturgic\r\n\tShrineTypeAny,    // Fascinating\r\n\tShrineTypeAny,    // Cryptic\r\n\tShrineTypeAny,    // Magical\r\n\tShrineTypeAny,    // Eldritch\r\n\tShrineTypeAny,    // Eerie\r\n\tShrineTypeAny,    // Divine\r\n\tShrineTypeAny,    // Holy\r\n\tShrineTypeAny,    // Sacred\r\n\tShrineTypeAny,    // Spiritual\r\n\tShrineTypeMulti,  // Spooky\r\n\tShrineTypeAny,    // Abandoned\r\n\tShrineTypeAny,    // Creepy\r\n\tShrineTypeAny,    // Quiet\r\n\tShrineTypeAny,    // Secluded\r\n\tShrineTypeAny,    // Ornate\r\n\tShrineTypeAny,    // Glimmering\r\n\tShrineTypeMulti,  // Tainted\r\n\tShrineTypeAny,    // Oily\r\n\tShrineTypeAny,    // Glowing\r\n\tShrineTypeAny,    // Mendicant's\r\n\tShrineTypeAny,    // Sparkling\r\n\tShrineTypeAny,    // Town\r\n\tShrineTypeAny,    // Shimmering\r\n\tShrineTypeSingle, // Solar,\r\n\tShrineTypeAny,    // Murphy's\r\n};\r\n/** Maps from book_id to book name. */\r\nconst char *const StoryBookName[] = {\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Great Conflict\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Wages of Sin are War\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Tale of the Horadrim\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Dark Exile\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Sin War\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Binding of the Three\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Realms Beyond\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"Tale of the Three\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"The Black King\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"Journal: The Ensorcellment\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"Journal: The Meeting\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"Journal: The Tirade\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"Journal: His Power Grows\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"Journal: NA-KRUL\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"Journal: The End\"),\r\n\tN_(/* TRANSLATORS: Book Title */ \"A Spellbook\"),\r\n};\r\n/** Specifies the speech IDs of each dungeon type narrator book, for each player class. */\r\n_speech_id StoryText[3][3] = {\r\n\t{ TEXT_BOOK11, TEXT_BOOK12, TEXT_BOOK13 },\r\n\t{ TEXT_BOOK21, TEXT_BOOK22, TEXT_BOOK23 },\r\n\t{ TEXT_BOOK31, TEXT_BOOK32, TEXT_BOOK33 }\r\n};\r\n\r\nbool RndLocOk(Point p)\r\n{\r\n\tif (dMonster[p.x][p.y] != 0)\r\n\t\treturn false;\r\n\tif (dPlayer[p.x][p.y] != 0)\r\n\t\treturn false;\r\n\tif (IsObjectAtPosition(p))\r\n\t\treturn false;\r\n\tif (TileContainsSetPiece(p))\r\n\t\treturn false;\r\n\tif (TileHasAny(p, TileProperties::Solid))\r\n\t\treturn false;\r\n\treturn IsNoneOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CRYPT) || dPiece[p.x][p.y] <= 125 || dPiece[p.x][p.y] >= 143;\r\n}\r\n\r\nbool IsAreaOk(Rectangle rect)\r\n{\r\n\treturn c_all_of(PointsInRectangle(rect), &RndLocOk);\r\n}\r\n\r\nbool CanPlaceWallTrap(Point pos)\r\n{\r\n\tif (dObject[pos.x][pos.y] != 0)\r\n\t\treturn false;\r\n\tif (TileContainsSetPiece(pos))\r\n\t\treturn false;\r\n\r\n\treturn TileHasAny(pos, TileProperties::Trap);\r\n}\r\n\r\nvoid InitRndLocObj(int min, int max, _object_id objtype)\r\n{\r\n\tconst int numobjs = GenerateRnd(max - min) + min;\r\n\r\n\tfor (int i = 0; i < numobjs; i++) {\r\n\t\twhile (true) {\r\n\t\t\tconst int xp = GenerateRnd(80) + 16;\r\n\t\t\tconst int yp = GenerateRnd(80) + 16;\r\n\t\t\tif (IsAreaOk(Rectangle { { xp - 1, yp - 1 }, { 3, 3 } })) {\r\n\t\t\t\tAddObject(objtype, { xp, yp });\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid InitRndLocBigObj(int min, int max, _object_id objtype)\r\n{\r\n\tconst int numobjs = GenerateRnd(max - min) + min;\r\n\tfor (int i = 0; i < numobjs; i++) {\r\n\t\twhile (true) {\r\n\t\t\tconst int xp = GenerateRnd(80) + 16;\r\n\t\t\tconst int yp = GenerateRnd(80) + 16;\r\n\t\t\tif (IsAreaOk(Rectangle { { xp - 1, yp - 2 }, { 3, 4 } })) {\r\n\t\t\t\tAddObject(objtype, { xp, yp });\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool CanPlaceRandomObject(Point position, Displacement standoff)\r\n{\r\n\treturn IsAreaOk(Rectangle { position - standoff,\r\n\t    Size { standoff.deltaX * 2 + 1, standoff.deltaY * 2 + 1 } });\r\n}\r\n\r\nstd::optional<Point> GetRandomObjectPosition(Displacement standoff)\r\n{\r\n\tfor (int i = 0; i <= 20000; i++) {\r\n\t\tPoint position = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 };\r\n\t\tif (CanPlaceRandomObject(position, standoff))\r\n\t\t\treturn position;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid InitRndLocObj5x5(int min, int max, _object_id objtype)\r\n{\r\n\tconst int numobjs = min + GenerateRnd(max - min);\r\n\tfor (int i = 0; i < numobjs; i++) {\r\n\t\tstd::optional<Point> position = GetRandomObjectPosition({ 2, 2 });\r\n\t\tif (!position)\r\n\t\t\treturn;\r\n\t\tAddObject(objtype, *position);\r\n\t}\r\n}\r\n\r\nvoid ClrAllObjects()\r\n{\r\n\tfor (Object &object : Objects) {\r\n\t\tobject = {};\r\n\t}\r\n\tActiveObjectCount = 0;\r\n\tfor (int i = 0; i < MAXOBJECTS; i++) {\r\n\t\tAvailableObjects[i] = i;\r\n\t}\r\n\tmemset(ActiveObjects, 0, sizeof(ActiveObjects));\r\n\ttrapdir = 0;\r\n\ttrapid = 1;\r\n\tleverid = 1;\r\n}\r\n\r\nvoid AddTortures()\r\n{\r\n\tfor (int oy = 0; oy < MAXDUNY; oy++) {\r\n\t\tfor (int ox = 0; ox < MAXDUNX; ox++) {\r\n\t\t\tif (dPiece[ox][oy] == 366) {\r\n\t\t\t\tAddObject(OBJ_TORTURE1, { ox, oy + 1 });\r\n\t\t\t\tAddObject(OBJ_TORTURE3, { ox + 2, oy - 1 });\r\n\t\t\t\tAddObject(OBJ_TORTURE2, { ox, oy + 3 });\r\n\t\t\t\tAddObject(OBJ_TORTURE4, { ox + 4, oy - 1 });\r\n\t\t\t\tAddObject(OBJ_TORTURE5, { ox, oy + 5 });\r\n\t\t\t\tAddObject(OBJ_TNUDEM1, { ox + 1, oy + 3 });\r\n\t\t\t\tAddObject(OBJ_TNUDEM2, { ox + 4, oy + 5 });\r\n\t\t\t\tAddObject(OBJ_TNUDEM3, { ox + 2, oy });\r\n\t\t\t\tAddObject(OBJ_TNUDEM4, { ox + 3, oy + 2 });\r\n\t\t\t\tAddObject(OBJ_TNUDEW1, { ox + 2, oy + 4 });\r\n\t\t\t\tAddObject(OBJ_TNUDEW2, { ox + 2, oy + 1 });\r\n\t\t\t\tAddObject(OBJ_TNUDEW3, { ox + 4, oy + 2 });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddCandles()\r\n{\r\n\tconst int tx = Quests[Q_PWATER].position.x;\r\n\tconst int ty = Quests[Q_PWATER].position.y;\r\n\tAddObject(OBJ_STORYCANDLE, { tx - 2, ty + 1 });\r\n\tAddObject(OBJ_STORYCANDLE, { tx + 3, ty + 1 });\r\n\tAddObject(OBJ_STORYCANDLE, { tx - 1, ty + 2 });\r\n\tAddObject(OBJ_STORYCANDLE, { tx + 2, ty + 2 });\r\n}\r\n\r\n/**\r\n * @brief Attempts to spawn a book somewhere on the current floor which when activated will change a region of the map.\r\n *\r\n * This object acts like a lever and will cause a change to the map based on what quest is active. The exact effect is\r\n * determined by OperateBookLever().\r\n *\r\n * @param affectedArea The map region to be updated when this object is activated by the player.\r\n * @param msg The quest text to play when the player activates the book.\r\n */\r\nvoid AddBookLever(_object_id type, WorldTileRectangle affectedArea, _speech_id msg)\r\n{\r\n\tstd::optional<Point> position = GetRandomObjectPosition({ 2, 2 });\r\n\tif (!position)\r\n\t\treturn;\r\n\r\n\tif (type == OBJ_BLOODBOOK)\r\n\t\tposition = SetPiece.position.megaToWorld() + Displacement { 9, 24 };\r\n\r\n\tObject *lever = AddObject(type, *position);\r\n\tassert(lever != nullptr);\r\n\r\n\tlever->InitializeQuestBook(affectedArea, leverid, msg);\r\n\tleverid++;\r\n}\r\n\r\nvoid InitRndBarrels()\r\n{\r\n\t_object_id barrelId = OBJ_BARREL;\r\n\t_object_id explosiveBarrelId = OBJ_BARRELEX;\r\n\tif (leveltype == DTYPE_NEST) {\r\n\t\tbarrelId = OBJ_POD;\r\n\t\texplosiveBarrelId = OBJ_PODEX;\r\n\t} else if (leveltype == DTYPE_CRYPT) {\r\n\t\tbarrelId = OBJ_URN;\r\n\t\texplosiveBarrelId = OBJ_URNEX;\r\n\t}\r\n\r\n\t/** number of groups of barrels to generate */\r\n\tconst int numobjs = GenerateRnd(5) + 3;\r\n\tfor (int i = 0; i < numobjs; i++) {\r\n\t\tint xp;\r\n\t\tint yp;\r\n\t\tdo {\r\n\t\t\txp = GenerateRnd(80) + 16;\r\n\t\t\typ = GenerateRnd(80) + 16;\r\n\t\t} while (!RndLocOk({ xp, yp }));\r\n\t\t_object_id o = FlipCoin(4) ? explosiveBarrelId : barrelId;\r\n\t\tAddObject(o, { xp, yp });\r\n\t\tbool found = true;\r\n\t\t/** regulates chance to stop placing barrels in current group */\r\n\t\tint p = 0;\r\n\t\t/** number of barrels in current group */\r\n\t\tint c = 1;\r\n\t\twhile (FlipCoin(p) && found) {\r\n\t\t\t/** number of tries of placing next barrel in current group */\r\n\t\t\tint t = 0;\r\n\t\t\tfound = false;\r\n\t\t\twhile (true) {\r\n\t\t\t\tif (t >= 3)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tconst int dir = GenerateRnd(8);\r\n\t\t\t\txp += bxadd[dir];\r\n\t\t\t\typ += byadd[dir];\r\n\t\t\t\tfound = RndLocOk({ xp, yp });\r\n\t\t\t\tt++;\r\n\t\t\t\tif (found)\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif (found) {\r\n\t\t\t\to = FlipCoin(5) ? explosiveBarrelId : barrelId;\r\n\t\t\t\tAddObject(o, { xp, yp });\r\n\t\t\t\tc++;\r\n\t\t\t}\r\n\t\t\tp = c / 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddL2Torches()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tconst Point testPosition = { i, j };\r\n\t\t\tif (TileContainsSetPiece(testPosition))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tconst int pn = dPiece[i][j];\r\n\t\t\tif (pn == 0 && FlipCoin(3)) {\r\n\t\t\t\tAddObject(OBJ_TORCHL2, testPosition);\r\n\t\t\t}\r\n\r\n\t\t\tif (pn == 4 && FlipCoin(3)) {\r\n\t\t\t\tAddObject(OBJ_TORCHR2, testPosition);\r\n\t\t\t}\r\n\r\n\t\t\tif (pn == 36 && FlipCoin(10) && !IsObjectAtPosition(testPosition + Direction::NorthWest)) {\r\n\t\t\t\tAddObject(OBJ_TORCHL, testPosition + Direction::NorthWest);\r\n\t\t\t}\r\n\r\n\t\t\tif (pn == 40 && FlipCoin(10) && !IsObjectAtPosition(testPosition + Direction::NorthEast)) {\r\n\t\t\t\tAddObject(OBJ_TORCHR, testPosition + Direction::NorthEast);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddObjTraps()\r\n{\r\n\tint rndv;\r\n\tif (currlevel == 1)\r\n\t\trndv = 10;\r\n\tif (currlevel >= 2)\r\n\t\trndv = 15;\r\n\tif (currlevel >= 5)\r\n\t\trndv = 20;\r\n\tif (currlevel >= 7)\r\n\t\trndv = 25;\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) {\r\n\t\t\tObject *triggerObject = FindObjectAtPosition({ i, j }, false);\r\n\t\t\tif (triggerObject == nullptr || GenerateRnd(100) >= rndv)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif (!AllObjects[triggerObject->_otype].isTrap())\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tObject *trapObject = nullptr;\r\n\t\t\tif (FlipCoin()) {\r\n\t\t\t\tint xp = i - 1;\r\n\t\t\t\twhile (IsTileNotSolid({ xp, j }))\r\n\t\t\t\t\txp--;\r\n\r\n\t\t\t\tif (!CanPlaceWallTrap({ xp, j }) || i - xp <= 1)\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\ttrapObject = AddObject(OBJ_TRAPL, { xp, j });\r\n\t\t\t} else {\r\n\t\t\t\tint yp = j - 1;\r\n\t\t\t\twhile (IsTileNotSolid({ i, yp }))\r\n\t\t\t\t\typ--;\r\n\r\n\t\t\t\tif (!CanPlaceWallTrap({ i, yp }) || j - yp <= 1)\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\ttrapObject = AddObject(OBJ_TRAPR, { i, yp });\r\n\t\t\t}\r\n\r\n\t\t\tif (trapObject != nullptr) {\r\n\t\t\t\t// nullptr check just in case we fail to find a valid location to place a trap in the chosen direction\r\n\t\t\t\ttrapObject->_oVar1 = i;\r\n\t\t\t\ttrapObject->_oVar2 = j;\r\n\t\t\t\ttriggerObject->_oTrapFlag = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddChestTraps()\r\n{\r\n\tfor (int j = 0; j < MAXDUNY; j++) {\r\n\t\tfor (int i = 0; i < MAXDUNX; i++) { // NOLINT(modernize-loop-convert)\r\n\t\t\tObject *chestObject = FindObjectAtPosition({ i, j }, false);\r\n\t\t\tif (chestObject != nullptr && chestObject->IsUntrappedChest() && GenerateRnd(100) < 10) {\r\n\t\t\t\tswitch (chestObject->_otype) {\r\n\t\t\t\tcase OBJ_CHEST1:\r\n\t\t\t\t\tchestObject->_otype = OBJ_TCHEST1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase OBJ_CHEST2:\r\n\t\t\t\t\tchestObject->_otype = OBJ_TCHEST2;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase OBJ_CHEST3:\r\n\t\t\t\t\tchestObject->_otype = OBJ_TCHEST3;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tchestObject->_oTrapFlag = true;\r\n\t\t\t\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\t\t\t\tchestObject->_oVar4 = GenerateRnd(2);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tchestObject->_oVar4 = GenerateRnd(gbIsHellfire ? 6 : 3);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LoadMapObjects(const char *path, Point start, WorldTileRectangle mapRange = {}, int leveridx = 0)\r\n{\r\n\tLoadingMapObjects = true;\r\n\r\n\tauto dunData = LoadFileInMem<uint16_t>(path);\r\n\r\n\tWorldTileSize size = GetDunSize(dunData.get());\r\n\r\n\tconst int layer2Offset = 2 + size.width * size.height;\r\n\r\n\t// The rest of the layers are at dPiece scale\r\n\tsize *= static_cast<WorldTileCoord>(2);\r\n\r\n\tconst uint16_t *objectLayer = &dunData[layer2Offset + size.width * size.height * 2];\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tauto objectId = static_cast<uint8_t>(Swap16LE(objectLayer[j * size.width + i]));\r\n\t\t\tif (objectId != 0) {\r\n\t\t\t\tconst Point mapPos = start + Displacement { i, j };\r\n\t\t\t\tObject *mapObject = AddObject(ObjTypeConv[objectId], mapPos);\r\n\t\t\t\tif (leveridx > 0 && mapObject != nullptr)\r\n\t\t\t\t\tmapObject->InitializeLoadedObject(mapRange, leveridx);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tLoadingMapObjects = false;\r\n}\r\n\r\nvoid AddDiabObjs()\r\n{\r\n\tLoadMapObjects(\"levels\\\\l4data\\\\diab1.dun\", DiabloQuad1.megaToWorld(), { DiabloQuad2, { 11, 12 } }, 1);\r\n\tLoadMapObjects(\"levels\\\\l4data\\\\diab2a.dun\", DiabloQuad2.megaToWorld(), { DiabloQuad3, { 11, 11 } }, 2);\r\n\tLoadMapObjects(\"levels\\\\l4data\\\\diab3a.dun\", DiabloQuad3.megaToWorld(), { DiabloQuad4, { 9, 9 } }, 3);\r\n}\r\n\r\nvoid AddCryptObject(Object &object, int a2)\r\n{\r\n\tif (a2 > 5) {\r\n\t\tconst Player &myPlayer = *MyPlayer;\r\n\t\tswitch (a2) {\r\n\t\tcase 6:\r\n\t\t\tswitch (myPlayer._pClass) {\r\n\t\t\tcase HeroClass::Warrior:\r\n\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\tobject._oVar2 = TEXT_BOOKA;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\tobject._oVar2 = TEXT_RBOOKA;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\tobject._oVar2 = TEXT_MBOOKA;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Monk:\r\n\t\t\t\tobject._oVar2 = TEXT_OBOOKA;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Bard:\r\n\t\t\t\tobject._oVar2 = TEXT_BBOOKA;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 7:\r\n\t\t\tswitch (myPlayer._pClass) {\r\n\t\t\tcase HeroClass::Warrior:\r\n\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\tobject._oVar2 = TEXT_BOOKB;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\tobject._oVar2 = TEXT_RBOOKB;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\tobject._oVar2 = TEXT_MBOOKB;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Monk:\r\n\t\t\t\tobject._oVar2 = TEXT_OBOOKB;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Bard:\r\n\t\t\t\tobject._oVar2 = TEXT_BBOOKB;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 8:\r\n\t\t\tswitch (myPlayer._pClass) {\r\n\t\t\tcase HeroClass::Warrior:\r\n\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\tobject._oVar2 = TEXT_BOOKC;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\tobject._oVar2 = TEXT_RBOOKC;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\tobject._oVar2 = TEXT_MBOOKC;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Monk:\r\n\t\t\t\tobject._oVar2 = TEXT_OBOOKC;\r\n\t\t\t\tbreak;\r\n\t\t\tcase HeroClass::Bard:\r\n\t\t\t\tobject._oVar2 = TEXT_BBOOKC;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tobject._oVar3 = 15;\r\n\t\tobject._oVar8 = a2;\r\n\t} else {\r\n\t\tobject._oVar2 = a2 + TEXT_SKLJRN;\r\n\t\tobject._oVar3 = a2 + 9;\r\n\t\tobject._oVar8 = 0;\r\n\t}\r\n\tobject._oVar1 = 1;\r\n\tobject._oAnimFrame = 5 - 2 * object._oVar1;\r\n\tobject._oVar4 = object._oAnimFrame + 1;\r\n}\r\n\r\nvoid SetupObject(Object &object, Point position, _object_id ot)\r\n{\r\n\tconst ObjectData &objectData = AllObjects[ot];\r\n\tobject._otype = ot;\r\n\tobject_graphic_id ofi = objectData.ofindex;\r\n\tobject.position = position;\r\n\r\n\tif (!HeadlessMode) {\r\n\t\tconst auto &found = c_find(ObjFileList, ofi);\r\n\t\tif (found == std::end(ObjFileList)) {\r\n\t\t\tLogCritical(\"Unable to find object_graphic_id {} in list of objects to load, level generation error.\", static_cast<int>(ofi));\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst size_t j = std::distance(std::begin(ObjFileList), found);\r\n\r\n\t\tif (pObjCels[j]) {\r\n\t\t\tobject._oAnimData.emplace(*pObjCels[j]);\r\n\t\t} else {\r\n\t\t\tobject._oAnimData = std::nullopt;\r\n\t\t}\r\n\t}\r\n\tobject._oAnimFlag = objectData.isAnimated();\r\n\tif (object._oAnimFlag) {\r\n\t\tobject._oAnimDelay = objectData.animDelay;\r\n\t\tobject._oAnimCnt = GenerateRnd(object._oAnimDelay);\r\n\t\tobject._oAnimLen = objectData.animLen;\r\n\t\tobject._oAnimFrame = GenerateRnd(object._oAnimLen - 1) + 1;\r\n\t} else {\r\n\t\tobject._oAnimDelay = 1000;\r\n\t\tobject._oAnimCnt = 0;\r\n\t\tobject._oAnimLen = objectData.animLen;\r\n\t\tobject._oAnimFrame = objectData.animDelay;\r\n\t}\r\n\tobject._oAnimWidth = objectData.animWidth;\r\n\tobject._oSolidFlag = objectData.isSolid() ? 1 : 0;\r\n\tobject._oMissFlag = objectData.missilesPassThrough() ? 1 : 0;\r\n\tobject.applyLighting = objectData.applyLighting();\r\n\tobject._oDelFlag = false;\r\n\tobject._oBreak = objectData.isBreakable() ? 1 : 0;\r\n\tobject.selectionRegion = objectData.selectionRegion;\r\n\tobject._oPreFlag = false;\r\n\tobject._oTrapFlag = false;\r\n\tobject._oDoorFlag = false;\r\n}\r\n\r\nvoid AddCryptBook(_object_id ot, int v2, Point position)\r\n{\r\n\tif (ActiveObjectCount >= MAXOBJECTS)\r\n\t\treturn;\r\n\r\n\tconst int oi = AvailableObjects[0];\r\n\tAvailableObjects[0] = AvailableObjects[MAXOBJECTS - 1 - ActiveObjectCount];\r\n\tActiveObjects[ActiveObjectCount] = oi;\r\n\tdObject[position.x][position.y] = oi + 1;\r\n\tObject &object = Objects[oi];\r\n\tSetupObject(object, position, ot);\r\n\tAddCryptObject(object, v2);\r\n\tActiveObjectCount++;\r\n}\r\n\r\nvoid AddCryptStoryBook(int s)\r\n{\r\n\tstd::optional<Point> position = GetRandomObjectPosition({ 3, 2 });\r\n\tif (!position)\r\n\t\treturn;\r\n\tAddCryptBook(OBJ_L5BOOKS, s, *position);\r\n\tAddObject(OBJ_L5CANDLE, *position + Displacement { -2, 1 });\r\n\tAddObject(OBJ_L5CANDLE, *position + Displacement { -2, 0 });\r\n\tAddObject(OBJ_L5CANDLE, *position + Displacement { -1, -1 });\r\n\tAddObject(OBJ_L5CANDLE, *position + Displacement { 1, -1 });\r\n\tAddObject(OBJ_L5CANDLE, *position + Displacement { 2, 0 });\r\n\tAddObject(OBJ_L5CANDLE, *position + Displacement { 2, 1 });\r\n}\r\n\r\nvoid AddNakrulLever()\r\n{\r\n\twhile (true) {\r\n\t\tconst int xp = GenerateRnd(80) + 16;\r\n\t\tconst int yp = GenerateRnd(80) + 16;\r\n\t\tif (IsAreaOk(Rectangle { { xp - 1, yp - 1 }, { 3, 3 } })) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tAddObject(OBJ_L5LEVER, { UberRow + 3, UberCol - 1 });\r\n}\r\n\r\nvoid AddNakrulBook(int a1, Point position)\r\n{\r\n\tAddCryptBook(OBJ_L5BOOKS, a1, position);\r\n}\r\n\r\nvoid AddNakrulGate()\r\n{\r\n\tAddNakrulLever();\r\n\tswitch (GenerateRnd(6)) {\r\n\tcase 0:\r\n\t\tAddNakrulBook(6, { UberRow + 3, UberCol });\r\n\t\tAddNakrulBook(7, { UberRow + 2, UberCol - 3 });\r\n\t\tAddNakrulBook(8, { UberRow + 2, UberCol + 2 });\r\n\t\tbreak;\r\n\tcase 1:\r\n\t\tAddNakrulBook(6, { UberRow + 3, UberCol });\r\n\t\tAddNakrulBook(8, { UberRow + 2, UberCol - 3 });\r\n\t\tAddNakrulBook(7, { UberRow + 2, UberCol + 2 });\r\n\t\tbreak;\r\n\tcase 2:\r\n\t\tAddNakrulBook(7, { UberRow + 3, UberCol });\r\n\t\tAddNakrulBook(6, { UberRow + 2, UberCol - 3 });\r\n\t\tAddNakrulBook(8, { UberRow + 2, UberCol + 2 });\r\n\t\tbreak;\r\n\tcase 3:\r\n\t\tAddNakrulBook(7, { UberRow + 3, UberCol });\r\n\t\tAddNakrulBook(8, { UberRow + 2, UberCol - 3 });\r\n\t\tAddNakrulBook(6, { UberRow + 2, UberCol + 2 });\r\n\t\tbreak;\r\n\tcase 4:\r\n\t\tAddNakrulBook(8, { UberRow + 3, UberCol });\r\n\t\tAddNakrulBook(7, { UberRow + 2, UberCol - 3 });\r\n\t\tAddNakrulBook(6, { UberRow + 2, UberCol + 2 });\r\n\t\tbreak;\r\n\tcase 5:\r\n\t\tAddNakrulBook(8, { UberRow + 3, UberCol });\r\n\t\tAddNakrulBook(6, { UberRow + 2, UberCol - 3 });\r\n\t\tAddNakrulBook(7, { UberRow + 2, UberCol + 2 });\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid AddStoryBooks()\r\n{\r\n\tstd::optional<Point> position = GetRandomObjectPosition({ 3, 2 });\r\n\tif (!position)\r\n\t\treturn;\r\n\r\n\tAddObject(OBJ_STORYBOOK, *position);\r\n\tAddObject(OBJ_STORYCANDLE, *position + Displacement { -2, 1 });\r\n\tAddObject(OBJ_STORYCANDLE, *position + Displacement { -2, 0 });\r\n\tAddObject(OBJ_STORYCANDLE, *position + Displacement { -1, -1 });\r\n\tAddObject(OBJ_STORYCANDLE, *position + Displacement { 1, -1 });\r\n\tAddObject(OBJ_STORYCANDLE, *position + Displacement { 2, 0 });\r\n\tAddObject(OBJ_STORYCANDLE, *position + Displacement { 2, 1 });\r\n}\r\n\r\nvoid AddHookedBodies(int freq)\r\n{\r\n\tfor (WorldTileCoord j = 0; j < DMAXY; j++) {\r\n\t\tconst WorldTileCoord jj = 16 + j * 2;\r\n\t\tfor (WorldTileCoord i = 0; i < DMAXX; i++) {\r\n\t\t\tconst WorldTileCoord ii = 16 + i * 2;\r\n\t\t\tif (dungeon[i][j] != 1 && dungeon[i][j] != 2)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (!FlipCoin(freq))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (IsNearThemeRoom({ i, j }))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (dungeon[i][j] == 1 && dungeon[i + 1][j] == 6) {\r\n\t\t\t\tswitch (GenerateRnd(3)) {\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tAddObject(OBJ_TORTURE1, { ii + 1, jj });\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\tAddObject(OBJ_TORTURE2, { ii + 1, jj });\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\tAddObject(OBJ_TORTURE5, { ii + 1, jj });\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (dungeon[i][j] == 2 && dungeon[i][j + 1] == 6) {\r\n\t\t\t\tAddObject(PickRandomlyAmong({ OBJ_TORTURE3, OBJ_TORTURE4 }), { ii, jj });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddL4Goodies()\r\n{\r\n\tAddHookedBodies(6);\r\n\tInitRndLocObj(2, 6, OBJ_TNUDEM1);\r\n\tInitRndLocObj(2, 6, OBJ_TNUDEM2);\r\n\tInitRndLocObj(2, 6, OBJ_TNUDEM3);\r\n\tInitRndLocObj(2, 6, OBJ_TNUDEM4);\r\n\tInitRndLocObj(2, 6, OBJ_TNUDEW1);\r\n\tInitRndLocObj(2, 6, OBJ_TNUDEW2);\r\n\tInitRndLocObj(2, 6, OBJ_TNUDEW3);\r\n\tInitRndLocObj(2, 6, OBJ_DECAP);\r\n\tInitRndLocObj(1, 3, OBJ_CAULDRON);\r\n}\r\n\r\nvoid AddLazStand()\r\n{\r\n\tint cnt = 0;\r\n\tint xp;\r\n\tint yp;\r\n\twhile (true) {\r\n\t\txp = GenerateRnd(80) + 16;\r\n\t\typ = GenerateRnd(80) + 16;\r\n\r\n\t\tif (!IsAreaOk(Rectangle { { xp - 2, yp - 3 }, { 6, 7 } })) {\r\n\t\t\tcnt++;\r\n\t\t\tif (cnt > 10000) {\r\n\t\t\t\tInitRndLocObj(1, 1, OBJ_LAZSTAND);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tAddObject(OBJ_LAZSTAND, { xp, yp });\r\n\tAddObject(OBJ_TNUDEM2, { xp, yp + 2 });\r\n\tAddObject(OBJ_STORYCANDLE, { xp + 1, yp + 2 });\r\n\tAddObject(OBJ_TNUDEM3, { xp + 2, yp + 2 });\r\n\tAddObject(OBJ_TNUDEW1, { xp, yp - 2 });\r\n\tAddObject(OBJ_STORYCANDLE, { xp + 1, yp - 2 });\r\n\tAddObject(OBJ_TNUDEW2, { xp + 2, yp - 2 });\r\n\tAddObject(OBJ_STORYCANDLE, { xp - 1, yp - 1 });\r\n\tAddObject(OBJ_TNUDEW3, { xp - 1, yp });\r\n\tAddObject(OBJ_STORYCANDLE, { xp - 1, yp + 1 });\r\n}\r\n\r\nvoid DeleteObject(int oi, int i)\r\n{\r\n\tconst Object &object = Objects[oi];\r\n\tconst Point position = object.position;\r\n\tdObject[position.x][position.y] = 0;\r\n\tAvailableObjects[-ActiveObjectCount + MAXOBJECTS] = oi;\r\n\tActiveObjectCount--;\r\n\tif (ObjectUnderCursor == &object) // Unselect object if this was highlighted by player\r\n\t\tObjectUnderCursor = nullptr;\r\n\tif (ActiveObjectCount > 0 && i != ActiveObjectCount)\r\n\t\tActiveObjects[i] = ActiveObjects[ActiveObjectCount];\r\n}\r\n\r\nvoid AddChest(Object &chest)\r\n{\r\n\tif (FlipCoin())\r\n\t\tchest._oAnimFrame += 3;\r\n\tchest._oRndSeed = AdvanceRndSeed();\r\n\tswitch (chest._otype) {\r\n\tcase OBJ_CHEST1:\r\n\tcase OBJ_TCHEST1:\r\n\t\tif (setlevel) {\r\n\t\t\tchest._oVar1 = 1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tchest._oVar1 = GenerateRnd(2);\r\n\t\tbreak;\r\n\tcase OBJ_TCHEST2:\r\n\tcase OBJ_CHEST2:\r\n\t\tif (setlevel) {\r\n\t\t\tchest._oVar1 = 2;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tchest._oVar1 = GenerateRnd(3);\r\n\t\tbreak;\r\n\tcase OBJ_TCHEST3:\r\n\tcase OBJ_CHEST3:\r\n\t\tif (setlevel) {\r\n\t\t\tchest._oVar1 = 3;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tchest._oVar1 = GenerateRnd(4);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\tchest._oVar2 = GenerateRnd(8);\r\n}\r\n\r\nvoid ObjSetMicro(Point position, int pn)\r\n{\r\n\tdPiece[position.x][position.y] = pn;\r\n}\r\n\r\nvoid DoorSet(Point position, bool isLeftDoor)\r\n{\r\n\tconst int pn = dPiece[position.x][position.y];\r\n\tswitch (pn) {\r\n\tcase 42:\r\n\t\tObjSetMicro(position, 391);\r\n\t\tbreak;\r\n\tcase 44:\r\n\t\tObjSetMicro(position, 393);\r\n\t\tbreak;\r\n\tcase 49:\r\n\t\tObjSetMicro(position, isLeftDoor ? 410 : 411);\r\n\t\tbreak;\r\n\tcase 53:\r\n\t\tObjSetMicro(position, 396);\r\n\t\tbreak;\r\n\tcase 54:\r\n\t\tObjSetMicro(position, 397);\r\n\t\tbreak;\r\n\tcase 60:\r\n\t\tObjSetMicro(position, 398);\r\n\t\tbreak;\r\n\tcase 66:\r\n\t\tObjSetMicro(position, 399);\r\n\t\tbreak;\r\n\tcase 67:\r\n\t\tObjSetMicro(position, 400);\r\n\t\tbreak;\r\n\tcase 68:\r\n\t\tObjSetMicro(position, 402);\r\n\t\tbreak;\r\n\tcase 69:\r\n\t\tObjSetMicro(position, 403);\r\n\t\tbreak;\r\n\tcase 71:\r\n\t\tObjSetMicro(position, 405);\r\n\t\tbreak;\r\n\tcase 211:\r\n\t\tObjSetMicro(position, 406);\r\n\t\tbreak;\r\n\tcase 353:\r\n\t\tObjSetMicro(position, 408);\r\n\t\tbreak;\r\n\tcase 354:\r\n\t\tObjSetMicro(position, 409);\r\n\t\tbreak;\r\n\tcase 410:\r\n\tcase 411:\r\n\t\tObjSetMicro(position, 395);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid CryptDoorSet(Point position, bool isLeftDoor)\r\n{\r\n\tconst int pn = dPiece[position.x][position.y];\r\n\tswitch (pn) {\r\n\tcase 74:\r\n\t\tObjSetMicro(position, 203);\r\n\t\tbreak;\r\n\tcase 78:\r\n\t\tObjSetMicro(position, 207);\r\n\t\tbreak;\r\n\tcase 85:\r\n\t\tObjSetMicro(position, isLeftDoor ? 231 : 233);\r\n\t\tbreak;\r\n\tcase 90:\r\n\t\tObjSetMicro(position, 214);\r\n\t\tbreak;\r\n\tcase 92:\r\n\t\tObjSetMicro(position, 217);\r\n\t\tbreak;\r\n\tcase 98:\r\n\t\tObjSetMicro(position, 219);\r\n\t\tbreak;\r\n\tcase 110:\r\n\t\tObjSetMicro(position, 221);\r\n\t\tbreak;\r\n\tcase 112:\r\n\t\tObjSetMicro(position, 223);\r\n\t\tbreak;\r\n\tcase 114:\r\n\t\tObjSetMicro(position, 225);\r\n\t\tbreak;\r\n\tcase 116:\r\n\t\tObjSetMicro(position, 227);\r\n\t\tbreak;\r\n\tcase 118:\r\n\t\tObjSetMicro(position, 229);\r\n\t\tbreak;\r\n\tcase 231:\r\n\tcase 233:\r\n\t\tObjSetMicro(position, 211);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid SetDoorStateOpen(Object &door)\r\n{\r\n\tdoor._oVar4 = DOOR_OPEN;\r\n\tdoor._oPreFlag = true;\r\n\tdoor._oMissFlag = true;\r\n\tdoor.selectionRegion = SelectionRegion::Middle;\r\n\r\n\tswitch (door._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\t\t// 214: blood splater\r\n\t\t// 407: blood pool\r\n\t\t// 392: open door (no frame)\r\n\t\tObjSetMicro(door.position, door._oVar1 == 214 ? 407 : 392);\r\n\t\tdSpecial[door.position.x][door.position.y] = 7;\r\n\t\tDoorSet(door.position + Direction::NorthEast, true);\r\n\t\tbreak;\r\n\tcase OBJ_L1RDOOR:\r\n\t\tObjSetMicro(door.position, 394);\r\n\t\tdSpecial[door.position.x][door.position.y] = 8;\r\n\t\tDoorSet(door.position + Direction::NorthWest, false);\r\n\t\tbreak;\r\n\tcase OBJ_L2LDOOR:\r\n\t\tObjSetMicro(door.position, 12);\r\n\t\tdSpecial[door.position.x][door.position.y] = 5;\r\n\t\tbreak;\r\n\tcase OBJ_L2RDOOR:\r\n\t\tObjSetMicro(door.position, 16);\r\n\t\tdSpecial[door.position.x][door.position.y] = 6;\r\n\t\tbreak;\r\n\tcase OBJ_L3LDOOR:\r\n\t\tObjSetMicro(door.position, 537);\r\n\t\tbreak;\r\n\tcase OBJ_L3RDOOR:\r\n\t\tObjSetMicro(door.position, 540);\r\n\t\tbreak;\r\n\tcase OBJ_L5LDOOR:\r\n\t\tObjSetMicro(door.position, 205);\r\n\t\tCryptDoorSet(door.position + Direction::NorthEast, true);\r\n\t\tbreak;\r\n\tcase OBJ_L5RDOOR:\r\n\t\tObjSetMicro(door.position, 208);\r\n\t\tCryptDoorSet(door.position + Direction::NorthWest, false);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid SetDoorStateClosed(Object &door)\r\n{\r\n\tdoor._oVar4 = DOOR_CLOSED;\r\n\tdoor._oPreFlag = false;\r\n\tdoor._oMissFlag = false;\r\n\tdoor.selectionRegion = SelectionRegion::Bottom | SelectionRegion::Middle;\r\n\r\n\tswitch (door._otype) {\r\n\tcase OBJ_L1LDOOR: {\r\n\t\t// Clear overlapping arches\r\n\t\tdSpecial[door.position.x][door.position.y] = 0;\r\n\t\tObjSetMicro(door.position, door._oVar1 - 1);\r\n\r\n\t\t// Restore the normal tile where the open door used to be\r\n\t\tauto openPosition = door.position + Direction::NorthEast;\r\n\t\tif (door._oVar2 == 50 && dPiece[openPosition.x][openPosition.y] == 395)\r\n\t\t\tObjSetMicro(openPosition, 411);\r\n\t\telse\r\n\t\t\tObjSetMicro(openPosition, door._oVar2 - 1);\r\n\t\tbreak;\r\n\t} break;\r\n\tcase OBJ_L1RDOOR: {\r\n\t\t// Clear overlapping arches\r\n\t\tdSpecial[door.position.x][door.position.y] = 0;\r\n\t\tObjSetMicro(door.position, door._oVar1 - 1);\r\n\r\n\t\t// Restore the normal tile where the open door used to be\r\n\t\tauto openPosition = door.position + Direction::NorthWest;\r\n\t\tif (door._oVar2 == 50 && dPiece[openPosition.x][openPosition.y] == 395)\r\n\t\t\tObjSetMicro(openPosition, 410);\r\n\t\telse\r\n\t\t\tObjSetMicro(openPosition, door._oVar2 - 1);\r\n\t\tbreak;\r\n\t} break;\r\n\tcase OBJ_L2LDOOR:\r\n\t\t// Clear overlapping arches\r\n\t\tdSpecial[door.position.x][door.position.y] = 0;\r\n\t\tObjSetMicro(door.position, 537);\r\n\t\tbreak;\r\n\tcase OBJ_L2RDOOR:\r\n\t\t// Clear overlapping arches\r\n\t\tdSpecial[door.position.x][door.position.y] = 0;\r\n\t\tObjSetMicro(door.position, 539);\r\n\t\tbreak;\r\n\tcase OBJ_L3LDOOR:\r\n\t\tObjSetMicro(door.position, 530);\r\n\t\tbreak;\r\n\tcase OBJ_L3RDOOR:\r\n\t\tObjSetMicro(door.position, 533);\r\n\t\tbreak;\r\n\tcase OBJ_L5LDOOR: {\r\n\t\tObjSetMicro(door.position, door._oVar1 - 1);\r\n\r\n\t\t// Restore the normal tile where the open door used to be\r\n\t\tauto openPosition = door.position + Direction::NorthEast;\r\n\t\tif (door._oVar2 == 86 && dPiece[openPosition.x][openPosition.y] == 209)\r\n\t\t\tObjSetMicro(openPosition, 233);\r\n\t\telse\r\n\t\t\tObjSetMicro(openPosition, door._oVar2 - 1);\r\n\t} break;\r\n\tcase OBJ_L5RDOOR: {\r\n\t\tObjSetMicro(door.position, door._oVar1 - 1);\r\n\r\n\t\t// Restore the normal tile where the open door used to be\r\n\t\tauto openPosition = door.position + Direction::NorthWest;\r\n\t\tif (door._oVar2 == 86 && dPiece[openPosition.x][openPosition.y] == 209)\r\n\t\t\tObjSetMicro(openPosition, 231);\r\n\t\telse\r\n\t\t\tObjSetMicro(openPosition, door._oVar2 - 1);\r\n\t} break;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid AddDoor(Object &door)\r\n{\r\n\tdoor._oDoorFlag = true;\r\n\r\n\tswitch (door._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\t\tdoor._oVar1 = dPiece[door.position.x][door.position.y] + 1;\r\n\t\tdoor._oVar2 = dPiece[door.position.x][door.position.y - 1] + 1;\r\n\t\tbreak;\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tdoor._oVar1 = dPiece[door.position.x][door.position.y] + 1;\r\n\t\tdoor._oVar2 = dPiece[door.position.x - 1][door.position.y] + 1;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tSetDoorStateClosed(door);\r\n}\r\n\r\nvoid AddSarcophagus(Object &sarcophagus)\r\n{\r\n\tdObject[sarcophagus.position.x][sarcophagus.position.y - 1] = -(static_cast<int8_t>(sarcophagus.GetId()) + 1);\r\n\tsarcophagus._oVar1 = GenerateRnd(10);\r\n\tsarcophagus._oRndSeed = AdvanceRndSeed();\r\n\tif (sarcophagus._oVar1 >= 8) {\r\n\t\tMonster *monster = PreSpawnSkeleton();\r\n\t\tif (monster != nullptr) {\r\n\t\t\tsarcophagus._oVar2 = static_cast<int>(monster->getId());\r\n\t\t} else {\r\n\t\t\tsarcophagus._oVar2 = -1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddFlameTrap(Object &flameTrap)\r\n{\r\n\tflameTrap._oVar1 = trapid;\r\n\tflameTrap._oVar2 = 0;\r\n\tflameTrap._oVar3 = trapdir;\r\n\tflameTrap._oVar4 = 0;\r\n}\r\n\r\nvoid AddFlameLever(Object &flameLever)\r\n{\r\n\tflameLever._oVar1 = trapid;\r\n\tflameLever._oVar2 = static_cast<int8_t>(MissileID::InfernoControl);\r\n}\r\n\r\nvoid AddTrap(Object &trap)\r\n{\r\n\tint effectiveLevel = currlevel;\r\n\tif (leveltype == DTYPE_NEST)\r\n\t\teffectiveLevel -= 4;\r\n\telse if (leveltype == DTYPE_CRYPT)\r\n\t\teffectiveLevel -= 8;\r\n\r\n\tconst int missileType = GenerateRnd(effectiveLevel / 3 + 1);\r\n\tif (missileType == 0)\r\n\t\ttrap._oVar3 = static_cast<int8_t>(MissileID::Arrow);\r\n\tif (missileType == 1)\r\n\t\ttrap._oVar3 = static_cast<int8_t>(MissileID::Firebolt);\r\n\tif (missileType == 2)\r\n\t\ttrap._oVar3 = static_cast<int8_t>(MissileID::LightningControl);\r\n\ttrap._oVar4 = 0;\r\n}\r\n\r\nvoid AddObjectLight(Object &object)\r\n{\r\n\tint radius;\r\n\tswitch (object._otype) {\r\n\tcase OBJ_STORYCANDLE:\r\n\tcase OBJ_L5CANDLE:\r\n\t\tradius = 3;\r\n\t\tbreak;\r\n\tcase OBJ_L1LIGHT:\r\n\tcase OBJ_SKFIRE:\r\n\tcase OBJ_CANDLE1:\r\n\tcase OBJ_CANDLE2:\r\n\tcase OBJ_BOOKCANDLE:\r\n\tcase OBJ_BCROSS:\r\n\tcase OBJ_TBCROSS:\r\n\t\tradius = 5;\r\n\t\tbreak;\r\n\tcase OBJ_TORCHL:\r\n\tcase OBJ_TORCHR:\r\n\tcase OBJ_TORCHL2:\r\n\tcase OBJ_TORCHR2:\r\n\t\tradius = 8;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn;\r\n\t}\r\n\r\n\tDoLighting(object.position, radius, {});\r\n\tif (LoadingMapObjects) {\r\n\t\tDoUnLight(object.position, radius);\r\n\t\tUpdateLighting = true;\r\n\t}\r\n\tobject._oVar1 = -1;\r\n}\r\n\r\nvoid AddBarrel(Object &barrel)\r\n{\r\n\tbarrel._oVar1 = 0;\r\n\tbarrel._oRndSeed = AdvanceRndSeed();\r\n\tbarrel._oVar2 = barrel.isExplosive() ? 0 : GenerateRnd(10);\r\n\tbarrel._oVar3 = GenerateRnd(3);\r\n\r\n\tif (barrel._oVar2 >= 8) {\r\n\t\tMonster *skeleton = PreSpawnSkeleton();\r\n\t\tif (skeleton != nullptr) {\r\n\t\t\tbarrel._oVar4 = static_cast<int>(skeleton->getId());\r\n\t\t} else {\r\n\t\t\tbarrel._oVar4 = -1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddShrine(Object &shrine)\r\n{\r\n\tshrine._oRndSeed = AdvanceRndSeed();\r\n\tshrine._oPreFlag = true;\r\n\r\n\tconst int shrineCount = gbIsHellfire ? NumberOfShrineTypes : 26;\r\n\tbool slist[NumberOfShrineTypes] = {};\r\n\r\n\tfor (int i = 0; i < shrineCount; i++) {\r\n\t\tbool isShrineAvailable = true;\r\n\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tisShrineAvailable = (shrineavail[i] != ShrineTypeSingle);\r\n\t\t} else {\r\n\t\t\tisShrineAvailable = (shrineavail[i] != ShrineTypeMulti);\r\n\t\t}\r\n\r\n\t\tconst bool isEnchantedShrine = (i == ShrineEnchanted);\r\n\t\tconst bool isCorrectLevelType = IsAnyOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CATACOMBS);\r\n\r\n\t\tslist[i] = isShrineAvailable && (!isEnchantedShrine || isCorrectLevelType);\r\n\t}\r\n\r\n\tint selectedIndex;\r\n\tdo {\r\n\t\tselectedIndex = GenerateRnd(shrineCount);\r\n\t} while (!slist[selectedIndex]);\r\n\r\n\tshrine._oVar1 = selectedIndex;\r\n\r\n\tif (!FlipCoin()) {\r\n\t\tshrine._oAnimFrame = 12;\r\n\t\tshrine._oAnimLen = 22;\r\n\t}\r\n}\r\n\r\nvoid AddBookcase(Object &bookcase)\r\n{\r\n\tbookcase._oRndSeed = AdvanceRndSeed();\r\n\tbookcase._oPreFlag = true;\r\n}\r\n\r\nvoid AddLargeFountain(Object &fountain)\r\n{\r\n\tconst int ox = fountain.position.x;\r\n\tconst int oy = fountain.position.y;\r\n\tconst uint8_t id = -(static_cast<int8_t>(fountain.GetId()) + 1);\r\n\tdObject[ox][oy - 1] = id;\r\n\tdObject[ox - 1][oy] = id;\r\n\tdObject[ox - 1][oy - 1] = id;\r\n\tfountain._oRndSeed = AdvanceRndSeed();\r\n}\r\n\r\nvoid AddArmorStand(Object &armorStand)\r\n{\r\n\tif (!armorFlag) {\r\n\t\tarmorStand._oAnimFlag = true;\r\n\t\tarmorStand.selectionRegion = SelectionRegion::None;\r\n\t}\r\n\r\n\tarmorStand._oRndSeed = AdvanceRndSeed();\r\n}\r\n\r\nvoid AddDecapitatedBody(Object &decapitatedBody)\r\n{\r\n\tdecapitatedBody._oRndSeed = AdvanceRndSeed();\r\n\tdecapitatedBody._oAnimFrame = GenerateRnd(8) + 1;\r\n\tdecapitatedBody._oPreFlag = true;\r\n}\r\n\r\nvoid AddBookOfVileness(Object &bookOfVileness)\r\n{\r\n\tif (setlevel && setlvlnum == SL_VILEBETRAYER) {\r\n\t\tbookOfVileness._oAnimFrame = 4;\r\n\t}\r\n}\r\n\r\nvoid AddMagicCircle(Object &magicCircle)\r\n{\r\n\tmagicCircle._oRndSeed = AdvanceRndSeed();\r\n\tmagicCircle._oPreFlag = true;\r\n\tmagicCircle._oVar6 = 0;\r\n\tmagicCircle._oVar5 = 1;\r\n}\r\n\r\nvoid AddPedestalOfBlood(Object &pedestalOfBlood)\r\n{\r\n\tpedestalOfBlood._oVar1 = SetPiece.position.x;\r\n\tpedestalOfBlood._oVar2 = SetPiece.position.y;\r\n\tpedestalOfBlood._oVar3 = SetPiece.position.x + SetPiece.size.width;\r\n\tpedestalOfBlood._oVar4 = SetPiece.position.y + SetPiece.size.height;\r\n\tpedestalOfBlood._oVar6 = 0;\r\n}\r\n\r\nvoid AddStoryBook(Object &storyBook)\r\n{\r\n\tstoryBook._oVar1 = (DungeonSeeds[16] >> 16) % 3;\r\n\tif (currlevel == 4)\r\n\t\tstoryBook._oVar2 = StoryText[storyBook._oVar1][0];\r\n\telse if (currlevel == 8)\r\n\t\tstoryBook._oVar2 = StoryText[storyBook._oVar1][1];\r\n\telse if (currlevel == 12)\r\n\t\tstoryBook._oVar2 = StoryText[storyBook._oVar1][2];\r\n\tstoryBook._oVar3 = (currlevel / 4) + 3 * storyBook._oVar1 - 1;\r\n\tstoryBook._oAnimFrame = 5 - 2 * storyBook._oVar1;\r\n\tstoryBook._oVar4 = storyBook._oAnimFrame + 1;\r\n}\r\n\r\nvoid AddWeaponRack(Object &weaponRack)\r\n{\r\n\tif (!weaponFlag) {\r\n\t\tweaponRack._oAnimFlag = true;\r\n\t\tweaponRack.selectionRegion = SelectionRegion::None;\r\n\t}\r\n\tweaponRack._oRndSeed = AdvanceRndSeed();\r\n}\r\n\r\nvoid AddTorturedBody(Object &torturedBody)\r\n{\r\n\ttorturedBody._oRndSeed = AdvanceRndSeed();\r\n\ttorturedBody._oAnimFrame = GenerateRnd(4) + 1;\r\n\ttorturedBody._oPreFlag = true;\r\n}\r\n\r\nPoint GetRndObjLoc(int randarea)\r\n{\r\n\tif (randarea == 0)\r\n\t\treturn { 0, 0 };\r\n\r\n\tint tries = 0;\r\n\tint x;\r\n\tint y;\r\n\twhile (true) {\r\n\t\ttries++;\r\n\t\tif (tries > 1000 && randarea > 1)\r\n\t\t\trandarea--;\r\n\t\tx = GenerateRnd(MAXDUNX);\r\n\t\ty = GenerateRnd(MAXDUNY);\r\n\t\tif (IsAreaOk(Rectangle { { x, y }, { randarea, randarea } }))\r\n\t\t\tbreak;\r\n\t}\r\n\treturn { x, y };\r\n}\r\n\r\nvoid AddMushPatch()\r\n{\r\n\tif (ActiveObjectCount < MAXOBJECTS) {\r\n\t\tconst int i = AvailableObjects[0];\r\n\t\tconst Point loc = GetRndObjLoc(5);\r\n\t\tdObject[loc.x + 1][loc.y + 1] = -(i + 1);\r\n\t\tdObject[loc.x + 2][loc.y + 1] = -(i + 1);\r\n\t\tdObject[loc.x + 1][loc.y + 2] = -(i + 1);\r\n\t\tAddObject(OBJ_MUSHPATCH, { loc.x + 2, loc.y + 2 });\r\n\t}\r\n}\r\n\r\nbool IsLightVisible(Object &light, int lightRadius)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DisableLighting)\r\n\t\treturn false;\r\n#endif\r\n\r\n\tfor (const Player &player : Players) {\r\n\t\tif (!player.plractive)\r\n\t\t\tcontinue;\r\n\r\n\t\tif (!player.isOnActiveLevel())\r\n\t\t\tcontinue;\r\n\r\n\t\tif (player.position.tile.WalkingDistance(light.position) < lightRadius + 10) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid UpdateObjectLight(Object &light, int lightRadius)\r\n{\r\n\tif (light._oVar1 == -1) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (IsLightVisible(light, lightRadius)) {\r\n\t\tif (light._oVar1 == 0)\r\n\t\t\tlight._olid = AddLight(light.position, lightRadius);\r\n\t\tlight._oVar1 = 1;\r\n\t} else {\r\n\t\tif (light._oVar1 == 1)\r\n\t\t\tAddUnLight(light._olid);\r\n\t\tlight._oVar1 = 0;\r\n\t}\r\n}\r\n\r\nvoid UpdateCircle(Object &circle)\r\n{\r\n\tPlayer *playerOnCircle = PlayerAtPosition(circle.position);\r\n\r\n\tif (!playerOnCircle) {\r\n\t\tif (circle._otype == OBJ_MCIRCLE1)\r\n\t\t\tcircle._oAnimFrame = 1;\r\n\t\tif (circle._otype == OBJ_MCIRCLE2)\r\n\t\t\tcircle._oAnimFrame = 3;\r\n\t\tcircle._oVar6 = 0;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (circle._otype == OBJ_MCIRCLE1)\r\n\t\tcircle._oAnimFrame = 2;\r\n\tif (circle._otype == OBJ_MCIRCLE2)\r\n\t\tcircle._oAnimFrame = 4;\r\n\tif (circle.position == Point { 45, 47 }) {\r\n\t\tcircle._oVar6 = 2;\r\n\t} else if (circle.position == Point { 26, 46 }) {\r\n\t\tcircle._oVar6 = 1;\r\n\t} else {\r\n\t\tcircle._oVar6 = 0;\r\n\t}\r\n\tif (circle.position == Point { 35, 36 } && circle._oVar5 == 3) {\r\n\t\tcircle._oVar6 = 4;\r\n\t\tif (Quests[Q_BETRAYER]._qvar1 <= 4) {\r\n\t\t\tLoadingMapObjects = true;\r\n\t\t\tObjChangeMap(circle._oVar1, circle._oVar2, circle._oVar3, circle._oVar4);\r\n\t\t\tLoadingMapObjects = false;\r\n\t\t\tQuests[Q_BETRAYER]._qvar1 = 4;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_BETRAYER]);\r\n\t\t}\r\n\t\tAddMissile(playerOnCircle->position.tile, { 35, 46 }, Direction::South, MissileID::Phasing, TARGET_BOTH, *playerOnCircle, 0, 0);\r\n\t\tif (playerOnCircle == MyPlayer) {\r\n\t\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\t\tsgbMouseDown = CLICK_NONE;\r\n\t\t}\r\n\t\tClrPlrPath(*playerOnCircle);\r\n\t\tStartStand(*playerOnCircle, Direction::South);\r\n\t}\r\n}\r\n\r\nvoid ObjectStopAnim(Object &object)\r\n{\r\n\tif (object._oAnimFrame == object._oAnimLen) {\r\n\t\tobject._oAnimCnt = 0;\r\n\t\tobject._oAnimDelay = 1000;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Checks if an open door can be closed\r\n *\r\n * In order to be able to close a door the space where the closed door would be must be free of bodies, monsters, players, and items\r\n *\r\n * @param doorPosition Map tile where the door is in its closed position\r\n * @return true if the door is free to be closed, false if anything is blocking it\r\n */\r\ninline bool IsDoorClear(const Object &door)\r\n{\r\n\treturn dCorpse[door.position.x][door.position.y] == 0\r\n\t    && dMonster[door.position.x][door.position.y] == 0\r\n\t    && dItem[door.position.x][door.position.y] == 0\r\n\t    && dPlayer[door.position.x][door.position.y] == 0;\r\n}\r\n\r\nvoid UpdateDoor(Object &door)\r\n{\r\n\tif (door._oVar4 == DOOR_CLOSED) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tdoor._oVar4 = IsDoorClear(door) ? DOOR_OPEN : DOOR_BLOCKED;\r\n}\r\n\r\nvoid UpdateSarcophagus(Object &sarcophagus)\r\n{\r\n\tif (sarcophagus._oAnimFrame == sarcophagus._oAnimLen)\r\n\t\tsarcophagus._oAnimFlag = false;\r\n}\r\n\r\nvoid ActivateTrapLine(int ttype, int tid)\r\n{\r\n\tfor (int i = 0; i < ActiveObjectCount; i++) {\r\n\t\tObject &trap = Objects[ActiveObjects[i]];\r\n\t\tif (trap._otype == ttype && trap._oVar1 == tid) {\r\n\t\t\ttrap._oVar4 = 1;\r\n\t\t\ttrap._oAnimFlag = true;\r\n\t\t\ttrap._oAnimDelay = 1;\r\n\t\t\ttrap._olid = AddLight(trap.position, 1);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid UpdateFlameTrap(Object &trap)\r\n{\r\n\tif (trap._oVar2 != 0) {\r\n\t\tif (trap._oVar4 != 0) {\r\n\t\t\ttrap._oAnimFrame--;\r\n\t\t\tif (trap._oAnimFrame == 1) {\r\n\t\t\t\ttrap._oVar4 = 0;\r\n\t\t\t\tAddUnLight(trap._olid);\r\n\t\t\t} else if (trap._oAnimFrame <= 4) {\r\n\t\t\t\tChangeLightRadius(trap._olid, trap._oAnimFrame);\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (trap._oVar4 == 0) {\r\n\t\tif (trap._oVar3 == 2) {\r\n\t\t\tint x = trap.position.x - 2;\r\n\t\t\tconst int y = trap.position.y;\r\n\t\t\tfor (int j = 0; j < 5; j++) {\r\n\t\t\t\tif (dPlayer[x][y] != 0 || dMonster[x][y] != 0)\r\n\t\t\t\t\ttrap._oVar4 = 1;\r\n\t\t\t\tx++;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst int x = trap.position.x;\r\n\t\t\tint y = trap.position.y - 2;\r\n\t\t\tfor (int k = 0; k < 5; k++) {\r\n\t\t\t\tif (dPlayer[x][y] != 0 || dMonster[x][y] != 0)\r\n\t\t\t\t\ttrap._oVar4 = 1;\r\n\t\t\t\ty++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (trap._oVar4 != 0)\r\n\t\t\tActivateTrapLine(trap._otype, trap._oVar1);\r\n\t} else {\r\n\t\tconst int damage[6] = { 6, 8, 10, 12, 10, 12 };\r\n\r\n\t\tconst int mindam = damage[leveltype - 1];\r\n\t\tconst int maxdam = mindam * 2;\r\n\r\n\t\tconstexpr MissileID TrapMissile = MissileID::FireWallControl;\r\n\t\tMonster *monster = FindMonsterAtPosition(trap.position, true);\r\n\t\tif (monster != nullptr)\r\n\t\t\tMonsterTrapHit(*monster, mindam / 2, maxdam / 2, 0, TrapMissile, GetMissileData(TrapMissile).damageType(), false);\r\n\t\tPlayer *player = PlayerAtPosition(trap.position, true);\r\n\t\tif (player != nullptr) {\r\n\t\t\tbool unused;\r\n\t\t\tPlayerMHit(*player, nullptr, 0, mindam, maxdam, TrapMissile, GetMissileData(TrapMissile).damageType(), false, DeathReason::MonsterOrTrap, &unused);\r\n\t\t}\r\n\r\n\t\tif (trap._oAnimFrame == trap._oAnimLen)\r\n\t\t\ttrap._oAnimFrame = 11;\r\n\t\tif (trap._oAnimFrame <= 5)\r\n\t\t\tChangeLightRadius(trap._olid, trap._oAnimFrame);\r\n\t}\r\n}\r\n\r\nvoid UpdateBurningCrossDamage(Object &cross)\r\n{\r\n\tint damage[6] = { 6, 8, 10, 12, 10, 12 };\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer._pmode == PM_DEATH)\r\n\t\treturn;\r\n\r\n\tconst int8_t fireResist = myPlayer._pFireResist;\r\n\tif (fireResist > 0)\r\n\t\tdamage[leveltype - 1] -= fireResist * damage[leveltype - 1] / 100;\r\n\r\n\tif (myPlayer.position.tile != cross.position + Displacement { 0, -1 })\r\n\t\treturn;\r\n\r\n\tApplyPlrDamage(DamageType::Fire, myPlayer, 0, 0, damage[leveltype - 1]);\r\n\tif (!myPlayer.hasNoLife()) {\r\n\t\tmyPlayer.Say(HeroSpeech::Argh);\r\n\t}\r\n}\r\n\r\nvoid ObjSetMini(Point position, int v)\r\n{\r\n\tconst MegaTile mega = pMegaTiles[v - 1];\r\n\r\n\tconst Point megaOrigin = position.megaToWorld();\r\n\r\n\tObjSetMicro(megaOrigin, Swap16LE(mega.micro1));\r\n\tObjSetMicro(megaOrigin + Direction::SouthEast, Swap16LE(mega.micro2));\r\n\tObjSetMicro(megaOrigin + Direction::SouthWest, Swap16LE(mega.micro3));\r\n\tObjSetMicro(megaOrigin + Direction::South, Swap16LE(mega.micro4));\r\n}\r\n\r\nvoid ObjL1Special(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int i = y1; i <= y2; ++i) {\r\n\t\tfor (int j = x1; j <= x2; ++j) {\r\n\t\t\tdSpecial[j][i] = 0;\r\n\t\t\tif (dPiece[j][i] == 11)\r\n\t\t\t\tdSpecial[j][i] = 1;\r\n\t\t\tif (dPiece[j][i] == 10)\r\n\t\t\t\tdSpecial[j][i] = 2;\r\n\t\t\tif (dPiece[j][i] == 70)\r\n\t\t\t\tdSpecial[j][i] = 1;\r\n\t\t\tif (dPiece[j][i] == 252)\r\n\t\t\t\tdSpecial[j][i] = 3;\r\n\t\t\tif (dPiece[j][i] == 266)\r\n\t\t\t\tdSpecial[j][i] = 6;\r\n\t\t\tif (dPiece[j][i] == 258)\r\n\t\t\t\tdSpecial[j][i] = 5;\r\n\t\t\tif (dPiece[j][i] == 248)\r\n\t\t\t\tdSpecial[j][i] = 2;\r\n\t\t\tif (dPiece[j][i] == 324)\r\n\t\t\t\tdSpecial[j][i] = 2;\r\n\t\t\tif (dPiece[j][i] == 320)\r\n\t\t\t\tdSpecial[j][i] = 1;\r\n\t\t\tif (dPiece[j][i] == 254)\r\n\t\t\t\tdSpecial[j][i] = 4;\r\n\t\t\tif (dPiece[j][i] == 210)\r\n\t\t\t\tdSpecial[j][i] = 1;\r\n\t\t\tif (dPiece[j][i] == 343)\r\n\t\t\t\tdSpecial[j][i] = 2;\r\n\t\t\tif (dPiece[j][i] == 340)\r\n\t\t\t\tdSpecial[j][i] = 1;\r\n\t\t\tif (dPiece[j][i] == 330)\r\n\t\t\t\tdSpecial[j][i] = 2;\r\n\t\t\tif (dPiece[j][i] == 417)\r\n\t\t\t\tdSpecial[j][i] = 1;\r\n\t\t\tif (dPiece[j][i] == 420)\r\n\t\t\t\tdSpecial[j][i] = 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ObjL2Special(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j <= y2; j++) {\r\n\t\tfor (int i = x1; i <= x2; i++) {\r\n\t\t\tdSpecial[i][j] = 0;\r\n\t\t\tif (dPiece[i][j] == 540)\r\n\t\t\t\tdSpecial[i][j] = 5;\r\n\t\t\tif (dPiece[i][j] == 177)\r\n\t\t\t\tdSpecial[i][j] = 5;\r\n\t\t\tif (dPiece[i][j] == 550)\r\n\t\t\t\tdSpecial[i][j] = 5;\r\n\t\t\tif (dPiece[i][j] == 541)\r\n\t\t\t\tdSpecial[i][j] = 6;\r\n\t\t\tif (dPiece[i][j] == 552)\r\n\t\t\t\tdSpecial[i][j] = 6;\r\n\t\t}\r\n\t}\r\n\tfor (int j = y1; j <= y2; j++) {\r\n\t\tfor (int i = x1; i <= x2; i++) {\r\n\t\t\tif (dPiece[i][j] == 131) {\r\n\t\t\t\tdSpecial[i][j + 1] = 2;\r\n\t\t\t\tdSpecial[i][j + 2] = 1;\r\n\t\t\t}\r\n\t\t\tif (dPiece[i][j] == 134 || dPiece[i][j] == 138) {\r\n\t\t\t\tdSpecial[i + 1][j] = 3;\r\n\t\t\t\tdSpecial[i + 2][j] = 4;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid OpenDoor(Object &door)\r\n{\r\n\tdoor._oAnimFrame += 2;\r\n\tSetDoorStateOpen(door);\r\n}\r\n\r\nvoid CloseDoor(Object &door)\r\n{\r\n\tdoor._oAnimFrame -= 2;\r\n\tSetDoorStateClosed(door);\r\n}\r\n\r\nvoid OperateDoor(Object &door, bool sendflag)\r\n{\r\n\tconst bool isCrypt = IsAnyOf(door._otype, OBJ_L5LDOOR, OBJ_L5RDOOR);\r\n\tconst bool openDoor = door._oVar4 == DOOR_CLOSED;\r\n\r\n\tif (!openDoor && !IsDoorClear(door)) {\r\n\t\tPlaySfxLoc(isCrypt ? SfxID::CryptDoorClose : SfxID::DoorClose, door.position);\r\n\t\tdoor._oVar4 = DOOR_BLOCKED;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (openDoor) {\r\n\t\tPlaySfxLoc(isCrypt ? SfxID::CryptDoorOpen : SfxID::DoorOpen, door.position);\r\n\t\tOpenDoor(door);\r\n\t} else {\r\n\t\tPlaySfxLoc(isCrypt ? SfxID::CryptDoorClose : SfxID::DoorClose, door.position);\r\n\t\tCloseDoor(door);\r\n\t}\r\n\r\n\tRedoPlayerVision();\r\n\r\n\tif (sendflag)\r\n\t\tNetSendCmdLoc(MyPlayerId, true, openDoor ? CMD_OPENDOOR : CMD_CLOSEDOOR, door.position);\r\n}\r\n\r\nbool AreAllLeversActivated(int leverId)\r\n{\r\n\tfor (int j = 0; j < ActiveObjectCount; j++) {\r\n\t\tconst Object &lever = Objects[ActiveObjects[j]];\r\n\t\tif (lever._otype == OBJ_SWITCHSKL\r\n\t\t    && lever._oVar8 == leverId\r\n\t\t    && lever.canInteractWith()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid UpdateLeverState(Object &object)\r\n{\r\n\tif (!object.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tobject.selectionRegion = SelectionRegion::None;\r\n\tobject._oAnimFrame++;\r\n\r\n\tif (currlevel == 16 && !AreAllLeversActivated(object._oVar8))\r\n\t\treturn;\r\n\r\n\tif (currlevel == 24) {\r\n\t\tSyncNakrulRoom();\r\n\t\tIsUberLeverActivated = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (setlevel && setlvlnum == SL_VILEBETRAYER)\r\n\t\tObjectAtPosition({ 35, 36 })._oVar5++;\r\n\r\n\tObjChangeMap(object._oVar1, object._oVar2, object._oVar3, object._oVar4);\r\n}\r\n\r\nvoid OperateLever(Object &object, bool sendmsg)\r\n{\r\n\tif (!object.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySfxLoc(SfxID::OperateLever, object.position);\r\n\r\n\tUpdateLeverState(object);\r\n\r\n\tif (currlevel == 24) {\r\n\t\tPlaySfxLoc(SfxID::CryptDoorOpen, { UberRow, UberCol });\r\n\t\tQuests[Q_NAKRUL]._qactive = QUEST_DONE;\r\n\t\tNetSendCmdQuest(true, Quests[Q_NAKRUL]);\r\n\t}\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, object.position);\r\n}\r\n\r\nvoid OperateBook(Player &player, Object &book, bool sendmsg)\r\n{\r\n\tif (!book.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (setlevel && setlvlnum == SL_VILEBETRAYER) {\r\n\t\tPoint target {};\r\n\t\tif (book.position == Point { 26, 45 }) {\r\n\t\t\ttarget = { 27, 29 };\r\n\t\t} else if (book.position == Point { 45, 46 }) {\r\n\t\t\ttarget = { 43, 29 };\r\n\t\t} else {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tObject &circle = ObjectAtPosition(book.position + Direction::SouthWest);\r\n\t\tassert(circle._otype == OBJ_MCIRCLE2);\r\n\r\n\t\t// Only verify that the player stands on the circle when it's the local player (sendmsg), because for remote players the position could be desynced\r\n\t\tif (sendmsg && circle.position != player.position.tile) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tcircle._oVar6 = 4;\r\n\t\tObjectAtPosition({ 35, 36 })._oVar5++;\r\n\t\tAddMissile(player.position.tile, target, Direction::South, MissileID::Phasing, TARGET_BOTH, player, 0, 0);\r\n\t}\r\n\r\n\tbook.selectionRegion = SelectionRegion::None;\r\n\tbook._oAnimFrame++;\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, book.position);\r\n\r\n\tif (!setlevel) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (setlvlnum == SL_BONECHAMB) {\r\n\t\tif (sendmsg) {\r\n\t\t\tconst uint8_t newSpellLevel = player._pSplLvl[static_cast<int8_t>(SpellID::Guardian)] + 1;\r\n\t\t\tif (newSpellLevel <= MaxSpellLevel) {\r\n\t\t\t\tplayer._pSplLvl[static_cast<int8_t>(SpellID::Guardian)] = newSpellLevel;\r\n\t\t\t\tNetSendCmdParam2(true, CMD_CHANGE_SPELL_LEVEL, static_cast<uint16_t>(SpellID::Guardian), newSpellLevel);\r\n\t\t\t}\r\n\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tfor (Item &item : InventoryPlayerItemsRange { player }) {\r\n\t\t\t\t\titem.updateRequiredStatsCacheForPlayer(player);\r\n\t\t\t\t}\r\n\t\t\t\tif (IsStashOpen) {\r\n\t\t\t\t\tStash.RefreshItemStatFlags();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tQuests[Q_SCHAMB]._qactive = QUEST_DONE;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_SCHAMB]);\r\n\t\t}\r\n\t\tPlaySfxLoc(SfxID::QuestDone, book.position);\r\n\t\tInitDiabloMsg(EMSG_BONECHAMB);\r\n\t\tAddMissile(\r\n\t\t    player.position.tile,\r\n\t\t    book.position + Displacement { -2, -4 },\r\n\t\t    player._pdir,\r\n\t\t    MissileID::Guardian,\r\n\t\t    TARGET_MONSTERS,\r\n\t\t    player,\r\n\t\t    0,\r\n\t\t    0);\r\n\t}\r\n\tif (setlvlnum == SL_VILEBETRAYER) {\r\n\t\tObjChangeMap(\r\n\t\t    book._oVar1,\r\n\t\t    book._oVar2,\r\n\t\t    book._oVar3,\r\n\t\t    book._oVar4);\r\n\t\tfor (int j = 0; j < ActiveObjectCount; j++)\r\n\t\t\tSyncObjectAnim(Objects[ActiveObjects[j]]);\r\n\t}\r\n}\r\n\r\nvoid OperateBookLever(Object &questBook, bool sendmsg)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS) {\r\n\t\treturn;\r\n\t}\r\n\tif (questBook.canInteractWith() && !qtextflag) {\r\n\t\tif (questBook._otype == OBJ_BLINDBOOK && Quests[Q_BLIND]._qvar1 == 0) {\r\n\t\t\tQuests[Q_BLIND]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_BLIND]._qlog = true;\r\n\t\t\tQuests[Q_BLIND]._qvar1 = 1;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_BLIND]);\r\n\t\t}\r\n\t\tif (questBook._otype == OBJ_BLOODBOOK && Quests[Q_BLOOD]._qvar1 == 0) {\r\n\t\t\tQuests[Q_BLOOD]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_BLOOD]._qlog = true;\r\n\t\t\tQuests[Q_BLOOD]._qvar1 = 1;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_BLOOD]);\r\n\t\t\tif (sendmsg)\r\n\t\t\t\tSpawnQuestItem(IDI_BLDSTONE, SetPiece.position.megaToWorld() + Displacement { 9, 17 }, 0, SelectionRegion::Bottom, true);\r\n\t\t}\r\n\t\tif (questBook._otype == OBJ_STEELTOME && Quests[Q_WARLORD]._qvar1 == QS_WARLORD_INIT) {\r\n\t\t\tQuests[Q_WARLORD]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_WARLORD]._qlog = true;\r\n\t\t\tQuests[Q_WARLORD]._qvar1 = QS_WARLORD_STEELTOME_READ;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_WARLORD]);\r\n\t\t}\r\n\t\tif (questBook._oAnimFrame != questBook._oVar6) {\r\n\t\t\tif (questBook._otype != OBJ_BLOODBOOK)\r\n\t\t\t\tObjChangeMap(questBook._oVar1, questBook._oVar2, questBook._oVar3, questBook._oVar4);\r\n\t\t\tif (questBook._otype == OBJ_BLINDBOOK) {\r\n\t\t\t\tif (sendmsg)\r\n\t\t\t\t\tSpawnUnique(UITEM_OPTAMULET, SetPiece.position.megaToWorld() + Displacement { 5, 5 }, std::nullopt, true, true);\r\n\t\t\t\tauto tren = TransVal;\r\n\t\t\t\tTransVal = 9;\r\n\t\t\t\tDRLG_MRectTrans(WorldTilePosition(questBook._oVar1, questBook._oVar2), WorldTilePosition(questBook._oVar3, questBook._oVar4));\r\n\t\t\t\tTransVal = tren;\r\n\t\t\t}\r\n\t\t}\r\n\t\tquestBook._oAnimFrame = questBook._oVar6;\r\n\t\tInitQTextMsg(questBook.bookMessage);\r\n\t\tif (sendmsg)\r\n\t\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, questBook.position);\r\n\t}\r\n}\r\n\r\nvoid OperateChamberOfBoneBook(Object &questBook, bool sendmsg)\r\n{\r\n\tif (!questBook.canInteractWith() || qtextflag) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (questBook._oAnimFrame != questBook._oVar6) {\r\n\t\tObjChangeMapResync(questBook._oVar1, questBook._oVar2, questBook._oVar3, questBook._oVar4);\r\n\t\tfor (int j = 0; j < ActiveObjectCount; j++) {\r\n\t\t\tSyncObjectAnim(Objects[ActiveObjects[j]]);\r\n\t\t}\r\n\t}\r\n\tquestBook._oAnimFrame = questBook._oVar6;\r\n\tif (Quests[Q_SCHAMB]._qactive == QUEST_INIT) {\r\n\t\tQuests[Q_SCHAMB]._qactive = QUEST_ACTIVE;\r\n\t\tQuests[Q_SCHAMB]._qlog = true;\r\n\t}\r\n\r\n\t_speech_id textdef;\r\n\tswitch (MyPlayer->_pClass) {\r\n\tcase HeroClass::Warrior:\r\n\t\ttextdef = TEXT_BONER;\r\n\t\tbreak;\r\n\tcase HeroClass::Rogue:\r\n\t\ttextdef = TEXT_RBONER;\r\n\t\tbreak;\r\n\tcase HeroClass::Sorcerer:\r\n\t\ttextdef = TEXT_MBONER;\r\n\t\tbreak;\r\n\tcase HeroClass::Monk:\r\n\t\ttextdef = TEXT_HBONER;\r\n\t\tbreak;\r\n\tcase HeroClass::Bard:\r\n\t\ttextdef = TEXT_RBONER;\r\n\t\tbreak;\r\n\tcase HeroClass::Barbarian:\r\n\t\ttextdef = TEXT_BONER;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\tif (sendmsg) {\r\n\t\tQuests[Q_SCHAMB]._qmsg = textdef;\r\n\t\tNetSendCmdQuest(true, Quests[Q_SCHAMB]);\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, questBook.position);\r\n\t\tInitQTextMsg(textdef);\r\n\t}\r\n}\r\n\r\nvoid OperateChest(const Player &player, Object &chest, bool sendLootMsg)\r\n{\r\n\tif (!chest.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySfxLoc(SfxID::ChestOpen, chest.position);\r\n\tchest.selectionRegion = SelectionRegion::None;\r\n\tchest._oAnimFrame += 2;\r\n\tSetRndSeed(chest._oRndSeed);\r\n\tif (setlevel) {\r\n\t\tfor (int j = 0; j < chest._oVar1; j++) {\r\n\t\t\tCreateRndItem(chest.position, true, sendLootMsg, false);\r\n\t\t}\r\n\t} else {\r\n\t\tfor (int j = 0; j < chest._oVar1; j++) {\r\n\t\t\tif (chest._oVar2 != 0)\r\n\t\t\t\tCreateRndItem(chest.position, false, sendLootMsg, false);\r\n\t\t\telse\r\n\t\t\t\tCreateRndUseful(chest.position, sendLootMsg);\r\n\t\t}\r\n\t}\r\n\tif (chest.IsTrappedChest()) {\r\n\t\tconst Direction mdir = GetDirection(chest.position, player.position.tile);\r\n\t\tMissileID mtype;\r\n\t\tswitch (chest._oVar4) {\r\n\t\tcase 0:\r\n\t\t\tmtype = MissileID::Arrow;\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tmtype = MissileID::FireArrow;\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tmtype = MissileID::Nova;\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tmtype = MissileID::RingOfFire;\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\t\tmtype = MissileID::StealPotions;\r\n\t\t\tbreak;\r\n\t\tcase 5:\r\n\t\t\tmtype = MissileID::StealMana;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tmtype = MissileID::Arrow;\r\n\t\t}\r\n\t\tAddMissile(chest.position, player.position.tile, mdir, mtype, TARGET_PLAYERS, -1, 0, 0);\r\n\t\tPlaySfxLoc(SfxID::TriggerTrap, chest.position);\r\n\t\tchest._oTrapFlag = false;\r\n\t}\r\n\tif (&player == MyPlayer)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, chest.position);\r\n}\r\n\r\nvoid OperateMushroomPatch(const Player &player, Object &mushroomPatch)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (Quests[Q_MUSHROOM]._qactive != QUEST_ACTIVE) {\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tplayer.Say(HeroSpeech::ICantUseThisYet);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!mushroomPatch.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tmushroomPatch.selectionRegion = SelectionRegion::None;\r\n\tmushroomPatch._oAnimFrame++;\r\n\r\n\tPlaySfxLoc(SfxID::ChestOpen, mushroomPatch.position);\r\n\tconst Point pos = GetSuperItemLoc(mushroomPatch.position);\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tSpawnQuestItem(IDI_MUSHROOM, pos, 0, SelectionRegion::None, true);\r\n\t\tQuests[Q_MUSHROOM]._qvar1 = QS_MUSHSPAWNED;\r\n\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, mushroomPatch.position);\r\n\t}\r\n}\r\n\r\nvoid OperateInnSignChest(const Player &player, Object &questContainer, bool sendmsg)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (Quests[Q_LTBANNER]._qvar1 != 2) {\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tplayer.Say(HeroSpeech::ICantOpenThisYet);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!questContainer.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tquestContainer.selectionRegion = SelectionRegion::None;\r\n\tquestContainer._oAnimFrame += 2;\r\n\r\n\tPlaySfxLoc(SfxID::ChestOpen, questContainer.position);\r\n\r\n\tif (sendmsg) {\r\n\t\tconst Point pos = GetSuperItemLoc(questContainer.position);\r\n\t\tSpawnQuestItem(IDI_BANNER, pos, 0, SelectionRegion::None, true);\r\n\t\tNetSendCmdLoc(MyPlayerId, true, CMD_OPERATEOBJ, questContainer.position);\r\n\t}\r\n}\r\n\r\nvoid OperateSlainHero(const Player &player, Object &corpse, bool sendmsg)\r\n{\r\n\tif (!corpse.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\tcorpse.selectionRegion = SelectionRegion::None;\r\n\r\n\tSetRndSeed(corpse._oRndSeed);\r\n\r\n\tif (player._pClass == HeroClass::Warrior) {\r\n\t\tCreateMagicArmor(corpse.position, ItemType::HeavyArmor, ICURS_BREAST_PLATE, sendmsg, false);\r\n\t} else if (player._pClass == HeroClass::Rogue) {\r\n\t\tCreateMagicWeapon(corpse.position, ItemType::Bow, ICURS_LONG_BATTLE_BOW, sendmsg, false);\r\n\t} else if (player._pClass == HeroClass::Sorcerer) {\r\n\t\tCreateSpellBook(corpse.position, SpellID::Lightning, sendmsg, false);\r\n\t} else if (player._pClass == HeroClass::Monk) {\r\n\t\tCreateMagicWeapon(corpse.position, ItemType::Staff, ICURS_WAR_STAFF, sendmsg, false);\r\n\t} else if (player._pClass == HeroClass::Bard) {\r\n\t\tCreateMagicWeapon(corpse.position, ItemType::Sword, ICURS_BASTARD_SWORD, sendmsg, false);\r\n\t} else if (player._pClass == HeroClass::Barbarian) {\r\n\t\tCreateMagicWeapon(corpse.position, ItemType::Axe, ICURS_BATTLE_AXE, sendmsg, false);\r\n\t}\r\n\tMyPlayer->Say(HeroSpeech::RestInPeaceMyFriend);\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, corpse.position);\r\n}\r\n\r\nvoid OperateTrapLever(Object &flameLever)\r\n{\r\n\tPlaySfxLoc(SfxID::OperateLever, flameLever.position);\r\n\r\n\tif (flameLever._oAnimFrame == 1) {\r\n\t\tflameLever._oAnimFrame = 2;\r\n\t\tfor (int j = 0; j < ActiveObjectCount; j++) {\r\n\t\t\tObject &target = Objects[ActiveObjects[j]];\r\n\t\t\tif (target._otype == flameLever._oVar2 && target._oVar1 == flameLever._oVar1) {\r\n\t\t\t\ttarget._oVar2 = 1;\r\n\t\t\t\ttarget._oAnimFlag = false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tflameLever._oAnimFrame--;\r\n\tfor (int j = 0; j < ActiveObjectCount; j++) {\r\n\t\tObject &target = Objects[ActiveObjects[j]];\r\n\t\tif (target._otype == flameLever._oVar2 && target._oVar1 == flameLever._oVar1) {\r\n\t\t\ttarget._oVar2 = 0;\r\n\t\t\tif (target._oVar4 != 0) {\r\n\t\t\t\ttarget._oAnimFlag = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid OperateSarcophagus(Object &sarcophagus, bool sendMsg, bool sendLootMsg)\r\n{\r\n\tif (!sarcophagus.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySfxLoc(SfxID::Sarcophagus, sarcophagus.position);\r\n\tsarcophagus.selectionRegion = SelectionRegion::None;\r\n\tsarcophagus._oAnimFlag = true;\r\n\tsarcophagus._oAnimDelay = 3;\r\n\tSetRndSeed(sarcophagus._oRndSeed);\r\n\tif (sarcophagus._oVar1 <= 2)\r\n\t\tCreateRndItem(sarcophagus.position, false, sendLootMsg, false);\r\n\tif (sarcophagus._oVar1 >= 8 && sarcophagus._oVar2 >= 0)\r\n\t\tActivateSkeleton(Monsters[sarcophagus._oVar2], sarcophagus.position);\r\n\tif (sendMsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, sarcophagus.position);\r\n}\r\n\r\nvoid OperatePedestal(Player &player, Object &pedestal, bool sendmsg)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (pedestal._oVar6 == 3 || (sendmsg && !RemoveInventoryItemById(player, IDI_BLDSTONE))) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (sendmsg) {\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, pedestal.position);\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\t// Store added stones to pedestal in qvar2, because we get only one CMD_OPERATEOBJ from DeltaLoadLevel even if we add multiple stones\r\n\t\t\tQuests[Q_BLOOD]._qvar2++;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_BLOOD]);\r\n\t\t}\r\n\t}\r\n\r\n\tpedestal._oAnimFrame++;\r\n\tpedestal._oVar6++;\r\n\tif (pedestal._oVar6 == 1) {\r\n\t\tPlaySfxLoc(SfxID::SpellPuddle, pedestal.position);\r\n\t\tObjChangeMap(SetPiece.position.x, SetPiece.position.y + 3, SetPiece.position.x + 2, SetPiece.position.y + 7);\r\n\t\tif (sendmsg)\r\n\t\t\tSpawnQuestItem(IDI_BLDSTONE, SetPiece.position.megaToWorld() + Displacement { 3, 10 }, 0, SelectionRegion::Bottom, true);\r\n\t}\r\n\tif (pedestal._oVar6 == 2) {\r\n\t\tPlaySfxLoc(SfxID::SpellPuddle, pedestal.position);\r\n\t\tObjChangeMap(SetPiece.position.x + 6, SetPiece.position.y + 3, SetPiece.position.x + SetPiece.size.width, SetPiece.position.y + 7);\r\n\t\tif (sendmsg)\r\n\t\t\tSpawnQuestItem(IDI_BLDSTONE, SetPiece.position.megaToWorld() + Displacement { 15, 10 }, 0, SelectionRegion::Bottom, true);\r\n\t}\r\n\tif (pedestal._oVar6 == 3) {\r\n\t\tPlaySfxLoc(SfxID::SpellBloodStar, pedestal.position);\r\n\t\tObjChangeMap(pedestal._oVar1, pedestal._oVar2, pedestal._oVar3, pedestal._oVar4);\r\n\t\tLoadMapObjects(\"levels\\\\l2data\\\\blood2.dun\", SetPiece.position.megaToWorld());\r\n\t\tif (sendmsg)\r\n\t\t\tSpawnUnique(UITEM_ARMOFVAL, SetPiece.position.megaToWorld() + Displacement { 9, 3 }, std::nullopt, true, true);\r\n\t\tpedestal.selectionRegion = SelectionRegion::None;\r\n\t}\r\n}\r\n\r\nvoid OperateShrineMysterious(DiabloGenerator &rng, Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tModifyPlrStr(player, -1);\r\n\tModifyPlrMag(player, -1);\r\n\tModifyPlrDex(player, -1);\r\n\tModifyPlrVit(player, -1);\r\n\r\n\tswitch (static_cast<CharacterAttribute>(rng.generateRnd(4))) {\r\n\tcase CharacterAttribute::Strength:\r\n\t\tModifyPlrStr(player, 6);\r\n\t\tbreak;\r\n\tcase CharacterAttribute::Magic:\r\n\t\tModifyPlrMag(player, 6);\r\n\t\tbreak;\r\n\tcase CharacterAttribute::Dexterity:\r\n\t\tModifyPlrDex(player, 6);\r\n\t\tbreak;\r\n\tcase CharacterAttribute::Vitality:\r\n\t\tModifyPlrVit(player, 6);\r\n\t\tbreak;\r\n\t}\r\n\r\n\tCheckStats(player);\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_MYSTERIOUS);\r\n}\r\n\r\nvoid OperateShrineHidden(DiabloGenerator &rng, Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tint cnt = 0;\r\n\tfor (const auto &item : player.InvBody) {\r\n\t\tif (!item.isEmpty())\r\n\t\t\tcnt++;\r\n\t}\r\n\tif (cnt > 0) {\r\n\t\tfor (auto &item : player.InvBody) {\r\n\t\t\tif (!item.isEmpty()\r\n\t\t\t    && item._iMaxDur != DUR_INDESTRUCTIBLE\r\n\t\t\t    && item._iMaxDur != 0) {\r\n\t\t\t\titem._iDurability += 10;\r\n\t\t\t\titem._iMaxDur += 10;\r\n\t\t\t\tif (item._iDurability > item._iMaxDur)\r\n\t\t\t\t\titem._iDurability = item._iMaxDur;\r\n\t\t\t}\r\n\t\t}\r\n\t\twhile (true) {\r\n\t\t\tcnt = 0;\r\n\t\t\tfor (auto &item : player.InvBody) {\r\n\t\t\t\tif (!item.isEmpty() && item._iMaxDur != DUR_INDESTRUCTIBLE && item._iMaxDur != 0) {\r\n\t\t\t\t\tcnt++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (cnt == 0)\r\n\t\t\t\tbreak;\r\n\t\t\tconst int r = rng.generateRnd(NUM_INVLOC);\r\n\t\t\tif (player.InvBody[r].isEmpty() || player.InvBody[r]._iMaxDur == DUR_INDESTRUCTIBLE || player.InvBody[r]._iMaxDur == 0)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tplayer.InvBody[r]._iDurability -= 20;\r\n\t\t\tplayer.InvBody[r]._iMaxDur -= 20;\r\n\t\t\tif (player.InvBody[r]._iDurability <= 0)\r\n\t\t\t\tplayer.InvBody[r]._iDurability = 1;\r\n\t\t\tif (player.InvBody[r]._iMaxDur <= 0)\r\n\t\t\t\tplayer.InvBody[r]._iMaxDur = 1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_HIDDEN);\r\n}\r\n\r\nvoid OperateShrineGloomy(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\t// Increment armor class by 2 and decrements max damage by 1.\r\n\tfor (Item &item : PlayerItemsRange(player)) {\r\n\t\tswitch (item._itype) {\r\n\t\tcase ItemType::Sword:\r\n\t\tcase ItemType::Axe:\r\n\t\tcase ItemType::Bow:\r\n\t\tcase ItemType::Mace:\r\n\t\tcase ItemType::Staff:\r\n\t\t\titem._iMaxDam--;\r\n\t\t\tif (item._iMaxDam < item._iMinDam)\r\n\t\t\t\titem._iMaxDam = item._iMinDam;\r\n\t\t\tbreak;\r\n\t\tcase ItemType::Shield:\r\n\t\tcase ItemType::Helm:\r\n\t\tcase ItemType::LightArmor:\r\n\t\tcase ItemType::MediumArmor:\r\n\t\tcase ItemType::HeavyArmor:\r\n\t\t\titem._iAC += 2;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_GLOOMY);\r\n}\r\n\r\nvoid OperateShrineWeird(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tif (!player.InvBody[INVLOC_HAND_LEFT].isEmpty() && player.InvBody[INVLOC_HAND_LEFT]._itype != ItemType::Shield)\r\n\t\tplayer.InvBody[INVLOC_HAND_LEFT]._iMaxDam++;\r\n\tif (!player.InvBody[INVLOC_HAND_RIGHT].isEmpty() && player.InvBody[INVLOC_HAND_RIGHT]._itype != ItemType::Shield)\r\n\t\tplayer.InvBody[INVLOC_HAND_RIGHT]._iMaxDam++;\r\n\r\n\tfor (Item &item : InventoryPlayerItemsRange { player }) {\r\n\t\tswitch (item._itype) {\r\n\t\tcase ItemType::Sword:\r\n\t\tcase ItemType::Axe:\r\n\t\tcase ItemType::Bow:\r\n\t\tcase ItemType::Mace:\r\n\t\tcase ItemType::Staff:\r\n\t\t\titem._iMaxDam++;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_WEIRD);\r\n}\r\n\r\nvoid OperateShrineMagical(const Player &player)\r\n{\r\n\tAddMissile(\r\n\t    player.position.tile,\r\n\t    player.position.tile,\r\n\t    player._pdir,\r\n\t    MissileID::ManaShield,\r\n\t    TARGET_MONSTERS,\r\n\t    player,\r\n\t    0,\r\n\t    2 * leveltype);\r\n\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_MAGICAL);\r\n}\r\n\r\nvoid OperateShrineStone(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tfor (Item &item : PlayerItemsRange { player }) {\r\n\t\tif (item._itype == ItemType::Staff)\r\n\t\t\titem._iCharges = item._iMaxCharges;\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_STONE);\r\n}\r\n\r\nvoid OperateShrineReligious(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tfor (Item &item : PlayerItemsRange { player }) {\r\n\t\titem._iDurability = item._iMaxDur;\r\n\t}\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_RELIGIOUS);\r\n}\r\n\r\nvoid OperateShrineEnchanted(DiabloGenerator &rng, Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tint cnt = 0;\r\n\tuint64_t spell = 1;\r\n\tconst uint64_t spells = player._pMemSpells;\r\n\tfor (uint16_t j = 0; j < SpellsData.size(); j++) {\r\n\t\tif ((spell & spells) != 0)\r\n\t\t\tcnt++;\r\n\t\tspell *= 2;\r\n\t}\r\n\tif (cnt > 1) {\r\n\t\tint spellToReduce;\r\n\t\tdo {\r\n\t\t\tspellToReduce = rng.generateRnd(static_cast<int32_t>(SpellsData.size())) + 1;\r\n\t\t} while ((player._pMemSpells & GetSpellBitmask(static_cast<SpellID>(spellToReduce))) == 0);\r\n\r\n\t\tspell = 1;\r\n\t\tfor (uint8_t j = static_cast<uint8_t>(SpellID::Firebolt); j < SpellsData.size(); j++) {\r\n\t\t\tif ((player._pMemSpells & spell) != 0 && player._pSplLvl[j] < MaxSpellLevel && j != spellToReduce) {\r\n\t\t\t\tconst uint8_t newSpellLevel = static_cast<uint8_t>(player._pSplLvl[j] + 1);\r\n\t\t\t\tplayer._pSplLvl[j] = newSpellLevel;\r\n\t\t\t\tNetSendCmdParam2(true, CMD_CHANGE_SPELL_LEVEL, j, newSpellLevel);\r\n\t\t\t}\r\n\t\t\tspell *= 2;\r\n\t\t}\r\n\r\n\t\tif (player._pSplLvl[spellToReduce] > 0) {\r\n\t\t\tconst uint8_t newSpellLevel = static_cast<uint8_t>(player._pSplLvl[spellToReduce] - 1);\r\n\t\t\tplayer._pSplLvl[spellToReduce] = newSpellLevel;\r\n\t\t\tNetSendCmdParam2(true, CMD_CHANGE_SPELL_LEVEL, spellToReduce, newSpellLevel);\r\n\t\t}\r\n\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tfor (Item &item : InventoryPlayerItemsRange { player }) {\r\n\t\t\t\titem.updateRequiredStatsCacheForPlayer(player);\r\n\t\t\t}\r\n\t\t\tif (IsStashOpen) {\r\n\t\t\t\tStash.RefreshItemStatFlags();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_ENCHANTED);\r\n}\r\n\r\nvoid OperateShrineThaumaturgic(DiabloGenerator &rng, const Player &player)\r\n{\r\n\tfor (int j = 0; j < ActiveObjectCount; j++) {\r\n\t\tObject &object = Objects[ActiveObjects[j]];\r\n\t\tif (object.IsChest() && !object.canInteractWith()) {\r\n\t\t\tobject._oRndSeed = rng.advanceRndSeed();\r\n\t\t\tobject.selectionRegion = SelectionRegion::Bottom;\r\n\t\t\tobject._oAnimFrame -= 2;\r\n\t\t}\r\n\t}\r\n\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_THAUMATURGIC);\r\n}\r\n\r\nvoid OperateShrineCostOfWisdom(Player &player, SpellID spellId, diablo_message message)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tplayer._pMemSpells |= GetSpellBitmask(spellId);\r\n\r\n\tconst uint8_t curSpellLevel = player._pSplLvl[static_cast<int8_t>(spellId)];\r\n\tif (curSpellLevel < MaxSpellLevel) {\r\n\t\tconst uint8_t newSpellLevel = std::min(static_cast<uint8_t>(curSpellLevel + 2), MaxSpellLevel);\r\n\t\tplayer._pSplLvl[static_cast<int8_t>(spellId)] = newSpellLevel;\r\n\t\tNetSendCmdParam2(true, CMD_CHANGE_SPELL_LEVEL, static_cast<uint16_t>(spellId), newSpellLevel);\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tfor (Item &item : InventoryPlayerItemsRange { player }) {\r\n\t\t\titem.updateRequiredStatsCacheForPlayer(player);\r\n\t\t}\r\n\t\tif (IsStashOpen) {\r\n\t\t\tStash.RefreshItemStatFlags();\r\n\t\t}\r\n\t}\r\n\r\n\tint maxBase = player._pMaxManaBase;\r\n\r\n\tif (maxBase < 0) {\r\n\t\t// Fix bugged state; do not turn this into a \"negative penalty\" mana boost.\r\n\t\tplayer._pMaxManaBase = 0;\r\n\t\tmaxBase = 0;\r\n\t}\r\n\r\n\tconst int penalty = maxBase / 10; // 10% of max base mana (>= 0)\r\n\r\n\tplayer._pMaxManaBase -= penalty; // will remain >= 0\r\n\tplayer._pManaBase -= penalty;    // may go negative, allowed\r\n\tplayer._pMaxMana -= penalty;     // may go negative, allowed\r\n\tplayer._pMana -= penalty;        // may go negative, allowed\r\n\r\n\tRedrawEverything();\r\n\tInitDiabloMsg(message);\r\n}\r\n\r\nvoid OperateShrineCryptic(Player &player)\r\n{\r\n\tAddMissile(\r\n\t    player.position.tile,\r\n\t    player.position.tile,\r\n\t    player._pdir,\r\n\t    MissileID::Nova,\r\n\t    TARGET_MONSTERS,\r\n\t    player,\r\n\t    0,\r\n\t    2 * leveltype);\r\n\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tplayer._pMana = player._pMaxMana;\r\n\tplayer._pManaBase = player._pMaxManaBase;\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_CRYPTIC);\r\n\r\n\tRedrawEverything();\r\n}\r\n\r\nvoid OperateShrineEldritch(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tfor (Item &item : InventoryAndBeltPlayerItemsRange { player }) {\r\n\t\tif (item._itype != ItemType::Misc) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (IsAnyOf(item._iMiscId, IMISC_HEAL, IMISC_MANA)) {\r\n\t\t\t// Reinitializing the item zeroes out the seed, we save and restore here to avoid triggering false\r\n\t\t\t// positives on duplicated item checks (e.g. when picking up the item).\r\n\t\t\tauto seed = item._iSeed;\r\n\t\t\tInitializeItem(item, ItemMiscIdIdx(IMISC_REJUV));\r\n\t\t\titem._iSeed = seed;\r\n\t\t\titem._iStatFlag = true;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (IsAnyOf(item._iMiscId, IMISC_FULLHEAL, IMISC_FULLMANA)) {\r\n\t\t\t// As above.\r\n\t\t\tauto seed = item._iSeed;\r\n\t\t\tInitializeItem(item, ItemMiscIdIdx(IMISC_FULLREJUV));\r\n\t\t\titem._iSeed = seed;\r\n\t\t\titem._iStatFlag = true;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t}\r\n\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_ELDRITCH);\r\n}\r\n\r\nvoid OperateShrineEerie(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tModifyPlrMag(player, 2);\r\n\tCheckStats(player);\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_EERIE);\r\n}\r\n\r\n/**\r\n * @brief Fully restores HP and Mana of the active player and spawns a pair of potions\r\n *        in response to the player activating a Divine shrine\r\n * @param player The player who activated the shrine\r\n * @param spawnPosition The map tile where the potions will be spawned\r\n */\r\nvoid OperateShrineDivine(Player &player, Point spawnPosition)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tif (currlevel < 4) {\r\n\t\tCreateTypeItem(spawnPosition, false, ItemType::Misc, IMISC_FULLMANA, false, false, true);\r\n\t\tCreateTypeItem(spawnPosition, false, ItemType::Misc, IMISC_FULLHEAL, false, false, true);\r\n\t} else {\r\n\t\tCreateTypeItem(spawnPosition, false, ItemType::Misc, IMISC_FULLREJUV, false, false, true);\r\n\t\tCreateTypeItem(spawnPosition, false, ItemType::Misc, IMISC_FULLREJUV, false, false, true);\r\n\t}\r\n\r\n\tplayer._pMana = player._pMaxMana;\r\n\tplayer._pManaBase = player._pMaxManaBase;\r\n\tplayer._pHitPoints = player._pMaxHP;\r\n\tplayer._pHPBase = player._pMaxHPBase;\r\n\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_DIVINE);\r\n}\r\n\r\nvoid OperateShrineHoly(const Player &player)\r\n{\r\n\tAddMissile(player.position.tile, { 0, 0 }, Direction::South, MissileID::Phasing, TARGET_MONSTERS, player, 0, 2 * leveltype);\r\n\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_HOLY);\r\n}\r\n\r\nvoid OperateShrineSpiritual(DiabloGenerator &rng, Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tfor (int8_t &itemIndex : player.InvGrid) {\r\n\t\tif (itemIndex == 0) {\r\n\t\t\tItem &goldItem = player.InvList[player._pNumInv];\r\n\t\t\tMakeGoldStack(goldItem, 5 * leveltype + rng.generateRnd(10 * leveltype));\r\n\t\t\tplayer._pNumInv++;\r\n\t\t\titemIndex = player._pNumInv;\r\n\r\n\t\t\tplayer._pGold += goldItem._ivalue;\r\n\t\t}\r\n\t}\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_SPIRITUAL);\r\n}\r\n\r\nvoid OperateShrineSpooky(const Player &player)\r\n{\r\n\tif (&player == MyPlayer) {\r\n\t\tInitDiabloMsg(EMSG_SHRINE_SPOOKY1);\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tmyPlayer._pHitPoints = myPlayer._pMaxHP;\r\n\tmyPlayer._pHPBase = myPlayer._pMaxHPBase;\r\n\tmyPlayer._pMana = myPlayer._pMaxMana;\r\n\tmyPlayer._pManaBase = myPlayer._pMaxManaBase;\r\n\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_SPOOKY2);\r\n}\r\n\r\nvoid OperateShrineAbandoned(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tModifyPlrDex(player, 2);\r\n\tCheckStats(player);\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_ABANDONED);\r\n}\r\n\r\nvoid OperateShrineCreepy(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tModifyPlrStr(player, 2);\r\n\tCheckStats(player);\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_CREEPY);\r\n}\r\n\r\nvoid OperateShrineQuiet(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tModifyPlrVit(player, 2);\r\n\tCheckStats(player);\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_QUIET);\r\n}\r\n\r\nvoid OperateShrineSecluded(const Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tfor (int x = 0; x < DMAXX; x++)\r\n\t\tfor (int y = 0; y < DMAXY; y++)\r\n\t\t\tUpdateAutomapExplorer({ x, y }, MAP_EXP_SHRINE);\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_SECLUDED);\r\n}\r\n\r\nvoid OperateShrineGlimmering(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tfor (Item &item : PlayerItemsRange { player }) {\r\n\t\tif (item._iMagical != ITEM_QUALITY_NORMAL && !item._iIdentified) {\r\n\t\t\titem._iIdentified = true;\r\n\t\t}\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_GLIMMERING);\r\n}\r\n\r\nvoid OperateShrineTainted(DiabloGenerator &rng, const Player &player)\r\n{\r\n\tif (&player == MyPlayer) {\r\n\t\tInitDiabloMsg(EMSG_SHRINE_TAINTED1);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int r = rng.generateRnd(4);\r\n\r\n\tconst int v1 = r == 0 ? 1 : -1;\r\n\tconst int v2 = r == 1 ? 1 : -1;\r\n\tconst int v3 = r == 2 ? 1 : -1;\r\n\tconst int v4 = r == 3 ? 1 : -1;\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tModifyPlrStr(myPlayer, v1);\r\n\tModifyPlrMag(myPlayer, v2);\r\n\tModifyPlrDex(myPlayer, v3);\r\n\tModifyPlrVit(myPlayer, v4);\r\n\r\n\tCheckStats(myPlayer);\r\n\tCalcPlrInv(myPlayer, true);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_TAINTED2);\r\n}\r\n\r\n/**\r\n * @brief Oily shrines increase the players primary stat(s) by a total of two, but spawn a\r\n *        firewall near the shrine that will spread towards the player\r\n * @param player The player that will be affected by the shrine\r\n * @param spawnPosition Start location for the firewall\r\n */\r\nvoid OperateShrineOily(Player &player, Point spawnPosition)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tswitch (player._pClass) {\r\n\tcase HeroClass::Warrior:\r\n\t\tModifyPlrStr(player, 2);\r\n\t\tbreak;\r\n\tcase HeroClass::Rogue:\r\n\t\tModifyPlrDex(player, 2);\r\n\t\tbreak;\r\n\tcase HeroClass::Sorcerer:\r\n\t\tModifyPlrMag(player, 2);\r\n\t\tbreak;\r\n\tcase HeroClass::Barbarian:\r\n\t\tModifyPlrVit(player, 2);\r\n\t\tbreak;\r\n\tcase HeroClass::Monk:\r\n\t\tModifyPlrStr(player, 1);\r\n\t\tModifyPlrDex(player, 1);\r\n\t\tbreak;\r\n\tcase HeroClass::Bard:\r\n\t\tModifyPlrDex(player, 1);\r\n\t\tModifyPlrMag(player, 1);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tCheckStats(player);\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n\r\n\tAddMissile(\r\n\t    spawnPosition,\r\n\t    player.position.tile,\r\n\t    player._pdir,\r\n\t    MissileID::FireWall,\r\n\t    TARGET_PLAYERS,\r\n\t    -1,\r\n\t    2 * currlevel + 2,\r\n\t    0);\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_OILY);\r\n}\r\n\r\nvoid OperateShrineGlowing(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\t// Add 0-5 points to Magic (0.1% of the players XP)\r\n\tModifyPlrMag(player, static_cast<int>(std::min<uint32_t>(player._pExperience / 1000, 5)));\r\n\r\n\t// Take 5% of the players experience to offset the bonus, unless they're very low level in which case take all their experience.\r\n\tif (player._pExperience > 5000)\r\n\t\tplayer._pExperience = static_cast<uint32_t>(player._pExperience * 0.95);\r\n\telse\r\n\t\tplayer._pExperience = 0;\r\n\r\n\tCheckStats(player);\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_GLOWING);\r\n}\r\n\r\nvoid OperateShrineMendicant(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tconst int gold = player._pGold / 2;\r\n\tplayer.addExperience(gold);\r\n\tTakePlrsMoney(gold);\r\n\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_MENDICANT);\r\n}\r\n\r\n/**\r\n * @brief Grants experience to the player based on the current dungeon level while also triggering a magic trap\r\n * @param player The player that will be affected by the shrine\r\n * @param spawnPosition The trap results in casting flash from this location targeting the player\r\n */\r\nvoid OperateShrineSparkling(Player &player, Point spawnPosition)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tplayer.addExperience(1000 * currlevel);\r\n\r\n\tAddMissile(\r\n\t    spawnPosition,\r\n\t    player.position.tile,\r\n\t    player._pdir,\r\n\t    MissileID::FlashBottom,\r\n\t    TARGET_PLAYERS,\r\n\t    -1,\r\n\t    3 * currlevel + 2,\r\n\t    0);\r\n\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_SPARKLING);\r\n}\r\n\r\n/**\r\n * @brief Spawns a town portal near the active player\r\n * @param pnum The player that activated the shrine\r\n * @param spawnPosition The position of the shrine, the portal will be placed on the side closest to the player\r\n */\r\nvoid OperateShrineTown(const Player &player, Point spawnPosition)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tAddMissile(\r\n\t    spawnPosition,\r\n\t    player.position.tile,\r\n\t    player._pdir,\r\n\t    MissileID::TownPortal,\r\n\t    TARGET_MONSTERS,\r\n\t    player,\r\n\t    0,\r\n\t    0);\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_TOWN);\r\n}\r\n\r\nvoid OperateShrineShimmering(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tplayer._pMana = player._pMaxMana;\r\n\tplayer._pManaBase = player._pMaxManaBase;\r\n\r\n\tRedrawEverything();\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_SHIMMERING);\r\n}\r\n\r\nvoid OperateShrineSolar(Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tconst time_t timeResult = time(nullptr);\r\n\tconst std::tm *localtimeResult = localtime(&timeResult);\r\n\tconst int hour = localtimeResult != nullptr ? localtimeResult->tm_hour : 20;\r\n\tif (hour >= 20 || hour < 4) {\r\n\t\tInitDiabloMsg(EMSG_SHRINE_SOLAR4);\r\n\t\tModifyPlrVit(player, 2);\r\n\t} else if (hour >= 18) {\r\n\t\tInitDiabloMsg(EMSG_SHRINE_SOLAR3);\r\n\t\tModifyPlrMag(player, 2);\r\n\t} else if (hour >= 12) {\r\n\t\tInitDiabloMsg(EMSG_SHRINE_SOLAR2);\r\n\t\tModifyPlrStr(player, 2);\r\n\t} else /* 4:00 to 11:59 */ {\r\n\t\tInitDiabloMsg(EMSG_SHRINE_SOLAR1);\r\n\t\tModifyPlrDex(player, 2);\r\n\t}\r\n\r\n\tCheckStats(player);\r\n\tCalcPlrInv(player, true);\r\n\tRedrawEverything();\r\n}\r\n\r\nvoid OperateShrineMurphys(DiabloGenerator &rng, Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\r\n\tbool broke = false;\r\n\tfor (auto &item : player.InvBody) {\r\n\t\tif (!item.isEmpty() && rng.flipCoin(3)) {\r\n\t\t\tif (item._iDurability != DUR_INDESTRUCTIBLE) {\r\n\t\t\t\tif (item._iDurability > 0) {\r\n\t\t\t\t\titem._iDurability /= 2;\r\n\t\t\t\t\tbroke = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (!broke) {\r\n\t\tTakePlrsMoney(player._pGold / 3);\r\n\t}\r\n\r\n\tInitDiabloMsg(EMSG_SHRINE_MURPHYS);\r\n}\r\n\r\nvoid OperateShrine(Player &player, Object &shrine, SfxID sType)\r\n{\r\n\tif (!shrine.canInteractWith())\r\n\t\treturn;\r\n\r\n\tCloseGoldDrop();\r\n\r\n\tDiabloGenerator rng(shrine._oRndSeed);\r\n\tshrine.selectionRegion = SelectionRegion::None;\r\n\r\n\tPlaySfxLoc(sType, shrine.position);\r\n\tshrine._oAnimFlag = true;\r\n\tshrine._oAnimDelay = 1;\r\n\r\n\tswitch (shrine._oVar1) {\r\n\tcase ShrineMysterious:\r\n\t\tOperateShrineMysterious(rng, player);\r\n\t\tbreak;\r\n\tcase ShrineHidden:\r\n\t\tOperateShrineHidden(rng, player);\r\n\t\tbreak;\r\n\tcase ShrineGloomy:\r\n\t\tOperateShrineGloomy(player);\r\n\t\tbreak;\r\n\tcase ShrineWeird:\r\n\t\tOperateShrineWeird(player);\r\n\t\tbreak;\r\n\tcase ShrineMagical:\r\n\tcase ShrineMagicaL2:\r\n\t\tOperateShrineMagical(player);\r\n\t\tbreak;\r\n\tcase ShrineStone:\r\n\t\tOperateShrineStone(player);\r\n\t\tbreak;\r\n\tcase ShrineReligious:\r\n\t\tOperateShrineReligious(player);\r\n\t\tbreak;\r\n\tcase ShrineEnchanted:\r\n\t\tOperateShrineEnchanted(rng, player);\r\n\t\tbreak;\r\n\tcase ShrineThaumaturgic:\r\n\t\tOperateShrineThaumaturgic(rng, player);\r\n\t\tbreak;\r\n\tcase ShrineFascinating:\r\n\t\tOperateShrineCostOfWisdom(player, SpellID::Firebolt, EMSG_SHRINE_FASCINATING);\r\n\t\tbreak;\r\n\tcase ShrineCryptic:\r\n\t\tOperateShrineCryptic(player);\r\n\t\tbreak;\r\n\tcase ShrineEldritch:\r\n\t\tOperateShrineEldritch(player);\r\n\t\tbreak;\r\n\tcase ShrineEerie:\r\n\t\tOperateShrineEerie(player);\r\n\t\tbreak;\r\n\tcase ShrineDivine:\r\n\t\tOperateShrineDivine(player, shrine.position);\r\n\t\tbreak;\r\n\tcase ShrineHoly:\r\n\t\tOperateShrineHoly(player);\r\n\t\tbreak;\r\n\tcase ShrineSacred:\r\n\t\tOperateShrineCostOfWisdom(player, SpellID::ChargedBolt, EMSG_SHRINE_SACRED);\r\n\t\tbreak;\r\n\tcase ShrineSpiritual:\r\n\t\tOperateShrineSpiritual(rng, player);\r\n\t\tbreak;\r\n\tcase ShrineSpooky:\r\n\t\tOperateShrineSpooky(player);\r\n\t\tbreak;\r\n\tcase ShrineAbandoned:\r\n\t\tOperateShrineAbandoned(player);\r\n\t\tbreak;\r\n\tcase ShrineCreepy:\r\n\t\tOperateShrineCreepy(player);\r\n\t\tbreak;\r\n\tcase ShrineQuiet:\r\n\t\tOperateShrineQuiet(player);\r\n\t\tbreak;\r\n\tcase ShrineSecluded:\r\n\t\tOperateShrineSecluded(player);\r\n\t\tbreak;\r\n\tcase ShrineOrnate:\r\n\t\tOperateShrineCostOfWisdom(player, SpellID::HolyBolt, EMSG_SHRINE_ORNATE);\r\n\t\tbreak;\r\n\tcase ShrineGlimmering:\r\n\t\tOperateShrineGlimmering(player);\r\n\t\tbreak;\r\n\tcase ShrineTainted:\r\n\t\tOperateShrineTainted(rng, player);\r\n\t\tbreak;\r\n\tcase ShrineOily:\r\n\t\tOperateShrineOily(player, shrine.position);\r\n\t\tbreak;\r\n\tcase ShrineGlowing:\r\n\t\tOperateShrineGlowing(player);\r\n\t\tbreak;\r\n\tcase ShrineMendicant:\r\n\t\tOperateShrineMendicant(player);\r\n\t\tbreak;\r\n\tcase ShrineSparkling:\r\n\t\tOperateShrineSparkling(player, shrine.position);\r\n\t\tbreak;\r\n\tcase ShrineTown:\r\n\t\tOperateShrineTown(player, shrine.position);\r\n\t\tbreak;\r\n\tcase ShrineShimmering:\r\n\t\tOperateShrineShimmering(player);\r\n\t\tbreak;\r\n\tcase ShrineSolar:\r\n\t\tOperateShrineSolar(player);\r\n\t\tbreak;\r\n\tcase ShrineMurphys:\r\n\t\tOperateShrineMurphys(rng, player);\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (&player == MyPlayer)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, shrine.position);\r\n}\r\n\r\nvoid OperateBookStand(Object &bookStand, bool sendmsg, bool sendLootMsg)\r\n{\r\n\tif (!bookStand.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySfxLoc(SfxID::ItemScroll, bookStand.position);\r\n\tbookStand.selectionRegion = SelectionRegion::None;\r\n\tbookStand._oAnimFrame += 2;\r\n\tSetRndSeed(bookStand._oRndSeed);\r\n\tif (FlipCoin(5))\r\n\t\tCreateTypeItem(bookStand.position, false, ItemType::Misc, IMISC_BOOK, sendLootMsg, false);\r\n\telse\r\n\t\tCreateTypeItem(bookStand.position, false, ItemType::Misc, IMISC_SCROLL, sendLootMsg, false);\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, bookStand.position);\r\n}\r\n\r\nvoid OperateBookcase(Object &bookcase, bool sendmsg, bool sendLootMsg)\r\n{\r\n\tif (!bookcase.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySfxLoc(SfxID::ItemScroll, bookcase.position);\r\n\tbookcase.selectionRegion = SelectionRegion::None;\r\n\tbookcase._oAnimFrame -= 2;\r\n\tSetRndSeed(bookcase._oRndSeed);\r\n\tCreateTypeItem(bookcase.position, false, ItemType::Misc, IMISC_BOOK, sendLootMsg, false);\r\n\r\n\tif (Quests[Q_ZHAR].IsAvailable()) {\r\n\t\tMonster &zhar = Monsters[MAX_PLRS];\r\n\t\tif (zhar.mode == MonsterMode::Stand // prevents playing the \"angry\" message for the second time if zhar got aggroed by losing vision and talking again\r\n\t\t    && zhar.uniqueType == UniqueMonsterType::Zhar\r\n\t\t    && zhar.activeForTicks == UINT8_MAX\r\n\t\t    && zhar.hitPoints > 0) {\r\n\t\t\tzhar.talkMsg = TEXT_ZHAR2;\r\n\t\t\tM_StartStand(zhar, zhar.direction); // BUGFIX: first parameter in call to M_StartStand should be MAX_PLRS, not 0. (fixed)\r\n\t\t\tzhar.goal = MonsterGoal::Attack;\r\n\t\t\tif (sendmsg)\r\n\t\t\t\tzhar.mode = MonsterMode::Talk;\r\n\t\t}\r\n\t}\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, bookcase.position);\r\n}\r\n\r\nvoid OperateDecapitatedBody(Object &corpse, bool sendmsg, bool sendLootMsg)\r\n{\r\n\tif (!corpse.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\tcorpse.selectionRegion = SelectionRegion::None;\r\n\tSetRndSeed(corpse._oRndSeed);\r\n\tCreateRndItem(corpse.position, false, sendLootMsg, false);\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, corpse.position);\r\n}\r\n\r\nvoid OperateArmorStand(Object &armorStand, bool sendmsg, bool sendLootMsg)\r\n{\r\n\tif (!armorStand.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\tarmorStand.selectionRegion = SelectionRegion::None;\r\n\tarmorStand._oAnimFrame++;\r\n\tSetRndSeed(armorStand._oRndSeed);\r\n\tconst bool uniqueRnd = !FlipCoin();\r\n\tif (currlevel <= 5) {\r\n\t\tCreateTypeItem(armorStand.position, true, ItemType::LightArmor, IMISC_NONE, sendLootMsg, false);\r\n\t} else if (currlevel >= 6 && currlevel <= 9) {\r\n\t\tCreateTypeItem(armorStand.position, uniqueRnd, ItemType::MediumArmor, IMISC_NONE, sendLootMsg, false);\r\n\t} else if (currlevel >= 10 && currlevel <= 12) {\r\n\t\tCreateTypeItem(armorStand.position, false, ItemType::HeavyArmor, IMISC_NONE, sendLootMsg, false);\r\n\t} else if (currlevel >= 13) {\r\n\t\tCreateTypeItem(armorStand.position, true, ItemType::HeavyArmor, IMISC_NONE, sendLootMsg, false);\r\n\t}\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, armorStand.position);\r\n}\r\n\r\nint FindValidShrine()\r\n{\r\n\tfor (;;) {\r\n\t\tconst int rv = GenerateRnd(gbIsHellfire ? NumberOfShrineTypes : 26);\r\n\t\tif ((rv == ShrineEnchanted && !IsAnyOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CATACOMBS)) || rv == ShrineThaumaturgic)\r\n\t\t\tcontinue;\r\n\t\tif (gbIsMultiplayer && shrineavail[rv] == ShrineTypeSingle)\r\n\t\t\tcontinue;\r\n\t\tif (!gbIsMultiplayer && shrineavail[rv] == ShrineTypeMulti)\r\n\t\t\tcontinue;\r\n\t\treturn rv;\r\n\t}\r\n}\r\n\r\nvoid OperateGoatShrine(Player &player, Object &object, SfxID sType)\r\n{\r\n\tSetRndSeed(object._oRndSeed);\r\n\tobject._oVar1 = FindValidShrine();\r\n\tOperateShrine(player, object, sType);\r\n\tobject._oAnimDelay = 2;\r\n\tRedrawEverything();\r\n}\r\n\r\nvoid OperateCauldron(Player &player, Object &object, SfxID sType)\r\n{\r\n\tSetRndSeed(object._oRndSeed);\r\n\tobject._oVar1 = FindValidShrine();\r\n\tOperateShrine(player, object, sType);\r\n\tobject._oAnimFrame = 3;\r\n\tobject._oAnimFlag = false;\r\n\tRedrawEverything();\r\n}\r\n\r\nbool OperateFountains(Player &player, Object &fountain)\r\n{\r\n\tbool applied = false;\r\n\tswitch (fountain._otype) {\r\n\tcase OBJ_BLOODFTN:\r\n\t\tif (&player != MyPlayer)\r\n\t\t\treturn false;\r\n\r\n\t\tif (player._pHitPoints < player._pMaxHP) {\r\n\t\t\tPlaySfxLoc(SfxID::OperateFountain, fountain.position);\r\n\t\t\tplayer._pHitPoints += 64;\r\n\t\t\tplayer._pHPBase += 64;\r\n\t\t\tif (player._pHitPoints > player._pMaxHP) {\r\n\t\t\t\tplayer._pHitPoints = player._pMaxHP;\r\n\t\t\t\tplayer._pHPBase = player._pMaxHPBase;\r\n\t\t\t}\r\n\t\t\tapplied = true;\r\n\t\t} else\r\n\t\t\tPlaySfxLoc(SfxID::OperateFountain, fountain.position);\r\n\t\tbreak;\r\n\tcase OBJ_PURIFYINGFTN:\r\n\t\tif (&player != MyPlayer)\r\n\t\t\treturn false;\r\n\r\n\t\tif (player._pMana < player._pMaxMana) {\r\n\t\t\tPlaySfxLoc(SfxID::OperateFountain, fountain.position);\r\n\r\n\t\t\tplayer._pMana += 64;\r\n\t\t\tplayer._pManaBase += 64;\r\n\t\t\tif (player._pMana > player._pMaxMana) {\r\n\t\t\t\tplayer._pMana = player._pMaxMana;\r\n\t\t\t\tplayer._pManaBase = player._pMaxManaBase;\r\n\t\t\t}\r\n\r\n\t\t\tapplied = true;\r\n\t\t} else\r\n\t\t\tPlaySfxLoc(SfxID::OperateFountain, fountain.position);\r\n\t\tbreak;\r\n\tcase OBJ_MURKYFTN:\r\n\t\tif (!fountain.canInteractWith())\r\n\t\t\tbreak;\r\n\t\tPlaySfxLoc(SfxID::OperateFountain, fountain.position);\r\n\t\tfountain.selectionRegion = SelectionRegion::None;\r\n\t\tAddMissile(\r\n\t\t    player.position.tile,\r\n\t\t    player.position.tile,\r\n\t\t    player._pdir,\r\n\t\t    MissileID::Infravision,\r\n\t\t    TARGET_MONSTERS,\r\n\t\t    player,\r\n\t\t    0,\r\n\t\t    2 * leveltype);\r\n\t\tapplied = true;\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, fountain.position);\r\n\t\tbreak;\r\n\tcase OBJ_TEARFTN: {\r\n\t\tif (!fountain.canInteractWith())\r\n\t\t\tbreak;\r\n\t\tPlaySfxLoc(SfxID::OperateFountain, fountain.position);\r\n\t\tfountain.selectionRegion = SelectionRegion::None;\r\n\t\tif (&player != MyPlayer)\r\n\t\t\treturn false;\r\n\r\n\t\tconst unsigned randomValue = (fountain._oRndSeed >> 16) % 12;\r\n\t\tconst unsigned fromStat = randomValue / 3;\r\n\t\tunsigned toStat = randomValue % 3;\r\n\t\tif (toStat >= fromStat)\r\n\t\t\ttoStat++;\r\n\r\n\t\tconst std::pair<unsigned, int> alterations[] = { { fromStat, -1 }, { toStat, 1 } };\r\n\t\tfor (const auto &[stat, delta] : alterations) {\r\n\t\t\tswitch (stat) {\r\n\t\t\tcase 0:\r\n\t\t\t\tModifyPlrStr(player, delta);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tModifyPlrMag(player, delta);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tModifyPlrDex(player, delta);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tModifyPlrVit(player, delta);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tCheckStats(player);\r\n\t\tapplied = true;\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, fountain.position);\r\n\t} break;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\tRedrawEverything();\r\n\treturn applied;\r\n}\r\n\r\nvoid OperateWeaponRack(Object &weaponRack, bool sendmsg, bool sendLootMsg)\r\n{\r\n\tif (!weaponRack.canInteractWith())\r\n\t\treturn;\r\n\tSetRndSeed(weaponRack._oRndSeed);\r\n\r\n\tconst ItemType weaponType { PickRandomlyAmong({ ItemType::Sword, ItemType::Axe, ItemType::Bow, ItemType::Mace }) };\r\n\r\n\tweaponRack.selectionRegion = SelectionRegion::None;\r\n\tweaponRack._oAnimFrame++;\r\n\r\n\tCreateTypeItem(weaponRack.position, leveltype != DTYPE_CATHEDRAL, weaponType, IMISC_NONE, sendLootMsg, false);\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, weaponRack.position);\r\n}\r\n\r\n/**\r\n * @brief Checks whether the player is activating Na-Krul's spell tomes in the correct order\r\n *\r\n * Used as part of the final Diablo: Hellfire quest (from the hints provided to the player in the\r\n * reconstructed note). This function both updates the state of the variable that tracks progress\r\n * and also determines whether the spawn conditions are met (i.e. all tomes have been triggered\r\n * in the correct order).\r\n *\r\n * @param s the id of the spell tome\r\n * @return true if the player has activated all three tomes in the correct order, false otherwise\r\n */\r\nbool OperateNakrulBook(int s)\r\n{\r\n\tswitch (s) {\r\n\tcase 6:\r\n\t\tNaKrulTomeSequence = 1;\r\n\t\tbreak;\r\n\tcase 7:\r\n\t\tif (NaKrulTomeSequence == 1) {\r\n\t\t\tNaKrulTomeSequence = 2;\r\n\t\t} else {\r\n\t\t\tNaKrulTomeSequence = 0;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase 8:\r\n\t\tif (NaKrulTomeSequence == 2)\r\n\t\t\treturn true;\r\n\t\tNaKrulTomeSequence = 0;\r\n\t\tbreak;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid OperateStoryBook(Object &storyBook)\r\n{\r\n\tif (!storyBook.canInteractWith() || qtextflag) {\r\n\t\treturn;\r\n\t}\r\n\tstoryBook._oAnimFrame = storyBook._oVar4;\r\n\tPlaySfxLoc(SfxID::ItemScroll, storyBook.position);\r\n\tauto msg = static_cast<_speech_id>(storyBook._oVar2);\r\n\tif (storyBook._oVar8 != 0 && currlevel == 24) {\r\n\t\tif (!IsUberLeverActivated && Quests[Q_NAKRUL]._qactive != QUEST_DONE && OperateNakrulBook(storyBook._oVar8)) {\r\n\t\t\tNetSendCmd(false, CMD_NAKRUL);\r\n\t\t\treturn;\r\n\t\t}\r\n\t} else if (leveltype == DTYPE_CRYPT && Quests[Q_NAKRUL]._qactive != QUEST_DONE) {\r\n\t\tQuests[Q_NAKRUL]._qactive = QUEST_ACTIVE;\r\n\t\tQuests[Q_NAKRUL]._qlog = true;\r\n\t\tQuests[Q_NAKRUL]._qmsg = msg;\r\n\t\tNetSendCmdQuest(true, Quests[Q_NAKRUL]);\r\n\t}\r\n\tInitQTextMsg(msg);\r\n\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, storyBook.position);\r\n}\r\n\r\nvoid OperateLazStand(Object &stand)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!stand.canInteractWith() || qtextflag) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tstand._oAnimFrame++;\r\n\tstand.selectionRegion = SelectionRegion::None;\r\n\tconst Point pos = GetSuperItemLoc(stand.position);\r\n\tSpawnQuestItem(IDI_LAZSTAFF, pos, 0, SelectionRegion::None, true);\r\n\tNetSendCmdLoc(MyPlayerId, false, CMD_OPERATEOBJ, stand.position);\r\n}\r\n\r\n/**\r\n * @brief Checks if all active crux objects of the given type have been broken.\r\n *\r\n * Called by BreakCrux and SyncCrux to see if the linked map area needs to be updated. In practice I think this is\r\n * always true when called by BreakCrux as there *should* only be one instance of each crux with a given _oVar8 value?\r\n *\r\n * @param cruxType Discriminator/type (_oVar8 value) of the crux object which is currently changing state\r\n * @return true if all active cruxes of that type on the level are broken, false if at least one remains unbroken\r\n */\r\nbool AreAllCruxesOfTypeBroken(int cruxType)\r\n{\r\n\tfor (int j = 0; j < ActiveObjectCount; j++) {\r\n\t\tconst auto &testObject = Objects[ActiveObjects[j]];\r\n\t\tif (!testObject.IsCrux())\r\n\t\t\tcontinue; // Not a Crux object, keep searching\r\n\t\tif (cruxType != testObject._oVar8 || testObject._oBreak == -1)\r\n\t\t\tcontinue; // Found either a different crux or a previously broken crux, keep searching\r\n\r\n\t\t// Found an unbroken crux of this type\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid BreakCrux(Object &crux, bool sendmsg)\r\n{\r\n\tif (!crux.canInteractWith())\r\n\t\treturn;\r\n\r\n\tcrux._oAnimFlag = true;\r\n\tcrux._oAnimFrame = 1;\r\n\tcrux._oAnimDelay = 1;\r\n\tcrux._oSolidFlag = true;\r\n\tcrux._oMissFlag = true;\r\n\tcrux._oBreak = -1;\r\n\tcrux.selectionRegion = SelectionRegion::None;\r\n\r\n\tif (sendmsg)\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_BREAKOBJ, crux.position);\r\n\r\n\tif (!AreAllCruxesOfTypeBroken(crux._oVar8))\r\n\t\treturn;\r\n\r\n\tPlaySfxLoc(SfxID::OperateLever, crux.position);\r\n\tObjChangeMap(crux._oVar1, crux._oVar2, crux._oVar3, crux._oVar4);\r\n}\r\n\r\nvoid BreakBarrel(const Player &player, Object &barrel, bool forcebreak, bool sendmsg)\r\n{\r\n\tif (!barrel.canInteractWith())\r\n\t\treturn;\r\n\tif (!forcebreak && &player != MyPlayer) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tbarrel._oAnimFlag = true;\r\n\tbarrel._oAnimFrame = 1;\r\n\tbarrel._oAnimDelay = 1;\r\n\tbarrel._oSolidFlag = false;\r\n\tbarrel._oMissFlag = true;\r\n\tbarrel._oBreak = -1;\r\n\tbarrel.selectionRegion = SelectionRegion::None;\r\n\tbarrel._oPreFlag = true;\r\n\r\n\tif (barrel.isExplosive()) {\r\n\t\tif (barrel._otype == _object_id::OBJ_URNEX)\r\n\t\t\tPlaySfxLoc(SfxID::UrnExpload, barrel.position);\r\n\t\telse if (barrel._otype == _object_id::OBJ_PODEX)\r\n\t\t\tPlaySfxLoc(SfxID::PodExpload, barrel.position);\r\n\t\telse\r\n\t\t\tPlaySfxLoc(SfxID::BarrelExpload, barrel.position);\r\n\t\tfor (int yp = barrel.position.y - 1; yp <= barrel.position.y + 1; yp++) {\r\n\t\t\tfor (int xp = barrel.position.x - 1; xp <= barrel.position.x + 1; xp++) {\r\n\t\t\t\tconstexpr MissileID TrapMissile = MissileID::Firebolt;\r\n\t\t\t\tMonster *monster = FindMonsterAtPosition({ xp, yp }, true);\r\n\t\t\t\tif (monster != nullptr) {\r\n\t\t\t\t\tMonsterTrapHit(*monster, 1, 4, 0, TrapMissile, GetMissileData(TrapMissile).damageType(), false);\r\n\t\t\t\t}\r\n\t\t\t\tPlayer *adjacentPlayer = PlayerAtPosition({ xp, yp }, true);\r\n\t\t\t\tif (adjacentPlayer != nullptr) {\r\n\t\t\t\t\tbool unused;\r\n\t\t\t\t\tPlayerMHit(*adjacentPlayer, nullptr, 0, 8, 16, TrapMissile, GetMissileData(TrapMissile).damageType(), false, DeathReason::MonsterOrTrap, &unused);\r\n\t\t\t\t}\r\n\t\t\t\t// don't really need to exclude large objects as explosive barrels are single tile objects, but using considerLargeObjects == false as this matches the old logic.\r\n\t\t\t\tObject *adjacentObject = FindObjectAtPosition({ xp, yp }, false);\r\n\t\t\t\tif (adjacentObject != nullptr && adjacentObject->isExplosive() && !adjacentObject->IsBroken()) {\r\n\t\t\t\t\tBreakBarrel(player, *adjacentObject, true, sendmsg);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tif (barrel._otype == _object_id::OBJ_URN)\r\n\t\t\tPlaySfxLoc(SfxID::UrnBreak, barrel.position);\r\n\t\telse if (barrel._otype == _object_id::OBJ_POD)\r\n\t\t\tPlaySfxLoc(SfxID::PodPop, barrel.position);\r\n\t\telse\r\n\t\t\tPlaySfxLoc(SfxID::BarrelBreak, barrel.position);\r\n\t\tSetRndSeed(barrel._oRndSeed);\r\n\t\tif (barrel._oVar2 <= 1) {\r\n\t\t\tif (barrel._oVar3 == 0)\r\n\t\t\t\tCreateRndUseful(barrel.position, sendmsg);\r\n\t\t\telse\r\n\t\t\t\tCreateRndItem(barrel.position, false, sendmsg, false);\r\n\t\t}\r\n\t\tif (barrel._oVar2 >= 8 && barrel._oVar4 >= 0)\r\n\t\t\tActivateSkeleton(Monsters[barrel._oVar4], barrel.position);\r\n\t}\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdLoc(MyPlayerId, false, CMD_BREAKOBJ, barrel.position);\r\n\t}\r\n}\r\n\r\nvoid SyncCrux(const Object &crux)\r\n{\r\n\tif (AreAllCruxesOfTypeBroken(crux._oVar8))\r\n\t\tObjChangeMap(crux._oVar1, crux._oVar2, crux._oVar3, crux._oVar4);\r\n}\r\n\r\nvoid SyncLever(const Object &lever)\r\n{\r\n\tif (lever.canInteractWith())\r\n\t\treturn;\r\n\r\n\tif (currlevel == 16 && !AreAllLeversActivated(lever._oVar8))\r\n\t\treturn;\r\n\r\n\tObjChangeMap(lever._oVar1, lever._oVar2, lever._oVar3, lever._oVar4);\r\n}\r\n\r\nvoid SyncQSTLever(const Object &qstLever)\r\n{\r\n\tif (qstLever._oAnimFrame == qstLever._oVar6) {\r\n\t\tif (qstLever._otype != OBJ_BLOODBOOK)\r\n\t\t\tObjChangeMapResync(qstLever._oVar1, qstLever._oVar2, qstLever._oVar3, qstLever._oVar4);\r\n\t\tif (qstLever._otype == OBJ_BLINDBOOK) {\r\n\t\t\tauto tren = TransVal;\r\n\t\t\tTransVal = 9;\r\n\t\t\tDRLG_MRectTrans(WorldTilePosition(qstLever._oVar1, qstLever._oVar2), WorldTilePosition(qstLever._oVar3, qstLever._oVar4));\r\n\t\t\tTransVal = tren;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SyncPedestal(const Object &pedestal)\r\n{\r\n\tif (pedestal._oVar6 == 1)\r\n\t\tObjChangeMapResync(SetPiece.position.x, SetPiece.position.y + 3, SetPiece.position.x + 2, SetPiece.position.y + 7);\r\n\tif (pedestal._oVar6 == 2) {\r\n\t\tObjChangeMapResync(SetPiece.position.x, SetPiece.position.y + 3, SetPiece.position.x + 2, SetPiece.position.y + 7);\r\n\t\tObjChangeMapResync(SetPiece.position.x + 6, SetPiece.position.y + 3, SetPiece.position.x + SetPiece.size.width, SetPiece.position.y + 7);\r\n\t}\r\n\tif (pedestal._oVar6 >= 3) {\r\n\t\tObjChangeMapResync(pedestal._oVar1, pedestal._oVar2, pedestal._oVar3, pedestal._oVar4);\r\n\t\tLoadMapObjects(\"levels\\\\l2data\\\\blood2.dun\", SetPiece.position.megaToWorld());\r\n\t}\r\n}\r\n\r\nvoid UpdatePedestalState(Object &pedestal)\r\n{\r\n\tconst int addedStones = Quests[Q_BLOOD]._qvar2;\r\n\tpedestal._oAnimFrame += addedStones;\r\n\tpedestal._oVar6 += addedStones;\r\n\tSyncPedestal(pedestal);\r\n\tif (pedestal._oVar6 >= 3)\r\n\t\tpedestal.selectionRegion = SelectionRegion::None;\r\n}\r\n\r\nvoid SyncDoor(Object &door)\r\n{\r\n\tif (door._oVar4 == DOOR_CLOSED) {\r\n\t\tSetDoorStateClosed(door);\r\n\t} else {\r\n\t\tSetDoorStateOpen(door);\r\n\t}\r\n}\r\n\r\nvoid ResyncDoors(WorldTilePosition p1, WorldTilePosition p2, bool sendmsg)\r\n{\r\n\tconst WorldTileSize size { static_cast<WorldTileCoord>(p2.x - p1.x), static_cast<WorldTileCoord>(p2.y - p1.y) };\r\n\tconst WorldTileRectangle area { p1, size };\r\n\r\n\tfor (const WorldTilePosition p : PointsInRectangle { area }) {\r\n\t\tObject *obj = FindObjectAtPosition(p);\r\n\t\tif (obj == nullptr)\r\n\t\t\tcontinue;\r\n\t\tif (IsNoneOf(obj->_otype, OBJ_L1LDOOR, OBJ_L1RDOOR, OBJ_L2LDOOR, OBJ_L2RDOOR, OBJ_L3LDOOR, OBJ_L3RDOOR, OBJ_L5LDOOR, OBJ_L5RDOOR))\r\n\t\t\tcontinue;\r\n\t\tSyncDoor(*obj);\r\n\t\tif (sendmsg) {\r\n\t\t\tconst bool isOpen = obj->_oVar4 == DOOR_OPEN;\r\n\t\t\tNetSendCmdLoc(MyPlayerId, true, isOpen ? CMD_OPENDOOR : CMD_CLOSEDOOR, obj->position);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid UpdateState(Object &object, int frame)\r\n{\r\n\tif (!object.canInteractWith()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tobject.selectionRegion = SelectionRegion::None;\r\n\tobject._oAnimFrame = frame;\r\n\tobject._oAnimFlag = false;\r\n}\r\n\r\n} // namespace\r\n\r\nunsigned int Object::GetId() const\r\n{\r\n\treturn std::abs(dObject[position.x][position.y]) - 1;\r\n}\r\n\r\nbool Object::IsDisabled() const\r\n{\r\n\tif (!*GetOptions().Gameplay.disableCripplingShrines) {\r\n\t\treturn false;\r\n\t}\r\n\tif (IsAnyOf(_otype, _object_id::OBJ_GOATSHRINE, _object_id::OBJ_CAULDRON)) {\r\n\t\treturn true;\r\n\t}\r\n\tif (!IsShrine()) {\r\n\t\treturn false;\r\n\t}\r\n\treturn IsAnyOf(static_cast<shrine_type>(_oVar1), shrine_type::ShrineFascinating, shrine_type::ShrineOrnate, shrine_type::ShrineSacred, shrine_type::ShrineMurphys);\r\n}\r\n\r\nObject *FindObjectAtPosition(Point position, bool considerLargeObjects)\r\n{\r\n\tif (!InDungeonBounds(position)) {\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tauto objectId = dObject[position.x][position.y];\r\n\r\n\tif (objectId > 0 || (considerLargeObjects && objectId != 0)) {\r\n\t\treturn &Objects[std::abs(objectId) - 1];\r\n\t}\r\n\r\n\t// nothing at this position, return a nullptr\r\n\treturn nullptr;\r\n}\r\n\r\nbool IsItemBlockingObjectAtPosition(Point position)\r\n{\r\n\tObject *object = FindObjectAtPosition(position);\r\n\tif (object != nullptr && object->_oSolidFlag) {\r\n\t\t// solid object\r\n\t\treturn true;\r\n\t}\r\n\r\n\tobject = FindObjectAtPosition(position + Direction::South);\r\n\tif (object != nullptr && object->canInteractWith()) {\r\n\t\t// An unopened container or breakable object exists which potentially overlaps this tile, the player might not be able to pick up an item dropped here.\r\n\t\treturn true;\r\n\t}\r\n\r\n\tobject = FindObjectAtPosition(position + Direction::SouthEast, false);\r\n\tif (object != nullptr) {\r\n\t\tObject *otherDoor = FindObjectAtPosition(position + Direction::SouthWest, false);\r\n\t\tif (otherDoor != nullptr && object->canInteractWith() && otherDoor->canInteractWith()) {\r\n\t\t\t// Two interactive objects potentially overlap both sides of this tile, as above the player might not be able to pick up an item which is dropped here.\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\ntl::expected<void, std::string> LoadLevelObjects(uint16_t filesWidths[65])\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn {};\r\n\r\n\tfor (const ObjectData objectData : AllObjects) {\r\n\t\tif (leveltype == objectData.olvltype) {\r\n\t\t\tfilesWidths[objectData.ofindex] = objectData.animWidth;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (size_t i = 0, n = ObjMasterLoadList.size(); i < n; ++i) {\r\n\t\tif (filesWidths[i] == 0) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tObjFileList[numobjfiles] = static_cast<object_graphic_id>(i);\r\n\t\tchar filestr[32];\r\n\t\t*BufCopy(filestr, \"objects\\\\\", ObjMasterLoadList[i]) = '\\0';\r\n\t\tASSIGN_OR_RETURN(pObjCels[numobjfiles], LoadCelWithStatus(filestr, filesWidths[i]));\r\n\t\tnumobjfiles++;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\ntl::expected<void, std::string> InitObjectGFX()\r\n{\r\n\tuint16_t filesWidths[65] = {};\r\n\r\n\tif (IsAnyOf(currlevel, 4, 8, 12)) {\r\n\t\tfor (const auto id : { OBJ_STORYBOOK, OBJ_STORYCANDLE }) {\r\n\t\t\tconst ObjectData &obj = AllObjects[id];\r\n\t\t\tfilesWidths[obj.ofindex] = obj.animWidth;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (size_t id = 0, n = AllObjects.size(); id < n; ++id) {\r\n\t\tconst ObjectData &objectData = AllObjects[id];\r\n\t\tif (objectData.minlvl != 0 && currlevel >= objectData.minlvl && currlevel <= objectData.maxlvl) {\r\n\t\t\tif (IsAnyOf(static_cast<_object_id>(id), OBJ_TRAPL, OBJ_TRAPR) && leveltype == DTYPE_HELL) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tfilesWidths[objectData.ofindex] = objectData.animWidth;\r\n\t\t}\r\n\t\tif (objectData.otheme != THEME_NONE) {\r\n\t\t\tfor (int j = 0; j < numthemes; j++) {\r\n\t\t\t\tif (themes[j].ttype == objectData.otheme) {\r\n\t\t\t\t\tfilesWidths[objectData.ofindex] = objectData.animWidth;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (objectData.oquest != Q_INVALID && Quests[objectData.oquest].IsAvailable()) {\r\n\t\t\tfilesWidths[objectData.ofindex] = objectData.animWidth;\r\n\t\t}\r\n\t}\r\n\r\n\treturn LoadLevelObjects(filesWidths);\r\n}\r\n\r\nvoid FreeObjectGFX()\r\n{\r\n\tfor (int i = 0; i < numobjfiles; i++) {\r\n\t\tpObjCels[i] = std::nullopt;\r\n\t}\r\n\tnumobjfiles = 0;\r\n}\r\n\r\nvoid AddL1Objs(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j < y2; j++) {\r\n\t\tfor (int i = x1; i < x2; i++) {\r\n\t\t\tconst int pn = dPiece[i][j];\r\n\t\t\tif (pn == 269)\r\n\t\t\t\tAddObject(OBJ_L1LIGHT, { i, j });\r\n\t\t\tif (pn == 43 || pn == 50 || pn == 213)\r\n\t\t\t\tAddObject(OBJ_L1LDOOR, { i, j });\r\n\t\t\tif (pn == 45 || pn == 55)\r\n\t\t\t\tAddObject(OBJ_L1RDOOR, { i, j });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddL2Objs(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j < y2; j++) {\r\n\t\tfor (int i = x1; i < x2; i++) {\r\n\t\t\tconst int pn = dPiece[i][j];\r\n\t\t\tif (pn == 12 || pn == 540)\r\n\t\t\t\tAddObject(OBJ_L2LDOOR, { i, j });\r\n\t\t\tif (pn == 16 || pn == 541)\r\n\t\t\t\tAddObject(OBJ_L2RDOOR, { i, j });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddL3Objs(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j < y2; j++) {\r\n\t\tfor (int i = x1; i < x2; i++) {\r\n\t\t\tconst int pn = dPiece[i][j];\r\n\t\t\tif (pn == 530)\r\n\t\t\t\tAddObject(OBJ_L3LDOOR, { i, j });\r\n\t\t\tif (pn == 533)\r\n\t\t\t\tAddObject(OBJ_L3RDOOR, { i, j });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddCryptObjects(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j < y2; j++) {\r\n\t\tfor (int i = x1; i < x2; i++) {\r\n\t\t\tconst int pn = dPiece[i][j];\r\n\t\t\tif (pn == 76)\r\n\t\t\t\tAddObject(OBJ_L5LDOOR, { i, j });\r\n\t\t\tif (pn == 79)\r\n\t\t\t\tAddObject(OBJ_L5RDOOR, { i, j });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddSlainHero()\r\n{\r\n\tconst Point rndObjLoc = GetRndObjLoc(5);\r\n\tAddObject(OBJ_SLAINHERO, rndObjLoc + Displacement { 2, 2 });\r\n}\r\n\r\nvoid InitObjects()\r\n{\r\n\tClrAllObjects();\r\n\tNaKrulTomeSequence = 0;\r\n\tif (currlevel == 16) {\r\n\t\tAddDiabObjs();\r\n\t} else {\r\n\t\tDiscardRandomValues(1);\r\n\t\tif (currlevel == 9 && !UseMultiplayerQuests())\r\n\t\t\tAddSlainHero();\r\n\t\tif (Quests[Q_MUSHROOM].IsAvailable())\r\n\t\t\tAddMushPatch();\r\n\r\n\t\tif (currlevel == 4 || currlevel == 8 || currlevel == 12)\r\n\t\t\tAddStoryBooks();\r\n\t\tif (currlevel == 21) {\r\n\t\t\tAddCryptStoryBook(1);\r\n\t\t} else if (currlevel == 22) {\r\n\t\t\tAddCryptStoryBook(2);\r\n\t\t\tAddCryptStoryBook(3);\r\n\t\t} else if (currlevel == 23) {\r\n\t\t\tAddCryptStoryBook(4);\r\n\t\t\tAddCryptStoryBook(5);\r\n\t\t}\r\n\t\tif (currlevel == 24) {\r\n\t\t\tAddNakrulGate();\r\n\t\t}\r\n\t\tif (leveltype == DTYPE_CATHEDRAL) {\r\n\t\t\tif (Quests[Q_BUTCHER].IsAvailable())\r\n\t\t\t\tAddTortures();\r\n\t\t\tif (Quests[Q_PWATER].IsAvailable())\r\n\t\t\t\tAddCandles();\r\n\t\t\tif (Quests[Q_LTBANNER].IsAvailable())\r\n\t\t\t\tAddObject(OBJ_SIGNCHEST, SetPiece.position.megaToWorld() + Displacement { 10, 3 });\r\n\t\t\tInitRndLocBigObj(10, 15, OBJ_SARC);\r\n\t\t\tAddL1Objs(0, 0, MAXDUNX, MAXDUNY);\r\n\t\t\tInitRndBarrels();\r\n\t\t}\r\n\t\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\t\tif (Quests[Q_ROCK].IsAvailable())\r\n\t\t\t\tInitRndLocObj5x5(1, 1, OBJ_STAND);\r\n\t\t\tif (Quests[Q_SCHAMB].IsAvailable())\r\n\t\t\t\tInitRndLocObj5x5(1, 1, OBJ_BOOK2R);\r\n\t\t\tAddL2Objs(0, 0, MAXDUNX, MAXDUNY);\r\n\t\t\tAddL2Torches();\r\n\t\t\tif (Quests[Q_BLIND].IsAvailable()) {\r\n\t\t\t\t_speech_id spId;\r\n\t\t\t\tswitch (MyPlayer->_pClass) {\r\n\t\t\t\tcase HeroClass::Warrior:\r\n\t\t\t\t\tspId = TEXT_BLINDING;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\t\tspId = TEXT_RBLINDING;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\t\tspId = TEXT_MBLINDING;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Monk:\r\n\t\t\t\t\tspId = TEXT_HBLINDING;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Bard:\r\n\t\t\t\t\tspId = TEXT_RBLINDING;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\t\tspId = TEXT_BLINDING;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tQuests[Q_BLIND]._qmsg = spId;\r\n\t\t\t\tAddBookLever(OBJ_BLINDBOOK, { SetPiece.position, SetPiece.size + 1 }, spId);\r\n\t\t\t\tLoadMapObjects(\"levels\\\\l2data\\\\blind2.dun\", SetPiece.position.megaToWorld());\r\n\t\t\t}\r\n\t\t\tif (Quests[Q_BLOOD].IsAvailable()) {\r\n\t\t\t\t_speech_id spId;\r\n\t\t\t\tswitch (MyPlayer->_pClass) {\r\n\t\t\t\tcase HeroClass::Warrior:\r\n\t\t\t\t\tspId = TEXT_BLOODY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\t\tspId = TEXT_RBLOODY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\t\tspId = TEXT_MBLOODY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Monk:\r\n\t\t\t\t\tspId = TEXT_HBLOODY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Bard:\r\n\t\t\t\t\tspId = TEXT_RBLOODY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\t\tspId = TEXT_BLOODY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tQuests[Q_BLOOD]._qmsg = spId;\r\n\t\t\t\tAddBookLever(OBJ_BLOODBOOK, { SetPiece.position + Displacement { 0, 3 }, { 2, 4 } }, spId);\r\n\t\t\t\tAddObject(OBJ_PEDESTAL, SetPiece.position.megaToWorld() + Displacement { 9, 16 });\r\n\t\t\t}\r\n\t\t\tInitRndBarrels();\r\n\t\t}\r\n\t\tif (leveltype == DTYPE_CAVES) {\r\n\t\t\tAddL3Objs(0, 0, MAXDUNX, MAXDUNY);\r\n\t\t\tInitRndBarrels();\r\n\t\t}\r\n\t\tif (leveltype == DTYPE_HELL) {\r\n\t\t\tif (Quests[Q_WARLORD].IsAvailable()) {\r\n\t\t\t\t_speech_id spId;\r\n\t\t\t\tswitch (MyPlayer->_pClass) {\r\n\t\t\t\tcase HeroClass::Warrior:\r\n\t\t\t\t\tspId = TEXT_BLOODWAR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\t\tspId = TEXT_RBLOODWAR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\t\tspId = TEXT_MBLOODWAR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Monk:\r\n\t\t\t\t\tspId = TEXT_HBLOODWAR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Bard:\r\n\t\t\t\t\tspId = TEXT_RBLOODWAR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\t\tspId = TEXT_BLOODWAR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tQuests[Q_WARLORD]._qmsg = spId;\r\n\t\t\t\tAddBookLever(OBJ_STEELTOME, SetPiece, spId);\r\n\t\t\t\tLoadMapObjects(\"levels\\\\l4data\\\\warlord.dun\", SetPiece.position.megaToWorld());\r\n\t\t\t}\r\n\t\t\tif (Quests[Q_BETRAYER].IsAvailable() && !UseMultiplayerQuests())\r\n\t\t\t\tAddLazStand();\r\n\t\t\tInitRndBarrels();\r\n\t\t\tAddL4Goodies();\r\n\t\t}\r\n\t\tif (leveltype == DTYPE_NEST) {\r\n\t\t\tInitRndBarrels();\r\n\t\t}\r\n\t\tif (leveltype == DTYPE_CRYPT) {\r\n\t\t\tInitRndLocBigObj(10, 15, OBJ_L5SARC);\r\n\t\t\tAddCryptObjects(0, 0, MAXDUNX, MAXDUNY);\r\n\t\t\tInitRndBarrels();\r\n\t\t}\r\n\t\tInitRndLocObj(5, 10, OBJ_CHEST1);\r\n\t\tInitRndLocObj(3, 6, OBJ_CHEST2);\r\n\t\tInitRndLocObj(1, 5, OBJ_CHEST3);\r\n\t\tif (leveltype != DTYPE_HELL)\r\n\t\t\tAddObjTraps();\r\n\t\tif (IsAnyOf(leveltype, DTYPE_CATACOMBS, DTYPE_CAVES, DTYPE_HELL, DTYPE_NEST))\r\n\t\t\tAddChestTraps();\r\n\t}\r\n}\r\n\r\nvoid SetMapObjects(const uint16_t *dunData, int startx, int starty)\r\n{\r\n\tuint16_t filesWidths[65] = {};\r\n\r\n\tClrAllObjects();\r\n\r\n\tWorldTileSize size = GetDunSize(dunData);\r\n\r\n\tconst int layer2Offset = 2 + size.width * size.height;\r\n\r\n\t// The rest of the layers are at dPiece scale\r\n\tsize *= static_cast<WorldTileCoord>(2);\r\n\r\n\tconst uint16_t *objectLayer = &dunData[layer2Offset + size.width * size.height * 2];\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tauto objectId = static_cast<uint8_t>(Swap16LE(objectLayer[j * size.width + i]));\r\n\t\t\tif (objectId != 0) {\r\n\t\t\t\tconst ObjectData &objectData = AllObjects[ObjTypeConv[objectId]];\r\n\t\t\t\tfilesWidths[objectData.ofindex] = objectData.animWidth;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tLoadLevelObjects(filesWidths);\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tauto objectId = static_cast<uint8_t>(Swap16LE(objectLayer[j * size.width + i]));\r\n\t\t\tif (objectId != 0) {\r\n\t\t\t\tAddObject(ObjTypeConv[objectId], { startx + 16 + i, starty + 16 + j });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nObject *AddObject(_object_id objType, Point objPos)\r\n{\r\n\tif (ActiveObjectCount >= MAXOBJECTS)\r\n\t\treturn nullptr;\r\n\r\n\tconst int oi = AvailableObjects[0];\r\n\tAvailableObjects[0] = AvailableObjects[MAXOBJECTS - 1 - ActiveObjectCount];\r\n\tActiveObjects[ActiveObjectCount] = oi;\r\n\tdObject[objPos.x][objPos.y] = oi + 1;\r\n\tObject &object = Objects[oi];\r\n\tSetupObject(object, objPos, objType);\r\n\tswitch (object._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L2LDOOR:\r\n\tcase OBJ_L2RDOOR:\r\n\tcase OBJ_L3LDOOR:\r\n\tcase OBJ_L3RDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tAddDoor(object);\r\n\t\tbreak;\r\n\tcase OBJ_BOOK2R:\r\n\t\tobject.InitializeBook({ SetPiece.position, WorldTileSize(SetPiece.size.width + 1, SetPiece.size.height + 1) });\r\n\t\tbreak;\r\n\tcase OBJ_CHEST1:\r\n\tcase OBJ_CHEST2:\r\n\tcase OBJ_CHEST3:\r\n\t\tAddChest(object);\r\n\t\tbreak;\r\n\tcase OBJ_TCHEST1:\r\n\tcase OBJ_TCHEST2:\r\n\tcase OBJ_TCHEST3:\r\n\t\tAddChest(object);\r\n\t\tobject._oTrapFlag = true;\r\n\t\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\t\tobject._oVar4 = GenerateRnd(2);\r\n\t\t} else {\r\n\t\t\tobject._oVar4 = GenerateRnd(3);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase OBJ_SARC:\r\n\tcase OBJ_L5SARC:\r\n\t\tAddSarcophagus(object);\r\n\t\tbreak;\r\n\tcase OBJ_FLAMEHOLE:\r\n\t\tAddFlameTrap(object);\r\n\t\tbreak;\r\n\tcase OBJ_FLAMELVR:\r\n\t\tAddFlameLever(object);\r\n\t\tbreak;\r\n\tcase OBJ_WATER:\r\n\t\tobject._oAnimFrame = 1;\r\n\t\tbreak;\r\n\tcase OBJ_TRAPL:\r\n\tcase OBJ_TRAPR:\r\n\t\tAddTrap(object);\r\n\t\tbreak;\r\n\tcase OBJ_BARREL:\r\n\tcase OBJ_BARRELEX:\r\n\tcase OBJ_POD:\r\n\tcase OBJ_PODEX:\r\n\tcase OBJ_URN:\r\n\tcase OBJ_URNEX:\r\n\t\tAddBarrel(object);\r\n\t\tbreak;\r\n\tcase OBJ_SHRINEL:\r\n\tcase OBJ_SHRINER:\r\n\t\tAddShrine(object);\r\n\t\tbreak;\r\n\tcase OBJ_BOOKCASEL:\r\n\tcase OBJ_BOOKCASER:\r\n\t\tAddBookcase(object);\r\n\t\tbreak;\r\n\tcase OBJ_SKELBOOK:\r\n\tcase OBJ_BOOKSTAND:\r\n\tcase OBJ_BLOODFTN:\r\n\tcase OBJ_GOATSHRINE:\r\n\tcase OBJ_CAULDRON:\r\n\tcase OBJ_TEARFTN:\r\n\tcase OBJ_SLAINHERO:\r\n\t\tobject._oRndSeed = AdvanceRndSeed();\r\n\t\tbreak;\r\n\tcase OBJ_DECAP:\r\n\t\tAddDecapitatedBody(object);\r\n\t\tbreak;\r\n\tcase OBJ_PURIFYINGFTN:\r\n\tcase OBJ_MURKYFTN:\r\n\t\tAddLargeFountain(object);\r\n\t\tbreak;\r\n\tcase OBJ_ARMORSTAND:\r\n\tcase OBJ_WARARMOR:\r\n\t\tAddArmorStand(object);\r\n\t\tbreak;\r\n\tcase OBJ_BOOK2L:\r\n\t\tAddBookOfVileness(object);\r\n\t\tbreak;\r\n\tcase OBJ_MCIRCLE1:\r\n\tcase OBJ_MCIRCLE2:\r\n\t\tAddMagicCircle(object);\r\n\t\tbreak;\r\n\tcase OBJ_STORYBOOK:\r\n\tcase OBJ_L5BOOKS:\r\n\t\tAddStoryBook(object);\r\n\t\tbreak;\r\n\tcase OBJ_BCROSS:\r\n\tcase OBJ_TBCROSS:\r\n\t\tobject._oRndSeed = AdvanceRndSeed();\r\n\t\tbreak;\r\n\tcase OBJ_PEDESTAL:\r\n\t\tAddPedestalOfBlood(object);\r\n\t\tbreak;\r\n\tcase OBJ_WARWEAP:\r\n\tcase OBJ_WEAPONRACK:\r\n\t\tAddWeaponRack(object);\r\n\t\tbreak;\r\n\tcase OBJ_TNUDEM2:\r\n\t\tAddTorturedBody(object);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tAddObjectLight(object);\r\n\r\n\tActiveObjectCount++;\r\n\treturn &object;\r\n}\r\n\r\nbool UpdateTrapState(Object &trap)\r\n{\r\n\tif (trap._oVar4 != 0)\r\n\t\treturn false;\r\n\r\n\tObject &trigger = ObjectAtPosition({ trap._oVar1, trap._oVar2 });\r\n\tswitch (trigger._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L2LDOOR:\r\n\tcase OBJ_L2RDOOR:\r\n\tcase OBJ_L3LDOOR:\r\n\tcase OBJ_L3RDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tif (trigger._oVar4 == DOOR_CLOSED && trigger._oTrapFlag)\r\n\t\t\treturn false;\r\n\t\tbreak;\r\n\tcase OBJ_LEVER:\r\n\tcase OBJ_CHEST1:\r\n\tcase OBJ_CHEST2:\r\n\tcase OBJ_CHEST3:\r\n\tcase OBJ_SWITCHSKL:\r\n\tcase OBJ_SARC:\r\n\tcase OBJ_L5LEVER:\r\n\tcase OBJ_L5SARC:\r\n\t\tif (trigger.canInteractWith() && trigger._oTrapFlag)\r\n\t\t\treturn false;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n\r\n\ttrap._oVar4 = 1;\r\n\ttrigger._oTrapFlag = false;\r\n\treturn true;\r\n}\r\n\r\nvoid OperateTrap(Object &trap)\r\n{\r\n\tif (!UpdateTrapState(trap))\r\n\t\treturn;\r\n\r\n\t// default to firing at the trigger object\r\n\tconst Point triggerPosition = { trap._oVar1, trap._oVar2 };\r\n\tPoint target = triggerPosition;\r\n\r\n\tauto searchArea = PointsInRectangle(Rectangle { target, 1 });\r\n\t// look for a player near the trigger (using a reverse search to match vanilla behaviour)\r\n\tauto foundPosition = std::find_if(searchArea.crbegin(), searchArea.crend(), [](Point testPosition) { return InDungeonBounds(testPosition) && dPlayer[testPosition.x][testPosition.y] != 0; });\r\n\tif (foundPosition != searchArea.crend()) {\r\n\t\t// if a player is standing near the trigger then target them instead\r\n\t\ttarget = *foundPosition;\r\n\t}\r\n\r\n\tconst Direction dir = GetDirection(trap.position, target);\r\n\tAddMissile(trap.position, target, dir, static_cast<MissileID>(trap._oVar3), TARGET_PLAYERS, -1, 0, 0);\r\n\tPlaySfxLoc(SfxID::TriggerTrap, triggerPosition);\r\n}\r\n\r\nvoid ProcessObjects()\r\n{\r\n\tfor (int i = 0; i < ActiveObjectCount; ++i) {\r\n\t\tObject &object = Objects[ActiveObjects[i]];\r\n\t\tswitch (object._otype) {\r\n\t\tcase OBJ_L1LIGHT:\r\n\t\tcase OBJ_SKFIRE:\r\n\t\tcase OBJ_CANDLE1:\r\n\t\tcase OBJ_CANDLE2:\r\n\t\tcase OBJ_BOOKCANDLE:\r\n\t\t\tUpdateObjectLight(object, 5);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_STORYCANDLE:\r\n\t\tcase OBJ_L5CANDLE:\r\n\t\t\tUpdateObjectLight(object, 3);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_CRUX1:\r\n\t\tcase OBJ_CRUX2:\r\n\t\tcase OBJ_CRUX3:\r\n\t\tcase OBJ_BARREL:\r\n\t\tcase OBJ_BARRELEX:\r\n\t\tcase OBJ_POD:\r\n\t\tcase OBJ_PODEX:\r\n\t\tcase OBJ_URN:\r\n\t\tcase OBJ_URNEX:\r\n\t\tcase OBJ_SHRINEL:\r\n\t\tcase OBJ_SHRINER:\r\n\t\t\tObjectStopAnim(object);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_L1LDOOR:\r\n\t\tcase OBJ_L1RDOOR:\r\n\t\tcase OBJ_L2LDOOR:\r\n\t\tcase OBJ_L2RDOOR:\r\n\t\tcase OBJ_L3LDOOR:\r\n\t\tcase OBJ_L3RDOOR:\r\n\t\tcase OBJ_L5LDOOR:\r\n\t\tcase OBJ_L5RDOOR:\r\n\t\t\tUpdateDoor(object);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_TORCHL:\r\n\t\tcase OBJ_TORCHR:\r\n\t\tcase OBJ_TORCHL2:\r\n\t\tcase OBJ_TORCHR2:\r\n\t\t\tUpdateObjectLight(object, 8);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_SARC:\r\n\t\tcase OBJ_L5SARC:\r\n\t\t\tUpdateSarcophagus(object);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_FLAMEHOLE:\r\n\t\t\tUpdateFlameTrap(object);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_TRAPL:\r\n\t\tcase OBJ_TRAPR:\r\n\t\t\tOperateTrap(object);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_MCIRCLE1:\r\n\t\tcase OBJ_MCIRCLE2:\r\n\t\t\tUpdateCircle(object);\r\n\t\t\tbreak;\r\n\t\tcase OBJ_BCROSS:\r\n\t\tcase OBJ_TBCROSS:\r\n\t\t\tUpdateObjectLight(object, 5);\r\n\t\t\tUpdateBurningCrossDamage(object);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (!object._oAnimFlag)\r\n\t\t\tcontinue;\r\n\r\n\t\tobject._oAnimCnt++;\r\n\r\n\t\tif (object._oAnimCnt < object._oAnimDelay)\r\n\t\t\tcontinue;\r\n\r\n\t\tobject._oAnimCnt = 0;\r\n\t\tobject._oAnimFrame++;\r\n\t\tif (object._oAnimFrame > object._oAnimLen)\r\n\t\t\tobject._oAnimFrame = 1;\r\n\t}\r\n\r\n\tfor (int i = 0; i < ActiveObjectCount;) {\r\n\t\tconst int oi = ActiveObjects[i];\r\n\t\tif (Objects[oi]._oDelFlag) {\r\n\t\t\tDeleteObject(oi, i);\r\n\t\t} else {\r\n\t\t\ti++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid RedoPlayerVision()\r\n{\r\n\tfor (const Player &player : Players) {\r\n\t\tif (player.plractive && player.isOnActiveLevel()) {\r\n\t\t\tChangeVisionXY(player.getId(), player.position.tile);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MonstCheckDoors(const Monster &monster)\r\n{\r\n\tfor (const Direction dir : { Direction::NorthEast, Direction::SouthWest, Direction::North, Direction::East, Direction::South, Direction::West, Direction::NorthWest, Direction::SouthEast }) {\r\n\t\tObject *object = FindObjectAtPosition(monster.position.tile + dir);\r\n\t\tif (object == nullptr)\r\n\t\t\tcontinue;\r\n\r\n\t\tObject &door = *object;\r\n\t\t// Doors use _oVar4 to track open/closed state, non-zero values indicate an open door\r\n\t\tif (!door.isDoor() || door._oVar4 != DOOR_CLOSED)\r\n\t\t\tcontinue;\r\n\r\n\t\tOperateDoor(door, true);\r\n\t}\r\n}\r\n\r\nvoid ObjChangeMap(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j <= y2; j++) {\r\n\t\tfor (int i = x1; i <= x2; i++) {\r\n\t\t\tObjSetMini({ i, j }, pdungeon[i][j]);\r\n\t\t\tdungeon[i][j] = pdungeon[i][j];\r\n\t\t}\r\n\t}\r\n\r\n\tconst WorldTilePosition mega1 { static_cast<WorldTileCoord>(x1), static_cast<WorldTileCoord>(y1) };\r\n\tconst WorldTilePosition mega2 { static_cast<WorldTileCoord>(x2), static_cast<WorldTileCoord>(y2) };\r\n\tconst WorldTilePosition world1 = mega1.megaToWorld();\r\n\tconst WorldTilePosition world2 = mega2.megaToWorld() + Displacement { 1, 1 };\r\n\tif (leveltype == DTYPE_CATHEDRAL) {\r\n\t\tObjL1Special(world1.x, world1.y, world2.x, world2.y);\r\n\t\tAddL1Objs(world1.x, world1.y, world2.x, world2.y);\r\n\t}\r\n\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\tObjL2Special(world1.x, world1.y, world2.x, world2.y);\r\n\t\tAddL2Objs(world1.x, world1.y, world2.x, world2.y);\r\n\t}\r\n\tif (leveltype == DTYPE_CAVES) {\r\n\t\tAddL3Objs(world1.x, world1.y, world2.x, world2.y);\r\n\t}\r\n\tif (leveltype == DTYPE_CRYPT) {\r\n\t\tAddCryptObjects(world1.x, world1.y, world2.x, world2.y);\r\n\t}\r\n\tResyncDoors(world1, world2, true);\r\n}\r\n\r\nvoid ObjChangeMapResync(int x1, int y1, int x2, int y2)\r\n{\r\n\tfor (int j = y1; j <= y2; j++) {\r\n\t\tfor (int i = x1; i <= x2; i++) {\r\n\t\t\tObjSetMini({ i, j }, pdungeon[i][j]);\r\n\t\t\tdungeon[i][j] = pdungeon[i][j];\r\n\t\t}\r\n\t}\r\n\r\n\tconst WorldTilePosition mega1 { static_cast<WorldTileCoord>(x1), static_cast<WorldTileCoord>(y1) };\r\n\tconst WorldTilePosition mega2 { static_cast<WorldTileCoord>(x2), static_cast<WorldTileCoord>(y2) };\r\n\tconst WorldTilePosition world1 = mega1.megaToWorld();\r\n\tconst WorldTilePosition world2 = mega2.megaToWorld() + Displacement { 1, 1 };\r\n\tif (leveltype == DTYPE_CATHEDRAL) {\r\n\t\tObjL1Special(world1.x, world1.y, world2.x, world2.y);\r\n\t}\r\n\tif (leveltype == DTYPE_CATACOMBS) {\r\n\t\tObjL2Special(world1.x, world1.y, world2.x, world2.y);\r\n\t}\r\n\tResyncDoors(world1, world2, false);\r\n}\r\n\r\n_item_indexes ItemMiscIdIdx(item_misc_id imiscid)\r\n{\r\n\tstd::underlying_type_t<_item_indexes> i = IDI_GOLD;\r\n\twhile (AllItemsList[i].dropRate == 0 || AllItemsList[i].iMiscId != imiscid) {\r\n\t\ti++;\r\n\t}\r\n\r\n\treturn static_cast<_item_indexes>(i);\r\n}\r\n\r\nvoid OperateObject(Player &player, Object &object)\r\n{\r\n\tconst bool sendmsg = &player == MyPlayer;\r\n\r\n\tswitch (object._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L2LDOOR:\r\n\tcase OBJ_L2RDOOR:\r\n\tcase OBJ_L3LDOOR:\r\n\tcase OBJ_L3RDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tif (sendmsg)\r\n\t\t\tOperateDoor(object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_LEVER:\r\n\tcase OBJ_L5LEVER:\r\n\tcase OBJ_SWITCHSKL:\r\n\t\tOperateLever(object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_BOOK2L:\r\n\t\tif (sendmsg)\r\n\t\t\tOperateBook(player, object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_BOOK2R:\r\n\t\tOperateChamberOfBoneBook(object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_CHEST1:\r\n\tcase OBJ_CHEST2:\r\n\tcase OBJ_CHEST3:\r\n\tcase OBJ_TCHEST1:\r\n\tcase OBJ_TCHEST2:\r\n\tcase OBJ_TCHEST3:\r\n\t\tOperateChest(player, object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_SARC:\r\n\tcase OBJ_L5SARC:\r\n\t\tOperateSarcophagus(object, sendmsg, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_FLAMELVR:\r\n\t\tOperateTrapLever(object);\r\n\t\tbreak;\r\n\tcase OBJ_BLINDBOOK:\r\n\tcase OBJ_BLOODBOOK:\r\n\tcase OBJ_STEELTOME:\r\n\t\tif (sendmsg)\r\n\t\t\tOperateBookLever(object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_SHRINEL:\r\n\tcase OBJ_SHRINER:\r\n\t\tOperateShrine(player, object, SfxID::OperateShrine);\r\n\t\tbreak;\r\n\tcase OBJ_SKELBOOK:\r\n\tcase OBJ_BOOKSTAND:\r\n\t\tOperateBookStand(object, sendmsg, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_BOOKCASEL:\r\n\tcase OBJ_BOOKCASER:\r\n\t\tOperateBookcase(object, sendmsg, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_DECAP:\r\n\t\tOperateDecapitatedBody(object, sendmsg, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_ARMORSTAND:\r\n\tcase OBJ_WARARMOR:\r\n\t\tOperateArmorStand(object, sendmsg, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_GOATSHRINE:\r\n\t\tOperateGoatShrine(player, object, SfxID::OperateGoatShrine);\r\n\t\tbreak;\r\n\tcase OBJ_CAULDRON:\r\n\t\tOperateCauldron(player, object, SfxID::OperateCaldron);\r\n\t\tbreak;\r\n\tcase OBJ_BLOODFTN:\r\n\tcase OBJ_PURIFYINGFTN:\r\n\tcase OBJ_MURKYFTN:\r\n\tcase OBJ_TEARFTN:\r\n\t\tOperateFountains(player, object);\r\n\t\tbreak;\r\n\tcase OBJ_STORYBOOK:\r\n\tcase OBJ_L5BOOKS:\r\n\t\tif (sendmsg)\r\n\t\t\tOperateStoryBook(object);\r\n\t\tbreak;\r\n\tcase OBJ_PEDESTAL:\r\n\t\tif (sendmsg)\r\n\t\t\tOperatePedestal(player, object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_WARWEAP:\r\n\tcase OBJ_WEAPONRACK:\r\n\t\tOperateWeaponRack(object, sendmsg, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_MUSHPATCH:\r\n\t\tOperateMushroomPatch(player, object);\r\n\t\tbreak;\r\n\tcase OBJ_LAZSTAND:\r\n\t\tif (sendmsg)\r\n\t\t\tOperateLazStand(object);\r\n\t\tbreak;\r\n\tcase OBJ_SLAINHERO:\r\n\t\tOperateSlainHero(player, object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_SIGNCHEST:\r\n\t\tOperateInnSignChest(player, object, sendmsg);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid DeltaSyncOpObject(Object &object)\r\n{\r\n\tswitch (object._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L2LDOOR:\r\n\tcase OBJ_L2RDOOR:\r\n\tcase OBJ_L3LDOOR:\r\n\tcase OBJ_L3RDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tOpenDoor(object);\r\n\t\tbreak;\r\n\tcase OBJ_LEVER:\r\n\tcase OBJ_L5LEVER:\r\n\tcase OBJ_SWITCHSKL:\r\n\tcase OBJ_BOOK2L:\r\n\t\tUpdateLeverState(object);\r\n\t\tbreak;\r\n\tcase OBJ_CHEST1:\r\n\tcase OBJ_CHEST2:\r\n\tcase OBJ_CHEST3:\r\n\tcase OBJ_TCHEST1:\r\n\tcase OBJ_TCHEST2:\r\n\tcase OBJ_TCHEST3:\r\n\tcase OBJ_SKELBOOK:\r\n\tcase OBJ_BOOKSTAND:\r\n\t\tUpdateState(object, object._oAnimFrame + 2);\r\n\t\tbreak;\r\n\tcase OBJ_SARC:\r\n\tcase OBJ_L5SARC:\r\n\tcase OBJ_GOATSHRINE:\r\n\tcase OBJ_SHRINEL:\r\n\tcase OBJ_SHRINER:\r\n\t\tUpdateState(object, object._oAnimLen);\r\n\t\tbreak;\r\n\tcase OBJ_BLINDBOOK:\r\n\tcase OBJ_BLOODBOOK:\r\n\tcase OBJ_STEELTOME:\r\n\tcase OBJ_BOOK2R:\r\n\t\tobject._oAnimFrame = object._oVar6;\r\n\t\tSyncQSTLever(object);\r\n\t\tbreak;\r\n\tcase OBJ_BOOKCASEL:\r\n\tcase OBJ_BOOKCASER:\r\n\t\tUpdateState(object, object._oAnimFrame - 2);\r\n\t\tbreak;\r\n\tcase OBJ_DECAP:\r\n\tcase OBJ_MURKYFTN:\r\n\tcase OBJ_TEARFTN:\r\n\tcase OBJ_SLAINHERO:\r\n\t\tUpdateState(object, object._oAnimFrame);\r\n\t\tbreak;\r\n\tcase OBJ_ARMORSTAND:\r\n\tcase OBJ_WARARMOR:\r\n\tcase OBJ_WARWEAP:\r\n\tcase OBJ_WEAPONRACK:\r\n\tcase OBJ_LAZSTAND:\r\n\t\tUpdateState(object, object._oAnimFrame + 1);\r\n\t\tbreak;\r\n\tcase OBJ_CAULDRON:\r\n\t\tUpdateState(object, 3);\r\n\t\tbreak;\r\n\tcase OBJ_STORYBOOK:\r\n\tcase OBJ_L5BOOKS:\r\n\t\tobject._oAnimFrame = object._oVar4;\r\n\t\tbreak;\r\n\tcase OBJ_MUSHPATCH:\r\n\t\tif (Quests[Q_MUSHROOM]._qvar1 >= QS_MUSHSPAWNED) {\r\n\t\t\tUpdateState(object, object._oAnimFrame + 1);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase OBJ_SIGNCHEST:\r\n\t\tif (Quests[Q_LTBANNER]._qvar1 >= 2) {\r\n\t\t\tUpdateState(object, object._oAnimFrame + 2);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase OBJ_PEDESTAL:\r\n\t\tUpdatePedestalState(object);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid DeltaSyncCloseObj(Object &object)\r\n{\r\n\t// Object was closed.\r\n\t// That means it was opened once, so all traps have been activated.\r\n\tobject._oTrapFlag = false;\r\n}\r\n\r\nvoid SyncOpObject(Player &player, int cmd, Object &object)\r\n{\r\n\tconst bool sendmsg = &player == MyPlayer;\r\n\r\n\tswitch (object._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L2LDOOR:\r\n\tcase OBJ_L2RDOOR:\r\n\tcase OBJ_L3LDOOR:\r\n\tcase OBJ_L3RDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tif (sendmsg)\r\n\t\t\tbreak;\r\n\t\tif (cmd == CMD_CLOSEDOOR && object._oVar4 == DOOR_CLOSED)\r\n\t\t\tbreak;\r\n\t\tif (cmd == CMD_OPENDOOR && object._oVar4 == DOOR_OPEN)\r\n\t\t\tbreak;\r\n\t\tOperateDoor(object, false);\r\n\t\tbreak;\r\n\tcase OBJ_LEVER:\r\n\tcase OBJ_L5LEVER:\r\n\tcase OBJ_SWITCHSKL:\r\n\t\tOperateLever(object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_BOOK2L:\r\n\t\tif (!sendmsg)\r\n\t\t\tOperateBook(player, object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_CHEST1:\r\n\tcase OBJ_CHEST2:\r\n\tcase OBJ_CHEST3:\r\n\tcase OBJ_TCHEST1:\r\n\tcase OBJ_TCHEST2:\r\n\tcase OBJ_TCHEST3:\r\n\t\tOperateChest(player, object, false);\r\n\t\tbreak;\r\n\tcase OBJ_SARC:\r\n\tcase OBJ_L5SARC:\r\n\t\tOperateSarcophagus(object, sendmsg, false);\r\n\t\tbreak;\r\n\tcase OBJ_BLINDBOOK:\r\n\tcase OBJ_BLOODBOOK:\r\n\tcase OBJ_STEELTOME:\r\n\t\tif (sendmsg)\r\n\t\t\tbreak;\r\n\t\tobject._oAnimFrame = object._oVar6;\r\n\t\tSyncQSTLever(object);\r\n\t\tbreak;\r\n\tcase OBJ_SHRINEL:\r\n\tcase OBJ_SHRINER:\r\n\t\tOperateShrine(player, object, SfxID::OperateShrine);\r\n\t\tbreak;\r\n\tcase OBJ_SKELBOOK:\r\n\tcase OBJ_BOOKSTAND:\r\n\t\tOperateBookStand(object, sendmsg, false);\r\n\t\tbreak;\r\n\tcase OBJ_BOOKCASEL:\r\n\tcase OBJ_BOOKCASER:\r\n\t\tOperateBookcase(object, sendmsg, false);\r\n\t\tbreak;\r\n\tcase OBJ_DECAP:\r\n\t\tOperateDecapitatedBody(object, sendmsg, false);\r\n\t\tbreak;\r\n\tcase OBJ_ARMORSTAND:\r\n\tcase OBJ_WARARMOR:\r\n\t\tOperateArmorStand(object, sendmsg, false);\r\n\t\tbreak;\r\n\tcase OBJ_GOATSHRINE:\r\n\t\tOperateGoatShrine(player, object, SfxID::OperateGoatShrine);\r\n\t\tbreak;\r\n\tcase OBJ_LAZSTAND:\r\n\t\tif (!sendmsg)\r\n\t\t\tUpdateState(object, object._oAnimFrame + 1);\r\n\t\tbreak;\r\n\tcase OBJ_CAULDRON:\r\n\t\tOperateCauldron(player, object, SfxID::OperateCaldron);\r\n\t\tbreak;\r\n\tcase OBJ_MURKYFTN:\r\n\tcase OBJ_TEARFTN:\r\n\t\tOperateFountains(player, object);\r\n\t\tbreak;\r\n\tcase OBJ_STORYBOOK:\r\n\tcase OBJ_L5BOOKS:\r\n\t\tif (sendmsg)\r\n\t\t\tOperateStoryBook(object);\r\n\t\tbreak;\r\n\tcase OBJ_PEDESTAL:\r\n\t\tif (!sendmsg)\r\n\t\t\tOperatePedestal(player, object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_WARWEAP:\r\n\tcase OBJ_WEAPONRACK:\r\n\t\tOperateWeaponRack(object, sendmsg, false);\r\n\t\tbreak;\r\n\tcase OBJ_MUSHPATCH:\r\n\t\tOperateMushroomPatch(player, object);\r\n\t\tbreak;\r\n\tcase OBJ_SLAINHERO:\r\n\t\tOperateSlainHero(player, object, sendmsg);\r\n\t\tbreak;\r\n\tcase OBJ_SIGNCHEST:\r\n\t\tOperateInnSignChest(player, object, sendmsg);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid BreakObjectMissile(const Player *player, Object &object)\r\n{\r\n\tif (object.IsCrux())\r\n\t\tBreakCrux(object, true);\r\n}\r\nvoid BreakObject(const Player &player, Object &object)\r\n{\r\n\tif (object.IsBarrel()) {\r\n\t\tBreakBarrel(player, object, false, true);\r\n\t} else if (object.IsCrux()) {\r\n\t\tBreakCrux(object, true);\r\n\t}\r\n}\r\n\r\nvoid DeltaSyncBreakObj(Object &object)\r\n{\r\n\tif (!object.IsBreakable() || !object.canInteractWith())\r\n\t\treturn;\r\n\r\n\tobject._oMissFlag = true;\r\n\tobject._oBreak = -1;\r\n\tobject.selectionRegion = SelectionRegion::None;\r\n\tobject._oPreFlag = true;\r\n\tobject._oAnimFlag = false;\r\n\tobject._oAnimFrame = object._oAnimLen;\r\n\r\n\tif (object.IsBarrel()) {\r\n\t\tobject._oSolidFlag = false;\r\n\t} else if (object.IsCrux() && AreAllCruxesOfTypeBroken(object._oVar8)) {\r\n\t\tObjChangeMap(object._oVar1, object._oVar2, object._oVar3, object._oVar4);\r\n\t}\r\n}\r\n\r\nvoid SyncBreakObj(const Player &player, Object &object)\r\n{\r\n\tif (object.IsBarrel()) {\r\n\t\tBreakBarrel(player, object, true, false);\r\n\t} else if (object.IsCrux()) {\r\n\t\tBreakCrux(object, false);\r\n\t}\r\n}\r\n\r\nvoid SyncObjectAnim(Object &object)\r\n{\r\n\tobject_graphic_id index = AllObjects[object._otype].ofindex;\r\n\r\n\tif (!HeadlessMode) {\r\n\t\tconst auto &found = c_find(ObjFileList, index);\r\n\t\tif (found == std::end(ObjFileList)) {\r\n\t\t\tLogCritical(\"Unable to find object_graphic_id {} in list of objects to load, level generation error.\", static_cast<int>(index));\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst size_t i = std::distance(std::begin(ObjFileList), found);\r\n\r\n\t\tif (pObjCels[i]) {\r\n\t\t\tobject._oAnimData.emplace(*pObjCels[i]);\r\n\t\t} else {\r\n\t\t\tobject._oAnimData = std::nullopt;\r\n\t\t}\r\n\t}\r\n\r\n\tswitch (object._otype) {\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L2LDOOR:\r\n\tcase OBJ_L2RDOOR:\r\n\tcase OBJ_L3LDOOR:\r\n\tcase OBJ_L3RDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tSyncDoor(object);\r\n\t\tbreak;\r\n\tcase OBJ_CRUX1:\r\n\tcase OBJ_CRUX2:\r\n\tcase OBJ_CRUX3:\r\n\t\tSyncCrux(object);\r\n\t\tbreak;\r\n\tcase OBJ_LEVER:\r\n\tcase OBJ_L5LEVER:\r\n\tcase OBJ_BOOK2L:\r\n\tcase OBJ_SWITCHSKL:\r\n\t\tSyncLever(object);\r\n\t\tbreak;\r\n\tcase OBJ_BOOK2R:\r\n\tcase OBJ_BLINDBOOK:\r\n\tcase OBJ_STEELTOME:\r\n\t\tSyncQSTLever(object);\r\n\t\tbreak;\r\n\tcase OBJ_PEDESTAL:\r\n\t\tSyncPedestal(object);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nStringOrView Object::name() const\r\n{\r\n\tswitch (_otype) {\r\n\tcase OBJ_CRUX1:\r\n\tcase OBJ_CRUX2:\r\n\tcase OBJ_CRUX3:\r\n\t\treturn _(\"Crucified Skeleton\");\r\n\tcase OBJ_LEVER:\r\n\tcase OBJ_L5LEVER:\r\n\tcase OBJ_FLAMELVR:\r\n\t\treturn _(\"Lever\");\r\n\tcase OBJ_L1LDOOR:\r\n\tcase OBJ_L1RDOOR:\r\n\tcase OBJ_L2LDOOR:\r\n\tcase OBJ_L2RDOOR:\r\n\tcase OBJ_L3LDOOR:\r\n\tcase OBJ_L3RDOOR:\r\n\tcase OBJ_L5LDOOR:\r\n\tcase OBJ_L5RDOOR:\r\n\t\tif (_oVar4 == DOOR_OPEN)\r\n\t\t\treturn _(\"Open Door\");\r\n\t\tif (_oVar4 == DOOR_CLOSED)\r\n\t\t\treturn _(\"Closed Door\");\r\n\t\tif (_oVar4 == DOOR_BLOCKED)\r\n\t\t\treturn _(\"Blocked Door\");\r\n\t\tbreak;\r\n\tcase OBJ_BOOK2L:\r\n\t\tif (setlevel) {\r\n\t\t\tif (setlvlnum == SL_BONECHAMB) {\r\n\t\t\t\treturn _(\"Ancient Tome\");\r\n\t\t\t} else if (setlvlnum == SL_VILEBETRAYER) {\r\n\t\t\t\treturn _(\"Book of Vileness\");\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase OBJ_SWITCHSKL:\r\n\t\treturn _(\"Skull Lever\");\r\n\tcase OBJ_BOOK2R:\r\n\t\treturn _(\"Mythical Book\");\r\n\tcase OBJ_CHEST1:\r\n\tcase OBJ_TCHEST1:\r\n\t\treturn _(\"Small Chest\");\r\n\tcase OBJ_CHEST2:\r\n\tcase OBJ_TCHEST2:\r\n\t\treturn _(\"Chest\");\r\n\tcase OBJ_CHEST3:\r\n\tcase OBJ_TCHEST3:\r\n\tcase OBJ_SIGNCHEST:\r\n\t\treturn _(\"Large Chest\");\r\n\tcase OBJ_SARC:\r\n\tcase OBJ_L5SARC:\r\n\t\treturn _(\"Sarcophagus\");\r\n\tcase OBJ_BOOKSHELF:\r\n\t\treturn _(\"Bookshelf\");\r\n\tcase OBJ_BOOKCASEL:\r\n\tcase OBJ_BOOKCASER:\r\n\t\treturn _(\"Bookcase\");\r\n\tcase OBJ_BARREL:\r\n\tcase OBJ_BARRELEX:\r\n\t\treturn _(\"Barrel\");\r\n\tcase OBJ_POD:\r\n\tcase OBJ_PODEX:\r\n\t\treturn _(\"Pod\");\r\n\tcase OBJ_URN:\r\n\tcase OBJ_URNEX:\r\n\t\treturn _(\"Urn\");\r\n\tcase OBJ_SHRINEL:\r\n\tcase OBJ_SHRINER:\r\n\t\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} will be a name from the Shrine block above */ \"{:s} Shrine\")), _(ShrineNames[_oVar1]));\r\n\tcase OBJ_SKELBOOK:\r\n\t\treturn _(\"Skeleton Tome\");\r\n\tcase OBJ_BOOKSTAND:\r\n\t\treturn _(\"Library Book\");\r\n\tcase OBJ_BLOODFTN:\r\n\t\treturn _(\"Blood Fountain\");\r\n\tcase OBJ_DECAP:\r\n\t\treturn _(\"Decapitated Body\");\r\n\tcase OBJ_BLINDBOOK:\r\n\t\treturn _(\"Book of the Blind\");\r\n\tcase OBJ_BLOODBOOK:\r\n\t\treturn _(\"Book of Blood\");\r\n\tcase OBJ_PURIFYINGFTN:\r\n\t\treturn _(\"Purifying Spring\");\r\n\tcase OBJ_ARMORSTAND:\r\n\tcase OBJ_WARARMOR:\r\n\t\treturn _(\"Armor\");\r\n\tcase OBJ_WARWEAP:\r\n\t\treturn _(\"Weapon Rack\");\r\n\tcase OBJ_GOATSHRINE:\r\n\t\treturn _(\"Goat Shrine\");\r\n\tcase OBJ_CAULDRON:\r\n\t\treturn _(\"Cauldron\");\r\n\tcase OBJ_MURKYFTN:\r\n\t\treturn _(\"Murky Pool\");\r\n\tcase OBJ_TEARFTN:\r\n\t\treturn _(\"Fountain of Tears\");\r\n\tcase OBJ_STEELTOME:\r\n\t\treturn _(\"Steel Tome\");\r\n\tcase OBJ_PEDESTAL:\r\n\t\treturn _(\"Pedestal of Blood\");\r\n\tcase OBJ_STORYBOOK:\r\n\tcase OBJ_L5BOOKS:\r\n\t\treturn _(StoryBookName[_oVar3]);\r\n\tcase OBJ_WEAPONRACK:\r\n\t\treturn _(\"Weapon Rack\");\r\n\tcase OBJ_MUSHPATCH:\r\n\t\treturn _(\"Mushroom Patch\");\r\n\tcase OBJ_LAZSTAND:\r\n\t\treturn _(\"Vile Stand\");\r\n\tcase OBJ_SLAINHERO:\r\n\t\treturn _(\"Slain Hero\");\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\treturn std::string_view();\r\n}\r\n\r\nvoid GetObjectStr(const Object &object)\r\n{\r\n\tInfoString = object.name();\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(MyPlayer->_pClass);\r\n\tif (HasAnyOf(classAttributes.classFlags, PlayerClassFlag::TrapSense)) {\r\n\t\tif (object._oTrapFlag) {\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} will either be a chest or a door */ \"Trapped {:s}\")), InfoString.str());\r\n\t\t\tInfoColor = UiFlags::ColorRed;\r\n\t\t}\r\n\t}\r\n\tif (object.IsDisabled()) {\r\n\t\tInfoString = fmt::format(fmt::runtime(_(/* TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever */ \"{:s} (disabled)\")), InfoString.str());\r\n\t\tInfoColor = UiFlags::ColorRed;\r\n\t}\r\n}\r\n\r\nvoid SyncNakrulRoom()\r\n{\r\n\tdPiece[UberRow][UberCol] = 297;\r\n\tdPiece[UberRow][UberCol - 1] = 300;\r\n\tdPiece[UberRow][UberCol - 2] = 299;\r\n\tdPiece[UberRow][UberCol + 1] = 298;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/objects.h",
    "content": "/**\r\n * @file objects.h\r\n *\r\n * Interface of object functionality, interaction, spawning, loading, etc.\r\n */\r\n#pragma once\r\n\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"cursor.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"monster.h\"\r\n#include \"tables/itemdat.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/string_or_view.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#define MAXOBJECTS 127\r\n\r\nstruct Object {\r\n\t_object_id _otype = OBJ_NULL;\r\n\tbool applyLighting = false;\r\n\tbool _oTrapFlag = false;\r\n\tbool _oDoorFlag = false;\r\n\r\n\tPoint position;\r\n\tuint32_t _oAnimFlag = 0;\r\n\tOptionalClxSpriteList _oAnimData;\r\n\tint _oAnimDelay = 0;      // Tick length of each frame in the current animation\r\n\tint _oAnimCnt = 0;        // Increases by one each game tick, counting how close we are to _pAnimDelay\r\n\tuint32_t _oAnimLen = 0;   // Number of frames in current animation\r\n\tuint32_t _oAnimFrame = 0; // Current frame of animation.\r\n\r\n\t// TODO: Remove this field, it is unused and always equal to:\r\n\t// (*_oAnimData)[0].width()\r\n\tuint16_t _oAnimWidth = 0;\r\n\r\n\tbool _oDelFlag = false;\r\n\tint8_t _oBreak = 0;\r\n\tbool _oSolidFlag = false;\r\n\t/** True if the object allows missiles to pass through, false if it collides with missiles */\r\n\tbool _oMissFlag = false;\r\n\tSelectionRegion selectionRegion = SelectionRegion::None;\r\n\tbool _oPreFlag = false;\r\n\tint _olid = 0;\r\n\t/**\r\n\t * Saves the absolute value of the engine state (typically from a call to AdvanceRndSeed()) to later use when spawning items from a container object\r\n\t * This is an unsigned value to avoid implementation defined behaviour when reading from this variable.\r\n\t */\r\n\tuint32_t _oRndSeed = 0;\r\n\tint _oVar1 = 0;\r\n\tint _oVar2 = 0;\r\n\tint _oVar3 = 0;\r\n\tint _oVar4 = 0;\r\n\tint _oVar5 = 0;\r\n\tuint32_t _oVar6 = 0;\r\n\tint _oVar8 = 0;\r\n\r\n\t/**\r\n\t * @brief ID of a quest message to play when this object is activated.\r\n\t *\r\n\t * Used by spell book objects which trigger quest progress for Halls of the Blind, Valor, or Warlord of Blood\r\n\t */\r\n\t_speech_id bookMessage = TEXT_NONE;\r\n\r\n\t/**\r\n\t * @brief Returns the network identifier for this object\r\n\t *\r\n\t * This is currently the index into the Objects array, but may change in the future.\r\n\t */\r\n\t[[nodiscard]] unsigned int GetId() const;\r\n\r\n\t/**\r\n\t * @brief Marks the map region to be refreshed when the player interacts with the object.\r\n\t *\r\n\t * Some objects will cause a map region to change when a player interacts with them (e.g. Skeleton King\r\n\t * antechamber levers). The coordinates used for this region are based on a 40*40 grid overlaying the central\r\n\t * 80*80 region of the dungeon.\r\n\t *\r\n\t * @param topLeftPosition corner of the map region closest to the origin.\r\n\t * @param bottomRightPosition corner of the map region furthest from the origin.\r\n\t */\r\n\tconstexpr void SetMapRange(WorldTilePosition topLeftPosition, WorldTilePosition bottomRightPosition)\r\n\t{\r\n\t\t_oVar1 = topLeftPosition.x;\r\n\t\t_oVar2 = topLeftPosition.y;\r\n\t\t_oVar3 = bottomRightPosition.x;\r\n\t\t_oVar4 = bottomRightPosition.y;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Convenience function for SetMapRange(Point, Point).\r\n\t * @param mapRange A rectangle defining the top left corner and size of the affected region.\r\n\t */\r\n\tconstexpr void SetMapRange(WorldTileRectangle mapRange)\r\n\t{\r\n\t\tSetMapRange(mapRange.position, mapRange.position + DisplacementOf<uint8_t>(mapRange.size));\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Sets up a generic quest book which will trigger a change in the map when activated.\r\n\t *\r\n\t * Books of this type use a generic message (see OperateSChambBook()) compared to the more specific quest books\r\n\t * initialized by IntializeQuestBook().\r\n\t *\r\n\t * @param mapRange The region to be updated when this object is activated.\r\n\t */\r\n\tconstexpr void InitializeBook(WorldTileRectangle mapRange)\r\n\t{\r\n\t\tSetMapRange(mapRange);\r\n\t\t_oVar6 = _oAnimFrame + 1; // Save the frame number for the open book frame\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Initializes this object as a quest book which will cause further changes and play a message when activated.\r\n\t * @param mapRange The region to be updated when this object is activated.\r\n\t * @param leverID An ID (distinct from the object index) to identify the new objects spawned after updating the map.\r\n\t * @param message The quest text to play when this object is activated.\r\n\t */\r\n\tconstexpr void InitializeQuestBook(WorldTileRectangle mapRange, int leverID, _speech_id message)\r\n\t{\r\n\t\tInitializeBook(mapRange);\r\n\t\t_oVar8 = leverID;\r\n\t\tbookMessage = message;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Marks an object which was spawned from a sublevel in response to a lever activation.\r\n\t * @param mapRange The region which was updated to spawn this object.\r\n\t * @param leverID The id (*not* an object ID/index) of the lever responsible for the map change.\r\n\t */\r\n\tconstexpr void InitializeLoadedObject(WorldTileRectangle mapRange, int leverID)\r\n\t{\r\n\t\tSetMapRange(mapRange);\r\n\t\t_oVar8 = leverID;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if the object can be broken (is an intact barrel or crux)\r\n\t * @return True if the object is intact and breakable, false if already broken or not a breakable object.\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsBreakable() const\r\n\t{\r\n\t\treturn _oBreak == 1;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if the object has been broken\r\n\t * @return True if the object is breakable and has been broken, false if unbroken or not a breakable object.\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsBroken() const\r\n\t{\r\n\t\treturn _oBreak == -1;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns true if the object is a harmful shrine and the player has disabled permanent shrine effects.\r\n\t */\r\n\t[[nodiscard]] bool IsDisabled() const;\r\n\r\n\t[[nodiscard]] constexpr bool canInteractWith() const\r\n\t{\r\n\t\treturn selectionRegion != SelectionRegion::None;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is barrel (or explosive barrel)\r\n\t * @return True if the object is one of the barrel types (see _object_id)\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsBarrel() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_BARREL, _object_id::OBJ_BARRELEX, _object_id::OBJ_POD, _object_id::OBJ_PODEX, _object_id::OBJ_URN, _object_id::OBJ_URNEX);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object contains explosives or caustic material\r\n\t */\r\n\t[[nodiscard]] constexpr bool isExplosive() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_BARRELEX, _object_id::OBJ_PODEX, _object_id::OBJ_URNEX);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is a chest (or trapped chest).\r\n\t *\r\n\t * Trapped chests get their base type change in addition to having the trap flag set, but if they get \"refilled\" by\r\n\t * a Thaumaturgic shrine the base type is not reverted. This means you need to consider both the base type and the\r\n\t * trap flag to differentiate between chests that are currently trapped and chests which have never been trapped.\r\n\t *\r\n\t * @return True if the object is any of the chest types (see _object_id)\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsChest() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_CHEST1, _object_id::OBJ_CHEST2, _object_id::OBJ_CHEST3, _object_id::OBJ_TCHEST1, _object_id::OBJ_TCHEST2, _object_id::OBJ_TCHEST3);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is a trapped chest (specifically a chest which is currently trapped).\r\n\t * @return True if the object is one of the trapped chest types (see _object_id) and has an active trap.\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsTrappedChest() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_TCHEST1, _object_id::OBJ_TCHEST2, _object_id::OBJ_TCHEST3) && _oTrapFlag;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is an untrapped chest (specifically a chest which has not been trapped).\r\n\t * @return True if the object is one of the untrapped chest types (see _object_id) and has no active trap.\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsUntrappedChest() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_CHEST1, _object_id::OBJ_CHEST2, _object_id::OBJ_CHEST3) && !_oTrapFlag;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is a crucifix\r\n\t * @return True if the object is one of the crux types (see _object_id)\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsCrux() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_CRUX1, _object_id::OBJ_CRUX2, _object_id::OBJ_CRUX3);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is a door\r\n\t * @return True if the object is one of the door types (see _object_id)\r\n\t */\r\n\t[[nodiscard]] constexpr bool isDoor() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_L1LDOOR, _object_id::OBJ_L1RDOOR, _object_id::OBJ_L2LDOOR, _object_id::OBJ_L2RDOOR, _object_id::OBJ_L3LDOOR, _object_id::OBJ_L3RDOOR, _object_id::OBJ_L5LDOOR, _object_id::OBJ_L5RDOOR);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is a shrine\r\n\t * @return True if the object is one of the shrine types (see _object_id)\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsShrine() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_SHRINEL, _object_id::OBJ_SHRINER);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Check if this object is a trap source\r\n\t * @return True if the object is one of the trap types (see _object_id)\r\n\t */\r\n\t[[nodiscard]] constexpr bool IsTrap() const\r\n\t{\r\n\t\treturn IsAnyOf(_otype, _object_id::OBJ_TRAPL, _object_id::OBJ_TRAPR);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns the name of the object as shown in the info box\r\n\t */\r\n\t[[nodiscard]] StringOrView name() const;\r\n\r\n\t[[nodiscard]] ClxSprite currentSprite() const\r\n\t{\r\n\t\treturn (*_oAnimData)[_oAnimFrame - 1];\r\n\t}\r\n\t[[nodiscard]] Displacement getRenderingOffset(const ClxSprite sprite, Point tilePosition) const\r\n\t{\r\n\t\tDisplacement offset = Displacement { -CalculateSpriteTileCenterX(sprite.width()), 0 };\r\n\t\tif (position != tilePosition) {\r\n\t\t\t// drawing a large or offset object, calculate the correct position for the center of the sprite\r\n\t\t\tDisplacement worldOffset = position - tilePosition;\r\n\t\t\toffset -= worldOffset.worldToScreen();\r\n\t\t}\r\n\t\treturn offset;\r\n\t}\r\n};\r\n\r\nextern DVL_API_FOR_TEST Object Objects[MAXOBJECTS];\r\nextern int AvailableObjects[MAXOBJECTS];\r\nextern int ActiveObjects[MAXOBJECTS];\r\nextern int ActiveObjectCount;\r\n/** @brief Indicates that objects are being loaded during gameplay and pre calculated data should be updated. */\r\nextern bool LoadingMapObjects;\r\n/** Tracks progress through the tome sequence that spawns Na-Krul (see OperateNakrulBook()) */\r\nextern int NaKrulTomeSequence;\r\n\r\n/**\r\n * @brief Find an object given a point in map coordinates\r\n *\r\n * @param position The map coordinate to test\r\n * @param considerLargeObjects Default behaviour will return a pointer to a large object that covers this tile, set\r\n *                             this param to false if you only want the object whose base position matches this tile\r\n * @return A pointer to the object or nullptr if no object exists at this location\r\n */\r\nObject *FindObjectAtPosition(Point position, bool considerLargeObjects = true);\r\n\r\n/**\r\n * @brief Check whether an item occupies this tile position\r\n * @param position The map coordinate to test\r\n * @return true if the tile is occupied\r\n */\r\ninline bool IsObjectAtPosition(Point position)\r\n{\r\n\treturn FindObjectAtPosition(position) != nullptr;\r\n}\r\n\r\n/**\r\n * @brief Get a reference to the object located at this tile\r\n *\r\n * This function is unchecked. Trying to access an invalid position will result in out of bounds memory access\r\n * @param position The map coordinate of the object\r\n * @return a reference to the object\r\n */\r\ninline Object &ObjectAtPosition(Point position)\r\n{\r\n\treturn Objects[std::abs(dObject[position.x][position.y]) - 1];\r\n}\r\n\r\n/**\r\n * @brief Check whether an item blocking object (solid object or open door) is located at this tile position\r\n * @param position The map coordinate to test\r\n * @return true if the tile is blocked\r\n */\r\nbool IsItemBlockingObjectAtPosition(Point position);\r\n\r\ntl::expected<void, std::string> InitObjectGFX();\r\nvoid FreeObjectGFX();\r\nvoid AddL1Objs(int x1, int y1, int x2, int y2);\r\nvoid AddL2Objs(int x1, int y1, int x2, int y2);\r\nvoid AddL3Objs(int x1, int y1, int x2, int y2);\r\nvoid AddCryptObjects(int x1, int y1, int x2, int y2);\r\nvoid InitObjects();\r\nvoid SetMapObjects(const uint16_t *dunData, int startx, int starty);\r\n/**\r\n * @brief Spawns an object of the given type at the map coordinates provided\r\n * @param objType Type specifier\r\n * @param objPos tile coordinates\r\n */\r\nObject *AddObject(_object_id objType, Point objPos);\r\nbool UpdateTrapState(Object &trap);\r\nvoid OperateTrap(Object &trap);\r\nvoid ProcessObjects();\r\nvoid RedoPlayerVision();\r\nvoid MonstCheckDoors(const Monster &monster);\r\nvoid ObjChangeMap(int x1, int y1, int x2, int y2);\r\nvoid ObjChangeMapResync(int x1, int y1, int x2, int y2);\r\n_item_indexes ItemMiscIdIdx(item_misc_id imiscid);\r\nvoid OperateObject(Player &player, Object &object);\r\nvoid SyncOpObject(Player &player, int cmd, Object &object);\r\nvoid BreakObjectMissile(const Player *player, Object &object);\r\nvoid BreakObject(const Player &player, Object &object);\r\nvoid DeltaSyncOpObject(Object &object);\r\nvoid DeltaSyncCloseObj(Object &object);\r\nvoid DeltaSyncBreakObj(Object &object);\r\nvoid SyncBreakObj(const Player &player, Object &object);\r\nvoid SyncObjectAnim(Object &object);\r\n/**\r\n * @brief Updates the text drawn in the info box to describe the given object\r\n * @param object The currently highlighted object\r\n */\r\nvoid GetObjectStr(const Object &object);\r\nvoid SyncNakrulRoom();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/options.cpp",
    "content": "/**\r\n * @file options.cpp\r\n *\r\n * Load and save options from the diablo.ini file.\r\n */\r\n#include \"options.h\"\r\n\r\n#include <algorithm>\r\n#include <cerrno>\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <cstring>\r\n#include <functional>\r\n#include <iterator>\r\n#include <optional>\r\n#include <span>\r\n#include <string>\r\n#include <unordered_set>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_audio.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#include <SDL3/SDL_stdinc.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL_version.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n#include <fmt/format.h>\r\n#include <function_ref.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/controller_buttons.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/sound_defs.hpp\"\r\n#include \"platform/locale.hpp\"\r\n#include \"quick_messages.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/ini.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/logged_fstream.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/sdl_ptrs.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#ifndef DEFAULT_AUDIO_SAMPLE_RATE\r\n#define DEFAULT_AUDIO_SAMPLE_RATE 22050\r\n#endif\r\n#ifndef DEFAULT_AUDIO_CHANNELS\r\n#define DEFAULT_AUDIO_CHANNELS 2\r\n#endif\r\n#ifndef DEFAULT_AUDIO_BUFFER_SIZE\r\n#define DEFAULT_AUDIO_BUFFER_SIZE 2048\r\n#endif\r\n#ifndef DEFAULT_AUDIO_RESAMPLING_QUALITY\r\n#define DEFAULT_AUDIO_RESAMPLING_QUALITY 3\r\n#endif\r\n#ifndef DEFAULT_PER_PIXEL_LIGHTING\r\n#define DEFAULT_PER_PIXEL_LIGHTING true\r\n#endif\r\n\r\nnamespace {\r\n\r\nvoid DiscoverMods()\r\n{\r\n\t// Add mods available by default:\r\n\tstd::unordered_set<std::string> modNames = { \"clock\", \"adria_refills_mana\", \"Floating Numbers - Damage\", \"Floating Numbers - XP\" };\r\n\r\n\tif (HaveHellfire()) {\r\n\t\tmodNames.insert(\"Hellfire\");\r\n\t}\r\n\r\n\t// Check if the mods directory exists.\r\n\tconst std::string modsPath = StrCat(paths::PrefPath(), \"mods\");\r\n\tif (DirectoryExists(modsPath.c_str())) {\r\n\t\t// Find unpacked mods\r\n\t\tfor (const std::string &modFolder : ListDirectories(modsPath.c_str())) {\r\n\t\t\t// Only consider this folder if the init.lua file exists.\r\n\t\t\tconst std::string modScriptPath = modsPath + DIRECTORY_SEPARATOR_STR + modFolder + DIRECTORY_SEPARATOR_STR + \"lua\" + DIRECTORY_SEPARATOR_STR + \"mods\" + DIRECTORY_SEPARATOR_STR + modFolder + DIRECTORY_SEPARATOR_STR + \"init.lua\";\r\n\t\t\tif (!FileExists(modScriptPath.c_str()))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tmodNames.insert(modFolder);\r\n\t\t}\r\n\r\n\t\t// Find packed mods\r\n\t\tfor (const std::string &modMpq : ListFiles(modsPath.c_str())) {\r\n\t\t\tif (!modMpq.ends_with(\".mpq\"))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tmodNames.insert(modMpq.substr(0, modMpq.size() - 4));\r\n\t\t}\r\n\t}\r\n\r\n\t// Get the list of mods currently stored in the INI.\r\n\tstd::vector<std::string_view> existingMods = GetOptions().Mods.GetModList();\r\n\r\n\t// Add new mods.\r\n\tfor (const std::string &modName : modNames) {\r\n\t\tif (std::find(existingMods.begin(), existingMods.end(), modName) == existingMods.end())\r\n\t\t\tGetOptions().Mods.AddModEntry(modName);\r\n\t}\r\n\r\n\t// Remove mods that are no longer installed.\r\n\tfor (const std::string_view &modName : existingMods) {\r\n\t\tif (modNames.find(std::string(modName)) == modNames.end())\r\n\t\t\tGetOptions().Mods.RemoveModEntry(std::string(modName));\r\n\t}\r\n}\r\n\r\nstd::optional<Ini> ini;\r\n\r\n#if defined(__ANDROID__) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)\r\nconstexpr OptionEntryFlags OnlyIfSupportsWindowed = OptionEntryFlags::Invisible;\r\n#else\r\nconstexpr OptionEntryFlags OnlyIfSupportsWindowed = OptionEntryFlags::None;\r\n#endif\r\n\r\nconstexpr size_t NumResamplers =\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\n    1 +\r\n#endif\r\n#ifdef DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n    1 +\r\n#endif\r\n    0;\r\n\r\nstd::string GetIniPath()\r\n{\r\n\tauto path = paths::ConfigPath() + std::string(\"diablo.ini\");\r\n\treturn path;\r\n}\r\n\r\nvoid LoadIni()\r\n{\r\n\tstd::vector<char> buffer;\r\n\tauto path = GetIniPath();\r\n\tFILE *file = OpenFile(path.c_str(), \"rb\");\r\n\tif (file != nullptr) {\r\n\t\tuintmax_t size;\r\n\t\tif (GetFileSize(path.c_str(), &size)) {\r\n\t\t\tbuffer.resize(static_cast<size_t>(size));\r\n\t\t\tif (std::fread(buffer.data(), static_cast<size_t>(size), 1, file) != 1) {\r\n\t\t\t\tconst char *errorMessage = std::strerror(errno);\r\n\t\t\t\tif (errorMessage == nullptr) errorMessage = \"\";\r\n\t\t\t\tLogError(LogCategory::System, \"std::fread: failed with \\\"{}\\\"\", errorMessage);\r\n\t\t\t\tbuffer.clear();\r\n\t\t\t}\r\n\t\t}\r\n\t\tstd::fclose(file);\r\n\t}\r\n\ttl::expected<Ini, std::string> result = Ini::parse(std::string_view(buffer.data(), buffer.size()));\r\n\tif (!result.has_value()) app_fatal(result.error());\r\n\tini.emplace(std::move(result).value());\r\n}\r\n\r\nvoid SaveIni()\r\n{\r\n\tif (!ini.has_value()) return;\r\n\tif (!ini->changed()) return;\r\n\tif (!paths::ConfigPath().empty()) {\r\n\t\tRecursivelyCreateDir(paths::ConfigPath().c_str());\r\n\t}\r\n\tconst std::string iniPath = GetIniPath();\r\n\tLoggedFStream out;\r\n\tif (!out.Open(iniPath.c_str(), \"wb\")) {\r\n\t\tLogError(\"Failed to open ini file for writing at {}: {}\", iniPath, std::strerror(errno));\r\n\t\treturn;\r\n\t}\r\n\tconst std::string newContents = ini->serialize();\r\n\tif (out.Write(newContents.data(), newContents.size())) {\r\n\t\tini->markAsUnchanged();\r\n\t}\r\n\tout.Close();\r\n}\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nbool HardwareCursorDefault()\r\n{\r\n#if defined(__ANDROID__) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)\r\n\t// See https://github.com/diasurgical/devilutionX/issues/2502\r\n\treturn false;\r\n#else\r\n\treturn HardwareCursorSupported();\r\n#endif\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\nOptions &GetOptions()\r\n{\r\n\tstatic Options options;\r\n\treturn options;\r\n}\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nbool HardwareCursorSupported()\r\n{\r\n#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) || __DJGPP__\r\n\treturn false;\r\n#elif USE_SDL3\r\n\treturn true;\r\n#else\r\n\tSDL_version v;\r\n\tSDL_GetVersion(&v);\r\n\treturn SDL_VERSIONNUM(v.major, v.minor, v.patch) >= SDL_VERSIONNUM(2, 0, 12);\r\n#endif\r\n}\r\n#endif\r\n\r\nvoid LoadOptions()\r\n{\r\n\tLoadIni();\r\n\tDiscoverMods();\r\n\tOptions &options = GetOptions();\r\n\tfor (OptionCategoryBase *pCategory : options.GetCategories()) {\r\n\t\tfor (OptionEntryBase *pEntry : pCategory->GetEntries()) {\r\n\t\t\tpEntry->LoadFromIni(pCategory->GetKey());\r\n\t\t}\r\n\t}\r\n\r\n\tini->getUtf8Buf(\"Hellfire\", \"SItem\", options.Hellfire.szItem, sizeof(options.Hellfire.szItem));\r\n\tini->getUtf8Buf(\"Network\", \"Bind Address\", \"0.0.0.0\", options.Network.szBindAddress, sizeof(options.Network.szBindAddress));\r\n\tini->getUtf8Buf(\"Network\", \"Previous Game ID\", options.Network.szPreviousZTGame, sizeof(options.Network.szPreviousZTGame));\r\n\tini->getUtf8Buf(\"Network\", \"Previous Host\", options.Network.szPreviousHost, sizeof(options.Network.szPreviousHost));\r\n\r\n\tfor (size_t i = 0; i < QuickMessages.size(); i++) {\r\n\t\tconst std::span<const Ini::Value> values = ini->get(\"NetMsg\", QuickMessages[i].key);\r\n\t\tstd::vector<std::string> &result = options.Chat.szHotKeyMsgs[i];\r\n\t\tresult.clear();\r\n\t\tresult.reserve(values.size());\r\n\t\tfor (const Ini::Value &value : values) {\r\n\t\t\tresult.emplace_back(value.value);\r\n\t\t}\r\n\t}\r\n\r\n\tini->getUtf8Buf(\"Controller\", \"Mapping\", options.Controller.szMapping, sizeof(options.Controller.szMapping));\r\n\toptions.Controller.fDeadzone = ini->getFloat(\"Controller\", \"deadzone\", 0.07F);\r\n#ifdef __vita__\r\n\toptions.Controller.bRearTouch = ini->getBool(\"Controller\", \"Enable Rear Touchpad\", true);\r\n#endif\r\n}\r\n\r\nvoid SaveOptions()\r\n{\r\n\tOptions &options = GetOptions();\r\n\tfor (OptionCategoryBase *pCategory : options.GetCategories()) {\r\n\t\tfor (const OptionEntryBase *pEntry : pCategory->GetEntries()) {\r\n\t\t\tpEntry->SaveToIni(pCategory->GetKey());\r\n\t\t}\r\n\t}\r\n\r\n\tini->set(\"Hellfire\", \"SItem\", options.Hellfire.szItem);\r\n\r\n\tini->set(\"Network\", \"Bind Address\", options.Network.szBindAddress);\r\n\tini->set(\"Network\", \"Previous Game ID\", options.Network.szPreviousZTGame);\r\n\tini->set(\"Network\", \"Previous Host\", options.Network.szPreviousHost);\r\n\r\n\tfor (size_t i = 0; i < QuickMessages.size(); i++) {\r\n\t\tini->set(\"NetMsg\", QuickMessages[i].key, options.Chat.szHotKeyMsgs[i]);\r\n\t}\r\n\r\n\tini->set(\"Controller\", \"Mapping\", options.Controller.szMapping);\r\n\tini->set(\"Controller\", \"deadzone\", options.Controller.fDeadzone);\r\n#ifdef __vita__\r\n\tini->set(\"Controller\", \"Enable Rear Touchpad\", options.Controller.bRearTouch);\r\n#endif\r\n\r\n\tSaveIni();\r\n}\r\n\r\nstd::string_view OptionEntryBase::GetName() const\r\n{\r\n\treturn _(name);\r\n}\r\nstd::string_view OptionEntryBase::GetDescription() const\r\n{\r\n\treturn _(description);\r\n}\r\nOptionEntryFlags OptionEntryBase::GetFlags() const\r\n{\r\n\treturn flags;\r\n}\r\nvoid OptionEntryBase::SetValueChangedCallback(tl::function_ref<void()> callback)\r\n{\r\n\tcallback_ = callback;\r\n}\r\nvoid OptionEntryBase::NotifyValueChanged()\r\n{\r\n\tif (callback_.has_value()) (*callback_)();\r\n}\r\n\r\nvoid OptionEntryBoolean::LoadFromIni(std::string_view category)\r\n{\r\n\tvalue = ini->getBool(category, key, defaultValue);\r\n}\r\nvoid OptionEntryBoolean::SaveToIni(std::string_view category) const\r\n{\r\n\tini->set(category, key, value);\r\n}\r\nvoid OptionEntryBoolean::SetValue(bool newValue)\r\n{\r\n\tthis->value = newValue;\r\n\tthis->NotifyValueChanged();\r\n}\r\nOptionEntryType OptionEntryBoolean::GetType() const\r\n{\r\n\treturn OptionEntryType::Boolean;\r\n}\r\nstd::string_view OptionEntryBoolean::GetValueDescription() const\r\n{\r\n\treturn value ? _(\"ON\") : _(\"OFF\");\r\n}\r\n\r\nOptionEntryType OptionEntryListBase::GetType() const\r\n{\r\n\treturn OptionEntryType::List;\r\n}\r\nstd::string_view OptionEntryListBase::GetValueDescription() const\r\n{\r\n\treturn GetListDescription(GetActiveListIndex());\r\n}\r\n\r\nvoid OptionEntryEnumBase::LoadFromIni(std::string_view category)\r\n{\r\n\tvalue = ini->getInt(category, key, defaultValue);\r\n}\r\nvoid OptionEntryEnumBase::SaveToIni(std::string_view category) const\r\n{\r\n\tini->set(category, key, value);\r\n}\r\nvoid OptionEntryEnumBase::SetValueInternal(int newValue)\r\n{\r\n\tthis->value = newValue;\r\n\tthis->NotifyValueChanged();\r\n}\r\nvoid OptionEntryEnumBase::AddEntry(int entryValue, std::string_view name)\r\n{\r\n\tentryValues.push_back(entryValue);\r\n\tentryNames.push_back(name);\r\n}\r\nsize_t OptionEntryEnumBase::GetListSize() const\r\n{\r\n\treturn entryValues.size();\r\n}\r\nstd::string_view OptionEntryEnumBase::GetListDescription(size_t index) const\r\n{\r\n\treturn _(entryNames[index].data());\r\n}\r\nsize_t OptionEntryEnumBase::GetActiveListIndex() const\r\n{\r\n\tauto iterator = c_find(entryValues, value);\r\n\tif (iterator == entryValues.end())\r\n\t\treturn 0;\r\n\treturn std::distance(entryValues.begin(), iterator);\r\n}\r\nvoid OptionEntryEnumBase::SetActiveListIndex(size_t index)\r\n{\r\n\tthis->value = entryValues[index];\r\n\tthis->NotifyValueChanged();\r\n}\r\n\r\nvoid OptionEntryIntBase::LoadFromIni(std::string_view category)\r\n{\r\n\tvalue = ini->getInt(category, key, defaultValue);\r\n\tif (c_find(entryValues, value) == entryValues.end()) {\r\n\t\tentryValues.insert(c_lower_bound(entryValues, value), value);\r\n\t\tentryNames.clear();\r\n\t}\r\n}\r\nvoid OptionEntryIntBase::SaveToIni(std::string_view category) const\r\n{\r\n\tini->set(category, key, value);\r\n}\r\nvoid OptionEntryIntBase::SetValueInternal(int newValue)\r\n{\r\n\tthis->value = newValue;\r\n\tthis->NotifyValueChanged();\r\n}\r\nvoid OptionEntryIntBase::AddEntry(int entryValue)\r\n{\r\n\tentryValues.push_back(entryValue);\r\n}\r\nsize_t OptionEntryIntBase::GetListSize() const\r\n{\r\n\treturn entryValues.size();\r\n}\r\nstd::string_view OptionEntryIntBase::GetListDescription(size_t index) const\r\n{\r\n\tif (entryNames.empty()) {\r\n\t\tfor (auto entryValue : entryValues) {\r\n\t\t\tentryNames.push_back(StrCat(entryValue));\r\n\t\t}\r\n\t}\r\n\treturn entryNames[index].data();\r\n}\r\nsize_t OptionEntryIntBase::GetActiveListIndex() const\r\n{\r\n\tauto iterator = c_find(entryValues, value);\r\n\tif (iterator == entryValues.end())\r\n\t\treturn 0;\r\n\treturn std::distance(entryValues.begin(), iterator);\r\n}\r\nvoid OptionEntryIntBase::SetActiveListIndex(size_t index)\r\n{\r\n\tthis->value = entryValues[index];\r\n\tthis->NotifyValueChanged();\r\n}\r\n\r\nstd::string_view OptionCategoryBase::GetKey() const\r\n{\r\n\treturn key;\r\n}\r\nstd::string_view OptionCategoryBase::GetName() const\r\n{\r\n\treturn _(name);\r\n}\r\nstd::string_view OptionCategoryBase::GetDescription() const\r\n{\r\n\treturn _(description);\r\n}\r\n\r\nGameModeOptions::GameModeOptions()\r\n    : OptionCategoryBase(\"GameMode\", N_(\"Game Mode\"), N_(\"Game Mode Settings\"))\r\n    , gameMode(\"Game\", OptionEntryFlags::Invisible, N_(\"Game Mode\"), N_(\"Play Diablo or Hellfire.\"), StartUpGameMode::Ask,\r\n          {\r\n              { StartUpGameMode::Diablo, N_(\"Diablo\") },\r\n              // Ask is missing, because we want to hide it from UI-Settings.\r\n              { StartUpGameMode::Hellfire, N_(\"Hellfire\") },\r\n          })\r\n    , shareware(\"Shareware\", OptionEntryFlags::NeedDiabloMpq | OptionEntryFlags::RecreateUI, N_(\"Restrict to Shareware\"), N_(\"Makes the game compatible with the demo. Enables multiplayer with friends who don't own a full copy of Diablo.\"), false)\r\n\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> GameModeOptions::GetEntries()\r\n{\r\n\treturn {\r\n\t\t&gameMode,\r\n\t\t&shareware,\r\n\t};\r\n}\r\n\r\nStartUpOptions::StartUpOptions()\r\n    : OptionCategoryBase(\"StartUp\", N_(\"Start Up\"), N_(\"Start Up Settings\"))\r\n    , diabloIntro(\"Diablo Intro\", OptionEntryFlags::OnlyDiablo, N_(\"Intro\"), N_(\"Shown Intro cinematic.\"), StartUpIntro::Once,\r\n          {\r\n              { StartUpIntro::Off, N_(\"OFF\") },\r\n              // Once is missing, because we want to hide it from UI-Settings.\r\n              { StartUpIntro::On, N_(\"ON\") },\r\n          })\r\n    , hellfireIntro(\"Hellfire Intro\", OptionEntryFlags::OnlyHellfire, N_(\"Intro\"), N_(\"Shown Intro cinematic.\"), StartUpIntro::Once,\r\n          {\r\n              { StartUpIntro::Off, N_(\"OFF\") },\r\n              // Once is missing, because we want to hide it from UI-Settings.\r\n              { StartUpIntro::On, N_(\"ON\") },\r\n          })\r\n    , splash(\"Splash\", OptionEntryFlags::None, N_(\"Splash\"), N_(\"Shown splash screen.\"), StartUpSplash::LogoAndTitleDialog,\r\n          {\r\n              { StartUpSplash::LogoAndTitleDialog, N_(\"Logo and Title Screen\") },\r\n              { StartUpSplash::TitleDialog, N_(\"Title Screen\") },\r\n              { StartUpSplash::None, N_(\"None\") },\r\n          })\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> StartUpOptions::GetEntries()\r\n{\r\n\treturn {\r\n\t\t&diabloIntro,\r\n\t\t&hellfireIntro,\r\n\t\t&splash,\r\n\t};\r\n}\r\n\r\nDiabloOptions::DiabloOptions()\r\n    : OptionCategoryBase(\"Diablo\", N_(\"Diablo\"), N_(\"Diablo specific Settings\"))\r\n    , lastSinglePlayerHero(\"LastSinglePlayerHero\", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyDiablo, \"Sample Rate\", \"Remembers what singleplayer hero/save was last used.\", 0)\r\n    , lastMultiplayerHero(\"LastMultiplayerHero\", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyDiablo, \"Sample Rate\", \"Remembers what multiplayer hero/save was last used.\", 0)\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> DiabloOptions::GetEntries()\r\n{\r\n\treturn {\r\n\t\t&lastSinglePlayerHero,\r\n\t\t&lastMultiplayerHero,\r\n\t};\r\n}\r\n\r\nHellfireOptions::HellfireOptions()\r\n    : OptionCategoryBase(\"Hellfire\", N_(\"Hellfire\"), N_(\"Hellfire specific Settings\"))\r\n    , lastSinglePlayerHero(\"LastSinglePlayerHero\", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyHellfire, \"Sample Rate\", \"Remembers what singleplayer hero/save was last used.\", 0)\r\n    , lastMultiplayerHero(\"LastMultiplayerHero\", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyHellfire, \"Sample Rate\", \"Remembers what multiplayer hero/save was last used.\", 0)\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> HellfireOptions::GetEntries()\r\n{\r\n\treturn {\r\n\t\t&lastSinglePlayerHero,\r\n\t\t&lastMultiplayerHero,\r\n\t};\r\n}\r\n\r\nAudioOptions::AudioOptions()\r\n    : OptionCategoryBase(\"Audio\", N_(\"Audio\"), N_(\"Audio Settings\"))\r\n    , soundVolume(\"Sound Volume\", OptionEntryFlags::Invisible, \"Sound Volume\", \"Movie and SFX volume.\", VOLUME_MAX)\r\n    , audioCuesVolume(\"Audio Cues Volume\", OptionEntryFlags::Invisible, \"Audio Cues Volume\", \"Navigation audio cues volume.\", VOLUME_MAX)\r\n    , musicVolume(\"Music Volume\", OptionEntryFlags::Invisible, \"Music Volume\", \"Music Volume.\", VOLUME_MAX)\r\n    , walkingSound(\"Walking Sound\", OptionEntryFlags::None, N_(\"Walking Sound\"), N_(\"Player emits sound when walking.\"), true)\r\n    , autoEquipSound(\"Auto Equip Sound\", OptionEntryFlags::None, N_(\"Auto Equip Sound\"), N_(\"Automatically equipping items on pickup emits the equipment sound.\"), false)\r\n    , itemPickupSound(\"Item Pickup Sound\", OptionEntryFlags::None, N_(\"Item Pickup Sound\"), N_(\"Picking up items emits the items pickup sound.\"), false)\r\n    , sampleRate(\"Sample Rate\", OptionEntryFlags::CantChangeInGame, N_(\"Sample Rate\"), N_(\"Output sample rate (Hz).\"), DEFAULT_AUDIO_SAMPLE_RATE, { 22050, 44100, 48000 })\r\n    , channels(\"Channels\", OptionEntryFlags::CantChangeInGame, N_(\"Channels\"), N_(\"Number of output channels.\"), DEFAULT_AUDIO_CHANNELS, { 1, 2 })\r\n    , bufferSize(\"Buffer Size\", OptionEntryFlags::CantChangeInGame, N_(\"Buffer Size\"), N_(\"Buffer size (number of frames per channel).\"), DEFAULT_AUDIO_BUFFER_SIZE, { 1024, 2048, 5120 })\r\n    , resamplingQuality(\"Resampling Quality\", OptionEntryFlags::CantChangeInGame, N_(\"Resampling Quality\"), N_(\"Quality of the resampler, from 0 (lowest) to 5 (highest).\"), DEFAULT_AUDIO_RESAMPLING_QUALITY, { 0, 1, 2, 3, 4, 5 })\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> AudioOptions::GetEntries()\r\n{\r\n\t// clang-format off\r\n\treturn {\r\n\t\t&soundVolume,\r\n\t\t&audioCuesVolume,\r\n\t\t&musicVolume,\r\n\t\t&walkingSound,\r\n\t\t&autoEquipSound,\r\n\t\t&itemPickupSound,\r\n\t\t&sampleRate,\r\n\t\t&channels,\r\n\t\t&bufferSize,\r\n\t\t&resampler,\r\n\t\t&resamplingQuality,\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t\t&device,\r\n#endif\r\n\t};\r\n\t// clang-format on\r\n}\r\n\r\nOptionEntryResolution::OptionEntryResolution()\r\n    : OptionEntryListBase(\"\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI, N_(\"Resolution\"), N_(\"Affect the game's internal resolution and determine your view area. Note: This can differ from screen resolution, when Upscaling, Integer Scaling or Fit to Screen is used.\"))\r\n{\r\n}\r\nvoid OptionEntryResolution::LoadFromIni(std::string_view category)\r\n{\r\n\tsize_ = { ini->getInt(category, \"Width\", DEFAULT_WIDTH), ini->getInt(category, \"Height\", DEFAULT_HEIGHT) };\r\n}\r\nvoid OptionEntryResolution::SaveToIni(std::string_view category) const\r\n{\r\n\tini->set(category, \"Width\", size_.width);\r\n\tini->set(category, \"Height\", size_.height);\r\n}\r\n\r\nsize_t OptionEntryResolution::GetListSize() const\r\n{\r\n\treturn resolutions_.size();\r\n}\r\nstd::string_view OptionEntryResolution::GetListDescription(size_t index) const\r\n{\r\n\treturn resolutions_[index].second;\r\n}\r\nsize_t OptionEntryResolution::GetActiveListIndex() const\r\n{\r\n\tauto found = c_find_if(resolutions_, [this](const auto &x) { return x.first == size_; });\r\n\tif (found == resolutions_.end())\r\n\t\treturn 0;\r\n\treturn std::distance(resolutions_.begin(), found);\r\n}\r\nvoid OptionEntryResolution::SetActiveListIndex(size_t index)\r\n{\r\n\tsize_ = resolutions_[index].first;\r\n\tNotifyValueChanged();\r\n}\r\n\r\nOptionEntryResampler::OptionEntryResampler()\r\n    : OptionEntryListBase(\"Resampler\", OptionEntryFlags::CantChangeInGame\r\n              // When there are exactly 2 options there is no submenu, so we need to recreate the UI\r\n              // to reflect the change in the \"Resampling quality\" setting visibility.\r\n              | (NumResamplers == 2 ? OptionEntryFlags::RecreateUI : OptionEntryFlags::None),\r\n          N_(\"Resampler\"), N_(\"Audio resampler\"))\r\n{\r\n}\r\nvoid OptionEntryResampler::LoadFromIni(std::string_view category)\r\n{\r\n\tconst std::string_view resamplerStr = ini->getString(category, key);\r\n\tif (!resamplerStr.empty()) {\r\n\t\tstd::optional<Resampler> resampler = ResamplerFromString(resamplerStr);\r\n\t\tif (resampler) {\r\n\t\t\tresampler_ = *resampler;\r\n\t\t\tUpdateDependentOptions();\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tresampler_ = Resampler::DEVILUTIONX_DEFAULT_RESAMPLER;\r\n\tUpdateDependentOptions();\r\n}\r\n\r\nvoid OptionEntryResampler::SaveToIni(std::string_view category) const\r\n{\r\n\tini->set(category, key, ResamplerToString(resampler_));\r\n}\r\n\r\nsize_t OptionEntryResampler::GetListSize() const\r\n{\r\n\treturn NumResamplers;\r\n}\r\n\r\nstd::string_view OptionEntryResampler::GetListDescription(size_t index) const\r\n{\r\n\treturn ResamplerToString(static_cast<Resampler>(index));\r\n}\r\n\r\nsize_t OptionEntryResampler::GetActiveListIndex() const\r\n{\r\n\treturn static_cast<size_t>(resampler_);\r\n}\r\n\r\nvoid OptionEntryResampler::SetActiveListIndex(size_t index)\r\n{\r\n\tresampler_ = static_cast<Resampler>(index);\r\n\tUpdateDependentOptions();\r\n\tNotifyValueChanged();\r\n}\r\n\r\nvoid OptionEntryResampler::UpdateDependentOptions() const\r\n{\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\n\tif (resampler_ == Resampler::Speex) {\r\n\t\tGetOptions().Audio.resamplingQuality.flags &= ~OptionEntryFlags::Invisible;\r\n\t} else {\r\n\t\tGetOptions().Audio.resamplingQuality.flags |= OptionEntryFlags::Invisible;\r\n\t}\r\n#endif\r\n}\r\n\r\nOptionEntryAudioDevice::OptionEntryAudioDevice()\r\n    : OptionEntryListBase(\"Device\", OptionEntryFlags::CantChangeInGame, N_(\"Device\"), N_(\"Audio device\"))\r\n{\r\n}\r\nvoid OptionEntryAudioDevice::LoadFromIni(std::string_view category)\r\n{\r\n\tdeviceName_ = ini->getString(category, key);\r\n}\r\n\r\nvoid OptionEntryAudioDevice::SaveToIni(std::string_view category) const\r\n{\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\tini->set(category, key, deviceName_);\r\n#endif\r\n}\r\n\r\nsize_t OptionEntryAudioDevice::GetListSize() const\r\n{\r\n#if defined(USE_SDL3)\r\n\tint numDevices = 0;\r\n\tSDLUniquePtr<SDL_AudioDeviceID> devices { SDL_GetAudioPlaybackDevices(&numDevices) };\r\n\treturn static_cast<size_t>(numDevices) + 1;\r\n#elif SDL_VERSION_ATLEAST(2, 0, 0)\r\n\treturn SDL_GetNumAudioDevices(false) + 1;\r\n#else\r\n\treturn 1;\r\n#endif\r\n}\r\n\r\nstd::string_view OptionEntryAudioDevice::GetListDescription(size_t index) const\r\n{\r\n\tstd::string_view deviceName = GetDeviceName(index);\r\n\tif (deviceName.empty()) deviceName = \"System Default\";\r\n\treturn deviceName;\r\n}\r\n\r\nsize_t OptionEntryAudioDevice::GetActiveListIndex() const\r\n{\r\n#ifdef USE_SDL3\r\n\tint numDevices;\r\n\tSDLUniquePtr<SDL_AudioDeviceID> devices { SDL_GetAudioPlaybackDevices(&numDevices) };\r\n\tif (devices == nullptr) return 0;\r\n\tfor (int i = 0; i < numDevices; ++i) {\r\n\t\tconst char *deviceName = SDL_GetAudioDeviceName(devices.get()[i]);\r\n\t\tif (deviceName_ == deviceName) return i;\r\n\t}\r\n\treturn 0;\r\n#else\r\n\tfor (size_t i = 0; i < GetListSize(); i++) {\r\n\t\tconst std::string_view deviceName = GetDeviceName(i);\r\n\t\tif (deviceName_ == deviceName) return i;\r\n\t}\r\n\treturn 0;\r\n#endif\r\n}\r\n\r\nvoid OptionEntryAudioDevice::SetActiveListIndex(size_t index)\r\n{\r\n\tdeviceName_ = std::string { GetDeviceName(index) };\r\n\tNotifyValueChanged();\r\n}\r\n\r\nstd::string_view OptionEntryAudioDevice::GetDeviceName(size_t index) const\r\n{\r\n\tif (index == 0) return {}; // System Default\r\n#if defined(USE_SDL3)\r\n\tint numDevices = 0;\r\n\tSDLUniquePtr<SDL_AudioDeviceID> devices { SDL_GetAudioPlaybackDevices(&numDevices) };\r\n\tif (devices == nullptr || static_cast<int>(index) > numDevices) return \"Unknown\";\r\n\tconst char *deviceName = SDL_GetAudioDeviceName(devices.get()[index - 1]);\r\n\tif (deviceName == nullptr) return \"Unknown\";\r\n\treturn deviceName;\r\n#elif SDL_VERSION_ATLEAST(2, 0, 0)\r\n\treturn SDL_GetAudioDeviceName(static_cast<int>(index) - 1, false);\r\n#endif\r\n\treturn {};\r\n}\r\n\r\n#ifdef USE_SDL3\r\nSDL_AudioDeviceID OptionEntryAudioDevice::id() const\r\n{\r\n\tif (deviceName_.empty()) return SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;\r\n\tint numDevices = 0;\r\n\tSDLUniquePtr<SDL_AudioDeviceID> devices { SDL_GetAudioPlaybackDevices(&numDevices) };\r\n\tif (devices == nullptr) {\r\n\t\tLogWarn(\"Failed to get audio devices: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;\r\n\t}\r\n\tfor (int i = 0; i < numDevices; ++i) {\r\n\t\tconst SDL_AudioDeviceID id = devices.get()[i];\r\n\t\tif (deviceName_ == SDL_GetAudioDeviceName(id)) return id;\r\n\t}\r\n\treturn SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;\r\n}\r\n#endif\r\n\r\nGraphicsOptions::GraphicsOptions()\r\n    : OptionCategoryBase(\"Graphics\", N_(\"Graphics\"), N_(\"Graphics Settings\"))\r\n    , fullscreen(\"Fullscreen\", OnlyIfSupportsWindowed | OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI, N_(\"Fullscreen\"), N_(\"Display the game in windowed or fullscreen mode.\"), true)\r\n#if !defined(USE_SDL1) || defined(__3DS__)\r\n    , fitToScreen(\"Fit to Screen\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI, N_(\"Fit to Screen\"), N_(\"Automatically adjust the game window to your current desktop screen aspect ratio and resolution.\"),\r\n#ifdef __DJGPP__\r\n          false\r\n#else\r\n          true\r\n#endif\r\n          )\r\n#endif\r\n#ifndef USE_SDL1\r\n    , upscale(\"Upscale\", OptionEntryFlags::Invisible | OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI, N_(\"Upscale\"), N_(\"Enables image scaling from the game resolution to your monitor resolution. Prevents changing the monitor resolution and allows window resizing.\"),\r\n#if defined(NXDK) || defined(__DJGPP__)\r\n          false\r\n#else\r\n          true\r\n#endif\r\n          )\r\n    , scaleQuality(\"Scaling Quality\", OptionEntryFlags::None, N_(\"Scaling Quality\"), N_(\"Enables optional filters to the output image when upscaling.\"), ScalingQuality::AnisotropicFiltering,\r\n          {\r\n              { ScalingQuality::NearestPixel, N_(\"Nearest Pixel\") },\r\n              { ScalingQuality::BilinearFiltering, N_(\"Bilinear\") },\r\n              { ScalingQuality::AnisotropicFiltering, N_(\"Anisotropic\") },\r\n          })\r\n    , integerScaling(\"Integer Scaling\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI, N_(\"Integer Scaling\"), N_(\"Scales the image using whole number pixel ratio.\"), false)\r\n#endif\r\n    , frameRateControl(\"Frame Rate Control\",\r\n          OptionEntryFlags::RecreateUI\r\n#if defined(NXDK) || defined(__ANDROID__)\r\n              | OptionEntryFlags::Invisible\r\n#endif\r\n          ,\r\n          N_(\"Frame Rate Control\"),\r\n          N_(\"Manages frame rate to balance performance, reduce tearing, or save power.\"),\r\n#if defined(NXDK) || defined(USE_SDL1)\r\n          FrameRateControl::CPUSleep\r\n#else\r\n          FrameRateControl::VerticalSync\r\n#endif\r\n          ,\r\n          {\r\n              { FrameRateControl::None, N_(\"None\") },\r\n#ifndef USE_SDL1\r\n              { FrameRateControl::VerticalSync, N_(\"Vertical Sync\") },\r\n#endif\r\n              { FrameRateControl::CPUSleep, N_(\"Limit FPS\") },\r\n          })\r\n    , brightness(\"Brightness Correction\", OptionEntryFlags::Invisible, \"Brightness Correction\", \"Brightness correction level.\", 0)\r\n    , zoom(\"Zoom\", OptionEntryFlags::None, N_(\"Zoom\"), N_(\"Zoom on when enabled.\"), false)\r\n    , perPixelLighting(\"Per-pixel Lighting\", OptionEntryFlags::None, N_(\"Per-pixel Lighting\"), N_(\"Subtile lighting for smoother light gradients.\"), DEFAULT_PER_PIXEL_LIGHTING)\r\n    , colorCycling(\"Color Cycling\", OptionEntryFlags::None, N_(\"Color Cycling\"), N_(\"Color cycling effect used for water, lava, and acid animation.\"), true)\r\n    , alternateNestArt(\"Alternate nest art\", OptionEntryFlags::OnlyHellfire | OptionEntryFlags::CantChangeInGame, N_(\"Alternate nest art\"), N_(\"The game will use an alternative palette for Hellfire’s nest tileset.\"), false)\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n    , hardwareCursor(\"Hardware Cursor\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI | (HardwareCursorSupported() ? OptionEntryFlags::None : OptionEntryFlags::Invisible), N_(\"Hardware Cursor\"), N_(\"Use a hardware cursor\"), HardwareCursorDefault())\r\n    , hardwareCursorForItems(\"Hardware Cursor For Items\", OptionEntryFlags::CantChangeInGame | (HardwareCursorSupported() ? OptionEntryFlags::None : OptionEntryFlags::Invisible), N_(\"Hardware Cursor For Items\"), N_(\"Use a hardware cursor for items.\"), false)\r\n    , hardwareCursorMaxSize(\"Hardware Cursor Maximum Size\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI | (HardwareCursorSupported() ? OptionEntryFlags::None : OptionEntryFlags::Invisible), N_(\"Hardware Cursor Maximum Size\"), N_(\"Maximum width / height for the hardware cursor. Larger cursors fall back to software.\"), 128, { 0, 64, 128, 256, 512 })\r\n#endif\r\n    , showFPS(\"Show FPS\", OptionEntryFlags::None, N_(\"Show FPS\"), N_(\"Displays the FPS in the upper left corner of the screen.\"), false)\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> GraphicsOptions::GetEntries()\r\n{\r\n\t// clang-format off\r\n\treturn {\r\n\t\t&resolution,\r\n#ifndef __vita__\r\n\t\t&fullscreen,\r\n#endif\r\n#if !defined(USE_SDL1) || defined(__3DS__)\r\n\t\t&fitToScreen,\r\n#endif\r\n#ifndef USE_SDL1\r\n\t\t&upscale,\r\n\t\t&scaleQuality,\r\n\t\t&integerScaling,\r\n#endif\r\n\t\t&frameRateControl,\r\n\t\t&brightness,\r\n\t\t&zoom,\r\n\t\t&showFPS,\r\n\t\t&perPixelLighting,\r\n\t\t&colorCycling,\r\n\t\t&alternateNestArt,\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t\t&hardwareCursor,\r\n\t\t&hardwareCursorForItems,\r\n\t\t&hardwareCursorMaxSize,\r\n#endif\r\n\t};\r\n\t// clang-format on\r\n}\r\n\r\nGameplayOptions::GameplayOptions()\r\n    : OptionCategoryBase(\"Game\", N_(\"Gameplay\"), N_(\"Gameplay Settings\"))\r\n    , tickRate(\"Speed\", OptionEntryFlags::Invisible, \"Speed\", \"Gameplay ticks per second.\", 20)\r\n    , runInTown(\"Run in Town\", OptionEntryFlags::CantChangeInMultiPlayer, N_(\"Run in Town\"), N_(\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was introduced in the expansion.\"), false)\r\n    , grabInput(\"Grab Input\", OptionEntryFlags::None, N_(\"Grab Input\"), N_(\"When enabled mouse is locked to the game window.\"), false)\r\n    , pauseOnFocusLoss(\"Pause Game When Window Loses Focus\", OptionEntryFlags::None, N_(\"Pause Game When Window Loses Focus\"), N_(\"When enabled, the game will pause when focus is lost.\"), true)\r\n    , theoQuest(\"Theo Quest\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::OnlyHellfire, N_(\"Theo Quest\"), N_(\"Enable Little Girl quest.\"), false)\r\n    , cowQuest(\"Cow Quest\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::OnlyHellfire, N_(\"Cow Quest\"), N_(\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"), false)\r\n    , friendlyFire(\"Friendly Fire\", OptionEntryFlags::CantChangeInMultiPlayer, N_(\"Friendly Fire\"), N_(\"Allow arrow/spell damage between players in multiplayer even when the friendly mode is on.\"), true)\r\n    , multiplayerFullQuests(\"MultiplayerFullQuests\", OptionEntryFlags::CantChangeInMultiPlayer, N_(\"Full quests in Multiplayer\"), N_(\"Enables the full/uncut singleplayer version of quests.\"), false)\r\n    , testBard(\"Test Bard\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::OnlyHellfire, N_(\"Test Bard\"), N_(\"Force the Bard character type to appear in the hero selection menu.\"), false)\r\n    , testBarbarian(\"Test Barbarian\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::OnlyHellfire, N_(\"Test Barbarian\"), N_(\"Force the Barbarian character type to appear in the hero selection menu.\"), false)\r\n    , experienceBar(\"Experience Bar\", OptionEntryFlags::None, N_(\"Experience Bar\"), N_(\"Experience Bar is added to the UI at the bottom of the screen.\"), false)\r\n    , showItemGraphicsInStores(\"Show Item Graphics in Stores\", OptionEntryFlags::None, N_(\"Show Item Graphics in Stores\"), N_(\"Show item graphics to the left of item descriptions in store menus.\"), false)\r\n    , showHealthValues(\"Show health values\", OptionEntryFlags::None, N_(\"Show health values\"), N_(\"Displays current / max health value on health globe.\"), false)\r\n    , showManaValues(\"Show mana values\", OptionEntryFlags::None, N_(\"Show mana values\"), N_(\"Displays current / max mana value on mana globe.\"), false)\r\n    , showMultiplayerPartyInfo(\"Show Multiplayer Party Information\", OptionEntryFlags::CantChangeInMultiPlayer, N_(\"Show Party Information\"), N_(\"Displays the health and mana of all connected multiplayer party members.\"), false)\r\n    , enemyHealthBar(\"Enemy Health Bar\", OptionEntryFlags::None, N_(\"Enemy Health Bar\"), N_(\"Enemy Health Bar is displayed at the top of the screen.\"), false)\r\n    , floatingInfoBox(\"Floating Item Info Box\", OptionEntryFlags::None, N_(\"Floating Item Info Box\"), N_(\"Displays item info in a floating box when hovering over an item.\"), false)\r\n    , autoGoldPickup(\"Auto Gold Pickup\", OptionEntryFlags::None, N_(\"Auto Gold Pickup\"), N_(\"Gold is automatically collected when in close proximity to the player.\"), false)\r\n    , autoElixirPickup(\"Auto Elixir Pickup\", OptionEntryFlags::None, N_(\"Auto Elixir Pickup\"), N_(\"Elixirs are automatically collected when in close proximity to the player.\"), false)\r\n    , autoOilPickup(\"Auto Oil Pickup\", OptionEntryFlags::OnlyHellfire, N_(\"Auto Oil Pickup\"), N_(\"Oils are automatically collected when in close proximity to the player.\"), false)\r\n    , autoPickupInTown(\"Auto Pickup in Town\", OptionEntryFlags::None, N_(\"Auto Pickup in Town\"), N_(\"Automatically pickup items in town.\"), false)\r\n    , autoEquipWeapons(\"Auto Equip Weapons\", OptionEntryFlags::None, N_(\"Auto Equip Weapons\"), N_(\"Weapons will be automatically equipped on pickup or purchase if enabled.\"), true)\r\n    , autoEquipArmor(\"Auto Equip Armor\", OptionEntryFlags::None, N_(\"Auto Equip Armor\"), N_(\"Armor will be automatically equipped on pickup or purchase if enabled.\"), false)\r\n    , autoEquipHelms(\"Auto Equip Helms\", OptionEntryFlags::None, N_(\"Auto Equip Helms\"), N_(\"Helms will be automatically equipped on pickup or purchase if enabled.\"), false)\r\n    , autoEquipShields(\"Auto Equip Shields\", OptionEntryFlags::None, N_(\"Auto Equip Shields\"), N_(\"Shields will be automatically equipped on pickup or purchase if enabled.\"), false)\r\n    , autoEquipJewelry(\"Auto Equip Jewelry\", OptionEntryFlags::None, N_(\"Auto Equip Jewelry\"), N_(\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"), false)\r\n    , randomizeQuests(\"Randomize Quests\", OptionEntryFlags::CantChangeInGame, N_(\"Randomize Quests\"), N_(\"Randomly selecting available quests for new games.\"), true)\r\n    , showMonsterType(\"Show Monster Type\", OptionEntryFlags::None, N_(\"Show Monster Type\"), N_(\"Hovering over a monster will display the type of monster in the description box in the UI.\"), false)\r\n    , showItemLabels(\"Show Item Labels\", OptionEntryFlags::None, N_(\"Show Item Labels\"), N_(\"Show labels for items on the ground when enabled.\"), false)\r\n    , autoRefillBelt(\"Auto Refill Belt\", OptionEntryFlags::None, N_(\"Auto Refill Belt\"), N_(\"Refill belt from inventory when belt item is consumed.\"), false)\r\n    , disableCripplingShrines(\"Disable Crippling Shrines\", OptionEntryFlags::None, N_(\"Disable Crippling Shrines\"), N_(\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, Sacred Shrines and Murphy's Shrines are not able to be clicked on and labeled as disabled.\"), false)\r\n    , quickCast(\"Quick Cast\", OptionEntryFlags::None, N_(\"Quick Cast\"), N_(\"Spell hotkeys instantly cast the spell, rather than switching the readied spell.\"), false)\r\n    , numHealPotionPickup(\"Heal Potion Pickup\", OptionEntryFlags::None, N_(\"Heal Potion Pickup\"), N_(\"Number of Healing potions to pick up automatically.\"), 0, { 0, 1, 2, 4, 8, 16 })\r\n    , numFullHealPotionPickup(\"Full Heal Potion Pickup\", OptionEntryFlags::None, N_(\"Full Heal Potion Pickup\"), N_(\"Number of Full Healing potions to pick up automatically.\"), 0, { 0, 1, 2, 4, 8, 16 })\r\n    , numManaPotionPickup(\"Mana Potion Pickup\", OptionEntryFlags::None, N_(\"Mana Potion Pickup\"), N_(\"Number of Mana potions to pick up automatically.\"), 0, { 0, 1, 2, 4, 8, 16 })\r\n    , numFullManaPotionPickup(\"Full Mana Potion Pickup\", OptionEntryFlags::None, N_(\"Full Mana Potion Pickup\"), N_(\"Number of Full Mana potions to pick up automatically.\"), 0, { 0, 1, 2, 4, 8, 16 })\r\n    , numRejuPotionPickup(\"Rejuvenation Potion Pickup\", OptionEntryFlags::None, N_(\"Rejuvenation Potion Pickup\"), N_(\"Number of Rejuvenation potions to pick up automatically.\"), 0, { 0, 1, 2, 4, 8, 16 })\r\n    , numFullRejuPotionPickup(\"Full Rejuvenation Potion Pickup\", OptionEntryFlags::None, N_(\"Full Rejuvenation Potion Pickup\"), N_(\"Number of Full Rejuvenation potions to pick up automatically.\"), 0, { 0, 1, 2, 4, 8, 16 })\r\n    , skipLoadingScreenThresholdMs(\"Skip loading screen threshold, ms\", OptionEntryFlags::Invisible, \"\", \"\", 0)\r\n{\r\n}\r\n\r\nstd::vector<OptionEntryBase *> GameplayOptions::GetEntries()\r\n{\r\n\treturn {\r\n\t\t&tickRate,\r\n\t\t&friendlyFire,\r\n\t\t&multiplayerFullQuests,\r\n\t\t&randomizeQuests,\r\n\t\t&theoQuest,\r\n\t\t&cowQuest,\r\n\t\t&runInTown,\r\n\t\t&quickCast,\r\n\t\t&testBard,\r\n\t\t&testBarbarian,\r\n\t\t&experienceBar,\r\n\t\t&showItemGraphicsInStores,\r\n\t\t&showHealthValues,\r\n\t\t&showManaValues,\r\n\t\t&showMultiplayerPartyInfo,\r\n\t\t&enemyHealthBar,\r\n\t\t&floatingInfoBox,\r\n\t\t&showMonsterType,\r\n\t\t&showItemLabels,\r\n\t\t&autoRefillBelt,\r\n\t\t&autoEquipWeapons,\r\n\t\t&autoEquipArmor,\r\n\t\t&autoEquipHelms,\r\n\t\t&autoEquipShields,\r\n\t\t&autoEquipJewelry,\r\n\t\t&autoGoldPickup,\r\n\t\t&autoElixirPickup,\r\n\t\t&autoOilPickup,\r\n\t\t&numHealPotionPickup,\r\n\t\t&numFullHealPotionPickup,\r\n\t\t&numManaPotionPickup,\r\n\t\t&numFullManaPotionPickup,\r\n\t\t&numRejuPotionPickup,\r\n\t\t&numFullRejuPotionPickup,\r\n\t\t&autoPickupInTown,\r\n\t\t&disableCripplingShrines,\r\n\t\t&grabInput,\r\n\t\t&pauseOnFocusLoss,\r\n\t\t&skipLoadingScreenThresholdMs,\r\n\t};\r\n}\r\n\r\nControllerOptions::ControllerOptions()\r\n    : OptionCategoryBase(\"Controller\", N_(\"Controller\"), N_(\"Controller Settings\"))\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> ControllerOptions::GetEntries()\r\n{\r\n\treturn {};\r\n}\r\n\r\nNetworkOptions::NetworkOptions()\r\n    : OptionCategoryBase(\"Network\", N_(\"Network\"), N_(\"Network Settings\"))\r\n    , port(\"Port\", OptionEntryFlags::Invisible, \"Port\", \"What network port to use.\", 6112)\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> NetworkOptions::GetEntries()\r\n{\r\n\treturn {\r\n\t\t&port,\r\n\t};\r\n}\r\n\r\nChatOptions::ChatOptions()\r\n    : OptionCategoryBase(\"NetMsg\", N_(\"Chat\"), N_(\"Chat Settings\"))\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> ChatOptions::GetEntries()\r\n{\r\n\treturn {};\r\n}\r\n\r\nOptionEntryLanguageCode::OptionEntryLanguageCode()\r\n    : OptionEntryListBase(\"Code\", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI, N_(\"Language\"), N_(\"Define what language to use in game.\"))\r\n{\r\n}\r\nvoid OptionEntryLanguageCode::LoadFromIni(std::string_view category)\r\n{\r\n\tini->getUtf8Buf(category, key, szCode, sizeof(szCode));\r\n\tif (szCode[0] != '\\0' && HasTranslation(szCode)) {\r\n\t\t// User preferred language is available\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Might be a first run or the user has attempted to load a translation that doesn't exist via manual ini edit. Try\r\n\t//  find a best fit from the platform locale information.\r\n\tstd::vector<std::string> locales = GetLocales();\r\n\r\n\t// So that the correct language is shown in the settings menu for users with US english set as a preferred language\r\n\t//  we need to replace the \"en_US\" locale code with the neutral string \"en\" as expected by the available options\r\n\tstd::replace(locales.begin(), locales.end(), std::string { \"en_US\" }, std::string { \"en\" });\r\n\r\n\t// Insert non-regional locale codes after the last regional variation so we fallback to neutral translations if no\r\n\t//  regional translation exists that meets user preferences.\r\n\tfor (auto localeIter = locales.rbegin(); localeIter != locales.rend(); localeIter++) {\r\n\t\tauto regionSeparator = localeIter->find('_');\r\n\t\tif (regionSeparator != std::string::npos) {\r\n\t\t\tconst std::string neutralLocale = localeIter->substr(0, regionSeparator);\r\n\t\t\tif (std::find(locales.rbegin(), localeIter, neutralLocale) == localeIter) {\r\n\t\t\t\tlocaleIter = std::make_reverse_iterator(locales.insert(localeIter.base(), neutralLocale));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tLogVerbose(\"Found user preferred locales: {}\", fmt::join(locales, \", \"));\r\n\r\n\tfor (const auto &locale : locales) {\r\n\t\tLogVerbose(\"Trying to load translation: {}\", locale);\r\n\t\tif (HasTranslation(locale)) {\r\n\t\t\tLogVerbose(\"Best match locale: {}\", locale);\r\n\t\t\tCopyUtf8(szCode, locale, sizeof(szCode));\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tLogVerbose(\"No suitable translation found\");\r\n\tstrcpy(szCode, \"en\");\r\n}\r\nvoid OptionEntryLanguageCode::SaveToIni(std::string_view category) const\r\n{\r\n\tini->set(category, key, szCode);\r\n}\r\n\r\nvoid OptionEntryLanguageCode::CheckLanguagesAreInitialized() const\r\n{\r\n\tif (!languages.empty())\r\n\t\treturn;\r\n\tconst bool haveExtraFonts = HaveExtraFonts();\r\n\r\n\t// Add well-known supported languages\r\n\tlanguages.emplace_back(\"da\", \"Dansk\");\r\n\tlanguages.emplace_back(\"de\", \"Deutsch\");\r\n\tlanguages.emplace_back(\"et\", \"Eesti\");\r\n\tlanguages.emplace_back(\"en\", \"English\");\r\n\tlanguages.emplace_back(\"es\", \"Español\");\r\n\tlanguages.emplace_back(\"fr\", \"Français\");\r\n\tlanguages.emplace_back(\"hr\", \"Hrvatski\");\r\n\tlanguages.emplace_back(\"it\", \"Italiano\");\r\n\tlanguages.emplace_back(\"hu\", \"Magyar\");\r\n\tlanguages.emplace_back(\"pl\", \"Polski\");\r\n\tlanguages.emplace_back(\"pt_BR\", \"Português do Brasil\");\r\n\tlanguages.emplace_back(\"ro\", \"Română\");\r\n\tlanguages.emplace_back(\"fi\", \"Suomi\");\r\n\tlanguages.emplace_back(\"sv\", \"Svenska\");\r\n\tlanguages.emplace_back(\"tr\", \"Türkçe\");\r\n\tlanguages.emplace_back(\"cs\", \"Čeština\");\r\n\tlanguages.emplace_back(\"el\", \"Ελληνικά\");\r\n\tlanguages.emplace_back(\"be\", \"беларуская\");\r\n\tlanguages.emplace_back(\"bg\", \"Български\");\r\n\tlanguages.emplace_back(\"ru\", \"Русский\");\r\n\tlanguages.emplace_back(\"uk\", \"Українська\");\r\n\r\n\tif (haveExtraFonts) {\r\n\t\tlanguages.emplace_back(\"ja\", \"日本語\");\r\n\t\tlanguages.emplace_back(\"ko\", \"한국어\");\r\n\t\tlanguages.emplace_back(\"zh_CN\", \"汉语\");\r\n\t\tlanguages.emplace_back(\"zh_TW\", \"漢語\");\r\n\t}\r\n\r\n\t// Ensures that the ini specified language is present in languages list even if unknown (for example if someone starts to translate a new language)\r\n\tif (c_find_if(languages, [this](const auto &x) { return x.first == this->szCode; }) == languages.end()) {\r\n\t\tlanguages.emplace_back(szCode, szCode);\r\n\t}\r\n}\r\n\r\nsize_t OptionEntryLanguageCode::GetListSize() const\r\n{\r\n\tCheckLanguagesAreInitialized();\r\n\treturn languages.size();\r\n}\r\nstd::string_view OptionEntryLanguageCode::GetListDescription(size_t index) const\r\n{\r\n\tCheckLanguagesAreInitialized();\r\n\treturn languages[index].second;\r\n}\r\nsize_t OptionEntryLanguageCode::GetActiveListIndex() const\r\n{\r\n\tCheckLanguagesAreInitialized();\r\n\tauto found = c_find_if(languages, [this](const auto &x) { return x.first == this->szCode; });\r\n\tif (found == languages.end())\r\n\t\treturn 0;\r\n\treturn std::distance(languages.begin(), found);\r\n}\r\nvoid OptionEntryLanguageCode::SetActiveListIndex(size_t index)\r\n{\r\n\tCopyUtf8(szCode, languages[index].first, sizeof(szCode));\r\n\tNotifyValueChanged();\r\n}\r\n\r\nLanguageOptions::LanguageOptions()\r\n    : OptionCategoryBase(\"Language\", N_(\"Language\"), N_(\"Language Settings\"))\r\n{\r\n}\r\nstd::vector<OptionEntryBase *> LanguageOptions::GetEntries()\r\n{\r\n\treturn {\r\n\t\t&code,\r\n\t};\r\n}\r\n\r\nKeymapperOptions::KeymapperOptions()\r\n    : OptionCategoryBase(\"Keymapping\", N_(\"Keymapping\"), N_(\"Keymapping Settings\"))\r\n{\r\n\t// Insert all supported keys: a-z, 0-9 and F1-F24.\r\n\tkeyIDToKeyName.reserve(('Z' - 'A' + 1) + ('9' - '0' + 1) + 12);\r\n\tfor (char c = 'A'; c <= 'Z'; ++c) {\r\n\t\tkeyIDToKeyName.emplace(c, std::string(1, c));\r\n\t}\r\n\tfor (char c = '0'; c <= '9'; ++c) {\r\n\t\tkeyIDToKeyName.emplace(c, std::string(1, c));\r\n\t}\r\n\tfor (int i = 0; i < 12; ++i) {\r\n\t\tkeyIDToKeyName.emplace(SDLK_F1 + i, StrCat(\"F\", i + 1));\r\n\t}\r\n\tfor (int i = 0; i < 12; ++i) {\r\n\t\tkeyIDToKeyName.emplace(SDLK_F13 + i, StrCat(\"F\", i + 13));\r\n\t}\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_KP_0, \"KEYPADNUM 0\");\r\n\tfor (int i = 0; i < 9; i++) {\r\n\t\tkeyIDToKeyName.emplace(SDLK_KP_1 + i, StrCat(\"KEYPADNUM \", i + 1));\r\n\t}\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_LALT, \"LALT\");\r\n\tkeyIDToKeyName.emplace(SDLK_RALT, \"RALT\");\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_SPACE, \"SPACE\");\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_RCTRL, \"RCONTROL\");\r\n\tkeyIDToKeyName.emplace(SDLK_LCTRL, \"LCONTROL\");\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_PRINTSCREEN, \"PRINT\");\r\n\tkeyIDToKeyName.emplace(SDLK_PAUSE, \"PAUSE\");\r\n\tkeyIDToKeyName.emplace(SDLK_TAB, \"TAB\");\r\n\tkeyIDToKeyName.emplace(SDL_BUTTON_MIDDLE | KeymapperMouseButtonMask, \"MMOUSE\");\r\n\tkeyIDToKeyName.emplace(SDL_BUTTON_X1 | KeymapperMouseButtonMask, \"X1MOUSE\");\r\n\tkeyIDToKeyName.emplace(SDL_BUTTON_X2 | KeymapperMouseButtonMask, \"X2MOUSE\");\r\n\tkeyIDToKeyName.emplace(MouseScrollUpButton, \"SCROLLUPMOUSE\");\r\n\tkeyIDToKeyName.emplace(MouseScrollDownButton, \"SCROLLDOWNMOUSE\");\r\n\tkeyIDToKeyName.emplace(MouseScrollLeftButton, \"SCROLLLEFTMOUSE\");\r\n\tkeyIDToKeyName.emplace(MouseScrollRightButton, \"SCROLLRIGHTMOUSE\");\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_GRAVE, \"`\");\r\n\tkeyIDToKeyName.emplace(SDLK_LEFTBRACKET, \"[\");\r\n\tkeyIDToKeyName.emplace(SDLK_RIGHTBRACKET, \"]\");\r\n\tkeyIDToKeyName.emplace(SDLK_BACKSLASH, \"\\\\\");\r\n\tkeyIDToKeyName.emplace(SDLK_SEMICOLON, \";\");\r\n\tkeyIDToKeyName.emplace(SDLK_APOSTROPHE, \"'\");\r\n\tkeyIDToKeyName.emplace(SDLK_COMMA, \",\");\r\n\tkeyIDToKeyName.emplace(SDLK_PERIOD, \".\");\r\n\tkeyIDToKeyName.emplace(SDLK_SLASH, \"/\");\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_BACKSPACE, \"BACKSPACE\");\r\n\tkeyIDToKeyName.emplace(SDLK_CAPSLOCK, \"CAPSLOCK\");\r\n\tkeyIDToKeyName.emplace(SDLK_SCROLLLOCK, \"SCROLLLOCK\");\r\n\tkeyIDToKeyName.emplace(SDLK_INSERT, \"INSERT\");\r\n\tkeyIDToKeyName.emplace(SDLK_DELETE, \"DELETE\");\r\n\tkeyIDToKeyName.emplace(SDLK_HOME, \"HOME\");\r\n\tkeyIDToKeyName.emplace(SDLK_END, \"END\");\r\n\r\n\tkeyIDToKeyName.emplace(SDLK_KP_DIVIDE, \"KEYPAD /\");\r\n\tkeyIDToKeyName.emplace(SDLK_KP_MULTIPLY, \"KEYPAD *\");\r\n\tkeyIDToKeyName.emplace(SDLK_KP_ENTER, \"KEYPAD ENTER\");\r\n\tkeyIDToKeyName.emplace(SDLK_KP_PERIOD, \"KEYPAD DECIMAL\");\r\n\r\n\tkeyNameToKeyID.reserve(keyIDToKeyName.size());\r\n\tfor (const auto &[key, value] : keyIDToKeyName) {\r\n\t\tkeyNameToKeyID.emplace(value, key);\r\n\t}\r\n}\r\n\r\nstd::vector<OptionEntryBase *> KeymapperOptions::GetEntries()\r\n{\r\n\tstd::vector<OptionEntryBase *> entries;\r\n\tfor (Action &action : actions) {\r\n\t\tentries.push_back(&action);\r\n\t}\r\n\treturn entries;\r\n}\r\n\r\nKeymapperOptions::Action::Action(std::string_view key, const char *name, const char *description, uint32_t defaultKey, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index)\r\n    : OptionEntryBase(key, OptionEntryFlags::None, name, description)\r\n    , actionPressed(std::move(actionPressed))\r\n    , actionReleased(std::move(actionReleased))\r\n    , defaultKey(defaultKey)\r\n    , enable(std::move(enable))\r\n    , dynamicIndex(index)\r\n{\r\n\tif (index != 0) {\r\n\t\tdynamicKey = fmt::format(fmt::runtime(std::string_view(key.data(), key.size())), index);\r\n\t\tthis->key = dynamicKey;\r\n\t}\r\n}\r\n\r\nstd::string_view KeymapperOptions::Action::GetName() const\r\n{\r\n\tif (dynamicIndex == 0)\r\n\t\treturn _(name);\r\n\tdynamicName = fmt::format(fmt::runtime(_(name)), dynamicIndex);\r\n\treturn dynamicName;\r\n}\r\n\r\nvoid KeymapperOptions::Action::LoadFromIni(std::string_view category)\r\n{\r\n\tconst std::span<const Ini::Value> iniValues = ini->get(category, key);\r\n\tif (iniValues.empty()) {\r\n\t\tSetValue(defaultKey);\r\n\t\treturn; // Use the default key if no key has been set.\r\n\t}\r\n\r\n\tconst std::string_view iniValue = iniValues.back().value;\r\n\tif (iniValue.empty()) {\r\n\t\tSetValue(SDLK_UNKNOWN);\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto keyIt = GetOptions().Keymapper.keyNameToKeyID.find(iniValue);\r\n\tif (keyIt == GetOptions().Keymapper.keyNameToKeyID.end()) {\r\n\t\t// Use the default key if the key is unknown.\r\n\t\tLog(\"Keymapper: unknown key '{}'\", iniValue);\r\n\t\tSetValue(defaultKey);\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Store the key in action.key and in the map so we can save() the\r\n\t// actions while keeping the same order as they have been added.\r\n\tSetValue(keyIt->second);\r\n}\r\nvoid KeymapperOptions::Action::SaveToIni(std::string_view category) const\r\n{\r\n\tif (boundKey == SDLK_UNKNOWN) {\r\n\t\t// Just add an empty config entry if the action is unbound.\r\n\t\tini->set(category, key, std::string {});\r\n\t\treturn;\r\n\t}\r\n\tauto keyNameIt = GetOptions().Keymapper.keyIDToKeyName.find(boundKey);\r\n\tif (keyNameIt == GetOptions().Keymapper.keyIDToKeyName.end()) {\r\n\t\tLogVerbose(\"Keymapper: no name found for key {} bound to {}\", boundKey, key);\r\n\t\treturn;\r\n\t}\r\n\tini->set(category, key, keyNameIt->second);\r\n}\r\n\r\nstd::string_view KeymapperOptions::Action::GetValueDescription() const\r\n{\r\n\tif (boundKey == SDLK_UNKNOWN)\r\n\t\treturn \"\";\r\n\tauto keyNameIt = GetOptions().Keymapper.keyIDToKeyName.find(boundKey);\r\n\tif (keyNameIt == GetOptions().Keymapper.keyIDToKeyName.end()) {\r\n\t\treturn \"\";\r\n\t}\r\n\treturn keyNameIt->second;\r\n}\r\n\r\nbool KeymapperOptions::Action::SetValue(int value)\r\n{\r\n\tif (value != SDLK_UNKNOWN && GetOptions().Keymapper.keyIDToKeyName.find(value) == GetOptions().Keymapper.keyIDToKeyName.end()) {\r\n\t\t// Ignore invalid key values\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// Remove old key\r\n\tif (boundKey != SDLK_UNKNOWN) {\r\n\t\tGetOptions().Keymapper.keyIDToAction.erase(boundKey);\r\n\t\tboundKey = SDLK_UNKNOWN;\r\n\t}\r\n\r\n\t// Add new key\r\n\tif (value != SDLK_UNKNOWN) {\r\n\t\tauto it = GetOptions().Keymapper.keyIDToAction.find(value);\r\n\t\tif (it != GetOptions().Keymapper.keyIDToAction.end()) {\r\n\t\t\t// Warn about overwriting keys.\r\n\t\t\tLog(\"Keymapper: key '{}' is already bound to action '{}', overwriting\", value, it->second.get().name);\r\n\t\t\tit->second.get().boundKey = SDLK_UNKNOWN;\r\n\t\t}\r\n\r\n\t\tGetOptions().Keymapper.keyIDToAction.insert_or_assign(value, *this);\r\n\t\tboundKey = value;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid KeymapperOptions::AddAction(std::string_view key, const char *name, const char *description, uint32_t defaultKey, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index)\r\n{\r\n\tactions.emplace_front(key, name, description, defaultKey, std::move(actionPressed), std::move(actionReleased), std::move(enable), index);\r\n}\r\n\r\nvoid KeymapperOptions::CommitActions()\r\n{\r\n\tactions.reverse();\r\n}\r\n\r\nconst KeymapperOptions::Action *KeymapperOptions::findAction(uint32_t key) const\r\n{\r\n\tauto it = keyIDToAction.find(key);\r\n\tif (it == keyIDToAction.end()) return nullptr;\r\n\treturn &it->second.get();\r\n}\r\n\r\nstd::string_view KeymapperOptions::KeyNameForAction(std::string_view actionName) const\r\n{\r\n\tfor (const Action &action : actions) {\r\n\t\tif (action.key == actionName && action.boundKey != SDLK_UNKNOWN) {\r\n\t\t\treturn action.GetValueDescription();\r\n\t\t}\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nuint32_t KeymapperOptions::KeyForAction(std::string_view actionName) const\r\n{\r\n\tfor (const Action &action : actions) {\r\n\t\tif (action.key == actionName && action.boundKey != SDLK_UNKNOWN) {\r\n\t\t\treturn action.boundKey;\r\n\t\t}\r\n\t}\r\n\treturn SDLK_UNKNOWN;\r\n}\r\n\r\nPadmapperOptions::PadmapperOptions()\r\n    : OptionCategoryBase(\"Padmapping\", N_(\"Padmapping\"), N_(\"Padmapping Settings\"))\r\n    , buttonToButtonName { {\r\n\t      /*ControllerButton_NONE*/ {},\r\n\t      /*ControllerButton_IGNORE*/ {},\r\n\t      /*ControllerButton_AXIS_TRIGGERLEFT*/ \"LT\",\r\n\t      /*ControllerButton_AXIS_TRIGGERRIGHT*/ \"RT\",\r\n\t      /*ControllerButton_BUTTON_A*/ \"A\",\r\n\t      /*ControllerButton_BUTTON_B*/ \"B\",\r\n\t      /*ControllerButton_BUTTON_X*/ \"X\",\r\n\t      /*ControllerButton_BUTTON_Y*/ \"Y\",\r\n\t      /*ControllerButton_BUTTON_LEFTSTICK*/ \"LS\",\r\n\t      /*ControllerButton_BUTTON_RIGHTSTICK*/ \"RS\",\r\n\t      /*ControllerButton_BUTTON_LEFTSHOULDER*/ \"LB\",\r\n\t      /*ControllerButton_BUTTON_RIGHTSHOULDER*/ \"RB\",\r\n\t      /*ControllerButton_BUTTON_START*/ \"Start\",\r\n\t      /*ControllerButton_BUTTON_BACK*/ \"Select\",\r\n\t      /*ControllerButton_BUTTON_DPAD_UP*/ \"Up\",\r\n\t      /*ControllerButton_BUTTON_DPAD_DOWN*/ \"Down\",\r\n\t      /*ControllerButton_BUTTON_DPAD_LEFT*/ \"Left\",\r\n\t      /*ControllerButton_BUTTON_DPAD_RIGHT*/ \"Right\",\r\n\t  } }\r\n{\r\n\tbuttonNameToButton.reserve(buttonToButtonName.size());\r\n\tfor (size_t i = 0; i < buttonToButtonName.size(); ++i) {\r\n\t\tbuttonNameToButton.emplace(buttonToButtonName[i], static_cast<ControllerButton>(i));\r\n\t}\r\n}\r\n\r\nstd::vector<OptionEntryBase *> PadmapperOptions::GetEntries()\r\n{\r\n\tstd::vector<OptionEntryBase *> entries;\r\n\tfor (Action &action : actions) {\r\n\t\tentries.push_back(&action);\r\n\t}\r\n\treturn entries;\r\n}\r\n\r\nPadmapperOptions::Action::Action(std::string_view key, const char *name, const char *description, ControllerButtonCombo defaultInput, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index)\r\n    : OptionEntryBase(key, OptionEntryFlags::None, name, description)\r\n    , actionPressed(std::move(actionPressed))\r\n    , actionReleased(std::move(actionReleased))\r\n    , defaultInput(defaultInput)\r\n    , enable(std::move(enable))\r\n    , dynamicIndex(index)\r\n{\r\n\tif (index != 0) {\r\n\t\tdynamicKey = fmt::format(fmt::runtime(std::string_view(key.data(), key.size())), index);\r\n\t\tthis->key = dynamicKey;\r\n\t}\r\n}\r\n\r\nstd::string_view PadmapperOptions::Action::GetName() const\r\n{\r\n\tif (dynamicIndex == 0)\r\n\t\treturn _(name);\r\n\tdynamicName = fmt::format(fmt::runtime(_(name)), dynamicIndex);\r\n\treturn dynamicName;\r\n}\r\n\r\nvoid PadmapperOptions::Action::LoadFromIni(std::string_view category)\r\n{\r\n\tconst std::span<const Ini::Value> iniValues = ini->get(category, key);\r\n\tif (iniValues.empty()) {\r\n\t\tSetValue(defaultInput);\r\n\t\treturn; // Use the default button combo if no mapping has been set.\r\n\t}\r\n\tconst std::string_view iniValue = iniValues.back().value;\r\n\r\n\tstd::string modName;\r\n\tstd::string buttonName;\r\n\tauto parts = SplitByChar(iniValue, '+');\r\n\tauto it = parts.begin();\r\n\tif (it == parts.end()) {\r\n\t\tSetValue(ControllerButtonCombo {});\r\n\t\treturn;\r\n\t}\r\n\tbuttonName = std::string(*it);\r\n\tif (++it != parts.end()) {\r\n\t\tmodName = std::move(buttonName);\r\n\t\tbuttonName = std::string(*it);\r\n\t}\r\n\r\n\tControllerButtonCombo input {};\r\n\tif (!modName.empty()) {\r\n\t\tauto modifierIt = GetOptions().Padmapper.buttonNameToButton.find(modName);\r\n\t\tif (modifierIt == GetOptions().Padmapper.buttonNameToButton.end()) {\r\n\t\t\t// Use the default button combo if the modifier name is unknown.\r\n\t\t\tLogWarn(\"Padmapper: unknown button '{}'\", modName);\r\n\t\t\tSetValue(defaultInput);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tinput.modifier = modifierIt->second;\r\n\t}\r\n\r\n\tauto buttonIt = GetOptions().Padmapper.buttonNameToButton.find(buttonName);\r\n\tif (buttonIt == GetOptions().Padmapper.buttonNameToButton.end()) {\r\n\t\t// Use the default button combo if the button name is unknown.\r\n\t\tLogWarn(\"Padmapper: unknown button '{}'\", buttonName);\r\n\t\tSetValue(defaultInput);\r\n\t\treturn;\r\n\t}\r\n\tinput.button = buttonIt->second;\r\n\r\n\t// Store the input in action.boundInput and in the map so we can save()\r\n\t// the actions while keeping the same order as they have been added.\r\n\tSetValue(input);\r\n}\r\nvoid PadmapperOptions::Action::SaveToIni(std::string_view category) const\r\n{\r\n\tif (boundInput.button == ControllerButton_NONE) {\r\n\t\t// Just add an empty config entry if the action is unbound.\r\n\t\tini->set(category, key, \"\");\r\n\t\treturn;\r\n\t}\r\n\tstd::string inputName = GetOptions().Padmapper.buttonToButtonName[static_cast<size_t>(boundInput.button)];\r\n\tif (inputName.empty()) {\r\n\t\tLogVerbose(\"Padmapper: no name found for button {} bound to {}\", static_cast<size_t>(boundInput.button), key);\r\n\t\treturn;\r\n\t}\r\n\tif (boundInput.modifier != ControllerButton_NONE) {\r\n\t\tconst std::string &modifierName = GetOptions().Padmapper.buttonToButtonName[static_cast<size_t>(boundInput.modifier)];\r\n\t\tif (modifierName.empty()) {\r\n\t\t\tLogVerbose(\"Padmapper: no name found for modifier button {} bound to {}\", static_cast<size_t>(boundInput.button), key);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tinputName = StrCat(modifierName, \"+\", inputName);\r\n\t}\r\n\tini->set(category, key, inputName.data());\r\n}\r\n\r\nvoid PadmapperOptions::Action::UpdateValueDescription() const\r\n{\r\n\tboundInputDescriptionType = GamepadType;\r\n\tif (boundInput.button == ControllerButton_NONE) {\r\n\t\tboundInputDescription = \"\";\r\n\t\tboundInputShortDescription = \"\";\r\n\t\treturn;\r\n\t}\r\n\tconst std::string_view buttonName = ToString(GamepadType, boundInput.button);\r\n\tif (boundInput.modifier == ControllerButton_NONE) {\r\n\t\tboundInputDescription = std::string(buttonName);\r\n\t\tboundInputShortDescription = std::string(Shorten(buttonName));\r\n\t\treturn;\r\n\t}\r\n\tconst std::string_view modifierName = ToString(GamepadType, boundInput.modifier);\r\n\tboundInputDescription = StrCat(modifierName, \"+\", buttonName);\r\n\tboundInputShortDescription = StrCat(Shorten(modifierName), \"+\", Shorten(buttonName));\r\n}\r\n\r\nstd::string_view PadmapperOptions::Action::Shorten(std::string_view buttonName) const\r\n{\r\n\tsize_t index = 0;\r\n\tsize_t chars = 0;\r\n\twhile (index < buttonName.size()) {\r\n\t\tif (!IsTrailUtf8CodeUnit(buttonName[index]))\r\n\t\t\tchars++;\r\n\t\tif (chars == 3)\r\n\t\t\tbreak;\r\n\t\tindex++;\r\n\t}\r\n\treturn std::string_view(buttonName.data(), index);\r\n}\r\n\r\nstd::string_view PadmapperOptions::Action::GetValueDescription() const\r\n{\r\n\treturn GetValueDescription(false);\r\n}\r\n\r\nstd::string_view PadmapperOptions::Action::GetValueDescription(bool useShortName) const\r\n{\r\n\tif (GamepadType != boundInputDescriptionType)\r\n\t\tUpdateValueDescription();\r\n\treturn useShortName ? boundInputShortDescription : boundInputDescription;\r\n}\r\n\r\nbool PadmapperOptions::Action::SetValue(ControllerButtonCombo value)\r\n{\r\n\tif (boundInput.button != ControllerButton_NONE)\r\n\t\tboundInput = {};\r\n\tif (value.button != ControllerButton_NONE)\r\n\t\tboundInput = value;\r\n\tUpdateValueDescription();\r\n\treturn true;\r\n}\r\n\r\nvoid PadmapperOptions::AddAction(std::string_view key, const char *name, const char *description, ControllerButtonCombo defaultInput, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index)\r\n{\r\n\tif (committed)\r\n\t\treturn;\r\n\tactions.emplace_front(key, name, description, defaultInput, std::move(actionPressed), std::move(actionReleased), std::move(enable), index);\r\n}\r\n\r\nvoid PadmapperOptions::CommitActions()\r\n{\r\n\tif (committed)\r\n\t\treturn;\r\n\tactions.reverse();\r\n\tcommitted = true;\r\n}\r\n\r\nstd::string_view PadmapperOptions::InputNameForAction(std::string_view actionName, bool useShortName) const\r\n{\r\n\tfor (const Action &action : actions) {\r\n\t\tif (action.key == actionName && action.boundInput.button != ControllerButton_NONE) {\r\n\t\t\treturn action.GetValueDescription(useShortName);\r\n\t\t}\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nControllerButtonCombo PadmapperOptions::ButtonComboForAction(std::string_view actionName) const\r\n{\r\n\tfor (const auto &action : actions) {\r\n\t\tif (action.key == actionName && action.boundInput.button != ControllerButton_NONE) {\r\n\t\t\treturn action.boundInput;\r\n\t\t}\r\n\t}\r\n\treturn ControllerButton_NONE;\r\n}\r\n\r\nconst PadmapperOptions::Action *PadmapperOptions::findAction(ControllerButton button, tl::function_ref<bool(ControllerButton)> isModifierPressed) const\r\n{\r\n\t// To give preference to button combinations,\r\n\t// first pass ignores mappings where no modifier is bound\r\n\tfor (const Action &action : actions) {\r\n\t\tconst ControllerButtonCombo combo = action.boundInput;\r\n\t\tif (combo.modifier == ControllerButton_NONE)\r\n\t\t\tcontinue;\r\n\t\tif (button != combo.button)\r\n\t\t\tcontinue;\r\n\t\tif (!isModifierPressed(combo.modifier))\r\n\t\t\tcontinue;\r\n\t\tif (action.enable && !action.enable())\r\n\t\t\tcontinue;\r\n\t\treturn &action;\r\n\t}\r\n\r\n\tfor (const Action &action : actions) {\r\n\t\tconst ControllerButtonCombo combo = action.boundInput;\r\n\t\tif (combo.modifier != ControllerButton_NONE)\r\n\t\t\tcontinue;\r\n\t\tif (button != combo.button)\r\n\t\t\tcontinue;\r\n\t\tif (action.enable && !action.enable())\r\n\t\t\tcontinue;\r\n\t\treturn &action;\r\n\t}\r\n\r\n\treturn nullptr;\r\n}\r\n\r\nModOptions::ModOptions()\r\n    : OptionCategoryBase(\"Mods\", N_(\"Mods\"), N_(\"Mod Settings\"))\r\n{\r\n}\r\n\r\nstd::vector<std::string_view> ModOptions::GetActiveModList()\r\n{\r\n\tstd::vector<std::string_view> modList;\r\n\tfor (auto &modEntry : GetModEntries()) {\r\n\t\tif (*modEntry.enabled)\r\n\t\t\tmodList.emplace_back(modEntry.name);\r\n\t}\r\n\treturn modList;\r\n}\r\n\r\nstd::vector<std::string_view> ModOptions::GetModList()\r\n{\r\n\tstd::vector<std::string_view> modList;\r\n\tfor (auto &modEntry : GetModEntries()) {\r\n\t\tmodList.emplace_back(modEntry.name);\r\n\t}\r\n\treturn modList;\r\n}\r\n\r\nstd::vector<OptionEntryBase *> ModOptions::GetEntries()\r\n{\r\n\tstd::vector<OptionEntryBase *> optionEntries;\r\n\tfor (auto &modEntry : GetModEntries()) {\r\n\t\toptionEntries.emplace_back(&modEntry.enabled);\r\n\t}\r\n\treturn optionEntries;\r\n}\r\n\r\nvoid ModOptions::AddModEntry(const std::string &modName)\r\n{\r\n\tauto &entries = GetModEntries();\r\n\tentries.emplace_front(modName);\r\n}\r\n\r\nvoid ModOptions::RemoveModEntry(const std::string &modName)\r\n{\r\n\tif (!modEntries) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto &entries = *modEntries;\r\n\tentries.remove_if([&](const ModEntry &entry) {\r\n\t\treturn entry.name == modName;\r\n\t});\r\n}\r\n\r\nvoid ModOptions::SetHellfireEnabled(bool enableHellfire)\r\n{\r\n\tfor (auto &modEntry : GetModEntries()) {\r\n\t\tif (modEntry.name == \"Hellfire\") {\r\n\t\t\tmodEntry.enabled.SetValue(enableHellfire);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nstd::forward_list<ModOptions::ModEntry> &ModOptions::GetModEntries()\r\n{\r\n\tif (modEntries)\r\n\t\treturn *modEntries;\r\n\r\n\tconst std::vector<std::string> modNames = ini->getKeys(key);\r\n\r\n\tstd::forward_list<ModOptions::ModEntry> &newModEntries = modEntries.emplace();\r\n\tfor (auto &modName : modNames) {\r\n\t\tnewModEntries.emplace_front(modName);\r\n\t}\r\n\tnewModEntries.reverse();\r\n\treturn newModEntries;\r\n}\r\n\r\nModOptions::ModEntry::ModEntry(std::string_view name)\r\n    : name(name)\r\n    , enabled(this->name, OptionEntryFlags::RecreateUI, this->name.c_str(), \"\", false)\r\n{\r\n}\r\n\r\nnamespace {\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\nconstexpr char ResamplerSpeex[] = \"Speex\";\r\n#endif\r\n#ifdef DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\nconstexpr char ResamplerSDL[] = \"SDL\";\r\n#endif\r\n} // namespace\r\n\r\nstd::string_view ResamplerToString(Resampler resampler)\r\n{\r\n\tswitch (resampler) {\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\n\tcase Resampler::Speex:\r\n\t\treturn ResamplerSpeex;\r\n#endif\r\n#ifdef DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n\tcase Resampler::SDL:\r\n\t\treturn ResamplerSDL;\r\n#endif\r\n\tdefault:\r\n\t\treturn \"\";\r\n\t}\r\n}\r\n\r\nstd::optional<Resampler> ResamplerFromString(std::string_view resampler)\r\n{\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\n\tif (resampler == ResamplerSpeex)\r\n\t\treturn Resampler::Speex;\r\n#endif\r\n#ifdef DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n\tif (resampler == ResamplerSDL)\r\n\t\treturn Resampler::SDL;\r\n#endif\r\n\treturn std::nullopt;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/options.h",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <forward_list>\r\n#include <functional>\r\n#include <initializer_list>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_version.h>\r\n\r\n#ifndef NOSOUND\r\n#include <SDL3/SDL_audio.h>\r\n#endif\r\n#else\r\n#include <SDL_version.h>\r\n#endif\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <function_ref.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"controls/controller_buttons.h\"\r\n#include \"engine/size.hpp\"\r\n#include \"engine/sound_defs.hpp\"\r\n#include \"pack.h\"\r\n#include \"quick_messages.hpp\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/string_view_hash.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#ifndef DEFAULT_WIDTH\r\n#define DEFAULT_WIDTH 640\r\n#endif\r\n#ifndef DEFAULT_HEIGHT\r\n#define DEFAULT_HEIGHT 480\r\n#endif\r\n\r\nenum class StartUpGameMode : uint8_t {\r\n\t/** @brief If hellfire is present, asks the user what game they want to start. */\r\n\tAsk = 0,\r\n\tHellfire = 1,\r\n\tDiablo = 2,\r\n};\r\n\r\nenum class StartUpIntro : uint8_t {\r\n\tOff = 0,\r\n\tOnce = 1,\r\n\tOn = 2,\r\n};\r\n\r\n/** @brief Defines what splash screen should be shown at startup. */\r\nenum class StartUpSplash : uint8_t {\r\n\t/** @brief Show no splash screen. */\r\n\tNone = 0,\r\n\t/** @brief Show only TitleDialog. */\r\n\tTitleDialog = 1,\r\n\t/** @brief Show Logo and TitleDialog. */\r\n\tLogoAndTitleDialog = 2,\r\n};\r\n\r\nenum class ScalingQuality : uint8_t {\r\n\tNearestPixel,\r\n\tBilinearFiltering,\r\n\tAnisotropicFiltering,\r\n};\r\n\r\nenum class FrameRateControl : uint8_t {\r\n\tNone = 0,\r\n#ifndef USE_SDL1\r\n\tVerticalSync = 1,\r\n#endif\r\n\tCPUSleep = 2,\r\n};\r\n\r\nenum class Resampler : uint8_t {\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\n\tSpeex = 0,\r\n#endif\r\n#ifdef DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n\tSDL,\r\n#endif\r\n};\r\n\r\nstd::string_view ResamplerToString(Resampler resampler);\r\nstd::optional<Resampler> ResamplerFromString(std::string_view resampler);\r\n\r\nenum class OptionEntryType : uint8_t {\r\n\tBoolean,\r\n\tList,\r\n\tKey,\r\n\tPadButton,\r\n};\r\n\r\nenum class OptionEntryFlags : uint8_t {\r\n\t/** @brief No special logic. */\r\n\tNone = 0,\r\n\t/** @brief Shouldn't be shown in settings dialog. */\r\n\tInvisible = 1 << 0,\r\n\t/** @brief Need to restart the current running game (single- or multiplayer) to take effect. */\r\n\tCantChangeInGame = 1 << 1,\r\n\t/** @brief Need to restart the current running multiplayer game to take effect. */\r\n\tCantChangeInMultiPlayer = 1 << 2,\r\n\t/** @brief Option is only relevant for Hellfire. */\r\n\tOnlyHellfire = 1 << 3,\r\n\t/** @brief Option is only relevant for Diablo. */\r\n\tOnlyDiablo = 1 << 4,\r\n\t/** @brief After option is changed the UI needs to be recreated. */\r\n\tRecreateUI = 1 << 5,\r\n\t/** @brief diablo.mpq must be present. */\r\n\tNeedDiabloMpq = 1 << 6,\r\n};\r\nuse_enum_as_flags(OptionEntryFlags);\r\n\r\nclass OptionEntryBase {\r\npublic:\r\n\tOptionEntryBase(std::string_view key, OptionEntryFlags flags, const char *name, const char *description)\r\n\t    : flags(flags)\r\n\t    , key(key)\r\n\t    , name(name)\r\n\t    , description(description)\r\n\t{\r\n\t}\r\n\t[[nodiscard]] virtual std::string_view GetName() const;\r\n\t[[nodiscard]] std::string_view GetDescription() const;\r\n\t[[nodiscard]] virtual OptionEntryType GetType() const = 0;\r\n\t[[nodiscard]] OptionEntryFlags GetFlags() const;\r\n\r\n\tvoid SetValueChangedCallback(tl::function_ref<void()> callback);\r\n\r\n\t[[nodiscard]] virtual std::string_view GetValueDescription() const = 0;\r\n\tvirtual void LoadFromIni(std::string_view category) = 0;\r\n\tvirtual void SaveToIni(std::string_view category) const = 0;\r\n\r\n\tOptionEntryFlags flags;\r\n\r\npublic:\r\n\tstd::string_view key;\r\n\r\nprotected:\r\n\tconst char *name;\r\n\tconst char *description;\r\n\tvoid NotifyValueChanged();\r\n\r\nprivate:\r\n\tstd::optional<tl::function_ref<void()>> callback_;\r\n};\r\n\r\nclass OptionEntryBoolean : public OptionEntryBase {\r\npublic:\r\n\tOptionEntryBoolean(std::string_view key, OptionEntryFlags flags, const char *name, const char *description, bool defaultValue)\r\n\t    : OptionEntryBase(key, flags, name, description)\r\n\t    , defaultValue(defaultValue)\r\n\t    , value(defaultValue)\r\n\t{\r\n\t}\r\n\t[[nodiscard]] bool operator*() const\r\n\t{\r\n\t\treturn value;\r\n\t}\r\n\tvoid SetValue(bool value);\r\n\r\n\t[[nodiscard]] OptionEntryType GetType() const override;\r\n\t[[nodiscard]] std::string_view GetValueDescription() const override;\r\n\tvoid LoadFromIni(std::string_view category) override;\r\n\tvoid SaveToIni(std::string_view category) const override;\r\n\r\nprivate:\r\n\tbool defaultValue;\r\n\tbool value;\r\n};\r\n\r\nclass OptionEntryListBase : public OptionEntryBase {\r\npublic:\r\n\t[[nodiscard]] virtual size_t GetListSize() const = 0;\r\n\t[[nodiscard]] virtual std::string_view GetListDescription(size_t index) const = 0;\r\n\t[[nodiscard]] virtual size_t GetActiveListIndex() const = 0;\r\n\tvirtual void SetActiveListIndex(size_t index) = 0;\r\n\r\n\t[[nodiscard]] OptionEntryType GetType() const override;\r\n\t[[nodiscard]] std::string_view GetValueDescription() const override;\r\n\r\nprotected:\r\n\tOptionEntryListBase(std::string_view key, OptionEntryFlags flags, const char *name, const char *description)\r\n\t    : OptionEntryBase(key, flags, name, description)\r\n\t{\r\n\t}\r\n};\r\n\r\nclass OptionEntryEnumBase : public OptionEntryListBase {\r\npublic:\r\n\tvoid LoadFromIni(std::string_view category) override;\r\n\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t[[nodiscard]] size_t GetListSize() const override;\r\n\t[[nodiscard]] std::string_view GetListDescription(size_t index) const override;\r\n\t[[nodiscard]] size_t GetActiveListIndex() const override;\r\n\tvoid SetActiveListIndex(size_t index) override;\r\n\r\nprotected:\r\n\tOptionEntryEnumBase(std::string_view key, OptionEntryFlags flags, const char *name, const char *description, int defaultValue)\r\n\t    : OptionEntryListBase(key, flags, name, description)\r\n\t    , defaultValue(defaultValue)\r\n\t    , value(defaultValue)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] int GetValueInternal() const\r\n\t{\r\n\t\treturn value;\r\n\t}\r\n\tvoid SetValueInternal(int value);\r\n\r\n\tvoid AddEntry(int value, std::string_view name);\r\n\r\nprivate:\r\n\tint defaultValue;\r\n\tint value;\r\n\tstd::vector<std::string_view> entryNames;\r\n\tstd::vector<int> entryValues;\r\n};\r\n\r\ntemplate <typename T>\r\nclass OptionEntryEnum : public OptionEntryEnumBase {\r\npublic:\r\n\tOptionEntryEnum(std::string_view key, OptionEntryFlags flags, const char *name, const char *description, T defaultValue, std::initializer_list<std::pair<T, std::string_view>> entries)\r\n\t    : OptionEntryEnumBase(key, flags, name, description, static_cast<int>(defaultValue))\r\n\t{\r\n\t\tfor (auto &&[entryValue, entryName] : entries) {\r\n\t\t\tAddEntry(static_cast<int>(entryValue), entryName);\r\n\t\t}\r\n\t}\r\n\t[[nodiscard]] T operator*() const\r\n\t{\r\n\t\treturn static_cast<T>(GetValueInternal());\r\n\t}\r\n\tvoid SetValue(T value)\r\n\t{\r\n\t\tSetValueInternal(static_cast<int>(value));\r\n\t}\r\n};\r\n\r\nclass OptionEntryIntBase : public OptionEntryListBase {\r\npublic:\r\n\tvoid LoadFromIni(std::string_view category) override;\r\n\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t[[nodiscard]] size_t GetListSize() const override;\r\n\t[[nodiscard]] std::string_view GetListDescription(size_t index) const override;\r\n\t[[nodiscard]] size_t GetActiveListIndex() const override;\r\n\tvoid SetActiveListIndex(size_t index) override;\r\n\r\nprotected:\r\n\tOptionEntryIntBase(std::string_view key, OptionEntryFlags flags, const char *name, const char *description, int defaultValue)\r\n\t    : OptionEntryListBase(key, flags, name, description)\r\n\t    , defaultValue(defaultValue)\r\n\t    , value(defaultValue)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] int GetValueInternal() const\r\n\t{\r\n\t\treturn value;\r\n\t}\r\n\tvoid SetValueInternal(int value);\r\n\r\n\tvoid AddEntry(int value);\r\n\r\nprivate:\r\n\tint defaultValue;\r\n\tint value;\r\n\tmutable std::vector<std::string> entryNames;\r\n\tstd::vector<int> entryValues;\r\n};\r\n\r\ntemplate <typename T>\r\nclass OptionEntryInt : public OptionEntryIntBase {\r\npublic:\r\n\tOptionEntryInt(std::string_view key, OptionEntryFlags flags, const char *name, const char *description, T defaultValue, std::initializer_list<T> entries)\r\n\t    : OptionEntryIntBase(key, flags, name, description, static_cast<int>(defaultValue))\r\n\t{\r\n\t\tfor (auto entry : entries) {\r\n\t\t\tAddEntry(static_cast<int>(entry));\r\n\t\t}\r\n\t}\r\n\tOptionEntryInt(std::string_view key, OptionEntryFlags flags, const char *name, const char *description, T defaultValue)\r\n\t    : OptionEntryInt(key, flags, name, description, defaultValue, { defaultValue })\r\n\t{\r\n\t}\r\n\t[[nodiscard]] T operator*() const\r\n\t{\r\n\t\treturn static_cast<T>(GetValueInternal());\r\n\t}\r\n\tvoid SetValue(T value)\r\n\t{\r\n\t\tSetValueInternal(static_cast<int>(value));\r\n\t}\r\n};\r\n\r\nclass OptionEntryLanguageCode : public OptionEntryListBase {\r\npublic:\r\n\tOptionEntryLanguageCode();\r\n\r\n\tvoid LoadFromIni(std::string_view category) override;\r\n\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t[[nodiscard]] size_t GetListSize() const override;\r\n\t[[nodiscard]] std::string_view GetListDescription(size_t index) const override;\r\n\t[[nodiscard]] size_t GetActiveListIndex() const override;\r\n\tvoid SetActiveListIndex(size_t index) override;\r\n\r\n\tstd::string_view operator*() const\r\n\t{\r\n\t\treturn szCode;\r\n\t}\r\n\r\n\tOptionEntryLanguageCode &operator=(std::string_view code)\r\n\t{\r\n\t\tassert(code.size() < 6);\r\n\t\tmemcpy(szCode, code.data(), code.size());\r\n\t\tszCode[code.size()] = '\\0';\r\n\t\treturn *this;\r\n\t}\r\n\r\nprivate:\r\n\t/** @brief Language code (ISO-15897) for text. */\r\n\tchar szCode[6];\r\n\tmutable std::vector<std::pair<std::string, std::string>> languages;\r\n\r\n\tvoid CheckLanguagesAreInitialized() const;\r\n};\r\n\r\nclass OptionEntryResolution : public OptionEntryListBase {\r\npublic:\r\n\tOptionEntryResolution();\r\n\r\n\tvoid LoadFromIni(std::string_view category) override;\r\n\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t[[nodiscard]] size_t GetListSize() const override;\r\n\t[[nodiscard]] std::string_view GetListDescription(size_t index) const override;\r\n\t[[nodiscard]] size_t GetActiveListIndex() const override;\r\n\tvoid SetActiveListIndex(size_t index) override;\r\n\r\n\tvoid setAvailableResolutions(std::vector<std::pair<Size, std::string>> &&resolutions)\r\n\t{\r\n\t\tresolutions_ = std::move(resolutions);\r\n\t}\r\n\r\n\tSize operator*() const { return size_; }\r\n\r\nprivate:\r\n\t/** @brief View size. */\r\n\tSize size_;\r\n\tstd::vector<std::pair<Size, std::string>> resolutions_;\r\n};\r\n\r\nclass OptionEntryResampler : public OptionEntryListBase {\r\npublic:\r\n\tOptionEntryResampler();\r\n\r\n\tvoid LoadFromIni(std::string_view category) override;\r\n\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t[[nodiscard]] size_t GetListSize() const override;\r\n\t[[nodiscard]] std::string_view GetListDescription(size_t index) const override;\r\n\t[[nodiscard]] size_t GetActiveListIndex() const override;\r\n\tvoid SetActiveListIndex(size_t index) override;\r\n\r\n\tResampler operator*() const\r\n\t{\r\n\t\treturn resampler_;\r\n\t}\r\n\r\nprivate:\r\n\tvoid UpdateDependentOptions() const;\r\n\r\n\tResampler resampler_;\r\n};\r\n\r\nclass OptionEntryAudioDevice : public OptionEntryListBase {\r\npublic:\r\n\tOptionEntryAudioDevice();\r\n\r\n\tvoid LoadFromIni(std::string_view category) override;\r\n\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t[[nodiscard]] size_t GetListSize() const override;\r\n\t[[nodiscard]] std::string_view GetListDescription(size_t index) const override;\r\n\t[[nodiscard]] size_t GetActiveListIndex() const override;\r\n\tvoid SetActiveListIndex(size_t index) override;\r\n\r\n\tstd::string operator*() const\r\n\t{\r\n\t\tfor (size_t i = 0; i < GetListSize(); i++) {\r\n\t\t\tstd::string_view deviceName = GetDeviceName(i);\r\n\t\t\tif (deviceName == deviceName_)\r\n\t\t\t\treturn deviceName_;\r\n\t\t}\r\n\t\treturn \"\";\r\n\t}\r\n\r\n#ifdef USE_SDL3\r\n\t[[nodiscard]] SDL_AudioDeviceID id() const;\r\n#endif\r\n\r\nprivate:\r\n\tstd::string_view GetDeviceName(size_t index) const;\r\n\r\n\tstd::string deviceName_;\r\n#ifdef USE_SDL3\r\n\tSDL_AudioDeviceID deviceId_ = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;\r\n#endif\r\n};\r\n\r\nstruct OptionCategoryBase {\r\n\tOptionCategoryBase(std::string_view key, const char *name, const char *description)\r\n\t    : key(key)\r\n\t    , name(name)\r\n\t    , description(description)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view GetKey() const;\r\n\t[[nodiscard]] std::string_view GetName() const;\r\n\t[[nodiscard]] std::string_view GetDescription() const;\r\n\r\n\tvirtual std::vector<OptionEntryBase *> GetEntries() = 0;\r\n\r\nprotected:\r\n\tstd::string_view key;\r\n\tconst char *name;\r\n\tconst char *description;\r\n};\r\n\r\nstruct GameModeOptions : OptionCategoryBase {\r\n\tGameModeOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\tOptionEntryEnum<StartUpGameMode> gameMode;\r\n\tOptionEntryBoolean shareware;\r\n};\r\n\r\nstruct StartUpOptions : OptionCategoryBase {\r\n\tStartUpOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief Play game intro video on diablo startup. */\r\n\tOptionEntryEnum<StartUpIntro> diabloIntro;\r\n\t/** @brief Play game intro video on hellfire startup. */\r\n\tOptionEntryEnum<StartUpIntro> hellfireIntro;\r\n\tOptionEntryEnum<StartUpSplash> splash;\r\n};\r\n\r\nstruct DiabloOptions : OptionCategoryBase {\r\n\tDiabloOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief Remembers what singleplayer hero/save was last used. */\r\n\tOptionEntryInt<std::uint32_t> lastSinglePlayerHero;\r\n\t/** @brief Remembers what multiplayer hero/save was last used. */\r\n\tOptionEntryInt<std::uint32_t> lastMultiplayerHero;\r\n};\r\n\r\nstruct HellfireOptions : OptionCategoryBase {\r\n\tHellfireOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief Cornerstone of the world item. */\r\n\tchar szItem[sizeof(ItemPack) * 2 + 1];\r\n\t/** @brief Remembers what singleplayer hero/save was last used. */\r\n\tOptionEntryInt<std::uint32_t> lastSinglePlayerHero;\r\n\t/** @brief Remembers what multiplayer hero/save was last used. */\r\n\tOptionEntryInt<std::uint32_t> lastMultiplayerHero;\r\n};\r\n\r\nstruct AudioOptions : OptionCategoryBase {\r\n\tAudioOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief Movie and SFX volume. */\r\n\tOptionEntryInt<int> soundVolume;\r\n\t/** @brief Accessibility / navigation cues volume. */\r\n\tOptionEntryInt<int> audioCuesVolume;\r\n\t/** @brief Music volume. */\r\n\tOptionEntryInt<int> musicVolume;\r\n\t/** @brief Player emits sound when walking. */\r\n\tOptionEntryBoolean walkingSound;\r\n\t/** @brief Automatically equipping items on pickup emits the equipment sound. */\r\n\tOptionEntryBoolean autoEquipSound;\r\n\t/** @brief Picking up items emits the items pickup sound. */\r\n\tOptionEntryBoolean itemPickupSound;\r\n\r\n\t/** @brief Output sample rate (Hz). */\r\n\tOptionEntryInt<std::uint32_t> sampleRate;\r\n\t/** @brief The number of output channels (1 or 2) */\r\n\tOptionEntryInt<std::uint8_t> channels;\r\n\t/** @brief Buffer size (number of frames per channel) */\r\n\tOptionEntryInt<std::uint32_t> bufferSize;\r\n\t/** @brief Resampler implementation. */\r\n\tOptionEntryResampler resampler;\r\n\t/** @brief Quality of the resampler, from 0 (lowest) to 10 (highest). Available for the speex resampler only. */\r\n\tOptionEntryInt<std::uint8_t> resamplingQuality;\r\n\t/** @brief Audio device. */\r\n\tOptionEntryAudioDevice device;\r\n};\r\n\r\nstruct GraphicsOptions : OptionCategoryBase {\r\n\tGraphicsOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\tOptionEntryResolution resolution;\r\n\t/** @brief Run in fullscreen or windowed mode. */\r\n\tOptionEntryBoolean fullscreen;\r\n#if !defined(USE_SDL1) || defined(__3DS__)\r\n\t/** @brief Expand the aspect ratio to match the screen. */\r\n\tOptionEntryBoolean fitToScreen;\r\n#endif\r\n#ifndef USE_SDL1\r\n\t/** @brief Scale the image after rendering. */\r\n\tOptionEntryBoolean upscale;\r\n\t/** @brief See SDL_HINT_RENDER_SCALE_QUALITY. */\r\n\tOptionEntryEnum<ScalingQuality> scaleQuality;\r\n\t/** @brief Only scale by values divisible by the width and height. */\r\n\tOptionEntryBoolean integerScaling;\r\n#endif\r\n\t/** @brief Limit frame rate either for vsync or CPU load. */\r\n\tOptionEntryEnum<FrameRateControl> frameRateControl;\r\n\t/** @brief Brightness level. */\r\n\tOptionEntryInt<int> brightness;\r\n\t/** @brief Zoom on start. */\r\n\tOptionEntryBoolean zoom;\r\n\t/** @brief Subtile lighting for smoother light gradients. */\r\n\tOptionEntryBoolean perPixelLighting;\r\n\t/** @brief Enable color cycling animations. */\r\n\tOptionEntryBoolean colorCycling;\r\n\t/** @brief Use alternate nest palette. */\r\n\tOptionEntryBoolean alternateNestArt;\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t/** @brief Use a hardware cursor (SDL2 only). */\r\n\tOptionEntryBoolean hardwareCursor;\r\n\t/** @brief Use a hardware cursor for items. */\r\n\tOptionEntryBoolean hardwareCursorForItems;\r\n\t/** @brief Maximum width / height for the hardware cursor. Larger cursors fall back to software. */\r\n\tOptionEntryInt<int> hardwareCursorMaxSize;\r\n#endif\r\n\t/** @brief Show FPS, even without the -f command line flag. */\r\n\tOptionEntryBoolean showFPS;\r\n};\r\n\r\nstruct GameplayOptions : OptionCategoryBase {\r\n\tGameplayOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief Gameplay ticks per second. */\r\n\tOptionEntryInt<int> tickRate;\r\n\t/** @brief Enable double walk speed when in town. */\r\n\tOptionEntryBoolean runInTown;\r\n\t/** @brief Do not let the mouse leave the application window. */\r\n\tOptionEntryBoolean grabInput;\r\n\t/** @brief Pause the game when focus is lost. */\r\n\tOptionEntryBoolean pauseOnFocusLoss;\r\n\t/** @brief Enable the Theo quest. */\r\n\tOptionEntryBoolean theoQuest;\r\n\t/** @brief Enable the cow quest. */\r\n\tOptionEntryBoolean cowQuest;\r\n\t/** @brief Will players still damage other players in non-PvP mode. */\r\n\tOptionEntryBoolean friendlyFire;\r\n\t/** @brief Enables the full/uncut singleplayer version of quests. */\r\n\tOptionEntryBoolean multiplayerFullQuests;\r\n\t/** @brief Enable the bard hero class. */\r\n\tOptionEntryBoolean testBard;\r\n\t/** @brief Enable the babarian hero class. */\r\n\tOptionEntryBoolean testBarbarian;\r\n\t/** @brief Show the current level progress. */\r\n\tOptionEntryBoolean experienceBar;\r\n\t/** @brief Show item graphics to the left of item descriptions in store menus. */\r\n\tOptionEntryBoolean showItemGraphicsInStores;\r\n\t/** @brief Display current/max health values on health globe. */\r\n\tOptionEntryBoolean showHealthValues;\r\n\t/** @brief Display current/max mana values on mana globe. */\r\n\tOptionEntryBoolean showManaValues;\r\n\t/** @brief Enable the multiplayer party information display */\r\n\tOptionEntryBoolean showMultiplayerPartyInfo;\r\n\t/** @brief Show enemy health at the top of the screen. */\r\n\tOptionEntryBoolean enemyHealthBar;\r\n\t/** @brief Displays item info in a floating box when hovering over an ite. */\r\n\tOptionEntryBoolean floatingInfoBox;\r\n\t/** @brief Automatically pick up gold when walking over it. */\r\n\tOptionEntryBoolean autoGoldPickup;\r\n\t/** @brief Auto-pickup elixirs */\r\n\tOptionEntryBoolean autoElixirPickup;\r\n\t/** @brief Auto-pickup oils */\r\n\tOptionEntryBoolean autoOilPickup;\r\n\t/** @brief Enable or Disable auto-pickup in town */\r\n\tOptionEntryBoolean autoPickupInTown;\r\n\t/** @brief Automatically attempt to equip weapon-type items when picking them up. */\r\n\tOptionEntryBoolean autoEquipWeapons;\r\n\t/** @brief Automatically attempt to equip armor-type items when picking them up. */\r\n\tOptionEntryBoolean autoEquipArmor;\r\n\t/** @brief Automatically attempt to equip helm-type items when picking them up. */\r\n\tOptionEntryBoolean autoEquipHelms;\r\n\t/** @brief Automatically attempt to equip shield-type items when picking them up. */\r\n\tOptionEntryBoolean autoEquipShields;\r\n\t/** @brief Automatically attempt to equip jewelry-type items when picking them up. */\r\n\tOptionEntryBoolean autoEquipJewelry;\r\n\t/** @brief Only enable 2/3 quests in each game session */\r\n\tOptionEntryBoolean randomizeQuests;\r\n\t/** @brief Indicates whether or not monster type (Animal, Demon, Undead) is shown along with other monster information. */\r\n\tOptionEntryBoolean showMonsterType;\r\n\t/** @brief Displays item labels for items on the ground.  */\r\n\tOptionEntryBoolean showItemLabels;\r\n\t/** @brief Refill belt from inventory, or rather, use potions/scrolls from inventory first when belt item is consumed.  */\r\n\tOptionEntryBoolean autoRefillBelt;\r\n\t/** @brief Locally disable clicking on shrines which permanently cripple character. */\r\n\tOptionEntryBoolean disableCripplingShrines;\r\n\t/** @brief Spell hotkeys instantly cast the spell. */\r\n\tOptionEntryBoolean quickCast;\r\n\t/** @brief Number of Healing potions to pick up automatically */\r\n\tOptionEntryInt<int> numHealPotionPickup;\r\n\t/** @brief Number of Full Healing potions to pick up automatically */\r\n\tOptionEntryInt<int> numFullHealPotionPickup;\r\n\t/** @brief Number of Mana potions to pick up automatically */\r\n\tOptionEntryInt<int> numManaPotionPickup;\r\n\t/** @brief Number of Full Mana potions to pick up automatically */\r\n\tOptionEntryInt<int> numFullManaPotionPickup;\r\n\t/** @brief Number of Rejuvenating potions to pick up automatically */\r\n\tOptionEntryInt<int> numRejuPotionPickup;\r\n\t/** @brief Number of Full Rejuvenating potions to pick up automatically */\r\n\tOptionEntryInt<int> numFullRejuPotionPickup;\r\n\r\n\t/**\r\n\t * @brief If loading takes less than this value, skips displaying the loading screen.\r\n\t *\r\n\t * Advanced option, not displayed in the UI.\r\n\t */\r\n\tOptionEntryInt<int> skipLoadingScreenThresholdMs;\r\n};\r\n\r\nstruct ControllerOptions : OptionCategoryBase {\r\n\tControllerOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief SDL Controller mapping, see SDL_GameControllerDB. */\r\n\tchar szMapping[1024];\r\n\t/** @brief Configure gamepad joysticks deadzone */\r\n\tfloat fDeadzone;\r\n#ifdef __vita__\r\n\t/** @brief Enable input via rear touchpad */\r\n\tbool bRearTouch;\r\n#endif\r\n};\r\n\r\nstruct NetworkOptions : OptionCategoryBase {\r\n\tNetworkOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief Optionally bind to a specific network interface. */\r\n\tchar szBindAddress[129];\r\n\t/** @brief Most recently entered ZeroTier Game ID. */\r\n\tchar szPreviousZTGame[129];\r\n\t/** @brief Most recently entered Hostname in join dialog. */\r\n\tchar szPreviousHost[129];\r\n\t/** @brief What network port to use. */\r\n\tOptionEntryInt<uint16_t> port;\r\n};\r\n\r\nstruct ChatOptions : OptionCategoryBase {\r\n\tChatOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\t/** @brief Quick chat messages. */\r\n\tstd::vector<std::string> szHotKeyMsgs[QuickMessages.size()];\r\n};\r\n\r\nstruct LanguageOptions : OptionCategoryBase {\r\n\tLanguageOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\tOptionEntryLanguageCode code;\r\n};\r\n\r\nconstexpr uint32_t KeymapperMouseButtonMask = 1 << 31;\r\nconstexpr uint32_t MouseScrollUpButton = 65536 | KeymapperMouseButtonMask;\r\nconstexpr uint32_t MouseScrollDownButton = 65537 | KeymapperMouseButtonMask;\r\nconstexpr uint32_t MouseScrollLeftButton = 65538 | KeymapperMouseButtonMask;\r\nconstexpr uint32_t MouseScrollRightButton = 65539 | KeymapperMouseButtonMask;\r\n\r\n/** The Keymapper maps keys to actions. */\r\nstruct KeymapperOptions : OptionCategoryBase {\r\n\t/**\r\n\t * Action represents an action that can be triggered using a keyboard\r\n\t * shortcut.\r\n\t */\r\n\tclass Action final : public OptionEntryBase {\r\n\tpublic:\r\n\t\t// OptionEntryBase::key may be referencing Action::dynamicKey.\r\n\t\t// The implicit copy constructor would copy that reference instead of referencing the copy.\r\n\t\tAction(const Action &) = delete;\r\n\r\n\t\tAction(std::string_view key, const char *name, const char *description, uint32_t defaultKey, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index);\r\n\r\n\t\t[[nodiscard]] std::string_view GetName() const override;\r\n\t\t[[nodiscard]] OptionEntryType GetType() const override\r\n\t\t{\r\n\t\t\treturn OptionEntryType::Key;\r\n\t\t}\r\n\r\n\t\tvoid LoadFromIni(std::string_view category) override;\r\n\t\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t\t[[nodiscard]] std::string_view GetValueDescription() const override;\r\n\r\n\t\tbool SetValue(int value);\r\n\r\n\t\t[[nodiscard]] bool isEnabled() const { return !enable || enable(); }\r\n\r\n\t\tstd::function<void()> actionPressed;\r\n\t\tstd::function<void()> actionReleased;\r\n\r\n\tprivate:\r\n\t\tuint32_t defaultKey;\r\n\t\tstd::function<bool()> enable;\r\n\t\tuint32_t boundKey = SDLK_UNKNOWN;\r\n\t\tunsigned dynamicIndex;\r\n\t\tstd::string dynamicKey;\r\n\t\tmutable std::string dynamicName;\r\n\r\n\t\tfriend struct KeymapperOptions;\r\n\t};\r\n\r\n\tKeymapperOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\tvoid AddAction(\r\n\t    std::string_view key, const char *name, const char *description, uint32_t defaultKey,\r\n\t    std::function<void()> actionPressed,\r\n\t    std::function<void()> actionReleased = nullptr,\r\n\t    std::function<bool()> enable = nullptr,\r\n\t    unsigned index = 0);\r\n\tvoid CommitActions();\r\n\r\n\t[[nodiscard]] const Action *findAction(uint32_t key) const;\r\n\r\n\tstd::string_view KeyNameForAction(std::string_view actionName) const;\r\n\tuint32_t KeyForAction(std::string_view actionName) const;\r\n\r\nprivate:\r\n\tstd::forward_list<Action> actions;\r\n\tankerl::unordered_dense::segmented_map<uint32_t, std::reference_wrapper<Action>> keyIDToAction;\r\n\tankerl::unordered_dense::segmented_map<uint32_t, std::string> keyIDToKeyName;\r\n\tankerl::unordered_dense::segmented_map<std::string, uint32_t, StringViewHash, StringViewEquals> keyNameToKeyID;\r\n};\r\n\r\n/** The Padmapper maps gamepad buttons to actions. */\r\nstruct PadmapperOptions : OptionCategoryBase {\r\n\t/**\r\n\t * Action represents an action that can be triggered using a gamepad\r\n\t * button combo.\r\n\t */\r\n\tclass Action final : public OptionEntryBase {\r\n\tpublic:\r\n\t\tAction(std::string_view key, const char *name, const char *description, ControllerButtonCombo defaultInput, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index);\r\n\r\n\t\t// OptionEntryBase::key may be referencing Action::dynamicKey.\r\n\t\t// The implicit copy constructor would copy that reference instead of referencing the copy.\r\n\t\tAction(const Action &) = delete;\r\n\r\n\t\t[[nodiscard]] std::string_view GetName() const override;\r\n\t\t[[nodiscard]] OptionEntryType GetType() const override\r\n\t\t{\r\n\t\t\treturn OptionEntryType::PadButton;\r\n\t\t}\r\n\r\n\t\tvoid LoadFromIni(std::string_view category) override;\r\n\t\tvoid SaveToIni(std::string_view category) const override;\r\n\r\n\t\t[[nodiscard]] std::string_view GetValueDescription() const override;\r\n\t\t[[nodiscard]] std::string_view GetValueDescription(bool useShortName) const;\r\n\r\n\t\tbool SetValue(ControllerButtonCombo value);\r\n\r\n\t\t[[nodiscard]] bool isEnabled() const { return !enable || enable(); }\r\n\r\n\t\tstd::function<void()> actionPressed;\r\n\t\tstd::function<void()> actionReleased;\r\n\t\tControllerButtonCombo boundInput;\r\n\r\n\tprivate:\r\n\t\tControllerButtonCombo defaultInput;\r\n\t\tstd::function<bool()> enable;\r\n\t\tmutable GamepadLayout boundInputDescriptionType = GamepadLayout::Generic;\r\n\t\tmutable std::string boundInputDescription;\r\n\t\tmutable std::string boundInputShortDescription;\r\n\t\tunsigned dynamicIndex;\r\n\t\tstd::string dynamicKey;\r\n\t\tmutable std::string dynamicName;\r\n\r\n\t\tvoid UpdateValueDescription() const;\r\n\t\tstd::string_view Shorten(std::string_view buttonName) const;\r\n\r\n\t\tfriend struct PadmapperOptions;\r\n\t};\r\n\r\n\tPadmapperOptions();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\r\n\tvoid AddAction(\r\n\t    std::string_view key, const char *name, const char *description, ControllerButtonCombo defaultInput,\r\n\t    std::function<void()> actionPressed,\r\n\t    std::function<void()> actionReleased = nullptr,\r\n\t    std::function<bool()> enable = nullptr,\r\n\t    unsigned index = 0);\r\n\tvoid CommitActions();\r\n\tstd::string_view InputNameForAction(std::string_view actionName, bool useShortName = false) const;\r\n\tControllerButtonCombo ButtonComboForAction(std::string_view actionName) const;\r\n\r\n\t[[nodiscard]] const Action *findAction(ControllerButton button, tl::function_ref<bool(ControllerButton)> isModifierPressed) const;\r\n\r\n\tstd::forward_list<Action> actions;\r\n\r\nprivate:\r\n\tstd::array<std::string, enum_size<ControllerButton>::value> buttonToButtonName;\r\n\tankerl::unordered_dense::segmented_map<std::string, ControllerButton, StringViewHash, StringViewEquals> buttonNameToButton;\r\n\tbool committed = false;\r\n};\r\n\r\nstruct ModOptions : OptionCategoryBase {\r\n\tModOptions();\r\n\tstd::vector<std::string_view> GetActiveModList();\r\n\tstd::vector<std::string_view> GetModList();\r\n\tstd::vector<OptionEntryBase *> GetEntries() override;\r\n\tvoid AddModEntry(const std::string &modName);\r\n\tvoid RemoveModEntry(const std::string &modName);\r\n\tvoid SetHellfireEnabled(bool enableHellfire);\r\n\r\nprivate:\r\n\tstruct ModEntry {\r\n\t\t// OptionEntryBase::key references ModEntry::name.\r\n\t\t// The implicit copy constructor would copy that reference instead of referencing the copy.\r\n\t\tModEntry(const ModEntry &) = delete;\r\n\r\n\t\tModEntry(std::string_view name);\r\n\t\tstd::string name;\r\n\t\tOptionEntryBoolean enabled;\r\n\t};\r\n\r\n\tstd::forward_list<ModEntry> &GetModEntries();\r\n\tstd::optional<std::forward_list<ModEntry>> modEntries;\r\n};\r\n\r\nstruct Options {\r\n\tGameModeOptions GameMode;\r\n\tStartUpOptions StartUp;\r\n\tDiabloOptions Diablo;\r\n\tHellfireOptions Hellfire;\r\n\tAudioOptions Audio;\r\n\tGameplayOptions Gameplay;\r\n\tGraphicsOptions Graphics;\r\n\tControllerOptions Controller;\r\n\tNetworkOptions Network;\r\n\tChatOptions Chat;\r\n\tLanguageOptions Language;\r\n\tKeymapperOptions Keymapper;\r\n\tPadmapperOptions Padmapper;\r\n\tModOptions Mods;\r\n\r\n\t[[nodiscard]] std::vector<OptionCategoryBase *> GetCategories()\r\n\t{\r\n\t\treturn {\r\n\t\t\t&Language,\r\n\t\t\t&Mods,\r\n\t\t\t&GameMode,\r\n\t\t\t&StartUp,\r\n\t\t\t&Graphics,\r\n\t\t\t&Audio,\r\n\t\t\t&Diablo,\r\n\t\t\t&Hellfire,\r\n\t\t\t&Gameplay,\r\n\t\t\t&Controller,\r\n\t\t\t&Network,\r\n\t\t\t&Chat,\r\n\t\t\t&Keymapper,\r\n\t\t\t&Padmapper,\r\n\t\t};\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief Get the Options singleton object\r\n */\r\n[[nodiscard]] Options &GetOptions();\r\n\r\nbool HardwareCursorSupported();\r\n\r\n/**\r\n * @brief Save game configurations to ini file\r\n */\r\nvoid SaveOptions();\r\n\r\n/**\r\n * @brief Load game configurations from ini file\r\n */\r\nvoid LoadOptions();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/pack.cpp",
    "content": "/**\r\n * @file pack.cpp\r\n *\r\n * Implementation of functions for minifying player data structure.\r\n */\r\n#include \"pack.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/random.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"items/validation.h\"\r\n#include \"loadsave.h\"\r\n#include \"plrmsg.h\"\r\n#include \"stores.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#define ValidateField(logValue, condition)                         \\\r\n\tdo {                                                           \\\r\n\t\tif (!(condition)) {                                        \\\r\n\t\t\tLogFailedJoinAttempt(#condition, #logValue, logValue); \\\r\n\t\t\tEventFailedJoinAttempt(player._pName);                 \\\r\n\t\t\treturn false;                                          \\\r\n\t\t}                                                          \\\r\n\t} while (0)\r\n\r\n#define ValidateFields(logValue1, logValue2, condition)                                     \\\r\n\tdo {                                                                                    \\\r\n\t\tif (!(condition)) {                                                                 \\\r\n\t\t\tLogFailedJoinAttempt(#condition, #logValue1, logValue1, #logValue2, logValue2); \\\r\n\t\t\tEventFailedJoinAttempt(player._pName);                                          \\\r\n\t\t\treturn false;                                                                   \\\r\n\t\t}                                                                                   \\\r\n\t} while (0)\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid EventFailedJoinAttempt(const char *playerName)\r\n{\r\n\tconst std::string message = fmt::format(\"Player '{}' sent invalid player data during attempt to join the game.\", playerName);\r\n\tEventPlrMsg(message);\r\n}\r\n\r\ntemplate <typename T>\r\nvoid LogFailedJoinAttempt(const char *condition, const char *name, T value)\r\n{\r\n\tLogDebug(\"Remote player validation failed: ValidateField({}: {}, {})\", name, value, condition);\r\n}\r\n\r\ntemplate <typename T1, typename T2>\r\nvoid LogFailedJoinAttempt(const char *condition, const char *name1, T1 value1, const char *name2, T2 value2)\r\n{\r\n\tLogDebug(\"Remote player validation failed: ValidateFields({}: {}, {}: {}, {})\", name1, value1, name2, value2, condition);\r\n}\r\n\r\nvoid VerifyGoldSeeds(Player &player)\r\n{\r\n\tfor (int i = 0; i < player._pNumInv; i++) {\r\n\t\tif (player.InvList[i].IDidx != IDI_GOLD)\r\n\t\t\tcontinue;\r\n\t\tfor (int j = 0; j < player._pNumInv; j++) {\r\n\t\t\tif (i == j)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (player.InvList[j].IDidx != IDI_GOLD)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (player.InvList[i]._iSeed != player.InvList[j]._iSeed)\r\n\t\t\t\tcontinue;\r\n\t\t\tplayer.InvList[i]._iSeed = AdvanceRndSeed();\r\n\t\t\tj = -1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nbool RecreateHellfireSpellBook(const Player &player, const TItem &packedItem, Item *item)\r\n{\r\n\tItem spellBook {};\r\n\tRecreateItem(player, packedItem, spellBook);\r\n\r\n\t// Hellfire uses the spell book level when generating items via CreateSpellBook()\r\n\tint spellBookLevel = GetSpellBookLevel(spellBook._iSpell);\r\n\r\n\t// CreateSpellBook() adds 1 to the spell level for ilvl\r\n\tspellBookLevel++;\r\n\r\n\tif (spellBookLevel >= 1 && (spellBook._iCreateInfo & CF_LEVEL) == spellBookLevel * 2) {\r\n\t\t// The ilvl matches the result for a spell book drop, so we confirm the item is legitimate\r\n\t\tif (item != nullptr)\r\n\t\t\t*item = spellBook;\r\n\t\treturn true;\r\n\t}\r\n\r\n\tValidateFields(spellBook._iCreateInfo, spellBook.dwBuff, IsDungeonItemValid(spellBook._iCreateInfo, spellBook.dwBuff));\r\n\tif (item != nullptr)\r\n\t\t*item = spellBook;\r\n\treturn true;\r\n}\r\n\r\nvoid PackItem(ItemPack &packedItem, const Item &item, bool isHellfire)\r\n{\r\n\tpackedItem = {};\r\n\t// Arena potions don't exist in vanilla so don't save them to stay backward compatible\r\n\tif (item.isEmpty() || item._iMiscId == IMISC_ARENAPOT) {\r\n\t\tpackedItem.idx = 0xFFFF;\r\n\t} else {\r\n\t\tauto idx = item.IDidx;\r\n\t\tif (!isHellfire) {\r\n\t\t\tidx = RemapItemIdxToDiablo(idx);\r\n\t\t}\r\n\t\tif (gbIsSpawn) {\r\n\t\t\tidx = RemapItemIdxToSpawn(idx);\r\n\t\t}\r\n\t\tpackedItem.idx = Swap16LE(idx);\r\n\t\tif (item.IDidx == IDI_EAR) {\r\n\t\t\tpackedItem.iCreateInfo = Swap16LE(item._iIName[1] | (item._iIName[0] << 8));\r\n\t\t\tpackedItem.iSeed = Swap32LE(LoadBE32(&item._iIName[2]));\r\n\t\t\tpackedItem.bId = item._iIName[6];\r\n\t\t\tpackedItem.bDur = item._iIName[7];\r\n\t\t\tpackedItem.bMDur = item._iIName[8];\r\n\t\t\tpackedItem.bCh = item._iIName[9];\r\n\t\t\tpackedItem.bMCh = item._iIName[10];\r\n\t\t\tpackedItem.wValue = Swap16LE(item._ivalue | (item._iIName[11] << 8) | ((item._iCurs - ICURS_EAR_SORCERER) << 6));\r\n\t\t\tpackedItem.dwBuff = Swap32LE(LoadBE32(&item._iIName[12]));\r\n\t\t} else {\r\n\t\t\tpackedItem.iSeed = Swap32LE(item._iSeed);\r\n\t\t\tpackedItem.iCreateInfo = Swap16LE(item._iCreateInfo);\r\n\t\t\tpackedItem.bId = (item._iMagical << 1) | (item._iIdentified ? 1 : 0);\r\n\t\t\tif (item._iMaxDur > 255)\r\n\t\t\t\tpackedItem.bMDur = 254;\r\n\t\t\telse\r\n\t\t\t\tpackedItem.bMDur = item._iMaxDur;\r\n\t\t\tpackedItem.bDur = std::min<int32_t>(item._iDurability, packedItem.bMDur);\r\n\r\n\t\t\tpackedItem.bCh = item._iCharges;\r\n\t\t\tpackedItem.bMCh = item._iMaxCharges;\r\n\t\t\tif (item.IDidx == IDI_GOLD)\r\n\t\t\t\tpackedItem.wValue = Swap16LE(item._ivalue);\r\n\t\t\tpackedItem.dwBuff = item.dwBuff;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PackPlayer(PlayerPack &packed, const Player &player)\r\n{\r\n\tmemset(&packed, 0, sizeof(packed));\r\n\tpacked.destAction = player.destAction;\r\n\tpacked.destParam1 = player.destParam1;\r\n\tpacked.destParam2 = player.destParam2;\r\n\tpacked.plrlevel = player.plrlevel;\r\n\tpacked.px = player.position.tile.x;\r\n\tpacked.py = player.position.tile.y;\r\n\tif (gbVanilla) {\r\n\t\tpacked.targx = player.position.tile.x;\r\n\t\tpacked.targy = player.position.tile.y;\r\n\t}\r\n\tCopyUtf8(packed.pName, player._pName, sizeof(packed.pName));\r\n\tpacked.pClass = static_cast<uint8_t>(player._pClass);\r\n\tpacked.pBaseStr = player._pBaseStr;\r\n\tpacked.pBaseMag = player._pBaseMag;\r\n\tpacked.pBaseDex = player._pBaseDex;\r\n\tpacked.pBaseVit = player._pBaseVit;\r\n\tpacked.pLevel = player.getCharacterLevel();\r\n\tpacked.pStatPts = player._pStatPts;\r\n\tpacked.pExperience = Swap32LE(player._pExperience);\r\n\tpacked.pGold = Swap32LE(player._pGold);\r\n\tpacked.pHPBase = Swap32LE(player._pHPBase);\r\n\tpacked.pMaxHPBase = Swap32LE(player._pMaxHPBase);\r\n\tpacked.pManaBase = Swap32LE(player._pManaBase);\r\n\tpacked.pMaxManaBase = Swap32LE(player._pMaxManaBase);\r\n\tpacked.pMemSpells = Swap64LE(player._pMemSpells);\r\n\r\n\tfor (int i = 0; i < 37; i++) // Should be MAX_SPELLS but set to 37 to make save games compatible\r\n\t\tpacked.pSplLvl[i] = player._pSplLvl[i];\r\n\tfor (int i = 37; i < 47; i++)\r\n\t\tpacked.pSplLvl2[i - 37] = player._pSplLvl[i];\r\n\r\n\tfor (int i = 0; i < NUM_INVLOC; i++)\r\n\t\tPackItem(packed.InvBody[i], player.InvBody[i], gbIsHellfire);\r\n\r\n\tpacked._pNumInv = player._pNumInv;\r\n\tfor (int i = 0; i < packed._pNumInv; i++)\r\n\t\tPackItem(packed.InvList[i], player.InvList[i], gbIsHellfire);\r\n\r\n\tfor (int i = 0; i < InventoryGridCells; i++)\r\n\t\tpacked.InvGrid[i] = player.InvGrid[i];\r\n\r\n\tfor (int i = 0; i < MaxBeltItems; i++)\r\n\t\tPackItem(packed.SpdList[i], player.SpdList[i], gbIsHellfire);\r\n\r\n\tpacked.wReflections = Swap16LE(player.wReflections);\r\n\tpacked.pDamAcFlags = Swap32LE(static_cast<uint32_t>(player.pDamAcFlags));\r\n\tpacked.pDiabloKillLevel = Swap32LE(player.pDiabloKillLevel);\r\n\tpacked.bIsHellfire = gbIsHellfire ? 1 : 0;\r\n}\r\n\r\nvoid PackNetItem(const Item &item, ItemNetPack &packedItem)\r\n{\r\n\tif (item.isEmpty()) {\r\n\t\tpackedItem.def.wIndx = static_cast<_item_indexes>(0xFFFF);\r\n\t\treturn;\r\n\t}\r\n\tpackedItem.def.wIndx = static_cast<_item_indexes>(Swap16LE(item.IDidx));\r\n\tpackedItem.def.wCI = Swap16LE(item._iCreateInfo);\r\n\tpackedItem.def.dwSeed = Swap32LE(item._iSeed);\r\n\tif (item.IDidx != IDI_EAR)\r\n\t\tPrepareItemForNetwork(item, packedItem.item);\r\n\telse\r\n\t\tPrepareEarForNetwork(item, packedItem.ear);\r\n}\r\n\r\nvoid PackNetPlayer(PlayerNetPack &packed, const Player &player)\r\n{\r\n\tpacked.plrlevel = player.plrlevel;\r\n\tpacked.px = player.position.tile.x;\r\n\tpacked.py = player.position.tile.y;\r\n\tpacked.pdir = static_cast<uint8_t>(player._pdir);\r\n\tCopyUtf8(packed.pName, player._pName, sizeof(packed.pName));\r\n\tpacked.pClass = static_cast<uint8_t>(player._pClass);\r\n\tpacked.pBaseStr = player._pBaseStr;\r\n\tpacked.pBaseMag = player._pBaseMag;\r\n\tpacked.pBaseDex = player._pBaseDex;\r\n\tpacked.pBaseVit = player._pBaseVit;\r\n\tpacked.pLevel = player.getCharacterLevel();\r\n\tpacked.pStatPts = player._pStatPts;\r\n\tpacked.pExperience = Swap32LE(player._pExperience);\r\n\tpacked.pHPBase = Swap32LE(player._pHPBase);\r\n\tpacked.pMaxHPBase = Swap32LE(player._pMaxHPBase);\r\n\tpacked.pManaBase = Swap32LE(player._pManaBase);\r\n\tpacked.pMaxManaBase = Swap32LE(player._pMaxManaBase);\r\n\tpacked.pMemSpells = Swap64LE(player._pMemSpells);\r\n\r\n\tfor (int i = 0; i < MAX_SPELLS; i++)\r\n\t\tpacked.pSplLvl[i] = player._pSplLvl[i];\r\n\r\n\tfor (int i = 0; i < NUM_INVLOC; i++)\r\n\t\tPackNetItem(player.InvBody[i], packed.InvBody[i]);\r\n\r\n\tpacked._pNumInv = player._pNumInv;\r\n\tfor (int i = 0; i < packed._pNumInv; i++)\r\n\t\tPackNetItem(player.InvList[i], packed.InvList[i]);\r\n\r\n\tfor (int i = 0; i < InventoryGridCells; i++)\r\n\t\tpacked.InvGrid[i] = player.InvGrid[i];\r\n\r\n\tfor (int i = 0; i < MaxBeltItems; i++)\r\n\t\tPackNetItem(player.SpdList[i], packed.SpdList[i]);\r\n\r\n\tpacked.wReflections = Swap16LE(player.wReflections);\r\n\tpacked.pDiabloKillLevel = player.pDiabloKillLevel;\r\n\tpacked.pManaShield = player.pManaShield;\r\n\tpacked.friendlyMode = player.friendlyMode ? 1 : 0;\r\n\tpacked.isOnSetLevel = player.plrIsOnSetLevel;\r\n\r\n\tpacked.pStrength = Swap32LE(player._pStrength);\r\n\tpacked.pMagic = Swap32LE(player._pMagic);\r\n\tpacked.pDexterity = Swap32LE(player._pDexterity);\r\n\tpacked.pVitality = Swap32LE(player._pVitality);\r\n\tpacked.pHitPoints = Swap32LE(player._pHitPoints);\r\n\tpacked.pMaxHP = Swap32LE(player._pMaxHP);\r\n\tpacked.pMana = Swap32LE(player._pMana);\r\n\tpacked.pMaxMana = Swap32LE(player._pMaxMana);\r\n\tpacked.pDamageMod = Swap32LE(player._pDamageMod);\r\n\t// we pack base to block as a basic check that remote players are using the same playerdat values as we are\r\n\tpacked.pBaseToBlk = Swap32LE(player.getBaseToBlock());\r\n\tpacked.pIMinDam = Swap32LE(player._pIMinDam);\r\n\tpacked.pIMaxDam = Swap32LE(player._pIMaxDam);\r\n\tpacked.pIAC = Swap32LE(player._pIAC);\r\n\tpacked.pIBonusDam = Swap32LE(player._pIBonusDam);\r\n\tpacked.pIBonusToHit = Swap32LE(player._pIBonusToHit);\r\n\tpacked.pIBonusAC = Swap32LE(player._pIBonusAC);\r\n\tpacked.pIBonusDamMod = Swap32LE(player._pIBonusDamMod);\r\n\tpacked.pIGetHit = Swap32LE(player._pIGetHit);\r\n\tpacked.pIEnAc = Swap32LE(player._pIEnAc);\r\n\tpacked.pIFMinDam = Swap32LE(player._pIFMinDam);\r\n\tpacked.pIFMaxDam = Swap32LE(player._pIFMaxDam);\r\n\tpacked.pILMinDam = Swap32LE(player._pILMinDam);\r\n\tpacked.pILMaxDam = Swap32LE(player._pILMaxDam);\r\n}\r\n\r\nvoid UnPackItem(const ItemPack &packedItem, const Player &player, Item &item, bool isHellfire)\r\n{\r\n\tif (packedItem.idx == 0xFFFF) {\r\n\t\titem.clear();\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto idx = static_cast<_item_indexes>(Swap16LE(packedItem.idx));\r\n\r\n\tif (gbIsSpawn) {\r\n\t\tidx = RemapItemIdxFromSpawn(idx);\r\n\t}\r\n\tif (!isHellfire) {\r\n\t\tidx = RemapItemIdxFromDiablo(idx);\r\n\t}\r\n\r\n\tif (!IsItemAvailable(idx)) {\r\n\t\titem.clear();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (idx == IDI_EAR) {\r\n\t\tconst uint16_t ic = Swap16LE(packedItem.iCreateInfo);\r\n\t\tconst uint32_t iseed = Swap32LE(packedItem.iSeed);\r\n\t\tconst uint16_t ivalue = Swap16LE(packedItem.wValue);\r\n\t\tconst int32_t ibuff = Swap32LE(packedItem.dwBuff);\r\n\r\n\t\tchar heroName[17];\r\n\t\theroName[0] = static_cast<char>((ic >> 8) & 0x7F);\r\n\t\theroName[1] = static_cast<char>(ic & 0x7F);\r\n\t\theroName[2] = static_cast<char>((iseed >> 24) & 0x7F);\r\n\t\theroName[3] = static_cast<char>((iseed >> 16) & 0x7F);\r\n\t\theroName[4] = static_cast<char>((iseed >> 8) & 0x7F);\r\n\t\theroName[5] = static_cast<char>(iseed & 0x7F);\r\n\t\theroName[6] = static_cast<char>(packedItem.bId & 0x7F);\r\n\t\theroName[7] = static_cast<char>(packedItem.bDur & 0x7F);\r\n\t\theroName[8] = static_cast<char>(packedItem.bMDur & 0x7F);\r\n\t\theroName[9] = static_cast<char>(packedItem.bCh & 0x7F);\r\n\t\theroName[10] = static_cast<char>(packedItem.bMCh & 0x7F);\r\n\t\theroName[11] = static_cast<char>((ivalue >> 8) & 0x7F);\r\n\t\theroName[12] = static_cast<char>((ibuff >> 24) & 0x7F);\r\n\t\theroName[13] = static_cast<char>((ibuff >> 16) & 0x7F);\r\n\t\theroName[14] = static_cast<char>((ibuff >> 8) & 0x7F);\r\n\t\theroName[15] = static_cast<char>(ibuff & 0x7F);\r\n\t\theroName[16] = '\\0';\r\n\r\n\t\tRecreateEar(item, ic, iseed, ivalue & 0xFF, heroName);\r\n\t} else {\r\n\t\titem = {};\r\n\t\t// Item generation logic will assign CF_HELLFIRE based on isHellfire\r\n\t\t// so if we carry it over from packedItem, it may be incorrect\r\n\t\tconst uint32_t dwBuff = Swap32LE(packedItem.dwBuff) | (isHellfire ? CF_HELLFIRE : 0);\r\n\t\tRecreateItem(player, item, idx, Swap16LE(packedItem.iCreateInfo), Swap32LE(packedItem.iSeed), Swap16LE(packedItem.wValue), dwBuff);\r\n\t\titem._iIdentified = (packedItem.bId & 1) != 0;\r\n\t\titem._iMaxDur = packedItem.bMDur;\r\n\t\titem._iDurability = ClampDurability(item, packedItem.bDur);\r\n\t\titem._iMaxCharges = std::clamp<int>(packedItem.bMCh, 0, item._iMaxCharges);\r\n\t\titem._iCharges = std::clamp<int>(packedItem.bCh, 0, item._iMaxCharges);\r\n\t}\r\n}\r\n\r\nvoid UnPackPlayer(const PlayerPack &packed, Player &player)\r\n{\r\n\tconst Point position { packed.px, packed.py };\r\n\r\n\tplayer = {};\r\n\tplayer.setCharacterLevel(packed.pLevel);\r\n\tplayer._pMaxHPBase = Swap32LE(packed.pMaxHPBase);\r\n\tplayer._pHPBase = Swap32LE(packed.pHPBase);\r\n\tplayer._pHPBase = std::clamp<int32_t>(player._pHPBase, 0, player._pMaxHPBase);\r\n\tplayer._pMaxHP = player._pMaxHPBase;\r\n\tplayer._pHitPoints = player._pHPBase;\r\n\tplayer.position.tile = position;\r\n\tplayer.position.future = position;\r\n\tplayer.setLevel(std::clamp<int8_t>(packed.plrlevel, 0, NUMLEVELS));\r\n\r\n\tplayer._pClass = static_cast<HeroClass>(std::clamp<uint8_t>(packed.pClass, 0, static_cast<uint8_t>(GetNumPlayerClasses() - 1)));\r\n\r\n\tClrPlrPath(player);\r\n\tplayer.destAction = ACTION_NONE;\r\n\r\n\tCopyUtf8(player._pName, packed.pName, sizeof(player._pName));\r\n\r\n\tInitPlayer(player, true);\r\n\r\n\tplayer._pBaseStr = std::min<uint8_t>(packed.pBaseStr, player.GetMaximumAttributeValue(CharacterAttribute::Strength));\r\n\tplayer._pStrength = player._pBaseStr;\r\n\tplayer._pBaseMag = std::min<uint8_t>(packed.pBaseMag, player.GetMaximumAttributeValue(CharacterAttribute::Magic));\r\n\tplayer._pMagic = player._pBaseMag;\r\n\tplayer._pBaseDex = std::min<uint8_t>(packed.pBaseDex, player.GetMaximumAttributeValue(CharacterAttribute::Dexterity));\r\n\tplayer._pDexterity = player._pBaseDex;\r\n\tplayer._pBaseVit = std::min<uint8_t>(packed.pBaseVit, player.GetMaximumAttributeValue(CharacterAttribute::Vitality));\r\n\tplayer._pVitality = player._pBaseVit;\r\n\tplayer._pStatPts = packed.pStatPts;\r\n\r\n\tplayer._pExperience = Swap32LE(packed.pExperience);\r\n\tplayer._pGold = Swap32LE(packed.pGold);\r\n\tif ((int)(player._pHPBase & 0xFFFFFFC0) < 64)\r\n\t\tplayer._pHPBase = 64;\r\n\r\n\tplayer._pMaxManaBase = Swap32LE(packed.pMaxManaBase);\r\n\tplayer._pManaBase = Swap32LE(packed.pManaBase);\r\n\tplayer._pManaBase = std::min<int32_t>(player._pManaBase, player._pMaxManaBase);\r\n\tplayer._pMemSpells = Swap64LE(packed.pMemSpells);\r\n\r\n\t// Only read spell levels for learnable spells (Diablo)\r\n\tfor (int i = 0; i < 37; i++) { // Should be MAX_SPELLS but set to 36 to make save games compatible\r\n\t\tauto spl = static_cast<SpellID>(i);\r\n\t\tif (GetSpellBookLevel(spl) != -1)\r\n\t\t\tplayer._pSplLvl[i] = packed.pSplLvl[i];\r\n\t\telse\r\n\t\t\tplayer._pSplLvl[i] = 0;\r\n\t}\r\n\t// Only read spell levels for learnable spells (Hellfire)\r\n\tfor (int i = 37; i < 47; i++) {\r\n\t\tauto spl = static_cast<SpellID>(i);\r\n\t\tif (GetSpellBookLevel(spl) != -1)\r\n\t\t\tplayer._pSplLvl[i] = packed.pSplLvl2[i - 37];\r\n\t\telse\r\n\t\t\tplayer._pSplLvl[i] = 0;\r\n\t}\r\n\t// These spells are unavailable in Diablo as learnable spells\r\n\tif (!gbIsHellfire) {\r\n\t\tplayer._pSplLvl[static_cast<uint8_t>(SpellID::Apocalypse)] = 0;\r\n\t\tplayer._pSplLvl[static_cast<uint8_t>(SpellID::Nova)] = 0;\r\n\t}\r\n\r\n\tconst bool isHellfire = packed.bIsHellfire != 0;\r\n\r\n\tfor (int i = 0; i < NUM_INVLOC; i++)\r\n\t\tUnPackItem(packed.InvBody[i], player, player.InvBody[i], isHellfire);\r\n\r\n\tplayer._pNumInv = packed._pNumInv;\r\n\tfor (int i = 0; i < player._pNumInv; i++)\r\n\t\tUnPackItem(packed.InvList[i], player, player.InvList[i], isHellfire);\r\n\r\n\tfor (int i = 0; i < InventoryGridCells; i++)\r\n\t\tplayer.InvGrid[i] = packed.InvGrid[i];\r\n\r\n\tVerifyGoldSeeds(player);\r\n\r\n\tfor (int i = 0; i < MaxBeltItems; i++)\r\n\t\tUnPackItem(packed.SpdList[i], player, player.SpdList[i], isHellfire);\r\n\r\n\tCalcPlrInv(player, false);\r\n\tplayer.wReflections = Swap16LE(packed.wReflections);\r\n\tplayer.pDiabloKillLevel = Swap32LE(packed.pDiabloKillLevel);\r\n}\r\n\r\nbool UnPackNetItem(const Player &player, const ItemNetPack &packedItem, Item &item)\r\n{\r\n\titem = {};\r\n\tconst _item_indexes idx = static_cast<_item_indexes>(Swap16LE(packedItem.def.wIndx));\r\n\tif (idx < 0 || idx >= static_cast<_item_indexes>(AllItemsList.size()))\r\n\t\treturn true;\r\n\tif (idx == IDI_EAR) {\r\n\t\tRecreateEar(item, Swap16LE(packedItem.ear.wCI), Swap32LE(packedItem.ear.dwSeed), packedItem.ear.bCursval, packedItem.ear.heroname);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconst uint16_t creationFlags = Swap16LE(packedItem.item.wCI);\r\n\tconst uint32_t dwBuff = Swap16LE(packedItem.item.dwBuff);\r\n\tif (idx != IDI_GOLD)\r\n\t\tValidateField(creationFlags, IsCreationFlagComboValid(creationFlags));\r\n\tif ((creationFlags & CF_TOWN) != 0)\r\n\t\tValidateField(creationFlags, IsTownItemValid(creationFlags, player));\r\n\telse if ((creationFlags & CF_USEFUL) == CF_UPER15)\r\n\t\tValidateFields(creationFlags, dwBuff, IsUniqueMonsterItemValid(creationFlags, dwBuff));\r\n\telse if ((dwBuff & CF_HELLFIRE) != 0 && AllItemsList[idx].iMiscId == IMISC_BOOK)\r\n\t\treturn RecreateHellfireSpellBook(player, packedItem.item, &item);\r\n\telse\r\n\t\tValidateFields(creationFlags, dwBuff, IsDungeonItemValid(creationFlags, dwBuff));\r\n\r\n\tRecreateItem(player, packedItem.item, item);\r\n\treturn true;\r\n}\r\n\r\nbool UnPackNetPlayer(const PlayerNetPack &packed, Player &player)\r\n{\r\n\tCopyUtf8(player._pName, packed.pName, sizeof(player._pName));\r\n\r\n\tValidateField(packed.pClass, packed.pClass < GetNumPlayerClasses());\r\n\tplayer._pClass = static_cast<HeroClass>(packed.pClass);\r\n\r\n\tconst Point position { packed.px, packed.py };\r\n\tValidateFields(position.x, position.y, InDungeonBounds(position));\r\n\tValidateField(packed.plrlevel, packed.plrlevel < NUMLEVELS);\r\n\tValidateField(packed.pLevel, packed.pLevel >= 1 && packed.pLevel <= player.getMaxCharacterLevel());\r\n\r\n\tconst int32_t baseHpMax = Swap32LE(packed.pMaxHPBase);\r\n\tconst int32_t baseHp = Swap32LE(packed.pHPBase);\r\n\tconst int32_t hpMax = Swap32LE(packed.pMaxHP);\r\n\tValidateFields(baseHp, baseHpMax, baseHp >= (baseHpMax - hpMax) && baseHp <= baseHpMax);\r\n\r\n\tconst int32_t baseManaMax = Swap32LE(packed.pMaxManaBase);\r\n\tconst int32_t baseMana = Swap32LE(packed.pManaBase);\r\n\tValidateFields(baseMana, baseManaMax, baseMana <= baseManaMax);\r\n\r\n\tValidateFields(packed.pClass, packed.pBaseStr, packed.pBaseStr <= player.GetMaximumAttributeValue(CharacterAttribute::Strength));\r\n\tValidateFields(packed.pClass, packed.pBaseMag, packed.pBaseMag <= player.GetMaximumAttributeValue(CharacterAttribute::Magic));\r\n\tValidateFields(packed.pClass, packed.pBaseDex, packed.pBaseDex <= player.GetMaximumAttributeValue(CharacterAttribute::Dexterity));\r\n\tValidateFields(packed.pClass, packed.pBaseVit, packed.pBaseVit <= player.GetMaximumAttributeValue(CharacterAttribute::Vitality));\r\n\r\n\tValidateField(packed._pNumInv, packed._pNumInv <= InventoryGridCells);\r\n\r\n\tValidateField(packed.pdir, packed.pdir <= static_cast<uint8_t>(Direction::SouthEast));\r\n\tplayer.setCharacterLevel(packed.pLevel);\r\n\tplayer.position.tile = position;\r\n\tplayer.position.future = position;\r\n\tplayer._pdir = static_cast<Direction>(packed.pdir);\r\n\tplayer.plrlevel = packed.plrlevel;\r\n\tplayer.plrIsOnSetLevel = packed.isOnSetLevel != 0;\r\n\tplayer._pMaxHPBase = baseHpMax;\r\n\tplayer._pHPBase = baseHp;\r\n\tplayer._pMaxHP = baseHpMax;\r\n\tplayer._pHitPoints = baseHp;\r\n\r\n\tClrPlrPath(player);\r\n\tplayer.destAction = ACTION_NONE;\r\n\r\n\tInitPlayer(player, true);\r\n\r\n\tplayer._pBaseStr = packed.pBaseStr;\r\n\tplayer._pStrength = player._pBaseStr;\r\n\tplayer._pBaseMag = packed.pBaseMag;\r\n\tplayer._pMagic = player._pBaseMag;\r\n\tplayer._pBaseDex = packed.pBaseDex;\r\n\tplayer._pDexterity = player._pBaseDex;\r\n\tplayer._pBaseVit = packed.pBaseVit;\r\n\tplayer._pVitality = player._pBaseVit;\r\n\tplayer._pStatPts = packed.pStatPts;\r\n\r\n\tplayer._pExperience = Swap32LE(packed.pExperience);\r\n\tplayer._pMaxManaBase = baseManaMax;\r\n\tplayer._pManaBase = baseMana;\r\n\tplayer._pMemSpells = Swap64LE(packed.pMemSpells);\r\n\tplayer.wReflections = Swap16LE(packed.wReflections);\r\n\tplayer.pDiabloKillLevel = packed.pDiabloKillLevel;\r\n\tplayer.pManaShield = packed.pManaShield != 0;\r\n\tplayer.friendlyMode = packed.friendlyMode != 0;\r\n\r\n\tfor (int i = 0; i < MAX_SPELLS; i++)\r\n\t\tplayer._pSplLvl[i] = packed.pSplLvl[i];\r\n\r\n\tfor (int i = 0; i < NUM_INVLOC; i++) {\r\n\t\tif (!UnPackNetItem(player, packed.InvBody[i], player.InvBody[i]))\r\n\t\t\treturn false;\r\n\t\tif (player.InvBody[i].isEmpty())\r\n\t\t\tcontinue;\r\n\t\tauto loc = static_cast<int8_t>(player.GetItemLocation(player.InvBody[i]));\r\n\t\tswitch (i) {\r\n\t\tcase INVLOC_HEAD:\r\n\t\t\tValidateField(loc, loc == ILOC_HELM);\r\n\t\t\tbreak;\r\n\t\tcase INVLOC_RING_LEFT:\r\n\t\tcase INVLOC_RING_RIGHT:\r\n\t\t\tValidateField(loc, loc == ILOC_RING);\r\n\t\t\tbreak;\r\n\t\tcase INVLOC_AMULET:\r\n\t\t\tValidateField(loc, loc == ILOC_AMULET);\r\n\t\t\tbreak;\r\n\t\tcase INVLOC_HAND_LEFT:\r\n\t\tcase INVLOC_HAND_RIGHT:\r\n\t\t\tValidateField(loc, IsAnyOf(loc, ILOC_ONEHAND, ILOC_TWOHAND));\r\n\t\t\tbreak;\r\n\t\tcase INVLOC_CHEST:\r\n\t\t\tValidateField(loc, loc == ILOC_ARMOR);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tplayer._pNumInv = packed._pNumInv;\r\n\tfor (int i = 0; i < player._pNumInv; i++) {\r\n\t\tif (!UnPackNetItem(player, packed.InvList[i], player.InvList[i]))\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tfor (int i = 0; i < InventoryGridCells; i++)\r\n\t\tplayer.InvGrid[i] = packed.InvGrid[i];\r\n\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tItem &item = player.SpdList[i];\r\n\t\tif (!UnPackNetItem(player, packed.SpdList[i], item))\r\n\t\t\treturn false;\r\n\t\tif (item.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tconst Size beltItemSize = GetInventorySize(item);\r\n\t\tconst int8_t beltItemType = static_cast<int8_t>(item._itype);\r\n\t\tconst bool beltItemUsable = item.isUsable();\r\n\t\tValidateFields(beltItemSize.width, beltItemSize.height, (beltItemSize == Size { 1, 1 }));\r\n\t\tValidateField(beltItemType, item._itype != ItemType::Gold);\r\n\t\tValidateField(beltItemUsable, beltItemUsable);\r\n\t}\r\n\r\n\tCalcPlrInv(player, false);\r\n\tplayer._pGold = CalculateGold(player);\r\n\r\n\tValidateFields(player._pStrength, SwapSigned32LE(packed.pStrength), player._pStrength == SwapSigned32LE(packed.pStrength));\r\n\tValidateFields(player._pMagic, SwapSigned32LE(packed.pMagic), player._pMagic == SwapSigned32LE(packed.pMagic));\r\n\tValidateFields(player._pDexterity, SwapSigned32LE(packed.pDexterity), player._pDexterity == SwapSigned32LE(packed.pDexterity));\r\n\tValidateFields(player._pVitality, SwapSigned32LE(packed.pVitality), player._pVitality == SwapSigned32LE(packed.pVitality));\r\n\tValidateFields(player._pHitPoints, SwapSigned32LE(packed.pHitPoints), player._pHitPoints == SwapSigned32LE(packed.pHitPoints));\r\n\tValidateFields(player._pMaxHP, SwapSigned32LE(packed.pMaxHP), player._pMaxHP == SwapSigned32LE(packed.pMaxHP));\r\n\tValidateFields(player._pMana, SwapSigned32LE(packed.pMana), player._pMana == SwapSigned32LE(packed.pMana));\r\n\tValidateFields(player._pMaxMana, SwapSigned32LE(packed.pMaxMana), player._pMaxMana == SwapSigned32LE(packed.pMaxMana));\r\n\tValidateFields(player._pDamageMod, SwapSigned32LE(packed.pDamageMod), player._pDamageMod == SwapSigned32LE(packed.pDamageMod));\r\n\tValidateFields(player.getBaseToBlock(), SwapSigned32LE(packed.pBaseToBlk), player.getBaseToBlock() == SwapSigned32LE(packed.pBaseToBlk));\r\n\tValidateFields(player._pIMinDam, SwapSigned32LE(packed.pIMinDam), player._pIMinDam == SwapSigned32LE(packed.pIMinDam));\r\n\tValidateFields(player._pIMaxDam, SwapSigned32LE(packed.pIMaxDam), player._pIMaxDam == SwapSigned32LE(packed.pIMaxDam));\r\n\tValidateFields(player._pIAC, SwapSigned32LE(packed.pIAC), player._pIAC == SwapSigned32LE(packed.pIAC));\r\n\tValidateFields(player._pIBonusDam, SwapSigned32LE(packed.pIBonusDam), player._pIBonusDam == SwapSigned32LE(packed.pIBonusDam));\r\n\tValidateFields(player._pIBonusToHit, SwapSigned32LE(packed.pIBonusToHit), player._pIBonusToHit == SwapSigned32LE(packed.pIBonusToHit));\r\n\tValidateFields(player._pIBonusAC, SwapSigned32LE(packed.pIBonusAC), player._pIBonusAC == SwapSigned32LE(packed.pIBonusAC));\r\n\tValidateFields(player._pIBonusDamMod, SwapSigned32LE(packed.pIBonusDamMod), player._pIBonusDamMod == SwapSigned32LE(packed.pIBonusDamMod));\r\n\tValidateFields(player._pIGetHit, SwapSigned32LE(packed.pIGetHit), player._pIGetHit == SwapSigned32LE(packed.pIGetHit));\r\n\tValidateFields(player._pIEnAc, SwapSigned32LE(packed.pIEnAc), player._pIEnAc == SwapSigned32LE(packed.pIEnAc));\r\n\tValidateFields(player._pIFMinDam, SwapSigned32LE(packed.pIFMinDam), player._pIFMinDam == SwapSigned32LE(packed.pIFMinDam));\r\n\tValidateFields(player._pIFMaxDam, SwapSigned32LE(packed.pIFMaxDam), player._pIFMaxDam == SwapSigned32LE(packed.pIFMaxDam));\r\n\tValidateFields(player._pILMinDam, SwapSigned32LE(packed.pILMinDam), player._pILMinDam == SwapSigned32LE(packed.pILMinDam));\r\n\tValidateFields(player._pILMaxDam, SwapSigned32LE(packed.pILMaxDam), player._pILMaxDam == SwapSigned32LE(packed.pILMaxDam));\r\n\tValidateFields(player._pMaxHPBase, player.calculateBaseLife(), player._pMaxHPBase <= player.calculateBaseLife());\r\n\tValidateFields(player._pMaxManaBase, player.calculateBaseMana(), player._pMaxManaBase <= player.calculateBaseMana());\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/pack.h",
    "content": "/**\r\n * @file pack.h\r\n *\r\n * Interface of functions for minifying player data structure.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"inv.h\"\r\n#include \"items.h\"\r\n#include \"msg.h\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\n#define MAX_SPELLS 52\r\n\r\n#pragma pack(push, 1)\r\nstruct ItemPack {\r\n\tuint32_t iSeed;\r\n\tuint16_t iCreateInfo;\r\n\tuint16_t idx;\r\n\tuint8_t bId;\r\n\tuint8_t bDur;\r\n\tuint8_t bMDur;\r\n\tuint8_t bCh;\r\n\tuint8_t bMCh;\r\n\tuint16_t wValue;\r\n\tuint32_t dwBuff;\r\n};\r\n\r\nstruct PlayerPack {\r\n\tuint32_t dwLowDateTime;\r\n\tuint32_t dwHighDateTime;\r\n\tint8_t destAction;\r\n\tint8_t destParam1;\r\n\tint8_t destParam2;\r\n\tuint8_t plrlevel;\r\n\tuint8_t px;\r\n\tuint8_t py;\r\n\tuint8_t targx;\r\n\tuint8_t targy;\r\n\tchar pName[PlayerNameLength];\r\n\tuint8_t pClass;\r\n\tuint8_t pBaseStr;\r\n\tuint8_t pBaseMag;\r\n\tuint8_t pBaseDex;\r\n\tuint8_t pBaseVit;\r\n\tuint8_t pLevel;\r\n\tuint8_t pStatPts;\r\n\tuint32_t pExperience;\r\n\tint32_t pGold;\r\n\tint32_t pHPBase;\r\n\tint32_t pMaxHPBase;\r\n\tint32_t pManaBase;\r\n\tint32_t pMaxManaBase;\r\n\tuint8_t pSplLvl[37]; // Should be MAX_SPELLS but set to 37 to make save games compatible\r\n\tuint64_t pMemSpells;\r\n\tItemPack InvBody[NUM_INVLOC];\r\n\tItemPack InvList[InventoryGridCells];\r\n\tint8_t InvGrid[InventoryGridCells];\r\n\tuint8_t _pNumInv;\r\n\tItemPack SpdList[MaxBeltItems];\r\n\tint8_t pTownWarps;\r\n\tint8_t pDungMsgs;\r\n\tint8_t pLvlLoad;\r\n\tuint8_t pBattleNet;\r\n\tuint8_t pManaShield;\r\n\tuint8_t pDungMsgs2;\r\n\t/** The format the character is in, 0: Diablo, 1: Hellfire */\r\n\tint8_t bIsHellfire;\r\n\tuint8_t reserved; // For future use\r\n\tuint16_t wReflections;\r\n\tuint8_t reserved2[2]; // For future use\r\n\tuint8_t pSplLvl2[10]; // Hellfire spells\r\n\tint16_t wReserved8;   // For future use\r\n\tuint32_t pDiabloKillLevel;\r\n\tuint32_t pDifficulty;\r\n\tuint32_t pDamAcFlags;  // `ItemSpecialEffectHf` is 1 byte but this is 4 bytes.\r\n\tuint8_t reserved3[20]; // For future use\r\n};\r\n\r\nunion ItemNetPack {\r\n\tTItemDef def;\r\n\tTItem item;\r\n\tTEar ear;\r\n};\r\n\r\nstruct PlayerNetPack {\r\n\tuint8_t plrlevel;\r\n\tuint8_t px;\r\n\tuint8_t py;\r\n\tuint8_t pdir;\r\n\tchar pName[PlayerNameLength];\r\n\tuint8_t pClass;\r\n\tuint8_t pBaseStr;\r\n\tuint8_t pBaseMag;\r\n\tuint8_t pBaseDex;\r\n\tuint8_t pBaseVit;\r\n\tint8_t pLevel;\r\n\tuint8_t pStatPts;\r\n\tuint32_t pExperience;\r\n\tint32_t pHPBase;\r\n\tint32_t pMaxHPBase;\r\n\tint32_t pManaBase;\r\n\tint32_t pMaxManaBase;\r\n\tuint8_t pSplLvl[MAX_SPELLS];\r\n\tuint64_t pMemSpells;\r\n\tItemNetPack InvBody[NUM_INVLOC];\r\n\tItemNetPack InvList[InventoryGridCells];\r\n\tint8_t InvGrid[InventoryGridCells];\r\n\tuint8_t _pNumInv;\r\n\tItemNetPack SpdList[MaxBeltItems];\r\n\tuint8_t pManaShield;\r\n\tuint16_t wReflections;\r\n\tuint8_t pDiabloKillLevel;\r\n\tuint8_t friendlyMode;\r\n\tuint8_t isOnSetLevel;\r\n\r\n\t// For validation\r\n\tint32_t pStrength;\r\n\tint32_t pMagic;\r\n\tint32_t pDexterity;\r\n\tint32_t pVitality;\r\n\tint32_t pHitPoints;\r\n\tint32_t pMaxHP;\r\n\tint32_t pMana;\r\n\tint32_t pMaxMana;\r\n\tint32_t pDamageMod;\r\n\tint32_t pBaseToBlk;\r\n\tint32_t pIMinDam;\r\n\tint32_t pIMaxDam;\r\n\tint32_t pIAC;\r\n\tint32_t pIBonusDam;\r\n\tint32_t pIBonusToHit;\r\n\tint32_t pIBonusAC;\r\n\tint32_t pIBonusDamMod;\r\n\tint32_t pIGetHit;\r\n\tint32_t pIEnAc;\r\n\tint32_t pIFMinDam;\r\n\tint32_t pIFMaxDam;\r\n\tint32_t pILMinDam;\r\n\tint32_t pILMaxDam;\r\n};\r\n#pragma pack(pop)\r\n\r\nbool RecreateHellfireSpellBook(const Player &player, const TItem &packedItem, Item *item = nullptr);\r\nvoid PackPlayer(PlayerPack &pPack, const Player &player);\r\nvoid UnPackPlayer(const PlayerPack &pPack, Player &player);\r\nvoid PackNetPlayer(PlayerNetPack &packed, const Player &player);\r\nbool UnPackNetPlayer(const PlayerNetPack &packed, Player &player);\r\n\r\n/**\r\n * @brief Save the attributes needed to recreate this item into an ItemPack struct\r\n *\r\n * @param packedItem The destination packed struct\r\n * @param item The source item\r\n * @param isHellfire Whether the item is from Hellfire or not\r\n */\r\nvoid PackItem(ItemPack &packedItem, const Item &item, bool isHellfire);\r\n\r\n/**\r\n * Expand a ItemPack in to a Item\r\n *\r\n * @param packedItem The source packed item\r\n * @param item The destination item\r\n * @param isHellfire Whether the item is from Hellfire or not\r\n */\r\nvoid UnPackItem(const ItemPack &packedItem, const Player &player, Item &item, bool isHellfire);\r\n\r\n/**\r\n * @brief Save the attributes needed to recreate this item into an ItemNetPack struct\r\n * @param item The source item\r\n * @param packedItem The destination packed struct\r\n */\r\nvoid PackNetItem(const Item &item, ItemNetPack &packedItem);\r\n\r\n/**\r\n * @brief Expand a ItemPack in to a Item\r\n * @param player The player holding the item\r\n * @param packedItem The source packed item\r\n * @param item The destination item\r\n * @return True if the item is valid\r\n */\r\nbool UnPackNetItem(const Player &player, const ItemNetPack &packedItem, Item &item);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/charpanel.cpp",
    "content": "#include \"panels/charpanel.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#include <algorithm>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n#include <fmt/format.h>\r\n#include <function_ref.hpp>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"player.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/surface_to_clx.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteList pChrButtons;\r\n\r\nnamespace {\r\n\r\nstruct StyledText {\r\n\tUiFlags style;\r\n\tstd::string text;\r\n\tint spacing = 1;\r\n};\r\n\r\nstruct PanelEntry {\r\n\tstd::string label;\r\n\tPoint position;\r\n\tint length;\r\n\tint labelLength;                                               // max label's length - used for line wrapping\r\n\tstd::optional<tl::function_ref<StyledText()>> statDisplayFunc; // function responsible for displaying stat\r\n};\r\n\r\nUiFlags GetBaseStatColor(CharacterAttribute attr)\r\n{\r\n\tUiFlags style = UiFlags::ColorWhite;\r\n\tif (InspectPlayer->GetBaseAttributeValue(attr) == InspectPlayer->GetMaximumAttributeValue(attr))\r\n\t\tstyle = UiFlags::ColorWhitegold;\r\n\treturn style;\r\n}\r\n\r\nUiFlags GetCurrentStatColor(CharacterAttribute attr)\r\n{\r\n\tUiFlags style = UiFlags::ColorWhite;\r\n\tconst int current = InspectPlayer->GetCurrentAttributeValue(attr);\r\n\tconst int base = InspectPlayer->GetBaseAttributeValue(attr);\r\n\tif (current > base)\r\n\t\tstyle = UiFlags::ColorBlue;\r\n\tif (current < base)\r\n\t\tstyle = UiFlags::ColorRed;\r\n\treturn style;\r\n}\r\n\r\nUiFlags GetValueColor(int value, bool flip = false)\r\n{\r\n\tUiFlags style = UiFlags::ColorWhite;\r\n\tif (value > 0)\r\n\t\tstyle = (flip ? UiFlags::ColorRed : UiFlags::ColorBlue);\r\n\tif (value < 0)\r\n\t\tstyle = (flip ? UiFlags::ColorBlue : UiFlags::ColorRed);\r\n\treturn style;\r\n}\r\n\r\nUiFlags GetMaxManaColor()\r\n{\r\n\tif (HasAnyOf(InspectPlayer->_pIFlags, ItemSpecialEffect::NoMana))\r\n\t\treturn UiFlags::ColorRed;\r\n\treturn InspectPlayer->_pMaxMana > InspectPlayer->_pMaxManaBase ? UiFlags::ColorBlue : UiFlags::ColorWhite;\r\n}\r\n\r\nUiFlags GetMaxHealthColor()\r\n{\r\n\treturn InspectPlayer->_pMaxHP > InspectPlayer->_pMaxHPBase ? UiFlags::ColorBlue : UiFlags::ColorWhite;\r\n}\r\n\r\nstd::pair<int, int> GetDamage()\r\n{\r\n\tint damageMod = InspectPlayer->_pIBonusDamMod;\r\n\tif (InspectPlayer->InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Bow && InspectPlayer->_pClass != HeroClass::Rogue) {\r\n\t\tdamageMod += InspectPlayer->_pDamageMod / 2;\r\n\t} else {\r\n\t\tdamageMod += InspectPlayer->_pDamageMod;\r\n\t}\r\n\tconst int mindam = InspectPlayer->_pIMinDam + InspectPlayer->_pIBonusDam * InspectPlayer->_pIMinDam / 100 + damageMod;\r\n\tconst int maxdam = InspectPlayer->_pIMaxDam + InspectPlayer->_pIBonusDam * InspectPlayer->_pIMaxDam / 100 + damageMod;\r\n\treturn { mindam, maxdam };\r\n}\r\n\r\nStyledText GetResistInfo(int8_t resist)\r\n{\r\n\tUiFlags style = UiFlags::ColorBlue;\r\n\tif (resist == 0)\r\n\t\tstyle = UiFlags::ColorWhite;\r\n\telse if (resist < 0)\r\n\t\tstyle = UiFlags::ColorRed;\r\n\telse if (resist >= MaxResistance)\r\n\t\tstyle = UiFlags::ColorWhitegold;\r\n\r\n\treturn { style, StrCat(resist, \"%\") };\r\n}\r\n\r\nconstexpr int LeftColumnLabelX = 88;\r\nconstexpr int TopRightLabelX = 211;\r\nconstexpr int RightColumnLabelX = 253;\r\n\r\nconstexpr int LeftColumnLabelWidth = 76;\r\nconstexpr int RightColumnLabelWidth = 68;\r\n\r\n// Indices in `panelEntries`.\r\nconstexpr unsigned AttributeHeaderEntryIndices[2] = { 5, 6 };\r\nconstexpr unsigned GoldHeaderEntryIndex = 16;\r\n\r\nPanelEntry panelEntries[] = {\r\n\t{ \"\", { 9, 14 }, 150, 0,\r\n\t    []() { return StyledText { UiFlags::ColorWhite, InspectPlayer->_pName }; } },\r\n\t{ \"\", { 161, 14 }, 149, 0,\r\n\t    []() { return StyledText { UiFlags::ColorWhite, std::string(InspectPlayer->getClassName()) }; } },\r\n\r\n\t{ N_(\"Level\"), { 57, 52 }, 57, 45,\r\n\t    []() { return StyledText { UiFlags::ColorWhite, StrCat(InspectPlayer->getCharacterLevel()) }; } },\r\n\t{ N_(\"Experience\"), { TopRightLabelX, 52 }, 99, 91,\r\n\t    []() {\r\n\t        return StyledText { UiFlags::ColorWhite, FormatInteger(InspectPlayer->_pExperience) };\r\n\t    } },\r\n\t{ N_(\"Next level\"), { TopRightLabelX, 80 }, 99, 198,\r\n\t    []() {\r\n\t        if (InspectPlayer->isMaxCharacterLevel()) {\r\n\t\t        return StyledText { UiFlags::ColorWhitegold, std::string(_(\"None\")) };\r\n\t        }\r\n\t        const uint32_t nextExperienceThreshold = InspectPlayer->getNextExperienceThreshold();\r\n\t        return StyledText { UiFlags::ColorWhite, FormatInteger(nextExperienceThreshold) };\r\n\t    } },\r\n\r\n\t{ N_(\"Base\"), { LeftColumnLabelX, /* set dynamically */ 0 }, 0, 44, {} },\r\n\t{ N_(\"Now\"), { 135, /* set dynamically */ 0 }, 0, 44, {} },\r\n\t{ N_(\"Strength\"), { LeftColumnLabelX, 135 }, 45, LeftColumnLabelWidth,\r\n\t    []() { return StyledText { GetBaseStatColor(CharacterAttribute::Strength), StrCat(InspectPlayer->_pBaseStr) }; } },\r\n\t{ \"\", { 135, 135 }, 45, 0,\r\n\t    []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Strength), StrCat(InspectPlayer->_pStrength) }; } },\r\n\t{ N_(\"Magic\"), { LeftColumnLabelX, 163 }, 45, LeftColumnLabelWidth,\r\n\t    []() { return StyledText { GetBaseStatColor(CharacterAttribute::Magic), StrCat(InspectPlayer->_pBaseMag) }; } },\r\n\t{ \"\", { 135, 163 }, 45, 0,\r\n\t    []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Magic), StrCat(InspectPlayer->_pMagic) }; } },\r\n\t{ N_(\"Dexterity\"), { LeftColumnLabelX, 191 }, 45, LeftColumnLabelWidth, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Dexterity), StrCat(InspectPlayer->_pBaseDex) }; } },\r\n\t{ \"\", { 135, 191 }, 45, 0,\r\n\t    []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Dexterity), StrCat(InspectPlayer->_pDexterity) }; } },\r\n\t{ N_(\"Vitality\"), { LeftColumnLabelX, 219 }, 45, LeftColumnLabelWidth, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Vitality), StrCat(InspectPlayer->_pBaseVit) }; } },\r\n\t{ \"\", { 135, 219 }, 45, 0,\r\n\t    []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Vitality), StrCat(InspectPlayer->_pVitality) }; } },\r\n\t{ N_(\"Points to distribute\"), { LeftColumnLabelX, 248 }, 45, LeftColumnLabelWidth,\r\n\t    []() {\r\n\t        InspectPlayer->_pStatPts = std::min(CalcStatDiff(*InspectPlayer), InspectPlayer->_pStatPts);\r\n\t        return StyledText { UiFlags::ColorRed, (InspectPlayer->_pStatPts > 0 ? StrCat(InspectPlayer->_pStatPts) : \"\") };\r\n\t    } },\r\n\r\n\t{ N_(\"Gold\"), { TopRightLabelX, /* set dynamically */ 0 }, 0, 98, {} },\r\n\t{ \"\", { TopRightLabelX, 127 }, 99, 0,\r\n\t    []() { return StyledText { UiFlags::ColorWhite, FormatInteger(InspectPlayer->_pGold) }; } },\r\n\r\n\t{ N_(\"Armor class\"), { RightColumnLabelX, 163 }, 57, RightColumnLabelWidth,\r\n\t    []() { return StyledText { GetValueColor(InspectPlayer->_pIBonusAC), StrCat(InspectPlayer->GetArmor() + InspectPlayer->getCharacterLevel() * 2) }; } },\r\n\t{ N_(\"Chance To Hit\"), { RightColumnLabelX, 191 }, 57, RightColumnLabelWidth,\r\n\t    []() { return StyledText { GetValueColor(InspectPlayer->_pIBonusToHit), StrCat(InspectPlayer->InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Bow ? InspectPlayer->GetRangedToHit() : InspectPlayer->GetMeleeToHit(), \"%\") }; } },\r\n\t{ N_(\"Damage\"), { RightColumnLabelX, 219 }, 57, RightColumnLabelWidth,\r\n\t    []() {\r\n\t        const auto [dmgMin, dmgMax] = GetDamage();\r\n\t        return StyledText { GetValueColor(InspectPlayer->_pIBonusDam), StrCat(dmgMin, \"-\", dmgMax) };\r\n\t    } },\r\n\r\n\t{ N_(\"Life\"), { LeftColumnLabelX, 284 }, 45, LeftColumnLabelWidth,\r\n\t    []() { return StyledText { GetMaxHealthColor(), StrCat(InspectPlayer->_pMaxHP >> 6) }; } },\r\n\t{ \"\", { 135, 284 }, 45, 0,\r\n\t    []() { return StyledText { (InspectPlayer->_pHitPoints != InspectPlayer->_pMaxHP ? UiFlags::ColorRed : GetMaxHealthColor()), StrCat(InspectPlayer->_pHitPoints >> 6) }; } },\r\n\t{ N_(\"Mana\"), { LeftColumnLabelX, 312 }, 45, LeftColumnLabelWidth,\r\n\t    []() { return StyledText { GetMaxManaColor(), StrCat(HasAnyOf(InspectPlayer->_pIFlags, ItemSpecialEffect::NoMana) ? 0 : InspectPlayer->_pMaxMana >> 6) }; } },\r\n\t{ \"\", { 135, 312 }, 45, 0,\r\n\t    []() { return StyledText { (InspectPlayer->_pMana != InspectPlayer->_pMaxMana ? UiFlags::ColorRed : GetMaxManaColor()), StrCat((HasAnyOf(InspectPlayer->_pIFlags, ItemSpecialEffect::NoMana) || InspectPlayer->hasNoMana()) ? 0 : InspectPlayer->_pMana >> 6) }; } },\r\n\r\n\t{ N_(\"Resist magic\"), { RightColumnLabelX, 256 }, 57, RightColumnLabelWidth,\r\n\t    []() { return GetResistInfo(InspectPlayer->_pMagResist); } },\r\n\t{ N_(\"Resist fire\"), { RightColumnLabelX, 284 }, 57, RightColumnLabelWidth,\r\n\t    []() { return GetResistInfo(InspectPlayer->_pFireResist); } },\r\n\t{ N_(\"Resist lightning\"), { RightColumnLabelX, 313 }, 57, RightColumnLabelWidth,\r\n\t    []() { return GetResistInfo(InspectPlayer->_pLghtResist); } },\r\n};\r\n\r\nOptionalOwnedClxSpriteList Panel;\r\n\r\nconstexpr int PanelFieldHeight = 24;\r\nconstexpr int PanelFieldPaddingTop = 3;\r\nconstexpr int PanelFieldPaddingBottom = 3;\r\nconstexpr int PanelFieldPaddingSide = 5;\r\nconstexpr int PanelFieldInnerHeight = PanelFieldHeight - PanelFieldPaddingTop - PanelFieldPaddingBottom;\r\n\r\nvoid DrawPanelField(const Surface &out, Point pos, int len, ClxSprite left, ClxSprite middle, ClxSprite right)\r\n{\r\n\tRenderClxSprite(out, left, pos);\r\n\tpos.x += left.width();\r\n\tlen -= left.width() + right.width();\r\n\tRenderClxSprite(out.subregion(pos.x, pos.y, len, middle.height()), middle, Point { 0, 0 });\r\n\tpos.x += len;\r\n\tRenderClxSprite(out, right, pos);\r\n}\r\n\r\nvoid DrawShadowString(const Surface &out, const PanelEntry &entry)\r\n{\r\n\tif (entry.label.empty())\r\n\t\treturn;\r\n\r\n\tconstexpr int Spacing = 0;\r\n\tconst std::string_view textStr = LanguageTranslate(entry.label);\r\n\tstd::string_view text;\r\n\tstd::string wrapped;\r\n\tif (entry.labelLength > 0) {\r\n\t\twrapped = WordWrapString(textStr, entry.labelLength, GameFont12, Spacing);\r\n\t\ttext = wrapped;\r\n\t} else {\r\n\t\ttext = textStr;\r\n\t}\r\n\r\n\tUiFlags style = UiFlags::VerticalCenter;\r\n\r\n\tPoint labelPosition = entry.position;\r\n\r\n\tif (entry.length == 0) {\r\n\t\tstyle |= UiFlags::AlignCenter;\r\n\t} else {\r\n\t\tstyle |= UiFlags::AlignRight;\r\n\t\tlabelPosition += Displacement { -entry.labelLength - (IsSmallFontTall() ? 2 : 3), 0 };\r\n\t}\r\n\r\n\t// If the text is less tall than the field, we center it vertically relative to the field.\r\n\t// Otherwise, we draw from the top of the field.\r\n\tconst int textHeight = static_cast<int>((c_count(wrapped, '\\n') + 1) * GetLineHeight(wrapped, GameFont12));\r\n\tconst int labelHeight = std::max(PanelFieldHeight, textHeight);\r\n\r\n\tDrawString(out, text, { labelPosition + Displacement { -2, 2 }, { entry.labelLength, labelHeight } },\r\n\t    { .flags = style | UiFlags::ColorBlack, .spacing = Spacing });\r\n\tDrawString(out, text, { labelPosition, { entry.labelLength, labelHeight } },\r\n\t    { .flags = style | UiFlags::ColorWhite, .spacing = Spacing });\r\n}\r\n\r\nvoid DrawStatButtons(const Surface &out)\r\n{\r\n\tif (InspectPlayer->_pStatPts > 0 && !IsInspectingPlayer()) {\r\n\t\tif (InspectPlayer->_pBaseStr < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Strength))\r\n\t\t\tClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 157 }), (*pChrButtons)[CharPanelButton[static_cast<size_t>(CharacterAttribute::Strength)] ? 2 : 1]);\r\n\t\tif (InspectPlayer->_pBaseMag < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Magic))\r\n\t\t\tClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 185 }), (*pChrButtons)[CharPanelButton[static_cast<size_t>(CharacterAttribute::Magic)] ? 4 : 3]);\r\n\t\tif (InspectPlayer->_pBaseDex < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Dexterity))\r\n\t\t\tClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 214 }), (*pChrButtons)[CharPanelButton[static_cast<size_t>(CharacterAttribute::Dexterity)] ? 6 : 5]);\r\n\t\tif (InspectPlayer->_pBaseVit < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Vitality))\r\n\t\t\tClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 242 }), (*pChrButtons)[CharPanelButton[static_cast<size_t>(CharacterAttribute::Vitality)] ? 8 : 7]);\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\ntl::expected<void, std::string> LoadCharPanel()\r\n{\r\n\tASSIGN_OR_RETURN(OptionalOwnedClxSpriteList background, LoadClxWithStatus(\"data\\\\charbg.clx\"));\r\n\tconst OwnedSurface out((*background)[0].width(), (*background)[0].height());\r\n\tRenderClxSprite(out, (*background)[0], { 0, 0 });\r\n\tbackground = std::nullopt;\r\n\r\n\t{\r\n\t\tASSIGN_OR_RETURN(OwnedClxSpriteList boxLeft, LoadClxWithStatus(\"data\\\\boxleftend.clx\"));\r\n\t\tASSIGN_OR_RETURN(OwnedClxSpriteList boxMiddle, LoadClxWithStatus(\"data\\\\boxmiddle.clx\"));\r\n\t\tASSIGN_OR_RETURN(OwnedClxSpriteList boxRight, LoadClxWithStatus(\"data\\\\boxrightend.clx\"));\r\n\r\n\t\tconst bool isSmallFontTall = IsSmallFontTall();\r\n\t\tconst int attributeHeadersY = isSmallFontTall ? 112 : 114;\r\n\t\tfor (const unsigned i : AttributeHeaderEntryIndices) {\r\n\t\t\tpanelEntries[i].position.y = attributeHeadersY;\r\n\t\t}\r\n\t\tpanelEntries[GoldHeaderEntryIndex].position.y = isSmallFontTall ? 105 : 106;\r\n\r\n\t\tfor (auto &entry : panelEntries) {\r\n\t\t\tif (entry.statDisplayFunc) {\r\n\t\t\t\tDrawPanelField(out, entry.position, entry.length, boxLeft[0], boxMiddle[0], boxRight[0]);\r\n\t\t\t}\r\n\t\t\tDrawShadowString(out, entry);\r\n\t\t}\r\n\t}\r\n\r\n\tPanel = SurfaceToClx(out);\r\n\treturn {};\r\n}\r\n\r\nvoid FreeCharPanel()\r\n{\r\n\tPanel = std::nullopt;\r\n}\r\n\r\nvoid DrawChr(const Surface &out)\r\n{\r\n\tconst Point pos = GetPanelPosition(UiPanels::Character, { 0, 0 });\r\n\tRenderClxSprite(out, (*Panel)[0], pos);\r\n\tfor (auto &entry : panelEntries) {\r\n\t\tif (entry.statDisplayFunc) {\r\n\t\t\tconst StyledText tmp = (*entry.statDisplayFunc)();\r\n\t\t\tDrawString(\r\n\t\t\t    out,\r\n\t\t\t    tmp.text,\r\n\t\t\t    { entry.position + Displacement { pos.x + PanelFieldPaddingSide, pos.y + PanelFieldPaddingTop }, { entry.length - (PanelFieldPaddingSide * 2), PanelFieldInnerHeight } },\r\n\t\t\t    { .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter | UiFlags::VerticalCenter | tmp.style });\r\n\t\t}\r\n\t}\r\n\tDrawStatButtons(out);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/charpanel.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern OptionalOwnedClxSpriteList pChrButtons;\r\n\r\nvoid DrawChr(const Surface &);\r\ntl::expected<void, std::string> LoadCharPanel();\r\nvoid FreeCharPanel();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/console.cpp",
    "content": "#ifdef _DEBUG\r\n#include \"panels/console.hpp\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_scancode.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"DiabloUI/text_input.hpp\"\r\n#include \"control/control.hpp\"\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"lua/autocomplete.hpp\"\r\n#include \"lua/repl.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconstexpr std::string_view Prompt = \"> \";\r\nconstexpr std::string_view HelpText =\r\n    // Displayed as the first console message\r\n    \"Lua console\\n\"\r\n    \"Shift+Enter to insert a newline, PageUp/Down to scroll,\"\r\n    \" Up/Down to fill the input from history,\"\r\n    \" Shift+Up/Down to fill the input from output history,\"\r\n    \" Ctrl+L to clear history, Esc to close.\";\r\nstd::optional<tl::expected<AssetData, std::string>> ConsolePrelude;\r\n\r\nbool IsConsoleVisible;\r\nchar ConsoleInputBuffer[4096];\r\nTextInputCursorState ConsoleInputCursor;\r\nTextInputState ConsoleInputState {\r\n\tTextInputState::Options {\r\n\t    .value = ConsoleInputBuffer,\r\n\t    .cursor = &ConsoleInputCursor,\r\n\t    .maxLength = sizeof(ConsoleInputBuffer) - 1,\r\n\t}\r\n};\r\n\r\nenum class InputTextState {\r\n\tUpToDate,\r\n\tEdited,\r\n\tRestoredFromHistory\r\n};\r\n\r\nInputTextState CurrentInputTextState = InputTextState::UpToDate;\r\nstd::string WrappedInputText { Prompt };\r\nstd::vector<LuaAutocompleteSuggestion> AutocompleteSuggestions;\r\nint AutocompleteSuggestionsMaxWidth = -1;\r\nint AutocompleteSuggestionFocusIndex = -1;\r\nconstexpr size_t MaxSuggestions = 12;\r\n\r\nstruct ConsoleLine {\r\n\tenum Type : uint8_t {\r\n\t\tHelp,\r\n\t\tInput,\r\n\t\tOutput,\r\n\t\tWarning,\r\n\t\tError\r\n\t};\r\n\r\n\tType type;\r\n\tstd::string text;\r\n\tstd::string wrapped = {};\r\n\tint numLines = 0;\r\n\r\n\t[[nodiscard]] std::string_view textWithoutPrompt() const\r\n\t{\r\n\t\tstd::string_view result = text;\r\n\t\tif (type == ConsoleLine::Input) {\r\n\t\t\tresult.remove_prefix(Prompt.size());\r\n\t\t}\r\n\t\treturn result;\r\n\t}\r\n};\r\n\r\nstd::vector<ConsoleLine> ConsoleLines;\r\nsize_t NumPreparedConsoleLines;\r\nint ConsoleLinesTotalHeight;\r\n\r\n// Index of the currently filled input/output, counting from end.\r\nint HistoryIndex = -1;\r\n\r\n// Draft input, saved when navigating history.\r\nstd::string DraftInput;\r\n\r\nRectangle OuterRect;\r\nRectangle InputRect;\r\nint InputRectHeight;\r\nconstexpr int LineHeight = 20;\r\nconstexpr int TextPaddingYTop = 0;\r\nconstexpr int TextPaddingYBottom = 4;\r\nconstexpr int TextPaddingX = 4;\r\nconstexpr uint8_t BorderColor = PAL8_YELLOW;\r\nbool FirstRender;\r\n\r\nconstexpr UiFlags TextUiFlags = UiFlags::FontSizeDialog;\r\nconstexpr UiFlags InputTextUiFlags = TextUiFlags | UiFlags::ColorDialogWhite;\r\nconstexpr UiFlags OutputTextUiFlags = TextUiFlags | UiFlags::ColorDialogWhite;\r\nconstexpr UiFlags WarningTextUiFlags = TextUiFlags | UiFlags::ColorDialogYellow;\r\nconstexpr UiFlags ErrorTextUiFlags = TextUiFlags | UiFlags::ColorDialogRed;\r\nconstexpr UiFlags AutocompleteSuggestionsTextUiFlags = TextUiFlags | UiFlags::ColorDialogWhite;\r\nconstexpr UiFlags AutocompleteSuggestionsFocusedTextUiFlags = TextUiFlags | UiFlags::ColorDialogYellow;\r\n\r\nconstexpr int TextSpacing = 0;\r\nconstexpr GameFontTables TextFontSize = GetFontSizeFromUiFlags(InputTextUiFlags);\r\nconstexpr GameFontTables AutocompleteSuggestionsTextFontSize = GetFontSizeFromUiFlags(AutocompleteSuggestionsTextUiFlags);\r\n\r\n// Scroll offset from the bottom (in pages), to be applied on next render.\r\nint PendingScrollPages;\r\n// Scroll offset from the bottom in pixels.\r\nint ScrollOffset;\r\nconstexpr int ScrollStep = LineHeight * 3;\r\n\r\nvoid CloseConsole()\r\n{\r\n\tIsConsoleVisible = false;\r\n\tSDLC_StopTextInput(ghMainWnd);\r\n}\r\n\r\nint GetConsoleLinesInnerWidth()\r\n{\r\n\treturn OuterRect.size.width - 2 * TextPaddingX;\r\n}\r\n\r\nvoid PrepareForRender(ConsoleLine &consoleLine)\r\n{\r\n\tconsoleLine.wrapped = WordWrapString(consoleLine.text, GetConsoleLinesInnerWidth(), TextFontSize, TextSpacing);\r\n\tconsoleLine.numLines += static_cast<int>(c_count(consoleLine.wrapped, '\\n')) + 1;\r\n\tConsoleLinesTotalHeight += consoleLine.numLines * LineHeight;\r\n}\r\n\r\nvoid AddConsoleLine(ConsoleLine &&consoleLine)\r\n{\r\n\tConsoleLines.emplace_back(std::move(consoleLine));\r\n}\r\n\r\nvoid SendInput()\r\n{\r\n\tRunInConsole(ConsoleInputState.value());\r\n\tConsoleInputState.clear();\r\n\tDraftInput.clear();\r\n\tHistoryIndex = -1;\r\n}\r\n\r\nvoid DrawAutocompleteSuggestions(const Surface &out, const std::vector<LuaAutocompleteSuggestion> &suggestions, Point position)\r\n{\r\n\tconst int maxInnerWidth = out.w() - TextPaddingX * 2;\r\n\tif (AutocompleteSuggestionsMaxWidth == -1) {\r\n\t\tint maxWidth = 0;\r\n\t\tfor (const LuaAutocompleteSuggestion &suggestion : suggestions) {\r\n\t\t\tmaxWidth = std::max(maxWidth, GetLineWidth(suggestion.displayText, AutocompleteSuggestionsTextFontSize, TextSpacing));\r\n\t\t}\r\n\t\tAutocompleteSuggestionsMaxWidth = std::min(maxWidth, maxInnerWidth);\r\n\t}\r\n\r\n\tconst int outerWidth = AutocompleteSuggestionsMaxWidth + TextPaddingX * 2;\r\n\r\n\tif (position.x + outerWidth > out.w()) {\r\n\t\tposition.x = out.w() - outerWidth;\r\n\t}\r\n\tconst int height = static_cast<int>(suggestions.size()) * LineHeight + TextPaddingYBottom + TextPaddingYTop;\r\n\r\n\tposition.y -= height;\r\n\tposition.y = std::max(LineHeight, position.y);\r\n\r\n\tFillRect(out, position.x, position.y, outerWidth, height, PAL16_BLUE + 14);\r\n\tsize_t i = 0;\r\n\r\n\tPoint textPosition { position.x + TextPaddingX, position.y + TextPaddingYTop };\r\n\tfor (const LuaAutocompleteSuggestion &suggestion : suggestions) {\r\n\t\tif (static_cast<int>(i) == AutocompleteSuggestionFocusIndex) {\r\n\t\t\tconst int extraTop = i == 0 ? TextPaddingYTop : 0;\r\n\t\t\tconst int extraHeight = extraTop + TextPaddingYBottom;\r\n\t\t\tFillRect(out, position.x, textPosition.y - extraTop, outerWidth, LineHeight + extraHeight, PAL16_BLUE + 8);\r\n\t\t}\r\n\t\tconst int textHeight = LineHeight + TextPaddingYBottom;\r\n\t\tDrawString(\r\n\t\t    out.subregion(textPosition.x, textPosition.y, maxInnerWidth, textHeight), suggestion.displayText,\r\n\t\t    Rectangle { Point { 0, 0 }, Size { maxInnerWidth, textHeight } },\r\n\t\t    TextRenderOptions {\r\n\t\t        .flags = AutocompleteSuggestionsTextUiFlags,\r\n\t\t        .spacing = TextSpacing,\r\n\t\t    });\r\n\t\ttextPosition.y += LineHeight;\r\n\t\t++i;\r\n\t}\r\n}\r\n\r\nbool IsBreakStart(std::string_view str, size_t &breakLen)\r\n{\r\n\tconst char32_t cp = DecodeFirstUtf8CodePoint(str, &breakLen);\r\n\treturn cp == U'\\n' || IsBreakableWhitespace(cp);\r\n}\r\n\r\nvoid DrawInputText(const Surface &out,\r\n    Rectangle rect, std::string_view originalInputText, std::string_view wrappedInputText)\r\n{\r\n\tint lineY = 0;\r\n\tint numRendered = -static_cast<int>(Prompt.size());\r\n\tbool prevIsOriginalWhitespace = false;\r\n\r\n\tconst Surface inputTextSurface = out.subregion(rect.position.x, rect.position.y, rect.size.width, rect.size.height);\r\n\tstd::optional<Point> renderedCursorPositionOut;\r\n\tfor (const std::string_view line : SplitByChar(wrappedInputText, '\\n')) {\r\n\t\tconst int lineCursorPosition = static_cast<int>(ConsoleInputCursor.position) - numRendered;\r\n\t\tconst bool isCursorOnPrevLine = lineCursorPosition == 0 && !prevIsOriginalWhitespace && numRendered > 0;\r\n\t\tDrawString(\r\n\t\t    inputTextSurface, line, { 0, lineY },\r\n\t\t    TextRenderOptions {\r\n\t\t        .flags = InputTextUiFlags,\r\n\t\t        .spacing = TextSpacing,\r\n\t\t        .cursorPosition = isCursorOnPrevLine ? -1 : lineCursorPosition,\r\n\t\t        .highlightRange = { static_cast<int>(ConsoleInputCursor.selection.begin) - numRendered, static_cast<int>(ConsoleInputCursor.selection.end) - numRendered },\r\n\t\t        .renderedCursorPositionOut = &renderedCursorPositionOut });\r\n\t\tlineY += LineHeight;\r\n\t\tnumRendered += static_cast<int>(line.size());\r\n\r\n\t\tsize_t whitespaceLength;\r\n\t\tprevIsOriginalWhitespace = static_cast<size_t>(numRendered) < originalInputText.size()\r\n\t\t    && IsBreakStart(originalInputText.substr(static_cast<size_t>(numRendered)), whitespaceLength);\r\n\t\tif (prevIsOriginalWhitespace) {\r\n\t\t\t// If we replaced an original whitespace with a newline, count the original whitespace as rendered.\r\n\t\t\tnumRendered += static_cast<int>(whitespaceLength);\r\n\t\t}\r\n\t\tif (numRendered < 0 && IsBreakStart(Prompt.substr(Prompt.size() - static_cast<size_t>(-numRendered)), whitespaceLength)) {\r\n\t\t\t// If we replaced the whitespace in a prompt with a newline, count it as rendered.\r\n\t\t\tnumRendered += static_cast<int>(whitespaceLength);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!AutocompleteSuggestions.empty() && renderedCursorPositionOut.has_value()) {\r\n\t\tPoint position = *renderedCursorPositionOut;\r\n\t\tposition.x += rect.position.x;\r\n\t\tposition.y += rect.position.y;\r\n\t\tDrawAutocompleteSuggestions(out, AutocompleteSuggestions, position);\r\n\t}\r\n}\r\n\r\nvoid DrawConsoleLines(const Surface &out)\r\n{\r\n\tconst int innerHeight = out.h() - 4; // Extra space for letters like g.\r\n\tif (PendingScrollPages) {\r\n\t\tScrollOffset += innerHeight * PendingScrollPages;\r\n\t\tPendingScrollPages = 0;\r\n\t}\r\n\r\n\tif (NumPreparedConsoleLines != ConsoleLines.size()) {\r\n\t\tfor (size_t i = NumPreparedConsoleLines; i < ConsoleLines.size(); ++i) {\r\n\t\t\tPrepareForRender(ConsoleLines[i]);\r\n\t\t}\r\n\t\tNumPreparedConsoleLines = ConsoleLines.size();\r\n\t\tScrollOffset = 0;\r\n\t}\r\n\r\n\tScrollOffset = std::clamp(ScrollOffset, 0, std::max(0, ConsoleLinesTotalHeight - innerHeight));\r\n\r\n\tint lineYEnd = innerHeight + ScrollOffset;\r\n\t// NOLINTNEXTLINE(modernize-loop-convert)\r\n\tfor (auto it = ConsoleLines.rbegin(), itEnd = ConsoleLines.rend(); it != itEnd; ++it) {\r\n\t\tConsoleLine &consoleLine = *it;\r\n\t\tconst int linesYBegin = lineYEnd - LineHeight * consoleLine.numLines;\r\n\t\tif (linesYBegin > innerHeight) {\r\n\t\t\tlineYEnd = linesYBegin;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tsize_t end = consoleLine.wrapped.size();\r\n\t\twhile (true) {\r\n\t\t\tconst size_t begin = consoleLine.wrapped.rfind('\\n', end - 1) + 1;\r\n\t\t\tconst std::string_view line = std::string_view(consoleLine.wrapped.data() + begin, end - begin);\r\n\t\t\tlineYEnd -= LineHeight;\r\n\t\t\tswitch (consoleLine.type) {\r\n\t\t\tcase ConsoleLine::Input:\r\n\t\t\t\tDrawString(out, line, { 0, lineYEnd },\r\n\t\t\t\t    TextRenderOptions { .flags = InputTextUiFlags, .spacing = TextSpacing });\r\n\t\t\t\tbreak;\r\n\t\t\tcase ConsoleLine::Output:\r\n\t\t\tcase ConsoleLine::Help:\r\n\t\t\t\tDrawString(out, line, { 0, lineYEnd },\r\n\t\t\t\t    TextRenderOptions { .flags = OutputTextUiFlags, .spacing = TextSpacing });\r\n\t\t\t\tbreak;\r\n\t\t\tcase ConsoleLine::Warning:\r\n\t\t\t\tDrawString(out, line, { 0, lineYEnd },\r\n\t\t\t\t    TextRenderOptions { .flags = WarningTextUiFlags, .spacing = TextSpacing });\r\n\t\t\t\tbreak;\r\n\t\t\tcase ConsoleLine::Error:\r\n\t\t\t\tDrawString(out, line, { 0, lineYEnd },\r\n\t\t\t\t    TextRenderOptions { .flags = ErrorTextUiFlags, .spacing = TextSpacing });\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif (lineYEnd < 0 || begin == 0)\r\n\t\t\t\tbreak;\r\n\t\t\tend = begin - 1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nconst ConsoleLine &GetConsoleLineFromEnd(int index)\r\n{\r\n\treturn *(ConsoleLines.rbegin() + index);\r\n}\r\n\r\nvoid SetHistoryIndex(int index)\r\n{\r\n\tCurrentInputTextState = InputTextState::RestoredFromHistory;\r\n\tHistoryIndex = static_cast<int>(std::ssize(ConsoleLines)) - (index + 1);\r\n\tif (HistoryIndex == -1) {\r\n\t\tConsoleInputState.assign(DraftInput);\r\n\t\treturn;\r\n\t}\r\n\tconst ConsoleLine &line = ConsoleLines[index];\r\n\tConsoleInputState.assign(line.textWithoutPrompt());\r\n}\r\n\r\nvoid PrevHistoryItem(tl::function_ref<bool(const ConsoleLine &line)> filter)\r\n{\r\n\tif (HistoryIndex == -1) {\r\n\t\tDraftInput = ConsoleInputState.value();\r\n\t}\r\n\tconst int n = static_cast<int>(std::ssize(ConsoleLines));\r\n\tfor (int i = HistoryIndex + 1; i < n; ++i) {\r\n\t\tconst int index = n - (i + 1);\r\n\t\tif (filter(ConsoleLines[index])) {\r\n\t\t\tSetHistoryIndex(index);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NextHistoryItem(tl::function_ref<bool(const ConsoleLine &line)> filter)\r\n{\r\n\tconst int n = static_cast<int>(std::ssize(ConsoleLines));\r\n\tfor (int i = n - HistoryIndex; i < n; ++i) {\r\n\t\tif (filter(ConsoleLines[i])) {\r\n\t\t\tSetHistoryIndex(i);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tif (HistoryIndex != -1) {\r\n\t\tSetHistoryIndex(n);\r\n\t}\r\n}\r\n\r\nbool IsHistoryInputLine(const ConsoleLine &line)\r\n{\r\n\tif (line.type != ConsoleLine::Input)\r\n\t\treturn false;\r\n\tstd::string_view text = line.text;\r\n\ttext.remove_prefix(Prompt.size());\r\n\tif (text.empty())\r\n\t\treturn false;\r\n\treturn HistoryIndex == -1 || GetConsoleLineFromEnd(HistoryIndex).textWithoutPrompt() != text;\r\n}\r\n\r\nvoid PrevInput()\r\n{\r\n\tPrevHistoryItem(IsHistoryInputLine);\r\n}\r\n\r\nvoid NextInput()\r\n{\r\n\tNextHistoryItem(IsHistoryInputLine);\r\n}\r\n\r\nbool IsHistoryOutputLine(const ConsoleLine &line)\r\n{\r\n\treturn !line.text.empty()\r\n\t    && (line.type == ConsoleLine::Output || line.type == ConsoleLine::Warning || line.type == ConsoleLine::Error)\r\n\t    && (HistoryIndex == -1\r\n\t        || GetConsoleLineFromEnd(HistoryIndex).textWithoutPrompt() != line.text);\r\n}\r\n\r\nvoid PrevOutput()\r\n{\r\n\tPrevHistoryItem(IsHistoryOutputLine);\r\n}\r\n\r\nvoid NextOutput()\r\n{\r\n\tNextHistoryItem(IsHistoryOutputLine);\r\n}\r\n\r\nvoid AddInitialConsoleLines()\r\n{\r\n\tif (ConsolePrelude->has_value()) {\r\n\t\tstd::string_view prelude { **ConsolePrelude };\r\n\t\tif (!prelude.empty() && prelude.back() == '\\n')\r\n\t\t\tprelude.remove_suffix(1);\r\n\t\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Help, .text = StrCat(HelpText, \"\\n\", prelude) });\r\n\t} else {\r\n\t\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Help, .text = std::string(HelpText) });\r\n\t\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Error, .text = ConsolePrelude->error() });\r\n\t}\r\n}\r\n\r\nvoid ClearConsole()\r\n{\r\n\tConsoleLines.clear();\r\n\tHistoryIndex = -1;\r\n\tScrollOffset = 0;\r\n\tNumPreparedConsoleLines = 0;\r\n\tConsoleLinesTotalHeight = 0;\r\n\tAddInitialConsoleLines();\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsConsoleOpen()\r\n{\r\n\treturn IsConsoleVisible;\r\n}\r\n\r\nvoid OpenConsole()\r\n{\r\n\tIsConsoleVisible = true;\r\n\tFirstRender = true;\r\n}\r\n\r\nvoid AcceptSuggestion()\r\n{\r\n\tconst LuaAutocompleteSuggestion &suggestion = AutocompleteSuggestions[AutocompleteSuggestionFocusIndex];\r\n\tConsoleInputState.type(suggestion.completionText);\r\n\tif (suggestion.cursorAdjust == -1) {\r\n\t\tConsoleInputState.moveCursorLeft(/*word=*/false);\r\n\t}\r\n}\r\n\r\nbool ConsoleHandleEvent(const SDL_Event &event)\r\n{\r\n\tif (!IsConsoleVisible) {\r\n\t\t// Make console open on the top-left keyboard key even if it is not a backtick.\r\n\t\tif (event.type == SDL_EVENT_KEY_DOWN && SDLC_EventScancode(event) == SDL_SCANCODE_GRAVE) {\r\n\t\t\tOpenConsole();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\tif (HandleTextInputEvent(event, ConsoleInputState)) {\r\n\t\tCurrentInputTextState = InputTextState::Edited;\r\n\t\treturn true;\r\n\t}\r\n\tconst auto modState = SDL_GetModState();\r\n\tconst bool isShift = (modState & SDL_KMOD_SHIFT) != 0;\r\n\tswitch (event.type) {\r\n\tcase SDL_EVENT_KEY_DOWN:\r\n\t\tswitch (SDLC_EventKey(event)) {\r\n\t\tcase SDLK_ESCAPE:\r\n\t\t\tif (!AutocompleteSuggestions.empty()) {\r\n\t\t\t\tAutocompleteSuggestions.clear();\r\n\t\t\t\tAutocompleteSuggestionFocusIndex = -1;\r\n\t\t\t} else {\r\n\t\t\t\tCloseConsole();\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\tcase SDLK_UP:\r\n\t\t\tif (AutocompleteSuggestionFocusIndex != -1) {\r\n\t\t\t\tAutocompleteSuggestionFocusIndex = std::max(\r\n\t\t\t\t    0, AutocompleteSuggestionFocusIndex - 1);\r\n\t\t\t} else {\r\n\t\t\t\tisShift ? PrevOutput() : PrevInput();\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\tcase SDLK_DOWN:\r\n\t\t\tif (AutocompleteSuggestionFocusIndex != -1) {\r\n\t\t\t\tAutocompleteSuggestionFocusIndex = std::min(\r\n\t\t\t\t    static_cast<int>(AutocompleteSuggestions.size()) - 1,\r\n\t\t\t\t    AutocompleteSuggestionFocusIndex + 1);\r\n\t\t\t} else {\r\n\t\t\t\tisShift ? NextOutput() : NextInput();\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\tcase SDLK_TAB:\r\n\t\t\tif (AutocompleteSuggestionFocusIndex != -1) {\r\n\t\t\t\tAcceptSuggestion();\r\n\t\t\t\tCurrentInputTextState = InputTextState::Edited;\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\tcase SDLK_RETURN:\r\n\t\tcase SDLK_KP_ENTER:\r\n\t\t\tif (isShift) {\r\n\t\t\t\tConsoleInputState.type(\"\\n\");\r\n\t\t\t} else {\r\n\t\t\t\tif (AutocompleteSuggestionFocusIndex != -1) {\r\n\t\t\t\t\tAcceptSuggestion();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tSendInput();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tCurrentInputTextState = InputTextState::Edited;\r\n\t\t\treturn true;\r\n\t\tcase SDLK_PAGEUP:\r\n\t\t\t++PendingScrollPages;\r\n\t\t\treturn true;\r\n\t\tcase SDLK_PAGEDOWN:\r\n\t\t\t--PendingScrollPages;\r\n\t\t\treturn true;\r\n\t\tcase SDLK_L:\r\n\t\t\tClearConsole();\r\n\t\t\treturn true;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tbreak;\r\n#ifndef USE_SDL1\r\n\tcase SDL_EVENT_MOUSE_WHEEL:\r\n\t\tif (SDLC_EventWheelIntY(event) > 0) {\r\n\t\t\tScrollOffset += ScrollStep;\r\n\t\t} else if (SDLC_EventWheelIntY(event) < 0) {\r\n\t\t\tScrollOffset -= ScrollStep;\r\n\t\t}\r\n\t\treturn true;\r\n#else\r\n\tcase SDL_MOUSEBUTTONDOWN:\r\n\tcase SDL_MOUSEBUTTONUP:\r\n\t\tif (event.button.button == SDL_BUTTON_WHEELUP) {\r\n\t\t\tScrollOffset += ScrollStep;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (event.button.button == SDL_BUTTON_WHEELDOWN) {\r\n\t\t\tScrollOffset -= ScrollStep;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n#endif\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid DrawConsole(const Surface &out)\r\n{\r\n\tif (!IsConsoleVisible)\r\n\t\treturn;\r\n\r\n\tOuterRect.position = { 0, 0 };\r\n\tOuterRect.size = { out.w(), out.h() - GetMainPanel().size.height - 2 };\r\n\r\n\tconst std::string_view originalInputText = ConsoleInputState.value();\r\n\tif (CurrentInputTextState != InputTextState::UpToDate) {\r\n\t\tWrappedInputText = WordWrapString(StrCat(Prompt, originalInputText), OuterRect.size.width - 2 * TextPaddingX, TextFontSize, TextSpacing);\r\n\t\tif (CurrentInputTextState == InputTextState::RestoredFromHistory) {\r\n\t\t\tAutocompleteSuggestions.clear();\r\n\t\t} else {\r\n\t\t\tGetLuaAutocompleteSuggestions(originalInputText, ConsoleInputCursor.position, GetLuaReplEnvironment(), /*maxSuggestions=*/MaxSuggestions, AutocompleteSuggestions);\r\n\t\t}\r\n\t\tAutocompleteSuggestionsMaxWidth = -1;\r\n\t\tAutocompleteSuggestionFocusIndex = AutocompleteSuggestions.empty() ? -1 : 0;\r\n\t\tCurrentInputTextState = InputTextState::UpToDate;\r\n\t}\r\n\r\n\tconst int numLines = static_cast<int>(c_count(WrappedInputText, '\\n')) + 1;\r\n\tInputRectHeight = std::min(OuterRect.size.height, numLines * LineHeight + TextPaddingYTop + TextPaddingYBottom);\r\n\tconst int inputTextHeight = InputRectHeight - (TextPaddingYTop + TextPaddingYBottom);\r\n\r\n\tInputRect.position = { 0, OuterRect.size.height - InputRectHeight };\r\n\tInputRect.size = { OuterRect.size.width, InputRectHeight };\r\n\tconst Rectangle inputTextRect {\r\n\t\t{ InputRect.position.x + TextPaddingX, InputRect.position.y + TextPaddingYTop },\r\n\t\t{ InputRect.size.width - 2 * TextPaddingX, inputTextHeight }\r\n\t};\r\n\r\n\tif (FirstRender) {\r\n\t\tSDL_Rect sdlInputRect = MakeSdlRect(InputRect);\r\n\t\tSDL_SetTextInputArea(ghMainWnd, &sdlInputRect, static_cast<int>(ConsoleInputState.cursorPosition()));\r\n\t\tSDLC_StartTextInput(ghMainWnd);\r\n\t\tFirstRender = false;\r\n\t\tif (ConsoleLines.empty()) {\r\n\t\t\tInitConsole();\r\n\t\t}\r\n\t}\r\n\r\n\tconst Rectangle bgRect = OuterRect;\r\n\tDrawHalfTransparentRectTo(out, bgRect.position.x, bgRect.position.y, bgRect.size.width, bgRect.size.height);\r\n\r\n\tDrawConsoleLines(\r\n\t    out.subregion(\r\n\t        TextPaddingX,\r\n\t        TextPaddingYTop,\r\n\t        GetConsoleLinesInnerWidth(),\r\n\t        OuterRect.size.height - inputTextRect.size.height - 8));\r\n\r\n\tDrawHorizontalLine(out, InputRect.position - Displacement { 0, 1 }, InputRect.size.width, BorderColor);\r\n\tDrawInputText(\r\n\t    out,\r\n\t    Rectangle(\r\n\t        inputTextRect.position,\r\n\t        Size {\r\n\t            // Extra space for the cursor on the right:\r\n\t            inputTextRect.size.width + TextPaddingX,\r\n\t            // Extra space for letters like g.\r\n\t            inputTextRect.size.height + TextPaddingYBottom }),\r\n\t    originalInputText,\r\n\t    WrappedInputText);\r\n\r\n\tSDL_Rect sdlRect = MakeSdlRect(OuterRect);\r\n\tBltFast(&sdlRect, &sdlRect);\r\n}\r\n\r\nvoid InitConsole()\r\n{\r\n\tif (!ConsoleLines.empty())\r\n\t\treturn;\r\n\tConsolePrelude = LoadAsset(\"lua\\\\repl_prelude.lua\");\r\n\tAddInitialConsoleLines();\r\n\tif (ConsolePrelude->has_value())\r\n\t\tRunLuaReplLine(std::string_view(**ConsolePrelude));\r\n}\r\n\r\nvoid RunInConsole(std::string_view code)\r\n{\r\n\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Input, .text = StrCat(Prompt, code) });\r\n\ttl::expected<std::string, std::string> result = RunLuaReplLine(code);\r\n\r\n\tif (result.has_value()) {\r\n\t\tif (!result->empty()) {\r\n\t\t\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Output, .text = *std::move(result) });\r\n\t\t}\r\n\t} else {\r\n\t\tif (!result.error().empty()) {\r\n\t\t\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Error, .text = std::move(result).error() });\r\n\t\t} else {\r\n\t\t\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Error, .text = \"Unknown error\" });\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PrintToConsole(std::string_view text)\r\n{\r\n\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Output, .text = std::string(text) });\r\n}\r\n\r\nvoid PrintWarningToConsole(std::string_view text)\r\n{\r\n\tAddConsoleLine(ConsoleLine { .type = ConsoleLine::Warning, .text = std::string(text) });\r\n}\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/panels/console.hpp",
    "content": "#ifdef _DEBUG\r\n#pragma once\r\n\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid InitConsole();\r\nbool IsConsoleOpen();\r\nvoid OpenConsole();\r\nbool ConsoleHandleEvent(const SDL_Event &event);\r\nvoid DrawConsole(const Surface &out);\r\nvoid RunInConsole(std::string_view code);\r\nvoid PrintToConsole(std::string_view text);\r\nvoid PrintWarningToConsole(std::string_view text);\r\n\r\n} // namespace devilution\r\n#endif // _DEBUG\r\n"
  },
  {
    "path": "Source/panels/info_box.cpp",
    "content": "#include \"panels/info_box.hpp\"\r\n\r\n#include \"engine/load_cel.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteList pSTextBoxCels;\r\nOptionalOwnedClxSpriteList pSTextSlidCels;\r\n\r\nvoid InitInfoBoxGfx()\r\n{\r\n\tpSTextSlidCels = LoadCel(\"data\\\\textslid\", 12);\r\n\tpSTextBoxCels = LoadCel(\"data\\\\textbox2\", 271);\r\n}\r\n\r\nvoid FreeInfoBoxGfx()\r\n{\r\n\tpSTextBoxCels = std::nullopt;\r\n\tpSTextSlidCels = std::nullopt;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/info_box.hpp",
    "content": "#pragma once\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Fixed size info box frame\r\n *\r\n * Used in stores, the quest log, the help window, and the unique item info window.\r\n */\r\nextern OptionalOwnedClxSpriteList pSTextBoxCels;\r\n\r\n/**\r\n * @brief Dynamic size info box frame and scrollbar graphics.\r\n *\r\n * Used in stores and `DrawDiabloMsg`.\r\n */\r\nextern OptionalOwnedClxSpriteList pSTextSlidCels;\r\n\r\nvoid InitInfoBoxGfx();\r\nvoid FreeInfoBoxGfx();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/mainpanel.cpp",
    "content": "#include \"panels/mainpanel.hpp\"\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/surface_to_clx.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOptionalOwnedClxSpriteList PanelButtonDown;\r\nOptionalOwnedClxSpriteList TalkButton;\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList PanelButton;\r\nOptionalOwnedClxSpriteList PanelButtonGrime;\r\nOptionalOwnedClxSpriteList PanelButtonDownGrime;\r\n\r\nvoid DrawButtonText(const Surface &out, std::string_view text, Rectangle placement, UiFlags style, int spacing = 1)\r\n{\r\n\tDrawString(out, text, { placement.position + Displacement { 0, 1 }, placement.size },\r\n\t    { .flags = UiFlags::AlignCenter | UiFlags::KerningFitSpacing | UiFlags::ColorBlack, .spacing = spacing });\r\n\tDrawString(out, text, placement,\r\n\t    { .flags = UiFlags::AlignCenter | UiFlags::KerningFitSpacing | style, .spacing = spacing });\r\n}\r\n\r\nvoid DrawButtonOnPanel(Point position, std::string_view text, int frame)\r\n{\r\n\tRenderClxSprite(*BottomBuffer, (*PanelButton)[frame], position);\r\n\tint spacing = 2;\r\n\tint width = std::min<int>(GetLineWidth(text, GameFont12, spacing), (*PanelButton)[0].width());\r\n\tif (width > 38) {\r\n\t\tspacing = 1;\r\n\t\twidth = std::min<int>(GetLineWidth(text, GameFont12, spacing), (*PanelButton)[0].width());\r\n\t}\r\n\tRenderClxSprite(BottomBuffer->subregion(position.x + ((*PanelButton)[0].width() - width) / 2, position.y + 7, width, BottomBuffer->h() - 7), (*PanelButtonGrime)[frame], { 0, 0 });\r\n\tDrawButtonText(*BottomBuffer, text, { position, { (*PanelButton)[0].width(), 0 } }, UiFlags::ColorButtonface, spacing);\r\n}\r\n\r\nvoid RenderMainButton(const Surface &out, int buttonId, std::string_view text, int frame)\r\n{\r\n\tconst Point panelPosition { MainPanelButtonRect[buttonId].position + Displacement { 4, 17 } };\r\n\tDrawButtonOnPanel(panelPosition, text, frame);\r\n\tif (IsChatAvailable())\r\n\t\tDrawButtonOnPanel(panelPosition + Displacement { 0, GetMainPanel().size.height + 16 }, text, frame);\r\n\r\n\tconst Point position { 0, 19 * buttonId };\r\n\tint spacing = 2;\r\n\tint width = std::min<int>(GetLineWidth(text, GameFont12, spacing), (*PanelButton)[0].width());\r\n\tif (width > 38) {\r\n\t\tspacing = 1;\r\n\t\twidth = std::min<int>(GetLineWidth(text, GameFont12, spacing), (*PanelButton)[0].width());\r\n\t}\r\n\tRenderClxSprite(out.subregion(position.x + ((*PanelButton)[0].width() - width) / 2, position.y + 9, width, out.h() - position.y - 9), (*PanelButtonDownGrime)[frame], { 0, 0 });\r\n\tDrawButtonText(out, text, { position + Displacement { 0, 2 }, { out.w(), 0 } }, UiFlags::ColorButtonpushed, spacing);\r\n}\r\n\r\n} // namespace\r\n\r\ntl::expected<void, std::string> LoadMainPanel()\r\n{\r\n\tstd::optional<OwnedSurface> out;\r\n\tconstexpr uint16_t NumButtonSprites = 6;\r\n\t{\r\n\t\tASSIGN_OR_RETURN(OptionalOwnedClxSpriteList background, LoadClxWithStatus(\"data\\\\panel8bucp.clx\"));\r\n\t\tout.emplace((*background)[0].width(), (*background)[0].height() * NumButtonSprites);\r\n\t\tint y = 0;\r\n\t\tfor (const ClxSprite sprite : ClxSpriteList(*background)) {\r\n\t\t\tRenderClxSprite(*out, sprite, { 0, y });\r\n\t\t\ty += sprite.height();\r\n\t\t}\r\n\t}\r\n\r\n\tPanelButton = LoadOptionalClx(\"data\\\\panel8buc.clx\");\r\n\tPanelButtonGrime = LoadOptionalClx(\"data\\\\dirtybuc.clx\");\r\n\tPanelButtonDownGrime = LoadOptionalClx(\"data\\\\dirtybucp.clx\");\r\n\r\n\tRenderMainButton(*out, 0, _(\"char\"), 0);\r\n\tRenderMainButton(*out, 1, _(\"quests\"), 1);\r\n\tRenderMainButton(*out, 2, _(\"map\"), 1);\r\n\tRenderMainButton(*out, 3, _(\"menu\"), 0);\r\n\tRenderMainButton(*out, 4, _(\"inv\"), 1);\r\n\tRenderMainButton(*out, 5, _(\"spells\"), 0);\r\n\tPanelButtonDown = SurfaceToClx(*out, NumButtonSprites);\r\n\tout = std::nullopt;\r\n\r\n\tif (IsChatAvailable()) {\r\n\t\tOptionalOwnedClxSpriteList talkButton = LoadClx(\"data\\\\talkbutton.clx\");\r\n\t\tconst int talkButtonWidth = (*talkButton)[0].width();\r\n\r\n\t\tconstexpr size_t NumOtherPlayers = 3;\r\n\t\t// Render the unpressed voice buttons to BottomBuffer.\r\n\t\tconst std::string_view text = _(\"voice\");\r\n\t\tconst int textWidth = GetLineWidth(text, GameFont12, 1);\r\n\t\tfor (size_t i = 0; i < NumOtherPlayers; ++i) {\r\n\t\t\tconst Point position { 176, static_cast<int>(GetMainPanel().size.height + 101 + 18 * i) };\r\n\t\t\tRenderClxSprite(*BottomBuffer, (*talkButton)[0], position);\r\n\t\t\tconst int width = std::min<int>(textWidth, (*PanelButton)[0].width());\r\n\t\t\tRenderClxSprite(BottomBuffer->subregion(position.x + (talkButtonWidth - width) / 2, position.y + 6, width, 9), (*PanelButtonGrime)[1], { 0, 0 });\r\n\t\t\tDrawButtonText(*BottomBuffer, text, { position, { talkButtonWidth, 0 } }, UiFlags::ColorButtonface);\r\n\t\t}\r\n\r\n\t\tconst int talkButtonHeight = (*talkButton)[0].height();\r\n\t\tconstexpr uint16_t NumTalkButtonSprites = 3;\r\n\t\tconst OwnedSurface talkSurface(talkButtonWidth, talkButtonHeight * NumTalkButtonSprites);\r\n\r\n\t\t// Prerender translated versions of the other button states for voice buttons\r\n\t\tRenderClxSprite(talkSurface, (*talkButton)[0], { 0, 0 });                    // background for unpressed mute button\r\n\t\tRenderClxSprite(talkSurface, (*talkButton)[1], { 0, talkButtonHeight });     // background for pressed mute button\r\n\t\tRenderClxSprite(talkSurface, (*talkButton)[1], { 0, talkButtonHeight * 2 }); // background for pressed voice button\r\n\r\n\t\ttalkButton = std::nullopt;\r\n\r\n\t\tconst int muteWidth = GetLineWidth(_(\"mute\"), GameFont12, 2);\r\n\t\tRenderClxSprite(talkSurface.subregion((talkButtonWidth - muteWidth) / 2, 6, muteWidth, 9), (*PanelButtonGrime)[1], { 0, 0 });\r\n\t\tDrawButtonText(talkSurface, _(\"mute\"), { { 0, 0 }, { talkButtonWidth, 0 } }, UiFlags::ColorButtonface);\r\n\t\tRenderClxSprite(talkSurface.subregion((talkButtonWidth - muteWidth) / 2, 23, muteWidth, 9), (*PanelButtonGrime)[1], { 0, 0 });\r\n\t\tDrawButtonText(talkSurface, _(\"mute\"), { { 0, 17 }, { talkButtonWidth, 0 } }, UiFlags::ColorButtonpushed);\r\n\t\tconst int voiceWidth = GetLineWidth(_(\"voice\"), GameFont12, 2);\r\n\t\tRenderClxSprite(talkSurface.subregion((talkButtonWidth - voiceWidth) / 2, 39, voiceWidth, 9), (*PanelButtonGrime)[1], { 0, 0 });\r\n\t\tDrawButtonText(talkSurface, _(\"voice\"), { { 0, 33 }, { talkButtonWidth, 0 } }, UiFlags::ColorButtonpushed);\r\n\t\tTalkButton = SurfaceToClx(talkSurface, NumTalkButtonSprites);\r\n\t}\r\n\r\n\tPanelButtonDownGrime = std::nullopt;\r\n\tPanelButtonGrime = std::nullopt;\r\n\tPanelButton = std::nullopt;\r\n\treturn {};\r\n}\r\n\r\nvoid FreeMainPanel()\r\n{\r\n\tTalkButton = std::nullopt;\r\n\tPanelButtonDown = std::nullopt;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/mainpanel.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern OptionalOwnedClxSpriteList PanelButtonDown;\r\nextern OptionalOwnedClxSpriteList TalkButton;\r\n\r\ntl::expected<void, std::string> LoadMainPanel();\r\nvoid FreeMainPanel();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/partypanel.cpp",
    "content": "#include \"panels/partypanel.hpp\"\r\n\r\n#include <expected.hpp>\r\n#include <optional>\r\n\r\n#include \"automap.h\"\r\n#include \"control/control.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"inv.h\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"qol/monhealthbar.h\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/surface_to_clx.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct PartySpriteOffset {\r\n\tPoint inTownOffset;\r\n\tPoint inDungeonOffset;\r\n\tPoint isDeadOffset;\r\n};\r\n\r\nconst PartySpriteOffset ClassSpriteOffsets[] = {\r\n\t{ { -4, -18 }, { 6, -21 }, { -6, -50 } },\r\n\t{ { -2, -18 }, { 1, -20 }, { -8, -35 } },\r\n\t{ { -2, -16 }, { 3, -20 }, { 0, -50 } },\r\n\t{ { -2, -19 }, { 1, -19 }, { 28, -60 } }\r\n};\r\n\r\nOptionalOwnedClxSpriteList PartyMemberFrame;\r\nOptionalOwnedClxSpriteList PlayerTags;\r\n\r\nPoint PartyPanelPos = { 8, 8 };\r\nRectangle PortraitFrameRects[MAX_PLRS];\r\nint RightClickedPortraitIndex = -1;\r\nconstexpr int HealthBarHeight = 7;\r\nconstexpr int ManaBarHeight = 7;\r\nconstexpr int FrameGap = 15;\r\nconstexpr int FrameBorderSize = 3;\r\nconstexpr int FrameSpriteSize = 12;\r\nconstexpr Size FrameSections = { 4, 4 }; // x/y can't be less than 2\r\nconstexpr Size PortraitFrameSize = { FrameSections.width * FrameSpriteSize, FrameSections.height *FrameSpriteSize };\r\n\r\nconstexpr uint8_t FrameBackgroundColor = PAL16_BLUE + 14;\r\n\r\nvoid DrawBar(const Surface &out, Rectangle rect, uint8_t color)\r\n{\r\n\tfor (int x = 0; x < rect.size.width; x++) {\r\n\t\tDrawVerticalLine(out, { rect.position.x + x, rect.position.y }, rect.size.height, color);\r\n\t}\r\n}\r\n\r\nvoid DrawMemberFrame(const Surface &out, OwnedClxSpriteList &frame, Point pos)\r\n{\r\n\t// Draw the frame background\r\n\tFillRect(out, pos.x, pos.y, PortraitFrameSize.width, PortraitFrameSize.height, FrameBackgroundColor);\r\n\r\n\t// Now draw the frame border\r\n\tconst Size adjustedFrame = { FrameSections.width - 1, FrameSections.height - 1 };\r\n\tfor (int x = 0; x <= adjustedFrame.width; x++) {\r\n\t\tfor (int y = 0; y <= adjustedFrame.height; y++) {\r\n\t\t\t// Get what section of the frame we're drawing\r\n\t\t\tint spriteIndex = -1;\r\n\t\t\tif (x == 0 && y == 0)\r\n\t\t\t\tspriteIndex = 0; // Top-left corner\r\n\t\t\telse if (x == 0 && y == adjustedFrame.height)\r\n\t\t\t\tspriteIndex = 1; // Bottom-left corner\r\n\t\t\telse if (x == adjustedFrame.width && y == adjustedFrame.height)\r\n\t\t\t\tspriteIndex = 2; // Bottom-right corner\r\n\t\t\telse if (x == adjustedFrame.width && y == 0)\r\n\t\t\t\tspriteIndex = 3; // Top-right corner\r\n\t\t\telse if (y == 0)\r\n\t\t\t\tspriteIndex = 4; // Top border\r\n\t\t\telse if (x == 0)\r\n\t\t\t\tspriteIndex = 5; // Left border\r\n\t\t\telse if (y == adjustedFrame.height)\r\n\t\t\t\tspriteIndex = 6; // Bottom border\r\n\t\t\telse if (x == adjustedFrame.width)\r\n\t\t\t\tspriteIndex = 7; // Right border\r\n\r\n\t\t\tif (spriteIndex != -1) {\r\n\t\t\t\t// Draw the frame section\r\n\t\t\t\tRenderClxSprite(out, frame[spriteIndex], { pos.x + (x * FrameSpriteSize), pos.y + (y * FrameSpriteSize) });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid HandleRightClickPortait()\r\n{\r\n\tPlayer &player = Players[RightClickedPortraitIndex];\r\n\tif (player.plractive && &player != MyPlayer) {\r\n\t\tInspectPlayer = &player;\r\n\t\tOpenCharPanel();\r\n\t\tif (!SpellbookFlag)\r\n\t\t\tinvflag = true;\r\n\t\tRedrawEverything();\r\n\t\tRightClickedPortraitIndex = -1;\r\n\t}\r\n}\r\n\r\nPartySpriteOffset GetClassSpriteOffset(HeroClass hClass)\r\n{\r\n\tswitch (hClass) {\r\n\tcase HeroClass::Bard:\r\n\t\thClass = HeroClass::Rogue;\r\n\t\tbreak;\r\n\tcase HeroClass::Barbarian:\r\n\t\thClass = HeroClass::Warrior;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\treturn ClassSpriteOffsets[static_cast<size_t>(hClass)];\r\n}\r\n\r\n} // namespace\r\n\r\nbool PartySidePanelOpen = true;\r\nbool InspectingFromPartyPanel;\r\nint PortraitIdUnderCursor = -1;\r\n\r\ntl::expected<void, std::string> LoadPartyPanel()\r\n{\r\n\tASSIGN_OR_RETURN(OwnedClxSpriteList frame, LoadCelWithStatus(\"data\\\\textslid\", FrameSpriteSize));\r\n\tASSIGN_OR_RETURN(PlayerTags, LoadClxWithStatus(\"data\\\\monstertags.clx\"));\r\n\tconst OwnedSurface out(PortraitFrameSize.width, PortraitFrameSize.height + HealthBarHeight + ManaBarHeight);\r\n\r\n\t// Draw the health bar background\r\n\tDrawBar(out, { { 0, 0 }, { PortraitFrameSize.width, HealthBarHeight } }, PAL16_GRAY + 10);\r\n\t// Draw the frame the character portrait sprite will go\r\n\tDrawMemberFrame(out, frame, { 0, HealthBarHeight });\r\n\t// Draw the mana bar background\r\n\tDrawBar(out, { { 0, HealthBarHeight + PortraitFrameSize.height }, { PortraitFrameSize.width, ManaBarHeight } }, PAL16_GRAY + 10);\r\n\r\n\tPartyMemberFrame = SurfaceToClx(out);\r\n\r\n\treturn {};\r\n}\r\n\r\nvoid FreePartyPanel()\r\n{\r\n\tPartyMemberFrame = std::nullopt;\r\n\tPlayerTags = std::nullopt;\r\n}\r\n\r\nvoid DrawPartyMemberInfoPanel(const Surface &out)\r\n{\r\n\t// Don't draw based on these criteria\r\n\tif (CharFlag || !gbIsMultiplayer || !MyPlayer->friendlyMode || IsPlayerInStore() || IsStashOpen) {\r\n\t\tif (PortraitIdUnderCursor != -1)\r\n\t\t\tPortraitIdUnderCursor = -1;\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tPoint pos = PartyPanelPos;\r\n\tif (AutomapActive)\r\n\t\tpos.y += (FrameGap * 4);\r\n\tif (*GetOptions().Graphics.showFPS)\r\n\t\tpos.y += FrameGap;\r\n\r\n\tint currentLongestNameWidth = PortraitFrameSize.width;\r\n\tbool portraitUnderCursor = false;\r\n\r\n\tfor (Player &player : Players) {\r\n\r\n\t\tif (!player.plractive || !player.friendlyMode)\r\n\t\t\tcontinue;\r\n\r\n#ifndef _DEBUG\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tcontinue;\r\n#endif\r\n\t\t// Get the rect of the portrait to use later\r\n\t\tconst Rectangle currentPortraitRect = { pos, PortraitFrameSize };\r\n\r\n\t\tconst Surface gameScreen = out.subregionY(0, gnViewportHeight);\r\n\r\n\t\t// Draw the characters frame\r\n\t\tRenderClxSprite(gameScreen, (*PartyMemberFrame)[0], pos);\r\n\r\n\t\t// Get the players remaining life\r\n\t\t// If the player is using mana shield change the color\r\n\t\tconst int lifeTicks = ((player._pHitPoints * PortraitFrameSize.width) + (player._pMaxHP / 2)) / player._pMaxHP;\r\n\t\tconst uint8_t hpBarColor = (player.pManaShield) ? PAL8_YELLOW + 5 : PAL8_RED + 4;\r\n\t\t// Now draw the characters remaining life\r\n\t\tDrawBar(gameScreen, { pos, { lifeTicks, HealthBarHeight } }, hpBarColor);\r\n\r\n\t\t// Add to the position before continuing to the next item\r\n\t\tpos.y += HealthBarHeight;\r\n\r\n\t\t// Get the players current portrait sprite\r\n\t\tconst ClxSprite playerPortraitSprite = GetPlayerPortraitSprite(player);\r\n\t\t// Get the offset of the sprite based on the players class so it get's rendered in the correct position\r\n\t\tconst PartySpriteOffset offsets = GetClassSpriteOffset(player._pClass);\r\n\t\tPoint offset = (player.isOnLevel(0)) ? offsets.inTownOffset : offsets.inDungeonOffset;\r\n\r\n\t\tif (player._pHitPoints <= 0 && IsPlayerUnarmed(player))\r\n\t\t\toffset = offsets.isDeadOffset;\r\n\r\n\t\t// Calculate the players portait position\r\n\t\tconst Point portraitPos = { ((-(playerPortraitSprite.width() / 2)) + (PortraitFrameSize.width / 2)) + offset.x, offset.y };\r\n\t\t// Get a subregion of the surface so the portrait doesn't get drawn over the frame\r\n\t\tconst Surface frameSubregion = gameScreen.subregion(\r\n\t\t    pos.x + FrameBorderSize,\r\n\t\t    pos.y + FrameBorderSize,\r\n\t\t    PortraitFrameSize.width - (FrameBorderSize * 2),\r\n\t\t    PortraitFrameSize.height - (FrameBorderSize * 2));\r\n\r\n\t\tPortraitFrameRects[player.getId()] = {\r\n\t\t\t{ frameSubregion.region.x, frameSubregion.region.y },\r\n\t\t\t{ frameSubregion.region.w, frameSubregion.region.h }\r\n\t\t};\r\n\r\n\t\t// Draw the portrait sprite\r\n\t\tRenderClxSprite(\r\n\t\t    frameSubregion,\r\n\t\t    playerPortraitSprite,\r\n\t\t    portraitPos);\r\n\r\n\t\tif ((player.getId() + 1U) < (*PlayerTags).numSprites()) {\r\n\t\t\t// Draw the player tag\r\n\t\t\tconst int tagWidth = (*PlayerTags)[player.getId() + 1].width();\r\n\t\t\tRenderClxSprite(\r\n\t\t\t    frameSubregion,\r\n\t\t\t    (*PlayerTags)[player.getId() + 1],\r\n\t\t\t    { PortraitFrameSize.width - (tagWidth + (tagWidth / 2)), 0 });\r\n\t\t}\r\n\r\n\t\t// Check to see if the player is dead and if so we draw a half transparent red rect over the portrait\r\n\t\tif (player._pHitPoints <= 0) {\r\n\t\t\tDrawHalfTransparentRectTo(\r\n\t\t\t    frameSubregion,\r\n\t\t\t    0, 0,\r\n\t\t\t    PortraitFrameSize.width,\r\n\t\t\t    PortraitFrameSize.height,\r\n\t\t\t    PAL8_RED + 4);\r\n\t\t}\r\n\r\n\t\t// Add to the position before continuing to the next item\r\n\t\tpos.y += PortraitFrameSize.height;\r\n\r\n\t\t// Get the players remaining mana\r\n\t\tconst int manaTicks = ((player._pMana * PortraitFrameSize.width) + (player._pMaxMana / 2)) / player._pMaxMana;\r\n\t\tconst uint8_t manaBarColor = PAL8_BLUE + 3;\r\n\t\t// Now draw the characters remaining mana\r\n\t\tDrawBar(gameScreen, { pos, { manaTicks, ManaBarHeight } }, manaBarColor);\r\n\r\n\t\t// Add to the position before continuing to the next item\r\n\t\tpos.y += ManaBarHeight;\r\n\r\n\t\t// Draw the players name under the frame\r\n\t\tDrawString(\r\n\t\t    gameScreen,\r\n\t\t    player._pName,\r\n\t\t    pos,\r\n\t\t    { .flags = UiFlags::ColorGold | UiFlags::Outlined | UiFlags::FontSize12 });\r\n\r\n\t\t// Add to the position before continuing onto the next player\r\n\t\tpos.y += FrameGap + 5;\r\n\r\n\t\t// Check to see if the player is hovering over this portrait and if so draw a string under the cursor saying they can right click to inspect\r\n\t\tif (currentPortraitRect.contains(MousePosition)) {\r\n\t\t\tPortraitIdUnderCursor = player.getId();\r\n\t\t\tportraitUnderCursor = true;\r\n\t\t}\r\n\r\n\t\t// Get the current players name width\r\n\t\tconst int width = GetLineWidth(player._pName);\r\n\t\t// Now check to see if it's the current longest name\r\n\t\tif (width >= currentLongestNameWidth)\r\n\t\t\tcurrentLongestNameWidth = width;\r\n\r\n\t\t// Check to see if the Y position is more then the main panel position\r\n\t\tif (pos.y >= GetMainPanel().position.y - PortraitFrameSize.height - 10) {\r\n\t\t\t// If so we need to draw the next set of portraits back at the top and to the right of the original position\r\n\t\t\tpos.y = PartyPanelPos.y;\r\n\t\t\tif (AutomapActive)\r\n\t\t\t\tpos.y += (FrameGap * 4);\r\n\t\t\tif (*GetOptions().Graphics.showFPS)\r\n\t\t\t\tpos.y += FrameGap;\r\n\t\t\t// Add the current longest name width to the X position\r\n\t\t\tpos.x += currentLongestNameWidth + (FrameGap / 2);\r\n\t\t}\r\n\t}\r\n\r\n\tif (RightClickedPortraitIndex != -1)\r\n\t\tHandleRightClickPortait();\r\n\r\n\tif (!portraitUnderCursor)\r\n\t\tPortraitIdUnderCursor = -1;\r\n}\r\n\r\nbool DidRightClickPartyPortrait()\r\n{\r\n\tfor (size_t i = 0; i < sizeof(PortraitFrameRects) / sizeof(PortraitFrameRects[0]); i++) {\r\n\t\tif (PortraitFrameRects[i].contains(MousePosition)) {\r\n\t\t\tRightClickedPortraitIndex = static_cast<int>(i);\r\n\t\t\tInspectingFromPartyPanel = true;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/partypanel.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern bool PartySidePanelOpen;\r\nextern bool InspectingFromPartyPanel;\r\nextern int PortraitIdUnderCursor;\r\n\r\ntl::expected<void, std::string> LoadPartyPanel();\r\nvoid FreePartyPanel();\r\nvoid DrawPartyMemberInfoPanel(const Surface &out);\r\nbool DidRightClickPartyPortrait();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/spell_book.cpp",
    "content": "#include \"panels/spell_book.hpp\"\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n#include <fmt/format.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"missiles.h\"\r\n#include \"panels/spell_icons.hpp\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"player.h\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/status_macros.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList spellBookButtons;\r\nOptionalOwnedClxSpriteList spellBookBackground;\r\n\r\nconst size_t SpellBookPages = 6;\r\nconst size_t SpellBookPageEntries = 7;\r\n\r\nconstexpr uint16_t SpellBookButtonWidthDiablo = 76;\r\nconstexpr uint16_t SpellBookButtonWidthHellfire = 61;\r\n\r\nuint16_t SpellBookButtonWidth()\r\n{\r\n\treturn gbIsHellfire ? SpellBookButtonWidthHellfire : SpellBookButtonWidthDiablo;\r\n}\r\n\r\n/** Maps from spellbook page number and position to SpellID. */\r\nconst SpellID SpellPages[SpellBookPages][SpellBookPageEntries] = {\r\n\t{ SpellID::Null, SpellID::Firebolt, SpellID::ChargedBolt, SpellID::HolyBolt, SpellID::Healing, SpellID::HealOther, SpellID::Inferno },\r\n\t{ SpellID::Resurrect, SpellID::FireWall, SpellID::Telekinesis, SpellID::Lightning, SpellID::TownPortal, SpellID::Flash, SpellID::StoneCurse },\r\n\t{ SpellID::Phasing, SpellID::ManaShield, SpellID::Elemental, SpellID::Fireball, SpellID::FlameWave, SpellID::ChainLightning, SpellID::Guardian },\r\n\t{ SpellID::Nova, SpellID::Golem, SpellID::Teleport, SpellID::Apocalypse, SpellID::BoneSpirit, SpellID::BloodStar, SpellID::Etherealize },\r\n\t{ SpellID::LightningWall, SpellID::Immolation, SpellID::Warp, SpellID::Reflect, SpellID::Berserk, SpellID::RingOfFire, SpellID::Search },\r\n\t{ SpellID::Invalid, SpellID::Invalid, SpellID::Invalid, SpellID::Invalid, SpellID::Invalid, SpellID::Invalid, SpellID::Invalid }\r\n};\r\n\r\nSpellID GetSpellFromSpellPage(size_t page, size_t entry)\r\n{\r\n\tassert(page <= SpellBookPages && entry <= SpellBookPageEntries);\r\n\tif (page == 0 && entry == 0)\r\n\t\treturn GetPlayerStartingLoadoutForClass(InspectPlayer->_pClass).skill;\r\n\treturn SpellPages[page][entry];\r\n}\r\n\r\nconstexpr Size SpellBookDescription { 250, 43 };\r\nconstexpr int SpellBookDescriptionPaddingHorizontal = 2;\r\n\r\nvoid PrintSBookStr(const Surface &out, Point position, std::string_view text, UiFlags flags = UiFlags::None)\r\n{\r\n\tDrawString(out, text,\r\n\t    Rectangle(GetPanelPosition(UiPanels::Spell, position + Displacement { SPLICONLENGTH, 0 }),\r\n\t        SpellBookDescription)\r\n\t        .inset({ SpellBookDescriptionPaddingHorizontal, 0 }),\r\n\t    { .flags = UiFlags::ColorWhite | flags });\r\n}\r\n\r\nSpellType GetSBookTrans(SpellID ii, bool townok)\r\n{\r\n\tconst Player &player = *InspectPlayer;\r\n\tif (ii == GetPlayerStartingLoadoutForClass(player._pClass).skill)\r\n\t\treturn SpellType::Skill;\r\n\tSpellType st = SpellType::Spell;\r\n\tif ((player._pISpells & GetSpellBitmask(ii)) != 0) {\r\n\t\tst = SpellType::Charges;\r\n\t}\r\n\tif ((player._pAblSpells & GetSpellBitmask(ii)) != 0) {\r\n\t\tst = SpellType::Skill;\r\n\t}\r\n\tif (st == SpellType::Spell) {\r\n\t\tif (CheckSpell(*InspectPlayer, ii, st, true) != SpellCheckResult::Success) {\r\n\t\t\tst = SpellType::Invalid;\r\n\t\t}\r\n\t\tif (player.GetSpellLevel(ii) == 0) {\r\n\t\t\tst = SpellType::Invalid;\r\n\t\t}\r\n\t}\r\n\tif (townok && leveltype == DTYPE_TOWN && st != SpellType::Invalid && !GetSpellData(ii).isAllowedInTown()) {\r\n\t\tst = SpellType::Invalid;\r\n\t}\r\n\r\n\treturn st;\r\n}\r\n\r\nStringOrView GetSpellPowerText(SpellID spell, int spellLevel)\r\n{\r\n\tif (spellLevel == 0) {\r\n\t\treturn _(\"Unusable\");\r\n\t}\r\n\tif (spell == SpellID::BoneSpirit) {\r\n\t\treturn _(/* TRANSLATORS: UI constraints, keep short please.*/ \"Dmg: 1/3 target hp\");\r\n\t}\r\n\tconst auto [min, max] = GetDamageAmt(spell, spellLevel);\r\n\tif (min == -1) {\r\n\t\treturn StringOrView {};\r\n\t}\r\n\tif (spell == SpellID::Healing || spell == SpellID::HealOther) {\r\n\t\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: UI constraints, keep short please.*/ \"Heals: {:d} - {:d}\")), min, max);\r\n\t}\r\n\treturn fmt::format(fmt::runtime(_(/* TRANSLATORS: UI constraints, keep short please.*/ \"Damage: {:d} - {:d}\")), min, max);\r\n}\r\n\r\n} // namespace\r\n\r\ntl::expected<void, std::string> InitSpellBook()\r\n{\r\n\tASSIGN_OR_RETURN(spellBookBackground, LoadCelWithStatus(\"data\\\\spellbk\", static_cast<uint16_t>(SidePanelSize.width)));\r\n\tASSIGN_OR_RETURN(spellBookButtons, LoadCelWithStatus(\"data\\\\spellbkb\", SpellBookButtonWidth()));\r\n\treturn LoadSmallSpellIcons();\r\n}\r\n\r\nvoid FreeSpellBook()\r\n{\r\n\tFreeSmallSpellIcons();\r\n\tspellBookButtons = std::nullopt;\r\n\tspellBookBackground = std::nullopt;\r\n}\r\n\r\nvoid DrawSpellBook(const Surface &out)\r\n{\r\n\tconstexpr int SpellBookButtonX = 7;\r\n\tconstexpr int SpellBookButtonY = 348;\r\n\tClxDraw(out, GetPanelPosition(UiPanels::Spell, { 0, 351 }), (*spellBookBackground)[0]);\r\n\tconst int buttonX = gbIsHellfire && SpellbookTab < 5\r\n\t    ? SpellBookButtonWidthHellfire * SpellbookTab\r\n\t    : SpellBookButtonWidthDiablo * SpellbookTab\r\n\t        // BUGFIX: rendering of page 3 and page 4 buttons are both off-by-one pixel (fixed).\r\n\t        + (SpellbookTab == 2 || SpellbookTab == 3 ? 1 : 0);\r\n\r\n\tClxDraw(out, GetPanelPosition(UiPanels::Spell, { SpellBookButtonX + buttonX, SpellBookButtonY }), (*spellBookButtons)[SpellbookTab]);\r\n\tconst Player &player = *InspectPlayer;\r\n\tconst uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells;\r\n\r\n\tconst int lineHeight = 18;\r\n\r\n\tint yp = 12;\r\n\tconst int textPaddingTop = 7;\r\n\tfor (size_t pageEntry = 0; pageEntry < SpellBookPageEntries; pageEntry++) {\r\n\t\tconst SpellID sn = GetSpellFromSpellPage(SpellbookTab, pageEntry);\r\n\t\tif (IsValidSpell(sn) && (spl & GetSpellBitmask(sn)) != 0) {\r\n\t\t\tconst SpellType st = GetSBookTrans(sn, true);\r\n\t\t\tSetSpellTrans(st);\r\n\t\t\tconst Point spellCellPosition = GetPanelPosition(UiPanels::Spell, { 11, yp + SpellBookDescription.height });\r\n\t\t\tDrawSmallSpellIcon(out, spellCellPosition, sn);\r\n\t\t\tif (sn == player._pRSpell && st == player._pRSplType && !IsInspectingPlayer()) {\r\n\t\t\t\tSetSpellTrans(SpellType::Skill);\r\n\t\t\t\tDrawSmallSpellIconBorder(out, spellCellPosition);\r\n\t\t\t}\r\n\r\n\t\t\tconst Point line0 { 0, yp + textPaddingTop };\r\n\t\t\tconst Point line1 { 0, yp + textPaddingTop + lineHeight };\r\n\t\t\tPrintSBookStr(out, line0, pgettext(\"spell\", GetSpellData(sn).sNameText));\r\n\t\t\tswitch (GetSBookTrans(sn, false)) {\r\n\t\t\tcase SpellType::Skill:\r\n\t\t\t\tPrintSBookStr(out, line1, _(\"Skill\"));\r\n\t\t\t\tbreak;\r\n\t\t\tcase SpellType::Charges: {\r\n\t\t\t\tconst int charges = player.InvBody[INVLOC_HAND_LEFT]._iCharges;\r\n\t\t\t\tPrintSBookStr(out, line1, fmt::format(fmt::runtime(ngettext(\"Staff ({:d} charge)\", \"Staff ({:d} charges)\", charges)), charges));\r\n\t\t\t} break;\r\n\t\t\tdefault: {\r\n\t\t\t\tconst int mana = GetManaAmount(player, sn) >> 6;\r\n\t\t\t\tconst int lvl = player.GetSpellLevel(sn);\r\n\t\t\t\tPrintSBookStr(out, line0, fmt::format(fmt::runtime(pgettext(/* TRANSLATORS: UI constraints, keep short please.*/ \"spellbook\", \"Level {:d}\")), lvl), UiFlags::AlignRight);\r\n\t\t\t\tif (const StringOrView text = GetSpellPowerText(sn, lvl); !text.empty()) {\r\n\t\t\t\t\tPrintSBookStr(out, line1, text, UiFlags::AlignRight);\r\n\t\t\t\t}\r\n\t\t\t\tPrintSBookStr(out, line1, fmt::format(fmt::runtime(pgettext(/* TRANSLATORS: UI constraints, keep short please.*/ \"spellbook\", \"Mana: {:d}\")), mana));\r\n\t\t\t} break;\r\n\t\t\t}\r\n\t\t}\r\n\t\typ += SpellBookDescription.height;\r\n\t}\r\n}\r\n\r\nvoid CheckSBook()\r\n{\r\n\t// Icons are drawn in a column near the left side of the panel and aligned with the spell book description entries\r\n\t// Spell icons/buttons are 37x38 pixels, laid out from 11,18 with a 5 pixel margin between each icon. This is close\r\n\t// enough to the height of the space given to spell descriptions that we can reuse that value and subtract the\r\n\t// padding from the end of the area.\r\n\tconst Rectangle iconArea = { GetPanelPosition(UiPanels::Spell, { 11, 18 }), Size { 37, SpellBookDescription.height * 7 - 5 } };\r\n\tif (iconArea.contains(MousePosition) && !IsInspectingPlayer()) {\r\n\t\tconst SpellID sn = GetSpellFromSpellPage(SpellbookTab, (MousePosition.y - iconArea.position.y) / SpellBookDescription.height);\r\n\t\tPlayer &player = *InspectPlayer;\r\n\t\tconst uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells;\r\n\t\tif (IsValidSpell(sn) && (spl & GetSpellBitmask(sn)) != 0) {\r\n\t\t\tSpellType st = SpellType::Spell;\r\n\t\t\tif ((player._pISpells & GetSpellBitmask(sn)) != 0) {\r\n\t\t\t\tst = SpellType::Charges;\r\n\t\t\t}\r\n\t\t\tif ((player._pAblSpells & GetSpellBitmask(sn)) != 0) {\r\n\t\t\t\tst = SpellType::Skill;\r\n\t\t\t}\r\n\t\t\tplayer._pRSpell = sn;\r\n\t\t\tplayer._pRSplType = st;\r\n\t\t\tRedrawEverything();\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\t// The width of the panel excluding the border is 305 pixels. This does not cleanly divide by 4 meaning Diablo tabs\r\n\t// end up with an extra pixel somewhere around the buttons. Vanilla Diablo had the buttons left-aligned, devilutionX\r\n\t// instead justifies the buttons and puts the gap between buttons 2/3. See DrawSpellBook\r\n\tconst int buttonWidth = SpellBookButtonWidth();\r\n\t// Tabs are drawn in a row near the bottom of the panel\r\n\tconst Rectangle tabArea = { GetPanelPosition(UiPanels::Spell, { 7, 320 }), Size { 305, 29 } };\r\n\tif (tabArea.contains(MousePosition)) {\r\n\t\tint hitColumn = MousePosition.x - tabArea.position.x;\r\n\t\t// Clicking on the gutter currently activates tab 3. Could make it do nothing by checking for == here and return early.\r\n\t\tif (!gbIsHellfire && hitColumn > buttonWidth * 2) {\r\n\t\t\t// Subtract 1 pixel to account for the gutter between buttons 2/3\r\n\t\t\thitColumn--;\r\n\t\t}\r\n\t\tSpellbookTab = hitColumn / buttonWidth;\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/spell_book.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\ntl::expected<void, std::string> InitSpellBook();\r\nvoid FreeSpellBook();\r\nvoid CheckSBook();\r\nvoid DrawSpellBook(const Surface &out);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/spell_icons.cpp",
    "content": "#include \"panels/spell_icons.hpp\"\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n#ifdef UNPACKED_MPQS\r\nOptionalOwnedClxSpriteList LargeSpellIconsBackground;\r\nOptionalOwnedClxSpriteList SmallSpellIconsBackground;\r\n#endif\r\n\r\nOptionalOwnedClxSpriteList SmallSpellIcons;\r\nOptionalOwnedClxSpriteList LargeSpellIcons;\r\n\r\nuint8_t SplTransTbl[256];\r\n\r\n/** Maps from SpellID to spelicon.cel frame number. */\r\nconst SpellIcon SpellITbl[] = {\r\n\t// clang-format off\r\n/* SpellID::Null             */ SpellIcon::Empty,\r\n/* SpellID::Firebolt         */ SpellIcon::Firebolt,\r\n/* SpellID::Healing          */ SpellIcon::Healing,\r\n/* SpellID::Lightning        */ SpellIcon::Lightning,\r\n/* SpellID::Flash            */ SpellIcon::Flash,\r\n/* SpellID::Identify         */ SpellIcon::Identify,\r\n/* SpellID::FireWall         */ SpellIcon::FireWall,\r\n/* SpellID::TownPortal       */ SpellIcon::TownPortal,\r\n/* SpellID::StoneCurse       */ SpellIcon::StoneCurse,\r\n/* SpellID::Infravision      */ SpellIcon::Infravision,\r\n/* SpellID::Phasing          */ SpellIcon::Phasing,\r\n/* SpellID::ManaShield       */ SpellIcon::ManaShield,\r\n/* SpellID::Fireball         */ SpellIcon::Fireball,\r\n/* SpellID::Guardian         */ SpellIcon::DoomSerpents,\r\n/* SpellID::ChainLightning   */ SpellIcon::ChainLightning,\r\n/* SpellID::FlameWave        */ SpellIcon::FlameWave,\r\n/* SpellID::DoomSerpents     */ SpellIcon::DoomSerpents,\r\n/* SpellID::BloodRitual      */ SpellIcon::BloodRitual,\r\n/* SpellID::Nova             */ SpellIcon::Nova,\r\n/* SpellID::Invisibility     */ SpellIcon::Invisibility,\r\n/* SpellID::Inferno          */ SpellIcon::Inferno,\r\n/* SpellID::Golem            */ SpellIcon::Golem,\r\n/* SpellID::Rage             */ SpellIcon::BloodBoil,\r\n/* SpellID::Teleport         */ SpellIcon::Teleport,\r\n/* SpellID::Apocalypse       */ SpellIcon::Apocalypse,\r\n/* SpellID::Etherealize      */ SpellIcon::Etherealize,\r\n/* SpellID::ItemRepair       */ SpellIcon::ItemRepair,\r\n/* SpellID::StaffRecharge    */ SpellIcon::StaffRecharge,\r\n/* SpellID::TrapDisarm       */ SpellIcon::TrapDisarm,\r\n/* SpellID::Elemental        */ SpellIcon::Elemental,\r\n/* SpellID::ChargedBolt      */ SpellIcon::ChargedBolt,\r\n/* SpellID::HolyBolt         */ SpellIcon::HolyBolt,\r\n/* SpellID::Resurrect        */ SpellIcon::Resurrect,\r\n/* SpellID::Telekinesis      */ SpellIcon::Telekinesis,\r\n/* SpellID::HealOther        */ SpellIcon::HealOther,\r\n/* SpellID::BloodStar        */ SpellIcon::BloodStar,\r\n/* SpellID::BoneSpirit       */ SpellIcon::BoneSpirit,\r\n/* SpellID::Mana             */ SpellIcon::Mana,\r\n/* SpellID::Magi             */ SpellIcon::Mana,\r\n/* SpellID::Jester           */ SpellIcon::Jester,\r\n/* SpellID::LightningWall    */ SpellIcon::LightningWall,\r\n/* SpellID::Immolation       */ SpellIcon::Immolation,\r\n/* SpellID::Warp             */ SpellIcon::Warp,\r\n/* SpellID::Reflect          */ SpellIcon::Reflect,\r\n/* SpellID::Berserk          */ SpellIcon::Berserk,\r\n/* SpellID::RingOfFire       */ SpellIcon::RingOfFire,\r\n/* SpellID::Search           */ SpellIcon::Search,\r\n/* SpellID::RuneOfFire       */ SpellIcon::PentaStar,\r\n/* SpellID::RuneOfLight      */ SpellIcon::PentaStar,\r\n/* SpellID::RuneOfNova       */ SpellIcon::PentaStar,\r\n/* SpellID::RuneOfImmolation */ SpellIcon::PentaStar,\r\n/* SpellID::RuneOfStone      */ SpellIcon::PentaStar,\r\n\t// clang-format on\r\n};\r\n\r\n} // namespace\r\n\r\ntl::expected<void, std::string> LoadLargeSpellIcons()\r\n{\r\n#ifdef UNPACKED_MPQS\r\n\tLargeSpellIcons = LoadOptionalClx(\"data\\\\spelicon_fg.clx\");\r\n\tLargeSpellIconsBackground = LoadOptionalClx(\"data\\\\spelicon_bg.clx\");\r\n\tif (!LargeSpellIcons.has_value() || !LargeSpellIconsBackground.has_value()) {\r\n\t\tASSIGN_OR_RETURN(LargeSpellIcons, LoadClxWithStatus(\"ctrlpan\\\\spelicon_fg.clx\"));\r\n\t\tASSIGN_OR_RETURN(LargeSpellIconsBackground, LoadClxWithStatus(\"ctrlpan\\\\spelicon_bg.clx\"));\r\n\t}\r\n#else\r\n\tLargeSpellIcons = LoadOptionalCel(\"data\\\\spelicon\", SPLICONLENGTH);\r\n\tif (!LargeSpellIcons.has_value()) {\r\n\t\tASSIGN_OR_RETURN(LargeSpellIcons, LoadCelWithStatus(\"ctrlpan\\\\spelicon\", SPLICONLENGTH));\r\n\t}\r\n#endif\r\n\tSetSpellTrans(SpellType::Skill);\r\n\treturn {};\r\n}\r\n\r\nvoid FreeLargeSpellIcons()\r\n{\r\n#ifdef UNPACKED_MPQS\r\n\tLargeSpellIconsBackground = std::nullopt;\r\n#endif\r\n\tLargeSpellIcons = std::nullopt;\r\n}\r\n\r\ntl::expected<void, std::string> LoadSmallSpellIcons()\r\n{\r\n#ifdef UNPACKED_MPQS\r\n\tASSIGN_OR_RETURN(SmallSpellIcons, LoadClxWithStatus(\"data\\\\spelli2_fg.clx\"));\r\n\tASSIGN_OR_RETURN(SmallSpellIconsBackground, LoadClxWithStatus(\"data\\\\spelli2_bg.clx\"));\r\n#else\r\n\tASSIGN_OR_RETURN(SmallSpellIcons, LoadCelWithStatus(\"data\\\\spelli2\", 37));\r\n#endif\r\n\treturn {};\r\n}\r\n\r\nvoid FreeSmallSpellIcons()\r\n{\r\n#ifdef UNPACKED_MPQS\r\n\tSmallSpellIconsBackground = std::nullopt;\r\n#endif\r\n\tSmallSpellIcons = std::nullopt;\r\n}\r\n\r\nuint8_t GetSpellIconFrame(SpellID spell)\r\n{\r\n\treturn static_cast<uint8_t>(SpellITbl[static_cast<int8_t>(spell)]);\r\n}\r\n\r\nvoid DrawLargeSpellIcon(const Surface &out, Point position, SpellID spell)\r\n{\r\n#ifdef UNPACKED_MPQS\r\n\tClxDrawTRN(out, position, (*LargeSpellIconsBackground)[0], SplTransTbl);\r\n#endif\r\n\tClxDrawTRN(out, position, (*LargeSpellIcons)[GetSpellIconFrame(spell)], SplTransTbl);\r\n}\r\n\r\nvoid DrawSmallSpellIcon(const Surface &out, Point position, SpellID spell)\r\n{\r\n#ifdef UNPACKED_MPQS\r\n\tClxDrawTRN(out, position, (*SmallSpellIconsBackground)[0], SplTransTbl);\r\n#endif\r\n\tClxDrawTRN(out, position, (*SmallSpellIcons)[GetSpellIconFrame(spell)], SplTransTbl);\r\n}\r\n\r\nvoid DrawLargeSpellIconBorder(const Surface &out, Point position, uint8_t color)\r\n{\r\n\tconst int width = (*LargeSpellIcons)[0].width();\r\n\tconst int height = (*LargeSpellIcons)[0].height();\r\n\tUnsafeDrawBorder2px(out, Rectangle { Point { position.x, position.y - height + 1 }, Size { width, height } }, color);\r\n}\r\n\r\nvoid DrawSmallSpellIconBorder(const Surface &out, Point position)\r\n{\r\n\tconst int width = (*SmallSpellIcons)[0].width();\r\n\tconst int height = (*SmallSpellIcons)[0].height();\r\n\tUnsafeDrawBorder2px(out, Rectangle { Point { position.x, position.y - height + 1 }, Size { width, height } }, SplTransTbl[PAL8_YELLOW + 2]);\r\n}\r\n\r\nvoid SetSpellTrans(SpellType t)\r\n{\r\n\tif (t == SpellType::Skill) {\r\n\t\tfor (int i = 0; i < 128; i++)\r\n\t\t\tSplTransTbl[i] = i;\r\n\t}\r\n\tfor (int i = 128; i < 256; i++)\r\n\t\tSplTransTbl[i] = i;\r\n\tSplTransTbl[255] = 0;\r\n\r\n\tswitch (t) {\r\n\tcase SpellType::Spell:\r\n\t\tSplTransTbl[PAL8_YELLOW] = PAL16_BLUE + 1;\r\n\t\tSplTransTbl[PAL8_YELLOW + 1] = PAL16_BLUE + 3;\r\n\t\tSplTransTbl[PAL8_YELLOW + 2] = PAL16_BLUE + 5;\r\n\t\tfor (int i = PAL16_BLUE; i < PAL16_BLUE + 16; i++) {\r\n\t\t\tSplTransTbl[PAL16_BEIGE - PAL16_BLUE + i] = i;\r\n\t\t\tSplTransTbl[PAL16_YELLOW - PAL16_BLUE + i] = i;\r\n\t\t\tSplTransTbl[PAL16_ORANGE - PAL16_BLUE + i] = i;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase SpellType::Scroll:\r\n\t\tSplTransTbl[PAL8_YELLOW] = PAL16_BEIGE + 1;\r\n\t\tSplTransTbl[PAL8_YELLOW + 1] = PAL16_BEIGE + 3;\r\n\t\tSplTransTbl[PAL8_YELLOW + 2] = PAL16_BEIGE + 5;\r\n\t\tfor (int i = PAL16_BEIGE; i < PAL16_BEIGE + 16; i++) {\r\n\t\t\tSplTransTbl[PAL16_YELLOW - PAL16_BEIGE + i] = i;\r\n\t\t\tSplTransTbl[PAL16_ORANGE - PAL16_BEIGE + i] = i;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase SpellType::Charges:\r\n\t\tSplTransTbl[PAL8_YELLOW] = PAL16_ORANGE + 1;\r\n\t\tSplTransTbl[PAL8_YELLOW + 1] = PAL16_ORANGE + 3;\r\n\t\tSplTransTbl[PAL8_YELLOW + 2] = PAL16_ORANGE + 5;\r\n\t\tfor (int i = PAL16_ORANGE; i < PAL16_ORANGE + 16; i++) {\r\n\t\t\tSplTransTbl[PAL16_BEIGE - PAL16_ORANGE + i] = i;\r\n\t\t\tSplTransTbl[PAL16_YELLOW - PAL16_ORANGE + i] = i;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase SpellType::Invalid:\r\n\t\tSplTransTbl[PAL8_YELLOW] = PAL16_GRAY + 1;\r\n\t\tSplTransTbl[PAL8_YELLOW + 1] = PAL16_GRAY + 3;\r\n\t\tSplTransTbl[PAL8_YELLOW + 2] = PAL16_GRAY + 5;\r\n\t\tfor (int i = PAL16_GRAY; i < PAL16_GRAY + 15; i++) {\r\n\t\t\tSplTransTbl[PAL16_BEIGE - PAL16_GRAY + i] = i;\r\n\t\t\tSplTransTbl[PAL16_YELLOW - PAL16_GRAY + i] = i;\r\n\t\t\tSplTransTbl[PAL16_ORANGE - PAL16_GRAY + i] = i;\r\n\t\t}\r\n\t\tSplTransTbl[PAL16_BEIGE + 15] = 0;\r\n\t\tSplTransTbl[PAL16_YELLOW + 15] = 0;\r\n\t\tSplTransTbl[PAL16_ORANGE + 15] = 0;\r\n\t\tbreak;\r\n\tcase SpellType::Skill:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/spell_icons.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"tables/spelldat.h\"\r\n\r\n#define SPLICONLENGTH 56\r\n\r\nnamespace devilution {\r\n\r\nenum class SpellIcon : uint8_t {\r\n\tFirebolt,\r\n\tHealing,\r\n\tLightning,\r\n\tFlash,\r\n\tIdentify,\r\n\tFireWall,\r\n\tTownPortal,\r\n\tStoneCurse,\r\n\tInfravision,\r\n\tHealOther,\r\n\tNova,\r\n\tFireball,\r\n\tManaShield,\r\n\tFlameWave,\r\n\tInferno,\r\n\tChainLightning,\r\n\tSentinel, // unused\r\n\tDoomSerpents,\r\n\tBloodRitual,  // unused\r\n\tInvisibility, // unused\r\n\tGolem,\r\n\tEtherealize,\r\n\tBloodBoil,\r\n\tTeleport,\r\n\tApocalypse,\r\n\tItemRepair,\r\n\tEmpty,\r\n\tPhasing,\r\n\tStaffRecharge,\r\n\tBoneSpirit,\r\n\tRedSkull,  // unused\r\n\tPentagram, // unused\r\n\tFireCloud, // unused\r\n\tLongHorn,  // unused\r\n\tPentaStar, // unused\r\n\tBloodStar,\r\n\tTrapDisarm,\r\n\tElemental,\r\n\tChargedBolt,\r\n\tTelekinesis,\r\n\tResurrect,\r\n\tHolyBolt,\r\n\tWarp,\r\n\tSearch,\r\n\tReflect,\r\n\tLightningWall,\r\n\tImmolation,\r\n\tBerserk,\r\n\tRingOfFire,\r\n\tJester,\r\n\tMana,\r\n};\r\n\r\n/**\r\n * Draw a large (56x56) spell icon onto the given buffer.\r\n *\r\n * @param out Output buffer.\r\n * @param position Buffer coordinates (bottom-left).\r\n * @param spell Spell ID.\r\n */\r\nvoid DrawLargeSpellIcon(const Surface &out, Point position, SpellID spell);\r\n\r\n/**\r\n * Draw a small (37x38) spell icon onto the given buffer.\r\n *\r\n * @param out Output buffer.\r\n * @param position Buffer coordinates (bottom-left).\r\n * @param spell Spell ID.\r\n */\r\nvoid DrawSmallSpellIcon(const Surface &out, Point position, SpellID spell);\r\n\r\n/**\r\n * Draw an inset 2px border for a large (56x56) spell icon.\r\n *\r\n * @param out Output buffer.\r\n * @param position Buffer coordinates (bottom-left).\r\n * @param spell Spell ID.\r\n */\r\nvoid DrawLargeSpellIconBorder(const Surface &out, Point position, uint8_t color);\r\n\r\n/**\r\n * Draw an inset 2px border for a small (37x38) spell icon.\r\n *\r\n * @param out Output buffer.\r\n * @param position Buffer coordinates (bottom-left).\r\n * @param spell Spell ID.\r\n */\r\nvoid DrawSmallSpellIconBorder(const Surface &out, Point position);\r\n\r\n/**\r\n * @brief Set the color mapping for the `Draw(Small|Large)SpellIcon(Border)` calls.\r\n */\r\nvoid SetSpellTrans(SpellType t);\r\n\r\ntl::expected<void, std::string> LoadLargeSpellIcons();\r\nvoid FreeLargeSpellIcons();\r\n\r\ntl::expected<void, std::string> LoadSmallSpellIcons();\r\nvoid FreeSmallSpellIcons();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/spell_list.cpp",
    "content": "#include \"panels/spell_list.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"inv_iterators.hpp\"\r\n#include \"options.h\"\r\n#include \"panels/spell_icons.hpp\"\r\n#include \"player.h\"\r\n#include \"spells.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#define SPLROWICONLS 10\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid PrintSBookSpellType(const Surface &out, Point position, std::string_view text, uint8_t rectColorIndex)\r\n{\r\n\tDrawLargeSpellIconBorder(out, position, rectColorIndex);\r\n\r\n\t// Align the spell type text with bottom of spell icon\r\n\tposition += Displacement { SPLICONLENGTH / 2 - GetLineWidth(text) / 2, (IsSmallFontTall() ? -19 : -15) };\r\n\r\n\t// Then draw the text over the top\r\n\tDrawString(out, text, position, { .flags = UiFlags::ColorWhite | UiFlags::Outlined });\r\n}\r\n\r\nvoid PrintSBookHotkey(const Surface &out, Point position, const std::string_view text)\r\n{\r\n\t// Align the hot key text with the top-right corner of the spell icon\r\n\tposition += Displacement { SPLICONLENGTH - (GetLineWidth(text.data()) + 5), 5 - SPLICONLENGTH };\r\n\r\n\t// Then draw the text over the top\r\n\tDrawString(out, text, position, { .flags = UiFlags::ColorWhite | UiFlags::Outlined });\r\n}\r\n\r\nbool GetSpellListSelection(SpellID &pSpell, SpellType &pSplType)\r\n{\r\n\tpSpell = SpellID::Invalid;\r\n\tpSplType = SpellType::Invalid;\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tfor (auto &spellListItem : GetSpellListItems()) {\r\n\t\tif (spellListItem.isSelected) {\r\n\t\t\tpSpell = spellListItem.id;\r\n\t\t\tpSplType = spellListItem.type;\r\n\t\t\tif (spellListItem.id == GetPlayerStartingLoadoutForClass(myPlayer._pClass).skill)\r\n\t\t\t\tpSplType = SpellType::Skill;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nstd::optional<std::string_view> GetHotkeyName(SpellID spellId, SpellType spellType, bool useShortName = false)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tfor (size_t t = 0; t < NumHotkeys; t++) {\r\n\t\tif (myPlayer._pSplHotKey[t] != spellId || myPlayer._pSplTHotKey[t] != spellType)\r\n\t\t\tcontinue;\r\n\t\tauto quickSpellActionKey = StrCat(\"QuickSpell\", t + 1);\r\n\t\tif (ControlMode == ControlTypes::Gamepad)\r\n\t\t\treturn GetOptions().Padmapper.InputNameForAction(quickSpellActionKey, useShortName);\r\n\t\treturn GetOptions().Keymapper.KeyNameForAction(quickSpellActionKey);\r\n\t}\r\n\treturn {};\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DrawSpell(const Surface &out)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tSpellID spl = myPlayer._pRSpell;\r\n\tSpellType st = myPlayer._pRSplType;\r\n\r\n\tif (!IsValidSpell(spl)) {\r\n\t\tst = SpellType::Invalid;\r\n\t\tspl = SpellID::Null;\r\n\t}\r\n\r\n\tif (st == SpellType::Spell) {\r\n\t\tconst int tlvl = myPlayer.GetSpellLevel(spl);\r\n\t\tif (CheckSpell(*MyPlayer, spl, st, true) != SpellCheckResult::Success)\r\n\t\t\tst = SpellType::Invalid;\r\n\t\tif (tlvl <= 0)\r\n\t\t\tst = SpellType::Invalid;\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_TOWN && st != SpellType::Invalid && !GetSpellData(spl).isAllowedInTown())\r\n\t\tst = SpellType::Invalid;\r\n\r\n\tSetSpellTrans(st);\r\n\tconst Point position = GetMainPanel().position + Displacement { 565, 119 };\r\n\tDrawLargeSpellIcon(out, position, spl);\r\n\r\n\tstd::optional<std::string_view> hotkeyName = GetHotkeyName(spl, myPlayer._pRSplType, true);\r\n\tif (hotkeyName)\r\n\t\tPrintSBookHotkey(out, position, *hotkeyName);\r\n}\r\n\r\nvoid DrawSpellList(const Surface &out)\r\n{\r\n\tInfoString = StringOrView {};\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tfor (auto &spellListItem : GetSpellListItems()) {\r\n\t\tconst SpellID spellId = spellListItem.id;\r\n\t\tSpellType transType = spellListItem.type;\r\n\t\tint spellLevel = 0;\r\n\t\tconst SpellData &spellDataItem = GetSpellData(spellListItem.id);\r\n\t\tif (leveltype == DTYPE_TOWN && !spellDataItem.isAllowedInTown()) {\r\n\t\t\ttransType = SpellType::Invalid;\r\n\t\t}\r\n\t\tif (spellListItem.type == SpellType::Spell) {\r\n\t\t\tspellLevel = myPlayer.GetSpellLevel(spellListItem.id);\r\n\t\t\tif (spellLevel == 0)\r\n\t\t\t\ttransType = SpellType::Invalid;\r\n\t\t}\r\n\r\n\t\tSetSpellTrans(transType);\r\n\t\tDrawLargeSpellIcon(out, spellListItem.location, spellId);\r\n\r\n\t\tstd::optional<std::string_view> shortHotkeyName = GetHotkeyName(spellId, spellListItem.type, true);\r\n\r\n\t\tif (shortHotkeyName)\r\n\t\t\tPrintSBookHotkey(out, spellListItem.location, *shortHotkeyName);\r\n\r\n\t\tif (!spellListItem.isSelected)\r\n\t\t\tcontinue;\r\n\r\n\t\tuint8_t spellColor = PAL16_GRAY + 5;\r\n\r\n\t\tswitch (spellListItem.type) {\r\n\t\tcase SpellType::Skill:\r\n\t\t\tspellColor = PAL16_YELLOW - 46;\r\n\t\t\tPrintSBookSpellType(out, spellListItem.location, _(\"Skill\"), spellColor);\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"{:s} Skill\")), pgettext(\"spell\", spellDataItem.sNameText));\r\n\t\t\tbreak;\r\n\t\tcase SpellType::Spell:\r\n\t\t\tif (!myPlayer.isOnLevel(0)) {\r\n\t\t\t\tspellColor = PAL16_BLUE + 5;\r\n\t\t\t}\r\n\t\t\tPrintSBookSpellType(out, spellListItem.location, _(\"Spell\"), spellColor);\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"{:s} Spell\")), pgettext(\"spell\", spellDataItem.sNameText));\r\n\t\t\tif (spellId == SpellID::HolyBolt) {\r\n\t\t\t\tAddInfoBoxString(_(\"Damages undead only\"));\r\n\t\t\t}\r\n\t\t\tif (spellLevel == 0)\r\n\t\t\t\tAddInfoBoxString(_(\"Spell Level 0 - Unusable\"));\r\n\t\t\telse\r\n\t\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Spell Level {:d}\")), spellLevel));\r\n\t\t\tbreak;\r\n\t\tcase SpellType::Scroll: {\r\n\t\t\tif (!myPlayer.isOnLevel(0)) {\r\n\t\t\t\tspellColor = PAL16_RED - 59;\r\n\t\t\t}\r\n\t\t\tPrintSBookSpellType(out, spellListItem.location, _(\"Scroll\"), spellColor);\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Scroll of {:s}\")), pgettext(\"spell\", spellDataItem.sNameText));\r\n\t\t\tconst int scrollCount = c_count_if(InventoryAndBeltPlayerItemsRange { myPlayer }, [spellId](const Item &item) {\r\n\t\t\t\treturn item.isScrollOf(spellId);\r\n\t\t\t});\r\n\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(ngettext(\"{:d} Scroll\", \"{:d} Scrolls\", scrollCount)), scrollCount));\r\n\t\t} break;\r\n\t\tcase SpellType::Charges: {\r\n\t\t\tif (!myPlayer.isOnLevel(0)) {\r\n\t\t\t\tspellColor = PAL16_ORANGE + 5;\r\n\t\t\t}\r\n\t\t\tPrintSBookSpellType(out, spellListItem.location, _(\"Staff\"), spellColor);\r\n\t\t\tInfoString = fmt::format(fmt::runtime(_(\"Staff of {:s}\")), pgettext(\"spell\", spellDataItem.sNameText));\r\n\t\t\tint charges = myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges;\r\n\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(ngettext(\"{:d} Charge\", \"{:d} Charges\", charges)), charges));\r\n\t\t} break;\r\n\t\tcase SpellType::Invalid:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tstd::optional<std::string_view> fullHotkeyName = GetHotkeyName(spellId, spellListItem.type);\r\n\t\tif (fullHotkeyName) {\r\n\t\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Spell Hotkey {:s}\")), *fullHotkeyName));\r\n\t\t}\r\n\t}\r\n}\r\n\r\nstd::vector<SpellListItem> GetSpellListItems()\r\n{\r\n\tstd::vector<SpellListItem> spellListItems;\r\n\r\n\tuint64_t mask;\r\n\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\r\n\tint x = mainPanelPosition.x + 12 + SPLICONLENGTH * SPLROWICONLS;\r\n\tint y = mainPanelPosition.y - 17;\r\n\r\n\tfor (auto i : enum_values<SpellType>()) {\r\n\t\tconst Player &myPlayer = *MyPlayer;\r\n\t\tswitch (static_cast<SpellType>(i)) {\r\n\t\tcase SpellType::Skill:\r\n\t\t\tmask = myPlayer._pAblSpells;\r\n\t\t\tbreak;\r\n\t\tcase SpellType::Spell:\r\n\t\t\tmask = myPlayer._pMemSpells;\r\n\t\t\tbreak;\r\n\t\tcase SpellType::Scroll:\r\n\t\t\tmask = myPlayer._pScrlSpells;\r\n\t\t\tbreak;\r\n\t\tcase SpellType::Charges:\r\n\t\t\tmask = myPlayer._pISpells;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tint8_t j = static_cast<int8_t>(SpellID::Firebolt);\r\n\t\tfor (uint64_t spl = 1; static_cast<size_t>(j) < SpellsData.size(); spl <<= 1, j++) {\r\n\t\t\tif ((mask & spl) == 0)\r\n\t\t\t\tcontinue;\r\n\t\t\tconst int lx = x;\r\n\t\t\tconst int ly = y - SPLICONLENGTH;\r\n\t\t\tconst bool isSelected = (MousePosition.x >= lx && MousePosition.x < lx + SPLICONLENGTH && MousePosition.y >= ly && MousePosition.y < ly + SPLICONLENGTH);\r\n\t\t\tspellListItems.emplace_back(SpellListItem { { x, y }, static_cast<SpellType>(i), static_cast<SpellID>(j), isSelected });\r\n\t\t\tx -= SPLICONLENGTH;\r\n\t\t\tif (x == mainPanelPosition.x + 12 - SPLICONLENGTH) {\r\n\t\t\t\tx = mainPanelPosition.x + 12 + SPLICONLENGTH * SPLROWICONLS;\r\n\t\t\t\ty -= SPLICONLENGTH;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (mask != 0 && x != mainPanelPosition.x + 12 + SPLICONLENGTH * SPLROWICONLS)\r\n\t\t\tx -= SPLICONLENGTH;\r\n\t\tif (x == mainPanelPosition.x + 12 - SPLICONLENGTH) {\r\n\t\t\tx = mainPanelPosition.x + 12 + SPLICONLENGTH * SPLROWICONLS;\r\n\t\t\ty -= SPLICONLENGTH;\r\n\t\t}\r\n\t}\r\n\r\n\treturn spellListItems;\r\n}\r\n\r\nvoid SetSpell()\r\n{\r\n\tSpellID pSpell;\r\n\tSpellType pSplType;\r\n\r\n\tSpellSelectFlag = false;\r\n\tif (!GetSpellListSelection(pSpell, pSplType)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tmyPlayer._pRSpell = pSpell;\r\n\tmyPlayer._pRSplType = pSplType;\r\n\r\n\tRedrawEverything();\r\n}\r\n\r\nvoid SetSpeedSpell(size_t slot)\r\n{\r\n\tSpellID pSpell;\r\n\tSpellType pSplType;\r\n\r\n\tif (!GetSpellListSelection(pSpell, pSplType)) {\r\n\t\treturn;\r\n\t}\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer._pSplHotKey[slot] == pSpell && myPlayer._pSplTHotKey[slot] == pSplType) {\r\n\t\t// Unset spell hotkey\r\n\t\tmyPlayer._pSplHotKey[slot] = SpellID::Invalid;\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (size_t i = 0; i < NumHotkeys; ++i) {\r\n\t\tif (myPlayer._pSplHotKey[i] == pSpell && myPlayer._pSplTHotKey[i] == pSplType)\r\n\t\t\tmyPlayer._pSplHotKey[i] = SpellID::Invalid;\r\n\t}\r\n\tmyPlayer._pSplHotKey[slot] = pSpell;\r\n\tmyPlayer._pSplTHotKey[slot] = pSplType;\r\n}\r\n\r\nbool IsValidSpeedSpell(size_t slot)\r\n{\r\n\tuint64_t spells;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tconst SpellID spellId = myPlayer._pSplHotKey[slot];\r\n\tif (!IsValidSpell(spellId)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tswitch (myPlayer._pSplTHotKey[slot]) {\r\n\tcase SpellType::Skill:\r\n\t\tspells = myPlayer._pAblSpells;\r\n\t\tbreak;\r\n\tcase SpellType::Spell:\r\n\t\tspells = myPlayer._pMemSpells;\r\n\t\tbreak;\r\n\tcase SpellType::Scroll:\r\n\t\tspells = myPlayer._pScrlSpells;\r\n\t\tbreak;\r\n\tcase SpellType::Charges:\r\n\t\tspells = myPlayer._pISpells;\r\n\t\tbreak;\r\n\tcase SpellType::Invalid:\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn (spells & GetSpellBitmask(spellId)) != 0;\r\n}\r\n\r\nvoid ToggleSpell(size_t slot)\r\n{\r\n\tif (IsValidSpeedSpell(slot)) {\r\n\t\tPlayer &myPlayer = *MyPlayer;\r\n\t\tmyPlayer._pRSpell = myPlayer._pSplHotKey[slot];\r\n\t\tmyPlayer._pRSplType = myPlayer._pSplTHotKey[slot];\r\n\t\tRedrawEverything();\r\n\t}\r\n}\r\n\r\nvoid DoSpeedBook()\r\n{\r\n\tSpellSelectFlag = true;\r\n\tconst Point mainPanelPosition = GetMainPanel().position;\r\n\tint xo = mainPanelPosition.x + 12 + SPLICONLENGTH * 10;\r\n\tint yo = mainPanelPosition.y - 17;\r\n\tint x = xo + SPLICONLENGTH / 2;\r\n\tint y = yo - SPLICONLENGTH / 2;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (IsValidSpell(myPlayer._pRSpell)) {\r\n\t\tfor (auto i : enum_values<SpellType>()) {\r\n\t\t\tuint64_t spells;\r\n\t\t\tswitch (static_cast<SpellType>(i)) {\r\n\t\t\tcase SpellType::Skill:\r\n\t\t\t\tspells = myPlayer._pAblSpells;\r\n\t\t\t\tbreak;\r\n\t\t\tcase SpellType::Spell:\r\n\t\t\t\tspells = myPlayer._pMemSpells;\r\n\t\t\t\tbreak;\r\n\t\t\tcase SpellType::Scroll:\r\n\t\t\t\tspells = myPlayer._pScrlSpells;\r\n\t\t\t\tbreak;\r\n\t\t\tcase SpellType::Charges:\r\n\t\t\t\tspells = myPlayer._pISpells;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tuint64_t spell = 1;\r\n\t\t\tfor (size_t j = 1; j < SpellsData.size(); j++) {\r\n\t\t\t\tif ((spell & spells) != 0) {\r\n\t\t\t\t\tif (j == static_cast<size_t>(myPlayer._pRSpell) && static_cast<SpellType>(i) == myPlayer._pRSplType) {\r\n\t\t\t\t\t\tx = xo + SPLICONLENGTH / 2;\r\n\t\t\t\t\t\ty = yo - SPLICONLENGTH / 2;\r\n\t\t\t\t\t}\r\n\t\t\t\t\txo -= SPLICONLENGTH;\r\n\t\t\t\t\tif (xo == mainPanelPosition.x + 12 - SPLICONLENGTH) {\r\n\t\t\t\t\t\txo = mainPanelPosition.x + 12 + SPLICONLENGTH * SPLROWICONLS;\r\n\t\t\t\t\t\tyo -= SPLICONLENGTH;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tspell <<= 1ULL;\r\n\t\t\t}\r\n\t\t\tif (spells != 0 && xo != mainPanelPosition.x + 12 + SPLICONLENGTH * SPLROWICONLS)\r\n\t\t\t\txo -= SPLICONLENGTH;\r\n\t\t\tif (xo == mainPanelPosition.x + 12 - SPLICONLENGTH) {\r\n\t\t\t\txo = mainPanelPosition.x + 12 + SPLICONLENGTH * SPLROWICONLS;\r\n\t\t\t\tyo -= SPLICONLENGTH;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tSetCursorPos({ x, y });\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/spell_list.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <vector>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"tables/spelldat.h\"\r\n\r\nnamespace devilution {\r\n\r\nstruct SpellListItem {\r\n\tPoint location;\r\n\tSpellType type;\r\n\tSpellID id;\r\n\tbool isSelected;\r\n};\r\n\r\n/**\r\n * @brief draws the current right mouse button spell.\r\n * @param out screen buffer representing the main UI panel\r\n */\r\nvoid DrawSpell(const Surface &out);\r\nvoid DrawSpellList(const Surface &out);\r\nstd::vector<SpellListItem> GetSpellListItems();\r\nvoid SetSpell();\r\nvoid SetSpeedSpell(size_t slot);\r\nbool IsValidSpeedSpell(size_t slot);\r\nvoid ToggleSpell(size_t slot);\r\n\r\n/**\r\n * Draws the \"Speed Book\": the rows of known spells for quick-setting a spell that\r\n * show up when you click the spell slot at the control panel.\r\n */\r\nvoid DoSpeedBook();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/panels/ui_panels.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nenum class UiPanels : uint8_t {\r\n\tMain,\r\n\tQuest,\r\n\tCharacter,\r\n\tSpell,\r\n\tInventory,\r\n\tStash,\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/pfile.cpp",
    "content": "/**\r\n * @file pfile.cpp\r\n *\r\n * Implementation of the save game encoding functionality.\r\n */\r\n#include \"pfile.h\"\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"codec.h\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"loadsave.h\"\r\n#include \"menu.h\"\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"pack.h\"\r\n#include \"qol/stash.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/parse_int.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/stdcompat/filesystem.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/str_split.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#ifdef UNPACKED_SAVES\r\n#include \"utils/file_util.h\"\r\n#else\r\n#include \"mpq/mpq_reader.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n#define PASSWORD_SPAWN_SINGLE \"adslhfb1\"\r\n#define PASSWORD_SPAWN_MULTI \"lshbkfg1\"\r\n#define PASSWORD_SINGLE \"xrgyrkj1\"\r\n#define PASSWORD_MULTI \"szqnlsk1\"\r\n\r\nbool gbValidSaveFile;\r\n\r\nnamespace {\r\n\r\n/** List of character names for the character selection screen. */\r\nchar hero_names[MAX_CHARACTERS][PlayerNameLength];\r\n\r\nstd::string GetSavePath(uint32_t saveNum, std::string_view savePrefix = {})\r\n{\r\n\treturn StrCat(paths::PrefPath(), savePrefix,\r\n\t    gbIsSpawn\r\n\t        ? (gbIsMultiplayer ? \"share_\" : \"spawn_\")\r\n\t        : (gbIsMultiplayer ? \"multi_\" : \"single_\"),\r\n\t    saveNum,\r\n#ifdef UNPACKED_SAVES\r\n\t    gbIsHellfire ? \"_hsv\" DIRECTORY_SEPARATOR_STR : \"_sv\" DIRECTORY_SEPARATOR_STR\r\n#else\r\n\t    gbIsHellfire ? \".hsv\" : \".sv\"\r\n#endif\r\n\t);\r\n}\r\n\r\nstd::string GetStashSavePath()\r\n{\r\n\treturn StrCat(paths::PrefPath(),\r\n\t    gbIsSpawn ? \"stash_spawn\" : \"stash\",\r\n#ifdef UNPACKED_SAVES\r\n\t    gbIsHellfire ? \"_hsv\" DIRECTORY_SEPARATOR_STR : \"_sv\" DIRECTORY_SEPARATOR_STR\r\n#else\r\n\t    gbIsHellfire ? \".hsv\" : \".sv\"\r\n#endif\r\n\t);\r\n}\r\n\r\nbool GetSaveNames(uint8_t index, std::string_view prefix, char *out)\r\n{\r\n\tchar suf;\r\n\tif (index < giNumberOfLevels)\r\n\t\tsuf = 'l';\r\n\telse if (index < giNumberOfLevels * 2) {\r\n\t\tindex -= giNumberOfLevels;\r\n\t\tsuf = 's';\r\n\t} else {\r\n\t\treturn false;\r\n\t}\r\n\r\n\t*BufCopy(out, prefix, std::string_view(&suf, 1), LeftPad(index, 2, '0')) = '\\0';\r\n\treturn true;\r\n}\r\n\r\nbool GetPermSaveNames(uint8_t dwIndex, char *szPerm)\r\n{\r\n\treturn GetSaveNames(dwIndex, \"perm\", szPerm);\r\n}\r\n\r\nbool GetTempSaveNames(uint8_t dwIndex, char *szTemp)\r\n{\r\n\treturn GetSaveNames(dwIndex, \"temp\", szTemp);\r\n}\r\n\r\nvoid RenameTempToPerm(SaveWriter &saveWriter)\r\n{\r\n\tchar szTemp[MaxMpqPathSize];\r\n\tchar szPerm[MaxMpqPathSize];\r\n\r\n\tuint32_t dwIndex = 0;\r\n\twhile (GetTempSaveNames(dwIndex, szTemp)) {\r\n\t\t[[maybe_unused]] const bool result = GetPermSaveNames(dwIndex, szPerm); // DO NOT PUT DIRECTLY INTO ASSERT!\r\n\t\tassert(result);\r\n\t\tdwIndex++;\r\n\t\tif (saveWriter.HasFile(szTemp)) {\r\n\t\t\tif (saveWriter.HasFile(szPerm))\r\n\t\t\t\tsaveWriter.RemoveHashEntry(szPerm);\r\n\t\t\tsaveWriter.RenameFile(szTemp, szPerm);\r\n\t\t}\r\n\t}\r\n\tassert(!GetPermSaveNames(dwIndex, szPerm));\r\n}\r\n\r\nbool ReadHero(SaveReader &archive, PlayerPack *pPack)\r\n{\r\n\tsize_t read;\r\n\r\n\tauto buf = ReadArchive(archive, \"hero\", &read);\r\n\tif (buf == nullptr)\r\n\t\treturn false;\r\n\r\n\tbool ret = false;\r\n\tif (read == sizeof(*pPack)) {\r\n\t\tmemcpy(pPack, buf.get(), sizeof(*pPack));\r\n\t\tret = true;\r\n\t}\r\n\r\n\treturn ret;\r\n}\r\n\r\nvoid EncodeHero(SaveWriter &saveWriter, const PlayerPack *pack)\r\n{\r\n\tconst size_t packedLen = codec_get_encoded_len(sizeof(*pack));\r\n\tconst std::unique_ptr<std::byte[]> packed { new std::byte[packedLen] };\r\n\r\n\tmemcpy(packed.get(), pack, sizeof(*pack));\r\n\tcodec_encode(packed.get(), sizeof(*pack), packedLen, pfile_get_password());\r\n\tsaveWriter.WriteFile(\"hero\", packed.get(), packedLen);\r\n}\r\n\r\nSaveWriter GetSaveWriter(uint32_t saveNum)\r\n{\r\n\treturn SaveWriter(GetSavePath(saveNum));\r\n}\r\n\r\nSaveWriter GetStashWriter()\r\n{\r\n\treturn SaveWriter(GetStashSavePath());\r\n}\r\n\r\n#ifndef DISABLE_DEMOMODE\r\nvoid CopySaveFile(uint32_t saveNum, std::string targetPath)\r\n{\r\n\tconst std::string savePath = GetSavePath(saveNum);\r\n#if defined(UNPACKED_SAVES)\r\n#ifdef DVL_NO_FILESYSTEM\r\n#error \"UNPACKED_SAVES requires either DISABLE_DEMOMODE or C++17 <filesystem>\"\r\n#endif\r\n\tif (!targetPath.empty()) {\r\n\t\tCreateDir(targetPath.c_str());\r\n\t}\r\n\tfor (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(savePath)) {\r\n\t\tCopyFileOverwrite(entry.path().string().c_str(), (targetPath + entry.path().filename().string()).c_str());\r\n\t}\r\n#else\r\n\tCopyFileOverwrite(savePath.c_str(), targetPath.c_str());\r\n#endif\r\n}\r\n#endif\r\n\r\nvoid Game2UiPlayer(const Player &player, _uiheroinfo *heroinfo, bool bHasSaveFile)\r\n{\r\n\tCopyUtf8(heroinfo->name, player._pName, sizeof(heroinfo->name));\r\n\theroinfo->level = player.getCharacterLevel();\r\n\theroinfo->heroclass = player._pClass;\r\n\theroinfo->strength = player._pStrength;\r\n\theroinfo->magic = player._pMagic;\r\n\theroinfo->dexterity = player._pDexterity;\r\n\theroinfo->vitality = player._pVitality;\r\n\theroinfo->hassaved = bHasSaveFile;\r\n\theroinfo->herorank = player.pDiabloKillLevel;\r\n\theroinfo->spawned = gbIsSpawn;\r\n}\r\n\r\nbool GetFileName(uint8_t lvl, char *dst)\r\n{\r\n\tif (gbIsMultiplayer) {\r\n\t\tif (lvl != 0)\r\n\t\t\treturn false;\r\n\t\tmemcpy(dst, \"hero\", 5);\r\n\t\treturn true;\r\n\t}\r\n\tif (GetPermSaveNames(lvl, dst)) {\r\n\t\treturn true;\r\n\t}\r\n\tif (lvl == giNumberOfLevels * 2) {\r\n\t\tmemcpy(dst, \"game\", 5);\r\n\t\treturn true;\r\n\t}\r\n\tif (lvl == giNumberOfLevels * 2 + 1) {\r\n\t\tmemcpy(dst, \"hero\", 5);\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool ArchiveContainsGame(SaveReader &hsArchive)\r\n{\r\n\tif (gbIsMultiplayer)\r\n\t\treturn false;\r\n\r\n\tauto gameData = ReadArchive(hsArchive, \"game\");\r\n\tif (gameData == nullptr)\r\n\t\treturn false;\r\n\r\n\tconst uint32_t hdr = LoadLE32(gameData.get());\r\n\r\n\treturn IsHeaderValid(hdr);\r\n}\r\n\r\nstd::optional<SaveReader> CreateSaveReader(std::string &&path)\r\n{\r\n#ifdef UNPACKED_SAVES\r\n\tif (!FileExists(path))\r\n\t\treturn std::nullopt;\r\n\treturn SaveReader(std::move(path));\r\n#else\r\n\tstd::int32_t error;\r\n\treturn MpqArchive::Open(path.c_str(), error);\r\n#endif\r\n}\r\n\r\n#ifndef DISABLE_DEMOMODE\r\nstruct CompareInfo {\r\n\tstd::unique_ptr<std::byte[]> &data;\r\n\tsize_t currentPosition;\r\n\tsize_t size;\r\n\tbool isTownLevel;\r\n\tbool dataExists;\r\n};\r\n\r\nstruct CompareCounter {\r\n\tint reference;\r\n\tint actual;\r\n\tint max() const\r\n\t{\r\n\t\treturn std::max(reference, actual);\r\n\t}\r\n\tvoid checkIfDataExists(int count, CompareInfo &compareInfoReference, CompareInfo &compareInfoActual) const\r\n\t{\r\n\t\tif (reference == count)\r\n\t\t\tcompareInfoReference.dataExists = false;\r\n\t\tif (actual == count)\r\n\t\t\tcompareInfoActual.dataExists = false;\r\n\t}\r\n};\r\n\r\ninline bool string_ends_with(std::string_view value, std::string_view suffix)\r\n{\r\n\tif (suffix.size() > value.size())\r\n\t\treturn false;\r\n\treturn std::equal(suffix.rbegin(), suffix.rend(), value.rbegin());\r\n}\r\n\r\nvoid CreateDetailDiffs(std::string_view prefix, std::string_view memoryMapFile, CompareInfo &compareInfoReference, CompareInfo &compareInfoActual, ankerl::unordered_dense::segmented_map<std::string, size_t> &foundDiffs)\r\n{\r\n\t// Note: Detail diffs are currently only supported in unit tests\r\n\tconst std::string memoryMapFileAssetName = StrCat(paths::BasePath(), \"/test/fixtures/memory_map/\", memoryMapFile, \".txt\");\r\n\r\n\tSDL_IOStream *handle = SDL_IOFromFile(memoryMapFileAssetName.c_str(), \"r\");\r\n\tif (handle == nullptr) {\r\n\t\tapp_fatal(StrCat(\"MemoryMapFile \", memoryMapFile, \" is missing\"));\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst size_t readBytes = static_cast<size_t>(SDL_GetIOSize(handle));\r\n\tconst std::unique_ptr<std::byte[]> memoryMapFileData { new std::byte[readBytes] };\r\n\tSDL_ReadIO(handle, memoryMapFileData.get(), readBytes);\r\n\tSDL_CloseIO(handle);\r\n\r\n\tconst std::string_view buffer(reinterpret_cast<const char *>(memoryMapFileData.get()), readBytes);\r\n\r\n\tankerl::unordered_dense::segmented_map<std::string, CompareCounter> counter;\r\n\r\n\tauto getCounter = [&](const std::string &counterAsString) {\r\n\t\tauto it = counter.find(counterAsString);\r\n\t\tif (it != counter.end())\r\n\t\t\treturn it->second;\r\n\t\tconst ParseIntResult<int> countFromMapFile = ParseInt<int>(counterAsString);\r\n\t\tif (!countFromMapFile.has_value())\r\n\t\t\tapp_fatal(StrCat(\"Failed to parse \", counterAsString, \" as int\"));\r\n\t\treturn CompareCounter { countFromMapFile.value(), countFromMapFile.value() };\r\n\t};\r\n\tauto addDiff = [&](const std::string &diffKey) {\r\n\t\tauto it = foundDiffs.find(diffKey);\r\n\t\tif (it == foundDiffs.end()) {\r\n\t\t\tfoundDiffs.insert_or_assign(diffKey, 1);\r\n\t\t} else {\r\n\t\t\tfoundDiffs.insert_or_assign(diffKey, it->second + 1);\r\n\t\t}\r\n\t};\r\n\r\n\tauto compareBytes = [&](size_t countBytes) {\r\n\t\tif (compareInfoReference.dataExists && compareInfoReference.currentPosition + countBytes > compareInfoReference.size)\r\n\t\t\tapp_fatal(StrCat(\"Comparison failed. Not enough bytes in reference to compare. Location: \", prefix));\r\n\t\tif (compareInfoActual.dataExists && compareInfoActual.currentPosition + countBytes > compareInfoActual.size)\r\n\t\t\tapp_fatal(StrCat(\"Comparison failed. Not enough bytes in actual to compare. Location: \", prefix));\r\n\t\tbool result = true;\r\n\t\tif (compareInfoReference.dataExists && compareInfoActual.dataExists)\r\n\t\t\tresult = memcmp(compareInfoReference.data.get() + compareInfoReference.currentPosition, compareInfoActual.data.get() + compareInfoActual.currentPosition, countBytes) == 0;\r\n\t\tif (compareInfoReference.dataExists)\r\n\t\t\tcompareInfoReference.currentPosition += countBytes;\r\n\t\tif (compareInfoActual.dataExists)\r\n\t\t\tcompareInfoActual.currentPosition += countBytes;\r\n\t\treturn result;\r\n\t};\r\n\r\n\tauto read32BitInt = [&](CompareInfo &compareInfo, bool useLE) {\r\n\t\tint32_t value = 0;\r\n\t\tif (!compareInfo.dataExists)\r\n\t\t\treturn value;\r\n\t\tif (compareInfo.currentPosition + sizeof(value) > compareInfo.size)\r\n\t\t\tapp_fatal(\"read32BitInt failed. Too less bytes to read.\");\r\n\t\tmemcpy(&value, compareInfo.data.get() + compareInfo.currentPosition, sizeof(value));\r\n\t\tif (useLE)\r\n\t\t\tvalue = Swap32LE(value);\r\n\t\telse\r\n\t\t\tvalue = Swap32BE(value);\r\n\t\treturn value;\r\n\t};\r\n\r\n\tfor (std::string_view line : SplitByChar(buffer, '\\n')) {\r\n\t\tif (!line.empty() && line.back() == '\\r')\r\n\t\t\tline.remove_suffix(1);\r\n\t\tif (line.empty())\r\n\t\t\tcontinue;\r\n\t\tconst auto tokens = SplitByChar(line, ' ');\r\n\t\tauto it = tokens.begin();\r\n\t\tconst auto end = tokens.end();\r\n\t\tif (it == end)\r\n\t\t\tcontinue;\r\n\r\n\t\tstd::string_view command = *it;\r\n\r\n\t\tconst bool dataExistsReference = compareInfoReference.dataExists;\r\n\t\tconst bool dataExistsActual = compareInfoActual.dataExists;\r\n\r\n\t\tif (string_ends_with(command, \"_HF\")) {\r\n\t\t\tif (!gbIsHellfire)\r\n\t\t\t\tcontinue;\r\n\t\t\tcommand.remove_suffix(3);\r\n\t\t}\r\n\t\tif (string_ends_with(command, \"_DA\")) {\r\n\t\t\tif (gbIsHellfire)\r\n\t\t\t\tcontinue;\r\n\t\t\tcommand.remove_suffix(3);\r\n\t\t}\r\n\t\tif (string_ends_with(command, \"_DL\")) {\r\n\t\t\tif (compareInfoReference.isTownLevel && compareInfoActual.isTownLevel)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (compareInfoReference.isTownLevel)\r\n\t\t\t\tcompareInfoReference.dataExists = false;\r\n\t\t\tif (compareInfoActual.isTownLevel)\r\n\t\t\t\tcompareInfoActual.dataExists = false;\r\n\t\t\tcommand.remove_suffix(3);\r\n\t\t}\r\n\t\tif (command == \"R\" || command == \"LT\" || command == \"LC\" || command == \"LC_LE\") {\r\n\t\t\tconst auto bitsAsString = std::string(*++it);\r\n\t\t\tconst auto comment = std::string(*++it);\r\n\t\t\tconst ParseIntResult<size_t> parsedBytes = ParseInt<size_t>(bitsAsString);\r\n\t\t\tif (!parsedBytes.has_value())\r\n\t\t\t\tapp_fatal(StrCat(\"Failed to parse \", bitsAsString, \" as size_t\"));\r\n\t\t\tconst size_t bytes = static_cast<size_t>(parsedBytes.value() / 8);\r\n\r\n\t\t\tif (command == \"LT\") {\r\n\t\t\t\tconst int32_t valueReference = read32BitInt(compareInfoReference, false);\r\n\t\t\t\tconst int32_t valueActual = read32BitInt(compareInfoActual, false);\r\n\t\t\t\tassert(sizeof(valueReference) == bytes);\r\n\t\t\t\tcompareInfoReference.isTownLevel = valueReference == 0;\r\n\t\t\t\tcompareInfoActual.isTownLevel = valueActual == 0;\r\n\t\t\t}\r\n\t\t\tif (command == \"LC\" || command == \"LC_LE\") {\r\n\t\t\t\tconst int32_t valueReference = read32BitInt(compareInfoReference, command == \"LC_LE\");\r\n\t\t\t\tconst int32_t valueActual = read32BitInt(compareInfoActual, command == \"LC_LE\");\r\n\t\t\t\tassert(sizeof(valueReference) == bytes);\r\n\t\t\t\tcounter.insert_or_assign(std::string(comment), CompareCounter { valueReference, valueActual });\r\n\t\t\t}\r\n\r\n\t\t\tif (!compareBytes(bytes)) {\r\n\t\t\t\tconst std::string diffKey = StrCat(prefix, \".\", comment);\r\n\t\t\t\taddDiff(diffKey);\r\n\t\t\t}\r\n\t\t} else if (command == \"M\") {\r\n\t\t\tconst auto countAsString = std::string(*++it);\r\n\t\t\tconst auto bitsAsString = std::string(*++it);\r\n\t\t\tconst std::string_view comment = *++it;\r\n\r\n\t\t\tconst CompareCounter count = getCounter(countAsString);\r\n\t\t\tconst ParseIntResult<size_t> parsedBytes = ParseInt<size_t>(bitsAsString);\r\n\t\t\tif (!parsedBytes.has_value())\r\n\t\t\t\tapp_fatal(StrCat(\"Failed to parse \", bitsAsString, \" as size_t\"));\r\n\t\t\tconst size_t bytes = static_cast<size_t>(parsedBytes.value() / 8);\r\n\t\t\tfor (int i = 0; i < count.max(); i++) {\r\n\t\t\t\tcount.checkIfDataExists(i, compareInfoReference, compareInfoActual);\r\n\t\t\t\tif (!compareBytes(bytes)) {\r\n\t\t\t\t\tconst std::string diffKey = StrCat(prefix, \".\", comment);\r\n\t\t\t\t\taddDiff(diffKey);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else if (command == \"C\") {\r\n\t\t\tconst auto countAsString = std::string(*++it);\r\n\t\t\tauto subMemoryMapFile = std::string(*++it);\r\n\t\t\tconst auto comment = std::string(*++it);\r\n\r\n\t\t\tconst CompareCounter count = getCounter(countAsString);\r\n\t\t\tsubMemoryMapFile.erase(std::remove(subMemoryMapFile.begin(), subMemoryMapFile.end(), '\\r'), subMemoryMapFile.end());\r\n\t\t\tfor (int i = 0; i < count.max(); i++) {\r\n\t\t\t\tcount.checkIfDataExists(i, compareInfoReference, compareInfoActual);\r\n\t\t\t\tconst std::string subPrefix = StrCat(prefix, \".\", comment);\r\n\t\t\t\tCreateDetailDiffs(subPrefix, subMemoryMapFile, compareInfoReference, compareInfoActual, foundDiffs);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tcompareInfoReference.dataExists = dataExistsReference;\r\n\t\tcompareInfoActual.dataExists = dataExistsActual;\r\n\t}\r\n}\r\n\r\nstruct CompareTargets {\r\n\tstd::string fileName;\r\n\tstd::string memoryMapFileName;\r\n\tbool isTownLevel;\r\n};\r\n\r\nHeroCompareResult CompareSaves(const std::string &actualSavePath, const std::string &referenceSavePath, bool logDetails)\r\n{\r\n\tstd::vector<CompareTargets> possibleFileToCheck;\r\n\tpossibleFileToCheck.push_back({ \"hero\", \"hero\", false });\r\n\tpossibleFileToCheck.push_back({ \"game\", \"game\", false });\r\n\tpossibleFileToCheck.push_back({ \"additionalMissiles\", \"additionalMissiles\", false });\r\n\tchar szPerm[MaxMpqPathSize];\r\n\tfor (int i = 0; GetPermSaveNames(i, szPerm); i++) {\r\n\t\tpossibleFileToCheck.push_back({ std::string(szPerm), \"level\", i == 0 });\r\n\t}\r\n\r\n\tSaveReader actualArchive = *CreateSaveReader(std::string(actualSavePath));\r\n\tSaveReader referenceArchive = *CreateSaveReader(std::string(referenceSavePath));\r\n\r\n\tbool compareResult = true;\r\n\tstd::string message;\r\n\tfor (const auto &compareTarget : possibleFileToCheck) {\r\n\t\tsize_t fileSizeActual = 0;\r\n\t\tauto fileDataActual = ReadArchive(actualArchive, compareTarget.fileName.c_str(), &fileSizeActual);\r\n\t\tsize_t fileSizeReference = 0;\r\n\t\tauto fileDataReference = ReadArchive(referenceArchive, compareTarget.fileName.c_str(), &fileSizeReference);\r\n\t\tif (fileDataActual.get() == nullptr && fileDataReference.get() == nullptr) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (fileSizeActual == fileSizeReference && memcmp(fileDataReference.get(), fileDataActual.get(), fileSizeActual) == 0)\r\n\t\t\tcontinue;\r\n\t\tcompareResult = false;\r\n\t\tif (!message.empty())\r\n\t\t\tmessage.append(\"\\n\");\r\n\t\tif (fileSizeActual != fileSizeReference)\r\n\t\t\tStrAppend(message, \"file \\\"\", compareTarget.fileName, \"\\\" is different size. Expected: \", fileSizeReference, \" Actual: \", fileSizeActual);\r\n\t\telse\r\n\t\t\tStrAppend(message, \"file \\\"\", compareTarget.fileName, \"\\\" has different content.\");\r\n\t\tif (!logDetails)\r\n\t\t\tcontinue;\r\n\t\tankerl::unordered_dense::segmented_map<std::string, size_t> foundDiffs;\r\n\t\tCompareInfo compareInfoReference = { fileDataReference, 0, fileSizeReference, compareTarget.isTownLevel, fileSizeReference != 0 };\r\n\t\tCompareInfo compareInfoActual = { fileDataActual, 0, fileSizeActual, compareTarget.isTownLevel, fileSizeActual != 0 };\r\n\t\tCreateDetailDiffs(compareTarget.fileName, compareTarget.memoryMapFileName, compareInfoReference, compareInfoActual, foundDiffs);\r\n\t\tif (compareInfoReference.currentPosition != fileSizeReference)\r\n\t\t\tapp_fatal(StrCat(\"Comparison failed. Uncompared bytes in reference. File: \", compareTarget.fileName));\r\n\t\tif (compareInfoActual.currentPosition != fileSizeActual)\r\n\t\t\tapp_fatal(StrCat(\"Comparison failed. Uncompared bytes in actual. File: \", compareTarget.fileName));\r\n\t\tfor (const auto &[location, count] : foundDiffs) {\r\n\t\t\tStrAppend(message, \"\\nDiff found in \", location, \" count: \", count);\r\n\t\t}\r\n\t}\r\n\treturn { compareResult ? HeroCompareResult::Same : HeroCompareResult::Difference, message };\r\n}\r\n#endif // !DISABLE_DEMOMODE\r\n\r\nvoid pfile_write_hero(SaveWriter &saveWriter, bool writeGameData)\r\n{\r\n\tif (writeGameData) {\r\n\t\tSaveGameData(saveWriter);\r\n\t\tRenameTempToPerm(saveWriter);\r\n\t}\r\n\tPlayerPack pkplr;\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tPackPlayer(pkplr, myPlayer);\r\n\tEncodeHero(saveWriter, &pkplr);\r\n\tif (!gbVanilla) {\r\n\t\tSaveHotkeys(saveWriter, myPlayer);\r\n\t\tSaveHeroItems(saveWriter, myPlayer);\r\n\t}\r\n}\r\n\r\nvoid RemoveAllInvalidItems(Player &player)\r\n{\r\n\tfor (int i = 0; i < NUM_INVLOC; i++)\r\n\t\tRemoveInvalidItem(player.InvBody[i]);\r\n\tfor (int i = 0; i < player._pNumInv; i++)\r\n\t\tRemoveInvalidItem(player.InvList[i]);\r\n\tfor (int i = 0; i < MaxBeltItems; i++)\r\n\t\tRemoveInvalidItem(player.SpdList[i]);\r\n\tRemoveEmptyInventory(player);\r\n}\r\n\r\n} // namespace\r\n\r\n#ifdef UNPACKED_SAVES\r\nstd::unique_ptr<std::byte[]> SaveReader::ReadFile(const char *filename, std::size_t &fileSize, int32_t &error)\r\n{\r\n\tstd::unique_ptr<std::byte[]> result;\r\n\terror = 0;\r\n\tconst std::string path = dir_ + filename;\r\n\tuintmax_t size;\r\n\tif (!GetFileSize(path.c_str(), &size)) {\r\n\t\terror = 1;\r\n\t\treturn nullptr;\r\n\t}\r\n\tfileSize = size;\r\n\tFILE *file = OpenFile(path.c_str(), \"rb\");\r\n\tif (file == nullptr) {\r\n\t\terror = 1;\r\n\t\treturn nullptr;\r\n\t}\r\n\tresult.reset(new std::byte[size]);\r\n\tif (std::fread(result.get(), size, 1, file) != 1) {\r\n\t\tstd::fclose(file);\r\n\t\terror = 1;\r\n\t\treturn nullptr;\r\n\t}\r\n\tstd::fclose(file);\r\n\treturn result;\r\n}\r\n\r\nbool SaveWriter::WriteFile(const char *filename, const std::byte *data, size_t size)\r\n{\r\n\tconst std::string path = dir_ + filename;\r\n\tFILE *file = OpenFile(path.c_str(), \"wb\");\r\n\tif (file == nullptr) {\r\n\t\treturn false;\r\n\t}\r\n\tif (std::fwrite(data, size, 1, file) != 1) {\r\n\t\tstd::fclose(file);\r\n\t\treturn false;\r\n\t}\r\n\tstd::fclose(file);\r\n\treturn true;\r\n}\r\n\r\nvoid SaveWriter::RemoveHashEntries(bool (*fnGetName)(uint8_t, char *))\r\n{\r\n\tchar pszFileName[MaxMpqPathSize];\r\n\r\n\tfor (uint8_t i = 0; fnGetName(i, pszFileName); i++) {\r\n\t\tRemoveHashEntry(pszFileName);\r\n\t}\r\n}\r\n#endif\r\n\r\nstd::optional<SaveReader> OpenSaveArchive(uint32_t saveNum)\r\n{\r\n\treturn CreateSaveReader(GetSavePath(saveNum));\r\n}\r\n\r\nstd::optional<SaveReader> OpenStashArchive()\r\n{\r\n\treturn CreateSaveReader(GetStashSavePath());\r\n}\r\n\r\nstd::unique_ptr<std::byte[]> ReadArchive(SaveReader &archive, const char *pszName, size_t *pdwLen)\r\n{\r\n\tint32_t error;\r\n\tstd::size_t length;\r\n\r\n\tstd::unique_ptr<std::byte[]> result = archive.ReadFile(pszName, length, error);\r\n\tif (error != 0)\r\n\t\treturn nullptr;\r\n\r\n\tconst std::size_t decodedLength = codec_decode(result.get(), length, pfile_get_password());\r\n\tif (decodedLength == 0)\r\n\t\treturn nullptr;\r\n\r\n\tif (pdwLen != nullptr)\r\n\t\t*pdwLen = decodedLength;\r\n\r\n\treturn result;\r\n}\r\n\r\nconst char *pfile_get_password()\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn gbIsMultiplayer ? PASSWORD_SPAWN_MULTI : PASSWORD_SPAWN_SINGLE;\r\n\treturn gbIsMultiplayer ? PASSWORD_MULTI : PASSWORD_SINGLE;\r\n}\r\n\r\nvoid pfile_write_hero(bool writeGameData)\r\n{\r\n\tSaveWriter saveWriter = GetSaveWriter(gSaveNumber);\r\n\tpfile_write_hero(saveWriter, writeGameData);\r\n}\r\n\r\n#ifndef DISABLE_DEMOMODE\r\nvoid pfile_write_hero_demo(int demo)\r\n{\r\n\tconst std::string savePath = GetSavePath(gSaveNumber, StrCat(\"demo_\", demo, \"_reference_\"));\r\n\tCopySaveFile(gSaveNumber, savePath);\r\n\tauto saveWriter = SaveWriter(savePath.c_str());\r\n\tpfile_write_hero(saveWriter, true);\r\n}\r\n\r\nHeroCompareResult pfile_compare_hero_demo(int demo, bool logDetails)\r\n{\r\n\tconst std::string referenceSavePath = GetSavePath(gSaveNumber, StrCat(\"demo_\", demo, \"_reference_\"));\r\n\r\n\tif (!FileExists(referenceSavePath.c_str()))\r\n\t\treturn { HeroCompareResult::ReferenceNotFound, {} };\r\n\r\n\tconst std::string actualSavePath = GetSavePath(gSaveNumber, StrCat(\"demo_\", demo, \"_actual_\"));\r\n\t{\r\n\t\tCopySaveFile(gSaveNumber, actualSavePath);\r\n\t\tSaveWriter saveWriter(actualSavePath.c_str());\r\n\t\tpfile_write_hero(saveWriter, true);\r\n\t}\r\n\r\n\treturn CompareSaves(actualSavePath, referenceSavePath, logDetails);\r\n}\r\n#endif\r\n\r\nvoid sfile_write_stash()\r\n{\r\n\tif (!Stash.dirty)\r\n\t\treturn;\r\n\r\n\tSaveWriter stashWriter = GetStashWriter();\r\n\r\n\tSaveStash(stashWriter);\r\n\r\n\tStash.dirty = false;\r\n}\r\n\r\nbool pfile_ui_set_hero_infos(bool (*uiAddHeroInfo)(_uiheroinfo *))\r\n{\r\n\tmemset(hero_names, 0, sizeof(hero_names));\r\n\r\n\tfor (uint32_t i = 0; i < MAX_CHARACTERS; i++) {\r\n\t\tstd::optional<SaveReader> archive = OpenSaveArchive(i);\r\n\t\tif (archive) {\r\n\t\t\tPlayerPack pkplr;\r\n\t\t\tif (ReadHero(*archive, &pkplr)) {\r\n\t\t\t\t_uiheroinfo uihero;\r\n\t\t\t\tuihero.saveNumber = i;\r\n\t\t\t\tstrcpy(hero_names[i], pkplr.pName);\r\n\t\t\t\tconst bool hasSaveGame = ArchiveContainsGame(*archive);\r\n\t\t\t\tif (hasSaveGame)\r\n\t\t\t\t\tpkplr.bIsHellfire = gbIsHellfireSaveGame ? 1 : 0;\r\n\r\n\t\t\t\tPlayer &player = Players[0];\r\n\r\n\t\t\t\tUnPackPlayer(pkplr, player);\r\n\t\t\t\tLoadHeroItems(player);\r\n\t\t\t\tRemoveAllInvalidItems(player);\r\n\t\t\t\tCalcPlrInv(player, false);\r\n\r\n\t\t\t\tGame2UiPlayer(player, &uihero, hasSaveGame);\r\n\t\t\t\tuiAddHeroInfo(&uihero);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid pfile_ui_set_class_stats(HeroClass playerClass, _uidefaultstats *classStats)\r\n{\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(playerClass);\r\n\tclassStats->strength = classAttributes.baseStr;\r\n\tclassStats->magic = classAttributes.baseMag;\r\n\tclassStats->dexterity = classAttributes.baseDex;\r\n\tclassStats->vitality = classAttributes.baseVit;\r\n}\r\n\r\nuint32_t pfile_ui_get_first_unused_save_num()\r\n{\r\n\tuint32_t saveNum;\r\n\tfor (saveNum = 0; saveNum < MAX_CHARACTERS; saveNum++) {\r\n\t\tif (hero_names[saveNum][0] == '\\0')\r\n\t\t\tbreak;\r\n\t}\r\n\treturn saveNum;\r\n}\r\n\r\nbool pfile_ui_save_create(_uiheroinfo *heroinfo)\r\n{\r\n\tPlayerPack pkplr;\r\n\r\n\tconst uint32_t saveNum = heroinfo->saveNumber;\r\n\tif (saveNum >= MAX_CHARACTERS)\r\n\t\treturn false;\r\n\theroinfo->saveNumber = saveNum;\r\n\r\n\tgiNumberOfLevels = gbIsHellfire ? 25 : 17;\r\n\r\n\tSaveWriter saveWriter = GetSaveWriter(saveNum);\r\n\tsaveWriter.RemoveHashEntries(GetFileName);\r\n\tCopyUtf8(hero_names[saveNum], heroinfo->name, sizeof(hero_names[saveNum]));\r\n\r\n\tPlayer &player = Players[0];\r\n\tCreatePlayer(player, heroinfo->heroclass);\r\n\tCopyUtf8(player._pName, heroinfo->name, PlayerNameLength);\r\n\tPackPlayer(pkplr, player);\r\n\tEncodeHero(saveWriter, &pkplr);\r\n\tGame2UiPlayer(player, heroinfo, false);\r\n\tif (!gbVanilla) {\r\n\t\tSaveHotkeys(saveWriter, player);\r\n\t\tSaveHeroItems(saveWriter, player);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool pfile_delete_save(_uiheroinfo *heroInfo)\r\n{\r\n\tconst uint32_t saveNum = heroInfo->saveNumber;\r\n\tif (saveNum < MAX_CHARACTERS) {\r\n\t\thero_names[saveNum][0] = '\\0';\r\n\t\tRemoveFile(GetSavePath(saveNum).c_str());\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid pfile_read_player_from_save(uint32_t saveNum, Player &player)\r\n{\r\n\tPlayerPack pkplr;\r\n\t{\r\n\t\tstd::optional<SaveReader> archive = OpenSaveArchive(saveNum);\r\n\t\tif (!archive)\r\n\t\t\tapp_fatal(_(\"Unable to open archive\"));\r\n\t\tif (!ReadHero(*archive, &pkplr))\r\n\t\t\tapp_fatal(_(\"Unable to load character\"));\r\n\r\n\t\tgbValidSaveFile = ArchiveContainsGame(*archive);\r\n\t\tif (gbValidSaveFile)\r\n\t\t\tpkplr.bIsHellfire = gbIsHellfireSaveGame ? 1 : 0;\r\n\t}\r\n\r\n\tUnPackPlayer(pkplr, player);\r\n\tLoadHeroItems(player);\r\n\tRemoveAllInvalidItems(player);\r\n\tCalcPlrInv(player, false);\r\n}\r\n\r\nvoid pfile_save_level()\r\n{\r\n\tSaveWriter saveWriter = GetSaveWriter(gSaveNumber);\r\n\tSaveLevel(saveWriter);\r\n}\r\n\r\ntl::expected<void, std::string> pfile_convert_levels()\r\n{\r\n\tSaveWriter saveWriter = GetSaveWriter(gSaveNumber);\r\n\treturn ConvertLevels(saveWriter);\r\n}\r\n\r\nvoid pfile_remove_temp_files()\r\n{\r\n\tif (gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tSaveWriter saveWriter = GetSaveWriter(gSaveNumber);\r\n\tsaveWriter.RemoveHashEntries(GetTempSaveNames);\r\n}\r\n\r\nvoid pfile_update(bool forceSave)\r\n{\r\n\tstatic Uint32 prevTick;\r\n\r\n\tif (!gbIsMultiplayer)\r\n\t\treturn;\r\n\r\n\tconst Uint32 tick = SDL_GetTicks();\r\n\tif (!forceSave && tick - prevTick <= 60000)\r\n\t\treturn;\r\n\r\n\tprevTick = tick;\r\n\tpfile_write_hero();\r\n\tsfile_write_stash();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/pfile.h",
    "content": "/**\r\n * @file pfile.h\r\n *\r\n * Interface of the save game encoding functionality.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"player.h\"\r\n\r\n#ifdef UNPACKED_SAVES\r\n#include \"utils/file_util.h\"\r\n#else\r\n#include \"mpq/mpq_reader.hpp\"\r\n#include \"mpq/mpq_writer.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n#define MAX_CHARACTERS 99\r\n\r\nextern bool gbValidSaveFile;\r\n\r\n#ifdef UNPACKED_SAVES\r\nstruct SaveReader {\r\n\texplicit SaveReader(std::string &&dir)\r\n\t    : dir_(std::move(dir))\r\n\t{\r\n\t}\r\n\r\n\tconst std::string &dir() const\r\n\t{\r\n\t\treturn dir_;\r\n\t}\r\n\r\n\tstd::unique_ptr<std::byte[]> ReadFile(const char *filename, std::size_t &fileSize, int32_t &error);\r\n\r\n\tbool HasFile(const char *path)\r\n\t{\r\n\t\treturn ::devilution::FileExists((dir_ + path).c_str());\r\n\t}\r\n\r\nprivate:\r\n\tstd::string dir_;\r\n};\r\n\r\nstruct SaveWriter {\r\n\texplicit SaveWriter(std::string &&dir)\r\n\t    : dir_(std::move(dir))\r\n\t{\r\n\t}\r\n\r\n\tbool WriteFile(const char *filename, const std::byte *data, size_t size);\r\n\r\n\tbool HasFile(const char *path)\r\n\t{\r\n\t\treturn ::devilution::FileExists((dir_ + path).c_str());\r\n\t}\r\n\r\n\tvoid RenameFile(const char *from, const char *to)\r\n\t{\r\n\t\t::devilution::RenameFile((dir_ + from).c_str(), (dir_ + to).c_str());\r\n\t}\r\n\r\n\tvoid RemoveHashEntry(const char *path)\r\n\t{\r\n\t\tRemoveFile((dir_ + path).c_str());\r\n\t}\r\n\r\n\tvoid RemoveHashEntries(bool (*fnGetName)(uint8_t, char *));\r\n\r\nprivate:\r\n\tstd::string dir_;\r\n};\r\n\r\n#else\r\nusing SaveReader = MpqArchive;\r\nusing SaveWriter = MpqWriter;\r\n#endif\r\n\r\n/**\r\n * @brief Comparison result of pfile_compare_hero_demo\r\n */\r\nstruct HeroCompareResult {\r\n\tenum Status : uint8_t {\r\n\t\tReferenceNotFound,\r\n\t\tSame,\r\n\t\tDifference,\r\n\t};\r\n\tStatus status;\r\n\tstd::string message;\r\n};\r\n\r\nstd::optional<SaveReader> OpenSaveArchive(uint32_t saveNum);\r\nstd::optional<SaveReader> OpenStashArchive();\r\nconst char *pfile_get_password();\r\nstd::unique_ptr<std::byte[]> ReadArchive(SaveReader &archive, const char *pszName, size_t *pdwLen = nullptr);\r\nvoid pfile_write_hero(bool writeGameData = false);\r\n\r\n#ifndef DISABLE_DEMOMODE\r\n/**\r\n * @brief Save a reference game-state (save game) for the demo recording\r\n * @param demo that is recorded\r\n */\r\nvoid pfile_write_hero_demo(int demo);\r\n/**\r\n * @brief Compares the actual game-state (savegame) with a reference game-state (save game from demo recording)\r\n * @param demo for the comparison\r\n * @param logDetails in case of a difference log details\r\n * @return The comparison result.\r\n */\r\nHeroCompareResult pfile_compare_hero_demo(int demo, bool logDetails);\r\n#endif\r\n\r\nvoid sfile_write_stash();\r\nbool pfile_ui_set_hero_infos(bool (*uiAddHeroInfo)(_uiheroinfo *));\r\nvoid pfile_ui_set_class_stats(HeroClass playerClass, _uidefaultstats *classStats);\r\nuint32_t pfile_ui_get_first_unused_save_num();\r\nbool pfile_ui_save_create(_uiheroinfo *heroinfo);\r\nbool pfile_delete_save(_uiheroinfo *heroInfo);\r\nvoid pfile_read_player_from_save(uint32_t saveNum, Player &player);\r\nvoid pfile_save_level();\r\ntl::expected<void, std::string> pfile_convert_levels();\r\nvoid pfile_remove_temp_files();\r\nstd::unique_ptr<std::byte[]> pfile_read(const char *pszName, size_t *pdwLen);\r\nvoid pfile_update(bool forceSave);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/android/CMakeLists.txt",
    "content": "include(functions/devilutionx_library)\r\nadd_devilutionx_object_library(libdevilutionx_android android.cpp)\r\ntarget_link_dependencies(libdevilutionx_android PUBLIC\r\n  DevilutionX::SDL\r\n  libdevilutionx_init\r\n  libdevilutionx_mpq\r\n)\r\n"
  },
  {
    "path": "Source/platform/android/android.cpp",
    "content": "#include \"init.hpp\"\r\n#include \"mpq/mpq_reader.hpp\"\r\n\r\n#include <jni.h>\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nbool AreExtraFontsOutOfDateForMpqPath(const char *mpqPath)\r\n{\r\n\tint32_t error = 0;\r\n\tstd::optional<MpqArchive> archive = MpqArchive::Open(mpqPath, error);\r\n\treturn error == 0 && archive && AreExtraFontsOutOfDate(*archive);\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n\r\nextern \"C\" {\r\nJNIEXPORT jboolean JNICALL Java_org_diasurgical_devilutionx_DevilutionXSDLActivity_areFontsOutOfDate(JNIEnv *env, jclass cls, jstring fonts_mpq)\r\n{\r\n\tconst char *mpqPath = env->GetStringUTFChars(fonts_mpq, nullptr);\r\n\tbool outOfDate = devilution::AreExtraFontsOutOfDateForMpqPath(mpqPath);\r\n\tenv->ReleaseStringUTFChars(fonts_mpq, mpqPath);\r\n\treturn outOfDate;\r\n}\r\n}\r\n"
  },
  {
    "path": "Source/platform/ctr/CMakeLists.txt",
    "content": "include(functions/devilutionx_library)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_ctr\r\n  system.cpp\r\n  keyboard.cpp\r\n  display.cpp\r\n  messagebox.cpp\r\n  sockets.cpp\r\n  locale.cpp\r\n  asio/net/if.c\r\n  asio/sys/socket.c\r\n  asio/sys/uio.c\r\n)\r\n\r\nif(NOT NONET)\r\n  if(NOT DISABLE_TCP)\r\n    target_link_libraries(libdevilutionx_ctr PUBLIC asio)\r\n  endif()\r\n  if(PACKET_ENCRYPTION)\r\n    target_sources(libdevilutionx_ctr PRIVATE random.cpp)\r\n    target_link_libraries(libdevilutionx_ctr PUBLIC sodium)\r\n  endif()\r\nendif()\r\n\r\ntarget_link_libraries(libdevilutionx_ctr PUBLIC\r\n  DevilutionX::SDL\r\n  fmt::fmt\r\n  3ds::citro3d\r\n  3ds::ctrulib\r\n)\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/errno.h",
    "content": "#pragma once\r\n\r\n#include_next <errno.h>\r\n\r\n#define ESHUTDOWN (__ELASTERROR + 1)\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/net/if.h",
    "content": "#ifndef _NET_IF_H\r\n#define _NET_IF_H 1\r\n\r\n#define IF_NAMESIZE 16\r\n\r\nstruct if_nameindex {\r\n\tunsigned int if_index;\r\n\tchar *if_name;\r\n};\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\nunsigned int if_nametoindex(const char *__ifname);\r\nchar *if_indextoname(unsigned int __ifindex, char *__ifname);\r\nstruct if_nameindex *if_nameindex();\r\nvoid if_freenameindex(struct if_nameindex *__ptr);\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/netdb.h",
    "content": "#pragma once\r\n\r\n#include_next <netdb.h>\r\n\r\n#define EAI_SERVICE -401\r\n#define EAI_AGAIN -402\r\n#define EAI_BADFLAGS -403\r\n#define EAI_FAIL -404\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/netinet/in.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include_next <netinet/in.h>\r\n\r\nstruct in6_addr {\r\n\tuint8_t s6_addr[16];\r\n};\r\n\r\nstruct ipv6_mreq {\r\n\tstruct in6_addr ipv6mr_multiaddr;\r\n\tunsigned ipv6mr_interface;\r\n};\r\n\r\nstruct sockaddr_in6 {\r\n\tsa_family_t sin6_family;\r\n\tin_port_t sin6_port;\r\n\tuint32_t sin6_flowinfo;\r\n\tstruct in6_addr sin6_addr;\r\n\tuint32_t sin6_scope_id;\r\n};\r\n\r\n#define IPPROTO_IPV6 -1\r\n#define IP_MULTICAST_IF -1\r\n#define IPV6_JOIN_GROUP -1\r\n#define IPV6_LEAVE_GROUP -1\r\n#define IPV6_UNICAST_HOPS -1\r\n#define IPV6_MULTICAST_HOPS -1\r\n#define IPV6_MULTICAST_IF -1\r\n#define IPV6_MULTICAST_LOOP -1\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/sys/ioctl.h",
    "content": "#pragma once\r\n\r\n#include_next <sys/ioctl.h>\r\n\r\n#define FIONREAD -999\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/sys/poll.h",
    "content": "#include <poll.h>\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/sys/socket.h",
    "content": "#pragma once\r\n\r\n#include_next <sys/socket.h>\r\n\r\n#define SO_DEBUG 0\r\n#define SO_DONTROUTE 0\r\n#define SO_KEEPALIVE 0\r\n#define SOMAXCONN 10\r\n#define MSG_EOR 0\r\n\r\nstruct msghdr {\r\n\tvoid *msg_name;\r\n\tsocklen_t msg_namelen;\r\n\tstruct iovec *msg_iov;\r\n\tint msg_iovlen;\r\n\tvoid *msg_control;\r\n\tsocklen_t msg_controllen;\r\n\tint msg_flags;\r\n};\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\nssize_t recvmsg(int socket, struct msghdr *message, int flags);\r\nssize_t sendmsg(int socket, const struct msghdr *message, int flags);\r\nint socketpair(int domain, int type, int protocol, int socket_vector[2]);\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/sys/uio.h",
    "content": "#ifndef _SYS_UIO_H\r\n#define _SYS_UIO_H 1\r\n\r\n#include <sys/types.h>\r\n\r\nstruct iovec {\r\n\tvoid *iov_base;\r\n\tsize_t iov_len;\r\n};\r\n\r\nssize_t readv(int __fd, const struct iovec *__iovec, int __count);\r\nssize_t writev(int __fd, const struct iovec *__iovec, int __count);\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/include/sys/un.h",
    "content": "#ifndef _SYS_UN_H\r\n#define _SYS_UN_H 1\r\n\r\ntypedef unsigned short int sa_family_t;\r\n\r\nstruct sockaddr_un {\r\n\tsa_family_t sun_family;\r\n\tchar sun_path[108];\r\n};\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/ctr/asio/net/if.c",
    "content": "#include <errno.h>\n#include <net/if.h>\n#include <stddef.h>\n\nunsigned int if_nametoindex(const char *__ifname)\n{\n\treturn ENOTSUP;\n}\n\nchar *if_indextoname(unsigned int __ifindex, char *__ifname)\n{\n\treturn NULL;\n}\n\nstruct if_nameindex *if_nameindex()\n{\n\treturn NULL;\n}\n\nvoid if_freenameindex(struct if_nameindex *__ptr)\n{\n}\n"
  },
  {
    "path": "Source/platform/ctr/asio/sys/socket.c",
    "content": "#include <errno.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <sys/uio.h>\n\nssize_t stream_recvmsg(int socket, struct msghdr *message, int flags)\n{\n\tstruct iovec *next = message->msg_iov;\n\tint iovcount = message->msg_iovlen;\n\n\tssize_t total = 0;\n\tfor (int i = 0; i < iovcount; ++i, ++next) {\n\t\tstruct iovec *iov = next;\n\t\tvoid *base = iov->iov_base;\n\t\tsize_t length = iov->iov_len;\n\n\t\twhile (length > 0) {\n\t\t\tssize_t bytesReceived = recv(socket, base, length, flags);\n\t\t\tif (bytesReceived == -1) {\n\t\t\t\tif (total > 0 && errno == EAGAIN)\n\t\t\t\t\treturn total;\n\t\t\t\tif (total > 0 && errno == EWOULDBLOCK)\n\t\t\t\t\treturn total;\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tbase += bytesReceived;\n\t\t\tlength -= bytesReceived;\n\t\t\ttotal += bytesReceived;\n\n\t\t\tif ((flags & MSG_WAITALL) == 0)\n\t\t\t\treturn total;\n\t\t}\n\t}\n\treturn total;\n}\n\nssize_t dgram_recvmsg(int socket, struct msghdr *message, int flags)\n{\n\treturn ENOTSUP;\n}\n\nssize_t recvmsg(int socket, struct msghdr *message, int flags)\n{\n\tint type;\n\tsocklen_t length = sizeof(int);\n\tif (getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == -1)\n\t\treturn -1;\n\n\tif (type == SOCK_STREAM)\n\t\treturn stream_recvmsg(socket, message, flags);\n\tif (type == SOCK_DGRAM)\n\t\treturn dgram_recvmsg(socket, message, flags);\n\n\terrno = ENOTSOCK;\n\treturn -1;\n}\n\nssize_t stream_sendmsg(int socket, const struct msghdr *message, int flags)\n{\n\tstruct iovec *next = message->msg_iov;\n\tint iovcount = message->msg_iovlen;\n\n\tssize_t total = 0;\n\tfor (int i = 0; i < iovcount; ++i, ++next) {\n\t\tstruct iovec *iov = next;\n\t\tvoid *base = iov->iov_base;\n\t\tsize_t length = iov->iov_len;\n\t\tif (length == 0)\n\t\t\tcontinue;\n\n\t\tssize_t bytesSent = send(socket, base, length, flags);\n\t\tif (bytesSent == -1) {\n\t\t\tif (total > 0 && errno == EAGAIN)\n\t\t\t\treturn total;\n\t\t\tif (total > 0 && errno == EWOULDBLOCK)\n\t\t\t\treturn total;\n\t\t\treturn -1;\n\t\t}\n\t\ttotal += bytesSent;\n\t}\n\treturn total;\n}\n\nssize_t dgram_sendmsg(int socket, const struct msghdr *message, int flags)\n{\n\treturn ENOTSUP;\n}\n\nssize_t sendmsg(int socket, const struct msghdr *message, int flags)\n{\n\tint type;\n\tsocklen_t length = sizeof(int);\n\tif (getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == -1)\n\t\treturn -1;\n\n\tif (type == SOCK_STREAM)\n\t\treturn stream_sendmsg(socket, message, flags);\n\tif (type == SOCK_DGRAM)\n\t\treturn dgram_sendmsg(socket, message, flags);\n\n\terrno = ENOTSOCK;\n\treturn -1;\n}\n\nint socketpair(int domain, int type, int protocol, int socket_vector[2])\n{\n\treturn ENOTSUP;\n}\n"
  },
  {
    "path": "Source/platform/ctr/asio/sys/uio.c",
    "content": "#include <errno.h>\n#include <sys/types.h>\n#include <sys/uio.h>\n\nssize_t readv(int __fd, const struct iovec *__iovec, int __count)\n{\n\treturn ENOTSUP;\n}\n\nssize_t writev(int __fd, const struct iovec *__iovec, int __count)\n{\n\treturn ENOTSUP;\n}\n"
  },
  {
    "path": "Source/platform/ctr/cfgu_service.hpp",
    "content": "#pragma once\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n#include <3ds/result.h>\r\n#include <3ds/services/cfgu.h>\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\nnamespace devilution {\r\nnamespace n3ds {\r\n\r\nclass CFGUService {\r\npublic:\r\n\tCFGUService()\r\n\t{\r\n\t\tResult res = cfguInit();\r\n\t\tisInitialized = R_SUCCEEDED(res);\r\n\t}\r\n\r\n\t~CFGUService()\r\n\t{\r\n\t\tcfguExit();\r\n\t}\r\n\r\n\tbool IsInitialized()\r\n\t{\r\n\t\treturn isInitialized;\r\n\t}\r\n\r\nprivate:\r\n\tbool isInitialized;\r\n};\r\n\r\n} // namespace n3ds\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/ctr/display.cpp",
    "content": "#include \"platform/ctr/display.hpp\"\r\n#include <SDL.h>\r\n\r\n#include <cstdint>\r\nuint32_t Get3DSScalingFlag(bool fitToScreen, int width, int height)\r\n{\r\n\tif (fitToScreen)\r\n\t\treturn SDL_FULLSCREEN;\r\n\tif (width * 3 < height * 5)\r\n\t\treturn SDL_FITHEIGHT;\r\n\treturn SDL_FITWIDTH;\r\n}\r\n"
  },
  {
    "path": "Source/platform/ctr/display.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nuint32_t Get3DSScalingFlag(bool fitToScreen, int width, int height);\r\n"
  },
  {
    "path": "Source/platform/ctr/keyboard.cpp",
    "content": "#include <cstdlib>\r\n#include <cstring>\r\n\r\n#include \"platform/ctr/keyboard.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nconstexpr size_t MAX_TEXT_LENGTH = 255;\r\n\r\nstruct vkbdEvent {\r\n\tstd::string_view hintText;\r\n\tstd::string_view inText;\r\n\tchar *outText;\r\n\tsize_t maxLength;\r\n};\r\n\r\nstatic vkbdEvent events[16];\r\nstatic int eventCount = 0;\r\n\r\nvoid ctr_vkbdInput(std::string_view hintText, std::string_view inText, char *outText, size_t maxLength)\r\n{\r\n\tif (eventCount >= sizeof(events))\r\n\t\treturn;\r\n\r\n\tvkbdEvent &event = events[eventCount];\r\n\tevent.hintText = hintText;\r\n\tevent.inText = inText;\r\n\tevent.outText = outText;\r\n\tevent.maxLength = maxLength;\r\n\teventCount++;\r\n}\r\n\r\nvoid ctr_vkbdFlush()\r\n{\r\n\tfor (int i = 0; i < eventCount; i++) {\r\n\t\tvkbdEvent &event = events[i];\r\n\t\tSwkbdState swkbd;\r\n\r\n\t\tswkbdInit(&swkbd, SWKBD_TYPE_WESTERN, 2, MAX_TEXT_LENGTH);\r\n\t\tswkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, 0, 0);\r\n\r\n\t\t// swkbdSetInitialText stores the pointer to the c-string, only copying it when swkbdInputText is called. Need to\r\n\t\t//  ensure it has a valid null-terminated string until that point.\r\n\t\tstd::string initialText { event.inText };\r\n\t\tswkbdSetInitialText(&swkbd, initialText.c_str());\r\n\r\n\t\t// swkbdSetHintText copies from the c-string immediately so we can use the output buffer to save a malloc\r\n\t\tchar mybuf[MAX_TEXT_LENGTH + 1];\r\n\t\tdevilution::CopyUtf8(mybuf, event.hintText, sizeof(mybuf));\r\n\t\tswkbdSetHintText(&swkbd, mybuf);\r\n\r\n\t\tmemset(mybuf, 0, sizeof(mybuf));\r\n\t\tSwkbdButton button = swkbdInputText(&swkbd, mybuf, sizeof(mybuf));\r\n\r\n\t\tif (button == SWKBD_BUTTON_CONFIRM) {\r\n\t\t\tdevilution::CopyUtf8(event.outText, mybuf, event.maxLength);\r\n\t\t}\r\n\t}\r\n\r\n\teventCount = 0;\r\n}\r\n"
  },
  {
    "path": "Source/platform/ctr/keyboard.h",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\n#include <3ds.h>\r\n\r\n/**\r\n * @brief Queues a request for user input for the next call to ctr_vkbdFlush()\r\n * @see ctr_vkdbFlush()\r\n * @param title Label for the input\r\n * @param inText Optional text to prefil the input field\r\n * @param outText Pointer to a buffer to receive user input\r\n * @param maxLength Size of the buffer\r\n */\r\nvoid ctr_vkbdInput(std::string_view title, std::string_view inText, char *outText, size_t maxLength);\r\n\r\n/**\r\n * @brief Processes pending requests for user input\r\n */\r\nvoid ctr_vkbdFlush();\r\n"
  },
  {
    "path": "Source/platform/ctr/locale.cpp",
    "content": "#include \"platform/ctr/locale.hpp\"\r\n\r\n#include <3ds.h>\r\n\r\n#include \"platform/ctr/cfgu_service.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace n3ds {\r\n\r\nstd::string GetLocale()\r\n{\r\n\tCFGUService cfguService;\r\n\tif (!cfguService.IsInitialized())\r\n\t\treturn \"\";\r\n\r\n\tu8 language;\r\n\tResult res = CFGU_GetSystemLanguage(&language);\r\n\tif (!R_SUCCEEDED(res))\r\n\t\treturn \"\";\r\n\r\n\tswitch (language) {\r\n\tcase CFG_LANGUAGE_JP:\r\n\t\treturn \"ja\";\r\n\tcase CFG_LANGUAGE_EN:\r\n\t\treturn \"en\";\r\n\tcase CFG_LANGUAGE_FR:\r\n\t\treturn \"fr\";\r\n\tcase CFG_LANGUAGE_DE:\r\n\t\treturn \"de\";\r\n\tcase CFG_LANGUAGE_IT:\r\n\t\treturn \"it\";\r\n\tcase CFG_LANGUAGE_ES:\r\n\t\treturn \"es\";\r\n\tcase CFG_LANGUAGE_ZH:\r\n\t\treturn \"zh_CN\";\r\n\tcase CFG_LANGUAGE_KO:\r\n\t\treturn \"ko\";\r\n\tcase CFG_LANGUAGE_NL:\r\n\t\treturn \"nl\";\r\n\tcase CFG_LANGUAGE_PT:\r\n\t\treturn \"pt_BR\";\r\n\tcase CFG_LANGUAGE_RU:\r\n\t\treturn \"ru\";\r\n\tcase CFG_LANGUAGE_TW:\r\n\t\treturn \"zh_TW\";\r\n\tdefault:\r\n\t\treturn \"\";\r\n\t}\r\n}\r\n\r\n} // namespace n3ds\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/ctr/locale.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n\r\nnamespace devilution {\r\nnamespace n3ds {\r\n\r\nstd::string GetLocale();\r\n\r\n} // namespace n3ds\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/ctr/messagebox.cpp",
    "content": "#include <3ds.h>\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nint SDL_ShowSimpleMessageBox(Uint32 flags,\r\n    const char *title,\r\n    const char *message,\r\n    SDL_Surface *window)\r\n{\r\n\tif (SDL_ShowCursor(SDL_DISABLE) <= -1)\r\n\t\tSDL_Log(\"%s\", SDL_GetError());\r\n\r\n\tbool init = !gspHasGpuRight();\r\n\tauto text = devilution::StrCat(title, \"\\n\\n\", message);\r\n\r\n\tif (init)\r\n\t\tgfxInitDefault();\r\n\r\n\terrorConf error;\r\n\terrorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN);\r\n\terrorText(&error, text.c_str());\r\n\terrorDisp(&error);\r\n\r\n\tif (init)\r\n\t\tgfxExit();\r\n\r\n\treturn 0;\r\n}\r\n"
  },
  {
    "path": "Source/platform/ctr/random.cpp",
    "content": "#include <3ds.h>\r\n#include <cstdint>\r\n#include <sodium.h>\r\n#include <sys/types.h>\r\n\r\nstatic const char *randombytes_ctrrandom_implementation_name()\r\n{\r\n\treturn \"ctrrandom\";\r\n}\r\n\r\nstatic bool randombytes_ctrrandom_tryfill(void *const buf, const size_t size)\r\n{\r\n\tResult res;\r\n\tif (!psGetSessionHandle()) {\r\n\t\tres = psInit();\r\n\t\tif (!R_SUCCEEDED(res))\r\n\t\t\treturn false;\r\n\t}\r\n\tres = PS_GenerateRandomBytes(buf, size);\r\n\treturn R_SUCCEEDED(res);\r\n}\r\n\r\nstatic uint32_t randombytes_ctrrandom()\r\n{\r\n\tuint32_t num;\r\n\tif (!randombytes_ctrrandom_tryfill(&num, sizeof(uint32_t)))\r\n\t\tsodium_misuse();\r\n\treturn num;\r\n}\r\n\r\nstatic void randombytes_ctrrandom_buf(void *const buf, const size_t size)\r\n{\r\n\tif (!randombytes_ctrrandom_tryfill(buf, size))\r\n\t\tsodium_misuse();\r\n}\r\n\r\nstruct randombytes_implementation randombytes_ctrrandom_implementation = {\r\n\trandombytes_ctrrandom_implementation_name,\r\n\trandombytes_ctrrandom,\r\n\tnullptr,\r\n\tnullptr,\r\n\trandombytes_ctrrandom_buf,\r\n\tnullptr\r\n};\r\n\r\nvoid randombytes_ctrrandom_init()\r\n{\r\n\trandombytes_set_implementation(&randombytes_ctrrandom_implementation);\r\n}\r\n"
  },
  {
    "path": "Source/platform/ctr/random.hpp",
    "content": "#pragma once\r\nvoid randombytes_ctrrandom_init();\r\n"
  },
  {
    "path": "Source/platform/ctr/sockets.cpp",
    "content": "#include \"platform/ctr/sockets.hpp\"\r\n\r\n#include <cstdint>\r\n#include <malloc.h>\r\n\r\n// This header must be included before any 3DS code\r\n// because 3DS SDK defines a macro with the same name\r\n// as an fmt template parameter in some versions of fmt.\r\n// See https://github.com/fmtlib/fmt/issues/3632\r\n#include <fmt/core.h>\r\n\r\n#include <3ds.h>\r\n\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr auto SOC_ALIGN = 0x1000;\r\nconstexpr auto SOC_BUFFERSIZE = 0x100000;\r\nstatic u32 *socBuffer;\r\nstatic bool initialized;\r\n\r\nstatic bool waitForWifi()\r\n{\r\n\t// 100 ms\r\n\tconstexpr s64 sleepNano = 100 * 1000 * 1000;\r\n\r\n\t// 5 sec\r\n\tconstexpr int loopCount = 5 * 1000 / 100;\r\n\r\n\tuint32_t wifi = 0;\r\n\tfor (int i = 0; i < loopCount; ++i) {\r\n\t\tif (R_SUCCEEDED(ACU_GetWifiStatus(&wifi)) && wifi)\r\n\t\t\treturn true;\r\n\r\n\t\tsvcSleepThread(sleepNano);\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid n3ds_socExit()\r\n{\r\n\tif (socBuffer == nullptr)\r\n\t\treturn;\r\n\r\n\tsocExit();\r\n\tfree(socBuffer);\r\n\tsocBuffer = nullptr;\r\n}\r\n\r\nvoid n3ds_socInit()\r\n{\r\n\tif (!waitForWifi()) {\r\n\t\tLogError(\"n3ds_socInit: Wifi off\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tsocBuffer = (u32 *)memalign(SOC_ALIGN, SOC_BUFFERSIZE);\r\n\tif (socBuffer == nullptr) {\r\n\t\tLogError(\"n3ds_socInit: memalign() failed\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tResult result = socInit(socBuffer, SOC_BUFFERSIZE);\r\n\tif (!R_SUCCEEDED(result)) {\r\n\t\tLogError(\"n3ds_socInit: socInit() failed\");\r\n\t\tfree(socBuffer);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!initialized)\r\n\t\tatexit([]() { n3ds_socExit(); });\r\n\tinitialized = true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/ctr/sockets.hpp",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\n\r\nvoid n3ds_socInit();\r\nvoid n3ds_socExit();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/ctr/system.cpp",
    "content": "#include <3ds.h>\r\n#include <cstdio>\r\n#include <cstdlib>\r\n\r\n#include \"platform/ctr/cfgu_service.hpp\"\r\n#include \"platform/ctr/random.hpp\"\r\n#include \"platform/ctr/sockets.hpp\"\r\n#include \"platform/ctr/system.h\"\r\n\r\nusing namespace devilution;\r\n\r\nbool shouldDisableBacklight;\r\n\r\naptHookCookie cookie;\r\n\r\nvoid aptHookFunc(APT_HookType hookType, void *param)\r\n{\r\n\tswitch (hookType) {\r\n\tcase APTHOOK_ONSUSPEND:\r\n\t\tctr_lcd_backlight_on();\r\n\t\tbreak;\r\n\tcase APTHOOK_ONSLEEP:\r\n\t\tbreak;\r\n\tcase APTHOOK_ONRESTORE:\r\n\t\tctr_lcd_backlight_off();\r\n\t\tbreak;\r\n\tcase APTHOOK_ONWAKEUP:\r\n\t\tctr_lcd_backlight_off();\r\n\t\tbreak;\r\n\tcase APTHOOK_ONEXIT:\r\n\t\tctr_lcd_backlight_on();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid ctr_lcd_backlight_on()\r\n{\r\n\tif (!shouldDisableBacklight)\r\n\t\treturn;\r\n\tgspLcdInit();\r\n\tGSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTTOM);\r\n\tgspLcdExit();\r\n}\r\n\r\nvoid ctr_lcd_backlight_off()\r\n{\r\n\tif (!shouldDisableBacklight)\r\n\t\treturn;\r\n\tgspLcdInit();\r\n\tGSPLCD_PowerOffBacklight(GSPLCD_SCREEN_BOTTOM);\r\n\tgspLcdExit();\r\n}\r\n\r\nbool ctr_check_dsp()\r\n{\r\n\tFILE *dsp = fopen(\"sdmc:/3ds/dspfirm.cdc\", \"r\");\r\n\tif (dsp == NULL) {\r\n\t\tgfxInitDefault();\r\n\t\terrorConf error;\r\n\t\terrorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN);\r\n\t\terrorText(&error, \"Cannot find DSP firmware!\\n\\n\\\"sdmc:/3ds/dspfirm.cdc\\\"\\n\\nRun \\'DSP1\\' at least once to\\ndump your DSP firmware.\");\r\n\t\terrorDisp(&error);\r\n\t\tgfxExit();\r\n\t\treturn false;\r\n\t}\r\n\tfclose(dsp);\r\n\treturn true;\r\n}\r\n\r\nbool ctr_is_n3ds()\r\n{\r\n\tbool isN3DS;\r\n\tResult res = APT_CheckNew3DS(&isN3DS);\r\n\treturn R_SUCCEEDED(res) && isN3DS;\r\n}\r\n\r\nbool ctr_should_disable_backlight()\r\n{\r\n\tn3ds::CFGUService cfguService;\r\n\tif (!cfguService.IsInitialized())\r\n\t\treturn false;\r\n\r\n\tu8 model;\r\n\tResult res = CFGU_GetSystemModel(&model);\r\n\tif (!R_SUCCEEDED(res))\r\n\t\treturn false;\r\n\r\n\treturn model != CFG_MODEL_2DS;\r\n}\r\n\r\nvoid ctr_sys_init()\r\n{\r\n\tif (ctr_check_dsp() == false)\r\n\t\texit(0);\r\n\r\n\taptHook(&cookie, aptHookFunc, NULL);\r\n\r\n\tif (ctr_is_n3ds())\r\n\t\tosSetSpeedupEnable(true);\r\n\r\n\tshouldDisableBacklight = ctr_should_disable_backlight();\r\n\r\n\tctr_lcd_backlight_off();\r\n\tatexit([]() { ctr_lcd_backlight_on(); });\r\n\r\n\tromfsInit();\r\n\tatexit([]() { romfsExit(); });\r\n\r\n\tacInit();\r\n\tatexit([]() { acExit(); });\r\n\r\n\tn3ds_socInit();\r\n\tatexit([]() { n3ds_socExit(); });\r\n\r\n#ifdef PACKET_ENCRYPTION\r\n\trandombytes_ctrrandom_init();\r\n\tatexit([]() {\r\n\t\tif (psGetSessionHandle())\r\n\t\t\tpsExit();\r\n\t});\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Source/platform/ctr/system.h",
    "content": "#pragma once\r\n\r\nvoid ctr_lcd_backlight_on();\r\nvoid ctr_lcd_backlight_off();\r\n\r\nbool ctr_check_dsp();\r\n\r\nvoid ctr_sys_init();\r\n"
  },
  {
    "path": "Source/platform/ios/ios_paths.h",
    "content": "#pragma once\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\nextern char *IOSGetPrefPath();\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/ios/ios_paths.m",
    "content": "#import <Foundation/Foundation.h>\n\n#include \"ios_paths.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nchar *IOSGetPrefPath()\n{\n\t@autoreleasepool {\n\t\tNSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);\n\n\t\tif ([array count] > 0) {\n\t\t\tNSString *str = [array objectAtIndex:0];\n\t\t\tstr = [str stringByAppendingString:@\"/\"];\n\t\t\tconst char *base = [str fileSystemRepresentation];\n\n\t\t\tchar *copy = malloc(strlen(base) + 1);\n\t\t\tstrcpy(copy, base);\n\t\t\treturn copy;\n\t\t}\n\n\t\treturn \"\";\n\t}\n}\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "Source/platform/locale.cpp",
    "content": "#include \"locale.hpp\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#ifdef __ANDROID__\r\n#include <SDL.h>\r\n#include <jni.h>\r\n#elif defined(__vita__)\r\n#include <cstring>\r\n\r\n#include <psp2/apputil.h>\r\n#include <psp2/system_param.h>\r\n#elif defined(__3DS__)\r\n#include \"platform/ctr/locale.hpp\"\r\n#elif defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n// Suppress definitions of `min` and `max` macros by <windows.h>:\r\n#define NOMINMAX 1\r\n#define WIN32_LEAN_AND_MEAN\r\n// clang-format off\r\n#include <windows.h>\r\n#include <winnls.h>\r\n// clang-format on\r\n#elif defined(__APPLE__) and defined(USE_COREFOUNDATION)\r\n#include <CoreFoundation/CoreFoundation.h>\r\n#else\r\n#include <clocale>\r\n#endif\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\n#if (defined(_WIN32) && WINVER >= 0x0600 && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)) || (defined(__APPLE__) && defined(USE_COREFOUNDATION))\r\nstd::string IetfToPosix(std::string_view langCode)\r\n{\r\n\t/*\r\n\t * Handle special case for simplified/traditional Chinese. IETF/BCP-47 specifies that only the script should be\r\n\t *  used to discriminate languages when the region doesn't add additional value. For chinese scripts zh-Hans is\r\n\t *  preferred over zh-Hans-CN (but platforms may include the region identifier anyway). POSIX locales don't use\r\n\t *  script in the same way so we need to convert these back to lang_region.\r\n\t */\r\n\tif (langCode.substr(0, 7) == \"zh-Hans\") {\r\n\t\treturn \"zh_CN\";\r\n\t}\r\n\tif (langCode.substr(0, 7) == \"zh-Hant\") {\r\n\t\treturn \"zh_TW\";\r\n\t}\r\n\r\n\tstd::string posixLangCode { langCode };\r\n\r\n\t// if a region is included in the locale do a simple transformation to the expected POSIX style.\r\n\tstd::replace(posixLangCode.begin(), posixLangCode.end(), '-', '_');\r\n\r\n\treturn posixLangCode;\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\nstd::vector<std::string> GetLocales()\r\n{\r\n\tstd::vector<std::string> locales {};\r\n#ifdef __ANDROID__\r\n\tJNIEnv *env = (JNIEnv *)SDL_AndroidGetJNIEnv();\r\n\tjobject activity = (jobject)SDL_AndroidGetActivity();\r\n\tjclass clazz(env->GetObjectClass(activity));\r\n\tjmethodID method_id = env->GetMethodID(clazz, \"getLocale\", \"()Ljava/lang/String;\");\r\n\tjstring jLocale = (jstring)env->CallObjectMethod(activity, method_id);\r\n\tconst char *cLocale = env->GetStringUTFChars(jLocale, nullptr);\r\n\tlocales.emplace_back(cLocale);\r\n\tenv->ReleaseStringUTFChars(jLocale, cLocale);\r\n\tenv->DeleteLocalRef(jLocale);\r\n\tenv->DeleteLocalRef(activity);\r\n\tenv->DeleteLocalRef(clazz);\r\n#elif defined(__vita__)\r\n\tint32_t language = SCE_SYSTEM_PARAM_LANG_ENGLISH_US; // default to english\r\n\tconst char *vita_locales[] = {\r\n\t\t\"ja_JP\",\r\n\t\t\"en_US\",\r\n\t\t\"fr_FR\",\r\n\t\t\"es_ES\",\r\n\t\t\"de_DE\",\r\n\t\t\"it_IT\",\r\n\t\t\"nl_NL\",\r\n\t\t\"pt_PT\",\r\n\t\t\"ru_RU\",\r\n\t\t\"ko_KR\",\r\n\t\t\"zh_TW\",\r\n\t\t\"zh_CN\",\r\n\t\t\"fi_FI\",\r\n\t\t\"sv_SE\",\r\n\t\t\"da_DK\",\r\n\t\t\"no_NO\",\r\n\t\t\"pl_PL\",\r\n\t\t\"pt_BR\",\r\n\t\t\"en_GB\",\r\n\t\t\"tr_TR\",\r\n\t};\r\n\tSceAppUtilInitParam initParam;\r\n\tSceAppUtilBootParam bootParam;\r\n\tmemset(&initParam, 0, sizeof(SceAppUtilInitParam));\r\n\tmemset(&bootParam, 0, sizeof(SceAppUtilBootParam));\r\n\tsceAppUtilInit(&initParam, &bootParam);\r\n\tsceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_LANG, &language);\r\n\tif (language < 0 || language > SCE_SYSTEM_PARAM_LANG_TURKISH)\r\n\t\tlanguage = SCE_SYSTEM_PARAM_LANG_ENGLISH_US; // default to english\r\n\tlocales.emplace_back(vita_locales[language]);\r\n\tsceAppUtilShutdown();\r\n\r\n#elif defined(__ORBIS__)\r\n\t// use default\r\n#elif defined(__3DS__)\r\n\tlocales.push_back(n3ds::GetLocale());\r\n#elif defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n#if WINVER >= 0x0600\r\n\tauto wideCharToUtf8 = [](PWSTR wideString) {\r\n\t\t// WideCharToMultiByte potentially leaves the buffer unterminated, default initialise here as a workaround\r\n\t\tchar utf8Buffer[16] {};\r\n\r\n\t\t// Fetching up to 10 characters to allow for script tags\r\n\t\tWideCharToMultiByte(CP_UTF8, 0, wideString, 10, utf8Buffer, sizeof(utf8Buffer), nullptr, nullptr);\r\n\r\n\t\t// Windows NLS functions return IETF/BCP-47 locale codes (or potentially arbitrary custom locales) but devX\r\n\t\t//  uses posix format codes, return the expected format\r\n\t\treturn std::move(IetfToPosix(utf8Buffer));\r\n\t};\r\n\r\n\tWCHAR localeBuffer[LOCALE_NAME_MAX_LENGTH];\r\n\r\n\tif (GetUserDefaultLocaleName(localeBuffer, sizeof(localeBuffer)) != 0) {\r\n\t\t// Found a user default locale convert from WIN32's default of UTF16 to UTF8 and add to the list\r\n\t\tlocales.push_back(wideCharToUtf8(localeBuffer));\r\n\t}\r\n\r\n\tULONG numberOfLanguages;\r\n\tULONG bufferSize = sizeof(localeBuffer);\r\n\tGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numberOfLanguages, localeBuffer, &bufferSize);\r\n\r\n\tPWSTR bufferOffset = localeBuffer;\r\n\tfor (unsigned i = 0; i < numberOfLanguages; i++) {\r\n\t\t// Found one (or more) user preferred UI language(s), add these to the list to check as well\r\n\t\tlocales.push_back(wideCharToUtf8(bufferOffset));\r\n\r\n\t\t// GetUserPreferredUILanguages returns a null separated list of strings, need to increment past the null terminating\r\n\t\t//  the current string.\r\n\t\tbufferOffset += lstrlenW(localeBuffer) + 1;\r\n\t}\r\n#else\r\n\t// Fallback method for older versions of windows, this is deprecated since Vista\r\n\tchar localeBuffer[LOCALE_NAME_MAX_LENGTH];\r\n\t// Deliberately not using the unicode versions here as the information retrieved should be represented in ASCII/single\r\n\t//  byte UTF8 codepoints.\r\n\tif (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, localeBuffer, LOCALE_NAME_MAX_LENGTH) != 0) {\r\n\t\tstd::string locale { localeBuffer };\r\n\t\tif (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, localeBuffer, LOCALE_NAME_MAX_LENGTH) != 0) {\r\n\t\t\tlocale.append(\"_\");\r\n\t\t\tlocale.append(localeBuffer);\r\n\t\t}\r\n\t\tlocales.push_back(std::move(locale));\r\n\t}\r\n#endif\r\n#elif defined(__APPLE__) && defined(USE_COREFOUNDATION) && DARWIN_MAJOR_VERSION >= 9\r\n\t// Get the user's language list (in order of preference)\r\n\tCFArrayRef languages = CFLocaleCopyPreferredLanguages();\r\n\tCFIndex numLanguages = CFArrayGetCount(languages);\r\n\r\n\tfor (CFIndex i = 0; i < numLanguages; i++) {\r\n\t\tauto language = static_cast<CFStringRef>(CFArrayGetValueAtIndex(languages, i));\r\n\r\n\t\tchar buffer[16];\r\n\r\n\t\tif (CFStringGetCString(language, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {\r\n\t\t\t// Convert to the posix format expected by callers\r\n\t\t\tlocales.push_back(IetfToPosix(buffer));\r\n\t\t}\r\n\t}\r\n\r\n\tCFRelease(languages);\r\n#else\r\n\tconstexpr auto svOrEmpty = [](const char *cString) -> std::string_view {\r\n\t\treturn cString != nullptr ? cString : \"\";\r\n\t};\r\n\tstd::string_view languages = svOrEmpty(std::getenv(\"LANGUAGE\"));\r\n\tif (languages.empty()) {\r\n\t\tlanguages = svOrEmpty(std::getenv(\"LANG\"));\r\n\t\tif (languages.empty()) {\r\n\t\t\t// Ideally setlocale with a POSIX defined constant should never return NULL, but...\r\n#ifdef LC_MESSAGES\r\n\t\t\tlanguages = svOrEmpty(setlocale(LC_MESSAGES, nullptr));\r\n#else\r\n\t\t\tlanguages = svOrEmpty(setlocale(LC_CTYPE, nullptr));\r\n#endif\r\n\t\t}\r\n\t\tif (!languages.empty())\r\n\t\t\tlocales.emplace_back(languages.substr(0, languages.find_first_of(\".\")));\r\n\t} else {\r\n\t\tdo {\r\n\t\t\tconst size_t separatorPos = languages.find_first_of(\":\");\r\n\t\t\tif (separatorPos != 0)\r\n\t\t\t\tlocales.emplace_back(std::string(languages.substr(0, separatorPos)));\r\n\r\n\t\t\tif (separatorPos != languages.npos)\r\n\t\t\t\tlanguages.remove_prefix(separatorPos + 1);\r\n\t\t\telse\r\n\t\t\t\tbreak;\r\n\t\t} while (true);\r\n\t}\r\n#endif\r\n\treturn locales;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/locale.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n#include <vector>\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Returns a list of preferred languages based on user/system configuration.\r\n * @return 0 or more POSIX locale codes (language code with optional region identifier)\r\n */\r\nstd::vector<std::string> GetLocales();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/macos_sdl1/SDL_filesystem.m",
    "content": "/*\r\n  Simple DirectMedia Layer\r\n  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>\r\n\r\n  This software is provided 'as-is', without any express or implied\r\n  warranty.  In no event will the authors be held liable for any damages\r\n  arising from the use of this software.\r\n\r\n  Permission is granted to anyone to use this software for any purpose,\r\n  including commercial applications, and to alter it and redistribute it\r\n  freely, subject to the following restrictions:\r\n\r\n  1. The origin of this software must not be misrepresented; you must not\r\n     claim that you wrote the original software. If you use this software\r\n     in a product, an acknowledgment in the product documentation would be\r\n     appreciated but is not required.\r\n  2. Altered source versions must be plainly marked as such, and must not be\r\n     misrepresented as being the original software.\r\n  3. This notice may not be removed or altered from any source distribution.\r\n\r\n  An altered version based on:\r\n    https://github.com/libsdl-org/SDL/blob/3c142abcb2b0b0ad7e08b096ea8d9a1a1e1af1ef/src/filesystem/cocoa/SDL_sysfilesystem.m\r\n\r\n  Modifications:\r\n    1. Changes to compile with gcc (@autoreleasepool -> NSAutoreleasePool)\r\n    2. Targets SDL-1.2 rather than SDL2 (SDL_InvalidParamError -> SDL_SetError)\r\n*/\r\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\r\n/* System dependent filesystem routines                                */\r\n\r\n#include <Foundation/Foundation.h>\r\n#include <sys/stat.h>\r\n#include <sys/types.h>\r\n\r\n#include <SDL.h>\r\n\r\nchar *SDL_GetBasePath(void)\r\n{\r\n\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r\n\tNSBundle *bundle = [NSBundle mainBundle];\r\n\tconst char *baseType = [[[bundle infoDictionary] objectForKey:@\"SDL_FILESYSTEM_BASE_DIR_TYPE\"] UTF8String];\r\n\tconst char *base = NULL;\r\n\tchar *retval = NULL;\r\n\r\n\tif (baseType == NULL) {\r\n\t\tbaseType = \"resource\";\r\n\t}\r\n\tif (SDL_strcasecmp(baseType, \"bundle\") == 0) {\r\n\t\tbase = [[bundle bundlePath] fileSystemRepresentation];\r\n\t} else if (SDL_strcasecmp(baseType, \"parent\") == 0) {\r\n\t\tbase = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation];\r\n\t} else {\r\n\t\t/* this returns the exedir for non-bundled  and the resourceDir for bundled apps */\r\n\t\tbase = [[bundle resourcePath] fileSystemRepresentation];\r\n\t}\r\n\r\n\tif (base) {\r\n\t\tconst size_t len = SDL_strlen(base) + 2;\r\n\t\tretval = (char *)SDL_malloc(len);\r\n\t\tif (retval == NULL) {\r\n\t\t\tSDL_OutOfMemory();\r\n\t\t} else {\r\n\t\t\tSDL_snprintf(retval, len, \"%s/\", base);\r\n\t\t}\r\n\t}\r\n\r\n\t[pool drain];\r\n\treturn retval;\r\n}\r\n\r\nchar *SDL_GetPrefPath(const char *org, const char *app)\r\n{\r\n\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r\n\tchar *retval = NULL;\r\n\tNSArray *array;\r\n\r\n\tif (!app) {\r\n\t\tSDL_SetError(\"SDL_GetPrefPath: app argument cannot be null\");\r\n\t\treturn NULL;\r\n\t}\r\n\tif (!org) {\r\n\t\torg = \"\";\r\n\t}\r\n\r\n#if !TARGET_OS_TV\r\n\tarray = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);\r\n#else\r\n\t/* tvOS does not have persistent local storage!\r\n\t * The only place on-device where we can store data is\r\n\t * a cache directory that the OS can empty at any time.\r\n\t *\r\n\t * It's therefore very likely that save data will be erased\r\n\t * between sessions. If you want your app's save data to\r\n\t * actually stick around, you'll need to use iCloud storage.\r\n\t */\r\n\t{\r\n\t\tstatic SDL_bool shown = SDL_FALSE;\r\n\t\tif (!shown) {\r\n\t\t\tshown = SDL_TRUE;\r\n\t\t\tSDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, \"tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\\n\");\r\n\t\t}\r\n\t}\r\n\r\n\tarray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);\r\n#endif /* !TARGET_OS_TV */\r\n\r\n\tif ([array count] > 0) { /* we only want the first item in the list. */\r\n\t\tNSString *str = [array objectAtIndex:0];\r\n\t\tconst char *base = [str fileSystemRepresentation];\r\n\t\tif (base) {\r\n\t\t\tconst size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;\r\n\t\t\tretval = (char *)SDL_malloc(len);\r\n\t\t\tif (retval == NULL) {\r\n\t\t\t\tSDL_OutOfMemory();\r\n\t\t\t} else {\r\n\t\t\t\tchar *ptr;\r\n\t\t\t\tif (*org) {\r\n\t\t\t\t\tSDL_snprintf(retval, len, \"%s/%s/%s/\", base, org, app);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tSDL_snprintf(retval, len, \"%s/%s/\", base, app);\r\n\t\t\t\t}\r\n\t\t\t\tfor (ptr = retval + 1; *ptr; ptr++) {\r\n\t\t\t\t\tif (*ptr == '/') {\r\n\t\t\t\t\t\t*ptr = '\\0';\r\n\t\t\t\t\t\tmkdir(retval, 0700);\r\n\t\t\t\t\t\t*ptr = '/';\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tmkdir(retval, 0700);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t[pool drain];\r\n\treturn retval;\r\n}\r\n\r\n/* vi: set ts=4 sw=4 expandtab: */\r\n"
  },
  {
    "path": "Source/platform/switch/CMakeLists.txt",
    "content": "include(functions/devilutionx_library)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_switch\r\n  romfs.cpp\r\n  network.cpp\r\n  keyboard.cpp\r\n  docking.cpp\r\n  asio/pause.c\r\n  asio/net/if.c\r\n  asio/sys/signal.c\r\n)\r\n\r\nif(NOT NONET)\r\n  if(NOT DISABLE_TCP)\r\n    target_link_libraries(libdevilutionx_switch PUBLIC asio)\r\n  endif()\r\n  if(PACKET_ENCRYPTION)\r\n    target_sources(libdevilutionx_switch PRIVATE random.cpp)\r\n    target_link_libraries(libdevilutionx_switch PUBLIC sodium)\r\n  endif()\r\nendif()\r\n\r\ntarget_link_libraries(libdevilutionx_switch PUBLIC\r\n  DevilutionX::SDL\r\n  libdevilutionx_log\r\n)\r\n"
  },
  {
    "path": "Source/platform/switch/asio/include/errno.h",
    "content": "#pragma once\r\n\r\n#include_next <errno.h>\r\n\r\n#define ESHUTDOWN (__ELASTERROR + 1)\r\n"
  },
  {
    "path": "Source/platform/switch/asio/include/net/if.h",
    "content": "#ifndef _NET_IF_H\r\n#define _NET_IF_H 1\r\n\r\n#define IF_NAMESIZE 16\r\n\r\nstruct if_nameindex {\r\n\tunsigned int if_index;\r\n\tchar *if_name;\r\n};\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\nunsigned int if_nametoindex(const char *__ifname);\r\nchar *if_indextoname(unsigned int __ifindex, char *__ifname);\r\nstruct if_nameindex *if_nameindex();\r\nvoid if_freenameindex(struct if_nameindex *__ptr);\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/switch/asio/include/netinet/in.h",
    "content": "#pragma once\r\n\r\n#include_next <netinet/in.h>\r\n\r\nstruct ipv6_mreq {\r\n\tstruct in6_addr ipv6mr_multiaddr;\r\n\tunsigned ipv6mr_interface;\r\n};\r\n"
  },
  {
    "path": "Source/platform/switch/asio/include/sys/uio.h",
    "content": "#ifndef _SYS_UIO_H\r\n#define _SYS_UIO_H 1\r\n\r\n#include <sys/_iovec.h>\r\n#include <sys/types.h>\r\n\r\nssize_t readv(int __fd, const struct iovec *__iovec, int __count);\r\nssize_t writev(int __fd, const struct iovec *__iovec, int __count);\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/switch/asio/include/sys/un.h",
    "content": "#ifndef _SYS_UN_H\r\n#define _SYS_UN_H 1\r\n\r\n#include <sys/types.h>\r\n\r\n#ifndef _SA_FAMILY_T_DECLARED\r\ntypedef __sa_family_t sa_family_t;\r\n#define _SA_FAMILY_T_DECLARED\r\n#endif\r\n\r\nstruct sockaddr_un {\r\n\tsa_family_t sun_family;\r\n\tchar sun_path[108];\r\n};\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/platform/switch/asio/net/if.c",
    "content": "#include <errno.h>\n#include <net/if.h>\n#include <stddef.h>\n\nunsigned int if_nametoindex(const char *__ifname)\n{\n\treturn ENOTSUP;\n}\n\nchar *if_indextoname(unsigned int __ifindex, char *__ifname)\n{\n\treturn NULL;\n}\n\nstruct if_nameindex *if_nameindex()\n{\n\treturn NULL;\n}\n\nvoid if_freenameindex(struct if_nameindex *__ptr)\n{\n}\n"
  },
  {
    "path": "Source/platform/switch/asio/pause.c",
    "content": "#include <errno.h>\r\n\r\nint pause(void)\r\n{\r\n\terrno = ENOSYS;\r\n\treturn -1;\r\n}"
  },
  {
    "path": "Source/platform/switch/asio/sys/signal.c",
    "content": "#include <errno.h>\n#include <sys/signal.h>\n\nint pthread_sigmask(int, const sigset_t *, sigset_t *)\n{\n\treturn ENOTSUP;\n}\n"
  },
  {
    "path": "Source/platform/switch/docking.cpp",
    "content": "#include \"platform/switch/docking.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include <SDL.h>\r\n#include <switch.h>\r\n\r\n#include \"utils/display.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nenum class OperationMode : int8_t {\r\n\tHandheld,\r\n\tDocked,\r\n\tUninitialized = -1\r\n};\r\n}\r\n\r\n/**\r\n * @brief Do a manual window resize when docking/undocking the Switch\r\n */\r\nvoid HandleDocking()\r\n{\r\n\tstatic OperationMode currentMode = OperationMode::Uninitialized; // keep track of docked or handheld mode\r\n\r\n\tOperationMode newMode;\r\n\tswitch (appletGetOperationMode()) {\r\n\tcase AppletOperationMode_Console:\r\n\t\tnewMode = OperationMode::Docked;\r\n\t\tbreak;\r\n\tcase AppletOperationMode_Handheld:\r\n\tdefault:\r\n\t\tnewMode = OperationMode::Handheld;\r\n\t}\r\n\r\n\tif (currentMode != newMode) {\r\n\t\tint display_width;\r\n\t\tint display_height;\r\n\r\n\t\t// docked mode has changed, update window size\r\n\t\tif (newMode == OperationMode::Docked) {\r\n\t\t\tdisplay_width = 1920;\r\n\t\t\tdisplay_height = 1080;\r\n\t\t} else {\r\n\t\t\tdisplay_width = 1280;\r\n\t\t\tdisplay_height = 720;\r\n\t\t}\r\n\t\tcurrentMode = newMode;\r\n\r\n\t\t// remove leftover-garbage on screen. Need to perform three clears to ensure all buffers get cleared, otherwise\r\n\t\t//  the display flickers showing a stale frame at certain refresh rates/dock modes.\r\n\t\tfor (auto i = 0; i < 3; i++) {\r\n\t\t\tSDL_RenderClear(renderer);\r\n\t\t\tSDL_RenderPresent(renderer);\r\n\t\t}\r\n\t\tSDL_SetWindowSize(ghMainWnd, display_width, display_height);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/switch/docking.h",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\n\r\nvoid HandleDocking();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/switch/keyboard.cpp",
    "content": "#include \"platform/switch/keyboard.h\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include <SDL.h>\r\n#include <switch.h>\r\n\r\n#include \"utils/utf8.hpp\"\r\n\r\nstatic void switch_keyboard_get(std::string_view guide_text, std::string_view initial_text, char *buf, unsigned buf_len)\r\n{\r\n\tResult rc = 0;\r\n\r\n\tSwkbdConfig kbd;\r\n\r\n\trc = swkbdCreate(&kbd, 0);\r\n\r\n\tif (R_SUCCEEDED(rc)) {\r\n\t\tswkbdConfigMakePresetDefault(&kbd);\r\n\r\n\t\t// swkbConfigSetGuide/InitialText both copy the input string. They expect a null terminated c-string but we're\r\n\t\t//  getting a string view which may be a substring of a larger std::string/c-string, so we copy to a temporary\r\n\t\t//  null-terminated string first for safety\r\n\t\tif (!guide_text.empty()) {\r\n\t\t\tstd::string textCopy { guide_text };\r\n\t\t\tswkbdConfigSetGuideText(&kbd, textCopy.c_str());\r\n\t\t}\r\n\t\tif (!initial_text.empty()) {\r\n\t\t\tstd::string textCopy { initial_text };\r\n\t\t\tswkbdConfigSetInitialText(&kbd, textCopy.c_str());\r\n\t\t}\r\n\r\n\t\tswkbdConfigSetStringLenMax(&kbd, buf_len);\r\n\t\trc = swkbdShow(&kbd, buf, buf_len);\r\n\t\tswkbdClose(&kbd);\r\n\t}\r\n}\r\n\r\nstatic int get_utf8_character_bytes(const uint8_t *uc)\r\n{\r\n\tif (uc[0] < 0x80) {\r\n\t\treturn 1;\r\n\t} else if ((uc[0] & 0xe0) == 0xc0 && (uc[1] & 0xc0) == 0x80) {\r\n\t\treturn 2;\r\n\t} else if ((uc[0] & 0xf0) == 0xe0 && (uc[1] & 0xc0) == 0x80 && (uc[2] & 0xc0) == 0x80) {\r\n\t\treturn 3;\r\n\t} else if ((uc[0] & 0xf8) == 0xf0 && (uc[1] & 0xc0) == 0x80 && (uc[2] & 0xc0) == 0x80 && (uc[3] & 0xc0) == 0x80) {\r\n\t\treturn 4;\r\n\t} else {\r\n\t\treturn 1;\r\n\t}\r\n}\r\n\r\nstatic void switch_create_and_push_sdlkey_event(uint32_t event_type, SDL_Scancode scan, SDL_Keycode key)\r\n{\r\n\tSDL_Event event;\r\n\tevent.type = event_type;\r\n\tevent.key.keysym.scancode = scan;\r\n\tevent.key.keysym.sym = key;\r\n\tevent.key.keysym.mod = 0;\r\n\tSDL_PushEvent(&event);\r\n}\r\n\r\nvoid switch_start_text_input(std::string_view guide_text, std::string_view initial_text, unsigned max_length)\r\n{\r\n\tchar text[max_length] = { '\\0' };\r\n\tswitch_keyboard_get(guide_text, initial_text, text, sizeof(text));\r\n\tfor (int i = 0; i < 600; i++) {\r\n\t\tswitch_create_and_push_sdlkey_event(SDL_KEYDOWN, SDL_SCANCODE_BACKSPACE, SDLK_BACKSPACE);\r\n\t\tswitch_create_and_push_sdlkey_event(SDL_KEYUP, SDL_SCANCODE_BACKSPACE, SDLK_BACKSPACE);\r\n\t}\r\n\tfor (int i = 0; i < 600; i++) {\r\n\t\tswitch_create_and_push_sdlkey_event(SDL_KEYDOWN, SDL_SCANCODE_DELETE, SDLK_DELETE);\r\n\t\tswitch_create_and_push_sdlkey_event(SDL_KEYUP, SDL_SCANCODE_DELETE, SDLK_DELETE);\r\n\t}\r\n\tif (text[0] == '\\0') {\r\n\t\tdevilution::CopyUtf8(text, initial_text, sizeof(text));\r\n\t}\r\n\tconst uint8_t *utf8_text = (uint8_t *)text;\r\n\tfor (int i = 0; i < sizeof(text) && utf8_text[i];) {\r\n\t\tint bytes_in_char = get_utf8_character_bytes(&utf8_text[i]);\r\n\t\tSDL_Event textinput_event;\r\n\t\ttextinput_event.type = SDL_TEXTINPUT;\r\n\t\tfor (int n = 0; n < bytes_in_char; n++) {\r\n\t\t\ttextinput_event.text.text[n] = text[i + n];\r\n\t\t}\r\n\t\ttextinput_event.text.text[bytes_in_char] = 0;\r\n\t\tSDL_PushEvent(&textinput_event);\r\n\t\ti += bytes_in_char;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "Source/platform/switch/keyboard.h",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\n/**\r\n * @brief Prompts the user for text input, pushes the user-provided text to the event queue, then returns\r\n * @param guide_text Hint text to display to the user if the input is empty\r\n * @param initial_text An optional prefilled value for the input\r\n * @param max_length How many bytes of input to accept from the user (certain characters will take multiple bytes)\r\n */\r\nvoid switch_start_text_input(std::string_view guide_text, std::string_view initial_text, unsigned max_length);\r\n"
  },
  {
    "path": "Source/platform/switch/network.cpp",
    "content": "#include \"platform/switch/network.h\"\r\n#include <cstdlib>\r\n#include <switch.h>\r\n#include <unistd.h>\r\n\r\nstatic int nxlink_sock = -1; // for stdio on Switch\r\n\r\nvoid switch_enable_network()\r\n{\r\n\t// enable network and stdio on Switch\r\n\tsocketInitializeDefault();\r\n\t// enable error messages via nxlink on Switch\r\n\tnxlink_sock = nxlinkStdio();\r\n\tatexit(switch_disable_network);\r\n}\r\n\r\nvoid switch_disable_network()\r\n{\r\n\t// disable network and stdio on Switch\r\n\tif (nxlink_sock != -1)\r\n\t\tclose(nxlink_sock);\r\n\tsocketExit();\r\n}\r\n"
  },
  {
    "path": "Source/platform/switch/network.h",
    "content": "#pragma once\r\n\r\nvoid switch_enable_network();\r\nvoid switch_disable_network();\r\n"
  },
  {
    "path": "Source/platform/switch/random.cpp",
    "content": "#include \"platform/switch/random.hpp\"\r\n\r\n#include <cstdint>\r\n#include <sys/types.h>\r\n\r\n#include <sodium.h>\r\n\r\nextern \"C\" {\r\n#include <switch/services/csrng.h>\r\n#include <switch/sf/service.h>\r\n}\r\n\r\nstatic const char *randombytes_switchrandom_implementation_name()\r\n{\r\n\treturn \"switchrandom\";\r\n}\r\n\r\nstatic bool randombytes_switchrandom_tryfill(void *const buf, const size_t size)\r\n{\r\n\tResult res;\r\n\tService *csrngService = csrngGetServiceSession();\r\n\tif (!serviceIsActive(csrngService)) {\r\n\t\tres = csrngInitialize();\r\n\t\tif (!R_SUCCEEDED(res))\r\n\t\t\treturn false;\r\n\t}\r\n\tres = csrngGetRandomBytes(buf, size);\r\n\treturn R_SUCCEEDED(res);\r\n}\r\n\r\nstatic uint32_t randombytes_switchrandom()\r\n{\r\n\tuint32_t num;\r\n\tif (!randombytes_switchrandom_tryfill(&num, sizeof(uint32_t)))\r\n\t\tsodium_misuse();\r\n\treturn num;\r\n}\r\n\r\nstatic void randombytes_switchrandom_buf(void *const buf, const size_t size)\r\n{\r\n\tif (!randombytes_switchrandom_tryfill(buf, size))\r\n\t\tsodium_misuse();\r\n}\r\n\r\nstruct randombytes_implementation randombytes_switchrandom_implementation = {\r\n\trandombytes_switchrandom_implementation_name,\r\n\trandombytes_switchrandom,\r\n\tnullptr,\r\n\tnullptr,\r\n\trandombytes_switchrandom_buf,\r\n\tnullptr\r\n};\r\n\r\nvoid randombytes_switchrandom_init()\r\n{\r\n\trandombytes_set_implementation(&randombytes_switchrandom_implementation);\r\n\tatexit(csrngExit);\r\n}\r\n"
  },
  {
    "path": "Source/platform/switch/random.hpp",
    "content": "#pragma once\r\nvoid randombytes_switchrandom_init();\r\n"
  },
  {
    "path": "Source/platform/switch/romfs.cpp",
    "content": "#include \"platform/switch/romfs.hpp\"\r\n\r\n#include <cstdlib>\r\n\r\nextern \"C\" {\r\n#include <switch/runtime/devices/romfs_dev.h>\r\n}\r\n\r\nvoid switch_romfs_init()\r\n{\r\n\tResult res = romfsInit();\r\n\tif (R_SUCCEEDED(res))\r\n\t\tatexit([]() { romfsExit(); });\r\n}"
  },
  {
    "path": "Source/platform/switch/romfs.hpp",
    "content": "#pragma once\r\nvoid switch_romfs_init();\r\n"
  },
  {
    "path": "Source/platform/vita/CMakeLists.txt",
    "content": "include(functions/devilutionx_library)\r\n\r\nadd_devilutionx_object_library(libdevilutionx_vita\r\n  network.cpp\r\n  keyboard.cpp\r\n  touch.cpp\r\n)\r\n\r\nif(NOT NONET)\r\n  if(NOT DISABLE_TCP)\r\n    target_link_libraries(libdevilutionx_vita PUBLIC asio)\r\n  endif()\r\n  if(PACKET_ENCRYPTION)\r\n    target_sources(libdevilutionx_vita PRIVATE random.cpp)\r\n    target_link_libraries(libdevilutionx_vita PUBLIC sodium)\r\n  endif()\r\nendif()\r\n\r\ntarget_link_libraries(libdevilutionx_vita PUBLIC\r\n  DevilutionX::SDL\r\n  ScePower_stub\r\n  SceAppUtil_stub\r\n  SceNet_stub\r\n  SceNetCtl_stub\r\n  libdevilutionx_options\r\n)\r\n"
  },
  {
    "path": "Source/platform/vita/keyboard.cpp",
    "content": "#include \"platform/vita/keyboard.h\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include <SDL.h>\r\n#include <psp2/ime_dialog.h>\r\n#include <psp2/types.h>\r\n\r\nstatic void utf16_to_utf8(const uint16_t *src, uint8_t *dst)\r\n{\r\n\tfor (int i = 0; src[i]; i++) {\r\n\t\tif ((src[i] & 0xFF80) == 0) {\r\n\t\t\t*(dst++) = src[i] & 0xFF;\r\n\t\t} else if ((src[i] & 0xF800) == 0) {\r\n\t\t\t*(dst++) = ((src[i] >> 6) & 0xFF) | 0xC0;\r\n\t\t\t*(dst++) = (src[i] & 0x3F) | 0x80;\r\n\t\t} else if ((src[i] & 0xFC00) == 0xD800 && (src[i + 1] & 0xFC00) == 0xDC00) {\r\n\t\t\t*(dst++) = (((src[i] + 64) >> 8) & 0x3) | 0xF0;\r\n\t\t\t*(dst++) = (((src[i] >> 2) + 16) & 0x3F) | 0x80;\r\n\t\t\t*(dst++) = ((src[i] >> 4) & 0x30) | 0x80 | ((src[i + 1] << 2) & 0xF);\r\n\t\t\t*(dst++) = (src[i + 1] & 0x3F) | 0x80;\r\n\t\t\ti += 1;\r\n\t\t} else {\r\n\t\t\t*(dst++) = ((src[i] >> 12) & 0xF) | 0xE0;\r\n\t\t\t*(dst++) = ((src[i] >> 6) & 0x3F) | 0x80;\r\n\t\t\t*(dst++) = (src[i] & 0x3F) | 0x80;\r\n\t\t}\r\n\t}\r\n\r\n\t*dst = '\\0';\r\n}\r\n\r\nstatic void utf8_to_utf16(const uint8_t *src, size_t src_size, uint16_t *dst)\r\n{\r\n\tfor (size_t i = 0; i < src_size && src[i];) {\r\n\t\tif ((src[i] & 0xE0) == 0xE0) {\r\n\t\t\tif (i + 2 >= src_size) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t*(dst++) = ((src[i] & 0x0F) << 12) | ((src[i + 1] & 0x3F) << 6) | (src[i + 2] & 0x3F);\r\n\t\t\ti += 3;\r\n\t\t} else if ((src[i] & 0xC0) == 0xC0) {\r\n\t\t\tif (i + 1 >= src_size) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t*(dst++) = ((src[i] & 0x1F) << 6) | (src[i + 1] & 0x3F);\r\n\t\t\ti += 2;\r\n\t\t} else {\r\n\t\t\t*(dst++) = src[i];\r\n\t\t\ti += 1;\r\n\t\t}\r\n\t}\r\n\r\n\t*dst = '\\0';\r\n}\r\n\r\nstatic int vita_input_thread(void *ime_buffer)\r\n{\r\n\twhile (1) {\r\n\t\t// update IME status. Terminate, if finished\r\n\t\tSceCommonDialogStatus dialogStatus = sceImeDialogGetStatus();\r\n\t\tif (dialogStatus == SCE_COMMON_DIALOG_STATUS_FINISHED) {\r\n\t\t\tuint8_t utf8_buffer[SCE_IME_DIALOG_MAX_TEXT_LENGTH];\r\n\t\t\tSceImeDialogResult result;\r\n\r\n\t\t\tSDL_memset(&result, 0, sizeof(SceImeDialogResult));\r\n\t\t\tsceImeDialogGetResult(&result);\r\n\r\n\t\t\t// Convert UTF16 to UTF8\r\n\t\t\tutf16_to_utf8((SceWChar16 *)ime_buffer, utf8_buffer);\r\n\r\n\t\t\t// send sdl event\r\n\t\t\tSDL_Event event;\r\n\t\t\tevent.text.type = SDL_TEXTINPUT;\r\n\t\t\tSDL_utf8strlcpy(event.text.text, (const char *)utf8_buffer, SDL_arraysize(event.text.text));\r\n\t\t\tSDL_PushEvent(&event);\r\n\r\n\t\t\tsceImeDialogTerm();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nstatic int vita_keyboard_get(std::string_view guide_text, std::string_view initial_text, unsigned max_len, SceWChar16 *buf)\r\n{\r\n\tSceWChar16 title[SCE_IME_DIALOG_MAX_TITLE_LENGTH];\r\n\tSceWChar16 text[SCE_IME_DIALOG_MAX_TEXT_LENGTH];\r\n\tSceInt32 res;\r\n\r\n\tSDL_memset(&title, 0, sizeof(title));\r\n\tSDL_memset(&text, 0, sizeof(text));\r\n\tutf8_to_utf16(reinterpret_cast<const uint8_t *>(guide_text.data()), guide_text.size(), title);\r\n\tutf8_to_utf16(reinterpret_cast<const uint8_t *>(initial_text.data()), initial_text.size(), text);\r\n\r\n\tSceImeDialogParam param;\r\n\tsceImeDialogParamInit(&param);\r\n\r\n\tparam.supportedLanguages = 0;\r\n\tparam.languagesForced = SCE_FALSE;\r\n\tparam.type = SCE_IME_TYPE_DEFAULT;\r\n\tparam.option = 0;\r\n\tparam.textBoxMode = SCE_IME_DIALOG_TEXTBOX_MODE_WITH_CLEAR;\r\n\tparam.maxTextLength = max_len;\r\n\r\n\tparam.title = title;\r\n\tparam.initialText = text;\r\n\tparam.inputTextBuffer = buf;\r\n\r\n\tres = sceImeDialogInit(&param);\r\n\tif (res < 0) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn 1;\r\n}\r\n\r\nvoid vita_start_text_input(std::string_view guide_text, std::string_view initial_text, unsigned max_length)\r\n{\r\n\tSceWChar16 ime_buffer[SCE_IME_DIALOG_MAX_TEXT_LENGTH];\r\n\tif (vita_keyboard_get(guide_text, initial_text, max_length, ime_buffer)) {\r\n\t\tSDL_CreateThread(vita_input_thread, \"vita_input_thread\", (void *)ime_buffer);\r\n\t}\r\n}\r\n"
  },
  {
    "path": "Source/platform/vita/keyboard.h",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\nvoid vita_start_text_input(std::string_view guide_text, std::string_view initial_text, unsigned max_length);\r\n"
  },
  {
    "path": "Source/platform/vita/network.cpp",
    "content": "#include \"platform/vita/network.h\"\r\n\r\n#include <cstdio>\r\n#include <cstdlib>\r\n#include <unistd.h>\r\n\r\n#include <psp2/net/net.h>\r\n#include <psp2/net/netctl.h>\r\n#include <psp2/sysmodule.h>\r\n\r\nvoid vita_enable_network()\r\n{\r\n\tSceNetInitParam param;\r\n\tstatic char memory[64 * 1024];\r\n\tint ret;\r\n\r\n\tret = sceSysmoduleLoadModule(SCE_SYSMODULE_NET);\r\n\tif (ret < 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tparam.memory = memory;\r\n\tparam.size = sizeof(memory);\r\n\tparam.flags = 0;\r\n\tret = sceNetInit(&param);\r\n\tif (ret < 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tret = sceNetCtlInit();\r\n\tif (ret < 0) {\r\n\t\treturn;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "Source/platform/vita/network.h",
    "content": "#pragma once\r\n\r\nvoid vita_enable_network();\r\n"
  },
  {
    "path": "Source/platform/vita/random.cpp",
    "content": "#include <cstdint>\r\n#include <psp2/kernel/rng.h>\r\n#include <sodium.h>\r\n#include <sys/types.h>\r\n\r\nstatic const char *randombytes_vitarandom_implementation_name()\r\n{\r\n\treturn \"vitarandom\";\r\n}\r\n\r\nstatic uint32_t randombytes_vitarandom()\r\n{\r\n\tuint32_t num;\r\n\tsceKernelGetRandomNumber(&num, sizeof(uint32_t));\r\n\treturn num;\r\n}\r\n\r\nstatic void randombytes_vitarandom_buf(void *const buf, const size_t size)\r\n{\r\n\tsceKernelGetRandomNumber(buf, size);\r\n}\r\n\r\nstruct randombytes_implementation randombytes_vitarandom_implementation = {\r\n\trandombytes_vitarandom_implementation_name,\r\n\trandombytes_vitarandom,\r\n\tnullptr,\r\n\tnullptr,\r\n\trandombytes_vitarandom_buf,\r\n\tnullptr\r\n};\r\n\r\nvoid randombytes_vitarandom_init()\r\n{\r\n\trandombytes_set_implementation(&randombytes_vitarandom_implementation);\r\n}\r\n"
  },
  {
    "path": "Source/platform/vita/random.hpp",
    "content": "#pragma once\r\nvoid randombytes_vitarandom_init();\r\n"
  },
  {
    "path": "Source/platform/vita/touch.cpp",
    "content": "#include \"platform/vita/touch.h\"\r\n\r\n#include <cmath>\r\n#include <cstdint>\r\n\r\n#include \"options.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n#define TOUCH_PORT_MAX_NUM 1\r\n#define NO_TOUCH (-1) // finger id setting if finger is not touching the screen\r\n\r\nint visible_width;\r\nint visible_height;\r\nint x_borderwidth;\r\nint y_borderwidth;\r\n\r\ntemplate <typename T>\r\ninline T clip(T v, T amin, T amax)\r\n{\r\n\tif (v < amin)\r\n\t\treturn amin;\r\n\tif (v > amax)\r\n\t\treturn amax;\r\n\r\n\treturn v;\r\n}\r\n\r\nvoid SetMouseMotionEvent(SDL_Event *event, int32_t x, int32_t y, int32_t xrel, int32_t yrel)\r\n{\r\n\tevent->type = SDL_MOUSEMOTION;\r\n\tevent->motion.x = x;\r\n\tevent->motion.y = y;\r\n\tevent->motion.xrel = xrel;\r\n\tevent->motion.yrel = yrel;\r\n\tevent->motion.which = SDL_TOUCH_MOUSEID;\r\n}\r\n\r\nbool touch_initialized = false;\r\nunsigned int simulated_click_start_time[TOUCH_PORT_MAX_NUM][2]; // initiation time of last simulated left or right click (zero if no click)\r\nbool direct_touch = true;                                       // pointer jumps to finger\r\nPoint Mouse;                                                    // always reflects current mouse position\r\nuint32_t IgnoreEvent = SDL_USEREVENT;                           // custom event type to signal events that should be ignored\r\n\r\nenum {\r\n\t// clang-format off\r\n\tMaxNumFingers          =   3, // number of fingers to track per panel\r\n\tMaxTapTime             = 250, // taps longer than this will not result in mouse click events\r\n\tMaxTapMotionDistance   =  10, // max distance finger motion in Vita screen pixels to be considered a tap\r\n\tSimulatedClickDuration =  50, // time in ms how long simulated mouse clicks should be\r\n\t// clang-format on\r\n};\r\n\r\nstruct Touch {\r\n\tint id; // -1: not touching\r\n\tuint32_t timeLastDown;\r\n\tint lastX;       // last known screen coordinates\r\n\tint lastY;       // last known screen coordinates\r\n\tfloat lastDownX; // SDL touch coordinates when last pressed down\r\n\tfloat lastDownY; // SDL touch coordinates when last pressed down\r\n};\r\n\r\nTouch finger[TOUCH_PORT_MAX_NUM][MaxNumFingers]; // keep track of finger status\r\n\r\nenum DraggingType : uint8_t {\r\n\tDragNone,\r\n\tDragTwoFinger,\r\n\tDragThreeFinger,\r\n};\r\n\r\nDraggingType multi_finger_dragging[TOUCH_PORT_MAX_NUM]; // keep track whether we are currently drag-and-dropping\r\n\r\nvoid InitTouch()\r\n{\r\n\tfor (int port = 0; port < TOUCH_PORT_MAX_NUM; port++) {\r\n\t\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\t\tfinger[port][i].id = NO_TOUCH;\r\n\t\t}\r\n\t\tmulti_finger_dragging[port] = DragNone;\r\n\t}\r\n\r\n\tfor (auto &port : simulated_click_start_time) {\r\n\t\tfor (unsigned int &time : port) {\r\n\t\t\ttime = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tSDL_DisplayMode current;\r\n\tSDL_GetCurrentDisplayMode(0, &current);\r\n\tvisible_height = current.h;\r\n\tvisible_width = (current.h * devilution::gnScreenWidth) / devilution::gnScreenHeight;\r\n\tx_borderwidth = (current.w - visible_width) / 2;\r\n\ty_borderwidth = (current.h - visible_height) / 2;\r\n\r\n\tIgnoreEvent = SDL_RegisterEvents(1);\r\n}\r\n\r\nvoid SetMouseButtonEvent(SDL_Event &event, uint32_t type, uint8_t button, Point position)\r\n{\r\n\tevent.type = type;\r\n\tevent.button.button = button;\r\n\tif (type == SDL_MOUSEBUTTONDOWN) {\r\n\t\tevent.button.state = SDL_PRESSED;\r\n\t} else {\r\n\t\tevent.button.state = SDL_RELEASED;\r\n\t}\r\n\tevent.button.x = position.x;\r\n\tevent.button.y = position.y;\r\n}\r\n\r\nvoid PreprocessFingerDown(SDL_Event *event)\r\n{\r\n\t// front (0) or back (1) panel\r\n\tSDL_TouchID port = event->tfinger.touchId;\r\n\t// id (for multitouch)\r\n\tSDL_FingerID id = event->tfinger.fingerId;\r\n\r\n\tint x = Mouse.x;\r\n\tint y = Mouse.y;\r\n\r\n\tif (direct_touch) {\r\n\t\tx = static_cast<int>(event->tfinger.x * visible_width) + x_borderwidth;\r\n\t\ty = static_cast<int>(event->tfinger.y * visible_height) + y_borderwidth;\r\n\t\tdevilution::OutputToLogical(&x, &y);\r\n\t}\r\n\r\n\t// make sure each finger is not reported down multiple times\r\n\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\tif (finger[port][i].id != id) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tfinger[port][i].id = NO_TOUCH;\r\n\t}\r\n\r\n\t// we need the timestamps to decide later if the user performed a short tap (click)\r\n\t// or a long tap (drag)\r\n\t// we also need the last coordinates for each finger to keep track of dragging\r\n\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\tif (finger[port][i].id != NO_TOUCH) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tfinger[port][i].id = id;\r\n\t\tfinger[port][i].timeLastDown = event->tfinger.timestamp;\r\n\t\tfinger[port][i].lastDownX = event->tfinger.x;\r\n\t\tfinger[port][i].lastDownY = event->tfinger.y;\r\n\t\tfinger[port][i].lastX = x;\r\n\t\tfinger[port][i].lastY = y;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid PreprocessBackFingerDown(SDL_Event *event)\r\n{\r\n\t// front (0) or back (1) panel\r\n\tSDL_TouchID port = event->tfinger.touchId;\r\n\r\n\tif (port != 1)\r\n\t\treturn;\r\n\r\n\tevent->type = SDL_CONTROLLERAXISMOTION;\r\n\tevent->caxis.value = 32767;\r\n\tevent->caxis.which = 0;\r\n\tif (event->tfinger.x <= 0.5) {\r\n\t\t;\r\n\t\tevent->caxis.axis = SDL_CONTROLLER_AXIS_TRIGGERLEFT;\r\n\t} else {\r\n\t\tevent->caxis.axis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT;\r\n\t}\r\n}\r\n\r\nvoid PreprocessBackFingerUp(SDL_Event *event)\r\n{\r\n\t// front (0) or back (1) panel\r\n\tSDL_TouchID port = event->tfinger.touchId;\r\n\r\n\tif (port != 1)\r\n\t\treturn;\r\n\r\n\tevent->type = SDL_CONTROLLERAXISMOTION;\r\n\tevent->caxis.value = 0;\r\n\tevent->caxis.which = 0;\r\n\tif (event->tfinger.x <= 0.5) {\r\n\t\tevent->caxis.axis = SDL_CONTROLLER_AXIS_TRIGGERLEFT;\r\n\t} else {\r\n\t\tevent->caxis.axis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT;\r\n\t}\r\n}\r\n\r\nvoid PreprocessFingerUp(SDL_Event *event)\r\n{\r\n\t// front (0) or back (1) panel\r\n\tSDL_TouchID port = event->tfinger.touchId;\r\n\t// id (for multitouch)\r\n\tSDL_FingerID id = event->tfinger.fingerId;\r\n\r\n\t// find out how many fingers were down before this event\r\n\tint numFingersDown = 0;\r\n\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\tif (finger[port][i].id >= 0) {\r\n\t\t\tnumFingersDown++;\r\n\t\t}\r\n\t}\r\n\r\n\tint x = Mouse.x;\r\n\tint y = Mouse.y;\r\n\r\n\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\tif (finger[port][i].id != id) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tfinger[port][i].id = NO_TOUCH;\r\n\t\tif (multi_finger_dragging[port] == DragNone) {\r\n\t\t\tif ((event->tfinger.timestamp - finger[port][i].timeLastDown) > MaxTapTime) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// short (<MAX_TAP_TIME ms) tap is interpreted as right/left mouse click depending on # fingers already down\r\n\t\t\t// but only if the finger hasn't moved since it was pressed down by more than MAX_TAP_MOTION_DISTANCE pixels\r\n\t\t\tfloat xrel = ((event->tfinger.x * devilution::GetOutputSurface()->w) - (finger[port][i].lastDownX * devilution::GetOutputSurface()->w));\r\n\t\t\tfloat yrel = ((event->tfinger.y * devilution::GetOutputSurface()->h) - (finger[port][i].lastDownY * devilution::GetOutputSurface()->h));\r\n\t\t\tauto maxRSquared = static_cast<float>(MaxTapMotionDistance * MaxTapMotionDistance);\r\n\t\t\tif ((xrel * xrel + yrel * yrel) >= maxRSquared) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (numFingersDown != 2 && numFingersDown != 1) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tUint8 simulatedButton = 0;\r\n\t\t\tif (numFingersDown == 2) {\r\n\t\t\t\tsimulatedButton = SDL_BUTTON_RIGHT;\r\n\t\t\t\t// need to raise the button later\r\n\t\t\t\tsimulated_click_start_time[port][1] = event->tfinger.timestamp;\r\n\t\t\t} else if (numFingersDown == 1) {\r\n\t\t\t\tsimulatedButton = SDL_BUTTON_LEFT;\r\n\t\t\t\t// need to raise the button later\r\n\t\t\t\tsimulated_click_start_time[port][0] = event->tfinger.timestamp;\r\n\t\t\t\tif (direct_touch) {\r\n\t\t\t\t\tx = static_cast<int>(event->tfinger.x * visible_width) + x_borderwidth;\r\n\t\t\t\t\ty = static_cast<int>(event->tfinger.y * visible_height) + y_borderwidth;\r\n\t\t\t\t\tdevilution::OutputToLogical(&x, &y);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tSetMouseButtonEvent(*event, SDL_MOUSEBUTTONDOWN, simulatedButton, { x, y });\r\n\t\t\tevent->button.which = SDL_TOUCH_MOUSEID;\r\n\t\t} else if (numFingersDown == 1) {\r\n\t\t\t// when dragging, and the last finger is lifted, the drag is over\r\n\t\t\tUint8 simulatedButton = 0;\r\n\t\t\tif (multi_finger_dragging[port] == DragThreeFinger) {\r\n\t\t\t\tsimulatedButton = SDL_BUTTON_RIGHT;\r\n\t\t\t} else {\r\n\t\t\t\tsimulatedButton = SDL_BUTTON_LEFT;\r\n\t\t\t}\r\n\t\t\tSetMouseButtonEvent(*event, SDL_MOUSEBUTTONUP, simulatedButton, { x, y });\r\n\t\t\tevent->button.which = SDL_TOUCH_MOUSEID;\r\n\t\t\tmulti_finger_dragging[port] = DragNone;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PreprocessFingerMotion(SDL_Event *event)\r\n{\r\n\t// front (0) or back (1) panel\r\n\tSDL_TouchID port = event->tfinger.touchId;\r\n\t// id (for multitouch)\r\n\tSDL_FingerID id = event->tfinger.fingerId;\r\n\r\n\t// find out how many fingers were down before this event\r\n\tint numFingersDown = 0;\r\n\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\tif (finger[port][i].id >= 0) {\r\n\t\t\tnumFingersDown++;\r\n\t\t}\r\n\t}\r\n\r\n\tif (numFingersDown == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (numFingersDown >= 1) {\r\n\t\tint x = Mouse.x;\r\n\t\tint y = Mouse.y;\r\n\r\n\t\tif (direct_touch) {\r\n\t\t\tx = static_cast<int>(event->tfinger.x * visible_width) + x_borderwidth;\r\n\t\t\ty = static_cast<int>(event->tfinger.y * visible_height) + y_borderwidth;\r\n\t\t\tdevilution::OutputToLogical(&x, &y);\r\n\t\t} else {\r\n\t\t\t// for relative mode, use the pointer speed setting\r\n\t\t\tconstexpr float SpeedFactor = 1.25F;\r\n\r\n\t\t\t// convert touch events to relative mouse pointer events\r\n\t\t\t// Whenever an SDL_event involving the mouse is processed,\r\n\t\t\tx = static_cast<int>(Mouse.x + (event->tfinger.dx * SpeedFactor * devilution::GetOutputSurface()->w));\r\n\t\t\ty = static_cast<int>(Mouse.y + (event->tfinger.dy * SpeedFactor * devilution::GetOutputSurface()->h));\r\n\t\t}\r\n\r\n\t\tx = clip(x, 0, devilution::GetOutputSurface()->w);\r\n\t\ty = clip(y, 0, devilution::GetOutputSurface()->h);\r\n\t\tint xrel = x - Mouse.x;\r\n\t\tint yrel = y - Mouse.y;\r\n\r\n\t\t// update the current finger's coordinates so we can track it later\r\n\t\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\t\tif (finger[port][i].id != id)\r\n\t\t\t\tcontinue;\r\n\t\t\tfinger[port][i].lastX = x;\r\n\t\t\tfinger[port][i].lastY = y;\r\n\t\t}\r\n\r\n\t\t// If we are starting a multi-finger drag, start holding down the mouse button\r\n\t\tif (numFingersDown >= 2 && multi_finger_dragging[port] == DragNone) {\r\n\t\t\t// only start a multi-finger drag if at least two fingers have been down long enough\r\n\t\t\tint numFingersDownlong = 0;\r\n\t\t\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\t\t\tif (finger[port][i].id == NO_TOUCH) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif (event->tfinger.timestamp - finger[port][i].timeLastDown > MaxTapTime) {\r\n\t\t\t\t\tnumFingersDownlong++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (numFingersDownlong >= 2) {\r\n\t\t\t\tPoint mouseDown = Mouse;\r\n\t\t\t\tif (direct_touch) {\r\n\t\t\t\t\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\t\t\t\t\tif (finger[port][i].id == id) {\r\n\t\t\t\t\t\t\tuint32_t earliestTime = finger[port][i].timeLastDown;\r\n\t\t\t\t\t\t\tfor (int j = 0; j < MaxNumFingers; j++) {\r\n\t\t\t\t\t\t\t\tif (finger[port][j].id >= 0 && (i != j)) {\r\n\t\t\t\t\t\t\t\t\tif (finger[port][j].timeLastDown < earliestTime) {\r\n\t\t\t\t\t\t\t\t\t\tmouseDown.x = finger[port][j].lastX;\r\n\t\t\t\t\t\t\t\t\t\tmouseDown.y = finger[port][j].lastY;\r\n\t\t\t\t\t\t\t\t\t\tearliestTime = finger[port][j].timeLastDown;\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tUint8 simulatedButton = 0;\r\n\t\t\t\tif (numFingersDownlong == 2) {\r\n\t\t\t\t\tsimulatedButton = SDL_BUTTON_LEFT;\r\n\t\t\t\t\tmulti_finger_dragging[port] = DragTwoFinger;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tsimulatedButton = SDL_BUTTON_RIGHT;\r\n\t\t\t\t\tmulti_finger_dragging[port] = DragThreeFinger;\r\n\t\t\t\t}\r\n\t\t\t\tSDL_Event ev;\r\n\t\t\t\tSetMouseButtonEvent(ev, SDL_MOUSEBUTTONDOWN, simulatedButton, mouseDown);\r\n\t\t\t\tev.button.which = SDL_TOUCH_MOUSEID;\r\n\t\t\t\tSDL_PushEvent(&ev);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (xrel == 0 && yrel == 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// check if this is the \"oldest\" finger down (or the only finger down)\r\n\t\t// otherwise it will not affect mouse motion\r\n\t\tbool updatePointer = true;\r\n\t\tif (numFingersDown > 1) {\r\n\t\t\tfor (int i = 0; i < MaxNumFingers; i++) {\r\n\t\t\t\tif (finger[port][i].id != id) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tfor (int j = 0; j < MaxNumFingers; j++) {\r\n\t\t\t\t\tif (finger[port][j].id == NO_TOUCH || (j == i)) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (finger[port][j].timeLastDown < finger[port][i].timeLastDown) {\r\n\t\t\t\t\t\tupdatePointer = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!updatePointer) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tSetMouseMotionEvent(event, x, y, xrel, yrel);\r\n\t}\r\n}\r\n\r\nvoid PreprocessEvents(SDL_Event *event)\r\n{\r\n\t// Supported touch gestures:\r\n\t// left mouse click: single finger short tap\r\n\t// right mouse click: second finger short tap while first finger is still down\r\n\t// pointer motion: single finger drag\r\n\t// left button drag and drop: dual finger drag\r\n\t// right button drag and drop: triple finger drag\r\n\tif (event->type != SDL_FINGERDOWN && event->type != SDL_FINGERUP && event->type != SDL_FINGERMOTION) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// front (0) or back (1) panel\r\n\tSDL_TouchID port = event->tfinger.touchId;\r\n\tif (port != 0) {\r\n\t\tif (devilution::GetOptions().Controller.bRearTouch) {\r\n\t\t\tswitch (event->type) {\r\n\t\t\tcase SDL_FINGERDOWN:\r\n\t\t\t\tPreprocessBackFingerDown(event);\r\n\t\t\t\tbreak;\r\n\t\t\tcase SDL_FINGERUP:\r\n\t\t\t\tPreprocessBackFingerUp(event);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (event->type) {\r\n\tcase SDL_FINGERDOWN:\r\n\t\tPreprocessFingerDown(event);\r\n\t\tbreak;\r\n\tcase SDL_FINGERUP:\r\n\t\tPreprocessFingerUp(event);\r\n\t\tbreak;\r\n\tcase SDL_FINGERMOTION:\r\n\t\tPreprocessFingerMotion(event);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid HandleTouchEvent(SDL_Event *event, Point mousePosition)\r\n{\r\n\tMouse = mousePosition;\r\n\r\n\tif (!touch_initialized) {\r\n\t\tInitTouch();\r\n\t\ttouch_initialized = true;\r\n\t}\r\n\tPreprocessEvents(event);\r\n\tif (event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP || event->type == SDL_FINGERMOTION) {\r\n\t\tevent->type = IgnoreEvent;\r\n\t}\r\n}\r\n\r\nvoid FinishSimulatedMouseClicks(Point mousePosition)\r\n{\r\n\tMouse = mousePosition;\r\n\r\n\tfor (auto &port : simulated_click_start_time) {\r\n\t\tfor (int i = 0; i < 2; i++) {\r\n\t\t\tif (port[i] == 0) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tUint32 currentTime = SDL_GetTicks();\r\n\t\t\tif (currentTime - port[i] < SimulatedClickDuration) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tint simulatedButton;\r\n\t\t\tif (i == 0) {\r\n\t\t\t\tsimulatedButton = SDL_BUTTON_LEFT;\r\n\t\t\t} else {\r\n\t\t\t\tsimulatedButton = SDL_BUTTON_RIGHT;\r\n\t\t\t}\r\n\t\t\tSDL_Event ev;\r\n\t\t\tSetMouseButtonEvent(ev, SDL_MOUSEBUTTONUP, simulatedButton, Mouse);\r\n\t\t\tev.button.which = SDL_TOUCH_MOUSEID;\r\n\t\t\tSDL_PushEvent(&ev);\r\n\r\n\t\t\tport[i] = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/platform/vita/touch.h",
    "content": "#pragma once\r\n\r\n#ifdef __vita__\r\n\r\n#include <SDL.h>\r\n\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid HandleTouchEvent(SDL_Event *event, Point mousePosition);\r\nvoid FinishSimulatedMouseClicks(Point mousePosition);\r\n\r\n} // namespace devilution\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/player.cpp",
    "content": "/**\r\n * @file player.cpp\r\n *\r\n * Implementation of player functionality, leveling, actions, creation, loading, etc.\r\n */\r\n#include <algorithm>\r\n#include <cmath>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"dead.h\"\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/load_cl2.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/trn.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"gamemenu.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"help.h\"\r\n#include \"inv_iterators.hpp\"\r\n#include \"levels/tile_properties.hpp\"\r\n#include \"levels/trigs.h\"\r\n#include \"lighting.h\"\r\n#include \"loadsave.h\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"minitext.h\"\r\n#include \"missiles.h\"\r\n#include \"monster.h\"\r\n#include \"nthread.h\"\r\n#include \"objects.h\"\r\n#include \"options.h\"\r\n#include \"player.h\"\r\n#include \"qol/autopickup.h\"\r\n#include \"qol/stash.h\"\r\n#include \"spells.h\"\r\n#include \"stores.h\"\r\n#include \"towners.h\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nuint8_t MyPlayerId;\r\nPlayer *MyPlayer;\r\nstd::vector<Player> Players;\r\nPlayer *InspectPlayer;\r\nbool MyPlayerIsDead;\r\n\r\nnamespace {\r\n\r\nstruct DirectionSettings {\r\n\tDirection dir;\r\n\tPLR_MODE walkMode;\r\n};\r\n\r\nvoid UpdatePlayerLightOffset(Player &player)\r\n{\r\n\tif (player.lightId == NO_LIGHT)\r\n\t\treturn;\r\n\r\n\tconst WorldTileDisplacement offset = player.position.CalculateWalkingOffset(player._pdir, player.AnimInfo);\r\n\tChangeLightOffset(player.lightId, offset.screenToLight());\r\n}\r\n\r\nvoid WalkInDirection(Player &player, const DirectionSettings &walkParams)\r\n{\r\n\tplayer.occupyTile(player.position.future, true);\r\n\tplayer.position.temp = player.position.tile + walkParams.dir;\r\n}\r\n\r\nconstexpr std::array<const DirectionSettings, 8> WalkSettings { {\r\n\t// clang-format off\r\n\t{ Direction::South,     PM_WALK_SOUTHWARDS },\r\n\t{ Direction::SouthWest, PM_WALK_SOUTHWARDS },\r\n\t{ Direction::West,      PM_WALK_SIDEWAYS   },\r\n\t{ Direction::NorthWest, PM_WALK_NORTHWARDS },\r\n\t{ Direction::North,     PM_WALK_NORTHWARDS },\r\n\t{ Direction::NorthEast, PM_WALK_NORTHWARDS },\r\n\t{ Direction::East,      PM_WALK_SIDEWAYS   },\r\n\t{ Direction::SouthEast, PM_WALK_SOUTHWARDS }\r\n\t// clang-format on\r\n} };\r\n\r\nbool PlrDirOK(const Player &player, Direction dir)\r\n{\r\n\tconst Point position = player.position.tile;\r\n\tconst Point futurePosition = position + dir;\r\n\tif (futurePosition.x < 0 || !PosOkPlayer(player, futurePosition)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (dir == Direction::East) {\r\n\t\treturn !IsTileSolid(position + Direction::SouthEast);\r\n\t}\r\n\r\n\tif (dir == Direction::West) {\r\n\t\treturn !IsTileSolid(position + Direction::SouthWest);\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid HandleWalkMode(Player &player, Direction dir)\r\n{\r\n\tconst auto &dirModeParams = WalkSettings[static_cast<size_t>(dir)];\r\n\tSetPlayerOld(player);\r\n\tif (!PlrDirOK(player, dir)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tplayer._pdir = dir;\r\n\r\n\t// The player's tile position after finishing this movement action\r\n\tplayer.position.future = player.position.tile + dirModeParams.dir;\r\n\r\n\tWalkInDirection(player, dirModeParams);\r\n\r\n\tplayer.tempDirection = dirModeParams.dir;\r\n\tplayer._pmode = dirModeParams.walkMode;\r\n}\r\n\r\nvoid StartWalkAnimation(Player &player, Direction dir, bool pmWillBeCalled)\r\n{\r\n\tint8_t skippedFrames = -2;\r\n\tif (leveltype == DTYPE_TOWN && sgGameInitInfo.bRunInTown != 0)\r\n\t\tskippedFrames = 2;\r\n\tif (pmWillBeCalled)\r\n\t\tskippedFrames += 1;\r\n\tNewPlrAnim(player, player_graphic::Walk, dir, AnimationDistributionFlags::ProcessAnimationPending, skippedFrames);\r\n}\r\n\r\n/**\r\n * @brief Start moving a player to a new tile\r\n */\r\nvoid StartWalk(Player &player, Direction dir, bool pmWillBeCalled)\r\n{\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer) {\r\n\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\treturn;\r\n\t}\r\n\r\n\tStartWalkAnimation(player, dir, pmWillBeCalled);\r\n\tHandleWalkMode(player, dir);\r\n}\r\n\r\nvoid ClearStateVariables(Player &player)\r\n{\r\n\tplayer.position.temp = { 0, 0 };\r\n\tplayer.tempDirection = Direction::South;\r\n\tplayer.queuedSpell.spellLevel = 0;\r\n}\r\n\r\nvoid StartAttack(Player &player, Direction d, bool includesFirstFrame)\r\n{\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer) {\r\n\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\treturn;\r\n\t}\r\n\r\n\tint8_t skippedAnimationFrames = 0;\r\n\tconst auto flags = player._pIFlags;\r\n\r\n\t// If the first frame is not included in vanilla, the skip logic for the first frame will not be executed.\r\n\t// This will result in a different and slower attack speed.\r\n\tif (HasAnyOf(flags, ItemSpecialEffect::FastestAttack)) {\r\n\t\t// If the fastest attack logic is trigger frames in vanilla two frames are skipped, so missing the first frame reduces the skip logic by two frames.\r\n\t\tskippedAnimationFrames = includesFirstFrame ? 4 : 2;\r\n\t} else if (HasAnyOf(flags, ItemSpecialEffect::FasterAttack)) {\r\n\t\tskippedAnimationFrames = includesFirstFrame ? 3 : 2;\r\n\t} else if (HasAnyOf(flags, ItemSpecialEffect::FastAttack)) {\r\n\t\tskippedAnimationFrames = includesFirstFrame ? 2 : 1;\r\n\t} else if (HasAnyOf(flags, ItemSpecialEffect::QuickAttack)) {\r\n\t\tskippedAnimationFrames = includesFirstFrame ? 1 : 0;\r\n\t}\r\n\r\n\tauto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;\r\n\tif (player._pmode == PM_ATTACK)\r\n\t\tanimationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);\r\n\tNewPlrAnim(player, player_graphic::Attack, d, animationFlags, skippedAnimationFrames, player._pAFNum);\r\n\tplayer._pmode = PM_ATTACK;\r\n\tFixPlayerLocation(player, d);\r\n\tSetPlayerOld(player);\r\n}\r\n\r\nvoid StartRangeAttack(Player &player, Direction d, WorldTileCoord cx, WorldTileCoord cy, bool includesFirstFrame)\r\n{\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer) {\r\n\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\treturn;\r\n\t}\r\n\r\n\tint8_t skippedAnimationFrames = 0;\r\n\tconst auto flags = player._pIFlags;\r\n\r\n\tif (!gbIsHellfire) {\r\n\t\tif (includesFirstFrame && HasAnyOf(flags, ItemSpecialEffect::QuickAttack | ItemSpecialEffect::FastAttack)) {\r\n\t\t\tskippedAnimationFrames += 1;\r\n\t\t}\r\n\t\tif (HasAnyOf(flags, ItemSpecialEffect::FastAttack)) {\r\n\t\t\tskippedAnimationFrames += 1;\r\n\t\t}\r\n\t}\r\n\r\n\tauto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;\r\n\tif (player._pmode == PM_RATTACK)\r\n\t\tanimationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);\r\n\tNewPlrAnim(player, player_graphic::Attack, d, animationFlags, skippedAnimationFrames, player._pAFNum);\r\n\r\n\tplayer._pmode = PM_RATTACK;\r\n\tFixPlayerLocation(player, d);\r\n\tSetPlayerOld(player);\r\n\tplayer.position.temp = WorldTilePosition { cx, cy };\r\n}\r\n\r\nplayer_graphic GetPlayerGraphicForSpell(SpellID spellId)\r\n{\r\n\tswitch (GetSpellData(spellId).type()) {\r\n\tcase MagicType::Fire:\r\n\t\treturn player_graphic::Fire;\r\n\tcase MagicType::Lightning:\r\n\t\treturn player_graphic::Lightning;\r\n\tdefault:\r\n\t\treturn player_graphic::Magic;\r\n\t}\r\n}\r\n\r\nvoid StartSpell(Player &player, Direction d, WorldTileCoord cx, WorldTileCoord cy)\r\n{\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer) {\r\n\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Checks conditions for spell again, because initial check was done when spell was queued and the parameters could be changed meanwhile\r\n\tbool isValid = false;\r\n\tswitch (player.queuedSpell.spellType) {\r\n\tcase SpellType::Skill:\r\n\tcase SpellType::Spell:\r\n\t\tisValid = CheckSpell(player, player.queuedSpell.spellId, player.queuedSpell.spellType, true) == SpellCheckResult::Success;\r\n\t\tbreak;\r\n\tcase SpellType::Scroll:\r\n\t\tisValid = CanUseScroll(player, player.queuedSpell.spellId);\r\n\t\tbreak;\r\n\tcase SpellType::Charges:\r\n\t\tisValid = CanUseStaff(player, player.queuedSpell.spellId);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\tif (!isValid)\r\n\t\treturn;\r\n\r\n\tauto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;\r\n\tif (player._pmode == PM_SPELL)\r\n\t\tanimationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);\r\n\tNewPlrAnim(player, GetPlayerGraphicForSpell(player.queuedSpell.spellId), d, animationFlags, 0, player._pSFNum);\r\n\r\n\tPlaySfxLoc(GetSpellData(player.queuedSpell.spellId).sSFX, player.position.tile);\r\n\r\n\tplayer._pmode = PM_SPELL;\r\n\r\n\tFixPlayerLocation(player, d);\r\n\tSetPlayerOld(player);\r\n\r\n\tplayer.position.temp = WorldTilePosition { cx, cy };\r\n\tplayer.queuedSpell.spellLevel = player.GetSpellLevel(player.queuedSpell.spellId);\r\n\tplayer.executedSpell = player.queuedSpell;\r\n}\r\n\r\nvoid RespawnDeadItem(Item &&itm, Point target)\r\n{\r\n\tif (ActiveItemCount >= MAXITEMS)\r\n\t\treturn;\r\n\r\n\tconst int ii = AllocateItem();\r\n\tItem &item = Items[ii];\r\n\r\n\tdItem[target.x][target.y] = ii + 1;\r\n\r\n\titem = itm;\r\n\titem.position = target;\r\n\tRespawnItem(item, true);\r\n\tNetSendCmdPItem(false, CMD_SPAWNITEM, target, item);\r\n}\r\n\r\nvoid DeadItem(Player &player, Item &&item, Displacement direction)\r\n{\r\n\tif (item.isEmpty())\r\n\t\treturn;\r\n\r\n\tconst Point playerTile = player.position.tile;\r\n\tif (direction != Displacement { 0, 0 }) {\r\n\t\tconst Point target = playerTile + direction;\r\n\t\tif (ItemSpaceOk(target)) {\r\n\t\t\tRespawnDeadItem(std::move(item), target);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tstd::optional<Point> dropPoint = FindClosestValidPosition(ItemSpaceOk, playerTile, 1, 50);\r\n\tif (dropPoint) {\r\n\t\tRespawnDeadItem(std::move(item), *dropPoint);\r\n\t}\r\n}\r\n\r\nint DropGold(Player &player, int amount, bool skipFullStacks)\r\n{\r\n\tfor (int i = 0; i < player._pNumInv && amount > 0; i++) {\r\n\t\tItem &item = player.InvList[i];\r\n\r\n\t\tif (item._itype != ItemType::Gold || (skipFullStacks && item._ivalue == MaxGold))\r\n\t\t\tcontinue;\r\n\r\n\t\tif (amount < item._ivalue) {\r\n\t\t\tItem goldItem;\r\n\t\t\tMakeGoldStack(goldItem, amount);\r\n\t\t\tDeadItem(player, std::move(goldItem), { 0, 0 });\r\n\r\n\t\t\titem._ivalue -= amount;\r\n\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\tamount -= item._ivalue;\r\n\t\tDeadItem(player, std::move(item), { 0, 0 });\r\n\t\tplayer.RemoveInvItem(i);\r\n\t\ti = -1;\r\n\t}\r\n\r\n\treturn amount;\r\n}\r\n\r\nvoid DropHalfPlayersGold(Player &player)\r\n{\r\n\tconst int remainingGold = DropGold(player, player._pGold / 2, true);\r\n\tif (remainingGold > 0) {\r\n\t\tDropGold(player, remainingGold, false);\r\n\t}\r\n\r\n\tplayer._pGold /= 2;\r\n}\r\n\r\nvoid InitLevelChange(Player &player)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tRemoveEnemyReferences(player);\r\n\tRemovePlrMissiles(player);\r\n\tplayer.pManaShield = false;\r\n\tplayer.wReflections = 0;\r\n\tif (&player != MyPlayer) {\r\n\t\t// share info about your manashield when another player joins the level\r\n\t\tif (myPlayer.pManaShield)\r\n\t\t\tNetSendCmd(true, CMD_SETSHIELD);\r\n\t\t// share info about your reflect charges when another player joins the level\r\n\t\tNetSendCmdParam1(true, CMD_SETREFLECT, myPlayer.wReflections);\r\n\t} else if (qtextflag) {\r\n\t\tqtextflag = false;\r\n\t\tstream_stop();\r\n\t}\r\n\r\n\tFixPlrWalkTags(player);\r\n\tSetPlayerOld(player);\r\n\tif (&player == MyPlayer) {\r\n\t\tplayer.occupyTile(player.position.tile, false);\r\n\t} else {\r\n\t\tplayer._pLvlVisited[player.plrlevel] = true;\r\n\t}\r\n\r\n\tClrPlrPath(player);\r\n\tplayer.destAction = ACTION_NONE;\r\n\tplayer._pLvlChanging = true;\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tplayer.pLvlLoad = 10;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Continue movement towards new tile\r\n */\r\nbool DoWalk(Player &player)\r\n{\r\n\t// Play walking sound effect on certain animation frames\r\n\tif (*GetOptions().Audio.walkingSound && (leveltype != DTYPE_TOWN || sgGameInitInfo.bRunInTown == 0)) {\r\n\t\tif (player.AnimInfo.currentFrame == 0\r\n\t\t    || player.AnimInfo.currentFrame == 4) {\r\n\t\t\tPlaySfxLoc(SfxID::Walk, player.position.tile);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!player.AnimInfo.isLastFrame()) {\r\n\t\t// We didn't reach new tile so update player's \"sub-tile\" position\r\n\t\tUpdatePlayerLightOffset(player);\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// We reached the new tile -> update the player's tile position\r\n\tdPlayer[player.position.tile.x][player.position.tile.y] = 0;\r\n\tplayer.position.tile = player.position.temp;\r\n\t// dPlayer is set here for backwards compatibility; without it, the player would be invisible if loaded from a vanilla save.\r\n\tplayer.occupyTile(player.position.tile, false);\r\n\r\n\t// Update the coordinates for lighting and vision entries for the player\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tChangeLightXY(player.lightId, player.position.tile);\r\n\t\tChangeVisionXY(player.getId(), player.position.tile);\r\n\t}\r\n\r\n\tStartStand(player, player.tempDirection);\r\n\r\n\tClearStateVariables(player);\r\n\r\n\t// Reset the \"sub-tile\" position of the player's light entry to 0\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tChangeLightOffset(player.lightId, { 0, 0 });\r\n\t}\r\n\r\n\tAutoPickup(player);\r\n\treturn true;\r\n}\r\n\r\nbool WeaponDecay(Player &player, int ii)\r\n{\r\n\tif (!player.InvBody[ii].isEmpty() && player.InvBody[ii]._iClass == ICLASS_WEAPON && HasAnyOf(player.InvBody[ii]._iDamAcFlags, ItemSpecialEffectHf::Decay)) {\r\n\t\tplayer.InvBody[ii]._iPLDam -= 5;\r\n\t\tif (player.InvBody[ii]._iPLDam <= -100) {\r\n\t\t\tRemoveEquipment(player, static_cast<inv_body_loc>(ii), true);\r\n\t\t\tCalcPlrInv(player, true);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tCalcPlrInv(player, true);\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool DamageWeapon(Player &player, unsigned damageFrequency)\r\n{\r\n\tif (&player != MyPlayer) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (WeaponDecay(player, INVLOC_HAND_LEFT))\r\n\t\treturn true;\r\n\tif (WeaponDecay(player, INVLOC_HAND_RIGHT))\r\n\t\treturn true;\r\n\r\n\tif (!FlipCoin(damageFrequency)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (!player.InvBody[INVLOC_HAND_LEFT].isEmpty() && player.InvBody[INVLOC_HAND_LEFT]._iClass == ICLASS_WEAPON) {\r\n\t\tif (player.InvBody[INVLOC_HAND_LEFT]._iDurability == DUR_INDESTRUCTIBLE) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tplayer.InvBody[INVLOC_HAND_LEFT]._iDurability--;\r\n\t\tif (player.InvBody[INVLOC_HAND_LEFT]._iDurability <= 0) {\r\n\t\t\tRemoveEquipment(player, INVLOC_HAND_LEFT, true);\r\n\t\t\tCalcPlrInv(player, true);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!player.InvBody[INVLOC_HAND_RIGHT].isEmpty() && player.InvBody[INVLOC_HAND_RIGHT]._iClass == ICLASS_WEAPON) {\r\n\t\tif (player.InvBody[INVLOC_HAND_RIGHT]._iDurability == DUR_INDESTRUCTIBLE) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tplayer.InvBody[INVLOC_HAND_RIGHT]._iDurability--;\r\n\t\tif (player.InvBody[INVLOC_HAND_RIGHT]._iDurability == 0) {\r\n\t\t\tRemoveEquipment(player, INVLOC_HAND_RIGHT, true);\r\n\t\t\tCalcPlrInv(player, true);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (player.InvBody[INVLOC_HAND_LEFT].isEmpty() && player.InvBody[INVLOC_HAND_RIGHT]._itype == ItemType::Shield) {\r\n\t\tif (player.InvBody[INVLOC_HAND_RIGHT]._iDurability == DUR_INDESTRUCTIBLE) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tplayer.InvBody[INVLOC_HAND_RIGHT]._iDurability--;\r\n\t\tif (player.InvBody[INVLOC_HAND_RIGHT]._iDurability == 0) {\r\n\t\t\tRemoveEquipment(player, INVLOC_HAND_RIGHT, true);\r\n\t\t\tCalcPlrInv(player, true);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (player.InvBody[INVLOC_HAND_RIGHT].isEmpty() && player.InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Shield) {\r\n\t\tif (player.InvBody[INVLOC_HAND_LEFT]._iDurability == DUR_INDESTRUCTIBLE) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tplayer.InvBody[INVLOC_HAND_LEFT]._iDurability--;\r\n\t\tif (player.InvBody[INVLOC_HAND_LEFT]._iDurability == 0) {\r\n\t\t\tRemoveEquipment(player, INVLOC_HAND_LEFT, true);\r\n\t\t\tCalcPlrInv(player, true);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool PlrHitMonst(Player &player, Monster &monster, bool adjacentDamage = false)\r\n{\r\n\tint hper = 0;\r\n\r\n\tif (!monster.isPossibleToHit())\r\n\t\treturn false;\r\n\r\n\tif (adjacentDamage) {\r\n\t\tif (player.getCharacterLevel() > 20)\r\n\t\t\thper -= 30;\r\n\t\telse\r\n\t\t\thper -= (35 - player.getCharacterLevel()) * 2;\r\n\t}\r\n\r\n\tint hit = GenerateRnd(100);\r\n\tif (monster.mode == MonsterMode::Petrified) {\r\n\t\thit = 0;\r\n\t}\r\n\r\n\thper += player.GetMeleePiercingToHit() - player.CalculateArmorPierce(monster.armorClass, true);\r\n\thper = std::clamp(hper, 5, 95);\r\n\r\n\tif (monster.tryLiftGargoyle())\r\n\t\treturn true;\r\n\r\n\tif (hit >= hper) {\r\n#ifdef _DEBUG\r\n\t\tif (!DebugGodMode)\r\n#endif\r\n\t\t\treturn false;\r\n\t}\r\n\r\n\tif (gbIsHellfire && HasAllOf(player._pIFlags, ItemSpecialEffect::FireDamage | ItemSpecialEffect::LightningDamage)) {\r\n\t\t// Fixed off by 1 error from Hellfire\r\n\t\tconst int midam = RandomIntBetween(player._pIFMinDam, player._pIFMaxDam);\r\n\t\tAddMissile(player.position.tile, player.position.temp, player._pdir, MissileID::SpectralArrow, TARGET_MONSTERS, player, midam, 0);\r\n\t}\r\n\tconst int mind = player._pIMinDam;\r\n\tconst int maxd = player._pIMaxDam;\r\n\tint dam = RandomIntBetween(mind, maxd);\r\n\tdam += dam * player._pIBonusDam / 100;\r\n\tdam += player._pIBonusDamMod;\r\n\tint dam2 = dam << 6;\r\n\tdam += player._pDamageMod;\r\n\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(player._pClass);\r\n\tif (HasAnyOf(classAttributes.classFlags, PlayerClassFlag::CriticalStrike)) {\r\n\t\tif (GenerateRnd(100) < player.getCharacterLevel()) {\r\n\t\t\tdam *= 2;\r\n\t\t}\r\n\t}\r\n\r\n\tItemType phanditype = ItemType::None;\r\n\tif (player.InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Sword || player.InvBody[INVLOC_HAND_RIGHT]._itype == ItemType::Sword) {\r\n\t\tphanditype = ItemType::Sword;\r\n\t}\r\n\tif (player.InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Mace || player.InvBody[INVLOC_HAND_RIGHT]._itype == ItemType::Mace) {\r\n\t\tphanditype = ItemType::Mace;\r\n\t}\r\n\r\n\tswitch (monster.data().monsterClass) {\r\n\tcase MonsterClass::Undead:\r\n\t\tif (phanditype == ItemType::Sword) {\r\n\t\t\tdam -= dam / 2;\r\n\t\t} else if (phanditype == ItemType::Mace) {\r\n\t\t\tdam += dam / 2;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase MonsterClass::Animal:\r\n\t\tif (phanditype == ItemType::Mace) {\r\n\t\t\tdam -= dam / 2;\r\n\t\t} else if (phanditype == ItemType::Sword) {\r\n\t\t\tdam += dam / 2;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase MonsterClass::Demon:\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::TripleDemonDamage)) {\r\n\t\t\tdam *= 3;\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::Devastation) && GenerateRnd(100) < 5) {\r\n\t\tdam *= 3;\r\n\t}\r\n\r\n\tif (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::Doppelganger) && monster.type().type != MT_DIABLO && !monster.isUnique() && GenerateRnd(100) < 10) {\r\n\t\tAddDoppelganger(monster);\r\n\t}\r\n\r\n\tdam <<= 6;\r\n\tif (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::Jesters)) {\r\n\t\tint r = GenerateRnd(201);\r\n\t\tif (r >= 100)\r\n\t\t\tr = 100 + (r - 100) * 5;\r\n\t\tdam = dam * r / 100;\r\n\t}\r\n\r\n\tif (adjacentDamage)\r\n\t\tdam >>= 2;\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tif (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::Peril)) {\r\n\t\t\tdam2 += player._pIGetHit << 6;\r\n\t\t\tif (dam2 >= 0) {\r\n\t\t\t\tApplyPlrDamage(DamageType::Physical, player, 0, 1, dam2);\r\n\t\t\t}\r\n\t\t\tdam *= 2;\r\n\t\t}\r\n#ifdef _DEBUG\r\n\t\tif (DebugGodMode) {\r\n\t\t\tdam = monster.hitPoints; /* ensure monster is killed with one hit */\r\n\t\t}\r\n#endif\r\n\t\tApplyMonsterDamage(DamageType::Physical, monster, dam);\r\n\t}\r\n\r\n\tint skdam = 0;\r\n\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::RandomStealLife)) {\r\n\t\tskdam = GenerateRnd(dam / 8);\r\n\t\tplayer._pHitPoints += skdam;\r\n\t\tif (player._pHitPoints > player._pMaxHP) {\r\n\t\t\tplayer._pHitPoints = player._pMaxHP;\r\n\t\t}\r\n\t\tplayer._pHPBase += skdam;\r\n\t\tif (player._pHPBase > player._pMaxHPBase) {\r\n\t\t\tplayer._pHPBase = player._pMaxHPBase;\r\n\t\t}\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t}\r\n\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::StealMana3 | ItemSpecialEffect::StealMana5) && HasNoneOf(player._pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::StealMana3)) {\r\n\t\t\tskdam = 3 * dam / 100;\r\n\t\t}\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::StealMana5)) {\r\n\t\t\tskdam = 5 * dam / 100;\r\n\t\t}\r\n\t\tplayer._pMana += skdam;\r\n\t\tif (player._pMana > player._pMaxMana) {\r\n\t\t\tplayer._pMana = player._pMaxMana;\r\n\t\t}\r\n\t\tplayer._pManaBase += skdam;\r\n\t\tif (player._pManaBase > player._pMaxManaBase) {\r\n\t\t\tplayer._pManaBase = player._pMaxManaBase;\r\n\t\t}\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t}\r\n\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::StealLife3 | ItemSpecialEffect::StealLife5)) {\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::StealLife3)) {\r\n\t\t\tskdam = 3 * dam / 100;\r\n\t\t}\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::StealLife5)) {\r\n\t\t\tskdam = 5 * dam / 100;\r\n\t\t}\r\n\t\tplayer._pHitPoints += skdam;\r\n\t\tif (player._pHitPoints > player._pMaxHP) {\r\n\t\t\tplayer._pHitPoints = player._pMaxHP;\r\n\t\t}\r\n\t\tplayer._pHPBase += skdam;\r\n\t\tif (player._pHPBase > player._pMaxHPBase) {\r\n\t\t\tplayer._pHPBase = player._pMaxHPBase;\r\n\t\t}\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t}\r\n\tif (monster.hasNoLife()) {\r\n\t\tM_StartKill(monster, player);\r\n\t} else {\r\n\t\tif (monster.mode != MonsterMode::Petrified && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))\r\n\t\t\tM_GetKnockback(monster, player.position.tile);\r\n\t\tM_StartHit(monster, player, dam);\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool PlrHitPlr(Player &attacker, Player &target)\r\n{\r\n\tif (target._pInvincible) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (HasAnyOf(target._pSpellFlags, SpellFlag::Etherealize)) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst int hit = GenerateRnd(100);\r\n\r\n\tint hper = attacker.GetMeleeToHit() - target.GetArmor();\r\n\thper = std::clamp(hper, 5, 95);\r\n\r\n\tint blk = 100;\r\n\tif ((target._pmode == PM_STAND || target._pmode == PM_ATTACK) && target._pBlockFlag) {\r\n\t\tblk = GenerateRnd(100);\r\n\t}\r\n\r\n\tint blkper = target.GetBlockChance() - (attacker.getCharacterLevel() * 2);\r\n\tblkper = std::clamp(blkper, 0, 100);\r\n\r\n\tif (hit >= hper) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (blk < blkper) {\r\n\t\tconst Direction dir = GetDirection(target.position.tile, attacker.position.tile);\r\n\t\tStartPlrBlock(target, dir);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconst int mind = attacker._pIMinDam;\r\n\tconst int maxd = attacker._pIMaxDam;\r\n\tint dam = RandomIntBetween(mind, maxd);\r\n\tdam += (dam * attacker._pIBonusDam) / 100;\r\n\tdam += attacker._pIBonusDamMod + attacker._pDamageMod;\r\n\r\n\tconst ClassAttributes &classAttributes = GetClassAttributes(attacker._pClass);\r\n\tif (HasAnyOf(classAttributes.classFlags, PlayerClassFlag::CriticalStrike)) {\r\n\t\tif (GenerateRnd(100) < attacker.getCharacterLevel()) {\r\n\t\t\tdam *= 2;\r\n\t\t}\r\n\t}\r\n\tconst int skdam = dam << 6;\r\n\tif (HasAnyOf(attacker._pIFlags, ItemSpecialEffect::RandomStealLife)) {\r\n\t\tconst int tac = GenerateRnd(skdam / 8);\r\n\t\tattacker._pHitPoints += tac;\r\n\t\tif (attacker._pHitPoints > attacker._pMaxHP) {\r\n\t\t\tattacker._pHitPoints = attacker._pMaxHP;\r\n\t\t}\r\n\t\tattacker._pHPBase += tac;\r\n\t\tif (attacker._pHPBase > attacker._pMaxHPBase) {\r\n\t\t\tattacker._pHPBase = attacker._pMaxHPBase;\r\n\t\t}\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t}\r\n\tif (&attacker == MyPlayer) {\r\n\t\tNetSendCmdDamage(true, target, skdam, DamageType::Physical);\r\n\t}\r\n\tStartPlrHit(target, skdam, false);\r\n\r\n\treturn true;\r\n}\r\n\r\nbool PlrHitObj(const Player &player, Object &targetObject)\r\n{\r\n\tif (targetObject.IsBreakable()) {\r\n\t\tBreakObject(player, targetObject);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool DoAttack(Player &player)\r\n{\r\n\tif (player.AnimInfo.currentFrame == player._pAFNum - 2) {\r\n\t\tPlaySfxLoc(SfxID::Swing, player.position.tile);\r\n\t}\r\n\r\n\tbool didhit = false;\r\n\r\n\tif (player.AnimInfo.currentFrame == player._pAFNum - 1) {\r\n\t\tPoint position = player.position.tile + player._pdir;\r\n\t\tMonster *monster = FindMonsterAtPosition(position);\r\n\r\n\t\tif (monster != nullptr) {\r\n\t\t\tif (CanTalkToMonst(*monster)) {\r\n\t\t\t\tplayer.position.temp.x = 0; /** @todo Looks to be irrelevant, probably just remove it */\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!gbIsHellfire || !HasAllOf(player._pIFlags, ItemSpecialEffect::FireDamage | ItemSpecialEffect::LightningDamage)) {\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FireDamage)) {\r\n\t\t\t\tAddMissile(position, { 1, 0 }, Direction::South, MissileID::WeaponExplosion, TARGET_MONSTERS, player, 0, 0);\r\n\t\t\t}\r\n\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::LightningDamage)) {\r\n\t\t\t\tAddMissile(position, { 2, 0 }, Direction::South, MissileID::WeaponExplosion, TARGET_MONSTERS, player, 0, 0);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (monster != nullptr) {\r\n\t\t\tdidhit = PlrHitMonst(player, *monster);\r\n\t\t} else if (PlayerAtPosition(position) != nullptr && !player.friendlyMode) {\r\n\t\t\tdidhit = PlrHitPlr(player, *PlayerAtPosition(position));\r\n\t\t} else {\r\n\t\t\tObject *object = FindObjectAtPosition(position, false);\r\n\t\t\tif (object != nullptr) {\r\n\t\t\t\tdidhit = PlrHitObj(player, *object);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (player.CanCleave()) {\r\n\t\t\t// playing as a class/weapon with cleave\r\n\t\t\tposition = player.position.tile + Right(player._pdir);\r\n\t\t\tmonster = FindMonsterAtPosition(position);\r\n\t\t\tif (monster != nullptr) {\r\n\t\t\t\tif (!CanTalkToMonst(*monster) && monster->position.old == position) {\r\n\t\t\t\t\tif (PlrHitMonst(player, *monster, true))\r\n\t\t\t\t\t\tdidhit = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tposition = player.position.tile + Left(player._pdir);\r\n\t\t\tmonster = FindMonsterAtPosition(position);\r\n\t\t\tif (monster != nullptr) {\r\n\t\t\t\tif (!CanTalkToMonst(*monster) && monster->position.old == position) {\r\n\t\t\t\t\tif (PlrHitMonst(player, *monster, true))\r\n\t\t\t\t\t\tdidhit = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (didhit && DamageWeapon(player, 30)) {\r\n\t\t\tStartStand(player, player._pdir);\r\n\t\t\tClearStateVariables(player);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (player.AnimInfo.isLastFrame()) {\r\n\t\tStartStand(player, player._pdir);\r\n\t\tClearStateVariables(player);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool DoRangeAttack(Player &player)\r\n{\r\n\tint arrows = 0;\r\n\tif (player.AnimInfo.currentFrame == player._pAFNum - 1) {\r\n\t\tarrows = 1;\r\n\t}\r\n\r\n\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::MultipleArrows) && player.AnimInfo.currentFrame == player._pAFNum + 1) {\r\n\t\tarrows = 2;\r\n\t}\r\n\r\n\tfor (int arrow = 0; arrow < arrows; arrow++) {\r\n\t\tint xoff = 0;\r\n\t\tint yoff = 0;\r\n\t\tif (arrows != 1) {\r\n\t\t\tconst int angle = arrow == 0 ? -1 : 1;\r\n\t\t\tconst int x = player.position.temp.x - player.position.tile.x;\r\n\t\t\tif (x != 0)\r\n\t\t\t\tyoff = x < 0 ? angle : -angle;\r\n\t\t\tconst int y = player.position.temp.y - player.position.tile.y;\r\n\t\t\tif (y != 0)\r\n\t\t\t\txoff = y < 0 ? -angle : angle;\r\n\t\t}\r\n\r\n\t\tint dmg = 4;\r\n\t\tMissileID mistype = MissileID::Arrow;\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FireArrows)) {\r\n\t\t\tmistype = MissileID::FireArrow;\r\n\t\t}\r\n\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::LightningArrows)) {\r\n\t\t\tmistype = MissileID::LightningArrow;\r\n\t\t}\r\n\t\tif (HasAllOf(player._pIFlags, ItemSpecialEffect::FireArrows | ItemSpecialEffect::LightningArrows)) {\r\n\t\t\t// Fixed off by 1 error from Hellfire\r\n\t\t\tdmg = RandomIntBetween(player._pIFMinDam, player._pIFMaxDam);\r\n\t\t\tmistype = MissileID::SpectralArrow;\r\n\t\t}\r\n\r\n\t\tAddMissile(\r\n\t\t    player.position.tile,\r\n\t\t    player.position.temp + Displacement { xoff, yoff },\r\n\t\t    player._pdir,\r\n\t\t    mistype,\r\n\t\t    TARGET_MONSTERS,\r\n\t\t    player,\r\n\t\t    dmg,\r\n\t\t    0);\r\n\r\n\t\tif (arrow == 0 && mistype != MissileID::SpectralArrow) {\r\n\t\t\tPlaySfxLoc(arrows != 1 ? SfxID::ShootBow2 : SfxID::ShootBow, player.position.tile);\r\n\t\t}\r\n\r\n\t\tif (DamageWeapon(player, 40)) {\r\n\t\t\tStartStand(player, player._pdir);\r\n\t\t\tClearStateVariables(player);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\tif (player.AnimInfo.isLastFrame()) {\r\n\t\tStartStand(player, player._pdir);\r\n\t\tClearStateVariables(player);\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid DamageParryItem(Player &player)\r\n{\r\n\tif (&player != MyPlayer) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (player.InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Shield || player.InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Staff) {\r\n\t\tif (player.InvBody[INVLOC_HAND_LEFT]._iDurability == DUR_INDESTRUCTIBLE) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tplayer.InvBody[INVLOC_HAND_LEFT]._iDurability--;\r\n\t\tif (player.InvBody[INVLOC_HAND_LEFT]._iDurability == 0) {\r\n\t\t\tRemoveEquipment(player, INVLOC_HAND_LEFT, true);\r\n\t\t\tCalcPlrInv(player, true);\r\n\t\t}\r\n\t}\r\n\r\n\tif (player.InvBody[INVLOC_HAND_RIGHT]._itype == ItemType::Shield) {\r\n\t\tif (player.InvBody[INVLOC_HAND_RIGHT]._iDurability != DUR_INDESTRUCTIBLE) {\r\n\t\t\tplayer.InvBody[INVLOC_HAND_RIGHT]._iDurability--;\r\n\t\t\tif (player.InvBody[INVLOC_HAND_RIGHT]._iDurability == 0) {\r\n\t\t\t\tRemoveEquipment(player, INVLOC_HAND_RIGHT, true);\r\n\t\t\t\tCalcPlrInv(player, true);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool DoBlock(Player &player)\r\n{\r\n\tif (player.AnimInfo.isLastFrame()) {\r\n\t\tStartStand(player, player._pdir);\r\n\t\tClearStateVariables(player);\r\n\r\n\t\tif (FlipCoin(10)) {\r\n\t\t\tDamageParryItem(player);\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid DamageArmor(Player &player)\r\n{\r\n\tif (&player != MyPlayer) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (player.InvBody[INVLOC_CHEST].isEmpty() && player.InvBody[INVLOC_HEAD].isEmpty()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tbool targetHead = FlipCoin(3);\r\n\tif (!player.InvBody[INVLOC_CHEST].isEmpty() && player.InvBody[INVLOC_HEAD].isEmpty()) {\r\n\t\ttargetHead = false;\r\n\t}\r\n\tif (player.InvBody[INVLOC_CHEST].isEmpty() && !player.InvBody[INVLOC_HEAD].isEmpty()) {\r\n\t\ttargetHead = true;\r\n\t}\r\n\r\n\tItem *pi;\r\n\tif (targetHead) {\r\n\t\tpi = &player.InvBody[INVLOC_HEAD];\r\n\t} else {\r\n\t\tpi = &player.InvBody[INVLOC_CHEST];\r\n\t}\r\n\tif (pi->_iDurability == DUR_INDESTRUCTIBLE) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tpi->_iDurability--;\r\n\tif (pi->_iDurability != 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (targetHead) {\r\n\t\tRemoveEquipment(player, INVLOC_HEAD, true);\r\n\t} else {\r\n\t\tRemoveEquipment(player, INVLOC_CHEST, true);\r\n\t}\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nbool DoSpell(Player &player)\r\n{\r\n\tif (player.AnimInfo.currentFrame == player._pSFNum) {\r\n\t\tCastSpell(\r\n\t\t    player,\r\n\t\t    player.executedSpell.spellId,\r\n\t\t    player.position.tile,\r\n\t\t    player.position.temp,\r\n\t\t    player.executedSpell.spellLevel);\r\n\r\n\t\tif (IsAnyOf(player.executedSpell.spellType, SpellType::Scroll, SpellType::Charges)) {\r\n\t\t\tEnsureValidReadiedSpell(player);\r\n\t\t}\r\n\t}\r\n\r\n\tif (player.AnimInfo.isLastFrame()) {\r\n\t\tStartStand(player, player._pdir);\r\n\t\tClearStateVariables(player);\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool DoGotHit(Player &player)\r\n{\r\n\tif (player.AnimInfo.isLastFrame()) {\r\n\t\tStartStand(player, player._pdir);\r\n\t\tClearStateVariables(player);\r\n\t\tif (!FlipCoin(4)) {\r\n\t\t\tDamageArmor(player);\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool DoDeath(Player &player)\r\n{\r\n\tif (player.AnimInfo.isLastFrame()) {\r\n\t\tif (player.AnimInfo.tickCounterOfCurrentFrame == 0) {\r\n\t\t\tplayer.AnimInfo.ticksPerFrame = 100;\r\n\t\t\tdFlags[player.position.tile.x][player.position.tile.y] |= DungeonFlag::DeadPlayer;\r\n\t\t} else if (&player == MyPlayer && player.AnimInfo.tickCounterOfCurrentFrame == 30) {\r\n\t\t\tMyPlayerIsDead = true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool IsPlayerAdjacentToObject(Player &player, Object &object)\r\n{\r\n\tconst int x = std::abs(player.position.tile.x - object.position.x);\r\n\tint y = std::abs(player.position.tile.y - object.position.y);\r\n\tif (y > 1 && object.position.y >= 1 && FindObjectAtPosition(object.position + Direction::NorthEast) == &object) {\r\n\t\t// special case for activating a large object from the north-east side\r\n\t\ty = std::abs(player.position.tile.y - object.position.y + 1);\r\n\t}\r\n\treturn x <= 1 && y <= 1;\r\n}\r\n\r\nvoid TryDisarm(const Player &player, Object &object)\r\n{\r\n\tif (&player == MyPlayer)\r\n\t\tNewCursor(CURSOR_HAND);\r\n\tif (!object._oTrapFlag) {\r\n\t\treturn;\r\n\t}\r\n\tconst int trapdisper = 2 * player._pDexterity - 5 * currlevel;\r\n\tif (GenerateRnd(100) > trapdisper) {\r\n\t\treturn;\r\n\t}\r\n\tfor (int j = 0; j < ActiveObjectCount; j++) {\r\n\t\tObject &trap = Objects[ActiveObjects[j]];\r\n\t\tif (trap.IsTrap() && FindObjectAtPosition({ trap._oVar1, trap._oVar2 }) == &object) {\r\n\t\t\ttrap._oVar4 = 1;\r\n\t\t\tobject._oTrapFlag = false;\r\n\t\t}\r\n\t}\r\n\tif (object.IsTrappedChest()) {\r\n\t\tobject._oTrapFlag = false;\r\n\t}\r\n}\r\n\r\nvoid CheckNewPath(Player &player, bool pmWillBeCalled)\r\n{\r\n\tint x = 0;\r\n\tint y = 0;\r\n\r\n\tMonster *monster;\r\n\tPlayer *target;\r\n\tObject *object;\r\n\tItem *item;\r\n\r\n\tconst int targetId = player.destParam1;\r\n\r\n\tswitch (player.destAction) {\r\n\tcase ACTION_ATTACKMON:\r\n\tcase ACTION_RATTACKMON:\r\n\tcase ACTION_SPELLMON:\r\n\t\tmonster = &Monsters[targetId];\r\n\t\tif (monster->hasNoLife()) {\r\n\t\t\tplayer.Stop();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (player.destAction == ACTION_ATTACKMON)\r\n\t\t\tMakePlrPath(player, monster->position.future, false);\r\n\t\tbreak;\r\n\tcase ACTION_ATTACKPLR:\r\n\tcase ACTION_RATTACKPLR:\r\n\tcase ACTION_SPELLPLR:\r\n\t\ttarget = &Players[targetId];\r\n\t\tif (target->hasNoLife()) {\r\n\t\t\tplayer.Stop();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (player.destAction == ACTION_ATTACKPLR)\r\n\t\t\tMakePlrPath(player, target->position.future, false);\r\n\t\tbreak;\r\n\tcase ACTION_OPERATE:\r\n\tcase ACTION_DISARM:\r\n\tcase ACTION_OPERATETK:\r\n\t\tobject = &Objects[targetId];\r\n\t\tbreak;\r\n\tcase ACTION_PICKUPITEM:\r\n\tcase ACTION_PICKUPAITEM:\r\n\t\titem = &Items[targetId];\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tDirection d;\r\n\tif (player.walkpath[0] != WALK_NONE) {\r\n\t\tif (player._pmode == PM_STAND) {\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tif (player.destAction == ACTION_ATTACKMON || player.destAction == ACTION_ATTACKPLR) {\r\n\t\t\t\t\tif (player.destAction == ACTION_ATTACKMON) {\r\n\t\t\t\t\t\tx = std::abs(player.position.future.x - monster->position.future.x);\r\n\t\t\t\t\t\ty = std::abs(player.position.future.y - monster->position.future.y);\r\n\t\t\t\t\t\td = GetDirection(player.position.future, monster->position.future);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tx = std::abs(player.position.future.x - target->position.future.x);\r\n\t\t\t\t\t\ty = std::abs(player.position.future.y - target->position.future.y);\r\n\t\t\t\t\t\td = GetDirection(player.position.future, target->position.future);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (x < 2 && y < 2) {\r\n\t\t\t\t\t\tClrPlrPath(player);\r\n\t\t\t\t\t\tif (player.destAction == ACTION_ATTACKMON && monster->talkMsg != TEXT_NONE && monster->talkMsg != TEXT_VILE14) {\r\n\t\t\t\t\t\t\tTalktoMonster(player, *monster);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tswitch (player.walkpath[0]) {\r\n\t\t\tcase WALK_N:\r\n\t\t\t\tStartWalk(player, Direction::North, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_NE:\r\n\t\t\t\tStartWalk(player, Direction::NorthEast, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_E:\r\n\t\t\t\tStartWalk(player, Direction::East, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_SE:\r\n\t\t\t\tStartWalk(player, Direction::SouthEast, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_S:\r\n\t\t\t\tStartWalk(player, Direction::South, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_SW:\r\n\t\t\t\tStartWalk(player, Direction::SouthWest, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_W:\r\n\t\t\t\tStartWalk(player, Direction::West, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_NW:\r\n\t\t\t\tStartWalk(player, Direction::NorthWest, pmWillBeCalled);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tfor (size_t j = 1; j < MaxPathLengthPlayer; j++) {\r\n\t\t\t\tplayer.walkpath[j - 1] = player.walkpath[j];\r\n\t\t\t}\r\n\r\n\t\t\tplayer.walkpath[MaxPathLengthPlayer - 1] = WALK_NONE;\r\n\r\n\t\t\tif (player._pmode == PM_STAND) {\r\n\t\t\t\tStartStand(player, player._pdir);\r\n\t\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn;\r\n\t}\r\n\tif (player.destAction == ACTION_NONE) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (player._pmode == PM_STAND) {\r\n\t\tswitch (player.destAction) {\r\n\t\tcase ACTION_ATTACK:\r\n\t\t\td = GetDirection(player.position.tile, { player.destParam1, player.destParam2 });\r\n\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\tbreak;\r\n\t\tcase ACTION_ATTACKMON:\r\n\t\t\tx = std::abs(player.position.tile.x - monster->position.future.x);\r\n\t\t\ty = std::abs(player.position.tile.y - monster->position.future.y);\r\n\t\t\tif (x <= 1 && y <= 1) {\r\n\t\t\t\td = GetDirection(player.position.future, monster->position.future);\r\n\t\t\t\tif (monster->talkMsg != TEXT_NONE && monster->talkMsg != TEXT_VILE14) {\r\n\t\t\t\t\tTalktoMonster(player, *monster);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_ATTACKPLR:\r\n\t\t\tx = std::abs(player.position.tile.x - target->position.future.x);\r\n\t\t\ty = std::abs(player.position.tile.y - target->position.future.y);\r\n\t\t\tif (x <= 1 && y <= 1) {\r\n\t\t\t\td = GetDirection(player.position.future, target->position.future);\r\n\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_RATTACK:\r\n\t\t\td = GetDirection(player.position.tile, { player.destParam1, player.destParam2 });\r\n\t\t\tStartRangeAttack(player, d, player.destParam1, player.destParam2, pmWillBeCalled);\r\n\t\t\tbreak;\r\n\t\tcase ACTION_RATTACKMON:\r\n\t\t\td = GetDirection(player.position.future, monster->position.future);\r\n\t\t\tif (monster->talkMsg != TEXT_NONE && monster->talkMsg != TEXT_VILE14) {\r\n\t\t\t\tTalktoMonster(player, *monster);\r\n\t\t\t} else {\r\n\t\t\t\tStartRangeAttack(player, d, monster->position.future.x, monster->position.future.y, pmWillBeCalled);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_RATTACKPLR:\r\n\t\t\td = GetDirection(player.position.future, target->position.future);\r\n\t\t\tStartRangeAttack(player, d, target->position.future.x, target->position.future.y, pmWillBeCalled);\r\n\t\t\tbreak;\r\n\t\tcase ACTION_SPELL:\r\n\t\t\td = GetDirection(player.position.tile, { player.destParam1, player.destParam2 });\r\n\t\t\tStartSpell(player, d, player.destParam1, player.destParam2);\r\n\t\t\tbreak;\r\n\t\tcase ACTION_SPELLWALL:\r\n\t\t\tStartSpell(player, static_cast<Direction>(player.destParam3), player.destParam1, player.destParam2);\r\n\t\t\tplayer.tempDirection = static_cast<Direction>(player.destParam3);\r\n\t\t\tbreak;\r\n\t\tcase ACTION_SPELLMON:\r\n\t\t\td = GetDirection(player.position.tile, monster->position.future);\r\n\t\t\tStartSpell(player, d, monster->position.future.x, monster->position.future.y);\r\n\t\t\tbreak;\r\n\t\tcase ACTION_SPELLPLR:\r\n\t\t\td = GetDirection(player.position.tile, target->position.future);\r\n\t\t\tStartSpell(player, d, target->position.future.x, target->position.future.y);\r\n\t\t\tbreak;\r\n\t\tcase ACTION_OPERATE:\r\n\t\t\tif (IsPlayerAdjacentToObject(player, *object)) {\r\n\t\t\t\tif (object->_oBreak == 1) {\r\n\t\t\t\t\td = GetDirection(player.position.tile, object->position);\r\n\t\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tOperateObject(player, *object);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_DISARM:\r\n\t\t\tif (IsPlayerAdjacentToObject(player, *object)) {\r\n\t\t\t\tif (object->_oBreak == 1) {\r\n\t\t\t\t\td = GetDirection(player.position.tile, object->position);\r\n\t\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tTryDisarm(player, *object);\r\n\t\t\t\t\tOperateObject(player, *object);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_OPERATETK:\r\n\t\t\tif (object->_oBreak != 1) {\r\n\t\t\t\tOperateObject(player, *object);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_PICKUPITEM:\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tx = std::abs(player.position.tile.x - item->position.x);\r\n\t\t\t\ty = std::abs(player.position.tile.y - item->position.y);\r\n\t\t\t\tif (x <= 1 && y <= 1 && pcurs == CURSOR_HAND && !item->_iRequest) {\r\n\t\t\t\t\tNetSendCmdGItem(true, CMD_REQUESTGITEM, player, targetId);\r\n\t\t\t\t\titem->_iRequest = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_PICKUPAITEM:\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tx = std::abs(player.position.tile.x - item->position.x);\r\n\t\t\t\ty = std::abs(player.position.tile.y - item->position.y);\r\n\t\t\t\tif (x <= 1 && y <= 1 && pcurs == CURSOR_HAND) {\r\n\t\t\t\t\tNetSendCmdGItem(true, CMD_REQUESTAGITEM, player, targetId);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ACTION_TALK:\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tHelpFlag = false;\r\n\t\t\t\tTalkToTowner(player, player.destParam1);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tFixPlayerLocation(player, player._pdir);\r\n\t\tplayer.destAction = ACTION_NONE;\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (player._pmode == PM_ATTACK && player.AnimInfo.currentFrame >= player._pAFNum) {\r\n\t\tif (player.destAction == ACTION_ATTACK) {\r\n\t\t\td = GetDirection(player.position.future, { player.destParam1, player.destParam2 });\r\n\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t} else if (player.destAction == ACTION_ATTACKMON) {\r\n\t\t\tx = std::abs(player.position.tile.x - monster->position.future.x);\r\n\t\t\ty = std::abs(player.position.tile.y - monster->position.future.y);\r\n\t\t\tif (x <= 1 && y <= 1) {\r\n\t\t\t\td = GetDirection(player.position.future, monster->position.future);\r\n\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t}\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t} else if (player.destAction == ACTION_ATTACKPLR) {\r\n\t\t\tx = std::abs(player.position.tile.x - target->position.future.x);\r\n\t\t\ty = std::abs(player.position.tile.y - target->position.future.y);\r\n\t\t\tif (x <= 1 && y <= 1) {\r\n\t\t\t\td = GetDirection(player.position.future, target->position.future);\r\n\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t}\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t} else if (player.destAction == ACTION_OPERATE) {\r\n\t\t\tif (IsPlayerAdjacentToObject(player, *object)) {\r\n\t\t\t\tif (object->_oBreak == 1) {\r\n\t\t\t\t\td = GetDirection(player.position.tile, object->position);\r\n\t\t\t\t\tStartAttack(player, d, pmWillBeCalled);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (player._pmode == PM_RATTACK && player.AnimInfo.currentFrame >= player._pAFNum) {\r\n\t\tif (player.destAction == ACTION_RATTACK) {\r\n\t\t\td = GetDirection(player.position.tile, { player.destParam1, player.destParam2 });\r\n\t\t\tStartRangeAttack(player, d, player.destParam1, player.destParam2, pmWillBeCalled);\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t} else if (player.destAction == ACTION_RATTACKMON) {\r\n\t\t\td = GetDirection(player.position.tile, monster->position.future);\r\n\t\t\tStartRangeAttack(player, d, monster->position.future.x, monster->position.future.y, pmWillBeCalled);\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t} else if (player.destAction == ACTION_RATTACKPLR) {\r\n\t\t\td = GetDirection(player.position.tile, target->position.future);\r\n\t\t\tStartRangeAttack(player, d, target->position.future.x, target->position.future.y, pmWillBeCalled);\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t}\r\n\t}\r\n\r\n\tif (player._pmode == PM_SPELL && player.AnimInfo.currentFrame >= player._pSFNum) {\r\n\t\tif (player.destAction == ACTION_SPELL) {\r\n\t\t\td = GetDirection(player.position.tile, { player.destParam1, player.destParam2 });\r\n\t\t\tStartSpell(player, d, player.destParam1, player.destParam2);\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t} else if (player.destAction == ACTION_SPELLMON) {\r\n\t\t\td = GetDirection(player.position.tile, monster->position.future);\r\n\t\t\tStartSpell(player, d, monster->position.future.x, monster->position.future.y);\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t} else if (player.destAction == ACTION_SPELLPLR) {\r\n\t\t\td = GetDirection(player.position.tile, target->position.future);\r\n\t\t\tStartSpell(player, d, target->position.future.x, target->position.future.y);\r\n\t\t\tplayer.destAction = ACTION_NONE;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool PlrDeathModeOK(Player &player)\r\n{\r\n\tif (&player != MyPlayer) {\r\n\t\treturn true;\r\n\t}\r\n\tif (player._pmode == PM_DEATH) {\r\n\t\treturn true;\r\n\t}\r\n\tif (player._pmode == PM_QUIT) {\r\n\t\treturn true;\r\n\t}\r\n\tif (player._pmode == PM_NEWLVL) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid ValidatePlayer()\r\n{\r\n\tassert(MyPlayer != nullptr);\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\t// Player::setCharacterLevel ensures that the player level is within the expected range in case someone has edited their character level in memory\r\n\tmyPlayer.setCharacterLevel(myPlayer.getCharacterLevel());\r\n\t// This lets us catch cases where someone is editing experience directly through memory modification and reset their experience back to the expected cap.\r\n\tif (myPlayer._pExperience > myPlayer.getNextExperienceThreshold()) {\r\n\t\tmyPlayer._pExperience = myPlayer.getNextExperienceThreshold();\r\n\t\tif (*GetOptions().Gameplay.experienceBar) {\r\n\t\t\tRedrawEverything();\r\n\t\t}\r\n\t}\r\n\r\n\tint gt = 0;\r\n\tfor (int i = 0; i < myPlayer._pNumInv; i++) {\r\n\t\tif (myPlayer.InvList[i]._itype == ItemType::Gold) {\r\n\t\t\tint maxGold = GOLD_MAX_LIMIT;\r\n\t\t\tif (gbIsHellfire) {\r\n\t\t\t\tmaxGold *= 2;\r\n\t\t\t}\r\n\t\t\tif (myPlayer.InvList[i]._ivalue > maxGold) {\r\n\t\t\t\tmyPlayer.InvList[i]._ivalue = maxGold;\r\n\t\t\t}\r\n\t\t\tgt += myPlayer.InvList[i]._ivalue;\r\n\t\t}\r\n\t}\r\n\tif (gt != myPlayer._pGold)\r\n\t\tmyPlayer._pGold = gt;\r\n\r\n\tif (myPlayer._pBaseStr > myPlayer.GetMaximumAttributeValue(CharacterAttribute::Strength)) {\r\n\t\tmyPlayer._pBaseStr = myPlayer.GetMaximumAttributeValue(CharacterAttribute::Strength);\r\n\t}\r\n\tif (myPlayer._pBaseMag > myPlayer.GetMaximumAttributeValue(CharacterAttribute::Magic)) {\r\n\t\tmyPlayer._pBaseMag = myPlayer.GetMaximumAttributeValue(CharacterAttribute::Magic);\r\n\t}\r\n\tif (myPlayer._pBaseDex > myPlayer.GetMaximumAttributeValue(CharacterAttribute::Dexterity)) {\r\n\t\tmyPlayer._pBaseDex = myPlayer.GetMaximumAttributeValue(CharacterAttribute::Dexterity);\r\n\t}\r\n\tif (myPlayer._pBaseVit > myPlayer.GetMaximumAttributeValue(CharacterAttribute::Vitality)) {\r\n\t\tmyPlayer._pBaseVit = myPlayer.GetMaximumAttributeValue(CharacterAttribute::Vitality);\r\n\t}\r\n\r\n\tuint64_t msk = 0;\r\n\tfor (size_t b = static_cast<size_t>(SpellID::Firebolt); b < SpellsData.size(); b++) {\r\n\t\tif (GetSpellBookLevel((SpellID)b) != -1) {\r\n\t\t\tmsk |= GetSpellBitmask(static_cast<SpellID>(b));\r\n\t\t\tif (myPlayer._pSplLvl[b] > MaxSpellLevel)\r\n\t\t\t\tmyPlayer._pSplLvl[b] = MaxSpellLevel;\r\n\t\t}\r\n\t}\r\n\r\n\tmyPlayer._pMemSpells &= msk;\r\n\tmyPlayer._pInfraFlag = false;\r\n}\r\n\r\nHeroClass GetPlayerSpriteClass(HeroClass cls)\r\n{\r\n\tif (cls == HeroClass::Bard && !HaveBardAssets())\r\n\t\treturn HeroClass::Rogue;\r\n\tif (cls == HeroClass::Barbarian && !HaveBarbarianAssets())\r\n\t\treturn HeroClass::Warrior;\r\n\treturn cls;\r\n}\r\n\r\nPlayerWeaponGraphic GetPlayerWeaponGraphic(player_graphic graphic, PlayerWeaponGraphic weaponGraphic)\r\n{\r\n\tif (leveltype == DTYPE_TOWN && IsAnyOf(graphic, player_graphic::Lightning, player_graphic::Fire, player_graphic::Magic)) {\r\n\t\t// If the hero doesn't hold the weapon in town then we should use the unarmed animation for casting\r\n\t\tswitch (weaponGraphic) {\r\n\t\tcase PlayerWeaponGraphic::Mace:\r\n\t\tcase PlayerWeaponGraphic::Sword:\r\n\t\t\treturn PlayerWeaponGraphic::Unarmed;\r\n\t\tcase PlayerWeaponGraphic::SwordShield:\r\n\t\tcase PlayerWeaponGraphic::MaceShield:\r\n\t\t\treturn PlayerWeaponGraphic::UnarmedShield;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn weaponGraphic;\r\n}\r\n\r\nuint16_t GetPlayerSpriteWidth(HeroClass cls, player_graphic graphic, PlayerWeaponGraphic weaponGraphic)\r\n{\r\n\tconst PlayerSpriteData spriteData = GetPlayerSpriteDataForClass(cls);\r\n\r\n\tswitch (graphic) {\r\n\tcase player_graphic::Stand:\r\n\t\treturn spriteData.stand;\r\n\tcase player_graphic::Walk:\r\n\t\treturn spriteData.walk;\r\n\tcase player_graphic::Attack:\r\n\t\tif (weaponGraphic == PlayerWeaponGraphic::Bow)\r\n\t\t\treturn spriteData.bow;\r\n\t\treturn spriteData.attack;\r\n\tcase player_graphic::Hit:\r\n\t\treturn spriteData.swHit;\r\n\tcase player_graphic::Block:\r\n\t\treturn spriteData.block;\r\n\tcase player_graphic::Lightning:\r\n\t\treturn spriteData.lightning;\r\n\tcase player_graphic::Fire:\r\n\t\treturn spriteData.fire;\r\n\tcase player_graphic::Magic:\r\n\t\treturn spriteData.magic;\r\n\tcase player_graphic::Death:\r\n\t\treturn spriteData.death;\r\n\t}\r\n\tapp_fatal(\"Invalid player_graphic\");\r\n}\r\n\r\nvoid GetPlayerGraphicsPath(std::string_view path, std::string_view prefix, std::string_view type, char out[256])\r\n{\r\n\t*BufCopy(out, \"plrgfx\\\\\", path, \"\\\\\", prefix, \"\\\\\", prefix, type) = '\\0';\r\n}\r\n\r\n} // namespace\r\n\r\nvoid Player::CalcScrolls()\r\n{\r\n\t_pScrlSpells = 0;\r\n\tfor (const Item &item : InventoryAndBeltPlayerItemsRange { *this }) {\r\n\t\tif (item.isScroll() && item._iStatFlag) {\r\n\t\t\t_pScrlSpells |= GetSpellBitmask(item._iSpell);\r\n\t\t}\r\n\t}\r\n\tEnsureValidReadiedSpell(*this);\r\n}\r\n\r\nbool Player::CanUseItem(const Item &item) const\r\n{\r\n\tif (!IsItemValid(*this, item))\r\n\t\treturn false;\r\n\r\n\treturn _pStrength >= item._iMinStr\r\n\t    && _pMagic >= item._iMinMag\r\n\t    && _pDexterity >= item._iMinDex;\r\n}\r\n\r\nvoid Player::RemoveInvItem(int iv, bool calcScrolls)\r\n{\r\n\tif (this == MyPlayer) {\r\n\t\t// Locate the first grid index containing this item and notify remote clients\r\n\t\tfor (size_t i = 0; i < InventoryGridCells; i++) {\r\n\t\t\tconst int8_t itemIndex = InvGrid[i];\r\n\t\t\tif (std::abs(itemIndex) - 1 == iv) {\r\n\t\t\t\tNetSendCmdParam1(false, CMD_DELINVITEMS, static_cast<uint16_t>(i));\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Iterate through invGrid and remove every reference to item\r\n\tfor (int8_t &itemIndex : InvGrid) {\r\n\t\tif (std::abs(itemIndex) - 1 == iv) {\r\n\t\t\titemIndex = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tInvList[iv].clear();\r\n\r\n\t_pNumInv--;\r\n\r\n\t// If the item at the end of inventory array isn't the one removed, shift all following items back one index to retain inventory order.\r\n\tif (_pNumInv > 0 && _pNumInv != iv) {\r\n\t\tfor (int newIndex = iv; newIndex < _pNumInv; newIndex++) {\r\n\t\t\tInvList[newIndex] = InvList[newIndex + 1].pop();\r\n\t\t}\r\n\r\n\t\tfor (int8_t &itemIndex : InvGrid) {\r\n\t\t\tif (itemIndex > iv + 1) { // if item was shifted, decrease the index so it's paired with the correct item.\r\n\t\t\t\titemIndex--;\r\n\t\t\t}\r\n\t\t\tif (itemIndex < -(iv + 1)) {\r\n\t\t\t\titemIndex++; // since occupied cells are negative, increment the index to keep it same as as top-left cell for item, only negative.\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (calcScrolls) {\r\n\t\tCalcScrolls();\r\n\t}\r\n}\r\n\r\nvoid Player::RemoveSpdBarItem(int iv)\r\n{\r\n\tif (this == MyPlayer) {\r\n\t\tNetSendCmdParam1(false, CMD_DELBELTITEMS, iv);\r\n\t}\r\n\r\n\tSpdList[iv].clear();\r\n\r\n\tCalcScrolls();\r\n\tRedrawEverything();\r\n}\r\n\r\n[[nodiscard]] uint8_t Player::getId() const\r\n{\r\n\treturn static_cast<uint8_t>(std::distance<const Player *>(&Players[0], this));\r\n}\r\n\r\nint Player::GetBaseAttributeValue(CharacterAttribute attribute) const\r\n{\r\n\tswitch (attribute) {\r\n\tcase CharacterAttribute::Dexterity:\r\n\t\treturn this->_pBaseDex;\r\n\tcase CharacterAttribute::Magic:\r\n\t\treturn this->_pBaseMag;\r\n\tcase CharacterAttribute::Strength:\r\n\t\treturn this->_pBaseStr;\r\n\tcase CharacterAttribute::Vitality:\r\n\t\treturn this->_pBaseVit;\r\n\tdefault:\r\n\t\tapp_fatal(\"Unsupported attribute\");\r\n\t}\r\n}\r\n\r\nint Player::GetCurrentAttributeValue(CharacterAttribute attribute) const\r\n{\r\n\tswitch (attribute) {\r\n\tcase CharacterAttribute::Dexterity:\r\n\t\treturn this->_pDexterity;\r\n\tcase CharacterAttribute::Magic:\r\n\t\treturn this->_pMagic;\r\n\tcase CharacterAttribute::Strength:\r\n\t\treturn this->_pStrength;\r\n\tcase CharacterAttribute::Vitality:\r\n\t\treturn this->_pVitality;\r\n\tdefault:\r\n\t\tapp_fatal(\"Unsupported attribute\");\r\n\t}\r\n}\r\n\r\nint Player::GetMaximumAttributeValue(CharacterAttribute attribute) const\r\n{\r\n\tconst ClassAttributes &attr = getClassAttributes();\r\n\tswitch (attribute) {\r\n\tcase CharacterAttribute::Strength:\r\n\t\treturn attr.maxStr;\r\n\tcase CharacterAttribute::Magic:\r\n\t\treturn attr.maxMag;\r\n\tcase CharacterAttribute::Dexterity:\r\n\t\treturn attr.maxDex;\r\n\tcase CharacterAttribute::Vitality:\r\n\t\treturn attr.maxVit;\r\n\t}\r\n\tapp_fatal(\"Unsupported attribute\");\r\n}\r\n\r\nPoint Player::GetTargetPosition() const\r\n{\r\n\t// clang-format off\r\n\tconstexpr int DirectionOffsetX[8] = {  0,-1, 1, 0,-1, 1, 1,-1 };\r\n\tconstexpr int DirectionOffsetY[8] = { -1, 0, 0, 1,-1,-1, 1, 1 };\r\n\t// clang-format on\r\n\tPoint target = position.future;\r\n\tfor (auto step : walkpath) {\r\n\t\tif (step == WALK_NONE)\r\n\t\t\tbreak;\r\n\t\tif (step > 0) {\r\n\t\t\ttarget.x += DirectionOffsetX[step - 1];\r\n\t\t\ttarget.y += DirectionOffsetY[step - 1];\r\n\t\t}\r\n\t}\r\n\treturn target;\r\n}\r\n\r\nint Player::GetPositionPathIndex(Point pos)\r\n{\r\n\tconstexpr Displacement DirectionOffset[8] = { { 0, -1 }, { -1, 0 }, { 1, 0 }, { 0, 1 }, { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } };\r\n\tPoint target = position.future;\r\n\tint i = 0;\r\n\tfor (auto step : walkpath) {\r\n\t\tif (target == pos) return i;\r\n\t\tif (step == WALK_NONE)\r\n\t\t\tbreak;\r\n\t\tif (step > 0) {\r\n\t\t\ttarget += DirectionOffset[step - 1];\r\n\t\t}\r\n\t\t++i;\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\nvoid Player::Say(HeroSpeech speechId) const\r\n{\r\n\tconst SfxID soundEffect = GetHeroSound(_pClass, speechId);\r\n\r\n\tif (soundEffect == SfxID::None)\r\n\t\treturn;\r\n\r\n\tPlaySfxLoc(soundEffect, position.tile);\r\n}\r\n\r\nvoid Player::SaySpecific(HeroSpeech speechId) const\r\n{\r\n\tconst SfxID soundEffect = GetHeroSound(_pClass, speechId);\r\n\r\n\tif (soundEffect == SfxID::None || effect_is_playing(soundEffect))\r\n\t\treturn;\r\n\r\n\tPlaySfxLoc(soundEffect, position.tile, false);\r\n}\r\n\r\nvoid Player::Say(HeroSpeech speechId, int delay) const\r\n{\r\n\tsfxdelay = delay;\r\n\tsfxdnum = GetHeroSound(_pClass, speechId);\r\n}\r\n\r\nvoid Player::Stop()\r\n{\r\n\tClrPlrPath(*this);\r\n\tdestAction = ACTION_NONE;\r\n}\r\n\r\nbool Player::isWalking() const\r\n{\r\n\treturn IsAnyOf(_pmode, PM_WALK_NORTHWARDS, PM_WALK_SOUTHWARDS, PM_WALK_SIDEWAYS);\r\n}\r\n\r\nint Player::GetManaShieldDamageReduction()\r\n{\r\n\tconstexpr uint8_t Max = 7;\r\n\treturn 24 - std::min(_pSplLvl[static_cast<int8_t>(SpellID::ManaShield)], Max) * 3;\r\n}\r\n\r\nvoid Player::RestorePartialLife()\r\n{\r\n\tconst int wholeHitpoints = _pMaxHP >> 6;\r\n\tint l = ((wholeHitpoints / 8) + GenerateRnd(wholeHitpoints / 4)) << 6;\r\n\tif (IsAnyOf(_pClass, HeroClass::Warrior, HeroClass::Barbarian))\r\n\t\tl *= 2;\r\n\tif (IsAnyOf(_pClass, HeroClass::Rogue, HeroClass::Monk, HeroClass::Bard))\r\n\t\tl += l / 2;\r\n\t_pHitPoints = std::min(_pHitPoints + l, _pMaxHP);\r\n\t_pHPBase = std::min(_pHPBase + l, _pMaxHPBase);\r\n}\r\n\r\nvoid Player::RestorePartialMana()\r\n{\r\n\tconst int wholeManaPoints = _pMaxMana >> 6;\r\n\tint l = ((wholeManaPoints / 8) + GenerateRnd(wholeManaPoints / 4)) << 6;\r\n\tif (_pClass == HeroClass::Sorcerer)\r\n\t\tl *= 2;\r\n\tif (IsAnyOf(_pClass, HeroClass::Rogue, HeroClass::Monk, HeroClass::Bard))\r\n\t\tl += l / 2;\r\n\tif (HasNoneOf(_pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\t_pMana = std::min(_pMana + l, _pMaxMana);\r\n\t\t_pManaBase = std::min(_pManaBase + l, _pMaxManaBase);\r\n\t}\r\n}\r\n\r\nvoid Player::ReadySpellFromEquipment(inv_body_loc bodyLocation, bool forceSpell)\r\n{\r\n\tconst Item &item = InvBody[bodyLocation];\r\n\tif (item._itype == ItemType::Staff && IsValidSpell(item._iSpell) && item._iCharges > 0 && item._iStatFlag) {\r\n\t\tif (forceSpell || _pRSpell == SpellID::Invalid || _pRSplType == SpellType::Invalid) {\r\n\t\t\t_pRSpell = item._iSpell;\r\n\t\t\t_pRSplType = SpellType::Charges;\r\n\t\t\tRedrawEverything();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nplayer_graphic Player::getGraphic() const\r\n{\r\n\tswitch (_pmode) {\r\n\tcase PM_STAND:\r\n\tcase PM_NEWLVL:\r\n\tcase PM_QUIT:\r\n\t\treturn player_graphic::Stand;\r\n\tcase PM_WALK_NORTHWARDS:\r\n\tcase PM_WALK_SOUTHWARDS:\r\n\tcase PM_WALK_SIDEWAYS:\r\n\t\treturn player_graphic::Walk;\r\n\tcase PM_ATTACK:\r\n\tcase PM_RATTACK:\r\n\t\treturn player_graphic::Attack;\r\n\tcase PM_BLOCK:\r\n\t\treturn player_graphic::Block;\r\n\tcase PM_SPELL:\r\n\t\treturn GetPlayerGraphicForSpell(executedSpell.spellId);\r\n\tcase PM_GOTHIT:\r\n\t\treturn player_graphic::Hit;\r\n\tcase PM_DEATH:\r\n\t\treturn player_graphic::Death;\r\n\tdefault:\r\n\t\tapp_fatal(\"SyncPlrAnim\");\r\n\t}\r\n}\r\n\r\nuint16_t Player::getSpriteWidth() const\r\n{\r\n\tif (!HeadlessMode)\r\n\t\treturn (*AnimInfo.sprites)[0].width();\r\n\tconst player_graphic graphic = getGraphic();\r\n\tconst HeroClass cls = GetPlayerSpriteClass(_pClass);\r\n\tconst PlayerWeaponGraphic weaponGraphic = GetPlayerWeaponGraphic(graphic, static_cast<PlayerWeaponGraphic>(_pgfxnum & 0xF));\r\n\treturn GetPlayerSpriteWidth(cls, graphic, weaponGraphic);\r\n}\r\n\r\nvoid Player::getAnimationFramesAndTicksPerFrame(player_graphic graphics, int8_t &numberOfFrames, int8_t &ticksPerFrame) const\r\n{\r\n\tticksPerFrame = 1;\r\n\tswitch (graphics) {\r\n\tcase player_graphic::Stand:\r\n\t\tnumberOfFrames = _pNFrames;\r\n\t\tticksPerFrame = 4;\r\n\t\tbreak;\r\n\tcase player_graphic::Walk:\r\n\t\tnumberOfFrames = _pWFrames;\r\n\t\tbreak;\r\n\tcase player_graphic::Attack:\r\n\t\tnumberOfFrames = _pAFrames;\r\n\t\tbreak;\r\n\tcase player_graphic::Hit:\r\n\t\tnumberOfFrames = _pHFrames;\r\n\t\tbreak;\r\n\tcase player_graphic::Lightning:\r\n\tcase player_graphic::Fire:\r\n\tcase player_graphic::Magic:\r\n\t\tnumberOfFrames = _pSFrames;\r\n\t\tbreak;\r\n\tcase player_graphic::Death:\r\n\t\tnumberOfFrames = _pDFrames;\r\n\t\tticksPerFrame = 2;\r\n\t\tbreak;\r\n\tcase player_graphic::Block:\r\n\t\tnumberOfFrames = _pBFrames;\r\n\t\tticksPerFrame = 3;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"Unknown player graphics\");\r\n\t}\r\n}\r\n\r\nvoid Player::UpdatePreviewCelSprite(_cmd_id cmdId, Point point, uint16_t wParam1, uint16_t wParam2)\r\n{\r\n\t// if game is not running don't show a preview\r\n\tif (!gbRunGame || PauseMode != 0 || !gbProcessPlayers)\r\n\t\treturn;\r\n\r\n\t// we can only show a preview if our command is executed in the next game tick\r\n\tif (_pmode != PM_STAND)\r\n\t\treturn;\r\n\r\n\tstd::optional<player_graphic> graphic;\r\n\tDirection dir = Direction::South;\r\n\tint minimalWalkDistance = -1;\r\n\r\n\tswitch (cmdId) {\r\n\tcase _cmd_id::CMD_RATTACKID: {\r\n\t\tconst Monster &monster = Monsters[wParam1];\r\n\t\tdir = GetDirection(position.future, monster.position.future);\r\n\t\tgraphic = player_graphic::Attack;\r\n\t\tbreak;\r\n\t}\r\n\tcase _cmd_id::CMD_SPELLID: {\r\n\t\tconst Monster &monster = Monsters[wParam1];\r\n\t\tdir = GetDirection(position.future, monster.position.future);\r\n\t\tgraphic = GetPlayerGraphicForSpell(static_cast<SpellID>(wParam2));\r\n\t\tbreak;\r\n\t}\r\n\tcase _cmd_id::CMD_ATTACKID: {\r\n\t\tconst Monster &monster = Monsters[wParam1];\r\n\t\tpoint = monster.position.future;\r\n\t\tminimalWalkDistance = 2;\r\n\t\tif (!CanTalkToMonst(monster)) {\r\n\t\t\tdir = GetDirection(position.future, monster.position.future);\r\n\t\t\tgraphic = player_graphic::Attack;\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\tcase _cmd_id::CMD_RATTACKPID: {\r\n\t\tconst Player &targetPlayer = Players[wParam1];\r\n\t\tdir = GetDirection(position.future, targetPlayer.position.future);\r\n\t\tgraphic = player_graphic::Attack;\r\n\t\tbreak;\r\n\t}\r\n\tcase _cmd_id::CMD_SPELLPID: {\r\n\t\tconst Player &targetPlayer = Players[wParam1];\r\n\t\tdir = GetDirection(position.future, targetPlayer.position.future);\r\n\t\tgraphic = GetPlayerGraphicForSpell(static_cast<SpellID>(wParam2));\r\n\t\tbreak;\r\n\t}\r\n\tcase _cmd_id::CMD_ATTACKPID: {\r\n\t\tconst Player &targetPlayer = Players[wParam1];\r\n\t\tpoint = targetPlayer.position.future;\r\n\t\tminimalWalkDistance = 2;\r\n\t\tdir = GetDirection(position.future, targetPlayer.position.future);\r\n\t\tgraphic = player_graphic::Attack;\r\n\t\tbreak;\r\n\t}\r\n\tcase _cmd_id::CMD_RATTACKXY:\r\n\tcase _cmd_id::CMD_SATTACKXY:\r\n\t\tdir = GetDirection(position.tile, point);\r\n\t\tgraphic = player_graphic::Attack;\r\n\t\tbreak;\r\n\tcase _cmd_id::CMD_SPELLXY:\r\n\t\tdir = GetDirection(position.tile, point);\r\n\t\tgraphic = GetPlayerGraphicForSpell(static_cast<SpellID>(wParam1));\r\n\t\tbreak;\r\n\tcase _cmd_id::CMD_SPELLXYD:\r\n\t\tdir = static_cast<Direction>(wParam2);\r\n\t\tgraphic = GetPlayerGraphicForSpell(static_cast<SpellID>(wParam1));\r\n\t\tbreak;\r\n\tcase _cmd_id::CMD_WALKXY:\r\n\t\tminimalWalkDistance = 1;\r\n\t\tbreak;\r\n\tcase _cmd_id::CMD_TALKXY:\r\n\tcase _cmd_id::CMD_DISARMXY:\r\n\tcase _cmd_id::CMD_OPOBJXY:\r\n\tcase _cmd_id::CMD_GOTOGETITEM:\r\n\tcase _cmd_id::CMD_GOTOAGETITEM:\r\n\t\tminimalWalkDistance = 2;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (minimalWalkDistance >= 0 && position.future != point) {\r\n\t\tint8_t testWalkPath[MaxPathLengthPlayer];\r\n\t\tconst int steps = FindPath(CanStep, [this](Point tile) { return PosOkPlayer(*this, tile); }, position.future, point, testWalkPath, MaxPathLengthPlayer);\r\n\t\tif (steps == 0) {\r\n\t\t\t// Can't walk to desired location => stand still\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (steps >= minimalWalkDistance) {\r\n\t\t\tgraphic = player_graphic::Walk;\r\n\t\t\tswitch (testWalkPath[0]) {\r\n\t\t\tcase WALK_N:\r\n\t\t\t\tdir = Direction::North;\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_NE:\r\n\t\t\t\tdir = Direction::NorthEast;\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_E:\r\n\t\t\t\tdir = Direction::East;\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_SE:\r\n\t\t\t\tdir = Direction::SouthEast;\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_S:\r\n\t\t\t\tdir = Direction::South;\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_SW:\r\n\t\t\t\tdir = Direction::SouthWest;\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_W:\r\n\t\t\t\tdir = Direction::West;\r\n\t\t\t\tbreak;\r\n\t\t\tcase WALK_NW:\r\n\t\t\t\tdir = Direction::NorthWest;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif (!PlrDirOK(*this, dir))\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!graphic || HeadlessMode)\r\n\t\treturn;\r\n\r\n\tLoadPlrGFX(*this, *graphic);\r\n\tconst ClxSpriteList sprites = AnimationData[static_cast<size_t>(*graphic)].spritesForDirection(dir);\r\n\tif (!previewCelSprite || *previewCelSprite != sprites[0]) {\r\n\t\tpreviewCelSprite = sprites[0];\r\n\t\tprogressToNextGameTickWhenPreviewWasSet = ProgressToNextGameTick;\r\n\t}\r\n}\r\n\r\nvoid Player::setCharacterLevel(uint8_t level)\r\n{\r\n\tthis->_pLevel = std::clamp<uint8_t>(level, 1U, getMaxCharacterLevel());\r\n}\r\n\r\nuint8_t Player::getMaxCharacterLevel() const\r\n{\r\n\treturn GetMaximumCharacterLevel();\r\n}\r\n\r\nuint32_t Player::getNextExperienceThreshold() const\r\n{\r\n\treturn GetNextExperienceThresholdForLevel(this->getCharacterLevel());\r\n}\r\n\r\nint32_t Player::calculateBaseLife() const\r\n{\r\n\tconst ClassAttributes &attr = getClassAttributes();\r\n\treturn attr.adjLife + (attr.lvlLife * getCharacterLevel()) + (attr.chrLife * _pBaseVit);\r\n}\r\n\r\nint32_t Player::calculateBaseMana() const\r\n{\r\n\tconst ClassAttributes &attr = getClassAttributes();\r\n\treturn attr.adjMana + (attr.lvlMana * getCharacterLevel()) + (attr.chrMana * _pBaseMag);\r\n}\r\n\r\nvoid Player::occupyTile(Point tilePosition, bool isMoving) const\r\n{\r\n\tint16_t id = this->getId();\r\n\tid += 1;\r\n\tdPlayer[tilePosition.x][tilePosition.y] = isMoving ? -id : id;\r\n}\r\n\r\nbool Player::isLevelOwnedByLocalClient() const\r\n{\r\n\tfor (const Player &other : Players) {\r\n\t\tif (!other.plractive)\r\n\t\t\tcontinue;\r\n\t\tif (other._pLvlChanging)\r\n\t\t\tcontinue;\r\n\t\tif (other._pmode == PM_NEWLVL)\r\n\t\t\tcontinue;\r\n\t\tif (other.plrlevel != this->plrlevel)\r\n\t\t\tcontinue;\r\n\t\tif (other.plrIsOnSetLevel != this->plrIsOnSetLevel)\r\n\t\t\tcontinue;\r\n\t\tif (&other == MyPlayer && gbBufferMsgs != 0)\r\n\t\t\tcontinue;\r\n\t\treturn &other == MyPlayer;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nPlayer *PlayerAtPosition(Point position, bool ignoreMovingPlayers /*= false*/)\r\n{\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn nullptr;\r\n\r\n\tauto playerIndex = dPlayer[position.x][position.y];\r\n\tif (playerIndex == 0 || (ignoreMovingPlayers && playerIndex < 0))\r\n\t\treturn nullptr;\r\n\r\n\treturn &Players[std::abs(playerIndex) - 1];\r\n}\r\n\r\nClxSprite GetPlayerPortraitSprite(Player &player)\r\n{\r\n\tconst bool inDungeon = (player.plrlevel != 0);\r\n\r\n\tconst HeroClass cls = GetPlayerSpriteClass(player._pClass);\r\n\tconst PlayerWeaponGraphic animWeaponId = GetPlayerWeaponGraphic(player_graphic::Stand, static_cast<PlayerWeaponGraphic>(player._pgfxnum & 0xF));\r\n\r\n\tconst PlayerSpriteData &spriteData = GetPlayerSpriteDataForClass(cls);\r\n\tconst char *path = spriteData.classPath.c_str();\r\n\r\n\tstd::string_view szCel = inDungeon ? \"as\" : \"st\";\r\n\r\n\tplayer_graphic graphic = player_graphic::Stand;\r\n\tif (player.hasNoLife()) {\r\n\t\tif (animWeaponId == PlayerWeaponGraphic::Unarmed) {\r\n\t\t\tszCel = \"dt\";\r\n\t\t\tgraphic = player_graphic::Death;\r\n\t\t}\r\n\t}\r\n\r\n\tconst char prefixBuf[3] = { spriteData.classChar, ArmourChar[player._pgfxnum >> 4], WepChar[static_cast<std::size_t>(animWeaponId)] };\r\n\tchar pszName[256];\r\n\tGetPlayerGraphicsPath(path, std::string_view(prefixBuf, 3), szCel, pszName);\r\n\r\n\tconst std::string spritePath { pszName };\r\n\t// Check to see if the sprite has updated.\r\n\tif (player.PartyInfoSpriteLocations[inDungeon] != spritePath) {\r\n\t\t// The sprite has changed so store the new location\r\n\t\tplayer.PartyInfoSpriteLocations[inDungeon] = spritePath;\r\n\r\n\t\tplayer.PartyInfoSprites[inDungeon] = std::nullopt;\r\n\r\n\t\t// And now load the new sprite and store it\r\n\t\tconst uint16_t animationWidth = GetPlayerSpriteWidth(cls, graphic, animWeaponId);\r\n\t\tplayer.PartyInfoSprites[inDungeon] = LoadCl2Sheet(pszName, animationWidth);\r\n\t}\r\n\r\n\tconst ClxSpriteList spriteList = (*player.PartyInfoSprites[inDungeon])[static_cast<size_t>(Direction::South)];\r\n\treturn spriteList[(graphic == player_graphic::Stand) ? 0 : spriteList.numSprites() - 1];\r\n}\r\n\r\nbool IsPlayerUnarmed(Player &player)\r\n{\r\n\tconst PlayerWeaponGraphic animWeaponId = GetPlayerWeaponGraphic(player_graphic::Stand, static_cast<PlayerWeaponGraphic>(player._pgfxnum & 0xF));\r\n\treturn animWeaponId == PlayerWeaponGraphic::Unarmed;\r\n}\r\n\r\nvoid LoadPlrGFX(Player &player, player_graphic graphic)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tauto &animationData = player.AnimationData[static_cast<size_t>(graphic)];\r\n\tif (animationData.sprites)\r\n\t\treturn;\r\n\r\n\tconst HeroClass cls = GetPlayerSpriteClass(player._pClass);\r\n\tPlayerWeaponGraphic animWeaponId = GetPlayerWeaponGraphic(graphic, static_cast<PlayerWeaponGraphic>(player._pgfxnum & 0xF));\r\n\r\n\tconst PlayerSpriteData &spriteData = GetPlayerSpriteDataForClass(cls);\r\n\tconst char *path = spriteData.classPath.c_str();\r\n\r\n\tstd::string_view szCel;\r\n\tswitch (graphic) {\r\n\tcase player_graphic::Stand:\r\n\t\tszCel = \"as\";\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\tszCel = \"st\";\r\n\t\tbreak;\r\n\tcase player_graphic::Walk:\r\n\t\tszCel = \"aw\";\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\tszCel = \"wl\";\r\n\t\tbreak;\r\n\tcase player_graphic::Attack:\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\treturn;\r\n\t\tszCel = \"at\";\r\n\t\tbreak;\r\n\tcase player_graphic::Hit:\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\treturn;\r\n\t\tszCel = \"ht\";\r\n\t\tbreak;\r\n\tcase player_graphic::Lightning:\r\n\t\tszCel = \"lm\";\r\n\t\tbreak;\r\n\tcase player_graphic::Fire:\r\n\t\tszCel = \"fm\";\r\n\t\tbreak;\r\n\tcase player_graphic::Magic:\r\n\t\tszCel = \"qm\";\r\n\t\tbreak;\r\n\tcase player_graphic::Death:\r\n\t\t// Only one Death animation exists, for unarmed characters\r\n\t\tanimWeaponId = PlayerWeaponGraphic::Unarmed;\r\n\t\tszCel = \"dt\";\r\n\t\tbreak;\r\n\tcase player_graphic::Block:\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\treturn;\r\n\t\tif (!player._pBlockFlag)\r\n\t\t\treturn;\r\n\t\tszCel = \"bl\";\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"PLR:2\");\r\n\t}\r\n\r\n\tconst char prefixBuf[3] = { spriteData.classChar, ArmourChar[player._pgfxnum >> 4], WepChar[static_cast<std::size_t>(animWeaponId)] };\r\n\tchar pszName[256];\r\n\tGetPlayerGraphicsPath(path, std::string_view(prefixBuf, 3), szCel, pszName);\r\n\tconst uint16_t animationWidth = GetPlayerSpriteWidth(cls, graphic, animWeaponId);\r\n\tanimationData.sprites = LoadCl2Sheet(pszName, animationWidth);\r\n\tstd::optional<std::array<uint8_t, 256>> graphicTRN = GetPlayerGraphicTRN(pszName);\r\n\tif (graphicTRN) {\r\n\t\tClxApplyTrans(*animationData.sprites, graphicTRN->data());\r\n\t}\r\n\tstd::optional<std::array<uint8_t, 256>> classTRN = GetClassTRN(player);\r\n\tif (classTRN) {\r\n\t\tClxApplyTrans(*animationData.sprites, classTRN->data());\r\n\t}\r\n}\r\n\r\nvoid InitPlayerGFX(Player &player)\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn;\r\n\r\n\tResetPlayerGFX(player);\r\n\r\n\tif (player.hasNoLife()) {\r\n\t\tplayer._pgfxnum &= ~0xFU;\r\n\t\tLoadPlrGFX(player, player_graphic::Death);\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (size_t i = 0; i < enum_size<player_graphic>::value; i++) {\r\n\t\tauto graphic = static_cast<player_graphic>(i);\r\n\t\tif (graphic == player_graphic::Death)\r\n\t\t\tcontinue;\r\n\t\tLoadPlrGFX(player, graphic);\r\n\t}\r\n}\r\n\r\nvoid ResetPlayerGFX(Player &player)\r\n{\r\n\tplayer.AnimInfo.sprites = std::nullopt;\r\n\r\n\tif (!gbRunGame) {\r\n\t\tplayer.PartyInfoSprites[0] = std::nullopt;\r\n\t\tplayer.PartyInfoSprites[1] = std::nullopt;\r\n\t}\r\n\r\n\tfor (PlayerAnimationData &animData : player.AnimationData) {\r\n\t\tanimData.sprites = std::nullopt;\r\n\t}\r\n}\r\n\r\nvoid NewPlrAnim(Player &player, player_graphic graphic, Direction dir, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int8_t numSkippedFrames /*= 0*/, int8_t distributeFramesBeforeFrame /*= 0*/)\r\n{\r\n\tLoadPlrGFX(player, graphic);\r\n\r\n\tOptionalClxSpriteList sprites;\r\n\tint previewShownGameTickFragments = 0;\r\n\tif (!HeadlessMode) {\r\n\t\tsprites = player.AnimationData[static_cast<size_t>(graphic)].spritesForDirection(dir);\r\n\t\tif (player.previewCelSprite && (*sprites)[0] == *player.previewCelSprite && !player.isWalking()) {\r\n\t\t\tpreviewShownGameTickFragments = std::clamp<int>(AnimationInfo::baseValueFraction - player.progressToNextGameTickWhenPreviewWasSet, 0, AnimationInfo::baseValueFraction);\r\n\t\t}\r\n\t}\r\n\r\n\tint8_t numberOfFrames;\r\n\tint8_t ticksPerFrame;\r\n\tplayer.getAnimationFramesAndTicksPerFrame(graphic, numberOfFrames, ticksPerFrame);\r\n\tplayer.AnimInfo.setNewAnimation(sprites, numberOfFrames, ticksPerFrame, flags, numSkippedFrames, distributeFramesBeforeFrame, static_cast<uint8_t>(previewShownGameTickFragments));\r\n}\r\n\r\nvoid SetPlrAnims(Player &player)\r\n{\r\n\tconst HeroClass pc = player._pClass;\r\n\tconst PlayerAnimData &plrAtkAnimData = GetPlayerAnimDataForClass(pc);\r\n\tauto gn = static_cast<PlayerWeaponGraphic>(player._pgfxnum & 0xFU);\r\n\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tplayer._pNFrames = plrAtkAnimData.townIdleFrames;\r\n\t\tplayer._pWFrames = plrAtkAnimData.townWalkingFrames;\r\n\t} else {\r\n\t\tplayer._pNFrames = plrAtkAnimData.idleFrames;\r\n\t\tplayer._pWFrames = plrAtkAnimData.walkingFrames;\r\n\t\tplayer._pHFrames = plrAtkAnimData.recoveryFrames;\r\n\t\tplayer._pBFrames = plrAtkAnimData.blockingFrames;\r\n\t\tswitch (gn) {\r\n\t\tcase PlayerWeaponGraphic::Unarmed:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.unarmedFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.unarmedActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::UnarmedShield:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.unarmedShieldFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.unarmedShieldActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::Sword:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.swordFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.swordActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::SwordShield:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.swordShieldFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.swordShieldActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::Bow:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.bowFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.bowActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::Axe:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.axeFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.axeActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::Mace:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.maceFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.maceActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::MaceShield:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.maceShieldFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.maceShieldActionFrame;\r\n\t\t\tbreak;\r\n\t\tcase PlayerWeaponGraphic::Staff:\r\n\t\t\tplayer._pAFrames = plrAtkAnimData.staffFrames;\r\n\t\t\tplayer._pAFNum = plrAtkAnimData.staffActionFrame;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tplayer._pDFrames = plrAtkAnimData.deathFrames;\r\n\tplayer._pSFrames = plrAtkAnimData.castingFrames;\r\n\tplayer._pSFNum = plrAtkAnimData.castingActionFrame;\r\n\tconst int armorGraphicIndex = player._pgfxnum & ~0xFU;\r\n\tif (IsAnyOf(pc, HeroClass::Warrior, HeroClass::Barbarian)) {\r\n\t\tif (gn == PlayerWeaponGraphic::Bow && leveltype != DTYPE_TOWN)\r\n\t\t\tplayer._pNFrames = 8;\r\n\t\tif (armorGraphicIndex > 0)\r\n\t\t\tplayer._pDFrames = 15;\r\n\t}\r\n}\r\n\r\n/**\r\n * @param player The player reference.\r\n * @param c The hero class.\r\n */\r\nvoid CreatePlayer(Player &player, HeroClass c)\r\n{\r\n\tplayer = {};\r\n\tSetRndSeed(SDL_GetTicks());\r\n\r\n\tplayer.setCharacterLevel(1);\r\n\tplayer._pClass = c;\r\n\r\n\tconst ClassAttributes &attr = player.getClassAttributes();\r\n\r\n\tplayer._pBaseStr = attr.baseStr;\r\n\tplayer._pStrength = player._pBaseStr;\r\n\r\n\tplayer._pBaseMag = attr.baseMag;\r\n\tplayer._pMagic = player._pBaseMag;\r\n\r\n\tplayer._pBaseDex = attr.baseDex;\r\n\tplayer._pDexterity = player._pBaseDex;\r\n\r\n\tplayer._pBaseVit = attr.baseVit;\r\n\tplayer._pVitality = player._pBaseVit;\r\n\r\n\tplayer._pHitPoints = player.calculateBaseLife();\r\n\tplayer._pMaxHP = player._pHitPoints;\r\n\tplayer._pHPBase = player._pHitPoints;\r\n\tplayer._pMaxHPBase = player._pHitPoints;\r\n\r\n\tplayer._pMana = player.calculateBaseMana();\r\n\tplayer._pMaxMana = player._pMana;\r\n\tplayer._pManaBase = player._pMana;\r\n\tplayer._pMaxManaBase = player._pMana;\r\n\r\n\tplayer._pExperience = 0;\r\n\tplayer._pArmorClass = 0;\r\n\tplayer._pLightRad = 10;\r\n\tplayer._pInfraFlag = false;\r\n\r\n\tfor (uint8_t &spellLevel : player._pSplLvl) {\r\n\t\tspellLevel = 0;\r\n\t}\r\n\r\n\tplayer._pSpellFlags = SpellFlag::None;\r\n\tplayer._pRSplType = SpellType::Invalid;\r\n\r\n\t// Initializing the hotkey bindings to no selection\r\n\tstd::fill(player._pSplHotKey, player._pSplHotKey + NumHotkeys, SpellID::Invalid);\r\n\r\n\t// CreatePlrItems calls AutoEquip which will overwrite the player graphic if required\r\n\tplayer._pgfxnum = static_cast<uint8_t>(PlayerWeaponGraphic::Unarmed);\r\n\r\n\tfor (bool &levelVisited : player._pLvlVisited) {\r\n\t\tlevelVisited = false;\r\n\t}\r\n\r\n\tfor (int i = 0; i < 10; i++) {\r\n\t\tplayer._pSLvlVisited[i] = false;\r\n\t}\r\n\r\n\tplayer._pLvlChanging = false;\r\n\tplayer.pTownWarps = 0;\r\n\tplayer.pLvlLoad = 0;\r\n\tplayer.pManaShield = false;\r\n\tplayer.pDamAcFlags = ItemSpecialEffectHf::None;\r\n\tplayer.wReflections = 0;\r\n\r\n\tInitDungMsgs(player);\r\n\tCreatePlrItems(player);\r\n\tSetRndSeed(0);\r\n}\r\n\r\nint CalcStatDiff(Player &player)\r\n{\r\n\tint diff = 0;\r\n\tfor (auto attribute : enum_values<CharacterAttribute>()) {\r\n\t\tdiff += player.GetMaximumAttributeValue(attribute);\r\n\t\tdiff -= player.GetBaseAttributeValue(attribute);\r\n\t}\r\n\treturn diff;\r\n}\r\n\r\nvoid NextPlrLevel(Player &player)\r\n{\r\n\tplayer.setCharacterLevel(player.getCharacterLevel() + 1);\r\n\r\n\tCalcPlrInv(player, true);\r\n\r\n\tif (CalcStatDiff(player) < 5) {\r\n\t\tplayer._pStatPts = CalcStatDiff(player);\r\n\t} else {\r\n\t\tplayer._pStatPts += 5;\r\n\t}\r\n\tconst int hp = player.getClassAttributes().lvlLife;\r\n\r\n\tplayer._pMaxHP += hp;\r\n\tplayer._pHitPoints = player._pMaxHP;\r\n\tplayer._pMaxHPBase += hp;\r\n\tplayer._pHPBase = player._pMaxHPBase;\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t}\r\n\r\n\tconst int mana = player.getClassAttributes().lvlMana;\r\n\r\n\tplayer._pMaxMana += mana;\r\n\tplayer._pMaxManaBase += mana;\r\n\r\n\tif (HasNoneOf(player._pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\tplayer._pMana = player._pMaxMana;\r\n\t\tplayer._pManaBase = player._pMaxManaBase;\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t}\r\n\r\n\tif (ControlMode != ControlTypes::KeyboardAndMouse)\r\n\t\tFocusOnCharInfo();\r\n\r\n\tCalcPlrInv(player, true);\r\n\tPlaySFX(SfxID::ItemArmor);\r\n\tPlaySFX(SfxID::ItemSign);\r\n}\r\n\r\nvoid Player::_addExperience(uint32_t experience, int levelDelta)\r\n{\r\n\tif (this != MyPlayer || hasNoLife())\r\n\t\treturn;\r\n\r\n\tif (isMaxCharacterLevel()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Adjust xp based on difference between the players current level and the target level (usually a monster level)\r\n\tuint32_t clampedExp = static_cast<uint32_t>(std::clamp<int64_t>(static_cast<int64_t>(experience * (1 + levelDelta / 10.0)), 0, std::numeric_limits<uint32_t>::max()));\r\n\r\n\t// Prevent power leveling\r\n\tif (gbIsMultiplayer) {\r\n\t\t// for low level characters experience gain is capped to 1/20 of current levels xp\r\n\t\t// for high level characters experience gain is capped to 200 * current level - this is a smaller value than 1/20 of the exp needed for the next level after level 5.\r\n\t\tclampedExp = std::min<uint32_t>({ clampedExp, /* level 1-5: */ getNextExperienceThreshold() / 20U, /* level 6-50: */ 200U * getCharacterLevel() });\r\n\t}\r\n\r\n\tlua::OnPlayerGainExperience(this, clampedExp);\r\n\r\n\tconst uint32_t maxExperience = GetNextExperienceThresholdForLevel(getMaxCharacterLevel());\r\n\r\n\t// ensure we only add enough experience to reach the max experience cap so we don't overflow\r\n\t_pExperience += std::min(clampedExp, maxExperience - _pExperience);\r\n\r\n\tif (*GetOptions().Gameplay.experienceBar) {\r\n\t\tRedrawEverything();\r\n\t}\r\n\r\n\t// Increase player level if applicable\r\n\twhile (!isMaxCharacterLevel() && _pExperience >= getNextExperienceThreshold()) {\r\n\t\t// NextPlrLevel increments character level which changes the next experience threshold\r\n\t\tNextPlrLevel(*this);\r\n\t}\r\n\r\n\tNetSendCmdParam1(false, CMD_PLRLEVEL, getCharacterLevel());\r\n}\r\n\r\nvoid AddPlrMonstExper(int lvl, unsigned exp, char pmask)\r\n{\r\n\tunsigned totplrs = 0;\r\n\tfor (size_t i = 0; i < Players.size(); i++) {\r\n\t\tif (((1 << i) & pmask) != 0) {\r\n\t\t\ttotplrs++;\r\n\t\t}\r\n\t}\r\n\r\n\tif (totplrs != 0) {\r\n\t\tconst unsigned e = exp / totplrs;\r\n\t\tif ((pmask & (1 << MyPlayerId)) != 0)\r\n\t\t\tMyPlayer->addExperience(e, lvl);\r\n\t}\r\n}\r\n\r\nvoid InitPlayer(Player &player, bool firstTime)\r\n{\r\n\tif (firstTime) {\r\n\t\tplayer._pRSplType = SpellType::Invalid;\r\n\t\tplayer._pRSpell = SpellID::Invalid;\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tLoadHotkeys();\r\n\t\tplayer._pSBkSpell = SpellID::Invalid;\r\n\t\tplayer.queuedSpell.spellId = player._pRSpell;\r\n\t\tplayer.queuedSpell.spellType = player._pRSplType;\r\n\t\tplayer.pManaShield = false;\r\n\t\tplayer.wReflections = 0;\r\n\t}\r\n\r\n\tplayer.lightId = NO_LIGHT;\r\n\r\n\tif (player.isOnActiveLevel()) {\r\n\r\n\t\tSetPlrAnims(player);\r\n\r\n\t\tClearStateVariables(player);\r\n\r\n\t\tif (!player.hasNoLife()) {\r\n\t\t\tplayer._pmode = PM_STAND;\r\n\t\t\tNewPlrAnim(player, player_graphic::Stand, Direction::South);\r\n\t\t\tplayer.AnimInfo.currentFrame = GenerateRnd(player._pNFrames - 1);\r\n\t\t\tplayer.AnimInfo.tickCounterOfCurrentFrame = GenerateRnd(3);\r\n\t\t} else {\r\n\t\t\tplayer._pgfxnum &= ~0xFU;\r\n\t\t\tplayer._pmode = PM_DEATH;\r\n\t\t\tNewPlrAnim(player, player_graphic::Death, Direction::South);\r\n\t\t\tplayer.AnimInfo.currentFrame = player.AnimInfo.numberOfFrames - 2;\r\n\t\t}\r\n\r\n\t\tplayer._pdir = Direction::South;\r\n\r\n\t\tif (&player == MyPlayer && (!firstTime || leveltype != DTYPE_TOWN)) {\r\n\t\t\tplayer.position.tile = ViewPosition;\r\n\t\t}\r\n\r\n\t\tSetPlayerOld(player);\r\n\t\tplayer.walkpath[0] = WALK_NONE;\r\n\t\tplayer.destAction = ACTION_NONE;\r\n\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tplayer.lightId = AddLight(player.position.tile, player._pLightRad);\r\n\t\t\tChangeLightXY(player.lightId, player.position.tile); // fix for a bug where old light is still visible at the entrance after reentering level\r\n\t\t}\r\n\t\tActivateVision(player.position.tile, player._pLightRad, player.getId());\r\n\t}\r\n\r\n\tplayer._pAblSpells = GetSpellBitmask(GetPlayerStartingLoadoutForClass(player._pClass).skill);\r\n\r\n\tplayer._pInvincible = false;\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tMyPlayerIsDead = false;\r\n\t}\r\n}\r\n\r\nvoid InitMultiView()\r\n{\r\n\tassert(MyPlayer != nullptr);\r\n\tViewPosition = MyPlayer->position.tile;\r\n}\r\n\r\nvoid PlrClrTrans(Point position)\r\n{\r\n\tfor (int i = position.y - 1; i <= position.y + 1; i++) {\r\n\t\tfor (int j = position.x - 1; j <= position.x + 1; j++) {\r\n\t\t\tTransList[dTransVal[j][i]] = false;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PlrDoTrans(Point position)\r\n{\r\n\tif (IsNoneOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CATACOMBS, DTYPE_CRYPT)) {\r\n\t\tTransList[1] = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (int i = position.y - 1; i <= position.y + 1; i++) {\r\n\t\tfor (int j = position.x - 1; j <= position.x + 1; j++) {\r\n\t\t\tif (IsTileNotSolid({ j, i }) && dTransVal[j][i] != 0) {\r\n\t\t\t\tTransList[dTransVal[j][i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SetPlayerOld(Player &player)\r\n{\r\n\tplayer.position.old = player.position.tile;\r\n}\r\n\r\nvoid FixPlayerLocation(Player &player, Direction bDir)\r\n{\r\n\tplayer.position.future = player.position.tile;\r\n\tplayer._pdir = bDir;\r\n\tif (&player == MyPlayer) {\r\n\t\tViewPosition = player.position.tile;\r\n\t}\r\n\tChangeLightXY(player.lightId, player.position.tile);\r\n\tChangeVisionXY(player.getId(), player.position.tile);\r\n}\r\n\r\nvoid StartStand(Player &player, Direction dir)\r\n{\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer) {\r\n\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\treturn;\r\n\t}\r\n\r\n\tNewPlrAnim(player, player_graphic::Stand, dir);\r\n\tplayer._pmode = PM_STAND;\r\n\tFixPlayerLocation(player, dir);\r\n\tFixPlrWalkTags(player);\r\n\tplayer.occupyTile(player.position.tile, false);\r\n\tSetPlayerOld(player);\r\n}\r\n\r\nvoid StartPlrBlock(Player &player, Direction dir)\r\n{\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer) {\r\n\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySfxLoc(SfxID::ItemSword, player.position.tile);\r\n\r\n\tint8_t skippedAnimationFrames = 0;\r\n\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastBlock)) {\r\n\t\tskippedAnimationFrames = (player._pBFrames - 2); // ISPL_FASTBLOCK means we cancel the animation if frame 2 was shown\r\n\t}\r\n\r\n\tNewPlrAnim(player, player_graphic::Block, dir, AnimationDistributionFlags::SkipsDelayOfLastFrame, skippedAnimationFrames);\r\n\r\n\tplayer._pmode = PM_BLOCK;\r\n\tFixPlayerLocation(player, dir);\r\n\tSetPlayerOld(player);\r\n}\r\n\r\n/**\r\n * @todo Figure out why clearing player.position.old sometimes fails\r\n */\r\nvoid FixPlrWalkTags(const Player &player)\r\n{\r\n\tfor (int y = 0; y < MAXDUNY; y++) {\r\n\t\tfor (int x = 0; x < MAXDUNX; x++) {\r\n\t\t\tif (PlayerAtPosition({ x, y }) == &player)\r\n\t\t\t\tdPlayer[x][y] = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid StartPlrHit(Player &player, int dam, bool forcehit)\r\n{\r\n\tif (player._pInvincible && player.hasNoLife() && &player == MyPlayer) {\r\n\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\treturn;\r\n\t}\r\n\r\n\tplayer.Say(HeroSpeech::ArghClang);\r\n\r\n\tRedrawComponent(PanelDrawComponent::Health);\r\n\tif (player._pClass == HeroClass::Barbarian) {\r\n\t\tif (dam >> 6 < player.getCharacterLevel() + player.getCharacterLevel() / 4 && !forcehit) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t} else if (dam >> 6 < player.getCharacterLevel() && !forcehit) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Direction pd = player._pdir;\r\n\r\n\tint8_t skippedAnimationFrames = 0;\r\n\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastestHitRecovery)) {\r\n\t\tskippedAnimationFrames = 3;\r\n\t} else if (HasAnyOf(player._pIFlags, ItemSpecialEffect::FasterHitRecovery)) {\r\n\t\tskippedAnimationFrames = 2;\r\n\t} else if (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastHitRecovery)) {\r\n\t\tskippedAnimationFrames = 1;\r\n\t} else {\r\n\t\tskippedAnimationFrames = 0;\r\n\t}\r\n\r\n\tNewPlrAnim(player, player_graphic::Hit, pd, AnimationDistributionFlags::None, skippedAnimationFrames);\r\n\r\n\tplayer._pmode = PM_GOTHIT;\r\n\tFixPlayerLocation(player, pd);\r\n\tFixPlrWalkTags(player);\r\n\tplayer.occupyTile(player.position.tile, false);\r\n\tSetPlayerOld(player);\r\n}\r\n\r\n#if defined(__clang__) || defined(__GNUC__)\r\n__attribute__((no_sanitize(\"shift-base\")))\r\n#endif\r\nvoid\r\nStartPlayerKill(Player &player, DeathReason deathReason)\r\n{\r\n\tif (player.hasNoLife() && player._pmode == PM_DEATH) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdParam1(true, CMD_PLRDEAD, static_cast<uint16_t>(deathReason));\r\n\t\tgamemenu_off();\r\n\t}\r\n\r\n\tconst bool dropGold = !gbIsMultiplayer || !(player.isOnLevel(16) || player.isOnArenaLevel());\r\n\tconst bool dropItems = dropGold && deathReason == DeathReason::MonsterOrTrap;\r\n\tconst bool dropEar = dropGold && deathReason == DeathReason::Player;\r\n\r\n\tplayer.Say(HeroSpeech::AuughUh);\r\n\r\n\t// Are the current animations item dependent?\r\n\tif (player._pgfxnum != 0) {\r\n\t\tif (dropItems) {\r\n\t\t\t// Ensure death animation show the player without weapon and armor, because they drop on death\r\n\t\t\tplayer._pgfxnum = 0;\r\n\t\t} else {\r\n\t\t\t// Death animation aren't weapon specific, so always use the unarmed animations\r\n\t\t\tplayer._pgfxnum &= ~0xFU;\r\n\t\t}\r\n\t\tResetPlayerGFX(player);\r\n\t\tSetPlrAnims(player);\r\n\t}\r\n\r\n\tNewPlrAnim(player, player_graphic::Death, player._pdir);\r\n\r\n\tplayer._pBlockFlag = false;\r\n\tplayer._pmode = PM_DEATH;\r\n\tplayer._pInvincible = true;\r\n\tSetPlayerHitPoints(player, 0);\r\n\r\n\tif (&player != MyPlayer && dropItems) {\r\n\t\t// Ensure that items are removed for remote players\r\n\t\t// The dropped items will be synced separately (by the remote client)\r\n\t\tfor (Item &item : player.InvBody) {\r\n\t\t\titem.clear();\r\n\t\t}\r\n\t\tCalcPlrInv(player, false);\r\n\t}\r\n\r\n\tif (player.isOnActiveLevel()) {\r\n\t\tFixPlayerLocation(player, player._pdir);\r\n\t\tFixPlrWalkTags(player);\r\n\t\tdFlags[player.position.tile.x][player.position.tile.y] |= DungeonFlag::DeadPlayer;\r\n\t\tSetPlayerOld(player);\r\n\r\n\t\t// Only generate drops once (for the local player)\r\n\t\t// For remote players we get separated sync messages (by the remote client)\r\n\t\tif (&player == MyPlayer) {\r\n\t\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\r\n\t\t\tif (!player.HoldItem.isEmpty()) {\r\n\t\t\t\tDeadItem(player, std::move(player.HoldItem), { 0, 0 });\r\n\t\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\t}\r\n\t\t\tif (dropGold) {\r\n\t\t\t\tDropHalfPlayersGold(player);\r\n\t\t\t}\r\n\t\t\tif (dropEar) {\r\n\t\t\t\tItem ear;\r\n\t\t\t\tInitializeItem(ear, IDI_EAR);\r\n\t\t\t\tCopyUtf8(ear._iName, fmt::format(fmt::runtime(\"Ear of {:s}\"), player._pName), sizeof(ear._iName));\r\n\t\t\t\tCopyUtf8(ear._iIName, player._pName, ItemNameLength);\r\n\t\t\t\tswitch (player._pClass) {\r\n\t\t\t\tcase HeroClass::Sorcerer:\r\n\t\t\t\t\tear._iCurs = ICURS_EAR_SORCERER;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Warrior:\r\n\t\t\t\t\tear._iCurs = ICURS_EAR_WARRIOR;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase HeroClass::Rogue:\r\n\t\t\t\tcase HeroClass::Monk:\r\n\t\t\t\tcase HeroClass::Bard:\r\n\t\t\t\tcase HeroClass::Barbarian:\r\n\t\t\t\t\tear._iCurs = ICURS_EAR_ROGUE;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tear._iCreateInfo = player._pName[0] << 8 | player._pName[1];\r\n\t\t\t\tear._iSeed = player._pName[2] << 24 | player._pName[3] << 16 | player._pName[4] << 8 | player._pName[5];\r\n\t\t\t\tear._ivalue = player.getCharacterLevel();\r\n\r\n\t\t\t\tif (FindGetItem(ear._iSeed, IDI_EAR, ear._iCreateInfo) == -1) {\r\n\t\t\t\t\tDeadItem(player, std::move(ear), { 0, 0 });\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (dropItems) {\r\n\t\t\t\tDirection pdd = player._pdir;\r\n\t\t\t\tfor (Item &item : player.InvBody) {\r\n\t\t\t\t\tpdd = Left(pdd);\r\n\t\t\t\t\tDeadItem(player, item.pop(), Displacement(pdd));\r\n\t\t\t\t}\r\n\r\n\t\t\t\tCalcPlrInv(player, false);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tSetPlayerHitPoints(player, 0);\r\n}\r\n\r\nvoid StripTopGold(Player &player)\r\n{\r\n\tfor (Item &item : InventoryPlayerItemsRange { player }) {\r\n\t\tif (item._itype != ItemType::Gold)\r\n\t\t\tcontinue;\r\n\t\tif (item._ivalue <= MaxGold)\r\n\t\t\tcontinue;\r\n\t\tItem excessGold;\r\n\t\tMakeGoldStack(excessGold, item._ivalue - MaxGold);\r\n\t\titem._ivalue = MaxGold;\r\n\r\n\t\tif (GoldAutoPlace(player, excessGold))\r\n\t\t\tcontinue;\r\n\t\tif (!player.HoldItem.isEmpty() && ActiveItemCount + 1 >= MAXITEMS)\r\n\t\t\tcontinue;\r\n\t\tDeadItem(player, std::move(excessGold), { 0, 0 });\r\n\t}\r\n\tplayer._pGold = CalculateGold(player);\r\n\r\n\tif (player.HoldItem.isEmpty())\r\n\t\treturn;\r\n\tif (AutoEquip(player, player.HoldItem, false))\r\n\t\treturn;\r\n\tif (CanFitItemInInventory(player, player.HoldItem))\r\n\t\treturn;\r\n\tif (AutoPlaceItemInBelt(player, player.HoldItem))\r\n\t\treturn;\r\n\tconst std::optional<Point> itemTile = FindAdjacentPositionForItem(player.position.tile, player._pdir);\r\n\tif (itemTile)\r\n\t\treturn;\r\n\tDeadItem(player, std::move(player.HoldItem), { 0, 0 });\r\n\tNewCursor(CURSOR_HAND);\r\n}\r\n\r\nvoid ApplyPlrDamage(DamageType damageType, Player &player, int dam, int minHP /*= 0*/, int frac /*= 0*/, DeathReason deathReason /*= DeathReason::MonsterOrTrap*/)\r\n{\r\n\tint totalDamage = (dam << 6) + frac;\r\n\tif (&player == MyPlayer && !player.hasNoLife()) {\r\n\t\tlua::OnPlayerTakeDamage(&player, totalDamage, static_cast<int>(damageType));\r\n\t}\r\n\tif (totalDamage > 0 && player.pManaShield && HasNoneOf(player._pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\tconst uint8_t manaShieldLevel = player._pSplLvl[static_cast<int8_t>(SpellID::ManaShield)];\r\n\t\tif (manaShieldLevel > 0) {\r\n\t\t\ttotalDamage += totalDamage / -player.GetManaShieldDamageReduction();\r\n\t\t}\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\tif (player._pMana >= totalDamage) {\r\n\t\t\tplayer._pMana -= totalDamage;\r\n\t\t\tplayer._pManaBase -= totalDamage;\r\n\t\t\ttotalDamage = 0;\r\n\t\t} else {\r\n\t\t\ttotalDamage -= player._pMana;\r\n\t\t\tif (manaShieldLevel > 0) {\r\n\t\t\t\ttotalDamage += totalDamage / (player.GetManaShieldDamageReduction() - 1);\r\n\t\t\t}\r\n\t\t\tplayer._pMana = 0;\r\n\t\t\tplayer._pManaBase = player._pMaxManaBase - player._pMaxMana;\r\n\t\t\tif (&player == MyPlayer)\r\n\t\t\t\tNetSendCmd(true, CMD_REMSHIELD);\r\n\t\t}\r\n\t}\r\n\r\n\tif (totalDamage == 0)\r\n\t\treturn;\r\n\r\n\tRedrawComponent(PanelDrawComponent::Health);\r\n\tplayer._pHitPoints -= totalDamage;\r\n\tplayer._pHPBase -= totalDamage;\r\n\tif (player._pHitPoints > player._pMaxHP) {\r\n\t\tplayer._pHitPoints = player._pMaxHP;\r\n\t\tplayer._pHPBase = player._pMaxHPBase;\r\n\t}\r\n\tconst int minHitPoints = minHP << 6;\r\n\tif (player._pHitPoints < minHitPoints) {\r\n\t\tSetPlayerHitPoints(player, minHitPoints);\r\n\t}\r\n\tif (player.hasNoLife()) {\r\n\t\tSyncPlrKill(player, deathReason);\r\n\t}\r\n}\r\n\r\nvoid SyncPlrKill(Player &player, DeathReason deathReason)\r\n{\r\n\tSetPlayerHitPoints(player, 0);\r\n\tStartPlayerKill(player, deathReason);\r\n}\r\n\r\nvoid RemovePlrMissiles(const Player &player)\r\n{\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tMonster *golem;\r\n\t\twhile ((golem = FindGolemForPlayer(player)) != nullptr) {\r\n\t\t\tKillGolem(*golem);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (auto &missile : Missiles) {\r\n\t\tif (missile._mitype == MissileID::StoneCurse && &Players[missile._misource] == &player) {\r\n\t\t\tMonsters[missile.var2].mode = static_cast<MonsterMode>(missile.var1);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#if defined(__clang__) || defined(__GNUC__)\r\n__attribute__((no_sanitize(\"shift-base\")))\r\n#endif\r\nvoid\r\nStartNewLvl(Player &player, interface_mode fom, int lvl)\r\n{\r\n\tInitLevelChange(player);\r\n\r\n\tswitch (fom) {\r\n\tcase WM_DIABNEXTLVL:\r\n\tcase WM_DIABPREVLVL:\r\n\tcase WM_DIABRTNLVL:\r\n\tcase WM_DIABTOWNWARP:\r\n\t\tplayer.setLevel(lvl);\r\n\t\tbreak;\r\n\tcase WM_DIABSETLVL:\r\n\t\tif (&player == MyPlayer)\r\n\t\t\tsetlvlnum = (_setlevels)lvl;\r\n\t\tplayer.setLevel(setlvlnum);\r\n\t\tbreak;\r\n\tcase WM_DIABTWARPUP:\r\n\t\tMyPlayer->pTownWarps |= 1 << (leveltype - 2);\r\n\t\tplayer.setLevel(lvl);\r\n\t\tbreak;\r\n\tcase WM_DIABRETOWN:\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(\"StartNewLvl\");\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tplayer._pmode = PM_NEWLVL;\r\n\t\tplayer._pInvincible = true;\r\n\t\tSDL_Event event;\r\n\t\tCustomEventToSdlEvent(event, fom);\r\n\t\tSDL_PushEvent(&event);\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tNetSendCmdParam2(true, CMD_NEWLVL, fom, lvl);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid RestartTownLvl(Player &player)\r\n{\r\n\tInitLevelChange(player);\r\n\r\n\tplayer.setLevel(0);\r\n\tplayer._pInvincible = false;\r\n\r\n\tSetPlayerHitPoints(player, 64);\r\n\r\n\tplayer._pMana = 0;\r\n\tplayer._pManaBase = player._pMana - (player._pMaxMana - player._pMaxManaBase);\r\n\r\n\tCalcPlrInv(player, false);\r\n\tplayer._pmode = PM_NEWLVL;\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tplayer._pInvincible = true;\r\n\t\tSDL_Event event;\r\n\t\tCustomEventToSdlEvent(event, WM_DIABRETOWN);\r\n\t\tSDL_PushEvent(&event);\r\n\t}\r\n}\r\n\r\nvoid StartWarpLvl(Player &player, size_t pidx)\r\n{\r\n\tInitLevelChange(player);\r\n\r\n\tif (gbIsMultiplayer) {\r\n\t\tif (!player.isOnLevel(0)) {\r\n\t\t\tplayer.setLevel(0);\r\n\t\t} else {\r\n\t\t\tif (Portals[pidx].setlvl)\r\n\t\t\t\tplayer.setLevel(static_cast<_setlevels>(Portals[pidx].level));\r\n\t\t\telse\r\n\t\t\t\tplayer.setLevel(Portals[pidx].level);\r\n\t\t}\r\n\t}\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tSetCurrentPortal(pidx);\r\n\t\tplayer._pmode = PM_NEWLVL;\r\n\t\tplayer._pInvincible = true;\r\n\t\tSDL_Event event;\r\n\t\tCustomEventToSdlEvent(event, WM_DIABWARPLVL);\r\n\t\tSDL_PushEvent(&event);\r\n\t}\r\n}\r\n\r\nvoid ProcessPlayers()\r\n{\r\n\tassert(MyPlayer != nullptr);\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer.pLvlLoad > 0) {\r\n\t\tmyPlayer.pLvlLoad--;\r\n\t}\r\n\r\n\tif (sfxdelay > 0) {\r\n\t\tsfxdelay--;\r\n\t\tif (sfxdelay == 0) {\r\n\t\t\tswitch (sfxdnum) {\r\n\t\t\tcase SfxID::Defiler1:\r\n\t\t\t\tInitQTextMsg(TEXT_DEFILER1);\r\n\t\t\t\tbreak;\r\n\t\t\tcase SfxID::Defiler2:\r\n\t\t\t\tInitQTextMsg(TEXT_DEFILER2);\r\n\t\t\t\tbreak;\r\n\t\t\tcase SfxID::Defiler3:\r\n\t\t\t\tInitQTextMsg(TEXT_DEFILER3);\r\n\t\t\t\tbreak;\r\n\t\t\tcase SfxID::Defiler4:\r\n\t\t\t\tInitQTextMsg(TEXT_DEFILER4);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tPlaySFX(sfxdnum);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tValidatePlayer();\r\n\r\n\tfor (size_t pnum = 0; pnum < Players.size(); pnum++) {\r\n\t\tPlayer &player = Players[pnum];\r\n\t\tif (player.plractive && player.isOnActiveLevel() && (&player == MyPlayer || !player._pLvlChanging)) {\r\n\t\t\tif (!PlrDeathModeOK(player) && player.hasNoLife()) {\r\n\t\t\t\tSyncPlrKill(player, DeathReason::Unknown);\r\n\t\t\t}\r\n\r\n\t\t\tif (&player == MyPlayer) {\r\n\t\t\t\tif (HasAnyOf(player._pIFlags, ItemSpecialEffect::DrainLife) && leveltype != DTYPE_TOWN) {\r\n\t\t\t\t\tApplyPlrDamage(DamageType::Physical, player, 0, 0, 4);\r\n\t\t\t\t}\r\n\t\t\t\tif (player.pManaShield && HasAnyOf(player._pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\t\t\t\tNetSendCmd(true, CMD_REMSHIELD);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tbool tplayer = false;\r\n\t\t\tdo {\r\n\t\t\t\tswitch (player._pmode) {\r\n\t\t\t\tcase PM_STAND:\r\n\t\t\t\tcase PM_NEWLVL:\r\n\t\t\t\tcase PM_QUIT:\r\n\t\t\t\t\ttplayer = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase PM_WALK_NORTHWARDS:\r\n\t\t\t\tcase PM_WALK_SOUTHWARDS:\r\n\t\t\t\tcase PM_WALK_SIDEWAYS:\r\n\t\t\t\t\ttplayer = DoWalk(player);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase PM_ATTACK:\r\n\t\t\t\t\ttplayer = DoAttack(player);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase PM_RATTACK:\r\n\t\t\t\t\ttplayer = DoRangeAttack(player);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase PM_BLOCK:\r\n\t\t\t\t\ttplayer = DoBlock(player);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase PM_SPELL:\r\n\t\t\t\t\ttplayer = DoSpell(player);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase PM_GOTHIT:\r\n\t\t\t\t\ttplayer = DoGotHit(player);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase PM_DEATH:\r\n\t\t\t\t\ttplayer = DoDeath(player);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tCheckNewPath(player, tplayer);\r\n\t\t\t} while (tplayer);\r\n\r\n\t\t\tplayer.previewCelSprite = std::nullopt;\r\n\t\t\tif (player._pmode != PM_DEATH || player.AnimInfo.tickCounterOfCurrentFrame != 40)\r\n\t\t\t\tplayer.AnimInfo.processAnimation();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ClrPlrPath(Player &player)\r\n{\r\n\tmemset(player.walkpath, WALK_NONE, sizeof(player.walkpath));\r\n}\r\n\r\n/**\r\n * @brief Determines if the target position is clear for the given player to stand on.\r\n *\r\n * This requires an ID instead of a Player& to compare with the dPlayer lookup table values.\r\n *\r\n * @param player The player to check.\r\n * @param position Dungeon tile coordinates.\r\n * @return False if something (other than the player themselves) is blocking the tile.\r\n */\r\nbool PosOkPlayer(const Player &player, Point position)\r\n{\r\n\tif (!InDungeonBounds(position))\r\n\t\treturn false;\r\n\tif (!IsTileWalkable(position))\r\n\t\treturn false;\r\n\tPlayer *otherPlayer = PlayerAtPosition(position);\r\n\tif (otherPlayer != nullptr && otherPlayer != &player && !otherPlayer->hasNoLife())\r\n\t\treturn false;\r\n\r\n\tif (dMonster[position.x][position.y] != 0) {\r\n\t\tif (leveltype == DTYPE_TOWN) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (dMonster[position.x][position.y] <= 0) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (!Monsters[dMonster[position.x][position.y] - 1].hasNoLife()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid MakePlrPath(Player &player, Point targetPosition, bool endspace)\r\n{\r\n\tif (player.position.future == targetPosition) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tint path = FindPath(CanStep, [&player](Point position) { return PosOkPlayer(player, position); }, player.position.future, targetPosition, player.walkpath, MaxPathLengthPlayer);\r\n\tif (path == 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!endspace) {\r\n\t\tpath--;\r\n\t}\r\n\r\n\tplayer.walkpath[path] = WALK_NONE;\r\n}\r\n\r\nvoid CheckPlrSpell(bool isShiftHeld, SpellID spellID, SpellType spellType)\r\n{\r\n\tbool addflag = false;\r\n\r\n\tassert(MyPlayer != nullptr);\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (!IsValidSpell(spellID)) {\r\n\t\tmyPlayer.Say(HeroSpeech::IDontHaveASpellReady);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (ControlMode == ControlTypes::KeyboardAndMouse) {\r\n\t\tif (pcurs != CURSOR_HAND)\r\n\t\t\treturn;\r\n\r\n\t\tif (GetMainPanel().contains(MousePosition)) // inside main panel\r\n\t\t\treturn;\r\n\r\n\t\tif (\r\n\t\t    (IsLeftPanelOpen() && GetLeftPanel().contains(MousePosition))      // inside left panel\r\n\t\t    || (IsRightPanelOpen() && GetRightPanel().contains(MousePosition)) // inside right panel\r\n\t\t) {\r\n\t\t\tif (spellID != SpellID::Healing\r\n\t\t\t    && spellID != SpellID::Identify\r\n\t\t\t    && spellID != SpellID::ItemRepair\r\n\t\t\t    && spellID != SpellID::Infravision\r\n\t\t\t    && spellID != SpellID::StaffRecharge)\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tif (leveltype == DTYPE_TOWN && !GetSpellData(spellID).isAllowedInTown()) {\r\n\t\tmyPlayer.Say(HeroSpeech::ICantCastThatHere);\r\n\t\treturn;\r\n\t}\r\n\r\n\tSpellCheckResult spellcheck = SpellCheckResult::Success;\r\n\tswitch (spellType) {\r\n\tcase SpellType::Skill:\r\n\tcase SpellType::Spell:\r\n\t\tspellcheck = CheckSpell(*MyPlayer, spellID, spellType, false);\r\n\t\taddflag = spellcheck == SpellCheckResult::Success;\r\n\t\tbreak;\r\n\tcase SpellType::Scroll:\r\n\t\taddflag = pcurs == CURSOR_HAND && CanUseScroll(myPlayer, spellID);\r\n\t\tbreak;\r\n\tcase SpellType::Charges:\r\n\t\taddflag = pcurs == CURSOR_HAND && CanUseStaff(myPlayer, spellID);\r\n\t\tbreak;\r\n\tcase SpellType::Invalid:\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!addflag) {\r\n\t\tif (spellType == SpellType::Spell) {\r\n\t\t\tswitch (spellcheck) {\r\n\t\t\tcase SpellCheckResult::Fail_NoMana:\r\n\t\t\t\tmyPlayer.Say(HeroSpeech::NotEnoughMana);\r\n\t\t\t\tbreak;\r\n\t\t\tcase SpellCheckResult::Fail_Level0:\r\n\t\t\t\tmyPlayer.Say(HeroSpeech::ICantCastThatYet);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tmyPlayer.Say(HeroSpeech::ICantDoThat);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tLastPlayerAction = PlayerActionType::None;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst int spellFrom = 0;\r\n\tif (IsWallSpell(spellID)) {\r\n\t\tLastPlayerAction = PlayerActionType::Spell;\r\n\t\tconst Direction sd = GetDirection(myPlayer.position.tile, cursPosition);\r\n\t\tNetSendCmdLocParam4(true, CMD_SPELLXYD, cursPosition, static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), static_cast<uint16_t>(sd), spellFrom);\r\n\t} else if (pcursmonst != -1 && !isShiftHeld) {\r\n\t\tLastPlayerAction = PlayerActionType::SpellMonsterTarget;\r\n\t\tNetSendCmdParam4(true, CMD_SPELLID, pcursmonst, static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), spellFrom);\r\n\t} else if (PlayerUnderCursor != nullptr && !PlayerUnderCursor->hasNoLife() && !isShiftHeld && !myPlayer.friendlyMode) {\r\n\t\tLastPlayerAction = PlayerActionType::SpellPlayerTarget;\r\n\t\tNetSendCmdParam4(true, CMD_SPELLPID, PlayerUnderCursor->getId(), static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), spellFrom);\r\n\t} else {\r\n\t\tPoint targetedTile = cursPosition;\r\n\t\tif (spellID == SpellID::Teleport && myPlayer.executedSpell.spellId == SpellID::Teleport) {\r\n\t\t\t// Check if the player is attempting to queue Teleport onto a tile that is currently being targeted with Teleport, or a nearby tile\r\n\t\t\tif (cursPosition.WalkingDistance(myPlayer.position.temp) <= 1) {\r\n\t\t\t\t// Get the relative displacement from the player's current position to the cursor position\r\n\t\t\t\tconst WorldTileDisplacement relativeMove = cursPosition - static_cast<Point>(myPlayer.position.tile);\r\n\t\t\t\t// Target the tile the relative distance away from the player's targeted Teleport tile\r\n\t\t\t\ttargetedTile = myPlayer.position.temp + relativeMove;\r\n\t\t\t}\r\n\t\t}\r\n\t\tLastPlayerAction = PlayerActionType::Spell;\r\n\t\tNetSendCmdLocParam3(true, CMD_SPELLXY, targetedTile, static_cast<int8_t>(spellID), static_cast<uint8_t>(spellType), spellFrom);\r\n\t}\r\n}\r\n\r\nvoid SyncPlrAnim(Player &player)\r\n{\r\n\tconst player_graphic graphic = player.getGraphic();\r\n\tif (!HeadlessMode)\r\n\t\tplayer.AnimInfo.sprites = player.AnimationData[static_cast<size_t>(graphic)].spritesForDirection(player._pdir);\r\n}\r\n\r\nvoid SyncInitPlrPos(Player &player)\r\n{\r\n\tif (!player.isOnActiveLevel())\r\n\t\treturn;\r\n\r\n\tconst WorldTileDisplacement offset[9] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 }, { 2, 0 }, { 0, 2 }, { 1, 2 }, { 2, 1 }, { 2, 2 } };\r\n\r\n\tconst Point position = [&]() {\r\n\t\tfor (int i = 0; i < 8; i++) {\r\n\t\t\tPoint position = player.position.tile + offset[i];\r\n\t\t\tif (PosOkPlayer(player, position))\r\n\t\t\t\treturn position;\r\n\t\t}\r\n\r\n\t\tconst std::optional<Point> nearPosition = FindClosestValidPosition(\r\n\t\t    [&player](Point testPosition) {\r\n\t\t\t    for (int i = 0; i < numtrigs; i++) {\r\n\t\t\t\t    if (trigs[i].position == testPosition)\r\n\t\t\t\t\t    return false;\r\n\t\t\t    }\r\n\t\t\t    return PosOkPlayer(player, testPosition) && !PosOkPortal(currlevel, testPosition);\r\n\t\t    },\r\n\t\t    player.position.tile,\r\n\t\t    1, // skip the starting tile since that was checked in the previous loop\r\n\t\t    50);\r\n\r\n\t\treturn nearPosition.value_or(Point { 0, 0 });\r\n\t}();\r\n\r\n\tplayer.position.tile = position;\r\n\tplayer.occupyTile(position, false);\r\n\tplayer.position.future = position;\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tViewPosition = position;\r\n\t}\r\n}\r\n\r\nvoid SyncInitPlr(Player &player)\r\n{\r\n\tSetPlrAnims(player);\r\n\tSyncInitPlrPos(player);\r\n\tif (&player != MyPlayer)\r\n\t\tplayer.lightId = NO_LIGHT;\r\n}\r\n\r\nvoid CheckStats(Player &player)\r\n{\r\n\tfor (auto attribute : enum_values<CharacterAttribute>()) {\r\n\t\tconst int maxStatPoint = player.GetMaximumAttributeValue(attribute);\r\n\t\tswitch (attribute) {\r\n\t\tcase CharacterAttribute::Strength:\r\n\t\t\tplayer._pBaseStr = std::clamp(player._pBaseStr, 0, maxStatPoint);\r\n\t\t\tbreak;\r\n\t\tcase CharacterAttribute::Magic:\r\n\t\t\tplayer._pBaseMag = std::clamp(player._pBaseMag, 0, maxStatPoint);\r\n\t\t\tbreak;\r\n\t\tcase CharacterAttribute::Dexterity:\r\n\t\t\tplayer._pBaseDex = std::clamp(player._pBaseDex, 0, maxStatPoint);\r\n\t\t\tbreak;\r\n\t\tcase CharacterAttribute::Vitality:\r\n\t\t\tplayer._pBaseVit = std::clamp(player._pBaseVit, 0, maxStatPoint);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ModifyPlrStr(Player &player, int l)\r\n{\r\n\tl = std::clamp(l, 0 - player._pBaseStr, player.GetMaximumAttributeValue(CharacterAttribute::Strength) - player._pBaseStr);\r\n\r\n\tplayer._pStrength += l;\r\n\tplayer._pBaseStr += l;\r\n\r\n\tCalcPlrInv(player, true);\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdParam1(false, CMD_SETSTR, player._pBaseStr);\r\n\t}\r\n}\r\n\r\nvoid ModifyPlrMag(Player &player, int l)\r\n{\r\n\tl = std::clamp(l, 0 - player._pBaseMag, player.GetMaximumAttributeValue(CharacterAttribute::Magic) - player._pBaseMag);\r\n\r\n\tplayer._pMagic += l;\r\n\tplayer._pBaseMag += l;\r\n\r\n\tint ms = l;\r\n\tms *= player.getClassAttributes().chrMana;\r\n\r\n\tplayer._pMaxManaBase += ms;\r\n\tplayer._pMaxMana += ms;\r\n\tif (HasNoneOf(player._pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\tplayer._pManaBase += ms;\r\n\t\tplayer._pMana += ms;\r\n\t}\r\n\r\n\tCalcPlrInv(player, true);\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdParam1(false, CMD_SETMAG, player._pBaseMag);\r\n\t}\r\n}\r\n\r\nvoid ModifyPlrDex(Player &player, int l)\r\n{\r\n\tl = std::clamp(l, 0 - player._pBaseDex, player.GetMaximumAttributeValue(CharacterAttribute::Dexterity) - player._pBaseDex);\r\n\r\n\tplayer._pDexterity += l;\r\n\tplayer._pBaseDex += l;\r\n\tCalcPlrInv(player, true);\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdParam1(false, CMD_SETDEX, player._pBaseDex);\r\n\t}\r\n}\r\n\r\nvoid ModifyPlrVit(Player &player, int l)\r\n{\r\n\tl = std::clamp(l, 0 - player._pBaseVit, player.GetMaximumAttributeValue(CharacterAttribute::Vitality) - player._pBaseVit);\r\n\r\n\tplayer._pVitality += l;\r\n\tplayer._pBaseVit += l;\r\n\r\n\tint ms = l;\r\n\tms *= player.getClassAttributes().chrLife;\r\n\r\n\tplayer._pHPBase += ms;\r\n\tplayer._pMaxHPBase += ms;\r\n\tplayer._pHitPoints += ms;\r\n\tplayer._pMaxHP += ms;\r\n\r\n\tCalcPlrInv(player, true);\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tNetSendCmdParam1(false, CMD_SETVIT, player._pBaseVit);\r\n\t}\r\n}\r\n\r\nvoid SetPlayerHitPoints(Player &player, int val)\r\n{\r\n\tplayer._pHitPoints = val;\r\n\tplayer._pHPBase = val + player._pMaxHPBase - player._pMaxHP;\r\n\r\n\tif (&player == MyPlayer) {\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t}\r\n}\r\n\r\nvoid SetPlrStr(Player &player, int v)\r\n{\r\n\tplayer._pBaseStr = v;\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid SetPlrMag(Player &player, int v)\r\n{\r\n\tplayer._pBaseMag = v;\r\n\r\n\tint m = v;\r\n\tm *= player.getClassAttributes().chrMana;\r\n\r\n\tplayer._pMaxManaBase = m;\r\n\tplayer._pMaxMana = m;\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid SetPlrDex(Player &player, int v)\r\n{\r\n\tplayer._pBaseDex = v;\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid SetPlrVit(Player &player, int v)\r\n{\r\n\tplayer._pBaseVit = v;\r\n\r\n\tint hp = v;\r\n\thp *= player.getClassAttributes().chrLife;\r\n\r\n\tplayer._pHPBase = hp;\r\n\tplayer._pMaxHPBase = hp;\r\n\tCalcPlrInv(player, true);\r\n}\r\n\r\nvoid InitDungMsgs(Player &player)\r\n{\r\n\tplayer.pDungMsgs = 0;\r\n\tplayer.pDungMsgs2 = 0;\r\n}\r\n\r\nenum {\r\n\t// clang-format off\r\n\tDungMsgCathedral = 1 << 0,\r\n\tDungMsgCatacombs = 1 << 1,\r\n\tDungMsgCaves     = 1 << 2,\r\n\tDungMsgHell      = 1 << 3,\r\n\tDungMsgDiablo    = 1 << 4,\r\n\t// clang-format on\r\n};\r\n\r\nvoid PlayDungMsgs()\r\n{\r\n\tassert(MyPlayer != nullptr);\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (!setlevel && currlevel == 1 && !myPlayer._pLvlVisited[1] && (myPlayer.pDungMsgs & DungMsgCathedral) == 0) {\r\n\t\tmyPlayer.Say(HeroSpeech::TheSanctityOfThisPlaceHasBeenFouled, 40);\r\n\t\tmyPlayer.pDungMsgs = myPlayer.pDungMsgs | DungMsgCathedral;\r\n\t} else if (!setlevel && currlevel == 5 && !myPlayer._pLvlVisited[5] && (myPlayer.pDungMsgs & DungMsgCatacombs) == 0) {\r\n\t\tmyPlayer.Say(HeroSpeech::TheSmellOfDeathSurroundsMe, 40);\r\n\t\tmyPlayer.pDungMsgs |= DungMsgCatacombs;\r\n\t} else if (!setlevel && currlevel == 9 && !myPlayer._pLvlVisited[9] && (myPlayer.pDungMsgs & DungMsgCaves) == 0) {\r\n\t\tmyPlayer.Say(HeroSpeech::ItsHotDownHere, 40);\r\n\t\tmyPlayer.pDungMsgs |= DungMsgCaves;\r\n\t} else if (!setlevel && currlevel == 13 && !myPlayer._pLvlVisited[13] && (myPlayer.pDungMsgs & DungMsgHell) == 0) {\r\n\t\tmyPlayer.Say(HeroSpeech::IMustBeGettingClose, 40);\r\n\t\tmyPlayer.pDungMsgs |= DungMsgHell;\r\n\t} else if (!setlevel && currlevel == 16 && !myPlayer._pLvlVisited[16] && (myPlayer.pDungMsgs & DungMsgDiablo) == 0) {\r\n\t\tfor (auto &monster : Monsters) {\r\n\t\t\tif (monster.type().type != MT_DIABLO) continue;\r\n\t\t\tif (monster.hitPoints > 0) {\r\n\t\t\t\tsfxdelay = 40;\r\n\t\t\t\tsfxdnum = SfxID::DiabloGreeting;\r\n\t\t\t\tmyPlayer.pDungMsgs |= DungMsgDiablo;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t} else if (!setlevel && currlevel == 17 && !myPlayer._pLvlVisited[17] && (myPlayer.pDungMsgs2 & 1) == 0) {\r\n\t\tsfxdelay = 10;\r\n\t\tsfxdnum = SfxID::Defiler1;\r\n\t\tQuests[Q_DEFILER]._qactive = QUEST_ACTIVE;\r\n\t\tQuests[Q_DEFILER]._qlog = true;\r\n\t\tQuests[Q_DEFILER]._qmsg = TEXT_DEFILER1;\r\n\t\tNetSendCmdQuest(true, Quests[Q_DEFILER]);\r\n\t\tmyPlayer.pDungMsgs2 |= 1;\r\n\t} else if (!setlevel && currlevel == 19 && !myPlayer._pLvlVisited[19] && (myPlayer.pDungMsgs2 & 4) == 0) {\r\n\t\tsfxdelay = 10;\r\n\t\tsfxdnum = SfxID::Defiler3;\r\n\t\tmyPlayer.pDungMsgs2 |= 4;\r\n\t} else if (!setlevel && currlevel == 21 && !myPlayer._pLvlVisited[21] && (myPlayer.pDungMsgs & 32) == 0) {\r\n\t\tmyPlayer.Say(HeroSpeech::ThisIsAPlaceOfGreatPower, 30);\r\n\t\tmyPlayer.pDungMsgs |= 32;\r\n\t} else if (setlevel && setlvlnum == SL_SKELKING && !gbIsSpawn && !myPlayer._pSLvlVisited[SL_SKELKING] && Quests[Q_SKELKING]._qactive == QUEST_ACTIVE) {\r\n\t\tsfxdelay = 10;\r\n\t\tsfxdnum = SfxID::LeoricGreeting;\r\n\t} else {\r\n\t\tsfxdelay = 0;\r\n\t}\r\n}\r\n\r\n#ifdef BUILD_TESTING\r\nbool TestPlayerDoGotHit(Player &player)\r\n{\r\n\treturn DoGotHit(player);\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/player.h",
    "content": "/**\r\n * @file player.h\r\n *\r\n * Interface of player functionality, leveling, actions, creation, loading, etc.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <vector>\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <string_view>\r\n\r\n#include \"diablo.h\"\r\n#include \"engine/actor_position.hpp\"\r\n#include \"engine/animationinfo.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/path.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"interfac.h\"\r\n#include \"items.h\"\r\n#include \"items/validation.h\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"multi.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/enum_traits.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr int InventoryGridCells = 40;\r\nconstexpr int MaxBeltItems = 8;\r\nconstexpr int MaxResistance = 75;\r\nconstexpr uint8_t MaxSpellLevel = 15;\r\nconstexpr int PlayerNameLength = 32;\r\n\r\nconstexpr size_t NumHotkeys = 12;\r\n\r\n/** Walking directions */\r\nenum {\r\n\t// clang-format off\r\n\tWALK_NE   =  1,\r\n\tWALK_NW   =  2,\r\n\tWALK_SE   =  3,\r\n\tWALK_SW   =  4,\r\n\tWALK_N    =  5,\r\n\tWALK_E    =  6,\r\n\tWALK_S    =  7,\r\n\tWALK_W    =  8,\r\n\tWALK_NONE = -1,\r\n\t// clang-format on\r\n};\r\n\r\nenum class CharacterAttribute : uint8_t {\r\n\tStrength,\r\n\tMagic,\r\n\tDexterity,\r\n\tVitality,\r\n\r\n\tFIRST = Strength,\r\n\tLAST = Vitality\r\n};\r\n\r\n// Logical equipment locations\r\nenum inv_body_loc : uint8_t {\r\n\tINVLOC_HEAD,\r\n\tINVLOC_RING_LEFT,\r\n\tINVLOC_RING_RIGHT,\r\n\tINVLOC_AMULET,\r\n\tINVLOC_HAND_LEFT,\r\n\tINVLOC_HAND_RIGHT,\r\n\tINVLOC_CHEST,\r\n\tNUM_INVLOC,\r\n};\r\n\r\nenum class player_graphic : uint8_t {\r\n\tStand,\r\n\tWalk,\r\n\tAttack,\r\n\tHit,\r\n\tLightning,\r\n\tFire,\r\n\tMagic,\r\n\tDeath,\r\n\tBlock,\r\n\r\n\tLAST = Block\r\n};\r\n\r\nenum class PlayerWeaponGraphic : uint8_t {\r\n\tUnarmed,\r\n\tUnarmedShield,\r\n\tSword,\r\n\tSwordShield,\r\n\tBow,\r\n\tAxe,\r\n\tMace,\r\n\tMaceShield,\r\n\tStaff,\r\n};\r\n\r\nenum PLR_MODE : uint8_t {\r\n\tPM_STAND,\r\n\tPM_WALK_NORTHWARDS,\r\n\tPM_WALK_SOUTHWARDS,\r\n\tPM_WALK_SIDEWAYS,\r\n\tPM_ATTACK,\r\n\tPM_RATTACK,\r\n\tPM_BLOCK,\r\n\tPM_GOTHIT,\r\n\tPM_DEATH,\r\n\tPM_SPELL,\r\n\tPM_NEWLVL,\r\n\tPM_QUIT,\r\n};\r\n\r\nenum action_id : int8_t {\r\n\t// clang-format off\r\n\tACTION_WALK        = -2, // Automatic walk when using gamepad\r\n\tACTION_NONE        = -1,\r\n\tACTION_ATTACK      = 9,\r\n\tACTION_RATTACK     = 10,\r\n\tACTION_SPELL       = 12,\r\n\tACTION_OPERATE     = 13,\r\n\tACTION_DISARM      = 14,\r\n\tACTION_PICKUPITEM  = 15, // put item in hand (inventory screen open)\r\n\tACTION_PICKUPAITEM = 16, // put item in inventory\r\n\tACTION_TALK        = 17,\r\n\tACTION_OPERATETK   = 18, // operate via telekinesis\r\n\tACTION_ATTACKMON   = 20,\r\n\tACTION_ATTACKPLR   = 21,\r\n\tACTION_RATTACKMON  = 22,\r\n\tACTION_RATTACKPLR  = 23,\r\n\tACTION_SPELLMON    = 24,\r\n\tACTION_SPELLPLR    = 25,\r\n\tACTION_SPELLWALL   = 26,\r\n\t// clang-format on\r\n};\r\n\r\nenum class SpellFlag : uint8_t {\r\n\t// clang-format off\r\n\tNone         = 0,\r\n\tEtherealize  = 1 << 0,\r\n\tRageActive   = 1 << 1,\r\n\tRageCooldown = 1 << 2,\r\n\t// bits 3-7 are unused\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(SpellFlag);\r\n\r\n/* @brief When the player dies, what is the reason/source why? */\r\nenum class DeathReason {\r\n\t/* @brief Monster or Trap (dungeon) */\r\n\tMonsterOrTrap,\r\n\t/* @brief Other player or selfkill (for example firewall) */\r\n\tPlayer,\r\n\t/* @brief HP is zero but we don't know when or where this happened */\r\n\tUnknown,\r\n};\r\n\r\n/** Maps from armor animation to letter used in graphic files. */\r\nconstexpr std::array<char, 3> ArmourChar = {\r\n\t'l', // light\r\n\t'm', // medium\r\n\t'h', // heavy\r\n};\r\n/** Maps from weapon animation to letter used in graphic files. */\r\nconstexpr std::array<char, 9> WepChar = {\r\n\t'n', // unarmed\r\n\t'u', // no weapon + shield\r\n\t's', // sword + no shield\r\n\t'd', // sword + shield\r\n\t'b', // bow\r\n\t'a', // axe\r\n\t'm', // blunt + no shield\r\n\t'h', // blunt + shield\r\n\t't', // staff\r\n};\r\n\r\n/**\r\n * @brief Contains Data (CelSprites) for a player graphic (player_graphic)\r\n */\r\nstruct PlayerAnimationData {\r\n\t/**\r\n\t * @brief Sprite lists for each of the 8 directions.\r\n\t */\r\n\tOptionalOwnedClxSpriteSheet sprites;\r\n\r\n\t[[nodiscard]] ClxSpriteList spritesForDirection(Direction direction) const\r\n\t{\r\n\t\treturn (*sprites)[static_cast<size_t>(direction)];\r\n\t}\r\n};\r\n\r\nstruct SpellCastInfo {\r\n\tSpellID spellId;\r\n\tSpellType spellType;\r\n\t/* @brief Inventory location for scrolls */\r\n\tint8_t spellFrom;\r\n\t/* @brief Used for spell level */\r\n\tint spellLevel;\r\n};\r\n\r\nstruct Player {\r\n\tPlayer() = default;\r\n\tPlayer(Player &&) noexcept = default;\r\n\tPlayer &operator=(Player &&) noexcept = default;\r\n\r\n\tchar _pName[PlayerNameLength];\r\n\tItem InvBody[NUM_INVLOC];\r\n\tItem InvList[InventoryGridCells];\r\n\tItem SpdList[MaxBeltItems];\r\n\tItem HoldItem;\r\n\r\n\tint lightId;\r\n\r\n\tint _pNumInv;\r\n\tint _pStrength;\r\n\tint _pBaseStr;\r\n\tint _pMagic;\r\n\tint _pBaseMag;\r\n\tint _pDexterity;\r\n\tint _pBaseDex;\r\n\tint _pVitality;\r\n\tint _pBaseVit;\r\n\tint _pStatPts;\r\n\tint _pDamageMod;\r\n\tint _pHPBase;\r\n\tint _pMaxHPBase;\r\n\tint _pHitPoints;\r\n\tint _pMaxHP;\r\n\tint _pHPPer;\r\n\tint _pManaBase;\r\n\tint _pMaxManaBase;\r\n\tint _pMana;\r\n\tint _pMaxMana;\r\n\tint _pManaPer;\r\n\tint _pIMinDam;\r\n\tint _pIMaxDam;\r\n\tint _pIAC;\r\n\tint _pIBonusDam;\r\n\tint _pIBonusToHit;\r\n\tint _pIBonusAC;\r\n\tint _pIBonusDamMod;\r\n\tint _pIGetHit;\r\n\tint _pIEnAc;\r\n\tint _pIFMinDam;\r\n\tint _pIFMaxDam;\r\n\tint _pILMinDam;\r\n\tint _pILMaxDam;\r\n\tuint32_t _pExperience;\r\n\tPLR_MODE _pmode;\r\n\tint8_t walkpath[MaxPathLengthPlayer];\r\n\tbool plractive;\r\n\taction_id destAction;\r\n\tint destParam1;\r\n\tint destParam2;\r\n\tint destParam3;\r\n\tint destParam4;\r\n\tint _pGold;\r\n\r\n\t/**\r\n\t * @brief Contains Information for current Animation\r\n\t */\r\n\tAnimationInfo AnimInfo;\r\n\t/**\r\n\t * @brief Contains a optional preview ClxSprite that is displayed until the current command is handled by the game logic\r\n\t */\r\n\tOptionalClxSprite previewCelSprite;\r\n\t/**\r\n\t * @brief Contains the progress to next game tick when previewCelSprite was set\r\n\t */\r\n\tint8_t progressToNextGameTickWhenPreviewWasSet;\r\n\t/** @brief Bitmask using item_special_effect */\r\n\tItemSpecialEffect _pIFlags;\r\n\t/**\r\n\t * @brief Contains Data (Sprites) for the different Animations\r\n\t */\r\n\tstd::array<PlayerAnimationData, enum_size<player_graphic>::value> AnimationData;\r\n\tstd::array<OptionalOwnedClxSpriteSheet, 2> PartyInfoSprites;\r\n\tstd::array<std::string, 2> PartyInfoSpriteLocations;\r\n\tint8_t _pNFrames;\r\n\tint8_t _pWFrames;\r\n\tint8_t _pAFrames;\r\n\tint8_t _pAFNum;\r\n\tint8_t _pSFrames;\r\n\tint8_t _pSFNum;\r\n\tint8_t _pHFrames;\r\n\tint8_t _pDFrames;\r\n\tint8_t _pBFrames;\r\n\tint8_t InvGrid[InventoryGridCells];\r\n\r\n\tuint8_t plrlevel;\r\n\tbool plrIsOnSetLevel;\r\n\tActorPosition position;\r\n\tDirection _pdir; // Direction faced by player (direction enum)\r\n\tHeroClass _pClass;\r\n\r\nprivate:\r\n\tuint8_t _pLevel = 1; // Use get/setCharacterLevel to ensure this attribute stays within the accepted range\r\n\r\npublic:\r\n\tuint8_t _pgfxnum; // Bitmask indicating what variant of the sprite the player is using. The 3 lower bits define weapon (PlayerWeaponGraphic) and the higher bits define armour (starting with PlayerArmorGraphic)\r\n\tint8_t _pISplLvlAdd;\r\n\t/** @brief Specifies whether players are in non-PvP mode. */\r\n\tbool friendlyMode = true;\r\n\r\n\t/** @brief The next queued spell */\r\n\tSpellCastInfo queuedSpell;\r\n\t/** @brief The spell that is currently being cast */\r\n\tSpellCastInfo executedSpell;\r\n\t/* @brief Which spell should be executed with CURSOR_TELEPORT */\r\n\tSpellID inventorySpell;\r\n\t/* @brief Inventory location for scrolls with CURSOR_TELEPORT */\r\n\tint8_t spellFrom;\r\n\tSpellID _pRSpell;\r\n\tSpellType _pRSplType;\r\n\tSpellID _pSBkSpell;\r\n\tuint8_t _pSplLvl[64];\r\n\t/** @brief Bitmask of staff spell */\r\n\tuint64_t _pISpells;\r\n\t/** @brief Bitmask of learned spells */\r\n\tuint64_t _pMemSpells;\r\n\t/** @brief Bitmask of abilities */\r\n\tuint64_t _pAblSpells;\r\n\t/** @brief Bitmask of spells available via scrolls */\r\n\tuint64_t _pScrlSpells;\r\n\tSpellFlag _pSpellFlags;\r\n\tSpellID _pSplHotKey[NumHotkeys];\r\n\tSpellType _pSplTHotKey[NumHotkeys];\r\n\tbool _pBlockFlag;\r\n\tbool _pInvincible;\r\n\tint8_t _pLightRad;\r\n\t/** @brief True when the player is transitioning between levels */\r\n\tbool _pLvlChanging;\r\n\r\n\tint8_t _pArmorClass;\r\n\tint8_t _pMagResist;\r\n\tint8_t _pFireResist;\r\n\tint8_t _pLghtResist;\r\n\tbool _pInfraFlag;\r\n\t/** Player's direction when ending movement. Also used for casting direction of SpellID::FireWall. */\r\n\tDirection tempDirection;\r\n\r\n\tbool _pLvlVisited[NUMLEVELS];\r\n\tbool _pSLvlVisited[NUMLEVELS]; // only 10 used\r\n\r\n\titem_misc_id _pOilType;\r\n\tuint8_t pTownWarps;\r\n\tuint8_t pDungMsgs;\r\n\tuint8_t pLvlLoad;\r\n\tbool pManaShield;\r\n\tuint8_t pDungMsgs2;\r\n\tbool pOriginalCathedral;\r\n\tuint8_t pDiabloKillLevel;\r\n\tuint16_t wReflections;\r\n\tItemSpecialEffectHf pDamAcFlags;\r\n\r\n\t[[nodiscard]] std::string_view name() const\r\n\t{\r\n\t\treturn _pName;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Convenience function to get the base stats/bonuses for this player's class\r\n\t */\r\n\t[[nodiscard]] const ClassAttributes &getClassAttributes() const\r\n\t{\r\n\t\treturn GetClassAttributes(_pClass);\r\n\t}\r\n\r\n\t[[nodiscard]] const PlayerCombatData &getPlayerCombatData() const\r\n\t{\r\n\t\treturn GetPlayerCombatDataForClass(_pClass);\r\n\t}\r\n\r\n\t[[nodiscard]] const PlayerData &getPlayerData() const\r\n\t{\r\n\t\treturn GetPlayerDataForClass(_pClass);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Gets the translated name for the character's class\r\n\t */\r\n\t[[nodiscard]] std::string_view getClassName() const\r\n\t{\r\n\t\treturn _(getPlayerData().className);\r\n\t}\r\n\r\n\t[[nodiscard]] int getBaseToBlock() const\r\n\t{\r\n\t\treturn getPlayerCombatData().baseToBlock;\r\n\t}\r\n\r\n\tvoid CalcScrolls();\r\n\r\n\tbool CanUseItem(const Item &item) const;\r\n\r\n\tbool CanCleave()\r\n\t{\r\n\t\tswitch (_pClass) {\r\n\t\tcase HeroClass::Warrior:\r\n\t\tcase HeroClass::Rogue:\r\n\t\tcase HeroClass::Sorcerer:\r\n\t\t\treturn false;\r\n\t\tcase HeroClass::Monk:\r\n\t\t\treturn isEquipped(ItemType::Staff);\r\n\t\tcase HeroClass::Bard:\r\n\t\t\treturn InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Sword && InvBody[INVLOC_HAND_RIGHT]._itype == ItemType::Sword;\r\n\t\tcase HeroClass::Barbarian:\r\n\t\t\treturn isEquipped(ItemType::Axe) || (!isEquipped(ItemType::Shield) && (isEquipped(ItemType::Mace, true) || isEquipped(ItemType::Sword, true)));\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tbool isEquipped(ItemType itemType, bool isTwoHanded = false)\r\n\t{\r\n\t\tswitch (itemType) {\r\n\t\tcase ItemType::Sword:\r\n\t\tcase ItemType::Axe:\r\n\t\tcase ItemType::Bow:\r\n\t\tcase ItemType::Mace:\r\n\t\tcase ItemType::Shield:\r\n\t\tcase ItemType::Staff:\r\n\t\t\treturn (InvBody[INVLOC_HAND_LEFT]._itype == itemType && (!isTwoHanded || InvBody[INVLOC_HAND_LEFT]._iLoc == ILOC_TWOHAND))\r\n\t\t\t    || (InvBody[INVLOC_HAND_RIGHT]._itype == itemType && (!isTwoHanded || InvBody[INVLOC_HAND_LEFT]._iLoc == ILOC_TWOHAND));\r\n\t\tcase ItemType::LightArmor:\r\n\t\tcase ItemType::MediumArmor:\r\n\t\tcase ItemType::HeavyArmor:\r\n\t\t\treturn InvBody[INVLOC_CHEST]._itype == itemType;\r\n\t\tcase ItemType::Helm:\r\n\t\t\treturn InvBody[INVLOC_HEAD]._itype == itemType;\r\n\t\tcase ItemType::Ring:\r\n\t\t\treturn InvBody[INVLOC_RING_LEFT]._itype == itemType || InvBody[INVLOC_RING_RIGHT]._itype == itemType;\r\n\t\tcase ItemType::Amulet:\r\n\t\t\treturn InvBody[INVLOC_AMULET]._itype == itemType;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Remove an item from player inventory\r\n\t * @param iv invList index of item to be removed\r\n\t * @param calcScrolls If true, CalcScrolls() gets called after removing item\r\n\t */\r\n\tvoid RemoveInvItem(int iv, bool calcScrolls = true);\r\n\r\n\t/**\r\n\t * @brief Returns the network identifier for this player\r\n\t */\r\n\t[[nodiscard]] uint8_t getId() const;\r\n\r\n\tvoid RemoveSpdBarItem(int iv);\r\n\r\n\t/**\r\n\t * @brief Gets the most valuable item out of all the player's items that match the given predicate.\r\n\t * @param itemPredicate The predicate used to match the items.\r\n\t * @return The most valuable item out of all the player's items that match the given predicate, or 'nullptr' in case no\r\n\t * matching items were found.\r\n\t */\r\n\ttemplate <typename TPredicate>\r\n\tconst Item *GetMostValuableItem(const TPredicate &itemPredicate) const\r\n\t{\r\n\t\tconst auto getMostValuableItem = [&itemPredicate](const Item *begin, const Item *end, const Item *mostValuableItem = nullptr) {\r\n\t\t\tfor (const auto *item = begin; item < end; item++) {\r\n\t\t\t\tif (item->isEmpty() || !itemPredicate(*item)) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (mostValuableItem == nullptr || item->_iIvalue > mostValuableItem->_iIvalue) {\r\n\t\t\t\t\tmostValuableItem = item;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn mostValuableItem;\r\n\t\t};\r\n\r\n\t\tconst Item *mostValuableItem = getMostValuableItem(SpdList, SpdList + MaxBeltItems);\r\n\t\tmostValuableItem = getMostValuableItem(InvBody, InvBody + inv_body_loc::NUM_INVLOC, mostValuableItem);\r\n\t\tmostValuableItem = getMostValuableItem(InvList, InvList + _pNumInv, mostValuableItem);\r\n\r\n\t\treturn mostValuableItem;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Gets the base value of the player's specified attribute.\r\n\t * @param attribute The attribute to retrieve the base value for\r\n\t * @return The base value for the requested attribute.\r\n\t */\r\n\tint GetBaseAttributeValue(CharacterAttribute attribute) const;\r\n\r\n\t/**\r\n\t * @brief Gets the current value of the player's specified attribute.\r\n\t * @param attribute The attribute to retrieve the current value for\r\n\t * @return The current value for the requested attribute.\r\n\t */\r\n\tint GetCurrentAttributeValue(CharacterAttribute attribute) const;\r\n\r\n\t/**\r\n\t * @brief Gets the maximum value of the player's specified attribute.\r\n\t * @param attribute The attribute to retrieve the maximum value for\r\n\t * @return The maximum value for the requested attribute.\r\n\t */\r\n\tint GetMaximumAttributeValue(CharacterAttribute attribute) const;\r\n\r\n\t/**\r\n\t * @brief Get the tile coordinates a player is moving to (if not moving, then it corresponds to current position).\r\n\t */\r\n\tPoint GetTargetPosition() const;\r\n\r\n\t/**\r\n\t * @brief Returns the index of the given position in `walkpath`, or -1 if not found.\r\n\t */\r\n\tint GetPositionPathIndex(Point position);\r\n\r\n\t/**\r\n\t * @brief Says a speech line.\r\n\t * @todo BUGFIX Prevent more than one speech to be played at a time (reject new requests).\r\n\t */\r\n\tvoid Say(HeroSpeech speechId) const;\r\n\t/**\r\n\t * @brief Says a speech line after a given delay.\r\n\t * @param speechId The speech ID to say.\r\n\t * @param delay Multiple of 50ms wait before starting the speech\r\n\t */\r\n\tvoid Say(HeroSpeech speechId, int delay) const;\r\n\t/**\r\n\t * @brief Says a speech line, without random variants.\r\n\t */\r\n\tvoid SaySpecific(HeroSpeech speechId) const;\r\n\r\n\t/**\r\n\t * @brief Attempts to stop the player from performing any queued up action. If the player is currently walking, his walking will\r\n\t * stop as soon as he reaches the next tile. If any action was queued with the previous command (like targeting a monster,\r\n\t * opening a chest, picking an item up, etc) this action will also be cancelled.\r\n\t */\r\n\tvoid Stop();\r\n\r\n\t/**\r\n\t * @brief Is the player currently walking?\r\n\t */\r\n\tbool isWalking() const;\r\n\r\n\t/**\r\n\t * @brief Returns item location taking into consideration barbarian's ability to hold two-handed maces and clubs in one hand.\r\n\t */\r\n\titem_equip_type GetItemLocation(const Item &item) const\r\n\t{\r\n\t\tif (_pClass == HeroClass::Barbarian && item._iLoc == ILOC_TWOHAND && IsAnyOf(item._itype, ItemType::Sword, ItemType::Mace))\r\n\t\t\treturn ILOC_ONEHAND;\r\n\t\treturn item._iLoc;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return player's armor value\r\n\t */\r\n\tint GetArmor() const\r\n\t{\r\n\t\treturn _pIBonusAC + _pIAC + _pDexterity / 5;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return player's melee to hit value\r\n\t */\r\n\tint GetMeleeToHit() const\r\n\t{\r\n\t\treturn getCharacterLevel() + _pDexterity / 2 + _pIBonusToHit + getPlayerCombatData().baseMeleeToHit;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return player's melee to hit value, including armor piercing\r\n\t */\r\n\tint GetMeleePiercingToHit() const\r\n\t{\r\n\t\tint hper = GetMeleeToHit();\r\n\t\t// in hellfire armor piercing ignores % of enemy armor instead, no way to include it here\r\n\t\tif (!gbIsHellfire)\r\n\t\t\thper += _pIEnAc;\r\n\t\treturn hper;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return player's ranged to hit value\r\n\t */\r\n\tint GetRangedToHit() const\r\n\t{\r\n\t\treturn getCharacterLevel() + _pDexterity + _pIBonusToHit + getPlayerCombatData().baseRangedToHit;\r\n\t}\r\n\r\n\tint GetRangedPiercingToHit() const\r\n\t{\r\n\t\tint hper = GetRangedToHit();\r\n\t\t// in hellfire armor piercing ignores % of enemy armor instead, no way to include it here\r\n\t\tif (!gbIsHellfire)\r\n\t\t\thper += _pIEnAc;\r\n\t\treturn hper;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return magic hit chance\r\n\t */\r\n\tint GetMagicToHit() const\r\n\t{\r\n\t\treturn _pMagic + getPlayerCombatData().baseMagicToHit;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return block chance\r\n\t * @param useLevel - indicate if player's level should be added to block chance (the only case where it isn't is blocking a trap)\r\n\t */\r\n\tint GetBlockChance(bool useLevel = true) const\r\n\t{\r\n\t\tint blkper = _pDexterity + getBaseToBlock();\r\n\t\tif (useLevel)\r\n\t\t\tblkper += getCharacterLevel() * 2;\r\n\t\treturn blkper;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return reciprocal of the factor for calculating damage reduction due to Mana Shield.\r\n\t *\r\n\t * Valid only for players with Mana Shield spell level greater than zero.\r\n\t */\r\n\tint GetManaShieldDamageReduction();\r\n\r\n\t/**\r\n\t * @brief Gets the effective spell level for the player, considering item bonuses\r\n\t * @param spell SpellID enum member identifying the spell\r\n\t * @return effective spell level\r\n\t */\r\n\tint GetSpellLevel(SpellID spell) const\r\n\t{\r\n\t\tif (spell == SpellID::Invalid || static_cast<std::size_t>(spell) >= sizeof(_pSplLvl)) {\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\treturn std::max<int>(_pISplLvlAdd + _pSplLvl[static_cast<std::size_t>(spell)], 0);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Return monster armor value after including player's armor piercing % (hellfire only)\r\n\t * @param monsterArmor - monster armor before applying % armor pierce\r\n\t * @param isMelee - indicates if it's melee or ranged combat\r\n\t */\r\n\tint CalculateArmorPierce(int monsterArmor, bool isMelee) const\r\n\t{\r\n\t\tint tmac = monsterArmor;\r\n\t\tif (_pIEnAc > 0) {\r\n\t\t\tif (gbIsHellfire) {\r\n\t\t\t\tint pIEnAc = _pIEnAc - 1;\r\n\t\t\t\tif (pIEnAc > 0)\r\n\t\t\t\t\ttmac >>= pIEnAc;\r\n\t\t\t\telse\r\n\t\t\t\t\ttmac -= tmac / 4;\r\n\t\t\t}\r\n\t\t\tif (isMelee && _pClass == HeroClass::Barbarian) {\r\n\t\t\t\ttmac -= monsterArmor / 8;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (tmac < 0)\r\n\t\t\ttmac = 0;\r\n\r\n\t\treturn tmac;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Calculates the players current Hit Points as a percentage of their max HP and stores it for later reference\r\n\t *\r\n\t * The stored value is unused...\r\n\t * @see _pHPPer\r\n\t * @return The players current hit points as a percentage of their maximum (from 0 to 80%)\r\n\t */\r\n\tint UpdateHitPointPercentage()\r\n\t{\r\n\t\tif (_pMaxHP <= 0) { // divide by zero guard\r\n\t\t\t_pHPPer = 0;\r\n\t\t} else {\r\n\t\t\t// Maximum achievable HP is approximately 1200. Diablo uses fixed point integers where the last 6 bits are\r\n\t\t\t// fractional values. This means that we will never overflow HP values normally by doing this multiplication\r\n\t\t\t// as the max value is representable in 17 bits and the multiplication result will be at most 23 bits\r\n\t\t\t_pHPPer = std::clamp(_pHitPoints * 81 / _pMaxHP, 0, 81); // hp should never be greater than maxHP but just in case\r\n\t\t}\r\n\r\n\t\treturn _pHPPer;\r\n\t}\r\n\r\n\tint UpdateManaPercentage()\r\n\t{\r\n\t\tif (_pMaxMana <= 0) {\r\n\t\t\t_pManaPer = 0;\r\n\t\t} else {\r\n\t\t\t_pManaPer = std::clamp(_pMana * 81 / _pMaxMana, 0, 81);\r\n\t\t}\r\n\r\n\t\treturn _pManaPer;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Restores between 1/8 (inclusive) and 1/4 (exclusive) of the players max HP (further adjusted by class).\r\n\t *\r\n\t * This determines a random amount of non-fractional life points to restore then scales the value based on the\r\n\t *  player class. Warriors/barbarians get between 1/4 and 1/2 life restored per potion, rogue/monk/bard get 3/16\r\n\t *  to 3/8, and sorcerers get the base amount.\r\n\t */\r\n\tvoid RestorePartialLife();\r\n\r\n\t/**\r\n\t * @brief Resets hp to maxHp\r\n\t */\r\n\tvoid RestoreFullLife()\r\n\t{\r\n\t\t_pHitPoints = _pMaxHP;\r\n\t\t_pHPBase = _pMaxHPBase;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Restores between 1/8 (inclusive) and 1/4 (exclusive) of the players max Mana (further adjusted by class).\r\n\t *\r\n\t * This determines a random amount of non-fractional mana points to restore then scales the value based on the\r\n\t *  player class. Sorcerers get between 1/4 and 1/2 mana restored per potion, rogue/monk/bard get 3/16 to 3/8,\r\n\t *  and warrior/barbarian get the base amount. However if the player can't use magic due to an equipped item then\r\n\t *  they get nothing.\r\n\t */\r\n\tvoid RestorePartialMana();\r\n\r\n\t/**\r\n\t * @brief Resets mana to maxMana (if the player can use magic)\r\n\t */\r\n\tvoid RestoreFullMana()\r\n\t{\r\n\t\tif (HasNoneOf(_pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\t\t_pMana = _pMaxMana;\r\n\t\t\t_pManaBase = _pMaxManaBase;\r\n\t\t}\r\n\t}\r\n\t/**\r\n\t * @brief Sets the readied spell to the spell in the specified equipment slot. Does nothing if the item does not have a valid spell.\r\n\t * @param bodyLocation - the body location whose item will be checked for the spell.\r\n\t * @param forceSpell - if true, always change active spell, if false, only when current spell slot is empty\r\n\t */\r\n\tvoid ReadySpellFromEquipment(inv_body_loc bodyLocation, bool forceSpell);\r\n\r\n\t/**\r\n\t * @brief Does the player currently have a ranged weapon equipped?\r\n\t */\r\n\tbool UsesRangedWeapon() const\r\n\t{\r\n\t\treturn static_cast<PlayerWeaponGraphic>(_pgfxnum & 0xF) == PlayerWeaponGraphic::Bow;\r\n\t}\r\n\r\n\tbool CanChangeAction()\r\n\t{\r\n\t\tif (_pmode == PM_STAND)\r\n\t\t\treturn true;\r\n\t\tif (_pmode == PM_ATTACK && AnimInfo.currentFrame >= _pAFNum)\r\n\t\t\treturn true;\r\n\t\tif (_pmode == PM_RATTACK && AnimInfo.currentFrame >= _pAFNum)\r\n\t\t\treturn true;\r\n\t\tif (_pmode == PM_SPELL && AnimInfo.currentFrame >= _pSFNum)\r\n\t\t\treturn true;\r\n\t\tif (isWalking() && AnimInfo.isLastFrame())\r\n\t\t\treturn true;\r\n\t\treturn false;\r\n\t}\r\n\r\n\t[[nodiscard]] player_graphic getGraphic() const;\r\n\r\n\t[[nodiscard]] uint16_t getSpriteWidth() const;\r\n\r\n\tvoid getAnimationFramesAndTicksPerFrame(player_graphic graphics, int8_t &numberOfFrames, int8_t &ticksPerFrame) const;\r\n\r\n\t[[nodiscard]] ClxSprite currentSprite() const\r\n\t{\r\n\t\treturn previewCelSprite ? *previewCelSprite : AnimInfo.currentSprite();\r\n\t}\r\n\t[[nodiscard]] Displacement getRenderingOffset(const ClxSprite sprite) const\r\n\t{\r\n\t\tDisplacement offset = { -CalculateSpriteTileCenterX(sprite.width()), 0 };\r\n\t\tif (isWalking())\r\n\t\t\toffset += GetOffsetForWalking(AnimInfo, _pdir);\r\n\t\treturn offset;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Updates previewCelSprite according to new requested command\r\n\t * @param cmdId What command is requested\r\n\t * @param point Point for the command\r\n\t * @param wParam1 First Parameter\r\n\t * @param wParam2 Second Parameter\r\n\t */\r\n\tvoid UpdatePreviewCelSprite(_cmd_id cmdId, Point point, uint16_t wParam1, uint16_t wParam2);\r\n\r\n\t[[nodiscard]] uint8_t getCharacterLevel() const\r\n\t{\r\n\t\treturn _pLevel;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Sets the character level to the target level or nearest valid value.\r\n\t * @param level New character level, will be clamped to the allowed range\r\n\t */\r\n\tvoid setCharacterLevel(uint8_t level);\r\n\r\n\t[[nodiscard]] uint8_t getMaxCharacterLevel() const;\r\n\r\n\t[[nodiscard]] bool isMaxCharacterLevel() const\r\n\t{\r\n\t\treturn getCharacterLevel() >= getMaxCharacterLevel();\r\n\t}\r\n\r\nprivate:\r\n\tvoid _addExperience(uint32_t experience, int levelDelta);\r\n\r\npublic:\r\n\t/**\r\n\t * @brief Adds experience to the local player based on the current game mode\r\n\t * @param experience base value to add, this will be adjusted to prevent power leveling in multiplayer games\r\n\t */\r\n\tvoid addExperience(uint32_t experience)\r\n\t{\r\n\t\t_addExperience(experience, 0);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Adds experience to the local player based on the difference between the monster level\r\n\t * and current level, then also applying the power level cap in multiplayer games.\r\n\t * @param experience base value to add, will be scaled up/down by the difference between player and monster level\r\n\t * @param monsterLevel level of the monster that has rewarded this experience\r\n\t */\r\n\tvoid addExperience(uint32_t experience, int monsterLevel)\r\n\t{\r\n\t\t_addExperience(experience, monsterLevel - getCharacterLevel());\r\n\t}\r\n\r\n\t[[nodiscard]] uint32_t getNextExperienceThreshold() const;\r\n\r\n\t/** @brief Checks if the player is on the same level as the local player (MyPlayer). */\r\n\tbool isOnActiveLevel() const\r\n\t{\r\n\t\tif (setlevel)\r\n\t\t\treturn isOnLevel(setlvlnum);\r\n\t\treturn isOnLevel(currlevel);\r\n\t}\r\n\r\n\t/** @brief Checks if the player is on the corresponding level. */\r\n\tbool isOnLevel(uint8_t level) const\r\n\t{\r\n\t\treturn !this->plrIsOnSetLevel && this->plrlevel == level;\r\n\t}\r\n\t/** @brief Checks if the player is on the corresponding level. */\r\n\tbool isOnLevel(_setlevels level) const\r\n\t{\r\n\t\treturn this->plrIsOnSetLevel && this->plrlevel == static_cast<uint8_t>(level);\r\n\t}\r\n\t/** @brief Checks if the player is on a arena level. */\r\n\tbool isOnArenaLevel() const\r\n\t{\r\n\t\treturn plrIsOnSetLevel && IsArenaLevel(static_cast<_setlevels>(plrlevel));\r\n\t}\r\n\tvoid setLevel(uint8_t level)\r\n\t{\r\n\t\tthis->plrlevel = level;\r\n\t\tthis->plrIsOnSetLevel = false;\r\n\t}\r\n\tvoid setLevel(_setlevels level)\r\n\t{\r\n\t\tthis->plrlevel = static_cast<uint8_t>(level);\r\n\t\tthis->plrIsOnSetLevel = true;\r\n\t}\r\n\r\n\t/** @brief Returns a character's life based on starting life, character level, and base vitality. */\r\n\tint32_t calculateBaseLife() const;\r\n\r\n\t/** @brief Returns a character's mana based on starting mana, character level, and base magic. */\r\n\tint32_t calculateBaseMana() const;\r\n\r\n\t/**\r\n\t * @brief Sets a tile/dPlayer to be occupied by the player\r\n\t * @param position tile to update\r\n\t * @param isMoving specifies whether the player is moving or not (true/moving results in a negative index in dPlayer)\r\n\t */\r\n\tvoid occupyTile(Point position, bool isMoving) const;\r\n\r\n\t/** @brief Checks if the player level is owned by local client. */\r\n\tbool isLevelOwnedByLocalClient() const;\r\n\r\n\t/** @brief Checks if the player is holding an item of the provided type, and is usable. */\r\n\tbool isHoldingItem(const ItemType type) const\r\n\t{\r\n\t\tconst Item &leftHandItem = InvBody[INVLOC_HAND_LEFT];\r\n\t\tconst Item &rightHandItem = InvBody[INVLOC_HAND_RIGHT];\r\n\r\n\t\treturn (type == leftHandItem._itype && leftHandItem._iStatFlag) || (type == rightHandItem._itype && rightHandItem._iStatFlag);\r\n\t}\r\n\r\n\tbool hasNoLife() const\r\n\t{\r\n\t\treturn leveltype == DTYPE_TOWN ? false : _pHitPoints >> 6 <= 0;\r\n\t}\r\n\r\n\tbool hasNoMana() const\r\n\t{\r\n\t\treturn _pMana >> 6 <= 0;\r\n\t}\r\n};\r\n\r\nextern DVL_API_FOR_TEST uint8_t MyPlayerId;\r\nextern DVL_API_FOR_TEST Player *MyPlayer;\r\nextern DVL_API_FOR_TEST std::vector<Player> Players;\r\n/** @brief What Player items and stats should be displayed? Normally this is identical to MyPlayer but can differ when /inspect was used. */\r\nextern Player *InspectPlayer;\r\n/** @brief Do we currently inspect a remote player (/inspect was used)? In this case the (remote) players items and stats can't be modified. */\r\ninline bool IsInspectingPlayer()\r\n{\r\n\treturn MyPlayer != InspectPlayer;\r\n}\r\nextern bool MyPlayerIsDead;\r\n\r\nPlayer *PlayerAtPosition(Point position, bool ignoreMovingPlayers = false);\r\n\r\n/**\r\n * @brief Get the players current portrait sprite which is used for the party panel.\r\n * @param player\r\n */\r\nClxSprite GetPlayerPortraitSprite(Player &player);\r\nbool IsPlayerUnarmed(Player &player);\r\n\r\nvoid LoadPlrGFX(Player &player, player_graphic graphic);\r\nvoid InitPlayerGFX(Player &player);\r\nvoid ResetPlayerGFX(Player &player);\r\n\r\n/**\r\n * @brief Sets the new Player Animation with all relevant information for rendering\r\n * @param player The player to set the animation for\r\n * @param graphic What player animation should be displayed\r\n * @param dir Direction of the animation\r\n * @param numberOfFrames Number of Frames in Animation\r\n * @param delayLen Delay after each Animation sequence\r\n * @param flags Specifies what special logics are applied to this Animation\r\n * @param numSkippedFrames Number of Frames that will be skipped (for example with modifier \"faster attack\")\r\n * @param distributeFramesBeforeFrame Distribute the numSkippedFrames only before this frame\r\n */\r\nvoid NewPlrAnim(Player &player, player_graphic graphic, Direction dir, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int8_t numSkippedFrames = 0, int8_t distributeFramesBeforeFrame = 0);\r\nvoid SetPlrAnims(Player &player);\r\nvoid CreatePlayer(Player &player, HeroClass c);\r\nint CalcStatDiff(Player &player);\r\n#ifdef _DEBUG\r\nvoid NextPlrLevel(Player &player);\r\n#endif\r\nvoid AddPlrMonstExper(int lvl, unsigned int exp, char pmask);\r\nvoid ApplyPlrDamage(DamageType damageType, Player &player, int dam, int minHP = 0, int frac = 0, DeathReason deathReason = DeathReason::MonsterOrTrap);\r\nvoid InitPlayer(Player &player, bool FirstTime);\r\nvoid InitMultiView();\r\nvoid PlrClrTrans(Point position);\r\nvoid PlrDoTrans(Point position);\r\nvoid SetPlayerOld(Player &player);\r\nvoid FixPlayerLocation(Player &player, Direction bDir);\r\nvoid StartStand(Player &player, Direction dir);\r\nvoid StartPlrBlock(Player &player, Direction dir);\r\nvoid FixPlrWalkTags(const Player &player);\r\nvoid StartPlrHit(Player &player, int dam, bool forcehit);\r\nvoid StartPlayerKill(Player &player, DeathReason deathReason);\r\n/**\r\n * @brief Strip the top off gold piles that are larger than MaxGold\r\n */\r\nvoid StripTopGold(Player &player);\r\nvoid SyncPlrKill(Player &player, DeathReason deathReason);\r\nvoid RemovePlrMissiles(const Player &player);\r\nvoid StartNewLvl(Player &player, interface_mode fom, int lvl);\r\nvoid RestartTownLvl(Player &player);\r\nvoid StartWarpLvl(Player &player, size_t pidx);\r\nvoid ProcessPlayers();\r\nvoid ClrPlrPath(Player &player);\r\nbool PosOkPlayer(const Player &player, Point position);\r\nvoid MakePlrPath(Player &player, Point targetPosition, bool endspace);\r\nvoid CheckPlrSpell(bool isShiftHeld, SpellID spellID = MyPlayer->_pRSpell, SpellType spellType = MyPlayer->_pRSplType);\r\nvoid SyncPlrAnim(Player &player);\r\nvoid SyncInitPlrPos(Player &player);\r\nvoid SyncInitPlr(Player &player);\r\nvoid CheckStats(Player &player);\r\nvoid ModifyPlrStr(Player &player, int l);\r\nvoid ModifyPlrMag(Player &player, int l);\r\nvoid ModifyPlrDex(Player &player, int l);\r\nvoid ModifyPlrVit(Player &player, int l);\r\nvoid SetPlayerHitPoints(Player &player, int val);\r\nvoid SetPlrStr(Player &player, int v);\r\nvoid SetPlrMag(Player &player, int v);\r\nvoid SetPlrDex(Player &player, int v);\r\nvoid SetPlrVit(Player &player, int v);\r\nvoid InitDungMsgs(Player &player);\r\nvoid PlayDungMsgs();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/plrmsg.cpp",
    "content": "/**\r\n * @file plrmsg.cpp\r\n *\r\n * Implementation of functionality for printing the ingame chat messages.\r\n */\r\n#include \"plrmsg.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"inv.h\"\r\n#include \"qol/chatlog.h\"\r\n#include \"qol/stash.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct PlayerMessage {\r\n\t/** Time message was received */\r\n\tuint32_t time;\r\n\t/** The default text color */\r\n\tUiFlags style;\r\n\t/** The text message to display on screen */\r\n\tstd::string text;\r\n\t/** Length of first portion of text that should be rendered in gold */\r\n\tsize_t prefixLength;\r\n\t/** The line height of the text */\r\n\tint lineHeight;\r\n};\r\n\r\nstd::array<PlayerMessage, 8> Messages;\r\n\r\nint CountLinesOfText(std::string_view text)\r\n{\r\n\treturn static_cast<int>(1 + c_count(text, '\\n'));\r\n}\r\n\r\nPlayerMessage &GetNextMessage()\r\n{\r\n\tstd::move_backward(Messages.begin(), Messages.end() - 1, Messages.end()); // Push back older messages\r\n\r\n\treturn Messages.front();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid DelayPlrMessages(uint32_t delayTime)\r\n{\r\n\tfor (PlayerMessage &message : Messages)\r\n\t\tmessage.time += delayTime;\r\n}\r\n\r\nvoid EventPlrMsg(std::string_view text, UiFlags style)\r\n{\r\n\tPlayerMessage &message = GetNextMessage();\r\n\r\n\tmessage.style = style;\r\n\tmessage.time = SDL_GetTicks();\r\n\tmessage.text = std::string(text);\r\n\tmessage.prefixLength = 0;\r\n\tmessage.lineHeight = GetLineHeight(message.text, GameFont12) + 3;\r\n\tAddMessageToChatLog(text);\r\n}\r\n\r\nvoid SendPlrMsg(Player &player, std::string_view text)\r\n{\r\n\tPlayerMessage &message = GetNextMessage();\r\n\r\n\tconst std::string from = fmt::format(fmt::runtime(_(\"{:s} (lvl {:d}): \")), player._pName, player.getCharacterLevel());\r\n\r\n\tmessage.style = UiFlags::ColorWhite;\r\n\tmessage.time = SDL_GetTicks();\r\n\tmessage.text = from + std::string(text);\r\n\tmessage.prefixLength = from.size();\r\n\tmessage.lineHeight = GetLineHeight(message.text, GameFont12) + 3;\r\n\tAddMessageToChatLog(text, &player);\r\n}\r\n\r\nvoid InitPlrMsg()\r\n{\r\n\tMessages = {};\r\n}\r\n\r\nvoid DrawPlrMsg(const Surface &out)\r\n{\r\n\tif (ChatLogFlag)\r\n\t\treturn;\r\n\r\n\tint x = 10;\r\n\tint y = GetMainPanel().position.y - 13;\r\n\tint width = gnScreenWidth - 20;\r\n\r\n\tif (!ChatFlag && IsLeftPanelOpen()) {\r\n\t\tx += GetLeftPanel().position.x + GetLeftPanel().size.width;\r\n\t\twidth -= GetLeftPanel().size.width;\r\n\t}\r\n\tif (!ChatFlag && IsRightPanelOpen())\r\n\t\twidth -= gnScreenWidth - GetRightPanel().position.x;\r\n\r\n\tif (width < 300)\r\n\t\treturn;\r\n\r\n\twidth = std::min(540, width);\r\n\r\n\tfor (const PlayerMessage &message : Messages) {\r\n\t\tif (message.text.empty())\r\n\t\t\tbreak;\r\n\t\tif (!ChatFlag && SDL_GetTicks() - message.time >= 10000)\r\n\t\t\tbreak;\r\n\r\n\t\tstd::string text = WordWrapString(message.text, width);\r\n\t\tconst int chatlines = CountLinesOfText(text);\r\n\t\ty -= message.lineHeight * chatlines;\r\n\r\n\t\tDrawHalfTransparentRectTo(out, x - 3, y, width + 6, message.lineHeight * chatlines);\r\n\r\n\t\tstd::array<DrawStringFormatArg, 2> args {\r\n\t\t\tDrawStringFormatArg { std::string_view(text.data(), message.prefixLength), UiFlags::ColorWhitegold },\r\n\t\t\tDrawStringFormatArg { std::string_view(text.data() + message.prefixLength, text.size() - message.prefixLength), message.style }\r\n\t\t};\r\n\t\tDrawStringWithColors(out, \"{:s}{:s}\", args.data(), args.size(), { { x, y }, { width, 0 } },\r\n\t\t    { .flags = UiFlags::None, .lineHeight = message.lineHeight });\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/plrmsg.h",
    "content": "/**\r\n * @file plrmsg.h\r\n *\r\n * Interface of functionality for printing the ingame chat messages.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid DelayPlrMessages(uint32_t delayTime);\r\nvoid EventPlrMsg(std::string_view text, UiFlags style = UiFlags::ColorWhitegold);\r\nvoid SendPlrMsg(Player &player, std::string_view text);\r\nvoid InitPlrMsg();\r\nvoid DrawPlrMsg(const Surface &out);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/portal.cpp",
    "content": "/**\r\n * @file portal.cpp\r\n *\r\n * Implementation of functionality for handling town portals.\r\n */\r\n#include \"portal.h\"\r\n\r\n#include \"lighting.h\"\r\n#include \"missiles.h\"\r\n#include \"multi.h\"\r\n#include \"player.h\"\r\n#include \"tables/misdat.h\"\r\n\r\nnamespace devilution {\r\n\r\n/** In-game state of portals. */\r\nPortal Portals[MAXPORTAL];\r\n\r\nnamespace {\r\n\r\n/** Current portal number (a portal array index). */\r\nsize_t portalindex;\r\n\r\n/** Coordinate of each player's portal in town. */\r\nPoint PortalTownPosition[MAXPORTAL] = {\r\n\t{ 57, 40 },\r\n\t{ 59, 40 },\r\n\t{ 61, 40 },\r\n\t{ 63, 40 },\r\n};\r\n\r\n} // namespace\r\n\r\nvoid InitPortals()\r\n{\r\n\tfor (auto &portal : Portals) {\r\n\t\tportal.open = false;\r\n\t}\r\n}\r\n\r\nvoid SetPortalStats(int i, bool o, Point position, int lvl, dungeon_type lvltype, bool isSetLevel)\r\n{\r\n\tPortals[i].open = o;\r\n\tPortals[i].position = position;\r\n\tPortals[i].level = lvl;\r\n\tPortals[i].ltype = lvltype;\r\n\tPortals[i].setlvl = isSetLevel;\r\n}\r\n\r\nvoid AddPortalMissile(const Player &player, Point position, bool sync)\r\n{\r\n\tauto *missile = AddMissile({ 0, 0 }, position, Direction::South, MissileID::TownPortal, TARGET_MONSTERS, player, 0, 0, /*parent=*/nullptr, SfxID::None);\r\n\tif (missile != nullptr) {\r\n\t\t// Don't show portal opening animation if we sync existing portals\r\n\t\tif (sync)\r\n\t\t\tmissile->setFrameGroup<PortalFrame>(PortalFrame::Idle);\r\n\r\n\t\tif (leveltype != DTYPE_TOWN)\r\n\t\t\tmissile->_mlid = AddLight(missile->position.tile, 15);\r\n\t}\r\n}\r\n\r\nvoid SyncPortals()\r\n{\r\n\tfor (int i = 0; i < MAXPORTAL; i++) {\r\n\t\tif (!Portals[i].open)\r\n\t\t\tcontinue;\r\n\t\tconst Player &player = Players[i];\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\tAddPortalMissile(player, PortalTownPosition[i], true);\r\n\t\telse {\r\n\t\t\tint lvl = currlevel;\r\n\t\t\tif (setlevel)\r\n\t\t\t\tlvl = setlvlnum;\r\n\t\t\tif (Portals[i].level == lvl && Portals[i].setlvl == setlevel)\r\n\t\t\t\tAddPortalMissile(player, Portals[i].position, true);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AddPortalInTown(const Player &player)\r\n{\r\n\tAddPortalMissile(player, PortalTownPosition[player.getId()], false);\r\n}\r\n\r\nvoid ActivatePortal(const Player &player, Point position, int lvl, dungeon_type dungeonType, bool isSetLevel)\r\n{\r\n\tPortal &portal = Portals[player.getId()];\r\n\tportal.open = true;\r\n\r\n\tif (lvl != 0) {\r\n\t\tportal.position = position;\r\n\t\tportal.level = lvl;\r\n\t\tportal.ltype = dungeonType;\r\n\t\tportal.setlvl = isSetLevel;\r\n\t}\r\n}\r\n\r\nvoid DeactivatePortal(const Player &player)\r\n{\r\n\tPortals[player.getId()].open = false;\r\n}\r\n\r\nbool PortalOnLevel(const Player &player)\r\n{\r\n\tconst Portal &portal = Portals[player.getId()];\r\n\tif (portal.setlvl == setlevel && portal.level == (setlevel ? static_cast<int>(setlvlnum) : currlevel))\r\n\t\treturn true;\r\n\r\n\treturn leveltype == DTYPE_TOWN;\r\n}\r\n\r\nvoid RemovePortalMissile(const Player &player)\r\n{\r\n\tconst size_t id = player.getId();\r\n\tMissiles.remove_if([id](Missile &missile) {\r\n\t\tif (missile._mitype == MissileID::TownPortal && missile._misource == static_cast<int>(id)) {\r\n\t\t\tdFlags[missile.position.tile.x][missile.position.tile.y] &= ~DungeonFlag::Missile;\r\n\r\n\t\t\tif (Portals[id].level != 0)\r\n\t\t\t\tAddUnLight(missile._mlid);\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t});\r\n}\r\n\r\nvoid SetCurrentPortal(size_t p)\r\n{\r\n\tportalindex = p;\r\n}\r\n\r\nvoid GetPortalLevel()\r\n{\r\n\tif (leveltype != DTYPE_TOWN) {\r\n\t\tsetlevel = false;\r\n\t\tcurrlevel = 0;\r\n\t\tMyPlayer->setLevel(0);\r\n\t\tleveltype = DTYPE_TOWN;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (Portals[portalindex].setlvl) {\r\n\t\tsetlevel = true;\r\n\t\tsetlvlnum = (_setlevels)Portals[portalindex].level;\r\n\t\tcurrlevel = Portals[portalindex].level;\r\n\t\tMyPlayer->setLevel(setlvlnum);\r\n\t\tsetlvltype = leveltype = Portals[portalindex].ltype;\r\n\t} else {\r\n\t\tsetlevel = false;\r\n\t\tcurrlevel = Portals[portalindex].level;\r\n\t\tMyPlayer->setLevel(currlevel);\r\n\t\tleveltype = Portals[portalindex].ltype;\r\n\t}\r\n\r\n\tif (portalindex == MyPlayerId) {\r\n\t\tNetSendCmd(true, CMD_DEACTIVATEPORTAL);\r\n\t\tDeactivatePortal(*MyPlayer);\r\n\t}\r\n}\r\n\r\nvoid GetPortalLvlPos()\r\n{\r\n\tif (leveltype == DTYPE_TOWN) {\r\n\t\tViewPosition = PortalTownPosition[portalindex] + Displacement { 1, 1 };\r\n\t} else {\r\n\t\tViewPosition = Portals[portalindex].position;\r\n\r\n\t\tif (portalindex != MyPlayerId) {\r\n\t\t\tViewPosition.x++;\r\n\t\t\tViewPosition.y++;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool PosOkPortal(int lvl, Point position)\r\n{\r\n\tfor (auto &portal : Portals) {\r\n\t\tif (portal.open\r\n\t\t    && portal.level == lvl\r\n\t\t    && ((portal.position == position)\r\n\t\t        || (portal.position == position - Displacement { 1, 1 })))\r\n\t\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/portal.h",
    "content": "/**\r\n * @file portal.h\r\n *\r\n * Interface of functionality for handling town portals.\r\n */\r\n#pragma once\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\n// Defined in player.h, forward declared here to allow for functions which operate in the context of a player.\r\nstruct Player;\r\n\r\n#define MAXPORTAL 4\r\n\r\nstruct Portal {\r\n\tbool open;\r\n\tPoint position;\r\n\tint level;\r\n\tdungeon_type ltype;\r\n\tbool setlvl;\r\n};\r\n\r\nextern Portal Portals[MAXPORTAL];\r\n\r\nvoid InitPortals();\r\nvoid SetPortalStats(int i, bool o, Point position, int lvl, dungeon_type lvltype, bool isSetLevel);\r\nvoid AddPortalMissile(const Player &player, Point position, bool sync);\r\nvoid SyncPortals();\r\nvoid AddPortalInTown(const Player &player);\r\nvoid ActivatePortal(const Player &player, Point position, int lvl, dungeon_type lvltype, bool sp);\r\nvoid DeactivatePortal(const Player &player);\r\nbool PortalOnLevel(const Player &player);\r\nvoid RemovePortalMissile(const Player &player);\r\nvoid SetCurrentPortal(size_t p);\r\nvoid GetPortalLevel();\r\nvoid GetPortalLvlPos();\r\nbool PosOkPortal(int lvl, Point position);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/portals/validation.cpp",
    "content": "/**\r\n * @file portals/validation.cpp\r\n *\r\n * Implementation of functions for validation of portal data.\r\n */\r\n\r\n#include \"portals/validation.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/world_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/setmaps.h\"\r\n#include \"quests.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\ndungeon_type GetQuestLevelType(_setlevels questLevel)\r\n{\r\n\tfor (const Quest &quest : Quests) {\r\n\t\tif (quest._qslvl == questLevel)\r\n\t\t\treturn quest._qlvltype;\r\n\t}\r\n\treturn DTYPE_NONE;\r\n}\r\n\r\ndungeon_type GetSetLevelType(_setlevels setLevel)\r\n{\r\n\tconst bool isArenaLevel = setLevel >= SL_FIRST_ARENA && setLevel <= SL_LAST;\r\n\treturn isArenaLevel ? GetArenaLevelType(setLevel) : GetQuestLevelType(setLevel);\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsPortalDeltaValid(WorldTilePosition location, uint8_t level, uint8_t ltype, bool isOnSetLevel)\r\n{\r\n\tif (!InDungeonBounds(location))\r\n\t\treturn false;\r\n\tconst dungeon_type levelType = static_cast<dungeon_type>(ltype);\r\n\tif (levelType == DTYPE_NONE)\r\n\t\treturn false;\r\n\tif (isOnSetLevel)\r\n\t\treturn levelType == GetSetLevelType(static_cast<_setlevels>(level));\r\n\treturn levelType == GetLevelType(level);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/portals/validation.hpp",
    "content": "/**\r\n * @file portals/validation.hpp\r\n *\r\n * Interface of functions for validation of portal data.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/world_tile.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool IsPortalDeltaValid(WorldTilePosition location, uint8_t level, uint8_t levelType, bool isOnSetLevel);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/autopickup.cpp",
    "content": "/**\r\n * @file autopickup.cpp\r\n *\r\n * QoL feature for automatically picking up gold\r\n */\r\n#include \"qol/autopickup.h\"\r\n\r\n#include <algorithm>\r\n\r\n#include \"inv_iterators.hpp\"\r\n#include \"options.h\"\r\n#include \"player.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nbool HasRoomForGold()\r\n{\r\n\tfor (const int idx : MyPlayer->InvGrid) {\r\n\t\t// Secondary item cell. No need to check those as we'll go through the main item cells anyway.\r\n\t\tif (idx < 0)\r\n\t\t\tcontinue;\r\n\r\n\t\t// Empty cell. 1x1 space available.\r\n\t\tif (idx == 0)\r\n\t\t\treturn true;\r\n\r\n\t\t// Main item cell. Potentially a gold pile so check it.\r\n\t\tauto item = MyPlayer->InvList[idx - 1];\r\n\t\tif (item._itype == ItemType::Gold && item._ivalue < MaxGold)\r\n\t\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nint NumMiscItemsInInv(int iMiscId)\r\n{\r\n\treturn c_count_if(InventoryAndBeltPlayerItemsRange { *MyPlayer },\r\n\t    [iMiscId](const Item &item) { return item._iMiscId == iMiscId; });\r\n}\r\n\r\nbool DoPickup(Item item)\r\n{\r\n\tif (item._itype == ItemType::Gold && *GetOptions().Gameplay.autoGoldPickup && HasRoomForGold())\r\n\t\treturn true;\r\n\r\n\tif (item._itype == ItemType::Misc\r\n\t    && (CanFitItemInInventory(*MyPlayer, item) || AutoPlaceItemInBelt(*MyPlayer, item))) {\r\n\t\tswitch (item._iMiscId) {\r\n\t\tcase IMISC_HEAL:\r\n\t\t\treturn *GetOptions().Gameplay.numHealPotionPickup > NumMiscItemsInInv(item._iMiscId);\r\n\t\tcase IMISC_FULLHEAL:\r\n\t\t\treturn *GetOptions().Gameplay.numFullHealPotionPickup > NumMiscItemsInInv(item._iMiscId);\r\n\t\tcase IMISC_MANA:\r\n\t\t\treturn *GetOptions().Gameplay.numManaPotionPickup > NumMiscItemsInInv(item._iMiscId);\r\n\t\tcase IMISC_FULLMANA:\r\n\t\t\treturn *GetOptions().Gameplay.numFullManaPotionPickup > NumMiscItemsInInv(item._iMiscId);\r\n\t\tcase IMISC_REJUV:\r\n\t\t\treturn *GetOptions().Gameplay.numRejuPotionPickup > NumMiscItemsInInv(item._iMiscId);\r\n\t\tcase IMISC_FULLREJUV:\r\n\t\t\treturn *GetOptions().Gameplay.numFullRejuPotionPickup > NumMiscItemsInInv(item._iMiscId);\r\n\t\tcase IMISC_ELIXSTR:\r\n\t\tcase IMISC_ELIXMAG:\r\n\t\tcase IMISC_ELIXDEX:\r\n\t\tcase IMISC_ELIXVIT:\r\n\t\t\treturn *GetOptions().Gameplay.autoElixirPickup;\r\n\t\tcase IMISC_OILFIRST:\r\n\t\tcase IMISC_OILOF:\r\n\t\tcase IMISC_OILACC:\r\n\t\tcase IMISC_OILMAST:\r\n\t\tcase IMISC_OILSHARP:\r\n\t\tcase IMISC_OILDEATH:\r\n\t\tcase IMISC_OILSKILL:\r\n\t\tcase IMISC_OILBSMTH:\r\n\t\tcase IMISC_OILFORT:\r\n\t\tcase IMISC_OILPERM:\r\n\t\tcase IMISC_OILHARD:\r\n\t\tcase IMISC_OILIMP:\r\n\t\tcase IMISC_OILLAST:\r\n\t\t\treturn *GetOptions().Gameplay.autoOilPickup;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid AutoPickup(const Player &player)\r\n{\r\n\tif (&player != MyPlayer)\r\n\t\treturn;\r\n\tif (leveltype == DTYPE_TOWN && !*GetOptions().Gameplay.autoPickupInTown)\r\n\t\treturn;\r\n\r\n\tfor (auto pathDir : PathDirs) {\r\n\t\tconst Point tile = player.position.tile + pathDir;\r\n\t\tif (dItem[tile.x][tile.y] != 0) {\r\n\t\t\tconst int itemIndex = dItem[tile.x][tile.y] - 1;\r\n\t\t\tauto &item = Items[itemIndex];\r\n\t\t\tif (DoPickup(item)) {\r\n\t\t\t\tNetSendCmdGItem(true, CMD_REQUESTAGITEM, player, itemIndex);\r\n\t\t\t\titem._iRequest = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/autopickup.h",
    "content": "/**\r\n * @file autopickup.h\r\n *\r\n * QoL feature for automatically picking up gold\r\n */\r\n\r\n#pragma once\r\n\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid AutoPickup(const Player &player);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/chatlog.cpp",
    "content": "/**\r\n * @file chatlog.cpp\r\n *\r\n * Implementation of the in-game chat log.\r\n */\r\n#include <ctime>\r\n#include <sstream>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"automap.h\"\r\n#include \"chatlog.h\"\r\n#include \"control/control.hpp\"\r\n#include \"diablo_msg.hpp\"\r\n#include \"doom.h\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"gamemenu.h\"\r\n#include \"help.h\"\r\n#include \"inv.h\"\r\n#include \"minitext.h\"\r\n#include \"stores.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct ColoredText {\r\n\tstd::string text;\r\n\tUiFlags color;\r\n};\r\n\r\nstruct MultiColoredText {\r\n\tstd::string text;\r\n\tstd::vector<ColoredText> colors;\r\n};\r\n\r\nbool UnreadFlag = false;\r\nsize_t SkipLines;\r\nunsigned int MessageCounter = 0;\r\n\r\nstd::vector<MultiColoredText> ChatLogLines;\r\n\r\nconstexpr int PaddingTop = 32;\r\nconstexpr int PaddingLeft = 32;\r\n\r\nconstexpr int PanelHeight = 297;\r\nconstexpr int ContentTextWidth = 577;\r\n\r\nint LineHeight()\r\n{\r\n\treturn IsSmallFontTall() ? 18 : 14;\r\n}\r\n\r\nint BlankLineHeight()\r\n{\r\n\treturn 12;\r\n}\r\n\r\nint DividerLineMarginY()\r\n{\r\n\treturn BlankLineHeight() / 2;\r\n}\r\n\r\nint HeaderHeight()\r\n{\r\n\treturn PaddingTop + LineHeight() + 2 * BlankLineHeight() + DividerLineMarginY();\r\n}\r\n\r\nint ContentPaddingY()\r\n{\r\n\treturn BlankLineHeight();\r\n}\r\n\r\nint ContentsTextHeight()\r\n{\r\n\treturn PanelHeight - HeaderHeight() - DividerLineMarginY() - 2 * ContentPaddingY() - BlankLineHeight();\r\n}\r\n\r\nint NumVisibleLines()\r\n{\r\n\treturn (ContentsTextHeight() - 1) / LineHeight() + 1; // Ceil\r\n}\r\n\r\n} // namespace\r\n\r\nbool ChatLogFlag = false;\r\n\r\nvoid ToggleChatLog()\r\n{\r\n\tif (ChatLogFlag) {\r\n\t\tChatLogFlag = false;\r\n\t} else {\r\n\t\tActiveStore = TalkID::None;\r\n\t\tCloseInventory();\r\n\t\tCloseCharPanel();\r\n\t\tSpellbookFlag = false;\r\n\t\tSpellSelectFlag = false;\r\n\t\tif (qtextflag && leveltype == DTYPE_TOWN) {\r\n\t\t\tqtextflag = false;\r\n\t\t\tstream_stop();\r\n\t\t}\r\n\t\tQuestLogIsOpen = false;\r\n\t\tHelpFlag = false;\r\n\t\tCancelCurrentDiabloMsg();\r\n\t\tgamemenu_off();\r\n\t\tSkipLines = 0;\r\n\t\tChatLogFlag = true;\r\n\t\tdoom_close();\r\n\t}\r\n}\r\n\r\nvoid AddMessageToChatLog(std::string_view message, Player *player, UiFlags flags)\r\n{\r\n\tMessageCounter++;\r\n\tconst time_t timeResult = time(nullptr);\r\n\tconst std::tm *localtimeResult = localtime(&timeResult);\r\n\tstd::string timestamp = localtimeResult != nullptr\r\n\t    ? StrCat(\"[#\", MessageCounter, \"] \", LeftPad(localtimeResult->tm_hour, 2, '0'), \":\", LeftPad(localtimeResult->tm_min, 2, '0'), \":\", LeftPad(localtimeResult->tm_sec, 2, '0'))\r\n\t    : StrCat(\"[#\", MessageCounter, \"] \");\r\n\tconst size_t oldSize = ChatLogLines.size();\r\n\tif (player == nullptr) {\r\n\t\tChatLogLines.emplace_back(MultiColoredText { \"{0} {1}\", { { timestamp, UiFlags::ColorRed }, { std::string(message), flags } } });\r\n\t} else {\r\n\t\tstd::string playerInfo = fmt::format(fmt::runtime(_(\"{:s} (lvl {:d}): \")), player->_pName, player->getCharacterLevel());\r\n\t\tUiFlags nameColor = player == MyPlayer ? UiFlags::ColorWhitegold : UiFlags::ColorBlue;\r\n\t\tconst std::string prefix = timestamp + \" - \" + playerInfo;\r\n\t\tconst std::string text = WordWrapString(prefix + std::string(message), ContentTextWidth);\r\n\t\tstd::vector<std::string> lines;\r\n\t\tstd::stringstream ss(text);\r\n\r\n\t\tfor (std::string s; getline(ss, s, '\\n');) {\r\n\t\t\tlines.push_back(s);\r\n\t\t}\r\n\t\tfor (int i = static_cast<int>(lines.size()) - 1; i >= 1; i--) {\r\n\t\t\tChatLogLines.emplace_back(MultiColoredText { lines[i], {} });\r\n\t\t}\r\n\t\tlines[0].erase(0, prefix.length());\r\n\t\tChatLogLines.emplace_back(MultiColoredText { \"{0} - {1}{2}\", { { timestamp, UiFlags::ColorRed }, { playerInfo, nameColor }, { lines[0], UiFlags::ColorWhite } } });\r\n\t}\r\n\r\n\tconst size_t diff = ChatLogLines.size() - oldSize;\r\n\t// only autoscroll when on top of the log\r\n\tif (SkipLines != 0) {\r\n\t\tSkipLines += diff;\r\n\t\tUnreadFlag = true;\r\n\t}\r\n}\r\n\r\nvoid DrawChatLog(const Surface &out)\r\n{\r\n\tDrawSTextHelp();\r\n\tDrawQTextBack(out);\r\n\r\n\tif (SkipLines == 0) {\r\n\t\tUnreadFlag = false;\r\n\t}\r\n\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tconst int lineHeight = LineHeight();\r\n\tconst int blankLineHeight = BlankLineHeight();\r\n\tconst int sx = uiPosition.x + PaddingLeft;\r\n\tconst int sy = uiPosition.y;\r\n\r\n\tDrawString(out, fmt::format(fmt::runtime(_(\"Chat History (Messages: {:d})\")), MessageCounter),\r\n\t    { { sx, sy + PaddingTop + blankLineHeight }, { ContentTextWidth, lineHeight } },\r\n\t    { .flags = (UnreadFlag ? UiFlags::ColorRed : UiFlags::ColorWhitegold) | UiFlags::AlignCenter });\r\n\r\n\tconst time_t timeResult = time(nullptr);\r\n\tconst std::tm *localtimeResult = localtime(&timeResult);\r\n\tif (localtimeResult != nullptr) {\r\n\t\tconst std::string timestamp = StrCat(\r\n\t\t    LeftPad(localtimeResult->tm_hour, 2, '0'), \":\", LeftPad(localtimeResult->tm_min, 2, '0'), \":\", LeftPad(localtimeResult->tm_sec, 2, '0'));\r\n\t\tDrawString(out, timestamp, { { sx, sy + PaddingTop + blankLineHeight }, { ContentTextWidth, lineHeight } },\r\n\t\t    { .flags = UiFlags::ColorWhitegold });\r\n\t}\r\n\r\n\tconst int titleBottom = sy + HeaderHeight();\r\n\tDrawSLine(out, titleBottom);\r\n\r\n\tconst int numLines = NumVisibleLines();\r\n\tconst int contentY = titleBottom + DividerLineMarginY() + ContentPaddingY();\r\n\tfor (int i = 0; i < numLines; i++) {\r\n\t\tif (i + SkipLines >= ChatLogLines.size())\r\n\t\t\tbreak;\r\n\t\tconst MultiColoredText &text = ChatLogLines[ChatLogLines.size() - (i + SkipLines + 1)];\r\n\t\tconst std::string_view line = text.text;\r\n\r\n\t\tstd::vector<DrawStringFormatArg> args;\r\n\t\tfor (auto &x : text.colors) {\r\n\t\t\targs.emplace_back(DrawStringFormatArg { x.text, x.color });\r\n\t\t}\r\n\t\tDrawStringWithColors(out, line, args, { { sx, contentY + i * lineHeight }, { ContentTextWidth, lineHeight } },\r\n\t\t    { .flags = UiFlags::ColorWhite, .lineHeight = lineHeight });\r\n\t}\r\n\r\n\tDrawString(out, _(\"Press ESC to end or the arrow keys to scroll.\"),\r\n\t    { { sx, contentY + ContentsTextHeight() + ContentPaddingY() + blankLineHeight }, { ContentTextWidth, lineHeight } },\r\n\t    { .flags = UiFlags::ColorWhitegold | UiFlags::AlignCenter });\r\n}\r\n\r\nvoid ChatLogScrollUp()\r\n{\r\n\tif (SkipLines > 0)\r\n\t\tSkipLines--;\r\n}\r\n\r\nvoid ChatLogScrollDown()\r\n{\r\n\tif (SkipLines + NumVisibleLines() < ChatLogLines.size())\r\n\t\tSkipLines++;\r\n}\r\n\r\nvoid ChatLogScrollTop()\r\n{\r\n\tSkipLines = 0;\r\n}\r\n\r\nvoid ChatLogScrollBottom()\r\n{\r\n\tSkipLines = ChatLogLines.size() - NumVisibleLines();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/chatlog.h",
    "content": "/**\r\n * @file chatlog.h\r\n *\r\n * Adds Chat log QoL feature\r\n */\r\n#pragma once\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern bool ChatLogFlag;\r\n\r\nvoid ToggleChatLog();\r\nvoid AddMessageToChatLog(std::string_view message, Player *player = nullptr, UiFlags flags = UiFlags::ColorWhite);\r\nvoid DrawChatLog(const Surface &out);\r\nvoid ChatLogScrollUp();\r\nvoid ChatLogScrollDown();\r\nvoid ChatLogScrollTop();\r\nvoid ChatLogScrollBottom();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/floatingnumbers.cpp",
    "content": "#include \"floatingnumbers.h\"\r\n\r\n#include <cstdint>\r\n#include <ctime>\r\n#include <deque>\r\n#include <fmt/format.h>\r\n#include <string>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct FloatingNumber {\r\n\tPoint startPos;\r\n\tDisplacement startOffset;\r\n\tDisplacement endOffset;\r\n\tstd::string text;\r\n\tuint32_t time;\r\n\tuint32_t lastMerge;\r\n\tUiFlags style;\r\n\tint id;\r\n\tbool reverseDirection;\r\n};\r\n\r\nstd::deque<FloatingNumber> FloatingQueue;\r\n\r\nvoid ClearExpiredNumbers()\r\n{\r\n\twhile (!FloatingQueue.empty()) {\r\n\t\tconst FloatingNumber &num = FloatingQueue.front();\r\n\t\tif (num.time > SDL_GetTicks())\r\n\t\t\tbreak;\r\n\r\n\t\tFloatingQueue.pop_front();\r\n\t}\r\n}\r\n\r\nGameFontTables GetGameFontSize(UiFlags flags)\r\n{\r\n\tif (HasAnyOf(flags, UiFlags::FontSize30))\r\n\t\treturn GameFont30;\r\n\tif (HasAnyOf(flags, UiFlags::FontSize24))\r\n\t\treturn GameFont24;\r\n\treturn GameFont12;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid AddFloatingNumber(Point pos, Displacement offset, std::string text, UiFlags style, int id, bool reverseDirection)\r\n{\r\n\tDisplacement endOffset;\r\n\tif (!reverseDirection)\r\n\t\tendOffset = { 0, -140 };\r\n\telse\r\n\t\tendOffset = { 0, 140 };\r\n\r\n\tfor (auto &num : FloatingQueue) {\r\n\t\tif (id != 0 && num.id == id && (SDL_GetTicks() - static_cast<int>(num.lastMerge)) <= 100) {\r\n\t\t\tnum.text = text;\r\n\t\t\tnum.lastMerge = SDL_GetTicks();\r\n\t\t\tnum.style = style;\r\n\t\t\tnum.startPos = pos;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tFloatingNumber num {\r\n\t\tpos, offset, endOffset, text,\r\n\t\tstatic_cast<uint32_t>(SDL_GetTicks() + 2500),\r\n\t\tstatic_cast<uint32_t>(SDL_GetTicks()),\r\n\t\tstyle | UiFlags::Outlined, id, reverseDirection\r\n\t};\r\n\tFloatingQueue.push_back(num);\r\n}\r\n\r\nvoid DrawFloatingNumbers(const Surface &out, Point viewPosition, Displacement offset)\r\n{\r\n\tfor (auto &floatingNum : FloatingQueue) {\r\n\t\tDisplacement worldOffset = viewPosition - floatingNum.startPos;\r\n\t\tworldOffset = worldOffset.worldToScreen() + offset + Displacement { TILE_WIDTH / 2, -TILE_HEIGHT / 2 } + floatingNum.startOffset;\r\n\r\n\t\tif (*GetOptions().Graphics.zoom) {\r\n\t\t\tworldOffset *= 2;\r\n\t\t}\r\n\r\n\t\tPoint screenPosition { worldOffset.deltaX, worldOffset.deltaY };\r\n\r\n\t\tconst int lineWidth = GetLineWidth(floatingNum.text, GetGameFontSize(floatingNum.style));\r\n\t\tscreenPosition.x -= lineWidth / 2;\r\n\t\tconst uint32_t timeLeft = floatingNum.time - SDL_GetTicks();\r\n\t\tconst float mul = 1 - (timeLeft / 2500.0f);\r\n\t\tscreenPosition += floatingNum.endOffset * mul;\r\n\r\n\t\tDrawString(out, floatingNum.text, Rectangle { screenPosition, { lineWidth, 0 } },\r\n\t\t    { .flags = floatingNum.style });\r\n\t}\r\n\r\n\tClearExpiredNumbers();\r\n}\r\n\r\nvoid ClearFloatingNumbers()\r\n{\r\n\tsrand(static_cast<unsigned int>(time(nullptr)));\r\n\r\n\tFloatingQueue.clear();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/floatingnumbers.h",
    "content": "/**\r\n * @file floatingnumbers.h\r\n *\r\n * Adds floating numbers QoL feature\r\n */\r\n#pragma once\r\n\r\n#include <string>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid AddFloatingNumber(Point pos, Displacement offset, std::string text, UiFlags style, int id = 0, bool reverseDirection = false);\r\nvoid DrawFloatingNumbers(const Surface &out, Point viewPosition, Displacement offset);\r\nvoid ClearFloatingNumbers();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/itemlabels.cpp",
    "content": "#include \"itemlabels.h\"\r\n\r\n#include <algorithm>\r\n#include <cmath>\r\n#include <limits>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"cursor.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"gmenu.h\"\r\n#include \"inv.h\"\r\n#include \"options.h\"\r\n#include \"qol/stash.h\"\r\n#include \"stores.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct ItemLabel {\r\n\tint id, width;\r\n\tPoint pos;\r\n\tStringOrView text;\r\n};\r\n\r\nstd::vector<ItemLabel> labelQueue;\r\n\r\nbool highlightKeyPressed = false;\r\nbool isLabelHighlighted = false;\r\nstd::array<std::optional<int>, ITEMTYPES> labelCenterOffsets;\r\n\r\nconst int BorderX = 4; // minimal horizontal space between labels\r\nconst int BorderY = 2; // minimal vertical space between labels\r\nconst int MarginX = 2; // horizontal margins between text and edges of the label\r\n\r\n// Vertical space between the text and the edges of the label.\r\nint TextMarginTop() { return IsSmallFontTall() ? 1 : -1; }\r\nint TextMarginBottom() { return IsSmallFontTall() ? 1 : 3; }\r\n\r\n// The total height of the label box.\r\nint LabelHeight() { return (IsSmallFontTall() ? 16 : 11) + TextMarginBottom() + TextMarginTop(); }\r\n\r\n/**\r\n * @brief The set of used X coordinates for a certain Y coordinate.\r\n */\r\nclass UsedX {\r\npublic:\r\n\t[[nodiscard]] bool contains(int val) const\r\n\t{\r\n\t\treturn c_find(data_, val) != data_.end();\r\n\t}\r\n\r\n\tvoid insert(int val)\r\n\t{\r\n\t\tif (!contains(val))\r\n\t\t\tdata_.push_back(val);\r\n\t}\r\n\r\n\tvoid clear()\r\n\t{\r\n\t\tdata_.clear();\r\n\t}\r\n\r\nprivate:\r\n\tstd::vector<int> data_;\r\n};\r\n\r\n} // namespace\r\n\r\nvoid ToggleItemLabelHighlight()\r\n{\r\n\tGetOptions().Gameplay.showItemLabels.SetValue(!*GetOptions().Gameplay.showItemLabels);\r\n}\r\n\r\nvoid HighlightKeyPressed(bool pressed)\r\n{\r\n\thighlightKeyPressed = pressed;\r\n}\r\n\r\nbool IsItemLabelHighlighted()\r\n{\r\n\treturn isLabelHighlighted;\r\n}\r\n\r\nvoid ResetItemlabelHighlighted()\r\n{\r\n\tisLabelHighlighted = false;\r\n}\r\n\r\nbool IsHighlightingLabelsEnabled()\r\n{\r\n\treturn !IsPlayerInStore() && highlightKeyPressed != *GetOptions().Gameplay.showItemLabels;\r\n}\r\n\r\nvoid AddItemToLabelQueue(int id, Point position)\r\n{\r\n\tif (!IsHighlightingLabelsEnabled())\r\n\t\treturn;\r\n\tItem &item = Items[id];\r\n\r\n\tStringOrView textOnGround;\r\n\tif (item._itype == ItemType::Gold) {\r\n\t\ttextOnGround = fmt::format(fmt::runtime(_(\"{:s} gold\")), FormatInteger(item._ivalue));\r\n\t} else {\r\n\t\ttextOnGround = item.getName();\r\n\t}\r\n\r\n\tint nameWidth = GetLineWidth(textOnGround);\r\n\tnameWidth += MarginX * 2;\r\n\tconst int index = ItemCAnimTbl[item._iCurs];\r\n\tif (!labelCenterOffsets[index]) {\r\n\t\tconst auto [xBegin, xEnd] = ClxMeasureSolidHorizontalBounds((*item.AnimInfo.sprites)[item.AnimInfo.currentFrame]);\r\n\t\tlabelCenterOffsets[index].emplace((xBegin + xEnd) / 2);\r\n\t}\r\n\r\n\tposition.x += *labelCenterOffsets[index];\r\n\tposition.y -= TILE_HEIGHT;\r\n\tif (*GetOptions().Graphics.zoom) {\r\n\t\tposition *= 2;\r\n\t}\r\n\tposition.x -= nameWidth / 2;\r\n\tposition.y -= LabelHeight();\r\n\tlabelQueue.push_back(ItemLabel { id, nameWidth, position, std::move(textOnGround) });\r\n}\r\n\r\nbool IsMouseOverGameArea()\r\n{\r\n\tif ((IsRightPanelOpen()) && GetRightPanel().contains(MousePosition))\r\n\t\treturn false;\r\n\tif ((IsLeftPanelOpen()) && GetLeftPanel().contains(MousePosition))\r\n\t\treturn false;\r\n\tif (GetMainPanel().contains(MousePosition))\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid DrawItemNameLabels(const Surface &out)\r\n{\r\n\tconst Surface clippedOut = out.subregionY(0, gnViewportHeight);\r\n\tisLabelHighlighted = false;\r\n\tif (labelQueue.empty())\r\n\t\treturn;\r\n\tUsedX usedX;\r\n\tconst int labelHeight = LabelHeight();\r\n\tconst int labelMarginTop = TextMarginTop();\r\n\r\n\tfor (unsigned i = 0; i < labelQueue.size(); ++i) {\r\n\t\tusedX.clear();\r\n\r\n\t\tbool canShow;\r\n\t\tdo {\r\n\t\t\tcanShow = true;\r\n\t\t\tfor (unsigned j = 0; j < i; ++j) {\r\n\t\t\t\tItemLabel &a = labelQueue[i];\r\n\t\t\t\tconst ItemLabel &b = labelQueue[j];\r\n\t\t\t\tif (std::abs(b.pos.y - a.pos.y) < labelHeight + BorderY) {\r\n\t\t\t\t\tconst int widthA = a.width + BorderX + MarginX * 2;\r\n\t\t\t\t\tconst int widthB = b.width + BorderX + MarginX * 2;\r\n\t\t\t\t\tint newpos = b.pos.x;\r\n\t\t\t\t\tif (b.pos.x >= a.pos.x && b.pos.x - a.pos.x < widthA) {\r\n\t\t\t\t\t\tnewpos -= widthA;\r\n\t\t\t\t\t\tif (usedX.contains(newpos))\r\n\t\t\t\t\t\t\tnewpos = b.pos.x + widthB;\r\n\t\t\t\t\t} else if (b.pos.x < a.pos.x && a.pos.x - b.pos.x < widthB) {\r\n\t\t\t\t\t\tnewpos += widthB;\r\n\t\t\t\t\t\tif (usedX.contains(newpos))\r\n\t\t\t\t\t\t\tnewpos = b.pos.x - widthA;\r\n\t\t\t\t\t} else\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\tcanShow = false;\r\n\t\t\t\t\ta.pos.x = newpos;\r\n\t\t\t\t\tusedX.insert(newpos);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} while (!canShow);\r\n\t}\r\n\r\n\tfor (const ItemLabel &label : labelQueue) {\r\n\t\tconst Item &item = Items[label.id];\r\n\r\n\t\tif (MousePosition.x >= label.pos.x && MousePosition.x < label.pos.x + label.width\r\n\t\t    && MousePosition.y >= label.pos.y && MousePosition.y < label.pos.y + labelHeight) {\r\n\t\t\tif (!gmenu_is_active()\r\n\t\t\t    && PauseMode == 0\r\n\t\t\t    && !MyPlayerIsDead\r\n\t\t\t    && !IsPlayerInStore()\r\n\t\t\t    && IsMouseOverGameArea()\r\n\t\t\t    && LastPlayerAction == PlayerActionType::None) {\r\n\t\t\t\tisLabelHighlighted = true;\r\n\t\t\t\tcursPosition = item.position;\r\n\t\t\t\tpcursitem = label.id;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (pcursitem == label.id && !IsPlayerInStore())\r\n\t\t\tFillRect(clippedOut, label.pos.x, label.pos.y, label.width, labelHeight, PAL8_BLUE + 6);\r\n\t\telse\r\n\t\t\tDrawHalfTransparentRectTo(clippedOut, label.pos.x, label.pos.y, label.width, labelHeight);\r\n\t\tDrawString(clippedOut, label.text, { { label.pos.x + MarginX, label.pos.y + labelMarginTop }, { label.width, labelHeight } },\r\n\t\t    { .flags = item.getTextColor() });\r\n\t}\r\n\tlabelQueue.clear();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/itemlabels.h",
    "content": "/**\r\n * @file itemlabels.h\r\n *\r\n * Adds item labels QoL feature\r\n */\r\n#pragma once\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid ToggleItemLabelHighlight();\r\nvoid HighlightKeyPressed(bool pressed);\r\nbool IsItemLabelHighlighted();\r\nvoid ResetItemlabelHighlighted();\r\nbool IsHighlightingLabelsEnabled();\r\nvoid AddItemToLabelQueue(int id, Point position);\r\nvoid DrawItemNameLabels(const Surface &out);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/monhealthbar.cpp",
    "content": "/**\r\n * @file monhealthbar.cpp\r\n *\r\n * Adds monster health bar QoL feature\r\n */\r\n#include \"monhealthbar.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"cursor.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteList healthBox;\r\nOptionalOwnedClxSpriteList resistance;\r\nOptionalOwnedClxSpriteList health;\r\nOptionalOwnedClxSpriteList healthBlue;\r\nOptionalOwnedClxSpriteList playerExpTags;\r\n\r\nvoid OptionEnemyHealthBarChanged()\r\n{\r\n\tif (!gbRunGame)\r\n\t\treturn;\r\n\tif (*GetOptions().Gameplay.enemyHealthBar)\r\n\t\tInitMonsterHealthBar();\r\n\telse\r\n\t\tFreeMonsterHealthBar();\r\n}\r\n\r\nconst auto OptionChangeHandler = (GetOptions().Gameplay.enemyHealthBar.SetValueChangedCallback(OptionEnemyHealthBarChanged), true);\r\n\r\n} // namespace\r\n\r\nvoid InitMonsterHealthBar()\r\n{\r\n\tif (!*GetOptions().Gameplay.enemyHealthBar)\r\n\t\treturn;\r\n\r\n\thealthBox = LoadClx(\"data\\\\healthbox.clx\");\r\n\thealth = LoadClx(\"data\\\\health.clx\");\r\n\tresistance = LoadClx(\"data\\\\resistance.clx\");\r\n\tplayerExpTags = LoadClx(\"data\\\\monstertags.clx\");\r\n\r\n\tstd::array<uint8_t, 256> healthBlueTrn;\r\n\thealthBlueTrn[234] = 185;\r\n\thealthBlueTrn[235] = 186;\r\n\thealthBlueTrn[236] = 187;\r\n\thealthBlue = health->clone();\r\n\tClxApplyTrans(*healthBlue, healthBlueTrn.data());\r\n}\r\n\r\nvoid FreeMonsterHealthBar()\r\n{\r\n\thealthBlue = std::nullopt;\r\n\tplayerExpTags = std::nullopt;\r\n\tresistance = std::nullopt;\r\n\thealth = std::nullopt;\r\n\thealthBox = std::nullopt;\r\n}\r\n\r\nvoid DrawMonsterHealthBar(const Surface &out)\r\n{\r\n\tif (!*GetOptions().Gameplay.enemyHealthBar)\r\n\t\treturn;\r\n\r\n\tif (leveltype == DTYPE_TOWN)\r\n\t\treturn;\r\n\tif (pcursmonst == -1)\r\n\t\treturn;\r\n\r\n\tconst Monster &monster = Monsters[pcursmonst];\r\n\r\n\tconst int width = (*healthBox)[0].width();\r\n\tconst int barWidth = (*health)[0].width();\r\n\tconst int height = (*healthBox)[0].height();\r\n\tPoint position = { (gnScreenWidth - width) / 2, 18 };\r\n\r\n\tif (CanPanelsCoverView()) {\r\n\t\tif (IsRightPanelOpen())\r\n\t\t\tposition.x -= SidePanelSize.width / 2;\r\n\t\tif (IsLeftPanelOpen())\r\n\t\t\tposition.x += SidePanelSize.width / 2;\r\n\t}\r\n\r\n\tconst int border = 3;\r\n\r\n\tint multiplier = 0;\r\n\tint currLife = monster.hitPoints;\r\n\t// lifestealing monsters can reach HP exceeding their max\r\n\tif (monster.hitPoints > monster.maxHitPoints) {\r\n\t\tmultiplier = monster.hitPoints / monster.maxHitPoints;\r\n\t\tcurrLife = monster.hitPoints - monster.maxHitPoints * multiplier;\r\n\t\tif (currLife == 0 && multiplier > 0) {\r\n\t\t\tmultiplier--;\r\n\t\t\tcurrLife = monster.maxHitPoints;\r\n\t\t}\r\n\t}\r\n\r\n\tRenderClxSprite(out, (*healthBox)[0], position);\r\n\tDrawHalfTransparentRectTo(out, position.x + border, position.y + border, width - (border * 2), height - (border * 2));\r\n\tconst int barProgress = (barWidth * currLife) / monster.maxHitPoints;\r\n\tif (barProgress != 0) {\r\n\t\tRenderClxSprite(\r\n\t\t    out.subregion(position.x + border + 1, position.y + border + 1, barProgress, height - (border * 2) - 2),\r\n\t\t    (*(multiplier > 0 ? healthBlue : health))[0], { 0, 0 });\r\n\t}\r\n\r\n\tconstexpr auto GetBorderColor = [](MonsterClass monsterClass) {\r\n\t\tswitch (monsterClass) {\r\n\t\tcase MonsterClass::Undead:\r\n\t\t\treturn 248;\r\n\r\n\t\tcase MonsterClass::Demon:\r\n\t\t\treturn 232;\r\n\r\n\t\tcase MonsterClass::Animal:\r\n\t\t\treturn 150;\r\n\r\n\t\tdefault:\r\n\t\t\tapp_fatal(StrCat(\"Invalid monster class: \", static_cast<int>(monsterClass)));\r\n\t\t}\r\n\t};\r\n\r\n\tif (*GetOptions().Gameplay.showMonsterType) {\r\n\t\tconst Uint8 borderColor = GetBorderColor(monster.data().monsterClass);\r\n\t\tconst int borderWidth = width - (border * 2);\r\n\t\tUnsafeDrawHorizontalLine(out, { position.x + border, position.y + border }, borderWidth, borderColor);\r\n\t\tUnsafeDrawHorizontalLine(out, { position.x + border, position.y + height - border - 1 }, borderWidth, borderColor);\r\n\t\tconst int borderHeight = height - (border * 2) - 2;\r\n\t\tUnsafeDrawVerticalLine(out, { position.x + border, position.y + border + 1 }, borderHeight, borderColor);\r\n\t\tUnsafeDrawVerticalLine(out, { position.x + width - border - 1, position.y + border + 1 }, borderHeight, borderColor);\r\n\t}\r\n\r\n\tUiFlags style = UiFlags::AlignCenter | UiFlags::VerticalCenter;\r\n\tDrawString(out, monster.name(), { position + Displacement { -1, 1 }, { width, height } },\r\n\t    { .flags = style | UiFlags::ColorBlack });\r\n\tif (monster.isUnique())\r\n\t\tstyle |= UiFlags::ColorWhitegold;\r\n\telse if (monster.leader != Monster::NoLeader)\r\n\t\tstyle |= UiFlags::ColorBlue;\r\n\telse\r\n\t\tstyle |= UiFlags::ColorWhite;\r\n\tDrawString(out, monster.name(), { position, { width, height } },\r\n\t    { .flags = style });\r\n\r\n\tif (multiplier > 0)\r\n\t\tDrawString(out, StrCat(\"x\", multiplier), { position, { width - 2, height } },\r\n\t\t    { .flags = UiFlags::ColorWhite | UiFlags::AlignRight | UiFlags::VerticalCenter });\r\n\tif (monster.isUnique() || MonsterKillCounts[monster.type().type] >= 15) {\r\n\t\tconst monster_resistance immunes[] = { IMMUNE_MAGIC, IMMUNE_FIRE, IMMUNE_LIGHTNING };\r\n\t\tconst monster_resistance resists[] = { RESIST_MAGIC, RESIST_FIRE, RESIST_LIGHTNING };\r\n\r\n\t\tint resOffset = 5;\r\n\t\tfor (size_t i = 0; i < 3; i++) {\r\n\t\t\tif ((monster.resistance & immunes[i]) != 0) {\r\n\t\t\t\tRenderClxSprite(out, (*resistance)[i * 2 + 1], position + Displacement { resOffset, height - 6 });\r\n\t\t\t\tresOffset += (*resistance)[0].width() + 2;\r\n\t\t\t} else if ((monster.resistance & resists[i]) != 0) {\r\n\t\t\t\tRenderClxSprite(out, (*resistance)[i * 2], position + Displacement { resOffset, height - 6 });\r\n\t\t\t\tresOffset += (*resistance)[0].width() + 2;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (Players.size() > 1) {\r\n\t\tint tagOffset = 5;\r\n\t\tfor (size_t i = 0; i < Players.size(); i++) {\r\n\t\t\tif (((1U << i) & monster.whoHit) != 0) {\r\n\t\t\t\tRenderClxSprite(out, (*playerExpTags)[i + 1], position + Displacement { tagOffset, height - 31 });\r\n\t\t\t} else if (Players[i].plractive) {\r\n\t\t\t\tRenderClxSprite(out, (*playerExpTags)[0], position + Displacement { tagOffset, height - 31 });\r\n\t\t\t}\r\n\t\t\ttagOffset += (*playerExpTags)[0].width();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/monhealthbar.h",
    "content": "/**\r\n * @file monhealthbar.h\r\n *\r\n * Adds monster health bar QoL feature\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\n\r\nstruct Surface;\r\n\r\nvoid InitMonsterHealthBar();\r\nvoid FreeMonsterHealthBar();\r\n\r\nvoid DrawMonsterHealthBar(const Surface &out);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/stash.cpp",
    "content": "#include \"qol/stash.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_keyboard.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"DiabloUI/text_input.hpp\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"hwcursor.hpp\"\r\n#include \"inv.h\"\r\n#include \"minitext.h\"\r\n#include \"stores.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool IsStashOpen;\r\nStashStruct Stash;\r\nbool IsWithdrawGoldOpen;\r\n\r\nnamespace {\r\n\r\nconstexpr unsigned CountStashPages = 100;\r\nconstexpr unsigned LastStashPage = CountStashPages - 1;\r\n\r\nchar GoldWithdrawText[21];\r\nTextInputCursorState GoldWithdrawCursor;\r\nstd::optional<NumberInputState> GoldWithdrawInputState;\r\n\r\nconstexpr Size ButtonSize { 27, 16 };\r\n/** Contains mappings for the buttons in the stash (2 navigation buttons, withdraw gold buttons, 2 navigation buttons) */\r\nconstexpr Rectangle StashButtonRect[] = {\r\n\t// clang-format off\r\n\t{ {  19, 19 }, ButtonSize }, // 10 left\r\n\t{ {  56, 19 }, ButtonSize }, // 1 left\r\n\t{ {  93, 19 }, ButtonSize }, // withdraw gold\r\n\t{ { 242, 19 }, ButtonSize }, // 1 right\r\n\t{ { 279, 19 }, ButtonSize }  // 10 right\r\n\t// clang-format on\r\n};\r\n\r\nOptionalOwnedClxSpriteList StashPanelArt;\r\nOptionalOwnedClxSpriteList StashNavButtonArt;\r\n\r\n/**\r\n * @param page The stash page index.\r\n * @param position Position to add the item to.\r\n * @param stashListIndex The item's StashList index\r\n * @param itemSize Size of item\r\n */\r\nvoid AddItemToStashGrid(unsigned page, Point position, uint16_t stashListIndex, Size itemSize)\r\n{\r\n\tfor (const Point point : PointsInRectangle(Rectangle { position, itemSize })) {\r\n\t\tStash.stashGrids[page][point.x][point.y] = stashListIndex + 1;\r\n\t}\r\n}\r\n\r\nstd::optional<Point> FindTargetSlotUnderItemCursor(Point cursorPosition, Size itemSize)\r\n{\r\n\tfor (auto point : StashGridRange) {\r\n\t\tconst Rectangle cell {\r\n\t\t\tGetStashSlotCoord(point),\r\n\t\t\tInventorySlotSizeInPixels + 1\r\n\t\t};\r\n\r\n\t\tif (cell.contains(cursorPosition)) {\r\n\t\t\t// When trying to paste into the stash we need to determine the top left cell of the nearest area that could fit the item, not the slot under the center/hot pixel.\r\n\t\t\tif (itemSize.height <= 1 && itemSize.width <= 1) {\r\n\t\t\t\t// top left cell of a 1x1 item is the same cell as the hot pixel, no work to do\r\n\t\t\t\treturn point;\r\n\t\t\t}\r\n\t\t\t// Otherwise work out how far the central cell is from the top-left cell\r\n\t\t\tDisplacement hotPixelCellOffset = { (itemSize.width - 1) / 2, (itemSize.height - 1) / 2 };\r\n\t\t\t// For even dimension items we need to work out if the cursor is in the left/right (or top/bottom) half of the central cell and adjust the offset so the item lands in the area most covered by the cursor.\r\n\t\t\tif (itemSize.width % 2 == 0 && cell.contains(cursorPosition + Displacement { INV_SLOT_HALF_SIZE_PX, 0 })) {\r\n\t\t\t\t// hot pixel was in the left half of the cell, so we want to increase the offset to preference the column to the left\r\n\t\t\t\thotPixelCellOffset.deltaX++;\r\n\t\t\t}\r\n\t\t\tif (itemSize.height % 2 == 0 && cell.contains(cursorPosition + Displacement { 0, INV_SLOT_HALF_SIZE_PX })) {\r\n\t\t\t\t// hot pixel was in the top half of the cell, so we want to increase the offset to preference the row above\r\n\t\t\t\thotPixelCellOffset.deltaY++;\r\n\t\t\t}\r\n\t\t\t// Then work out the top left cell of the nearest area that could fit this item (as pasting on the edge of the stash would otherwise put it out of bounds)\r\n\t\t\tpoint.y = std::clamp(point.y - hotPixelCellOffset.deltaY, 0, StashGridSize.height - itemSize.height);\r\n\t\t\tpoint.x = std::clamp(point.x - hotPixelCellOffset.deltaX, 0, StashGridSize.width - itemSize.width);\r\n\t\t\treturn point;\r\n\t\t}\r\n\t}\r\n\r\n\treturn {};\r\n}\r\n\r\nbool IsItemAllowedInStash(const Item &item)\r\n{\r\n\treturn item._iMiscId != IMISC_ARENAPOT;\r\n}\r\n\r\nvoid CheckStashPaste(Point cursorPosition)\r\n{\r\n\tPlayer &player = *MyPlayer;\r\n\r\n\tif (!IsItemAllowedInStash(player.HoldItem))\r\n\t\treturn;\r\n\r\n\tif (player.HoldItem._itype == ItemType::Gold) {\r\n\t\tif (Stash.gold > std::numeric_limits<int>::max() - player.HoldItem._ivalue)\r\n\t\t\treturn;\r\n\t\tStash.gold += player.HoldItem._ivalue;\r\n\t\tplayer.HoldItem.clear();\r\n\t\tPlaySFX(SfxID::ItemGold);\r\n\t\tStash.dirty = true;\r\n\t\tNewCursor(CURSOR_HAND);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Size itemSize = GetInventorySize(player.HoldItem);\r\n\r\n\tstd::optional<Point> targetSlot = FindTargetSlotUnderItemCursor(cursorPosition, itemSize);\r\n\tif (!targetSlot)\r\n\t\treturn;\r\n\r\n\tconst Point firstSlot = *targetSlot;\r\n\r\n\t// Check that no more than 1 item is replaced by the move\r\n\tStashStruct::StashCell stashIndex = StashStruct::EmptyCell;\r\n\tfor (const Point point : PointsInRectangle(Rectangle { firstSlot, itemSize })) {\r\n\t\tconst StashStruct::StashCell iv = Stash.GetItemIdAtPosition(point);\r\n\t\tif (iv == StashStruct::EmptyCell || stashIndex == iv)\r\n\t\t\tcontinue;\r\n\t\tif (stashIndex == StashStruct::EmptyCell) {\r\n\t\t\tstashIndex = iv; // Found first item\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\treturn; // Found a second item\r\n\t}\r\n\r\n\tPlaySFX(ItemInvSnds[ItemCAnimTbl[player.HoldItem._iCurs]]);\r\n\r\n\t// Need to set the item anchor position to the bottom left so drawing code functions correctly.\r\n\tplayer.HoldItem.position = firstSlot + Displacement { 0, itemSize.height - 1 };\r\n\r\n\tif (stashIndex == StashStruct::EmptyCell) {\r\n\t\tStash.stashList.emplace_back(player.HoldItem.pop());\r\n\t\t// stashList will have at most 10 000 items, up to 65 535 are supported with uint16_t indexes\r\n\t\tstashIndex = static_cast<uint16_t>(Stash.stashList.size() - 1);\r\n\t} else {\r\n\t\t// swap the held item and whatever was in the stash at this position\r\n\t\tstd::swap(Stash.stashList[stashIndex], player.HoldItem);\r\n\t\t// then clear the space occupied by the old item\r\n\t\tfor (auto &row : Stash.GetCurrentGrid()) {\r\n\t\t\tfor (auto &itemId : row) {\r\n\t\t\t\tif (itemId - 1 == stashIndex)\r\n\t\t\t\t\titemId = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Finally mark the area now occupied by the pasted item in the current page/grid.\r\n\tAddItemToStashGrid(Stash.GetPage(), firstSlot, stashIndex, itemSize);\r\n\r\n\tStash.dirty = true;\r\n\r\n\tNewCursor(player.HoldItem);\r\n}\r\n\r\nvoid CheckStashCut(Point cursorPosition, bool automaticMove)\r\n{\r\n\tPlayer &player = *MyPlayer;\r\n\r\n\tCloseGoldWithdraw();\r\n\r\n\tPoint slot = InvalidStashPoint;\r\n\r\n\tfor (auto point : StashGridRange) {\r\n\t\tconst Rectangle cell {\r\n\t\t\tGetStashSlotCoord(point),\r\n\t\t\tInventorySlotSizeInPixels + 1\r\n\t\t};\r\n\r\n\t\t// check which inventory rectangle the mouse is in, if any\r\n\t\tif (cell.contains(cursorPosition)) {\r\n\t\t\tslot = point;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (slot == InvalidStashPoint) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tItem &holdItem = player.HoldItem;\r\n\tholdItem.clear();\r\n\r\n\tbool automaticallyMoved = false;\r\n\tconst bool automaticallyEquipped = false;\r\n\r\n\tconst StashStruct::StashCell iv = Stash.GetItemIdAtPosition(slot);\r\n\tif (iv != StashStruct::EmptyCell) {\r\n\t\tholdItem = Stash.stashList[iv];\r\n\t\tif (automaticMove) {\r\n\t\t\tif (CanBePlacedOnBelt(player, holdItem)) {\r\n\t\t\t\tautomaticallyMoved = AutoPlaceItemInBelt(player, holdItem, true, true);\r\n\t\t\t} else {\r\n\t\t\t\tautomaticallyMoved = AutoEquip(player, holdItem, true, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!automaticMove || automaticallyMoved) {\r\n\t\t\tStash.RemoveStashItem(iv);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!holdItem.isEmpty()) {\r\n\t\tCalcPlrInv(player, true);\r\n\t\tholdItem._iStatFlag = player.CanUseItem(holdItem);\r\n\t\tif (automaticallyEquipped) {\r\n\t\t\tPlaySFX(ItemInvSnds[ItemCAnimTbl[holdItem._iCurs]]);\r\n\t\t} else if (!automaticMove || automaticallyMoved) {\r\n\t\t\tPlaySFX(SfxID::GrabItem);\r\n\t\t}\r\n\r\n\t\tif (automaticMove) {\r\n\t\t\tif (!automaticallyMoved) {\r\n\t\t\t\tif (CanBePlacedOnBelt(player, holdItem)) {\r\n\t\t\t\t\tplayer.SaySpecific(HeroSpeech::IHaveNoRoom);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tplayer.SaySpecific(HeroSpeech::ICantDoThat);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tholdItem.clear();\r\n\t\t} else {\r\n\t\t\tNewCursor(holdItem);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid WithdrawGold(Player &player, int amount)\r\n{\r\n\tAddGoldToInventory(player, amount);\r\n\tStash.gold -= amount;\r\n\tStash.dirty = true;\r\n}\r\n\r\n} // namespace\r\n\r\nPoint GetStashSlotCoord(Point slot)\r\n{\r\n\tconstexpr int StashNextCell = INV_SLOT_SIZE_PX + 1; // spacing between each cell\r\n\r\n\treturn GetPanelPosition(UiPanels::Stash, slot * StashNextCell + Displacement { 17, 48 });\r\n}\r\n\r\nvoid FreeStashGFX()\r\n{\r\n\tStashNavButtonArt = std::nullopt;\r\n\tStashPanelArt = std::nullopt;\r\n}\r\n\r\nvoid InitStash()\r\n{\r\n\tif (!HeadlessMode) {\r\n\t\tStashPanelArt = LoadClx(\"data\\\\stash.clx\");\r\n\t\tStashNavButtonArt = LoadClx(\"data\\\\stashnavbtns.clx\");\r\n\t}\r\n}\r\n\r\nvoid TransferItemToInventory(Player &player, uint16_t itemId)\r\n{\r\n\tif (itemId == StashStruct::EmptyCell) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Item &item = Stash.stashList[itemId];\r\n\tif (item.isEmpty()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!AutoPlaceItemInInventory(player, item)) {\r\n\t\tplayer.SaySpecific(HeroSpeech::IHaveNoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySFX(ItemInvSnds[ItemCAnimTbl[item._iCurs]]);\r\n\r\n\tStash.RemoveStashItem(itemId);\r\n}\r\n\r\nint StashButtonPressed = -1;\r\n\r\nvoid CheckStashButtonRelease(Point mousePosition)\r\n{\r\n\tif (StashButtonPressed == -1)\r\n\t\treturn;\r\n\r\n\tRectangle stashButton = StashButtonRect[StashButtonPressed];\r\n\tstashButton.position = GetPanelPosition(UiPanels::Stash, stashButton.position);\r\n\tif (stashButton.contains(mousePosition)) {\r\n\t\tswitch (StashButtonPressed) {\r\n\t\tcase 0:\r\n\t\t\tStash.PreviousPage(10);\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tStash.PreviousPage();\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tStartGoldWithdraw();\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tStash.NextPage();\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\t\tStash.NextPage(10);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tStashButtonPressed = -1;\r\n}\r\n\r\nvoid CheckStashButtonPress(Point mousePosition)\r\n{\r\n\tRectangle stashButton;\r\n\r\n\tfor (int i = 0; i < 5; i++) {\r\n\t\tstashButton = StashButtonRect[i];\r\n\t\tstashButton.position = GetPanelPosition(UiPanels::Stash, stashButton.position);\r\n\t\tif (stashButton.contains(mousePosition)) {\r\n\t\t\tStashButtonPressed = i;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tStashButtonPressed = -1;\r\n}\r\n\r\nvoid DrawStash(const Surface &out)\r\n{\r\n\tRenderClxSprite(out, (*StashPanelArt)[0], GetPanelPosition(UiPanels::Stash));\r\n\r\n\tif (StashButtonPressed != -1) {\r\n\t\tconst Point stashButton = GetPanelPosition(UiPanels::Stash, StashButtonRect[StashButtonPressed].position);\r\n\t\tRenderClxSprite(out, (*StashNavButtonArt)[StashButtonPressed], stashButton);\r\n\t}\r\n\r\n\tconstexpr Displacement offset { 0, INV_SLOT_SIZE_PX - 1 };\r\n\r\n\tfor (auto slot : StashGridRange) {\r\n\t\tconst StashStruct::StashCell itemId = Stash.GetItemIdAtPosition(slot);\r\n\t\tif (itemId == StashStruct::EmptyCell) {\r\n\t\t\tcontinue; // No item in the given slot\r\n\t\t}\r\n\t\tconst Item &item = Stash.stashList[itemId];\r\n\t\tInvDrawSlotBack(out, GetStashSlotCoord(slot) + offset, InventorySlotSizeInPixels, item._iMagical);\r\n\t}\r\n\r\n\tfor (auto slot : StashGridRange) {\r\n\t\tconst StashStruct::StashCell itemId = Stash.GetItemIdAtPosition(slot);\r\n\t\tif (itemId == StashStruct::EmptyCell) {\r\n\t\t\tcontinue; // No item in the given slot\r\n\t\t}\r\n\r\n\t\tconst Item &item = Stash.stashList[itemId];\r\n\t\tif (item.position != slot) {\r\n\t\t\tcontinue; // Not the first slot of the item\r\n\t\t}\r\n\r\n\t\tconst int frame = item._iCurs + CURSOR_FIRSTITEM;\r\n\r\n\t\tconst Point position = GetStashSlotCoord(item.position) + offset;\r\n\t\tconst ClxSprite sprite = GetInvItemSprite(frame);\r\n\r\n\t\tif (pcursstashitem == itemId) {\r\n\t\t\tconst uint8_t color = GetOutlineColor(item, true);\r\n\t\t\tClxDrawOutline(out, color, position, sprite);\r\n\t\t}\r\n\r\n\t\tDrawItem(item, out, position, sprite);\r\n\t}\r\n\r\n\tconst Point position = GetPanelPosition(UiPanels::Stash);\r\n\tconst UiFlags style = UiFlags::VerticalCenter | UiFlags::ColorWhite;\r\n\tconst int textboxHeight = 13;\r\n\r\n\tDrawString(out, StrCat(Stash.GetPage() + 1), { position + Displacement { 132, 0 }, { 57, textboxHeight } },\r\n\t    { .flags = UiFlags::AlignCenter | style });\r\n\tDrawString(out, FormatInteger(Stash.gold), { position + Displacement { 122, 19 }, { 107, textboxHeight } },\r\n\t    { .flags = UiFlags::AlignRight | style });\r\n}\r\n\r\nvoid CheckStashItem(Point mousePosition, bool isShiftHeld, bool isCtrlHeld)\r\n{\r\n\tif (!MyPlayer->HoldItem.isEmpty()) {\r\n\t\tCheckStashPaste(mousePosition);\r\n\t} else if (isCtrlHeld) {\r\n\t\tTransferItemToInventory(*MyPlayer, pcursstashitem);\r\n\t} else {\r\n\t\tCheckStashCut(mousePosition, isShiftHeld);\r\n\t}\r\n}\r\n\r\nuint16_t CheckStashHLight(Point mousePosition)\r\n{\r\n\tPoint slot = InvalidStashPoint;\r\n\tfor (auto point : StashGridRange) {\r\n\t\tconst Rectangle cell {\r\n\t\t\tGetStashSlotCoord(point),\r\n\t\t\tInventorySlotSizeInPixels + 1\r\n\t\t};\r\n\r\n\t\tif (cell.contains(mousePosition)) {\r\n\t\t\tslot = point;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (slot == InvalidStashPoint)\r\n\t\treturn -1;\r\n\r\n\tInfoColor = UiFlags::ColorWhite;\r\n\r\n\tconst StashStruct::StashCell itemId = Stash.GetItemIdAtPosition(slot);\r\n\tif (itemId == StashStruct::EmptyCell) {\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tconst Item &item = Stash.stashList[itemId];\r\n\tif (item.isEmpty()) {\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tInfoColor = item.getTextColor();\r\n\tInfoString = item.getName();\r\n\tFloatingInfoString = item.getName();\r\n\tif (item._iIdentified) {\r\n\t\tPrintItemDetails(item);\r\n\t} else {\r\n\t\tPrintItemDur(item);\r\n\t}\r\n\r\n\treturn itemId;\r\n}\r\n\r\nbool UseStashItem(uint16_t c)\r\n{\r\n\tif (MyPlayer->_pInvincible && MyPlayer->hasNoLife())\r\n\t\treturn true;\r\n\tif (pcurs != CURSOR_HAND)\r\n\t\treturn true;\r\n\tif (IsPlayerInStore())\r\n\t\treturn true;\r\n\r\n\tItem *item = &Stash.stashList[c];\r\n\r\n\tconstexpr int SpeechDelay = 10;\r\n\tif (item->IDidx == IDI_MUSHROOM) {\r\n\t\tMyPlayer->Say(HeroSpeech::NowThatsOneBigMushroom, SpeechDelay);\r\n\t\treturn true;\r\n\t}\r\n\tif (item->IDidx == IDI_FUNGALTM) {\r\n\t\tPlaySFX(SfxID::ItemBook);\r\n\t\tMyPlayer->Say(HeroSpeech::ThatDidntDoAnything, SpeechDelay);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (!item->isUsable())\r\n\t\treturn false;\r\n\r\n\tif (!MyPlayer->CanUseItem(*item)) {\r\n\t\tMyPlayer->Say(HeroSpeech::ICantUseThisYet);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tCloseGoldWithdraw();\r\n\r\n\tif (item->isScroll()) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (item->_iMiscId > IMISC_RUNEFIRST && item->_iMiscId < IMISC_RUNELAST && leveltype == DTYPE_TOWN) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (item->_iMiscId == IMISC_BOOK)\r\n\t\tPlaySFX(SfxID::ReadBook);\r\n\telse\r\n\t\tPlaySFX(ItemInvSnds[ItemCAnimTbl[item->_iCurs]]);\r\n\r\n\tUseItem(*MyPlayer, item->_iMiscId, item->_iSpell, -1);\r\n\r\n\tif (Stash.stashList[c]._iMiscId == IMISC_MAPOFDOOM)\r\n\t\treturn true;\r\n\tif (Stash.stashList[c]._iMiscId == IMISC_NOTE) {\r\n\t\tInitQTextMsg(TEXT_BOOK9);\r\n\t\tCloseInventory();\r\n\t\treturn true;\r\n\t}\r\n\tStash.RemoveStashItem(c);\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid StashStruct::RemoveStashItem(StashStruct::StashCell iv)\r\n{\r\n\t// Iterate through stashGrid and remove every reference to item\r\n\tfor (auto &row : Stash.GetCurrentGrid()) {\r\n\t\tfor (StashStruct::StashCell &itemId : row) {\r\n\t\t\tif (itemId - 1 == iv) {\r\n\t\t\t\titemId = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (stashList.empty()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\t// If the item at the end of stash array isn't the one we removed, we need to swap its position in the array with the removed item\r\n\tconst StashStruct::StashCell lastItemIndex = static_cast<StashStruct::StashCell>(stashList.size() - 1);\r\n\tif (lastItemIndex != iv) {\r\n\t\tstashList[iv] = stashList[lastItemIndex];\r\n\r\n\t\tfor (auto &[_, grid] : Stash.stashGrids) {\r\n\t\t\tfor (auto &row : grid) {\r\n\t\t\t\tfor (StashStruct::StashCell &itemId : row) {\r\n\t\t\t\t\tif (itemId == lastItemIndex + 1) {\r\n\t\t\t\t\t\titemId = iv + 1;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tstashList.pop_back();\r\n\tStash.dirty = true;\r\n}\r\n\r\nvoid StashStruct::SetPage(unsigned newPage)\r\n{\r\n\tpage = std::min(newPage, LastStashPage);\r\n\tdirty = true;\r\n}\r\n\r\nvoid StashStruct::NextPage(unsigned offset)\r\n{\r\n\tif (page <= LastStashPage) {\r\n\t\tpage += std::min(offset, LastStashPage - page);\r\n\t} else {\r\n\t\tpage = LastStashPage;\r\n\t}\r\n\tdirty = true;\r\n}\r\n\r\nvoid StashStruct::PreviousPage(unsigned offset)\r\n{\r\n\tif (page <= LastStashPage) {\r\n\t\tpage -= std::min(offset, page);\r\n\t} else {\r\n\t\tpage = LastStashPage;\r\n\t}\r\n\tdirty = true;\r\n}\r\n\r\nvoid StashStruct::RefreshItemStatFlags()\r\n{\r\n\tfor (auto &item : Stash.stashList) {\r\n\t\titem.updateRequiredStatsCacheForPlayer(*MyPlayer);\r\n\t}\r\n}\r\n\r\nvoid StartGoldWithdraw()\r\n{\r\n\tCloseGoldDrop();\r\n\r\n\tif (ChatFlag)\r\n\t\tResetChat();\r\n\r\n\tconst Point start = GetPanelPosition(UiPanels::Stash, { 67, 128 });\r\n\tSDL_Rect rect = MakeSdlRect(start.x, start.y, 180, 20);\r\n\tSDL_SetTextInputArea(ghMainWnd, &rect, /*cursor=*/0);\r\n\r\n\tIsWithdrawGoldOpen = true;\r\n\tGoldWithdrawText[0] = '\\0';\r\n\tGoldWithdrawInputState.emplace(NumberInputState::Options {\r\n\t    .textOptions {\r\n\t        .value = GoldWithdrawText,\r\n\t        .cursor = &GoldWithdrawCursor,\r\n\t        .maxLength = sizeof(GoldWithdrawText) - 1,\r\n\t    },\r\n\t    .min = 0,\r\n\t    .max = std::min(RoomForGold(), Stash.gold),\r\n\t});\r\n\tSDLC_StartTextInput(ghMainWnd);\r\n}\r\n\r\nvoid WithdrawGoldKeyPress(SDL_Keycode vkey)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer.hasNoLife()) {\r\n\t\tCloseGoldWithdraw();\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (vkey) {\r\n\tcase SDLK_RETURN:\r\n\tcase SDLK_KP_ENTER:\r\n\t\tif (const int value = GoldWithdrawInputState->value(); value != 0) {\r\n\t\t\tWithdrawGold(myPlayer, value);\r\n\t\t\tPlaySFX(SfxID::ItemGold);\r\n\t\t}\r\n\t\tCloseGoldWithdraw();\r\n\t\tbreak;\r\n\tcase SDLK_ESCAPE:\r\n\t\tCloseGoldWithdraw();\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid DrawGoldWithdraw(const Surface &out)\r\n{\r\n\tif (!IsWithdrawGoldOpen) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst std::string_view amountText = GoldWithdrawText;\r\n\tconst TextInputCursorState &cursor = GoldWithdrawCursor;\r\n\r\n\tconst int dialogX = 30;\r\n\r\n\tClxDraw(out, GetPanelPosition(UiPanels::Stash, { dialogX, 178 }), (*GoldBoxBuffer)[0]);\r\n\r\n\t// Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words\r\n\tconst std::string wrapped = WordWrapString(_(\"How many gold pieces do you want to withdraw?\"), 200);\r\n\r\n\t// The split gold dialog is roughly 4 lines high, but we need at least one line for the player to input an amount.\r\n\t// Using a clipping region 50 units high (approx 3 lines with a lineheight of 17) to ensure there is enough room left\r\n\t//  for the text entered by the player.\r\n\tDrawString(out, wrapped, { GetPanelPosition(UiPanels::Stash, { dialogX + 31, 75 }), { 200, 50 } },\r\n\t    { .flags = UiFlags::ColorWhitegold | UiFlags::AlignCenter, .lineHeight = 17 });\r\n\r\n\t// Even a ten digit amount of gold only takes up about half a line. There's no need to wrap or clip text here so we\r\n\t// use the Point form of DrawString.\r\n\tDrawString(out, amountText, GetPanelPosition(UiPanels::Stash, { dialogX + 37, 128 }),\r\n\t    {\r\n\t        .flags = UiFlags::ColorWhite | UiFlags::PentaCursor,\r\n\t        .cursorPosition = static_cast<int>(cursor.position),\r\n\t        .highlightRange = { static_cast<int>(cursor.selection.begin), static_cast<int>(cursor.selection.end) },\r\n\t    });\r\n}\r\n\r\nvoid CloseGoldWithdraw()\r\n{\r\n\tif (!IsWithdrawGoldOpen)\r\n\t\treturn;\r\n\tSDLC_StopTextInput(ghMainWnd);\r\n\tIsWithdrawGoldOpen = false;\r\n\tGoldWithdrawInputState = std::nullopt;\r\n}\r\n\r\nbool HandleGoldWithdrawTextInputEvent(const SDL_Event &event)\r\n{\r\n\treturn HandleNumberInputEvent(event, *GoldWithdrawInputState);\r\n}\r\n\r\nbool AutoPlaceItemInStash(Player &player, const Item &item, bool persistItem)\r\n{\r\n\tif (!IsItemAllowedInStash(item))\r\n\t\treturn false;\r\n\r\n\tif (item._itype == ItemType::Gold) {\r\n\t\tif (Stash.gold > std::numeric_limits<int>::max() - item._ivalue)\r\n\t\t\treturn false;\r\n\t\tif (persistItem) {\r\n\t\t\tStash.gold += item._ivalue;\r\n\t\t\tStash.dirty = true;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconst Size itemSize = GetInventorySize(item);\r\n\r\n\t// Try to add the item to the current active page and if it's not possible move forward\r\n\tfor (unsigned pageCounter = 0; pageCounter < CountStashPages; pageCounter++) {\r\n\t\tunsigned pageIndex = Stash.GetPage() + pageCounter;\r\n\t\t// Wrap around if needed\r\n\t\tif (pageIndex >= CountStashPages)\r\n\t\t\tpageIndex -= CountStashPages;\r\n\t\t// Search all possible position in stash grid\r\n\t\tfor (auto stashPosition : PointsInRectangle(Rectangle { { 0, 0 }, Size { 10 - (itemSize.width - 1), 10 - (itemSize.height - 1) } })) {\r\n\t\t\t// Check that all needed slots are free\r\n\t\t\tbool isSpaceFree = true;\r\n\t\t\tfor (auto itemPoint : PointsInRectangle(Rectangle { stashPosition, itemSize })) {\r\n\t\t\t\tconst uint16_t iv = Stash.stashGrids[pageIndex][itemPoint.x][itemPoint.y];\r\n\t\t\t\tif (iv != 0) {\r\n\t\t\t\t\tisSpaceFree = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!isSpaceFree)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (persistItem) {\r\n\t\t\t\tStash.stashList.push_back(item);\r\n\t\t\t\tconst uint16_t stashIndex = static_cast<uint16_t>(Stash.stashList.size() - 1);\r\n\t\t\t\tStash.stashList[stashIndex].position = stashPosition + Displacement { 0, itemSize.height - 1 };\r\n\t\t\t\tAddItemToStashGrid(pageIndex, stashPosition, stashIndex, itemSize);\r\n\t\t\t\tStash.dirty = true;\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/stash.h",
    "content": "/**\r\n * @file qol/stash.h\r\n *\r\n * Interface of player stash.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"items.h\"\r\n\r\nnamespace devilution {\r\n\r\nclass StashStruct {\r\npublic:\r\n\tusing StashCell = uint16_t;\r\n\tusing StashGrid = std::array<std::array<StashCell, 10>, 10>;\r\n\tstatic constexpr StashCell EmptyCell = -1;\r\n\r\n\tvoid RemoveStashItem(StashCell iv);\r\n\tankerl::unordered_dense::map<unsigned, StashGrid> stashGrids;\r\n\tstd::vector<Item> stashList;\r\n\tint gold;\r\n\tbool dirty = false;\r\n\r\n\tunsigned GetPage() const\r\n\t{\r\n\t\treturn page;\r\n\t}\r\n\r\n\tStashGrid &GetCurrentGrid()\r\n\t{\r\n\t\treturn stashGrids[GetPage()];\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns the 0-based index of the item at the specified position, or EmptyCell if no item occupies that slot\r\n\t * @param gridPosition x,y coordinate of the current stash page\r\n\t * @return a value which can be used to index into stashList or StashStruct::EmptyCell\r\n\t */\r\n\tStashCell GetItemIdAtPosition(Point gridPosition)\r\n\t{\r\n\t\t// Because StashCell is an unsigned type we can let this underflow\r\n\t\treturn GetCurrentGrid()[gridPosition.x][gridPosition.y] - 1;\r\n\t}\r\n\r\n\tbool IsItemAtPosition(Point gridPosition)\r\n\t{\r\n\t\treturn GetItemIdAtPosition(gridPosition) != EmptyCell;\r\n\t}\r\n\r\n\tvoid SetPage(unsigned newPage);\r\n\tvoid NextPage(unsigned offset = 1);\r\n\tvoid PreviousPage(unsigned offset = 1);\r\n\r\n\t/** @brief Updates _iStatFlag for all stash items. */\r\n\tvoid RefreshItemStatFlags();\r\n\r\nprivate:\r\n\t/** Current Page */\r\n\tunsigned page;\r\n};\r\n\r\nconstexpr Point InvalidStashPoint { -1, -1 };\r\n\r\nextern bool IsStashOpen;\r\nextern StashStruct Stash;\r\n\r\nextern bool IsWithdrawGoldOpen;\r\nextern int WithdrawGoldValue;\r\n\r\ninline constexpr Size StashGridSize { 10, 10 };\r\ninline constexpr PointsInRectangle<int> StashGridRange { { { 0, 0 }, StashGridSize } };\r\n\r\nPoint GetStashSlotCoord(Point slot);\r\nvoid InitStash();\r\nvoid FreeStashGFX();\r\nvoid TransferItemToInventory(Player &player, uint16_t itemId);\r\n/**\r\n * @brief Render the inventory panel to the given buffer.\r\n */\r\nvoid DrawStash(const Surface &out);\r\nvoid CheckStashItem(Point mousePosition, bool isShiftHeld = false, bool isCtrlHeld = false);\r\nbool UseStashItem(uint16_t cii);\r\nuint16_t CheckStashHLight(Point mousePosition);\r\nvoid CheckStashButtonRelease(Point mousePosition);\r\nvoid CheckStashButtonPress(Point mousePosition);\r\n\r\nvoid StartGoldWithdraw();\r\nvoid WithdrawGoldKeyPress(SDL_Keycode vkey);\r\nvoid DrawGoldWithdraw(const Surface &out);\r\nvoid CloseGoldWithdraw();\r\nbool HandleGoldWithdrawTextInputEvent(const SDL_Event &event);\r\n\r\n/**\r\n * @brief Checks whether the given item can be placed on the specified player's stash.\r\n * If 'persistItem' is 'True', the item is also placed in the inventory.\r\n * @param player The player to check.\r\n * @param item The item to be checked.\r\n * @param persistItem Pass 'True' to actually place the item in the inventory. The default is 'False'.\r\n * @return 'True' in case the item can be placed on the player's inventory and 'False' otherwise.\r\n */\r\nbool AutoPlaceItemInStash(Player &player, const Item &item, bool persistItem);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/xpbar.cpp",
    "content": "/**\r\n * @file xpbar.cpp\r\n *\r\n * Adds XP bar QoL feature\r\n */\r\n#include \"xpbar.h\"\r\n\r\n#include <array>\r\n#include <cstdint>\r\n\r\n#include <fmt/core.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"options.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconstexpr int BarWidth = 307;\r\n\r\nusing ColorGradient = std::array<Uint8, 12>;\r\nconstexpr ColorGradient GoldGradient = { 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8, 0xC7, 0xC6, 0xC5, 0xC4 };\r\nconstexpr ColorGradient SilverGradient = { 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3 };\r\n\r\nconstexpr int BackWidth = 313;\r\nconstexpr int BackHeight = 9;\r\n\r\nOptionalOwnedClxSpriteList xpbarArt;\r\n\r\nvoid DrawBar(const Surface &out, Point screenPosition, int width, const ColorGradient &gradient)\r\n{\r\n\tUnsafeDrawHorizontalLine(out, screenPosition + Displacement { 0, 1 }, width, gradient[gradient.size() * 3 / 4 - 1]);\r\n\tUnsafeDrawHorizontalLine(out, screenPosition + Displacement { 0, 2 }, width, gradient[gradient.size() - 1]);\r\n\tUnsafeDrawHorizontalLine(out, screenPosition + Displacement { 0, 3 }, width, gradient[gradient.size() / 2 - 1]);\r\n}\r\n\r\nvoid DrawEndCap(const Surface &out, Point point, int idx, const ColorGradient &gradient)\r\n{\r\n\tout.SetPixel({ point.x, point.y + 1 }, gradient[idx * 3 / 4]);\r\n\tout.SetPixel({ point.x, point.y + 2 }, gradient[idx]);\r\n\tout.SetPixel({ point.x, point.y + 3 }, gradient[idx / 2]);\r\n}\r\n\r\nvoid OptionExperienceBarChanged()\r\n{\r\n\tif (!gbRunGame)\r\n\t\treturn;\r\n\tif (*GetOptions().Gameplay.experienceBar)\r\n\t\tInitXPBar();\r\n\telse\r\n\t\tFreeXPBar();\r\n}\r\n\r\nconst auto OptionChangeHandler = (GetOptions().Gameplay.experienceBar.SetValueChangedCallback(OptionExperienceBarChanged), true);\r\n\r\n} // namespace\r\n\r\nvoid InitXPBar()\r\n{\r\n\tif (*GetOptions().Gameplay.experienceBar) {\r\n\t\txpbarArt = LoadClx(\"data\\\\xpbar.clx\");\r\n\t}\r\n}\r\n\r\nvoid FreeXPBar()\r\n{\r\n\txpbarArt = std::nullopt;\r\n}\r\n\r\nvoid DrawXPBar(const Surface &out)\r\n{\r\n\tif (!*GetOptions().Gameplay.experienceBar || ChatFlag)\r\n\t\treturn;\r\n\r\n\tconst Player &player = *MyPlayer;\r\n\tconst Rectangle &mainPanel = GetMainPanel();\r\n\r\n\tconst Point back = { mainPanel.position.x + mainPanel.size.width / 2 - 155, mainPanel.position.y + mainPanel.size.height - 11 };\r\n\tconst Point position = back + Displacement { 3, 2 };\r\n\r\n\tRenderClxSprite(out, (*xpbarArt)[0], back);\r\n\r\n\tif (player.isMaxCharacterLevel()) {\r\n\t\t// Draw a nice golden bar for max level characters.\r\n\t\tDrawBar(out, position, BarWidth, GoldGradient);\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst uint8_t charLevel = player.getCharacterLevel();\r\n\r\n\tconst uint64_t prevXp = GetNextExperienceThresholdForLevel(charLevel - 1);\r\n\tif (player._pExperience < prevXp)\r\n\t\treturn;\r\n\r\n\tconst uint64_t prevXpDelta1 = player._pExperience - prevXp;\r\n\tconst uint64_t prevXpDelta = GetNextExperienceThresholdForLevel(charLevel) - prevXp;\r\n\tconst uint64_t fullBar = BarWidth * prevXpDelta1 / prevXpDelta;\r\n\r\n\t// Figure out how much to fill the last pixel of the XP bar, to make it gradually appear with gained XP\r\n\tconst uint64_t onePx = prevXpDelta / BarWidth + 1;\r\n\tconst uint64_t lastFullPx = fullBar * prevXpDelta / BarWidth;\r\n\r\n\tconst uint64_t fade = (prevXpDelta1 - lastFullPx) * (SilverGradient.size() - 1) / onePx;\r\n\r\n\t// Draw beginning of bar full brightness\r\n\tDrawBar(out, position, static_cast<int>(fullBar), SilverGradient);\r\n\r\n\t// End pixels appear gradually\r\n\tDrawEndCap(out, position + Displacement { static_cast<int>(fullBar), 0 }, static_cast<int>(fade), SilverGradient);\r\n}\r\n\r\nbool CheckXPBarInfo()\r\n{\r\n\tif (!*GetOptions().Gameplay.experienceBar)\r\n\t\treturn false;\r\n\tconst Rectangle &mainPanel = GetMainPanel();\r\n\r\n\tconst int backX = mainPanel.position.x + mainPanel.size.width / 2 - 155;\r\n\tconst int backY = mainPanel.position.y + mainPanel.size.height - 11;\r\n\r\n\tif (MousePosition.x < backX || MousePosition.x >= backX + BackWidth || MousePosition.y < backY || MousePosition.y >= backY + BackHeight)\r\n\t\treturn false;\r\n\r\n\tconst Player &player = *MyPlayer;\r\n\r\n\tconst uint8_t charLevel = player.getCharacterLevel();\r\n\r\n\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Level {:d}\")), charLevel));\r\n\r\n\tif (player.isMaxCharacterLevel()) {\r\n\t\t// Show a maximum level indicator for max level players.\r\n\t\tInfoColor = UiFlags::ColorWhitegold;\r\n\r\n\t\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Experience: {:s}\")), FormatInteger(player._pExperience)));\r\n\t\tAddInfoBoxString(_(\"Maximum Level\"));\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\tInfoColor = UiFlags::ColorWhite;\r\n\r\n\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Experience: {:s}\")), FormatInteger(player._pExperience)));\r\n\tconst uint32_t nextExperienceThreshold = player.getNextExperienceThreshold();\r\n\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"Next Level: {:s}\")), FormatInteger(nextExperienceThreshold)));\r\n\tAddInfoBoxString(fmt::format(fmt::runtime(_(\"{:s} to Level {:d}\")), FormatInteger(nextExperienceThreshold - player._pExperience), charLevel + 1));\r\n\r\n\treturn true;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/qol/xpbar.h",
    "content": "/**\r\n * @file xpbar.h\r\n *\r\n * Adds XP bar QoL feature\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\n\r\nstruct Surface;\r\n\r\nvoid InitXPBar();\r\nvoid FreeXPBar();\r\n\r\nvoid DrawXPBar(const Surface &out);\r\nbool CheckXPBarInfo();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/quests/validation.cpp",
    "content": "/**\r\n * @file quests/validation.cpp\r\n *\r\n * Implementation of functions for validation of quest data.\r\n */\r\n\r\n#include \"quests/validation.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#include \"quests.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nbool IsQuestDeltaValid(quest_id qidx, quest_state qstate, uint8_t qlog, int16_t qmsg)\r\n{\r\n\tif (IsNoneOf(qlog, 0, 1))\r\n\t\treturn false;\r\n\r\n\tif (qmsg < 0 || static_cast<size_t>(qmsg) >= Speeches.size())\r\n\t\treturn false;\r\n\r\n\tswitch (qstate) {\r\n\tcase QUEST_NOTAVAIL:\r\n\tcase QUEST_INIT:\r\n\tcase QUEST_ACTIVE:\r\n\tcase QUEST_DONE:\r\n\t\treturn true;\r\n\r\n\tcase QUEST_HIVE_TEASE1:\r\n\tcase QUEST_HIVE_TEASE2:\r\n\tcase QUEST_HIVE_ACTIVE:\r\n\t\treturn qidx == Q_JERSEY;\r\n\r\n\tcase QUEST_HIVE_DONE:\r\n\t\treturn IsAnyOf(qidx, Q_FARMER, Q_JERSEY);\r\n\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/quests/validation.hpp",
    "content": "/**\r\n * @file quests/validation.hpp\r\n *\r\n * Interface of functions for validation of quest data.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"quests.h\"\r\n#include \"tables/objdat.h\"\r\n\r\nnamespace devilution {\r\n\r\nbool IsQuestDeltaValid(quest_id qidx, quest_state qstate, uint8_t qlog, int16_t qmsg);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/quests.cpp",
    "content": "/**\r\n * @file quests.cpp\r\n *\r\n * Implementation of functionality for handling quests.\r\n */\r\n#include \"quests.h\"\r\n\r\n#include <cstdint>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"control/control.hpp\"\r\n#include \"cursor.h\"\r\n#include \"data/file.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"levels/town.h\"\r\n#include \"levels/trigs.h\"\r\n#include \"minitext.h\"\r\n#include \"missiles.h\"\r\n#include \"monster.h\"\r\n#include \"options.h\"\r\n#include \"panels/ui_panels.hpp\"\r\n#include \"stores.h\"\r\n#include \"tables/townerdat.hpp\"\r\n#include \"towners.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nbool QuestLogIsOpen;\r\nOptionalOwnedClxSpriteList pQLogCel;\r\n/** Contains the quests of the current game. */\r\nQuest Quests[MAXQUESTS];\r\nPoint ReturnLvlPosition;\r\ndungeon_type ReturnLevelType;\r\nint ReturnLevel;\r\n\r\n/** Contains the data related to each quest_id. */\r\nstd::vector<QuestData> QuestsData;\r\n\r\nnamespace {\r\n\r\nint WaterDone;\r\n\r\n/** Indices of quests to display in quest log window. `FirstFinishedQuest` are active quests the rest are completed */\r\nquest_id EncounteredQuests[MAXQUESTS];\r\n/** Overall number of EncounteredQuests entries */\r\nint EncounteredQuestCount;\r\n/** First (nonselectable) finished quest in list */\r\nint FirstFinishedQuest;\r\n/** Currently selected quest list item */\r\nint SelectedQuest;\r\n\r\nconstexpr Rectangle InnerPanel { { 32, 26 }, { 280, 300 } };\r\nconstexpr int LineHeight = 12;\r\nconstexpr int MaxSpacing = LineHeight * 2;\r\nint ListYOffset;\r\nint LineSpacing;\r\n/** The number of pixels to move finished quest, to separate them from the active ones */\r\nint FinishedQuestOffset;\r\n\r\nconst char *const QuestTriggerNames[5] = {\r\n\tN_(/* TRANSLATORS: Quest Map*/ \"King Leoric's Tomb\"),\r\n\tN_(/* TRANSLATORS: Quest Map*/ \"The Chamber of Bone\"),\r\n\tN_(/* TRANSLATORS: Quest Map*/ \"Maze\"),\r\n\tN_(/* TRANSLATORS: Quest Map*/ \"A Dark Passage\"),\r\n\tN_(/* TRANSLATORS: Quest Map*/ \"Unholy Altar\")\r\n};\r\n\r\n/**\r\n * @brief There is no reason to run this, the room has already had a proper sector assigned\r\n */\r\nvoid DrawButcher()\r\n{\r\n\tconst Point position = SetPiece.position.megaToWorld() + Displacement { 3, 3 };\r\n\tDRLG_RectTrans({ position, { 7, 7 } });\r\n}\r\n\r\nvoid DrawSkelKing(quest_id q, Point position)\r\n{\r\n\tQuests[q].position = position.megaToWorld() + Displacement { 12, 7 };\r\n}\r\n\r\nvoid DrawWarLord(Point position)\r\n{\r\n\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l4data\\\\warlord2.dun\");\r\n\r\n\tSetPiece = { position, GetDunSize(dunData.get()) };\r\n\r\n\tPlaceDunTiles(dunData.get(), position, 6);\r\n}\r\n\r\nvoid DrawSChamber(quest_id q, Point position)\r\n{\r\n\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\bonestr1.dun\");\r\n\r\n\tSetPiece = { position, GetDunSize(dunData.get()) };\r\n\r\n\tPlaceDunTiles(dunData.get(), position, 3);\r\n\r\n\tQuests[q].position = position.megaToWorld() + Displacement { 6, 7 };\r\n}\r\n\r\nvoid DrawLTBanner(Point position)\r\n{\r\n\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l1data\\\\banner1.dun\");\r\n\r\n\tconst WorldTileSize size = GetDunSize(dunData.get());\r\n\r\n\tSetPiece = { position, size };\r\n\r\n\tconst uint16_t *tileLayer = &dunData[2];\r\n\r\n\tfor (WorldTileCoord j = 0; j < size.height; j++) {\r\n\t\tfor (WorldTileCoord i = 0; i < size.width; i++) {\r\n\t\t\tauto tileId = static_cast<uint8_t>(Swap16LE(tileLayer[j * size.width + i]));\r\n\t\t\tif (tileId != 0) {\r\n\t\t\t\tpdungeon[position.x + i][position.y + j] = tileId;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Close outer wall\r\n */\r\nvoid DrawBlind(Point position)\r\n{\r\n\tdungeon[position.x][position.y + 1] = 154;\r\n\tdungeon[position.x + 10][position.y + 8] = 154;\r\n}\r\n\r\nvoid DrawBlood(Point position)\r\n{\r\n\tauto dunData = LoadFileInMem<uint16_t>(\"levels\\\\l2data\\\\blood2.dun\");\r\n\r\n\tSetPiece = { position, GetDunSize(dunData.get()) };\r\n\r\n\tPlaceDunTiles(dunData.get(), position, 0);\r\n}\r\n\r\nint QuestLogMouseToEntry()\r\n{\r\n\tRectangle innerArea = InnerPanel;\r\n\tinnerArea.position += Displacement(GetLeftPanel().position.x, GetLeftPanel().position.y);\r\n\tif (!innerArea.contains(MousePosition) || (EncounteredQuestCount == 0))\r\n\t\treturn -1;\r\n\tconst int y = MousePosition.y - innerArea.position.y;\r\n\tfor (int i = 0; i < FirstFinishedQuest; i++) {\r\n\t\tif ((y >= ListYOffset + i * LineSpacing)\r\n\t\t    && (y < ListYOffset + i * LineSpacing + LineHeight)) {\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\nvoid PrintQLString(const Surface &out, int x, int y, std::string_view str, bool marked, bool disabled = false)\r\n{\r\n\tconst int width = GetLineWidth(str);\r\n\tx += std::max((257 - width) / 2, 0);\r\n\tif (marked) {\r\n\t\tClxDraw(out, GetPanelPosition(UiPanels::Quest, { x - 20, y + 13 }), (*pSPentSpn2Cels)[PentSpn2Spin()]);\r\n\t}\r\n\tDrawString(out, str, { GetPanelPosition(UiPanels::Quest, { x, y }), { 257, 0 } },\r\n\t    { .flags = disabled ? UiFlags::ColorWhitegold : UiFlags::ColorWhite });\r\n\tif (marked) {\r\n\t\tClxDraw(out, GetPanelPosition(UiPanels::Quest, { x + width + 7, y + 13 }), (*pSPentSpn2Cels)[PentSpn2Spin()]);\r\n\t}\r\n}\r\n\r\nstd::array<Color, 32> PureWaterPalette;\r\n\r\nvoid StartPWaterPurify()\r\n{\r\n\tPlaySfxLoc(SfxID::QuestDone, MyPlayer->position.tile);\r\n\tLoadFileInMem(\"levels\\\\l3data\\\\l3pwater.pal\", PureWaterPalette);\r\n\tUpdatePWaterPalette();\r\n\tWaterDone = 32;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InitQuests()\r\n{\r\n\tSetTownerQuestDialog(TOWN_HEALER, Q_MUSHROOM, TEXT_NONE);\r\n\tSetTownerQuestDialog(TOWN_WITCH, Q_MUSHROOM, TEXT_MUSH9);\r\n\r\n\tQuestLogIsOpen = false;\r\n\tWaterDone = 0;\r\n\r\n\tint q = 0;\r\n\tfor (auto &quest : Quests) {\r\n\t\tquest._qidx = static_cast<quest_id>(q);\r\n\t\tauto &questData = QuestsData[q];\r\n\t\tq++;\r\n\r\n\t\tquest._qactive = QUEST_NOTAVAIL;\r\n\t\tquest.position = { 0, 0 };\r\n\t\tquest._qlvltype = questData._qlvlt;\r\n\t\tquest._qslvl = questData._qslvl;\r\n\t\tquest._qvar1 = 0;\r\n\t\tquest._qvar2 = 0;\r\n\t\tquest._qlog = false;\r\n\t\tquest._qmsg = questData._qdmsg;\r\n\r\n\t\tif (!UseMultiplayerQuests()) {\r\n\t\t\tquest._qlevel = questData._qdlvl;\r\n\t\t\tquest._qactive = QUEST_INIT;\r\n\t\t} else if (!questData.isSinglePlayerOnly) {\r\n\t\t\tquest._qlevel = questData._qdmultlvl;\r\n\t\t\tquest._qactive = QUEST_INIT;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!UseMultiplayerQuests() && *GetOptions().Gameplay.randomizeQuests) {\r\n\t\t// Quests are set from the seed used to generate level 15.\r\n\t\tInitialiseQuestPools(DungeonSeeds[15], Quests);\r\n\t}\r\n\r\n\tif (gbIsSpawn) {\r\n\t\tfor (auto &quest : Quests) {\r\n\t\t\tquest._qactive = QUEST_NOTAVAIL;\r\n\t\t}\r\n\t}\r\n\r\n\tif (Quests[Q_SKELKING]._qactive == QUEST_NOTAVAIL)\r\n\t\tQuests[Q_SKELKING]._qvar2 = 2;\r\n\tif (Quests[Q_ROCK]._qactive == QUEST_NOTAVAIL)\r\n\t\tQuests[Q_ROCK]._qvar2 = 2;\r\n\tQuests[Q_LTBANNER]._qvar1 = 1;\r\n\tif (UseMultiplayerQuests())\r\n\t\tQuests[Q_BETRAYER]._qvar1 = 2;\r\n\t// In multiplayer items spawn during level generation to avoid desyncs\r\n\tif (gbIsMultiplayer && Quests[Q_MUSHROOM]._qactive == QUEST_INIT)\r\n\t\tQuests[Q_MUSHROOM]._qvar1 = QS_TOMESPAWNED;\r\n}\r\n\r\nvoid InitialiseQuestPools(uint32_t seed, Quest quests[])\r\n{\r\n\tDiabloGenerator rng(seed);\r\n\tquests[rng.pickRandomlyAmong({ Q_SKELKING, Q_PWATER })]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tif (seed == 988045466) {\r\n\t\t// If someone starts a new game at 1977-12-28 19:44:42 UTC or 2087-02-18 22:43:02 UTC\r\n\t\t//  vanilla Diablo ends up reading QuestGroup1[-2] here. Due to the way the data segment\r\n\t\t//  is laid out (at least in 1.09) this ends up reading the address of the string\r\n\t\t//  \"A Dark Passage\" and trying to write to Quests[<addr>*8] which lands in read-only memory.\r\n\t\t// The proper result would've been to mark The Butcher unavailable but instead nothing happens.\r\n\t\trng.discardRandomValues(1);\r\n\t} else {\r\n\t\tquests[rng.pickRandomlyAmong({ Q_BUTCHER, Q_LTBANNER, Q_GARBUD })]._qactive = QUEST_NOTAVAIL;\r\n\t}\r\n\r\n\tquests[rng.pickRandomlyAmong({ Q_BLIND, Q_ROCK, Q_BLOOD })]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tquests[rng.pickRandomlyAmong({ Q_MUSHROOM, Q_ZHAR, Q_ANVIL })]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tquests[rng.pickRandomlyAmong({ Q_VEIL, Q_WARLORD })]._qactive = QUEST_NOTAVAIL;\r\n}\r\n\r\nvoid CheckQuests()\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn;\r\n\r\n\tauto &quest = Quests[Q_BETRAYER];\r\n\tif (quest.IsAvailable() && UseMultiplayerQuests() && quest._qvar1 == 2) {\r\n\t\tAddObject(OBJ_ALTBOY, SetPiece.position.megaToWorld() + Displacement { 4, 6 });\r\n\t\tquest._qvar1 = 3;\r\n\t\tNetSendCmdQuest(true, quest);\r\n\t}\r\n\r\n\tif (UseMultiplayerQuests()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (currlevel == quest._qlevel\r\n\t    && !setlevel\r\n\t    && quest._qvar1 >= 2\r\n\t    && (quest._qactive == QUEST_ACTIVE || quest._qactive == QUEST_DONE)\r\n\t    && (quest._qvar2 == 0 || quest._qvar2 == 2)) {\r\n\t\t// Spawn a portal at the quest trigger location\r\n\t\tAddMissile(quest.position, quest.position, Direction::South, MissileID::RedPortal, TARGET_MONSTERS, *MyPlayer, 0, 0);\r\n\t\tquest._qvar2 = 1;\r\n\t\tif (quest._qactive == QUEST_ACTIVE && quest._qvar1 == 2) {\r\n\t\t\tquest._qvar1 = 3;\r\n\t\t}\r\n\t}\r\n\r\n\tif (quest._qactive == QUEST_DONE\r\n\t    && setlevel\r\n\t    && setlvlnum == SL_VILEBETRAYER\r\n\t    && quest._qvar2 == 4) {\r\n\t\tconst Point portalLocation { 35, 32 };\r\n\t\tAddMissile(portalLocation, portalLocation, Direction::South, MissileID::RedPortal, TARGET_MONSTERS, *MyPlayer, 0, 0);\r\n\t\tquest._qvar2 = 3;\r\n\t}\r\n\r\n\tif (setlevel) {\r\n\t\tQuest &poisonWater = Quests[Q_PWATER];\r\n\t\tif (setlvlnum == poisonWater._qslvl\r\n\t\t    && poisonWater._qactive != QUEST_INIT\r\n\t\t    && leveltype == poisonWater._qlvltype\r\n\t\t    && ActiveMonsterCount == 4\r\n\t\t    && poisonWater._qactive != QUEST_DONE) {\r\n\t\t\tpoisonWater._qactive = QUEST_DONE;\r\n\t\t\tpoisonWater._qlog = true; // even if the player skips talking to Pepin completely they should at least notice the water being purified once they cleanse the level\r\n\t\t\tNetSendCmdQuest(true, poisonWater);\r\n\t\t\tStartPWaterPurify();\r\n\t\t}\r\n\t} else if (MyPlayer->_pmode == PM_STAND) {\r\n\t\tfor (auto &currentQuest : Quests) {\r\n\t\t\tif (currlevel == currentQuest._qlevel\r\n\t\t\t    && currentQuest._qslvl != 0\r\n\t\t\t    && currentQuest._qactive != QUEST_NOTAVAIL\r\n\t\t\t    && MyPlayer->position.tile == currentQuest.position\r\n\t\t\t    && (currentQuest._qidx != Q_BETRAYER || currentQuest._qvar1 >= 3)) {\r\n\t\t\t\tif (currentQuest._qlvltype != DTYPE_NONE) {\r\n\t\t\t\t\tsetlvltype = currentQuest._qlvltype;\r\n\t\t\t\t}\r\n\t\t\t\tStartNewLvl(*MyPlayer, WM_DIABSETLVL, currentQuest._qslvl);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool ForceQuests()\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn false;\r\n\r\n\tif (UseMultiplayerQuests()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qidx != Q_BETRAYER && currlevel == quest._qlevel && quest._qslvl != 0) {\r\n\t\t\tconst int ql = quest._qslvl - 1;\r\n\r\n\t\t\tif (EntranceBoundaryContains(quest.position, cursPosition)) {\r\n\t\t\t\tInfoString = fmt::format(fmt::runtime(_(/* TRANSLATORS: Used for Quest Portals. {:s} is a Map Name */ \"To {:s}\")), _(QuestTriggerNames[ql]));\r\n\t\t\t\tcursPosition = quest.position;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid CheckQuestKill(const Monster &monster, bool sendmsg)\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn;\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tif (monster.type().type == MT_SKING) {\r\n\t\tauto &quest = Quests[Q_SKELKING];\r\n\t\tquest._qactive = QUEST_DONE;\r\n\t\tmyPlayer.Say(HeroSpeech::RestWellLeoricIllFindYourSon, 30);\r\n\t\tif (sendmsg)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\r\n\t} else if (monster.type().type == MT_CLEAVER) {\r\n\t\tauto &quest = Quests[Q_BUTCHER];\r\n\t\tquest._qactive = QUEST_DONE;\r\n\t\tmyPlayer.Say(HeroSpeech::TheSpiritsOfTheDeadAreNowAvenged, 30);\r\n\t\tif (sendmsg)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t} else if (monster.uniqueType == UniqueMonsterType::Garbud) { //\"Gharbad the Weak\"\r\n\t\tQuests[Q_GARBUD]._qactive = QUEST_DONE;\r\n\t\tNetSendCmdQuest(true, Quests[Q_GARBUD]);\r\n\t\tmyPlayer.Say(HeroSpeech::ImNotImpressed, 30);\r\n\t} else if (monster.uniqueType == UniqueMonsterType::Zhar) { //\"Zhar the Mad\"\r\n\t\tQuests[Q_ZHAR]._qactive = QUEST_DONE;\r\n\t\tNetSendCmdQuest(true, Quests[Q_ZHAR]);\r\n\t\tmyPlayer.Say(HeroSpeech::ImSorryDidIBreakYourConcentration, 30);\r\n\t} else if (monster.uniqueType == UniqueMonsterType::Lazarus) { //\"Arch-Bishop Lazarus\"\r\n\t\tauto &betrayerQuest = Quests[Q_BETRAYER];\r\n\t\tbetrayerQuest._qactive = QUEST_DONE;\r\n\t\tmyPlayer.Say(HeroSpeech::YourMadnessEndsHereBetrayer, 30);\r\n\t\tbetrayerQuest._qvar1 = 7;\r\n\t\tauto &diabloQuest = Quests[Q_DIABLO];\r\n\t\tdiabloQuest._qactive = QUEST_ACTIVE;\r\n\r\n\t\tif (UseMultiplayerQuests()) {\r\n\t\t\tfor (WorldTileCoord j = 0; j < MAXDUNY; j++) {\r\n\t\t\t\tfor (WorldTileCoord i = 0; i < MAXDUNX; i++) {\r\n\t\t\t\t\tif (dPiece[i][j] == 369) {\r\n\t\t\t\t\t\ttrigs[numtrigs].position = { i, j };\r\n\t\t\t\t\t\ttrigs[numtrigs]._tmsg = WM_DIABNEXTLVL;\r\n\t\t\t\t\t\tnumtrigs++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tInitVPTriggers();\r\n\t\t\tbetrayerQuest._qvar2 = 4;\r\n\t\t\tAddMissile({ 35, 32 }, { 35, 32 }, Direction::South, MissileID::RedPortal, TARGET_MONSTERS, myPlayer, 0, 0);\r\n\t\t}\r\n\t\tif (sendmsg) {\r\n\t\t\tNetSendCmdQuest(true, betrayerQuest);\r\n\t\t\tNetSendCmdQuest(true, diabloQuest);\r\n\t\t}\r\n\t} else if (monster.uniqueType == UniqueMonsterType::WarlordOfBlood) {\r\n\t\tQuests[Q_WARLORD]._qactive = QUEST_DONE;\r\n\t\tNetSendCmdQuest(true, Quests[Q_WARLORD]);\r\n\t\tmyPlayer.Say(HeroSpeech::YourReignOfPainHasEnded, 30);\r\n\t}\r\n}\r\n\r\nvoid DRLG_CheckQuests(Point position)\r\n{\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest.IsAvailable()) {\r\n\t\t\tswitch (quest._qidx) {\r\n\t\t\tcase Q_BUTCHER:\r\n\t\t\t\tDrawButcher();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Q_LTBANNER:\r\n\t\t\t\tDrawLTBanner(position);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Q_BLIND:\r\n\t\t\t\tDrawBlind(position);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Q_BLOOD:\r\n\t\t\t\tDrawBlood(position);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Q_WARLORD:\r\n\t\t\t\tDrawWarLord(position);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Q_SKELKING:\r\n\t\t\t\tDrawSkelKing(quest._qidx, position);\r\n\t\t\t\tbreak;\r\n\t\t\tcase Q_SCHAMB:\r\n\t\t\t\tDrawSChamber(quest._qidx, position);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint GetMapReturnLevel()\r\n{\r\n\tswitch (setlvlnum) {\r\n\tcase SL_SKELKING:\r\n\t\treturn Quests[Q_SKELKING]._qlevel;\r\n\tcase SL_BONECHAMB:\r\n\t\treturn Quests[Q_SCHAMB]._qlevel;\r\n\tcase SL_POISONWATER:\r\n\t\treturn Quests[Q_PWATER]._qlevel;\r\n\tcase SL_VILEBETRAYER:\r\n\t\treturn Quests[Q_BETRAYER]._qlevel;\r\n\tdefault:\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nPoint GetMapReturnPosition()\r\n{\r\n#ifdef _DEBUG\r\n\tif (!TestMapPath.empty())\r\n\t\treturn ViewPosition;\r\n#endif\r\n\r\n\tswitch (setlvlnum) {\r\n\tcase SL_SKELKING:\r\n\t\treturn Quests[Q_SKELKING].position + Direction::SouthEast;\r\n\tcase SL_BONECHAMB:\r\n\t\treturn Quests[Q_SCHAMB].position + Direction::SouthEast;\r\n\tcase SL_POISONWATER:\r\n\t\treturn Quests[Q_PWATER].position + Direction::SouthWest;\r\n\tcase SL_VILEBETRAYER:\r\n\t\treturn Quests[Q_BETRAYER].position + Direction::South;\r\n\tdefault:\r\n\t\treturn GetTowner(TOWN_DRUNK)->position + Direction::SouthEast;\r\n\t}\r\n}\r\n\r\nvoid LoadPWaterPalette()\r\n{\r\n\tif (!setlevel || setlvlnum != Quests[Q_PWATER]._qslvl || Quests[Q_PWATER]._qactive == QUEST_INIT || leveltype != Quests[Q_PWATER]._qlvltype)\r\n\t\treturn;\r\n\r\n\tif (Quests[Q_PWATER]._qactive == QUEST_DONE)\r\n\t\tLoadPaletteAndInitBlending(\"levels\\\\l3data\\\\l3pwater.pal\");\r\n\telse\r\n\t\tLoadPaletteAndInitBlending(\"levels\\\\l3data\\\\l3pfoul.pal\");\r\n}\r\n\r\nvoid UpdatePWaterPalette()\r\n{\r\n\tif (WaterDone > 0) {\r\n\t\t// `WaterDone` is in [1, 32], so `colorIndex` is in [0, 31].\r\n\t\tconst unsigned colorIndex = 32 - WaterDone;\r\n\t\tSetLogicalPaletteColor(colorIndex, PureWaterPalette[colorIndex].toSDL());\r\n\t\tWaterDone--;\r\n\t\treturn;\r\n\t}\r\n\tpalette_update_caves();\r\n}\r\n\r\nvoid ResyncMPQuests()\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn;\r\n\r\n\tauto &kingQuest = Quests[Q_SKELKING];\r\n\tif (kingQuest._qactive == QUEST_INIT\r\n\t    && currlevel >= kingQuest._qlevel - 1\r\n\t    && currlevel <= kingQuest._qlevel + 1) {\r\n\t\tkingQuest._qactive = QUEST_ACTIVE;\r\n\t\tNetSendCmdQuest(true, kingQuest);\r\n\t}\r\n\r\n\tauto &butcherQuest = Quests[Q_BUTCHER];\r\n\tif (butcherQuest._qactive == QUEST_INIT\r\n\t    && currlevel >= butcherQuest._qlevel - 1\r\n\t    && currlevel <= butcherQuest._qlevel + 1) {\r\n\t\tbutcherQuest._qactive = QUEST_ACTIVE;\r\n\t\tNetSendCmdQuest(true, butcherQuest);\r\n\t}\r\n\r\n\tauto &betrayerQuest = Quests[Q_BETRAYER];\r\n\tif (betrayerQuest._qactive == QUEST_INIT && currlevel == betrayerQuest._qlevel - 1) {\r\n\t\tbetrayerQuest._qactive = QUEST_ACTIVE;\r\n\t\tNetSendCmdQuest(true, betrayerQuest);\r\n\t}\r\n\tif (betrayerQuest.IsAvailable())\r\n\t\tAddObject(OBJ_ALTBOY, SetPiece.position.megaToWorld() + Displacement { 4, 6 });\r\n\r\n\tauto &cryptQuest = Quests[Q_GRAVE];\r\n\tif (cryptQuest._qactive == QUEST_INIT && currlevel == cryptQuest._qlevel - 1) {\r\n\t\tcryptQuest._qactive = QUEST_ACTIVE;\r\n\t\tNetSendCmdQuest(true, cryptQuest);\r\n\t}\r\n\r\n\tauto &defilerQuest = Quests[Q_DEFILER];\r\n\tif (defilerQuest._qactive == QUEST_INIT && currlevel == defilerQuest._qlevel - 1) {\r\n\t\tdefilerQuest._qactive = QUEST_ACTIVE;\r\n\t\tNetSendCmdQuest(true, defilerQuest);\r\n\t}\r\n\r\n\tauto &nakrulQuest = Quests[Q_NAKRUL];\r\n\tif (nakrulQuest._qactive == QUEST_INIT && currlevel == nakrulQuest._qlevel - 1) {\r\n\t\tnakrulQuest._qactive = QUEST_ACTIVE;\r\n\t\tNetSendCmdQuest(true, nakrulQuest);\r\n\t}\r\n}\r\n\r\nvoid ResyncQuests()\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn;\r\n\r\n\tLoadingMapObjects = true;\r\n\r\n\tif (Quests[Q_LTBANNER].IsAvailable()) {\r\n\t\tMonster *snotSpill = FindUniqueMonster(UniqueMonsterType::SnotSpill);\r\n\t\tif (Quests[Q_LTBANNER]._qvar1 == 1) {\r\n\t\t\tObjChangeMapResync(\r\n\t\t\t    SetPiece.position.x + SetPiece.size.width - 2,\r\n\t\t\t    SetPiece.position.y + SetPiece.size.height - 2,\r\n\t\t\t    SetPiece.position.x + SetPiece.size.width + 1,\r\n\t\t\t    SetPiece.position.y + SetPiece.size.height + 1);\r\n\t\t}\r\n\t\tif (Quests[Q_LTBANNER]._qvar1 == 2) {\r\n\t\t\tObjChangeMapResync(\r\n\t\t\t    SetPiece.position.x + SetPiece.size.width - 2,\r\n\t\t\t    SetPiece.position.y + SetPiece.size.height - 2,\r\n\t\t\t    SetPiece.position.x + SetPiece.size.width + 1,\r\n\t\t\t    SetPiece.position.y + SetPiece.size.height + 1);\r\n\t\t\tObjChangeMapResync(SetPiece.position.x, SetPiece.position.y, SetPiece.position.x + (SetPiece.size.width / 2) + 2, SetPiece.position.y + (SetPiece.size.height / 2) - 2);\r\n\t\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\t\tSyncObjectAnim(Objects[ActiveObjects[i]]);\r\n\t\t\tauto tren = TransVal;\r\n\t\t\tTransVal = 9;\r\n\t\t\tDRLG_MRectTrans({ SetPiece.position, WorldTileSize(SetPiece.size.width / 2 + 4, SetPiece.size.height / 2) });\r\n\t\t\tTransVal = tren;\r\n\t\t\tif (gbIsMultiplayer && snotSpill != nullptr && snotSpill->talkMsg != TEXT_BANNER12) {\r\n\t\t\t\tsnotSpill->goal = MonsterGoal::Inquiring;\r\n\t\t\t\tsnotSpill->talkMsg = Quests[Q_LTBANNER]._qactive == QUEST_DONE ? TEXT_BANNER12 : TEXT_BANNER11;\r\n\t\t\t\tsnotSpill->flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (Quests[Q_LTBANNER]._qvar1 == 3) {\r\n\t\t\tObjChangeMapResync(SetPiece.position.x, SetPiece.position.y, SetPiece.position.x + SetPiece.size.width + 1, SetPiece.position.y + SetPiece.size.height + 1);\r\n\t\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\t\tSyncObjectAnim(Objects[ActiveObjects[i]]);\r\n\t\t\tauto tren = TransVal;\r\n\t\t\tTransVal = 9;\r\n\t\t\tDRLG_MRectTrans({ SetPiece.position, WorldTileSize(SetPiece.size.width / 2 + 4, SetPiece.size.height / 2) });\r\n\t\t\tTransVal = tren;\r\n\t\t\tif (gbIsMultiplayer && snotSpill != nullptr) {\r\n\t\t\t\tsnotSpill->goal = MonsterGoal::Normal;\r\n\t\t\t\tsnotSpill->flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\t\tsnotSpill->talkMsg = TEXT_NONE;\r\n\t\t\t\tsnotSpill->activeForTicks = UINT8_MAX;\r\n\t\t\t\tRedoPlayerVision();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (currlevel == Quests[Q_MUSHROOM]._qlevel && !setlevel) {\r\n\t\tif (Quests[Q_MUSHROOM]._qactive == QUEST_INIT && Quests[Q_MUSHROOM]._qvar1 == QS_INIT) {\r\n\t\t\tSpawnQuestItem(IDI_FUNGALTM, { 0, 0 }, 5, SelectionRegion::Bottom, true);\r\n\t\t\tQuests[Q_MUSHROOM]._qvar1 = QS_TOMESPAWNED;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t} else {\r\n\t\t\tif (Quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE) {\r\n\t\t\t\tif (Quests[Q_MUSHROOM]._qvar1 >= QS_MUSHGIVEN) {\r\n\t\t\t\t\tSetTownerQuestDialog(TOWN_WITCH, Q_MUSHROOM, TEXT_NONE);\r\n\t\t\t\t\tSetTownerQuestDialog(TOWN_HEALER, Q_MUSHROOM, TEXT_MUSH3);\r\n\t\t\t\t} else if (Quests[Q_MUSHROOM]._qvar1 >= QS_BRAINGIVEN) {\r\n\t\t\t\t\tSetTownerQuestDialog(TOWN_HEALER, Q_MUSHROOM, TEXT_NONE);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (currlevel == Quests[Q_VEIL]._qlevel + 1 && Quests[Q_VEIL]._qactive == QUEST_ACTIVE && Quests[Q_VEIL]._qvar1 == 0 && !gbIsMultiplayer) {\r\n\t\tQuests[Q_VEIL]._qvar1 = 1;\r\n\t\tSpawnQuestItem(IDI_GLDNELIX, { 0, 0 }, 5, SelectionRegion::Bottom, true);\r\n\t\tNetSendCmdQuest(true, Quests[Q_VEIL]);\r\n\t}\r\n\tif (setlevel && setlvlnum == SL_VILEBETRAYER) {\r\n\t\tif (Quests[Q_BETRAYER]._qvar1 >= 4)\r\n\t\t\tObjChangeMapResync(1, 11, 20, 18);\r\n\t\tif (Quests[Q_BETRAYER]._qvar1 >= 6) {\r\n\t\t\tObjChangeMapResync(1, 18, 20, 24);\r\n\t\t\tif (gbIsMultiplayer) {\r\n\t\t\t\tMonster *lazarus = FindUniqueMonster(UniqueMonsterType::Lazarus);\r\n\t\t\t\tif (lazarus != nullptr) {\r\n\t\t\t\t\t// Ensure lazarus starts attacking again after returning to the level\r\n\t\t\t\t\tlazarus->goal = MonsterGoal::Normal;\r\n\t\t\t\t\tlazarus->talkMsg = TEXT_NONE;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (Quests[Q_BETRAYER]._qvar1 >= 7)\r\n\t\t\tInitVPTriggers();\r\n\t\tfor (int i = 0; i < ActiveObjectCount; i++)\r\n\t\t\tSyncObjectAnim(Objects[ActiveObjects[i]]);\r\n\t}\r\n\tif (currlevel == Quests[Q_BETRAYER]._qlevel\r\n\t    && !setlevel\r\n\t    && (Quests[Q_BETRAYER]._qvar2 == 1 || Quests[Q_BETRAYER]._qvar2 >= 3)\r\n\t    && (Quests[Q_BETRAYER]._qactive == QUEST_ACTIVE || Quests[Q_BETRAYER]._qactive == QUEST_DONE)) {\r\n\t\tQuests[Q_BETRAYER]._qvar2 = 2;\r\n\t\tNetSendCmdQuest(true, Quests[Q_BETRAYER]);\r\n\t}\r\n\tif (currlevel == Quests[Q_DIABLO]._qlevel\r\n\t    && !setlevel\r\n\t    && Quests[Q_DIABLO]._qactive == QUEST_ACTIVE\r\n\t    && gbIsMultiplayer) {\r\n\t\tconst Point posPentagram = Quests[Q_DIABLO].position;\r\n\t\tObjChangeMapResync(posPentagram.x, posPentagram.y, posPentagram.x + 5, posPentagram.y + 5);\r\n\t\tInitL4Triggers();\r\n\t}\r\n\tif (currlevel == 0\r\n\t    && Quests[Q_PWATER]._qactive == QUEST_DONE\r\n\t    && gbIsMultiplayer) {\r\n\t\tCleanTownFountain();\r\n\t}\r\n\tif (Quests[Q_GARBUD].IsAvailable() && gbIsMultiplayer) {\r\n\t\tMonster *garbud = FindUniqueMonster(UniqueMonsterType::Garbud);\r\n\t\tif (garbud != nullptr && Quests[Q_GARBUD]._qvar1 != QS_GHARBAD_INIT) {\r\n\t\t\tswitch (Quests[Q_GARBUD]._qvar1) {\r\n\t\t\tcase QS_GHARBAD_FIRST_ITEM_READY:\r\n\t\t\t\tgarbud->goal = MonsterGoal::Inquiring;\r\n\t\t\t\tbreak;\r\n\t\t\tcase QS_GHARBAD_FIRST_ITEM_SPAWNED:\r\n\t\t\t\tgarbud->talkMsg = TEXT_GARBUD2;\r\n\t\t\t\tgarbud->flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\t\tgarbud->goal = MonsterGoal::Talking;\r\n\t\t\t\tbreak;\r\n\t\t\tcase QS_GHARBAD_SECOND_ITEM_NEARLY_DONE:\r\n\t\t\t\tgarbud->talkMsg = TEXT_GARBUD3;\r\n\t\t\t\tgarbud->flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\t\tgarbud->goal = MonsterGoal::Inquiring;\r\n\t\t\t\tbreak;\r\n\t\t\tcase QS_GHARBAD_SECOND_ITEM_READY:\r\n\t\t\t\tgarbud->talkMsg = TEXT_GARBUD4;\r\n\t\t\t\tgarbud->flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\t\tgarbud->goal = MonsterGoal::Inquiring;\r\n\t\t\t\tbreak;\r\n\t\t\tcase QS_GHARBAD_ATTACKING:\r\n\t\t\t\tgarbud->talkMsg = TEXT_NONE;\r\n\t\t\t\tgarbud->flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\t\tgarbud->goal = MonsterGoal::Normal;\r\n\t\t\t\tgarbud->activeForTicks = UINT8_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (Quests[Q_ZHAR].IsAvailable() && gbIsMultiplayer) {\r\n\t\tMonster *zhar = FindUniqueMonster(UniqueMonsterType::Zhar);\r\n\t\tif (zhar != nullptr && Quests[Q_ZHAR]._qvar1 != QS_ZHAR_INIT) {\r\n\t\t\tzhar->flags |= MFLAG_QUEST_COMPLETE;\r\n\r\n\t\t\tswitch (Quests[Q_ZHAR]._qvar1) {\r\n\t\t\tcase QS_ZHAR_ITEM_SPAWNED:\r\n\t\t\t\tzhar->goal = MonsterGoal::Talking;\r\n\t\t\t\tbreak;\r\n\t\t\tcase QS_ZHAR_ANGRY:\r\n\t\t\t\tzhar->talkMsg = TEXT_ZHAR2;\r\n\t\t\t\tzhar->goal = MonsterGoal::Inquiring;\r\n\t\t\t\tbreak;\r\n\t\t\tcase QS_ZHAR_ATTACKING:\r\n\t\t\t\tzhar->talkMsg = TEXT_NONE;\r\n\t\t\t\tzhar->goal = MonsterGoal::Normal;\r\n\t\t\t\tzhar->activeForTicks = UINT8_MAX;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (Quests[Q_WARLORD].IsAvailable() && gbIsMultiplayer) {\r\n\t\tMonster *warlord = FindUniqueMonster(UniqueMonsterType::WarlordOfBlood);\r\n\t\tif (warlord != nullptr && Quests[Q_WARLORD]._qvar1 == QS_WARLORD_ATTACKING) {\r\n\t\t\twarlord->activeForTicks = UINT8_MAX;\r\n\t\t\twarlord->talkMsg = TEXT_NONE;\r\n\t\t\twarlord->goal = MonsterGoal::Normal;\r\n\t\t}\r\n\t}\r\n\tif (Quests[Q_VEIL].IsAvailable() && gbIsMultiplayer) {\r\n\t\tMonster *lachdan = FindUniqueMonster(UniqueMonsterType::Lachdan);\r\n\t\tif (lachdan != nullptr) {\r\n\t\t\tswitch (Quests[Q_VEIL]._qvar2) {\r\n\t\t\tcase QS_VEIL_EARLY_RETURN:\r\n\t\t\t\tlachdan->talkMsg = TEXT_VEIL10;\r\n\t\t\t\tlachdan->goal = MonsterGoal::Inquiring;\r\n\t\t\t\tbreak;\r\n\t\t\tcase QS_VEIL_ITEM_SPAWNED:\r\n\t\t\t\tif (lachdan->talkMsg == TEXT_VEIL11)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tlachdan->talkMsg = TEXT_VEIL11;\r\n\t\t\t\tlachdan->flags |= MFLAG_QUEST_COMPLETE;\r\n\t\t\t\tlachdan->goal = MonsterGoal::Inquiring;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tLoadingMapObjects = false;\r\n}\r\n\r\nvoid DrawQuestLog(const Surface &out)\r\n{\r\n\tconst int l = QuestLogMouseToEntry();\r\n\tif (l >= 0) {\r\n\t\tSelectedQuest = l;\r\n\t}\r\n\tconst auto x = InnerPanel.position.x;\r\n\tClxDraw(out, GetPanelPosition(UiPanels::Quest, { 0, 351 }), (*pQLogCel)[0]);\r\n\tint y = InnerPanel.position.y + ListYOffset;\r\n\tfor (int i = 0; i < EncounteredQuestCount; i++) {\r\n\t\tif (i == FirstFinishedQuest) {\r\n\t\t\ty += FinishedQuestOffset;\r\n\t\t}\r\n\t\tPrintQLString(out, x, y, _(QuestsData[EncounteredQuests[i]]._qlstr), i == SelectedQuest, i >= FirstFinishedQuest);\r\n\t\ty += LineSpacing;\r\n\t}\r\n}\r\n\r\nvoid StartQuestlog()\r\n{\r\n\r\n\tauto sortQuestIdx = [](int a, int b) {\r\n\t\treturn QuestsData[a].questBookOrder < QuestsData[b].questBookOrder;\r\n\t};\r\n\r\n\tEncounteredQuestCount = 0;\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qactive == QUEST_ACTIVE && quest._qlog) {\r\n\t\t\tEncounteredQuests[EncounteredQuestCount] = quest._qidx;\r\n\t\t\tEncounteredQuestCount++;\r\n\t\t}\r\n\t}\r\n\tFirstFinishedQuest = EncounteredQuestCount;\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qactive == QUEST_DONE || quest._qactive == QUEST_HIVE_DONE) {\r\n\t\t\tEncounteredQuests[EncounteredQuestCount] = quest._qidx;\r\n\t\t\tEncounteredQuestCount++;\r\n\t\t}\r\n\t}\r\n\r\n\tstd::sort(&EncounteredQuests[0], &EncounteredQuests[FirstFinishedQuest], sortQuestIdx);\r\n\tstd::sort(&EncounteredQuests[FirstFinishedQuest], &EncounteredQuests[EncounteredQuestCount], sortQuestIdx);\r\n\r\n\tconst bool twoBlocks = FirstFinishedQuest != 0 && FirstFinishedQuest < EncounteredQuestCount;\r\n\r\n\tListYOffset = 0;\r\n\tFinishedQuestOffset = !twoBlocks ? 0 : LineHeight / 2;\r\n\r\n\tconst int overallMinHeight = EncounteredQuestCount * LineHeight + FinishedQuestOffset;\r\n\tconst int space = InnerPanel.size.height;\r\n\r\n\tif (EncounteredQuestCount > 0) {\r\n\t\tconst int additionalSpace = space - overallMinHeight;\r\n\t\tint addLineSpacing = additionalSpace / EncounteredQuestCount;\r\n\t\taddLineSpacing = std::min(MaxSpacing - LineHeight, addLineSpacing);\r\n\t\tLineSpacing = LineHeight + addLineSpacing;\r\n\t\tif (twoBlocks) {\r\n\t\t\tint additionalSepSpace = additionalSpace - (addLineSpacing * EncounteredQuestCount);\r\n\t\t\tadditionalSepSpace = std::min(LineHeight, additionalSepSpace);\r\n\t\t\tFinishedQuestOffset = std::max(4, additionalSepSpace);\r\n\t\t}\r\n\r\n\t\tconst int overallHeight = EncounteredQuestCount * LineSpacing + FinishedQuestOffset;\r\n\t\tListYOffset += (space - overallHeight) / 2;\r\n\t}\r\n\r\n\tSelectedQuest = FirstFinishedQuest == 0 ? -1 : 0;\r\n\tQuestLogIsOpen = true;\r\n}\r\n\r\nvoid QuestlogUp()\r\n{\r\n\tif (FirstFinishedQuest == 0) {\r\n\t\tSelectedQuest = -1;\r\n\t} else {\r\n\t\tSelectedQuest--;\r\n\t\tif (SelectedQuest < 0) {\r\n\t\t\tSelectedQuest = FirstFinishedQuest - 1;\r\n\t\t}\r\n\t\tPlaySFX(SfxID::MenuMove);\r\n\t}\r\n}\r\n\r\nvoid QuestlogDown()\r\n{\r\n\tif (FirstFinishedQuest == 0) {\r\n\t\tSelectedQuest = -1;\r\n\t} else {\r\n\t\tSelectedQuest++;\r\n\t\tif (SelectedQuest == FirstFinishedQuest) {\r\n\t\t\tSelectedQuest = 0;\r\n\t\t}\r\n\t\tPlaySFX(SfxID::MenuMove);\r\n\t}\r\n}\r\n\r\nvoid QuestlogEnter()\r\n{\r\n\tPlaySFX(SfxID::MenuSelect);\r\n\tif (EncounteredQuestCount != 0 && SelectedQuest >= 0 && SelectedQuest < FirstFinishedQuest)\r\n\t\tInitQTextMsg(Quests[EncounteredQuests[SelectedQuest]]._qmsg);\r\n\tQuestLogIsOpen = false;\r\n}\r\n\r\nvoid QuestlogESC()\r\n{\r\n\tconst int l = QuestLogMouseToEntry();\r\n\tif (l != -1) {\r\n\t\tQuestlogEnter();\r\n\t}\r\n}\r\n\r\nvoid SetMultiQuest(int q, quest_state s, bool log, int v1, int v2, int16_t qmsg)\r\n{\r\n\tif (gbIsSpawn)\r\n\t\treturn;\r\n\r\n\tauto &quest = Quests[q];\r\n\tconst quest_state oldQuestState = quest._qactive;\r\n\tif (quest._qactive != QUEST_DONE) {\r\n\t\tif (s > quest._qactive || (IsAnyOf(s, QUEST_ACTIVE, QUEST_DONE) && IsAnyOf(quest._qactive, QUEST_HIVE_TEASE1, QUEST_HIVE_TEASE2, QUEST_HIVE_ACTIVE)))\r\n\t\t\tquest._qactive = s;\r\n\t\tif (log)\r\n\t\t\tquest._qlog = true;\r\n\t}\r\n\tif (v1 > quest._qvar1)\r\n\t\tquest._qvar1 = v1;\r\n\tquest._qvar2 = v2;\r\n\tquest._qmsg = static_cast<_speech_id>(qmsg);\r\n\tif (!UseMultiplayerQuests()) {\r\n\t\t// Ensure that changes on another client is also updated on our own\r\n\t\tResyncQuests();\r\n\r\n\t\tconst bool questGotCompleted = oldQuestState != QUEST_DONE && quest._qactive == QUEST_DONE;\r\n\t\t// Ensure that water also changes for remote players\r\n\t\tif (quest._qidx == Q_PWATER && questGotCompleted && MyPlayer->isOnLevel(quest._qslvl))\r\n\t\t\tStartPWaterPurify();\r\n\t\tif (quest._qidx == Q_GIRL && questGotCompleted && MyPlayer->isOnLevel(0))\r\n\t\t\tUpdateGirlAnimAfterQuestComplete();\r\n\t\tif (quest._qidx == Q_JERSEY && questGotCompleted && MyPlayer->isOnLevel(0))\r\n\t\t\tUpdateCowFarmerAnimAfterQuestComplete();\r\n\t}\r\n}\r\n\r\nbool UseMultiplayerQuests()\r\n{\r\n\treturn sgGameInitInfo.fullQuests == 0;\r\n}\r\n\r\nbool Quest::IsAvailable() const\r\n{\r\n\tif (setlevel)\r\n\t\treturn false;\r\n\tif (currlevel != _qlevel)\r\n\t\treturn false;\r\n\tif (_qactive == QUEST_NOTAVAIL)\r\n\t\treturn false;\r\n\tif (QuestsData[_qidx].isSinglePlayerOnly && UseMultiplayerQuests())\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nnamespace {\r\n\r\nvoid LoadQuestDatFromFile(DataFile &dataFile, std::string_view filename)\r\n{\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tQuestsData.reserve(QuestsData.size() + dataFile.numRecords());\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tQuestData &quest = QuestsData.emplace_back();\r\n\t\treader.readInt(\"qdlvl\", quest._qdlvl);\r\n\t\treader.readInt(\"qdmultlvl\", quest._qdmultlvl);\r\n\t\treader.read(\"qlvlt\", quest._qlvlt, ParseDungeonType);\r\n\t\treader.readInt(\"bookOrder\", quest.questBookOrder);\r\n\t\treader.readInt(\"qdrnd\", quest._qdrnd);\r\n\t\treader.read(\"qslvl\", quest._qslvl, ParseSetLevel);\r\n\t\treader.readBool(\"isSinglePlayerOnly\", quest.isSinglePlayerOnly);\r\n\t\treader.read(\"qdmsg\", quest._qdmsg, ParseSpeechId);\r\n\t\treader.readString(\"qlstr\", quest._qlstr);\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadQuestData()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\quests\\\\questdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\r\n\tQuestsData.clear();\r\n\tLoadQuestDatFromFile(dataFile, filename);\r\n\r\n\tQuestsData.shrink_to_fit();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/quests.h",
    "content": "/**\r\n * @file quests.cpp\r\n *\r\n * Interface of functionality for handling quests.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"monster.h\"\r\n#include \"panels/info_box.hpp\"\r\n#include \"tables/objdat.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\n#define MAXQUESTS 24\r\n\r\n/** States of the mushroom quest */\r\nenum {\r\n\tQS_INIT,\r\n\tQS_TOMESPAWNED,\r\n\tQS_TOMEGIVEN,\r\n\tQS_MUSHSPAWNED,\r\n\tQS_MUSHPICKED,\r\n\tQS_MUSHGIVEN,\r\n\tQS_BRAINSPAWNED,\r\n\tQS_BRAINGIVEN,\r\n};\r\n\r\n/** @brief States of the gharbad the week quest for multiplayer sync */\r\nenum {\r\n\tQS_GHARBAD_INIT,\r\n\tQS_GHARBAD_FIRST_ITEM_READY,\r\n\tQS_GHARBAD_FIRST_ITEM_SPAWNED,\r\n\tQS_GHARBAD_SECOND_ITEM_NEARLY_DONE,\r\n\tQS_GHARBAD_SECOND_ITEM_READY,\r\n\tQS_GHARBAD_ATTACKING,\r\n};\r\n\r\n/** @brief States of Zhar the Mad quest for multiplayer sync */\r\nenum {\r\n\tQS_ZHAR_INIT,\r\n\tQS_ZHAR_ITEM_SPAWNED,\r\n\tQS_ZHAR_ANGRY,\r\n\tQS_ZHAR_ATTACKING,\r\n};\r\n\r\n/** @brief States of the Warlord of Blood quest */\r\nenum {\r\n\tQS_WARLORD_INIT,\r\n\tQS_WARLORD_STEELTOME_READ,\r\n\tQS_WARLORD_TALKING,\r\n\t/** @brief State only added for multiplayer quests. Doesn't affect vanilla compatibility. */\r\n\tQS_WARLORD_ATTACKING,\r\n};\r\n\r\n/** @brief States of Lachdanan quest for multiplayer sync */\r\nenum {\r\n\tQS_VEIL_INIT,\r\n\tQS_VEIL_EARLY_RETURN,\r\n\tQS_VEIL_ITEM_SPAWNED,\r\n};\r\n\r\nenum quest_state : uint8_t {\r\n\tQUEST_NOTAVAIL, // quest did not spawn this game\r\n\tQUEST_INIT,     // quest has spawned, waiting to trigger\r\n\tQUEST_ACTIVE,   // quest is currently in progress\r\n\tQUEST_DONE,     // quest log closed and finished\r\n\tQUEST_HIVE_TEASE1 = 7,\r\n\tQUEST_HIVE_TEASE2,\r\n\tQUEST_HIVE_ACTIVE,\r\n\tQUEST_HIVE_DONE,\r\n\tQUEST_INVALID = 0xFF,\r\n};\r\n\r\nstruct Quest {\r\n\tquest_id _qidx;\r\n\tquest_state _qactive;\r\n\tuint8_t _qlevel;\r\n\tPoint position;\r\n\tdungeon_type _qlvltype;\r\n\t_setlevels _qslvl;\r\n\tbool _qlog;\r\n\t_speech_id _qmsg;\r\n\tuint8_t _qvar1;\r\n\tuint8_t _qvar2;\r\n\r\n\tbool IsAvailable() const;\r\n};\r\n\r\nstruct QuestData {\r\n\tuint8_t _qdlvl;\r\n\tint8_t _qdmultlvl;\r\n\tdungeon_type _qlvlt;\r\n\tint8_t questBookOrder;\r\n\tuint8_t _qdrnd;\r\n\t_setlevels _qslvl;\r\n\tbool isSinglePlayerOnly;\r\n\t_speech_id _qdmsg;\r\n\tstd::string _qlstr;\r\n};\r\n\r\nextern bool QuestLogIsOpen;\r\nextern OptionalOwnedClxSpriteList pQLogCel;\r\nextern DVL_API_FOR_TEST Quest Quests[MAXQUESTS];\r\nextern Point ReturnLvlPosition;\r\nextern dungeon_type ReturnLevelType;\r\nextern int ReturnLevel;\r\n\r\nvoid InitQuests();\r\n\r\n/**\r\n * @brief Deactivates quests from each quest pool at random to provide variety for single player games\r\n * @param seed The seed used to control which quests are deactivated\r\n * @param quests The available quest list, this function will make some of them inactive by the time it returns\r\n */\r\nvoid InitialiseQuestPools(uint32_t seed, Quest quests[]);\r\nvoid CheckQuests();\r\nbool ForceQuests();\r\nvoid CheckQuestKill(const Monster &monster, bool sendmsg);\r\nvoid DRLG_CheckQuests(Point position);\r\nint GetMapReturnLevel();\r\nPoint GetMapReturnPosition();\r\nvoid LoadPWaterPalette();\r\nvoid UpdatePWaterPalette();\r\nvoid ResyncMPQuests();\r\nvoid ResyncQuests();\r\nvoid DrawQuestLog(const Surface &out);\r\nvoid StartQuestlog();\r\nvoid QuestlogUp();\r\nvoid QuestlogDown();\r\nvoid QuestlogEnter();\r\nvoid QuestlogESC();\r\nvoid SetMultiQuest(int q, quest_state s, bool log, int v1, int v2, int16_t qmsg);\r\nbool UseMultiplayerQuests();\r\n\r\n/* rdata */\r\nextern std::vector<QuestData> QuestsData;\r\n\r\nvoid LoadQuestData();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/quick_messages.cpp",
    "content": "#include \"quick_messages.hpp\"\r\n\r\n#include <array>\r\n\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nstd::array<QuickMessage, 10> QuickMessages = {\r\n\tQuickMessage { \"QuickMessage1\", N_(\"I need help! Come here!\") },\r\n\tQuickMessage { \"QuickMessage2\", N_(\"Follow me.\") },\r\n\tQuickMessage { \"QuickMessage3\", N_(\"Here's something for you.\") },\r\n\tQuickMessage { \"QuickMessage4\", N_(\"Now you DIE!\") },\r\n\tQuickMessage { \"QuickMessage5\", N_(\"Heal yourself!\") },\r\n\tQuickMessage { \"QuickMessage6\", N_(\"Watch out!\") },\r\n\tQuickMessage { \"QuickMessage7\", N_(\"Thanks.\") },\r\n\tQuickMessage { \"QuickMessage8\", N_(\"Retreat!\") },\r\n\tQuickMessage { \"QuickMessage9\", N_(\"Sorry.\") },\r\n\tQuickMessage { \"QuickMessage10\", N_(\"I'm waiting.\") },\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/quick_messages.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n\r\nnamespace devilution {\r\n\r\nstruct QuickMessage {\r\n\t/** Config variable names for quick message */\r\n\tconst char *const key;\r\n\t/** Default quick message */\r\n\tconst char *const message;\r\n};\r\n\r\nextern std::array<QuickMessage, 10> QuickMessages;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/restrict.cpp",
    "content": "/**\r\n * @file restrict.cpp\r\n *\r\n * Implementation of functionality for checking if the game will be able run on the system.\r\n */\r\n\r\n#include <string>\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/paths.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid ReadOnlyTest()\r\n{\r\n\tconst std::string path = paths::PrefPath() + \"Diablo1ReadOnlyTest.foo\";\r\n\tSDL_IOStream *file = SDL_IOFromFile(path.c_str(), \"w\");\r\n\tif (file == nullptr) {\r\n\t\tDirErrorDlg(paths::PrefPath());\r\n\t}\r\n\tSDL_CloseIO(file);\r\n\tRemoveFile(path.c_str());\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/restrict.h",
    "content": "/**\r\n * @file restrict.h\r\n *\r\n * Interface of functionality for checking if the game will be able run on the system.\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Check that we have write access to the game install folder\r\n */\r\nvoid ReadOnlyTest();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/sha.cpp",
    "content": "#include \"sha.h\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\nnamespace devilution {\r\n\r\n// NOTE: Diablo's \"SHA1\" is different from actual SHA1 in that it uses arithmetic\r\n// right shifts (sign bit extension).\r\n\r\nnamespace {\r\n\r\n/**\r\n * Diablo-\"SHA1\" circular left shift, portable version.\r\n */\r\nuint32_t SHA1CircularShift(uint32_t word, size_t bits)\r\n{\r\n\t// The SHA-like algorithm as originally implemented treated word as a signed value and used arithmetic right shifts\r\n\t//  (sign-extending). This results in the high 32-`bits` bits being set to 1.\r\n\tif ((word & (1 << 31)) != 0)\r\n\t\treturn (0xFFFFFFFF << bits) | (word >> (32 - bits));\r\n\treturn (word << bits) | (word >> (32 - bits));\r\n}\r\n\r\nvoid SHA1ProcessMessageBlock(SHA1Context *context)\r\n{\r\n\tstd::uint32_t w[80];\r\n\r\n\tmemcpy(w, context->buffer, BlockSize * sizeof(uint32_t));\r\n\tfor (int i = 16; i < 80; i++) {\r\n\t\tw[i] = w[i - 16] ^ w[i - 14] ^ w[i - 8] ^ w[i - 3];\r\n\t}\r\n\r\n\tstd::uint32_t a = context->state[0];\r\n\tstd::uint32_t b = context->state[1];\r\n\tstd::uint32_t c = context->state[2];\r\n\tstd::uint32_t d = context->state[3];\r\n\tstd::uint32_t e = context->state[4];\r\n\r\n\tfor (int i = 0; i < 20; i++) {\r\n\t\tconst std::uint32_t temp = SHA1CircularShift(a, 5) + ((b & c) | ((~b) & d)) + e + w[i] + 0x5A827999;\r\n\t\te = d;\r\n\t\td = c;\r\n\t\tc = SHA1CircularShift(b, 30);\r\n\t\tb = a;\r\n\t\ta = temp;\r\n\t}\r\n\r\n\tfor (int i = 20; i < 40; i++) {\r\n\t\tconst std::uint32_t temp = SHA1CircularShift(a, 5) + (b ^ c ^ d) + e + w[i] + 0x6ED9EBA1;\r\n\t\te = d;\r\n\t\td = c;\r\n\t\tc = SHA1CircularShift(b, 30);\r\n\t\tb = a;\r\n\t\ta = temp;\r\n\t}\r\n\r\n\tfor (int i = 40; i < 60; i++) {\r\n\t\tconst std::uint32_t temp = SHA1CircularShift(a, 5) + ((b & c) | (b & d) | (c & d)) + e + w[i] + 0x8F1BBCDC;\r\n\t\te = d;\r\n\t\td = c;\r\n\t\tc = SHA1CircularShift(b, 30);\r\n\t\tb = a;\r\n\t\ta = temp;\r\n\t}\r\n\r\n\tfor (int i = 60; i < 80; i++) {\r\n\t\tconst std::uint32_t temp = SHA1CircularShift(a, 5) + (b ^ c ^ d) + e + w[i] + 0xCA62C1D6;\r\n\t\te = d;\r\n\t\td = c;\r\n\t\tc = SHA1CircularShift(b, 30);\r\n\t\tb = a;\r\n\t\ta = temp;\r\n\t}\r\n\r\n\tcontext->state[0] += a;\r\n\tcontext->state[1] += b;\r\n\tcontext->state[2] += c;\r\n\tcontext->state[3] += d;\r\n\tcontext->state[4] += e;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid SHA1Result(SHA1Context &context, uint32_t messageDigest[SHA1HashSize])\r\n{\r\n\tmemcpy(messageDigest, context.state, sizeof(context.state));\r\n}\r\n\r\nvoid SHA1Calculate(SHA1Context &context, const uint32_t data[BlockSize])\r\n{\r\n\tmemcpy(&context.buffer[0], data, BlockSize * sizeof(uint32_t));\r\n\tSHA1ProcessMessageBlock(&context);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/sha.h",
    "content": "/**\r\n * @file sha.cpp\r\n *\r\n * Interface of functionality for calculating X-SHA-1 (a flawed implementation of SHA-1).\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nconstexpr size_t BlockSize = 16;\r\nconstexpr size_t SHA1HashSize = 5;\r\n\r\nstruct SHA1Context {\r\n\tuint32_t state[SHA1HashSize] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };\r\n\tuint32_t buffer[BlockSize];\r\n};\r\n\r\nvoid SHA1Result(SHA1Context &context, uint32_t messageDigest[SHA1HashSize]);\r\nvoid SHA1Calculate(SHA1Context &context, const uint32_t data[BlockSize]);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/sound_effect_enums.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\nnamespace devilution {\r\n\r\nenum class HeroSpeech : uint8_t {\r\n\tChamberOfBoneLore,\r\n\tHorazonsSanctumLore,\r\n\tGolemSpellLore,\r\n\tHorazonsCreatureOfFlameLore,\r\n\tMortaVespaGaieaInnuminoEvegeenJatanLuaGraton,\r\n\tGrimspikeLieutenantOfBelialLore,\r\n\tHorazonsJournal,\r\n\tYourDeathWillBeAvenged,\r\n\tRestInPeaceMyFriend,\r\n\tValorLore,\r\n\tHallsOfTheBlindLore,\r\n\tWarlordOfBloodLore,\r\n\tICantUseThisYet,\r\n\tICantCarryAnymore,\r\n\tIHaveNoRoom,\r\n\tWhereWouldIPutThis,\r\n\tNoWay,\r\n\tNotAChance,\r\n\tIdNeverUseThis,\r\n\tIdHaveToEquipThat,\r\n\tICantMoveThis,\r\n\tICantMoveThisYet,\r\n\tICantOpenThis,\r\n\tICantOpenThisYet,\r\n\tICantLiftThis,\r\n\tICantLiftThisYet,\r\n\tICantCastThatHere,\r\n\tICantCastThatYet,\r\n\tThatDidntDoAnything,\r\n\tICanAlreadyDoThat,\r\n\tIDontNeedThat,\r\n\tIDontNeedToDoThat,\r\n\tIDontWantThat,\r\n\tIDontHaveASpellReady,\r\n\tNotEnoughMana,\r\n\tThatWouldKillMe,\r\n\tICantDoThat,\r\n\tNo,\r\n\tYes,\r\n\tThatWontWork,\r\n\tThatWontWorkHere,\r\n\tThatWontWorkYet,\r\n\tICantGetThereFromHere,\r\n\tItsTooHeavy,\r\n\tItsTooBig,\r\n\tJustWhatIWasLookingFor,\r\n\tIveGotABadFeelingAboutThis,\r\n\tGotMilk,\r\n\tImNotThirsty,\r\n\tImNoMilkmaid,\r\n\tICouldBlowUpTheWholeVillage,\r\n\tYepThatsACowAlright,\r\n\tTooUghHeavy,\r\n\tInSpirituSanctum,\r\n\tPraedictumOtium,\r\n\tEfficioObitusUtInimicus,\r\n\tTheEnchantmentIsGone,\r\n\tOhTooEasy,\r\n\tBackToTheGrave,\r\n\tTimeToDie,\r\n\tImNotImpressed,\r\n\tImSorryDidIBreakYourConcentration,\r\n\tVengeanceIsMine,\r\n\tDie,\r\n\tYeah,\r\n\tAh,\r\n\tPhew,\r\n\tArgh,\r\n\tArghClang,\r\n\tAaaaargh,\r\n\tOofAh,\r\n\tHeavyBreathing,\r\n\tOh,\r\n\tWow,\r\n\tThankTheLight,\r\n\tWhatWasThat,\r\n\tMmHmm,\r\n\tHmm,\r\n\tUhHuh,\r\n\tTheSpiritsOfTheDeadAreNowAvenged,\r\n\tTheTownIsSafeFromTheseFoulSpawn,\r\n\tRestWellLeoricIllFindYourSon,\r\n\tYourMadnessEndsHereBetrayer,\r\n\tYoullLureNoMoreMenToTheirDeaths,\r\n\tReturnToHeavenWarriorOfLight,\r\n\tICanSeeWhyTheyFearThisWeapon,\r\n\tThisMustBeWhatGriswoldWanted,\r\n\tINeedToGetThisToLachdanan,\r\n\tINeedToGetThisToGriswold,\r\n\tIveNeverBeenHereBefore,\r\n\tMayTheSpiritOfArkaineProtectMe,\r\n\tThisIsAPlaceOfGreatPower,\r\n\tThisBladeMustBeDestroyed,\r\n\tYourReignOfPainHasEnded,\r\n\tNowThatsOneBigMushroom,\r\n\tTheSmellOfDeathSurroundsMe,\r\n\tTheSanctityOfThisPlaceHasBeenFouled,\r\n\tItsHotDownHere,\r\n\tIMustBeGettingClose,\r\n\tMaybeItsLockedFromTheInside,\r\n\tLooksLikeItsRustedShut,\r\n\tMaybeTheresAnotherWay,\r\n\tAuughUh,\r\n\r\n\tLAST = AuughUh\r\n};\r\n\r\nenum class SfxID : int16_t {\r\n\tWalk,\r\n\tShootBow,\r\n\tCastSpell,\r\n\tSwing,\r\n\tSwing2,\r\n\tWarriorDeath,\r\n\tQuestDone,\r\n\tBarrelExpload,\r\n\tBarrelBreak,\r\n\tChestOpen,\r\n\tDoorClose,\r\n\tDoorOpen,\r\n\tItemAnvilFlip,\r\n\tItemAxeFlip,\r\n\tItemBloodStoneFlip,\r\n\tItemBodyPartFlip,\r\n\tItemBookFlip,\r\n\tItemBowFlip,\r\n\tItemCapFlip,\r\n\tItemArmorFlip,\r\n\tItemLeatherFlip,\r\n\tItemMushroomFlip,\r\n\tItemPotionFlip,\r\n\tItemRingFlip,\r\n\tItemRockFlip,\r\n\tItemScrollFlip,\r\n\tItemShieldFlip,\r\n\tItemSignFlip,\r\n\tItemStaffFlip,\r\n\tItemSwordFlip,\r\n\tItemGold,\r\n\tItemAnvil,\r\n\tItemAxe,\r\n\tItemBloodStone,\r\n\tItemBodyPart,\r\n\tItemBook,\r\n\tItemBow,\r\n\tItemCap,\r\n\tGrabItem,\r\n\tItemArmor,\r\n\tItemLeather,\r\n\tItemMushroom,\r\n\tItemPotion,\r\n\tItemRing,\r\n\tItemRock,\r\n\tItemScroll,\r\n\tItemShield,\r\n\tItemSign,\r\n\tItemStaff,\r\n\tItemSword,\r\n\tOperateLever,\r\n\tOperateShrine,\r\n\tOperateShrine1,\r\n\tReadBook,\r\n\tSarcophagus,\r\n\tMenuMove,\r\n\tMenuSelect,\r\n\tTriggerTrap,\r\n\tCastFire,\r\n\tCastLightning,\r\n\tCastSkill,\r\n\tSpellEnd,\r\n\tCastHealing,\r\n\tSpellRepair,\r\n\tSpellAcid,\r\n\tSpellAcid1,\r\n\tSpellApocalypse,\r\n\tSpellBloodStar,\r\n\tSpellBloodStarHit,\r\n\tSpellBoneSpirit,\r\n\tSpellBoneSpiritHit,\r\n\tOperateCaldron,\r\n\tSpellChargedBolt,\r\n\tSpellDoomSerpents, // Unused\r\n\tSpellLightningHit,\r\n\tSpellElemental,\r\n\tSpellEtherealize,\r\n\tSpellFirebolt,\r\n\tSpellFireHit,\r\n\tSpellFlameWave,\r\n\tOperateFountain,\r\n\tSpellGolem,\r\n\tOperateGoatShrine,\r\n\tSpellGuardian,\r\n\tSpellHolyBolt,\r\n\tSpellInfravision,\r\n\tSpellInvisibility, // Unused\r\n\tSpellLightning,\r\n\tSpellManaShield,\r\n\tSpellNova,\r\n\tSpellPuddle,\r\n\tSpellResurrect,\r\n\tSpellStoneCurse,\r\n\tSpellPortal,\r\n\tSpellInferno,\r\n\tSpellTrapDisarm,\r\n\tSpellTeleport,\r\n\tSpellFireWall,\r\n\tGillian1,\r\n\tGillian2,\r\n\tGillian3,\r\n\tGillian4,\r\n\tGillian5,\r\n\tGillian6,\r\n\tGillian7,\r\n\tGillian8,\r\n\tGillian9,\r\n\tGillian10,\r\n\tGillian11,\r\n\tGillian12,\r\n\tGillian13,\r\n\tGillian14,\r\n\tGillian15,\r\n\tGillian16,\r\n\tGillian17,\r\n\tGillian18,\r\n\tGillian19,\r\n\tGillian20,\r\n\tGillian21,\r\n\tGillian22,\r\n\tGillian23,\r\n\tGillian24,\r\n\tGillian25,\r\n\tGillian26,\r\n\tGillian27,\r\n\tGillian28,\r\n\tGillian29,\r\n\tGillian30,\r\n\tGillian31,\r\n\tGillian32,\r\n\tGillian33,\r\n\tGillian34,\r\n\tGillian35,\r\n\tGillian36,\r\n\tGillian37,\r\n\tGillian38,\r\n\tGillian39,\r\n\tGillian40,\r\n\tGriswold1,\r\n\tGriswold2,\r\n\tGriswold3,\r\n\tGriswold4,\r\n\tGriswold5,\r\n\tGriswold6,\r\n\tGriswold7,\r\n\tGriswold8,\r\n\tGriswold9,\r\n\tGriswold10,\r\n\tGriswold12,\r\n\tGriswold13,\r\n\tGriswold14,\r\n\tGriswold15,\r\n\tGriswold16,\r\n\tGriswold17,\r\n\tGriswold18,\r\n\tGriswold19,\r\n\tGriswold20,\r\n\tGriswold21,\r\n\tGriswold22,\r\n\tGriswold23,\r\n\tGriswold24,\r\n\tGriswold25,\r\n\tGriswold26,\r\n\tGriswold27,\r\n\tGriswold28,\r\n\tGriswold29,\r\n\tGriswold30,\r\n\tGriswold31,\r\n\tGriswold32,\r\n\tGriswold33,\r\n\tGriswold34,\r\n\tGriswold35,\r\n\tGriswold36,\r\n\tGriswold37,\r\n\tGriswold38,\r\n\tGriswold39,\r\n\tGriswold40,\r\n\tGriswold41,\r\n\tGriswold42,\r\n\tGriswold43,\r\n\tGriswold44,\r\n\tGriswold45,\r\n\tGriswold46,\r\n\tGriswold47,\r\n\tGriswold48,\r\n\tGriswold49,\r\n\tGriswold50,\r\n\tGriswold51,\r\n\tGriswold52,\r\n\tGriswold53,\r\n\tGriswold55,\r\n\tGriswold56,\r\n\tCow1,\r\n\tCow2,\r\n\tWoundedTownsmanOld, // Unused\r\n\tFarnham1,\r\n\tFarnham2,\r\n\tFarnham3,\r\n\tFarnham4,\r\n\tFarnham5,\r\n\tFarnham6,\r\n\tFarnham7,\r\n\tFarnham8,\r\n\tFarnham9,\r\n\tFarnham10,\r\n\tFarnham11,\r\n\tFarnham12,\r\n\tFarnham13,\r\n\tFarnham14,\r\n\tFarnham15,\r\n\tFarnham16,\r\n\tFarnham17,\r\n\tFarnham18,\r\n\tFarnham19,\r\n\tFarnham20,\r\n\tFarnham21,\r\n\tFarnham22,\r\n\tFarnham23,\r\n\tFarnham24,\r\n\tFarnham25,\r\n\tFarnham26,\r\n\tFarnham27,\r\n\tFarnham28,\r\n\tFarnham29,\r\n\tFarnham30,\r\n\tFarnham31,\r\n\tFarnham32,\r\n\tFarnham33,\r\n\tFarnham34,\r\n\tFarnham35,\r\n\tPepin1,\r\n\tPepin2,\r\n\tPepin3,\r\n\tPepin4,\r\n\tPepin5,\r\n\tPepin6,\r\n\tPepin7,\r\n\tPepin8,\r\n\tPepin9,\r\n\tPepin10,\r\n\tPepin11,\r\n\tPepin12,\r\n\tPepin13,\r\n\tPepin14,\r\n\tPepin15,\r\n\tPepin16,\r\n\tPepin17,\r\n\tPepin18,\r\n\tPepin19,\r\n\tPepin20,\r\n\tPepin21,\r\n\tPepin22,\r\n\tPepin23,\r\n\tPepin24,\r\n\tPepin25,\r\n\tPepin26,\r\n\tPepin27,\r\n\tPepin28,\r\n\tPepin29,\r\n\tPepin30,\r\n\tPepin31,\r\n\tPepin32,\r\n\tPepin33,\r\n\tPepin34,\r\n\tPepin35,\r\n\tPepin36,\r\n\tPepin37,\r\n\tPepin38,\r\n\tPepin39,\r\n\tPepin40,\r\n\tPepin41,\r\n\tPepin42,\r\n\tPepin43,\r\n\tPepin44,\r\n\tPepin45,\r\n\tPepin46,\r\n\tPepin47,\r\n\tWirt1,\r\n\tWirt2,\r\n\tWirt3,\r\n\tWirt4,\r\n\tWirt5,\r\n\tWirt6,\r\n\tWirt7,\r\n\tWirt8,\r\n\tWirt9,\r\n\tWirt10,\r\n\tWirt11,\r\n\tWirt12,\r\n\tWirt13,\r\n\tWirt14,\r\n\tWirt15,\r\n\tWirt16,\r\n\tWirt17,\r\n\tWirt18,\r\n\tWirt19,\r\n\tWirt20,\r\n\tWirt21,\r\n\tWirt22,\r\n\tWirt23,\r\n\tWirt24,\r\n\tWirt25,\r\n\tWirt26,\r\n\tWirt27,\r\n\tWirt28,\r\n\tWirt29,\r\n\tWirt30,\r\n\tWirt31,\r\n\tWirt32,\r\n\tWirt33,\r\n\tWirt34,\r\n\tWirt35,\r\n\tWirt36,\r\n\tWirt37,\r\n\tWirt38,\r\n\tWirt39,\r\n\tWirt40,\r\n\tWirt41,\r\n\tWirt42,\r\n\tWirt43,\r\n\tTremain0, // Unused\r\n\tTremain1, // Unused\r\n\tTremain2, // Unused\r\n\tTremain3, // Unused\r\n\tTremain4, // Unused\r\n\tTremain5, // Unused\r\n\tTremain6, // Unused\r\n\tTremain7, // Unused\r\n\tCain0,\r\n\tCain1,\r\n\tCain2,\r\n\tCain3,\r\n\tCain4,\r\n\tCain5,\r\n\tCain6,\r\n\tCain7,\r\n\tCain8,\r\n\tCain9,\r\n\tCain10,\r\n\tCain11,\r\n\tCain12,\r\n\tCain13,\r\n\tCain14,\r\n\tCain15,\r\n\tCain16,\r\n\tCain17,\r\n\tCain18,\r\n\tCain19,\r\n\tCain20,\r\n\tCain21,\r\n\tCain22,\r\n\tCain23,\r\n\tCain24,\r\n\tCain25,\r\n\tCain26,\r\n\tCain27,\r\n\tCain28,\r\n\tCain29,\r\n\tCain30,\r\n\tCain31,\r\n\tCain33,\r\n\tCain34,\r\n\tCain35,\r\n\tCain36,\r\n\tCain37,\r\n\tCain38,\r\n\tOgden0,\r\n\tOgden1,\r\n\tOgden2,\r\n\tOgden3,\r\n\tOgden4,\r\n\tOgden5,\r\n\tOgden6,\r\n\tOgden7,\r\n\tOgden8,\r\n\tOgden9,\r\n\tOgden10,\r\n\tOgden11,\r\n\tOgden12,\r\n\tOgden13,\r\n\tOgden14,\r\n\tOgden15,\r\n\tOgden16,\r\n\tOgden17,\r\n\tOgden18,\r\n\tOgden19,\r\n\tOgden20,\r\n\tOgden21,\r\n\tOgden22,\r\n\tOgden23,\r\n\tOgden24,\r\n\tOgden25,\r\n\tOgden26,\r\n\tOgden27,\r\n\tOgden28,\r\n\tOgden29,\r\n\tOgden30,\r\n\tOgden31,\r\n\tOgden32,\r\n\tOgden33,\r\n\tOgden34,\r\n\tOgden35,\r\n\tOgden36,\r\n\tOgden37,\r\n\tOgden38,\r\n\tOgden39,\r\n\tOgden40,\r\n\tOgden41,\r\n\tOgden43,\r\n\tOgden44,\r\n\tOgden45,\r\n\tAdria1,\r\n\tAdria2,\r\n\tAdria3,\r\n\tAdria4,\r\n\tAdria5,\r\n\tAdria6,\r\n\tAdria7,\r\n\tAdria8,\r\n\tAdria9,\r\n\tAdria10,\r\n\tAdria11,\r\n\tAdria12,\r\n\tAdria13,\r\n\tAdria14,\r\n\tAdria15,\r\n\tAdria16,\r\n\tAdria17,\r\n\tAdria18,\r\n\tAdria19,\r\n\tAdria20,\r\n\tAdria21,\r\n\tAdria22,\r\n\tAdria23,\r\n\tAdria24,\r\n\tAdria25,\r\n\tAdria26,\r\n\tAdria27,\r\n\tAdria28,\r\n\tAdria29,\r\n\tAdria30,\r\n\tAdria31,\r\n\tAdria32,\r\n\tAdria33,\r\n\tAdria34,\r\n\tAdria35,\r\n\tAdria36,\r\n\tAdria37,\r\n\tAdria38,\r\n\tAdria39,\r\n\tAdria40,\r\n\tAdria41,\r\n\tAdria42,\r\n\tAdria43,\r\n\tAdria44,\r\n\tAdria45,\r\n\tAdria46,\r\n\tAdria47,\r\n\tAdria48,\r\n\tAdria49,\r\n\tAdria50,\r\n\tWoundedTownsman,\r\n\tSorceror1,\r\n\tSorceror2,\r\n\tSorceror3,\r\n\tSorceror4,\r\n\tSorceror5,\r\n\tSorceror6,\r\n\tSorceror7,\r\n\tSorceror8,\r\n\tSorceror9,\r\n\tSorceror10,\r\n\tSorceror11,\r\n\tSorceror12,\r\n\tSorceror13,\r\n\tSorceror14,\r\n\tSorceror15,\r\n\tSorceror16,\r\n\tSorceror17,\r\n\tSorceror18,\r\n\tSorceror19,\r\n\tSorceror20,\r\n\tSorceror21,\r\n\tSorceror22,\r\n\tSorceror23,\r\n\tSorceror24,\r\n\tSorceror25,\r\n\tSorceror26,\r\n\tSorceror27,\r\n\tSorceror28,\r\n\tSorceror29,\r\n\tSorceror30,\r\n\tSorceror31,\r\n\tSorceror32,\r\n\tSorceror33,\r\n\tSorceror34,\r\n\tSorceror35,\r\n\tSorceror36,\r\n\tSorceror37,\r\n\tSorceror38,\r\n\tSorceror39,\r\n\tSorceror40,\r\n\tSorceror41,\r\n\tSorceror42,\r\n\tSorceror43,\r\n\tSorceror44,\r\n\tSorceror45,\r\n\tSorceror46,\r\n\tSorceror47,\r\n\tSorceror48,\r\n\tSorceror49,\r\n\tSorceror50,\r\n\tSorceror51,\r\n\tSorceror52,\r\n\tSorceror53,\r\n\tSorceror54,\r\n\tSorceror55,\r\n\tSorceror56,\r\n\tSorceror57,\r\n\tSorceror58,\r\n\tSorceror59,\r\n\tSorceror60,\r\n\tSorceror61,\r\n\tSorceror62,\r\n\tSorceror63,\r\n\tSorceror64,\r\n\tSorceror65,\r\n\tSorceror66,\r\n\tSorceror67,\r\n\tSorceror68,\r\n\tSorceror69,\r\n\tSorceror69b,\r\n\tSorceror70,\r\n\tSorceror71,\r\n\tSorceror72,\r\n\tSorceror73,\r\n\tSorceror74,\r\n\tSorceror75,\r\n\tSorceror76,\r\n\tSorceror77,\r\n\tSorceror78,\r\n\tSorceror79,\r\n\tSorceror80,\r\n\tSorceror81,\r\n\tSorceror82,\r\n\tSorceror83,\r\n\tSorceror84,\r\n\tSorceror85,\r\n\tSorceror86,\r\n\tSorceror87,\r\n\tSorceror88,\r\n\tSorceror89,\r\n\tSorceror90,\r\n\tSorceror91,\r\n\tSorceror92,\r\n\tSorceror93,\r\n\tSorceror94,\r\n\tSorceror95,\r\n\tSorceror96,\r\n\tSorceror97,\r\n\tSorceror98,\r\n\tSorceror99,\r\n\tSorceror100,\r\n\tSorceror101,\r\n\tSorceror102,\r\n\tRogue1,\r\n\tRogue2,\r\n\tRogue3,\r\n\tRogue4,\r\n\tRogue5,\r\n\tRogue6,\r\n\tRogue7,\r\n\tRogue8,\r\n\tRogue9,\r\n\tRogue10,\r\n\tRogue11,\r\n\tRogue12,\r\n\tRogue13,\r\n\tRogue14,\r\n\tRogue15,\r\n\tRogue16,\r\n\tRogue17,\r\n\tRogue18,\r\n\tRogue19,\r\n\tRogue20,\r\n\tRogue21,\r\n\tRogue22,\r\n\tRogue23,\r\n\tRogue24,\r\n\tRogue25,\r\n\tRogue26,\r\n\tRogue27,\r\n\tRogue28,\r\n\tRogue29,\r\n\tRogue30,\r\n\tRogue31,\r\n\tRogue32,\r\n\tRogue33,\r\n\tRogue34,\r\n\tRogue35,\r\n\tRogue36,\r\n\tRogue37,\r\n\tRogue38,\r\n\tRogue39,\r\n\tRogue40,\r\n\tRogue41,\r\n\tRogue42,\r\n\tRogue43,\r\n\tRogue44,\r\n\tRogue45,\r\n\tRogue46,\r\n\tRogue47,\r\n\tRogue48,\r\n\tRogue49,\r\n\tRogue50,\r\n\tRogue51,\r\n\tRogue52,\r\n\tRogue53,\r\n\tRogue54,\r\n\tRogue55,\r\n\tRogue56,\r\n\tRogue57,\r\n\tRogue58,\r\n\tRogue59,\r\n\tRogue60,\r\n\tRogue61,\r\n\tRogue62,\r\n\tRogue63,\r\n\tRogue64,\r\n\tRogue65,\r\n\tRogue66,\r\n\tRogue67,\r\n\tRogue68,\r\n\tRogue69,\r\n\tRogue69b,\r\n\tRogue70,\r\n\tRogue71,\r\n\tRogue72,\r\n\tRogue73,\r\n\tRogue74,\r\n\tRogue75,\r\n\tRogue76,\r\n\tRogue77,\r\n\tRogue78,\r\n\tRogue79,\r\n\tRogue80,\r\n\tRogue81,\r\n\tRogue82,\r\n\tRogue83,\r\n\tRogue84,\r\n\tRogue85,\r\n\tRogue86,\r\n\tRogue87,\r\n\tRogue88,\r\n\tRogue89,\r\n\tRogue90,\r\n\tRogue91,\r\n\tRogue92,\r\n\tRogue93,\r\n\tRogue94,\r\n\tRogue95,\r\n\tRogue96,\r\n\tRogue97,\r\n\tRogue98,\r\n\tRogue99,\r\n\tRogue100,\r\n\tRogue101,\r\n\tRogue102,\r\n\tWarrior1,\r\n\tWarrior2,\r\n\tWarrior3,\r\n\tWarrior4,\r\n\tWarrior5,\r\n\tWarrior6,\r\n\tWarrior7,\r\n\tWarrior8,\r\n\tWarrior9,\r\n\tWarrior10,\r\n\tWarrior11,\r\n\tWarrior12,\r\n\tWarrior13,\r\n\tWarrior14,\r\n\tWarrior14b,\r\n\tWarrior14c,\r\n\tWarrior15,\r\n\tWarrior15b,\r\n\tWarrior15c,\r\n\tWarrior16,\r\n\tWarrior16b,\r\n\tWarrior16c,\r\n\tWarrior17,\r\n\tWarrior18,\r\n\tWarrior19,\r\n\tWarrior20,\r\n\tWarrior21,\r\n\tWarrior22,\r\n\tWarrior23,\r\n\tWarrior24,\r\n\tWarrior25,\r\n\tWarrior26,\r\n\tWarrior27,\r\n\tWarrior28,\r\n\tWarrior29,\r\n\tWarrior30,\r\n\tWarrior31,\r\n\tWarrior32,\r\n\tWarrior33,\r\n\tWarrior34,\r\n\tWarrior35,\r\n\tWarrior36,\r\n\tWarrior37,\r\n\tWarrior38,\r\n\tWarrior39,\r\n\tWarrior40,\r\n\tWarrior41,\r\n\tWarrior42,\r\n\tWarrior43,\r\n\tWarrior44,\r\n\tWarrior45,\r\n\tWarrior46,\r\n\tWarrior47,\r\n\tWarrior48,\r\n\tWarrior49,\r\n\tWarrior50,\r\n\tWarrior51,\r\n\tWarrior52,\r\n\tWarrior53,\r\n\tWarrior54,\r\n\tWarrior55,\r\n\tWarrior56,\r\n\tWarrior57,\r\n\tWarrior58,\r\n\tWarrior59,\r\n\tWarrior60,\r\n\tWarrior61,\r\n\tWarrior62,\r\n\tWarrior63,\r\n\tWarrior64,\r\n\tWarrior65,\r\n\tWarrior66,\r\n\tWarrior67,\r\n\tWarrior68,\r\n\tWarrior69,\r\n\tWarrior69b,\r\n\tWarrior70,\r\n\tWarrior71,\r\n\tWarrior72,\r\n\tWarrior73,\r\n\tWarrior74,\r\n\tWarrior75,\r\n\tWarrior76,\r\n\tWarrior77,\r\n\tWarrior78,\r\n\tWarrior79,\r\n\tWarrior80,\r\n\tWarrior81,\r\n\tWarrior82,\r\n\tWarrior83,\r\n\tWarrior84,\r\n\tWarrior85,\r\n\tWarrior86,\r\n\tWarrior87,\r\n\tWarrior88,\r\n\tWarrior89,\r\n\tWarrior90,\r\n\tWarrior91,\r\n\tWarrior92,\r\n\tWarrior93,\r\n\tWarrior94,\r\n\tWarrior95,\r\n\tWarrior96b,\r\n\tWarrior97,\r\n\tWarrior98,\r\n\tWarrior99,\r\n\tWarrior100,\r\n\tWarrior101,\r\n\tWarrior102,\r\n\tNarrator1,\r\n\tNarrator2,\r\n\tNarrator3,\r\n\tNarrator4,\r\n\tNarrator5,\r\n\tNarrator6,\r\n\tNarrator7,\r\n\tNarrator8,\r\n\tNarrator9,\r\n\tDiabloGreeting,\r\n\tButcherGreeting,\r\n\tGharbad1,\r\n\tGharbad2,\r\n\tGharbad3,\r\n\tGharbad4,\r\n\tLachdanan1,\r\n\tLachdanan2,\r\n\tLachdanan3,\r\n\tLazarusGreeting,\r\n\tLeoricGreeting,\r\n\tSnotspill1,\r\n\tSnotspill2,\r\n\tSnotspill3,\r\n\tWarlord,\r\n\tZhar1,\r\n\tZhar2,\r\n\tDiabloDeath,\r\n\r\n\tShootBow2,\r\n\tShootFireballBow,\r\n\tPodExpload,\r\n\tPodPop,\r\n\tUrnExpload,\r\n\tUrnBreak,\r\n\tBigExplosion,\r\n\tSpellLightningWall,\r\n\tPig,\r\n\tMonk1,\r\n\tMonk8,\r\n\tMonk9,\r\n\tMonk10,\r\n\tMonk11,\r\n\tMonk12,\r\n\tMonk13,\r\n\tMonk14,\r\n\tMonk15,\r\n\tMonk16,\r\n\tMonk24,\r\n\tMonk27,\r\n\tMonk29,\r\n\tMonk34,\r\n\tMonk35,\r\n\tMonk43,\r\n\tMonk46,\r\n\tMonk49,\r\n\tMonk50,\r\n\tMonk52,\r\n\tMonk54,\r\n\tMonk55,\r\n\tMonk56,\r\n\tMonk61,\r\n\tMonk62,\r\n\tMonk68,\r\n\tMonk69,\r\n\tMonk69b,\r\n\tMonk70,\r\n\tMonk71,\r\n\tMonk79,\r\n\tMonk80,\r\n\tMonk82,\r\n\tMonk83,\r\n\tMonk87,\r\n\tMonk88,\r\n\tMonk89,\r\n\tMonk91,\r\n\tMonk92,\r\n\tMonk94,\r\n\tMonk95,\r\n\tMonk96,\r\n\tMonk97,\r\n\tMonk98,\r\n\tMonk99,\r\n\tFarmer1,\r\n\tFarmer2,\r\n\tFarmer2a,\r\n\tFarmer3,\r\n\tFarmer4,\r\n\tFarmer5,\r\n\tFarmer6,\r\n\tFarmer7,\r\n\tFarmer8,\r\n\tFarmer9,\r\n\tCelia1,\r\n\tCelia2,\r\n\tCelia3,\r\n\tCelia4,\r\n\tDefiler1,\r\n\tDefiler2,\r\n\tDefiler3,\r\n\tDefiler4,\r\n\tDefiler8,\r\n\tDefiler6,\r\n\tDefiler7,\r\n\tNaKrul1,\r\n\tNaKrul2,\r\n\tNaKrul3,\r\n\tNaKrul4,\r\n\tNaKrul5,\r\n\tNaKrul6,\r\n\tNarratorHF3,\r\n\tCompleteNut1,\r\n\tCompleteNut2,\r\n\tCompleteNut3,\r\n\tCompleteNut4,\r\n\tCompleteNut4a,\r\n\tCompleteNut5,\r\n\tCompleteNut6,\r\n\tCompleteNut7,\r\n\tCompleteNut8,\r\n\tCompleteNut9,\r\n\tCompleteNut10,\r\n\tCompleteNut11,\r\n\tCompleteNut12,\r\n\tNarratorHF6,\r\n\tNarratorHF7,\r\n\tNarratorHF8,\r\n\tNarratorHF5,\r\n\tNarratorHF9,\r\n\tNarratorHF4,\r\n\tCryptDoorOpen,\r\n\tCryptDoorClose,\r\n\tAccessibilityWeapon,\r\n\tAccessibilityArmor,\r\n\tAccessibilityGold,\r\n\tAccessibilityPotion,\r\n\tAccessibilityScroll,\r\n\tAccessibilityChest,\r\n\tAccessibilityDoor,\r\n\tAccessibilityStairs,\r\n\tAccessibilityMonster,\r\n\tAccessibilityInteract,\r\n\r\n\tLAST = AccessibilityInteract,\r\n\tNone = -1,\r\n};\r\n\r\nenum sfx_flag : uint8_t {\r\n\t// clang-format off\r\n\tsfx_STREAM   = 1 << 0,\r\n\tsfx_MISC     = 1 << 1,\r\n\tsfx_UI       = 1 << 2,\r\n\tsfx_MONK     = 1 << 3,\r\n\tsfx_ROGUE    = 1 << 4,\r\n\tsfx_WARRIOR  = 1 << 5,\r\n\tsfx_SORCERER = 1 << 6,\r\n\t// clang-format on\r\n};\r\n\r\n} // namespace devilution\r\n\r\ntemplate <>\r\nstruct magic_enum::customize::enum_range<devilution::SfxID> {\r\n\tstatic constexpr int min = static_cast<int>(devilution::SfxID::None);\r\n\tstatic constexpr int max = static_cast<int>(devilution::SfxID::LAST);\r\n};\r\n"
  },
  {
    "path": "Source/spells.cpp",
    "content": "/**\r\n * @file spells.cpp\r\n *\r\n * Implementation of functionality for casting player spells.\r\n */\r\n#include \"spells.h\"\r\n\r\n#include \"control/control.hpp\"\r\n#include \"cursor.h\"\r\n#ifdef _DEBUG\r\n#include \"debug.h\"\r\n#endif\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"gamemenu.h\"\r\n#include \"inv.h\"\r\n#include \"missiles.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n/**\r\n * @brief Gets a value indicating whether the player's current readied spell is a valid spell. Readied spells can be\r\n * invalidaded in a few scenarios where the spell comes from items, for example (like dropping the only scroll that\r\n * provided the spell).\r\n * @param player The player whose readied spell is to be checked.\r\n * @return 'true' when the readied spell is currently valid, and 'false' otherwise.\r\n */\r\nbool IsReadiedSpellValid(const Player &player)\r\n{\r\n\tswitch (player._pRSplType) {\r\n\tcase SpellType::Skill:\r\n\tcase SpellType::Spell:\r\n\tcase SpellType::Invalid:\r\n\t\treturn true;\r\n\r\n\tcase SpellType::Charges:\r\n\t\treturn (player._pISpells & GetSpellBitmask(player._pRSpell)) != 0;\r\n\r\n\tcase SpellType::Scroll:\r\n\t\treturn (player._pScrlSpells & GetSpellBitmask(player._pRSpell)) != 0;\r\n\r\n\tdefault:\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Clears the current player's readied spell selection.\r\n * @note Will force a UI redraw in case the values actually change, so that the new spell reflects on the bottom panel.\r\n * @param player The player whose readied spell is to be cleared.\r\n */\r\nvoid ClearReadiedSpell(Player &player)\r\n{\r\n\tif (player._pRSpell != SpellID::Invalid) {\r\n\t\tplayer._pRSpell = SpellID::Invalid;\r\n\t\tRedrawEverything();\r\n\t}\r\n\r\n\tif (player._pRSplType != SpellType::Invalid) {\r\n\t\tplayer._pRSplType = SpellType::Invalid;\r\n\t\tRedrawEverything();\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nbool IsValidSpell(SpellID spl)\r\n{\r\n\treturn spl > SpellID::Null && static_cast<size_t>(spl) < SpellsData.size();\r\n}\r\n\r\nbool IsValidSpellFrom(int spellFrom)\r\n{\r\n\tif (spellFrom == 0)\r\n\t\treturn true;\r\n\tif (spellFrom >= INVITEM_INV_FIRST && spellFrom <= INVITEM_INV_LAST)\r\n\t\treturn true;\r\n\tif (spellFrom >= INVITEM_BELT_FIRST && spellFrom <= INVITEM_BELT_LAST)\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\nbool IsWallSpell(SpellID spl)\r\n{\r\n\treturn spl == SpellID::FireWall || spl == SpellID::LightningWall;\r\n}\r\n\r\nbool TargetsMonster(SpellID id)\r\n{\r\n\treturn id == SpellID::Fireball\r\n\t    || id == SpellID::FireWall\r\n\t    || id == SpellID::Inferno\r\n\t    || id == SpellID::Lightning\r\n\t    || id == SpellID::StoneCurse\r\n\t    || id == SpellID::FlameWave;\r\n}\r\n\r\nint GetManaAmount(const Player &player, SpellID sn)\r\n{\r\n\tint ma; // mana amount\r\n\r\n\t// mana adjust\r\n\tint adj = 0;\r\n\r\n\t// spell level\r\n\tconst int sl = std::max(player.GetSpellLevel(sn) - 1, 0);\r\n\r\n\tif (sl > 0) {\r\n\t\tadj = sl * GetSpellData(sn).sManaAdj;\r\n\t}\r\n\tif (sn == SpellID::Firebolt) {\r\n\t\tadj /= 2;\r\n\t}\r\n\tif (sn == SpellID::Resurrect && sl > 0) {\r\n\t\tadj = sl * (GetSpellData(SpellID::Resurrect).sManaCost / 8);\r\n\t}\r\n\r\n\tif (sn == SpellID::Healing || sn == SpellID::HealOther) {\r\n\t\tma = (GetSpellData(SpellID::Healing).sManaCost + 2 * player.getCharacterLevel() - adj);\r\n\t} else if (GetSpellData(sn).sManaCost == 255) {\r\n\t\tma = (player._pMaxManaBase >> 6) - adj;\r\n\t} else {\r\n\t\tma = (GetSpellData(sn).sManaCost - adj);\r\n\t}\r\n\r\n\tma = std::max(ma, 0);\r\n\tma <<= 6;\r\n\r\n\tif (gbIsHellfire && player._pClass == HeroClass::Sorcerer) {\r\n\t\tma /= 2;\r\n\t} else if (player._pClass == HeroClass::Rogue || player._pClass == HeroClass::Monk || player._pClass == HeroClass::Bard) {\r\n\t\tma -= ma / 4;\r\n\t}\r\n\r\n\tif (GetSpellData(sn).sMinMana > ma >> 6) {\r\n\t\tma = GetSpellData(sn).sMinMana << 6;\r\n\t}\r\n\r\n\treturn ma;\r\n}\r\n\r\nvoid ConsumeSpell(Player &player, SpellID sn)\r\n{\r\n\tswitch (player.executedSpell.spellType) {\r\n\tcase SpellType::Skill:\r\n\tcase SpellType::Invalid:\r\n\t\tbreak;\r\n\tcase SpellType::Scroll:\r\n\t\tConsumeScroll(player);\r\n\t\tbreak;\r\n\tcase SpellType::Charges:\r\n\t\tConsumeStaffCharge(player);\r\n\t\tbreak;\r\n\tcase SpellType::Spell:\r\n#ifdef _DEBUG\r\n\t\tif (DebugGodMode)\r\n\t\t\tbreak;\r\n#endif\r\n\t\tint ma = GetManaAmount(player, sn);\r\n\t\tplayer._pMana -= ma;\r\n\t\tplayer._pManaBase -= ma;\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t\tbreak;\r\n\t}\r\n\tif (sn == SpellID::BloodStar) {\r\n\t\tApplyPlrDamage(DamageType::Physical, player, 5);\r\n\t}\r\n\tif (sn == SpellID::BoneSpirit) {\r\n\t\tApplyPlrDamage(DamageType::Physical, player, 6);\r\n\t}\r\n}\r\n\r\nvoid EnsureValidReadiedSpell(Player &player)\r\n{\r\n\tif (!IsReadiedSpellValid(player)) {\r\n\t\tClearReadiedSpell(player);\r\n\t}\r\n}\r\n\r\nSpellCheckResult CheckSpell(const Player &player, SpellID sn, SpellType st, bool manaonly)\r\n{\r\n#ifdef _DEBUG\r\n\tif (DebugGodMode)\r\n\t\treturn SpellCheckResult::Success;\r\n#endif\r\n\r\n\tif (!manaonly && pcurs != CURSOR_HAND) {\r\n\t\treturn SpellCheckResult::Fail_Busy;\r\n\t}\r\n\r\n\tif (st == SpellType::Skill) {\r\n\t\treturn SpellCheckResult::Success;\r\n\t}\r\n\r\n\tif (player.GetSpellLevel(sn) <= 0) {\r\n\t\treturn SpellCheckResult::Fail_Level0;\r\n\t}\r\n\r\n\tif (player._pMana < GetManaAmount(player, sn) || HasAnyOf(player._pIFlags, ItemSpecialEffect::NoMana)) {\r\n\t\treturn SpellCheckResult::Fail_NoMana;\r\n\t}\r\n\r\n\treturn SpellCheckResult::Success;\r\n}\r\n\r\nvoid CastSpell(Player &player, SpellID spl, WorldTilePosition src, WorldTilePosition dst, int spllvl)\r\n{\r\n\tDirection dir = player._pdir;\r\n\tif (IsWallSpell(spl)) {\r\n\t\tdir = player.tempDirection;\r\n\t}\r\n\r\n\tbool fizzled = false;\r\n\tconst SpellData &spellData = GetSpellData(spl);\r\n\tfor (size_t i = 0; i < sizeof(spellData.sMissiles) / sizeof(spellData.sMissiles[0]) && spellData.sMissiles[i] != MissileID::Null; i++) {\r\n\t\tMissile *missile = AddMissile(src, dst, dir, spellData.sMissiles[i], TARGET_MONSTERS, player, 0, spllvl);\r\n\t\tfizzled |= (missile == nullptr);\r\n\t}\r\n\tif (spl == SpellID::ChargedBolt) {\r\n\t\tfor (int i = (spllvl / 2) + 3; i > 0; i--) {\r\n\t\t\tMissile *missile = AddMissile(src, dst, dir, MissileID::ChargedBolt, TARGET_MONSTERS, player, 0, spllvl);\r\n\t\t\tfizzled |= (missile == nullptr);\r\n\t\t}\r\n\t}\r\n\tif (!fizzled) {\r\n\t\tConsumeSpell(player, spl);\r\n\t}\r\n}\r\n\r\nvoid SpawnResurrectBeam(Player &caster, Player &target)\r\n{\r\n\tAddMissile(\r\n\t    target.position.tile,\r\n\t    target.position.tile,\r\n\t    Direction::South,\r\n\t    MissileID::ResurrectBeam,\r\n\t    TARGET_MONSTERS,\r\n\t    caster.getId(),\r\n\t    0,\r\n\t    0);\r\n}\r\n\r\nvoid ApplyResurrect(Player &target)\r\n{\r\n\tif (&target == MyPlayer) {\r\n\t\tMyPlayerIsDead = false;\r\n\t\tgamemenu_off();\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t\tRedrawComponent(PanelDrawComponent::Mana);\r\n\t}\r\n\r\n\tClrPlrPath(target);\r\n\ttarget.destAction = ACTION_NONE;\r\n\ttarget._pInvincible = false;\r\n\tSyncInitPlrPos(target);\r\n\r\n\tint hp = 10 << 6;\r\n\tif (target._pMaxHPBase < (10 << 6)) {\r\n\t\thp = target._pMaxHPBase;\r\n\t}\r\n\tSetPlayerHitPoints(target, hp);\r\n\r\n\ttarget._pHPBase = target._pHitPoints + (target._pMaxHPBase - target._pMaxHP); // CODEFIX: does the same stuff as SetPlayerHitPoints above, can be removed\r\n\ttarget._pMana = 0;\r\n\ttarget._pManaBase = target._pMana + (target._pMaxManaBase - target._pMaxMana);\r\n\r\n\ttarget._pmode = PM_STAND;\r\n\r\n\tCalcPlrInv(target, true);\r\n\r\n\tif (target.isOnActiveLevel()) {\r\n\t\tStartStand(target, target._pdir);\r\n\t}\r\n}\r\n\r\nvoid DoHealOther(const Player &caster, Player &target)\r\n{\r\n\tif (target.hasNoLife()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tint hp = (GenerateRnd(10) + 1) << 6;\r\n\tfor (unsigned i = 0; i < caster.getCharacterLevel(); i++) {\r\n\t\thp += (GenerateRnd(4) + 1) << 6;\r\n\t}\r\n\tfor (int i = 0; i < caster.GetSpellLevel(SpellID::HealOther); i++) {\r\n\t\thp += (GenerateRnd(6) + 1) << 6;\r\n\t}\r\n\r\n\tif (caster._pClass == HeroClass::Warrior || caster._pClass == HeroClass::Barbarian) {\r\n\t\thp *= 2;\r\n\t} else if (caster._pClass == HeroClass::Rogue || caster._pClass == HeroClass::Bard) {\r\n\t\thp += hp / 2;\r\n\t} else if (caster._pClass == HeroClass::Monk) {\r\n\t\thp *= 3;\r\n\t}\r\n\r\n\ttarget._pHitPoints = std::min(target._pHitPoints + hp, target._pMaxHP);\r\n\ttarget._pHPBase = std::min(target._pHPBase + hp, target._pMaxHPBase);\r\n\r\n\tif (&target == MyPlayer) {\r\n\t\tRedrawComponent(PanelDrawComponent::Health);\r\n\t}\r\n}\r\n\r\nint GetSpellBookLevel(SpellID s)\r\n{\r\n\tif (gbIsSpawn) {\r\n\t\tswitch (s) {\r\n\t\tcase SpellID::StoneCurse:\r\n\t\tcase SpellID::Guardian:\r\n\t\tcase SpellID::Golem:\r\n\t\tcase SpellID::Elemental:\r\n\t\tcase SpellID::BloodStar:\r\n\t\tcase SpellID::BoneSpirit:\r\n\t\t\treturn -1;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (static_cast<uint8_t>(s) >= SpellsData.size()) {\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn GetSpellData(s).sBookLvl;\r\n}\r\n\r\nint GetSpellStaffLevel(SpellID s)\r\n{\r\n\tif (gbIsSpawn) {\r\n\t\tswitch (s) {\r\n\t\tcase SpellID::StoneCurse:\r\n\t\tcase SpellID::Guardian:\r\n\t\tcase SpellID::Golem:\r\n\t\tcase SpellID::Apocalypse:\r\n\t\tcase SpellID::Elemental:\r\n\t\tcase SpellID::BloodStar:\r\n\t\tcase SpellID::BoneSpirit:\r\n\t\t\treturn -1;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif (static_cast<uint8_t>(s) >= SpellsData.size()) {\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn GetSpellData(s).sStaffLvl;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/spells.h",
    "content": "/**\r\n * @file spells.h\r\n *\r\n * Interface of functionality for casting player spells.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/world_tile.hpp\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class SpellCheckResult : uint8_t {\r\n\tSuccess,\r\n\tFail_NoMana,\r\n\tFail_Level0,\r\n\tFail_Busy,\r\n};\r\n\r\nbool IsValidSpell(SpellID spl);\r\nbool IsValidSpellFrom(int spellFrom);\r\nbool IsWallSpell(SpellID spl);\r\nbool TargetsMonster(SpellID id);\r\nint GetManaAmount(const Player &player, SpellID sn);\r\nvoid ConsumeSpell(Player &player, SpellID sn);\r\nSpellCheckResult CheckSpell(const Player &player, SpellID sn, SpellType st, bool manaonly);\r\n\r\n/**\r\n * @brief Ensures the player's current readied spell is a valid selection for the character. If the current selection is\r\n * incompatible with the player's items and spell (for example, if the player does not currently have access to the spell),\r\n * the selection is cleared.\r\n * @note Will force a UI redraw in case the values actually change, so that the new spell reflects on the bottom panel.\r\n * @param player The player whose readied spell is to be checked.\r\n */\r\nvoid EnsureValidReadiedSpell(Player &player);\r\nvoid CastSpell(Player &player, SpellID spl, WorldTilePosition src, WorldTilePosition dst, int spllvl);\r\nvoid SpawnResurrectBeam(Player &caster, Player &target);\r\nvoid ApplyResurrect(Player &target);\r\nvoid DoHealOther(const Player &caster, Player &target);\r\nint GetSpellBookLevel(SpellID s);\r\nint GetSpellStaffLevel(SpellID s);\r\n\r\n/**\r\n * @brief Gets a value that represents the specified spellID in 64bit bitmask format.\r\n * For example:\r\n *  - spell ID  1: 0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0001\r\n *  - spell ID 43: 0000.0000.0000.0000.0000.0100.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000\r\n * @param spellId The id of the spell to get a bitmask for.\r\n * @return A 64bit bitmask representation for the specified spell.\r\n */\r\nconstexpr uint64_t GetSpellBitmask(SpellID spellId)\r\n{\r\n\treturn 1ULL << (static_cast<int8_t>(spellId) - 1);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/stores.cpp",
    "content": "/**\r\n * @file stores.cpp\r\n *\r\n * Implementation of functionality for stores and towner dialogs.\r\n */\r\n#include \"stores.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/trn.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"minitext.h\"\r\n#include \"multi.h\"\r\n#include \"options.h\"\r\n#include \"panels/info_box.hpp\"\r\n#include \"qol/stash.h\"\r\n#include \"tables/townerdat.hpp\"\r\n#include \"towners.h\"\r\n#include \"utils/format_int.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nTalkID ActiveStore;\r\n\r\nint CurrentItemIndex;\r\nint8_t PlayerItemIndexes[48];\r\nItem PlayerItems[48];\r\n\r\nStaticVector<Item, NumSmithBasicItemsHf> SmithItems;\r\nint PremiumItemCount;\r\nint PremiumItemLevel;\r\nStaticVector<Item, NumSmithItemsHf> PremiumItems;\r\n\r\nStaticVector<Item, NumHealerItemsHf> HealerItems;\r\n\r\nStaticVector<Item, NumWitchItemsHf> WitchItems;\r\n\r\nint BoyItemLevel;\r\nItem BoyItem;\r\n\r\nnamespace {\r\n\r\n/** The current towner being interacted with */\r\n_talker_id TownerId;\r\n\r\n/** Is the current dialog full size */\r\nbool IsTextFullSize;\r\n\r\n/** Number of text lines in the current dialog */\r\nint NumTextLines;\r\n/** Remember currently selected text line from TextLine while displaying a dialog */\r\nint OldTextLine;\r\n/** Currently selected text line from TextLine */\r\nint CurrentTextLine;\r\n\r\nstruct STextStruct {\r\n\tenum Type : uint8_t {\r\n\t\tLabel,\r\n\t\tDivider,\r\n\t\tSelectable,\r\n\t};\r\n\r\n\tstd::string text;\r\n\tint _sval;\r\n\tint y;\r\n\tUiFlags flags;\r\n\tType type;\r\n\tuint8_t _sx;\r\n\tuint8_t _syoff;\r\n\tint cursId;\r\n\tbool cursIndent;\r\n\r\n\t[[nodiscard]] bool isDivider() const\r\n\t{\r\n\t\treturn type == Divider;\r\n\t}\r\n\t[[nodiscard]] bool isSelectable() const\r\n\t{\r\n\t\treturn type == Selectable;\r\n\t}\r\n\r\n\t[[nodiscard]] bool hasText() const\r\n\t{\r\n\t\treturn !text.empty();\r\n\t}\r\n};\r\n\r\n/** Text lines */\r\nSTextStruct TextLine[NumStoreLines];\r\n\r\n/** Whether to render the player's gold amount in the top left */\r\nbool RenderGold;\r\n\r\n/** Does the current panel have a scrollbar */\r\nbool HasScrollbar;\r\n/** Remember last scroll position */\r\nint OldScrollPos;\r\n/** Scroll position */\r\nint ScrollPos;\r\n/** Next scroll position */\r\nint NextScrollPos;\r\n/** Previous scroll position */\r\nint PreviousScrollPos;\r\n/** Countdown for the push state of the scroll up button */\r\nint8_t CountdownScrollUp;\r\n/** Countdown for the push state of the scroll down button */\r\nint8_t CountdownScrollDown;\r\n\r\n/** Remember current store while displaying a dialog */\r\nTalkID OldActiveStore;\r\n\r\n/** Temporary item used to hold the item being traded */\r\nItem TempItem;\r\n\r\n/** Maps from towner IDs to NPC names. */\r\nconst char *const TownerNames[] = {\r\n\tN_(\"Griswold\"),\r\n\tN_(\"Pepin\"),\r\n\t\"\",\r\n\tN_(\"Ogden\"),\r\n\tN_(\"Cain\"),\r\n\tN_(\"Farnham\"),\r\n\tN_(\"Adria\"),\r\n\tN_(\"Gillian\"),\r\n\tN_(\"Wirt\"),\r\n};\r\n\r\nconstexpr int PaddingTop = 32;\r\n\r\n// For most languages, line height is always 12.\r\n// This includes blank lines and divider line.\r\nconstexpr int SmallLineHeight = 12;\r\nconstexpr int SmallTextHeight = 12;\r\n\r\n// For larger small fonts (Chinese and Japanese), text lines are\r\n// taller and overflow.\r\n// We space out blank lines a bit more to give space to 3-line store items.\r\nconstexpr int LargeLineHeight = SmallLineHeight + 1;\r\nconstexpr int LargeTextHeight = 18;\r\n\r\n/**\r\n * The line index with the Back / Leave button.\r\n * This is a special button that is always the last line.\r\n *\r\n * For lists with a scrollbar, it is not selectable (mouse-only).\r\n */\r\nint BackButtonLine()\r\n{\r\n\tif (IsSmallFontTall()) {\r\n\t\treturn HasScrollbar ? 21 : 20;\r\n\t}\r\n\treturn 22;\r\n}\r\n\r\nint LineHeight()\r\n{\r\n\treturn IsSmallFontTall() ? LargeLineHeight : SmallLineHeight;\r\n}\r\n\r\nint TextHeight()\r\n{\r\n\treturn IsSmallFontTall() ? LargeTextHeight : SmallTextHeight;\r\n}\r\n\r\nvoid CalculateLineHeights()\r\n{\r\n\tTextLine[0].y = 0;\r\n\tif (IsSmallFontTall()) {\r\n\t\tfor (int i = 1; i < NumStoreLines; ++i) {\r\n\t\t\t// Space out consecutive text lines, unless they are both selectable (never the case currently).\r\n\t\t\tif (TextLine[i].hasText() && TextLine[i - 1].hasText() && !(TextLine[i].isSelectable() && TextLine[i - 1].isSelectable())) {\r\n\t\t\t\tTextLine[i].y = TextLine[i - 1].y + LargeTextHeight;\r\n\t\t\t} else {\r\n\t\t\t\tTextLine[i].y = i * LargeLineHeight;\r\n\t\t\t}\r\n\t\t}\r\n\t} else {\r\n\t\tfor (int i = 1; i < NumStoreLines; ++i) {\r\n\t\t\tTextLine[i].y = i * SmallLineHeight;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DrawSTextBack(const Surface &out)\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tClxDraw(out, { uiPosition.x + 320 + 24, 327 + uiPosition.y }, (*pSTextBoxCels)[0]);\r\n\tDrawHalfTransparentRectTo(out, uiPosition.x + 347, uiPosition.y + 28, 265, 297);\r\n}\r\n\r\nvoid DrawSSlider(const Surface &out, int y1, int y2)\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tint yd1 = y1 * 12 + 44 + uiPosition.y;\r\n\tconst int yd2 = y2 * 12 + 44 + uiPosition.y;\r\n\tif (CountdownScrollUp != -1)\r\n\t\tClxDraw(out, { uiPosition.x + 601, yd1 }, (*pSTextSlidCels)[11]);\r\n\telse\r\n\t\tClxDraw(out, { uiPosition.x + 601, yd1 }, (*pSTextSlidCels)[9]);\r\n\tif (CountdownScrollDown != -1)\r\n\t\tClxDraw(out, { uiPosition.x + 601, yd2 }, (*pSTextSlidCels)[10]);\r\n\telse\r\n\t\tClxDraw(out, { uiPosition.x + 601, yd2 }, (*pSTextSlidCels)[8]);\r\n\tyd1 += 12;\r\n\tint yd3 = yd1;\r\n\tfor (; yd3 < yd2; yd3 += 12) {\r\n\t\tClxDraw(out, { uiPosition.x + 601, yd3 }, (*pSTextSlidCels)[13]);\r\n\t}\r\n\tif (CurrentTextLine == BackButtonLine())\r\n\t\tyd3 = OldTextLine;\r\n\telse\r\n\t\tyd3 = CurrentTextLine;\r\n\tif (CurrentItemIndex > 1)\r\n\t\tyd3 = 1000 * (ScrollPos + ((yd3 - PreviousScrollPos) / 4)) / (CurrentItemIndex - 1) * (y2 * 12 - y1 * 12 - 24) / 1000;\r\n\telse\r\n\t\tyd3 = 0;\r\n\tClxDraw(out, { uiPosition.x + 601, (y1 + 1) * 12 + 44 + uiPosition.y + yd3 }, (*pSTextSlidCels)[12]);\r\n}\r\n\r\nvoid AddSLine(size_t y)\r\n{\r\n\tTextLine[y]._sx = 0;\r\n\tTextLine[y]._syoff = 0;\r\n\tTextLine[y].text.clear();\r\n\tTextLine[y].text.shrink_to_fit();\r\n\tTextLine[y].type = STextStruct::Divider;\r\n\tTextLine[y].cursId = -1;\r\n\tTextLine[y].cursIndent = false;\r\n}\r\n\r\nvoid AddSTextVal(size_t y, int val)\r\n{\r\n\tTextLine[y]._sval = val;\r\n}\r\n\r\nvoid AddSText(uint8_t x, size_t y, std::string_view text, UiFlags flags, bool sel, int cursId = -1, bool cursIndent = false)\r\n{\r\n\tTextLine[y]._sx = x;\r\n\tTextLine[y]._syoff = 0;\r\n\tTextLine[y].text.clear();\r\n\tTextLine[y].text.append(text);\r\n\tTextLine[y].flags = flags;\r\n\tTextLine[y].type = sel ? STextStruct::Selectable : STextStruct::Label;\r\n\tTextLine[y].cursId = cursId;\r\n\tTextLine[y].cursIndent = cursIndent;\r\n}\r\n\r\nvoid AddOptionsBackButton()\r\n{\r\n\tconst int line = BackButtonLine();\r\n\tAddSText(0, line, _(\"Back\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tTextLine[line]._syoff = IsSmallFontTall() ? 0 : 6;\r\n}\r\n\r\nvoid AddItemListBackButton(bool selectable = false)\r\n{\r\n\tconst int line = BackButtonLine();\r\n\tconst std::string_view text = _(\"Back\");\r\n\tif (!selectable && IsSmallFontTall()) {\r\n\t\tAddSText(0, line, text, UiFlags::ColorWhite | UiFlags::AlignRight, selectable);\r\n\t} else {\r\n\t\tAddSLine(line - 1);\r\n\t\tAddSText(0, line, text, UiFlags::ColorWhite | UiFlags::AlignCenter, selectable);\r\n\t\tTextLine[line]._syoff = 6;\r\n\t}\r\n}\r\n\r\nvoid PrintStoreItem(const Item &item, int l, UiFlags flags, bool cursIndent = false)\r\n{\r\n\tstd::string productLine;\r\n\r\n\tif (item._iIdentified) {\r\n\t\tif (item._iMagical != ITEM_QUALITY_UNIQUE) {\r\n\t\t\tif (item._iPrePower != -1) {\r\n\t\t\t\tproductLine.append(PrintItemPower(item._iPrePower, item));\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (item._iSufPower != -1) {\r\n\t\t\tif (!productLine.empty())\r\n\t\t\t\tproductLine.append(_(\",  \"));\r\n\t\t\tproductLine.append(PrintItemPower(item._iSufPower, item));\r\n\t\t}\r\n\t}\r\n\tif (item._iMiscId == IMISC_STAFF && item._iMaxCharges != 0) {\r\n\t\tif (!productLine.empty())\r\n\t\t\tproductLine.append(_(\",  \"));\r\n\t\tproductLine.append(fmt::format(fmt::runtime(_(\"Charges: {:d}/{:d}\")), item._iCharges, item._iMaxCharges));\r\n\t}\r\n\tif (!productLine.empty()) {\r\n\t\tAddSText(40, l, productLine, flags, false, -1, cursIndent);\r\n\t\tl++;\r\n\t\tproductLine.clear();\r\n\t}\r\n\r\n\tif (item._itype != ItemType::Misc) {\r\n\t\tif (item._iClass == ICLASS_WEAPON)\r\n\t\t\tproductLine = fmt::format(fmt::runtime(_(\"Damage: {:d}-{:d}  \")), item._iMinDam, item._iMaxDam);\r\n\t\telse if (item._iClass == ICLASS_ARMOR)\r\n\t\t\tproductLine = fmt::format(fmt::runtime(_(\"Armor: {:d}  \")), item._iAC);\r\n\t\tif (item._iMaxDur != DUR_INDESTRUCTIBLE && item._iMaxDur != 0)\r\n\t\t\tproductLine += fmt::format(fmt::runtime(_(\"Dur: {:d}/{:d}\")), item._iDurability, item._iMaxDur);\r\n\t\telse\r\n\t\t\tproductLine.append(_(\"Indestructible\"));\r\n\t}\r\n\r\n\tint8_t str = item._iMinStr;\r\n\tuint8_t mag = item._iMinMag;\r\n\tint8_t dex = item._iMinDex;\r\n\r\n\tif (str != 0 || mag != 0 || dex != 0) {\r\n\t\tif (!productLine.empty())\r\n\t\t\tproductLine.append(_(\",  \"));\r\n\t\tproductLine.append(_(\"Required:\"));\r\n\t\tif (str != 0)\r\n\t\t\tproductLine.append(fmt::format(fmt::runtime(_(\" {:d} Str\")), str));\r\n\t\tif (mag != 0)\r\n\t\t\tproductLine.append(fmt::format(fmt::runtime(_(\" {:d} Mag\")), mag));\r\n\t\tif (dex != 0)\r\n\t\t\tproductLine.append(fmt::format(fmt::runtime(_(\" {:d} Dex\")), dex));\r\n\t}\r\n\tAddSText(40, l++, productLine, flags, false, -1, cursIndent);\r\n}\r\n\r\nbool StoreAutoPlace(Item &item, bool persistItem)\r\n{\r\n\tPlayer &player = *MyPlayer;\r\n\r\n\tif (AutoEquipEnabled(player, item) && AutoEquip(player, item, persistItem, true)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (AutoPlaceItemInBelt(player, item, persistItem, true)) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif (persistItem) {\r\n\t\treturn AutoPlaceItemInInventory(player, item, true);\r\n\t}\r\n\r\n\treturn CanFitItemInInventory(player, item);\r\n}\r\n\r\nvoid ScrollVendorStore(std::span<Item> itemData, int storeLimit, int idx, int selling = true)\r\n{\r\n\tClearSText(5, 21);\r\n\tPreviousScrollPos = 5;\r\n\r\n\tfor (int l = 5; l < 20 && idx < storeLimit; l += 4) {\r\n\t\tconst Item &item = itemData[idx];\r\n\t\tconst UiFlags itemColor = item.getTextColorWithStatCheck();\r\n\t\tAddSText(20, l, item.getName(), itemColor, true, item._iCurs, true);\r\n\t\tAddSTextVal(l, item._iIdentified ? item._iIvalue : item._ivalue);\r\n\t\tPrintStoreItem(item, l + 1, itemColor, true);\r\n\t\tNextScrollPos = l;\r\n\t\tidx++;\r\n\t}\r\n\tif (selling) {\r\n\t\tif (CurrentTextLine != -1 && !TextLine[CurrentTextLine].isSelectable() && CurrentTextLine != BackButtonLine())\r\n\t\t\tCurrentTextLine = NextScrollPos;\r\n\t} else {\r\n\t\tNumTextLines = std::max(static_cast<int>(storeLimit) - 4, 0);\r\n\t}\r\n}\r\n\r\nvoid StartSmith()\r\n{\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 1, _(\"Welcome to the\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 3, _(\"Blacksmith's shop\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 7, _(\"Would you like to:\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 10, _(\"Talk to Griswold\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 12, _(\"Buy basic items\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 14, _(\"Buy premium items\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 16, _(\"Sell items\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 18, _(\"Repair items\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 20, _(\"Leave the shop\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSLine(5);\r\n\tCurrentItemIndex = 20;\r\n}\r\n\r\nvoid ScrollSmithBuy(int idx)\r\n{\r\n\tScrollVendorStore(SmithItems, static_cast<int>(SmithItems.size()), idx);\r\n}\r\n\r\nuint32_t TotalPlayerGold()\r\n{\r\n\treturn MyPlayer->_pGold + Stash.gold;\r\n}\r\n\r\n// TODO: Change `_iIvalue` to be unsigned instead of passing `int` here.\r\nbool PlayerCanAfford(int price)\r\n{\r\n\treturn TotalPlayerGold() >= static_cast<uint32_t>(price);\r\n}\r\n\r\nvoid StartSmithBuy()\r\n{\r\n\tIsTextFullSize = true;\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"I have these items for sale:\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\tScrollSmithBuy(ScrollPos);\r\n\tAddItemListBackButton();\r\n\r\n\tCurrentItemIndex = 0;\r\n\tfor (Item &item : SmithItems) {\r\n\t\titem._iStatFlag = MyPlayer->CanUseItem(item);\r\n\t\tCurrentItemIndex++;\r\n\t}\r\n\r\n\tNumTextLines = std::max(CurrentItemIndex - 4, 0);\r\n}\r\n\r\nvoid ScrollSmithPremiumBuy(int boughtitems)\r\n{\r\n\tint idx = 0;\r\n\tfor (; boughtitems != 0; idx++) {\r\n\t\tif (!PremiumItems[idx].isEmpty())\r\n\t\t\tboughtitems--;\r\n\t}\r\n\r\n\tScrollVendorStore(PremiumItems, static_cast<int>(PremiumItems.size()), idx);\r\n}\r\n\r\nbool StartSmithPremiumBuy()\r\n{\r\n\tCurrentItemIndex = 0;\r\n\tfor (Item &item : PremiumItems) {\r\n\t\titem._iStatFlag = MyPlayer->CanUseItem(item);\r\n\t\tCurrentItemIndex++;\r\n\t}\r\n\tif (CurrentItemIndex == 0) {\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 14;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tIsTextFullSize = true;\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"I have these premium items for sale:\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\tAddItemListBackButton();\r\n\r\n\tNumTextLines = std::max(CurrentItemIndex - 4, 0);\r\n\r\n\tScrollSmithPremiumBuy(ScrollPos);\r\n\r\n\treturn true;\r\n}\r\n\r\nbool SmithSellOk(int i)\r\n{\r\n\tItem *pI;\r\n\r\n\tif (i >= 0) {\r\n\t\tpI = &MyPlayer->InvList[i];\r\n\t} else {\r\n\t\tpI = &MyPlayer->SpdList[-(i + 1)];\r\n\t}\r\n\r\n\tif (pI->isEmpty())\r\n\t\treturn false;\r\n\r\n\tif (pI->_iMiscId > IMISC_OILFIRST && pI->_iMiscId < IMISC_OILLAST)\r\n\t\treturn true;\r\n\r\n\tif (pI->_itype == ItemType::Misc)\r\n\t\treturn false;\r\n\tif (pI->_itype == ItemType::Gold)\r\n\t\treturn false;\r\n\tif (pI->_itype == ItemType::Staff && (!gbIsHellfire || IsValidSpell(pI->_iSpell)))\r\n\t\treturn false;\r\n\tif (pI->_iClass == ICLASS_QUEST)\r\n\t\treturn false;\r\n\tif (pI->IDidx == IDI_LAZSTAFF)\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid ScrollSmithSell(int idx)\r\n{\r\n\tScrollVendorStore(PlayerItems, CurrentItemIndex, idx, false);\r\n}\r\n\r\nvoid StartSmithSell()\r\n{\r\n\tIsTextFullSize = true;\r\n\tbool sellOk = false;\r\n\tCurrentItemIndex = 0;\r\n\r\n\tfor (auto &item : PlayerItems) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tfor (int8_t i = 0; i < myPlayer._pNumInv; i++) {\r\n\t\tif (CurrentItemIndex >= 48)\r\n\t\t\tbreak;\r\n\t\tif (SmithSellOk(i)) {\r\n\t\t\tsellOk = true;\r\n\t\t\tPlayerItems[CurrentItemIndex] = myPlayer.InvList[i];\r\n\r\n\t\t\tif (PlayerItems[CurrentItemIndex]._iMagical != ITEM_QUALITY_NORMAL && PlayerItems[CurrentItemIndex]._iIdentified)\r\n\t\t\t\tPlayerItems[CurrentItemIndex]._ivalue = PlayerItems[CurrentItemIndex]._iIvalue;\r\n\r\n\t\t\tPlayerItems[CurrentItemIndex]._ivalue = std::max(PlayerItems[CurrentItemIndex]._ivalue / 4, 1);\r\n\t\t\tPlayerItems[CurrentItemIndex]._iIvalue = PlayerItems[CurrentItemIndex]._ivalue;\r\n\t\t\tPlayerItemIndexes[CurrentItemIndex] = i;\r\n\t\t\tCurrentItemIndex++;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tif (CurrentItemIndex >= 48)\r\n\t\t\tbreak;\r\n\t\tif (SmithSellOk(-(i + 1))) {\r\n\t\t\tsellOk = true;\r\n\t\t\tPlayerItems[CurrentItemIndex] = myPlayer.SpdList[i];\r\n\r\n\t\t\tif (PlayerItems[CurrentItemIndex]._iMagical != ITEM_QUALITY_NORMAL && PlayerItems[CurrentItemIndex]._iIdentified)\r\n\t\t\t\tPlayerItems[CurrentItemIndex]._ivalue = PlayerItems[CurrentItemIndex]._iIvalue;\r\n\r\n\t\t\tPlayerItems[CurrentItemIndex]._ivalue = std::max(PlayerItems[CurrentItemIndex]._ivalue / 4, 1);\r\n\t\t\tPlayerItems[CurrentItemIndex]._iIvalue = PlayerItems[CurrentItemIndex]._ivalue;\r\n\t\t\tPlayerItemIndexes[CurrentItemIndex] = -(i + 1);\r\n\t\t\tCurrentItemIndex++;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!sellOk) {\r\n\t\tHasScrollbar = false;\r\n\r\n\t\tRenderGold = true;\r\n\t\tAddSText(20, 1, _(\"You have nothing I want.\"), UiFlags::ColorWhitegold, false);\r\n\t\tAddSLine(3);\r\n\t\tAddItemListBackButton(/*selectable=*/true);\r\n\t\treturn;\r\n\t}\r\n\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\tNumTextLines = myPlayer._pNumInv;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"Which item is for sale?\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\tScrollSmithSell(ScrollPos);\r\n\tAddItemListBackButton();\r\n}\r\n\r\nbool SmithRepairOk(int i)\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tconst Item &item = myPlayer.InvList[i];\r\n\r\n\tif (item.isEmpty())\r\n\t\treturn false;\r\n\tif (item._itype == ItemType::Misc)\r\n\t\treturn false;\r\n\tif (item._itype == ItemType::Gold)\r\n\t\treturn false;\r\n\tif (item._iDurability == item._iMaxDur)\r\n\t\treturn false;\r\n\tif (item._iMaxDur == DUR_INDESTRUCTIBLE)\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid StartSmithRepair()\r\n{\r\n\tIsTextFullSize = true;\r\n\tCurrentItemIndex = 0;\r\n\r\n\tfor (auto &item : PlayerItems) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tauto &helmet = myPlayer.InvBody[INVLOC_HEAD];\r\n\tif (!helmet.isEmpty() && helmet._iDurability != helmet._iMaxDur) {\r\n\t\tAddStoreHoldRepair(&helmet, -1);\r\n\t}\r\n\r\n\tauto &armor = myPlayer.InvBody[INVLOC_CHEST];\r\n\tif (!armor.isEmpty() && armor._iDurability != armor._iMaxDur) {\r\n\t\tAddStoreHoldRepair(&armor, -2);\r\n\t}\r\n\r\n\tauto &leftHand = myPlayer.InvBody[INVLOC_HAND_LEFT];\r\n\tif (!leftHand.isEmpty() && leftHand._iDurability != leftHand._iMaxDur) {\r\n\t\tAddStoreHoldRepair(&leftHand, -3);\r\n\t}\r\n\r\n\tauto &rightHand = myPlayer.InvBody[INVLOC_HAND_RIGHT];\r\n\tif (!rightHand.isEmpty() && rightHand._iDurability != rightHand._iMaxDur) {\r\n\t\tAddStoreHoldRepair(&rightHand, -4);\r\n\t}\r\n\r\n\tfor (int i = 0; i < myPlayer._pNumInv; i++) {\r\n\t\tif (CurrentItemIndex >= 48)\r\n\t\t\tbreak;\r\n\t\tif (SmithRepairOk(i)) {\r\n\t\t\tAddStoreHoldRepair(&myPlayer.InvList[i], i);\r\n\t\t}\r\n\t}\r\n\r\n\tif (CurrentItemIndex == 0) {\r\n\t\tHasScrollbar = false;\r\n\r\n\t\tRenderGold = true;\r\n\t\tAddSText(20, 1, _(\"You have nothing to repair.\"), UiFlags::ColorWhitegold, false);\r\n\t\tAddSLine(3);\r\n\t\tAddItemListBackButton(/*selectable=*/true);\r\n\t\treturn;\r\n\t}\r\n\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\tNumTextLines = myPlayer._pNumInv;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"Repair which item?\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\r\n\tScrollSmithSell(ScrollPos);\r\n\tAddItemListBackButton();\r\n}\r\n\r\nvoid StartWitch()\r\n{\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 2, _(\"Witch's shack\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 9, _(\"Would you like to:\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 12, _(\"Talk to Adria\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 14, _(\"Buy items\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 16, _(\"Sell items\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 18, _(\"Recharge staves\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 20, _(\"Leave the shack\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSLine(5);\r\n\tCurrentItemIndex = 20;\r\n}\r\n\r\nvoid ScrollWitchBuy(int idx)\r\n{\r\n\tScrollVendorStore(WitchItems, static_cast<int>(WitchItems.size()), idx);\r\n}\r\n\r\nvoid WitchBookLevel(Item &bookItem)\r\n{\r\n\tif (bookItem._iMiscId != IMISC_BOOK)\r\n\t\treturn;\r\n\tbookItem._iMinMag = GetSpellData(bookItem._iSpell).minInt;\r\n\tuint8_t spellLevel = MyPlayer->_pSplLvl[static_cast<int8_t>(bookItem._iSpell)];\r\n\twhile (spellLevel > 0) {\r\n\t\tbookItem._iMinMag += 20 * bookItem._iMinMag / 100;\r\n\t\tspellLevel--;\r\n\t\tif (bookItem._iMinMag + 20 * bookItem._iMinMag / 100 > 255) {\r\n\t\t\tbookItem._iMinMag = 255;\r\n\t\t\tspellLevel = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid StartWitchBuy()\r\n{\r\n\tIsTextFullSize = true;\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\tNumTextLines = 20;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"I have these items for sale:\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\tScrollWitchBuy(ScrollPos);\r\n\tAddItemListBackButton();\r\n\r\n\tCurrentItemIndex = 0;\r\n\tfor (Item &item : WitchItems) {\r\n\t\tWitchBookLevel(item);\r\n\t\titem._iStatFlag = MyPlayer->CanUseItem(item);\r\n\t\tCurrentItemIndex++;\r\n\t}\r\n\tNumTextLines = std::max(CurrentItemIndex - 4, 0);\r\n}\r\n\r\nbool WitchSellOk(int i)\r\n{\r\n\tItem *pI;\r\n\r\n\tbool rv = false;\r\n\r\n\tif (i >= 0)\r\n\t\tpI = &MyPlayer->InvList[i];\r\n\telse\r\n\t\tpI = &MyPlayer->SpdList[-(i + 1)];\r\n\r\n\tif (pI->_itype == ItemType::Misc)\r\n\t\trv = true;\r\n\tif (pI->_iMiscId > 29 && pI->_iMiscId < 41)\r\n\t\trv = false;\r\n\tif (pI->_iClass == ICLASS_QUEST)\r\n\t\trv = false;\r\n\tif (pI->_itype == ItemType::Staff && (!gbIsHellfire || IsValidSpell(pI->_iSpell)))\r\n\t\trv = true;\r\n\tif (pI->IDidx >= IDI_FIRSTQUEST && pI->IDidx <= IDI_LASTQUEST)\r\n\t\trv = false;\r\n\tif (pI->IDidx == IDI_LAZSTAFF)\r\n\t\trv = false;\r\n\treturn rv;\r\n}\r\n\r\nvoid StartWitchSell()\r\n{\r\n\tIsTextFullSize = true;\r\n\tbool sellok = false;\r\n\tCurrentItemIndex = 0;\r\n\r\n\tfor (auto &item : PlayerItems) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tfor (int i = 0; i < myPlayer._pNumInv; i++) {\r\n\t\tif (CurrentItemIndex >= 48)\r\n\t\t\tbreak;\r\n\t\tif (WitchSellOk(i)) {\r\n\t\t\tsellok = true;\r\n\t\t\tPlayerItems[CurrentItemIndex] = myPlayer.InvList[i];\r\n\r\n\t\t\tif (PlayerItems[CurrentItemIndex]._iMagical != ITEM_QUALITY_NORMAL && PlayerItems[CurrentItemIndex]._iIdentified)\r\n\t\t\t\tPlayerItems[CurrentItemIndex]._ivalue = PlayerItems[CurrentItemIndex]._iIvalue;\r\n\r\n\t\t\tPlayerItems[CurrentItemIndex]._ivalue = std::max(PlayerItems[CurrentItemIndex]._ivalue / 4, 1);\r\n\t\t\tPlayerItems[CurrentItemIndex]._iIvalue = PlayerItems[CurrentItemIndex]._ivalue;\r\n\t\t\tPlayerItemIndexes[CurrentItemIndex] = i;\r\n\t\t\tCurrentItemIndex++;\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tif (CurrentItemIndex >= 48)\r\n\t\t\tbreak;\r\n\t\tif (!myPlayer.SpdList[i].isEmpty() && WitchSellOk(-(i + 1))) {\r\n\t\t\tsellok = true;\r\n\t\t\tPlayerItems[CurrentItemIndex] = myPlayer.SpdList[i];\r\n\r\n\t\t\tif (PlayerItems[CurrentItemIndex]._iMagical != ITEM_QUALITY_NORMAL && PlayerItems[CurrentItemIndex]._iIdentified)\r\n\t\t\t\tPlayerItems[CurrentItemIndex]._ivalue = PlayerItems[CurrentItemIndex]._iIvalue;\r\n\r\n\t\t\tPlayerItems[CurrentItemIndex]._ivalue = std::max(PlayerItems[CurrentItemIndex]._ivalue / 4, 1);\r\n\t\t\tPlayerItems[CurrentItemIndex]._iIvalue = PlayerItems[CurrentItemIndex]._ivalue;\r\n\t\t\tPlayerItemIndexes[CurrentItemIndex] = -(i + 1);\r\n\t\t\tCurrentItemIndex++;\r\n\t\t}\r\n\t}\r\n\r\n\tif (!sellok) {\r\n\t\tHasScrollbar = false;\r\n\r\n\t\tRenderGold = true;\r\n\t\tAddSText(20, 1, _(\"You have nothing I want.\"), UiFlags::ColorWhitegold, false);\r\n\r\n\t\tAddSLine(3);\r\n\t\tAddItemListBackButton(/*selectable=*/true);\r\n\t\treturn;\r\n\t}\r\n\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\tNumTextLines = myPlayer._pNumInv;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"Which item is for sale?\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\tScrollSmithSell(ScrollPos);\r\n\tAddItemListBackButton();\r\n}\r\n\r\nbool WitchRechargeOk(int i)\r\n{\r\n\tconst auto &item = MyPlayer->InvList[i];\r\n\r\n\tif (item._itype == ItemType::Staff && item._iCharges != item._iMaxCharges) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif ((item._iMiscId == IMISC_UNIQUE || item._iMiscId == IMISC_STAFF) && item._iCharges < item._iMaxCharges) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid AddStoreHoldRecharge(Item itm, int8_t i)\r\n{\r\n\tPlayerItems[CurrentItemIndex] = itm;\r\n\tPlayerItems[CurrentItemIndex]._ivalue += GetSpellData(itm._iSpell).staffCost();\r\n\tPlayerItems[CurrentItemIndex]._ivalue = PlayerItems[CurrentItemIndex]._ivalue * (PlayerItems[CurrentItemIndex]._iMaxCharges - PlayerItems[CurrentItemIndex]._iCharges) / (PlayerItems[CurrentItemIndex]._iMaxCharges * 2);\r\n\tPlayerItems[CurrentItemIndex]._iIvalue = PlayerItems[CurrentItemIndex]._ivalue;\r\n\tPlayerItemIndexes[CurrentItemIndex] = i;\r\n\tCurrentItemIndex++;\r\n}\r\n\r\nvoid StartWitchRecharge()\r\n{\r\n\tIsTextFullSize = true;\r\n\tbool rechargeok = false;\r\n\tCurrentItemIndex = 0;\r\n\r\n\tfor (auto &item : PlayerItems) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\tconst auto &leftHand = myPlayer.InvBody[INVLOC_HAND_LEFT];\r\n\r\n\tif ((leftHand._itype == ItemType::Staff || leftHand._iMiscId == IMISC_UNIQUE) && leftHand._iCharges != leftHand._iMaxCharges) {\r\n\t\trechargeok = true;\r\n\t\tAddStoreHoldRecharge(leftHand, -1);\r\n\t}\r\n\r\n\tfor (int i = 0; i < myPlayer._pNumInv; i++) {\r\n\t\tif (CurrentItemIndex >= 48)\r\n\t\t\tbreak;\r\n\t\tif (WitchRechargeOk(i)) {\r\n\t\t\trechargeok = true;\r\n\t\t\tAddStoreHoldRecharge(myPlayer.InvList[i], i);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!rechargeok) {\r\n\t\tHasScrollbar = false;\r\n\r\n\t\tRenderGold = true;\r\n\t\tAddSText(20, 1, _(\"You have nothing to recharge.\"), UiFlags::ColorWhitegold, false);\r\n\t\tAddSLine(3);\r\n\t\tAddItemListBackButton(/*selectable=*/true);\r\n\t\treturn;\r\n\t}\r\n\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\tNumTextLines = myPlayer._pNumInv;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"Recharge which item?\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\tScrollSmithSell(ScrollPos);\r\n\tAddItemListBackButton();\r\n}\r\n\r\nvoid StoreNoMoney()\r\n{\r\n\tStartStore(OldActiveStore);\r\n\tHasScrollbar = false;\r\n\tIsTextFullSize = true;\r\n\tRenderGold = true;\r\n\tClearSText(5, 23);\r\n\tAddSText(0, 14, _(\"You do not have enough gold\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n}\r\n\r\nvoid StoreNoRoom()\r\n{\r\n\tStartStore(OldActiveStore);\r\n\tHasScrollbar = false;\r\n\tClearSText(5, 23);\r\n\tAddSText(0, 14, _(\"You do not have enough room in inventory\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n}\r\n\r\nvoid StoreConfirm(Item &item)\r\n{\r\n\tStartStore(OldActiveStore);\r\n\tHasScrollbar = false;\r\n\tClearSText(5, 23);\r\n\r\n\tconst UiFlags itemColor = item.getTextColorWithStatCheck();\r\n\tAddSText(20, 8, item.getName(), itemColor, false);\r\n\tAddSTextVal(8, item._iIvalue);\r\n\tPrintStoreItem(item, 9, itemColor);\r\n\r\n\tstd::string_view prompt;\r\n\r\n\tswitch (OldActiveStore) {\r\n\tcase TalkID::BoyBuy:\r\n\t\tprompt = _(\"Do we have a deal?\");\r\n\t\tbreak;\r\n\tcase TalkID::StorytellerIdentify:\r\n\t\tprompt = _(\"Are you sure you want to identify this item?\");\r\n\t\tbreak;\r\n\tcase TalkID::HealerBuy:\r\n\tcase TalkID::SmithPremiumBuy:\r\n\tcase TalkID::WitchBuy:\r\n\tcase TalkID::SmithBuy:\r\n\t\tprompt = _(\"Are you sure you want to buy this item?\");\r\n\t\tbreak;\r\n\tcase TalkID::WitchRecharge:\r\n\t\tprompt = _(\"Are you sure you want to recharge this item?\");\r\n\t\tbreak;\r\n\tcase TalkID::SmithSell:\r\n\tcase TalkID::WitchSell:\r\n\t\tprompt = _(\"Are you sure you want to sell this item?\");\r\n\t\tbreak;\r\n\tcase TalkID::SmithRepair:\r\n\t\tprompt = _(\"Are you sure you want to repair this item?\");\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tapp_fatal(StrCat(\"Unknown store dialog \", static_cast<int>(OldActiveStore)));\r\n\t}\r\n\tAddSText(0, 15, prompt, UiFlags::ColorWhite | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 18, _(\"Yes\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 20, _(\"No\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n}\r\n\r\nvoid StartBoy()\r\n{\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 2, _(\"Wirt the Peg-legged boy\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSLine(5);\r\n\tif (!BoyItem.isEmpty()) {\r\n\t\tAddSText(0, 8, _(\"Talk to Wirt\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\t\tAddSText(0, 12, _(\"I have something for sale,\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\t\tAddSText(0, 14, _(\"but it will cost 50 gold\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\t\tAddSText(0, 16, _(\"just to take a look. \"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\t\tAddSText(0, 18, _(\"What have you got?\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\t\tAddSText(0, 20, _(\"Say goodbye\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\t} else {\r\n\t\tAddSText(0, 12, _(\"Talk to Wirt\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\t\tAddSText(0, 18, _(\"Say goodbye\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\t}\r\n}\r\n\r\nvoid SStartBoyBuy()\r\n{\r\n\tIsTextFullSize = true;\r\n\tHasScrollbar = false;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"I have this item for sale:\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\r\n\tBoyItem._iStatFlag = MyPlayer->CanUseItem(BoyItem);\r\n\tconst UiFlags itemColor = BoyItem.getTextColorWithStatCheck();\r\n\tAddSText(20, 10, BoyItem.getName(), itemColor, true, BoyItem._iCurs, true);\r\n\tif (gbIsHellfire)\r\n\t\tAddSTextVal(10, BoyItem._iIvalue - (BoyItem._iIvalue / 4));\r\n\telse\r\n\t\tAddSTextVal(10, BoyItem._iIvalue + (BoyItem._iIvalue / 2));\r\n\tPrintStoreItem(BoyItem, 11, itemColor, true);\r\n\r\n\t{\r\n\t\t// Add a Leave button. Unlike the other item list back buttons,\r\n\t\t// this one has different text and different layout in LargerSmallFont locales.\r\n\t\tconst int line = BackButtonLine();\r\n\t\tAddSLine(line - 1);\r\n\t\tAddSText(0, line, _(\"Leave\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\t\tTextLine[line]._syoff = 6;\r\n\t}\r\n}\r\n\r\nvoid HealPlayer()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (myPlayer._pHitPoints != myPlayer._pMaxHP) {\r\n\t\tPlaySFX(SfxID::CastHealing);\r\n\t}\r\n\tmyPlayer._pHitPoints = myPlayer._pMaxHP;\r\n\tmyPlayer._pHPBase = myPlayer._pMaxHPBase;\r\n\tRedrawComponent(PanelDrawComponent::Health);\r\n}\r\n\r\nvoid StartHealer()\r\n{\r\n\tHealPlayer();\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 1, _(\"Welcome to the\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 3, _(\"Healer's home\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 9, _(\"Would you like to:\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 12, _(\"Talk to Pepin\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 14, _(\"Buy items\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 18, _(\"Leave Healer's home\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSLine(5);\r\n\tCurrentItemIndex = 20;\r\n}\r\n\r\nvoid ScrollHealerBuy(int idx)\r\n{\r\n\tScrollVendorStore(HealerItems, static_cast<int>(HealerItems.size()), idx);\r\n}\r\n\r\nvoid StartHealerBuy()\r\n{\r\n\tIsTextFullSize = true;\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"I have these items for sale:\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\r\n\tScrollHealerBuy(ScrollPos);\r\n\tAddItemListBackButton();\r\n\r\n\tCurrentItemIndex = 0;\r\n\tfor (Item &item : HealerItems) {\r\n\t\titem._iStatFlag = MyPlayer->CanUseItem(item);\r\n\t\tCurrentItemIndex++;\r\n\t}\r\n\r\n\tNumTextLines = std::max(CurrentItemIndex - 4, 0);\r\n}\r\n\r\nvoid StartStoryteller()\r\n{\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 2, _(\"The Town Elder\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 9, _(\"Would you like to:\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 12, _(\"Talk to Cain\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 14, _(\"Identify an item\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 18, _(\"Say goodbye\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSLine(5);\r\n}\r\n\r\nbool IdItemOk(Item *i)\r\n{\r\n\tif (i->isEmpty()) {\r\n\t\treturn false;\r\n\t}\r\n\tif (i->_iMagical == ITEM_QUALITY_NORMAL) {\r\n\t\treturn false;\r\n\t}\r\n\treturn !i->_iIdentified;\r\n}\r\n\r\nvoid AddStoreHoldId(Item itm, int8_t i)\r\n{\r\n\tPlayerItems[CurrentItemIndex] = itm;\r\n\tPlayerItems[CurrentItemIndex]._ivalue = 100;\r\n\tPlayerItems[CurrentItemIndex]._iIvalue = 100;\r\n\tPlayerItemIndexes[CurrentItemIndex] = i;\r\n\tCurrentItemIndex++;\r\n}\r\n\r\nvoid StartStorytellerIdentify()\r\n{\r\n\tbool idok = false;\r\n\tIsTextFullSize = true;\r\n\tCurrentItemIndex = 0;\r\n\r\n\tfor (auto &item : PlayerItems) {\r\n\t\titem.clear();\r\n\t}\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tauto &helmet = myPlayer.InvBody[INVLOC_HEAD];\r\n\tif (IdItemOk(&helmet)) {\r\n\t\tidok = true;\r\n\t\tAddStoreHoldId(helmet, -1);\r\n\t}\r\n\r\n\tauto &armor = myPlayer.InvBody[INVLOC_CHEST];\r\n\tif (IdItemOk(&armor)) {\r\n\t\tidok = true;\r\n\t\tAddStoreHoldId(armor, -2);\r\n\t}\r\n\r\n\tauto &leftHand = myPlayer.InvBody[INVLOC_HAND_LEFT];\r\n\tif (IdItemOk(&leftHand)) {\r\n\t\tidok = true;\r\n\t\tAddStoreHoldId(leftHand, -3);\r\n\t}\r\n\r\n\tauto &rightHand = myPlayer.InvBody[INVLOC_HAND_RIGHT];\r\n\tif (IdItemOk(&rightHand)) {\r\n\t\tidok = true;\r\n\t\tAddStoreHoldId(rightHand, -4);\r\n\t}\r\n\r\n\tauto &leftRing = myPlayer.InvBody[INVLOC_RING_LEFT];\r\n\tif (IdItemOk(&leftRing)) {\r\n\t\tidok = true;\r\n\t\tAddStoreHoldId(leftRing, -5);\r\n\t}\r\n\r\n\tauto &rightRing = myPlayer.InvBody[INVLOC_RING_RIGHT];\r\n\tif (IdItemOk(&rightRing)) {\r\n\t\tidok = true;\r\n\t\tAddStoreHoldId(rightRing, -6);\r\n\t}\r\n\r\n\tauto &amulet = myPlayer.InvBody[INVLOC_AMULET];\r\n\tif (IdItemOk(&amulet)) {\r\n\t\tidok = true;\r\n\t\tAddStoreHoldId(amulet, -7);\r\n\t}\r\n\r\n\tfor (int i = 0; i < myPlayer._pNumInv; i++) {\r\n\t\tif (CurrentItemIndex >= 48)\r\n\t\t\tbreak;\r\n\t\tauto &item = myPlayer.InvList[i];\r\n\t\tif (IdItemOk(&item)) {\r\n\t\t\tidok = true;\r\n\t\t\tAddStoreHoldId(item, i);\r\n\t\t}\r\n\t}\r\n\r\n\tif (!idok) {\r\n\t\tHasScrollbar = false;\r\n\r\n\t\tRenderGold = true;\r\n\t\tAddSText(20, 1, _(\"You have nothing to identify.\"), UiFlags::ColorWhitegold, false);\r\n\t\tAddSLine(3);\r\n\t\tAddItemListBackButton(/*selectable=*/true);\r\n\t\treturn;\r\n\t}\r\n\r\n\tHasScrollbar = true;\r\n\tScrollPos = 0;\r\n\tNumTextLines = myPlayer._pNumInv;\r\n\r\n\tRenderGold = true;\r\n\tAddSText(20, 1, _(\"Identify which item?\"), UiFlags::ColorWhitegold, false);\r\n\tAddSLine(3);\r\n\r\n\tScrollSmithSell(ScrollPos);\r\n\tAddItemListBackButton();\r\n}\r\n\r\nvoid StartStorytellerIdentifyShow(Item &item)\r\n{\r\n\tStartStore(OldActiveStore);\r\n\tHasScrollbar = false;\r\n\tClearSText(5, 23);\r\n\r\n\tconst UiFlags itemColor = item.getTextColorWithStatCheck();\r\n\r\n\tAddSText(0, 7, _(\"This item is:\"), UiFlags::ColorWhite | UiFlags::AlignCenter, false);\r\n\tAddSText(20, 11, item.getName(), itemColor, false);\r\n\tPrintStoreItem(item, 12, itemColor);\r\n\tAddSText(0, 18, _(\"Done\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n}\r\n\r\nvoid StartTalk()\r\n{\r\n\tint la;\r\n\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 2, fmt::format(fmt::runtime(_(\"Talk to {:s}\")), _(TownerNames[TownerId])), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSLine(5);\r\n\tif (gbIsSpawn) {\r\n\t\tAddSText(0, 10, fmt::format(fmt::runtime(_(\"Talking to {:s}\")), _(TownerNames[TownerId])), UiFlags::ColorWhite | UiFlags::AlignCenter, false);\r\n\t\tAddSText(0, 12, _(\"is not available\"), UiFlags::ColorWhite | UiFlags::AlignCenter, false);\r\n\t\tAddSText(0, 14, _(\"in the shareware\"), UiFlags::ColorWhite | UiFlags::AlignCenter, false);\r\n\t\tAddSText(0, 16, _(\"version\"), UiFlags::ColorWhite | UiFlags::AlignCenter, false);\r\n\t\tAddOptionsBackButton();\r\n\t\treturn;\r\n\t}\r\n\r\n\tint sn = 0;\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qactive == QUEST_ACTIVE && GetTownerQuestDialog(TownerId, quest._qidx) != TEXT_NONE && quest._qlog)\r\n\t\t\tsn++;\r\n\t}\r\n\r\n\tif (sn > 6) {\r\n\t\tsn = 14 - (sn / 2);\r\n\t\tla = 1;\r\n\t} else {\r\n\t\tsn = 15 - sn;\r\n\t\tla = 2;\r\n\t}\r\n\r\n\tconst int sn2 = sn - 2;\r\n\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qactive == QUEST_ACTIVE && GetTownerQuestDialog(TownerId, quest._qidx) != TEXT_NONE && quest._qlog) {\r\n\t\t\tAddSText(0, sn, _(QuestsData[quest._qidx]._qlstr), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\t\t\tsn += la;\r\n\t\t}\r\n\t}\r\n\tAddSText(0, sn2, _(\"Gossip\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddOptionsBackButton();\r\n}\r\n\r\nvoid StartTavern()\r\n{\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 1, _(\"Welcome to the\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 3, _(\"Rising Sun\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 9, _(\"Would you like to:\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 12, _(\"Talk to Ogden\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 18, _(\"Leave the tavern\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSLine(5);\r\n\tCurrentItemIndex = 20;\r\n}\r\n\r\nvoid StartBarmaid()\r\n{\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 2, _(\"Gillian\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 9, _(\"Would you like to:\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 12, _(\"Talk to Gillian\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 14, _(\"Access Storage\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 18, _(\"Say goodbye\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSLine(5);\r\n\tCurrentItemIndex = 20;\r\n}\r\n\r\nvoid StartDrunk()\r\n{\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tAddSText(0, 2, _(\"Farnham the Drunk\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 9, _(\"Would you like to:\"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);\r\n\tAddSText(0, 12, _(\"Talk to Farnham\"), UiFlags::ColorBlue | UiFlags::AlignCenter, true);\r\n\tAddSText(0, 18, _(\"Say Goodbye\"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);\r\n\tAddSLine(5);\r\n\tCurrentItemIndex = 20;\r\n}\r\n\r\nvoid SmithEnter()\r\n{\r\n\tswitch (CurrentTextLine) {\r\n\tcase 10:\r\n\t\tTownerId = TOWN_SMITH;\r\n\t\tOldTextLine = 10;\r\n\t\tOldActiveStore = TalkID::Smith;\r\n\t\tStartStore(TalkID::Gossip);\r\n\t\tbreak;\r\n\tcase 12:\r\n\t\tStartStore(TalkID::SmithBuy);\r\n\t\tbreak;\r\n\tcase 14:\r\n\t\tStartStore(TalkID::SmithPremiumBuy);\r\n\t\tbreak;\r\n\tcase 16:\r\n\t\tStartStore(TalkID::SmithSell);\r\n\t\tbreak;\r\n\tcase 18:\r\n\t\tStartStore(TalkID::SmithRepair);\r\n\t\tbreak;\r\n\tcase 20:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Purchases an item from the smith.\r\n */\r\nvoid SmithBuyItem(Item &item)\r\n{\r\n\tTakePlrsMoney(item._iIvalue);\r\n\tif (item._iMagical == ITEM_QUALITY_NORMAL)\r\n\t\titem._iIdentified = false;\r\n\tStoreAutoPlace(item, true);\r\n\tint idx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\tSmithItems.erase(SmithItems.begin() + idx);\r\n\tCalcPlrInv(*MyPlayer, true);\r\n}\r\n\r\nvoid SmithBuyEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 12;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldScrollPos = ScrollPos;\r\n\tOldActiveStore = TalkID::SmithBuy;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\tif (!PlayerCanAfford(SmithItems[idx]._iIvalue)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!StoreAutoPlace(SmithItems[idx], false)) {\r\n\t\tStartStore(TalkID::NoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = SmithItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\n/**\r\n * @brief Purchases a premium item from the smith.\r\n */\r\nvoid SmithBuyPItem(Item &item)\r\n{\r\n\tTakePlrsMoney(item._iIvalue);\r\n\tif (item._iMagical == ITEM_QUALITY_NORMAL)\r\n\t\titem._iIdentified = false;\r\n\tStoreAutoPlace(item, true);\r\n\r\n\tint idx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\tReplacePremium(*MyPlayer, idx);\r\n}\r\n\r\nvoid SmithPremiumBuyEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 14;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldActiveStore = TalkID::SmithPremiumBuy;\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldScrollPos = ScrollPos;\r\n\r\n\tint idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!PlayerCanAfford(PremiumItems[idx]._iIvalue)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!StoreAutoPlace(PremiumItems[idx], false)) {\r\n\t\tStartStore(TalkID::NoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = PremiumItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\nbool StoreGoldFit(Item &item)\r\n{\r\n\tconst int cost = item._iIvalue;\r\n\r\n\tconst Size itemSize = GetInventorySize(item);\r\n\tconst int itemRoomForGold = itemSize.width * itemSize.height * MaxGold;\r\n\r\n\tif (cost <= itemRoomForGold) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn cost <= itemRoomForGold + RoomForGold();\r\n}\r\n\r\n/**\r\n * @brief Sells an item from the player's inventory or belt.\r\n */\r\nvoid StoreSellItem()\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tint idx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\tif (PlayerItemIndexes[idx] >= 0)\r\n\t\tmyPlayer.RemoveInvItem(PlayerItemIndexes[idx]);\r\n\telse\r\n\t\tmyPlayer.RemoveSpdBarItem(-(PlayerItemIndexes[idx] + 1));\r\n\r\n\tconst int cost = PlayerItems[idx]._iIvalue;\r\n\tCurrentItemIndex--;\r\n\tif (idx != CurrentItemIndex) {\r\n\t\twhile (idx < CurrentItemIndex) {\r\n\t\t\tPlayerItems[idx] = PlayerItems[idx + 1];\r\n\t\t\tPlayerItemIndexes[idx] = PlayerItemIndexes[idx + 1];\r\n\t\t\tidx++;\r\n\t\t}\r\n\t}\r\n\r\n\tAddGoldToInventory(myPlayer, cost);\r\n\r\n\tmyPlayer._pGold += cost;\r\n}\r\n\r\nvoid SmithSellEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 16;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldActiveStore = TalkID::SmithSell;\r\n\tOldScrollPos = ScrollPos;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!StoreGoldFit(PlayerItems[idx])) {\r\n\t\tStartStore(TalkID::NoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = PlayerItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\n/**\r\n * @brief Repairs an item in the player's inventory or body in the smith.\r\n */\r\nvoid SmithRepairItem(int price)\r\n{\r\n\tconst int idx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\tPlayerItems[idx]._iDurability = PlayerItems[idx]._iMaxDur;\r\n\r\n\tconst int8_t i = PlayerItemIndexes[idx];\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tif (i < 0) {\r\n\t\tif (i == -1)\r\n\t\t\tmyPlayer.InvBody[INVLOC_HEAD]._iDurability = myPlayer.InvBody[INVLOC_HEAD]._iMaxDur;\r\n\t\tif (i == -2)\r\n\t\t\tmyPlayer.InvBody[INVLOC_CHEST]._iDurability = myPlayer.InvBody[INVLOC_CHEST]._iMaxDur;\r\n\t\tif (i == -3)\r\n\t\t\tmyPlayer.InvBody[INVLOC_HAND_LEFT]._iDurability = myPlayer.InvBody[INVLOC_HAND_LEFT]._iMaxDur;\r\n\t\tif (i == -4)\r\n\t\t\tmyPlayer.InvBody[INVLOC_HAND_RIGHT]._iDurability = myPlayer.InvBody[INVLOC_HAND_RIGHT]._iMaxDur;\r\n\t\tTakePlrsMoney(price);\r\n\t\treturn;\r\n\t}\r\n\r\n\tmyPlayer.InvList[i]._iDurability = myPlayer.InvList[i]._iMaxDur;\r\n\tTakePlrsMoney(price);\r\n}\r\n\r\nvoid SmithRepairEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 18;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldActiveStore = TalkID::SmithRepair;\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldScrollPos = ScrollPos;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!PlayerCanAfford(PlayerItems[idx]._iIvalue)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = PlayerItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\nvoid WitchEnter()\r\n{\r\n\tswitch (CurrentTextLine) {\r\n\tcase 12:\r\n\t\tOldTextLine = 12;\r\n\t\tTownerId = TOWN_WITCH;\r\n\t\tOldActiveStore = TalkID::Witch;\r\n\t\tStartStore(TalkID::Gossip);\r\n\t\tbreak;\r\n\tcase 14:\r\n\t\tStartStore(TalkID::WitchBuy);\r\n\t\tbreak;\r\n\tcase 16:\r\n\t\tStartStore(TalkID::WitchSell);\r\n\t\tbreak;\r\n\tcase 18:\r\n\t\tStartStore(TalkID::WitchRecharge);\r\n\t\tbreak;\r\n\tcase 20:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Purchases an item from the witch.\r\n */\r\nvoid WitchBuyItem(Item &item)\r\n{\r\n\tint idx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (idx < 3)\r\n\t\titem._iSeed = AdvanceRndSeed();\r\n\r\n\tTakePlrsMoney(item._iIvalue);\r\n\tStoreAutoPlace(item, true);\r\n\r\n\tif (idx >= 3) {\r\n\t\tWitchItems.erase(WitchItems.begin() + idx);\r\n\t}\r\n\r\n\tCalcPlrInv(*MyPlayer, true);\r\n}\r\n\r\nvoid WitchBuyEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Witch);\r\n\t\tCurrentTextLine = 14;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldScrollPos = ScrollPos;\r\n\tOldActiveStore = TalkID::WitchBuy;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!PlayerCanAfford(WitchItems[idx]._iIvalue)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!StoreAutoPlace(WitchItems[idx], false)) {\r\n\t\tStartStore(TalkID::NoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = WitchItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\nvoid WitchSellEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Witch);\r\n\t\tCurrentTextLine = 16;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldActiveStore = TalkID::WitchSell;\r\n\tOldScrollPos = ScrollPos;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!StoreGoldFit(PlayerItems[idx])) {\r\n\t\tStartStore(TalkID::NoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = PlayerItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\n/**\r\n * @brief Recharges an item in the player's inventory or body in the witch.\r\n */\r\nvoid WitchRechargeItem(int price)\r\n{\r\n\tconst int idx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\tPlayerItems[idx]._iCharges = PlayerItems[idx]._iMaxCharges;\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tconst int8_t i = PlayerItemIndexes[idx];\r\n\tif (i < 0) {\r\n\t\tmyPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges = myPlayer.InvBody[INVLOC_HAND_LEFT]._iMaxCharges;\r\n\t\tNetSendCmdChItem(true, INVLOC_HAND_LEFT);\r\n\t} else {\r\n\t\tmyPlayer.InvList[i]._iCharges = myPlayer.InvList[i]._iMaxCharges;\r\n\t\tNetSyncInvItem(myPlayer, i);\r\n\t}\r\n\r\n\tTakePlrsMoney(price);\r\n\tCalcPlrInv(myPlayer, true);\r\n}\r\n\r\nvoid WitchRechargeEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Witch);\r\n\t\tCurrentTextLine = 18;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldActiveStore = TalkID::WitchRecharge;\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldScrollPos = ScrollPos;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!PlayerCanAfford(PlayerItems[idx]._iIvalue)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = PlayerItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\nvoid BoyEnter()\r\n{\r\n\tif (!BoyItem.isEmpty() && CurrentTextLine == 18) {\r\n\t\tif (!PlayerCanAfford(50)) {\r\n\t\t\tOldActiveStore = TalkID::Boy;\r\n\t\t\tOldTextLine = 18;\r\n\t\t\tOldScrollPos = ScrollPos;\r\n\t\t\tStartStore(TalkID::NoMoney);\r\n\t\t} else {\r\n\t\t\tTakePlrsMoney(50);\r\n\t\t\tStartStore(TalkID::BoyBuy);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ((CurrentTextLine != 8 && !BoyItem.isEmpty()) || (CurrentTextLine != 12 && BoyItem.isEmpty())) {\r\n\t\tActiveStore = TalkID::None;\r\n\t\treturn;\r\n\t}\r\n\r\n\tTownerId = TOWN_PEGBOY;\r\n\tOldActiveStore = TalkID::Boy;\r\n\tOldTextLine = CurrentTextLine;\r\n\tStartStore(TalkID::Gossip);\r\n}\r\n\r\nvoid BoyBuyItem(Item &item, int itemPrice)\r\n{\r\n\tTakePlrsMoney(itemPrice);\r\n\tStoreAutoPlace(item, true);\r\n\titem.clear();\r\n\tOldActiveStore = TalkID::Boy;\r\n\tCalcPlrInv(*MyPlayer, true);\r\n\tOldTextLine = 12;\r\n}\r\n\r\n/**\r\n * @brief Purchases an item from the healer.\r\n */\r\nvoid HealerBuyItem(Item &item)\r\n{\r\n\tint idx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\tif (!gbIsMultiplayer) {\r\n\t\tif (idx < 2)\r\n\t\t\titem._iSeed = AdvanceRndSeed();\r\n\t} else {\r\n\t\tif (idx < 3)\r\n\t\t\titem._iSeed = AdvanceRndSeed();\r\n\t}\r\n\r\n\tTakePlrsMoney(item._iIvalue);\r\n\tif (item._iMagical == ITEM_QUALITY_NORMAL)\r\n\t\titem._iIdentified = false;\r\n\tStoreAutoPlace(item, true);\r\n\r\n\tif (!gbIsMultiplayer) {\r\n\t\tif (idx < 2)\r\n\t\t\treturn;\r\n\t} else {\r\n\t\tif (idx < 3)\r\n\t\t\treturn;\r\n\t}\r\n\tidx = OldScrollPos + ((OldTextLine - PreviousScrollPos) / 4);\r\n\tHealerItems.erase(HealerItems.begin() + idx);\r\n\tCalcPlrInv(*MyPlayer, true);\r\n}\r\n\r\nvoid BoyBuyEnter()\r\n{\r\n\tif (CurrentTextLine != 10) {\r\n\t\tActiveStore = TalkID::None;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldActiveStore = TalkID::BoyBuy;\r\n\tOldScrollPos = ScrollPos;\r\n\tOldTextLine = 10;\r\n\tint price = BoyItem._iIvalue;\r\n\tif (gbIsHellfire)\r\n\t\tprice -= BoyItem._iIvalue / 4;\r\n\telse\r\n\t\tprice += BoyItem._iIvalue / 2;\r\n\r\n\tif (!PlayerCanAfford(price)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!StoreAutoPlace(BoyItem, false)) {\r\n\t\tStartStore(TalkID::NoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = BoyItem;\r\n\tTempItem._iIvalue = price;\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\nvoid StorytellerIdentifyItem(Item &item)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tconst int8_t idx = PlayerItemIndexes[((OldTextLine - PreviousScrollPos) / 4) + OldScrollPos];\r\n\tif (idx < 0) {\r\n\t\tif (idx == -1)\r\n\t\t\tmyPlayer.InvBody[INVLOC_HEAD]._iIdentified = true;\r\n\t\tif (idx == -2)\r\n\t\t\tmyPlayer.InvBody[INVLOC_CHEST]._iIdentified = true;\r\n\t\tif (idx == -3)\r\n\t\t\tmyPlayer.InvBody[INVLOC_HAND_LEFT]._iIdentified = true;\r\n\t\tif (idx == -4)\r\n\t\t\tmyPlayer.InvBody[INVLOC_HAND_RIGHT]._iIdentified = true;\r\n\t\tif (idx == -5)\r\n\t\t\tmyPlayer.InvBody[INVLOC_RING_LEFT]._iIdentified = true;\r\n\t\tif (idx == -6)\r\n\t\t\tmyPlayer.InvBody[INVLOC_RING_RIGHT]._iIdentified = true;\r\n\t\tif (idx == -7)\r\n\t\t\tmyPlayer.InvBody[INVLOC_AMULET]._iIdentified = true;\r\n\t} else {\r\n\t\tmyPlayer.InvList[idx]._iIdentified = true;\r\n\t}\r\n\titem._iIdentified = true;\r\n\tTakePlrsMoney(item._iIvalue);\r\n\tCalcPlrInv(myPlayer, true);\r\n}\r\n\r\nvoid ConfirmEnter(Item &item)\r\n{\r\n\tif (CurrentTextLine == 18) {\r\n\t\tswitch (OldActiveStore) {\r\n\t\tcase TalkID::SmithBuy:\r\n\t\t\tSmithBuyItem(item);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::SmithSell:\r\n\t\tcase TalkID::WitchSell:\r\n\t\t\tStoreSellItem();\r\n\t\t\tbreak;\r\n\t\tcase TalkID::SmithRepair:\r\n\t\t\tSmithRepairItem(item._iIvalue);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::WitchBuy:\r\n\t\t\tWitchBuyItem(item);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::WitchRecharge:\r\n\t\t\tWitchRechargeItem(item._iIvalue);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::BoyBuy:\r\n\t\t\tBoyBuyItem(BoyItem, item._iIvalue);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::HealerBuy:\r\n\t\t\tHealerBuyItem(item);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::StorytellerIdentify:\r\n\t\t\tStorytellerIdentifyItem(item);\r\n\t\t\tStartStore(TalkID::StorytellerIdentifyShow);\r\n\t\t\treturn;\r\n\t\tcase TalkID::SmithPremiumBuy:\r\n\t\t\tSmithBuyPItem(item);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tStartStore(OldActiveStore);\r\n\r\n\tif (CurrentTextLine == BackButtonLine())\r\n\t\treturn;\r\n\r\n\tCurrentTextLine = OldTextLine;\r\n\tScrollPos = std::min(OldScrollPos, NumTextLines);\r\n\r\n\twhile (CurrentTextLine != -1 && !TextLine[CurrentTextLine].isSelectable()) {\r\n\t\tCurrentTextLine--;\r\n\t}\r\n}\r\n\r\nvoid HealerEnter()\r\n{\r\n\tswitch (CurrentTextLine) {\r\n\tcase 12:\r\n\t\tOldTextLine = 12;\r\n\t\tTownerId = TOWN_HEALER;\r\n\t\tOldActiveStore = TalkID::Healer;\r\n\t\tStartStore(TalkID::Gossip);\r\n\t\tbreak;\r\n\tcase 14:\r\n\t\tStartStore(TalkID::HealerBuy);\r\n\t\tbreak;\r\n\tcase 18:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid HealerBuyEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Healer);\r\n\t\tCurrentTextLine = 14;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldScrollPos = ScrollPos;\r\n\tOldActiveStore = TalkID::HealerBuy;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!PlayerCanAfford(HealerItems[idx]._iIvalue)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!StoreAutoPlace(HealerItems[idx], false)) {\r\n\t\tStartStore(TalkID::NoRoom);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = HealerItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\nvoid StorytellerEnter()\r\n{\r\n\tswitch (CurrentTextLine) {\r\n\tcase 12:\r\n\t\tOldTextLine = 12;\r\n\t\tTownerId = TOWN_STORY;\r\n\t\tOldActiveStore = TalkID::Storyteller;\r\n\t\tStartStore(TalkID::Gossip);\r\n\t\tbreak;\r\n\tcase 14:\r\n\t\tStartStore(TalkID::StorytellerIdentify);\r\n\t\tbreak;\r\n\tcase 18:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid StorytellerIdentifyEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(TalkID::Storyteller);\r\n\t\tCurrentTextLine = 14;\r\n\t\treturn;\r\n\t}\r\n\r\n\tOldActiveStore = TalkID::StorytellerIdentify;\r\n\tOldTextLine = CurrentTextLine;\r\n\tOldScrollPos = ScrollPos;\r\n\r\n\tconst int idx = ScrollPos + ((CurrentTextLine - PreviousScrollPos) / 4);\r\n\r\n\tif (!PlayerCanAfford(PlayerItems[idx]._iIvalue)) {\r\n\t\tStartStore(TalkID::NoMoney);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTempItem = PlayerItems[idx];\r\n\tStartStore(TalkID::Confirm);\r\n}\r\n\r\nvoid TalkEnter()\r\n{\r\n\tif (CurrentTextLine == BackButtonLine()) {\r\n\t\tStartStore(OldActiveStore);\r\n\t\tCurrentTextLine = OldTextLine;\r\n\t\treturn;\r\n\t}\r\n\r\n\tint sn = 0;\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qactive == QUEST_ACTIVE && GetTownerQuestDialog(TownerId, quest._qidx) != TEXT_NONE && quest._qlog)\r\n\t\t\tsn++;\r\n\t}\r\n\tint la = 2;\r\n\tif (sn > 6) {\r\n\t\tsn = 14 - (sn / 2);\r\n\t\tla = 1;\r\n\t} else {\r\n\t\tsn = 15 - sn;\r\n\t}\r\n\r\n\tif (CurrentTextLine == sn - 2) {\r\n\t\tTowner *target = GetTowner(TownerId);\r\n\t\tassert(target != nullptr);\r\n\t\tInitQTextMsg(target->gossip);\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (auto &quest : Quests) {\r\n\t\tif (quest._qactive == QUEST_ACTIVE && GetTownerQuestDialog(TownerId, quest._qidx) != TEXT_NONE && quest._qlog) {\r\n\t\t\tif (sn == CurrentTextLine) {\r\n\t\t\t\tInitQTextMsg(GetTownerQuestDialog(TownerId, quest._qidx));\r\n\t\t\t}\r\n\t\t\tsn += la;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid TavernEnter()\r\n{\r\n\tswitch (CurrentTextLine) {\r\n\tcase 12:\r\n\t\tOldTextLine = 12;\r\n\t\tTownerId = TOWN_TAVERN;\r\n\t\tOldActiveStore = TalkID::Tavern;\r\n\t\tStartStore(TalkID::Gossip);\r\n\t\tbreak;\r\n\tcase 18:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid BarmaidEnter()\r\n{\r\n\tswitch (CurrentTextLine) {\r\n\tcase 12:\r\n\t\tOldTextLine = 12;\r\n\t\tTownerId = TOWN_BMAID;\r\n\t\tOldActiveStore = TalkID::Barmaid;\r\n\t\tStartStore(TalkID::Gossip);\r\n\t\tbreak;\r\n\tcase 14:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tIsStashOpen = true;\r\n\t\tStash.RefreshItemStatFlags();\r\n\t\tinvflag = true;\r\n\t\tif (ControlMode != ControlTypes::KeyboardAndMouse) {\r\n\t\t\tif (pcurs == CURSOR_DISARM)\r\n\t\t\t\tNewCursor(CURSOR_HAND);\r\n\t\t\tFocusOnInventory();\r\n\t\t}\r\n\t\tbreak;\r\n\tcase 18:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid DrunkEnter()\r\n{\r\n\tswitch (CurrentTextLine) {\r\n\tcase 12:\r\n\t\tOldTextLine = 12;\r\n\t\tTownerId = TOWN_DRUNK;\r\n\t\tOldActiveStore = TalkID::Drunk;\r\n\t\tStartStore(TalkID::Gossip);\r\n\t\tbreak;\r\n\tcase 18:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nint TakeGold(Player &player, int cost, bool skipMaxPiles)\r\n{\r\n\tfor (int i = 0; i < player._pNumInv; i++) {\r\n\t\tauto &item = player.InvList[i];\r\n\t\tif (item._itype != ItemType::Gold || (skipMaxPiles && item._ivalue == MaxGold))\r\n\t\t\tcontinue;\r\n\r\n\t\tif (cost < item._ivalue) {\r\n\t\t\titem._ivalue -= cost;\r\n\t\t\tSetPlrHandGoldCurs(player.InvList[i]);\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\tcost -= item._ivalue;\r\n\t\tplayer.RemoveInvItem(i);\r\n\t\ti = -1;\r\n\t}\r\n\r\n\treturn cost;\r\n}\r\n\r\nvoid DrawSelector(const Surface &out, const Rectangle &rect, std::string_view text, UiFlags flags)\r\n{\r\n\tconst int lineWidth = GetLineWidth(text);\r\n\r\n\tint x1 = rect.position.x - 20;\r\n\tif (HasAnyOf(flags, UiFlags::AlignCenter))\r\n\t\tx1 += (rect.size.width - lineWidth) / 2;\r\n\r\n\tClxDraw(out, { x1, rect.position.y + 13 }, (*pSPentSpn2Cels)[PentSpn2Spin()]);\r\n\r\n\tint x2 = rect.position.x + rect.size.width + 5;\r\n\tif (HasAnyOf(flags, UiFlags::AlignCenter))\r\n\t\tx2 = rect.position.x + (rect.size.width - lineWidth) / 2 + lineWidth + 5;\r\n\r\n\tClxDraw(out, { x2, rect.position.y + 13 }, (*pSPentSpn2Cels)[PentSpn2Spin()]);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid AddStoreHoldRepair(Item *itm, int8_t i)\r\n{\r\n\tItem *item;\r\n\tint v;\r\n\r\n\titem = &PlayerItems[CurrentItemIndex];\r\n\tPlayerItems[CurrentItemIndex] = *itm;\r\n\r\n\tconst int due = item->_iMaxDur - item->_iDurability;\r\n\tif (item->_iMagical != ITEM_QUALITY_NORMAL && item->_iIdentified) {\r\n\t\tv = 30 * item->_iIvalue * due / (item->_iMaxDur * 100 * 2);\r\n\t\tif (v == 0)\r\n\t\t\treturn;\r\n\t} else {\r\n\t\tv = item->_ivalue * due / (item->_iMaxDur * 2);\r\n\t\tv = std::max(v, 1);\r\n\t}\r\n\titem->_iIvalue = v;\r\n\titem->_ivalue = v;\r\n\tPlayerItemIndexes[CurrentItemIndex] = i;\r\n\tCurrentItemIndex++;\r\n}\r\n\r\nvoid InitStores()\r\n{\r\n\tClearSText(0, NumStoreLines);\r\n\tActiveStore = TalkID::None;\r\n\tIsTextFullSize = false;\r\n\tHasScrollbar = false;\r\n\tPremiumItemCount = 0;\r\n\tPremiumItemLevel = 1;\r\n\r\n\tSmithItems.clear();\r\n\tWitchItems.clear();\r\n\tHealerItems.clear();\r\n\tPremiumItems.clear();\r\n\r\n\tBoyItem.clear();\r\n\tBoyItemLevel = 0;\r\n}\r\n\r\nvoid SetupTownStores()\r\n{\r\n\tconst Player &myPlayer = *MyPlayer;\r\n\r\n\tint l = myPlayer.getCharacterLevel() / 2;\r\n\tif (!gbIsMultiplayer) {\r\n\t\tl = 0;\r\n\t\tfor (int i = 0; i < NUMLEVELS; i++) {\r\n\t\t\tif (myPlayer._pLvlVisited[i])\r\n\t\t\t\tl = i;\r\n\t\t}\r\n\t}\r\n\r\n\tl = std::clamp(l + 2, 6, 16);\r\n\tSpawnSmith(l);\r\n\tSpawnWitch(l);\r\n\tSpawnHealer(l);\r\n\tSpawnBoy(myPlayer.getCharacterLevel());\r\n\tSpawnPremium(myPlayer);\r\n}\r\n\r\nvoid FreeStoreMem()\r\n{\r\n\tif (*GetOptions().Gameplay.showItemGraphicsInStores) {\r\n\t\tFreeHalfSizeItemSprites();\r\n\t}\r\n\tActiveStore = TalkID::None;\r\n\tfor (STextStruct &entry : TextLine) {\r\n\t\tentry.text.clear();\r\n\t\tentry.text.shrink_to_fit();\r\n\t}\r\n}\r\n\r\nvoid PrintSString(const Surface &out, int margin, int line, std::string_view text, UiFlags flags, int price, int cursId, bool cursIndent)\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tint sx = uiPosition.x + 32 + margin;\r\n\tif (!IsTextFullSize) {\r\n\t\tsx += 320;\r\n\t}\r\n\r\n\tconst int sy = uiPosition.y + PaddingTop + TextLine[line].y + TextLine[line]._syoff;\r\n\r\n\tint width = IsTextFullSize ? 575 : 255;\r\n\tif (HasScrollbar && line >= 4 && line <= 20) {\r\n\t\twidth -= 9; // Space for the selector\r\n\t}\r\n\twidth -= margin * 2;\r\n\r\n\tconst Rectangle rect { { sx, sy }, { width, 0 } };\r\n\r\n\t// Space reserved for item graphic is based on the size of 2x3 cursor sprites\r\n\tconstexpr int CursWidth = INV_SLOT_SIZE_PX * 2;\r\n\tconstexpr int HalfCursWidth = CursWidth / 2;\r\n\r\n\tif (*GetOptions().Gameplay.showItemGraphicsInStores && cursId >= 0) {\r\n\t\tconst Size size = GetInvItemSize(static_cast<int>(CURSOR_FIRSTITEM) + cursId);\r\n\t\tconst bool useHalfSize = size.width > INV_SLOT_SIZE_PX || size.height > INV_SLOT_SIZE_PX;\r\n\t\tconst bool useRed = HasAnyOf(flags, UiFlags::ColorRed);\r\n\t\tconst ClxSprite sprite = useHalfSize\r\n\t\t    ? (useRed ? GetHalfSizeItemSpriteRed(cursId) : GetHalfSizeItemSprite(cursId))\r\n\t\t    : GetInvItemSprite(static_cast<int>(CURSOR_FIRSTITEM) + cursId);\r\n\t\tconst Point position {\r\n\t\t\trect.position.x + (HalfCursWidth - sprite.width()) / 2,\r\n\t\t\trect.position.y + (TextHeight() * 3 + sprite.height()) / 2\r\n\t\t};\r\n\t\tif (useHalfSize || !useRed) {\r\n\t\t\tClxDraw(out, position, sprite);\r\n\t\t} else {\r\n\t\t\tClxDrawTRN(out, position, sprite, GetInfravisionTRN());\r\n\t\t}\r\n\t}\r\n\r\n\tif (*GetOptions().Gameplay.showItemGraphicsInStores && cursIndent) {\r\n\t\tconst Rectangle textRect { { rect.position.x + HalfCursWidth + 8, rect.position.y }, { rect.size.width - HalfCursWidth + 8, rect.size.height } };\r\n\t\tDrawString(out, text, textRect, { .flags = flags });\r\n\t} else {\r\n\t\tDrawString(out, text, rect, { .flags = flags });\r\n\t}\r\n\r\n\tif (price > 0)\r\n\t\tDrawString(out, FormatInteger(price), rect, { .flags = flags | UiFlags::AlignRight });\r\n\r\n\tif (CurrentTextLine == line) {\r\n\t\tDrawSelector(out, rect, text, flags);\r\n\t}\r\n}\r\n\r\nvoid DrawSLine(const Surface &out, int sy)\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tint sx = 26;\r\n\tint width = 587;\r\n\r\n\tif (!IsTextFullSize) {\r\n\t\tsx += SidePanelSize.width;\r\n\t\twidth -= SidePanelSize.width;\r\n\t}\r\n\r\n\tuint8_t *src = out.at(uiPosition.x + sx, uiPosition.y + 25);\r\n\tuint8_t *dst = out.at(uiPosition.x + sx, sy);\r\n\r\n\tfor (int i = 0; i < 3; i++, src += out.pitch(), dst += out.pitch())\r\n\t\tmemcpy(dst, src, width);\r\n}\r\n\r\nvoid DrawSTextHelp()\r\n{\r\n\tCurrentTextLine = -1;\r\n\tIsTextFullSize = true;\r\n}\r\n\r\nvoid ClearSText(int s, int e)\r\n{\r\n\tfor (int i = s; i < e; i++) {\r\n\t\tTextLine[i]._sx = 0;\r\n\t\tTextLine[i]._syoff = 0;\r\n\t\tTextLine[i].text.clear();\r\n\t\tTextLine[i].text.shrink_to_fit();\r\n\t\tTextLine[i].flags = UiFlags::None;\r\n\t\tTextLine[i].type = STextStruct::Label;\r\n\t\tTextLine[i]._sval = 0;\r\n\t}\r\n}\r\n\r\nvoid StartStore(TalkID s)\r\n{\r\n\tif (*GetOptions().Gameplay.showItemGraphicsInStores) {\r\n\t\tCreateHalfSizeItemSprites();\r\n\t}\r\n\tSpellbookFlag = false;\r\n\tCloseInventory();\r\n\tCloseCharPanel();\r\n\tRenderGold = false;\r\n\tQuestLogIsOpen = false;\r\n\tCloseGoldDrop();\r\n\tClearSText(0, NumStoreLines);\r\n\tReleaseStoreBtn();\r\n\r\n\t// Fire StoreOpened Lua event for main store entries\r\n\tswitch (s) {\r\n\tcase TalkID::Smith:\r\n\t\tlua::StoreOpened(\"griswold\");\r\n\t\tbreak;\r\n\tcase TalkID::Witch:\r\n\t\tlua::StoreOpened(\"adria\");\r\n\t\tbreak;\r\n\tcase TalkID::Boy:\r\n\t\tlua::StoreOpened(\"wirt\");\r\n\t\tbreak;\r\n\tcase TalkID::Healer:\r\n\t\tlua::StoreOpened(\"pepin\");\r\n\t\tbreak;\r\n\tcase TalkID::Storyteller:\r\n\t\tlua::StoreOpened(\"cain\");\r\n\t\tbreak;\r\n\tcase TalkID::Tavern:\r\n\t\tlua::StoreOpened(\"ogden\");\r\n\t\tbreak;\r\n\tcase TalkID::Drunk:\r\n\t\tlua::StoreOpened(\"farnham\");\r\n\t\tbreak;\r\n\tcase TalkID::Barmaid:\r\n\t\tlua::StoreOpened(\"gillian\");\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tswitch (s) {\r\n\tcase TalkID::Smith:\r\n\t\tStartSmith();\r\n\t\tbreak;\r\n\tcase TalkID::SmithBuy: {\r\n\t\tif (!SmithItems.empty())\r\n\t\t\tStartSmithBuy();\r\n\t\telse {\r\n\t\t\tActiveStore = TalkID::SmithBuy;\r\n\t\t\tOldTextLine = 12;\r\n\t\t\tStoreESC();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\tcase TalkID::SmithSell:\r\n\t\tStartSmithSell();\r\n\t\tbreak;\r\n\tcase TalkID::SmithRepair:\r\n\t\tStartSmithRepair();\r\n\t\tbreak;\r\n\tcase TalkID::Witch:\r\n\t\tStartWitch();\r\n\t\tbreak;\r\n\tcase TalkID::WitchBuy:\r\n\t\tif (CurrentItemIndex > 0)\r\n\t\t\tStartWitchBuy();\r\n\t\tbreak;\r\n\tcase TalkID::WitchSell:\r\n\t\tStartWitchSell();\r\n\t\tbreak;\r\n\tcase TalkID::WitchRecharge:\r\n\t\tStartWitchRecharge();\r\n\t\tbreak;\r\n\tcase TalkID::NoMoney:\r\n\t\tStoreNoMoney();\r\n\t\tbreak;\r\n\tcase TalkID::NoRoom:\r\n\t\tStoreNoRoom();\r\n\t\tbreak;\r\n\tcase TalkID::Confirm:\r\n\t\tStoreConfirm(TempItem);\r\n\t\tbreak;\r\n\tcase TalkID::Boy:\r\n\t\tStartBoy();\r\n\t\tbreak;\r\n\tcase TalkID::BoyBuy:\r\n\t\tSStartBoyBuy();\r\n\t\tbreak;\r\n\tcase TalkID::Healer:\r\n\t\tStartHealer();\r\n\t\tbreak;\r\n\tcase TalkID::Storyteller:\r\n\t\tStartStoryteller();\r\n\t\tbreak;\r\n\tcase TalkID::HealerBuy:\r\n\t\tif (CurrentItemIndex > 0)\r\n\t\t\tStartHealerBuy();\r\n\t\tbreak;\r\n\tcase TalkID::StorytellerIdentify:\r\n\t\tStartStorytellerIdentify();\r\n\t\tbreak;\r\n\tcase TalkID::SmithPremiumBuy:\r\n\t\tif (!StartSmithPremiumBuy())\r\n\t\t\treturn;\r\n\t\tbreak;\r\n\tcase TalkID::Gossip:\r\n\t\tStartTalk();\r\n\t\tbreak;\r\n\tcase TalkID::StorytellerIdentifyShow:\r\n\t\tStartStorytellerIdentifyShow(TempItem);\r\n\t\tbreak;\r\n\tcase TalkID::Tavern:\r\n\t\tStartTavern();\r\n\t\tbreak;\r\n\tcase TalkID::Drunk:\r\n\t\tStartDrunk();\r\n\t\tbreak;\r\n\tcase TalkID::Barmaid:\r\n\t\tStartBarmaid();\r\n\t\tbreak;\r\n\tcase TalkID::None:\r\n\t\tbreak;\r\n\t}\r\n\r\n\tCurrentTextLine = -1;\r\n\tfor (int i = 0; i < NumStoreLines; i++) {\r\n\t\tif (TextLine[i].isSelectable()) {\r\n\t\t\tCurrentTextLine = i;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tActiveStore = s;\r\n}\r\n\r\nvoid DrawSText(const Surface &out)\r\n{\r\n\tif (!IsTextFullSize)\r\n\t\tDrawSTextBack(out);\r\n\telse\r\n\t\tDrawQTextBack(out);\r\n\r\n\tif (HasScrollbar) {\r\n\t\tswitch (ActiveStore) {\r\n\t\tcase TalkID::SmithBuy:\r\n\t\t\tScrollSmithBuy(ScrollPos);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::SmithSell:\r\n\t\tcase TalkID::SmithRepair:\r\n\t\tcase TalkID::WitchSell:\r\n\t\tcase TalkID::WitchRecharge:\r\n\t\tcase TalkID::StorytellerIdentify:\r\n\t\t\tScrollSmithSell(ScrollPos);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::WitchBuy:\r\n\t\t\tScrollWitchBuy(ScrollPos);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::HealerBuy:\r\n\t\t\tScrollHealerBuy(ScrollPos);\r\n\t\t\tbreak;\r\n\t\tcase TalkID::SmithPremiumBuy:\r\n\t\t\tScrollSmithPremiumBuy(ScrollPos);\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tCalculateLineHeights();\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tfor (int i = 0; i < NumStoreLines; i++) {\r\n\t\tif (TextLine[i].isDivider())\r\n\t\t\tDrawSLine(out, uiPosition.y + PaddingTop + TextLine[i].y + TextHeight() / 2);\r\n\t\telse if (TextLine[i].hasText())\r\n\t\t\tPrintSString(out, TextLine[i]._sx, i, TextLine[i].text, TextLine[i].flags, TextLine[i]._sval, TextLine[i].cursId, TextLine[i].cursIndent);\r\n\t}\r\n\r\n\tif (RenderGold) {\r\n\t\tPrintSString(out, 28, 1, fmt::format(fmt::runtime(_(\"Your gold: {:s}\")), FormatInteger(TotalPlayerGold())).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignRight);\r\n\t}\r\n\r\n\tif (HasScrollbar)\r\n\t\tDrawSSlider(out, 4, 20);\r\n}\r\n\r\nvoid StoreESC()\r\n{\r\n\tif (qtextflag) {\r\n\t\tqtextflag = false;\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\tstream_stop();\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (ActiveStore) {\r\n\tcase TalkID::Smith:\r\n\tcase TalkID::Witch:\r\n\tcase TalkID::Boy:\r\n\tcase TalkID::BoyBuy:\r\n\tcase TalkID::Healer:\r\n\tcase TalkID::Storyteller:\r\n\tcase TalkID::Tavern:\r\n\tcase TalkID::Drunk:\r\n\tcase TalkID::Barmaid:\r\n\t\tActiveStore = TalkID::None;\r\n\t\tbreak;\r\n\tcase TalkID::Gossip:\r\n\t\tStartStore(OldActiveStore);\r\n\t\tCurrentTextLine = OldTextLine;\r\n\t\tbreak;\r\n\tcase TalkID::SmithBuy:\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 12;\r\n\t\tbreak;\r\n\tcase TalkID::SmithPremiumBuy:\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 14;\r\n\t\tbreak;\r\n\tcase TalkID::SmithSell:\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 16;\r\n\t\tbreak;\r\n\tcase TalkID::SmithRepair:\r\n\t\tStartStore(TalkID::Smith);\r\n\t\tCurrentTextLine = 18;\r\n\t\tbreak;\r\n\tcase TalkID::WitchBuy:\r\n\t\tStartStore(TalkID::Witch);\r\n\t\tCurrentTextLine = 14;\r\n\t\tbreak;\r\n\tcase TalkID::WitchSell:\r\n\t\tStartStore(TalkID::Witch);\r\n\t\tCurrentTextLine = 16;\r\n\t\tbreak;\r\n\tcase TalkID::WitchRecharge:\r\n\t\tStartStore(TalkID::Witch);\r\n\t\tCurrentTextLine = 18;\r\n\t\tbreak;\r\n\tcase TalkID::HealerBuy:\r\n\t\tStartStore(TalkID::Healer);\r\n\t\tCurrentTextLine = 14;\r\n\t\tbreak;\r\n\tcase TalkID::StorytellerIdentify:\r\n\t\tStartStore(TalkID::Storyteller);\r\n\t\tCurrentTextLine = 14;\r\n\t\tbreak;\r\n\tcase TalkID::StorytellerIdentifyShow:\r\n\t\tStartStore(TalkID::StorytellerIdentify);\r\n\t\tbreak;\r\n\tcase TalkID::NoMoney:\r\n\tcase TalkID::NoRoom:\r\n\tcase TalkID::Confirm:\r\n\t\tStartStore(OldActiveStore);\r\n\t\tCurrentTextLine = OldTextLine;\r\n\t\tScrollPos = OldScrollPos;\r\n\t\tbreak;\r\n\tcase TalkID::None:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid StoreUp()\r\n{\r\n\tPlaySFX(SfxID::MenuMove);\r\n\tif (CurrentTextLine == -1) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (HasScrollbar) {\r\n\t\tif (CurrentTextLine == PreviousScrollPos) {\r\n\t\t\tif (ScrollPos != 0)\r\n\t\t\t\tScrollPos--;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tCurrentTextLine--;\r\n\t\twhile (!TextLine[CurrentTextLine].isSelectable()) {\r\n\t\t\tif (CurrentTextLine == 0)\r\n\t\t\t\tCurrentTextLine = NumStoreLines - 1;\r\n\t\t\telse\r\n\t\t\t\tCurrentTextLine--;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (CurrentTextLine == 0)\r\n\t\tCurrentTextLine = NumStoreLines - 1;\r\n\telse\r\n\t\tCurrentTextLine--;\r\n\r\n\twhile (!TextLine[CurrentTextLine].isSelectable()) {\r\n\t\tif (CurrentTextLine == 0)\r\n\t\t\tCurrentTextLine = NumStoreLines - 1;\r\n\t\telse\r\n\t\t\tCurrentTextLine--;\r\n\t}\r\n}\r\n\r\nvoid StoreDown()\r\n{\r\n\tPlaySFX(SfxID::MenuMove);\r\n\tif (CurrentTextLine == -1) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (HasScrollbar) {\r\n\t\tif (CurrentTextLine == NextScrollPos) {\r\n\t\t\tif (ScrollPos < NumTextLines)\r\n\t\t\t\tScrollPos++;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tCurrentTextLine++;\r\n\t\twhile (!TextLine[CurrentTextLine].isSelectable()) {\r\n\t\t\tif (CurrentTextLine == NumStoreLines - 1)\r\n\t\t\t\tCurrentTextLine = 0;\r\n\t\t\telse\r\n\t\t\t\tCurrentTextLine++;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (CurrentTextLine == NumStoreLines - 1)\r\n\t\tCurrentTextLine = 0;\r\n\telse\r\n\t\tCurrentTextLine++;\r\n\r\n\twhile (!TextLine[CurrentTextLine].isSelectable()) {\r\n\t\tif (CurrentTextLine == NumStoreLines - 1)\r\n\t\t\tCurrentTextLine = 0;\r\n\t\telse\r\n\t\t\tCurrentTextLine++;\r\n\t}\r\n}\r\n\r\nvoid StorePrior()\r\n{\r\n\tPlaySFX(SfxID::MenuMove);\r\n\tif (CurrentTextLine != -1 && HasScrollbar) {\r\n\t\tif (CurrentTextLine == PreviousScrollPos) {\r\n\t\t\tScrollPos = std::max(ScrollPos - 4, 0);\r\n\t\t} else {\r\n\t\t\tCurrentTextLine = PreviousScrollPos;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid StoreNext()\r\n{\r\n\tPlaySFX(SfxID::MenuMove);\r\n\tif (CurrentTextLine != -1 && HasScrollbar) {\r\n\t\tif (CurrentTextLine == NextScrollPos) {\r\n\t\t\tif (ScrollPos < NumTextLines)\r\n\t\t\t\tScrollPos += 4;\r\n\t\t\tif (ScrollPos > NumTextLines)\r\n\t\t\t\tScrollPos = NumTextLines;\r\n\t\t} else {\r\n\t\t\tCurrentTextLine = NextScrollPos;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid TakePlrsMoney(int cost)\r\n{\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\r\n\tmyPlayer._pGold -= std::min(cost, myPlayer._pGold);\r\n\r\n\tcost = TakeGold(myPlayer, cost, true);\r\n\tif (cost != 0) {\r\n\t\tcost = TakeGold(myPlayer, cost, false);\r\n\t}\r\n\r\n\tStash.gold -= cost;\r\n\tStash.dirty = true;\r\n}\r\n\r\nvoid StoreEnter()\r\n{\r\n\tif (qtextflag) {\r\n\t\tqtextflag = false;\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\tstream_stop();\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tPlaySFX(SfxID::MenuSelect);\r\n\tswitch (ActiveStore) {\r\n\tcase TalkID::Smith:\r\n\t\tSmithEnter();\r\n\t\tbreak;\r\n\tcase TalkID::SmithPremiumBuy:\r\n\t\tSmithPremiumBuyEnter();\r\n\t\tbreak;\r\n\tcase TalkID::SmithBuy:\r\n\t\tSmithBuyEnter();\r\n\t\tbreak;\r\n\tcase TalkID::SmithSell:\r\n\t\tSmithSellEnter();\r\n\t\tbreak;\r\n\tcase TalkID::SmithRepair:\r\n\t\tSmithRepairEnter();\r\n\t\tbreak;\r\n\tcase TalkID::Witch:\r\n\t\tWitchEnter();\r\n\t\tbreak;\r\n\tcase TalkID::WitchBuy:\r\n\t\tWitchBuyEnter();\r\n\t\tbreak;\r\n\tcase TalkID::WitchSell:\r\n\t\tWitchSellEnter();\r\n\t\tbreak;\r\n\tcase TalkID::WitchRecharge:\r\n\t\tWitchRechargeEnter();\r\n\t\tbreak;\r\n\tcase TalkID::NoMoney:\r\n\tcase TalkID::NoRoom:\r\n\t\tStartStore(OldActiveStore);\r\n\t\tCurrentTextLine = OldTextLine;\r\n\t\tScrollPos = OldScrollPos;\r\n\t\tbreak;\r\n\tcase TalkID::Confirm:\r\n\t\tConfirmEnter(TempItem);\r\n\t\tbreak;\r\n\tcase TalkID::Boy:\r\n\t\tBoyEnter();\r\n\t\tbreak;\r\n\tcase TalkID::BoyBuy:\r\n\t\tBoyBuyEnter();\r\n\t\tbreak;\r\n\tcase TalkID::Healer:\r\n\t\tHealerEnter();\r\n\t\tbreak;\r\n\tcase TalkID::Storyteller:\r\n\t\tStorytellerEnter();\r\n\t\tbreak;\r\n\tcase TalkID::HealerBuy:\r\n\t\tHealerBuyEnter();\r\n\t\tbreak;\r\n\tcase TalkID::StorytellerIdentify:\r\n\t\tStorytellerIdentifyEnter();\r\n\t\tbreak;\r\n\tcase TalkID::Gossip:\r\n\t\tTalkEnter();\r\n\t\tbreak;\r\n\tcase TalkID::StorytellerIdentifyShow:\r\n\t\tStartStore(TalkID::StorytellerIdentify);\r\n\t\tbreak;\r\n\tcase TalkID::Drunk:\r\n\t\tDrunkEnter();\r\n\t\tbreak;\r\n\tcase TalkID::Tavern:\r\n\t\tTavernEnter();\r\n\t\tbreak;\r\n\tcase TalkID::Barmaid:\r\n\t\tBarmaidEnter();\r\n\t\tbreak;\r\n\tcase TalkID::None:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid CheckStoreBtn()\r\n{\r\n\tconst Point uiPosition = GetUIRectangle().position;\r\n\tconst Rectangle windowRect { { uiPosition.x + 344, uiPosition.y + PaddingTop - 7 }, { 271, 303 } };\r\n\tconst Rectangle windowRectFull { { uiPosition.x + 24, uiPosition.y + PaddingTop - 7 }, { 591, 303 } };\r\n\r\n\tif (!IsTextFullSize) {\r\n\t\tif (!windowRect.contains(MousePosition)) {\r\n\t\t\twhile (IsPlayerInStore())\r\n\t\t\t\tStoreESC();\r\n\t\t}\r\n\t} else {\r\n\t\tif (!windowRectFull.contains(MousePosition)) {\r\n\t\t\twhile (IsPlayerInStore())\r\n\t\t\t\tStoreESC();\r\n\t\t}\r\n\t}\r\n\r\n\tif (qtextflag) {\r\n\t\tqtextflag = false;\r\n\t\tif (leveltype == DTYPE_TOWN)\r\n\t\t\tstream_stop();\r\n\t} else if (CurrentTextLine != -1) {\r\n\t\tconst int relativeY = MousePosition.y - (uiPosition.y + PaddingTop);\r\n\r\n\t\tif (HasScrollbar && MousePosition.x > 600 + uiPosition.x) {\r\n\t\t\t// Scroll bar is always measured in terms of the small line height.\r\n\t\t\tconst int y = relativeY / SmallLineHeight;\r\n\t\t\tif (y == 4) {\r\n\t\t\t\tif (CountdownScrollUp <= 0) {\r\n\t\t\t\t\tStoreUp();\r\n\t\t\t\t\tCountdownScrollUp = 10;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tCountdownScrollUp--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (y == 20) {\r\n\t\t\t\tif (CountdownScrollDown <= 0) {\r\n\t\t\t\t\tStoreDown();\r\n\t\t\t\t\tCountdownScrollDown = 10;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tCountdownScrollDown--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tint y = relativeY / LineHeight();\r\n\r\n\t\t// Large small fonts draw beyond LineHeight. Check if the click was on the overflow text.\r\n\t\tif (IsSmallFontTall() && y > 0 && y < NumStoreLines\r\n\t\t    && TextLine[y - 1].hasText() && !TextLine[y].hasText()\r\n\t\t    && relativeY < TextLine[y - 1].y + LargeTextHeight) {\r\n\t\t\t--y;\r\n\t\t}\r\n\r\n\t\tif (y >= 5) {\r\n\t\t\tif (y >= BackButtonLine() + 1)\r\n\t\t\t\ty = BackButtonLine();\r\n\t\t\tif (HasScrollbar && y <= 20 && !TextLine[y].isSelectable()) {\r\n\t\t\t\tif (TextLine[y - 2].isSelectable()) {\r\n\t\t\t\t\ty -= 2;\r\n\t\t\t\t} else if (TextLine[y - 1].isSelectable()) {\r\n\t\t\t\t\ty--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (TextLine[y].isSelectable() || (HasScrollbar && y == BackButtonLine())) {\r\n\t\t\t\tCurrentTextLine = y;\r\n\t\t\t\tStoreEnter();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid ReleaseStoreBtn()\r\n{\r\n\tCountdownScrollUp = -1;\r\n\tCountdownScrollDown = -1;\r\n}\r\n\r\nbool IsPlayerInStore()\r\n{\r\n\treturn ActiveStore != TalkID::None;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/stores.h",
    "content": "/**\r\n * @file stores.h\r\n *\r\n * Interface of functionality for stores and towner dialogs.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#include \"DiabloUI/ui_flags.hpp\"\r\n#include \"control/control.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"utils/attributes.h\"\r\n#include \"utils/static_vector.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconstexpr int NumSmithBasicItems = 19;\r\nconstexpr int NumSmithBasicItemsHf = 24;\r\n\r\nconstexpr int NumSmithItems = 6;\r\nconstexpr int NumSmithItemsHf = 15;\r\n\r\nconstexpr int NumHealerItems = 17;\r\nconstexpr int NumHealerItemsHf = 19;\r\nconstexpr int NumHealerPinnedItems = 2;\r\nconstexpr int NumHealerPinnedItemsMp = 3;\r\n\r\nconstexpr int NumWitchItems = 17;\r\nconstexpr int NumWitchItemsHf = 24;\r\nconstexpr int NumWitchPinnedItems = 3;\r\n\r\nconstexpr int NumStoreLines = 104;\r\n\r\nenum class TalkID : uint8_t {\r\n\tNone,\r\n\tSmith,\r\n\tSmithBuy,\r\n\tSmithSell,\r\n\tSmithRepair,\r\n\tWitch,\r\n\tWitchBuy,\r\n\tWitchSell,\r\n\tWitchRecharge,\r\n\tNoMoney,\r\n\tNoRoom,\r\n\tConfirm,\r\n\tBoy,\r\n\tBoyBuy,\r\n\tHealer,\r\n\tStoryteller,\r\n\tHealerBuy,\r\n\tStorytellerIdentify,\r\n\tSmithPremiumBuy,\r\n\tGossip,\r\n\tStorytellerIdentifyShow,\r\n\tTavern,\r\n\tDrunk,\r\n\tBarmaid,\r\n};\r\n\r\n/** Currently active store */\r\nextern TalkID ActiveStore;\r\n\r\n/** Current index into PlayerItemIndexes/PlayerItems */\r\nextern DVL_API_FOR_TEST int CurrentItemIndex;\r\n/** Map of inventory items being presented in the store */\r\nextern int8_t PlayerItemIndexes[48];\r\n/** Copies of the players items as presented in the store */\r\nextern DVL_API_FOR_TEST Item PlayerItems[48];\r\n\r\n/** Items sold by Griswold */\r\nextern DVL_API_FOR_TEST StaticVector<Item, NumSmithBasicItemsHf> SmithItems;\r\n/** Number of premium items for sale by Griswold */\r\nextern DVL_API_FOR_TEST int PremiumItemCount;\r\n/** Base level of current premium items sold by Griswold */\r\nextern DVL_API_FOR_TEST int PremiumItemLevel;\r\n/** Premium items sold by Griswold */\r\nextern DVL_API_FOR_TEST StaticVector<Item, NumSmithItemsHf> PremiumItems;\r\n\r\n/** Items sold by Pepin */\r\nextern DVL_API_FOR_TEST StaticVector<Item, NumHealerItemsHf> HealerItems;\r\n\r\n/** Items sold by Adria */\r\nextern DVL_API_FOR_TEST StaticVector<Item, NumWitchItemsHf> WitchItems;\r\n\r\n/** Current level of the item sold by Wirt */\r\nextern int BoyItemLevel;\r\n/** Current item sold by Wirt */\r\nextern Item BoyItem;\r\n\r\nvoid AddStoreHoldRepair(Item *itm, int8_t i);\r\n\r\n/** Clears premium items sold by Griswold and Wirt. */\r\nvoid InitStores();\r\n\r\n/** Spawns items sold by vendors, including premium items sold by Griswold and Wirt. */\r\nvoid SetupTownStores();\r\n\r\nvoid FreeStoreMem();\r\n\r\nvoid PrintSString(const Surface &out, int margin, int line, std::string_view text, UiFlags flags, int price = 0, int cursId = -1, bool cursIndent = false);\r\nvoid DrawSLine(const Surface &out, int sy);\r\nvoid DrawSTextHelp();\r\nvoid ClearSText(int s, int e);\r\nvoid StartStore(TalkID s);\r\nvoid DrawSText(const Surface &out);\r\nvoid StoreESC();\r\nvoid StoreUp();\r\nvoid StoreDown();\r\nvoid StorePrior();\r\nvoid StoreNext();\r\nvoid TakePlrsMoney(int cost);\r\nvoid StoreEnter();\r\nvoid CheckStoreBtn();\r\nvoid ReleaseStoreBtn();\r\nbool IsPlayerInStore();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/storm/storm_net.cpp",
    "content": "#include \"storm/storm_net.hpp\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <memory>\r\n\r\n#ifndef NONET\r\n#include <mutex>\r\n#include <thread>\r\n#include <utility>\r\n\r\n#include \"utils/sdl_mutex.h\"\r\n#endif\r\n\r\n#include \"dvlnet/abstract_net.h\"\r\n#include \"engine/demomode.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"menu.h\"\r\n#include \"multi.h\"\r\n#include \"options.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/stubs.h\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\nstd::unique_ptr<net::abstract_net> dvlnet_inst;\r\nbool GameIsPublic = {};\r\n\r\n#ifndef NONET\r\nSdlMutex storm_net_mutex;\r\n#endif\r\n} // namespace\r\n\r\nbool SNetReceiveMessage(uint8_t *senderplayerid, void **data, size_t *databytes)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn dvlnet_inst->SNetReceiveMessage(senderplayerid, data, databytes);\r\n}\r\n\r\nbool SNetSendMessage(uint8_t playerID, void *data, size_t databytes)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn dvlnet_inst->SNetSendMessage(playerID, data, databytes);\r\n}\r\n\r\nbool SNetReceiveTurns(int arraysize, char **arraydata, size_t *arraydatabytes, uint32_t *arrayplayerstatus)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tif (arraysize != MAX_PLRS)\r\n\t\tUNIMPLEMENTED();\r\n\treturn dvlnet_inst->SNetReceiveTurns(arraydata, arraydatabytes, arrayplayerstatus);\r\n}\r\n\r\nbool SNetSendTurn(char *data, size_t databytes)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn dvlnet_inst->SNetSendTurn(data, databytes);\r\n}\r\n\r\nvoid SNetGetProviderCaps(struct _SNETCAPS *caps)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tdvlnet_inst->SNetGetProviderCaps(caps);\r\n}\r\n\r\nbool SNetUnregisterEventHandler(event_type evtype)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tif (dvlnet_inst == nullptr)\r\n\t\treturn true;\r\n\treturn dvlnet_inst->SNetUnregisterEventHandler(evtype);\r\n}\r\n\r\nbool SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn dvlnet_inst->SNetRegisterEventHandler(evtype, func);\r\n}\r\n\r\nbool SNetDestroy()\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tdvlnet_inst = nullptr;\r\n\treturn true;\r\n}\r\n\r\nbool SNetDropPlayer(uint8_t playerid, leaveinfo_t flags)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn dvlnet_inst->SNetDropPlayer(playerid, flags);\r\n}\r\n\r\nbool SNetLeaveGame(leaveinfo_t type)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tif (dvlnet_inst == nullptr)\r\n\t\treturn true;\r\n\tif (!IsLoopback) {\r\n\t\tstd::string upperGameName = GameName;\r\n\t\tstd::transform(upperGameName.begin(), upperGameName.end(), upperGameName.begin(), ::toupper);\r\n\t\tconst std::string reasonDescription = DescribeLeaveReason(type);\r\n\t\tLogInfo(\"Leaving {} multiplayer game '{}' (reason: {})\",\r\n\t\t    ConnectionNames[provider], upperGameName, reasonDescription);\r\n\t}\r\n\treturn dvlnet_inst->SNetLeaveGame(type);\r\n}\r\n\r\n/**\r\n * @brief Called by engine for single, called by ui for multi\r\n * @param provider BNET, IPXN, MODM, SCBL or UDPN\r\n * @param gameData The game data\r\n */\r\nbool SNetInitializeProvider(uint32_t provider, struct GameData *gameData)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tdvlnet_inst = net::abstract_net::MakeNet(provider);\r\n\treturn (HeadlessMode && !demo::IsRunning()) || mainmenu_select_hero_dialog(gameData);\r\n}\r\n\r\n/**\r\n * @brief Called by engine for single, called by ui for multi\r\n */\r\nbool SNetCreateGame(const char *pszGameName, const char *pszGamePassword, char *gameTemplateData, int gameTemplateSize, int *playerID)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tif (gameTemplateSize != sizeof(GameData))\r\n\t\tABORT();\r\n\tnet::buffer_t gameInitInfo(gameTemplateData, gameTemplateData + gameTemplateSize);\r\n\tdvlnet_inst->setup_gameinfo(std::move(gameInitInfo));\r\n\r\n\tstd::string defaultName;\r\n\tif (pszGameName == nullptr) {\r\n\t\tdefaultName = dvlnet_inst->make_default_gamename();\r\n\t\tpszGameName = defaultName.c_str();\r\n\t}\r\n\r\n\tGameName = pszGameName;\r\n\tif (pszGamePassword != nullptr)\r\n\t\tDvlNet_SetPassword(pszGamePassword);\r\n\telse\r\n\t\tDvlNet_ClearPassword();\r\n\tconst int createdPlayerId = dvlnet_inst->create(pszGameName);\r\n\tif (createdPlayerId == -1)\r\n\t\treturn false;\r\n\t*playerID = createdPlayerId;\r\n\tif (!IsLoopback) {\r\n\t\tstd::string upperGameName = GameName;\r\n\t\tstd::transform(upperGameName.begin(), upperGameName.end(), upperGameName.begin(), ::toupper);\r\n\t\tconst char *privacy = GameIsPublic ? \"public\" : \"private\";\r\n\t\tif (gameTemplateData != nullptr && gameTemplateSize >= static_cast<int>(sizeof(GameData))) {\r\n\t\t\tconst GameData *gameData = reinterpret_cast<const GameData *>(gameTemplateData);\r\n\t\t\tLogInfo(\"Created {} {} multiplayer game '{}' (player id: {}, seed: {})\",\r\n\t\t\t    privacy, ConnectionNames[provider], upperGameName, createdPlayerId,\r\n\t\t\t    FormatGameSeed(gameData->gameSeed));\r\n\t\t} else {\r\n\t\t\tLogInfo(\"Created {} {} multiplayer game '{}' (player id: {}, seed unavailable)\",\r\n\t\t\t    privacy, ConnectionNames[provider], upperGameName, createdPlayerId);\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool SNetJoinGame(char *pszGameName, char *pszGamePassword, int *playerID)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\tif (pszGameName != nullptr)\r\n\t\tGameName = pszGameName;\r\n\tif (pszGamePassword != nullptr)\r\n\t\tDvlNet_SetPassword(pszGamePassword);\r\n\telse\r\n\t\tDvlNet_ClearPassword();\r\n\tconst int joinedPlayerId = dvlnet_inst->join(pszGameName);\r\n\tif (joinedPlayerId == -1)\r\n\t\treturn false;\r\n\t*playerID = joinedPlayerId;\r\n\t// Join message with seed will be logged in NetInit after game data is synchronized\r\n\treturn true;\r\n}\r\n\r\n/**\r\n * @brief Is this the mirror image of SNetGetTurnsInTransit?\r\n */\r\nbool SNetGetOwnerTurnsWaiting(uint32_t *turns)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn dvlnet_inst->SNetGetOwnerTurnsWaiting(turns);\r\n}\r\n\r\nbool SNetGetTurnsInTransit(uint32_t *turns)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn dvlnet_inst->SNetGetTurnsInTransit(turns);\r\n}\r\n\r\n/**\r\n * @brief engine calls this only once with argument 1\r\n */\r\nbool SNetSetBasePlayer(int /*unused*/)\r\n{\r\n#ifndef NONET\r\n\tstd::lock_guard<SdlMutex> lg(storm_net_mutex);\r\n#endif\r\n\treturn true;\r\n}\r\n\r\nvoid DvlNet_ProcessNetworkPackets()\r\n{\r\n\treturn dvlnet_inst->process_network_packets();\r\n}\r\n\r\nbool DvlNet_SendInfoRequest()\r\n{\r\n\treturn dvlnet_inst->send_info_request();\r\n}\r\n\r\nvoid DvlNet_ClearGamelist()\r\n{\r\n\treturn dvlnet_inst->clear_gamelist();\r\n}\r\n\r\nstd::vector<GameInfo> DvlNet_GetGamelist()\r\n{\r\n\treturn dvlnet_inst->get_gamelist();\r\n}\r\n\r\nvoid DvlNet_SetPassword(std::string pw)\r\n{\r\n\tGameIsPublic = false;\r\n\tGamePassword = pw;\r\n\tdvlnet_inst->setup_password(std::move(pw));\r\n}\r\n\r\nvoid DvlNet_ClearPassword()\r\n{\r\n\tGameIsPublic = true;\r\n\tGamePassword.clear();\r\n\tdvlnet_inst->clear_password();\r\n}\r\n\r\nbool DvlNet_IsPublicGame()\r\n{\r\n\treturn GameIsPublic;\r\n}\r\n\r\nDvlNetLatencies DvlNet_GetLatencies(uint8_t playerId)\r\n{\r\n\treturn dvlnet_inst->get_latencies(playerId);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/storm/storm_net.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <vector>\r\n\r\n#include \"multi.h\"\r\n\r\nnamespace devilution {\r\n\r\nusing net::leaveinfo_t;\r\n\r\nenum conn_type : uint8_t {\r\n\tSELCONN_ZT,\r\n\tSELCONN_TCP,\r\n\tSELCONN_LOOPBACK,\r\n};\r\n\r\nenum event_type : uint8_t {\r\n\tEVENT_TYPE_PLAYER_CREATE_GAME,\r\n\tEVENT_TYPE_PLAYER_LEAVE_GAME,\r\n\tEVENT_TYPE_PLAYER_MESSAGE,\r\n};\r\n\r\nextern const char *ConnectionNames[];\r\nextern int provider;\r\n\r\nstruct _SNETCAPS {\r\n\tuint32_t size;\r\n\tuint32_t flags;\r\n\tuint32_t maxmessagesize;\r\n\tuint32_t maxqueuesize;\r\n\tuint32_t maxplayers;\r\n\tuint32_t bytessec;\r\n\tuint32_t latencyms;\r\n\tuint32_t defaultturnssec;\r\n\tuint32_t defaultturnsintransit;\r\n};\r\n\r\nstruct _SNETEVENT {\r\n\tuint32_t eventid;  // native-endian\r\n\tuint32_t playerid; // native-endian\r\n\tvoid *data;        // little-endian\r\n\tsize_t databytes;  // native-endian\r\n};\r\n\r\nstruct DvlNetLatencies {\r\n\tuint32_t echoLatency;\r\n\tstd::optional<int> providerLatency;\r\n\tstd::optional<bool> isRelayed;\r\n};\r\n\r\n#define PS_CONNECTED 0x10000\r\n#define PS_TURN_ARRIVED 0x20000\r\n#define PS_ACTIVE 0x40000\r\n\r\nbool SNetCreateGame(const char *pszGameName, const char *pszGamePassword, char *GameTemplateData, int GameTemplateSize, int *playerID);\r\nbool SNetDestroy();\r\n\r\n/*  SNetDropPlayer @ 106\r\n *\r\n *  Drops a player from the current game.\r\n *\r\n *  playerid:     The player ID for the player to be dropped.\r\n *  flags:\r\n *\r\n *  Returns true if the function was called successfully and false otherwise.\r\n */\r\nbool SNetDropPlayer(uint8_t playerid, leaveinfo_t flags);\r\n\r\n/*  SNetGetTurnsInTransit @ 115\r\n *\r\n *  Retrieves the number of turns (buffers) that have been queued\r\n *  before sending them over the network.\r\n *\r\n *  turns: A pointer to an integer that will receive the value.\r\n *\r\n *  Returns true if the function was called successfully and false otherwise.\r\n */\r\nbool SNetGetTurnsInTransit(uint32_t *turns);\r\n\r\nbool SNetJoinGame(char *gameName, char *gamePassword, int *playerid);\r\n\r\n/*  SNetLeaveGame @ 119\r\n *\r\n *  Notifies Storm that the player has left the game. Storm will\r\n *  notify all connected peers through the network provider.\r\n *\r\n *  type: The leave type. It doesn't appear to be important, no documentation available.\r\n *\r\n *  Returns true if the function was called successfully and false otherwise.\r\n */\r\nbool SNetLeaveGame(leaveinfo_t type);\r\n\r\nbool SNetReceiveMessage(uint8_t *senderplayerid, void **data, size_t *databytes);\r\nbool SNetReceiveTurns(int arraysize, char **arraydata, size_t *arraydatabytes, uint32_t *arrayplayerstatus);\r\n\r\ntypedef void (*SEVTHANDLER)(struct _SNETEVENT *);\r\n\r\n/*  SNetSendMessage @ 127\r\n *\r\n *  Sends a message to a player given their player ID. Network message\r\n *  is sent using class 01 and is retrieved by the other client using\r\n *  SNetReceiveMessage().\r\n *\r\n *  playerID:   The player index of the player to receive the data.\r\n *              Conversely, this field can be one of the following constants:\r\n *                  SNPLAYER_ALL      | Sends the message to all players, including oneself.\r\n *                  SNPLAYER_OTHERS   | Sends the message to all players, except for oneself.\r\n *  data:       A pointer to the data.\r\n *  databytes:  The amount of bytes that the data pointer contains.\r\n *\r\n *  Returns true if the function was called successfully and false otherwise.\r\n */\r\nbool SNetSendMessage(uint8_t playerID, void *data, size_t databytes);\r\n\r\n// Macro values to target specific players\r\nconstexpr uint8_t SNPLAYER_OTHERS = 0xFF;\r\n\r\n/*  SNetSendTurn @ 128\r\n *\r\n *  Sends a turn (data packet) to all players in the game. Network data\r\n *  is sent using class 02 and is retrieved by the other client using\r\n *  SNetReceiveTurns().\r\n *\r\n *  data:       A pointer to the data.\r\n *  databytes:  The amount of bytes that the data pointer contains.\r\n *\r\n *  Returns true if the function was called successfully and false otherwise.\r\n */\r\nbool SNetSendTurn(char *data, size_t databytes);\r\n\r\nbool SNetGetOwnerTurnsWaiting(uint32_t *);\r\nbool SNetUnregisterEventHandler(event_type);\r\nbool SNetRegisterEventHandler(event_type, SEVTHANDLER);\r\nbool SNetSetBasePlayer(int);\r\nbool SNetInitializeProvider(uint32_t provider, struct GameData *gameData);\r\nvoid SNetGetProviderCaps(struct _SNETCAPS *);\r\n\r\nvoid DvlNet_ProcessNetworkPackets();\r\nbool DvlNet_SendInfoRequest();\r\nvoid DvlNet_ClearGamelist();\r\nstd::vector<GameInfo> DvlNet_GetGamelist();\r\nvoid DvlNet_SetPassword(std::string pw);\r\nvoid DvlNet_ClearPassword();\r\nbool DvlNet_IsPublicGame();\r\nDvlNetLatencies DvlNet_GetLatencies(uint8_t playerId);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/storm/storm_svid.cpp",
    "content": "#include \"storm/storm_svid.h\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_pixels.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_timer.h>\r\n\r\n#ifndef NOSOUND\r\n#include <SDL3/SDL_audio.h>\r\n#endif\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifndef NOSOUND\r\n#include \"utils/aulib.hpp\"\r\n#include \"utils/push_aulib_decoder.h\"\r\n#endif\r\n#endif\r\n\r\n#include <SmackerDecoder.h>\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"engine/palette.h\"\r\n#include \"options.h\"\r\n#include \"utils/display.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\n#ifndef NOSOUND\r\n#ifdef USE_SDL3\r\nSDL_AudioStream *SVidAudioStream;\r\nbool SVidAutoStreamEnabled;\r\n#else\r\nstd::optional<Aulib::Stream> SVidAudioStream;\r\nPushAulibDecoder *SVidAudioDecoder;\r\n#endif\r\nstd::uint8_t SVidAudioDepth;\r\nstd::unique_ptr<int16_t[]> SVidAudioBuffer;\r\n#endif\r\n\r\n// Smacker's atomic time unit is a one hundred thousand's of a second (i.e. 0.01 millisecond, or 10 microseconds).\r\n// We use SDL ticks for timing, which have millisecond resolution.\r\n// There are 100 Smacker time units in a millisecond.\r\nconstexpr uint64_t SmackerTimeUnit = 100;\r\nconstexpr uint64_t TimeMsToSmk(uint64_t ms) { return ms * SmackerTimeUnit; }\r\nconstexpr uint64_t TimeSmkToMs(uint64_t time) { return time / SmackerTimeUnit; };\r\nuint64_t GetTicksSmk()\r\n{\r\n#if SDL_VERSION_ATLEAST(2, 0, 18) && !defined(USE_SDL3)\r\n\treturn TimeMsToSmk(SDL_GetTicks64());\r\n#else\r\n\treturn TimeMsToSmk(SDL_GetTicks());\r\n#endif\r\n}\r\n\r\nuint32_t SVidWidth, SVidHeight;\r\nbool SVidLoop;\r\nSmackerHandle SVidHandle;\r\nstd::unique_ptr<uint8_t[]> SVidFrameBuffer;\r\nSDLPaletteUniquePtr SVidPalette;\r\nSDLSurfaceUniquePtr SVidSurface;\r\n\r\n// The end of the current frame (time in SMK time units from the start of the program).\r\nuint64_t SVidFrameEnd;\r\n// The length of a frame in SMK time units.\r\nuint32_t SVidFrameLength;\r\n\r\nbool IsLandscapeFit(unsigned long srcW, unsigned long srcH, unsigned long dstW, unsigned long dstH)\r\n{\r\n\treturn srcW * dstH > dstW * srcH;\r\n}\r\n\r\n#ifdef USE_SDL1\r\n// Whether we've changed the video mode temporarily for SVid.\r\n// If true, we must restore it once the video has finished playing.\r\nbool IsSVidVideoMode = false;\r\n\r\n// Set the video mode close to the SVid resolution while preserving aspect ratio.\r\nvoid TrySetVideoModeToSVidForSDL1()\r\n{\r\n\tconst SDL_Surface *display = SDL_GetVideoSurface();\r\n#if defined(SDL1_VIDEO_MODE_SVID_FLAGS)\r\n\tconst int flags = SDL1_VIDEO_MODE_SVID_FLAGS;\r\n#elif defined(SDL1_VIDEO_MODE_FLAGS)\r\n\tconst int flags = SDL1_VIDEO_MODE_FLAGS;\r\n#else\r\n\tconst int flags = display->flags;\r\n#endif\r\n#ifdef SDL1_FORCE_SVID_VIDEO_MODE\r\n\tIsSVidVideoMode = true;\r\n#else\r\n\tIsSVidVideoMode = (flags & (SDL_FULLSCREEN | SDL_NOFRAME)) != 0;\r\n#endif\r\n\tif (!IsSVidVideoMode)\r\n\t\treturn;\r\n\r\n\tint w;\r\n\tint h;\r\n\tif (IsLandscapeFit(SVidWidth, SVidHeight, display->w, display->h)) {\r\n\t\tw = SVidWidth;\r\n\t\th = SVidWidth * display->h / display->w;\r\n\t} else {\r\n\t\tw = SVidHeight * display->w / display->h;\r\n\t\th = SVidHeight;\r\n\t}\r\n\r\n#ifndef SDL1_FORCE_SVID_VIDEO_MODE\r\n\tif (!SDL_VideoModeOK(w, h, /*bpp=*/display->format->BitsPerPixel, flags)) {\r\n\t\tIsSVidVideoMode = false;\r\n\r\n\t\t// Get available fullscreen/hardware modes\r\n\t\tSDL_Rect **modes = SDL_ListModes(nullptr, flags);\r\n\r\n\t\t// Check is there are any modes available.\r\n\t\tif (modes == reinterpret_cast<SDL_Rect **>(0)\r\n\t\t    || modes == reinterpret_cast<SDL_Rect **>(-1)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Search for a usable video mode\r\n\t\tbool found = false;\r\n\t\tfor (int i = 0; modes[i]; i++) {\r\n\t\t\tif (modes[i]->w == w || modes[i]->h == h) {\r\n\t\t\t\tfound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!found)\r\n\t\t\treturn;\r\n\t\tIsSVidVideoMode = true;\r\n\t}\r\n#endif\r\n\tSetVideoMode(w, h, display->format->BitsPerPixel, flags);\r\n}\r\n#endif\r\n\r\n#ifndef NOSOUND\r\n// Returns the volume scaled to [0.0F, 1.0F] range.\r\nfloat GetVolume() { return static_cast<float>(*GetOptions().Audio.soundVolume - VOLUME_MIN) / -VOLUME_MIN; }\r\n\r\nbool ShouldPushAudioData()\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SVidAudioStream != nullptr && SVidAutoStreamEnabled;\r\n#else\r\n\treturn SVidAudioStream && SVidAudioStream->isPlaying();\r\n#endif\r\n}\r\n#endif\r\n\r\nbool SVidLoadNextFrame()\r\n{\r\n\tif (Smacker_GetCurrentFrameNum(SVidHandle) >= Smacker_GetNumFrames(SVidHandle)) {\r\n\t\tif (!SVidLoop) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tSmacker_Rewind(SVidHandle);\r\n\t}\r\n\r\n\tSVidFrameEnd += SVidFrameLength;\r\n\r\n\tSmacker_GetNextFrame(SVidHandle);\r\n\tSmacker_GetFrame(SVidHandle, SVidFrameBuffer.get());\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid UpdatePalette()\r\n{\r\n\tconstexpr size_t NumColors = 256;\r\n\tuint8_t paletteData[NumColors * 3];\r\n\tSmacker_GetPalette(SVidHandle, paletteData);\r\n\r\n\tSDL_Color *colors = SVidPalette->colors;\r\n\tfor (unsigned i = 0; i < NumColors; ++i) {\r\n\t\tcolors[i].r = paletteData[i * 3];\r\n\t\tcolors[i].g = paletteData[i * 3 + 1];\r\n\t\tcolors[i].b = paletteData[i * 3 + 2];\r\n#ifndef USE_SDL1\r\n\t\tcolors[i].a = SDL_ALPHA_OPAQUE;\r\n#endif\r\n\t}\r\n\r\n#ifdef USE_SDL1\r\n#if SDL1_VIDEO_MODE_BPP == 8\r\n\t// When the video surface is 8bit, we need to set the output palette.\r\n\tSDL_SetColors(SDL_GetVideoSurface(), colors, 0, NumColors);\r\n#endif\r\n\tif (SDL_SetPalette(SVidSurface.get(), SDL_LOGPAL, colors, 0, NumColors) <= 0) {\r\n\t\tErrSdl();\r\n\t}\r\n#else\r\n\tif (!SDLC_SetSurfacePalette(SVidSurface.get(), SVidPalette.get())) {\r\n\t\tErrSdl();\r\n\t}\r\n\r\n\tconst SDL_Surface *surface = GetOutputSurface();\r\n\tif (SDLC_SURFACE_BITSPERPIXEL(surface) == 8) {\r\n\t\tif (!SDLC_SetSurfacePalette(GetOutputSurface(), SVidPalette.get())) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\nbool BlitFrame()\r\n{\r\n#ifndef USE_SDL1\r\n\tif (renderer != nullptr) {\r\n\t\tif (\r\n#ifdef USE_SDL3\r\n\t\t    !SDL_BlitSurface(SVidSurface.get(), nullptr, GetOutputSurface(), nullptr)\r\n#else\r\n\t\t    SDL_BlitSurface(SVidSurface.get(), nullptr, GetOutputSurface(), nullptr) <= -1\r\n#endif\r\n\t\t) {\r\n\t\t\tLog(\"{}\", SDL_GetError());\r\n\t\t\treturn false;\r\n\t\t}\r\n\t} else\r\n#endif\r\n\t{\r\n\t\tSDL_Surface *outputSurface = GetOutputSurface();\r\n#ifdef USE_SDL1\r\n\t\tconst bool isIndexedOutputFormat = SDLBackport_IsPixelFormatIndexed(outputSurface->format);\r\n#else\r\n\r\n#ifdef USE_SDL3\r\n\t\tconst SDL_PixelFormat wndFormat = SDL_GetWindowPixelFormat(ghMainWnd);\r\n#else\r\n\t\tconst Uint32 wndFormat = SDL_GetWindowPixelFormat(ghMainWnd);\r\n#endif\r\n\t\tconst bool isIndexedOutputFormat = SDL_ISPIXELFORMAT_INDEXED(wndFormat);\r\n#endif\r\n\t\tSDL_Rect outputRect;\r\n\t\tif (isIndexedOutputFormat) {\r\n\t\t\t// Cannot scale if the output format is indexed (8-bit palette).\r\n\t\t\toutputRect.w = static_cast<int>(SVidWidth);\r\n\t\t\toutputRect.h = static_cast<int>(SVidHeight);\r\n\t\t} else if (IsLandscapeFit(SVidWidth, SVidHeight, outputSurface->w, outputSurface->h)) {\r\n\t\t\toutputRect.w = outputSurface->w;\r\n\t\t\toutputRect.h = SVidHeight * outputSurface->w / SVidWidth;\r\n\t\t} else {\r\n\t\t\toutputRect.w = SVidWidth * outputSurface->h / SVidHeight;\r\n\t\t\toutputRect.h = outputSurface->h;\r\n\t\t}\r\n\t\toutputRect.x = (outputSurface->w - outputRect.w) / 2;\r\n\t\toutputRect.y = (outputSurface->h - outputRect.h) / 2;\r\n\r\n\t\tif (isIndexedOutputFormat\r\n\t\t    || outputSurface->w == static_cast<int>(SVidWidth)\r\n\t\t    || outputSurface->h == static_cast<int>(SVidHeight)) {\r\n\t\t\tif (\r\n#ifdef USE_SDL3\r\n\t\t\t    SDL_BlitSurface(SVidSurface.get(), nullptr, outputSurface, &outputRect)\r\n#else\r\n\t\t\t    SDL_BlitSurface(SVidSurface.get(), nullptr, outputSurface, &outputRect) <= -1\r\n#endif\r\n\t\t\t) {\r\n\t\t\t\tErrSdl();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// The source surface is always 8-bit, and the output surface is never 8-bit in this branch.\r\n\t\t\t// We must convert to the output format before calling SDL_BlitScaled.\r\n#ifdef USE_SDL1\r\n\t\t\tSDLSurfaceUniquePtr converted = SDLWrap::ConvertSurface(SVidSurface.get(), ghMainWnd->format, 0);\r\n#else\r\n\t\t\tSDLSurfaceUniquePtr converted = SDLWrap::ConvertSurfaceFormat(SVidSurface.get(), wndFormat, 0);\r\n#endif\r\n\t\t\tif (\r\n#ifdef USE_SDL3\r\n\t\t\t    SDL_BlitSurfaceScaled(converted.get(), nullptr, outputSurface, &outputRect, SDL_SCALEMODE_LINEAR)\r\n#else\r\n\t\t\t    SDL_BlitScaled(converted.get(), nullptr, outputSurface, &outputRect) <= -1\r\n#endif\r\n\t\t\t) {\r\n\t\t\t\tLog(\"{}\", SDL_GetError());\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tRenderPresent();\r\n\treturn true;\r\n}\r\n\r\n#if defined(USE_SDL3) && !defined(NOSOUND)\r\nvoid SVidInitAudioStream(const SmackerAudioInfo &audioInfo)\r\n{\r\n\tSVidAutoStreamEnabled = diablo_is_focused();\r\n\tSDL_AudioSpec srcSpec = {};\r\n\tsrcSpec.channels = static_cast<int>(audioInfo.nChannels);\r\n\tsrcSpec.freq = static_cast<int>(audioInfo.sampleRate);\r\n\tsrcSpec.format = audioInfo.bitsPerSample == 8 ? SDL_AUDIO_U8 : SDL_AUDIO_S16LE;\r\n\tSVidAudioStream = SDL_CreateAudioStream(&srcSpec, /*dstSpec=*/&srcSpec);\r\n\tif (SVidAudioStream == nullptr) {\r\n\t\tLogError(LogCategory::Audio, \"SDL_CreateAudioStream (from SVidPlayBegin): {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\tSVidAudioStream = nullptr;\r\n\t\treturn;\r\n\t}\r\n\tif (!SDL_BindAudioStream(CurrentAudioDeviceId, SVidAudioStream)) {\r\n\t\tLogError(LogCategory::Audio, \"SDL_BindAudioStream (from SVidPlayBegin): {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\tSDL_DestroyAudioStream(SVidAudioStream);\r\n\t\tSVidAudioStream = nullptr;\r\n\t\treturn;\r\n\t}\r\n\tif (!SDL_SetAudioStreamGain(SVidAudioStream, GetVolume())) {\r\n\t\tLogWarn(LogCategory::Audio, \"SDL_SetAudioStreamGain (from SVidPlayBegin): {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t}\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\nbool SVidPlayBegin(const char *filename, int flags)\r\n{\r\n\tif ((flags & 0x10000) != 0 || (flags & 0x20000000) != 0) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tSVidLoop = false;\r\n\tif ((flags & 0x40000) != 0)\r\n\t\tSVidLoop = true;\r\n\t// 0x8 // Non-interlaced\r\n\t// 0x200, 0x800 // Upscale video\r\n\t// 0x80000 // Center horizontally\r\n\t// 0x100000 // Disable video\r\n\t// 0x800000 // Edge detection\r\n\t// 0x200800 // Clear FB\r\n\r\n\tauto *videoStream = OpenAssetAsSdlRwOps(filename);\r\n\tSVidHandle = Smacker_Open(videoStream);\r\n\tif (!SVidHandle.isValid) {\r\n\t\treturn false;\r\n\t}\r\n\r\n#ifndef NOSOUND\r\n\tconst bool enableAudio = (flags & 0x1000000) == 0;\r\n\r\n\tauto audioInfo = Smacker_GetAudioTrackDetails(SVidHandle, 0);\r\n\tLogVerbose(LogCategory::Audio, \"SVid audio depth={} channels={} rate={}\", audioInfo.bitsPerSample, audioInfo.nChannels, audioInfo.sampleRate);\r\n\r\n\tif (enableAudio && audioInfo.bitsPerSample != 0) {\r\n\t\tsound_stop(); // Stop in-progress music and sound effects\r\n\r\n\t\tSVidAudioDepth = audioInfo.bitsPerSample;\r\n\t\tSVidAudioBuffer = std::unique_ptr<int16_t[]> { new int16_t[audioInfo.idealBufferSize / 2] };\r\n\r\n#ifndef USE_SDL3\r\n\t\tauto decoder = std::make_unique<PushAulibDecoder>(audioInfo.nChannels, audioInfo.sampleRate);\r\n\t\tSVidAudioDecoder = decoder.get();\r\n\t\tSVidAudioStream.emplace(/*rwops=*/nullptr, std::move(decoder), CreateAulibResampler(audioInfo.sampleRate), /*closeRw=*/false);\r\n\t\tSVidAudioStream->setVolume(GetVolume());\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\n\t\tSVidInitAudioStream(audioInfo);\r\n#else\r\n\t\tif (!diablo_is_focused())\r\n\t\t\tSVidMute();\r\n\t\tif (!SVidAudioStream->open()) {\r\n\t\t\tLogError(LogCategory::Audio, \"Aulib::Stream::open (from SVidPlayBegin): {}\", SDL_GetError());\r\n\t\t\tSVidAudioStream = std::nullopt;\r\n\t\t\tSVidAudioDecoder = nullptr;\r\n\t\t}\r\n\t\tif (!SVidAudioStream->play()) {\r\n\t\t\tLogError(LogCategory::Audio, \"Aulib::Stream::play (from SVidPlayBegin): {}\", SDL_GetError());\r\n\t\t\tSVidAudioStream = std::nullopt;\r\n\t\t\tSVidAudioDecoder = nullptr;\r\n\t\t}\r\n#endif\r\n\t}\r\n#endif\r\n\r\n\t// SMK format internally defines the frame rate as the frame duration\r\n\t// in either milliseconds or SMK time units (0.01ms). The library converts it\r\n\t// to FPS, which is always an integer, and here we convert it back to SMK time units.\r\n\tSVidFrameLength = 100000 / static_cast<uint32_t>(Smacker_GetFrameRate(SVidHandle));\r\n\tSmacker_GetFrameSize(SVidHandle, SVidWidth, SVidHeight);\r\n\r\n#ifndef USE_SDL1\r\n\tif (renderer != nullptr) {\r\n\t\tconst int renderWidth = static_cast<int>(SVidWidth);\r\n\t\tconst int renderHeight = static_cast<int>(SVidHeight);\r\n\t\ttexture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, renderWidth, renderHeight);\r\n\t\tif (\r\n#ifdef USE_SDL3\r\n\t\t    !SDL_SetRenderLogicalPresentation(renderer, renderWidth, renderHeight,\r\n\t\t        *GetOptions().Graphics.integerScaling ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_STRETCH)\r\n#else\r\n\t\t    SDL_RenderSetLogicalSize(renderer, renderWidth, renderHeight) <= -1\r\n#endif\r\n\t\t) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\t}\r\n#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) && DEVILUTIONX_DISPLAY_PIXELFORMAT == SDL_PIXELFORMAT_INDEX8\r\n\telse {\r\n\t\tconst Size windowSize = { static_cast<int>(SVidWidth), static_cast<int>(SVidHeight) };\r\n\t\tSDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT);\r\n\t\tif (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\t}\r\n#endif\r\n#else\r\n\tTrySetVideoModeToSVidForSDL1();\r\n#endif\r\n\r\n\t// Set the background to black.\r\n\tSDL_FillSurfaceRect(GetOutputSurface(), nullptr, 0x000000);\r\n\r\n\t// The buffer for the frame. It is not the same as the SDL surface because the SDL surface also has pitch padding.\r\n\tSVidFrameBuffer = std::unique_ptr<uint8_t[]> { new uint8_t[static_cast<size_t>(SVidWidth * SVidHeight)] };\r\n\r\n\t// Decode first frame.\r\n\tSmacker_GetNextFrame(SVidHandle);\r\n\tSmacker_GetFrame(SVidHandle, SVidFrameBuffer.get());\r\n\r\n\t// Create the surface from the frame buffer data.\r\n\t// It will be rendered in `SVidPlayContinue`, called immediately after this function.\r\n\t// Subsequents frames will also be copied to this surface.\r\n\tSVidSurface = SDLWrap::CreateRGBSurfaceWithFormatFrom(\r\n\t    reinterpret_cast<void *>(SVidFrameBuffer.get()),\r\n\t    static_cast<int>(SVidWidth),\r\n\t    static_cast<int>(SVidHeight),\r\n\t    8,\r\n\t    static_cast<int>(SVidWidth),\r\n\t    SDL_PIXELFORMAT_INDEX8);\r\n\r\n\tSVidPalette = SDLWrap::AllocPalette();\r\n\tUpdatePalette();\r\n\r\n\tSVidFrameEnd = GetTicksSmk() + SVidFrameLength;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool SVidPlayContinue()\r\n{\r\n\tif (Smacker_DidPaletteChange(SVidHandle)) {\r\n\t\tUpdatePalette();\r\n\t}\r\n\r\n\tif (GetTicksSmk() >= SVidFrameEnd) {\r\n#if defined(USE_SDL3) && !defined(NOSOUND)\r\n\t\tif (ShouldPushAudioData()) SDL_ClearAudioStream(SVidAudioStream);\r\n#endif\r\n\t\treturn SVidLoadNextFrame(); // Skip video and audio if the system is to slow\r\n\t}\r\n\r\n#ifndef NOSOUND\r\n\tif (ShouldPushAudioData()) {\r\n\t\tstd::int16_t *buf = SVidAudioBuffer.get();\r\n\t\tconst auto len = Smacker_GetAudioData(SVidHandle, 0, buf);\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_PutAudioStreamData(SVidAudioStream, buf, static_cast<int>(len))) {\r\n\t\t\tLogError(LogCategory::Audio, \"SDL_PutAudioStreamData (from SVidPlayContinue): {}\", SDL_GetError());\r\n\t\t\tSDL_ClearError();\r\n\t\t\tSDL_DestroyAudioStream(SVidAudioStream);\r\n\t\t\tSVidAudioStream = nullptr;\r\n\t\t}\r\n#else\r\n\t\tif (SVidAudioDepth == 16) {\r\n\t\t\tSVidAudioDecoder->PushSamples(buf, len / 2);\r\n\t\t} else {\r\n\t\t\tSVidAudioDecoder->PushSamples(reinterpret_cast<const std::uint8_t *>(buf), len);\r\n\t\t}\r\n#endif\r\n\t}\r\n#endif\r\n\r\n\tif (GetTicksSmk() >= SVidFrameEnd) {\r\n\t\treturn SVidLoadNextFrame(); // Skip video if the system is to slow\r\n\t}\r\n\r\n\tif (!BlitFrame())\r\n\t\treturn false;\r\n\r\n\tconst uint64_t now = GetTicksSmk();\r\n\tif (now < SVidFrameEnd) {\r\n\t\tSDL_Delay(static_cast<Uint32>(TimeSmkToMs(SVidFrameEnd - now))); // wait with next frame if the system is too fast\r\n\t}\r\n\r\n\treturn SVidLoadNextFrame();\r\n}\r\n\r\nvoid SVidPlayEnd()\r\n{\r\n#ifndef NOSOUND\r\n\tif (SVidAudioStream) {\r\n#ifdef USE_SDL3\r\n\t\tSDL_DestroyAudioStream(SVidAudioStream);\r\n\t\tSVidAudioStream = nullptr;\r\n#else\r\n\t\tSVidAudioStream = std::nullopt;\r\n\t\tSVidAudioDecoder = nullptr;\r\n#endif\r\n\t\tSVidAudioBuffer = nullptr;\r\n\t}\r\n#endif\r\n\r\n\tif (SVidHandle.isValid)\r\n\t\tSmacker_Close(SVidHandle);\r\n\r\n\tSVidPalette = nullptr;\r\n\tSVidSurface = nullptr;\r\n\tSVidFrameBuffer = nullptr;\r\n\r\n#ifndef USE_SDL1\r\n\tif (renderer != nullptr) {\r\n\t\ttexture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, gnScreenWidth, gnScreenHeight);\r\n\t\tif (\r\n#ifdef USE_SDL3\r\n\t\t    !SDL_SetRenderLogicalPresentation(renderer, gnScreenWidth, gnScreenHeight,\r\n\t\t        *GetOptions().Graphics.integerScaling ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_STRETCH)\r\n#else\r\n\t\t    SDL_RenderSetLogicalSize(renderer, gnScreenWidth, gnScreenHeight) <= -1\r\n#endif\r\n\t\t) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\t}\r\n#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) && DEVILUTIONX_DISPLAY_PIXELFORMAT == SDL_PIXELFORMAT_INDEX8\r\n\telse {\r\n\t\tconst Size windowSize = { static_cast<int>(gnScreenWidth), static_cast<int>(gnScreenHeight) };\r\n\t\tSDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT);\r\n\t\tif (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\t}\r\n#endif\r\n#else\r\n\tif (IsSVidVideoMode) {\r\n\t\tSetVideoModeToPrimary(IsFullScreen(), gnScreenWidth, gnScreenHeight);\r\n\t\tIsSVidVideoMode = false;\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid SVidMute()\r\n{\r\n#ifndef NOSOUND\r\n#ifdef USE_SDL3\r\n\tSVidAutoStreamEnabled = false;\r\n#else\r\n\tif (SVidAudioStream)\r\n\t\tSVidAudioStream->mute();\r\n#endif\r\n#endif\r\n}\r\n\r\nvoid SVidUnmute()\r\n{\r\n#ifndef NOSOUND\r\n#ifdef USE_SDL3\r\n\tif (SVidAudioStream != nullptr) SVidAutoStreamEnabled = true;\r\n#else\r\n\tif (SVidAudioStream)\r\n\t\tSVidAudioStream->unmute();\r\n#endif\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/storm/storm_svid.h",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\n\r\nbool SVidPlayBegin(const char *filename, int flags);\r\nbool SVidPlayContinue();\r\nvoid SVidPlayEnd();\r\nvoid SVidMute();\r\nvoid SVidUnmute();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/sync.cpp",
    "content": "/**\r\n * @file sync.cpp\r\n *\r\n * Implementation of functionality for syncing game state with other players.\r\n */\r\n#include <cstdint>\r\n\r\n#include <limits>\r\n\r\n#include \"levels/gendung.h\"\r\n#include \"lighting.h\"\r\n#include \"monster.h\"\r\n#include \"monsters/validation.hpp\"\r\n#include \"player.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nuint16_t sgnMonsterPriority[MaxMonsters];\r\nsize_t sgnMonsters;\r\nuint16_t sgwLRU[MaxMonsters];\r\nint sgnSyncItem;\r\nint sgnSyncPInv;\r\n\r\nvoid SyncOneMonster()\r\n{\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst unsigned m = ActiveMonsters[i];\r\n\t\tconst Monster &monster = Monsters[m];\r\n\t\tsgnMonsterPriority[m] = MyPlayer->position.tile.ManhattanDistance(monster.position.tile);\r\n\t\tif (monster.activeForTicks == 0) {\r\n\t\t\tsgnMonsterPriority[m] += 0x1000;\r\n\t\t} else if (sgwLRU[m] != 0) {\r\n\t\t\tsgwLRU[m]--;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SyncMonsterPos(TSyncMonster &monsterSync, int ndx)\r\n{\r\n\tMonster &monster = Monsters[ndx];\r\n\tmonsterSync._mndx = ndx;\r\n\tmonsterSync._mx = monster.position.tile.x;\r\n\tmonsterSync._my = monster.position.tile.y;\r\n\tmonsterSync._menemy = encode_enemy(monster);\r\n\tmonsterSync._mdelta = sgnMonsterPriority[ndx] > 255 ? 255 : sgnMonsterPriority[ndx];\r\n\tmonsterSync.mWhoHit = monster.whoHit;\r\n\tmonsterSync._mhitpoints = Swap32LE(monster.hitPoints);\r\n\r\n\tsgnMonsterPriority[ndx] = 0xFFFF;\r\n\tsgwLRU[ndx] = monster.activeForTicks == 0 ? 0xFFFF : 0xFFFE;\r\n}\r\n\r\nbool SyncMonsterActive(TSyncMonster &monsterSync)\r\n{\r\n\tunsigned ndx = std::numeric_limits<unsigned>::max();\r\n\tuint32_t lru = 0xFFFFFFFF;\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tconst unsigned m = ActiveMonsters[i];\r\n\t\tif (sgnMonsterPriority[m] < lru && sgwLRU[m] < 0xFFFE) {\r\n\t\t\tlru = sgnMonsterPriority[m];\r\n\t\t\tndx = ActiveMonsters[i];\r\n\t\t}\r\n\t}\r\n\r\n\tif (ndx == std::numeric_limits<unsigned>::max()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tSyncMonsterPos(monsterSync, static_cast<int>(ndx));\r\n\treturn true;\r\n}\r\n\r\nbool SyncMonsterActive2(TSyncMonster &monsterSync)\r\n{\r\n\tunsigned ndx = std::numeric_limits<unsigned>::max();\r\n\tuint32_t lru = 0xFFFE;\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount; i++) {\r\n\t\tif (sgnMonsters >= ActiveMonsterCount) {\r\n\t\t\tsgnMonsters = 0;\r\n\t\t}\r\n\t\tconst unsigned m = ActiveMonsters[sgnMonsters];\r\n\t\tif (sgwLRU[m] < lru) {\r\n\t\t\tlru = sgwLRU[m];\r\n\t\t\tndx = ActiveMonsters[sgnMonsters];\r\n\t\t}\r\n\t\tsgnMonsters++;\r\n\t}\r\n\r\n\tif (ndx == std::numeric_limits<unsigned>::max()) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tSyncMonsterPos(monsterSync, static_cast<int>(ndx));\r\n\treturn true;\r\n}\r\n\r\nvoid SyncPlrInv(TSyncHeader *pHdr)\r\n{\r\n\tpHdr->bItemI = -1;\r\n\tif (ActiveItemCount > 0) {\r\n\t\tif (sgnSyncItem >= ActiveItemCount) {\r\n\t\t\tsgnSyncItem = 0;\r\n\t\t}\r\n\t\tpHdr->bItemI = ActiveItems[sgnSyncItem];\r\n\t\tsgnSyncItem++;\r\n\t\tauto &item = Items[pHdr->bItemI];\r\n\t\tpHdr->bItemX = item.position.x;\r\n\t\tpHdr->bItemY = item.position.y;\r\n\t\tpHdr->wItemIndx = Swap16LE(item.IDidx);\r\n\t\tif (item.IDidx == IDI_EAR) {\r\n\t\t\tpHdr->wItemCI = Swap16LE((item._iIName[0] << 8) | item._iIName[1]);\r\n\t\t\tpHdr->dwItemSeed = Swap32LE((item._iIName[2] << 24) | (item._iIName[3] << 16) | (item._iIName[4] << 8) | item._iIName[5]);\r\n\t\t\tpHdr->bItemId = item._iIName[6];\r\n\t\t\tpHdr->bItemDur = item._iIName[7];\r\n\t\t\tpHdr->bItemMDur = item._iIName[8];\r\n\t\t\tpHdr->bItemCh = item._iIName[9];\r\n\t\t\tpHdr->bItemMCh = item._iIName[10];\r\n\t\t\tpHdr->wItemVal = Swap16LE((item._iIName[11] << 8) | ((item._iCurs - ICURS_EAR_SORCERER) << 6) | item._ivalue);\r\n\t\t\tpHdr->dwItemBuff = Swap32LE((item._iIName[12] << 24) | (item._iIName[13] << 16) | (item._iIName[14] << 8) | item._iIName[15]);\r\n\t\t} else {\r\n\t\t\tpHdr->wItemCI = Swap16LE(item._iCreateInfo);\r\n\t\t\tpHdr->dwItemSeed = Swap32LE(item._iSeed);\r\n\t\t\tpHdr->bItemId = item._iIdentified ? 1 : 0;\r\n\t\t\tpHdr->bItemDur = item._iDurability;\r\n\t\t\tpHdr->bItemMDur = item._iMaxDur;\r\n\t\t\tpHdr->bItemCh = item._iCharges;\r\n\t\t\tpHdr->bItemMCh = item._iMaxCharges;\r\n\t\t\tif (item.IDidx == IDI_GOLD) {\r\n\t\t\t\tpHdr->wItemVal = Swap16LE(item._ivalue);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tpHdr->bPInvLoc = -1;\r\n\tassert(sgnSyncPInv > -1 && sgnSyncPInv < NUM_INVLOC);\r\n\tconst auto &item = MyPlayer->InvBody[sgnSyncPInv];\r\n\tif (!item.isEmpty()) {\r\n\t\tpHdr->bPInvLoc = sgnSyncPInv;\r\n\t\tpHdr->wPInvIndx = Swap16LE(item.IDidx);\r\n\t\tpHdr->wPInvCI = Swap16LE(item._iCreateInfo);\r\n\t\tpHdr->dwPInvSeed = Swap32LE(item._iSeed);\r\n\t\tpHdr->bPInvId = item._iIdentified ? 1 : 0;\r\n\t}\r\n\r\n\tsgnSyncPInv++;\r\n\tif (sgnSyncPInv >= NUM_INVLOC) {\r\n\t\tsgnSyncPInv = 0;\r\n\t}\r\n}\r\n\r\nvoid SyncMonster(bool isOwner, const TSyncMonster &monsterSync)\r\n{\r\n\tMonster &monster = Monsters[monsterSync._mndx];\r\n\tif (monster.hitPoints <= 0 || monster.mode == MonsterMode::Death) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst Point position { monsterSync._mx, monsterSync._my };\r\n\tconst uint8_t enemyId = monsterSync._menemy;\r\n\r\n\tif (monster.activeForTicks != 0) {\r\n\t\tuint32_t delta = MyPlayer->position.tile.ManhattanDistance(monster.position.tile);\r\n\t\tif (delta > 255) {\r\n\t\t\tdelta = 255;\r\n\t\t}\r\n\r\n\t\tif (delta < monsterSync._mdelta || (delta == monsterSync._mdelta && isOwner)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (monster.position.future == position) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tif (IsAnyOf(monster.mode, MonsterMode::Charge, MonsterMode::Petrified)) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (monster.position.tile.WalkingDistance(position) <= 2) {\r\n\t\tif (!monster.isWalking()) {\r\n\t\t\tconst Direction md = GetDirection(monster.position.tile, position);\r\n\t\t\tif (DirOK(monster, md)) {\r\n\t\t\t\tM_ClearSquares(monster);\r\n\t\t\t\tmonster.occupyTile(monster.position.tile, false);\r\n\t\t\t\tWalk(monster, md);\r\n\t\t\t\tmonster.activeForTicks = std::numeric_limits<uint8_t>::max();\r\n\t\t\t}\r\n\t\t}\r\n\t} else if (dMonster[position.x][position.y] == 0) {\r\n\t\tM_ClearSquares(monster);\r\n\t\tmonster.occupyTile(position, false);\r\n\t\tmonster.position.tile = position;\r\n\t\tif (monster.lightId != NO_LIGHT)\r\n\t\t\tChangeLightXY(monster.lightId, position);\r\n\t\tdecode_enemy(monster, enemyId);\r\n\t\tconst Direction md = GetDirection(position, monster.enemyPosition);\r\n\t\tM_StartStand(monster, md);\r\n\t\tmonster.activeForTicks = std::numeric_limits<uint8_t>::max();\r\n\t}\r\n\r\n\tdecode_enemy(monster, enemyId);\r\n\tmonster.whoHit = static_cast<int8_t>(monster.whoHit | monsterSync.mWhoHit);\r\n}\r\n\r\nbool IsTSyncMonsterValid(const TSyncMonster &monsterSync)\r\n{\r\n\tconst size_t monsterId = monsterSync._mndx;\r\n\r\n\tif (monsterId >= MaxMonsters)\r\n\t\treturn false;\r\n\r\n\tif (!InDungeonBounds({ monsterSync._mx, monsterSync._my }))\r\n\t\treturn false;\r\n\r\n\tif (!IsEnemyIdValid(monsterSync._menemy))\r\n\t\treturn false;\r\n\r\n\treturn true;\r\n}\r\n\r\nbool IsTSyncEnemyValid(const TSyncMonster &monsterSync)\r\n{\r\n\treturn IsEnemyValid(monsterSync._mndx, monsterSync._menemy);\r\n}\r\n\r\n} // namespace\r\n\r\nsize_t sync_all_monsters(std::byte *pbBuf, size_t dwMaxLen)\r\n{\r\n\tif (ActiveMonsterCount < 1) {\r\n\t\treturn dwMaxLen;\r\n\t}\r\n\tif (dwMaxLen < sizeof(TSyncHeader) + sizeof(TSyncMonster)) {\r\n\t\treturn dwMaxLen;\r\n\t}\r\n\tif (MyPlayer->_pLvlChanging) {\r\n\t\treturn dwMaxLen;\r\n\t}\r\n\r\n\tauto *pHdr = reinterpret_cast<TSyncHeader *>(pbBuf);\r\n\tpbBuf += sizeof(TSyncHeader);\r\n\tdwMaxLen -= sizeof(TSyncHeader);\r\n\r\n\tpHdr->bCmd = CMD_SYNCDATA;\r\n\tpHdr->bLevel = GetLevelForMultiplayer(*MyPlayer);\r\n\tpHdr->wLen = 0;\r\n\tSyncPlrInv(pHdr);\r\n\tassert(dwMaxLen <= 0xffff);\r\n\tSyncOneMonster();\r\n\r\n\tfor (size_t i = 0; i < ActiveMonsterCount && dwMaxLen >= sizeof(TSyncMonster); i++) {\r\n\t\tauto &monsterSync = *reinterpret_cast<TSyncMonster *>(pbBuf);\r\n\t\tbool sync = false;\r\n\t\tif (i < 2) {\r\n\t\t\tsync = SyncMonsterActive2(monsterSync);\r\n\t\t}\r\n\t\tif (!sync) {\r\n\t\t\tsync = SyncMonsterActive(monsterSync);\r\n\t\t}\r\n\t\tif (!sync) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tpbBuf += sizeof(TSyncMonster);\r\n\t\tpHdr->wLen += sizeof(TSyncMonster);\r\n\t\tdwMaxLen -= sizeof(TSyncMonster);\r\n\t}\r\n\tpHdr->wLen = Swap16LE(pHdr->wLen);\r\n\r\n\treturn dwMaxLen;\r\n}\r\n\r\nsize_t OnSyncData(const TSyncHeader &header, size_t maxCmdSize, const Player &player)\r\n{\r\n\tconst uint16_t wLen = Swap16LE(header.wLen);\r\n\r\n\tif (!ValidateCmdSize(wLen + sizeof(header), maxCmdSize, player.getId()))\r\n\t\treturn maxCmdSize;\r\n\r\n\tassert(gbBufferMsgs != 2);\r\n\r\n\tif (gbBufferMsgs == 1) {\r\n\t\treturn wLen + sizeof(header);\r\n\t}\r\n\tif (&player == MyPlayer) {\r\n\t\treturn wLen + sizeof(header);\r\n\t}\r\n\r\n\tassert(header.wLen % sizeof(TSyncMonster) == 0);\r\n\tconst int monsterCount = static_cast<int>(wLen / sizeof(TSyncMonster));\r\n\r\n\tconst uint8_t level = header.bLevel;\r\n\tconst bool syncLocalLevel = !MyPlayer->_pLvlChanging && GetLevelForMultiplayer(*MyPlayer) == level;\r\n\r\n\tif (IsValidLevelForMultiplayer(level)) {\r\n\t\tconst auto *monsterSyncs = reinterpret_cast<const TSyncMonster *>(&header + 1);\r\n\t\tconst bool isOwner = player.getId() > MyPlayerId;\r\n\r\n\t\tfor (int i = 0; i < monsterCount; i++) {\r\n\t\t\tif (!IsTSyncMonsterValid(monsterSyncs[i]))\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif (syncLocalLevel) {\r\n\t\t\t\tif (!IsTSyncEnemyValid(monsterSyncs[i]))\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tSyncMonster(isOwner, monsterSyncs[i]);\r\n\t\t\t}\r\n\r\n\t\t\tdelta_sync_monster(monsterSyncs[i], level);\r\n\t\t}\r\n\t}\r\n\r\n\treturn wLen + sizeof(header);\r\n}\r\n\r\nvoid sync_init()\r\n{\r\n\tsgnMonsters = static_cast<size_t>(16 * MyPlayerId);\r\n\tmemset(sgwLRU, 255, sizeof(sgwLRU));\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/sync.h",
    "content": "/**\r\n * @file sync.h\r\n *\r\n * Interface of functionality for syncing game state with other players.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include \"msg.h\"\r\n#include \"player.h\"\r\n\r\nnamespace devilution {\r\n\r\nsize_t sync_all_monsters(std::byte *pbBuf, size_t dwMaxLen);\r\nsize_t OnSyncData(const TSyncHeader &header, size_t maxCmdSize, const Player &player);\r\nvoid sync_init();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/itemdat.cpp",
    "content": "/**\r\n * @file itemdat.cpp\r\n *\r\n * Implementation of all item data.\r\n */\r\n\r\n#include \"tables/itemdat.h\"\r\n\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <fmt/format.h>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/** Contains the data related to each item ID. */\r\nstd::vector<ItemData> AllItemsList;\r\n\r\n/** Contains item mapping IDs, with item indices assigned to them. This is used for loading saved games. */\r\nankerl::unordered_dense::map<int32_t, int16_t> ItemMappingIdsToIndices;\r\n\r\n/** Contains the mapping between unique base item ID strings and indices, used for parsing additional item data. */\r\nankerl::unordered_dense::map<std::string, int8_t> AdditionalUniqueBaseItemStringsToIndices;\r\n\r\n/** Contains the data related to each unique item ID. */\r\nstd::vector<UniqueItem> UniqueItems;\r\n\r\n/** Contains unique item mapping IDs, with unique item indices assigned to them. This is used for loading saved games. */\r\nankerl::unordered_dense::map<int32_t, int32_t> UniqueItemMappingIdsToIndices;\r\n\r\n/** Contains the data related to each item prefix. */\r\nstd::vector<PLStruct> ItemPrefixes;\r\n\r\n/** Contains the data related to each item suffix. */\r\nstd::vector<PLStruct> ItemSuffixes;\r\n\r\ntl::expected<_item_indexes, std::string> ParseItemId(std::string_view value)\r\n{\r\n\tconst std::optional<_item_indexes> enumValueOpt = magic_enum::enum_cast<_item_indexes>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\nnamespace {\r\n\r\ntl::expected<item_class, std::string> ParseItemClass(std::string_view value)\r\n{\r\n\tif (value == \"None\") return ICLASS_NONE;\r\n\tif (value == \"Weapon\") return ICLASS_WEAPON;\r\n\tif (value == \"Armor\") return ICLASS_ARMOR;\r\n\tif (value == \"Misc\") return ICLASS_MISC;\r\n\tif (value == \"Gold\") return ICLASS_GOLD;\r\n\tif (value == \"Quest\") return ICLASS_QUEST;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<item_equip_type, std::string> ParseItemEquipType(std::string_view value)\r\n{\r\n\tif (value == \"None\") return ILOC_NONE;\r\n\tif (value == \"One-handed\") return ILOC_ONEHAND;\r\n\tif (value == \"Two-handed\") return ILOC_TWOHAND;\r\n\tif (value == \"Armor\") return ILOC_ARMOR;\r\n\tif (value == \"Helm\") return ILOC_HELM;\r\n\tif (value == \"Ring\") return ILOC_RING;\r\n\tif (value == \"Amulet\") return ILOC_AMULET;\r\n\tif (value == \"Unequippable\") return ILOC_UNEQUIPABLE;\r\n\tif (value == \"Belt\") return ILOC_BELT;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<item_cursor_graphic, std::string> ParseItemCursorGraphic(std::string_view value)\r\n{\r\n\tif (value == \"POTION_OF_FULL_MANA\") return ICURS_POTION_OF_FULL_MANA;\r\n\tif (value == \"SCROLL_OF\") return ICURS_SCROLL_OF;\r\n\tif (value == \"GOLD_SMALL\") return ICURS_GOLD_SMALL;\r\n\tif (value == \"GOLD_MEDIUM\") return ICURS_GOLD_MEDIUM;\r\n\tif (value == \"GOLD_LARGE\") return ICURS_GOLD_LARGE;\r\n\tif (value == \"THE_BLEEDER\") return ICURS_THE_BLEEDER;\r\n\tif (value == \"BRAMBLE\") return ICURS_BRAMBLE;\r\n\tif (value == \"RING_OF_TRUTH\") return ICURS_RING_OF_TRUTH;\r\n\tif (value == \"RING_OF_REGHA\") return ICURS_RING_OF_REGHA;\r\n\tif (value == \"RING\") return ICURS_RING;\r\n\tif (value == \"RING_OF_ENGAGEMENT\") return ICURS_RING_OF_ENGAGEMENT;\r\n\tif (value == \"CONSTRICTING_RING\") return ICURS_CONSTRICTING_RING;\r\n\tif (value == \"SPECTRAL_ELIXIR\") return ICURS_SPECTRAL_ELIXIR;\r\n\tif (value == \"ARENA_POTION\") return ICURS_ARENA_POTION;\r\n\tif (value == \"GOLDEN_ELIXIR\") return ICURS_GOLDEN_ELIXIR;\r\n\tif (value == \"EMPYREAN_BAND\") return ICURS_EMPYREAN_BAND;\r\n\tif (value == \"EAR_SORCERER\") return ICURS_EAR_SORCERER;\r\n\tif (value == \"EAR_WARRIOR\") return ICURS_EAR_WARRIOR;\r\n\tif (value == \"EAR_ROGUE\") return ICURS_EAR_ROGUE;\r\n\tif (value == \"BLOOD_STONE\") return ICURS_BLOOD_STONE;\r\n\tif (value == \"OIL\") return ICURS_OIL;\r\n\tif (value == \"ELIXIR_OF_VITALITY\") return ICURS_ELIXIR_OF_VITALITY;\r\n\tif (value == \"POTION_OF_HEALING\") return ICURS_POTION_OF_HEALING;\r\n\tif (value == \"POTION_OF_FULL_REJUVENATION\") return ICURS_POTION_OF_FULL_REJUVENATION;\r\n\tif (value == \"ELIXIR_OF_MAGIC\") return ICURS_ELIXIR_OF_MAGIC;\r\n\tif (value == \"POTION_OF_FULL_HEALING\") return ICURS_POTION_OF_FULL_HEALING;\r\n\tif (value == \"ELIXIR_OF_DEXTERITY\") return ICURS_ELIXIR_OF_DEXTERITY;\r\n\tif (value == \"POTION_OF_REJUVENATION\") return ICURS_POTION_OF_REJUVENATION;\r\n\tif (value == \"ELIXIR_OF_STRENGTH\") return ICURS_ELIXIR_OF_STRENGTH;\r\n\tif (value == \"POTION_OF_MANA\") return ICURS_POTION_OF_MANA;\r\n\tif (value == \"BRAIN\") return ICURS_BRAIN;\r\n\tif (value == \"OPTIC_AMULET\") return ICURS_OPTIC_AMULET;\r\n\tif (value == \"AMULET\") return ICURS_AMULET;\r\n\tif (value == \"WIZARDSPIKE\") return ICURS_WIZARDSPIKE;\r\n\tif (value == \"DAGGER\") return ICURS_DAGGER;\r\n\tif (value == \"BLACK_RAZOR\") return ICURS_BLACK_RAZOR;\r\n\tif (value == \"GONNAGALS_DIRK\") return ICURS_GONNAGALS_DIRK;\r\n\tif (value == \"BLADE\") return ICURS_BLADE;\r\n\tif (value == \"BASTARD_SWORD\") return ICURS_BASTARD_SWORD;\r\n\tif (value == \"THE_EXECUTIONERS_BLADE\") return ICURS_THE_EXECUTIONERS_BLADE;\r\n\tif (value == \"MACE\") return ICURS_MACE;\r\n\tif (value == \"LONG_SWORD\") return ICURS_LONG_SWORD;\r\n\tif (value == \"BROAD_SWORD\") return ICURS_BROAD_SWORD;\r\n\tif (value == \"FALCHION\") return ICURS_FALCHION;\r\n\tif (value == \"MORNING_STAR\") return ICURS_MORNING_STAR;\r\n\tif (value == \"SHORT_SWORD\") return ICURS_SHORT_SWORD;\r\n\tif (value == \"CLAYMORE\") return ICURS_CLAYMORE;\r\n\tif (value == \"CLUB\") return ICURS_CLUB;\r\n\tif (value == \"SABRE\") return ICURS_SABRE;\r\n\tif (value == \"GRYPHONS_CLAW\") return ICURS_GRYPHONS_CLAW;\r\n\tif (value == \"SPIKED_CLUB\") return ICURS_SPIKED_CLUB;\r\n\tif (value == \"SCIMITAR\") return ICURS_SCIMITAR;\r\n\tif (value == \"FULL_HELM\") return ICURS_FULL_HELM;\r\n\tif (value == \"MAGIC_ROCK\") return ICURS_MAGIC_ROCK;\r\n\tif (value == \"HELM_OF_SPIRITS\") return ICURS_HELM_OF_SPIRITS;\r\n\tif (value == \"THE_UNDEAD_CROWN\") return ICURS_THE_UNDEAD_CROWN;\r\n\tif (value == \"ROYAL_CIRCLET\") return ICURS_ROYAL_CIRCLET;\r\n\tif (value == \"FOOLS_CREST\") return ICURS_FOOLS_CREST;\r\n\tif (value == \"HARLEQUIN_CREST\") return ICURS_HARLEQUIN_CREST;\r\n\tif (value == \"HELM\") return ICURS_HELM;\r\n\tif (value == \"BUCKLER\") return ICURS_BUCKLER;\r\n\tif (value == \"VEIL_OF_STEEL\") return ICURS_VEIL_OF_STEEL;\r\n\tif (value == \"BOOK_GREY\") return ICURS_BOOK_GREY;\r\n\tif (value == \"BOOK_RED\") return ICURS_BOOK_RED;\r\n\tif (value == \"BOOK_BLUE\") return ICURS_BOOK_BLUE;\r\n\tif (value == \"BLACK_MUSHROOM\") return ICURS_BLACK_MUSHROOM;\r\n\tif (value == \"SKULL_CAP\") return ICURS_SKULL_CAP;\r\n\tif (value == \"CAP\") return ICURS_CAP;\r\n\tif (value == \"TORN_FLESH_OF_SOULS\") return ICURS_TORN_FLESH_OF_SOULS;\r\n\tif (value == \"THINKING_CAP\") return ICURS_THINKING_CAP;\r\n\tif (value == \"CROWN\") return ICURS_CROWN;\r\n\tif (value == \"MAP_OF_THE_STARS\") return ICURS_MAP_OF_THE_STARS;\r\n\tif (value == \"FUNGAL_TOME\") return ICURS_FUNGAL_TOME;\r\n\tif (value == \"GREAT_HELM\") return ICURS_GREAT_HELM;\r\n\tif (value == \"OVERLORDS_HELM\") return ICURS_OVERLORDS_HELM;\r\n\tif (value == \"BATTLE_AXE\") return ICURS_BATTLE_AXE;\r\n\tif (value == \"HUNTERS_BOW\") return ICURS_HUNTERS_BOW;\r\n\tif (value == \"FIELD_PLATE\") return ICURS_FIELD_PLATE;\r\n\tif (value == \"STONECLEAVER\") return ICURS_STONECLEAVER;\r\n\tif (value == \"SMALL_SHIELD\") return ICURS_SMALL_SHIELD;\r\n\tif (value == \"CLEAVER\") return ICURS_CLEAVER;\r\n\tif (value == \"STUDDED_LEATHER_ARMOR\") return ICURS_STUDDED_LEATHER_ARMOR;\r\n\tif (value == \"DEADLY_HUNTER\") return ICURS_DEADLY_HUNTER;\r\n\tif (value == \"SHORT_STAFF\") return ICURS_SHORT_STAFF;\r\n\tif (value == \"TWO_HANDED_SWORD\") return ICURS_TWO_HANDED_SWORD;\r\n\tif (value == \"CHAIN_MAIL\") return ICURS_CHAIN_MAIL;\r\n\tif (value == \"SMALL_AXE\") return ICURS_SMALL_AXE;\r\n\tif (value == \"KITE_SHIELD\") return ICURS_KITE_SHIELD;\r\n\tif (value == \"SCALE_MAIL\") return ICURS_SCALE_MAIL;\r\n\tif (value == \"SPLIT_SKULL_SHIELD\") return ICURS_SPLIT_SKULL_SHIELD;\r\n\tif (value == \"DRAGONS_BREACH\") return ICURS_DRAGONS_BREACH;\r\n\tif (value == \"SHORT_BOW\") return ICURS_SHORT_BOW;\r\n\tif (value == \"LONG_BATTLE_BOW\") return ICURS_LONG_BATTLE_BOW;\r\n\tif (value == \"LONG_WAR_BOW\") return ICURS_LONG_WAR_BOW;\r\n\tif (value == \"WAR_HAMMER\") return ICURS_WAR_HAMMER;\r\n\tif (value == \"MAUL\") return ICURS_MAUL;\r\n\tif (value == \"LONG_STAFF\") return ICURS_LONG_STAFF;\r\n\tif (value == \"WAR_STAFF\") return ICURS_WAR_STAFF;\r\n\tif (value == \"TAVERN_SIGN\") return ICURS_TAVERN_SIGN;\r\n\tif (value == \"HARD_LEATHER_ARMOR\") return ICURS_HARD_LEATHER_ARMOR;\r\n\tif (value == \"RAGS\") return ICURS_RAGS;\r\n\tif (value == \"QUILTED_ARMOR\") return ICURS_QUILTED_ARMOR;\r\n\tif (value == \"FLAIL\") return ICURS_FLAIL;\r\n\tif (value == \"TOWER_SHIELD\") return ICURS_TOWER_SHIELD;\r\n\tif (value == \"COMPOSITE_BOW\") return ICURS_COMPOSITE_BOW;\r\n\tif (value == \"GREAT_SWORD\") return ICURS_GREAT_SWORD;\r\n\tif (value == \"LEATHER_ARMOR\") return ICURS_LEATHER_ARMOR;\r\n\tif (value == \"SPLINT_MAIL\") return ICURS_SPLINT_MAIL;\r\n\tif (value == \"ROBE\") return ICURS_ROBE;\r\n\tif (value == \"THE_RAINBOW_CLOAK\") return ICURS_THE_RAINBOW_CLOAK;\r\n\tif (value == \"ANVIL_OF_FURY\") return ICURS_ANVIL_OF_FURY;\r\n\tif (value == \"BROAD_AXE\") return ICURS_BROAD_AXE;\r\n\tif (value == \"LARGE_AXE\") return ICURS_LARGE_AXE;\r\n\tif (value == \"GREAT_AXE\") return ICURS_GREAT_AXE;\r\n\tif (value == \"AXE\") return ICURS_AXE;\r\n\tif (value == \"BLACKOAK_SHIELD\") return ICURS_BLACKOAK_SHIELD;\r\n\tif (value == \"LARGE_SHIELD\") return ICURS_LARGE_SHIELD;\r\n\tif (value == \"GOTHIC_SHIELD\") return ICURS_GOTHIC_SHIELD;\r\n\tif (value == \"CLOAK\") return ICURS_CLOAK;\r\n\tif (value == \"CAPE\") return ICURS_CAPE;\r\n\tif (value == \"FULL_PLATE_MAIL\") return ICURS_FULL_PLATE_MAIL;\r\n\tif (value == \"GOTHIC_PLATE\") return ICURS_GOTHIC_PLATE;\r\n\tif (value == \"BREAST_PLATE\") return ICURS_BREAST_PLATE;\r\n\tif (value == \"RING_MAIL\") return ICURS_RING_MAIL;\r\n\tif (value == \"STAFF_OF_LAZARUS\") return ICURS_STAFF_OF_LAZARUS;\r\n\tif (value == \"ARKAINES_VALOR\") return ICURS_ARKAINES_VALOR;\r\n\tif (value == \"THE_NEEDLER\") return ICURS_THE_NEEDLER;\r\n\tif (value == \"NAJS_LIGHT_PLATE\") return ICURS_NAJS_LIGHT_PLATE;\r\n\tif (value == \"THE_GRIZZLY\") return ICURS_THE_GRIZZLY;\r\n\tif (value == \"THE_GRANDFATHER\") return ICURS_THE_GRANDFATHER;\r\n\tif (value == \"THE_PROTECTOR\") return ICURS_THE_PROTECTOR;\r\n\tif (value == \"MESSERSCHMIDTS_REAVER\") return ICURS_MESSERSCHMIDTS_REAVER;\r\n\tif (value == \"WINDFORCE\") return ICURS_WINDFORCE;\r\n\tif (value == \"SHORT_WAR_BOW\") return ICURS_SHORT_WAR_BOW;\r\n\tif (value == \"COMPOSITE_STAFF\") return ICURS_COMPOSITE_STAFF;\r\n\tif (value == \"SHORT_BATTLE_BOW\") return ICURS_SHORT_BATTLE_BOW;\r\n\tif (value == \"XORINES_RING\") return ICURS_XORINES_RING;\r\n\tif (value == \"AMULET_OF_WARDING\") return ICURS_AMULET_OF_WARDING;\r\n\tif (value == \"KARIKS_RING\") return ICURS_KARIKS_RING;\r\n\tif (value == \"MERCURIAL_RING\") return ICURS_MERCURIAL_RING;\r\n\tif (value == \"RING_OF_THUNDER\") return ICURS_RING_OF_THUNDER;\r\n\tif (value == \"GIANTS_KNUCKLE\") return ICURS_GIANTS_KNUCKLE;\r\n\tif (value == \"AURIC_AMULET\") return ICURS_AURIC_AMULET;\r\n\tif (value == \"RING_OF_THE_MYSTICS\") return ICURS_RING_OF_THE_MYSTICS;\r\n\tif (value == \"ACOLYTES_AMULET\") return ICURS_ACOLYTES_AMULET;\r\n\tif (value == \"RING_OF_MAGMA\") return ICURS_RING_OF_MAGMA;\r\n\tif (value == \"GLADIATORS_RING\") return ICURS_GLADIATORS_RING;\r\n\tif (value == \"RUNE_BOMB\") return ICURS_RUNE_BOMB;\r\n\tif (value == \"THEODORE\") return ICURS_THEODORE;\r\n\tif (value == \"TORN_NOTE_1\") return ICURS_TORN_NOTE_1;\r\n\tif (value == \"TORN_NOTE_2\") return ICURS_TORN_NOTE_2;\r\n\tif (value == \"TORN_NOTE_3\") return ICURS_TORN_NOTE_3;\r\n\tif (value == \"RECONSTRUCTED_NOTE\") return ICURS_RECONSTRUCTED_NOTE;\r\n\tif (value == \"RUNE_OF_FIRE\") return ICURS_RUNE_OF_FIRE;\r\n\tif (value == \"GREATER_RUNE_OF_FIRE\") return ICURS_GREATER_RUNE_OF_FIRE;\r\n\tif (value == \"RUNE_OF_LIGHTNING\") return ICURS_RUNE_OF_LIGHTNING;\r\n\tif (value == \"GREATER_RUNE_OF_LIGHTNING\") return ICURS_GREATER_RUNE_OF_LIGHTNING;\r\n\tif (value == \"RUNE_OF_STONE\") return ICURS_RUNE_OF_STONE;\r\n\tif (value == \"GREY_SUIT\") return ICURS_GREY_SUIT;\r\n\tif (value == \"BROWN_SUIT\") return ICURS_BROWN_SUIT;\r\n\tif (value == \"EATER_OF_SOULS\") return ICURS_EATER_OF_SOULS;\r\n\tif (value == \"ARMOR_OF_GLOOM\") return ICURS_ARMOR_OF_GLOOM;\r\n\tif (value == \"BONE_CHAIN_ARMOR\") return ICURS_BONE_CHAIN_ARMOR;\r\n\tif (value == \"THUNDERCLAP\") return ICURS_THUNDERCLAP;\r\n\tif (value == \"DIAMONDEDGE\") return ICURS_DIAMONDEDGE;\r\n\tif (value == \"FLAMBEAU\") return ICURS_FLAMBEAU;\r\n\tif (value == \"GNAT_STING\") return ICURS_GNAT_STING;\r\n\tif (value == \"BLITZEN\") return ICURS_BLITZEN;\r\n\tif (value == \"DEMON_PLATE_ARMOR\") return ICURS_DEMON_PLATE_ARMOR;\r\n\tif (value == \"BOVINE\") return ICURS_BOVINE;\r\n\tif (value == \"\") return ICURS_DEFAULT;\r\n\r\n\t// also support providing the item cursor icon frame number directly\r\n\treturn ParseInt<uint8_t>(value)\r\n\t    .map([](auto numericalValue) { return static_cast<item_cursor_graphic>(numericalValue); })\r\n\t    .map_error([](auto) { return std::string(\"Unknown enum value\"); });\r\n}\r\n\r\ntl::expected<ItemType, std::string> ParseItemType(std::string_view value)\r\n{\r\n\tif (value == \"Misc\") return ItemType::Misc;\r\n\tif (value == \"Sword\") return ItemType::Sword;\r\n\tif (value == \"Axe\") return ItemType::Axe;\r\n\tif (value == \"Bow\") return ItemType::Bow;\r\n\tif (value == \"Mace\") return ItemType::Mace;\r\n\tif (value == \"Shield\") return ItemType::Shield;\r\n\tif (value == \"LightArmor\") return ItemType::LightArmor;\r\n\tif (value == \"Helm\") return ItemType::Helm;\r\n\tif (value == \"MediumArmor\") return ItemType::MediumArmor;\r\n\tif (value == \"HeavyArmor\") return ItemType::HeavyArmor;\r\n\tif (value == \"Staff\") return ItemType::Staff;\r\n\tif (value == \"Gold\") return ItemType::Gold;\r\n\tif (value == \"Ring\") return ItemType::Ring;\r\n\tif (value == \"Amulet\") return ItemType::Amulet;\r\n\tif (value == \"None\") return ItemType::None;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<unique_base_item, std::string> ParseUniqueBaseItem(std::string_view value)\r\n{\r\n\tif (value == \"NONE\") return UITYPE_NONE;\r\n\tif (value == \"SHORTBOW\") return UITYPE_SHORTBOW;\r\n\tif (value == \"LONGBOW\") return UITYPE_LONGBOW;\r\n\tif (value == \"HUNTBOW\") return UITYPE_HUNTBOW;\r\n\tif (value == \"COMPBOW\") return UITYPE_COMPBOW;\r\n\tif (value == \"WARBOW\") return UITYPE_WARBOW;\r\n\tif (value == \"BATTLEBOW\") return UITYPE_BATTLEBOW;\r\n\tif (value == \"DAGGER\") return UITYPE_DAGGER;\r\n\tif (value == \"FALCHION\") return UITYPE_FALCHION;\r\n\tif (value == \"CLAYMORE\") return UITYPE_CLAYMORE;\r\n\tif (value == \"BROADSWR\") return UITYPE_BROADSWR;\r\n\tif (value == \"SABRE\") return UITYPE_SABRE;\r\n\tif (value == \"SCIMITAR\") return UITYPE_SCIMITAR;\r\n\tif (value == \"LONGSWR\") return UITYPE_LONGSWR;\r\n\tif (value == \"BASTARDSWR\") return UITYPE_BASTARDSWR;\r\n\tif (value == \"TWOHANDSWR\") return UITYPE_TWOHANDSWR;\r\n\tif (value == \"GREATSWR\") return UITYPE_GREATSWR;\r\n\tif (value == \"CLEAVER\") return UITYPE_CLEAVER;\r\n\tif (value == \"LARGEAXE\") return UITYPE_LARGEAXE;\r\n\tif (value == \"BROADAXE\") return UITYPE_BROADAXE;\r\n\tif (value == \"SMALLAXE\") return UITYPE_SMALLAXE;\r\n\tif (value == \"BATTLEAXE\") return UITYPE_BATTLEAXE;\r\n\tif (value == \"GREATAXE\") return UITYPE_GREATAXE;\r\n\tif (value == \"MACE\") return UITYPE_MACE;\r\n\tif (value == \"MORNSTAR\") return UITYPE_MORNSTAR;\r\n\tif (value == \"SPIKCLUB\") return UITYPE_SPIKCLUB;\r\n\tif (value == \"MAUL\") return UITYPE_MAUL;\r\n\tif (value == \"WARHAMMER\") return UITYPE_WARHAMMER;\r\n\tif (value == \"FLAIL\") return UITYPE_FLAIL;\r\n\tif (value == \"LONGSTAFF\") return UITYPE_LONGSTAFF;\r\n\tif (value == \"SHORTSTAFF\") return UITYPE_SHORTSTAFF;\r\n\tif (value == \"COMPSTAFF\") return UITYPE_COMPSTAFF;\r\n\tif (value == \"QUARSTAFF\") return UITYPE_QUARSTAFF;\r\n\tif (value == \"WARSTAFF\") return UITYPE_WARSTAFF;\r\n\tif (value == \"SKULLCAP\") return UITYPE_SKULLCAP;\r\n\tif (value == \"HELM\") return UITYPE_HELM;\r\n\tif (value == \"GREATHELM\") return UITYPE_GREATHELM;\r\n\tif (value == \"CROWN\") return UITYPE_CROWN;\r\n\tif (value == \"RAGS\") return UITYPE_RAGS;\r\n\tif (value == \"STUDARMOR\") return UITYPE_STUDARMOR;\r\n\tif (value == \"CLOAK\") return UITYPE_CLOAK;\r\n\tif (value == \"ROBE\") return UITYPE_ROBE;\r\n\tif (value == \"CHAINMAIL\") return UITYPE_CHAINMAIL;\r\n\tif (value == \"LEATHARMOR\") return UITYPE_LEATHARMOR;\r\n\tif (value == \"BREASTPLATE\") return UITYPE_BREASTPLATE;\r\n\tif (value == \"CAPE\") return UITYPE_CAPE;\r\n\tif (value == \"PLATEMAIL\") return UITYPE_PLATEMAIL;\r\n\tif (value == \"FULLPLATE\") return UITYPE_FULLPLATE;\r\n\tif (value == \"BUCKLER\") return UITYPE_BUCKLER;\r\n\tif (value == \"SMALLSHIELD\") return UITYPE_SMALLSHIELD;\r\n\tif (value == \"LARGESHIELD\") return UITYPE_LARGESHIELD;\r\n\tif (value == \"KITESHIELD\") return UITYPE_KITESHIELD;\r\n\tif (value == \"GOTHSHIELD\") return UITYPE_GOTHSHIELD;\r\n\tif (value == \"RING\") return UITYPE_RING;\r\n\tif (value == \"AMULET\") return UITYPE_AMULET;\r\n\tif (value == \"SKCROWN\") return UITYPE_SKCROWN;\r\n\tif (value == \"INFRARING\") return UITYPE_INFRARING;\r\n\tif (value == \"OPTAMULET\") return UITYPE_OPTAMULET;\r\n\tif (value == \"TRING\") return UITYPE_TRING;\r\n\tif (value == \"HARCREST\") return UITYPE_HARCREST;\r\n\tif (value == \"MAPOFDOOM\") return UITYPE_MAPOFDOOM;\r\n\tif (value == \"ELIXIR\") return UITYPE_ELIXIR;\r\n\tif (value == \"ARMOFVAL\") return UITYPE_ARMOFVAL;\r\n\tif (value == \"STEELVEIL\") return UITYPE_STEELVEIL;\r\n\tif (value == \"GRISWOLD\") return UITYPE_GRISWOLD;\r\n\tif (value == \"LGTFORGE\") return UITYPE_LGTFORGE;\r\n\tif (value == \"LAZSTAFF\") return UITYPE_LAZSTAFF;\r\n\tif (value == \"BOVINE\") return UITYPE_BOVINE;\r\n\tif (value == \"INVALID\") return UITYPE_INVALID;\r\n\r\n\tconst auto findIt = AdditionalUniqueBaseItemStringsToIndices.find(std::string(value));\r\n\tif (findIt != AdditionalUniqueBaseItemStringsToIndices.end()) {\r\n\t\treturn static_cast<unique_base_item>(findIt->second);\r\n\t}\r\n\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<unique_base_item, std::string> ParseOrAddUniqueBaseItem(std::string_view value)\r\n{\r\n\tconst auto parseResult = ParseUniqueBaseItem(value);\r\n\tif (parseResult.has_value()) {\r\n\t\treturn parseResult.value();\r\n\t}\r\n\r\n\tconst size_t newUniqueBaseItemIndex = static_cast<size_t>(NUM_DEFAULT_UITYPES) + AdditionalUniqueBaseItemStringsToIndices.size();\r\n\r\n\tif (newUniqueBaseItemIndex >= static_cast<size_t>(NUM_MAX_UITYPES)) {\r\n\t\treturn tl::make_unexpected(fmt::format(\"Could not define new unique base item \\\"{}\\\", since the maximum number of {} has already been reached.\", value, static_cast<size_t>(NUM_MAX_UITYPES)));\r\n\t}\r\n\r\n\tconst unique_base_item newUniqueBaseItem = static_cast<unique_base_item>(newUniqueBaseItemIndex);\r\n\tAdditionalUniqueBaseItemStringsToIndices[std::string(value)] = newUniqueBaseItem;\r\n\treturn newUniqueBaseItem;\r\n}\r\n\r\ntl::expected<ItemSpecialEffect, std::string> ParseItemSpecialEffect(std::string_view value)\r\n{\r\n\tif (value == \"RandomStealLife\") return ItemSpecialEffect::RandomStealLife;\r\n\tif (value == \"RandomArrowVelocity\") return ItemSpecialEffect::RandomArrowVelocity;\r\n\tif (value == \"FireArrows\") return ItemSpecialEffect::FireArrows;\r\n\tif (value == \"FireDamage\") return ItemSpecialEffect::FireDamage;\r\n\tif (value == \"LightningDamage\") return ItemSpecialEffect::LightningDamage;\r\n\tif (value == \"DrainLife\") return ItemSpecialEffect::DrainLife;\r\n\tif (value == \"MultipleArrows\") return ItemSpecialEffect::MultipleArrows;\r\n\tif (value == \"Knockback\") return ItemSpecialEffect::Knockback;\r\n\tif (value == \"StealMana3\") return ItemSpecialEffect::StealMana3;\r\n\tif (value == \"StealMana5\") return ItemSpecialEffect::StealMana5;\r\n\tif (value == \"StealLife3\") return ItemSpecialEffect::StealLife3;\r\n\tif (value == \"StealLife5\") return ItemSpecialEffect::StealLife5;\r\n\tif (value == \"QuickAttack\") return ItemSpecialEffect::QuickAttack;\r\n\tif (value == \"FastAttack\") return ItemSpecialEffect::FastAttack;\r\n\tif (value == \"FasterAttack\") return ItemSpecialEffect::FasterAttack;\r\n\tif (value == \"FastestAttack\") return ItemSpecialEffect::FastestAttack;\r\n\tif (value == \"FastHitRecovery\") return ItemSpecialEffect::FastHitRecovery;\r\n\tif (value == \"FasterHitRecovery\") return ItemSpecialEffect::FasterHitRecovery;\r\n\tif (value == \"FastestHitRecovery\") return ItemSpecialEffect::FastestHitRecovery;\r\n\tif (value == \"FastBlock\") return ItemSpecialEffect::FastBlock;\r\n\tif (value == \"LightningArrows\") return ItemSpecialEffect::LightningArrows;\r\n\tif (value == \"Thorns\") return ItemSpecialEffect::Thorns;\r\n\tif (value == \"NoMana\") return ItemSpecialEffect::NoMana;\r\n\tif (value == \"HalfTrapDamage\") return ItemSpecialEffect::HalfTrapDamage;\r\n\tif (value == \"TripleDemonDamage\") return ItemSpecialEffect::TripleDemonDamage;\r\n\tif (value == \"ZeroResistance\") return ItemSpecialEffect::ZeroResistance;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<item_misc_id, std::string> ParseItemMiscId(std::string_view value)\r\n{\r\n\tif (value == \"NONE\") return IMISC_NONE;\r\n\tif (value == \"USEFIRST\") return IMISC_USEFIRST;\r\n\tif (value == \"FULLHEAL\") return IMISC_FULLHEAL;\r\n\tif (value == \"HEAL\") return IMISC_HEAL;\r\n\tif (value == \"MANA\") return IMISC_MANA;\r\n\tif (value == \"FULLMANA\") return IMISC_FULLMANA;\r\n\tif (value == \"ELIXSTR\") return IMISC_ELIXSTR;\r\n\tif (value == \"ELIXMAG\") return IMISC_ELIXMAG;\r\n\tif (value == \"ELIXDEX\") return IMISC_ELIXDEX;\r\n\tif (value == \"ELIXVIT\") return IMISC_ELIXVIT;\r\n\tif (value == \"REJUV\") return IMISC_REJUV;\r\n\tif (value == \"FULLREJUV\") return IMISC_FULLREJUV;\r\n\tif (value == \"USELAST\") return IMISC_USELAST;\r\n\tif (value == \"SCROLL\") return IMISC_SCROLL;\r\n\tif (value == \"SCROLLT\") return IMISC_SCROLLT;\r\n\tif (value == \"STAFF\") return IMISC_STAFF;\r\n\tif (value == \"BOOK\") return IMISC_BOOK;\r\n\tif (value == \"RING\") return IMISC_RING;\r\n\tif (value == \"AMULET\") return IMISC_AMULET;\r\n\tif (value == \"UNIQUE\") return IMISC_UNIQUE;\r\n\tif (value == \"OILFIRST\") return IMISC_OILFIRST;\r\n\tif (value == \"OILOF\") return IMISC_OILOF;\r\n\tif (value == \"OILACC\") return IMISC_OILACC;\r\n\tif (value == \"OILMAST\") return IMISC_OILMAST;\r\n\tif (value == \"OILSHARP\") return IMISC_OILSHARP;\r\n\tif (value == \"OILDEATH\") return IMISC_OILDEATH;\r\n\tif (value == \"OILSKILL\") return IMISC_OILSKILL;\r\n\tif (value == \"OILBSMTH\") return IMISC_OILBSMTH;\r\n\tif (value == \"OILFORT\") return IMISC_OILFORT;\r\n\tif (value == \"OILPERM\") return IMISC_OILPERM;\r\n\tif (value == \"OILHARD\") return IMISC_OILHARD;\r\n\tif (value == \"OILIMP\") return IMISC_OILIMP;\r\n\tif (value == \"OILLAST\") return IMISC_OILLAST;\r\n\tif (value == \"MAPOFDOOM\") return IMISC_MAPOFDOOM;\r\n\tif (value == \"EAR\") return IMISC_EAR;\r\n\tif (value == \"SPECELIX\") return IMISC_SPECELIX;\r\n\tif (value == \"RUNEFIRST\") return IMISC_RUNEFIRST;\r\n\tif (value == \"RUNEF\") return IMISC_RUNEF;\r\n\tif (value == \"RUNEL\") return IMISC_RUNEL;\r\n\tif (value == \"GR_RUNEL\") return IMISC_GR_RUNEL;\r\n\tif (value == \"GR_RUNEF\") return IMISC_GR_RUNEF;\r\n\tif (value == \"RUNES\") return IMISC_RUNES;\r\n\tif (value == \"RUNELAST\") return IMISC_RUNELAST;\r\n\tif (value == \"AURIC\") return IMISC_AURIC;\r\n\tif (value == \"NOTE\") return IMISC_NOTE;\r\n\tif (value == \"ARENAPOT\") return IMISC_ARENAPOT;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<item_effect_type, std::string> ParseItemEffectType(std::string_view value)\r\n{\r\n\tif (value == \"TOHIT\") return IPL_TOHIT;\r\n\tif (value == \"TOHIT_CURSE\") return IPL_TOHIT_CURSE;\r\n\tif (value == \"DAMP\") return IPL_DAMP;\r\n\tif (value == \"DAMP_CURSE\") return IPL_DAMP_CURSE;\r\n\tif (value == \"TOHIT_DAMP\") return IPL_TOHIT_DAMP;\r\n\tif (value == \"TOHIT_DAMP_CURSE\") return IPL_TOHIT_DAMP_CURSE;\r\n\tif (value == \"ACP\") return IPL_ACP;\r\n\tif (value == \"ACP_CURSE\") return IPL_ACP_CURSE;\r\n\tif (value == \"FIRERES\") return IPL_FIRERES;\r\n\tif (value == \"LIGHTRES\") return IPL_LIGHTRES;\r\n\tif (value == \"MAGICRES\") return IPL_MAGICRES;\r\n\tif (value == \"ALLRES\") return IPL_ALLRES;\r\n\tif (value == \"SPLLVLADD\") return IPL_SPLLVLADD;\r\n\tif (value == \"CHARGES\") return IPL_CHARGES;\r\n\tif (value == \"FIREDAM\") return IPL_FIREDAM;\r\n\tif (value == \"LIGHTDAM\") return IPL_LIGHTDAM;\r\n\tif (value == \"STR\") return IPL_STR;\r\n\tif (value == \"STR_CURSE\") return IPL_STR_CURSE;\r\n\tif (value == \"MAG\") return IPL_MAG;\r\n\tif (value == \"MAG_CURSE\") return IPL_MAG_CURSE;\r\n\tif (value == \"DEX\") return IPL_DEX;\r\n\tif (value == \"DEX_CURSE\") return IPL_DEX_CURSE;\r\n\tif (value == \"VIT\") return IPL_VIT;\r\n\tif (value == \"VIT_CURSE\") return IPL_VIT_CURSE;\r\n\tif (value == \"ATTRIBS\") return IPL_ATTRIBS;\r\n\tif (value == \"ATTRIBS_CURSE\") return IPL_ATTRIBS_CURSE;\r\n\tif (value == \"GETHIT_CURSE\") return IPL_GETHIT_CURSE;\r\n\tif (value == \"GETHIT\") return IPL_GETHIT;\r\n\tif (value == \"LIFE\") return IPL_LIFE;\r\n\tif (value == \"LIFE_CURSE\") return IPL_LIFE_CURSE;\r\n\tif (value == \"MANA\") return IPL_MANA;\r\n\tif (value == \"MANA_CURSE\") return IPL_MANA_CURSE;\r\n\tif (value == \"DUR\") return IPL_DUR;\r\n\tif (value == \"DUR_CURSE\") return IPL_DUR_CURSE;\r\n\tif (value == \"INDESTRUCTIBLE\") return IPL_INDESTRUCTIBLE;\r\n\tif (value == \"LIGHT\") return IPL_LIGHT;\r\n\tif (value == \"LIGHT_CURSE\") return IPL_LIGHT_CURSE;\r\n\tif (value == \"MULT_ARROWS\") return IPL_MULT_ARROWS;\r\n\tif (value == \"FIRE_ARROWS\") return IPL_FIRE_ARROWS;\r\n\tif (value == \"LIGHT_ARROWS\") return IPL_LIGHT_ARROWS;\r\n\tif (value == \"THORNS\") return IPL_THORNS;\r\n\tif (value == \"NOMANA\") return IPL_NOMANA;\r\n\tif (value == \"FIREBALL\") return IPL_FIREBALL;\r\n\tif (value == \"ABSHALFTRAP\") return IPL_ABSHALFTRAP;\r\n\tif (value == \"KNOCKBACK\") return IPL_KNOCKBACK;\r\n\tif (value == \"STEALMANA\") return IPL_STEALMANA;\r\n\tif (value == \"STEALLIFE\") return IPL_STEALLIFE;\r\n\tif (value == \"TARGAC\") return IPL_TARGAC;\r\n\tif (value == \"FASTATTACK\") return IPL_FASTATTACK;\r\n\tif (value == \"FASTRECOVER\") return IPL_FASTRECOVER;\r\n\tif (value == \"FASTBLOCK\") return IPL_FASTBLOCK;\r\n\tif (value == \"DAMMOD\") return IPL_DAMMOD;\r\n\tif (value == \"RNDARROWVEL\") return IPL_RNDARROWVEL;\r\n\tif (value == \"SETDAM\") return IPL_SETDAM;\r\n\tif (value == \"SETDUR\") return IPL_SETDUR;\r\n\tif (value == \"NOMINSTR\") return IPL_NOMINSTR;\r\n\tif (value == \"SPELL\") return IPL_SPELL;\r\n\tif (value == \"ONEHAND\") return IPL_ONEHAND;\r\n\tif (value == \"3XDAMVDEM\") return IPL_3XDAMVDEM;\r\n\tif (value == \"ALLRESZERO\") return IPL_ALLRESZERO;\r\n\tif (value == \"DRAINLIFE\") return IPL_DRAINLIFE;\r\n\tif (value == \"RNDSTEALLIFE\") return IPL_RNDSTEALLIFE;\r\n\tif (value == \"SETAC\") return IPL_SETAC;\r\n\tif (value == \"ADDACLIFE\") return IPL_ADDACLIFE;\r\n\tif (value == \"ADDMANAAC\") return IPL_ADDMANAAC;\r\n\tif (value == \"AC_CURSE\") return IPL_AC_CURSE;\r\n\tif (value == \"LASTDIABLO\") return IPL_LASTDIABLO;\r\n\tif (value == \"FIRERES_CURSE\") return IPL_FIRERES_CURSE;\r\n\tif (value == \"LIGHTRES_CURSE\") return IPL_LIGHTRES_CURSE;\r\n\tif (value == \"MAGICRES_CURSE\") return IPL_MAGICRES_CURSE;\r\n\tif (value == \"DEVASTATION\") return IPL_DEVASTATION;\r\n\tif (value == \"DECAY\") return IPL_DECAY;\r\n\tif (value == \"PERIL\") return IPL_PERIL;\r\n\tif (value == \"JESTERS\") return IPL_JESTERS;\r\n\tif (value == \"CRYSTALLINE\") return IPL_CRYSTALLINE;\r\n\tif (value == \"DOPPELGANGER\") return IPL_DOPPELGANGER;\r\n\tif (value == \"ACDEMON\") return IPL_ACDEMON;\r\n\tif (value == \"ACUNDEAD\") return IPL_ACUNDEAD;\r\n\tif (value == \"MANATOLIFE\") return IPL_MANATOLIFE;\r\n\tif (value == \"LIFETOMANA\") return IPL_LIFETOMANA;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<AffixItemType, std::string> ParseAffixItemType(std::string_view value)\r\n{\r\n\tif (value == \"Misc\") return AffixItemType::Misc;\r\n\tif (value == \"Bow\") return AffixItemType::Bow;\r\n\tif (value == \"Staff\") return AffixItemType::Staff;\r\n\tif (value == \"Weapon\") return AffixItemType::Weapon;\r\n\tif (value == \"Shield\") return AffixItemType::Shield;\r\n\tif (value == \"Armor\") return AffixItemType::Armor;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<goodorevil, std::string> ParseAffixAlignment(std::string_view value)\r\n{\r\n\tif (value == \"Any\") return GOE_ANY;\r\n\tif (value == \"Evil\") return GOE_EVIL;\r\n\tif (value == \"Good\") return GOE_GOOD;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId)\r\n{\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tint32_t currentMappingId = baseMappingId;\r\n\tAllItemsList.reserve(AllItemsList.size() + dataFile.numRecords());\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tItemData &item = AllItemsList.emplace_back();\r\n\t\treader.advance(); // Skip the first column (item ID).\r\n\t\treader.readInt(\"dropRate\", item.dropRate);\r\n\t\treader.read(\"class\", item.iClass, ParseItemClass);\r\n\t\treader.read(\"equipType\", item.iLoc, ParseItemEquipType);\r\n\t\treader.read(\"cursorGraphic\", item.iCurs, ParseItemCursorGraphic);\r\n\t\treader.read(\"itemType\", item.itype, ParseItemType);\r\n\t\treader.read(\"uniqueBaseItem\", item.iItemId, ParseOrAddUniqueBaseItem);\r\n\t\treader.readString(\"name\", item.iName);\r\n\t\treader.readString(\"shortName\", item.iSName);\r\n\t\treader.readInt(\"minMonsterLevel\", item.iMinMLvl);\r\n\t\treader.readInt(\"durability\", item.iDurability);\r\n\t\treader.readInt(\"minDamage\", item.iMinDam);\r\n\t\treader.readInt(\"maxDamage\", item.iMaxDam);\r\n\t\treader.readInt(\"minArmor\", item.iMinAC);\r\n\t\treader.readInt(\"maxArmor\", item.iMaxAC);\r\n\t\treader.readInt(\"minStrength\", item.iMinStr);\r\n\t\treader.readInt(\"minMagic\", item.iMinMag);\r\n\t\treader.readInt(\"minDexterity\", item.iMinDex);\r\n\t\treader.readEnumList(\"specialEffects\", item.iFlags, ParseItemSpecialEffect);\r\n\t\treader.read(\"miscId\", item.iMiscId, ParseItemMiscId);\r\n\t\treader.read(\"spell\", item.iSpell, ParseSpellId);\r\n\t\treader.readBool(\"usable\", item.iUsable);\r\n\t\treader.readInt(\"value\", item.iValue);\r\n\r\n\t\titem.iMappingId = currentMappingId;\r\n\t\tconst auto [it, inserted] = ItemMappingIdsToIndices.emplace(item.iMappingId, static_cast<int16_t>(AllItemsList.size()) - 1);\r\n\t\tif (!inserted) {\r\n\t\t\tDisplayFatalErrorAndExit(\"Adding Item Failed\", fmt::format(\"An item already exists for mapping ID {}.\", item.iMappingId));\r\n\t\t}\r\n\r\n\t\t++currentMappingId;\r\n\t}\r\n\tAllItemsList.shrink_to_fit();\r\n}\r\n\r\nnamespace {\r\n\r\nvoid LoadItemDat()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\items\\\\itemdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\r\n\tAllItemsList.clear();\r\n\tAdditionalUniqueBaseItemStringsToIndices.clear();\r\n\tItemMappingIdsToIndices.clear();\r\n\tLoadItemDatFromFile(dataFile, filename, 0);\r\n\r\n\tlua::ItemDataLoaded();\r\n}\r\n\r\nvoid ReadItemPower(RecordReader &reader, std::string_view fieldName, ItemPower &power)\r\n{\r\n\treader.read(fieldName, power.type, ParseItemEffectType);\r\n\treader.readOptionalInt(StrCat(fieldName, \".value1\"), power.param1);\r\n\treader.readOptionalInt(StrCat(fieldName, \".value2\"), power.param2);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadUniqueItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId)\r\n{\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tint32_t currentMappingId = baseMappingId;\r\n\tUniqueItems.reserve(UniqueItems.size() + dataFile.numRecords());\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tUniqueItem &item = UniqueItems.emplace_back();\r\n\t\treader.readString(\"name\", item.UIName);\r\n\t\treader.read(\"cursorGraphic\", item.UICurs, ParseItemCursorGraphic);\r\n\t\treader.read(\"uniqueBaseItem\", item.UIItemId, ParseUniqueBaseItem);\r\n\t\treader.readInt(\"minLevel\", item.UIMinLvl);\r\n\t\treader.readInt(\"value\", item.UIValue);\r\n\r\n\t\t// powers (up to 6)\r\n\t\titem.UINumPL = 0;\r\n\t\tfor (size_t i = 0; i < 6; ++i) {\r\n\t\t\tif (reader.value().empty())\r\n\t\t\t\tbreak;\r\n\t\t\tReadItemPower(reader, StrCat(\"power\", i), item.powers[item.UINumPL++]);\r\n\t\t}\r\n\r\n\t\titem.mappingId = currentMappingId;\r\n\t\tconst auto [it, inserted] = UniqueItemMappingIdsToIndices.emplace(item.mappingId, static_cast<int32_t>(UniqueItems.size()) - 1);\r\n\t\tif (!inserted) {\r\n\t\t\tDisplayFatalErrorAndExit(\"Adding Unique Item Failed\", fmt::format(\"A unique item already exists for mapping ID {}.\", item.mappingId));\r\n\t\t}\r\n\r\n\t\t++currentMappingId;\r\n\t}\r\n\tUniqueItems.shrink_to_fit();\r\n}\r\n\r\nnamespace {\r\n\r\nvoid LoadUniqueItemDat()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\items\\\\unique_itemdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\r\n\tUniqueItems.clear();\r\n\tUniqueItemMappingIdsToIndices.clear();\r\n\tLoadUniqueItemDatFromFile(dataFile, filename, 0);\r\n\r\n\tlua::UniqueItemDataLoaded();\r\n}\r\n\r\nvoid LoadItemAffixesDat(std::string_view filename, std::vector<PLStruct> &out)\r\n{\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tout.clear();\r\n\tout.reserve(dataFile.numRecords());\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tPLStruct &item = out.emplace_back();\r\n\t\treader.readString(\"name\", item.PLName);\r\n\t\tReadItemPower(reader, \"power\", item.power);\r\n\t\treader.readInt(\"minLevel\", item.PLMinLvl);\r\n\t\treader.readEnumList(\"itemTypes\", item.PLIType, ParseAffixItemType);\r\n\t\treader.read(\"alignment\", item.PLGOE, ParseAffixAlignment);\r\n\t\treader.readInt(\"chance\", item.PLChance);\r\n\t\treader.readBool(\"useful\", item.PLOk);\r\n\t\treader.readInt(\"minVal\", item.minVal);\r\n\t\treader.readInt(\"maxVal\", item.maxVal);\r\n\t\treader.readInt(\"multVal\", item.multVal);\r\n\t}\r\n\tout.shrink_to_fit();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadItemData()\r\n{\r\n\tLoadItemDat();\r\n\tLoadUniqueItemDat();\r\n\tLoadItemAffixesDat(\"txtdata\\\\items\\\\item_prefixes.tsv\", ItemPrefixes);\r\n\tLoadItemAffixesDat(\"txtdata\\\\items\\\\item_suffixes.tsv\", ItemSuffixes);\r\n}\r\n\r\nstd::string_view ItemTypeToString(ItemType itemType)\r\n{\r\n\tswitch (itemType) {\r\n\tcase ItemType::Misc: return \"Misc\";\r\n\tcase ItemType::Sword: return \"Sword\";\r\n\tcase ItemType::Axe: return \"Axe\";\r\n\tcase ItemType::Bow: return \"Bow\";\r\n\tcase ItemType::Mace: return \"Mace\";\r\n\tcase ItemType::Shield: return \"Shield\";\r\n\tcase ItemType::LightArmor: return \"LightArmor\";\r\n\tcase ItemType::Helm: return \"Helm\";\r\n\tcase ItemType::MediumArmor: return \"MediumArmor\";\r\n\tcase ItemType::HeavyArmor: return \"HeavyArmor\";\r\n\tcase ItemType::Staff: return \"Staff\";\r\n\tcase ItemType::Gold: return \"Gold\";\r\n\tcase ItemType::Ring: return \"Ring\";\r\n\tcase ItemType::Amulet: return \"Amulet\";\r\n\tcase ItemType::None: return \"None\";\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/itemdat.h",
    "content": "/**\r\n * @file itemdat.h\r\n *\r\n * Interface of all item data.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"tables/objdat.h\"\r\n#include \"tables/spelldat.h\"\r\n\r\nnamespace devilution {\r\n\r\nclass DataFile;\r\n\r\n/** @todo add missing values and apply */\r\nenum _item_indexes : int16_t { // TODO defines all indexes in AllItemsList\r\n\tIDI_GOLD,\r\n\tIDI_WARRIOR,\r\n\tIDI_WARRSHLD,\r\n\tIDI_WARRCLUB,\r\n\tIDI_ROGUE,\r\n\tIDI_SORCERER,\r\n\tIDI_CLEAVER,\r\n\tIDI_FIRSTQUEST = IDI_CLEAVER,\r\n\tIDI_SKCROWN,\r\n\tIDI_INFRARING,\r\n\tIDI_ROCK,\r\n\tIDI_OPTAMULET,\r\n\tIDI_TRING,\r\n\tIDI_BANNER,\r\n\tIDI_HARCREST,\r\n\tIDI_STEELVEIL,\r\n\tIDI_GLDNELIX,\r\n\tIDI_ANVIL,\r\n\tIDI_MUSHROOM,\r\n\tIDI_BRAIN,\r\n\tIDI_FUNGALTM,\r\n\tIDI_SPECELIX,\r\n\tIDI_BLDSTONE,\r\n\tIDI_MAPOFDOOM,\r\n\tIDI_LASTQUEST = IDI_MAPOFDOOM,\r\n\tIDI_EAR,\r\n\tIDI_HEAL,\r\n\tIDI_MANA,\r\n\tIDI_IDENTIFY,\r\n\tIDI_PORTAL,\r\n\tIDI_ARMOFVAL,\r\n\tIDI_FULLHEAL,\r\n\tIDI_FULLMANA,\r\n\tIDI_GRISWOLD,\r\n\tIDI_LGTFORGE,\r\n\tIDI_LAZSTAFF,\r\n\tIDI_RESURRECT,\r\n\tIDI_OIL,\r\n\tIDI_SHORTSTAFF,\r\n\tIDI_BARDSWORD,\r\n\tIDI_BARDDAGGER,\r\n\tIDI_RUNEBOMB,\r\n\tIDI_THEODORE,\r\n\tIDI_AURIC,\r\n\tIDI_NOTE1,\r\n\tIDI_NOTE2,\r\n\tIDI_NOTE3,\r\n\tIDI_FULLNOTE,\r\n\tIDI_BROWNSUIT,\r\n\tIDI_GREYSUIT,\r\n\tIDI_BOOK1 = 114,\r\n\tIDI_BOOK2,\r\n\tIDI_BOOK3,\r\n\tIDI_BOOK4,\r\n\tIDI_BARBARIAN = 139,\r\n\tIDI_SHORT_BATTLE_BOW = 148,\r\n\tIDI_RUNEOFSTONE = 165,\r\n\tIDI_SORCERER_DIABLO,\r\n\tIDI_ARENAPOT,\r\n\r\n\tIDI_NUM_DEFAULT_ITEMS,\r\n\tIDI_NONE = -1,\r\n};\r\n\r\nenum item_class : uint8_t {\r\n\tICLASS_NONE,\r\n\tICLASS_WEAPON,\r\n\tICLASS_ARMOR,\r\n\tICLASS_MISC,\r\n\tICLASS_GOLD,\r\n\tICLASS_QUEST,\r\n};\r\n\r\nenum item_equip_type : int8_t {\r\n\tILOC_NONE,\r\n\tILOC_ONEHAND,\r\n\tILOC_TWOHAND,\r\n\tILOC_ARMOR,\r\n\tILOC_HELM,\r\n\tILOC_RING,\r\n\tILOC_AMULET,\r\n\tILOC_UNEQUIPABLE,\r\n\tILOC_BELT,\r\n\tILOC_INVALID = -1,\r\n};\r\n\r\n/// Item graphic IDs; frame_num-11 of objcurs.cel.\r\nenum item_cursor_graphic : uint8_t {\r\n\t// clang-format off\r\n\tICURS_POTION_OF_FULL_MANA         = 0,\r\n\tICURS_SCROLL_OF                   = 1,\r\n\tICURS_GOLD_SMALL                  = 4,\r\n\tICURS_GOLD_MEDIUM                 = 5,\r\n\tICURS_GOLD_LARGE                  = 6,\r\n\tICURS_THE_BLEEDER                 = 8,\r\n\tICURS_BRAMBLE                     = 9,\r\n\tICURS_RING_OF_TRUTH               = 10,\r\n\tICURS_RING_OF_REGHA               = 11,\r\n\tICURS_RING                        = 12,\r\n\tICURS_RING_OF_ENGAGEMENT          = 13,\r\n\tICURS_CONSTRICTING_RING           = 14,\r\n\tICURS_SPECTRAL_ELIXIR             = 15,\r\n\tICURS_ARENA_POTION                = 16,\r\n\tICURS_GOLDEN_ELIXIR               = 17,\r\n\tICURS_EMPYREAN_BAND               = 18,\r\n\tICURS_EAR_SORCERER                = 19,\r\n\tICURS_EAR_WARRIOR                 = 20,\r\n\tICURS_EAR_ROGUE                   = 21,\r\n\tICURS_BLOOD_STONE                 = 25,\r\n\tICURS_OIL                         = 30,\r\n\tICURS_ELIXIR_OF_VITALITY          = 31,\r\n\tICURS_POTION_OF_HEALING           = 32,\r\n\tICURS_POTION_OF_FULL_REJUVENATION = 33,\r\n\tICURS_ELIXIR_OF_MAGIC             = 34,\r\n\tICURS_POTION_OF_FULL_HEALING      = 35,\r\n\tICURS_ELIXIR_OF_DEXTERITY         = 36,\r\n\tICURS_POTION_OF_REJUVENATION      = 37,\r\n\tICURS_ELIXIR_OF_STRENGTH          = 38,\r\n\tICURS_POTION_OF_MANA              = 39,\r\n\tICURS_BRAIN                       = 40,\r\n\tICURS_OPTIC_AMULET                = 44,\r\n\tICURS_AMULET                      = 45,\r\n\tICURS_WIZARDSPIKE                 = 50,\r\n\tICURS_DAGGER                      = 51,\r\n\tICURS_BLACK_RAZOR                 = 53,\r\n\tICURS_GONNAGALS_DIRK              = 54,\r\n\tICURS_BLADE                       = 56,\r\n\tICURS_BASTARD_SWORD               = 57,\r\n\tICURS_THE_EXECUTIONERS_BLADE      = 58,\r\n\tICURS_MACE                        = 59,\r\n\tICURS_LONG_SWORD                  = 60,\r\n\tICURS_BROAD_SWORD                 = 61,\r\n\tICURS_FALCHION                    = 62,\r\n\tICURS_MORNING_STAR                = 63,\r\n\tICURS_SHORT_SWORD                 = 64,\r\n\tICURS_CLAYMORE                    = 65,\r\n\tICURS_CLUB                        = 66,\r\n\tICURS_SABRE                       = 67,\r\n\tICURS_GRYPHONS_CLAW               = 68,\r\n\tICURS_SPIKED_CLUB                 = 70,\r\n\tICURS_SCIMITAR                    = 72,\r\n\tICURS_FULL_HELM                   = 75,\r\n\tICURS_MAGIC_ROCK                  = 76,\r\n\tICURS_HELM_OF_SPIRITS             = 77,\r\n\tICURS_THE_UNDEAD_CROWN            = 78,\r\n\tICURS_ROYAL_CIRCLET               = 79,\r\n\tICURS_FOOLS_CREST                 = 80,\r\n\tICURS_HARLEQUIN_CREST             = 81,\r\n\tICURS_HELM                        = 82,\r\n\tICURS_BUCKLER                     = 83,\r\n\tICURS_VEIL_OF_STEEL               = 85,\r\n\tICURS_BOOK_GREY                   = 86,\r\n\tICURS_BOOK_RED                    = 87,\r\n\tICURS_BOOK_BLUE                   = 88,\r\n\tICURS_BLACK_MUSHROOM              = 89,\r\n\tICURS_SKULL_CAP                   = 90,\r\n\tICURS_CAP                         = 91,\r\n\tICURS_TORN_FLESH_OF_SOULS         = 92,\r\n\tICURS_THINKING_CAP                = 93,\r\n\tICURS_CROWN                       = 95,\r\n\tICURS_MAP_OF_THE_STARS            = 96,\r\n\tICURS_FUNGAL_TOME                 = 97,\r\n\tICURS_GREAT_HELM                  = 98,\r\n\tICURS_OVERLORDS_HELM              = 99,\r\n\tICURS_BATTLE_AXE                  = 101,\r\n\tICURS_HUNTERS_BOW                 = 102,\r\n\tICURS_FIELD_PLATE                 = 103,\r\n\tICURS_STONECLEAVER                = 104,\r\n\tICURS_SMALL_SHIELD                = 105,\r\n\tICURS_CLEAVER                     = 106,\r\n\tICURS_STUDDED_LEATHER_ARMOR       = 107,\r\n\tICURS_DEADLY_HUNTER               = 108,\r\n\tICURS_SHORT_STAFF                 = 109,\r\n\tICURS_TWO_HANDED_SWORD            = 110,\r\n\tICURS_CHAIN_MAIL                  = 111,\r\n\tICURS_SMALL_AXE                   = 112,\r\n\tICURS_KITE_SHIELD                 = 113,\r\n\tICURS_SCALE_MAIL                  = 114,\r\n\tICURS_SPLIT_SKULL_SHIELD          = 116,\r\n\tICURS_DRAGONS_BREACH              = 117,\r\n\tICURS_SHORT_BOW                   = 118,\r\n\tICURS_LONG_BATTLE_BOW             = 119,\r\n\tICURS_LONG_WAR_BOW                = 120,\r\n\tICURS_WAR_HAMMER                  = 121,\r\n\tICURS_MAUL                        = 122,\r\n\tICURS_LONG_STAFF                  = 123,\r\n\tICURS_WAR_STAFF                   = 124,\r\n\tICURS_TAVERN_SIGN                 = 126,\r\n\tICURS_HARD_LEATHER_ARMOR          = 127,\r\n\tICURS_RAGS                        = 128,\r\n\tICURS_QUILTED_ARMOR               = 129,\r\n\tICURS_FLAIL                       = 131,\r\n\tICURS_TOWER_SHIELD                = 132,\r\n\tICURS_COMPOSITE_BOW               = 133,\r\n\tICURS_GREAT_SWORD                 = 134,\r\n\tICURS_LEATHER_ARMOR               = 135,\r\n\tICURS_SPLINT_MAIL                 = 136,\r\n\tICURS_ROBE                        = 137,\r\n\tICURS_THE_RAINBOW_CLOAK           = 138,\r\n\tICURS_ANVIL_OF_FURY               = 140,\r\n\tICURS_BROAD_AXE                   = 141,\r\n\tICURS_LARGE_AXE                   = 142,\r\n\tICURS_GREAT_AXE                   = 143,\r\n\tICURS_AXE                         = 144,\r\n\tICURS_BLACKOAK_SHIELD             = 146,\r\n\tICURS_LARGE_SHIELD                = 147,\r\n\tICURS_GOTHIC_SHIELD               = 148,\r\n\tICURS_CLOAK                       = 149,\r\n\tICURS_CAPE                        = 150,\r\n\tICURS_FULL_PLATE_MAIL             = 151,\r\n\tICURS_GOTHIC_PLATE                = 152,\r\n\tICURS_BREAST_PLATE                = 153,\r\n\tICURS_RING_MAIL                   = 154,\r\n\tICURS_STAFF_OF_LAZARUS            = 155,\r\n\tICURS_ARKAINES_VALOR              = 157,\r\n\tICURS_THE_NEEDLER                 = 158,\r\n\tICURS_NAJS_LIGHT_PLATE            = 159,\r\n\tICURS_THE_GRIZZLY                 = 160,\r\n\tICURS_THE_GRANDFATHER             = 161,\r\n\tICURS_THE_PROTECTOR               = 162,\r\n\tICURS_MESSERSCHMIDTS_REAVER       = 163,\r\n\tICURS_WINDFORCE                   = 164,\r\n\tICURS_SHORT_WAR_BOW               = 165,\r\n\tICURS_COMPOSITE_STAFF             = 166,\r\n\tICURS_SHORT_BATTLE_BOW            = 167,\r\n\t// Hellfire items:\r\n\tICURS_XORINES_RING                = 168,\r\n\tICURS_AMULET_OF_WARDING           = 170,\r\n\tICURS_KARIKS_RING                 = 173,\r\n\tICURS_MERCURIAL_RING              = 176,\r\n\tICURS_RING_OF_THUNDER             = 177,\r\n\tICURS_GIANTS_KNUCKLE              = 179,\r\n\tICURS_AURIC_AMULET                = 180,\r\n\tICURS_RING_OF_THE_MYSTICS         = 181,\r\n\tICURS_ACOLYTES_AMULET             = 183,\r\n\tICURS_RING_OF_MAGMA               = 184,\r\n\tICURS_GLADIATORS_RING             = 186,\r\n\tICURS_RUNE_BOMB                   = 187,\r\n\tICURS_THEODORE                    = 188,\r\n\tICURS_TORN_NOTE_1                 = 189,\r\n\tICURS_TORN_NOTE_2                 = 190,\r\n\tICURS_TORN_NOTE_3                 = 191,\r\n\tICURS_RECONSTRUCTED_NOTE          = 192,\r\n\tICURS_RUNE_OF_FIRE                = 193,\r\n\tICURS_GREATER_RUNE_OF_FIRE        = 194,\r\n\tICURS_RUNE_OF_LIGHTNING           = 195,\r\n\tICURS_GREATER_RUNE_OF_LIGHTNING   = 196,\r\n\tICURS_RUNE_OF_STONE               = 197,\r\n\tICURS_GREY_SUIT                   = 198,\r\n\tICURS_BROWN_SUIT                  = 199,\r\n\tICURS_EATER_OF_SOULS              = 200,\r\n\tICURS_ARMOR_OF_GLOOM              = 203,\r\n\tICURS_BONE_CHAIN_ARMOR            = 204,\r\n\tICURS_THUNDERCLAP                 = 205,\r\n\tICURS_DIAMONDEDGE                 = 206,\r\n\tICURS_FLAMBEAU                    = 209,\r\n\tICURS_GNAT_STING                  = 210,\r\n\tICURS_BLITZEN                     = 219,\r\n\tICURS_DEMON_PLATE_ARMOR           = 225,\r\n\tICURS_BOVINE                      = 226,\r\n\r\n\tICURS_DEFAULT = static_cast<uint8_t>(-1),\r\n\t// clang-format on\r\n};\r\n\r\nenum class ItemType : int8_t {\r\n\tMisc,\r\n\tSword,\r\n\tAxe,\r\n\tBow,\r\n\tMace,\r\n\tShield,\r\n\tLightArmor,\r\n\tHelm,\r\n\tMediumArmor,\r\n\tHeavyArmor,\r\n\tStaff,\r\n\tGold,\r\n\tRing,\r\n\tAmulet,\r\n\tNone = -1,\r\n};\r\n\r\nstd::string_view ItemTypeToString(ItemType itemType);\r\n\r\nenum unique_base_item : int8_t {\r\n\tUITYPE_NONE,\r\n\tUITYPE_SHORTBOW,\r\n\tUITYPE_LONGBOW,\r\n\tUITYPE_HUNTBOW,\r\n\tUITYPE_COMPBOW,\r\n\tUITYPE_WARBOW,\r\n\tUITYPE_BATTLEBOW,\r\n\tUITYPE_DAGGER,\r\n\tUITYPE_FALCHION,\r\n\tUITYPE_CLAYMORE,\r\n\tUITYPE_BROADSWR,\r\n\tUITYPE_SABRE,\r\n\tUITYPE_SCIMITAR,\r\n\tUITYPE_LONGSWR,\r\n\tUITYPE_BASTARDSWR,\r\n\tUITYPE_TWOHANDSWR,\r\n\tUITYPE_GREATSWR,\r\n\tUITYPE_CLEAVER,\r\n\tUITYPE_LARGEAXE,\r\n\tUITYPE_BROADAXE,\r\n\tUITYPE_SMALLAXE,\r\n\tUITYPE_BATTLEAXE,\r\n\tUITYPE_GREATAXE,\r\n\tUITYPE_MACE,\r\n\tUITYPE_MORNSTAR,\r\n\tUITYPE_SPIKCLUB,\r\n\tUITYPE_MAUL,\r\n\tUITYPE_WARHAMMER,\r\n\tUITYPE_FLAIL,\r\n\tUITYPE_LONGSTAFF,\r\n\tUITYPE_SHORTSTAFF,\r\n\tUITYPE_COMPSTAFF,\r\n\tUITYPE_QUARSTAFF,\r\n\tUITYPE_WARSTAFF,\r\n\tUITYPE_SKULLCAP,\r\n\tUITYPE_HELM,\r\n\tUITYPE_GREATHELM,\r\n\tUITYPE_CROWN,\r\n\tUITYPE_38,\r\n\tUITYPE_RAGS,\r\n\tUITYPE_STUDARMOR,\r\n\tUITYPE_CLOAK,\r\n\tUITYPE_ROBE,\r\n\tUITYPE_CHAINMAIL,\r\n\tUITYPE_LEATHARMOR,\r\n\tUITYPE_BREASTPLATE,\r\n\tUITYPE_CAPE,\r\n\tUITYPE_PLATEMAIL,\r\n\tUITYPE_FULLPLATE,\r\n\tUITYPE_BUCKLER,\r\n\tUITYPE_SMALLSHIELD,\r\n\tUITYPE_LARGESHIELD,\r\n\tUITYPE_KITESHIELD,\r\n\tUITYPE_GOTHSHIELD,\r\n\tUITYPE_RING,\r\n\tUITYPE_55,\r\n\tUITYPE_AMULET,\r\n\tUITYPE_SKCROWN,\r\n\tUITYPE_INFRARING,\r\n\tUITYPE_OPTAMULET,\r\n\tUITYPE_TRING,\r\n\tUITYPE_HARCREST,\r\n\tUITYPE_MAPOFDOOM,\r\n\tUITYPE_ELIXIR,\r\n\tUITYPE_ARMOFVAL,\r\n\tUITYPE_STEELVEIL,\r\n\tUITYPE_GRISWOLD,\r\n\tUITYPE_LGTFORGE,\r\n\tUITYPE_LAZSTAFF,\r\n\tUITYPE_BOVINE,\r\n\tNUM_DEFAULT_UITYPES,\r\n\tNUM_MAX_UITYPES = std::numeric_limits<int8_t>::max(),\r\n\tUITYPE_INVALID = -1,\r\n};\r\n\r\nenum class ItemSpecialEffect : uint32_t {\r\n\t// clang-format off\r\n\tNone                   = 0,\r\n\tRandomStealLife        = 1 << 1,\r\n\tRandomArrowVelocity    = 1 << 2,\r\n\tFireArrows             = 1 << 3,\r\n\tFireDamage             = 1 << 4,\r\n\tLightningDamage        = 1 << 5,\r\n\tDrainLife              = 1 << 6,\r\n\tMultipleArrows         = 1 << 9,\r\n\tKnockback              = 1 << 11,\r\n\tStealMana3             = 1 << 13,\r\n\tStealMana5             = 1 << 14,\r\n\tStealLife3             = 1 << 15,\r\n\tStealLife5             = 1 << 16,\r\n\tQuickAttack            = 1 << 17,\r\n\tFastAttack             = 1 << 18,\r\n\tFasterAttack           = 1 << 19,\r\n\tFastestAttack          = 1 << 20,\r\n\tFastHitRecovery        = 1 << 21,\r\n\tFasterHitRecovery      = 1 << 22,\r\n\tFastestHitRecovery     = 1 << 23,\r\n\tFastBlock              = 1 << 24,\r\n\tLightningArrows        = 1 << 25,\r\n\tThorns                 = 1 << 26,\r\n\tNoMana                 = 1 << 27,\r\n\tHalfTrapDamage         = 1 << 28,\r\n\tTripleDemonDamage      = 1 << 30,\r\n\tZeroResistance         = 1U << 31,\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(ItemSpecialEffect);\r\n\r\nenum class ItemSpecialEffectHf : uint8_t {\r\n\t// clang-format off\r\n\tNone               = 0,\r\n\tDevastation        = 1 << 0,\r\n\tDecay              = 1 << 1,\r\n\tPeril              = 1 << 2,\r\n\tJesters            = 1 << 3,\r\n\tDoppelganger       = 1 << 4,\r\n\tACAgainstDemons    = 1 << 5,\r\n\tACAgainstUndead    = 1 << 6,\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(ItemSpecialEffectHf);\r\n\r\nenum item_misc_id : int8_t {\r\n\tIMISC_NONE,\r\n\tIMISC_USEFIRST,\r\n\tIMISC_FULLHEAL,\r\n\tIMISC_HEAL,\r\n\tIMISC_0x4, // Unused\r\n\tIMISC_0x5, // Unused\r\n\tIMISC_MANA,\r\n\tIMISC_FULLMANA,\r\n\tIMISC_0x8, // Unused\r\n\tIMISC_0x9, // Unused\r\n\tIMISC_ELIXSTR,\r\n\tIMISC_ELIXMAG,\r\n\tIMISC_ELIXDEX,\r\n\tIMISC_ELIXVIT,\r\n\tIMISC_0xE,  // Unused\r\n\tIMISC_0xF,  // Unused\r\n\tIMISC_0x10, // Unused\r\n\tIMISC_0x11, // Unused\r\n\tIMISC_REJUV,\r\n\tIMISC_FULLREJUV,\r\n\tIMISC_USELAST,\r\n\tIMISC_SCROLL,\r\n\tIMISC_SCROLLT,\r\n\tIMISC_STAFF,\r\n\tIMISC_BOOK,\r\n\tIMISC_RING,\r\n\tIMISC_AMULET,\r\n\tIMISC_UNIQUE,\r\n\tIMISC_0x1C, // Unused\r\n\tIMISC_OILFIRST,\r\n\tIMISC_OILOF, /* oils are beta or hellfire only */\r\n\tIMISC_OILACC,\r\n\tIMISC_OILMAST,\r\n\tIMISC_OILSHARP,\r\n\tIMISC_OILDEATH,\r\n\tIMISC_OILSKILL,\r\n\tIMISC_OILBSMTH,\r\n\tIMISC_OILFORT,\r\n\tIMISC_OILPERM,\r\n\tIMISC_OILHARD,\r\n\tIMISC_OILIMP,\r\n\tIMISC_OILLAST,\r\n\tIMISC_MAPOFDOOM,\r\n\tIMISC_EAR,\r\n\tIMISC_SPECELIX,\r\n\tIMISC_0x2D, // Unused\r\n\tIMISC_RUNEFIRST,\r\n\tIMISC_RUNEF,\r\n\tIMISC_RUNEL,\r\n\tIMISC_GR_RUNEL,\r\n\tIMISC_GR_RUNEF,\r\n\tIMISC_RUNES,\r\n\tIMISC_RUNELAST,\r\n\tIMISC_AURIC,\r\n\tIMISC_NOTE,\r\n\tIMISC_ARENAPOT,\r\n\tIMISC_INVALID = -1,\r\n};\r\n\r\nstruct ItemData {\r\n\tuint8_t dropRate;\r\n\tenum item_class iClass;\r\n\tenum item_equip_type iLoc;\r\n\tenum item_cursor_graphic iCurs;\r\n\tenum ItemType itype;\r\n\tenum unique_base_item iItemId;\r\n\tstd::string iName;\r\n\tstd::string iSName;\r\n\tuint8_t iMinMLvl;\r\n\tuint8_t iDurability;\r\n\tuint8_t iMinDam;\r\n\tuint8_t iMaxDam;\r\n\tuint8_t iMinAC;\r\n\tuint8_t iMaxAC;\r\n\tuint8_t iMinStr;\r\n\tuint8_t iMinMag;\r\n\tuint8_t iMinDex;\r\n\tItemSpecialEffect iFlags; // ItemSpecialEffect as bit flags\r\n\tenum item_misc_id iMiscId;\r\n\tSpellID iSpell;\r\n\tbool iUsable;\r\n\tuint16_t iValue;\r\n\tint32_t iMappingId;\r\n};\r\n\r\nenum item_effect_type : int8_t {\r\n\tIPL_TOHIT,\r\n\tIPL_TOHIT_CURSE,\r\n\tIPL_DAMP,\r\n\tIPL_DAMP_CURSE,\r\n\tIPL_TOHIT_DAMP,\r\n\tIPL_TOHIT_DAMP_CURSE,\r\n\tIPL_ACP,\r\n\tIPL_ACP_CURSE,\r\n\tIPL_FIRERES,\r\n\tIPL_LIGHTRES,\r\n\tIPL_MAGICRES,\r\n\tIPL_ALLRES,\r\n\tIPL_SPLLVLADD = 14,\r\n\tIPL_CHARGES,\r\n\tIPL_FIREDAM,\r\n\tIPL_LIGHTDAM,\r\n\tIPL_STR = 19,\r\n\tIPL_STR_CURSE,\r\n\tIPL_MAG,\r\n\tIPL_MAG_CURSE,\r\n\tIPL_DEX,\r\n\tIPL_DEX_CURSE,\r\n\tIPL_VIT,\r\n\tIPL_VIT_CURSE,\r\n\tIPL_ATTRIBS,\r\n\tIPL_ATTRIBS_CURSE,\r\n\tIPL_GETHIT_CURSE,\r\n\tIPL_GETHIT,\r\n\tIPL_LIFE,\r\n\tIPL_LIFE_CURSE,\r\n\tIPL_MANA,\r\n\tIPL_MANA_CURSE,\r\n\tIPL_DUR,\r\n\tIPL_DUR_CURSE,\r\n\tIPL_INDESTRUCTIBLE,\r\n\tIPL_LIGHT,\r\n\tIPL_LIGHT_CURSE,\r\n\tIPL_MULT_ARROWS = 41, /* only used in hellfire */\r\n\tIPL_FIRE_ARROWS,\r\n\tIPL_LIGHT_ARROWS,\r\n\tIPL_THORNS = 45,\r\n\tIPL_NOMANA,\r\n\tIPL_FIREBALL = 50, /* only used in hellfire */\r\n\tIPL_ABSHALFTRAP = 52,\r\n\tIPL_KNOCKBACK,\r\n\tIPL_STEALMANA = 55,\r\n\tIPL_STEALLIFE,\r\n\tIPL_TARGAC,\r\n\tIPL_FASTATTACK,\r\n\tIPL_FASTRECOVER,\r\n\tIPL_FASTBLOCK,\r\n\tIPL_DAMMOD,\r\n\tIPL_RNDARROWVEL,\r\n\tIPL_SETDAM,\r\n\tIPL_SETDUR,\r\n\tIPL_NOMINSTR,\r\n\tIPL_SPELL,\r\n\tIPL_ONEHAND = 68,\r\n\tIPL_3XDAMVDEM,\r\n\tIPL_ALLRESZERO,\r\n\tIPL_DRAINLIFE = 72,\r\n\tIPL_RNDSTEALLIFE,\r\n\tIPL_SETAC = 75,\r\n\tIPL_ADDACLIFE,\r\n\tIPL_ADDMANAAC,\r\n\tIPL_AC_CURSE = 79,\r\n\tIPL_LASTDIABLO = IPL_AC_CURSE,\r\n\tIPL_FIRERES_CURSE,\r\n\tIPL_LIGHTRES_CURSE,\r\n\tIPL_MAGICRES_CURSE,\r\n\tIPL_DEVASTATION = 84,\r\n\tIPL_DECAY,\r\n\tIPL_PERIL,\r\n\tIPL_JESTERS,\r\n\tIPL_CRYSTALLINE,\r\n\tIPL_DOPPELGANGER,\r\n\tIPL_ACDEMON,\r\n\tIPL_ACUNDEAD,\r\n\tIPL_MANATOLIFE,\r\n\tIPL_LIFETOMANA,\r\n\tIPL_INVALID = -1,\r\n};\r\n\r\nenum goodorevil : uint8_t {\r\n\tGOE_ANY,\r\n\tGOE_EVIL,\r\n\tGOE_GOOD,\r\n};\r\n\r\nenum class AffixItemType : uint8_t {\r\n\t// clang-format off\r\n\tNone      = 0,\r\n\tMisc      = 1 << 0,\r\n\tBow       = 1 << 1,\r\n\tStaff     = 1 << 2,\r\n\tWeapon    = 1 << 3,\r\n\tShield    = 1 << 4,\r\n\tArmor     = 1 << 5,\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(AffixItemType);\r\n\r\nstruct ItemPower {\r\n\titem_effect_type type = IPL_INVALID;\r\n\tint param1 = 0;\r\n\tint param2 = 0;\r\n};\r\n\r\nstruct PLStruct {\r\n\tstd::string PLName;\r\n\tItemPower power;\r\n\tint8_t PLMinLvl;\r\n\tAffixItemType PLIType; // AffixItemType as bit flags\r\n\tenum goodorevil PLGOE;\r\n\tuint8_t PLChance;\r\n\tbool PLOk;\r\n\tint minVal;\r\n\tint maxVal;\r\n\tint multVal;\r\n};\r\n\r\nstruct UniqueItem {\r\n\tstd::string UIName;\r\n\tenum item_cursor_graphic UICurs;\r\n\tenum unique_base_item UIItemId;\r\n\tint8_t UIMinLvl;\r\n\tuint8_t UINumPL;\r\n\tint UIValue;\r\n\tItemPower powers[6];\r\n\tint32_t mappingId;\r\n};\r\n\r\nextern DVL_API_FOR_TEST std::vector<ItemData> AllItemsList;\r\nextern ankerl::unordered_dense::map<int32_t, int16_t> ItemMappingIdsToIndices;\r\nextern std::vector<PLStruct> ItemPrefixes;\r\nextern std::vector<PLStruct> ItemSuffixes;\r\nextern DVL_API_FOR_TEST std::vector<UniqueItem> UniqueItems;\r\nextern ankerl::unordered_dense::map<int32_t, int32_t> UniqueItemMappingIdsToIndices;\r\n\r\ntl::expected<_item_indexes, std::string> ParseItemId(std::string_view value);\r\nvoid LoadItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId);\r\nvoid LoadUniqueItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId);\r\nvoid LoadItemData();\r\n\r\n} // namespace devilution\r\n\r\ntemplate <>\r\nstruct magic_enum::customize::enum_range<devilution::_item_indexes> {\r\n\tstatic constexpr int min = devilution::_item_indexes::IDI_NONE;\r\n\tstatic constexpr int max = devilution::_item_indexes::IDI_NUM_DEFAULT_ITEMS;\r\n};\r\n"
  },
  {
    "path": "Source/tables/misdat.cpp",
    "content": "/**\r\n * @file misdat.cpp\r\n *\r\n * Implementation of data related to missiles.\r\n */\r\n#include \"tables/misdat.h\"\r\n\r\n#include <array>\r\n#include <cassert>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <string>\r\n#include <string_view>\r\n#include <type_traits>\r\n#include <utility>\r\n#include <vector>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"missiles.h\"\r\n#include \"mpq/mpq_common.hpp\"\r\n#include \"sound_effect_enums.h\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/file_name_generator.hpp\"\r\n#include \"utils/status_macros.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef UNPACKED_MPQS\r\n#include \"engine/load_clx.hpp\"\r\n#else\r\n#include \"engine/load_cl2.hpp\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n/** Data related to each missile graphic ID. */\r\nstd::vector<MissileFileData> MissileSpriteData;\r\nstd::vector<std::array<uint8_t, 16>> MissileAnimDelays;\r\nstd::vector<std::array<uint8_t, 16>> MissileAnimLengths;\r\n\r\n/** Data related to each missile ID. */\r\nstd::vector<MissileData> MissilesData;\r\n\r\nsize_t ToIndex(std::vector<std::array<uint8_t, 16>> &all, const std::array<uint8_t, 16> &value)\r\n{\r\n\tfor (size_t i = 0; i < all.size(); ++i) {\r\n\t\tif (all[i] == value) return i;\r\n\t}\r\n\tall.push_back(value);\r\n\treturn all.size() - 1;\r\n}\r\n\r\ntl::expected<MissileGraphicsFlags, std::string> ParseMissileGraphicsFlag(std::string_view value)\r\n{\r\n\tif (value.empty()) return MissileGraphicsFlags::None;\r\n\tif (value == \"MonsterOwned\") return MissileGraphicsFlags::MonsterOwned;\r\n\tif (value == \"NotAnimated\") return MissileGraphicsFlags::NotAnimated;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<MissileGraphicID, std::string> ParseMissileGraphicID(std::string_view value)\r\n{\r\n\tif (value.empty()) return MissileGraphicID::None;\r\n\tif (value == \"Arrow\") return MissileGraphicID::Arrow;\r\n\tif (value == \"Fireball\") return MissileGraphicID::Fireball;\r\n\tif (value == \"Guardian\") return MissileGraphicID::Guardian;\r\n\tif (value == \"Lightning\") return MissileGraphicID::Lightning;\r\n\tif (value == \"FireWall\") return MissileGraphicID::FireWall;\r\n\tif (value == \"MagmaBallExplosion\") return MissileGraphicID::MagmaBallExplosion;\r\n\tif (value == \"TownPortal\") return MissileGraphicID::TownPortal;\r\n\tif (value == \"FlashBottom\") return MissileGraphicID::FlashBottom;\r\n\tif (value == \"FlashTop\") return MissileGraphicID::FlashTop;\r\n\tif (value == \"ManaShield\") return MissileGraphicID::ManaShield;\r\n\tif (value == \"BloodHit\") return MissileGraphicID::BloodHit;\r\n\tif (value == \"BoneHit\") return MissileGraphicID::BoneHit;\r\n\tif (value == \"MetalHit\") return MissileGraphicID::MetalHit;\r\n\tif (value == \"FireArrow\") return MissileGraphicID::FireArrow;\r\n\tif (value == \"DoomSerpents\") return MissileGraphicID::DoomSerpents;\r\n\tif (value == \"Golem\") return MissileGraphicID::Golem;\r\n\tif (value == \"Spurt\") return MissileGraphicID::Spurt;\r\n\tif (value == \"ApocalypseBoom\") return MissileGraphicID::ApocalypseBoom;\r\n\tif (value == \"StoneCurseShatter\") return MissileGraphicID::StoneCurseShatter;\r\n\tif (value == \"BigExplosion\") return MissileGraphicID::BigExplosion;\r\n\tif (value == \"Inferno\") return MissileGraphicID::Inferno;\r\n\tif (value == \"ThinLightning\") return MissileGraphicID::ThinLightning;\r\n\tif (value == \"BloodStar\") return MissileGraphicID::BloodStar;\r\n\tif (value == \"BloodStarExplosion\") return MissileGraphicID::BloodStarExplosion;\r\n\tif (value == \"MagmaBall\") return MissileGraphicID::MagmaBall;\r\n\tif (value == \"Krull\") return MissileGraphicID::Krull;\r\n\tif (value == \"ChargedBolt\") return MissileGraphicID::ChargedBolt;\r\n\tif (value == \"HolyBolt\") return MissileGraphicID::HolyBolt;\r\n\tif (value == \"HolyBoltExplosion\") return MissileGraphicID::HolyBoltExplosion;\r\n\tif (value == \"LightningArrow\") return MissileGraphicID::LightningArrow;\r\n\tif (value == \"FireArrowExplosion\") return MissileGraphicID::FireArrowExplosion;\r\n\tif (value == \"Acid\") return MissileGraphicID::Acid;\r\n\tif (value == \"AcidSplat\") return MissileGraphicID::AcidSplat;\r\n\tif (value == \"AcidPuddle\") return MissileGraphicID::AcidPuddle;\r\n\tif (value == \"Etherealize\") return MissileGraphicID::Etherealize;\r\n\tif (value == \"Elemental\") return MissileGraphicID::Elemental;\r\n\tif (value == \"Resurrect\") return MissileGraphicID::Resurrect;\r\n\tif (value == \"BoneSpirit\") return MissileGraphicID::BoneSpirit;\r\n\tif (value == \"RedPortal\") return MissileGraphicID::RedPortal;\r\n\tif (value == \"DiabloApocalypseBoom\") return MissileGraphicID::DiabloApocalypseBoom;\r\n\tif (value == \"BloodStarBlue\") return MissileGraphicID::BloodStarBlue;\r\n\tif (value == \"BloodStarBlueExplosion\") return MissileGraphicID::BloodStarBlueExplosion;\r\n\tif (value == \"BloodStarYellow\") return MissileGraphicID::BloodStarYellow;\r\n\tif (value == \"BloodStarYellowExplosion\") return MissileGraphicID::BloodStarYellowExplosion;\r\n\tif (value == \"BloodStarRed\") return MissileGraphicID::BloodStarRed;\r\n\tif (value == \"BloodStarRedExplosion\") return MissileGraphicID::BloodStarRedExplosion;\r\n\tif (value == \"HorkSpawn\") return MissileGraphicID::HorkSpawn;\r\n\tif (value == \"Reflect\") return MissileGraphicID::Reflect;\r\n\tif (value == \"OrangeFlare\") return MissileGraphicID::OrangeFlare;\r\n\tif (value == \"BlueFlare\") return MissileGraphicID::BlueFlare;\r\n\tif (value == \"RedFlare\") return MissileGraphicID::RedFlare;\r\n\tif (value == \"YellowFlare\") return MissileGraphicID::YellowFlare;\r\n\tif (value == \"Rune\") return MissileGraphicID::Rune;\r\n\tif (value == \"YellowFlareExplosion\") return MissileGraphicID::YellowFlareExplosion;\r\n\tif (value == \"BlueFlareExplosion\") return MissileGraphicID::BlueFlareExplosion;\r\n\tif (value == \"RedFlareExplosion\") return MissileGraphicID::RedFlareExplosion;\r\n\tif (value == \"BlueFlare2\") return MissileGraphicID::BlueFlare2;\r\n\tif (value == \"OrangeFlareExplosion\") return MissileGraphicID::OrangeFlareExplosion;\r\n\tif (value == \"BlueFlareExplosion2\") return MissileGraphicID::BlueFlareExplosion2;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\nvoid LoadMissileSpriteData()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\missiles\\\\missile_sprites.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tMissileAnimDelays.clear();\r\n\tMissileAnimLengths.clear();\r\n\tMissileSpriteData.clear();\r\n\tMissileSpriteData.reserve(dataFile.numRecords());\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tMissileFileData &item = MissileSpriteData.emplace_back();\r\n\t\tMissileGraphicID id;\r\n\t\treader.read(\"id\", id, ParseMissileGraphicID);\r\n\t\tassert(static_cast<size_t>(id) + 1 == MissileSpriteData.size());\r\n\t\treader.readInt(\"width\", item.animWidth);\r\n\t\treader.readInt(\"width2\", item.animWidth2);\r\n\t\treader.readString(\"name\", item.name);\r\n\t\treader.readInt(\"numFrames\", item.animFAmt);\r\n\t\treader.read(\"flags\", item.flags, ParseMissileGraphicsFlag);\r\n\r\n\t\tstd::array<uint8_t, 16> arr;\r\n\t\treader.readIntArray(\"frameDelay\", arr);\r\n\t\titem.animDelayIdx = static_cast<uint8_t>(ToIndex(MissileAnimDelays, arr));\r\n\r\n\t\treader.readIntArray(\"frameLength\", arr);\r\n\t\titem.animLenIdx = static_cast<uint8_t>(ToIndex(MissileAnimLengths, arr));\r\n\t}\r\n\r\n\tMissileSpriteData.shrink_to_fit();\r\n\tMissileAnimDelays.shrink_to_fit();\r\n\tMissileAnimLengths.shrink_to_fit();\r\n}\r\n\r\ntl::expected<MissileDataFlags, std::string> ParseMissileDataFlag(std::string_view value)\r\n{\r\n\tif (value == \"Physical\") return MissileDataFlags::Physical;\r\n\tif (value == \"Fire\") return MissileDataFlags::Fire;\r\n\tif (value == \"Lightning\") return MissileDataFlags::Lightning;\r\n\tif (value == \"Magic\") return MissileDataFlags::Magic;\r\n\tif (value == \"Acid\") return MissileDataFlags::Acid;\r\n\tif (value == \"Arrow\") return MissileDataFlags::Arrow;\r\n\tif (value == \"Invisible\") return MissileDataFlags::Invisible;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\n// NOLINTNEXTLINE(readability-function-cognitive-complexity)\r\ntl::expected<MissileData::AddFn, std::string> ParseMissileAddFn(std::string_view value)\r\n{\r\n\tif (value.empty()) return nullptr;\r\n\tif (value == \"AddOpenNest\") return AddOpenNest;\r\n\tif (value == \"AddRuneOfFire\") return AddRuneOfFire;\r\n\tif (value == \"AddRuneOfLight\") return AddRuneOfLight;\r\n\tif (value == \"AddRuneOfNova\") return AddRuneOfNova;\r\n\tif (value == \"AddRuneOfImmolation\") return AddRuneOfImmolation;\r\n\tif (value == \"AddRuneOfStone\") return AddRuneOfStone;\r\n\tif (value == \"AddReflect\") return AddReflect;\r\n\tif (value == \"AddBerserk\") return AddBerserk;\r\n\tif (value == \"AddHorkSpawn\") return AddHorkSpawn;\r\n\tif (value == \"AddJester\") return AddJester;\r\n\tif (value == \"AddStealPotions\") return AddStealPotions;\r\n\tif (value == \"AddStealMana\") return AddStealMana;\r\n\tif (value == \"AddSpectralArrow\") return AddSpectralArrow;\r\n\tif (value == \"AddWarp\") return AddWarp;\r\n\tif (value == \"AddLightningWall\") return AddLightningWall;\r\n\tif (value == \"AddBigExplosion\") return AddBigExplosion;\r\n\tif (value == \"AddImmolation\") return AddImmolation;\r\n\tif (value == \"AddLightningBow\") return AddLightningBow;\r\n\tif (value == \"AddMana\") return AddMana;\r\n\tif (value == \"AddMagi\") return AddMagi;\r\n\tif (value == \"AddRingOfFire\") return AddRingOfFire;\r\n\tif (value == \"AddSearch\") return AddSearch;\r\n\tif (value == \"AddChargedBoltBow\") return AddChargedBoltBow;\r\n\tif (value == \"AddElementalArrow\") return AddElementalArrow;\r\n\tif (value == \"AddArrow\") return AddArrow;\r\n\tif (value == \"AddPhasing\") return AddPhasing;\r\n\tif (value == \"AddFirebolt\") return AddFirebolt;\r\n\tif (value == \"AddMagmaBall\") return AddMagmaBall;\r\n\tif (value == \"AddTeleport\") return AddTeleport;\r\n\tif (value == \"AddNovaBall\") return AddNovaBall;\r\n\tif (value == \"AddFireWall\") return AddFireWall;\r\n\tif (value == \"AddFireball\") return AddFireball;\r\n\tif (value == \"AddLightningControl\") return AddLightningControl;\r\n\tif (value == \"AddLightning\") return AddLightning;\r\n\tif (value == \"AddMissileExplosion\") return AddMissileExplosion;\r\n\tif (value == \"AddWeaponExplosion\") return AddWeaponExplosion;\r\n\tif (value == \"AddTownPortal\") return AddTownPortal;\r\n\tif (value == \"AddFlashBottom\") return AddFlashBottom;\r\n\tif (value == \"AddFlashTop\") return AddFlashTop;\r\n\tif (value == \"AddManaShield\") return AddManaShield;\r\n\tif (value == \"AddFlameWave\") return AddFlameWave;\r\n\tif (value == \"AddGuardian\") return AddGuardian;\r\n\tif (value == \"AddChainLightning\") return AddChainLightning;\r\n\tif (value == \"AddRhino\") return AddRhino;\r\n\tif (value == \"AddGenericMagicMissile\") return AddGenericMagicMissile;\r\n\tif (value == \"AddAcid\") return AddAcid;\r\n\tif (value == \"AddAcidPuddle\") return AddAcidPuddle;\r\n\tif (value == \"AddStoneCurse\") return AddStoneCurse;\r\n\tif (value == \"AddGolem\") return AddGolem;\r\n\tif (value == \"AddApocalypseBoom\") return AddApocalypseBoom;\r\n\tif (value == \"AddHealing\") return AddHealing;\r\n\tif (value == \"AddHealOther\") return AddHealOther;\r\n\tif (value == \"AddElemental\") return AddElemental;\r\n\tif (value == \"AddIdentify\") return AddIdentify;\r\n\tif (value == \"AddWallControl\") return AddWallControl;\r\n\tif (value == \"AddInfravision\") return AddInfravision;\r\n\tif (value == \"AddFlameWaveControl\") return AddFlameWaveControl;\r\n\tif (value == \"AddNova\") return AddNova;\r\n\tif (value == \"AddRage\") return AddRage;\r\n\tif (value == \"AddItemRepair\") return AddItemRepair;\r\n\tif (value == \"AddStaffRecharge\") return AddStaffRecharge;\r\n\tif (value == \"AddTrapDisarm\") return AddTrapDisarm;\r\n\tif (value == \"AddApocalypse\") return AddApocalypse;\r\n\tif (value == \"AddInferno\") return AddInferno;\r\n\tif (value == \"AddInfernoControl\") return AddInfernoControl;\r\n\tif (value == \"AddChargedBolt\") return AddChargedBolt;\r\n\tif (value == \"AddHolyBolt\") return AddHolyBolt;\r\n\tif (value == \"AddResurrect\") return AddResurrect;\r\n\tif (value == \"AddResurrectBeam\") return AddResurrectBeam;\r\n\tif (value == \"AddTelekinesis\") return AddTelekinesis;\r\n\tif (value == \"AddBoneSpirit\") return AddBoneSpirit;\r\n\tif (value == \"AddRedPortal\") return AddRedPortal;\r\n\tif (value == \"AddDiabloApocalypse\") return AddDiabloApocalypse;\r\n\treturn tl::make_unexpected(\"Unknown MissileData::AddFn name\");\r\n}\r\n\r\n// NOLINTNEXTLINE(readability-function-cognitive-complexity)\r\ntl::expected<MissileData::ProcessFn, std::string> ParseMissileProcessFn(std::string_view value)\r\n{\r\n\tif (value.empty()) return nullptr;\r\n\tif (value == \"ProcessElementalArrow\") return ProcessElementalArrow;\r\n\tif (value == \"ProcessArrow\") return ProcessArrow;\r\n\tif (value == \"ProcessGenericProjectile\") return ProcessGenericProjectile;\r\n\tif (value == \"ProcessNovaBall\") return ProcessNovaBall;\r\n\tif (value == \"ProcessAcidPuddle\") return ProcessAcidPuddle;\r\n\tif (value == \"ProcessFireWall\") return ProcessFireWall;\r\n\tif (value == \"ProcessFireball\") return ProcessFireball;\r\n\tif (value == \"ProcessHorkSpawn\") return ProcessHorkSpawn;\r\n\tif (value == \"ProcessRune\") return ProcessRune;\r\n\tif (value == \"ProcessLightningWall\") return ProcessLightningWall;\r\n\tif (value == \"ProcessBigExplosion\") return ProcessBigExplosion;\r\n\tif (value == \"ProcessLightningBow\") return ProcessLightningBow;\r\n\tif (value == \"ProcessRingOfFire\") return ProcessRingOfFire;\r\n\tif (value == \"ProcessSearch\") return ProcessSearch;\r\n\tif (value == \"ProcessImmolation\") return ProcessImmolation;\r\n\tif (value == \"ProcessSpectralArrow\") return ProcessSpectralArrow;\r\n\tif (value == \"ProcessLightningControl\") return ProcessLightningControl;\r\n\tif (value == \"ProcessLightning\") return ProcessLightning;\r\n\tif (value == \"ProcessTownPortal\") return ProcessTownPortal;\r\n\tif (value == \"ProcessFlashBottom\") return ProcessFlashBottom;\r\n\tif (value == \"ProcessFlashTop\") return ProcessFlashTop;\r\n\tif (value == \"ProcessFlameWave\") return ProcessFlameWave;\r\n\tif (value == \"ProcessGuardian\") return ProcessGuardian;\r\n\tif (value == \"ProcessChainLightning\") return ProcessChainLightning;\r\n\tif (value == \"ProcessWeaponExplosion\") return ProcessWeaponExplosion;\r\n\tif (value == \"ProcessMissileExplosion\") return ProcessMissileExplosion;\r\n\tif (value == \"ProcessAcidSplate\") return ProcessAcidSplate;\r\n\tif (value == \"ProcessTeleport\") return ProcessTeleport;\r\n\tif (value == \"ProcessStoneCurse\") return ProcessStoneCurse;\r\n\tif (value == \"ProcessApocalypseBoom\") return ProcessApocalypseBoom;\r\n\tif (value == \"ProcessRhino\") return ProcessRhino;\r\n\tif (value == \"ProcessWallControl\") return ProcessWallControl;\r\n\tif (value == \"ProcessInfravision\") return ProcessInfravision;\r\n\tif (value == \"ProcessApocalypse\") return ProcessApocalypse;\r\n\tif (value == \"ProcessFlameWaveControl\") return ProcessFlameWaveControl;\r\n\tif (value == \"ProcessNova\") return ProcessNova;\r\n\tif (value == \"ProcessRage\") return ProcessRage;\r\n\tif (value == \"ProcessInferno\") return ProcessInferno;\r\n\tif (value == \"ProcessInfernoControl\") return ProcessInfernoControl;\r\n\tif (value == \"ProcessChargedBolt\") return ProcessChargedBolt;\r\n\tif (value == \"ProcessHolyBolt\") return ProcessHolyBolt;\r\n\tif (value == \"ProcessElemental\") return ProcessElemental;\r\n\tif (value == \"ProcessBoneSpirit\") return ProcessBoneSpirit;\r\n\tif (value == \"ProcessResurrectBeam\") return ProcessResurrectBeam;\r\n\tif (value == \"ProcessRedPortal\") return ProcessRedPortal;\r\n\treturn tl::make_unexpected(\"Unknown MissileData::ProcessFn name\");\r\n}\r\n\r\n// A temporary solution for parsing SfxID until we have a more general one.\r\n// NOLINTNEXTLINE(readability-function-cognitive-complexity)\r\ntl::expected<SfxID, std::string> ParseCastSound(std::string_view value)\r\n{\r\n\tif (value.empty()) return SfxID::None;\r\n\tif (value == \"BigExplosion\") return SfxID::BigExplosion;\r\n\tif (value == \"ShootFireballBow\") return SfxID::ShootFireballBow;\r\n\tif (value == \"SpellAcid\") return SfxID::SpellAcid;\r\n\tif (value == \"SpellApocalypse\") return SfxID::SpellApocalypse;\r\n\tif (value == \"SpellBloodStar\") return SfxID::SpellBloodStar;\r\n\tif (value == \"SpellBoneSpirit\") return SfxID::SpellBoneSpirit;\r\n\tif (value == \"SpellChargedBolt\") return SfxID::SpellChargedBolt;\r\n\tif (value == \"SpellDoomSerpents\") return SfxID::SpellDoomSerpents;\r\n\tif (value == \"SpellElemental\") return SfxID::SpellElemental;\r\n\tif (value == \"SpellEnd\") return SfxID::SpellEnd;\r\n\tif (value == \"SpellEtherealize\") return SfxID::SpellEtherealize;\r\n\tif (value == \"SpellFireHit\") return SfxID::SpellFireHit;\r\n\tif (value == \"SpellFireWall\") return SfxID::SpellFireWall;\r\n\tif (value == \"SpellFirebolt\") return SfxID::SpellFirebolt;\r\n\tif (value == \"SpellFlameWave\") return SfxID::SpellFlameWave;\r\n\tif (value == \"SpellGolem\") return SfxID::SpellGolem;\r\n\tif (value == \"SpellGuardian\") return SfxID::SpellGuardian;\r\n\tif (value == \"SpellHolyBolt\") return SfxID::SpellHolyBolt;\r\n\tif (value == \"SpellInferno\") return SfxID::SpellInferno;\r\n\tif (value == \"SpellInfravision\") return SfxID::SpellInfravision;\r\n\tif (value == \"SpellInvisibility\") return SfxID::SpellInvisibility;\r\n\tif (value == \"SpellLightning\") return SfxID::SpellLightning;\r\n\tif (value == \"SpellLightningWall\") return SfxID::SpellLightningWall;\r\n\tif (value == \"SpellManaShield\") return SfxID::SpellManaShield;\r\n\tif (value == \"SpellNova\") return SfxID::SpellNova;\r\n\tif (value == \"SpellPortal\") return SfxID::SpellPortal;\r\n\tif (value == \"SpellPuddle\") return SfxID::SpellPuddle;\r\n\tif (value == \"SpellStoneCurse\") return SfxID::SpellStoneCurse;\r\n\tif (value == \"SpellTeleport\") return SfxID::SpellTeleport;\r\n\tif (value == \"SpellTrapDisarm\") return SfxID::SpellTrapDisarm;\r\n\treturn tl::make_unexpected(\"Unknown enum value (only a few are supported for now)\");\r\n}\r\n\r\n// A temporary solution for parsing SfxID until we have a more general one.\r\ntl::expected<SfxID, std::string> ParseHitSound(std::string_view value)\r\n{\r\n\tif (value.empty()) return SfxID::None;\r\n\tif (value == \"BigExplosion\") return SfxID::BigExplosion;\r\n\tif (value == \"SpellBloodStarHit\") return SfxID::SpellBloodStarHit;\r\n\tif (value == \"SpellBoneSpiritHit\") return SfxID::SpellBoneSpiritHit;\r\n\tif (value == \"SpellFireHit\") return SfxID::SpellFireHit;\r\n\tif (value == \"SpellLightningHit\") return SfxID::SpellLightningHit;\r\n\tif (value == \"SpellResurrect\") return SfxID::SpellResurrect;\r\n\treturn tl::make_unexpected(\"Unknown enum value (only a few are supported for now)\");\r\n}\r\n\r\ntl::expected<MissileMovementDistribution, std::string> ParseMissileMovementDistribution(std::string_view value)\r\n{\r\n\tif (value.empty()) return MissileMovementDistribution::Disabled;\r\n\tif (value == \"Blockable\") return MissileMovementDistribution::Blockable;\r\n\tif (value == \"Unblockable\") return MissileMovementDistribution::Unblockable;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\nvoid LoadMisdat()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\missiles\\\\misdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tMissilesData.clear();\r\n\tMissilesData.reserve(dataFile.numRecords());\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tMissileData &item = MissilesData.emplace_back();\r\n\t\treader.advance(); // skip id\r\n\t\treader.read(\"addFn\", item.addFn, ParseMissileAddFn);\r\n\t\treader.read(\"processFn\", item.processFn, ParseMissileProcessFn);\r\n\t\treader.read(\"castSound\", item.castSound, ParseCastSound);\r\n\t\treader.read(\"hitSound\", item.hitSound, ParseHitSound);\r\n\t\treader.read(\"graphic\", item.graphic, ParseMissileGraphicID);\r\n\t\treader.readEnumList(\"flags\", item.flags, ParseMissileDataFlag);\r\n\t\treader.read(\"movementDistribution\", item.movementDistribution, ParseMissileMovementDistribution);\r\n\t}\r\n\r\n\t// Sanity check because we do not actually parse the IDs yet.\r\n\tassert(static_cast<size_t>(MissileID::LastDiablo) + 1 == MissilesData.size() || static_cast<size_t>(MissileID::LAST) + 1 == MissilesData.size());\r\n\r\n\tMissilesData.shrink_to_fit();\r\n}\r\n\r\n} // namespace\r\n\r\nuint8_t MissileFileData::animDelay(uint8_t dir) const\r\n{\r\n\treturn MissileAnimDelays[animDelayIdx][dir];\r\n}\r\n\r\nuint8_t MissileFileData::animLen(uint8_t dir) const\r\n{\r\n\treturn MissileAnimLengths[animLenIdx][dir];\r\n}\r\n\r\ntl::expected<void, std::string> MissileFileData::LoadGFX()\r\n{\r\n\tif (sprites)\r\n\t\treturn {};\r\n\r\n\tif (name[0] == '\\0')\r\n\t\treturn {};\r\n\r\n#ifdef UNPACKED_MPQS\r\n\tchar path[MaxMpqPathSize];\r\n\t*BufCopy(path, \"missiles\\\\\", name, \".clx\") = '\\0';\r\n\tASSIGN_OR_RETURN(sprites, LoadClxListOrSheetWithStatus(path));\r\n#else\r\n\tif (animFAmt == 1) {\r\n\t\tchar path[MaxMpqPathSize];\r\n\t\t*BufCopy(path, \"missiles\\\\\", name) = '\\0';\r\n\t\tASSIGN_OR_RETURN(OwnedClxSpriteList spriteList, LoadCl2WithStatus(path, animWidth));\r\n\t\tsprites.emplace(OwnedClxSpriteListOrSheet { std::move(spriteList) });\r\n\t} else {\r\n\t\tFileNameGenerator pathGenerator({ \"missiles\\\\\", name }, DEVILUTIONX_CL2_EXT);\r\n\t\tASSIGN_OR_RETURN(OwnedClxSpriteSheet spriteSheet, LoadMultipleCl2Sheet<16>(pathGenerator, animFAmt, animWidth));\r\n\t\tsprites.emplace(OwnedClxSpriteListOrSheet { std::move(spriteSheet) });\r\n\t}\r\n#endif\r\n\treturn {};\r\n}\r\n\r\nMissileFileData &GetMissileSpriteData(MissileGraphicID graphicId)\r\n{\r\n\treturn MissileSpriteData[static_cast<std::underlying_type_t<MissileGraphicID>>(graphicId)];\r\n}\r\n\r\nvoid LoadMissileData()\r\n{\r\n\tLoadMissileSpriteData();\r\n\tLoadMisdat();\r\n}\r\n\r\nconst MissileData &GetMissileData(MissileID missileId)\r\n{\r\n\treturn MissilesData[static_cast<std::underlying_type_t<MissileID>>(missileId)];\r\n}\r\n\r\ntl::expected<void, std::string> InitMissileGFX()\r\n{\r\n\tif (HeadlessMode)\r\n\t\treturn {};\r\n\r\n\tfor (MissileFileData &missileSprite : MissileSpriteData) {\r\n\t\tif (missileSprite.flags == MissileGraphicsFlags::MonsterOwned)\r\n\t\t\tcontinue;\r\n\t\tRETURN_IF_ERROR(missileSprite.LoadGFX());\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nvoid FreeMissileGFX()\r\n{\r\n\tfor (MissileFileData &missileData : MissileSpriteData) {\r\n\t\tmissileData.FreeGFX();\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/misdat.h",
    "content": "/**\r\n * @file misdat.h\r\n *\r\n * Interface of data related to missiles.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <string>\r\n#include <type_traits>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"effects.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"tables/spelldat.h\"\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum mienemy_type : uint8_t {\r\n\tTARGET_MONSTERS,\r\n\tTARGET_PLAYERS,\r\n\tTARGET_BOTH,\r\n};\r\n\r\nenum class DamageType : uint8_t {\r\n\tPhysical,\r\n\tFire,\r\n\tLightning,\r\n\tMagic,\r\n\tAcid,\r\n};\r\n\r\nenum class MissileGraphicID : uint8_t {\r\n\tArrow,\r\n\tFireball,\r\n\tGuardian,\r\n\tLightning,\r\n\tFireWall,\r\n\tMagmaBallExplosion,\r\n\tTownPortal,\r\n\tFlashBottom,\r\n\tFlashTop,\r\n\tManaShield,\r\n\tBloodHit,\r\n\tBoneHit,\r\n\tMetalHit,\r\n\tFireArrow,\r\n\tDoomSerpents,\r\n\tGolem,\r\n\tSpurt,\r\n\tApocalypseBoom,\r\n\tStoneCurseShatter,\r\n\tBigExplosion,\r\n\tInferno,\r\n\tThinLightning,\r\n\tBloodStar,\r\n\tBloodStarExplosion,\r\n\tMagmaBall,\r\n\tKrull,\r\n\tChargedBolt,\r\n\tHolyBolt,\r\n\tHolyBoltExplosion,\r\n\tLightningArrow,\r\n\tFireArrowExplosion,\r\n\tAcid,\r\n\tAcidSplat,\r\n\tAcidPuddle,\r\n\tEtherealize,\r\n\tElemental,\r\n\tResurrect,\r\n\tBoneSpirit,\r\n\tRedPortal,\r\n\tDiabloApocalypseBoom,\r\n\tBloodStarBlue,\r\n\tBloodStarBlueExplosion,\r\n\tBloodStarYellow,\r\n\tBloodStarYellowExplosion,\r\n\tBloodStarRed,\r\n\tBloodStarRedExplosion,\r\n\tHorkSpawn,\r\n\tReflect,\r\n\tOrangeFlare,\r\n\tBlueFlare,\r\n\tRedFlare,\r\n\tYellowFlare,\r\n\tRune,\r\n\tYellowFlareExplosion,\r\n\tBlueFlareExplosion,\r\n\tRedFlareExplosion,\r\n\tBlueFlare2,\r\n\tOrangeFlareExplosion,\r\n\tBlueFlareExplosion2,\r\n\tNone,\r\n};\r\n\r\n/**\r\n * @brief Specifies what if and how movement distribution is applied\r\n */\r\nenum class MissileMovementDistribution : uint8_t {\r\n\t/**\r\n\t * @brief No movement distribution is calculated. Normally this means the missile doesn't move at all.\r\n\t */\r\n\tDisabled,\r\n\t/**\r\n\t * @brief The missile moves and if it hits an enemy it stops (for example firebolt)\r\n\t */\r\n\tBlockable,\r\n\t/**\r\n\t * @brief The missile moves and even it hits an enemy it keeps moving (for example flame wave)\r\n\t */\r\n\tUnblockable,\r\n};\r\n\r\nstruct Missile;\r\nstruct AddMissileParameter;\r\n\r\nenum class MissileDataFlags : uint8_t {\r\n\t// The lower 3 bytes are used to store DamageType.\r\n\tPhysical = static_cast<uint8_t>(DamageType::Physical),\r\n\tFire = static_cast<uint8_t>(DamageType::Fire),\r\n\tLightning = static_cast<uint8_t>(DamageType::Lightning),\r\n\tMagic = static_cast<uint8_t>(DamageType::Magic),\r\n\tAcid = static_cast<uint8_t>(DamageType::Acid),\r\n\tArrow = 1 << 4,\r\n\tInvisible = 1 << 5,\r\n};\r\nuse_enum_as_flags(MissileDataFlags);\r\n\r\n/**\r\n * Represent a more fine-grained direction than the 8 value Direction enum.\r\n *\r\n * This is used when rendering projectiles like arrows which have additional sprites for \"half-winds\" on a 16-point compass.\r\n * The sprite sheets are typically 0-indexed and use the following layout (relative to the screen projection)\r\n *\r\n *      W  WSW   SW  SSW  S\r\n *               ^\r\n *     WNW       |       SSE\r\n *               |\r\n *     NW -------+------> SE\r\n *               |\r\n *     NNW       |       ESE\r\n *               |\r\n *      N  NNE   NE  ENE  E\r\n */\r\nenum class Direction16 : uint8_t {\r\n\tSouth,\r\n\tSouth_SouthWest,\r\n\tSouthWest,\r\n\tWest_SouthWest,\r\n\tWest,\r\n\tWest_NorthWest,\r\n\tNorthWest,\r\n\tNorth_NorthWest,\r\n\tNorth,\r\n\tNorth_NorthEast,\r\n\tNorthEast,\r\n\tEast_NorthEast,\r\n\tEast,\r\n\tEast_SouthEast,\r\n\tSouthEast,\r\n\tSouth_SouthEast,\r\n};\r\n\r\nstruct MissileData {\r\n\tusing AddFn = void (*)(Missile &, AddMissileParameter &);\r\n\tusing ProcessFn = void (*)(Missile &);\r\n\r\n\tAddFn addFn;\r\n\tProcessFn processFn;\r\n\r\n\t/**\r\n\t * @brief Sound emitted when cast.\r\n\t */\r\n\tSfxID castSound;\r\n\t/**\r\n\t * @brief Sound emitted on impact.\r\n\t */\r\n\tSfxID hitSound;\r\n\tMissileGraphicID graphic;\r\n\tMissileDataFlags flags;\r\n\tMissileMovementDistribution movementDistribution;\r\n\r\n\t[[nodiscard]] bool isDrawn() const\r\n\t{\r\n\t\treturn !HasAnyOf(flags, MissileDataFlags::Invisible);\r\n\t}\r\n\r\n\t[[nodiscard]] bool isArrow() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, MissileDataFlags::Arrow);\r\n\t}\r\n\r\n\t[[nodiscard]] DamageType damageType() const\r\n\t{\r\n\t\treturn static_cast<DamageType>(static_cast<std::underlying_type<MissileDataFlags>::type>(flags) & 0b111U);\r\n\t}\r\n};\r\n\r\nenum class MissileGraphicsFlags : uint8_t {\r\n\t// clang-format off\r\n\tNone         = 0,\r\n\tMonsterOwned = 1 << 0,\r\n\tNotAnimated  = 1 << 1,\r\n\t// clang-format on\r\n};\r\n\r\nstruct MissileFileData {\r\n\tOptionalOwnedClxSpriteListOrSheet sprites;\r\n\tuint16_t animWidth;\r\n\tint8_t animWidth2;\r\n\tstd::string name;\r\n\tuint8_t animFAmt;\r\n\tMissileGraphicsFlags flags;\r\n\tuint8_t animDelayIdx;\r\n\tuint8_t animLenIdx;\r\n\r\n\t[[nodiscard]] uint8_t animDelay(uint8_t dir) const;\r\n\t[[nodiscard]] uint8_t animLen(uint8_t dir) const;\r\n\r\n\ttl::expected<void, std::string> LoadGFX();\r\n\r\n\tvoid FreeGFX()\r\n\t{\r\n\t\tsprites = std::nullopt;\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Returns the sprite list for a given direction.\r\n\t *\r\n\t * @param direction One of the 16 directions. Valid range: [0, 15].\r\n\t * @return OptionalClxSpriteList\r\n\t */\r\n\t[[nodiscard]] OptionalClxSpriteList spritesForDirection(Direction16 direction) const\r\n\t{\r\n\t\tif (!sprites)\r\n\t\t\treturn std::nullopt;\r\n\t\treturn sprites->isSheet() ? sprites->sheet()[static_cast<size_t>(direction)] : sprites->list();\r\n\t}\r\n};\r\n\r\nconst MissileData &GetMissileData(MissileID missileId);\r\nMissileFileData &GetMissileSpriteData(MissileGraphicID graphicId);\r\n\r\nvoid LoadMissileData();\r\n\r\ntl::expected<void, std::string> InitMissileGFX();\r\nvoid FreeMissileGFX();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/monstdat.cpp",
    "content": "/**\r\n * @file monstdat.cpp\r\n *\r\n * Implementation of all monster data.\r\n */\r\n#include \"tables/monstdat.h\"\r\n\r\n#include <algorithm>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n#include <fmt/core.h>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"appfat.h\"\r\n#include \"cursor.h\"\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n#include \"items.h\"\r\n#include \"lua/lua_event.hpp\"\r\n#include \"monster.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n// Returns a `treasure` value for the given item.\r\nconstexpr uint16_t Uniq(_unique_items item)\r\n{\r\n\treturn static_cast<uint16_t>(T_UNIQ) + item;\r\n}\r\n\r\nstd::vector<std::string> MonsterSpritePaths;\r\n\r\n} // namespace\r\n\r\nconst char *MonsterData::spritePath() const\r\n{\r\n\treturn MonsterSpritePaths[static_cast<size_t>(spriteId)].c_str();\r\n}\r\n\r\n/** Contains the data related to each monster ID. */\r\nstd::vector<MonsterData> MonstersData;\r\n\r\n/** Contains the data related to each unique monster ID. */\r\nstd::vector<UniqueMonsterData> UniqueMonstersData;\r\n\r\n/**\r\n * Map between .DUN file value and monster type enum\r\n */\r\nconst _monster_id MonstConvTbl[] = {\r\n\tMT_NZOMBIE,\r\n\tMT_BZOMBIE,\r\n\tMT_GZOMBIE,\r\n\tMT_YZOMBIE,\r\n\tMT_RFALLSP,\r\n\tMT_DFALLSP,\r\n\tMT_YFALLSP,\r\n\tMT_BFALLSP,\r\n\tMT_WSKELAX,\r\n\tMT_TSKELAX,\r\n\tMT_RSKELAX,\r\n\tMT_XSKELAX,\r\n\tMT_RFALLSD,\r\n\tMT_DFALLSD,\r\n\tMT_YFALLSD,\r\n\tMT_BFALLSD,\r\n\tMT_NSCAV,\r\n\tMT_BSCAV,\r\n\tMT_WSCAV,\r\n\tMT_YSCAV,\r\n\tMT_WSKELBW,\r\n\tMT_TSKELBW,\r\n\tMT_RSKELBW,\r\n\tMT_XSKELBW,\r\n\tMT_WSKELSD,\r\n\tMT_TSKELSD,\r\n\tMT_RSKELSD,\r\n\tMT_XSKELSD,\r\n\tMT_SNEAK,\r\n\tMT_STALKER,\r\n\tMT_UNSEEN,\r\n\tMT_ILLWEAV,\r\n\tMT_NGOATMC,\r\n\tMT_BGOATMC,\r\n\tMT_RGOATMC,\r\n\tMT_GGOATMC,\r\n\tMT_FIEND,\r\n\tMT_GLOOM,\r\n\tMT_BLINK,\r\n\tMT_FAMILIAR,\r\n\tMT_NGOATBW,\r\n\tMT_BGOATBW,\r\n\tMT_RGOATBW,\r\n\tMT_GGOATBW,\r\n\tMT_NACID,\r\n\tMT_RACID,\r\n\tMT_BACID,\r\n\tMT_XACID,\r\n\tMT_SKING,\r\n\tMT_FAT,\r\n\tMT_MUDMAN,\r\n\tMT_TOAD,\r\n\tMT_FLAYED,\r\n\tMT_WYRM,\r\n\tMT_CAVSLUG,\r\n\tMT_DEVOUR,\r\n\tMT_DVLWYRM,\r\n\tMT_NMAGMA,\r\n\tMT_YMAGMA,\r\n\tMT_BMAGMA,\r\n\tMT_WMAGMA,\r\n\tMT_HORNED,\r\n\tMT_MUDRUN,\r\n\tMT_FROSTC,\r\n\tMT_OBLORD,\r\n\tMT_BONEDMN,\r\n\tMT_REDDTH,\r\n\tMT_LTCHDMN,\r\n\tMT_UDEDBLRG,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INCIN,\r\n\tMT_FLAMLRD,\r\n\tMT_DOOMFIRE,\r\n\tMT_HELLBURN,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_RSTORM,\r\n\tMT_STORM,\r\n\tMT_STORML,\r\n\tMT_MAEL,\r\n\tMT_WINGED,\r\n\tMT_GARGOYLE,\r\n\tMT_BLOODCLW,\r\n\tMT_DEATHW,\r\n\tMT_MEGA,\r\n\tMT_GUARD,\r\n\tMT_VTEXLRD,\r\n\tMT_BALROG,\r\n\tMT_NSNAKE,\r\n\tMT_RSNAKE,\r\n\tMT_GSNAKE,\r\n\tMT_BSNAKE,\r\n\tMT_NBLACK,\r\n\tMT_RTBLACK,\r\n\tMT_BTBLACK,\r\n\tMT_RBLACK,\r\n\tMT_UNRAV,\r\n\tMT_HOLOWONE,\r\n\tMT_PAINMSTR,\r\n\tMT_REALWEAV,\r\n\tMT_SUCCUBUS,\r\n\tMT_SNOWWICH,\r\n\tMT_HLSPWN,\r\n\tMT_SOLBRNR,\r\n\tMT_COUNSLR,\r\n\tMT_MAGISTR,\r\n\tMT_CABALIST,\r\n\tMT_ADVOCATE,\r\n\tMT_INVALID,\r\n\tMT_DIABLO,\r\n\tMT_INVALID,\r\n\tMT_GOLEM,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INVALID, // Monster from blood1.dun and blood2.dun\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_INVALID, // Snotspill from banner2.dun\r\n\tMT_INVALID,\r\n\tMT_INVALID,\r\n\tMT_BIGFALL,\r\n\tMT_DARKMAGE,\r\n\tMT_HELLBOAR,\r\n\tMT_STINGER,\r\n\tMT_PSYCHORB,\r\n\tMT_ARACHNON,\r\n\tMT_FELLTWIN,\r\n\tMT_HORKSPWN,\r\n\tMT_VENMTAIL,\r\n\tMT_NECRMORB,\r\n\tMT_SPIDLORD,\r\n\tMT_LASHWORM,\r\n\tMT_TORCHANT,\r\n\tMT_HORKDMN,\r\n\tMT_DEFILER,\r\n\tMT_GRAVEDIG,\r\n\tMT_TOMBRAT,\r\n\tMT_FIREBAT,\r\n\tMT_SKLWING,\r\n\tMT_LICH,\r\n\tMT_CRYPTDMN,\r\n\tMT_HELLBAT,\r\n\tMT_BONEDEMN,\r\n\tMT_LICH,\r\n\tMT_BICLOPS,\r\n\tMT_FLESTHNG,\r\n\tMT_REAPER,\r\n\tMT_NAKRUL,\r\n\tMT_CLEAVER,\r\n\tMT_INVILORD,\r\n\tMT_LRDSAYTR,\r\n};\r\n\r\nnamespace {\r\n\r\n/** Contains the mapping between monster ID strings and indices, used for parsing additional monster data. */\r\nankerl::unordered_dense::map<std::string, int16_t> AdditionalMonsterIdStringsToIndices;\r\n\r\ntl::expected<_monster_id, std::string> ParseMonsterId(std::string_view value)\r\n{\r\n\tconst std::optional<_monster_id> enumValueOpt = magic_enum::enum_cast<_monster_id>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\tconst auto findIt = AdditionalMonsterIdStringsToIndices.find(std::string(value));\r\n\tif (findIt != AdditionalMonsterIdStringsToIndices.end()) {\r\n\t\treturn static_cast<_monster_id>(findIt->second);\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<MonsterAvailability, std::string> ParseMonsterAvailability(std::string_view value)\r\n{\r\n\tif (value == \"Always\") return MonsterAvailability::Always;\r\n\tif (value == \"Never\") return MonsterAvailability::Never;\r\n\tif (value == \"Retail\") return MonsterAvailability::Retail;\r\n\treturn tl::make_unexpected(\"Expected one of: Always, Never, or Retail\");\r\n}\r\n\r\ntl::expected<MonsterAIID, std::string> ParseAiId(std::string_view value)\r\n{\r\n\tconst std::optional<MonsterAIID> enumValueOpt = magic_enum::enum_cast<MonsterAIID>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<monster_flag, std::string> ParseMonsterFlag(std::string_view value)\r\n{\r\n\tif (value == \"HIDDEN\") return MFLAG_HIDDEN;\r\n\tif (value == \"LOCK_ANIMATION\") return MFLAG_LOCK_ANIMATION;\r\n\tif (value == \"ALLOW_SPECIAL\") return MFLAG_ALLOW_SPECIAL;\r\n\tif (value == \"TARGETS_MONSTER\") return MFLAG_TARGETS_MONSTER;\r\n\tif (value == \"GOLEM\") return MFLAG_GOLEM;\r\n\tif (value == \"QUEST_COMPLETE\") return MFLAG_QUEST_COMPLETE;\r\n\tif (value == \"KNOCKBACK\") return MFLAG_KNOCKBACK;\r\n\tif (value == \"SEARCH\") return MFLAG_SEARCH;\r\n\tif (value == \"CAN_OPEN_DOOR\") return MFLAG_CAN_OPEN_DOOR;\r\n\tif (value == \"NO_ENEMY\") return MFLAG_NO_ENEMY;\r\n\tif (value == \"BERSERK\") return MFLAG_BERSERK;\r\n\tif (value == \"NOLIFESTEAL\") return MFLAG_NOLIFESTEAL;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<MonsterClass, std::string> ParseMonsterClass(std::string_view value)\r\n{\r\n\tconst std::optional<MonsterClass> enumValueOpt = magic_enum::enum_cast<MonsterClass>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<monster_resistance, std::string> ParseMonsterResistance(std::string_view value)\r\n{\r\n\tconst std::optional<monster_resistance> enumValueOpt = magic_enum::enum_cast<monster_resistance>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<SelectionRegion, std::string> ParseSelectionRegion(std::string_view value)\r\n{\r\n\tif (value.empty()) return SelectionRegion::None;\r\n\tif (value == \"Bottom\") return SelectionRegion::Bottom;\r\n\tif (value == \"Middle\") return SelectionRegion::Middle;\r\n\tif (value == \"Top\") return SelectionRegion::Top;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<uint16_t, std::string> ParseMonsterTreasure(std::string_view value)\r\n{\r\n\t// TODO: Replace this hack with proper parsing.\r\n\r\n\tif (value.empty()) return 0;\r\n\tif (value == \"None\") return T_NODROP;\r\n\tif (value == \"Uniq(SKCROWN)\") return Uniq(UITEM_SKCROWN);\r\n\tif (value == \"Uniq(CLEAVER)\") return Uniq(UITEM_CLEAVER);\r\n\treturn tl::make_unexpected(\"Invalid value. NOTE: Parser is incomplete\");\r\n}\r\n\r\ntl::expected<UniqueMonsterPack, std::string> ParseUniqueMonsterPack(std::string_view value)\r\n{\r\n\tconst std::optional<UniqueMonsterPack> enumValueOpt = magic_enum::enum_cast<UniqueMonsterPack>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadMonstDatFromFile(DataFile &dataFile, const std::string_view filename, bool grow)\r\n{\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tif (grow) {\r\n\t\tMonstersData.reserve(MonstersData.size() + dataFile.numRecords());\r\n\t}\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tif (MonstersData.size() >= static_cast<size_t>(NUM_MAX_MTYPES)) {\r\n\t\t\tDisplayFatalErrorAndExit(_(\"Loading Monster Data Failed\"), fmt::format(fmt::runtime(_(\"Could not add a monster, since the maximum monster type number of {} has already been reached.\")), static_cast<size_t>(NUM_MAX_MTYPES)));\r\n\t\t}\r\n\r\n\t\tRecordReader reader { record, filename };\r\n\r\n\t\tstd::string monsterId;\r\n\t\treader.readString(\"_monster_id\", monsterId);\r\n\t\tconst std::optional<_monster_id> monsterIdEnumValueOpt = magic_enum::enum_cast<_monster_id>(monsterId);\r\n\r\n\t\tif (!monsterIdEnumValueOpt.has_value()) {\r\n\t\t\tconst size_t monsterIndex = MonstersData.size();\r\n\t\t\tconst auto [it, inserted] = AdditionalMonsterIdStringsToIndices.emplace(monsterId, static_cast<int16_t>(monsterIndex));\r\n\t\t\tif (!inserted) {\r\n\t\t\t\tDisplayFatalErrorAndExit(_(\"Loading Monster Data Failed\"), fmt::format(fmt::runtime(_(\"A monster type already exists for ID \\\"{}\\\".\")), monsterId));\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// for hardcoded monsters, use their predetermined slot; for non-hardcoded ones, use the slots after that\r\n\t\tMonsterData &monster = monsterIdEnumValueOpt.has_value() ? MonstersData[monsterIdEnumValueOpt.value()] : MonstersData.emplace_back();\r\n\r\n\t\treader.readString(\"name\", monster.name);\r\n\t\t{\r\n\t\t\tstd::string assetsSuffix;\r\n\t\t\treader.readString(\"assetsSuffix\", assetsSuffix);\r\n\t\t\tconst auto findIt = std::find(MonsterSpritePaths.begin(), MonsterSpritePaths.end(), assetsSuffix);\r\n\t\t\tif (findIt != MonsterSpritePaths.end()) {\r\n\t\t\t\tmonster.spriteId = static_cast<uint16_t>(findIt - MonsterSpritePaths.begin());\r\n\t\t\t} else {\r\n\t\t\t\tmonster.spriteId = static_cast<uint16_t>(MonsterSpritePaths.size());\r\n\t\t\t\tMonsterSpritePaths.push_back(std::string(assetsSuffix));\r\n\t\t\t}\r\n\t\t}\r\n\t\treader.readString(\"soundSuffix\", monster.soundSuffix);\r\n\t\treader.readString(\"trnFile\", monster.trnFile);\r\n\t\treader.read(\"availability\", monster.availability, ParseMonsterAvailability);\r\n\t\treader.readInt(\"width\", monster.width);\r\n\t\treader.readInt(\"image\", monster.image);\r\n\t\treader.readBool(\"hasSpecial\", monster.hasSpecial);\r\n\t\treader.readBool(\"hasSpecialSound\", monster.hasSpecialSound);\r\n\t\treader.readIntArray(\"frames\", monster.frames);\r\n\t\treader.readIntArray(\"rate\", monster.rate);\r\n\t\treader.readInt(\"minDunLvl\", monster.minDunLvl);\r\n\t\treader.readInt(\"maxDunLvl\", monster.maxDunLvl);\r\n\t\treader.readInt(\"level\", monster.level);\r\n\t\treader.readInt(\"hitPointsMinimum\", monster.hitPointsMinimum);\r\n\t\treader.readInt(\"hitPointsMaximum\", monster.hitPointsMaximum);\r\n\t\treader.read(\"ai\", monster.ai, ParseAiId);\r\n\t\treader.readEnumList(\"abilityFlags\", monster.abilityFlags, ParseMonsterFlag);\r\n\t\treader.readInt(\"intelligence\", monster.intelligence);\r\n\t\treader.readInt(\"toHit\", monster.toHit);\r\n\t\treader.readInt(\"animFrameNum\", monster.animFrameNum);\r\n\t\treader.readInt(\"minDamage\", monster.minDamage);\r\n\t\treader.readInt(\"maxDamage\", monster.maxDamage);\r\n\t\treader.readInt(\"toHitSpecial\", monster.toHitSpecial);\r\n\t\treader.readInt(\"animFrameNumSpecial\", monster.animFrameNumSpecial);\r\n\t\treader.readInt(\"minDamageSpecial\", monster.minDamageSpecial);\r\n\t\treader.readInt(\"maxDamageSpecial\", monster.maxDamageSpecial);\r\n\t\treader.readInt(\"reducePlayerStrength\", monster.reducePlayerStrength);\r\n\t\treader.readInt(\"reducePlayerMagic\", monster.reducePlayerMagic);\r\n\t\treader.readInt(\"reducePlayerDexterity\", monster.reducePlayerDexterity);\r\n\t\treader.readInt(\"reducePlayerVitality\", monster.reducePlayerVitality);\r\n\t\treader.readInt(\"reducePlayerMaxHP\", monster.reducePlayerMaxHP);\r\n\t\treader.readInt(\"reducePlayerMaxMana\", monster.reducePlayerMaxMana);\r\n\t\treader.readInt(\"armorClass\", monster.armorClass);\r\n\t\treader.read(\"monsterClass\", monster.monsterClass, ParseMonsterClass);\r\n\t\treader.readEnumList(\"resistance\", monster.resistance, ParseMonsterResistance);\r\n\t\treader.readEnumList(\"resistanceHell\", monster.resistanceHell, ParseMonsterResistance);\r\n\t\treader.readEnumList(\"selectionRegion\", monster.selectionRegion, ParseSelectionRegion);\r\n\t\treader.read(\"treasure\", monster.treasure, ParseMonsterTreasure);\r\n\r\n\t\treader.readInt(\"exp\", monster.exp);\r\n\t}\r\n}\r\n\r\nnamespace {\r\n\r\nvoid LoadMonstDat()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\monsters\\\\monstdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tMonstersData.clear();\r\n\tAdditionalMonsterIdStringsToIndices.clear();\r\n\tMonstersData.resize(NUM_DEFAULT_MTYPES); // ensure the hardcoded monster type slots are filled\r\n\tLoadMonstDatFromFile(dataFile, filename, false);\r\n\r\n\tlua::MonsterDataLoaded();\r\n\r\n\tMonstersData.shrink_to_fit();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadUniqueMonstDatFromFile(DataFile &dataFile, std::string_view filename)\r\n{\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tUniqueMonstersData.reserve(UniqueMonstersData.size() + dataFile.numRecords());\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tUniqueMonsterData &monster = UniqueMonstersData.emplace_back();\r\n\t\treader.read(\"type\", monster.mtype, ParseMonsterId);\r\n\t\treader.readString(\"name\", monster.mName);\r\n\t\treader.readString(\"trn\", monster.mTrnName);\r\n\t\treader.readInt(\"level\", monster.mlevel);\r\n\t\treader.readInt(\"maxHp\", monster.mmaxhp);\r\n\t\treader.read(\"ai\", monster.mAi, ParseAiId);\r\n\t\treader.readInt(\"intelligence\", monster.mint);\r\n\t\treader.readInt(\"minDamage\", monster.mMinDamage);\r\n\t\treader.readInt(\"maxDamage\", monster.mMaxDamage);\r\n\t\treader.readInt(\"reducePlayerStrength\", monster.reducePlayerStrength);\r\n\t\treader.readInt(\"reducePlayerMagic\", monster.reducePlayerMagic);\r\n\t\treader.readInt(\"reducePlayerDexterity\", monster.reducePlayerDexterity);\r\n\t\treader.readInt(\"reducePlayerVitality\", monster.reducePlayerVitality);\r\n\t\treader.readInt(\"reducePlayerMaxHP\", monster.reducePlayerMaxHP);\r\n\t\treader.readInt(\"reducePlayerMaxMana\", monster.reducePlayerMaxMana);\r\n\t\treader.readEnumList(\"resistance\", monster.mMagicRes, ParseMonsterResistance);\r\n\t\treader.read(\"monsterPack\", monster.monsterPack, ParseUniqueMonsterPack);\r\n\t\treader.readInt(\"customToHit\", monster.customToHit);\r\n\t\treader.readInt(\"customArmorClass\", monster.customArmorClass);\r\n\t\treader.read(\"talkMessage\", monster.mtalkmsg, ParseSpeechId);\r\n\t}\r\n}\r\n\r\nnamespace {\r\n\r\nvoid LoadUniqueMonstDat()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\monsters\\\\unique_monstdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\r\n\tUniqueMonstersData.clear();\r\n\tLoadUniqueMonstDatFromFile(dataFile, filename);\r\n\r\n\tlua::UniqueMonsterDataLoaded();\r\n\r\n\tUniqueMonstersData.shrink_to_fit();\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadMonsterData()\r\n{\r\n\tLoadMonstDat();\r\n\tLoadUniqueMonstDat();\r\n}\r\n\r\nsize_t GetNumMonsterSprites()\r\n{\r\n\treturn MonsterSpritePaths.size();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/monstdat.h",
    "content": "/**\r\n * @file monstdat.h\r\n *\r\n * Interface of all monster data.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <string>\r\n#include <vector>\r\n\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"cursor.h\"\r\n#include \"tables/textdat.h\"\r\n\r\nnamespace devilution {\r\n\r\nclass DataFile;\r\n\r\nenum class MonsterAIID : int8_t {\r\n\tZombie,\r\n\tFat,\r\n\tSkeletonMelee,\r\n\tSkeletonRanged,\r\n\tScavenger,\r\n\tRhino,\r\n\tGoatMelee,\r\n\tGoatRanged,\r\n\tFallen,\r\n\tMagma,\r\n\tSkeletonKing,\r\n\tBat,\r\n\tGargoyle,\r\n\tButcher,\r\n\tSuccubus,\r\n\tSneak,\r\n\tStorm,\r\n\tFireMan,\r\n\tGharbad,\r\n\tAcid,\r\n\tAcidUnique,\r\n\tGolem,\r\n\tZhar,\r\n\tSnotspill,\r\n\tSnake,\r\n\tCounselor,\r\n\tMega,\r\n\tDiablo,\r\n\tLazarus,\r\n\tLazarusSuccubus,\r\n\tLachdanan,\r\n\tWarlord,\r\n\tFireBat,\r\n\tTorchant,\r\n\tHorkDemon,\r\n\tLich,\r\n\tArchLich,\r\n\tPsychorb,\r\n\tNecromorb,\r\n\tBoneDemon,\r\n\tInvalid = -1,\r\n};\r\n\r\nenum class MonsterClass : uint8_t {\r\n\tUndead,\r\n\tDemon,\r\n\tAnimal,\r\n};\r\n\r\nenum monster_resistance : uint8_t {\r\n\t// clang-format off\r\n\tRESIST_MAGIC     = 1 << 0,\r\n\tRESIST_FIRE      = 1 << 1,\r\n\tRESIST_LIGHTNING = 1 << 2,\r\n\tIMMUNE_MAGIC     = 1 << 3,\r\n\tIMMUNE_FIRE      = 1 << 4,\r\n\tIMMUNE_LIGHTNING = 1 << 5,\r\n\tIMMUNE_ACID      = 1 << 7,\r\n\t// clang-format on\r\n};\r\n\r\nenum monster_treasure : uint16_t {\r\n\t// clang-format off\r\n\tT_MASK    = 0xFFF,\r\n\tT_NODROP = 0x4000, // monster doesn't drop any loot\r\n\tT_UNIQ    = 0x8000, // use combined with unique item's ID - for example butcher's cleaver = T_UNIQ+UITEM_CLEAVE\r\n\t// clang-format on\r\n};\r\n\r\nenum class MonsterAvailability : uint8_t {\r\n\tNever,\r\n\tAlways,\r\n\tRetail,\r\n};\r\n\r\nstruct MonsterData {\r\n\tstd::string name;\r\n\tstd::string soundSuffix;\r\n\tstd::string trnFile;\r\n\tuint16_t spriteId = 0;\r\n\tMonsterAvailability availability = MonsterAvailability::Never;\r\n\tuint16_t width = 0;\r\n\tuint16_t image = 0;\r\n\tbool hasSpecial = false;\r\n\tbool hasSpecialSound = false;\r\n\tint8_t frames[6] {};\r\n\tint8_t rate[6] {};\r\n\tint8_t minDunLvl = 0;\r\n\tint8_t maxDunLvl = 0;\r\n\tint8_t level = 0;\r\n\tuint16_t hitPointsMinimum = 0;\r\n\tuint16_t hitPointsMaximum = 0;\r\n\tMonsterAIID ai = MonsterAIID::Invalid;\r\n\t/**\r\n\t * @brief Denotes monster's abilities defined in @p monster_flag as bitflags\r\n\t * For usage, see @p MonstersData in monstdat.cpp\r\n\t */\r\n\tuint16_t abilityFlags = 0;\r\n\tuint8_t intelligence = 0;\r\n\tuint8_t toHit = 0;\r\n\tint8_t animFrameNum = 0;\r\n\tuint8_t minDamage = 0;\r\n\tuint8_t maxDamage = 0;\r\n\tuint8_t toHitSpecial = 0;\r\n\tint8_t animFrameNumSpecial = 0;\r\n\tuint8_t minDamageSpecial = 0;\r\n\tuint8_t maxDamageSpecial = 0;\r\n\tuint8_t reducePlayerStrength = 0;\r\n\tuint8_t reducePlayerMagic = 0;\r\n\tuint8_t reducePlayerDexterity = 0;\r\n\tuint8_t reducePlayerVitality = 0;\r\n\tuint8_t reducePlayerMaxHP = 0;\r\n\tuint8_t reducePlayerMaxMana = 0;\r\n\tuint8_t armorClass = 0;\r\n\tMonsterClass monsterClass {};\r\n\t/** Using monster_resistance as bitflags */\r\n\tuint8_t resistance = 0;\r\n\t/** Using monster_resistance as bitflags */\r\n\tuint8_t resistanceHell = 0;\r\n\tSelectionRegion selectionRegion = SelectionRegion::None;\r\n\t/** Using monster_treasure */\r\n\tuint16_t treasure = 0;\r\n\tuint16_t exp = 0;\r\n\r\n\t[[nodiscard]] const char *spritePath() const;\r\n\r\n\t[[nodiscard]] const char *soundPath() const\r\n\t{\r\n\t\treturn !soundSuffix.empty() ? soundSuffix.c_str() : spritePath();\r\n\t}\r\n\r\n\t[[nodiscard]] bool hasAnim(size_t index) const\r\n\t{\r\n\t\treturn frames[index] != 0;\r\n\t}\r\n};\r\n\r\nenum _monster_id : int16_t {\r\n\tMT_NZOMBIE,\r\n\tMT_BZOMBIE,\r\n\tMT_GZOMBIE,\r\n\tMT_YZOMBIE,\r\n\tMT_RFALLSP,\r\n\tMT_DFALLSP,\r\n\tMT_YFALLSP,\r\n\tMT_BFALLSP,\r\n\tMT_WSKELAX,\r\n\tMT_TSKELAX,\r\n\tMT_RSKELAX,\r\n\tMT_XSKELAX,\r\n\tMT_RFALLSD,\r\n\tMT_DFALLSD,\r\n\tMT_YFALLSD,\r\n\tMT_BFALLSD,\r\n\tMT_NSCAV,\r\n\tMT_BSCAV,\r\n\tMT_WSCAV,\r\n\tMT_YSCAV,\r\n\tMT_WSKELBW,\r\n\tMT_TSKELBW,\r\n\tMT_RSKELBW,\r\n\tMT_XSKELBW,\r\n\tMT_WSKELSD,\r\n\tMT_TSKELSD,\r\n\tMT_RSKELSD,\r\n\tMT_XSKELSD,\r\n\tMT_INVILORD,\r\n\tMT_SNEAK,\r\n\tMT_STALKER,\r\n\tMT_UNSEEN,\r\n\tMT_ILLWEAV,\r\n\tMT_LRDSAYTR,\r\n\tMT_NGOATMC,\r\n\tMT_BGOATMC,\r\n\tMT_RGOATMC,\r\n\tMT_GGOATMC,\r\n\tMT_FIEND,\r\n\tMT_BLINK,\r\n\tMT_GLOOM,\r\n\tMT_FAMILIAR,\r\n\tMT_NGOATBW,\r\n\tMT_BGOATBW,\r\n\tMT_RGOATBW,\r\n\tMT_GGOATBW,\r\n\tMT_NACID,\r\n\tMT_RACID,\r\n\tMT_BACID,\r\n\tMT_XACID,\r\n\tMT_SKING,\r\n\tMT_CLEAVER,\r\n\tMT_FAT,\r\n\tMT_MUDMAN,\r\n\tMT_TOAD,\r\n\tMT_FLAYED,\r\n\tMT_WYRM,\r\n\tMT_CAVSLUG,\r\n\tMT_DVLWYRM,\r\n\tMT_DEVOUR,\r\n\tMT_NMAGMA,\r\n\tMT_YMAGMA,\r\n\tMT_BMAGMA,\r\n\tMT_WMAGMA,\r\n\tMT_HORNED,\r\n\tMT_MUDRUN,\r\n\tMT_FROSTC,\r\n\tMT_OBLORD,\r\n\tMT_BONEDMN,\r\n\tMT_REDDTH,\r\n\tMT_LTCHDMN,\r\n\tMT_UDEDBLRG,\r\n\tMT_INCIN,\r\n\tMT_FLAMLRD,\r\n\tMT_DOOMFIRE,\r\n\tMT_HELLBURN,\r\n\tMT_STORM,\r\n\tMT_RSTORM,\r\n\tMT_STORML,\r\n\tMT_MAEL,\r\n\tMT_BIGFALL,\r\n\tMT_WINGED,\r\n\tMT_GARGOYLE,\r\n\tMT_BLOODCLW,\r\n\tMT_DEATHW,\r\n\tMT_MEGA,\r\n\tMT_GUARD,\r\n\tMT_VTEXLRD,\r\n\tMT_BALROG,\r\n\tMT_NSNAKE,\r\n\tMT_RSNAKE,\r\n\tMT_BSNAKE,\r\n\tMT_GSNAKE,\r\n\tMT_NBLACK,\r\n\tMT_RTBLACK,\r\n\tMT_BTBLACK,\r\n\tMT_RBLACK,\r\n\tMT_UNRAV,\r\n\tMT_HOLOWONE,\r\n\tMT_PAINMSTR,\r\n\tMT_REALWEAV,\r\n\tMT_SUCCUBUS,\r\n\tMT_SNOWWICH,\r\n\tMT_HLSPWN,\r\n\tMT_SOLBRNR,\r\n\tMT_COUNSLR,\r\n\tMT_MAGISTR,\r\n\tMT_CABALIST,\r\n\tMT_ADVOCATE,\r\n\tMT_GOLEM,\r\n\tMT_DIABLO,\r\n\tMT_DARKMAGE,\r\n\tMT_HELLBOAR,\r\n\tMT_STINGER,\r\n\tMT_PSYCHORB,\r\n\tMT_ARACHNON,\r\n\tMT_FELLTWIN,\r\n\tMT_HORKSPWN,\r\n\tMT_VENMTAIL,\r\n\tMT_NECRMORB,\r\n\tMT_SPIDLORD,\r\n\tMT_LASHWORM,\r\n\tMT_TORCHANT,\r\n\tMT_HORKDMN,\r\n\tMT_DEFILER,\r\n\tMT_GRAVEDIG,\r\n\tMT_TOMBRAT,\r\n\tMT_FIREBAT,\r\n\tMT_SKLWING,\r\n\tMT_LICH,\r\n\tMT_CRYPTDMN,\r\n\tMT_HELLBAT,\r\n\tMT_BONEDEMN,\r\n\tMT_ARCHLICH,\r\n\tMT_BICLOPS,\r\n\tMT_FLESTHNG,\r\n\tMT_REAPER,\r\n\tMT_NAKRUL,\r\n\tNUM_DEFAULT_MTYPES,\r\n\tNUM_MAX_MTYPES = 200, // same as MaxMonsters, for the sake of save game compability\r\n\tMT_INVALID = -1,\r\n};\r\n\r\n/**\r\n * @brief Defines if and how a group of monsters should be spawned with the unique monster\r\n */\r\nenum class UniqueMonsterPack : uint8_t {\r\n\t/**\r\n\t * @brief Don't spawn a group of monsters with the unique monster\r\n\t */\r\n\tNone,\r\n\t/**\r\n\t * @brief Spawn a group of monsters that are independent from the unique monster\r\n\t */\r\n\tIndependent,\r\n\t/**\r\n\t * @brief Spawn a group of monsters that are leashed to the unique monster\r\n\t */\r\n\tLeashed,\r\n};\r\n\r\nstruct UniqueMonsterData {\r\n\t_monster_id mtype;\r\n\tstd::string mName;\r\n\tstd::string mTrnName;\r\n\tuint8_t mlevel;\r\n\tuint16_t mmaxhp;\r\n\tMonsterAIID mAi;\r\n\tuint8_t mint;\r\n\tuint8_t mMinDamage;\r\n\tuint8_t mMaxDamage;\r\n\t/** Using monster_resistance as bitflags */\r\n\tuint16_t mMagicRes;\r\n\t/**\r\n\t * @brief Defines if and how a group of monsters should be spawned with the unique monster\r\n\t */\r\n\r\n\tuint8_t reducePlayerStrength;\r\n\tuint8_t reducePlayerMagic;\r\n\tuint8_t reducePlayerDexterity;\r\n\tuint8_t reducePlayerVitality;\r\n\tuint8_t reducePlayerMaxHP;\r\n\tuint8_t reducePlayerMaxMana;\r\n\tUniqueMonsterPack monsterPack;\r\n\tuint8_t customToHit;\r\n\tuint8_t customArmorClass;\r\n\t_speech_id mtalkmsg;\r\n};\r\n\r\nextern std::vector<MonsterData> MonstersData;\r\nextern const _monster_id MonstConvTbl[];\r\nextern std::vector<UniqueMonsterData> UniqueMonstersData;\r\n\r\nvoid LoadMonstDatFromFile(DataFile &dataFile, std::string_view filename, bool grow);\r\nvoid LoadUniqueMonstDatFromFile(DataFile &dataFile, std::string_view filename);\r\nvoid LoadMonsterData();\r\n\r\n/**\r\n * @brief Returns the number of the monster sprite files.\r\n *\r\n * Different monsters can use the same sprite with different TRNs, these count as 1.\r\n */\r\nsize_t GetNumMonsterSprites();\r\n\r\n} // namespace devilution\r\n\r\ntemplate <>\r\nstruct magic_enum::customize::enum_range<devilution::_monster_id> {\r\n\tstatic constexpr int min = devilution::MT_INVALID;\r\n\tstatic constexpr int max = devilution::NUM_DEFAULT_MTYPES;\r\n};\r\n\r\ntemplate <>\r\nstruct magic_enum::customize::enum_range<devilution::monster_resistance> {\r\n\tstatic constexpr int min = 0;\r\n\tstatic constexpr int max = 128;\r\n};\r\n"
  },
  {
    "path": "Source/tables/objdat.cpp",
    "content": "/**\r\n * @file objdat.cpp\r\n *\r\n * Implementation of all object data.\r\n */\r\n#include \"tables/objdat.h\"\r\n\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n\r\n#include \"cursor.h\"\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/** Maps from dun_object_id to object_id. */\r\nconst _object_id ObjTypeConv[] = {\r\n\tOBJ_NULL,\r\n\tOBJ_LEVER,\r\n\tOBJ_CRUX1,\r\n\tOBJ_CRUX2,\r\n\tOBJ_CRUX3,\r\n\tOBJ_ANGEL,\r\n\tOBJ_BANNERL,\r\n\tOBJ_BANNERM,\r\n\tOBJ_BANNERR,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_BOOK2L,\r\n\tOBJ_BOOK2R,\r\n\tOBJ_BCROSS,\r\n\tOBJ_NULL,\r\n\tOBJ_CANDLE1,\r\n\tOBJ_CANDLE2,\r\n\tOBJ_CANDLEO,\r\n\tOBJ_CAULDRON,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_FLAMEHOLE,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_MCIRCLE1,\r\n\tOBJ_MCIRCLE2,\r\n\tOBJ_SKFIRE,\r\n\tOBJ_SKPILE,\r\n\tOBJ_SKSTICK1,\r\n\tOBJ_SKSTICK2,\r\n\tOBJ_SKSTICK3,\r\n\tOBJ_SKSTICK4,\r\n\tOBJ_SKSTICK5,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_SWITCHSKL,\r\n\tOBJ_NULL,\r\n\tOBJ_TRAPL,\r\n\tOBJ_TRAPR,\r\n\tOBJ_TORTURE1,\r\n\tOBJ_TORTURE2,\r\n\tOBJ_TORTURE3,\r\n\tOBJ_TORTURE4,\r\n\tOBJ_TORTURE5,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NUDEW2R,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_TNUDEM1,\r\n\tOBJ_TNUDEM2,\r\n\tOBJ_TNUDEM3,\r\n\tOBJ_TNUDEM4,\r\n\tOBJ_TNUDEW1,\r\n\tOBJ_TNUDEW2,\r\n\tOBJ_TNUDEW3,\r\n\tOBJ_CHEST1,\r\n\tOBJ_CHEST1,\r\n\tOBJ_CHEST1,\r\n\tOBJ_CHEST2,\r\n\tOBJ_CHEST2,\r\n\tOBJ_CHEST2,\r\n\tOBJ_CHEST3,\r\n\tOBJ_CHEST3,\r\n\tOBJ_CHEST3,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_PEDESTAL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_ALTBOY,\r\n\tOBJ_NULL,\r\n\tOBJ_NULL,\r\n\tOBJ_WARARMOR,\r\n\tOBJ_WARWEAP,\r\n\tOBJ_TORCHR2,\r\n\tOBJ_TORCHL2,\r\n\tOBJ_MUSHPATCH,\r\n\tOBJ_STAND,\r\n\tOBJ_TORCHL,\r\n\tOBJ_TORCHR,\r\n\tOBJ_FLAMELVR,\r\n\tOBJ_SARC,\r\n\tOBJ_BARREL,\r\n\tOBJ_BARRELEX,\r\n\tOBJ_BOOKSHELF,\r\n\tOBJ_BOOKCASEL,\r\n\tOBJ_BOOKCASER,\r\n\tOBJ_ARMORSTANDN,\r\n\tOBJ_WEAPONRACKN,\r\n\tOBJ_BLOODFTN,\r\n\tOBJ_PURIFYINGFTN,\r\n\tOBJ_SHRINEL,\r\n\tOBJ_SHRINER,\r\n\tOBJ_GOATSHRINE,\r\n\tOBJ_MURKYFTN,\r\n\tOBJ_TEARFTN,\r\n\tOBJ_DECAP,\r\n\tOBJ_TCHEST1,\r\n\tOBJ_TCHEST2,\r\n\tOBJ_TCHEST3,\r\n\tOBJ_LAZSTAND,\r\n\tOBJ_BOOKSTAND,\r\n\tOBJ_BOOKSHELFR,\r\n\tOBJ_POD,\r\n\tOBJ_PODEX,\r\n\tOBJ_URN,\r\n\tOBJ_URNEX,\r\n\tOBJ_L5BOOKS,\r\n\tOBJ_L5CANDLE,\r\n\tOBJ_L5LEVER,\r\n\tOBJ_L5SARC,\r\n};\r\n\r\n/** Contains the data related to each object ID. */\r\nstd::vector<ObjectData> AllObjects;\r\n\r\n/** Maps from object_graphic_id to object CEL name. */\r\nstd::vector<std::string> ObjMasterLoadList;\r\n\r\nnamespace {\r\n\r\ntl::expected<theme_id, std::string> ParseTheme(std::string_view value)\r\n{\r\n\tif (value.empty()) return THEME_NONE;\r\n\tif (value == \"THEME_BARREL\") return THEME_BARREL;\r\n\tif (value == \"THEME_SHRINE\") return THEME_SHRINE;\r\n\tif (value == \"THEME_MONSTPIT\") return THEME_MONSTPIT;\r\n\tif (value == \"THEME_SKELROOM\") return THEME_SKELROOM;\r\n\tif (value == \"THEME_TREASURE\") return THEME_TREASURE;\r\n\tif (value == \"THEME_LIBRARY\") return THEME_LIBRARY;\r\n\tif (value == \"THEME_TORTURE\") return THEME_TORTURE;\r\n\tif (value == \"THEME_BLOODFOUNTAIN\") return THEME_BLOODFOUNTAIN;\r\n\tif (value == \"THEME_DECAPITATED\") return THEME_DECAPITATED;\r\n\tif (value == \"THEME_PURIFYINGFOUNTAIN\") return THEME_PURIFYINGFOUNTAIN;\r\n\tif (value == \"THEME_ARMORSTAND\") return THEME_ARMORSTAND;\r\n\tif (value == \"THEME_GOATSHRINE\") return THEME_GOATSHRINE;\r\n\tif (value == \"THEME_CAULDRON\") return THEME_CAULDRON;\r\n\tif (value == \"THEME_MURKYFOUNTAIN\") return THEME_MURKYFOUNTAIN;\r\n\tif (value == \"THEME_TEARFOUNTAIN\") return THEME_TEARFOUNTAIN;\r\n\tif (value == \"THEME_BRNCROSS\") return THEME_BRNCROSS;\r\n\tif (value == \"THEME_WEAPONRACK\") return THEME_WEAPONRACK;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<quest_id, std::string> ParseQuest(std::string_view value)\r\n{\r\n\tif (value.empty()) return Q_INVALID;\r\n\tif (value == \"Q_ROCK\") return Q_ROCK;\r\n\tif (value == \"Q_MUSHROOM\") return Q_MUSHROOM;\r\n\tif (value == \"Q_GARBUD\") return Q_GARBUD;\r\n\tif (value == \"Q_ZHAR\") return Q_ZHAR;\r\n\tif (value == \"Q_VEIL\") return Q_VEIL;\r\n\tif (value == \"Q_DIABLO\") return Q_DIABLO;\r\n\tif (value == \"Q_BUTCHER\") return Q_BUTCHER;\r\n\tif (value == \"Q_LTBANNER\") return Q_LTBANNER;\r\n\tif (value == \"Q_BLIND\") return Q_BLIND;\r\n\tif (value == \"Q_BLOOD\") return Q_BLOOD;\r\n\tif (value == \"Q_ANVIL\") return Q_ANVIL;\r\n\tif (value == \"Q_WARLORD\") return Q_WARLORD;\r\n\tif (value == \"Q_SKELKING\") return Q_SKELKING;\r\n\tif (value == \"Q_PWATER\") return Q_PWATER;\r\n\tif (value == \"Q_SCHAMB\") return Q_SCHAMB;\r\n\tif (value == \"Q_BETRAYER\") return Q_BETRAYER;\r\n\tif (value == \"Q_GRAVE\") return Q_GRAVE;\r\n\tif (value == \"Q_FARMER\") return Q_FARMER;\r\n\tif (value == \"Q_GIRL\") return Q_GIRL;\r\n\tif (value == \"Q_TRADER\") return Q_TRADER;\r\n\tif (value == \"Q_DEFILER\") return Q_DEFILER;\r\n\tif (value == \"Q_NAKRUL\") return Q_NAKRUL;\r\n\tif (value == \"Q_CORNSTN\") return Q_CORNSTN;\r\n\tif (value == \"Q_JERSEY\") return Q_JERSEY;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<ObjectDataFlags, std::string> ParseObjectDataFlags(std::string_view value)\r\n{\r\n\tif (value.empty()) return ObjectDataFlags::None;\r\n\tif (value == \"Animated\") return ObjectDataFlags::Animated;\r\n\tif (value == \"Solid\") return ObjectDataFlags::Solid;\r\n\tif (value == \"MissilesPassThrough\") return ObjectDataFlags::MissilesPassThrough;\r\n\tif (value == \"Light\") return ObjectDataFlags::Light;\r\n\tif (value == \"Trap\") return ObjectDataFlags::Trap;\r\n\tif (value == \"Breakable\") return ObjectDataFlags::Breakable;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<SelectionRegion, std::string> ParseSelectionRegion(std::string_view value)\r\n{\r\n\tif (value.empty()) return SelectionRegion::None;\r\n\tif (value == \"Bottom\") return SelectionRegion::Bottom;\r\n\tif (value == \"Middle\") return SelectionRegion::Middle;\r\n\tif (value == \"Top\") return SelectionRegion::Top;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadObjectData()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\objects\\\\objdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tAllObjects.clear();\r\n\tObjMasterLoadList.clear();\r\n\r\n\tankerl::unordered_dense::map<std::string, uint8_t> filenameToId;\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tObjectData &item = AllObjects.emplace_back();\r\n\r\n\t\treader.advance(); // skip id\r\n\r\n\t\tstd::string objFilename;\r\n\t\treader.readString(\"file\", objFilename);\r\n\t\tif (const auto it = filenameToId.find(objFilename); it != filenameToId.end()) {\r\n\t\t\titem.ofindex = it->second;\r\n\t\t} else {\r\n\t\t\tconst auto id = static_cast<uint8_t>(ObjMasterLoadList.size());\r\n\t\t\tObjMasterLoadList.push_back(objFilename);\r\n\t\t\tfilenameToId.emplace(std::move(objFilename), id);\r\n\t\t\titem.ofindex = id;\r\n\t\t}\r\n\r\n\t\treader.readInt(\"minLevel\", item.minlvl);\r\n\t\treader.readInt(\"maxLevel\", item.maxlvl);\r\n\t\treader.read(\"levelType\", item.olvltype, ParseDungeonType);\r\n\t\treader.read(\"theme\", item.otheme, ParseTheme);\r\n\t\treader.read(\"quest\", item.oquest, ParseQuest);\r\n\t\treader.readEnumList(\"flags\", item.flags, ParseObjectDataFlags);\r\n\t\treader.readInt(\"animDelay\", item.animDelay);\r\n\t\treader.readInt(\"animLen\", item.animLen);\r\n\t\treader.readInt(\"animWidth\", item.animWidth);\r\n\t\treader.readEnumList(\"selectionRegion\", item.selectionRegion, ParseSelectionRegion);\r\n\t}\r\n\r\n\t// Sanity check because we do not actually parse the IDs yet.\r\n\tassert(static_cast<size_t>(OBJ_LAST) + 1 == AllObjects.size());\r\n\r\n\tAllObjects.shrink_to_fit();\r\n\tObjMasterLoadList.shrink_to_fit();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/objdat.h",
    "content": "/**\r\n * @file objdat.h\r\n *\r\n * Interface of all object data.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <vector>\r\n\r\n#include \"cursor.h\"\r\n#include \"levels/gendung.h\"\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum theme_id : int8_t {\r\n\tTHEME_BARREL,\r\n\tTHEME_SHRINE,\r\n\tTHEME_MONSTPIT,\r\n\tTHEME_SKELROOM,\r\n\tTHEME_TREASURE,\r\n\tTHEME_LIBRARY,\r\n\tTHEME_TORTURE,\r\n\tTHEME_BLOODFOUNTAIN,\r\n\tTHEME_DECAPITATED,\r\n\tTHEME_PURIFYINGFOUNTAIN,\r\n\tTHEME_ARMORSTAND,\r\n\tTHEME_GOATSHRINE,\r\n\tTHEME_CAULDRON,\r\n\tTHEME_MURKYFOUNTAIN,\r\n\tTHEME_TEARFOUNTAIN,\r\n\tTHEME_BRNCROSS,\r\n\tTHEME_WEAPONRACK,\r\n\tTHEME_NONE = -1,\r\n};\r\n\r\n// Index into ObjMasterLoadList.\r\nusing object_graphic_id = uint8_t;\r\n\r\nenum _object_id : int8_t {\r\n\tOBJ_L1LIGHT,\r\n\tOBJ_L1LDOOR,\r\n\tOBJ_L1RDOOR,\r\n\tOBJ_SKFIRE,\r\n\tOBJ_LEVER,\r\n\tOBJ_CHEST1,\r\n\tOBJ_CHEST2,\r\n\tOBJ_CHEST3,\r\n\tOBJ_CANDLE1,\r\n\tOBJ_CANDLE2,\r\n\tOBJ_CANDLEO,\r\n\tOBJ_BANNERL,\r\n\tOBJ_BANNERM,\r\n\tOBJ_BANNERR,\r\n\tOBJ_SKPILE,\r\n\tOBJ_SKSTICK1,\r\n\tOBJ_SKSTICK2,\r\n\tOBJ_SKSTICK3,\r\n\tOBJ_SKSTICK4,\r\n\tOBJ_SKSTICK5,\r\n\tOBJ_CRUX1,\r\n\tOBJ_CRUX2,\r\n\tOBJ_CRUX3,\r\n\tOBJ_STAND,\r\n\tOBJ_ANGEL,\r\n\tOBJ_BOOK2L,\r\n\tOBJ_BCROSS,\r\n\tOBJ_NUDEW2R,\r\n\tOBJ_SWITCHSKL,\r\n\tOBJ_TNUDEM1,\r\n\tOBJ_TNUDEM2,\r\n\tOBJ_TNUDEM3,\r\n\tOBJ_TNUDEM4,\r\n\tOBJ_TNUDEW1,\r\n\tOBJ_TNUDEW2,\r\n\tOBJ_TNUDEW3,\r\n\tOBJ_TORTURE1,\r\n\tOBJ_TORTURE2,\r\n\tOBJ_TORTURE3,\r\n\tOBJ_TORTURE4,\r\n\tOBJ_TORTURE5,\r\n\tOBJ_BOOK2R,\r\n\tOBJ_L2LDOOR,\r\n\tOBJ_L2RDOOR,\r\n\tOBJ_TORCHL,\r\n\tOBJ_TORCHR,\r\n\tOBJ_TORCHL2,\r\n\tOBJ_TORCHR2,\r\n\tOBJ_SARC,\r\n\tOBJ_FLAMEHOLE,\r\n\tOBJ_FLAMELVR,\r\n\tOBJ_WATER,\r\n\tOBJ_BOOKLVR,\r\n\tOBJ_TRAPL,\r\n\tOBJ_TRAPR,\r\n\tOBJ_BOOKSHELF,\r\n\tOBJ_WEAPRACK,\r\n\tOBJ_BARREL,\r\n\tOBJ_BARRELEX,\r\n\tOBJ_SHRINEL,\r\n\tOBJ_SHRINER,\r\n\tOBJ_SKELBOOK,\r\n\tOBJ_BOOKCASEL,\r\n\tOBJ_BOOKCASER,\r\n\tOBJ_BOOKSTAND,\r\n\tOBJ_BOOKCANDLE,\r\n\tOBJ_BLOODFTN,\r\n\tOBJ_DECAP,\r\n\tOBJ_TCHEST1,\r\n\tOBJ_TCHEST2,\r\n\tOBJ_TCHEST3,\r\n\tOBJ_BLINDBOOK,\r\n\tOBJ_BLOODBOOK,\r\n\tOBJ_PEDESTAL,\r\n\tOBJ_L3LDOOR,\r\n\tOBJ_L3RDOOR,\r\n\tOBJ_PURIFYINGFTN,\r\n\tOBJ_ARMORSTAND,\r\n\tOBJ_ARMORSTANDN,\r\n\tOBJ_GOATSHRINE,\r\n\tOBJ_CAULDRON,\r\n\tOBJ_MURKYFTN,\r\n\tOBJ_TEARFTN,\r\n\tOBJ_ALTBOY,\r\n\tOBJ_MCIRCLE1,\r\n\tOBJ_MCIRCLE2,\r\n\tOBJ_STORYBOOK,\r\n\tOBJ_STORYCANDLE,\r\n\tOBJ_STEELTOME,\r\n\tOBJ_WARARMOR,\r\n\tOBJ_WARWEAP,\r\n\tOBJ_TBCROSS,\r\n\tOBJ_WEAPONRACK,\r\n\tOBJ_WEAPONRACKN,\r\n\tOBJ_MUSHPATCH,\r\n\tOBJ_LAZSTAND,\r\n\tOBJ_SLAINHERO,\r\n\tOBJ_SIGNCHEST,\r\n\tOBJ_BOOKSHELFR,\r\n\tOBJ_POD,\r\n\tOBJ_PODEX,\r\n\tOBJ_URN,\r\n\tOBJ_URNEX,\r\n\tOBJ_L5BOOKS,\r\n\tOBJ_L5CANDLE,\r\n\tOBJ_L5LDOOR,\r\n\tOBJ_L5RDOOR,\r\n\tOBJ_L5LEVER,\r\n\tOBJ_L5SARC,\r\n\r\n\tOBJ_LAST = OBJ_L5SARC,\r\n\tOBJ_NULL = -1,\r\n};\r\n\r\nenum quest_id : int8_t {\r\n\tQ_ROCK,\r\n\tQ_MUSHROOM,\r\n\tQ_GARBUD,\r\n\tQ_ZHAR,\r\n\tQ_VEIL,\r\n\tQ_DIABLO,\r\n\tQ_BUTCHER,\r\n\tQ_LTBANNER,\r\n\tQ_BLIND,\r\n\tQ_BLOOD,\r\n\tQ_ANVIL,\r\n\tQ_WARLORD,\r\n\tQ_SKELKING,\r\n\tQ_PWATER,\r\n\tQ_SCHAMB,\r\n\tQ_BETRAYER,\r\n\tQ_GRAVE,\r\n\tQ_FARMER,\r\n\tQ_GIRL,\r\n\tQ_TRADER,\r\n\tQ_DEFILER,\r\n\tQ_NAKRUL,\r\n\tQ_CORNSTN,\r\n\tQ_JERSEY,\r\n\tQ_INVALID = -1,\r\n};\r\n\r\nenum class ObjectDataFlags : uint8_t {\r\n\tNone = 0,\r\n\tAnimated = 1U,\r\n\tSolid = 1U << 1,\r\n\tMissilesPassThrough = 1U << 2,\r\n\tLight = 1U << 3,\r\n\tTrap = 1U << 4,\r\n\tBreakable = 1U << 5,\r\n};\r\nuse_enum_as_flags(ObjectDataFlags);\r\n\r\nstruct ObjectData {\r\n\tobject_graphic_id ofindex;\r\n\tint8_t minlvl;\r\n\tint8_t maxlvl;\r\n\tdungeon_type olvltype;\r\n\ttheme_id otheme;\r\n\tquest_id oquest;\r\n\tObjectDataFlags flags;\r\n\tuint8_t animDelay; // Tick length of each frame in the current animation\r\n\tuint8_t animLen;   // Number of frames in current animation\r\n\tuint8_t animWidth;\r\n\tSelectionRegion selectionRegion;\r\n\r\n\t[[nodiscard]] bool isAnimated() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, ObjectDataFlags::Animated);\r\n\t}\r\n\r\n\t[[nodiscard]] bool isSolid() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, ObjectDataFlags::Solid);\r\n\t}\r\n\r\n\t[[nodiscard]] bool missilesPassThrough() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, ObjectDataFlags::MissilesPassThrough);\r\n\t}\r\n\r\n\t[[nodiscard]] bool applyLighting() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, ObjectDataFlags::Light);\r\n\t}\r\n\r\n\t[[nodiscard]] bool isTrap() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, ObjectDataFlags::Trap);\r\n\t}\r\n\r\n\t[[nodiscard]] bool isBreakable() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, ObjectDataFlags::Breakable);\r\n\t}\r\n};\r\n\r\nextern const _object_id ObjTypeConv[];\r\nextern std::vector<ObjectData> AllObjects;\r\nextern std::vector<std::string> ObjMasterLoadList;\r\n\r\nvoid LoadObjectData();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/playerdat.cpp",
    "content": "/**\r\n * @file playerdat.cpp\r\n *\r\n * Implementation of all player data.\r\n */\r\n\r\n#include \"tables/playerdat.hpp\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <bitset>\r\n#include <charconv>\r\n#include <cstdint>\r\n#include <vector>\r\n\r\n#include <expected.hpp>\r\n#include <fmt/format.h>\r\n#include <magic_enum/magic_enum_utility.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n#include \"data/value_reader.hpp\"\r\n#include \"items.h\"\r\n#include \"player.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"utils/language.h\"\r\n#include \"utils/static_vector.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nclass ExperienceData {\r\n\t/** Specifies the experience point limit of each level. */\r\n\tstd::vector<uint32_t> levelThresholds;\r\n\r\npublic:\r\n\tuint8_t getMaxLevel() const\r\n\t{\r\n\t\treturn static_cast<uint8_t>(std::min<size_t>(levelThresholds.size(), std::numeric_limits<uint8_t>::max()));\r\n\t}\r\n\r\n\tDVL_REINITIALIZES void clear()\r\n\t{\r\n\t\tlevelThresholds.clear();\r\n\t}\r\n\r\n\t[[nodiscard]] uint32_t getThresholdForLevel(unsigned level) const\r\n\t{\r\n\t\tif (level > 0)\r\n\t\t\treturn levelThresholds[std::min<unsigned>(level - 1, getMaxLevel())];\r\n\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tvoid setThresholdForLevel(unsigned level, uint32_t experience)\r\n\t{\r\n\t\tif (level > 0) {\r\n\t\t\tif (level > levelThresholds.size()) {\r\n\t\t\t\t// To avoid ValidatePlayer() resetting players to 0 experience we need to use the maximum possible value here\r\n\t\t\t\t// As long as the file has no gaps it'll get initialised properly.\r\n\t\t\t\tlevelThresholds.resize(level, std::numeric_limits<uint32_t>::max());\r\n\t\t\t}\r\n\r\n\t\t\tlevelThresholds[static_cast<size_t>(level - 1)] = experience;\r\n\t\t}\r\n\t}\r\n} ExperienceData;\r\n\r\nenum class ExperienceColumn {\r\n\tLevel,\r\n\tExperience,\r\n\tLAST = Experience\r\n};\r\n\r\ntl::expected<ExperienceColumn, ColumnDefinition::Error> mapExperienceColumnFromName(std::string_view name)\r\n{\r\n\tif (name == \"Level\") {\r\n\t\treturn ExperienceColumn::Level;\r\n\t}\r\n\tif (name == \"Experience\") {\r\n\t\treturn ExperienceColumn::Experience;\r\n\t}\r\n\treturn tl::unexpected { ColumnDefinition::Error::UnknownColumn };\r\n}\r\n\r\nvoid ReloadExperienceData()\r\n{\r\n\tconstexpr std::string_view filename = \"txtdata\\\\Experience.tsv\";\r\n\tauto dataFileResult = DataFile::load(filename);\r\n\tif (!dataFileResult.has_value()) {\r\n\t\tDataFile::reportFatalError(dataFileResult.error(), filename);\r\n\t}\r\n\tDataFile &dataFile = dataFileResult.value();\r\n\r\n\tconstexpr unsigned ExpectedColumnCount = enum_size<ExperienceColumn>::value;\r\n\r\n\tstd::array<ColumnDefinition, ExpectedColumnCount> columns;\r\n\tauto parseHeaderResult = dataFile.parseHeader<ExperienceColumn>(columns.data(), columns.data() + columns.size(), mapExperienceColumnFromName);\r\n\r\n\tif (!parseHeaderResult.has_value()) {\r\n\t\tDataFile::reportFatalError(parseHeaderResult.error(), filename);\r\n\t}\r\n\r\n\tExperienceData.clear();\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tuint8_t level = 0;\r\n\t\tuint32_t experience = 0;\r\n\t\tbool skipRecord = false;\r\n\r\n\t\tFieldIterator fieldIt = record.begin();\r\n\t\tconst FieldIterator endField = record.end();\r\n\t\tfor (auto &column : columns) {\r\n\t\t\tfieldIt += column.skipLength;\r\n\r\n\t\t\tif (fieldIt == endField) {\r\n\t\t\t\tDataFile::reportFatalError(DataFile::Error::NotEnoughColumns, filename);\r\n\t\t\t}\r\n\r\n\t\t\tDataFileField field = *fieldIt;\r\n\r\n\t\t\tswitch (static_cast<ExperienceColumn>(column)) {\r\n\t\t\tcase ExperienceColumn::Level: {\r\n\t\t\t\tauto parseIntResult = field.parseInt(level);\r\n\r\n\t\t\t\tif (!parseIntResult.has_value()) {\r\n\t\t\t\t\tif (*field == \"MaxLevel\") {\r\n\t\t\t\t\t\tskipRecord = true;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tDataFile::reportFatalFieldError(parseIntResult.error(), filename, \"Level\", field);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} break;\r\n\r\n\t\t\tcase ExperienceColumn::Experience: {\r\n\t\t\t\tauto parseIntResult = field.parseInt(experience);\r\n\r\n\t\t\t\tif (!parseIntResult.has_value()) {\r\n\t\t\t\t\tDataFile::reportFatalFieldError(parseIntResult.error(), filename, \"Experience\", field);\r\n\t\t\t\t}\r\n\t\t\t} break;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tif (skipRecord)\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t++fieldIt;\r\n\t\t}\r\n\r\n\t\tif (!skipRecord)\r\n\t\t\tExperienceData.setThresholdForLevel(level, experience);\r\n\t}\r\n}\r\n\r\ntl::expected<PlayerClassFlag, std::string> ParsePlayerClassFlag(std::string_view value)\r\n{\r\n\tconst std::optional<PlayerClassFlag> enumValueOpt = magic_enum::enum_cast<PlayerClassFlag>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\nvoid LoadClassData(std::string_view classPath, ClassAttributes &attributes, PlayerCombatData &combat)\r\n{\r\n\tconst std::string filename = StrCat(\"txtdata\\\\classes\\\\\", classPath, \"\\\\attributes.tsv\");\r\n\ttl::expected<DataFile, DataFile::Error> dataFileResult = DataFile::loadOrDie(filename);\r\n\tDataFile &dataFile = dataFileResult.value();\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tValueReader reader { dataFile, filename };\r\n\r\n\treader.readEnumList(\"classFlags\", attributes.classFlags, ParsePlayerClassFlag);\r\n\treader.readInt(\"baseStr\", attributes.baseStr);\r\n\treader.readInt(\"baseMag\", attributes.baseMag);\r\n\treader.readInt(\"baseDex\", attributes.baseDex);\r\n\treader.readInt(\"baseVit\", attributes.baseVit);\r\n\treader.readInt(\"maxStr\", attributes.maxStr);\r\n\treader.readInt(\"maxMag\", attributes.maxMag);\r\n\treader.readInt(\"maxDex\", attributes.maxDex);\r\n\treader.readInt(\"maxVit\", attributes.maxVit);\r\n\treader.readInt(\"blockBonus\", combat.baseToBlock);\r\n\treader.readDecimal(\"adjLife\", attributes.adjLife);\r\n\treader.readDecimal(\"adjMana\", attributes.adjMana);\r\n\treader.readDecimal(\"lvlLife\", attributes.lvlLife);\r\n\treader.readDecimal(\"lvlMana\", attributes.lvlMana);\r\n\treader.readDecimal(\"chrLife\", attributes.chrLife);\r\n\treader.readDecimal(\"chrMana\", attributes.chrMana);\r\n\treader.readDecimal(\"itmLife\", attributes.itmLife);\r\n\treader.readDecimal(\"itmMana\", attributes.itmMana);\r\n\treader.readInt(\"baseMagicToHit\", combat.baseMagicToHit);\r\n\treader.readInt(\"baseMeleeToHit\", combat.baseMeleeToHit);\r\n\treader.readInt(\"baseRangedToHit\", combat.baseRangedToHit);\r\n}\r\n\r\nvoid LoadClassStartingLoadoutData(std::string_view classPath, PlayerStartingLoadoutData &startingLoadoutData)\r\n{\r\n\tconst std::string filename = StrCat(\"txtdata\\\\classes\\\\\", classPath, \"\\\\starting_loadout.tsv\");\r\n\ttl::expected<DataFile, DataFile::Error> dataFileResult = DataFile::loadOrDie(filename);\r\n\tDataFile &dataFile = dataFileResult.value();\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tValueReader reader { dataFile, filename };\r\n\r\n\treader.read(\"skill\", startingLoadoutData.skill, ParseSpellId);\r\n\treader.read(\"spell\", startingLoadoutData.spell, ParseSpellId);\r\n\treader.readInt(\"spellLevel\", startingLoadoutData.spellLevel);\r\n\tfor (size_t i = 0; i < startingLoadoutData.items.size(); ++i) {\r\n\t\treader.read(StrCat(\"item\", i), startingLoadoutData.items[i], ParseItemId);\r\n\t}\r\n\treader.readInt(\"gold\", startingLoadoutData.gold);\r\n}\r\n\r\nvoid LoadClassSpriteData(std::string_view classPath, PlayerSpriteData &spriteData)\r\n{\r\n\tconst std::string filename = StrCat(\"txtdata\\\\classes\\\\\", classPath, \"\\\\sprites.tsv\");\r\n\ttl::expected<DataFile, DataFile::Error> dataFileResult = DataFile::loadOrDie(filename);\r\n\tDataFile &dataFile = dataFileResult.value();\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tValueReader reader { dataFile, filename };\r\n\r\n\treader.readString(\"classPath\", spriteData.classPath);\r\n\treader.readChar(\"classChar\", spriteData.classChar);\r\n\treader.readString(\"trn\", spriteData.trn);\r\n\treader.readInt(\"stand\", spriteData.stand);\r\n\treader.readInt(\"walk\", spriteData.walk);\r\n\treader.readInt(\"attack\", spriteData.attack);\r\n\treader.readInt(\"bow\", spriteData.bow);\r\n\treader.readInt(\"swHit\", spriteData.swHit);\r\n\treader.readInt(\"block\", spriteData.block);\r\n\treader.readInt(\"lightning\", spriteData.lightning);\r\n\treader.readInt(\"fire\", spriteData.fire);\r\n\treader.readInt(\"magic\", spriteData.magic);\r\n\treader.readInt(\"death\", spriteData.death);\r\n}\r\n\r\nvoid LoadClassAnimData(std::string_view classPath, PlayerAnimData &animData)\r\n{\r\n\tconst std::string filename = StrCat(\"txtdata\\\\classes\\\\\", classPath, \"\\\\animations.tsv\");\r\n\ttl::expected<DataFile, DataFile::Error> dataFileResult = DataFile::loadOrDie(filename);\r\n\tDataFile &dataFile = dataFileResult.value();\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tValueReader reader { dataFile, filename };\r\n\r\n\treader.readInt(\"unarmedFrames\", animData.unarmedFrames);\r\n\treader.readInt(\"unarmedActionFrame\", animData.unarmedActionFrame);\r\n\treader.readInt(\"unarmedShieldFrames\", animData.unarmedShieldFrames);\r\n\treader.readInt(\"unarmedShieldActionFrame\", animData.unarmedShieldActionFrame);\r\n\treader.readInt(\"swordFrames\", animData.swordFrames);\r\n\treader.readInt(\"swordActionFrame\", animData.swordActionFrame);\r\n\treader.readInt(\"swordShieldFrames\", animData.swordShieldFrames);\r\n\treader.readInt(\"swordShieldActionFrame\", animData.swordShieldActionFrame);\r\n\treader.readInt(\"bowFrames\", animData.bowFrames);\r\n\treader.readInt(\"bowActionFrame\", animData.bowActionFrame);\r\n\treader.readInt(\"axeFrames\", animData.axeFrames);\r\n\treader.readInt(\"axeActionFrame\", animData.axeActionFrame);\r\n\treader.readInt(\"maceFrames\", animData.maceFrames);\r\n\treader.readInt(\"maceActionFrame\", animData.maceActionFrame);\r\n\treader.readInt(\"maceShieldFrames\", animData.maceShieldFrames);\r\n\treader.readInt(\"maceShieldActionFrame\", animData.maceShieldActionFrame);\r\n\treader.readInt(\"staffFrames\", animData.staffFrames);\r\n\treader.readInt(\"staffActionFrame\", animData.staffActionFrame);\r\n\treader.readInt(\"idleFrames\", animData.idleFrames);\r\n\treader.readInt(\"walkingFrames\", animData.walkingFrames);\r\n\treader.readInt(\"blockingFrames\", animData.blockingFrames);\r\n\treader.readInt(\"deathFrames\", animData.deathFrames);\r\n\treader.readInt(\"castingFrames\", animData.castingFrames);\r\n\treader.readInt(\"recoveryFrames\", animData.recoveryFrames);\r\n\treader.readInt(\"townIdleFrames\", animData.townIdleFrames);\r\n\treader.readInt(\"townWalkingFrames\", animData.townWalkingFrames);\r\n\treader.readInt(\"castingActionFrame\", animData.castingActionFrame);\r\n}\r\n\r\nvoid LoadClassSounds(std::string_view classPath, ankerl::unordered_dense::map<HeroSpeech, SfxID> &sounds)\r\n{\r\n\tconst std::string filename = StrCat(\"txtdata\\\\classes\\\\\", classPath, \"\\\\sounds.tsv\");\r\n\ttl::expected<DataFile, DataFile::Error> dataFileResult = DataFile::loadOrDie(filename);\r\n\tDataFile &dataFile = dataFileResult.value();\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tValueReader reader { dataFile, filename };\r\n\r\n\tmagic_enum::enum_for_each<HeroSpeech>([&](const HeroSpeech speech) {\r\n\t\treader.read(magic_enum::enum_name(speech), sounds[speech], ParseSfxId);\r\n\t});\r\n}\r\n\r\n/** Contains the data related to each player class. */\r\nstd::vector<PlayerData> PlayersData;\r\n\r\nstd::vector<ClassAttributes> ClassAttributesPerClass;\r\n\r\nstd::vector<PlayerCombatData> PlayersCombatData;\r\n\r\nstd::vector<PlayerStartingLoadoutData> PlayersStartingLoadoutData;\r\n\r\n/** Contains the data related to each player class. */\r\nstd::vector<PlayerSpriteData> PlayersSpriteData;\r\n\r\nstd::vector<PlayerAnimData> PlayersAnimData;\r\n\r\nstd::vector<ankerl::unordered_dense::map<HeroSpeech, SfxID>> herosounds;\r\n\r\n} // namespace\r\n\r\nvoid LoadClassDatFromFile(DataFile &dataFile, const std::string_view filename)\r\n{\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tPlayersData.reserve(PlayersData.size() + dataFile.numRecords());\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tif (PlayersData.size() >= static_cast<size_t>(HeroClass::NUM_MAX_CLASSES)) {\r\n\t\t\tDisplayFatalErrorAndExit(_(\"Loading Class Data Failed\"), fmt::format(fmt::runtime(_(\"Could not add a class, since the maximum class number of {} has already been reached.\")), static_cast<size_t>(HeroClass::NUM_MAX_CLASSES)));\r\n\t\t}\r\n\r\n\t\tRecordReader reader { record, filename };\r\n\r\n\t\tPlayerData &playerData = PlayersData.emplace_back();\r\n\r\n\t\treader.readString(\"className\", playerData.className);\r\n\t\treader.readString(\"folderName\", playerData.folderName);\r\n\t\treader.readInt(\"portrait\", playerData.portrait);\r\n\t\treader.readString(\"inv\", playerData.inv);\r\n\t}\r\n}\r\n\r\nnamespace {\r\n\r\nvoid LoadClassDat()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\classes\\\\classdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tPlayersData.clear();\r\n\tLoadClassDatFromFile(dataFile, filename);\r\n\r\n\tPlayersData.shrink_to_fit();\r\n}\r\n\r\nvoid LoadClassesAttributes()\r\n{\r\n\tClassAttributesPerClass.clear();\r\n\tClassAttributesPerClass.reserve(PlayersData.size());\r\n\tPlayersCombatData.clear();\r\n\tPlayersCombatData.reserve(PlayersData.size());\r\n\tPlayersStartingLoadoutData.clear();\r\n\tPlayersStartingLoadoutData.reserve(PlayersData.size());\r\n\tPlayersSpriteData.clear();\r\n\tPlayersSpriteData.reserve(PlayersData.size());\r\n\tPlayersAnimData.clear();\r\n\tPlayersAnimData.reserve(PlayersData.size());\r\n\therosounds.clear();\r\n\therosounds.reserve(PlayersData.size());\r\n\r\n\tfor (const PlayerData &playerData : PlayersData) {\r\n\t\tLoadClassData(playerData.folderName, ClassAttributesPerClass.emplace_back(), PlayersCombatData.emplace_back());\r\n\t\tLoadClassStartingLoadoutData(playerData.folderName, PlayersStartingLoadoutData.emplace_back());\r\n\t\tLoadClassSpriteData(playerData.folderName, PlayersSpriteData.emplace_back());\r\n\t\tLoadClassAnimData(playerData.folderName, PlayersAnimData.emplace_back());\r\n\t\tLoadClassSounds(playerData.folderName, herosounds.emplace_back());\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nconst ClassAttributes &GetClassAttributes(HeroClass playerClass)\r\n{\r\n\treturn ClassAttributesPerClass[static_cast<size_t>(playerClass)];\r\n}\r\n\r\nvoid LoadPlayerDataFiles()\r\n{\r\n\tReloadExperienceData();\r\n\tLoadClassDat();\r\n\tLoadClassesAttributes();\r\n}\r\n\r\nSfxID GetHeroSound(HeroClass clazz, HeroSpeech speech)\r\n{\r\n\tconst size_t playerClassIndex = static_cast<size_t>(clazz);\r\n\tassert(playerClassIndex < herosounds.size());\r\n\tconst auto findIt = herosounds[playerClassIndex].find(speech);\r\n\tif (findIt != herosounds[playerClassIndex].end()) {\r\n\t\treturn findIt->second;\r\n\t}\r\n\r\n\treturn SfxID::None;\r\n}\r\n\r\nuint32_t GetNextExperienceThresholdForLevel(unsigned level)\r\n{\r\n\treturn ExperienceData.getThresholdForLevel(level);\r\n}\r\n\r\nuint8_t GetMaximumCharacterLevel()\r\n{\r\n\treturn ExperienceData.getMaxLevel();\r\n}\r\n\r\nsize_t GetNumPlayerClasses()\r\n{\r\n\treturn PlayersData.size();\r\n}\r\n\r\nconst PlayerData &GetPlayerDataForClass(HeroClass playerClass)\r\n{\r\n\tconst size_t playerClassIndex = static_cast<size_t>(playerClass);\r\n\tassert(playerClassIndex < PlayersData.size());\r\n\treturn PlayersData[playerClassIndex];\r\n}\r\n\r\nconst PlayerCombatData &GetPlayerCombatDataForClass(HeroClass pClass)\r\n{\r\n\tconst size_t playerClassIndex = static_cast<size_t>(pClass);\r\n\tassert(playerClassIndex < PlayersCombatData.size());\r\n\treturn PlayersCombatData[playerClassIndex];\r\n}\r\n\r\nconst PlayerStartingLoadoutData &GetPlayerStartingLoadoutForClass(HeroClass pClass)\r\n{\r\n\tconst size_t playerClassIndex = static_cast<size_t>(pClass);\r\n\tassert(playerClassIndex < PlayersStartingLoadoutData.size());\r\n\treturn PlayersStartingLoadoutData[playerClassIndex];\r\n}\r\n\r\nconst PlayerSpriteData &GetPlayerSpriteDataForClass(HeroClass pClass)\r\n{\r\n\tconst size_t playerClassIndex = static_cast<size_t>(pClass);\r\n\tassert(playerClassIndex < PlayersSpriteData.size());\r\n\treturn PlayersSpriteData[playerClassIndex];\r\n}\r\n\r\nconst PlayerAnimData &GetPlayerAnimDataForClass(HeroClass pClass)\r\n{\r\n\tconst size_t playerClassIndex = static_cast<size_t>(pClass);\r\n\tassert(playerClassIndex < PlayersAnimData.size());\r\n\treturn PlayersAnimData[playerClassIndex];\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/playerdat.hpp",
    "content": "/**\r\n * @file playerdat.hpp\r\n *\r\n * Interface of all player data.\r\n */\r\n#pragma once\r\n\r\n#include <array>\r\n#include <cstdint>\r\n\r\n#include \"effects.h\"\r\n#include \"tables/itemdat.h\"\r\n#include \"tables/spelldat.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class HeroClass : uint8_t {\r\n\tWarrior,\r\n\tRogue,\r\n\tSorcerer,\r\n\tMonk,\r\n\tBard,\r\n\tBarbarian,\r\n\r\n\tNUM_MAX_CLASSES = std::numeric_limits<uint8_t>::max(),\r\n\r\n\tLAST = Barbarian,\r\n};\r\n\r\nenum class PlayerClassFlag : uint8_t {\r\n\t// clang-format off\r\n\tNone = 0,\r\n\tCriticalStrike = 1 << 0,\r\n\tDualWield = 1 << 1,\r\n\tIronSkin = 1 << 2,\r\n\tNaturalResistance = 1 << 3,\r\n\tTrapSense = 1 << 4,\r\n\r\n\tLast = TrapSense\r\n\t// clang-format on\r\n};\r\nuse_enum_as_flags(PlayerClassFlag);\r\n\r\nstruct PlayerData {\r\n\t/* Class Name */\r\n\tstd::string className;\r\n\t/* Class Folder Name */\r\n\tstd::string folderName;\r\n\t/* Class Portrait Index */\r\n\tuint8_t portrait;\r\n\t/* Class Inventory UI File */\r\n\tstd::string inv;\r\n};\r\n\r\nstruct ClassAttributes {\r\n\t/* Class Flags */\r\n\tPlayerClassFlag classFlags;\r\n\t/* Class Starting Strength Stat */\r\n\tuint8_t baseStr;\r\n\t/* Class Starting Magic Stat */\r\n\tuint8_t baseMag;\r\n\t/* Class Starting Dexterity Stat */\r\n\tuint8_t baseDex;\r\n\t/* Class Starting Vitality Stat */\r\n\tuint8_t baseVit;\r\n\t/* Class Maximum Strength Stat */\r\n\tuint8_t maxStr;\r\n\t/* Class Maximum Magic Stat */\r\n\tuint8_t maxMag;\r\n\t/* Class Maximum Dexterity Stat */\r\n\tuint8_t maxDex;\r\n\t/* Class Maximum Vitality Stat */\r\n\tuint8_t maxVit;\r\n\t/* Class Life Adjustment */\r\n\tint16_t adjLife;\r\n\t/* Class Mana Adjustment */\r\n\tint16_t adjMana;\r\n\t/* Life gained on level up */\r\n\tint16_t lvlLife;\r\n\t/* Mana gained on level up */\r\n\tint16_t lvlMana;\r\n\t/* Life from base Vitality */\r\n\tint16_t chrLife;\r\n\t/* Mana from base Magic */\r\n\tint16_t chrMana;\r\n\t/* Life from item bonus Vitality */\r\n\tint16_t itmLife;\r\n\t/* Mana from item bonus Magic */\r\n\tint16_t itmMana;\r\n};\r\n\r\nconst ClassAttributes &GetClassAttributes(HeroClass playerClass);\r\n\r\nstruct PlayerCombatData {\r\n\t/* Class starting chance to Block (used as a %) */\r\n\tuint8_t baseToBlock;\r\n\t/* Class starting chance to hit when using melee attacks (used as a %) */\r\n\tuint8_t baseMeleeToHit;\r\n\t/* Class starting chance to hit when using ranged weapons (used as a %) */\r\n\tuint8_t baseRangedToHit;\r\n\t/* Class starting chance to hit when using spells (used as a %) */\r\n\tuint8_t baseMagicToHit;\r\n};\r\n\r\n/**\r\n * @brief Data used to set known skills and provide initial equipment when starting a new game\r\n *\r\n * Items will be created in order starting with item 1, 2, etc. If the item can be equipped it\r\n * will be placed in the first available slot, otherwise if it fits on the belt it will be\r\n * placed in the first free space, finally being placed in the first free inventory position.\r\n *\r\n * The active game mode at the time we're creating a new character controls the choice of item\r\n * type. ItemType.hellfire is used if we're in Hellfire mode, ItemType.diablo otherwise.\r\n */\r\nstruct PlayerStartingLoadoutData {\r\n\t/* Class Skill */\r\n\tSpellID skill;\r\n\t/* Starting Spell (if any) */\r\n\tSpellID spell;\r\n\t/* Initial level of the starting spell */\r\n\tuint8_t spellLevel;\r\n\r\n\tstd::array<_item_indexes, 5> items;\r\n\r\n\t/* Initial gold amount, up to a single stack (5000 gold) */\r\n\tuint16_t gold;\r\n};\r\n\r\nstruct PlayerSpriteData {\r\n\t/* Class Directory Path */\r\n\tstd::string classPath;\r\n\t/* Class letter used in graphic files */\r\n\tchar classChar;\r\n\t/* Class TRN file */\r\n\tstd::string trn;\r\n\t/* Sprite width: Stand */\r\n\tuint8_t stand;\r\n\t/* Sprite width: Walk */\r\n\tuint8_t walk;\r\n\t/* Sprite width: Attack */\r\n\tuint8_t attack;\r\n\t/* Sprite width: Attack (Bow) */\r\n\tuint8_t bow;\r\n\t/* Sprite width: Hit Recovery */\r\n\tuint8_t swHit;\r\n\t/* Sprite width: Block */\r\n\tuint8_t block;\r\n\t/* Sprite width: Cast Lightning Spell */\r\n\tuint8_t lightning;\r\n\t/* Sprite width: Cast Fire Spell */\r\n\tuint8_t fire;\r\n\t/* Sprite width: Cast Magic Spell */\r\n\tuint8_t magic;\r\n\t/* Sprite width: Death */\r\n\tuint8_t death;\r\n};\r\n\r\nstruct PlayerAnimData {\r\n\t/* Unarmed frame count */\r\n\tint8_t unarmedFrames;\r\n\t/* Unarmed action frame number */\r\n\tint8_t unarmedActionFrame;\r\n\t/* UnarmedShield frame count */\r\n\tint8_t unarmedShieldFrames;\r\n\t/* UnarmedShield action frame number */\r\n\tint8_t unarmedShieldActionFrame;\r\n\t/* Sword frame count */\r\n\tint8_t swordFrames;\r\n\t/* Sword action frame number */\r\n\tint8_t swordActionFrame;\r\n\t/* SwordShield frame count */\r\n\tint8_t swordShieldFrames;\r\n\t/* SwordShield action frame number */\r\n\tint8_t swordShieldActionFrame;\r\n\t/* Bow frame count */\r\n\tint8_t bowFrames;\r\n\t/* Bow action frame number */\r\n\tint8_t bowActionFrame;\r\n\t/* Axe frame count */\r\n\tint8_t axeFrames;\r\n\t/* Axe action frame number */\r\n\tint8_t axeActionFrame;\r\n\t/* Mace frame count */\r\n\tint8_t maceFrames;\r\n\t/* Mace action frame */\r\n\tint8_t maceActionFrame;\r\n\t/* MaceShield frame count */\r\n\tint8_t maceShieldFrames;\r\n\t/* MaceShield action frame number */\r\n\tint8_t maceShieldActionFrame;\r\n\t/* Staff frame count */\r\n\tint8_t staffFrames;\r\n\t/* Staff action frame number */\r\n\tint8_t staffActionFrame;\r\n\t/* Nothing (Idle) frame count */\r\n\tint8_t idleFrames;\r\n\t/* Walking frame count */\r\n\tint8_t walkingFrames;\r\n\t/* Blocking frame count */\r\n\tint8_t blockingFrames;\r\n\t/* Death frame count */\r\n\tint8_t deathFrames;\r\n\t/* Spellcasting frame count */\r\n\tint8_t castingFrames;\r\n\t/* Hit Recovery frame count */\r\n\tint8_t recoveryFrames;\r\n\t/* Town Nothing (Idle) frame count */\r\n\tint8_t townIdleFrames;\r\n\t/* Town Walking frame count */\r\n\tint8_t townWalkingFrames;\r\n\t/* Spellcasting action frame number */\r\n\tint8_t castingActionFrame;\r\n};\r\n\r\n/**\r\n * @brief Attempts to load data values from external files.\r\n */\r\nvoid LoadClassDatFromFile(DataFile &dataFile, const std::string_view filename);\r\nvoid LoadPlayerDataFiles();\r\n\r\nSfxID GetHeroSound(HeroClass clazz, HeroSpeech speech);\r\nuint32_t GetNextExperienceThresholdForLevel(unsigned level);\r\nuint8_t GetMaximumCharacterLevel();\r\nsize_t GetNumPlayerClasses();\r\nconst PlayerData &GetPlayerDataForClass(HeroClass clazz);\r\nconst PlayerCombatData &GetPlayerCombatDataForClass(HeroClass clazz);\r\nconst PlayerStartingLoadoutData &GetPlayerStartingLoadoutForClass(HeroClass clazz);\r\nconst PlayerSpriteData &GetPlayerSpriteDataForClass(HeroClass clazz);\r\nconst PlayerAnimData &GetPlayerAnimDataForClass(HeroClass clazz);\r\n\r\n} // namespace devilution\r\n\r\ntemplate <>\r\nstruct magic_enum::customize::enum_range<devilution::PlayerClassFlag> {\r\n\tstatic constexpr uint8_t min = static_cast<uint64_t>(devilution::PlayerClassFlag::None);\r\n\tstatic constexpr uint8_t max = static_cast<uint64_t>(devilution::PlayerClassFlag::Last);\r\n};\r\n"
  },
  {
    "path": "Source/tables/spelldat.cpp",
    "content": "/**\r\n * @file spelldat.cpp\r\n *\r\n * Implementation of all spell data.\r\n */\r\n#include \"tables/spelldat.h\"\r\n\r\n#include <optional>\r\n#include <string_view>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/iterators.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid AddNullSpell()\r\n{\r\n\tSpellData &null = SpellsData.emplace_back();\r\n\tnull.sSFX = SfxID::None;\r\n\tnull.bookCost10 = null.staffCost10 = null.sManaCost = 0;\r\n\tnull.flags = SpellDataFlags::Fire;\r\n\tnull.sBookLvl = null.sStaffLvl = 0;\r\n\tnull.minInt = 0;\r\n\tnull.sMissiles[0] = null.sMissiles[1] = MissileID::Null;\r\n\tnull.sManaAdj = null.sMinMana = 0;\r\n\tnull.sStaffMin = 40;\r\n\tnull.sStaffMax = 80;\r\n}\r\n\r\n// A temporary solution for parsing soundID until we have a more general one.\r\ntl::expected<SfxID, std::string> ParseSpellSoundId(std::string_view value)\r\n{\r\n\tif (value == \"CastFire\") return SfxID::CastFire;\r\n\tif (value == \"CastHealing\") return SfxID::CastHealing;\r\n\tif (value == \"CastLightning\") return SfxID::CastLightning;\r\n\tif (value == \"CastSkill\") return SfxID::CastSkill;\r\n\treturn tl::make_unexpected(\"Unknown enum value (only a few are supported for now)\");\r\n}\r\n\r\ntl::expected<SpellDataFlags, std::string> ParseSpellDataFlag(std::string_view value)\r\n{\r\n\tif (value == \"Fire\") return SpellDataFlags::Fire;\r\n\tif (value == \"Lightning\") return SpellDataFlags::Lightning;\r\n\tif (value == \"Magic\") return SpellDataFlags::Magic;\r\n\tif (value == \"Targeted\") return SpellDataFlags::Targeted;\r\n\tif (value == \"AllowedInTown\") return SpellDataFlags::AllowedInTown;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\ntl::expected<MissileID, std::string> ParseMissileId(std::string_view value)\r\n{\r\n\tif (value == \"Arrow\") return MissileID::Arrow;\r\n\tif (value == \"Firebolt\") return MissileID::Firebolt;\r\n\tif (value == \"Guardian\") return MissileID::Guardian;\r\n\tif (value == \"Phasing\") return MissileID::Phasing;\r\n\tif (value == \"NovaBall\") return MissileID::NovaBall;\r\n\tif (value == \"FireWall\") return MissileID::FireWall;\r\n\tif (value == \"Fireball\") return MissileID::Fireball;\r\n\tif (value == \"LightningControl\") return MissileID::LightningControl;\r\n\tif (value == \"Lightning\") return MissileID::Lightning;\r\n\tif (value == \"MagmaBallExplosion\") return MissileID::MagmaBallExplosion;\r\n\tif (value == \"TownPortal\") return MissileID::TownPortal;\r\n\tif (value == \"FlashBottom\") return MissileID::FlashBottom;\r\n\tif (value == \"FlashTop\") return MissileID::FlashTop;\r\n\tif (value == \"ManaShield\") return MissileID::ManaShield;\r\n\tif (value == \"FlameWave\") return MissileID::FlameWave;\r\n\tif (value == \"ChainLightning\") return MissileID::ChainLightning;\r\n\tif (value == \"ChainBall\") return MissileID::ChainBall;\r\n\tif (value == \"BloodHit\") return MissileID::BloodHit;\r\n\tif (value == \"BoneHit\") return MissileID::BoneHit;\r\n\tif (value == \"MetalHit\") return MissileID::MetalHit;\r\n\tif (value == \"Rhino\") return MissileID::Rhino;\r\n\tif (value == \"MagmaBall\") return MissileID::MagmaBall;\r\n\tif (value == \"ThinLightningControl\") return MissileID::ThinLightningControl;\r\n\tif (value == \"ThinLightning\") return MissileID::ThinLightning;\r\n\tif (value == \"BloodStar\") return MissileID::BloodStar;\r\n\tif (value == \"BloodStarExplosion\") return MissileID::BloodStarExplosion;\r\n\tif (value == \"Teleport\") return MissileID::Teleport;\r\n\tif (value == \"FireArrow\") return MissileID::FireArrow;\r\n\tif (value == \"DoomSerpents\") return MissileID::DoomSerpents;\r\n\tif (value == \"FireOnly\") return MissileID::FireOnly;\r\n\tif (value == \"StoneCurse\") return MissileID::StoneCurse;\r\n\tif (value == \"BloodRitual\") return MissileID::BloodRitual;\r\n\tif (value == \"Invisibility\") return MissileID::Invisibility;\r\n\tif (value == \"Golem\") return MissileID::Golem;\r\n\tif (value == \"Etherealize\") return MissileID::Etherealize;\r\n\tif (value == \"Spurt\") return MissileID::Spurt;\r\n\tif (value == \"ApocalypseBoom\") return MissileID::ApocalypseBoom;\r\n\tif (value == \"Healing\") return MissileID::Healing;\r\n\tif (value == \"FireWallControl\") return MissileID::FireWallControl;\r\n\tif (value == \"Infravision\") return MissileID::Infravision;\r\n\tif (value == \"Identify\") return MissileID::Identify;\r\n\tif (value == \"FlameWaveControl\") return MissileID::FlameWaveControl;\r\n\tif (value == \"Nova\") return MissileID::Nova;\r\n\tif (value == \"Rage\") return MissileID::Rage;\r\n\tif (value == \"Apocalypse\") return MissileID::Apocalypse;\r\n\tif (value == \"ItemRepair\") return MissileID::ItemRepair;\r\n\tif (value == \"StaffRecharge\") return MissileID::StaffRecharge;\r\n\tif (value == \"TrapDisarm\") return MissileID::TrapDisarm;\r\n\tif (value == \"Inferno\") return MissileID::Inferno;\r\n\tif (value == \"InfernoControl\") return MissileID::InfernoControl;\r\n\tif (value == \"FireMan\") return MissileID::FireMan;\r\n\tif (value == \"Krull\") return MissileID::Krull;\r\n\tif (value == \"ChargedBolt\") return MissileID::ChargedBolt;\r\n\tif (value == \"HolyBolt\") return MissileID::HolyBolt;\r\n\tif (value == \"Resurrect\") return MissileID::Resurrect;\r\n\tif (value == \"Telekinesis\") return MissileID::Telekinesis;\r\n\tif (value == \"LightningArrow\") return MissileID::LightningArrow;\r\n\tif (value == \"Acid\") return MissileID::Acid;\r\n\tif (value == \"AcidSplat\") return MissileID::AcidSplat;\r\n\tif (value == \"AcidPuddle\") return MissileID::AcidPuddle;\r\n\tif (value == \"HealOther\") return MissileID::HealOther;\r\n\tif (value == \"Elemental\") return MissileID::Elemental;\r\n\tif (value == \"ResurrectBeam\") return MissileID::ResurrectBeam;\r\n\tif (value == \"BoneSpirit\") return MissileID::BoneSpirit;\r\n\tif (value == \"WeaponExplosion\") return MissileID::WeaponExplosion;\r\n\tif (value == \"RedPortal\") return MissileID::RedPortal;\r\n\tif (value == \"DiabloApocalypseBoom\") return MissileID::DiabloApocalypseBoom;\r\n\tif (value == \"DiabloApocalypse\") return MissileID::DiabloApocalypse;\r\n\tif (value == \"Mana\") return MissileID::Mana;\r\n\tif (value == \"Magi\") return MissileID::Magi;\r\n\tif (value == \"LightningWall\") return MissileID::LightningWall;\r\n\tif (value == \"LightningWallControl\") return MissileID::LightningWallControl;\r\n\tif (value == \"Immolation\") return MissileID::Immolation;\r\n\tif (value == \"SpectralArrow\") return MissileID::SpectralArrow;\r\n\tif (value == \"FireballBow\") return MissileID::FireballBow;\r\n\tif (value == \"LightningBow\") return MissileID::LightningBow;\r\n\tif (value == \"ChargedBoltBow\") return MissileID::ChargedBoltBow;\r\n\tif (value == \"HolyBoltBow\") return MissileID::HolyBoltBow;\r\n\tif (value == \"Warp\") return MissileID::Warp;\r\n\tif (value == \"Reflect\") return MissileID::Reflect;\r\n\tif (value == \"Berserk\") return MissileID::Berserk;\r\n\tif (value == \"RingOfFire\") return MissileID::RingOfFire;\r\n\tif (value == \"StealPotions\") return MissileID::StealPotions;\r\n\tif (value == \"StealMana\") return MissileID::StealMana;\r\n\tif (value == \"RingOfLightning\") return MissileID::RingOfLightning;\r\n\tif (value == \"Search\") return MissileID::Search;\r\n\tif (value == \"Aura\") return MissileID::Aura;\r\n\tif (value == \"Aura2\") return MissileID::Aura2;\r\n\tif (value == \"SpiralFireball\") return MissileID::SpiralFireball;\r\n\tif (value == \"RuneOfFire\") return MissileID::RuneOfFire;\r\n\tif (value == \"RuneOfLight\") return MissileID::RuneOfLight;\r\n\tif (value == \"RuneOfNova\") return MissileID::RuneOfNova;\r\n\tif (value == \"RuneOfImmolation\") return MissileID::RuneOfImmolation;\r\n\tif (value == \"RuneOfStone\") return MissileID::RuneOfStone;\r\n\tif (value == \"BigExplosion\") return MissileID::BigExplosion;\r\n\tif (value == \"HorkSpawn\") return MissileID::HorkSpawn;\r\n\tif (value == \"Jester\") return MissileID::Jester;\r\n\tif (value == \"OpenNest\") return MissileID::OpenNest;\r\n\tif (value == \"OrangeFlare\") return MissileID::OrangeFlare;\r\n\tif (value == \"BlueFlare\") return MissileID::BlueFlare;\r\n\tif (value == \"RedFlare\") return MissileID::RedFlare;\r\n\tif (value == \"YellowFlare\") return MissileID::YellowFlare;\r\n\tif (value == \"BlueFlare2\") return MissileID::BlueFlare2;\r\n\tif (value == \"YellowExplosion\") return MissileID::YellowExplosion;\r\n\tif (value == \"RedExplosion\") return MissileID::RedExplosion;\r\n\tif (value == \"BlueExplosion\") return MissileID::BlueExplosion;\r\n\tif (value == \"BlueExplosion2\") return MissileID::BlueExplosion2;\r\n\tif (value == \"OrangeExplosion\") return MissileID::OrangeExplosion;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\n} // namespace\r\n\r\n/** Data related to each spell ID. */\r\nstd::vector<SpellData> SpellsData;\r\n\r\ntl::expected<SpellID, std::string> ParseSpellId(std::string_view value)\r\n{\r\n\tif (value == \"Null\") return SpellID::Null;\r\n\tif (value == \"Firebolt\") return SpellID::Firebolt;\r\n\tif (value == \"Healing\") return SpellID::Healing;\r\n\tif (value == \"Lightning\") return SpellID::Lightning;\r\n\tif (value == \"Flash\") return SpellID::Flash;\r\n\tif (value == \"Identify\") return SpellID::Identify;\r\n\tif (value == \"FireWall\") return SpellID::FireWall;\r\n\tif (value == \"TownPortal\") return SpellID::TownPortal;\r\n\tif (value == \"StoneCurse\") return SpellID::StoneCurse;\r\n\tif (value == \"Infravision\") return SpellID::Infravision;\r\n\tif (value == \"Phasing\") return SpellID::Phasing;\r\n\tif (value == \"ManaShield\") return SpellID::ManaShield;\r\n\tif (value == \"Fireball\") return SpellID::Fireball;\r\n\tif (value == \"Guardian\") return SpellID::Guardian;\r\n\tif (value == \"ChainLightning\") return SpellID::ChainLightning;\r\n\tif (value == \"FlameWave\") return SpellID::FlameWave;\r\n\tif (value == \"DoomSerpents\") return SpellID::DoomSerpents;\r\n\tif (value == \"BloodRitual\") return SpellID::BloodRitual;\r\n\tif (value == \"Nova\") return SpellID::Nova;\r\n\tif (value == \"Invisibility\") return SpellID::Invisibility;\r\n\tif (value == \"Inferno\") return SpellID::Inferno;\r\n\tif (value == \"Golem\") return SpellID::Golem;\r\n\tif (value == \"Rage\") return SpellID::Rage;\r\n\tif (value == \"Teleport\") return SpellID::Teleport;\r\n\tif (value == \"Apocalypse\") return SpellID::Apocalypse;\r\n\tif (value == \"Etherealize\") return SpellID::Etherealize;\r\n\tif (value == \"ItemRepair\") return SpellID::ItemRepair;\r\n\tif (value == \"StaffRecharge\") return SpellID::StaffRecharge;\r\n\tif (value == \"TrapDisarm\") return SpellID::TrapDisarm;\r\n\tif (value == \"Elemental\") return SpellID::Elemental;\r\n\tif (value == \"ChargedBolt\") return SpellID::ChargedBolt;\r\n\tif (value == \"HolyBolt\") return SpellID::HolyBolt;\r\n\tif (value == \"Resurrect\") return SpellID::Resurrect;\r\n\tif (value == \"Telekinesis\") return SpellID::Telekinesis;\r\n\tif (value == \"HealOther\") return SpellID::HealOther;\r\n\tif (value == \"BloodStar\") return SpellID::BloodStar;\r\n\tif (value == \"BoneSpirit\") return SpellID::BoneSpirit;\r\n\tif (value == \"Mana\") return SpellID::Mana;\r\n\tif (value == \"Magi\") return SpellID::Magi;\r\n\tif (value == \"Jester\") return SpellID::Jester;\r\n\tif (value == \"LightningWall\") return SpellID::LightningWall;\r\n\tif (value == \"Immolation\") return SpellID::Immolation;\r\n\tif (value == \"Warp\") return SpellID::Warp;\r\n\tif (value == \"Reflect\") return SpellID::Reflect;\r\n\tif (value == \"Berserk\") return SpellID::Berserk;\r\n\tif (value == \"RingOfFire\") return SpellID::RingOfFire;\r\n\tif (value == \"Search\") return SpellID::Search;\r\n\tif (value == \"RuneOfFire\") return SpellID::RuneOfFire;\r\n\tif (value == \"RuneOfLight\") return SpellID::RuneOfLight;\r\n\tif (value == \"RuneOfNova\") return SpellID::RuneOfNova;\r\n\tif (value == \"RuneOfImmolation\") return SpellID::RuneOfImmolation;\r\n\tif (value == \"RuneOfStone\") return SpellID::RuneOfStone;\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\nvoid LoadSpellData()\r\n{\r\n\tSpellsData.clear();\r\n\tconst std::string_view filename = \"txtdata\\\\spells\\\\spelldat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tSpellsData.reserve(dataFile.numRecords() + 1);\r\n\tAddNullSpell();\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tSpellData &item = SpellsData.emplace_back();\r\n\t\treader.advance(); // skip id\r\n\t\treader.readString(\"name\", item.sNameText);\r\n\t\treader.read(\"soundId\", item.sSFX, ParseSpellSoundId);\r\n\t\treader.readInt(\"bookCost10\", item.bookCost10);\r\n\t\treader.readInt(\"staffCost10\", item.staffCost10);\r\n\t\treader.readInt(\"manaCost\", item.sManaCost);\r\n\t\treader.readEnumList(\"flags\", item.flags, ParseSpellDataFlag);\r\n\t\treader.readInt(\"bookLevel\", item.sBookLvl);\r\n\t\treader.readInt(\"staffLevel\", item.sStaffLvl);\r\n\t\treader.readInt(\"minIntelligence\", item.minInt);\r\n\t\treader.readEnumArray(\"missiles\", /*fillMissing=*/std::make_optional(MissileID::Null), item.sMissiles, ParseMissileId);\r\n\t\treader.readInt(\"manaMultiplier\", item.sManaAdj);\r\n\t\treader.readInt(\"minMana\", item.sMinMana);\r\n\t\treader.readInt(\"staffMin\", item.sStaffMin);\r\n\t\treader.readInt(\"staffMax\", item.sStaffMax);\r\n\t}\r\n\tSpellsData.shrink_to_fit();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/spelldat.h",
    "content": "/**\r\n * @file spelldat.h\r\n *\r\n * Interface of all spell data.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <string_view>\r\n#include <type_traits>\r\n#include <vector>\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"sound_effect_enums.h\"\r\n#include \"utils/enum_traits.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum class SpellType : uint8_t {\r\n\tSkill,\r\n\tFIRST = Skill,\r\n\tSpell,\r\n\tScroll,\r\n\tCharges,\r\n\tLAST = Charges,\r\n\tInvalid,\r\n};\r\n\r\nenum class SpellID : int8_t {\r\n\tNull,\r\n\tFIRST = Null,\r\n\tFirebolt,\r\n\tHealing,\r\n\tLightning,\r\n\tFlash,\r\n\tIdentify,\r\n\tFireWall,\r\n\tTownPortal,\r\n\tStoneCurse,\r\n\tInfravision,\r\n\tPhasing,\r\n\tManaShield,\r\n\tFireball,\r\n\tGuardian,\r\n\tChainLightning,\r\n\tFlameWave,\r\n\tDoomSerpents,\r\n\tBloodRitual,\r\n\tNova,\r\n\tInvisibility,\r\n\tInferno,\r\n\tGolem,\r\n\tRage,\r\n\tTeleport,\r\n\tApocalypse,\r\n\tEtherealize,\r\n\tItemRepair,\r\n\tStaffRecharge,\r\n\tTrapDisarm,\r\n\tElemental,\r\n\tChargedBolt,\r\n\tHolyBolt,\r\n\tResurrect,\r\n\tTelekinesis,\r\n\tHealOther,\r\n\tBloodStar,\r\n\tBoneSpirit,\r\n\tLastDiablo = BoneSpirit,\r\n\tMana,\r\n\tMagi,\r\n\tJester,\r\n\tLightningWall,\r\n\tImmolation,\r\n\tWarp,\r\n\tReflect,\r\n\tBerserk,\r\n\tRingOfFire,\r\n\tSearch,\r\n\tRuneOfFire,\r\n\tRuneOfLight,\r\n\tRuneOfNova,\r\n\tRuneOfImmolation,\r\n\tRuneOfStone,\r\n\r\n\tLAST = RuneOfStone,\r\n\tInvalid = -1,\r\n};\r\n\r\ntl::expected<SpellID, std::string> ParseSpellId(std::string_view value);\r\n\r\nenum class MagicType : uint8_t {\r\n\tFire,\r\n\tLightning,\r\n\tMagic,\r\n};\r\n\r\nenum class MissileID : int8_t {\r\n\t// clang-format off\r\n\tArrow,\r\n\tFirebolt,\r\n\tGuardian,\r\n\tPhasing,\r\n\tNovaBall,\r\n\tFireWall,\r\n\tFireball,\r\n\tLightningControl,\r\n\tLightning,\r\n\tMagmaBallExplosion,\r\n\tTownPortal,\r\n\tFlashBottom,\r\n\tFlashTop,\r\n\tManaShield,\r\n\tFlameWave,\r\n\tChainLightning,\r\n\tChainBall, // unused\r\n\tBloodHit, // unused\r\n\tBoneHit, // unused\r\n\tMetalHit, // unused\r\n\tRhino,\r\n\tMagmaBall,\r\n\tThinLightningControl,\r\n\tThinLightning,\r\n\tBloodStar,\r\n\tBloodStarExplosion,\r\n\tTeleport,\r\n\tFireArrow,\r\n\tDoomSerpents, // unused\r\n\tFireOnly, // unused\r\n\tStoneCurse,\r\n\tBloodRitual, // unused\r\n\tInvisibility, // unused\r\n\tGolem,\r\n\tEtherealize,\r\n\tSpurt, // unused\r\n\tApocalypseBoom,\r\n\tHealing,\r\n\tFireWallControl,\r\n\tInfravision,\r\n\tIdentify,\r\n\tFlameWaveControl,\r\n\tNova,\r\n\tRage, // BloodBoil in Diablo\r\n\tApocalypse,\r\n\tItemRepair,\r\n\tStaffRecharge,\r\n\tTrapDisarm,\r\n\tInferno,\r\n\tInfernoControl,\r\n\tFireMan, // unused\r\n\tKrull, // unused\r\n\tChargedBolt,\r\n\tHolyBolt,\r\n\tResurrect,\r\n\tTelekinesis,\r\n\tLightningArrow,\r\n\tAcid,\r\n\tAcidSplat,\r\n\tAcidPuddle,\r\n\tHealOther,\r\n\tElemental,\r\n\tResurrectBeam,\r\n\tBoneSpirit,\r\n\tWeaponExplosion,\r\n\tRedPortal,\r\n\tDiabloApocalypseBoom,\r\n\tDiabloApocalypse,\r\n\tLastDiablo = DiabloApocalypse,\r\n\tMana,\r\n\tMagi,\r\n\tLightningWall,\r\n\tLightningWallControl,\r\n\tImmolation,\r\n\tSpectralArrow,\r\n\tFireballBow,\r\n\tLightningBow,\r\n\tChargedBoltBow,\r\n\tHolyBoltBow,\r\n\tWarp,\r\n\tReflect,\r\n\tBerserk,\r\n\tRingOfFire,\r\n\tStealPotions,\r\n\tStealMana,\r\n\tRingOfLightning, // unused\r\n\tSearch,\r\n\tAura, // unused\r\n\tAura2, // unused\r\n\tSpiralFireball, // unused\r\n\tRuneOfFire,\r\n\tRuneOfLight,\r\n\tRuneOfNova,\r\n\tRuneOfImmolation,\r\n\tRuneOfStone,\r\n\tBigExplosion,\r\n\tHorkSpawn,\r\n\tJester,\r\n\tOpenNest,\r\n\tOrangeFlare,\r\n\tBlueFlare,\r\n\tRedFlare,\r\n\tYellowFlare,\r\n\tBlueFlare2,\r\n\tYellowExplosion,\r\n\tRedExplosion,\r\n\tBlueExplosion,\r\n\tBlueExplosion2,\r\n\tOrangeExplosion,\r\n\r\n\tLAST = OrangeExplosion,\r\n\tNull = -1,\r\n\t// clang-format on\r\n};\r\n\r\nenum class SpellDataFlags : uint8_t {\r\n\t// The lower 2 bytes are used to store MagicType.\r\n\tFire = static_cast<uint8_t>(MagicType::Fire),\r\n\tLightning = static_cast<uint8_t>(MagicType::Lightning),\r\n\tMagic = static_cast<uint8_t>(MagicType::Magic),\r\n\tTargeted = 1U << 2,\r\n\tAllowedInTown = 1U << 3,\r\n};\r\nuse_enum_as_flags(SpellDataFlags);\r\n\r\nstruct SpellData {\r\n\tstd::string sNameText;\r\n\tSfxID sSFX;\r\n\tuint16_t bookCost10;\r\n\tuint8_t staffCost10;\r\n\tuint8_t sManaCost;\r\n\tSpellDataFlags flags;\r\n\tint8_t sBookLvl;\r\n\tint8_t sStaffLvl;\r\n\tuint8_t minInt;\r\n\tMissileID sMissiles[2];\r\n\tuint8_t sManaAdj;\r\n\tuint8_t sMinMana;\r\n\tuint8_t sStaffMin;\r\n\tuint8_t sStaffMax;\r\n\r\n\t[[nodiscard]] MagicType type() const\r\n\t{\r\n\t\treturn static_cast<MagicType>(static_cast<std::underlying_type<SpellDataFlags>::type>(flags) & 0b11U);\r\n\t}\r\n\r\n\t[[nodiscard]] uint32_t bookCost() const\r\n\t{\r\n\t\treturn bookCost10 * 10;\r\n\t}\r\n\r\n\t[[nodiscard]] uint16_t staffCost() const\r\n\t{\r\n\t\treturn staffCost10 * 10;\r\n\t}\r\n\r\n\t[[nodiscard]] bool isTargeted() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, SpellDataFlags::Targeted);\r\n\t}\r\n\r\n\t[[nodiscard]] bool isAllowedInTown() const\r\n\t{\r\n\t\treturn HasAnyOf(flags, SpellDataFlags::AllowedInTown);\r\n\t}\r\n};\r\n\r\nextern std::vector<SpellData> SpellsData;\r\n\r\ninline const SpellData &GetSpellData(SpellID spellId)\r\n{\r\n\treturn SpellsData[static_cast<std::underlying_type<SpellID>::type>(spellId)];\r\n}\r\n\r\nvoid LoadSpellData();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/textdat.cpp",
    "content": "/**\r\n * @file textdat.cpp\r\n *\r\n * Implementation of all dialog texts.\r\n */\r\n#include \"tables/textdat.h\"\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <fmt/core.h>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n#include \"effects.h\"\r\n#include \"utils/language.h\"\r\n\r\nnamespace devilution {\r\n\r\n/* todo: move text out of struct */\r\n\r\n/** Contains the data related to each speech ID. */\r\nstd::vector<Speech> Speeches;\r\n\r\n/** Contains the mapping between text ID strings and indices, used for parsing additional text data. */\r\nankerl::unordered_dense::map<std::string, int16_t> AdditionalTextIdStringsToIndices;\r\n\r\ntl::expected<_speech_id, std::string> ParseSpeechId(std::string_view value)\r\n{\r\n\tif (value.empty()) {\r\n\t\treturn TEXT_NONE;\r\n\t}\r\n\r\n\tconst std::optional<_speech_id> enumValueOpt = magic_enum::enum_cast<_speech_id>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\r\n\tconst auto findIt = AdditionalTextIdStringsToIndices.find(std::string(value));\r\n\tif (findIt != AdditionalTextIdStringsToIndices.end()) {\r\n\t\treturn static_cast<_speech_id>(findIt->second);\r\n\t}\r\n\r\n\treturn tl::make_unexpected(\"Invalid value.\");\r\n}\r\n\r\nnamespace {\r\n\r\nvoid LoadTextDatFromFile(DataFile &dataFile, std::string_view filename, bool grow)\r\n{\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tif (grow) {\r\n\t\tSpeeches.reserve(Speeches.size() + dataFile.numRecords());\r\n\t}\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\r\n\t\tstd::string txtstrid;\r\n\t\treader.readString(\"txtstrid\", txtstrid);\r\n\r\n\t\tif (txtstrid.empty()) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst std::optional<_speech_id> speechIdEnumValueOpt = magic_enum::enum_cast<_speech_id>(txtstrid);\r\n\r\n\t\tif (!speechIdEnumValueOpt.has_value()) {\r\n\t\t\tconst size_t textEntryIndex = Speeches.size();\r\n\t\t\tconst auto [it, inserted] = AdditionalTextIdStringsToIndices.emplace(txtstrid, static_cast<int16_t>(textEntryIndex));\r\n\t\t\tif (!inserted) {\r\n\t\t\t\tDisplayFatalErrorAndExit(_(\"Loading Text Data Failed\"), fmt::format(fmt::runtime(_(\"A text data entry already exists for ID \\\"{}\\\".\")), txtstrid));\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// for hardcoded speeches, use their predetermined slot; for non-hardcoded ones, use the slots after that\r\n\t\tSpeech &speech = speechIdEnumValueOpt.has_value() ? Speeches[speechIdEnumValueOpt.value()] : Speeches.emplace_back();\r\n\r\n\t\treader.readString(\"txtstr\", speech.txtstr);\r\n\r\n\t\t{\r\n\t\t\tstd::string processed;\r\n\t\t\tprocessed.reserve(speech.txtstr.size());\r\n\t\t\tfor (size_t i = 0; i < speech.txtstr.size();) {\r\n\t\t\t\tif (i + 1 < speech.txtstr.size() && speech.txtstr[i] == '\\\\' && speech.txtstr[i + 1] == 'n') {\r\n\t\t\t\t\tprocessed.push_back('\\n');\r\n\t\t\t\t\ti += 2;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tprocessed.push_back(speech.txtstr[i]);\r\n\t\t\t\t\t++i;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tspeech.txtstr = std::move(processed);\r\n\t\t}\r\n\r\n\t\treader.readBool(\"scrlltxt\", speech.scrlltxt);\r\n\t\treader.read(\"sfxnr\", speech.sfxnr, ParseSfxId);\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadTextData()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\text\\\\textdat.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\r\n\tSpeeches.clear();\r\n\tAdditionalTextIdStringsToIndices.clear();\r\n\tSpeeches.resize(NUM_DEFAULT_TEXT_IDS); // ensure the hardcoded text entry slots are filled\r\n\tLoadTextDatFromFile(dataFile, filename, false);\r\n\r\n\tSpeeches.shrink_to_fit();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/textdat.h",
    "content": "/**\r\n * @file textdat.h\r\n *\r\n * Interface of all dialog texts.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\n#include <expected.hpp>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"sound_effect_enums.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum _speech_id : int16_t {\r\n\tTEXT_KING1,\r\n\tTEXT_KING2,\r\n\tTEXT_KING3,\r\n\tTEXT_KING4,\r\n\tTEXT_KING5,\r\n\tTEXT_KING6,\r\n\tTEXT_KING7,\r\n\tTEXT_KING8,\r\n\tTEXT_KING9,\r\n\tTEXT_KING10,\r\n\tTEXT_KING11,\r\n\tTEXT_BANNER1,\r\n\tTEXT_BANNER2,\r\n\tTEXT_BANNER3,\r\n\tTEXT_BANNER4,\r\n\tTEXT_BANNER5,\r\n\tTEXT_BANNER6,\r\n\tTEXT_BANNER7,\r\n\tTEXT_BANNER8,\r\n\tTEXT_BANNER9,\r\n\tTEXT_BANNER10,\r\n\tTEXT_BANNER11,\r\n\tTEXT_BANNER12,\r\n\tTEXT_VILE1,\r\n\tTEXT_VILE2,\r\n\tTEXT_VILE3,\r\n\tTEXT_VILE4,\r\n\tTEXT_VILE5,\r\n\tTEXT_VILE6,\r\n\tTEXT_VILE7,\r\n\tTEXT_VILE8,\r\n\tTEXT_VILE9,\r\n\tTEXT_VILE10,\r\n\tTEXT_VILE11,\r\n\tTEXT_VILE12,\r\n\tTEXT_VILE13,\r\n\tTEXT_VILE14,\r\n\tTEXT_POISON1,\r\n\tTEXT_POISON2,\r\n\tTEXT_POISON3,\r\n\tTEXT_POISON4,\r\n\tTEXT_POISON5,\r\n\tTEXT_POISON6,\r\n\tTEXT_POISON7,\r\n\tTEXT_POISON8,\r\n\tTEXT_POISON9,\r\n\tTEXT_POISON10,\r\n\tTEXT_BONE1,\r\n\tTEXT_BONE2,\r\n\tTEXT_BONE3,\r\n\tTEXT_BONE4,\r\n\tTEXT_BONE5,\r\n\tTEXT_BONE6,\r\n\tTEXT_BONE7,\r\n\tTEXT_BONE8,\r\n\tTEXT_BUTCH1,\r\n\tTEXT_BUTCH2,\r\n\tTEXT_BUTCH3,\r\n\tTEXT_BUTCH4,\r\n\tTEXT_BUTCH5,\r\n\tTEXT_BUTCH6,\r\n\tTEXT_BUTCH7,\r\n\tTEXT_BUTCH8,\r\n\tTEXT_BUTCH9,\r\n\tTEXT_BUTCH10,\r\n\tTEXT_BLIND1,\r\n\tTEXT_BLIND2,\r\n\tTEXT_BLIND3,\r\n\tTEXT_BLIND4,\r\n\tTEXT_BLIND5,\r\n\tTEXT_BLIND6,\r\n\tTEXT_BLIND7,\r\n\tTEXT_BLIND8,\r\n\tTEXT_VEIL1,\r\n\tTEXT_VEIL2,\r\n\tTEXT_VEIL3,\r\n\tTEXT_VEIL4,\r\n\tTEXT_VEIL5,\r\n\tTEXT_VEIL6,\r\n\tTEXT_VEIL7,\r\n\tTEXT_VEIL8,\r\n\tTEXT_VEIL9,\r\n\tTEXT_VEIL10,\r\n\tTEXT_VEIL11,\r\n\tTEXT_ANVIL1,\r\n\tTEXT_ANVIL2,\r\n\tTEXT_ANVIL3,\r\n\tTEXT_ANVIL4,\r\n\tTEXT_ANVIL5,\r\n\tTEXT_ANVIL6,\r\n\tTEXT_ANVIL7,\r\n\tTEXT_ANVIL8,\r\n\tTEXT_ANVIL9,\r\n\tTEXT_ANVIL10,\r\n\tTEXT_BLOOD1,\r\n\tTEXT_BLOOD2,\r\n\tTEXT_BLOOD3,\r\n\tTEXT_BLOOD4,\r\n\tTEXT_BLOOD5,\r\n\tTEXT_BLOOD6,\r\n\tTEXT_BLOOD7,\r\n\tTEXT_BLOOD8,\r\n\tTEXT_WARLRD1,\r\n\tTEXT_WARLRD2,\r\n\tTEXT_WARLRD3,\r\n\tTEXT_WARLRD4,\r\n\tTEXT_WARLRD5,\r\n\tTEXT_WARLRD6,\r\n\tTEXT_WARLRD7,\r\n\tTEXT_WARLRD8,\r\n\tTEXT_WARLRD9,\r\n\tTEXT_INFRA1,\r\n\tTEXT_INFRA2,\r\n\tTEXT_INFRA3,\r\n\tTEXT_INFRA4,\r\n\tTEXT_INFRA5,\r\n\tTEXT_INFRA6,\r\n\tTEXT_INFRA7,\r\n\tTEXT_INFRA8,\r\n\tTEXT_INFRA9,\r\n\tTEXT_INFRA10,\r\n\tTEXT_MUSH1,\r\n\tTEXT_MUSH2,\r\n\tTEXT_MUSH3,\r\n\tTEXT_MUSH4,\r\n\tTEXT_MUSH5,\r\n\tTEXT_MUSH6,\r\n\tTEXT_MUSH7,\r\n\tTEXT_MUSH8,\r\n\tTEXT_MUSH9,\r\n\tTEXT_MUSH10,\r\n\tTEXT_MUSH11,\r\n\tTEXT_MUSH12,\r\n\tTEXT_MUSH13,\r\n\tTEXT_DOOM1,\r\n\tTEXT_DOOM2,\r\n\tTEXT_DOOM3,\r\n\tTEXT_DOOM4,\r\n\tTEXT_DOOM5,\r\n\tTEXT_DOOM6,\r\n\tTEXT_DOOM7,\r\n\tTEXT_DOOM8,\r\n\tTEXT_DOOM9,\r\n\tTEXT_DOOM10,\r\n\tTEXT_GARBUD1,\r\n\tTEXT_GARBUD2,\r\n\tTEXT_GARBUD3,\r\n\tTEXT_GARBUD4,\r\n\tTEXT_ZHAR1,\r\n\tTEXT_ZHAR2,\r\n\tTEXT_STORY1,\r\n\tTEXT_STORY2,\r\n\tTEXT_STORY3,\r\n\tTEXT_STORY4,\r\n\tTEXT_STORY5,\r\n\tTEXT_STORY6,\r\n\tTEXT_STORY7,\r\n\tTEXT_STORY9,\r\n\tTEXT_STORY10,\r\n\tTEXT_STORY11,\r\n\tTEXT_OGDEN1,\r\n\tTEXT_OGDEN2,\r\n\tTEXT_OGDEN3,\r\n\tTEXT_OGDEN4,\r\n\tTEXT_OGDEN5,\r\n\tTEXT_OGDEN6,\r\n\tTEXT_OGDEN8,\r\n\tTEXT_OGDEN9,\r\n\tTEXT_OGDEN10,\r\n\tTEXT_PEPIN1,\r\n\tTEXT_PEPIN2,\r\n\tTEXT_PEPIN3,\r\n\tTEXT_PEPIN4,\r\n\tTEXT_PEPIN5,\r\n\tTEXT_PEPIN6,\r\n\tTEXT_PEPIN7,\r\n\tTEXT_PEPIN9,\r\n\tTEXT_PEPIN10,\r\n\tTEXT_PEPIN11,\r\n\tTEXT_GILLIAN1,\r\n\tTEXT_GILLIAN2,\r\n\tTEXT_GILLIAN3,\r\n\tTEXT_GILLIAN4,\r\n\tTEXT_GILLIAN5,\r\n\tTEXT_GILLIAN6,\r\n\tTEXT_GILLIAN7,\r\n\tTEXT_GILLIAN9,\r\n\tTEXT_GILLIAN10,\r\n\tTEXT_GRISWOLD1,\r\n\tTEXT_GRISWOLD2,\r\n\tTEXT_GRISWOLD3,\r\n\tTEXT_GRISWOLD4,\r\n\tTEXT_GRISWOLD5,\r\n\tTEXT_GRISWOLD6,\r\n\tTEXT_GRISWOLD7,\r\n\tTEXT_GRISWOLD8,\r\n\tTEXT_GRISWOLD9,\r\n\tTEXT_GRISWOLD10,\r\n\tTEXT_GRISWOLD12,\r\n\tTEXT_GRISWOLD13,\r\n\tTEXT_FARNHAM1,\r\n\tTEXT_FARNHAM2,\r\n\tTEXT_FARNHAM3,\r\n\tTEXT_FARNHAM4,\r\n\tTEXT_FARNHAM5,\r\n\tTEXT_FARNHAM6,\r\n\tTEXT_FARNHAM8,\r\n\tTEXT_FARNHAM9,\r\n\tTEXT_FARNHAM10,\r\n\tTEXT_FARNHAM11,\r\n\tTEXT_FARNHAM12,\r\n\tTEXT_FARNHAM13,\r\n\tTEXT_ADRIA1,\r\n\tTEXT_ADRIA2,\r\n\tTEXT_ADRIA3,\r\n\tTEXT_ADRIA4,\r\n\tTEXT_ADRIA5,\r\n\tTEXT_ADRIA6,\r\n\tTEXT_ADRIA7,\r\n\tTEXT_ADRIA8,\r\n\tTEXT_ADRIA9,\r\n\tTEXT_ADRIA10,\r\n\tTEXT_ADRIA12,\r\n\tTEXT_ADRIA13,\r\n\tTEXT_WIRT1,\r\n\tTEXT_WIRT2,\r\n\tTEXT_WIRT3,\r\n\tTEXT_WIRT4,\r\n\tTEXT_WIRT5,\r\n\tTEXT_WIRT6,\r\n\tTEXT_WIRT7,\r\n\tTEXT_WIRT8,\r\n\tTEXT_WIRT9,\r\n\tTEXT_WIRT11,\r\n\tTEXT_WIRT12,\r\n\tTEXT_BONER,\r\n\tTEXT_BLOODY,\r\n\tTEXT_BLINDING,\r\n\tTEXT_BLOODWAR,\r\n\tTEXT_MBONER,\r\n\tTEXT_MBLOODY,\r\n\tTEXT_MBLINDING,\r\n\tTEXT_MBLOODWAR,\r\n\tTEXT_RBONER,\r\n\tTEXT_RBLOODY,\r\n\tTEXT_RBLINDING,\r\n\tTEXT_RBLOODWAR,\r\n\tTEXT_COW1,\r\n\tTEXT_COW2,\r\n\tTEXT_BOOK11,\r\n\tTEXT_BOOK12,\r\n\tTEXT_BOOK13,\r\n\tTEXT_BOOK21,\r\n\tTEXT_BOOK22,\r\n\tTEXT_BOOK23,\r\n\tTEXT_BOOK31,\r\n\tTEXT_BOOK32,\r\n\tTEXT_BOOK33,\r\n\tTEXT_INTRO,\r\n\tTEXT_HBONER,\r\n\tTEXT_HBLOODY,\r\n\tTEXT_HBLINDING,\r\n\tTEXT_HBLOODWAR,\r\n\tTEXT_BBONER,\r\n\tTEXT_BBLOODY,\r\n\tTEXT_BBLINDING,\r\n\tTEXT_BBLOODWAR,\r\n\tTEXT_GRAVE1,\r\n\tTEXT_GRAVE2,\r\n\tTEXT_GRAVE3,\r\n\tTEXT_GRAVE4,\r\n\tTEXT_GRAVE5,\r\n\tTEXT_GRAVE6,\r\n\tTEXT_GRAVE7,\r\n\tTEXT_GRAVE8,\r\n\tTEXT_GRAVE9,\r\n\tTEXT_GRAVE10,\r\n\tTEXT_FARMER1,\r\n\tTEXT_FARMER2,\r\n\tTEXT_FARMER3,\r\n\tTEXT_FARMER4,\r\n\tTEXT_FARMER5,\r\n\tTEXT_GIRL1,\r\n\tTEXT_GIRL2,\r\n\tTEXT_GIRL3,\r\n\tTEXT_GIRL4,\r\n\tTEXT_DEFILER1,\r\n\tTEXT_DEFILER2,\r\n\tTEXT_DEFILER3,\r\n\tTEXT_DEFILER4,\r\n\tTEXT_DEFILER5,\r\n\tTEXT_NAKRUL1,\r\n\tTEXT_NAKRUL2,\r\n\tTEXT_NAKRUL3,\r\n\tTEXT_NAKRUL4,\r\n\tTEXT_NAKRUL5,\r\n\tTEXT_CORNSTN,\r\n\tTEXT_JERSEY1,\r\n\tTEXT_JERSEY2,\r\n\tTEXT_JERSEY3,\r\n\tTEXT_JERSEY4,\r\n\tTEXT_JERSEY5,\r\n\tTEXT_JERSEY6,\r\n\tTEXT_JERSEY7,\r\n\tTEXT_JERSEY8,\r\n\tTEXT_JERSEY9,\r\n\tTEXT_TRADER,\r\n\tTEXT_FARMER6,\r\n\tTEXT_FARMER7,\r\n\tTEXT_FARMER8,\r\n\tTEXT_FARMER9,\r\n\tTEXT_FARMER10,\r\n\tTEXT_JERSEY10,\r\n\tTEXT_JERSEY11,\r\n\tTEXT_JERSEY12,\r\n\tTEXT_JERSEY13,\r\n\tTEXT_SKLJRN,\r\n\tTEXT_BOOK4,\r\n\tTEXT_BOOK5,\r\n\tTEXT_BOOK6,\r\n\tTEXT_BOOK7,\r\n\tTEXT_BOOK8,\r\n\tTEXT_BOOK9,\r\n\tTEXT_BOOKA,\r\n\tTEXT_BOOKB,\r\n\tTEXT_BOOKC,\r\n\tTEXT_OBOOKA,\r\n\tTEXT_OBOOKB,\r\n\tTEXT_OBOOKC,\r\n\tTEXT_MBOOKA,\r\n\tTEXT_MBOOKB,\r\n\tTEXT_MBOOKC,\r\n\tTEXT_RBOOKA,\r\n\tTEXT_RBOOKB,\r\n\tTEXT_RBOOKC,\r\n\tTEXT_BBOOKA,\r\n\tTEXT_BBOOKB,\r\n\tTEXT_BBOOKC,\r\n\tTEXT_DEADGUY,\r\n\tTEXT_FARNHAM14,\r\n\tTEXT_FARNHAM15,\r\n\tTEXT_FARNHAM16,\r\n\tTEXT_FARNHAM17,\r\n\tTEXT_FARNHAM18,\r\n\tTEXT_FARNHAM19,\r\n\tTEXT_FARNHAM20,\r\n\tTEXT_FARNHAM21,\r\n\tTEXT_FARNHAM22,\r\n\tTEXT_GILLIAN11,\r\n\tTEXT_GILLIAN12,\r\n\tTEXT_GILLIAN13,\r\n\tTEXT_GILLIAN14,\r\n\tTEXT_GILLIAN15,\r\n\tTEXT_GILLIAN16,\r\n\tTEXT_GILLIAN17,\r\n\tTEXT_GILLIAN18,\r\n\tTEXT_GILLIAN19,\r\n\tTEXT_GILLIAN20,\r\n\tTEXT_GILLIAN21,\r\n\tTEXT_GILLIAN22,\r\n\tTEXT_GILLIAN23,\r\n\tTEXT_GILLIAN24,\r\n\tTEXT_GILLIAN25,\r\n\tTEXT_GILLIAN26,\r\n\tTEXT_PEPIN12,\r\n\tTEXT_PEPIN13,\r\n\tTEXT_PEPIN14,\r\n\tTEXT_PEPIN15,\r\n\tTEXT_PEPIN16,\r\n\tTEXT_PEPIN17,\r\n\tTEXT_PEPIN18,\r\n\tTEXT_PEPIN19,\r\n\tTEXT_PEPIN20,\r\n\tTEXT_PEPIN21,\r\n\tTEXT_PEPIN22,\r\n\tTEXT_PEPIN23,\r\n\tTEXT_PEPIN24,\r\n\tTEXT_PEPIN25,\r\n\tTEXT_PEPIN26,\r\n\tTEXT_PEPIN27,\r\n\tTEXT_PEPIN28,\r\n\tTEXT_PEPIN29,\r\n\tTEXT_PEPIN30,\r\n\tTEXT_GRISWOLD14,\r\n\tTEXT_GRISWOLD15,\r\n\tTEXT_GRISWOLD16,\r\n\tTEXT_GRISWOLD17,\r\n\tTEXT_GRISWOLD18,\r\n\tTEXT_GRISWOLD19,\r\n\tTEXT_GRISWOLD20,\r\n\tTEXT_GRISWOLD21,\r\n\tTEXT_GRISWOLD22,\r\n\tTEXT_GRISWOLD23,\r\n\tTEXT_GRISWOLD24,\r\n\tTEXT_GRISWOLD25,\r\n\tTEXT_GRISWOLD26,\r\n\tTEXT_GRISWOLD27,\r\n\tTEXT_GRISWOLD28,\r\n\tTEXT_GRISWOLD29,\r\n\tTEXT_GRISWOLD30,\r\n\tTEXT_GRISWOLD31,\r\n\tTEXT_GRISWOLD32,\r\n\tTEXT_GRISWOLD33,\r\n\tTEXT_GRISWOLD34,\r\n\tTEXT_GRISWOLD35,\r\n\tTEXT_GRISWOLD36,\r\n\tTEXT_GRISWOLD37,\r\n\tNUM_DEFAULT_TEXT_IDS,\r\n\tTEXT_NONE = -1,\r\n};\r\n\r\nstruct Speech {\r\n\tstd::string txtstr;\r\n\tbool scrlltxt;\r\n\tSfxID sfxnr;\r\n};\r\n\r\nextern std::vector<Speech> Speeches;\r\n\r\ntl::expected<_speech_id, std::string> ParseSpeechId(std::string_view value);\r\n\r\nvoid LoadTextData();\r\n\r\n} // namespace devilution\r\n\r\ntemplate <>\r\nstruct magic_enum::customize::enum_range<devilution::_speech_id> {\r\n\tstatic constexpr int min = devilution::TEXT_NONE;\r\n\tstatic constexpr int max = devilution::NUM_DEFAULT_TEXT_IDS;\r\n};\r\n"
  },
  {
    "path": "Source/tables/townerdat.cpp",
    "content": "/**\r\n * @file townerdat.cpp\r\n *\r\n * Implementation of towner data loading from TSV files.\r\n */\r\n#include \"tables/townerdat.hpp\"\r\n\r\n#include <charconv>\r\n#include <optional>\r\n#include <string_view>\r\n#include <unordered_map>\r\n#include <vector>\r\n\r\n#include <expected.hpp>\r\n#include <magic_enum/magic_enum.hpp>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/record_reader.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::vector<TownerDataEntry> TownersDataEntries;\r\nstd::unordered_map<_talker_id, std::array<_speech_id, MAXQUESTS>> TownerQuestDialogTable;\r\n\r\nnamespace {\r\n\r\n/**\r\n * @brief Generic enum parser using magic_enum.\r\n * @tparam EnumT The enum type to parse\r\n * @param value The string representation of the enum value\r\n * @return The parsed enum value, or an error message\r\n */\r\ntemplate <typename EnumT>\r\ntl::expected<EnumT, std::string> ParseEnum(std::string_view value)\r\n{\r\n\tconst auto enumValueOpt = magic_enum::enum_cast<EnumT>(value);\r\n\tif (enumValueOpt.has_value()) {\r\n\t\treturn enumValueOpt.value();\r\n\t}\r\n\treturn tl::make_unexpected(\"Unknown enum value\");\r\n}\r\n\r\n/**\r\n * @brief Parses a comma-separated list of values.\r\n * @tparam T The output type\r\n * @tparam Parser A callable that converts string_view to optional<T>\r\n * @param value The comma-separated string\r\n * @param out Vector to store parsed values (cleared first)\r\n * @param parser Function to parse individual tokens\r\n */\r\ntemplate <typename T, typename Parser>\r\nvoid ParseCommaSeparatedList(std::string_view value, std::vector<T> &out, Parser parser)\r\n{\r\n\tout.clear();\r\n\tif (value.empty()) return;\r\n\r\n\tsize_t start = 0;\r\n\twhile (start < value.size()) {\r\n\t\tsize_t end = value.find(',', start);\r\n\t\tif (end == std::string_view::npos) end = value.size();\r\n\r\n\t\tstd::string_view token = value.substr(start, end - start);\r\n\t\tif (auto result = parser(token)) {\r\n\t\t\tout.push_back(*result);\r\n\t\t}\r\n\r\n\t\tstart = end + 1;\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Parses a comma-separated list of speech IDs.\r\n */\r\nvoid ParseGossipTexts(std::string_view value, std::vector<_speech_id> &out)\r\n{\r\n\tParseCommaSeparatedList(value, out, [](std::string_view token) -> std::optional<_speech_id> {\r\n\t\tif (auto result = ParseSpeechId(token); result.has_value()) {\r\n\t\t\treturn result.value();\r\n\t\t}\r\n\t\treturn std::nullopt;\r\n\t});\r\n}\r\n\r\n/**\r\n * @brief Parses a comma-separated list of integers for animation frame order.\r\n */\r\nvoid ParseAnimOrder(std::string_view value, std::vector<uint8_t> &out)\r\n{\r\n\tParseCommaSeparatedList(value, out, [](std::string_view token) -> std::optional<uint8_t> {\r\n\t\tint val = 0;\r\n\t\tif (auto [ptr, ec] = std::from_chars(token.data(), token.data() + token.size(), val); ec == std::errc()) {\r\n\t\t\treturn static_cast<uint8_t>(val);\r\n\t\t}\r\n\t\treturn std::nullopt;\r\n\t});\r\n}\r\n\r\nvoid LoadTownersFromFile()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\towners\\\\towners.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\tTownersDataEntries.clear();\r\n\tTownersDataEntries.reserve(dataFile.numRecords());\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tRecordReader reader { record, filename };\r\n\t\tTownerDataEntry &entry = TownersDataEntries.emplace_back();\r\n\r\n\t\treader.read(\"type\", entry.type, ParseEnum<_talker_id>);\r\n\t\treader.readString(\"name\", entry.name);\r\n\t\treader.readInt(\"position_x\", entry.position.x);\r\n\t\treader.readInt(\"position_y\", entry.position.y);\r\n\t\treader.read(\"direction\", entry.direction, ParseEnum<Direction>);\r\n\t\treader.readInt(\"animWidth\", entry.animWidth);\r\n\t\treader.readString(\"animPath\", entry.animPath);\r\n\t\treader.readOptionalInt(\"animFrames\", entry.animFrames);\r\n\t\treader.readOptionalInt(\"animDelay\", entry.animDelay);\r\n\r\n\t\tstd::string gossipStr;\r\n\t\treader.readString(\"gossipTexts\", gossipStr);\r\n\t\tParseGossipTexts(gossipStr, entry.gossipTexts);\r\n\r\n\t\tstd::string animOrderStr;\r\n\t\treader.readString(\"animOrder\", animOrderStr);\r\n\t\tParseAnimOrder(animOrderStr, entry.animOrder);\r\n\t}\r\n\r\n\tTownersDataEntries.shrink_to_fit();\r\n}\r\n\r\nvoid LoadQuestDialogFromFile()\r\n{\r\n\tconst std::string_view filename = \"txtdata\\\\towners\\\\quest_dialog.tsv\";\r\n\tDataFile dataFile = DataFile::loadOrDie(filename);\r\n\r\n\t// Initialize table (will be populated as we read rows)\r\n\tTownerQuestDialogTable.clear();\r\n\r\n\t// Parse header to find which quest columns exist\r\n\t// Store the iterator to avoid temporary lifetime issues\r\n\tauto headerIt = dataFile.begin();\r\n\tDataFileRecord headerRecord = *headerIt;\r\n\tstd::unordered_map<std::string, unsigned> columnMap;\r\n\tunsigned columnIndex = 0;\r\n\tfor (DataFileField field : headerRecord) {\r\n\t\tcolumnMap[std::string(field.value())] = columnIndex++;\r\n\t}\r\n\r\n\t// Reset header position and skip for data reading\r\n\tdataFile.resetHeader();\r\n\tdataFile.skipHeaderOrDie(filename);\r\n\r\n\t// Find the towner_type column index\r\n\tif (!columnMap.contains(\"towner_type\")) {\r\n\t\treturn; // Invalid file format\r\n\t}\r\n\tunsigned townerTypeColIndex = columnMap[\"towner_type\"];\r\n\r\n\t// Build quest column index map\r\n\tstd::unordered_map<quest_id, unsigned> questColumnMap;\r\n\tfor (quest_id quest : magic_enum::enum_values<quest_id>()) {\r\n\t\tif (quest == Q_INVALID || quest >= MAXQUESTS) continue;\r\n\r\n\t\tauto questName = std::string(magic_enum::enum_name(quest));\r\n\t\tif (columnMap.contains(questName)) {\r\n\t\t\tquestColumnMap[quest] = columnMap[questName];\r\n\t\t}\r\n\t}\r\n\r\n\t// Read data rows\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\t// Read all fields into a map keyed by column index for indexed access\r\n\t\tstd::unordered_map<unsigned, std::string_view> fields;\r\n\t\tfor (DataFileField field : record) {\r\n\t\t\tfields[field.column()] = field.value();\r\n\t\t}\r\n\r\n\t\t// Read towner_type\r\n\t\tif (!fields.contains(townerTypeColIndex)) {\r\n\t\t\tcontinue; // Invalid row\r\n\t\t}\r\n\r\n\t\tauto townerTypeResult = ParseEnum<_talker_id>(fields[townerTypeColIndex]);\r\n\t\tif (!townerTypeResult.has_value()) {\r\n\t\t\tcontinue; // Invalid towner type\r\n\t\t}\r\n\t\t_talker_id townerType = townerTypeResult.value();\r\n\r\n\t\t// Initialize row if it doesn't exist, then get reference\r\n\t\tauto [it, inserted] = TownerQuestDialogTable.try_emplace(townerType);\r\n\t\tif (inserted) {\r\n\t\t\tit->second.fill(TEXT_NONE);\r\n\t\t}\r\n\t\tauto &dialogRow = it->second;\r\n\r\n\t\t// Read quest columns that exist in this file\r\n\t\tfor (const auto &[quest, colIndex] : questColumnMap) {\r\n\t\t\tif (!fields.contains(colIndex)) {\r\n\t\t\t\tcontinue; // Column missing in this row\r\n\t\t\t}\r\n\r\n\t\t\tauto speechResult = ParseSpeechId(fields[colIndex]);\r\n\t\t\tif (speechResult.has_value()) {\r\n\t\t\t\tdialogRow[quest] = speechResult.value();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nvoid LoadTownerData()\r\n{\r\n\tLoadTownersFromFile();\r\n\tLoadQuestDialogFromFile();\r\n}\r\n\r\n_speech_id GetTownerQuestDialog(_talker_id type, quest_id quest)\r\n{\r\n\tif (quest < 0 || quest >= MAXQUESTS) {\r\n\t\treturn TEXT_NONE;\r\n\t}\r\n\tauto it = TownerQuestDialogTable.find(type);\r\n\tif (it == TownerQuestDialogTable.end()) {\r\n\t\treturn TEXT_NONE;\r\n\t}\r\n\treturn it->second[quest];\r\n}\r\n\r\nvoid SetTownerQuestDialog(_talker_id type, quest_id quest, _speech_id speech)\r\n{\r\n\tif (quest < 0 || quest >= MAXQUESTS) {\r\n\t\treturn;\r\n\t}\r\n\t// Initialize row if it doesn't exist\r\n\tauto [it, inserted] = TownerQuestDialogTable.try_emplace(type);\r\n\tif (inserted) {\r\n\t\tit->second.fill(TEXT_NONE);\r\n\t}\r\n\tit->second[quest] = speech;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tables/townerdat.hpp",
    "content": "/**\r\n * @file townerdat.hpp\r\n *\r\n * Interface for loading towner data from TSV files.\r\n */\r\n#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <unordered_map>\r\n#include <vector>\r\n\r\n#include \"engine/direction.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"tables/objdat.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"towners.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Data for a single towner entry loaded from TSV.\r\n */\r\nstruct TownerDataEntry {\r\n\t_talker_id type; // Parsed from TSV using magic_enum\r\n\tstd::string name;\r\n\tPoint position;\r\n\tDirection direction;\r\n\tuint16_t animWidth;\r\n\tstd::string animPath;\r\n\tuint8_t animFrames;\r\n\tint16_t animDelay;\r\n\tstd::vector<_speech_id> gossipTexts;\r\n\tstd::vector<uint8_t> animOrder;\r\n};\r\n\r\n/** Contains the data for all towners loaded from TSV. */\r\nextern DVL_API_FOR_TEST std::vector<TownerDataEntry> TownersDataEntries;\r\n\r\n/** Contains the quest dialog table loaded from TSV. Indexed by [towner_type][quest_id]. */\r\nextern std::unordered_map<_talker_id, std::array<_speech_id, MAXQUESTS>> TownerQuestDialogTable;\r\n\r\n/**\r\n * @brief Loads towner data from TSV files.\r\n *\r\n * This function loads data from:\r\n * - txtdata/towners/towners.tsv - Main towner definitions\r\n * - txtdata/towners/quest_dialog.tsv - Quest dialog mappings\r\n */\r\nvoid LoadTownerData();\r\n\r\n/**\r\n * @brief Gets the quest dialog speech ID for a towner and quest combination.\r\n * @param type The towner type\r\n * @param quest The quest ID\r\n * @return The speech ID for the dialog, or TEXT_NONE if not available\r\n */\r\n_speech_id GetTownerQuestDialog(_talker_id type, quest_id quest);\r\n\r\n/**\r\n * @brief Sets the quest dialog speech ID for a towner and quest combination.\r\n * @param type The towner type\r\n * @param quest The quest ID\r\n * @param speech The speech ID to set\r\n */\r\nvoid SetTownerQuestDialog(_talker_id type, quest_id quest, _speech_id speech);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tmsg.cpp",
    "content": "/**\r\n * @file tmsg.cpp\r\n *\r\n * Implementation of functionality transmitting chat messages.\r\n */\r\n#include <cstdint>\r\n#include <list>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"diablo.h\"\r\n#include \"tmsg.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nstruct TMsg {\r\n\tuint32_t time;\r\n\tstd::unique_ptr<std::byte[]> body;\r\n\tuint8_t len;\r\n\r\n\tTMsg(uint32_t time, const std::byte *data, uint8_t len)\r\n\t    : time(time)\r\n\t    , body(new std::byte[len])\r\n\t    , len(len)\r\n\t{\r\n\t\tmemcpy(body.get(), data, len);\r\n\t}\r\n};\r\n\r\nstd::list<TMsg> TimedMsgList;\r\n\r\n} // namespace\r\n\r\nuint8_t tmsg_get(std::unique_ptr<std::byte[]> *msg)\r\n{\r\n\tif (TimedMsgList.empty())\r\n\t\treturn 0;\r\n\r\n\tTMsg &head = TimedMsgList.front();\r\n\tif ((int)(head.time - SDL_GetTicks()) >= 0)\r\n\t\treturn 0;\r\n\r\n\tconst uint8_t len = head.len;\r\n\t*msg = std::move(head.body);\r\n\tTimedMsgList.pop_front();\r\n\treturn len;\r\n}\r\n\r\nvoid tmsg_add(const std::byte *msg, uint8_t len)\r\n{\r\n\tconst uint32_t time = SDL_GetTicks() + gnTickDelay * 10;\r\n\tTimedMsgList.emplace_back(time, msg, len);\r\n}\r\n\r\nvoid tmsg_start()\r\n{\r\n\tassert(TimedMsgList.empty());\r\n}\r\n\r\nvoid tmsg_cleanup()\r\n{\r\n\tTimedMsgList.clear();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/tmsg.h",
    "content": "/**\r\n * @file tmsg.h\r\n *\r\n * Interface of functionality transmitting chat messages.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n\r\nnamespace devilution {\r\n\r\nuint8_t tmsg_get(std::unique_ptr<std::byte[]> *msg);\r\nvoid tmsg_add(const std::byte *msg, uint8_t bLen);\r\nvoid tmsg_start();\r\nvoid tmsg_cleanup();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/towners.cpp",
    "content": "#include \"towners.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <unordered_map>\r\n\r\n#include \"cursor.h\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/load_cel.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"inv.h\"\r\n#include \"minitext.h\"\r\n#include \"stores.h\"\r\n#include \"tables/textdat.h\"\r\n#include \"tables/townerdat.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/language.h\"\r\n#include \"utils/str_case.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nOptionalOwnedClxSpriteSheet CowSprites;\r\nint CowMsg;\r\nint CowClicks;\r\n\r\n/** Specifies the active sound effect ID for interacting with cows. */\r\nSfxID CowPlaying = SfxID::None;\r\n\r\n/** Storage for animation order data loaded from TSV (needs stable addresses for span). */\r\nstd::vector<std::vector<uint8_t>> TownerAnimOrderStorage;\r\n\r\n/**\r\n * @brief Defines the behavior (init and talk functions) for each towner type.\r\n *\r\n * The actual data (position, animation, gossip) comes from TSV files.\r\n * This struct only holds the code that can't be data-driven.\r\n */\r\nstruct TownerData {\r\n\t_talker_id type;\r\n\t/** Custom initialization function, or nullptr to use the default InitTownerFromData. */\r\n\tvoid (*init)(Towner &towner, const TownerDataEntry &entry);\r\n\t/** Function called when the player talks to this towner. */\r\n\tvoid (*talk)(Player &player, Towner &towner);\r\n};\r\n\r\n/**\r\n * @brief Lookup table from towner type to its behavior data.\r\n *\r\n * Populated during InitTowners() from the TownersData array.\r\n */\r\nstd::unordered_map<_talker_id, const TownerData *> TownerBehaviors;\r\n\r\n/**\r\n * @brief Default towner initialization using TSV data.\r\n *\r\n * Sets up animation, gossip texts, and other properties from the TSV entry.\r\n * Used for most towners; special cases (cows, cow farmer) have custom init functions.\r\n */\r\nvoid InitTownerFromData(Towner &towner, const TownerDataEntry &entry);\r\n\r\n#ifdef _DEBUG\r\n/**\r\n * @brief Finds the towner data entry from TSV for a given type.\r\n */\r\nconst TownerDataEntry *FindTownerDataEntry(_talker_id type, Point position = {})\r\n{\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tif (entry.type == type) {\r\n\t\t\t// For types with multiple instances (like cows), match by position\r\n\t\t\tif (position != Point {} && entry.position != position)\r\n\t\t\t\tcontinue;\r\n\t\t\treturn &entry;\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n#endif\r\n\r\nvoid NewTownerAnim(Towner &towner, ClxSpriteList sprites, uint8_t numFrames, int delay)\r\n{\r\n\ttowner.anim.emplace(sprites);\r\n\ttowner._tAnimLen = numFrames;\r\n\ttowner._tAnimFrame = 0;\r\n\ttowner._tAnimCnt = 0;\r\n\ttowner._tAnimDelay = delay;\r\n}\r\n\r\nvoid InitTownerInfo(Towner &towner, const TownerData &townerData, const TownerDataEntry &entry)\r\n{\r\n\ttowner._ttype = townerData.type;\r\n\tauto nameIt = TownerLongNames.find(townerData.type);\r\n\ttowner.name = nameIt != TownerLongNames.end() ? _(nameIt->second.c_str()) : std::string_view(entry.name);\r\n\ttowner.position = entry.position;\r\n\ttowner.talk = townerData.talk;\r\n\r\n\tif (townerData.init != nullptr) {\r\n\t\ttownerData.init(towner, entry);\r\n\t} else {\r\n\t\tInitTownerFromData(towner, entry);\r\n\t}\r\n}\r\n\r\nvoid LoadTownerAnimations(Towner &towner, const char *path, int frames, int delay)\r\n{\r\n\ttowner.ownedAnim = std::nullopt;\r\n\ttowner.ownedAnim = LoadCel(path, towner._tAnimWidth);\r\n\tNewTownerAnim(towner, *towner.ownedAnim, frames, delay);\r\n}\r\n\r\n/**\r\n * @brief Default towner initialization using TSV data.\r\n */\r\nvoid InitTownerFromData(Towner &towner, const TownerDataEntry &entry)\r\n{\r\n\ttowner._tAnimWidth = entry.animWidth;\r\n\r\n\t// Store animation order and set the span\r\n\tif (!entry.animOrder.empty()) {\r\n\t\tTownerAnimOrderStorage.push_back(entry.animOrder);\r\n\t\ttowner.animOrder = { TownerAnimOrderStorage.back() };\r\n\t} else {\r\n\t\ttowner.animOrder = {};\r\n\t}\r\n\r\n\tif (!entry.animPath.empty()) {\r\n\t\tLoadTownerAnimations(towner, entry.animPath.c_str(), entry.animFrames, entry.animDelay);\r\n\t}\r\n\r\n\t// Set gossip from TSV data\r\n\tif (!entry.gossipTexts.empty()) {\r\n\t\tconst auto index = std::max<int32_t>(GenerateRnd(static_cast<int32_t>(entry.gossipTexts.size())), 0);\r\n\t\ttowner.gossip = entry.gossipTexts[index];\r\n\t}\r\n}\r\n\r\n/**\r\n * @brief Special initialization for cows.\r\n *\r\n * Cows differ from other towners:\r\n * - They share a sprite sheet (CowSprites) instead of loading individual animations\r\n * - They occupy multiple tiles (4 tiles for collision purposes)\r\n * - Animation frame is randomized on spawn\r\n */\r\nvoid InitCows(Towner &towner, const TownerDataEntry &entry)\r\n{\r\n\t// Cows use a shared sprite sheet and need special handling\r\n\ttowner._tAnimWidth = entry.animWidth;\r\n\ttowner.animOrder = {};\r\n\r\n\tNewTownerAnim(towner, (*CowSprites)[static_cast<size_t>(entry.direction)], 12, 3);\r\n\ttowner._tAnimFrame = GenerateRnd(11);\r\n\r\n\tconst Point position = entry.position;\r\n\tconst int16_t cowId = dMonster[position.x][position.y];\r\n\r\n\t// Cows are large sprites so take up multiple tiles. Vanilla Diablo/Hellfire allowed the player to stand adjacent\r\n\t//  to a cow facing an ordinal direction (the two top-right cows) which leads to visual clipping. It's easier to\r\n\t//  treat all cows as 4 tile sprites since this works for all facings.\r\n\t// The active tile is always the south tile as this is closest to the camera, we mark the other 3 tiles as occupied\r\n\t//  using -id to match the convention used for moving/large monsters and players.\r\n\tPoint offset = position + Direction::NorthWest;\r\n\tdMonster[offset.x][offset.y] = -cowId;\r\n\toffset = position + Direction::NorthEast;\r\n\tdMonster[offset.x][offset.y] = -cowId;\r\n\toffset = position + Direction::North;\r\n\tdMonster[offset.x][offset.y] = -cowId;\r\n}\r\n\r\n/**\r\n * @brief Special initialization for the cow farmer (Complete Nut).\r\n *\r\n * Uses different sprites depending on whether the Jersey quest is complete.\r\n */\r\nvoid InitCowFarmer(Towner &towner, const TownerDataEntry &entry)\r\n{\r\n\ttowner._tAnimWidth = entry.animWidth;\r\n\ttowner.animOrder = {};\r\n\r\n\t// CowFarmer has special logic for quest state\r\n\tconst char *celPath = \"towners\\\\farmer\\\\cfrmrn2\";\r\n\tif (Quests[Q_JERSEY]._qactive == QUEST_DONE) {\r\n\t\tcelPath = \"towners\\\\farmer\\\\mfrmrn2\";\r\n\t}\r\n\tLoadTownerAnimations(towner, celPath, 15, 3);\r\n}\r\n\r\nvoid TownDead(Towner &towner)\r\n{\r\n\tif (qtextflag) {\r\n\t\tif (Quests[Q_BUTCHER]._qvar1 == 1)\r\n\t\t\ttowner._tAnimCnt = 0; // Freeze while speaking\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ((Quests[Q_BUTCHER]._qactive == QUEST_DONE || Quests[Q_BUTCHER]._qvar1 == 1) && towner._tAnimLen != 1) {\r\n\t\ttowner._tAnimLen = 1;\r\n\t\ttowner.name = _(\"Slain Townsman\");\r\n\t}\r\n}\r\n\r\nvoid TownerTalk(_speech_id message)\r\n{\r\n\tCowClicks = 0;\r\n\tCowMsg = 0;\r\n\tInitQTextMsg(message);\r\n}\r\n\r\nvoid TalkToBarOwner(Player &player, Towner &barOwner)\r\n{\r\n\tif (!player._pLvlVisited[0]) {\r\n\t\tInitQTextMsg(TEXT_INTRO);\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto &kingQuest = Quests[Q_SKELKING];\r\n\tif (kingQuest._qactive != QUEST_NOTAVAIL) {\r\n\t\tif (player._pLvlVisited[2] || player._pLvlVisited[4]) {\r\n\t\t\tif (kingQuest._qvar2 == 0) {\r\n\t\t\t\tkingQuest._qvar2 = 1;\r\n\t\t\t\tkingQuest._qlog = true;\r\n\t\t\t\tif (kingQuest._qactive == QUEST_INIT) {\r\n\t\t\t\t\tkingQuest._qactive = QUEST_ACTIVE;\r\n\t\t\t\t\tkingQuest._qvar1 = 1;\r\n\t\t\t\t}\r\n\t\t\t\tInitQTextMsg(TEXT_KING2);\r\n\t\t\t\tNetSendCmdQuest(true, kingQuest);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tif (kingQuest._qactive == QUEST_DONE && kingQuest._qvar2 == 1) {\r\n\t\t\t\tkingQuest._qvar2 = 2;\r\n\t\t\t\tkingQuest._qvar1 = 2;\r\n\t\t\t\tInitQTextMsg(TEXT_KING4);\r\n\t\t\t\tNetSendCmdQuest(true, kingQuest);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tauto &bannerQuest = Quests[Q_LTBANNER];\r\n\tif (bannerQuest._qactive != QUEST_NOTAVAIL) {\r\n\t\tif ((player._pLvlVisited[3] || player._pLvlVisited[4]) && bannerQuest._qactive != QUEST_DONE) {\r\n\t\t\tif (bannerQuest._qvar2 == 0) {\r\n\t\t\t\tbannerQuest._qvar2 = 1;\r\n\t\t\t\tif (bannerQuest._qactive == QUEST_INIT) {\r\n\t\t\t\t\tbannerQuest._qvar1 = 1;\r\n\t\t\t\t\tbannerQuest._qactive = QUEST_ACTIVE;\r\n\t\t\t\t}\r\n\t\t\t\tbannerQuest._qlog = true;\r\n\t\t\t\tNetSendCmdQuest(true, bannerQuest);\r\n\t\t\t\tInitQTextMsg(TEXT_BANNER2);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (bannerQuest._qvar2 == 1 && RemoveInventoryItemById(player, IDI_BANNER)) {\r\n\t\t\t\tbannerQuest._qactive = QUEST_DONE;\r\n\t\t\t\tbannerQuest._qvar1 = 3;\r\n\t\t\t\tNetSendCmdQuest(true, bannerQuest);\r\n\t\t\t\tSpawnUnique(UITEM_HARCREST, barOwner.position + Direction::SouthWest, bannerQuest._qlevel);\r\n\t\t\t\tInitQTextMsg(TEXT_BANNER3);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tTownerTalk(TEXT_OGDEN1);\r\n\tStartStore(TalkID::Tavern);\r\n}\r\n\r\nvoid TalkToDeadguy(Player &player, Towner & /*deadguy*/)\r\n{\r\n\tauto &quest = Quests[Q_BUTCHER];\r\n\tif (quest._qactive == QUEST_DONE)\r\n\t\treturn;\r\n\r\n\tif (quest._qvar1 == 1) {\r\n\t\tplayer.SaySpecific(HeroSpeech::YourDeathWillBeAvenged);\r\n\t\treturn;\r\n\t}\r\n\r\n\tquest._qactive = QUEST_ACTIVE;\r\n\tquest._qlog = true;\r\n\tquest._qmsg = TEXT_BUTCH9;\r\n\tquest._qvar1 = 1;\r\n\tInitQTextMsg(TEXT_BUTCH9);\r\n\tNetSendCmdQuest(true, quest);\r\n}\r\n\r\nvoid TalkToBlackSmith(Player &player, Towner &blackSmith)\r\n{\r\n\tif (Quests[Q_ROCK]._qactive != QUEST_NOTAVAIL) {\r\n\t\tif ((player._pLvlVisited[4] || player._pLvlVisited[5]) && Quests[Q_ROCK]._qactive != QUEST_DONE) {\r\n\t\t\tif (Quests[Q_ROCK]._qvar2 == 0) {\r\n\t\t\t\tQuests[Q_ROCK]._qvar2 = 1;\r\n\t\t\t\tQuests[Q_ROCK]._qlog = true;\r\n\t\t\t\tif (Quests[Q_ROCK]._qactive == QUEST_INIT) {\r\n\t\t\t\t\tQuests[Q_ROCK]._qactive = QUEST_ACTIVE;\r\n\t\t\t\t}\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_ROCK]);\r\n\t\t\t\tInitQTextMsg(TEXT_INFRA5);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (Quests[Q_ROCK]._qvar2 == 1 && RemoveInventoryItemById(player, IDI_ROCK)) {\r\n\t\t\t\tQuests[Q_ROCK]._qactive = QUEST_DONE;\r\n\t\t\t\tNetSendCmdQuest(true, Quests[Q_ROCK]);\r\n\t\t\t\tSpawnUnique(UITEM_INFRARING, blackSmith.position + Direction::SouthWest, Quests[Q_ROCK]._qlevel);\r\n\t\t\t\tInitQTextMsg(TEXT_INFRA7);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (IsNoneOf(Quests[Q_ANVIL]._qactive, QUEST_NOTAVAIL, QUEST_DONE)) {\r\n\t\tif ((player._pLvlVisited[9] || player._pLvlVisited[10]) && Quests[Q_ANVIL]._qvar2 == 0) {\r\n\t\t\tQuests[Q_ANVIL]._qvar2 = 1;\r\n\t\t\tQuests[Q_ANVIL]._qlog = true;\r\n\t\t\tif (Quests[Q_ANVIL]._qactive == QUEST_INIT) {\r\n\t\t\t\tQuests[Q_ANVIL]._qactive = QUEST_ACTIVE;\r\n\t\t\t}\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_ANVIL]);\r\n\t\t\tInitQTextMsg(TEXT_ANVIL5);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (Quests[Q_ANVIL]._qvar2 == 1 && RemoveInventoryItemById(player, IDI_ANVIL)) {\r\n\t\t\tQuests[Q_ANVIL]._qactive = QUEST_DONE;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_ANVIL]);\r\n\t\t\tSpawnUnique(UITEM_GRISWOLD, blackSmith.position + Direction::SouthWest, Quests[Q_ANVIL]._qlevel);\r\n\t\t\tInitQTextMsg(TEXT_ANVIL7);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tTownerTalk(TEXT_GRISWOLD1);\r\n\tStartStore(TalkID::Smith);\r\n}\r\n\r\nvoid TalkToWitch(Player &player, Towner & /*witch*/)\r\n{\r\n\tif (Quests[Q_MUSHROOM]._qactive != QUEST_NOTAVAIL) {\r\n\t\tif (Quests[Q_MUSHROOM]._qactive == QUEST_INIT && RemoveInventoryItemById(player, IDI_FUNGALTM)) {\r\n\t\t\tQuests[Q_MUSHROOM]._qactive = QUEST_ACTIVE;\r\n\t\t\tQuests[Q_MUSHROOM]._qlog = true;\r\n\t\t\tQuests[Q_MUSHROOM]._qvar1 = QS_TOMEGIVEN;\r\n\t\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t\tInitQTextMsg(TEXT_MUSH8);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (Quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE) {\r\n\t\t\tif (Quests[Q_MUSHROOM]._qvar1 >= QS_TOMEGIVEN && Quests[Q_MUSHROOM]._qvar1 < QS_MUSHGIVEN) {\r\n\t\t\t\tif (RemoveInventoryItemById(player, IDI_MUSHROOM)) {\r\n\t\t\t\t\tQuests[Q_MUSHROOM]._qvar1 = QS_MUSHGIVEN;\r\n\t\t\t\t\tSetTownerQuestDialog(TOWN_HEALER, Q_MUSHROOM, TEXT_MUSH3);\r\n\t\t\t\t\tSetTownerQuestDialog(TOWN_WITCH, Q_MUSHROOM, TEXT_NONE);\r\n\t\t\t\t\tQuests[Q_MUSHROOM]._qmsg = TEXT_MUSH10;\r\n\t\t\t\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t\t\t\tInitQTextMsg(TEXT_MUSH10);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (Quests[Q_MUSHROOM]._qmsg != TEXT_MUSH9) {\r\n\t\t\t\t\tQuests[Q_MUSHROOM]._qmsg = TEXT_MUSH9;\r\n\t\t\t\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t\t\t\tInitQTextMsg(TEXT_MUSH9);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (Quests[Q_MUSHROOM]._qvar1 >= QS_MUSHGIVEN) {\r\n\t\t\t\tif (HasInventoryItemWithId(player, IDI_BRAIN)) {\r\n\t\t\t\t\tQuests[Q_MUSHROOM]._qmsg = TEXT_MUSH11;\r\n\t\t\t\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t\t\t\tInitQTextMsg(TEXT_MUSH11);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (HasInventoryOrBeltItemWithId(player, IDI_SPECELIX)) {\r\n\t\t\t\t\tQuests[Q_MUSHROOM]._qactive = QUEST_DONE;\r\n\t\t\t\t\tNetSendCmdQuest(true, Quests[Q_MUSHROOM]);\r\n\t\t\t\t\tInitQTextMsg(TEXT_MUSH12);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tTownerTalk(TEXT_ADRIA1);\r\n\tStartStore(TalkID::Witch);\r\n}\r\n\r\nvoid TalkToBarmaid(Player &player, Towner & /*barmaid*/)\r\n{\r\n\tif (!player._pLvlVisited[21] && HasInventoryItemWithId(player, IDI_MAPOFDOOM) && Quests[Q_GRAVE]._qmsg != TEXT_GRAVE8) {\r\n\t\tQuests[Q_GRAVE]._qactive = QUEST_ACTIVE;\r\n\t\tQuests[Q_GRAVE]._qlog = true;\r\n\t\tQuests[Q_GRAVE]._qmsg = TEXT_GRAVE8;\r\n\t\tNetSendCmdQuest(true, Quests[Q_GRAVE]);\r\n\t\tInitQTextMsg(TEXT_GRAVE8);\r\n\t\treturn;\r\n\t}\r\n\r\n\tTownerTalk(TEXT_GILLIAN1);\r\n\tStartStore(TalkID::Barmaid);\r\n}\r\n\r\nvoid TalkToDrunk(Player & /*player*/, Towner & /*drunk*/)\r\n{\r\n\tTownerTalk(TEXT_FARNHAM1);\r\n\tStartStore(TalkID::Drunk);\r\n}\r\n\r\nvoid TalkToHealer(Player &player, Towner &healer)\r\n{\r\n\tQuest &poisonWater = Quests[Q_PWATER];\r\n\tif (poisonWater._qactive != QUEST_NOTAVAIL) {\r\n\t\tif ((poisonWater._qactive == QUEST_INIT && (player._pLvlVisited[1] || player._pLvlVisited[5])) || (poisonWater._qactive == QUEST_ACTIVE && !poisonWater._qlog)) {\r\n\t\t\t// Play the dialog and make the quest visible in the log if the player has not started the quest but has\r\n\t\t\t// visited the dungeon at least once, or if they've found the poison water cave before speaking to Pepin\r\n\t\t\tpoisonWater._qactive = QUEST_ACTIVE;\r\n\t\t\tpoisonWater._qlog = true;\r\n\t\t\tpoisonWater._qmsg = TEXT_POISON3;\r\n\t\t\tInitQTextMsg(TEXT_POISON3);\r\n\t\t\tNetSendCmdQuest(true, poisonWater);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (poisonWater._qactive == QUEST_DONE && poisonWater._qvar1 != 2) {\r\n\t\t\tpoisonWater._qvar1 = 2;\r\n\t\t\tInitQTextMsg(TEXT_POISON5);\r\n\t\t\tSpawnUnique(UITEM_TRING, healer.position + Direction::SouthWest, poisonWater._qlevel);\r\n\t\t\tNetSendCmdQuest(true, poisonWater);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tQuest &blackMushroom = Quests[Q_MUSHROOM];\r\n\tif (blackMushroom._qactive == QUEST_ACTIVE) {\r\n\t\tif (blackMushroom._qvar1 >= QS_MUSHGIVEN && blackMushroom._qvar1 < QS_BRAINGIVEN && RemoveInventoryItemById(player, IDI_BRAIN)) {\r\n\t\t\tSpawnQuestItem(IDI_SPECELIX, healer.position + Displacement { 0, 1 }, 0, SelectionRegion::None, true);\r\n\t\t\tInitQTextMsg(TEXT_MUSH4);\r\n\t\t\tblackMushroom._qvar1 = QS_BRAINGIVEN;\r\n\t\t\tSetTownerQuestDialog(TOWN_HEALER, Q_MUSHROOM, TEXT_NONE);\r\n\t\t\tNetSendCmdQuest(true, blackMushroom);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tTownerTalk(TEXT_PEPIN1);\r\n\tStartStore(TalkID::Healer);\r\n}\r\n\r\nvoid TalkToBoy(Player & /*player*/, Towner & /*boy*/)\r\n{\r\n\tTownerTalk(TEXT_WIRT1);\r\n\tStartStore(TalkID::Boy);\r\n}\r\n\r\nvoid TalkToStoryteller(Player &player, Towner & /*storyteller*/)\r\n{\r\n\tauto &betrayerQuest = Quests[Q_BETRAYER];\r\n\tif (!UseMultiplayerQuests()) {\r\n\t\tif (betrayerQuest._qactive == QUEST_INIT && RemoveInventoryItemById(player, IDI_LAZSTAFF)) {\r\n\t\t\tInitQTextMsg(TEXT_VILE1);\r\n\t\t\tbetrayerQuest._qlog = true;\r\n\t\t\tbetrayerQuest._qactive = QUEST_ACTIVE;\r\n\t\t\tbetrayerQuest._qvar1 = 2;\r\n\t\t\tNetSendCmdQuest(true, betrayerQuest);\r\n\t\t\treturn;\r\n\t\t}\r\n\t} else {\r\n\t\tif (betrayerQuest._qactive == QUEST_ACTIVE && !betrayerQuest._qlog) {\r\n\t\t\tInitQTextMsg(TEXT_VILE1);\r\n\t\t\tbetrayerQuest._qlog = true;\r\n\t\t\tNetSendCmdQuest(true, betrayerQuest);\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tif (betrayerQuest._qactive == QUEST_DONE && betrayerQuest._qvar1 == 7) {\r\n\t\tbetrayerQuest._qvar1 = 8;\r\n\t\tInitQTextMsg(TEXT_VILE3);\r\n\t\tauto &diabloQuest = Quests[Q_DIABLO];\r\n\t\tdiabloQuest._qlog = true;\r\n\t\tif (gbIsMultiplayer) {\r\n\t\t\tNetSendCmdQuest(true, betrayerQuest);\r\n\t\t\tNetSendCmdQuest(true, diabloQuest);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tTownerTalk(TEXT_STORY1);\r\n\tStartStore(TalkID::Storyteller);\r\n}\r\n\r\nvoid TalkToCow(Player &player, Towner &cow)\r\n{\r\n\tif (CowPlaying != SfxID::None && effect_is_playing(CowPlaying))\r\n\t\treturn;\r\n\r\n\tCowClicks++;\r\n\r\n\tCowPlaying = SfxID::Cow1;\r\n\tif (CowClicks == 4) {\r\n\t\tif (gbIsSpawn)\r\n\t\t\tCowClicks = 0;\r\n\r\n\t\tCowPlaying = SfxID::Cow2;\r\n\t} else if (CowClicks >= 8 && !gbIsSpawn) {\r\n\t\tCowClicks = 4;\r\n\r\n\t\tstatic const HeroSpeech SnSfx[3] = {\r\n\t\t\tHeroSpeech::YepThatsACowAlright,\r\n\t\t\tHeroSpeech::ImNotThirsty,\r\n\t\t\tHeroSpeech::ImNoMilkmaid,\r\n\t\t};\r\n\t\tplayer.SaySpecific(SnSfx[CowMsg]);\r\n\t\tCowMsg++;\r\n\t\tif (CowMsg >= 3)\r\n\t\t\tCowMsg = 0;\r\n\t}\r\n\r\n\tPlaySfxLoc(CowPlaying, cow.position);\r\n}\r\n\r\nvoid TalkToFarmer(Player &player, Towner &farmer)\r\n{\r\n\tauto &quest = Quests[Q_FARMER];\r\n\tswitch (quest._qactive) {\r\n\tcase QUEST_NOTAVAIL:\r\n\tcase QUEST_INIT:\r\n\t\tif (HasInventoryItemWithId(player, IDI_RUNEBOMB)) {\r\n\t\t\tInitQTextMsg(TEXT_FARMER2);\r\n\t\t\tquest._qactive = QUEST_ACTIVE;\r\n\t\t\tquest._qvar1 = 1;\r\n\t\t\tquest._qmsg = TEXT_FARMER1;\r\n\t\t\tquest._qlog = true;\r\n\t\t\tif (gbIsMultiplayer)\r\n\t\t\t\tNetSendCmdQuest(true, quest);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif (!player._pLvlVisited[9] && player.getCharacterLevel() < 15) {\r\n\t\t\t_speech_id qt = TEXT_FARMER8;\r\n\t\t\tif (player._pLvlVisited[2])\r\n\t\t\t\tqt = TEXT_FARMER5;\r\n\t\t\tif (player._pLvlVisited[5])\r\n\t\t\t\tqt = TEXT_FARMER7;\r\n\t\t\tif (player._pLvlVisited[7])\r\n\t\t\t\tqt = TEXT_FARMER9;\r\n\t\t\tInitQTextMsg(qt);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tInitQTextMsg(TEXT_FARMER1);\r\n\t\tquest._qactive = QUEST_ACTIVE;\r\n\t\tquest._qvar1 = 1;\r\n\t\tquest._qlog = true;\r\n\t\tquest._qmsg = TEXT_FARMER1;\r\n\t\tSpawnRuneBomb(farmer.position + Displacement { 1, 0 }, true);\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\tbreak;\r\n\tcase QUEST_ACTIVE:\r\n\t\tInitQTextMsg(HasInventoryItemWithId(player, IDI_RUNEBOMB) ? TEXT_FARMER2 : TEXT_FARMER3);\r\n\t\tbreak;\r\n\tcase QUEST_DONE:\r\n\t\tInitQTextMsg(TEXT_FARMER4);\r\n\t\tSpawnRewardItem(IDI_AURIC, farmer.position + Displacement { 1, 0 }, true);\r\n\t\tquest._qactive = QUEST_HIVE_DONE;\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\tbreak;\r\n\tcase QUEST_HIVE_DONE:\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tInitQTextMsg(TEXT_FARMER4);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid TalkToCowFarmer(Player &player, Towner &cowFarmer)\r\n{\r\n\tif (RemoveInventoryItemById(player, IDI_GREYSUIT)) {\r\n\t\tInitQTextMsg(TEXT_JERSEY7);\r\n\t\treturn;\r\n\t}\r\n\r\n\tauto &quest = Quests[Q_JERSEY];\r\n\r\n\tif (RemoveInventoryItemById(player, IDI_BROWNSUIT)) {\r\n\t\tSpawnUnique(UITEM_BOVINE, cowFarmer.position + Direction::SouthEast, quest._qlevel);\r\n\t\tInitQTextMsg(TEXT_JERSEY8);\r\n\t\tquest._qactive = QUEST_DONE;\r\n\t\tUpdateCowFarmerAnimAfterQuestComplete();\r\n\t\tNetSendCmdQuest(true, quest);\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (HasInventoryItemWithId(player, IDI_RUNEBOMB)) {\r\n\t\tInitQTextMsg(TEXT_JERSEY5);\r\n\t\tquest._qactive = QUEST_ACTIVE;\r\n\t\tquest._qvar1 = 1;\r\n\t\tquest._qmsg = TEXT_JERSEY4;\r\n\t\tquest._qlog = true;\r\n\t\tNetSendCmdQuest(true, quest);\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (quest._qactive) {\r\n\tcase QUEST_NOTAVAIL:\r\n\tcase QUEST_INIT:\r\n\t\tInitQTextMsg(TEXT_JERSEY1);\r\n\t\tquest._qactive = QUEST_HIVE_TEASE1;\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\tbreak;\r\n\tcase QUEST_DONE:\r\n\t\tInitQTextMsg(TEXT_JERSEY1);\r\n\t\tbreak;\r\n\tcase QUEST_HIVE_TEASE1:\r\n\t\tInitQTextMsg(TEXT_JERSEY2);\r\n\t\tquest._qactive = QUEST_HIVE_TEASE2;\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\tbreak;\r\n\tcase QUEST_HIVE_TEASE2:\r\n\t\tInitQTextMsg(TEXT_JERSEY3);\r\n\t\tquest._qactive = QUEST_HIVE_ACTIVE;\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\tbreak;\r\n\tcase QUEST_HIVE_ACTIVE:\r\n\t\tif (!player._pLvlVisited[9] && player.getCharacterLevel() < 15) {\r\n\t\t\tInitQTextMsg(PickRandomlyAmong({ TEXT_JERSEY9, TEXT_JERSEY10, TEXT_JERSEY11, TEXT_JERSEY12 }));\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tInitQTextMsg(TEXT_JERSEY4);\r\n\t\tquest._qactive = QUEST_ACTIVE;\r\n\t\tquest._qvar1 = 1;\r\n\t\tquest._qmsg = TEXT_JERSEY4;\r\n\t\tquest._qlog = true;\r\n\t\tSpawnRuneBomb(cowFarmer.position + Displacement { 1, 0 }, true);\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tInitQTextMsg(TEXT_JERSEY5);\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid TalkToGirl(Player &player, Towner &girl)\r\n{\r\n\tauto &quest = Quests[Q_GIRL];\r\n\r\n\tif (quest._qactive != QUEST_DONE && RemoveInventoryItemById(player, IDI_THEODORE)) {\r\n\t\tInitQTextMsg(TEXT_GIRL4);\r\n\t\tCreateAmulet(girl.position, 13, false, false, true);\r\n\t\tquest._qactive = QUEST_DONE;\r\n\t\tUpdateGirlAnimAfterQuestComplete();\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (quest._qactive) {\r\n\tcase QUEST_NOTAVAIL:\r\n\tcase QUEST_INIT:\r\n\t\tInitQTextMsg(TEXT_GIRL2);\r\n\t\tquest._qactive = QUEST_ACTIVE;\r\n\t\tquest._qvar1 = 1;\r\n\t\tquest._qlog = true;\r\n\t\tquest._qmsg = TEXT_GIRL2;\r\n\t\tif (gbIsMultiplayer)\r\n\t\t\tNetSendCmdQuest(true, quest);\r\n\t\treturn;\r\n\tcase QUEST_ACTIVE:\r\n\t\tInitQTextMsg(TEXT_GIRL3);\r\n\t\treturn;\r\n\tdefault:\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\nconst TownerData TownersData[] = {\r\n\t// clang-format off\r\n\t// type          init (nullptr = default)  talk\r\n\t{ TOWN_SMITH,   nullptr,       TalkToBlackSmith  },\r\n\t{ TOWN_HEALER,  nullptr,       TalkToHealer      },\r\n\t{ TOWN_DEADGUY, nullptr,       TalkToDeadguy     },\r\n\t{ TOWN_TAVERN,  nullptr,       TalkToBarOwner    },\r\n\t{ TOWN_STORY,   nullptr,       TalkToStoryteller },\r\n\t{ TOWN_DRUNK,   nullptr,       TalkToDrunk       },\r\n\t{ TOWN_WITCH,   nullptr,       TalkToWitch       },\r\n\t{ TOWN_BMAID,   nullptr,       TalkToBarmaid     },\r\n\t{ TOWN_PEGBOY,  nullptr,       TalkToBoy         },\r\n\t{ TOWN_COW,     InitCows,      TalkToCow         },\r\n\t{ TOWN_COWFARM, InitCowFarmer, TalkToCowFarmer   },\r\n\t{ TOWN_FARMER,  nullptr,       TalkToFarmer      },\r\n\t{ TOWN_GIRL,    nullptr,       TalkToGirl        },\r\n\t// clang-format on\r\n};\r\n\r\n} // namespace\r\n\r\nstd::vector<Towner> Towners;\r\n\r\nstd::unordered_map<_talker_id, std::string> TownerLongNames;\r\n\r\nsize_t GetNumTownerTypes()\r\n{\r\n\treturn TownerLongNames.size();\r\n}\r\n\r\nsize_t GetNumTowners()\r\n{\r\n\treturn Towners.size();\r\n}\r\n\r\nbool IsTownerPresent(_talker_id npc)\r\n{\r\n\tswitch (npc) {\r\n\tcase TOWN_DEADGUY:\r\n\t\treturn Quests[Q_BUTCHER]._qactive != QUEST_NOTAVAIL && Quests[Q_BUTCHER]._qactive != QUEST_DONE;\r\n\tcase TOWN_FARMER:\r\n\t\treturn gbIsHellfire && sgGameInitInfo.bCowQuest == 0 && Quests[Q_FARMER]._qactive != QUEST_HIVE_DONE;\r\n\tcase TOWN_COWFARM:\r\n\t\treturn gbIsHellfire && sgGameInitInfo.bCowQuest != 0;\r\n\tcase TOWN_GIRL:\r\n\t\treturn gbIsHellfire && sgGameInitInfo.bTheoQuest != 0 && MyPlayer->_pLvlVisited[17] && Quests[Q_GIRL]._qactive != QUEST_DONE;\r\n\tdefault:\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\nTowner *GetTowner(_talker_id type)\r\n{\r\n\tfor (Towner &towner : Towners) {\r\n\t\tif (towner._ttype == type)\r\n\t\t\treturn &towner;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nvoid InitTowners()\r\n{\r\n\tassert(!CowSprites);\r\n\r\n\t// Load towner data from TSV files\r\n\tLoadTownerData();\r\n\tTownerAnimOrderStorage.clear();\r\n\r\n\t// Build lookup table for towner behaviors\r\n\tTownerBehaviors.clear();\r\n\tfor (const auto &behavior : TownersData) {\r\n\t\tTownerBehaviors[behavior.type] = &behavior;\r\n\t}\r\n\r\n\t// Build TownerLongNames from TSV data (first occurrence of each type wins)\r\n\tTownerLongNames.clear();\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tTownerLongNames.try_emplace(entry.type, entry.name);\r\n\t}\r\n\r\n\tCowSprites.emplace(LoadCelSheet(\"towners\\\\animals\\\\cow\", 128));\r\n\r\n\tTowners.clear();\r\n\tTowners.reserve(TownersDataEntries.size());\r\n\tint16_t i = 0;\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tif (!IsTownerPresent(entry.type))\r\n\t\t\tcontinue;\r\n\r\n\t\tauto behaviorIt = TownerBehaviors.find(entry.type);\r\n\t\tif (behaviorIt == TownerBehaviors.end() || behaviorIt->second == nullptr)\r\n\t\t\tcontinue;\r\n\r\n\t\t// It's necessary to assign this before invoking townerData.init()\r\n\t\t// specifically for the cows that need to read this value to fill adjacent tiles\r\n\t\tdMonster[entry.position.x][entry.position.y] = i + 1;\r\n\r\n\t\tTowners.emplace_back();\r\n\t\tInitTownerInfo(Towners.back(), *behaviorIt->second, entry);\r\n\t\ti++;\r\n\t}\r\n}\r\n\r\nvoid FreeTownerGFX()\r\n{\r\n\tfor (Towner &towner : Towners) {\r\n\t\ttowner.ownedAnim = std::nullopt;\r\n\t}\r\n\tCowSprites = std::nullopt;\r\n}\r\n\r\nvoid ProcessTowners()\r\n{\r\n\t// BUGFIX: should be `i < numtowners`, was `i < NUM_TOWNERS`\r\n\tfor (auto &towner : Towners) {\r\n\t\tif (towner._ttype == TOWN_DEADGUY) {\r\n\t\t\tTownDead(towner);\r\n\t\t}\r\n\r\n\t\ttowner._tAnimCnt++;\r\n\t\tif (towner._tAnimCnt < towner._tAnimDelay) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\ttowner._tAnimCnt = 0;\r\n\r\n\t\tif (!towner.animOrder.empty()) {\r\n\t\t\ttowner._tAnimFrameCnt++;\r\n\t\t\tif (towner._tAnimFrameCnt > towner.animOrder.size() - 1)\r\n\t\t\t\ttowner._tAnimFrameCnt = 0;\r\n\r\n\t\t\ttowner._tAnimFrame = towner.animOrder[towner._tAnimFrameCnt];\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\ttowner._tAnimFrame++;\r\n\t\tif (towner._tAnimFrame >= towner._tAnimLen)\r\n\t\t\ttowner._tAnimFrame = 0;\r\n\t}\r\n}\r\n\r\nvoid TalkToTowner(Player &player, int t)\r\n{\r\n\tauto &towner = Towners[t];\r\n\r\n\tif (player.position.tile.WalkingDistance(towner.position) >= 2)\r\n\t\treturn;\r\n\r\n\tif (!player.HoldItem.isEmpty()) {\r\n\t\treturn;\r\n\t}\r\n\r\n\ttowner.talk(player, towner);\r\n}\r\n\r\nvoid UpdateGirlAnimAfterQuestComplete()\r\n{\r\n\tTowner *girl = GetTowner(TOWN_GIRL);\r\n\tif (girl == nullptr || !girl->ownedAnim)\r\n\t\treturn; // Girl is not spawned in town yet\r\n\tauto curFrame = girl->_tAnimFrame;\r\n\tLoadTownerAnimations(*girl, \"towners\\\\girl\\\\girls1\", 20, 6);\r\n\tgirl->_tAnimFrame = std::min<uint8_t>(curFrame, girl->_tAnimLen - 1);\r\n}\r\n\r\nvoid UpdateCowFarmerAnimAfterQuestComplete()\r\n{\r\n\tTowner *cowFarmer = GetTowner(TOWN_COWFARM);\r\n\tauto curFrame = cowFarmer->_tAnimFrame;\r\n\tLoadTownerAnimations(*cowFarmer, \"towners\\\\farmer\\\\mfrmrn2\", 15, 3);\r\n\tcowFarmer->_tAnimFrame = std::min<uint8_t>(curFrame, cowFarmer->_tAnimLen - 1);\r\n}\r\n\r\n#ifdef _DEBUG\r\nbool DebugTalkToTowner(_talker_id type)\r\n{\r\n\tif (!IsTownerPresent(type))\r\n\t\treturn false;\r\n\t// cows have an init function that differs from the rest and isn't compatible with this code, skip them :(\r\n\tif (type == TOWN_COW)\r\n\t\treturn false;\r\n\r\n\tconst TownerData *behavior = TownerBehaviors[type];\r\n\tif (behavior == nullptr)\r\n\t\treturn false;\r\n\r\n\tconst TownerDataEntry *entry = FindTownerDataEntry(type);\r\n\tif (entry == nullptr)\r\n\t\treturn false;\r\n\r\n\tSetupTownStores();\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tTowner fakeTowner;\r\n\tInitTownerInfo(fakeTowner, *behavior, *entry);\r\n\tfakeTowner.position = myPlayer.position.tile;\r\n\tbehavior->talk(myPlayer, fakeTowner);\r\n\treturn true;\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/towners.h",
    "content": "/**\r\n * @file towners.h\r\n *\r\n * Interface of functionality for loading and spawning towners.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n#include <span>\r\n#include <string>\r\n#include <string_view>\r\n#include <unordered_map>\r\n#include <vector>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"items.h\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nenum _talker_id : uint8_t {\r\n\tTOWN_SMITH,\r\n\tTOWN_HEALER,\r\n\tTOWN_DEADGUY,\r\n\tTOWN_TAVERN,\r\n\tTOWN_STORY,\r\n\tTOWN_DRUNK,\r\n\tTOWN_WITCH,\r\n\tTOWN_BMAID,\r\n\tTOWN_PEGBOY,\r\n\tTOWN_COW,\r\n\tTOWN_FARMER,\r\n\tTOWN_GIRL,\r\n\tTOWN_COWFARM,\r\n\t// Note: Enum values are parsed from TSV using magic_enum\r\n\t// The actual count is determined dynamically from TSV data\r\n};\r\n\r\n// Runtime mappings built from TSV data\r\nextern DVL_API_FOR_TEST std::unordered_map<_talker_id, std::string> TownerLongNames; // Maps towner type enum to display name\r\n\r\nstruct Towner {\r\n\tOptionalOwnedClxSpriteList ownedAnim;\r\n\tOptionalClxSpriteList anim;\r\n\t/** Specifies the animation frame sequence. */\r\n\tstd::span<const uint8_t> animOrder;\r\n\tvoid (*talk)(Player &player, Towner &towner);\r\n\r\n\tstd::string_view name;\r\n\r\n\t/** Tile position of NPC */\r\n\tPoint position;\r\n\t/** Randomly chosen topic for discussion (picked when loading into town) */\r\n\t_speech_id gossip;\r\n\tuint16_t _tAnimWidth;\r\n\t/** Tick length of each frame in the current animation */\r\n\tint16_t _tAnimDelay;\r\n\t/** Increases by one each game tick, counting how close we are to _pAnimDelay */\r\n\tint16_t _tAnimCnt;\r\n\t/** Number of frames in current animation */\r\n\tuint8_t _tAnimLen;\r\n\t/** Current frame of animation. */\r\n\tuint8_t _tAnimFrame;\r\n\tuint8_t _tAnimFrameCnt;\r\n\t_talker_id _ttype;\r\n\r\n\t[[nodiscard]] ClxSprite currentSprite() const\r\n\t{\r\n\t\treturn (*anim)[_tAnimFrame];\r\n\t}\r\n\t[[nodiscard]] Displacement getRenderingOffset() const\r\n\t{\r\n\t\treturn { -CalculateSpriteTileCenterX(_tAnimWidth), 0 };\r\n\t}\r\n};\r\n\r\nextern std::vector<Towner> Towners;\r\n\r\n/**\r\n * @brief Returns the number of unique towner types found in TSV data.\r\n * This is dynamically determined from the loaded towner data.\r\n */\r\nsize_t GetNumTownerTypes();\r\n\r\n/**\r\n * @brief Returns the number of towner instances (actual spawned towners).\r\n * This is dynamically determined from the loaded towner data.\r\n */\r\nsize_t GetNumTowners();\r\n\r\nbool IsTownerPresent(_talker_id npc);\r\n/**\r\n * @brief Maps from a _talker_id value to a pointer to the Towner object, if they have been initialised\r\n * @param type enum constant identifying the towner\r\n * @return Pointer to the Towner or nullptr if they are not available\r\n */\r\nTowner *GetTowner(_talker_id type);\r\n\r\nvoid InitTowners();\r\nvoid FreeTownerGFX();\r\nvoid ProcessTowners();\r\nvoid TalkToTowner(Player &player, int t);\r\n\r\nvoid UpdateGirlAnimAfterQuestComplete();\r\nvoid UpdateCowFarmerAnimAfterQuestComplete();\r\n\r\n#ifdef _DEBUG\r\nbool DebugTalkToTowner(_talker_id type);\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/track.cpp",
    "content": "/**\r\n * @file track.cpp\r\n *\r\n * Implementation of functionality tracking what the mouse cursor is pointing at.\r\n */\r\n#include \"track.h\"\r\n\r\n#include \"controls/control_mode.hpp\"\r\n#include \"controls/game_controls.h\"\r\n#include \"controls/plrctrls.h\"\r\n#include \"cursor.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"player.h\"\r\n#include \"stores.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid RepeatWalk(Player &player)\r\n{\r\n\tif (!InDungeonBounds(cursPosition))\r\n\t\treturn;\r\n\r\n\tif (player._pmode != PM_STAND && (!player.isWalking() || player.AnimInfo.getFrameToUseForRendering() <= 6))\r\n\t\treturn;\r\n\r\n\tconst Point target = player.GetTargetPosition();\r\n\tif (cursPosition == target)\r\n\t\treturn;\r\n\r\n\tNetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, cursPosition);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid InvalidateTargets()\r\n{\r\n\tif (pcursmonst != -1) {\r\n\t\tconst Monster &monster = Monsters[pcursmonst];\r\n\t\tif (monster.isInvalid || monster.hasNoLife()\r\n\t\t    || (monster.flags & MFLAG_HIDDEN) != 0\r\n\t\t    || !IsTileLit(monster.position.tile)) {\r\n\t\t\tpcursmonst = -1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (ObjectUnderCursor != nullptr && !ObjectUnderCursor->canInteractWith())\r\n\t\tObjectUnderCursor = nullptr;\r\n\r\n\tif (PlayerUnderCursor != nullptr) {\r\n\t\tconst Player &targetPlayer = *PlayerUnderCursor;\r\n\t\tif (targetPlayer._pmode == PM_DEATH || targetPlayer._pmode == PM_QUIT || !targetPlayer.plractive\r\n\t\t    || !targetPlayer.isOnActiveLevel() || targetPlayer.hasNoLife()\r\n\t\t    || !IsTileLit(targetPlayer.position.tile))\r\n\t\t\tPlayerUnderCursor = nullptr;\r\n\t}\r\n}\r\n\r\nvoid RepeatPlayerAction()\r\n{\r\n\tif (pcurs != CURSOR_HAND)\r\n\t\treturn;\r\n\r\n\tif (sgbMouseDown == CLICK_NONE && ControllerActionHeld == GameActionType_NONE)\r\n\t\treturn;\r\n\r\n\tif (IsPlayerInStore())\r\n\t\treturn;\r\n\r\n\tif (LastPlayerAction == PlayerActionType::None)\r\n\t\treturn;\r\n\r\n\tPlayer &myPlayer = *MyPlayer;\r\n\tif (myPlayer.destAction != ACTION_NONE)\r\n\t\treturn;\r\n\tif (myPlayer._pInvincible)\r\n\t\treturn;\r\n\tif (!myPlayer.CanChangeAction())\r\n\t\treturn;\r\n\r\n\tconst bool rangedAttack = myPlayer.UsesRangedWeapon();\r\n\tswitch (LastPlayerAction) {\r\n\tcase PlayerActionType::Attack:\r\n\t\tif (InDungeonBounds(cursPosition))\r\n\t\t\tNetSendCmdLoc(MyPlayerId, true, rangedAttack ? CMD_RATTACKXY : CMD_SATTACKXY, cursPosition);\r\n\t\tbreak;\r\n\tcase PlayerActionType::AttackMonsterTarget:\r\n\t\tif (pcursmonst != -1)\r\n\t\t\tNetSendCmdParam1(true, rangedAttack ? CMD_RATTACKID : CMD_ATTACKID, pcursmonst);\r\n\t\tbreak;\r\n\tcase PlayerActionType::AttackPlayerTarget:\r\n\t\tif (PlayerUnderCursor != nullptr && !myPlayer.friendlyMode)\r\n\t\t\tNetSendCmdParam1(true, rangedAttack ? CMD_RATTACKPID : CMD_ATTACKPID, PlayerUnderCursor->getId());\r\n\t\tbreak;\r\n\tcase PlayerActionType::Spell:\r\n\t\tif (ControlMode != ControlTypes::KeyboardAndMouse) {\r\n\t\t\tUpdateSpellTarget(MyPlayer->_pRSpell);\r\n\t\t}\r\n\t\tCheckPlrSpell(ControlMode == ControlTypes::KeyboardAndMouse);\r\n\t\tbreak;\r\n\tcase PlayerActionType::SpellMonsterTarget:\r\n\t\tif (pcursmonst != -1)\r\n\t\t\tCheckPlrSpell(false);\r\n\t\tbreak;\r\n\tcase PlayerActionType::SpellPlayerTarget:\r\n\t\tif (PlayerUnderCursor != nullptr && !myPlayer.friendlyMode)\r\n\t\t\tCheckPlrSpell(false);\r\n\t\tbreak;\r\n\tcase PlayerActionType::OperateObject:\r\n\t\tif (ObjectUnderCursor != nullptr && !ObjectUnderCursor->isDoor()) {\r\n\t\t\tNetSendCmdLoc(MyPlayerId, true, CMD_OPOBJXY, cursPosition);\r\n\t\t}\r\n\t\tbreak;\r\n\tcase PlayerActionType::Walk:\r\n\t\tRepeatWalk(myPlayer);\r\n\t\tbreak;\r\n\tcase PlayerActionType::None:\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nbool track_isscrolling()\r\n{\r\n\treturn LastPlayerAction == PlayerActionType::Walk;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/track.h",
    "content": "/**\r\n * @file track.h\r\n *\r\n * Interface of functionality tracking what the mouse cursor is pointing at.\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\n\r\nvoid InvalidateTargets();\r\nvoid RepeatPlayerAction();\r\nbool track_isscrolling();\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/translation_dummy.cpp",
    "content": "/**\r\n * @file translation_dummy.cpp\r\n *\r\n * Do not edit this file manually, it is automatically generated\r\n * and updated by the extract_translation_data.py script.\r\n */\r\n#include \"utils/language.h\"\r\n\r\nnamespace {\r\n\r\nconst char *CLASS_WARRIOR_NAME = N_(\"Warrior\");\r\nconst char *CLASS_ROGUE_NAME = N_(\"Rogue\");\r\nconst char *CLASS_SORCERER_NAME = N_(\"Sorcerer\");\r\nconst char *CLASS_MONK_NAME = N_(\"Monk\");\r\nconst char *CLASS_BARD_NAME = N_(\"Bard\");\r\nconst char *CLASS_BARBARIAN_NAME = N_(\"Barbarian\");\r\nconst char *MT_NZOMBIE_NAME = P_(\"monster\", \"Zombie\");\r\nconst char *MT_BZOMBIE_NAME = P_(\"monster\", \"Ghoul\");\r\nconst char *MT_GZOMBIE_NAME = P_(\"monster\", \"Rotting Carcass\");\r\nconst char *MT_YZOMBIE_NAME = P_(\"monster\", \"Black Death\");\r\nconst char *MT_RFALLSP_NAME = P_(\"monster\", \"Fallen One\");\r\nconst char *MT_DFALLSP_NAME = P_(\"monster\", \"Carver\");\r\nconst char *MT_YFALLSP_NAME = P_(\"monster\", \"Devil Kin\");\r\nconst char *MT_BFALLSP_NAME = P_(\"monster\", \"Dark One\");\r\nconst char *MT_WSKELAX_NAME = P_(\"monster\", \"Skeleton\");\r\nconst char *MT_TSKELAX_NAME = P_(\"monster\", \"Corpse Axe\");\r\nconst char *MT_RSKELAX_NAME = P_(\"monster\", \"Burning Dead\");\r\nconst char *MT_XSKELAX_NAME = P_(\"monster\", \"Horror\");\r\nconst char *MT_NSCAV_NAME = P_(\"monster\", \"Scavenger\");\r\nconst char *MT_BSCAV_NAME = P_(\"monster\", \"Plague Eater\");\r\nconst char *MT_WSCAV_NAME = P_(\"monster\", \"Shadow Beast\");\r\nconst char *MT_YSCAV_NAME = P_(\"monster\", \"Bone Gasher\");\r\nconst char *MT_TSKELBW_NAME = P_(\"monster\", \"Corpse Bow\");\r\nconst char *MT_WSKELSD_NAME = P_(\"monster\", \"Skeleton Captain\");\r\nconst char *MT_TSKELSD_NAME = P_(\"monster\", \"Corpse Captain\");\r\nconst char *MT_RSKELSD_NAME = P_(\"monster\", \"Burning Dead Captain\");\r\nconst char *MT_XSKELSD_NAME = P_(\"monster\", \"Horror Captain\");\r\nconst char *MT_INVILORD_NAME = P_(\"monster\", \"Invisible Lord\");\r\nconst char *MT_SNEAK_NAME = P_(\"monster\", \"Hidden\");\r\nconst char *MT_STALKER_NAME = P_(\"monster\", \"Stalker\");\r\nconst char *MT_UNSEEN_NAME = P_(\"monster\", \"Unseen\");\r\nconst char *MT_ILLWEAV_NAME = P_(\"monster\", \"Illusion Weaver\");\r\nconst char *MT_LRDSAYTR_NAME = P_(\"monster\", \"Satyr Lord\");\r\nconst char *MT_NGOATMC_NAME = P_(\"monster\", \"Flesh Clan\");\r\nconst char *MT_BGOATMC_NAME = P_(\"monster\", \"Stone Clan\");\r\nconst char *MT_RGOATMC_NAME = P_(\"monster\", \"Fire Clan\");\r\nconst char *MT_GGOATMC_NAME = P_(\"monster\", \"Night Clan\");\r\nconst char *MT_FIEND_NAME = P_(\"monster\", \"Fiend\");\r\nconst char *MT_BLINK_NAME = P_(\"monster\", \"Blink\");\r\nconst char *MT_GLOOM_NAME = P_(\"monster\", \"Gloom\");\r\nconst char *MT_FAMILIAR_NAME = P_(\"monster\", \"Familiar\");\r\nconst char *MT_NACID_NAME = P_(\"monster\", \"Acid Beast\");\r\nconst char *MT_RACID_NAME = P_(\"monster\", \"Poison Spitter\");\r\nconst char *MT_BACID_NAME = P_(\"monster\", \"Pit Beast\");\r\nconst char *MT_XACID_NAME = P_(\"monster\", \"Lava Maw\");\r\nconst char *MT_SKING_NAME = P_(\"monster\", \"Skeleton King\");\r\nconst char *MT_CLEAVER_NAME = P_(\"monster\", \"The Butcher\");\r\nconst char *MT_FAT_NAME = P_(\"monster\", \"Overlord\");\r\nconst char *MT_MUDMAN_NAME = P_(\"monster\", \"Mud Man\");\r\nconst char *MT_TOAD_NAME = P_(\"monster\", \"Toad Demon\");\r\nconst char *MT_FLAYED_NAME = P_(\"monster\", \"Flayed One\");\r\nconst char *MT_WYRM_NAME = P_(\"monster\", \"Wyrm\");\r\nconst char *MT_CAVSLUG_NAME = P_(\"monster\", \"Cave Slug\");\r\nconst char *MT_DVLWYRM_NAME = P_(\"monster\", \"Devil Wyrm\");\r\nconst char *MT_DEVOUR_NAME = P_(\"monster\", \"Devourer\");\r\nconst char *MT_NMAGMA_NAME = P_(\"monster\", \"Magma Demon\");\r\nconst char *MT_YMAGMA_NAME = P_(\"monster\", \"Blood Stone\");\r\nconst char *MT_BMAGMA_NAME = P_(\"monster\", \"Hell Stone\");\r\nconst char *MT_WMAGMA_NAME = P_(\"monster\", \"Lava Lord\");\r\nconst char *MT_HORNED_NAME = P_(\"monster\", \"Horned Demon\");\r\nconst char *MT_MUDRUN_NAME = P_(\"monster\", \"Mud Runner\");\r\nconst char *MT_FROSTC_NAME = P_(\"monster\", \"Frost Charger\");\r\nconst char *MT_OBLORD_NAME = P_(\"monster\", \"Obsidian Lord\");\r\nconst char *MT_BONEDMN_NAME = P_(\"monster\", \"oldboned\");\r\nconst char *MT_REDDTH_NAME = P_(\"monster\", \"Red Death\");\r\nconst char *MT_LTCHDMN_NAME = P_(\"monster\", \"Litch Demon\");\r\nconst char *MT_UDEDBLRG_NAME = P_(\"monster\", \"Undead Balrog\");\r\nconst char *MT_INCIN_NAME = P_(\"monster\", \"Incinerator\");\r\nconst char *MT_FLAMLRD_NAME = P_(\"monster\", \"Flame Lord\");\r\nconst char *MT_DOOMFIRE_NAME = P_(\"monster\", \"Doom Fire\");\r\nconst char *MT_HELLBURN_NAME = P_(\"monster\", \"Hell Burner\");\r\nconst char *MT_STORM_NAME = P_(\"monster\", \"Red Storm\");\r\nconst char *MT_RSTORM_NAME = P_(\"monster\", \"Storm Rider\");\r\nconst char *MT_STORML_NAME = P_(\"monster\", \"Storm Lord\");\r\nconst char *MT_MAEL_NAME = P_(\"monster\", \"Maelstrom\");\r\nconst char *MT_BIGFALL_NAME = P_(\"monster\", \"Devil Kin Brute\");\r\nconst char *MT_WINGED_NAME = P_(\"monster\", \"Winged-Demon\");\r\nconst char *MT_GARGOYLE_NAME = P_(\"monster\", \"Gargoyle\");\r\nconst char *MT_BLOODCLW_NAME = P_(\"monster\", \"Blood Claw\");\r\nconst char *MT_DEATHW_NAME = P_(\"monster\", \"Death Wing\");\r\nconst char *MT_MEGA_NAME = P_(\"monster\", \"Slayer\");\r\nconst char *MT_GUARD_NAME = P_(\"monster\", \"Guardian\");\r\nconst char *MT_VTEXLRD_NAME = P_(\"monster\", \"Vortex Lord\");\r\nconst char *MT_BALROG_NAME = P_(\"monster\", \"Balrog\");\r\nconst char *MT_NSNAKE_NAME = P_(\"monster\", \"Cave Viper\");\r\nconst char *MT_RSNAKE_NAME = P_(\"monster\", \"Fire Drake\");\r\nconst char *MT_BSNAKE_NAME = P_(\"monster\", \"Gold Viper\");\r\nconst char *MT_GSNAKE_NAME = P_(\"monster\", \"Azure Drake\");\r\nconst char *MT_NBLACK_NAME = P_(\"monster\", \"Black Knight\");\r\nconst char *MT_RTBLACK_NAME = P_(\"monster\", \"Doom Guard\");\r\nconst char *MT_BTBLACK_NAME = P_(\"monster\", \"Steel Lord\");\r\nconst char *MT_RBLACK_NAME = P_(\"monster\", \"Blood Knight\");\r\nconst char *MT_UNRAV_NAME = P_(\"monster\", \"The Shredded\");\r\nconst char *MT_HOLOWONE_NAME = P_(\"monster\", \"Hollow One\");\r\nconst char *MT_PAINMSTR_NAME = P_(\"monster\", \"Pain Master\");\r\nconst char *MT_REALWEAV_NAME = P_(\"monster\", \"Reality Weaver\");\r\nconst char *MT_SUCCUBUS_NAME = P_(\"monster\", \"Succubus\");\r\nconst char *MT_SNOWWICH_NAME = P_(\"monster\", \"Snow Witch\");\r\nconst char *MT_HLSPWN_NAME = P_(\"monster\", \"Hell Spawn\");\r\nconst char *MT_SOLBRNR_NAME = P_(\"monster\", \"Soul Burner\");\r\nconst char *MT_COUNSLR_NAME = P_(\"monster\", \"Counselor\");\r\nconst char *MT_MAGISTR_NAME = P_(\"monster\", \"Magistrate\");\r\nconst char *MT_CABALIST_NAME = P_(\"monster\", \"Cabalist\");\r\nconst char *MT_ADVOCATE_NAME = P_(\"monster\", \"Advocate\");\r\nconst char *MT_GOLEM_NAME = P_(\"monster\", \"Golem\");\r\nconst char *MT_DIABLO_NAME = P_(\"monster\", \"The Dark Lord\");\r\nconst char *MT_DARKMAGE_NAME = P_(\"monster\", \"The Arch-Litch Malignus\");\r\nconst char *GHARBAD_THE_WEAK_NAME = P_(\"monster\", \"Gharbad the Weak\");\r\nconst char *ZHAR_THE_MAD_NAME = P_(\"monster\", \"Zhar the Mad\");\r\nconst char *SNOTSPILL_NAME = P_(\"monster\", \"Snotspill\");\r\nconst char *ARCH_BISHOP_LAZARUS_NAME = P_(\"monster\", \"Arch-Bishop Lazarus\");\r\nconst char *RED_VEX_NAME = P_(\"monster\", \"Red Vex\");\r\nconst char *BLACK_JADE_NAME = P_(\"monster\", \"Black Jade\");\r\nconst char *LACHDANAN_NAME = P_(\"monster\", \"Lachdanan\");\r\nconst char *WARLORD_OF_BLOOD_NAME = P_(\"monster\", \"Warlord of Blood\");\r\nconst char *HORK_DEMON_NAME = P_(\"monster\", \"Hork Demon\");\r\nconst char *THE_DEFILER_NAME = P_(\"monster\", \"The Defiler\");\r\nconst char *NA_KRUL_NAME = P_(\"monster\", \"Na-Krul\");\r\nconst char *BONEHEAD_KEENAXE_NAME = P_(\"monster\", \"Bonehead Keenaxe\");\r\nconst char *BLADESKIN_THE_SLASHER_NAME = P_(\"monster\", \"Bladeskin the Slasher\");\r\nconst char *SOULPUS_NAME = P_(\"monster\", \"Soulpus\");\r\nconst char *PUKERAT_THE_UNCLEAN_NAME = P_(\"monster\", \"Pukerat the Unclean\");\r\nconst char *BONERIPPER_NAME = P_(\"monster\", \"Boneripper\");\r\nconst char *ROTFEAST_THE_HUNGRY_NAME = P_(\"monster\", \"Rotfeast the Hungry\");\r\nconst char *GUTSHANK_THE_QUICK_NAME = P_(\"monster\", \"Gutshank the Quick\");\r\nconst char *BROKENHEAD_BANGSHIELD_NAME = P_(\"monster\", \"Brokenhead Bangshield\");\r\nconst char *BONGO_NAME = P_(\"monster\", \"Bongo\");\r\nconst char *ROTCARNAGE_NAME = P_(\"monster\", \"Rotcarnage\");\r\nconst char *SHADOWBITE_NAME = P_(\"monster\", \"Shadowbite\");\r\nconst char *DEADEYE_NAME = P_(\"monster\", \"Deadeye\");\r\nconst char *MADEYE_THE_DEAD_NAME = P_(\"monster\", \"Madeye the Dead\");\r\nconst char *EL_CHUPACABRAS_NAME = P_(\"monster\", \"El Chupacabras\");\r\nconst char *SKULLFIRE_NAME = P_(\"monster\", \"Skullfire\");\r\nconst char *WARPSKULL_NAME = P_(\"monster\", \"Warpskull\");\r\nconst char *GORETONGUE_NAME = P_(\"monster\", \"Goretongue\");\r\nconst char *PULSECRAWLER_NAME = P_(\"monster\", \"Pulsecrawler\");\r\nconst char *MOONBENDER_NAME = P_(\"monster\", \"Moonbender\");\r\nconst char *WRATHRAVEN_NAME = P_(\"monster\", \"Wrathraven\");\r\nconst char *SPINEEATER_NAME = P_(\"monster\", \"Spineeater\");\r\nconst char *BLACKASH_THE_BURNING_NAME = P_(\"monster\", \"Blackash the Burning\");\r\nconst char *SHADOWCROW_NAME = P_(\"monster\", \"Shadowcrow\");\r\nconst char *BLIGHTSTONE_THE_WEAK_NAME = P_(\"monster\", \"Blightstone the Weak\");\r\nconst char *BILEFROTH_THE_PIT_MASTER_NAME = P_(\"monster\", \"Bilefroth the Pit Master\");\r\nconst char *BLOODSKIN_DARKBOW_NAME = P_(\"monster\", \"Bloodskin Darkbow\");\r\nconst char *FOULWING_NAME = P_(\"monster\", \"Foulwing\");\r\nconst char *SHADOWDRINKER_NAME = P_(\"monster\", \"Shadowdrinker\");\r\nconst char *HAZESHIFTER_NAME = P_(\"monster\", \"Hazeshifter\");\r\nconst char *DEATHSPIT_NAME = P_(\"monster\", \"Deathspit\");\r\nconst char *BLOODGUTTER_NAME = P_(\"monster\", \"Bloodgutter\");\r\nconst char *DEATHSHADE_FLESHMAUL_NAME = P_(\"monster\", \"Deathshade Fleshmaul\");\r\nconst char *WARMAGGOT_THE_MAD_NAME = P_(\"monster\", \"Warmaggot the Mad\");\r\nconst char *GLASSKULL_THE_JAGGED_NAME = P_(\"monster\", \"Glasskull the Jagged\");\r\nconst char *BLIGHTFIRE_NAME = P_(\"monster\", \"Blightfire\");\r\nconst char *NIGHTWING_THE_COLD_NAME = P_(\"monster\", \"Nightwing the Cold\");\r\nconst char *GORESTONE_NAME = P_(\"monster\", \"Gorestone\");\r\nconst char *BRONZEFIST_FIRESTONE_NAME = P_(\"monster\", \"Bronzefist Firestone\");\r\nconst char *WRATHFIRE_THE_DOOMED_NAME = P_(\"monster\", \"Wrathfire the Doomed\");\r\nconst char *FIREWOUND_THE_GRIM_NAME = P_(\"monster\", \"Firewound the Grim\");\r\nconst char *BARON_SLUDGE_NAME = P_(\"monster\", \"Baron Sludge\");\r\nconst char *BLIGHTHORN_STEELMACE_NAME = P_(\"monster\", \"Blighthorn Steelmace\");\r\nconst char *CHAOSHOWLER_NAME = P_(\"monster\", \"Chaoshowler\");\r\nconst char *DOOMGRIN_THE_ROTTING_NAME = P_(\"monster\", \"Doomgrin the Rotting\");\r\nconst char *MADBURNER_NAME = P_(\"monster\", \"Madburner\");\r\nconst char *BONESAW_THE_LITCH_NAME = P_(\"monster\", \"Bonesaw the Litch\");\r\nconst char *BREAKSPINE_NAME = P_(\"monster\", \"Breakspine\");\r\nconst char *DEVILSKULL_SHARPBONE_NAME = P_(\"monster\", \"Devilskull Sharpbone\");\r\nconst char *BROKENSTORM_NAME = P_(\"monster\", \"Brokenstorm\");\r\nconst char *STORMBANE_NAME = P_(\"monster\", \"Stormbane\");\r\nconst char *OOZEDROOL_NAME = P_(\"monster\", \"Oozedrool\");\r\nconst char *GOLDBLIGHT_OF_THE_FLAME_NAME = P_(\"monster\", \"Goldblight of the Flame\");\r\nconst char *BLACKSTORM_NAME = P_(\"monster\", \"Blackstorm\");\r\nconst char *PLAGUEWRATH_NAME = P_(\"monster\", \"Plaguewrath\");\r\nconst char *THE_FLAYER_NAME = P_(\"monster\", \"The Flayer\");\r\nconst char *BLUEHORN_NAME = P_(\"monster\", \"Bluehorn\");\r\nconst char *WARPFIRE_HELLSPAWN_NAME = P_(\"monster\", \"Warpfire Hellspawn\");\r\nconst char *FANGSPEIR_NAME = P_(\"monster\", \"Fangspeir\");\r\nconst char *FESTERSKULL_NAME = P_(\"monster\", \"Festerskull\");\r\nconst char *LIONSKULL_THE_BENT_NAME = P_(\"monster\", \"Lionskull the Bent\");\r\nconst char *BLACKTONGUE_NAME = P_(\"monster\", \"Blacktongue\");\r\nconst char *VILETOUCH_NAME = P_(\"monster\", \"Viletouch\");\r\nconst char *VIPERFLAME_NAME = P_(\"monster\", \"Viperflame\");\r\nconst char *FANGSKIN_NAME = P_(\"monster\", \"Fangskin\");\r\nconst char *WITCHFIRE_THE_UNHOLY_NAME = P_(\"monster\", \"Witchfire the Unholy\");\r\nconst char *BLACKSKULL_NAME = P_(\"monster\", \"Blackskull\");\r\nconst char *SOULSLASH_NAME = P_(\"monster\", \"Soulslash\");\r\nconst char *WINDSPAWN_NAME = P_(\"monster\", \"Windspawn\");\r\nconst char *LORD_OF_THE_PIT_NAME = P_(\"monster\", \"Lord of the Pit\");\r\nconst char *RUSTWEAVER_NAME = P_(\"monster\", \"Rustweaver\");\r\nconst char *HOWLINGIRE_THE_SHADE_NAME = P_(\"monster\", \"Howlingire the Shade\");\r\nconst char *DOOMCLOUD_NAME = P_(\"monster\", \"Doomcloud\");\r\nconst char *BLOODMOON_SOULFIRE_NAME = P_(\"monster\", \"Bloodmoon Soulfire\");\r\nconst char *WITCHMOON_NAME = P_(\"monster\", \"Witchmoon\");\r\nconst char *GOREFEAST_NAME = P_(\"monster\", \"Gorefeast\");\r\nconst char *GRAYWAR_THE_SLAYER_NAME = P_(\"monster\", \"Graywar the Slayer\");\r\nconst char *DREADJUDGE_NAME = P_(\"monster\", \"Dreadjudge\");\r\nconst char *STAREYE_THE_WITCH_NAME = P_(\"monster\", \"Stareye the Witch\");\r\nconst char *STEELSKULL_THE_HUNTER_NAME = P_(\"monster\", \"Steelskull the Hunter\");\r\nconst char *SIR_GORASH_NAME = P_(\"monster\", \"Sir Gorash\");\r\nconst char *THE_VIZIER_NAME = P_(\"monster\", \"The Vizier\");\r\nconst char *ZAMPHIR_NAME = P_(\"monster\", \"Zamphir\");\r\nconst char *BLOODLUST_NAME = P_(\"monster\", \"Bloodlust\");\r\nconst char *WEBWIDOW_NAME = P_(\"monster\", \"Webwidow\");\r\nconst char *FLESHDANCER_NAME = P_(\"monster\", \"Fleshdancer\");\r\nconst char *GRIMSPIKE_NAME = P_(\"monster\", \"Grimspike\");\r\nconst char *DOOMLOCK_NAME = P_(\"monster\", \"Doomlock\");\r\nconst char *IDI_GOLD_NAME = N_(\"Gold\");\r\nconst char *IDI_WARRIOR_NAME = N_(\"Short Sword\");\r\nconst char *IDI_WARRSHLD_NAME = N_(\"Buckler\");\r\nconst char *IDI_WARRCLUB_NAME = N_(\"Club\");\r\nconst char *IDI_ROGUE_NAME = N_(\"Short Bow\");\r\nconst char *IDI_SORCERER_NAME = N_(\"Short Staff of Mana\");\r\nconst char *IDI_CLEAVER_NAME = N_(\"Cleaver\");\r\nconst char *IDI_SKCROWN_NAME = N_(\"The Undead Crown\");\r\nconst char *IDI_INFRARING_NAME = N_(\"Empyrean Band\");\r\nconst char *IDI_ROCK_NAME = N_(\"Magic Rock\");\r\nconst char *IDI_OPTAMULET_NAME = N_(\"Optic Amulet\");\r\nconst char *IDI_TRING_NAME = N_(\"Ring of Truth\");\r\nconst char *IDI_BANNER_NAME = N_(\"Tavern Sign\");\r\nconst char *IDI_HARCREST_NAME = N_(\"Harlequin Crest\");\r\nconst char *IDI_STEELVEIL_NAME = N_(\"Veil of Steel\");\r\nconst char *IDI_GLDNELIX_NAME = N_(\"Golden Elixir\");\r\nconst char *IDI_ANVIL_NAME = N_(\"Anvil of Fury\");\r\nconst char *IDI_MUSHROOM_NAME = N_(\"Black Mushroom\");\r\nconst char *IDI_BRAIN_NAME = N_(\"Brain\");\r\nconst char *IDI_FUNGALTM_NAME = N_(\"Fungal Tome\");\r\nconst char *IDI_SPECELIX_NAME = N_(\"Spectral Elixir\");\r\nconst char *IDI_BLDSTONE_NAME = N_(\"Blood Stone\");\r\nconst char *IDI_MAPOFDOOM_NAME = N_(\"Cathedral Map\");\r\nconst char *IDI_EAR_NAME = N_(\"Ear\");\r\nconst char *IDI_HEAL_NAME = N_(\"Potion of Healing\");\r\nconst char *IDI_MANA_NAME = N_(\"Potion of Mana\");\r\nconst char *IDI_IDENTIFY_NAME = N_(\"Scroll of Identify\");\r\nconst char *IDI_PORTAL_NAME = N_(\"Scroll of Town Portal\");\r\nconst char *IDI_ARMOFVAL_NAME = N_(\"Arkaine's Valor\");\r\nconst char *IDI_FULLHEAL_NAME = N_(\"Potion of Full Healing\");\r\nconst char *IDI_FULLMANA_NAME = N_(\"Potion of Full Mana\");\r\nconst char *IDI_GRISWOLD_NAME = N_(\"Griswold's Edge\");\r\nconst char *IDI_LGTFORGE_NAME = N_(\"Bovine Plate\");\r\nconst char *IDI_LAZSTAFF_NAME = N_(\"Staff of Lazarus\");\r\nconst char *IDI_RESURRECT_NAME = N_(\"Scroll of Resurrect\");\r\nconst char *IDI_OIL_NAME = N_(\"Blacksmith Oil\");\r\nconst char *IDI_SHORTSTAFF_NAME = N_(\"Short Staff\");\r\nconst char *IDI_BARDSWORD_NAME = N_(\"Sword\");\r\nconst char *IDI_BARDDAGGER_NAME = N_(\"Dagger\");\r\nconst char *IDI_RUNEBOMB_NAME = N_(\"Rune Bomb\");\r\nconst char *IDI_THEODORE_NAME = N_(\"Theodore\");\r\nconst char *IDI_AURIC_NAME = N_(\"Auric Amulet\");\r\nconst char *IDI_NOTE1_NAME = N_(\"Torn Note 1\");\r\nconst char *IDI_NOTE2_NAME = N_(\"Torn Note 2\");\r\nconst char *IDI_NOTE3_NAME = N_(\"Torn Note 3\");\r\nconst char *IDI_FULLNOTE_NAME = N_(\"Reconstructed Note\");\r\nconst char *IDI_BROWNSUIT_NAME = N_(\"Brown Suit\");\r\nconst char *IDI_GREYSUIT_NAME = N_(\"Grey Suit\");\r\nconst char *ITEM_48_NAME = N_(\"Cap\");\r\nconst char *ITEM_49_NAME = N_(\"Skull Cap\");\r\nconst char *ITEM_50_NAME = N_(\"Helm\");\r\nconst char *ITEM_51_NAME = N_(\"Full Helm\");\r\nconst char *ITEM_52_NAME = N_(\"Crown\");\r\nconst char *ITEM_53_NAME = N_(\"Great Helm\");\r\nconst char *ITEM_54_NAME = N_(\"Cape\");\r\nconst char *ITEM_55_NAME = N_(\"Rags\");\r\nconst char *ITEM_56_NAME = N_(\"Cloak\");\r\nconst char *ITEM_57_NAME = N_(\"Robe\");\r\nconst char *ITEM_58_NAME = N_(\"Quilted Armor\");\r\nconst char *ITEM_58_SHORT_NAME = N_(\"Armor\");\r\nconst char *ITEM_59_NAME = N_(\"Leather Armor\");\r\nconst char *ITEM_60_NAME = N_(\"Hard Leather Armor\");\r\nconst char *ITEM_61_NAME = N_(\"Studded Leather Armor\");\r\nconst char *ITEM_62_NAME = N_(\"Ring Mail\");\r\nconst char *ITEM_62_SHORT_NAME = N_(\"Mail\");\r\nconst char *ITEM_63_NAME = N_(\"Chain Mail\");\r\nconst char *ITEM_64_NAME = N_(\"Scale Mail\");\r\nconst char *ITEM_65_NAME = N_(\"Breast Plate\");\r\nconst char *ITEM_65_SHORT_NAME = N_(\"Plate\");\r\nconst char *ITEM_66_NAME = N_(\"Splint Mail\");\r\nconst char *ITEM_67_NAME = N_(\"Plate Mail\");\r\nconst char *ITEM_68_NAME = N_(\"Field Plate\");\r\nconst char *ITEM_69_NAME = N_(\"Gothic Plate\");\r\nconst char *ITEM_70_NAME = N_(\"Full Plate Mail\");\r\nconst char *ITEM_71_SHORT_NAME = N_(\"Shield\");\r\nconst char *ITEM_72_NAME = N_(\"Small Shield\");\r\nconst char *ITEM_73_NAME = N_(\"Large Shield\");\r\nconst char *ITEM_74_NAME = N_(\"Kite Shield\");\r\nconst char *ITEM_75_NAME = N_(\"Tower Shield\");\r\nconst char *ITEM_76_NAME = N_(\"Gothic Shield\");\r\nconst char *ITEM_81_NAME = N_(\"Potion of Rejuvenation\");\r\nconst char *ITEM_82_NAME = N_(\"Potion of Full Rejuvenation\");\r\nconst char *ITEM_84_NAME = N_(\"Oil of Accuracy\");\r\nconst char *ITEM_85_NAME = N_(\"Oil of Sharpness\");\r\nconst char *ITEM_86_NAME = N_(\"Oil\");\r\nconst char *ITEM_87_NAME = N_(\"Elixir of Strength\");\r\nconst char *ITEM_88_NAME = N_(\"Elixir of Magic\");\r\nconst char *ITEM_89_NAME = N_(\"Elixir of Dexterity\");\r\nconst char *ITEM_90_NAME = N_(\"Elixir of Vitality\");\r\nconst char *ITEM_91_NAME = N_(\"Scroll of Healing\");\r\nconst char *ITEM_92_NAME = N_(\"Scroll of Search\");\r\nconst char *ITEM_93_NAME = N_(\"Scroll of Lightning\");\r\nconst char *ITEM_96_NAME = N_(\"Scroll of Fire Wall\");\r\nconst char *ITEM_97_NAME = N_(\"Scroll of Inferno\");\r\nconst char *ITEM_99_NAME = N_(\"Scroll of Flash\");\r\nconst char *ITEM_100_NAME = N_(\"Scroll of Infravision\");\r\nconst char *ITEM_101_NAME = N_(\"Scroll of Phasing\");\r\nconst char *ITEM_102_NAME = N_(\"Scroll of Mana Shield\");\r\nconst char *ITEM_103_NAME = N_(\"Scroll of Flame Wave\");\r\nconst char *ITEM_104_NAME = N_(\"Scroll of Fireball\");\r\nconst char *ITEM_105_NAME = N_(\"Scroll of Stone Curse\");\r\nconst char *ITEM_106_NAME = N_(\"Scroll of Chain Lightning\");\r\nconst char *ITEM_107_NAME = N_(\"Scroll of Guardian\");\r\nconst char *ITEM_109_NAME = N_(\"Scroll of Nova\");\r\nconst char *ITEM_110_NAME = N_(\"Scroll of Golem\");\r\nconst char *ITEM_112_NAME = N_(\"Scroll of Teleport\");\r\nconst char *ITEM_113_NAME = N_(\"Scroll of Apocalypse\");\r\nconst char *ITEM_120_NAME = N_(\"Falchion\");\r\nconst char *ITEM_121_NAME = N_(\"Scimitar\");\r\nconst char *ITEM_122_NAME = N_(\"Claymore\");\r\nconst char *ITEM_123_NAME = N_(\"Blade\");\r\nconst char *ITEM_124_NAME = N_(\"Sabre\");\r\nconst char *ITEM_125_NAME = N_(\"Long Sword\");\r\nconst char *ITEM_126_NAME = N_(\"Broad Sword\");\r\nconst char *ITEM_127_NAME = N_(\"Bastard Sword\");\r\nconst char *ITEM_128_NAME = N_(\"Two-Handed Sword\");\r\nconst char *ITEM_129_NAME = N_(\"Great Sword\");\r\nconst char *ITEM_130_NAME = N_(\"Small Axe\");\r\nconst char *ITEM_130_SHORT_NAME = N_(\"Axe\");\r\nconst char *ITEM_132_NAME = N_(\"Large Axe\");\r\nconst char *ITEM_133_NAME = N_(\"Broad Axe\");\r\nconst char *ITEM_134_NAME = N_(\"Battle Axe\");\r\nconst char *ITEM_135_NAME = N_(\"Great Axe\");\r\nconst char *ITEM_136_NAME = N_(\"Mace\");\r\nconst char *ITEM_137_NAME = N_(\"Morning Star\");\r\nconst char *ITEM_138_NAME = N_(\"War Hammer\");\r\nconst char *ITEM_138_SHORT_NAME = N_(\"Hammer\");\r\nconst char *ITEM_139_NAME = N_(\"Spiked Club\");\r\nconst char *ITEM_141_NAME = N_(\"Flail\");\r\nconst char *ITEM_142_NAME = N_(\"Maul\");\r\nconst char *ITEM_143_SHORT_NAME = N_(\"Bow\");\r\nconst char *ITEM_144_NAME = N_(\"Hunter's Bow\");\r\nconst char *ITEM_145_NAME = N_(\"Long Bow\");\r\nconst char *ITEM_146_NAME = N_(\"Composite Bow\");\r\nconst char *IDI_SHORT_BATTLE_BOW_NAME = N_(\"Short Battle Bow\");\r\nconst char *ITEM_148_NAME = N_(\"Long Battle Bow\");\r\nconst char *ITEM_149_NAME = N_(\"Short War Bow\");\r\nconst char *ITEM_150_NAME = N_(\"Long War Bow\");\r\nconst char *ITEM_151_SHORT_NAME = N_(\"Staff\");\r\nconst char *ITEM_152_NAME = N_(\"Long Staff\");\r\nconst char *ITEM_153_NAME = N_(\"Composite Staff\");\r\nconst char *ITEM_154_NAME = N_(\"Quarter Staff\");\r\nconst char *ITEM_155_NAME = N_(\"War Staff\");\r\nconst char *ITEM_156_NAME = N_(\"Ring\");\r\nconst char *ITEM_159_NAME = N_(\"Amulet\");\r\nconst char *ITEM_161_NAME = N_(\"Rune of Fire\");\r\nconst char *ITEM_161_SHORT_NAME = N_(\"Rune\");\r\nconst char *ITEM_162_NAME = N_(\"Rune of Lightning\");\r\nconst char *ITEM_163_NAME = N_(\"Greater Rune of Fire\");\r\nconst char *ITEM_164_NAME = N_(\"Greater Rune of Lightning\");\r\nconst char *ITEM_165_NAME = N_(\"Rune of Stone\");\r\nconst char *ITEM_166_NAME = N_(\"Short Staff of Charged Bolt\");\r\nconst char *IDI_ARENAPOT_NAME = N_(\"Arena Potion\");\r\nconst char *UNIQUE_ITEM_0_NAME = N_(\"The Butcher's Cleaver\");\r\nconst char *UNIQUE_ITEM_9_NAME = N_(\"Lightforge\");\r\nconst char *UNIQUE_ITEM_10_NAME = N_(\"The Rift Bow\");\r\nconst char *UNIQUE_ITEM_11_NAME = N_(\"The Needler\");\r\nconst char *UNIQUE_ITEM_12_NAME = N_(\"The Celestial Bow\");\r\nconst char *UNIQUE_ITEM_13_NAME = N_(\"Deadly Hunter\");\r\nconst char *UNIQUE_ITEM_14_NAME = N_(\"Bow of the Dead\");\r\nconst char *UNIQUE_ITEM_15_NAME = N_(\"The Blackoak Bow\");\r\nconst char *UNIQUE_ITEM_16_NAME = N_(\"Flamedart\");\r\nconst char *UNIQUE_ITEM_17_NAME = N_(\"Fleshstinger\");\r\nconst char *UNIQUE_ITEM_18_NAME = N_(\"Windforce\");\r\nconst char *UNIQUE_ITEM_19_NAME = N_(\"Eaglehorn\");\r\nconst char *UNIQUE_ITEM_20_NAME = N_(\"Gonnagal's Dirk\");\r\nconst char *UNIQUE_ITEM_21_NAME = N_(\"The Defender\");\r\nconst char *UNIQUE_ITEM_22_NAME = N_(\"Gryphon's Claw\");\r\nconst char *UNIQUE_ITEM_23_NAME = N_(\"Black Razor\");\r\nconst char *UNIQUE_ITEM_24_NAME = N_(\"Gibbous Moon\");\r\nconst char *UNIQUE_ITEM_25_NAME = N_(\"Ice Shank\");\r\nconst char *UNIQUE_ITEM_26_NAME = N_(\"The Executioner's Blade\");\r\nconst char *UNIQUE_ITEM_27_NAME = N_(\"The Bonesaw\");\r\nconst char *UNIQUE_ITEM_28_NAME = N_(\"Shadowhawk\");\r\nconst char *UNIQUE_ITEM_29_NAME = N_(\"Wizardspike\");\r\nconst char *UNIQUE_ITEM_30_NAME = N_(\"Lightsabre\");\r\nconst char *UNIQUE_ITEM_31_NAME = N_(\"The Falcon's Talon\");\r\nconst char *UNIQUE_ITEM_32_NAME = N_(\"Inferno\");\r\nconst char *UNIQUE_ITEM_33_NAME = N_(\"Doombringer\");\r\nconst char *UNIQUE_ITEM_34_NAME = N_(\"The Grizzly\");\r\nconst char *UNIQUE_ITEM_35_NAME = N_(\"The Grandfather\");\r\nconst char *UNIQUE_ITEM_36_NAME = N_(\"The Mangler\");\r\nconst char *UNIQUE_ITEM_37_NAME = N_(\"Sharp Beak\");\r\nconst char *UNIQUE_ITEM_38_NAME = N_(\"BloodSlayer\");\r\nconst char *UNIQUE_ITEM_39_NAME = N_(\"The Celestial Axe\");\r\nconst char *UNIQUE_ITEM_40_NAME = N_(\"Wicked Axe\");\r\nconst char *UNIQUE_ITEM_41_NAME = N_(\"Stonecleaver\");\r\nconst char *UNIQUE_ITEM_42_NAME = N_(\"Aguinara's Hatchet\");\r\nconst char *UNIQUE_ITEM_43_NAME = N_(\"Hellslayer\");\r\nconst char *UNIQUE_ITEM_44_NAME = N_(\"Messerschmidt's Reaver\");\r\nconst char *UNIQUE_ITEM_45_NAME = N_(\"Crackrust\");\r\nconst char *UNIQUE_ITEM_46_NAME = N_(\"Hammer of Jholm\");\r\nconst char *UNIQUE_ITEM_47_NAME = N_(\"Civerb's Cudgel\");\r\nconst char *UNIQUE_ITEM_48_NAME = N_(\"The Celestial Star\");\r\nconst char *UNIQUE_ITEM_49_NAME = N_(\"Baranar's Star\");\r\nconst char *UNIQUE_ITEM_50_NAME = N_(\"Gnarled Root\");\r\nconst char *UNIQUE_ITEM_51_NAME = N_(\"The Cranium Basher\");\r\nconst char *UNIQUE_ITEM_52_NAME = N_(\"Schaefer's Hammer\");\r\nconst char *UNIQUE_ITEM_53_NAME = N_(\"Dreamflange\");\r\nconst char *UNIQUE_ITEM_54_NAME = N_(\"Staff of Shadows\");\r\nconst char *UNIQUE_ITEM_55_NAME = N_(\"Immolator\");\r\nconst char *UNIQUE_ITEM_56_NAME = N_(\"Storm Spire\");\r\nconst char *UNIQUE_ITEM_57_NAME = N_(\"Gleamsong\");\r\nconst char *UNIQUE_ITEM_58_NAME = N_(\"Thundercall\");\r\nconst char *UNIQUE_ITEM_59_NAME = N_(\"The Protector\");\r\nconst char *UNIQUE_ITEM_60_NAME = N_(\"Naj's Puzzler\");\r\nconst char *UNIQUE_ITEM_61_NAME = N_(\"Mindcry\");\r\nconst char *UNIQUE_ITEM_62_NAME = N_(\"Rod of Onan\");\r\nconst char *UNIQUE_ITEM_63_NAME = N_(\"Helm of Spirits\");\r\nconst char *UNIQUE_ITEM_64_NAME = N_(\"Thinking Cap\");\r\nconst char *UNIQUE_ITEM_65_NAME = N_(\"OverLord's Helm\");\r\nconst char *UNIQUE_ITEM_66_NAME = N_(\"Fool's Crest\");\r\nconst char *UNIQUE_ITEM_67_NAME = N_(\"Gotterdamerung\");\r\nconst char *UNIQUE_ITEM_68_NAME = N_(\"Royal Circlet\");\r\nconst char *UNIQUE_ITEM_69_NAME = N_(\"Torn Flesh of Souls\");\r\nconst char *UNIQUE_ITEM_70_NAME = N_(\"The Gladiator's Bane\");\r\nconst char *UNIQUE_ITEM_71_NAME = N_(\"The Rainbow Cloak\");\r\nconst char *UNIQUE_ITEM_72_NAME = N_(\"Leather of Aut\");\r\nconst char *UNIQUE_ITEM_73_NAME = N_(\"Wisdom's Wrap\");\r\nconst char *UNIQUE_ITEM_74_NAME = N_(\"Sparking Mail\");\r\nconst char *UNIQUE_ITEM_75_NAME = N_(\"Scavenger Carapace\");\r\nconst char *UNIQUE_ITEM_76_NAME = N_(\"Nightscape\");\r\nconst char *UNIQUE_ITEM_77_NAME = N_(\"Naj's Light Plate\");\r\nconst char *UNIQUE_ITEM_78_NAME = N_(\"Demonspike Coat\");\r\nconst char *UNIQUE_ITEM_79_NAME = N_(\"The Deflector\");\r\nconst char *UNIQUE_ITEM_80_NAME = N_(\"Split Skull Shield\");\r\nconst char *UNIQUE_ITEM_81_NAME = N_(\"Dragon's Breach\");\r\nconst char *UNIQUE_ITEM_82_NAME = N_(\"Blackoak Shield\");\r\nconst char *UNIQUE_ITEM_83_NAME = N_(\"Holy Defender\");\r\nconst char *UNIQUE_ITEM_84_NAME = N_(\"Stormshield\");\r\nconst char *UNIQUE_ITEM_85_NAME = N_(\"Bramble\");\r\nconst char *UNIQUE_ITEM_86_NAME = N_(\"Ring of Regha\");\r\nconst char *UNIQUE_ITEM_87_NAME = N_(\"The Bleeder\");\r\nconst char *UNIQUE_ITEM_88_NAME = N_(\"Constricting Ring\");\r\nconst char *UNIQUE_ITEM_89_NAME = N_(\"Ring of Engagement\");\r\nconst char *ITEM_PREFIX_0_NAME = N_(\"Tin\");\r\nconst char *ITEM_PREFIX_1_NAME = N_(\"Brass\");\r\nconst char *ITEM_PREFIX_2_NAME = N_(\"Bronze\");\r\nconst char *ITEM_PREFIX_3_NAME = N_(\"Iron\");\r\nconst char *ITEM_PREFIX_4_NAME = N_(\"Steel\");\r\nconst char *ITEM_PREFIX_5_NAME = N_(\"Silver\");\r\nconst char *ITEM_PREFIX_7_NAME = N_(\"Platinum\");\r\nconst char *ITEM_PREFIX_8_NAME = N_(\"Mithril\");\r\nconst char *ITEM_PREFIX_9_NAME = N_(\"Meteoric\");\r\nconst char *ITEM_PREFIX_10_NAME = N_(\"Weird\");\r\nconst char *ITEM_PREFIX_11_NAME = N_(\"Strange\");\r\nconst char *ITEM_PREFIX_12_NAME = N_(\"Useless\");\r\nconst char *ITEM_PREFIX_13_NAME = N_(\"Bent\");\r\nconst char *ITEM_PREFIX_14_NAME = N_(\"Weak\");\r\nconst char *ITEM_PREFIX_15_NAME = N_(\"Jagged\");\r\nconst char *ITEM_PREFIX_16_NAME = N_(\"Deadly\");\r\nconst char *ITEM_PREFIX_17_NAME = N_(\"Heavy\");\r\nconst char *ITEM_PREFIX_18_NAME = N_(\"Vicious\");\r\nconst char *ITEM_PREFIX_19_NAME = N_(\"Brutal\");\r\nconst char *ITEM_PREFIX_20_NAME = N_(\"Massive\");\r\nconst char *ITEM_PREFIX_21_NAME = N_(\"Savage\");\r\nconst char *ITEM_PREFIX_22_NAME = N_(\"Ruthless\");\r\nconst char *ITEM_PREFIX_23_NAME = N_(\"Merciless\");\r\nconst char *ITEM_PREFIX_24_NAME = N_(\"Clumsy\");\r\nconst char *ITEM_PREFIX_25_NAME = N_(\"Dull\");\r\nconst char *ITEM_PREFIX_26_NAME = N_(\"Sharp\");\r\nconst char *ITEM_PREFIX_27_NAME = N_(\"Fine\");\r\nconst char *ITEM_PREFIX_28_NAME = N_(\"Warrior's\");\r\nconst char *ITEM_PREFIX_29_NAME = N_(\"Soldier's\");\r\nconst char *ITEM_PREFIX_30_NAME = N_(\"Lord's\");\r\nconst char *ITEM_PREFIX_31_NAME = N_(\"Knight's\");\r\nconst char *ITEM_PREFIX_32_NAME = N_(\"Master's\");\r\nconst char *ITEM_PREFIX_33_NAME = N_(\"Champion's\");\r\nconst char *ITEM_PREFIX_34_NAME = N_(\"King's\");\r\nconst char *ITEM_PREFIX_35_NAME = N_(\"Vulnerable\");\r\nconst char *ITEM_PREFIX_36_NAME = N_(\"Rusted\");\r\nconst char *ITEM_PREFIX_38_NAME = N_(\"Strong\");\r\nconst char *ITEM_PREFIX_39_NAME = N_(\"Grand\");\r\nconst char *ITEM_PREFIX_40_NAME = N_(\"Valiant\");\r\nconst char *ITEM_PREFIX_41_NAME = N_(\"Glorious\");\r\nconst char *ITEM_PREFIX_42_NAME = N_(\"Blessed\");\r\nconst char *ITEM_PREFIX_43_NAME = N_(\"Saintly\");\r\nconst char *ITEM_PREFIX_44_NAME = N_(\"Awesome\");\r\nconst char *ITEM_PREFIX_45_NAME = N_(\"Holy\");\r\nconst char *ITEM_PREFIX_46_NAME = N_(\"Godly\");\r\nconst char *ITEM_PREFIX_47_NAME = N_(\"Red\");\r\nconst char *ITEM_PREFIX_48_NAME = N_(\"Crimson\");\r\nconst char *ITEM_PREFIX_50_NAME = N_(\"Garnet\");\r\nconst char *ITEM_PREFIX_51_NAME = N_(\"Ruby\");\r\nconst char *ITEM_PREFIX_52_NAME = N_(\"Blue\");\r\nconst char *ITEM_PREFIX_53_NAME = N_(\"Azure\");\r\nconst char *ITEM_PREFIX_54_NAME = N_(\"Lapis\");\r\nconst char *ITEM_PREFIX_55_NAME = N_(\"Cobalt\");\r\nconst char *ITEM_PREFIX_56_NAME = N_(\"Sapphire\");\r\nconst char *ITEM_PREFIX_57_NAME = N_(\"White\");\r\nconst char *ITEM_PREFIX_58_NAME = N_(\"Pearl\");\r\nconst char *ITEM_PREFIX_59_NAME = N_(\"Ivory\");\r\nconst char *ITEM_PREFIX_60_NAME = N_(\"Crystal\");\r\nconst char *ITEM_PREFIX_61_NAME = N_(\"Diamond\");\r\nconst char *ITEM_PREFIX_62_NAME = N_(\"Topaz\");\r\nconst char *ITEM_PREFIX_63_NAME = N_(\"Amber\");\r\nconst char *ITEM_PREFIX_64_NAME = N_(\"Jade\");\r\nconst char *ITEM_PREFIX_65_NAME = N_(\"Obsidian\");\r\nconst char *ITEM_PREFIX_66_NAME = N_(\"Emerald\");\r\nconst char *ITEM_PREFIX_67_NAME = N_(\"Hyena's\");\r\nconst char *ITEM_PREFIX_68_NAME = N_(\"Frog's\");\r\nconst char *ITEM_PREFIX_69_NAME = N_(\"Spider's\");\r\nconst char *ITEM_PREFIX_70_NAME = N_(\"Raven's\");\r\nconst char *ITEM_PREFIX_71_NAME = N_(\"Snake's\");\r\nconst char *ITEM_PREFIX_72_NAME = N_(\"Serpent's\");\r\nconst char *ITEM_PREFIX_73_NAME = N_(\"Drake's\");\r\nconst char *ITEM_PREFIX_74_NAME = N_(\"Dragon's\");\r\nconst char *ITEM_PREFIX_75_NAME = N_(\"Wyrm's\");\r\nconst char *ITEM_PREFIX_76_NAME = N_(\"Hydra's\");\r\nconst char *ITEM_PREFIX_77_NAME = N_(\"Angel's\");\r\nconst char *ITEM_PREFIX_78_NAME = N_(\"Arch-Angel's\");\r\nconst char *ITEM_PREFIX_79_NAME = N_(\"Plentiful\");\r\nconst char *ITEM_PREFIX_80_NAME = N_(\"Bountiful\");\r\nconst char *ITEM_PREFIX_81_NAME = N_(\"Flaming\");\r\nconst char *ITEM_PREFIX_82_NAME = N_(\"Lightning\");\r\nconst char *ITEM_SUFFIX_0_NAME = N_(\"quality\");\r\nconst char *ITEM_SUFFIX_1_NAME = N_(\"maiming\");\r\nconst char *ITEM_SUFFIX_2_NAME = N_(\"slaying\");\r\nconst char *ITEM_SUFFIX_3_NAME = N_(\"gore\");\r\nconst char *ITEM_SUFFIX_4_NAME = N_(\"carnage\");\r\nconst char *ITEM_SUFFIX_5_NAME = N_(\"slaughter\");\r\nconst char *ITEM_SUFFIX_6_NAME = N_(\"pain\");\r\nconst char *ITEM_SUFFIX_7_NAME = N_(\"tears\");\r\nconst char *ITEM_SUFFIX_8_NAME = N_(\"health\");\r\nconst char *ITEM_SUFFIX_9_NAME = N_(\"protection\");\r\nconst char *ITEM_SUFFIX_10_NAME = N_(\"absorption\");\r\nconst char *ITEM_SUFFIX_11_NAME = N_(\"deflection\");\r\nconst char *ITEM_SUFFIX_12_NAME = N_(\"osmosis\");\r\nconst char *ITEM_SUFFIX_13_NAME = N_(\"frailty\");\r\nconst char *ITEM_SUFFIX_14_NAME = N_(\"weakness\");\r\nconst char *ITEM_SUFFIX_15_NAME = N_(\"strength\");\r\nconst char *ITEM_SUFFIX_16_NAME = N_(\"might\");\r\nconst char *ITEM_SUFFIX_17_NAME = N_(\"power\");\r\nconst char *ITEM_SUFFIX_18_NAME = N_(\"giants\");\r\nconst char *ITEM_SUFFIX_19_NAME = N_(\"titans\");\r\nconst char *ITEM_SUFFIX_20_NAME = N_(\"paralysis\");\r\nconst char *ITEM_SUFFIX_21_NAME = N_(\"atrophy\");\r\nconst char *ITEM_SUFFIX_22_NAME = N_(\"dexterity\");\r\nconst char *ITEM_SUFFIX_23_NAME = N_(\"skill\");\r\nconst char *ITEM_SUFFIX_24_NAME = N_(\"accuracy\");\r\nconst char *ITEM_SUFFIX_25_NAME = N_(\"precision\");\r\nconst char *ITEM_SUFFIX_26_NAME = N_(\"perfection\");\r\nconst char *ITEM_SUFFIX_27_NAME = N_(\"the fool\");\r\nconst char *ITEM_SUFFIX_28_NAME = N_(\"dyslexia\");\r\nconst char *ITEM_SUFFIX_29_NAME = N_(\"magic\");\r\nconst char *ITEM_SUFFIX_30_NAME = N_(\"the mind\");\r\nconst char *ITEM_SUFFIX_31_NAME = N_(\"brilliance\");\r\nconst char *ITEM_SUFFIX_32_NAME = N_(\"sorcery\");\r\nconst char *ITEM_SUFFIX_33_NAME = N_(\"wizardry\");\r\nconst char *ITEM_SUFFIX_34_NAME = N_(\"illness\");\r\nconst char *ITEM_SUFFIX_35_NAME = N_(\"disease\");\r\nconst char *ITEM_SUFFIX_36_NAME = N_(\"vitality\");\r\nconst char *ITEM_SUFFIX_37_NAME = N_(\"zest\");\r\nconst char *ITEM_SUFFIX_38_NAME = N_(\"vim\");\r\nconst char *ITEM_SUFFIX_39_NAME = N_(\"vigor\");\r\nconst char *ITEM_SUFFIX_40_NAME = N_(\"life\");\r\nconst char *ITEM_SUFFIX_41_NAME = N_(\"trouble\");\r\nconst char *ITEM_SUFFIX_42_NAME = N_(\"the pit\");\r\nconst char *ITEM_SUFFIX_43_NAME = N_(\"the sky\");\r\nconst char *ITEM_SUFFIX_44_NAME = N_(\"the moon\");\r\nconst char *ITEM_SUFFIX_45_NAME = N_(\"the stars\");\r\nconst char *ITEM_SUFFIX_46_NAME = N_(\"the heavens\");\r\nconst char *ITEM_SUFFIX_47_NAME = N_(\"the zodiac\");\r\nconst char *ITEM_SUFFIX_48_NAME = N_(\"the vulture\");\r\nconst char *ITEM_SUFFIX_49_NAME = N_(\"the jackal\");\r\nconst char *ITEM_SUFFIX_50_NAME = N_(\"the fox\");\r\nconst char *ITEM_SUFFIX_51_NAME = N_(\"the jaguar\");\r\nconst char *ITEM_SUFFIX_52_NAME = N_(\"the eagle\");\r\nconst char *ITEM_SUFFIX_53_NAME = N_(\"the wolf\");\r\nconst char *ITEM_SUFFIX_54_NAME = N_(\"the tiger\");\r\nconst char *ITEM_SUFFIX_55_NAME = N_(\"the lion\");\r\nconst char *ITEM_SUFFIX_56_NAME = N_(\"the mammoth\");\r\nconst char *ITEM_SUFFIX_57_NAME = N_(\"the whale\");\r\nconst char *ITEM_SUFFIX_58_NAME = N_(\"fragility\");\r\nconst char *ITEM_SUFFIX_59_NAME = N_(\"brittleness\");\r\nconst char *ITEM_SUFFIX_60_NAME = N_(\"sturdiness\");\r\nconst char *ITEM_SUFFIX_61_NAME = N_(\"craftsmanship\");\r\nconst char *ITEM_SUFFIX_62_NAME = N_(\"structure\");\r\nconst char *ITEM_SUFFIX_63_NAME = N_(\"the ages\");\r\nconst char *ITEM_SUFFIX_64_NAME = N_(\"the dark\");\r\nconst char *ITEM_SUFFIX_65_NAME = N_(\"the night\");\r\nconst char *ITEM_SUFFIX_66_NAME = N_(\"light\");\r\nconst char *ITEM_SUFFIX_67_NAME = N_(\"radiance\");\r\nconst char *ITEM_SUFFIX_68_NAME = N_(\"flame\");\r\nconst char *ITEM_SUFFIX_69_NAME = N_(\"fire\");\r\nconst char *ITEM_SUFFIX_70_NAME = N_(\"burning\");\r\nconst char *ITEM_SUFFIX_71_NAME = N_(\"shock\");\r\nconst char *ITEM_SUFFIX_72_NAME = N_(\"lightning\");\r\nconst char *ITEM_SUFFIX_73_NAME = N_(\"thunder\");\r\nconst char *ITEM_SUFFIX_74_NAME = N_(\"many\");\r\nconst char *ITEM_SUFFIX_75_NAME = N_(\"plenty\");\r\nconst char *ITEM_SUFFIX_76_NAME = N_(\"thorns\");\r\nconst char *ITEM_SUFFIX_77_NAME = N_(\"corruption\");\r\nconst char *ITEM_SUFFIX_78_NAME = N_(\"thieves\");\r\nconst char *ITEM_SUFFIX_79_NAME = N_(\"the bear\");\r\nconst char *ITEM_SUFFIX_80_NAME = N_(\"the bat\");\r\nconst char *ITEM_SUFFIX_81_NAME = N_(\"vampires\");\r\nconst char *ITEM_SUFFIX_82_NAME = N_(\"the leech\");\r\nconst char *ITEM_SUFFIX_83_NAME = N_(\"blood\");\r\nconst char *ITEM_SUFFIX_84_NAME = N_(\"piercing\");\r\nconst char *ITEM_SUFFIX_85_NAME = N_(\"puncturing\");\r\nconst char *ITEM_SUFFIX_86_NAME = N_(\"bashing\");\r\nconst char *ITEM_SUFFIX_87_NAME = N_(\"readiness\");\r\nconst char *ITEM_SUFFIX_88_NAME = N_(\"swiftness\");\r\nconst char *ITEM_SUFFIX_89_NAME = N_(\"speed\");\r\nconst char *ITEM_SUFFIX_90_NAME = N_(\"haste\");\r\nconst char *ITEM_SUFFIX_91_NAME = N_(\"balance\");\r\nconst char *ITEM_SUFFIX_92_NAME = N_(\"stability\");\r\nconst char *ITEM_SUFFIX_93_NAME = N_(\"harmony\");\r\nconst char *ITEM_SUFFIX_94_NAME = N_(\"blocking\");\r\nconst char *QUEST_THE_MAGIC_ROCK_NAME = N_(\"The Magic Rock\");\r\nconst char *QUEST_GHARBAD_THE_WEAK_NAME = N_(\"Gharbad The Weak\");\r\nconst char *QUEST_ZHAR_THE_MAD_NAME = N_(\"Zhar the Mad\");\r\nconst char *QUEST_LACHDANAN_NAME = N_(\"Lachdanan\");\r\nconst char *QUEST_DIABLO_NAME = N_(\"Diablo\");\r\nconst char *QUEST_THE_BUTCHER_NAME = N_(\"The Butcher\");\r\nconst char *QUEST_OGDENS_SIGN_NAME = N_(\"Ogden's Sign\");\r\nconst char *QUEST_HALLS_OF_THE_BLIND_NAME = N_(\"Halls of the Blind\");\r\nconst char *QUEST_VALOR_NAME = N_(\"Valor\");\r\nconst char *QUEST_WARLORD_OF_BLOOD_NAME = N_(\"Warlord of Blood\");\r\nconst char *QUEST_THE_CURSE_OF_KING_LEORIC_NAME = N_(\"The Curse of King Leoric\");\r\nconst char *QUEST_POISONED_WATER_SUPPLY_NAME = N_(\"Poisoned Water Supply\");\r\nconst char *QUEST_THE_CHAMBER_OF_BONE_NAME = N_(\"The Chamber of Bone\");\r\nconst char *QUEST_ARCHBISHOP_LAZARUS_NAME = N_(\"Archbishop Lazarus\");\r\nconst char *QUEST_GRAVE_MATTERS_NAME = N_(\"Grave Matters\");\r\nconst char *QUEST_FARMERS_ORCHARD_NAME = N_(\"Farmer's Orchard\");\r\nconst char *QUEST_LITTLE_GIRL_NAME = N_(\"Little Girl\");\r\nconst char *QUEST_WANDERING_TRADER_NAME = N_(\"Wandering Trader\");\r\nconst char *QUEST_THE_DEFILER_NAME = N_(\"The Defiler\");\r\nconst char *QUEST_NA_KRUL_NAME = N_(\"Na-Krul\");\r\nconst char *QUEST_CORNERSTONE_OF_THE_WORLD_NAME = N_(\"Cornerstone of the World\");\r\nconst char *QUEST_THE_JERSEYS_JERSEY_NAME = N_(\"The Jersey's Jersey\");\r\nconst char *SPELL_FIREBOLT_NAME = P_(\"spell\", \"Firebolt\");\r\nconst char *SPELL_HEALING_NAME = P_(\"spell\", \"Healing\");\r\nconst char *SPELL_LIGHTNING_NAME = P_(\"spell\", \"Lightning\");\r\nconst char *SPELL_FLASH_NAME = P_(\"spell\", \"Flash\");\r\nconst char *SPELL_IDENTIFY_NAME = P_(\"spell\", \"Identify\");\r\nconst char *SPELL_FIRE_WALL_NAME = P_(\"spell\", \"Fire Wall\");\r\nconst char *SPELL_TOWN_PORTAL_NAME = P_(\"spell\", \"Town Portal\");\r\nconst char *SPELL_STONE_CURSE_NAME = P_(\"spell\", \"Stone Curse\");\r\nconst char *SPELL_INFRAVISION_NAME = P_(\"spell\", \"Infravision\");\r\nconst char *SPELL_PHASING_NAME = P_(\"spell\", \"Phasing\");\r\nconst char *SPELL_MANA_SHIELD_NAME = P_(\"spell\", \"Mana Shield\");\r\nconst char *SPELL_FIREBALL_NAME = P_(\"spell\", \"Fireball\");\r\nconst char *SPELL_GUARDIAN_NAME = P_(\"spell\", \"Guardian\");\r\nconst char *SPELL_CHAIN_LIGHTNING_NAME = P_(\"spell\", \"Chain Lightning\");\r\nconst char *SPELL_FLAME_WAVE_NAME = P_(\"spell\", \"Flame Wave\");\r\nconst char *SPELL_DOOM_SERPENTS_NAME = P_(\"spell\", \"Doom Serpents\");\r\nconst char *SPELL_BLOOD_RITUAL_NAME = P_(\"spell\", \"Blood Ritual\");\r\nconst char *SPELL_NOVA_NAME = P_(\"spell\", \"Nova\");\r\nconst char *SPELL_INVISIBILITY_NAME = P_(\"spell\", \"Invisibility\");\r\nconst char *SPELL_INFERNO_NAME = P_(\"spell\", \"Inferno\");\r\nconst char *SPELL_GOLEM_NAME = P_(\"spell\", \"Golem\");\r\nconst char *SPELL_RAGE_NAME = P_(\"spell\", \"Rage\");\r\nconst char *SPELL_TELEPORT_NAME = P_(\"spell\", \"Teleport\");\r\nconst char *SPELL_APOCALYPSE_NAME = P_(\"spell\", \"Apocalypse\");\r\nconst char *SPELL_ETHEREALIZE_NAME = P_(\"spell\", \"Etherealize\");\r\nconst char *SPELL_ITEM_REPAIR_NAME = P_(\"spell\", \"Item Repair\");\r\nconst char *SPELL_STAFF_RECHARGE_NAME = P_(\"spell\", \"Staff Recharge\");\r\nconst char *SPELL_TRAP_DISARM_NAME = P_(\"spell\", \"Trap Disarm\");\r\nconst char *SPELL_ELEMENTAL_NAME = P_(\"spell\", \"Elemental\");\r\nconst char *SPELL_CHARGED_BOLT_NAME = P_(\"spell\", \"Charged Bolt\");\r\nconst char *SPELL_HOLY_BOLT_NAME = P_(\"spell\", \"Holy Bolt\");\r\nconst char *SPELL_RESURRECT_NAME = P_(\"spell\", \"Resurrect\");\r\nconst char *SPELL_TELEKINESIS_NAME = P_(\"spell\", \"Telekinesis\");\r\nconst char *SPELL_HEAL_OTHER_NAME = P_(\"spell\", \"Heal Other\");\r\nconst char *SPELL_BLOOD_STAR_NAME = P_(\"spell\", \"Blood Star\");\r\nconst char *SPELL_BONE_SPIRIT_NAME = P_(\"spell\", \"Bone Spirit\");\r\nconst char *TEXT_0 = N_(\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh blow to this land. The people always loved the King, and now they live in mortal fear of him. The question that I keep asking myself is how he could have fallen so far from the Light, as Leoric had always been the holiest of men. Only the vilest powers of Hell could so utterly destroy a man from within...\");\r\nconst char *TEXT_1 = N_(\"The village needs your help, good master! Some months ago King Leoric's son, Prince Albrecht, was kidnapped. The King went into a rage and scoured the village for his missing child. With each passing day, Leoric seemed to slip deeper into madness. He sought to blame innocent townsfolk for the boy's disappearance and had them brutally executed. Less than half of us survived his insanity...\\n \\nThe King's Knights and Priests tried to placate him, but he turned against them and sadly, they were forced to kill him. With his dying breath the King called down a terrible curse upon his former followers. He vowed that they would serve him in darkness forever...\\n \\nThis is where things take an even darker twist than I thought possible! Our former King has risen from his eternal sleep and now commands a legion of undead minions within the Labyrinth. His body was buried in a tomb three levels beneath the Cathedral. Please, good master, put his soul at ease by destroying his now cursed form...\");\r\nconst char *TEXT_2 = N_(\"As I told you, good master, the King was entombed three levels below. He's down there, waiting in the putrid darkness for his chance to destroy this land...\");\r\nconst char *TEXT_3 = N_(\"The curse of our King has passed, but I fear that it was only part of a greater evil at work. However, we may yet be saved from the darkness that consumes our land, for your victory is a good omen. May Light guide you on your way, good master.\");\r\nconst char *TEXT_4 = N_(\"The loss of his son was too much for King Leoric. I did what I could to ease his madness, but in the end it overcame him. A black curse has hung over this kingdom from that day forward, but perhaps if you were to free his spirit from his earthly prison, the curse would be lifted...\");\r\nconst char *TEXT_5 = N_(\"I don't like to think about how the King died. I like to remember him for the kind and just ruler that he was. His death was so sad and seemed very wrong, somehow.\");\r\nconst char *TEXT_6 = N_(\"I made many of the weapons and most of the armor that King Leoric used to outfit his knights. I even crafted a huge two-handed sword of the finest mithril for him, as well as a field crown to match. I still cannot believe how he died, but it must have been some sinister force that drove him insane!\");\r\nconst char *TEXT_7 = N_(\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is King. King, so you hear me? HAIL TO THE KING!\");\r\nconst char *TEXT_8 = N_(\"The dead who walk among the living follow the cursed King. He holds the power to raise yet more warriors for an ever growing army of the undead. If you do not stop his reign, he will surely march across this land and slay all who still live here.\");\r\nconst char *TEXT_9 = N_(\"Look, I'm running a business here. I don't sell information, and I don't care about some King that's been dead longer than I've been alive. If you need something to use against this King of the undead, then I can help you out...\");\r\nconst char *TEXT_10 = N_(\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve my Master for eternity!\");\r\nconst char *TEXT_11 = N_(\"I see that this strange behavior puzzles you as well. I would surmise that since many demons fear the light of the sun and believe that it holds great power, it may be that the rising sun depicted on the sign you speak of has led them to believe that it too holds some arcane powers. Hmm, perhaps they are not all as smart as we had feared...\");\r\nconst char *TEXT_12 = N_(\"Master, I have a strange experience to relate. I know that you have a great knowledge of those monstrosities that inhabit the labyrinth, and this is something that I cannot understand for the very life of me... I was awakened during the night by a scraping sound just outside of my tavern. When I looked out from my bedroom, I saw the shapes of small demon-like creatures in the inn yard. After a short time, they ran off, but not before stealing the sign to my inn. I don't know why the demons would steal my sign but leave my family in peace... 'tis strange, no?\");\r\nconst char *TEXT_13 = N_(\"Oh, you didn't have to bring back my sign, but I suppose that it does save me the expense of having another one made. Well, let me see, what could I give you as a fee for finding it? Hmmm, what have we here... ah, yes! This cap was left in one of the rooms by a magician who stayed here some time ago. Perhaps it may be of some value to you.\");\r\nconst char *TEXT_14 = N_(\"My goodness, demons running about the village at night, pillaging our homes - is nothing sacred? I hope that Ogden and Garda are all right. I suppose that they would come to see me if they were hurt...\");\r\nconst char *TEXT_15 = N_(\"Oh my! Is that where the sign went? My Grandmother and I must have slept right through the whole thing. Thank the Light that those monsters didn't attack the inn.\");\r\nconst char *TEXT_16 = N_(\"Demons stole Ogden's sign, you say? That doesn't sound much like the atrocities I've heard of - or seen. \\n \\nDemons are concerned with ripping out your heart, not your signpost.\");\r\nconst char *TEXT_17 = N_(\"You know what I think? Somebody took that sign, and they gonna want lots of money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece of cheese...\");\r\nconst char *TEXT_18 = N_(\"No mortal can truly understand the mind of the demon. \\n \\nNever let their erratic actions confuse you, as that too may be their plan.\");\r\nconst char *TEXT_19 = N_(\"What - is he saying I took that? I suppose that Griswold is on his side, too. \\n \\nLook, I got over simple sign stealing months ago. You can't turn a profit on a piece of wood.\");\r\nconst char *TEXT_20 = N_(\"Hey - You that one that kill all! You get me Magic Banner or we attack! You no leave with life! You kill big uglies and give back Magic. Go past corner and door, find uglies. You give, you go!\");\r\nconst char *TEXT_21 = N_(\"You kill uglies, get banner. You bring to me, or else...\");\r\nconst char *TEXT_22 = N_(\"You give! Yes, good! Go now, we strong. We kill all with big Magic!\");\r\nconst char *TEXT_23 = N_(\"This does not bode well, for it confirms my darkest fears. While I did not allow myself to believe the ancient legends, I cannot deny them now. Perhaps the time has come to reveal who I am.\\n \\nMy true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released.\\n \\nThe Archbishop Lazarus, once King Leoric's most trusted advisor, led a party of simple townsfolk into the Labyrinth to find the King's missing son, Albrecht. Quite some time passed before they returned, and only a few of them escaped with their lives.\\n \\nCurse me for a fool! I should have suspected his veiled treachery then. It must have been Lazarus himself who kidnapped Albrecht and has since hidden him within the Labyrinth. I do not understand why the Archbishop turned to the darkness, or what his interest is in the child, unless he means to sacrifice him to his dark masters!\\n \\nThat must be what he has planned! The survivors of his 'rescue party' say that Lazarus was last seen running into the deepest bowels of the labyrinth. You must hurry and save the prince from the sacrificial blade of this demented fiend!\");\r\nconst char *TEXT_24 = N_(\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and the people of this kingdom are counting on you!\");\r\nconst char *TEXT_25 = N_(\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for his horrific deed. The boy that you describe is not our prince, but I believe that Albrecht may yet be in danger. The symbol of power that you speak of must be a portal in the very heart of the labyrinth.\\n \\nKnow this, my friend - The evil that you move against is the dark Lord of Terror. He is known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago and I fear that he seeks to once again sow chaos in the realm of mankind. You must venture through the portal and destroy Diablo before it is too late!\");\r\nconst char *TEXT_26 = N_(\"Lazarus was the Archbishop who led many of the townspeople into the labyrinth. I lost many good friends that day, and Lazarus never returned. I suppose he was killed along with most of the others. If you would do me a favor, good master - please do not talk to Farnham about that day.\");\r\nconst char *TEXT_29 = N_(\"I was shocked when I heard of what the townspeople were planning to do that night. I thought that of all people, Lazarus would have had more sense than that. He was an Archbishop, and always seemed to care so much for the townsfolk of Tristram. So many were injured, I could not save them all...\");\r\nconst char *TEXT_30 = N_(\"I remember Lazarus as being a very kind and giving man. He spoke at my mother's funeral, and was supportive of my grandmother and myself in a very troubled time. I pray every night that somehow, he is still alive and safe.\");\r\nconst char *TEXT_31 = N_(\"I was there when Lazarus led us into the labyrinth. He spoke of holy retribution, but when we started fighting those hellspawn, he did not so much as lift his mace against them. He just ran deeper into the dim, endless chambers that were filled with the servants of darkness!\");\r\nconst char *TEXT_32 = N_(\"They stab, then bite, then they're all around you. Liar! LIAR! They're all dead! Dead! Do you hear me? They just keep falling and falling... their blood spilling out all over the floor... all his fault...\");\r\nconst char *TEXT_33 = N_(\"I did not know this Lazarus of whom you speak, but I do sense a great conflict within his being. He poses a great danger, and will stop at nothing to serve the powers of darkness which have claimed him as theirs.\");\r\nconst char *TEXT_34 = N_(\"Yes, the righteous Lazarus, who was sooo effective against those monsters down there. Didn't help save my leg, did it? Look, I'll give you a free piece of advice. Ask Farnham, he was there.\");\r\nconst char *TEXT_35 = N_(\"Abandon your foolish quest. All that awaits you is the wrath of my Master! You are too late to save the child. Now you will join him in Hell!\");\r\nconst char *TEXT_37 = N_(\"Hmm, I don't know what I can really tell you about this that will be of any help. The water that fills our wells comes from an underground spring. I have heard of a tunnel that leads to a great lake - perhaps they are one and the same. Unfortunately, I do not know what would cause our water supply to be tainted.\");\r\nconst char *TEXT_38 = N_(\"I have always tried to keep a large supply of foodstuffs and drink in our storage cellar, but with the entire town having no source of fresh water, even our stores will soon run dry. \\n \\nPlease, do what you can or I don't know what we will do.\");\r\nconst char *TEXT_39 = N_(\"I'm glad I caught up to you in time! Our wells have become brackish and stagnant and some of the townspeople have become ill drinking from them. Our reserves of fresh water are quickly running dry. I believe that there is a passage that leads to the springs that serve our town. Please find what has caused this calamity, or we all will surely perish.\");\r\nconst char *TEXT_40 = N_(\"Please, you must hurry. Every hour that passes brings us closer to having no water to drink. \\n \\nWe cannot survive for long without your help.\");\r\nconst char *TEXT_41 = N_(\"What's that you say - the mere presence of the demons had caused the water to become tainted? Oh, truly a great evil lurks beneath our town, but your perseverance and courage gives us hope. Please take this ring - perhaps it will aid you in the destruction of such vile creatures.\");\r\nconst char *TEXT_42 = N_(\"My grandmother is very weak, and Garda says that we cannot drink the water from the wells. Please, can you do something to help us?\");\r\nconst char *TEXT_43 = N_(\"Pepin has told you the truth. We will need fresh water badly, and soon. I have tried to clear one of the smaller wells, but it reeks of stagnant filth. It must be getting clogged at the source.\");\r\nconst char *TEXT_44 = N_(\"You drink water?\");\r\nconst char *TEXT_45 = N_(\"The people of Tristram will die if you cannot restore fresh water to their wells. \\n \\nKnow this - demons are at the heart of this matter, but they remain ignorant of what they have spawned.\");\r\nconst char *TEXT_46 = N_(\"For once, I'm with you. My business runs dry - so to speak - if I have no market to sell to. You better find out what is going on, and soon!\");\r\nconst char *TEXT_47 = N_(\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is mentioned in certain archaic writings that I studied in the libraries of the East. These tomes inferred that when the Lords of the underworld desired to protect great treasures, they would create domains where those who died in the attempt to steal that treasure would be forever bound to defend it. A twisted, but strangely fitting, end?\");\r\nconst char *TEXT_48 = N_(\"I am afraid that I don't know anything about that, good master. Cain has many books that may be of some help.\");\r\nconst char *TEXT_49 = N_(\"This sounds like a very dangerous place. If you venture there, please take great care.\");\r\nconst char *TEXT_50 = N_(\"I am afraid that I haven't heard anything about that. Perhaps Cain the Storyteller could be of some help.\");\r\nconst char *TEXT_51 = N_(\"I know nothing of this place, but you may try asking Cain. He talks about many things, and it would not surprise me if he had some answers to your question.\");\r\nconst char *TEXT_52 = N_(\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - her - tells the tree... cause you gotta wait. Then I says, that might work against him, but if you think I'm gonna PAY for this... you... uh... yeah.\");\r\nconst char *TEXT_53 = N_(\"You will become an eternal servant of the dark lords should you perish within this cursed domain. \\n \\nEnter the Chamber of Bone at your own peril.\");\r\nconst char *TEXT_54 = N_(\"A vast and mysterious treasure, you say? Maybe I could be interested in picking up a few things from you... or better yet, don't you need some rare and expensive supplies to get you through this ordeal?\");\r\nconst char *TEXT_55 = N_(\"It seems that the Archbishop Lazarus goaded many of the townsmen into venturing into the Labyrinth to find the King's missing son. He played upon their fears and whipped them into a frenzied mob. None of them were prepared for what lay within the cold earth... Lazarus abandoned them down there - left in the clutches of unspeakable horrors - to die.\");\r\nconst char *TEXT_56 = N_(\"Yes, Farnham has mumbled something about a hulking brute who wielded a fierce weapon. I believe he called him a butcher.\");\r\nconst char *TEXT_57 = N_(\"By the Light, I know of this vile demon. There were many that bore the scars of his wrath upon their bodies when the few survivors of the charge led by Lazarus crawled from the Cathedral. I don't know what he used to slice open his victims, but it could not have been of this world. It left wounds festering with disease and even I found them almost impossible to treat. Beware if you plan to battle this fiend...\");\r\nconst char *TEXT_58 = N_(\"When Farnham said something about a butcher killing people, I immediately discounted it. But since you brought it up, maybe it is true.\");\r\nconst char *TEXT_59 = N_(\"I saw what Farnham calls the Butcher as it swathed a path through the bodies of my friends. He swung a cleaver as large as an axe, hewing limbs and cutting down brave men where they stood. I was separated from the fray by a host of small screeching demons and somehow found the stairway leading out. I never saw that hideous beast again, but his blood-stained visage haunts me to this day.\");\r\nconst char *TEXT_60 = N_(\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, couldn't save them. Trapped in a room with so many bodies... so many friends... NOOOOOOOOOO!\");\r\nconst char *TEXT_61 = N_(\"The Butcher is a sadistic creature that delights in the torture and pain of others. You have seen his handiwork in the drunkard Farnham. His destruction will do much to ensure the safety of this village.\");\r\nconst char *TEXT_62 = N_(\"I know more than you'd think about that grisly fiend. His little friends got a hold of me and managed to get my leg before Griswold pulled me out of that hole. \\n \\nI'll put it bluntly - kill him before he kills you and adds your corpse to his collection.\");\r\nconst char *TEXT_63 = N_(\"Please, listen to me. The Archbishop Lazarus, he led us down here to find the lost prince. The bastard led us into a trap! Now everyone is dead... killed by a demon he called the Butcher. Avenge us! Find this Butcher and slay him so that our souls may finally rest...\");\r\nconst char *TEXT_65 = N_(\"You recite an interesting rhyme written in a style that reminds me of other works. Let me think now - what was it?\\n \\n...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of razor claws briefly scraping to torment those poor souls who have been made sightless for all eternity. The prison for those so damned is named the Halls of the Blind...\");\r\nconst char *TEXT_66 = N_(\"I never much cared for poetry. Occasionally, I had cause to hire minstrels when the inn was doing well, but that seems like such a long time ago now. \\n \\nWhat? Oh, yes... uh, well, I suppose you could see what someone else knows.\");\r\nconst char *TEXT_67 = N_(\"This does seem familiar, somehow. I seem to recall reading something very much like that poem while researching the history of demonic afflictions. It spoke of a place of great evil that... wait - you're not going there are you?\");\r\nconst char *TEXT_68 = N_(\"If you have questions about blindness, you should talk to Pepin. I know that he gave my grandmother a potion that helped clear her vision, so maybe he can help you, too.\");\r\nconst char *TEXT_69 = N_(\"I am afraid that I have neither heard nor seen a place that matches your vivid description, my friend. Perhaps Cain the Storyteller could be of some help.\");\r\nconst char *TEXT_70 = N_(\"Look here... that's pretty funny, huh? Get it? Blind - look here?\");\r\nconst char *TEXT_71 = N_(\"This is a place of great anguish and terror, and so serves its master well. \\n \\nTread carefully or you may yourself be staying much longer than you had anticipated.\");\r\nconst char *TEXT_72 = N_(\"Lets see, am I selling you something? No. Are you giving me money to tell you about this? No. Are you now leaving and going to talk to the storyteller who lives for this kind of thing? Yes.\");\r\nconst char *TEXT_73 = N_(\"You claim to have spoken with Lachdanan? He was a great hero during his life. Lachdanan was an honorable and just man who served his King faithfully for years. But of course, you already know that.\\n \\nOf those who were caught within the grasp of the King's Curse, Lachdanan would be the least likely to submit to the darkness without a fight, so I suppose that your story could be true. If I were in your place, my friend, I would find a way to release him from his torture.\");\r\nconst char *TEXT_74 = N_(\"You speak of a brave warrior long dead! I'll have no such talk of speaking with departed souls in my inn yard, thank you very much.\");\r\nconst char *TEXT_75 = N_(\"A golden elixir, you say. I have never concocted a potion of that color before, so I can't tell you how it would effect you if you were to try to drink it. As your healer, I strongly advise that should you find such an elixir, do as Lachdanan asks and DO NOT try to use it.\");\r\nconst char *TEXT_76 = N_(\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I can be of much help to you.\");\r\nconst char *TEXT_77 = N_(\"If it is actually Lachdanan that you have met, then I would advise that you aid him. I dealt with him on several occasions and found him to be honest and loyal in nature. The curse that fell upon the followers of King Leoric would fall especially hard upon him.\");\r\nconst char *TEXT_78 = N_(\" Lachdanan is dead. Everybody knows that, and you can't fool me into thinking any other way. You can't talk to the dead. I know!\");\r\nconst char *TEXT_79 = N_(\"You may meet people who are trapped within the Labyrinth, such as Lachdanan. \\n \\nI sense in him honor and great guilt. Aid him, and you aid all of Tristram.\");\r\nconst char *TEXT_80 = N_(\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened beneath him. He was incinerated in a ball of hellfire, and can't answer your questions anymore. Oh, that isn't what happened? Then I guess you'll be buying something or you'll be on your way.\");\r\nconst char *TEXT_81 = N_(\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's Knights, upholding the laws of this land with justice and honor. Then his dark Curse fell upon us for the role we played in his tragic death. As my fellow Knights succumbed to their twisted fate, I fled from the King's burial chamber, searching for some way to free myself from the Curse. I failed...\\n \\nI have heard of a Golden Elixir that could lift the Curse and allow my soul to rest, but I have been unable to find it. My strength now wanes, and with it the last of my humanity as well. Please aid me and find the Elixir. I will repay your efforts - I swear upon my honor.\");\r\nconst char *TEXT_82 = N_(\"You have not found the Golden Elixir. I fear that I am doomed for eternity. Please, keep trying...\");\r\nconst char *TEXT_83 = N_(\"You have saved my soul from damnation, and for that I am in your debt. If there is ever a way that I can repay you from beyond the grave I will find it, but for now - take my helm. On the journey I am about to take I will have little use for it. May it protect you against the dark powers below. Go with the Light, my friend...\");\r\nconst char *TEXT_84 = N_(\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched for, but never found. Crafted from the metallic bones of the Razor Pit demons, the Anvil of Fury was smelt around the skulls of the five most powerful magi of the underworld. Carved with runes of power and chaos, any weapon or armor forged upon this Anvil will be immersed into the realm of Chaos, imbedding it with magical properties. It is said that the unpredictable nature of Chaos makes it difficult to know what the outcome of this smithing will be...\");\r\nconst char *TEXT_85 = N_(\"Don't you think that Griswold would be a better person to ask about this? He's quite handy, you know.\");\r\nconst char *TEXT_86 = N_(\"If you had been looking for information on the Pestle of Curing or the Silver Chalice of Purification, I could have assisted you, my friend. However, in this matter, you would be better served to speak to either Griswold or Cain.\");\r\nconst char *TEXT_87 = N_(\"Griswold's father used to tell some of us when we were growing up about a giant anvil that was used to make mighty weapons. He said that when a hammer was struck upon this anvil, the ground would shake with a great fury. Whenever the earth moves, I always remember that story.\");\r\nconst char *TEXT_88 = N_(\"Greetings! It's always a pleasure to see one of my best customers! I know that you have been venturing deeper into the Labyrinth, and there is a story I was told that you may find worth the time to listen to...\\n \\nOne of the men who returned from the Labyrinth told me about a mystic anvil that he came across during his escape. His description reminded me of legends I had heard in my youth about the burning Hellforge where powerful weapons of magic are crafted. The legend had it that deep within the Hellforge rested the Anvil of Fury! This Anvil contained within it the very essence of the demonic underworld...\\n \\nIt is said that any weapon crafted upon the burning Anvil is imbued with great power. If this anvil is indeed the Anvil of Fury, I may be able to make you a weapon capable of defeating even the darkest lord of Hell! \\n \\nFind the Anvil for me, and I'll get to work!\");\r\nconst char *TEXT_89 = N_(\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could be your best hope, and I am sure that I can make you one of legendary proportions.\");\r\nconst char *TEXT_90 = N_(\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. Now we'll show those bastards that there are no weapons in Hell more deadly than those made by men! Take this and may Light protect you.\");\r\nconst char *TEXT_91 = N_(\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if someone took my anvil!\");\r\nconst char *TEXT_92 = N_(\"There are many artifacts within the Labyrinth that hold powers beyond the comprehension of mortals. Some of these hold fantastic power that can be used by either the Light or the Darkness. Securing the Anvil from below could shift the course of the Sin War towards the Light.\");\r\nconst char *TEXT_93 = N_(\"If you were to find this artifact for Griswold, it could put a serious damper on my business here. Awwww, you'll never find it.\");\r\nconst char *TEXT_94 = N_(\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. Wherever this book you read from resides it is surely a place of great power.\\n \\nLegends speak of a pedestal that is carved from obsidian stone and has a pool of boiling blood atop its bone encrusted surface. There are also allusions to Stones of Blood that will open a door that guards an ancient treasure...\\n \\nThe nature of this treasure is shrouded in speculation, my friend, but it is said that the ancient hero Arkaine placed the holy armor Valor in a secret vault. Arkaine was the first mortal to turn the tide of the Sin War and chase the legions of darkness back to the Burning Hells.\\n \\nJust before Arkaine died, his armor was hidden away in a secret vault. It is said that when this holy armor is again needed, a hero will arise to don Valor once more. Perhaps you are that hero...\");\r\nconst char *TEXT_95 = N_(\"Every child hears the story of the warrior Arkaine and his mystic armor known as Valor. If you could find its resting place, you would be well protected against the evil in the Labyrinth.\");\r\nconst char *TEXT_96 = N_(\"Hmm... it sounds like something I should remember, but I've been so busy learning new cures and creating better elixirs that I must have forgotten. Sorry...\");\r\nconst char *TEXT_97 = N_(\"The story of the magic armor called Valor is something I often heard the boys talk about. You had better ask one of the men in the village.\");\r\nconst char *TEXT_98 = N_(\"The armor known as Valor could be what tips the scales in your favor. I will tell you that many have looked for it - including myself. Arkaine hid it well, my friend, and it will take more than a bit of luck to unlock the secrets that have kept it concealed oh, lo these many years.\");\r\nconst char *TEXT_99 = N_(\"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\");\r\nconst char *TEXT_100 = N_(\"Should you find these Stones of Blood, use them carefully. \\n \\nThe way is fraught with danger and your only hope rests within your self trust.\");\r\nconst char *TEXT_101 = N_(\"You intend to find the armor known as Valor? \\n \\nNo one has ever figured out where Arkaine stashed the stuff, and if my contacts couldn't find it, I seriously doubt you ever will either.\");\r\nconst char *TEXT_102 = N_(\"I know of only one legend that speaks of such a warrior as you describe. His story is found within the ancient chronicles of the Sin War...\\n \\nStained by a thousand years of war, blood and death, the Warlord of Blood stands upon a mountain of his tattered victims. His dark blade screams a black curse to the living; a tortured invitation to any who would stand before this Executioner of Hell.\\n \\nIt is also written that although he was once a mortal who fought beside the Legion of Darkness during the Sin War, he lost his humanity to his insatiable hunger for blood.\");\r\nconst char *TEXT_103 = N_(\"I am afraid that I haven't heard anything about such a vicious warrior, good master. I hope that you do not have to fight him, for he sounds extremely dangerous.\");\r\nconst char *TEXT_104 = N_(\"Cain would be able to tell you much more about something like this than I would ever wish to know.\");\r\nconst char *TEXT_105 = N_(\"If you are to battle such a fierce opponent, may Light be your guide and your defender. I will keep you in my thoughts.\");\r\nconst char *TEXT_106 = N_(\"Dark and wicked legends surrounds the one Warlord of Blood. Be well prepared, my friend, for he shows no mercy or quarter.\");\r\nconst char *TEXT_107 = N_(\"Always you gotta talk about Blood? What about flowers, and sunshine, and that pretty girl that brings the drinks. Listen here, friend - you're obsessive, you know that?\");\r\nconst char *TEXT_108 = N_(\"His prowess with the blade is awesome, and he has lived for thousands of years knowing only warfare. I am sorry... I can not see if you will defeat him.\");\r\nconst char *TEXT_109 = N_(\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's going through a lot of swords. Wouldn't mind supplying his armies...\");\r\nconst char *TEXT_110 = N_(\"My blade sings for your blood, mortal, and by my dark masters it shall not be denied.\");\r\nconst char *TEXT_111 = N_(\"Griswold speaks of the Heaven Stone that was destined for the enclave located in the east. It was being taken there for further study. This stone glowed with an energy that somehow granted vision beyond that which a normal man could possess. I do not know what secrets it holds, my friend, but finding this stone would certainly prove most valuable.\");\r\nconst char *TEXT_112 = N_(\"The caravan stopped here to take on some supplies for their journey to the east. I sold them quite an array of fresh fruits and some excellent sweetbreads that Garda has just finished baking. Shame what happened to them...\");\r\nconst char *TEXT_113 = N_(\"I don't know what it is that they thought they could see with that rock, but I will say this. If rocks are falling from the sky, you had better be careful!\");\r\nconst char *TEXT_114 = N_(\"Well, a caravan of some very important people did stop here, but that was quite a while ago. They had strange accents and were starting on a long journey, as I recall. \\n \\nI don't see how you could hope to find anything that they would have been carrying.\");\r\nconst char *TEXT_115 = N_(\"Stay for a moment - I have a story you might find interesting. A caravan that was bound for the eastern kingdoms passed through here some time ago. It was supposedly carrying a piece of the heavens that had fallen to earth! The caravan was ambushed by cloaked riders just north of here along the roadway. I searched the wreckage for this sky rock, but it was nowhere to be found. If you should find it, I believe that I can fashion something useful from it.\");\r\nconst char *TEXT_116 = N_(\"I am still waiting for you to bring me that stone from the heavens. I know that I can make something powerful out of it.\");\r\nconst char *TEXT_117 = N_(\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n \\nAh, Here you are. I arranged pieces of the stone within a silver ring that my father left me. I hope it serves you well.\");\r\nconst char *TEXT_118 = N_(\"I used to have a nice ring; it was a really expensive one, with blue and green and red and silver. Don't remember what happened to it, though. I really miss that ring...\");\r\nconst char *TEXT_119 = N_(\"The Heaven Stone is very powerful, and were it any but Griswold who bid you find it, I would prevent it. He will harness its powers and its use will be for the good of us all.\");\r\nconst char *TEXT_120 = N_(\"If anyone can make something out of that rock, Griswold can. He knows what he is doing, and as much as I try to steal his customers, I respect the quality of his work.\");\r\nconst char *TEXT_121 = N_(\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, but this is something that cannot be found in any of my stories or books.\");\r\nconst char *TEXT_122 = N_(\"Let me just say this. Both Garda and I would never, EVER serve black mushrooms to our honored guests. If Adria wants some mushrooms in her stew, then that is her business, but I can't help you find any. Black mushrooms... disgusting!\");\r\nconst char *TEXT_123 = N_(\"The witch told me that you were searching for the brain of a demon to assist me in creating my elixir. It should be of great value to the many who are injured by those foul beasts, if I can just unlock the secrets I suspect that its alchemy holds. If you can remove the brain of a demon when you kill it, I would be grateful if you could bring it to me.\");\r\nconst char *TEXT_124 = N_(\"Excellent, this is just what I had in mind. I was able to finish the elixir without this, but it can't hurt to have this to study. Would you please carry this to the witch? I believe that she is expecting it.\");\r\nconst char *TEXT_125 = N_(\"I think Ogden might have some mushrooms in the storage cellar. Why don't you ask him?\");\r\nconst char *TEXT_126 = N_(\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. I can offer you no more help than that, but it sounds like... a huge, gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\");\r\nconst char *TEXT_127 = N_(\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, listen... here's the secret - moderation is the key!\");\r\nconst char *TEXT_128 = N_(\"What do we have here? Interesting, it looks like a book of reagents. Keep your eyes open for a black mushroom. It should be fairly large and easy to identify. If you find it, bring it to me, won't you?\");\r\nconst char *TEXT_129 = N_(\"It's a big, black mushroom that I need. Now run off and get it for me so that I can use it for a special concoction that I am working on.\");\r\nconst char *TEXT_130 = N_(\"Yes, this will be perfect for a brew that I am creating. By the way, the healer is looking for the brain of some demon or another so he can treat those who have been afflicted by their poisonous venom. I believe that he intends to make an elixir from it. If you help him find what he needs, please see if you can get a sample of the elixir for me.\");\r\nconst char *TEXT_131 = N_(\"Why have you brought that here? I have no need for a demon's brain at this time. I do need some of the elixir that the Healer is working on. He needs that grotesque organ that you are holding, and then bring me the elixir. Simple when you think about it, isn't it?\");\r\nconst char *TEXT_132 = N_(\"What? Now you bring me that elixir from the healer? I was able to finish my brew without it. Why don't you just keep it...\");\r\nconst char *TEXT_133 = N_(\"I don't have any mushrooms of any size or color for sale. How about something a bit more useful?\");\r\nconst char *TEXT_134 = N_(\"So, the legend of the Map is real. Even I never truly believed any of it! I suppose it is time that I told you the truth about who I am, my friend. You see, I am not all that I seem...\\n \\nMy true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to keeping and safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released...\\n \\nThe evil that you move against is the dark Lord of Terror - known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago. The Map that you hold now was created ages ago to mark the time when Diablo would rise again from his imprisonment. When the two stars on that map align, Diablo will be at the height of his power. He will be all but invincible...\\n \\nYou are now in a race against time, my friend! Find Diablo and destroy him before the stars align, for we may never have a chance to rid the world of his evil again!\");\r\nconst char *TEXT_135 = N_(\"Our time is running short! I sense his dark power building and only you can stop him from attaining his full might.\");\r\nconst char *TEXT_136 = N_(\"I am sure that you tried your best, but I fear that even your strength and will may not be enough. Diablo is now at the height of his earthly power, and you will need all your courage and strength to defeat him. May the Light protect and guide you, my friend. I will help in any way that I am able.\");\r\nconst char *TEXT_137 = N_(\"If the witch can't help you and suggests you see Cain, what makes you think that I would know anything? It sounds like this is a very serious matter. You should hurry along and see the storyteller as Adria suggests.\");\r\nconst char *TEXT_138 = N_(\"I can't make much of the writing on this map, but perhaps Adria or Cain could help you decipher what this refers to. \\n \\nI can see that it is a map of the stars in our sky, but any more than that is beyond my talents.\");\r\nconst char *TEXT_139 = N_(\"The best person to ask about that sort of thing would be our storyteller. \\n \\nCain is very knowledgeable about ancient writings, and that is easily the oldest looking piece of paper that I have ever seen.\");\r\nconst char *TEXT_140 = N_(\"I have never seen a map of this sort before. Where'd you get it? Although I have no idea how to read this, Cain or Adria may be able to provide the answers that you seek.\");\r\nconst char *TEXT_141 = N_(\"Listen here, come close. I don't know if you know what I know, but you have really got somethin' here. That's a map.\");\r\nconst char *TEXT_142 = N_(\"Oh, I'm afraid this does not bode well at all. This map of the stars portends great disaster, but its secrets are not mine to tell. The time has come for you to have a very serious conversation with the Storyteller...\");\r\nconst char *TEXT_143 = N_(\"I've been looking for a map, but that certainly isn't it. You should show that to Adria - she can probably tell you what it is. I'll say one thing; it looks old, and old usually means valuable.\");\r\nconst char *TEXT_144 = N_(\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\");\r\nconst char *TEXT_145 = N_(\"Something for you I am making. Again, not kill Gharbad. Live and give good. \\n \\nYou take this as proof I keep word...\");\r\nconst char *TEXT_146 = N_(\"Nothing yet! Almost done. \\n \\nVery powerful, very strong. Live! Live! \\n \\nNo pain and promise I keep!\");\r\nconst char *TEXT_147 = N_(\"This too good for you. Very Powerful! You want - you take!\");\r\nconst char *TEXT_148 = N_(\"What?! Why are you here? All these interruptions are enough to make one insane. Here, take this and leave me to my work. Trouble me no more!\");\r\nconst char *TEXT_149 = N_(\"Arrrrgh! Your curiosity will be the death of you!!!\");\r\nconst char *TEXT_150 = N_(\"Hello, my friend. Stay awhile and listen...\");\r\nconst char *TEXT_151 = N_(\"While you are venturing deeper into the Labyrinth you may find tomes of great knowledge hidden there. \\n \\nRead them carefully for they can tell you things that even I cannot.\");\r\nconst char *TEXT_152 = N_(\"I know of many myths and legends that may contain answers to questions that may arise in your journeys into the Labyrinth. If you come across challenges and questions to which you seek knowledge, seek me out and I will tell you what I can.\");\r\nconst char *TEXT_153 = N_(\"Griswold - a man of great action and great courage. I bet he never told you about the time he went into the Labyrinth to save Wirt, did he? He knows his fair share of the dangers to be found there, but then again - so do you. He is a skilled craftsman, and if he claims to be able to help you in any way, you can count on his honesty and his skill.\");\r\nconst char *TEXT_154 = N_(\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years now. He purchased it just a few short months before everything here went to hell. He and his wife Garda do not have the money to leave as they invested all they had in making a life for themselves here. He is a good man with a deep sense of responsibility.\");\r\nconst char *TEXT_155 = N_(\"Poor Farnham. He is a disquieting reminder of the doomed assembly that entered into the Cathedral with Lazarus on that dark day. He escaped with his life, but his courage and much of his sanity were left in some dark pit. He finds comfort only at the bottom of his tankard nowadays, but there are occasional bits of truth buried within his constant ramblings.\");\r\nconst char *TEXT_156 = N_(\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after the Cathedral was desecrated while most everyone else was fleeing. She had a small hut constructed at the edge of town, seemingly overnight, and has access to many strange and arcane artifacts and tomes of knowledge that even I have never seen before.\");\r\nconst char *TEXT_157 = N_(\"The story of Wirt is a frightening and tragic one. He was taken from the arms of his mother and dragged into the labyrinth by the small, foul demons that wield wicked spears. There were many other children taken that day, including the son of King Leoric. The Knights of the palace went below, but never returned. The Blacksmith found the boy, but only after the foul beasts had begun to torture him for their sadistic pleasures.\");\r\nconst char *TEXT_158 = N_(\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. He is a bit addled at times, but never a more caring or considerate soul has existed. His knowledge and skills are equaled by few, and his door is always open.\");\r\nconst char *TEXT_159 = N_(\"Gillian is a fine woman. Much adored for her high spirits and her quick laugh, she holds a special place in my heart. She stays on at the tavern to support her elderly grandmother who is too sick to travel. I sometimes fear for her safety, but I know that any man in the village would rather die than see her harmed.\");\r\nconst char *TEXT_160 = N_(\"Greetings, good master. Welcome to the Tavern of the Rising Sun!\");\r\nconst char *TEXT_161 = N_(\"Many adventurers have graced the tables of my tavern, and ten times as many stories have been told over as much ale. The only thing that I ever heard any of them agree on was this old axiom. Perhaps it will help you. You can cut the flesh, but you must crush the bone.\");\r\nconst char *TEXT_162 = N_(\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. If you ever need work done on your gear, he is definitely the man to see.\");\r\nconst char *TEXT_163 = N_(\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I would make him leave, but he did suffer so during his time in the Labyrinth.\");\r\nconst char *TEXT_164 = N_(\"Adria is wise beyond her years, but I must admit - she frightens me a little. \\n \\nWell, no matter. If you ever have need to trade in items of sorcery, she maintains a strangely well-stocked hut just across the river.\");\r\nconst char *TEXT_165 = N_(\"If you want to know more about the history of our village, the storyteller Cain knows quite a bit about the past.\");\r\nconst char *TEXT_166 = N_(\"Wirt is a rapscallion and a little scoundrel. He was always getting into trouble, and it's no surprise what happened to him. \\n \\nHe probably went fooling about someplace that he shouldn't have been. I feel sorry for the boy, but I don't abide the company that he keeps.\");\r\nconst char *TEXT_167 = N_(\"Pepin is a good man - and certainly the most generous in the village. He is always attending to the needs of others, but trouble of some sort or another does seem to follow him wherever he goes...\");\r\nconst char *TEXT_168 = N_(\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, she would have fled from here long ago. \\n \\nGoodness knows I begged her to leave, telling her that I would watch after the old woman, but she is too sweet and caring to have done so.\");\r\nconst char *TEXT_169 = N_(\"What ails you, my friend?\");\r\nconst char *TEXT_170 = N_(\"I have made a very interesting discovery. Unlike us, the creatures in the Labyrinth can heal themselves without the aid of potions or magic. If you hurt one of the monsters, make sure it is dead or it very well may regenerate itself.\");\r\nconst char *TEXT_171 = N_(\"Before it was taken over by, well, whatever lurks below, the Cathedral was a place of great learning. There are many books to be found there. If you find any, you should read them all, for some may hold secrets to the workings of the Labyrinth.\");\r\nconst char *TEXT_172 = N_(\"Griswold knows as much about the art of war as I do about the art of healing. He is a shrewd merchant, but his work is second to none. Oh, I suppose that may be because he is the only blacksmith left here.\");\r\nconst char *TEXT_173 = N_(\"Cain is a true friend and a wise sage. He maintains a vast library and has an innate ability to discern the true nature of many things. If you ever have any questions, he is the person to go to.\");\r\nconst char *TEXT_174 = N_(\"Even my skills have been unable to fully heal Farnham. Oh, I have been able to mend his body, but his mind and spirit are beyond anything I can do.\");\r\nconst char *TEXT_175 = N_(\"While I use some limited forms of magic to create the potions and elixirs I store here, Adria is a true sorceress. She never seems to sleep, and she always has access to many mystic tomes and artifacts. I believe her hut may be much more than the hovel it appears to be, but I can never seem to get inside the place.\");\r\nconst char *TEXT_176 = N_(\"Poor Wirt. I did all that was possible for the child, but I know he despises that wooden peg that I was forced to attach to his leg. His wounds were hideous. No one - and especially such a young child - should have to suffer the way he did.\");\r\nconst char *TEXT_177 = N_(\"I really don't understand why Ogden stays here in Tristram. He suffers from a slight nervous condition, but he is an intelligent and industrious man who would do very well wherever he went. I suppose it may be the fear of the many murders that happen in the surrounding countryside, or perhaps the wishes of his wife that keep him and his family where they are.\");\r\nconst char *TEXT_178 = N_(\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers from delusions. \\n \\nShe claims that they are visions, but I have no proof of that one way or the other.\");\r\nconst char *TEXT_179 = N_(\"Good day! How may I serve you?\");\r\nconst char *TEXT_180 = N_(\"My grandmother had a dream that you would come and talk to me. She has visions, you know and can see into the future.\");\r\nconst char *TEXT_181 = N_(\"The woman at the edge of town is a witch! She seems nice enough, and her name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n \\nIt would take someone quite brave, like you, to see what she is doing out there.\");\r\nconst char *TEXT_182 = N_(\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he a master craftsman who has won many contests within his guild, but he received praises from our King Leoric himself - may his soul rest in peace. Griswold is also a great hero; just ask Cain.\");\r\nconst char *TEXT_183 = N_(\"Cain has been the storyteller of Tristram for as long as I can remember. He knows so much, and can tell you just about anything about almost everything.\");\r\nconst char *TEXT_184 = N_(\"Farnham is a drunkard who fills his belly with ale and everyone else's ears with nonsense. \\n \\nI know that both Pepin and Ogden feel sympathy for him, but I get so frustrated watching him slip farther and farther into a befuddled stupor every night.\");\r\nconst char *TEXT_185 = N_(\"Pepin saved my grandmother's life, and I know that I can never repay him for that. His ability to heal any sickness is more powerful than the mightiest sword and more mysterious than any spell you can name. If you ever are in need of healing, Pepin can help you.\");\r\nconst char *TEXT_186 = N_(\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt when those hideous creatures stole him, she never recovered. I think she died of a broken heart. Wirt has become a mean-spirited youngster, looking only to profit from the sweat of others. I know that he suffered and has seen horrors that I cannot even imagine, but some of that darkness hangs over him still.\");\r\nconst char *TEXT_187 = N_(\"Ogden and his wife have taken me and my grandmother into their home and have even let me earn a few gold pieces by working at the inn. I owe so much to them, and hope one day to leave this place and help them start a grand hotel in the east.\");\r\nconst char *TEXT_188 = N_(\"Well, what can I do for ya?\");\r\nconst char *TEXT_189 = N_(\"If you're looking for a good weapon, let me show this to you. Take your basic blunt weapon, such as a mace. Works like a charm against most of those undying horrors down there, and there's nothing better to shatter skinny little skeletons!\");\r\nconst char *TEXT_190 = N_(\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it cleaves the air, and then imagine a nice fat demon head in its path. Keep in mind, however, that it is slow to swing - but talk about dealing a heavy blow!\");\r\nconst char *TEXT_191 = N_(\"Look at that edge, that balance. A sword in the right hands, and against the right foe, is the master of all weapons. Its keen blade finds little to hack or pierce on the undead, but against a living, breathing enemy, a sword will better slice their flesh!\");\r\nconst char *TEXT_192 = N_(\"Your weapons and armor will show the signs of your struggles against the Darkness. If you bring them to me, with a bit of work and a hot forge, I can restore them to top fighting form.\");\r\nconst char *TEXT_193 = N_(\"While I have to practically smuggle in the metals and tools I need from caravans that skirt the edges of our damned town, that witch, Adria, always seems to get whatever she needs. If I knew even the smallest bit about how to harness magic as she did, I could make some truly incredible things.\");\r\nconst char *TEXT_194 = N_(\"Gillian is a nice lass. Shame that her gammer is in such poor health or I would arrange to get both of them out of here on one of the trading caravans.\");\r\nconst char *TEXT_195 = N_(\"Sometimes I think that Cain talks too much, but I guess that is his calling in life. If I could bend steel as well as he can bend your ear, I could make a suit of court plate good enough for an Emperor!\");\r\nconst char *TEXT_196 = N_(\"I was with Farnham that night that Lazarus led us into Labyrinth. I never saw the Archbishop again, and I may not have survived if Farnham was not at my side. I fear that the attack left his soul as crippled as, well, another did my leg. I cannot fight this battle for him now, but I would if I could.\");\r\nconst char *TEXT_197 = N_(\"A good man who puts the needs of others above his own. You won't find anyone left in Tristram - or anywhere else for that matter - who has a bad thing to say about the healer.\");\r\nconst char *TEXT_198 = N_(\"That lad is going to get himself into serious trouble... or I guess I should say, again. I've tried to interest him in working here and learning an honest trade, but he prefers the high profits of dealing in goods of dubious origin. I cannot hold that against him after what happened to him, but I do wish he would at least be careful.\");\r\nconst char *TEXT_199 = N_(\"The Innkeeper has little business and no real way of turning a profit. He manages to make ends meet by providing food and lodging for those who occasionally drift through the village, but they are as likely to sneak off into the night as they are to pay him. If it weren't for the stores of grains and dried meats he kept in his cellar, why, most of us would have starved during that first year when the entire countryside was overrun by demons.\");\r\nconst char *TEXT_200 = N_(\"Can't a fella drink in peace?\");\r\nconst char *TEXT_201 = N_(\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\");\r\nconst char *TEXT_202 = N_(\"Why don't that old crone do somethin' for a change. Sure, sure, she's got stuff, but you listen to me... she's unnatural. I ain't never seen her eat or drink - and you can't trust somebody who doesn't drink at least a little.\");\r\nconst char *TEXT_203 = N_(\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of 'em are real scary or funny... but I think he knows more than he knows he knows.\");\r\nconst char *TEXT_204 = N_(\"Griswold? Good old Griswold. I love him like a brother! We fought together, you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\");\r\nconst char *TEXT_205 = N_(\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should make sure you get to know him. Good fella like that with people always wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a hero too...\");\r\nconst char *TEXT_206 = N_(\"Wirt is a kid with more problems than even me, and I know all about problems. Listen here - that kid is gotta sweet deal, but he's been there, you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\");\r\nconst char *TEXT_207 = N_(\"Ogden is the best man in town. I don't think his wife likes me much, but as long as she keeps tappin' kegs, I'll like her just fine. Seems like I been spendin' more time with Ogden than most, but he's so good to me...\");\r\nconst char *TEXT_208 = N_(\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my specialty. This here is the best... theeeee best! That other ale ain't no good since those stupid dogs...\");\r\nconst char *TEXT_209 = N_(\"No one ever lis... listens to me. Somewhere - I ain't too sure - but somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and just waitin' for someone to get it.\");\r\nconst char *TEXT_210 = N_(\"I know you gots your own ideas, and I know you're not gonna believe this, but that weapon you got there - it just ain't no good against those big brutes! Oh, I don't care what Griswold says, they can't make anything like they used to in the old days...\");\r\nconst char *TEXT_211 = N_(\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got and get out of here. That boy out there... He's always got somethin' good, but you gotta give him some gold or he won't even show you what he's got.\");\r\nconst char *TEXT_212 = N_(\"I sense a soul in search of answers...\");\r\nconst char *TEXT_213 = N_(\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its words. Should you already have knowledge of the arcane mysteries scribed within a book, remember - that level of mastery can always increase.\");\r\nconst char *TEXT_214 = N_(\"The greatest power is often the shortest lived. You may find ancient words of power written upon scrolls of parchment. The strength of these scrolls lies in the ability of either apprentice or adept to cast them with equal ability. Their weakness is that they must first be read aloud and can never be kept at the ready in your mind. Know also that these scrolls can be read but once, so use them with care.\");\r\nconst char *TEXT_215 = N_(\"Though the heat of the sun is beyond measure, the mere flame of a candle is of greater danger. No energies, no matter how great, can be used without the proper focus. For many spells, ensorcelled Staves may be charged with magical energies many times over. I have the ability to restore their power - but know that nothing is done without a price.\");\r\nconst char *TEXT_216 = N_(\"The sum of our knowledge is in the sum of its people. Should you find a book or scroll that you cannot decipher, do not hesitate to bring it to me. If I can make sense of it I will share what I find.\");\r\nconst char *TEXT_217 = N_(\"To a man who only knows Iron, there is no greater magic than Steel. The blacksmith Griswold is more of a sorcerer than he knows. His ability to meld fire and metal is unequaled in this land.\");\r\nconst char *TEXT_218 = N_(\"Corruption has the strength of deceit, but innocence holds the power of purity. The young woman Gillian has a pure heart, placing the needs of her matriarch over her own. She fears me, but it is only because she does not understand me.\");\r\nconst char *TEXT_219 = N_(\"A chest opened in darkness holds no greater treasure than when it is opened in the light. The storyteller Cain is an enigma, but only to those who do not look. His knowledge of what lies beneath the cathedral is far greater than even he allows himself to realize.\");\r\nconst char *TEXT_220 = N_(\"The higher you place your faith in one man, the farther it has to fall. Farnham has lost his soul, but not to any demon. It was lost when he saw his fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to be gleaned, but you must separate fact from fantasy.\");\r\nconst char *TEXT_221 = N_(\"The hand, the heart and the mind can perform miracles when they are in perfect harmony. The healer Pepin sees into the body in a way that even I cannot. His ability to restore the sick and injured is magnified by his understanding of the creation of elixirs and potions. He is as great an ally as you have in Tristram.\");\r\nconst char *TEXT_222 = N_(\"There is much about the future we cannot see, but when it comes it will be the children who wield it. The boy Wirt has a blackness upon his soul, but he poses no threat to the town or its people. His secretive dealings with the urchins and unspoken guilds of nearby towns gain him access to many devices that cannot be easily found in Tristram. While his methods may be reproachful, Wirt can provide assistance for your battle against the encroaching Darkness.\");\r\nconst char *TEXT_223 = N_(\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden serves more of a purpose in this town than many understand. He provides shelter for Gillian and her matriarch, maintains what life Farnham has left to him, and provides an anchor for all who are left in the town to what Tristram once was. His tavern, and the simple pleasures that can still be found there, provide a glimpse of a life that the people here remember. It is that memory that continues to feed their hopes for your success.\");\r\nconst char *TEXT_224 = N_(\"Pssst... over here...\");\r\nconst char *TEXT_225 = N_(\"Not everyone in Tristram has a use - or a market - for everything you will find in the labyrinth. Not even me, as hard as that is to believe. \\n \\nSometimes, only you will be able to find a purpose for some things.\");\r\nconst char *TEXT_226 = N_(\"Don't trust everything the drunk says. Too many ales have fogged his vision and his good sense.\");\r\nconst char *TEXT_227 = N_(\"In case you haven't noticed, I don't buy anything from Tristram. I am an importer of quality goods. If you want to peddle junk, you'll have to see Griswold, Pepin or that witch, Adria. I'm sure that they will snap up whatever you can bring them...\");\r\nconst char *TEXT_228 = N_(\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold offered me an apprenticeship at the smithy, and he is a nice enough guy, but I'll never get enough money to... well, let's just say that I have definite plans that require a large amount of gold.\");\r\nconst char *TEXT_229 = N_(\"If I were a few years older, I would shower her with whatever riches I could muster, and let me assure you I can get my hands on some very nice stuff. Gillian is a beautiful girl who should get out of Tristram as soon as it is safe. Hmmm... maybe I'll take her with me when I go...\");\r\nconst char *TEXT_230 = N_(\"Cain knows too much. He scares the life out of me - even more than that woman across the river. He keeps telling me about how lucky I am to be alive, and how my story is foretold in legend. I think he's off his crock.\");\r\nconst char *TEXT_231 = N_(\"Farnham - now there is a man with serious problems, and I know all about how serious problems can be. He trusted too much in the integrity of one man, and Lazarus led him into the very jaws of death. Oh, I know what it's like down there, so don't even start telling me about your plans to destroy the evil that dwells in that Labyrinth. Just watch your legs...\");\r\nconst char *TEXT_232 = N_(\"As long as you don't need anything reattached, old Pepin is as good as they come. \\n \\nIf I'd have had some of those potions he brews, I might still have my leg...\");\r\nconst char *TEXT_233 = N_(\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about the past, but that witch can see into your past. She always has some way to get whatever she needs, too. Adria gets her hands on more merchandise than I've seen pass through the gates of the King's Bazaar during High Festival.\");\r\nconst char *TEXT_234 = N_(\"Ogden is a fool for staying here. I could get him out of town for a very reasonable price, but he insists on trying to make a go of it with that stupid tavern. I guess at the least he gives Gillian a place to work, and his wife Garda does make a superb Shepherd's pie...\");\r\nconst char *TEXT_235 = N_(\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written.\");\r\nconst char *TEXT_236 = N_(\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken...\");\r\nconst char *TEXT_237 = N_(\"I can see what you see not.\\nVision milky then eyes rot.\\nWhen you turn they will be gone,\\nWhispering their hidden song.\\nThen you see what cannot be,\\nShadows move where light should be.\\nOut of darkness, out of mind,\\nCast down into the Halls of the Blind.\");\r\nconst char *TEXT_238 = N_(\"The armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and men alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood.\");\r\nconst char *TEXT_249 = N_(\"Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. There is a war that rages on even now, beyond the fields that we know - between the utopian kingdoms of the High Heavens and the chaotic pits of the Burning Hells. This war is known as the Great Conflict, and it has raged and burned longer than any of the stars in the sky. Neither side ever gains sway for long as the forces of Light and Darkness constantly vie for control over all creation.\");\r\nconst char *TEXT_250 = N_(\"Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. When the Eternal Conflict between the High Heavens and the Burning Hells falls upon mortal soil, it is called the Sin War. Angels and Demons walk amongst humanity in disguise, fighting in secret, away from the prying eyes of mortals. Some daring, powerful mortals have even allied themselves with either side, and helped to dictate the course of the Sin War.\");\r\nconst char *TEXT_251 = N_(\"Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. Nearly three hundred years ago, it came to be known that the Three Prime Evils of the Burning Hells had mysteriously come to our world. The Three Brothers ravaged the lands of the east for decades, while humanity was left trembling in their wake. Our Order - the Horadrim - was founded by a group of secretive magi to hunt down and capture the Three Evils once and for all.\\n \\nThe original Horadrim captured two of the Three within powerful artifacts known as Soulstones and buried them deep beneath the desolate eastern sands. The third Evil escaped capture and fled to the west with many of the Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - was eventually captured, his essence set in a Soulstone and buried within this Labyrinth.\\n \\nBe warned that the soulstone must be kept from discovery by those not of the faith. If Diablo were to be released, he would seek a body that is easily controlled as he would be very weak - perhaps that of an old man or a child.\");\r\nconst char *TEXT_252 = N_(\"So it came to be that there was a great revolution within the Burning Hells known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils and banished their spirit forms to the mortal realm. The demons Belial (the Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of Hell during the absence of the Three Brothers. All of Hell polarized between the factions of Belial and Azmodan while the forces of the High Heavens continually battered upon the very Gates of Hell.\");\r\nconst char *TEXT_253 = N_(\"Many demons traveled to the mortal realm in search of the Three Brothers. These demons were followed to the mortal plane by Angels who hunted them throughout the vast cities of the East. The Angels allied themselves with a secretive Order of mortal magi named the Horadrim, who quickly became adept at hunting demons. They also made many dark enemies in the underworlds.\");\r\nconst char *TEXT_254 = N_(\"So it came to be that the Three Prime Evils were banished in spirit form to the mortal realm and after sewing chaos across the East for decades, they were hunted down by the cursed Order of the mortal Horadrim. The Horadrim used artifacts called Soulstones to contain the essence of Mephisto, the Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest brother - Diablo, the Lord of Terror - escaped to the west.\\n \\nEventually the Horadrim captured Diablo within a Soulstone as well, and buried him under an ancient, forgotten Cathedral. There, the Lord of Terror sleeps and awaits the time of his rebirth. Know ye that he will seek a body of youth and power to possess - one that is innocent and easily controlled. He will then arise to free his Brothers and once more fan the flames of the Sin War...\");\r\nconst char *TEXT_255 = N_(\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When he awakened from his long slumber, my Lord and Master spoke to me of secrets that few mortals know. He told me the kingdoms of the High Heavens and the pits of the Burning Hells engage in an eternal war. He revealed the powers that have brought this discord to the realms of man. My lord has named the battle for this world and all who exist here the Sin War.\");\r\nconst char *TEXT_256 = N_(\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished to this world long ago. My Lord wishes to bide his time and harness his awesome power so that he may free his captive brothers from their tombs beneath the sands of the east. Once my Lord releases his Brothers, the Sin War will once again know the fury of the Three.\");\r\nconst char *TEXT_257 = N_(\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I awoke my Master from his sleep, he attempted to possess a mortal's form. Diablo attempted to claim the body of King Leoric, but my Master was too weak from his imprisonment. My Lord required a simple and innocent anchor to this world, and so found the boy Albrecht to be perfect for the task. While the good King Leoric was left maddened by Diablo's unsuccessful possession, I kidnapped his son Albrecht and brought him before my Master. I now await Diablo's call and pray that I will be rewarded when he at last emerges as the Lord of this world.\");\r\nconst char *TEXT_258 = N_(\"Thank goodness you've returned!\\nMuch has changed since you lived here, my friend. All was peaceful until the dark riders came and destroyed our village. Many were cut down where they stood, and those who took up arms were slain or dragged away to become slaves - or worse. The church at the edge of town has been desecrated and is being used for dark rituals. The screams that echo in the night are inhuman, but some of our townsfolk may yet survive. Follow the path that lies between my tavern and the blacksmith shop to find the church and save who you can. \\n \\nPerhaps I can tell you more if we speak again. Good luck.\");\r\nconst char *TEXT_267 = N_(\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding a treasure that is hidden less so.  I will leave you with this.  Do not let the sands of time confuse your search.\");\r\nconst char *TEXT_268 = N_(\"A what?!  This is foolishness.  There's no treasure buried here in Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They don't match our town at all.  I'd keep my mind on what lies below the cathedral and not what lies below our topsoil.\");\r\nconst char *TEXT_269 = N_(\"I really don't have time to discuss some map you are looking for.  I have many sick people that require my help and yours as well.\");\r\nconst char *TEXT_270 = N_(\"The once proud Iswall is trapped deep beneath the surface of this world.  His honor stripped and his visage altered.  He is trapped in immortal torment.  Charged to conceal the very thing that could free him.\");\r\nconst char *TEXT_271 = N_(\"I'll bet that Wirt saw you coming and put on an act just so he could laugh at you later when you were running around the town with your nose in the dirt.  I'd ignore it.\");\r\nconst char *TEXT_272 = N_(\"There was a time when this town was a frequent stop for travelers from far and wide.  Much has changed since then.  But hidden caves and buried treasure are common fantasies of any child.  Wirt seldom indulges in youthful games.  So it may just be his imagination.\");\r\nconst char *TEXT_273 = N_(\"Listen here.  Come close.  I don't know if you know what I know, but you've have really got something here.  That's a map.\");\r\nconst char *TEXT_274 = N_(\"My grandmother often tells me stories about the strange forces that inhabit the graveyard outside of the church.  And it may well interest you to hear one of them.  She said that if you were to leave the proper offering in the cemetery, enter the cathedral to pray for the dead, and then return, the offering would be altered in some strange way.  I don't know if this is just the talk of an old sick woman, but anything seems possible these days.\");\r\nconst char *TEXT_275 = N_(\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be interested in picking up a few things from you.  Or better yet, don't you need some rare and expensive supplies to get you through this ordeal?\");\r\nconst char *TEXT_277 = N_(\"So, you're the hero everyone's been talking about. Perhaps you could help a poor, simple farmer out of a terrible mess? At the edge of my orchard, just south of here, there's a horrible thing swelling out of the ground! I can't get to my crops or my bales of hay, and my poor cows will starve. The witch gave this to me and said that it would blast that thing out of my field. If you could destroy it, I would be forever grateful. I'd do it myself, but someone has to stay here with the cows...\");\r\nconst char *TEXT_278 = N_(\"I knew that it couldn't be as simple as that witch made it sound. It's a sad world when you can't even trust your neighbors.\");\r\nconst char *TEXT_279 = N_(\"Is it gone? Did you send it back to the dark recesses of Hades that spawned it? You what? Oh, don't tell me you lost it! Those things don't come cheap, you know. You've got to find it, and then blast that horror out of our town.\");\r\nconst char *TEXT_280 = N_(\"I heard the explosion from here! Many thanks to you, kind stranger. What with all these things comin' out of the ground, monsters taking over the church, and so forth, these are trying times. I am but a poor farmer, but here -- take this with my great thanks.\");\r\nconst char *TEXT_281 = N_(\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with all the other troubles. Maybe after you've cleansed the church of some of those creatures you could come back... and spare a little time to help a poor farmer?\");\r\nconst char *TEXT_282 = N_(\"Waaaah! (sniff) Waaaah! (sniff)\");\r\nconst char *TEXT_283 = N_(\"I lost Theo!  I lost my best friend!  We were playing over by the river, and Theo said he wanted to go look at the big green thing.  I said we shouldn't, but we snuck over there, and then suddenly this BUG came out!  We ran away but Theo fell down and the bug GRABBED him and took him away!\");\r\nconst char *TEXT_284 = N_(\"Didja find him?  You gotta find Theodore, please!  He's just little.  He can't take care of himself!  Please!\");\r\nconst char *TEXT_285 = N_(\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, Theo, let's go home!  Thanks again, hero person!\");\r\nconst char *TEXT_286 = N_(\"We have long lain dormant, and the time to awaken has come.  After our long sleep, we are filled with great hunger.  Soon, now, we shall feed...\");\r\nconst char *TEXT_287 = N_(\"Have you been enjoying yourself, little mammal?  How pathetic. Your little world will be no challenge at all.\");\r\nconst char *TEXT_288 = N_(\"These lands shall be defiled, and our brood shall overrun the fields that men call home.  Our tendrils shall envelop this world, and we will feast on the flesh of its denizens.  Man shall become our chattel and sustenance.\");\r\nconst char *TEXT_289 = N_(\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and fear...how enticing...\");\r\nconst char *TEXT_296 = N_(\"And in the year of the Golden Light, it was so decreed that a great Cathedral be raised.  The cornerstone of this holy place was to be carved from the translucent stone Antyrael, named for the Angel who shared his power with the Horadrim.  \\n \\nIn the Year of Drawing Shadows, the ground shook and the Cathedral shattered and fell.  As the building of catacombs and castles began and man stood against the ravages of the Sin War, the ruins were scavenged for their stones.  And so it was that the cornerstone vanished from the eyes of man. \\n \\nThe stone was of this world -- and of all worlds -- as the Light is both within all things and beyond all things. Light and unity are the products of this holy foundation, a unity of purpose and a unity of possession.\");\r\nconst char *TEXT_297 = N_(\"Moo.\");\r\nconst char *TEXT_298 = N_(\"I said, Moo.\");\r\nconst char *TEXT_299 = N_(\"Look I'm just a cow, OK?\");\r\nconst char *TEXT_300 = N_(\"All right, all right.  I'm not really a cow.  I don't normally go around like this; but, I was sitting at home minding my own business and all of a sudden these bugs & vines & bulbs & stuff started coming out of the floor... it was horrible!  If only I had something normal to wear, it wouldn't be so bad.  Hey!  Could you go back to my place and get my suit for me?  The brown one, not the gray one, that's for evening wear.  I'd do it myself, but I don't want anyone seeing me like this.  Here, take this, you might need it... to kill those things that have overgrown everything.  You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.\");\r\nconst char *TEXT_301 = N_(\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein over there keeps winking at me!\");\r\nconst char *TEXT_302 = N_(\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like you wouldn't believe!\");\r\nconst char *TEXT_303 = N_(\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need the BROWN suit.\");\r\nconst char *TEXT_304 = N_(\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as a gift; and, you know... a little fashion tip... you could use a little... you could use a new... yknowwhatImean?  The whole adventurer motif is just so... retro.  Just a word of advice, eh?  Ciao.\");\r\nconst char *TEXT_305 = N_(\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under your belt!  We'll talk...\");\r\nconst char *TEXT_307 = N_(\"It must truly be a fearsome task I've set before you. If there was just some way that I could... would a flagon of some nice, fresh milk help?\");\r\nconst char *TEXT_308 = N_(\"Oh, I could use your help, but perhaps after you've saved the catacombs from the desecration of those beasts.\");\r\nconst char *TEXT_309 = N_(\"I need something done, but I couldn't impose on a perfect stranger. Perhaps after you've been here a while I might feel more comfortable asking a favor.\");\r\nconst char *TEXT_310 = N_(\"I see in you the potential for greatness.  Perhaps sometime while you are fulfilling your destiny, you could stop by and do a little favor for me?\");\r\nconst char *TEXT_311 = N_(\"I think you could probably help me, but perhaps after you've gotten a little more powerful. I wouldn't want to injure the village's only chance to destroy the menace in the church!\");\r\nconst char *TEXT_312 = N_(\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\");\r\nconst char *TEXT_313 = N_(\"I don't have to explain myself to every tourist that walks by!  Don't you have some monsters to kill?  Maybe we'll talk later.  If you live...\");\r\nconst char *TEXT_314 = N_(\"Quit bugging me.  I'm looking for someone really heroic.  And you're not it.  I can't trust you, you're going to get eaten by monsters any day now... I need someone who's an experienced hero.\");\r\nconst char *TEXT_315 = N_(\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was sitting at home, feeling moo-dy, when things got really un-stable; a whole stampede of monsters came out of the floor!  I just cowed.  I just happened to be wearing this Jersey when I ran out the door, and now I look udderly ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  Hey!  Can you go back to my place and get my suit for me?  The brown one, not the gray one, that's for evening wear.  I'd do it myself, but I don't want anyone seeing me like this.  Here, take this, you might need it... to kill those things that have overgrown everything.  You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.\");\r\nconst char *TEXT_317 = N_(\"I have tried spells, threats, abjuration and bargaining with this foul creature -- to no avail.  My methods of enslaving lesser demons seem to have no effect on this fearsome beast.\");\r\nconst char *TEXT_318 = N_(\"My home is slowly becoming corrupted by the vileness of this unwanted prisoner.  The crypts are full of shadows that move just beyond the corners of my vision.  The faint scrabble of claws dances at the edges of my hearing. They are searching, I think, for this journal.\");\r\nconst char *TEXT_319 = N_(\"In its ranting, the creature has let slip its name -- Na-Krul.  I have attempted to research the name, but the smaller demons have somehow destroyed my library.  Na-Krul... The name fills me with a cold dread.  I prefer to think of it only as The Creature rather than ponder its true name.\");\r\nconst char *TEXT_320 = N_(\"The entrapped creature's howls of fury keep me from gaining much needed sleep.  It rages against the one who sent it to the Void, and it calls foul curses upon me for trapping it here.  Its words fill my heart with terror, and yet I cannot block out its voice.\");\r\nconst char *TEXT_321 = N_(\"My time is quickly running out.  I must record the ways to weaken the demon, and then conceal that text, lest his minions find some way to use my knowledge to free their lord.  I hope that whoever finds this journal will seek the knowledge.\");\r\nconst char *TEXT_322 = N_(\"Whoever finds this scroll is charged with stopping the demonic creature that lies within these walls.  My time is over. Even now, its hellish minions claw at the frail door behind which I hide.  \\n \\nI have hobbled the demon with arcane magic and encased it within great walls, but I fear that will not be enough. \\n \\nThe spells found in my three grimoires will provide you protected entrance to his domain, but only if cast in their proper sequence.  The levers at the entryway will remove the barriers and free the demon; touch them not!  Use only these spells to gain entry or his power may be too great for you to defeat.\");\r\nconst char *TEXT_323 = N_(\"In Spiritu Sanctum.\");\r\nconst char *TEXT_324 = N_(\"Praedictum Otium.\");\r\nconst char *TEXT_325 = N_(\"Efficio Obitus Ut Inimicus.\");\r\nconst char *MT_HELLBOAR_NAME = P_(\"monster\", \"Hellboar\");\r\nconst char *MT_STINGER_NAME = P_(\"monster\", \"Stinger\");\r\nconst char *MT_PSYCHORB_NAME = P_(\"monster\", \"Psychorb\");\r\nconst char *MT_ARACHNON_NAME = P_(\"monster\", \"Arachnon\");\r\nconst char *MT_FELLTWIN_NAME = P_(\"monster\", \"Felltwin\");\r\nconst char *MT_HORKSPWN_NAME = P_(\"monster\", \"Hork Spawn\");\r\nconst char *MT_VENMTAIL_NAME = P_(\"monster\", \"Venomtail\");\r\nconst char *MT_NECRMORB_NAME = P_(\"monster\", \"Necromorb\");\r\nconst char *MT_SPIDLORD_NAME = P_(\"monster\", \"Spider Lord\");\r\nconst char *MT_LASHWORM_NAME = P_(\"monster\", \"Lashworm\");\r\nconst char *MT_TORCHANT_NAME = P_(\"monster\", \"Torchant\");\r\nconst char *MT_DEFILER_NAME = P_(\"monster\", \"Hell Bug\");\r\nconst char *MT_GRAVEDIG_NAME = P_(\"monster\", \"Gravedigger\");\r\nconst char *MT_TOMBRAT_NAME = P_(\"monster\", \"Tomb Rat\");\r\nconst char *MT_FIREBAT_NAME = P_(\"monster\", \"Firebat\");\r\nconst char *MT_SKLWING_NAME = P_(\"monster\", \"Skullwing\");\r\nconst char *MT_LICH_NAME = P_(\"monster\", \"Lich\");\r\nconst char *MT_CRYPTDMN_NAME = P_(\"monster\", \"Crypt Demon\");\r\nconst char *MT_HELLBAT_NAME = P_(\"monster\", \"Hellbat\");\r\nconst char *MT_BONEDEMN_NAME = P_(\"monster\", \"Bone Demon\");\r\nconst char *MT_ARCHLICH_NAME = P_(\"monster\", \"Arch Lich\");\r\nconst char *MT_BICLOPS_NAME = P_(\"monster\", \"Biclops\");\r\nconst char *MT_FLESTHNG_NAME = P_(\"monster\", \"Flesh Thing\");\r\nconst char *MT_REAPER_NAME = P_(\"monster\", \"Reaper\");\r\nconst char *UNIQUE_ITEM_90_NAME = N_(\"Giant's Knuckle\");\r\nconst char *UNIQUE_ITEM_91_NAME = N_(\"Mercurial Ring\");\r\nconst char *UNIQUE_ITEM_92_NAME = N_(\"Xorine's Ring\");\r\nconst char *UNIQUE_ITEM_93_NAME = N_(\"Karik's Ring\");\r\nconst char *UNIQUE_ITEM_94_NAME = N_(\"Ring of Magma\");\r\nconst char *UNIQUE_ITEM_95_NAME = N_(\"Ring of the Mystics\");\r\nconst char *UNIQUE_ITEM_96_NAME = N_(\"Ring of Thunder\");\r\nconst char *UNIQUE_ITEM_97_NAME = N_(\"Amulet of Warding\");\r\nconst char *UNIQUE_ITEM_98_NAME = N_(\"Gnat Sting\");\r\nconst char *UNIQUE_ITEM_99_NAME = N_(\"Flambeau\");\r\nconst char *UNIQUE_ITEM_100_NAME = N_(\"Armor of Gloom\");\r\nconst char *UNIQUE_ITEM_101_NAME = N_(\"Blitzen\");\r\nconst char *UNIQUE_ITEM_102_NAME = N_(\"Thunderclap\");\r\nconst char *UNIQUE_ITEM_103_NAME = N_(\"Shirotachi\");\r\nconst char *UNIQUE_ITEM_104_NAME = N_(\"Eater of Souls\");\r\nconst char *UNIQUE_ITEM_105_NAME = N_(\"Diamondedge\");\r\nconst char *UNIQUE_ITEM_106_NAME = N_(\"Bone Chain Armor\");\r\nconst char *UNIQUE_ITEM_107_NAME = N_(\"Demon Plate Armor\");\r\nconst char *UNIQUE_ITEM_108_NAME = N_(\"Acolyte's Amulet\");\r\nconst char *UNIQUE_ITEM_109_NAME = N_(\"Gladiator's Ring\");\r\nconst char *ITEM_PREFIX_83_NAME = N_(\"Jester's\");\r\nconst char *ITEM_PREFIX_84_NAME = N_(\"Crystalline\");\r\nconst char *ITEM_PREFIX_85_NAME = N_(\"Doppelganger's\");\r\nconst char *ITEM_SUFFIX_95_NAME = N_(\"devastation\");\r\nconst char *ITEM_SUFFIX_96_NAME = N_(\"decay\");\r\nconst char *ITEM_SUFFIX_97_NAME = N_(\"peril\");\r\nconst char *SPELL_MANA_NAME = P_(\"spell\", \"Mana\");\r\nconst char *SPELL_THE_MAGI_NAME = P_(\"spell\", \"the Magi\");\r\nconst char *SPELL_THE_JESTER_NAME = P_(\"spell\", \"the Jester\");\r\nconst char *SPELL_LIGHTNING_WALL_NAME = P_(\"spell\", \"Lightning Wall\");\r\nconst char *SPELL_IMMOLATION_NAME = P_(\"spell\", \"Immolation\");\r\nconst char *SPELL_WARP_NAME = P_(\"spell\", \"Warp\");\r\nconst char *SPELL_REFLECT_NAME = P_(\"spell\", \"Reflect\");\r\nconst char *SPELL_BERSERK_NAME = P_(\"spell\", \"Berserk\");\r\nconst char *SPELL_RING_OF_FIRE_NAME = P_(\"spell\", \"Ring of Fire\");\r\nconst char *SPELL_SEARCH_NAME = P_(\"spell\", \"Search\");\r\nconst char *SPELL_RUNE_OF_FIRE_NAME = P_(\"spell\", \"Rune of Fire\");\r\nconst char *SPELL_RUNE_OF_LIGHT_NAME = P_(\"spell\", \"Rune of Light\");\r\nconst char *SPELL_RUNE_OF_NOVA_NAME = P_(\"spell\", \"Rune of Nova\");\r\nconst char *SPELL_RUNE_OF_IMMOLATION_NAME = P_(\"spell\", \"Rune of Immolation\");\r\nconst char *SPELL_RUNE_OF_STONE_NAME = P_(\"spell\", \"Rune of Stone\");\r\n\r\n} // namespace\r\n"
  },
  {
    "path": "Source/utils/algorithm/container.hpp",
    "content": "#pragma once\r\n\r\n#include <algorithm>\r\n#include <iterator>\r\n#include <type_traits>\r\n#include <utility>\r\n\r\nnamespace devilution {\r\n\r\n// Internal namespace that sets up ADL lookup and the container Iterator type.\r\nnamespace container_internal {\r\nusing std::begin;\r\nusing std::end;\r\n\r\ntemplate <typename C>\r\nusing Iterator = decltype(begin(std::declval<C &>()));\r\n\r\ntemplate <typename C>\r\nusing Difference = typename std::iterator_traits<Iterator<C>>::difference_type;\r\n\r\ntemplate <typename C>\r\nIterator<C> c_begin(C &c)\r\n{\r\n\treturn begin(c);\r\n}\r\n\r\ntemplate <typename C>\r\nIterator<C> c_end(C &c)\r\n{\r\n\treturn end(c);\r\n}\r\n\r\n} // namespace container_internal\r\n\r\ntemplate <typename C, typename Predicate>\r\nbool c_any_of(const C &c, Predicate &&predicate)\r\n{\r\n\treturn std::any_of(container_internal::begin(c),\r\n\t    container_internal::end(c),\r\n\t    std::forward<Predicate>(predicate));\r\n}\r\n\r\ntemplate <typename C, typename Predicate>\r\nbool c_all_of(const C &c, Predicate &&predicate)\r\n{\r\n\treturn std::all_of(container_internal::begin(c),\r\n\t    container_internal::end(c),\r\n\t    std::forward<Predicate>(predicate));\r\n}\r\n\r\ntemplate <typename C, typename Predicate>\r\nbool c_none_of(const C &c, Predicate &&predicate)\r\n{\r\n\treturn std::none_of(container_internal::begin(c),\r\n\t    container_internal::end(c),\r\n\t    std::forward<Predicate>(predicate));\r\n}\r\n\r\ntemplate <typename C, typename T>\r\ncontainer_internal::Iterator<C>\r\nc_find(C &c, T &&value)\r\n{\r\n\treturn std::find(container_internal::begin(c),\r\n\t    container_internal::end(c),\r\n\t    std::forward<T>(value));\r\n}\r\n\r\ntemplate <typename C, typename Predicate>\r\ncontainer_internal::Iterator<C>\r\nc_find_if(C &c, Predicate &&predicate)\r\n{\r\n\treturn std::find_if(container_internal::begin(c),\r\n\t    container_internal::end(c),\r\n\t    std::forward<Predicate>(predicate));\r\n}\r\n\r\ntemplate <typename C, typename Predicate>\r\ncontainer_internal::Difference<C>\r\nc_count_if(const C &c, Predicate &&predicate)\r\n{\r\n\treturn std::count_if(container_internal::c_begin(c),\r\n\t    container_internal::c_end(c),\r\n\t    std::forward<Predicate>(predicate));\r\n}\r\n\r\ntemplate <typename C, typename T>\r\ncontainer_internal::Difference<C>\r\nc_count(const C &c, T &&value)\r\n{\r\n\treturn std::count(container_internal::c_begin(c),\r\n\t    container_internal::c_end(c),\r\n\t    std::forward<T>(value));\r\n}\r\n\r\ntemplate <typename C>\r\nvoid c_sort(C &c)\r\n{\r\n\tstd::sort(container_internal::c_begin(c),\r\n\t    container_internal::c_end(c));\r\n}\r\n\r\ntemplate <typename C, typename LessThan>\r\nvoid c_sort(C &c, LessThan &&comp)\r\n{\r\n\tstd::sort(container_internal::c_begin(c),\r\n\t    container_internal::c_end(c),\r\n\t    std::forward<LessThan>(comp));\r\n}\r\n\r\ntemplate <typename C, typename T>\r\ncontainer_internal::Iterator<C> c_lower_bound(C &c, T &&value)\r\n{\r\n\treturn std::lower_bound(container_internal::c_begin(c),\r\n\t    container_internal::c_end(c),\r\n\t    std::forward<T>(value));\r\n}\r\n\r\ntemplate <typename C>\r\ncontainer_internal::Iterator<C> c_unique(C &c)\r\n{\r\n\treturn std::unique(container_internal::c_begin(c),\r\n\t    container_internal::c_end(c));\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/attributes.h",
    "content": "/**\r\n * @file attributes.h\r\n *\r\n * Macros for attributes on functions, variables, etc.\r\n */\r\n#pragma once\r\n\r\n#ifdef __has_attribute\r\n#define DVL_HAVE_ATTRIBUTE(x) __has_attribute(x)\r\n#else\r\n#define DVL_HAVE_ATTRIBUTE(x) 0\r\n#endif\r\n\r\n#ifdef __has_builtin\r\n#define DVL_HAVE_BUILTIN(x) __has_builtin(x)\r\n#else\r\n#define DVL_HAVE_BUILTIN(x) 0\r\n#endif\r\n\r\n#if DVL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__))\r\n#define DVL_PRINTF_ATTRIBUTE(fmtargnum, firstarg) \\\r\n\t__attribute__((__format__(__printf__, fmtargnum, firstarg)))\r\n#else\r\n#define DVL_PRINTF_ATTRIBUTE(fmtargnum, firstarg)\r\n#endif\r\n\r\n#if DVL_HAVE_ATTRIBUTE(pure)\r\n#define DVL_PURE __attribute__((pure))\r\n#else\r\n#define DVL_PURE\r\n#endif\r\n\r\n#if DVL_HAVE_ATTRIBUTE(always_inline)\r\n#define DVL_ALWAYS_INLINE inline __attribute__((always_inline))\r\n#elif defined(_MSC_VER)\r\n#define DVL_ALWAYS_INLINE __forceinline\r\n#else\r\n#define DVL_ALWAYS_INLINE inline\r\n#endif\r\n\r\n#if DVL_HAVE_ATTRIBUTE(noinline)\r\n#define DVL_NO_INLINE __attribute__((noinline))\r\n#elif defined(_MSC_VER)\r\n#define DVL_NO_INLINE __declspec(noinline)\r\n#else\r\n#define DVL_NO_INLINE\r\n#endif\r\n\r\n#if DVL_HAVE_ATTRIBUTE(hot)\r\n#define DVL_ATTRIBUTE_HOT __attribute__((hot))\r\n#else\r\n#define DVL_ATTRIBUTE_HOT\r\n#endif\r\n\r\n// Any global data used by tests must be marked with `DVL_API_FOR_TEST`.\r\n#if defined(_MSC_VER) && defined(BUILD_TESTING)\r\n#ifdef _DVL_EXPORTING\r\n#define DVL_API_FOR_TEST __declspec(dllexport)\r\n#else\r\n#define DVL_API_FOR_TEST __declspec(dllimport)\r\n#endif\r\n#else\r\n#define DVL_API_FOR_TEST\r\n#endif\r\n\r\n#if defined(__clang__)\r\n#define DVL_REINITIALIZES [[clang::reinitializes]]\r\n#elif DVL_HAVE_ATTRIBUTE(reinitializes)\r\n#define DVL_REINITIALIZES __attribute__((reinitializes))\r\n#else\r\n#define DVL_REINITIALIZES\r\n#endif\r\n\r\n#if ((defined(__GNUC__) || defined(__clang__)) && !defined(__EXCEPTIONS)) || defined(_MSC_VER) && !_HAS_EXCEPTIONS\r\n// NOLINTNEXTLINE(modernize-macro-to-enum)\r\n#define DVL_EXCEPTIONS 0\r\n#else\r\n// NOLINTNEXTLINE(modernize-macro-to-enum)\r\n#define DVL_EXCEPTIONS 1\r\n#endif\r\n\r\n#if defined(_MSC_VER)\r\n#define DVL_RESTRICT __restrict\r\n#else\r\n#define DVL_RESTRICT __restrict__\r\n#endif\r\n\r\n#ifdef __has_cpp_attribute\r\n#if __has_cpp_attribute(assume) >= 202207L\r\n#define DVL_ASSUME(...) [[assume(__VA_ARGS__)]]\r\n#endif\r\n#endif\r\n#ifndef DVL_ASSUME\r\n#if defined(__clang__)\r\n#define DVL_ASSUME(...)                \\\r\n\tdo {                               \\\r\n\t\t__builtin_assume(__VA_ARGS__); \\\r\n\t} while (false)\r\n#elif defined(_MSC_VER)\r\n#define DVL_ASSUME(...)        \\\r\n\tdo {                       \\\r\n\t\t__assume(__VA_ARGS__); \\\r\n\t} while (false)\r\n#elif defined(__GNUC__)\r\n#if __GNUC__ >= 13\r\n#define DVL_ASSUME(...) __attribute__((__assume__(__VA_ARGS__)))\r\n#endif\r\n#endif\r\n#endif\r\n#ifndef DVL_ASSUME\r\n#define DVL_ASSUME(...)\r\n#endif\r\n\r\n#if defined(__clang__) || defined(__GNUC__)\r\n#define DVL_UNREACHABLE() __builtin_unreachable()\r\n#elif defined(_MSC_VER)\r\n#define DVL_UNREACHABLE() __assume(false)\r\n#else\r\n#define DVL_UNREACHABLE()\r\n#endif\r\n\r\n#if DVL_HAVE_BUILTIN(__builtin_expect)\r\n#define DVL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))\r\n#define DVL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))\r\n#else\r\n#define DVL_PREDICT_FALSE(x) (x)\r\n#define DVL_PREDICT_TRUE(x) (x)\r\n#endif\r\n"
  },
  {
    "path": "Source/utils/aulib.hpp",
    "content": "#pragma once\r\n#ifndef NOSOUND\r\n\r\n#include <memory>\r\n\r\n#include <Aulib/Stream.h>\r\n\r\n#include \"engine/sound_defs.hpp\" // for DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\n#include <Aulib/ResamplerSpeex.h>\r\n#endif\r\n\r\n#ifdef DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n#include <Aulib/ResamplerSdl.h>\r\n#endif\r\n\r\n#include \"options.h\"\r\n\r\nnamespace devilution {\r\n\r\ninline std::unique_ptr<Aulib::Resampler> CreateAulibResampler(int sourceRate)\r\n{\r\n\tif (Aulib::sampleRate() == sourceRate)\r\n\t\treturn nullptr;\r\n\tswitch (*GetOptions().Audio.resampler) {\r\n#ifdef DEVILUTIONX_RESAMPLER_SPEEX\r\n\tcase Resampler::Speex:\r\n\t\treturn std::make_unique<Aulib::ResamplerSpeex>(*GetOptions().Audio.resamplingQuality);\r\n#endif\r\n#ifdef DVL_AULIB_SUPPORTS_SDL_RESAMPLER\r\n\tcase Resampler::SDL:\r\n\t\treturn std::make_unique<Aulib::ResamplerSdl>();\r\n#endif\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\n} // namespace devilution\r\n\r\n#endif // !NOSOUND\r\n"
  },
  {
    "path": "Source/utils/bitset2d.hpp",
    "content": "#pragma once\r\n\r\n#include <bitset>\r\n#include <cstddef>\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief A 2D variant of std::bitset.\r\n *\r\n * For function documentation, see `std::bitset`\r\n *\r\n * @tparam Width\r\n * @tparam Height\r\n */\r\ntemplate <size_t Width, size_t Height>\r\nclass Bitset2d {\r\npublic:\r\n\tbool test(size_t x, size_t y) const\r\n\t{\r\n\t\treturn data_.test(index(x, y));\r\n\t}\r\n\r\n\tvoid set(size_t x, size_t y, bool value = true)\r\n\t{\r\n\t\tdata_.set(index(x, y), value);\r\n\t}\r\n\r\n\tvoid reset(size_t x, size_t y)\r\n\t{\r\n\t\tdata_.reset(index(x, y));\r\n\t}\r\n\r\n\tvoid reset()\r\n\t{\r\n\t\tdata_.reset();\r\n\t}\r\n\r\n\t[[nodiscard]] size_t count() const\r\n\t{\r\n\t\treturn data_.count();\r\n\t}\r\n\r\nprivate:\r\n\tstatic size_t index(size_t x, size_t y)\r\n\t{\r\n\t\treturn y * Width + x;\r\n\t}\r\n\r\n\tstd::bitset<Width * Height> data_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/cel_to_clx.cpp",
    "content": "#include \"utils/cel_to_clx.hpp\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include <vector>\r\n\r\n#ifdef DEBUG_CEL_TO_CL2_SIZE\r\n#include <iomanip>\r\n#include <iostream>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/clx_encode.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconstexpr bool IsCelTransparent(uint8_t control)\r\n{\r\n\tconstexpr uint8_t CelTransparentMin = 0x80;\r\n\treturn control >= CelTransparentMin;\r\n}\r\n\r\nconstexpr uint8_t GetCelTransparentWidth(uint8_t control)\r\n{\r\n\treturn -static_cast<int8_t>(control);\r\n}\r\n\r\n} // namespace\r\n\r\nOwnedClxSpriteListOrSheet CelToClx(const uint8_t *data, size_t size, PointerOrValue<uint16_t> widthOrWidths)\r\n{\r\n\t// A CEL file either begins with:\r\n\t// 1. A CEL header.\r\n\t// 2. A list of offsets to frame groups (each group is a CEL file).\r\n\tsize_t groupsHeaderSize = 0;\r\n\tuint32_t numGroups = 1;\r\n\tconst uint32_t maybeNumFrames = LoadLE32(data);\r\n\r\n\tstd::vector<uint8_t> cl2Data;\r\n\r\n\t// Most files become smaller with CL2. Allocate exactly enough bytes to avoid reallocation.\r\n\t// The only file that becomes larger is data\\hf_logo3.cel, by exactly 4445 bytes.\r\n\tcl2Data.reserve(size + 4445);\r\n\r\n\t// If it is a number of frames, then the last frame offset will be equal to the size of the file.\r\n\tif (LoadLE32(&data[maybeNumFrames * 4 + 4]) != size) {\r\n\t\t// maybeNumFrames is the address of the first group, right after\r\n\t\t// the list of group offsets.\r\n\t\tnumGroups = maybeNumFrames / 4;\r\n\t\tgroupsHeaderSize = maybeNumFrames;\r\n\t\tdata += groupsHeaderSize;\r\n\t\tcl2Data.resize(groupsHeaderSize);\r\n\t}\r\n\r\n\tfor (size_t group = 0; group < numGroups; ++group) {\r\n\t\tuint32_t numFrames;\r\n\t\tif (numGroups == 1) {\r\n\t\t\tnumFrames = maybeNumFrames;\r\n\t\t} else {\r\n\t\t\tnumFrames = LoadLE32(data);\r\n\t\t\tWriteLE32(&cl2Data[4 * group], static_cast<uint32_t>(cl2Data.size()));\r\n\t\t}\r\n\r\n\t\t// CL2 header: frame count, frame offset for each frame, file size\r\n\t\tconst size_t cl2DataOffset = cl2Data.size();\r\n\t\tcl2Data.resize(cl2Data.size() + 4 * (2 + static_cast<size_t>(numFrames)));\r\n\t\tWriteLE32(&cl2Data[cl2DataOffset], numFrames);\r\n\r\n\t\tconst uint8_t *srcEnd = &data[LoadLE32(&data[4])];\r\n\t\tfor (size_t frame = 1; frame <= numFrames; ++frame) {\r\n\t\t\tconst uint8_t *src = srcEnd;\r\n\t\t\tsrcEnd = &data[LoadLE32(&data[4 * (frame + 1)])];\r\n\t\t\tWriteLE32(&cl2Data[cl2DataOffset + 4 * frame], static_cast<uint32_t>(cl2Data.size() - cl2DataOffset));\r\n\r\n\t\t\t// Skip CEL frame header if there is one.\r\n\t\t\tconstexpr size_t CelFrameHeaderSize = 10;\r\n\t\t\tconst bool celFrameHasHeader = LoadLE16(src) == CelFrameHeaderSize;\r\n\t\t\tif (celFrameHasHeader)\r\n\t\t\t\tsrc += CelFrameHeaderSize;\r\n\r\n\t\t\tconst unsigned frameWidth = widthOrWidths.HoldsPointer() ? widthOrWidths.AsPointer()[frame - 1] : widthOrWidths.AsValue();\r\n\r\n\t\t\t// CLX frame header.\r\n\t\t\tconst size_t frameHeaderPos = cl2Data.size();\r\n\t\t\tcl2Data.resize(cl2Data.size() + ClxFrameHeaderSize);\r\n\t\t\tWriteLE16(&cl2Data[frameHeaderPos], ClxFrameHeaderSize);\r\n\t\t\tWriteLE16(&cl2Data[frameHeaderPos + 2], frameWidth);\r\n\r\n\t\t\tunsigned transparentRunWidth = 0;\r\n\t\t\tsize_t frameHeight = 0;\r\n\t\t\twhile (src != srcEnd) {\r\n\t\t\t\t// Process line:\r\n\t\t\t\tfor (unsigned remainingCelWidth = frameWidth; remainingCelWidth != 0;) {\r\n\t\t\t\t\tuint8_t val = *src++;\r\n\t\t\t\t\tif (IsCelTransparent(val)) {\r\n\t\t\t\t\t\tval = GetCelTransparentWidth(val);\r\n\t\t\t\t\t\ttransparentRunWidth += val;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tAppendClxTransparentRun(transparentRunWidth, cl2Data);\r\n\t\t\t\t\t\ttransparentRunWidth = 0;\r\n\t\t\t\t\t\tAppendClxPixelsOrFillRun(src, val, cl2Data);\r\n\t\t\t\t\t\tsrc += val;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tremainingCelWidth -= val;\r\n\t\t\t\t}\r\n\t\t\t\t++frameHeight;\r\n\t\t\t}\r\n\t\t\tWriteLE16(&cl2Data[frameHeaderPos + 4], static_cast<uint16_t>(frameHeight));\r\n\t\t\tAppendClxTransparentRun(transparentRunWidth, cl2Data);\r\n\t\t}\r\n\r\n\t\tWriteLE32(&cl2Data[cl2DataOffset + 4 * (1 + static_cast<size_t>(numFrames))], static_cast<uint32_t>(cl2Data.size() - cl2DataOffset));\r\n\t\tdata = srcEnd;\r\n\t}\r\n\r\n\tauto out = std::unique_ptr<uint8_t[]>(new uint8_t[cl2Data.size()]);\r\n\tmemcpy(&out[0], cl2Data.data(), cl2Data.size());\r\n#ifdef DEBUG_CEL_TO_CL2_SIZE\r\n\tstd::cout << \"\\t\" << size << \"\\t\" << cl2Data.size() << \"\\t\" << std::setprecision(1) << std::fixed << (static_cast<int>(cl2Data.size()) - static_cast<int>(size)) / ((float)size) * 100 << \"%\" << std::endl;\r\n#endif\r\n\treturn OwnedClxSpriteListOrSheet { std::move(out), static_cast<uint16_t>(numGroups == 1 ? 0 : numGroups) };\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/cel_to_clx.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"utils/pointer_value_union.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nOwnedClxSpriteListOrSheet CelToClx(const uint8_t *data, size_t size, PointerOrValue<uint16_t> widthOrWidths);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/cl2_to_clx.cpp",
    "content": "#include \"utils/cl2_to_clx.hpp\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include <vector>\r\n\r\n#include \"utils/clx_decode.hpp\"\r\n#include \"utils/clx_encode.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nuint16_t Cl2ToClx(const uint8_t *data, size_t size,\r\n    PointerOrValue<uint16_t> widthOrWidths, std::vector<uint8_t> &clxData)\r\n{\r\n\tuint32_t numGroups = 1;\r\n\tconst uint32_t maybeNumFrames = LoadLE32(data);\r\n\tconst uint8_t *groupBegin = data;\r\n\r\n\t// If it is a number of frames, then the last frame offset will be equal to the size of the file.\r\n\tif (LoadLE32(&data[maybeNumFrames * 4 + 4]) != size) {\r\n\t\t// maybeNumFrames is the address of the first group, right after\r\n\t\t// the list of group offsets.\r\n\t\tnumGroups = maybeNumFrames / 4;\r\n\t\tclxData.resize(maybeNumFrames);\r\n\t}\r\n\r\n\t// Transient buffer for a contiguous run of non-transparent pixels.\r\n\tstd::vector<uint8_t> pixels;\r\n\tpixels.reserve(4096);\r\n\r\n\tfor (size_t group = 0; group < numGroups; ++group) {\r\n\t\tuint32_t numFrames;\r\n\t\tif (numGroups == 1) {\r\n\t\t\tnumFrames = maybeNumFrames;\r\n\t\t} else {\r\n\t\t\tgroupBegin = &data[LoadLE32(&data[group * 4])];\r\n\t\t\tnumFrames = LoadLE32(groupBegin);\r\n\t\t\tWriteLE32(&clxData[4 * group], static_cast<uint32_t>(clxData.size()));\r\n\t\t}\r\n\r\n\t\t// CLX header: frame count, frame offset for each frame, file size\r\n\t\tconst size_t clxDataOffset = clxData.size();\r\n\t\tclxData.resize(clxData.size() + 4 * (2 + static_cast<size_t>(numFrames)));\r\n\t\tWriteLE32(&clxData[clxDataOffset], numFrames);\r\n\r\n\t\tconst uint8_t *frameEnd = &groupBegin[LoadLE32(&groupBegin[4])];\r\n\t\tfor (size_t frame = 1; frame <= numFrames; ++frame) {\r\n\t\t\tWriteLE32(&clxData[clxDataOffset + 4 * frame],\r\n\t\t\t    static_cast<uint32_t>(clxData.size() - clxDataOffset));\r\n\r\n\t\t\tconst uint8_t *frameBegin = frameEnd;\r\n\t\t\tframeEnd = &groupBegin[LoadLE32(&groupBegin[4 * (frame + 1)])];\r\n\r\n\t\t\tconst uint16_t frameWidth = widthOrWidths.HoldsPointer() ? widthOrWidths.AsPointer()[frame - 1] : widthOrWidths.AsValue();\r\n\r\n\t\t\tconst size_t frameHeaderPos = clxData.size();\r\n\t\t\tclxData.resize(clxData.size() + ClxFrameHeaderSize);\r\n\t\t\tWriteLE16(&clxData[frameHeaderPos], ClxFrameHeaderSize);\r\n\t\t\tWriteLE16(&clxData[frameHeaderPos + 2], frameWidth);\r\n\r\n\t\t\tunsigned transparentRunWidth = 0;\r\n\t\t\tint_fast16_t xOffset = 0;\r\n\t\t\tsize_t frameHeight = 0;\r\n\t\t\tconst uint8_t *src = frameBegin + LoadLE16(frameBegin);\r\n\t\t\twhile (src != frameEnd) {\r\n\t\t\t\tauto remainingWidth = static_cast<int_fast16_t>(frameWidth) - xOffset;\r\n\t\t\t\twhile (remainingWidth > 0) {\r\n\t\t\t\t\tconst uint8_t control = *src++;\r\n\t\t\t\t\tif (!IsClxOpaque(control)) {\r\n\t\t\t\t\t\tif (!pixels.empty()) {\r\n\t\t\t\t\t\t\tAppendClxPixelsOrFillRun(pixels.data(), pixels.size(), clxData);\r\n\t\t\t\t\t\t\tpixels.clear();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\ttransparentRunWidth += control;\r\n\t\t\t\t\t\tremainingWidth -= control;\r\n\t\t\t\t\t} else if (IsClxOpaqueFill(control)) {\r\n\t\t\t\t\t\tAppendClxTransparentRun(transparentRunWidth, clxData);\r\n\t\t\t\t\t\ttransparentRunWidth = 0;\r\n\t\t\t\t\t\tconst uint8_t width = GetClxOpaqueFillWidth(control);\r\n\t\t\t\t\t\tconst uint8_t color = *src++;\r\n\t\t\t\t\t\tpixels.insert(pixels.end(), width, color);\r\n\t\t\t\t\t\tremainingWidth -= width;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tAppendClxTransparentRun(transparentRunWidth, clxData);\r\n\t\t\t\t\t\ttransparentRunWidth = 0;\r\n\t\t\t\t\t\tconst uint8_t width = GetClxOpaquePixelsWidth(control);\r\n\t\t\t\t\t\tpixels.insert(pixels.end(), src, src + width);\r\n\t\t\t\t\t\tsrc += width;\r\n\t\t\t\t\t\tremainingWidth -= width;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst auto skipSize = GetSkipSize(remainingWidth, static_cast<int_fast16_t>(frameWidth));\r\n\t\t\t\txOffset = skipSize.xOffset;\r\n\t\t\t\tframeHeight += skipSize.wholeLines;\r\n\t\t\t}\r\n\t\t\tif (!pixels.empty()) {\r\n\t\t\t\tAppendClxPixelsOrFillRun(pixels.data(), pixels.size(), clxData);\r\n\t\t\t\tpixels.clear();\r\n\t\t\t}\r\n\t\t\tAppendClxTransparentRun(transparentRunWidth, clxData);\r\n\r\n\t\t\tWriteLE16(&clxData[frameHeaderPos + 4], static_cast<uint16_t>(frameHeight));\r\n\t\t}\r\n\r\n\t\tWriteLE32(&clxData[clxDataOffset + 4 * (1 + static_cast<size_t>(numFrames))], static_cast<uint32_t>(clxData.size() - clxDataOffset));\r\n\t}\r\n\treturn numGroups == 1 ? 0 : numGroups;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/cl2_to_clx.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include <memory>\r\n#include <vector>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"utils/pointer_value_union.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Converts CL2 to CLX in-place.\r\n *\r\n * @return uint16_t The number of lists in a sheet if it is a sheet, 0 otherwise.\r\n */\r\nuint16_t Cl2ToClx(const uint8_t *data, size_t size,\r\n    PointerOrValue<uint16_t> widthOrWidths, std::vector<uint8_t> &clxData);\r\n\r\ninline OwnedClxSpriteListOrSheet Cl2ToClx(std::unique_ptr<uint8_t[]> &&data, size_t size, PointerOrValue<uint16_t> widthOrWidths)\r\n{\r\n\tstd::vector<uint8_t> clxData;\r\n\tconst uint16_t numLists = Cl2ToClx(data.get(), size, widthOrWidths, clxData);\r\n\tdata = nullptr;\r\n\tdata = std::unique_ptr<uint8_t[]>(new uint8_t[clxData.size()]);\r\n\tmemcpy(&data[0], clxData.data(), clxData.size());\r\n\treturn OwnedClxSpriteListOrSheet { std::move(data), numLists };\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/clx_decode.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\n[[nodiscard]] constexpr bool IsClxOpaque(uint8_t control)\r\n{\r\n\tconstexpr uint8_t ClxOpaqueMin = 0x80;\r\n\treturn control >= ClxOpaqueMin;\r\n}\r\n\r\n[[nodiscard]] constexpr uint8_t GetClxOpaquePixelsWidth(uint8_t control)\r\n{\r\n\treturn -static_cast<int8_t>(control);\r\n}\r\n\r\n[[nodiscard]] constexpr bool IsClxOpaqueFill(uint8_t control)\r\n{\r\n\tconstexpr uint8_t ClxFillMax = 0xBE;\r\n\treturn control <= ClxFillMax;\r\n}\r\n\r\n[[nodiscard]] constexpr uint8_t GetClxOpaqueFillWidth(uint8_t control)\r\n{\r\n\tconstexpr uint8_t ClxFillEnd = 0xBF;\r\n\treturn ClxFillEnd - control;\r\n}\r\n\r\nstruct SkipSize {\r\n\tint_fast16_t wholeLines;\r\n\tint_fast16_t xOffset;\r\n};\r\n\r\n// Returns the number of lines and the x-offset by which the rendering has overrun\r\n// the current line (when a CLX command overruns the current line).\r\n//\r\n// Requires: remainingWidth <= 0.\r\nDVL_ALWAYS_INLINE SkipSize GetSkipSize(int_fast16_t remainingWidth, int_fast16_t srcWidth)\r\n{\r\n\t// If `remainingWidth` is negative, `-remainingWidth` is the overrun.\r\n\t// Otherwise, `remainingWidth` is always 0.\r\n\r\n\t// Remaining width of 0 (= no overrun) is a common case.\r\n\t// The calculation below would result in the same result.\r\n\t// However, checking for 0 and skipping it entirely turns out to be faster.\r\n\tif (remainingWidth == 0) return { 1, 0 };\r\n\r\n\tconst auto overrun = static_cast<uint_fast16_t>(-remainingWidth);\r\n\tconst uint_fast16_t overrunLines = overrun / srcWidth + 1;\r\n\tconst uint_fast16_t xOffset = overrun % srcWidth;\r\n\treturn { static_cast<int_fast16_t>(overrunLines), static_cast<int_fast16_t>(xOffset) };\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/clx_encode.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <vector>\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * CLX frame header is 6 bytes:\r\n *\r\n *  Bytes |   Type   | Value\r\n * :-----:|:--------:|-------------\r\n *  0..2  | uint16_t | header size\r\n *  2..4  | uint16_t | width\r\n *  4..6  | uint16_t | height\r\n */\r\nconstexpr size_t ClxFrameHeaderSize = 6;\r\n\r\ninline void AppendClxTransparentRun(unsigned width, std::vector<uint8_t> &out)\r\n{\r\n\twhile (width >= 0x7F) {\r\n\t\tout.push_back(0x7F);\r\n\t\twidth -= 0x7F;\r\n\t}\r\n\tif (width == 0)\r\n\t\treturn;\r\n\tout.push_back(width);\r\n}\r\n\r\ninline void AppendClxFillRun(uint8_t color, unsigned width, std::vector<uint8_t> &out)\r\n{\r\n\twhile (width >= 0x3F) {\r\n\t\tout.push_back(0x80);\r\n\t\tout.push_back(color);\r\n\t\twidth -= 0x3F;\r\n\t}\r\n\tif (width == 0)\r\n\t\treturn;\r\n\tout.push_back(0xBF - width);\r\n\tout.push_back(color);\r\n}\r\n\r\ninline void AppendClxPixelsRun(const uint8_t *src, unsigned width, std::vector<uint8_t> &out)\r\n{\r\n\twhile (width >= 0x41) {\r\n\t\tout.push_back(0xBF);\r\n\t\tfor (size_t i = 0; i < 0x41; ++i)\r\n\t\t\tout.push_back(src[i]);\r\n\t\twidth -= 0x41;\r\n\t\tsrc += 0x41;\r\n\t}\r\n\tif (width == 0)\r\n\t\treturn;\r\n\tout.push_back(256 - width);\r\n\tfor (size_t i = 0; i < width; ++i)\r\n\t\tout.push_back(src[i]);\r\n}\r\n\r\ninline void AppendClxPixelsOrFillRun(const uint8_t *src, size_t length, std::vector<uint8_t> &out)\r\n{\r\n\tconst uint8_t *begin = src;\r\n\tconst uint8_t *prevColorBegin = src;\r\n\tunsigned prevColorRunLength = 1;\r\n\tuint8_t prevColor = *src++;\r\n\twhile (--length > 0) {\r\n\t\tconst uint8_t color = *src;\r\n\t\tif (prevColor == color) {\r\n\t\t\t++prevColorRunLength;\r\n\t\t} else {\r\n\t\t\t// A tunable parameter that decides at which minimum length we encode a fill run.\r\n\t\t\t// 3 appears to be optimal for most of our data (much better than 2, rarely very slightly worse than 4).\r\n\t\t\tconstexpr unsigned MinFillRunLength = 3;\r\n\t\t\tif (prevColorRunLength >= MinFillRunLength) {\r\n\t\t\t\tAppendClxPixelsRun(begin, static_cast<unsigned>(prevColorBegin - begin), out);\r\n\t\t\t\tAppendClxFillRun(prevColor, prevColorRunLength, out);\r\n\t\t\t\tbegin = src;\r\n\t\t\t}\r\n\t\t\tprevColorBegin = src;\r\n\t\t\tprevColorRunLength = 1;\r\n\t\t\tprevColor = color;\r\n\t\t}\r\n\t\t++src;\r\n\t}\r\n\r\n\t// Here we use 2 instead of `MinFillRunLength` because we know that this run\r\n\t// is followed by transparent pixels.\r\n\t// Width=2 Fill command takes 2 bytes, while the Pixels command is 3 bytes.\r\n\tif (prevColorRunLength >= 2) {\r\n\t\tAppendClxPixelsRun(begin, static_cast<unsigned>(prevColorBegin - begin), out);\r\n\t\tAppendClxFillRun(prevColor, prevColorRunLength, out);\r\n\t} else {\r\n\t\tAppendClxPixelsRun(begin, static_cast<unsigned>(prevColorBegin - begin + prevColorRunLength), out);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/console.cpp",
    "content": "#include \"./console.h\"\r\n\r\n#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n#include <cstddef>\r\n#include <cstdio>\r\n#include <string>\r\n\r\n// Suppress definitions of `min` and `max` macros by <windows.h>:\r\n#define NOMINMAX 1\r\n#define WIN32_LEAN_AND_MEAN\r\n#include <windows.h>\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nHANDLE GetStderrHandle()\r\n{\r\n\tstatic HANDLE handle = NULL;\r\n\tif (handle == NULL) {\r\n\t\tif (AttachConsole(ATTACH_PARENT_PROCESS)) {\r\n\t\t\thandle = GetStdHandle(STD_ERROR_HANDLE);\r\n\t\t}\r\n\t}\r\n\treturn handle;\r\n}\r\n\r\nvoid WriteToStderr(std::string_view str)\r\n{\r\n\tHANDLE handle = GetStderrHandle();\r\n\tif (handle == NULL)\r\n\t\treturn;\r\n\tWriteConsole(handle, str.data(), static_cast<DWORD>(str.size()), NULL, NULL);\r\n}\r\n\r\n} // namespace\r\n\r\nvoid printInConsole(std::string_view str)\r\n{\r\n\tOutputDebugString(std::string(str).c_str());\r\n\tWriteToStderr(str);\r\n}\r\n\r\nvoid printNewlineInConsole()\r\n{\r\n\tOutputDebugString(\"\\r\\n\");\r\n\tWriteToStderr(\"\\r\\n\");\r\n}\r\n\r\nvoid printfInConsole(const char *fmt, ...)\r\n{\r\n\tchar message[4096];\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tstd::vsnprintf(message, sizeof(message), fmt, ap);\r\n\tva_end(ap);\r\n\tOutputDebugString(message);\r\n\tWriteToStderr(message);\r\n}\r\n\r\nvoid vprintfInConsole(const char *fmt, va_list ap)\r\n{\r\n\tchar message[4096];\r\n\tstd::vsnprintf(message, sizeof(message), fmt, ap);\r\n\tOutputDebugString(message);\r\n\tWriteToStderr(message);\r\n}\r\n\r\n} // namespace devilution\r\n#else\r\n#include <cstdio>\r\n\r\nnamespace devilution {\r\n\r\nvoid printInConsole(std::string_view str)\r\n{\r\n\tstd::fwrite(str.data(), sizeof(char), str.size(), stderr);\r\n}\r\n\r\nvoid printNewlineInConsole()\r\n{\r\n\tstd::fputs(\"\\n\", stderr);\r\n}\r\n\r\nvoid printfInConsole(const char *fmt, ...)\r\n{\r\n\tstd::va_list ap;\r\n\tva_start(ap, fmt);\r\n\tstd::vfprintf(stderr, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid vprintfInConsole(const char *fmt, std::va_list ap)\r\n{\r\n\tstd::vfprintf(stderr, fmt, ap);\r\n}\r\n\r\n} // namespace devilution\r\n#endif\r\n"
  },
  {
    "path": "Source/utils/console.h",
    "content": "#pragma once\r\n\r\n#include <cstdarg>\r\n#include <cstddef>\r\n#include <string_view>\r\n\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nvoid printInConsole(std::string_view str);\r\nvoid printNewlineInConsole();\r\nvoid printfInConsole(const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(1, 2);\r\nvoid vprintfInConsole(const char *fmt, std::va_list ap) DVL_PRINTF_ATTRIBUTE(1, 0);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/display.cpp",
    "content": "#include \"utils/display.h\"\r\n\r\n#include <algorithm>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_hints.h>\r\n#include <SDL3/SDL_init.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_video.h>\r\n#else\r\n#include <SDL.h>\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#ifdef __vita__\r\n#include <psp2/power.h>\r\n#endif\r\n\r\n#ifdef __3DS__\r\n#include \"platform/ctr/display.hpp\"\r\n#endif\r\n\r\n#ifdef NXDK\r\n#include <hal/video.h>\r\n#endif\r\n\r\n#include \"DiabloUI/diabloui.h\"\r\n#include \"config.h\"\r\n#include \"control/control.hpp\"\r\n#include \"controls/controller.h\"\r\n#ifndef USE_SDL1\r\n#include \"controls/devices/game_controller.h\"\r\n#endif\r\n#include \"controls/devices/joystick.h\"\r\n#include \"controls/devices/kbcontroller.h\"\r\n#include \"controls/game_controls.h\"\r\n#include \"controls/touch/gamepad.h\"\r\n#include \"engine/backbuffer_state.hpp\"\r\n#include \"engine/dx.h\"\r\n#include \"headless_mode.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_geometry.h\"\r\n#include \"utils/sdl_wrap.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef USE_SDL1\r\n#ifndef SDL1_VIDEO_MODE_BPP\r\n#define SDL1_VIDEO_MODE_BPP 0\r\n#endif\r\n#ifndef SDL1_VIDEO_MODE_FLAGS\r\n#define SDL1_VIDEO_MODE_FLAGS SDL_SWSURFACE\r\n#endif\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nextern SDLSurfaceUniquePtr RendererTextureSurface; /** defined in dx.cpp */\r\nSDL_Window *ghMainWnd;\r\n\r\nSize forceResolution;\r\n\r\nuint16_t gnScreenWidth;\r\nuint16_t gnScreenHeight;\r\nuint16_t gnViewportHeight;\r\n\r\nuint16_t GetScreenWidth()\r\n{\r\n\treturn gnScreenWidth;\r\n}\r\n\r\nuint16_t GetScreenHeight()\r\n{\r\n\treturn gnScreenHeight;\r\n}\r\n\r\nuint16_t GetViewportHeight()\r\n{\r\n\treturn gnViewportHeight;\r\n}\r\n\r\nRectangle UIRectangle;\r\nconst Rectangle &GetUIRectangle()\r\n{\r\n\treturn UIRectangle;\r\n}\r\n\r\nnamespace {\r\n\r\n#ifndef USE_SDL1\r\nvoid CalculatePreferredWindowSize(int &width, int &height)\r\n{\r\n\tSDL_DisplayMode mode;\r\n#ifdef USE_SDL3\r\n\tint numDisplays = 0;\r\n\tSDL_DisplayID *displays = SDL_GetDisplays(&numDisplays);\r\n\tif (numDisplays <= 0 || displays == nullptr) ErrSdl();\r\n\tconst SDL_DisplayMode *modePtr = SDL_GetDesktopDisplayMode(displays[0]);\r\n\tif (modePtr == nullptr) ErrSdl();\r\n\tmode = *modePtr;\r\n#else\r\n\tif (SDL_GetDesktopDisplayMode(0, &mode) != 0) ErrSdl();\r\n#endif\r\n\r\n\tif (mode.w < mode.h) {\r\n\t\tstd::swap(mode.w, mode.h);\r\n\t}\r\n\r\n\tif (*GetOptions().Graphics.integerScaling) {\r\n\t\tconst int factor = std::min(mode.w / width, mode.h / height);\r\n\t\twidth = mode.w / factor;\r\n\t\theight = mode.h / factor;\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst float wFactor = (float)mode.w / width;\r\n\tconst float hFactor = (float)mode.h / height;\r\n\r\n\tif (wFactor > hFactor) {\r\n\t\twidth = mode.w * height / mode.h;\r\n\t} else {\r\n\t\theight = mode.h * width / mode.w;\r\n\t}\r\n}\r\n#endif\r\n\r\nvoid CalculateUIRectangle()\r\n{\r\n\tconstexpr Size UISize { 640, 480 };\r\n\tUIRectangle = {\r\n\t\t{ (gnScreenWidth - UISize.width) / 2, (gnScreenHeight - UISize.height) / 2 },\r\n\t\tUISize\r\n\t};\r\n}\r\n\r\nSize GetPreferredWindowSize()\r\n{\r\n\tSize windowSize = forceResolution.width != 0 ? forceResolution : *GetOptions().Graphics.resolution;\r\n\r\n#ifndef USE_SDL1\r\n\tif (*GetOptions().Graphics.upscale && *GetOptions().Graphics.fitToScreen) {\r\n\t\tCalculatePreferredWindowSize(windowSize.width, windowSize.height);\r\n\t}\r\n#endif\r\n\tAdjustToScreenGeometry(windowSize);\r\n\treturn windowSize;\r\n}\r\n\r\nconst auto OptionChangeHandlerResolution = (GetOptions().Graphics.resolution.SetValueChangedCallback(ResizeWindow), true);\r\nconst auto OptionChangeHandlerFullscreen = (GetOptions().Graphics.fullscreen.SetValueChangedCallback(SetFullscreenMode), true);\r\n\r\nvoid OptionGrabInputChanged()\r\n{\r\n#ifdef USE_SDL3\r\n\tif (ghMainWnd != nullptr) {\r\n\t\tSDL_SetWindowMouseGrab(ghMainWnd, *GetOptions().Gameplay.grabInput);\r\n\t}\r\n#elif !defined(USE_SDL1)\r\n\tif (ghMainWnd != nullptr) {\r\n\t\tSDL_SetWindowGrab(ghMainWnd, *GetOptions().Gameplay.grabInput ? SDL_TRUE : SDL_FALSE);\r\n\t}\r\n#else\r\n\tSDL_WM_GrabInput(*GetOptions().Gameplay.grabInput ? SDL_GRAB_ON : SDL_GRAB_OFF);\r\n#endif\r\n}\r\nconst auto OptionChangeHandlerGrabInput = (GetOptions().Gameplay.grabInput.SetValueChangedCallback(OptionGrabInputChanged), true);\r\n\r\nvoid UpdateAvailableResolutions()\r\n{\r\n#ifndef USE_SDL1\r\n\tif ((SDL_WasInit(SDL_INIT_VIDEO) & SDL_INIT_VIDEO) == 0) {\r\n\t\t// Called before the video subsystem has been initialized, no-op.\r\n\t\treturn;\r\n\t}\r\n#endif\r\n\tGraphicsOptions &graphicsOptions = GetOptions().Graphics;\r\n\r\n\tstd::vector<Size> sizes;\r\n\tconst float scaleFactor = GetDpiScalingFactor();\r\n\r\n\t// Add resolutions\r\n\tbool supportsAnyResolution = false;\r\n#ifdef USE_SDL3\r\n\tconst SDL_DisplayID displayId = SDL_GetDisplayForWindow(ghMainWnd);\r\n\tif (displayId == 0) ErrSdl();\r\n\tint modeCount;\r\n\tSDLUniquePtr<SDL_DisplayMode *> modes { SDL_GetFullscreenDisplayModes(displayId, &modeCount) };\r\n\tif (modes == nullptr) return;\r\n\tfor (SDL_DisplayMode **it = modes.get(), **end = modes.get() + modeCount; it != end; ++it) {\r\n\t\tconst SDL_DisplayMode &mode = **it;\r\n\t\tint w = mode.w;\r\n\t\tint h = mode.h;\r\n\t\tif (w < h) std::swap(w, h);\r\n\t\tsizes.emplace_back(Size {\r\n\t\t    static_cast<int>(w * scaleFactor),\r\n\t\t    static_cast<int>(h * scaleFactor) });\r\n\t}\r\n\tsupportsAnyResolution = *GetOptions().Graphics.upscale;\r\n#elif !defined(USE_SDL1)\r\n\tint displayModeCount = SDL_GetNumDisplayModes(0);\r\n\tfor (int i = 0; i < displayModeCount; i++) {\r\n\t\tSDL_DisplayMode mode;\r\n\t\tif (SDL_GetDisplayMode(0, i, &mode) != 0) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\t\tif (mode.w < mode.h) {\r\n\t\t\tstd::swap(mode.w, mode.h);\r\n\t\t}\r\n\t\tsizes.emplace_back(Size {\r\n\t\t    static_cast<int>(mode.w * scaleFactor),\r\n\t\t    static_cast<int>(mode.h * scaleFactor) });\r\n\t}\r\n\tsupportsAnyResolution = *GetOptions().Graphics.upscale;\r\n#else\r\n\tauto *modes = SDL_ListModes(nullptr, SDL_FULLSCREEN | SDL_HWPALETTE);\r\n\t// SDL_ListModes returns -1 if any resolution is allowed (for example returned on 3DS)\r\n\tif (modes == (SDL_Rect **)-1) {\r\n\t\tsupportsAnyResolution = true;\r\n\t} else if (modes != nullptr) {\r\n\t\tfor (size_t i = 0; modes[i] != nullptr; i++) {\r\n\t\t\tif (modes[i]->w < modes[i]->h) {\r\n\t\t\t\tstd::swap(modes[i]->w, modes[i]->h);\r\n\t\t\t}\r\n\t\t\tsizes.emplace_back(Size {\r\n\t\t\t    static_cast<int>(modes[i]->w * scaleFactor),\r\n\t\t\t    static_cast<int>(modes[i]->h * scaleFactor) });\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tif (supportsAnyResolution && sizes.size() == 1) {\r\n\t\t// Attempt to provide sensible options for 4:3 and the native aspect ratio\r\n\t\tconst int width = sizes[0].width;\r\n\t\tconst int height = sizes[0].height;\r\n\t\tconst int commonHeights[] = { 480, 540, 720, 960, 1080, 1440, 2160 };\r\n\t\tfor (const int commonHeight : commonHeights) {\r\n\t\t\tif (commonHeight > height)\r\n\t\t\t\tbreak;\r\n\t\t\tsizes.emplace_back(Size { commonHeight * 4 / 3, commonHeight });\r\n\t\t\tif (commonHeight * width % height == 0)\r\n\t\t\t\tsizes.emplace_back(Size { commonHeight * width / height, commonHeight });\r\n\t\t}\r\n\t}\r\n\r\n\tconst Size configuredSize = *graphicsOptions.resolution;\r\n\r\n\t// Ensures that the ini specified resolution is present in resolution list even if it doesn't match a monitor resolution (for example if played in window mode)\r\n\tsizes.push_back(configuredSize);\r\n\t// Ensures that the platform's preferred default resolution is always present\r\n\tsizes.emplace_back(Size { DEFAULT_WIDTH, DEFAULT_HEIGHT });\r\n\t// Ensures that the vanilla Diablo resolution is present on systems that would support it\r\n\tif (supportsAnyResolution)\r\n\t\tsizes.emplace_back(Size { 640, 480 });\r\n\r\n#ifndef USE_SDL1\r\n\tif (*graphicsOptions.fitToScreen) {\r\n#ifdef USE_SDL3\r\n\t\tconst SDL_DisplayID displayId = SDL_GetDisplayForWindow(ghMainWnd);\r\n\t\tif (displayId == 0) ErrSdl();\r\n\t\tconst SDL_DisplayMode *modePtr = SDL_GetDesktopDisplayMode(displayId);\r\n\t\tif (modePtr == nullptr) ErrSdl();\r\n\t\tconst SDL_DisplayMode &mode = *modePtr;\r\n#else\r\n\t\tSDL_DisplayMode mode;\r\n\t\tif (SDL_GetDesktopDisplayMode(0, &mode) != 0) ErrSdl();\r\n#endif\r\n\t\tfor (auto &size : sizes) {\r\n\t\t\tif (mode.h == 0) continue;\r\n\t\t\t// Ensure that the ini specified resolution remains present in the resolution list\r\n\t\t\tif (size.height == configuredSize.height)\r\n\t\t\t\tsize.width = configuredSize.width;\r\n\t\t\telse\r\n\t\t\t\tsize.width = size.height * mode.w / mode.h;\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\t// Sort by width then by height\r\n\tc_sort(sizes, [](const Size &x, const Size &y) -> bool {\r\n\t\tif (x.width == y.width)\r\n\t\t\treturn x.height > y.height;\r\n\t\treturn x.width > y.width;\r\n\t});\r\n\t// Remove duplicate entries\r\n\tsizes.erase(std::unique(sizes.begin(), sizes.end()), sizes.end());\r\n\r\n\tstd::vector<std::pair<Size, std::string>> resolutions;\r\n\tfor (auto &size : sizes) {\r\n#ifndef USE_SDL1\r\n\t\tif (*graphicsOptions.fitToScreen) {\r\n\t\t\tresolutions.emplace_back(size, StrCat(size.height, \"p\"));\r\n\t\t\tcontinue;\r\n\t\t}\r\n#endif\r\n\t\tresolutions.emplace_back(size, StrCat(size.width, \"x\", size.height));\r\n\t}\r\n\tgraphicsOptions.resolution.setAvailableResolutions(std::move(resolutions));\r\n}\r\n\r\n#if !defined(USE_SDL1) || defined(__3DS__)\r\nvoid ResizeWindowAndUpdateResolutionOptions()\r\n{\r\n\tResizeWindow();\r\n#ifndef __3DS__\r\n\tUpdateAvailableResolutions();\r\n#endif\r\n}\r\nconst auto OptionChangeHandlerFitToScreen = (GetOptions().Graphics.fitToScreen.SetValueChangedCallback(ResizeWindowAndUpdateResolutionOptions), true);\r\n#endif\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nconst auto OptionChangeHandlerScaleQuality = (GetOptions().Graphics.scaleQuality.SetValueChangedCallback(ReinitializeTexture), true);\r\nconst auto OptionChangeHandlerIntegerScaling = (GetOptions().Graphics.integerScaling.SetValueChangedCallback(ReinitializeIntegerScale), true);\r\nconst auto OptionChangeHandlerVSync = (GetOptions().Graphics.frameRateControl.SetValueChangedCallback(ReinitializeRenderer), true);\r\n\r\nstruct DisplayModeComparator {\r\n\tSize size;\r\n#ifdef USE_SDL3\r\n\tSDL_PixelFormat pixelFormat;\r\n#else\r\n\tSDL_PixelFormatEnum pixelFormat;\r\n#endif\r\n\r\n\t// Is `a` better than `b`?\r\n#ifdef USE_SDL3\r\n\t[[nodiscard]] bool operator()(const SDL_DisplayMode *aPtr, const SDL_DisplayMode *bPtr)\r\n#else\r\n\t[[nodiscard]] bool operator()(const SDL_DisplayMode &a, const SDL_DisplayMode &b)\r\n#endif\r\n\t{\r\n#ifdef USE_SDL3\r\n\t\tconst SDL_DisplayMode &a = *aPtr;\r\n\t\tconst SDL_DisplayMode &b = *bPtr;\r\n#endif\r\n\t\tconst int dwa = a.w - size.width;\r\n\t\tconst int dha = a.h - size.height;\r\n\t\tconst int dwb = b.w - size.width;\r\n\t\tconst int dhb = b.h - size.height;\r\n\r\n\t\t// A mode that fits the target is always better than one that doesn't:\r\n\t\tif (dha >= 0 && dwa >= 0 && (dhb < 0 || dwb < 0)) return true;\r\n\t\tif (dhb >= 0 && dwb >= 0 && (dha < 0 || dwa < 0)) return false;\r\n\r\n\t\t// Either both modes fit or they both don't.\r\n\r\n\t\t// If they're the same size, prefer one with matching pixel format.\r\n\t\tif (pixelFormat != SDL_PIXELFORMAT_UNKNOWN && a.h == b.h && a.w == b.w) {\r\n\t\t\tif (a.format != b.format) {\r\n\t\t\t\tif (a.format == pixelFormat) return true;\r\n\t\t\t\tif (b.format == pixelFormat) return false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Prefer smallest height difference, or width difference if heights are the same.\r\n\t\treturn a.h != b.h ? std::abs(dha) < std::abs(dhb)\r\n\t\t                  : std::abs(dwa) < std::abs(dwb);\r\n\t}\r\n};\r\n\r\n#endif\r\n\r\n} // namespace\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nSDL_DisplayMode GetNearestDisplayMode(Size preferredSize,\r\n#ifdef USE_SDL3\r\n    SDL_PixelFormat preferredPixelFormat\r\n#else\r\n    SDL_PixelFormatEnum preferredPixelFormat\r\n#endif\r\n)\r\n{\r\n\tSDL_DisplayMode *nearestDisplayMode = nullptr;\r\n#ifdef USE_SDL3\r\n\tconst SDL_DisplayID displayId = SDL_GetDisplayForWindow(ghMainWnd);\r\n\tif (displayId == 0) ErrSdl();\r\n\tint modeCount;\r\n\tSDLUniquePtr<SDL_DisplayMode *> modes { SDL_GetFullscreenDisplayModes(displayId, &modeCount) };\r\n\tif (modes == nullptr) ErrSdl();\r\n\tnearestDisplayMode = *std::min_element(\r\n\t    modes.get(), modes.get() + modeCount, DisplayModeComparator { preferredSize, preferredPixelFormat });\r\n#else\r\n\tSDL_DisplayMode ownedNearestDisplayMode;\r\n\tif (SDL_GetWindowDisplayMode(ghMainWnd, &ownedNearestDisplayMode) != 0) ErrSdl();\r\n\tnearestDisplayMode = &ownedNearestDisplayMode;\r\n\r\n\tconst int displayIndex = SDL_GetWindowDisplayIndex(ghMainWnd);\r\n\tconst int modeCount = SDL_GetNumDisplayModes(displayIndex);\r\n\r\n\t// First, find the best mode among the modes with the requested pixel format.\r\n\tstd::vector<SDL_DisplayMode> modes;\r\n\tmodes.reserve(modeCount);\r\n\tfor (int modeIndex = 0; modeIndex < modeCount; modeIndex++) {\r\n\t\tSDL_DisplayMode displayMode;\r\n\t\tif (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0)\r\n\t\t\tcontinue;\r\n\t\tmodes.push_back(displayMode);\r\n\t}\r\n\tif (!modes.empty()) {\r\n\t\tnearestDisplayMode = &*std::min_element(\r\n\t\t    modes.begin(), modes.end(), DisplayModeComparator { preferredSize, preferredPixelFormat });\r\n\t}\r\n#endif\r\n\r\n\tLogVerbose(\"Nearest display mode to {}x{} is {}x{} {}bpp {}Hz\",\r\n\t    preferredSize.width, preferredSize.height,\r\n\t    nearestDisplayMode->w, nearestDisplayMode->h,\r\n\t    SDL_BITSPERPIXEL(nearestDisplayMode->format),\r\n\t    nearestDisplayMode->refresh_rate);\r\n\r\n\treturn *nearestDisplayMode;\r\n}\r\n#endif\r\n\r\nvoid AdjustToScreenGeometry(Size windowSize)\r\n{\r\n\tgnScreenWidth = windowSize.width;\r\n\tgnScreenHeight = windowSize.height;\r\n\tCalculateUIRectangle();\r\n\tCalculatePanelAreas();\r\n}\r\n\r\nfloat GetDpiScalingFactor()\r\n{\r\n#ifdef USE_SDL3\r\n\tconst float dispScale = SDL_GetWindowDisplayScale(ghMainWnd);\r\n\tif (dispScale == 0.0F) {\r\n\t\tLogError(\"SDL_GetWindowDisplayScale: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn 1.0F;\r\n\t}\r\n\treturn dispScale;\r\n#elif !defined(USE_SDL1)\r\n\tif (renderer == nullptr)\r\n\t\treturn 1.0F;\r\n\r\n\tint renderWidth;\r\n\tint renderHeight;\r\n\tSDL_GetRendererOutputSize(renderer, &renderWidth, &renderHeight);\r\n\r\n\tint windowWidth;\r\n\tint windowHeight;\r\n\tSDL_GetWindowSize(ghMainWnd, &windowWidth, &windowHeight);\r\n\r\n\tconst float hfactor = static_cast<float>(renderWidth) / windowWidth;\r\n\tconst float vhfactor = static_cast<float>(renderHeight) / windowHeight;\r\n\r\n\treturn std::min(hfactor, vhfactor);\r\n#else\r\n\treturn 1.0F;\r\n#endif\r\n}\r\n\r\n#ifdef USE_SDL1\r\nvoid SetVideoMode(int width, int height, int bpp, uint32_t flags)\r\n{\r\n\tLog(\"Setting video mode {}x{} bpp={} flags=0x{:08X}\", width, height, bpp, flags);\r\n\tghMainWnd = SDL_SetVideoMode(width, height, bpp, flags);\r\n\tif (ghMainWnd == nullptr) {\r\n\t\tErrSdl();\r\n\t}\r\n\tconst SDL_Surface *surface = SDL_GetVideoSurface();\r\n\tif (surface == nullptr) {\r\n\t\tErrSdl();\r\n\t}\r\n\tLog(\"Video surface is now {}x{} bpp={} flags=0x{:08X}\",\r\n\t    surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);\r\n}\r\n\r\nvoid SetVideoModeToPrimary(bool fullscreen, int width, int height)\r\n{\r\n\tint flags = SDL1_VIDEO_MODE_FLAGS | SDL_HWPALETTE;\r\n\tif (fullscreen)\r\n\t\tflags |= SDL_FULLSCREEN;\r\n#ifdef __3DS__\r\n\tflags &= ~SDL_FULLSCREEN;\r\n\tflags |= Get3DSScalingFlag(*GetOptions().Graphics.fitToScreen, width, height);\r\n#endif\r\n\tSetVideoMode(width, height, SDL1_VIDEO_MODE_BPP, flags);\r\n\tif (OutputRequiresScaling())\r\n\t\tLog(\"Using software scaling\");\r\n}\r\n#endif\r\n\r\nbool IsFullScreen()\r\n{\r\n#ifdef USE_SDL3\r\n\treturn (SDL_GetWindowFlags(ghMainWnd) & SDL_WINDOW_FULLSCREEN) != 0;\r\n#elif !defined(USE_SDL1)\r\n\treturn (SDL_GetWindowFlags(ghMainWnd) & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0;\r\n#else\r\n\treturn (SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) != 0;\r\n#endif\r\n}\r\n\r\nbool SpawnWindow(const char *lpWindowName)\r\n{\r\n#ifdef __vita__\r\n\tscePowerSetArmClockFrequency(444);\r\n#endif\r\n#ifdef NXDK\r\n\t{\r\n\t\tSize windowSize = forceResolution.width != 0 ? forceResolution : *GetOptions().Graphics.resolution;\r\n\t\tVIDEO_MODE xmode;\r\n\t\tvoid *p = nullptr;\r\n\t\twhile (XVideoListModes(&xmode, 0, 0, &p)) {\r\n\t\t\tif (windowSize.width >= xmode.width && windowSize.height == xmode.height)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tXVideoSetMode(xmode.width, xmode.height, xmode.bpp, xmode.refresh);\r\n\t}\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\n\tSDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, PROJECT_NAME);\r\n\tSDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, PROJECT_VERSION);\r\n\tSDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, \"org.diasurgical.devilutionx\");\r\n\tSDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_URL_STRING, \"https://devilutionx.com\");\r\n\tSDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_TYPE_STRING, \"game\");\r\n\r\n\tSDL_SetHint(SDL_HINT_RETURN_KEY_HIDES_IME, \"1\");\r\n#endif\r\n#if SDL_VERSION_ATLEAST(2, 0, 4) && !defined(USE_SDL3)\r\n\tSDL_SetHint(SDL_HINT_IME_INTERNAL_EDITING, \"1\");\r\n#endif\r\n#if SDL_VERSION_ATLEAST(2, 0, 6) && defined(__vita__)\r\n\tSDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, \"0\");\r\n#endif\r\n#if SDL_VERSION_ATLEAST(2, 0, 10)\r\n\tSDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, \"0\");\r\n#endif\r\n#ifdef USE_SDL3\r\n\tSDL_SetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION, \"0\");\r\n#elif SDL_VERSION_ATLEAST(2, 0, 2)\r\n\tSDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, \"0\");\r\n#endif\r\n#if SDL_VERSION_ATLEAST(2, 0, 12) && !defined(USE_SDL3)\r\n\tSDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, \"0\");\r\n#endif\r\n\r\n\tint initFlags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK;\r\n#ifndef NOSOUND\r\n\tinitFlags |= SDL_INIT_AUDIO;\r\n#endif\r\n#ifndef USE_SDL1\r\n#ifdef USE_SDL3\r\n\tinitFlags |= SDL_INIT_GAMEPAD;\r\n#else\r\n\tinitFlags |= SDL_INIT_GAMECONTROLLER;\r\n#endif\r\n\r\n\tSDL_SetHint(SDL_HINT_ORIENTATIONS, \"LandscapeLeft LandscapeRight\");\r\n#endif\r\n\tif (\r\n#ifdef USE_SDL3\r\n\t    !SDL_Init(initFlags)\r\n#else\r\n\t    SDL_Init(initFlags) <= -1\r\n#endif\r\n\t) {\r\n\t\tErrSdl();\r\n\t}\r\n\tRegisterCustomEvents();\r\n\r\n#ifndef USE_SDL1\r\n\tif (GetOptions().Controller.szMapping[0] != '\\0') {\r\n#ifdef USE_SDL3\r\n\t\tSDL_AddGamepadMapping(GetOptions().Controller.szMapping);\r\n#else\r\n\t\tSDL_GameControllerAddMapping(GetOptions().Controller.szMapping);\r\n#endif\r\n\t}\r\n#endif\r\n\r\n#ifdef USE_SDL1\r\n\t// On SDL 1, there are no ADDED/REMOVED events.\r\n\t// Always try to initialize the first joystick.\r\n\tJoystick::Add(0);\r\n#ifdef __SWITCH__\r\n\t// TODO: There is a bug in SDL2 on Switch where it does not report controllers on startup (Jan 1, 2020)\r\n\tGameController::Add(0);\r\n#endif\r\n#endif\r\n\r\n\tSize windowSize = GetPreferredWindowSize();\r\n\r\n#ifdef USE_SDL1\r\n\tSDL_WM_SetCaption(lpWindowName, WINDOW_ICON_NAME);\r\n\tSetVideoModeToPrimary(*GetOptions().Graphics.fullscreen, windowSize.width, windowSize.height);\r\n\tif (*GetOptions().Gameplay.grabInput)\r\n\t\tSDL_WM_GrabInput(SDL_GRAB_ON);\r\n\tatexit(SDL_VideoQuit); // Without this video mode is not restored after fullscreen.\r\n#else\r\n#ifdef USE_SDL3\r\n\tSDL_WindowFlags flags = SDL_WINDOW_HIGH_PIXEL_DENSITY;\r\n#else\r\n\tint flags = SDL_WINDOW_ALLOW_HIGHDPI;\r\n#endif\r\n\tif (*GetOptions().Graphics.upscale) {\r\n\t\tif (*GetOptions().Graphics.fullscreen) {\r\n#ifdef USE_SDL3\r\n\t\t\tflags |= SDL_WINDOW_FULLSCREEN;\r\n#else\r\n\t\t\tflags |= SDL_WINDOW_FULLSCREEN_DESKTOP;\r\n#endif\r\n\t\t}\r\n\t\tflags |= SDL_WINDOW_RESIZABLE;\r\n\t} else if (*GetOptions().Graphics.fullscreen) {\r\n\t\tflags |= SDL_WINDOW_FULLSCREEN;\r\n\t}\r\n\r\n#ifdef USE_SDL3\r\n\tif (*GetOptions().Graphics.upscale) {\r\n\t\tif (!SDL_CreateWindowAndRenderer(lpWindowName, windowSize.width, windowSize.height, flags, &ghMainWnd, &renderer)) ErrSdl();\r\n\t} else {\r\n\t\tghMainWnd = SDL_CreateWindow(lpWindowName, windowSize.width, windowSize.height, flags);\r\n\t}\r\n#else\r\n\tghMainWnd = SDL_CreateWindow(lpWindowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowSize.width, windowSize.height, flags);\r\n#endif\r\n\r\n#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT)\r\n\tSDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT);\r\n#if USE_SDL3\r\n\tif (!SDL_SetWindowFullscreenMode(ghMainWnd, &nearestDisplayMode)) ErrSdl();\r\n#else\r\n\tif (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) ErrSdl();\r\n#endif\r\n#endif\r\n\r\n// Note: https://github.com/libsdl-org/SDL/issues/962\r\n// This is a solution to a problem related to SDL mouse grab.\r\n// See https://github.com/diasurgical/devilutionX/issues/4251\r\n#ifdef USE_SDL3\r\n\tif (ghMainWnd != nullptr) {\r\n\t\tSDL_SetWindowMouseGrab(ghMainWnd, *GetOptions().Gameplay.grabInput);\r\n\t}\r\n#else\r\n\tif (ghMainWnd != nullptr) {\r\n\t\tSDL_SetWindowGrab(ghMainWnd, *GetOptions().Gameplay.grabInput ? SDL_TRUE : SDL_FALSE);\r\n\t}\r\n#endif\r\n\r\n#endif\r\n\tif (ghMainWnd == nullptr) {\r\n\t\tErrSdl();\r\n\t}\r\n\r\n\tint refreshRate = 60;\r\n#ifndef USE_SDL1\r\n#ifdef USE_SDL3\r\n\tconst SDL_DisplayID displayId = SDL_GetDisplayForWindow(ghMainWnd);\r\n\tif (displayId == 0) ErrSdl();\r\n\tconst SDL_DisplayMode *displayMode = SDL_GetCurrentDisplayMode(displayId);\r\n\tif (displayMode == nullptr) ErrSdl();\r\n\tif (displayMode->refresh_rate != 0.F) {\r\n\t\trefreshRate = static_cast<int>(displayMode->refresh_rate);\r\n\t}\r\n#else\r\n\tSDL_DisplayMode mode;\r\n\tSDL_GetDisplayMode(0, 0, &mode);\r\n\tif (mode.refresh_rate != 0) {\r\n\t\trefreshRate = mode.refresh_rate;\r\n\t}\r\n#endif\r\n#endif\r\n\trefreshDelay = 1000000 / refreshRate;\r\n\r\n\tReinitializeRenderer();\r\n\r\n\tif (ghMainWnd != nullptr) {\r\n\t\tUpdateAvailableResolutions();\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\n#ifndef USE_SDL1\r\nvoid ReinitializeTexture()\r\n{\r\n\tif (texture)\r\n\t\ttexture.reset();\r\n\r\n\tif (renderer == nullptr)\r\n\t\treturn;\r\n\r\n#ifdef USE_SDL3\r\n\tif (!SDL_SetDefaultTextureScaleMode(renderer,\r\n\t        *GetOptions().Graphics.scaleQuality == ScalingQuality::NearestPixel\r\n\t            ? SDL_SCALEMODE_PIXELART\r\n\t            : SDL_SCALEMODE_LINEAR)) {\r\n\t\tLog(\"SDL_SetDefaultTextureScaleMode: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t}\r\n\ttexture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, gnScreenWidth, gnScreenHeight);\r\n#else\r\n\tauto quality = StrCat(static_cast<int>(*GetOptions().Graphics.scaleQuality));\r\n\tSDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, quality.c_str());\r\n\ttexture = SDLWrap::CreateTexture(renderer, DEVILUTIONX_DISPLAY_TEXTURE_FORMAT, SDL_TEXTUREACCESS_STREAMING, gnScreenWidth, gnScreenHeight);\r\n#endif\r\n}\r\n\r\nvoid ReinitializeIntegerScale()\r\n{\r\n\tif (*GetOptions().Graphics.fitToScreen) {\r\n\t\tResizeWindow();\r\n\t\treturn;\r\n\t}\r\n\tif (renderer == nullptr) return;\r\n\r\n#ifdef USE_SDL3\r\n\tint w, h;\r\n\tSDL_RendererLogicalPresentation mode;\r\n\tif (!SDL_GetRenderLogicalPresentation(renderer, &w, &h, &mode)) ErrSdl();\r\n\tconst SDL_RendererLogicalPresentation newMode = *GetOptions().Graphics.integerScaling\r\n\t    ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE\r\n\t    : SDL_LOGICAL_PRESENTATION_LETTERBOX;\r\n\tif (mode != newMode) SDL_SetRenderLogicalPresentation(renderer, w, h, newMode);\r\n#else\r\n\tif (SDL_RenderSetIntegerScale(renderer, *GetOptions().Graphics.integerScaling ? SDL_TRUE : SDL_FALSE) < 0) {\r\n\t\tErrSdl();\r\n\t}\r\n#endif\r\n}\r\n#endif\r\n\r\nvoid ReinitializeRenderer()\r\n{\r\n\tif (ghMainWnd == nullptr)\r\n\t\treturn;\r\n\r\n#ifdef USE_SDL1\r\n\tconst SDL_Surface *surface = SDL_GetVideoSurface();\r\n\tif (surface == nullptr) {\r\n\t\tErrSdl();\r\n\t}\r\n\tAdjustToScreenGeometry(Size(surface->w, surface->h));\r\n#else\r\n\r\n\tif (*GetOptions().Graphics.upscale) {\r\n\t\t// We don't recreate the renderer, because this can result in a freezing (not refreshing) rendering\r\n\t\tif (renderer == nullptr) {\r\n#ifdef USE_SDL3\r\n\t\t\trenderer = SDL_CreateRenderer(ghMainWnd, nullptr);\r\n#else\r\n\t\t\trenderer = SDL_CreateRenderer(ghMainWnd, -1, 0);\r\n#endif\r\n\t\t\tif (renderer == nullptr) {\r\n\t\t\t\tErrSdl();\r\n\t\t\t}\r\n\t\t}\r\n\r\n#ifdef USE_SDL3\r\n\t\tSDL_SetRenderVSync(renderer, *GetOptions().Graphics.frameRateControl == FrameRateControl::VerticalSync ? 1 : 0);\r\n#elif SDL_VERSION_ATLEAST(2, 0, 18)\r\n\t\tSDL_RenderSetVSync(renderer, *GetOptions().Graphics.frameRateControl == FrameRateControl::VerticalSync ? 1 : 0);\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_SetRenderLogicalPresentation(renderer, gnScreenWidth, gnScreenHeight,\r\n\t\t        *GetOptions().Graphics.integerScaling\r\n\t\t            ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE\r\n\t\t            : SDL_LOGICAL_PRESENTATION_LETTERBOX)) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n#else\r\n\t\tif (SDL_RenderSetIntegerScale(renderer, *GetOptions().Graphics.integerScaling ? SDL_TRUE : SDL_FALSE) < 0) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n\r\n\t\tif (SDL_RenderSetLogicalSize(renderer, gnScreenWidth, gnScreenHeight) <= -1) {\r\n\t\t\tErrSdl();\r\n\t\t}\r\n#endif\r\n\r\n\t\tReinitializeTexture();\r\n\r\n#ifdef USE_SDL3\r\n\t\tRendererTextureSurface = SDLSurfaceUniquePtr { SDL_CreateSurface(gnScreenWidth, gnScreenHeight, texture->format) };\r\n\t\tif (RendererTextureSurface == nullptr) ErrSdl();\r\n#else\r\n\t\tUint32 format;\r\n\t\tif (SDL_QueryTexture(texture.get(), &format, nullptr, nullptr, nullptr) < 0) ErrSdl();\r\n\t\tRendererTextureSurface = SDLWrap::CreateRGBSurfaceWithFormat(0, gnScreenWidth, gnScreenHeight, SDL_BITSPERPIXEL(format), format);\r\n#endif\r\n\t} else {\r\n\t\tSize windowSize = {};\r\n\t\tSDL_GetWindowSize(ghMainWnd, &windowSize.width, &windowSize.height);\r\n\t\tAdjustToScreenGeometry(windowSize);\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid SetFullscreenMode()\r\n{\r\n#ifdef USE_SDL1\r\n\tUint32 flags = ghMainWnd->flags ^ SDL_FULLSCREEN;\r\n\tif (*GetOptions().Graphics.fullscreen) {\r\n\t\tflags |= SDL_FULLSCREEN;\r\n\t}\r\n\tghMainWnd = SDL_SetVideoMode(0, 0, 0, flags);\r\n\tif (ghMainWnd == NULL) {\r\n\t\tErrSdl();\r\n\t}\r\n#else\r\n\t// When switching from windowed to \"true fullscreen\",\r\n\t// update the display mode of the window before changing the\r\n\t// fullscreen mode so that the display mode only has to change once\r\n\tif (*GetOptions().Graphics.fullscreen && !*GetOptions().Graphics.upscale) {\r\n\t\tconst Size windowSize = GetPreferredWindowSize();\r\n\t\tconst SDL_DisplayMode displayMode = GetNearestDisplayMode(windowSize);\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_SetWindowFullscreenMode(ghMainWnd, &displayMode)) ErrSdl();\r\n#else\r\n\t\tif (SDL_SetWindowDisplayMode(ghMainWnd, &displayMode) != 0) ErrSdl();\r\n#endif\r\n\t}\r\n\r\n#if USE_SDL3\r\n\tif (!SDL_SetWindowFullscreen(ghMainWnd, *GetOptions().Graphics.fullscreen)) ErrSdl();\r\n#else\r\n\tconst Uint32 flags = *GetOptions().Graphics.upscale ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN;\r\n\tif (SDL_SetWindowFullscreen(ghMainWnd, *GetOptions().Graphics.fullscreen ? flags : 0) != 0) ErrSdl();\r\n#endif\r\n\r\n\tif (!*GetOptions().Graphics.fullscreen) {\r\n\t\tSDL_RestoreWindow(ghMainWnd); // Avoid window being maximized before resizing\r\n\t\tconst Size windowSize = GetPreferredWindowSize();\r\n\t\tSDL_SetWindowSize(ghMainWnd, windowSize.width, windowSize.height);\r\n\t}\r\n\tif (!*GetOptions().Graphics.upscale) {\r\n\t\t// Because \"true fullscreen\" is locked into specific resolutions based on the modes\r\n\t\t// supported by the display, the resolution may have changed when fullscreen was toggled\r\n\t\tReinitializeRenderer();\r\n\t\tCreateBackBuffer();\r\n\t}\r\n\tInitializeVirtualGamepad();\r\n#endif\r\n\tRedrawEverything();\r\n}\r\n\r\nvoid ResizeWindow()\r\n{\r\n\tif (ghMainWnd == nullptr)\r\n\t\treturn;\r\n\r\n\tconst Size windowSize = GetPreferredWindowSize();\r\n\r\n#ifdef USE_SDL1\r\n\tSetVideoModeToPrimary(*GetOptions().Graphics.fullscreen, windowSize.width, windowSize.height);\r\n#else\r\n\t// For \"true fullscreen\" windows, the window resizes automatically based on the display mode\r\n\tconst bool trueFullscreen = *GetOptions().Graphics.fullscreen && !*GetOptions().Graphics.upscale;\r\n\tif (trueFullscreen) {\r\n\t\tconst SDL_DisplayMode displayMode = GetNearestDisplayMode(windowSize);\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_SetWindowFullscreenMode(ghMainWnd, &displayMode)) ErrSdl();\r\n#else\r\n\t\tif (SDL_SetWindowDisplayMode(ghMainWnd, &displayMode) != 0) ErrSdl();\r\n#endif\r\n\t}\r\n\r\n\t// Handle switching between \"fake fullscreen\" and \"true fullscreen\" when upscale is toggled\r\n\tconst bool upscaleChanged = *GetOptions().Graphics.upscale != (renderer != nullptr);\r\n\tif (upscaleChanged && *GetOptions().Graphics.fullscreen) {\r\n#ifdef USE_SDL3\r\n\t\tif (!SDL_SetWindowFullscreen(ghMainWnd, *GetOptions().Graphics.fullscreen)) ErrSdl();\r\n#else\r\n\t\tconst Uint32 flags = *GetOptions().Graphics.upscale ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN;\r\n\t\tif (SDL_SetWindowFullscreen(ghMainWnd, flags) != 0) ErrSdl();\r\n#endif\r\n\t\tif (!*GetOptions().Graphics.fullscreen)\r\n\t\t\tSDL_RestoreWindow(ghMainWnd); // Avoid window being maximized before resizing\r\n\t}\r\n\r\n\tif (!trueFullscreen)\r\n\t\tSDL_SetWindowSize(ghMainWnd, windowSize.width, windowSize.height);\r\n#endif\r\n\r\n\tReinitializeRenderer();\r\n\r\n#ifndef USE_SDL1\r\n#ifdef USE_SDL3\r\n\tSDL_SetWindowResizable(ghMainWnd, renderer != nullptr);\r\n#else\r\n\tSDL_SetWindowResizable(ghMainWnd, renderer != nullptr ? SDL_TRUE : SDL_FALSE);\r\n#endif\r\n\tInitializeVirtualGamepad();\r\n#endif\r\n\r\n\tCreateBackBuffer();\r\n\tRedrawEverything();\r\n}\r\n\r\nSDL_Surface *GetOutputSurface()\r\n{\r\n#ifdef USE_SDL1\r\n\tSDL_Surface *ret = SDL_GetVideoSurface();\r\n\tif (ret == nullptr)\r\n\t\tErrSdl();\r\n\treturn ret;\r\n#else\r\n\tif (renderer != nullptr)\r\n\t\treturn RendererTextureSurface.get();\r\n\tSDL_Surface *ret = SDL_GetWindowSurface(ghMainWnd);\r\n\tif (ret == nullptr)\r\n\t\tErrSdl();\r\n\treturn ret;\r\n#endif\r\n}\r\n\r\nbool OutputRequiresScaling()\r\n{\r\n#ifdef USE_SDL1\r\n\tif (HeadlessMode)\r\n\t\treturn false;\r\n\treturn gnScreenWidth != GetOutputSurface()->w || gnScreenHeight != GetOutputSurface()->h;\r\n#else // SDL2, scaling handled by renderer.\r\n\treturn false;\r\n#endif\r\n}\r\n\r\nvoid ScaleOutputRect(SDL_Rect *rect)\r\n{\r\n\tif (!OutputRequiresScaling())\r\n\t\treturn;\r\n\tconst SDL_Surface *surface = GetOutputSurface();\r\n\trect->x = rect->x * surface->w / gnScreenWidth;\r\n\trect->y = rect->y * surface->h / gnScreenHeight;\r\n\trect->w = rect->w * surface->w / gnScreenWidth;\r\n\trect->h = rect->h * surface->h / gnScreenHeight;\r\n}\r\n\r\n#ifdef USE_SDL1\r\nnamespace {\r\n\r\nSDLSurfaceUniquePtr CreateScaledSurface(SDL_Surface *src)\r\n{\r\n\tSDL_Rect stretched_rect = MakeSdlRect(0, 0, src->w, src->h);\r\n\tScaleOutputRect(&stretched_rect);\r\n\tSDLSurfaceUniquePtr stretched = SDLWrap::CreateRGBSurface(\r\n\t    SDL_SWSURFACE, stretched_rect.w, stretched_rect.h, src->format->BitsPerPixel,\r\n\t    src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);\r\n\tif (SDL_HasColorKey(src)) {\r\n\t\tSDL_SetColorKey(stretched.get(), SDL_SRCCOLORKEY, src->format->colorkey);\r\n\t\tif (src->format->palette != NULL)\r\n\t\t\tSDL_SetPalette(stretched.get(), SDL_LOGPAL, src->format->palette->colors, 0, src->format->palette->ncolors);\r\n\t}\r\n\tif (SDL_SoftStretch((src), NULL, stretched.get(), &stretched_rect) < 0)\r\n\t\tErrSdl();\r\n\treturn stretched;\r\n}\r\n\r\n} // namespace\r\n#endif // USE_SDL1\r\n\r\nSDLSurfaceUniquePtr ScaleSurfaceToOutput(SDLSurfaceUniquePtr surface)\r\n{\r\n#ifdef USE_SDL1\r\n\tif (OutputRequiresScaling())\r\n\t\treturn CreateScaledSurface(surface.get());\r\n#endif\r\n\treturn surface;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/display.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <type_traits>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_video.h>\r\n#else\r\n#include <SDL.h>\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"utils/attributes.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_ptrs.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern int refreshDelay; // Screen refresh rate in nanoseconds\r\nextern SDL_Window *window;\r\nextern SDL_Window *ghMainWnd;\r\nextern SDL_Renderer *renderer;\r\n#ifndef USE_SDL1\r\nextern SDLTextureUniquePtr texture;\r\n#endif\r\n\r\nextern SDLPaletteUniquePtr Palette;\r\nextern SDL_Surface *PalSurface;\r\nextern DVL_API_FOR_TEST Size forceResolution;\r\n\r\n#ifdef USE_SDL1\r\nvoid SetVideoMode(int width, int height, int bpp, uint32_t flags);\r\nvoid SetVideoModeToPrimary(bool fullscreen, int width, int height);\r\n#endif\r\n\r\nbool IsFullScreen();\r\n\r\n// Returns:\r\n// SDL1: Video surface.\r\n// SDL2, no upscale: Window surface.\r\n// SDL2, upscale: Renderer texture surface.\r\nSDL_Surface *GetOutputSurface();\r\n\r\n// Whether the output surface requires software scaling.\r\n// Always returns false on SDL2.\r\nbool OutputRequiresScaling();\r\n\r\n// Scales rect if necessary.\r\nvoid ScaleOutputRect(SDL_Rect *rect);\r\n\r\n// If the output requires software scaling, replaces the given surface with a scaled one.\r\nSDLSurfaceUniquePtr ScaleSurfaceToOutput(SDLSurfaceUniquePtr surface);\r\n\r\n// Convert from output coordinates to logical (resolution-independent) coordinates.\r\ntemplate <\r\n    typename T,\r\n    typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>\r\nvoid OutputToLogical(T *x, T *y)\r\n{\r\n#ifdef USE_SDL3\r\n\tif (renderer == nullptr) return;\r\n\tfloat outX, outY;\r\n\tif (!SDL_RenderCoordinatesFromWindow(renderer, *x, *y, &outX, &outY)) {\r\n\t\tLogError(\"SDL_RenderCoordinatesFromWindow: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn;\r\n\t}\r\n\t*x = static_cast<T>(outX);\r\n\t*y = static_cast<T>(outY);\r\n#elif !defined(USE_SDL1)\r\n\tif (renderer == nullptr) return;\r\n\tfloat scaleX;\r\n\tSDL_RenderGetScale(renderer, &scaleX, nullptr);\r\n\tfloat scaleDpi = GetDpiScalingFactor();\r\n\tfloat scale = scaleX / scaleDpi;\r\n\t*x = static_cast<T>(*x / scale);\r\n\t*y = static_cast<T>(*y / scale);\r\n\r\n\tSDL_Rect view;\r\n\tSDL_RenderGetViewport(renderer, &view);\r\n\t*x -= view.x;\r\n\t*y -= view.y;\r\n#else\r\n\tif (!OutputRequiresScaling())\r\n\t\treturn;\r\n\tconst SDL_Surface *surface = GetOutputSurface();\r\n\t*x = *x * gnScreenWidth / surface->w;\r\n\t*y = *y * gnScreenHeight / surface->h;\r\n#endif\r\n}\r\n\r\ntemplate <\r\n    typename T,\r\n    typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>\r\nvoid LogicalToOutput(T *x, T *y)\r\n{\r\n#ifdef USE_SDL3\r\n\tif (renderer == nullptr) return;\r\n\tfloat outX, outY;\r\n\tif (!SDL_RenderCoordinatesToWindow(renderer, *x, *y, &outX, &outY)) {\r\n\t\tLogError(\"SDL_RenderCoordinatesFromWindow: {}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t\treturn;\r\n\t}\r\n\t*x = static_cast<T>(outX);\r\n\t*y = static_cast<T>(outY);\r\n#elif !defined(USE_SDL1)\r\n\tif (renderer == nullptr) return;\r\n\tSDL_Rect view;\r\n\tSDL_RenderGetViewport(renderer, &view);\r\n\t*x += view.x;\r\n\t*y += view.y;\r\n\r\n\tfloat scaleX;\r\n\tSDL_RenderGetScale(renderer, &scaleX, nullptr);\r\n\tfloat scaleDpi = GetDpiScalingFactor();\r\n\tfloat scale = scaleX / scaleDpi;\r\n\t*x = static_cast<T>(*x * scale);\r\n\t*y = static_cast<T>(*y * scale);\r\n#else\r\n\tif (!OutputRequiresScaling())\r\n\t\treturn;\r\n\tconst SDL_Surface *surface = GetOutputSurface();\r\n\t*x = *x * surface->w / gnScreenWidth;\r\n\t*y = *y * surface->h / gnScreenHeight;\r\n#endif\r\n}\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nSDL_DisplayMode GetNearestDisplayMode(Size preferredSize,\r\n#ifdef USE_SDL3\r\n    SDL_PixelFormat preferredPixelFormat = SDL_PIXELFORMAT_UNKNOWN\r\n#else\r\n    SDL_PixelFormatEnum preferredPixelFormat = SDL_PIXELFORMAT_UNKNOWN\r\n#endif\r\n);\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/endian_read.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename T>\r\nconstexpr uint16_t LoadLE16(const T *b)\r\n{\r\n\tstatic_assert(sizeof(T) == 1, \"invalid argument\");\r\n\t// NOLINTNEXTLINE(readability-magic-numbers)\r\n\treturn (static_cast<uint8_t>(b[1]) << 8) | static_cast<uint8_t>(b[0]);\r\n}\r\n\r\ntemplate <typename T>\r\nconstexpr uint16_t LoadBE16(const T *b)\r\n{\r\n\tstatic_assert(sizeof(T) == 1, \"invalid argument\");\r\n\t// NOLINTNEXTLINE(readability-magic-numbers)\r\n\treturn (static_cast<uint8_t>(b[0]) << 8) | static_cast<uint8_t>(b[1]);\r\n}\r\n\r\ntemplate <typename T>\r\nconstexpr uint32_t LoadLE32(const T *b)\r\n{\r\n\tstatic_assert(sizeof(T) == 1, \"invalid argument\");\r\n\t// NOLINTNEXTLINE(readability-magic-numbers)\r\n\treturn (static_cast<uint8_t>(b[3]) << 24) | (static_cast<uint8_t>(b[2]) << 16) | (static_cast<uint8_t>(b[1]) << 8) | static_cast<uint8_t>(b[0]);\r\n}\r\n\r\ntemplate <typename T>\r\nconstexpr uint32_t LoadBE32(const T *b)\r\n{\r\n\tstatic_assert(sizeof(T) == 1, \"invalid argument\");\r\n\t// NOLINTNEXTLINE(readability-magic-numbers)\r\n\treturn (static_cast<uint8_t>(b[0]) << 24) | (static_cast<uint8_t>(b[1]) << 16) | (static_cast<uint8_t>(b[2]) << 8) | static_cast<uint8_t>(b[3]);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/endian_stream.hpp",
    "content": "#pragma once\r\n\r\n#include <cerrno>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <cstring>\r\n\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n#include \"utils/log.hpp\"\r\n\r\nnamespace devilution {\r\n\r\ninline void LoggedFread(void *buffer, size_t size, FILE *stream)\r\n{\r\n\tif (std::fread(buffer, size, 1, stream) != 1 && !std::feof(stream)) {\r\n\t\tLogError(\"fread failed: {}\", std::strerror(errno));\r\n\t}\r\n}\r\n\r\ninline void LoggedFwrite(const void *buffer, size_t size, FILE *stream)\r\n{\r\n\tif (std::fwrite(buffer, size, 1, stream) != 1) {\r\n\t\tLogError(\"fwrite failed: {}\", std::strerror(errno));\r\n\t}\r\n}\r\n\r\ntemplate <typename T = uint8_t>\r\nT ReadByte(FILE *stream)\r\n{\r\n\tstatic_assert(sizeof(T) == 1, \"invalid argument\");\r\n\tchar buf;\r\n\tLoggedFread(&buf, sizeof(buf), stream);\r\n\treturn static_cast<T>(buf);\r\n}\r\n\r\ntemplate <typename T = uint16_t>\r\nT ReadLE16(FILE *stream)\r\n{\r\n\tstatic_assert(sizeof(T) == 2, \"invalid argument\");\r\n\tchar buf[2];\r\n\tLoggedFread(&buf, sizeof(buf), stream);\r\n\treturn static_cast<T>(LoadLE16(buf));\r\n}\r\n\r\ntemplate <typename T = uint32_t>\r\nT ReadLE32(FILE *stream)\r\n{\r\n\tstatic_assert(sizeof(T) == 4, \"invalid argument\");\r\n\tchar buf[4];\r\n\tLoggedFread(&buf, sizeof(buf), stream);\r\n\treturn static_cast<T>(LoadLE32(buf));\r\n}\r\n\r\ninline float ReadLEFloat(FILE *stream)\r\n{\r\n\tstatic_assert(sizeof(float) == sizeof(uint32_t), \"invalid float size\");\r\n\tconst uint32_t val = ReadLE32(stream);\r\n\tfloat result;\r\n\tmemcpy(&result, &val, sizeof(float));\r\n\treturn result;\r\n}\r\n\r\ninline void WriteByte(FILE *out, uint8_t val)\r\n{\r\n\tLoggedFwrite(&val, sizeof(val), out);\r\n}\r\n\r\ninline void WriteLE16(FILE *out, uint16_t val)\r\n{\r\n\tchar data[2];\r\n\tWriteLE16(data, val);\r\n\tLoggedFwrite(data, sizeof(data), out);\r\n}\r\n\r\ninline void WriteLE32(FILE *out, uint32_t val)\r\n{\r\n\tchar data[4];\r\n\tWriteLE32(data, val);\r\n\tLoggedFwrite(data, sizeof(data), out);\r\n}\r\n\r\ninline void WriteLEFloat(FILE *out, float val)\r\n{\r\n\tstatic_assert(sizeof(float) == sizeof(uint32_t), \"invalid float size\");\r\n\tuint32_t intVal;\r\n\tmemcpy(&intVal, &val, sizeof(uint32_t));\r\n\tchar data[4];\r\n\tWriteLE32(data, intVal);\r\n\tLoggedFwrite(data, sizeof(data), out);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/endian_swap.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_endian.h>\r\n#else\r\n#include <SDL_endian.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\ninline uint16_t Swap16LE(uint16_t val)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDL_Swap16LE(val);\r\n#else\r\n\treturn SDL_SwapLE16(val);\r\n#endif\r\n}\r\n\r\ninline uint16_t Swap16BE(uint16_t val)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDL_Swap16BE(val);\r\n#else\r\n\treturn SDL_SwapBE16(val);\r\n#endif\r\n}\r\n\r\ninline uint32_t Swap32LE(uint32_t val)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDL_Swap32LE(val);\r\n#else\r\n\treturn SDL_SwapLE32(val);\r\n#endif\r\n}\r\n\r\ninline int32_t SwapSigned32LE(int32_t val)\r\n{\r\n\treturn static_cast<int32_t>(Swap32LE(static_cast<uint32_t>(val)));\r\n}\r\n\r\ninline uint32_t Swap32BE(uint32_t val)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDL_Swap32BE(val);\r\n#else\r\n\treturn SDL_SwapBE32(val);\r\n#endif\r\n}\r\n\r\ninline uint64_t Swap64LE(uint64_t val)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDL_Swap64LE(val);\r\n#else\r\n\treturn SDL_SwapLE64(val);\r\n#endif\r\n}\r\n\r\ninline uint64_t Swap64BE(uint64_t val)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDL_Swap64BE(val);\r\n#else\r\n\treturn SDL_SwapBE64(val);\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/endian_write.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include \"utils/endian_swap.hpp\"\r\n\r\nnamespace devilution {\r\n\r\ninline void WriteLE16(void *out, uint16_t val)\r\n{\r\n\tconst uint16_t littleEndian = Swap16LE(val);\r\n\tmemcpy(out, &littleEndian, 2);\r\n}\r\n\r\ninline void WriteLE32(void *out, uint32_t val)\r\n{\r\n\tconst uint32_t littleEndian = Swap32LE(val);\r\n\tmemcpy(out, &littleEndian, 4);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/enum_traits.h",
    "content": "/**\r\n * @file enum_traits.h\r\n *\r\n * Base template for 'enum_traits' which allow us to access static information about an enum.\r\n */\r\n#pragma once\r\n\r\n#include <cstddef>\r\n#include <type_traits>\r\n\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename T>\r\nstruct enum_size {\r\n\tconstexpr static const std::size_t value = static_cast<std::size_t>(T::LAST) + 1;\r\n};\r\n\r\ntemplate <typename T>\r\nclass enum_values {\r\npublic:\r\n\tclass Iterator {\r\n\t\ttypename std::underlying_type<T>::type m_value;\r\n\r\n\tpublic:\r\n\t\tIterator(typename std::underlying_type<T>::type value)\r\n\t\t    : m_value(value)\r\n\t\t{\r\n\t\t}\r\n\r\n\t\t[[nodiscard]] DVL_ALWAYS_INLINE const T operator*() const\r\n\t\t{\r\n\t\t\treturn static_cast<T>(m_value);\r\n\t\t}\r\n\r\n\t\tDVL_ALWAYS_INLINE void operator++()\r\n\t\t{\r\n\t\t\tm_value++;\r\n\t\t}\r\n\r\n\t\t[[nodiscard]] DVL_ALWAYS_INLINE bool operator!=(Iterator rhs) const\r\n\t\t{\r\n\t\t\treturn m_value != rhs.m_value;\r\n\t\t}\r\n\t};\r\n};\r\n\r\ntemplate <typename T>\r\n[[nodiscard]] DVL_ALWAYS_INLINE typename enum_values<T>::Iterator begin(enum_values<T>)\r\n{\r\n\treturn typename enum_values<T>::Iterator(static_cast<typename std::underlying_type<T>::type>(T::FIRST));\r\n}\r\n\r\ntemplate <typename T>\r\n[[nodiscard]] DVL_ALWAYS_INLINE typename enum_values<T>::Iterator end(enum_values<T>)\r\n{\r\n\treturn typename enum_values<T>::Iterator(static_cast<typename std::underlying_type<T>::type>(T::LAST) + 1);\r\n}\r\n\r\ntemplate <typename>\r\nstruct is_flags_enum : std::false_type {\r\n};\r\n\r\n#define use_enum_as_flags(Type)                   \\\r\n\ttemplate <>                                   \\\r\n\tstruct is_flags_enum<Type> : std::true_type { \\\r\n\t};\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\n[[nodiscard]] DVL_ALWAYS_INLINE constexpr EnumType operator|(EnumType lhs, EnumType rhs)\r\n{\r\n\tusing T = std::underlying_type_t<EnumType>;\r\n\treturn static_cast<EnumType>(static_cast<T>(lhs) | static_cast<T>(rhs));\r\n}\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\nDVL_ALWAYS_INLINE constexpr EnumType operator|=(EnumType &lhs, EnumType rhs)\r\n{\r\n\tlhs = lhs | rhs;\r\n\treturn lhs;\r\n}\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\n[[nodiscard]] DVL_ALWAYS_INLINE constexpr EnumType operator&(EnumType lhs, EnumType rhs)\r\n{\r\n\tusing T = std::underlying_type_t<EnumType>;\r\n\treturn static_cast<EnumType>(static_cast<T>(lhs) & static_cast<T>(rhs));\r\n}\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\nDVL_ALWAYS_INLINE constexpr EnumType operator&=(EnumType &lhs, EnumType rhs)\r\n{\r\n\tlhs = lhs & rhs;\r\n\treturn lhs;\r\n}\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\n[[nodiscard]] DVL_ALWAYS_INLINE constexpr EnumType operator~(EnumType value)\r\n{\r\n\tusing T = std::underlying_type_t<EnumType>;\r\n\treturn static_cast<EnumType>(~static_cast<T>(value));\r\n}\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\n[[nodiscard]] DVL_ALWAYS_INLINE constexpr bool HasAnyOf(EnumType lhs, EnumType test)\r\n{\r\n\treturn (lhs & test) != static_cast<EnumType>(0); // Some flags enums may not use a None value outside this check so we don't require an EnumType::None definition here.\r\n}\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\n[[nodiscard]] DVL_ALWAYS_INLINE constexpr bool HasAllOf(EnumType lhs, EnumType test)\r\n{\r\n\treturn (lhs & test) == test;\r\n}\r\n\r\ntemplate <typename EnumType, std::enable_if_t<std::is_enum<EnumType>::value && is_flags_enum<EnumType>::value, bool> = true>\r\n[[nodiscard]] DVL_ALWAYS_INLINE constexpr bool HasNoneOf(EnumType lhs, EnumType test)\r\n{\r\n\treturn !HasAnyOf(lhs, test);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/file_name_generator.hpp",
    "content": "#pragma once\r\n\r\n#include <cstring>\r\n#include <initializer_list>\r\n#include <string_view>\r\n\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nclass BaseFileNameGenerator {\r\npublic:\r\n\tBaseFileNameGenerator(std::initializer_list<std::string_view> prefixes, std::string_view suffix)\r\n\t    : suffix_(suffix)\r\n\t    , prefixEnd_(Append(buf_, prefixes))\r\n\t{\r\n\t}\r\n\r\n\tconst char *operator()() const\r\n\t{\r\n\t\t*BufCopy(prefixEnd_, suffix_) = '\\0';\r\n\t\treturn buf_;\r\n\t}\r\n\r\nprotected:\r\n\tstatic char *Append(char *buf, std::initializer_list<std::string_view> strings)\r\n\t{\r\n\t\tfor (std::string_view str : strings)\r\n\t\t\tbuf = BufCopy(buf, str);\r\n\t\treturn buf;\r\n\t}\r\n\r\n\t[[nodiscard]] std::string_view Suffix() const\r\n\t{\r\n\t\treturn suffix_;\r\n\t}\r\n\t[[nodiscard]] char *PrefixEnd() const\r\n\t{\r\n\t\treturn prefixEnd_;\r\n\t}\r\n\t[[nodiscard]] const char *Buffer() const\r\n\t{\r\n\t\treturn buf_;\r\n\t}\r\n\r\nprivate:\r\n\tstd::string_view suffix_;\r\n\tchar *prefixEnd_;\r\n\tchar buf_[256];\r\n};\r\n\r\n/**\r\n * @brief Generates file names from prefixes, a suffix, and an index.\r\n *\r\n *     FileNameGenerator f({\"a/\", \"b\"}, \".txt\", 1);\r\n *     f()  // \"a/b.txt\"\r\n *     f(0) // \"a/b1.txt\"\r\n *     f(1) // \"a/b2.txt\"\r\n */\r\nclass FileNameGenerator : public BaseFileNameGenerator {\r\npublic:\r\n\tFileNameGenerator(std::initializer_list<std::string_view> prefixes, std::string_view suffix, unsigned min = 1)\r\n\t    : BaseFileNameGenerator(prefixes, suffix)\r\n\t    , min_(min)\r\n\t{\r\n\t}\r\n\r\n\tusing BaseFileNameGenerator::operator();\r\n\r\n\tconst char *operator()(size_t i) const\r\n\t{\r\n\t\t*BufCopy(PrefixEnd(), static_cast<unsigned>(min_ + i), Suffix()) = '\\0';\r\n\t\treturn Buffer();\r\n\t}\r\n\r\nprivate:\r\n\tunsigned min_;\r\n};\r\n\r\n/**\r\n * @brief Generates file names from prefixes, a suffix, a char array and an index into it.\r\n *\r\n *     FileNameWithCharAffixGenerator f({\"a/\", \"b\"}, \".txt\", \"ABC\");\r\n *     f(0) // \"a/bA.txt\"\r\n *     f(1) // \"a/bB.txt\"\r\n */\r\nclass FileNameWithCharAffixGenerator : public BaseFileNameGenerator {\r\npublic:\r\n\tFileNameWithCharAffixGenerator(std::initializer_list<std::string_view> prefixes, std::string_view suffix, const char *chars)\r\n\t    : BaseFileNameGenerator(prefixes, suffix)\r\n\t    , chars_(chars)\r\n\t{\r\n\t\t*BufCopy(PrefixEnd() + 1, Suffix()) = '\\0';\r\n\t}\r\n\r\n\tconst char *operator()(size_t i) const\r\n\t{\r\n\t\tPrefixEnd()[0] = chars_[i];\r\n\t\treturn Buffer();\r\n\t}\r\n\r\nprivate:\r\n\tconst char *chars_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/file_util.cpp",
    "content": "#include \"utils/file_util.h\"\r\n\r\n#include <algorithm>\r\n#include <cerrno>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <limits>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl_compat.h\"\r\n#endif\r\n\r\n#include \"utils/log.hpp\"\r\n#include \"utils/stdcompat/filesystem.hpp\"\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n\r\n#ifdef _WIN32\r\n#include <memory>\r\n\r\n// Suppress definitions of `min` and `max` macros by <windows.h>:\r\n#define NOMINMAX 1\r\n#define WIN32_LEAN_AND_MEAN\r\n#include <windows.h>\r\n\r\n#ifndef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n#include <shlwapi.h>\r\n#endif\r\n#endif\r\n\r\n#if _POSIX_C_SOURCE >= 200112L || defined(_BSD_SOURCE) || defined(__APPLE__) || defined(__DJGPP__)\r\n#define DVL_HAS_POSIX_2001\r\n#endif\r\n\r\n#if defined(DVL_HAS_POSIX_2001) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n#include <sys/stat.h>\r\n#include <unistd.h>\r\n\r\n#ifndef DVL_HAS_FILESYSTEM\r\n#include <dirent.h>\r\n#endif\r\n#endif\r\n\r\n#if defined(__APPLE__) && DARWIN_MAJOR_VERSION >= 9\r\n#include <copyfile.h>\r\n#endif\r\n\r\n// We include sys/stat.h for mkdir where available.\r\n#if !defined(DVL_HAS_FILESYSTEM) && defined(__has_include) && !defined(_WIN32)\r\n#if __has_include(<sys/stat.h>)\r\n#include <sys/stat.h>\r\n#endif\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\nstd::unique_ptr<wchar_t[]> ToWideChar(std::string_view path)\r\n{\r\n\tconstexpr std::uint32_t flags = MB_ERR_INVALID_CHARS;\r\n\tconst int utf16Size = ::MultiByteToWideChar(CP_UTF8, flags, path.data(), static_cast<int>(path.size()), nullptr, 0);\r\n\tif (utf16Size == 0)\r\n\t\treturn nullptr;\r\n\tstd::unique_ptr<wchar_t[]> utf16 { new wchar_t[utf16Size + 1] };\r\n\tif (::MultiByteToWideChar(CP_UTF8, flags, path.data(), static_cast<int>(path.size()), &utf16[0], utf16Size) != utf16Size)\r\n\t\treturn nullptr;\r\n\tutf16[utf16Size] = L'\\0';\r\n\treturn utf16;\r\n}\r\n#endif\r\n\r\nstd::string_view Dirname(std::string_view path)\r\n{\r\n\twhile (path.size() > 1 && path.back() == DirectorySeparator)\r\n\t\tpath.remove_suffix(1);\r\n\tif (path.size() == 1 && path.back() == DirectorySeparator)\r\n\t\treturn DIRECTORY_SEPARATOR_STR;\r\n\tconst size_t sep = path.find_last_of(DIRECTORY_SEPARATOR_STR);\r\n\tif (sep == std::string_view::npos)\r\n\t\treturn \".\";\r\n\treturn std::string_view { path.data(), sep };\r\n}\r\n\r\nbool FileExists(const char *path)\r\n{\r\n#ifdef _WIN32\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\tconst bool exists = ::GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;\r\n#else\r\n\tconst auto pathUtf16 = ToWideChar(path);\r\n\tif (pathUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn false;\r\n\t}\r\n\tconst bool exists = ::PathFileExistsW(&pathUtf16[0]);\r\n#endif\r\n\tif (!exists) {\r\n\t\tif (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) {\r\n\t\t\t::SetLastError(ERROR_SUCCESS);\r\n\t\t} else {\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\t\t\tLogError(\"GetFileAttributesA({}): error code {}\", path, ::GetLastError());\r\n#else\r\n\t\t\tLogError(\"PathFileExistsW({}): error code {}\", path, ::GetLastError());\r\n#endif\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n#elif defined(DVL_HAS_POSIX_2001) && !defined(__ANDROID__)\r\n\treturn ::access(path, F_OK) == 0;\r\n#elif defined(DVL_HAS_FILESYSTEM)\r\n\tstd::error_code ec;\r\n\treturn std::filesystem::exists(reinterpret_cast<const char8_t *>(path), ec);\r\n#else\r\n\tSDL_IOStream *file = SDL_IOFromFile(path, \"rb\");\r\n\tif (file == nullptr) return false;\r\n\tSDL_CloseIO(file);\r\n\treturn true;\r\n#endif\r\n}\r\n\r\n#ifdef _WIN32\r\nnamespace {\r\nDWORD WindowsGetFileAttributes(const char *path)\r\n{\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\tconst DWORD attr = ::GetFileAttributesA(path);\r\n#else\r\n\tconst auto pathUtf16 = ToWideChar(path);\r\n\tif (pathUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn false;\r\n\t}\r\n\tconst DWORD attr = ::GetFileAttributesW(&pathUtf16[0]);\r\n#endif\r\n\tif (attr == INVALID_FILE_ATTRIBUTES) {\r\n\t\tif (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) {\r\n\t\t\t::SetLastError(ERROR_SUCCESS);\r\n\t\t} else {\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\t\t\tLogError(\"GetFileAttributesA: error code {}\", ::GetLastError());\r\n#else\r\n\t\t\tLogError(\"GetFileAttributesW: error code {}\", ::GetLastError());\r\n#endif\r\n\t\t}\r\n\t}\r\n\treturn attr;\r\n}\r\n} // namespace\r\n\r\n#endif\r\n\r\nbool DirectoryExists(const char *path)\r\n{\r\n#ifdef _WIN32\r\n\tconst DWORD attr = WindowsGetFileAttributes(path);\r\n\treturn attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;\r\n#elif defined(DVL_HAS_FILESYSTEM)\r\n\tstd::error_code error;\r\n\treturn std::filesystem::is_directory(reinterpret_cast<const char8_t *>(path), error);\r\n#elif (_POSIX_C_SOURCE >= 200112L || defined(_BSD_SOURCE) || defined(__APPLE__)) && !defined(__ANDROID__)\r\n\tstruct ::stat statResult;\r\n\treturn ::stat(path, &statResult) == 0 && S_ISDIR(statResult.st_mode);\r\n#endif\r\n}\r\n\r\nbool FileExistsAndIsWriteable(const char *path)\r\n{\r\n#ifdef _WIN32\r\n\tconst DWORD attr = WindowsGetFileAttributes(path);\r\n\treturn attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY) == 0;\r\n#elif defined(DVL_HAS_POSIX_2001) && !defined(__ANDROID__)\r\n\treturn ::access(path, W_OK) == 0;\r\n#else\r\n\tif (!FileExists(path))\r\n\t\treturn false;\r\n\tSDL_IOStream *file = SDL_IOFromFile(path, \"ab\");\r\n\tif (file == nullptr) return false;\r\n\tSDL_CloseIO(file);\r\n\treturn true;\r\n#endif\r\n}\r\n\r\nbool GetFileSize(const char *path, std::uintmax_t *size)\r\n{\r\n#ifdef _WIN32\r\n#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)\r\n\tHANDLE handle = ::CreateFileA(path, GENERIC_READ,\r\n\t    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,\r\n\t    FILE_ATTRIBUTE_NORMAL, NULL);\r\n\tif (handle == INVALID_HANDLE_VALUE) {\r\n\t\tLogError(\"File not found: {}\", GetLastError());\r\n\t\treturn false;\r\n\t}\r\n\tDWORD fileSizeHigh;\r\n\tconst DWORD fileSizeLow = ::GetFileSize(handle, &fileSizeHigh);\r\n\tif (fileSizeLow == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {\r\n\t\tLogError(\"GetFileSize failed for {}: {}\", path, GetLastError());\r\n\t\t::CloseHandle(handle);\r\n\t\treturn false;\r\n\t}\r\n\t*size = (static_cast<uintmax_t>(fileSizeHigh) << 32) | fileSizeLow;\r\n\t::CloseHandle(handle);\r\n\treturn true;\r\n#else\r\n\tWIN32_FILE_ATTRIBUTE_DATA attr;\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\tif (!GetFileAttributesExA(path, GetFileExInfoStandard, &attr)) {\r\n\t\treturn false;\r\n\t}\r\n#else\r\n\tconst auto pathUtf16 = ToWideChar(path);\r\n\tif (pathUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn false;\r\n\t}\r\n\tif (!GetFileAttributesExW(&pathUtf16[0], GetFileExInfoStandard, &attr)) {\r\n\t\treturn false;\r\n\t}\r\n#endif\r\n\t// C4293 in msvc when shifting a 32 bit type by 32 bits.\r\n\t*size = static_cast<std::uintmax_t>(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow;\r\n\treturn true;\r\n#endif\r\n#else\r\n\tstruct ::stat statResult;\r\n\tif (::stat(path, &statResult) == -1)\r\n\t\treturn false;\r\n\t*size = static_cast<uintmax_t>(statResult.st_size);\r\n\treturn true;\r\n#endif\r\n}\r\n\r\nbool CreateDir(const char *path)\r\n{\r\n#ifdef DVL_HAS_FILESYSTEM\r\n\tstd::error_code error;\r\n\tstd::filesystem::create_directory(reinterpret_cast<const char8_t *>(path), error);\r\n\tif (error) {\r\n\t\tLogError(\"failed to create directory {}: {}\", path, error.message());\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n#elif defined(_WIN32)\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\tif (::CreateDirectoryA(path, /*lpSecurityAttributes=*/nullptr) != 0)\r\n\t\treturn true;\r\n\tif (::GetLastError() == ERROR_ALREADY_EXISTS)\r\n\t\treturn true;\r\n\tLogError(\"failed to create directory {}\", path);\r\n\treturn false;\r\n#else\r\n\tconst auto pathUtf16 = ToWideChar(path);\r\n\tif (pathUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn false;\r\n\t}\r\n\tif (::CreateDirectoryW(&pathUtf16[0], /*lpSecurityAttributes=*/nullptr) != 0)\r\n\t\treturn true;\r\n\tif (::GetLastError() == ERROR_ALREADY_EXISTS)\r\n\t\treturn true;\r\n\tLogError(\"failed to create directory {}\", path);\r\n\treturn false;\r\n#endif\r\n#else\r\n\tconst int result = ::mkdir(path, 0777);\r\n\tif (result != 0 && result != EEXIST) {\r\n\t\tLogError(\"failed to create directory {}\", path);\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n#endif\r\n}\r\n\r\nvoid RecursivelyCreateDir(const char *path)\r\n{\r\n#ifdef DVL_HAS_FILESYSTEM\r\n\tstd::error_code error;\r\n\tstd::filesystem::create_directories(reinterpret_cast<const char8_t *>(path), error);\r\n\tif (error) {\r\n\t\tLogError(\"failed to create directory {}: {}\", path, error.message());\r\n\t}\r\n#else\r\n\tif (DirectoryExists(path))\r\n\t\treturn;\r\n\tstd::vector<std::string> paths;\r\n\tstd::string cur { path };\r\n\tdo {\r\n\t\tpaths.push_back(cur);\r\n\t\tstd::string_view parent = Dirname(cur);\r\n\t\tif (parent == cur)\r\n\t\t\tbreak;\r\n\t\tcur.assign(parent.data(), parent.size());\r\n\t} while (!DirectoryExists(cur.c_str()));\r\n\tfor (auto it = std::rbegin(paths); it != std::rend(paths); ++it) {\r\n\t\tif (!CreateDir(it->c_str()))\r\n\t\t\treturn;\r\n\t}\r\n#endif\r\n}\r\n\r\nbool ResizeFile(const char *path, std::uintmax_t size)\r\n{\r\n#ifdef _WIN32\r\n#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)\r\n\tif (size > std::numeric_limits<LONG>::max()) {\r\n\t\treturn false;\r\n\t}\r\n\tauto lisize = static_cast<LONG>(size);\r\n#else\r\n\tLARGE_INTEGER lisize;\r\n\tlisize.QuadPart = static_cast<LONGLONG>(size);\r\n\tif (lisize.QuadPart < 0) {\r\n\t\treturn false;\r\n\t}\r\n#endif\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\tHANDLE file = ::CreateFileA(path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);\r\n\tif (file == INVALID_HANDLE_VALUE) {\r\n\t\tLogError(\"CreateFileA({}) failed: {}\", path, ::GetLastError());\r\n\t\treturn false;\r\n\t}\r\n#else\r\n\tconst auto pathUtf16 = ToWideChar(path);\r\n\tif (pathUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn false;\r\n\t}\r\n\tHANDLE file = ::CreateFileW(&pathUtf16[0], GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);\r\n\tif (file == INVALID_HANDLE_VALUE) {\r\n\t\tLogError(\"CreateFileW({}) failed: {}\", path, ::GetLastError());\r\n\t\treturn false;\r\n\t}\r\n#endif\r\n#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)\r\n\tif (::SetFilePointer(file, lisize, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {\r\n\t\tLogError(\"SetFilePointer(file, {}, NULL, FILE_BEGIN) failed: {}\", lisize, ::GetLastError());\r\n\t\t::CloseHandle(file);\r\n\t\treturn false;\r\n\t}\r\n#else\r\n\tif (::SetFilePointerEx(file, lisize, NULL, FILE_BEGIN) == 0) {\r\n\t\tLogError(\"SetFilePointerEx(file, {}, NULL, FILE_BEGIN) failed: {}\", size, ::GetLastError());\r\n\t\t::CloseHandle(file);\r\n\t\treturn false;\r\n\t}\r\n#endif\r\n\tif (::SetEndOfFile(file) == 0) {\r\n\t\tLogError(\"SetEndOfFile failed: {}\", ::GetLastError());\r\n\t\t::CloseHandle(file);\r\n\t\treturn false;\r\n\t}\r\n\t::CloseHandle(file);\r\n\treturn true;\r\n#elif defined(DVL_HAS_POSIX_2001)\r\n\treturn ::truncate(path, static_cast<off_t>(size)) == 0;\r\n#else\r\n\tstatic_assert(false, \"truncate not implemented for the current platform\");\r\n#endif\r\n}\r\n\r\nvoid RenameFile(const char *from, const char *to)\r\n{\r\n#ifdef _WIN32\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\t::MoveFile(from, to);\r\n#else\r\n\tconst auto fromUtf16 = ToWideChar(from);\r\n\tconst auto toUtf16 = ToWideChar(to);\r\n\tif (fromUtf16 == nullptr || toUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn;\r\n\t}\r\n\t::MoveFileW(&fromUtf16[0], &toUtf16[0]);\r\n#endif // _WIN32\r\n#elif defined(DVL_HAS_FILESYSTEM)\r\n\tstd::error_code ec;\r\n\tstd::filesystem::rename(reinterpret_cast<const char8_t *>(from), reinterpret_cast<const char8_t *>(to), ec);\r\n#else\r\n\t::rename(from, to);\r\n#endif\r\n}\r\n\r\nvoid CopyFileOverwrite(const char *from, const char *to)\r\n{\r\n#ifdef _WIN32\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\tif (!::CopyFile(from, to, /*bFailIfExists=*/false)) {\r\n\t\tLogError(\"Failed to copy {} to {}\", from, to);\r\n\t}\r\n#else\r\n\tconst auto fromUtf16 = ToWideChar(from);\r\n\tconst auto toUtf16 = ToWideChar(to);\r\n\tif (fromUtf16 == nullptr || toUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn;\r\n\t}\r\n\tif (!::CopyFileW(&fromUtf16[0], &toUtf16[0], /*bFailIfExists=*/false)) {\r\n\t\tLogError(\"Failed to copy {} to {}\", from, to);\r\n\t}\r\n#endif // _WIN32\r\n#elif defined(__APPLE__) && DARWIN_MAJOR_VERSION >= 9\r\n\t::copyfile(from, to, nullptr, COPYFILE_ALL);\r\n#elif defined(DVL_HAS_FILESYSTEM)\r\n\tstd::error_code error;\r\n\tstd::filesystem::copy_file(reinterpret_cast<const char8_t *>(from), reinterpret_cast<const char8_t *>(to), std::filesystem::copy_options::overwrite_existing, error);\r\n\tif (error) {\r\n\t\tLogError(\"Failed to copy {} to {}: {}\", from, to, error.message());\r\n\t}\r\n#else\r\n\tFILE *infile = OpenFile(from, \"rb\");\r\n\tif (infile == nullptr) {\r\n\t\tLogError(\"Failed to open {} for reading: {}\", from, std::strerror(errno));\r\n\t\treturn;\r\n\t}\r\n\tFILE *outfile = OpenFile(to, \"wb\");\r\n\tif (outfile == nullptr) {\r\n\t\tLogError(\"Failed to open {} for writing: {}\", to, std::strerror(errno));\r\n\t\tstd::fclose(infile);\r\n\t\treturn;\r\n\t}\r\n\tchar buffer[4096];\r\n\tsize_t numRead;\r\n\twhile ((numRead = std::fread(buffer, sizeof(char), sizeof(buffer), infile)) > 0) {\r\n\t\tif (std::fwrite(buffer, sizeof(char), numRead, outfile) != numRead) {\r\n\t\t\tLogError(\"Write failed {}: {}\", to, std::strerror(errno));\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tstd::fclose(infile);\r\n\tstd::fclose(outfile);\r\n#endif\r\n}\r\n\r\nvoid RemoveFile(const char *path)\r\n{\r\n#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n\t::DeleteFileA(path);\r\n#elif defined(_WIN32)\r\n\tconst auto pathUtf16 = ToWideChar(path);\r\n\tif (pathUtf16 == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn;\r\n\t}\r\n\t::DeleteFileW(&pathUtf16[0]);\r\n#else\r\n\tstd::string name { path };\r\n\tstd::replace(name.begin(), name.end(), '\\\\', '/');\r\n\tFILE *f = fopen(name.c_str(), \"r+\");\r\n\tif (f != nullptr) {\r\n\t\tfclose(f);\r\n\t\tremove(name.c_str());\r\n\t\tf = nullptr;\r\n\t\tLogVerbose(\"Removed file: {}\", name);\r\n\t} else {\r\n\t\tLogVerbose(\"Failed to remove file: {}\", name);\r\n\t}\r\n#endif\r\n}\r\n\r\nFILE *OpenFile(const char *path, const char *mode)\r\n{\r\n#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n\tstd::unique_ptr<wchar_t[]> pathUtf16;\r\n\tstd::unique_ptr<wchar_t[]> modeUtf16;\r\n\tif ((pathUtf16 = ToWideChar(path)) == nullptr\r\n\t    || (modeUtf16 = ToWideChar(mode)) == nullptr) {\r\n\t\tLogError(\"UTF-8 -> UTF-16 conversion error code {}\", ::GetLastError());\r\n\t\treturn {};\r\n\t}\r\n\treturn _wfopen(pathUtf16.get(), modeUtf16.get());\r\n#else\r\n\treturn std::fopen(path, mode);\r\n#endif\r\n}\r\n\r\nstd::vector<std::string> ListDirectories(const char *path)\r\n{\r\n\tstd::vector<std::string> dirs;\r\n#ifdef DVL_HAS_FILESYSTEM\r\n\tstd::error_code ec;\r\n\tfor (const auto &entry : std::filesystem::directory_iterator(reinterpret_cast<const char8_t *>(path), ec)) {\r\n\t\tif (!entry.is_directory())\r\n\t\t\tcontinue;\r\n\t\tstd::u8string filename = entry.path().filename().u8string();\r\n\t\tdirs.emplace_back(filename.begin(), filename.end());\r\n\t}\r\n#elif defined(_WIN32)\r\n\tWIN32_FIND_DATAA findData;\r\n\t// Construct the search path by appending the directory separator and wildcard.\r\n\tstd::string searchPath = std::string(path) + DIRECTORY_SEPARATOR_STR + \"*\";\r\n\tHANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData);\r\n\tif (hFind == INVALID_HANDLE_VALUE)\r\n\t\treturn dirs;\r\n\tdo {\r\n\t\tstd::string folder = findData.cFileName;\r\n\t\t// Skip the special entries \".\" and \"..\"\r\n\t\tif (folder == \".\" || folder == \"..\")\r\n\t\t\tcontinue;\r\n\t\tif (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\r\n\t\t\tdirs.push_back(folder);\r\n\t} while (FindNextFileA(hFind, &findData));\r\n\tFindClose(hFind);\r\n#elif (_POSIX_C_SOURCE >= 200112L || defined(_BSD_SOURCE) || defined(__APPLE__))\r\n\tDIR *d = ::opendir(path);\r\n\tif (d != nullptr) {\r\n\t\tstruct dirent *dir;\r\n\t\twhile ((dir = ::readdir(d)) != nullptr) {\r\n\t\t\tif (dir->d_type != DT_DIR) continue;\r\n\t\t\tconst std::string_view name = dir->d_name;\r\n\t\t\tif (name == \".\" || name == \"..\") continue;\r\n\t\t\tdirs.emplace_back(name);\r\n\t\t}\r\n\t\t::closedir(d);\r\n\t}\r\n#else\r\n\tstatic_assert(false, \"ListDirectories not implemented for the current platform\");\r\n#endif\r\n\treturn dirs;\r\n}\r\n\r\nstd::vector<std::string> ListFiles(const char *path)\r\n{\r\n\tstd::vector<std::string> files;\r\n#ifdef DVL_HAS_FILESYSTEM\r\n\tstd::error_code ec;\r\n\tfor (const auto &entry : std::filesystem::directory_iterator(reinterpret_cast<const char8_t *>(path), ec)) {\r\n\t\tif (!entry.is_regular_file())\r\n\t\t\tcontinue;\r\n\t\tstd::u8string filename = entry.path().filename().u8string();\r\n\t\tfiles.emplace_back(filename.begin(), filename.end());\r\n\t}\r\n#elif defined(_WIN32)\r\n\tWIN32_FIND_DATAA findData;\r\n\t// Construct the search path by appending the directory separator and wildcard.\r\n\tstd::string searchPath = std::string(path) + DIRECTORY_SEPARATOR_STR + \"*\";\r\n\tHANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData);\r\n\tif (hFind == INVALID_HANDLE_VALUE)\r\n\t\treturn files;\r\n\tdo {\r\n\t\tstd::string file = findData.cFileName;\r\n\t\t// Skip the special entries \".\" and \"..\"\r\n\t\tif (file == \".\" || file == \"..\")\r\n\t\t\tcontinue;\r\n\t\tif (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))\r\n\t\t\tfiles.push_back(file);\r\n\t} while (FindNextFileA(hFind, &findData));\r\n\tFindClose(hFind);\r\n#elif (_POSIX_C_SOURCE >= 200112L || defined(_BSD_SOURCE) || defined(__APPLE__))\r\n\tDIR *d = ::opendir(path);\r\n\tif (d != nullptr) {\r\n\t\tstruct dirent *dir;\r\n\t\twhile ((dir = ::readdir(d)) != nullptr) {\r\n\t\t\tif (dir->d_type != DT_REG) continue;\r\n\t\t\tconst std::string_view name = dir->d_name;\r\n\t\t\tif (name == \".\" || name == \"..\") continue;\r\n\t\t\tfiles.emplace_back(name);\r\n\t\t}\r\n\t\t::closedir(d);\r\n\t}\r\n#else\r\n\tstatic_assert(false, \"ListFiles not implemented for the current platform\");\r\n#endif\r\n\treturn files;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/file_util.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <memory>\r\n#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\nnamespace devilution {\r\n\r\n#if defined(_WIN32) || defined(__DJGPP__)\r\nconstexpr char DirectorySeparator = '\\\\';\r\n#define DIRECTORY_SEPARATOR_STR \"\\\\\"\r\n#else\r\nconstexpr char DirectorySeparator = '/';\r\n#define DIRECTORY_SEPARATOR_STR \"/\"\r\n#endif\r\n\r\nbool FileExists(const char *path);\r\n\r\ninline bool FileExists(const std::string &str)\r\n{\r\n\treturn FileExists(str.c_str());\r\n}\r\n\r\nbool DirectoryExists(const char *path);\r\nstd::string_view Dirname(std::string_view path);\r\nbool FileExistsAndIsWriteable(const char *path);\r\nbool GetFileSize(const char *path, std::uintmax_t *size);\r\n\r\n/**\r\n * @brief Creates a single directory (non-recursively).\r\n *\r\n * @return True if the directory already existed or has been created successfully.\r\n */\r\nbool CreateDir(const char *path);\r\n\r\nvoid RecursivelyCreateDir(const char *path);\r\nbool ResizeFile(const char *path, std::uintmax_t size);\r\nvoid RenameFile(const char *from, const char *to);\r\nvoid CopyFileOverwrite(const char *from, const char *to);\r\nvoid RemoveFile(const char *path);\r\nFILE *OpenFile(const char *path, const char *mode);\r\n\r\n#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\nstd::unique_ptr<wchar_t[]> ToWideChar(std::string_view path);\r\n#endif\r\n\r\nstd::vector<std::string> ListDirectories(const char *path);\r\nstd::vector<std::string> ListFiles(const char *path);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/format_int.cpp",
    "content": "#include \"utils/format_int.hpp\"\r\n\r\n#include <cstdint>\r\n#include <string_view>\r\n\r\n#include \"utils/language.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nstd::string FormatInteger(int n)\r\n{\r\n\tconstexpr size_t GroupSize = 3;\r\n\r\n\tchar buf[40];\r\n\tchar *begin = buf;\r\n\tconst char *end = BufCopy(buf, n);\r\n\tconst size_t len = end - begin;\r\n\r\n\tstd::string out;\r\n\tconst size_t prefixLen = n < 0 ? 1 : 0;\r\n\tconst size_t numLen = len - prefixLen;\r\n\tif (numLen <= GroupSize) {\r\n\t\tout.append(begin, len);\r\n\t\treturn out;\r\n\t}\r\n\r\n\tconst std::string_view separator = _(/* TRANSLATORS: Thousands separator */ \",\");\r\n\tout.reserve(len + separator.size() * (numLen - 1) / GroupSize);\r\n\tif (n < 0) {\r\n\t\tout += '-';\r\n\t\t++begin;\r\n\t}\r\n\r\n\tsize_t mlen = numLen % GroupSize;\r\n\tif (mlen == 0)\r\n\t\tmlen = GroupSize;\r\n\tout.append(begin, mlen);\r\n\tbegin += mlen;\r\n\tfor (; begin != end; begin += GroupSize) {\r\n\t\tout.append(separator);\r\n\t\tout.append(begin, GroupSize);\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nstd::string FormatInteger(uint32_t n)\r\n{\r\n\tconstexpr size_t GroupSize = 3;\r\n\r\n\tchar buf[40];\r\n\tchar *begin = buf;\r\n\tconst char *end = BufCopy(buf, n);\r\n\tconst size_t len = end - begin;\r\n\r\n\tstd::string out;\r\n\tconst size_t numLen = len;\r\n\tif (numLen <= GroupSize) {\r\n\t\tout.append(begin, len);\r\n\t\treturn out;\r\n\t}\r\n\r\n\tconst std::string_view separator = _(/* TRANSLATORS: Thousands separator */ \",\");\r\n\tout.reserve(len + separator.size() * (numLen - 1) / GroupSize);\r\n\r\n\tsize_t mlen = numLen % GroupSize;\r\n\tif (mlen == 0)\r\n\t\tmlen = GroupSize;\r\n\tout.append(begin, mlen);\r\n\tbegin += mlen;\r\n\tfor (; begin != end; begin += GroupSize) {\r\n\t\tout.append(separator);\r\n\t\tout.append(begin, GroupSize);\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/format_int.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Formats integer with thousands separator.\r\n */\r\nstd::string FormatInteger(int n);\r\nstd::string FormatInteger(uint32_t n);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/hp_mana_units.hpp",
    "content": "#pragma once\n\nnamespace devilution {\n\nconstexpr int HpManaFracBits = 6;\nconstexpr int HpManaScale = 1 << HpManaFracBits;\n\nconstexpr int HpManaToFrac(int whole)\n{\n\treturn whole * HpManaScale;\n}\n\nconstexpr int HpManaToWhole(int frac)\n{\n\treturn frac / HpManaScale;\n}\n\nconstexpr int HpManaFromParts(int whole, int frac)\n{\n\treturn HpManaToFrac(whole) + frac;\n}\n\n} // namespace devilution\n"
  },
  {
    "path": "Source/utils/ini.cpp",
    "content": "#include \"utils/ini.hpp\"\r\n\r\n#include <algorithm>\r\n#include <charconv>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstdlib>\r\n#include <cstring>\r\n#include <span>\r\n#include <string>\r\n#include <string_view>\r\n#include <system_error>\r\n#include <utility>\r\n#include <variant>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n#include <fmt/core.h>\r\n\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/string_view_hash.hpp\"\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n// We avoid including the \"appfat.h\" to avoid depending on SDL in tests.\r\n[[noreturn]] extern void app_fatal(std::string_view str);\r\n\r\nnamespace {\r\n\r\ntemplate <typename T>\r\nbool OrderByValueIndex(const std::pair<std::string, T> &a, const std::pair<std::string, T> &b)\r\n{\r\n\treturn a.second.index < b.second.index;\r\n};\r\n\r\n// Returns a pointer to the first non-leading whitespace.\r\n// Only ' ' and '\\t' are considered whitespace.\r\n// Requires: begin <= end.\r\nconst char *SkipLeadingWhitespace(const char *begin, const char *end)\r\n{\r\n\twhile (begin != end && (*begin == ' ' || *begin == '\\t')) {\r\n\t\t++begin;\r\n\t}\r\n\treturn begin;\r\n}\r\n\r\n// Returns a pointer to the last non-whitespace.\r\n// Only ' ' and '\\t' are considered whitespace.\r\n// Requires: begin <= end.\r\nconst char *SkipTrailingWhitespace(const char *begin, const char *end)\r\n{\r\n\twhile (begin != end && (*(end - 1) == ' ' || *(end - 1) == '\\t')) {\r\n\t\t--end;\r\n\t}\r\n\treturn end;\r\n}\r\n\r\n// Skips UTF-8 byte order mark.\r\n// See https://en.wikipedia.org/wiki/Byte_order_mark\r\nconst char *SkipUtf8Bom(const char *begin, const char *end)\r\n{\r\n\tif (end - begin >= 3 && begin[0] == '\\xEF' && begin[1] == '\\xBB' && begin[2] == '\\xBF') {\r\n\t\treturn begin + 3;\r\n\t}\r\n\treturn begin;\r\n}\r\n\r\n} // namespace\r\n\r\nIni::Values::Values()\r\n    : rep_(std::vector<Value> {})\r\n{\r\n}\r\n\r\nIni::Values::Values(const Value &data)\r\n    : rep_(data)\r\n{\r\n}\r\n\r\nstd::vector<std::string> Ini::getKeys(std::string_view section) const\r\n{\r\n\tconst auto sectionIt = data_.sections.find(section);\r\n\tif (sectionIt == data_.sections.end()) return {};\r\n\r\n\tstd::vector<std::pair<std::string, ValuesData>> entries(sectionIt->second.entries.begin(), sectionIt->second.entries.end());\r\n\tc_sort(entries, OrderByValueIndex<ValuesData>);\r\n\r\n\tstd::vector<std::string> keys;\r\n\tkeys.reserve(entries.size());\r\n\tfor (const auto &[key, _] : entries) {\r\n\t\tkeys.push_back(key);\r\n\t}\r\n\treturn keys;\r\n}\r\n\r\nstd::span<const Ini::Value> Ini::Values::get() const\r\n{\r\n\tif (std::holds_alternative<Ini::Value>(rep_)) {\r\n\t\treturn { &std::get<Ini::Value>(rep_), 1 };\r\n\t}\r\n\treturn std::get<std::vector<Ini::Value>>(rep_);\r\n}\r\n\r\nstd::span<Ini::Value> Ini::Values::get()\r\n{\r\n\tif (std::holds_alternative<Ini::Value>(rep_)) {\r\n\t\treturn { &std::get<Ini::Value>(rep_), 1 };\r\n\t}\r\n\treturn std::get<std::vector<Ini::Value>>(rep_);\r\n}\r\n\r\nvoid Ini::Values::append(const Ini::Value &value)\r\n{\r\n\tif (std::holds_alternative<Value>(rep_)) {\r\n\t\trep_ = std::vector<Value> { std::get<Value>(rep_), value };\r\n\t\treturn;\r\n\t}\r\n\tstd::get<std::vector<Value>>(rep_).push_back(value);\r\n}\r\n\r\ntl::expected<Ini, std::string> Ini::parse(std::string_view buffer)\r\n{\r\n\tIni::FileData fileData;\r\n\tankerl::unordered_dense::map<std::string, ValuesData, StringViewHash, StringViewEquals> *sectionEntries = nullptr;\r\n\tconst char *eof = buffer.data() + buffer.size();\r\n\tconst char *lineBegin = SkipUtf8Bom(buffer.data(), eof);\r\n\tsize_t lineNum = 0;\r\n\r\n\tconst char *commentBegin = nullptr;\r\n\tconst char *nextLineBegin;\r\n\tfor (; lineBegin < eof; lineBegin = nextLineBegin) {\r\n\t\t++lineNum;\r\n\t\tconst char *lineEnd = static_cast<const char *>(memchr(lineBegin, '\\n', eof - lineBegin));\r\n\t\tif (lineEnd == nullptr) {\r\n\t\t\tlineEnd = eof;\r\n\t\t\tnextLineBegin = eof;\r\n\t\t} else {\r\n\t\t\tnextLineBegin = lineEnd + 1;\r\n\t\t\tif (lineBegin + 1 <= lineEnd && *(lineEnd - 1) == '\\r') --lineEnd;\r\n\t\t}\r\n\t\tconst char *keyBegin = SkipLeadingWhitespace(lineBegin, lineEnd);\r\n\t\tif (keyBegin == lineEnd) continue;\r\n\r\n\t\tif (*keyBegin == ';') {\r\n\t\t\tif (commentBegin == nullptr) commentBegin = lineBegin;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tstd::string_view comment;\r\n\t\tif (commentBegin != nullptr) {\r\n\t\t\tcomment = std::string_view(commentBegin, lineBegin - commentBegin);\r\n\t\t}\r\n\r\n\t\tif (*keyBegin == '[') {\r\n\t\t\tconst char *keyEnd = ++keyBegin;\r\n\t\t\twhile (keyEnd < lineEnd && *keyEnd != ']') {\r\n\t\t\t\t++keyEnd;\r\n\t\t\t}\r\n\t\t\tif (keyEnd == lineEnd) {\r\n\t\t\t\treturn tl::make_unexpected(fmt::format(\"line {}: unclosed section name {}\", lineNum, std::string_view(keyBegin, keyEnd - keyBegin)));\r\n\t\t\t}\r\n\t\t\tif (const char *after = SkipTrailingWhitespace(keyEnd + 1, lineEnd); after != lineEnd) {\r\n\t\t\t\treturn tl::make_unexpected(fmt::format(\"line {}: content after section [{}]: {}\", lineNum, std::string_view(keyBegin, keyEnd - keyBegin), std::string_view(after, lineEnd - after)));\r\n\t\t\t}\r\n\t\t\tconst std::string_view sectionName = std::string_view(keyBegin, keyEnd - keyBegin);\r\n\t\t\tauto it = fileData.sections.find(sectionName);\r\n\t\t\tif (it == fileData.sections.end()) {\r\n\t\t\t\tit = fileData.sections.emplace_hint(it, sectionName,\r\n\t\t\t\t    SectionData {\r\n\t\t\t\t        .comment = std::string(comment),\r\n\t\t\t\t        .entries = {},\r\n\t\t\t\t        .index = static_cast<uint32_t>(fileData.sections.size()),\r\n\t\t\t\t    });\r\n\t\t\t}\r\n\t\t\tsectionEntries = &it->second.entries;\r\n\t\t\tcommentBegin = nullptr;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tif (sectionEntries == nullptr) return tl::unexpected(fmt::format(\"line {}: key not in any section\", lineNum));\r\n\t\tconst char *eqPos = static_cast<const char *>(memchr(keyBegin, '=', lineEnd - keyBegin));\r\n\t\tif (eqPos == nullptr) {\r\n\t\t\treturn tl::make_unexpected(fmt::format(\"line {}: key {} has no value\", lineNum, std::string_view(keyBegin, lineEnd - keyBegin)));\r\n\t\t}\r\n\t\tconst char *keyEnd = SkipTrailingWhitespace(keyBegin, eqPos);\r\n\t\tconst std::string_view key = std::string_view(keyBegin, keyEnd - keyBegin);\r\n\t\tconst char *valueBegin = SkipLeadingWhitespace(eqPos + 1, lineEnd);\r\n\t\tconst std::string_view value = std::string_view(valueBegin, lineEnd - valueBegin);\r\n\t\tif (const auto it = sectionEntries->find(key); it != sectionEntries->end()) {\r\n\t\t\tit->second.values.append(Value { std::string(comment), std::string(value) });\r\n\t\t} else {\r\n\t\t\tsectionEntries->emplace_hint(it, key,\r\n\t\t\t    ValuesData {\r\n\t\t\t        .values = Values { Value {\r\n\t\t\t            .comment = std::string(comment),\r\n\t\t\t            .value = std::string(value),\r\n\t\t\t        } },\r\n\t\t\t        .index = static_cast<uint32_t>(sectionEntries->size()),\r\n\t\t\t    });\r\n\t\t}\r\n\t\tcommentBegin = nullptr;\r\n\t}\r\n\treturn Ini(std::move(fileData));\r\n}\r\n\r\nstd::span<const Ini::Value> Ini::get(std::string_view section, std::string_view key) const\r\n{\r\n\tconst auto sectionIt = data_.sections.find(section);\r\n\tif (sectionIt == data_.sections.end()) return {};\r\n\tconst auto it = sectionIt->second.entries.find(key);\r\n\tif (it == sectionIt->second.entries.end()) return {};\r\n\treturn it->second.values.get();\r\n}\r\n\r\nstd::string_view Ini::getString(std::string_view section, std::string_view key, std::string_view defaultValue) const\r\n{\r\n\tconst std::span<const Ini::Value> xs = get(section, key);\r\n\tif (xs.empty() || xs.back().value.empty()) return defaultValue;\r\n\treturn xs.back().value;\r\n}\r\n\r\nint Ini::getInt(std::string_view section, std::string_view key, int defaultValue) const\r\n{\r\n\tconst std::span<const Ini::Value> xs = get(section, key);\r\n\tif (xs.empty() || xs.back().value.empty()) return defaultValue;\r\n\tconst std::string_view str = xs.back().value;\r\n\tint value;\r\n\tconst std::from_chars_result result = std::from_chars(str.data(), str.data() + str.size(), value);\r\n\tif (result.ec != std::errc()) {\r\n\t\tapp_fatal(fmt::format(\"ini: Failed to parse {}.{}={} as int\", section, key, str));\r\n\t\treturn defaultValue;\r\n\t}\r\n\treturn value;\r\n}\r\n\r\nbool Ini::getBool(std::string_view section, std::string_view key, bool defaultValue) const\r\n{\r\n\tconst std::span<const Ini::Value> xs = get(section, key);\r\n\tif (xs.empty() || xs.back().value.empty()) return defaultValue;\r\n\tconst std::string_view str = xs.back().value;\r\n\tif (str == \"0\") return false;\r\n\tif (str == \"1\") return true;\r\n\tapp_fatal(fmt::format(\"ini: Failed to parse {}.{}={} as bool\", section, key, str));\r\n}\r\n\r\nfloat Ini::getFloat(std::string_view section, std::string_view key, float defaultValue) const\r\n{\r\n\tconst std::span<const Ini::Value> xs = get(section, key);\r\n\tif (xs.empty() || xs.back().value.empty()) return defaultValue;\r\n\tconst std::string &str = xs.back().value;\r\n\r\n#if __cpp_lib_to_chars >= 201611L\r\n\tfloat value;\r\n\tconst std::from_chars_result result = std::from_chars(str.data(), str.data() + str.size(), value);\r\n\tif (result.ec != std::errc()) {\r\n\t\tapp_fatal(fmt::format(\"ini: Failed to parse {}.{}={} as float\", section, key, str));\r\n\t\treturn defaultValue;\r\n\t}\r\n\treturn value;\r\n#else\r\n\treturn strtof(str.data(), nullptr);\r\n#endif\r\n}\r\n\r\nvoid Ini::getUtf8Buf(std::string_view section, std::string_view key, std::string_view defaultValue, char *dst, size_t dstSize) const\r\n{\r\n\tCopyUtf8(dst, getString(section, key, defaultValue), dstSize);\r\n}\r\n\r\nvoid Ini::set(std::string_view section, std::string_view key, Ini::Values &&values)\r\n{\r\n\tconst std::span<Value> updated = values.get();\r\n\r\n\tauto sectionIt = data_.sections.find(section);\r\n\tif (sectionIt == data_.sections.end()) {\r\n\t\t// Deleting a key from a non-existing section\r\n\t\tif (updated.empty()) return;\r\n\r\n\t\t// Adding a new section and key\r\n\t\tdata_.sections.emplace_hint(sectionIt, section,\r\n\t\t    SectionData {\r\n\t\t        .comment = {},\r\n\t\t        .entries = { { std::string(key), ValuesData { .values = std::move(values), .index = 0 } } },\r\n\t\t        .index = static_cast<uint32_t>(data_.sections.size()),\r\n\t\t    });\r\n\t\tchanged_ = true;\r\n\t\treturn;\r\n\t}\r\n\tconst auto it = sectionIt->second.entries.find(key);\r\n\tif (it == sectionIt->second.entries.end()) {\r\n\t\t// Deleting a non-existing key\r\n\t\tif (updated.empty()) return;\r\n\r\n\t\t// Adding a new key to an existing section\r\n\t\tsectionIt->second.entries.emplace(key,\r\n\t\t    ValuesData {\r\n\t\t        .values = std::move(values),\r\n\t\t        .index = static_cast<uint32_t>(sectionIt->second.entries.size()),\r\n\t\t    });\r\n\t\tchanged_ = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Deleting an existing key\r\n\tif (updated.empty()) {\r\n\t\tsectionIt->second.entries.erase(it);\r\n\t\tif (sectionIt->second.entries.empty()) data_.sections.erase(sectionIt);\r\n\t\tchanged_ = true;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Overriding an existing key\r\n\tconst std::span<Value> original = it->second.values.get();\r\n\tif (original.size() == updated.size()) {\r\n\t\tbool equal = true;\r\n\t\tfor (size_t i = 0; i < original.size(); ++i) {\r\n\t\t\tif (original[i].value != updated[i].value) {\r\n\t\t\t\tequal = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (equal) return;\r\n\t}\r\n\r\n\t// Preserve existing comments where not overriden.\r\n\tfor (size_t i = 0, n = std::min(original.size(), updated.size()); i < n; ++i) {\r\n\t\tif (!updated[i].comment.has_value() && original[i].comment.has_value()) {\r\n\t\t\tupdated[i].comment = std::move(original[i].comment);\r\n\t\t}\r\n\t}\r\n\tit->second.values = std::move(values);\r\n\tchanged_ = true;\r\n}\r\n\r\nvoid Ini::set(std::string_view section, std::string_view key, std::span<const std::string> strings)\r\n{\r\n\tif (strings.empty()) {\r\n\t\tset(section, key, Values {});\r\n\t} else if (strings.size() == 1) {\r\n\t\tset(section, key, Values { Value { .comment = {}, .value = strings[0] } });\r\n\t} else {\r\n\t\tValues values;\r\n\t\tauto &items = std::get<std::vector<Value>>(values.rep_);\r\n\t\titems.reserve(strings.size());\r\n\t\tfor (const std::string &str : strings) {\r\n\t\t\titems.push_back(Value { .comment = {}, .value = str });\r\n\t\t}\r\n\t\tset(section, key, std::move(values));\r\n\t}\r\n}\r\n\r\nvoid Ini::set(std::string_view section, std::string_view key, std::string &&value)\r\n{\r\n\tset(section, key, Values { Value { .comment = {}, .value = std::move(value) } });\r\n}\r\n\r\nvoid Ini::set(std::string_view section, std::string_view key, std::string_view value)\r\n{\r\n\r\n\tset(section, key, std::string(value));\r\n}\r\n\r\nvoid Ini::set(std::string_view section, std::string_view key, int value)\r\n{\r\n\tset(section, key, StrCat(value));\r\n}\r\n\r\nvoid Ini::set(std::string_view section, std::string_view key, bool value)\r\n{\r\n\tset(section, key, std::string(value ? \"1\" : \"0\"));\r\n}\r\n\r\nvoid Ini::set(std::string_view section, std::string_view key, float value)\r\n{\r\n#if __cpp_lib_to_chars >= 201611L\r\n\tconstexpr size_t BufSize = 64;\r\n\tchar buf[BufSize] {};\r\n\tconst std::to_chars_result result = std::to_chars(buf, buf + BufSize, value);\r\n\tif (result.ec != std::errc()) {\r\n\t\tapp_fatal(\"float->string failed\"); // should never happen\r\n\t}\r\n\tset(section, key, std::string_view(buf, result.ptr - buf));\r\n#else\r\n\tset(section, key, fmt::format(\"{}\", value));\r\n#endif\r\n}\r\n\r\nnamespace {\r\n\r\n// Appends a possibly multi-line comment, converting \\n to \\r\\n.\r\nvoid AppendComment(std::string_view comment, std::string &out)\r\n{\r\n\tbool prevR = false;\r\n\tfor (const char c : comment) {\r\n\t\tif (c == '\\r') {\r\n\t\t\tprevR = true;\r\n\t\t} else {\r\n\t\t\tif (c == '\\n' && !prevR) out += '\\r';\r\n\t\t\tprevR = false;\r\n\t\t}\r\n\t\tout += c;\r\n\t}\r\n}\r\n\r\nvoid AppendSection(std::string_view sectionName, std::string &out)\r\n{\r\n\tout.append(\"[\").append(sectionName).append(\"]\\r\\n\");\r\n}\r\n\r\nvoid AppendKeyValue(std::string_view key, std::string_view value, std::string &out)\r\n{\r\n\tout.append(key).append(\"=\").append(value).append(\"\\r\\n\");\r\n}\r\n\r\n} // namespace\r\n\r\nstd::string Ini::serialize() const\r\n{\r\n\tstd::string result;\r\n\tstd::vector<std::pair<std::string, SectionData>> sections(data_.sections.begin(), data_.sections.end());\r\n\tc_sort(sections, OrderByValueIndex<SectionData>);\r\n\r\n\tstd::vector<std::pair<std::string, ValuesData>> entries;\r\n\tfor (auto &[sectionName, section] : sections) {\r\n\t\tif (!result.empty()) result.append(\"\\r\\n\");\r\n\t\tif (!section.comment.empty()) AppendComment(section.comment, result);\r\n\t\tAppendSection(sectionName, result);\r\n\t\tentries.assign(section.entries.begin(), section.entries.end());\r\n\t\tc_sort(entries, OrderByValueIndex<ValuesData>);\r\n\t\tfor (const auto &[key, entry] : entries) {\r\n\t\t\tfor (const auto &[comment, value] : entry.values.get()) {\r\n\t\t\t\tif (comment.has_value() && !comment->empty()) AppendComment(*comment, result);\r\n\t\t\t\tAppendKeyValue(key, value, result);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn result;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/ini.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <optional>\r\n#include <span>\r\n#include <string>\r\n#include <string_view>\r\n#include <utility>\r\n#include <variant>\r\n#include <vector>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <expected.hpp>\r\n\r\n#include \"utils/string_view_hash.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nclass Ini {\r\npublic:\r\n\t// A single value associated with a section and key.\r\n\tstruct Value {\r\n\t\t// When setting a value, `nullopt` results\r\n\t\t// in preserving the existing comment if any.\r\n\t\tstd::optional<std::string> comment;\r\n\t\tstd::string value;\r\n\t};\r\n\r\n\t// All the values associated with a section and key.\r\n\tclass Values {\r\n\tpublic:\r\n\t\t/**\r\n\t\t * @brief Constructs an empty set of values.\r\n\t\t *\r\n\t\t * If passed to `set`, the key is deleted.\r\n\t\t */\r\n\t\tValues();\r\n\r\n\t\texplicit Values(const Value &data);\r\n\r\n\t\t[[nodiscard]] std::span<const Value> get() const;\r\n\t\t[[nodiscard]] std::span<Value> get();\r\n\t\tvoid append(const Value &value);\r\n\r\n\tprivate:\r\n\t\t// Most keys only have a single value, so we use\r\n\t\t// a representation that avoids allocations in that case.\r\n\t\tstd::variant<Value, std::vector<Value>> rep_;\r\n\r\n\t\tfriend class Ini;\r\n\t};\r\n\r\n\tstatic tl::expected<Ini, std::string> parse(std::string_view buffer);\r\n\t[[nodiscard]] std::string serialize() const;\r\n\r\n\t/** @return all the keys associated with this section in the ini */\r\n\t[[nodiscard]] std::vector<std::string> getKeys(std::string_view section) const;\r\n\r\n\t/** @return all the values associated with this section and key in the ini */\r\n\t[[nodiscard]] std::span<const Value> get(std::string_view section, std::string_view key) const;\r\n\r\n\t/** @return the default value if the ini value is unset or empty */\r\n\t[[nodiscard]] std::string_view getString(std::string_view section, std::string_view key, std::string_view defaultValue = {}) const;\r\n\r\n\t/** @return the default value if the ini value is unset or empty */\r\n\t[[nodiscard]] bool getBool(std::string_view section, std::string_view key, bool defaultValue) const;\r\n\r\n\t/** @return the default value if the ini value is unset or empty */\r\n\t[[nodiscard]] int getInt(std::string_view section, std::string_view key, int defaultValue) const;\r\n\r\n\t/** @return the default value if the ini value is unset or empty */\r\n\t[[nodiscard]] float getFloat(std::string_view section, std::string_view key, float defaultValue) const;\r\n\r\n\tvoid getUtf8Buf(std::string_view section, std::string_view key, std::string_view defaultValue, char *dst, size_t dstSize) const;\r\n\r\n\tvoid getUtf8Buf(std::string_view section, std::string_view key, char *dst, size_t dstSize) const\r\n\t{\r\n\t\tgetUtf8Buf(section, key, /*defaultValue=*/ {}, dst, dstSize);\r\n\t}\r\n\r\n\t[[nodiscard]] bool changed() const { return changed_; }\r\n\tvoid markAsUnchanged() { changed_ = false; }\r\n\r\n\t// If values are empty, deletes the entry.\r\n\tvoid set(std::string_view section, std::string_view key, Values &&values);\r\n\r\n\tvoid set(std::string_view section, std::string_view key, std::span<const std::string> value);\r\n\tvoid set(std::string_view section, std::string_view key, std::string &&value);\r\n\tvoid set(std::string_view section, std::string_view key, std::string_view value);\r\n\tvoid set(std::string_view section, std::string_view key, const char *value)\r\n\t{\r\n\t\tset(section, key, std::string_view(value));\r\n\t}\r\n\tvoid set(std::string_view section, std::string_view key, bool value);\r\n\tvoid set(std::string_view section, std::string_view key, int value);\r\n\tvoid set(std::string_view section, std::string_view key, float value);\r\n\r\nprivate:\r\n\tstruct ValuesData {\r\n\t\tValues values;\r\n\t\tuint32_t index;\r\n\t};\r\n\r\n\tstruct SectionData {\r\n\t\tstd::string comment;\r\n\t\tankerl::unordered_dense::map<std::string, ValuesData, StringViewHash, StringViewEquals> entries;\r\n\t\tuint32_t index;\r\n\t};\r\n\r\n\tstruct FileData {\r\n\t\tankerl::unordered_dense::map<std::string, SectionData, StringViewHash, StringViewEquals> sections;\r\n\t};\r\n\r\n\texplicit Ini(FileData &&data)\r\n\t    : data_(std::move(data))\r\n\t{\r\n\t}\r\n\r\n\tFileData data_;\r\n\tbool changed_ = false;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/intrusive_optional.hpp",
    "content": "#pragma once\r\n\r\n#include <optional>\r\n#include <type_traits>\r\n#include <utility>\r\n\r\n#include \"appfat.h\"\r\n\r\n/// An optional that uses a field of the stored class and some value to store nullopt.\r\n#define DEFINE_INTRUSIVE_OPTIONAL_IMPL(OPTIONAL_CLASS, VALUE_CLASS, FIELD, NULL_VALUE, CONSTEXPR) \\\r\npublic:                                                                                           \\\r\n\tCONSTEXPR OPTIONAL_CLASS() = default;                                                         \\\r\n                                                                                                  \\\r\n\ttemplate <class U = VALUE_CLASS>                                                              \\\r\n\tCONSTEXPR OPTIONAL_CLASS(VALUE_CLASS &&value)                                                 \\\r\n\t    : value_(std::forward<U>(value))                                                          \\\r\n\t{                                                                                             \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\tCONSTEXPR OPTIONAL_CLASS(std::nullopt_t)                                                      \\\r\n\t    : OPTIONAL_CLASS()                                                                        \\\r\n\t{                                                                                             \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\ttemplate <typename... Args>                                                                   \\\r\n\tCONSTEXPR VALUE_CLASS &emplace(Args &&...args)                                                \\\r\n\t{                                                                                             \\\r\n\t\tvalue_ = VALUE_CLASS(std::forward<Args>(args)...);                                        \\\r\n\t\treturn value_;                                                                            \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\ttemplate <class U = VALUE_CLASS>                                                              \\\r\n\tCONSTEXPR std::enable_if_t<                                                                   \\\r\n\t    !std::is_same_v<OPTIONAL_CLASS, std::remove_cv_t<std::remove_reference_t<U>>>,            \\\r\n\t    OPTIONAL_CLASS> &                                                                         \\\r\n\toperator=(U &&value) noexcept                                                                 \\\r\n\t{                                                                                             \\\r\n\t\tvalue_ = std::forward<U>(value);                                                          \\\r\n\t\treturn *this;                                                                             \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\tCONSTEXPR OPTIONAL_CLASS &operator=(std::nullopt_t)                                           \\\r\n\t{                                                                                             \\\r\n\t\tvalue_ = VALUE_CLASS {};                                                                  \\\r\n\t\treturn *this;                                                                             \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\tCONSTEXPR const VALUE_CLASS &operator*() const                                                \\\r\n\t{                                                                                             \\\r\n\t\tassert(value_.FIELD != NULL_VALUE);                                                       \\\r\n\t\treturn value_;                                                                            \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\tCONSTEXPR VALUE_CLASS &operator*()                                                            \\\r\n\t{                                                                                             \\\r\n\t\tassert(value_.FIELD != NULL_VALUE);                                                       \\\r\n\t\treturn value_;                                                                            \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\tCONSTEXPR const VALUE_CLASS *operator->() const                                               \\\r\n\t{                                                                                             \\\r\n\t\tassert(value_.FIELD != NULL_VALUE);                                                       \\\r\n\t\treturn &value_;                                                                           \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\tCONSTEXPR VALUE_CLASS *operator->()                                                           \\\r\n\t{                                                                                             \\\r\n\t\tassert(value_.FIELD != NULL_VALUE);                                                       \\\r\n\t\treturn &value_;                                                                           \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\t[[nodiscard]] CONSTEXPR bool has_value() const                                                \\\r\n\t{                                                                                             \\\r\n\t\treturn value_.FIELD != NULL_VALUE;                                                        \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\n\tCONSTEXPR operator bool() const                                                               \\\r\n\t{                                                                                             \\\r\n\t\treturn has_value();                                                                       \\\r\n\t}                                                                                             \\\r\n                                                                                                  \\\r\nprivate:                                                                                          \\\r\n\tVALUE_CLASS value_;\r\n\r\n#define DEFINE_CONSTEXPR_INTRUSIVE_OPTIONAL(OPTIONAL_CLASS, VALUE_CLASS, FIELD, NULL_VALUE) \\\r\n\tDEFINE_INTRUSIVE_OPTIONAL_IMPL(OPTIONAL_CLASS, VALUE_CLASS, FIELD, NULL_VALUE, constexpr)\r\n\r\n#define DEFINE_INTRUSIVE_OPTIONAL(OPTIONAL_CLASS, VALUE_CLASS, FIELD, NULL_VALUE) \\\r\n\tDEFINE_INTRUSIVE_OPTIONAL_IMPL(OPTIONAL_CLASS, VALUE_CLASS, FIELD, NULL_VALUE, )\r\n"
  },
  {
    "path": "Source/utils/is_of.hpp",
    "content": "#pragma once\r\n\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\ntemplate <typename V, typename X, typename... Xs>\r\nDVL_ALWAYS_INLINE constexpr bool IsAnyOf(const V &v, X x, Xs... xs)\r\n{\r\n\treturn v == x || ((v == xs) || ...);\r\n}\r\n\r\ntemplate <typename V, typename X, typename... Xs>\r\nDVL_ALWAYS_INLINE constexpr bool IsNoneOf(const V &v, X x, Xs... xs)\r\n{\r\n\treturn v != x && ((v != xs) && ...);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/language.cpp",
    "content": "#include \"utils/language.h\"\r\n\r\n#include <cstdint>\r\n#include <memory>\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/algorithm/container.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/string_view_hash.hpp\"\r\n\r\n#define MO_MAGIC 0x950412de\r\n\r\nstd::string forceLocale;\r\n\r\nnamespace {\r\n\r\nusing namespace devilution;\r\n\r\n// Translations normally come in \".gmo\" files.\r\n// We also support \".mo\" because that is what poedit generates\r\n// and what translators use to test their work.\r\nconstexpr std::array<const char *, 2> Extensions { \".mo\", \".gmo\" };\r\n\r\nstd::unique_ptr<char[]> translationKeys;\r\nstd::unique_ptr<char[]> translationValues;\r\n\r\nusing TranslationRef = uint32_t;\r\n\r\nstd::vector<ankerl::unordered_dense::map<const char *, TranslationRef, StringViewHash, StringViewEquals>> translation = { {}, {} };\r\n\r\nconstexpr uint32_t TranslationRefOffsetBits = 19;\r\nconstexpr uint32_t TranslationRefSizeBits = 32 - TranslationRefOffsetBits; // 13\r\nconstexpr uint32_t TranslationRefSizeMask = (1 << TranslationRefSizeBits) - 1;\r\n\r\nTranslationRef EncodeTranslationRef(uint32_t offset, uint32_t size)\r\n{\r\n\treturn (offset << TranslationRefSizeBits) | size;\r\n}\r\n\r\nstd::string_view GetTranslation(TranslationRef ref)\r\n{\r\n\treturn { &translationValues[ref >> TranslationRefSizeBits], ref & TranslationRefSizeMask };\r\n}\r\n\r\n} // namespace\r\n\r\nnamespace {\r\n\r\nstruct MoHead {\r\n\tuint32_t magic;\r\n\tstruct {\r\n\t\tuint16_t major;\r\n\t\tuint16_t minor;\r\n\t} revision;\r\n\r\n\tuint32_t nbMappings;\r\n\tuint32_t srcOffset;\r\n\tuint32_t dstOffset;\r\n};\r\n\r\nvoid SwapLE(MoHead &head)\r\n{\r\n\thead.magic = Swap32LE(head.magic);\r\n\thead.revision.major = Swap16LE(head.revision.major);\r\n\thead.revision.minor = Swap16LE(head.revision.minor);\r\n\thead.nbMappings = Swap32LE(head.nbMappings);\r\n\thead.srcOffset = Swap32LE(head.srcOffset);\r\n\thead.dstOffset = Swap32LE(head.dstOffset);\r\n}\r\n\r\nstruct MoEntry {\r\n\tuint32_t length;\r\n\tuint32_t offset;\r\n};\r\n\r\nvoid SwapLE(MoEntry &entry)\r\n{\r\n\tentry.length = Swap32LE(entry.length);\r\n\tentry.offset = Swap32LE(entry.offset);\r\n}\r\n\r\nstd::string_view TrimLeft(std::string_view str)\r\n{\r\n\tstr.remove_prefix(std::min(str.find_first_not_of(\" \\t\"), str.size()));\r\n\treturn str;\r\n}\r\n\r\nstd::string_view TrimRight(std::string_view str)\r\n{\r\n\tstr.remove_suffix(str.size() - (str.find_last_not_of(\" \\t\") + 1));\r\n\treturn str;\r\n}\r\n\r\n/** plural=(n != 1); */\r\nint PluralIfNotOne(int n)\r\n{\r\n\treturn n != 1 ? 1 : 0;\r\n}\r\n\r\n// English, Danish, Spanish, Italian, Swedish\r\nunsigned PluralForms = 2;\r\ntl::function_ref<int(int n)> GetLocalPluralId = PluralIfNotOne;\r\n\r\n/**\r\n * Match plural=(n != 1);\"\r\n */\r\nvoid SetPluralForm(std::string_view expression)\r\n{\r\n\tconst std::string_view key = \"plural=\";\r\n\tconst std::string_view::size_type keyPos = expression.find(key);\r\n\tif (keyPos == std::string_view::npos)\r\n\t\treturn;\r\n\texpression.remove_prefix(keyPos + key.size());\r\n\r\n\tconst std::string_view::size_type semicolonPos = expression.find(';');\r\n\tif (semicolonPos != std::string_view::npos) {\r\n\t\texpression.remove_suffix(expression.size() - semicolonPos);\r\n\t}\r\n\r\n\texpression = TrimLeft(TrimRight(expression));\r\n\r\n\t// ko, zh_CN, zh_TW\r\n\tif (expression == \"0\") {\r\n\t\tGetLocalPluralId = [](int /*n*/) -> int { return 0; };\r\n\t\treturn;\r\n\t}\r\n\r\n\t// en, bg, da, de, es, fi, it, sv\r\n\tif (expression == \"(n != 1)\") {\r\n\t\tGetLocalPluralId = PluralIfNotOne;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// fr, pt_BR\r\n\tif (expression == \"(n > 1)\") {\r\n\t\tGetLocalPluralId = [](int n) -> int { return n > 1 ? 1 : 0; };\r\n\t\treturn;\r\n\t}\r\n\r\n\t// be, hr, ru\r\n\tif (expression == \"(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2)\") {\r\n\t\tGetLocalPluralId = [](int n) -> int {\r\n\t\t\tif (n % 10 == 1 && n % 100 != 11)\r\n\t\t\t\treturn 0;\r\n\t\t\tif (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14))\r\n\t\t\t\treturn 1;\r\n\t\t\treturn 2;\r\n\t\t};\r\n\t\treturn;\r\n\t}\r\n\r\n\t// pl\r\n\tif (expression == \"(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2)\") {\r\n\t\tGetLocalPluralId = [](int n) -> int {\r\n\t\t\tif (n == 1)\r\n\t\t\t\treturn 0;\r\n\t\t\tif (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14))\r\n\t\t\t\treturn 1;\r\n\t\t\treturn 2;\r\n\t\t};\r\n\t\treturn;\r\n\t}\r\n\r\n\t// ro\r\n\tif (expression == \"(n==1 ? 0 : n==0 || (n!=1 && n%100>=1 && n%100<=19) ? 1 : 2)\") {\r\n\t\tGetLocalPluralId = [](int n) -> int {\r\n\t\t\tif (n == 1)\r\n\t\t\t\treturn 0;\r\n\t\t\tif (n == 0 || (n != 1 && n % 100 >= 1 && n % 100 <= 19))\r\n\t\t\t\treturn 1;\r\n\t\t\treturn 2;\r\n\t\t};\r\n\t\treturn;\r\n\t}\r\n\r\n\t// cs\r\n\tif (expression == \"(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\") {\r\n\t\tGetLocalPluralId = [](int n) -> int {\r\n\t\t\tif (n == 1)\r\n\t\t\t\treturn 0;\r\n\t\t\tif (n >= 2 && n <= 4)\r\n\t\t\t\treturn 1;\r\n\t\t\treturn 2;\r\n\t\t};\r\n\t\treturn;\r\n\t}\r\n\r\n\tLogError(\"Unknown plural expression: '{}'\", expression);\r\n}\r\n\r\n/**\r\n * Parse \"nplurals=2;\"\r\n */\r\nvoid ParsePluralForms(std::string_view string)\r\n{\r\n\tconst std::string_view pluralsKey = \"nplurals\";\r\n\tconst std::string_view::size_type pluralsPos = string.find(pluralsKey);\r\n\tif (pluralsPos == std::string_view::npos)\r\n\t\treturn;\r\n\tstring.remove_prefix(pluralsPos + pluralsKey.size());\r\n\r\n\tconst std::string_view::size_type eqPos = string.find('=');\r\n\tif (eqPos == std::string_view::npos)\r\n\t\treturn;\r\n\r\n\tconst std::string_view value = string.substr(eqPos + 1);\r\n\tif (value.empty() || value[0] < '0')\r\n\t\treturn;\r\n\r\n\tconst unsigned nplurals = value[0] - '0';\r\n\tif (nplurals == 0)\r\n\t\treturn;\r\n\r\n\tPluralForms = nplurals;\r\n\r\n\tSetPluralForm(value);\r\n}\r\n\r\nvoid ParseMetadata(std::string_view metadata)\r\n{\r\n\tstd::string_view::size_type delim;\r\n\r\n\twhile (!metadata.empty() && ((delim = metadata.find(':')) != std::string_view::npos)) {\r\n\t\tconst std::string_view key = TrimLeft(std::string_view(metadata.data(), delim));\r\n\t\tstd::string_view val = TrimLeft(std::string_view(metadata.data() + delim + 1, metadata.size() - delim - 1));\r\n\r\n\t\tif ((delim = val.find('\\n')) != std::string_view::npos) {\r\n\t\t\tval = std::string_view(val.data(), delim);\r\n\t\t\tmetadata.remove_prefix(val.data() - metadata.data() + val.size() + 1);\r\n\t\t} else {\r\n\t\t\tmetadata.remove_prefix(metadata.size());\r\n\t\t}\r\n\r\n\t\t// Match \"Plural-Forms: nplurals=2; plural=(n != 1);\"\r\n\t\tif (key == \"Plural-Forms\") {\r\n\t\t\tParsePluralForms(val);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool ReadEntry(AssetHandle &handle, const MoEntry &e, char *result)\r\n{\r\n\tif (!handle.seek(e.offset))\r\n\t\treturn false;\r\n\tresult[e.length] = '\\0';\r\n\treturn handle.read(result, e.length);\r\n}\r\n\r\nbool CopyData(void *dst, const std::byte *data, size_t dataSize, size_t offset, size_t length)\r\n{\r\n\tif (offset + length > dataSize)\r\n\t\treturn false;\r\n\tmemcpy(dst, data + offset, length);\r\n\treturn true;\r\n}\r\n\r\nbool ReadEntry(const std::byte *data, size_t dataSize, const MoEntry &e, char *result)\r\n{\r\n\tif (!CopyData(result, data, dataSize, e.offset, e.length))\r\n\t\treturn false;\r\n\tresult[e.length] = '\\0';\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nstd::string_view LanguageParticularTranslate(std::string_view context, std::string_view message)\r\n{\r\n\tconstexpr const char Glue = '\\004';\r\n\r\n\tstd::string key = std::string(context);\r\n\tkey.reserve(key.size() + 1 + message.size());\r\n\tkey += Glue;\r\n\tkey.append(message);\r\n\r\n\tauto it = translation[0].find(key.c_str());\r\n\tif (it == translation[0].end()) {\r\n\t\treturn message;\r\n\t}\r\n\r\n\treturn GetTranslation(it->second);\r\n}\r\n\r\nstd::string_view LanguagePluralTranslate(const char *singular, std::string_view plural, int count)\r\n{\r\n\tconst int n = GetLocalPluralId(count);\r\n\r\n\tauto it = translation[n].find(singular);\r\n\tif (it == translation[n].end()) {\r\n\t\tif (count != 1)\r\n\t\t\treturn plural;\r\n\t\treturn singular;\r\n\t}\r\n\r\n\treturn GetTranslation(it->second);\r\n}\r\n\r\nstd::string_view LanguageTranslate(const char *key)\r\n{\r\n\tauto it = translation[0].find(key);\r\n\tif (it == translation[0].end()) {\r\n\t\treturn key;\r\n\t}\r\n\r\n\treturn GetTranslation(it->second);\r\n}\r\n\r\nbool HasTranslation(const std::string &locale)\r\n{\r\n\tif (locale == \"en\") {\r\n\t\t// the base translation is en (really en_US). No translation file will be present for this code but we want\r\n\t\t//  the check to succeed to prevent further searches.\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn c_any_of(Extensions, [locale](const char *extension) {\r\n\t\treturn FindAsset((locale + extension).c_str()).ok();\r\n\t});\r\n}\r\n\r\nstd::string_view GetLanguageCode()\r\n{\r\n\tif (!forceLocale.empty())\r\n\t\treturn forceLocale;\r\n\treturn *GetOptions().Language.code;\r\n}\r\n\r\nvoid LanguageInitialize()\r\n{\r\n\ttranslation = { {}, {} };\r\n\ttranslationKeys = nullptr;\r\n\ttranslationValues = nullptr;\r\n\r\n\tconst std::string lang(GetLanguageCode());\r\n\r\n\tif (lang == \"en\") {\r\n\t\t// English does not have a translation file.\r\n\t\tGetLocalPluralId = PluralIfNotOne;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (IsSmallFontTall() && !HaveExtraFonts()) {\r\n\t\tUiErrorOkDialog(\r\n\t\t    \"Missing fonts.mpq\",\r\n\t\t    StrCat(\"fonts.mpq is required for locale \\\"\",\r\n\t\t        GetLanguageCode(),\r\n\t\t        \"\\\"\\n\\n\"\r\n\t\t        \"Please download fonts.mpq from:\\n\"\r\n\t\t        \"github.com/diasurgical/\\ndevilutionx-assets/releases\"));\r\n\t\tforceLocale = \"en\";\r\n\t\tGetLocalPluralId = PluralIfNotOne;\r\n\t\treturn;\r\n\t}\r\n\r\n\tAssetHandle handle;\r\n\tconst uint32_t loadTranslationsStart = SDL_GetTicks();\r\n\r\n\tstd::string translationsPath;\r\n\tsize_t fileSize;\r\n\tfor (const char *ext : Extensions) {\r\n\t\ttranslationsPath = lang + ext;\r\n\t\thandle = OpenAsset(translationsPath.c_str(), fileSize);\r\n\t\tif (handle.ok())\r\n\t\t\tbreak;\r\n\t}\r\n\tif (!handle.ok()) {\r\n\t\t// Reset to English, which is always available:\r\n\t\tforceLocale = \"en\";\r\n\t\tGetLocalPluralId = PluralIfNotOne;\r\n\t\treturn;\r\n\t}\r\n\r\n#ifdef UNPACKED_MPQS\r\n\tconst bool readWholeFile = false;\r\n#else\r\n#ifdef USE_SDL3\r\n\t// In SDL3, we don't have a way to check if the handle is to an MPQ file.\r\n\t// Assume that it is.\r\n\tconst bool readWholeFile = true;\r\n#else\r\n\t// If reading from an MPQ, it is much faster to\r\n\t// load the whole file instead of seeking.\r\n\tconst bool readWholeFile = handle.handle->type == SDL_RWOPS_UNKNOWN;\r\n#endif\r\n#endif\r\n\r\n\tstd::unique_ptr<std::byte[]> data;\r\n\tif (readWholeFile) {\r\n\t\tdata.reset(new std::byte[fileSize]);\r\n\t\tif (!handle.read(data.get(), fileSize))\r\n\t\t\treturn;\r\n\t\thandle = {};\r\n\t}\r\n\r\n\t// Read header and do sanity checks\r\n\tMoHead head;\r\n\tif (readWholeFile\r\n\t        ? !CopyData(&head, data.get(), fileSize, 0, sizeof(MoHead))\r\n\t        : !handle.read(&head, sizeof(MoHead))) {\r\n\t\treturn;\r\n\t}\r\n\tSwapLE(head);\r\n\r\n\tif (head.magic != MO_MAGIC) {\r\n\t\treturn; // not a MO file\r\n\t}\r\n\r\n\tif (head.revision.major > 1 || head.revision.minor > 1) {\r\n\t\treturn; // unsupported revision\r\n\t}\r\n\r\n\t// Read entries of source strings\r\n\tconst std::unique_ptr<MoEntry[]> src { new MoEntry[head.nbMappings] };\r\n\tif (readWholeFile\r\n\t        ? !CopyData(src.get(), data.get(), fileSize, head.srcOffset, head.nbMappings * sizeof(MoEntry))\r\n\t        : !handle.seek(head.srcOffset) || !handle.read(src.get(), head.nbMappings * sizeof(MoEntry))) {\r\n\t\treturn;\r\n\t}\r\n\tfor (size_t i = 0; i < head.nbMappings; ++i) {\r\n\t\tSwapLE(src[i]);\r\n\t}\r\n\r\n\t// Read entries of target strings\r\n\tconst std::unique_ptr<MoEntry[]> dst { new MoEntry[head.nbMappings] };\r\n\tif (readWholeFile\r\n\t        ? !CopyData(dst.get(), data.get(), fileSize, head.dstOffset, head.nbMappings * sizeof(MoEntry))\r\n\t        : !handle.seek(head.dstOffset) || !handle.read(dst.get(), head.nbMappings * sizeof(MoEntry))) {\r\n\t\treturn;\r\n\t}\r\n\tfor (size_t i = 0; i < head.nbMappings; ++i) {\r\n\t\tSwapLE(dst[i]);\r\n\t}\r\n\r\n\t// MO header\r\n\tif (src[0].length != 0) {\r\n\t\treturn;\r\n\t}\r\n\t{\r\n\t\tauto headerValue = std::unique_ptr<char[]> { new char[dst[0].length + 1] };\r\n\t\tif (readWholeFile\r\n\t\t        ? !ReadEntry(data.get(), fileSize, dst[0], &headerValue[0])\r\n\t\t        : !ReadEntry(handle, dst[0], &headerValue[0])) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tParseMetadata(&headerValue[0]);\r\n\t}\r\n\r\n\ttranslation.resize(PluralForms);\r\n\tfor (unsigned i = 0; i < PluralForms; i++)\r\n\t\ttranslation[i] = {};\r\n\r\n\t// Read strings described by entries\r\n\tsize_t keysSize = 0;\r\n\tsize_t valuesSize = 0;\r\n\tfor (uint32_t i = 1; i < head.nbMappings; i++) {\r\n\t\tkeysSize += src[i].length + 1;\r\n\t\tvaluesSize += dst[i].length + 1;\r\n\t}\r\n\ttranslationKeys = std::unique_ptr<char[]> { new char[keysSize] };\r\n\ttranslationValues = std::unique_ptr<char[]> { new char[valuesSize] };\r\n\r\n\tchar *keyPtr = &translationKeys[0];\r\n\tchar *valuePtr = &translationValues[0];\r\n\ttranslation[0].reserve(head.nbMappings - 1);\r\n\tfor (uint32_t i = 1; i < head.nbMappings; i++) {\r\n\t\tif (readWholeFile\r\n\t\t        ? ReadEntry(data.get(), fileSize, src[i], keyPtr) && ReadEntry(data.get(), fileSize, dst[i], valuePtr)\r\n\t\t        : ReadEntry(handle, src[i], keyPtr) && ReadEntry(handle, dst[i], valuePtr)) {\r\n\t\t\t// Plural keys also have a plural form but it does not participate in lookup.\r\n\t\t\t// Plural values are \\0-terminated.\r\n\t\t\tstd::string_view value { valuePtr, dst[i].length + 1 };\r\n\t\t\tfor (size_t j = 0; j < PluralForms && !value.empty(); j++) {\r\n\t\t\t\tconst size_t formValueEnd = value.find('\\0');\r\n\t\t\t\ttranslation[j].emplace(keyPtr, EncodeTranslationRef(static_cast<uint32_t>(value.data() - &translationValues[0]), static_cast<uint32_t>(formValueEnd)));\r\n\t\t\t\tvalue.remove_prefix(formValueEnd + 1);\r\n\t\t\t}\r\n\r\n\t\t\tkeyPtr += src[i].length + 1;\r\n\t\t\tvaluePtr += dst[i].length + 1;\r\n\t\t}\r\n\t}\r\n\r\n\tLogVerbose(StrCat(\"Loaded translations from \", translationsPath, \" in \", SDL_GetTicks() - loadTranslationsStart, \"ms\"));\r\n}\r\n"
  },
  {
    "path": "Source/utils/language.h",
    "content": "#pragma once\r\n\r\n#include <string>\r\n#include <string_view>\r\n\r\n#define _(x) LanguageTranslate(x)\r\n#define ngettext(x, y, z) LanguagePluralTranslate(x, y, z)\r\n#define pgettext(context, x) LanguageParticularTranslate(context, x)\r\n#define N_(x) (x)\r\n#define P_(context, x) (x)\r\n\r\nextern std::string forceLocale;\r\n\r\nstd::string_view GetLanguageCode();\r\n\r\nbool HasTranslation(const std::string &locale);\r\nvoid LanguageInitialize();\r\n\r\n/**\r\n * @brief Returns the translation for the given key.\r\n *\r\n * @return guaranteed to be null-terminated.\r\n */\r\nstd::string_view LanguageTranslate(const char *key);\r\ninline std::string_view LanguageTranslate(const std::string &key)\r\n{\r\n\treturn LanguageTranslate(key.c_str());\r\n}\r\n\r\n/**\r\n * @brief Returns a singular or plural translation for the given keys and count.\r\n *\r\n * @return guaranteed to be null-terminated if `plural` is.\r\n */\r\nstd::string_view LanguagePluralTranslate(const char *singular, std::string_view plural, int count);\r\n\r\n/**\r\n * @brief Returns the translation for the given key and context identifier.\r\n *\r\n * @return guaranteed to be null-terminated.\r\n */\r\nstd::string_view LanguageParticularTranslate(std::string_view context, std::string_view message);\r\n\r\n// Chinese and Japanese, and Korean small font is 16px instead of a 12px one for readability.\r\ninline bool IsSmallFontTall()\r\n{\r\n\tconst std::string_view code = GetLanguageCode().substr(0, 2);\r\n\treturn code == \"zh\" || code == \"ja\" || code == \"ko\";\r\n}\r\n"
  },
  {
    "path": "Source/utils/log.hpp",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_log.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <fmt/core.h>\r\n#include <fmt/format.h>\r\n#include <fmt/ranges.h>\r\n\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n// Local definition to fix compilation issue due to header conflict.\r\n[[noreturn]] extern void app_fatal(std::string_view);\r\n\r\nenum class LogCategory {\r\n\tApplication = SDL_LOG_CATEGORY_APPLICATION,\r\n\tError = SDL_LOG_CATEGORY_ERROR,\r\n\tAssert = SDL_LOG_CATEGORY_ASSERT,\r\n\tSystem = SDL_LOG_CATEGORY_SYSTEM,\r\n\tAudio = SDL_LOG_CATEGORY_AUDIO,\r\n\tVideo = SDL_LOG_CATEGORY_VIDEO,\r\n\tRender = SDL_LOG_CATEGORY_RENDER,\r\n\tInput = SDL_LOG_CATEGORY_INPUT,\r\n\tTest = SDL_LOG_CATEGORY_TEST,\r\n};\r\n\r\nconstexpr auto defaultCategory = LogCategory::Application;\r\n\r\nenum class LogPriority {\r\n\tVerbose = SDL_LOG_PRIORITY_VERBOSE,\r\n\tDebug = SDL_LOG_PRIORITY_DEBUG,\r\n\tInfo = SDL_LOG_PRIORITY_INFO,\r\n\tWarn = SDL_LOG_PRIORITY_WARN,\r\n\tError = SDL_LOG_PRIORITY_ERROR,\r\n\tCritical = SDL_LOG_PRIORITY_CRITICAL,\r\n};\r\n\r\nnamespace detail {\r\n\r\ntemplate <typename... Args>\r\nstd::string format(std::string_view fmt, Args &&...args)\r\n{\r\n\tFMT_TRY\r\n\t{\r\n\t\treturn fmt::format(fmt::runtime(fmt), std::forward<Args>(args)...);\r\n\t}\r\n#if FMT_EXCEPTIONS\r\n\tFMT_CATCH(const fmt::format_error &e)\r\n\t{\r\n\t\t// e.what() is undefined if exceptions are disabled, so we wrap it\r\n\t\t// with an `FMT_EXCEPTIONS` check.\r\n\t\tstd::string error = e.what();\r\n#else\r\n\tFMT_CATCH(const fmt::format_error &)\r\n\t{\r\n\t\tstd::string error = \"unknown (FMT_EXCEPTIONS disabled)\";\r\n#endif\r\n\t\tstd::string fullError = StrCat(\"Format error, fmt: \", fmt, \" error: \", error);\r\n\t\tSDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, \"%s\", error.c_str());\r\n\t\tapp_fatal(error);\r\n\t}\r\n}\r\n\r\n} // namespace detail\r\n\r\ninline void Log(std::string_view str)\r\n{\r\n\tSDL_Log(\"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid Log(std::string_view fmt, Args &&...args)\r\n{\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_Log(\"%s\", str.c_str());\r\n}\r\n\r\ninline void LogVerbose(LogCategory category, std::string_view str)\r\n{\r\n\tSDL_LogVerbose(static_cast<int>(category), \"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ninline bool IsLogLevel(LogCategory category, SDL_LogPriority priority)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDL_GetLogPriority(static_cast<int>(category)) <= priority;\r\n#else\r\n\treturn SDL_LogGetPriority(static_cast<int>(category)) <= priority;\r\n#endif\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogVerbose(LogCategory category, std::string_view fmt, Args &&...args)\r\n{\r\n\tif (!IsLogLevel(category, SDL_LOG_PRIORITY_VERBOSE)) return;\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_LogVerbose(static_cast<int>(category), \"%s\", str.c_str());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogVerbose(std::string_view fmt, Args &&...args)\r\n{\r\n\tLogVerbose(defaultCategory, fmt, std::forward<Args>(args)...);\r\n}\r\n\r\ninline void LogDebug(LogCategory category, std::string_view str)\r\n{\r\n\tSDL_LogDebug(static_cast<int>(category), \"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogDebug(LogCategory category, std::string_view fmt, Args &&...args)\r\n{\r\n\tif (!IsLogLevel(category, SDL_LOG_PRIORITY_DEBUG)) return;\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_LogDebug(static_cast<int>(category), \"%s\", str.c_str());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogDebug(std::string_view fmt, Args &&...args)\r\n{\r\n\tLogDebug(defaultCategory, fmt, std::forward<Args>(args)...);\r\n}\r\n\r\ninline void LogInfo(LogCategory category, std::string_view str)\r\n{\r\n\tSDL_LogInfo(static_cast<int>(category), \"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogInfo(LogCategory category, std::string_view fmt, Args &&...args)\r\n{\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_LogInfo(static_cast<int>(category), \"%s\", str.c_str());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogInfo(std::string_view fmt, Args &&...args)\r\n{\r\n\tLogInfo(defaultCategory, fmt, std::forward<Args>(args)...);\r\n}\r\n\r\ninline void LogWarn(LogCategory category, std::string_view str)\r\n{\r\n\tSDL_LogWarn(static_cast<int>(category), \"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogWarn(LogCategory category, std::string_view fmt, Args &&...args)\r\n{\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_LogWarn(static_cast<int>(category), \"%s\", str.c_str());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogWarn(std::string_view fmt, Args &&...args)\r\n{\r\n\tLogWarn(defaultCategory, fmt, std::forward<Args>(args)...);\r\n}\r\n\r\ninline void LogError(LogCategory category, std::string_view str)\r\n{\r\n\tSDL_LogError(static_cast<int>(category), \"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogError(LogCategory category, std::string_view fmt, Args &&...args)\r\n{\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_LogError(static_cast<int>(category), \"%s\", str.c_str());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogError(std::string_view fmt, Args &&...args)\r\n{\r\n\tLogError(defaultCategory, fmt, std::forward<Args>(args)...);\r\n}\r\n\r\ninline void LogCritical(LogCategory category, std::string_view str)\r\n{\r\n\tSDL_LogCritical(static_cast<int>(category), \"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogCritical(LogCategory category, std::string_view fmt, Args &&...args)\r\n{\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_LogCritical(static_cast<int>(category), \"%s\", str.c_str());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogCritical(std::string_view fmt, Args &&...args)\r\n{\r\n\tLogCritical(defaultCategory, fmt, std::forward<Args>(args)...);\r\n}\r\n\r\ninline void LogMessageV(LogCategory category, LogPriority priority, std::string_view str)\r\n{\r\n\tSDL_LogMessage(static_cast<int>(category), static_cast<SDL_LogPriority>(priority),\r\n\t    \"%.*s\", static_cast<int>(str.size()), str.data());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogMessageV(LogCategory category, LogPriority priority, std::string_view fmt, Args &&...args)\r\n{\r\n\tauto str = detail::format(fmt, std::forward<Args>(args)...);\r\n\tSDL_LogMessageV(static_cast<int>(category), static_cast<SDL_LogPriority>(priority), \"%s\", str.c_str());\r\n}\r\n\r\ntemplate <typename... Args>\r\nvoid LogMessageV(std::string_view fmt, Args &&...args)\r\n{\r\n\tLogMessageV(defaultCategory, fmt, std::forward<Args>(args)...);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/logged_fstream.cpp",
    "content": "#include \"utils/logged_fstream.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nconst char *LoggedFStream::DirToString(int dir)\r\n{\r\n\tswitch (dir) {\r\n\tcase SEEK_SET:\r\n\t\treturn \"SEEK_SET\";\r\n\tcase SEEK_END:\r\n\t\treturn \"SEEK_END\";\r\n\tcase SEEK_CUR:\r\n\t\treturn \"SEEK_CUR\";\r\n\tdefault:\r\n\t\treturn \"invalid\";\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/logged_fstream.hpp",
    "content": "#pragma once\r\n\r\n#include <cerrno>\r\n#include <cstdio>\r\n#include <cstring>\r\n#include <optional>\r\n#include <string>\r\n\r\n#include \"utils/file_util.h\"\r\n#include \"utils/log.hpp\"\r\nnamespace devilution {\r\n\r\n// A wrapper around `FILE *` that logs errors.\r\nstruct LoggedFStream {\r\npublic:\r\n\tbool Open(const char *path, const char *mode)\r\n\t{\r\n\t\ts_ = OpenFile(path, mode);\r\n\t\treturn CheckError(s_ != nullptr, \"fopen(\\\"{}\\\", \\\"{}\\\")\", path, mode);\r\n\t}\r\n\r\n\tvoid Close()\r\n\t{\r\n\t\tif (s_ != nullptr) {\r\n\t\t\tstd::fclose(s_);\r\n\t\t\ts_ = nullptr;\r\n\t\t}\r\n\t}\r\n\r\n\t[[nodiscard]] bool IsOpen() const\r\n\t{\r\n\t\treturn s_ != nullptr;\r\n\t}\r\n\r\n\tbool Seekp(long pos, int dir = SEEK_SET)\r\n\t{\r\n\t\treturn CheckError(std::fseek(s_, pos, dir) == 0,\r\n\t\t    \"fseek({}, {})\", pos, DirToString(dir));\r\n\t}\r\n\r\n\tbool Tellp(long *result)\r\n\t{\r\n\t\t*result = std::ftell(s_);\r\n\t\treturn CheckError(*result != -1L,\r\n\t\t    \"ftell() = {}\", *result);\r\n\t}\r\n\r\n\tbool Write(const char *data, size_t size)\r\n\t{\r\n\t\treturn CheckError(std::fwrite(data, size, 1, s_) == 1,\r\n\t\t    \"fwrite(data, {})\", size);\r\n\t}\r\n\r\n\tbool Read(char *out, size_t size)\r\n\t{\r\n\t\treturn CheckError(std::fread(out, size, 1, s_) == 1,\r\n\t\t    \"fread(out, {})\", size);\r\n\t}\r\n\r\nprivate:\r\n\tstatic const char *DirToString(int dir);\r\n\r\n\ttemplate <typename... PrintFArgs>\r\n\tbool CheckError(bool ok, const char *fmt, PrintFArgs... args)\r\n\t{\r\n\t\tif (!ok) {\r\n\t\t\tstd::string fmtWithError = fmt;\r\n\t\t\tfmtWithError.append(\": failed with \\\"{}\\\"\");\r\n\t\t\tconst char *errorMessage = std::strerror(errno);\r\n\t\t\tif (errorMessage == nullptr)\r\n\t\t\t\terrorMessage = \"\";\r\n\t\t\tLogError(LogCategory::System, fmtWithError.c_str(), args..., errorMessage);\r\n\t\t} else {\r\n\t\t\tLogVerbose(LogCategory::System, fmt, args...);\r\n\t\t}\r\n\t\treturn ok;\r\n\t}\r\n\r\n\tFILE *s_ = nullptr;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/math.h",
    "content": "/**\r\n * @file math.h\r\n *\r\n * Math utility functions\r\n */\r\n#pragma once\r\n\r\nnamespace devilution {\r\nnamespace math {\r\n\r\n/**\r\n * @brief Compute sign of t\r\n * @tparam T Any arithmetic type\r\n * @param t Value to compute sign of\r\n * @return -1 if t < 0, 1 if t > 0, 0 if t == 0\r\n */\r\ntemplate <typename T>\r\nint Sign(T t)\r\n{\r\n\treturn (t > T(0)) - (t < T(0));\r\n}\r\n\r\n/**\r\n * @brief Linearly interpolate from a towards b using mixing value t\r\n * @tparam V Any arithmetic type, used for interpolants and return value\r\n * @tparam T Any arithmetic type, used for interpolator\r\n * @param a Low interpolation value (returned when t == 0)\r\n * @param b High interpolation value (returned when t == 1)\r\n * @param t Interpolator, commonly in range [0..1], values outside this range will extrapolate\r\n * @return a + (b - a) * t\r\n */\r\ntemplate <typename V, typename T>\r\nV Lerp(V a, V b, T t)\r\n{\r\n\treturn a + (b - a) * t;\r\n}\r\n\r\n/**\r\n * @brief Inverse lerp, given two key values a and b, and a free value v, determine mixing factor t so that v = Lerp(a, b, t)\r\n * @tparam T Any arithmetic type\r\n * @param a Low key value (function returns 0 if v == a)\r\n * @param b High key value (function returns 1 if v == b)\r\n * @param v Mixing factor, commonly in range [a..b] to get a return [0..1]\r\n * @return Value t so that v = Lerp(a, b, t); or 0 if b == a\r\n */\r\ntemplate <typename T>\r\nT InvLerp(T a, T b, T v)\r\n{\r\n\tif (b == a)\r\n\t\treturn T(0);\r\n\r\n\treturn (v - a) / (b - a);\r\n}\r\n\r\n/**\r\n * @brief Remaps value v from range [inMin, inMax] to [outMin, outMax]\r\n * @tparam T Any arithmetic type\r\n * @param inMin First bound of input range\r\n * @param inMax Second bound of input range\r\n * @param outMin First bound of output range\r\n * @param outMax Second bound of output range\r\n * @param v Value to remap\r\n * @return Transformed value so that InvLerp(inMin, inMax, v) == InvLerp(outMin, outMax, return)\r\n */\r\ntemplate <typename T>\r\nT Remap(T inMin, T inMax, T outMin, T outMax, T v)\r\n{\r\n\tauto t = InvLerp(inMin, inMax, v);\r\n\treturn Lerp(outMin, outMax, t);\r\n}\r\n\r\n} // namespace math\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/palette_blending.cpp",
    "content": "#include \"utils/palette_blending.hpp\"\r\n\r\n#include <array>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"utils/palette_kd_tree.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n// This array is read from a lot on every frame.\r\n// We do not use `std::array` here to improve debug build performance.\r\n// In a debug build, `std::array` accesses are function calls.\r\nuint8_t paletteTransparencyLookup[256][256];\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\nuint16_t paletteTransparencyLookupBlack16[65536];\r\n#endif\r\n\r\nnamespace {\r\n\r\nPaletteKdTree CurrentPaletteKdTree;\r\n\r\nusing RGB = std::array<uint8_t, 3>;\r\n\r\nRGB BlendColors(const SDL_Color &a, const SDL_Color &b)\r\n{\r\n\treturn RGB {\r\n\t\tstatic_cast<uint8_t>((static_cast<int>(a.r) + static_cast<int>(b.r)) / 2),\r\n\t\tstatic_cast<uint8_t>((static_cast<int>(a.g) + static_cast<int>(b.g)) / 2),\r\n\t\tstatic_cast<uint8_t>((static_cast<int>(a.b) + static_cast<int>(b.b)) / 2),\r\n\t};\r\n}\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\nvoid SetPaletteTransparencyLookupBlack16(unsigned i, unsigned j)\r\n{\r\n\tpaletteTransparencyLookupBlack16[i | (j << 8U)] = paletteTransparencyLookup[0][i] | (paletteTransparencyLookup[0][j] << 8U);\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\nvoid GenerateBlendedLookupTable(const SDL_Color *palette, int skipFrom, int skipTo)\r\n{\r\n\tCurrentPaletteKdTree = PaletteKdTree { palette, skipFrom, skipTo };\r\n\tfor (unsigned i = 0; i < 256; i++) {\r\n\t\tpaletteTransparencyLookup[i][i] = i;\r\n\t\tunsigned j = 0;\r\n\t\tfor (; j < i; j++) {\r\n\t\t\tpaletteTransparencyLookup[i][j] = paletteTransparencyLookup[j][i];\r\n\t\t}\r\n\t\t++j;\r\n\t\tfor (; j < 256; j++) {\r\n\t\t\tpaletteTransparencyLookup[i][j] = CurrentPaletteKdTree.findNearestNeighbor(BlendColors(palette[i], palette[j]));\r\n\t\t}\r\n\t}\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n\tfor (unsigned i = 0; i < 256; ++i) {\r\n\t\tSetPaletteTransparencyLookupBlack16(i, i);\r\n\t\tfor (unsigned j = 0; j < i; ++j) {\r\n\t\t\tSetPaletteTransparencyLookupBlack16(i, j);\r\n\t\t\tSetPaletteTransparencyLookupBlack16(j, i);\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n\r\nvoid UpdateBlendedLookupTableSingleColor(const SDL_Color *palette, unsigned i)\r\n{\r\n\tfor (unsigned j = 0; j < 256; j++) {\r\n\t\tif (i == j) { // No need to calculate transparency between 2 identical colors\r\n\t\t\tpaletteTransparencyLookup[i][j] = j;\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst uint8_t best = CurrentPaletteKdTree.findNearestNeighbor(BlendColors(palette[i], palette[j]));\r\n\t\tpaletteTransparencyLookup[i][j] = paletteTransparencyLookup[j][i] = best;\r\n\t}\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n\tUpdateTransparencyLookupBlack16(i, i);\r\n#endif\r\n}\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\nvoid UpdateTransparencyLookupBlack16(unsigned from, unsigned to)\r\n{\r\n\tfor (unsigned i = from; i <= to; i++) {\r\n\t\tfor (unsigned j = 0; j < 256; j++) {\r\n\t\t\tSetPaletteTransparencyLookupBlack16(i, j);\r\n\t\t\tSetPaletteTransparencyLookupBlack16(j, i);\r\n\t\t}\r\n\t}\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/palette_blending.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Lookup table for the average of two colors in `logical_palette`.\r\n */\r\nextern uint8_t paletteTransparencyLookup[256][256];\r\n\r\n/**\r\n * @brief Generates `paletteTransparencyLookup` table.\r\n *\r\n * This is based of the same technique found in Quake2.\r\n *\r\n * To mimic 50% transparency we figure out what colors in the existing palette are the best match for the combination of any 2 colors.\r\n * We save this into a lookup table for use during rendering.\r\n *\r\n * @param skipFrom Do not use colors between this index and skipTo\r\n * @param skipTo Do not use colors between skipFrom and this index\r\n */\r\nvoid GenerateBlendedLookupTable(const SDL_Color *palette, int skipFrom = -1, int skipTo = -1);\r\n\r\n/**\r\n * @brief Updates the transparency lookup table for a single color.\r\n */\r\nvoid UpdateBlendedLookupTableSingleColor(const SDL_Color *palette, unsigned i);\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n/**\r\n * A lookup table from black for a pair of colors in `logical_palette`.\r\n *\r\n * For a pair of colors i and j, the index `i | (j << 8)` contains\r\n * `paletteTransparencyLookup[0][i] | (paletteTransparencyLookup[0][j] << 8)`.\r\n *\r\n * On big-endian platforms, the indices are encoded as `j | (i << 8)`, while the\r\n * value order remains the same.\r\n */\r\nextern uint16_t paletteTransparencyLookupBlack16[65536];\r\n\r\nvoid UpdateTransparencyLookupBlack16(unsigned from, unsigned to);\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/palette_kd_tree.cpp",
    "content": "#include \"utils/palette_kd_tree.hpp\"\r\n\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <span>\r\n#include <string>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#elif defined(USE_SDL1)\r\n#include <SDL_video.h>\r\n#else\r\n#include <SDL_pixels.h>\r\n#endif\r\n\r\n#include \"utils/static_vector.hpp\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#if DEVILUTIONX_PRINT_PALETTE_BLENDING_TREE_GRAPHVIZ\r\n#include <cstdio>\r\n#endif\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\ntemplate <size_t N>\r\nuint8_t GetColorComponent(const SDL_Color &);\r\ntemplate <>\r\ninline uint8_t GetColorComponent<0>(const SDL_Color &c) { return c.r; }\r\ntemplate <>\r\ninline uint8_t GetColorComponent<1>(const SDL_Color &c) { return c.g; }\r\ntemplate <>\r\ninline uint8_t GetColorComponent<2>(const SDL_Color &c) { return c.b; }\r\n\r\ntemplate <size_t RemainingDepth>\r\n[[nodiscard]] PaletteKdTreeNode<0> &LeafByIndex(PaletteKdTreeNode<RemainingDepth> &node, uint8_t index)\r\n{\r\n\tif constexpr (RemainingDepth == 1) {\r\n\t\treturn node.child(index % 2 == 0);\r\n\t} else {\r\n\t\treturn LeafByIndex(node.child(index % 2 == 0), index / 2);\r\n\t}\r\n}\r\n\r\ntemplate <size_t RemainingDepth>\r\n[[nodiscard]] uint8_t LeafIndexForColor(const PaletteKdTreeNode<RemainingDepth> &node, const SDL_Color &color, uint8_t result = 0)\r\n{\r\n\tconst bool isLeft = GetColorComponent<PaletteKdTreeNode<RemainingDepth>::Coord>(color) < node.pivot;\r\n\tif constexpr (RemainingDepth == 1) {\r\n\t\treturn (2 * result) + (isLeft ? 0 : 1);\r\n\t} else {\r\n\t\treturn (2 * LeafIndexForColor(node.child(isLeft), color, result)) + (isLeft ? 0 : 1);\r\n\t}\r\n}\r\n\r\nstruct MedianInfo {\r\n\tstd::array<uint16_t, 256> counts = {};\r\n\tuint16_t numValues = 0;\r\n};\r\n\r\n[[nodiscard]] static uint8_t GetMedian(const MedianInfo &medianInfo)\r\n{\r\n\tconst std::span<const uint16_t, 256> counts = medianInfo.counts;\r\n\tconst uint_fast16_t numValues = medianInfo.numValues;\r\n\tconst auto medianTarget = static_cast<uint_fast16_t>((medianInfo.numValues + 1) / 2);\r\n\tuint_fast16_t partialSum = 0;\r\n\tuint_fast16_t i = 0;\r\n\tfor (; partialSum < medianTarget && partialSum != numValues; ++i) {\r\n\t\tpartialSum += counts[i];\r\n\t}\r\n\r\n\t// Special cases:\r\n\t// 1. If the elements are empty, this will return 0.\r\n\t// 2. If all the elements are the same, this will be `value + 1` (rolling over to 0 if value is 256).\r\n\t//    This means all the elements will be on one side of the pivot (left unless the value is 255).\r\n\treturn static_cast<uint8_t>(i);\r\n}\r\n\r\ntemplate <size_t RemainingDepth, size_t N>\r\nvoid MaybeAddToSubdivisionForMedian(\r\n    const PaletteKdTreeNode<RemainingDepth> &node,\r\n    const SDL_Color palette[256], unsigned paletteIndex,\r\n    std::span<MedianInfo, N> medianInfos)\r\n{\r\n\tconst uint8_t color = GetColorComponent<PaletteKdTreeNode<RemainingDepth>::Coord>(palette[paletteIndex]);\r\n\tif constexpr (N == 1) {\r\n\t\tMedianInfo &medianInfo = medianInfos[0];\r\n\t\t++medianInfo.counts[color];\r\n\t\t++medianInfo.numValues;\r\n\t} else {\r\n\t\tconst bool isLeft = color < node.pivot;\r\n\t\tMaybeAddToSubdivisionForMedian(node.child(isLeft),\r\n\t\t    palette,\r\n\t\t    paletteIndex,\r\n\t\t    isLeft\r\n\t\t        ? medianInfos.template subspan<0, N / 2>()\r\n\t\t        : medianInfos.template subspan<N / 2, N / 2>());\r\n\t}\r\n}\r\n\r\ntemplate <size_t RemainingDepth, size_t N>\r\nvoid SetPivotsRecursively(\r\n    PaletteKdTreeNode<RemainingDepth> &node,\r\n    std::span<MedianInfo, N> medianInfos)\r\n{\r\n\tif constexpr (N == 1) {\r\n\t\tnode.pivot = GetMedian(medianInfos[0]);\r\n\t} else {\r\n\t\tSetPivotsRecursively(node.left, medianInfos.template subspan<0, N / 2>());\r\n\t\tSetPivotsRecursively(node.right, medianInfos.template subspan<N / 2, N / 2>());\r\n\t}\r\n}\r\n\r\ntemplate <size_t TargetDepth>\r\nvoid PopulatePivotsForTargetDepth(PaletteKdTreeNode<PaletteKdTreeDepth> &root,\r\n    const SDL_Color palette[256], int skipFrom, int skipTo)\r\n{\r\n\tconstexpr size_t NumSubdivisions = 1U << TargetDepth;\r\n\tstd::array<MedianInfo, NumSubdivisions> subdivisions = {};\r\n\tconst std::span<MedianInfo, NumSubdivisions> subdivisionsSpan { subdivisions };\r\n\tfor (int i = 0; i < 256; ++i) {\r\n\t\tif (i >= skipFrom && i <= skipTo) continue;\r\n\t\tMaybeAddToSubdivisionForMedian(root, palette, i, subdivisionsSpan);\r\n\t}\r\n\tSetPivotsRecursively(root, subdivisionsSpan);\r\n}\r\n\r\ntemplate <size_t... TargetDepths>\r\nvoid PopulatePivotsImpl(PaletteKdTreeNode<PaletteKdTreeDepth> &root,\r\n    const SDL_Color palette[256], int skipFrom, int skipTo, std::index_sequence<TargetDepths...> intSeq) // NOLINT(misc-unused-parameters)\r\n{\r\n\t(PopulatePivotsForTargetDepth<TargetDepths>(root, palette, skipFrom, skipTo), ...);\r\n}\r\n\r\nvoid PopulatePivots(PaletteKdTreeNode<PaletteKdTreeDepth> &root,\r\n    const SDL_Color palette[256], int skipFrom, int skipTo)\r\n{\r\n\tPopulatePivotsImpl(root, palette, skipFrom, skipTo, std::make_index_sequence<PaletteKdTreeDepth> {});\r\n}\r\n\r\n} // namespace\r\n\r\nPaletteKdTree::PaletteKdTree(const SDL_Color palette[256], int skipFrom, int skipTo)\r\n{\r\n\tPopulatePivots(tree_, palette, skipFrom, skipTo);\r\n\tStaticVector<uint8_t, 256> leafValues[NumLeaves];\r\n\tfor (int i = 0; i < 256; ++i) {\r\n\t\tif (i >= skipFrom && i <= skipTo) continue;\r\n\t\tleafValues[LeafIndexForColor(tree_, palette[i])].emplace_back(i);\r\n\t}\r\n\r\n\tsize_t totalLen = 0;\r\n\tfor (uint8_t leafIndex = 0; leafIndex < NumLeaves; ++leafIndex) {\r\n\t\tPaletteKdTreeNode<0> &leaf = LeafByIndex(tree_, leafIndex);\r\n\t\tconst std::span<const uint8_t> values = leafValues[leafIndex];\r\n\t\tif (values.empty()) {\r\n\t\t\tleaf.valuesBegin = 1;\r\n\t\t\tleaf.valuesEndInclusive = 0;\r\n\t\t} else {\r\n\t\t\tleaf.valuesBegin = static_cast<uint8_t>(totalLen);\r\n\t\t\tleaf.valuesEndInclusive = static_cast<uint8_t>(totalLen - 1 + values.size());\r\n\r\n\t\t\tfor (size_t i = 0; i < values.size(); ++i) {\r\n\t\t\t\tconst uint8_t value = values[i];\r\n\t\t\t\tvalues_[totalLen + i] = std::make_pair(RGB { palette[value].r, palette[value].g, palette[value].b }, value);\r\n\t\t\t}\r\n\t\t\ttotalLen += values.size();\r\n\t\t}\r\n\t}\r\n\r\n#if DEVILUTIONX_PRINT_PALETTE_BLENDING_TREE_GRAPHVIZ\r\n\t// To generate palette.dot.svg, run:\r\n\t// dot -O -Tsvg palette.dot\r\n\tFILE *out = std::fopen(\"palette.dot\", \"w\");\r\n\tstd::string dot = toGraphvizDot();\r\n\tstd::fwrite(dot.data(), dot.size(), 1, out);\r\n\tstd::fclose(out);\r\n#endif\r\n}\r\n\r\nstd::string PaletteKdTree::toGraphvizDot() const\r\n{\r\n\tstd::string dot = \"graph palette_tree {\\n  rankdir=LR\\n\";\r\n\ttree_.toGraphvizDot(0, values_, dot);\r\n\tdot.append(\"}\\n\");\r\n\treturn dot;\r\n}\r\n\r\nvoid PaletteKdTreeNode<0>::toGraphvizDot(\r\n    size_t id, std::span<const std::pair<PaletteKdTreeNode<0>::RGB, uint8_t>, 256> values, std::string &dot) const\r\n{\r\n\tStrAppend(dot, \"  node_\", id, R\"( [shape=plain label=<\r\n  <table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"2\" style=\"ROUNDED\">\r\n    <tr>)\");\r\n\tconst std::pair<RGB, uint8_t> *const end = values.data() + valuesEndInclusive;\r\n\tfor (const std::pair<RGB, uint8_t> *it = values.data() + valuesBegin; it <= end; ++it) {\r\n\t\tconst auto &[rgb, paletteIndex] = *it;\r\n\t\tStrAppend(dot, R\"(<td balign=\"left\" bgcolor=\"#)\",\r\n\t\t    AsHexPad2(rgb[0]), AsHexPad2(rgb[1]), AsHexPad2(rgb[2]), \"\\\">\");\r\n\t\tconst bool useWhiteText = rgb[0] + rgb[1] + rgb[2] < 350;\r\n\t\tif (useWhiteText) StrAppend(dot, R\"(<font color=\"white\">)\");\r\n\t\tStrAppend(dot,\r\n\t\t    static_cast<int>(rgb[0]), \" \",\r\n\t\t    static_cast<int>(rgb[1]), \" \",\r\n\t\t    static_cast<int>(rgb[2]), R\"(<br/>)\",\r\n\t\t    static_cast<int>(paletteIndex));\r\n\t\tif (useWhiteText) StrAppend(dot, \"</font>\");\r\n\t\tStrAppend(dot, \"</td>\");\r\n\t}\r\n\tif (valuesBegin > valuesEndInclusive) StrAppend(dot, \"<td></td>\");\r\n\tStrAppend(dot, \"</tr>\\n  </table>>]\\n\");\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/palette_kd_tree.hpp",
    "content": "#pragma once\r\n\r\n#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <limits>\r\n#include <span>\r\n#include <string>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#elif defined(USE_SDL1)\r\n#include <SDL_video.h>\r\n#else\r\n#include <SDL_pixels.h>\r\n#endif\r\n\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#define DEVILUTIONX_PRINT_PALETTE_BLENDING_TREE_GRAPHVIZ 0 // NOLINT(modernize-macro-to-enum)\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Depth (number of levels) of the tree.\r\n */\r\nconstexpr size_t PaletteKdTreeDepth = 5;\r\n\r\n/**\r\n * @brief A node in the k-d tree.\r\n *\r\n * @tparam RemainingDepth distance to the leaf nodes.\r\n */\r\ntemplate <size_t RemainingDepth>\r\nstruct PaletteKdTreeNode {\r\n\tusing RGB = std::array<uint8_t, 3>;\r\n\r\n\tstatic constexpr unsigned Coord = (PaletteKdTreeDepth - RemainingDepth) % 3;\r\n\r\n\tPaletteKdTreeNode<RemainingDepth - 1> left;\r\n\tPaletteKdTreeNode<RemainingDepth - 1> right;\r\n\tuint8_t pivot;\r\n\r\n\t[[nodiscard]] const PaletteKdTreeNode<RemainingDepth - 1> &child(bool isLeft) const\r\n\t{\r\n\t\treturn isLeft ? left : right;\r\n\t}\r\n\t[[nodiscard]] PaletteKdTreeNode<RemainingDepth - 1> &child(bool isLeft)\r\n\t{\r\n\t\treturn isLeft ? left : right;\r\n\t}\r\n\r\n\t[[maybe_unused]] void toGraphvizDot(size_t id, std::span<const std::pair<RGB, uint8_t>, 256> values, std::string &dot) const\r\n\t{\r\n\t\tStrAppend(dot, \"  node_\", id, \" [label=\\\"\", \"rgb\"[Coord], \": \", pivot, \"\\\"]\\n\");\r\n\t\tconst size_t leftId = (2 * id) + 1;\r\n\t\tconst size_t rightId = (2 * id) + 2;\r\n\t\tleft.toGraphvizDot(leftId, values, dot);\r\n\t\tright.toGraphvizDot(rightId, values, dot);\r\n\t\tStrAppend(dot, \"  node_\", id, \" -- node_\", leftId,\r\n\t\t    \"\\n  node_\", id, \" -- node_\", rightId, \"\\n\");\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief A leaf node in the k-d tree.\r\n */\r\ntemplate <>\r\nstruct PaletteKdTreeNode</*RemainingDepth=*/0> {\r\n\tusing RGB = std::array<uint8_t, 3>;\r\n\r\n\t// We use inclusive indices to allow for representing the full [0, 255] range.\r\n\t// An empty node is represented as [1, 0].\r\n\tuint8_t valuesBegin;\r\n\tuint8_t valuesEndInclusive;\r\n\r\n\tvoid toGraphvizDot(size_t id, std::span<const std::pair<RGB, uint8_t>, 256> values, std::string &dot) const;\r\n};\r\n\r\n/**\r\n * @brief A kd-tree used to find the nearest neighbor in the color space.\r\n *\r\n * Each level splits the space in half by red, green, and blue respectively.\r\n */\r\nclass PaletteKdTree {\r\nprivate:\r\n\tusing RGB = std::array<uint8_t, 3>;\r\n\tstatic constexpr unsigned NumLeaves = 1U << PaletteKdTreeDepth;\r\n\r\npublic:\r\n\tPaletteKdTree() = default;\r\n\r\n\t/**\r\n\t * @brief Constructs a PaletteKdTree\r\n\t *\r\n\t * The palette is used as points in the tree.\r\n\t * Colors between skipFrom and skipTo (inclusive) are skipped.\r\n\t */\r\n\tPaletteKdTree(const SDL_Color palette[256], int skipFrom, int skipTo);\r\n\r\n\tstruct VisitState {\r\n\t\tuint8_t best;\r\n\t\tuint32_t bestDiff;\r\n\t};\r\n\r\n\t[[nodiscard]] uint8_t findNearestNeighbor(const RGB &rgb) const\r\n\t{\r\n\t\tVisitState visitState;\r\n\t\tvisitState.bestDiff = std::numeric_limits<uint32_t>::max();\r\n\t\tfindNearestNeighborVisit(tree_, rgb, visitState);\r\n\t\treturn visitState.best;\r\n\t}\r\n\r\n\t[[maybe_unused]] [[nodiscard]] std::string toGraphvizDot() const;\r\n\r\nprivate:\r\n\t[[nodiscard]] static constexpr uint32_t getColorDistance(const std::array<uint8_t, 3> &a, const std::array<uint8_t, 3> &b)\r\n\t{\r\n\t\tconst int diffr = a[0] - b[0];\r\n\t\tconst int diffg = a[1] - b[1];\r\n\t\tconst int diffb = a[2] - b[2];\r\n\t\treturn (diffr * diffr) + (diffg * diffg) + (diffb * diffb);\r\n\t}\r\n\r\n\t[[nodiscard]] static constexpr uint32_t getColorDistanceToPlane(int x1, int x2)\r\n\t{\r\n\t\t// Our planes are axis-aligned, so a distance from a point to a plane\r\n\t\t// can be calculated based on just the axis coordinate.\r\n\t\tconst int delta = x1 - x2;\r\n\t\treturn static_cast<uint32_t>(delta * delta);\r\n\t}\r\n\r\n\ttemplate <size_t RemainingDepth>\r\n\tvoid findNearestNeighborVisit(const PaletteKdTreeNode<RemainingDepth> &node, const RGB &rgb,\r\n\t    VisitState &visitState) const\r\n\t{\r\n\t\tconst uint8_t coord = rgb[PaletteKdTreeNode<RemainingDepth>::Coord];\r\n\t\tfindNearestNeighborVisit(node.child(coord < node.pivot), rgb, visitState);\r\n\r\n\t\t// To see if we need to check a node's subtree, we compare the distance from the query\r\n\t\t// to the current best candidate vs the distance to the edge of the half-space represented\r\n\t\t// by the node.\r\n\t\tif (getColorDistanceToPlane(node.pivot, coord) < visitState.bestDiff) {\r\n\t\t\tfindNearestNeighborVisit(node.child(coord >= node.pivot), rgb, visitState);\r\n\t\t}\r\n\t}\r\n\r\n\tvoid findNearestNeighborVisit(const PaletteKdTreeNode<0> &node, const RGB &rgb,\r\n\t    VisitState &visitState) const\r\n\t{\r\n\t\t// Nodes are almost never empty.\r\n\t\t// Separating the empty check from the loop makes this faster,\r\n\t\t// probaly because of better branch prediction.\r\n\t\tif (node.valuesBegin > node.valuesEndInclusive) return;\r\n\r\n\t\tconst std::pair<RGB, uint8_t> *it = values_.data() + node.valuesBegin;\r\n\t\tconst std::pair<RGB, uint8_t> *const end = values_.data() + node.valuesEndInclusive;\r\n\t\tdo {\r\n\t\t\tconst auto &[paletteColor, paletteIndex] = *it++;\r\n\t\t\tconst uint32_t diff = getColorDistance(paletteColor, rgb);\r\n\t\t\tif (diff < visitState.bestDiff) {\r\n\t\t\t\tvisitState.best = paletteIndex;\r\n\t\t\t\tvisitState.bestDiff = diff;\r\n\t\t\t}\r\n\t\t} while (it <= end);\r\n\t}\r\n\r\n\tPaletteKdTreeNode<PaletteKdTreeDepth> tree_;\r\n\tstd::array<std::pair<RGB, uint8_t>, 256> values_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/parse_int.cpp",
    "content": "#include \"parse_int.hpp\"\r\n\r\n#include <algorithm>\r\n\r\nnamespace devilution {\r\n\r\nuint8_t ParseFixed6Fraction(std::string_view str, const char **endOfParse)\r\n{\r\n\tunsigned numDigits = 0;\r\n\tuint32_t decimalFraction = 0;\r\n\r\n\t// Read at most 7 digits, at that threshold we're able to determine an exact rounding for 6 bit fixed point numbers\r\n\twhile (!str.empty() && numDigits < 7) {\r\n\t\tif (str[0] < '0' || str[0] > '9') {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdecimalFraction = decimalFraction * 10 + str[0] - '0';\r\n\t\t++numDigits;\r\n\t\tstr.remove_prefix(1);\r\n\t}\r\n\tif (endOfParse != nullptr) {\r\n\t\t// to mimic the behaviour of std::from_chars consume all remaining digits in case the value was overly precise.\r\n\t\t*endOfParse = std::find_if_not(str.data(), str.data() + str.size(), [](char character) { return character >= '0' && character <= '9'; });\r\n\t}\r\n\t// to ensure rounding to nearest we normalise all values to 7 decimal places\r\n\twhile (numDigits < 7) {\r\n\t\tdecimalFraction *= 10;\r\n\t\t++numDigits;\r\n\t}\r\n\t// we add half the step between representable values to use integer truncation as a substitute for rounding to nearest.\r\n\treturn (decimalFraction + 78125) / 156250;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/parse_int.hpp",
    "content": "#pragma once\r\n\r\n#include <charconv>\r\n#include <cstdint>\r\n#include <string_view>\r\n#include <system_error>\r\n\r\n#include <expected.hpp>\r\n\r\nnamespace devilution {\r\n\r\nenum class ParseIntError {\r\n\tParseError = 1,\r\n\tOutOfRange\r\n};\r\n\r\ntemplate <typename IntT>\r\nusing ParseIntResult = tl::expected<IntT, ParseIntError>;\r\n\r\ntemplate <typename IntT>\r\nParseIntResult<IntT> ParseInt(\r\n    std::string_view str, IntT min = std::numeric_limits<IntT>::min(),\r\n    IntT max = std::numeric_limits<IntT>::max(), const char **endOfParse = nullptr)\r\n{\r\n\tIntT value;\r\n\tconst std::from_chars_result result = std::from_chars(str.data(), str.data() + str.size(), value);\r\n\tif (endOfParse != nullptr) {\r\n\t\t*endOfParse = result.ptr;\r\n\t}\r\n\tif (result.ec == std::errc::invalid_argument)\r\n\t\treturn tl::unexpected(ParseIntError::ParseError);\r\n\tif (result.ec == std::errc::result_out_of_range || value < min || value > max)\r\n\t\treturn tl::unexpected(ParseIntError::OutOfRange);\r\n\tif (result.ec != std::errc())\r\n\t\treturn tl::unexpected(ParseIntError::ParseError);\r\n\treturn value;\r\n}\r\n\r\n/**\r\n * @brief Parses a sequence of decimal characters into a 6 bit fixed point number in the range [0, 1.0]\r\n * @param str a potentially empty string of base 10 digits, optionally followed by non-digit characters\r\n * @param[out] endOfParse equivalent to std::from_chars_result::ptr, used to tell where parsing stopped\r\n * @return a value in the range [0, 64], representing a 2.6 fixed value in the range [0, 1.0]\r\n */\r\nuint8_t ParseFixed6Fraction(std::string_view str, const char **endOfParse = nullptr);\r\n\r\ntemplate <typename IntT>\r\nParseIntResult<IntT> ParseFixed6(std::string_view str, const char **endOfParse = nullptr)\r\n{\r\n\tif (endOfParse != nullptr) {\r\n\t\t// To allow for early returns we set the end pointer to the start of the string, which is the common case for errors.\r\n\t\t*endOfParse = str.data();\r\n\t}\r\n\r\n\tif (str.empty()) {\r\n\t\treturn tl::unexpected { ParseIntError::ParseError };\r\n\t}\r\n\r\n\tconstexpr IntT minIntegerValue = std::numeric_limits<IntT>::min() >> 6;\r\n\tconstexpr IntT maxIntegerValue = std::numeric_limits<IntT>::max() >> 6;\r\n\r\n\tconst char *currentChar; // will be set by the call to parseInt\r\n\tParseIntResult<IntT> integerParseResult = ParseInt(str, minIntegerValue, maxIntegerValue, &currentChar);\r\n\r\n\tbool isNegative = std::is_signed_v<IntT> && str[0] == '-';\r\n\tbool haveDigits = integerParseResult.has_value() || integerParseResult.error() == ParseIntError::OutOfRange;\r\n\tif (haveDigits) {\r\n\t\tstr.remove_prefix(static_cast<size_t>(std::distance(str.data(), currentChar)));\r\n\t} else if (isNegative) {\r\n\t\tstr.remove_prefix(1);\r\n\t}\r\n\r\n\t// if the string has no leading digits we still need to try parse the fraction part\r\n\tuint8_t fractionPart = 0;\r\n\tif (!str.empty() && str[0] == '.') {\r\n\t\t// got a fractional part to read too\r\n\t\tstr.remove_prefix(1); // skip past the decimal point\r\n\r\n\t\tfractionPart = ParseFixed6Fraction(str, &currentChar);\r\n\t\thaveDigits = haveDigits || str.data() != currentChar;\r\n\t}\r\n\r\n\tif (!haveDigits) {\r\n\t\t// early return in case we got a string like \"-.abc\", don't want to set the end pointer in this case\r\n\t\treturn tl::unexpected { ParseIntError::ParseError };\r\n\t}\r\n\r\n\tif (endOfParse != nullptr) {\r\n\t\t*endOfParse = currentChar;\r\n\t}\r\n\r\n\tif (!integerParseResult.has_value() && integerParseResult.error() == ParseIntError::OutOfRange) {\r\n\t\t// if the integer parsing gave us an out of range value then we've done a bit of unnecessary\r\n\t\t//  work parsing the fraction part, but it saves duplicating code.\r\n\t\treturn integerParseResult;\r\n\t}\r\n\t// integerParseResult could be a ParseError at this point because of a string like \".123\" or \"-.1\"\r\n\t//  so we need to default to 0 (and use the result of the minus sign check when it's relevant)\r\n\tIntT integerPart = integerParseResult.value_or(0);\r\n\r\n\t// rounding could give us a value of 64 for the fraction part (e.g. 0.993 rounds to 1.0) so we need to ensure this doesn't overflow\r\n\tif (fractionPart >= 64 && (integerPart >= maxIntegerValue || (std::is_signed_v<IntT> && integerPart <= minIntegerValue))) {\r\n\t\treturn tl::unexpected { ParseIntError::OutOfRange };\r\n\t} else {\r\n\t\tIntT fixedValue = integerPart << 6;\r\n\t\tif (isNegative) {\r\n\t\t\tfixedValue -= fractionPart;\r\n\t\t} else {\r\n\t\t\tfixedValue += fractionPart;\r\n\t\t}\r\n\t\treturn fixedValue;\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/paths.cpp",
    "content": "#include \"utils/paths.h\"\r\n\r\n#include <optional>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_filesystem.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_ptrs.h\"\r\n\r\n#ifdef __IPHONEOS__\r\n#include \"platform/ios/ios_paths.h\"\r\n#endif\r\n\r\n#ifdef NXDK\r\n#define NOMINMAX 1\r\n#define WIN32_LEAN_AND_MEAN\r\n#include <windows.h>\r\n#endif\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace paths {\r\n\r\nnamespace {\r\n\r\nstd::optional<std::string> basePath;\r\nstd::optional<std::string> prefPath;\r\nstd::optional<std::string> configPath;\r\nstd::optional<std::string> assetsPath;\r\n\r\nvoid AddTrailingSlash(std::string &path)\r\n{\r\n\tif (!path.empty() && path.back() != DirectorySeparator)\r\n\t\tpath += DirectorySeparator;\r\n}\r\n\r\n[[maybe_unused]] std::string FromSDL(char *s)\r\n{\r\n\tconst SDLUniquePtr<char> pinned(s);\r\n\tstd::string result = (s != nullptr ? s : \"\");\r\n\tif (s == nullptr) {\r\n\t\tLog(\"{}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t}\r\n\treturn result;\r\n}\r\n\r\n#ifdef NXDK\r\nconst std::string &NxdkGetPrefPath()\r\n{\r\n\tstatic const std::string Path = []() {\r\n\t\tconst char *path = \"E:\\\\UDATA\\\\devilutionx\\\\\";\r\n\t\tif (CreateDirectoryA(path, nullptr) == FALSE && ::GetLastError() != ERROR_ALREADY_EXISTS) {\r\n\t\t\tDirErrorDlg(path);\r\n\t\t}\r\n\t\treturn path;\r\n\t}();\r\n\treturn Path;\r\n}\r\n#endif\r\n\r\nstd::string GetSdlBasePath()\r\n{\r\n\tstd::string result;\r\n#if defined(__DJGPP__)\r\n\t// In DOS, use an empty base path.\r\n#elif defined(USE_SDL3)\r\n\tconst char *s = SDL_GetBasePath();\r\n\tif (s == nullptr) {\r\n\t\tLogError(\"{}\", SDL_GetError());\r\n\t\tSDL_ClearError();\r\n\t} else {\r\n\t\tresult = s;\r\n\t}\r\n#else\r\n\tresult = FromSDL(SDL_GetBasePath());\r\n#endif\r\n\treturn result;\r\n}\r\n\r\n} // namespace\r\n\r\nconst std::string &BasePath()\r\n{\r\n\tif (!basePath) {\r\n\t\tbasePath = GetSdlBasePath();\r\n\t}\r\n\treturn *basePath;\r\n}\r\n\r\nconst std::string &PrefPath()\r\n{\r\n\tif (!prefPath) {\r\n#if defined(__DJGPP__)\r\n\t\tprefPath = std::string();\r\n#elif defined(__IPHONEOS__)\r\n\t\tprefPath = FromSDL(IOSGetPrefPath());\r\n#elif defined(NXDK)\r\n\t\tprefPath = NxdkGetPrefPath();\r\n#else\r\n\t\tprefPath = FromSDL(SDL_GetPrefPath(\"diasurgical\", \"devilution\"));\r\n#if !defined(__amigaos__) && !defined(__DJGPP__)\r\n\t\tif (FileExistsAndIsWriteable(\"diablo.ini\")) {\r\n\t\t\tprefPath = std::string();\r\n\t\t}\r\n#endif\r\n#endif\r\n\t}\r\n\treturn *prefPath;\r\n}\r\n\r\nconst std::string &ConfigPath()\r\n{\r\n\tif (!configPath) {\r\n#if defined(__DJGPP__)\r\n\t\tconfigPath = std::string();\r\n#elif defined(__IPHONEOS__)\r\n\t\tconfigPath = FromSDL(IOSGetPrefPath());\r\n#elif defined(NXDK)\r\n\t\tconfigPath = NxdkGetPrefPath();\r\n#else\r\n\t\tconfigPath = FromSDL(SDL_GetPrefPath(\"diasurgical\", \"devilution\"));\r\n#if !defined(__amigaos__) && !defined(__DJGPP__)\r\n\t\tif (FileExistsAndIsWriteable(\"diablo.ini\")) {\r\n\t\t\tconfigPath = std::string();\r\n\t\t}\r\n#endif\r\n#endif\r\n\t}\r\n\treturn *configPath;\r\n}\r\n\r\nconst std::string &AssetsPath()\r\n{\r\n\tif (!assetsPath) {\r\n#if __EMSCRIPTEN__ || defined(__DJGPP__)\r\n\t\tassetsPath.emplace(\"assets\" DIRECTORY_SEPARATOR_STR);\r\n#elif defined(NXDK)\r\n\t\tassetsPath.emplace(\"D:\\\\assets\\\\\");\r\n#elif defined(__3DS__) || defined(__SWITCH__)\r\n\t\tassetsPath.emplace(\"romfs:/\");\r\n#elif defined(__APPLE__) && defined(USE_SDL1)\r\n\t\t// In `Info.plist` we have\r\n\t\t//\r\n\t\t//    <key>SDL_FILESYSTEM_BASE_DIR_TYPE</key>\r\n\t\t//    <string>resource</string>\r\n\t\t//\r\n\t\t// This means `SDL_GetBasePath()` returns exedir for non-bundled\r\n\t\t// and the `app_dir.app/Resources/` for bundles.\r\n\t\t//\r\n\t\t// Our built-in resources are directly in the `devilutionx.app/Resources` directory\r\n\t\t// and are normally looked up via a relative lookup in `FindAsset`.\r\n\t\t// In SDL2, this is implemented by calling `SDL_OpenFPFromBundleOrFallback`\r\n\t\t// from `SDL_RWFromFile` but SDL1 doesn't do it, so we set the directory explicitly.\r\n\t\t//\r\n\t\t// Note that SDL3 reverts to SDL1 behaviour!\r\n\t\t// https://github.com/libsdl-org/SDL/blob/962268ca21ed10b9cee31198c22681099293f20a/docs/README-migration.md?plain=1#L1623\r\n\t\tassetsPath.emplace(GetSdlBasePath());\r\n#else\r\n\t\tassetsPath.emplace(GetSdlBasePath() + (\"assets\" DIRECTORY_SEPARATOR_STR));\r\n#endif\r\n\t}\r\n\treturn *assetsPath;\r\n}\r\n\r\nvoid SetBasePath(const std::string &path)\r\n{\r\n\tbasePath = path;\r\n\tAddTrailingSlash(*basePath);\r\n}\r\n\r\nvoid SetPrefPath(const std::string &path)\r\n{\r\n\tprefPath = path;\r\n\tAddTrailingSlash(*prefPath);\r\n}\r\n\r\nvoid SetConfigPath(const std::string &path)\r\n{\r\n\tconfigPath = path;\r\n\tAddTrailingSlash(*configPath);\r\n}\r\n\r\nvoid SetAssetsPath(const std::string &path)\r\n{\r\n\tassetsPath = path;\r\n\tAddTrailingSlash(*assetsPath);\r\n}\r\n\r\n} // namespace paths\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/paths.h",
    "content": "#pragma once\r\n\r\n#include <string>\r\n\r\nnamespace devilution {\r\n\r\nnamespace paths {\r\n\r\nconst std::string &BasePath();\r\nconst std::string &PrefPath();\r\nconst std::string &ConfigPath();\r\nconst std::string &AssetsPath();\r\n\r\nvoid SetBasePath(const std::string &path);\r\nvoid SetPrefPath(const std::string &path);\r\nvoid SetConfigPath(const std::string &path);\r\nvoid SetAssetsPath(const std::string &path);\r\n\r\n} // namespace paths\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/pcx.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\nstruct PCXHeader {\r\n\tuint8_t Manufacturer;\r\n\tuint8_t Version;\r\n\tuint8_t Encoding;\r\n\tuint8_t BitsPerPixel;\r\n\tuint16_t Xmin;\r\n\tuint16_t Ymin;\r\n\tuint16_t Xmax;\r\n\tuint16_t Ymax;\r\n\tuint16_t HDpi;\r\n\tuint16_t VDpi;\r\n\tuint8_t Colormap[48];\r\n\tuint8_t Reserved;\r\n\tuint8_t NPlanes;\r\n\tuint16_t BytesPerLine;\r\n\tuint16_t PaletteInfo;\r\n\tuint16_t HscreenSize;\r\n\tuint16_t VscreenSize;\r\n\tuint8_t Filler[54];\r\n};\r\n\r\nstatic constexpr size_t PcxHeaderSize = 128;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/pcx_to_clx.cpp",
    "content": "#include \"utils/pcx_to_clx.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n\r\n#include <array>\r\n#include <memory>\r\n#include <optional>\r\n#include <vector>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/clx_encode.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n#include \"utils/pcx.hpp\"\r\n\r\n#ifdef DEBUG_PCX_TO_CL2_SIZE\r\n#include <iomanip>\r\n#include <iostream>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nsize_t GetReservationSize(size_t pcxSize)\r\n{\r\n\t// For the most part, CL2 is smaller than PCX, with a few exceptions.\r\n\tswitch (pcxSize) {\r\n\tcase 2352187: // ui_art\\hf_logo1.pcx\r\n\t\treturn 2464867;\r\n\tcase 172347: // ui_art\\creditsw.pcx\r\n\t\treturn 172347;\r\n\tcase 157275: // ui_art\\credits.pcx\r\n\t\treturn 173367;\r\n\tdefault:\r\n\t\treturn pcxSize;\r\n\t}\r\n}\r\n\r\nbool LoadPcxMeta(AssetHandle &handle, int &width, int &height, uint8_t &bpp)\r\n{\r\n\tPCXHeader pcxhdr;\r\n\tif (!handle.read(&pcxhdr, PcxHeaderSize)) {\r\n\t\treturn false;\r\n\t}\r\n\twidth = Swap16LE(pcxhdr.Xmax) - Swap16LE(pcxhdr.Xmin) + 1;\r\n\theight = Swap16LE(pcxhdr.Ymax) - Swap16LE(pcxhdr.Ymin) + 1;\r\n\tbpp = pcxhdr.BitsPerPixel;\r\n\treturn true;\r\n}\r\n\r\n} // namespace\r\n\r\nOptionalOwnedClxSpriteList PcxToClx(AssetHandle &handle, size_t fileSize, int numFramesOrFrameHeight, std::optional<uint8_t> transparentColor, SDL_Color *outPalette)\r\n{\r\n\tint width;\r\n\tint height;\r\n\tuint8_t bpp;\r\n\tif (!LoadPcxMeta(handle, width, height, bpp)) {\r\n\t\treturn std::nullopt;\r\n\t}\r\n\tassert(bpp == 8);\r\n\r\n\tunsigned numFrames;\r\n\tunsigned frameHeight;\r\n\tif (numFramesOrFrameHeight > 0) {\r\n\t\tnumFrames = numFramesOrFrameHeight;\r\n\t\tframeHeight = height / numFrames;\r\n\t} else {\r\n\t\tframeHeight = -numFramesOrFrameHeight;\r\n\t\tnumFrames = height / frameHeight;\r\n\t}\r\n\r\n\tsize_t pixelDataSize = fileSize;\r\n\tif (pixelDataSize <= PcxHeaderSize) {\r\n\t\treturn std::nullopt;\r\n\t}\r\n\tpixelDataSize -= PcxHeaderSize;\r\n\r\n\tstd::unique_ptr<uint8_t[]> fileBuffer { new uint8_t[pixelDataSize] };\r\n\tif (handle.read(fileBuffer.get(), pixelDataSize) == 0) {\r\n\t\treturn std::nullopt;\r\n\t}\r\n\r\n\t// CLX header: frame count, frame offset for each frame, file size\r\n\tstd::vector<uint8_t> cl2Data;\r\n\tcl2Data.reserve(GetReservationSize(pixelDataSize));\r\n\tcl2Data.resize(4 * (2 + static_cast<size_t>(numFrames)));\r\n\tWriteLE32(cl2Data.data(), numFrames);\r\n\r\n\t// We process the PCX a whole frame at a time because the lines are reversed in CEL.\r\n\tauto frameBuffer = std::unique_ptr<uint8_t[]>(new uint8_t[static_cast<size_t>(frameHeight) * width]);\r\n\r\n\tconst unsigned srcSkip = width % 2;\r\n\tuint8_t *dataPtr = fileBuffer.get();\r\n\tfor (unsigned frame = 1; frame <= numFrames; ++frame) {\r\n\t\tWriteLE32(&cl2Data[4 * static_cast<size_t>(frame)], static_cast<uint32_t>(cl2Data.size()));\r\n\r\n\t\tconst size_t frameHeaderPos = cl2Data.size();\r\n\t\tcl2Data.resize(cl2Data.size() + ClxFrameHeaderSize);\r\n\r\n\t\t// Frame header:\r\n\t\tWriteLE16(&cl2Data[frameHeaderPos], ClxFrameHeaderSize);\r\n\t\tWriteLE16(&cl2Data[frameHeaderPos + 2], static_cast<uint16_t>(width));\r\n\t\tWriteLE16(&cl2Data[frameHeaderPos + 4], static_cast<uint16_t>(frameHeight));\r\n\r\n\t\tfor (unsigned j = 0; j < frameHeight; ++j) {\r\n\t\t\tuint8_t *buffer = &frameBuffer[static_cast<size_t>(j) * width];\r\n\t\t\tfor (unsigned x = 0; x < static_cast<unsigned>(width);) {\r\n\t\t\t\tconstexpr uint8_t PcxMaxSinglePixel = 0xBF;\r\n\t\t\t\tconst uint8_t byte = *dataPtr++;\r\n\t\t\t\tif (byte <= PcxMaxSinglePixel) {\r\n\t\t\t\t\t*buffer++ = byte;\r\n\t\t\t\t\t++x;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tconstexpr uint8_t PcxRunLengthMask = 0x3F;\r\n\t\t\t\tconst uint8_t runLength = (byte & PcxRunLengthMask);\r\n\t\t\t\tstd::memset(buffer, *dataPtr++, runLength);\r\n\t\t\t\tbuffer += runLength;\r\n\t\t\t\tx += runLength;\r\n\t\t\t}\r\n\t\t\tdataPtr += srcSkip;\r\n\t\t}\r\n\r\n\t\tunsigned transparentRunWidth = 0;\r\n\t\tsize_t line = 0;\r\n\t\twhile (line != frameHeight) {\r\n\t\t\t// Process line:\r\n\t\t\tconst uint8_t *src = &frameBuffer[(frameHeight - (line + 1)) * width];\r\n\t\t\tif (transparentColor) {\r\n\t\t\t\tunsigned solidRunWidth = 0;\r\n\t\t\t\tfor (const uint8_t *srcEnd = src + width; src != srcEnd; ++src) {\r\n\t\t\t\t\tif (*src == *transparentColor) {\r\n\t\t\t\t\t\tif (solidRunWidth != 0) {\r\n\t\t\t\t\t\t\tAppendClxPixelsOrFillRun(src - transparentRunWidth - solidRunWidth, solidRunWidth, cl2Data);\r\n\t\t\t\t\t\t\tsolidRunWidth = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t++transparentRunWidth;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tAppendClxTransparentRun(transparentRunWidth, cl2Data);\r\n\t\t\t\t\t\ttransparentRunWidth = 0;\r\n\t\t\t\t\t\t++solidRunWidth;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (solidRunWidth != 0) {\r\n\t\t\t\t\tAppendClxPixelsOrFillRun(src - solidRunWidth, solidRunWidth, cl2Data);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tAppendClxPixelsOrFillRun(src, width, cl2Data);\r\n\t\t\t}\r\n\t\t\t++line;\r\n\t\t}\r\n\t\tAppendClxTransparentRun(transparentRunWidth, cl2Data);\r\n\t}\r\n\tWriteLE32(&cl2Data[4 * (1 + static_cast<size_t>(numFrames))], static_cast<uint32_t>(cl2Data.size()));\r\n\r\n\tif (outPalette != nullptr) {\r\n\t\t[[maybe_unused]] constexpr unsigned PcxPaletteSeparator = 0x0C;\r\n\t\tassert(*dataPtr == PcxPaletteSeparator); // PCX may not have a palette\r\n\t\t++dataPtr;\r\n\r\n\t\tfor (unsigned i = 0; i < 256; ++i) {\r\n\t\t\toutPalette->r = *dataPtr++;\r\n\t\t\toutPalette->g = *dataPtr++;\r\n\t\t\toutPalette->b = *dataPtr++;\r\n#ifndef USE_SDL1\r\n\t\t\toutPalette->a = SDL_ALPHA_OPAQUE;\r\n#endif\r\n\t\t\t++outPalette;\r\n\t\t}\r\n\t}\r\n\r\n\t// Release buffers before allocating the result array to reduce peak memory use.\r\n\tframeBuffer = nullptr;\r\n\tfileBuffer = nullptr;\r\n\r\n\tauto out = std::unique_ptr<uint8_t[]>(new uint8_t[cl2Data.size()]);\r\n\tmemcpy(&out[0], cl2Data.data(), cl2Data.size());\r\n#ifdef DEBUG_PCX_TO_CL2_SIZE\r\n\tstd::cout << \"\\t\" << pixelDataSize << \"\\t\" << cl2Data.size() << \"\\t\" << std::setprecision(1) << std::fixed << (static_cast<int>(cl2Data.size()) - static_cast<int>(pixelDataSize)) / ((float)pixelDataSize) * 100 << \"%\" << std::endl;\r\n#endif\r\n\treturn OwnedClxSpriteList { std::move(out) };\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/pcx_to_clx.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Loads a PCX file as a CLX sprite.\r\n *\r\n * @param handle A non-null SDL_RWops handle. Closed by this function.\r\n * @param numFramesOrFrameHeight Pass a positive value with the number of frames, or the frame height as a negative value.\r\n * @param transparentColor The PCX palette index of the transparent color.\r\n */\r\nOptionalOwnedClxSpriteList PcxToClx(AssetHandle &handle, size_t fileSize, int numFramesOrFrameHeight = 1, std::optional<uint8_t> transparentColor = std::nullopt, SDL_Color *outPalette = nullptr);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/png.h",
    "content": "#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#include <SDL3_image/SDL_image.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/assets.hpp\"\r\n\r\n#ifndef USE_SDL3\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\nconst int IMG_INIT_PNG = 0x00000002;\r\n\r\nint IMG_Init(int flags);\r\nvoid IMG_Quit(void);\r\nint IMG_isPNG(SDL_RWops *src);\r\nSDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src);\r\nint IMG_SavePNG(SDL_Surface *surface, const char *file);\r\nint IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst);\r\n\r\ninline SDL_Surface *IMG_LoadPNG(const char *file)\r\n{\r\n\tSDL_RWops *src = SDL_RWFromFile(file, \"rb\");\r\n\treturn IMG_LoadPNG_RW(src);\r\n}\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n#ifndef USE_SDL3\r\ninline int InitPNG()\r\n{\r\n\treturn IMG_Init(IMG_INIT_PNG);\r\n}\r\n\r\ninline void QuitPNG()\r\n{\r\n\tIMG_Quit();\r\n}\r\n#endif\r\n\r\ninline SDL_Surface *LoadPNG(const char *file)\r\n{\r\n\tauto *rwops = OpenAssetAsSdlRwOps(file);\r\n#ifdef USE_SDL3\r\n\tSDL_Surface *surface = IMG_LoadPNG_IO(rwops);\r\n\tSDL_CloseIO(rwops);\r\n#else\r\n\tSDL_Surface *surface = IMG_LoadPNG_RW(rwops);\r\n\tSDL_RWclose(rwops);\r\n#endif\r\n\treturn surface;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/pointer_value_union.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief A tagged union of a pointer and a value in the space of a single pointer.\r\n *\r\n * Requires the type T to have alignment > 1.\r\n * Internally, uses the last bit to hold the tag:\r\n * 0 if it is a pointer, guaranteed by T's alignment requirements.\r\n * 1 if it is a value.\r\n */\r\ntemplate <typename T>\r\nclass PointerOrValue {\r\n\tstatic_assert(alignof(T) > 1, \"requires alignof > 1\");\r\n\tstatic_assert(sizeof(T) < sizeof(T *), \"type too large\");\r\n\r\npublic:\r\n\texplicit PointerOrValue(const T *ptr)\r\n\t    : repr_(reinterpret_cast<uintptr_t>(ptr))\r\n\t{\r\n\t}\r\n\r\n\texplicit PointerOrValue(T val)\r\n\t    : repr_((static_cast<uintptr_t>(val) << 1) | 1)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] bool HoldsPointer() const\r\n\t{\r\n\t\treturn (repr_ & 1) == 0;\r\n\t}\r\n\r\n\t[[nodiscard]] const T *AsPointer() const\r\n\t{\r\n\t\treturn reinterpret_cast<const T *>(repr_);\r\n\t}\r\n\r\n\t[[nodiscard]] T AsValue() const\r\n\t{\r\n\t\treturn static_cast<T>(repr_ >> 1);\r\n\t}\r\n\r\nprivate:\r\n\tuintptr_t repr_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/push_aulib_decoder.cpp",
    "content": "#include \"push_aulib_decoder.h\"\r\n\r\n#include <algorithm>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <limits>\r\n#include <mutex>\r\n#include <type_traits>\r\n#include <variant>\r\n\r\n#include <aulib.h>\r\n\r\n#include \"appfat.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nfloat SampleToFloat(int16_t sample)\r\n{\r\n\tconstexpr float Factor = 1.0F / (std::numeric_limits<int16_t>::max() + 1);\r\n\treturn sample * Factor;\r\n}\r\n\r\nfloat SampleToFloat(uint8_t sample)\r\n{\r\n\tconstexpr float Factor = 2.0F / std::numeric_limits<uint8_t>::max();\r\n\treturn (sample * Factor) - 1;\r\n}\r\n\r\ntemplate <typename T>\r\nvoid ToFloats(const T *samples, float *out, unsigned count)\r\n{\r\n\tstd::transform(samples, samples + count, out, [](T sample) {\r\n\t\treturn SampleToFloat(sample);\r\n\t});\r\n}\r\n\r\n} // namespace\r\n\r\nvoid PushAulibDecoder::DiscardPendingSamples() noexcept\r\n{\r\n\tconst auto lock = std::lock_guard(queue_mutex_);\r\n\tqueue_ = std::queue<AudioQueueItem>();\r\n}\r\n\r\nbool PushAulibDecoder::open([[maybe_unused]] SDL_IOStream *rwops)\r\n{\r\n\tassert(rwops == nullptr);\r\n\treturn true;\r\n}\r\n\r\nbool PushAulibDecoder::rewind()\r\n{\r\n\treturn false;\r\n}\r\n\r\nstd::chrono::microseconds PushAulibDecoder::duration() const\r\n{\r\n\treturn {};\r\n}\r\n\r\nbool PushAulibDecoder::seekToTime([[maybe_unused]] std::chrono::microseconds pos)\r\n{\r\n\treturn false;\r\n}\r\n\r\nint PushAulibDecoder::doDecoding(float buf[], int len, bool &callAgain)\r\n{\r\n\tcallAgain = false;\r\n\r\n\tconstexpr auto WriteFloats = [](PushAulibDecoder::AudioQueueItem &item, float *out, unsigned count) {\r\n\t\tstd::visit([&](const auto &samples) { ToFloats(&samples[item.pos], out, count); }, item.data);\r\n\t};\r\n\r\n\tunsigned remaining = len;\r\n\t{\r\n\t\tconst auto lock = std::lock_guard(queue_mutex_);\r\n\t\tAudioQueueItem *item;\r\n\t\twhile ((item = Next()) != nullptr) {\r\n\t\t\tif (static_cast<unsigned>(remaining) <= item->len) {\r\n\t\t\t\tWriteFloats(*item, buf, remaining);\r\n\t\t\t\titem->pos += remaining;\r\n\t\t\t\titem->len -= remaining;\r\n\t\t\t\tif (item->len == 0)\r\n\t\t\t\t\tqueue_.pop();\r\n\t\t\t\treturn len;\r\n\t\t\t}\r\n\r\n\t\t\tWriteFloats(*item, buf, item->len);\r\n\t\t\tbuf += item->len;\r\n\t\t\tremaining -= static_cast<int>(item->len);\r\n\t\t\tqueue_.pop();\r\n\t\t}\r\n\t}\r\n\tstd::memset(buf, 0, remaining * sizeof(buf[0]));\r\n\treturn len;\r\n}\r\n\r\nPushAulibDecoder::AudioQueueItem *PushAulibDecoder::Next()\r\n{\r\n\twhile (!queue_.empty() && queue_.front().len == 0)\r\n\t\tqueue_.pop();\r\n\tif (queue_.empty())\r\n\t\treturn nullptr;\r\n\treturn &queue_.front();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/push_aulib_decoder.h",
    "content": "#pragma once\r\n\r\n#include <chrono>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <memory>\r\n#include <mutex>\r\n#include <queue>\r\n#include <variant>\r\n\r\n#include <Aulib/Decoder.h>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_mutex.h>\r\n#else\r\n#include <SDL_mutex.h>\r\n#endif\r\n\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_mutex.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief A Decoder interface implementations that simply has the samples pushed into it by the user.\r\n */\r\nclass PushAulibDecoder final : public ::Aulib::Decoder {\r\npublic:\r\n\tPushAulibDecoder(int numChannels, int sampleRate)\r\n\t    : numChannels_(numChannels)\r\n\t    , sampleRate_(sampleRate)\r\n\t{\r\n\t}\r\n\r\n\ttemplate <typename T>\r\n\tvoid PushSamples(const T *data, unsigned size) noexcept\r\n\t{\r\n\t\tAudioQueueItem item { data, size };\r\n\t\tconst auto lock = std::lock_guard(queue_mutex_);\r\n\t\tqueue_.push(std::move(item));\r\n\t}\r\n\r\n\tvoid DiscardPendingSamples() noexcept;\r\n\r\n\tbool open(SDL_IOStream *rwops) override;\r\n\r\n\t[[nodiscard]] int getChannels() const override\r\n\t{\r\n\t\treturn numChannels_;\r\n\t}\r\n\r\n\t[[nodiscard]] int getRate() const override\r\n\t{\r\n\t\treturn sampleRate_;\r\n\t}\r\n\r\n\tbool rewind() override;\r\n\t[[nodiscard]] std::chrono::microseconds duration() const override;\r\n\tbool seekToTime(std::chrono::microseconds pos) override;\r\n\r\nprotected:\r\n\tint doDecoding(float buf[], int len, bool &callAgain) override;\r\n\r\nprivate:\r\n\tstruct AudioQueueItem {\r\n\t\tstd::variant<\r\n\t\t    std::unique_ptr<int16_t[]>,\r\n\t\t    std::unique_ptr<uint8_t[]>>\r\n\t\t    data;\r\n\t\tunsigned len;\r\n\t\tunsigned pos;\r\n\r\n\t\ttemplate <typename T>\r\n\t\tAudioQueueItem(const T *data, unsigned size)\r\n\t\t    : data { std::unique_ptr<T[]> { new T[size] } }\r\n\t\t    , len { size }\r\n\t\t    , pos { 0 }\r\n\t\t{\r\n\t\t\tstd::memcpy(std::get<std::unique_ptr<T[]>>(this->data).get(), data, size * sizeof(T));\r\n\t\t}\r\n\t};\r\n\r\n\tconst int numChannels_;\r\n\tconst int sampleRate_;\r\n\r\n\t// Requires holding the queue_mutex_.\r\n\tAudioQueueItem *Next();\r\n\r\n\tstd::queue<AudioQueueItem> queue_;\r\n\tSdlMutex queue_mutex_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/screen_reader.cpp",
    "content": "#include \"utils/screen_reader.hpp\"\r\n\r\n#include <string>\r\n#include <string_view>\r\n\r\n#ifdef _WIN32\r\n#include \"utils/file_util.h\"\r\n#include <Tolk.h>\r\n#else\r\n#include <speech-dispatcher/libspeechd.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n#ifndef _WIN32\r\nSPDConnection *Speechd;\r\n#endif\r\n\r\nvoid InitializeScreenReader()\r\n{\r\n#ifdef _WIN32\r\n\tTolk_Load();\r\n#else\r\n\tSpeechd = spd_open(\"DevilutionX\", \"DevilutionX\", NULL, SPD_MODE_SINGLE);\r\n#endif\r\n}\r\n\r\nvoid ShutDownScreenReader()\r\n{\r\n#ifdef _WIN32\r\n\tTolk_Unload();\r\n#else\r\n\tspd_close(Speechd);\r\n#endif\r\n}\r\n\r\nvoid SpeakText(std::string_view text, bool force)\r\n{\r\n\tstatic std::string SpokenText;\r\n\r\n\tif (!force && SpokenText == text)\r\n\t\treturn;\r\n\r\n\tSpokenText = text;\r\n\r\n#ifdef _WIN32\r\n\tconst auto textUtf16 = ToWideChar(SpokenText);\r\n\tif (textUtf16 != nullptr)\r\n\t\tTolk_Output(textUtf16.get(), true);\r\n#else\r\n\tspd_say(Speechd, SPD_TEXT, SpokenText.c_str());\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/screen_reader.hpp",
    "content": "#pragma once\r\n\r\n#include <string_view>\r\n\r\nnamespace devilution {\r\n\r\n#ifdef SCREEN_READER_INTEGRATION\r\nvoid InitializeScreenReader();\r\nvoid ShutDownScreenReader();\r\nvoid SpeakText(std::string_view text, bool force = false);\r\n#else\r\nconstexpr void InitializeScreenReader()\r\n{\r\n}\r\n\r\nconstexpr void ShutDownScreenReader()\r\n{\r\n}\r\n\r\nconstexpr void SpeakText(std::string_view text, bool force = false)\r\n{\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl2_backports.h",
    "content": "#pragma once\r\n// Backports for older versions of SDL 2.\r\n\r\n#include <SDL.h>\r\n\r\n#ifndef SDL_MAX_UINT32\r\n#define SDL_MAX_UINT32 ((Uint32)0xFFFFFFFFu)\r\n#endif\r\n\r\n#if !SDL_VERSION_ATLEAST(2, 0, 4)\r\ninline SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r)\r\n{\r\n\treturn ((p->x >= r->x) && (p->x < (r->x + r->w))\r\n\t           && (p->y >= r->y) && (p->y < (r->y + r->h)))\r\n\t    ? SDL_TRUE\r\n\t    : SDL_FALSE;\r\n}\r\n#endif\r\n\r\n#if !SDL_VERSION_ATLEAST(2, 0, 5)\r\ninline SDL_Surface *\r\nSDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth,\r\n    Uint32 format)\r\n{\r\n\tint bpp;\r\n\tUint32 rmask, gmask, bmask, amask;\r\n\tif (!SDL_PixelFormatEnumToMasks(format, &bpp, &rmask, &gmask, &bmask, &amask))\r\n\t\treturn NULL;\r\n\treturn SDL_CreateRGBSurface(flags, width, height, bpp, rmask, gmask, bmask, amask);\r\n}\r\n\r\n// From SDL 2.0.9.\r\ninline SDL_Surface *\r\nSDL_CreateRGBSurfaceWithFormatFrom(void *pixels,\r\n    int width, int height, int depth, int pitch,\r\n    Uint32 format)\r\n{\r\n\tSDL_Surface *surface;\r\n\r\n\tsurface = SDL_CreateRGBSurfaceWithFormat(0, 0, 0, depth, format);\r\n\tif (surface != NULL) {\r\n\t\tsurface->flags |= SDL_PREALLOC;\r\n\t\tsurface->pixels = pixels;\r\n\t\tsurface->w = width;\r\n\t\tsurface->h = height;\r\n\t\tsurface->pitch = pitch;\r\n\t\tSDL_SetClipRect(surface, NULL);\r\n\t}\r\n\treturn surface;\r\n}\r\n#endif\r\n\r\n#if !SDL_VERSION_ATLEAST(2, 0, 14)\r\ninline SDL_bool\r\nSDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button)\r\n{\r\n\tSDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForButton(gamecontroller, button);\r\n\treturn (bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE;\r\n}\r\n#endif\r\n"
  },
  {
    "path": "Source/utils/sdl2_to_1_2_backports.cpp",
    "content": "#include \"utils/sdl2_to_1_2_backports.h\"\r\n\r\n#include <algorithm>\r\n#include <cstddef>\r\n#include <cstring>\r\n#include <string_view>\r\n\r\n#if defined(_WIN32)\r\n#define WIN32_LEAN_AND_MEAN\r\n#define NOMINMAX 1\r\n#ifndef DEVILUTIONX_WINDOWS_NO_WCHAR\r\n#define UNICODE 1\r\n#include <shlobj.h>\r\n#endif\r\n#include <windows.h>\r\n#endif\r\n\r\n#include \"utils/console.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\n#define DEFAULT_PRIORITY SDL_LOG_PRIORITY_CRITICAL\r\n#define DEFAULT_ASSERT_PRIORITY SDL_LOG_PRIORITY_WARN\r\n#define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO\r\n#define DEFAULT_TEST_PRIORITY SDL_LOG_PRIORITY_VERBOSE\r\n\r\nnamespace {\r\n\r\n// We use the same names of these structs as the SDL2 implementation:\r\n// NOLINTNEXTLINE(readability-identifier-naming)\r\nstruct SDL_LogLevel {\r\n\tint category;\r\n\tSDL_LogPriority priority;\r\n\tSDL_LogLevel *next;\r\n};\r\n\r\nSDL_LogLevel *SDL_loglevels;                                             // NOLINT(readability-identifier-naming)\r\nSDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY;                 // NOLINT(readability-identifier-naming)\r\nSDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;           // NOLINT(readability-identifier-naming)\r\nSDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; // NOLINT(readability-identifier-naming)\r\nSDL_LogPriority SDL_test_priority = DEFAULT_TEST_PRIORITY;               // NOLINT(readability-identifier-naming)\r\n\r\n// NOLINTNEXTLINE(readability-identifier-naming)\r\nconst char *const SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {\r\n\tnullptr,\r\n\t\"VERBOSE\",\r\n\t\"DEBUG\",\r\n\t\"INFO\",\r\n\t\"WARN\",\r\n\t\"ERROR\",\r\n\t\"CRITICAL\"\r\n};\r\n\r\n} // namespace\r\n\r\nvoid SDL_LogSetAllPriority(SDL_LogPriority priority)\r\n{\r\n\tfor (SDL_LogLevel *entry = SDL_loglevels; entry != nullptr; entry = entry->next) {\r\n\t\tentry->priority = priority;\r\n\t}\r\n\tSDL_default_priority = priority;\r\n\tSDL_assert_priority = priority;\r\n\tSDL_application_priority = priority;\r\n}\r\n\r\nvoid SDL_LogSetPriority(int category, SDL_LogPriority priority)\r\n{\r\n\tSDL_LogLevel *entry;\r\n\tfor (entry = SDL_loglevels; entry != nullptr; entry = entry->next) {\r\n\t\tif (entry->category == category) {\r\n\t\t\tentry->priority = priority;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tentry = static_cast<SDL_LogLevel *>(SDL_malloc(sizeof(*entry)));\r\n\tif (entry != nullptr) {\r\n\t\tentry->category = category;\r\n\t\tentry->priority = priority;\r\n\t\tentry->next = SDL_loglevels;\r\n\t\tSDL_loglevels = entry;\r\n\t}\r\n}\r\n\r\nSDL_LogPriority SDL_LogGetPriority(int category)\r\n{\r\n\tfor (SDL_LogLevel *entry = SDL_loglevels; entry != nullptr; entry = entry->next) {\r\n\t\tif (entry->category == category) {\r\n\t\t\treturn entry->priority;\r\n\t\t}\r\n\t}\r\n\r\n\tswitch (category) {\r\n\tcase SDL_LOG_CATEGORY_TEST:\r\n\t\treturn SDL_test_priority;\r\n\tcase SDL_LOG_CATEGORY_APPLICATION:\r\n\t\treturn SDL_application_priority;\r\n\tcase SDL_LOG_CATEGORY_ASSERT:\r\n\t\treturn SDL_assert_priority;\r\n\tdefault:\r\n\t\treturn SDL_default_priority;\r\n\t}\r\n}\r\n\r\nvoid SDL_Log(const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogVerbose(int category, const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogDebug(int category, const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogInfo(int category, const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogWarn(int category, const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogError(int category, const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogCritical(int category, const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)\r\n{\r\n\tva_list ap;\r\n\tva_start(ap, fmt);\r\n\tSDL_LogMessageV(category, priority, fmt, ap);\r\n\tva_end(ap);\r\n}\r\n\r\nvoid SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)\r\n{\r\n\tif (static_cast<int>(priority) < 0 || priority >= SDL_NUM_LOG_PRIORITIES || SDL_LogGetPriority(category) > priority)\r\n\t\treturn;\r\n\r\n\t::devilution::printfInConsole(\"%s: \", SDL_priority_prefixes[priority]);\r\n\t::devilution::vprintfInConsole(fmt, ap);\r\n\t::devilution::printNewlineInConsole();\r\n}\r\n\r\nnamespace {\r\n\r\n#define DEFINE_COPY_ROW(name, type)                       \\\r\n\tvoid name(type *src, int src_w, type *dst, int dst_w) \\\r\n\t{                                                     \\\r\n\t\ttype pixel = 0;                                   \\\r\n                                                          \\\r\n\t\tint pos = 0x10000;                                \\\r\n\t\tint inc = (src_w << 16) / dst_w;                  \\\r\n\t\tfor (int i = dst_w; i > 0; i--) {                 \\\r\n\t\t\twhile (pos >= 0x10000L) {                     \\\r\n\t\t\t\tpixel = *src++;                           \\\r\n\t\t\t\tpos -= 0x10000L;                          \\\r\n\t\t\t}                                             \\\r\n\t\t\t*dst++ = pixel;                               \\\r\n\t\t\tpos += inc;                                   \\\r\n\t\t}                                                 \\\r\n\t}\r\nDEFINE_COPY_ROW(copy_row1, Uint8)\r\nDEFINE_COPY_ROW(copy_row2, Uint16)\r\nDEFINE_COPY_ROW(copy_row4, Uint32)\r\n\r\nvoid copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w)\r\n{\r\n\tUint8 pixel[3] = { 0, 0, 0 };\r\n\r\n\tint pos = 0x10000;\r\n\tint inc = (src_w << 16) / dst_w;\r\n\tfor (int i = dst_w; i > 0; --i) {\r\n\t\twhile (pos >= 0x10000L) {\r\n\t\t\tpixel[0] = *src++;\r\n\t\t\tpixel[1] = *src++;\r\n\t\t\tpixel[2] = *src++;\r\n\t\t\tpos -= 0x10000L;\r\n\t\t}\r\n\t\t*dst++ = pixel[0];\r\n\t\t*dst++ = pixel[1];\r\n\t\t*dst++ = pixel[2];\r\n\t\tpos += inc;\r\n\t}\r\n}\r\n\r\n} // namespace\r\n\r\nint SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect,\r\n    SDL_Surface *dst, const SDL_Rect *dstrect)\r\n{\r\n\t// All the ASM support has been removed, as the platforms that the ASM\r\n\t// implementation exists for support SDL2 anyway.\r\n\tint src_locked;\r\n\tint dst_locked;\r\n\tint pos, inc;\r\n\tint dst_maxrow;\r\n\tint src_row, dst_row;\r\n\tUint8 *srcp = NULL;\r\n\tUint8 *dstp;\r\n\tSDL_Rect full_src;\r\n\tSDL_Rect full_dst;\r\n\tconst int bpp = dst->format->BytesPerPixel;\r\n\r\n\tif (!SDLBackport_PixelFormatFormatEq(src->format, dst->format)) {\r\n\t\tSDL_SetError(\"Only works with same format surfaces\");\r\n\t\treturn -1;\r\n\t}\r\n\r\n\t/* Verify the blit rectangles */\r\n\tif (srcrect) {\r\n\t\tif ((srcrect->x < 0) || (srcrect->y < 0) || ((srcrect->x + srcrect->w) > src->w) || ((srcrect->y + srcrect->h) > src->h)) {\r\n\t\t\tSDL_SetError(\"Invalid source blit rectangle\");\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t} else {\r\n\t\tfull_src.x = 0;\r\n\t\tfull_src.y = 0;\r\n\t\tfull_src.w = src->w;\r\n\t\tfull_src.h = src->h;\r\n\t\tsrcrect = &full_src;\r\n\t}\r\n\tif (dstrect) {\r\n\t\tif ((dstrect->x < 0) || (dstrect->y < 0) || ((dstrect->x + dstrect->w) > dst->w) || ((dstrect->y + dstrect->h) > dst->h)) {\r\n\t\t\tSDL_SetError(\"Invalid destination blit rectangle\");\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t} else {\r\n\t\tfull_dst.x = 0;\r\n\t\tfull_dst.y = 0;\r\n\t\tfull_dst.w = dst->w;\r\n\t\tfull_dst.h = dst->h;\r\n\t\tdstrect = &full_dst;\r\n\t}\r\n\r\n\t/* Lock the destination if it's in hardware */\r\n\tdst_locked = 0;\r\n\tif (SDL_MUSTLOCK(dst)) {\r\n\t\tif (SDL_LockSurface(dst) < 0) {\r\n\t\t\tSDL_SetError(\"Unable to lock destination surface\");\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tdst_locked = 1;\r\n\t}\r\n\t/* Lock the source if it's in hardware */\r\n\tsrc_locked = 0;\r\n\tif (SDL_MUSTLOCK(src)) {\r\n\t\tif (SDL_LockSurface(src) < 0) {\r\n\t\t\tif (dst_locked) {\r\n\t\t\t\tSDL_UnlockSurface(dst);\r\n\t\t\t}\r\n\t\t\tSDL_SetError(\"Unable to lock source surface\");\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tsrc_locked = 1;\r\n\t}\r\n\r\n\t/* Set up the data... */\r\n\tpos = 0x10000;\r\n\tinc = (srcrect->h << 16) / dstrect->h;\r\n\tsrc_row = srcrect->y;\r\n\tdst_row = dstrect->y;\r\n\r\n\t/* Perform the stretch blit */\r\n\tfor (dst_maxrow = dst_row + dstrect->h; dst_row < dst_maxrow; ++dst_row) {\r\n\t\tdstp = (Uint8 *)dst->pixels + (dst_row * dst->pitch)\r\n\t\t    + (dstrect->x * bpp);\r\n\t\twhile (pos >= 0x10000L) {\r\n\t\t\tsrcp = (Uint8 *)src->pixels + (src_row * src->pitch)\r\n\t\t\t    + (srcrect->x * bpp);\r\n\t\t\t++src_row;\r\n\t\t\tpos -= 0x10000L;\r\n\t\t}\r\n\t\tswitch (bpp) {\r\n\t\tcase 1:\r\n\t\t\tcopy_row1(srcp, srcrect->w, dstp, dstrect->w);\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tcopy_row2((Uint16 *)srcp, srcrect->w,\r\n\t\t\t    (Uint16 *)dstp, dstrect->w);\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tcopy_row3(srcp, srcrect->w, dstp, dstrect->w);\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\t\tcopy_row4((Uint32 *)srcp, srcrect->w,\r\n\t\t\t    (Uint32 *)dstp, dstrect->w);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tpos += inc;\r\n\t}\r\n\r\n\t/* We need to unlock the surfaces if they're locked */\r\n\tif (dst_locked) {\r\n\t\tSDL_UnlockSurface(dst);\r\n\t}\r\n\tif (src_locked) {\r\n\t\tSDL_UnlockSurface(src);\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nint SDL_BlitScaled(SDL_Surface *src, SDL_Rect *srcrect,\r\n    SDL_Surface *dst, SDL_Rect *dstrect)\r\n{\r\n\tif (!SDLBackport_PixelFormatFormatEq(src->format, dst->format) || SDLBackport_IsPixelFormatIndexed(src->format)) {\r\n\t\treturn SDL_BlitSurface(src, srcrect, dst, dstrect);\r\n\t}\r\n\r\n\tfloat src_x0, src_y0, src_x1, src_y1;\r\n\tfloat dst_x0, dst_y0, dst_x1, dst_y1;\r\n\tSDL_Rect final_src, final_dst;\r\n\tfloat scaling_w, scaling_h;\r\n\tint src_w, src_h;\r\n\tint dst_w, dst_h;\r\n\r\n\t/* Make sure the surfaces aren't locked */\r\n\tif (!src || !dst) {\r\n\t\tSDL_SetError(\"SDL_UpperBlitScaled: passed a NULL surface\");\r\n\t\treturn -1;\r\n\t}\r\n\tif (src->locked || dst->locked) {\r\n\t\tSDL_SetError(\"Surfaces must not be locked during blit\");\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tif (NULL == srcrect) {\r\n\t\tsrc_w = src->w;\r\n\t\tsrc_h = src->h;\r\n\t} else {\r\n\t\tsrc_w = srcrect->w;\r\n\t\tsrc_h = srcrect->h;\r\n\t}\r\n\r\n\tif (NULL == dstrect) {\r\n\t\tdst_w = dst->w;\r\n\t\tdst_h = dst->h;\r\n\t} else {\r\n\t\tdst_w = dstrect->w;\r\n\t\tdst_h = dstrect->h;\r\n\t}\r\n\r\n\tif (dst_w == src_w && dst_h == src_h) {\r\n\t\t/* No scaling, defer to regular blit */\r\n\t\treturn SDL_BlitSurface(src, srcrect, dst, dstrect);\r\n\t}\r\n\r\n\tscaling_w = (float)dst_w / src_w;\r\n\tscaling_h = (float)dst_h / src_h;\r\n\r\n\tif (NULL == dstrect) {\r\n\t\tdst_x0 = 0;\r\n\t\tdst_y0 = 0;\r\n\t\tdst_x1 = static_cast<float>(dst_w - 1);\r\n\t\tdst_y1 = static_cast<float>(dst_h - 1);\r\n\t} else {\r\n\t\tdst_x0 = dstrect->x;\r\n\t\tdst_y0 = dstrect->y;\r\n\t\tdst_x1 = dst_x0 + dst_w - 1;\r\n\t\tdst_y1 = dst_y0 + dst_h - 1;\r\n\t}\r\n\r\n\tif (NULL == srcrect) {\r\n\t\tsrc_x0 = 0;\r\n\t\tsrc_y0 = 0;\r\n\t\tsrc_x1 = static_cast<float>(src_w - 1);\r\n\t\tsrc_y1 = static_cast<float>(src_h - 1);\r\n\t} else {\r\n\t\tsrc_x0 = srcrect->x;\r\n\t\tsrc_y0 = srcrect->y;\r\n\t\tsrc_x1 = src_x0 + src_w - 1;\r\n\t\tsrc_y1 = src_y0 + src_h - 1;\r\n\r\n\t\t/* Clip source rectangle to the source surface */\r\n\r\n\t\tif (src_x0 < 0) {\r\n\t\t\tdst_x0 -= src_x0 * scaling_w;\r\n\t\t\tsrc_x0 = 0;\r\n\t\t}\r\n\r\n\t\tif (src_x1 >= src->w) {\r\n\t\t\tdst_x1 -= (src_x1 - src->w + 1) * scaling_w;\r\n\t\t\tsrc_x1 = static_cast<float>(src->w - 1);\r\n\t\t}\r\n\r\n\t\tif (src_y0 < 0) {\r\n\t\t\tdst_y0 -= src_y0 * scaling_h;\r\n\t\t\tsrc_y0 = 0;\r\n\t\t}\r\n\r\n\t\tif (src_y1 >= src->h) {\r\n\t\t\tdst_y1 -= (src_y1 - src->h + 1) * scaling_h;\r\n\t\t\tsrc_y1 = static_cast<float>(src->h - 1);\r\n\t\t}\r\n\t}\r\n\r\n\t/* Clip destination rectangle to the clip rectangle */\r\n\r\n\t/* Translate to clip space for easier calculations */\r\n\tdst_x0 -= dst->clip_rect.x;\r\n\tdst_x1 -= dst->clip_rect.x;\r\n\tdst_y0 -= dst->clip_rect.y;\r\n\tdst_y1 -= dst->clip_rect.y;\r\n\r\n\tif (dst_x0 < 0) {\r\n\t\tsrc_x0 -= dst_x0 / scaling_w;\r\n\t\tdst_x0 = 0;\r\n\t}\r\n\r\n\tif (dst_x1 >= dst->clip_rect.w) {\r\n\t\tsrc_x1 -= (dst_x1 - dst->clip_rect.w + 1) / scaling_w;\r\n\t\tdst_x1 = static_cast<float>(dst->clip_rect.w - 1);\r\n\t}\r\n\r\n\tif (dst_y0 < 0) {\r\n\t\tsrc_y0 -= dst_y0 / scaling_h;\r\n\t\tdst_y0 = 0;\r\n\t}\r\n\r\n\tif (dst_y1 >= dst->clip_rect.h) {\r\n\t\tsrc_y1 -= (dst_y1 - dst->clip_rect.h + 1) / scaling_h;\r\n\t\tdst_y1 = static_cast<float>(dst->clip_rect.h - 1);\r\n\t}\r\n\r\n\t/* Translate back to surface coordinates */\r\n\tdst_x0 += dst->clip_rect.x;\r\n\tdst_x1 += dst->clip_rect.x;\r\n\tdst_y0 += dst->clip_rect.y;\r\n\tdst_y1 += dst->clip_rect.y;\r\n\r\n\tfinal_src.x = static_cast<Sint16>(SDL_floor(src_x0 + 0.5));\r\n\tfinal_src.y = static_cast<Sint16>(SDL_floor(src_y0 + 0.5));\r\n\tsrc_w = std::max(static_cast<int>(SDL_floor(src_x1 + 1 + 0.5)) - static_cast<int>(SDL_floor(src_x0 + 0.5)), 0);\r\n\tsrc_h = std::max(static_cast<int>(SDL_floor(src_y1 + 1 + 0.5)) - static_cast<int>(SDL_floor(src_y0 + 0.5)), 0);\r\n\r\n\tfinal_src.w = static_cast<Uint16>(src_w);\r\n\tfinal_src.h = static_cast<Uint16>(src_h);\r\n\r\n\tfinal_dst.x = static_cast<Sint16>(SDL_floor(dst_x0 + 0.5));\r\n\tfinal_dst.y = static_cast<Sint16>(SDL_floor(dst_y0 + 0.5));\r\n\tdst_w = std::max(static_cast<int>(SDL_floor(dst_x1 - dst_x0 + 1.5)), 0);\r\n\tdst_h = std::max(static_cast<int>(SDL_floor(dst_y1 - dst_y0 + 1.5)), 0);\r\n\r\n\tfinal_dst.w = static_cast<Uint16>(dst_w);\r\n\tfinal_dst.h = static_cast<Uint16>(dst_h);\r\n\r\n\tif (dstrect)\r\n\t\t*dstrect = final_dst;\r\n\r\n\tif (final_dst.w == 0 || final_dst.h == 0 || final_src.w == 0 || final_src.h == 0) {\r\n\t\t/* No-op. */\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn SDL_SoftStretch(src, &final_src, dst, &final_dst);\r\n}\r\n\r\n// = Filesystem\r\n\r\nSint64 SDL_RWsize(SDL_RWops *context)\r\n{\r\n\tconst int current = SDL_RWtell(context);\r\n\tif (current == -1)\r\n\t\treturn -1;\r\n\r\n\tconst int begin = SDL_RWseek(context, 0, RW_SEEK_SET);\r\n\tif (begin == -1)\r\n\t\treturn -1;\r\n\r\n\tconst int end = SDL_RWseek(context, 0, RW_SEEK_END);\r\n\tif (end == -1)\r\n\t\treturn -1;\r\n\r\n\tif (SDL_RWseek(context, current, RW_SEEK_SET) == -1)\r\n\t\treturn -1;\r\n\r\n\treturn end - begin;\r\n}\r\n\r\n#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)\r\n\r\nnamespace {\r\n\r\n// From sdl2-2.0.9/src/core/windows/SDL_windows.h\r\n#define WIN_StringToUTF8(S) SDL_iconv_string(\"UTF-8\", \"UTF-16LE\", (char *)(S), (wcslen(S) + 1) * sizeof(WCHAR))\r\n#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string(\"UTF-16LE\", \"UTF-8\", (char *)(S), SDL_strlen(S) + 1)\r\n\r\n/* Sets an error message based on an HRESULT */\r\nint WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)\r\n{\r\n\t// From sdl2-2.0.9/src/core/windows/SDL_windows.c\r\n\r\n\tTCHAR buffer[1024];\r\n\tchar *message;\r\n\tFormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0,\r\n\t    buffer, SDL_arraysize(buffer), NULL);\r\n\tmessage = WIN_StringToUTF8(buffer);\r\n\tSDL_SetError(\"%s%s%s\", prefix ? prefix : \"\", prefix ? \": \" : \"\", message);\r\n\tSDL_free(message);\r\n\treturn -1;\r\n}\r\n\r\n/* Sets an error message based on GetLastError() */\r\nint WIN_SetError(const char *prefix)\r\n{\r\n\t// From sdl2-2.0.9/src/core/windows/SDL_windows.c\r\n\r\n\treturn WIN_SetErrorFromHRESULT(prefix, GetLastError());\r\n}\r\n\r\n} // namespace\r\n\r\nextern \"C\" char *SDL_GetBasePath(void)\r\n{\r\n\t// From sdl2-2.0.9/src/filesystem/windows/SDL_sysfilesystem.c\r\n\r\n\ttypedef DWORD(WINAPI * GetModuleFileNameExW_t)(HANDLE, HMODULE, LPWSTR, DWORD);\r\n\tGetModuleFileNameExW_t pGetModuleFileNameExW;\r\n\tDWORD buflen = 128;\r\n\tWCHAR *path = NULL;\r\n\tHMODULE psapi = LoadLibrary(L\"psapi.dll\");\r\n\tchar *retval = NULL;\r\n\tDWORD len = 0;\r\n\tint i;\r\n\r\n\tif (!psapi) {\r\n\t\tWIN_SetError(\"Couldn't load psapi.dll\");\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tpGetModuleFileNameExW = (GetModuleFileNameExW_t)GetProcAddress(psapi, \"GetModuleFileNameExW\");\r\n\tif (!pGetModuleFileNameExW) {\r\n\t\tWIN_SetError(\"Couldn't find GetModuleFileNameExW\");\r\n\t\tFreeLibrary(psapi);\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\twhile (SDL_TRUE) {\r\n\t\tvoid *ptr = SDL_realloc(path, buflen * sizeof(WCHAR));\r\n\t\tif (!ptr) {\r\n\t\t\tSDL_free(path);\r\n\t\t\tFreeLibrary(psapi);\r\n\t\t\tSDL_OutOfMemory();\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\r\n\t\tpath = (WCHAR *)ptr;\r\n\r\n\t\tlen = pGetModuleFileNameExW(GetCurrentProcess(), NULL, path, buflen);\r\n\t\tif (len != buflen) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t/* buffer too small? Try again. */\r\n\t\tbuflen *= 2;\r\n\t}\r\n\r\n\tFreeLibrary(psapi);\r\n\r\n\tif (len == 0) {\r\n\t\tSDL_free(path);\r\n\t\tWIN_SetError(\"Couldn't locate our .exe\");\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tfor (i = len - 1; i > 0; i--) {\r\n\t\tif (path[i] == '\\\\') {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tpath[i + 1] = '\\0'; /* chop off filename. */\r\n\r\n\tretval = WIN_StringToUTF8(path);\r\n\tSDL_free(path);\r\n\r\n\treturn retval;\r\n}\r\n\r\nextern \"C\" char *SDL_GetPrefPath(const char *org, const char *app)\r\n{\r\n\t// From sdl2-2.0.9/src/filesystem/windows/SDL_sysfilesystem.c\r\n\r\n\t/*\r\n\t * Vista and later has a new API for this, but SHGetFolderPath works there,\r\n\t *  and apparently just wraps the new API. This is the new way to do it:\r\n\t *\r\n\t *     SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_CREATE,\r\n\t *                          NULL, &wszPath);\r\n\t */\r\n\r\n\tWCHAR path[MAX_PATH];\r\n\tchar *retval = NULL;\r\n\tWCHAR *worg = NULL;\r\n\tWCHAR *wapp = NULL;\r\n\tsize_t new_wpath_len = 0;\r\n\tBOOL api_result = FALSE;\r\n\r\n\tif (!app) {\r\n\t\tSDL_InvalidParamError(\"app\");\r\n\t\treturn NULL;\r\n\t}\r\n\tif (!org) {\r\n\t\torg = \"\";\r\n\t}\r\n\r\n\tif (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) {\r\n\t\tWIN_SetError(\"Couldn't locate our prefpath\");\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tworg = WIN_UTF8ToString(org);\r\n\tif (worg == NULL) {\r\n\t\tSDL_OutOfMemory();\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\twapp = WIN_UTF8ToString(app);\r\n\tif (wapp == NULL) {\r\n\t\tSDL_free(worg);\r\n\t\tSDL_OutOfMemory();\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tnew_wpath_len = lstrlenW(worg) + lstrlenW(wapp) + lstrlenW(path) + 3;\r\n\r\n\tif ((new_wpath_len + 1) > MAX_PATH) {\r\n\t\tSDL_free(worg);\r\n\t\tSDL_free(wapp);\r\n\t\tWIN_SetError(\"Path too long.\");\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tif (*worg) {\r\n\t\tlstrcatW(path, L\"\\\\\");\r\n\t\tlstrcatW(path, worg);\r\n\t}\r\n\tSDL_free(worg);\r\n\r\n\tapi_result = CreateDirectoryW(path, NULL);\r\n\tif (api_result == FALSE) {\r\n\t\tif (GetLastError() != ERROR_ALREADY_EXISTS) {\r\n\t\t\tSDL_free(wapp);\r\n\t\t\tWIN_SetError(\"Couldn't create a prefpath.\");\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n\r\n\tlstrcatW(path, L\"\\\\\");\r\n\tlstrcatW(path, wapp);\r\n\tSDL_free(wapp);\r\n\r\n\tapi_result = CreateDirectoryW(path, NULL);\r\n\tif (api_result == FALSE) {\r\n\t\tif (GetLastError() != ERROR_ALREADY_EXISTS) {\r\n\t\t\tWIN_SetError(\"Couldn't create a prefpath.\");\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n\r\n\tlstrcatW(path, L\"\\\\\");\r\n\r\n\tretval = WIN_StringToUTF8(path);\r\n\r\n\treturn retval;\r\n}\r\n\r\n// For Apple, definitions are in Source/platform/macos_sdl1/SDL_filesystem.m\r\n#elif !defined(__APPLE__)\r\n\r\nnamespace {\r\n#if !defined(__QNXNTO__) && !defined(__amigaos__) && !(defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0))\r\nchar *readSymLink(const char *path)\r\n{\r\n\t// From sdl2-2.0.9/src/filesystem/unix/SDL_sysfilesystem.c\r\n\tchar *retval = NULL;\r\n\tssize_t len = 64;\r\n\tssize_t rc = -1;\r\n\r\n\twhile (1) {\r\n\t\tchar *ptr = (char *)SDL_realloc(retval, (size_t)len);\r\n\t\tif (ptr == NULL) {\r\n\t\t\tSDL_OutOfMemory();\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tretval = ptr;\r\n\r\n\t\trc = readlink(path, retval, len);\r\n\t\tif (rc == -1) {\r\n\t\t\tbreak; /* not a symlink, i/o error, etc. */\r\n\t\t} else if (rc < len) {\r\n\t\t\tretval[rc] = '\\0'; /* readlink doesn't null-terminate. */\r\n\t\t\treturn retval;     /* we're good to go. */\r\n\t\t}\r\n\r\n\t\tlen *= 2; /* grow buffer, try again. */\r\n\t}\r\n\r\n\tSDL_free(retval);\r\n\treturn NULL;\r\n}\r\n#endif\r\n} // namespace\r\n\r\nextern \"C\" char *SDL_GetBasePath()\r\n{\r\n\t// From sdl2-2.0.9/src/filesystem/unix/SDL_sysfilesystem.c\r\n\r\n\tchar *retval = NULL;\r\n\r\n#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)\r\n\tTCHAR buffer[MAX_PATH] = { 0 };\r\n\tGetModuleFileName(NULL, buffer, MAX_PATH);\r\n\tsize_t len = std::string_view(buffer).size();\r\n\twhile (len > 0) {\r\n\t\tif (buffer[len - 1] == '\\\\') {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t--len;\r\n\t}\r\n\tbuffer[len] = '\\0';\r\n\tretval = static_cast<char *>(SDL_malloc(len + 1));\r\n\tif (!retval) {\r\n\t\tSDL_OutOfMemory();\r\n\t\treturn NULL;\r\n\t}\r\n\tSDL_memcpy(retval, buffer, len + 1);\r\n#elif defined(__FREEBSD__)\r\n\tchar fullpath[PATH_MAX];\r\n\tsize_t buflen = sizeof(fullpath);\r\n\tconst int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };\r\n\tif (sysctl(mib, SDL_arraysize(mib), fullpath, &buflen, NULL, 0) != -1) {\r\n\t\tretval = SDL_strdup(fullpath);\r\n\t\tif (!retval) {\r\n\t\t\tSDL_OutOfMemory();\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n#elif defined(__OPENBSD__)\r\n\tchar **retvalargs;\r\n\tsize_t len;\r\n\tconst int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };\r\n\tif (sysctl(mib, 4, NULL, &len, NULL, 0) != -1) {\r\n\t\tretvalargs = SDL_malloc(len);\r\n\t\tif (!retvalargs) {\r\n\t\t\tSDL_OutOfMemory();\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t\tsysctl(mib, 4, retvalargs, &len, NULL, 0);\r\n\t\tretval = SDL_malloc(PATH_MAX + 1);\r\n\t\tif (retval)\r\n\t\t\trealpath(retvalargs[0], retval);\r\n\r\n\t\tSDL_free(retvalargs);\r\n\t}\r\n#elif defined(__SOLARIS__)\r\n\tconst char *path = getexecname();\r\n\tif ((path != NULL) && (path[0] == '/')) { /* must be absolute path... */\r\n\t\tretval = SDL_strdup(path);\r\n\t\tif (!retval) {\r\n\t\t\tSDL_OutOfMemory();\r\n\t\t\treturn NULL;\r\n\t\t}\r\n\t}\r\n#elif defined(__3DS__)\r\n\tretval = SDL_strdup(\"file:sdmc:/3ds/devilutionx/\");\r\n#elif defined(__amigaos__)\r\n\tretval = SDL_strdup(\"PROGDIR:\");\r\n#else\r\n\r\n\t/* is a Linux-style /proc filesystem available? */\r\n\tif (!retval && (access(\"/proc\", F_OK) == 0)) {\r\n\t\t/* !!! FIXME: after 2.0.6 ships, let's delete this code and just\r\n\t\t              use the /proc/%llu version. There's no reason to have\r\n\t\t              two copies of this plus all the #ifdefs. --ryan. */\r\n#if defined(__FREEBSD__)\r\n\t\tretval = readSymLink(\"/proc/curproc/file\");\r\n#elif defined(__NETBSD__)\r\n\t\tretval = readSymLink(\"/proc/curproc/exe\");\r\n#elif defined(__QNXNTO__)\r\n\t\tretval = SDL_LoadFile(\"/proc/self/exefile\", NULL);\r\n#else\r\n\t\tretval = readSymLink(\"/proc/self/exe\"); /* linux. */\r\n\t\tif (retval == NULL) {\r\n\t\t\t/* older kernels don't have /proc/self ... try PID version... */\r\n\t\t\tchar path[64];\r\n\t\t\tconst int rc = (int)SDL_snprintf(path, sizeof(path),\r\n\t\t\t    \"/proc/%llu/exe\",\r\n\t\t\t    (unsigned long long)getpid());\r\n\t\t\tif ((rc > 0) && (static_cast<std::size_t>(rc) < sizeof(path))) {\r\n\t\t\t\tretval = readSymLink(path);\r\n\t\t\t}\r\n\t\t}\r\n#endif\r\n\t}\r\n\r\n\t/* If we had access to argv[0] here, we could check it for a path,\r\n\t    or troll through $PATH looking for it, too. */\r\n\r\n\tif (retval != NULL) { /* chop off filename. */\r\n\t\tchar *ptr = SDL_strrchr(retval, '/');\r\n\t\tif (ptr != NULL) {\r\n\t\t\t*(ptr + 1) = '\\0';\r\n\t\t} else { /* shouldn't happen, but just in case... */\r\n\t\t\tSDL_free(retval);\r\n\t\t\tretval = NULL;\r\n\t\t}\r\n\t}\r\n\r\n\tif (retval != NULL) {\r\n\t\t/* try to shrink buffer... */\r\n\t\tchar *ptr = (char *)SDL_realloc(retval, strlen(retval) + 1);\r\n\t\tif (ptr != NULL)\r\n\t\t\tretval = ptr; /* oh well if it failed. */\r\n\t}\r\n#endif\r\n\treturn retval;\r\n}\r\n\r\nextern \"C\" char *SDL_GetPrefPath(const char *org, const char *app)\r\n{\r\n\t// From sdl2-2.0.9/src/filesystem/unix/SDL_sysfilesystem.c\r\n\t/*\r\n\t * We use XDG's base directory spec, even if you're not on Linux.\r\n\t *  This isn't strictly correct, but the results are relatively sane\r\n\t *  in any case.\r\n\t *\r\n\t * https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html\r\n\t */\r\n#if (defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)) || defined(__DJGPP__)\r\n\t// On Windows9x there is no such thing as PrefPath. Simply use the current directory.\r\n\tchar *result = (char *)SDL_malloc(1);\r\n\t*result = '\\0';\r\n\treturn result;\r\n#else\r\n\tconst char *envr = SDL_getenv(\"XDG_DATA_HOME\");\r\n\tconst char *append;\r\n\tchar *retval = NULL;\r\n\tchar *ptr = NULL;\r\n\tsize_t len = 0;\r\n\r\n#if defined(__3DS__)\r\n\tretval = SDL_strdup(\"sdmc:/3ds/devilutionx/\");\r\n\treturn retval;\r\n#elif defined(__amigaos__)\r\n\tretval = SDL_strdup(\"PROGDIR:\");\r\n\treturn retval;\r\n#endif\r\n\r\n\tif (!app) {\r\n\t\tSDL_InvalidParamError(\"app\");\r\n\t\treturn NULL;\r\n\t}\r\n\tif (!org) {\r\n\t\torg = \"\";\r\n\t}\r\n\r\n\tif (!envr) {\r\n\t\t/* You end up with \"$HOME/.local/share/Game Name 2\" */\r\n\t\tenvr = SDL_getenv(\"HOME\");\r\n\t\tif (!envr) {\r\n\t\t\t/* we could take heroic measures with /etc/passwd, but oh well. */\r\n\t\t\tSDL_SetError(\"neither XDG_DATA_HOME nor HOME environment is set\");\r\n\t\t\treturn NULL;\r\n\t\t}\r\n#if defined(__unix__) || defined(__unix)\r\n\t\tappend = \"/.local/share/\";\r\n#else\r\n\t\tappend = \"/\";\r\n#endif\r\n\t} else {\r\n\t\tappend = \"/\";\r\n\t}\r\n\r\n\tlen = SDL_strlen(envr);\r\n\tif (envr[len - 1] == '/')\r\n\t\tappend += 1;\r\n\r\n\tlen += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;\r\n\tretval = (char *)SDL_malloc(len);\r\n\tif (!retval) {\r\n\t\tSDL_OutOfMemory();\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tif (*org) {\r\n\t\t*devilution::BufCopy(retval, envr, append, org, \"/\", app) = '\\0';\r\n\t} else {\r\n\t\t*devilution::BufCopy(retval, envr, append, app) = '\\0';\r\n\t}\r\n\r\n\tfor (ptr = retval + 1; *ptr; ptr++) {\r\n\t\tif (*ptr == '/') {\r\n\t\t\t*ptr = '\\0';\r\n\t\t\tif (mkdir(retval, 0700) != 0 && errno != EEXIST)\r\n\t\t\t\tgoto error;\r\n\t\t\t*ptr = '/';\r\n\t\t}\r\n\t}\r\n\tif (mkdir(retval, 0700) != 0 && errno != EEXIST) {\r\n\terror:\r\n\t\tSDL_SetError(\"Couldn't create directory '%s': '%s'\", retval, strerror(errno));\r\n\t\tSDL_free(retval);\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\t// Append trailing /\r\n\tsize_t final_len = SDL_strlen(retval);\r\n\tif (final_len + 1 < len) {\r\n\t\tretval[final_len++] = '/';\r\n\t\tretval[final_len] = '\\0';\r\n\t}\r\n\r\n\treturn retval;\r\n#endif\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "Source/utils/sdl2_to_1_2_backports.h",
    "content": "#pragma once\r\n\r\n#include <cerrno>\r\n#include <cmath>\r\n#include <cstddef>\r\n#include <cstdio>\r\n#include <sys/stat.h>\r\n#include <sys/types.h>\r\n\r\n#include <SDL.h>\r\n\r\n#include \"utils/attributes.h\"\r\n#include \"utils/console.h\"\r\n\r\n#ifndef _WIN32\r\n#include <unistd.h>\r\n#endif\r\n\r\n#define WINDOW_ICON_NAME 0\r\n#define SDL_Window SDL_Surface\r\n\r\n//== Utility\r\n\r\n#define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))\r\n#define SDL_InvalidParamError(param) SDL_SetError(\"Parameter '%s' is invalid\", (param))\r\n#define SDL_floor floor\r\n\r\n#define SDL_MAX_UINT32 ((Uint32)0xFFFFFFFFu)\r\n\r\n//== Events handling\r\n\r\n#define SDL_threadID Uint32\r\n\r\n#define SDL_Keysym SDL_keysym\r\n#define SDL_Keycode SDLKey\r\n#define SDL_Keymod SDLMod\r\n\r\n#define SDLK_PRINTSCREEN SDLK_PRINT\r\n#define SDLK_SCROLLLOCK SDLK_SCROLLOCK\r\n#define SDLK_NUMLOCKCLEAR SDLK_NUMLOCK\r\n#define SDLK_KP_1 SDLK_KP1\r\n#define SDLK_KP_2 SDLK_KP2\r\n#define SDLK_KP_3 SDLK_KP3\r\n#define SDLK_KP_4 SDLK_KP4\r\n#define SDLK_KP_5 SDLK_KP5\r\n#define SDLK_KP_6 SDLK_KP6\r\n#define SDLK_KP_7 SDLK_KP7\r\n#define SDLK_KP_8 SDLK_KP8\r\n#define SDLK_KP_9 SDLK_KP9\r\n#define SDLK_KP_0 SDLK_KP0\r\n#define SDLK_KP_COMMA SDLK_COMMA\r\n#define SDLK_LGUI SDLK_LSUPER\r\n#define SDLK_RGUI SDLK_RSUPER\r\n\r\n#define SDL_SCANCODE_GRAVE 53\r\n\r\n// Haptic events are not supported in SDL1.\r\n#define SDL_INIT_HAPTIC 0\r\n\r\n// For now we only process ASCII input when using SDL1.\r\n#define SDL_TEXTINPUTEVENT_TEXT_SIZE 2\r\n\r\n#define SDL_JoystickID Sint32\r\n#define SDL_JoystickNameForIndex SDL_JoystickName\r\n\r\nenum SDL_LogCategory {\r\n\tSDL_LOG_CATEGORY_APPLICATION,\r\n\tSDL_LOG_CATEGORY_ERROR,\r\n\tSDL_LOG_CATEGORY_ASSERT,\r\n\tSDL_LOG_CATEGORY_SYSTEM,\r\n\tSDL_LOG_CATEGORY_AUDIO,\r\n\tSDL_LOG_CATEGORY_VIDEO,\r\n\tSDL_LOG_CATEGORY_RENDER,\r\n\tSDL_LOG_CATEGORY_INPUT,\r\n\tSDL_LOG_CATEGORY_TEST,\r\n};\r\n\r\nenum SDL_LogPriority {\r\n\tSDL_LOG_PRIORITY_VERBOSE = 1,\r\n\tSDL_LOG_PRIORITY_DEBUG,\r\n\tSDL_LOG_PRIORITY_INFO,\r\n\tSDL_LOG_PRIORITY_WARN,\r\n\tSDL_LOG_PRIORITY_ERROR,\r\n\tSDL_LOG_PRIORITY_CRITICAL,\r\n\tSDL_NUM_LOG_PRIORITIES\r\n};\r\n\r\nvoid SDL_Log(const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(1, 2);\r\nvoid SDL_LogVerbose(int category, const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(2, 3);\r\nvoid SDL_LogDebug(int category, const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(2, 3);\r\nvoid SDL_LogInfo(int category, const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(2, 3);\r\nvoid SDL_LogWarn(int category, const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(2, 3);\r\nvoid SDL_LogError(int category, const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(2, 3);\r\nvoid SDL_LogCritical(int category, const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(2, 3);\r\nvoid SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...) DVL_PRINTF_ATTRIBUTE(3, 4);\r\nvoid SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap) DVL_PRINTF_ATTRIBUTE(3, 0);\r\n\r\nvoid SDL_LogSetAllPriority(SDL_LogPriority priority);\r\nvoid SDL_LogSetPriority(int category, SDL_LogPriority priority);\r\nSDL_LogPriority SDL_LogGetPriority(int category);\r\n\r\ninline void SDL_StartTextInput()\r\n{\r\n\tSDL_EnableUNICODE(1);\r\n}\r\n\r\ninline void SDL_StopTextInput()\r\n{\r\n\tSDL_EnableUNICODE(0);\r\n}\r\n\r\ninline void SDL_SetTextInputRect(const SDL_Rect *r)\r\n{\r\n}\r\n\r\ninline bool SDLC_StartTextInput(SDL_Window *)\r\n{\r\n\tSDL_StartTextInput();\r\n\treturn true;\r\n}\r\ninline bool SDLC_StopTextInput(SDL_Window *)\r\n{\r\n\tSDL_StopTextInput();\r\n\treturn true;\r\n}\r\ninline bool SDL_SetTextInputArea(SDL_Window *, const SDL_Rect *, int)\r\n{\r\n\treturn true;\r\n}\r\n\r\n//== Graphics helpers\r\n\r\ntypedef struct SDL_Point {\r\n\tint x;\r\n\tint y;\r\n} SDL_Point;\r\n\r\ninline SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r)\r\n{\r\n\treturn ((p->x >= r->x) && (p->x < (r->x + r->w)) && (p->y >= r->y) && (p->y < (r->y + r->h))) ? SDL_TRUE : SDL_FALSE;\r\n}\r\n\r\ninline bool SDLC_PointInRect(const SDL_Point *p, const SDL_Rect *r) { return SDL_PointInRect(p, r) == SDL_TRUE; }\r\n\r\n//= Messagebox (simply logged to stderr for now)\r\n\r\nenum {\r\n\t// clang-format off\r\n\tSDL_MESSAGEBOX_ERROR       = 1 << 4, /**< error dialog */\r\n\tSDL_MESSAGEBOX_WARNING     = 1 << 5, /**< warning dialog */\r\n\tSDL_MESSAGEBOX_INFORMATION = 1 << 6, /**< informational dialog */\r\n\t// clang-format on\r\n};\r\n\r\n#ifdef __3DS__\r\n/** Defined in Source/platform/ctr/messagebox.cpp */\r\nint SDL_ShowSimpleMessageBox(Uint32 flags,\r\n    const char *title,\r\n    const char *message,\r\n    SDL_Surface *window);\r\n#else\r\ninline int SDL_ShowSimpleMessageBox(Uint32 flags,\r\n    const char *title,\r\n    const char *message,\r\n    SDL_Surface *window)\r\n{\r\n\tSDL_Log(\"MSGBOX: %s\\n%s\", title, message);\r\n\treturn 0;\r\n}\r\n#endif\r\n\r\n//= Window handling\r\n\r\ninline void SDL_GetWindowPosition(SDL_Window *window, int *x, int *y)\r\n{\r\n\t*x = window->clip_rect.x;\r\n\t*y = window->clip_rect.x;\r\n\tSDL_Log(\"SDL_GetWindowPosition %i %i\", *x, *y);\r\n}\r\n\r\ninline void SDL_GetWindowSize(SDL_Window *window, int *w, int *h)\r\n{\r\n\t*w = window->clip_rect.w;\r\n\t*h = window->clip_rect.h;\r\n\tSDL_Log(\"SDL_GetWindowSize %i %i\", *w, *h);\r\n}\r\n\r\ninline void SDL_DestroyWindow(SDL_Window *window)\r\n{\r\n}\r\n\r\ninline void\r\nSDL_WarpMouseInWindow(SDL_Window *window, int x, int y)\r\n{\r\n\tSDL_WarpMouse(x, y);\r\n}\r\n\r\n//= Renderer stubs\r\n\r\n#define SDL_Renderer void\r\n\r\n//= Texture stubs\r\n\r\n#define SDL_Texture void\r\n\r\n//= Palette handling\r\n\r\ninline SDL_Palette *\r\nSDL_AllocPalette(int ncolors)\r\n{\r\n\tSDL_Palette *palette;\r\n\r\n\t/* Input validation */\r\n\tif (ncolors < 1) {\r\n\t\tSDL_InvalidParamError(\"ncolors\");\r\n\t\treturn NULL;\r\n\t}\r\n\r\n\tpalette = (SDL_Palette *)SDL_malloc(sizeof(*palette));\r\n\tif (!palette) {\r\n\t\tSDL_OutOfMemory();\r\n\t\treturn NULL;\r\n\t}\r\n\tpalette->colors = (SDL_Color *)SDL_malloc(ncolors * sizeof(*palette->colors));\r\n\tif (!palette->colors) {\r\n\t\tSDL_free(palette);\r\n\t\treturn NULL;\r\n\t}\r\n\tpalette->ncolors = ncolors;\r\n\tSDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));\r\n\treturn palette;\r\n}\r\n\r\ninline void\r\nSDL_FreePalette(SDL_Palette *palette)\r\n{\r\n\tif (!palette) {\r\n\t\tSDL_InvalidParamError(\"palette\");\r\n\t\treturn;\r\n\t}\r\n\tSDL_free(palette->colors);\r\n\tSDL_free(palette);\r\n}\r\n\r\ninline bool SDL_HasColorKey(SDL_Surface *surface)\r\n{\r\n\treturn (surface->flags & SDL_SRCCOLORKEY) != 0;\r\n}\r\n\r\n//= Pixel formats\r\n\r\n#define SDL_PIXELFORMAT_INDEX8 1\r\n#define SDL_PIXELFORMAT_RGB888 2\r\n#define SDL_PIXELFORMAT_RGBA8888 3\r\n\r\ninline void SDLBackport_PixelformatToMask(int pixelformat, Uint32 *flags, Uint32 *rmask,\r\n    Uint32 *gmask,\r\n    Uint32 *bmask,\r\n    Uint32 *amask)\r\n{\r\n\tif (pixelformat == SDL_PIXELFORMAT_RGBA8888) {\r\n#if SDL_BYTEORDER == SDL_BIG_ENDIAN\r\n\t\t*rmask = 0xff000000;\r\n\t\t*gmask = 0x00ff0000;\r\n\t\t*bmask = 0x0000ff00;\r\n\t\t*amask = 0x000000ff;\r\n#else\r\n\t\t*rmask = 0x000000ff;\r\n\t\t*gmask = 0x0000ff00;\r\n\t\t*bmask = 0x00ff0000;\r\n\t\t*amask = 0xff000000;\r\n#endif\r\n\t} else if (pixelformat == SDL_PIXELFORMAT_RGB888) {\r\n#if SDL_BYTEORDER == SDL_BIG_ENDIAN\r\n\t\t*rmask = 0xff000000;\r\n\t\t*gmask = 0x00ff0000;\r\n\t\t*bmask = 0x0000ff00;\r\n#else\r\n\t\t*rmask = 0x000000ff;\r\n\t\t*gmask = 0x0000ff00;\r\n\t\t*bmask = 0x00ff0000;\r\n#endif\r\n\t\t*amask = 0;\r\n\t} else {\r\n\t\t*rmask = *gmask = *bmask = *amask = 0;\r\n\t}\r\n}\r\n\r\n/**\r\n * A limited implementation of `a.format` == `b.format` from SDL2.\r\n */\r\ninline bool SDLBackport_PixelFormatFormatEq(const SDL_PixelFormat *a, const SDL_PixelFormat *b)\r\n{\r\n\treturn a->BitsPerPixel == b->BitsPerPixel && (a->palette != NULL) == (b->palette != NULL)\r\n\t    && a->Rmask == b->Rmask && a->Gmask == b->Gmask && a->Bmask == b->Bmask;\r\n}\r\n\r\n/**\r\n * Similar to `SDL_ISPIXELFORMAT_INDEXED` from SDL2.\r\n */\r\ninline bool SDLBackport_IsPixelFormatIndexed(const SDL_PixelFormat *pf)\r\n{\r\n\treturn pf->BitsPerPixel == 8 && pf->palette != NULL;\r\n}\r\n\r\n//= Surface creation\r\n\r\ninline SDL_Surface *\r\nSDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth,\r\n    Uint32 format)\r\n{\r\n\tUint32 rmask, gmask, bmask, amask;\r\n\tSDLBackport_PixelformatToMask(format, &flags, &rmask, &gmask, &bmask, &amask);\r\n\treturn SDL_CreateRGBSurface(flags, width, height, depth, rmask, gmask, bmask, amask);\r\n}\r\n\r\ninline SDL_Surface *\r\nSDL_CreateRGBSurfaceWithFormatFrom(void *pixels, Uint32 flags, int width, int height, int depth,\r\n    Uint32 format)\r\n{\r\n\tUint32 rmask, gmask, bmask, amask;\r\n\tSDLBackport_PixelformatToMask(format, &flags, &rmask, &gmask, &bmask, &amask);\r\n\treturn SDL_CreateRGBSurfaceFrom(pixels, flags, width, height, depth, rmask, gmask, bmask, amask);\r\n}\r\n\r\n//= BlitScaled backport from SDL 2.0.9.\r\n\r\n// NOTE: Not thread-safe\r\nint SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect,\r\n    SDL_Surface *dst, const SDL_Rect *dstrect);\r\n\r\n// NOTE: The second argument is const in SDL2 but not here.\r\nint SDL_BlitScaled(SDL_Surface *src, SDL_Rect *srcrect,\r\n    SDL_Surface *dst, SDL_Rect *dstrect);\r\n\r\n//== Filesystem\r\n#define SDL_RWOPS_UNKNOWN 0U\r\n\r\nSint64 SDL_RWsize(SDL_RWops *context);\r\n\r\nextern \"C\" char *SDL_GetBasePath();\r\nextern \"C\" char *SDL_GetPrefPath(const char *org, const char *app);\r\n"
  },
  {
    "path": "Source/utils/sdl_bilinear_scale.cpp",
    "content": "#include \"utils/sdl_bilinear_scale.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <memory>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_rect.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n\r\n// Performs bilinear scaling using fixed-width integer math.\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nint Frac(int fixedPoint)\r\n{\r\n\treturn fixedPoint & 0xffff;\r\n}\r\n\r\nint ToInt(int fixedPoint)\r\n{\r\n\treturn fixedPoint >> 16;\r\n}\r\n\r\nstd::unique_ptr<int[]> CreateMixFactors(unsigned srcSize, unsigned dstSize)\r\n{\r\n\tstd::unique_ptr<int[]> result { new int[dstSize + 1] };\r\n\tconst auto scale = static_cast<int>(65536.0 * static_cast<float>(srcSize - 1) / dstSize);\r\n\tint mix = 0;\r\n\tfor (unsigned i = 0; i <= dstSize; ++i) {\r\n\t\tresult[i] = mix;\r\n\t\tmix = Frac(mix) + scale;\r\n\t}\r\n\treturn result;\r\n};\r\n\r\nuint8_t MixColors(uint8_t first, uint8_t second, int ratio)\r\n{\r\n\treturn ToInt((second - first) * ratio) + first;\r\n}\r\n\r\nuint8_t MixColorsWithAlpha(uint8_t first, uint8_t firstAlpha,\r\n    uint8_t second, uint8_t secondAlpha,\r\n    uint8_t mixedAlpha, int ratio)\r\n{\r\n\tif (mixedAlpha == 0)\r\n\t\treturn 0;\r\n\tif (mixedAlpha == 255)\r\n\t\treturn MixColors(first, second, ratio);\r\n\r\n\tconst int firstWithAlpha = first * firstAlpha;\r\n\tconst int secondWithAlpha = second * secondAlpha;\r\n\r\n\t// We want to calculate:\r\n\t//\r\n\t//    (ToInt((secondWithAlpha - firstWithAlpha) * ratio) + firstWithAlpha) / mixedAlpha\r\n\t//\r\n\t// However, the above written as-is can overflow in the argument to `ToInt`.\r\n\t// To avoid the overflow we divide each term by `mixedAlpha` separately.\r\n\t//\r\n\t// This would be lower precision and could result in a negative overall result,\r\n\t// so we do the rounding-up integer division for each term (instead of a truncating one):\r\n\t//\r\n\t//    (a + (b - 1)) / b\r\n\treturn ToInt((secondWithAlpha - firstWithAlpha) * ((ratio + (mixedAlpha - 1)) / mixedAlpha)) + (firstWithAlpha + (mixedAlpha - 1)) / mixedAlpha;\r\n}\r\n\r\n} // namespace\r\n\r\nvoid BilinearScale32(SDL_Surface *src, SDL_Surface *dst)\r\n{\r\n\tconst std::unique_ptr<int[]> mixXs = CreateMixFactors(src->w, dst->w);\r\n\tconst std::unique_ptr<int[]> mixYs = CreateMixFactors(src->h, dst->h);\r\n\r\n\tconst unsigned dgap = dst->pitch - dst->w * 4;\r\n\r\n\tauto *srcPixels = static_cast<uint8_t *>(src->pixels);\r\n\tauto *dstPixels = static_cast<uint8_t *>(dst->pixels);\r\n\r\n\tint *curMixY = &mixYs[0];\r\n\tunsigned srcY = 0;\r\n\tfor (unsigned y = 0; y < static_cast<unsigned>(dst->h); ++y) {\r\n\t\tuint8_t *s[4] = {\r\n\t\t\tsrcPixels,                 // Self\r\n\t\t\tsrcPixels + 4,             // Right\r\n\t\t\tsrcPixels + src->pitch,    // Bottom\r\n\t\t\tsrcPixels + src->pitch + 4 // Bottom right\r\n\t\t};\r\n\r\n\t\tint *curMixX = &mixXs[0];\r\n\t\tunsigned srcX = 0;\r\n\t\tfor (unsigned x = 0; x < static_cast<unsigned>(dst->w); ++x) {\r\n\t\t\tconst int mixX = Frac(*curMixX);\r\n\t\t\tconst int mixY = Frac(*curMixY);\r\n\r\n\t\t\tconst uint8_t alpha0 = MixColors(s[0][3], s[1][3], mixX);\r\n\t\t\tconst uint8_t alpha1 = MixColors(s[2][3], s[3][3], mixX);\r\n\t\t\tconst uint8_t finalAlpha = MixColors(alpha0, alpha1, mixY);\r\n\r\n\t\t\tif (finalAlpha == 0) {\r\n\t\t\t\tdstPixels[0] = 0;\r\n\t\t\t\tdstPixels[1] = 0;\r\n\t\t\t\tdstPixels[2] = 0;\r\n\t\t\t\tdstPixels[3] = 0;\r\n\t\t\t} else if (finalAlpha == 255) {\r\n\t\t\t\tfor (unsigned channel = 0; channel < 3; ++channel) {\r\n\t\t\t\t\tdstPixels[channel] = MixColors(\r\n\t\t\t\t\t    MixColors(s[0][channel], s[1][channel], mixX),\r\n\t\t\t\t\t    MixColors(s[2][channel], s[3][channel], mixX),\r\n\t\t\t\t\t    mixY);\r\n\t\t\t\t}\r\n\t\t\t\tdstPixels[3] = 255;\r\n\t\t\t} else {\r\n\t\t\t\tfor (unsigned channel = 0; channel < 3; ++channel) {\r\n\t\t\t\t\tdstPixels[channel] = MixColorsWithAlpha(\r\n\t\t\t\t\t    MixColorsWithAlpha(s[0][channel], s[0][3], s[1][channel], s[1][3], alpha0, mixX),\r\n\t\t\t\t\t    alpha0,\r\n\t\t\t\t\t    MixColorsWithAlpha(s[2][channel], s[2][3], s[3][channel], s[3][3], alpha1, mixX),\r\n\t\t\t\t\t    alpha1,\r\n\t\t\t\t\t    finalAlpha,\r\n\t\t\t\t\t    mixY);\r\n\t\t\t\t}\r\n\t\t\t\tdstPixels[3] = finalAlpha;\r\n\t\t\t}\r\n\r\n\t\t\t++curMixX;\r\n\t\t\tif (*curMixX > 0) {\r\n\t\t\t\tunsigned step = ToInt(*curMixX);\r\n\t\t\t\tsrcX += step;\r\n\t\t\t\tif (srcX <= static_cast<unsigned>(src->w)) {\r\n\t\t\t\t\tstep *= 4;\r\n\t\t\t\t\tfor (auto &v : s) {\r\n\t\t\t\t\t\tv += step;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tdstPixels += 4;\r\n\t\t}\r\n\r\n\t\t++curMixY;\r\n\t\tif (*curMixY > 0) {\r\n\t\t\tconst unsigned step = ToInt(*curMixY);\r\n\t\t\tsrcY += step;\r\n\t\t\tif (srcY < static_cast<unsigned>(src->h)) {\r\n\t\t\t\tsrcPixels += step * src->pitch;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdstPixels += dgap;\r\n\t}\r\n}\r\n\r\nvoid BilinearDownscaleByHalf8(SDL_Surface *src, const uint8_t paletteBlendingTable[256][256], SDL_Surface *dst, uint8_t transparentIndex)\r\n{\r\n\tSDL_Rect srcClipRect, dstClipRect;\r\n#ifdef USE_SDL3\r\n\tif (!SDL_GetSurfaceClipRect(src, &srcClipRect)) app_fatal(SDL_GetError());\r\n\tif (!SDL_GetSurfaceClipRect(dst, &dstClipRect)) app_fatal(SDL_GetError());\r\n#else\r\n\tsrcClipRect = src->clip_rect;\r\n\tdstClipRect = dst->clip_rect;\r\n#endif\r\n\r\n\tconst auto *const srcPixelsBegin = static_cast<const uint8_t *>(src->pixels)\r\n\t    + static_cast<size_t>((srcClipRect.y * src->pitch) + srcClipRect.x);\r\n\tauto *const dstPixelsBegin = static_cast<uint8_t *>(dst->pixels)\r\n\t    + static_cast<size_t>((dstClipRect.y * dst->pitch) + dstClipRect.x);\r\n\tfor (unsigned y = 0, h = static_cast<unsigned>(dstClipRect.h); y < h; ++y) {\r\n\t\tconst uint8_t *srcPixels = srcPixelsBegin + static_cast<size_t>(2 * y * src->pitch);\r\n\t\tuint8_t *dstPixels = dstPixelsBegin + static_cast<size_t>(y * dst->pitch);\r\n\t\tfor (unsigned x = 0, w = static_cast<unsigned>(dstClipRect.w); x < w; ++x) {\r\n\t\t\tuint8_t quad[] = {\r\n\t\t\t\tsrcPixels[0],\r\n\t\t\t\tsrcPixels[1],\r\n\t\t\t\tsrcPixels[src->pitch],\r\n\t\t\t\tsrcPixels[src->pitch + 1]\r\n\t\t\t};\r\n\t\t\t// Attempt to avoid blending with transparent pixels\r\n\t\t\tif (quad[0] == transparentIndex)\r\n\t\t\t\tquad[0] = quad[1];\r\n\t\t\tif (quad[1] == transparentIndex)\r\n\t\t\t\tquad[1] = quad[0];\r\n\t\t\tif (quad[2] == transparentIndex)\r\n\t\t\t\tquad[2] = quad[3];\r\n\t\t\tif (quad[3] == transparentIndex)\r\n\t\t\t\tquad[3] = quad[2];\r\n\t\t\tuint8_t top = paletteBlendingTable[quad[0]][quad[1]];\r\n\t\t\tuint8_t bottom = paletteBlendingTable[quad[2]][quad[3]];\r\n\t\t\tif (top == transparentIndex)\r\n\t\t\t\ttop = bottom;\r\n\t\t\tif (bottom == transparentIndex)\r\n\t\t\t\tbottom = top;\r\n\t\t\t*dstPixels++ = paletteBlendingTable[top][bottom];\r\n\t\t\tsrcPixels += 2;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl_bilinear_scale.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Bilinear 32-bit scaling.\r\n * Requires `src` and `dst` to have the same pixel format (ARGB8888 or RGBA8888).\r\n */\r\nvoid BilinearScale32(SDL_Surface *src, SDL_Surface *dst);\r\n\r\n/**\r\n * @brief Streamlined bilinear downscaling using blended transparency table.\r\n * Requires `src` and `dst` to have the same pixel format (INDEX8).\r\n */\r\nvoid BilinearDownscaleByHalf8(SDL_Surface *src, const uint8_t paletteBlendingTable[256][256], SDL_Surface *dst, uint8_t transparentIndex);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl_compat.h",
    "content": "// Compatibility wrappers for SDL 1 & 2.\r\n#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_events.h>\r\n#include <SDL3/SDL_keyboard.h>\r\n#include <SDL3/SDL_keycode.h>\r\n#include <SDL3/SDL_pixels.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_scancode.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL.h>\r\n#ifdef USE_SDL1\r\n#include \"utils/display.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#ifdef USE_SDL1\r\n#define SDL_Scancode Uint8\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\n#define SDLC_PushEvent SDL_PushEvent\r\n#define SDLC_SetClipboardText SDL_SetClipboardText\r\n#define SDLC_HasClipboardText SDL_HasClipboardText\r\n\r\ninline SDL_Keycode SDLC_EventKey(const SDL_Event &event) { return event.key.key; }\r\ninline SDL_Scancode SDLC_EventScancode(const SDL_Event &event) { return event.key.scancode; }\r\n\r\ninline int SDLC_EventMotionIntX(const SDL_Event &event) { return static_cast<int>(event.motion.x); }\r\ninline int SDLC_EventMotionIntY(const SDL_Event &event) { return static_cast<int>(event.motion.y); }\r\ninline int SDLC_EventButtonIntX(const SDL_Event &event) { return static_cast<int>(event.button.x); }\r\ninline int SDLC_EventButtonIntY(const SDL_Event &event) { return static_cast<int>(event.button.y); }\r\ninline int SDLC_EventWheelIntX(const SDL_Event &event)\r\n{\r\n#if SDL_VERSION_ATLEAST(3, 2, 12)\r\n\treturn event.wheel.integer_x;\r\n#else\r\n\treturn static_cast<int>(event.wheel.x);\r\n#endif\r\n}\r\n\r\ninline int SDLC_EventWheelIntY(const SDL_Event &event)\r\n{\r\n#if SDL_VERSION_ATLEAST(3, 2, 12)\r\n\treturn event.wheel.integer_y;\r\n#else\r\n\treturn static_cast<int>(event.wheel.y);\r\n#endif\r\n}\r\n\r\ninline const SDL_GamepadAxisEvent &SDLC_EventGamepadAxis(const SDL_Event &event) { return event.gaxis; }\r\ninline const SDL_GamepadButtonEvent &SDLC_EventGamepadButton(const SDL_Event &event) { return event.gbutton; }\r\ninline const SDL_GamepadDeviceEvent &SDLC_EventGamepadDevice(const SDL_Event &event) { return event.gdevice; }\r\n\r\n#define SDLC_SURFACE_BITSPERPIXEL(surface) SDL_BITSPERPIXEL(surface->format)\r\n\r\n#define SDLC_StartTextInput SDL_StartTextInput\r\n#define SDLC_StopTextInput SDL_StopTextInput\r\n\r\n#define SDLC_SetSurfacePalette SDL_SetSurfacePalette\r\n\r\n#define SDLC_PointInRect SDL_PointInRect\r\n\r\n#define SDLC_ShowCursor SDL_ShowCursor\r\n#define SDLC_HideCursor SDL_HideCursor\r\n\r\n#define SDLC_ShowSimpleMessageBox SDL_ShowSimpleMessageBox\r\n#else\r\n#define SDL_EVENT_AUDIO_DEVICE_ADDED SDL_AUDIODEVICEADDED\r\n#define SDL_EVENT_AUDIO_DEVICE_REMOVED SDL_AUDIODEVICEREMOVED\r\n#define SDL_EVENT_CLIPBOARD_UPDATE SDL_CLIPBOARDUPDATE\r\n#define SDL_EVENT_GAMEPAD_AXIS_MOTION SDL_CONTROLLERAXISMOTION\r\n#define SDL_EVENT_GAMEPAD_BUTTON_DOWN SDL_CONTROLLERBUTTONDOWN\r\n#define SDL_EVENT_GAMEPAD_BUTTON_UP SDL_CONTROLLERBUTTONUP\r\n#define SDL_EVENT_GAMEPAD_ADDED SDL_CONTROLLERDEVICEADDED\r\n#define SDL_EVENT_GAMEPAD_REMAPPED SDL_CONTROLLERDEVICEREMAPPED\r\n#define SDL_EVENT_GAMEPAD_REMOVED SDL_CONTROLLERDEVICEREMOVED\r\n#define SDL_EVENT_GAMEPAD_SENSOR_UPDATE SDL_CONTROLLERSENSORUPDATE\r\n#define SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED SDL_CONTROLLERSTEAMHANDLEUPDATED\r\n#define SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN SDL_CONTROLLERTOUCHPADDOWN\r\n#define SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION SDL_CONTROLLERTOUCHPADMOTION\r\n#define SDL_EVENT_GAMEPAD_TOUCHPAD_UP SDL_CONTROLLERTOUCHPADUP\r\n#define SDL_GAMEPAD_AXIS_INVALID SDL_CONTROLLER_AXIS_INVALID\r\n#define SDL_GAMEPAD_AXIS_LEFTX SDL_CONTROLLER_AXIS_LEFTX\r\n#define SDL_GAMEPAD_AXIS_LEFTY SDL_CONTROLLER_AXIS_LEFTY\r\n#define SDL_GAMEPAD_AXIS_COUNT SDL_CONTROLLER_AXIS_MAX\r\n#define SDL_GAMEPAD_AXIS_RIGHTX SDL_CONTROLLER_AXIS_RIGHTX\r\n#define SDL_GAMEPAD_AXIS_RIGHTY SDL_CONTROLLER_AXIS_RIGHTY\r\n#define SDL_GAMEPAD_AXIS_LEFT_TRIGGER SDL_CONTROLLER_AXIS_TRIGGERLEFT\r\n#define SDL_GAMEPAD_AXIS_RIGHT_TRIGGER SDL_CONTROLLER_AXIS_TRIGGERRIGHT\r\n#define SDL_EVENT_FINGER_DOWN SDL_FINGERDOWN\r\n#define SDL_EVENT_FINGER_MOTION SDL_FINGERMOTION\r\n#define SDL_EVENT_FINGER_UP SDL_FINGERUP\r\n#define SDL_EVENT_JOYSTICK_AXIS_MOTION SDL_JOYAXISMOTION\r\n#define SDL_EVENT_JOYSTICK_BATTERY_UPDATED SDL_JOYBATTERYUPDATED\r\n#define SDL_EVENT_JOYSTICK_BUTTON_DOWN SDL_JOYBUTTONDOWN\r\n#define SDL_EVENT_JOYSTICK_BUTTON_UP SDL_JOYBUTTONUP\r\n#define SDL_EVENT_JOYSTICK_ADDED SDL_JOYDEVICEADDED\r\n#define SDL_EVENT_JOYSTICK_REMOVED SDL_JOYDEVICEREMOVED\r\n#define SDL_EVENT_JOYSTICK_BALL_MOTION SDL_JOYBALLMOTION\r\n#define SDL_EVENT_JOYSTICK_HAT_MOTION SDL_JOYHATMOTION\r\n#define SDL_EVENT_KEY_DOWN SDL_KEYDOWN\r\n#define SDL_EVENT_KEYMAP_CHANGED SDL_KEYMAPCHANGED\r\n#define SDL_EVENT_KEY_UP SDL_KEYUP\r\n#define SDL_EVENT_LAST SDL_LASTEVENT\r\n#define SDL_EVENT_LOCALE_CHANGED SDL_LOCALECHANGED\r\n#define SDL_EVENT_MOUSE_BUTTON_DOWN SDL_MOUSEBUTTONDOWN\r\n#define SDL_EVENT_MOUSE_BUTTON_UP SDL_MOUSEBUTTONUP\r\n#define SDL_EVENT_MOUSE_MOTION SDL_MOUSEMOTION\r\n#define SDL_EVENT_MOUSE_WHEEL SDL_MOUSEWHEEL\r\n#define SDL_EVENT_POLL_SENTINEL SDL_POLLSENTINEL\r\n#define SDL_EVENT_QUIT SDL_QUIT\r\n#define SDL_EVENT_TEXT_INPUT SDL_TEXTINPUT\r\n#define SDL_EVENT_USER SDL_USEREVENT\r\n\r\n#define SDL_Gamepad SDL_GameController\r\n#define SDL_GamepadButton SDL_GameControllerButton\r\n#define SDL_GamepadAxisEvent SDL_ControllerAxisEvent\r\n#define SDL_GamepadButtonEvent SDL_ControllerButtonEvent\r\n#define SDL_GamepadDeviceEvent SDL_ControllerDeviceEvent\r\n#define SDL_GAMEPAD_BUTTON_SOUTH SDL_CONTROLLER_BUTTON_A\r\n#define SDL_GAMEPAD_BUTTON_EAST SDL_CONTROLLER_BUTTON_B\r\n#define SDL_GAMEPAD_BUTTON_BACK SDL_CONTROLLER_BUTTON_BACK\r\n#define SDL_GAMEPAD_BUTTON_DPAD_DOWN SDL_CONTROLLER_BUTTON_DPAD_DOWN\r\n#define SDL_GAMEPAD_BUTTON_DPAD_LEFT SDL_CONTROLLER_BUTTON_DPAD_LEFT\r\n#define SDL_GAMEPAD_BUTTON_DPAD_RIGHT SDL_CONTROLLER_BUTTON_DPAD_RIGHT\r\n#define SDL_GAMEPAD_BUTTON_DPAD_UP SDL_CONTROLLER_BUTTON_DPAD_UP\r\n#define SDL_GAMEPAD_BUTTON_GUIDE SDL_CONTROLLER_BUTTON_GUIDE\r\n#define SDL_GAMEPAD_BUTTON_INVALID SDL_CONTROLLER_BUTTON_INVALID\r\n#define SDL_GAMEPAD_BUTTON_LEFT_SHOULDER SDL_CONTROLLER_BUTTON_LEFTSHOULDER\r\n#define SDL_GAMEPAD_BUTTON_LEFT_STICK SDL_CONTROLLER_BUTTON_LEFTSTICK\r\n#define SDL_GAMEPAD_BUTTON_COUNT SDL_CONTROLLER_BUTTON_MAX\r\n#define SDL_GAMEPAD_BUTTON_MISC1 SDL_CONTROLLER_BUTTON_MISC1\r\n#define SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 SDL_CONTROLLER_BUTTON_PADDLE1\r\n#define SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 SDL_CONTROLLER_BUTTON_PADDLE2\r\n#define SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 SDL_CONTROLLER_BUTTON_PADDLE3\r\n#define SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 SDL_CONTROLLER_BUTTON_PADDLE4\r\n#define SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER SDL_CONTROLLER_BUTTON_RIGHTSHOULDER\r\n#define SDL_GAMEPAD_BUTTON_RIGHT_STICK SDL_CONTROLLER_BUTTON_RIGHTSTICK\r\n#define SDL_GAMEPAD_BUTTON_START SDL_CONTROLLER_BUTTON_START\r\n#define SDL_GAMEPAD_BUTTON_TOUCHPAD SDL_CONTROLLER_BUTTON_TOUCHPAD\r\n#define SDL_GAMEPAD_BUTTON_WEST SDL_CONTROLLER_BUTTON_X\r\n#define SDL_GAMEPAD_BUTTON_NORTH SDL_CONTROLLER_BUTTON_Y\r\n\r\n#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT\r\n#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR\r\n#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT\r\n#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO\r\n#define SDL_GAMEPAD_TYPE_PS3 SDL_CONTROLLER_TYPE_PS3\r\n#define SDL_GAMEPAD_TYPE_PS4 SDL_CONTROLLER_TYPE_PS4\r\n#define SDL_GAMEPAD_TYPE_PS5 SDL_CONTROLLER_TYPE_PS5\r\n#define SDL_GAMEPAD_TYPE_STANDARD SDL_CONTROLLER_TYPE_UNKNOWN\r\n#define SDL_GAMEPAD_TYPE_VIRTUAL SDL_CONTROLLER_TYPE_VIRTUAL\r\n#define SDL_GAMEPAD_TYPE_XBOX360 SDL_CONTROLLER_TYPE_XBOX360\r\n#define SDL_GAMEPAD_TYPE_XBOXONE SDL_CONTROLLER_TYPE_XBOXONE\r\n\r\n#define SDL_KMOD_ALT KMOD_ALT\r\n#define SDL_KMOD_CAPS KMOD_CAPS\r\n#define SDL_KMOD_CTRL KMOD_CTRL\r\n#define SDL_KMOD_GUI KMOD_GUI\r\n#define SDL_KMOD_LALT KMOD_LALT\r\n#define SDL_KMOD_LCTRL KMOD_LCTRL\r\n#define SDL_KMOD_LGUI KMOD_LGUI\r\n#define SDL_KMOD_LSHIFT KMOD_LSHIFT\r\n#define SDL_KMOD_MODE KMOD_MODE\r\n#define SDL_KMOD_NONE KMOD_NONE\r\n#define SDL_KMOD_NUM KMOD_NUM\r\n#define SDL_KMOD_RALT KMOD_RALT\r\n#define SDL_KMOD_RCTRL KMOD_RCTRL\r\n#define SDL_KMOD_RGUI KMOD_RGUI\r\n#define SDL_KMOD_RSHIFT KMOD_RSHIFT\r\n#define SDL_KMOD_SCROLL KMOD_SCROLL\r\n#define SDL_KMOD_SHIFT KMOD_SHIFT\r\n\r\n#define SDLK_GRAVE SDLK_BACKQUOTE\r\n#define SDLK_APOSTROPHE SDLK_QUOTE\r\n#define SDLK_A SDLK_a\r\n#define SDLK_B SDLK_b\r\n#define SDLK_C SDLK_c\r\n#define SDLK_D SDLK_d\r\n#define SDLK_E SDLK_e\r\n#define SDLK_F SDLK_f\r\n#define SDLK_G SDLK_g\r\n#define SDLK_H SDLK_h\r\n#define SDLK_I SDLK_i\r\n#define SDLK_J SDLK_j\r\n#define SDLK_K SDLK_k\r\n#define SDLK_L SDLK_l\r\n#define SDLK_M SDLK_m\r\n#define SDLK_N SDLK_n\r\n#define SDLK_O SDLK_o\r\n#define SDLK_P SDLK_p\r\n#define SDLK_Q SDLK_q\r\n#define SDLK_R SDLK_r\r\n#define SDLK_S SDLK_s\r\n#define SDLK_T SDLK_t\r\n#define SDLK_U SDLK_u\r\n#define SDLK_V SDLK_v\r\n#define SDLK_W SDLK_w\r\n#define SDLK_X SDLK_x\r\n#define SDLK_Y SDLK_y\r\n#define SDLK_Z SDLK_z\r\n\r\n#define SDL_PIXELFORMAT_XBGR4444 SDL_PIXELFORMAT_BGR444\r\n#define SDL_PIXELFORMAT_XBGR1555 SDL_PIXELFORMAT_BGR555\r\n#define SDL_PIXELFORMAT_XBGR8888 SDL_PIXELFORMAT_BGR888\r\n#define SDL_PIXELFORMAT_XRGB4444 SDL_PIXELFORMAT_RGB444\r\n#define SDL_PIXELFORMAT_XRGB1555 SDL_PIXELFORMAT_RGB555\r\n#define SDL_PIXELFORMAT_XRGB8888 SDL_PIXELFORMAT_RGB888\r\n\r\n#define SDL_IO_SEEK_CUR RW_SEEK_CUR\r\n#define SDL_IO_SEEK_END RW_SEEK_END\r\n#define SDL_IO_SEEK_SET RW_SEEK_SET\r\n#define SDL_IOFromConstMem SDL_RWFromConstMem\r\n#define SDL_IOFromFile SDL_RWFromFile\r\n#define SDL_IOFromMem SDL_RWFromMem\r\n#define SDL_IOStream SDL_RWops\r\n#define SDL_SeekIO SDL_RWseek\r\n#define SDL_GetIOSize SDL_RWsize\r\n#define SDL_TellIO SDL_RWtell\r\n\r\n#define SDL_GetLogOutputFunction SDL_LogGetOutputFunction\r\n#define SDL_GetLogPriority SDL_LogGetPriority\r\n#define SDL_ResetLogPriorities SDL_LogResetPriorities\r\n#define SDL_SetLogPriorities SDL_LogSetAllPriority\r\n#define SDL_SetLogOutputFunction SDL_LogSetOutputFunction\r\n#define SDL_SetLogPriority SDL_LogSetPriority\r\n#define SDL_LOG_PRIORITY_COUNT SDL_NUM_LOG_PRIORITIES\r\n\r\n#define SDL_ThreadID SDL_threadID\r\n\r\n#define SDLC_SURFACE_BITSPERPIXEL(surface) surface->format->BitsPerPixel\r\n\r\ninline bool SDLC_PushEvent(SDL_Event *event) { return SDL_PushEvent(event) == 1; }\r\n\r\ninline\r\n#ifdef USE_SDL1\r\n    SDLKey\r\n#else\r\n    SDL_Keycode\r\n#endif\r\n    SDLC_EventKey(const SDL_Event &event)\r\n{\r\n\treturn event.key.keysym.sym;\r\n}\r\ninline SDL_Scancode SDLC_EventScancode(const SDL_Event &event) { return event.key.keysym.scancode; }\r\n\r\ninline int SDLC_EventMotionIntX(const SDL_Event &event) { return event.motion.x; }\r\ninline int SDLC_EventMotionIntY(const SDL_Event &event) { return event.motion.y; }\r\ninline int SDLC_EventButtonIntX(const SDL_Event &event) { return event.button.x; }\r\ninline int SDLC_EventButtonIntY(const SDL_Event &event) { return event.button.y; }\r\n\r\ninline bool SDL_FillSurfaceRect(SDL_Surface *dst,\r\n#ifdef USE_SDL1\r\n    SDL_Rect *rect,\r\n#else\r\n    const SDL_Rect *rect,\r\n#endif\r\n    Uint32 color)\r\n{\r\n\treturn SDL_FillRect(dst, rect, color) == 0;\r\n}\r\n\r\ninline bool SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect) { return SDL_SetClipRect(surface, rect) == SDL_TRUE; }\r\ninline bool SDL_SetSurfaceColorKey(SDL_Surface *surface, bool enabled, Uint32 key)\r\n{\r\n\treturn SDL_SetColorKey(surface, enabled ? 1 : 0, key) == 0;\r\n}\r\n\r\n#ifndef USE_SDL1\r\ninline bool SDLC_SetClipboardText(const char *text) { return SDL_SetClipboardText(text) == 0; }\r\ninline bool SDLC_HasClipboardText() { return SDL_HasClipboardText() == SDL_TRUE; }\r\n\r\ninline int SDLC_EventWheelIntX(const SDL_Event &event) { return event.wheel.x; }\r\ninline int SDLC_EventWheelIntY(const SDL_Event &event) { return event.wheel.y; }\r\n\r\ninline const SDL_GamepadAxisEvent &SDLC_EventGamepadAxis(const SDL_Event &event) { return event.caxis; }\r\ninline const SDL_GamepadButtonEvent &SDLC_EventGamepadButton(const SDL_Event &event) { return event.cbutton; }\r\ninline const SDL_GamepadDeviceEvent &SDLC_EventGamepadDevice(const SDL_Event &event) { return event.cdevice; }\r\ninline bool SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_GamepadButton button)\r\n{\r\n\treturn SDL_GameControllerHasButton(gamepad, button) == SDL_TRUE;\r\n}\r\ninline bool SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button)\r\n{\r\n\treturn SDL_GameControllerGetButton(gamepad, button) != 0;\r\n}\r\n\r\ninline bool SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY)\r\n{\r\n\tSDL_RenderGetScale(renderer, scaleX, scaleY);\r\n\treturn true;\r\n}\r\n\r\n// For SDL1.2, these are defined in sdl2_to_1_2_backports.h\r\ninline bool SDLC_StartTextInput([[maybe_unused]] SDL_Window *window)\r\n{\r\n\tSDL_StartTextInput();\r\n\treturn true;\r\n}\r\ninline bool SDLC_StopTextInput([[maybe_unused]] SDL_Window *window)\r\n{\r\n\tSDL_StopTextInput();\r\n\treturn true;\r\n}\r\ninline bool SDL_SetTextInputArea([[maybe_unused]] SDL_Window *window, SDL_Rect *rect, [[maybe_unused]] int cursor)\r\n{\r\n\tSDL_SetTextInputRect(rect);\r\n\treturn true;\r\n}\r\n\r\ninline bool SDLC_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)\r\n{\r\n\treturn SDL_SetSurfacePalette(surface, palette) == 0;\r\n}\r\n\r\ninline bool SDL_CursorVisible() { return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE; }\r\n\r\n// For SDL1.2, this is defined in sdl2_to_1_2_backports.h\r\ninline bool SDLC_PointInRect(const SDL_Point *p, const SDL_Rect *r) { return SDL_PointInRect(p, r) == SDL_TRUE; }\r\n#endif\r\n\r\ninline bool SDLC_ShowCursor() { return SDL_ShowCursor(SDL_ENABLE) >= 0; }\r\ninline bool SDLC_HideCursor() { return SDL_ShowCursor(SDL_DISABLE) >= 0; }\r\n\r\ninline size_t SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size)\r\n{\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\treturn SDL_RWread(context, ptr, 1, size);\r\n#else\r\n\treturn SDL_RWread(context, ptr, 1, static_cast<int>(size));\r\n#endif\r\n}\r\ninline size_t SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size)\r\n{\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\treturn SDL_RWwrite(context, ptr, 1, size);\r\n#else\r\n\treturn SDL_RWwrite(context, ptr, 1, static_cast<int>(size));\r\n#endif\r\n}\r\n\r\ninline bool SDL_CloseIO(SDL_IOStream *iostr)\r\n{\r\n\treturn SDL_RWclose(iostr) == 0;\r\n}\r\n\r\n#define SDLC_ShowSimpleMessageBox(flags, title, message, window) SDL_ShowSimpleMessageBox(flags, title, message, window) == 0\r\n#endif\r\n\r\n#ifndef USE_SDL1\r\n#define SDLC_KEYSTATE_LEFTCTRL SDL_SCANCODE_LCTRL\r\n#define SDLC_KEYSTATE_RIGHTCTRL SDL_SCANCODE_RCTRL\r\n#define SDLC_KEYSTATE_LEFTSHIFT SDL_SCANCODE_LSHIFT\r\n#define SDLC_KEYSTATE_RIGHTSHIFT SDL_SCANCODE_RSHIFT\r\n#define SDLC_KEYSTATE_LALT SDL_SCANCODE_LALT\r\n#define SDLC_KEYSTATE_RALT SDL_SCANCODE_RALT\r\n#define SDLC_KEYSTATE_UP SDL_SCANCODE_UP\r\n#define SDLC_KEYSTATE_DOWN SDL_SCANCODE_DOWN\r\n#define SDLC_KEYSTATE_LEFT SDL_SCANCODE_LEFT\r\n#define SDLC_KEYSTATE_RIGHT SDL_SCANCODE_RIGHT\r\n#else\r\n#define SDLC_KEYSTATE_LEFTCTRL SDLK_LCTRL\r\n#define SDLC_KEYSTATE_RIGHTCTRL SDLK_RCTRL\r\n#define SDLC_KEYSTATE_LEFTSHIFT SDLK_LSHIFT\r\n#define SDLC_KEYSTATE_RIGHTSHIFT SDLK_LSHIFT\r\n#define SDLC_KEYSTATE_LALT SDLK_LALT\r\n#define SDLC_KEYSTATE_RALT SDLK_RALT\r\n#define SDLC_KEYSTATE_UP SDLK_UP\r\n#define SDLC_KEYSTATE_DOWN SDLK_DOWN\r\n#define SDLC_KEYSTATE_LEFT SDLK_LEFT\r\n#define SDLC_KEYSTATE_RIGHT SDLK_RIGHT\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\ninline const bool *SDLC_GetKeyState()\r\n#else\r\ninline const Uint8 *SDLC_GetKeyState()\r\n#endif\r\n{\r\n#ifndef USE_SDL1\r\n\treturn SDL_GetKeyboardState(nullptr);\r\n#else\r\n\treturn SDL_GetKeyState(nullptr);\r\n#endif\r\n}\r\n\r\n// Convert events to renderer coordinates.\r\n// This is done automatically in SDL2 but not in SDL3 and SDL1.2.\r\ninline bool SDLC_ConvertEventToRenderCoordinates(\r\n#ifndef USE_SDL1\r\n    SDL_Renderer *renderer,\r\n#else\r\n    void *,\r\n#endif\r\n    SDL_Event *event)\r\n{\r\n#ifdef USE_SDL3\r\n\tif (renderer != nullptr) {\r\n\t\treturn SDL_ConvertEventToRenderCoordinates(renderer, event);\r\n\t}\r\n#elif !defined(USE_SDL1)\r\n\t// No-op in SDL2.\r\n#else\r\n\tif (event->type == SDL_MOUSEMOTION) {\r\n\t\tdevilution::OutputToLogical(&event->motion.x, &event->motion.y);\r\n\t} else if (event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP) {\r\n\t\tdevilution::OutputToLogical(&event->button.x, &event->button.y);\r\n\t}\r\n#endif\r\n\treturn true;\r\n}\r\n\r\n// Sets the palette's colors and:\r\n// SDL3 and SDL2: Points the surface's palette to the given palette if necessary.\r\n// SDL1: Sets the surface's colors.\r\ninline bool SDLC_SetSurfaceAndPaletteColors(SDL_Surface *surface, SDL_Palette *palette, SDL_Color *colors, int firstcolor, int ncolors)\r\n{\r\n#if defined(USE_SDL1)\r\n\tif (ncolors > (palette->ncolors - firstcolor)) {\r\n\t\tSDL_SetError(\"ncolors > (palette->ncolors - firstcolor)\");\r\n\t\treturn false;\r\n\t}\r\n\tif (colors != (palette->colors + firstcolor))\r\n\t\tSDL_memcpy(palette->colors + firstcolor, colors, ncolors * sizeof(*colors));\r\n\r\n#if SDL1_VIDEO_MODE_BPP == 8\r\n\t// When the video surface is 8bit, we need to set the output palette as well.\r\n\tSDL_Surface *videoSurface = SDL_GetVideoSurface();\r\n\tSDL_SetColors(videoSurface, colors, firstcolor, ncolors);\r\n\tif (videoSurface == surface) return true;\r\n#endif\r\n\t// In SDL1, the surface always has its own distinct palette, so we need to\r\n\t// update it as well.\r\n\treturn SDL_SetPalette(surface, SDL_LOGPAL, colors, firstcolor, ncolors) != 0;\r\n#elif defined(USE_SDL3)\r\n\tif (!SDL_SetPaletteColors(palette, colors, firstcolor, ncolors)) return false;\r\n\tif (SDL_GetSurfacePalette(surface) != palette) {\r\n\t\tif (!SDL_SetSurfacePalette(surface, palette)) return false;\r\n\t}\r\n\treturn true;\r\n#else\r\n\tif (SDL_SetPaletteColors(palette, colors, firstcolor, ncolors) < 0)\r\n\t\treturn false;\r\n\tif (surface->format->palette != palette)\r\n\t\treturn SDL_SetSurfacePalette(surface, palette) == 0;\r\n\treturn true;\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Source/utils/sdl_geometry.h",
    "content": "/**\r\n * @file sdl_geometry.h\r\n * Helpers for SDL geometry types\r\n */\r\n#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_rect.h>\r\n#else\r\n#include <SDL_version.h>\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n#include <SDL_rect.h>\r\n#else\r\n#include <SDL_video.h>\r\n#endif\r\n#endif\r\n\r\n#include \"engine/rectangle.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Same as constructing directly but avoids type conversion warnings.\r\n */\r\ninline SDL_Rect MakeSdlRect(\r\n    decltype(SDL_Rect {}.x) x, decltype(SDL_Rect {}.y) y,\r\n    decltype(SDL_Rect {}.w) w, decltype(SDL_Rect {}.h) h)\r\n{\r\n\treturn SDL_Rect { x, y, w, h };\r\n}\r\n\r\ninline SDL_Rect MakeSdlRect(Rectangle rect)\r\n{\r\n\treturn MakeSdlRect(rect.position.x, rect.position.y, rect.size.width, rect.size.height);\r\n}\r\n\r\nconstexpr Rectangle MakeRectangle(SDL_Rect sdlRect)\r\n{\r\n\treturn { Point { sdlRect.x, sdlRect.y }, Size { sdlRect.w, sdlRect.h } };\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl_mutex.h",
    "content": "#pragma once\r\n\r\n#include <memory>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_mutex.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL_mutex.h>\r\n#include <SDL_version.h>\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n\r\nnamespace devilution {\r\n\r\n/*\r\n * RAII wrapper for SDL_mutex. Satisfies std's \"Lockable\" (SDL 2) or \"BasicLockable\" (SDL 1)\r\n * requirements so it can be used with std::lock_guard and friends.\r\n */\r\n#ifdef __DJGPP__\r\nclass SdlMutex final {\r\npublic:\r\n\tSdlMutex() noexcept { }\r\n\t~SdlMutex() noexcept { }\r\n\r\n\tSdlMutex(const SdlMutex &) = delete;\r\n\tSdlMutex(SdlMutex &&) = delete;\r\n\tSdlMutex &operator=(const SdlMutex &) = delete;\r\n\tSdlMutex &operator=(SdlMutex &&) = delete;\r\n\r\n\tvoid lock() noexcept { }\r\n\tvoid unlock() noexcept { }\r\n\r\n\tvoid *get() noexcept { return nullptr; } // Dummy\r\n};\r\n#else\r\nclass SdlMutex final {\r\npublic:\r\n\tSdlMutex()\r\n\t    : mutex_(SDL_CreateMutex())\r\n\t{\r\n\t\tif (mutex_ == nullptr)\r\n\t\t\tErrSdl();\r\n\t}\r\n\r\n\t~SdlMutex()\r\n\t{\r\n\t\tSDL_DestroyMutex(mutex_);\r\n\t}\r\n\r\n\tSdlMutex(const SdlMutex &) = delete;\r\n\tSdlMutex(SdlMutex &&) = delete;\r\n\tSdlMutex &operator=(const SdlMutex &) = delete;\r\n\tSdlMutex &operator=(SdlMutex &&) = delete;\r\n\r\n\tvoid lock() noexcept // NOLINT(readability-identifier-naming)\r\n\t{\r\n#ifdef USE_SDL3\r\n\t\tSDL_LockMutex(mutex_);\r\n#else\r\n\t\tint err = SDL_LockMutex(mutex_);\r\n\t\tif (err == -1) ErrSdl();\r\n#endif\r\n\t}\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t[[nodiscard]] bool try_lock() noexcept // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\tconst bool ok =\r\n#ifdef USE_SDL3\r\n\t\t    SDL_TryLockMutex(mutex_);\r\n#else\r\n\t\t    SDL_TryLockMutex(mutex_) == 0;\r\n#endif\r\n\t\treturn ok;\r\n\t}\r\n#endif\r\n\r\n\tvoid unlock() noexcept // NOLINT(readability-identifier-naming)\r\n\t{\r\n#ifdef USE_SDL3\r\n\t\tSDL_UnlockMutex(mutex_);\r\n#else\r\n\t\tint err = SDL_UnlockMutex(mutex_);\r\n\t\tif (err == -1) ErrSdl();\r\n#endif\r\n\t}\r\n\r\n#ifdef USE_SDL3\r\n\tSDL_Mutex *get() { return mutex_; }\r\n#else\r\n\tSDL_mutex *get() { return mutex_; }\r\n#endif\r\n\r\nprivate:\r\n#ifdef USE_SDL3\r\n\tSDL_Mutex *mutex_;\r\n#else\r\n\tSDL_mutex *mutex_;\r\n#endif\r\n};\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl_ptrs.h",
    "content": "#pragma once\r\n/**\r\n * @brief std::unique_ptr specializations for SDL types.\r\n */\r\n\r\n#include <memory>\r\n#include <type_traits>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_mouse.h>\r\n#include <SDL3/SDL_pixels.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_stdinc.h>\r\n#include <SDL3/SDL_surface.h>\r\n#include <SDL3/SDL_version.h>\r\n#else\r\n#include <SDL.h>\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Deletes the SDL surface using `SDL_FreeSurface`.\r\n */\r\nstruct SDLSurfaceDeleter {\r\n\tvoid operator()(SDL_Surface *surface) const\r\n\t{\r\n#ifdef USE_SDL3\r\n\t\tSDL_DestroySurface(surface);\r\n#else\r\n\t\tSDL_FreeSurface(surface);\r\n#endif\r\n\t}\r\n};\r\n\r\nusing SDLSurfaceUniquePtr = std::unique_ptr<SDL_Surface, SDLSurfaceDeleter>;\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\nstruct SDLCursorDeleter {\r\n\tvoid operator()(SDL_Cursor *cursor) const\r\n\t{\r\n#ifdef USE_SDL3\r\n\t\tSDL_DestroyCursor(cursor);\r\n#else\r\n\t\tSDL_FreeCursor(cursor);\r\n#endif\r\n\t}\r\n};\r\n\r\nusing SDLCursorUniquePtr = std::unique_ptr<SDL_Cursor, SDLCursorDeleter>;\r\n\r\nstruct SDLTextureDeleter {\r\n\tvoid operator()(SDL_Texture *texture) const\r\n\t{\r\n\t\tSDL_DestroyTexture(texture);\r\n\t}\r\n};\r\n\r\nusing SDLTextureUniquePtr = std::unique_ptr<SDL_Texture, SDLTextureDeleter>;\r\n#endif\r\n\r\nstruct SDLPaletteDeleter {\r\n\tvoid operator()(SDL_Palette *palette) const\r\n\t{\r\n#ifdef USE_SDL3\r\n\t\tSDL_DestroyPalette(palette);\r\n#else\r\n\t\tSDL_FreePalette(palette);\r\n#endif\r\n\t}\r\n};\r\n\r\nusing SDLPaletteUniquePtr = std::unique_ptr<SDL_Palette, SDLPaletteDeleter>;\r\n\r\n/**\r\n * @brief Deletes the object using `SDL_free`.\r\n */\r\ntemplate <typename T>\r\nstruct SDLFreeDeleter {\r\n\tstatic_assert(!std::is_same<T, SDL_Surface>::value,\r\n\t    \"SDL_Surface should use SDLSurfaceUniquePtr instead.\");\r\n\r\n\tvoid operator()(T *obj) const\r\n\t{\r\n\t\tSDL_free(obj);\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief A unique pointer to T that is deleted with SDL_free.\r\n */\r\ntemplate <typename T>\r\nusing SDLUniquePtr = std::unique_ptr<T, SDLFreeDeleter<T>>;\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl_thread.cpp",
    "content": "#include \"utils/sdl_thread.h\"\r\n\r\nnamespace devilution {\r\n\r\n#ifndef __DJGPP__\r\nint SDLCALL SdlThread::ThreadTranslate(void *ptr)\r\n{\r\n\tauto handler = (void (*)())ptr;\r\n\r\n\thandler();\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid SdlThread::ThreadDeleter(SDL_Thread *thread)\r\n{\r\n\tif (thread != nullptr)\r\n\t\tapp_fatal(\"Joinable thread destroyed\");\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl_thread.h",
    "content": "#pragma once\r\n\r\n#include <memory>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_thread.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace this_sdl_thread {\r\n#ifdef USE_SDL3\r\ninline SDL_ThreadID get_id()\r\n#else\r\ninline SDL_threadID get_id()\r\n#endif\r\n{\r\n#if defined(__DJGPP__)\r\n\treturn 1;\r\n#else\r\n\treturn SDL_GetThreadID(nullptr);\r\n#endif\r\n}\r\n} // namespace this_sdl_thread\r\n\r\n#if defined(__DJGPP__)\r\nclass SdlThread final {\r\npublic:\r\n\tSdlThread(int(SDLCALL *handler)(void *), void *data)\r\n\t{\r\n\t\tif (handler != nullptr) handler(data);\r\n\t}\r\n\texplicit SdlThread(void (*handler)(void))\r\n\t{\r\n\t\tif (handler != nullptr) handler();\r\n\t}\r\n\tSdlThread() = default;\r\n\tbool joinable() const\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n#ifdef USE_SDL3\r\n\tSDL_ThreadID get_id() const\r\n#else\r\n\tSDL_threadID get_id() const\r\n#endif\r\n\t{\r\n\t\treturn this_sdl_thread::get_id();\r\n\t}\r\n\tvoid join()\r\n\t{\r\n\t}\r\n};\r\n#else\r\n\r\nclass SdlThread final {\r\n\tstatic int SDLCALL ThreadTranslate(void *ptr);\r\n\tstatic void ThreadDeleter(SDL_Thread *thread);\r\n\r\n\tstd::unique_ptr<SDL_Thread, void (*)(SDL_Thread *)> thread { nullptr, ThreadDeleter };\r\n\r\npublic:\r\n\tSdlThread(int(SDLCALL *handler)(void *), void *data)\r\n#ifdef USE_SDL1\r\n\t    : thread(SDL_CreateThread(handler, data), ThreadDeleter)\r\n#else\r\n\t    : thread(SDL_CreateThread(handler, nullptr, data), ThreadDeleter)\r\n#endif\r\n\t{\r\n\t\tif (thread == nullptr)\r\n\t\t\tErrSdl();\r\n\t}\r\n\r\n\texplicit SdlThread(void (*handler)(void))\r\n\t    : SdlThread(ThreadTranslate, (void *)handler)\r\n\t{\r\n\t}\r\n\r\n\tSdlThread() = default;\r\n\r\n\tbool joinable() const\r\n\t{\r\n\t\treturn thread != nullptr;\r\n\t}\r\n\r\n#ifdef USE_SDL3\r\n\tSDL_ThreadID get_id() const\r\n#else\r\n\tSDL_threadID get_id() const\r\n#endif\r\n\t{\r\n\t\treturn SDL_GetThreadID(thread.get());\r\n\t}\r\n\r\n\tvoid join()\r\n\t{\r\n\t\tif (!joinable())\r\n\t\t\treturn;\r\n\t\tif (get_id() == this_sdl_thread::get_id())\r\n\t\t\tapp_fatal(\"Thread joined from within itself\");\r\n\r\n\t\tSDL_WaitThread(thread.get(), nullptr);\r\n\t\tthread.release();\r\n\t}\r\n};\r\n\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/sdl_wrap.h",
    "content": "#pragma once\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_pixels.h>\r\n#include <SDL3/SDL_render.h>\r\n#include <SDL3/SDL_stdinc.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#endif\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/sdl_ptrs.h\"\r\n\r\n#define NonNull(x) NullErrDlg(x, __FILE__, __LINE__)\r\n\r\nnamespace devilution {\r\n\r\nnamespace SDLWrap {\r\n\r\ntemplate <typename T>\r\nT NullErrDlg(T x, const char *file, int line)\r\n{\r\n\tif (x == nullptr)\r\n\t\tErrDlg(\"SDL Error\", SDL_GetError(), file, line);\r\n\treturn x;\r\n}\r\n\r\ninline SDLSurfaceUniquePtr CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_CreateSurface(width, height, SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask))) };\r\n#else\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask, Amask)) };\r\n#endif\r\n}\r\n\r\n#ifdef USE_SDL3\r\ninline SDLSurfaceUniquePtr CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, SDL_PixelFormat format)\r\n{\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_CreateSurface(width, height, format)) };\r\n}\r\n#else\r\ninline SDLSurfaceUniquePtr CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format)\r\n{\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_CreateRGBSurfaceWithFormat(flags, width, height, depth, format)) };\r\n}\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\ninline SDLSurfaceUniquePtr CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, SDL_PixelFormat format)\r\n{\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_CreateSurfaceFrom(width, height, format, pixels, pitch)) };\r\n}\r\n#else\r\ninline SDLSurfaceUniquePtr CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 format)\r\n{\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, depth, pitch, format)) };\r\n}\r\n#endif\r\n\r\n#ifndef USE_SDL1\r\ninline SDLSurfaceUniquePtr ConvertSurface(SDL_Surface *src, const SDL_PixelFormat *fmt, Uint32 flags)\r\n#else\r\ninline SDLSurfaceUniquePtr ConvertSurface(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags)\r\n#endif\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_ConvertSurface(src, *fmt)) };\r\n#else\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_ConvertSurface(src, fmt, flags)) };\r\n#endif\r\n}\r\n\r\n#ifndef USE_SDL1\r\n#ifdef USE_SDL3\r\ninline SDLSurfaceUniquePtr ConvertSurfaceFormat(SDL_Surface *src, SDL_PixelFormat format, Uint32 flags)\r\n{\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_ConvertSurface(src, format)) };\r\n}\r\n#else\r\ninline SDLSurfaceUniquePtr ConvertSurfaceFormat(SDL_Surface *src, Uint32 format, Uint32 flags)\r\n{\r\n\treturn SDLSurfaceUniquePtr { NonNull(SDL_ConvertSurfaceFormat(src, format, flags)) };\r\n}\r\n#endif\r\n\r\n#ifdef USE_SDL3\r\ninline SDLTextureUniquePtr CreateTexture(SDL_Renderer *renderer, SDL_PixelFormat format, SDL_TextureAccess access, int w, int h)\r\n{\r\n\treturn SDLTextureUniquePtr { NonNull(SDL_CreateTexture(renderer, format, access, w, h)) };\r\n}\r\n#else\r\ninline SDLTextureUniquePtr CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h)\r\n{\r\n\treturn SDLTextureUniquePtr { NonNull(SDL_CreateTexture(renderer, format, access, w, h)) };\r\n}\r\n#endif\r\n#endif\r\n\r\ninline SDLPaletteUniquePtr AllocPalette(int ncolors = 256)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn SDLPaletteUniquePtr { NonNull(SDL_CreatePalette(ncolors)) };\r\n#else\r\n\treturn SDLPaletteUniquePtr { NonNull(SDL_AllocPalette(ncolors)) };\r\n#endif\r\n}\r\n\r\n} // namespace SDLWrap\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/soundsample.cpp",
    "content": "#include \"utils/soundsample.h\"\r\n\r\n#include <chrono>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <utility>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <Aulib/DecoderDrmp3.h>\r\n#include <Aulib/DecoderDrwav.h>\r\n#include <Aulib/Stream.h>\r\n\r\n#include <SDL.h>\r\n#ifdef USE_SDL1\r\n#include \"utils/sdl2_to_1_2_backports.h\"\r\n#else\r\n#include \"utils/sdl2_backports.h\"\r\n#endif\r\n#include \"utils/aulib.hpp\"\r\n#endif\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/math.h\"\r\n#include \"utils/stubs.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconstexpr float LogBase = 10.0;\r\n\r\n/**\r\n * Scaling factor for attenuating volume.\r\n * Picked so that a volume change of -10 dB results in half perceived loudness.\r\n * VolumeScale = -1000 / log(0.5)\r\n */\r\nconstexpr float VolumeScale = 3321.9281F;\r\n\r\n/**\r\n * Min and max volume range, in millibel.\r\n * -100 dB (muted) to 0 dB (max. loudness).\r\n */\r\nconstexpr float MillibelMin = -10000.F;\r\nconstexpr float MillibelMax = 0.F;\r\n\r\n/**\r\n * Stereo separation factor for left/right speaker panning. Lower values increase separation, moving\r\n * sounds further left/right, while higher values will pull sounds more towards the middle, reducing separation.\r\n * Current value is tuned to have ~2:1 mix for sounds that happen on the edge of a 640x480 screen.\r\n */\r\nconstexpr float StereoSeparation = 6000.F;\r\n\r\n#ifndef USE_SDL3\r\nfloat PanLogToLinear(int logPan)\r\n{\r\n\tif (logPan == 0)\r\n\t\treturn 0;\r\n\r\n\tauto factor = std::pow(LogBase, static_cast<float>(-std::abs(logPan)) / StereoSeparation);\r\n\r\n\treturn copysign(1.F - factor, static_cast<float>(logPan));\r\n}\r\n\r\nstd::unique_ptr<Aulib::Decoder> CreateDecoder(bool isMp3)\r\n{\r\n\tif (isMp3)\r\n\t\treturn std::make_unique<Aulib::DecoderDrmp3>();\r\n\treturn std::make_unique<Aulib::DecoderDrwav>();\r\n}\r\n\r\nstd::unique_ptr<Aulib::Stream> CreateStream(SDL_IOStream *handle, bool isMp3)\r\n{\r\n\tauto decoder = CreateDecoder(isMp3);\r\n\tif (!decoder->open(handle)) // open for `getRate`\r\n\t\treturn nullptr;\r\n\tauto resampler = CreateAulibResampler(decoder->getRate());\r\n\treturn std::make_unique<Aulib::Stream>(handle, std::move(decoder), std::move(resampler), /*closeRw=*/true);\r\n}\r\n\r\n/**\r\n * @brief Converts log volume passed in into linear volume.\r\n * @param logVolume Logarithmic volume in the range [logMin..logMax]\r\n * @param logMin Volume range minimum (usually ATTENUATION_MIN for game sounds and VOLUME_MIN for volume sliders)\r\n * @param logMax Volume range maximum (usually 0)\r\n * @return Linear volume in the range [0..1]\r\n */\r\nfloat VolumeLogToLinear(int logVolume, int logMin, int logMax)\r\n{\r\n\tconst auto logScaled = math::Remap(static_cast<float>(logMin), static_cast<float>(logMax), MillibelMin, MillibelMax, static_cast<float>(logVolume));\r\n\treturn std::pow(LogBase, logScaled / VolumeScale); // linVolume\r\n}\r\n#endif\r\n\r\n} // namespace\r\n\r\n///// SoundSample /////\r\n\r\n#ifndef USE_SDL3\r\nvoid SoundSample::SetFinishCallback(Aulib::Stream::Callback &&callback)\r\n{\r\n\tstream_->setFinishCallback(std::forward<Aulib::Stream::Callback>(callback));\r\n}\r\n#endif\r\n\r\nvoid SoundSample::Stop()\r\n{\r\n#ifndef USE_SDL3\r\n\tstream_->stop();\r\n#endif\r\n}\r\n\r\nvoid SoundSample::Mute()\r\n{\r\n#ifndef USE_SDL3\r\n\tstream_->mute();\r\n#endif\r\n}\r\n\r\nvoid SoundSample::Unmute()\r\n{\r\n#ifndef USE_SDL3\r\n\tstream_->unmute();\r\n#endif\r\n}\r\n\r\nvoid SoundSample::Release()\r\n{\r\n#ifndef USE_SDL3\r\n\tstream_ = nullptr;\r\n#endif\r\n\tfile_data_ = nullptr;\r\n\tfile_data_size_ = 0;\r\n}\r\n\r\n/**\r\n * @brief Check if a the sound is being played atm\r\n */\r\nbool SoundSample::IsPlaying()\r\n{\r\n#ifdef USE_SDL3\r\n\treturn false;\r\n#else\r\n\treturn stream_ && stream_->isPlaying();\r\n#endif\r\n}\r\n\r\nbool SoundSample::Play(int numIterations)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn false;\r\n#else\r\n\tif (!stream_->play(numIterations)) {\r\n\t\tLogError(LogCategory::Audio, \"Aulib::Stream::play (from SoundSample::Play): {}\", SDL_GetError());\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n#endif\r\n}\r\n\r\nint SoundSample::SetChunkStream(std::string filePath, bool isMp3, bool logErrors)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn 0;\r\n#else\r\n\tSDL_IOStream *handle = OpenAssetAsSdlRwOps(filePath.c_str(), /*threadsafe=*/true);\r\n\tif (handle == nullptr) {\r\n\t\tif (logErrors)\r\n\t\t\tLogError(LogCategory::Audio, \"OpenAsset failed (from SoundSample::SetChunkStream) for {}: {}\", filePath, SDL_GetError());\r\n\t\treturn -1;\r\n\t}\r\n\tfile_path_ = std::move(filePath);\r\n\tisMp3_ = isMp3;\r\n\tstream_ = CreateStream(handle, isMp3);\r\n\tif (!stream_->open()) {\r\n\t\tstream_ = nullptr;\r\n\t\tif (logErrors)\r\n\t\t\tLogError(LogCategory::Audio, \"Aulib::Stream::open (from SoundSample::SetChunkStream) for {}: {}\", file_path_, SDL_GetError());\r\n\t\treturn -1;\r\n\t}\r\n\treturn 0;\r\n#endif\r\n}\r\n\r\nint SoundSample::SetChunk(ArraySharedPtr<std::uint8_t> fileData, std::size_t dwBytes, bool isMp3)\r\n{\r\n#ifdef USE_SDL3\r\n\treturn 0;\r\n#else\r\n\tisMp3_ = isMp3;\r\n\tfile_data_ = std::move(fileData);\r\n\tfile_data_size_ = dwBytes;\r\n\tSDL_IOStream *buf = SDL_IOFromConstMem(file_data_.get(), static_cast<int>(dwBytes));\r\n\tif (buf == nullptr) {\r\n\t\treturn -1;\r\n\t}\r\n\r\n\tstream_ = CreateStream(buf, isMp3_);\r\n\tif (!stream_->open()) {\r\n\t\tstream_ = nullptr;\r\n\t\tfile_data_ = nullptr;\r\n\t\tLogError(LogCategory::Audio, \"Aulib::Stream::open (from SoundSample::SetChunk): {}\", SDL_GetError());\r\n\t\treturn -1;\r\n\t}\r\n\r\n\treturn 0;\r\n#endif\r\n}\r\n\r\nvoid SoundSample::SetVolume(int logVolume, int logMin, int logMax)\r\n{\r\n#ifndef USE_SDL3\r\n\tstream_->setVolume(VolumeLogToLinear(logVolume, logMin, logMax));\r\n#endif\r\n}\r\n\r\nvoid SoundSample::SetStereoPosition(int logPan)\r\n{\r\n#ifndef USE_SDL3\r\n\tstream_->setStereoPosition(PanLogToLinear(logPan));\r\n#endif\r\n}\r\n\r\nint SoundSample::GetLength() const\r\n{\r\n#ifdef USE_SDL3\r\n\treturn 0;\r\n#else\r\n\tif (!stream_)\r\n\t\treturn 0;\r\n\treturn static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(stream_->duration()).count());\r\n#endif\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/soundsample.h",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <functional>\r\n#include <memory>\r\n#include <string>\r\n\r\n#include \"engine/sound_defs.hpp\"\r\n#include \"utils/stdcompat/shared_ptr_array.hpp\"\r\n\r\n#ifndef USE_SDL3\r\n// Forward-declares Aulib::Stream to avoid adding dependencies\r\n// on SDL_audiolib to every user of this header.\r\nnamespace Aulib {\r\nclass Stream;\r\n} // namespace Aulib\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nclass SoundSample final {\r\npublic:\r\n\tSoundSample() = default;\r\n\tSoundSample(SoundSample &&) noexcept = default;\r\n\tSoundSample &operator=(SoundSample &&) noexcept = default;\r\n\r\n\t[[nodiscard]] bool IsLoaded() const\r\n\t{\r\n#ifdef USE_SDL3\r\n\t\treturn false;\r\n#else\r\n\t\treturn stream_ != nullptr;\r\n#endif\r\n\t}\r\n\r\n\tvoid Release();\r\n\tbool IsPlaying();\r\n\r\n\t// Returns 0 on success.\r\n\tint SetChunkStream(std::string filePath, bool isMp3, bool logErrors = true);\r\n\r\n#ifndef USE_SDL3\r\n\tvoid SetFinishCallback(std::function<void(Aulib::Stream &)> &&callback);\r\n#endif\r\n\r\n\t/**\r\n\t * @brief Sets the sample's WAV, FLAC, or Ogg/Vorbis data.\r\n\t * @param fileData Buffer containing the data\r\n\t * @param dwBytes Length of buffer\r\n\t * @param isMp3 Whether the data is an MP3\r\n\t * @return 0 on success, -1 otherwise\r\n\t */\r\n\tint SetChunk(ArraySharedPtr<std::uint8_t> fileData, std::size_t dwBytes, bool isMp3);\r\n\r\n\t[[nodiscard]] bool IsStreaming() const\r\n\t{\r\n\t\treturn file_data_ == nullptr;\r\n\t}\r\n\r\n\tint DuplicateFrom(const SoundSample &other)\r\n\t{\r\n\t\tif (other.IsStreaming())\r\n\t\t\treturn SetChunkStream(other.file_path_, other.isMp3_);\r\n\t\treturn SetChunk(other.file_data_, other.file_data_size_, other.isMp3_);\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Start playing the sound for a given number of iterations (0 means loop).\r\n\t */\r\n\tbool Play(int numIterations = 1);\r\n\r\n\t/**\r\n\t * @brief Start playing the sound with the given sound and user volume, and a stereo position.\r\n\t */\r\n\tbool PlayWithVolumeAndPan(int logSoundVolume, int logUserVolume, int logPan)\r\n\t{\r\n\t\tSetVolume(logSoundVolume + logUserVolume * (ATTENUATION_MIN / VOLUME_MIN), ATTENUATION_MIN, 0);\r\n\t\tSetStereoPosition(logPan);\r\n\t\treturn Play();\r\n\t}\r\n\r\n\t/**\r\n\t * @brief Stop playing the sound\r\n\t */\r\n\tvoid Stop();\r\n\r\n\tvoid SetVolume(int logVolume, int logMin, int logMax);\r\n\tvoid SetStereoPosition(int logPan);\r\n\r\n\tvoid Mute();\r\n\tvoid Unmute();\r\n\r\n\t/**\r\n\t * @return Audio duration in ms\r\n\t */\r\n\tint GetLength() const;\r\n\r\nprivate:\r\n\t// Non-streaming audio fields:\r\n\tArraySharedPtr<std::uint8_t> file_data_;\r\n\tstd::size_t file_data_size_;\r\n\r\n\t// Set for streaming audio to allow for duplicating it:\r\n\tstd::string file_path_;\r\n\r\n\tbool isMp3_;\r\n\r\n#ifndef USE_SDL3\r\n\tstd::unique_ptr<Aulib::Stream> stream_;\r\n#endif\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/static_vector.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <initializer_list>\r\n#include <memory>\r\n#include <utility>\r\n\r\n#include \"appfat.h\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief A stack-allocated vector with a fixed capacity.\r\n *\r\n * @tparam T element type.\r\n * @tparam N capacity.\r\n */\r\ntemplate <class T, size_t N>\r\nclass StaticVector {\r\npublic:\r\n\tusing value_type = T;\r\n\tusing reference = T &;\r\n\tusing const_reference = const T &;\r\n\tusing pointer = T *;\r\n\tusing const_pointer = const T *;\r\n\tusing size_type = size_t;\r\n\tusing iterator = T *;\r\n\tusing const_iterator = const T *;\r\n\tusing difference_type = std::ptrdiff_t;\r\n\r\n\tStaticVector() = default;\r\n\r\n\ttemplate <typename U>\r\n\tStaticVector(std::initializer_list<U> elements)\r\n\t{\r\n\t\tfor (auto &&element : elements) {\r\n\t\t\templace_back(element);\r\n\t\t}\r\n\t}\r\n\r\n\t[[nodiscard]] const T *begin() const { return &(*this)[0]; }\r\n\t[[nodiscard]] T *begin() { return &(*this)[0]; }\r\n\r\n\t[[nodiscard]] const T *end() const { return begin() + size_; }\r\n\t[[nodiscard]] T *end() { return begin() + size_; }\r\n\r\n\t[[nodiscard]] size_t size() const { return size_; }\r\n\r\n\t[[nodiscard]] bool empty() const DVL_PURE { return size_ == 0; }\r\n\r\n\t[[nodiscard]] const T &front() const { return (*this)[0]; }\r\n\t[[nodiscard]] T &front() { return (*this)[0]; }\r\n\r\n\t[[nodiscard]] const T &back() const { return (*this)[size_ - 1]; }\r\n\t[[nodiscard]] T &back() { return (*this)[size_ - 1]; }\r\n\r\n\t[[nodiscard]] const T *data() const { return data_[0].ptr(); }\r\n\t[[nodiscard]] T *data() { return data_[0].ptr(); }\r\n\r\n\ttemplate <typename... Args>\r\n\tvoid push_back(Args &&...args) // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\templace_back(std::forward<Args>(args)...);\r\n\t}\r\n\r\n\ttemplate <typename... Args>\r\n\tT &emplace_back(Args &&...args) // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\tassert(size_ < N);\r\n\t\treturn *::new (&data_[size_++]) T(std::forward<Args>(args)...);\r\n\t}\r\n\r\n\tconst T &operator[](std::size_t pos) const { return *data_[pos].ptr(); }\r\n\tT &operator[](std::size_t pos) { return *data_[pos].ptr(); }\r\n\r\n\tvoid erase(const T *first, const T *last)\r\n\t{\r\n\t\tif (last == first) return;\r\n\t\tassert(first >= begin() && last <= end() && first <= last);\r\n\t\tconst auto count = last - first;\r\n\t\tauto tail = std::move(const_cast<T *>(last), end(), const_cast<T *>(first));\r\n\t\tstd::destroy(tail, end());\r\n\t\tsize_ -= count;\r\n\t}\r\n\r\n\tvoid erase(const T *element)\r\n\t{\r\n\t\tassert(element >= begin() && element < end());\r\n\t\terase(element, element + 1);\r\n\t}\r\n\r\n\tvoid pop_back() // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\tstd::destroy_at(&back());\r\n\t\t--size_;\r\n\t}\r\n\r\n\tvoid clear()\r\n\t{\r\n\t\terase(begin(), end());\r\n\t}\r\n\r\n\t~StaticVector()\r\n\t{\r\n\t\tstd::destroy_n(data(), size_);\r\n\t}\r\n\r\nprivate:\r\n\tstruct AlignedStorage {\r\n\t\talignas(alignof(T)) std::byte data[sizeof(T)];\r\n\r\n\t\t[[nodiscard]] const T *ptr() const\r\n\t\t{\r\n\t\t\treturn std::launder(reinterpret_cast<const T *>(data));\r\n\t\t}\r\n\r\n\t\t[[nodiscard]] T *ptr()\r\n\t\t{\r\n\t\t\treturn std::launder(reinterpret_cast<T *>(data));\r\n\t\t}\r\n\t};\r\n\tAlignedStorage data_[N];\r\n\tstd::size_t size_ = 0;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/status_macros.hpp",
    "content": "#pragma once\r\n\r\n#include \"utils/attributes.h\"\r\n\r\n#define RETURN_IF_ERROR(expr)                                         \\\r\n\tif (auto result = expr; DVL_PREDICT_FALSE(!result.has_value())) { \\\r\n\t\treturn tl::make_unexpected(std::move(result).error());        \\\r\n\t}\r\n\r\n#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y\r\n#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y)\r\n\r\n#define ASSIGN_OR_RETURN_IMPL(result, lhs, rhs)                                                        \\\r\n\tauto result = rhs;                            /* NOLINT(bugprone-macro-parentheses): assignment */ \\\r\n\tif (DVL_PREDICT_FALSE(!result.has_value())) { /* NOLINT(bugprone-macro-parentheses): assignment */ \\\r\n\t\treturn tl::make_unexpected(std::move(result).error());                                         \\\r\n\t}                                                                                                  \\\r\n\tlhs = std::move(result).value(); /* NOLINT(bugprone-macro-parentheses): assignment */\r\n\r\n#define ASSIGN_OR_RETURN(lhs, rhs) \\\r\n\tASSIGN_OR_RETURN_IMPL(         \\\r\n\t    STATUS_MACROS_CONCAT_NAME(_result, __COUNTER__), lhs, rhs)\r\n"
  },
  {
    "path": "Source/utils/stdcompat/filesystem.hpp",
    "content": "#pragma once\r\n\r\n#if defined(__APPLE__) && DARWIN_MAJOR_VERSION >= 9\r\n#include <Availability.h>\r\n#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500) \\\r\n    || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000)\r\n#define DVL_NO_FILESYSTEM\r\n#endif\r\n#elif defined(NXDK) || (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) \\\r\n    || (defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0))\r\n#define DVL_NO_FILESYSTEM\r\n#endif\r\n\r\n#ifndef DVL_NO_FILESYSTEM\r\n#if defined(__has_include)\r\n#if __has_include(<filesystem>)\r\n#define DVL_HAS_FILESYSTEM\r\n#include <filesystem> // IWYU pragma: export\r\n#elif __has_include(<experimental/filesystem>)\r\n#define DVL_HAS_FILESYSTEM\r\n#include <experimental/filesystem> // IWYU pragma: export\r\n#define filesystem experimental::filesystem\r\n#endif\r\n#endif\r\n#endif\r\n"
  },
  {
    "path": "Source/utils/stdcompat/shared_ptr_array.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <memory>\r\n\r\nnamespace devilution {\r\n\r\n// Apple Clang 12 has a buggy implementation that fails to compile `std::shared_ptr<T[]>(new T[size])`.\r\n#if (__cplusplus >= 201611L && (!defined(__clang_major__) || __clang_major__ >= 13)) && !defined(NXDK)\r\ntemplate <typename T>\r\nusing ArraySharedPtr = std::shared_ptr<T[]>;\r\n\r\ntemplate <typename T>\r\nArraySharedPtr<T> MakeArraySharedPtr(std::size_t size)\r\n{\r\n\treturn ArraySharedPtr<T>(new T[size]);\r\n}\r\n#else\r\ntemplate <typename T>\r\nusing ArraySharedPtr = std::shared_ptr<T>;\r\n\r\ntemplate <typename T>\r\nArraySharedPtr<T> MakeArraySharedPtr(std::size_t size)\r\n{\r\n\treturn ArraySharedPtr<T> { new T[size], std::default_delete<T[]>() };\r\n}\r\n#endif\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/str_case.cpp",
    "content": "#include \"utils/str_case.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid AsciiStrToLower(std::string &str)\r\n{\r\n\tfor (char &c : str) { // NOLINT(readability-identifier-length)\r\n\t\tif (c >= 'A' && c <= 'Z')\r\n\t\t\tc += ('a' - 'A');\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/str_case.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n#include <string_view>\r\n\r\nnamespace devilution {\r\n\r\nvoid AsciiStrToLower(std::string &str);\r\n\r\n[[nodiscard]] inline std::string AsciiStrToLower(std::string_view str)\r\n{\r\n\tstd::string copy { str.data(), str.size() };\r\n\tAsciiStrToLower(copy);\r\n\treturn copy;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/str_cat.cpp",
    "content": "#include \"utils/str_cat.hpp\"\r\n\r\n#include <cstdint>\r\n\r\n#include <fmt/format.h>\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\n[[nodiscard]] char HexDigit(uint8_t v) { return \"0123456789abcdef\"[v]; }\r\n[[nodiscard]] char HexDigitUpper(uint8_t v) { return \"0123456789ABCDEF\"[v]; }\r\n\r\n} // namespace\r\n\r\nchar *BufCopy(char *out, long long value)\r\n{\r\n\tconst fmt::format_int formatted { value };\r\n\tstd::memcpy(out, formatted.data(), formatted.size());\r\n\treturn out + formatted.size();\r\n}\r\nchar *BufCopy(char *out, unsigned long long value)\r\n{\r\n\tconst fmt::format_int formatted { value };\r\n\tstd::memcpy(out, formatted.data(), formatted.size());\r\n\treturn out + formatted.size();\r\n}\r\nchar *BufCopy(char *out, AsHexU8Pad2 value)\r\n{\r\n\tif (value.uppercase) {\r\n\t\t*out++ = HexDigitUpper(value.value >> 4);\r\n\t\t*out++ = HexDigitUpper(value.value & 0xf);\r\n\t} else {\r\n\t\t*out++ = HexDigit(value.value >> 4);\r\n\t\t*out++ = HexDigit(value.value & 0xf);\r\n\t}\r\n\treturn out;\r\n}\r\nchar *BufCopy(char *out, AsHexU16Pad2 value)\r\n{\r\n\tif (value.value > 0xff) {\r\n\t\tif (value.value > 0xfff) {\r\n\t\t\tout = BufCopy(out, AsHexU8Pad2 { static_cast<uint8_t>(value.value >> 8) });\r\n\t\t} else {\r\n\t\t\t*out++ = value.uppercase ? HexDigitUpper(value.value >> 8) : HexDigit(value.value >> 8);\r\n\t\t}\r\n\t}\r\n\treturn BufCopy(out, AsHexU8Pad2 { static_cast<uint8_t>(value.value & 0xff) });\r\n}\r\n\r\nvoid StrAppend(std::string &out, long long value)\r\n{\r\n\tconst fmt::format_int formatted { value };\r\n\tout.append(formatted.data(), formatted.size());\r\n}\r\nvoid StrAppend(std::string &out, unsigned long long value)\r\n{\r\n\tconst fmt::format_int formatted { value };\r\n\tout.append(formatted.data(), formatted.size());\r\n}\r\nvoid StrAppend(std::string &out, AsHexU8Pad2 value)\r\n{\r\n\tchar hex[2];\r\n\tBufCopy(hex, value);\r\n\tout.append(hex, 2);\r\n}\r\nvoid StrAppend(std::string &out, AsHexU16Pad2 value)\r\n{\r\n\tchar hex[4];\r\n\tconst auto len = static_cast<size_t>(BufCopy(hex, value) - hex);\r\n\tout.append(hex, len);\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/str_cat.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <string>\r\n#include <string_view>\r\n#include <type_traits>\r\n\r\nnamespace devilution {\r\n\r\nstruct AsHexU8Pad2 {\r\n\tuint8_t value;\r\n\tbool uppercase = false;\r\n};\r\n\r\nstruct AsHexU16Pad2 {\r\n\tuint16_t value;\r\n\tbool uppercase = false;\r\n};\r\n\r\n/** @brief Maximum number of digits for a value of type T.\r\n * If T is signed, also accounts for a potential '-'.\r\n */\r\ntemplate <typename T>\r\nconstexpr size_t MaxNumDigits = (8 * sizeof(T) * 28 / 93) + 1 + (std::is_signed_v<T> ? 1 : 0);\r\n\r\ntemplate <typename T>\r\nstruct LeftPadT {\r\n\tT value;\r\n\tunsigned length;\r\n\tchar padChar;\r\n};\r\n\r\n/**\r\n * @brief Formats the value as a lowercase zero-padded hexadecimal with at least 2 hex digits (0-padded on the left).\r\n */\r\nconstexpr AsHexU8Pad2 AsHexPad2(uint8_t value, bool uppercase = false) { return { value, uppercase }; }\r\n\r\n/**\r\n * @brief Formats the value as a lowercase zero-padded hexadecimal with at least 2 hex digits (0-padded on the left).\r\n */\r\nconstexpr AsHexU16Pad2 AsHexPad2(uint16_t value, bool uppercase = false) { return { value, uppercase }; }\r\n\r\n/**\r\n * @brief Left-pads the value to the specified length with the specified character.\r\n */\r\ntemplate <typename T>\r\nconstexpr LeftPadT<T> LeftPad(T value, unsigned length, char padChar) { return { value, length, padChar }; }\r\n\r\n/**\r\n * @brief Writes the integer to the given buffer.\r\n * @return char* end of the buffer\r\n */\r\nchar *BufCopy(char *out, long long value);\r\ninline char *BufCopy(char *out, long value)\r\n{\r\n\treturn BufCopy(out, static_cast<long long>(value));\r\n}\r\ninline char *BufCopy(char *out, int value)\r\n{\r\n\treturn BufCopy(out, static_cast<long long>(value));\r\n}\r\ninline char *BufCopy(char *out, short value)\r\n{\r\n\treturn BufCopy(out, static_cast<long long>(value));\r\n}\r\n\r\n/**\r\n * @brief Writes the integer to the given buffer.\r\n * @return char* end of the buffer\r\n */\r\nchar *BufCopy(char *out, unsigned long long value);\r\ninline char *BufCopy(char *out, unsigned long value)\r\n{\r\n\treturn BufCopy(out, static_cast<unsigned long long>(value));\r\n}\r\ninline char *BufCopy(char *out, unsigned int value)\r\n{\r\n\treturn BufCopy(out, static_cast<unsigned long long>(value));\r\n}\r\ninline char *BufCopy(char *out, unsigned short value)\r\n{\r\n\treturn BufCopy(out, static_cast<unsigned long long>(value));\r\n}\r\n\r\nchar *BufCopy(char *out, AsHexU8Pad2 value);\r\nchar *BufCopy(char *out, AsHexU16Pad2 value);\r\n\r\ntemplate <typename T>\r\nchar *BufCopy(char *out, LeftPadT<T> value)\r\n{\r\n\tchar buf[MaxNumDigits<T>];\r\n\tconst char *end = BufCopy(buf, value.value);\r\n\tconst std::string_view str = std::string_view(buf, end - buf);\r\n\tfor (size_t i = str.size(); i < value.length; ++i) {\r\n\t\t*out++ = value.padChar;\r\n\t}\r\n\tstd::memcpy(out, str.data(), str.size());\r\n\treturn out + str.size();\r\n}\r\n\r\n/**\r\n * @brief Appends the integer to the given string.\r\n */\r\nvoid StrAppend(std::string &out, long long value);\r\ninline void StrAppend(std::string &out, long value)\r\n{\r\n\tStrAppend(out, static_cast<long long>(value));\r\n}\r\ninline void StrAppend(std::string &out, int value)\r\n{\r\n\tStrAppend(out, static_cast<long long>(value));\r\n}\r\ninline void StrAppend(std::string &out, short value)\r\n{\r\n\tStrAppend(out, static_cast<long long>(value));\r\n}\r\n\r\n/**\r\n * @brief Appends the integer to the given string.\r\n */\r\nvoid StrAppend(std::string &out, unsigned long long value);\r\ninline void StrAppend(std::string &out, unsigned long value)\r\n{\r\n\tStrAppend(out, static_cast<unsigned long long>(value));\r\n}\r\ninline void StrAppend(std::string &out, unsigned int value)\r\n{\r\n\tStrAppend(out, static_cast<unsigned long long>(value));\r\n}\r\ninline void StrAppend(std::string &out, unsigned short value)\r\n{\r\n\tStrAppend(out, static_cast<unsigned long long>(value));\r\n}\r\n\r\nvoid StrAppend(std::string &out, AsHexU8Pad2 value);\r\nvoid StrAppend(std::string &out, AsHexU16Pad2 value);\r\n\r\ntemplate <typename T>\r\nvoid StrAppend(std::string &out, LeftPadT<T> value)\r\n{\r\n\tchar buf[MaxNumDigits<T>];\r\n\tconst auto len = static_cast<size_t>(BufCopy(buf, value) - buf);\r\n\tout.append(buf, len);\r\n}\r\n\r\n/**\r\n * @brief Copies the given std::string_view to the given buffer.\r\n */\r\ninline char *BufCopy(char *out, std::string_view value)\r\n{\r\n\tstd::memcpy(out, value.data(), value.size());\r\n\treturn out + value.size();\r\n}\r\n\r\n/**\r\n * @brief Copies the given std::string_view to the given string.\r\n */\r\ninline void StrAppend(std::string &out, std::string_view value)\r\n{\r\n\tout.append(value);\r\n}\r\n\r\n/**\r\n * @brief Appends the given C string to the given buffer.\r\n *\r\n * `str` must be a null-terminated C string, `out` will not be null terminated.\r\n */\r\ninline char *BufCopy(char *out, const char *str)\r\n{\r\n\treturn BufCopy(out, std::string_view(str != nullptr ? str : \"(nullptr)\"));\r\n}\r\n\r\n/**\r\n * @brief Appends the given C string to the given string.\r\n */\r\ninline void StrAppend(std::string &out, const char *str)\r\n{\r\n\tout.append(std::string_view(str != nullptr ? str : \"(nullptr)\"));\r\n}\r\n\r\ntemplate <typename... Args>\r\ntypename std::enable_if<(sizeof...(Args) > 1), char *>::type\r\nBufCopy(char *out, Args &&...args)\r\n{\r\n\treturn ((out = BufCopy(out, std::forward<Args>(args))), ...);\r\n}\r\n\r\ntemplate <typename... Args>\r\ntypename std::enable_if<(sizeof...(Args) > 1), void>::type\r\nStrAppend(std::string &out, Args &&...args)\r\n{\r\n\t(StrAppend(out, std::forward<Args>(args)), ...);\r\n}\r\n\r\ntemplate <typename... Args>\r\nstd::string StrCat(Args &&...args)\r\n{\r\n\tstd::string result;\r\n\tStrAppend(result, std::forward<Args>(args)...);\r\n\treturn result;\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/str_split.hpp",
    "content": "#pragma once\r\n\r\n#include <iterator>\r\n#include <string_view>\r\n#include <type_traits>\r\n\r\nnamespace devilution {\r\nclass SplitByCharIterator {\r\npublic:\r\n\tusing iterator_category = std::forward_iterator_tag;\r\n\tusing value_type = std::string_view;\r\n\tusing reference = std::add_lvalue_reference<value_type>::type;\r\n\tusing pointer = std::add_pointer<value_type>::type;\r\n\r\n\tstatic SplitByCharIterator begin(std::string_view text, char split_by) // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\treturn SplitByCharIterator(split_by, text, text.substr(0, text.find(split_by)));\r\n\t}\r\n\r\n\t// End iterator\r\n\tSplitByCharIterator() = default;\r\n\r\n\t[[nodiscard]] std::string_view operator*() const\r\n\t{\r\n\t\treturn slice_;\r\n\t}\r\n\r\n\t[[nodiscard]] const std::string_view *operator->() const\r\n\t{\r\n\t\treturn &slice_;\r\n\t}\r\n\r\n\tSplitByCharIterator &operator++()\r\n\t{\r\n\t\tif (slice_.data() + slice_.size() == text_.data() + text_.size()) {\r\n\t\t\tslice_ = {};\r\n\t\t\treturn *this;\r\n\t\t}\r\n\t\tslice_ = text_.substr(slice_.data() - text_.data() + slice_.size());\r\n\t\tif (!slice_.empty())\r\n\t\t\tslice_.remove_prefix(1); // skip the split_by char\r\n\t\tslice_ = slice_.substr(0, slice_.find(split_by_));\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tSplitByCharIterator operator++(int)\r\n\t{\r\n\t\tauto copy = *this;\r\n\t\t++(*this);\r\n\t\treturn copy;\r\n\t}\r\n\r\n\tbool operator==(const SplitByCharIterator &rhs) const\r\n\t{\r\n\t\treturn slice_.data() == rhs.slice_.data();\r\n\t}\r\n\r\n\tbool operator!=(const SplitByCharIterator &rhs) const\r\n\t{\r\n\t\treturn !(*this == rhs);\r\n\t}\r\n\r\nprivate:\r\n\tSplitByCharIterator(char split_by, std::string_view text, std::string_view slice)\r\n\t    : split_by_(split_by)\r\n\t    , text_(text)\r\n\t    , slice_(slice)\r\n\t{\r\n\t}\r\n\r\n\tconst char split_by_ = '\\0';\r\n\tconst std::string_view text_;\r\n\tstd::string_view slice_;\r\n};\r\n\r\nclass SplitByChar {\r\npublic:\r\n\texplicit SplitByChar(std::string_view text, char split_by)\r\n\t    : text_(text)\r\n\t    , split_by_(split_by)\r\n\t{\r\n\t}\r\n\r\n\t[[nodiscard]] SplitByCharIterator begin() const // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\treturn SplitByCharIterator::begin(text_, split_by_);\r\n\t}\r\n\r\n\t[[nodiscard]] SplitByCharIterator end() const // NOLINT(readability-identifier-naming)\r\n\t{\r\n\t\treturn {};\r\n\t}\r\n\r\nprivate:\r\n\tconst std::string_view text_;\r\n\tconst char split_by_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/string_or_view.hpp",
    "content": "#pragma once\r\n\r\n#include <string>\r\n#include <string_view>\r\n#include <utility>\r\n#include <variant>\r\n\r\nnamespace devilution {\r\n\r\nclass StringOrView {\r\npublic:\r\n\tStringOrView()\r\n\t    : rep_ { std::string_view {} }\r\n\t{\r\n\t}\r\n\r\n\tStringOrView(const StringOrView &) = default;\r\n\tStringOrView(StringOrView &&) noexcept = default;\r\n\r\n\tStringOrView(std::string &&str)\r\n\t    : rep_ { std::move(str) }\r\n\t{\r\n\t}\r\n\r\n\tStringOrView(std::string_view str)\r\n\t    : rep_ { str }\r\n\t{\r\n\t}\r\n\r\n\tStringOrView &operator=(StringOrView &&) noexcept = default;\r\n\r\n\tStringOrView &operator=(std::string &&value) noexcept\r\n\t{\r\n\t\trep_ = std::move(value);\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tStringOrView &operator=(std::string_view value) noexcept\r\n\t{\r\n\t\trep_ = value;\r\n\t\treturn *this;\r\n\t}\r\n\r\n\tbool empty() const\r\n\t{\r\n\t\treturn std::visit([](auto &&val) -> bool { return val.empty(); }, rep_);\r\n\t}\r\n\r\n\tstd::string_view str() const\r\n\t{\r\n\t\treturn std::visit([](auto &&val) -> std::string_view { return val; }, rep_);\r\n\t}\r\n\r\n\toperator std::string_view() const\r\n\t{\r\n\t\treturn str();\r\n\t}\r\n\r\nprivate:\r\n\tstd::variant<std::string, std::string_view> rep_;\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/string_view_hash.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <string_view>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\nnamespace devilution {\r\n\r\n// A hash functor that enables heterogenous lookup for `unordered_set/map`.\r\nstruct StringViewHash {\r\n\tusing is_transparent = void;\r\n\tusing is_avalanching = void;\r\n\r\n\t[[nodiscard]] uint64_t operator()(std::string_view str) const noexcept\r\n\t{\r\n\t\treturn ankerl::unordered_dense::hash<std::string_view> {}(str);\r\n\t}\r\n\r\n\t[[nodiscard]] uint64_t operator()(const char *str) const noexcept\r\n\t{\r\n\t\treturn (*this)(std::string_view { str });\r\n\t}\r\n\r\n\t[[nodiscard]] uint64_t operator()(const std::string &str) const noexcept\r\n\t{\r\n\t\treturn (*this)(std::string_view { str });\r\n\t}\r\n};\r\n\r\n// Usually we'd use `std::equal_to<>` instead but the latter\r\n// does not link on the libcxx that comes with Xbox NXDK as of Aug 2024,\r\nstruct StringViewEquals {\r\n\tusing is_transparent = void;\r\n\r\n\t[[nodiscard]] bool operator()(std::string_view a, std::string_view b) const { return a == b; }\r\n\t[[nodiscard]] bool operator()(std::string_view a, const std::string &b) const { return a == b; }\r\n\t[[nodiscard]] bool operator()(const std::string &a, std::string_view &b) const { return a == b; }\r\n\t[[nodiscard]] bool operator()(const char *a, const std::string &b) const { return a == b; }\r\n\t[[nodiscard]] bool operator()(const std::string &a, const char *b) const { return a == b; }\r\n\t[[nodiscard]] bool operator()(std::string_view a, const char *b) const { return a == b; }\r\n\t[[nodiscard]] bool operator()(const char *a, std::string_view b) const { return a == b; }\r\n\t[[nodiscard]] bool operator()(const char *a, const char *b) const { return std::string_view { a } == b; }\r\n};\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/stubs.h",
    "content": "#pragma once\r\n\r\n#include \"utils/log.hpp\"\r\n\r\n#define UNIMPLEMENTED()                                                                        \\\r\n\tdo {                                                                                       \\\r\n\t\t::devilution::LogDebug(\"UNIMPLEMENTED: {} @ {}:{}\", __FUNCTION__, __FILE__, __LINE__); \\\r\n\t\tabort();                                                                               \\\r\n\t} while (0)\r\n\r\n#define ABORT()                                                                           \\\r\n\tdo {                                                                                  \\\r\n\t\t::devilution::LogCritical(\"ABORT: {} @ {}:{}\", __FUNCTION__, __FILE__, __LINE__); \\\r\n\t\tabort();                                                                          \\\r\n\t} while (0)\r\n\r\n#define ASSERT(x)                                                                           \\\r\n\tif (!(x)) {                                                                             \\\r\n\t\t::devilution::LogCritical(\"Assertion failed in {}:{}: {}\", __FILE__, __LINE__, #x); \\\r\n\t\tabort();                                                                            \\\r\n\t}\r\n"
  },
  {
    "path": "Source/utils/surface_to_clx.cpp",
    "content": "#include \"utils/surface_to_clx.hpp\"\r\n\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <vector>\r\n\r\n#include \"utils/clx_encode.hpp\"\r\n#include \"utils/endian_read.hpp\"\r\n#include \"utils/endian_write.hpp\"\r\n\r\n#ifdef DEBUG_SURFACE_TO_CLX_SIZE\r\n#include <iomanip>\r\n#include <iostream>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nOwnedClxSpriteList SurfaceToClx(const Surface &surface, unsigned numFrames,\r\n    std::optional<uint8_t> transparentColor)\r\n{\r\n\t// CLX header: frame count, frame offset for each frame, file size\r\n\tstd::vector<uint8_t> clxData(4 * (2 + static_cast<size_t>(numFrames)));\r\n\tWriteLE32(clxData.data(), numFrames);\r\n\r\n\tconst auto height = static_cast<unsigned>(surface.h());\r\n\tconst auto width = static_cast<unsigned>(surface.w());\r\n\tconst auto pitch = static_cast<unsigned>(surface.pitch());\r\n\tconst unsigned frameHeight = height / numFrames;\r\n\r\n\t// We process the surface a whole frame at a time because the lines are reversed in CEL.\r\n\tconst uint8_t *dataPtr = surface.begin();\r\n\tfor (unsigned frame = 1; frame <= numFrames; ++frame) {\r\n\t\tWriteLE32(&clxData[4 * static_cast<size_t>(frame)], static_cast<uint32_t>(clxData.size()));\r\n\r\n\t\tconst size_t frameHeaderPos = clxData.size();\r\n\t\tclxData.resize(clxData.size() + ClxFrameHeaderSize);\r\n\r\n\t\t// Frame header:\r\n\t\tWriteLE16(&clxData[frameHeaderPos], ClxFrameHeaderSize);\r\n\t\tWriteLE16(&clxData[frameHeaderPos + 2], static_cast<uint16_t>(width));\r\n\t\tWriteLE16(&clxData[frameHeaderPos + 4], static_cast<uint16_t>(frameHeight));\r\n\r\n\t\tunsigned transparentRunWidth = 0;\r\n\t\tsize_t line = 0;\r\n\t\twhile (line != frameHeight) {\r\n\t\t\t// Process line:\r\n\t\t\tconst uint8_t *src = &dataPtr[(frameHeight - (line + 1)) * pitch];\r\n\t\t\tif (transparentColor) {\r\n\t\t\t\tunsigned solidRunWidth = 0;\r\n\t\t\t\tfor (const uint8_t *srcEnd = src + width; src != srcEnd; ++src) {\r\n\t\t\t\t\tif (*src == *transparentColor) {\r\n\t\t\t\t\t\tif (solidRunWidth != 0) {\r\n\t\t\t\t\t\t\tAppendClxPixelsOrFillRun(src - transparentRunWidth - solidRunWidth, solidRunWidth, clxData);\r\n\t\t\t\t\t\t\tsolidRunWidth = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t++transparentRunWidth;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tAppendClxTransparentRun(transparentRunWidth, clxData);\r\n\t\t\t\t\t\ttransparentRunWidth = 0;\r\n\t\t\t\t\t\t++solidRunWidth;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (solidRunWidth != 0) {\r\n\t\t\t\t\tAppendClxPixelsOrFillRun(src - solidRunWidth, solidRunWidth, clxData);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tAppendClxPixelsOrFillRun(src, width, clxData);\r\n\t\t\t}\r\n\t\t\t++line;\r\n\t\t}\r\n\t\tAppendClxTransparentRun(transparentRunWidth, clxData);\r\n\r\n\t\tdataPtr += static_cast<unsigned>(pitch * frameHeight);\r\n\t}\r\n\r\n\tWriteLE32(&clxData[4 * (1 + static_cast<size_t>(numFrames))], static_cast<uint32_t>(clxData.size()));\r\n\r\n\tauto out = std::unique_ptr<uint8_t[]>(new uint8_t[clxData.size()]);\r\n\tmemcpy(&out[0], clxData.data(), clxData.size());\r\n\r\n#ifdef DEBUG_SURFACE_TO_CLX_SIZE\r\n\tconst int surfaceSize = surface.h() * surface.pitch();\r\n\tstd::cout << \"Surface(\" << surface.w() << \", \" << surface.h() << \") -> CLX\\t\"\r\n\t          << surfaceSize << \" -> \" << clxData.size() << \"\\t\"\r\n\t          << std::setprecision(1) << std::fixed << (static_cast<int>(clxData.size()) - surfaceSize) / ((float)surfaceSize) * 100 << \"%\" << std::endl;\r\n#endif\r\n\r\n\treturn OwnedClxSpriteList { std::move(out) };\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/surface_to_clx.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n#include <optional>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Converts a Surface to a CLX sprite list.\r\n *\r\n * @param surface The source surface.\r\n * @param numFrames The number of vertically stacked frames in the surface.\r\n * @param transparentColor The PCX palette index of the transparent color.\r\n */\r\nOwnedClxSpriteList SurfaceToClx(const Surface &surface, unsigned numFrames = 1,\r\n    std::optional<uint8_t> transparentColor = std::nullopt);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/surface_to_pcx.cpp",
    "content": "#include \"utils/surface_to_pcx.hpp\"\r\n\r\n#include <cerrno>\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <cstring>\r\n#include <string>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/pcx.hpp\"\r\n#include \"utils/sdl_compat.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\ntl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size, SDL_IOStream *out)\r\n{\r\n\tif (SDL_WriteIO(out, ptr, size) != size) {\r\n\t\tconst char *errorMessage = SDL_GetError();\r\n\t\tif (errorMessage == nullptr)\r\n\t\t\terrorMessage = \"\";\r\n\t\ttl::expected<void, std::string> result = tl::make_unexpected(std::string(\"write failed with: \").append(errorMessage));\r\n\t\tSDL_ClearError();\r\n\t\treturn result;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\n/**\r\n * @brief Write the PCX-file header\r\n * @param width Image width\r\n * @param height Image height\r\n * @param out File stream to write to\r\n * @return True on success\r\n */\r\ntl::expected<void, std::string> WritePcxHeader(int16_t width, int16_t height, SDL_IOStream *out)\r\n{\r\n\tPCXHeader buffer;\r\n\r\n\tmemset(&buffer, 0, sizeof(buffer));\r\n\tbuffer.Manufacturer = 10;\r\n\tbuffer.Version = 5;\r\n\tbuffer.Encoding = 1;\r\n\tbuffer.BitsPerPixel = 8;\r\n\tbuffer.Xmax = Swap16LE(width - 1);\r\n\tbuffer.Ymax = Swap16LE(height - 1);\r\n\tbuffer.HDpi = Swap16LE(width);\r\n\tbuffer.VDpi = Swap16LE(height);\r\n\tbuffer.NPlanes = 1;\r\n\tbuffer.BytesPerLine = Swap16LE(width);\r\n\r\n\treturn CheckedFWrite(&buffer, sizeof(buffer), out);\r\n}\r\n\r\n/**\r\n * @brief Write the current in-game palette to the PCX file\r\n * @param palette Current palette\r\n * @param out File stream for the PCX file.\r\n * @return True if successful, else false\r\n */\r\ntl::expected<void, std::string> WritePcxPalette(SDL_Color *palette, SDL_IOStream *out)\r\n{\r\n\tuint8_t pcxPalette[1 + 256 * 3];\r\n\r\n\tpcxPalette[0] = 12;\r\n\tfor (int i = 0; i < 256; i++) {\r\n\t\tpcxPalette[1 + 3 * i + 0] = palette[i].r;\r\n\t\tpcxPalette[1 + 3 * i + 1] = palette[i].g;\r\n\t\tpcxPalette[1 + 3 * i + 2] = palette[i].b;\r\n\t}\r\n\r\n\treturn CheckedFWrite(pcxPalette, sizeof(pcxPalette), out);\r\n}\r\n\r\n/**\r\n * @brief RLE compress the pixel data\r\n * @param src Raw pixel buffer\r\n * @param dst Output buffer\r\n * @param width Width of pixel buffer\r\n\r\n * @return Output buffer\r\n */\r\nuint8_t *WritePcxLine(uint8_t *src, uint8_t *dst, int width)\r\n{\r\n\tint rleLength;\r\n\r\n\tdo {\r\n\t\tconst uint8_t rlePixel = *src;\r\n\t\tsrc++;\r\n\t\trleLength = 1;\r\n\r\n\t\twidth--;\r\n\r\n\t\twhile (rlePixel == *src) {\r\n\t\t\tif (rleLength >= 63)\r\n\t\t\t\tbreak;\r\n\t\t\tif (width == 0)\r\n\t\t\t\tbreak;\r\n\t\t\trleLength++;\r\n\r\n\t\t\twidth--;\r\n\t\t\tsrc++;\r\n\t\t}\r\n\r\n\t\tif (rleLength > 1 || rlePixel > 0xBF) {\r\n\t\t\t*dst = rleLength | 0xC0;\r\n\t\t\tdst++;\r\n\t\t}\r\n\r\n\t\t*dst = rlePixel;\r\n\t\tdst++;\r\n\t} while (width > 0);\r\n\r\n\treturn dst;\r\n}\r\n\r\n/**\r\n * @brief Write the pixel data to the PCX file\r\n *\r\n * @param buf Pixel data\r\n * @param out File stream for the PCX file.\r\n * @return True if successful, else false\r\n */\r\ntl::expected<void, std::string> WritePcxPixels(const Surface &buf, SDL_IOStream *out)\r\n{\r\n\tconst int width = buf.w();\r\n\tconst std::unique_ptr<uint8_t[]> pBuffer { new uint8_t[static_cast<size_t>(2 * width)] };\r\n\tuint8_t *pixels = buf.begin();\r\n\tfor (int height = buf.h(); height > 0; height--) {\r\n\t\tconst uint8_t *pBufferEnd = WritePcxLine(pixels, pBuffer.get(), width);\r\n\t\tpixels += buf.pitch();\r\n\t\ttl::expected<void, std::string> result = CheckedFWrite(pBuffer.get(), pBufferEnd - pBuffer.get(), out);\r\n\t\tif (!result.has_value()) return result;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\n} // namespace\r\n\r\ntl::expected<void, std::string>\r\nWriteSurfaceToFilePcx(const Surface &buf, SDL_IOStream *outStream)\r\n{\r\n\ttl::expected<void, std::string> result = WritePcxHeader(buf.w(), buf.h(), outStream);\r\n\tif (!result.has_value()) return result;\r\n\tresult = WritePcxPixels(buf, outStream);\r\n\tif (!result.has_value()) return result;\r\n\tresult = WritePcxPalette(buf.surface->format->palette->colors, outStream);\r\n\tif (!result.has_value()) return result;\r\n\tSDL_CloseIO(outStream);\r\n\treturn {};\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/surface_to_pcx.hpp",
    "content": "#include <string>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl_compat.h\"\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\ntl::expected<void, std::string>\r\nWriteSurfaceToFilePcx(const Surface &buf, SDL_IOStream *outStream);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/surface_to_png.cpp",
    "content": "#include \"utils/surface_to_png.hpp\"\r\n\r\n#include <string>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_error.h>\r\n#include <SDL3/SDL_iostream.h>\r\n#include <SDL3_image/SDL_image.h>\r\n#else\r\n#include <SDL.h>\r\n\r\n#include \"utils/sdl_compat.h\"\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n#ifndef USE_SDL3\r\nextern \"C\" int IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst);\r\n#endif\r\n\r\ntl::expected<void, std::string>\r\nWriteSurfaceToFilePng(const Surface &buf, SDL_IOStream *dst)\r\n{\r\n#ifdef USE_SDL3\r\n\tconst bool ok = IMG_SavePNG_IO(buf.surface, dst, /*closeio=*/true);\r\n#else\r\n\tconst bool ok = IMG_SavePNG_RW(buf.surface, dst, /*freedst=*/1) == 0;\r\n#endif\r\n\tif (!ok) {\r\n\t\ttl::expected<void, std::string> result = tl::make_unexpected(std::string(SDL_GetError()));\r\n\t\tSDL_ClearError();\r\n\t\treturn result;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/surface_to_png.hpp",
    "content": "#include <cstdio>\r\n#include <string>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n\r\n#include \"engine/surface.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n/**\r\n * @brief Writes the given surface to `dst` as PNG.\r\n *\r\n * Takes ownership of `dst` and closes it when done.\r\n */\r\ntl::expected<void, std::string>\r\nWriteSurfaceToFilePng(const Surface &buf,\r\n#ifdef USE_SDL3\r\n    SDL_IOStream *\r\n#else\r\n    SDL_RWops *\r\n#endif\r\n        dst);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/timer.cpp",
    "content": "#include \"engine/demomode.h\"\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_timer.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\nnamespace devilution {\r\n\r\nuint32_t GetMillisecondsSinceStartup()\r\n{\r\n\treturn (demo::IsRunning() || demo::IsRecording()) ? demo::SimulateMillisecondsSinceStartup() : SDL_GetTicks();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/timer.hpp",
    "content": "#pragma once\r\n\r\nnamespace devilution {\r\n\r\nuint32_t GetMillisecondsSinceStartup();\r\n\r\n}\r\n"
  },
  {
    "path": "Source/utils/ui_fwd.h",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include \"engine/rectangle.hpp\"\r\n#include \"utils/attributes.h\"\r\n\r\nnamespace devilution {\r\n\r\nextern DVL_API_FOR_TEST uint16_t gnScreenWidth;\r\nextern DVL_API_FOR_TEST uint16_t gnScreenHeight;\r\nextern DVL_API_FOR_TEST uint16_t gnViewportHeight;\r\n\r\nuint16_t GetScreenWidth();\r\nuint16_t GetScreenHeight();\r\nuint16_t GetViewportHeight();\r\n\r\n/** @brief Returns the UI (Menus, Messages, Help) can use. Currently this is 640x480 like vanilla. */\r\nconst Rectangle &GetUIRectangle();\r\n\r\nvoid AdjustToScreenGeometry(Size windowSize);\r\nfloat GetDpiScalingFactor();\r\n/**\r\n * @brief Set the screen to fullscreen or windowe if fullsc\r\n */\r\nvoid SetFullscreenMode();\r\nbool SpawnWindow(const char *lpWindowName);\r\n#ifndef USE_SDL1\r\nvoid ReinitializeTexture();\r\nvoid ReinitializeIntegerScale();\r\n#endif\r\nvoid ReinitializeRenderer();\r\nvoid ResizeWindow();\r\nvoid UiErrorOkDialog(std::string_view caption, std::string_view text, bool error = true);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/utf8.cpp",
    "content": "#include \"utils/utf8.hpp\"\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <string_view>\r\n\r\n#include <SheenBidi/SheenBidi.h>\r\n\r\nnamespace devilution {\r\n\r\nchar32_t DecodeFirstUtf8CodePoint(std::string_view input, std::size_t *len)\r\n{\r\n\tSBUInteger index = 0;\r\n\tconst SBCodepoint result = SBCodepointDecodeNextFromUTF8(\r\n\t    reinterpret_cast<const SBUInt8 *>(input.data()), static_cast<SBUInteger>(input.size()), &index);\r\n\t*len = index;\r\n\treturn result;\r\n}\r\n\r\nstd::string_view TruncateUtf8(std::string_view str, std::size_t len)\r\n{\r\n\tif (str.size() > len) {\r\n\t\tstd::size_t truncIndex = len;\r\n\t\twhile (truncIndex > 0 && IsTrailUtf8CodeUnit(str[truncIndex]))\r\n\t\t\ttruncIndex--;\r\n\t\tstr.remove_suffix(str.size() - truncIndex);\r\n\t}\r\n\treturn str;\r\n}\r\n\r\nvoid CopyUtf8(char *dest, std::string_view source, std::size_t bytes)\r\n{\r\n\tsource = TruncateUtf8(source, bytes - 1);\r\n\t// source.empty() can mean source.data() == nullptr.\r\n\t// It is UB to pass a null pointer to memcpy, so we guard against it.\r\n\tif (!source.empty()) {\r\n\t\tstd::memcpy(dest, source.data(), source.size());\r\n\t}\r\n\tdest[source.size()] = '\\0';\r\n}\r\n\r\nvoid AppendUtf8(char32_t codepoint, std::string &out)\r\n{\r\n\tif (codepoint <= 0x7F) {\r\n\t\tout += static_cast<char>(codepoint);\r\n\t\treturn;\r\n\t}\r\n\r\n\tchar buf[4];\r\n\tif (codepoint <= 0x7FF) {\r\n\t\tbuf[0] = static_cast<char>(0xC0 | (codepoint >> 6 & 0x3F));\r\n\t\tbuf[1] = static_cast<char>(0x80 | (codepoint & 0x3F));\r\n\t\tout.append(buf, 2);\r\n\t} else if (codepoint <= 0xFFFF) {\r\n\t\tbuf[0] = static_cast<char>(0xE0 | (codepoint >> 12 & 0x3F));\r\n\t\tbuf[1] = static_cast<char>(0x80 | (codepoint >> 6 & 0x3F));\r\n\t\tbuf[2] = static_cast<char>(0x80 | (codepoint & 0x3F));\r\n\t\tout.append(buf, 3);\r\n\t} else {\r\n\t\tbuf[0] = static_cast<char>(0xF0 | (codepoint >> 18 & 0x3F));\r\n\t\tbuf[1] = static_cast<char>(0x80 | (codepoint >> 12 & 0x3F));\r\n\t\tbuf[2] = static_cast<char>(0x80 | (codepoint >> 6 & 0x3F));\r\n\t\tbuf[3] = static_cast<char>(0x80 | (codepoint & 0x3F));\r\n\t\tout.append(buf, 4);\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/utils/utf8.hpp",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <string>\r\n#include <string_view>\r\n\r\nnamespace devilution {\r\n\r\nconstexpr char32_t Utf8DecodeError = 0xFFFD;\r\n\r\n/**\r\n * Decodes the first code point from UTF8-encoded input.\r\n *\r\n * Sets `len` to the length of the code point in bytes.\r\n * Returns `Utf8DecodeError` on error.\r\n */\r\nchar32_t DecodeFirstUtf8CodePoint(std::string_view input, std::size_t *len);\r\n\r\n/**\r\n * Decodes and removes the first code point from UTF8-encoded input.\r\n */\r\ninline char32_t ConsumeFirstUtf8CodePoint(std::string_view *input)\r\n{\r\n\tstd::size_t len;\r\n\tconst char32_t result = DecodeFirstUtf8CodePoint(*input, &len);\r\n\tinput->remove_prefix(len);\r\n\treturn result;\r\n}\r\n\r\n/**\r\n * Returns true if the character is part of the Basic Latin set.\r\n *\r\n * This includes ASCII punctuation, symbols, math operators, digits, and both uppercase/lowercase latin alphabets\r\n */\r\nconstexpr bool IsBasicLatin(char x)\r\n{\r\n\treturn x >= '\\x20' && x <= '\\x7E';\r\n}\r\n\r\n/**\r\n * Returns true if this is a trailing byte in a UTF-8 code point encoding.\r\n *\r\n * Trailing bytes all begin with 10 as the most significant bits, meaning they generally fall in the range 0x80 to\r\n * 0xBF. Please note that certain 3 and 4 byte sequences use a narrower range for the second byte, this function is\r\n * not intended to guarantee the character is valid within the sequence (or that the sequence is well-formed).\r\n */\r\ninline bool IsTrailUtf8CodeUnit(char x)\r\n{\r\n\t// The following is equivalent to a bitmask test (x & 0xC0) == 0x80\r\n\t// On x86_64 architectures it ends up being one instruction shorter\r\n\treturn static_cast<signed char>(x) < static_cast<signed char>('\\xC0');\r\n}\r\n\r\n/**\r\n * @brief Returns the number of code units for a code point starting at *src;\r\n *\r\n * `src` must not be empty.\r\n * If `src` does not begin with a UTF-8 code point start byte, returns 1.\r\n */\r\ninline size_t Utf8CodePointLen(const char *src)\r\n{\r\n\t// This constant is effectively a lookup table for 2-bit keys, where\r\n\t// values represent code point length - 1.\r\n\t// `-1` is so that this method never returns 0, even for invalid values\r\n\t// (which could lead to infinite loops in some code).\r\n\t// Generated with:\r\n\t// ruby -e 'p \"0000000000000000000000001111223\".reverse.to_i(4).to_s(16)'\r\n\treturn ((0x3a55000000000000ULL >> (2 * (static_cast<unsigned char>(*src) >> 3))) & 0x3) + 1;\r\n}\r\n\r\n/**\r\n * Returns the start byte index of the last code point in a UTF-8 string.\r\n */\r\ninline std::size_t FindLastUtf8Symbols(std::string_view input)\r\n{\r\n\tif (input.empty())\r\n\t\treturn 0;\r\n\r\n\tstd::size_t pos = input.size() - 1;\r\n\twhile (pos > 0 && IsTrailUtf8CodeUnit(input[pos]))\r\n\t\t--pos;\r\n\treturn pos;\r\n}\r\n\r\n/**\r\n * @brief Copy up to a given number of bytes from a UTF8 string, and zero terminate string\r\n * @param dest The destination buffer\r\n * @param source The source string\r\n * @param bytes Max number of bytes to copy\r\n */\r\nvoid CopyUtf8(char *dest, std::string_view source, std::size_t bytes);\r\n\r\nvoid AppendUtf8(char32_t codepoint, std::string &out);\r\n\r\n/** @brief Truncates `str` to at most `len` at a code point boundary. */\r\nstd::string_view TruncateUtf8(std::string_view str, std::size_t len);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/vision.cpp",
    "content": "#include \"vision.hpp\"\r\n\r\n#include <cstdint>\r\n#include <iterator>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n/*\r\n * XY points of vision rays are cast to trace the visibility of the\r\n * surrounding environment. The table represents N rays of M points in\r\n * one quadrant (0°-90°) of a circle, so rays for other quadrants will\r\n * be created by mirroring. Zero points at the end will be trimmed and\r\n * ignored. A similar table can be recreated using Bresenham's line\r\n * drawing algorithm, which is suitable for integer arithmetic:\r\n * https://en.wikipedia.org/wiki/Bresenham's_line_algorithm\r\n */\r\nconst DisplacementOf<int8_t> VisionRays[23][15] = {\r\n\t// clang-format off\r\n\t{ { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 0 }, { 5, 0 }, { 6, 0 }, { 7, 0 }, { 8, 0 }, { 9, 0 }, { 10,  0 }, { 11,  0 }, { 12,  0 }, { 13,  0 }, { 14,  0 }, { 15,  0 } },\r\n\t{ { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 0 }, { 5, 0 }, { 6, 0 }, { 7, 0 }, { 8, 1 }, { 9, 1 }, { 10,  1 }, { 11,  1 }, { 12,  1 }, { 13,  1 }, { 14,  1 }, { 15,  1 } },\r\n\t{ { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10,  1 }, { 11,  1 }, { 12,  2 }, { 13,  2 }, { 14,  2 }, { 15,  2 } },\r\n\t{ { 1, 0 }, { 2, 0 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1 }, { 8, 2 }, { 9, 2 }, { 10,  2 }, { 11,  2 }, { 12,  2 }, { 13,  3 }, { 14,  3 }, { 15,  3 } },\r\n\t{ { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, { 6, 2 }, { 7, 2 }, { 8, 2 }, { 9, 3 }, { 10,  3 }, { 11,  3 }, { 12,  3 }, { 13,  4 }, { 14,  4 }, {  0,  0 } },\r\n\t{ { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 2 }, { 6, 2 }, { 7, 3 }, { 8, 3 }, { 9, 3 }, { 10,  4 }, { 11,  4 }, { 12,  4 }, { 13,  5 }, { 14,  5 }, {  0,  0 } },\r\n\t{ { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 2 }, { 5, 2 }, { 6, 3 }, { 7, 3 }, { 8, 3 }, { 9, 4 }, { 10,  4 }, { 11,  5 }, { 12,  5 }, { 13,  6 }, { 14,  6 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 2 }, { 5, 3 }, { 6, 3 }, { 7, 4 }, { 8, 4 }, { 9, 5 }, { 10,  5 }, { 11,  6 }, { 12,  6 }, { 13,  7 }, {  0,  0 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 2 }, { 5, 3 }, { 6, 4 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10,  6 }, { 11,  7 }, { 12,  7 }, { 12,  8 }, { 13,  8 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 2, 2 }, { 3, 2 }, { 4, 3 }, { 5, 4 }, { 6, 5 }, { 7, 5 }, { 8, 6 }, { 9, 7 }, { 10,  7 }, { 10,  8 }, { 11,  8 }, { 12,  9 }, {  0,  0 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 5 }, { 7, 6 }, { 8, 7 }, { 9, 8 }, { 10,  9 }, { 11,  9 }, { 11, 10 }, {  0,  0 }, {  0,  0 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 8, 8 }, { 9, 9 }, { 10, 10 }, { 11, 11 }, {  0,  0 }, {  0,  0 }, {  0,  0 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 9 }, {  9, 10 }, {  9, 11 }, { 10, 11 }, {  0,  0 }, {  0,  0 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 2, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 5, 6 }, { 5, 7 }, { 6, 8 }, { 7, 9 }, {  7, 10 }, {  8, 10 }, {  8, 11 }, {  9, 12 }, {  0,  0 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 1, 2 }, { 2, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 4, 7 }, { 5, 8 }, { 6, 9 }, {  6, 10 }, {  7, 11 }, {  7, 12 }, {  8, 12 }, {  8, 13 }, {  0,  0 } },\r\n\t{ { 1, 1 }, { 1, 2 }, { 2, 3 }, { 2, 4 }, { 3, 5 }, { 3, 6 }, { 4, 7 }, { 4, 8 }, { 5, 9 }, {  5, 10 }, {  6, 11 }, {  6, 12 }, {  7, 13 }, {  0,  0 }, {  0,  0 } },\r\n\t{ { 0, 1 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 2, 5 }, { 3, 6 }, { 3, 7 }, { 3, 8 }, { 4, 9 }, {  4, 10 }, {  5, 11 }, {  5, 12 }, {  6, 13 }, {  6, 14 }, {  0,  0 } },\r\n\t{ { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 2, 5 }, { 2, 6 }, { 3, 7 }, { 3, 8 }, { 3, 9 }, {  4, 10 }, {  4, 11 }, {  4, 12 }, {  5, 13 }, {  5, 14 }, {  0,  0 } },\r\n\t{ { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, { 2, 8 }, { 3, 9 }, {  3, 10 }, {  3, 11 }, {  3, 12 }, {  4, 13 }, {  4, 14 }, {  0,  0 } },\r\n\t{ { 0, 1 }, { 0, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 1, 6 }, { 1, 7 }, { 2, 8 }, { 2, 9 }, {  2, 10 }, {  2, 11 }, {  2, 12 }, {  3, 13 }, {  3, 14 }, {  3, 15 } },\r\n\t{ { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 4 }, { 1, 5 }, { 1, 6 }, { 1, 7 }, { 1, 8 }, { 1, 9 }, {  1, 10 }, {  1, 11 }, {  2, 12 }, {  2, 13 }, {  2, 14 }, {  2, 15 } },\r\n\t{ { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 6 }, { 0, 7 }, { 1, 8 }, { 1, 9 }, {  1, 10 }, {  1, 11 }, {  1, 12 }, {  1, 13 }, {  1, 14 }, {  1, 15 } },\r\n\t{ { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 }, {  0, 10 }, {  0, 11 }, {  0, 12 }, {  0, 13 }, {  0, 14 }, {  0, 15 } },\r\n\t// clang-format on\r\n};\r\n} // namespace\r\n\r\nvoid DoVision(Point position, uint8_t radius,\r\n    tl::function_ref<void(Point)> markVisibleFn,\r\n    tl::function_ref<void(Point)> markTransparentFn,\r\n    tl::function_ref<bool(Point)> passesLightFn,\r\n    tl::function_ref<bool(Point)> inBoundsFn)\r\n{\r\n\tmarkVisibleFn(position);\r\n\r\n\t// Adjustment to a ray length to ensure all rays lie on an\r\n\t// accurate circle\r\n\tconstexpr uint8_t RayLenAdj[23] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 4, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0 };\r\n\tstatic_assert(std::size(RayLenAdj) == std::size(VisionRays));\r\n\r\n\t// Four quadrants on a circle\r\n\tconstexpr Displacement Quadrants[] = { { 1, 1 }, { -1, 1 }, { 1, -1 }, { -1, -1 } };\r\n\r\n\t// Loop over quadrants and mirror rays for each one\r\n\tfor (const auto &quadrant : Quadrants) {\r\n\t\t// Cast a ray for a quadrant\r\n\t\tfor (unsigned int j = 0; j < std::size(VisionRays); j++) {\r\n\t\t\tconst int rayLen = radius - RayLenAdj[j];\r\n\t\t\tfor (int k = 0; k < rayLen; k++) {\r\n\t\t\t\tconst auto &relRayPoint = VisionRays[j][k];\r\n\t\t\t\t// Calculate the next point on a ray in the quadrant\r\n\t\t\t\tconst Point rayPoint = position + relRayPoint * quadrant;\r\n\t\t\t\tif (!inBoundsFn(rayPoint)) break;\r\n\r\n\t\t\t\t// We've cast an approximated ray on an integer 2D\r\n\t\t\t\t// grid, so we need to check if a ray can pass through\r\n\t\t\t\t// the diagonally adjacent tiles. For example, consider\r\n\t\t\t\t// this case:\r\n\t\t\t\t//\r\n\t\t\t\t//        #?\r\n\t\t\t\t//       ↗ #\r\n\t\t\t\t//     x\r\n\t\t\t\t//\r\n\t\t\t\t// The ray is cast from the observer 'x', and reaches\r\n\t\t\t\t// the '?', but diagonally adjacent tiles '#' do not\r\n\t\t\t\t// pass the light, so the '?' should not be visible\r\n\t\t\t\t// for the 2D observer.\r\n\t\t\t\t//\r\n\t\t\t\t// The trick is to perform two additional visibility\r\n\t\t\t\t// checks for the diagonally adjacent tiles, but only\r\n\t\t\t\t// for the rays that are not parallel to the X or Y\r\n\t\t\t\t// coordinate lines. Parallel rays, which have a 0 in\r\n\t\t\t\t// one of their coordinate components, do not require\r\n\t\t\t\t// any additional adjacent visibility checks, and the\r\n\t\t\t\t// tile, hit by the ray, is always considered visible.\r\n\t\t\t\t//\r\n\t\t\t\tif (relRayPoint.deltaX > 0 && relRayPoint.deltaY > 0) {\r\n\t\t\t\t\tconst Displacement adjacent1 = { -quadrant.deltaX, 0 };\r\n\t\t\t\t\tconst Displacement adjacent2 = { 0, -quadrant.deltaY };\r\n\r\n\t\t\t\t\t// If diagonally adjacent tiles do not pass the\r\n\t\t\t\t\t// light further, we are done with this ray.\r\n\t\t\t\t\tconst bool passesLight = (passesLightFn(rayPoint + adjacent1) || passesLightFn(rayPoint + adjacent2));\r\n\t\t\t\t\tif (!passesLight) break;\r\n\t\t\t\t}\r\n\t\t\t\tmarkVisibleFn(rayPoint);\r\n\r\n\t\t\t\t// If the tile does not pass the light further, we are\r\n\t\t\t\t// done with this ray.\r\n\t\t\t\tconst bool passesLight = passesLightFn(rayPoint);\r\n\t\t\t\tif (!passesLight) break;\r\n\r\n\t\t\t\tmarkTransparentFn(rayPoint);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Source/vision.hpp",
    "content": "#pragma once\r\n\r\n#include <cstdint>\r\n\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/point.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nvoid DoVision(Point position, uint8_t radius,\r\n    tl::function_ref<void(Point)> markVisibleFn,\r\n    tl::function_ref<void(Point)> markTransparentFn,\r\n    tl::function_ref<bool(Point)> passesLightFn,\r\n    tl::function_ref<bool(Point)> inBoundsFn);\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "Translations/be.po",
    "content": "\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2022-04-11 10:56+0100\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Данек <cheremnykh-danya@mail.ru> \\n\"\n\"Language-Team: \\n\"\n\"Language: be_BY\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && \"\n\"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\\n\"\n\"X-Generator: Poedit 3.4.1\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:7\nmsgid \"Game Design\"\nmsgstr \"Дызайн гульні\"\n\n#: Source/DiabloUI/credits_lines.cpp:10\nmsgid \"Senior Designers\"\nmsgstr \"Старшыя дызайнеры\"\n\n#: Source/DiabloUI/credits_lines.cpp:13 Source/DiabloUI/credits_lines.cpp:232\nmsgid \"Additional Design\"\nmsgstr \"Дадатковы дызайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:16 Source/DiabloUI/credits_lines.cpp:215\nmsgid \"Lead Programmer\"\nmsgstr \"Вядучы праграміст\"\n\n#: Source/DiabloUI/credits_lines.cpp:19\nmsgid \"Senior Programmers\"\nmsgstr \"Старшыя праграмісты\"\n\n#: Source/DiabloUI/credits_lines.cpp:23\nmsgid \"Programming\"\nmsgstr \"Праграмаванне\"\n\n#: Source/DiabloUI/credits_lines.cpp:26\nmsgid \"Special Guest Programmers\"\nmsgstr \"Спецыяльна запрошаныя праграмісты\"\n\n#: Source/DiabloUI/credits_lines.cpp:29\nmsgid \"Battle.net Programming\"\nmsgstr \"Праграмаванне Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:32\nmsgid \"Serial Communications Programming\"\nmsgstr \"Прагамаванне паслядоўнай передачы дадзеных\"\n\n#: Source/DiabloUI/credits_lines.cpp:35\nmsgid \"Installer Programming\"\nmsgstr \"Праграмаванне ўсталёўшчыка\"\n\n#: Source/DiabloUI/credits_lines.cpp:38\nmsgid \"Art Directors\"\nmsgstr \"Арт-дырэктары\"\n\n#: Source/DiabloUI/credits_lines.cpp:41\nmsgid \"Artwork\"\nmsgstr \"Афармленне\"\n\n#: Source/DiabloUI/credits_lines.cpp:48\nmsgid \"Technical Artwork\"\nmsgstr \"Тэхнічнае афармленне\"\n\n#: Source/DiabloUI/credits_lines.cpp:52\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Арт-дырэктары катсцэн\"\n\n#: Source/DiabloUI/credits_lines.cpp:55\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"Афармленне 3D катсцэн\"\n\n#: Source/DiabloUI/credits_lines.cpp:61\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Тэчнічнае афармленне катсцэн\"\n\n#: Source/DiabloUI/credits_lines.cpp:64\nmsgid \"Executive Producer\"\nmsgstr \"Выканаўчы прадзюсар\"\n\n#: Source/DiabloUI/credits_lines.cpp:67\nmsgid \"Producer\"\nmsgstr \"Прадзюсар\"\n\n#: Source/DiabloUI/credits_lines.cpp:70\nmsgid \"Associate Producer\"\nmsgstr \"Памочнік прадзюсара\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:73\nmsgid \"Diablo Strike Team\"\nmsgstr \"Каманда Diablo Strike\"\n\n#: Source/DiabloUI/credits_lines.cpp:77 Source/gamemenu.cpp:67\nmsgid \"Music\"\nmsgstr \"Музыка\"\n\n#: Source/DiabloUI/credits_lines.cpp:80\nmsgid \"Sound Design\"\nmsgstr \"Гукавы дызайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:83\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Музыка і гук у катсцэнах\"\n\n#: Source/DiabloUI/credits_lines.cpp:86\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Агучка, рэжысура, пробы\"\n\n#: Source/DiabloUI/credits_lines.cpp:89\nmsgid \"Script & Story\"\nmsgstr \"Сцэнарый і сюжэт\"\n\n#: Source/DiabloUI/credits_lines.cpp:93\nmsgid \"Voice Editing\"\nmsgstr \"Апрацоўка голаса\"\n\n#: Source/DiabloUI/credits_lines.cpp:96 Source/DiabloUI/credits_lines.cpp:250\nmsgid \"Voices\"\nmsgstr \"Галасы\"\n\n#: Source/DiabloUI/credits_lines.cpp:101\nmsgid \"Recording Engineer\"\nmsgstr \"Інжынер гуказапісу\"\n\n#: Source/DiabloUI/credits_lines.cpp:104\nmsgid \"Manual Design & Layout\"\nmsgstr \"Дызайн дапаможніка і макета\"\n\n#: Source/DiabloUI/credits_lines.cpp:108\nmsgid \"Manual Artwork\"\nmsgstr \"Афармленне дапаможніка\"\n\n#: Source/DiabloUI/credits_lines.cpp:112\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Часовы рэжысёр па праверцы якасці (Вядучы тэсціроўшчык)\"\n\n#: Source/DiabloUI/credits_lines.cpp:115\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Штурмавая каманда па праверцы якасці (Тэсціроўшчыкі)\"\n\n#: Source/DiabloUI/credits_lines.cpp:120\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Спецпадраздзяленне па праверцы якасці (Тэсціроўшчыкі сумяшчальнасці)\"\n\n#: Source/DiabloUI/credits_lines.cpp:123\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Артылерыйская падтрымка па праверцы якасці (Дадатковыя тэсціроўшчыкі) \"\n\n#: Source/DiabloUI/credits_lines.cpp:127\nmsgid \"QA Counterintelligence\"\nmsgstr \"Каманда па праверцы якасці (Контрразведка)\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:130\nmsgid \"Order of Network Information Services\"\nmsgstr \"Парадак Інфармацыйнай службы сеткі\"\n\n#: Source/DiabloUI/credits_lines.cpp:134\nmsgid \"Customer Support\"\nmsgstr \"Служба падтрымкі\"\n\n#: Source/DiabloUI/credits_lines.cpp:139\nmsgid \"Sales\"\nmsgstr \"Продажы\"\n\n#: Source/DiabloUI/credits_lines.cpp:142\nmsgid \"Dunsel\"\nmsgstr \"Бескарысны\"\n\n#: Source/DiabloUI/credits_lines.cpp:145\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Бэквакалісты містэра Дэбіры\"\n\n#: Source/DiabloUI/credits_lines.cpp:149\nmsgid \"Public Relations\"\nmsgstr \"Сувязі з грамадствам\"\n\n#: Source/DiabloUI/credits_lines.cpp:152\nmsgid \"Marketing\"\nmsgstr \"Маркетынг\"\n\n#: Source/DiabloUI/credits_lines.cpp:155\nmsgid \"International Sales\"\nmsgstr \"Міжнародныя продажы\"\n\n#: Source/DiabloUI/credits_lines.cpp:158\nmsgid \"U.S. Sales\"\nmsgstr \"Продажы ў ЗША\"\n\n#: Source/DiabloUI/credits_lines.cpp:161\nmsgid \"Manufacturing\"\nmsgstr \"Вытворчасць\"\n\n#: Source/DiabloUI/credits_lines.cpp:164\nmsgid \"Legal & Business\"\nmsgstr \"Юрыспрудэнцыя і бізнес\"\n\n#: Source/DiabloUI/credits_lines.cpp:167\nmsgid \"Special Thanks To\"\nmsgstr \"Асаблівая падзяка\"\n\n#: Source/DiabloUI/credits_lines.cpp:171\nmsgid \"Thanks To\"\nmsgstr \"Дзякуючы\"\n\n#: Source/DiabloUI/credits_lines.cpp:200\nmsgid \"In memory of\"\nmsgstr \"У памяць\"\n\n#: Source/DiabloUI/credits_lines.cpp:206\nmsgid \"Very Special Thanks to\"\nmsgstr \"Вельмі асаблівая падзяка\"\n\n#: Source/DiabloUI/credits_lines.cpp:212\nmsgid \"General Manager\"\nmsgstr \"Галоўны менеджар\"\n\n#: Source/DiabloUI/credits_lines.cpp:218\nmsgid \"Software Engineering\"\nmsgstr \"Распрацоўка праграмнага забеспячэння\"\n\n#: Source/DiabloUI/credits_lines.cpp:221\nmsgid \"Art Director\"\nmsgstr \"Арт-дырэктар\"\n\n#: Source/DiabloUI/credits_lines.cpp:224\nmsgid \"Artists\"\nmsgstr \"Мастакі\"\n\n#: Source/DiabloUI/credits_lines.cpp:228\nmsgid \"Design\"\nmsgstr \"Дызайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:235\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Гукавы дызайн, SFX і гукарэжысура\"\n\n#: Source/DiabloUI/credits_lines.cpp:238\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Вядучы па праверцы якасці\"\n\n#: Source/DiabloUI/credits_lines.cpp:241\nmsgid \"Testers\"\nmsgstr \"Тэсціроўшчыкі\"\n\n#: Source/DiabloUI/credits_lines.cpp:246\nmsgid \"Manual\"\nmsgstr \"Дапаможнік\"\n\n#: Source/DiabloUI/credits_lines.cpp:255\nmsgid \"\\tAdditional Work\"\nmsgstr \" Дадатковая праца\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"Quest Text Writing\"\nmsgstr \"Напісанне тэксту заданняў\"\n\n#: Source/DiabloUI/credits_lines.cpp:260 Source/DiabloUI/credits_lines.cpp:295\nmsgid \"Thanks to\"\nmsgstr \"Дзякуючы\"\n\n#: Source/DiabloUI/credits_lines.cpp:265\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tАсаблівая падзяка Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:270\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \" Sierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Кіраўнік праверкі якасці\"\n\n#: Source/DiabloUI/credits_lines.cpp:275\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Вядучы тэсціроўшчык праверкі якасці\"\n\n#: Source/DiabloUI/credits_lines.cpp:278\nmsgid \"Main Testers\"\nmsgstr \"Галоўныя тэсціроўшчыкі\"\n\n#: Source/DiabloUI/credits_lines.cpp:281\nmsgid \"Additional Testers\"\nmsgstr \"Дадатковыя тэсціроўшчыкі\"\n\n#: Source/DiabloUI/credits_lines.cpp:286\nmsgid \"Product Marketing Manager\"\nmsgstr \"Кіраўнік маркетынгу прадукту\"\n\n#: Source/DiabloUI/credits_lines.cpp:289\nmsgid \"Public Relations Manager\"\nmsgstr \"Кіраўнік сувязі з грамадствам\"\n\n#: Source/DiabloUI/credits_lines.cpp:292\nmsgid \"Associate Product Manager\"\nmsgstr \"Часовы менеджар прадукту\"\n\n#: Source/DiabloUI/credits_lines.cpp:301\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Пярсцёнак Тысячы\"\n\n#: Source/DiabloUI/credits_lines.cpp:547\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tПры стварэнні гульні ніводнай душы не было прададзена.\"\n\n#: Source/DiabloUI/dialogs.cpp:196 Source/DiabloUI/dialogs.cpp:208\n#: Source/DiabloUI/selconn.cpp:80 Source/DiabloUI/selgame.cpp:168\n#: Source/DiabloUI/selgame.cpp:306 Source/DiabloUI/selgame.cpp:332\n#: Source/DiabloUI/selgame.cpp:472 Source/DiabloUI/selgame.cpp:547\n#: Source/DiabloUI/selhero.cpp:154 Source/DiabloUI/selhero.cpp:179\n#: Source/DiabloUI/selhero.cpp:249 Source/DiabloUI/selhero.cpp:493\n#: Source/DiabloUI/selok.cpp:69\nmsgid \"OK\"\nmsgstr \"ОК\"\n\n#: Source/DiabloUI/mainmenu.cpp:38\nmsgid \"Single Player\"\nmsgstr \"Адзіночная гульня\"\n\n#: Source/DiabloUI/mainmenu.cpp:39\nmsgid \"Multi Player\"\nmsgstr \"Шматкарыстальніцкая гульня\"\n\n#: Source/DiabloUI/mainmenu.cpp:40 Source/DiabloUI/settingsmenu.cpp:259\nmsgid \"Settings\"\nmsgstr \"Налады\"\n\n#: Source/DiabloUI/mainmenu.cpp:41\nmsgid \"Support\"\nmsgstr \"Падтрымка\"\n\n#: Source/DiabloUI/mainmenu.cpp:42\nmsgid \"Show Credits\"\nmsgstr \"Паказаць удзельнікаў\"\n\n#: Source/DiabloUI/mainmenu.cpp:44\nmsgid \"Exit Hellfire\"\nmsgstr \"Выйсці з Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:44\nmsgid \"Exit Diablo\"\nmsgstr \"Выйсці з Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:60\nmsgid \"Shareware\"\nmsgstr \"Дэма\"\n\n#: Source/DiabloUI/progress.cpp:37 Source/DiabloUI/selconn.cpp:83\n#: Source/DiabloUI/selhero.cpp:157 Source/DiabloUI/selhero.cpp:182\n#: Source/DiabloUI/selhero.cpp:252 Source/DiabloUI/selhero.cpp:501\nmsgid \"Cancel\"\nmsgstr \"Адмяніць\"\n\n#: Source/DiabloUI/selconn.cpp:14\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Кліент-сервер (TCP)\"\n\n#: Source/DiabloUI/selconn.cpp:15\nmsgid \"Loopback\"\nmsgstr \"Loopback\"\n\n#: Source/DiabloUI/selconn.cpp:54 Source/DiabloUI/selgame.cpp:604\n#: Source/DiabloUI/selgame.cpp:625\nmsgid \"Multi Player Game\"\nmsgstr \"Шматкарыстальніцкая гульня\"\n\n#: Source/DiabloUI/selconn.cpp:60\nmsgid \"Requirements:\"\nmsgstr \"Патрабаванні:\"\n\n#: Source/DiabloUI/selconn.cpp:66\nmsgid \"no gateway needed\"\nmsgstr \"шлюз не патрэбен\"\n\n#: Source/DiabloUI/selconn.cpp:72\nmsgid \"Select Connection\"\nmsgstr \"Выбраць злучэнне\"\n\n#: Source/DiabloUI/selconn.cpp:75\nmsgid \"Change Gateway\"\nmsgstr \"Змяніць шлюз\"\n\n#: Source/DiabloUI/selconn.cpp:108\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Усе камп'ютары павінны быць падключанымі да сеткі, сумяшчальнай з TCP.\"\n\n#: Source/DiabloUI/selconn.cpp:112\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Усе камп'ютары павінны быць падключанымі да Інтэрнэта.\"\n\n#: Source/DiabloUI/selconn.cpp:116\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Гуляць самому без кантакта з сеткаю.\"\n\n#: Source/DiabloUI/selconn.cpp:121\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Гульцоў падтрымліваецца: {:d}\"\n\n#: Source/DiabloUI/selgame.cpp:83 Source/options.cpp:542 Source/options.cpp:581\n#: Source/quests.cpp:49\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/selgame.cpp:86\nmsgid \"Diablo Shareware\"\nmsgstr \"Дэма-версія Diablo\"\n\n#: Source/DiabloUI/selgame.cpp:89 Source/options.cpp:544 Source/options.cpp:595\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/selgame.cpp:92\nmsgid \"Hellfire Shareware\"\nmsgstr \"Дэма-версія Hellfire\"\n\n#: Source/DiabloUI/selgame.cpp:95\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Хост зараз гуляе ў другую гульню.\"\n\n#: Source/DiabloUI/selgame.cpp:97\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Хост зараз гуляе ў другую ({:s}) гульню.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/selgame.cpp:99\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Ваша версія {:s} не падыходзіць да хоста {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/selgame.cpp:134 Source/DiabloUI/selgame.cpp:533\nmsgid \"Description:\"\nmsgstr \"Апісанне:\"\n\n#: Source/DiabloUI/selgame.cpp:140\nmsgid \"Select Action\"\nmsgstr \"Выбраць дзеянне\"\n\n#: Source/DiabloUI/selgame.cpp:143 Source/DiabloUI/selgame.cpp:294\n#: Source/DiabloUI/selgame.cpp:453\nmsgid \"Create Game\"\nmsgstr \"Стварыць гульню\"\n\n#: Source/DiabloUI/selgame.cpp:145\nmsgid \"Create Public Game\"\nmsgstr \"Стварыць публічную гульню\"\n\n#: Source/DiabloUI/selgame.cpp:146\nmsgid \"Join Game\"\nmsgstr \"Далучыцца да гульні\"\n\n#: Source/DiabloUI/selgame.cpp:150\nmsgid \"Public Games\"\nmsgstr \"Публічныя гульні\"\n\n#: Source/DiabloUI/selgame.cpp:155 Source/error.cpp:62\nmsgid \"Loading...\"\nmsgstr \"Загрузка...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/selgame.cpp:157 Source/discord/discord.cpp:71\n#: Source/options.cpp:563 Source/panels/charpanel.cpp:137\nmsgid \"None\"\nmsgstr \"Ніякі\"\n\n#: Source/DiabloUI/selgame.cpp:171 Source/DiabloUI/selgame.cpp:309\n#: Source/DiabloUI/selgame.cpp:335 Source/DiabloUI/selgame.cpp:475\n#: Source/DiabloUI/selgame.cpp:550\nmsgid \"CANCEL\"\nmsgstr \"Адмяніць\"\n\n#: Source/DiabloUI/selgame.cpp:187\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Стварыць новую гульню са складанасцю на ваш выбар.\"\n\n#: Source/DiabloUI/selgame.cpp:190\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Стварыць новую публічную гульню, да якой могуць далучыцца са складанасцю на \"\n\"ваш выбар.\"\n\n#: Source/DiabloUI/selgame.cpp:194\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Напішыце ID гульні, каб далучыцца да ўжо запушчанай гульні.\"\n\n#: Source/DiabloUI/selgame.cpp:196\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Напішыце IP ці імя хоста, каб далучыцца да ўжо запушчанай гульні.\"\n\n#: Source/DiabloUI/selgame.cpp:201\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Далучыцца да ўжо запушчанай гульні.\"\n\n#: Source/DiabloUI/selgame.cpp:207 Source/DiabloUI/selgame.cpp:299\n#: Source/DiabloUI/selgame.cpp:360 Source/DiabloUI/selgame.cpp:464\n#: Source/DiabloUI/selgame.cpp:484 Source/automap.cpp:522\n#: Source/discord/discord.cpp:100\nmsgid \"Normal\"\nmsgstr \"Нармальная\"\n\n#: Source/DiabloUI/selgame.cpp:210 Source/DiabloUI/selgame.cpp:300\n#: Source/DiabloUI/selgame.cpp:364 Source/automap.cpp:525\n#: Source/discord/discord.cpp:100\nmsgid \"Nightmare\"\nmsgstr \"Кашмар\"\n\n#: Source/DiabloUI/selgame.cpp:213 Source/DiabloUI/selgame.cpp:301\n#: Source/DiabloUI/selgame.cpp:368 Source/automap.cpp:528\n#: Source/discord/discord.cpp:66 Source/discord/discord.cpp:100\nmsgid \"Hell\"\nmsgstr \"Пекла\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/selgame.cpp:216 Source/automap.cpp:532\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Складанасць: {:s}\"\n\n#: Source/DiabloUI/selgame.cpp:220 Source/gamemenu.cpp:161\nmsgid \"Speed: Normal\"\nmsgstr \"Хуткасць: Нармальная\"\n\n#: Source/DiabloUI/selgame.cpp:223 Source/gamemenu.cpp:159\nmsgid \"Speed: Fast\"\nmsgstr \"Хуткасць: Шпарка\"\n\n#: Source/DiabloUI/selgame.cpp:226 Source/gamemenu.cpp:157\nmsgid \"Speed: Faster\"\nmsgstr \"Хуткасць: Шпарчэй\"\n\n#: Source/DiabloUI/selgame.cpp:229 Source/gamemenu.cpp:155\nmsgid \"Speed: Fastest\"\nmsgstr \"Хуткасць: Найшпарчэй\"\n\n#: Source/DiabloUI/selgame.cpp:237\nmsgid \"Players: \"\nmsgstr \"Гульцы: \"\n\n#: Source/DiabloUI/selgame.cpp:297\nmsgid \"Select Difficulty\"\nmsgstr \"Выбраць складанасць\"\n\n#: Source/DiabloUI/selgame.cpp:315\nmsgid \"Join {:s} Games\"\nmsgstr \"Далучыцца да {:s} гульняў\"\n\n#: Source/DiabloUI/selgame.cpp:320\nmsgid \"Enter Game ID\"\nmsgstr \"Напішыце ID гульні\"\n\n#: Source/DiabloUI/selgame.cpp:322\nmsgid \"Enter address\"\nmsgstr \"Напішыце адрас\"\n\n#: Source/DiabloUI/selgame.cpp:361\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нармальная складанасць\\n\"\n\"Пачаткоўцу трэба пачынаць шлях да перамогі над Д'яблам тут.\"\n\n#: Source/DiabloUI/selgame.cpp:365\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Складанасць Кашмар\\n\"\n\"Жыхары Лабірынту ўзмацніліся, выпрабаванне стане складнейшым. Рэкамендуецца \"\n\"толькі для дасведчаных гульцоў.\"\n\n#: Source/DiabloUI/selgame.cpp:369\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Складанасць Пекла\\n\"\n\"Наймацнейшыя стварэнні падземнага свету пільнуюць вас каля варот Пекла. \"\n\"Толькі самыя дасведчаныя адважацца зайсці ў гэтае царства.\"\n\n#: Source/DiabloUI/selgame.cpp:384\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Ваш персанаж павінен быць 20 ўзроўню, каб зайсці ў шматкарыстальніцкую \"\n\"гульню на складанасці Кашмар.\"\n\n#: Source/DiabloUI/selgame.cpp:386\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Ваш персанаж павінен быць 30 ўзроўню, каб зайсці ў шматкарыстальніцкую \"\n\"гульню на складанасці Пекла.\"\n\n#: Source/DiabloUI/selgame.cpp:462\nmsgid \"Select Game Speed\"\nmsgstr \"Выбраць хуткасць гульні\"\n\n#: Source/DiabloUI/selgame.cpp:465 Source/DiabloUI/selgame.cpp:488\nmsgid \"Fast\"\nmsgstr \"Шпаркая\"\n\n#: Source/DiabloUI/selgame.cpp:466 Source/DiabloUI/selgame.cpp:492\nmsgid \"Faster\"\nmsgstr \"Шпарчэйшая\"\n\n#: Source/DiabloUI/selgame.cpp:467 Source/DiabloUI/selgame.cpp:496\nmsgid \"Fastest\"\nmsgstr \"Найшпарчэйшая\"\n\n#: Source/DiabloUI/selgame.cpp:485\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нармальная хуткасць\\n\"\n\"Пачаткоўцу трэба пачынаць шлях да перамогі над Д'яблам тут.\"\n\n#: Source/DiabloUI/selgame.cpp:489\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Шпаркая хуткасць\\n\"\n\"Жыхароў Лабірынту прыспешылі, выпрабаванне стане складнейшым. Рэкамендуецца \"\n\"толькі для дасведчаных гульцоў.\"\n\n#: Source/DiabloUI/selgame.cpp:493\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Шпарчэйшая хуткасць\\n\"\n\"Большасць пачвар цяпер адшукае вас шпарчэй, чым калі-небудзь раней. Толькі \"\n\"дасведчаны асілак можа пакаштаваць шчасця на такой хуткасці.\"\n\n#: Source/DiabloUI/selgame.cpp:497\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Найшпарчэйшая хутскасць\\n\"\n\"Памагатыя падзем'я рынуцца ў бой без вагання. Толькі сапраўды хуткі як чорт \"\n\"можа увайсці такой хадою.\"\n\n#: Source/DiabloUI/selgame.cpp:539 Source/DiabloUI/selgame.cpp:544\nmsgid \"Enter Password\"\nmsgstr \"Увесці пароль\"\n\n#: Source/DiabloUI/selhero.cpp:132\nmsgid \"Choose Class\"\nmsgstr \"Выбраць клас\"\n\n#: Source/DiabloUI/selhero.cpp:136 Source/panels/charpanel.cpp:23\nmsgid \"Warrior\"\nmsgstr \"Ваяр\"\n\n#: Source/DiabloUI/selhero.cpp:137 Source/panels/charpanel.cpp:24\nmsgid \"Rogue\"\nmsgstr \"Шэльма\"\n\n#: Source/DiabloUI/selhero.cpp:138 Source/panels/charpanel.cpp:25\nmsgid \"Sorcerer\"\nmsgstr \"Чараўнік\"\n\n#: Source/DiabloUI/selhero.cpp:140 Source/panels/charpanel.cpp:26\nmsgid \"Monk\"\nmsgstr \"Манах\"\n\n#: Source/DiabloUI/selhero.cpp:143 Source/panels/charpanel.cpp:27\nmsgid \"Bard\"\nmsgstr \"Бард\"\n\n#: Source/DiabloUI/selhero.cpp:146 Source/panels/charpanel.cpp:28\nmsgid \"Barbarian\"\nmsgstr \"Варвар\"\n\n#: Source/DiabloUI/selhero.cpp:163 Source/DiabloUI/selhero.cpp:237\nmsgid \"New Multi Player Hero\"\nmsgstr \"Новы герой для Мультыплэера\"\n\n#: Source/DiabloUI/selhero.cpp:163 Source/DiabloUI/selhero.cpp:237\nmsgid \"New Single Player Hero\"\nmsgstr \"Новы адзіночны герой\"\n\n#: Source/DiabloUI/selhero.cpp:171\nmsgid \"Save File Exists\"\nmsgstr \"Захаванне існуе\"\n\n#: Source/DiabloUI/selhero.cpp:174 Source/gamemenu.cpp:38\nmsgid \"Load Game\"\nmsgstr \"Загрузіць гульню\"\n\n#: Source/DiabloUI/selhero.cpp:175 Source/gamemenu.cpp:37\n#: Source/gamemenu.cpp:48 Source/multi.cpp:737\nmsgid \"New Game\"\nmsgstr \"Новая гульня\"\n\n#: Source/DiabloUI/selhero.cpp:185 Source/DiabloUI/selhero.cpp:507\nmsgid \"Single Player Characters\"\nmsgstr \"Персанажы для адзіночнай гульні\"\n\n#: Source/DiabloUI/selhero.cpp:231\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Шэльма і Чараўнік даступныя толькі ў поўнай рознічнай версіі Diablo. \"\n\"Наведайце https://www.gog.com/game/diablo, каб набыць.\"\n\n#: Source/DiabloUI/selhero.cpp:243 Source/DiabloUI/selhero.cpp:246\nmsgid \"Enter Name\"\nmsgstr \"Увесці імя\"\n\n#: Source/DiabloUI/selhero.cpp:275\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Імя не падыходзіць. У імені не павінна быць прабелаў, зарэзерваваных \"\n\"сімвалаў і слоў.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/selhero.cpp:282\nmsgid \"Unable to create character.\"\nmsgstr \"Немагчыма стварыць персанажа.\"\n\n#: Source/DiabloUI/selhero.cpp:436 Source/DiabloUI/selhero.cpp:439\nmsgid \"Level:\"\nmsgstr \"Узровень:\"\n\n#: Source/DiabloUI/selhero.cpp:444\nmsgid \"Strength:\"\nmsgstr \"Сіла:\"\n\n#: Source/DiabloUI/selhero.cpp:449\nmsgid \"Magic:\"\nmsgstr \"Магія:\"\n\n#: Source/DiabloUI/selhero.cpp:454\nmsgid \"Dexterity:\"\nmsgstr \"Спрыт:\"\n\n#: Source/DiabloUI/selhero.cpp:459\nmsgid \"Vitality:\"\nmsgstr \"Жывучасць:\"\n\n#: Source/DiabloUI/selhero.cpp:465\nmsgid \"Savegame:\"\nmsgstr \"Захаванне:\"\n\n#: Source/DiabloUI/selhero.cpp:477\nmsgid \"Select Hero\"\nmsgstr \"Выбраць героя\"\n\n#: Source/DiabloUI/selhero.cpp:485\nmsgid \"New Hero\"\nmsgstr \"Новы герой\"\n\n#: Source/DiabloUI/selhero.cpp:496\nmsgid \"Delete\"\nmsgstr \"Выдаліць\"\n\n#: Source/DiabloUI/selhero.cpp:505\nmsgid \"Multi Player Characters\"\nmsgstr \"Героі для мультыплэера\"\n\n#: Source/DiabloUI/selhero.cpp:555\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Выдаліць мультыплэернага героя\"\n\n#: Source/DiabloUI/selhero.cpp:557\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Выдаліць адзіночнага героя\"\n\n#: Source/DiabloUI/selhero.cpp:559\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Вы ўпэўненныя ў выдаленні персанажа \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/selstart.cpp:43\nmsgid \"Enter Hellfire\"\nmsgstr \"Зайсці ў Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:44\nmsgid \"Switch to Diablo\"\nmsgstr \"Вярнуцца да Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:55 Source/stores.cpp:991\nmsgid \"Yes\"\nmsgstr \"Так\"\n\n#: Source/DiabloUI/selyesno.cpp:56 Source/stores.cpp:992\nmsgid \"No\"\nmsgstr \"Не\"\n\n#: Source/DiabloUI/settingsmenu.cpp:304\nmsgid \"Bound key:\"\nmsgstr \"Прывязаная клавіша:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:339\nmsgid \"Press any key to change.\"\nmsgstr \"Націснеце любую клавішу каб замяніць.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:341\nmsgid \"Unbind key\"\nmsgstr \"Адвязаць клавішу\"\n\n#: Source/DiabloUI/settingsmenu.cpp:347 Source/gamemenu.cpp:61\nmsgid \"Previous Menu\"\nmsgstr \"Папярэдняе меню\"\n\n#: Source/DiabloUI/support_lines.cpp:8\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/YQKCAYQ Follow the links to join our \"\n\"community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"У нас ёсць чат у Discord.gg/YQKCAYQ Прайдзіе па спасылках, каб далучыцца да \"\n\"нашай суполкі, дзе мы абмяркоўваем усё звязанае з Diablo і дапаўненнем \"\n\"Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX падтрымліваецца Diasurgical, аб праблемах і памылках паведаміць \"\n\"па адрасе https://github.com/diasurgical/devilutionX Каб дапамагчы нам лепей \"\n\"вас абслугоўваць, калі ласка не забывайце дадаваць нумар версіі, аперацыйную \"\n\"сістэму і сутнасць праблемы.\"\n\n#: Source/DiabloUI/support_lines.cpp:13\nmsgid \"Disclaimer:\"\nmsgstr \"Дысклеймер:\"\n\n#: Source/DiabloUI/support_lines.cpp:14\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX не падтрымліваецца ні Blizzard Entertainment ні GOG.com. Ні \"\n\"Blizzard Entertainment, ні GOG.com не тэсціравалі ці сведчылі якасць ці \"\n\"сумяшчальнасць DevilutionX. Усе запытанні, датычныя DevilutionX, трэба \"\n\"накіроўваць да Diasurgical, не Blizzard Entertainment ці GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:17\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tГэты порт карыстаецца Charis SIL, New Athena Unicode, Unifont і Noto, якія \"\n\"ліцэнзаваныя SIL Open Font, гэтак жа сама і Twitmoj ліцэнзавана CC-BY 4.0. \"\n\"Порт таксама карыстаецца SDL, ліцэнзаванай zlib-ліцэнзіяй. Паглядзіце ReadMe \"\n\"для дадатковых дэталяў.\"\n\n#: Source/DiabloUI/title.cpp:46\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:38\nmsgid \"Error\"\nmsgstr \"Памылка\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:100\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Адбылася памылка на {:s} радку {:d}\"\n\n#: Source/appfat.cpp:109\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Немагчыма адчыніць галоўны архіў ({:s}).\\n\"\n\"\\n\"\n\"Праверце, ці яна ў папке з гульнёй.\"\n\n#: Source/appfat.cpp:114\nmsgid \"Data File Error\"\nmsgstr \"Памылка з файлам\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:120\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Не ўдалося запісаць месцазнаходжанне:\\n\"\n\"{:s}\"\n\n#: Source/appfat.cpp:122\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Памылка у Read-Only дапаможніку\"\n\n#: Source/automap.cpp:484\nmsgid \"Game: \"\nmsgstr \"Гульня: \"\n\n#: Source/automap.cpp:492\nmsgid \"Password: \"\nmsgstr \"Пароль: \"\n\n#: Source/automap.cpp:495\nmsgid \"Public Game\"\nmsgstr \"Публічная гульня\"\n\n#: Source/automap.cpp:509\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Узровень: Гняздо {:d}\"\n\n#: Source/automap.cpp:511\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Узровень: Крыпта {:d}\"\n\n#: Source/automap.cpp:513\nmsgid \"Level: {:d}\"\nmsgstr \"Узровень: {:d}\"\n\n#: Source/control.cpp:155\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:155\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:155\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:158\nmsgid \"Character Information\"\nmsgstr \"Аб персанажы\"\n\n#: Source/control.cpp:159\nmsgid \"Quests log\"\nmsgstr \"Заданні\"\n\n#: Source/control.cpp:160\nmsgid \"Automap\"\nmsgstr \"Аўтамапа\"\n\n#: Source/control.cpp:161\nmsgid \"Main Menu\"\nmsgstr \"Меню\"\n\n#: Source/control.cpp:162 Source/diablo.cpp:1537\nmsgid \"Inventory\"\nmsgstr \"Інвентар\"\n\n#: Source/control.cpp:163\nmsgid \"Spell book\"\nmsgstr \"Кніга чараў\"\n\n#: Source/control.cpp:164\nmsgid \"Send Message\"\nmsgstr \"Даслаць паведамленне\"\n\n#: Source/control.cpp:694\nmsgid \"Player friendly\"\nmsgstr \"Плэер-фрэндлі\"\n\n#: Source/control.cpp:696\nmsgid \"Player attack\"\nmsgstr \"Гулец атакуе\"\n\n#: Source/control.cpp:699\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Гарачая клавіша: {:s}\"\n\n#: Source/control.cpp:706\nmsgid \"Select current spell button\"\nmsgstr \"Выбраць клавішу цяперашняй чары\"\n\n#: Source/control.cpp:709\nmsgid \"Hotkey: 's'\"\nmsgstr \"Гарачая клавіша: 's'\"\n\n#: Source/control.cpp:715 Source/panels/spell_list.cpp:163\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Уменне\"\n\n#: Source/control.cpp:718 Source/panels/spell_list.cpp:170\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Чара\"\n\n#: Source/control.cpp:720 Source/panels/spell_list.cpp:175\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Чара Узровень 0 – Няздатная\"\n\n#: Source/control.cpp:720 Source/panels/spell_list.cpp:177\nmsgid \"Spell Level {:d}\"\nmsgstr \"Узровень Чары {:d}\"\n\n#: Source/control.cpp:723 Source/panels/spell_list.cpp:184\nmsgid \"Scroll of {:s}\"\nmsgstr \"Скрутак {:s}\"\n\n#: Source/control.cpp:728 Source/panels/spell_list.cpp:189\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Скрутак\"\nmsgstr[1] \"{:d} Скруткі\"\nmsgstr[2] \"{:d} Скруткаў\"\n\n#: Source/control.cpp:731 Source/panels/spell_list.cpp:196\nmsgid \"Staff of {:s}\"\nmsgstr \"Посах {:s}\"\n\n#: Source/control.cpp:732 Source/panels/spell_list.cpp:198\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Зарад\"\nmsgstr[1] \"{:d} Зарады\"\nmsgstr[2] \"{:d} Зарадаў\"\n\n#: Source/control.cpp:860 Source/inv.cpp:2004 Source/items.cpp:3486\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} манета\"\nmsgstr[1] \"{:s} манеты\"\nmsgstr[2] \"{:s} манет\"\n\n#: Source/control.cpp:862\nmsgid \"Requirements not met\"\nmsgstr \"Патрабаванні не выкананыя\"\n\n#: Source/control.cpp:896\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Узровень: {:d}\"\n\n#: Source/control.cpp:897\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Ачкі здароўя {:d} of {:d}\"\n\n#: Source/control.cpp:931\nmsgid \"Level Up\"\nmsgstr \"Новы ўзровень\"\n\n#. TRANSLATORS: {:d} is a number. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1039\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"У вас ёсць {:s} манета. Колькі хочаце пакінуць?\"\nmsgstr[1] \"У вас ёсць {:s} манеты. Колькі хочаце пакінуць?\"\nmsgstr[2] \"У вас ёсць {:s} манет. Колькі хочаце пакінуць?\"\n\n#: Source/controls/modifier_hints.cpp:177 Source/qol/monhealthbar.cpp:36\n#: Source/qol/xpbar.cpp:76\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Не атрымалася загрузіць рэсурсы інтэрфэйса.\\n\"\n\"\\n\"\n\"Праверце, ці devilutionx.mpq у папке з гульнёю і ці абноўлены ён.\"\n\n#: Source/cursor.cpp:234\nmsgid \"Town Portal\"\nmsgstr \"Партал у горад\"\n\n#: Source/cursor.cpp:235\nmsgid \"from {:s}\"\nmsgstr \"з {:s}\"\n\n#: Source/cursor.cpp:249\nmsgid \"Portal to\"\nmsgstr \"Партал у\"\n\n#: Source/cursor.cpp:250\nmsgid \"The Unholy Altar\"\nmsgstr \"Паганы алтар\"\n\n#: Source/cursor.cpp:250\nmsgid \"level 15\"\nmsgstr \"узровень 15\"\n\n#: Source/diablo.cpp:120\nmsgid \"I need help! Come Here!\"\nmsgstr \"Дапамажыце! Сюды!\"\n\n#: Source/diablo.cpp:121\nmsgid \"Follow me.\"\nmsgstr \"За мною.\"\n\n#: Source/diablo.cpp:122\nmsgid \"Here's something for you.\"\nmsgstr \"Вось, на.\"\n\n#: Source/diablo.cpp:123\nmsgid \"Now you DIE!\"\nmsgstr \"Здохні!\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:822\nmsgid \"Options:\"\nmsgstr \"Варыянты:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:823\nmsgid \"Print this message and exit\"\nmsgstr \"Пакінуць паведамленне і выйсці\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:824\nmsgid \"Print the version and exit\"\nmsgstr \"Пакінуць версію і выйсці\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:825\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Вызначыць папку diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:826\nmsgid \"Specify the folder of save files\"\nmsgstr \"Вызначаць папку захаванняў\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:827\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Вызначыць знаходжанне diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:828\nmsgid \"Skip startup videos\"\nmsgstr \"Прапусціць відэа\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:829\nmsgid \"Display frames per second\"\nmsgstr \"Паказваць кадры ў секунду\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:830\nmsgid \"Enable verbose logging\"\nmsgstr \"Дазволіць падрабязнае апісанне\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:831\nmsgid \"Record a demo file\"\nmsgstr \"Запісаць дэма-файл\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:832\nmsgid \"Play a demo file\"\nmsgstr \"Прайграць дэма-файл\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:833\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Адмяніць усё абмежаванне кадраў падчас прайгравання дэма\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:834\nmsgid \"Game selection:\"\nmsgstr \"Выбар гульні:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:835\nmsgid \"Force Shareware mode\"\nmsgstr \"Уключыць рэжым Дэма\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:836\nmsgid \"Force Diablo mode\"\nmsgstr \"Уключыць рэжым Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:837\nmsgid \"Force Hellfire mode\"\nmsgstr \"Уключыць рэжым Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:838\nmsgid \"Hellfire options:\"\nmsgstr \"Налады Hellfire:\"\n\n#: Source/diablo.cpp:844\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Паведаміць аб памылках https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:956\nmsgid \"version {:s}\"\nmsgstr \"версія {:s}\"\n\n#: Source/diablo.cpp:1277\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Перапынак сеткі --\"\n\n#: Source/diablo.cpp:1278\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Чакаем гульцоў --\"\n\n#: Source/diablo.cpp:1297\nmsgid \"No help available\"\nmsgstr \"Дапамога не даступна\"\n\n#: Source/diablo.cpp:1298\nmsgid \"while in stores\"\nmsgstr \"пакуль у чаканні\"\n\n#: Source/diablo.cpp:1439\nmsgid \"Belt item {}\"\nmsgstr \"Рэч на поясе {}\"\n\n#: Source/diablo.cpp:1440\nmsgid \"Use Belt item.\"\nmsgstr \"Скарыстаць рэч на поясе.\"\n\n#: Source/diablo.cpp:1455\nmsgid \"Quick spell {}\"\nmsgstr \"Быстрае закляцце {}\"\n\n#: Source/diablo.cpp:1456\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Гарачая клавіша пад уменне ці чару.\"\n\n#: Source/diablo.cpp:1474\nmsgid \"Speedbook\"\nmsgstr \"Кніга прыткасці\"\n\n#: Source/diablo.cpp:1475\nmsgid \"Open Speedbook.\"\nmsgstr \"Адчыніць кнігу прыткасці.\"\n\n#: Source/diablo.cpp:1482\nmsgid \"Quick save\"\nmsgstr \"Хутка захавацца\"\n\n#: Source/diablo.cpp:1483\nmsgid \"Saves the game.\"\nmsgstr \"Захоўвае гульню.\"\n\n#: Source/diablo.cpp:1490\nmsgid \"Quick load\"\nmsgstr \"Хутка загрузіцца\"\n\n#: Source/diablo.cpp:1491\nmsgid \"Loads the game.\"\nmsgstr \"Загрузіць гульню.\"\n\n#: Source/diablo.cpp:1499\nmsgid \"Quit game\"\nmsgstr \"Выйсці\"\n\n#: Source/diablo.cpp:1500\nmsgid \"Closes the game.\"\nmsgstr \"Зачыніць гульню.\"\n\n#: Source/diablo.cpp:1506\nmsgid \"Stop hero\"\nmsgstr \"Спыніць героя\"\n\n#: Source/diablo.cpp:1507\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Спыніць ход і адмяніць дзеянне.\"\n\n#: Source/diablo.cpp:1514\nmsgid \"Item highlighting\"\nmsgstr \"Падсвечванне рэчаў\"\n\n#: Source/diablo.cpp:1515\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Паказваць/хаваць рэчы на зямлі.\"\n\n#: Source/diablo.cpp:1521\nmsgid \"Toggle item highlighting\"\nmsgstr \"Пераключыць падсвечванне рэчаў\"\n\n#: Source/diablo.cpp:1522\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Імгненна паказваць/хаваць рэчы на зямлі.\"\n\n#: Source/diablo.cpp:1528\nmsgid \"Toggle automap\"\nmsgstr \"Пераключыць аўтамапу\"\n\n#: Source/diablo.cpp:1529\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Пераключае калі аўтамапа ўключана.\"\n\n#: Source/diablo.cpp:1538\nmsgid \"Open Inventory screen.\"\nmsgstr \"Адчыніць інвентар.\"\n\n#: Source/diablo.cpp:1545\nmsgid \"Character\"\nmsgstr \"Персанаж\"\n\n#: Source/diablo.cpp:1546\nmsgid \"Open Character screen.\"\nmsgstr \"Адчыніць экран персанажа.\"\n\n#: Source/diablo.cpp:1553\nmsgid \"Quest log\"\nmsgstr \"Заданні\"\n\n#: Source/diablo.cpp:1554\nmsgid \"Open Quest log.\"\nmsgstr \"Паглядзець заданні.\"\n\n#: Source/diablo.cpp:1561\nmsgid \"Spellbook\"\nmsgstr \"Кніга чараў\"\n\n#: Source/diablo.cpp:1562\nmsgid \"Open Spellbook.\"\nmsgstr \"Адчыніць кнігу чараў.\"\n\n#: Source/diablo.cpp:1570\nmsgid \"Quick Message {}\"\nmsgstr \"Хутка паведаміць {}\"\n\n#: Source/diablo.cpp:1571\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Хутка паведаміць у чат.\"\n\n#: Source/diablo.cpp:1580\nmsgid \"Hide Info Screens\"\nmsgstr \"Схаваць экраны інфармацыі\"\n\n#: Source/diablo.cpp:1581\nmsgid \"Hide all info screens.\"\nmsgstr \"Схаваць усе экраны інфармацыі.\"\n\n#: Source/diablo.cpp:1601\nmsgid \"Zoom\"\nmsgstr \"Наблізіць\"\n\n#: Source/diablo.cpp:1602\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Наблізіць экран гульні.\"\n\n#: Source/diablo.cpp:1612\nmsgid \"Pause Game\"\nmsgstr \"Спыніць гульню\"\n\n#: Source/diablo.cpp:1613\nmsgid \"Pauses the game.\"\nmsgstr \"Спыняе гульню.\"\n\n#: Source/diablo.cpp:1618\nmsgid \"Decrease Gamma\"\nmsgstr \"Паменшыць гаму\"\n\n#: Source/diablo.cpp:1619\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Знізіць яркасць экрана.\"\n\n#: Source/diablo.cpp:1626\nmsgid \"Increase Gamma\"\nmsgstr \"Павысіць гаму\"\n\n#: Source/diablo.cpp:1627\nmsgid \"Increase screen brightness.\"\nmsgstr \"Павысіць яркасць экрана.\"\n\n#: Source/diablo.cpp:1634\nmsgid \"Help\"\nmsgstr \"Дапамога\"\n\n#: Source/diablo.cpp:1635\nmsgid \"Open Help Screen.\"\nmsgstr \"Адчыніць экран дапамогі.\"\n\n#: Source/diablo.cpp:1642\nmsgid \"Screenshot\"\nmsgstr \"Здымак экрана\"\n\n#: Source/diablo.cpp:1643\nmsgid \"Takes a screenshot.\"\nmsgstr \"Зрабіць здымак экрана.\"\n\n#: Source/diablo.cpp:1649\nmsgid \"Game info\"\nmsgstr \"Аб гульні\"\n\n#: Source/diablo.cpp:1650\nmsgid \"Displays game infos.\"\nmsgstr \"Паказвае інфармацыю аб гульні.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:1654\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:1663\nmsgid \"Chat Log\"\nmsgstr \"Чат\"\n\n#: Source/diablo.cpp:1664\nmsgid \"Displays chat log.\"\nmsgstr \"Паказвае чат.\"\n\n#: Source/discord/discord.cpp:66 Source/objects.cpp:136\nmsgid \"Town\"\nmsgstr \"Горад\"\n\n#: Source/discord/discord.cpp:66\nmsgid \"Cathedral\"\nmsgstr \"Сабор\"\n\n#: Source/discord/discord.cpp:66\nmsgid \"Catacombs\"\nmsgstr \"Катакомбы\"\n\n#: Source/discord/discord.cpp:66\nmsgid \"Caves\"\nmsgstr \"Пячоры\"\n\n#: Source/discord/discord.cpp:66\nmsgid \"Nest\"\nmsgstr \"Гняздо\"\n\n#: Source/discord/discord.cpp:66\nmsgid \"Crypt\"\nmsgstr \"Крыпта\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:82\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:90\nmsgid \"Lv {} {}\"\nmsgstr \"Уз {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:102\nmsgid \"{} difficulty\"\nmsgstr \"{} складанасць\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:182\nmsgid \"In Menu\"\nmsgstr \"У меню\"\n\n#: Source/dvlnet/loopback.cpp:113\nmsgid \"loopback\"\nmsgstr \"loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:65\nmsgid \"Unable to connect\"\nmsgstr \"Няма як звязацца\"\n\n#: Source/dvlnet/tcp_client.cpp:91\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"памылка: счытана 0 байт з сервера\"\n\n#: Source/error.cpp:53\nmsgid \"No automap available in town\"\nmsgstr \"Мапа не даступна ў горадзе\"\n\n#: Source/error.cpp:54\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"У дэма няма шматкарыстальніцкай гульні\"\n\n#: Source/error.cpp:55\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Стварэнне гука правалілася\"\n\n#: Source/error.cpp:56\nmsgid \"Not available in shareware version\"\nmsgstr \"Недаступна ў дэма версіі\"\n\n#: Source/error.cpp:57\nmsgid \"Not enough space to save\"\nmsgstr \"Няма месца каб захаваць\"\n\n#: Source/error.cpp:58\nmsgid \"No Pause in town\"\nmsgstr \"Нельга ставіць паўзу ў горадзе\"\n\n#: Source/error.cpp:59\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Рэкамендуем захваць на цвёрдым дыску\"\n\n#: Source/error.cpp:60\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Праблема з сінхранізацыяй у мультыплэеры\"\n\n#: Source/error.cpp:61\nmsgid \"No pause in multiplayer\"\nmsgstr \"Нельга ставіць на паўзу ў мультыплэеры\"\n\n#: Source/error.cpp:63\nmsgid \"Saving...\"\nmsgstr \"Захоўвае...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:64\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Як нехта мацнее другія слабеюць\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:65\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Моц новая куецца разбурэннем\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:66\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Хто бароніцца рэдка нападае\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:67\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Меч справядлівасці хуткі ды востры\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:68\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Пакуль дух пільнуе, цела квітнее\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:69\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Перакіраваўшыся моц маны аднаўляецца\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:70\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Час сталі моцы не паслабіць\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:71\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Магія не заўжды тое, чым здаецца\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:72\nmsgid \"What once was opened now is closed\"\nmsgstr \"Што адчынілі цяпер зачынілі\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:73\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Напружанне каштуе мудрасці\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:74\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Таемная моц нясе разбурэнне\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:75\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"За што ні ўзяцца, няма як параніць\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:76\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Чырвань ды блакіт стануць нібы сонца\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:77\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Веды ды мудрасць па кошту сябе самога\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:78\nmsgid \"Drink and be refreshed\"\nmsgstr \"Пі ды асвяжыся\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:79\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Дзе б ты ні быў, вось і ты\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:80\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Сіла жыццёвая мудрасці каштуе\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:81\nmsgid \"Riches abound when least expected\"\nmsgstr \"Багацця там многа, дзе менш за ўсё думаеш\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:82\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Дзе прайграе сквапнасць, там цярпенне ўзнагародзіцца\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:83\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Благаславёны добразычлівым спадарожнікам!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:84\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Няхай рукі чалавечыя лёсам накіруюцца\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:85\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Сіла ўмацавана вераю нябеснай\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:86\nmsgid \"The essence of life flows from within\"\nmsgstr \"Жыццёвая сутнасць ліецца знутры\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:87\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Зверху глядзіш – шлях лягчэй пабачыць\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:88\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Ратунак прыйдзе цаною мудрасці\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:89\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Таямніцы раскрыюцца пры святле розуму\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:90\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Апошнія могуць быць яшчэ і першымі\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:91\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Шчодрасць узнагародзіць па-свойму\"\n\n#: Source/error.cpp:92\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Трэба быць хаця б 8 ўзроўню.\"\n\n#: Source/error.cpp:93\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Трэба быць хаця б 13 ўзроўню.\"\n\n#: Source/error.cpp:94\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Трэба быць хаця б 8 ўзроўню.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:95\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Таемныя веды вывучаны!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:96\nmsgid \"That which does not kill you...\"\nmsgstr \"Тое што вас не забівае...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:97\nmsgid \"Knowledge is power.\"\nmsgstr \"Веды ёсць сіла.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:98\nmsgid \"Give and you shall receive.\"\nmsgstr \"Давайце і вам будзе дадзена.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:99\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Досвед можна і крануўшыся атрымаць.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:100\nmsgid \"There's no place like home.\"\nmsgstr \"Усюды добра, а дома лепей.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:101\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Сіла духа вернута.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:102\nmsgid \"You feel more agile.\"\nmsgstr \"Вы нібыта пажвавелі.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:103\nmsgid \"You feel stronger.\"\nmsgstr \"Вы нібыта узмацнелі.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:104\nmsgid \"You feel wiser.\"\nmsgstr \"Вы нібыта памудрэлі.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:105\nmsgid \"You feel refreshed.\"\nmsgstr \"Вы нібыта пасвяжэлі.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/error.cpp:106\nmsgid \"That which can break will.\"\nmsgstr \"Тое, што можа зламіць волю.\"\n\n#: Source/gamemenu.cpp:35\nmsgid \"Save Game\"\nmsgstr \"Захаваць гульню\"\n\n#: Source/gamemenu.cpp:36 Source/gamemenu.cpp:47\nmsgid \"Options\"\nmsgstr \"Налады\"\n\n#: Source/gamemenu.cpp:39 Source/gamemenu.cpp:50\nmsgid \"Quit Game\"\nmsgstr \"Выйсці\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Restart In Town\"\nmsgstr \"Пачаць зноў у Горадзе\"\n\n#: Source/gamemenu.cpp:59\nmsgid \"Gamma\"\nmsgstr \"Гама\"\n\n#: Source/gamemenu.cpp:60 Source/gamemenu.cpp:167\nmsgid \"Speed\"\nmsgstr \"Хуткасць\"\n\n#: Source/gamemenu.cpp:68\nmsgid \"Music Disabled\"\nmsgstr \"Музыка адключана\"\n\n#: Source/gamemenu.cpp:72\nmsgid \"Sound\"\nmsgstr \"Гук\"\n\n#: Source/gamemenu.cpp:73\nmsgid \"Sound Disabled\"\nmsgstr \"Гук адключаны\"\n\n#: Source/gmenu.cpp:168\nmsgid \"Pause\"\nmsgstr \"Паўза\"\n\n#: Source/help.cpp:27\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Скарачэнні клавіш:\"\n\n#: Source/help.cpp:28\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1::    Адчыніць экран дапамогі\"\n\n#: Source/help.cpp:29\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Паказаць Галоўнае Меню\"\n\n#: Source/help.cpp:30\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Паказаць аўтамапу\"\n\n#: Source/help.cpp:31\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Прабел: Схаваць усе экраны інфармацыі\"\n\n#: Source/help.cpp:32\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Адчыцніь кнігу прыткасці\"\n\n#: Source/help.cpp:33\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Адчыцніць кнігу чараў\"\n\n#: Source/help.cpp:34\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Адчыніць інвентар\"\n\n#: Source/help.cpp:35\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Адчыніць экран персанажа\"\n\n#: Source/help.cpp:36\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Паглядзець заданні\"\n\n#: Source/help.cpp:37\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Знізіць яркасць экрана\"\n\n#: Source/help.cpp:38\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Павысіць яркасць экрана\"\n\n#: Source/help.cpp:39\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Наблізіць экран гульні\"\n\n#: Source/help.cpp:40\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Маштабаванне аўтамапы\"\n\n#: Source/help.cpp:41\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 – 8: Выкарыстаць рэч з пояса\"\n\n#: Source/help.cpp:42\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Устанавіць гарачую клавішу\"\n\n#: Source/help.cpp:43\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Левая кнопка мышы: Біць не рухаючыся\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Левая кнопка мышы (на экране персанажа): Прызначыць ачкі статыстыкі\"\n\n#: Source/help.cpp:45\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Левая кнопка мышы (у інвентары): Павесіць нешта на пояс ці зняць/\"\n\"надзець рэч\"\n\n#: Source/help.cpp:46\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Левая кнопка мышы (на поясе): Убраць рэч у інвентар\"\n\n#: Source/help.cpp:48\nmsgid \"$Movement:\"\nmsgstr \"$Рух:\"\n\n#: Source/help.cpp:49\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Калі трымаеце кнопку мышы падчас руху, персанаж будзе працягваць рухацца ў \"\n\"гэтым кірунку.\"\n\n#: Source/help.cpp:52\nmsgid \"$Combat:\"\nmsgstr \"$Бой:\"\n\n#: Source/help.cpp:53\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Трымаючы клавішу shift і пасля націскаючы левую кнопку мышы, персанаж можа \"\n\"біцца стоячы на месцы.\"\n\n#: Source/help.cpp:56\nmsgid \"$Auto-map:\"\nmsgstr \"$Аўтамапа:\"\n\n#: Source/help.cpp:57\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Каб адкрыць аўтамапу, націснеце \\\"МАПА\\\" на панэлі інфармацыі ці клавішу \"\n\"'TAB' на клавіатуры. Маштабаванне карты ажыццяўляецца клавішамі + ды -. \"\n\"Пракручвайце карту стрэлкамі на клавіатуры.\"\n\n#: Source/help.cpp:62\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Падыманне рэчаў:\"\n\n#: Source/help.cpp:63\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Розныя маленькія рэчы, якімі можна карыстацца, як зеллі ці скруткі, \"\n\"аўтаматычна змяшчаюцца ў ваш \\\"пояс\\\", наверсе панэлі інтэрфейсу. Калі \"\n\"прадмет вешаецца на пояс, невялікая лічба з'яўляецца ў яго полі. Каб \"\n\"скарыстацца рэччу, трэба націснуць адпаведную лічбу на клавіатуры або \"\n\"націснуць па ім правай кнопкай мышы.\"\n\n#: Source/help.cpp:69\nmsgid \"$Gold:\"\nmsgstr \"$Золата:\"\n\n#: Source/help.cpp:70\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Вы можаце выбраць, колькі золата кінуць, націснуўшы правай кнопкай мышы па \"\n\"жменьцы золота ў інвентары.\"\n\n#: Source/help.cpp:73\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Уменні ды Чары:\"\n\n#: Source/help.cpp:74\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Вы можаце адкрыць спіс уменняў ды чараў, націснуўшы левай кнопкай мышы па \"\n\"'ЧАРЫ' на панэлі інтэрфейсу. Тут пералічаны вывучаныя ды даступныя праз \"\n\"посах чары. Каб падрыхтаваць патрэбныя чары, клікніце па іх левай кнопкай \"\n\"мышы. Чары можна наслаць націснуўшы правай кнопкаю мышы.\"\n\n#: Source/help.cpp:80\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Кніга прыткасці для чараў:\"\n\n#: Source/help.cpp:81\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Калі націснуць на \\\"гатовыя чары\\\", то адкрыецца \\\"Кніга прыткасці\\\", якая \"\n\"дае выбраць чары ці уменне для хуткага карыстання. Каб скарыстацца гатовым \"\n\"уменнем ці чарамі, проста націснеце правай кнопкаю мышы.\"\n\n#: Source/help.cpp:85\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + Левая кнопка мышы па \\\"выбраць цяперашнія чары\\\" прыбярэ гатовыя \"\n\"чары.\"\n\n#: Source/help.cpp:87\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Устаноўка гарачых клавішаў для чараў:\"\n\n#: Source/help.cpp:88\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Вы можаце прызначыць да чатырох гарачых клавіш для навыкаў, чараў ці \"\n\"скруткаў. Пачніце адкрыўшы \\\"кнігу прыткасці\\\", як апісана вышэй. Націснеце \"\n\"F5, F6, F7 ці F8 пасля вылучэння чараў, якія хочаце прызначыць.\"\n\n#: Source/help.cpp:93\nmsgid \"$Spell Books:\"\nmsgstr \"$Кнігі чараў:\"\n\n#: Source/help.cpp:94\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Чытанне больш за адну кнігу павышае вашыя веды аб гэтых чарах, дазваляючы \"\n\"карыстацца імі эфектыўней.\"\n\n#: Source/help.cpp:177\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Дамапога з дэма Hellfire\"\n\n#: Source/help.cpp:177\nmsgid \"Hellfire Help\"\nmsgstr \"Дапамога з Hellfire\"\n\n#: Source/help.cpp:179\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Дапамога з дэма Diablo\"\n\n#: Source/help.cpp:179\nmsgid \"Diablo Help\"\nmsgstr \"Дапамога з Diablo\"\n\n#: Source/help.cpp:209 Source/qol/chatlog.cpp:180\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Націснеце ESC каб скончыць ці пракруціце стрэлачкамі.\"\n\n#: Source/init.cpp:194\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq ці spawn.mpq\"\n\n#: Source/init.cpp:215\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Нейкіх MPQ файлаў Hellfire бракуе\"\n\n#: Source/init.cpp:215\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Не ўсе MPQ файлы Hellfire знойдзеныя.\\n\"\n\"Скапіюйце ўсе hf*.mpq файлы, калі ласка.\"\n\n#: Source/init.cpp:223\nmsgid \"Unable to create main window\"\nmsgstr \"Немагчыма стварыць галоўнае акно\"\n\n#: Source/itemdat.cpp:53 Source/itemdat.cpp:235 Source/panels/charpanel.cpp:164\nmsgid \"Gold\"\nmsgstr \"Золата\"\n\n#: Source/itemdat.cpp:54 Source/itemdat.cpp:172\nmsgid \"Short Sword\"\nmsgstr \"Корд\"\n\n#: Source/itemdat.cpp:55 Source/itemdat.cpp:124\nmsgid \"Buckler\"\nmsgstr \"Пуклер\"\n\n#: Source/itemdat.cpp:56 Source/itemdat.cpp:192 Source/itemdat.cpp:193\nmsgid \"Club\"\nmsgstr \"Дубіна\"\n\n#: Source/itemdat.cpp:57 Source/itemdat.cpp:196\nmsgid \"Short Bow\"\nmsgstr \"Кароткі лук\"\n\n#: Source/itemdat.cpp:58\nmsgid \"Short Staff of Mana\"\nmsgstr \"Кароткі посах маны\"\n\n#: Source/itemdat.cpp:59\nmsgid \"Cleaver\"\nmsgstr \"Сякач\"\n\n#: Source/itemdat.cpp:60 Source/itemdat.cpp:434\nmsgid \"The Undead Crown\"\nmsgstr \"Нябожчыкава карона\"\n\n#: Source/itemdat.cpp:61 Source/itemdat.cpp:435\nmsgid \"Empyrean Band\"\nmsgstr \"Незямная стужка\"\n\n#: Source/itemdat.cpp:62\nmsgid \"Magic Rock\"\nmsgstr \"Чарадзейны камень\"\n\n#: Source/itemdat.cpp:63 Source/itemdat.cpp:436\nmsgid \"Optic Amulet\"\nmsgstr \"Аптычны амулет\"\n\n#: Source/itemdat.cpp:64 Source/itemdat.cpp:437\nmsgid \"Ring of Truth\"\nmsgstr \"Пярцсцёнак праўды\"\n\n#: Source/itemdat.cpp:65\nmsgid \"Tavern Sign\"\nmsgstr \"Знак карчмы\"\n\n#: Source/itemdat.cpp:66 Source/itemdat.cpp:438\nmsgid \"Harlequin Crest\"\nmsgstr \"Арлекінаў грабянец\"\n\n#: Source/itemdat.cpp:67 Source/itemdat.cpp:439\nmsgid \"Veil of Steel\"\nmsgstr \"Стальны вэлюм\"\n\n#: Source/itemdat.cpp:68\nmsgid \"Golden Elixir\"\nmsgstr \"Залаты эліксір\"\n\n#: Source/itemdat.cpp:69 Source/quests.cpp:54\nmsgid \"Anvil of Fury\"\nmsgstr \"Кавадла ярасці\"\n\n#: Source/itemdat.cpp:70 Source/quests.cpp:45\nmsgid \"Black Mushroom\"\nmsgstr \"Чорны грыб\"\n\n#: Source/itemdat.cpp:71\nmsgid \"Brain\"\nmsgstr \"Мозг\"\n\n#: Source/itemdat.cpp:72\nmsgid \"Fungal Tome\"\nmsgstr \"Грыбны фаліянт\"\n\n#: Source/itemdat.cpp:73\nmsgid \"Spectral Elixir\"\nmsgstr \"Прывідны эліксір\"\n\n#: Source/itemdat.cpp:74\nmsgid \"Blood Stone\"\nmsgstr \"Камень крыві\"\n\n#: Source/itemdat.cpp:75\nmsgid \"Cathedral Map\"\nmsgstr \"Мапа сабору\"\n\n#: Source/itemdat.cpp:76\nmsgid \"Heart\"\nmsgstr \"Сэрца\"\n\n#: Source/itemdat.cpp:77 Source/itemdat.cpp:130\nmsgid \"Potion of Healing\"\nmsgstr \"Зелле лячэння\"\n\n#: Source/itemdat.cpp:78 Source/itemdat.cpp:132\nmsgid \"Potion of Mana\"\nmsgstr \"Зелле маны\"\n\n#: Source/itemdat.cpp:79 Source/itemdat.cpp:147\nmsgid \"Scroll of Identify\"\nmsgstr \"Скрутак выяўлення\"\n\n#: Source/itemdat.cpp:80 Source/itemdat.cpp:151\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Скрутак партала ў Горад\"\n\n#: Source/itemdat.cpp:81 Source/itemdat.cpp:440\nmsgid \"Arkaine's Valor\"\nmsgstr \"Адвага Аркейна\"\n\n#: Source/itemdat.cpp:82 Source/itemdat.cpp:131\nmsgid \"Potion of Full Healing\"\nmsgstr \"Зелле поўнага лячэння\"\n\n#: Source/itemdat.cpp:83 Source/itemdat.cpp:133\nmsgid \"Potion of Full Mana\"\nmsgstr \"Зелле поўнай маны\"\n\n#: Source/itemdat.cpp:84 Source/itemdat.cpp:441\nmsgid \"Griswold's Edge\"\nmsgstr \"Вастрыё Грызвальда\"\n\n#: Source/itemdat.cpp:85 Source/itemdat.cpp:442\nmsgid \"Bovine Plate\"\nmsgstr \"Бычыная пласціна\"\n\n#: Source/itemdat.cpp:86\nmsgid \"Staff of Lazarus\"\nmsgstr \"Посах Лазара\"\n\n#: Source/itemdat.cpp:87 Source/itemdat.cpp:148\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Скрутак Уваскрэсення\"\n\n#: Source/itemdat.cpp:88 Source/itemdat.cpp:136 Source/items.cpp:172\nmsgid \"Blacksmith Oil\"\nmsgstr \"Кавалёва масла\"\n\n#: Source/itemdat.cpp:89 Source/itemdat.cpp:204\nmsgid \"Short Staff\"\nmsgstr \"Кароткі посах\"\n\n#: Source/itemdat.cpp:90 Source/itemdat.cpp:172 Source/itemdat.cpp:173\n#: Source/itemdat.cpp:174 Source/itemdat.cpp:175 Source/itemdat.cpp:178\n#: Source/itemdat.cpp:179 Source/itemdat.cpp:180 Source/itemdat.cpp:181\n#: Source/itemdat.cpp:182\nmsgid \"Sword\"\nmsgstr \"Меч\"\n\n#: Source/itemdat.cpp:91 Source/itemdat.cpp:171\nmsgid \"Dagger\"\nmsgstr \"Кінжал\"\n\n#: Source/itemdat.cpp:92\nmsgid \"Rune Bomb\"\nmsgstr \"Рунічная бомба\"\n\n#: Source/itemdat.cpp:93\nmsgid \"Theodore\"\nmsgstr \"Тэадор\"\n\n#: Source/itemdat.cpp:94\nmsgid \"Auric Amulet\"\nmsgstr \"Амулет аўры\"\n\n#: Source/itemdat.cpp:95\nmsgid \"Torn Note 1\"\nmsgstr \"Абрывак 1\"\n\n#: Source/itemdat.cpp:96\nmsgid \"Torn Note 2\"\nmsgstr \"Абрывак 2\"\n\n#: Source/itemdat.cpp:97\nmsgid \"Torn Note 3\"\nmsgstr \"Абрывак 3\"\n\n#: Source/itemdat.cpp:98\nmsgid \"Reconstructed Note\"\nmsgstr \"Узноўлены запіс\"\n\n#: Source/itemdat.cpp:99\nmsgid \"Brown Suit\"\nmsgstr \"Руды ўбор\"\n\n#: Source/itemdat.cpp:100\nmsgid \"Grey Suit\"\nmsgstr \"Шэры ўбор\"\n\n#: Source/itemdat.cpp:101 Source/itemdat.cpp:102\nmsgid \"Cap\"\nmsgstr \"Шапка\"\n\n#: Source/itemdat.cpp:102\nmsgid \"Skull Cap\"\nmsgstr \"Шышак\"\n\n#: Source/itemdat.cpp:103 Source/itemdat.cpp:104 Source/itemdat.cpp:106\nmsgid \"Helm\"\nmsgstr \"Шалом\"\n\n#: Source/itemdat.cpp:104\nmsgid \"Full Helm\"\nmsgstr \"Закрыты шалом\"\n\n#: Source/itemdat.cpp:105\nmsgid \"Crown\"\nmsgstr \"Карона\"\n\n#: Source/itemdat.cpp:106\nmsgid \"Great Helm\"\nmsgstr \"Вялікі шалом\"\n\n#: Source/itemdat.cpp:107\nmsgid \"Cape\"\nmsgstr \"Накідка\"\n\n#: Source/itemdat.cpp:108\nmsgid \"Rags\"\nmsgstr \"Рыззё\"\n\n#: Source/itemdat.cpp:109\nmsgid \"Cloak\"\nmsgstr \"Плашч\"\n\n#: Source/itemdat.cpp:110\nmsgid \"Robe\"\nmsgstr \"Мантыя\"\n\n#: Source/itemdat.cpp:111\nmsgid \"Quilted Armor\"\nmsgstr \"Падшыванка\"\n\n#: Source/itemdat.cpp:111 Source/itemdat.cpp:112 Source/itemdat.cpp:113\n#: Source/itemdat.cpp:114 Source/objects.cpp:5476\nmsgid \"Armor\"\nmsgstr \"Браня\"\n\n#: Source/itemdat.cpp:112\nmsgid \"Leather Armor\"\nmsgstr \"Кожаны панцыр\"\n\n#: Source/itemdat.cpp:113\nmsgid \"Hard Leather Armor\"\nmsgstr \"Жорсткі скураны панцыр\"\n\n#: Source/itemdat.cpp:114\nmsgid \"Studded Leather Armor\"\nmsgstr \"Нітаваны скураны панцыр\"\n\n#: Source/itemdat.cpp:115\nmsgid \"Ring Mail\"\nmsgstr \"Кольчаты панцыр\"\n\n#: Source/itemdat.cpp:115 Source/itemdat.cpp:116 Source/itemdat.cpp:117\n#: Source/itemdat.cpp:119\nmsgid \"Mail\"\nmsgstr \"Кальчуга\"\n\n#: Source/itemdat.cpp:116\nmsgid \"Chain Mail\"\nmsgstr \"Кальчуга\"\n\n#: Source/itemdat.cpp:117\nmsgid \"Scale Mail\"\nmsgstr \"Лускаваты панцыр\"\n\n#: Source/itemdat.cpp:118\nmsgid \"Breast Plate\"\nmsgstr \"Нагруднік\"\n\n#: Source/itemdat.cpp:118 Source/itemdat.cpp:120 Source/itemdat.cpp:121\n#: Source/itemdat.cpp:122 Source/itemdat.cpp:123\nmsgid \"Plate\"\nmsgstr \"Латы\"\n\n#: Source/itemdat.cpp:119\nmsgid \"Splint Mail\"\nmsgstr \"Бехцер\"\n\n#: Source/itemdat.cpp:120\nmsgid \"Plate Mail\"\nmsgstr \"Латы\"\n\n#: Source/itemdat.cpp:121\nmsgid \"Field Plate\"\nmsgstr \"Баявы даспех\"\n\n#: Source/itemdat.cpp:122\nmsgid \"Gothic Plate\"\nmsgstr \"Гатычны даспех\"\n\n#: Source/itemdat.cpp:123\nmsgid \"Full Plate Mail\"\nmsgstr \"Поўны латны даспех\"\n\n#: Source/itemdat.cpp:124 Source/itemdat.cpp:125 Source/itemdat.cpp:126\n#: Source/itemdat.cpp:127 Source/itemdat.cpp:128 Source/itemdat.cpp:129\nmsgid \"Shield\"\nmsgstr \"Шчыт\"\n\n#: Source/itemdat.cpp:125\nmsgid \"Small Shield\"\nmsgstr \"Малы шчыт\"\n\n#: Source/itemdat.cpp:126\nmsgid \"Large Shield\"\nmsgstr \"Вялізны шчыт\"\n\n#: Source/itemdat.cpp:127\nmsgid \"Kite Shield\"\nmsgstr \"Міндалепадобны шчыт\"\n\n#: Source/itemdat.cpp:128\nmsgid \"Tower Shield\"\nmsgstr \"Павеза\"\n\n#: Source/itemdat.cpp:129\nmsgid \"Gothic Shield\"\nmsgstr \"Гатычны шчыт\"\n\n#: Source/itemdat.cpp:134\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Зелле аднаўлення\"\n\n#: Source/itemdat.cpp:135\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Зелле поўнага аднаўлення\"\n\n#: Source/itemdat.cpp:137 Source/items.cpp:167\nmsgid \"Oil of Accuracy\"\nmsgstr \"Алей дакладнасці\"\n\n#: Source/itemdat.cpp:138 Source/items.cpp:169\nmsgid \"Oil of Sharpness\"\nmsgstr \"Алей вастрыні\"\n\n#: Source/itemdat.cpp:139\nmsgid \"Oil\"\nmsgstr \"Алей\"\n\n#: Source/itemdat.cpp:140\nmsgid \"Elixir of Strength\"\nmsgstr \"Эліксір моцы\"\n\n#: Source/itemdat.cpp:141\nmsgid \"Elixir of Magic\"\nmsgstr \"Эліксір магіі\"\n\n#: Source/itemdat.cpp:142\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Эліксір спрыту\"\n\n#: Source/itemdat.cpp:143\nmsgid \"Elixir of Vitality\"\nmsgstr \"Эліксір жывучасці\"\n\n#: Source/itemdat.cpp:144\nmsgid \"Scroll of Healing\"\nmsgstr \"Скрутак лячэння\"\n\n#: Source/itemdat.cpp:145\nmsgid \"Scroll of Search\"\nmsgstr \"Скрутак пошуку\"\n\n#: Source/itemdat.cpp:146\nmsgid \"Scroll of Lightning\"\nmsgstr \"Скрутак маланкі\"\n\n#: Source/itemdat.cpp:149\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Скрутак вогеннай сцяны\"\n\n#: Source/itemdat.cpp:150\nmsgid \"Scroll of Inferno\"\nmsgstr \"Скрутак апраметнай\"\n\n#: Source/itemdat.cpp:152\nmsgid \"Scroll of Flash\"\nmsgstr \"Скрутак бліску\"\n\n#: Source/itemdat.cpp:153\nmsgid \"Scroll of Infravision\"\nmsgstr \"Скрутак скрозьбачання\"\n\n#: Source/itemdat.cpp:154\nmsgid \"Scroll of Phasing\"\nmsgstr \"Скрутак перамяшчэння\"\n\n#: Source/itemdat.cpp:155\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Скрутак шчыта маны\"\n\n#: Source/itemdat.cpp:156\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Скрутак хвалі полымя\"\n\n#: Source/itemdat.cpp:157\nmsgid \"Scroll of Fireball\"\nmsgstr \"Скрутак вогненнага шара\"\n\n#: Source/itemdat.cpp:158\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Скрутак праклёну каменя\"\n\n#: Source/itemdat.cpp:159\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Скрутак ланцуговай маланкі\"\n\n#: Source/itemdat.cpp:160\nmsgid \"Scroll of Guardian\"\nmsgstr \"Скрутак вартавога\"\n\n#: Source/itemdat.cpp:162\nmsgid \"Scroll of Nova\"\nmsgstr \"Скрутак новай зоркі\"\n\n#: Source/itemdat.cpp:163\nmsgid \"Scroll of Golem\"\nmsgstr \"Скрутак голема\"\n\n#: Source/itemdat.cpp:165\nmsgid \"Scroll of Teleport\"\nmsgstr \"Скрутак тэлепартацыі\"\n\n#: Source/itemdat.cpp:166\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Скрутак апакаліпсіса\"\n\n#: Source/itemdat.cpp:167 Source/itemdat.cpp:168 Source/itemdat.cpp:169\n#: Source/itemdat.cpp:170\nmsgid \"Book of \"\nmsgstr \"Кніга \"\n\n#: Source/itemdat.cpp:173\nmsgid \"Falchion\"\nmsgstr \"Фальшыён\"\n\n#: Source/itemdat.cpp:174\nmsgid \"Scimitar\"\nmsgstr \"Крывая шабля\"\n\n#: Source/itemdat.cpp:175\nmsgid \"Claymore\"\nmsgstr \"Клеймор\"\n\n#: Source/itemdat.cpp:176\nmsgid \"Blade\"\nmsgstr \"Клінок\"\n\n#: Source/itemdat.cpp:177\nmsgid \"Sabre\"\nmsgstr \"Шабля\"\n\n#: Source/itemdat.cpp:178\nmsgid \"Long Sword\"\nmsgstr \"Доўгі меч\"\n\n#: Source/itemdat.cpp:179\nmsgid \"Broad Sword\"\nmsgstr \"Палаш\"\n\n#: Source/itemdat.cpp:180\nmsgid \"Bastard Sword\"\nmsgstr \"Паўтараручны меч\"\n\n#: Source/itemdat.cpp:181\nmsgid \"Two-Handed Sword\"\nmsgstr \"Двухручны меч\"\n\n#: Source/itemdat.cpp:182\nmsgid \"Great Sword\"\nmsgstr \"Аберучны меч\"\n\n#: Source/itemdat.cpp:183\nmsgid \"Small Axe\"\nmsgstr \"Сякерка\"\n\n#: Source/itemdat.cpp:183 Source/itemdat.cpp:184 Source/itemdat.cpp:185\n#: Source/itemdat.cpp:186 Source/itemdat.cpp:187 Source/itemdat.cpp:188\nmsgid \"Axe\"\nmsgstr \"Сякера\"\n\n#: Source/itemdat.cpp:185\nmsgid \"Large Axe\"\nmsgstr \"Бярдыш\"\n\n#: Source/itemdat.cpp:186\nmsgid \"Broad Axe\"\nmsgstr \"Склюд\"\n\n#: Source/itemdat.cpp:187\nmsgid \"Battle Axe\"\nmsgstr \"Лабрыс\"\n\n#: Source/itemdat.cpp:188\nmsgid \"Great Axe\"\nmsgstr \"Вялікая сякера\"\n\n#: Source/itemdat.cpp:189 Source/itemdat.cpp:190\nmsgid \"Mace\"\nmsgstr \"Булава\"\n\n#: Source/itemdat.cpp:190\nmsgid \"Morning Star\"\nmsgstr \"Маргенштэрн\"\n\n#: Source/itemdat.cpp:191\nmsgid \"War Hammer\"\nmsgstr \"Баявы молат\"\n\n#: Source/itemdat.cpp:191\nmsgid \"Hammer\"\nmsgstr \"Молат\"\n\n#: Source/itemdat.cpp:192\nmsgid \"Spiked Club\"\nmsgstr \"Шыпастая дубіна\"\n\n#: Source/itemdat.cpp:194\nmsgid \"Flail\"\nmsgstr \"Кісцень\"\n\n#: Source/itemdat.cpp:195\nmsgid \"Maul\"\nmsgstr \"Кувалда\"\n\n#: Source/itemdat.cpp:196 Source/itemdat.cpp:197 Source/itemdat.cpp:198\n#: Source/itemdat.cpp:199 Source/itemdat.cpp:200 Source/itemdat.cpp:201\n#: Source/itemdat.cpp:202 Source/itemdat.cpp:203\nmsgid \"Bow\"\nmsgstr \"Лук\"\n\n#: Source/itemdat.cpp:197\nmsgid \"Hunter's Bow\"\nmsgstr \"Паляўнічы лук\"\n\n#: Source/itemdat.cpp:198\nmsgid \"Long Bow\"\nmsgstr \"Доўгі лук\"\n\n#: Source/itemdat.cpp:199\nmsgid \"Composite Bow\"\nmsgstr \"Складаны лук\"\n\n#: Source/itemdat.cpp:200\nmsgid \"Short Battle Bow\"\nmsgstr \"Кароткі баявы лук\"\n\n#: Source/itemdat.cpp:201\nmsgid \"Long Battle Bow\"\nmsgstr \"Доўгі баявы лук\"\n\n#: Source/itemdat.cpp:202\nmsgid \"Short War Bow\"\nmsgstr \"Кароткі ваенны лук\"\n\n#: Source/itemdat.cpp:203\nmsgid \"Long War Bow\"\nmsgstr \"Доўгі ваенны лук\"\n\n#: Source/itemdat.cpp:204 Source/itemdat.cpp:205 Source/itemdat.cpp:206\n#: Source/itemdat.cpp:207 Source/itemdat.cpp:208\n#: Source/panels/spell_list.cpp:195\nmsgid \"Staff\"\nmsgstr \"Посах\"\n\n#: Source/itemdat.cpp:205\nmsgid \"Long Staff\"\nmsgstr \"Доўгі посах\"\n\n#: Source/itemdat.cpp:206\nmsgid \"Composite Staff\"\nmsgstr \"Складаны посах\"\n\n#: Source/itemdat.cpp:207\nmsgid \"Quarter Staff\"\nmsgstr \"Посах міласэрнасці\"\n\n#: Source/itemdat.cpp:208\nmsgid \"War Staff\"\nmsgstr \"Посах вайны\"\n\n#: Source/itemdat.cpp:209 Source/itemdat.cpp:210 Source/itemdat.cpp:211\nmsgid \"Ring\"\nmsgstr \"Пярсцёнак\"\n\n#: Source/itemdat.cpp:212 Source/itemdat.cpp:213\nmsgid \"Amulet\"\nmsgstr \"Амулет\"\n\n#: Source/itemdat.cpp:214\nmsgid \"Rune of Fire\"\nmsgstr \"Руна агню\"\n\n#: Source/itemdat.cpp:214 Source/itemdat.cpp:215 Source/itemdat.cpp:216\n#: Source/itemdat.cpp:217 Source/itemdat.cpp:218\nmsgid \"Rune\"\nmsgstr \"Руна\"\n\n#: Source/itemdat.cpp:215\nmsgid \"Rune of Lightning\"\nmsgstr \"Руна маланкі\"\n\n#: Source/itemdat.cpp:216\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Большая руна агню\"\n\n#: Source/itemdat.cpp:217\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Большая руна маланкі\"\n\n#: Source/itemdat.cpp:218\nmsgid \"Rune of Stone\"\nmsgstr \"Руна каменя\"\n\n#: Source/itemdat.cpp:219\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Кароткі посах заражанай маланкі\"\n\n#. TRANSLATORS: Item prefix section.\n#: Source/itemdat.cpp:229\nmsgid \"Tin\"\nmsgstr \"Алавянны\"\n\n#: Source/itemdat.cpp:230\nmsgid \"Brass\"\nmsgstr \"Латуневы\"\n\n#: Source/itemdat.cpp:231\nmsgid \"Bronze\"\nmsgstr \"Бронзавы\"\n\n#: Source/itemdat.cpp:232\nmsgid \"Iron\"\nmsgstr \"Жалезны\"\n\n#: Source/itemdat.cpp:233\nmsgid \"Steel\"\nmsgstr \"Стальны\"\n\n#: Source/itemdat.cpp:234\nmsgid \"Silver\"\nmsgstr \"Срэбраны\"\n\n#: Source/itemdat.cpp:236\nmsgid \"Platinum\"\nmsgstr \"Плацінавы\"\n\n#: Source/itemdat.cpp:237\nmsgid \"Mithril\"\nmsgstr \"Мітрылявы\"\n\n#: Source/itemdat.cpp:238\nmsgid \"Meteoric\"\nmsgstr \"Метэорны\"\n\n#: Source/itemdat.cpp:239 Source/objects.cpp:109\nmsgid \"Weird\"\nmsgstr \"Дзіўны\"\n\n#: Source/itemdat.cpp:240\nmsgid \"Strange\"\nmsgstr \"Невядомы\"\n\n#: Source/itemdat.cpp:241\nmsgid \"Useless\"\nmsgstr \"Дарэмны\"\n\n#: Source/itemdat.cpp:242\nmsgid \"Bent\"\nmsgstr \"Крывы\"\n\n#: Source/itemdat.cpp:243\nmsgid \"Weak\"\nmsgstr \"Слабы\"\n\n#: Source/itemdat.cpp:244\nmsgid \"Jagged\"\nmsgstr \"Вышчарблены\"\n\n#: Source/itemdat.cpp:245\nmsgid \"Deadly\"\nmsgstr \"Смяротны\"\n\n#: Source/itemdat.cpp:246\nmsgid \"Heavy\"\nmsgstr \"Важкі\"\n\n#: Source/itemdat.cpp:247\nmsgid \"Vicious\"\nmsgstr \"Ліхі\"\n\n#: Source/itemdat.cpp:248\nmsgid \"Brutal\"\nmsgstr \"Люты\"\n\n#: Source/itemdat.cpp:249\nmsgid \"Massive\"\nmsgstr \"Велізарны\"\n\n#: Source/itemdat.cpp:250\nmsgid \"Savage\"\nmsgstr \"Зверскі\"\n\n#: Source/itemdat.cpp:251\nmsgid \"Ruthless\"\nmsgstr \"Жорсткі\"\n\n#: Source/itemdat.cpp:252\nmsgid \"Merciless\"\nmsgstr \"Бязлітасны\"\n\n#: Source/itemdat.cpp:253\nmsgid \"Clumsy\"\nmsgstr \"Няспраўны\"\n\n#: Source/itemdat.cpp:254\nmsgid \"Dull\"\nmsgstr \"Тупы\"\n\n#: Source/itemdat.cpp:255\nmsgid \"Sharp\"\nmsgstr \"Востры\"\n\n#: Source/itemdat.cpp:256 Source/itemdat.cpp:266\nmsgid \"Fine\"\nmsgstr \"Файны\"\n\n#: Source/itemdat.cpp:257\nmsgid \"Warrior's\"\nmsgstr \"Ваярскі\"\n\n#: Source/itemdat.cpp:258\nmsgid \"Soldier's\"\nmsgstr \"Жаўнерскі\"\n\n#: Source/itemdat.cpp:259\nmsgid \"Lord's\"\nmsgstr \"Валадарскі\"\n\n#: Source/itemdat.cpp:260\nmsgid \"Knight's\"\nmsgstr \"Рыцарскі\"\n\n#: Source/itemdat.cpp:261\nmsgid \"Master's\"\nmsgstr \"Майстроўскі\"\n\n#: Source/itemdat.cpp:262\nmsgid \"Champion's\"\nmsgstr \"Чэмпіёнскі\"\n\n#: Source/itemdat.cpp:263\nmsgid \"King's\"\nmsgstr \"Каралеўскі\"\n\n#: Source/itemdat.cpp:264\nmsgid \"Vulnerable\"\nmsgstr \"Прыступны\"\n\n#: Source/itemdat.cpp:265\nmsgid \"Rusted\"\nmsgstr \"Заіржавелы\"\n\n#: Source/itemdat.cpp:267\nmsgid \"Strong\"\nmsgstr \"Моцны\"\n\n#: Source/itemdat.cpp:268\nmsgid \"Grand\"\nmsgstr \"Велічэзны\"\n\n#: Source/itemdat.cpp:269\nmsgid \"Valiant\"\nmsgstr \"Адважны\"\n\n#: Source/itemdat.cpp:270\nmsgid \"Glorious\"\nmsgstr \"Славуты\"\n\n#: Source/itemdat.cpp:271\nmsgid \"Blessed\"\nmsgstr \"Дабраславёны\"\n\n#: Source/itemdat.cpp:272\nmsgid \"Saintly\"\nmsgstr \"Праведны\"\n\n#: Source/itemdat.cpp:273\nmsgid \"Awesome\"\nmsgstr \"Жахлівы\"\n\n#: Source/itemdat.cpp:274 Source/objects.cpp:121\nmsgid \"Holy\"\nmsgstr \"Святы\"\n\n#: Source/itemdat.cpp:275\nmsgid \"Godly\"\nmsgstr \"Боскі\"\n\n#: Source/itemdat.cpp:276\nmsgid \"Red\"\nmsgstr \"Чырвоны\"\n\n#: Source/itemdat.cpp:277 Source/itemdat.cpp:278\nmsgid \"Crimson\"\nmsgstr \"Барвовы\"\n\n#: Source/itemdat.cpp:279\nmsgid \"Garnet\"\nmsgstr \"Гранатавы\"\n\n#: Source/itemdat.cpp:280\nmsgid \"Ruby\"\nmsgstr \"Рубінавы\"\n\n#: Source/itemdat.cpp:281\nmsgid \"Blue\"\nmsgstr \"Сіні\"\n\n#: Source/itemdat.cpp:282\nmsgid \"Azure\"\nmsgstr \"Блакітны\"\n\n#: Source/itemdat.cpp:283\nmsgid \"Lapis\"\nmsgstr \"Ляпісны\"\n\n#: Source/itemdat.cpp:284\nmsgid \"Cobalt\"\nmsgstr \"Кобальтавы\"\n\n#: Source/itemdat.cpp:285\nmsgid \"Sapphire\"\nmsgstr \"Сапфіравы\"\n\n#: Source/itemdat.cpp:286\nmsgid \"White\"\nmsgstr \"Белы\"\n\n#: Source/itemdat.cpp:287\nmsgid \"Pearl\"\nmsgstr \"Жамчужны\"\n\n#: Source/itemdat.cpp:288\nmsgid \"Ivory\"\nmsgstr \"Слановай косці\"\n\n#: Source/itemdat.cpp:289\nmsgid \"Crystal\"\nmsgstr \"Крыштальны\"\n\n#: Source/itemdat.cpp:290\nmsgid \"Diamond\"\nmsgstr \"Дыямантавы\"\n\n#: Source/itemdat.cpp:291\nmsgid \"Topaz\"\nmsgstr \"Тапазавы\"\n\n#: Source/itemdat.cpp:292\nmsgid \"Amber\"\nmsgstr \"Бурштынавы\"\n\n#: Source/itemdat.cpp:293\nmsgid \"Jade\"\nmsgstr \"Нефрытавы\"\n\n#: Source/itemdat.cpp:294\nmsgid \"Obsidian\"\nmsgstr \"Абсідыянавы\"\n\n#: Source/itemdat.cpp:295\nmsgid \"Emerald\"\nmsgstr \"Смарагдавы\"\n\n#: Source/itemdat.cpp:296\nmsgid \"Hyena's\"\nmsgstr \"Гіенін\"\n\n#: Source/itemdat.cpp:297\nmsgid \"Frog's\"\nmsgstr \"Жабін\"\n\n#: Source/itemdat.cpp:298\nmsgid \"Spider's\"\nmsgstr \"Павукоў\"\n\n#: Source/itemdat.cpp:299\nmsgid \"Raven's\"\nmsgstr \"Крумкачоў\"\n\n#: Source/itemdat.cpp:300\nmsgid \"Snake's\"\nmsgstr \"Змеяў\"\n\n#: Source/itemdat.cpp:301\nmsgid \"Serpent's\"\nmsgstr \"Вужаў\"\n\n#: Source/itemdat.cpp:302\nmsgid \"Drake's\"\nmsgstr \"Смокаў\"\n\n#: Source/itemdat.cpp:303\nmsgid \"Dragon's\"\nmsgstr \"Цмокаў\"\n\n#: Source/itemdat.cpp:304\nmsgid \"Wyrm's\"\nmsgstr \"Гадскі\"\n\n#: Source/itemdat.cpp:305\nmsgid \"Hydra's\"\nmsgstr \"Гідрын\"\n\n#: Source/itemdat.cpp:306\nmsgid \"Angel's\"\nmsgstr \"Анёльскі\"\n\n#: Source/itemdat.cpp:307\nmsgid \"Arch-Angel's\"\nmsgstr \"Арханёльскі\"\n\n#: Source/itemdat.cpp:308\nmsgid \"Plentiful\"\nmsgstr \"Шчодры\"\n\n#: Source/itemdat.cpp:309\nmsgid \"Bountiful\"\nmsgstr \"Дастатны\"\n\n#: Source/itemdat.cpp:310\nmsgid \"Flaming\"\nmsgstr \"Агністы\"\n\n#: Source/itemdat.cpp:311\nmsgid \"Lightning\"\nmsgstr \"Бліскавічны\"\n\n#: Source/itemdat.cpp:312\nmsgid \"Jester's\"\nmsgstr \"Блазанскі\"\n\n#: Source/itemdat.cpp:313\nmsgid \"Crystalline\"\nmsgstr \"Празрасты\"\n\n#. TRANSLATORS: Item prefix section end.\n#: Source/itemdat.cpp:315\nmsgid \"Doppelganger's\"\nmsgstr \"Двайніковы\"\n\n#. TRANSLATORS: Item suffix section. All items will have a word binding word. (Format: {:s} of {:s} - e.g. Rags of Valor)\n#: Source/itemdat.cpp:325\nmsgid \"quality\"\nmsgstr \"якасці\"\n\n#: Source/itemdat.cpp:326\nmsgid \"maiming\"\nmsgstr \"нявечання\"\n\n#: Source/itemdat.cpp:327\nmsgid \"slaying\"\nmsgstr \"забойства\"\n\n#: Source/itemdat.cpp:328\nmsgid \"gore\"\nmsgstr \"запечанай крыві\"\n\n#: Source/itemdat.cpp:329\nmsgid \"carnage\"\nmsgstr \"бойні\"\n\n#: Source/itemdat.cpp:330\nmsgid \"slaughter\"\nmsgstr \"разні\"\n\n#: Source/itemdat.cpp:331\nmsgid \"pain\"\nmsgstr \"болю\"\n\n#: Source/itemdat.cpp:332\nmsgid \"tears\"\nmsgstr \"слёзаў\"\n\n#: Source/itemdat.cpp:333\nmsgid \"health\"\nmsgstr \"здароўя\"\n\n#: Source/itemdat.cpp:334\nmsgid \"protection\"\nmsgstr \"аховы\"\n\n#: Source/itemdat.cpp:335\nmsgid \"absorption\"\nmsgstr \"паглынання\"\n\n#: Source/itemdat.cpp:336\nmsgid \"deflection\"\nmsgstr \"адхілення\"\n\n#: Source/itemdat.cpp:337\nmsgid \"osmosis\"\nmsgstr \"осмасу\"\n\n#: Source/itemdat.cpp:338\nmsgid \"frailty\"\nmsgstr \"кволасці\"\n\n#: Source/itemdat.cpp:339\nmsgid \"weakness\"\nmsgstr \"слабасці\"\n\n#: Source/itemdat.cpp:340\nmsgid \"strength\"\nmsgstr \"моцы\"\n\n#: Source/itemdat.cpp:341\nmsgid \"might\"\nmsgstr \"магутнасці\"\n\n#: Source/itemdat.cpp:342\nmsgid \"power\"\nmsgstr \"сілы\"\n\n#: Source/itemdat.cpp:343\nmsgid \"giants\"\nmsgstr \"волатаў\"\n\n#: Source/itemdat.cpp:344\nmsgid \"titans\"\nmsgstr \"тытанаў\"\n\n#: Source/itemdat.cpp:345\nmsgid \"paralysis\"\nmsgstr \"паралюшу\"\n\n#: Source/itemdat.cpp:346\nmsgid \"atrophy\"\nmsgstr \"адмірання\"\n\n#: Source/itemdat.cpp:347\nmsgid \"dexterity\"\nmsgstr \"спрыту\"\n\n#: Source/itemdat.cpp:348\nmsgid \"skill\"\nmsgstr \"спраўнасці\"\n\n#: Source/itemdat.cpp:349\nmsgid \"accuracy\"\nmsgstr \"дакладнасці\"\n\n#: Source/itemdat.cpp:350\nmsgid \"precision\"\nmsgstr \"зладжанасці\"\n\n#: Source/itemdat.cpp:351\nmsgid \"perfection\"\nmsgstr \"беззаганнасці\"\n\n#: Source/itemdat.cpp:352\nmsgid \"the fool\"\nmsgstr \"дурня\"\n\n#: Source/itemdat.cpp:353\nmsgid \"dyslexia\"\nmsgstr \"дыслексіі\"\n\n#: Source/itemdat.cpp:354\nmsgid \"magic\"\nmsgstr \"магіі\"\n\n#: Source/itemdat.cpp:355\nmsgid \"the mind\"\nmsgstr \"розуму\"\n\n#: Source/itemdat.cpp:356\nmsgid \"brilliance\"\nmsgstr \"выдатнасці\"\n\n#: Source/itemdat.cpp:357\nmsgid \"sorcery\"\nmsgstr \"вядзьмарства\"\n\n#: Source/itemdat.cpp:358\nmsgid \"wizardry\"\nmsgstr \"чарадзейства\"\n\n#: Source/itemdat.cpp:359\nmsgid \"illness\"\nmsgstr \"немачы\"\n\n#: Source/itemdat.cpp:360\nmsgid \"disease\"\nmsgstr \"хваробы\"\n\n#: Source/itemdat.cpp:361\nmsgid \"vitality\"\nmsgstr \"жывучасці\"\n\n#: Source/itemdat.cpp:362\nmsgid \"zest\"\nmsgstr \"запалу\"\n\n#: Source/itemdat.cpp:363\nmsgid \"vim\"\nmsgstr \"энергіі\"\n\n#: Source/itemdat.cpp:364\nmsgid \"vigor\"\nmsgstr \"дужасці\"\n\n#: Source/itemdat.cpp:365\nmsgid \"life\"\nmsgstr \"жыцця\"\n\n#: Source/itemdat.cpp:366\nmsgid \"trouble\"\nmsgstr \"бяды\"\n\n#: Source/itemdat.cpp:367\nmsgid \"the pit\"\nmsgstr \"ямы\"\n\n#: Source/itemdat.cpp:368\nmsgid \"the sky\"\nmsgstr \"неба\"\n\n#: Source/itemdat.cpp:369\nmsgid \"the moon\"\nmsgstr \"месяца\"\n\n#: Source/itemdat.cpp:370\nmsgid \"the stars\"\nmsgstr \"зорак\"\n\n#: Source/itemdat.cpp:371\nmsgid \"the heavens\"\nmsgstr \"нябёс\"\n\n#: Source/itemdat.cpp:372\nmsgid \"the zodiac\"\nmsgstr \"задыяку\"\n\n#: Source/itemdat.cpp:373\nmsgid \"the vulture\"\nmsgstr \"драпежніка\"\n\n#: Source/itemdat.cpp:374\nmsgid \"the jackal\"\nmsgstr \"шакала\"\n\n#: Source/itemdat.cpp:375\nmsgid \"the fox\"\nmsgstr \"ліса\"\n\n#: Source/itemdat.cpp:376\nmsgid \"the jaguar\"\nmsgstr \"ягуара\"\n\n#: Source/itemdat.cpp:377\nmsgid \"the eagle\"\nmsgstr \"арла\"\n\n#: Source/itemdat.cpp:378\nmsgid \"the wolf\"\nmsgstr \"ваўка\"\n\n#: Source/itemdat.cpp:379\nmsgid \"the tiger\"\nmsgstr \"тыгра\"\n\n#: Source/itemdat.cpp:380\nmsgid \"the lion\"\nmsgstr \"льва\"\n\n#: Source/itemdat.cpp:381\nmsgid \"the mammoth\"\nmsgstr \"маманта\"\n\n#: Source/itemdat.cpp:382\nmsgid \"the whale\"\nmsgstr \"кіта\"\n\n#: Source/itemdat.cpp:383\nmsgid \"fragility\"\nmsgstr \"кволасці\"\n\n#: Source/itemdat.cpp:384\nmsgid \"brittleness\"\nmsgstr \"ломкасці\"\n\n#: Source/itemdat.cpp:385\nmsgid \"sturdiness\"\nmsgstr \"непахіснасці\"\n\n#: Source/itemdat.cpp:386\nmsgid \"craftsmanship\"\nmsgstr \"майстэрства\"\n\n#: Source/itemdat.cpp:387\nmsgid \"structure\"\nmsgstr \"будовы\"\n\n#: Source/itemdat.cpp:388\nmsgid \"the ages\"\nmsgstr \"вякоў\"\n\n#: Source/itemdat.cpp:389\nmsgid \"the dark\"\nmsgstr \"цемры\"\n\n#: Source/itemdat.cpp:390\nmsgid \"the night\"\nmsgstr \"ночы\"\n\n#: Source/itemdat.cpp:391\nmsgid \"light\"\nmsgstr \"святла\"\n\n#: Source/itemdat.cpp:392\nmsgid \"radiance\"\nmsgstr \"ззяння\"\n\n#: Source/itemdat.cpp:393\nmsgid \"flame\"\nmsgstr \"полымя\"\n\n#: Source/itemdat.cpp:394\nmsgid \"fire\"\nmsgstr \"агню\"\n\n#: Source/itemdat.cpp:395\nmsgid \"burning\"\nmsgstr \"спякоты\"\n\n#: Source/itemdat.cpp:396\nmsgid \"shock\"\nmsgstr \"шоку\"\n\n#: Source/itemdat.cpp:397\nmsgid \"lightning\"\nmsgstr \"маланкі\"\n\n#: Source/itemdat.cpp:398\nmsgid \"thunder\"\nmsgstr \"грымот\"\n\n#: Source/itemdat.cpp:399\nmsgid \"many\"\nmsgstr \"шматлікіх\"\n\n#: Source/itemdat.cpp:400\nmsgid \"plenty\"\nmsgstr \"мноства\"\n\n#: Source/itemdat.cpp:401\nmsgid \"thorns\"\nmsgstr \"церняў\"\n\n#: Source/itemdat.cpp:402\nmsgid \"corruption\"\nmsgstr \"скажэння\"\n\n#: Source/itemdat.cpp:403\nmsgid \"thieves\"\nmsgstr \"зладзеяў\"\n\n#: Source/itemdat.cpp:404\nmsgid \"the bear\"\nmsgstr \"мядзведзя\"\n\n#: Source/itemdat.cpp:405\nmsgid \"the bat\"\nmsgstr \"кажана\"\n\n#: Source/itemdat.cpp:406\nmsgid \"vampires\"\nmsgstr \"вупараў\"\n\n#: Source/itemdat.cpp:407\nmsgid \"the leech\"\nmsgstr \"п'яўкі\"\n\n#: Source/itemdat.cpp:408\nmsgid \"blood\"\nmsgstr \"крыві\"\n\n#: Source/itemdat.cpp:409\nmsgid \"piercing\"\nmsgstr \"працінання\"\n\n#: Source/itemdat.cpp:410\nmsgid \"puncturing\"\nmsgstr \"праколу\"\n\n#: Source/itemdat.cpp:411\nmsgid \"bashing\"\nmsgstr \"збівання\"\n\n#: Source/itemdat.cpp:412\nmsgid \"readiness\"\nmsgstr \"падрыхтаванасці\"\n\n#: Source/itemdat.cpp:413\nmsgid \"swiftness\"\nmsgstr \"імклівасці\"\n\n#: Source/itemdat.cpp:414\nmsgid \"speed\"\nmsgstr \"хуткасці\"\n\n#: Source/itemdat.cpp:415\nmsgid \"haste\"\nmsgstr \"паспеху\"\n\n#: Source/itemdat.cpp:416\nmsgid \"balance\"\nmsgstr \"раўнавагі\"\n\n#: Source/itemdat.cpp:417\nmsgid \"stability\"\nmsgstr \"стойкасці\"\n\n#: Source/itemdat.cpp:418\nmsgid \"harmony\"\nmsgstr \"суладнасці\"\n\n#: Source/itemdat.cpp:419\nmsgid \"blocking\"\nmsgstr \"блакавання\"\n\n#: Source/itemdat.cpp:420\nmsgid \"devastation\"\nmsgstr \"спустошанасці\"\n\n#: Source/itemdat.cpp:421\nmsgid \"decay\"\nmsgstr \"гніцця\"\n\n#. TRANSLATORS: Item suffix section end.\n#: Source/itemdat.cpp:423\nmsgid \"peril\"\nmsgstr \"небяспекі\"\n\n#. TRANSLATORS: Unique Item section\n#: Source/itemdat.cpp:433\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Сякач Мясніка\"\n\n#: Source/itemdat.cpp:443\nmsgid \"The Rift Bow\"\nmsgstr \"Лук разлому\"\n\n#: Source/itemdat.cpp:444\nmsgid \"The Needler\"\nmsgstr \"Ігольшчык\"\n\n#: Source/itemdat.cpp:445\nmsgid \"The Celestial Bow\"\nmsgstr \"Нябескі лук\"\n\n#: Source/itemdat.cpp:446\nmsgid \"Deadly Hunter\"\nmsgstr \"Смяротны паляўнічы\"\n\n#: Source/itemdat.cpp:447\nmsgid \"Bow of the Dead\"\nmsgstr \"Лук памерлых\"\n\n#: Source/itemdat.cpp:448\nmsgid \"The Blackoak Bow\"\nmsgstr \"Лук з чорнага дубу\"\n\n#: Source/itemdat.cpp:449\nmsgid \"Flamedart\"\nmsgstr \"Палымяністы дроцік\"\n\n#: Source/itemdat.cpp:450\nmsgid \"Fleshstinger\"\nmsgstr \"Джганіплоць\"\n\n#: Source/itemdat.cpp:451\nmsgid \"Windforce\"\nmsgstr \"Сіла ветру\"\n\n#: Source/itemdat.cpp:452\nmsgid \"Eaglehorn\"\nmsgstr \"Рог арла\"\n\n#: Source/itemdat.cpp:453\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Кордзік Гонагала\"\n\n#: Source/itemdat.cpp:454\nmsgid \"The Defender\"\nmsgstr \"Абаронца\"\n\n#: Source/itemdat.cpp:455\nmsgid \"Gryphon's Claw\"\nmsgstr \"Кіпцюр грыфона\"\n\n#: Source/itemdat.cpp:456\nmsgid \"Black Razor\"\nmsgstr \"Чорная брытва\"\n\n#: Source/itemdat.cpp:457\nmsgid \"Gibbous Moon\"\nmsgstr \"Позні маладзік\"\n\n#: Source/itemdat.cpp:458\nmsgid \"Ice Shank\"\nmsgstr \"Лядзяны прэнт\"\n\n#: Source/itemdat.cpp:459\nmsgid \"The Executioner's Blade\"\nmsgstr \"Катаў меч\"\n\n#: Source/itemdat.cpp:460\nmsgid \"The Bonesaw\"\nmsgstr \"Касцярэз\"\n\n#: Source/itemdat.cpp:461\nmsgid \"Shadowhawk\"\nmsgstr \"Ястраб ценю\"\n\n#: Source/itemdat.cpp:462\nmsgid \"Wizardspike\"\nmsgstr \"Вастрыё чараўніка\"\n\n#: Source/itemdat.cpp:463\nmsgid \"Lightsabre\"\nmsgstr \"Шабля святла\"\n\n#: Source/itemdat.cpp:464\nmsgid \"The Falcon's Talon\"\nmsgstr \"Кіпцюр сокала\"\n\n#: Source/itemdat.cpp:465\nmsgid \"Inferno\"\nmsgstr \"Апраметны\"\n\n#: Source/itemdat.cpp:466\nmsgid \"Doombringer\"\nmsgstr \"Веснік пагібелі\"\n\n#: Source/itemdat.cpp:467\nmsgid \"The Grizzly\"\nmsgstr \"Грызлі\"\n\n#: Source/itemdat.cpp:468\nmsgid \"The Grandfather\"\nmsgstr \"Дзед\"\n\n#: Source/itemdat.cpp:469\nmsgid \"The Mangler\"\nmsgstr \"Рубайла\"\n\n#: Source/itemdat.cpp:470\nmsgid \"Sharp Beak\"\nmsgstr \"Вострая дзюба\"\n\n#: Source/itemdat.cpp:471\nmsgid \"BloodSlayer\"\nmsgstr \"Крывалівень\"\n\n#: Source/itemdat.cpp:472\nmsgid \"The Celestial Axe\"\nmsgstr \"Нябеская сякера\"\n\n#: Source/itemdat.cpp:473\nmsgid \"Wicked Axe\"\nmsgstr \"Ліхая сякера\"\n\n#: Source/itemdat.cpp:474\nmsgid \"Stonecleaver\"\nmsgstr \"Каменясек\"\n\n#: Source/itemdat.cpp:475\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Сякерка Агінары\"\n\n#: Source/itemdat.cpp:476\nmsgid \"Hellslayer\"\nmsgstr \"Пагібель аекла\"\n\n#: Source/itemdat.cpp:477\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Разаральнік Мэссершміта\"\n\n#: Source/itemdat.cpp:478\nmsgid \"Crackrust\"\nmsgstr \"Іржатрэск\"\n\n#: Source/itemdat.cpp:479\nmsgid \"Hammer of Jholm\"\nmsgstr \"Молат Джольма\"\n\n#: Source/itemdat.cpp:480\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Кій Сіверба\"\n\n#: Source/itemdat.cpp:481\nmsgid \"The Celestial Star\"\nmsgstr \"Нябеская зорка\"\n\n#: Source/itemdat.cpp:482\nmsgid \"Baranar's Star\"\nmsgstr \"Зорка Баранара\"\n\n#: Source/itemdat.cpp:483\nmsgid \"Gnarled Root\"\nmsgstr \"Скрыўлены корань\"\n\n#: Source/itemdat.cpp:484\nmsgid \"The Cranium Basher\"\nmsgstr \"Разбівальнік чарапоў\"\n\n#: Source/itemdat.cpp:485\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Молат Шэфера\"\n\n#: Source/itemdat.cpp:486\nmsgid \"Dreamflange\"\nmsgstr \"Грэбень сноў\"\n\n#: Source/itemdat.cpp:487\nmsgid \"Staff of Shadows\"\nmsgstr \"Посах ценяў\"\n\n#: Source/itemdat.cpp:488\nmsgid \"Immolator\"\nmsgstr \"Спаліцель\"\n\n#: Source/itemdat.cpp:489\nmsgid \"Storm Spire\"\nmsgstr \"Шпіль Буры\"\n\n#: Source/itemdat.cpp:490\nmsgid \"Gleamsong\"\nmsgstr \"Спеў промня\"\n\n#: Source/itemdat.cpp:491\nmsgid \"Thundercall\"\nmsgstr \"Вокліч грому\"\n\n#: Source/itemdat.cpp:492\nmsgid \"The Protector\"\nmsgstr \"Заступнік\"\n\n#: Source/itemdat.cpp:493\nmsgid \"Naj's Puzzler\"\nmsgstr \"Загваздка Наж\"\n\n#: Source/itemdat.cpp:494\nmsgid \"Mindcry\"\nmsgstr \"Выкрык розуму\"\n\n#: Source/itemdat.cpp:495\nmsgid \"Rod of Onan\"\nmsgstr \"Прут Онана\"\n\n#: Source/itemdat.cpp:496\nmsgid \"Helm of Spirits\"\nmsgstr \"Шалом духаў\"\n\n#: Source/itemdat.cpp:497\nmsgid \"Thinking Cap\"\nmsgstr \"Талковая шапка\"\n\n#: Source/itemdat.cpp:498\nmsgid \"OverLord's Helm\"\nmsgstr \"Шалом усеўладара\"\n\n#: Source/itemdat.cpp:499\nmsgid \"Fool's Crest\"\nmsgstr \"Грыва блазна\"\n\n#: Source/itemdat.cpp:500\nmsgid \"Gotterdamerung\"\nmsgstr \"Змрок багоў\"\n\n#: Source/itemdat.cpp:501\nmsgid \"Royal Circlet\"\nmsgstr \"Каралеўскі абруч\"\n\n#: Source/itemdat.cpp:502\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Драная плоць душ\"\n\n#: Source/itemdat.cpp:503\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Згуба гладыятара\"\n\n#: Source/itemdat.cpp:504\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Плашч вясёлкі\"\n\n#: Source/itemdat.cpp:505\nmsgid \"Leather of Aut\"\nmsgstr \"Скура Ота\"\n\n#: Source/itemdat.cpp:506\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Шаль мудрасці\"\n\n#: Source/itemdat.cpp:507\nmsgid \"Sparking Mail\"\nmsgstr \"Іскрыстая кальчуга\"\n\n#: Source/itemdat.cpp:508\nmsgid \"Scavenger Carapace\"\nmsgstr \"Панцыр трупаеда\"\n\n#: Source/itemdat.cpp:509\nmsgid \"Nightscape\"\nmsgstr \"Накідка ночы\"\n\n#: Source/itemdat.cpp:510\nmsgid \"Naj's Light Plate\"\nmsgstr \"Лёгкія латы Наж\"\n\n#: Source/itemdat.cpp:511\nmsgid \"Demonspike Coat\"\nmsgstr \"Курта чортавых шыпоў\"\n\n#: Source/itemdat.cpp:512\nmsgid \"The Deflector\"\nmsgstr \"Адхіляльнік\"\n\n#: Source/itemdat.cpp:513\nmsgid \"Split Skull Shield\"\nmsgstr \"Шчыт з расколатага чэрапа\"\n\n#: Source/itemdat.cpp:514\nmsgid \"Dragon's Breach\"\nmsgstr \"Цмокава адтуліна\"\n\n#: Source/itemdat.cpp:515\nmsgid \"Blackoak Shield\"\nmsgstr \"Шчыт з чорнага дубу\"\n\n#: Source/itemdat.cpp:516\nmsgid \"Holy Defender\"\nmsgstr \"Святы абаронца\"\n\n#: Source/itemdat.cpp:517\nmsgid \"Stormshield\"\nmsgstr \"Шчыт буры\"\n\n#: Source/itemdat.cpp:518\nmsgid \"Bramble\"\nmsgstr \"Ажына\"\n\n#: Source/itemdat.cpp:519\nmsgid \"Ring of Regha\"\nmsgstr \"Пярсцёнак Рэгі\"\n\n#: Source/itemdat.cpp:520\nmsgid \"The Bleeder\"\nmsgstr \"Крывацёк\"\n\n#: Source/itemdat.cpp:521\nmsgid \"Constricting Ring\"\nmsgstr \"Сціскальны пярсцёнак\"\n\n#: Source/itemdat.cpp:522\nmsgid \"Ring of Engagement\"\nmsgstr \"Заручальны пярсцёнак\"\n\n#: Source/itemdat.cpp:523\nmsgid \"Giant's Knuckle\"\nmsgstr \"Костка велікалюда\"\n\n#: Source/itemdat.cpp:524\nmsgid \"Mercurial Ring\"\nmsgstr \"Пярсцёнак Меркурыя\"\n\n#: Source/itemdat.cpp:525\nmsgid \"Xorine's Ring\"\nmsgstr \"Пярсцёнак Ксорына\"\n\n#: Source/itemdat.cpp:526\nmsgid \"Karik's Ring\"\nmsgstr \"Пярсцёнак Карыка\"\n\n#: Source/itemdat.cpp:527\nmsgid \"Ring of Magma\"\nmsgstr \"Пярсцёнак магмы\"\n\n#: Source/itemdat.cpp:528\nmsgid \"Ring of the Mystics\"\nmsgstr \"Пярсцёнак містыкі\"\n\n#: Source/itemdat.cpp:529\nmsgid \"Ring of Thunder\"\nmsgstr \"Пярсцёнак грому\"\n\n#: Source/itemdat.cpp:530\nmsgid \"Amulet of Warding\"\nmsgstr \"Амулет аховы\"\n\n#: Source/itemdat.cpp:531\nmsgid \"Gnat Sting\"\nmsgstr \"Джала мошкі\"\n\n#: Source/itemdat.cpp:532\nmsgid \"Flambeau\"\nmsgstr \"Светач\"\n\n#: Source/itemdat.cpp:533\nmsgid \"Armor of Gloom\"\nmsgstr \"Даспех цямнэчы\"\n\n#: Source/itemdat.cpp:534\nmsgid \"Blitzen\"\nmsgstr \"Бляск\"\n\n#: Source/itemdat.cpp:535\nmsgid \"Thunderclap\"\nmsgstr \"Пярун\"\n\n#: Source/itemdat.cpp:536\nmsgid \"Shirotachi\"\nmsgstr \"Шыратачы\"\n\n#: Source/itemdat.cpp:537\nmsgid \"Eater of Souls\"\nmsgstr \"Пажыральнік душ\"\n\n#: Source/itemdat.cpp:538\nmsgid \"Diamondedge\"\nmsgstr \"Алмазнае лязо\"\n\n#: Source/itemdat.cpp:539\nmsgid \"Bone Chain Armor\"\nmsgstr \"Касцяная кальчуга\"\n\n#: Source/itemdat.cpp:540\nmsgid \"Demon Plate Armor\"\nmsgstr \"Латы дэмана\"\n\n#: Source/itemdat.cpp:541\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Амулет прыслужніка\"\n\n#. TRANSLATORS: Unique Item section end.\n#: Source/itemdat.cpp:543\nmsgid \"Gladiator's Ring\"\nmsgstr \"Пярсцёнак гладыятара\"\n\n#: Source/items.cpp:168\nmsgid \"Oil of Mastery\"\nmsgstr \"Алей улады\"\n\n#: Source/items.cpp:170\nmsgid \"Oil of Death\"\nmsgstr \"Алей смерці\"\n\n#: Source/items.cpp:171\nmsgid \"Oil of Skill\"\nmsgstr \"Алей спраўнасці\"\n\n#: Source/items.cpp:173\nmsgid \"Oil of Fortitude\"\nmsgstr \"Алей трываласці\"\n\n#: Source/items.cpp:174\nmsgid \"Oil of Permanence\"\nmsgstr \"Алей нязменнасці\"\n\n#: Source/items.cpp:175\nmsgid \"Oil of Hardening\"\nmsgstr \"Алей гарту\"\n\n#: Source/items.cpp:176\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Алей непрабіўнасці\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1149\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0}  {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1157\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1175\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1178\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1181\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1716 Source/items.cpp:1724\nmsgid \"increases a weapon's\"\nmsgstr \"павялічвае зброі\"\n\n#: Source/items.cpp:1717\nmsgid \"chance to hit\"\nmsgstr \"шанец трапіць\"\n\n#: Source/items.cpp:1720\nmsgid \"greatly increases a\"\nmsgstr \"моцна павялічвае\"\n\n#: Source/items.cpp:1721\nmsgid \"weapon's chance to hit\"\nmsgstr \"шанец зброі трапіць\"\n\n#: Source/items.cpp:1725\nmsgid \"damage potential\"\nmsgstr \"патэнцыял шкоды\"\n\n#: Source/items.cpp:1728\nmsgid \"greatly increases a weapon's\"\nmsgstr \"моцна павялічвае зброі\"\n\n#: Source/items.cpp:1729\nmsgid \"damage potential - not bows\"\nmsgstr \"патэнцыял шкоды – не для лукаў\"\n\n#: Source/items.cpp:1732\nmsgid \"reduces attributes needed\"\nmsgstr \"змяншае неабходныя атрыбуты\"\n\n#: Source/items.cpp:1733\nmsgid \"to use armor or weapons\"\nmsgstr \"для карыстання брані ці зброі\"\n\n#: Source/items.cpp:1736\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"аднаўляе 20%\"\n\n#: Source/items.cpp:1737\nmsgid \"item's durability\"\nmsgstr \"мацунак рэчы\"\n\n#: Source/items.cpp:1740\nmsgid \"increases an item's\"\nmsgstr \"павялічвае рэчы\"\n\n#: Source/items.cpp:1741\nmsgid \"current and max durability\"\nmsgstr \"цяперашні ды максімальны мацунак\"\n\n#: Source/items.cpp:1744\nmsgid \"makes an item indestructible\"\nmsgstr \"робіць рэч незнішчальнаю\"\n\n#: Source/items.cpp:1747\nmsgid \"increases the armor class\"\nmsgstr \"павялічвае клас брані\"\n\n#: Source/items.cpp:1748\nmsgid \"of armor and shields\"\nmsgstr \"брані і шчытоў\"\n\n#: Source/items.cpp:1751\nmsgid \"greatly increases the armor\"\nmsgstr \"моцна павялічвае брані\"\n\n#: Source/items.cpp:1752\nmsgid \"class of armor and shields\"\nmsgstr \"клас даспехаў ды шчытоў\"\n\n#: Source/items.cpp:1755 Source/items.cpp:1762\nmsgid \"sets fire trap\"\nmsgstr \"ставіць вогненную пастку\"\n\n#: Source/items.cpp:1759\nmsgid \"sets lightning trap\"\nmsgstr \"ставіць маланкавую пастку\"\n\n#: Source/items.cpp:1765\nmsgid \"sets petrification trap\"\nmsgstr \"ставіць пастку акамянення\"\n\n#: Source/items.cpp:1768\nmsgid \"restore all life\"\nmsgstr \"аднавіць ўсё жыццё\"\n\n#: Source/items.cpp:1771\nmsgid \"restore some life\"\nmsgstr \"аднавіць трохі жыцця\"\n\n#: Source/items.cpp:1774\nmsgid \"recover life\"\nmsgstr \"вярнуць жыццё\"\n\n#: Source/items.cpp:1777\nmsgid \"deadly heal\"\nmsgstr \"смяротнае лячэнне\"\n\n#: Source/items.cpp:1780\nmsgid \"restore some mana\"\nmsgstr \"аднавіць трохі маны\"\n\n#: Source/items.cpp:1783\nmsgid \"restore all mana\"\nmsgstr \"аднавіць усю ману\"\n\n#: Source/items.cpp:1786\nmsgid \"increase strength\"\nmsgstr \"павялічыць моц\"\n\n#: Source/items.cpp:1789\nmsgid \"increase magic\"\nmsgstr \"павялічыць магію\"\n\n#: Source/items.cpp:1792\nmsgid \"increase dexterity\"\nmsgstr \"павялічыць спрыт\"\n\n#: Source/items.cpp:1795\nmsgid \"increase vitality\"\nmsgstr \"павялічыць жывучасць\"\n\n#: Source/items.cpp:1799\nmsgid \"decrease strength\"\nmsgstr \"паменшыць моц\"\n\n#: Source/items.cpp:1802\nmsgid \"decrease dexterity\"\nmsgstr \"паменшыць спрыт\"\n\n#: Source/items.cpp:1805\nmsgid \"decrease vitality\"\nmsgstr \"паменшыць жывучасць\"\n\n#: Source/items.cpp:1808\nmsgid \"restore some life and mana\"\nmsgstr \"аднавіць трохі жыцця ды маны\"\n\n#: Source/items.cpp:1811\nmsgid \"restore all life and mana\"\nmsgstr \"аднавіць ўсё жыццё ды ману\"\n\n#: Source/items.cpp:1826 Source/items.cpp:1866\nmsgid \"Right-click to read\"\nmsgstr \"Націснуць правай кнопкай мышы каб прачытаць\"\n\n#: Source/items.cpp:1829 Source/items.cpp:1844 Source/items.cpp:1858\nmsgid \"Open inventory to use\"\nmsgstr \"Адчыніце інвентар каб выкараставаць\"\n\n#: Source/items.cpp:1831 Source/items.cpp:1846 Source/items.cpp:1868\nmsgid \"Activate to read\"\nmsgstr \"Актывізуйце каб прачытаць\"\n\n#: Source/items.cpp:1837\nmsgid \"Right-click to read, then\"\nmsgstr \"Націснуць правай кнопкай мышы каб прачытаць, пасля\"\n\n#: Source/items.cpp:1838\nmsgid \"left-click to target\"\nmsgstr \"націснуць левай кнопкай мышы па цэлі\"\n\n#: Source/items.cpp:1841\nmsgid \"Select from spell book, then\"\nmsgstr \"Выберыце з кнігі чараў, пасля\"\n\n#: Source/items.cpp:1842\nmsgid \"cast spell to read\"\nmsgstr \"накладзіце чары каб прачытаць\"\n\n#: Source/items.cpp:1855\nmsgid \"Right-click to use\"\nmsgstr \"Правай кнопкай мышы каб выкараставаць\"\n\n#: Source/items.cpp:1860\nmsgid \"Activate to use\"\nmsgstr \"Актывізуйце каб выкараставаць\"\n\n#: Source/items.cpp:1873\nmsgid \"Right-click to view\"\nmsgstr \"Правай кнопкай мышы каб пабачыць\"\n\n#: Source/items.cpp:1875\nmsgid \"Activate to view\"\nmsgstr \"Актывуйце каб пабачыць\"\n\n#: Source/items.cpp:1879\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Узровень {:d}\"\n\n#: Source/items.cpp:1882\nmsgid \"Doubles gold capacity\"\nmsgstr \"Падвойвае ёмістасць золата\"\n\n#: Source/items.cpp:1893 Source/stores.cpp:282\nmsgid \"Required:\"\nmsgstr \"Патрэбна:\"\n\n#: Source/items.cpp:1895 Source/stores.cpp:284\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Моц\"\n\n#: Source/items.cpp:1897 Source/stores.cpp:286\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Маг\"\n\n#: Source/items.cpp:1899 Source/stores.cpp:288\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Спрт\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:3256 Source/player.cpp:3145\nmsgid \"Ear of {:s}\"\nmsgstr \"Вуха {:s}\"\n\n#: Source/items.cpp:3552\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"шанец трапіць: {:+d}%\"\n\n#: Source/items.cpp:3555\n#, no-c-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% шкоды\"\n\n#: Source/items.cpp:3558 Source/items.cpp:3759\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"трапіць: {:+d}%, {:+d}% шкоды\"\n\n#: Source/items.cpp:3561\n#, no-c-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% брані\"\n\n#: Source/items.cpp:3564\nmsgid \"armor class: {:d}\"\nmsgstr \"клас даспехаў: {:d}\"\n\n#: Source/items.cpp:3568 Source/items.cpp:3745\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Супраціў агню: {:+d}%\"\n\n#: Source/items.cpp:3570\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Супраціў агню: {:+d}% МАКС\"\n\n#: Source/items.cpp:3574\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Супраціў маланцы: {:+d}%\"\n\n#: Source/items.cpp:3576\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Супраціў маланцы: {:+d}% МАКС\"\n\n#: Source/items.cpp:3580\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Супраціў магіі: {:+d}%\"\n\n#: Source/items.cpp:3582\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Супраціў магіі: {:+d}% МАКС\"\n\n#: Source/items.cpp:3586\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Супраціў усяму: {:+d}%\"\n\n#: Source/items.cpp:3588\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Супраціў усяму: {:+d}% МАКС\"\n\n#: Source/items.cpp:3591\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"чары павышаныя на {:d} узровень\"\nmsgstr[1] \"чары павашанныя на {:d} ўзроўні\"\nmsgstr[2] \"чары павышаныя на {:d} узроўнюў\"\n\n#: Source/items.cpp:3593\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"чары паменшаныя на {:d} узровень\"\nmsgstr[1] \"чары паменьшаныя на {:d} узроўні\"\nmsgstr[2] \"чары паменьшаныя на {:d} узроўнюў\"\n\n#: Source/items.cpp:3595\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"узроўні чараў нязменныя (?)\"\n\n#: Source/items.cpp:3597\nmsgid \"Extra charges\"\nmsgstr \"Дадатковыя зарады\"\n\n#: Source/items.cpp:3599\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} зарад\"\nmsgstr[1] \"{:d} {:s} зарады\"\nmsgstr[2] \"{:d} {:s} зарадаў\"\n\n#: Source/items.cpp:3602\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Шкода агнём: {:d}\"\n\n#: Source/items.cpp:3604\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Шкода агнём: {:d}-{:d}\"\n\n#: Source/items.cpp:3607\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Шкода маланкаю: {:d}\"\n\n#: Source/items.cpp:3609\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Шкода маланкаю: {:d}-{:d}\"\n\n#: Source/items.cpp:3612\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} да моцы\"\n\n#: Source/items.cpp:3615\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} да магіі\"\n\n#: Source/items.cpp:3618\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} да спрыту\"\n\n#: Source/items.cpp:3621\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} да жывучасці\"\n\n#: Source/items.cpp:3624\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} да ўсіх атрыбутаў\"\n\n#: Source/items.cpp:3627\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} шкоды ад ворагаў\"\n\n#: Source/items.cpp:3630\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Здароўе: {:+d}\"\n\n#: Source/items.cpp:3633\nmsgid \"Mana: {:+d}\"\nmsgstr \"Мана: {:+d}\"\n\n#: Source/items.cpp:3635\nmsgid \"high durability\"\nmsgstr \"вялікі мацунак\"\n\n#: Source/items.cpp:3637\nmsgid \"decreased durability\"\nmsgstr \"паменшаны мацунак\"\n\n#: Source/items.cpp:3639\nmsgid \"indestructible\"\nmsgstr \"незнішчальны\"\n\n#: Source/items.cpp:3641\n#, no-c-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% радыуса святла\"\n\n#: Source/items.cpp:3643\n#, no-c-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% радыуса святла\"\n\n#: Source/items.cpp:3645\nmsgid \"multiple arrows per shot\"\nmsgstr \"некалькі стрэл за адзін стрэл\"\n\n#: Source/items.cpp:3648\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"шкода вогненнымі стрэламі: {:d}\"\n\n#: Source/items.cpp:3650\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"шкода вогненнымі стрэламі: {:d}-{:d}\"\n\n#: Source/items.cpp:3653\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"шкода маланкавымі стрэламі: {:d}\"\n\n#: Source/items.cpp:3655\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"шкода маланкавымі стрэламі: {:d}-{:d}\"\n\n#: Source/items.cpp:3658\nmsgid \"fireball damage: {:d}\"\nmsgstr \"шкода вогненным шарам: {:d}\"\n\n#: Source/items.cpp:3660\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"шкода вогненным шарам: {:d}-{:d}\"\n\n#: Source/items.cpp:3662\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"нападаючы атрымлівае 1-3 шкоды\"\n\n#: Source/items.cpp:3664\nmsgid \"user loses all mana\"\nmsgstr \"карыстальнік страчвае ўсю ману\"\n\n#: Source/items.cpp:3666\nmsgid \"you can't heal\"\nmsgstr \"не можаце лячыцца\"\n\n#: Source/items.cpp:3668\nmsgid \"absorbs half of trap damage\"\nmsgstr \"паглынае палову шкоды пасткі\"\n\n#: Source/items.cpp:3670\nmsgid \"knocks target back\"\nmsgstr \"адкідае цэль узад\"\n\n#: Source/items.cpp:3672\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% шкоды супраць дэманаў\"\n\n#: Source/items.cpp:3674\nmsgid \"All Resistance equals 0\"\nmsgstr \"Увесь супраціў роўны 0\"\n\n#: Source/items.cpp:3676\nmsgid \"hit monster doesn't heal\"\nmsgstr \"удар па пачвары не лечыць\"\n\n#: Source/items.cpp:3679\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"удар крадзе 3% маны\"\n\n#: Source/items.cpp:3681\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"удар крадзе 5% маны\"\n\n#: Source/items.cpp:3685\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"удар крадзе 3% жыцця\"\n\n#: Source/items.cpp:3687\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"удар крадзе 5% жыцця\"\n\n#: Source/items.cpp:3691 Source/items.cpp:3693\nmsgid \"penetrates target's armor\"\nmsgstr \"прабівае браню цэлі\"\n\n#: Source/items.cpp:3696\nmsgid \"quick attack\"\nmsgstr \"хуткі напад\"\n\n#: Source/items.cpp:3698\nmsgid \"fast attack\"\nmsgstr \"шпаркі напад\"\n\n#: Source/items.cpp:3700\nmsgid \"faster attack\"\nmsgstr \"шпарчэйшы напад\"\n\n#: Source/items.cpp:3702\nmsgid \"fastest attack\"\nmsgstr \"найшпарчэйшы напад\"\n\n#: Source/items.cpp:3703 Source/items.cpp:3711 Source/items.cpp:3769\nmsgid \"Another ability (NW)\"\nmsgstr \"Іншая здольнасць (NW)\"\n\n#: Source/items.cpp:3706\nmsgid \"fast hit recovery\"\nmsgstr \"хуткае ачуньванне па ўдары\"\n\n#: Source/items.cpp:3708\nmsgid \"faster hit recovery\"\nmsgstr \"хутчэйшае ачуньванне па ўдары\"\n\n#: Source/items.cpp:3710\nmsgid \"fastest hit recovery\"\nmsgstr \"найхутчэйшае ачуньванне па ўдары\"\n\n#: Source/items.cpp:3713\nmsgid \"fast block\"\nmsgstr \"хуткі блок\"\n\n#: Source/items.cpp:3715\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"дадае {:d} ачко шкодзе\"\nmsgstr[1] \"дадае {:d} ачкі шкодзе\"\nmsgstr[2] \"дадае {:d} ачкоў шкодзе\"\n\n#: Source/items.cpp:3717\nmsgid \"fires random speed arrows\"\nmsgstr \"пускае некалькі хуткіх стрэл\"\n\n#: Source/items.cpp:3719\nmsgid \"unusual item damage\"\nmsgstr \"незвычайная шкода рэчай\"\n\n#: Source/items.cpp:3721\nmsgid \"altered durability\"\nmsgstr \"зменены мацунак\"\n\n#: Source/items.cpp:3723\nmsgid \"Faster attack swing\"\nmsgstr \"Узмах шпарчэйшай атакі\"\n\n#: Source/items.cpp:3725\nmsgid \"one handed sword\"\nmsgstr \"аднаручны меч\"\n\n#: Source/items.cpp:3727\nmsgid \"constantly lose hit points\"\nmsgstr \"безупынна губляць здароўе\"\n\n#: Source/items.cpp:3729\nmsgid \"life stealing\"\nmsgstr \"крадзеж жыцця\"\n\n#: Source/items.cpp:3731\nmsgid \"no strength requirement\"\nmsgstr \"няма патрабавання моцы\"\n\n#: Source/items.cpp:3733\nmsgid \"see with infravision\"\nmsgstr \"глядзець скрозьбачаннем\"\n\n#: Source/items.cpp:3738\nmsgid \"lightning damage: {:d}\"\nmsgstr \"шкода маланкаю: {:d}\"\n\n#: Source/items.cpp:3740\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"шкода маланкаю: {:d}-{:d}\"\n\n#: Source/items.cpp:3742\nmsgid \"charged bolts on hits\"\nmsgstr \"выпускае зараджаныя стрэлы пры ўдарах\"\n\n#: Source/items.cpp:3749\nmsgid \"occasional triple damage\"\nmsgstr \"выпадковая патройная шкода\"\n\n#: Source/items.cpp:3751\n#, no-c-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"занепадае {:+d}% шкоды\"\n\n#: Source/items.cpp:3753\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2х шкд пачвр, 1х вам\"\n\n#: Source/items.cpp:3755\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Выпадковая 0 – 600% шкоды\"\n\n#: Source/items.cpp:3757\n#, no-c-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"нізкі спрыт, {:+d}% шкоды\"\n\n#: Source/items.cpp:3761\nmsgid \"extra AC vs demons\"\nmsgstr \"дадат. абарона ад дэманаў\"\n\n#: Source/items.cpp:3763\nmsgid \"extra AC vs undead\"\nmsgstr \"дадат. абарона ад наўцоў\"\n\n#: Source/items.cpp:3765\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% маны перайшло ў Здароўе\"\n\n#: Source/items.cpp:3767\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Здароўя перайшло ў Ману\"\n\n#: Source/items.cpp:3804 Source/items.cpp:3842\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"шкода {:d}  Незнішчальна\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:3806 Source/items.cpp:3844\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"шкода {:d}   мац: {:d}/{:d}\"\n\n#: Source/items.cpp:3809 Source/items.cpp:3847\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"шкода {:d}-{:d}  Незнішчальна\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:3811 Source/items.cpp:3849\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"шкода: {:d}-{:d}  мац: {:d}/{:d}\"\n\n#: Source/items.cpp:3816 Source/items.cpp:3859\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"браня: {:d}  Незнішчальна\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:3818 Source/items.cpp:3861\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"браня: {:d}  мац: {:d}/{:d}\"\n\n#: Source/items.cpp:3821 Source/items.cpp:3852 Source/items.cpp:3865\n#: Source/stores.cpp:256\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Зарады: {:d}/{:d}\"\n\n#: Source/items.cpp:3830\nmsgid \"unique item\"\nmsgstr \"унікальная рэч\"\n\n#: Source/items.cpp:3855 Source/items.cpp:3863 Source/items.cpp:3869\nmsgid \"Not Identified\"\nmsgstr \"Не выяўлена\"\n\n#: Source/loadsave.cpp:1870 Source/loadsave.cpp:2388\nmsgid \"Unable to open save file archive\"\nmsgstr \"Немагчыма адкрыць архіў захаванняў\"\n\n#: Source/loadsave.cpp:1873\nmsgid \"Invalid save file\"\nmsgstr \"Няправільны файл захавання\"\n\n#: Source/loadsave.cpp:1904\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Гулец толькі на ўзроўні Hellfire\"\n\n#: Source/loadsave.cpp:2150\nmsgid \"Invalid game state\"\nmsgstr \"Няправільны стан гульні\"\n\n#: Source/menu.cpp:149\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Няма як паказаць галоўнае меню\"\n\n#. TRANSLATORS: Monster Block start\n#. MT_NZOMBIE\n#: Source/monstdat.cpp:20\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Зомбі\"\n\n#: Source/monstdat.cpp:21\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Гуль\"\n\n#: Source/monstdat.cpp:22\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Гнілая туша\"\n\n#: Source/monstdat.cpp:23\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Чорная смерць\"\n\n#: Source/monstdat.cpp:24 Source/monstdat.cpp:32\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Загінулы\"\n\n#: Source/monstdat.cpp:25 Source/monstdat.cpp:33\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Рэзчык\"\n\n#: Source/monstdat.cpp:26 Source/monstdat.cpp:34\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Нячысцік\"\n\n#: Source/monstdat.cpp:27 Source/monstdat.cpp:35\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Цёмны\"\n\n#: Source/monstdat.cpp:28 Source/monstdat.cpp:40\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Шкілет\"\n\n#: Source/monstdat.cpp:29\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Мёртвы сякернік\"\n\n#: Source/monstdat.cpp:30 Source/monstdat.cpp:42\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Палымнеючы мрэц\"\n\n#: Source/monstdat.cpp:31 Source/monstdat.cpp:43\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Жах\"\n\n#: Source/monstdat.cpp:36\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Трупаед\"\n\n#: Source/monstdat.cpp:37\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Чумаед\"\n\n#: Source/monstdat.cpp:38\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Звер цемры\"\n\n#: Source/monstdat.cpp:39\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Касцяны разрэзак\"\n\n#: Source/monstdat.cpp:41\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Мёртвы лучнік\"\n\n#: Source/monstdat.cpp:44\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Шкілет капітана\"\n\n#: Source/monstdat.cpp:45\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Труп капітана\"\n\n#: Source/monstdat.cpp:46\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Палымнеючы мёртвы капітан\"\n\n#: Source/monstdat.cpp:47\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Жахлівы капітан\"\n\n#: Source/monstdat.cpp:48\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Нябачны ўладар\"\n\n#: Source/monstdat.cpp:49\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Схаваны\"\n\n#: Source/monstdat.cpp:50\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Пераследнік\"\n\n#: Source/monstdat.cpp:51\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Нябачны\"\n\n#: Source/monstdat.cpp:52\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Ткач ілюзій\"\n\n#: Source/monstdat.cpp:53\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Валадар сатыраў\"\n\n#: Source/monstdat.cpp:54 Source/monstdat.cpp:62\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Клан плоці\"\n\n#: Source/monstdat.cpp:55 Source/monstdat.cpp:63\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Клан каменя\"\n\n#: Source/monstdat.cpp:56 Source/monstdat.cpp:64\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Клан полымя\"\n\n#: Source/monstdat.cpp:57 Source/monstdat.cpp:65\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Клан ночы\"\n\n#: Source/monstdat.cpp:58\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Нячысты\"\n\n#: Source/monstdat.cpp:59\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Мірг\"\n\n#: Source/monstdat.cpp:60\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Морак\"\n\n#: Source/monstdat.cpp:61\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Фамільяр\"\n\n#: Source/monstdat.cpp:66\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Звер кіслаты\"\n\n#: Source/monstdat.cpp:67\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Ядаплюй\"\n\n#: Source/monstdat.cpp:68\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Звер з ямы\"\n\n#: Source/monstdat.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Лававая ляпа\"\n\n#: Source/monstdat.cpp:70 Source/monstdat.cpp:474\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Кароль шкілетаў\"\n\n#: Source/monstdat.cpp:71 Source/monstdat.cpp:482\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Мяснік\"\n\n#: Source/monstdat.cpp:72\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Усеўладар\"\n\n#: Source/monstdat.cpp:73\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Брыда\"\n\n#: Source/monstdat.cpp:74\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Чорт-рапуха\"\n\n#: Source/monstdat.cpp:75\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Залупцаваны\"\n\n#: Source/monstdat.cpp:76\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Змей\"\n\n#: Source/monstdat.cpp:77\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Пячорны смоўж\"\n\n#: Source/monstdat.cpp:78\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Чортаў Змей\"\n\n#: Source/monstdat.cpp:79\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Паглынальнік\"\n\n#: Source/monstdat.cpp:80\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Дэман магмы\"\n\n#: Source/monstdat.cpp:81\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Камень крыві\"\n\n#: Source/monstdat.cpp:82\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Камень пекла\"\n\n#: Source/monstdat.cpp:83\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Валадар лавы\"\n\n#: Source/monstdat.cpp:84\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Чорт рагаты\"\n\n#: Source/monstdat.cpp:85\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Брудны бягун\"\n\n#: Source/monstdat.cpp:86\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Ледзяны нападнік\"\n\n#: Source/monstdat.cpp:87\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Абсідыянавы ўладар\"\n\n#: Source/monstdat.cpp:88\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"трухлявыя косці\"\n\n#: Source/monstdat.cpp:89\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Чырвоная смерць\"\n\n#: Source/monstdat.cpp:90\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Кашчэй\"\n\n#: Source/monstdat.cpp:91\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Мёртвы балраг\"\n\n#: Source/monstdat.cpp:92\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Спальвальнік\"\n\n#: Source/monstdat.cpp:93\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Валадар полымя\"\n\n#: Source/monstdat.cpp:94\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Агонь пагібелі\"\n\n#: Source/monstdat.cpp:95\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Пякельны смальнік\"\n\n#: Source/monstdat.cpp:96\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Чырвоная бура\"\n\n#: Source/monstdat.cpp:97\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Вершнік буры\"\n\n#: Source/monstdat.cpp:98\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Валадар буры\"\n\n#: Source/monstdat.cpp:99\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Вір\"\n\n#: Source/monstdat.cpp:100\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Нячысты гіцаль\"\n\n#: Source/monstdat.cpp:101\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Крылаты чорт\"\n\n#: Source/monstdat.cpp:102\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Гаргулля\"\n\n#: Source/monstdat.cpp:103\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Крывавы кіпцюр\"\n\n#: Source/monstdat.cpp:104\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Крыло смерці\"\n\n#: Source/monstdat.cpp:105\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Забойца\"\n\n#: Source/monstdat.cpp:106\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Ахоўнік\"\n\n#: Source/monstdat.cpp:107\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Валадар віхру\"\n\n#: Source/monstdat.cpp:108\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Балраг\"\n\n#: Source/monstdat.cpp:109\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Пячорная гадзіна\"\n\n#: Source/monstdat.cpp:110\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Вогненны смок\"\n\n#: Source/monstdat.cpp:111\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Залатая гадзіна\"\n\n#: Source/monstdat.cpp:112\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Блакітны смок\"\n\n#: Source/monstdat.cpp:113\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Чорны рыцар\"\n\n#: Source/monstdat.cpp:114\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Вартавы лёсу\"\n\n#: Source/monstdat.cpp:115\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Валадар сталі\"\n\n#: Source/monstdat.cpp:116\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Рыцар крыві\"\n\n#: Source/monstdat.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Шаткаваны\"\n\n#: Source/monstdat.cpp:118\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Пусты\"\n\n#: Source/monstdat.cpp:119\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Гаспадар болю\"\n\n#: Source/monstdat.cpp:120\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Ткач запраўднасці\"\n\n#: Source/monstdat.cpp:121\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Сукуб\"\n\n#: Source/monstdat.cpp:122\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Снежная ведзьма\"\n\n#: Source/monstdat.cpp:123\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Вырадак пекла\"\n\n#: Source/monstdat.cpp:124\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Спалідуша\"\n\n#: Source/monstdat.cpp:125\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Дараднік\"\n\n#: Source/monstdat.cpp:126\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Суддзя\"\n\n#: Source/monstdat.cpp:127\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Махляр\"\n\n#: Source/monstdat.cpp:128\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Заступнік\"\n\n#: Source/monstdat.cpp:129\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/monstdat.cpp:130\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Цёмны валадар\"\n\n#: Source/monstdat.cpp:131\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Архі-Ліч Малігнус\"\n\n#: Source/monstdat.cpp:132\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Пякельны дзік\"\n\n#: Source/monstdat.cpp:133\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Джальнік\"\n\n#: Source/monstdat.cpp:134\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Псіхавока\"\n\n#: Source/monstdat.cpp:135\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Павучыска\"\n\n#: Source/monstdat.cpp:136\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Адцяты спарыш\"\n\n#: Source/monstdat.cpp:137\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Вырадак рыгатні\"\n\n#: Source/monstdat.cpp:138\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Атрутны хвост\"\n\n#: Source/monstdat.cpp:139\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Мёртвае вока\"\n\n#: Source/monstdat.cpp:140\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Валадар павукоў\"\n\n#: Source/monstdat.cpp:141\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Рабак-пуга\"\n\n#: Source/monstdat.cpp:142\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Успыхун\"\n\n#: Source/monstdat.cpp:143 Source/monstdat.cpp:483\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Рыготны чорт\"\n\n#: Source/monstdat.cpp:144\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Пеклаў жук\"\n\n#: Source/monstdat.cpp:145\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Далакоп\"\n\n#: Source/monstdat.cpp:146\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Магільны пацук\"\n\n#: Source/monstdat.cpp:147\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Агнявы кажан\"\n\n#: Source/monstdat.cpp:148\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Чарапун\"\n\n#: Source/monstdat.cpp:149\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Ліч\"\n\n#: Source/monstdat.cpp:150\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Склепавы чорт\"\n\n#: Source/monstdat.cpp:151\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Пякельны кажан\"\n\n#: Source/monstdat.cpp:152\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Касцяны чорт\"\n\n#: Source/monstdat.cpp:153\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Архіліч\"\n\n#: Source/monstdat.cpp:154\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Лупаты\"\n\n#: Source/monstdat.cpp:155\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Плоцень\"\n\n#: Source/monstdat.cpp:156\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Жнец\"\n\n#. TRANSLATORS: Monster Block end\n#. MT_NAKRUL\n#: Source/monstdat.cpp:158 Source/monstdat.cpp:485\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#. TRANSLATORS: Unique Monster Block start\n#: Source/monstdat.cpp:473\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Кволы Гарбад\"\n\n#: Source/monstdat.cpp:475\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Шалёны Зар\"\n\n#: Source/monstdat.cpp:476\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Смаркач\"\n\n#: Source/monstdat.cpp:477\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Архібіскуп Лазар\"\n\n#: Source/monstdat.cpp:478\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Чырованая бяда\"\n\n#: Source/monstdat.cpp:479\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Чорная Жад\"\n\n#: Source/monstdat.cpp:480\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Лакданан\"\n\n#: Source/monstdat.cpp:481\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Крывавы ваявода\"\n\n#: Source/monstdat.cpp:484\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Паганнік\"\n\n#: Source/monstdat.cpp:486\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Дурыла Вострая сякера\"\n\n#: Source/monstdat.cpp:487\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Лязаскурац Засякун\"\n\n#: Source/monstdat.cpp:488\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Гнойная душа\"\n\n#: Source/monstdat.cpp:489\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Ванітапац Нячысты\"\n\n#: Source/monstdat.cpp:490\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Вырвікосці\"\n\n#: Source/monstdat.cpp:491\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Банкетагнілец Галодны\"\n\n#: Source/monstdat.cpp:492\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Кішканожак Хуткі\"\n\n#: Source/monstdat.cpp:493\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Бітылоб Шчытабой\"\n\n#: Source/monstdat.cpp:494\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Банго\"\n\n#: Source/monstdat.cpp:495\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Гнілабой\"\n\n#: Source/monstdat.cpp:496\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Укус з Ценю\"\n\n#: Source/monstdat.cpp:497\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Гнілы Яблычак\"\n\n#: Source/monstdat.cpp:498\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Мёртвы Утрапенец\"\n\n#: Source/monstdat.cpp:499\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"Чупакабра\"\n\n#: Source/monstdat.cpp:500\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Вогненны Чэрап\"\n\n#: Source/monstdat.cpp:501\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Крывы Чэрап\"\n\n#: Source/monstdat.cpp:502\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Крывавы Язык\"\n\n#: Source/monstdat.cpp:503\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Пульс\"\n\n#: Source/monstdat.cpp:504\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Сагнімесяц\"\n\n#: Source/monstdat.cpp:505\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Крумкач Шалу\"\n\n#: Source/monstdat.cpp:506\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Хрыбтаед\"\n\n#: Source/monstdat.cpp:507\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Спалены Попел\"\n\n#: Source/monstdat.cpp:508\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Цёмная Варона\"\n\n#: Source/monstdat.cpp:509\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Чумны Камень Слабы\"\n\n#: Source/monstdat.cpp:510\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Гаспадар Ямы Пенажоўць\"\n\n#: Source/monstdat.cpp:511\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Цёмны лук Крываскур\"\n\n#: Source/monstdat.cpp:512\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Брыдкакрыл\"\n\n#: Source/monstdat.cpp:513\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Піток Ценю\"\n\n#: Source/monstdat.cpp:514\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Змянісмугу\"\n\n#: Source/monstdat.cpp:515\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Плявок Смерці\"\n\n#: Source/monstdat.cpp:516\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Крывасцёк\"\n\n#: Source/monstdat.cpp:517\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Рвіскуры Цень смерці\"\n\n#: Source/monstdat.cpp:518\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Шалёная Гніда\"\n\n#: Source/monstdat.cpp:519\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Зубчасты Шклочэрап\"\n\n#: Source/monstdat.cpp:520\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Агонь халеры\"\n\n#: Source/monstdat.cpp:521\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Нячулая Начніца\"\n\n#: Source/monstdat.cpp:522\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Крывакамень\"\n\n#: Source/monstdat.cpp:523\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Бронзавы Кулак агнякаменю\"\n\n#: Source/monstdat.cpp:524\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Пракляты Гнеў Полымя\"\n\n#: Source/monstdat.cpp:525\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Змрочны Апёк\"\n\n#: Source/monstdat.cpp:526\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Барон Дрыгвень\"\n\n#: Source/monstdat.cpp:527\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Чумны Рог Стальная Булава\"\n\n#: Source/monstdat.cpp:528\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Равун Хаосу\"\n\n#: Source/monstdat.cpp:529\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Згнілы Вышчар\"\n\n#: Source/monstdat.cpp:530\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Ліхі Падпальшчык\"\n\n#: Source/monstdat.cpp:531\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Кашчэй Піла\"\n\n#: Source/monstdat.cpp:532\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Зламіхрыбет\"\n\n#: Source/monstdat.cpp:533\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Востры Чэрап\"\n\n#: Source/monstdat.cpp:534\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Ветрабой\"\n\n#: Source/monstdat.cpp:535\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Ліхая Навала\"\n\n#: Source/monstdat.cpp:536\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Цячысліна\"\n\n#: Source/monstdat.cpp:537\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Злотачума Полымя\"\n\n#: Source/monstdat.cpp:538\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Чорная Бура\"\n\n#: Source/monstdat.cpp:539\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Гнеў Чумы\"\n\n#: Source/monstdat.cpp:540\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Скуралуп\"\n\n#: Source/monstdat.cpp:541\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Блакітны Рог\"\n\n#: Source/monstdat.cpp:542\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Пеклаў Вырадак Крывагню\"\n\n#: Source/monstdat.cpp:543\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Пазурак\"\n\n#: Source/monstdat.cpp:544\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Гнілы Чэрап\"\n\n#: Source/monstdat.cpp:545\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Крывы Ільвачэрап\"\n\n#: Source/monstdat.cpp:546\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Чорны Язык\"\n\n#: Source/monstdat.cpp:547\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Брыдкі дотык\"\n\n#: Source/monstdat.cpp:548\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Змеяполамень\"\n\n#: Source/monstdat.cpp:549\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Ікласкур\"\n\n#: Source/monstdat.cpp:550\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Бязбожная Вогненная Ведзьма\"\n\n#: Source/monstdat.cpp:551\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Чорны чэрап\"\n\n#: Source/monstdat.cpp:552\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Душасек\"\n\n#: Source/monstdat.cpp:553\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Дзіця ветру\"\n\n#: Source/monstdat.cpp:554\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Валадар ямы\"\n\n#: Source/monstdat.cpp:555\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Іржаткач\"\n\n#: Source/monstdat.cpp:556\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Цень Равучага Гневу\"\n\n#: Source/monstdat.cpp:557\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Воблака Долі\"\n\n#: Source/monstdat.cpp:558\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Агонь Душы з Крывавай Луны\"\n\n#: Source/monstdat.cpp:559\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Ведзьма Месяцу\"\n\n#: Source/monstdat.cpp:560\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Крывавы Банкет\"\n\n#: Source/monstdat.cpp:561\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Шэравойна Людабойца\"\n\n#: Source/monstdat.cpp:562\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Жуда-Суддзя\"\n\n#: Source/monstdat.cpp:563\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Ведзьма Зоркавока\"\n\n#: Source/monstdat.cpp:564\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Стальны чэрап Паляўнічы\"\n\n#: Source/monstdat.cpp:565\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Сэр Гораш\"\n\n#: Source/monstdat.cpp:566\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Візір\"\n\n#: Source/monstdat.cpp:567\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Замфір\"\n\n#: Source/monstdat.cpp:568\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Крывавая Прага\"\n\n#: Source/monstdat.cpp:569\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Удава Павуціння\"\n\n#: Source/monstdat.cpp:570\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Скураны Танцор\"\n\n#: Source/monstdat.cpp:571\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Змрокашып\"\n\n#. TRANSLATORS: Unique Monster Block end\n#: Source/monstdat.cpp:573\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Замок Долі\"\n\n#: Source/monster.cpp:3384\nmsgid \"Animal\"\nmsgstr \"Звер\"\n\n#: Source/monster.cpp:3386\nmsgid \"Demon\"\nmsgstr \"Чорт\"\n\n#: Source/monster.cpp:3388\nmsgid \"Undead\"\nmsgstr \"Навец\"\n\n#: Source/monster.cpp:4643\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Тып: {:s} Забітых: {:d}\"\n\n#: Source/monster.cpp:4645\nmsgid \"Total kills: {:d}\"\nmsgstr \"Усяго забітых: {:d}\"\n\n#: Source/monster.cpp:4677\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Ачкоў здароўя: {:d}-{:d}\"\n\n#: Source/monster.cpp:4682\nmsgid \"No magic resistance\"\nmsgstr \"Ані супраціву магіі\"\n\n#: Source/monster.cpp:4685\nmsgid \"Resists:\"\nmsgstr \"Супраціў:\"\n\n#: Source/monster.cpp:4687 Source/monster.cpp:4697\nmsgid \" Magic\"\nmsgstr \" Магія\"\n\n#: Source/monster.cpp:4689 Source/monster.cpp:4699\nmsgid \" Fire\"\nmsgstr \" Агонь\"\n\n#: Source/monster.cpp:4691 Source/monster.cpp:4701\nmsgid \" Lightning\"\nmsgstr \" Маланка\"\n\n#: Source/monster.cpp:4695\nmsgid \"Immune:\"\nmsgstr \"Імунітэт:\"\n\n#: Source/monster.cpp:4712\nmsgid \"Type: {:s}\"\nmsgstr \"Тып: {:s}\"\n\n#: Source/monster.cpp:4717 Source/monster.cpp:4723\nmsgid \"No resistances\"\nmsgstr \"Ані супраціваў\"\n\n#: Source/monster.cpp:4718 Source/monster.cpp:4727\nmsgid \"No Immunities\"\nmsgstr \"Ані імунітэтаў\"\n\n#: Source/monster.cpp:4721\nmsgid \"Some Magic Resistances\"\nmsgstr \"Трохі супраціву магіі\"\n\n#: Source/monster.cpp:4725\nmsgid \"Some Magic Immunities\"\nmsgstr \"Трохі імунітэту магіі\"\n\n#: Source/msg.cpp:486\nmsgid \"Trying to drop a floor item?\"\nmsgstr \"Хочаце кінуць рэч на зямлю?\"\n\n#: Source/msg.cpp:989 Source/msg.cpp:1024 Source/msg.cpp:1055\n#: Source/msg.cpp:1182 Source/msg.cpp:1214 Source/msg.cpp:1246\n#: Source/msg.cpp:1276\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} наклаў незаконную чару.\"\n\n#: Source/msg.cpp:1684 Source/multi.cpp:738 Source/multi.cpp:787\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Гулец '{:s}' (узроўню {:d}) далучыўся да гульні\"\n\n#: Source/msg.cpp:1994\nmsgid \"The game ended\"\nmsgstr \"Гульня скончана\"\n\n#: Source/msg.cpp:2000\nmsgid \"Unable to get level data\"\nmsgstr \"Немагчыма дазнацца аб узроўні\"\n\n#: Source/multi.cpp:198\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Гулец '{:s}' выйшаў з гульні\"\n\n#: Source/multi.cpp:201\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Гулец '{:s}' забіў Д'яблу і выйшаў з гульні!\"\n\n#: Source/multi.cpp:205\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Гулец '{:s}' выляцеў з-за таймаута\"\n\n#: Source/multi.cpp:789\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Гулец '{:s}' (узроўню {:d}) ужо ў гульні\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:106\nmsgid \"Mysterious\"\nmsgstr \"Таямнічы\"\n\n#: Source/objects.cpp:107\nmsgid \"Hidden\"\nmsgstr \"Схаваны\"\n\n#: Source/objects.cpp:108\nmsgid \"Gloomy\"\nmsgstr \"Змрочны\"\n\n#: Source/objects.cpp:110 Source/objects.cpp:117\nmsgid \"Magical\"\nmsgstr \"Магічны\"\n\n#: Source/objects.cpp:111\nmsgid \"Stone\"\nmsgstr \"Каменны\"\n\n#: Source/objects.cpp:112\nmsgid \"Religious\"\nmsgstr \"Набожны\"\n\n#: Source/objects.cpp:113\nmsgid \"Enchanted\"\nmsgstr \"Зачараваны\"\n\n#: Source/objects.cpp:114\nmsgid \"Thaumaturgic\"\nmsgstr \"Цудадзейны\"\n\n#: Source/objects.cpp:115\nmsgid \"Fascinating\"\nmsgstr \"Чароўны\"\n\n#: Source/objects.cpp:116\nmsgid \"Cryptic\"\nmsgstr \"Утоены\"\n\n#: Source/objects.cpp:118\nmsgid \"Eldritch\"\nmsgstr \"Жудасны\"\n\n#: Source/objects.cpp:119\nmsgid \"Eerie\"\nmsgstr \"Вусцішны\"\n\n#: Source/objects.cpp:120\nmsgid \"Divine\"\nmsgstr \"Боскі\"\n\n#: Source/objects.cpp:122\nmsgid \"Sacred\"\nmsgstr \"Святы\"\n\n#: Source/objects.cpp:123\nmsgid \"Spiritual\"\nmsgstr \"Духоўны\"\n\n#: Source/objects.cpp:124\nmsgid \"Spooky\"\nmsgstr \"Страшны\"\n\n#: Source/objects.cpp:125\nmsgid \"Abandoned\"\nmsgstr \"Кінуты\"\n\n#: Source/objects.cpp:126\nmsgid \"Creepy\"\nmsgstr \"Жахлівы\"\n\n#: Source/objects.cpp:127\nmsgid \"Quiet\"\nmsgstr \"Ціхі\"\n\n#: Source/objects.cpp:128\nmsgid \"Secluded\"\nmsgstr \"Самотны\"\n\n#: Source/objects.cpp:129\nmsgid \"Ornate\"\nmsgstr \"Аздоблены\"\n\n#: Source/objects.cpp:130\nmsgid \"Glimmering\"\nmsgstr \"Зіхатлівы\"\n\n#: Source/objects.cpp:131\nmsgid \"Tainted\"\nmsgstr \"Запэцканы\"\n\n#: Source/objects.cpp:132\nmsgid \"Oily\"\nmsgstr \"Маслены\"\n\n#: Source/objects.cpp:133\nmsgid \"Glowing\"\nmsgstr \"Святлівы\"\n\n#: Source/objects.cpp:134\nmsgid \"Mendicant's\"\nmsgstr \"Жабрацкі\"\n\n#: Source/objects.cpp:135\nmsgid \"Sparkling\"\nmsgstr \"Бліскучы\"\n\n#: Source/objects.cpp:137\nmsgid \"Shimmering\"\nmsgstr \"Мігатлівы\"\n\n#: Source/objects.cpp:138\nmsgid \"Solar\"\nmsgstr \"Сонечны\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:140\nmsgid \"Murphy's\"\nmsgstr \"Мёрфева\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:270\nmsgid \"The Great Conflict\"\nmsgstr \"Вялікае Змаганне\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:271\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Плата за грэх — вайна\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:272\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Аповесць Харадрым\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:273\nmsgid \"The Dark Exile\"\nmsgstr \"Цёмнае выгнанне\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:274\nmsgid \"The Sin War\"\nmsgstr \"Вайна граху\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:275\nmsgid \"The Binding of the Three\"\nmsgstr \"Палон Трох\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:276\nmsgid \"The Realms Beyond\"\nmsgstr \"Пазамежжа\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:277\nmsgid \"Tale of the Three\"\nmsgstr \"Аповесць аб Трох\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:278\nmsgid \"The Black King\"\nmsgstr \"Чорны Кароль\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:279\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Дзённік: Зачараванасць\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:280\nmsgid \"Journal: The Meeting\"\nmsgstr \"Дзённік: Сустрэча\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:281\nmsgid \"Journal: The Tirade\"\nmsgstr \"Дзённік: Тырада\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:282\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Дзённік: Яго моц расце\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:283\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Дзённік: НА-КРУЛ\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:284\nmsgid \"Journal: The End\"\nmsgstr \"Дзённік: Канец\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:285\nmsgid \"A Spellbook\"\nmsgstr \"Кніга Чараў\"\n\n#: Source/objects.cpp:5383\nmsgid \"Crucified Skeleton\"\nmsgstr \"Распяты шкілет\"\n\n#: Source/objects.cpp:5387\nmsgid \"Lever\"\nmsgstr \"Рычаг\"\n\n#: Source/objects.cpp:5396\nmsgid \"Open Door\"\nmsgstr \"Адчыненыя дзверы\"\n\n#: Source/objects.cpp:5398\nmsgid \"Closed Door\"\nmsgstr \"Зачыненыя дзверы\"\n\n#: Source/objects.cpp:5400\nmsgid \"Blocked Door\"\nmsgstr \"Заваленыя дзверы\"\n\n#: Source/objects.cpp:5405\nmsgid \"Ancient Tome\"\nmsgstr \"Старажытны фаліянт\"\n\n#: Source/objects.cpp:5407\nmsgid \"Book of Vileness\"\nmsgstr \"Кніга Подласці\"\n\n#: Source/objects.cpp:5412\nmsgid \"Skull Lever\"\nmsgstr \"Чэрапаў рычаг\"\n\n#: Source/objects.cpp:5415\nmsgid \"Mythical Book\"\nmsgstr \"Міфічная кніга\"\n\n#: Source/objects.cpp:5419\nmsgid \"Small Chest\"\nmsgstr \"Куфэрак\"\n\n#: Source/objects.cpp:5423\nmsgid \"Chest\"\nmsgstr \"Скрыня\"\n\n#: Source/objects.cpp:5428\nmsgid \"Large Chest\"\nmsgstr \"Куфар\"\n\n#: Source/objects.cpp:5431\nmsgid \"Sarcophagus\"\nmsgstr \"Саркафаг\"\n\n#: Source/objects.cpp:5434\nmsgid \"Bookshelf\"\nmsgstr \"Кніжная паліца\"\n\n#: Source/objects.cpp:5438\nmsgid \"Bookcase\"\nmsgstr \"Кніжная шафа\"\n\n#: Source/objects.cpp:5443\nmsgid \"Pod\"\nmsgstr \"Кокан\"\n\n#: Source/objects.cpp:5445\nmsgid \"Urn\"\nmsgstr \"Урна\"\n\n#: Source/objects.cpp:5447\nmsgid \"Barrel\"\nmsgstr \"Бочка\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:5451\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Алтар\"\n\n#: Source/objects.cpp:5454\nmsgid \"Skeleton Tome\"\nmsgstr \"Фаліянт шкілета\"\n\n#: Source/objects.cpp:5457\nmsgid \"Library Book\"\nmsgstr \"Бібліятэчная кніга\"\n\n#: Source/objects.cpp:5460\nmsgid \"Blood Fountain\"\nmsgstr \"Фантан крыві\"\n\n#: Source/objects.cpp:5463\nmsgid \"Decapitated Body\"\nmsgstr \"Абезгалоўлены труп\"\n\n#: Source/objects.cpp:5466\nmsgid \"Book of the Blind\"\nmsgstr \"Кніга Сляпых\"\n\n#: Source/objects.cpp:5469\nmsgid \"Book of Blood\"\nmsgstr \"Кніга крыві\"\n\n#: Source/objects.cpp:5472\nmsgid \"Purifying Spring\"\nmsgstr \"Ачышчальная крыніца\"\n\n#: Source/objects.cpp:5479 Source/objects.cpp:5503\nmsgid \"Weapon Rack\"\nmsgstr \"Паліца са зброяю\"\n\n#: Source/objects.cpp:5482\nmsgid \"Goat Shrine\"\nmsgstr \"Казліны алтар\"\n\n#: Source/objects.cpp:5485\nmsgid \"Cauldron\"\nmsgstr \"Кацёл\"\n\n#: Source/objects.cpp:5488\nmsgid \"Murky Pool\"\nmsgstr \"Мутны басейн\"\n\n#: Source/objects.cpp:5491\nmsgid \"Fountain of Tears\"\nmsgstr \"Фантан слёз\"\n\n#: Source/objects.cpp:5494\nmsgid \"Steel Tome\"\nmsgstr \"Стальны фаліянт\"\n\n#: Source/objects.cpp:5497\nmsgid \"Pedestal of Blood\"\nmsgstr \"Крывавы п'едэстал\"\n\n#: Source/objects.cpp:5506\nmsgid \"Mushroom Patch\"\nmsgstr \"Грыбны лапік\"\n\n#: Source/objects.cpp:5509\nmsgid \"Vile Stand\"\nmsgstr \"Агідная стойка\"\n\n#: Source/objects.cpp:5512\nmsgid \"Slain Hero\"\nmsgstr \"Загінулы герой\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:5519\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} з пасткай\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls leaver\n#: Source/objects.cpp:5524\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (немагчыма)\"\n\n#: Source/options.cpp:420 Source/options.cpp:551 Source/options.cpp:557\nmsgid \"ON\"\nmsgstr \"УКЛ\"\n\n#: Source/options.cpp:420 Source/options.cpp:549 Source/options.cpp:555\nmsgid \"OFF\"\nmsgstr \"ВЫКЛ\"\n\n#: Source/options.cpp:539\nmsgid \"Start Up\"\nmsgstr \"Запуск\"\n\n#: Source/options.cpp:539\nmsgid \"Start Up Settings\"\nmsgstr \"Запуск Наладаў\"\n\n#: Source/options.cpp:540\nmsgid \"Game Mode\"\nmsgstr \"Рэжым Гульні\"\n\n#: Source/options.cpp:540\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Гуляць у Diablo ці Hellfire.\"\n\n#: Source/options.cpp:546\nmsgid \"Restrict to Shareware\"\nmsgstr \"Абмежаваць дэма-рэжым\"\n\n#: Source/options.cpp:546\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Робіць гульню спалучанаю з дэма. Дазваляе мультыплэер з сябрамі, якія не \"\n\"маюць поўную копію Д'яблы.\"\n\n#: Source/options.cpp:547 Source/options.cpp:553\nmsgid \"Intro\"\nmsgstr \"Інтра\"\n\n#: Source/options.cpp:547 Source/options.cpp:553\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Уступны сінематык паказаны.\"\n\n#: Source/options.cpp:559\nmsgid \"Splash\"\nmsgstr \"Вітальны экран\"\n\n#: Source/options.cpp:559\nmsgid \"Shown splash screen.\"\nmsgstr \"Паказаны вітальны экран.\"\n\n#: Source/options.cpp:561\nmsgid \"Logo and Title Screen\"\nmsgstr \"Лагатып і тытульны экран\"\n\n#: Source/options.cpp:562\nmsgid \"Title Screen\"\nmsgstr \"Тытульны экран\"\n\n#: Source/options.cpp:581\nmsgid \"Diablo specific Settings\"\nmsgstr \"Спецыяльныя налады Diablo\"\n\n#: Source/options.cpp:595\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Спецыяльныя налады Hellfire\"\n\n#: Source/options.cpp:609\nmsgid \"Audio\"\nmsgstr \"Аўдыя\"\n\n#: Source/options.cpp:609\nmsgid \"Audio Settings\"\nmsgstr \"Налады аўдыя\"\n\n#: Source/options.cpp:612\nmsgid \"Walking Sound\"\nmsgstr \"Гук хадзьбы\"\n\n#: Source/options.cpp:612\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Гулец утварае гукі ходзячы.\"\n\n#: Source/options.cpp:613\nmsgid \"Auto Equip Sound\"\nmsgstr \"Гук аўтаэквіпа\"\n\n#: Source/options.cpp:613\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Аўтаматычны эквіп рэчаў утварае гук.\"\n\n#: Source/options.cpp:614\nmsgid \"Item Pickup Sound\"\nmsgstr \"Гук падбірання\"\n\n#: Source/options.cpp:614\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Падбіранне рэчаў утварае гук.\"\n\n#: Source/options.cpp:615\nmsgid \"Sample Rate\"\nmsgstr \"Частата Дыскрэтызацыі\"\n\n#: Source/options.cpp:615\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Частата дыскрэтызацыі вывада гуку (Гц).\"\n\n#: Source/options.cpp:616\nmsgid \"Channels\"\nmsgstr \"Каналы\"\n\n#: Source/options.cpp:616\nmsgid \"Number of output channels.\"\nmsgstr \"Колькасць каналаў вывада.\"\n\n#: Source/options.cpp:617\nmsgid \"Buffer Size\"\nmsgstr \"Памер буфера\"\n\n#: Source/options.cpp:617\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Памер буфера (колькасць кадраў на канал)\"\n\n#: Source/options.cpp:618\nmsgid \"Resampling Quality\"\nmsgstr \"Якасць перадыскрэтызацыі\"\n\n#: Source/options.cpp:618\nmsgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgstr \"Якасць перадыскрэтызатару, ад 0 (найменшы) да 10 (найбольшы)\"\n\n#: Source/options.cpp:641\nmsgid \"Resolution\"\nmsgstr \"Раздзяляльнасць\"\n\n#: Source/options.cpp:641\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Памяняць унутраную раздзяляльнасць гульні і вызначыць ваш бачны абсяг. \"\n\"Заўвага: Можа быць розніца з раздзяляльнасцю экрана, калі карыстуецца \"\n\"Павелічэнне маштабу, Цэлалікавае маштабаванне ці Падагнаць пад экран.\"\n\n#: Source/options.cpp:737\nmsgid \"Graphics\"\nmsgstr \"Графіка\"\n\n#: Source/options.cpp:737\nmsgid \"Graphics Settings\"\nmsgstr \"Налады графікі\"\n\n#: Source/options.cpp:738\nmsgid \"Fullscreen\"\nmsgstr \"Поўны экран\"\n\n#: Source/options.cpp:738\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Паказаць гульню ва акне ці ў поўным экране.\"\n\n#: Source/options.cpp:740\nmsgid \"Fit to Screen\"\nmsgstr \"Падагнаць пад экран\"\n\n#: Source/options.cpp:740\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Аўтаматычна наладжваць акно з гульнёю да вашых суадносінаў бакоў і \"\n\"раздзяляльнасці.\"\n\n#: Source/options.cpp:743\nmsgid \"Upscale\"\nmsgstr \"Павелічэнне маштабу\"\n\n#: Source/options.cpp:743\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Дазваляе маштабаванне ад раздзяляльнасці гульні да раздзяляльнасці вашага \"\n\"манітора. Забараняе змяняць раздзяляльнасць манітора і дазваляе змяняць \"\n\"памер вокнаў.\"\n\n#: Source/options.cpp:744\nmsgid \"Scaling Quality\"\nmsgstr \"Якасць маштабавання\"\n\n#: Source/options.cpp:744\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Уключае дадатковыя фільтры да выходнага відарыса пры павелічэнні маштабу.\"\n\n#: Source/options.cpp:746\nmsgid \"Nearest Pixel\"\nmsgstr \"Найбліжэйшы Піксель\"\n\n#: Source/options.cpp:747\nmsgid \"Bilinear\"\nmsgstr \"Білінейны\"\n\n#: Source/options.cpp:748\nmsgid \"Anisotropic\"\nmsgstr \"Анізатропны\"\n\n#: Source/options.cpp:750\nmsgid \"Integer Scaling\"\nmsgstr \"Цэлалікавае маштабаванне\"\n\n#: Source/options.cpp:750\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Маштабуе відарыс, карыстуючы суадносіны пікселей цэлага ліку.\"\n\n#: Source/options.cpp:751\nmsgid \"Vertical Sync\"\nmsgstr \"Вертыкальная Сінхранізацыя\"\n\n#: Source/options.cpp:751\nmsgid \"\"\n\"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n\"frame. Disabling it can help with mouse lag on some systems.\"\nmsgstr \"\"\n\"Прымушае пачакаць Вертыкальную Сінхранізацыю. Забараняе эфект разрыву калі \"\n\"кадр вымалёўваецца. Калі яго выключыць у некаторых сістэмах ладзіць лаг \"\n\"мышкі.\"\n\n#: Source/options.cpp:754\nmsgid \"Color Cycling\"\nmsgstr \"Зацыкліванне колеру\"\n\n#: Source/options.cpp:754\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Эфект зацыклівання колеру карыстуецца для анімацыі вады, лавы, і кіслаты.\"\n\n#: Source/options.cpp:755\nmsgid \"Alternate nest art\"\nmsgstr \"Альтэрнатыўны малюнак гнязда\"\n\n#: Source/options.cpp:755\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"У гульні выкарыстуецца альтэрнатыўная палітра для набору пліт гнязда для \"\n\"Hellfire.\"\n\n#: Source/options.cpp:757\nmsgid \"Hardware Cursor\"\nmsgstr \"Курсор апаратнага забеспячэння\"\n\n#: Source/options.cpp:757\nmsgid \"Use a hardware cursor\"\nmsgstr \"Карыстаць курсор апаратнага забеспячэння\"\n\n#: Source/options.cpp:758\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Курсор апаратнага забеспячэння для рэчаў\"\n\n#: Source/options.cpp:758\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Карыстаць курсор апаратнага забеспячэння для рэчаў.\"\n\n#: Source/options.cpp:759\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Максімальны размер курсора апаратнага забеспячэння\"\n\n#: Source/options.cpp:759\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"Максімальная шырыня / даўжыня для курсора апаратнага забеспячэння.\"\n\n#: Source/options.cpp:761\nmsgid \"FPS Limiter\"\nmsgstr \"Абмежавальнік FPS\"\n\n#: Source/options.cpp:761\nmsgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\nmsgstr \"\"\n\"FPS абмежаваны, каб пазбегнуць высокай нагрузкі на працэсар. Ліміт улічвае \"\n\"частату абнаўлення.\"\n\n#: Source/options.cpp:762\nmsgid \"Show FPS\"\nmsgstr \"Паказваць FPS\"\n\n#: Source/options.cpp:762\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Адлюстроўвае FPS у левым верхнім куце экрана.\"\n\n#: Source/options.cpp:763\nmsgid \"Show health values\"\nmsgstr \"Паказаць велічыню здароўя\"\n\n#: Source/options.cpp:763\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"\"\n\"Адлюстроўвае цяперашняе / максімальнае значэнне здароўя на шары здароўя.\"\n\n#: Source/options.cpp:764\nmsgid \"Show mana values\"\nmsgstr \"Паказаць велічыню маны\"\n\n#: Source/options.cpp:764\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Паказаць цяперашнюю / максімальную велічыню маны на шары маны.\"\n\n#: Source/options.cpp:813\nmsgid \"Gameplay\"\nmsgstr \"Гульня\"\n\n#: Source/options.cpp:813\nmsgid \"Gameplay Settings\"\nmsgstr \"Налады гульні\"\n\n#: Source/options.cpp:815\nmsgid \"Run in Town\"\nmsgstr \"Бегчы ў Горадзе\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Дазволіць бег/хуткую хаду ў горадзе для Diablo і Hellfire. Гэтая опцыя была \"\n\"ўведзена ў пашырэнні.\"\n\n#: Source/options.cpp:816\nmsgid \"Grab Input\"\nmsgstr \"Захапіць мыш\"\n\n#: Source/options.cpp:816\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Калі ўключана, мыш фіксуецца ў акне гульні.\"\n\n#: Source/options.cpp:817\nmsgid \"Theo Quest\"\nmsgstr \"Заданне Тэа\"\n\n#: Source/options.cpp:817\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Уключыць квэст \\\"Маленькая дзяўчынка\\\".\"\n\n#: Source/options.cpp:818\nmsgid \"Cow Quest\"\nmsgstr \"Заданне Каровы\"\n\n#: Source/options.cpp:818\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"Уключыць квэст Джэрсі. Фермер Лестэр замяняецца.\"\n\n#: Source/options.cpp:819\nmsgid \"Friendly Fire\"\nmsgstr \"Агонь па сваіх\"\n\n#: Source/options.cpp:819\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Дазволіць наносіць шкоду стрэламі/чарамі паміж гульцамі ў \"\n\"шматкарыстальніцкім рэжыме, нават калі ўключаны сяброўскі рэжым.\"\n\n#: Source/options.cpp:820\nmsgid \"Test Bard\"\nmsgstr \"Проба Барда\"\n\n#: Source/options.cpp:820\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Прымусіць тып персанажа \\\"Бард\\\" з'явіцца ў меню выбара героя.\"\n\n#: Source/options.cpp:821\nmsgid \"Test Barbarian\"\nmsgstr \"Проба Варвара\"\n\n#: Source/options.cpp:821\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Прымусіць тып персанажа \\\"Бард\\\" з'явіцца ў меню выбара героя.\"\n\n#: Source/options.cpp:822\nmsgid \"Experience Bar\"\nmsgstr \"Палоска досведу\"\n\n#: Source/options.cpp:822\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"У карыстальніцкі інтэрфэйс унізе экрана дадаецца палоска досведу.\"\n\n#: Source/options.cpp:823\nmsgid \"Enemy Health Bar\"\nmsgstr \"Палоска здароўя ворагаў\"\n\n#: Source/options.cpp:823\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Наверсе экрана паказваецца палоска здароўя ворага.\"\n\n#: Source/options.cpp:824\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Аўта-падняцце золата\"\n\n#: Source/options.cpp:824\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Золота аўтаматычна збіраецца, калі блізка да гульца.\"\n\n#: Source/options.cpp:825\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Аўта-падняцце эліксіраў\"\n\n#: Source/options.cpp:825\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Эліксіры падымаюцца аўтаматычна, калі блізка да гульца.\"\n\n#: Source/options.cpp:826\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Аўта-падняцце ў Горадзе\"\n\n#: Source/options.cpp:826\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Аўтаматычна падымаць рэчы ў горадзе.\"\n\n#: Source/options.cpp:827\nmsgid \"Adria Refills Mana\"\nmsgstr \"Эйдрыя Папаўняе Ману\"\n\n#: Source/options.cpp:827\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Эйдрыя будзе папаўняць вашу ману, пры наведванні яе крамы.\"\n\n#: Source/options.cpp:828\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Аўта-эквіп зброі\"\n\n#: Source/options.cpp:828\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Зброя будзе аўтаматычна экіпіравана пры атрыманні або куплі, калі ўключана.\"\n\n#: Source/options.cpp:829\nmsgid \"Auto Equip Armor\"\nmsgstr \"Аўта-эквіп брані\"\n\n#: Source/options.cpp:829\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Браня будзе аўтаматычна экіпіравана пры атрыманні або куплі, калі ўключана.\"\n\n#: Source/options.cpp:830\nmsgid \"Auto Equip Helms\"\nmsgstr \"Аўта-эквіп шаломаў\"\n\n#: Source/options.cpp:830\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Шаломы будуць аўтаматычна экіпіраваны пры атрыманні або куплі, калі ўключана.\"\n\n#: Source/options.cpp:831\nmsgid \"Auto Equip Shields\"\nmsgstr \"Аўта-эквіп шчытоў\"\n\n#: Source/options.cpp:831\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Шчыты будуць аўтаматычна экіпіраваны пры атрыманні або куплі, калі ўключана.\"\n\n#: Source/options.cpp:832\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Аўта-эквіп каштоўнасцяў\"\n\n#: Source/options.cpp:832\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Каштоўнасці будуць аўтаматычна экіпіраваны пры атрыманні або куплі, калі \"\n\"гэтая функцыя ўключана.\"\n\n#: Source/options.cpp:833\nmsgid \"Randomize Quests\"\nmsgstr \"Выпадковы парадак заданняў\"\n\n#: Source/options.cpp:833\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Выпадковы выбар даступных заданняў для новых гульняў.\"\n\n#: Source/options.cpp:834\nmsgid \"Show Monster Type\"\nmsgstr \"Паказаць тып монстра\"\n\n#: Source/options.cpp:834\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Пры навядзенні курсора на монстра яго тып будзе адлюстроўвацца ў полі \"\n\"апісання ў карыстальніцкім інтэрфейсе.\"\n\n#: Source/options.cpp:835\nmsgid \"Auto Refill Belt\"\nmsgstr \"Аўтазапаўненне ячэйкі пояса\"\n\n#: Source/options.cpp:835\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Укладваць з інвентара ў пояс, калі рэч на поясе спажываецца.\"\n\n#: Source/options.cpp:836\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Адключыць шкодныя Алтары\"\n\n#: Source/options.cpp:836\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n\"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgstr \"\"\n\"Калі ўключана, нельга націснуць на Катлы, Чароўныя Алтары, Казліныя Алтары, \"\n\"Аздобленыя Алтары, Святыя Алтары, і яны паказаныя як нерабочыя.\"\n\n#: Source/options.cpp:837\nmsgid \"Quick Cast\"\nmsgstr \"Хуткія чары\"\n\n#: Source/options.cpp:837\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"Гарачыя клавішы Чар імгненна накладваюць чары.\"\n\n#: Source/options.cpp:838\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Падбіранне зелляў лячэння\"\n\n#: Source/options.cpp:838\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Колькасць зелляў лячэння, што аўтаматычна падбяруцца.\"\n\n#: Source/options.cpp:839\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Падбіранне зелляў поўнага лячэння\"\n\n#: Source/options.cpp:839\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Колькасць зелляў поўнага лячэння, што аўтаматычна падбяруцца.\"\n\n#: Source/options.cpp:840\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Падбіранне зелляў маны\"\n\n#: Source/options.cpp:840\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Колькасць зелляў маны, што аўтаматычна падбяруцца.\"\n\n#: Source/options.cpp:841\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Падбіранне зелляў поўнай маны\"\n\n#: Source/options.cpp:841\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Колькасць зелляў поўнай маны, што аўтаматычна падбяруцца.\"\n\n#: Source/options.cpp:842\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Падбіранне зелляў аднаўлення\"\n\n#: Source/options.cpp:842\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Колькасць зелляў аднаўлення, што аўтаматычна падбяруцца.\"\n\n#: Source/options.cpp:843\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Падбіранне зелляў поўнага аднаўлення\"\n\n#: Source/options.cpp:843\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Колькасць зелляў поўнага аднаўлення, што аўтаматычна падбяруцца.\"\n\n#: Source/options.cpp:886\nmsgid \"Controller\"\nmsgstr \"Кантролер\"\n\n#: Source/options.cpp:886\nmsgid \"Controller Settings\"\nmsgstr \"Налады кантролера\"\n\n#: Source/options.cpp:895\nmsgid \"Network\"\nmsgstr \"Сетка\"\n\n#: Source/options.cpp:895\nmsgid \"Network Settings\"\nmsgstr \"Налады Сеткі\"\n\n#: Source/options.cpp:907\nmsgid \"Chat\"\nmsgstr \"Чат\"\n\n#: Source/options.cpp:907\nmsgid \"Chat Settings\"\nmsgstr \"Налады чата\"\n\n#: Source/options.cpp:916 Source/options.cpp:1032\nmsgid \"Language\"\nmsgstr \"Мова\"\n\n#: Source/options.cpp:916\nmsgid \"Define what language to use in game.\"\nmsgstr \"Выбраць мову для гульні.\"\n\n#: Source/options.cpp:1032\nmsgid \"Language Settings\"\nmsgstr \"Налады Мовы\"\n\n#: Source/options.cpp:1044\nmsgid \"Keymapping\"\nmsgstr \"Раскладка\"\n\n#: Source/options.cpp:1044\nmsgid \"Keymapping Settings\"\nmsgstr \"Налады раскладкі\"\n\n#: Source/panels/charpanel.cpp:130\nmsgid \"Level\"\nmsgstr \"Узровень\"\n\n#: Source/panels/charpanel.cpp:132\nmsgid \"Experience\"\nmsgstr \"Досвед\"\n\n#: Source/panels/charpanel.cpp:134\nmsgid \"Next level\"\nmsgstr \"Наступны ўзровень\"\n\n#: Source/panels/charpanel.cpp:142\nmsgid \"Base\"\nmsgstr \"Базавы\"\n\n#: Source/panels/charpanel.cpp:143\nmsgid \"Now\"\nmsgstr \"Цяперашні\"\n\n#: Source/panels/charpanel.cpp:144\nmsgid \"Strength\"\nmsgstr \"Моц\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Magic\"\nmsgstr \"Магія\"\n\n#: Source/panels/charpanel.cpp:152\nmsgid \"Dexterity\"\nmsgstr \"Спрыт\"\n\n#: Source/panels/charpanel.cpp:155\nmsgid \"Vitality\"\nmsgstr \"Жывучасць\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Points to distribute\"\nmsgstr \"Ачкі на размеркаванне\"\n\n#: Source/panels/charpanel.cpp:168\nmsgid \"Armor class\"\nmsgstr \"Клас даспехаў\"\n\n#: Source/panels/charpanel.cpp:170\nmsgid \"To hit\"\nmsgstr \"Ударыць\"\n\n#: Source/panels/charpanel.cpp:172\nmsgid \"Damage\"\nmsgstr \"Шкода\"\n\n#: Source/panels/charpanel.cpp:179\nmsgid \"Life\"\nmsgstr \"Жыццё\"\n\n#: Source/panels/charpanel.cpp:183\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Resist magic\"\nmsgstr \"Супраціў магіі\"\n\n#: Source/panels/charpanel.cpp:190\nmsgid \"Resist fire\"\nmsgstr \"Супраціў агню\"\n\n#: Source/panels/charpanel.cpp:192\nmsgid \"Resist lightning\"\nmsgstr \"Супраціў маланцы\"\n\n#: Source/panels/mainpanel.cpp:62 Source/panels/mainpanel.cpp:106\n#: Source/panels/mainpanel.cpp:108\nmsgid \"voice\"\nmsgstr \"голас\"\n\n#: Source/panels/mainpanel.cpp:84\nmsgid \"char\"\nmsgstr \"перс\"\n\n#: Source/panels/mainpanel.cpp:85\nmsgid \"quests\"\nmsgstr \"квэсты\"\n\n#: Source/panels/mainpanel.cpp:86\nmsgid \"map\"\nmsgstr \"мапа\"\n\n#: Source/panels/mainpanel.cpp:87\nmsgid \"menu\"\nmsgstr \"меню\"\n\n#: Source/panels/mainpanel.cpp:88\nmsgid \"inv\"\nmsgstr \"інв\"\n\n#: Source/panels/mainpanel.cpp:89\nmsgid \"spells\"\nmsgstr \"чары\"\n\n#: Source/panels/mainpanel.cpp:101 Source/panels/mainpanel.cpp:103\n#: Source/panels/mainpanel.cpp:105\nmsgid \"mute\"\nmsgstr \"мут\"\n\n#: Source/panels/spell_book.cpp:155 Source/panels/spell_list.cpp:162\nmsgid \"Skill\"\nmsgstr \"Уменне\"\n\n#: Source/panels/spell_book.cpp:159\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Посах ({:d} зарад)\"\nmsgstr[1] \"Посах ({:d} зарады)\"\nmsgstr[2] \"Посах ({:d} зарадаў)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:164\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Узровень {:d}\"\n\n#: Source/panels/spell_book.cpp:166\nmsgid \"Unusable\"\nmsgstr \"Нягодны\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:174\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Лечыць: {:d} – {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:176\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Шкода: {:d} – {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:180\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Шкд: 1/3 хп цэлі\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:182\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Мана: {:d}\"\n\n#: Source/panels/spell_list.cpp:169\nmsgid \"Spell\"\nmsgstr \"Чара\"\n\n#: Source/panels/spell_list.cpp:172\nmsgid \"Damages undead only\"\nmsgstr \"Шкодзіць толькі наўцам\"\n\n#: Source/panels/spell_list.cpp:183\nmsgid \"Scroll\"\nmsgstr \"Скрутак\"\n\n#: Source/panels/spell_list.cpp:204\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Гарачая клавіша Чары  {:s}\"\n\n#: Source/pfile.cpp:266\nmsgid \"Failed to open player archive for writing.\"\nmsgstr \"Не ўдалося адкрыць архіў гульца для запісу.\"\n\n#: Source/pfile.cpp:308\nmsgid \"Failed to open stash archive for writing.\"\nmsgstr \"Не ўдалося адкрыць схаваны архіў для запісу.\"\n\n#: Source/pfile.cpp:419\nmsgid \"Unable to open archive\"\nmsgstr \"Немагчыма адкрыць архіў\"\n\n#: Source/pfile.cpp:421\nmsgid \"Unable to load character\"\nmsgstr \"Немагчыма загрузіць персанажа\"\n\n#: Source/pfile.cpp:445 Source/pfile.cpp:465\nmsgid \"Unable to read to save file archive\"\nmsgstr \"Немагчыма прачытаць, каб захаваць архіў файла\"\n\n#: Source/pfile.cpp:484\nmsgid \"Unable to write to save file archive\"\nmsgstr \"Немагчыма запісаць, каб захаваць архіў файла\"\n\n#: Source/plrmsg.cpp:83 Source/qol/chatlog.cpp:126\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (узр {:d}): \"\n\n#: Source/qol/chatlog.cpp:154\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Гісторыя чата (Паведамленняў: {:d})\"\n\n#: Source/qol/itemlabels.cpp:72\nmsgid \"{:s} gold\"\nmsgstr \"{:s} золата\"\n\n#: Source/qol/stash.cpp:619\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Колькі манет хочаце пакінуць?\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/qol/xpbar.cpp:61\nmsgid \",\"\nmsgstr \",\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Level {:d}\"\nmsgstr \"Узровень {:d}\"\n\n#: Source/qol/xpbar.cpp:152 Source/qol/xpbar.cpp:160\nmsgid \"Experience: {:s}\"\nmsgstr \"Досвед {:s}\"\n\n#: Source/qol/xpbar.cpp:153\nmsgid \"Maximum Level\"\nmsgstr \"Максімальны ўзровень\"\n\n#: Source/qol/xpbar.cpp:161\nmsgid \"Next Level: {:s}\"\nmsgstr \"Наступны ўзровень {:s}\"\n\n#: Source/qol/xpbar.cpp:162\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} да ўзроўню {:d}\"\n\n#. TRANSLATORS: Quest Name Block\n#: Source/quests.cpp:44\nmsgid \"The Magic Rock\"\nmsgstr \"Магічны камень\"\n\n#: Source/quests.cpp:46\nmsgid \"Gharbad The Weak\"\nmsgstr \"Кволы Гарбад\"\n\n#: Source/quests.cpp:47\nmsgid \"Zhar the Mad\"\nmsgstr \"Шалёны Зар\"\n\n#: Source/quests.cpp:48\nmsgid \"Lachdanan\"\nmsgstr \"Лакданан\"\n\n#: Source/quests.cpp:50\nmsgid \"The Butcher\"\nmsgstr \"Мяснік\"\n\n#: Source/quests.cpp:51\nmsgid \"Ogden's Sign\"\nmsgstr \"Знак Огдэна\"\n\n#: Source/quests.cpp:52\nmsgid \"Halls of the Blind\"\nmsgstr \"Залы Сляпых\"\n\n#: Source/quests.cpp:53\nmsgid \"Valor\"\nmsgstr \"Адвага\"\n\n#: Source/quests.cpp:55\nmsgid \"Warlord of Blood\"\nmsgstr \"Крывавы ваявода\"\n\n#: Source/quests.cpp:56\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Праклён караля Леорыка\"\n\n#: Source/quests.cpp:57 Source/setmaps.cpp:27\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Атручаны запас вады\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:58 Source/quests.cpp:94\nmsgid \"The Chamber of Bone\"\nmsgstr \"Пакой Касцей\"\n\n#: Source/quests.cpp:59\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Архібіскуп Лазар\"\n\n#: Source/quests.cpp:60\nmsgid \"Grave Matters\"\nmsgstr \"Магільныя справы\"\n\n#: Source/quests.cpp:61\nmsgid \"Farmer's Orchard\"\nmsgstr \"Садок фермера\"\n\n#: Source/quests.cpp:62\nmsgid \"Little Girl\"\nmsgstr \"Дзяўчынка\"\n\n#: Source/quests.cpp:63\nmsgid \"Wandering Trader\"\nmsgstr \"Вандроўны гандляр\"\n\n#: Source/quests.cpp:64\nmsgid \"The Defiler\"\nmsgstr \"Паганнік\"\n\n#: Source/quests.cpp:65\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#: Source/quests.cpp:66 Source/trigs.cpp:449\nmsgid \"Cornerstone of the World\"\nmsgstr \"Краевугольны камень свету\"\n\n#. TRANSLATORS: Quest Name Block end\n#: Source/quests.cpp:67\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Джэрсі Джэрсі\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:93\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Грабніца караля Леорыка\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:95 Source/setmaps.cpp:26\nmsgid \"Maze\"\nmsgstr \"Лабірынт\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:96\nmsgid \"A Dark Passage\"\nmsgstr \"Цёмны Пераход\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:97\nmsgid \"Unholy Altar\"\nmsgstr \"Паганы алтар\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:451\nmsgid \"To {:s}\"\nmsgstr \"Для {:s}\"\n\n#: Source/setmaps.cpp:24\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Логава Караля шкілетаў\"\n\n#: Source/setmaps.cpp:25\nmsgid \"Chamber of Bone\"\nmsgstr \"Пакой Касцей\"\n\n#: Source/setmaps.cpp:28\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Логава архібіскупа Лазара\"\n\n#: Source/spelldat.cpp:16\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Вогненная бліскавіца\"\n\n#: Source/spelldat.cpp:17\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Лячэнне\"\n\n#: Source/spelldat.cpp:18\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Маланка\"\n\n#: Source/spelldat.cpp:19\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Бліск\"\n\n#: Source/spelldat.cpp:20\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Выявіць\"\n\n#: Source/spelldat.cpp:21\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Сцяна агню\"\n\n#: Source/spelldat.cpp:22\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Партал у Горад\"\n\n#: Source/spelldat.cpp:23\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Каменны праклён\"\n\n#: Source/spelldat.cpp:24\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Скрозьбачанне\"\n\n#: Source/spelldat.cpp:25\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Перамяшчэнне\"\n\n#: Source/spelldat.cpp:26\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Шчыт маны\"\n\n#: Source/spelldat.cpp:27\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Вогненны шар\"\n\n#: Source/spelldat.cpp:28\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Стораж\"\n\n#: Source/spelldat.cpp:29\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Маланкавы ланцуг\"\n\n#: Source/spelldat.cpp:30\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Хваля полымя\"\n\n#: Source/spelldat.cpp:31\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Змеі пагібелі\"\n\n#: Source/spelldat.cpp:32\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Крывавы рытуал\"\n\n#: Source/spelldat.cpp:33\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Новая Зорка\"\n\n#: Source/spelldat.cpp:34\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Нябачнасць\"\n\n#: Source/spelldat.cpp:35\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Пекла\"\n\n#: Source/spelldat.cpp:36\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/spelldat.cpp:37\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Гнеў\"\n\n#: Source/spelldat.cpp:38\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Тэлепорт\"\n\n#: Source/spelldat.cpp:39\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Апакаліпсіс\"\n\n#: Source/spelldat.cpp:40\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Этэрызаваць\"\n\n#: Source/spelldat.cpp:41\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Наладка рэчы\"\n\n#: Source/spelldat.cpp:42\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Перазарадка посаха\"\n\n#: Source/spelldat.cpp:43\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Абяскоджванне пасткі\"\n\n#: Source/spelldat.cpp:44\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Элементаль\"\n\n#: Source/spelldat.cpp:45\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Зараджаная бліскавіца\"\n\n#: Source/spelldat.cpp:46\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Святая бліскавіца\"\n\n#: Source/spelldat.cpp:47\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Уваскрасіць\"\n\n#: Source/spelldat.cpp:48\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Тэлекінэз\"\n\n#: Source/spelldat.cpp:49\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Лячы Блізкага\"\n\n#: Source/spelldat.cpp:50\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Крывавая зорка\"\n\n#: Source/spelldat.cpp:51\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Дух косці\"\n\n#: Source/spelldat.cpp:52\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n#: Source/spelldat.cpp:53\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Мудрацы\"\n\n#: Source/spelldat.cpp:54\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Блазан\"\n\n#: Source/spelldat.cpp:55\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Сцяна маланкі\"\n\n#: Source/spelldat.cpp:56\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Спаленне\"\n\n#: Source/spelldat.cpp:57\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Скажэнне\"\n\n#: Source/spelldat.cpp:58\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Адбіццё\"\n\n#: Source/spelldat.cpp:59\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Берсерк\"\n\n#: Source/spelldat.cpp:60\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Пярсцёнак агню\"\n\n#: Source/spelldat.cpp:61\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Пошук\"\n\n#: Source/spelldat.cpp:62\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Руна агню\"\n\n#: Source/spelldat.cpp:63\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Руна святла\"\n\n#: Source/spelldat.cpp:64\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Руна новай зоркі\"\n\n#: Source/spelldat.cpp:65\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Руна спалення\"\n\n#: Source/spelldat.cpp:66\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Руна каменя\"\n\n#: Source/stores.cpp:93\nmsgid \"Griswold\"\nmsgstr \"Грызвальд\"\n\n#: Source/stores.cpp:94\nmsgid \"Pepin\"\nmsgstr \"Піпін\"\n\n#: Source/stores.cpp:96\nmsgid \"Ogden\"\nmsgstr \"Огдэн\"\n\n#: Source/stores.cpp:97\nmsgid \"Cain\"\nmsgstr \"Каін\"\n\n#: Source/stores.cpp:98\nmsgid \"Farnham\"\nmsgstr \"Фарнам\"\n\n#: Source/stores.cpp:99\nmsgid \"Adria\"\nmsgstr \"Эйдрыя\"\n\n#: Source/stores.cpp:100 Source/stores.cpp:1313\nmsgid \"Gillian\"\nmsgstr \"Джыльен\"\n\n#: Source/stores.cpp:101\nmsgid \"Wirt\"\nmsgstr \"Вірт\"\n\n#: Source/stores.cpp:220 Source/stores.cpp:227\nmsgid \"Back\"\nmsgstr \"Назад\"\n\n#: Source/stores.cpp:249 Source/stores.cpp:255\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:266\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Шкода {:d}-{:d} \"\n\n#: Source/stores.cpp:268\nmsgid \"Armor: {:d}  \"\nmsgstr \"Браня: {:d} \"\n\n#: Source/stores.cpp:270\nmsgid \"Dur: {:d}/{:d},  \"\nmsgstr \"Мац: {:d}/{:d}, \"\n\n#: Source/stores.cpp:272\nmsgid \"Indestructible,  \"\nmsgstr \"Незнішчальны \"\n\n#: Source/stores.cpp:280\nmsgid \"No required attributes\"\nmsgstr \"Няма патрэбных атрыбутаў\"\n\n#: Source/stores.cpp:312 Source/stores.cpp:1064 Source/stores.cpp:1300\nmsgid \"Welcome to the\"\nmsgstr \"Вітаем у\"\n\n#: Source/stores.cpp:313\nmsgid \"Blacksmith's shop\"\nmsgstr \"Кавальская майстэрня\"\n\n#: Source/stores.cpp:314 Source/stores.cpp:668 Source/stores.cpp:1066\n#: Source/stores.cpp:1124 Source/stores.cpp:1302 Source/stores.cpp:1314\n#: Source/stores.cpp:1327\nmsgid \"Would you like to:\"\nmsgstr \"Ці хацелі б вы:\"\n\n#: Source/stores.cpp:315\nmsgid \"Talk to Griswold\"\nmsgstr \"Пагаварыць з Грызвальдам\"\n\n#: Source/stores.cpp:316\nmsgid \"Buy basic items\"\nmsgstr \"Купіць базавыя рэчы\"\n\n#: Source/stores.cpp:317\nmsgid \"Buy premium items\"\nmsgstr \"Купіць асаблівыя рэчы\"\n\n#: Source/stores.cpp:318 Source/stores.cpp:671\nmsgid \"Sell items\"\nmsgstr \"Прадаць\"\n\n#: Source/stores.cpp:319\nmsgid \"Repair items\"\nmsgstr \"Наладзіць\"\n\n#: Source/stores.cpp:320\nmsgid \"Leave the shop\"\nmsgstr \"Сысці з крамы\"\n\n#: Source/stores.cpp:363 Source/stores.cpp:728 Source/stores.cpp:1101\nmsgid \"I have these items for sale:\"\nmsgstr \"Маю тут на продаж:\"\n\n#: Source/stores.cpp:428\nmsgid \"I have these premium items for sale:\"\nmsgstr \"На продаж маю асаблівыя рэчы:\"\n\n#: Source/stores.cpp:547 Source/stores.cpp:821\nmsgid \"You have nothing I want.\"\nmsgstr \"Не маеш, што мне трэба.\"\n\n#: Source/stores.cpp:558 Source/stores.cpp:833\nmsgid \"Which item is for sale?\"\nmsgstr \"Што прадаеш?\"\n\n#: Source/stores.cpp:629\nmsgid \"You have nothing to repair.\"\nmsgstr \"Няма чаго ладзіць.\"\n\n#: Source/stores.cpp:640\nmsgid \"Repair which item?\"\nmsgstr \"Якую рэч наладзіць?\"\n\n#: Source/stores.cpp:667\nmsgid \"Witch's shack\"\nmsgstr \"Ведзьмін будан\"\n\n#: Source/stores.cpp:669\nmsgid \"Talk to Adria\"\nmsgstr \"Пагаварыць з Эйдрыяй\"\n\n#: Source/stores.cpp:670 Source/stores.cpp:1068\nmsgid \"Buy items\"\nmsgstr \"Купіць\"\n\n#: Source/stores.cpp:672\nmsgid \"Recharge staves\"\nmsgstr \"Перазарадзіць посахі\"\n\n#: Source/stores.cpp:673\nmsgid \"Leave the shack\"\nmsgstr \"Сысці з будана\"\n\n#: Source/stores.cpp:895\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Няма чаго перазараджаць.\"\n\n#: Source/stores.cpp:906\nmsgid \"Recharge which item?\"\nmsgstr \"Якую рэч перазарадзіць?\"\n\n#: Source/stores.cpp:919\nmsgid \"You do not have enough gold\"\nmsgstr \"Не хапае золата\"\n\n#: Source/stores.cpp:927\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Не хапае месца ў інтвентары\"\n\n#: Source/stores.cpp:966\nmsgid \"Do we have a deal?\"\nmsgstr \"Ну, згода?\"\n\n#: Source/stores.cpp:969\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Праўда хочаце выявіць гэту рэч?\"\n\n#: Source/stores.cpp:975\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Праўда хочаце гэта купіць?\"\n\n#: Source/stores.cpp:978\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Праўда хочаце перазарадзіць гэту рэч?\"\n\n#: Source/stores.cpp:982\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Праўда хочаце гэта прадаць?\"\n\n#: Source/stores.cpp:985\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Праўда хочаце наладзіць гэту рэч?\"\n\n#: Source/stores.cpp:999 Source/towners.cpp:150\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Аднаногі хлопчык Вірт\"\n\n#: Source/stores.cpp:1002 Source/stores.cpp:1009\nmsgid \"Talk to Wirt\"\nmsgstr \"Пагаварыць з Віртам\"\n\n#: Source/stores.cpp:1003\nmsgid \"I have something for sale,\"\nmsgstr \"Маю тут на продаж,\"\n\n#: Source/stores.cpp:1004\nmsgid \"but it will cost 50 gold\"\nmsgstr \"але проста каб зірнуць\"\n\n#: Source/stores.cpp:1005\nmsgid \"just to take a look. \"\nmsgstr \"50 золата. \"\n\n#: Source/stores.cpp:1006\nmsgid \"What have you got?\"\nmsgstr \"Што маеш?\"\n\n#: Source/stores.cpp:1007 Source/stores.cpp:1010 Source/stores.cpp:1127\n#: Source/stores.cpp:1317\nmsgid \"Say goodbye\"\nmsgstr \"Развітацца\"\n\n#: Source/stores.cpp:1020\nmsgid \"I have this item for sale:\"\nmsgstr \"Прадаю вось гэту рэч:\"\n\n#: Source/stores.cpp:1042\nmsgid \"Leave\"\nmsgstr \"Сысці\"\n\n#: Source/stores.cpp:1065\nmsgid \"Healer's home\"\nmsgstr \"Дом лекара\"\n\n#: Source/stores.cpp:1067\nmsgid \"Talk to Pepin\"\nmsgstr \"Пагаварыць з Піпінам\"\n\n#: Source/stores.cpp:1069\nmsgid \"Leave Healer's home\"\nmsgstr \"Сысці з дома лекара\"\n\n#: Source/stores.cpp:1123\nmsgid \"The Town Elder\"\nmsgstr \"Гарадскі старэйшына\"\n\n#: Source/stores.cpp:1125\nmsgid \"Talk to Cain\"\nmsgstr \"Пагаварыць з Кейнам\"\n\n#: Source/stores.cpp:1126\nmsgid \"Identify an item\"\nmsgstr \"Выявіць рэч\"\n\n#: Source/stores.cpp:1219\nmsgid \"You have nothing to identify.\"\nmsgstr \"Няма чаго выяўляць.\"\n\n#: Source/stores.cpp:1230\nmsgid \"Identify which item?\"\nmsgstr \"Якую рэч выявіць?\"\n\n#: Source/stores.cpp:1247\nmsgid \"This item is:\"\nmsgstr \"Гэта рэч:\"\n\n#: Source/stores.cpp:1250\nmsgid \"Done\"\nmsgstr \"Гатова\"\n\n#: Source/stores.cpp:1259\nmsgid \"Talk to {:s}\"\nmsgstr \"Пагаварыць з {:s}\"\n\n#: Source/stores.cpp:1262\nmsgid \"Talking to {:s}\"\nmsgstr \"Гаворыць з {:s}\"\n\n#: Source/stores.cpp:1263\nmsgid \"is not available\"\nmsgstr \"недаступны\"\n\n#: Source/stores.cpp:1264\nmsgid \"in the shareware\"\nmsgstr \"ва ўмоўна-бясплатнай версіі\"\n\n#: Source/stores.cpp:1265\nmsgid \"version\"\nmsgstr \"версія\"\n\n#: Source/stores.cpp:1292\nmsgid \"Gossip\"\nmsgstr \"Пляткарыць\"\n\n#: Source/stores.cpp:1301\nmsgid \"Rising Sun\"\nmsgstr \"Узыходнае Сонца\"\n\n#: Source/stores.cpp:1303\nmsgid \"Talk to Ogden\"\nmsgstr \"Пагаварыць з Огдэнам\"\n\n#: Source/stores.cpp:1304\nmsgid \"Leave the tavern\"\nmsgstr \"Сысці з карчмы\"\n\n#: Source/stores.cpp:1315\nmsgid \"Talk to Gillian\"\nmsgstr \"Пагаварыць з Джыліен\"\n\n#: Source/stores.cpp:1316\nmsgid \"Access Storage\"\nmsgstr \"Адкрыць сховішча\"\n\n#: Source/stores.cpp:1326 Source/towners.cpp:205\nmsgid \"Farnham the Drunk\"\nmsgstr \"П'яніца Фарнам\"\n\n#: Source/stores.cpp:1328\nmsgid \"Talk to Farnham\"\nmsgstr \"Пагаварыць з Фарнамам\"\n\n#: Source/stores.cpp:1329\nmsgid \"Say Goodbye\"\nmsgstr \"Развітацца\"\n\n#: Source/stores.cpp:2458\nmsgid \"Your gold: {:s}\"\nmsgstr \"Ваша золата: {:s}\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:15\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" А-а, цікавішся нашым Каралём, гм? Трагічнае падзенне Леорыка было страшным \"\n\"ударам для гэтай зямлі. Людзі заўсёды любілі Караля, зараз жа яны да смерці \"\n\"страшацца яго. Я ўсё пытаю сябе, як ён так аддаліўся ад Святла, бо Леорык \"\n\"заўсёды быў з найсвяцейшых між людзьмі. Толькі самыя паганыя сілы Пекла \"\n\"маглі так вынішчыць чалавека знутры...\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:17\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Вёсцы патрэбна твая дапамога, добры чалавек! Колькі месяцаў таму Прынца \"\n\"Альбрэхта, Караля Леорыкава сына, скралі. Кароль раз'юшыўся і пачаў \"\n\"абшнарваць тут усюль, шукаючы дзіця. З кожным днём Леорык усё больш шалеў ад \"\n\"гора. Ён абвінаваціў ва ўсім нявінных гараджан і жорстка пакараў многіх \"\n\"смерцю. Менш паловы з нас вырабілася ад яго вар'яцтва...\\n\"\n\"Рыцары Караля і Святары стараліся яго супакоіць, але ён і на іх узбурыўся, \"\n\"і, на жаль, ім давялося забіць яго. На самым сконе ён страшна пракляў сваіх \"\n\"былых прыхільнікаў. Ён прысягнуў, што яны будуць служыць яму ў цемры \"\n\"вечна...\\n\"\n\"І тут пачалося такое, я ўжо думаў горш не можа быць! Былы Кароль прачнуўся \"\n\"ад вечнага сну, і цяпер у Лабірынце ўзначаліў легіён мярцоў. Яго цела \"\n\"пахавалі ў грабніцы на трэцім ўзроўні пад Саборам. Калі ласка, добры \"\n\"чалавек, сунімі яго душу, зніжчы яго праклятае аблічча...\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:19\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Як я і гаварыў, добры чалавек, Караля пахавалі на тры паверхі ўніз. Ён там, \"\n\"у агіднай цемры, толькі і чакае магчымасці знішчыць гэты край...\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden (Quest End)\n#: Source/textdat.cpp:21\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Праклён нашага Караля прайшоў, але баюся, што вінавата тут большае зло. \"\n\"Аднак мы яшчэ можам выратавацца ад цемры, што ахінае наш край: твая перамога \"\n\"– добры знак. Няхай Святло вядзе цябе, добры чалавек.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pepin\n#: Source/textdat.cpp:23\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Згуба сына давяла Караля. Я зрабіў усё, што мог, каб палегчыць яго \"\n\"шаленства, але нарэшце яно адолела яго. Чорны праклён навіс над каралеўствам \"\n\"з таго дня, але, можа, калі б яго дух вызвалілі ад яго зямной турмы, праклён \"\n\"бы адрабіўся...\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:25\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Не хачу думаць пра смерць Караля. Мне падабаецца ўспамінаць яго добрым і \"\n\"справядлівым, бо такім ён і быў. Яго смерць была такой сумнай, і \"\n\"няправільнай, чамусьці.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:27\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Я выкуў шмат зброі і большую частку даспехаў, якія Кароль Леорык даваў сваім \"\n\"рыцарам. Для яго я нават вымайстраваў вялізны двуручны меч з \"\n\"найдасканалейшаго мітрыля, як і баявую карону ў том жа духу. Дасюль не магу \"\n\"паверыць, што ён умёр, але гэто дакладно нейкая паганая воля звяла яго з \"\n\"розуму!\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:29\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Ды начхаць мне на гэта. Слухай, ніякі шкілет не будзе МАІМ каралём. Леорык – \"\n\"кароль. Кароль, чуеш? СЛАВА КАРАЛЮ!\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:31\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Мёртвыя, што ходзяць меж жывых, служаць праклятаму Каралю. Ён валодае сілаю, \"\n\"каб падняць у войска наўцоў яшчэ больш новых ваяроў. Калі не супыніш яго \"\n\"панаванне, ён дакладна пройдзе маршам па гэтай зямлі, забіваючы ўсіх, хто \"\n\"яшчэ тут жывы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:33\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Слухай, я тут справу вяду. Інфармацыяй я не гандлюю, і мне ўсё роўна на \"\n\"нейкага там Караля, каторы мёртвы дольш, чым я жывы. Калі ж табе трэба \"\n\"нешта, каб біцца з ім ці з мярцамі яго, от тут я табе памочнік..\"\n\n#. TRANSLATORS: Quest dialog spoken by The Skeleton King (Hostile)\n#: Source/textdat.cpp:35\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Цяпло жыцця ўвайшло ў мой склеп. Рыхтуйся, смертны, служыць майму Гаспадару \"\n\"век вечны!\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:37\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Бачу, і цябе бянтэжаць гэтыя дзіўныя паводзіны. Магу толькі здагадвацца, але \"\n\"раз многія дэманы баяцца сонечнага святла і вераць, што яно мае вялікую \"\n\"сілу, магчыма, яны палічылі, што ўзыходнае сонца на знаку таксама стрымлівае \"\n\"нейкую таемную сілу. Гм-м, мабыць, не такія яны і разумныя, як мы баяліся...\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:39\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Добры чалавек, я тут хацеў падзяліцца адным дзіўным досведам. Знаю, ты шмат \"\n\"ведаеш пра пачвар, што насяляюць лабірынт, і я тут ніяк не магу зразумець \"\n\"адну рэч... Я прачнуўся сярод ночы ад нейкага скрыгатання ля шынка. Я \"\n\"выглянуў са спальні, аж убачыў на дварэ карчмы абрысы нейкіх чарцят. \"\n\"Неўзабаве яны збеглі, але адно пасля таго, як скралі шыльду. Я не разумею, \"\n\"нашто дэманы ўкралі знак, але маю сям'ю не чапілі... дзіўна, праўда?\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden (Quest End)\n#: Source/textdat.cpp:41\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Вой, табе не абавязкова было вяртаць знак, хаця так цяпер не трэба новы \"\n\"рабіць, ці купляць. Ну, дай пагляну, чым ж я магу з табою разлічыцца? Гм-м-\"\n\"м, што тут у нас... Ага! Вось, гэту шапку пакінуў адзін чараўнік у нашых \"\n\"пакоях, ён нядаўна тут спыняўся. Можа табе будзе неяк карысна.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:43\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Бацюхны, дэманы бегаюць па вёсцы ўночы, рабуюць нашы дамы – хіба не \"\n\"засталося нічога святога? Спадзяюся, Огдэн з Гардаю ў парадку. Яны б, \"\n\"здаецца, прыйшлі, каб іх паранілі...\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:45\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Авохці! Дык вось куды знак прапаў? Мы з бабуляю відаць усё праспалі. Дзякуй \"\n\"Святлу гэтыя пачвары не напалі на карчму.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:47\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Кажаш, дэманы скралі Огдэнаў знак? Непадобно гэто да іхных лютасцяў, пра \"\n\"якія я чуў. Ці якія бачыў сам. \\n\"\n\" \\n\"\n\"Дэманам бы сэрца табе вырваць, а не знак.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:49\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Ведаеш, што я мяркую? Нехта сцягнуў той знак, і цяпер запросіць за яго кучу \"\n\"грашыскаў. Быў бы я Огдэнам... а я не Огдэн, але каб я быў... Я б проста \"\n\"купіў новы, з якім малюнкам прыгожым. Мо з чарачкаю элю, або кавалачкам \"\n\"сыру...\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:51\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Ніводзін смертны не можа дасканала ахапіць розум дэмана. \\n\"\n\" \\n\"\n\"Ніколі не давай іх цьмяным учынкам збіць цябе з тропу, бо гэта можа быць \"\n\"частка іх плана.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:53\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Што... ён кажа, гэта я ўзяў? Відаць, і Грызвальд на яго баку.\\n\"\n\"\\n\"\n\"Слухай, я ўжо некалькі месяцаў крадзяжом шыльдаў не займаюся. На кавалку \"\n\"дрэва не разжывешся.\"\n\n#. TRANSLATORS: Quest dialog spoken by Snotspill (Hostile)\n#: Source/textdat.cpp:55\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Гэй, гэта ты тут усіх б'еш! Нясі мне Магічны Сцяг, бо нападзём! З жыццём не \"\n\"пойдзеш! Забі вялікіх гадасцяў і вярні Магічнага. Прайдзі ля вугла і \"\n\"дзвярэй, знайдзі там гадасцяў. Аддасі, і хадзі!\"\n\n#. TRANSLATORS: Quest dialog spoken by Snotspill (Hostile)\n#: Source/textdat.cpp:57\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Гадасцяў забі, сцяг забяры. Прынясеш мне, а не то...\"\n\n#. TRANSLATORS: Quest dialog spoken by Snotspill (Hostile)\n#: Source/textdat.cpp:59\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"Дай! Так, добра! Ідзі, мы сільныя. Мы з вялікім Магічным усіх забіць!\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:61\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Нічога добрага гэта не вяшчуе – усё пацвярджае мае найзмрочнейшыя страхі. \"\n\"Хаця я адмаўляўся верыць старасвецкім легендам, цяпер я не магу. Прыйшла \"\n\"пара адкрыць, хто я такі.\\n\"\n\"\\n\"\n\"Маё спраўдная імя Дэкард Кейн Старэйшы, і я апошні нашчадак старасвецкага \"\n\"Брацтва, якое прысвяціла сябе ахове таямніц вечнага Зла. Зла, якое, цяпер \"\n\"ужо відавочна, вызвалілі.\\n\"\n\"\\n\"\n\"Архібіскуп Лазар, калісьці дарадчык Караля Леорыка, якому той давяраў як \"\n\"нікому, завёў натоўп простых гараджан у Лабірынт на пошукі сына Караля, \"\n\"Альбрэхта. Мінула шмат часу, калі яны вярнуліся, і жывымі выратавалася зусім \"\n\"мала.\\n\"\n\"\\n\"\n\"Бадай мяне, дурня! Я мусіў быў западозрыць скрыты падман. Гэта сам Лазар, \"\n\"мусіць, і скраў Альбрэхта, і хаваў яго з тае пары ў Лабірынце. Але я не \"\n\"разумею, чаму Архібіскуп звярнуўся да Цемры, ці якая яму карысць у дзіцяці. \"\n\"Хіба толькі дзеля таго, каб ахвяраваць яго Цёмным Валадарам!\\n\"\n\"\\n\"\n\"Вось у чым была яго задума! Ацалелыя з таго “гурту ратавальнікаў” казалі, \"\n\"што ў апошні раз, калі Лазара бачылі, ён збягаў у найглыбейшыя нетры \"\n\"Лабірынта. Ты мусіш спяшацца, выратуй Прынца ад ахвярнага нажа гэтага \"\n\"шалёнага ліхадзея!\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:63\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Спяшайся! Альбрэхта трэба выратаваць з рук Лазара. Прынц і люд каралеўства \"\n\"разлічваюць на цябе!\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:65\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Змрочная гісторыя твая, дружа мой. Лазар дакладна будзе гарэць у Пекле за \"\n\"свой жудасны ўчынак. З твайго апісання гэта быў не наш прынц, але я думаю, \"\n\"Альбрэхт яшчэ можа быць у бядзе. Сімвал сілы, які ты апісваеш, мусіць, \"\n\"партал у самае сэрца лабірынта.\\n\"\n\"Ведай жа, дружа мой: зло, на якое ты ідзеш, – Цёмны Пан Жаху. Смяротным \"\n\"людзям ён вядомы як Д’ябла. Гэта яго зняволілі у лабірынце многа вякоў таму, \"\n\"і я страшуся, што ён зноў жадае пасеяць хаос на зямлі чалавечай. Ты мусіш \"\n\"прайсці праз партал і знішчыць Д’ябла, покуль не позна!\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:67\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Лазар – гэта той Архібіскуп, каторы тады павёў многіх гараджан у лабірынт. У \"\n\"той дзень я страціў многа сяброў, а Лазар так і не вярнуўся. Мяркую, яго \"\n\"забілі, як і шмат каго яшчэ. Калі вам гэта не цяжар, прашу, зрабіце мне \"\n\"ласку, не гаварыце з Фарнамам пра той дзень.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:71\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Планы гараджан, калі я іх пачуў тае ночы, проста ашаламілі мяне. Я думаў, \"\n\"што ў Лазара-то будзе больш развагі. Ён быў Архібіскупам, і заўсёды \"\n\"падавалася, што ён вельмі любіў жыхароў Трыстрама. Столькі параненых, я не \"\n\"змог выратаваць усіх...\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:73\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Я помню Лазара вельмі добрым і велікадушным чалавекам. Ён гаварыў на \"\n\"пахаванні маёй мацеры, і заўсёды падтрымліваў маю бабулю і мяне у цяжкія \"\n\"часы. Я малюся кожны вечар, што ён неяк і дасюль жывы і здаровы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:75\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Я быў там, калі Лазар завёў нас у лабірынт. Гаварыў пра святое пакаранне, а \"\n\"як пачалася бойка з параджэннямі пекла, ён нат булавы свае не падняў на іх. \"\n\"Просто бег уніз, у цемрадзь, у бясконцыя пакоі лабірынта, поўныя служак \"\n\"цемры!\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:77\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Поруць, кусаюцца, ажно яны ўсе вакол цябе. Хлус! ХЛУС! Яны ўсе мёртвыя! \"\n\"Мёртвыя! Чуеш? Яны ўсё падаюць ды падаюць… кроў, іхняя кроў па ўсёй падлозе… \"\n\"усё яго віна…\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:79\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Я не ведала таго Лазара, пра якога ты гаворыш, але я адчуваю вялікі разлад у \"\n\"яго сутнасці. Ён уяўляе сабою страшную небяспеку, і ні перад чым не спыніцца \"\n\"ў службе сілам цемры, што назвалі яго сваім.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:81\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Ага, праведны Лазар, які ну та-а-ак ужо нам усім дапамог тады ўнізе. Назе \"\n\"маёй адно не дапамог, от бяда. Слухай, дам за так табе параду. Спытай \"\n\"Фарнама, ён быў там.\"\n\n#. TRANSLATORS: Quest dialog spoken by Lazarus (Hostile)\n#: Source/textdat.cpp:83\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Кінь сваё дурное пачынанне. Усё, што цябе чакае, толькі гнеў майго Валадара! \"\n\"Ужо запозна ратаваць дзіця. Скора ты далучышся да яго ў Пекле!\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:86\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Гм-м, не ведаю, што я мог бы расказаць табе, што магло б табе дамагчы. Вада \"\n\"ў нашым калодзежы плыве з падземнай крыніцы. Я чуў пра тунель, які вядзе да \"\n\"нейкага вяліка возера, магчыма, гэта адно яна і ёсць. На жаль, мне невядома, \"\n\"з якой прычыны наша вада забрудзілася.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:88\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Я заўсёды стараўся трымаць у склепе вялізны запас ежы і пітва, але без \"\n\"крыніцы свежай вады ва ўсім горадзе, наша сховішча скора зусім спустошыцца.\\n\"\n\"Калі ласка, зрабіце, што зможаце, інакш я не ведаю, што нам рабіць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:90\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Рады я заспеў цябе ў пару! У нас у калодзезе застаялася вада, уся \"\n\"саленаватая стала, нехта з гарадскіх нават захварэў, выпіўшы яе. Нашы запасы \"\n\"свежай вады хутка вычэрпваюцца. Здаецца, ёсць праход, які вядзе да крыніц, \"\n\"што жывяць наш горад. Адшукай, якая прычына гэтаму бедству, калі ласка, \"\n\"інакш мы ўсе дакладна згінем.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:92\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Прашу, спяшайся. З кожнай гадзінаю мы маем усё менш вады для піцця.\\n\"\n\"Без тваёй дапамогі мы доўга не пратрываем.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:94\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Што кажаш? Сама прысутнасць дэманаў — прычына забруджвання вады? Вой, пад \"\n\"нашым горадам сапраўды таіцца вялікае зло, але твая стойкасць і храбрасць \"\n\"даюць нам надзею. Калі ласка, вазьмі гэты пярсцёнак — магчыма, ён дапаможа \"\n\"табе ў знішчэнні гэтых пачвар.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:96\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Маёй бабулі вельмі няможацца, а Гарда сказала, што нам няможна піць \"\n\"калодзезя. Можаш неяк нам дапамагчы, калі ласка?\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:98\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Піпін праўду сказаў. Нам сільно будзе патрэбна свежая вада, дый скоро. \"\n\"Спрабаваў ачысціць адзін з калодзезяў, меншых, але там смуродзіць гэтай \"\n\"затхлай гадасцю. Мусіць на крыніцы забрудзілося.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:100\nmsgid \"You drink water?\"\nmsgstr \"Ты што, п'еш ваду?\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:101\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Жыхары Трыстрама памруць, калі не аднавіць падачу свежай вады ў іх \"\n\"калодзезі.\\n\"\n\"\\n\"\n\"Ведай жа: за гэтаю справаю стаяць дэманы, але ім не вядома, што яны \"\n\"спарадзілі.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:103\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Гэты раз я за цябе. Дзела стаіць, як той кажа, калі няма каму прадаваць. \"\n\"Лепш дазнайся, што там робіцца, і хутчэй!\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:105\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Кніга, у якой гаворыцца пра пакой з чалавечых касцей? Што ж, у некаторых \"\n\"старадаўніх тэкстах, якія я даследаваў у Бібліятэцы Усходу, згадваецца Пакой \"\n\"Касцей. У тых фаліянтах паведамлялася, што, калі Валадары Падзямелля \"\n\"зажадалі ахаваць свае вялікія скарбы, яны стваралі ўладанні, дзе тыя, хто \"\n\"паміраў, спрабуючы скрасці скарбы, назаўсёды звязваўся б з гэтым месцам і \"\n\"бараніў яго. Жахлівы канец, але дзіўна адпаведны?\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:107\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Баюся, што пра гэта я нічога не ведаю, добры чалавек. Кейн мае шмат кніг, \"\n\"можа яны дапамогуць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:109\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Гучыць як вельмі небяспечнае месца. Калі накіруецеся туды, прашу, будзьце \"\n\"вельмі асцярожны.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:111\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Баюся, нічога пра гэта я не чула. Можа Расказчык Кейн мог бы дапамагчы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:113\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Я пра гэто нічагуткі не ведаю, але мо Кейна спытай. Ён пра шмат чаго \"\n\"гамоніць, і мяне б не здзівіло, калі ён ведае адказ на тваё пытанне.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:115\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Так, слухай. Ёсць такі пакой дрэва, бач. А жонка ягоная, ну ведаеш – гэтая \"\n\"самая – кажа дрэву... не, ты пачакай. А я, кажу, яно яму бокам вылезе, але \"\n\"калі думаеш, што я буду ПЛАЦІЦЬ... ты... гэта... так.\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:117\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Ты станеш вечным слугою цёмных уладароў, калі загінеш у тым праклятым \"\n\"месцы.\\n\"\n\"На свой страх і рызыку ўваходзь у Пакой Касцей.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:119\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Вялізны, таямнічы скарб, кажаш? Мо мне і было б цікава заграбці з цябе рэч \"\n\"другую... О, а шчэ лепш, табе не трэба якіх рэдкіх і дарагіх прыпасаў, каб \"\n\"прайсці гэткае выпрабаванне?\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:121\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Здаецца так, што архібіскуп Лазар прымусіў шмат мясцовых спусціцца ў \"\n\"Лабірынт, каб адшукаць зніклага сына Караля. Ён зыграў на іх страхах, і \"\n\"загнаў іх напрасткі ў шалёны натоўп. Ніхто не быў гатовы да таго, што ляжыць \"\n\"пад халоднай зямлёю… Лазар пакінуў іх там, унізе – у кіпцюрах невымоўных \"\n\"жахаў – на смерць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:123\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Ну, Фарнам нешта мармытаў пра нейкае грамаднае стварэнне, якое арудавала \"\n\"ліхой зброяй. Здаецца, ён назваў яго мясніком.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:125\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"О, Святло! Я ведаю аб гэтым агідным дэмане. Сярод тых нешматлікіх ацалелых з \"\n\"паствы Лазара, хто выпаўз з-пад Храма, багата людзей мела сляды яго гневу на \"\n\"сабе. Не ведаю, чым ён калечыў сваіх ахвяр, але тое дакладна не з гэтага \"\n\"свету. Раны гнілі хваробаю, і нават мне падавалася, што загаіць іх \"\n\"немагчыма. Шануйся, калі думаеш біцца з гэтай бэстыяй…\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:127\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Калі Фарнам нешта казаў пра мясніка, які забівае людзей, я адразу не \"\n\"паверыла. Але раз і ты гэта ўзгадваеш, мабыць, гэта і праўда.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:129\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Я бачыў, што Фарнам назваў Мясніком, калі яно касіло сабе дарогу праз цяла \"\n\"маіх сяброў. Ён размахваў секачом з сакеру, сцінаючы рукі-ногі, столькі \"\n\"смельчакоў забіваючы на месцы. Мяне аддзяліло ад бітвы зборышчо крыклівых \"\n\"д’ябалят, і я нек выйшаў на сходы наверх. Больш я таго брыдкаго пачварня не \"\n\"бачыў, але ягоная крывавая морда і па гэты дзень у мяне перад вачыма.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham (*sad face*)\n#: Source/textdat.cpp:131\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Вялізны! Вялізны сякач – усіх маіх сяброў пазабіваў. Не даў рады спыніць, \"\n\"трэ было ўцякаць, не змог іх выратаваць. Прымкнула ў пакою, а там столькі \"\n\"целаў… столькі сяброў… НЕЕЕЕЕЕЕЕЕЕ!\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:133\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Мяснік – садысцкая істота, якая цешыцца болем і катаваннем людзей. Яго \"\n\"работу бачна ў п’яніцы Фарнаме. Знішчэнне яго дакладна забяспечыла б \"\n\"захаванасць гэтай вёскі.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:135\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Я аб гэтым страшэнным чорце ведаю больш, чым ты думаеш. Ягоныя дружакі мяне \"\n\"злавілі і нагу маю адабралі, да таго як Грызвальд выцягнуў мяне з той \"\n\"дзіры. \\n\"\n\"\\n\"\n\"Скажу проста – забі яго, і бі першым, а то ён дадасць твой труп у сваю \"\n\"калекцыю.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wounded Townsman (Dying)\n#: Source/textdat.cpp:137\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Прашу, выслухай мяне. Архібіскуп Лазар, ён нас завёў сюды каб адшукаць \"\n\"прынца зніклага. Сволач завёў нас у пастку! Цяпер усіх забіла… забіў іх \"\n\"дэман, ён яго назваў Мяснік. Адпомсці за нас! Знайдзі гэтага Мясніка ды забі \"\n\"яго, каб нашы душы знайшлі спакой…\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:140\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Цікавы верш ты цытуеш, стыль мне нешта нагадвае. Дай падумаць – як жа там \"\n\"было?\\n\"\n\" \\n\"\n\"…Цьма ахінае Схаванае. Вочы нябачныя свецяцца, чуваць адно, як коратка \"\n\"скрабуцца брытвы-кіпцюры, мучаючы бедныя душы аслепленых на век вечны. \"\n\"Цямніца для гэтых Праклятых завецца Залы Сляпых…\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:142\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Заўсёды быў нейкі абыякавы да паэзіі. Іншы раз даводзілася наймаць \"\n\"менестрэляў, калі справы ў карчме ішлі добра, але гэта быццам было так \"\n\"даўно.\\n\"\n\"\\n\"\n\"Што? А, так... гм, ну, думаю, можаш астатніх спытаць, што яны ведаюць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:144\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Гучыць праўда знаёма, чамусьці. Здаецца, прыпамінаю, што чытаў штосьці \"\n\"вельмі падобнае, калі вывучаў гісторыю дэманічных насланняў. Там казалася \"\n\"пра месца вялікага зла... пастой – ты ж не збіраешся ісці туды, праўда?\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:146\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Калі ў цябе пытанні пра слепату, пагавары з Піпінам. Я ведаю, што ён даў \"\n\"маёй бабулі зелле, што праясніла ёй зрок, можа ён і табе дапаможа.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:148\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Баюся я ні відам не відаў, ні слыхам не чуваў пра месцо, каб падыходзіло пад \"\n\"гэдакае жывое апісанне, дружа. Расказчык Кейн мог бы спамагчы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:150\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Ну глядзі... праўда смешна, га? Зразумела? Зала сляпых– глядзі?\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:152\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Тое месца вялікіх пакут і жахаў, таму яно і служыць добра сваім гаспадарам.\\n\"\n\"\\n\"\n\"Ступай асцярожна, або і ты затрымаешся там дольш, чым спадзяваешся.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:154\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Так, паглядзім, я табе нешта прадаю? Не. Ты мне даеш грошы, каб я пра гэта \"\n\"нешта расказаў? Не. Ты ідзеш адсюль і размаўляеш з расказчыкам, які і жыве \"\n\"для такога? Так.\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:156\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Гаворыш, Лакданан размаўляў з табою? Ён быў вялікім героем пры жыцці. \"\n\"Шляхетны і справядлівы чалавек, які шмат год служыў Каралю вераю і праўдаю. \"\n\"Але ты, канечне, ужо гэта ведаеш. \\n\"\n\"\\n\"\n\"З усіх, каго апанаваў праклён Караля, Лакданан як ніхто іншы не здаваўся б \"\n\"Цемры без бою, таму, мяркую, што твае словы – праўда. Будзь я на тваім \"\n\"месцы, дружа, я бы паспрабаваў знайсці спосаб адратаваць яго ад такой пакуты.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:158\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Ты пра храбрага воіна, які даўно памёр! Я не жадаю размоў пра згінулыя душы \"\n\"на маім двары, дзякуй вам вялікі.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:160\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Кажаш, залаты элікір. Ніколі не варыў зелляў такога колеру, таму не ведаю, \"\n\"які яно мела б эфект, выпі ты яго. Як твой лекар, вельмі раю зрабіць, як \"\n\"прасіў Лакданан, калі знойдзеш такі эліксір, і НЕ ПРАБУЙ яго піць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:162\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Ніколі не чула пра Лакданана. Выбачай, але я не думаю, што магу табе неяк \"\n\"дапамагчы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:164\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Калі гэта сапраўды быў Лакданан, я бы параіў табе дапамагчы яму. Я меў з ім \"\n\"справу некалькі разоў, і палічыў яго па прыродзе шчырым і верным чалавекам. \"\n\"Праклён, што ахінуў паслядоўнікаў Караля Леорыка, паў быў на яго асабліва \"\n\"цяжка.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:166\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Лакданан памёр. Гэта ўсе ведаюць, і ты мяне не абдурыш, што не памёр. З \"\n\"мёртвымі не пагаворыш. Я-то ведаю!\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:168\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Ты можаш сустрэць у Лабірынце тых, хто захрас там у пастцы, як Лакданан.\\n\"\n\"\\n\"\n\"Я адчуваю ў ім годнасць і вялікае пачуццё віны. Дапаможаш яму, і ты \"\n\"дапаможаш усяму Трыстраму.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:170\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Пастой, дай згану. Пад Кейнам разявілася агромная рышчыліна і яго туды \"\n\"зацягнула. Яго спапяліла ў шары пякельнага агню і ён больш не можа адказваць \"\n\"на твае пытанні. Як, не было такога? Ну, тады ты або купляеш нешта, або \"\n\"ідзеш сваёй дарогай.\"\n\n#. TRANSLATORS: Quest dialog spoken by Lachdanan (in despair)\n#: Source/textdat.cpp:172\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Прашу, не забівай, выслухай мяне! Я быў Капітанам Рыцараў Караля Леорыка, \"\n\"падтрымліваў законы гэтай зямлі з чэсцю і справядлівасцю. Але потым яго \"\n\"цёмны Праклён паў на нас, за ролю, што мы сыгрылі ў яго трагічнай смерці. \"\n\"Пакуль мае сабраты скарыліся свайму страшнаму лёсу, я збег з усыпальні \"\n\"Караля, шукаючы, як збавіцца ад Праклёну. Аднак я не даў рады...\\n\"\n\"\\n\"\n\"Я чуў пра Залаты Эліксір, што мог бы адрабіць Праклён і дараваць маёй душы \"\n\"спакой, але не змог знайсці яго. Мая сіла цяпер згасае, і разам з ёю астаткі \"\n\"маёй чалавечнасці. Прашу, дапамажы мне, знайдзі Эліксір. Я адплачу табе за \"\n\"намаганні — клянуся сваёю чэсцю.\"\n\n#. TRANSLATORS: Quest dialog spoken by Lachdanan (in despair)\n#: Source/textdat.cpp:174\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Залаты Эліксір не знайшоўся. Страшуся, я на векі вякоў пракляты. Прашу, \"\n\"пашукай яшчэ...\"\n\n#. TRANSLATORS: Quest dialog spoken by Lachdanan (Quest End)\n#: Source/textdat.cpp:176\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Табою выратавана мая душа ад пракляцця, і за гэта я табе абавязаны. Калі \"\n\"ёсць спосаб разлічыцца з табою з таго свету, я знайду яго, а пакуль — вазьмі \"\n\"мой шалом. У падарожжы, у якое я адпраўляюся, мне ён не будзе надта карысны. \"\n\"Няхай ён ахоўвае цябе ад цёмных сіл унізе. Ідзі са Святлом, друг мой...\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:178\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Грызвальд гаворыць пра Кавадла Ярасці, легендарны артэфакт, які доўга \"\n\"шукалі, але так не знайшлі. Яно выраблена з касцей дэманаў з Лязовай Ямы, і \"\n\"выплаўлялі яго побач чэрапаў пяцярых наймацнейшых магаў падземнага свету. На \"\n\"ім высячаны руны сілы і хаосу, а любая зброя ці браня, выкутая на гэтым \"\n\"Кавадле, паглынецца царствам Хаосу, якое ўкараніць у рэчы магічныя \"\n\"ўласцівасці. Казалі, праз непрадказальную прыроду хаосу цяжка ведаць \"\n\"дакладна, які будзе вынік такой коўкі…\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:180\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Не думаеш, што было б лепш спытаць пра гэта Грызвальда? Ён да таго зручны, \"\n\"знаеш.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:182\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Калі б табе былі патрэбны звесткі пра Таўкачык Гаення ці пра Срэбны Келіх \"\n\"Ачышчэння, я мог бы дапамагчы табе, друг мой. Аднак, у гэтай справе было б \"\n\"карысней пагаварыць з Грызвальдам ці з Кейнам.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:184\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Грызвальдаў бацька бывала расказваў нам малым пра вялізнае кавадла, на якім \"\n\"рабілі магутную зброю. Ён казаў, што калі молат біў па тым кавадле, зямля аж \"\n\"трэслася шалёна. Калі трасецца зямля, я заўсёды гэта ўспамінаю.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:186\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Вітаю! Заўсёды рады бачыць аднаго са сваіх найлепшых пакупнікоў! Я ведаю, ты \"\n\"часто ходзіш глыбоко ў Лабірынт, а мне якраз нешто расказалі, што можа табе \"\n\"паказацца вартым часу...\\n\"\n\"\\n\"\n\"Адзін чалавек, які вярнуўся з Лабірынта, гаварыў, што, калі ўцякаў, знайшоў \"\n\"нейкае таямнічае кавадло. Яго апісанне нагадало мне легенды, якія я чуў шчэ \"\n\"юнаком, пра Пякельную Кузню, дзе куюць чарадзейную, моцную зброю. Па \"\n\"легендзе ў глыбіні Пякельнай Кузні стаяло Кавадло Ярасці! Гэтае Кавадло \"\n\"змяшчало ў сабе самую існасць падземнаго свету...\\n\"\n\"\\n\"\n\"Кажуць, любая зброя выкутая на пякельным Кавадле насычана вялікай сілаю. \"\n\"Калі гэто дапраўды Кавадло Ярасці, я змагу выкаваць такую зброю, што і \"\n\"самаго найцямнейшаго ўладара Пекла змагла б паразіць!\\n\"\n\"\\n\"\n\"Знайдзі Кавадло, і я вазьмуся за працу!\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:188\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Покуль нічого, так? Ну, шукай. Зброя, выкутая на гэтым Кавадле была б \"\n\"найлепшай надзеяю, і я пэўны я змог бы вырабіць для цябе нешто сапраўды \"\n\"вялікае.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:190\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Не магу паверыць! Кавадло Ярасці — малайчына, сябра. Цяпер-то мы ім пакажам, \"\n\"падлюгам, што няма ў Пякле зброі смяротнейшай, ніж той, што зрабіў чалавек! \"\n\"Трымай, і няхай Святло бароніць цябе.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:192\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Грызвальд не прадасць свайго кавадла. Што ён тады будзе рабіць? І я б \"\n\"таксама злаваў, каб нехта скраў маё кавадла!\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:194\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Унутры Лабірынта ёсць шмат артэфактаў, што маюць сілу па-за межамі разумення \"\n\"смертных. Некаторыя з іх маюць сілу, якую могуць карыстаць як Святло, так і \"\n\"Цемра. Дастаць адтуль Кавадла было б кідком на шалю Святла ў Вайне Гневу.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:196\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Калі знойдзеш Грызвальду гэты артэфакт, гэта моцна ўдарыць па паім дзеле. \"\n\"Ай, ты яго ніколі не знойдзеш.\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:198\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Вароты Крыві і Залі Агню — месцы таямнічага паходжання. Дзе б табе не \"\n\"трапілася гэтая кніга, месца, дзе яна захоўваецца, дакладна вялікай сілы.\\n\"\n\"\\n\"\n\"Легенды гавораць аб п'едэстале, высечаным з абсідыянавага каменя, а наверсе \"\n\"яго паверхні, убранай касцьмі, знаходзіцца басейн кіпучай крыві. Таксама \"\n\"намякаецца аб Камянях Крыві, якія адкрыюць дзверы, што ахоўваюць нейкі \"\n\"старасвецкі скарб...\\n\"\n\"\\n\"\n\"Прырода таго скарба ахутана загадкамі, дружа мой, але сказана, што \"\n\"старадаўні герой Аркейн пакінуў святыя даспехі Адвагі ў патаемным скляпенні. \"\n\"Аркейн быў першы смертны, што змяніў ход вайны Граху, прагнаўшы легіёны \"\n\"цемры аж да самых Агністых Пекел.\\n\"\n\"\\n\"\n\"Акурат перад яго смерцю, даспехі Аркейна схавалі ў патаемным скляпенні. \"\n\"Сказана, што калі святыя даспехі зноў будуць у патрэбе, паўстане іншы герой, \"\n\"які апране Адвагу. Магчыма, ты і ёсць той герой...\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:200\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Усякае дзіця ведае пра воіна Аркейна і яго таямнічыя даспехі, якія завуцца \"\n\"Адвага. Калі знойдзеш, дзе яно захоўваецца, атрымаеш добрую абарону ад зла ў \"\n\"Лабірынце.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:202\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Гм-м... гучыць як нешта, што я б ведаў, але я так доўга вывучаў новыя лекі \"\n\"ды паляпшаў эліксіры, што я, мусіць, забыў. Выбачай...\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:204\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Раней я часта чула пра чароўныя даспехі, якія завуць Адвагай, пра такое \"\n\"раней гаманілі хлопцы. Лепш мужыкоў папытай па вёсцы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:206\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Даспехі пад назвай Адвага могуць схіліць шалі на твой бок. Скажу, што многія \"\n\"іх шукалі — у тым ліку і я. Аркейн добра іх схаваў, сябру, і аднае ўдачы тут \"\n\"не хопіць, каб раскрыць сакрэты, якія хавалі іх, ух, столькі многа гадоў.\"\n\n#. TRANSLATORS: Quest dialog \"spoken\" by Farnham\n#: Source/textdat.cpp:208\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Хр-р-р-р-р-р-р-р-р-р-р-р-р-р-р-р...\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:209\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Знойдзеш гэтыя Камяні Крыві, абыходзься з імі асцярожна.\\n\"\n\"\\n\"\n\"Шлях таіць у сябе небяспеку, і ёсць толькі адна надзея — у табе.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:211\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Думаеш знайсці даспехі пад назвай Адвага?\\n\"\n\"\\n\"\n\"Ніхто так і не адшукаў, дзе там Аркейн іх схаваў, і раз мае сувязі не далі \"\n\"рады, нешта я сумняваюся, што ты калі-небудзь дасі.\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:213\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Я ведаю толькі адну легенду, якая апавядае пра такога воіна, якога ты \"\n\"апісваеш. Яго гісторыя сустракаецца ў старадаўніх хроніках вайны Граху...\\n\"\n\"\\n\"\n\"Заплямлены тысяччу год вайны, крыві і смерці, Крывавы ваявода стаў на гары \"\n\"сваіх падраных ахвяр.\\n\"\n\" \\n\"\n\"Таксама пісалася, што ён быў калісьці смертны, і біўся супраць Легіёна Цемры \"\n\"ў Вайне Граху, але ён страціў сваёй чалавечнасць з-за няўтольнай прагі да \"\n\"крыві.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:215\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Баюся, нічога пра такога ліхога воіна я не чуў, добры чалавек. Я \"\n\"спадзяваюся, табе не спатрэбіцца біцца з ім, бо здаецца ён вельмі небяспечны.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:217\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Кейн мог бы расказаць табе пра такое значна больш, чым я б калі-небудзь \"\n\"хацеў ведаць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:219\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Калі табе прыйдзецца біцца з такім лютым ворагам, няхай Святло будзе табе \"\n\"спадарожнікам і ахоўцам. Я буду думаць пра цябе.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:221\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Цёмныя і страшныя легенды ахінаюць Крывавага Ваяводу таго. Добра \"\n\"падрыхтуйся, сябру, бо ён не пакажа ані літасці.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:223\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Вечна ты пра Кроў. А як жа кветкі там, сонейка, або красуня тая, што выпіўку \"\n\"носіць. Слухай, друг, ты проста апантаны, табе не гаварылі?\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:225\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Яго ўмельства са зброяю жахлівае, і ён пражыў цэлыя тысячы год, ведаючы адно \"\n\"вайну. Прабач мне... Я не бачу, ці пераможаш ты яго.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:227\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Ніколі не меў спраў з гэтым Ваяводам, але відаць ён пераводзіць шмат мячоў. \"\n\"Забяспечваць яго было б ідэяй...\"\n\n#. TRANSLATORS: Quest dialog spoken by Warlord of Blood (Hostile)\n#: Source/textdat.cpp:229\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Мой клінок пяе тваёй крыві, смертны, і клянуся сваімі гаспадарамі, яго не \"\n\"спыняць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:231\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Грызвальд гаворыць пра Нябёсны Камень. Яго меліся адвезці на Усход вучоным, \"\n\"каб лепш даследаваць. Камень ззяў Энергіяю, якая нейкім чынам абдорвала \"\n\"зрокам, які звычайнаму чалавеку недаступны. Не ведаю, якія сакрэты ён тоіць, \"\n\"дружа мой, але знайсці гэты камень дорага б каштавала.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:233\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Той караван тут спыняўся купіць прыпасаў на дарогу на Усход. Я прадаў ім \"\n\"багата фруктаў і прыўдалага мяса, якое Гарда толькі напякла. Шкада, што ўсё \"\n\"так адбылося…\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:235\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Не ведаю, што яны там хацелі ўбачыць з гэтым каменем, але я вось што скажу. \"\n\"Калі з неба падаюць камяні, лепш быць асцярожным!\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian\n#: Source/textdat.cpp:237\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Ну, тут праўда спыняўся караван з нейкімі надта важнымі людзьмі, але гэта \"\n\"ўжо даволі даўно было. Вымова ў іх была дзіўная. Калі нічога не блытаю, яны \"\n\"пачыналі доўгае падарожжа.\\n\"\n\"\\n\"\n\"Не ўяўляю, як ты зможаш знайсці хоць штосьці з паклажы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:239\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"А пастаі хвілінку, маю тут адну рэч, мо цябе зацікавіць. Тут нядаўна караван \"\n\"праязджаў, які кіраваўся на ўсходнія каралеўствы. Везлі там нібыто кавалак \"\n\"неба, што ўпаў на зямлю! Караван трапіў у засаду нейкіх вершнікаў у плашчах, \"\n\"на поўнач па дарозе адсюль. Я абшукаў там абломкі, але каменя і след \"\n\"прастыў. Калі ён табе знойдзецца, думаю я б змог нешто карыснае з яго \"\n\"зладзіць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:241\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Я ўсё яшчэ чакаю, ці прынясеш ты мне таго каменя з нябёсаў. Я ведаю, што \"\n\"змагу зладзіць з яго нешто моцнае.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold(Quest End)\n#: Source/textdat.cpp:243\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Дай глянуць — але... але, так я і думаў. Дай хвілінку...\\n\"\n\"\\n\"\n\"Ну вось, трымай. Я ўладзіў кавалкі каменя ў сярэбраным пярсцёнку, які мне \"\n\"дай мой бацько. Буду спадзявацца, яно стане табе ў прыгодзе.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:245\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Быў у мяне некалі пярсцёнак. Даражэзны, з блакітным на ім, і зялёным, і \"\n\"чырвоным, і серабром. Не памятаю, што з ім сталася, праўда. Моцна па ім \"\n\"сумую...\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:247\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Нябёсны камень магутны, і калі б цябе прасіў яго знайсці хто-небудзь, апроч \"\n\"Грызвальда, я бы не дазволіла таго. Ён пакорыць яго сілу, і камень будзе \"\n\"ўжыты на карысць усім нам.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:249\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Калі нехта можа нешта зрабіць з таго каменя, дык гэта Грызвальд. Ён знае, \"\n\"што робіць, хоць я і сцягваю ў яго пакупнікоў, якасць яго працы я паважаю.\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain\n#: Source/textdat.cpp:251\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Ведзьма Эйдрыя шукае чорны грыб? Пра такое я магу сказаць не больш, чым пра \"\n\"селядзец. Мабыць, Піпін ведае больш, але гэта нешта такое, чаго ў маіх \"\n\"кнігах і байках не знойдзеш.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden\n#: Source/textdat.cpp:253\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Вось што я табе скажу. Ні Гарда, ні я, ніколі, ніколі б не падалі сваім \"\n\"шаноўным гасцям чорных грыбоў. Калі Эйдрыі хочацца сабе ў поліўку грыбоў, яе \"\n\"дзела, але я табе тут не памочнік. Чорныя грыбы… тфу!\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin\n#: Source/textdat.cpp:255\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Ведзьма казала, ты шукаеш мозг дэмана, каб дамагчы мне зварыць эліксір. Ён \"\n\"будзе вельмі каштоўны для ўсіх, каго паранілі гэтыя вычварні, мне бы толькі \"\n\"разгадаць сакрэт, што тоіць яго састаў. Дастанеш мозг з забітага дэмана, я \"\n\"буду вельмі ўдзячны, калі прынясеш яго мне.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pepin\n#: Source/textdat.cpp:257\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Выдатна, гэта я і ўяўляў. Я змог даварыць эліксір і без гэтага, але мець \"\n\"такое для доследу лішнім не будзе. Калі ласка, аднясеш вось гэта ведзьме? \"\n\"Думаю, яна якраз чакае.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:259\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"Думаю, Огдэн захаваў крыху грыбоў у склепенні. Можа яго спытай?\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold\n#: Source/textdat.cpp:261\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Калі і Эйдрыя не мае такіх, мусіць, і праўда рэдкая рэч. Наўрад ці магу яшчэ \"\n\"як спамагчы, але са слоў тваіх гэто… ну, здаровы такі, велізарны, уздуты, \"\n\"азызлы грыб! Ну, добраго палявання, мусіць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham\n#: Source/textdat.cpp:263\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Огдэн гоніць ФАЙНЫ “чорны грыб”, хаця мяне ірве калі вып’ю такога. Слухай, \"\n\"слухай… Вось у чым сакрэт – ТРЭБА ВЕДАЦЬ МЕРУ!\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:265\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Што гэта тут у нас? Цікава. З віду гэта Кніга Рэагентаў. Усюды пільна шукай \"\n\"Чорны Грыб. Ён даволі вялікі, не памылішся. Калі знойдзеш, ці не прынясеш \"\n\"мне, гм?\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:267\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Мне патрэбны вялікі чорны грыб. Давай, бяжы, прынясеш мне такі, і я дадам \"\n\"яго ў асаблівае зелле, з якім зараз работаю.\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:269\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Так. Дасканала для майго адвару будзе. Дарэчы, лекар шукаў мозг якогасьці \"\n\"дэмана, каб лячыць людзей, якіх заразілі атрутным ядам. Думаю, ён маецца \"\n\"зрабіць эліксір. Калі дапаможаш яму знайсці, што яму трэба, калі ласка, \"\n\"прынясі мне трохі гэтага эліксіру на пробу.\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria\n#: Source/textdat.cpp:271\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Навошта ты яго сюды нясеш? Гэты раз мне дэманаў мозг без патрэбы. Хаця мне \"\n\"патрэбна трохі эліксіра, які лекар цяпер варыць. Лепш аднясі гэты гратэскны \"\n\"орган яму, а мне потым прынясеш эліксіру. Праўда проста, калі трохі \"\n\"падумаць, гм?\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria (Quest End)\n#: Source/textdat.cpp:273\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Чаго? Цяпер-то ты мне нясеш эліксір лекара? Я ўжо скончыла адвар і без яго. \"\n\"Саба пакінь...\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt\n#: Source/textdat.cpp:275\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Я не прадаю грыбы, любых колераў і памераў. Можа табе лепш чаго больш \"\n\"карыснага?\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain (currently unused)\n#: Source/textdat.cpp:277\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Значыць, легедная ад Мапе праўдзівая. Нават я ніколі да канца не верыў! \"\n\"Здаецца, мне пара расказаць табе, хто я сапраўды такі, дружа мой. Бач, я не \"\n\"зусім той, кім падаюся...\\n\"\n\" \\n\"\n\"Маё сапраўднае імя Дэкард Кейн Старэйшы, і я апошні нашчадак старасвецкага \"\n\"Брацтва, якое прысвяціла сябе ахове і нагляду таямніц вечнага Зла. Зла, \"\n\"якое, цяпер ужо відавочна, вызвалілі...\\n\"\n\"\\n\"\n\"Зло, супраць якога ты рушыш, — цёмны Пах Жаху, смертным людзям вядомы як \"\n\"Д'ябла. Гэта яго паланілі ў Лабірынце многія стагоддзі таму. Мапа ў тваіх \"\n\"руках была створана даўным даўно, каб адзначыць час, калі Д'ябла зноў \"\n\"паўстане са свайго палону. Калі дзве зоркі з гэтай мапы зыдуцца, Д'ябла \"\n\"сягне вышыні сваёй сілы. Ён стане амаль неадольны!\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain (currently unused)\n#: Source/textdat.cpp:279\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Наш час канчаецца! Я адчуваю, як яго цёмная сіла збіраецца, і толькі ты \"\n\"можаш не даць яму дасягнуць усяе яго магутнасці.\"\n\n#. TRANSLATORS: Quest dialog spoken by Cain (currently unused)\n#: Source/textdat.cpp:281\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Я ўпэўнены, большага ў цябе нельга прасіць, але я страшуся нават тваёй сілы \"\n\"будзе не дастаткова. Д'ябла цяпер дасягнуў вышыні сваёй сілы, і табе \"\n\"спатрэбіцца ўся твая смеласьці і моц, каб перамагчы яго. Няхай Святло будзе \"\n\"тваім правадніком і абаронцам, дружа мой. Я дапамагу чым толькі змагу.\"\n\n#. TRANSLATORS: Quest dialog spoken by Ogden (currently unused)\n#: Source/textdat.cpp:283\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Раз ведзьма не дапамагла і кажа ісці да Кейна, чаго ты думаеш, што я нешта \"\n\"ведаю? Відаць вельмі важная справа. Спяшацца бы табе да расказчыка, як \"\n\"Эйдрыя і гаворыць.\"\n\n#. TRANSLATORS: Quest dialog spoken by Pipin (currently unused)\n#: Source/textdat.cpp:285\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Я не надта разумею напісанае, але можа Эйдрыя ці Кейн могуць дапамагчы \"\n\"расшыфраваць, пра што тут.\\n\"\n\" \\n\"\n\"Я бачу, што гэта мапа зорнага неба, але больш за тое ўжо па-за мамі \"\n\"талентамі.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gillian (currently unused)\n#: Source/textdat.cpp:287\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Найлепш спытаць аб гэтым нашага Расказчыка. \\n\"\n\" \\n\"\n\"Кейн вельмі добра знаецца на старажытным пісьме, а гэта лёгка можа быць \"\n\"найстарэшай паперкай, якую я бачыла.\"\n\n#. TRANSLATORS: Quest dialog spoken by Griswold (currently unused)\n#: Source/textdat.cpp:289\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Ніколі такой мапы не бачыў. Скуль яна? Хоць і не ведаю, як яе разумець, Кейн \"\n\"або Эйдрыя можа і дадуць табе патрэбныя адказы.\"\n\n#. TRANSLATORS: Quest dialog spoken by Farnham (currently unused)\n#: Source/textdat.cpp:291\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Слухай сюды, бліжэй стань. Не ведаю, ці ты ведаеш, што я ведаю, але тут у \"\n\"цябе сапраўды штосьці. Гэта мапа.\"\n\n#. TRANSLATORS: Quest dialog spoken by Adria (currently unused)\n#: Source/textdat.cpp:293\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Авохці, нічога добрага гэта не вяшчуе. Мапа зорнага неба, яна прадракае \"\n\"вялікую бяду, але яе сакрэты не мае. Таму прыйшла пара табе вельмі сур'ёзна \"\n\"пагаварыць з Расказчыкам.\"\n\n#. TRANSLATORS: Quest dialog spoken by Wirt (currently unused)\n#: Source/textdat.cpp:295\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Мапу я шукаў, але дакладна не такую. Эйдрыі пакажы. Напэўна аб'ясніць, што \"\n\"гэта. Скажу адно што з віду старая, а старая — значыць дарагая.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gharbad the Weak\n#: Source/textdat.cpp:297\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Калі лааааска, не бі. Не забі. Пакіні ў жывых, наступны раз нясці табе \"\n\"харошае.\"\n\n#. TRANSLATORS: Quest dialog spoken by Gharbad the Weak\n#: Source/textdat.cpp:299\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Нешта раблю для цябе. Не забівай Гарбада, калі ласка. Жыць і даць харошае.\\n\"\n\"\\n\"\n\"На, доказ, што праўду гавару...\"\n\n#. TRANSLATORS: Quest dialog spoken by Gharbad the Weak\n#: Source/textdat.cpp:301\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Яшчэ нічога! Амаль гатова.\\n\"\n\"\\n\"\n\"Вельмі моцнае, вельмі сільнае. Жыць! Жыць!\\n\"\n\"\\n\"\n\"Болю не будзе і абяцананне выканаю!\"\n\n#. TRANSLATORS: Quest dialog spoken by Gharbad the Weak (Hostile)\n#: Source/textdat.cpp:303\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Для цябе занадта харошае. Вельмі моцнае! Ты хацець — ты забіраць!\"\n\n#. TRANSLATORS: Quest dialog spoken by Zhar the Mad (annoyed / Hostile)\n#: Source/textdat.cpp:305\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Што?! Ты тут чаго? Так і здурнець можна калі столькі перыпыняюць. На, бяры і \"\n\"дай мне працаваць. Не дакучай мне больш!\"\n\n#. TRANSLATORS: Quest dialog spoken by Zhar the Mad (Hostile)\n#: Source/textdat.cpp:307\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"А-а-ай! Твая цікаўнасць стане табе смерцю!!!\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain\n#: Source/textdat.cpp:308\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Прывет, дружа мой. Пастой крыху ды паслухай...\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:309\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"На сваім шляху ўглыб Лабірынта ты можаш знайсці кнігі, якія таяць вялікія \"\n\"веды. \\n\"\n\"\\n\"\n\"Уважліва іх чытай, бо яны табе раскажуць такое, чаго і я нават не змог бы.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:311\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Пакуль ты вандруеш па Лабірынце, ў цябе могуць паўстаць пытанні, адказы на \"\n\"якія могуць таіць міфы і легенды якія я ведаю. Калі сутыкнешся з нейкім \"\n\"такім пытаннем і зацікавішся ім, адшукай мяне, ды я раскажу, пра што змагу.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:313\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Грызвальд — чалавек вельмі руплівы і смелы. Я ўпэўнены, ён ніколі не \"\n\"расказваў табе, як выратаваў Вірта з Лабірынта, так жа? Ён добра ведае, якая \"\n\"вялікая небяспека тоіцца там, як і ты. Ён умелы майстар, таму калі ён \"\n\"сцвярджае, што ва ўсім табе можа дапамагчы, можаш не сумнявацца ў яго \"\n\"сумленнасці ды, ўмельстве.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:315\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Огдэн ужо чатыры гады карчмарыць ва Узыходным Сонцы. Ён выкупіў яго ўсяго за \"\n\"пару месяцаў да таго, як тут усё пакацілася к чорту. Яму і жонцы яго Гардзе \"\n\"не хапае грошай, каб з'ехаць адсюль, бо ўсё патрацілі, каб тут асесці. Ён \"\n\"добры чалавек, з моцным пачуццём адказнасці.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:317\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Небарака Фарнам. Неспакойны напамін аб загубленай суполцы, што ступіла ў \"\n\"Храм за Лазарам тым змрочным днём. Ён збег адтуль жывым, але храбрасць сваю, \"\n\"як і частку здаровага розуму, пакінуў у якойсьці чорнай яме. Цяпер ён \"\n\"знаходзіць суцяшэнне толькі на дне свайго куфля, але ў плыні яго бясконцай \"\n\"балбатні схаваны крупінкі праўды.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:319\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Тая ведзьма, Эйдрыя, — як анамалія тут у Трыстраме. Яна прыбыла якраз калі \"\n\"апаганілі Храм, пакуль усе вакол з’язджалі адсюль. Яна збудавала хату на \"\n\"ўскраіне горада, відаць, ноччу, і мае доступ да многіх дзіўных і таемных \"\n\"артэфактаў і кніг з ведамі, якія нават я ніколі не бачыў.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:321\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Гісторыя Вірта жахлівая і трагічная. Гадкія дэманяты з коп’ямі вырвалі яго з \"\n\"рук яго мацеры і сцягнулі ў лабірынт. Многа дзяцей забралі ў той дзень, \"\n\"уключаючы сына Караля. Рыцары палаца спускаліся туды, але ніхто не вярнуўся. \"\n\"Наш каваль знайшоў хлопчыка, але ўжо пасля таго, як яны пачалі яго катаваць \"\n\"дзеля сваёй садысцкай асалоды.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:323\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"А, Піпін. Я лічу яго сапраўдным сябром, магчыма, бліжэйшага і не маю. Ён \"\n\"часам трохі збянтэжаны, але не нарадзілася яшчэ душа клапатлівейшая ці \"\n\"чуллівейшая. Мала з кім можна параўнаць яго веды і ўменне, а дзверы яго \"\n\"заўсёды адчыненыя.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Cain (Gossip)\n#: Source/textdat.cpp:325\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Джыліен добрая жанчына. Яе любяць за вясёлы нораў і смяшлівасць, і яна \"\n\"занімае асобнае месца ў маім сэрцы. Яна засталася ў карчме, каб даглядаць \"\n\"сваю пажылую бабулю, хвароба не дае ёй ехаць. Падчас я баюся за яе, але \"\n\"ведаю, што ўсякі ў вёсцы хутчэй бы сам памёр, чым даў бы яе ў крыўду.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden\n#: Source/textdat.cpp:327\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Дабрыдзень, добры чалавек. Вітаю ў карчме Узыходнага Сонца!\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:329\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Шмат прайдзісветаў удастоілі сталы маёй карчмы, а аповесцяў за імі расказалі \"\n\"ў дзесяць разоў больш пад столькі ж эля. Адзіная рэч, у якой яны ўсе \"\n\"сыходзіліся, была адна старая аксіёма. Можа яна табе дапаможа. Плоць можна \"\n\"разрэзаць, але мусіш разбіць косць.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:331\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Каваль Грызвальд надзвычай дасведчаны ў зброі і брані. Калі табе як-небудзь \"\n\"спатрэбіцца апрацаваць свой рыштунак, табе дакладна да яго.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:333\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Фарнам тут зашмат часу бавіць, топіць сваё гора ў танным элю. Я б праганяў \"\n\"яго, але ж тады ў Лабірынце ён і праўда многа выпакутаваў.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:335\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Эйдрыя мудрая не па гадах, але мушу прызнацца — яна мяне трохі пужае.\\n\"\n\"\\n\"\n\"Ну і няважна. Калі табе спатрэбяцца якія чараўнічыя рэчы, яе хата за ракою, \"\n\"з вельмі дзіўна багатым выбарам тавараў.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:337\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Калі хочаш больш знаць пра гісторыю нашай вёсці, расказчык Кейн ведае даволі \"\n\"многа пра мінульшчыну.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:339\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Вірт — маленькі жулік і нягоднік. Ён заўсёды трапляў у бяду, няма дзіва, што \"\n\"з ім такое здарылася.\\n\"\n\"\\n\"\n\"Відаць залез падурэць куды нельга было. Мне шкада яго, праўда, але тых, з \"\n\"кім ён водзіцца, я не трываю.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:341\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Піпін — добры чалавек, і дакладна самы велікадушны ў вёсцы. Ён заўсёды дбае \"\n\"пра патрэбы другіх, але нейкая бяда быццам і праўда следам за ім ідзе, куды \"\n\"б ён ні ішоў...\"\n\n#. TRANSLATORS: Neutral dialog spoken by Ogden (Gossip)\n#: Source/textdat.cpp:343\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Джыліен, барменка мая? Каб не пачуццё абавязку перад сваёй бабуляй, яна б \"\n\"даўно адсюль уцякла.\\n\"\n\"\\n\"\n\"Неба — сведка, маліў яе з'ехаць адсюль, казаў, маўляў, пагляджу старую, але \"\n\"яна занадта ўжо добрая і клапатлівая, каб так зрабіць.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin\n#: Source/textdat.cpp:345\nmsgid \"What ails you, my friend?\"\nmsgstr \"Што вам далягае, дружа мой?\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:346\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Я вынайшаў адну надта цікавую рэч. У адрозненні ад нас, істоты ў Лабірынце \"\n\"могуць гаіць свае раны без чужога ўмяшання ці магіі. Калі раніш пачвару, \"\n\"упэўніся, што яна мёртая, іначай яна лёгка адновіцца.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:348\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Да таго як Храм захапілі гэтыя, ну, хто там цяпер тоіцца, гэта было выдатнае \"\n\"месца для адукацыі. Там можна знайсці багата кніг. Усё што знойдзеш, чытай, \"\n\"бо з некаторых з іх можаш дазнацца аб тым, як устроены Лабірынт.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:350\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Грызвальд знаецца на ваенным дзеле так жа, як я на дзеле лячэбным. \"\n\"Праніклівы ён гандляр, але ж работа яго нікому не ўступае. Ой, мабыць гэта \"\n\"таму, што ён адзіны каваль, які тут застаўся.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:352\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Кейн – сапраўдны сябар і вялікі мудрэц. Ён трымае вялізную бібліятэку і ад \"\n\"прыроды здольны распазнаць існую натуру многіх рэчаў. Калі будзеш мець якое-\"\n\"небудзь пытанне, да яго дакладна звярніся.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:354\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Нават са сваімі ўменнямі я не змог да канца вылячыць Фарнама. Эх, целам-то \"\n\"ён ачуняў, але розум яго і дух па-за ўсімі маімі здольнасцямі.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:356\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Хоць я і карыстаюся магіяю, у абмежаваных яе формах, каб у запас ствараць \"\n\"зеллі ды эліксіры, вось Эйдрыя – сапраўдная чараўніца. Яна быццам ніколі не \"\n\"спіць, і заўсёды мае доступ да многіх таямнічых артэфактаў і фаліянтаў. \"\n\"Думаецца мне, хата яе — не проста халупа, якой яна падаецца, але туды ніколі \"\n\"не атрымліваецца зайсці.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:358\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Бедны Вірт. Я зрабіў ўсё, што мог, для малыша, але я ведаю, ён ненавідзіць \"\n\"тую кавялу, якую прыйшлося прымацаваць к яго назе. Раны былі жудасныя. Ды \"\n\"ніхто – асабліва такое малое дзіця – не мусіць пакутаваць так, як давялося \"\n\"яму.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:360\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Я праўда не разумею, чаму Огдэн дасюль застаецца ў Трыстраме. У яго трохі \"\n\"разышліся нервы, але ён дасціпны і працавіты чалавек, дзе б ні быў, ён бы \"\n\"прыстасаваўся. Мяркую, гэта з-за страху забойстваў, што чыняцца ў ваколіцы, \"\n\"або гэта жаданне жонкі ягонай, што ён з сям'ёй нікуды не з'язджае.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Pipin (Gossip)\n#: Source/textdat.cpp:362\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Огдэнава барменка мілая дзяўчына. Бабуля яе хварэе, мучыцца ад нейкага \"\n\"мораку.\\n\"\n\"\\n\"\n\"Кажа, яна бачыць відзежы, але доказаў таго у мяне няма так ці інакш.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian\n#: Source/textdat.cpp:364\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Добры дзень! Чым магу служыць?\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:365\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Мая бабуля мне сказала, што ты прыйдзеш пагаварыць са мною. А яна бачыць \"\n\"відзежы, можа глядзець у будучыню.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:367\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Жанчына з ускраіны горада — ведзьма! Ну, яна досыць добрая, і імя ў яе, \"\n\"Эйдрыя, прыемнае вуху, але я вельмі яе баюся.\\n\"\n\"\\n\"\n\"Толькі нехта досыць смелы, як ты, мог бы глянуць, чым яна там займаецца.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:369\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Наш каваль — прычына гордасці трыстрамцаў. Не толькі ў яго рукі залатыя, і \"\n\"ён многа спаборніцтваў у сваёй гільдыі выйграў, але яго сам кароль Леорык \"\n\"хваліў, няхай ён спіць спакойна. Грызвальд і вялікі герой, Кейна спытай.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:371\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Кейн быў расказчыкам Трыстрама колькі сябе помню. Ён столькі ўсяго ведае, \"\n\"можа расказаць пра што хочаш бадай усё што можна хацець.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:373\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Фарнам – п’яніца. Сабе ў глотку эль ліе, а іншым у вушы трызніць.\\n\"\n\"\\n\"\n\"Я ведаю, што Піпін і Огдэн спачуваюць яму, але мяне так засмучае бачыць, як \"\n\"ён штоноч скочваецца ў п’яны ступар ўсё глыбей і глыбей.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:375\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Піпін выратаваў жыццё маёй бабулі, і я ведаю, што ніколі не адгаджу яму за \"\n\"гэта. Яго здольнасць вылячыць любую хваробу сільнейшая за наймагутнейшы меч, \"\n\"і больш таямнічая за любыя чары, якія ведаеш. Калі спатрэбіцца лячэнне, \"\n\"Піпін можа дапамагчы.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:377\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Я вырасла з маці Вірта, Кэнэс. Хаця яе нясільна ранілі, калі тыя вычварні \"\n\"скралі яго, яна так і не ачулася. Думаю, яна памярла, бо ёй скрышыла сэрца. \"\n\"Вірт стаў зламысным басяком, усё шукае як нажыцца з чужой працы. Я ведаю, як \"\n\"ён нацярпеўся, а якіх жахаў нагледзеўся, не магу ўявіць, але тая цемра ўсё-\"\n\"такі яшчэ вісіць над ім.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Gillian (Gossip)\n#: Source/textdat.cpp:379\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Огдэн і жонка яго ўзялі мяне і маю бабулю к сабе, нават даюць мне зарабляць \"\n\"сабе на хлеб у сваёй карчме. Я ім столькім абавязана, спадзяваюся аднойчы \"\n\"з’ехаць адсюль з імі і дапамагчы ім адкрыць на ўсходзе вялікую гасцініцу.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold\n#: Source/textdat.cpp:381\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Ну, чым магу спамагчы?\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:382\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Шукаеш сабе якой добрай зброі, дай вось што пакажу. Узяць хоць звычайную \"\n\"тупую зброю, напрыклад паліцу. Супраць тых неўміручых страхаў проста цуды \"\n\"робіць, дый няма лепшай штукі, каб такой шкілеціка раскрышыць!\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:384\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Сякера? Але, добра зброя, на любого ворага збалансавана. Палянь як яна \"\n\"паветро расцінае, просто ўяві харошанькаго такого гаматного дэмана на яе \"\n\"шляху. Адно ж не забывай, што ёю размахвацца цяжко — але які пасля будзе \"\n\"моцны ўдар!\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:386\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Толькі лянь на вастрыё, якая раўнавага. У правільных руках, меч, дый супраць \"\n\"правільнаго ворага, гаспадар над усёй зброяю. Востраму лязу яго амаль няма \"\n\"чаго сячы ці пратыкаць на мярцах, але жывому, што шчэ дыхае, меч добра плоць \"\n\"пасячэ!\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:388\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"На тваёй зброі ды брані будзе відаць сляды барацьбы з Цемраю. Прынясеш мне, \"\n\"распалім горан, трохі папрацацуймо, і вернем ім лепшы баявы стан.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:390\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Покі я, лічы, шмуглюю, каб струманты там ды метал прыдбаць з караванаў, што \"\n\"ходзяць часам за нашым клятым горадам, ведзьма тая, Эйдрыя, нібыто ўсё што \"\n\"трэба дастаць можа. Знайся я хоць крыху як яна на чарадзействе, я б вырабляў \"\n\"сапраўды файныя рэчы.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:392\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Джыліен слаўная дзеўчына. Шкада, што бабулі ейнай так далягае, а то б я \"\n\"ўладзіў, каб які гандлёвы караван вывез іх адсюль.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:394\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Іншым разам задумваюся, маўляў Кейн замнога гаворыць, але відаць такое яго \"\n\"прызванне. Ездзі я па жалезе так, як ён табе па вушах, я б зрабіў ужо такі \"\n\"раскошны гарнітур, Імператару б пасаваў!\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:396\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Я быў з Фарнамам тае ночы, калі Лазар завёў нас у Лабірынт. Больш я \"\n\"Архібіскупа не бачыў, і я б сам не вырабіўся, каб не Фарнам. Баюся, тая \"\n\"атака скалечыла яму душу, ды так, як, ну, як мне маю нагу. Зараз у ягонай \"\n\"бітве я не магу біцца за яго, але каб прымеў, біўся б.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:398\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Добры той чалавек што ставіць патрэбы іншых вышэй за свае. Не знойдзеш \"\n\"нікого ў Трыстраме — і дзе яшчэ, раз на тое пайшло, — хто б казаў пра лекара \"\n\"нешто дрэннае.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:400\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"І трапіць жа той малец раз у бяду... ну, мушу сказаць, зноў трапіць. Я хацеў \"\n\"быў яго зацікавіць работай, каб вучыўся тут чэснай працы, але яму больш \"\n\"даспадобы вялікая выгада з гандлю таварам невядома адкуль узятым. Не магу \"\n\"яго за тое вініць, пасля ўсяго што з ім было, але я б вельмі хацеў, каб ён \"\n\"хоць асцярожны быў.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Griswold (Gossip)\n#: Source/textdat.cpp:402\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Справы ў карчмара ідуць не надто, ён амаль не мае выгады са свайго дзела. \"\n\"Канцы з канцамі зводзіць, забяспечваючы ежай і начлегам тых, хто падчас едзе \"\n\"праз вёску, але яны хутчэй змыюцца ўночы, ніж яму заплацяць. Каб ён не \"\n\"назапасіў у сваіх скляпах збожжа і сушанага мяса, авохці, з голаду б памерла \"\n\"большасць з нас у першы ж год, калі ўсю ваколіцу запаланілі дэманы.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham\n#: Source/textdat.cpp:404\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Ужо і выпіць нельга спакойна?\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:405\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"Дзеўка, што выпіўку падае? Ой, ну так, такая прыгажуня. Яшчэ і добрая.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:407\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Чаго тая карга хоць для разнастайнасці нешта не зробіць. Вядома, вядома ж, \"\n\"яна там нечым займаецца, але ты мяне паслухай... яна не нармальная. Я ніколі \"\n\"не бачыў, каб яна ела ці піла, а нельга давяраць таму, хто хоць крыху не п'е.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:409\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Кейн не той, за каго се выдае. Вядома, вядома ж, зубы загаворвае ён умела... \"\n\"а часам вельмі і страшна і смешна... але думаецца мне, ён ведае больш, чым \"\n\"сам ведае, што ведае.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:411\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Грызвальд-то? Стары добры Грызвальд. Ды я яго як брата люблю! Мы тады разам \"\n\"біліся, ну знаеш, калі гэта... мы... Лазар... Лазар... Лазар!!!\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:413\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Хехехе, мне да спадобы Піпін. Ён сапраўды стараецца, знаеш так. Слухай, ты з \"\n\"ім дакладна пазнаёмся. Добры таварыш сярод люду, якім вечна трэба помач. Ну, \"\n\"амаль нехта як ты, а, герой? І я быў героем…\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:415\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"У Вірта праблем нат больш ніж у мяне, а я-то пра праблемы знаю. Паслухай – \"\n\"дзела-то ў хлапчука спорыцца, аж ён быў там, знаеш? Нагу страціў! Клыпаць \"\n\"цяпер на кавалку дзерава. Якое гора, якое гора…\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:417\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Огдэн – найлепшы мужык у горадзе. Не думаю, што жонка ягоная мяне надта \"\n\"падабае, але пакуль яна з бочак разлівае, буду і я яе падабаць. З Огдэнам я \"\n\"баўлю нібыта больш часу, ніж яшчэ з кім, але ён такі добры…\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:419\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Нешта я табе скажу, бо ж гэта, я пра гэта ўсё ведаю. То мой канёк. От, ля, \"\n\"гэты проста найлепшы… нааааайлепшы! Той другі эль зусім не харошы, усё з-за \"\n\"тых тупых сабак…\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:421\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Ніхто мяне нік… ніколі ні слухае. Недзе — не пэўны дзе — недзе пад цэркваю ё \"\n\"цэлая куча золата. Блішчыць, зіхаціць ды адно чакае, каб яго нехта прыбраў.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:423\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Знаю, ў цябе там сваё наўме, дый знаю, што не паверыш, але зброя твая — ну \"\n\"зусім не дзела проці той нечысці! Ай, ды пляваць мне што там кажа Грызвальд, \"\n\"цяперака не робяць як у даўнейшыя часы...\"\n\n#. TRANSLATORS: Neutral dialog spoken by Farnham (Gossip)\n#: Source/textdat.cpp:425\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Будзь я табой... хаця я не ты... але будзь я, я б прадаў усё, што маеш, і \"\n\"даў бы драпака адсюлека. Унь хлопец гэны... У яго заўсёды нешта файнае, але \"\n\"яму трэ золата адсыпаць, а то ён нат не пакажа, што там у яго.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria\n#: Source/textdat.cpp:427\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Душу ў пошуках адказаў адчуваю...\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:428\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Мудрасць здабываецца, а не даецца. Адшукаўшы фаліянт вед, паглыні яго словы. \"\n\"Калі высветліцца, што ты ўжо валодаеш запаветнымі тайнамі, вылажанымі ў \"\n\"кнізе, помні – гэты ўзровень майстэрства заўжды можна перасягнуць.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:430\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Найвялікшая сіла часцей і жыве карацей ад усіх. Ты можаш знайсці словы \"\n\"старасвецкай сілы на скрутках пергаменту. Моц такіх скруткаў заключана ва \"\n\"уласцівасці іх карыстання: аднолькавы поспех чакае і простага вучня, і \"\n\"адэпта. Слабасць жа іх у тым, што спачатку павінна прачытаць іх услых, і іх \"\n\"нельга захаваць сабе ў памяці. Ведай і тое, што выкарыстаць такі скрутак \"\n\"можна толькі аднойчы, таму выкарыстоўвай іх абачліва.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:432\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Хаця гарачыню сонца нельга змераць, полымя ўсяго аднае свечкі \"\n\"небяспечнейшае. Няма энергіі, якою можна было б карыстацца без належнага \"\n\"фокусу. Для многіх чар гэта працуе так, што праз скрутак магчыма зарадзіць \"\n\"посах іх магічнаю сілаю, і многа раз. Я магу аднавіць іх сілу, але ведай, \"\n\"што нічога не робіцца дарма.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:434\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Сума нашых вед у суме людзей, што імі валодаюць. Калі знойдзеш кнігу ці \"\n\"скрутак, які не можаш расшыфраваць, не вагайся звярнуцца да мяне. Калі я \"\n\"ўбачу ў тым сэнс, я падзялюся, чым змагу.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:436\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Для чалавека, каторы ведае толькі жалеза, няма большай магіі за Сталь. \"\n\"Каваль Грызвальд большы чараўнік, чым ён здагадваецца. У гэтым краі ў \"\n\"здольнасці зліваць агонь і метал яму няма роўных.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:438\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Псота валодае сілай падману, але нявіннасць змяшчае сілу чысціні. Юная \"\n\"кабета Джыліен мае чыстае сэрца, і ставіць беды сваёй роданачальніцы вышэй \"\n\"за свае. Яна страшыцца мяне, але толькі таму, што не разумее мяне.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:440\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Куфар, калі адкрыты ў цемры, не змяшчацьме большы скарб, чым калі адкрыты ў \"\n\"святле. Расказчык Кейн – таямніца, але толькі для тых, хто не ўглядаецца. \"\n\"Яго веды аб тым, што знаходзіцца пад саборам, значна большыя, чым ён нават \"\n\"дазваляе сабе ўявіць.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:442\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Чым вышэй ты ставіш веру ў аднаго чалавека, тым вышэй ёй потым упасці. \"\n\"Фарнам страціў душу, але не на карысць дэманам. Яна страцілася, калі ён \"\n\"бачыў, як яго землякам здрадзіў Архібіскуп Лазар. Ён валодае ведамі, якія \"\n\"варта збіраць па каліве, але мусіш адрозніваць факт ад фантазіі.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:444\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Рука, сэрца і розум твораць цуды, калі яны ў суладнасці. Лекар Піпін зазірае \"\n\"ў цела так, як не магу нават я. Яго здольнасць аднаўляць хворых і параненых \"\n\"памножана яго разуменнем стварання эліксіраў і зелляў. Лепшага паплечніка ў \"\n\"Трыстраме табе не знайсці.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:446\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Мы многа не ведаем аб будучыні, але калі яна надыходзіць, то трапляе ў рукі \"\n\"дзяцей. Хлопчык Вірт мае чарнату на душы сваёй, але ён не кідае ценю пагрозы \"\n\"ні на горад, ні на яго людзей. Вынік яго патаемных спраў з абадранцамі і \"\n\"скрытнымі гільдыямі вакольных гарадоў у яго доступе да многіх прылад, якія \"\n\"не так проста знайсці ў Трыстраме. Яго спосабы можна дакараць, але Вірт можа \"\n\"паспрыяць табе ў тваёй бітве з Цемраю, якая не адступае.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Adria (Gossip)\n#: Source/textdat.cpp:448\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"То не сцены ды страха дом ствараюць. У гэтым мястэчку карчмар Огдэн служыць \"\n\"большай мэце, чым многія могуць падумаць. Ён дае прытулак Джыліен і яе \"\n\"роданачальніцы, падтрымлівае жыццё Фарнама, якое той скінуў на яго, і \"\n\"служыць усім, хто застаўся ў горадзе, якарам колішняга Трыстрама. Яго карчма \"\n\"і простыя радасці, што яшчэ можна знайсці там, даюць мелькам зірнуць на \"\n\"жыццё, якое людзі тут яшчэ помняць. Гэта ж памяць і жывіць іх надзею на твой \"\n\"поспех.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt\n#: Source/textdat.cpp:450\nmsgid \"Pssst... over here...\"\nmsgstr \"Пс... ходзь сюды...\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:451\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Не ўсім у Трыстраме ёсць карысць – ці інтарэс – да ўсяго, што ты знаходзіш у \"\n\"лабірынце. Нават мне, як ні цяжка гэтаму паверыць.\\n\"\n\"\\n\"\n\"Іншым разам толькі табе ўдасца знайсці прымяненне некаторым рэчам.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:453\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Не давай веры ўсяму, што кажа апівоша. Столькі многа элю патупіла яму і вочы \"\n\"і цвярозы розум.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:455\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Калі не добра відаць, я нічога не купляю з Трыстрама. Я імпарцёр якаснага \"\n\"тавару. Калі хочаш смецце каму загнаць, ідзі да Грызвальда там, Піпіна, або \"\n\"да ведзьмы той, Эйдрыі. Упэўнены, з рукамі адарвуць, што ні прынясеш…\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:457\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Здаецца я кавалю жыццём абавязаны, вярней тым што ад яго засталося. Вядома, \"\n\"Грызвальд мяне ў вучні зваў на кузню, і ён даволі добры мужык, але там я \"\n\"ніколі не накаплю на… ну, скажам так, ёсць у мяне адна задума, для якой мне \"\n\"трэба вялікая куча золата.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:459\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Будзь я трохі старшэй, хадзіла б яна ў золаце, якое толькі б пажадала, і не \"\n\"сумнявайся, я магу дастаць сапраўды харошыя рэчы. Джыліен – добрая дзяўчына, \"\n\"трэба ёй цякаць з Трыстрама, пакуль мажліва. Гм-м-м… мо ўзяць яе з сабою, \"\n\"калі пайду…\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:461\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Кейн ведае занадта многа. Як ён мяне гэтым страшыць, нават мацней за тую, \"\n\"што за ракой жыве. Ён усё кажа, маўляў, як мне павязло што я жывы, і што мая \"\n\"гісторыя прадказана ў легендзе. Мне здаецца ён зусім з глуздоў з'ехаў.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:463\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Фарнам — вось у каго сур'ёзныя праблемы, а я-то знаю, якімі сур'ёзнымі \"\n\"могуць быць праблемы. Даверыўся шчырасці аднаго чалавека засільна, Лазар яго \"\n\"і завёў у самую пашчу смерці. А, дый я знаю, як там, нават не пачынай пра \"\n\"свае планы знішчыць зло, што асялілася ў Лабірынце. Ногі беражы, вось што \"\n\"скажу...\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:465\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Калі толькі табе не трэба нешта прымацаваць, лепш старога Піпіна тут няма. \\n\"\n\"\\n\"\n\"Былі б у мяне тады яго зеллі, можа і з нагою бы застаўся...\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:467\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Вось Эйдрыя мяне праўда непакоіць. Кейн канешне страшны, як ён табе пра тваё \"\n\"мінулае можа расказаць, аж ведзьма тая можа ў тваё мінулае зазірнуць. І ёй \"\n\"вечна ўдаецца дастаць усё, што ёй зажадаецца. Яна столькі тавару прыдабывае, \"\n\"больш чым я бачыў цераз браму на каралеўскім базары ў Вялікі Фэст.\"\n\n#. TRANSLATORS: Neutral dialog spoken by Wirt (Gossip)\n#: Source/textdat.cpp:469\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Дурань Огдэн, што тут застаецца. Я бы яго адсюль вывез ды па вельмі разумнай \"\n\"цане, але ён упёрся, хоча з гэтай дурной карчмы разбагацець. Ну, хоць \"\n\"Джыліен ёсць дзе рабіць, і жонка ягоная, Гарда, проста цудоўную запяканку \"\n\"гатуе...\"\n\n#. TRANSLATORS: Quest text spoken aloud from a book by player\n#: Source/textdat.cpp:471 Source/textdat.cpp:479 Source/textdat.cpp:487\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"За заламі герояў стаіць Пакой Касцей. Вечная смерць чакае ўсякага хто \"\n\"паквапіцца на скарбы ахаваныя ў тым месцы. Так кажа Пан Жаху, так і напісана.\"\n\n#. TRANSLATORS: Quest text spoken aloud from a book by player\n#: Source/textdat.cpp:473 Source/textdat.cpp:481 Source/textdat.cpp:489\n#: Source/textdat.cpp:527 Source/textdat.cpp:535\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"І вось, замкнёная за варотамі крыві, цераз залу агнёў, Адвага чакае, калі \"\n\"герой святла абудзіцца…\"\n\n#. TRANSLATORS: Quest text spoken aloud from a book by player\n#: Source/textdat.cpp:475 Source/textdat.cpp:483 Source/textdat.cpp:491\n#: Source/textdat.cpp:529 Source/textdat.cpp:537\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Віджу, што табе не відна,\\n\"\n\"Зрок тупее, вочы ў гнілі.\\n\"\n\"Іх няма, як абярнешся, \\n\"\n\"Шэпчуць толькі тайну песню.\\n\"\n\"Тут убачыш, што не ўбачыць.\\n\"\n\"Дзе святло? Там цені танчуць.\\n\"\n\"З глудзу, з цьмы ты паляціш.\\n\"\n\"Проста ўніз, у Зал Сляпых.\"\n\n#. TRANSLATORS: Quest text spoken aloud from a book by player\n#: Source/textdat.cpp:477 Source/textdat.cpp:485 Source/textdat.cpp:493\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Збраёўні Пекла — дом Крывавага ваяводы. За ім ляжаць знявечаныя целы тысяч і \"\n\"тысяч. Забіты і анёлы і людзі, усё ў ахвяру Цёмным, што крычаць аб адным — \"\n\"крыві.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:505\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Зважайце ж і будзьце сведкамі ісціны, выказанае тут, бо то ёсць апошняе са \"\n\"спадчыны Харадрым. Нават цяпер лютуе вайна, па-за межамі, вядомымі нам – меж \"\n\"Бездакорных каралеўстваў Вярхоўных Нябёс і Бязладнай Прорвы Агністых Пекел. \"\n\"Імя тае вайны – Вялікае Змаганне, і бушуе яны ды гарыць ужо даўжэй за ўсякую \"\n\"зорку на небе. Ніводзін бок не бярэ верх надоўга, покуль сілы Святла і Цемры \"\n\"бесперастанку спаборнічаюць за ўладу над усім існым.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:507\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Зважайце ж і будзьце сведкамі ісціны, выказанае тут, бо то ёсць апошняе са \"\n\"спадчыны Харадрым. Калі адвечнае змаганне меж Вярхоўнымі Нябёсамі і \"\n\"Агністымі Пекламі выпадае на смертных грунт, то і ёсць Вайна Граху. Анёлы і \"\n\"дэманы скрытыя ходзяць сярод людзей, таемна змагаючыся, чым далей ад \"\n\"цікаўных чалавечых вачэй. Некаторыя са смертных, магутныя і смелыя, нават \"\n\"сталі ў хаўрус з адным з двух бакоў, дапамагаючы весці ход вайны.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:509\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Зважайце ж і будзьце сведкамі ісціны, выказанае тут, бо то ёсць апошняе са \"\n\"спадчыны Харадрым. Амаль трыста год таму, стала вядома аб таямнічым прыходзе \"\n\"тройцы Першага Зла з Агністых Пекел у наш свет. Трое братоў спусташалі землі \"\n\"Усходу дзесяцігоддзямі, покуль чалавецтва дрыжала пад імі. Нашае брацтва — \"\n\"Харадрым — заснавалася скрытнаю суполкаю Мудрацоў, дзеля таго, каб высачыць \"\n\"і паланіць Трое Зол раз і назаўжды.\\n\"\n\"\\n\"\n\"Першыя Харадрым двух з Трох захапілі ў моцныя артэфакты, вядомыя як Камяні \"\n\"Душ, і пахавалі іх глыбока пад усходнімі пустынямі. Трэцяе з Зол пазбегла \"\n\"палону і ўцякло ад вялікай пагоні Харадрым на Захад. Яго, вядомага як \"\n\"Д'ябла, Пан Жаху, урэшце паланілі, і існасць яго змясцілі ў Камень Душы і \"\n\"пахавалі ў Лабірынце.\\n\"\n\"\\n\"\n\"Сцеражыцеся ж, бо нельга таму стацца, каб Камень Душы знайшлі тыя, хто не ад \"\n\"Веры. Калі яны вызваляць Д'ябла, ён шукацьме цела, лёгкае для ўладання, бо \"\n\"ён будзе вельмі слабы. Магчыма, цела як старога альбо дзіцяці.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:511\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"І сталася так, што ў Агністых Пеклах быў мяцеж, празваны Цёмным Выгнаннем. \"\n\"Меншае Зло зрынула тройцу Першага Зла, і прагнала дух іх у царства смертных. \"\n\"Дэманы ж Бэліял, валадар ілжы, і Азмадан, валадар граху, за адсутнасцю Трох \"\n\"Братоў распачалі барацьбу за стырно ўлады. Усё Пекла падзялілася на два \"\n\"лагеры ў супрацьстаянні Бэліяла і Азмадана, покуль сілы Вярхоўных Нябёс \"\n\"бесперастанна таранілі ў самую браму Пякельную.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:513\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Многія дэманы адправіліся ў царства смертных, шукаючы Трох Братоў. А за тымі \"\n\"дэманамі рушылі следам анёлы, і палявалі на іх па неабсяжных гарадах Усходу. \"\n\"Анёлы аб'ядналіся з брацтвам смертных Мудрацоў, што звалася Харадрым, якія ў \"\n\"скорым часе сталі дасведчанымі паляўнічым на дэманаў. А ў падземных светах \"\n\"знайшлі яны сабе многа цёмных ворагаў.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:515\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"І сталася так, што духі Тройцы Першага Зла былі выгнаны ў царства смертных, \"\n\"а пасля таго, як яны сеялі хаос па ўсім Усходзе дзсяцігоддзямі, праклятае \"\n\"брацтва Харадрым высачыла іх. Харадрым выкарысталі артэфакты, называныя \"\n\"Камяні Душ, каб стрымаць у іх існасць Мефіста, Пана Нянавісці, і брата яго \"\n\"Баала, Пана Знішчэння. Малодшы брат, Д'ябла, Пан Жаху, збег на Захад.\\n\"\n\"\\n\"\n\"Урэшце, Харадрым зняволілі ў Каменю Душы і Д'ябла, і пахавалі яго пад \"\n\"старадаўнім, забытым Саборам. Там Пан Жаху і спіць, чакаючы гадзіну свайго \"\n\"адраджэння. Ведайце ж, што ён шукацьме цела юнае і моцнае, каб ухапіцца ў \"\n\"яго, такое, што бязвінным ёсць і для ўладання лёгкім. Тады паўстане ён, каб \"\n\"збавіць братоў сваіх і зноў раздзьмуць полымя вайны Граху...\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:517\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Аднаго Д’ябла ўсхваляем, пана Жаху, ацалелага Цёмнага Выгнання. Калі ён \"\n\"прачнуўся ад свайго доўгага сну, пан мой і гаспадар загаварыў са мною аб \"\n\"тайнах, якія немногім смертным вядомыя. Сказаў ён, што Вярхоўныя Нябёсы і \"\n\"Прорвы Агністых Пекел вядуць вечную вайну. І адкрыў ён мне сілы, што ўнеслі \"\n\"разлад у царствы Чалавекаў. І назваў пан і гаспадар мой бітву за свет гэты і \"\n\"ўсіх у ім Вайною Граху.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:519\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Уся хвала і слава Д'яблу, пану жаху і галаве над Трыма. Пан мой гаварыў са \"\n\"мною аб дваіх братах сваіх, Мефіста і Баале, выгнаных ў свет гэты даўным-\"\n\"даўно. Пан мой жадае вычакаць зручны момант і сабраць сваю жахлівую сілу, \"\n\"каб вызваліць сваіх паланёных братоў з грабніц пад усходнімі пяскамі. Калі \"\n\"мой пан збавіць братоў сваіх, Вайна Граху ізноў спазнае лютасць Трох.\"\n\n#. TRANSLATORS: Book read aloud\n#: Source/textdat.cpp:521\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Слава і ахвяра Д'яблу, Пану Жаху і Душагубу. Калі абудзіў я Гаспадара свайго \"\n\"ада сну яго, ён намогся ўхапіцца ў смертную абалонку. Д'ябла абраў цела \"\n\"Караля Леорыка, але Гаспадар мой быў заслабым праз сваё зняволенне. Пан мой \"\n\"меў патрэбу ў адным простым і бязвінным якары ў свет гэты, і так палічыў \"\n\"хлопчыка Альбрэхта найлепшым для той справы. Пакуль слаўны Кароль Леорык \"\n\"застаўся звар'яцелым пасля няўдалага апанавання Д'яблам, я скраў сына яго, \"\n\"Альбрэхта, і прывёў яго к Пану свайму. Цяпер чакаю поклічу Д'яблы, і малюся, \"\n\"што буду ўзнагароджаны, калі нарэшце ён паўстане як Пан гэтага свету.\"\n\n#. TRANSLATORS: Neutral Text spoken by Ogden\n#: Source/textdat.cpp:523\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Слава небу вы тут!\\n\"\n\"Шмат змянілася з часу, калы вы тут жылі, дружа мой. Усё было спакойна, але \"\n\"потым прыехалі цёмныя вершнікі і знішчылі нашу вёску. Многіх забілі на месцы \"\n\"ж, а хто адбіваўся, тых або забілі, або зацягнулі ў рабства, ці нават горш. \"\n\"Царкву на ўскраіне апаганілі, і цяпер там чыняцца цёмныя рытуалы. То не \"\n\"чалавечыя крыкі адтуль адгукаюцца ноччу, але магчыма, што нехта з гараджан і \"\n\"выжыў. Ідзіце дарогай між маёй карчмой і кузняй і знайдзіце царкву, \"\n\"выратуйце, каго зможаце.\\n\"\n\"\\n\"\n\"Можа другі раз змагу расказаць больш. Удачы.\"\n\n#. TRANSLATORS: Quest text spoken aloud from a book by player\n#: Source/textdat.cpp:525 Source/textdat.cpp:533\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n\"any who would seek to steal the treasures secured within this room.  So \"\n\"speaks the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"За заламі герояў стаіць Пакой Касцей. Вечная смерць чакае ўсякага хто \"\n\"паквапіцца на скарбы ахаваныя ў тым месцы. Так кажа Пан Жаху, так і напісана.\"\n\n#. TRANSLATORS: Quest text spoken aloud from a book by player\n#: Source/textdat.cpp:531 Source/textdat.cpp:539\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood.  In his wake lay the \"\n\"mutilated bodies of thousands.  Angels and man alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Збраёўні Пекла — дом Крывавага Ваяводы. За ім ляжаць знявечаныя целы тысяч і \"\n\"тысяч. Забіты і анёлы і людзі, усё ў ахвяру Цёмным, што крычаць аб адным — \"\n\"крыві.\"\n\n#. TRANSLATORS: Quest text spoken by Adria\n#: Source/textdat.cpp:541\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Не спыняй свае пошукі. Знайсці згублены скарб складана. Знайсці схаваны \"\n\"скарб — ужо менш. Гэтага табе пакуль хопіць. Не дай пяскам часу збянтэжыць \"\n\"цябе ў пошуках.\"\n\n#. TRANSLATORS: Quest text spoken by Griswold\n#: Source/textdat.cpp:543\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Каго?! Глупство гэто. Няма пад Трыстрамам ніякіх скарбаў. Дай гляну!! А, \"\n\"лянь, малюнкі з памылкамі. Зусім на наш горад не падобно. Я б думаў пра тое, \"\n\"што пад саборам, а не што пад верхнім пластом глебы.\"\n\n#. TRANSLATORS: Quest text spoken by Pipin\n#: Source/textdat.cpp:545\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Па праўдзе, не маю часу, каб абмяркоўваць нейкую мапу. У мяне тут шмат \"\n\"людзей, якім мне трэба дапамагчы, як і табе таксама.\"\n\n#. TRANSLATORS: Quest text spoken by Adria\n#: Source/textdat.cpp:547 Source/textdat.cpp:559\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Некалі горды Ізуал апынуўся ў пастцы пад паверхняй гэтага свету. Яго гонар \"\n\"адняты, а твар зменены. Ён у пастцы вечных пакут. Абавязаны скрываць тую \"\n\"адзіную рэч, што магла б яго вызваліць.\"\n\n#. TRANSLATORS: Quest text spoken by Ogden\n#: Source/textdat.cpp:549\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Стаўлю, што Вірт проста нешта выдумаў, калі цябе ўбачыў, каб потым \"\n\"пасмяяцца, калі пачнеш бегаць па вёсцы ў гразным носам. Я б не звяртаў на \"\n\"яго ўвагі.\"\n\n#. TRANSLATORS: Quest text spoken by Cain\n#: Source/textdat.cpp:551\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Быў час, калі ў падарожных з усіх старон гэты горад быў частым прыпынкам. \"\n\"Шмат чаго перамянілася. Але схаваныя пячоры ды пахаваныя скарбы, усё гэта \"\n\"звычайныя фантазіі ўсякага дзіцяці. Вірт рэдка дазваляе сабе пазабаўляцца. \"\n\"Магчыма, гэта проста яго ўяўленне.\"\n\n#. TRANSLATORS: Quest text spoken by Farnham\n#: Source/textdat.cpp:553\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Слухай сюды. Падыдзі. Я не ведаю, ці ведаеш ты, што я ведаю, але ў цябе тут \"\n\"нешта праўда важнае. Гэта мапа.\"\n\n#. TRANSLATORS: Quest text spoken by Gillian\n#: Source/textdat.cpp:555\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetary, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Бабуля мне часта расказвае пра дзіўныя сілы, што насяляюць могілкі каля \"\n\"царквы. Можа, адна такая гісторыя зацікавіць цябе. Яна казала, што калі \"\n\"пакінуць на цвінтары належную ахвяру, зайсці ў сабор і памаліцца за мёртвых, \"\n\"а потым вярнуцца, ахвяра неяк дзіўна зменіцца. Не ведаю, ці гэта проста \"\n\"словы хворай старой, але гэтыя дні быццам усё можа быць.\"\n\n#. TRANSLATORS: Quest text spoken by Wirt\n#: Source/textdat.cpp:557\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Гммм. Вялізны і таямнічы скарб, кажаш? Мммм. Мо я і зацікаўлюся, каб \"\n\"прыкупіць у цябе чагось. А мо шчэ лепей, не трэба табе нейкіх рэдкіх ды \"\n\"дарагіх прыпасаў, каб падолець у такім выпрабаванні?\"\n\n#. TRANSLATORS: Neutral text spoken by Farmer (Gossip)\n#: Source/textdat.cpp:561\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Дык гэта пра цябе героя тут усе балакаюць. Мо дапаможаш простаму беднаму \"\n\"фермеру ў жудаснай бядзе? На краі майго саду, рыхтык на поўдзень адсюль, \"\n\"нешта ўспухла проста з зямлі! Няма як падступіцца да майго жніва ды стагоў, \"\n\"кароўкі мае бедныя будуць галадаць. Тая ведзьма дала мне вось, сказала гэта \"\n\"ўзарве тую гадасць з майго поля. Калі знішчыш тое, век табе буду ўдзячны. Я \"\n\"б і сам гэта зрабіў, але некаму трэба пільнаваць кароў...\"\n\n#. TRANSLATORS: Neutral text spoken by Farmer (Gossip)\n#: Source/textdat.cpp:563\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Так і думаў, што ўсё не так проста, як са слоў ведзьмы. Сумны гэта свет, дзе \"\n\"не можаш давяраць нават сваім суседзям.\"\n\n#. TRANSLATORS: Neutral text spoken by Farmer (Gossip)\n#: Source/textdat.cpp:565\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Усё? Згінула яно назад у цёмныя ямы Аду што парадзіў яго? Чаго? Ой, не \"\n\"гавары што руна прапала! Яны ж не танныя, ну. Знайдзі яе, і ўзарві той \"\n\"страх, каб духу яго тут не было.\"\n\n#. TRANSLATORS: Neutral text spoken by Farmer (Gossip)\n#: Source/textdat.cpp:567\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Я адсюль чуў выбух! Вялікі дзякуй табе, добры незнаёмец. І што за напасць, \"\n\"усякае з зямлі лезе, пачвары царкву захапілі, і гэтак далей, цяжкая гэта \"\n\"часіна. Я проста бедны фермер, але вось, прымі гэта з маёй вялікай падзякай.\"\n\n#. TRANSLATORS: Neutral text spoken by Farmer (Gossip)\n#: Source/textdat.cpp:569\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Ох, якая бяда мая... можа... Не, не буду навязвацца, столькі бедаў і так. \"\n\"Можа калі крыху ачысціш царкву ад гэтай нечысці, вернешся... і прысвеціш \"\n\"колькі часу, каб дапамагчы беднаму фермеру?\"\n\n#. TRANSLATORS: Quest text spoken by Little Girl\n#: Source/textdat.cpp:571\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Уэээ! (шморг) Уэээ! (шморг)\"\n\n#. TRANSLATORS: Quest text spoken by Little Girl\n#: Source/textdat.cpp:572\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Я Тэа згубіла! Майго лепшага сябра! Мы гулялі за ракой, а Тэа сказаў што \"\n\"хоча паглядзець на тую зялёную штукенцыю. Я сказала што нам няможна, але мы \"\n\"залезлі туды, і тут вылез той ЖУК! Мы ходу, а Тэа ўпаў і жук той яго ХОП і \"\n\"забраў яго!\"\n\n#. TRANSLATORS: Quest text spoken by Little Girl\n#: Source/textdat.cpp:574\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Вы знайшлі яго? Знайдзіце, калі ласка! Ён такі маленькі. Ён сябе не можа \"\n\"даглядаць! Калі ласка!\"\n\n#. TRANSLATORS: Quest text spoken by Little Girl (Quest End)\n#: Source/textdat.cpp:576\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Знайшлі! Знайшлі! Дзякуй вам! Ох, Тэа, цябе напужалі тыя гадкія жукі? Эй! \"\n\"Фэ! У цябе нешта ў поўсці прыліпла! Фу! Хадзем, Тэа, дамоў! Яшчэ раз дзякуй \"\n\"вам, герой!\"\n\n#. TRANSLATORS: Quest text spoken by Defiler (Hostile)\n#: Source/textdat.cpp:578\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Доўга ляжалі мы ў дрымоце, надышла пара нам прабудзіцца. Па нашым доўгім \"\n\"сне, нас поўніць вялікі голад. Скора, цяпер жа, мы пакормімся...\"\n\n#. TRANSLATORS: Quest text spoken by Defiler (Hostile)\n#: Source/textdat.cpp:580\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Весялішся тут, малое млекакормячае? Якая нікчэмнасць. Ваш маленькі свет не \"\n\"стане ані перашкодаю.\"\n\n#. TRANSLATORS: Quest text spoken by Defiler (Hostile)\n#: Source/textdat.cpp:582\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Гэтыя землі будуць апаганены, і наш вывадак ахопіць палі, якія людзі клічуць \"\n\"домам. Нашы атожылкі ахутаюць гэты свет, і мы нажыруемся плоццю яго жыхароў. \"\n\"Чалавек будзе нам раб і харч.\"\n\n#. TRANSLATORS: Quest text spoken by Defiler (Hostile)\n#: Source/textdat.cpp:584\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ах, чую твой пах... ты блізка! Блізка! Сссс... пах крыві і страху... як \"\n\"прывабна...\"\n\n#. TRANSLATORS: Quest text spoken by Narrator\n#: Source/textdat.cpp:592\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"І ў год жа Залатога Святла было загадана, каб паўстаў Сабор. Краевогульны \"\n\"камень было павінна выразаць з напаўпразрыстага каменя Антыраэля, названага \"\n\"ў гонар Анёла, што дзяліўся сілаю сваёю з Харадрым.\\n\"\n\"\\n\"\n\"У Год Набліжэння Ценяў затрэслася зямля, і абрушыўся Сабор той. Калі \"\n\"будаўніцтва катакомб і замкаў пачалося, а чалавек паўстаў супраць \"\n\"разбурэнняў вайны Граху, разваліны тыя абабраны былі з-за камення свайго \"\n\"каштоўнага. І тым чынам згінуў з вачэй чалавечых краевугольны камень.\\n\"\n\"\\n\"\n\"Камень той быў ад гэтага свету — і ад усіх светаў — як Святло разам і ўнутры \"\n\"кожнай рэчы і па-за ёю. Святло і адзінства ёсць вынік гэтае святое асновы, \"\n\"адзінства цэлі і адзінства валодання.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:594\nmsgid \"Moo.\"\nmsgstr \"Му-у.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:595\nmsgid \"I said, Moo.\"\nmsgstr \"Му-у, кажу.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:596\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Слухай, я проста карова, добра?\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:597\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Добра, добра. Я не зусім карова. Я так звычайна не хаджу, але ж, ну, сядзеў \"\n\"я дома, займаўся там сваім, аж раптам павылазілі жукі, лозы, лямпы і ўсякае \"\n\"такое прама з падлогі… Жах які! Каб я меў што нармальнае надзець, ды не было \"\n\"б усё так кепска. Слухай! А можа сходзіш да маёй хаты і возьмеш мне мой \"\n\"касцюм? Толькі карычневы, не шэры, яго я на вечар надзяю. Я б і сам схадзіў, \"\n\"але не хачу, каб мяне бачылі такога. Вось, на, можа прыгадзіцца… Каб прыбіць \"\n\"усё, чым там зарасло. Маю хату не прапусціш. Проста на поўдзень адтуль, дзе \"\n\"рака разгаліноўваецца… Ну… Дзе там зарослы агарод.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:599\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Навошта марнуеш час? Ідзі і прынясі мне мой касцюм! І хутчэй! Вунь бычара \"\n\"адзін мне ўжо падміргвае!\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:601\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Прывет, гэта касцюм мой у цябе? Хутчэй, давай сюды! Гэтыя вушы так свярбяць, \"\n\"не паверыш!\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:603\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Не, не, не, не! Гэта мой ШЭРЫ касцюм! Ён на вечар! Для афіцыйных выпадкаў! Я \"\n\"не магу ГЭТА надзець. Ты што, дзівак нейкі? Мне патрэбен Карычневы касцюм.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:605\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Аа, вось гэта значна лепш будзе. Фух! Нарэшце, хоць якая годнасць! У мяне \"\n\"рогі роўна сталі? Добра. Слухай, дзякуй табе вялікі за дапамогу. Вось, \"\n\"вазьмі ў падарак, ведаеш... маленькая парада па модзе... можаш трохі... \"\n\"навейшае.... ну разумееш пра што я? Увесь гэты матыў шукальніка прыгод \"\n\"такі... рэтравы. Проста парада, добра? Чао.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:607\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Слухай. Я карова. А ты, ты прынада на пачвар. Назапасься досведу! Тады \"\n\"пагаворым.\"\n\n#. TRANSLATORS: Quest text spoken by Farmer\n#: Source/textdat.cpp:610\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Мусіць, і праўда страшную задачу я табе паставіў. Каб быў хоць нейкі \"\n\"спосаб... а табе не дапамог бы збанок свежага малачка?\"\n\n#. TRANSLATORS: Quest text spoken by Farmer\n#: Source/textdat.cpp:612\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"О, мне б прыдалася твая дапамога, але можа пасля таго, як выратуеш катакомбы \"\n\"ад тых пачвар-паганнікаў.\"\n\n#. TRANSLATORS: Quest text spoken by Farmer\n#: Source/textdat.cpp:614\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Мне тут трэба помач, але не магу ж я навязвацца зусім незнаёмаму чалавеку. \"\n\"Можа, як вы пабудзеце тут крыху, вось тады мне будзе лягчэй папрасіць аб \"\n\"паслузе.\"\n\n#. TRANSLATORS: Quest text spoken by Farmer\n#: Source/textdat.cpp:616\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Я бачу твой патэнцыял вялікасці. Можа якім разам прыйдзеш, пакуль выконваеш \"\n\"свой лёс, і зробіш мне адну паслугу?\"\n\n#. TRANSLATORS: Quest text spoken by Farmer\n#: Source/textdat.cpp:618\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Думаю, мажліва вы маглі б мне дапамагчы, але можа калі станеце зусім крыху \"\n\"мацнейшымі. Я б не хацеў шкодзіць адзінай надзеі вёсцы, што можа знішчыць \"\n\"пагрозу ў царкве!\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:620\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Я, я сваімі сіламі стаў каровай. Зрабі з сябе што-небудзь... тады і \"\n\"пагаворым.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:622\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"І зусім не трэба мне вытлумачвацца перад кожным прахожым турыстам! Ці табе \"\n\"не трэба было там пачвар біць? Можа потым пагаворым. Калі дажывеш...\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:624\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Годзе мяне турбаваць. Я шукаю нешта сапраўды геройскае. І гэта не ты. Як мне \"\n\"табе давяраць, цябе могуць зжэрці монстры хоць сёння...  Мне патрэбен \"\n\"дасведчаны герой.\"\n\n#. TRANSLATORS: Quest text spoken by Complete Nut\n#: Source/textdat.cpp:626\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Добра, годзе заліваць. Не хацеў збіць цябе з тропу. Сяджу я дома, на душы \"\n\"смууутна, аж раптам усё стала няў-стоойліва, з падлогі вылез цэлы статак \"\n\"пачвар! Я аж замыкаў са страху. І так ужо сталася, што я быў апрануты ў гэты \"\n\"Джэрсі, калі ўцякаў за дзверы, і цяпер выглядаю зусім недарэчна. Была б у \"\n\"мяне якая іншая вопратка, не было б так дрэнна. Слухай! А можа сходзіш да \"\n\"маёй хаты і возьмеш мне мой касцюм? Толькі карычневы, не шэры, яго я на \"\n\"вечар надзяю. Я б і сам схадзіў, але не хачу, каб мяне бачылі такога. Вось, \"\n\"на, можа прыгадзіцца… Каб прыбіць усё, чым там зарасло. Маю хату не \"\n\"прапусціш. Проста на поўдзень адтуль, дзе рака разгаліноўваецца… Ну… Дзе там \"\n\"зарослы агарод.\"\n\n#. TRANSLATORS: Quest text spoken by Unknown, Maybe Farmer\n#: Source/textdat.cpp:628\nmsgid \"\"\n\"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n\"landed two new subspecies of flying horror; a good day's work.  Must \"\n\"remember to order some more bat guano and black candles from Adria; I'm \"\n\"running a bit low.\"\nmsgstr \"\"\n\"Сёння халадней, і хмар больш. Закінутыя ў пустату сеткі некрамансіі злавілі \"\n\"два новыя падвіды лятучага жаху, слаўна сёння паработаў. Трэба не забыць \"\n\"заказаць яшчэ кажанова калу і чорных свечак у Эйдрыі. Патраціліся мае запасы.\"\n\n#. TRANSLATORS: Quest text read aloud from book\n#: Source/textdat.cpp:630\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Чары, пагрозы, адрачэнне, торг, усё спрабаваў – марна. Мае метады \"\n\"паняволення меншых дэманаў не дзейнічаюць на гэтую жудасную пачвару, зусім.\"\n\n#. TRANSLATORS: Quest text read aloud from book\n#: Source/textdat.cpp:632\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Мой дом павольна глуміцца поганню яго непажаданага вязня. Крыпты поўняцца \"\n\"ценямі, што рушаць па-за вугламі майго зроку. На краі майго слыху ціха \"\n\"скрабуцца ў танцы кіпцюры. Яны шукаюць, думаецца мне, гэты дзённік.\"\n\n#. TRANSLATORS: Quest text read aloud from book\n#: Source/textdat.cpp:634\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"У рове стварэння прамільгнула яго імя — На-Крул. Я сіліўся даследаваць гэтае \"\n\"імя, але меншыя дэманы нейкім чынам знішчылі маю бібліятэку. На-Крул... \"\n\"Гэтае імя ўсяляе ва мне халодную жудасць. Палічу за лепшае думаць аб ім \"\n\"толькі як аб Стварэнні, не разважаючы пра яго сапраўднае імя.\"\n\n#. TRANSLATORS: Quest text read aloud from book\n#: Source/textdat.cpp:636\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Шалёнае выццё палоннага не дае мне спаць, як моцна бы я ні хацеў. Яно лютуе \"\n\"супраць таго, хто паслаў яго ў Пустату, і выкрыквае на мяне агідныя праклёны \"\n\"за сваё зняволенне. Яго словы поўняць маё сэрца жахам, але ж заглушыць яго \"\n\"голас я не магу.\"\n\n#. TRANSLATORS: Quest text read aloud from book\n#: Source/textdat.cpp:638\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Час хутка скончваецца. Я мушу запісаць спосаб, як аслабіць дэмана, і потым \"\n\"схаваць гэты тэкст, каб яго прыслужнікі не скарысталі мае веды, каб \"\n\"вызваліць свайго валадара. Спадзяваюся, што той, хто знойдзе гэты дзённік, \"\n\"адшукае тыя веды.\"\n\n#. TRANSLATORS: Quest text read aloud from book\n#: Source/textdat.cpp:640\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Таму, хто знойдзе гэты скрутак, даручаецца спыніць дэманічнае стварэнне, што \"\n\"мяшкае ў гэтых сценах. Мой час мінуў. Нават цяпер, яго пякельныя прыслужнікі \"\n\"скрабуцца ў крохкія дзверы, за якімі я схаваўся.\\n\"\n\"\\n\"\n\"Я затрымаў дэмана таемнаю магіяю і замкнуў ў вялікіх сценах, але я страшуся, \"\n\"што гэтага не стане.\\n\"\n\"\\n\"\n\"Чары, якія знаходзяцця ў трох маіх грымуарах, дазволяць бяспечна ўвайсці ў \"\n\"яго ўладанні, але толькі калі выкарыстаны ў правільным парадку. Рычагі пры \"\n\"ўваходзе здымуць бар'еры і вызваляць дэмана. Не руш іх! Карыстайся толькі \"\n\"тымі чарамі, каб трапіць унутр, альбо яго сіла будзе неадольнаю.\"\n\n#. TRANSLATORS: Quest text read aloud from book by player\n#: Source/textdat.cpp:642 Source/textdat.cpp:645 Source/textdat.cpp:648\n#: Source/textdat.cpp:651 Source/textdat.cpp:654\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#. TRANSLATORS: Quest text read aloud from book by player\n#: Source/textdat.cpp:643 Source/textdat.cpp:646 Source/textdat.cpp:649\n#: Source/textdat.cpp:652 Source/textdat.cpp:655\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#. TRANSLATORS: Quest text read aloud from book by player\n#: Source/textdat.cpp:644 Source/textdat.cpp:647 Source/textdat.cpp:650\n#: Source/textdat.cpp:653 Source/textdat.cpp:656\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/towners.cpp:79\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Каваль Грызвальд\"\n\n#: Source/towners.cpp:101\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Карчмар Огдэн\"\n\n#: Source/towners.cpp:110\nmsgid \"Wounded Townsman\"\nmsgstr \"Паранены Гараджанін\"\n\n#: Source/towners.cpp:132\nmsgid \"Adria the Witch\"\nmsgstr \"Ведзьма Эйдрыя\"\n\n#: Source/towners.cpp:141\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Барменка Джыліен\"\n\n#: Source/towners.cpp:172\nmsgid \"Pepin the Healer\"\nmsgstr \"Лекар Піпін\"\n\n#: Source/towners.cpp:189\nmsgid \"Cain the Elder\"\nmsgstr \"Старэйшына Кейн\"\n\n#: Source/towners.cpp:218\nmsgid \"Cow\"\nmsgstr \"Карова\"\n\n#: Source/towners.cpp:242\nmsgid \"Lester the farmer\"\nmsgstr \"Фермер Лэстэр\"\n\n#: Source/towners.cpp:255\nmsgid \"Complete Nut\"\nmsgstr \"Ляснуты\"\n\n#: Source/towners.cpp:264\nmsgid \"Celia\"\nmsgstr \"Сілія\"\n\n#: Source/towners.cpp:277\nmsgid \"Slain Townsman\"\nmsgstr \"Забіты Гараджанін\"\n\n#: Source/trigs.cpp:343\nmsgid \"Down to dungeon\"\nmsgstr \"Уніз у падзямелле\"\n\n#: Source/trigs.cpp:354\nmsgid \"Down to catacombs\"\nmsgstr \"Уніз у катакомбы\"\n\n#: Source/trigs.cpp:364\nmsgid \"Down to caves\"\nmsgstr \"Уніз у пячоры\"\n\n#: Source/trigs.cpp:374\nmsgid \"Down to hell\"\nmsgstr \"Уніз у пекла\"\n\n#: Source/trigs.cpp:386\nmsgid \"Down to Hive\"\nmsgstr \"Уніз у Вулей\"\n\n#: Source/trigs.cpp:398\nmsgid \"Down to Crypt\"\nmsgstr \"Уніз у Склеп\"\n\n#: Source/trigs.cpp:414 Source/trigs.cpp:494 Source/trigs.cpp:541\n#: Source/trigs.cpp:636\nmsgid \"Up to level {:d}\"\nmsgstr \"Наверх на ўзровень {:d}\"\n\n#: Source/trigs.cpp:416 Source/trigs.cpp:471 Source/trigs.cpp:523\n#: Source/trigs.cpp:602 Source/trigs.cpp:619 Source/trigs.cpp:666\nmsgid \"Up to town\"\nmsgstr \"Наверх у горад\"\n\n#: Source/trigs.cpp:427 Source/trigs.cpp:505 Source/trigs.cpp:558\n#: Source/trigs.cpp:583 Source/trigs.cpp:648\nmsgid \"Down to level {:d}\"\nmsgstr \"Уніз на ўзровень {:d}\"\n\n#: Source/trigs.cpp:439\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Наверх на ўзровень Склепа {:d}\"\n\n#: Source/trigs.cpp:454\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Уніз на ўзровень Склепа {:d}\"\n\n#: Source/trigs.cpp:570\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Наверх на ўзровень Гнязда {:d}\"\n\n#: Source/trigs.cpp:679\nmsgid \"Down to Diablo\"\nmsgstr \"Уніз да Д'ябла\"\n\n#: Source/trigs.cpp:712 Source/trigs.cpp:726 Source/trigs.cpp:740\nmsgid \"Back to Level {:d}\"\nmsgstr \"Назад да ўзроўню {:d}\"\n"
  },
  {
    "path": "Translations/bg.po",
    "content": "# Translation of DevilutionX to Bulgarian\n# Nikolay Popov <nikolai.popovz@gmail.com>, 2021.\n# @Krezzin, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:19+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Nikolay Popov <nikolai.popovz@gmail.com>\\n\"\n\"Language-Team: Nikolay Popov <nikolai.popovz@gmail.com>; Zakxaev68 / \"\n\"Krezzin\\n\"\n\"Language: bg\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Идея и дизайн на играта\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Старши дизайнери\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Допълнителен дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Главен програмист\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Старши програмисти\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Програмиране\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Специални гост-програмисти\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Програмиране на Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Програмиране на сериини комуникации\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Програмиране на инсталатор\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Художествени директори\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Художествено оформление\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Техническо художествено оформление\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Кинематографични Художествени директори\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D кинематографично художествено оформление\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Кинематографично техническо оформление\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Изпълнителен продуцент\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Продуцент\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Асистент продуцент\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Музика\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Звуков дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Кинематографична музика и звук\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Гласова продукция, режисура и кастинг\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Сценарий и история\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Редактиране на диалог\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Гласове\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Инженер по звукозапис\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Дизайн и оформление на ръководство\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Художествено оформление на ръководство\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Временен директор по качеството (водещ изпитател)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Екип по осигуряване на качеството (изпитатели)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Екип за специални операции на QA (изпитатели за съвместимост)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA Артилерийска поддръжка (допълнителни изпитатели) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA Контраразузнаване\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Орден на мрежови информационни услуги\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Поддръжка на клиенти\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Продажби\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Бек вокалисти на г-н Дабири\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Връзки с обществеността\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Маркетинг\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Международни продажби\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Продажби в САЩ\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Производство\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Правни и бизнес въпроси\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Специални благодарности на\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Благодарение на\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"В памет на\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Специални благодарности на\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Генерален мениджър\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Софтуерно инженерство\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Художествен директор\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Художници\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Звуков дизайн, специални ефекти и аудио инженеринг\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Ръководител по осигуряване на качеството\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Изпитатели\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Ръководство\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tДопълнителна работа\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Оформяне на текстове за приключенията\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Благодарности на\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tСпециални благодарности на Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Мениджър по осигуряване на качеството\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Водещ изпитател за осигуряване на качеството\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Основни изпитатели\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Допълнителни изпитатели\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Мениджър продуктов маркетинг\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Мениджър връзки с обществеността\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Асистент продуктов мениджър\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Пръстенът на хилядата\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tПри създаването на тази игра не е продадена нито една душа.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"Добре\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Изберете клас\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Отказ\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Нов герой за Групова игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Нов герой за Единична игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Запис вече съществува\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Зареди игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Нова игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Герои за Единична игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Разбойникът и Магьосникът са достъпни само в пълната версия на играта. \"\n\"Посетете https://www.gog.com/game/diablo, за да я закупите.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Въведете име\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Неправилно име. Името не може да съдържа интервал, специални символи или \"\n\"непозволени думи.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Не е възможно създаването на герой.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Ниво:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Сила:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Магия:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Сръчност:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Жизненост:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Номер запис:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Изберете герой\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Нов герой\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Изтрий\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Герои за Групова игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Изтрий Герой за Групова игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Изтрий Герой за Единична игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Наистина ли искате да изтриете героя \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Единична игра\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Групова игра\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Настройки\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Поддръжка\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Виж създателите\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Изход от Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Изход от Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Пробна версия\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Клиент-сървър (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"Обратна връзка\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Групова игра\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Изисквания:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"\"\n\"не е необходим\\n\"\n\"регион\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Изберете връзка\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Промяна на регион\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Всички компютри трябва да са свързани с TCP-съвместима мрежа.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Всички компютри трябва да са свързани с интернет.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Играй в единична игра, без достъп до интернет.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Брой играчи: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo пробна версия\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire пробна версия\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Домакинът играе различна игра, в сравнение с Вас.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Домакинът играе различен игрови режим ({:s}), в сравнение с Вас.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Вашата версия {:s} не съвпада с тази на домакина {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Описание:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Изберете действие\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Нова игра\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Нова публична игра\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Влез в игра\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Публична игра\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Зареждане...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Няма\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ОТКАЗ\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Създайте игра с трудност по Ваш избор.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"Създайте публична игра с трудност по Ваш избор.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Въведете Game ID за да се присъединете към игра.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Въведете IP или hostname и се присъединете към текущата игра.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"\"\n\"Присъединете към текущата публична игра.\\n\"\n\".\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Нормалнa\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Кошмарнa\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Адска\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Трудност: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Скорост: Нормална\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Скорост: Бърза\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Скорост: По-бърза\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Скорост: Най-бърза\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Играчи: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Изберете трудност\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Присъедини се към {:s} игри\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Въведете Game ID\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Въведете адрес\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нормална трудност\\n\"\n\"Тук начинаещия герой започва своето приключение да срази Диабло.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Кошмарна трудност\\n\"\n\"Обитателите на Лабиринта са по-силни и ще бъдат по-голямо предизвикателство. \"\n\"Препоръчително за герои които имат опит.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Адска трудност\\n\"\n\"Най-могъщите адски същества се таят пред портите на Преизподнята. Само най-\"\n\"опитните герой могат да се осмелят да поемат този риск.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Вашият герой трябва да достигне ниво 20, преди да можете да се присъедините \"\n\"към игра от Кошмарна трудност.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Вашият герой трябва да достигне ниво 30, преди да можете да се присъедините \"\n\"към игра от Адска трудност.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Изберете скорост\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Бърза\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"По-бърза\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Най-бърза\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нормална скорост\\n\"\n\"Тук начинаещия герой започва своето приключение да срази Диабло.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Бърза скорост\\n\"\n\"Обитателите на Лабиринта са ускорени и ще бъдат по-голямо предизвикателство. \"\n\"Препоръчително за герои които имат опит.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"По-бърза скорост\\n\"\n\"Повечето чудовища от подземието ще Ви издирят по-бързо от когато и да било. \"\n\"Само опитни герои могат да изпробват късмета си на тази скорост.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Най-бърза скорост\\n\"\n\"Слуги на подземното царство ще нападат изненадващо и без задръжки. Само \"\n\"някой със светкавични рефлекси би се справил с това темпо.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Въведи парола\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Режим Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Режим Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Да\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Не\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\n#, fuzzy\n#| msgid \"Press any key to change.\"\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Зададете нов клавиш.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Зададен клавиш:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Зададете нов клавиш.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Освободете клавиш\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Предишно меню\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Поддържаме чат сървър на Discord.gg/devilutionx Следвайте връзката за да се \"\n\"присъедините към нашата общност където дискутираме всичко свързано с Diablo \"\n\"и допълнението Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX е поддържан от Diasurgical, сведения за проблеми и бъгове могат \"\n\"да бъдат докладвани на: https://github.com/diasurgical/devilutionX За да \"\n\"предложим по-добро качество на продукта, моля, посочете номер на версията, \"\n\"операционна система и естеството на проблема.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Отказ от отговорност:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX не е обвързан и/или поддържан от Blizzard Entertainment, нито \"\n\"от GOG.com. Blizzard Entertainment или GOG.com не са изпитали или \"\n\"сертифицирали качеството и съвместимостта на DevilutionX. Всички Въпроси за \"\n\"DevilutionX трябва да бъдат насочени към Diasurgical, и не към Blizzard \"\n\"Entertainment или GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tТози порт използва шрифтовете Charis SIL, New Athena Unicode, Unifont, и \"\n\"Noto лицензирани под SIL Open Font License, както и Twitmoji лицензирани под \"\n\"CC-BY 4.0. Този порт използва също SDL, лицензиран под zlib-license. Виж \"\n\"ReadMe (ПрочетиМе) за повече информация.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Запазени права © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Грешка\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Изглежда има грешка в {:s} при ред {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Грешка при прочитане на данни от файл\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Неуспешно прочитане на водещ файлов архив ({:s}).\\n\"\n\"\\n\"\n\"Уверете се, че се съответният се намира в папката на играта.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Грешка при отваряне на папка с зададен достъп само за четене\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Неуспешно записване в директория:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Игра: \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"Обратна връзка\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Парола: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Публична игра\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Ниво: Свърталище {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Ниво: Гробница {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Град\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Ниво: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Информация за персонажа\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Приключенски дневник\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Автоматична карта\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Главно меню\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Инвентар\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Книга за Заклинания\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Изпрати съобщение\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\n#, fuzzy\n#| msgid \"Description:\"\nmsgid \"Description: \"\nmsgstr \"Описание:\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\n#, fuzzy\n#| msgid \"Players: \"\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"Играчи: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to buy this item?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Наистина ли искате да купите този предмет?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\n#, fuzzy\n#| msgid \"Amber\"\nmsgid \"<number>\"\nmsgstr \"Кехлибарени\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\n#| msgctxt \"monster\"\n#| msgid \"Flayed One\"\nmsgid \"<player name>\"\nmsgstr \"Кожодер\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Приятелска игра\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Враждебна игра\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Бърз клавиш: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Бутон за избор на текущо заклинание\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Бърз Клавиш: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Умение\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Заклинание\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Заклинание Ниво 0 - Неизползваемо\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Заклинание Ниво {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Свитък на {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Свитък\"\nmsgstr[1] \"{:d} Свитъци\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Жезъл на {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Заряд\"\nmsgstr[1] \"{:d} Заряди\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} златна монета\"\nmsgstr[1] \"{:s} златни монети\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Изискванията не са покрити\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Ниво: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Точки живот {:d} от {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Десен клик за използване\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Ново ниво\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Имате {:s} златна монета. Колко искате да отделите?\"\nmsgstr[1] \"Имате {:s} златни монети. Колко искате да отделите?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Градски портал\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"от {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Портал до\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Нечестивия олтар\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"Ниво 15 \"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Неуспешно зареждане на герой\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Показване на това съобщение и изход\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Показване на версията и изход\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Посочете местонахождението на diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Посочете папката с записните файлове\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Посочете папката с файл diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Пропускане на началните видеа\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Показване на индикатор за кадри в секунда\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Използване на подробно регистриране на команди\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Записване на демо файл\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Репродуциране на демо файл\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Забраняване на всички лимити на кадри при репродукция\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Избор на игра:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Принудителен режим Пробна версия\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Принудителен режим Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Принудителен режим Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Настройки на Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"\"\n\"Докладвайте несъответствия на https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Неуспешно зареждане на ресурси за интерфейса.\\n\"\n\"\\n\"\n\"Уверете се, че файлът devilutionx.mpq е в папката на играта и е актуален.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Мрежово прекъсване --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Изчакване на играчи --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Не е намерен помощен файл\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"докато сте в магазин\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Предмет от колана {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Използване на предмет от колана.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Бързо заклинание {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Клавиш за умение или заклинание.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Предишно меню\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Бързо заклинание {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Бързи Заклинания\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Отваряне на листа с бърз достъп до заклинанния.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Бърз Запис\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Записва текуща игра.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Бързо Зареждане\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Зарежда запис.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Изход от играта\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Затваря играта.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Спри герой\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Спира героя и прекратява всички предстоящи действия.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Показване на предмети\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Подчертава/скрива предмети на пода.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Постоянно показване на предмети\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Подчертаването/скриването предмети на пода е за постоянно.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Включи авто-карта\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Включва показването на авто-карта.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Отваряне на инвентар.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Герой\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Отваряне на прозорец с информация за персонажа.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Задачи\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Q: Отваряне на Приключенски дневник.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Книга за Заклинания\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Отваряне на книга с заклинания.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Бързо съобщение {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Изпрати бързо съобщение в чата.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Скриване Инфо Екрани\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Скриване на всички информационни екрани.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Мащабиране\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Мащабиране на екрана.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Пауза\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Паузира играта.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Пауза\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Увеличаване яркостта на екрана.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Намаляване яркоста на екрана.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Увеличаване яркостта на екрана.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Увеличаване яркостта на екрана.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Помощ\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Помощен диалог.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Снимка Екран\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Прави снимка на текущия екран на играта.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Игрова информация\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Показва информация на играта.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Чат регистър\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Показва регистър на чат съобщенията.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Инвентар\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"Изберете действие\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"Изберете действие\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"Отказ\"\n\n#: Source/diablo.cpp:2175\n#, fuzzy\n#| msgid \"Closes the game.\"\nmsgid \"Close menus.\"\nmsgstr \"Затваря играта.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"Герои за Групова игра\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"Герои за Групова игра\"\n\n#: Source/diablo.cpp:2212\n#, fuzzy\n#| msgid \"$Movement:\"\nmsgid \"Move left\"\nmsgstr \"$Движение:\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"Герои за Групова игра\"\n\n#: Source/diablo.cpp:2218\n#, fuzzy\n#| msgid \"the night\"\nmsgid \"Move right\"\nmsgstr \"Нощта\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"Герои за Групова игра\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Автоматична карта\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\n#, fuzzy\n#| msgid \"The game ended\"\nmsgid \"Toggle game menu\"\nmsgstr \"Играта приключи\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Saves the game.\"\nmsgid \"Opens the game menu.\"\nmsgstr \"Записва текуща игра.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"Огнена вълна\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Мрежовата функция не е достъпна в демонстрационната версия\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Грешка при създаване на Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Не е налично в пробната версия\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Няма достатъчно място за направата на запис\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Прекъсването на играта не е позволено в града\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Препоръчително е копирането върху хард-диск\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Проблем с мрежовото синхронизиране\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Пауза не е позволена в групова игра\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Запазване...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Някои линеят, докато едно расте силно\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Нова сила е сътворена чрез разруха\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Който брани, рядко атакува\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Мечът на справедливостта е бърз и остър\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Тялото заяква, докато духът е бдителен\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Мощта на пренасочената мана я подновява\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Времето не може да отслаби мощта на стоманата\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Магията не винаги е това което изглежда\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Каквото е било отворено, сега е затворено\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Усилието идва на цената на проникновението\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Тайнствената сила носи разруха\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Онова, което не може да се държи, не може да се повреди\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Ален и Лазурен се превръщат като слънцето\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Знание и мъдрост на цената на живеца\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Пий и изпитай бодростта\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Където отидеш, там оставаш\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Енергията идва на цената на мъдростта\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Богатство идва когато най-малко го очакваш\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"\"\n\"Там, където скъперничеството се проваля, търпението носи възнаграждения\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Благословен от доброжелателен спътник!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Човешките дела могат да бъдат направлявани от съдбата\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Силата е подсилена с небесна воля\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Естеството на живота идва от вътре\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Пътят се вижда по-ясно, бидейки гледан от високо\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Избавлението идва с цената на мъдростта\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Загадките разбулва светлината на логиката\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Изостаналите все пак могат и да са първи\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Щедростта носи своите ползи\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Трябва да сте поне ниво 8, за да използвате това.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Трябва да сте поне ниво 13, за да използвате това.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Трябва да сте поне ниво 17, за да използвате това.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Усвоено бе тайнствено знание!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Това, което не те убива...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Знанието е сила.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Дай и ще получиш.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Малко опит се усвоява чрез допир.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Няма друго място като у дома.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Духовната сила е възстановена.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Чувстваш се по-сръчен.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Чувстваш се по-силен.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Чувстваш се по-мъдър.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Чувстваш се по-здрав.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Чупливото ще се счупи.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Катедрала\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Катакомби\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Пещери\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Свърталище\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Крипта\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Нв {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} трудност\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"В меню\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"Обратна връзка\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Свързването e невъзможно\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"грешка: прочетени 0 байта от сървъра\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq или spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Някой MPQ файловете от Hellfire липсват.\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Не всички Hellfire MPQ файлове бяха намерени.\\n\"\n\"Моля, поставете всички hf*.mpq файлове.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Разделителна способност\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Бърз ход в града\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Задача Търсенето на Тео\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Задача Кравешка мисия\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Авто взимане на злато\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Авто взимане на Еликсир\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\n#| msgid \"Auto Gold Pickup\"\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Авто взимане на злато\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Авто взимане на предмети в града\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Адрия пълни Мана\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Авто-екипиране на оръжия\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Авто-екипиране на брони\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Авто-екипиране на шлемове\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Авто-екипиране на щитове\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Авто-екипиране на накити\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Произволни Задачи\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\n#, fuzzy\n#| msgid \"Show mana values\"\nmsgid \"Show Item Labels\"\nmsgstr \"Покажи стойности мана\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Авто-пълнене на колан\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Забрани Увреждащи светилища\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Авто-взимане лечение\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Авто-взимане пълно лечение\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Авто-взимане мана\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Авто-взимане пълна мана\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Авто-взимане възобновление\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Авто-взимане пълно възобновление\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Настройки\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Запази игра\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Главно меню\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Изход от играта\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Гама\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Скорост\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Изключена музика\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Звук\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Изключен Звук\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Пауза\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Бързи клавиши:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Помощен диалог\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Главно меню\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Авто-карта\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Скриване на всички информационни екрани\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Отваряне на книга с магии за бърз достъп\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Отваряне на книга с заклинания\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Отваряне на инвентар\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Отваряне на прозорец с информация за персонажа\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Отваряне на Приключенски дневник\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Намаляване яркоста на екрана\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Увеличаване яркостта на екрана\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Мащабиране на екрана\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Мащабиране на картата\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Използване на предмет от колана\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Задаване на бърз клавиш за умение или заклинание\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Left Mouse Button: Замахване в неподвижно състояние\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Left Mouse Button (в прозореца на персонажа): Усвояване на всички \"\n\"точки за усъвършенстване\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Left Mouse Button (в инвентара): Преместване на предмет в колана или \"\n\"въоръжаване/разоръжаване на предмет\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\"Shift + Left Mouse Button (в колана): Преместване на предмет в инвентара\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Движение:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Ако задържите бутона на мишката, вашият герой ще се придвижи в съответната \"\n\"посока.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Битка:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Задръжте клавиша Shift и натиснете ляв бутон на мишката, за да замахвате, \"\n\"докато сте неподвижни.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Авто-карта:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"За да включите картата,натиснете бутона 'КАРТА' на информационната ивица или \"\n\"натиснете клавиша 'TAB' на клавиатурата. Мащабирането на картата е чрез \"\n\"клавишите + и -.Отместването е чрез клавишите за посока.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Взимане на Предмети:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Използваемите предмети, които са малки по размер, като например отвари и \"\n\"свитъци, автоматично преминават в 'колана', намиращ се в горната ивица на \"\n\"интерфейса. А когато предмет бъде поставен в колана, върху иконката му \"\n\"излиза цифра Предметите могат да бъдат ползвани чрез десен бутон мишката или \"\n\"съответната цифра на клавиатурата.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Злато:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Може да изберете колко злато искате да оставите, като натиснете десен бутон \"\n\"върху купчината златни монети в инвентара.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Умения & Заклинания:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Можете да получите достъп до списъка си с умения и заклинания, като кликнете \"\n\"с левия бутон на мишката върху бутона 'ЗАКЛ' върху интерфейса. Тук са \"\n\"изброени научените заклинания и тези, които са достъпни чрез жезли. \"\n\"Натискането на левия бутон на мишката върху заклинанието, което желаете да \"\n\"използвате, ще го подготви. Подготвеното заклинание може да бъде изречено \"\n\"чрез кликване с десния бутон на мишката в игралната зона.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Използване на Бърз списък за Заклинания:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Натискане с левия бутон на мишката върху бутона 'Подготвено заклинание' ще \"\n\"отвори 'Бърз лист', която ви позволява да изберете умение или заклинание за \"\n\"незабавна употреба.  За да използвате Подготвеното умение или заклинание, \"\n\"просто натиснете с десния бутон на мишката в основната игрална зона.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Бутон Shift + Ляв бутон на мишката върху бутона 'Подготвено заклинание' ще \"\n\"изчисти подготвеното заклинание. \"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Задаване бързи клавиши за заклинания\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Може да зададете до четири бързи клавиша за умения, заклинания или свитъци. \"\n\"Започнете с отварянето на 'бърз лист' както е обяснено в горния абзац. \"\n\"Натиснете клавиши F5, F6, F7 или F8 след като посочите заклинанието което \"\n\"искате да зададете.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Книги със Заклинания\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Четенето на повече от една книга за едно и също заклинание, прави същото по-\"\n\"ефикасно.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Помощ за пробна версия на Hellfire\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Помощ за Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Помощ за пробна версия на Diablo\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Помощ за Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"\"\n\"Наиснете ESC, за да прекъснете или клавишните стрелки за да превъртите.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Невъзможно създаването на основен прозорец\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Масло на Точността\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Масло на Майсторството\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Масло на Остротата\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Масло на Смъртта\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Масло на Умението\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Ковашко масло\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Масло на Крепкостта\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Масло на Неизменността\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Масло на Втвърдяването\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Масло на Непробиваемостта\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} на {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} на {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} на {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} на {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"увеличава\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"шанса за попадение на оръжието\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"значително увеличава шанса\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"за попадение на оръжието\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"потенциал за щети\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"значително увеличава\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"потенциала за щети - изкл. лъкове\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"намалява нужните атрибути\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"използва се в/у брони и оръжия\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"възстановява 20% от\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"здравината на предмета\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"увеличава\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"текуща и макс здравина на предмета\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"прави предмет неразрушим\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"увеличава клас на бронята\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"на брони и щитове\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"значително увеличава клас на бронята\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"на брони и щитове\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"залага огнена клопка\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"залага мълниена клопка\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"залага вкаменяваща клопка\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"напълно възстановява живот\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"частично възстановява живот\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"частично възстановява мана\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"напълно възстановява мана\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"увеличава сила\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"увеличава магия\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"увеличава сръчност\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"увеличава жизненост\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"частично възстановява живот и мана\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"напълно възстановява живот и мана\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Десен клик за поглед\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Десен клик за използване\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Десен клик за прочитане,\\n\"\n\"следван от ляв клик върху цел\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Десен клик за прочитане\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Активиране за поглед\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Отворете инвентар за да използвате\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Активиране за използване\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Изберете от книгата със заклинания,\\n\"\n\"след това изричане на заклинанието за прочит\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Активиране за прочит\"\n\n#: Source/items.cpp:1800\n#, fuzzy, c++-format\n#| msgid \"Activate to view\"\nmsgid \"{} to view\"\nmsgstr \"Активиране за поглед\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\n#| msgid \"{:+d} to strength\"\nmsgid \"{} to use\"\nmsgstr \"{:+d} към сила\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Изберете от книгата със заклинания,\\n\"\n\"след това изричане на заклинанието за прочит\"\n\n#: Source/items.cpp:1811\n#, fuzzy, c++-format\n#| msgid \"Activate to read\"\nmsgid \"{} to read\"\nmsgstr \"Активиране за прочит\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Ниво: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Удвоява лимит на златото\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Необходими:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Сила\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Маг\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Сръч\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Книга на {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Ухо на {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"шанс за удар: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% щети\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"шанс удар: {:+d}%, {:+d}% щети\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% броня\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"клас броня: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Устойчивост Огън: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Устойчивост Огън: {:+d}%\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Устойчивост Мълния: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Устойчивост Мълния: {:+d}%\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Устойчивост Магия: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Устойчивост Магия: {:+d}%\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Устойчивост Всичко: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Устойчивост Всичко: {:+d}%\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"заклинанията са увеличени с {:d} ниво\"\nmsgstr[1] \"заклинанията са увеличени с {:d} нива\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"заклинанията са намалени с {:d} ниво\"\nmsgstr[1] \"заклинанията са намалени с {:d} нива\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"нива на заклинания непроменени (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Допълнителни заряди\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} заряд\"\nmsgstr[1] \"{:d} {:s} заряди\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Щети Огнен Удар: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Щети Огнен Удар: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Щети Мълниен Удар: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Щети Мълниен Удар: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} към сила\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} към магия\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} към сръчност\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} към жизненост\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} към всички атрибути\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} щети от врагове\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Живот: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Мана: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"висока издържливост\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"понижена издържливост\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"неразрушими\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% светлинен радиус\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% светлинен радиус\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"множество стрели при изстрел\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"щети огнени стрели: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"щети огнени стрели: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"щети мълнийни стрели {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"щети мълнийни стрели {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"щети огненo кълбо {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"щети огнено кълбо {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"атакуващият получава 1-3 щети\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"играчът губи всичката мана\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"поглъща половината щети от капани\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"избутва целта назад\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% щети срещу демони\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Всички устойчивости са 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"удар отнема 3% мана\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"удар отнема 5% мана\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"удар отнема 3% жизненост\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"удар отнема 5% жизненост\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"пробива бронята на врага\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"ускорен замах\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"бърз замах\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"по-бърз замах\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"най-бърз замах\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Друга способност (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"бързо възстановяване от удар\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"по-бързо възстановяване от удар\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"най-бързо възстановяване от удар\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"бързо блокиране\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"добавя {:d} точка към щети\"\nmsgstr[1] \"добавя {:d} точки към щети\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"изстрелва стрели със случайна скорост\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"необичайни щети за тип предмет\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"променена издръжливост\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"меч за една ръка\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"постоянно губене на живот\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"изсмукване на живот\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"няма изисквания за сила\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"мълнийни щети: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"мълнийни щети: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"светкавични заряди при удар\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"случайни тройни щети\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"разпадащи се {:+d}% щети\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x щети за чуд., 1x за играч\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Произволни 0 - 600% щети\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"ниска изд., {:+d}% щети\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"допълнително КБ с/у демони\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"допълнително КБ с/у немъртви\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Мана пренесена в Живот\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Живот пренесен в Мана\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"щети: {:d}  Неразрушими\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"щети: {:d}  Изд: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"щети: {:d}-{:d}  Неразрушим\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"щети: {:d}-{:d}  Изд: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"броня: {:d}  Неразрушим\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"броня: {:d}  Изд: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Заряди: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"уникат\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Неразпознат\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Леговището на Краля на скелетите\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Камера на Костите\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Лабиринт\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Отровения извор\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Убежището на Архиепископ Лазар\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\n#| msgid \"Hellfire\"\nmsgid \"Hell Arena\"\nmsgstr \"Hellfire\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Надолу към Подземието\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Надолу към Катакомбите\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Надолу към Пещерите\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Надолу към Ада\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Надолу към Свърталището\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Надолу към Криптата\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Нагоре към ниво {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Нагоре към Града\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Надолу към ниво {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Надолу към Диабло\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Нагоре към Свърталище ниво {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Нагоре към Крипта ниво {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Основоположният камък на Света\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Надолу към Крипта ниво {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Нагоре към Ниво {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Невъзможно отваряне на файл за запис\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Невалиден файлов запис\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Играчът е на ниво само за Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Невалидно игрово състояние\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Невъзможно да се покаже главно меню\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Животно\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Демон\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Немъртъв\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Тип: {:s}  Убити: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Всичко убити: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Точки живот: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Няма магическа устойчивост\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Устойчивост:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Магия\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Огън\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Мълния\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Имунитет:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Тип: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Няма устойчивости\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Няма имунитети\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Някакви Магически Устойчивости\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Някакви Магически Имунитети\"\n\n#: Source/mpq/mpq_writer.cpp:174\n#, fuzzy\n#| msgid \"Failed to open stash archive for writing.\"\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Неуспешно отваряне на файла на склада за запис.\"\n\n#: Source/msg.cpp:1701\n#, fuzzy, c++-format\n#| msgid \"{:s} has cast an illegal spell.\"\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} е направил непозволено заклинание.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} е направил непозволено заклинание.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Играч '{:s}' (ниво {:d}) се присъедини към играта\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Играта приключи\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Невъзможно да получи данни за ниво\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Играч '{:s}' напусна играта\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Играч '{:s}' уби Диабло и напусна играта!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Играч '{:s}' отпадна заради прекъсване\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Играч '{:s}' (ниво {:d}) в вече в играта\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Мистериозно\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Прикрит\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Мрачно\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Особени\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Магическо\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Каменено\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Религиозно\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Омагьосано\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Чудно\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Очарователно\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Загадъчно\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Ужасно\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Свръхестествено\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Божествено\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Свещени\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Неприкосновено\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Духовно\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Призрачно\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Изоставено\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Зловещо\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Тихо\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Усамотено\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Инкрустирано\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Мъждеещо\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Опозорено\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Мазно\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Ярко\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Просещо\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Искрящо\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Блещукащо\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Слънчево\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Мърфово\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Великия Сблъсък\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Възмездието на Греха е Война\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Историята на Хорадрим\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Тъмното Изгнание\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Войната на Греха\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Запечатването на Тримата\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Царствата Отвъд\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Историята на Тримата\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Черния Крал\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Дневник: Омагьосването\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Дневник: Срещата\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Дневник: Гневния вой\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Дневник: Мощта му расте\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Дневник: На-Крул\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Дневник: Краят\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Книга за заклинания\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Разпнат Скелет\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Лост\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Отворена Врата\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Затворена Врата\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Блокирана Врата\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Древен Том\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Книга на Безчестието\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Черепен Лост\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Митична Книга\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Ковчеже\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Сандък\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Ракла\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Саркофаг\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Лавица за книги\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Библиотека\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Бъчва\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Зародиш\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Урна\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Светилище\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Скелетен Том\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Библиотечен Том\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Кръвен Фонтан\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Обезглавено Тяло\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Книга на Слепите\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Книга на Кръвта\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Пречистващ извор\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Броня\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Оръжейна стойка\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Козьо Светилище\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Котел\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Мътен вир\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Фонтан на сълзите\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Стоманен Том\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Педестал от Кръв\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Гъбен мицел\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Ужасяваща стойка\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Повален герой\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} клопка\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (изключено)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"Вкл.\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"Изкл.\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Режим на игра\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Игрови настройки\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Играй Diablo или Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Лимитирай до Пробна версия\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Прави играта съвместима с Пробната версия. Позволява игра в мрежа с \"\n\"потребители които нямат копие на пълната версия на играта.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Начало\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Начални настройки\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Интро\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Покажи Интро видео\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Лого\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Показва логото на създателите\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Лого и Заглавен екран\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Заглавен екран\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Специфични настройки за Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Специфични настройки за Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Звук\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Звукови настройки\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Звук при ход\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Героят издава звук от стъпки при движение.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Звук при Авто-екипиране\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Автоматичното екипиране на снаряжение издава звук.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Звук при взимане на предемет\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Взимането на предмети от пода издава звук.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Честота на сигнала\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Честота на сигнала при изход (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Канали\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Брой на канали при възпроизвеждане.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Размер на буфера\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Размер на буфера (номер на кадри за канал)\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Качество мащабиране звук\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"\"\n\"Качество на мащабиращия алгоритъм за звук, от 0 (най-ниско) to 10 (най-\"\n\"високо).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Тази настройка се отнася базовата разделителна способност на играта и \"\n\"определя границите на поглед. Забележка: Това се различава от разделителната \"\n\"способност на монитора при Мащабиране, цялостно мащабиране, приспособяване \"\n\"към екрана.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\n#, fuzzy\n#| msgid \"Audio Settings\"\nmsgid \"Audio device\"\nmsgstr \"Звукови настройки\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Графика\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Графични настройки\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Пълен екран\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Възпроизвежда играта в режим Прозорец или Пълен екран\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Приспособяване към екран\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Автоматично наглася прозореца на играта да използва вашите текущи настройки \"\n\"на монитора.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Мащабиране\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Включва режим на мащабиране от игровата разделителна способност до тази на \"\n\"вашия монитор. Запазва разделителна способност на екрана и позволява смяна \"\n\"на размер на прозореца.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Филтър мащабиране\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"Включва филтри за подобряване на изображението при мащабиране.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Най-близък пиксел\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Билинеарен\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Анизотропен\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Цялостно мащабиране\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Смяна размера на картината използвайки цели числа за всеки пиксел.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Вертикална синхронизация\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Мълния\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Цветен цикъл\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Включва ефект на цветови цикъл на палетизирани текстури, използван за \"\n\"анимация на вода, лава и киселина.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Алтернативна палитра за Свърталище\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"Играта ще използва алтернативна палитра за Hellfire нивата от Свърталището.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Хардуерен курсор\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Включване на хардуерен курсор\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Хардуерен курсор за предмети\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Използване на хардуерен курсор при графика на предмети.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Макс. размер хардуерен курсор\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Максимална ширина / височина за хардуерния курсор. Големите размери включват \"\n\"обратно софтуерен режим.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Покажи Кадри в секунда (FPS)\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Показва кадрите в секунда в горен ляв ъгъл на екрана.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Игра\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Игрови настройки\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Включи бягане/бързо ходене в града за Diablo и Hellfire. Тази опция се \"\n\"появява за първи път в допълнението на играта.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Захват на мишката\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"При включване мишката е заключена в прозореца на играта.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Включи мисията на Малкото момиче \"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Включи мисията Говежди одежди. Фермера Лестър е заместен от Пълния \"\n\"Откачалник.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Приятелски огън\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Позволява щети от стрели/заклинания между играчи в групова игра дори когато \"\n\"приятелски режим е включен.\"\n\n#: Source/options.cpp:790\n#, fuzzy\n#| msgid \"No pause in multiplayer\"\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Пауза не е позволена в групова игра\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Тествай Бард\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Принуждава героинята Бард да се появи в менюто избор на герой.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Тествай Варварин\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Принуждава героят Варварин да се появи в менюто избор на герой.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Скала Опит\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\"Скала показваща текущо ниво на опит е изобразена в долната част на екрана.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Покажи стойности живот\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"\"\n\"Показва текущи / максимални стойности на живот върху кълбото на живота.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Покажи стойности мана\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"\"\n\"Показва текущи / максимални стойности на живот върху кълбото на маната.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Информация за персонажа\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Скала за Живот на врага\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"\"\n\"Скала показваща текущо ниво на живот на врага е изобразена в горната част на \"\n\"екрана.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Включва автоматично взимане на злато от земята при близост с играча.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Включва автоматично взимане на Еликсири от земята при близост с играча.\"\n\n#: Source/options.cpp:802\n#, fuzzy\n#| msgid \"\"\n#| \"Elixirs are automatically collected when in close proximity to the player.\"\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Включва автоматично взимане на Еликсири от земята при близост с играча.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Автоматичното взимане на предмети от пода когато героя е в града.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Адрия пълни Вашата мана когато разговаряте с нея.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Оръжията ще бъдат автоматично екипирани при взимане или покупка.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Броните ще бъдат автоматично екипирани при взимане или покупка.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Шлемовете ще бъдат автоматично екипирани при взимане или покупка.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Щитовете ще бъдат автоматично екипирани при взимане или покупка.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Накитите ще бъдат автоматично екипирани при взимане или покупка.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Избира случаен набор от всички възможни задачи при нова игра.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Покажи тип на чудовището\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Посочването на чудовище с курсора на мишката показва типът му в \"\n\"информационния блок.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Запълва автоматично колана когато е използван консуматив.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"При Вкл. Котли (Cauldron), Кози светилища (Goat shrine), Очарователни \"\n\"(Fascinating) Неприкосновени (Sacred), Инкрустирани (Ornate) светилища \"\n\"(shrines) не могат да бъдат ползвани и са означени като изключени.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Бързо Заклинание\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Бързите клавиши директно използват заклинанието вместо да сменят подготвено \"\n\"заклинание.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Максимален брой на отвари за лечение за автоматично взимане от пода.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"\"\n\"Максимален брой отвари за пълно лечение за автоматично взимане от пода.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Максимален брой на отвари за мана за автоматично взимане от пода.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"\"\n\"Максимален брой на отвари за пълна мана за автоматично взимане от пода.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Максимален брой на отвари за възобновление за автоматично взимане от пода.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Максимален брой на отвари за пълно възобновление за автоматично взимане от \"\n\"пода.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\nmsgid \"Off\"\nmsgstr \"Обратна връзка\"\n\n#: Source/options.cpp:825\n#, fuzzy\n#| msgid \"Randomize Quests\"\nmsgid \"Random Angles\"\nmsgstr \"Произволни Задачи\"\n\n#: Source/options.cpp:826\n#, fuzzy\n#| msgid \"Vertical Sync\"\nmsgid \"Vertical Only\"\nmsgstr \"Вертикална синхронизация\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Управление\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Настройки за управление\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Мрежа\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Мрежови настройки\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Чат\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Настройки за Чат\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Език\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Избери какъв език да използва играта.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Езикови настройки\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Настойки клавиши\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Настойки клавиши\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping\"\nmsgid \"Padmapping\"\nmsgstr \"Настойки клавиши\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping Settings\"\nmsgid \"Padmapping Settings\"\nmsgstr \"Настойки клавиши\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Настройки\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Ниво\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Опит\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Следващо ниво\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"База\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Сега\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Сила\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Магия\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Сръчност\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Жизненост\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Точки за подобрение\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Злато\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Клас броня\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"шанса за попадение на оръжието\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Щети\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Живот\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"\"\n\" \\n\"\n\"Устойчивости:\\n\"\n\"Магия\\n\"\n\"\\n\"\n\" \"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Огън\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Мълния\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"герой\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"задачи\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"карта\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"mеню\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"инв\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"закл\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"глас\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"ням\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Неизползваемо\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Щети: 1/3 ж.т.цел\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Лекува: {:d}/{:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Щети: {:d}-{:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Умение\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Жезъл ({:d} заряд)\"\nmsgstr[1] \"Жезъл ({:d} заряди)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Ниво {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Мана: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Закл.\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Поразява само немъртви\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Свитък\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Жезъл\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Бърз клавиш за заклинания {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Неуспешно отваряне на архив\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Неуспешно зареждане на герой\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (ниво {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"История на Чата (Съобщения: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} злато\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Колко златни монети искате да изтеглите?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Ниво {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Опит: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Максимално ниво\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Следващо ниво: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} до Ниво {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Гробницата на Крал Леорик\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Залата на Костите\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Мрачен проход\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Неосветения олтар\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Към {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Ела! Нуждая се от помощ!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Следвай ме.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Ето нещо за теб.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Сега ще УМРЕШ!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Благодарение на\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Грисволд\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Пепин\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Огдън\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Кайн\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Фарнам\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Адрия\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Джилиън\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Върт\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Назад\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Щети: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Броня: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Издр.: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"неразрушими\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Добре дошли в\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Работилницата на Ковача\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Искате ли да:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Говорите с Грисволд\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Купите обикновени предмети\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Купите качествени предмети\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Продадете предмети\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Поправите предмети\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Напуснете ателието\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Продавам тези предмети.\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Продавам тези изключителни предмети.\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Нямате нищо, което ми трябва.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Кой предмет е за продажба?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Нямате предмет за поправка.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Кой предмет е за поправка?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Колибата на Вещицата\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Говорите с Адрия\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Купите магически предмети\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Презаредите жезли\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Напуснете Колибата\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Нямате предмет за презареждане.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Кой предмет е за презареждане?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Нямате достатъчно злато\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Нямате достатъчно място в инвентара\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Договорихме ли се?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Наистина ли искате да разпознаете този предмет?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Наистина ли искате да купите този предмет?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Наистина ли искате да презаредите този предмет?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Наистина ли искате да продадете този предмет?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Наистина ли искате да поправите този предмет?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Върт, момчето с дървения крак\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Говорите с Върт\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Имам нещо за продан,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"но това ще ти струва 50 злато\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"само да погледнеш. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Какво имаш?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Кажете довиждане\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Имам този предмет за продан:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Напуснете\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Домът на Лечителя\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Говорите с Пепин\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Напуснете дома на Лечителя\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Градският старейшина\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Говорите с Кайн\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Разпознаване на предмет\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Нямате нищо за разпознаване.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Кой предмет е за разпознаване?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Този предмет е:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Готово\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Говорете с {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Говори с {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"не е налично\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"в пробната\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"версия\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Общи приказки\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Изгряващото слънце\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Говорите с Огдън\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Напуснете гостилницата\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Говорите с Джилиън\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Влезите в Склада\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Пияницата Фарнам\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Говорите с Фарнам\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Кажете довиждане\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Вашето злато: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Поваления жител\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Ковача Грисволд\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Лечителя Пепин\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Ранения жител\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Гостилничаря Огдън\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Старейшината Кайн\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Вещицата Адрия\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Кръчмарката Джилиън\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Крава\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Фермера Лестър\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Селия\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Пълния Откачалник\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Войн\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Разбойник\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Магьосник\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Монах\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Бард\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Варварин\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Зомби\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Таласъм\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Гниещ Труп\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Черна Смърт\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Изпаднал\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Дълбач\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Дяволска Челяд\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Очернен\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Скелет\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Корпус Брадвен\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Горящ Мъртвец\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Кошмар\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Лешояд\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Чумояд\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Звяр от Сенките\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Костодрач\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Корпус Лъков\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Скелет Капитан\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Корпус Капитан\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Горящ Мъртвец Капитан\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Кошмар Капитан\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Невидим Повелител\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Прикрит\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Следящ от Сенките\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Незабелязан\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Предач на Илюзии\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Сатир Господар\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Плътски Клан\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Каменен Клан\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Огнен Клан\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Нощен Клан\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Злосторник\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Моменталник\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Мрачник\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Познайник\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Киселинен Звяр\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Отровохрачещ\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Ямен Звяр\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Магмена Паст\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Кралят Скелет\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Касапина\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Надзирател\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Кален човек\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Крастав демон\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Кожодер\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Змей\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Пещерен плужек\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Дяволски змей\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Поглъщащ\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Магмен Демон\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Кръвен Kамък\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Адски Камък\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Господар на Лавата\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Рогат Демон\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Кален Бегач\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Връхлитащ Мраз\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Обсидианов Повелител\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"Старокостен\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Червена Смърт\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Лич Демон\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Немъртъв Барлог\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Изгарящ\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Огнен Господар\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Обречен Пламък\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Адски Горяч\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Червена Буря\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Буреносен Водач\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Господар на Бурите\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Маелстрьом\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Дяволска Челяд Здравеняк\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Крилат Демон\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Гаргойл\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Кървав нокът\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Смъртоносно Крило\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Унищожител\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Пазител\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Господар на Вихъра\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Балрог\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Пещерна Усойница\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Огнена Ламя\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Златна Усойница\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Лазурена Ламя\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Черен Рицар\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Пазител на Обречените\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Стоманен Повелител\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Кървав Рицар\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Раздробените\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Празнодушен\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Господар на Болката\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Предач на Rеалности\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Сукуби\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Ледена Вещица\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Адска Отродия\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Душеизпепеляваща\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Съветник\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Магистрат\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Кабалист\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Адвокат\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Диабло\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Архи-немъртвия Малигнус\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Хилавия Гарбад\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Лудият Жар\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Сополивия\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Архиепископ Лазар\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Червената Векс\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Черната Джейд\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Лахданан\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Кървавият Пълководец\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Демона Хорк\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Осквернителят\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Кокалоглав Секирострастен\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Срязващия Острокож\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Душегной\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Нечистливия Бълвоплъх\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Костотрошача\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Гладния Гнилопир\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Пъргавия Чреволеш\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Чупеглав Хлопащит\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Бонго\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Кланегнил\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Сенкохапливия\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Мъртвоко\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Мъртвия Лудоок\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Черепогън\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Кривочереп\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Кръвоезик\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Пулсолазещия\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Луногърчещ\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Гнявогарван\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Шипояд\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Горящия Чернопепел\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Сянкогарван\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Слабия Болнокамен\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Жлъчепян Началника на Ямата\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Кръвокож Тъмнолък\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Долнокрил\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Сянкопиеца\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Омараменящия\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Смъртоплюй\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Кръвопорещия\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Смъртосян Плъточук\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Лудият Войночервей\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Нащърбения Стъклочереп\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Болестогън\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Студения Нощокрил\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Съсирекамък\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Бронзюмрук Огнекамък\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Гнявоплам Обречения\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Огнерана Безжалостния\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Барон Шлам\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Отровошип Стоманобух\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Хаосовиещия\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Орисхил Гниещия\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Лудогорящия\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Лича Косторез\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Чупигръбнак\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Дявочереп Острококал\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Разбибуря\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Бурегибел\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Течелига\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Заразлато от Пламъка\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Чернобур\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Чумоярост\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Бичуващия\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Синерог\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Кривогън Пъклочадие\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Зъбекопие\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Гноечереп\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Лъвочереп Привития\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Черноезик\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Гнуседопир\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Усойнопламък\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Зъбекож\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Вещогън Нечестивия\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Черночереп\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Душерез\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Ветрочеляд\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Господаря на Ямата\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Ръждоплет\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Гнявой Сянката\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Обреченоблак\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Кърволуна Душеогнена\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Вещолуна\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Съсирепир\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Сивойна Палача\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Страхосъдия\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Звездноока Вещицата\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Стоманочереп Ловецът\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Сър Гораш\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Визирът\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Сапфирени\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Кръвожажда\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Оплетовдовица\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Плътотанц\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Мрачешип\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Гибелобречен\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Къс меч\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Кръгъл щит\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Сопа\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Къс лък\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Къс жезъл за мана\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Сатър\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Корона на немъртвите\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Небесна гривна\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Магически камък\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Оптичен амулет\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Пръстен на Истината\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Табела от страноприемница\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Арлекинов герб\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Стоманено було\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Златен еликсир\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Наковалня на Яростта\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Черна гъба\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Мозък\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Гъбен алманах\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Спецтрален еликсир\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Кръвен камък\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Карта на катедралата\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Отвара за лечение\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Отвара за мана\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Свитък за разпознаване\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Свитък за Градски портал\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Доблестта на Аркайн\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Отвара за Пълно лечение\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Отвара за Пълна мана\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Острието на Грисволд\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Говежда броня\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Жезълът на Лазар\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Свитък за Възкресение\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Къс жезъл\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Меч\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Кама\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Рунична бомба\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Теодор\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Блестящ амулет\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Разкъсана бележка 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Разкъсана бележка 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Разкъсана бележка 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Възстановено Завещание\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Кафяв костюм\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Сив костюм\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Каска\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Наскулна каска\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Шлем\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Пълен шлем\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Корона\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Велик шлем\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Пелерина\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Дрипи\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Наметало\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Роба\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Ватирана броня\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Кожена броня\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Твърда кожена броня\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Ошипена кожена броня\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Пръстенова ризница\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Ризница\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Плетена ризница\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Плочна ризница\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Нагръдни доспехи\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Доспехи\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Шинирана ризница\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Плочни Доспехи\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Полеви Доспехи\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Готически Доспехи\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Пълни плочни доспехи\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Щит\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Малък щит\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Голям щит\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Гвардейски щит\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Крепостен щит\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Готически щит\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Отвара за Възобновление\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Отвара за Пълно възобновление\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Масло\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Еликсир за Сила\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Еликсир за Магия\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Еликсир за Сръчност\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Еликсир за Жизненост\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Свитък за Лечение\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Свитък за Издирване\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Свитък за Мълния\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Свитък за Огнена стена\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Свитък за Инферно\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Свитък за Светкавица\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Свитък за Инфразрение\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Свитък за Произволно положение\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Свитък за Щит от мана\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Свитък за Огнена вълна\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Свитък за Огнено кълбо\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Свитък за Каменно проклятие\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Свитък за Верижна мълния\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Свитък за Пазител\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Свитък за Нова\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Свитък за Голем\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Свитък за Телепортация\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Свитък за Апокалипсис\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Фалхион\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Ятаган\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Двуострен меч\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Острие\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Сабя\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Дълъг меч\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Широк меч\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Батардов меч\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Двурък меч\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Велик меч\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Секира\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Брадва\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Голяма брадва\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Широка брадва\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Бойна брадва\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Велика брадва\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Боздуган\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Утринна звезда\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Боен чук\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Чук\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Ошипена палка\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Млатило\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Млат\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Лък\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Ловен лък\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Дълъг лък\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Комбиниран лък\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Къс боен лък\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Дълъг Боен лък\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Къс военен лък\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Дълъг военен лък\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Дълъг жезъл\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Комбиниран жезъл\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Четвъртичен жезъл\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Военен жезъл\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Пръстен\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Амулет\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Руна за Огън\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Руна\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Руна за Мълния\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Мощна Руна за огън\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Мощна Руна за мълния\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Руна за Вкаменяване\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Къс жезъл за Светкавична искра\"\n\n#: Source/translation_dummy.cpp:368\n#, fuzzy\n#| msgid \"Mana Potion Pickup\"\nmsgid \"Arena Potion\"\nmsgstr \"Авто-взимане мана\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Сатъра на Касапина\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Светосабя\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Разривен лък\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Игленикът\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Небесния лък\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Смъртоносен Ловец\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Лък на мъртвите\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Чернодъбовият Лък\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Огнено острило\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Плътожилец\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Вятърмощ\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Орелорог\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Камата на Гонагал\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Закрилникът\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Грифонски нокът\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Черен бръснач\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Непълна луна\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Леден Къс\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Острието на Палача\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Трион за кости\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Сенкоястреб\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Чародейски шип\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Светосабя\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Соколски нокът\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Инферно\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Гибелоносец\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Гризлито\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Старецът\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Разкъсвача\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Остър Клюн\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Кървав унищожител\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Звездната Брадва\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Нечестива Брадва\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Каменен секач\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Агинарова секира\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Адски секач\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Месершмидски Опустошител\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Цеперъжд\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Чукът на Жолм\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Бухалката на Сиверб\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Небесна звезда\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Звездата на Баранар\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Възлест корен\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Черепен трошач\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Чукът на Шаефър\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Събуждач\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Жезъл от Сенки\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Подпалвач\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Бурешпил\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Искрапесен\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Гръмовит\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Защитника\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Загаждача на Наж\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Умостенание\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Тоягата на Онан\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Шлем от Духове\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Мислеща Шапка\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Надзирателски шлем\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Емблема на Шута\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Залезът на боговете\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Кралска диадема\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Откъсната плът от души\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Неволята на Гладиатора\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Пъстроцветната пелерина\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Кожа от Аут\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Прегръдка на Мъдростта\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Искряща ризница\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Мършоядска коруба\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Тъмоствол\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Леките доспехи на Наж\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Демоншипско палто\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Отразителят\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Сцепен черепен щит\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Драконов пробив\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Чернодъбов щит\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Свещен пазител\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Бурещит\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Бодливенец\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Пръстен на Рега\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Кървящият\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Сътворяващ пръстен\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Венчален Пръстен\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Оловни\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Месингови\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Бронзови\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Железни\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Стоманени\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Сребърни\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Платинени\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Митрилови\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Метеоритни\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Страненни\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Безполезни\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Криви\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Слаби\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Назъбени\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Смъртоносни\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Тежки\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Коварни\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Безмилостни\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Мощни\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Свирепи\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Жестоки\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Зверски\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Непохватни\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Тъпи\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Остри\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Изящни\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Войнски\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Войнишки\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Господарски\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Рицарски\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Повелителски\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Юнашки\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Кралски\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Уязвими\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Ръждиви\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Могъщи\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Внушителни\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Доблестни\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Славни\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Благословени\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Блажени\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Невероятни\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Божествени\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Червени\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Пурпурни\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Гранатени\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Рубинени\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Сини\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Лазурни\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Лаписови\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Кобалтови\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Сапфирени\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Бели\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Перлени\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Кварцови\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Кристални\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Диамантени\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Топазени\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Кехлибарени\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Нефритени\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Обсидиани\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Изумрудни\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Хиенови\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Жабешки\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Паешки\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Гарвански\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Змийски\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Гущерски\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Ламски\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Драконови\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Змейски\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Хидрови\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Ангелски\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Архангелски\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Щедри\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Обилни\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Пламени\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Светкавични\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"Качеството\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"Осакатяване\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"Посичането\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"Кръвопролитието\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"Касапницата\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"Клането\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"Болката\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"Сълзите\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"Здравето\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"Закрилата\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"Поглъщането\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"Отклонението\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"Осмозата\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"Хилавостта\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"Слабостта\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"Силата\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"Мощта\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"Могъществото\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"Великаните\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"Титаните\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"Парализата\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"Атрофията\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"Сръчността\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"Умението\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"Точността\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"Прецизността\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"Съвършенството\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"Глупака\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"Дислексията\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"Магията\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"Мисълта\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"Блясъка\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"Магьосничеството\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"Чародейството\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"Болестта\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"Заразата\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"Бодростта\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"Жарта\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"Живостта\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"Крепкостта\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"Живота\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"Бедата\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"Ямата\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"Небето\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"Луната\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"Звездите\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"Висините\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"Зодиака\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"Лешоядът\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"Чакала\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"Лисицата\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"Ягуара\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"Орела\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"Вълка\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"Тигъра\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"Лъвът\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"Мамута\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"Китът\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"Крехкостта\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"Чупливостта\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"Здравината\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"Изработката\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"Структурата\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"Епохите\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"Тъмнината\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"Нощта\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"Светлината\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"Сиянието\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"Пламъка\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"Огъня\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"Горенето\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"Сътресението\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"Мълнията\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"Гръмотевицата\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"Множеството\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"Изобилието\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"Шиповете\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"Покварата\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"Крадците\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"Мечката\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"Прилепа\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"Вампирите\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"Пиявицата\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"Кръвта\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"Пронизването\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"Пробождането\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"Блъскането\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"Готовността\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"Пъргавината\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"Скоростта\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"Бързината\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"Баланса\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"Стабилността\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"Хармонията\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"Блокирането\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Магическият камък\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Гарбад Хилавия\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Лудият Жар\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Лахданан\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Касапина\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Табелата на Огдън\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Залата на Слепите\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Доблест\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Кървавият Пълководец\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Проклятието на Крал Леорик\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Архиепископ Лазар\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Задгробни Въпроси\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Овошките на Фермера\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Малкото момиче\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Пътуващият търговец\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Осквернителят\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Говежди Одежди\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Огнен болид\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Лекуване\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Мълния\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Светкавица\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Разпознаване\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Огнена стена\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Градски портал\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Каменно прооклятие\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Инфразрение\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Произволно положение\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Щит от мана\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Огнена топка\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Пазител\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Верижна мълния\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Огнена вълна\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Гибелни Змии\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Кървав ритуал\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Нова\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Невидимост\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Инферно\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Ярост\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Телепортиране\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Апокалипсис\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Ефирализация\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Поправяне на предмет\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Презареждане на жезъл\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Обезвреждане на клопка\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Стихия\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Мълниен заряд\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Свещено кълбо\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Възкресяване\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Телекинеза\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Лекувай приятел\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Кървава звезда\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Костен дух\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ааа, за историята на Краля ли? Трагичния крах на Леорик дойде като гръм от \"\n\"ясно небе за тези земи. Хората обичаха Краля, а сега живеят в дълбок страх \"\n\"от него. Въпросът, който продължавам да си задавам, е, как е могъл да падне \"\n\"толкова далеч от Светилната, Леорик винаги е бил най-светлият от всички. \"\n\"Единствено най-покварените сили на Ада са способни да унищожат някого \"\n\"отвътре...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Градът се нуждае от Вашата помощ, драги господарю! Преди няколко месеца, \"\n\"Принц Албрихт, синът на Крал Леорик, бе отвлечен. Побеснял, Кралят обърна \"\n\"всеки камък, за да намери своята рожба. Но с всеки изминал ден, Леорик сякаш \"\n\"изпадаше във все по-дълбока лудост. Обвиняваше невинни жители за изчезването \"\n\"на сина си, като ги осъждаше на несправедлива екзекуция. По-малко от \"\n\"половината от нас успяха да се спасят от неговото безумие.\\n\"\n\"\\n\"\n\"Рицарите му и придворните свещеници се опитаха да го усмирят, но той се \"\n\"обърна срещу тях и за жалост, те бяха принудени на цареубийство. С последния \"\n\"си дъх, Кралят отправи жестоко проклятие към бившите си слуги, кълнейки, се \"\n\"че те ще му служат вечно в мрака.\\n\"\n\"\\n\"\n\"Точно тогава, събитията придобиха още по-мрачен изглед, какъвто не съм и \"\n\"предполагал! Някогашният ни Крал се надигна от своя вечен сън и в момента \"\n\"ръководи легион от немъртви чудовища в Лабиринта. Тялото му лежи заровено в \"\n\"гробница, на три нива под Катедралата. Умолявам те, драги господарю, върни \"\n\"душата му в покой, като унищожиш тази му прокълната същност...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Както вече споменах, драги господарю, Кралят е загробен на три нива \"\n\"дълбочина. Той е там долу, в зловещата тъмнина, чакайки момента да съсипе \"\n\"тази земя.\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Проклятието на Краля отмина, но се опасявам, че това е само частица от \"\n\"дебнещо по-велико зло. Въпреки всичко, може би има надежда да бъдем спасени \"\n\"от тъмнината, стелещо се над нашата земя, защото твоята победа е само добро \"\n\"знамение. Нека светлина озари твоя път, добри господарю.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Крал Леорик не можа да превъзмогне загубата на сина си. Положих всякакви \"\n\"усилия, за да облекча лудостта му, но все пак тя го пребори. От този ден \"\n\"нататък черно проклятие се стели над това кралство, но може би ако освободиш \"\n\"духа му от неговите земни окови, проклятието ще бъде повдигнато...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Не искам да си спомням как се спомина Краля. Искам да си го спомням като \"\n\"добър и справедлив владетел, какъвто беше. Неговата смърт донесе много скръб \"\n\"за всички и бе някак не намясто.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Изковал съм повечето от оръжията и броните, с които Крал Леорик екипираше \"\n\"своите рицари. Дори направих огромен меч от най-добрия митрил за негово \"\n\"величество, както и корона, за да си подхождат. Все още не мога да повярвам \"\n\"как си отиде, но определено трябва да е била някаква наистина злокобна сила, \"\n\"която да го доведе до пълна лудост!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Това не ме интересува. Слушай ме, никакъв скелет няма да бъде МОЙ крал. \"\n\"Единственият крал е Леорик. Крал, разбираш ли? ДА ЖИВЕЕ КРАЛЯТ!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Мъртвите, бродещи сред живите, следват прокълнатия Крал. Той притежава \"\n\"силата да призовава още повече войни, умножавайки своята вечно растяща армия \"\n\"от немъртви. Ако не сложиш край на неговото господство, той със сигурност не \"\n\"ще се поколебае да съсече всеки, който живее по тези земи.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Виж, имам си достатъчно работа. Не продавам информация и не ме увлича \"\n\"някакъв си Крал, особено ако е мъртъв от години. Ако ти трябва нещо, с което \"\n\"да се изправиш срещу този Господар на Немъртвите, може би мога да ти \"\n\"помогна...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Топлината на живота е пристъпила в гробницата ми. Приготви се, смъртнико, да \"\n\"служиш вовеки на моя Господар!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Забелязвам, това неясно държание озадачава и теб. Подозирам, че немалко \"\n\"демони се страхуват от светлината, вярвайки че тя има велика сила. Може би \"\n\"изгряващото слънце върху табелата им е заприличало на символ, носещ някаква \"\n\"тайнствена сила. Хммм, възможно е да не са чак толкова умни колкото \"\n\"подозираме...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Господарю, имам да споделя едно странно преживяване. Знам, че имаш дълбоки \"\n\"познания за тези чудовищни създания, които обитават лабиринта, а това е \"\n\"нещо, което не мога да проумея за нищо на света... През нощта бях събуден от \"\n\"стържещ звук точно пред моята кръчма. Когато погледнах от спалнята си, видях \"\n\"в двора на кръчмата силуетите на малки демоноподобни същества. Миг по-късно \"\n\"те се разбягаха, но не и преди да откраднат табелата на кръчмата ми. Не знам \"\n\"защо демоните откраднаха табелата ми, а оставиха семейството ми на мира... \"\n\"странно е, нали?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Оооо, не беше нужно да ми връщаш табелата, но предполагам, че това ще ми \"\n\"спести разходите по изработката на нова. Добре, нека да видим с какво мога \"\n\"да ти се отплатя за намирането ѝ? Хммм, какво имаме тук... а, да! Тази шапка \"\n\"бе забравена в една от стаите от един вълшебник, който остана тук преди \"\n\"време. Може би ще ти бъде от полза.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Боже мой, демони обикалят града нощем и плячкосват домовете ни? Нима няма \"\n\"нищо свято останало? Надявам се, че Огдън и Гарда са добре. Предполагам, че \"\n\"щяха да дойдат да ме видят, ако бяха ранени...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"О, Боже! Така ли е изчезнала табелата? Баба ми и аз сигурно сме преспали \"\n\"цялата случка. Благодаря на Светлината, че тези чудовища не са нападнали \"\n\"гостилницата.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Казваш, че демони са откраднали табелата на Огдън? Това не звучи много като \"\n\"зверствата, за които съм чувал или виждал.\\n\"\n\"\\n\"\n\"Демоните са загрижени как да изтръгнат сърцето ти, а не от дървената ти \"\n\"табела.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Знаеш ли какво си мисля? Някой е взел тази табела и ще иска една камара пари \"\n\"за нея. Ако бях Огдън... не, че съм, но ако бях... щях просто да си купя \"\n\"нова табела с някаква хубава рисунка на него. Може би една хубава халба пиво \"\n\"или парче сирене...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Никой смъртен не може да разбере ума на демона.\\n\"\n\" \\n\"\n\"Никога не позволявай на блуждаещите те им постъпки да те объркват, тъй като \"\n\"това също може да е тяхната цел.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Какво? Той мисли, че Аз съм го взел? Предполагам, че и Грисволд е на негова \"\n\"страна.\\n\"\n\" \\n\"\n\"Слушай, спрях да крада табели преди месеци. Не можеш да изкараш много от \"\n\"парче дърво.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Хей, ти този, който убива всички! Донеси ми Магическо знаме или нападаме! \"\n\"Няма да тръгнеш с живот! Ти убиваш големи грозници и връщаш Магия. Върви \"\n\"покрай ъгъл и врата, намираш грозници. Даваш, минаваш!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Убиваш грозници, взимаш знаме. Ти носиш, иначе...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Ти даваш! Да, добре! Върви сега, ние силни. Ние убиваме всички с голяма \"\n\"магия!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Това не вещае нищо добро и потвърждава най-мрачните ми страхове. Макар да не \"\n\"си позволявах да вярвам на древните предания, сега не мога да ги отрека. \"\n\"Настъпи момента да разкрия кой всъщност съм аз.\\n\"\n\"\\n\"\n\"Истинското ми име е Декард Кайн - Старейшината и съм последният потомък на \"\n\"древно Братство, посветено на опазването на тайните на безвременно зло. Зло, \"\n\"което очевидно вече е на свобода.\\n\"\n\"\\n\"\n\"Архиепископ Лазар, някогашният най-доверен съветник на крал Леорик, поведе \"\n\"група от обикновени жители на града в Лабиринта, за да намерят Албрихт, \"\n\"изчезналия син на краля. Мина доста време, преди малцината оцелели завърнат, \"\n\"избягали на косъм от смъртта .\\n\"\n\"\\n\"\n\"Проклета да бъде глупостта ми! Трябваше да предположа скритото му \"\n\"предателство още тогава. Сигурно самият Лазар е отвлякъл Албрихт и о го е \"\n\"отвел в Лабиринта. Не разбирам защо архиепископът се е преминал към мрака и \"\n\"какъв е интересът му към детето... Освен ако не смята да го принесе в жертва \"\n\"на тъмните си господари!\\n\"\n\"\\n\"\n\"Трябва да е замислил точно това! Оцелелите от неговата 'спасителна дружина' \"\n\"разказват, че за последен път са видели Лазар да бяга в най-дълбоките дебри \"\n\"на лабиринта. Трябва да побързаш и да спасиш принца от жертвеното острие на \"\n\"този обезумял злодей!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Трябва да побързаш и да спасиш Албрихт от ръцете на Лазар. Принцът и народът \"\n\"на това кралство разчитат на теб!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Разказа ти е доста зловещ, приятелю. Лазар със сигурност ще гори в ада за \"\n\"ужасното си деяние. Момчето, което описваш, не е нашият принц, но вярвам, че \"\n\"Албрихт все още може да е в опасност. Символът от тъмна сила, за който \"\n\"говориш, трябва да е портал в самото сърце на лабиринта.\\n\"\n\"\\n\"\n\"Знай това, приятелю - злото, срещу което се изправяш, е тъмният Господар на \"\n\"ужаса. Той е познат сред смъртните като Диабло. Именно той е бил затворен \"\n\"преди много векове в Лабиринта и се опасявам, че се стреми отново да сее \"\n\"хаос в царството на хората. Трябва да преминеш през портала и да унищожиш \"\n\"Диабло, преди да е станало твърде късно!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Лазар е архиепископът, който поведе много от жителите на града към \"\n\"лабиринта. В онзи ден загубих много добри приятели, а Лазар така и не се \"\n\"завърна. Предполагам, че е бил убит заедно с повечето от останалите. Ако \"\n\"можеш да ми направиш услуга, добри господарю - моля те, не говори на Фарнам \"\n\"за онзи ден.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Бях поразен, когато чух за какво се готвеха жителите на града онази нощ. \"\n\"Мислех си, че от всички хора Лазар би имал повече разум от това. Той беше \"\n\"архиепископ и винаги изглеждаше, че го е много грижа за жителите на \"\n\"Тристрам. Толкова много бяха ранените, нямаше как да ги спася всичките...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Спомням си Лазар като много добър и щедър човек. Той говори на погребението \"\n\"на майка ми и подкрепи баба ми и мен, в един много труден момент. Всяка \"\n\"вечер се моля да е жив и в безопасност.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Бях там, когато Лазар ни поведе в лабиринта. Говореше за свято възмездие, но \"\n\"когато започнахме да се бием с тези адски гадове, той дори не повдигна \"\n\"боздугана си срещу тях. Той просто побягна навътре в мрачните, безкрайни \"\n\"коридори, които бяха пълни със слугите на мрака!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Пронизват, после хапят, а после са навсякъде около теб. Лъжец! ЛЪЖЕЦ! Всички \"\n\"те са мъртви! Мъртви! Чуваш ли ме? Те продължават да падат и падат... кръвта \"\n\"им се разлива по земята... всичко е по негова вина...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Не познавам този Лазар, за когото говориш, но усещам голям конфликт в \"\n\"същността му. Той представлява голяма опасност и няма да се спре пред нищо, \"\n\"за да служи на силите на мрака, които са го приели за свой.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Да, праведника Лазар, който беше толкова деен срещу онези чудовища в \"\n\"подземията. Но така и не ми помогна да спася крака си, нали? Един безплатен \"\n\"съвет... Говори с Фарнам, той беше там...\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Откажи се от глупавото ти търсене. Очаква те само гневът на моя господар! \"\n\"Твърде късно е за да спасиш детето. Скоро ще се присъединиш към него в Ада!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Хммм, не знам какво точно мога да ти кажа по този въпрос, за да съм полезен. \"\n\"Водата, която тече в нашите кладенци, идва от подземен извор. Чувал съм за \"\n\"тунел, който води до голямо езеро - може би те са свързани. За съжаление не \"\n\"знам какво би могло да доведе до замърсяване на водата ни.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Винаги съм се опитвал да поддържам големи запаси от храна и напитки в избата \"\n\"ни, но тъй като целият град е останал без прясна вода, скоро и нашите запаси \"\n\"ще се изчерпят. \\n\"\n\"\\n\"\n\"Моля, направи каквото е по силите ти, иначе не знам какво ще стане с нас.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Радвам се, че те хванах навреме! Кладенците ни са мътни и застояли и някои \"\n\"от жителите на града се разболяха, пиейки от тях. Запасите ни от прясна вода \"\n\"бързо се изчерпват. Смятам, че има проход, който води до изворите, от които \"\n\"града ни черпи вода. Моля те, потърси какво ни е причинило това нещастие, \"\n\"иначе всички ние със сигурност ще изтлеем от жажда.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Моля те, побързай. С всеки изминал час запасите ни от питейна вода \"\n\"намаляват.\\n\"\n\"\\n\"\n\"Няма да оцелеем дълго без твоята помощ.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Какво говориш?! Самото присъствие на демони около извора е замърсило водата? \"\n\"О, наистина голямо зло се крие под нашия град, но твоята упоритост и смелост \"\n\"ни дават надежда. Моля те, вземи този пръстен, може би той ще ти помогне в \"\n\"унищожаването на тези противни създания.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Баба ми се чувства много слаба, а Гарда казва, че не можем да пием вода от \"\n\"кладенците. Моля те, не можеш ли да направиш нещо, за да ни помогнеш?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Пепин е прав. Наистина се нуждаем от прясна вода, и то скоро. Опитах се да \"\n\"изчистя един от по-малките кладенци, но той вони на застояла мръсотия. \"\n\"Сигурно е запушил при източника.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Ти пиеш вода?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Жителите на Тристрам ще загинат, ако не успееш да върнеш прясната вода в \"\n\"кладенците им.\\n\"\n\"\\n\"\n\"Знай, че демони са в основата на това дело, но самите те не знаят какво \"\n\"всъщност са породили.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Този път, съм с теб. Търговията ми пресъхва - така да се каже - ако нямам \"\n\"пазар, на който да продавам. По-добре разбери какво е в основата всичко, и \"\n\"то бързо!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Книга, в която се говори за Камера с човешки кости? Да, Камера на Костите се \"\n\"споменава в определени архаични писания, които изучавах в библиотеките на \"\n\"Изтока. В тези съчинения се загатва, че когато Владетелите на подземния свят \"\n\"искали да защитят големи богатства, те създавали територии, в които онези, \"\n\"загинали в опит да откраднат съкровището, били завинаги осъдени да го \"\n\"защитават като немъртви. Извратен, но странно подходящ край?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Боя се, че не знам нищо за това, добри господарю. Кайн има много книги, \"\n\"които могат да ти помогнат.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Това звучи като много опасно място. Ако ще ходиш натам, моля те, то бъди \"\n\"много внимателен.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Опасявам се, че не съм чувал нищо такова. Може би Кайн Разказвачът би могъл \"\n\"да ти помогне.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Нищо не съм чувал за подобно място, но може да попиташ Кайн. Той говори за \"\n\"много неща и няма да се изненадам, ако може да отговори на въпроса ти.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Добре, слушай сега. Има тази камера от дърво, сещаш се. И жена му, нали \"\n\"знаеш - нейната - казва на дървото... защото трябва да почакаш. Тогава аз \"\n\"рекох, че това може и да проработи срещу него, но ако мислиш, че аз ще \"\n\"ПЛАЩАМ за това... ти... ъъъ... да.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Ако загинеш в това прокълнато място, ще станеш вечен слуга на тъмните му \"\n\"владетели.\\n\"\n\"\\n\"\n\"Пристъпи в Камерата на Костите на собствен риск.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Казваш, че това е огромно и тайнствено съкровище? Може би бих се \"\n\"заинтересувал да взема няколко неща от теб... или още по-добре, не ти ли \"\n\"трябват рядко и скъпо снаряжение, което да ти помогне да преминеш през това \"\n\"изпитание?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Изглежда, че архиепископ Лазар е подтикнал много от жителите на града да се \"\n\"впуснат в Лабиринта, за да намерят изчезналия син на краля. Възползвайки се \"\n\"от страховете им, той ги превръща в бясна тълпа. Никой от тях не е бил \"\n\"подготвен за това, което ги е очаквало в смразяващите подземия... Лазар ги \"\n\"изоставя там - в лапите на неописуеми ужаси - да умрат.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Да, Фарнам промърмори нещо за грамаден звяр, който използвал жестоко оръжие. \"\n\"Струва ми се, че го нарече Касапина.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"В името на Светлината, знам за този свиреп демон. Много носеха белезите на \"\n\"яростта му по телата си, когато малцината оцелели от свитата, водена от \"\n\"Лазар, изпълзяха от катедралата. Не знам какво е използвал, за да разфасова \"\n\"жертвите си, но не може да е било от този свят. Рани, гноясали от зараза, \"\n\"дори за мен, те бяха почти непосилни за лечение. Пази се, ако възнамеряваш \"\n\"да се изправиш пред този злодей...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Когато Фарнам заговори нещо за касапин, който убива хора, не му обърнах \"\n\"внимание. Но сега след като ти го споменаваш, може би е вярно.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Видях онова, което Фарнам нарича Касапина, докато си проправяше път през \"\n\"телата на моите приятели. Той размахваше сатър, голям колкото брадва, \"\n\"откъсвайки крайници и съсичайки храбрите мъже на място. Бях отделен от \"\n\"схватката от множество малки пищящи демони и някак намерих пътя до \"\n\"стълбището, което водеше навън. Никога повече не видях този отвратителен \"\n\"звяр, но мисълта за окървавеният му лик ме преследва и до днес.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Огромен! Огромен сатър, съсича всичките ми приятели. Не можех да го спра, \"\n\"трябваше да избягам, не можех да ги спася. Хванати в капан, стая с толкова \"\n\"много тела... толкова много другари... НЕЕЕЕЕЕЕЕЕЕЕЕ!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Касапина е садистично същество, което изпитва удоволствие от мъченията и \"\n\"болката на другите. Виждал си делата му в лицето на пияницата Фарнам. \"\n\"Унищожаването му ще допринесе много за безопасността на този град.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Знам повече, отколкото можеш да си предтавиш, за този ужасен злодей. Малките \"\n\"му приятели ме хванаха и успяха отмъкнат крака ми, преди Грисволд да ме \"\n\"издърпа от онази дупка.\\n\"\n\"\\n\"\n\"Ще го кажа направо - убий го пръв, преди да те е съсякъл и да е добавил \"\n\"трупът ти към неговата колекцията си.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Моля те, чуй ме... Архиепископ Лазар, той ни поведе тук долу, за да търсим \"\n\"изчезналия принц. Мръсникът ни вкара в капан! Сега всички са мъртви... убити \"\n\"от демон, когото той нарече Касапина. Отмъсти за нас! Намери този Касапин и \"\n\"го убий, за да могат душите ни най-накрая да си отидат спокойни...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Рецитираш интересна рима, написана в стил, който ми напомня за други \"\n\"произведения. Нека сега помисля - как точно беше?\\n\"\n\"\\n\"\n\"...Тъмнината забулва Скритите. Очи блестят незабелязани, и само звуците от \"\n\"стържене на остри нокти измъчват онези бедни души, които са останали незрящи \"\n\"за цяла вечност. Затворът за тези прокълнати е наречен Залите на слепите...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Никога не съм изпитвал особен интерес към поезията. От време на време наемах \"\n\"странстващи музиканти, когато странноприемницата вървеше добре, но това вече \"\n\"изглежда много отдавна.\\n\"\n\"\\n\"\n\"Какво? А, да... ами, предполагам, че можеш да попиташ някой друг.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Това изглежда някак познато. Спомням си, че четох нещо много подобно на този \"\n\"стих, докато проучвах историята на демоничните страдания. В него се говореше \"\n\"за място на голямо зло, което... Чакай, няма да ходиш там, нали?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Ако имаш въпроси що се отнася до слепотата, посъветвай се с Пепин. Той \"\n\"приготви за баба ми отвара, която й помогна да изчисти зрението си, така че \"\n\"може и на теб да ти е от помощ.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Опасявам се, че нито съм чувал, нито виждал място, което да отговаря на \"\n\"твоето описание, приятелю. Може би разказвачът Кейн би могъл да ти помогне.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\"Гледай тук... Това е доста смешно, а? Схващаш ли? Слепият вика - виж това?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Това е място на голямо страдание и ужас, служещо добре на своя господар.\\n\"\n\"\\n\"\n\"Спохождай внимателно, защото може да се окаже, че ще останеш много по-дълго, \"\n\"отколкото си очаквал.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Нека се разберем, аз продавам ли ти нещо? Не. Даваш ли ми пари, за да ти го \"\n\"разяснявам? Не. Сега, тръгваш ли си и заминавайки да разговаряш с \"\n\"разказвача, който живее само за такива неща? Да.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Твърдиш, че си разговарял с Лахданан? Приживе той бе велик герой. Почтен и \"\n\"справедлив човек, който години наред е служил вярно на своя крал. Но, \"\n\"разбира се, ти вече знаеш това.\\n\"\n\"\\n\"\n\"От онези, които са попаднали в хватката на проклятието на Краля, Лахданан е \"\n\"най-малко склонен да се подчини на мрака без борба, така че предполагам, че \"\n\"историята ти може и да е вярна. Ако бях на твое място, приятелю, щях да \"\n\"намеря начин да го освободя от терзанията му.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Говориш за храбър воин, който е мъртъв от много време! Няма да допусна \"\n\"такива разговори за напусна ли ни отдавна души в двора на странноприемницата \"\n\"ми, не благодаря.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Златен еликсир, така ли? Никога досега не съм приготвял отвара с такъв \"\n\"оттенък, така че не мога да ти кажа как ще ти подейства, ако се опиташ да я \"\n\"изпиеш. Като твой лечител горещо те съветвам, ако намериш такъв еликсир, да \"\n\"постъпиш, както те моли Лахданан, и да НЕ се опитваш да го използваш.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Никога преди не съм чувала за Лахданан. Съжалявам, но не мисля, че мога да \"\n\"ти бъда от голяма полза.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Ако действително си срещнал Лахданан, те посъветвам да му помогнеш. Търгувал \"\n\"съм с него няколко пъти и съм го смятал за честен и лоялен по природа. \"\n\"Проклятието, което се стовари върху служещите на крал Леорик, ще се стовари \"\n\"особено тежко върху него.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Лахданан е мъртъв. Всички знаят това и не можеш да ме заблудиш, да мисля по \"\n\"друг начин. Не можеш да говориш с мъртвите. Това го знам!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Възможно е да срещнеш хора, като Лахданан, които са затворени в капана на \"\n\"Лабиринта. Усещам в него благородство и голяма вина.\\n\"\n\"\\n\"\n\"Помогни му и ще помогнеш на цял Тристрам.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Чакай малко, нека да предположа. Кайн бе погълнат от гигантска пукнатина, \"\n\"която се е отворила под него. Бил е изпепелен в кълбо от адски огън и вече \"\n\"не може да отговаря на въпросите ти. Оооо, нищо подобно не му се е случило? \"\n\"Тогава предполагам, си тук да пазаруваш или ще хващаш пътя.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Моля те, не ме убивай, просто ме изслушай. Някога аз бях капитан на рицарите \"\n\"на крал Леорик и с чест и справедливост браних правдата по тези земи. Тогава \"\n\"върху нас падна неговото мрачно проклятие заради ролята, която изиграхме в \"\n\"трагичната му смърт. Докато моите другари рицари се поддаваха на извратената \"\n\"си съдба, аз избягах от погребалната камера на краля, търсейки начин да се \"\n\"освободя от неговото Проклятие. Но аз се провалих...\\n\"\n\"\\n\"\n\"Чувал съм че съществува Златен Еликсир, който би могъл да премахне \"\n\"проклятието и да даде покой на душата ми, но не успях да го намеря. Силите \"\n\"ми вече чезнат, а с тях и малкото ми останала човечност. Моля те, помогни ми \"\n\"и намери Еликсира. Ще се отплатя за усилията ти, кълна се в честта си.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Не си намерил златния еликсир... Страхувам се, че съм обречен навеки. Моля \"\n\"те, не спирай да търсиш...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Ти спаси душата ми от проклятието, и за това ще съм ти навеки задължен. Ако \"\n\"има начин да ти се отплатя от отвъдното, ще го намеря, но засега вземи шлема \"\n\"ми. По пътя, което ми предстои, той няма да ми е нужен. Нека да те пази от \"\n\"мрачните сили там долу. Върви със Светлината, приятелю...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Грисволд говори за Наковалнята на Яростта - легендарен артефакт, който дълго \"\n\"е бил търсен, но никога не е бил намерен. Изработена от металните кости на \"\n\"демоните от Ямата на Остриетата, Наковалнята на Яростта е излята между \"\n\"черепите на петте най-могъщи магове на подземния свят. Гравирана с руни на \"\n\"силата и хаоса, всяко оръжие или броня, изковани на тази наковалня, ще бъдат \"\n\"потопени в Царството на отвъдното, което ще им придаде магически свойства. \"\n\"Твърди се, че непредсказуемостта на Хаоса прави трудно да се разбере какъв \"\n\"ще бъде резултатът от изковаването...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Не мислиш ли, че Грисволд би бил по-подходящия човек, когото да попиташ за \"\n\"това? Той е на близо, нали знаеш.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Ако търсеше информация за Чукалото за Изцелението или за Сребърния бокал за \"\n\"Пречистването, щях да съм ти от помощ, приятелю. Но в този случай обаче, би \"\n\"било по-добре да поговориш с Грисволд или Кайн.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Когато бяхме деца, Бащата на Грисволд ни разказваше история, за гигантска \"\n\"наковалня, на която се изработвали могъщи оръжия. Говореше ни, че когато чук \"\n\"удари върху тази наковалня, земята се разтърсва от голяма ярост. Винаги, \"\n\"когато има земетресение, си спомням тази история.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Привет! Винаги е удоволствие да видя един от най-добрите си клиенти! Знам, \"\n\"че си навлязъл дълбоко в Лабиринта и имам една история, която ми разказаха и \"\n\"която може би си струва да чуеш...\\n\"\n\"\\n\"\n\"Един от мъжете, завърнали се от Лабиринта, ми разказа за тайнствена \"\n\"наковалня, на която се натъкнал по време на бягството си. Описанието му ми \"\n\"напомни за легендите, които бях чувал в младостта си, за Горящите Адски \"\n\"Огнища, където се изработват могъщи магически оръжия. Легендата разказваше, \"\n\"че дълбоко в Адските Огнища се намирала Наковалнята на Яростта! Тази \"\n\"наковалня съдържала в себе си самата същност на демоничния подземен свят...\\n\"\n\"\\n\"\n\"Говори се, че всяко оръжие, изработено върху горящата наковалня, е наситено \"\n\"с голяма сила. Ако тази наковалня наистина е Наковалнята на Яростта, може би \"\n\"ще успея да ти направя оръжие, способно да победи дори най-мрачния господар \"\n\"на Ада!\\n\"\n\"\\n\"\n\"Намери ми наковалнята и аз ще се заема с работата!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Все още нищо, а? Добре, но продължавай да търсиш. Оръжие, изковано върху \"\n\"наковалнята, може да бъде най-добрата ти надежда и аз съм сигурен, че мога \"\n\"да ти изработя такова от легендарни пропорции.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Не мога да повярвам на очите си! Това е Наковалнята на Яростта! Добра \"\n\"работа, приятелю. Сега ще покажем на тези уроди, че в Ада няма по-\"\n\"смъртоносни оръжия от тези, които са направени от хора! Вземи това и нека \"\n\"Светлината те закриля.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Грисволд не може да продаде наковалнята си. Какво ще прави тогава? И аз също \"\n\"бих се ядосал, ако някой ми вземе наковалнята!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"В Лабиринта има много артефакти, които притежават сили, отвъд разбиранията \"\n\"на смъртните. Някои от тях притежават неизмерима сила, която може да се \"\n\"използва както от Мрака, така и от Светлината. Завземането на Наковалнята от \"\n\"дълбините на подземието може да промени хода на Войната на Греха в полза на \"\n\"Светлината.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Ако откриеш тази наковалня за Грисволд, това може сериозно да накърни \"\n\"бизнеса ми тук. Аааааа, едва ли някога ще я намериш.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Портата на Кръвта и Залите на Огъня са ориентири с мистичен произход. Където \"\n\"и да се намира тази книга, от която четеш, тя със сигурност е място с голяма \"\n\"сила.\\n\"\n\" \\n\"\n\"Легендите разказват за пиедестал, издялан от обсидианов камък, на който има \"\n\"съд с вряща кръв, върху повърхност с гравирани кости. Има предания за камъни \"\n\"от кръв, които ще отворят врата, пазеща древно съкровище...\\n\"\n\"\\n\"\n\"Същността на това съкровище е забулена в спекулации, приятелю, но се говори, \"\n\"че древният герой Аркайн е поставил свещената броня Доблест в тайно \"\n\"хранилище. Аркайн бил първият смъртен, който променил хода на Войната на \"\n\"Греха и прогонил легионите на мрака обратно в Горящия Ад.\\n\"\n\"\\n\"\n\"Точно преди да умре, бронята на Аркайн е била скрита в тайно хранилище. \"\n\"Казват, че когато свещените доспехи отново бъдат необходими, ще се появи \"\n\"герой, който отново ще облече Доблестта. Може и ти да си този герой...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Всяко дете знае историята на героя Аркайн и неговата мистична броня, \"\n\"известна като Доблест. Намериш ли мястото, където тя е пазена, ще бъдеш \"\n\"добре защитен от злото, дебнещо в Лабиринта.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Хмм, Звучи като нещо, което трябва да си спомня, но напоследък съм толкова \"\n\"зает с изучаването на нови лекарства и създаването на по-добри еликсири, че \"\n\"сигурно съм забравил. Съжалявам...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Историята за вълшебната броня, наречена Доблест, е нещо, за което често \"\n\"чувах момчетата да говорят. По-добре попитай някой от мъжете в града.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Бронята Доблест, може да наклони везните в твоя полза. Едно ще ти кажа, че \"\n\"мнозина са я търсили - включително и аз. Аркайн я е скрил добре, приятелю, и \"\n\"ще ти трябва повече от късмет, за да разкриеш тайните, които са я държали \"\n\"потулена толкова години.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Хърррррррррррррррррррррррррр...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Ако намериш тези Камъни на кръвта, използвайте ги внимателно.\\n\"\n\"\\n\"\n\"Пътят е осян с опасности и единствената ти надежда е увереността в самия теб.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Смяташ да намериш бронята, известна като Доблест?\\n\"\n\"\\n\"\n\"Никой не знае къде Аркайн я е скрил, а щом моите връзки не са способни да я \"\n\"намерят, силно се съмнявам, че и ти някога ще успееш.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Познавам само една легенда, в която се говори за такъв войн, какъвто \"\n\"описваш. Неговата история се намира в древните хроники на Войната на \"\n\"Греха...\\n\"\n\"\\n\"\n\"Очернен от хиляда години война, кръв и смърт, Кървавият Пълководец стои \"\n\"върху планина от своите разкъсани жертви. Мрачното му острие крещи черно \"\n\"проклятие за живите; измъчена покана към всеки, изправил се пред този \"\n\"Екзекутор на Ада.\\n\"\n\"\\n\"\n\"Пише също, че макар някога да е бил смъртен и да се е сражавал в редиците на \"\n\"Легиона на Мрака по време на Войната на Греха, той е загубил човешката си \"\n\"същност заради ненаситната си жажда за кръв.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Опасявам се, че не съм чувал нищо за такъв жесток войн, добри господарю. \"\n\"Надявам се, че няма да ти се наложи да се сражаваш с него, защото всичко \"\n\"това звучи изключително опасно.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Кайн би могъл да ти разкаже много повече за нещо подобно, отколкото аз бих \"\n\"искал да знам, когато и да било.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Ако ти предстои да се сражаваш с такъв свиреп противник, нека Светлината \"\n\"бъде твой водач и защитник. Ще те пазя в мислите си.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Тъмни и злокобни легенди обграждат единствения Кървав Пълководец. Подготви \"\n\"се добре , приятелю, защото той не проявява нито капка милост.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Постоянно ли трябва да говориш за кръв? А, какво ще кажеш за цветята, \"\n\"слънцето и красивото момиче, което носи напитките. Слушай, приятелю - ти си \"\n\"вманиачен, наясно ли си с това?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Умението му да борави с острието е несравнимо, а освен това е живял хиляди \"\n\"години в нестихваща битка. Съжалявам... Не мога да видя дали ще го победиш.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Не съм чувал за този военачалник, за когото говориш, но звучи така, сякаш \"\n\"през неговите ръце минават много мечове. Нямам нищо против да снабдявам \"\n\"армията му...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Острието ми стене за твоята кръв, смъртнико... и в името на моите тъмни \"\n\"господари, не ще му бъде отказано.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Грисволд говори за Небесния камък, който бе предназначен за анклава, \"\n\"разположен на изток. Беше на път за там, където го очакваше по-нататъшно \"\n\"проучване. Този камък излъчваше особена енергия, която по някакъв начин ти \"\n\"даваше поглед отвъд това, което обикновеният човек можеше да си позволи да \"\n\"види. Не знам какви тайни крие той, приятелю, но намирането му със сигурност \"\n\"ще донесе много ползи.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Керванът спря тук, за да набави някои припаси за пътуването си на изток. \"\n\"Продадох им доста пресни плодове и малко от невероятните сладкиши, които \"\n\"Гарда току-що беше изпекла. Жалко е какво ги сполетя...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Не знам какво са си въобразявали, че ще видят в този камък, но ще ти кажа \"\n\"само едно. Ако от небето завалят камъни, по-добре внимавай!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Да, оттук мина керван с много важни хора, но това беше доста отдавна. \"\n\"Доколкото си спомням, говореха някак странно и се приготвяха за дълъг път.\\n\"\n\"\\n\"\n\"Не виждам как би могъл да се надяваш да намериш нещо, което те биха носили.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Почакай малко, имам една история, която може да ти се стори интересна. Преди \"\n\"известно време оттук мина керван, който се отправяше към източните кралства. \"\n\"Предполагаше се, че носи парче от небесата, което е паднало на земята! \"\n\"Керванът бе нападнат от маскирани ездачи северно оттук, следвайки този път. \"\n\"Претърсих останките за този небесен камък, но не можах да го намеря никъде. \"\n\"Ако го намериш, вярвам, че мога да изработя нещо полезно от него.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Още чакам да ми донесеш онзи камък от небесата. Сигурен съм, че мога да \"\n\"направя нещо могъщо от него.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Нека да видя - да... да, това е, както и предполагах. Дай ми малко време...\\n\"\n\"\\n\"\n\"Ааа, ето те. Подредих парчетата от камъка в сребърен пръстен, който ми \"\n\"завеща баща ми. Надявам се, че ще ти служи добре.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Някога имах хубав пръстен, изключително ценен, със синьо, зелено, червено и \"\n\"сребърно. Не си спомням, обаче, какво стана с него. Много ми липсва този \"\n\"пръстен...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Небесният камък притежава несъразмерима мощ и ако някой друг, освен \"\n\"Грисволд, ти предлагаше да го намериш, щях да го възпра. Той ще овладее тази \"\n\"сила и ще създаде нещо добро от нея в името на всички ни.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Ако някой може да създаде нещо от този камък, то това е Грисволд. Той знае \"\n\"какво прави и колкото и да се опитвам да открадна клиентите му, уважавам \"\n\"неговия труд.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Вещицата Адрия търси черна гъба? Знам толкова за черни гъби , колкото и за \"\n\"зелени коне. Може би лечителят Пепин ще ти е по-полезен, но това е нещо, \"\n\"което не може да се намери в нито една от моите истории или книги.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Нека ти кажа нещо. Двамата с Гарда никога, НИКОГА не бихме поднесли черни \"\n\"гъби на нашите почетни гости. Ако Адрия иска гъби в яхнията си, това си е \"\n\"нейна работа, но аз не знам откъде може да ги набавиш. Черни гъби... \"\n\"отвратително!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Разбрах от Вещицата, че търсиш мозък на демон, който би могъл да ми помогне \"\n\"да създам моят еликсир. Той ще бъде от голяма полза за мнозина, ранени от \"\n\"тези отвратителни зверове, само ако успея да разгадая тайните му, които \"\n\"подозирам, че крие неговата алхимия. Ако можеш да извадиш мозъка на демон, \"\n\"след като го убиеш и ми го донесеш, ще съм ти много благодарен.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Чудесно, именно това имах предвид. Успях да приготвя еликсира и без него, но \"\n\"няма да навреди да го имам за изучаване. Би ли занесъл мострата на вещицата? \"\n\"Мисля, че тя я очаква.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"Мисля, че Огдън може да има някакви гъби в мазето. Защо не го попиташ?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Ако Адрия няма една от тези, бъди сигурен, че това е настина рядко срещано \"\n\"нещо. Не мога да ти кажа нищо повече, но на мен ми звучи като... огромна, \"\n\"великанска, дебела, разплута, гъба! Е, в такъв случай, наслука.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Огдън смесва страховита черна гъба, но ми става лошо, ако я пия. Слушай, \"\n\"слушай... Знам аз тайната - умереното пиене е ключът!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Я да видим какво имаме тук? Интересно, изглежда е книга за реактиви. \"\n\"Оглеждай се за черна гъба. Трябва да е доста голяма и лесна за разпознаване. \"\n\"Ако я видиш някъде, ще ми я донесеш, нали?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Нуждая се от голяма, черна гъба. Побързай и ми я донеси, за да мога да \"\n\"завърша специалната отвара, върху която работя.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Да, това е достатъчно добро за отварата, което забърквам. Между другото, \"\n\"лечителят търси мозък от някакъв демон, за да може да цери онези, поразени \"\n\"от ужасната им отрова. Подозирам, че възнамерява да изготви еликсир от него. \"\n\"Ако му помогнеш да намери това, което му трябва, моля те, виж дали можеш да \"\n\"ми донесеш мостра от еликсира.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Защо го носиш на мен? Нямам нужда от този мозък в момента. По-скоро ми \"\n\"трябва еликсира, който лечителят приготвя. Дай му отвратителния орган, който \"\n\"държиш, и се върни с еликсира. Нищо сложно, като се замислиш, нали?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Какво? Чак сега ли ми носиш този еликсир от лечителя? Успях да довърша \"\n\"отварата и без него. Защо просто не го задържиш...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Не разполагам с гъби от какъвто и да е размер или цвят за продажба. Какво ще \"\n\"кажеш за нещо по-полезно?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Значи легендата за Картата е истина. Дори аз никога не съм вярвал дотолкова \"\n\"в това! Предполагам, че е време да ти разкрия истината кой съм всъщност аз, \"\n\"приятелю. Тъй като не съм това, което изглеждам на пръв поглед...\\n\"\n\"\\n\"\n\"Истинското ми име е Декард Кайн Старейшината и съм последният потомък на \"\n\"древно Братство, което се е посветило на опазването и съхраняването на \"\n\"тайните на едно вечно зло. Зло, което очевидно вече е освободено... \\n\"\n\" \\n\"\n\"Тъмнината срещу което се изправяш, е мрачния Господар на Ужаса, познат на \"\n\"смъртните като Диабло. Именно той е бил затворен в Лабиринта преди много \"\n\"векове. Картата, която държиш сега, е създадена преди стотици години, за да \"\n\"отбележи времето, когато Диабло ще се издигне отново от затвора си. Когато \"\n\"двете звезди на картата съвпаднат, Диабло ще бъде на върха на своята мощ. \"\n\"Той ще бъде почти непобедим...\\n\"\n\" \\n\"\n\"Сега си в надпревара с времето, приятелю! Намери Диабло и го унищожи, преди \"\n\"звездите да съвпаднат, защото може би никога повече няма да имаме възможност \"\n\"да отървем света от злото му!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Времето ни изтича! Чувствам как тъмната му сила нараства и само ти можеш да \"\n\"го спреш, преди да възвърне напълно могъществото си.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Сигурен съм, че си дал всичко от себе си, но се опасявам, че дори твоята \"\n\"сила и воля могат да се окажат недостатъчни. Сега Диабло е на върха на \"\n\"земната си мощ и ще се нуждаеш от всичката си смелост и сила, за да го \"\n\"победиш. Нека Светлината те закриля и води, приятелю мой. Ще ти помогна с \"\n\"каквото мога.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Ако вещицата не може да ти помогне и ти предлага да отидеш при Кайн, защо си \"\n\"мислиш, че аз ще знам нещо? Изглежда, че това е много сериозен въпрос. \"\n\"Трябва да побързаш и да говориш с разказвача, както предлага Адрия.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Не мога да разбера написаното на тази карта, но може би Адрия или Кайн ще ти \"\n\"помогнат да разбереш за какво се отнася. \\n\"\n\" \\n\"\n\"Виждам, че това е карта на звездите в нашето небе, но останалото е извън \"\n\"моите способности.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Най-добрият човек, когото можеш да попиташ за тези неща, е нашия разказвач. \"\n\"Кайн е много добре запознат с древните писания, а това е най-старинното \"\n\"парче хартия, което някога съм виждала.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Никога досега не съм виждал подобна карта. Откъде я взе? Въпреки че нямам \"\n\"представа как да я разчета, Кайн или Адрия може би ще успеят да дадат \"\n\"отговорите, които търсиш.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Изслушай ме, приближи се. Не знам дали знаеш това, което аз знам, но ти \"\n\"наистина имаш нещо тук. Това е карта.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Опасявам се, че това не вещае нищо добро. Тази карта на звездите предвещава \"\n\"голямо бедствие, но тайните ѝ не са мои, за да ги споделям. Дошло е времето \"\n\"да проведеш много сериозен разговор с Разказвача...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Търся една карта, но не е тази. Трябва да я покажеш на Адрия - тя вероятно \"\n\"ще ти обясни какво е това. Ще ти кажа едно: изглежда стара, а стара \"\n\"обикновено означава ценна.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Моооооля, не наранява. Не убива. Пази живот си и следващ път носи добро на \"\n\"теб.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Аз прави нещо за теб. Отново, не убива Гарбад. Живее и дава добро.\\n\"\n\" \\n\"\n\"Ти вземе това за уверение, че държи на дума...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Още нищо! Почти готово. \\n\"\n\" \\n\"\n\"Много мощен, много силен. Жив! Жив! \\n\"\n\" \\n\"\n\"Не болка и аз обещание спазва!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Това твърде добро за теб. Много мощен! Ти иска - ти получава!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Какво?! Защо правиш? Всички тези досадници могат за да докарат човек до \"\n\"лудост. Хайде, вземи това и ме остави да си върша работата. Не ме безпокой \"\n\"повече!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Ааааррх! Любопитството ти ще те вкара в гроба!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Здравей, приятелю. Остани за малко и слушай...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Навлизайки по-дълбоко в Лабиринта, ще откриеш скрити книги съдържащи велико \"\n\"познание. \\n\"\n\" \\n\"\n\"Прочети ги внимателно, защото те могат да ти разкрият неща, които дори аз не \"\n\"мога.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Знам много митове и легенди, които могат да съдържат отговори на въпроси, \"\n\"възникнали по време на странстването ти в Лабиринта. Ако се сблъскаш с \"\n\"предизвикателства и въпроси, за които търсиш знания, потърси ме и аз ще ти \"\n\"кажа всичко, каквото мога.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Грисволд - човек на големи дела и голяма смелост. Обзалагам се, че никога не \"\n\"ти е разказвал за времето, когато влезе в Лабиринта, за да спаси Върт, нали? \"\n\"Той е видял своя дял от опасностите, които го дебнат там, но от друга страна \"\n\"- ти също. Той е опитен занаятчия и ако твърди, че може да ви помогне по \"\n\"някакъв начин, можете да разчиташ на неговата честност и умения.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Огдън е собственик и управител на странноприемницата и гостилница \"\n\"'Изгряващото слънце' вече почти четири години. Той я купи само няколко \"\n\"месеца преди всичко тук да се превърне в Ад. Двамата със съпругата му Гарда \"\n\"нямат пари, за да си тръгнат, тъй като са вложили всичко, което са имали, за \"\n\"да си създадат живот тук. Той е добър човек с дълбоко чувство за отговорност.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Бедният Фарнам. Той е обезпокоителен спомен за обречената трупа, която се \"\n\"отправи в катедралата заедно с Лазар, в онзи мрачен ден. Спаси се на косъм \"\n\"от смъртта, но смелостта му и голяма част от разсъдъка му, останаха в някоя \"\n\"тъмна яма. Днес той намира утеха само на дъното на бъклицата си, но в \"\n\"постоянното му бърборене понякога се крие частица истина.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Вещицата Адрия е аномалия в Тристрам. Тя пристигна малко след като \"\n\"катедралата бе осквернена, докато всички останали са бягаха. Построи си една \"\n\"малка колиба в края на града, сякаш от нощ за ден и има достъп до много \"\n\"странни и загадъчни артефакти и томове със знания, които дори аз не съм \"\n\"виждал преди.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Историята на Вирт е ужасяваща и трагична. Той бе изтръгнат от ръцете на \"\n\"майка си и завлечен в лабиринта от малки, противни демони, носещи порочни \"\n\"копия. В онзи ден бяха отвлечени и много други деца, включително и синът на \"\n\"крал Леорик. Придворните рицарите се впуснаха надолу, но никога не се \"\n\"завърнаха. Ковачът намери момчето, но само след като мръсните зверове били \"\n\"започнали да го изтезават за свое садистично удоволствие.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ах, Пепин. Считам го за истински приятел, може би най-близкият, който имам \"\n\"тук. На моменти е малко отвеян, но никога не е съществувала по-грижовна и \"\n\"внимателна душа. Малцина могат да се похвалят с неговите знания и умения, а \"\n\"вратата му е винаги отворена.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Джилиан е прекрасна девойка. Тачена много заради доброто си настроение и \"\n\"бързия си смях, с което заема специално място в сърцето ми. Тя остана в \"\n\"гостилницата, за да се грижи за възрастната си баба, която е твърде болнава, \"\n\"за да пътува. Понякога се страхувам за нейната безопасност, но знам, че \"\n\"всеки мъж в селото би предпочел да умре, отколкото да я види наранена.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"\"\n\"Привет, добри господарю. Добре дошъл в Гостилницата на Изгряващото Слънце!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Много приключенци са седели на масите в моята таверна и десет пъти повече \"\n\"истории са били разказани на чаша пиво. Единственото нещо, за което някога \"\n\"съм ги чувал да се съгласяват, е тази стара поговорка. Може би тя ще ви \"\n\"помогне. Можеш да срежеш плътта, но трябва да строшиш костта.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Ковачът Грисволд е изключително компетентен по отношение на оръжията и \"\n\"доспехите. Ако някога имаш нужда от работа по снаряжението ти, определено \"\n\"трябва да се обърнеш към него.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Фарнам прекарва твърде много време тук, давейки мъката си в евтино пиво. Бих \"\n\"го накарал да си тръгне, но той е страдал неимоверно много докато е бил в \"\n\"Лабиринта.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Адрия е изключително мъдра за годините си, и трябва да призная, че това \"\n\"малко ме плаши. \\n\"\n\" \\n\"\n\"Е, няма значение. Ако някога ти се наложи да търгуваш с магически предмети, \"\n\"тя държи една необичайно добре снабдена колиба точно от другата страна на \"\n\"реката.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Ако искаш да научиш повече за историята на нашия град, разказвачът Кайн знае \"\n\"доста истории от миналото.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Върт е нехранимайко и малък мошеник. Винаги се забърква в неприятности и не \"\n\"е изненада какво му се случили. \\n\"\n\" \\n\"\n\"Вероятно е ходил да се шляе някъде, където не е трябвало да бъде. Съжалявам \"\n\"за момчето, но не понасям кръгът от приятели, които държи.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Пепин е добър човек - и със сигурност най-щедрият в града ни. Винаги се \"\n\"грижи за нуждите на другите, но където и да отиде, го преследват \"\n\"неприятности от един или друг вид...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Джилиан, моята ханджийка? Ако не беше чувството ѝ за дълг към баба ѝ , тя \"\n\"отдавна да бе избягала оттук. \\n\"\n\" \\n\"\n\"Бог знае, че я помолих да си тръгне, като й казах, че ще се грижа за \"\n\"старицата, но тя е твърде мила и грижовна, за да го направи.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Какво те мъчи, приятелю?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Достигнах до много интересно откритие. За разлика от нас, съществата в \"\n\"Лабиринта могат да се лекуват без помощта на отвари или магии. Ако нараниш \"\n\"някое от чудовищата, увери се, че то е мъртво, защото в противен случай може \"\n\"да се възстанови.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Преди да бъде завзета от, онова, което дебне долу, Катедралата бе дом на \"\n\"велико познание. Там лежат изгубени множество книги. Откриеш ли ги, трябва \"\n\"да ги прочетеш всичките, без значение на коя попаднеш, защото някои от тях \"\n\"може би пазят тайните на Лабиринта.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Грисволд знае толкова за изкуството на войната, колкото аз за изкуството на \"\n\"лечението. Той е опитен търговец, но работата му като ковач, е ненадмината. \"\n\"Предполагам, това се дължи на факта, че е единственият занаятчия, който \"\n\"остана.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Кайн - истински приятел и велик мъдрец. Притежава огромна библиотека и има \"\n\"вродената способност да разчита естеството на много неща. Ако имаш някакви \"\n\"питания, той е точният човек, към когото да се обърнеш.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Дори моите умения не са достатъчни да излекуват напълно Фарнам. Да, поне \"\n\"успях да възстановя физическото тяло, но разумът и духът са отвъд \"\n\"възможностите ми.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Макар да използвам незначителни форми на магия, за да правя отварите и \"\n\"еликсирите, които продавам тук, Адрия е истинска магьосница. Никога не спи и \"\n\"винаги разполага с най-различни тайнствени четива и артефакти. Определено \"\n\"колибата, в която живее, е много повече от това, което се вижда, но никога \"\n\"не мога да се добера вътре.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Горкият Върт. Направих каквото можах за това дете, но независимо от това, \"\n\"знам, че ненавижда дървеният кол, който се наложи да прикрепя към крака му. \"\n\"Имаше страшни рани. Никой, особено младеж, не трябва да преживява това, на \"\n\"каквото той е бил подложен.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Наистина не мога да си го обясня, защо Огдън решил да остане тук, в \"\n\"Тристрам. Въпреки, че страда от леки нервни разстройства, той е умен и \"\n\"трудолюбив човек, който би преуспял навсякъде. Предполагам, многото убийства \"\n\"в околностите или, най-вероятно са причината, за желанието на съпругата му \"\n\"държи него и семейството му тук.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Помощницата на Огдън, е хубаво момиче. Баба й е болна и страда от деменция.\\n\"\n\"\\n\"\n\"Тя твърди, че имала провидения - няма как да знам дали това е вярно или не.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Добър ден! С какво мога да бъда полезна?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Баба ми сънува, че двамата с теб ще се срещнем и ще говорим. Тя има видения \"\n\"и разчита бъдещето, ако не знаеш.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Жената в края на града, е вещица! Изглежда добронамерена и името ѝ, Адрия, \"\n\"звучи доста звънко, но тя много ме плаши.\\n\"\n\"\\n\"\n\"Може би трябва някой смелчага, като теб, да отиде да види какви ги върши.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Нашият ковач е гордост за жителите на Тристрам. Не само майстор-занаятчия, \"\n\"който има участия в множество конкурси в своята гилдия, но и носител на \"\n\"благословията на Крал Леорик - мир на праха му. Грисволд също е велик герой, \"\n\"само попитай Кайн...\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Кайн е разказвачът на истории на Тристрам откакто се помня. Знае толкова \"\n\"много, може да ти каже за всеки и за всичко.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Фарнам е пияница, пълни своят търбух с пиво, а ушите на останалите с \"\n\"небивалиците.\\n\"\n\"\\n\"\n\"Знам, че Пепин и Огдън го подкрепят, но това да го гледам как изпада и \"\n\"изпада във вцепенение, всяка нощ, ме обезсърчава.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Пепин спаси живота на баба ми, никога няма да мога да му се отблагодаря \"\n\"достатъчно за това. Дарбата му да изцерява всяка болест е много по-могъща от \"\n\"най-силния меч и много по-мистериозна от което и да е заклинание, за което \"\n\"се сетиш. Ако някога си в нужда от лечител, Пепин ще ти помогне.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Израснах заедно с майката на Върт, Канис. Макар да не беше сериозно ранена, \"\n\"когато тези безбожни чудовища го отвлякоха, тя никога успя да се възстанови. \"\n\"Умря съкрушена от случилото се. Върт отрасна като негодник, възползвайки се \"\n\"от труда на останалите. Знам, че е изстрадал много и е видял такива ужаси, \"\n\"каквито дори не мога да си представя, обаче част от това тъмно минало все \"\n\"още го преследва.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Огдън и жена му бяха така добри да ни приемат с баба ми в дома си, дори ми \"\n\"позволиха да припечелвам някой грош в странноприемницата. Длъжница съм им и \"\n\"искрено се надявам някой ден, когато си тръгна оттук, да им помогна да \"\n\"отворят голям хотел на изток.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Е, с какво мога да помогна?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Ако си търсиш сгодно оръжие, нека ти предложа нещо. Да речем, най-обикновено \"\n\"тъпо оръжие, като например боздуган. Върши чудесна работа срещу повечето \"\n\"страшилища, които ще ти се изпречат на пътя. Какво по-добро от това да \"\n\"строшиш грозни малки скелетчета на парчета!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Брадвата?  Да, добро оръжие, подходящо срещу всякакви противници. Погледни \"\n\"как разсича въздуха, сега си представи как острието минава през дебелата \"\n\"глава на демона. Имай в предвид, че е замахът е бавен, но за разлика от \"\n\"това, последващият ефект е поразителен!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Погледни острието, какъв баланс. Меч в правилните ръце и срещу правилния \"\n\"враг, е господар на всички оръжия. Острият връх няма какво толкова да \"\n\"разсече или прониже в немъртвите, но пък срещу живия, дишащ противник, мечът \"\n\"ще го разфасова!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Оръжията и доспехите ти ще търпят щети в борбата ти срещу Мрака. Донеси ми \"\n\"ги и с чука и малко работа над огнището, мога да ги направя като нови.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Докато практически нямам друг избор, освен да си набавям материали и \"\n\"инструменти чрез керваните, прекосяващи нашият проклет град от длъж и шир, \"\n\"тази вещица, Адрия, винаги получава всичко, от което има нуждае. Ако знаех \"\n\"дори и малко за това, как да използвам магията, както тя го прави, щях да \"\n\"правя наистина невероятни неща.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Джилиън е мила девойка. Жалко, че нейното бабе е с лошо здраве, иначе досега \"\n\"да съм уредил да ги измъкнат от тук с един от търговските кервани.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Понякога ми се струва, че Кайн говори твърде много. Може би защото това е \"\n\"неговото призвание. Ако можех да гъна стомана така, както той може да гъне \"\n\"думите, бих изковал ризница, като за Император!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Бях редом с Фарнам онази нощ, когато Лазар ни поведе към Лабиринта. Никога \"\n\"повече не видях Архиепископа, а и нямаше да съм жив сега, ако Фарнам не беше \"\n\"до мен. Лошото е, че след случилото се, душата му остана осакатена завинаги, \"\n\"така както и кракът ми. Не мога да водя тази битка заради него сега, а ми се \"\n\"иска да можех.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Добър човек, който слага нуждите на другите пред своите. Няма да намериш \"\n\"нито в Тристрам, нито където и да е другаде, някой да каже лоша дума за \"\n\"лечителя.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Този калпазанин ще се забърка в сериозни неприятности... отново, ако трябва \"\n\"да съм точен. Опитах да привлека вниманието му, да го накарам да работи тук \"\n\"и да вземе нещо от мен за честния търговски занаят, той обаче предпочете \"\n\"парите от търговията на стока със неизвестен произход. Не мога да го \"\n\"обвинявам в нищо, след това, което го сполетя и поне се надявам, да внимава.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Търговията на Кръчмарят не върви, и не може да спечели достатъчно от нея. \"\n\"Успява да свърже двата края, като предлага храна и подслон на онези, които \"\n\"от време на време се появяват в градчето, но много от тях се измъкват през \"\n\"нощта и често без да не му платят. Нямаше ли ги запасите от зърно и сушените \"\n\"меса, които пази в мазето си, болшинството от нас щяхме да гладуваме през \"\n\"първата година, когато цялата околия беше превзета от демоните.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Не може ли човек да пие на спокойствие?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"Девойчето, което сервира напитките? А, да, каква красавица. И е много мила, \"\n\"също.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Защо тази дърта кукумявка не се заеме да прави нещо за разнообразие. Да, да, \"\n\"ясно ми е, че има всичко, но, слушай какво ще ти кажа... има нещо \"\n\"необикновено в нея. Никога не съм я виждал да яде или да пие, а не можеш да \"\n\"се има вяра на някой, който не близва дори капка.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Кайн не е този, който твърди, че е. Добър разказвач е, безспорно... някои от \"\n\"историите са страшни, други смешни....  Мен ако питаш, знае много повече от \"\n\"това, което твърди, че знае.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Грисволд? Добрият стар Грисволд. Обичам го като свой брат! Бихме се рамо до \"\n\"рамо навремето, когато.... двамата.... Лазаре... Лазаре... Лазаре!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Хи-хи-хи, харесвам Пепин. Той наистина се старае. Слушай, трябва да го \"\n\"опознаеш по-отблизо. Добър човечец, който винаги е при онези, които се \"\n\"нуждаят от помощ. Ей, мисля си, че е като теб, герой, а? И аз някога бях \"\n\"герой...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Върт е хлапе с повече проблеми, дори и от мен, и аз знам доста за това. \"\n\"Слушай, на това момче сега му върви добре, но то беше там, нали разбираш? \"\n\"Загуби си крака! Сега ходи на дървен кол. Колко жалко, колко жалко..\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Огдън - най-свестният мъж в града. Не мисля, че жена му ме харесва особено \"\n\"много, но докато тя отваря бъчвите, нямам нищо против това. Напоследък \"\n\"прекарвам повече време с Огдън, отколкото с останалите, но поне той ме \"\n\"оценява....\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Искам да ти кажа нешщо, 'щото аз ги зная тия работи. То ми е в кръвта. Т'ва \"\n\"тук е най-доброто.... нааааааай-доброто!  Другото пиво вече не струва откак \"\n\"тия нехранимайковци....\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Никой вече не ме слу... (хлъц) не ме слуша. Нейде, и аз не знам точно къде, \"\n\"но там долу, под църквата, лежи голямо имане. Блещука, сияе, само чака някой \"\n\"да го намери.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Знам, имаш свои виждания, и още по-добре знам, че няма да повярваш, но това \"\n\"оръжие, твоето - няма да те спаси от тези огромни гадове! Не ме интересува \"\n\"какво твърди Грисволд, вече не правят нищо така, както беше навремето.\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Ако бях теб.... а не съм.... но ако бях, щях да продам всичко и да се махна \"\n\"оттук. Онова момче там... то винаги има добро предложение, но за да ти го \"\n\"покаже, трябва първо да му платиш.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Усещам душа, в търсене на отговори...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Мъдростта се придобива, не се дава. Ако откриеш книга със знанията, погълни \"\n\"думите й. Ако вече имаш знанията за мистериозните тайни, описани в книга, \"\n\"запомни - обсегът на тази материя винаги може да се задълбочи.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Най-великата сила често е най-краткотрайната. Може да откриеш древни думи на \"\n\"могъществото, запечатани в свитъци от пергамент. Силата на тези свитъци се \"\n\"крие във възможността всеки начинаещ или напреднал, да ги използва с еднакъв \"\n\"резултат. Докато слабостта им е там, че трябва да бъдат прочитани на висок \"\n\"глас и никога наизустявани. Също така, знай, че могат да бъдат прочитани \"\n\"само веднъж, използвай ги разумно.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Макар слънчевата топлина да е неизмерима, пламъци на една свещ представляват \"\n\"много по-голямата опасност. Няма енергия, независимо колкото велика да е тя, \"\n\"която може да бъде ползвана, без подходящото съсредоточение. За много от \"\n\"заклинанията, омагьосан Жезъл може многократно да бъде наситен със заряди от \"\n\"магическа енергия. Имам способността да възстановя тяхната сила, но нищо не \"\n\"идва без своята цена.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Сборът от нашите знания е сборът от хората които го имат. Намериш ли книга \"\n\"или свитък, който е непознат за теб, не се притеснявай да го донесеш на мен. \"\n\"Успея ли да го разчета, ще споделя каквото знам.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"За човекът, който познава единствено Желязото, няма по-голяма магия от \"\n\"Стоманата. Ковачът Грисволд е магьосник, повече отколкото той може да \"\n\"осъзнае. Уменията му да топи огън и метал нямат равни по тези земи.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Покварата борави със силата на измамата, а невинността надделява със силата \"\n\"на непорочността. Младата девойка, Джилиън, има непокорно сърце, което \"\n\"поставя на преден план нуждите на баба ѝ пред нейните собствени. Тя се бои \"\n\"от мен, но това е така, защото не ме разбира.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Отворен в мрака сандък не ще даде по-голямо съкровище, ако бъде отворен на \"\n\"светло. Разказвачът Кайн е загадка, но само за онези, които не внимават. \"\n\"Знанията му относно онова, което се намира под катедралата, са много по-\"\n\"големи от това, което той си позволява да осъзнае.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"На колкото по-високо се намира вярата ти в един човек, от толкова по-високо \"\n\"ще и трябва, за да падне. Фарнам загуби душата си, но не от демон. Загуби я, \"\n\"когато видя как архиепископ Лазар предаде своите съграждани. Той разполага с \"\n\"знания, от които може да черпиш, но трябва да разделиш фактите от нереалното.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Ръката, сърцето и разумът могат да постигнат чудеса, когато се намират в \"\n\"пълна хармония. Лечителят Пепин вижда в тялото така, както аз не мога. Тази \"\n\"негова способност да вдига на крака болните и ранените се усилват от \"\n\"разбиранията му за елексирите и отварите. Той е толкова полезен съюзник в \"\n\"Тристрам, като никой друг.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Има толкова много неща в бъдещето, които не можем да предвидим, но когато \"\n\"времето настане, децата са онези, които ще ги поемат. Момчето, Върт, има \"\n\"черно петно надвиснало над душата, но той не представлява опасност за града \"\n\"и неговите жители. Тайните му пазарлъци с хлапаците и неспоменавани гилдии \"\n\"от околните градове, му осигуряват достъп до много средства, които не могат \"\n\"да бъдат намерени лесно в Тристрам. Но макар неговите методи да са позорни, \"\n\"Върт може да ти помогне в битката срещу нахлуващия Мрак.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Глинените стени и сламените навеси не градят дом. Кръчмарят, Огдън, \"\n\"допринася много повече в този град, отколкото мнозина осъзнават. Осигури \"\n\"подслон на Джилиън и баба ѝ, поддържа Фарнам на крака доколкото може и служи \"\n\"за крайъгълен камък напомнящ на всеки, останал в това градче, какво беше \"\n\"някога беше Тристрам. Неговата гостилница и обикновените забавления, които \"\n\"се предлагат там, връщат за момент глъчката от живота, който жителите \"\n\"помнят. Точно този спомен продължава да крепи надеждите им за твоя успех.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Пссст... насам...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Не всеки в Тристрам има приложение или пазар за всичко, на което ще се \"\n\"натъкнеш в лабиринта. Нито аз, колкото и трудно да е за вярване.\\n\"\n\"\\n\"\n\"Понякога, единствено ти самия можеш да намериш предназначение за нещата, \"\n\"които откриеш.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Не вярвай на всичко, което идва от устата на пияницата. Прекалено много пиво \"\n\"е замъглило зрението и разума му.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"В случай, че не си забелязал, не купувам нищо от Тристрам. Внасям само \"\n\"високо-качествени стоки. Ако имаш боклуци за продан, иди при Грисволд, Пепин \"\n\"или оная вещерица, Адрия. Със сигурност ще вземат каквото и да им занесеш.\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Дължа живота си на ковача, колкото и да не ми се ще - или поне това, което е \"\n\"останало от него. Да, Грисволд е достатъчно свестен и ми предложи да бъда \"\n\"чирак в ковачницата. Но парите няма да ми стигат, за... нека кажем, че имам \"\n\"сериозни планове, които изискват доста злато.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Ако бях малко по-възрастен, щях да я обсипя с всички богатства, които мога \"\n\"да събера и повярвай ми, мога да се сдобия с доста хубави неща. Джилиън е \"\n\"красавица, но трябва да се махне от Тристрам, възможно най-скоро. Хммм... \"\n\"може би... може би ще я взема със себе си, когато тръгна....\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Кайн знае твърде много. Плаши ме до смърт, много повече от онази жена \"\n\"оттатък реката. Той продължава да ми натяква какъв късметлия съм, че съм жив \"\n\"и как историята ми е предсказана в легенда. Защо ли си мисля, че не е наред \"\n\"с главата.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Фарнам - виж, това вече е човек със сериозни проблем, а на мен ми е пределно \"\n\"ясно колко сериозни могат да бъдат някои проблеми. Довери се твърде много на \"\n\"почтеността на един определен човек, а той го отведе право в пастта на змея. \"\n\"О, доста добре знам как е там долу, така че не ми идвай с тези приказки, че \"\n\"искаш да унищожиш злото, тегнещо над Лабиринта. Пази си краката...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Поне докато не се налага да съединяват крайници, старият Пепин ще ти свърши \"\n\"добра работа.\\n\"\n\"\\n\"\n\"Само да имах от онези отвари, които той приготвя, сега можеше и да ходя \"\n\"нормално.\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Адрия ме кара да настръхвам. Да, Кайн е странен, заради това, което може да \"\n\"ти наприказва за миналото, но Вещицата може да разчете твоето лично минало. \"\n\"Тя също винаги намира начини да се сдобие с онова, което и е необходимо. \"\n\"През ръцете й минава повече стока от всичкото, което съм виждал да минава \"\n\"през портите на Кралския пазар по времето на Големия панаир.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Огдън е глупак, задето остана тук. Мога да го изкарам от града срещу скромна \"\n\"сума, но той продължава да опитва да печели от проклетата кръчма. Поне \"\n\"прибра Джилиън и ѝ даде работа, а жена му, Гарда, прави невероятен Овчарски \"\n\"пай...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Отвъд Залата на Героите се намира Камерата на Костите. Нетленна смърт грози \"\n\"всеки, който се осмели да открадне съкровищата, съхранени в това място. Така \"\n\"каза Господарят на Ужаса и така бе написано.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...и тъй, заключена зад Портата на Кръвта и скрита отвъд Залата на Огъня, \"\n\"Доблестта очаква Героят на Светлината, за да бъде пробудена...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Аз виждам неща които ти убягват. \\n\"\n\"Мътни образи гниещи очи замазват. \\n\"\n\"Обърнеш ли се, вече чезнат. \\n\"\n\"В неведение скрита песен шепнат. \\n\"\n\"Изведнъж наблюдаваш ти поврат,\\n\"\n\"Где бе светлина, тъдява сенки бродят.\\n\"\n\"Далеч от разума, далеч в тъмите, \\n\"\n\"Безнадежден в Залите на Слепите.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Оръжейните на Ада са дом на Кървавия Пълководец. Зад него лежат разчленените \"\n\"трупове на хиляди. Ангели и хората са посечени, за да задоволят неговите \"\n\"нестихващи жертвоприношения за Мрачните, които стенат за едно нещо - кръв.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Бъди бдителен и обследвай истините, които лежат тук, защото те са последното \"\n\"наследство на Хорадрим. Има война бушуваща дори в този час, отвъд земите \"\n\"които познаваме - между утопичните царства на Високите небеса и хаотичните \"\n\"бездни на Горящия ад. Тази война, известна като Великия сблъсък е вилняла и \"\n\"горяла по-дълго от която и да е от звездите в небето. Нито една от страните \"\n\"не взема надмощие, докато силите на Светлината и Мрака постоянно воюват за \"\n\"контрол над всичко живо.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Бъди бдителен и обследвай истините, които лежат тук, защото те са последното \"\n\"наследство на Хорадрим. Когато Вечният конфликт между Високите небеса и \"\n\"Горящия ад, докосне земите на смъртните, се назовава Войната на Греха. \"\n\"Ангели и Демони странстват между хората в прикритие, сражавайки се потайно, \"\n\"далеч от зорките погледи на простосмъртните. Някой дръзки и могъщи смъртни, \"\n\"са влизали в съюз с една от двете страни, диктувайки хода на Войната на \"\n\"Греха.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Бъди бдителен и обследвай истините, които лежат тук, защото те са последното \"\n\"наследство на Хорадрим. Преди приблизително три столетия, стана известно, че \"\n\"тайнствените Трите Върховни Злини на Горящия ад, са дошли в нашия свят. В \"\n\"продължение на десетилетия, Тримата братя опустошат земите на изток, докато \"\n\"човечеството е оставено да тъне в разруха. Нашият орден, Хорадрим, бе \"\n\"основан от група магьосници, с цел да открие и залови Трите Върховни Злини \"\n\"веднъж и завинаги.\\n\"\n\"\\n\"\n\"Първите Хорадрим запечатаха двама от тях в могъщи артефакти, наречени Камъни \"\n\"на душата и ги заровиха дълбоко под самотните източни пясъци. Третото зло \"\n\"успява да избяга от плен и поема на запад, преследван от множество Хорадрим. \"\n\"Трето и последно зло - наричано още Диабло, Господарят на Ужаса, в \"\n\"последствие бива заловен и запечатан в Камък на душата и заровен в този \"\n\"Лабиринт.\\n\"\n\"\\n\"\n\"Знай, че този Камък не трябва да бъде откриван от тези, които не са \"\n\"посветени на ордена. Бидейки освободен, Диабло ще опита да се всели в тяло, \"\n\"което лесно може да бъде контролирано, тъй като ще е много отслабен, \"\n\"например това на старец или на дете.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"И така стана, че в Горящия ад започна велика революция - нарекоха я Тъмното \"\n\"изгнание. Малките злини свалиха от власт Трите Върховни Злини и запратиха \"\n\"техните душевни облици в Царството на смъртните. Демоните Белиал - \"\n\"Господарят на Измамата и Азмодан - Господарят на Греха, се сражаваха за \"\n\"власт над Ада, докато Тримата братя са заточени. Адът бива разделен между \"\n\"лагерите на Белиал и на Азмодан, в момент, в който Високите небеса \"\n\"продължително удряха върху Портите на Ада.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Много демони се отправиха към Царството на смъртните, за да търсят Тримата \"\n\"братя, последвани от Ангелите в света на смъртните, които ги преследваха \"\n\"през обширните градове на Изток. Ангелите се съюзиха с потайния Орден на \"\n\"смъртните магьосници на име Хорадрим, които бързо станаха изкусни в лова на \"\n\"демони. Така те си създадоха множество врагове в подземните светове.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"И така стана, че душите на Трите Върховни злини бяха заточени в Царството на \"\n\"смъртните, всявайки хаос десетилетия наред сред земите на Изтока, те биват \"\n\"заловени от прокълнатия Орден на смъртните Хорадрим. Хорадрим използваха \"\n\"артефакти, наречени Камъни на Душата, за да съхранят същността на Мефисто - \"\n\"Господарят на Омразата и неговия брат, Баал - Господарят на Унищожението. \"\n\"Най-младият брат, Диабло, Господарят на Ужаса, бяга на запад.\\n\"\n\"\\n\"\n\"Рано или късно, Хорадрим залавят Диабло в Камък на душата. и го заравят под \"\n\"древната, забравена Катедрала. Там, Господарят на Ужаса спи и изчаква \"\n\"моментът на своето възраждане. Знай, че той ще потърси младо тяло носещо \"\n\"власт, такова, което лесно може да обладае - невинно и лесно контролируемо. \"\n\"Тогава той ще се надигне, за да освободи братята си и отново ще наклади \"\n\"огньовете на Войната на греховете.\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Все хвала за Диабло - Господар на Ужаса и Оцелял от Мрачното изгнание. \"\n\"Когато той се пробуди от дълбокия си сън, моят Господар и Учител, ми разкри \"\n\"тайни, които малцина смъртни знаят. Той ми описа как кралствата на Високите \"\n\"небеса и бездните на Горящия ад, водят вечна война. Показа ми силите, които \"\n\"са довели този раздор в света на човека. Моят Господар назова конфликта на \"\n\"този свят и всички останали, които съществуват, Войната на Греха.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Слава и признание за Диабло - Господар на Ужаса и Водач на Тримата. Моят \"\n\"Господар ми разказа за неговите двама братя, Мефисто и Баал, които били \"\n\"запратени на този свят преди векове. Той желае да отдаде времето си да \"\n\"възстанови своята невероятната сила, за да освободи пленените си братя от \"\n\"техните гробници, дълбоко под пясъците на изток. И когато Господарят разбие \"\n\"оковите им, Войната на Греха отново ще усети яростта на Тримата.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Приветствия и жертвувания за Диабло - Господар на Ужаса и Унищожител на \"\n\"Души. Когато пробудих моя Господар от съня, той се опита да приеме образа на \"\n\"смъртен. Диабло опита да завземе тялото на Крал Леорик, но моят Господар \"\n\"нямаше сили, задето беше държан в плен. Моят Повелител се нуждаеше от проста \"\n\"и невинна котва на този свят и той намери малкия Албрихт да бъде най-\"\n\"подходящият за задачата. Докато, в това време, добрият Крал Леорик изпадаше \"\n\"в лудост заради неуспешното вселяване на Диабло, аз отвлякох сина му, \"\n\"Албрихт и го отведох при моя Господар. Сега, очаквам Диабло да вземе решение \"\n\"и се надявам, че усилията ми ще бъдат възнаградени, когато той бъде \"\n\"провъзгласен за Владетел на този свят.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Слава богу, че се завърна!\\n\"\n\"Доста неща се промениха откакто си замина, приятелю. Цареше мир, докато не \"\n\"минаха Мрачни ездачи и опустошиха градчето ни. Мнозина завариха смъртта си \"\n\"на място, а онези, осмелили се да вдигнат оръжие, бяха жестоко разсечени, \"\n\"взети за роби или ги застигна нещо още по-лошото. Църквата в края на града \"\n\"бе осквернена и ползвана за мрачни ритуали. Писъците, които се чуват през \"\n\"нощта оттам, са нечовешки, но някои от съжителите ни може и да е оцелял. \"\n\"Следвай пътеката, минаваща между моята гостилница и ковачницата, за да \"\n\"стигнеш до църквата и спасиш когото можеш.\\n\"\n\"\\n\"\n\"Може би ще можем да си поговорим по-обширно някой друг път. Успех.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Не прекратявай твоето търсене. Да намериш изгубено съкровище, не е никак \"\n\"лесно. Но да намериш съкровище, което е скрито, е още по-трудно. Ще ти кажа \"\n\"следното. Не позволявай на пясъците на времето да попречат на твоето търсене.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Какво?! Що за глупост!? Тук, в Тристрам, няма заровено съкровище. Нека да \"\n\"погледна! А, виж, тези очертания са неверни. Изобщо не съвпадат с тези \"\n\"нашето градче. Аз бих се съсредоточил над това, което се намира под \"\n\"катедралата, не върху това, което е под тревата.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Нямам време да обсъждам някаква карта, която търсиш. Има доста болни хора, \"\n\"които се нуждаят от моята и от твоята помощ.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Някогащният горд Исвол, сега е окован дълбоко под повърхността на този свят, \"\n\"лишен от честта си и с изменена същност. Затворен е в капана на безсмъртни \"\n\"мъчения, задължен да скрие единственото нещо, което може да го освободи.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Готов съм да се обзаложа, че когато Върт те е видял да идваш, и ти е скроил \"\n\"някакъв номер, така че да може да ти се присмива когато бягаш из града с \"\n\"нос, заврян в калта. Не му обръщай внимание.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Навремето, този град беше честа спирка за пътешествениците от всички краища \"\n\"на земята. Много неща се промениха оттогава. Но тайните пещери и заровените \"\n\"съкровища са винаги в главите на децата. Върт рядко взема участие в \"\n\"юношеските игри. Така че може просто да си въобразява.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Слушай. Ела по близо. Не знам дали знаеш, каквото аз знам, но действително \"\n\"носиш нещо интересно. Това е карта.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Моята баба често ми разказва истории за някаква странна сила, обитаваща \"\n\"пределите на гробището до църквата. Може би ще ти е интересно да чуеш една \"\n\"от тях. Тя ми прошепна, че ако оставиш подходящия дар в гробището, влезеш в \"\n\"катедралата, за да се помолиш за душите на мъртвите и се върнеш обратно, \"\n\"оставеният предмет щял да придобие друг вид. Не знам дали това е просто \"\n\"измислица в главата на една болна старица, но пък, всичко изглежда възможно \"\n\"тези дни.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Хммммм. Огромно и тайнствено съкровище. М-м-м. Може и да се заинтересовам да \"\n\"купя някои неща от теб. Или всъщност, не ти ли трябват редки и ценни \"\n\"материали, които да те преведат през това изпитание?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"А, значи ти си героят, за когото всички говорят. Навярно можеш да помогнеш \"\n\"на един беден, прост фермер, да се спаси от беда? На юг от тук, в края на \"\n\"овощната ми градина, има някакво ужасно подуване, излизащо от земята и \"\n\"препречва пътя. Не мога да стигна до моя посев или до балите сено, кравите \"\n\"ми нямат какво да ядат. Вещицата ми даде това и ми каза, че ще гръмне това \"\n\"нещо далеч от нивата. Ако можеш да го унищожиш, ще ти бъда благодарен до \"\n\"живот. Не искам да оставям кравите без надзор, иначе бих го направил сам.\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Предусещах, че няма да е толкова лесно, колкото вещицата го изкара, че ще е. \"\n\"Жалко място е светът, когато не можеш да се довериш на съседите си.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Няма го? Изпрати ли го обратно във владенията на Хадес, откъдето се е \"\n\"пръкнало? Е? Само не ми казвай, че го загуби! Тези неща струват скъпо, дано \"\n\"разбираш. Трябва да го намериш и да гръмнеш този ужас извън града ни.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Чух тътена от тук. Много ти благодаря, драги ми страннико. Не знам какво \"\n\"става, нито откъде се взеха тези неща, излизащи от земята, чудовищата \"\n\"завладяващи църквата и всичко останало. Живеем в тежки времена. Аз съм беден \"\n\"фермер, но ето, това е за теб, моят начин да се отблагодаря.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"О, каква беда си навлякох... може би... Не, не мога да те забърквам в това, \"\n\"при всичките други проблеми. Може би, после, след като поразчистиш църквата \"\n\"от тези същества, можеш да се върнеш... и да отделиш малко време, за да \"\n\"помогнеш на един беден фермер?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Аа-а-ааа! (подсмърча) Ааа-аа-а!(подсмърча)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Загубих Тео! Загубих най-добрия си приятел! Играехме си при реката, Тео \"\n\"искаше да отиде да види какво е онова голямо зелено нещо. Казах му, че не \"\n\"трябва да го прави, но... отидохме до него и изведнъж тази голяма буболечка \"\n\"се показа! Побягнахме, но Тео се спъна и тя го отвлече!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Намери ли го? Трябва да намериш Теодор, моля те! Той е толкова малък. Не \"\n\"знае да се грижи за себе си! Умолявам те!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Намерил си го! Намерил си го! Благодаря ти! О, Тео, тези гадни буболечки, \"\n\"изплашиха ли те? Ей! Ъъъ! Нещо се е лепнало за козината ти! Блах! Хайде, \"\n\"Тео, да се връщаме у дома! Благодаря ти отново, геройски персонаж!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Ние бяхме в дълга летаргия и настана време да се събудим. А след толкова \"\n\"много сън, изпитваме велик глад. Скоро, ще се нахраним...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Забавлявал ли си се досега, малки бозайнико? Колко жалък си. Твоят малък \"\n\"свят изобщо няма да бъде предизвикателство.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Тези земи ще бъдат осквернени и нашето челяд ще завземе полетата, които \"\n\"хората наричат домове. Нашите пипала ще хванат в прегръдка този свят и ние \"\n\"ще се храним от плътта на неговите обитатели. Човекът ще бъде наш скот и \"\n\"препитание.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Надушвам те... на близо си! Близо! Ссссс... мирисът на кръв и страх... колко \"\n\"съблазнително...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"И в годината на Златната Светлина, било речено да бъде издигната велика \"\n\"Катедрала. Основоположният камък на това свето място трябвало да бъде \"\n\"издялан от прозрачния камък Антираел, кръстен в чест на Ангела, споделил \"\n\"своята сила с Хорадрим.\\n\"\n\"\\n\"\n\"В годината на Застилащите сенки, земята се потресе и Катедралата се напука и \"\n\"рухна. Когато започнал строежът на катакомби и замъци започна наново и \"\n\"човека се изправи пред разрухата на Войната на Греха, руините бяха преровени \"\n\"за камъни. Така, крайъгълният камък изчезна от погледа на човека.\\n\"\n\"\\n\"\n\"Камъкът принадлежи на този свят и на всички други светове, също както \"\n\"Светлината, е вътре и отвъд всичко. Светлината и единството са плодовете от \"\n\"тази свята основа, единство за намерения и единство за притежание.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Муу.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Казах: муу.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Виж, аз съм крава, Ясно ли е?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Добре де, добре де, Не съм всъщност крава.  Обикновено не се разхождам така, \"\n\"но както си седя вкъщи вършейки моите си работи, изведнъж всички тези твари, \"\n\"пълзящи храсти, луковици и разни работи, започнаха да никнат от пода... \"\n\"страшно беше!  Ако само имах нещо нормално, което да облека, нямаше да е чак \"\n\"толкова зле.  Хей! Можеш ли да отидеш у дома и да ми донесеш костюма?  \"\n\"Кафявият по-точно, не сивия - той е вечерно облекло.  Бих го направил сам, \"\n\"но не искам никой да ме вижда в този вид.  Ето, вземи това, може да ти \"\n\"потрябва...  за да отстраниш тези неща, избуяли навсякъде.  Няма как да \"\n\"пропуснеш дома ми, на юг при разклонението на реката... онази с избуялата \"\n\"зеленчукова градина...\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Какво чакаш още? Отиди да вземеш костюма ми! И побързай! Това Холщайнско \"\n\"говедо отсреща продължава да ми намигва!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Е, взе ли костюма ми? Хайде, дай ми го! Ушите така ме сърбят така, че си \"\n\"нямаш и представа!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Не-не-не! Това е СИВИЯТ костюм! Той е вечерното облекло! За специални \"\n\"случай! Не мога да облека ТОВА. Ти, да не би да имаш проблеми със слуха? \"\n\"Трябва ми КАФЯВИЯ.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Е, това вече е много по-добре. Ааах! Най-накрая, нещо свястно!  Я кажи, \"\n\"рогата прави ли са? Добре. Виж, много ти благодаря, че ми помогна. Така, \"\n\"това е подарък за теб и още нещо... един съвет за външния вид... можеш да \"\n\"използваш малко... и нови.... нали разбираш, какво имам предвид? Този \"\n\"приключенски стил... твърде старомоден е. Просто съвет, нали? Чао.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Виж. Аз съм крава. А ти - стръв за зверовете. Първо натрупай опит! И ще \"\n\"говорим....\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Определено трябва да съм ти поставил доста страховита задача. Ако имаше друг \"\n\"начин да... Дали бутилка с хубаво прясно мляко, ще ти свърши ли работа?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Ооо, Може да възползвам от помощта ти, но трябва да разчистиш катакомбите от \"\n\"напастта, която ги обитава.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Имам една несвършена работа, но така и не мога да попадна на точния човек. \"\n\"Може би, ако си прекарал известно време в града, ще ми е по-удобно да те \"\n\"попитам.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"У теб виждам потенциал за величие. Може би, някой път, докато вървиш по пътя \"\n\"определен от съдбата, можеш да се отбиеш и да ми направиш една услуга?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Мисля, че можеш да ми помогнеш, но все още си твърде немощен. Не искам да \"\n\"пропилея единствения шанс селото да бъде избавено от напастта, върлуваща \"\n\"около църквата!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Аз ? Аз,съм самоиздигната крава. Направи и ти нещо от себе си... тогава ще \"\n\"говорим.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Не съм длъжен да се представям на всеки турист, който минава оттук! Нямаш ли \"\n\"си работа? Може би ще говорим по-късно. Ако все още си жив...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Престани да ме разиграваш. Търся някой със способностите на герой. А ти не \"\n\"си това. Не мога да ти се доверя, имаш вид на някой, който ще го схрускат \"\n\"зверовете всеки момент. Трябва ми някой с опит.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Добре, ще карам направо. Не исках да те вкарвам в заблуждения. Та, както си \"\n\"седя у дома, в приятно настроение, изведнъж нещата излязоха извън контрол - \"\n\"цели пълчища твари заизлизаха от пода! Избягах. Точно в този момент носех \"\n\"този пуловер, когато побягнах през вратата и сега, виж ме, изглеждам \"\n\"потресаващо. Де да имах нещо нормално, което да облека, нямаше да е лошо.  \"\n\"Ей! Можеш ли да отидеш вкъщи и да вземеш костюма ми? Имам предвид кафявия, \"\n\"не сивия - той е вечерно облекло. Нямам нищо против да отида сам, но не \"\n\"искам да ме виждат така. Вземи това, може да ти потрябва.... да си проправиш \"\n\"път през избуялите навсякъде гадинки. Къщата не може да подминеш, тя се \"\n\"намира на юг от разклонението на реката... Онази с буйната зеленчукова \"\n\"градина.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Опитах с заклинания, заплахи, прочистване и дори преговори с това покварно \"\n\"създание - без успех. Методите ми за заробване на малки демони, не \"\n\"подействаха при този страховит звяр.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Домът ми постепенно бива покварен от сквернотата на този нежелан затворник. \"\n\"В Криптите витаят множество силуети, на ръба на моя поглед. Плахото дращене \"\n\"от ноктите танцува на ръба на слуха ми. Те търсят дневника, мисля, този \"\n\"летопис.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"В яростта си, създанието издаде своето име -- На-Крул. Опитах да проуча \"\n\"името, но по-малките демони някак успяха да унищожат библиотеката ми. На-\"\n\"Крул.... Това име ме изпълва със студен страхопочитание. Предпочитам да го \"\n\"назовавам като Създанието, отколкото да промълвя истинското му име.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Яростното виене на това оковано същество не ми дават покой. Изглежда, излива \"\n\"яростта си по онзи, който го е изпратил в Бездната и ме проклина, задето съм \"\n\"оковал тук. Думите му, вкаменяват сърцето ми, и не мога да ги спра да ги \"\n\"чувам.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Времето ми бързо изтича. Трябва да запиша методите, чрез които мога да \"\n\"омаломощя демона и да скрия записките, в случай, че неговите слуги се опитат \"\n\"да използват знанията ми, за да освободят своя господар. Надявам се, че \"\n\"онзи, който открие този дневник, ще потърси знанието.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Онзи, който открие този свитък, е отговорен да спре демоничното създание зад \"\n\"тези стени. Моето време свърши. Дори в този момент, неговите дяволски слуги, \"\n\"гневно дращят по крехката вратата, зад която се крия.\\n\"\n\"\\n\"\n\"Отнех силите на демона чрез мистериозно заклинание и го запечатах между \"\n\"велики стени, но се опасявам, че това няма да е достатъчно.\\n\"\n\"\\n\"\n\"Заклинанията, описани в моите три гримоарa, ще ти осигурят безопасен достъп \"\n\"до неговото владение, но само, ако ги прочетеш в правилния ред. Лостът при \"\n\"входа, ще вдигне барикадата и освободят демона - не го докосвай! Използвай \"\n\"единствено силата на заклинанията, за да преминеш, инак рискуваш да не можеш \"\n\"да го победиш.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Адски глиган\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Бодливец\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Психорба\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Арахнон\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Изпаднал близнак\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Хоркски Отрок\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Отровопашка\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Некроморб\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Паяк Властелин\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Шибачервей\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Факлоплюец\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Адско насекомо\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Гробар\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Гробен плъх\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Огнен прилеп\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Черепокрил\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Лич\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Демон от Криптата\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Адски прилеп\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Костен демон\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Архи-лич\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Биклоп\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Буцаплът\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Жътвар\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Великански Юмрук\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Непредвидим Пръстен\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Пръстен на Зорийн\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Пръстен на Карик\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Пръстен от Магма\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Пръстен на Тайнствата\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Пръстен на Гръмотевицата\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Амулет на Бдението\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Дразнещо жило\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Пламокрасен\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Мрачна Броня\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Мълнистен\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Гръмопер\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Шиторачи\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Поглъщач на Души\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Диамантенострие\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Костна ризница\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Демонски доспехи\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Псалтски амулет\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Гладиаторски пръстен\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Шегаджийски\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Прозрачни\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Двойнишки\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"Опустошението\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"Разпадането\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"Угрозата\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"на Магьосника\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"на Шута\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Светкавична стена\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Имолация\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Пространствен скок\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Отразяване\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Обезумялост\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Пръстен на Огъня\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Издирване\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Руна за Огън\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Руна на Светлината\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Руна на Нова\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Руна на Изгарящ погром\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Руна за Вкаменяване\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Настройки:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"версия {:s}\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Намаляване Гама\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Увеличаване Гама\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Авто-картата не е достъпна в града\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Презареждане в града\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Сърце\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"възстановява живот\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"смъртоносно изцеление\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"намалява сила\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"намалява сръчност\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"намалява жизненост\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"не може да се лекувате\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"поразен враг не може да се лекува\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"по-бърз удар с замах\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"гледай с инфразрение\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Опит за хвърляне на предмет от пода?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Включва режим на Вертикална синхронизация. Предотвратява разкъсващ ефект \"\n#~ \"при изобразяване на всеки кадър. Изключването може да помогне с забавяне \"\n#~ \"на курсора на мишката при някои конфигурации.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Лимит на Кадри\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Броят на кадри е лимитиран за да намали използването на процесора. Лимита \"\n#~ \"е свързан с текущата честота на монитора.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"\"\n#~ \"Шанс\\n\"\n#~ \" за удар\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Неуспешно отваряне на файла на играча за запис.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Неуспешно прочитане на архив за записен файл\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Неуспешно записване в архив за записен файл\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Неразрушими,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Няма изисквани атрибути\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"Отвъд Залата на Героите се намира Камерата на Костите. Нетленна смърт \"\n#~ \"грози всеки, който се осмели да открадне съкровищата, съхранени в това \"\n#~ \"място. Така каза Господарят на Злото и така бе написано.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"Оръжейните на Ада са дом на Кървавия Пълководец. Зад него лежат \"\n#~ \"разчленените трупове на хиляди. Ангели и хората са посечени, за да \"\n#~ \"задоволят неговите нестихващи жертвоприношения за Мрачните, които стенат \"\n#~ \"за едно нещо - кръв.\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Днес е облачно и хладно. Докато спусках мрежите на некромантството из \"\n#~ \"бездната, хванах два нови видя на летящ ужас. Денят мина добре. Дано не \"\n#~ \"забравя да заръчам още гуано и черни свещи на Адрия, защото ми остават \"\n#~ \"малко.\"\n"
  },
  {
    "path": "Translations/cs.po",
    "content": "# Translation of DevilutionX to Czech\n# Psojed <realpsojed@gmail.com>, 2021.\n# @Srandista, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:19+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Psojed <realpsojed@gmail.com>\\n\"\n\"Language-Team: Psojed (realpsojed@gmail.com)\\n\"\n\"Language: cs\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3;  plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Design Hry\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Starší Designéři\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Dodatečný Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Hlavní Programátor\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Starší Programátoři\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programování\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Speciální Hostující Programátoři\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net Programování\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Programování Sériové Komunikace\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Programování Instalačního Programu\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Vedoucí Grafiky\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Grafika\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Technická Grafika\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Vedoucí filmové grafiky\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D Filmová Grafika\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Technická Filmová Grafika\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Výkonný Producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Přidružený Producent\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Zásahový Tým\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Hudba\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Zvukový Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Filmová Hudba a Zvuk\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Hlasová Produkce, Režie a Casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Scénář a Příběh\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Úprava Hlasů\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Hlasy\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Inženýr Nahrávání\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Design a Rozvržení Manuálu\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Grafika Manuálu\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Prozatimní Vedoucí QA (Hlavní Tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA Útočný Tým (Testeři)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA Tým Speciálních Jednotek (Testeři Kompatibility)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA Palebná Podpora (Dodateční Testeři) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA Kontrarozvědka\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Řád Síťových Informačních Služeb\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Zákaznická Podpora\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Prodej\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Přebytečný\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Zpěváci v pozadí (od Pana Dabiriho)\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Styk s Veřejností\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Mezinárodní Prodej\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"U.S. Prodej\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Výroba\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Právní a Obchodní oddělení\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Speciální Poděkování\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Poděkování\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"K památce\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Velmi Speciální Poděkování\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Generální Manažer\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Softwarový Inženýr\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Vedoucí Grafiky\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Umělci\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Zvukový Design, SFX a Audio Inženýr\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Vedoucí Kontroly Kvality\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testeři\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Manuál\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tDodatečné Práce\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Psaní Textu Úkolů\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Poděkování\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tSpeciální poděkování pro Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Manažer Kontroly Kvality\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Hlavní Tester Kontroly Kvality\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Hlavní Testeři\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Dodateční Testeři\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Manažer Produktového Marketingu\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Manažer Styku s Veřejností\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Přidružený Produktový Manažer\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Kruh Jednoho Tisíce\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tŽádné duše nebyly zaprodány při tvorbě této hry.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Vyber si Hrdinu\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Zrušit\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Nový Hrdina Hry pro Více Hráčů\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Nový Hrdina Hry pro Jednoho Hráče\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Existuje Uložená Hra\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Načíst Hru\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Začít Novou Hru\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Postavy Hry pro Jednoho Hráče\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Zlodějka a Čaroděj jsou dostupní pouze v plné verzi hry Diablo.Pro koupi hry \"\n\"navštiv https://www.gog.com/game/diablo .\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Zadej Jméno\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Neplatné jméno. Jméno nesmí obsahovat mezery, chráněné znaky a slova.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Nelze vytvořit postavu.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Úroveň:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Síla:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magie:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Obratnost:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalita:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Uložená hra:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Vyber Hrdinu\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Nový Hrdina\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Smazat\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Postavy Hry pro Více Hráčů\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Smazat Hrdinu Hry pro Více Hráčů\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Smazat Hrdinu Hry pro Jednoho Hráče\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Opravdu chceš smazat postavu \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Hra Jednoho Hráče\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Hra Více Hráčů\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Nastavení\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Podpora\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Ukaž Autory\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Ukonči Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Ukonči Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Klient-Server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"Smyčka\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Hra pro Více Hráčů\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Požadavky:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"brána není potřeba\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Vyber typ připojení\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Změň Bránu\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Všechny počítače musí být připojeny k TCP-kompatibilní síti.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Všechny počítače musí být připojeny k internetu.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Hraj sám, bez jakéhokoli připojení do sítě.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Možný Počet Hráčů: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Host má spuštěnou jinou hru než ty.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Host má spuštěnou jinou verzi hry ({:s}) než ty.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Tvoje verze {:s} neodpovídá verzi hosta {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Popis:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Vyber Akci\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Vytvoř Hru\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Vytvoř Veřejnou Hru\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Připoj se ke Hře\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Veřejné Hry\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Načítám...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Žádný\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ZRUŠIT\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Vytvoří novou hru s obtížností jakou si zvolíš.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"Vytvoří novou veřejnou hru s obtížností jakou si zvolíš.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Zadej ID Hry a připoj se k probíhající hře.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Zadej IP nebo název hry a připoj se k probíhající hře.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Připoj se ke veřejné probíhající hře.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Nightmare\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Hell\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Obtížnost: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Rychlost: Normální\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Rychlost: Rychlá\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Rychlost: Rychlejší\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Rychlost: Nejrychlejší\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Hráči: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Vyber Obtížnost\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Připojit se k {:s} Hrám\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Zadej ID Hry\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Zadej adresu\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Obtížnost Normal\\n\"\n\"Zde by měla začínající postava započít svoji výpravu k poražení Diabla.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Obtížnost Nightmare\\n\"\n\"Obyvatelé Labyrintu byli posíleni a budou pro tebe opravdovou zkouškou. \"\n\"Doporučeno pouze pro zkušené postavy.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Obtížnost Hell\\n\"\n\"Nejsilnější stvoření z podsvětí číhají u Pekelných bran. Pouze ty \"\n\"nejzkušenější postavy by měly vstoupit do tohoto světa.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Tvoje postava musí dosáhnout 20 úrovně než bude moci vstoupit do hry pro \"\n\"více hráčů na obtížnost Nightmare.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Tvoje postava musí dosáhnout 30 úrovně než bude moci vstoupit do hry pro \"\n\"více hráčů na obtížnost Hell.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Vyber Rychlost Hry\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Rychlá\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Rychlejší\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Nejrychlejší\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Běžná\\n\"\n\"Zde by měla začínající postava započít svoji výpravu k poražení Diabla.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Rychlá\\n\"\n\"Obyvatelé Labyrintu byli zrychleni a budou pro tebe opravdovou zkouškou. \"\n\"Doporučeno pouze pro zkušené postavy.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Rychlejší\\n\"\n\"Většina potvor v Labyrintu tě najde rychleji než kdykoli předtím. Pouze \"\n\"zkušený šampion by měl zkusit štěstí na této rychlosti.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Nejrychlejší\\n\"\n\"Pohůnci z podsvětí budou spěchat do útoku bez sebemenšího zaváhání. Pouze \"\n\"pravý rychlostní démon by měl hrát s tímto nastavením.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Zadej Heslo\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Otevři Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Přepni na Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Ano\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Ne\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\n#, fuzzy\n#| msgid \"Press any key to change.\"\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Stiskni jakoukoli klávesu pro změnu.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Nastavená klávesa:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Stiskni jakoukoli klávesu pro změnu.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Odeber klávesu\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Předchozí Menu\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Udržujeme chat server na adrese Discord.gg/devilutionx Následuj odkaz a \"\n\"přidej se k naší komunitě, kde diskutujeme o věcech kolem Diabla a datadisku \"\n\"Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX spravuje Diasurgical, problémy a chyby můžete hlásit na této \"\n\"adrese: https://github.com/diasurgical/devilutionX Abychom vám mohli lépe \"\n\"pomoci, prosím uveďte číslo verze hry, váš operační systém a popište váš \"\n\"problém.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Prohlášení:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX není podporován ani spravován společností Blizzard \"\n\"Entertainment, ani GOG.com. Blizzard Entertainment ani GOG.com netestovaly \"\n\"ani necertifikovaly kvalitu nebo kompatibilitu DevilutionX. Všechny dotazy \"\n\"ohledně DevilutionX by měly být směřovány k Diasurgical, nikoliv k Blizzard \"\n\"Entertainment nebo GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tTento port využívá Charis SIL, New Athena Unicode, Unifont a Noto, které \"\n\"jsou licencované pod SIL Open Font License, a také Twitmoji licencované pod \"\n\"CC-BY 4.0. Port také využívá SDL, které jsou licencované pod zlib-license. \"\n\"Přečti si ReadMe pro více informací.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Chyba\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Chyba nastala v: {:s} řádek {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Chyba Datového Souboru\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Nelze otevřít hlavní datový archiv ({:s}).\\n\"\n\"\\n\"\n\"Ujistěte se, že je výše uvedený soubor ve složce se hrou.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Chyba - Adresář Pouze pro Čtení\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Nelze zapisovat do umístění:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Hra: \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"Smyčka\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Heslo: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Veřejná Hra\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Patro: Hnízdo {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Patro: Krypta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Městský\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Patro: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Zadej Jméno\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Informace o Postavě\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Deník úkolů\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Automapa\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Hlavní Menu\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventář\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Kniha kouzel\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Odešli Zprávu\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\n#, fuzzy\n#| msgid \"Description:\"\nmsgid \"Description: \"\nmsgstr \"Popis:\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\n#, fuzzy\n#| msgid \"Players: \"\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"Hráči: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to buy this item?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Opravdu chceš koupit tento předmět?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\n#, fuzzy\n#| msgid \"Amber\"\nmsgid \"<number>\"\nmsgstr \"Jantarový\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\n#| msgctxt \"monster\"\n#| msgid \"Flayed One\"\nmsgid \"<player name>\"\nmsgstr \"Stažený z Kůže\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Neútočit na hráče\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Útočit na hráče\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Klávesová Zkratka: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Tlačítko pro výběr kouzla\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Klávesová Zkratka: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"Dovednost {:s}\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"Kouzlo {:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Kouzlo Úrovně 0 - Nefunguje\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Kouzlo Úrovně {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Svitek {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Svitek\"\nmsgstr[1] \"{:d} Svitky\"\nmsgstr[2] \"{:d} Svitků\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Hůl - {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Použití\"\nmsgstr[1] \"{:d} Použití\"\nmsgstr[2] \"{:d} Použití\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} zlaťák\"\nmsgstr[1] \"{:s} zlaťáky\"\nmsgstr[2] \"{:s} zlaťáků\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Nesplňuješ požadavky\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Úroveň: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Životy {:d} ze {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Použití - klikni Pravým\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Nová úroveň\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Máš {:s} zlaťák. Kolik jich chceš odebrat?\"\nmsgstr[1] \"Máš {:s} zlaťáky. Kolik jich chceš odebrat?\"\nmsgstr[2] \"Máš {:s} zlaťáků. Kolik jich chceš odebrat?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Městský Portál\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"od {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portál do\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Bezbožný Oltář\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"15. patro\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Nelze načíst postavu\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Zobraz tuto zprávu a ukonči\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Zobraz verzi a ukonči\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Vyber složku se souborem diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Vyber složku pro uložené hry\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Vyber složku pro soubor diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Přeskoč startovní videa\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Zobraz smínky za vteřinu\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Zapni důkladné logování\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Nahrát demo soubor\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Přehrát demo soubor\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Vypnout omezení snímků během přehrávání dema\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Výběr hry:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Vynutit Shareware mód\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Vynutit Diablo mód\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Vynutit Hellfire mód\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Hellfire nastavení:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Chyby hlašte na https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Nepodařilo se načíst UI zdroje.\\n\"\n\"\\n\"\n\"Ujistěte se, že devilutionx.mpq je ve složce se hrou a je aktuální.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Vypadlo spojení --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Čekám na hráče --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Žádná nápověda\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"v obchodech\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Předmět v opasku {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Použije Předmět z opasku.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Rychlá volba kouzla {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Klávesová zkratka pro dovednost nebo kouzlo.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Předchozí Menu\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Rychlá volba kouzla {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Rychlá Volba Kouzel\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Otevře Rychlou Volbu Kouzel.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Rychlé uložení\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Uloží hru.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Rychlé načtení\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Načte hru.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Ukončit hru\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Ukončí hru.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Zastav hrdinu\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Zastaví chození a zruší naplánované akce.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Zvýrazňování předmětů\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Ukaž/schovej předměty na zemi.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Přepni zvýrazňování předmětů\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Trvale ukáže/schová předměty na zemi.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Přepni automapu\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Přepíná zda je automapa zobrazena.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Otevře obrazovku Inventáře.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Postava\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Otevře obrazovku Postavy.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Deník úkolů\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Otevře Deník s úkoly.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Kniha Kouzel\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Otevře Knihu Kouzel.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Rychlé Zprávy {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Použije Rychlé Zprávy v chatu.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Schovat Info Obrazovky\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Zavře všechny informační obrazovky.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Přiblížení\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Přiblíží Herní Obrazovku.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Pauza Hry\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Zapauzuje hru.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pauza Hry\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Zvýší jas obrazovky.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Sníží jas obrazovky.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Zvýší jas obrazovky.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Zvýší jas obrazovky.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Nápověda\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Otevře Nápovědu.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Snímek obrazovky\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Udělá snímek obrazovky.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Informace o hře\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Zobrazí informace o hře.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Záznam Chatu\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Zobrazí záznam chatu.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Inventář\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"Vyber Akci\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"Vyber Akci\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"Zrušit\"\n\n#: Source/diablo.cpp:2175\n#, fuzzy\n#| msgid \"Closes the game.\"\nmsgid \"Close menus.\"\nmsgstr \"Ukončí hru.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"Postavy Hry pro Více Hráčů\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"Postavy Hry pro Více Hráčů\"\n\n#: Source/diablo.cpp:2212\n#, fuzzy\n#| msgid \"$Movement:\"\nmsgid \"Move left\"\nmsgstr \"$Pohyb:\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"Postavy Hry pro Více Hráčů\"\n\n#: Source/diablo.cpp:2218\n#, fuzzy\n#| msgid \"the night\"\nmsgid \"Move right\"\nmsgstr \"noci\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"Postavy Hry pro Více Hráčů\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Automapa\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\n#, fuzzy\n#| msgid \"The game ended\"\nmsgid \"Toggle game menu\"\nmsgstr \"Hra byla ukončena\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Saves the game.\"\nmsgid \"Opens the game menu.\"\nmsgstr \"Uloží hru.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"Ohnivá Vlna\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Multiplayer není v demu dostupný\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Selhalo Vytvoření Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Nedostupné v shareware verzi hry\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Nedostatek místa pro uložení\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Nelze pauzovat ve městě\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Je doporučeno kopírovat na harddisk\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Problém synchronizace multiplayeru\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Nelze pauzovat v multiplayeru\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Ukládám...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Některé jsou oslabeny zatímco jeden zesílí\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Nová síla je ukována skrz ničení\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Ti jenž se brání málokdy útočí\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Meč spravedlnosti je hbitý a ostrý\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Když je duch bdělý, tělo vzkvétá\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Zacílení zdroje many obnovuje\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Čas nemůže zeslabit sílu oceli\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Magie není vždy taková jak se zdá\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Co bylo jednou otevřené je nyní uzavřené\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Intenzita přichází za cenu moudrosti\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Tajemná síla přináší zničení\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Co nemůže být drženo nemůže být ani zraněno\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Rudá a Azurová stanou se jako slunce\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Znalosti a moudrost za cenu vlastního já\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Pijte a osvěžte se\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Kamkoli jdeš, už jsi tam\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Energie přichází za cenu moudrosti\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Bohatství přichází když jej nejmíň čekáš\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Kde lakomec nepochodí, trpělivost přináší růže\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Byls požehnán laskavým společníkem!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Ruce lidí mohou být řízeny osudem\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Síla je upevněna nebeskou vírou\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Esence života vyvěrá z nitra\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Cesta se vyjeví když se na ni díváš shora\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Spása přichází za cenu moudrosti\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Tajemství jsou odhalena ve světle rozumu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Ti co jsou poslední můžou ještě být první\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Štědrost přináší své vlastní odměny\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Musíš být alespoň na 8. úrovni abys to mohl použít.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Musíš být alespoň na 13. úrovni abys to mohl použít.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Musíš být alespoň na 17. úrovni abys to mohl použít.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Tajemná znalost získána!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Co tě nezabije...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Znalosti jsou síla.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Dej a taky dostaneš.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Některé zkušenosti získáš dotekem.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Není žádné místo jako je domov.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Duchovní energie je obnovena.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Cítíš se hbitější.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Cítíš se silnější.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Cítíš se moudřejší.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Cítíš se svěží.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Co se může rozbít se taky rozbije.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedrála\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Katakomby\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Jeskyně\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Hnízdo\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Krypta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Lv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} obtížnost\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"V Menu\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"zpětná vazba\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Nelze se připojit\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"chyba: přečteno 0 bytů ze serveru\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq nebo spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Některé Hellfire MPQ soubory chybí\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Ne všechny Hellfire MPQ soubory nalezeny.\\n\"\n\"Překopírujte všechny hf*.mpq soubory.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Rozlišení\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Běhání ve Městě\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Theův Úkol\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Kraví Úkol\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Auto Sbírání Zlaťáků\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Auto Sbírání Elixírů\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\n#| msgid \"Auto Gold Pickup\"\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Auto Sbírání Zlaťáků\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Auto Sbírání ve Městě\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria Doplňuje Manu\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Auto Přezbrojení Zbraně\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Auto Přezbrojení Zbroje\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Auto Přezbrojení Helmy\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Auto Přezbrojení Štítu\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Auto Přezbrojení Šperků\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Náhodné Úkoly\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\n#, fuzzy\n#| msgid \"Show mana values\"\nmsgid \"Show Item Labels\"\nmsgstr \"Zobraz hodnoty many\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Auto Plnění Opasku\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Deaktivovat Zmrzačující Oltáře\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Sbírání Léčívých Lektvarů\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Sbírání Plných Léčívých Lektvarů\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Sbírání Mana Lektvarů\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Sbírání Plných Mana Lektvarů\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Sbírání Lektvarů Omlazení\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Sbírání Plných Lektvarů Omlazení\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Nastavení\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Ulož Hru\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Hlavní Menu\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Ukonči Hru\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Jas\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Tempo\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Hudba Vypnuta\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Zvuky\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Zvuky Vypnuty\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pauza\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Klávesové Zkratky:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Otevři Nápovědu\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Zobraz Hlavní Menu\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Zobraz Auto-mapu\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Mezerník: Schovej všechny obrazovky\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Otevři Rychlou Volbu Kouzel\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Otevři Knihu Kouzel\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Otevři obrazovku Inventáře\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Otevři obrazovku Postavy\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Otevři Deník s Úkoly\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Snížit Jas\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Zvýšit Jas\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Přiblížení Herní Obrazovky\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Přiblížení Auto-mapy\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Použij Předmět z Opasku\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Nastav klávesovou zkratku pro Kouzlo\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Levé Tlačítko Myši: Útok bez pohybu\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Levé Tlačítko Myši (na obrazovce Postavy): Přiřaď všechny body \"\n\"statistik\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Levé Tlačítko Myši (v Inventáři): Přesuň předmět do Opasku nebo \"\n\"obleč/sundej předmět\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Levé Tlačítko Myši (na Opasku): Přesuň předmět do Inventáře\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Pohyb:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"Držením tlačítka myši se postava bude pohybovat v daném směru.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Souboj:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Držením klávesy Shift a klikáním levým tlačítkem bude postava držet pozici a \"\n\"útočit.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Auto-mapa:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Pro přístup k Auto-mapě, klikni na tlačítko 'MAPA' na informačním panelu \"\n\"nebo zmáčkni 'TAB' na klávesnici. Přiblížení a oddálení mapy lze provést \"\n\"pomocí kláves + a -. Pohybovat mapou lze pomocí šipek.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Sbírání předmětů:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Použitelné předměty malé velikosti, například lektvary a svitky, jsou \"\n\"automaticky umístěny do tvého 'opasku' v horní části informačního panelu. \"\n\"Když je předmět umístěn do opasku, objeví se malé číslo v dané kolonce. \"\n\"Předměty můžou být použity buď zmáčknutím odpovídajícího čísla na \"\n\"klávesnici, nebo kliknutím na předmět pomocí pravého tlačítka myši.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Zlaťáky:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Můžeš si zvolit konkrétní množství zlaťáků k odhození tak, že klikneš pravým \"\n\"tlačítkem myši na hromádku zlata ve tvém Inventáři.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Dovednosti & Kouzla:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"K seznamu dovedností a kouzel se dostaneš kliknutím levým tlačítkem myši na \"\n\"tlačítko 'KOUZLA' na informačním panelu. Zapamatovaná kouzla a kouzla \"\n\"dostupná z hole jsou zde zobrazena. Kliknutí levým tlačítkem na kouzlo \"\n\"vybere dané kouzlo. Vybrané kouzlo lze vyčarovat tak, že klikneš pravým \"\n\"tlačítkem myši do herní obrazovky.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Používání Rychlé Volby pro Kouzla:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Kliknutí levým tlačítkem na aktuální kouzlo v informačním panelu otevře \"\n\"'Rychlou Volbu', kde si můžeš rychle zvolit dovednost nebo kouzlo k použití. \"\n\"Vybrané kouzlo lze vyčarovat tak, že klikneš pravým tlačítkem myši do herní \"\n\"obrazovky.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Kliknutím Shift + Levé tlačítko myši na aktuální kouzlo můžeš odebrat \"\n\"vybrané kouzlo.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Nastavení Klávesových Zkratek pro Kouzla:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Můžeš nastavit až 4 Klávesové zkratky pro dovednosti, svitky nebo kouzla. \"\n\"Nejprve otevři 'Rychlou Volbu' jak je popsáno o sekci nahoře. Poté myší \"\n\"najeď na kouzlo, na které chceš nastavit klávesovou zkratku a zmáčkni jednu \"\n\"z kláves F5, F6, F7 nebo F8.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Knihy Kouzel:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Čtením více než jedné knihy zvyšuješ svou znalost daného kouzla, což ti \"\n\"umožní čarovat dané kouzlo efektivněji.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Nápověda k Shareware Hellfire\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Nápověda k Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Nápověda k Shareware Diablu\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Nápověda k Diablu\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Stiskni ESC pro ukončení, šipky pro posun.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Nelze vytvořit hlavní okno\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Olej Přesnosti\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Olej Mistrovství\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Olej Ostrosti\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Olej Smrti\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Olej Dovednosti\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Kovářský Olej\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Olej Statečnosti\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Olej Stálosti\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Olej Tvrdnutí\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Olej Nepropustnosti\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"zvyšuje u zbraně\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"šanci na zásah\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"výrazně zvyšuje\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"u zbraně šanci na zásah\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"potenciál poškození\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"výrazně zvyšuje u zbraně\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"potenciál poškození - ne u luku\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"snižuje potřebné atributy\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"pro používání zbroje a zbraní\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"doplňuje 20% z\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"výdrže předmětu\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"zvyšuje současnou a\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"maximální výdrž předmětu\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"udělá předmět nezničitelným\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"zvýší obranné číslo\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"zbroje nebo štítu\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"výrazně zvýší obranné číslo\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"zbroje nebo štítu\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"nastraží ohnivou past\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"nastraží bleskovou past\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"nastraží past zkamenění\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"doplní všechny životy\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"doplní část životů\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"doplní část many\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"doplní všechnu manu\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"zvýší sílu\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"zvýší magii\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"zvýší obratnost\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"zvýší vitalitu\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"doplní část životů a many\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"doplní všechny životy a manu\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Zobrazení - klikni Pravým\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Použití - klikni Pravým\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Přečtení - klikni Pravým, poté\\n\"\n\"klikni Levým na cíl\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Přečtení - klikni Pravým\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Aktivuj pro zobrazení\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Otevři inventář pro použití\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Aktivuj pro použití\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Vyber si z knihy kouzel, a poté\\n\"\n\"vyčaruj kouzlo pro přečtení\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Aktivuj pro přečtení\"\n\n#: Source/items.cpp:1800\n#, fuzzy, c++-format\n#| msgid \"Activate to view\"\nmsgid \"{} to view\"\nmsgstr \"Aktivuj pro zobrazení\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\n#| msgid \"{:+d} to strength\"\nmsgid \"{} to use\"\nmsgstr \"{:+d} síla\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Vyber si z knihy kouzel, a poté\\n\"\n\"vyčaruj kouzlo pro přečtení\"\n\n#: Source/items.cpp:1811\n#, fuzzy, c++-format\n#| msgid \"Activate to read\"\nmsgid \"{} to read\"\nmsgstr \"Aktivuj pro přečtení\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Patro: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Zdvojnásobí kapacitu hromádek zlata\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Požadavky:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Síla\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Magie\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Obrat\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Kniha - {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Ucho od {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"šance na zásah: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% poškození\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"na zásah: {:+d}%, {:+d}% poškození\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% obrana\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"obranné číslo: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Odolnost Oheň: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Odolnost Oheň: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Odolnost Blesky: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Odolnost Blesky: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Odolnost Magie: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Odolnost Magie: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Odolnost Vše: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Odolnost Vše: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"kouzla navýšena o {:d} úroveň\"\nmsgstr[1] \"kouzla navýšena o {:d} úrovně\"\nmsgstr[2] \"kouzla navýšena o {:d} úrovní\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"kouzla snížena o {:d} úroveň\"\nmsgstr[1] \"kouzla snížena o {:d} úrovně\"\nmsgstr[2] \"kouzla snížena o {:d} úrovní\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"úroveň kouzel beze změn\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Použití navíc\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} použití\"\nmsgstr[1] \"{:d} {:s} použití\"\nmsgstr[2] \"{:d} {:s} použití\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Poškození ohněm: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Poškození ohněm: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Poškození bleskem: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Poškození bleskem: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} síla\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} magie\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} obratnost\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} vitalita\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} ke všem statistikám\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} poškození od nepřátel\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Životy {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"vysoká výdrž\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"snížená výdrž\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"nezničitelný\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% osvětlení\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% osvětlení\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"střílí více šípů současně\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"poškození ohnivým šípem: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"poškození ohnivým šípem: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"poškození bleskovým šípem: {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"poškození bleskovým šípem: {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"poškození ohnivou koulí: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"poškození ohnivou koulí: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"útočník je poškozen za 1-3\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"uživatel ztratí všechnu manu\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"pohlcuje polovinu poškození z pastí\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"odhodí nepřítele dozadu\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% poškození proti démonům\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Všechny Odolnosti jsou 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"zásah vysaje 3% many\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"zásah vysaje 5% many\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"zásah vysaje 3% životů\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"zásah vysaje 5% životů\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"prorazí obranu nepřítele\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"hbitý útok\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"rychlý útok\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"rychlejší útok\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"nejrychlejší útok\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Další dovednost (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"rychlé vzpamatování ze zásahu\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"rychlejší vzpamatování ze zásahu\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"nejrychlejší vzpamatování ze zásahu\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"rychlé blokování\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"přidá {:d} bod k poškození\"\nmsgstr[1] \"přidá {:d} body k poškození\"\nmsgstr[2] \"přidá {:d} bodů k poškození\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"střílí šípy náhodnou rychlostí\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"předmět má neobvyklé poškození\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"upravená výdrž\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"jednoruční meč\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"neustále budeš ztrácet životy\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"vysátí životů\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"nepožaduje sílu\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"poškození bleskem: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"poškození bleskem: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"bleskové střely při zásahu\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"občas ztrojnásobí poškození\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"snižující se {:+d}% poškození\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x poškození do nepřítele, 1x do tebe\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Náhodné 0 - 600% poškození\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"nízká výdrž, {:+d}% poškození\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"extra OČ proti démonům\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"extra OČ proti nemrtvým\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Many přesunuto do Životů\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Životů přesunuto do Many\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"poškození: {:d}  Nezničitelný\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"poškození: {:d}  Výdrž: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"poškození: {:d}-{:d}  Nezničitelný\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"poškození: {:d}-{:d}  Výdrž: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"obrana: {:d}  Nezničitelný\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"obrana: {:d}  Výdrž: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Použití: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"unikátní předmět\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Není Identifikován\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Doupě Krále Kostlivců\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Komnata Kostí\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Bludiště\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Otrávené Zásoby Vody\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Doupě Arcibiskupa Lazaruse\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\n#| msgid \"Hellfire\"\nmsgid \"Hell Arena\"\nmsgstr \"Hellfire\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Dolů do sklepení\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Dolů do katakomb\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Dolů do jeskyní\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Dolů do pekla\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Dolů do hnízda\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Dolů do krypty\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Nahoru do patra {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Nahoru do města\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Dolů do patra {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Dolů do Hnízda úrovně {:d}\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Nahoru do Hnízda úrovně {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Nahoru do Krypty úrovně {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Základní Kámen Světa\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Dolů do Krypty úrovně {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Zpět do Patra {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Nelze otevřít archiv souboru s uloženou hrou\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Neplatný soubor s uloženou hrou\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Hráč je v úrovni pouze pro Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Neplatný stav hry\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Nelze zobrazit mainmenu\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Zvíře\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Démon\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Nemrtvý\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Typ: {:s}  Zabito: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Celkem zabito: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Životy: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Žádná magická odolnost\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Odolnosti:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magie\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Oheň\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Blesky\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Imunita:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Typ: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Žádné odolnosti\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Žádné imunity\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Má nějaké Magické Odolnosti\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Má nějaké Magické Imunity\"\n\n#: Source/mpq/mpq_writer.cpp:174\n#, fuzzy\n#| msgid \"Failed to open stash archive for writing.\"\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Nepodařilo se otevřít archiv bedny k zápisu.\"\n\n#: Source/msg.cpp:1701\n#, fuzzy, c++-format\n#| msgid \"{:s} has cast an illegal spell.\"\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} vyčaroval nedovolené kouzlo.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} vyčaroval nedovolené kouzlo.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Hráč '{:s}' (úroveň {:d}) se připojil do hry\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Hra byla ukončena\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Nelze získat data o patře\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Hráč '{:s}' opustil hru\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Hráč '{:s}' zabil Diabla a opustil hru!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Hráč '{:s}' byl odpojen (timeout)\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Hráč '{:s}' (úroveň {:d}) už je připojen do hry\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Tajemný\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Skrytý\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Ponurý\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Divný\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Kouzelný\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Kamenný\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Náboženský\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Očarovaný\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Divotvorný\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Fascinující\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Záhadný\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Podivný\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Tajuplný\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Božský\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Svatý\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Posvátný\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Duchovní\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Strašidelný\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Opuštěný\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Strašidelný\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Tichý\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Odloučený\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Ozdobený\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Mihotavý\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Poskvrněný\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Mastný\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Zařící\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Žebrákův\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Jiskřivý\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Třpytivý\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Sluneční\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Murphyho\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Velký Konflikt\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Mzdou Hříchu je Válka\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Příběh o Horadrimech\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Temný Exil\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Hříšná Válka\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Spoutání Trojice\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Sféry Mimo\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Příbeh o Třech\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Černý Král\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Deník: Očarování\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Deník: Setkání\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Deník: Tiráda\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Deník: Jeho Síla Roste\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Deník: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Deník: Konec\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Kniha Kouzel\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Ukřižovaný Kostlivec\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Páka\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Otevřené dveře\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Zavřené dveře\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Zablokované dveře\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Prastará Kniha\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Kniha Ohavností\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Páka s lebkou\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Mýtická Kniha\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Malá Truhla\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Truhla\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Velká Truhla\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarkofág\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Police na knihy\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Knihovna\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Barel\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Zámotek\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Oltář\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Kostěná Kniha\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Kniha v Knihovně\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Krvavá Fontána\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Setnuté Tělo\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Kniha Slepých\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Kniha Krve\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Očišťující Pramen\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Brnění\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Stojan na Zbraně\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Oltář Kozlů\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Velký Kotel\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Kalná Kaluž\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Fontána Slz\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Ocelová Kniha\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Podstavec Krve\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Houbový Porost\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Odporný Stojan\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Zabitý Hrdina\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} s pastí\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (deaktivováno)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"ZAP\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"VYP\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Herní Mód\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Herní Nastavení\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Hraj Diablo nebo Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Omezit na Shareware\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Udělá hru kompatibilní s demoverzí. Umožní hrát hru více hráčů s kamarády, \"\n\"kteří nemají plnou verzi Diabla.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Spuštění\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Nastavení pro Spuštění\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Intro\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Zobrazení Intro filmečku.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Úvodní obrazovka\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Zobrazení úvodní obrazovky.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo a Úvodní Obrazovka\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Jen Úvodní Obrazovka\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Specifická nastavení pro Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Specifická nastavení pro Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Zvuk\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Nastavení Zvuku\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Zvuky Chození\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Hráč vydá zvuk když chodí.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Zvuk Auto Přezbrojení\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\"Automatické přezbrojení předmětů při sebrání vydá zvuk daného předmětu.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Zvuk Sebrání Předmětu\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Sbírání předmětů vydá zvuk sebrání předmětu.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Vzorkovací Frekvence\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Výstupní vzorkovací frekvence (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanály\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Počet zvukových kanálů.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Velikost Bufferu\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Udává velikost bufferu (počet snímků na kanál).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Kvalita Převzorkování\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Udává kvalitu převzorkování, od 0 (nejnižší) po 10 (nejvyšší).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Udává interní rozlišení hry a určuje velikost herního výhledu. Pozn.: Toto \"\n\"se může lišit od rozlišení obrazovky, pokud je použito Škálování, \"\n\"Celočíselné Škálování nebo Přizpůsobit Obrazovce.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\n#, fuzzy\n#| msgid \"Audio Settings\"\nmsgid \"Audio device\"\nmsgstr \"Nastavení Zvuku\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafika\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Nastavení Grafiky\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Na celou obrazovku\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Zobrazí hru v okně nebo na celou obrazovku.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Přizpůsobit Obrazovce\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"Automaticky upraví herní okno na rozlišení a poměr stran tvojí plochy.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Škálování\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Zapne škálování obrazu z rozlišení hry na rozlišení monitoru. Zabrání \"\n\"přepínání rozlišení monitoru a umožní změnu velikosti okna.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Kvalita Škálování\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"Zapne volitelné filtry pro výstup obrazu při škálování.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Nejbližší Pixel\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilineární\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotropické\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Celočíselné Škálování\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Zapne škálování obrazu pomocí celočíselného poměru.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Vertikální Synchronizace\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Blesky\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Barevné Cyklování\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Efekt barevného cyklování používaný pro animaci vody, lávy a kyseliny.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternativní vykreslení hnízda\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"Použije alternativní paletu barev v Hellfire lokaci hnízdo.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Hardwarový Kurzor\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Použije Hardwarový kurzor\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Hardwarový Kurzor pro Předměty\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Použije Hardwarový kurzor pro předměty.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Max Velikost Hardwarového Kurzoru\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Maximální šířka a výška hardwarového kurzoru. Větší kurzory se vykreslí \"\n\"softwarově.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Zobraz FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Ukáže FPS v levém horním rohu obrazovky.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Gameplay\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Herní Nastavení\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Zapne běhání/rychlé chození ve městě pro Diablo i Hellfire. Tato možnost \"\n\"byla přidána v datadisku.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Zachycení Vstupu\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Po zapnutí bude myš zachycena k hernímu oknu.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Zapne úkol od Malé Holčičky.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Zapne úkol od Jerseyho. Farmář Lester bude nahrazen postavou Úplný Blázen.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Přátelská Palba\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Zapne poškození šípy/kouzly mezi hráči při hře více hráčů, i když budou v \"\n\"přátelském módu.\"\n\n#: Source/options.cpp:790\n#, fuzzy\n#| msgid \"No pause in multiplayer\"\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Nelze pauzovat v multiplayeru\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Test Bard\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Zobrazí postavu typu Bard v menu tvorby hrdiny.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Test Barbar\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Zobrazí postavu typu Barbar v menu tvorby hrdiny.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Lišta Zkušeností\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Přidá Lištu Zkušeností do UI ve spodní části obrazovky.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Zobraz hodnoty životů\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Ukáže aktuální a maximální hodnotu životů na kouli životů.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Zobraz hodnoty many\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Ukáže aktuální a maximální hodnotu many na kouli many.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Informace o Postavě\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Lišta Životů Nepřítele\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"V horní části obrazovky zobrazí Lištu Životů Nepřítele.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Zlaťáky jsou automaticky sbírány když hráč prochází poblíž.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Elixíry jsou automaticky sbírány když hráč prochází poblíž.\"\n\n#: Source/options.cpp:802\n#, fuzzy\n#| msgid \"\"\n#| \"Elixirs are automatically collected when in close proximity to the player.\"\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Elixíry jsou automaticky sbírány když hráč prochází poblíž.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Automatické sbírání předmětů ve městě.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria ti doplní manu když navštívíš její obchod.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Zapne automatické nasazení zbraně po sebrání nebo nákupu.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Zapne automatické nasazení zbroje po sebrání nebo nákupu.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Zapne automatické nasazení helmy po sebrání nebo nákupu.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Zapne automatické nasazení štítu po sebrání nebo nákupu.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Zapne automatické nasazení šperků po sebrání nebo nákupu.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Náhodně vybere dostupné úkoly pro novou hru.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Zobraz Typy Monster\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"Přejetím myši přes monstrum zobrazí typ daného monstra v popisce v UI.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Po použití předmětu z opasku doplní opasek předmětem z inventáře.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Je-li zapnuto, na Kotle, Fascinující Oltáře, Kozlí Oltáře, Ozdobené Oltáře a \"\n\"Posvátné Oltáře nepůjde kliknout a budou označeny jako deaktivované.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Rychlé Kouzlení\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Klávesové zkratky kouzel ihned vyčarují nastavené kouzlo namísto přepnutí na \"\n\"dané kouzlo.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Počet Léčivých Lektvarů k automatickému sebrání.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Počet Plných Léčivých Lektvarů k automatickému sebrání.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Počet Mana Lektvarů k automatickému sebrání.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Počet Plných Mana Lektvarů k automatickému sebrání.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Počet Lektvarů Omlazení k automatickému sebrání.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Počet Plných Lektvarů Omlazení k automatickému sebrání.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\nmsgid \"Off\"\nmsgstr \"Smyčka\"\n\n#: Source/options.cpp:825\n#, fuzzy\n#| msgid \"Randomize Quests\"\nmsgid \"Random Angles\"\nmsgstr \"Náhodné Úkoly\"\n\n#: Source/options.cpp:826\n#, fuzzy\n#| msgid \"Vertical Sync\"\nmsgid \"Vertical Only\"\nmsgstr \"Vertikální Synchronizace\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Ovladač\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Nastavení Ovladačů\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Síť\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Nastavení Sítě\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chat\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Nastavení Chatu\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Jazyk\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Nastaví který jazyk bude použit ve hře.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Nastavení Jazyků\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Klávesové Zkratky\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Nastavení Klávesových Zkratek\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping\"\nmsgid \"Padmapping\"\nmsgstr \"Klávesové Zkratky\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping Settings\"\nmsgid \"Padmapping Settings\"\nmsgstr \"Nastavení Klávesových Zkratek\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Nastavení\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Úroveň\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Zkušenosti\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Další úroveň\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Základ\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Nyní\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Síla\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magie\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Obratnost\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalita\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Body k distribuci\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Zlaťáky\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Obranné číslo\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"šanci na zásah\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Poškození\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Životy\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Odolnost Magie\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Odolnost Oheň\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Odolnost Blesky\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"postava\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"úkoly\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"mapa\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menu\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"inventář\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"kouzla\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"hlas\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"ztlumit\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Nepoužitelné\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Poš: 1/3 hp cíle\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Léčení: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Poškození: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Dovednost\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Hůl ({:d} použití)\"\nmsgstr[1] \"Hůl ({:d} použití)\"\nmsgstr[2] \"Hůl ({:d} použití)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Úroveň {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Kouzlo\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Zraňuje pouze nemrtvé\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Svitek\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Hůl\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Klávesová Zkratka Kouzla {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Nelze otevřít archiv\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Nelze načíst postavu\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (úroveň {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Historie Chatu (Zprávy: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} zlaťáků\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Kolik zlaťáků chceš odebrat?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Úroveň {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Zkušenosti: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Maximální úroveň\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Další úroveň: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} na Úroveň {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Hrobka Krále Leorica\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Komnata Kostí\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Temný Průchod\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Bezbožný Oltář\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Do: {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Potřebuji pomoc! Pojď sem!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Následuj mě.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Tady je něco pro tebe.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Teď chcípneš!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Poděkování\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Zpět\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Poškození: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Obrana: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Výdrž: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"nezničitelný\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Vítejte v mém\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Kovářském obchodě\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Co byste rádi:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Mluvit s Griswoldem\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Koupit základní předměty\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Koupit prémiové předměty\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Prodat předměty\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Opravit předměty\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Odejít z obchodu\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Mám na prodej tyto věci:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Mám na prodej tyto prémiové věci:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Nemáš nic co bych odkoupil.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Které předměty jsou na prodej?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Nemáš nic k opravě.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Který předmět mám opravit?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Čarodějná chalupa\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Mluvit s Adrií\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Koupit předměty\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Nabít hole\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Odejít z chalupy\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Nemáš žádné hole k nabití.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Kterou hůl chceš nabít?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Nemáš dostatek zlaťáků\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Nemáš dost místa v inventáři\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Máme dohodu?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Opravdu chceš identifikovat tento předmět?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Opravdu chceš koupit tento předmět?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Opravdu chceš dobít tento předmět?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Opravdu chceš prodat tento předmět?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Opravdu chceš opravit tento předmět?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt, kluk s protézou\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Mluvit s Wirtem\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Mám něco na prodej,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"ale bude tě stát 50 zlaťáků\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"aby ses mohl podívat. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Co máš za předmět?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Rozloučit se\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Mám na prodej tento předmět:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Odejít\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Domě Léčitele\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Mluvit s Pepinem\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Odejít z Léčitelova domu\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Městský Stařešina\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Mluvit s Cainem\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identifikovat předmět\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Nemáš nic k identifikaci.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Který předmět chceš identifikovat?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Tento předmět je:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Hotovo\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Mluvit s {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Mluvení s {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"není dostupné\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"v shareware\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"verzi\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Klábosit\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Vycházející Slunce\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Mluvit s Ogdenem\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Odejít z hospody\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Mluvit s Gillian\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Otevři Skladiště\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Opilec Farnham\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Mluvit s Farnhamem\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Rozloučit se\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Tvoje zlaťáky: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Zabitý Měšťák\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Kovář Griswold\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Léčitel Pepin\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Zraněný Měšťan\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Majitel hospody Ogden\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Stařešina Cain\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Čarodějnice Adria\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Barmanka Gillian\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Kráva\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Farmář Lester\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Úplný Blázen\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Válečník\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Zlodějka\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Čaroděj\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Mnich\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bard\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbar\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombík\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Ghůl\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Tlející Mrtvola\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Černá Smrt\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Odpadlík\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Řezbář\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Ďáblík\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Temný\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Skelet\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Kostra Sekerník\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Uhořelý\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Horor\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Mrchožrout\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Pojídač Moru\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Stínová Bestie\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Okusovač Kostí\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Kostra Lukostřelec\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Skelet Kapitán\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Kostra Kapitán\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Uhořelý Kapitán\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Horor Kapitán\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Neviditelný Pán\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Skrytý\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Stalker\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Nespatřený\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Tkadlec Iluzí\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Pán Satyr\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Klan Masa\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Klan Kamene\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Klan Ohně\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Klan Noci\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Pohůnek\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Šotek\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Pochmurník\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Posluhovač\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Kyselinová Bestie\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Jedovatý Plivač\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Bestie z Jámy\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Lávový Chřtán\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Král Kostlivců\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Řezník\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Mocipán\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Bláťák\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Žabí Démon\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Stažený z Kůže\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Wyrm\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Jeskynní Slimák\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Ďábelský Wyrm\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Požírač\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Magmový Démon\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Krvavý Kámen\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Pekelný Kámen\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Lávový Pán\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Rohatý Démon\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Zablácený Běžec\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Mrazivý Útočník\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obsidiánový Pán\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"staré kosti\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Rudá Smrt\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Kostěný Démon\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Nemrtvý Balrog\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Podpalovač\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Plamenný Pán\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Ohnivá Záhuba\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Pekelný Podpalovač\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Rudá Bouře\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Bouřný Jezdec\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Bouřný Pán\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Bouřná Smršť\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Ukrutný Ďáblík\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Okřídlený Démon\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Chrlič\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Krvavý Dráp\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Křídla Smrti\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Zabiják\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Dozorce\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Pán Víru\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Jeskynní Zmije\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Ohnivý Dráček\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Zlatá Zmije\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Azurový Dráček\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Temný Rytíř\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Stráž Záhuby\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Ocelový Pán\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Krvavý Rytíř\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Rozřezaný\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Prázdný\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Pán Bolesti\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Tkadlec Reality\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Sukuba\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Sněhová Čarodějnice\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Pekelná Stvůra\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Palič Duší\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Poradce\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Soudce\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Kabalista\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Advokát\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Temný Pán\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Arci-Lich Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad Slaboch\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Šílený Zhar\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Kapka z Nosu\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Arcibiskup Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Rudé Soužení\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Černý Nefrit\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Krvavý Válečník\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Horkův Démon\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Znesvěcovač\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Kosťohlav Sekáček\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Ostrokožec Rozřezávač\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Dušohnis\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Krysodav Nečistý\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Trhač Kostí\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Hnilobný Hodovač\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Střevopich zvaný Hbitý\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Rozbitohlav Štítoprásk\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Tlející Masakr\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Stínohlodač\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Smrtící Oko\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Šílené Oko Mrtvola\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Hořící Lebka\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Zkroucená Lebka\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Nabodávač Jazyků\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Tepolezec\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Uctívač Měsíce\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Havraní Hněv\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Požírač Páteří\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Uhořelý zvaný Černý Popel\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Stínový Havran\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Snětikámen Slaboch\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Žlučopěňoch Pán Jámy\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Krvokožec Temnoluk\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Odporné Křídlo\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Stínový Pijan\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Mlhový Úskočník\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Smrtiflus\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Krvežlab\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Smrtistín Tělotrhač\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Válečný Červ zvaný Šílený\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Sklolebec Rozeklaný\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Ohnivá Pohroma\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Noční Křídlo zvaný Chladný\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Kamenný Nabodávač\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Žhavá Bronzová Pěst\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Rozhněvaný Oheň zvaný Záhuba\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Ohnivý Zraňovač zvaný Ponurý\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Baron Splašky\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Pohromoroh Ocelová Palice\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Kvíleč Chaosu\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Záhuboškleb Tlející\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Šílený Hořák\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Lich Kostiřez\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Páteřolam\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Ďáblolebkoun Ostrá Kost\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Zlomený Bouřník\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Prokletý Bouřník\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Slintající Sliz\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Plamenná Zlatá Pohroma\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Černá Bouře\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Morohněv\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Stahovač z Kůže\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Modroroh\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Zkroucený Oheň Zplozenec Pekla\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Drápokaz\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Lebkohnis\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Lebkolev zvaný Ohnutý\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Černý Jazyk\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Ohavný Hmatač\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Zmijoplamen\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Drápokožec\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Čarodějný Oheň zvaný Bezbožný\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Černá Lebka\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Sekač Duší\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Zplozenec Větrů\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Vládce Jámy\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Rezavý Tkadlec\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Odstín Kvílející Zloby\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Záhubomrak\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Ohnivá Duše Krvavý Měsíc\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Čarodějný Měsíc\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Nabodávač Hodovník\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Šedovojna Zabiják\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Hrůzný Soudce\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Čarodějnice Hvězdné Oko\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Ocelová Lebka zvaný Lovec\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Vizír\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamfír\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Krvežíznivec\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Pavučinová Vdova\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Masový Tanečník\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Chmurný Bodec\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Zámek Záhuby\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Krátký Meč\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Pukléř\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Kyj\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Krátký Luk\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Krátká Hůl - Mana\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Sekáček\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Nemrtvá Koruna\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Empyreanský Kroužek\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Kouzelný Kámen\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Optický Amulet\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Prsten Pravdy\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Vývěsní Štít\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Harlekýnský Odznak\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Ocelový Závoj\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Zlatý Elixír\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Kovadlina Zuřivosti\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Černá Houba\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Mozek\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Plesnivá Kniha\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Spektrální Elixír\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Krvavý Kámen\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Mapa Katedrály\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Lektvar Léčení\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Lektvar Many\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Svitek Identifikace\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Svitek Městského Portálu\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Arkainova Chrabrost\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Lektvar Plného Léčení\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Lektvar Plné Many\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Griswoldovo Ostří\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Hovězí Pláty\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Lazarusova Hůl\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Svitek Oživení\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Krátká Hůl\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Meč\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Dýka\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Runová Bomba\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodor\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Aurický Amulet\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Potrhaný Vzkaz 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Potrhaný Vzkaz 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Potrhaný Vzkaz 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Rekonstruovaný Vzkaz\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Hnědý Oblek\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Šedý Oblek\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Šišák\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Šišák s Nánosníkem\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Helma\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Hrncová Helma\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Koruna\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Římská Helma\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Kápě\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Hadry\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Plášť\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Róba\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Prošívané Brnění\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Kožené Brnění\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Brnění z Tvrdé Kůže\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Pobité Kožené Brnění\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Prošívaná Zbroj\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Zbroj\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Kroužková Zbroj\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Šupinová Zbroj\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Hrudní Pláty\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Pláty\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Lamelová Zbroj\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Plátová Zbroj\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Bitevní Pláty\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gotické Pláty\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Plná Plátová Zbroj\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Štít\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Malý Štít\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Velký Štít\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Mandlový Štít\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Pavéza\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gotický Štít\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Lektvar Omlazení\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Lektvar Plného Omlazení\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Olej\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Elixír Síly\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Elixír Magie\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Elixír Obratnosti\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Elixír Vitality\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Svitek Léčení\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Svitek Hledání\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Svitek Blesku\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Svitek Ohnivé Zdi\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Svitek Inferna\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Svitek Záblesku\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Svitek Infravize\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Svitek Fázování\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Svitek Manového Štítu\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Svitek Ohnivé Vlny\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Svitek Ohnivé Koule\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Svitek Kamenné Kletby\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Svitek Řetězového Blesku\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Svitek Ochránce\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Svitek Novy\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Svitek Golema\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Svitek Teleportace\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Svitek Apokalypsy\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Malchus\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Scimitar\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Claymore\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Čepel\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Palaš\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Dlouhý Meč\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Široký Meč\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Meč Bastard\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Obouruční Meč\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Velký Meč\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Malá Sekera\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Sekera\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Sekera\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Široká Sekera\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Bojová Sekera\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Velká Sekera\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Palice\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Jitřenka\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Válečné Kladivo\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Kladivo\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Ostnatý Kyj\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Řemdih\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Velká Palice\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Luk\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Lovecký Luk\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Dlouhý Luk\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Kompozitní Luk\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Krátký Bojový Luk\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Dlouhý Bojový Luk\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Krátký Válečný Luk\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Dlouhý Válečný Luk\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Dlouhá Hůl\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Kompozitní Hůl\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Krátká Hůl\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Válečná Hůl\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Prsten\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amulet\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Runa Ohně\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Runa\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Runa Blesku\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Vyšší Runa Ohně\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Vyšší Runa Blesku\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Runa Kamene\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Krátká Hůl - Blesková Střela\"\n\n#: Source/translation_dummy.cpp:368\n#, fuzzy\n#| msgid \"Mana Potion Pickup\"\nmsgid \"Arena Potion\"\nmsgstr \"Sbírání Mana Lektvarů\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Řezníkův Sekáček\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Meč Světla\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Trhlinový Luk\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Jehelníček\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Luk z Nebes\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Smrtící Lovec\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Luk Mrtvých\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Luk z Černého Dubu\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Plamenná Šipka\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Masožrout\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Větrná Síla\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Orlí Roh\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Gonnagalův Nůž\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Obránce\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Gryfův Dráp\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Černá Břitva\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Vypouklý Měsíc\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Ledová Kudla\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Čepel Popravčího\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Řezač Kostí\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Stínový Jestřáb\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Kouzelníkův Hrot\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Meč Světla\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Sokolův Pařát\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Nositel Záhuby\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Grizzly\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Praotec\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Znetvořitel\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Ostrý Zobák\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Krvavý Zabiják\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Sekera z Nebes\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Zlovolná Sekera\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Sekač Kamene\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Aguinařina Sekyrka\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Pekelný Zabiják\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Messerschmidtův Plenitel\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Rezavý Louskáček\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Kladivo z Jholmu\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Civerbův Obušek\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Jitřenka z Nebes\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Baranarova Jitřenka\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Sukovitý Kořen\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Mlátič Lebek\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Schaeferovo Kladivo\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Přiruba Snů\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Stínová Hůl\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Upalovač\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Bouřná Věž\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Třpytivá Píseň\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Přivolavač Hromu\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Ochránce\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Najův Hádankář\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Výkřik Mysli\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Onanova Tyč\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Helma Duchů\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Přemýšlející Šišák\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Mocipánova Helma\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Hlupákův Odznak\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Soumrak Bohů\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Královská Čelenka\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Roztrhané Maso Duší\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Gladiátorova Zhouba\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Duhový Plášť\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Kožešina z Autu\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Přehoz Moudrosti\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Jiskřivá Zbroj\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Mrchožroutův Krunýř\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Kápě Noci\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Najovy Odlehčené Pláty\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Kabát z Ostnatého Démona\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Deflektor\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Štít Rozštěpené Lebky\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Dračí Průlom\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Štít z Černého Dubu\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Svatý Obránce\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Bouřný Štít\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Réva\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Prsten Reghy\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Prsten Krvácení\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Stahující Prsten\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Zásnubní Prsten\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Cínový\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Mosazný\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Bronzový\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Železný\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Ocelový\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Stříbrný\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platinový\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithrilový\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteorický\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Zvláštní\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Nepoužitelný\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Ohnutý\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Slabý\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Zubatý\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Smrtící\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Těžký\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Krutý\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Brutální\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Masivní\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Divoký\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Bezohledný\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Nemilosrdný\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Nemotorný\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Tupý\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Ostrý\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Skvělý\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Bojovníkův\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Vojákův\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Lordův\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Rytířův\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Mistrův\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Šampionův\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Králův\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Zranitelný\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Zrezivělý\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Silný\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Velkolepý\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Statečný\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Slavný\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Požehnaný\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Posvátný\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Úžasný\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Božský\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Červený\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Rudý\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Granátový\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubínový\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Modrý\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Azurový\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lapisový\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Kobaltový\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Safírový\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Bílý\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Perleťový\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Slonovinový\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Krystalový\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Diamantový\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topazový\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Jantarový\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Nefritový\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Obsidiánový\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Smaragdový\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Hyeny\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Žáby\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Pavoukův\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Havranův\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Hadův\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Ještěrův\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Dráčkův\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Drakův\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Wyrmův\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hydří\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Andělův\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Arch-Andělův\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Hojný\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Bohatý\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Planoucí\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Bleskový\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"kvality\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"zmrzačení\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"zabíjení\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"nabodnutí\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"krveprolití\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"vraždění\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"bolesti\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"slz\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"života\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"ochrany\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"absorpce\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"odklonění\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"osmózy\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"křehkosti\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"slabosti\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"síly\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"mocnosti\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"moci\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"obrů\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"titánů\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"paralýzy\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"atrofie\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"obratnosti\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"dovednosti\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"přesnosti\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"preciznosti\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"dokonalosti\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"hlupáka\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"dyslexie\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"magie\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"mysli\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"oslnivosti\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"čarodějnictví\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"kouzelnictví\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"nemoci\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"choroby\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"vitality\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"nadšení\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"elánu\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"ráznosti\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"života\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"potíží\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"jámy\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"oblohy\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"měsíce\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"hvězd\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"nebes\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"zvěrokruhu\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"supa\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"šakala\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"lišky\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"jaguára\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"orla\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"vlka\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tygra\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"lva\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mamuta\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"velryby\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"křehkosti\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"lámavosti\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"pevnosti\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"řemesla\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"struktury\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"věků\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"temnoty\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"noci\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"světla\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"zářivosti\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"plamene\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"ohně\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"hoření\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"šoku\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"blesku\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"hromu\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"množství\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"hojnosti\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"trnů\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"zkaženosti\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"zlodějů\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"medvěda\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"netopýra\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"upíra\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"pijavice\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"krve\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"pronikavý\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"propíchnutí\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"mlácení\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"připravenosti\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"hbitosti\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"rychlosti\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"spěchu\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"rovnováhy\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"stability\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"harmonie\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"blokování\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Kouzelný Kámen\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad Slaboch\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar Šílenec\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Řezník\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Ogdenova Cedule\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Síně Slepých\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Valor\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Krvavý Válečník\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Kletba Krále Leorica\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Arcibiskup Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Závažné Záležitosti\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Farmářův Sad\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Malá Holčička\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Potulný Obchodník\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Znesvěcovač\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Jerseyho Trikot\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Ohnivá Střela\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Léčení\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Blesk\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Záblesk\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identifikace\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Ohnivá Zeď\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Městský Portál\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Kamenná Kletba\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infravize\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Fázování\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Štít Many\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Ohnivá Koule\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Ochránce\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Řetězový Blesk\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Ohnivá Vlna\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Had Zhouby\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Krvavý Rituál\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Neviditelnost\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Zuřivost\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleportace\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apokalypsa\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Odhmotnění\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Oprava Předmětu\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Dobití Hole\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Odzbrojení Pasti\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elementál\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Blesková Střela\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Svatá Střela\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Oživení\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekineze\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Léčení Druhých\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Krvavá Hvězda\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Kostěný Duch\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ahh, příběh o našem Králi, je tak? Leoricův tragický pád byl pro tuto zemi \"\n\"hroznou ránou. Lidé Krále vždy milovali, a teď z něj mají smrtelný strach. \"\n\"Neustále si kladu otázku, jak mohl skončit tak daleko od Světla, protože \"\n\"Leoric byl vždy ten nejsvětější muž. Jedině ty nejodpornější síly Pekla by \"\n\"mohly tak kompletně zničit človeka zevnitř...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Vesnice potřebuje tvou pomoc, dobrý člověče! Před několika měsíci byl unesen \"\n\"syn Krále Leorica, princ Albrecht. Král se strašlivě rozzuřil a svého \"\n\"ztraceného syna hledal ve vesnici. S každým dalšim dnem se zdálo, že Leoric \"\n\"upadá hlouběji do šílenství. Obviňoval nevinné vesničany ze zmizení svého \"\n\"syna a nechával je brutálně popravovat. Jen necelá polovina z nás přežila \"\n\"jeho šílenství...\\n\"\n\" \\n\"\n\"Královi Rytíři a Kneží se ho pokoušeli uklidnit, ale obrátil se proti nim a \"\n\"bohužel byli nuceni ho zabít. S posledním vydechnutím Král přivolal hrozivou \"\n\"kletbu na své dřívější následovníky. Přísahal, že mu budou v temnotě sloužit \"\n\"navěky...\\n\"\n\" \\n\"\n\"A tady věci nabraly ještě temnější spád, než jaký jsem si uměl představit! \"\n\"Náš bývalý Král povstal z věčného spánku a nyní velí zástupům nemrtvých \"\n\"přisluhovačů v Labyrintu. Jeho tělo bylo pohřbeno v hrobce tři patra pod \"\n\"Katedrálou. Prosím tě, dobrý člověče, upokoj jeho duši tím, že zničís jeho \"\n\"současnou prokletou podobu...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Jak jsem ti rekl, dobry pane, Kral byl pohrben tri patra pod Katedralou. Je \"\n\"tam dole a ceka ve zkazene temnote na svou sanci znicit tuto zemi...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Kletba naseho Krale pominula, ale bojim se, ze to byla pouze cast nejakeho \"\n\"vetsiho zla. Avsak jiz mozna muzeme byt zachraneni pred temnotou, ktera \"\n\"suzuje nasi zem, protoze tve vitezstvi je dobrym znamenim. Necht te svetlo \"\n\"provazi na ceste.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Ztrata syna byla pro Krale Leorica prilis tezka. Udelal jsem, co jsem mohl, \"\n\"abych zmirnil jeho silenstvi, ale nakonec ho premohlo. Od toho dne se nad \"\n\"jeho kralovstvim vznasi temna kletba, ale mozna pokud uvolnis jeho dusi z \"\n\"pozemskeho vezeni, kletba snad pomine...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Nerada myslim na to, jak Kral zemrel. Radeji vzpominam na jeho laskavost a \"\n\"spravedlivou vladu. Jeho smrt byla tak nestastna a vypadale velice spatne.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Vyrobil jsem mnoho zbrani a hodne zbroji, kterymi Kral Leoric vybavil sve \"\n\"rytire. Take jsem pro nej vykoval ohromny obourucni mec z nejlepsiho mitrilu \"\n\"a take odpovidajici korunu do boje. Stale nemohu uverit tomu, jak zemrel, \"\n\"ale to, co ho uvrhlo do silenstvi, musela byt nejaka zlovestna sila!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Nestaram se o to. Poslouchej, zadny kostlivec nemuze byt MUJ kral. Leoric je \"\n\"Kral. Kral, rozumis mi ? SLAVA KRALI!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Mrtvi, kteri kraci mezi zivimi, nasleduji prokleteho Krale. Ma moc vzkrisit \"\n\"jeste vice valecniku do stale se rozrustajici armady nemrtvych. Jestli \"\n\"nezastavis jeho vladu, urcite se vyda do teto zeme a zavrazdi vsechny, kteri \"\n\"jsou jeste zivi.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Podivej, ja tady delam obchody. Neprodavam informace a nestaram se o \"\n\"jakehosi Krale, ktery muze byt mrtvy dele nez ja jsem zivy. Jestli \"\n\"potrebujes neco proti tomu Krali nemrtvych, tak bych ti s tim mohl pomoct...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Teplo zivota vstoupilo do moji hrobky. Smrtelniku, priprav se slouzit memu \"\n\"Panu celou vecnost!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Vidim, ze te to divne chovani docela popletlo. Jelikoz se mnoho demonu boji \"\n\"slunecniho svetla a veri, ze vladne velkou moci, tak se domnivam, ze \"\n\"vychazejici slunce zobrazene na znaku, o kterem mluvis, je presvedcilo, ze \"\n\"znak take vladne jakousi tajemnou silou. Hmm, mozna nejsou vsichni az tak \"\n\"chytri, jak jsme se obavali...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Pane, chci se s vami podelit o podivny zazitek. Vim, ze mas velke vedomosti \"\n\"o tech zrudach, ktere obyvaji labyrint, a toto je neco, cemu nemohu za cely \"\n\"zivot porozumet... V noci me probudilo nejake skrabani z venku mojeho \"\n\"hostince. Kdyz jsem vyhledl z moji loznice, videl jsem stiny nejakych potvor \"\n\"podobnych demonum na dvore hostince. Po kratke chvilce utekli pryc, ale \"\n\"predtim jeste ukradli znak mojeho hostince. Vubec nechapu, proc by demoni \"\n\"meli krast muj znak, ale nechat moji rodinu na pokoji... je to divne, ze?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Oh, nemusel jsi mi prinest zpet muj znak, ale urcite mi to usetri vydaje za \"\n\"vyrobu noveho. Dobre, podivam se, co bych ti mohl dat jako odmenu za \"\n\"nalezeni mojeho znaku? Hmmm, copak tu mame... ah, ano! Tuhle capku nechal v \"\n\"jednom pokoji carodej, ktery tady pred nejakou dobou bydlel. Treba se ti \"\n\"muze nejak hodit.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Muj boze, demoni behaji po nocich ve vesnici a pleni nase domovi - copak jim \"\n\"nic neni svate? Doufam, ze jsou Ogden a Garda v poradku. Myslim, ze by za \"\n\"mnou meli zajit, jestli nejsou zraneni...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Oh ne! Tak tam se podel ten znak? Moje babicka a ja jsme celou tu vec urcite \"\n\"zaspaly. Diky bohum, ze ty prisery nezautocili na hostinec.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Demoni ukradli Ogdenum znak, rikas? To nezni moc jako krutosti, o kterych \"\n\"jsem slysel - nebo je videl. \\n\"\n\" \\n\"\n\"Demoni se zajimaji o vytrhavani srdci z tela, ne o nejake znaky.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Vis co si myslim? Nekdo vezme ten znak a budou za neho chtit hodne prachu. \"\n\"Kdybych ja byl Ogden... a ja nejsem, ale kdybych byl... proste bych koupil \"\n\"novy znak s nejakym fajnym obrazkem. Mozna pekny dzbanek pivka nebo kus \"\n\"sira...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Nikdo smrtelny nemuze doopravdy pochopit mysl demonu. \\n\"\n\" \\n\"\n\"Nikdy se nenech jejich divnymi ciny zmast, protoze to muze byt jejich plan.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Co - rika, ze jsem to vzal ja? Predpokladam, ze Griswold je na jeho \"\n\"strane. \\n\"\n\" \\n\"\n\"Podivej, obycejneho kradeni znaku jsem nechal pred mesici. Na kusu dreva \"\n\"nemuzes vydelat.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hej - Ty, co zabijis vsechny! Dones mi Magicky Znak nebo mi zautocit! Ty \"\n\"neodejit zivy! Ty zabit velke osklivaky a donest Magii. Jdi za roh a dvere, \"\n\"najde osklivaky. Ty das, ty pujdes!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Ty zabit osklivaky, dostat znak. Ty prinest mi, jinak...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"Ty dal! Ano, dobre! Jdi, my silni. My zabit vsechny s velkou Magii!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"To nevesti dobre veci, protoze to potvrzuje me nejtemnejsi obavy. I kdyz \"\n\"jsem nechtel uverit davnym legendam, nyni je nemohu poprit. Mozna nastal cas \"\n\"k tomu, abych odhalil, kdo jsem.\\n\"\n\" \\n\"\n\"Me prave jmeno je Deckard Cain Starsi a jsem poslednim nasledovnikem davneho \"\n\"Bratrstva, ktere bylo zasveceno ochrane tajemstvi o nekonecnem zlu. Zlu, \"\n\"ktere bylo nyni ocividne uvolneno.\\n\"\n\" \\n\"\n\"Arcibiskup Lazarus, drive nejduveryhodnejsi poradce Krale Leorica, vedl do \"\n\"Labyrintu skupinu vesnicanu, aby nalezli Kralova ztraceneho syna, Albrechta. \"\n\"Uplynul nejaky cas nez se vratili a pouze nekolik jich uniklo zivych.\\n\"\n\" \\n\"\n\"Proklej me za blahovost! Mel jsem odhalit jeho skrytou zradu. Musel to byt \"\n\"sam Lazarus, kdo unesl Albrechta a ukryl ho v Labyrintu. Nechapu, proc se \"\n\"Arcibiskup obratil k temnote, nebo jake ma umysly s tim ditetem. Ledaze by \"\n\"ho chtel obetovat svemu temnemu panovi!\\n\"\n\" \\n\"\n\"To musel byt jeho plan! Ti, kteri prezili z jeho 'zachranne skupiny', \"\n\"rikaji, ze naposledy Lazara spatrili, jak bezi do nejhlubsiho nitra \"\n\"labyrintu. Musis si pospisit a zachranit prince pred obetnim nozem toho \"\n\"pomateneho zloducha!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Musis spechat a zachranit Albrechta z rukou Lazara. Princ a lide tohoto \"\n\"kralovstvi na tebe spolehaji!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Tvuj pribeh je dost hrozivy, priteli. Lazarus jiste shori v Pekle za sve \"\n\"hrozne ciny. Chlapec, ktereho jsi popsal, neni nas princ, ale verim, ze \"\n\"Albrecht jeste muze byt v nebezpeci. Symbol moci, o kterem mluvis musi byt \"\n\"portal do sameho srdce Labyrintu.\\n\"\n\" \\n\"\n\"Mel bys vedet toto, priteli - Zlo, proti kteremu bojujes je temny Pan Hruzy. \"\n\"Smrtelnikum je znam jako Diablo. To on byl pred mnoha staletimi uveznen v \"\n\"Labyrintu a verim, ze se opet snazi rozsevat chaos v lidskych risich. Musis \"\n\"projit portalem a znicit Diabla driv nez bude pozde!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus byl Arcibiskup, ktery vedl mnoho vesnicanu do Labyrintu. Tenkrat \"\n\"jsem ztratil mnoho dobrych pratel a Lazarus se nikdy nevratil. Doufam, ze \"\n\"byl zabit spolu s ostatnimi. Jestli pro mne chces udelat laskavost, dobry \"\n\"pane - prosim nemluv o tom dni s Farnhamem.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Byl jsem sokovan, kdyz jsem slysel, co vesnicane te noci planuji. Myslel \"\n\"jsem, ze Lazarus ma ze vsech lidi nejvice zdraveho rozumu. Byl Arcibiskup a \"\n\"vzdy se velmi staral o obcany Tristramu. Bylo jich zraneno prilis mnoho, \"\n\"nemohl jsem je zachranit vsechny...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Pamatuji si, ze Lazarus byl velmi laskavy a dobrotivy. Mluvil na pohrbu moji \"\n\"matky a pomahal moji babicce a mne v nejhorsich dobach. Kazdou noc se \"\n\"modlim, aby byl nejak nazivu a v bezpeci.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Byl jsem tam, kdyz nas Lazarus vedl do Labyrintu. Mluvil o svate odplate, \"\n\"ale kdyz jsme zacali bojovat s temi zplozenci pekla, ani proti nim nepozvedl \"\n\"svuj palcat. Jenom bezel dale serymi, nekonecnymi komnatami, ktere byly plne \"\n\"sluzebniku temnoty!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Bodaji, pak kousou, pak jsou vsude kolem tebe. Lhar! LHAR! Vsichni jsou \"\n\"mrtvi! Mrtvi! Slysis me? Jenom padaji a padaji... jejich krev se rozliva \"\n\"vsude po podlaze... vsechno je to jeho chyba...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Neznam toho Lazara, o kterem mluvis, ale citim v jeho dusi velky rozpor. \"\n\"Predstavuje velke nebezpeci a nezastavi se pred nicim, aby slouzil temnote, \"\n\"ktera ho prohlasila za sveho.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Ano, spravedlivy Lazarus, ktery byl taak ucinny proti tem priseram tam dole. \"\n\"Nepomohl snad zachranit moji nohu, ze? Podivej, dam ti radu zadarmo. Zeptej \"\n\"se Farnhama, byl tam.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Zapomen na svou blaznivou pout. Vse, co te ceka, je hnev meho Pana! Prisel \"\n\"jsi pozde, abys zachranil to dite. Ted se k nemu pridas v Pekle!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, ani nevim, jestli ti muzu rici neco, co by ti nejak pomohlo. Voda, \"\n\"ktera plni nase studny, prichazi z podzemniho pramene. Slysel jsem o tunelu, \"\n\"ktery vede k velkemu jezeru - mozna jsou jedno a totez. Nanestesti nevim, co \"\n\"by mohlo zpusobit, ze jsou nase zasoby vody otravene.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Vzdy jsem se ve sve zasobarne snazil udrzovat velke zasoby jidla a piti, ale \"\n\"kdyz nema cele mesto zadny zdroj ciste vody, i nase zasoby brzy dojdou. \\n\"\n\" \\n\"\n\"Prosim, udelej, co muzes, jinak nevim co budeme delat.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Jsem rad, ze jsem te zastihl! Voda z nasich studni se stala poloslanou a \"\n\"hnijici a nekteri vesnicane onemocneli, kdyz ji pili. Nase zasoby ciste vody \"\n\"rychle dochazeji. Verim, ze nekde je pruchod, ktery vede k pramenu, jez \"\n\"zasobuje cele nase mesto. Prosim, zjisti, co zpusobilo tuhle pohromu, jinak \"\n\"vsichni jistojiste zahyneme.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Prosim, musis spechat. S kazdou dalsi hodinou jsme blize tomu, ze nebudeme \"\n\"mit co pit. \\n\"\n\" \\n\"\n\"Bez tve pomoci nemuzeme dlouho prezit.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Co to rikas - pouha pritomnost demonu zpusobila, ze se voda zkazila? Oh, pod \"\n\"nasim mestem ciha opravdu velke zlo, ale tva vytrvalost a odvaha nam dava \"\n\"nadeji. Prosim, vezmi si tento prsten - treba ti pomuze pri zniceni tech \"\n\"desivych priser.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Moje babicka je velmi slaba a Garda rika, ze nemuzeme pit vodu ze studni. \"\n\"Prosim, muzes udelat neco, abys nam pomohl?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin ti rekl pravdu. Nalehave potrebujeme cistou vodu a co nejdrive. \"\n\"Zkousel jsem vycistit jednu z mensich studni, ale zase se zaplnila hnusnou \"\n\"spinou. Urcite je znecistena u pramene.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Ty pijes vodu?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Lide z Tristramu zemrou, pokud nemuzes dostat cistou vodu do jejich \"\n\"studni. \\n\"\n\" \\n\"\n\"Mel bys vedet, ze podstatou teto veci jsou demoni, ale vubec si nevsimaji \"\n\"toho, co zpusobili.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Pro jednou s tebou souhlasim. Moje obchody vyschnou - to ti rikam - kdyz \"\n\"nebudu mit komu prodavat. Nejlip bys mel zjistit, co se deje!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Kniha, ktera vypravi o komnate lidskych kosti? Dobra, Komnata kosti je \"\n\"zminovana v jistych starych spiscich, ktere jsem studoval v knihovnach na \"\n\"Vychode. Tyto svazky naznacovali, ze kdyz se Panove podsveti rozhodnou \"\n\"chranit velke poklady, vytvori oblast, kde budou vsichni ti, kteri se \"\n\"pokusili ukrast ten poklad, naveky svazani k jeho ochrane. Pokroucene, ale \"\n\"velmi ucinne, ze?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Bojim se, ze o tom nevim nic, dobry pane. Cain ma mnoho knih, ktere ti mohou \"\n\"nejak pomoci.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"To zni jako velmi nebezpecne misto. Pokud si tam troufnes jit, prosim bud \"\n\"opatrny.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Bohuzel jsem nikdy neslysela o nicem takovem. Mozna Cain Vypravec by ti mohl \"\n\"nejak pomoct.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Nevim nic o tom miste, ale muzes se zkusit zeptat Caina Mluvi o mnoha vecech \"\n\"a neprekvapilo by me, kdyby mohl zodpovedet tvoje otazky.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Oukej, tak poslouchej. Je tu ta drevena komnata, vis. A jeho zena, vis - ona \"\n\"- rika stromum... protoze musis pockat. Pak rikam, to proti nemu muze \"\n\"fungovat, ale jestli myslis, ze za to budu PLATIT... ty... uhh... jasne.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Stanes se vecnym sluzebnikem temnych panu, pokud zahynes v teto proklete \"\n\"oblasti. \\n\"\n\" \\n\"\n\"Vstup do Komnaty kosti na vlastni riziko.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Ohromny a zahadny poklad, rikas? Mozna bych mel zajem vzit od tebe par \"\n\"veci... nebo jeste lepe, nepotrebujes nejake vzacne a drahe vybaveni, aby \"\n\"ses dostal skrz tu zkousku?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Zda se, ze Arcibiskup Lazarus presvedcil mnoho vesnicanu k vyprave do \"\n\"Labyrintu, aby nalezli Kralova ztraceneho syna. Hral si s jejich strachem a \"\n\"udelal z nich zurivy dav. Nikdo z nich nebyl pripraven na to, co lezelo v \"\n\"chladne zemi... Lazarus je tam dole opustil - zanechal je ve sparech \"\n\"nepredstavitelnych priser - aby tam zemreli.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Ano, Farnham mumlal cosi o priserne bestii, ktera se zurive ohanela zbrani. \"\n\"Myslim, ze mu rikal reznik.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Proboha, ja znam toho odporneho demona. Mnozi z tech, kteri ze skupiny \"\n\"vedene Lazarem prezili a vyplazili se z Katedraly, meli na tele jizvy, ktere \"\n\"jim zpusobil Reznikuv hnev. Nevim, cim rozrezaval sve obeti, ale nemuze to \"\n\"byt z tohoto sveta. Zanecha to rany hnisajici a dokonce i ja jsem shledaval \"\n\"temer nemoznym je lecit. Davej si velky pozor, jestli planujes valcit s tim \"\n\"hroznym demonem...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Kdyz Farnham rikal neco o reznikovi, co zabiji lidi, vubec jsem si toho \"\n\"nevsimala. Ale kdyz jsi s tim prisel ty, mozna je to pravda.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Videl jsem to, cemu Farnham rika Reznik, jak se prosekaval skrz tela mych \"\n\"pratel. Ohanel se sekackem velkym jako sekera, odsekaval ruce a nohy a na \"\n\"miste zabijel statecne muze. Od bitky me oddelila banda malych jecicich \"\n\"demonu a nejak jsem nalezl schody vedouci ven. Uz nikdy jsem tu odpornou \"\n\"bestii nespatril, ale jeho krvavy vzhled me pronasleduje az do dnesnich dnu.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Velky! Velky sekacek zabiji moje pratele. Nemuzu ho zastavit, musim utect \"\n\"pryc, nemuzu jim pomoct. Chycen v mistnosti s tolika telama ... tolika \"\n\"prateli ... NEEEEEEEEEE!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Reznik je sadisticka prisera, ktera ma rozkos z muceni a bolesti jinych. \"\n\"Videl jsi jeho praci v ozralci Farnhamovi. Kdyz ho znicis, zajistis tak \"\n\"bezpeci teto vesnice.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Vim o te potvore vic, nez si myslis. Jeho mali pratele me chytili a povedlo \"\n\"se jim useknout moji nohu nez me Griswold z te diry vytahl. \\n\"\n\" \\n\"\n\"Reknu to jednoduse - zabij ho driv nez on zabije tebe a prida si tvoji \"\n\"mrtvolu do sbirky.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Prosim, pojd ke mne. Arcibiskup Lazarus nas zavedl dolu, abychom nasli \"\n\"ztraceneho prince. Ten bastard nas vedl do pasti! Ted jsou vsichni mrtvi... \"\n\"zabiti demonem, kteremu rikal Reznik. Pomsti nas! Najdi toho Reznika a zab \"\n\"ho, aby mohly nase duse odpocivat v pokoji...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Zarecitoval jsi zajimave verse, napsane stylem, ktery mi pripomnel jine \"\n\"dilo. Nech me premyslet - co to jen bylo?\\n\"\n\" \\n\"\n\"...Temnota zahali Skryte. Zarici oci nespatrenych a jen slysis zvuk ostrych \"\n\"drapu, ktere skrabou, aby mucily ty nebohe duse, ktere byly ucineny slepymi \"\n\"na vecnost. Vezeni pro tyto proklete se nazyva Sine slepych...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Nikdy jsem se moc nezajimal o poezii. Obcas jsem mel duvod najmout \"\n\"minstrely, kdyz se v hostinci darilo, ale to ted vypada, jako by to bylo uz \"\n\"davno. \\n\"\n\" \\n\"\n\"Co? Ah, ano... uh, dobra, predpokladam, ze muzes videt, co nekdo jiny vi.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"To mi zni jaksi povedomne. Myslim, ze si vzpominam, jak jsem cetl neco velmi \"\n\"podobneho te basni, kdyz jsem zkoumal historii demonickych trapeni. Je to \"\n\"misto velkeho zla... pockej - nechces se tam vypravit, ze ne?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Jestli se ptas na slepotu, mel by sis promluvit s Pepinem. Vim, ze dal moji \"\n\"babicce lektvar, ktery pomohl vyjasnit jeji zrak, takze by ti s tim taky \"\n\"mohl pomoci.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Obavam se, ze jsem nikdy nevidel ani neslysel o miste, ktere odpovida tvemu \"\n\"zivemu popisu, priteli. Mozna by ti nejak mohl pomoct Cain Vypravec.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Podivej se... to je docela vesely, he? Chapes? Slepy - podivej?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Je to misto velkych muk a hruzy, a proto slouzi dobre svemu panu. \\n\"\n\" \\n\"\n\"Naslapuj opatrne, jinak muzes zustat dele nez ti bude mile.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Hele, prodavam ti neco? Ne. Davas mi penize, abych ti o tom neco rekl? Ne. \"\n\"Odejdes ted a pujdes za vypravecem, ktery kvuli temhle vecem zije? Ano.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Tvrdis, ze jsi mluvil s Lachdananem? Za sveho zivota byl velkym hrdinou. \"\n\"Lachdanan byl cestnym a spravedlivym clovekem, ktery po leta slouzil verne \"\n\"svemu Krali. Ale to uz samozrejme vis.\\n\"\n\" \\n\"\n\"Z tech, kteri byli chyceni ve sparech Kralovy kletby, by byl Lachdanan tim \"\n\"poslednim, kdo by se podrobil temnote bez boje, tudiz predpokladam, ze tvuj \"\n\"pribeh muze byt pravdivy. Kdybych byl na tvem miste, nalezl bych zpusob, jak \"\n\"ho uvolnit z jeho muk.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Mluvis o dlouho mrtvem statecnem bojovnikovi! V hostinci jsem neslysel o \"\n\"mluveni s davno mrtvymi, mnohokrat dekuji.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Zlaty elixit, rikas. Nikdy drive jsem nevaril lektvar takove barvy, takze ti \"\n\"nemohu rict, jak by te ovlivnil, kdyby ses ho pokusil vypit. Jako tvuj \"\n\"lecitel ti radim - pokud najdes takovy elixir, udelej, o co te Lachdanan \"\n\"zada, a NEZKOUSEJ ho pouzit.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Nikdy drive jsem o Lachdananovi neslysela. Promin, ale nemyslim, ze ti mohu \"\n\"nejak pomoci.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Jestli je to opravdu Lachdanan, koho jsi potkal, pak ti radim, abys mu \"\n\"pomohl. Nekolikrat jsem s nim jednal a znal jsem ho jako cestneho a verneho \"\n\"cloveka. Kletba, ktera padla na nasledovniky Krale Leorica, na nej dopadla \"\n\"urcite zvlaste tvrde.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan je mrtvy. Kazdy to vi a ty me nemuzes oblbnout, abych si myslel \"\n\"neco jinyho. Nemuzes mluvit s mrtvyma. To vim!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Muzes potkat lidi, kteri jsou polapeni v Labyrintu, jako je Lachdanan. \\n\"\n\" \\n\"\n\"Citim v nem cest a velky pocit viny. Pomoz mu a pomuzes vsem z Tristramu.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Pockej, nech me hadat. Caina pohltila obrovska trhlina, ktera se pod nim \"\n\"otevrela. Pekelny ohen ho spalil na popel a uz nemuze odpovidat na tvoje \"\n\"otazky. Oh, tohle ze se nestalo? Tak potom si podle mne neco koupis nebo \"\n\"odejdes.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Prosim, nezabijej me, jen me vyslechni. Kdysi jsem byl Kapitanem Rytiru \"\n\"Krale Leorica a udrzoval jsem zakony teto zeme spravedlive a cestne. Potom \"\n\"na nas padla temna Kletba za nasi ucast na kralove tragicke smrti. I kdyz \"\n\"moji pratele Rytiri podlehli svemu hroznemu osudu, ja jsem uprchl z Kralovi \"\n\"hrobky a snazim se najit zpusob, jak se uvolnit z Kletby. Selhal jsem...\\n\"\n\" \\n\"\n\"Slysel jsem o Zlatem Elixiru, ktery muze zrusit Kletbu a dovoli moji dusi \"\n\"odpocivat, ale nemohu ho nalezt. Ma sila nyni zanika a s ni take posledni \"\n\"kousky lidskosti. Prosim pomoz mi a najdi ten Elixir. Za tve usili se ti \"\n\"odvdecim - prisaham na svou cest.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Nenalezl jsi Zlaty Elixir. Bojim se, ze jsem odsouzen na vecnost. Prosim, \"\n\"pokus se jeste...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Zachranil jsi mou dusi pred zatracenim a za to jsem ti velmi dluzen. Jestli \"\n\"je nejaky zpusob, jak se ti mohu odvdecit zpoza hrobu, naleznu jej, ale \"\n\"prozatim - vezmi si mou helmu. Na ceste, na kterou se vydam, ji nebudu \"\n\"potrebovat. At te ochrani pred temnymi silami, ktere cihaji dole. Jdi za \"\n\"Svetlem, priteli...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold mluvil o Kovadline Zurivosti - legendarnim artefaktu, dlouho \"\n\"hledanem, ale nenalezenem. Vyrobena z kovovych kosti demonu Pekelnych \"\n\"britev, Kovadlina Zurivosti byla tavena kolem kosti peti nejmocnejsich magu \"\n\"podsveti. Jsou na ni vyrezany runy moci a chaosu, jakakoliv zbran ci brneni \"\n\"vykovane na teto Kovadline, se ponori do rise Chaosu a naplni se magickymi \"\n\"schopnostmi. Rika se, ze kvuli nepredvidatelne povaze Chaosu je tezke urcit, \"\n\"jaky bude vysledek tohoto kovani...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Nemyslis, ze na tohle by ses mel radeji zeptat Griswolda? Je docela sikovny, \"\n\"vis.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Pokud shanis informace o Palicce leceni nebo Stribrnem kalichu ocistovani, \"\n\"mohl bych ti pomoci, priteli. Jenze v tomhle pripade udelas lepe, kdyz si \"\n\"promluvis s Griswoldem nebo Cainem.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Kdyz jsme vyrustali, Griswolduv otec nekterym z nas vypravel o obrovske \"\n\"kovadline, na ktere se vyrabeli mocne zbrane. Rikal, ze kdyz kladivo uderilo \"\n\"do te kovadliny, zem se otrasla velkou zurivosti. Kdykoliv se pohne zeme, \"\n\"vzdy si vzpomenu na ten pribeh.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Vitej! Vzdy je potesenim videt jednoho z mych nejlepsich zakazniku! Vim, ze \"\n\"se vydavas hloubeji do Labyrintu, a slychaval jsem pribeh, ktery by sis \"\n\"mozna rad poslechl...\\n\"\n\" \\n\"\n\"Jeden z muzu, kteri se vratili z Labyrintu mi vypravel o tajemne kovadline, \"\n\"na kterou narazil pri uteku. Jeho popis mi pripomnel legendy, ktere jsem \"\n\"slychaval v mladi, o horici Pekelne Vyhni, kde se vyrabeli mocne magicke \"\n\"zbrane. Legenda vypravela, ze hluboko v Pekelne Vyhni odpocivala Kovadlina \"\n\"Zurivosti! Tato Kovadlina obsahovala samotnou podstatu demonickeho \"\n\"podsveti...\\n\"\n\" \\n\"\n\"Rika se, ze jakakoliv zbran vykovana na te Kovadline je naplnena velkou \"\n\"silou. Jestli je tahle kovadlina Kovadlina Zurivosti, mozna bych ti mohl \"\n\"vykovat zbran, kterou bys porazil i nejtemnejsiho pana Pekla! \\n\"\n\" \\n\"\n\"Najdi pro me Kovadlinu a ja se dam do prace!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Jeste nic, eh? Dobra, pokracuj v patrani. Zbran vykovana na Kovadline muze \"\n\"byt tvou nejlepsi nadeji a jsem si jist, ze ti mohu vyrobit opravdu \"\n\"legendarni.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Nemohu tomu uverit! Toto je Kovadlina Zurivosti - dobra prace, priteli. Ted \"\n\"tem bastardum ukazeme, ze nejsou v Pekle hrozivejsi zbrane nez ty vykovane \"\n\"lidmi! Vezmi si toto a necht te Svetlo ochranuje.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold nemuze prodat svoji kovadlinu. Co by pak delal? Taky bych zuril, \"\n\"kdyby mi vzali kovadlinu!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"V Labyrintu je mnoho artefaktu, ktere vladnou silami, jez nemohou smrtelnici \"\n\"pochopit. Nektere z nich maji fantastickou moc, ktera muze byt pouzita \"\n\"Svetlem i Temnotou. Pokud ziskas Kovadlinu, mohlo by to zmenit prubeh Hrisne \"\n\"Valky ve prospech Svetla.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Jestli najdes pro Griswolda ten artefakt, muze mi to hodne pokazit obchody. \"\n\"Awww, nikdy to nenajdes.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Brana Krve a Sine Ohne jsou mista mystickeho puvodu. Kdekoliv spociva ta \"\n\"kniha, kterou jsi cetl, jiste je to misto velke sily.\\n\"\n\" \\n\"\n\"Legendy mluvi o podstavci, ktery je vytesan z obsidianu a na vrcholku \"\n\"pokrytem kostmi je kaluz vrici krve. Take jsou zde zminky o Kamenech krve, \"\n\"ktere otevrou dvere, jez strazi starodavny poklad...\\n\"\n\" \\n\"\n\"Povaha toho pokladu je zahalena domnenkami, priteli, ale rika se, ze davny \"\n\"hrdina Arkaine skryl svate brneni Udatnost v tajnem sklepeni. Arkaine byl \"\n\"prvnim smrtelnikem, ktery zmenil prubeh Hrisne Valky a pronasledoval legie \"\n\"temnoty zpet do Horoucich Pekel.\\n\"\n\" \\n\"\n\"Predtim nez Arkaine zemrel, bylo jeho brneni ukryto v tajne krypte. Rika se, \"\n\"ze az bude toto brneni opet potrebne, povstane hrdina, jez znovu oblekne \"\n\"Udatnost. Mozna jsi tim hrdinou ty...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Kazde dite slyselo pribeh valecnika Arkaina a jeho tajemneho brneni znameho \"\n\"jako Udatnost. Pokud naleznes misto jeho odpocinku, budes dobre chranen \"\n\"proti zlu v Labyrintu.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... to zni jako neco, co bych si mel pamatovat, ale byl jsem tak \"\n\"zamestnan ucenim se novych leku a tvorenim lepsich elixiru, ze jsem to \"\n\"zapomnel. Promin...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Pribeh kouzelneho brneni nazyvaneho Udatnosti je neco, o cem si chlapci \"\n\"casto povidali. Radeji by ses mel zeptat nektero z muzu ve vesnici.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Brneni zname jako Udatnost muze naklonit vahy ve tvuj prospech. Reknu ti, ze \"\n\"ho hledalo mnoho lidi - vcetne me samotneho. Arkaine ho skryl dobre, \"\n\"priteli, a budes potrebovat vice nez jen trochu stesti, abys odhalil \"\n\"tajemstvi, ktere ho ukryva jiz po mnoho let.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Najdes-li tyto Kameny Krve, pouzij je velmi opatrne. \\n\"\n\" \\n\"\n\"Cesta je plna nebezpeci a tva jedina nadeje spociva ve tve vire v sebe sama.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Zamyslis najit brneni nazyvane Udatnost? \\n\"\n\" \\n\"\n\"Nikdo nikdy nezjistil, kde Arkaine schoval svoje veci, a jestli je nemuze \"\n\"najit muj kontakt, vazne pochybuji o tom, ze to zvladnes ty.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Znam pouze jedinou legendu, jez vypravi o valecnikovi, ktereho jsi popsal. \"\n\"Jeho pribeh je zapsan v davnych kronikach o Hrisne Valce...\\n\"\n\" \\n\"\n\"Poskvrnen tisici let valky, krve a smrti stoji Vojevudce Krve na hore jeho \"\n\"roztrhanych obeti. Jeho temna cepel skuci cernou kletbu zivotu; muciva vyzva \"\n\"kazdemu, kdo se postavi Pekelnemu Popravcimu.\\n\"\n\" \\n\"\n\"Take je psano, ze ackoliv byl kdysi smrtelnikem, jez bojoval po boku Legii \"\n\"Temnoty behem Hrisne Valky, ztratil svou lidskost kvuli sve neukojitelne \"\n\"touze po krvi.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Bojim se, ze jsem nikdy neslysel o takovem strasnem valecnikovi, dobry pane. \"\n\"Doufam, ze s nim nebudes muset bojovat, protoze to zni neobycejne nebezpecne.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"Cain ti muze o necem takovem rict vice nez si budu kdy prat vedet.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Jestli budes bojovat s tak hroznym protivinikem, necht te Svetlo vede a \"\n\"ochranuje. Budu na tebe stale myslet.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Temne a strasne legendy se vypravi o Vojevudci Krve. Bud dobre pripraven, \"\n\"priteli, protoze nema s nikym vubec slitovani.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Vzdycky musis mluvit o Krvi? Co treba kyticky a slunecni svit a to hezke \"\n\"devce, ktere roznasi piti. Poslechni, priteli - ses posedly, vis?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Jeho zrucnost s mecem nahani hruzu a po tisice let zil pouze bojem. \"\n\"Promin... nemuzu videt, jestli ho porazis.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Nikdy jsem neobchodoval s tim Vojevudcem, o kterem mluvis, ale zni to jako \"\n\"by potreboval spoustu mecu. Nevadilo by mi zasobovat jeho armadu...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Muj mec zpiva o tvoji krvi, smrtelniku a mym temnym panum jiste nebude \"\n\"odeprena.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold mluvil o Nebeskem kameni, ktery smeroval do mista na vychode. Byl \"\n\"tam prevazen kvuli dalsimu studiu. Ten kamen planul energii, ktera nejak \"\n\"zarucovala videni toho, co normalni clovek nemuze spatrit. Nevim, jaka \"\n\"tajemstvi skryva, priteli, ale nalezeni tohoto kamene se urcite ukaze velice \"\n\"cennym.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Karavana se zde zastavila, aby nabrala zasoby pro cestu na vychod. Prodal \"\n\"jsem jim dost cerstveho ovoce a nejaky chleba, ktery Garda prave dopekla. Je \"\n\"to smula, co se jim stalo...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Nevim, co si mysleli, ze s tim kamenem uvidi, ale reknu ti jedno. Jestli \"\n\"padaji z oblohy kameny, radeji bys mel byt opatrny!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Ano, karavana nejakych velmi dulezitych lidi se zde zastavila, ale bylo to \"\n\"uz pred nejakou dobou. Meli divny prizvuk a chystali se na dlouhou cestu, co \"\n\"si vzpominam. \\n\"\n\" \\n\"\n\"Nevim, jak muzes doufat, ze najdes neco z toho, co prevazeli.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Postuj chvili - mam pribeh, ktery by te mohl zajimat. Pred nejakou dobou \"\n\"tudy projela karavana, ktera smerovala do vychodnich kralovstvi. \"\n\"Predpokladam, ze prevazeli kus nebes, ktery spadl na zem! Karavana byla na \"\n\"ceste severne odtud prepadena maskovanymi najezdniky. Hledal jsem v troskach \"\n\"ten kamen z nebe, ale nikde tam nebyl. Kdybys ho nasel, verim, ze bych z nej \"\n\"mohl pro tebe vytvorit neco uzitecneho.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Stale cekam, kdy mi prineses ten kamen z oblohy. Vim, ze z nej muzu udelat \"\n\"neco mocneho.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Podivejme se - ej... jo, je to jak, jsem veril. Pockej chvilku...\\n\"\n\" \\n\"\n\"Ah, tady mas. Vlozil jsem kousky kamene do stribrneho prstenu, ktery mi \"\n\"nechal muj otec. Doufam, ze ti bude k uzitku.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Mel jsem pekny prsten; byl fakt drahej, s modrym a zelenym a cervenym a \"\n\"stribrnym. Jenze si nepamatuju, co se s nim stalo. Fakt mi ten prsten \"\n\"chybi...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Nebesky kamen je velmi mocny a kdyby to byl nekdo jiny nez Griswold, kdo te \"\n\"ho poslal najit, branila bych ho. Spouta jeho sily a jeho uziti bude dobre \"\n\"pro nas vsechny.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Jestli muze nekdo udelat neco z toho kamene,tak Griswold. Vi toho o sve \"\n\"praci hodne a i kdyz se mu snazim ukrast zakazniky, respektuji kvalitu jeho \"\n\"prace.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Carodejka Adria hleda cernou houbu? O Cernych houbach toho vim tolik, co o \"\n\"Cervenych sledich. Mozna Pepin lecitel ti povi vice, ale v zednem z mych \"\n\"pribehu nebo knih takovou vec nenajdes.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Reknu ti jenom tohle. Ani Garda ani ja vubec NIKDY nepodavame nasim ctenym \"\n\"hostum cerne houby. Jestli chce Adria uvarit nejake houby, tak je to jenom \"\n\"jeji vec, ale ja ti nemuzu pomoct s jejich hledanim. Cerne houby... jak \"\n\"nechutne!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Carodejka mi rekla, ze hledas mozek demona, abys mi pomohl vytvorit muj \"\n\"elixir. Bude to mit velkou cenu pro mnoho lidi, kteri byly temi podlymi \"\n\"bestiemi poraneni, pokud se mi povede odhalit tajemstvi, ktere podle me \"\n\"ukryva. Pokud bys mohl vzit mozek demona, kdyz ho zabijes, byl bych ti velmi \"\n\"vdecny, kdybys mi ho prinesl.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Vynikajici, presne tohle jsem si myslel. Mohl jsem elixir dokoncit i bez \"\n\"toho, ale nikdy neuskodi trochu studia. Zaneses tohle, prosim, carodejce? \"\n\"Verim, ze na to uz ceka.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Myslim, ze Ogdem mozna ma v zasobarne nejake houby. Proc se nezeptas primo \"\n\"jeho?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Pokud to Adria nemuze dostat, muzes se vsadit, ze je to velice vzacna vec. \"\n\"Nemuzu ti nabidnout lepsi pomoc nez tohle, ale zni to jako... velka, \"\n\"obrovita, nebezpecna, vypasena houba! Tak, stastny lov, predpokladam.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden micha UBOHOU cernou houbu, ale kdyz to piju, tak mi je blbe. Davej \"\n\"pozor, pozor... reknu ti tajemstvi - musis se mirnit!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Copak to tu mame? Zajimave, to vypada jako kniha o cinidlecg. Mej oci \"\n\"otevrene a hledej cernou houbu. Mela by byt docela velka a lehce \"\n\"rozpoznatelna. Jestli ji najdes, prineses mi ji, prosim?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"To, co potrebuji, je velka cerna houba. Ted bez a dones mi ji, abych ji \"\n\"mohla pouzit ve zvlastni smesi, na ktere prave pracuji.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Ano, to je skvele do napoje, ktery vyrabim. Mimochodem, lecitel shani mozek \"\n\"nejakeho demona nebo neceho takoveho, aby mohl lecit ty, kteri byli otraveni \"\n\"jejich jedem. Verim, ze zamysli z neho udelat elixir. Jestli mu pomuzes to, \"\n\"co hleda, prosim, zkus mi prinest vzorek toho elixiru.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Proc mi to sem nosis? Zrovna ted mi je mozek demona k nicemu. Potrebuji \"\n\"trochu elixiru, na kterem pracuje Lecitel. To on potrebuje te groteskni \"\n\"organ, ktery drzis, a potom mi prines elixir. Je to tak jednoduche, kdyz se \"\n\"nad tim  zamyslis, ze ano?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Coze? Ted jsi mi donesl ten elixir od Lecitele? Svuj napoj jsem mohla \"\n\"dokoncit bez nej. Proc si to proste nenechas...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Neprodavam zadne houby jakekoliv velikosti nebo barvy. Co takhle neco trochu \"\n\"uzitecnejsiho?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Takze legenda o Mape je pravdiva. Ani ja jsem tomu opravdu neveril! \"\n\"Predpokladam, ze je cas rict ti pravdu o tom, kdo jsem, priteli. Vidis, ze \"\n\"nejsem tim, cim se zdam...\\n\"\n\" \\n\"\n\"Me prave jmeno je Deckard Cain a jsem poslednim nasledovnikem davneho \"\n\"Bratrstva, ktere bylo zasveceno udrzovani a ochrane tajemstvi o nekonecnem \"\n\"zlu. Zlu, ktere bylo nyni zrejme uvolneno...\\n\"\n\" \\n\"\n\"Zlo, proti kteremu stojis je temny Pan hruzy - smrtelnikum znamy jako \"\n\"Diablo. To on byl pred mnoha staletimi uveznen v Labyrintu. Mapa, kterou jsi \"\n\"prinesl byla pred davnymi veky vytvorena, aby oznacila dobu, kdy Diablo opet \"\n\"povstane ze sveho vezeni. Kdyz budou dve hvezdy vyznacene na mape v jedne \"\n\"rade, Diablo bude na vrcholu sve sily. Bude temer neznicitelny...\\n\"\n\" \\n\"\n\"Ted zavodis s casem, priteli! Najdi Diabla a znic ho drive nezse hvezdy \"\n\"seskupi, protoze uz mozna nebudeme mit zadnou dalsi sanci, jak vycistit svet \"\n\"od tohoto zla!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Nas cas se krati! Citim, jak se jeho temna sila zvetsuje a jedine ty muzes \"\n\"zabranit tomu, aby dosahl sve plne sily.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Jsem si jist, ze jsi zkusil to nejlepsi, ale bojim se, ze ani tva sila a \"\n\"vule nestaci. Diablo je nyni na vrcholu sve pozemske sily a ty budes \"\n\"potrebovat vsechu odvahu a silu, abys ho porazil. Necht te Svetlo ochranuje \"\n\"a vede, priteli. Budu ti pomahat jakymkoliv zpusobem, ktery bude v mych \"\n\"silach.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Kdyz ti nemuze pomoct carodejka a radi ti, abys sel za Cainem, proc si \"\n\"myslis, ze ti nejak pomohu ja? Zni to jako velmi zavazna zalezitost. Mel by \"\n\"sis pospisit a zajit za vypravecem, jak ti doporucila Adria.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Ja si s tim napisem na mape moc neporadim, ale treba Adria nebo Cain by ti \"\n\"mohl pomoc rozlustit, o cem se zde pise. \\n\"\n\" \\n\"\n\"Vidim, ze to je mapa hvezd na nasi obloze, ale nic vic moje vedomosti \"\n\"nezahrnuji.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Na tuhle vec by ses mel zeptat nejlepe naseho vypravece. \\n\"\n\" \\n\"\n\"Cain je velice informovany o davnych svitcich a tohle je docela dobre \"\n\"nejstarsi kousek papiru, ktery jsem kdy videla.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Nikdy driv jsem takovou mapu nevidel. Kde jsi ji ziskal? I kdyz me nenapada, \"\n\"jak to precist, na tvoje otazky by ti mohli odpovedet Cain nebo Adria.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Poslouchej, pojd bliz. Nevim, jestli vis, co vim, ale to co mas je opravdu \"\n\"neco. Tohleto je mapa.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Oh, bojim se, ze to nevesti vubec nic dobreho. Tato mapa hvezd predvida \"\n\"velke nestesti, ale o jejich tajemstvich ti nic nepovim. Prisel cas, aby sis \"\n\"velmi vazne promluvil s Vypravecem...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Hledam mapu, ale tohle urcite neni ona. Mel bys to ukazat Adrii - nepochybne \"\n\"ti muze rict, co to je. Reknu ti jednu vec; vypada stare a stare obvykle \"\n\"znamena dost cenne.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"Prooosim, neublizuj. Nezabijej. Nech zit a priste dam dobre.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Neco pro tebe udelat. Zase, nezabijej Gharbada. Zit a dat dobre. \\n\"\n\" \\n\"\n\"Vem to, jako dukaz ja drzim slovo...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Jeste ne! Skoro hotove. \\n\"\n\" \\n\"\n\"Mooc mocne, moc silne. Zit! Zit! \\n\"\n\" \\n\"\n\"Netrapit a ja dodrzet slib!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Hodne dobre pro tebe. Hodne Mocne! Ty chces - ty ber!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Co?! Proc tu jsi? Z toho neustale vyrusovani by jeden zesilel. Tady, vezmi \"\n\"si to a nech me pracovat. Uz me neobtezuj!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Tvoje zvedavost zpusobi tvoji smrt!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Vitej, priteli. Postuj chvili a poslouchej...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Na svych vypravach hloubeji do Labyrintu muzes nalezt ukryte svazky, ve \"\n\"kterych jsou mnohe vedomosti. \\n\"\n\" \\n\"\n\"Precti je pozorne, protoze ti mohou rici veci, ktere ani ja neznam.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Znam mnoho mytu a legend, jez mohou obsahovat odpovedi na tve otazky, ktere \"\n\"se mohou vynorit pri tvych cestach Labyrintem. Pokud narazis na vyzvy a \"\n\"otazky, o nichz se chces dozvedete vice, vyhledej me a ja ti reknu vse, co \"\n\"budu moci.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold - muz velkych cinu a velke odvahy. Vsadim se, ze ti nikdy nerekl o \"\n\"tom, jak se vydal do Labyrintu, aby zachranil Wirta, ze? Dobre vedel, jaka \"\n\"nebezpeci tam na nej cihaji, ale vlastne - ty to vis take. Je velmi zrucny \"\n\"remeslnik a pokud tvrdi, ze ti muze velmi pomoci jakymkoliv zpusobem, muzes \"\n\"se spolehnout na jeho cestnost a dovednost.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden vlastni a provozuje hostinec U Vychazejiciho slunce jiz temer ctyri \"\n\"roky. Koupil ho prave nekolik mesicu predtim nez tu slo vsechno k certu. On \"\n\"a jeho zena Garda nemaji penize, aby odesli, protoze vsechno vlozili do \"\n\"toho, aby si tady zaridili dobre zivobiti. Je to dobry muz s velkym smyslem \"\n\"pro odpovednost.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Chudak Farnham. Je poznamenan vzpominkami na dav, ktery vstoupil do \"\n\"Katedraly s Lazarem v ten temny den. Utekl zivy, ale jeho odvaha a mnoho \"\n\"jeho zdraveho rozumu zustalo v te temne dire. Nyni nachazi utechu jedine na \"\n\"dne sveho korbele, ale mezi jeho neustlym blouznenim jsou obcas pohrbeny \"\n\"kousku pravdy.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Carodejka, Adria, je v Tristramu trochu zvlastni. Prijela kratce pote, co \"\n\"byla Katedrala znesvecena, zatimco temer vsichni ostatni utikali. Postavila \"\n\"si malou chatrc na okraji mesta, zdanlive pres noc, a ma pristup k mnoha \"\n\"podivnym a tajemnym artefaktum a magickym svazkum, o kterych jsem ani ja \"\n\"drive neslysel.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Wirtuv pribeh je desivy a tragicky. Byl vytrzen z naruci sve matky a \"\n\"odvlecen do labyrintu malymi, odpornymi demony, kteri nosili hnusne ostepy. \"\n\"V tech dnech bylo uneseno mnoho dalsich deti, vcetne syna Krale Leorica. \"\n\"Rytiri z palace se vydali dolu, ale nikdy se nevratili. Kovar chlapce nasel, \"\n\"ale az pote, co ho ty hnusne bestie zacali mucit kvuli svym sadistickym \"\n\"choutkam.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Povazuji ho za praveho pritele - mozna nejblizsiho, co jsem kdy \"\n\"mel. Ted je trochu zmateny, ale nikdy neexistoval pozornejsi a ohleduplnejsi \"\n\"clovek. Jeho vedomostem a umeni se rovna malokdo a jeho dvere jsou stale \"\n\"otevrene.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian je dobra zena. Vsichni ji maji radi pro jejiho dobreho ducha a svezi \"\n\"smich, i ja ji mam velmi rad. Zustava v hostinci, aby se mohla starat o svou \"\n\"starou babicku, ktera je prilis nemocna a nemuze cestovat. Obcas se bojim o \"\n\"jeji bezpeci, ale vim, ze mnoho muzu by radeji zemrelo, jen aby se ji nic \"\n\"nestalo.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Vitej, dobry pane. Vitam te v hostinci U vychazejiciho slunce!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Mnoho dobrodruhu zasedlo za stoly meho hostince a vypravelo se tu desetkrat \"\n\"vice pribehu nez bylo vypito piva. Jedina vec, co jsem slysel, na ktere \"\n\"vsichni,shodli je tato stara poucka. Treba ti nejak pomuze. Muzes sekat \"\n\"maso, ale musis rozdrtit kosti.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Kovar Griswold toho vi o zbranich a brneni nesmirne mnoho. Pokud budes nekdy \"\n\"potrebovat spravit svou vyzbroj, urcite za nim zajdi.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham zde travi prilis mnoho casu utapenim sveho zarmutku v levnem pive. \"\n\"Vyhodil bych ho, ale kdyz byl v Labyrintu, velice trpel.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria je na svuj vek velice moudra, ale musim se priznat - trochu me desi. \\n\"\n\" \\n\"\n\"Dobre, to nevadi. Pokud budes nekdy potrebovat kouzelny predmet, udrzuje \"\n\"svou chatrc za rekou podivne dobre zasobenou.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Jestli chces vedet vice o historii nasi vesnice, vypravec Cain toho vi \"\n\"minulosti docela dost.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt je prohnany maly padouch. Vzdycky se dostane do problemu a vubec me \"\n\"neprekvapuje, co se mu stalo. \\n\"\n\" \\n\"\n\"Pravdepodobne se dostal nekam, kde by nemel byt. Toho chlapce je mi lito, \"\n\"ale nesnasim spolecnost, ve ktere se zdrzuje.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin je dobry muz - a urcite nejslechetnejsi ve vesnici. Vzdy se snazi \"\n\"pomahat ostatnim, ale zda se, ze potize toho ci onoho druhu ho nasleduji, \"\n\"kamkoliv jde...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, moje barmanka? Kdyby nebylo jeji pece o babicku, nejspis by odtud \"\n\"davno utekla. \\n\"\n\" \\n\"\n\"Bohove vi, ze jsem ji prosil, aby odesla a rikal ji, ze budu o jeji babicku \"\n\"pecovat, ale je prilis laskava a starostliva, aby to udelala.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Co te trapi, priteli?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Objevil jsem velice zajimavou vec. Narozdil od nas se prisery v Labyrintu \"\n\"mohou lecit bez pomoci lektvaru ci magie. Pokud zranis nekterou z tech \"\n\"priser, ujisti se, ze je opravdu mrtva jinak se muze docela dobre vylecit \"\n\"sama.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Predtim nez byla obsazena temi, cimkoliv co tam ciha, Katedrala byla mistem \"\n\"velkych vedomosti. Da se tam najit mnoho knih. Pokud nejake najdes, mel bys \"\n\"je vsechny precist, protoze v nich mohou byt ukryty tajemstvi o fungovani \"\n\"Labyrintu.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold toho vi o valecnem umeni tolik jako ja vim o umeni lecit. Je take \"\n\"mazany obchodnik, ale jeho praci se nikdo nevyrovna. Oh, domnivam se, ze to \"\n\"muze byt tim, ze je siroko daleko jediny kovar.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain je pravy pritel a uceny mudrc. Udrzuje ohromnou knihovnu a ma \"\n\"prirozenou schopnost odhalit pravou povahu mnoha veci. Budes-li mit nekdy \"\n\"jakekoliv otazky, mel bys jit prave za nim.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Ani me schopnosti nestacily na uplne vyleceni Farnhama. Oh, mohl jsem \"\n\"zahojit jeho telo, ale vyleceni jeho mysli a ducha je pro mne prilis tezke.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"I kdyz take pouzivam trochu magie k vytvareni lektvaru a elixiru, ktere zde \"\n\"skladuji, Adria je prava carodejka. Zda se, ze nikdy nespi, a vzdy ma \"\n\"pristup k mnoha mystickym svazkum a artefaktum. Verim, ze jeji chatrc je \"\n\"mnohem vice nez obycejna bouda, ale nikdy jsem se nemohl podivat dovnitr.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Chudak Wirt. Udelal jsem pro nej vse, co bylo mozne, ale vim, ze se mu hnusi \"\n\"ta drevena noha, kterou jsem mu nasadil. Jeho rany byly priserne. Nikdo - a \"\n\"zvlaste ne takove mlade dite - by nemel tak moc trpet.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Opravdu nechapu, proc Ogden zustava zde v Tristramu. Trpi slabsimi nervy, \"\n\"ale je inteligentni a pracovity clovek, ktery dela dobrotu, kamkoliv prijde. \"\n\"Domnivam se, ze to muze byt strachem z tolika vrazd, ktere se udaly v okolni \"\n\"zemi, nebo mozna prani jeho zeny, ktera se o nej a rodinu stara, kdekoliv \"\n\"jsou.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogdenova barmanka je sladka divka. Jeji babicka je dost nemocna a trpi \"\n\"preludy. \\n\"\n\" \\n\"\n\"Tvrdi, ze to jsou vize, ale nemam dukaz o jednom ani o druhem.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Dobry den! Cim mohu slouzit?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Moje babicka mela sen, ze prijdes a budes se mnou mluvit. Vis, ona miva vize \"\n\"a muze videt do budoucnosti.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Zena na okraji mesta je carodejnice! Vypada docela prijemne a jeji jmeno, \"\n\"Adria, zni velice prijemne, ale ja se ji velmi bojim. \\n\"\n\" \\n\"\n\"Clovek, ktery by se podival, co tam provadi, musi byt statecny, jako ty.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Nas kovar je chloubou Tristramu. Nejenom, ze je mistrovsky remeslnik, ktery \"\n\"vyhral mnoho turnaju v jeho cechu, ale pochvalil ho i sam nas Kral Leoric - \"\n\"necht jeho duse odpociva v pokoji. Griswold je take velky hrdina; vsak se \"\n\"zeptej Caina.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain je vypravecem v Tristramu tak dlouho, co si pamatuji. Vi toho hodne a \"\n\"muze ti rict o cemkoliv skoro vsecho.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham je ozrala, ktery plni svoje bricho pivem a usi ostatnich nesmysly. \\n\"\n\" \\n\"\n\"Vim, ze Pepin i Ogden s nim maji pochopeni, ale ja jsem zklamana, kdyz ho \"\n\"pozoruji, jak stale vice a vice sklouzava do uplneho otupeni kazdou noc.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin zachranil moji babicce zivot a ja vim, ze mu to nikdy nebudu moci \"\n\"oplatit. Jeho schopnost lecit jakoukoliv nemoc je mocnejsi nez nejsilnejsi \"\n\"mec a zahadnejsi nez jakekoliv kouzlo. Jestli budes nekdy potrebovat leceni, \"\n\"Pepin ti urcite pomuze.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Vyrustala jsem s Wirtovou matkou, Canace. I kdyz byla jen trochu zranena, \"\n\"kdyz ho ty odporne prisery unesly, nikdy se neuzdravila. Myslim, ze zemrela \"\n\"zalem. Z Wirta se stal necestny mladik, ktery se snazi jen vydelat na drine \"\n\"ostatnich. Vim, ze trpel a videl mnoho hruz, ktere si ani neumim predstavit, \"\n\"ale neco z te temnoty nad nim stale visi.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden a jeho zena vzali mne a moji babicku k sobe domu a nechavaji me \"\n\"vydelat par zlataku praci v hostinci. Tolik jim dluzim a doufam, ze jednoho \"\n\"dne opustime toto misto a pomuzu jim zalozit grand hotel na vychode.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Co pro tebe muzu udelat?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Jestli shanis dobrou zbran, nech mne at ti ukazu tohle. Vezmi si zakladni \"\n\"tupou zbran, jako je palcat. Na vetsinu tech nehynoucich hruz tam dole \"\n\"pusobi bezvadne a neni nic lepsiho na rozbijeni tech vyzablych kostlivecku!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Sekera? Jo, to je dobra zbran, vyvazena proti jakemukoliv nepriteli. \"\n\"Podivej, jak rozrazi vzduch a pak si v jeji ceste predstav nejakeho hnusneho \"\n\"demona. Mej na mysli, ze se s ni pomalu seka - ale rozdava pekne silne rany!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Podivej na to ostri, tu vyvazenost. Mec v pravych rukach, a proti spravnemu \"\n\"nepriteli, je mistrem vsech zbrani. Jeho ostra cepel najde malo mista k \"\n\"sekani ci prorazeni na tech nemrtvych, ale proti zivemu, dychajicimu \"\n\"nepriteli mec krasne porcuje jeho maso!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Tvuj zapas proti Temnote se projevi i na tvych zbranich a zbroji. Jestli je \"\n\"prineses ke mne, muzu je, s trochou prace a horkou vyhni, opravit do \"\n\"nejlepsi bojove podoby.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Zatimco ja musim kovy a naradi, ktere potrebuji od karavan, co projizdeji \"\n\"kolem naseho zatraceneho mesta, temer pasovat, zda se, ze ta carodejka Adria \"\n\"vzdy dostane vsechno, co chce. Kdybych o spoutani magie vedele jenomu trochu \"\n\"toho, co ona, mohla bych vyrabet skutecne neuveritelne veci.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian je hezke devce. Je smula, ze ma jeji babicka tak chatrne zdravi, \"\n\"jinak bych uz dohodl, aby je nektera z obchodnich karavan odvezla odtud.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Nekdy si myslim, ze Cain mluvi prilis mnoho, ale tusim, ze to je jeho smysl \"\n\"zivota. Kdybych si mohl poddat ocel jako on tvoje usi, mohl bych vykovat \"\n\"brneni dobre i pro samotneho Cisare!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Byl jsem s Farnhamem te noci, kdy nas Lazarus zavedl do Labyrintu. Uz nikdy \"\n\"jsem Arcibiskupa nevidel a nejspis bych neprezil, kdyby Farnham nebojoval se \"\n\"mnou. Bojim se, ze utok zmrzacil jeho dusi stejne jako jiny moji nohu. Tuhle \"\n\"bitvu pro nej nemohu vybojovat, ale udelal bych to, kdybych jen mohl.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Dobry clovek, ktery vyvysuje potreby jinych nad svoje. V Tristramu - nebo \"\n\"kdekoliv jinde - nenajdes jedineho cloveka, ktery by mohl rict neco spatneho \"\n\"o nasem leciteli.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Ten hoch se urcite dostane do velkych problemu... tusim, ze bych mohl rict, \"\n\"uz zase. Zkousel jsem v nem vzbudit zajem o praci u mne a nauceni se radneho \"\n\"remesla, ale on dava prednost vysokemu zisku pri obchodu se zbozim \"\n\"pochybneho puvodu. Nemohu to po nem chtit po tom, co se mu stalo, ale preji \"\n\"si, aby byl alespon opatrny.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Hostinsky zde ma male obchody a zadny zpusob vydelku. Trochu si to vynahradi \"\n\"tim, ze poskytuje jidlo a nocleh tem, kteri sem tam prochazeji vesnici, ale \"\n\"ti se pravdepodobne odplizi v noci, aby nemuseli platit. Kdyby nebylo jeho \"\n\"zasob obili a suseneho masa, ktere ma ve sklepe, vetsina z nas by urcite \"\n\"umrela hlady v tom prvni roce, kdy bylo cele okoli zaplaveno demony.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Copak nemuzu v klidu pit?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"Holka, co nosi piti? Oh, jo, to je pjekna divka. A prijemna taky.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Proc ta stara baba nedela taky neco jinyho. Jasne, jasne, ma ruzny nesmysly, \"\n\"ale poslouchej... ona neni normalni. Nikdy sem ji nevidel jist nebo pit - a \"\n\"nemuzes verit nekomu, kdo aspon trochu nepije.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain neni, co rika, ze je. Jasne, jasne, povida dobry pribehy... nektery \"\n\"jsou fakt strasidelny nebo vesely... ale myslim, ze vi vic, nez vi, ze vi.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Dobry Griswold. Mam ho rad jako bratra! Bojovali jsme spolu, vis, \"\n\"kdyz jsme... my... Lazarus... Lazarus... Lazarus... Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, mam rad Pepina. Fakt se snazi, vis. Poslouchej, mel bys ho fakt \"\n\"poznat. Dobry clovek a lidi, co potrebuou pomoct. Hej, hadam, ze je trochu \"\n\"jako ty, he hrdina? Ja sem taky bejval hrdina...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt je decko a ma vic problemu nez ja a ja vim o problemech vsecko. \"\n\"Poslouchej - ten kluk ma fajn obchod, ale byl tam dole, vis? Prisel o nohu! \"\n\"Musi chodit na kousku dreva. Smutne, smutne...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden je nejlepsi chlap ve meste. Nemyslim, ze mne jeho zena ma moc rada, \"\n\"ale dokud on ovlada pipu, tak mi nevadi. Zda se, ze u Ogdena travim vic \"\n\"casu, nez je mozne, ale on je na mne tak hodny...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Chci ti neco rict, protoze vim o techhle vecech vsechno. Je to moje \"\n\"specialita. Tohle tady je nejlepsi... neeeejlepsi! Tohle druhe pivko neni \"\n\"tak dobre, kvuli tem blbym psum...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Nikdo mne nepos... neposloucha. Nekde - nevim to jiste - ale nekde pod \"\n\"kostelem je velka kupa zlata. Leskne se a sviti a jenom ceka na nekoho, kdo \"\n\"si to vezme.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Vim, ze mas vlastni myslenky, a vim, ze tomu nebudes verit, ale ta zbran, co \"\n\"tu mas - to neni tak dobre proti tem velkym bestiim! Oh, nezajima mne, co \"\n\"rika Griswold, proste nemuzou udelat nic podobneho jako to delali kdysi...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Kdybych byl ty... a nejsem... ale kdybych byl, prodal bych to vsechno a \"\n\"rychle odcud vypadl. Ten kluk tam... Vzdycky ma neco dobryho, ale musis mu \"\n\"dat naky prachy jinak ti ani neukaze, co ma.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Uvedomuji si dusi v hledani odpovedi...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Zadny uceny z nebe nespadl. Objevis-li svazek vedeni, zjisti, co rika. I \"\n\"kdybys mel jiz vedomosti o davnych tajemstvich popsanych v knize, pamatuj si \"\n\"- uroven mistrovstvi se vzdy muze zvysit.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Nejvetsi sila ma casto nejkratsi zivot. Na svitku muzes nalezt zapsan davna \"\n\"slova moci. Sila techto svitku je v tom, ze je dokaze seslat i uplny \"\n\"zacatecnik i mistr. Jejich slabinou je, ze musi byt nejprve nahlas precteny \"\n\"a nikdy se ti neudrzi v mysli. Take bys mel vedet, ze tyto svitky mohou byt \"\n\"precteny pouze jednou, a proto je pouzivej s rozvahou.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Ackoliv je zar nesrovnatelny, pouhy plaminek svice je nebezpecnejsi. Zadna \"\n\"energie, nezalezi jak silna, nemuze byt pouzita bez patricneho soustredeni. \"\n\"Kouzelne Hole s mnoha kouzly mohou byt nescetnekrat nabity magickou energii. \"\n\"Mam  schopnost obnovit jejich silu - ale sam vis, ze nic neni zadarmo.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Mnozstvi nasich vedomosti zavisi na mnozstvi lidi. Najdes-li knihu ci \"\n\"svitek, ktery nemuzes rozlustit, nevahej a prines ho ke mne. Pokud ho \"\n\"pochopim, podelim se z tebou o to, co zjistim.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Pro muze, ktery zna pouze Zelezo, neni vetsi magie nez Ocel. Kovar Griswold \"\n\"je vice carodejem nez vi. Jeho schopnosti rozehrat ohen a kovat zelezo neni \"\n\"v teto zemi rovno.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Zkazenost ma silu podvodu, ale nevinnost vladne moci cistoty. Mlada zena \"\n\"Gillian ma ciste srdce a uprednostnuje potreby sve pramatky pred svymi. Boji \"\n\"se mne, ale je to pouze kvuli tomu, ze mi nerozumi.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Truhla otevrena v temnote neskryva vetsi poklad nez, kdyz je otevrena na \"\n\"svetle. Vypravec Cain je zahadou, ale jen pro ty, kteri se nedivaji. Jeho \"\n\"vedomosti o tom, co lezi pod katedralou, jsou jeste vetsi nez si on sam \"\n\"uvedomuje.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Cim vice veris jednomu muzi, tim horsi je pad. Farnham ztratil svou dusi, \"\n\"ale ne kvuli nejakemu demonovi. Ztratil ji, kdyz videl, jak Arcibiskup \"\n\"Lazarus zradil jeho pratele. Ma dulezite vedomosti, ale musis oddelit \"\n\"skutecnost od fantazie.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Ruce, srdce a mysl mohou provadet zazraky, pokud jsou v dokonalem souladu. \"\n\"Lecitel Pepin se v tele vyzna tak, jak to ani ja nedokaze. Jeho schopnost \"\n\"uzdravovat nemoci a poraneni je jeste zvetsena tim, ze chape vyrobu elixiru \"\n\"a lektvaru. Je to velky spojenec, ktereho muzes v Tristramu mit.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Nemuzeme videt mnoho z budoucnosti, ale az to prijde, prinese to dite. \"\n\"Chlapec Wirt ma na dusi cernotu, ale pro mesto nebo jeho obyvatele \"\n\"nepredstavuje hrozbu. Jeho tajne obchody se zlodejicky a podezrelymi cechy z \"\n\"blizkych mest mu zarucuje pristup k mnoha predmetum, ktere v Tristramu \"\n\"nejsou lehce dostupne. I kdyz muzes vycitat jeho metody, Wirt muze zajistit \"\n\"pomoc pro tvou bitvu proti pripravujici se Temnote.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Hlinene zdi a doskova strecha nedelaji domov. Hostinsky Ogden slouzi ve \"\n\"meste k vice vecem nez mnohy chape. Poskytuje pristresek Gillian a jeji \"\n\"pramatce, udrzuje to, co zivot zanechal Farnhamovi, a pomaha vsem, kteri ve \"\n\"meste zustali, aby byl Tristram jako driv. Jeho krcma, a prosta poteseni, \"\n\"ktera se zde daji stale nalezt, obstaravaji zablesky zivota, jaky si lide \"\n\"pamatuji. Jsou to tyto vzpominky, ktere stale udrzuji jejich nadeji, ze \"\n\"uspejes.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... tady...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Nikdo v Tristramu nema pouziti - nebo odbyt - pro vsechno, co najdes v \"\n\"labyrintu. Ani ja ne, i kdyz je tezke tomu uverit. \\n\"\n\" \\n\"\n\"Nekdy budes jenom ty schopen najitr vyuziti pro nektere ty veci.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Never vsemu, co rika ten opilec. Prilis mnoho piva zamlzilo jeho zrak a jeho \"\n\"zdravy rozum.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Jestli sis toho jeste nevsiml, nekupuju nic z Tristramu. Jsem dovozcem \"\n\"kvalitniho zbozi. Jestli chces nabizet vetes, musis jit za Griswoldem, \"\n\"Pepinem nebo za tou carodejnici Adrii. Jsem si jist, ze skoci po vsem, co \"\n\"jim prineses...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Soudim, ze dluzim kovari zivot - co z neho zbylo. Jiste, Griswold mi nabidl \"\n\"uceni v kovarne a je docela prijemny chlapik, ale nikdy bych neziskal dost \"\n\"zlata na... dobre, reknu ri jenom, ze mam urcite plany, na ktere potrebuju \"\n\"hodne zlata.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Kdybych byl o par let starsi, zahrnul bych ji vsim bohatstvim, co bych \"\n\"sehnal, a ujistuji te, ze se mohu dostat k opravdu pekne zbozi. Gillian je \"\n\"krasne devce, ktere by melo vypadnout z Tristramu hned, jak to bude \"\n\"bezpecne. Hmmm... mozna, ze ji vezmu s sebou, az pujdu...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain vi prilis hodne. Dost me otravuje - vic nez ta zenska za rekou. Porad \"\n\"mi vypravi, jak jsem stastny, ze jsem nazivu, a jak se muj pribeh prenasi v \"\n\"legendach. Myslim, ze mu trochu preskocilo.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - to je clovek s vaznymi problemy a ja vim o vaznych problemech \"\n\"vsechno. Prilis veril v poctivost jednoho muze a Lazarus ho zavedl do sameho \"\n\"chrtanu smrti. Oh, ja vim, jake to je tam dole, tak mi nezacni povidat o \"\n\"svych planech na zniceni zla, ktere zije v tom Labyrintu. Jenom si davej \"\n\"pozor na nohy...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Dokud nepotrebujes neco pripojit, je stary Pepin hodne dobry. \\n\"\n\" \\n\"\n\"Kdybych tenkrat mel nektery z tech lektvaru, co vari, mohl jsem mit nohu...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria me opravdu trapi. Jiste, Cain ti muze rict hodne o minulosti, ale \"\n\"carodejka vidi do tvoji minulosti. Vzdycky najde nejaky zpusob, jak dostat \"\n\"vsechno, co chce. Adriinyma rukama proslo vice zbozi, nez jsem kdy videl \"\n\"projit branami Kralovskeho Bazaru behem Velke Slavnosti.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden je blazen, ze tu zustava. Mohl bych ho dostat z mesta za velmi \"\n\"rozumnou cenu, ale on trva na tom, ze povede tu hloupou hospodu. Alespon \"\n\"dava Gillian misto, kde muze pracovat, a jeho zena Garda pece skvely Ovcacky \"\n\"kolac...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Za Sinemi hrdinu lezi Komnata kosti. Vecna smrt ceka na kazdeho, kdo by se \"\n\"snazil ukrast poklady chranene v teto sini. Tak pravil Pan hruzy a tak jest \"\n\"to psano.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...a tak, zamceno za Branou krve a Sinemi ohne, ceka Udatnost na Hrdinu \"\n\"svetla, aby procitlo...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Nemuzes videt to co ja.\\n\"\n\"Oko se mlzi,obzor zakryva.\\n\"\n\"Otocis se a jsou pryc,\\n\"\n\"Slysis sumot a nic vic.\\n\"\n\"Potom vidis, co nemuze byt,\\n\"\n\"Stin se hybe, kde svetlo ma byt.\\n\"\n\"Pryc z temna z myslenek tvych,\\n\"\n\"Svrzen jsi do Sine slepych.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Zbrojnice Pekla jsou domovem Vojevudce Krve. Za nim lezi zohavena tela \"\n\"tisicu. Andele i lide byli zabijeni, aby slouzili pri jeho nekonecnem \"\n\"obetovani Temnym, kteri prahnou pouze po jedine veci - po krvi.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Pozor dej a svedc o pravdach, jez zde ctes, jelikoz jsou poslednim odkazem \"\n\"Horadrim. Prave ted zuri valka, ne na bitevnim poli, ktere zname - mezi \"\n\"vybornym kralovstvim Vysokeho Nebe a chaotickou dirou Horoucich Pekel. Tato \"\n\"valka jest znama jako Velky konflikt a zuri a plane dele nez hvezdy na \"\n\"obloze. Zadna ze stran nikdy neziskala prevahu na dlouhou dobu, kdyz sily \"\n\"Svetla a Temnoty souperi o vladu nad vsemi stvorenimi.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Pozor dej a svedc o pravdach, jez zde ctes, jelikoz jsou poslednim odkazem \"\n\"Horadrim. Kdyz se Vecny konflikt mezi Vysokym Nebem a Horoucim Peklem \"\n\"presunul do zeme smrtelniku, byl nazyvan Hrisna Valka. Andele a Demoni \"\n\"kraceli v prevleku mezi lidmi, bojovali ve skrytu, vzdaleni od vsetecnych \"\n\"oci smrtelniku. Nekteri odvazni a mocni smrtelni se pripojili k nektere ze \"\n\"stran a pomahali urcovat vyvoj Hrisne Valky.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Pozor dej a svedc o pravdach, jez zde ctes, jelikoz jsou poslednim odkazem \"\n\"Horadrim. Pred temer tremi stovkami let se stalo, ze Tri Prvotni Zla z \"\n\"Horoucich Pekel zahadne vstoupila do naseho sveta. Tri Bratri pustosili po \"\n\"desetileti zeme vychodu, zatimco se lide v jejich stopach trasli strachem. \"\n\"Nas Rad - Horadrim - byl zalozen tajnou skupinou magu, aby vypatral a \"\n\"uveznil Tri Zla pro jednou a naveky.\\n\"\n\" \\n\"\n\"Puvodne Horadrim uveznili dva ze Tri v mocnych artefaktech, jez jsou znamy \"\n\"jako Kameny duse, a pohrbili je hluboko pod piskem vychodnich pousti. Treti \"\n\"Zlo uniklo zajmuti a uprchlo na zapad, pronasledovano mnoha Horadrim. Treti \"\n\"Zlo - zname jako Diablo, Pan Hruzy - bylo nakonec dopadeno, jeho podstata \"\n\"ulozena do Kamenu duse a pohrbena v tomto Labyrintu.\\n\"\n\" \\n\"\n\"Budiz kazdy varovan, ze Kamen duse nesmi byt objeven lidmi bez viry. Bude-li \"\n\"Diablo uvolnen, vyhleda telo, jez muze jednoduse ovladat, protoze bude \"\n\"velice slaby - treba telo starce ci ditete.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"I stalo se, ze v Horoucich Peklech propukla revoluce znama jako Temne \"\n\"vyhnanstvi. Nizsi Zla svrhla Tri Prvotni Zla a vyhostila jejich duchovni \"\n\"formy do rise smrtelniku. Demonove Belial (Pan Lzi) a Azmodan (Pan Hrichu) \"\n\"bojovali o ziskani vlady nad Peklem behem nepritomnosti Tri Bratru. Cele \"\n\"Peklo se rozdelilo na frakce Beliala a Azmodana, zatimco sily Vysokeho Nebe \"\n\"neustale dorazely az temer na same Brany Pekla.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Mnoho demonu putovalo po risich smrtelniku a hledalo Tri Bratry. Tito demoni \"\n\"byli do smrtelne roviny nasledovani Andeli, kteri je pronasledovali v \"\n\"ohromnych mestech Vychodu. Andele se spojili s tajnym Radem smrtelnych magu, \"\n\"znamym jako Horadrim, kteri se rychle stali odborniky na patrani po \"\n\"demonech. Take si udelali mnoho temnych nepratel v podsveti.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"I stalo se, ze Tri Prvotni Zla byal v duchovni forme vyhnana do rise \"\n\"smrtelniku a po desetiletich rozsevani chaosu na Vychode, byla ulovena \"\n\"prokletym Radem smrtelniku Horadrim. Horadrim pouzili artefakty zvane Kameny \"\n\"duse, aby v nich zachytili podstatu Mefista, Pana Nenavisti, a jeho bratra \"\n\"Baala, Pana Zniceni. Nejmladsi z bratru - Diablo, Pan Hruzy - uprchl na \"\n\"zapad.\\n\"\n\" \\n\"\n\"Nakonec Horadrim uveznili i Diabla do Kamenu duse a pohrbili ho pod davnou, \"\n\"zapomenutou Katedralou. Tam Pan Hruzy spi a ocekava cas sveho znovuzrozeni. \"\n\"Vez, ze bude hledat telo mlade a nadane, aby ho ovladl - takove, ktere je \"\n\"nevinne a snadno ovladatelne. Pote povstane, aby uvolnil sve Bratry a znovu \"\n\"rozviril plameny Hrisne Valky...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Vsichni velebi Diabla - Pana Hruzy a Toho, jez prezil Temne vyhnanstvi. Kdyz \"\n\"se probudil z dlouheho spanku, muj Pan a Mistr se mnou mluvil o tajemstvich, \"\n\"jez zna pouze par smrtelniku. Rekl mi o vecne valce kralovstvi Vysokeho Nebe \"\n\"a diry Horoucich Pekel. Odhalil mi sily, ktere prinesly tento nesvar do rise \"\n\"lidi. Muj Pan nazval tuto bitvu o nas svet a vse, co zde existuje, Hrisna \"\n\"Valka.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Slavu a podporu Diablovi - Panu Hruzy a Vudci Tri. Muj Pan mi rekl o svych \"\n\"dvou Bratrech, Mefistovi a Baalovi, kteri byli pred davnymi veky vyhnani do \"\n\"tohoto sveta. Muj Pan si preje vyckat na svuj cas a sbirat sve straslive \"\n\"sily, aby mohl osvobodit sve uveznene bratry z jejich hrobky pod poustemi \"\n\"vychodu. Jakmile muj Pan uvolni sve Bratry, Hrisna Valka opet pozna zurivost \"\n\"Tri.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Slava a obetovani Diablovi- Panu Hruzy a Niciteli dusi. Kdyz jsem probudil \"\n\"meho Pana ze spanku, pokusil se ziskat smrtelnou podobu. Diablo zkusil \"\n\"ziskat telo Krale Leorica, ale muj Pan byl z uvezneni prilis slaby. Muj Pan \"\n\"pozadoval jednoduchou a nevinnou cestu do tohoto sveta a zjistil, ze je pro \"\n\"tento ukol nejvhodnejsi chlapec Albrecht. Zatimco dobry Kral Leoric zesilel \"\n\"po neuspesnem Diablove pokusu o jeho ovladnuti, unesl jsem jeho syna \"\n\"Albrechta a privedl ho pred meho Mistra. Nyni ocekavam Diablovo volani a \"\n\"preji si, abych byl odmenen, kdyz se konecne vynori jako Pan tohoto sveta.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Díky bohu, že ses vrátil!\\n\"\n\"Hodně se toho změnilo od doby kdy jsi tu žil, příteli. Všude byl klid dokud \"\n\"nepřišli temní nájezdníci a nezničili naši vesnici. Mnozí byli na místě \"\n\"sťati a ti, kteří pozvedli zbraně, byli zabiti nebo odvlečeni, aby se stali \"\n\"otroky - nebo hůř. Kostel na konci mesta byl znesvěcen a je používán pro \"\n\"temné rituály. To vřískání co se rozléhá nocí je nelidské, ale nekteří \"\n\"našich vesničanů ještě možná přežijí. Jdi po cestě ležící mezi mojím \"\n\"hostincem a kovárnou, abys našel kostel, a zachraň koho můžeš. \\n\"\n\" \\n\"\n\"Snad ti řeknu více když si opět promluvíme. Hodně štěstí.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Pokracuj ve svem ukolu. Hledani ztraceneho pokladu neni jednoduche. Najit \"\n\"poklad, ktery nekdo schoval je jednodussi. Necham te nad tim premyslet. \"\n\"Nedovol, aby cas zmatl tve hledani.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Coze?! To je hloupost. Tady v Tristramu neni zadny zakopany poklad. Ukaz mi \"\n\"to!! Ah, podivej se na to. Tyhle kresby jsou nepresne. Neodpovidaji nasemu \"\n\"mestu. Pamatoval bych si na to, co lezi pod katedralou, ale ne co lezi pod \"\n\"nasimi kopci.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Opravdu nemam cas, diskutovat s tebou o nejake mape. Mam mnoho nemocnych \"\n\"lidi, kteri potrebuji mou pomoc a ty taky.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Pysny Iswall byl uveznen hluboko pod povrchem tohoto sveta. Jeho cest \"\n\"zmizela a vzhled se zmenil. Je uveznen v nekonecnych mukach a trapenich. \"\n\"Tajne doufa, ze se jednou stane velka vec, ktera ho osvobodi.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Vsadim se, ze te Wirt videl prichazet a nahral to tak, aby se mohl pozdeji \"\n\"smat, az budes behat kolem mesta s nosem ve spine. Ignoroval bych to.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Byly casy, kdy bylo tohle mesto castou zastavkou obchodniku z dalekeho \"\n\"okoli. Monoho se od tech dob zmenilo. Ale skryte jeskyne a pohrbene poklady \"\n\"jsou jenom detske povidacky. Wirt se malokdy oddava detskym hram. Mozna ze \"\n\"je to jenom jeho predstavivost.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Poslouchej. Pojd bliz. Nevim, jestli vis co vim ja, ale ty mas opravdu jednu \"\n\"zajimavou vec. Tohle je mapa.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Moje babicka mi casto vypravela pribehy o podivnych armadach, ktere obyvaly \"\n\"hrbitov kolem kostela. A mozna by te mohl zajimat jeden, ktery jsem slysela. \"\n\"Ona rikala, ze jestli nechas nejakou obet na hrbitove, vstoupis do \"\n\"katedraly, kde se budes modlit k mrtvym, a pak se vratis, tak ta obet by se \"\n\"mohla zmenit v neco docela jineho. Nevim, mozna ze to jsou pouze reci jedne \"\n\"stare nemocne zeny, ale v soucasne dobe je mozne vsechno.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Hmmm. Obrovsky a tajemny poklad rikas? Mmmm. Mozna bych si od tebe par veci \"\n\"vzal. Nebo radeji, nepotrebujes nejake vzacne a drahe zasoby veci, s ktere \"\n\"ti muzou pomoci projit touhle zkouskou?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Tak ty jsi ten hrdina o kterem kazdy mluvi. Mozna bys mohl pomoci chudemu \"\n\"farmari z jeho problemu? Na konci tohoto ovocneho sadu, jizne odtud, se \"\n\"objevila nejaka podivna vec, ktera vyleza za zeme! Kvuli ni se nemuzu dostat \"\n\"k me urode ani pytlum se senem a moje kravy jsou hladove. Carodejnice mi \"\n\"dala tohle a rikala, ze to tu vec odstrani. Jestli muzes, jdi a znic to, \"\n\"budu ti vdecny. Udelal bych to sam, ale nekdo tady musi zustat s kravami...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Vedel jsem, ze to nebude tak jednoduche, jak carodejnice rikala. Je to \"\n\"spatny svet, kdyz nemuzes verit ani svym sousedum.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Hotovo? Poslal jsi to zpet do temnych zakouti Hadesova sveta? Coze? Oh, \"\n\"nerikej mi, ze jsi to ztratil! Tyhle veci nejsou jen tak k dostani, vis. \"\n\"Musis to najit a potom odstranit tu hruzu pryc z naseho mesta.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Slysel jsem tu explozi! Mnohokrat ti dekuji cizince. Co se vsemi temito \"\n\"vecmi, co vylezaji ze zeme, monstry nicici chramy a tak dale, tohle je cas \"\n\"zkousek. Ja jsem jenom obycejny chudy farmar, ale tady -- vezmi si tohle a \"\n\"mnohokrat dekuji.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Oh, takove problemy co mam... mozna... Ne, nemuzu te vyuzit, co tedy s temi \"\n\"dalsimi problemy. Mozna az vycistis kostel od nekterych priser, mohl by ses \"\n\"vratit... a usetrit svou pomoci trochu casu jednomu chudemu farmari?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Waaaah! (smrka) Waaaah! (smrka)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Ztratil jsem Thea! Meho nejlepsiho pritele! Hrali jsme si u reky, a Theo \"\n\"rikal, ze se chce jit podivat na tu velkou zelenou vec. Rikal jsem mu, ze \"\n\"bychom to nemeli delat, ale potom najednou vylezl ten BROUK! Utikali jsme \"\n\"pryc, ale Theo upadl a ten brouk ho chytil a odnesl pryc!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Nasel jsi ho? Jdi najit Theodora, prosim te! Je jeste maly. Neumi se o sebe \"\n\"jeste postarat! Prosim te!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Ty jsi ho nasel! Nasel jsi ho! Dekuji ti! Oh Theo, vylekali te ti strasni \"\n\"brouci? Hey! Ugh! Tady je nejaka vec, ktera se na tebe lepi. Ick! Pojd Theo, \"\n\"pujdeme domu! Jeste jednou ti dekuji cizince!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Dlouho jsme necinne lezeli a ted nastal cas se probudit. Po nasem dlouhem \"\n\"spanku mame velky hlad. Uz brzo, ted, prijde cas se nakrmit...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Radoval ses, maly savce? Jak pateticke. Ten tvuj maly svet nebude mit zadnou \"\n\"sanci.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Tyhle plochy budou znesveceny a nase rasa zaplavi vsechny pole, ktere volaji \"\n\"lidi domu. Nase upony obklopi tenhle svet a my budeme oslavovat na telech \"\n\"jeho obyvatel. Lide se stanou nasimi otroky a potravou.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, citim te... jsi blizko! Blizko! Ssss... vune krve a strachu... jak je to \"\n\"lakave...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"A v roce Zlateho Svetla bylo rozhodnuto o stavbe velke Katedraly. Zakladni \"\n\"kamen tohoto svateho mista byl vytesan z prusvitneho kamene Antyrael, ktery \"\n\"dostal jmeno po Andelovi, ktery sdilel svou silu s Horadrim. \\n\"\n\" \\n\"\n\"V Roce Barevnych stinu nastalo zemetreseni a Katedrala se narusila a spadla. \"\n\"Kdyz zacala stavba katakomb a vezi a muzi byli postaveni proti pustoseni \"\n\"Hrisne Valky, byly ruiny rozebrany kvuli potrebe kameni. A tak se stalo, ze \"\n\"zakladni kamen zmizel z jejich oci. \\n\"\n\" \\n\"\n\"Tento kamen byl soucast tohoto sveta -- a soucast vsech svetu -- stejne jako \"\n\"Svetlo je na pocatku vsech veci i na konci vsech veci. Svetlo a jednota jsou \"\n\"produkty tohoto svateho zrizeni, jednota vsech smyslu a jednota vlastnictvi.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Rikam, Muuu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Podivej, jsem krava, OK?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Dobre, dobre. Nejsem opravdova krava. Normalne tohle nedelam; ale sedel jsem \"\n\"takhle doma, premyslel o obchode a najednou zacaly pres podlahu vylezat \"\n\"vsechny tyhle divne veci & brouci & rostliny... bylo to silene! Kdybych mel \"\n\"neco normalniho na sebe, nebylo by to tak hrozne. Hey! Mohl by jsi zajit ke \"\n\"mne domu a prinest mi obleceni? To hnede, ne to sedive, to je na vecer. \"\n\"Udelal bych to sam, ale nechci, aby me takhle nekdo videl. Tady, vezmi si \"\n\"tohle. Mozna to budes potrebovat... na zabiti tech veci, ktere mi rostou na \"\n\"zahrade. Muj dum nemuzes minout, je na jihu od mista, kde se reka \"\n\"rozdeluje... vsak uvidis... je to ten, u ktereho je zarostla zahradka.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Proc plytvas casem? Jdi hledat muj oblek! A rychle! Tamhleten Holstein se na \"\n\"mne porad diva!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hej, donesl jsi mi muj oblek? Rychle, nevsimej si toho. Tyhle usi svedi \"\n\"stejne jako ty neveris!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Ne ne ne ne!  Tohle je SEDIVY oblek!  Ten je na večer!  Tenhle si NEMUZU \"\n\"obleci.  Copak jsi to za hlupaka?  Potrebuju HNEDY oblek.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, to je mnohem lepsi. Whew! Konecne, nejaka dustojnost! Mam rohy rovne? \"\n\"Dobre. Podivej, diky, ze jsi mi pomohl. Tady, vezmi si to jako malou odmenu. \"\n\"A jeste jeden maly modni tip... muzes pouzit maly... muzes pouzit novy... \"\n\"vis co myslim? Cely motiv dobrodruha je tak... retro. Takova mala rada, ze? \"\n\"Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Podivej. Ja jsem krava. A ty jsi navnada pro prisery. Naber par zkusenosti a \"\n\"pak si promluvime...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Musi to opravdu byt strasny ukol, ktery jsem pred tebe postavil. Kdybych ti \"\n\"mohl jakkoliv... pomohla by ti sklenice pekneho, cerstveho mleka?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Oh, mozna bys mi mohl pomoci, ale snad az pote, co vycistis katakomby od \"\n\"tehletech nevericich bestii.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Potrebuji neco udelat, ale nemuzu duverovat cizinci. Mozna az tady budes \"\n\"nejaky cas, budu se citit lepe, kdyz s tebou budu mluvit.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Vidim v tobe velike moznosti. Mozna nekdy, az budes znat svuj osud, mohl by \"\n\"ses u mne zastavit a udelat mi jednu laskavost?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Myslim, ze bys mi pravdepodobne mohl pomoci, ale snad az budes trosku \"\n\"silnejsi. Nemuzu dopustit, aby padla jedina sance nasi vesnice na zniceni \"\n\"toho zla v chramu!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Ja jsem samorostla krava. Udelej neco se sebou a... potom si promluvime.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Nebudu se zpovidat kazdemu turistovi, ktery pujde kolem! Nemas zabit par \"\n\"monster? Mozna si promluvime pozdeji. Pokud budes jeste nazivu...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Prestan me otravovat. Hledam opravdoveho hrdinu. A to ty nejsi. Ty jsi jen \"\n\"potrava pro prisery... Potrebuji nejakeho zkuseneho hrdinu.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Dobra. Nechci te plest. Sedel jsem takhle doma, kdyz najednou se zacalo \"\n\"vsechno menit. Obrovske stada priser se zacala valit z podlahy! Zpanikaril \"\n\"jsem. Jedine, co jsem byl schopen udelat, bylo obleknout si tuhle Jersey \"\n\"kdyz jsem utikal ze dveri. No a ted vypadam takhle smesne. Kdybych ale mel \"\n\"neco normalniho na sebe, nebylo by to tak zle. Hey! Mohl bys zajit ke mne \"\n\"domu a donest mi obleceni? To hnede, ne to sedive, to je na vecer. Udelal \"\n\"bych to sam, ale nechci, aby me takhle nekdo videl. Tady, vezmi si tohle. \"\n\"Mozna to budes potrebovat... na zabiti tech veci, ktere mi rostou na \"\n\"zahrade. Muj dum nemuzes minout, je na jihu od mista, kde se reka \"\n\"rozdeluje... vsak uvidis... je to ten, u ktereho je zarostla zahradka.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Vyzkousel jsem kouzla, hrozby, prisahy a smlouvani s temihle odpornymi tvory \"\n\"-- bez uspechu. Moje metody na zotroceni mensich priser nemaji na techto \"\n\"bestiich zadny uspech.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Muj domov se pomalu kazi, diky temhletem nezvanym veznum. Krypty jsou plne \"\n\"stinu, ktere se pohybuji pouze v zakoutich me mysli. Nejasne naznaky drapu \"\n\"tanci na okrajich meho sluchu. Hledaji, myslim si to, hledaji novinky.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Mezi recmi jim uniklo jeho jmeno -- Na-Krul. Pokusil jsem se prozkoumat \"\n\"tohle jmeno, ale mali demoni mi nejak znicili mou knihovnu. Na-Krul... To \"\n\"jmeno me naplnuje obavami. Radeji o nem budu uvazovat jako o Prisere. Je to \"\n\"lepsi nez jeho prave jmeno.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Sileny vriskot zajatych priser mi neda spat. Jsou nastvane na toho, kdo je \"\n\"vyslal do Pustiny a svolavaji na me kletby za to, ze je tady veznime. Tyhle \"\n\"jejich slova naplnuji me srdce strachem a nedari se mi zbavit se tech hlasu.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Cas mi rychle ubiha. Musim zaznamenat zpusob, jak oslabit demona a pak ukryt \"\n\"tenhle text, pro pripad, ze by jeho prisluhovaci nasli zpusob, jak pomoci \"\n\"mych znalosti osvobodit sveho vudce. Doufam, ze ten kdo tohle najde bude \"\n\"hledat vedomost.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Kdokoliv nasel tenhle svitek, je schopen porazit demonickou stvuru, ktera je \"\n\"za touto zdi. Muj cas vyprsel. Prave ted, jejich prisluhovac skrabe na \"\n\"dvere, vedle kterych se schovavam. \\n\"\n\" \\n\"\n\"Zpoutal jsem demona posvatnym kouzlem a uveznil ho za silnou zdi, ale citim, \"\n\"ze to nestaci. \\n\"\n\" \\n\"\n\"Tri listiny nalezene u mne se postaraji o odstraneni tohoto chraneneho \"\n\"vstupu do jeho kralovstvi, ale pouze pokud se pouziji ve spravnem poradi. \"\n\"Paky na vstupni ceste odstrani barieru a osvobodi demona; nedotykej se jich! \"\n\"Pouzij pouze svitky k dosazeni vstupu jinak jeho sila bude velika a ty ho \"\n\"nebudes moci porazit.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Pekelné Prase\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Žihadlo\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psychokoule\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Arachnid\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Padlá Dvojčata\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Horkův Potěr\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Jedovatý Ocas\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Nekrokoule\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Pavoučí Pán\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Šlehající Červ\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Hořák\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Pekelný Brouk\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Hrobník\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Hrobová Krysa\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Ohnivý Netopýr\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Okřídlená Lebka\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lich\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Démon z Krypty\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Pekelný Netopýr\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Kostěný Démon\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Arci-Lich\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biklop\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Věc z Masa\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Smrťák\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Obrův Kloub\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Rtuťový Prsten\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Xorinin Prsten\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Karikův Prsten\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Prsten Magmatu\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Prsten Mystiků\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Prsten Hromu\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Ochranný Amulet\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Komáří Bodnutí\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Spalovač\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Brnění Pochmurnosti\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Bleskovník\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Zahřmění\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Bílá Čepel\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Pojídač Duší\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Diamantové Ostří\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Kostěné Kroužkové Brnění\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Démonické Plátové Brnění\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Amulet Ministranta\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Gladiátorův Prsten\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Šaškův\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Krystalický\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Dvojníkův\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"devastace\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"rozkladu\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"nebezpečí\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"od Mága\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"od Šaška\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Blesková zeď\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Upálení\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Warp\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Odražení\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Berserk\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Ohnivý Prstenec\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Hledání\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Runa Ohně\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Runa Světla\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Runa Novy\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Runa Upálení\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Runa Kamene\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Nastavení:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"verze {:s}\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Snížit Jas\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Zvýšit Jas\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Automapa není dostupná ve městě\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Restartuj Hru ve Městě\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Srdce\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"doplní životy\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"smrtící léčení\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"sníží sílu\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"sníží obratnost\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"sníží vitalitu\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"nemůžeš se léčit\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"zasažený nepřítel se nemůže léčit\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Rychlejší útočný švih\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"máš infra vidění\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Zkoušíš zahodit předmět na zemi?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Vynutí čekání na Vertikální Synchronizaci. Zabrání efektu trhání \"\n#~ \"obrazovky. Vypnutí může pomoct se zpožděním myši na některých systémech.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Omezovač FPS\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Omezení FPS zabrání vysokému vytížení CPU. Limit počítá s rychlostí \"\n#~ \"obnovení.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Šance na zásah\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Nepodařilo se otevřít archiv hráče k zápisu.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Nelze přečíst z archivu uložené hry\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Nelze zapsat do archivu uložené hry\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Nezničitelný,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Požadavky: nic\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"Za Sinemi hrdinu lezi Komnata kosti. Vecna smrt ceka na kazdeho, kdo by \"\n#~ \"se snazil ukrast poklady chranene v teto sini. Tak pravil Pan hruzy a tak \"\n#~ \"jest to psano.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"Zbrojnice Pekla jsou domovem Vojevudce Krve. Za nim lezi zohavena tela \"\n#~ \"tisicu. Andele i lide byli zabijeni, aby slouzili pri jeho nekonecnem \"\n#~ \"obetovani Temnym, kteri prahnou pouze po jedine veci - po krvi.\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Dneska je chladno a oblacno. Vrhani magickych siti na nove druhy \"\n#~ \"letajicich priser, to je dobra prace na dnesek. Musim si ale objednat \"\n#~ \"vice netopyru a cernych svici od Adrie. Zacinaji mi dochazet.\"\n"
  },
  {
    "path": "Translations/da.po",
    "content": "# Translation of DevilutionX to Danish\n# Anders Jenbo <anders@jenbo.dk>, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:19+0200\\n\"\n\"PO-Revision-Date: 2025-10-02 15:19+0200\\n\"\n\"Last-Translator: Anders Jenbo <anders@jenbo.dk>\\n\"\n\"Language-Team: \\n\"\n\"Language: da\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Spildesign\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Senior designere\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Yderligere design\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Ledende programmør\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Senior programmører\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programmering\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Særlige gæsteprogrammører\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net-programmering\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Seriel kommunikationsprogrammering\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Installationsprogrammering\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Kunst instruktører\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Kunst\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Teknisk kunst\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Filmregissører\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D filmisk kunst\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Filmisk teknisk kunst\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Overordnet instruktør\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Instruktør\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Associeret producent\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Musik\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Lyddesign\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Filmisk musik og lyd\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Stemmeproduktion, retning og casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Manuskript og historie\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Stemmeredigering\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Stemmer\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Optagelsesingeniør\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Design af manual og layout\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Manualkunst\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Foreløbig direktør for QA (Lead tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA-angrebsteam (testere)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA-frømandskorps (kompatibilitetstestere)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA-artilleristøtte (ekstra testere) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA-modintelligens\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Bestilling af netværksinformationstjenester\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\n#, fuzzy\n#| msgid \"Support\"\nmsgid \"Customer Support\"\nmsgstr \"Support\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Salg\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Drønnert\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Hr. Dabiris baggrundsvokalister\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"PR\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Internationalt salg\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"U.S.-salg\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Produktion\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Juridisk & forretning\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Særlig tak til\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Tak til\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Til minde om\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Meget Særlig tak til\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\n#, fuzzy\n#| msgid \"Art Directors\"\nmsgid \"Art Director\"\nmsgstr \"Kunst instruktører\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\n#, fuzzy\n#| msgid \"Game Design\"\nmsgid \"Design\"\nmsgstr \"Design af manual og layout\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\n#, fuzzy\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Foreløbig direktør for QA (Lead tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\n#, fuzzy\nmsgid \"Testers\"\nmsgstr \"QA-artilleristøtte (ekstra testere) \"\n\n#: Source/DiabloUI/credits_lines.cpp:248\n#, fuzzy\n#| msgid \"Manual Artwork\"\nmsgid \"Manual\"\nmsgstr \"Design af manual og layout\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\n#, fuzzy\n#| msgid \"Additional Design\"\nmsgid \"\\tAdditional Work\"\nmsgstr \"Yderligere design\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks to\"\nmsgstr \"Tak til\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\n#, fuzzy\n#| msgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"Meget Særlig tak til\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\n#, fuzzy\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Foreløbig direktør for QA (Lead tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\n#, fuzzy\nmsgid \"Main Testers\"\nmsgstr \"QA-angrebsteam (testere)\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\n#, fuzzy\n#| msgid \"Additional Design\"\nmsgid \"Additional Testers\"\nmsgstr \"QA-artilleristøtte (ekstra testere) \"\n\n#: Source/DiabloUI/credits_lines.cpp:288\n#, fuzzy\nmsgid \"Product Marketing Manager\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\n#, fuzzy\n#| msgid \"Public Relations\"\nmsgid \"Public Relations Manager\"\nmsgstr \"PR\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\n#, fuzzy\n#| msgid \"Associate Producer\"\nmsgid \"Associate Product Manager\"\nmsgstr \"Associeret producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tIngen sjæle blev solgt i fremstillingen af dette spil.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Vælg klasse\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Annuller\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Ny multiplayer-helt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Ny singleplayer-helt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Gem filen findes\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Indlæs spil\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Nyt spil\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Singleplayer-karakterer\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Skytten og Troldmanden er kun tilgængelige i den fulde detailversion af \"\n\"Diablo. Besøg https://www.gog.com/game/diablo for at købe den.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Indtast navn\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Ugyldigt navn. Et navn kan ikke indeholde mellemrum, reserverede tegn eller \"\n\"reserverede ord.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Niveau:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Styrke:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magi:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Smidighed:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalitet:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\n#, fuzzy\n#| msgid \"Save Game\"\nmsgid \"Savegame:\"\nmsgstr \"Gem spil\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Vælg helt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Ny helt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Slet\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Multiplayer-karakteren\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Slet multiplayer-helt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Slet singleplayer-helt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, fuzzy, c++-format\n#| msgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Er du sikker på, at du vil slette karakteren \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Singleplayer\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Multiplayer\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Support\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Vis kredit\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Afslut Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Afslut Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgid \"Shareware\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Klient-server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"Loopback\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Multiplayer-spil\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\n#, fuzzy\n#| msgid \"Requirements:\"\nmsgid \"Requirements:\"\nmsgstr \"Krav:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"ingen gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Vælg forbindelse\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Skift gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Alle computere skal være tilsluttet et TCP-kompatibelt netværk.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\n#, fuzzy\n#| msgid \"All computers must be connected to a TCP-compatible network.\"\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Alle computere skal være tilsluttet et TCP-kompatibelt netværk.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Spil alene uden nogen netværkseksponering.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Vælg handling\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Opret spil\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\n#, fuzzy\n#| msgid \"Create Game\"\nmsgid \"Create Public Game\"\nmsgstr \"Opret spil\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\n#, fuzzy\n#| msgid \"Join TCP Games\"\nmsgid \"Join Game\"\nmsgstr \"Spildesign\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\n#, fuzzy\n#| msgid \"Quit Diablo\"\nmsgid \"Public Games\"\nmsgstr \"Indlæs spil\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ANNULLER\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Opret et nyt spil med sværhedsgrad efter eget valg.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\n#, fuzzy\n#| msgid \"Create a new game with a difficulty setting of your choice.\"\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"Opret et nyt spil med sværhedsgrad efter eget valg.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Mareridt\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Helvede\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Vælg sværhedsgrad\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Deltag i et {:s}-spil\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\n#, fuzzy\n#| msgid \"Enter Name\"\nmsgid \"Enter address\"\nmsgstr \"Indtast adgangskode\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normal sværhedsgrad\\n\"\n\"Det er her en nybegynder skal starte sin stræben efter at besejre Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Mareridt sværhedsgrad\\n\"\n\"Borgerne i labyrinten er styrket og vil vise sig at være en større \"\n\"udfordring. Dette anbefales kun til erfarne helte.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Helvede sværhedsgrad\\n\"\n\"De mest magtfulde af underverdenens væsener lurer ved indgangen til helvede. \"\n\"Kun de mest erfarne helte skal vove sig ind i denne verden.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Din karakter skal nå niveau 20, før du kan deltage i et multiplayer-spil med \"\n\"mareridt-sværhedsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Din karakter skal nå niveau 30, før du kan deltage i et multiplayer-spil med \"\n\"helvede-sværhedsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\n#, fuzzy\nmsgid \"Select Game Speed\"\nmsgstr \"Vælg forbindelse\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\n#, fuzzy\n#| msgid \"\"\n#| \"Normal Difficulty\\n\"\n#| \"This is where a starting character should begin the quest to defeat \"\n#| \"Diablo.\"\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normal sværhedsgrad\\n\"\n\"Det er her en nybegynder skal starte sin stræben efter at besejre Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\n#, fuzzy\n#| msgid \"\"\n#| \"Nightmare Difficulty\\n\"\n#| \"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n#| \"greater challenge. This is recommended for experienced characters only.\"\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Mareridt sværhedsgrad\\n\"\n\"Borgerne i labyrinten er styrket og vil vise sig at være en større \"\n\"udfordring. Dette anbefales kun til erfarne helte.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Indtast adgangskode\"\n\n#: Source/DiabloUI/selstart.cpp:49\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Enter Hellfire\"\nmsgstr \"Afslut Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\n#, fuzzy\n#| msgid \"Exit Diablo\"\nmsgid \"Switch to Diablo\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Ja\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Nej\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Forrige menu\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/title.cpp:67\n#, fuzzy\n#| msgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment2\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Fejl\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/appfat.cpp:83\n#, fuzzy\nmsgid \"Data File Error\"\nmsgstr \"Skrivebeskyttet mappe fejl\"\n\n#: Source/appfat.cpp:84\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Unable to open {:s}.\\n\"\n#| \"\\n\"\n#| \"Make sure that it is in the game folder and that the file name is in all \"\n#| \"lowercase.\"\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Kan ikke åbne {:s}.\\n\"\n\"\\n\"\n\"Sørg for, at den findes i spilmappen, og at filnavnet er med små bogstaver.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Skrivebeskyttet mappe fejl\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\n#, fuzzy\nmsgid \"Game: \"\nmsgstr \"Multiplayer-spil\"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"Loopback\"\n\n#: Source/automap.cpp:1426\n#, fuzzy\nmsgid \"Password: \"\nmsgstr \"Indtast adgangskode\"\n\n#: Source/automap.cpp:1429\n#, fuzzy\n#| msgid \"Quit Diablo\"\nmsgid \"Public Game\"\nmsgstr \"Indlæs spil\"\n\n#: Source/automap.cpp:1443\n#, fuzzy, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/automap.cpp:1446\n#, fuzzy, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\n#, fuzzy\nmsgid \"Town\"\nmsgstr \"Genstart i byen\"\n\n#: Source/automap.cpp:1452\n#, fuzzy, c++-format\n#| msgid \"Level:\"\nmsgid \"Level: {:d}\"\nmsgstr \"Niveau:\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"\"\n\n#: Source/control.cpp:203\n#, fuzzy\n#| msgid \"Enter Name\"\nmsgid \"Enter\"\nmsgstr \"Indtast navn\"\n\n#: Source/control.cpp:206\n#, fuzzy\nmsgid \"Character Information\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"\"\n\n#: Source/control.cpp:209\n#, fuzzy\nmsgid \"Main Menu\"\nmsgstr \"Forrige menu\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Er du sikker på, at du vil slette karakteren \\\"{:s}\\\"?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\nmsgid \"<player name>\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\n#, fuzzy\nmsgid \"Player friendly\"\nmsgstr \"Multiplayer-spil\"\n\n#: Source/control.cpp:1313\n#, fuzzy\nmsgid \"Player attack\"\nmsgstr \"Singleplayer\"\n\n#: Source/control.cpp:1316\n#, fuzzy, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1331\n#, fuzzy\nmsgid \"Hotkey: 's'\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, fuzzy, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, fuzzy, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, fuzzy, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, fuzzy, c++-format\n#| msgid \"Talk to Pepin\"\nmsgid \"Scroll of {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, fuzzy, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"Understøttede spillere: {:d}\"\nmsgstr[1] \"Understøttede spillere: {:d}\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, fuzzy, c++-format\n#| msgid \"Talk to Pepin\"\nmsgid \"Staff of {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, fuzzy, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"Understøttede spillere: {:d}\"\nmsgstr[1] \"Understøttede spillere: {:d}\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, fuzzy, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"Understøttede spillere: {:s}\"\nmsgstr[1] \"Understøttede spillere: {:s}\"\n\n#: Source/control.cpp:1489\n#, fuzzy\n#| msgid \"Requirements:\"\nmsgid \"Requirements not met\"\nmsgstr \"Krav:\"\n\n#: Source/control.cpp:1518\n#, fuzzy, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"Niveau:\"\n\n#: Source/control.cpp:1519\n#, fuzzy, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\nmsgid \"Right click to inspect\"\nmsgstr \"Skrivebeskyttet mappe fejl\"\n\n#: Source/control.cpp:1573\n#, fuzzy\n#| msgid \"Level:\"\nmsgid \"Level Up\"\nmsgstr \"Niveau:\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/cursor.cpp:621\n#, fuzzy\nmsgid \"Town Portal\"\nmsgstr \"Genstart i byen\"\n\n#: Source/cursor.cpp:622\n#, fuzzy, c++-format\nmsgid \"from {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"\"\n\n#: Source/cursor.cpp:636\n#, fuzzy\nmsgid \"level 15\"\nmsgstr \"Niveau:\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to create character.\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\n#, fuzzy\nmsgid \"Print this message and exit\"\nmsgstr \"Afslut Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\n#, fuzzy\nmsgid \"Print the version and exit\"\nmsgstr \"Afslut Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\n#, fuzzy\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\n#, fuzzy\nmsgid \"Record a demo file\"\nmsgstr \"Gem filen findes\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\n#, fuzzy\nmsgid \"Play a demo file\"\nmsgstr \"Gem filen findes\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Force Hellfire mode\"\nmsgstr \"Afslut Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\n#, fuzzy\nmsgid \"Hellfire options:\"\nmsgstr \"Indstillinger\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\n#, fuzzy\nmsgid \"-- Network timeout --\"\nmsgstr \"Bestilling af netværksinformationstjenester\"\n\n#: Source/diablo.cpp:1552\n#, fuzzy\nmsgid \"-- Waiting for players --\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, fuzzy, c++-format\n#| msgid \"Buy items\"\nmsgid \"Belt item {}\"\nmsgstr \"Køb varer\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Forrige menu\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\n#, fuzzy\nmsgid \"Speedbook\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\n#, fuzzy\nmsgid \"Open Speedbook.\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\n#, fuzzy\n#| msgid \"Save Game\"\nmsgid \"Saves the game.\"\nmsgstr \"Gem spil\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\n#, fuzzy\n#| msgid \"Load Game\"\nmsgid \"Loads the game.\"\nmsgstr \"Indlæs spil\"\n\n#: Source/diablo.cpp:1866\n#, fuzzy\n#| msgid \"Quit Diablo\"\nmsgid \"Quit game\"\nmsgstr \"Indlæs spil\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\n#, fuzzy\nmsgid \"Character\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\n#, fuzzy\nmsgid \"Spellbook\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\n#, fuzzy\nmsgid \"Open Spellbook.\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\nmsgid \"Decrease Brightness\"\nmsgstr \"Styrke:\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\nmsgid \"Increase Brightness\"\nmsgstr \"Styrke:\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\n#, fuzzy\nmsgid \"Increase screen brightness.\"\nmsgstr \"Styrke:\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\n#, fuzzy\n#| msgid \"Game Design\"\nmsgid \"Game info\"\nmsgstr \"Spildesign\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, fuzzy, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"Vælg handling\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"Vælg handling\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"Annuller\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"Multiplayer-karakteren\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"Multiplayer-karakteren\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"Multiplayer-karakteren\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"Multiplayer-karakteren\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\nmsgid \"Automap Move Up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\n#, fuzzy\nmsgid \"Right mouse click\"\nmsgstr \"Skrivebeskyttet mappe fejl\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\n#, fuzzy\nmsgid \"Toggle game menu\"\nmsgstr \"Multiplayer-spil\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Save Game\"\nmsgid \"Opens the game menu.\"\nmsgstr \"Gem spil\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgid \"Game Design\"\nmsgid \"Game saved\"\nmsgstr \"Spildesign\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:67\n#, fuzzy\nmsgid \"Not enough space to save\"\nmsgstr \"Gem filen findes\"\n\n#: Source/diablo_msg.cpp:68\n#, fuzzy\nmsgid \"No Pause in town\"\nmsgstr \"Pause\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:71\n#, fuzzy\nmsgid \"No pause in multiplayer\"\nmsgstr \"Pause\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\n#, fuzzy\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Har du lyst til:\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\n#, fuzzy\nmsgid \"There's no place like home.\"\nmsgstr \"Forlad healers hjem\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\n#, fuzzy\nmsgid \"You feel stronger.\"\nmsgstr \"Har du lyst til:\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\n#, fuzzy\nmsgid \"You feel wiser.\"\nmsgstr \"Har du lyst til:\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\n#, fuzzy\nmsgid \"You feel refreshed.\"\nmsgstr \"Har du lyst til:\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, fuzzy, c++-format\n#| msgid \"Select Difficulty\"\nmsgid \"{} difficulty\"\nmsgstr \"Vælg sværhedsgrad\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\n#, fuzzy\nmsgid \"In Menu\"\nmsgstr \"Forrige menu\"\n\n#: Source/dvlnet/loopback.cpp:117\n#, fuzzy\n#| msgid \"loopback\"\nmsgid \"loopback\"\nmsgstr \"Loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\n#, fuzzy\n#| msgid \"Unable to create character.\"\nmsgid \"Unable to connect\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq eller spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Resolution\"\nmsgstr \"Vælg handling\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\n#, fuzzy\n#| msgid \"Restart In Town\"\nmsgid \"Run in Town\"\nmsgstr \"Genstart i byen\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Pause\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\n#, fuzzy\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Pause\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Indstillinger\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Gem spil\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\nmsgid \"Exit to Main Menu\"\nmsgstr \"Forrige menu\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\n#, fuzzy\n#| msgid \"Quit Diablo\"\nmsgid \"Quit Game\"\nmsgstr \"Indlæs spil\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Musik deaktiveret\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Lyd\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Lyd deaktiveret\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pause\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"\"\n\n#: Source/help.cpp:33\n#, fuzzy\nmsgid \"S: Open Speedbook\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\n#: Source/help.cpp:88\n#, fuzzy\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\n#: Source/help.cpp:94\n#, fuzzy\nmsgid \"$Spell Books:\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\n#: Source/help.cpp:200\n#, fuzzy\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Afslut Hellfire\"\n\n#: Source/help.cpp:200\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Hellfire Help\"\nmsgstr \"Afslut Hellfire\"\n\n#: Source/help.cpp:202\n#, fuzzy\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/help.cpp:202\n#, fuzzy\nmsgid \"Diablo Help\"\nmsgstr \"Afslut Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"\"\n\n#: Source/init.cpp:130\n#, fuzzy\n#| msgid \"Unable to create character.\"\nmsgid \"Unable to create main window\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, fuzzy, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, fuzzy, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, fuzzy, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, fuzzy, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"\"\n\n#: Source/items.cpp:1659\n#, fuzzy\nmsgid \"reduces attributes needed\"\nmsgstr \"ingen gateway\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"\"\n\n#: Source/items.cpp:1674\n#, fuzzy\nmsgid \"increases the armor class\"\nmsgstr \"Vælg klasse\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:1679\n#, fuzzy\nmsgid \"class of armor and shields\"\nmsgstr \"Vælg klasse\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1707\n#, fuzzy\nmsgid \"increase strength\"\nmsgstr \"Styrke:\"\n\n#: Source/items.cpp:1710\n#, fuzzy\nmsgid \"increase magic\"\nmsgstr \"Magi:\"\n\n#: Source/items.cpp:1713\n#, fuzzy\nmsgid \"increase dexterity\"\nmsgstr \"Smidighed:\"\n\n#: Source/items.cpp:1716\n#, fuzzy\nmsgid \"increase vitality\"\nmsgstr \"Vitalitet:\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Højreklik for at læse, og\\n\"\n\"venstreklik derefter for at målrette\"\n\n#: Source/items.cpp:1768\n#, fuzzy\nmsgid \"Right-click to read\"\nmsgstr \"Skrivebeskyttet mappe fejl\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Vælg fra stavebog, og\\n\"\n\"kast derefter stave for at læse\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\nmsgid \"{} to use\"\nmsgstr \"Styrke:\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Vælg fra stavebog, og\\n\"\n\"kast derefter stave for at læse\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Niveau: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\n#, fuzzy\n#| msgid \"Requirements:\"\nmsgid \"Required:\"\nmsgstr \"Krav:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, fuzzy, c++-format\nmsgid \" {:d} Str\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, fuzzy, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, fuzzy, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, fuzzy, c++-format\n#| msgid \"Talk to Pepin\"\nmsgid \"Ear of {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/items.cpp:3874\n#, fuzzy, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3877\n#, fuzzy, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, fuzzy, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/items.cpp:3883\n#, fuzzy, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3886\n#, fuzzy, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"Vælg klasse\"\n\n#: Source/items.cpp:3890\n#, fuzzy, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3896\n#, fuzzy, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3902\n#, fuzzy, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3907\n#, fuzzy, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"\"\n\n#: Source/items.cpp:3920\n#, fuzzy, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\nmsgstr[1] \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3933\n#, fuzzy, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"Styrke:\"\n\n#: Source/items.cpp:3936\n#, fuzzy, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"Magi:\"\n\n#: Source/items.cpp:3939\n#, fuzzy, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"Smidighed:\"\n\n#: Source/items.cpp:3942\n#, fuzzy, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"Vitalitet:\"\n\n#: Source/items.cpp:3945\n#, fuzzy, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"\"\n\n#: Source/items.cpp:3951\n#, fuzzy, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3954\n#, fuzzy, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"\"\n\n#: Source/items.cpp:3962\n#, fuzzy, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3964\n#, fuzzy, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3979\n#, fuzzy, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:3981\n#, fuzzy, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:4037\n#, fuzzy\n#| msgid \"Enter Password\"\nmsgid \"one handed sword\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"\"\n\n#: Source/items.cpp:4043\n#, fuzzy\nmsgid \"no strength requirement\"\nmsgstr \"Styrke:\"\n\n#: Source/items.cpp:4046\n#, fuzzy, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:4048\n#, fuzzy, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4054\n#, fuzzy, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, fuzzy, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, fuzzy, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, fuzzy, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, fuzzy, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, fuzzy, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, fuzzy, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, fuzzy, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/items.cpp:4139\n#, fuzzy\n#| msgid \"Buy items\"\nmsgid \"unique item\"\nmsgstr \"Køb varer\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\nmsgid \"Hell Arena\"\nmsgstr \"Helvede\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:384\n#, fuzzy\nmsgid \"Down to hell\"\nmsgstr \"Helvede\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, fuzzy, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\n#, fuzzy\nmsgid \"Up to town\"\nmsgstr \"Genstart i byen\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, fuzzy, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/levels/trigs.cpp:595\n#, fuzzy\n#| msgid \"Exit Diablo\"\nmsgid \"Down to Diablo\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, fuzzy, c++-format\n#| msgid \"Talk to Pepin\"\nmsgid \"Back to Level {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\n#, fuzzy\n#| msgid \"Unable to create character.\"\nmsgid \"Unable to open save file archive\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\n#, fuzzy\nmsgid \"Invalid save file\"\nmsgstr \"Gem filen findes\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2772\n#, fuzzy\nmsgid \"Invalid game state\"\nmsgstr \"Spildesign\"\n\n#: Source/menu.cpp:157\n#, fuzzy\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4413\n#, fuzzy, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/monster.cpp:4415\n#, fuzzy, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/monster.cpp:4441\n#, fuzzy, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/monster.cpp:4446\n#, fuzzy\nmsgid \"No magic resistance\"\nmsgstr \"Magi:\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magi\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Ild\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Lyn\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4476\n#, fuzzy, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4485\n#, fuzzy\nmsgid \"Some Magic Resistances\"\nmsgstr \"Magi:\"\n\n#: Source/monster.cpp:4489\n#, fuzzy\nmsgid \"Some Magic Immunities\"\nmsgstr \"Magi:\"\n\n#: Source/mpq/mpq_writer.cpp:174\n#, fuzzy\n#| msgid \"Unable to create character.\"\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2718\n#, fuzzy\nmsgid \"The game ended\"\nmsgstr \"Multiplayer-spil\"\n\n#: Source/msg.cpp:2724\n#, fuzzy\n#| msgid \"Unable to create character.\"\nmsgid \"Unable to get level data\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\n#, fuzzy\n#| msgid \"Magic:\"\nmsgid \"Magical\"\nmsgstr \"Magi:\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\n#, fuzzy\n#| msgid \"The Ring of One Thousand\"\nmsgid \"The Binding of the Three\"\nmsgstr \"Ringen af et tusinde\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4799\n#, fuzzy\n#| msgid \"Level:\"\nmsgid \"Lever\"\nmsgstr \"Niveau:\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, fuzzy, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4899\n#, fuzzy\n#| msgid \"Select Hero\"\nmsgid \"Slain Hero\"\nmsgstr \"Ny multiplayer-helt\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, fuzzy, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, fuzzy, c++-format\n#| msgid \"Music Disabled\"\nmsgid \"{:s} (disabled)\"\nmsgstr \"Musik deaktiveret\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\n#, fuzzy\n#| msgid \"Game Design\"\nmsgid \"Game Mode\"\nmsgstr \"Spildesign\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Game Design\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Spildesign\"\n\n#: Source/options.cpp:423\n#, fuzzy\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Gem filen findes\"\n\n#: Source/options.cpp:429\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgid \"Restrict to Shareware\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:487\n#, fuzzy\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Indstillinger\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"\"\n\n#: Source/options.cpp:691\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgid \"Fit to Screen\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Lyn\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\n#: Source/options.cpp:790\n#, fuzzy\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Pause\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\n#, fuzzy\nmsgid \"Test Bard\"\nmsgstr \"QA-artilleristøtte (ekstra testere) \"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:797\n#, fuzzy\nmsgid \"Show Party Information\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\nmsgid \"Off\"\nmsgstr \"Loopback\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:889\n#, fuzzy\n#| msgid \"Artwork\"\nmsgid \"Network\"\nmsgstr \"Kunst\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:139\n#, fuzzy\nmsgid \"Next level\"\nmsgstr \"Niveau:\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:149\n#, fuzzy\n#| msgid \"No\"\nmsgid \"Now\"\nmsgstr \"Nej\"\n\n#: Source/panels/charpanel.cpp:150\n#, fuzzy\n#| msgid \"Strength:\"\nmsgid \"Strength\"\nmsgstr \"Styrke:\"\n\n#: Source/panels/charpanel.cpp:154\n#, fuzzy\n#| msgid \"Magic:\"\nmsgid \"Magic\"\nmsgstr \"Magi:\"\n\n#: Source/panels/charpanel.cpp:158\n#, fuzzy\n#| msgid \"Dexterity:\"\nmsgid \"Dexterity\"\nmsgstr \"Smidighed:\"\n\n#: Source/panels/charpanel.cpp:161\n#, fuzzy\n#| msgid \"Vitality:\"\nmsgid \"Vitality\"\nmsgstr \"Vitalitet:\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:174\n#, fuzzy\nmsgid \"Armor class\"\nmsgstr \"Vælg klasse\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:193\n#, fuzzy\nmsgid \"Resist magic\"\nmsgstr \"Magi:\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:94\n#, fuzzy\nmsgid \"menu\"\nmsgstr \"Forrige menu\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\n#, fuzzy\n#| msgid \"Voices\"\nmsgid \"voice\"\nmsgstr \"Stemmeproduktion, retning og casting\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, fuzzy, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, fuzzy, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"\"\n\n#: Source/panels/spell_book.cpp:176\n#, fuzzy, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Understøttede spillere: {:d}\"\nmsgstr[1] \"Understøttede spillere: {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, fuzzy, c++-format\n#| msgid \"Level:\"\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Niveau:\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, fuzzy, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\n#, fuzzy\nmsgid \"Spell\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/panels/spell_list.cpp:162\n#, fuzzy\nmsgid \"Damages undead only\"\nmsgstr \"Skrivebeskyttet mappe fejl\"\n\n#: Source/panels/spell_list.cpp:173\n#, fuzzy\nmsgid \"Scroll\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"\"\n\n#: Source/panels/spell_list.cpp:194\n#, fuzzy, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/pfile.cpp:762\n#, fuzzy\n#| msgid \"Unable to create character.\"\nmsgid \"Unable to open archive\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/pfile.cpp:764\n#, fuzzy\n#| msgid \"Unable to create character.\"\nmsgid \"Unable to load character\"\nmsgstr \"Kunne ikke oprette karakter.\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, fuzzy, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fejlen opstod ved: {:s} linje {:d}\"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"\"\n\n#: Source/qol/itemlabels.cpp:113\n#, fuzzy, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"Understøttede spillere: {:s}\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:146\n#, fuzzy\nmsgid \"Maximum Level\"\nmsgstr \"Niveau:\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, fuzzy, c++-format\n#| msgid \"Talk to Pepin\"\nmsgid \"To {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:12\n#, fuzzy\nmsgid \"Here's something for you.\"\nmsgstr \"Har du lyst til:\"\n\n#: Source/quick_messages.cpp:13\n#, fuzzy\nmsgid \"Now you DIE!\"\nmsgstr \"Har du lyst til:\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Tak til\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Griswold\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"\"\n\n#: Source/stores.cpp:136\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Farnham\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Gillian\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \"\"\n\n#: Source/stores.cpp:311\n#, fuzzy, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/stores.cpp:313\n#, fuzzy, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/stores.cpp:317\n#, fuzzy\nmsgid \"Indestructible\"\nmsgstr \"Understøttede spillere: {:d}\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Velkommen til\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Har du lyst til:\"\n\n#: Source/stores.cpp:390\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to Griswold\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:391\n#, fuzzy\n#| msgid \"Buy items\"\nmsgid \"Buy basic items\"\nmsgstr \"Køb varer\"\n\n#: Source/stores.cpp:392\n#, fuzzy\n#| msgid \"Buy items\"\nmsgid \"Buy premium items\"\nmsgstr \"Køb varer\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\n#, fuzzy\n#| msgid \"Buy items\"\nmsgid \"Sell items\"\nmsgstr \"Køb varer\"\n\n#: Source/stores.cpp:394\n#, fuzzy\nmsgid \"Repair items\"\nmsgstr \"Køb varer\"\n\n#: Source/stores.cpp:395\n#, fuzzy\n#| msgid \"Leave Healer's home\"\nmsgid \"Leave the shop\"\nmsgstr \"Forlad healers hjem\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"\"\n\n#: Source/stores.cpp:687\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to Adria\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Køb varer\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"\"\n\n#: Source/stores.cpp:691\n#, fuzzy\nmsgid \"Leave the shack\"\nmsgstr \"Forlad healers hjem\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:945\n#, fuzzy\n#| msgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Er du sikker på, at du vil slette karakteren \\\"{:s}\\\"?\"\n\n#: Source/stores.cpp:951\n#, fuzzy\n#| msgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Er du sikker på, at du vil slette karakteren \\\"{:s}\\\"?\"\n\n#: Source/stores.cpp:954\n#, fuzzy\n#| msgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Er du sikker på, at du vil slette karakteren \\\"{:s}\\\"?\"\n\n#: Source/stores.cpp:958\n#, fuzzy\n#| msgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Er du sikker på, at du vil slette karakteren \\\"{:s}\\\"?\"\n\n#: Source/stores.cpp:961\n#, fuzzy\n#| msgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Er du sikker på, at du vil slette karakteren \\\"{:s}\\\"?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to Wirt\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"\"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1013\n#, fuzzy\nmsgid \"Leave\"\nmsgstr \"Forlad healers hjem\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Healers hjem\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Forlad healers hjem\"\n\n#: Source/stores.cpp:1079\n#, fuzzy\nmsgid \"The Town Elder\"\nmsgstr \"Genstart i byen\"\n\n#: Source/stores.cpp:1081\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to Cain\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1213\n#, fuzzy, c++-format\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to {:s}\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:1216\n#, fuzzy, c++-format\n#| msgid \"Talk to Pepin\"\nmsgid \"Talking to {:s}\"\nmsgstr \"\"\n\"Kan ikke skrive til lokation:\\n\"\n\"{:s}\"\n\n#: Source/stores.cpp:1217\n#, fuzzy\nmsgid \"is not available\"\nmsgstr \"\"\n\"Skytten og Troldmanden er kun tilgængelige i den fulde detailversion af \"\n\"Diablo. Besøg https://www.gog.com/game/diablo for at købe den.\"\n\n#: Source/stores.cpp:1218\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgid \"in the shareware\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/stores.cpp:1219\n#, fuzzy\nmsgid \"version\"\nmsgstr \"\"\n\"Skytten og Troldmanden er kun tilgængelige i den fulde detailversion af \"\n\"Diablo. Besøg https://www.gog.com/game/diablo for at købe den.\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1257\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to Ogden\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:1258\n#, fuzzy\nmsgid \"Leave the tavern\"\nmsgstr \"Forlad healers hjem\"\n\n#: Source/stores.cpp:1269\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to Gillian\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1282\n#, fuzzy\n#| msgid \"Talk to Pepin\"\nmsgid \"Talk to Farnham\"\nmsgstr \"Tal med Pepin\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"\"\n\n#: Source/towners.cpp:781\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgid \"Cain the Elder\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Kriger\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Skytte\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Troldmand\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:21\n#, fuzzy\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:24\n#, fuzzy\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:28\n#, fuzzy\n#| msgid \"Error\"\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Fejl\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:47\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Mareridt\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:61\n#, fuzzy\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:68\n#, fuzzy\n#| msgid \"Buy items\"\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Helvede\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:81\n#, fuzzy\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Helvede\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:91\n#, fuzzy\n#| msgid \"Single Player\"\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Singleplayer\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:104\n#, fuzzy\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:109\n#, fuzzy\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Helvede\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:111\n#, fuzzy\n#| msgid \"Dunsel\"\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Drønnert\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:130\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:163\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Mareridt\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:183\n#, fuzzy\n#| msgid \"Single Player\"\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Singleplayer\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:225\n#, fuzzy\n#| msgid \"Magic:\"\nmsgid \"Magic Rock\"\nmsgstr \"Magi:\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:227\n#, fuzzy\nmsgid \"Ring of Truth\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:243\n#, fuzzy\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Genstart i byen\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:248\n#, fuzzy\n#| msgid \"Single Player\"\nmsgid \"Bovine Plate\"\nmsgstr \"Singleplayer\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:279\n#, fuzzy\nmsgid \"Ring Mail\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:301\n#, fuzzy\nmsgid \"Elixir of Strength\"\nmsgstr \"Styrke:\"\n\n#: Source/translation_dummy.cpp:302\n#, fuzzy\nmsgid \"Elixir of Magic\"\nmsgstr \"Magi:\"\n\n#: Source/translation_dummy.cpp:303\n#, fuzzy\n#| msgid \"Dexterity:\"\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Smidighed:\"\n\n#: Source/translation_dummy.cpp:304\n#, fuzzy\nmsgid \"Elixir of Vitality\"\nmsgstr \"Vitalitet:\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:338\n#, fuzzy\n#| msgid \"Create Game\"\nmsgid \"Great Axe\"\nmsgstr \"Opret spil\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:359\n#, fuzzy\nmsgid \"Ring\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgid \"Lightforge\"\nmsgstr \"Mareridt\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:391\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgid \"Lightsabre\"\nmsgstr \"Mareridt\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:430\n#, fuzzy\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"\\tIngen sjæle blev solgt i fremstillingen af dette spil.\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:437\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgid \"Nightscape\"\nmsgstr \"Mareridt\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:447\n#, fuzzy\nmsgid \"Ring of Regha\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:449\n#, fuzzy\nmsgid \"Constricting Ring\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:450\n#, fuzzy\nmsgid \"Ring of Engagement\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:478\n#, fuzzy\n#| msgid \"Warrior\"\nmsgid \"Warrior's\"\nmsgstr \"Kriger\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:531\n#, fuzzy\n#| msgid \"Vitality:\"\nmsgid \"quality\"\nmsgstr \"Vitalitet:\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:542\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"deflection\"\nmsgstr \"Vælg handling\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:546\n#, fuzzy\n#| msgid \"Strength:\"\nmsgid \"strength\"\nmsgstr \"Styrke:\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:553\n#, fuzzy\n#| msgid \"Dexterity:\"\nmsgid \"dexterity\"\nmsgstr \"Smidighed:\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:557\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"perfection\"\nmsgstr \"Vælg handling\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:560\n#, fuzzy\n#| msgid \"Magic:\"\nmsgid \"magic\"\nmsgstr \"Magi:\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:563\n#, fuzzy\n#| msgid \"Sorcerer\"\nmsgid \"sorcery\"\nmsgstr \"Troldmand\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:567\n#, fuzzy\n#| msgid \"Vitality:\"\nmsgid \"vitality\"\nmsgstr \"Vitalitet:\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:583\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgid \"the eagle\"\nmsgstr \"Healeren Pepin\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:616\n#, fuzzy\n#| msgid \"Manufacturing\"\nmsgid \"puncturing\"\nmsgstr \"Produktion\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:622\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"balance\"\nmsgstr \"Annuller\"\n\n#: Source/translation_dummy.cpp:623\n#, fuzzy\n#| msgid \"Vitality:\"\nmsgid \"stability\"\nmsgstr \"Vitalitet:\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:626\n#, fuzzy\nmsgid \"The Magic Rock\"\nmsgstr \"Magi:\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:654\n#, fuzzy\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Genstart i byen\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:681\n#, fuzzy\n#| msgid \"Healer's home\"\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Healers hjem\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:725\n#, fuzzy\nmsgid \"You drink water?\"\nmsgstr \"Har du lyst til:\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:979\n#, fuzzy\n#| msgid \"Hell\"\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Helvede\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:990\n#, fuzzy\n#| msgid \"Hell\"\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Helvede\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:997\n#, fuzzy\n#| msgid \"Hell\"\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Helvede\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1004\n#, fuzzy\nmsgid \"Mercurial Ring\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1005\n#, fuzzy\nmsgid \"Xorine's Ring\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1006\n#, fuzzy\nmsgid \"Karik's Ring\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1007\n#, fuzzy\nmsgid \"Ring of Magma\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1008\n#, fuzzy\nmsgid \"Ring of the Mystics\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1009\n#, fuzzy\n#| msgid \"The Ring of One Thousand\"\nmsgid \"Ring of Thunder\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1022\n#, fuzzy\nmsgid \"Gladiator's Ring\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1037\n#, fuzzy\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Ringen af et tusinde\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \"\"\n\n#, fuzzy\n#~| msgid \"Options\"\n#~ msgid \"Options:\"\n#~ msgstr \"Indstillinger\"\n\n#, fuzzy\n#~ msgid \"version {:s}\"\n#~ msgstr \"\"\n#~ \"Kan ikke skrive til lokation:\\n\"\n#~ \"{:s}\"\n\n#, fuzzy\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Magi:\"\n\n#, fuzzy\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Genstart i byen\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Genstart i byen\"\n\n#, fuzzy\n#~ msgid \"decrease strength\"\n#~ msgstr \"Styrke:\"\n\n#, fuzzy\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"Smidighed:\"\n\n#, fuzzy\n#~ msgid \"decrease vitality\"\n#~ msgstr \"Vitalitet:\"\n\n#, fuzzy\n#~ msgid \"you can't heal\"\n#~ msgstr \"Har du lyst til:\"\n\n#, fuzzy\n#~| msgid \"Unable to create character.\"\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Kunne ikke oprette karakter.\"\n\n#, fuzzy\n#~| msgid \"\"\n#~| \"Unable to write to location:\\n\"\n#~| \"{:s}\"\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"\"\n#~ \"Kan ikke skrive til lokation:\\n\"\n#~ \"{:s}\"\n"
  },
  {
    "path": "Translations/de.po",
    "content": "# Translation of DevilutionX to German\n# Mathieu Maret <mathieu.maret@gmail.com>, 2021.\n# @ChaosMarc, 2021.\n# @sheng-luwei, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:19+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: de\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Spieldesigner\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Seniordesigner\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Zusätzliches Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Chefprogrammierer\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Seniorprogrammierer\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programmierung\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Besondere-Gäste-Programmierung\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net-Programmierung\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Programmierung der seriellen Kommunikation\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Installerprogrammierung\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Künstlerische Leitung\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Bildgestaltung\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Technische Bildgestaltung\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Filmkunstdirektor\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D-Filmgestaltung\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Technische Filmgestaltung\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Ausführender Produzent\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Produzent\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Assoziierter Produzent\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Musik\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Sound-Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Filmische Musik & Sound\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Stimmenproduktion, Regie und Casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Drehbuch und Geschichte\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Stimmenbearbeitung\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Stimmen\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Aufnahmetechniker\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Handbuchdesign und -layout\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Künstlerische Gestaltung des Handbuchs\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Kommissarischer Leiter QS (Cheftester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QS-Überfallkommando (Tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QS-Spezialeinheiten (Kompatibilitätstester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QS-Artillerieunterstützung (zusätzliche Tester) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QS-Spionageabwehr\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Sortierung der Netzwerkinformationsdienste\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Kundendienst\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Verkauf\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Mr. Dabiris Hintergrundsänger*innen\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Öffentlichkeitsarbeit\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Verkauf International\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"US-Verkäufe\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Produktion\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Recht- und Geschäftliches\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Besonderen Dank an\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Dank an\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"In Erinnerung an\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Ganz besonderen Dank an\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Generaldirektor\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Softwareentwicklung\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Kunstdirektor\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Künstler\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Sound-Design, SFX- & Audiotechnik\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Leiter der Qualitätssicherung\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Tester\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Handbuch\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tZusätzliche Arbeit\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Questtexter\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Dank an\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tVielen Dank an Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Qualitätssicherungsdirektor\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Qualitätssicherungscheftester\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Haupttester\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Zusätzliche Tester\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Marketingdirektor\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Direktor für Öffentlichkeitsarbeit\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Projektleiter\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Der Ring der Eintausend\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tKeine Seelen wurden während der Entstehung dieses Spiels verkauft.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Klasse wählen\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Zurück\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Neuer Mehrspielerheld\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Neuer Einzelspielerheld\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Spielstand existiert\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Spiel laden\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Neues Spiel\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Einzelspielercharaktere\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Die Jägerin und der Magier sind nur in der Vollversion von Diablo enthalten. \"\n\"Besuche https://www.gog.com/game/diablo um das Spiel zu erwerben.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Namen eingeben\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Ungültiger Name. Ein Name darf keine Leerzeichen, reservierte Zeichen oder \"\n\"reservierte Wörter enthalten.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Charaktererstellung fehlgeschlagen.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Level:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Stärke:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magie:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Agilität:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalität:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Spielstand:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Charakterwahl\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Neuer Held\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Löschen\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Mehrspielercharaktere\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Mehrspielercharakter löschen\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Einzelspielercharakter löschen\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Bist Du sicher, dass Du den Charakter \\\"{:s}\\\" löschen willst?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Einzelspieler\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Mehrspieler\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Einstellungen\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Hilfe\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Mitwirkende\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Hellfire verlassen\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Diablo verlassen\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Client-Server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Offline\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Mehrspieler-Spiel\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Beschreibung:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"\"\n\"Kein Gateway\\n\"\n\"erforderlich\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Verbindungsart\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Gateway wechseln\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Verbindung über ein TCP-kompatibles Netzwerk.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Alle Computer müssen mit dem Internet verbunden sein.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Ermöglicht das netzwerklose Solospiel.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Unterstützte Spieler: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Der Host betreibt ein anderes Spiel als Du.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Der Spielersteller verwendet einen anderen Spielmodus ({:s}) als du.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"\"\n\"Deine Version {:s} stimmt nicht mit der des Hosts {:d}.{:d}.{:d} überein.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Beschreibung:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Aktion wählen\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Spiel erstellen\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Offenes Spiel erstellen\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Spiel beitreten\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Öffentliche Spiele\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Lade...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Keine\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ABBRECHEN\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"\"\n\"Erstelle ein neues Spiel mit Passwort und dem von Dir gewählten \"\n\"Schwierigkeitsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Erstelle ein neues offenes Spiel mit freiem Beitritt und dem von Dir \"\n\"gewählten Schwierigkeitsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Einem laufenden Spiel via Spiel-ID beitreten.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Einem laufenden Spiel via IP-Adresse oder Hostnamen beitreten.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Einem laufenden öffentlichen Spiel beitreten.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Alptraum\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Hölle\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Schwierigkeitsgrad: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Geschwindigkeit: Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Geschwindigkeit: Schnell\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Geschwindigkeit: Schneller\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Geschwindigkeit: Am schnellsten\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Spieler: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Schwierigkeitsgrad\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Trete {:s}-Spiel bei\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Spiel-ID eingeben\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Adresse eingeben\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normal\\n\"\n\"Hier sollte ein neuer Charakter seine Abenteuer in der Welt von Diablo \"\n\"beginnen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Alptraum\\n\"\n\"Die Bewohner des Labyrinths sind stärker und erweisen sich als größere \"\n\"Herausforderung. Nur für erfahrene Charaktere geeignet.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Hölle\\n\"\n\"Hier warten die stärksten Dämonen an den Toren der Hölle auf Dich. Nur die \"\n\"stärksten Charaktere sind dieser Herausforderung gewachsen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Dein Charakter muss mindestens Level 20 erreicht haben bevor er einem \"\n\"Mehrspieler-Spiel der Stufe \\\"Alptraum\\\" beitreten kann.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Dein Charakter muss mindestens Level 30 erreicht haben bevor er einem \"\n\"Mehrspieler-Spiel der Stufe \\\"Hölle\\\" beitreten kann.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Spielgeschwindigkeit\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Schnell\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Schneller\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Am Schnellsten\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normale Geschwindigkeit\\n\"\n\"Hier sollte ein neuer Charakter seine Abenteuer in der Welt von Diablo \"\n\"beginnen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Schnelle Geschwindigkeit\\n\"\n\"Die Bewohner des Labyrinths sind schneller und erweisen sich als größere \"\n\"Herausforderung. Nur für erfahrene Charaktere geeignet.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Schnellere Geschwindigkeit\\n\"\n\"Die meisten Monster der Unterwelt werden Dich schneller aufspüren als je \"\n\"zuvor. Nur ein erfahrener Meister sollte sein Glück hier versuchen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Schnelle Geschwindigkeit\\n\"\n\"Die Gegner der Unterwelt werden unerbittlich schnell angreifen. Nur ein \"\n\"wahrer Geschwindigkeitsfanatiker sollte diese Gangart wählen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Passwort eingeben\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Hellfire spielen\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Zu Diablo wechseln\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Ja\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Nein\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Drücke eine beliebige Taste um diese zu ändern.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Festgelegte Taste:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Eine beliebige Taste drücken um sie festzulegen.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Festgelegte Taste freigeben\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Gebundene Knopfkombination:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Entbinde Knopfkombination\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Vorheriges Menü\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Wir unterhalten einen Chatserver unter Discord.gg/devilutionx rund um Diablo \"\n\"und das Hellfire-Addon. Du bist herzlich eingeladen, unserer Community \"\n\"beizutreten.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX ist ein Projekt von Diasurgical. Probleme und Fehler bitte hier \"\n\"melden: https://github.com/diasurgical/devilutionX. Damit wir Dir helfen \"\n\"können, teile uns bitte Deine Versionsnummer, Dein Betriebssystem und die \"\n\"Art Deines Problems mit.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Haftungsausschluss:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX wird weder von GOG.com noch von Blizzard Entertainment \"\n\"unterstützt oder betrieben oder zwecks Gewährleistung auf Qualität oder \"\n\"Kompatibilität getestet. Alle Anfragen bezüglich DevilutionX sollten direkt \"\n\"an Diasurgical gerichtet werden, nicht an Blizzard Entertainment oder an \"\n\"GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tDieser Port verwendet Charis SIL, New Athena Unicode, Unifont und Noto, \"\n\"lizenziert unter der SIL Open Font License, sowie Twitmoji, lizenziert unter \"\n\"CC-BY 4.0. Der Port verwendet außerdem SDL, lizenziert unter der zlib-\"\n\"Lizenz. Mehr Details in der ReadMe.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Urheberrecht © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Fehler\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Fehler an Position {:s} Zeile {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Dateifehler\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Das Hauptdatenarchiv ({:s}) kann nicht geöffnet werden.\\n\"\n\"\\n\"\n\"Stelle sicher, dass es sich im Spielordner befindet.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Nur-Lesen-Verzeichnisfehler\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"An folgenden Speicherort kann nicht geschrieben werden:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Spiel: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Offlinespiel\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Passwort: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Offenes Spiel\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Level: Stock {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Level: Krypta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Heimeliger\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Level {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Charakterinformation\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Questtagebuch\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Automatische Karte\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Hauptmenü\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventar\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Zauberbuch\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Nachricht senden\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Verfügbare Befehle:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Befehl \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" ist unbekannt.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Beschreibung: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parameter: Kein zusätzlicher Parameter erforderlich.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parameters: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Arenen nur in Multiplayer unterstützt.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Welche Arena willst du besuchen?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Untültige Arenen-Nummer. Gültige Nummern sind:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\"Zum Betreten einer Arena, brauchst musst du in der Stadt oder in einer \"\n\"anderen Arena sein.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Die Inspektion wird nur im Mehrspielermodus unterstützt.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Stoppen den Spieler zu inspizieren.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Keine Spieler mit so einem Namen gefunden\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Inspiziere Spieler: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Gebe Hilfeübersicht oder Hilfe für einen bestimmten Befehl.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[befehl]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Betrete die PvP Arena.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<arena-number>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Gebe Arena Tränke.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<number>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Überprüfe Statistiken und Ausrüstung eines anderen Spielers.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<Spielername>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Zeige Samen Informationen für das aktuelle Level.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Spieler ist freundlich\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Spieler greift an\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Schnelltaste: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Zauberauswahlknopf\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Schnelltaste: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s}-Fertigkeit\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s}-Zauber\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Zauberlevel 0 - Unbenutzbar\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Zauberlevel {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Schriftrolle der {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d}-Schriftrolle\"\nmsgstr[1] \"{:d}-Schriftrollen\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Stab mit {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d}-Ladung\"\nmsgstr[1] \"{:d}-Ladungen\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} Goldstück\"\nmsgstr[1] \"{:s} Goldstücke\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Anforderungen nicht erfüllt\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Level: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Trefferpunkte {:d} von {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Rechtsklick zum Benutzen\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Level-Up\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Du hast {:s} Goldstück. Wieviele möchtest Du abheben?\"\nmsgstr[1] \"Du hast {:s} Goldstücke. Wieviele möchtest Du abheben?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Stadtportal\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"von {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Zum unheiligen Altar\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"Zu Level 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Fehler beim Laden des Charakters\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Diese Nachricht ausgeben und beenden\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Version ausgeben und beenden\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Speicherort der diabdat.mpq definieren\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Speicherort der Spielstandsdateien definieren\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Speicherort der diablo.ini definieren\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Bestimme den Sprachencode (e.g. de or de-deu)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Introvideos überspringen\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Bilder pro Sekunde anzeigen\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"\\\"Verbose logging\\\" aktivieren\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Demo-Datei aufnehmen\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Demo-Datei abspielen\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Alle Frame-Begrenzungen bei Demo-Wiedergabe ausschalten\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Spielauswahl:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Shareware erzwingen\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Diablo erzwingen\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Hellfire erzwingen\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Hellfire-Optionen:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Bugs melden unter https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\"Bitte aktualisiere devilutionx.mpq und fonts.mpq auf die neuste Version\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Fehler beim Laden des Interfaces.\\n\"\n\"\\n\"\n\"devilutionx.mpq muss im Spielordner vorhanden und auf dem neuesten Stand \"\n\"sein.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Bitte aktualisiere fonts.mpq auf die neueste Version\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Netzwerkunterbrechung --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Warten auf Spieler --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Hilfe nicht verfügbar\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"während des Dialogs\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Gürtelgegenstand {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Gürtelgegenstand verwenden.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Schnellzauber {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Schnelltaste für Fertigkeiten oder Zauber.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Vorheriges Menü\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Schnellzauber {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Nutze den Heiltrank\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Nutze den Heiltrank vom Gürtel.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Benutze den Mana Trank\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Benutze die Mana Tränke vom Gürtel.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Schnellzauberleiste\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Schnellzauberleiste öffnen.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Schnellspeichern\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Speichert das Spiel.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Schnellladen\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Lädt das Spiel.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Spiel beenden\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Beendet das Spiel.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Held anhalten\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Hält den Helden an und unterbricht anstehende Aktionen.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Gegenstand-Hervorhebung\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Zeigt/Versteckt Gegenstände auf dem Boden.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Dauerhafte Gegenstand-Hervorhebung\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Zeigt/Versteckt Gegenstände auf dem Boden dauerhaft.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Karte an/ausschalten\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Aktiviert / Deaktiviert die Karte.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Öffnet das Inventar.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Charakterübersicht\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Öffnet die Charakterübersicht.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Questtagebuch\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Öffnet das Questtagebuch.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Zauberbuch\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Öffnet das Zauberbuch.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Schnellnachricht {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Schnellnachricht im Chat verwenden.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Infoanzeigen verstecken\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Versteckt alle Infoanzeigen.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Zoom\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Zoom näher an das Spiel heran.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Pause\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Pausiert das Spiel.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pause\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Erhöht die Bildschirmhelligkeit.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Verringert die Bildschirmhelligkeit.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Erhöht die Bildschirmhelligkeit.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Erhöht die Bildschirmhelligkeit.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Hilfe\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Öffnet das Hilfemenü.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Bildschirmfoto\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Erzeugt ein Bildschirmfoto.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Spielinfo\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Zeigt Spielinformationen an.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Chatverlauf\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Zeigt den Chatverlauf an.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Inventar\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Primitive Attacke\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Attackiere Monster, Rede mit den Stadtbewohnern, Inventargegenstände anheben \"\n\"und platzieren.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Zweite Aktion\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Öffene Kisten, interagiere mit den Türen, Sammle Items ein.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Aktion auswählen\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Wirke den aktiven Zauber.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Aktion abbrechen\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Schließe Menüs.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Bewege hoch\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Bewege den Charakter des Spieler nach oben.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Bewege runter\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Bewege den Charakter des Spieler nach unten.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Gehe nach links\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Bewege den Charakter des Spieler nach links.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Gehe nach rehcts\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Bewege den Charakter des Spieler nach rechts.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"auf dem Boden stehen.\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Halte gedrückt um dem Spieler vorm bewegen zu hindern.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Standfläche umschalten\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Schalte um wenn der Spieler sich bewegt.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Automatische Karte\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Bewege runter\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Gehe nach links\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Bewege den Charakter des Spieler nach oben.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Gehe nach rehcts\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Ziehe Maus nach oben\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Simuliere die Aufwärtsbewegung der Maus.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Ziehe die Maus nach unten\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Simuliere die Rückwärtsbewegung der Maus.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Ziehe die Maus nach links\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Simuliere die Bewegung der Maus nach links.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Ziehe Maus nach rechts\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Simuliere die Bewegung der Maus nach rechts.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Linksklick\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Simuliere den linken Maus-Button.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Rechtsklick\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Simuliere den rechten Maus-Button.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Gamepad-Hotspell-Menü\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Halte gedrückt um den Zauber-Hotkey fest zulegen oder zu nutzen.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Gamepad Menunavigator\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Halte zum betreten des Gamepad Navigationsmenü.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Schalte Spielmenü\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Öffnet das Spielmenü.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"Flammenwelle\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Keine Mehrspielerfunktionalität in der Demoversion\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Direct-Sound-Initialisierung fehlgeschlagen\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"In der Shareware-Version nicht verfügbar\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Nicht genug Platz zum Speichern\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Keine Pause in der Stadt\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Das Kopieren auf eine Festplatte wird empfohlen\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Mehrspielersynchronisationsproblem\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Keine Pause im Mehrspielermodus\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Speichere...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Manche werden schwächer, wenn einer erstarkt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Neue Kraft, geschmiedet durch Zerstörung\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Wer verteidigt, kann nicht zugleich angreifen\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Das Schwert der Gerechtigkeit ist flink und scharf\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Ist der Geist wachsam, gedeiht der Körper\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Die Kraft des Manas erneuert auf frischer Bahn\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Der Macht des Stahls kann die Zeit nichts anhaben\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Magie ist nicht immer das was sie zu sein scheint\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Was einst geöffnet, ist nun verschlossen\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Sättigung auf Kosten der Weisheit\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Arkane Kraft bringt Zerstörung\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Was nicht gebunden werden kann, bleibt unverdorben\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Purpur und Azur werden wie die Sonne\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Wissen und Weisheit auf Kosten Eurer selbst\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Trinkt und erfrischt Euch\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Viele Wege führen zum Ziel\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Energie auf Kosten der Weisheit\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Manchmal liegt das Gold auf der Straße\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Wo die Habgier scheitert, wird Geduld belohnt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Gesegnet von einem wohlwollenden Gefährten!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Möge das Schicksal die Hände der Menschen lenken\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Himmlischer Glaube spendet Stärke\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Die Essenz des Lebens fließt in Euch\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Von oben betrachtet wird der Weg klar\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Erlösung auf Kosten der Weisheit\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Geheimnisse im Licht der Vernunft gelüftet\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Die Letzten werden die Ersten sein\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Großzügigkeit ist ihr eigener Lohn\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Dafür müsst Ihr mindestens Level 8 sein.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Dafür müsst Ihr mindestens Level 13 sein.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Dafür müsst Ihr mindestens Level 17 sein.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Arkanes Wissen gewonnen!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Was Euch nicht umbringt...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Wissen ist Macht.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Gebt und Ihr werdet empfangen.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Manche Erfahrung wird durch Berührung gewonnen.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Es gibt keinen Ort wie Zuhause.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Spirituelle Energie wird wiederhergestellt.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Ihr fühlt Euch agiler.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Ihr fühlt Euch stärker.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Ihr fühlt Euch klüger.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Ihr fühlt Euch erfrischt.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Was den Willen brechen kann.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Kathedrale\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Katakomben\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Höhlen\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Nest\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Krypta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Lv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"Schwierigkeitsgrad: {}\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Im Hauptmenü\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"Loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Keine Verbindung möglich\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"Fehler: 0 Byte vom Server lesen\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq oder spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Einige Hellfire-MPQs fehlen\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Nicht alle Hellfire-MPQs vorhanden.\\n\"\n\"Bitte besorge alle hf*.mpq-Dateien.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Auflösung\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Rennen in der Stadt\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Theodor-Quest\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Kuh-Quest\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Gold autom. aufheben\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Elixire autom. aufheben\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Autom. Öl aufheben\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Autom. Aufheben in der Stadt\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria füllt Mana auf\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Waffen autom. anlegen\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Rüstungen autom. anlegen\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Helme autom. anlegen\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Schilde autom. anlegen\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Schmuck autom. anlegen\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Zufallsquests\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Zeig Gegenstandbeschriftung\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Gürtel autom. nachfüllen\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Spielzerstörende Schreine deaktivieren\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Heiltränke autom. aufheben\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Große Heiltränke autom. aufheben\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Manatränke autom. aufheben\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Große Manatränke autom. aufheben\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Genesungstränke autom. aufheben\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Große Genesungstränke autom. aufheben\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Optionen\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Spiel speichern\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Hauptmenü\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Spiel beenden\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Geschw.\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Musik Aus\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Ton\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Ton Aus\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pause\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Tastaturkürzel:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Hilfemenü\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Hauptmenü\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Automatische Karte\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Alle Fenster ausblenden\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Schnellzauberleiste\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B:  Zauberbuch\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Inventar\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Charakterübersicht\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Aufträge ansehen\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Helligkeit verringern\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Helligkeit erhöhen\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Zoom\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Autom.-Karte-Zoom\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Gürtelplätze\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Schnelltaste für Zauber festlegen\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Linke Maustaste: Angreifen im Stand\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Linke Maustaste (in der Charakterübersicht): Alle Statuspunkte \"\n\"vergeben\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Linke Maustaste (im Inventar): Ggst. bewegen oder ausrüsten bzw. \"\n\"ablegen\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Linke Maustaste (im Gürtel): Ggst. ins Inventar bewegen\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Bewegung:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Wenn Du den Mauszeiger festhältst, bewegt sich der Charakter kontinuierlich \"\n\"in diese Richtung.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Kampf:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"Mit Shift + Linksklick greift der Charakter an, ohne sich zu bewegen.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Autom. Karte:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Rufe die automatische Karte über den \\\"Karte\\\"-Knopf oder die TAB-Taste auf. \"\n\"Zoomen kann man innerhalb der autom. Karte mit den Tasten + und -. Mit den \"\n\"Pfeiltasten verschiebt man die Karte.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Objekte aufheben:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Kleine verwendbare Gegenstände wie Tränke oder Schriftrollen werden \"\n\"automatisch im Gürtel platziert und mit einer kleinen Nummer versehen. Diese \"\n\"Gegenstände können durch Drücken der entsprechenden Nummerntaste oder \"\n\"Rechtsklick mit der Maus benutzt werden.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Gold:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Mit Rechtsklick auf einen Goldhaufen kannst Du eine bestimmte Menge Gold \"\n\"abheben.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Fertigkeiten & Zauber:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Rufe Deine Liste der Fertigkeiten und Zauber über den \\\"Zauber\\\"-Knopf oder \"\n\"die B-Taste auf. Erlernte und durch Stäbe verfügbare Zauber werden hier \"\n\"angezeigt. Linksklick zum Auswählen eines Zaubers. Rechtsklick in das \"\n\"Spielfeld zum Auslösen des Zaubers.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Verwendung der Schnellzauberleiste:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Rufe die Schnellzauberleiste mit einem Linksklick auf den Knopf mit dem \"\n\"ausgewählten Zauber oder über die S-Taste auf. Linksklick auf eine \"\n\"Fertigkeit oder einen Zauber zum Auswählen. Rechtsklick in das Spielfeld zum \"\n\"Auslösen des Zaubers.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + Linksklick auf den Knopf mit dem ausgewählten Zauber hebt die \"\n\"Auswahl auf.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Zauber-Schnelltasten festlegen:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Du kannst bis zu vier Schnelltasten für Zauber, Fertigkeiten oder \"\n\"Schriftrollen festlegen. Rufe dafür wie oben beschrieben die \"\n\"Schnellzauberleiste auf. Fahre dann mit der Maus über einen Zauber und weise \"\n\"ihm mit F5, F6, F7 oder F8 eine Schnelltaste zu.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Zauberbücher:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Je mehr Bücher eines bestimmten Zaubers Du liest, desto größer wird Dein \"\n\"Wissen und Deine Effektivität beim Anwenden des Zaubers.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Shareware-Hellfire-Hilfe\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Hellfire-Hilfe\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Shareware-Diablo-Hilfe\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Diablo-Hilfe\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Escape zum Beenden oder Pfeiltasten um zu scrollen.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Hauptfenster kann nicht erstellt werden\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Kein Platz für das Item\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Öl der Genauigkeit\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Öl der Meisterschaft\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Öl der Schärfung\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Öl des Todes\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Öl der Agilität\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Öl der Reparatur\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Öl der Stärke\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Öl der Beständigkeit\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Öl des Härtens\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Öl der Undurchlässigkeit\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} mit {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0}{1} mit {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0}{1} de{2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0}{1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} de{1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"Erhöhung de\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"r Trefferchance\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"Starke Erhöhung de\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"r Waffentrefferchance\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"s Schadenspotentials\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"Starke Erhöhung de\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"s Schadenspotentials - außer Bögen\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"Verringerte Anforderungen\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"für Rüstungen und Waffen\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"Stellt 20% der\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"Haltbarkeit wieder her\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"Erhöht die aktuelle und\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"maximale Haltbarkeit\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"Macht einen Gegenstand unzerstörbar\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"Erhöhung des Rüstungswerts\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"von Rüstungen und Schilden\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"Große Erhöhung des Rüstungswerts\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"von Rüstungen und Schilden\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"legt eine Feuerfalle\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"legt eine Blitzfalle\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"legt eine Versteinerungsfalle\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"Volle Lebensaufladung\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"Partielle Lebensaufladung\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"Partielle Manaaufladung\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"Volle Manaaufladung\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"Erhöht die Stärke\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"Erhöht die Magie\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"Erhöht die Agilität\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"Erhöht die Vitalität\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"Lebens- und Manaaufladung\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"Volles Leben und Mana\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(funktioniert nur in Arenen)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Rechtsklick zum Ansehen\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Rechtsklick zum Benutzen\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"Rechtsklick zum Lesen, dann Linksklick zum Zielen\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Rechtsklick zum Lesen\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Aktivieren zum Ansehen\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Zum Benutzen das Inventar öffnen\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Aktivieren zum Benutzen\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Aus dem Zauberbuch wählen, dann\\n\"\n\"Zaubern zum Lesen\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Linksklick zum Lesen\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} zum Ansehen\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} zum benutzen\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Aus dem Zauberbuch wählen,\\n\"\n\"dann {} lesen\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} zum Lesen\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Level {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Verdoppelt die Goldkapazität\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Benötigt:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Str\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Agil\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Buch mit {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Ohr von {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"Trefferchance: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% Schaden\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"Treff.: {:+d}%, {:+d}% Schaden\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% Rüstung\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"Rüstungswert: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Feuerresistenz: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Feuerresistenz: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Blitzresistenz: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Blitzresistenz: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Magieresistenz: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Magieresistenz: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Resistenz gegen alles: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Resistenz gegen alles: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"+ {:d} auf alle Zauberlevel\"\nmsgstr[1] \"+ {:d} auf alle Zauberlevel\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"- {:d} auf alle Zauberlevel\"\nmsgstr[1] \"- {:d} auf alle Zauberlevel\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"Zauberlevel unverändert (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Extraladungen\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} Ladung\"\nmsgstr[1] \"{:d} {:s} Ladungen\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Feuerschaden: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Feuerschaden: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Blitzschaden: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Blitzschaden: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} zu Stärke\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} zu Magie\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} zu Agilität\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} zu Vitalität\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} zu allen Attributen\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} Schaden von Feinden\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Leben: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"hohe Haltbarkeit\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"verringerte Haltbarkeit\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"Unzerstörbar\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% Lichtradius\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% Lichtradius\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"Mehrere Pfeile pro Schuss\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"Feuerpfeilschaden: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"Feuerpfeilschaden: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"Blitzpfeilschaden {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"Blitzpfeilschaden {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"Feuerballschaden: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"Feuerballschaden: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"Angreifer erleidet 1-3 Schaden\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"Träger verliert gesamtes Mana\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"Halber Fallenschaden\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"Zurückstoßung\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% Schaden gegen Dämonen\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Träger verliert alle Resistenzen\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"3% Manaabsaugung\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"5% Manaabsaugung\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"3% Lebensabsaugung\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"3% Lebensabsaugung\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"Durchschlägt gegnerische Rüstung\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"Flinker Angriff\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"schneller Angriff\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"schnellerer Angriff\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"schnellster Angriff\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Anderer Effekt (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"schnelle Erholung\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"schnellere Erholung\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"schnellste Erholung\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"schnelles Blocken\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"{:d} Schadenspunkt extra\"\nmsgstr[1] \"{:d} Schadenspunkte extra\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"Zufällige Pfeilgeschwindigkeit\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"Ungewöhnlicher Schaden\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"Veränderte Haltbarkeit\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"Einhändig\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"Kontinuierlicher LP-Verlust\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"Lebensabsaugung\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"Keine Mindeststärke\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"Blitzschaden: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"Blitzschaden: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"Geladene Blitze bei Treffer\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"5% Chance auf 3-fachen Gesamtschaden\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"{:+d}% Schaden, -5% pro Treffer\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x Gegnerschaden, 1x Selbstschaden\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Plötzlich 0 - 600% Schaden\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"Geringe Haltb., {:+d}% Schaden\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"Extra-Rüstung gegen Dämonen\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"Extra-Rüstung gegen Untote\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Mana wird zu Leben\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Leben wird zu Mana\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"Schaden: {:d}  Unzerstörbar\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"Schaden: {:d}  Haltb.: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"Schaden: {:d}-{:d}  Unzerstörbar\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"Schaden: {:d}-{:d}  Haltb.: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"Rüstung: {:d}  Unzerstörbar\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"Rüstung: {:d}  Haltb.: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Ladungen: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"Einzigartiger Gegenstand\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Nicht identifiziert\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Halle des Skelettkönigs\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Knochenkammer\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labyrinth\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Die vergiftete Wasserquelle\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Refugium des Erzbischof Lazarus\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Kirchen Arena\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Höllen Arena\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Kreis des Lebens Arena\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Hinunter ins Labyrinth\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Hinunter in die Katakomben\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Hinunter in die Höhlen\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Hinunter in die Hölle\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Hinunter in den Stock\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Hinunter in die Krypta\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Hinauf zu Level {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Hinauf zur Stadt\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Hinab zu Level {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Hinunter zu Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Hinauf zu Stocklevel {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Hinauf zu Kryptalevel {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Grundstein des Universums\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Hinunter zu Kryptalevel {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Zurück zu Level {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Kann Spielstand nicht laden\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Ungültiger Spielstand\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Spieler befindet sich auf einem Hellfire-Level\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Ungültiger Spielzustand\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Kann Hauptmenü nicht öffnen\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Tierisch\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Dämonisch\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Untot\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Typ: {:s}  Getötet: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Insgesamt getötet: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Trefferpunkte: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Kein magischen Resistenzen\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Resistenzen:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magie\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Feuer\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Blitz\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Immunitäten:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Typ: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Keine Resistenzen\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Keine Immunitäten\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Einige magische Resistenzen\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Einige magische Immunitäten\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Fehler beim öffnen des Archives beim schreiben.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"Ungültiger Zauber von {:s}\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"Illegaler Zauber von {:s}\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Spieler '{:s}' (Level {:d}) ist dem Spiel beigetreten\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Das Spiel ist zu Ende\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Leveldaten nicht verfügbar\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Spieler '{:s}' hat das Spiel verlassen\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Spieler '{:s}' hat Diablo getötet und das Spiel verlassen!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Spieler '{:s}' wurde wegen Timeout entfernt\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Spieler '{:s}' (Level {:d}) ist bereits im Spiel\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Mysteriöser\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Versteckter\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Glimmernder\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Verdrehter\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Magischer\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Steinerner\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Religiöser\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Verzauberter\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Thaumaturgischer\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Faszinierender\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Rätselhafter\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Unheimlicher\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Grausiger\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Göttlicher\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Heiliger\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Geheiligter\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Spiritueller\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Gespenstischer\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Verlassener\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Gruseliger\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Stiller\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Abgelegener\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Verzierter\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Glimmender\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Verdorbener\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Öliger\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Leuchtender\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Bescheidener\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Funkelnder\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Schimmernder\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Sonniger\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Murphys\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Der große Zwist\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Der Lohn des Sündenkriegs\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Die Legende der Horadrim\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Das finstere Exil\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Der Sündenkrieg\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Die Gefangennahme der Drei\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Die Reiche des Jenseits\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Die Sage von den Dreien\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Der schwarze König\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Tagebuch: Die Verhexung\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Tagebuch: Die Begegnung\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Tagebuch: Die Tirade\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Tagebuch: Es wird stärker\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Tagebuch: Na-Krul\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Tagebuch: Das Ende\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Ein Zauberbuch\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Gekreuzigtes Skelett\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Hebel\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Offene Tür\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Geschlossene Tür\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Blockierte Tür\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Alter Wälzer\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Buch der Niedertracht\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Schädel-Hebel\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Mystisches Buch\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Kleine Truhe\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Truhe\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Große Truhe\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarkophag\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Bücheregal\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Bücherschrank\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Fass\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Exuvie\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urne\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Schrein\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Skelettbuch\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Ledergebundenes Buch\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Blutbrunnen\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Enthauptete Leiche\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Buch der Blinden\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Buch des Blutes\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Reinigende Quelle\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Rüstung\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Waffenständer\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Ziegenschrein\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Kessel\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Trübes Becken\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Fontäne der Tränen\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Stahlbuch\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Blutsockel\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Pilzbeet\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Abscheulicher Ständer\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Getöteter Held\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"Gesicherte {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (deaktiviert)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"An\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"Aus\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Spielmodus\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Spieleinstellungen\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Diablo oder Hellfire spielen.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Auf Demoversion beschränken\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Macht das Spiel zur Demo kompatibel. Ermöglicht das Zusammenspiel mit \"\n\"Freunden, die das Spiel nicht besitzen.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Spielstart\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Spielstarteinstellungen\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Intro\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Angezeigte Intro-Videos.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Begrüßungsbildschirm\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Angezeigte Begrüßungsbildschirme.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo- und Titelbildschirm\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Titelbildschirm\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Diablo-Einstellungen\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Hellfire-Einstellungen\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Audio\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Audio Einstellungen\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Laufgeräusche\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Der Spieler verursacht Geräusche beim Laufen.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Autom.-Aufheben Geräusch\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\"Wenn Gegenstände automatisch aufgehoben werden, wird ein Geräusch abgespielt.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Gegenstand-Aufheben Geräusch\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Wenn Gegenstände aufgehoben werden, wird ein Geräusch abgespielt.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Abtastrate\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Ausgangsabtastrate (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanäle\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Legt die Anzahl der Ausgangskanäle fest.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Puffergröße\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Puffergröße (Anzahl der Frames pro Kanal).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Neuberechnungsqualität\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Qualität der Neuberechnung, von 0 (niedrig) bis 10 (hoch).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Verändert die interne Auflösung des Spiels und bestimmt den sichtbaren \"\n\"Bereich. Hinweis: Dieser kann bei gleicher Auflösung je nach Auswahl der \"\n\"Skalierungseinstellungen variieren.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Resampler\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Audio resampler\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Gerät\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Audio Gerät\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafik\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Grafikeinstellungen\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Vollbild\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Zeigt das Spiel im Fenster- oder Vollbildmodus an.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"An Bildschirmgröße anpassen\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Passt das Seitenverhältnis des Spielfensters automatisch an die aktuelle \"\n\"Bildschirmauflösung an.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Hochskalieren\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Aktiviert die Bildskalierung von Spiel- zur Desktopauflösung. Verhindert das \"\n\"Wechseln der Desktopauflösung und erlaubt es die Fenstergröße anzupassen.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Skalierungsqualität\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"Aktiviert optionale Filter für das Ausgabebild beim Hochskalieren.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Pixelwiederholung\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilinear\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotropisch\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Ganzzahlige Skalierung\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Skaliert das Bild mit einem ganzzahligen Pixelverhältnis.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Vertikale Synchronisation\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Zoomen an wenn aktiviert.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Blitz\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Indizierte Farben\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Verwendet indizierte Farben für Wasser-, Lava- und Säureanimationen.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternative Nest-Farbpalette\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"In Hellfire wird eine andere Farbpalette für das Nest verwendet.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Hardware-Cursor\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Einen Hardware-Cursor verwenden\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Hardware-Cursor für Gegenstände\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Verwendet einen Hardware-Cursor für Gegenstände.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Hardware-Cursor Maximalgröße\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Legt die maximale Breite / Höhe für den Hardware-Cursor fest. Bei größeren \"\n\"Werten wird ein Software-Cursor verwendet.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Zeige FPS an\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Zeigt die FPS in der oberen linken Ecke des Bildschirms an.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Spiel\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Spieleinstellungen\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Aktiviert joggen / schnelles Laufen in der Stadt für Diablo und Hellfire. \"\n\"Diese Option wurde in der Erweiterung eingeführt.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Eingabe fangen\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Hindert den Mauszeiger am Verlassen des Spielfensters.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Theodor Quest aktivieren.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Kuh-Quest aktivieren. Lester der Farmer wird ersetzt durch den kompletten \"\n\"Narr.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Freundliches Feuer\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Erlaubt Pfeil- und Zauberschaden zwischen Spielern in Multiplayer, selbst \"\n\"wenn die Spieler sich freundlich gesinnt sind.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Volle Quests im Mehrspielermodus\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Aktiviert die voll / ungeschnitte Einzelspieler Version von Quest.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Bardin aktivieren\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Zeigt den Charaktertyp Bardin in der Heldenauswahl an.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Barbar aktivieren\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Zeigt den Charaktertyp Barabar in der Heldenauswahl an.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Erfahrungsleiste\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\"Eine Erfahrungsleiste wird in die Benutzeroberfläche am unteren Rand des \"\n\"Bildschirms integriert.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Zeigt Gegenständegrafiken im Store\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\"Zeigt Gestandgrafik zu der linken Gegenstandbeschreibung im Store Menu.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Lebenspunkte anzeigen\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Zeigt die aktuellen / maximalen Lebenspunkte an der Lebenskugel an.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Manapunkte anzeigen\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Zeigt die aktuellen / maximalen Manapunkte an der Manakugel an.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Charakterinformation\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Monsterlebensbalken\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Ein Lebensbalken für Monster wird am oberen Bildschirmrand angezeigt.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Gold wird automatisch aufgehoben, wenn der Held in die Nähe kommt.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Elixire werden automatisch aufgehoben, wenn der Held in die Nähe kommt.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Öle werden automatisch aufgehoben, wenn der Spieler in die Nähe kommt.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Gegenstände in der Stadt werden automatisch aufgehoben.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria füllt das Mana auf, wenn man sie in ihrem Laden besucht.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Waffen werden automatisch angelegt, wenn sie aufgehoben oder gekauft werden.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Rüstungen werden automatisch angelegt, wenn sie aufgehoben oder gekauft \"\n\"werden.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Helme werden automatisch angelegt, wenn sie aufgehoben oder gekauft werden.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Schilde werden automatisch angelegt, wenn sie aufgehoben oder gekauft werden.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Schmuck wird automatisch angelegt, wenn er aufgehoben oder gekauft wird.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Wählt die Quests bei neuen Spielen zufällig aus.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Monstertyp anzeigen\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Beim Halten des Mauszeigers auf ein Monster wird dessen Typ in der \"\n\"Beschreibungsbox am unteren Bildschirmrand angezeigt.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Beschriftungen für Gegenstände auf dem Boden anzeigen, wenn aktiviert.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Füllt den Gürtel automatisch aus dem Inventar nach, wenn ein Gegenstand \"\n\"verbraucht wird.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Kessel, Faszinierende, Verzierte, Geheiligte und Ziegenschreine können nicht \"\n\"mehr angeklickt werden und werden als deaktiviert markiert.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Schnellzaubern\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Schnelltasten führen einen Zauber augenblicklich aus, statt ihn nur als \"\n\"ausgewählt zu markieren.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Anzahl der Heiltränke, die automatisch aufgehoben werden sollen.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"\"\n\"Anzahl der großen Heiltränke, die automatisch aufgehoben werden sollen.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Anzahl der Manatränke, die automatisch aufgehoben werden sollen.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"\"\n\"Anzahl der großen Manatränke, die automatisch aufgehoben werden sollen.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Anzahl der Genesungstränke, die automatisch aufgehoben werden sollen.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Anzahl der großen Genesungstränke, die automatisch aufgehoben werden sollen.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Aktivert schwebende Nummern\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\"Ermöglicht schwebende Zahlen für den Erhalt von XP, das Verursachen von \"\n\"Schaden usw.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Aus\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Zufallsquests\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Nur Vertikal\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Controller\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Controllereinstellungen\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Netzwerk\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Netzwerkeinstellungen\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chat\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Chat Einstellungen\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Sprache\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Legt die Spielsprache fest.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Spracheinstellungen\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Tastaturbelegung\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Tastaturbelegungseinstellungen\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Gamepadbelegung\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Gamepadbelegungseinstellungen\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Einstellungen\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Level\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Erfahrung\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Nächstes Level\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Basis\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Aktuell\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Stärke\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magie\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Agilität\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalität\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Punkte\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Gold\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Rüstung\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"r Trefferchance\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Schaden\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Leben\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Magie-Res.\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Feuer-Res.\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Blitz-Res.\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"Char\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"Aufträge\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"Karte\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"Menü\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"Inv\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"Zauber\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"Sprechen\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"Stumm\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Unbenutzbar\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Schaden: 1/3 Leben des Ziels\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Heilt: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Schaden: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Fähigkeit\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Stab ({:d} Ladung)\"\nmsgstr[1] \"Stab ({:d} Ladungen)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Level {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Zauber\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Nur Schaden an Untoten\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Schriftrolle\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Stab\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Zauber-Schnelltaste {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Fehler beim Öffnen des Archivs\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Fehler beim Laden des Charakters\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (lvl {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Chatverlauf (Nachrichten: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} Gold\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Wieviel Gold möchtest du abheben?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Level {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Erfahrung: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Maximales Level\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Nächstes Level: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} zu Level {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"König Leorics Grabstätte\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Die Knochenkammer\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Einem dunkler Durchgang\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Unheiliger Altar\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Zu {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Ich brauche Hilfe!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Folge mir.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Ich habe etwas für Dich.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Stirb!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Dank an\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Zurück\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Schaden: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Rüstung: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Haltb.: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"Unzerstörbar\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Willkommen im\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Laden des Schmieds\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Was möchtet Ihr:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Mit Griswold sprechen\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Gewöhnliches kaufen\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Besonderes kaufen\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Verkaufen\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Reparieren\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Schmiede verlassen\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Hier meine Angebote:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Hier meine besonderen Angebote:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Ihr habt nichts zu verkaufen.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Was wollt Ihr verkaufen?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Ihr habt nichts zu Reparieren.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Was soll repariert werden?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Hütte der Hexe\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Mit Adria sprechen\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Etwas kaufen\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Stäbe aufladen\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Hütte verlassen\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Ihr habt nichts aufzuladen.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Was soll ich aufladen?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Ihr habt nicht genug Gold\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Ihr habt nicht genug Platz im Inventar\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Abgemacht?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Seid Ihr sicher, dass ich das identifizieren soll?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Seid Ihr sicher, dass Ihr diesen Gegenstand kaufen wollt?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Seid Ihr sicher, dass ich diesen Stab aufladen soll?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Seid Ihr sicher, dass Ihr diesen Gegenstand verkaufen wollt?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Seid Ihr sicher, dass ich das reparieren soll?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt mit dem Holzbein\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Mit Wirt sprechen\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Ich habe etwas Besonderes zu,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"verkaufen. Für 50 Gold-\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"stücke zeige ich es Dir. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Was hast Du?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Auf Wiedersehen\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Hier mein Angebot:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Verlassen\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Haus des Heilers\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Mit Pepin sprechen\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Heiler verlassen\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Deckard Cain\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Mit Cain sprechen\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Gegenstand identifizieren\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Ihr habt nichts zu identifizieren.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Was soll ich identifizieren?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Folgende Gegenstände habe ich identifiziert:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Erledigt\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Sprecht mit {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Ihr sprecht mit {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"ist nicht verfügbar\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"in der Shareware\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"Version\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Tratsch\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Aufgehende Sonne\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Mit Ogden sprechen\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Taverne verlassen\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Mit Gillian sprechen\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Truhe öffnen\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnham, der Säufer\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Mit Farnham sprechen\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Auf Wiedersehen\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Euer Gold: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Getöteter Dorfbewohner\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Griswold, der Schmied\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin, der Heiler\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Verwundeter Dorfbewohner\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden, der Gastwirt\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Cain, der Dorfälteste\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Adria, die Hexe\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian, die Barkeeperin\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Kuh\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester, der Farmer\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Kompletter Narr\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Krieger\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Jägerin\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Magier\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Mönch\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bardin\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbar\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombie\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Ghul\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Faulender Kadaver\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Pestbringer\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Gefallener\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Kobold\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Teuflischer\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Dunkle Kreatur\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Skelett\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Knochenkrieger\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Brennender Toter\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Horror\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Aasfresser\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Pestkäfer\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Schattenbiest\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Knochenreißer\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Knochen-Bogenschütze\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Skelett-Heerführer\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Knochen-Heerführer\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Brennender Heerführer\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Horror-Heerführer\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Fürst der Täuschung\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Phantom\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Anschleicher\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Ungesehener\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Illusionist\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Satyrfürst\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Blut-Clan\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Stein-Clan\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Feuer-Clan\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Nacht-Clan\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Fledermaus\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Blinzler\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Düsterflügel\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Familiar\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Säurespucker\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Giftspucker\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Grubenbiest\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Lavaschlund\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Skelettkönig\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Der Schlächter\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Aufseher\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Entstellter\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Verdammter\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Gehäuteter\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Lindwurm\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Höhlenlarve\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Teufelswurm\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Verschlinger\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Magmafürst\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Blutfürst\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Höllenfürst\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Lavafürst\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Gehörnter Drescher\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Schlammdrescher\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Frostdrescher\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obsidianfürst\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"oldboned\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Roter Tod\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Lich-Dämon\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Untoter Balrog\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Brennende Seele\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Flammenfürst\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Feuer der Verdammnis\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Höllenbrand\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Gewittergeißler\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Sturmreiter\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Sturmfürst\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Mahlstrom\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Teuflische Brut\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Geflügelter Dämon\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargoyle\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Blutklaue\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Todesschwinge\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Feuergeißler\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Wächter\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Feuerwirbler\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Höhlenviper\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Salamander\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Goldviper\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Azurschlange\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Schwarzer Ritter\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Ritter der Verdammnis\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Ritter des Abgrunds\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Blutritter\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Zerfetzte\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Leere Hülle\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Herr der Schmerzen\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Trugbild-Weber\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Sukkubus\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Schneehexe\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Höllenhexe\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Sirene\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Justiziar\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Magistrat\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Kabbalist\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Palatin\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Der Dunkle Fürst\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Der Erz-Lich Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad der Schwächliche\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar der Verrückte\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Snotspill\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Erzbischof Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Die Hexe Vanth\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Aterjadus\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Kriegsherr des Blutes\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Grendel\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Gothaur der Schlinger\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Knochenaxt der Kühne\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Klingenhaut der Schnitter\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Eitrige Seele\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Lygromath der Unreine\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Knochenbrecher\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Gatacheor der Hungrige\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Soor-Omash der Flinke\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Bhazman-Lath\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Garrach der Befallene\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Schattenbiss\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Todesauge\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Sarcon der Verblichene\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Feuerschädel\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Zyraell\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Drokvalath Bannschläger\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Carnifex\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Kalong\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Zornrabe\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Chyraptaroth\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Varmoth der Feuerteufel\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Schattenkrähe\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Beskatet der Ungestärkte\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Orkhabal der Grubenmeister\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Blutfell Düsterbogen\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Moderschwinge\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Schattentrinker\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Bhalaved\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Zhelobb der Giftige\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Tosfarel\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Gamrafos der Todesschatten\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Carcharoth die Kriegsmade\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Tar-Gralid der Umbarmherzige\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Oribadesh\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Fidar der Kalte\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Nograch\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Bronzefaust Feuerstein\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Gayazhed der Gezeichnete\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Bolgramoth der Harte\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Inarius\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Fäulnishorn Stahlkeule\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Chaosheuler\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Beelroth der Verfaulte\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Uphostadil\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Rikrak die Knochensäge\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Rückenbrecher\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Entseelte Fratze\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Bahkauv\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Taar-Umush\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Ozedrol\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Goldfäule der Flamme\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Schwarzer Sturm\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Graglior der Pestbringer\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Masabal der Häuter\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Buras der Pfähler\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Hyrug der Missgebildete\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Tarasque\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Rashgrador\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Ternobel der Gebeugte\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Schwarzzunge\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Schaurige Berührung\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Viperflamme\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Urzok der Tatzelwurm\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Thalac die Unheilige\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Der Schwarze Schnitter\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Scalptor\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Mazaruth\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Cellerarius\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Sartor der Rostige\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Asrud der Schattige\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Lanius der Unheilvolle\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Ragana Seelenfeuer\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Nyxana die Drude\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Addanc Blutmaul\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Ulschalal der Schlachter\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Der grausige Richter\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Die Hexe Sternenauge\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Zantharod der Jäger\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Varazhed der Wesir\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamphir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Blutdürstige Hexe\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Schwarze Witwe\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Erichtho Wirbeltanz\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Grimmzorn\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Volux der Vergessene\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Kurzschwert\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Beschützer\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Keule\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Kurzbogen\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Kurzstab des Manas\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Beil\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Die Krone der Untoten\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Der himmlische Ring\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Magischer Stein\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Das Optische Amulett\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Ring der Wahrheit\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Tavernenschild\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Harlekinskrone\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Stählerner Schleier\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Goldenes Elixier\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Amboss des Zornes\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Schwarzer Pilz\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Gehirn\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Pilzbuch\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Spektralelixier\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Blutstein\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Karte der Kathedrale\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Heiltrank\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Manatrank\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Schriftrolle der Identifikation\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Schriftrolle des Stadtportals\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Arkaines Tapferstahl\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Großer Heiltrank\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Großer Manatrank\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Griswolds Schneide\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Prunkharnisch des Kuhkönigs\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Stab des Lazarus\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Schriftrolle der Wiederbelebung\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Kurzstab\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Schwert\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Dolch\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Runenbombe\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodor\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Auratisches Amulett\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Zerissene Notiz 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Zerissene Notiz 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Zerissene Notiz 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Wiederhergestellte Notiz\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Brauner Anzug\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Grauer Anzug\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Kappe\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Schädelkappe\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Helm\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Vollhelm\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Krone\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Kammhelm\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Mantel\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Lumpen\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Umhang\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Robe\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Gesteppte Rüstung\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Lederrüstung\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Gehärtetes Leder\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Nietenrüstung\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Ringpanzer\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Brünne\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Kettenhemd\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Schuppenpanzer\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Brustharnisch\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Panzer\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Schienenrüstung\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Kettenpanzer\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Feldrüstung\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gotischer Harnisch\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Plattenpanzer\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Schild\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Kleiner Schild\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Großer Schild\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Drachenschild\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Turmschild\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gotischer Schild\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Trank der Genesung\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Trank der vollen Genesung\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Öl\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Elixir der Stärke\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Elixir der Magie\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Elixir der Agilität\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Elixir der Vitalität\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Schriftrolle der Heilung\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Schriftrolle der Suche\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Schriftrolle des Blitzes\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Schriftrolle der Feuerwand\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Schriftrolle des Infernos\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Schriftrolle des Lichtblitzes\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Schriftrolle des Durchblicks\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Schriftrolle der Verschiebung\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Schriftrolle des Manaschilds\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Schriftrolle der Flammenwelle\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Schriftrolle des Feuerballs\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Schriftrolle des Steinfluchs\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Schriftrolle des Kettenblitzes\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Schriftrolle der Wächter\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Schriftrolle der Nova\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Schriftrolle des Golems\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Schriftrolle des Teleports\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Schriftrolle der Apokalypse\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Sarazenenschwert\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Krummsäbel\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Flamberg\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Klinge\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Säbel\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Langschwert\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Breitschwert\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Bastardschwert\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Bidenhänder\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Kriegsschwert\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Handbeil\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Axt\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Streitaxt\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Breitaxt\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Kampfaxt\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Kriegsaxt\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Stahlkeule\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Morgenstern\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Streithammer\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Hammer\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Nagelkeule\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Dreschflegel\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Kriegshammer\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Bogen\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Jagdbogen\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Langbogen\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Kompositbogen\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Recurvebogen\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Kampfbogen\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Prunkbogen\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Kriegsbogen\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Langstab\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Kompositstab\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Kampfstab\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Kriegsstab\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Ring\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amulett\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Feuerrune\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Rune\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Blitzrune\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Große Feuerrune\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Große Blitzrune\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Steinrune\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Kurzstab des geladenen Blitzes\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Arena Trank\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Metzgerbeil des Schlächters\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Lichtsäbel\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Der Riftbogen\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Der Nadler\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Der himmlische Bogen\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Tödlicher Jäger\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Bogen der Toten\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Der Schwarzeichenbogen\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Feuerpfeil\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Nierenstecher\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Windmacht\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Adlerhorn\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Gonnagals Dolch\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Der Verteidiger\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Greifenklaue\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Schwarzer Schnitter\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Affenmond\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Eiszapfen\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Die Henkersklinge\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Die Knochensäge\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Schattenfalke\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Keris des Zauberers\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Lichtsäbel\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Die Falkenklaue\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Todesbringer\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Der Grizzly\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Der Großvater\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Der Zermalmer\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Scharfschnabel\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Blutschlächter\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Die himmlische Axt\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Bösartige Axt\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Steinspalter\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Aguinaras Kriegsbeil\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Höllenschlächter\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Messerschmidts Räuber\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Brechrost\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Hammer des Jholm\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Civerbs Knüppel\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Der himmlische Stern\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Baranars Stern\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Knorrige Wurzel\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Der Schädelspalter\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Dirks Streithammer\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Alptraumtöter\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Stab der Schatten\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Immolator\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Sturmspitze\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Glitzerlied\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Donnerruf\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Der Beschützer\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Najs Rätsler\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Seelenjammer\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Onans Stab\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Helm der Geister\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Die Denkkappe\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Helm des Aufsehers\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Narrenkappe\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Götterdämmerung\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Königlicher Reif\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Fleisch der gequälten Seelen\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Der Fluch des Gladiators\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Der Regenbogenumhang\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Auts Lederrüstung\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Gewand der Weisheit\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Funkenrüstung\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Aasfressers Beute\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Nachtschatten\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Najs leichter Panzer\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Stachelige Dämonenhaut\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Der Deflektor\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Spaltschädel-Schild\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Drachentöter\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Schwarzeichenschild\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Heiliger Lodder\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Sturmschild\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Dornenzweig\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Ring von Regha\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Der Bluter\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Würgering\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Verlobungsring\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Zinn-\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Messing-\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Bronze-\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Eisen-\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Stahl-\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Silber-\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platin-\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithril-\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteorischer\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Seltsamer\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Unnützer\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Verbogener\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Schwacher\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Gezackter\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Tödlicher\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Schwerer\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Grimmiger\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Brutaler\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Massiver\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Wilder\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Rücksichtsloser\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Gnadenloser\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Ungeschickter\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Stumpfer\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Scharfer\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Erlesener\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Kriegerischer\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Soldatischer\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Fürstlicher\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Ritterlicher\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Meisterlicher\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Heldenhafter\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Königlicher\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Verletzlicher\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Verrosteter\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Starker\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Robuster\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Tapferer\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Glorreicher\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Gesegneter\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Geweihter\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Großartiger\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Göttlicher\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Roter\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Karmesin-\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Granat-\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubin-\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Blauer\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Azurblauer\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lazulith-\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Kobalt-\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Saphir-\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Weißer\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Perlen-\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Elfenbein-\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Kristall-\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Diamant-\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topas-\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Bernstein-\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Jade-\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Obsidian-\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Smaragd-\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Hyänen-\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Frosch-\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Spinnen-\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Raben-\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Schlangen-\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Vipern-\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Echsen-\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Drachen-\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Lindwurm-\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hydra-\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Engels-\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Erzengels-\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Spendabler\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Großzügiger\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Flammender\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Blitzender\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"r Qualität\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"r Verstümmelung\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"s Erschlagens\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"s Massakers\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"s Gemetzels\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"s Schlachtens\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"s Schmerzes\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"r Tränen\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"r Gesundheit\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"s Schutzes\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"r Absorption\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"r Deflektion\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"r Osmose\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"r Zerbrechlichkeit\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"r Schwäche\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"r Stärke\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"r Macht\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"r Kraft\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"r Giganten\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"r Titanen\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"r Paralyse\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"r Atropie\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"r Agilität\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"r Fertigkeit\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"r Genauigkeit\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"r Präzision\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"r Perfektion\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"s Narren\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"r Dyslexie\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"r Magie\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"s Geistes\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"r Brillanz\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"r Zauberei\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"r Hexerei\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"r Krankheit\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"r Seuche\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"r Vitalität\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"r Frische\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"s Schwungs\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"r Härte\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"s Lebens\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"r Sorgen\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"r Lähmung\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"s Himmels\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"s Mondes\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"r Sterne\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"r Herrlichkeit\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"s Tierkreises\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"s Geiers\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"s Schakals\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"s Fuchses\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"s Jaguars\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"s Adlers\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"s Wolfs\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"s Tigers\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"s Löwen\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"s Mammuts\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"s Wals\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"r Brüchigkeit\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"r Sprödigkeit\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"r Festigkeit\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"r Kunstfertigkeit\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"r Dauerhaftigkeit\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"r Ewigkeit\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"r Finsternis\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"r Nacht\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"s Lichts\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"s Glanzes\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"r Flamme\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"s Feuers\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"s Brennens\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"s Schocks\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"s Blitzes\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"s Donners\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"r Vielfalt\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"r Fülle\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"r Dornen\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"r Verderbtheit\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"r Diebe\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"s Bären\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"r Fledermaus\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"r Vampire\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"s Blutegels\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"s Blutes\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"r Perforation\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"s Durchbohrens\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"s Zerschmetterns\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"r Bereitschaft\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"r Gewandtheit\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"r Geschwindigkeit\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"r Schnelligkeit\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"r Balance\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"r Stabilität\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"r Harmonie\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"s Blockens\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Der magische Stein\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad der Schwächliche\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar der Verrückte\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Der Schlächter\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Ogdens Schild\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Die Halle der Blinden\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Heldenmut\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Kriegsherr des Blutes\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Der Fluch des König Leoric\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Erzbischof Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Grabfunde\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Lesters Obstgarten\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Theodor\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Der fliegende Händler\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Gothaur der Schlinger\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Das festliche Gewand\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Feuerblitz\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Heilung\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Blitz\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Lichtblitz\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identifikation\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Feuerwand\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Stadtportal\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Steinfluch\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Durchblick\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Verschiebung\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Manaschild\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Feuerball\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Wächter\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Kettenblitz\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Flammenwelle\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Schlangen der Verdammnis\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Blutritual\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Unsichtbarkeit\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Wut\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleport\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apokalypse\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Ätherisieren\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Reparatur\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Stäbe aufladen\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Falle entschärfen\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elementarwesen\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Geladener Blitz\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Heiliger Blitz\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Wiederbelebung\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekinese\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Heilung Anderer\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Blutstern\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Knochengeist\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ah, die Geschichte unseres Königs wollt Ihr hören, wie? Der tragische \"\n\"Untergang von Leoric war ein harter Schlag für dieses Land. Die Menschen \"\n\"haben den König immer geliebt, und nun leben sie in ständiger Todesangst vor \"\n\"ihm. Was ich mich immer wieder frage, ist Folgendes: Wie konnte er so tief \"\n\"sinken? Leoric war ein Heiliger unter den Menschen. Nur die übelsten Mächte \"\n\"der Hölle können einen Mann im Innersten so gründlich vernichten...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Das Dorf braucht Eure Hilfe! Vor einigen Monaten wurde Prinz Albrecht \"\n\"gekidnappt, König Leorics Sohn. Der Monarch war außer sich vor Wut und \"\n\"durchsuchte das ganze Dorf nach seinem Erben. Mit jedem Tag, der ergebnislos \"\n\"verlief, rutschte Leoric tiefer in den Wahnsinn ab. Er beschuldigte \"\n\"schließlich wahllos unschuldige Untertanen und ließ sie grausam hinrichten. \"\n\"Weniger als die Hälfte von uns überlebte seinen Wahn. \\n\"\n\" \\n\"\n\"Die Ritter und Priester des Königs versuchten, ihn zu besänftigen, doch er \"\n\"stellte sich gegen sie, und zu ihrer tiefsten Schande waren sie gezwungen, \"\n\"ihn zu töten. Mit seinem letzten Atemzug sprach der König einen \"\n\"fürchterlichen Fluch über seine ehemaligen Gefolgsleute aus. Er schwor, dass \"\n\"sie ihm in der Finsternis auf ewig dienen würden... \\n\"\n\" \\n\"\n\"Und hier wird die Geschichte unheimlicher, als ich es jemals für möglich \"\n\"gehalten hätte. Unser früherer Herrscher stand von den Toten auf und \"\n\"befehligt jetzt eine Legion von Untoten im Labyrinth. Sein Körper wurde in \"\n\"einer Gruft drei Stockwerke unter der Kathedrale beigesetzt. Bitte, zerstört \"\n\"seinen untoten Körper und sorgt so dafür, dass seine Seele endlich Frieden \"\n\"findet.\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Wie ich Euch schon sagte, wurde unser König drei Stockwerke unter der Kirche \"\n\"beerdigt. Er ist jetzt da unten und wartet in der fauligen Dunkelheit auf \"\n\"seine Chance, das Land zu vernichten...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Der Fluch unseres Königs ist vorüber, aber ich fürchte, er war nur ein Teil \"\n\"eines größeren Übels. Wir können jedoch noch vor der Dunkelheit gerettet \"\n\"werden, die unser Land verzehrt, denn Euer Sieg ist ein gutes Omen. Möge das \"\n\"Licht Euch auf Eurem Weg leiten, guter Meister.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Der Verlust seines Sohnes war zuviel für König Leoric. Ich habe alles getan, \"\n\"was in meinen Kräften stand, um seine Wahnvorstellungen zu heilen, aber am \"\n\"Ende überwältigten sie ihn doch. Ein finsterer Fluch hing von diesem Tage an \"\n\"über diesem Königreich. Doch vielleicht endet er ja, wenn Ihr die Seele des \"\n\"Königs aus ihrem irdischen Gefängnis befreit.\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Ich mag gar nicht daran denken, wie der König gestorben ist. Ich erinnere \"\n\"mich lieber an ihn, wie er als freundlicher und gerechter Herrscher war. \"\n\"Sein Tod war so traurig und schien so unpassend.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Ich habe viele der Waffen und die meisten der Rüstungen hergestellt, mit \"\n\"denen König Leoric seine Ritter ausgerüstet hat. Ich habe ihm sogar ein \"\n\"riesiges Zweihänder-Schwert aus feinstem Mithril geschmiedet und eine \"\n\"passende Feldkrone dazu. Ich kann immer noch nicht glauben, wie er gestorben \"\n\"ist, aber es müssen ganz finstere Mächte gewesen sein, die ihn in den \"\n\"Wahnsinn getrieben haben.\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Ist mir egal. Hör mal, kein Skelett wird jemals mein König sein. Leoric ist \"\n\"der König, klar? König, verstehst Du? LANG LEBE DER KÖNIG!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Die Toten, die unter uns Lebenden wandeln, sie folgen dem verfluchten König. \"\n\"Er hat die Macht, noch mehr Krieger für die ständig wachsende Armee der \"\n\"Untoten zu rekrutieren. Wenn Ihr seine Herrschaft nicht beendet, wird er \"\n\"eines Tages über das Land marschieren und alle umbringen, die noch am Leben \"\n\"sind.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Hör mal, ich mache hier Geschäfte! Ich verkaufe keine Informationen, und mir \"\n\"ist dieser König völlig egal, der länger tot ist, als ich überhaupt lebe. \"\n\"Aber wenn Du was brauchst, was Du gegen diesen Untoten-König als Waffe \"\n\"verwenden kannst, dann kann ich Dir helfen.\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Die stickige Wärme des Lebens ist in mein Grab eingedrungen! Bereite Dich \"\n\"darauf vor, Sterblicher, meinem Herrn bis in alle Ewigkeit zu dienen!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Ich sehe, dass dieses merkwürdige Verhalten auch Euch verwundert. Ich kann \"\n\"nur vermuten, dass es die aufgehende Sonne auf dem Schild war, die die \"\n\"Dämonen zu der Annahme verleitet hat, das Schild selbst habe magische \"\n\"Kräfte. Ihr müsst wissen, dass die Dämonen das Sonnenlicht fürchten und \"\n\"glauben, es habe starke Zauberkräfte. Na ja, vielleicht sind sie dann doch \"\n\"nicht alle so schlau, wie wir befürchtet haben.\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Ich muss Euch von einem höchst merkwürdigen Erlebnis berichten, weil ich \"\n\"weiß, dass Ihr Euch mit diesen Monstrositäten auskennt, die im Labyrinth \"\n\"leben. Und ich verstehe es beim besten Willen nicht. Heute nacht wurde ich \"\n\"von einem kratzenden Geräusch vor meinem Gasthof geweckt. Als ich aus meinem \"\n\"Schlafzimmerfenster schaute, sah ich die Umrisse kleiner, dämonenartiger \"\n\"Wesen, die über den Hof huschten. Nach einiger Zeit liefen sie weg, aber sie \"\n\"nahmen dabei das Türschild des Gasthofes mit! Ich weiß nicht, warum Dämonen \"\n\"mein Holzschild stehlen, aber mich und meine Familie in Ruhe lassen sollten. \"\n\"Ist doch komisch, oder?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Och, Ihr hättet mir das Schild aber nicht extra zurückbringen müssen! Na ja, \"\n\"so spare ich auf jeden Fall die Kosten für ein neues. Wartet mal, was könnte \"\n\"ich Euch denn als kleines Dankeschön geben...ah ja, ich weiß schon. Diese \"\n\"Mütze hier hat ein durchreisender Magier in einem der Zimmer liegenlassen. \"\n\"Vielleicht könnt Ihr ja was damit anfangen.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Meine Güte, Dämonen laufen nachts durch das Dorf und plündern unsere Häuser \"\n\"- ist denen denn gar nichts mehr heilig? Ich hoffe, Ogden und Garda geht es \"\n\"gut? Na ja, wenn sie verletzt wären, hätten sie mich ja wohl schon besucht.\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Oh Himmel! Dahin ist das Schild also verschwunden. Meine Großmutter und ich \"\n\"müssen währenddessen friedlich geschlafen haben. Dem Licht sei Dank, dass \"\n\"diese Monster den Gasthof nicht überfallen haben.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Dämonen haben Ogdens Kneipenschild gestohlen? Das klingt aber gar nicht nach \"\n\"den Grausamkeiten, von denen ich gehört und einige auch selbst gesehen \"\n\"habe.\\n\"\n\"\\n\"\n\"Dämonen reißen Dir normalerweise den Kopf ab, nicht das Türschild!\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Weißt Du, was ich glaube? Irgend jemand hat das Schild geklaut, und jetzt \"\n\"wollen sie 'ne riesige Menge Knete dafür. Wenn ich Ogden wäre, ... bin ich \"\n\"ja nicht, aber wenn ich's wäre... Ich würde einfach ein neues Schild kaufen, \"\n\"mit einem netten Bild drauf. So ein hübscher Bierkrug vielleicht oder ein \"\n\"Stückchen Käse.\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Kein Sterblicher kann je den Verstand eines Dämon wirklich ergründen. \\n\"\n\"\\n\"\n\"Lasst Euch nie von ihren ziellosen Taten verwirren, denn genau das könnte \"\n\"ihr Plan sein.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Was denn, behauptet er etwa, ich hätte das gestohlen?\\n\"\n\"\\n\"\n\"Hör mal, über einfaches Schilderklauen bin ich seit Monaten weg. Aus so \"\n\"einem Stück Holz ist einfach kein Profit rauszuschlagen.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hey - Du sein doch der, der alle töten! Du mir holen magische Standarte, \"\n\"oder wir angreifen! Du nicht weggehen mit Leben! Du töten große Fieslinge \"\n\"und zurückgeben Magie! Gehen um Ecke und Türe, finden Fieslinge! Du geben, \"\n\"du gehen!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"\"\n\"Du töten Fieslinge, holen Standarte. Du mir bringen, sonst,...ja sonst...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Du bringen! Ja, gut, gut! Jetzt gehen, wir stark! Wir alle töten mit große \"\n\"Magie! Hahahahaha!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Das klingt nicht gut, denn es bestätigt meine schlimmsten Befürchtungen. \"\n\"Bisher habe ich nicht an die alten Legenden geglaubt, doch jetzt zweifle ich \"\n\"nicht mehr an ihnen. Vielleicht ist es an der Zeit, Euch zu sagen, wer ich \"\n\"wirklich bin. \\n\"\n\"\\n\"\n\"Mein wirklicher Name ist Deckard Cain der Ältere, und ich bin der letzte \"\n\"Nachfahre einer uralten Bruderschaft, die es sich zum Ziel gesetzt hatte, \"\n\"die Geheimnisse einer uralten bösen Macht zu bewahren. Einer Macht, die nun \"\n\"offensichtlich aus ihrem Gefängnis entkommen konnte. \\n\"\n\"\\n\"\n\"Erzbischof Lazarus, einst der vertrauteste Berater von König Leoric, hat \"\n\"einen Trupp einfacher Bürger ins Labyrinth geführt, um Albrecht zu suchen, \"\n\"den verschollenen Sohn des Königs. Es dauerte lange, bis jemand wiederkam, \"\n\"und nur wenige sind überhaupt mit dem Leben davongekommen. \\n\"\n\"\\n\"\n\"Was war ich bloß für ein Idiot! Ich hätte ihm damals schon auf die Schliche \"\n\"kommen müssen! Es muss Lazarus selbst gewesen sein, der Albrecht entführt \"\n\"hat und seitdem im Labyrinth versteckt hält. Ich weiß nicht, warum der \"\n\"Erzbischof zur Finsteren Seite hinübergewechselt ist oder was er mit dem \"\n\"Jungen vorhat, es sei denn, er will ihn seinem Dunklen Herrn opfern. \\n\"\n\"\\n\"\n\"Ja, das muss es sein! Die Überlebenden seines 'Rettungstrupps' haben \"\n\"erzählt, dass Lazarus, als sie ihn zum letzten Mal gesehen haben, \"\n\"hinunterrannte in die tiefsten Eingeweide des Labyrinths. Ihr müsst Euch \"\n\"beeilen und den Jungen vor dem Opfermesser dieses Verrückten retten!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Ihr müsst Euch beeilen und Albrecht aus Lazarus' Gewalt befreien! Der Prinz \"\n\"und die Bewohner des ganzen Königreiches zählen auf Euch!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Was Ihr da erzählt, klingt sehr ernst, mein Freund. Lazarus wird für seine \"\n\"schrecklichen Untaten in der Hölle schmoren. Der Junge, den Ihr mir \"\n\"beschrieben habt, ist nicht unser Prinz, aber ich glaube, dass Albrecht \"\n\"trotzdem in Gefahr sein könnte. Das Symbol der Macht, von dem Ihr mir \"\n\"berichtet habt, ist wahrscheinlich ein Portal, das direkt ins Herz des \"\n\"Labyrinthes führt.\\n\"\n\"\\n\"\n\"Doch wisset, mein Freund: Die böse Macht, mit der Ihr Euch messen wollt, ist \"\n\"der Finstere Lord des Terrors, unter den Sterblichen als Diablo bekannt. Er \"\n\"war es, der vor etlichen Jahrhunderten im Labyrinth eingesperrt worden ist, \"\n\"und ich fürchte, dass er erneut versucht, Chaos und Schrecken im Reiche der \"\n\"Menschen zu verbreiten. Ihr müsst Euch durch das Portal begeben und Diablo \"\n\"vernichten, bevor es zu spät ist!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus war der Erzbischof, der einen Trupp der Dorfbevölkerung in das \"\n\"Labyrinth hinabgeführt hat. Ich habe an jenem Tag viele gute Freunde \"\n\"verloren, und Lazarus ist nie zurückgekommen. Ich vermute, er ist zusammen \"\n\"mit den anderen getötet worden. Wenn Ihr mir einen Gefallen tun wollt, dann \"\n\"sprecht bitte Farnham nie auf diesen schrecklichen Tag an.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Ich war schockiert, als ich in jener Nacht von den Plänen der Leute hörte. \"\n\"Von allen Bewohnern des Dorfes hätte ich doch gerade Lazarus mehr Verstand \"\n\"zugetraut. Er war schließlich Erzbischof, und er schien sich immer sehr um \"\n\"die Leute von Tristram zu sorgen. So viele sind verletzt worden... ich \"\n\"konnte nicht alle retten.\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Ich erinnere mich an Lazarus als einen netten und großzügigen Mann. Er hat \"\n\"bei der Beerdigung meiner Mutter die Predigt gehalten, und er hat meiner \"\n\"Großmutter und mir in sehr schlimmen Zeiten Halt gegeben. Ich bete jede \"\n\"Nacht, dass er noch am Leben und in Sicherheit ist.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Ich war dabei, als Lazarus uns in das Labyrinth geführt hat. Er sprach von \"\n\"heiliger Vergeltung, aber als wir anfingen, gegen diese Höllenbrut zu \"\n\"kämpfen, hat er noch nicht mal seinen Morgenstern gezückt. Er rannte einfach \"\n\"immer tiefer in die dunklen, endlosen Gänge des Labyrinthes, aus denen die \"\n\"Knechte der Finsternis auf uns einströmten.\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Sie stechen, dann beißen sie, dann sind sie überall um Dich rum. Lügner! \"\n\"LÜGNER! Sie sind alle tot! Tot! Versteht Du?! Sie fallen wie die Fliegen... \"\n\"der ganze Boden schwimmt vor lauter Blut... alles seine Schuld...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Ich habe diesen Lazarus nicht gekannt, von dem Ihr erzählt. Aber ich spüre \"\n\"eine tiefe Spaltung in seinem Wesen. Er ist eine große Gefahr und er wird \"\n\"alles tun für die Mächte der Dunkelheit, die ihn zu einem der Ihren gemacht \"\n\"haben.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Oh ja, der heilige Lazarus, der ja soooo gut gegen diese Monster da unten \"\n\"gekämpft hat. Aber mein Bein hat er irgendwie auch nicht retten können, \"\n\"oder? Hör mal, ich gebe Dir einen Tipp - sogar gratis: Frag Farnham, der war \"\n\"dabei.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Vergesst Euer törichtes Vorhaben! Das Einzige, was Euch hier erwartet, ist \"\n\"der Zorn meines Herrn. Ihr kommt zu spät, um den Jungen noch zu retten. Doch \"\n\"Ihr werdet ihm bald Gesellschaft leisten - in der Hölle!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, ich weiß nicht, ob ich Euch darüber überhaupt etwas Hilfreiches \"\n\"erzählen kann. Das Wasser in unseren Brunnen stammt aus einer unterirdischen \"\n\"Quelle. Ich habe mal von einem Tunnel gehört, der zu einem großen \"\n\"unterirdischen See führen soll - vielleicht ist dort die Quelle. Aber \"\n\"unglücklicherweise weiß ich auch nicht, was unser Wasser so verseuchen \"\n\"könnte.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Ich habe immer versucht, ausreichend große Vorräte an Getränken und \"\n\"Lebensmitteln im Keller zu lagern. Aber wenn jetzt die ganze Stadt kein \"\n\"frisches Wasser mehr hat, werden sogar meine Reserven bald aufgebraucht \"\n\"sein. \\n\"\n\"\\n\"\n\"Bitte, tut Euer Bestes, oder ich weiß nicht, wie es weitergehen soll!\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Ich bin ja so froh, dass ich Euch noch rechtzeitig erwische! Unsere Brunnen \"\n\"sind plötzlich alle vergiftet und brackig. Einige Leute im Dorf sind schon \"\n\"krank geworden, weil sie davon getrunken haben. Unsere Frischwasserreserven \"\n\"gehen rapide zur Neige. Ich vermute, es gibt einen Durchgang vom Labyrinth \"\n\"zu der Höhle, in der unsere Quellen liegen. Bitte findet den Grund für \"\n\"dieses Desaster, oder wir werden alle zugrunde gehen.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Ich bitte Euch, beeilt Euch! Mit jeder Stunde kommen wir dem Verdursten \"\n\"näher!\\n\"\n\"\\n\"\n\"Ohne Eure Hilfe können wir nicht mehr lange durchhalten.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Was sagt Ihr? Die bloße Anwesenheit der Dämonen hat ausgereicht, das Wasser \"\n\"zu verseuchen? Da muss ja wirklich ein gewaltiges Übel unter unserer Stadt \"\n\"lauern... Aber Euer Mut und Eure Hartnäckigkeit geben uns Grund zur \"\n\"Hoffnung. Bitte, nehmt diesen Ring. Vielleicht wird er Euch bei der \"\n\"Vernichtung solch widerlicher Geschöpfe einmal hilfreich sein.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Meine Großmutter ist sehr schwach, und Garda sagt, dass wir das Wasser aus \"\n\"den Brunnen nicht trinken können. Ich bitte Euch, könnt Ihr nicht etwas tun, \"\n\"um uns zu helfen?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin hat Euch die Wahrheit erzählt. Wir brauchen dringend frisches Wasser, \"\n\"und zwar schnell. Ich habe versucht, einen der kleineren Brunnen sauber zu \"\n\"kriegen, aber das Wasser selbst stinkt nach verfaultem Dreck. Es wird \"\n\"offensichtlich schon direkt an der Quelle vergiftet.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Ihr trinkt ... Wasser?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Die Leute in Tristram müssen sterben, wenn Ihr nicht dafür sorgt, dass aus \"\n\"den Quellen wieder frisches Wasser sprudelt. \\n\"\n\"\\n\"\n\"Wisset, dass Dämonen hinter all dem stecken, doch sie wissen nicht, was sie \"\n\"angerichtet haben.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Zur Abwechslung bin ich mal ganz auf Deiner Seite. Mein Geschäft geht - \"\n\"bildlich gesprochen - den Bach runter, wenn ich keine Käufer mehr habe. Du \"\n\"solltest lieber schnell rausfinden, was da vor sich geht.\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Ein Buch, in dem eine Kammer aus Menschenknochen erwähnt wird? Na ja, eine \"\n\"Knochenkammer wurde in einigen der archaischen Schriften erwähnt, die ich in \"\n\"den Bibliotheken im Osten studiert habe. Diese Bücher meinten \"\n\"übereinstimmend, dass die Lords der Unterwelt zum Schutz großer Schätze \"\n\"solche Räume errichten könnten. Diejenigen, die bei dem Versuch starben, den \"\n\"Schatz zu stehlen, waren für alle Ewigkeit dazu verdammt, ihn zu beschützen. \"\n\"Ein schreckliches, aber merkwürdig passendes Ende...\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Ich fürchte, über das Thema weiß ich so gut wie nichts. Aber Cain hat viele \"\n\"Bücher, in denen was darüber stehen könnte.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Das klingt nach einem sehr gefährlichen Ort. Wenn Ihr dorthin geht, seid \"\n\"bitte besonders vorsichtig!\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Es tut mir leid, aber darüber habe ich noch nie etwas gehört. Vielleicht \"\n\"kann Cain Euch weiterhelfen, unser Geschichtenerzähler?\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Ich weiß nichts über diesen Ort, aber Ihr könntet Cain danach fragen. Er \"\n\"redet gerne und viel, und es würde mich nicht überraschen, wenn er Antworten \"\n\"auf Eure Fragen hätte.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Ok, hör mal zu. Da ist dieses Zimmer aus Holz, verstehst Du? Und seine Frau, \"\n\"weißt Du, also die... erzählt's den Bäumen... weil Du drauf wartest. Und \"\n\"drauf sag ich zu ihm, das könnte schlecht laufen für ihn, aber wenn Du \"\n\"meinst, ich bezahle dafür, dann.... äh.... ja, genau.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Solltet Ihr in diesem verfluchten Reich sterben, werdet Ihr auf ewige Zeiten \"\n\"den Dunklen Herrschern dienen müssen. \\n\"\n\"\\n\"\n\"Betretet die Knochenkammer auf eigene Gefahr!\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Ein riesiger und geheimnisvoller Schatz, sagst Du? Vielleicht könnte ich Dir \"\n\"ja nachher das eine oder andere Stück abkaufen. Oder noch besser, brauchst \"\n\"Du keine seltene und teure Spezialausrüstung für dieses gewagte Unternehmen?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Es sieht so aus, als habe Erzbischof Lazarus eine ganze Reihe von \"\n\"Stadtbewohnern dazu überredet, im Labyrinth nach dem verschollenen Sohn des \"\n\"Königs zu suchen. Er stachelte ihre Angst an und verwandelte sie in einen \"\n\"aufgeputschten Pöbel. Keiner von ihnen hatte auch nur die leiseste Ahnung, \"\n\"was ihn wirklich in der kalten Erde erwartete. Lazarus ließ sie dort unten \"\n\"im Stich, wo sie in den Fängen unvorstellbarer Horrorgestalten umkamen.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Ja, Farnham hat mal etwas über ein grausames Monster mit einem riesigen Beil \"\n\"erzählt. Ich glaube, er nannte es den Schlächter.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Beim Licht, ich kenne diesen bösen Dämon! Von den wenigen Überlebenden, die \"\n\"nach Lazarus' Expedition wieder aus dem Labyrinth zurückkehrten, trugen die \"\n\"meisten die Spuren seines Zornes auf dem Körper. Ich weiß nicht, womit er \"\n\"ihnen diese Wunden beigebracht hat, aber es kann keine gewöhnliche Waffe \"\n\"gewesen sein. Die Wunden waren eitrig und entzündet, und selbst ich konnte \"\n\"sie kaum heilen. Wenn Ihr gegen diesen Höllensohn kämpfen müsst, seht Euch \"\n\"vor!\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Als Farnham irgendwas über einen Schlächter erzählte, der Leute umbringt, \"\n\"habe ich es sofort als eine seiner Faseleien abgetan. Aber da Ihr jetzt auch \"\n\"davon anfangt, ist da wohl doch etwas mehr dran.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Ich habe dieses Ding gesehen, das Farnham den 'Schlächter' nennt, wie es in \"\n\"den Reihen meiner Freunde gewütet hat. Es schwang ein Metzgerbeil, so groß \"\n\"wie eine Zweihandaxt, schlug nach rechts und links, trennte Gliedmaßen und \"\n\"Köpfe ab. Ich wurde von einer Horde kleiner, kreischender Dämonen von der \"\n\"Haupttruppe abgedrängt und fand irgendwie eine Treppe nach oben. Ich habe \"\n\"das Monster seitdem nie wiedergesehen, doch sein blutverschmiertes Gesicht \"\n\"taucht immer noch in meinen schlimmsten Alpträumen auf.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Groß! Großes Hackebeil tötet alle meine Freunde! Konnte ihn nicht aufhalten, \"\n\"musste weglaufen, konnte sie nicht retten. Eingesperrt in einem Zimmer mit \"\n\"so vielen Leichen, so vielen Freunden...NEEEEEEEIIIIIN!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Der Schlächter ist ein sadistisches Geschöpf, das sich an Schmerz und Qual \"\n\"anderer Wesen erfreut. Ihr könnt die Spuren seines Wirkens nur zu gut an dem \"\n\"Trinker Farnham sehen. Die Vernichtung des Schlächters wäre ein großer \"\n\"Beitrag zur Sicherheit dieses Dorfes.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Ich weiß mehr über diesen Mistkerl, als Du ahnst. Seine kleinen Freunde \"\n\"haben mich festgehalten und mir das Bein ausgerissen, bevor Griswold mich \"\n\"aus diesem Loch rausgezogen hat. Ich will's mal ganz simpel ausdrücken:\\n\"\n\"\\n\"\n\"Mach ihn fertig, bevor er Dich umbringt und ausgestopft in seine \"\n\"Leichensammlung packt!\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Bitte, hört mir zu! Erzbischof Lazarus hat uns dort hinunter geführt, um den \"\n\"verschollenen Prinzen zu suchen. Der Bastard hat uns in eine Falle geführt! \"\n\"Jetzt sind alle tot... umgebracht von einem Dämon, den man den Schlächter \"\n\"nennt. Rächt uns! Findet diesen Schlächter und vernichtet ihn, damit unsere \"\n\"Seelen endlich Frieden finden...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Ihr zitiert da einen interessanten Reim, der mich vom Stil her an andere \"\n\"Werke erinnert...Lasst mich nachdenken, was war das doch gleich?\\n\"\n\"\\n\"\n\"...Dunkelheit verdeckt die Verborgenen. Augen glühen unbeobachtet, nur vom \"\n\"kurzen Kratzen rasiermesserscharfer Klauen begleitet, um die armen Seelen zu \"\n\"quälen, denen man für alle Ewigkeit das Augenlicht genommen hat. Das \"\n\"Gefängnis der so Gestraften heißt Kerker der Blinden...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Ich habe mir noch nie viel aus Gedichten gemacht. Manchmal habe ich fahrende \"\n\"Sänger engagiert, wenn der Gasthof gut lief, aber das ist jetzt schon lange \"\n\"her. \\n\"\n\"\\n\"\n\"Was? Ach ja, sicher, darüber weiß jemand anders bestimmt mehr als ich.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Das kommt mir irgendwie bekannt vor. Ich erinnere mich, mal etwas ganz \"\n\"Ähnliches gelesen zu haben wie dieses Gedicht. Es war während meiner \"\n\"Forschungen über die Geschichte der Dämonenseuchen. Da war die Rede von \"\n\"einem Ort großen Übels, der... wartet mal, Ihr habt doch nicht etwa vor, da \"\n\"hinzugehen, oder?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Wenn Ihr Fragen zum Thema Blindheit habt, solltet Ihr mit Pepin reden. Ich \"\n\"weiß noch, wie er meiner Großmutter einen Trank gab, der Ihr Augenlicht \"\n\"verbessert hat. Vielleicht kann er Euch auch helfen.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Ich fürchte, ich habe niemals einen Ort gesehen, der Eurer sehr lebhaften \"\n\"Beschreibung entspricht, und auch zuvor nie davon gehört, mein Freund. \"\n\"Vielleicht kann Euch Cain weiterhelfen, der Geschichtenerzähler.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\"Also schau mal.... hihihihi, lustig, was? Mitgekriegt? Blinde, schau mal? \"\n\"Hihihihi...\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Ein Ort des Terrors und der Panik, und damit dient er seinen Herren auf das \"\n\"Vortrefflichste. \\n\"\n\"\\n\"\n\"Seid vorsichtig, oder Ihr könntet viel länger dort bleiben müssen, als Euch \"\n\"lieb ist.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Schauen wir doch mal: Verkaufe ich Dir gerade was? Nein. Gibst Du mir Geld \"\n\"dafür, dass ich Dir etwas darüber erzähle? Ebenfalls Nein. Haust Du jetzt \"\n\"also ab und nervst den Erzähler mit Deinen Fragen, der liebend gerne lang \"\n\"und breit über alles Mögliche redet? Ja.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Ihr sagt, Ihr habt mit Lachdanan gesprochen? Er war Zeit seines Lebens ein \"\n\"großer Held. Lachdanan war ein ehrenhafter und gerechter Mann, der seinem \"\n\"König jahrelang treu gedient hatte. Aber das wisst Ihr natürlich längst. \\n\"\n\"\\n\"\n\"Von denen, die der Fluch des Königs befiel, wäre Lachdanan derjenige, der \"\n\"sich am ehesten weigern würde, sich der Finsternis kampflos zu ergeben. \"\n\"Daher vermute ich, dass Eure Geschichte wahr sein könnte. Wäre ich an Eurer \"\n\"Stelle, mein Freund, so würde ich einen Weg finden, ihn von seinen Qualen zu \"\n\"erlösen.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Ihr sprecht da von einem tapferen Krieger, der schon lange tot ist! Mit so \"\n\"einem Gerede über Unterhaltungen mit verstorbenen Seelen will ich nichts zu \"\n\"tun haben.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Ein goldenes Elixier, sagt Ihr? Ich habe noch nie einen Trank in dieser \"\n\"Farbe gebraut, daher kann ich Euch nicht sagen, welche Wirkung er auf Euch \"\n\"hätte. Als Euer Hausheiler kann ich Euch nur empfehlen, zu Risiken und \"\n\"Nebenwirkungen auf Lachdanan zu hören und ein solches Elixier - wenn Ihr es \"\n\"überhaupt findet - auf keinen Fall zu trinken!\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Ich habe noch nie von einem Lachdanan gehört. Tut mir leid, aber da kann ich \"\n\"Euch wohl nicht viel helfen.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Wenn es wirklich Lachdanan ist, den Ihr da getroffen habt, dann würde ich \"\n\"Euch dringend raten, ihm zu helfen. Ich hatte mehrmals mit ihm zu tun, und \"\n\"ich halte ihn für sehr loyal und ehrlich. Der Fluch, der das Gefolge von \"\n\"König Leoric traf, muss ihn besonders hart getroffen haben.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan ist tot. Das weiß jeder, und Du wirst mir das auch nicht \"\n\"ausreden. Und mit den Toten kannst Du nicht reden. Weiß ich genau!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Ihr trefft möglicherweise auf Menschen, die im Labyrinth gefangen sind, so \"\n\"wie Lachdanan etwa. \\n\"\n\"\\n\"\n\"Ich spüre in ihm viel Ehre, aber auch große Schuld. Helft ihm, und Ihr helft \"\n\"ganz Tristram.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Moment, lass mich raten: Cain ist von einer riesigen Erdspalte verschluckt \"\n\"worden, die sich unter ihm aufgetan hat. Dabei wurde er in einen gewaltigen \"\n\"Feuerball verwandelt und zu Asche verbrannt, und jetzt kann er Deine Fragen \"\n\"nicht mehr beantworten, stimmt's? Wenn nicht, dann willst Du bestimmt was \"\n\"kaufen oder schnell wieder abhauen.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Bitte, bringt mich nicht um! Hört mich an! Ich war einst Hauptmann in der \"\n\"Rittergarde von König Leoric, und ich habe das Gesetz dieses Landes mit Ehre \"\n\"und Gerechtigkeit verteidigt. Dann aber fiel sein Fluch auf uns, wegen der \"\n\"Rolle, die wir bei seinem tragischen Tod gespielt haben. Während sich meine \"\n\"Mitstreiter in ihr grausiges Schicksal ergaben, bin ich aus der Grabkammer \"\n\"des Königs geflohen. Seitdem suche ich nach einer Möglichkeit, mich von \"\n\"diesem Fluch zu befreien. Doch bisher habe ich versagt... \\n\"\n\"\\n\"\n\"Ich habe nur von einem Goldenen Elixier gehört, das den Fluch von mir nehmen \"\n\"und meiner Seele den Frieden des Todes bringen könnte, aber ich konnte es \"\n\"nie finden. Meine Kraft lässt nun langsam nach, und damit verfliegt auch der \"\n\"letzte Rest von Menschlichkeit in mir. Bitte helft mir und findet das \"\n\"Elixier! Ich werde Euch für Eure Mühe entlohnen - das schwöre ich bei meiner \"\n\"Ehre!\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Ihr habt das Goldene Elixier nicht gefunden. Ich fürchte, ich bin für alle \"\n\"Ewigkeit verdammt. Bitte, sucht weiter!\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Ihr habt meine Seele vor der Verdammnis gerettet, und dafür stehe ich in \"\n\"Eurer Schuld. Wenn es überhaupt einen Weg gibt, wie ich diese Schuld von \"\n\"jenseits des Grabes zurückzahlen kann, dann werde ich ihn finden. Doch fürs \"\n\"Erste kann ich Euch nur meinen Helm geben. Auf der Reise, die ich jetzt \"\n\"antrete, werde ich wohl kaum Verwendung dafür haben. Möge er Euch gegen die \"\n\"Mächte der Finsternis dort unten beschützen. Geht mit dem Licht, mein Freund!\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold spricht vom Amboss des Zornes - einem legendären Artefakt, nach dem \"\n\"lange gesucht, das aber nie gefunden wurde. Er wurde gefertigt aus den \"\n\"Metallknochen der Dämonen aus der Klingengrube, aber nicht nur das: Der \"\n\"Amboss des Zornes wurde um die Schädel der fünf mächtigsten Zauberer der \"\n\"Unterwelt herumgegossen und mit gewaltigen Runen der Macht und des Chaos \"\n\"versehen. Jede Waffe oder Rüstung, die auf diesem Amboss geschmiedet wird, \"\n\"taucht in das Reich des Chaos ein und erhält dabei magische Eigenschaften. \"\n\"Doch die unberechenbare Natur des Chaos macht es unmöglich, das Resultat \"\n\"dieses Schmiedevorganges vorab zu ahnen.\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Findet Ihr nicht, dass Ihr Euch da lieber an Griswold wenden solltet? Er ist \"\n\"ziemlich geschickt, müsst Ihr wissen.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Wenn Ihr mich jetzt nach der Silbernen Schale der Läuterung oder dem \"\n\"Heilenden Mörserstößel gefragt hättet, dann könnte ich Euch sofort \"\n\"weiterhelfen. Aber so wendet Ihr Euch lieber an Cain oder Griswold.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Als wir noch Kinder waren, erzählte Griswolds Vater einigen von uns \"\n\"Geschichten über einen riesigen Amboss, auf dem mächtige Waffen geschmiedet \"\n\"wurden. Er sagte, bei jedem Schlag des Hammers auf diesem Amboss zitterte \"\n\"der Boden vor Zorn. Ich muss jedesmal an diese Geschichte denken, wenn die \"\n\"Erde erbebt.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Seid gegrüßt! Es ist immer wieder eine Freude, einen meiner besten Kunden \"\n\"begrüßen zu dürfen. Ich weiß, dass Ihr inzwischen tiefer ins Labyrinth \"\n\"vorgedrungen seid, und es gibt da eine Geschichte, die Euch vielleicht \"\n\"interessieren dürfte. \\n\"\n\"\\n\"\n\"Einer der Männer, die aus dem Labyrinth zurückkehrten, erzählte mir von \"\n\"einem mystischen Amboss, an dem er während seiner Flucht vorbeigekommen war. \"\n\"Seine Beschreibung erinnerte mich an eine alte Legende, die ich als Junge \"\n\"mal gehört habe und die von der Höllenschmiede handelte, wo mächtige \"\n\"magische Waffen geschmiedet worden sein sollen. Der Sage zufolge stand tief \"\n\"im Herzen dieser Höllenschmiede der Amboss des Zornes. \\n\"\n\"\\n\"\n\"Der Kern dieses Ambosses bestand aus der Quintessenz der dämonischen \"\n\"Unterwelt. Man sagt, dass jede Waffe, die auf diesem Amboss geschmiedet \"\n\"wird, große Kräfte verliehen bekommt. Wenn dieser Amboss, den der Mann \"\n\"gesehen hat, wirklich der Amboss des Zornes ist, könnte ich Euch darauf \"\n\"vielleicht eine Waffe schmieden, die selbst den finstersten Fürsten der \"\n\"Hölle besiegen kann!\\n\"\n\"\\n\"\n\"Sucht mir diesen Amboss, und ich mache mich gleich an die Arbeit.\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Noch immer nichts, wie? Na ja, sucht einfach weiter. Eine Waffe, die auf dem \"\n\"Amboss des Zornes geschmiedet wurde, wäre Eure einzige Hoffnung, und ich bin \"\n\"sicher, ich könnte Euch eine Klinge von ungeahnten Dimensionen herstellen.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Ich kann es kaum glauben! Das ist wirklich der Amboss des Zornes! Gute \"\n\"Arbeit, mein Freund. Jetzt wollen wir diesen Bastarden in der Hölle mal \"\n\"beweisen, dass es dort keinen gefährlicheren Stahl gibt als den, den wir \"\n\"Menschen schmieden! Nehmt diese Waffe hier, und möge das Licht Euch behüten! \"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold kann seinen Amboss nicht verkaufen. Dann hätte er doch keine Arbeit \"\n\"mehr! Und ich würde ja auch sauer, wenn jemand meinen Amboss klauen wollte...\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Es gibt viele Gegenstände im Labyrinth, deren Kräfte das Verständnis jedes \"\n\"Sterblichen übersteigen. Einige davon können ihre Macht für das Licht oder \"\n\"für die Finsternis einsetzen. Wenn Ihr den Amboss in Sicherheit bringen \"\n\"könntet, würde das den Verlauf des Sündenkrieges zugunsten des Lichtes \"\n\"beeinflussen.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Wenn Du dieses Artefakt für Griswold fändest, würde das meinem Geschäft hier \"\n\"sehr schaden. Ach was, das findest Du doch sowieso nie...\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Das Blutportal und das Flammengewölbe sind Orte aus der Mystik. Wo immer \"\n\"dieses Buch auch liegt, in dem Ihr etwas darüber gelesen habt, es ist mit \"\n\"Sicherheit ein Ort voller Magie. \\n\"\n\"\\n\"\n\"Die Legenden berichten von einem Podest aus Obsidian, mit einem Tümpel aus \"\n\"kochendem Blut auf seiner knochenverkrusteten Oberfläche. Es werden auch \"\n\"Blutsteine erwähnt, mit deren Hilfe man ein Portal öffnen kann, das einen \"\n\"uralten Schatz behütet. \\n\"\n\"\\n\"\n\"Welche Art von Schatz das ist, darüber gibt es nur Spekulationen, mein \"\n\"Freund, aber man sagt, der Sagenheld Arkaine habe seine heilige Rüstung \"\n\"namens Tapferstahl in einer geheimen Gruft versteckt. Arkaine war der erste \"\n\"Sterbliche, der den Verlauf des Sündenkrieges veränderte und die Legionen \"\n\"der Finsternis in die Feuer der Hölle zurücktrieb. \\n\"\n\"\\n\"\n\"Kurz vor seinem Tod wurde seine Rüstung an einem geheimen Ort verborgen. Die \"\n\"Legende sagt, dass die Zeit kommen wird, in der man diese heilige Rüstung \"\n\"wieder braucht. Ein Held wird kommen und den Tapferstahl wieder in die \"\n\"Schlacht tragen.Vielleicht seid Ihr dieser Held...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Jedes Kind kennt die Geschichte von dem Krieger Arkaine und seiner magischen \"\n\"Rüstung Tapferstahl. Wenn Ihr das Versteck dieser Rüstung finden könntet, \"\n\"wäret Ihr vor dem Bösen im Labyrinth gut geschützt.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... klingt nach etwas, an das ich mich eigentlich erinnern müsste, aber \"\n\"ich war so beschäftigt damit, neue Heilmittel zu erforschen und immer \"\n\"wirksamere Tränke zu mischen, dass es mir wohl entfallen sein muss. Tut mir \"\n\"leid...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Die Geschichte von der Heiligen Rüstung Tapferstahl habe ich von den Jungen \"\n\"im Dorf oft gehört. Ihr solltet da lieber einen der Männer fragen.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Die Heilige Rüstung Tapferstahl könnte den Kampf für uns entscheiden. Lasst \"\n\"Euch gesagt sein, dass viele schon danach gesucht haben - mich selbst \"\n\"eingeschlossen. Aber Arkaine hat sie gut versteckt, mein Freund, und Ihr \"\n\"werdet mehr als nur ein bisschen Glück brauchen, um die Geheimnisse zu \"\n\"enträtseln, hinter denen sich die Rüstung all die Jahre verborgen hat.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Schnarch...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Solltet Ihr diese Blutsteine wirklich finden, geht vorsichtig mit ihnen \"\n\"um. \\n\"\n\"\\n\"\n\"Der Weg steckt voller Gefahren, und als Eure einzige Hoffnung bleibt Euer \"\n\"Selbstvertrauen.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Du willst diese Rüstung finden, die man Tapferstahl nennt?\\n\"\n\"\\n\"\n\"Niemand hat je rausfinden können, wo Arkaine den Kram versteckt hat, und \"\n\"wenn meine Gewährsleute das nicht rausfinden konnten, schaffst Du es erst \"\n\"recht nicht.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Ich kenne nur eine einzige Sage, in der von so einem Krieger die Rede ist, \"\n\"wie Ihr ihn beschreibt. Seine Geschichte steht in den alten Chroniken der \"\n\"Sündenkriege...\\n\"\n\"\\n\"\n\"'Besudelt von einem Jahrtausend voller Krieg, Blut und Tod steht der \"\n\"Blutfürst auf einem Berg seiner zerschmetterten Opfer. Seine schwarze Klinge \"\n\"schleudert den Lebenden einen finsteren Fluch entgegen, eine gequälte \"\n\"Herausforderung für alle, die sich diesem Henker der Hölle in den Weg zu \"\n\"stellen wagen.'\\n\"\n\"\\n\"\n\"Es steht auch noch geschrieben, dass er zwar früher mal ein Sterblicher war, \"\n\"der im Sündenkrieg auf der Seite der Finsternis gekämpft hat. Doch er \"\n\"opferte sein Menschsein seinem unersättlichen Durst nach Blut.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Es tut mir leid, von einem solchen Krieger habe ich noch nie etwas gehört. \"\n\"Ich hoffe nur, Ihr müsst nicht gegen ihn kämpfen, er klingt ja fürchterlich \"\n\"gefährlich.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain kann Euch darüber wahrscheinlich viel mehr erzählen, als ich überhaupt \"\n\"wissen möchte.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Wenn Ihr gegen so einen schweren Widersacher antreten müsst, dann möge das \"\n\"Licht Euch beschützen und leiten. Ich werde in Gedanken bei Euch sein.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Dunkle und böse Legenden ranken sich um den Blutfürsten. Bereitet Euch auf \"\n\"dieses Treffen gut vor, mein Freund, denn er kennt weder Gnade noch Pardon.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Musst Du immer nur über Blut reden? Was ist denn mit Blümchen, Sonnenschein \"\n\"oder dem hübschen Mädel, das immer die Getränke bringt? Hör mal, mein Freund \"\n\"- das ist schon eine richtige Marotte von Dir, weißt Du das?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Wie er mit einer Klinge umzugehen vermag, ist ehrfurchterregend, und er hat \"\n\"Tausende von Jahren nur für den Krieg gelebt. Es tut mir leid... ich wüsste \"\n\"nicht, wie Ihr ihn besiegen könntet.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Ich habe noch nie mit diesem Herrn zu tun gehabt, von dem Du da erzählst, \"\n\"aber es klingt so, als bräuchte er eine Menge Schwerter. Hätte nichts \"\n\"dagegen, seine Armeen zu beliefern...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Meine Klinge schreit vor Hunger nach Eurem Blut, und bei meinem Dunklen \"\n\"Herren, sie soll nicht enttäuscht werden! \"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold meint den Himmelsstein, der für die Enklave im Osten bestimmt war \"\n\"und dort weiter erforscht werden sollte. In dem Stein glühte eine Energie, \"\n\"die einen Menschen auf irgendeine Weise mehr erschauen ließ, als es ihm von \"\n\"Natur aus möglich war. Ich weiß nicht, welches Geheimnis sich in diesem \"\n\"Stein verbirgt, mein Freund, doch es ist auf jeden Fall der Mühe wert, ihn \"\n\"zu suchen! \"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Die Karawane hat hier Rast gemacht und einige Vorräte für die weite Reise in \"\n\"den Osten aufgeladen. Ich habe den Leuten eine Menge frisches Obst verkauft \"\n\"und einige süße Brote, die Garda gebacken hatte. Es ist eine Schande, was \"\n\"dann mit ihnen passiert ist...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Ich weiß ja nicht, was die mit diesem Stück Stein sehen wollten, aber eins \"\n\"weiß ich: Wenn jetzt schon die Steine vom Himmel fallen, dann seid lieber \"\n\"vorsichtig!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Na ja, eine Karawane mit sehr wichtigen Leuten hat hier gehalten, aber das \"\n\"ist schon ziemlich lange her. Sie hatten alle so einen komischen Akzent und \"\n\"haben sich auf eine weite Reise vorbereitet, soweit ich mich erinnere. \\n\"\n\"\\n\"\n\"Ich verstehe nur nicht, wie Ihr irgendwas finden wollt, das die bei sich \"\n\"hatten? \"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Verweilt einen Moment - ich habe da eine Geschichte gehört, die Euch \"\n\"interessieren dürfte. Vor einiger Zeit kam hier eine Karawane durch, auf dem \"\n\"Weg in die östlichen Königreiche. Man erzählte sich, sie habe ein Stück des \"\n\"Himmels dabei, das auf die Erde gefallen sei. Doch nur wenige Meilen \"\n\"nördlich von hier wurde die Karawane von vermummten Reitern überfallen. Ich \"\n\"habe in den Überresten nach diesem Stein vom Himmel gesucht, aber nichts \"\n\"gefunden. Wenn er Euch in die Hände fallen sollte, könnte ich daraus \"\n\"bestimmt etwas Nützliches herstellen.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Ich warte immer noch, dass Ihr mir diesen Stein des Himmels bringt. Ich \"\n\"weiß, dass ich etwas Machtvolles daraus herstellen könnte.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Zeigt mir das mal kurz. Ja, genau, das habe ich mir gedacht. Gebt ihn mal \"\n\"gerade her... hier!\\n\"\n\"\\n\"\n\"Ich habe Splitter des Steines in einen Silberring eingelassen, den ich von \"\n\"meinem Vater geerbt habe. Ich hoffe, er hilft Euch.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Ich hatte auch mal einen schönen Ring. War ein richtig teurer, so mit Blau \"\n\"und Rot und Grün und Silber. Weiß gar nicht, was damit passiert ist. Aber \"\n\"ich vermisse ihn wirklich.\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Der Himmelsstein ist sehr mächtig, und würde Euch jemand anderer als \"\n\"Griswold bitten, ihn zu suchen, so würde ich es verhindern. Er aber wird die \"\n\"Kräfte des Steins zu bändigen und zum Wohle der gesamten Menschheit \"\n\"einzusetzen wissen.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Wenn irgend jemand etwas aus diesem Stück Stein zaubern kann, dann Griswold. \"\n\"Er weiß genau, was er tut, und auch wenn ich versuche, ihm seine Kunden \"\n\"abspenstig zu machen, so respektiere ich doch die Qualität seiner Arbeit.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Adria, die Hexe, benötigt einen schwarzen Pilz? Über schwarze Pilze weiß ich \"\n\"leider genauso viel wie über rosa Schnittlauch. Vielleicht kann Euch Pepin, \"\n\"der Heiler, etwas mehr darüber verraten. In meinen Büchern und Geschichten \"\n\"jedenfalls steht nichts davon.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Dazu kann ich nur eines sagen: Weder Garda noch ich haben oder werden \"\n\"unseren zahlenden Gästen JEMALS schwarze Pilze servieren. Wenn Adria solche \"\n\"Pilze in ihren Eintopf schneiden möchte, ist das allein ihre Sache, aber ich \"\n\"werde Euch nicht auch noch helfen, schwarze Pilze zu finden... ist ja \"\n\"widerlich!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Die Hexe hat mir erzählt, dass Ihr nach einem Dämonenhirn sucht, um mir bei \"\n\"der Herstellung meines Elixiers zu helfen. Es wäre von unschätzbarem Wert \"\n\"für alle, die von diesen elenden Monstern verwundet werden, wenn ich die \"\n\"Geheimnisse entschlüsseln könnte, die ich in der Alchemie dieser Hirne \"\n\"vermute. Wenn Ihr also wieder mal einen Dämon tötet, versucht bitte, sein \"\n\"Hirn unversehrt mitzubringen und mir zu geben, ja? \"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Exzellent, genau das, was ich mir vorgestellt hatte. Ich konnte zwar das \"\n\"Elixier auch ohne das Dämonenhirn fertigstellen, aber es kann ja nicht \"\n\"schaden, es als Studienobjekt hier zu haben. Würdet Ihr das hier bitte zur \"\n\"Hexe bringen? Ich glaube, sie wartet darauf...\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Ich glaube, Ogden hat einige Pilze in seinem Vorratskeller.  Warum fragt Ihr \"\n\"ihn nicht mal?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Wenn Adria keinen hat, müssen die ja wirklich selten sein. Ich kann Euch \"\n\"nicht mehr dazu sagen, aber es klingt nach einem... irgendwie riesigen, \"\n\"aufgequollenen, gigantischen Pilz! Na ja, viel Spaß beim Suchen.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden kann einen tierischen Schwarzen Pilz mischen, aber davon muss ich \"\n\"immer kotzen. Hör mal, hör mal, ich verrate Dir was: Mäßigung ist das ganze \"\n\"Geheimnis. \"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Was haben wir denn hier? Interessant... sieht aus wie ein Buch mit \"\n\"Reagenzien. Haltet Eure Augen offen nach einem schwarzen Pilz. Er müsste \"\n\"ziemlich groß sein und daher leicht zu identifizieren. Wenn Ihr einen \"\n\"findet, bringt ihn her, ja?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Ich brauche einen großen, schwarzen Pilz. Los, geht jetzt und holt ihn mir, \"\n\"damit ich dieses spezielle Gebräu fertigmischen kann, an dem ich gerade \"\n\"arbeite.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Ja, das ist die perfekte Zutat für meinen Trank. Übrigens, der Heiler \"\n\"benötigt das Hirn eines Dämon für seinen Heiltrank gegen Dämonengift. Wenn \"\n\"Ihr ihm helfen könnt, dann tut es bitte, aber versucht doch auch, eine Probe \"\n\"dieses Elixiers für mich zu bekommen.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Warum schleppt Ihr mir das Zeug hier an? Ich brauche im Moment kein \"\n\"Dämonenhirn. Was ich brauche, ist ein Schluck von dem Elixier, an dem der \"\n\"Heiler gerade arbeitet. Er braucht dieses.... groteske Organ, das Ihr da so \"\n\"stolz herumzeigt. Und dann könnt Ihr mir sein Elixier bringen. Ist doch ganz \"\n\"einfach, wenn man mal drüber nachdenkt, oder?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Was denn, jetzt bringt Ihr mir endlich das Elixier vom Heiler? Jetzt habe \"\n\"ich meinen Trank auch ohne das Zeug fertigbekommen. Ihr könnt es behalten...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Ich habe überhaupt keine Pilze zu verkaufen, egal wie groß oder in welcher \"\n\"Farbe. Wie wäre es denn statt dessen mit etwas Nützlicherem?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Soso, die Legende über die Karte ist also wahr. Selbst ich habe nie wirklich \"\n\"daran geglaubt. Vielleicht ist es an der Zeit, Euch zu sagen, wer ich \"\n\"wirklich bin. Ihr müsst wissen, dass mein äußerer Anschein nicht ganz meiner \"\n\"wahren Natur entspricht. \\n\"\n\" \\n\"\n\"Mein wirklicher Name ist Deckard Cain der Ältere, und ich bin der letzte \"\n\"Nachfahre einer uralten Bruderschaft, die es sich zum Ziel gesetzt hatte, \"\n\"die Geheimnisse einer uralten bösen Macht zu bewahren. Einer Macht, die nun \"\n\"offensichtlich aus ihrem Gefängnis entkommen konnte. \\n\"\n\" \\n\"\n\"Die böse Macht, mit der Ihr Euch messen wollt, ist der Finstere Lord des \"\n\"Terrors, unter den Sterblichen als Diablo bekannt. Er war es, der vor \"\n\"etlichen Jahrhunderten im Labyrinth eingesperrt worden ist. Diese Karte in \"\n\"Eurer Hand ist vor Jahrhunderten angefertigt worden, um den Zeitpunkt \"\n\"festzulegen, an dem Diablo wieder aus seinem Gefängnis entkommen würde. Wenn \"\n\"die beiden Sterne auf der Karte zusammenkommen, ist Diablo auf dem Höhepunkt \"\n\"seiner Macht. Er ist dann praktisch unbesiegbar. \\n\"\n\" \\n\"\n\"Die Zeit arbeitet nun gegen Euch, mein Freund. Findet Diablo und vernichtet \"\n\"ihn, bevor die Sterne zusammenkommen, oder wir werden vielleicht nie wieder \"\n\"die Chance bekommen, die Welt vor seinem Würgegriff zu bewahren!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Unsere Zeit wird knapp! Ich kann spüren, wie seine finstere Macht wächst, \"\n\"und nur Ihr könnt verhindern, dass er all seine Kräfte wiedererlangt! \"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Ich bin sicher, dass Ihr Euer Bestes geben werdet, doch ich fürchte, nicht \"\n\"einmal Euer Arm und Euer Wille sind stark genug. Diablo ist nun auf dem \"\n\"Höhepunkt seiner irdischen Macht, und Ihr werdet all Euren Mut und Eure \"\n\"Kraft brauchen, um ihn zu besiegen. Möge das Licht Euch beschützen und \"\n\"leiten, mein Freund. Ich werde Euch helfen, soweit ich es vermag.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Wenn die Hexe Euch nicht helfen kann und Euch schon zu Cain schickt, wieso \"\n\"glaubt Ihr dann, ich könnte etwas darüber wissen? Das klingt nach einer sehr \"\n\"ernsten Angelegenheit. Ihr solltet lieber schleunigst das tun, was Adria \"\n\"vorgeschlagen hat und zum Geschichtenerzähler gehen.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Ich kann mit den Inschriften auf der Karte nicht viel anfangen, aber \"\n\"vielleicht wissen Adria oder Cain, was das bedeuten soll.\\n\"\n\"\\n\"\n\"Ich kann nur erkennen, dass es eine Karte unseres Sternenhimmels ist, aber \"\n\"mehr sagt mir das Ding nicht.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Bei solchen Sachen fragt Ihr am besten immer unseren Geschichtenerzähler.\\n\"\n\"\\n\"\n\"Cain weiß eine Menge über alte Schriften, und das hier ist ja nun wirklich \"\n\"das älteste Stück Papier, das mir jemals untergekommen ist.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"So eine Karte habe ich noch nie gesehen. Wo habt Ihr die denn her? Ich kann \"\n\"sie zwar nicht entziffern, aber Cain oder Adria müssten Euch da weiterhelfen \"\n\"können.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Hör mal, komm mal her. Ich weiß nicht, ob Du weißt, was ich weiß, aber weißt \"\n\"Du, dass das eine Karte ist? Eine richtige Landkarte! \"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Oh, ich fürchte, das hört sich gar nicht gut an. Diese Sternenkarte bedeutet \"\n\"großes Unheil, doch es ist nicht an mir, ihre Geheimnisse zu lüften. Die \"\n\"Zeit ist reif für ein ernstes Gespräch mit dem Geschichtenerzähler...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Ich habe nach einer Karte gesucht, aber bestimmt nicht nach der hier. Du \"\n\"solltest sie mal Adria zeigen - sie kann Dir eher sagen, was das ist. Ich \"\n\"weiß nur, dass sie ziemlich alt aussieht, und 'alt' bedeutet meist \"\n\"'wertvoll'.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Bitte nicht wehtun. Nicht töten. Leben lassen, nächstes Mal Gutes Euch \"\n\"bringen.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Etwas für Euch ich machen. Nicht töten Gharbad. Leben und Gutes geben. \\n\"\n\"\\n\"\n\"Hier das Ihr nehmen als Beweis ich halten Wort.\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Noch nichts! Fast fertig aber. \\n\"\n\"\\n\"\n\"Sehr mächtig, sehr stark. Leben! Leben!\\n\"\n\"\\n\"\n\"Keine Wehtun, ich halten Versprechung.\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Dies zu gut für Euch. Sehr stark! Ihr wollen, Ihr Euch holen kommen!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Was? Warum seid Ihr hier? Bei diesen ganzen Störungen muss man ja verrückt \"\n\"werden! Hier, nehmt das und geht, ich muss arbeiten! Stört mich bloß nicht \"\n\"mehr!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Eure Neugier wird Euch noch mal umbringen. Und zwar jetzt!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Hallo, mein Freund. Bleibt und hört mir ein wenig zu...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Während Ihr tiefer und tiefer in das Labyrinth vordringt, werdet Ihr Bücher \"\n\"mit geheimem Wissen finden, die dort seit Generationen verborgen liegen. \\n\"\n\"\\n\"\n\"Lest sie sorgfältig, denn sie können Euch Dinge lehren, von denen nicht \"\n\"einmal ich weiß.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Ich kenne viele Legenden und Mythen, und in einigen davon stecken \"\n\"wahrscheinliche Antworten auf ein paar der Fragen, die sich Euch im Laufe \"\n\"Eurer Abenteuer im Labyrinth stellen werden. Wenn Ihr also auf Rätsel und \"\n\"Herausforderungen stoßt, über die Ihr zu wenig wisst, kommt zu mir, und ich \"\n\"werde Euch alles sagen, was ich darüber weiß.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold - ein Mann der Tat, und ein ungeheuer mutiger Kämpfer. Ich wette, \"\n\"er hat Euch nie erzählt, dass er mal ins Labyrinth hinunter gestiegen ist, \"\n\"um Wirt zu retten, oder? Er kennt schon viele der Gefahren, die dort unten \"\n\"lauern, aber - die kennt Ihr inzwischen ja auch. Er ist ein geschickter \"\n\"Handwerker, und wenn er sagt, dass er Euch helfen kann, könnt Ihr Euch auf \"\n\"seine Ehrlichkeit und sein Können verlassen.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden ist jetzt seit fast vier Jahren Eigentümer des Gasthofs zum \"\n\"Sonnenaufgang. Er hat ihn erst ein paar Monate vor der Katastrophe hier \"\n\"gekauft. Er und seine Frau Garda haben kein Geld mehr, um woanders \"\n\"hinzuziehen. Sie haben alles investiert, um sich hier eine Existenz \"\n\"aufzubauen. Ogden ist ein guter, verantwortungbewusster Mann.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Der arme Farnham. Er ist für uns eine bleibende Erinnerung an den traurigen \"\n\"Tag, an dem der Trupp Dorfbewohner dem Erzbischof Lazarus in das Labyrinth \"\n\"unter der Kathedrale folgte. Farnham kam mit dem Leben davon, aber seinen \"\n\"Mut und den größten Teil seines Verstandes hat er in diesem dunklen Loch \"\n\"verloren. Er hat sich ganz in seinen Bierkrug zurückgezogen, aber in seinem \"\n\"betrunkenen Gelalle steckt doch ab und zu ein Körnchen Wahrheit.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Die Hexe Adria ist eine Außenseiterin hier in Tristram. Sie kam hier an, als \"\n\"alle anderen schon von hier flohen, kurz nachdem die Kathedrale entweiht \"\n\"worden war. Sie hat sich eine kleine Hütte am Stadtrand gebaut, scheinbar \"\n\"über Nacht, und sie besitzt viele seltsame, magische Gegenstände und Bücher, \"\n\"die selbst ich noch nie gesehen habe.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Wirts Geschichte ist tragisch und furchterregend. Er wurde von kleinen \"\n\"Dämonen mit Speeren seiner Mutter aus den Armen gerissen und ins Labyrinth \"\n\"verschleppt. Am gleichen Tag wurden noch viele andere Kinder entführt, \"\n\"darunter auch der Sohn von König Leoric. Die Ritter des Palastes gingen \"\n\"sofort hinunter, doch sie kamen nie wieder zurück. Der Schmied fand den \"\n\"Jungen, doch erst, nachdem die Monster angefangen hatten, ihn zu ihrem \"\n\"sadistischen Vergnügen zu foltern.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Ich zähle ihn zu meinen wahren Freunden - vielleicht ist er sogar \"\n\"der beste, den ich habe. Er ist manchmal etwas verwirrt, aber niemand kann \"\n\"freundlicher und fürsorglicher sein als er. Sein Wissen und sein Können sind \"\n\"unübertroffen, und seine Tür ist für alle stets offen.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian ist eine ganz besondere Frau. In meinem Herzen ist ein ganz \"\n\"besonderer Platz für sie reserviert, für ihre stets gute Laune und ihr \"\n\"fröhliches Lachen. Sie bleibt in der Taverne wegen ihrer alten Großmutter, \"\n\"die zu krank zum Reisen ist. Manchmal sorge ich mich um ihre Sicherheit, \"\n\"aber andererseits weiß ich, dass jeder Mann im Dorf lieber sterben würde als \"\n\"zuzulassen, dass ihr etwas zustößt.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Seid mir herzlich gegrüßt! Willkommen im Gasthof Zum Sonnenaufgang!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Viele Abenteurer haben schon an den Tischen meines Gasthofs gesessen, und \"\n\"zehnmal so viele Geschichten sind bei ebenso vielen Krügen Bier erzählt \"\n\"worden. Das Einzige, worin sich alle immer einig waren, ist die alte \"\n\"Grundregel, die Ihr vielleicht auch ganz nützlich finden werdet: \\\"Fleisch \"\n\"kann man schneiden, aber Knochen muss man zerschmettern\\\".\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Der Schmied Griswold kennt sich bei Waffen und Rüstungen extrem gut aus. \"\n\"Wenn Ihr jemals etwas an Euren Sachen auszubessern habt, solltet Ihr auf \"\n\"jeden Fall zu ihm gehen.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham verbringt viel zu viel Zeit hier. Er versucht, seine Sorgen in \"\n\"billigem Bier zu ertränken. Ich würde ihn ja rauswerfen, aber er hat so viel \"\n\"durchgemacht im Labyrinth.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria ist weiser, als es ihre Jugend vermuten lässt, aber ich muss zugeben, \"\n\"dass sie mir auch etwas Angst macht. \\n\"\n\"\\n\"\n\"Na ja, ist ja auch egal. Jedenfalls, wenn Ihr jemals ein paar magische \"\n\"Sachen braucht oder eintauschen wollt, geht zu ihr. Sie hat eine Hütte \"\n\"jenseits des Flusses, und ihre Vorräte sind merkwürdigerweise immer \"\n\"reichlich.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Wenn Ihr mehr über die Vergangenheit unseres Dorfes erfahren wollt, kann \"\n\"Euch der Geschichtenerzähler Cain bestimmt weiterhelfen.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt ist ein Taugenichts und ein kleiner Rumtreiber. Er hatte schon immer \"\n\"ein Talent dafür, sich Ärger einzuhandeln, und es überrascht mich nicht, \"\n\"dass ihm sowas zugestoßen ist. \\n\"\n\"\\n\"\n\"Hat sich wahrscheinlich irgendwo rumgetrieben, wo er nichts zu suchen hatte. \"\n\"Er tut mir ja schon irgendwie leid, aber sein Bekanntenkreis gefällt mir \"\n\"überhaupt nicht.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin ist ein guter Mensch - und mit Sicherheit der großzügigste der Stadt. \"\n\"Er kümmert sich immer um die Bedürfnisse der anderen, dabei hat er selbst \"\n\"immer genug Sorgen.\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, meine Kellnerin? Sie wäre schon vor langer Zeit von hier geflohen, \"\n\"wenn da nicht noch ihre Großmutter wäre. Sie würde sie niemals im Stich \"\n\"lassen. \\n\"\n\"\\n\"\n\"Ich habe ihr sogar angeboten, mich um die alte Dame zu kümmern und sie \"\n\"praktisch angefleht, sich doch in Sicherheit zu bringen, aber zwecklos.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Was fehlt Euch? Braucht Ihr Hilfe?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Ich habe eine sehr interessante Entdeckung gemacht. Im Gegensatz zu uns \"\n\"können sich die Geschöpfe des Labyrinthes ohne die Hilfe von Tränken oder \"\n\"Magie selbst heilen! Wenn Ihr also gegen eines dieser Monster kämpft, \"\n\"vergewissert Euch, dass es auch wirklich tot ist, sonst regeneriert es sich, \"\n\"und Euer Kampf war umsonst.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Bevor sie übernommen wurde von...na ja, was immer da unten lauert, war die \"\n\"Kathedrale ein Ort des Lernens. Es gibt dort heute noch viele Bücher. Wenn \"\n\"Ihr welche findet, solltet Ihr sie auf jeden Fall lesen, denn sie enthalten \"\n\"viele Hinweise darauf, was im Labyrinth vor sich geht.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold weiß so viel über die Kunst des Krieges wie ich über die Kunst des \"\n\"Heilens. Er ist ein gerissener Kaufmann, aber seine Arbeit ist \"\n\"unvergleichlich. Na ja, vielleicht auch deshalb, weil es keinen anderen \"\n\"Schmied mehr gibt, mit dessen Arbeit man sie vergleichen könnte...\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain ist ein wahrer Freund und ein Weiser. Er hat eine riesige Bibliothek \"\n\"und besitzt die angeborene Gabe, die wahre Natur vieler Dinge zu erkennen. \"\n\"Wenn Ihr jemals Fragen habt, solltet Ihr zu ihm gehen.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Selbst meine Kräfte reichen nicht aus, um Farnham völlig zu heilen. Oh ja, \"\n\"ich konnte seinen Körper wieder in Ordnung bringen, aber sein Geist und sein \"\n\"Verstand liegen jenseits meiner Möglichkeiten.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Ich benutze zwar eine gewisse Art von Magie, um die Tränke und Elixiere zu \"\n\"brauen, die ich hier lagere. Aber Adria ist eine echte Hexe. Sie scheint \"\n\"niemals zu schlafen, und sie hat immer Zugang zu seltenen Büchern und \"\n\"Artefakten. Ich vermute, ihre Hütte ist viel mehr als der Holzschuppen, nach \"\n\"dem sie aussieht. Aber irgendwie habe ich es nie geschafft, hineinzukommen.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Der arme Wirt. Ich habe für ihn getan, was ich konnte, aber ich weiß genau, \"\n\"dass er das Holzbein hasst, das ich an seinem Beinstumpf anbringen musste. \"\n\"Seine Wunden waren einfach grausam. Niemand - und schon gar kein Kind, wie \"\n\"er es war - sollte jemals so etwas erleiden müssen.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Ich verstehe wirklich nicht, warum Ogden hier in Tristram bleibt. Er bekommt \"\n\"leicht nervöse Zustände, aber er ist ein intelligenter und unternehmerischer \"\n\"Mann, der überall gut über die Runden käme, egal, wo er hinginge. Ich \"\n\"vermute, er hat Angst wegen der vielen Morde in der Umgebung, oder \"\n\"vielleicht will seine Frau hier einfach nicht weg.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogdens Kellnerin ist ein süßes Mädchen. Ihre Großmutter ist ziemlich krank \"\n\"und leidet an Wahnvorstellungen. \\n\"\n\"\\n\"\n\"Sie sagt zwar, es seien Visionen, aber dafür gibt es keinerlei Beweise.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Einen guten Tag! Womit kann ich Euch dienen?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Meine Großmutter hat im Traum gesehen, dass Ihr kommen und mit mir reden \"\n\"würdet. Sie hat Visionen, müsst Ihr wissen, und kann in die Zukunft sehen.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Diese Frau am Stadtrand ist eine Hexe! Sie scheint ja ganz nett zu sein, und \"\n\"ihr Name Adria klingt ja auch ganz angenehm, aber ich habe trotzdem Angst \"\n\"vor ihr. \\n\"\n\"\\n\"\n\"Man müsste schon sehr mutig sein, so wie Ihr, um nachzusehen, was sie da \"\n\"draußen überhaupt so macht.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Auf unseren Schmied sind die Leute hier in Tristram besonders stolz. Er ist \"\n\"nicht nur ein meisterlicher Handwerker, der schon viele Wettbewerbe seiner \"\n\"Zunft gewonnen hat, sondern er wurde sogar von König Leoric selbst gelobt - \"\n\"möge seine Seele in Frieden ruhen. Griswold ist außerdem ein großer Held - \"\n\"fragt nur mal Cain!\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain war schon immer der Geschichtenerzähler in Tristram, seit ich denken \"\n\"kann. Er weiß so viel und er kann Euch fast alles über fast jedes Thema \"\n\"berichten.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham ist ein Säufer, der seinen Bauch mit Fusel füllt und allen anderen \"\n\"die Ohren mit Unfug vollstammelt. \\n\"\n\"\\n\"\n\"Ich weiß, dass er sowohl Ogden als auch Pepin leid tut, aber mich frustriert \"\n\"es sehr, ihn jeden Abend immer weiter in den Rausch abrutschen zu sehen.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin hat meiner Großmutter das Leben gerettet, und ich weiß, dass ich das \"\n\"niemals wieder gutmachen kann. Seine Fähigkeit, alle Krankheiten zu heilen, \"\n\"ist stärker als das mächtigste Schwert und dabei geheimnisvoller als jeder \"\n\"nur erdenkliche Zauberspruch. Wenn Ihr jemals einen Heiler nötig habt, geht \"\n\"zu Pepin.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Ich bin zusammen mit Wirts Mutter Canace aufgewachsen. Obwohl sie nur leicht \"\n\"verletzt wurde, als die Dämonen ihn entführt haben, hat sie sich davon nie \"\n\"wieder erholt. Ich glaube, sie ist an gebrochenem Herzen gestorben. Wirt hat \"\n\"sich zu einem hartgesottenen Jungen entwickelt, der nur durch den Schweiß \"\n\"anderer reich werden will. Ich weiß ja, dass er viel durchgemacht und \"\n\"Schrecken gesehen hat, die ich mir nicht mal ausmalen könnte, aber etwas von \"\n\"dieser Finsternis schwebt immer noch über ihm.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden und seine Frau haben Großmutter und mich bei sich aufgenommen, und sie \"\n\"lassen mich sogar ein paar Goldstücke im Gasthof verdienen. Ich schulde \"\n\"ihnen so viel, und ich wünsche mir nichts sehnlicher, als ihnen eines Tages \"\n\"helfen zu können, ein großes Hotel im Osten aufzumachen.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Was kann ich für Euch tun?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Wenn Ihr auf der Suche nach der richtigen Waffe seid, kann ich Euch einiges \"\n\"erzählen. Nehmt zum Beispiel eine normale Schlagwaffe, etwa eine Keule. \"\n\"Gegen die meisten dieser Untoten da unten ist die einfach Gold wert; es gibt \"\n\"zum Beispiel nichts Besseres, um knochige kleine Skelette zu zertrümmern.\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Die Streitaxt? Ja, das ist eine richtig gute Waffe, ausgewogen gegen jeden \"\n\"Gegner. Seht, wie sie die Luft durchschneidet, und jetzt stellt Euch mal \"\n\"einen schönen, dicken Dämonenkopf genau in der Flugbahn vor. Denkt daran, \"\n\"dass sie sich nur langsam schwingen lässt, aber wenn sie trifft ... hmmmm.\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Schaut Euch nur die Schneide an, die Balance... Ein Schwert ist in den \"\n\"richtigen Händen und gegen den richtigen Gegner die beste aller Waffen. Zwar \"\n\"findet auch die schärfste Klinge an Untoten nur wenig zum Schneiden oder \"\n\"Durchbohren, doch gegen lebende, atmende Gegner gibt es nichts Besseres.\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Eure Waffen und Rüstungen werden bald schon Spuren Eurer Kämpfe gegen die \"\n\"Finsternis zeigen. Wenn Ihr sie zu mir bringt, kann ich sie - mit ein wenig \"\n\"Arbeit und einem schönen, heißen Schmiedefeuer - wieder in Höchstform \"\n\"bringen.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Während ich das Metall und meine Werkzeuge im wahrsten Sinne des Wortes von \"\n\"Karawanen am Stadtrand hereinschmuggeln muss, scheint diese Hexe Adria immer \"\n\"alles zu haben, was sie braucht. Wenn ich auch nur einen Funken ihrer \"\n\"magischen Fähigkeiten hätte, könnte ich einfach unglaubliche Sachen \"\n\"herstellen.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian ist ein nettes Mädchen. Schade, dass es ihrer Großmutter so schlecht \"\n\"geht, sonst würde ich sie beide mit einer der Handelskarawanen hier \"\n\"rausbringen lassen.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Manchmal denke ich, Cain redet zuviel. Aber das ist wohl seine Bestimmung. \"\n\"Wenn ich mit Stahl so gut umgehen könnte wie er mit Worten, würde ich jeden \"\n\"Tag ein Kettenhemd schmieden, das sogar der Kaiser von China tragen würde!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Ich war mit Farnham zusammen in jener Nacht, als Lazarus uns ins Labyrinth \"\n\"geführt hat. Ich habe den Erzbischof nie wiedergesehen und ich hätte wohl \"\n\"selbst nicht überlebt, wenn Farnham nicht bei mir gewesen wäre. Ich \"\n\"befürchte, der Angriff hat seine Seele so verkrüppelt, wie ein anderer mein \"\n\"Bein. Ich kann seinen Kampf jetzt nicht für ihn austragen, aber wenn ich es \"\n\"könnte, würde ich es sofort tun.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Ein guter Mann, der die Bedürfnisse der anderen über seine eigenen stellt. \"\n\"Ihr werdet niemanden in Tristram - oder auch anderswo - finden, der etwas \"\n\"Schlechtes über den Heiler sagen würde.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Dieser Kerl wird noch mal richtigen Ärger bekommen... oder besser gesagt, \"\n\"wieder mal. Ich habe versucht, ihm eine Lehre hier schmackhaft zu machen, \"\n\"damit er ein ehrliches Gewerbe erlernen könnte, aber er zieht es vor, das \"\n\"schnelle Geld zu machen, indem er mit Waren zweifelhafter Herkunft handelt. \"\n\"Kann ich ihm nicht mal verübeln, nach dem, was er durchgemacht hat, aber ich \"\n\"wünschte mir, er wäre wenigstens etwas vorsichtiger.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Der Gastwirt hat nur wenige Gäste und kann nicht viel verdienen. Er kommt \"\n\"gerade so über die Runden, indem er den gelegentlichen Besuchern der Stadt \"\n\"Nahrung und Unterkunft bietet, aber statt ihn zu bezahlen, verdrückt sich \"\n\"die Hälfte seiner Kunden einfach im Schutze der Nacht. Doch ohne seine \"\n\"Getreidevorräte und das getrocknete Fleisch, das er in seinem Keller lagert, \"\n\"wären die meisten von uns schon im ersten Jahr verhungert, als die Dämonen \"\n\"das ganze Land hier niedergetrampelt haben.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Kann man hier nicht mal in Ruhe einen trinken?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"Das Mädel, das die Drinks serviert? Oh ja, die ist hübsch, Und tierisch nett.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Warum tut diese alte Krähe nicht mal was zur Abwechslung? Klar, die hat \"\n\"ihren ganzen Kram und so, aber ich sag Euch was: Sie ist unnatürlich. Ich \"\n\"habe sie nie essen oder trinken sehen. Und man kann einfach niemanden \"\n\"vertrauen, der nicht wenigstens ab und zu mal ein wenig trinkt...\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain ist nicht der, für den er sich ausgibt. Klar, er kann prima Geschichten \"\n\"erzählen... manche sind richtig schaurig oder lustig. Aber ich glaube, er \"\n\"weiß mehr, als er weiß, dass er weiß, weißt Du...?\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Der gute alte Griswold. Ich liebe ihn wie einen Bruder! Wir haben \"\n\"zusammen gekämpft, weißt Du, damals, als wir... Lazarus... Lazarus... \"\n\"LAZARUS!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hihi, ich mag Pepin. Er gibt sich wirklich Mühe, weißt Du? Du musst ihn \"\n\"unbedingt kennenlernen. Sehr lieber Kerl, wo doch die Leute immer Hilfe von \"\n\"ihm wollen. He, das könnte Dir ja auch mal passieren, als Held und so. Ich \"\n\"war früher auch mal ein Held, weißt Du?\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt hat sogar noch mehr Probleme als ich, und ich kenne mich mit Problemen \"\n\"nun wirklich gut aus. Weißt Du, der Kleine zeigt zwar die harte Schale, aber \"\n\"er war da, verstehst Du? Hat sein Bein da unten verloren. Muss auf 'nem \"\n\"verdammten Stück Holz rumlaufen. Verdammt traurige Geschichte...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden ist der Beste hier in der Stadt. Ich glaube, seine Frau mag mich nicht \"\n\"besonders, aber solange sie die Krüge immer schön voll macht, finde ich sie \"\n\"ganz sympathisch. Ich schein' irgendwie mehr Zeit mit Ogden zu verbringen \"\n\"als die meisten anderen hier, aber er ist ja auch wirklich gut zu mir.\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Ich will Dir mal was sagen, weil ich mich mit diesen Sachen ja auskenne. Ist \"\n\"mein Spezialgebiet. Das hier ist einfach das Beste. Das Allerallerbeste. Das \"\n\"andere Bier ist einfach ungenießbar seit diese ...Hunde....\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Niemand hört mi-HICKS-mir zu. Irgendwo - ich weiß nicht mehr genau, wo, aber \"\n\"irgendwo unter dieser Kirche liegt ein Riiiesenhaufen Gold. Glänzt und \"\n\"schimmert und wartet nur darauf, dass ihn jemand mitnimmt.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Ich weiß, Du hast so Deine eigenen Vorstellungen, und ich weiß auch, dass Du \"\n\"mir nicht glauben wirst, aber ich sag's Dir trotzdem: Deine Waffe da ist \"\n\"völlig nutzlos gegen diese riesigen Monster! Ist mir egal, was Griswold \"\n\"sagt, heute gibt es keine echte Qualität mehr, nicht wie in den guten alten \"\n\"Zeiten!\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Wenn ich Du wäre... bin ich ja nicht, aber wenn ich's wäre...dann würde ich \"\n\"den ganzen Kram verkaufen, den Du da hast, und von hier verschwinden. Der \"\n\"Junge da oben, der hat immer was Gutes, aber Du musst ihm sogar Geld dafür \"\n\"geben, dass er Dir überhaupt zeigt, was er hat.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Ah, eine dürstende Seele, die nach Antworten sucht...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Weisheit muss man sich verdienen... man bekommt sie nicht geschenkt. Wenn \"\n\"Ihr ein Buch des Wissens findet, verschlingt seine Worte. Solltet Ihr schon \"\n\"mystisches Wissen um die Geheimnisse gesammelt haben, die in dem Werk \"\n\"beschrieben werden, so bedenket - auch ein Meister kann stets noch \"\n\"dazulernen.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Die größte Macht ist oft die, die am schnellsten verlischt. Ihr werdet auf \"\n\"Eurem Weg uralte Worte der Macht finden, die auf Schriftrollen aus Pergament \"\n\"gebannt wurden. Ihre große Stärke liegt darin, dass sowohl Zauberlehrling \"\n\"wie auch Meistermagier sie mit gleicher Leichtigkeit und Gewalt einsetzen \"\n\"können. Ihre große Schwäche hingegen ist, dass Ihr sie niemals im Gedächtnis \"\n\"halten könnt, sondern sie jedesmal laut verlesen müsst. Wisset auch, dass \"\n\"Ihr jede Schriftrolle nur ein einziges Mal lesen könnt, setzt sie also mit \"\n\"Bedacht ein.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Obwohl die Hitze der Sonne grenzenlos ist, stellt doch die bescheidene \"\n\"Flamme einer einzelnen Kerze eine weitaus größere Gefahr dar. Ohne den \"\n\"passenden Fokus lässt sich keine Energie einsetzen, egal wie groß. Viele \"\n\"Zaubersprüche lassen sich in magische Stäbe binden, oft sogar mehrfach. Ich \"\n\"habe die Fähigkeit, ihre Kräfte zu erneuern - doch Ihr könnt davon ausgehen, \"\n\"dass alles seinen Preis hat.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Die Summe unseres Wissens ist in der Summe der Menschen. Solltet Ihr ein \"\n\"Buch oder eine Schriftrolle finden, die Ihr nicht entziffern könnt, kommt \"\n\"einfach zu mir. Wenn ich etwas damit anfangen kann, werde ich mein Wissen \"\n\"mit Euch teilen.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Für einen Mann, der nur Eisen kennt, gibt es keine größere Magie als den \"\n\"Stahl. Griswold, der Schmied, ist ein größerer Zauberer, als er selbst weiß. \"\n\"Seine Fähigkeit, Feuer und Metall zu verschmelzen, ist einzigartig im ganzen \"\n\"Land.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Korruption hat die Stärke des Betruges, aber die Unschuld bezieht ihre Kraft \"\n\"aus der Reinheit. Die junge Gillian hat ein reines Herz und kümmert sich \"\n\"mehr um die Bedürfnisse ihrer Großmutter als um ihre eigenen Wünsche. Sie \"\n\"fürchtet sich vor mir, aber nur, weil sie mich nicht versteht.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Eine Kiste, die man in der Dunkelheit öffnet, enthält dadurch keinen \"\n\"größeren Schatz, als wenn man sie bei Licht aufmacht. Der \"\n\"Geschichtenerzähler Cain ist ein Rätsel, aber nur für diejenigen, die nicht \"\n\"hinschauen. Sein Wissen um die dunklen Dinge, die unter der Kathedrale \"\n\"lauern, ist größer, als er sich sogar selbst eingestehen mag.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Je mehr Vertrauen Ihr in einen Menschen setzt, um so größer kann die \"\n\"Enttäuschung sein. Farnham hat seine Seele verloren, aber nicht an \"\n\"irgendeinen Dämon.. Sie starb, als er mit ansehen musste, wie seine Nachbarn \"\n\"und Freunde von Erzbischof Lazarus hintergangen wurden. Er besitzt Wissen, \"\n\"das Euch nützen könnte, doch Ihr müsst sorgsam Tatsachen von \"\n\"Wahnvorstellungen trennen.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Die Hand, das Herz und der Verstand können Wunder vollbringen, wenn sie \"\n\"harmonisch zusammenarbeiten. Der Heiler Pepin vermag in einen Körper \"\n\"hineinzuschauen, wie nicht einmal ich es kann. Zu seiner Fähigkeit, den \"\n\"Kranken und Verwundeten zu helfen, gesellen sich noch wertvolle Kenntnisse \"\n\"auf dem Gebiet der Tränke und Elixiere Er ist einer der besten Verbündeten, \"\n\"die Ihr in Tristram haben könnt.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Es gibt vieles in der Zukunft, von dem wir noch nichts wissen können. Aber \"\n\"wenn es kommt, werden es unsere Kinder sein, die damit fertig werden müssen. \"\n\"Auf der Seele von Wirt, dem kleinen Rumtreiber, lasten dunkle Schatten, aber \"\n\"er ist deshalb noch lange keine Gefahr für diese Stadt oder ihre Bewohner. \"\n\"Durch seine Verbindungen und seine heimlichen Geschäfte mit der Unterwelt \"\n\"und den geheimen Gilden hat er Zugang zu Objekten, die man ansonsten in \"\n\"Tristram nicht so leicht bekommt. Seine Methoden kann man vielleicht \"\n\"kritisieren, aber Wirt kann Euch trotzdem eine wertvolle Hilfe sein in Eurem \"\n\"Kampf gegen die Mächte der Finsternis.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Wände aus Lehm mit einem Dach aus Stroh machen alleine noch kein Zuhause \"\n\"aus. Der Gastwirt Ogden ist für diese Stadt wichtiger, als vielen überhaupt \"\n\"bewusst ist. Er bietet Gillian und ihrer Großmutter Schutz und Obdach, hält \"\n\"Farnhams schwachen Lebensfunken am Glimmen und erinnert alle, die noch in \"\n\"der Stadt geblieben sind, daran, wie es in Tristram früher einmal war. Seine \"\n\"Kneipe und die einfachen Vergnügungen, die man sich da noch leisten kann, \"\n\"sind ein schwacher Nachhall des früheren Lebens, an das sich die Menschen \"\n\"hier noch erinnern. Diese Erinnerungen sind es, die ihnen immer noch \"\n\"Hoffnung auf Euren Erfolg geben.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... hier drüben...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Nicht jeder in Tristram hat Verwendung oder Kundschaft für jedes Teil, das \"\n\"Du im Labyrinth finden wirst. Nicht mal ich, so schwer das auch zu glauben \"\n\"sein mag. \\n\"\n\"\\n\"\n\"Manchmal wirst nur Du etwas damit anfangen können.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Hör nicht auf alles, was der Besoffene Dir erzählt. Die zahllosen Bierchen \"\n\"haben seinen Blick und seinen Verstand getrübt.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Falls Du es noch nicht bemerkt hast, ich kaufe nichts aus Tristram. Ich bin \"\n\"Importeur für Qualitätswaren. Wenn Du Deinen Müll verscherbeln willst, musst \"\n\"Du Dich schon an Griswold, Pepin oder an Adria wenden, diese Hexe. Ich bin \"\n\"sicher, die reißen Dir alles aus den Händen, was Du ihnen anschleppst.\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Ich schätze, ich verdanke dem Schmied mein Leben - oder zumindest das, was \"\n\"davon noch übrig ist. Klar, Griswold hat mir eine Lehre in seiner Schmiede \"\n\"angeboten, und er ist ja auch ein ganz netter Kerl, aber da würde ich nie \"\n\"genug Geld verdienen, um... na ja, sagen wir mal, ich habe ganz präzise \"\n\"Zukunftspläne, für die ich eine größere Geldsumme benötige.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Wenn ich ein paar Jährchen älter wäre, würde ich sie mit allen Reichtümern \"\n\"überschütten, die ich auftreiben könnte. Und glaub mir, ich komme an \"\n\"ziemlich ausgefallene Sachen ran, wenn ich will! Gillian ist ein wunderbares \"\n\"Mädchen, das Tristram verlassen sollte, sobald es gefahrlos möglich ist. \"\n\"Hmmm... vielleicht nehme ich sie mit, wenn ich gehe.\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain weiß zuviel. Er macht mir Höllenangst - mehr noch als diese Frau auf \"\n\"der anderen Seite des Flusses. Er erzählt mir dauernd, was für ein Glück ich \"\n\"habe, noch am Leben zu sein, und dass meine Geschichte in den Legenden \"\n\"vorhergesagt worden sei. Manchmal glaube ich, sein geistiger Sattel ist ein \"\n\"bisschen vom Pferd gerutscht.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - tja, da haben wir mal einen Mann mit richtig ernsten Problemen. \"\n\"Und ich bin Fachmann, wenn es um ernste Probleme geht. Er hat der Integrität \"\n\"eines einzigen Mannes zu sehr vertraut, und Lazarus hat ihn mitten in die \"\n\"Tore der Hölle geführt. Ich weiß genau, wie es da unten aussieht, also \"\n\"erzähl mir nichts vom \\\"Ausrotten des Bösen, das da unten haust\\\" - pass \"\n\"einfach nur auf Deine Beine auf.\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Solange keine Teile neu an Deinem Körper befestigt werden müssen, ist der \"\n\"alte Pepin genau der Richtige. \\n\"\n\"\\n\"\n\"Hätte ich damals ein paar seiner Tränke dabei gehabt, hätte ich vielleicht \"\n\"noch beide Beine.\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria macht mir richtig Angst. Klar, Cain ist ziemlich unheimlich mit seinen \"\n\"Geschichten über die Vergangenheit, aber Adria... die kann in Deine \"\n\"Vergangenheit reingucken! Und sie bekommt irgendwie immer genau das, was sie \"\n\"will. Adria kommt an mehr Sachen ran, als früher während des Herbstfestes \"\n\"durch die Tore des Königsbazars geliefert wurden.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden ist ein Idiot, dass er hierbleibt. Ich könnte ihn zu einem sehr \"\n\"zivilen Preis aus der Stadt bringen, aber er besteht darauf, sein Glück hier \"\n\"mit diesem blöden Gasthof zu versuchen. Na ja, zumindest hat Gillian dadurch \"\n\"einen Arbeitsplatz, und seine Frau Garda macht einen prima Hirtenkuchen.\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Jenseits der Halle der Helden liegt die Knochenkammer. Ewiger Tod erwartet \"\n\"den Frevler, der die Schätze aus dieser Kammer zu stehlen versucht. So \"\n\"spricht der Herr des Terrors, und so steht es geschrieben.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...und so wartet Tapferstahl hinter dem Blutportal und jenseits des \"\n\"Flammengewölbes auf den Tag, da der Held des Lichtes wieder erwacht...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Ich kann sehen, was niemand kann.\\n\"\n\"Milchiger Blick, kein Auge dann.\\n\"\n\"Wenn sie sich umdrehn, sind sie fort.\\n\"\n\"Ihr heimlich Lied flüstert der Ort.\\n\"\n\"Dann seht auch Ihr, was nicht sein darf.\\n\"\n\"Wo Licht sein soll, der Schatten warf.\\n\"\n\"Aus Dunkel, wild wie ein Berserker,\\n\"\n\"unten in der Blinden Kerker.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Die Waffenkammern der Hölle sind das Zuhause des Blutfürsten. In seinem \"\n\"Kielwasser treiben die verstümmelten Leichen von Tausenden. Engel und \"\n\"Menschen gleichermaßen wurden reihenweise niedergemäht, als Opfergaben für \"\n\"die Finsteren Herrscher, die es nur nach einem dürstet - nach Blut.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Merket auf und vernehmt die Worte der Wahrheit, denn sie sind das letzte \"\n\"Vermächtnis der Horadrim. Genau in diesem Moment tobt ein Krieg, jenseits \"\n\"der uns bekannten Dimensionen, zwischen den Fürstentümern des Himmelreiches \"\n\"und den chaotischen Abgründen der brennenden Hölle. Dieser Krieg wird der \"\n\"Große Zwist genannt, und er tobt und wütet schon länger, als irgendein Stern \"\n\"am Firmament leuchtet. Keine Seite hat lange einen echten Vorteil in diesem \"\n\"Zwist, in dem die Kräfte des Lichts und der Finsternis beharrlich um die \"\n\"Macht über die gesamte Schöpfung kämpfen.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Merket auf und vernehmt die Worte der Wahrheit, denn sie sind das letzte \"\n\"Vermächtnis der Horadrim. Als der Ewige Zwist zwischen Himmelreich und Hölle \"\n\"auf das Gebiet der Sterblichen übergriff, nannte man ihn den Sündenkrieg. \"\n\"Engel und Dämonen wandeln verkleidet unter den Menschen, kämpfen im \"\n\"Verborgenen, versteckt vor den Blicken der Sterblichen. Einige wagemutige, \"\n\"mächtige Sterbliche haben sich sogar der einen oder anderen Seite \"\n\"angeschlossen und so den Verlauf des Sündenkrieges mit beeinflusst.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Merket auf und vernehmt die Worte der Wahrheit, denn sie sind das letzte \"\n\"Vermächtnis der Horadrim. Vor beinahe dreihundert Jahren wurde bekannt, dass \"\n\"die Drei Erzübel der Hölle auf mysteriöse Weise in unsere Welt gelangt \"\n\"waren. Die drei Brüder verwüsteten jahrzehntelang die Länder des Ostens, und \"\n\"die Menschheit konnte nur zitternd zu ihnen aufsehen. Heimlich wurde von \"\n\"einer Gruppe Magier unser Orden gegründet, die Horadrim, mit dem Zweck, die \"\n\"drei Erzübel ein für allemal zu fangen. \\n\"\n\"\\n\"\n\"Die Gründerväter der Horadrim schafften es auch wirklich, zwei der drei \"\n\"Brüder in mächtigen Artefakten einzuschließen, den sogenannten \"\n\"Seelensteinen, die sie anschließend tief unten im Sand der verlassenen \"\n\"Wüsten des Ostens vergruben. Doch das dritte Erzübel entkam und floh nach \"\n\"Westen, verfolgt von vielen Horadrim. Dieser Dämon, bekannt als Diablo, \"\n\"Fürst des Terrors, wurde schließlich auch gefangen, seine Essenz in einen \"\n\"Seelenstein eingesperrt und in diesem Labyrinth versteckt. \\n\"\n\"\\n\"\n\"Hütet Euch, dass niemand den Seelenstein finde, der nicht dem Orden \"\n\"angehört! Wenn Diablo wieder freikäme, würde er sich sofort einen neuen \"\n\"Körper suchen, wahrscheinlich erst einmal einen schwachen, den er leicht \"\n\"kontrollieren kann, etwa einen alten Mann oder ein Kind.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Und so geschah es, dass in den Tiefen der Hölle eine Revolution stattfand, \"\n\"bekannt als das Dunkle Exil. Die Geringen Übel stürzten die drei Erzübel und \"\n\"verbannten ihre geistigen Formen in das Reich der Sterblichen. Kaum waren \"\n\"die drei Fürsten der Finsternis fort, kämpften in der Hölle die Dämonen \"\n\"Belial (der Herr der Lügen) und Azmodan (der Herr der Sünden) um die \"\n\"Vorherrschaft. Die gesamte Hölle spaltete sich in diese beiden Lager auf, \"\n\"während die vereinten Kräfte des Lichts konstant auf die Pforten einstürmten.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Viele Dämonen reisten in die Welt der Sterblichen, um die drei Brüder zu \"\n\"suchen. Doch jedem dieser Dämon folgten auch Engel in unsere Welt, die ihn \"\n\"in den riesigen Städten des Ostens jagten. Die Engel verbündeten sich dazu \"\n\"mit einem Orden sterblicher Magier, den Horadrim, die bald exzellente \"\n\"Dämonenjäger wurden. Doch dabei machten sie sich auch mächtige Feinde in der \"\n\"Unterwelt...\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"So geschah es, dass die drei Erzübel in geistiger Form in das Reich der \"\n\"Sterblichen verbannt wurden. Und nachdem sie jahrzehntelang das Chaos im \"\n\"Osten verbreitet hatten, wurden sie von dem verfluchten Orden der \"\n\"sterblichen Horadrim gejagt. Die Horadrim benutzten sogenannte Seelensteine, \"\n\"um die Essenz von Mephisto, dem Fürsten des Hasses, und von Baal, dem Herrn \"\n\"der Vernichtung, gefangenzunehmen und einzusperren. Der Jüngste der \"\n\"Gebrüder, Diablo, der Fürst des Terrors, entkam in den Westen. \\n\"\n\"\\n\"\n\"Doch schließlich setzten die Horadrim auch Diablo in einem Seelenstein \"\n\"gefangen, und sie vergruben ihn unter einer alten, vergessenen Kathedrale. \"\n\"Dort ruht der Fürst des Terrors nun und wartet auf die Zeit seiner \"\n\"Wiedergeburt. Wisset, dass er wiederkehren wird in einem Körper voller \"\n\"Jugend und Macht - einem Körper, der unschuldig und leicht zu kontrollieren \"\n\"ist. Dann wird er sich erheben, seine Brüder zu befreien und das Land aufs \"\n\"Neue mit der Fackel des Sündenkrieges in Brand zu stecken.\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Lob und Ruhm sei Diablo, dem Fürsten des Terrors und Überlebenden des \"\n\"Dunklen Exils. Als er aus seinem langen Schlummer erwachte, erzählte mir \"\n\"mein Herr und Meister von Geheimnissen, die nur wenigen Sterblichen je \"\n\"bekannt waren. Er erzählte mir von den Fürstentümern des Himmelreiches und \"\n\"den Abgründen der brennenden Hölle, und von einem ewigen Krieg zwischen den \"\n\"beiden. Er nannte mir auch die Mächte, die diesen Zwist ins Reich der \"\n\"Menschheit brachten. Mein Herr nannte die Schlacht um diese Welt und alle, \"\n\"die auf ihr leben, den Sündenkrieg...\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Ruhm und Ehre sei Diablo, dem Fürsten des Terrors und Anführer der Drei. \"\n\"Mein Gebieter erzählte mir von seinen beiden Brüdern, Mephisto und Baal, die \"\n\"schon vor langer Zeit auf diese Welt verbannt worden sind. Mein Herr will in \"\n\"Ruhe abwarten, seine furchterregenden Kräfte sammeln und dann seine \"\n\"gefangenen Brüder aus ihrem Gefängnis unter dem Wüstensand des Ostens \"\n\"befreien. Und sobald mein Gebieter erst seine Brüder befreit hat, wird der \"\n\"Sündenkrieg wieder unter der Peitsche der Drei zu neuen Höhen getrieben.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Gebete und Opfer für Diablo, den Fürsten des Terrors und Zerstörer der \"\n\"Seelen! Als ich meinen Herren aus seinem Schlaf weckte, versuchte er, sofort \"\n\"einen menschlichen Körper zu übernehmen. Er probierte, von König Leoric \"\n\"Besitz zu ergreifen, doch mein Gebieter war noch zu geschwächt von seiner \"\n\"langen Verbannung. Er braucht einen unschuldigen und einfachen Anker in \"\n\"dieser Welt, und so fand er, dass der Junge Albrecht die ideale Besetzung \"\n\"für diese Rolle sei. Und während der 'gute' König Leoric von Diablos \"\n\"erfolglosem Versuch der Übernahme in den Wahnsinn getrieben wurde, entführte \"\n\"ich seinen Sohn Albrecht und brachte ihn zu meinem Herrn. Nun warte ich \"\n\"darauf, dass Diablo mich ruft, und hoffe, dass ich meinen gerechten Lohn \"\n\"erhalte, wenn er letztendlich als Beherrscher dieser Welt auf dem Thron \"\n\"sitzt.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Dem Himmel sei Dank, Ihr seid wieder da!\\n\"\n\"Vieles hat sich verändert, seit Ihr hier gewohnt habt, mein Freund. Alles \"\n\"war friedlich, bis die Dunklen Reiter kamen und unser Dorf zerstörten. Viele \"\n\"von uns starben, bevor sie sich wehren konnten. Und die, die zu ihren Waffen \"\n\"eilten, wurden umgebracht oder verschleppt, als Sklaven - oder Schlimmeres. \"\n\"Die Kirche am Dorfrand wurde entweiht und wird jetzt für dunkle Rituale \"\n\"missbraucht. Die Schreie, die man nachts hört, sind unmenschlich, doch \"\n\"vielleicht haben einige unserer Freunde und Nachbarn ja doch noch überlebt. \"\n\"Folgt dem Weg, der zwischen meinem Gasthof und der Schmiede entlang führt, \"\n\"dann kommt Ihr zur Kirche. \\n\"\n\"\\n\"\n\"Rettet, wen Ihr retten könnt, und vielleicht kann ich Euch schon mehr sagen, \"\n\"wenn wir uns das nächste Mal wiedersehen. Viel Glück.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Haltet an Eurer Suche fest. Einen verlorenen Schatz zu finden ist nicht \"\n\"leicht. Einen versteckten Schatz noch weniger. Ich gebe Euch das mit auf den \"\n\"Weg: Lasst Euch bei Eurer Suche nicht vom Zahn der Zeit verwirren.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Ein was?! So eine Torheit. Es gibt keinen vergrabenen Schatz hier in \"\n\"Tristram. Lasst mich das sehen!! Ah seht, diese Zeichnungen sind ungenau. \"\n\"Sie passen überhaupt nicht zu unserem Dorf. Ich würde mich lieber damit \"\n\"beschäftigen, was unter der Kathedrale liegt, und nicht damit, was unter \"\n\"unserem Ackerboden liegt.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Ich habe wirklich keine Zeit um über irgendeine Karte zu besprechen, die Ihr \"\n\"sucht. Ich habe viele kranke Menschen, die meine Hilfe brauchen und Eure \"\n\"ebenso.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Der einst stolze Izual ist tief unter der Oberfläche dieser Welt gefangen. \"\n\"Seiner Ehre beraubt und sein Antlitz verwandelt. Er ist in ewiger Qual \"\n\"gefangen, gezwungen dasjenige zu verbergen, das ihn befreien könnte.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Ich wette, Wirt hat Euch kommen sehen und eine Schau abgezogen, damit er \"\n\"sich später über Euch lustig machen kann, wenn Ihr im Dorf herumlauft und \"\n\"Eure Nase in den Dreck steckt. Ich würde es ignorieren.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Es gab eine Zeit, in der diese Stadt ein häufiger Zwischenstopp für Reisende \"\n\"aus nah und fern war. Seitdem hat sich viel verändert. Aber versteckte \"\n\"Höhlen und vergrabene Schätze sind gängige Fantasien jedes Kindes. Wirt \"\n\"frönt selten jugendlichen Spielen. Es könnte also nur seine Einbildung sein.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Hör mal, komm mal her. Ich weiß nicht, ob Du weißt, was ich weiß, aber weißt \"\n\"Du, dass das eine Karte ist? Eine richtige Landkarte.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Meine Großmutter erzählt mir oft Geschichten über die seltsamen Kräfte, die \"\n\"den Friedhof außerhalb der Kirche bewohnen. Und es könnte Dich \"\n\"interessieren, eine davon zu hören. Sie sagte, dass, wenn man die richtige \"\n\"Opfergabe auf dem Friedhof hinterlässt, die Kathedrale betritt, um für die \"\n\"Toten zu beten, und dann wiederkommt, die Opfergabe auf seltsame Weise \"\n\"verändert würde. Ich weiß nicht, ob dies nur das Gerede einer alten kranken \"\n\"Frau ist, aber heutzutage scheint alles möglich zu sein.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Hmmm. Ein gewaltiger und rätselhafter Schatz, sagt Ihr. Mmmm. Ich würde Euch \"\n\"vielleicht das eine oder andere Kleinod abkaufen. Oder besser noch, benötigt \"\n\"Ihr nicht einiges an seltener und teurer Ausrüstung um diese Prüfung zu \"\n\"bestehen?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Also, Du musst der Held sein, über den alle reden. Vielleicht kannst du \"\n\"einem armen, einfachen Bauern aus einer furchtbaren Klemme helfen? Am Rande \"\n\"meiner Plantage, genau südlich von hier, quillt ein abscheuliches Ding aus \"\n\"dem Boden! Ich kann nicht zu meinen Pflanzen oder zu meinen Heuballen, und \"\n\"meine armen Kühe werden hungern. Die Hexe hat mir das hier gegeben und \"\n\"gesagt, dass es dieses Ding aus meinem Acker sprengen würde. Wenn Du es \"\n\"beseitigen könntest, wäre ich Dir ewig dankbar. Ich würde es ja selbst tun, \"\n\"aber jemand muss hier bei den Kühen bleiben...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Ich wusste, dass es nicht so einfach sein kann wie die Hexe behauptet hat. \"\n\"Es ist eine traurige Welt, wenn du noch nicht mal deinen Nachbarn vertrauen \"\n\"kannst.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Ist es weg? Hast du es in den dunklen Schoß des Hades zurückgeschickt, aus \"\n\"dem es gekrochen kam? Du hast was? Oh, erzähl mir nicht, du hast es \"\n\"verloren! Diese Dinger sind nicht billig, weißt du. Du musst es wiederfinden \"\n\"und dann dieses Grauen aus unserem Dorf sprengen.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Ich habe die Explosion von hier aus gehört! Hab vielen Dank, freundlicher \"\n\"Fremdling. Mit diesen ganzen Dingern, die aus dem Boden kommen, Monstern, \"\n\"die die Kirche übernehmen, und so weiter, es sind schwierige Zeiten. Ich bin \"\n\"zwar nur ein armer Bauer, aber hier -- nimm das mit meinem großen Dank.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Oh, solch einen Ärger habe ich ... möglicherweise ... nein, das kann ich dir \"\n\"nicht aufbürden, du hast sicher schon genug Probleme. Vielleicht könntest du \"\n\"zurückkommen, wenn du die Kirche von einigen dieser Kreaturen gesäubert \"\n\"hast ... und ein bisschen Zeit erübrigen, um einem armen Bauern zu helfen?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Waaaah! (schnief) Waaaah! (schnief)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Ich hab Theo verloren! Ich hab meinen besten Freund verloren! Wir haben auf \"\n\"der anderen Seite beim Fluss gespielt, und Theo sagte er will sich das große \"\n\"grüne Ding ansehen. Ich sagte, das sollten wir nicht, aber wir sind da \"\n\"hingeschlichen, und dann kam auf einmal dieser Käfer heraus! Wir sind \"\n\"weggerannt, aber Theo fiel hin und der Käfer packte ihn und nahm ihn weg!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Hast du ihn gefunden? Du musst Theodore finden, bitte! Er ist noch so klein. \"\n\"Er kann nicht auf sich selbst aufpassen! Bitte!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Du hast ihn gefunden! Du hast ihn gefunden! Danke! Oh Theo, haben dir die \"\n\"bösen Käfer Angst gemacht? Hey! Pfui! Da steckt etwas in deinem Fell! Igitt! \"\n\"Komm schon, Theo, lass uns nach Hause gehen! Danke nochmal, Herr Held!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Wir haben lange geschlafen, und die Zeit des Erwachens ist gekommen. Nach \"\n\"unserem langen Schlaf sind wir von großem Hunger erfüllt. Bald, jetzt, \"\n\"werden wir speisen...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Hast du dich amüsiert, kleines Säugetier? Wie erbärmlich. Deine kleine Welt \"\n\"wird keine Herausforderung sein.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Dieser Boden wird besudelt werden, und unsere Brut wird die Felder \"\n\"überrennen, die die Menschen zu Hause nennen. Unsere Ranken werden diese \"\n\"Welt einwickeln, und wir werden am Fleisch ihrer Bewohner schlemmen. Der \"\n\"Mensch wird unser Besitz und unsere Nahrung.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, ich kann dich riechen...du bist in der Nähe! Ganz nah! Ssss...der Geruch \"\n\"von Blut und Angst...wie verlockend...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Und im Jahre des goldenen Lichts wurde es daher verfügt, dass eine große \"\n\"Kathedrale errichtet werde. Der Grundstein dieses heiligen Orts sollte aus \"\n\"dem durchsichtigen Stein Antyrael gemeißelt werden, benannt nach dem Engel, \"\n\"der seine Kräfte mit den Horadrim geteilt hat.\\n\"\n\" \\n\"\n\"In dem Jahr, als sich die Schatten abzeichneten, erbebte die Erde und die \"\n\"Kathedrale zerbrach und stürzte ein. Als der Bau der Katakomben und Burgen \"\n\"begann und die Menschen sich gegen die Verheerungen des Sündenkriegs \"\n\"stellten, wurden die Ruinen wegen der Steine geplündert. Und so geschah es, \"\n\"dass der Grundstein aus den Augen der Menschen verschwand.\\n\"\n\" \\n\"\n\"Der Stein war von dieser Welt -- und von allen Welten -- da das Licht sowohl \"\n\"in allen Dingen als auch jenseits aller Dinge ist. Licht und Einheit sind \"\n\"die Erzeugnisse dieser heiligen Grundfeste, eine Einheit des Zwecks und eine \"\n\"Einheit des Besitzes.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muh.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Ich sagte, Muh.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Schau, ich bin nur eine Kuh, okay?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Schon gut, schon gut. Ich bin nicht wirklich eine Kuh. Ich laufe \"\n\"normalerweise nicht so herum; aber, ich habe zu Hause gesessen und mich um \"\n\"meine eigenen Angelegenheiten gekümmert, als ganz plötzlich diese Käfer & \"\n\"Ranken & Knollen aus dem Fußboden kamen ... es war schrecklich! Wenn ich nur \"\n\"etwas Normales anzuziehen hätte, wäre es nicht so schlimm. Heeey! Könntest \"\n\"du zu meiner Stube zurückgehen und meinen Anzug für mich holen? Den braunen, \"\n\"nicht den grauen, der ist Abendgarderobe. Ich würde es selbst tun, aber ich \"\n\"will nicht, dass mich jemand so sieht. Hier, nimm das, du könntest es \"\n\"brauchen ... um diese Dinger zu töten, die alles überwuchert haben. Du \"\n\"kannst mein Haus nicht verfehlen. Es ist genau südlich von der \"\n\"Flussgabelung ... du weißt schon ... das mit dem überwucherten Gemüsegarten.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Wofür vergeudest du denn noch Zeit? Geh und hol meinen Anzug! Und beeil \"\n\"dich! Die Milchkuh da drüben zwinkert mir ständig zu!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hey, hast du meinen Anzug? Schnell, gib Ihn mir! Diese Ohren jucken, als \"\n\"würdest du es nicht glauben!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Nein nein nein nein! Das ist mein grauer Anzug! Der ist Abendgarderobe! \"\n\"Formale Anlässe! Das kann ich nicht tragen. Was bist du, irgendein Spinner? \"\n\"Ich brauche den braunen Anzug.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, das ist viel besser. Hui! Endlich etwas Würde! Steht mein Geweih \"\n\"akkurat? Gut. Hör mal, vielen Dank, dass du mir ausgeholfen hast. Hier, nimm \"\n\"das als Geschenk; und, weißt du ... ein kleiner Modetipp ... du könntest ein \"\n\"bisschen ... du könntest ein neues ... weißtwasichmein? Dieses ganze \"\n\"Abenteurermotiv ist einfach so ... retro. Nur ein gut gemeinter Rat, ja? \"\n\"Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Schau, ich bin eine Kuh. Und du, du bist Monster-Frühstück. Sammel erstmal \"\n\"ein paar Erfahrungen! Wir sprechen uns noch.\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Es muss wirklich eine furchterregende Aufgabe sein, die ich Euch gestellt \"\n\"habe. Wenn es nur eine Möglichkeit gäbe... würde mir ein Krug frischer Milch \"\n\"helfen?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Oh, ich könnte deine Hilfe gebrauchen, aber vielleicht nachdem du die \"\n\"Katakomben vor ihrer Entweihung durch diese Biester bewahrt hast.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Ich müsste etwas erledigt haben, aber ich könnte das nicht einem völlig \"\n\"Fremden aufbürden. Vielleicht würde ich mich eher dabei wohlfühlen, dich um \"\n\"einen Gefallen zu bitten, nachdem du eine Weile hier verbracht hast.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Ich sehe ein Potential zu echter Größe in dir. Vielleicht kannst du \"\n\"irgendwann mal, während du dein Schicksal erfüllst, vorbeischauen und mir \"\n\"einen kleinen Gefallen tun?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Ich denke, Du könntest mir wahrscheinlich helfen, aber vielleicht, nachdem \"\n\"Du ein wenig mächtiger geworden bist. Ich möchte nicht die einzige Chance \"\n\"des Dorfes verspielen, die Bedrohung der Kirche ein für alle mal \"\n\"auszulöschen!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Ich? Ich bin eine Selfmade-Kuh. Mach du erstmal was aus dir, und ... dann \"\n\"reden wir.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Ich muss mich nicht jedem Touristen erklären, der zufällig vorbeiläuft! Hast \"\n\"du keine Monster umzubringen? Vielleicht reden wir später. Wenn du dann noch \"\n\"lebst...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Hör auf mich zu nerven! Ich suche nach jemand wirklich Heldenhaftem. Und du \"\n\"bist es nicht. Ich kann dir nicht vertrauen, du würdest doch jetzt jederzeit \"\n\"von Monstern gegessen werden ... Ich brauche jemanden, der ein erfahrender \"\n\"Held ist.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"In Ordnung, ich breche das Schweigen. Ich wollte dich nicht in falsche \"\n\"Wasser führen. Ich saß zu Hause und fühlte mich mürrisch, als die Dinge \"\n\"wirklich instabil wurden; ein ganzer Ansturm von Monstern kam aus dem Boden! \"\n\"Ich habe mich nur eingeschüchtert. Ich habe gerade dieses Trikot getragen, \"\n\"als ich aus der Tür gerannt bin, und jetzt sehe ich lächerlich aus. Wenn ich \"\n\"nur etwas Normales zum Anziehen hätte, wäre es nicht so schlimm. Hallo! \"\n\"Kannst Du zu mir zurückgehen und meinen Anzug für mich holen? Den braunen, \"\n\"nicht den grauen, das ist für die Abendgarderobe. Ich würde es selbst tun, \"\n\"aber ich möchte nicht, dass mich jemand so sieht. Hier, nimm das, du \"\n\"brauchst es vielleicht... um die Dinger zu töten, die alles überwuchert \"\n\"haben. Du kannst mein Haus nicht verfehlen, es liegt südlich der Gabelung im \"\n\"Fluss... du weißt schon... das mit dem überwucherten Gemüsegarten.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Ich habe Zauber versucht, Drohungen, Widerrufung und Handel mit dieser \"\n\"unreinen Kreatur, aber vergeblich. Meine Methoden zur Versklavung geringerer \"\n\"Dämonen scheinen keine Auswirkung auf diese furchterregende Bestie zu haben.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Allmählich legt die Niedertracht dieses ungebetenen Gefangenen ein Unheil \"\n\"über mein Heim. Die Krypta ist voller Schatten, die kaum mein Sichtfeld \"\n\"streifen. Das schwache Scharren von Klauen tanzt an der Grenze meines \"\n\"Hörsinns. Sie suchen, denke ich. Nach diesem Tagebuch.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"In seinem Fluchen hat diese Kreatur seinen Namen fallen lassen -- Na-Krul. \"\n\"Ich habe versucht, diesem Namen auf den Grund zu gehen, aber die geringeren \"\n\"Dämonen haben irgendwie meine Bibliothek zerstört. Na-Krul ... der Name \"\n\"erfüllt mich mit kaltem Grausen. Ich ziehe es vor, sie lieber als die \"\n\"\\\"Kreatur\\\" zu bezeichnen als über ihren wahren Namen nachzudenken.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Das wütende Brüllen der gefangenen Kreatur hindert mich daran, dringend \"\n\"benötigten Schlaf zu bekommen. Er wütet gegen denjenigen, der ihn in den \"\n\"Abgrund geschickt hat, und er spricht schlimme Flüche über mich aus, weil \"\n\"ich ihn hier gefangen habe. Seine Worte erfüllen mein Herz mit Schrecken, \"\n\"und dennoch kann ich seine Stimme nicht verdrängen.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Meine Zeit läuft schnell ab. Ich muss aufzeichnen, wie man den Dämon \"\n\"schwächen kann, und diesen Text dann verstecken, damit nicht seine Diener \"\n\"einen Weg finden, ihren Herrn mit Hilfe meines Wissens zu befreien. Ich \"\n\"hoffe, dass, wer immer dieses Tagebuch findet, er nach diesem Wissen suchen \"\n\"wird.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Wer immer diese Schriftrolle findet, hat die Aufgabe, die dämonische Kreatur \"\n\"aufzuhalten, die hinter diesen Mauern weilt. Meine Zeit ist vorbei. Selbst \"\n\"in diesem Moment kratzen seine höllischen Diener an der zerbrechlichen Tür, \"\n\"hinter der ich mich verstecke.-\\n\"\n\"\\n\"\n\"Ich habe den Dämon mit einer geheimen Magie gebunden und in diesen mächtigen \"\n\"Mauern eingeschlossen, aber ich befürchte, das wird nicht genug sein.\\n\"\n\"\\n\"\n\"Die Zaubersprüche aus den drei Zauberbüchern werden Euch einen geschützten \"\n\"Zugang in seinen Bereich gewähren, aber nur, wenn sie in der richtigen \"\n\"Reihenfolge aufgesagt werden. Die Hebel am Eingang werden die Sperre \"\n\"beseitigen und den Dämon freisetzen; berühre sie nicht! Benutze nur die \"\n\"Zaubersprüche, sonst könnte er zu mächtig sein um ihn zu besiegen.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Höllenkeiler\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Skorpion\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psychorb\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Arachnon\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Missgestalteter\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Hungrige Brut\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Giftschwanz\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Nekromorb\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Spinnenfürst\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Peitschenwurm\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Fackelträger\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Höllenkäfer\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Totengräber\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Gruftratte\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Feuerflügel\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Sturmrufer\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lich\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Geschmiedeter\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Höllenflügel\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Knochendämon\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Erz-Lich\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Byklop\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Fleisch-Untier\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Schnitter\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Riesenknöchel\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Lebhafter Ring\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Xorines Ring\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Kariks Ring\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Ring des Magmas\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Ring der Mystiker\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Ring des Donners\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Amulett des Widerstands\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Moskitostich\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Flambeau\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Harnisch der Düsternis\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Blitzen\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Donnerschlag\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Seelenfresser\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Diamantschneide\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Knochenkettenrüstung\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Dämonenpanzer\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Amulett des Akolythen\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Ring des Gladiators\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Einfältiger\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Gläserner\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Doppelgänger-\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"r Verwüstung\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"s Verfalls\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"r Tücke\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana-Ritual\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Mantik\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Torheit\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Blitzwand\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Deflagration\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Warp\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Dornen\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Berserker\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Feuerring\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Suche\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Feuerrune\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Lichtrune\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Novarune\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Deflagrationsrune\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Steinrune\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"/help\"\n#~ msgstr \"/hilfe\"\n\n#~ msgid \"/arena\"\n#~ msgstr \"/arena\"\n\n#~ msgid \"/arenapot\"\n#~ msgstr \"/arenapot\"\n\n#~ msgid \"/inspect\"\n#~ msgstr \"/inspect\"\n\n#~ msgid \"/seedinfo\"\n#~ msgstr \"/seedinfo\"\n\n#~ msgid \"Command \\\"\"\n#~ msgstr \"Befehl \\\"\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Helligkeit verringern\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Helligkeit erhöhen\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Die Karte ist in der Stadt nicht verfügbar\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Neustart in Tristram\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Herz\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Versuchst Du, einen Bodengegenstand fallen zu lassen?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Erzwingt das Warten auf die vertikale Synchronisation. Verhindert den \"\n#~ \"Zerreißeffekt. Deaktivieren kann auf manchen Systemen bei ruckelnden \"\n#~ \"Mauszeigern helfen.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Maximale FPS\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Die FPS werden limitiert um eine hohe CPU-Last zu verhindern. Das Limit \"\n#~ \"berücksichtig die Bildwiederholungsrate.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Treffer%\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Unzerstörbar, \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Ohne Anforderungen\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Heute bewölkt und kühler. Das Auswerfen der Netze der Nekromantie über \"\n#~ \"die Leere brachte zwei neue Unterarten des fliegenden Horrors an Land; \"\n#~ \"ein guter Arbeitstag. Muss daran denken, noch mehr Fledermaus-Guano und \"\n#~ \"schwarze Kerzen von Adria zu bestellen; Mein Vorrat geht ein langsam zur \"\n#~ \"Neige.\"\n"
  },
  {
    "path": "Translations/devilutionx.pot",
    "content": "#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:22+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: ;_;N_;ngettext:1,2;pgettext:1c,2;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"\"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"\"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"\"\n\n#: Source/control.cpp:1525\nmsgid \"Right click to inspect\"\nmsgstr \"\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\nmsgid \"Decrease Brightness\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\nmsgid \"Increase Brightness\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\nmsgid \"Automap Move Up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\nmsgid \"Exit to Main Menu\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \"\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \"\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"\"\n\n#: Source/options.cpp:422\nmsgid \"Game Mode Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\nmsgid \"Per-pixel Lighting\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:797\nmsgid \"Show Party Information\"\nmsgstr \"\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"\"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \"\"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"\"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"\"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"\"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:370\nmsgid \"Lightforge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \"\"\n"
  },
  {
    "path": "Translations/el.po",
    "content": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: Μιχάλης Χατζηβασιλείου\\n\"\n\"Language: el\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Σχεδιασμός Παιχνιδιού\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Προϊστάμενοι Σχεδιασμού\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Επιπλέον Σχεδιαστές\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Κύριος Προγραμματιστής\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Προϊστάμενοι Προγραμματιστές\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Προγραμματιστές\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Ειδικοί Έκτακτοι Προγραμματιστές\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Προγραμματισμός Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Προγραμματισμός Σειριακών Επικοινωνιών\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Προγραμματισμός Εγκατάστασης\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Καλλιτεχνικοί Διευθυντές\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Καλλιτεχνία\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Τεχνική Καλλιτεχνία\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Σκηνοθέτες Κινηματογραφικής Τέχνης\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D Κινηματογραφική Τέχνη\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Κινηματογραφική Τεχνική Τέχνη\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Εκτελεστικός Παραγωγός\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Παραγωγός\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Συνεργάτης Παραγωγός\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Ομάδα κρούσης Diablo\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Μουσική\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Σχεδιασμός Ήχου\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Κινηματογραφική Μουσική και Ήχος\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Παραγωγή φωνής, κατεύθυνση & κάστινγκ\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Σενάριο & Ιστορία\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Επεξεργασία Φωνής\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Φωνές\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Μηχανικός Εγγραφής Ήχου\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Σχεδιασμός και Μορφή Ενχειριδίου\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Καλλιτεχνία Εγχειριδίου\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Προσωρινός διευθυντής του QA (Προϊστάμενος Ελεγκτής)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Ομάδα επίθεσης QA (Ελεγκτές)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA Ειδική Ομάδα Επιχειρήσεων (Ελεγκτές Συμβατότητας)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Υποστήριξη πυροβολικού QA (πρόσθετοι ελεγκτές) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Αντικατασκοπεία QA\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Ομάδα Υπηρεσιών Δικτυακών Πληροφοριών\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Υποστήριξη Πελατών\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Πωλήσεις\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Άχρηστα\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Τραγουδιστές Υπόβαθρου του κ. Dabiri\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Δημόσιες Σχέσεις\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Μάρκετινγκ\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Διεθνείς Πωλήσεις\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Πωλήσεις U.S\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Παραγωγή\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Νομικά & Επιχειρηματικά\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Ειδικές Ευχαριστίες στους\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Ευχαριστούμε τους\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Στην μνήμη του\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Πολύ Ειδικές Ευχαριστίες στους\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Γενικός Μάνατζερ\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Μηχανική Λογισμικού\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Διευθυντής Τέχνης\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Καλιτέχνες\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Σχεδιασμός\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Σχεδιασμός Ήχου, SFX & Μηχανική Φωνής\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Προϊστάμενος  Διαπίστευσης Ποιότητας\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Έλεγχος\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Εγχειρίδιο\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\t Επιπλέον Εργασίες\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Συγγραφή Κειμένων Αποστολών\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Ευχαριστούμε τούς παρακάτω\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tΕιδικές Ευχαριστίες στην Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Μάνατζερ Διαπίστευσης Ποιότητας\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Προϊστάμενος και Ελεγκτής Διαπίστευσης Ποιότητας\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Κύριοι Ελεγκτές\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Επιπλέον Ελεγκτές\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Μάνατζερ Μάρκετινγκ Προϊόντος\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Μάνατζερ Δημοσίων Σχέσεων\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Βοηθός Μάνατζερ Προϊόντος\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Ο Κύκλος των Χιλίων\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tΔεν πουλήθηκαν ψυχές κατά την ανάπτυξη του παιχνιδιού.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Επιλέξτε Κλάση\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Άκυρο\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Νέος Ήρωας για τετραπλό\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Νέος Ήρωας για μονό\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Το αρχείο παιχνιδιού Υπάρχει ήδη\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Φόρτωση Παιχνιδιού\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Νέο Παιχνίδι\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Ήρωες για Μονό\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Το Κλεφτρόνι και ο Μάγος είναι μόνο διαθέσιμοι στην πλήρης εμπορική έκδοση του \"\n\"Ντιάμπλο. Επισκεφτείτε https://www.gog.com/game/diablo για να το αγοράσετε.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Εισάγετε Όνομα\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Άκυρο όνομα. Ένα όνομα δεν μπορεί να περιλαμβάνει κενά, ειδικούς χαρακτήρες ή \"\n\"λέξεις\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Ανικανότητα δημιουργίας ήρωα.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Επίπεδό:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Δύναμη:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Μαγεία:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Επιδεξιότητα:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Ζωτικότητα:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Αρχείο Παιχνιδιού:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"ΔΙΑΛΕΞΕ ΗΡΩΑ\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Νέος Ήρωας\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Διαγ\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Ήρωες για Τετραπλό\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Διαγραφή Ήρωα για Τετραπλό\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Διαγραφή Ήρωα για Μονό\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Είσαι σίγουρος ότι θες να διαγράψεις τον ήρωα \\\"{:s}\\\";\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Ατομικό Παιχνίδι\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Τετραπλό Παιχνίδι\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Ρυθμίσεις\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Υποστήρηξη\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Συντελεστές\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Έξοδος\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Έξοδος\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Δωρεάν Έκδοση\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Διακομιστή-πελάτη (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"Βρόχος επιστροφής\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Τετραπλό Παιχνίδι\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Απαιτήσεις:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"χωρίς πύλη\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Σύνδεση\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Αλλαγή Πύλης\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Όλοι οι υπολογιστές πρέπει να είναι συνδεδεμένοι σε TCP-συμβατό δίκτυο.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Όλοι οι υπολογιστές πρέπει να είναι συνδεδεμένοι στο διαδίκτυο.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Παίξε μόνος χωρίς έκθεση σε κάποιο δίκτυο.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Mέγιστοι πάικτες: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Ντιάμπλο\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Ντιάμπλο Διαμοιραζόμενή Έκδοση\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Χελφαϊερ\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Χελφαϊερ Διαμοιραζόμενή Έκδοση\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Ο εξυπηρετητής τρέχει διαφορετικό παιχνίδι σε σχέση με σένα.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Ο εξυπηρετητής τρέχει διαφορετικό παιχνίδι ({:s}) σε σχέση με σένα.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"\"\n\"Η έκδοση του λογισμικού σου {:s} είναι διαφορετική από τον εξυπηρετητή {:d}.\"\n\"{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Περιγραφή:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Επιλέξτε Δράση\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Νέο Παιχνίδι\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Νέο Ανοικτό Παιχνίδι\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Είσοδος σε Παιχνίδι\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Ανοικτά Παιχνίδια\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Φόρτωση...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730 Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Κανένα\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"Άκυρο\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Δημιούργησε νέο παιχνίδι με δυσκολία της επιλογής σας.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Δημιούργησε νέο δημόσιο παιχνίδι που οποιοσδήποτε μπορεί να μπει με δυσκολία \"\n\"της επιλογής σας.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"\"\n\"Εισάγετε ένα Αριθμό Ταυτότητας Παιχνιδιού (ID) για να εισέλθετε στο παιχνίδι \"\n\"που είναι σε εξέλιξη.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Εισάγετε μια IP ή ένα όνομα εξυπηρετητή για να εισέλθετε στο παιχνίδι που \"\n\"είναι σε εξέλιξη.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Εισέλθετε σε υπάρχων δημόσια ανοιχτό παιχνίδι που είναι σε εξέλιξη.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Κανονικό\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Εφιάλτης\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Κόλαση\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Δυσκολία: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Ταχύτητα: Κανονική\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Ταχύτητα: Γρήγορη\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Ταχύτητα: Γρηγορότερη\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Ταχύτητα: Ταχύτατη\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Παίκτες: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Δυσκολία\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Είσοδος σε {:s} παιχνίδια\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Εισάγετε Αριθμό Ταυτότητας Παιχνιδιού (ID)\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Διεύθυνση\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Κανονική Δυσκολία\\n\"\n\"Για την αρχή ενός νέου ήρωα που είναι στην αποστολή να νικήσει τον Ντιάμπλο.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Εφιαλτική Δυσκολία\\n\"\n\"Οι κάτοικοι του Λαβύρινθου έχουν ενδυναμωθεί και είναι πολύ πιο δύσκολο να \"\n\"τους νικήσεις. Προτεινόμενο για έμπειρους.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into Hell. \"\n\"Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Κολασμένη Δυσκολία\\n\"\n\"Τα πιο δυνατά πλάσματα του κάτω κόσμου σε περιμένουν στην πύλη μέσα στην \"\n\"Κόλαση. Μόνο για τους πιο έμπειρους.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game of \"\n\"Nightmare difficulty.\"\nmsgstr \"\"\n\"Ο ήρωας σου πρέπει να φτάσει στο επίπεδο 20 για να μπορέσεις να μπεις σε \"\n\"παιχνίδι πολλαπλών παικτών Εφιαλτικής δυσκολίας.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game of \"\n\"Hell difficulty.\"\nmsgstr \"\"\n\"Ο ήρωας σου πρέπει να φτάσει στο επίπεδο 30 για να μπορέσεις να μπεις σε \"\n\"παιχνίδι πολλαπλών παικτών Κολασμένης δυσκολίας.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Ταχύτητα\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Γρήγορο\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Γρηγορότερο\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Ταχύτατο\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Κανονική Ταχύτητα\\n\"\n\"Για την αρχή ενός νέου ήρωα που είναι στην αποστολή να νικήσει τον Ντιάμπλο.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Γρήγορη Ταχύτητα\\n\"\n\"Οι κάτοικοι του Λαβύρινθου έχουν επιταχυνθεί και είναι πολύ πιο δύσκολο να \"\n\"τους νικήσεις. Προτεινόμενο για έμπειρους.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. Only \"\n\"an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Γρηγορότερη Ταχύτητα\\n\"\n\"Τα τέρατα του μπουντρουμιού θα σε αναζητήσουν πιο γρήγορα από ποτέ. Μόνο για \"\n\"πολύ έμπειρους.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Ταχύτατη Ταχύτητα\\n\"\n\"Οι υποτακτικοί του κάτω κόσμου θα τρέξουν αστραπιαία να σου επιτεθούν χωρίς \"\n\"δισταγμό. Μόνο για δαίμονες της ταχύτητας.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Εισάγετε Κωδικό\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Εισαγωγή στο Χελφάϊερ\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Αλλαγή στο Ντιάμπλο\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Ναι\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Όχι\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Πατήστε οποιοδήποτε πλήκτρο στο χειριστήριο για αλλαγή.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Δεσμευμένο πλήκτρο:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Πατήστε οποιοδήποτε πλήκτρο για αλλαγή.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Αποδέσμευσή πλήκτρου\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Δεσμευμένο πλήκτρο συνδυασμένης κίνησης:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Άποδεσμευμένο πλήκτρο συνδιασμένης κίνησης\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Προηγούμενο Μενού\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Διατηρούμε εξυπηρετητή για συνομιλίες στο Discord.gg/devilutionx Ακολουθήστε \"\n\"τους συνδέσμους για να μπείτε στην κοινότητα μας όπου μιλάμε για θέματα \"\n\"σχετικά με το Ντιάμπλο, και την προέκταση του το Χελφαϊερ.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, and \"\n\"the nature of the problem.\"\nmsgstr \"\"\n\"Το DevilutionX το συντηρεί η ομάδα Diasurgical, Μπορείτε να μας ειδοποιήσετε \"\n\"για θέματα και σφάλματα σε αυτήν την διεύθυνση: https://github.com/diasurgical/\"\n\"devilutionX Για να μας βοηθήσετε να σας εξυπηρετήσουμε, παρακαλούμε να μας \"\n\"πείτε τον αριθμό έκδοσης, το λειτουργικό σας σύστημα/πλατφόρμα και την φύση \"\n\"του προβλήματος.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Αποποίηση Ευθύνης:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tΤο DevilutionX δεν υποστηρίζεται ή αναπτύσσεται από την Blizzard \"\n\"Entertainment, ή από το GOG.com. Ούτε η Blizzard Entertainment ή το GOG.com \"\n\"έχει τεστάρει ή πιστοποιήσει την ποιότητα ή την συμβατότητα του DevilutionX. \"\n\"Όλα τα ερωτήματα και τα αιτήματα σας σχετικά με το DevilutionX πρέπει να \"\n\"απευθυνθούν στον Diasurgical,  και όχι στην  Blizzard Entertainment ή στο \"\n\"GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji which \"\n\"is licensed under CC-BY 4.0. The port also makes use of SDL which is licensed \"\n\"under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tΤο παρών λογισμικό χρησιμοποιεί την γραμματοσειρες  Charis SIL, New Athena \"\n\"Unicode, Unifont, και Noto που είναι άδειοδιτημένες κάτω από την Ανοικτή Άδεια \"\n\"Γραμματοσοειρών SIL, καθώς και την γραμματοσειρά Twitmoji, που είναι \"\n\"αδειοδοτημένη κάτω από το CC-BY 4.0. Το λογισμικό επίσης χρησιμοποιεί το SDL \"\n\"που είναι αδειοδοτημένο κάτω από την άδεια zlib. Δείτε το ReadMe για περεταίρω \"\n\"λεπτομέρειες.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Σφάλμα\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Το σφάλμα έλαβε χώρα στο: {:s} γραμμή {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Σφάλμα στο αρχείο δεδομένων\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Το κύριο αρχείο δεδομένων ({:s}) δεν βρέθηκε.\\n\"\n\"\\n\"\n\"Βεβαιωθείτε ότι βρίσκετε το φάκελο του παιχνιδιού.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Σφάλμα Καταλόγου Μόνο για Ανάγνωση\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Αδυναμία εγγραφής στην τοποθεσία:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Παιχνίδι: \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"Βρόχος επιστροφής\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Κωδικός: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Δημόσιο Παιχνίδι\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Επίπεδο: Φωλιά {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Επίπεδο: Κρύπτη {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Πόλη\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Επίπεδο: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Πληροφορίες Ήρωα\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Βιβλίο ταξιδιού\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Χάρτης\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Κυρίως Μενού\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Αντικείμενα\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Βιβλίο με Ξόρκια\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Αποστολή Μυνήματος\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Διαθέσιμες Εντολές:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Η Εντολή \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" είναι άγνωστη.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Περιγραφή: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Παράμετροι: Καμία επιπλέον παράμετρος δεν χρειάζεται.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Παράμετροι: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Οι Αρένες υποστηρίζονται μόνο στο τετραπλό παιχνίδι.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Ποια αρένα θέλεις να επισκεφτείς;\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Άκυρος αριθμός αρένας. Έγκυροι αριθμοί είναι:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\"Για να εισέλθεις σε μια αρένα, πρέπει να είσαι στην πόλη ή σε μια άλλη αρένα.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"H επιθεώρηση παίκτη υποστηρίζεται μόνο στο τετραπλό παιχνίδι.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Λήξη επιθεώρησης παίκτη.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Δεν βρέθηκε παίκτης με τέτοιο όνομα\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Επιθεώρηση παίκτη: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Εμφανίζει γενική βοήθεια, η βοήθεια για συγκεκριμένη εντολή.\"\n\n#: Source/control.cpp:800\n#, fuzzy\n#| msgid \"Command \"\nmsgid \"[command]\"\nmsgstr \"Η Εντολή \"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Εισαγωγή σε PvP Αρένα.\"\n\n#: Source/control.cpp:801\n#, fuzzy\n#| msgid \"{arena-number}\"\nmsgid \"<arena-number>\"\nmsgstr \"{arena-number}\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Σου δίνει φιλτρά αρένας.\"\n\n#: Source/control.cpp:802\n#, fuzzy\n#| msgid \"{number}\"\nmsgid \"<number>\"\nmsgstr \"{number}\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Επιθεώρηση στατιστικών και αντικειμένων ενός άλλου παίκτη.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<όνομα παίκτη>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Εμφανίζει τον σπόρο παραγωγής του τρέχοντος επιπέδου.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Φιλικός προς Παίκτες\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Εχθρικός προς Παίκτες\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Πλήκτρο: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Επιλογή ξορκιού για ενεργοποίηση\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Πλήκτρο: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"Δεξιότητα \\\"{:s}\\\"\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"Ξόρκι \\\"{:s}\\\"\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Επίπεδο Ξορκιού 0 - Άχρηστο\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Επίπεδο Ξορκιού {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Πάπυρος \\\"{:s}\\\"\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Πάπυρος\"\nmsgstr[1] \"{:d} Πάπυροι\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Ράβδος {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Φορτίο\"\nmsgstr[1] \"{:d} Φορτία\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} χρυσό νόμισμα\"\nmsgstr[1] \"{:s} χρυσά νομίσματα\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Απαιτήσεις δεν έχουν εκπληρωθεί\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Επίπεδο: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Πόντοι Ζωής {:d} από {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Δεξί-κλικ για χρήση\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Νέο Επίπεδο\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Έχεις {:s} χρυσό νόμισμα. Πόσα θέλεις να αφαιρέσεις;\"\nmsgstr[1] \"Έχεις {:s} χρυσά νομίσματα. Πόσα θέλεις να αφαιρέσεις;\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Πύλη Πόλης\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"από {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Πύλη πρός\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Ο Ανίερος Βωμός\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"επίπεδο 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Αποτυχία κατά την φόρτωση χαρακτήρα\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Εμφάνιση αυτού του μηνύματος και έξοδος\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Εμφάνιση της έκδοσης και έξοδος\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Ορισμός φακέλου για το diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Ορισμός φακέλου για τα αποθηκευμένα παιχνίδια\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Ορισμός φακέλου για το diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Ορισμός κώδικα γλώσσας (π.χ. en ή pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Παράλειψη αρχικών βίντεο\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Προβολή αριθμού καρέ ανά δεπτερόλεπτο\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Ενεργοποίηση λεπτομερών εγγραφών\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Εγγραφή αρχείου δράσης\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Αναπαραγωγή αρχείου δράσης\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Απενεργοποίηση ορίων καρέ κατά την αναπαραγωγή αρχείου δράσης\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Επιλογή παιχνιδιού:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Εξαναγκαστική κατάστασή Δοκιμαστικής έκδοσης\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Εξαναγκαστική κατάστασή σε Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Εξαναγκαστική κατάστασή σε Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Επιλογές Χελφάϊερ:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"\"\n\"Αναφορά σφαλμάτων στην σελίδα https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\"Παρακαλώ ενημερώστε τα αρχεία devilutionx.mpq και fonts.mpq στην τελευταία \"\n\"τους έκδοση\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Αποτυχία φόρτωσης πόρων για το UI.\\n\"\n\"\\n\"\n\"Βεβαιωθείτε ότι το αρχείο devilutionx.mpq είναι στον φάκελο του παιχνιδιού και \"\n\"ότι είναι ενημερωμένο.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Παρακαλώ ενημερώστε το αρχείο fonts.mpq στην τελευταία του έκδοση\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Τέλος χρονικού ορίου Δικτύου --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Αναμονή για παίκτες --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Δεν υπάρχει διαθέσιμη βοήθεια\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"όσο βρίσκεσαι σε μαγαζί\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Αντικείμενο Ζώνης {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Χρήση αντικειμένου Ζώνης.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Γρήγορο ξόρκι {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Πλήκτρο για δεξιότητα ή ξόρκι.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Προηγούμενο Μενού\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Γρήγορο ξόρκι {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Χρήση φίλτρου ζωής\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Χρήση φίλτρου ζωής απο την ζώνη.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Χρήση φίλτρου μάνα\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Χρήση φίλτρου μάνα απο την ζώνη.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Γρήγορο Βιβλίου\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Άνοιγμα Γρήγορου Βιβλίου.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Άμεση αποθήκευση\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Αποθηκεύει το παιχνίδι.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Άμεση φώρτοση\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Φορτώνει το παιχνίδι.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Έξοδος παιχνιδιού\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Κλείνει το παιχνίδι.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Σταμάτημα ήρωα\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Σταματά το περπάτημα και ακυρώνει δράσεις που υπολείπονται.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Επισήμανση αντικειμένων\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Εμφανίζει ή κρύβει τα αντικείμενα στο έδαφος.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Εναλλαγή επισήμανσης αντικείμενων\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Μόνιμη εμφάνιση/απόκρυψη αντικειμένων στο έδαφος.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Εναλλαγή αυτόματου χάρτη\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Εναλλαγή εμφάνισης του αυτόματου χάρτη.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Ανοίγει την καρτέλα Αντικειμένων (σάκος).\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Ήρωας\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Ανοίγει την καρτέλα του ήρωα.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Ιστορία\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Ανοίγει την καρτέλα με τις Αποστολές της Ιστορίας.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Ξόρκια\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Ανοίγει την Καρτέλα του Βιβλίου με τα Ξόρκια.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Άμεσο Μήνυμα {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Χρήση για άμεσο μήνυμα στην συνομιλία.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Κλείσιμο των καρτελών πληροφορίας\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Κλείσιμο όλων των καρτελών.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Μεγένθυση\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Μεγεθύνει την προβολή του παιχνιδιού.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Παύση Παιχνιδιού\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Σταματάει την δράση στο παιχνίδι.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Παύση Παιχνιδιού\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Αύξηση φωτεινότητας.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Μείωση φωτεινότητας.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Αύξηση φωτεινότητας.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Αύξηση φωτεινότητας.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Βοήθεια\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Ανοίγει την Καρτέλα Βοήθειας.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Στιγμιότυπο οθόνης\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Λαμβάνει και αποθηκεύει την οθόνη σαν εικόνα.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Πληροφορίες Παιχνιδιού\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Εμφανίζει τις πληροφορίες του παιχνιδιού σε εξέλιξη.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Συνομιλίες\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Εμφανίζει τις συνομιλίες.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Αντικείμενα\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Πρωτογενή δράση\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Επίθεση σε τέρας, ομιλία σε κάτοικο πόλης, μάζεμα και τοποθέτηση αντικειμένων \"\n\"στο σάκο.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Δευτερογενής δράση\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Άνοιγμα σεντουκιών, αλληλεπίδραση με πόρτες, μάζεμα αντικειμένων.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Δράση ξορκιού\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Ρίψη του προεπιλεγμένου ξορκιού.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Ακύρωση δράσης\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Κλείνει τα ανοιχτά μενού.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Κίνηση πάνω\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Μετακίνηση του ήρωα προς τα πάνω.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Κίνηση κάτω\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Μετακίνηση του ήρωα προς τα κάτω.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Κίνηση αριστερα\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Μετακίνηση του ήρωα προς τα αριστερά.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Κίνηση δεξιά\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Μετακίνηση του ήρωα προς τα δεξιά.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Παρέμεινε ακίνητος\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Κράτα το για να αποτρέψεις κίνηση του ήρωα.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Διακόπτης εναλλαγής κατάστασης ακινησίας.\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Διακόπτης ορισμού ακινησίας ήρωα.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Χάρτης\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Κίνηση κάτω\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Κίνηση αριστερα\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Μετακίνηση του ήρωα προς τα πάνω.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Κίνηση δεξιά\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Κίνηση ποντικιού πάνω\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Εξομοιώνει την προς τα πάνω κίνηση του ποντικού.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Κίνηση ποντικιού κάτω\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Εξομοιώνει την προς τα κάτω κίνηση του ποντικού.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Κίνηση ποντικιού αριστερά\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Εξομοιώνει την προς τα αριστερά κίνηση του ποντικού.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Κίνηση ποντικιού δεξιά\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Εξομοιώνει την προς τα δεξιά κίνηση του ποντικού.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Αριστερό κλικ ποντικιού\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Εξομοιώνει το αριστερό πάτημα πλήκτρου στο ποντίκι.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Δεξί κλικ ποντικιού\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Εξομοιώνει το δεξί πάτημα πλήκτρου στο ποντίκι.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Μενού γρήγορου ξορκιού χειριστηρίου\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Κράτα το πατημένο για να ορίσεις ή να χρησιμοποιήσεις κουμπιά ξορκιών.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Μενού πλοήγησης χειριστηρίου\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Κράτα το πατημένο για να εμφανιστεί το μενού πλοήγησης του χειριστηρίου.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Διακόπτης μενού παιχνιδιού\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Ανοίγει το κυρίως μενού του παιχνιδιού.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"Κύμα Φωτιάς\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Το δωρεάν παιχνίδι δεν επιτρέπει λειτουργίες για πολλούς παίκτες\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Αποτυχία δημιουργίας υποσυστήματος Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Δεν είναι διαθέσιμο στην δωρεάν έκδοση\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Δεν υπάρχει αρκετός ελεύθερος χώρος για αποθήκευση\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Δεν επιτρέπεται η Παύση στην Πόλη\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Προτείνουμε να αντιγράψετε το αρχείο στον σκληρό δίσκο\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Πρόβλημα συγχρονισμού τετραπλού παιχνιδιού\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Δεν επιτρέπεται η Παύση στο τετραπλό\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Αποθήκευση...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Κάποια αδυνατούν καθώς ένα δυναμώνει πολύ\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Νέα δύναμη σφυρηλατείται μέσα από την καταστροφή\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Όσοι αμύνονται σπάνια επιτίθενται\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Το σπαθί της δικαιοσύνης είναι γρήγορο και κοφτερό\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Όταν το πνεύμα είναι άγρυπνο, το σώμα ευδοκιμάζει\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Η δύναμη του μάνα εστιασμένη ανανεώνει\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Ο χρόνος δεν μπορεί να εξασθενίσει την δύναμη του ατσαλιού\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Η μαγεία δεν είναι πάντα αυτό που φαίνεται\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Ότι ήταν κάποτε ανοικτό είναι πάλι κλειστό\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Η σφοδρότητα έρχεται με κόστος την σοφία\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Η απόκρυφη δύναμη φέρνει καταστροφή\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Αυτό που δεν πιάνεται δεν μπορεί να βλαφθεί\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Ερυθρό και κυανό γίνονται σαν τον ήλιο\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Γνώση και σοφία με κόστος ο εαυτό σου\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Πιές και αναζωογονήσου\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Όπου και αν πας, εκεί είσαι\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Η ενέργεια έρχεται με κόστος την σοφία\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Βρίθεις από πλούτη εκεί που δεν το περιμένεις\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Όταν η φιλαργυρία αποτυγχάνει, η υπομονή προσφέρει αμοιβή\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Ένας καλοκάγαθος σύντροφός σου, σε ευλόγησε!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Τα χέρια των ανθρώπων καθοδηγούνται από την μοίρα\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Η δύναμη ενισχύεται με την ουράνια πίστη\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Η ουσία της ζωής ρέει εκ των έσω\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Το μονοπάτι είναι ξεκάθαρο όταν το δείς από ψηλά\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Η σωτήρια έρχεται με κόστος την σοφία\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Μυστήρια αποκαλύπτονται στο φώς της λογικής\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Αυτοί που είναι τελευταίοι, μπορεί τελικά τα γίνουν πρώτοι\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Η γενναιοδωρία φέρνει τις δικές της αμοιβές\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Πρέπει να είσαι το λιγότερο επίπεδο 8 για να χρησιμοποιήσεις αυτό.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Πρέπει να είσαι το λιγότερο επίπεδο 13 για να χρησιμοποιήσεις αυτό.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Πρέπει να είσαι το λιγότερο επίπεδο 17 για να χρησιμοποιήσεις αυτό.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Απόκτησες απόκρυφη γνώση!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Ότι δεν σε σκοτώνει...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Η γνώση είναι δύναμη.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Δώσε και θα λάβεις.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Κάποια εμπειρία αποκτάται με το άγγιγμα.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Σπίτι μου, σπιτάκι μου και φτωχοκαλυβάκι μου.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Η πνευματική σου ενέργεια αποκαθίσταται.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Αισθάνεσαι πιο ευκίνητος.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Αισθάνεσαι πιο δυνατός.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Αισθάνεσαι πιο σοφός.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Αισθάνεσαι ανανεωμένος.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Ότι σπάει θα σπάσει.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Καθεδρικός Ναός\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Κατακόμβες\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Σπήλαια\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Φωλιά\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Κρύπτη\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Επ. {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"Δυσκολία {}\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Στο Μενού\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"βρόχος επιστροφής\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Αδυναμία σύνδεσης\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"σφάλμα: ανάγνωση 0 bytes από τον εξυπηρετητή\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq ή spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Μερικά αρχεία MPQ του Χελφαϊερ, λείπουν\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Δεν βρέθηκαν όλα τα αρχεία MPQ του Χελφαϊερ.\\n\"\n\"Παρακαλούμε αντιγράψτε όλα τα hf*.mpq αρχεία.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Ανάλυση\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Τρέξιμο στην Πόλη\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Αποστολή του Θέο\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Αποστολή Αγελάδας\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Αυτόματο Μάζεμα Χρυσού\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Αυτόματο Μάζεμα Ελιξιρίων\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Αυτόματο Μάζεμα Λαδιών\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Αυτόματο Μάζεμα στην Πόλη\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Η Άντρια αναπληρώνει Μάνα\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Αυτόματος Εξοπλισμός Όπλων\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Αυτόματος Εξοπλισμός Πανοπλίας\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Αυτόματος Εξοπλισμός Κράνους\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Αυτόματος Εξοπλισμός Ασπίδας\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Αυτόματος Εξοπλισμός Χρυσαφικών\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Τυχαίες Αποστολές\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Εμφάνιση Ετικετών Αντικειμένων\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Αυτόματο Γέμισμα Ζώνης\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Απενεργοποίηση Βλαβερών Βωμών\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Μάζεμα Φίλτρων Θεραπείας\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Μάζεμα Φίλτρων Πλήρους Θεραπείας\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Μάζεμα Φίλτρου Μάνα\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Μάζεμα Φίλτρου Πλήρωσης Μάνα\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Μάζεμα Φίλτρου Αναζωογόνησης\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Μάζεμα Φίλτρου Πλήρους Αναζωογόνησης\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Επιλογές\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Σώσιμο Παιχνιδιού\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Κυρίως Μενού\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Έξοδος Παχνιδιού\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Γάμα\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Ταχύτητα\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Μουσική Απενεργοποιημένη\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Ήχος\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Ήχος Απενεργοποιημένος\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Πάυση\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Συντομεύσεις Πληκτρολογίου:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Άνοιγμα Καρτέλας Βοήθειας\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Εμφάνιση Κεντρικού Μενού\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Εμφάνιση Χάρτη\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Κλείσιμο όλων των καρτελών\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Άνοιγμα Γρήγορου Βιβλίου\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Άνοιγμα Βιβλίου με Ξόρκια\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Άνοιγμα καρτέλας Αντικειμένων (σάκος)\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Άνοιγμα καρτέλας Ήρωα\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Άνοιγμα καρτέλας Αποστολών (ιστορία)\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Μείωση φωτεινότητας οθόνης\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"F: Αύξηση φωτεινότητας οθόνης\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Μεγέθυνση Οθόνης Παιχνιδιού\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Αυξομείωση Μεγέθυνσης Χάρτη\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Χρήση αντικειμένου Ζώνης\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Ορισμός πλήκτρου για άμεσο ξόρκι ή δεξιότητα\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Αριστερό Κουμπί Ποντικιού: Επίθεση χωρίς κίνηση\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Αριστερό Κουμπί Ποντικιού (στην καρτέλα ήρωα): Τοποθέτηση όλων των \"\n\"ελεύθερων πόντων\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Αριστερό Κουμπί Ποντικιού (στην καρτέλα αντικειμένων): Μετακίνηση \"\n\"αντικειμένου στην ζώνη ή εξοπλισμός/ανεξοπλισμός του\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\"Shift + Αριστερό Κουμπί Ποντικιού (στην ζώνη): Μετακίνηση αντικειμένου στον \"\n\"σάκο\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Κίνηση:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue to \"\n\"move in that direction.\"\nmsgstr \"\"\n\"Εάν κρατάτε το κουμπί του ποντικιού πατημένο καθώς κινήστε, ο ήρωας θα \"\n\"συνεχίσει να κινείται προς την κατεύθυνση αυτή.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Μάχη:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Κρατώντας πατημένο το πλήκτρο shift και κάνοντας αριστερό κλικ επιτρέπει τον \"\n\"ήρωα σας να επιτίθεται χωρίς να κινείται.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Χάρτης:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or press \"\n\"'TAB' on the keyboard. Zooming in and out of the map is done with the + and - \"\n\"keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Για να εμφανίσετε τον αυτόματο χάρτη, κάντε κλικ στο κουμπί 'χάρτης' στην \"\n\"μπάρα πληροφορίων κάτω ή πατήστε το πλήκτρο 'TAB' στο πληκτρολόγιο. Μεγέθυνση \"\n\"και σμίκρυνση μπορείτε να κάνετε με τα + και - πλήκτρα. Ανακύλιση τού χάρτη \"\n\"γίνεται με τα πλήκτρα με βελάκια.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Μαζεύοντας Αντικείμενα:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface bar . \"\n\"When an item is placed in the belt, a small number appears in that box. Items \"\n\"may be used by either pressing the corresponding number or right-clicking on \"\n\"the item.\"\nmsgstr \"\"\n\"Μικρά αντικείμενα μιας χρήσης όπως φίλτρα και πάπυροι, αυτόματα τοποθετούνται \"\n\"στην 'ζώνη', στην κορυφή της μπάρας πληροφοριών. Όταν ένα αντικείμενο είναι \"\n\"στην ζώνη, ένα μικρό νούμερο εμφανίζεται στο χώρο του. Μπορείτε να \"\n\"χρησιμοποιείται αυτά τα αντικείμενα πατώντας το πλήκτρο με τον αντίστοιχο \"\n\"αριθμό, ή κάνοντας δεξί κλικ στο αντικείμενο.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Χρυσός:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Μπορείς να διαλέξεις συγκεκριμένο ποσό χρυσού για να ρίξεις, κάνοντας δεξί \"\n\"κλικ σε έναν σωρό χρυσού στον σάκο σου.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Δεξιότητες & Ξόρκια:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the 'SPELLS' \"\n\"button in the interface bar. Memorized spells and those available through \"\n\"staffs are listed here. Left-clicking on the spell you wish to cast will ready \"\n\"the spell. A readied spell may be cast by simply right-clicking in the play \"\n\"area.\"\nmsgstr \"\"\n\"Μπορείς να έχεις πρόσβαση στην λίστα των ξορκιών και δεξιοτήτων σου κάνοντας \"\n\"αριστερό κλικ στο κουμπί 'ξόρκια' στην μπάρα πληροφοριών κάτω. Απομνημονευμένα \"\n\"ξόρκια και ξόρκια από ράβδους εμφανίζονται εδώ. Με αριστερό κλικ στο ξόρκι που \"\n\"θες να ρίξεις το ετοιμάζει κάτω δεξιά. Για να ρίξεις ένα προετοιμασμένο ξόρκι \"\n\"ή δεξιότητα απλά κάνε δεξί κλικ στον χώρο παιξίματος.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Χρησιμοποιόντας το γρήγορο βιβλίο για ξόρκια:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Με αριστερό κλικ στο κουμπί με το 'ετοιμασμένο ξόρκι' ανοίγει το γρήγορο \"\n\"βιβλίο το οποίο επιτρέπει την επιλογή ενός ξορκιού ή δεξιότητας για άμεση \"\n\"χρήση. Για να χρησιμοποιήσετε το ξόρκι ή την δεξιότητα απλά κάντε δεξί κλικ \"\n\"στον χώρο παιξίματος.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + αριστερό κλικ στο κουμπί με το 'ετοιμασμένο ξόρκι' θα καθαρίσει το \"\n\"ετοιμασμένο ξόρκι.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Ορίζοντας πλήκτρα για ξόρκια:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Μπορείς να ορίσεις μέχρι τέσσερα πλήκτρα για δεξιότητες, ξόρκια ή παπύρους. \"\n\"Άνοιξε το γρήγορο βιβλίο όπως περιγράφεται στην ενότητα πάνω και πάτησε το F5, \"\n\"F6, F7 ή F8 πλήκτρο, αφού 'αγγίξεις' με τον δείκτη ποντικιού το ξόρκι που θες.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Βιβλία Ξορκιών:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Διαβάζοντας παραπάνω από ένα βιβλίο σου αυξάνει την γνώση σου για το ξόρκι \"\n\"αυτό και σου επιτρέπει να το ρίχνεις πιο αποδοτικά.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Βοήθεια Δωρεάν έκδοσης Χελβαϊερ\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Βοήθεια Χελβαϊερ\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Βοήθεια Δωρεάν έκδοσης Ντιάμπλο\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Βοήθεια Ντιάμπλο\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Πατήστε ESC για κλείσιμο ή τα πλήκτρα με βελάκια για ανακύλιση.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Ανικανότητα δημιουργίας του κυρίως παραθύρου\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Δεν έχεις χώρο για το αντικείμενο\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Λάδι Ακρίβειας\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Λάδι της Μαεστρίας\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Λάδι Οξύτητας\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Λάδι του Θανάτου\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Λάδο της Δεξιότητας\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Λάδι του Σηδιρουργού\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Λάδι της Αντοχής\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Λάδι της Μονιμότητας\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Λάδι της Σκλήρυνσης\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Λάδι της Αδιαπερατότητας\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} με \\\"{1}\\\"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1} {0} με \\\"{2}\\\"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1} {0} και {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{1} {0}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"αυξάνει την πιθανότητα\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"ενός όπλου να χτυπήσει\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"αυξάνει κατά πολύ την πιθανότητα\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"ενός όπλου να χτυπήσει\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"δυνητικότητα ζημιάς\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"αυξάνει κατά πολύ την δυνητοκότητα\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"ενός όπλου για ζημιά - όχι σε τόξα\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"μειώνει τα απαιτούμενα στατιστικά\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"για να εξοπλίσεις όπλα και πανοπλίες\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"αποκαθιστά 20% της\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"ανθεκτικότητας ενος αντικειμένου\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"αυξάνει την μέγιστη και τρέχουσα\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"ανθεκτικότητα ενός αντικειμένου\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"κάνει ένα αντικείμενο άφθαρτο\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"αυξάνει την κλάση θωράκισης\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"μιας πανοπλίας ή ασπίδας\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"αυξάνει κατά πολύ την κλάση θωρακισης\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"μιας πανοπλίας ή ασπίδας\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"τοποθέτηση παγίδας φωτιας\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"τοποθέτηση παγίδας κεραυνού\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"τοποθέτηση παγίδας πέτρωσης\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"ολική αναπλήρωση της ζωής\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"μερική αναπλήρωση της ζωής\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"μερική αναπλήρωση των μάνα\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"ολική αναπλήρωση των μάνα\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"αυξάνει την δύναμη\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"αυξάνει την μαγεία\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"αυξάνει την επιδεξιότητα\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"αυξάνει την ζωτικότητα\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"μερική αναπλήρωση ζωής και μάνα\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"ολική αναπλήρωση ζωής και μάνα\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(λειτουργεί μόνο στης αρένες)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Δεξί-κλικ για προβολή\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Δεξί-κλικ για χρήση\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Δεξί-κλικ για διάβασμα, και\\n\"\n\"αριστερό-κλικ στον στόχο\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Δεξί-κλικ για διάβασμα\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Ενεργοποίηση για προβολή\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Άνοιξε τον σάκο σου για να το χρησιμοποιήσεις\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Ενεργοποίησε το για να το χρησιμοποιήσεις\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Επιλέξτε από το βιβλίο με τα ξόρκια και μετά\\n\"\n\"κάντε ξόρκι για ανάγνωση\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Ενεργοποίησε το για να το διαβάσεις\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} για προβολή\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} για χρήση\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Επιλέξτε από το βιβλίο με τα ξόρκια,\\n\"\n\" και μετά {} για ανάγνωση\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} για ανάγνωση\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Επίπεδο: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Διπλασιάζει τον αποθηκευτικό χώρο για τον χρυσό\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Απαιτεί:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Δυν\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Μαγ\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Επι\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Βιβλίο: {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Το αυτί του(ης) {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"πιθανότητα για χτύπημα: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% ζημιά\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"για χτύπημα: {:+d}%, {:+d}% ζημιά\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% θωράκιση\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"κλάση θωράκισης: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Αντοχή Φωτιάς: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Αντοχή Φωτιάς {:+d}% ΜΕΓΙΣΤΟ\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Αντοχή Κεραυνού: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Αντοχή Κεραυνού: {:+d}% ΜΕΓΙΣΤΟ\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Αντοχή Μαγείας: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Αντοχή Μαγείας: {:+d}% ΜΕΓΙΣΤΟ\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Αντοχή Πάντων: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Αντοχή Πάντων: {:+d}% ΜΕΓΙΣΤΟ\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"τα ξόρκια κερδίζουν {:d} επίπεδο\"\nmsgstr[1] \"τα ξόρκια κερδίζουν {:d} επίπεδα\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"τα ξόρκια μειώνονται {:d} επίπεδο\"\nmsgstr[1] \"τα ξόρκια μειώνονται {:d} επίπεδα\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"επίπεδα ξορκιών απαράλαχτα (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Επιπλέον φορτία\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} φορτίο\"\nmsgstr[1] \"{:d} {:s} φορτία\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Ζημιά χτυπήματος φωτιάς {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Ζημιά χτυπήματος φωτιάς {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Ζημιά χτυπήματος κεραυνού {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Ζημιά χτυπήματος κεραυνού {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} στην δύναμη\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} στην μαγεία\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} στην επιδεξιότητα\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} στην ζωτικότητα\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} σε όλα τα στατιστικά\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} ζημιά από εχθρούς\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Πόντοι Ζωής {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Μάνα {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"υψηλή ανθεκτικότητα\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"μειωμένη ανθεκτικότητα\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"άφθαρτο\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% εμβέλεια φωτός\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% εμβέλεια φωτός\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"πολλαπλά βέλη ανά βολή\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"ζημιά βέλους φωτιάς {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"ζημιά βέλους φωτιάς {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"ζημιά βέλους Κεραυνού {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"ζημιά βέλους Κεραυνού {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"ζημιά οβίδας φωτιάς: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"ζημιά οβίδας φωτιάς: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"ο επιτιθέμενος δέχεται 1-3 ζημιά\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"ο χρήστης χάνει όλα τα μάνα του\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"απορροφά την μισή ζημιά από παγίδες\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"σπρώχνει τον στόχο πίσω\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% ζημιά εναντίων δαιμονων\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Όλες οι Αντοχές γίνονται 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"με κτύπο κλέβει 3% μάνα\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"με κτύπο κλέβει 5% μάνα\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"με κτύπο κλέβει 3% ζωή\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"με κτύπο κλέβει 5% ζωή\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"διαπερνά θωράκιση\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"ταχεία επίθεση\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"γρήγορη επίθεση\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"γρηγορότερη επίθεση\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"γρηγορότατη επίθεση\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Άλλη δεξιότητα (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"γρήγορη ανάρρωση από χτύπημα\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"γρηγορότερη ανάρρωση από χτύπημα\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"γρηγορότατη ανάρρωση από χτύπημα\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"γρήγορο μπλοκάρισμα\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"προσθέτει {:d} πόντο ζημιάς\"\nmsgstr[1] \"προσθέτει {:d} πόντους ζημιάς\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"ρίχνει βέλη τυχαίας ταχύτητας\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"ασυνήθης ζημιά για αντικείμενο\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"αλλαγμένη ανθεκτικότητα\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"μονόχειρο σπαθί\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"χάνεις συνέχεια πόντους ζωής\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"κλέβει ζωή\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"καμία απαίτηση δύναμης\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"ζημιά κεραυνού: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"ζημιά κεραυνού: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"ρήψη Φορτισμένων Βλημάτων ανά κτύπημα\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"περιστασιακή τριπλή ζημιά\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"φθορά {:+d}% ζημιά\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x ζημ στους εχθρούς, 1x σε σένα\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Τυχαία ζημιά 0 - 600%\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"χαμηλή ανθ, {:+d}% ζημιά\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"επιπλέον ΚΘ εναντίων δαιμόνων\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"επιπλέον ΚΘ εναντίων απέθαντων\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% των Μάνα πάει στην Ζωή\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Ζωής πάει στα Μάνα\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"ζημιά: {:d}  Άφθαρτο\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"ζημιά: {:d}  Ανθ: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"ζημιά: {:d}-{:d}  Άφθαρτο\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"ζημιά: {:d}-{:d}  Ανθ: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"θωράκιση: {:d} Άφθαρτη\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"θωράκιση: {:d}  Ανθ: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Φορτία: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"μοναδικό Αντικείμενο\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Μη Ταυτοποιημένο\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Το Κρησφύγετο του Βασιλιά των Σκελετών\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Την Αίθουσα των Οστών\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Λαβυρινθος\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Η Δηλητηριασμένη Παροχή Νερού\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Το Κρησφύγετο του Αρχιεπισκόπου Λαζάρου\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Αρένα Εκλησίας\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Αρένα Κόλασης\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Αρένα Κύκλου Ζωής\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Κάτω στο Μπουντρούμι\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Κάτω στις Κατακόμβες\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Κάτω στα Σπήλαια\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Κάτω στην Κόλαση\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Κάτω στην Φωλιά\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Κάτω στην Κρύπτη\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Πάνω στο επίπεδο {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Πάνω στην πόλη\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Κάτω στο επίπεδο {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Κάτω στον Ντιάμπλο\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Πάνω στο επίπεδο Φωλιάς {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Πάνω στο επίπεδο Κρύπτης {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Ο Ακρογωνιαίος Λίθος του Κόσμου\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Κάτω στο επίπεδο Κρύπτης {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Πίσω στο Επίπεδο  {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Αδυναμία ανοίγματος αρχείου παιχνιδιού\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Εσφαλμένο αρχείο παιχνιδιού\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Ο παίκτης είναι σε επίπεδο που υπάρχει μόνο στο Χελφαϊερ\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Εσφαλμένη κατάσταση παιχνιδιού\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Αδυναμία εμφάνισης του κυρίως μενού\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Ζώο\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Δαίμονας\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Απέθαντος\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Είδος: {:s} Έσφαξες: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Σύνολο που έσφαξες: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Πόντοι Ζωής: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Καμία μαγική αντοχή\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Αντοχές:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Μαγεία\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Φωτιά\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Κεραυνός\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Ανοσίες:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Είδος: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Καμία Αντοχή\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Καμία Ανοσία\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Μερικές Μαγικές Αντοχές\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Μερικές Μαγικές Ανοσίες\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Αποτυχία ανοίγματος αρχείου παίκτη για εγγραφή.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"Ο/Η {:s} έριξε μη ορθό ξόρκι.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"Ο/Η {:s} έριξε παράνομο ξόρκι.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Ο παίκτης  '{:s}' (Επίπεδο {:d}) μόλις μπήκε στο παιχνίδι\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Το παιχνίδι έληξε\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Αδυναμία λήψης δεδομένων πίστας\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Ο παίκτης '{:s}' μόλις βγήκε από το παιχνίδι\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Ο παίκτης '{:s}' σκότωσε τον Ντιάμπλο και βγήκε από το παιχνίδι!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Ο παίκτης '{:s}' έπεσε λόγω δικτυακού χρόνου προθεσμίας\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Ο παίκτης '{:s}' (Επιπέδου {:d}) είναι ήδη στο παιχνίδι\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Μυστηριώδες\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Κρυφός\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Ζοφερός\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"του Περίεργου\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Μαγικός\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Πέτρινος\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Θρησκευτικός\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Μαγεμένος\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Θαυματουργικός\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Γοητευτικός\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Αινιγματικός\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Απόκοσμος\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Ανατριχιαστικός\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Θεϊκός\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"της Ιεροσύνης\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Ιερός\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Πνευματικός\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Τραμακτικός\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Εγκατελειμένος\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Φοβιστικός\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Ύσυχός\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Απομονωμένος\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Καλλωπισμένος\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Αστραφτερός\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Σπιλωμένος\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Λαδερός\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Λαμπερός\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Εεπαιτικός\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Σπινθηροβόλος\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Τρεμοπαικτικός\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Ηλιακός\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Μερφικός\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Η Μεγάλη Σύρραξη\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Ο Μισθός της Αμαρτίας είναι ο Πόλεμος\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Η Ιστορία των Χοράντριμ\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Η Σκοτεινή Εξορία\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Ο Πόλεμος της Αμαρτίας\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Το Δέσιμο των Τριών\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Οι Κόσμοι του Υπερπέραντος\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Η Ιστορία των Τριών\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Ο Μαύρος Βασιλιάς\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Πρακτικά: Η Γητεία\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Πρακτικά: Η Συνάντηση\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Πρακτικά: Το Ξέσπασμα\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Πρακτικά: Η Δύναμη του Μεγαλώνει\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Πρακτικά: ΝΑ-ΚΡΟΥΛ\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Πρακτικά: Το Τέλος\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Ένα Βιβλίο με ξόρκια\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Σταυρωμένος Σκελετός\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Μοχλός\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Ανοιχτή Πόρτα\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Κλειστή Πόρτα\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Μπλοκαρισμένη Πόρτα\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Αρχαίος Τόμος\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Βιβλίο της Αχρειότητας\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Μοχλός με Νεκροκεφαλή\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Μυθικό Βιβλίο\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Μικρό Σεντούκι\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Σεντούκι\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Μεγάλο Σεντούκι\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Σαρκοφάγος\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Ράφι Βιβλίων\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Βιβλιοθήκη\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Βαρέλι\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Λοβός\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Τεφροδόχος\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Βωμός\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Σκελετωμένο Αναλόγιο\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Αναλόγιο Εγγράφου\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Σιντριβάνι Αίματος\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Αποκεφαλισμένο Πτώμα\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Το Βιβλίο των Τυφλών\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Το Βιβλίο του Αίματος\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Εξαγνιστική Πηγή\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Θώρακας\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Οπλοβαστός\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Bωμός της Κατσίκας\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Καζάνι\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Θολή Δεξαμενή\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Σιντριβάνι των Δακρύων\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Ατσαλένιος Τόμος\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Βωμός του Αίματος\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Μανιτάρια\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Αχρείa Βάση\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Σκοτωμένος Ήρωας\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} με παγίδα\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (απενεργοποιημένο)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"ON\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"OFF\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Λειτουργία παιχνιδιού\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Ρυθμίσεις του τρόπου που παίζετε το παιχνίδι\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Παίξε Ντιάμπλο ή Χέλλφαϊερ.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Περιορισμός στην Δωρεάν Έκδοση\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends who \"\n\"don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Κάνει το παιχνίδι συμβατό με την δωρεάν έκδοση. Επιτρέπει τετραπλό με φίλους \"\n\"σου που δεν έχουν την πλήρη έκδοση του Ντιάμπλο.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Εκκίνηση\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Ρυθμίσεις Εκκίνησης\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Εισαγωγή\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Εμφάνιση βίντεο εισαγωγής.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Σπλάς\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Εμφάνιση Οθόνης Σπλάς.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Οθόνη Λογότυπου και Τίτλου\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Οθόνη Τίτλου\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Ρυθμίσεις ειδικά για το Ντιάμπλο\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Ρυθμίσεις ειδικά για το Χελφαϊερ\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Ήχος\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Ρυθμίσεις Ήχου\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Ήχος Βαδίσματος\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Ο παίκτης κάνει ήχο όταν κινείται.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Ήχος Αυτόματου εξοπλησμού\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\"Τα αυτόματα εξοπλισμένα αντικείμενα θα κάνουν τον ήχο εξοπλισμού όταν τα \"\n\"μαζεύεις.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Ήχος μαζέματος αντικειμένων\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Όταν μαζεύεις αντικείμενα θα ακούγεται ο ήχος αυτός.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Ρυθμός Δειγματοληψίας Ήχου\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Ρυθμός δειγμάτων (Hz)\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Κανάλια Ήχου\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Αριθμός καναλιών εξόδου ήχου.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Μέγεθος Ενδιάμεσης Μνήμης\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Μέγεθος Ενδιάμεσης Μνήμης (Αριθμός πλαισίων ήχου ανά κανάλι).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Ποιότητα Αναδειγματοληψίας\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Ποιότητα της Αναδειγματοληψίας Ήχου, από 0 (κατώτερο) έως 10 (μέγιστο).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: This \"\n\"can differ from screen resolution, when Upscaling, Integer Scaling or Fit to \"\n\"Screen is used.\"\nmsgstr \"\"\n\"Αφορά την εσωτερική ανάλυση του παιχνιδιού και ορίζει πόσο μεγάλο είναι το \"\n\"πεδίο όρασης στο παιχνίδι. Σημ.: Είναι διαφορετική από την ανάλυση της οθόνης, \"\n\"όταν γίνεται χρήση κλιμάκωσης ή προσαρμογής στην οθόνη.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Αναδειγματολήπτης\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Αναδειγματολήπτης ήχου\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Συσκευή\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Συσκευή εξόδου Ήχου\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Γραφικά\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Ρυθμίσεις Γραφικών\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Πλήρης Οθόνη\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Εμφάνιση του παιχνιδιού σε κατάσταση πλήρους οθόνης ή σε παράθυρο.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Προσαρμογή στην Οθόνη\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Αυτόματη κλιμάκωση του παιχνιδιού στην τρέχουσα ανάλυση και αναλογία της \"\n\"επιφάνειας εργασίας.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Κλιμάκωση\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Ενεργοποίηση της κλιμάκωσης από την ανάλυση του παιχνιδιού στην ανάλυση την \"\n\"οθόνης. Απενεργοποιεί την δυνατότητα αλλαγής της ανάλυσης οθόνης και επιτρέπει \"\n\"την αλλαγή των διαστάσεων του παραθύρου.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Ποιότητα Κλιμάκωσης\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Ενεργοποιεί προαιρετικά φίλτρα υφής για την προβολή όταν γίνεται κλιμάκωση \"\n\"ανάλυσης.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Κοντινότερο Εικονοστοιχείο\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Διγραμικό\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Ανισοτροπικό\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Ακέραια Κλιμάκωση\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Κλιμακώνει την εικόνα με βάση μόνο ακέραιου πολλαπλασιαστή.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Οριζόντιος Συνχρόνισμός\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Μεγέθυνση ενεργή στην επιλογή.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Κεραυνός\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Ανακύλιση Χρωμάτων\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Ανακύλιση χρωμάτων για τα εφέ κινησης της λάβας, του νερού και του οξέος.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Χρήση εναλλακτικής παλέτας για την φωλιά\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"Το παιχνίδι θα χρησιμοποιήσει άλλη παλέτα χρωμάτων για τα γραφικά πίστας της \"\n\"Φωλιάς στο Χελφαΐερ.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Κέρσορας Συστήματος\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Χρήση κέρσορα συστήματος (σε αντίθεση με κέρσορα λογισμικού)\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Κέρσορας συστήματος για Αντικείμενα\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Χρήση κέρσορα συστήματος όταν μεταφέρεις Αντικείμενα.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Μέγεθος του Κέρσορα Συστήματος\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Μέγιστό μήκος και πλάτος για τον κέρσορα συστήματος. Τιμές πέρα από τα όρια \"\n\"στρέφουν στην χρήση κέρσορα λογισμικού.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Εμφάνιση ΚΑΔ\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"\"\n\"Εμφανίζει τα ΚΑΔ(Καρέ ανά Δευτερόλεπτο) στην πάνω αριστερή γωνία της οθόνης.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Παίξιμο Παιχνιδιού\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Ρυθμίσεις του τρόπου που παίζετε το παιχνίδι\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Ενεργοποίηση γρήγορου περπατήματος στην πόλη για το Ντιάμπλο και το Χελφάϊερ. \"\n\"Αυτή η επιλογή προστέθηκε στην προέκταση του παιχνιδιού.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Κλείδωμα εισαγωγής\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"\"\n\"Όταν είναι ενεργοποιημένο, το ποντίκι είναι κλειδωμένο στο παράθυρο του \"\n\"παιχνιδιού.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Ενεργοποίηση της αποστολή με το μικρό κοριτσάκι.\"\n\n#: Source/options.cpp:788\nmsgid \"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Ενεργοποίηση της αποστολής του Τζέρσεϊ, Ο αγρότης Λέστερ, αντικαθίσταται από \"\n\"τον Ολοκληρωτικά Τρελό.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Φιλικό Πύρ\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the friendly \"\n\"mode is on.\"\nmsgstr \"\"\n\"Επιτρέπει τα βέλη και τα Ξόρκια να κάνουν ζημιά σε άλλους παίκτες ακόμα όταν \"\n\"είσαι φιλικός προς παίκτες.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Όλες οι αποστολές ενεργές στο τετραπλό\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Ενεργοποιεί τις πλήρες αποστολές απο το παιχνίδι ενός παίκτη.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Δοκιμή Βάρδου\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Επιτρέπει να διαλέξεις τον Βάρδο κατά την δημιουργία ήρωα.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Δοκιμή Βάρβαρου\"\n\n#: Source/options.cpp:792\nmsgid \"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Επιτρέπει να διαλέξεις τον Βάρβαρο κατά την δημιουργία ήρωα.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Μπάρα Εμπειρίας\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Προσθέτει μια Μπάρα Εμπειρίας στην κάτω καρτέλα στην οθόνη.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Εμφάνιση γραφικών αντικειμένων στα Μαγαζιά\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\"Θα εμφανίζονται τα αντικείμενα με τα γραφικά τους στα αριστερά της κειμενικής \"\n\"τους περιγραφής στα μενού των μαγαζιών.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Εμφάνιση Αριθμού Ζωής\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Δείχνει τον αριθμό των πόντων ζωής πάνω στην σφαίρα ζωής.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Εμφάνιση Αριθμού Μάνα\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Δείχνει τον αριθμό των πόντων μάνα πάνω στην σφαίρα μάνα.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Πληροφορίες Ήρωα\"\n\n#: Source/options.cpp:797\nmsgid \"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Μπάρα Υγείας Εχθρών\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Εμφανίζει την Μπάρα Υγείας Εχθρών στην κορυφή της οθόνης.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Ο χρυσός μαζεύεται αυτόματα όταν τον πλησιάσει ο παίκτης.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Τα ελιξίρια μαζεύονται αυτόματα όταν τα πλησιάσει ο παίκτης.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Τα Λάδια μαζεύονται αυτόματα όταν τα πλησιάσει ο παίκτης.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Αυτόματα μαζεύει αντικείμενα στην πόλη.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Η Άντρια αναπληρώνει τα μάνα σου όταν επισκεφτείς το μαγαζί της.\"\n\n#: Source/options.cpp:805\nmsgid \"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Άμα αγοράσεις ή μαζέψεις ένα όπλο, θα εξοπλιστεί αυτόματα, αν η επιλογή είναι \"\n\"ενεργοποιημένη.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Άμα αγοράσεις ή μαζέψεις μια πανοπλία, θα εξοπλιστεί αυτόματα, αν η επιλογή \"\n\"είναι ενεργοποιημένη.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Άμα αγοράσεις ή μαζέψεις ένα κράνος, θα εξοπλιστεί αυτόματα, αν η επιλογή \"\n\"είναι ενεργοποιημένη.\"\n\n#: Source/options.cpp:808\nmsgid \"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Άμα αγοράσεις ή μαζέψεις μια ασπίδα, θα εξοπλιστεί αυτόματα, αν η επιλογή \"\n\"είναι ενεργοποιημένη.\"\n\n#: Source/options.cpp:809\nmsgid \"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Άμα αγοράσεις ή μαζέψεις χρυσαφικά, θα εξοπλιστεί αυτόματα, αν η επιλογή είναι \"\n\"ενεργοποιημένη.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Σε κάθε νέο παιχνίδι, επιλέγονται τυχαίες αποστολές.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Εμφάνιση Τύπου των Τεράτων\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Αν τοποθετήσεις τον κέρσορα πάνω σε ένα τέρας, θα εμφανιστεί ο τύπος του στο \"\n\"κουτί πληροφοριών στην οθόνη.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\"Όταν είναι ενεργό θα εμφανίζονται ετικέτες για τα αντικείμενα στο έδαφος.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Η ζώνη σου γεμίζει ξανά από τον σάκο σου όταν καταναλώσεις ένα αντικείμενο.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and labeled \"\n\"as disabled.\"\nmsgstr \"\"\n\"Όταν είναι ενεργοποιημένο, ο Συναρπαστικός και Ιερός Βωμός καθώς και οι βωμοί \"\n\"Κατσίκας και Διακόσμησης, δεν μπορούν να γίνουν κλίκ, και είναι \"\n\"απενεργοποιημένοι.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Άμεσα Ξόρκια\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Τα πλήκτρα ξορκιών απευθείας ρίχνουν το ξόρκι, αντί να αλλάζουν το έτοιμο \"\n\"ξόρκι.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Αριθμός Φίλτρων Θεραπείας για αυτόματο μάζεμα.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Αριθμός Φίλτρων Πλήρους Θεραπείας για αυτόματο μάζεμα.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Αριθμός Φίλτρων Μάνα για αυτόματο μάζεμα.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Αριθμός Φίλτρων Πλήρωσης Μάνα για αυτόματο μάζεμα.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Αριθμός Φίλτρων Αναζωογόνησης για αυτόματο μάζεμα.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Αριθμός Φίλτρων Πλήρους Αναζωογόνησης για αυτόματο μάζεμα.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Ενεργοποίηση αριθμών κινητής υποδιαστολής\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\"Ενεργοποίηση αριθμών κινητής υποδιαστολής για τις αριθμητικές λειτουργίες των \"\n\"πόντων εμπειρίας / του υπολογισμού της ζημιάς και άλλων συστημάτων.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Απενεργοποιημένο\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Τυχαίες Γωνίες\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Κάθετα Μόνο\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Xειριστήριο\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Ρυθμίσεις Χειριστηρίου\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Δίκτυο\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Ρυθμίσεις Δικτύου\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Συνομιλία\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Ρυθμίσεις Συνομιλίας\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Γλώσσα\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Ορίζει ποια γλώσσα θα χρησιμοποιεί το παιχνίδι.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Ρυθμίσεις Γλώσσας\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Ορισμός Πλήκτρων\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Ρυθμίσεις Ορισμού Πλήκτρων\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Ορισμός Πλήκτρων Χειριστηρίου\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Ρυθμίσεις Ορισμού Πλήκτρων Χειριστηρίου\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Ρυθμίσεις\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Επίπεδο\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Εμπειρίες\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Επόμενο Επίπεδο\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Βάση\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Τελικό\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Δύναμη\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Μαγεία\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Επιδξτητα\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Ζωτικότητα\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Πόντους Επιλογής\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Χρυσός\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Θωράκιση\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"ενός όπλου να χτυπήσει\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Ζημιά\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Ζωή\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Μάνα\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Αντοχή Μαγείας\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Αντοχή Φωτιάς\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Αντοχή Κεραυνού\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"ήρωας\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"στόχοι\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"χάρτης\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"μενού\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"σάκος\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"ξόρκια\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"φωνή\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"σίγαση\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Άχρηστο\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Ζημιά: 1/3 ζωής\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Θεραπεύει {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Ζημια: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Δεξιότητα\"\n\n#: Source/panels/spell_book.cpp:176\n#, fuzzy, c++-format\n#| msgid \"Staff ({:d} charge)\"\n#| msgid_plural \"Staff ({:d} charges)\"\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Ράβδος ({:d} φορτίο}\"\nmsgstr[1] \"Ράβδος ({:d} φορτία}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Επίπ. {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Μάνα: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Ξόρκι\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Κάνει ζημιά σε απέθαντους μόνο\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Πάπυρος\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Ράβδος\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Πλήκτρο για Ξόρκι {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Αποτυχία κατά το άνοιγα αρχείου\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Αποτυχία κατά την φόρτωση χαρακτήρα\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (Επίπεδο {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Ιστορικό Συνομιλιών (Μηνύματα: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} χρυσά\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Πόσα χρυσά νομίσματα θέλεις να κάνεις ανάληψη;\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Επίπεδο {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Εμπειρίες {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Μέγιστο Επίπεδο\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Επόμενο Επίπεδο: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} για Επίπεδο {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Ο Τάφος του Βασιλιά Λεόρικ\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Η Αίθουσα των Οστών\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Ένα σκοτεινό μονοπάτι\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Ανίερος Βωμός\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Πρός {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Χρειάζομαι βοήθεια! Έλα εδώ!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Ακολούθα με.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Έχω κάτι για σένα.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Τώρα θα ΠΕΘΑΝΕΙΣ!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Ευχαριστούμε τους\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Γκρίσουαλντ\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Πέπιν\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Όγκντεν\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Κάιν\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Φάρνχαμ\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Άντρια\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Γκίλλιαν\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Ουίρτ\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Πίσω\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Ζημιά: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Θωράκιση: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Ανθ: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"άφθαρτο\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Καλώς ήρθες στο\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Μαγαζί του Σιδηρουργού\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Θα ήθελες να:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Μιλήσεις στον Γκρίσγουαλντ\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Αγοράσεις απλά αντικείμενα\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Αγοράσεις αντικείμενα αξίας\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Πουλήσεις αντικείμενα\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Επιδιορθώσεις αντικείμενα\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Φύγεις από το Μαγαζί\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Έχω τα παρακάτω για πώληση:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Έχω τα παρακάτω ακριβά για πώληση:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Δεν έχεις τίποτα που θέλω.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Ποιο αντικείμενο είναι για πούλημα;\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Δεν έχεις τίποτα για επιδιόρθωση.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Πιο αντικείμενο θέλει επιδιόρθωση;\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Η Παράγκα της Μάγισσας\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Μιλήσεις στην Άντρια\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Αγοράσεις αντικείμενα\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Επαναφορτίσεις Ράβδους\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Φύγε από την παράγκα\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Δεν έχεις τίποτα για επαναφόρτιση.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Ποια ράβδος θες να φορτίσεις;\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Δεν έχεις αρκετό χρυσό\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Δεν έχεις χώρο στον σάκο σου\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Είμαστε σύμφωνοι;\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Σίγουρα θες να ταυτοποιήσεις το αντικείμενο αυτό;\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Σίγουρα θες να αγοράσεις το αντικείμενο αυτό;\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Σίγουρα θες να επαναφορτίσεις το αντικείμενο αυτό;\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Σίγουρα θες να πουλήσεις το αντικείμενο αυτό;\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Σίγουρα θες να επιδιορθώσεις το αντικείμενο αυτό;\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Ο Ουίρτ, με το Ξύλινο Πόδι\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Μίλα με τον Ουίρτ\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Έχω κάτι προς πώληση,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"αλλά θα δώσεις 50 χρυσά\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"μονό για να το δεις. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Τι έχεις;\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Πες αντίο\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Έχω αυτό για πώληση:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Φύγε\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Το σπίτι του Θεραπευτή\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Μιλήσεις στον Πέπιν\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Φύγε από το σπίτι του Πέπιν\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Ο Γέροντας της Πόλης\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Μιλήσεις στον Κάιν\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Ταυτοποιήσεις ένα αντικείμενο\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Δεν έχεις τίποτα για ταυτοποίηση.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Πιο αντικείμενο θέλεις να ταυτοποιήσω;\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Αυτό το αντικείμενο είναι:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Τελειώσαμε\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Συνομιλία - {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Συνομιλία - {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"δεν είναι διαθέσιμο\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"στην δωρεάν\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"έκδοση\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Κουτσομπολιό\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Πανδοχείο 'Ανατέλλων Ήλιος'\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Μιλήσεις στον Όγκντεν\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Φύγε από την Ταβέρνα\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Μιλήσεις στην Γκίλλιαν\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Πρόσβαση Στην Αποθήκη\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Φάρνχαμ ο Μεθύστακας\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Μιλήσεις στον Φάρνχαμ\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Πες αντίο\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Ο χρυσός σου: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Σφαγμένος Κάτοικός\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Γκρίσουαλντ o Σιδηρουργός\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Πέπιν ο Θεραπευτής\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Τραυματισμένος Κάτοικος\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Όγκντεν ο ιδιοκτήτης της Ταβέρνας\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Κάιν ο Σοφός Γέροντας\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Άντρια η Μάγισσά\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Γκίλλιαν η Σερβιτόρα\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Αγελάδα\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Λέστερ ο Γεωργός\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Σέλια\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Τρελός\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Πολεμιστής\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Kλεφτρόνι\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Μάγος\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Μοναχός\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Βάρδος\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Βάρβαρός\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Ζόμπι\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Ζόμπι Βρυκόλακας\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Σαπισμένο Πτώμα\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Μαύρος Θάνατος\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Έκπτωτος\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Χαράκτης\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Διάβολοσόϊ\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Σκοτεινός\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Σκελετός\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Πτώμα με Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Φλεγόμενος Νεκρός\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Τρόμος\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Σαπροφάγος\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Καταβροχθέας Πανώλης\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Σκιώδες Θηρίο\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Χαρακωτής Κοκάλων\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Πτώμα με Τόξο\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Σκελετωμένος Λοχαγός\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Πτώμα Λοχαγού\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Φλεγόμενος Νεκρός Λοχαγός\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Λοχαγός του Τρόμου\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Αόρατος Άρχοντας\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Κρυφός\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Διώκτης\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Αθέαντος\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Υφαντής των ψευδαισθήσεων\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Άρχοντας Σάτυρος\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Η Φυλή της Σάρκας\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Η Φυλή της Πέτρας\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Η Φυλή της Φωτιάς\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Η Φυλή της Νύχτας\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Κτηνώδες Πετούμενο\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Αστραπιαίο Πετούμενο\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Ζοφερό Πετούμενο\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Μαγικός Ιπτάμενος Σύντροφος\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Όξινο Θηρίο\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Φτύστης Δηλητηρίου\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Θηρίο του Λάκου\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Στόμα Λάβας\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Βασιλιάς των Σκελετών\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Ο Χασάπης\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Δεσπότης\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Λασπωμένος\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Δαιμονικός Βάτραχος\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Γδαρμένος\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Δρακόντειος\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Γυμνοσάλιαγκας Σπηλαίων\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Διαβολικός Δράκοντας\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Καταβροχθέας\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Δαίμονας Μάγματος\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Ματωμένη Πέτρα\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Πέτρα της Κολάσεως\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Άρχονας της Λάβας\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Κερατάς Δαίμονας\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Δρομέας της Λάσπης\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Καταδρομέας του Παγετού\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Οψιανός Άρχοντας\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"γερασμένο Κόκαλο\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Κόκκινος Θάνατος\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Απέθαντος Μάγος Δαίμονας\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Απέθαντο Μπάλρογκ\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Αποτεφρωτής\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Άρχοντας της Φλόγας\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Φωτιά της Καταστροφής\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Καυστήρας της Κόλασης\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Κόκκινη Θύελλα\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Καβαλάρης της θύελλας\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Άρχοντας της θύελλας\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Ζωντανή Δίνη\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Κτηνώδες Διάβολοσόϊ\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Φτερωτός Δαιμονας\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Γκαργκόϊλ\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Ματωμένο Νύχι\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Φτερωτός Θάνατος\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Σφάχτης\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Προστάτης\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Άρχοντας της Δίνης\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Μπάλρογκ\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Οχιά της Σπιλιάς\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Δράκος της Φωτιάς\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Χρυσή Οχιά\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Κυανός Δράκος\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Μαύρος Ιππότης\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Φρουρός του Χαμού\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Ατσαλένιος Άρχοντας\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Ιππότης του Αίματος\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Ο Κοματιασμένος\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Κενό Πλάσμα\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Άρχοντας του Πόνου\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Υφαντής της Πραγματικότητας\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Σούκουμπους\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Μάγισσα του Χιονιού\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Γόνος της Κολάσεως\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Καυστήρας των Ψυχών\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Σύμβουλoς\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Δικαστής\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Μέλος Σάχτας\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Συνήγορος\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Πήλινος Μαχητής\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Ο Σκοτεινός Άρχοντας\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Ο Απέθαντος Αρχιμάγος Μαλίγκνους\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Γκάρμπάντ Ο Αδύναμος\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Ζάρ ο Τρελός\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Μυξορίχτης\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Ο Αρχιεπίσκοπος Λάζαρος\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Κόκκινη Αγανάκτηση\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Ο Μαύρος Νεφρίτη\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Λακντάναν\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Ο Πολέμαρχος του Αίματος\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Σαρκοδαίμονας\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Ο Βεβηλωτής\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Να-Κρούλ\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Κοφτερό Σκελετωμένο Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Ο Λεπιδόδερμας ο Κόφτης\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Το Πύον της Ψυχής\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Το Εμετικό Ακάθαρτο Ποντίκι\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Κόκαλόξηλωτής\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Σαπιοφάγος Ο Πεινασμένος\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Εντεροκνήμης Ο Γρήγορος\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Ο Σπαζοκέφαλος Ασπιδοκτύπης\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Μπόνγκο\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Σαπισμένος Μακελάρης\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Σκιωδαγκανιάρης\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Νεκρομάτης\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Τρελομάτης ο Νεκρός\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"Ελ Τσουπακάμπρας\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Κρανιοφωτιά\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Το Διαστροφικό Κρανίο\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Αιματόγλωσσος\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Παλμοερπετό\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Ο Λυγιστής της Σελήνης\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Το Κοράκι της Οργής\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Ο Καταβροχθέας Σπονδύλων\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Η Μαύρη Στάχτη της Ανάφλεξης\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Σκιεροκόρακας\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Περονόπετρος, Ο Αδύναμος\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Ο Αφρίστης Χολής, Ο Άρχοντας του Λάκκου\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Αιματόδερμος, το Σκοτεινό Τόξο\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"To Βρωμερό Πτερύγιο\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Ο Πότης των Σκιών\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Ομιχλώδες Περπατητής\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Θανατοφτύχτης\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Το Αυλάκι Αίματος\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Η Σκιά του Θανάτου, η Σφύρα της Σάρκας\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Το Σκουλήκι του Πολέμου, ο Τρελός\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Γυαλιόκρανος ο Οδοντωτός\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Η Άρρωστη Φωτιά\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Το Κρύο Φτερό της Νύχτας\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Η Αιματοβαμμένη Πέτρα\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Χαλκόγρονθος, ο Φλογόπετρος\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Η Φωτιά της Οργής και του Χαμού\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Η Βλοσυρή Φλεγόμενη Πληγή\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Ο Βαρόνος της Γλίτσας\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Αρρωστοκέρατος, το Ατσαλένιο Σκήπτρο\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Ουρλιαχτός του Χάους\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Χαμοφέρνης ο Σάπιος\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Τρελόεμπρηστής\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Κοκαλοπρίονος, Ο Απέθαντος Μάγος\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Σπονδυλοσπάστης\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Δαιμονόκρανος, το Αιχμηρό Κόκαλο\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Η Σπασμένη Καταιγίδα\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Ο Όλεθρος της Καταιγίδας\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Λασποσαλιαρίδης\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Χρυσοφθορός της Φλόγας\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Ο Μαύρος Καταδρομέας\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Η Οργή της Πανούκλας\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Ο Γδάρτης\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Το Μπλέ Κέρατο\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Η Διατροφική Φλόγα, η Κολασμένη\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Οδοντόσπειρα\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Πυόκρανος\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Λεοντόκρανιος ο Λυγισμένος\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Η Μαύρη Γλώσσα\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Το Αχρείο Άγγιγμα\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Η Φλεγόμενη Οχιά\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Οδοντόδερμα\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Η Ανίερη Φλόγα της Μάγισσάς\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Το Μαύρο Κρανίο\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Χαράκτης των Ψυχών\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Ο Γόνος του Ανέμου\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Άρχοντας του Λάκκου\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Υφαντής της Σκουριάς\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Το Θυμωμένο Ουρλιαχτό, το Σκιώδες\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Σύννεφο του Χαμού\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Ματωμένη Σελήνη, Η Φωτιά της Ψυχής\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Η Μάγισσα της Σελήνης\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Αιματογλέντης\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Γκριζοπόλεμος ο Σφάχτης\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Ο Δικαστής του Τρόμου\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Αστρομάτα, Η Μάγισσα\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Ατσαλόκρανιος Ο Κυνηγός\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Σερ Γκόρας\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Ο Βεζίρης\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Ζαμφίρ\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Αιμολάγνα\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Η Χήρα του Ιστού\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Ο Χορευτής της Σάρκας\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"To Βλοσυρό Δόρυ\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Μάντης του Χαμού\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Ξίφος\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Πόρπη\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Ρόπαλο\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Κοντό Τόξο\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Κοντή Ράβδος του Μάνα\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Μπαλτάς\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Η Απέθαντη Κορώνα\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Δακτύλιος των Ουρανών\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Μαγική Πέτρα\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Οπτικό Φυλακτό\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Δαχτυλίδι της Αλήθειας\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Πινακίδα Ταβέρνας\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Λοφίο Αρλεκίνου\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Πέπλο από Ατσάλι\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Χρυσό Ελιξίριο\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Το Αμόνι της Οργής\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Μαύρο Μανιτάρι\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Εγκέφαλος\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Μυκητιακός Τόμος\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Φασματικό Ελιξίριο\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Πέτρα Αίματος\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Χάρτης Καθεδρικού Ναού\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Φίλτρο Θεραπείας\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Φίλτρο Μάνα\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Πάπυρoς Ταυτοποίησης\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Πάπυρος Πύλης Πόλης\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Η Ανδρεία του Αρκαϊν\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Φίλτρο Πλήρους Θεραπείας\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Φίλτρο Πλήρωσης Μάνα\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Η Άκρη του Γκρίσγουαλντ\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Βοδινή Πανοπλία\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Ράβδος του Λαζάρου\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Πάπυρος Ανάστησης\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Κοντή Ράβδος\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Σπαθί\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Μάχαιρα\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Βόμβα Ρούνων\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Θεόδωρος\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Φυλακτό του Χρυσού\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Σκισμένο Σημείωμα 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Σκισμένο Σημείωμα 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Σκισμένο Σημείωμα 2\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Συναρμολογημένο Σημείωμα\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Καφέ Στολή\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Γκρίζα Στολή\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Σκούφος\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Φολιδωτο Κράνος\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Ελαφρύ Κράνος\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Ολομεταλλικό Κράνος\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Κορώνα\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Περικεφαλαία\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Κάπα\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Κουρέλια\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Μανδύας\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Ρόμπα\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Kαπιτονέ πανοπλία\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Δερμάτινος Θώράκας\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Σκληρός Δέρματος Θώρακας\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Δερμάτινος Θώρακας με Καρφιά\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Δαχτυλιδωτός Θώρακας\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Αλυσιδωτός Θώρακας\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Αλυσιδωτή Πανοπλία\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Φολιδωτή Πανοπλία\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Μεταλλικός Θώρακας\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Ολομεταλλικός Θώρακας\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Σκληθρωτή Πανοπλία\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Ολομεταλλική Πανοπλία\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Πλήρης  Ολομεταλλικός Θώρακας\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Γοτθική Ολομεταλλική Πανοπλία\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Πλήρης Ολομεταλλική Εξάρτυση\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Ασπίδα\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Μικρή Ασπίδα\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Μεγάλη Ασπίδα\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Ασπίδα Χαρταετού\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Ασπίδα Πύργου\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Γοτθική Ασπίδα\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Φίλτρο Αναζωογόνησης\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Φίλτρο Πλήρους Αναζωογόνησης\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Λάδι\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Ελιξίριο Δύναμης\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Ελιξίριο Μαγείας\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Ελιξίριο Επιδεξιότητας\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Ελιξίριο Ζωτικότητας\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Πάπυρος Θεραπείας\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Πάπυρος Αναζήτησης\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Πάπυρος Κεραυνού\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Πάπυρος Τείχους Φωτιάς\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Πάπυρος Λαίλαπας\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Πάπυρος Λάμψης\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Πάπυρος Υπέρυθρης Όρασης\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Πάπυρος Φασικής Μεταφοράς\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Πάπυρος Ασπίδας από Μάνα\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Πάπυρος Κύματος Φωτιάς\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Πάπυρος Οβίδας Φωτιάς\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Πάπυρος Κατάρας Πέτρωσης\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Πάπυρος Αλυσιδωτών Κεραυνών\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Πάπυρος Προστάτη\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Πάπυρος Αστρικής Έκρηξης\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Πάπυρος Πήλινου Μαχητή\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Πάπυρος Τηλεμεταφοράς\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Πάπυρος Αποκάλυψης\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Φάλτσιο\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Γιαταγάνι\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Δίκοπο Ξίφος\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Λεπίδα\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Φάλξ\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Σπάθα\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Ρομφαία\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Μπάσταρδη Σπάθα\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Δίχειρη Βαριά Σπάθα\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Κατάνα\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Τσεκουράκι\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Πέλεκυς\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Φαρδύ Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Δικέφαλο Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Μεγάλο Βαρύ Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Κεφαλοθραύστης\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Αγκαθωτός Κεφαλοθραύστης\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Σφύρα Πολέμου\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Σφύρί\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Ρόπαλο με Καρφιά\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Κόπανος\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Βαριά Σφύρα Πολέμου\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Τόξο\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Κυνηγετικό Τόξο\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Μακρύ Τόξο\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Σύνθετο Τόξο\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Κοντό Τόξο Μάχης\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Μακρύ Τόξο Μάχης\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Κοντό Τόξο Πολέμου\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Μακρύ Τόξο Πολεμού\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Πλούσια Ράβδος\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Σύνθετη Ράβδος\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Μακριά Ράβδος\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Πολεμική Ράβδος\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Δαχτυλίδι\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Φυλακτό\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Ρούνος της Φωτιάς\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Ρούνος\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Ρούνος του Κεραυνού\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Ανώτερος Ρούνος της Φωτιάς\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Ανώτερος Ρούνος του Κεραυνού\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Ρούνος της Πέτρας\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Κοντή Ράβδος των Φορτισμένων Σφαιριδίων\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Φίλτρο Αρένας\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Ο Μπαλτάς του Χασάπη\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Φωτόσπαθο\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Το Τόξο του Ρήγματος\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Ο Βελονιστής\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Το Τόξο των Ουρανών\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Ο Θανατηφόρος Κυνηγός\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Το Τόξο των Νεκρών\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Το Τόξο της Μαύρης Βελανιδιάς\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Βέλος της Φλόγας\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Το Κεντρί  της Σάρκας\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Η Δύναμη του Ανέμου\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Το Κέρας του Αετού\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Το Ξιφίδιο του Γκόναγκαλ\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Ο Αμυνόμενος\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Το Νύχι του Γρυπαετού\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Το Μαύρο Ξυράφι\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Η Αμφίκυρτος Σελήνη\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Το Μαχαίρι του Πάγου\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Η Λεπίδα του Εκτελεστή\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Το Πριόνι για Κόκκαλα\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Το Γεράκι της Σκιάς\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Η Αιχμή του Μάγου\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Φωτόσπαθο\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Το Νύχι του Αετού\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Λαίλαπα\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"O Μόρος\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Η Γρίζλι\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Ο Προπάππους\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Ο Ξεσκιστής\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Το Aιχμηρό Ράμφος\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Ο Φονιάς του Αίματος\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Το Ουράνιο Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Το Κακόβουλο Τσεκούρι\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Ο Μπαλτάς της Πέτρας\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Το Τσεκούρι της Αγκουϊνάρας\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Ο Σφάχτης της Κολάσεως\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"O Θεριστής του Μέσσερσμιντ\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Η Σκουριασμένη Ρωγμή\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Το Σφυρί του Γιόλμ\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Το Ρόπαλο του Κίβερμπ\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Το Ουράνιο Άστρο\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Το Άστρο του Μπάραναρ\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Οζώδης Ρίζα\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Ο Κόπανος των Κρανίων\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Η Σφύρα του Σχάφερ\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Ο Κεφαλοθραύστης των Ονείρων\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Η Ράβδος των Σκιών\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Ο Αναφλέκτηρας\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Ο Πυργίσκος της Θύελας\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Το Λαμπερό Τραγούδι\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Το Κάλεσμα του Κεραυνού\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Ο Προστάτης\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Ο Γρίφος του Νάτζ\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Το Κλάμα του Νού\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Η Ράβδος του Ονάν\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Το Κράνος των Πνευμάτων\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Σκούφος Σκέψης\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Η Περικεφαλαία του Άρχοντα\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Το Λοφίο του Βλαμμένου\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"To Λυκόφως των Θεών\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Βασιλικό Διάδεμα\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Η Σκισμένη Σάρκα των Ψυχών\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Το Μαρτύριο του Μονομάχου\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Ο Μανδύας του Ουράνιου Τόξου\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Το Δέρμα του Αούτ\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Το Περιτύλιγμα της Σοφίας\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Ο Αστραφτερός Αλυσιδωτός Θώρακας\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"To Καύκαλο του Σαπροφάγου\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Νυχτερινό Τοπίο\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Ο Ολομεταλλικός Θώρακας του Νάτζ\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Το Παλτό της Δαιμόνιας Αιχμής\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Ο Εκτροπέας\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Η Ασπίδα του Ραγισμένου Κρανίου\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Η Ρωγμή του Δράκου\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Η Ασπίδα της Μαύρης Βελανιδιάς\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Ο Άγιος Υπερασπιστής\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Η Ασπίδα της Θύελλας\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Ο Βάτος\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Το Δακτυλίδι της Ρέγκχας\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Το Ρεμάλι\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Το Περιοριστικό Δακτυλίδι\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Το δακτυλίδι της Συμπλοκής\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"του Κασσίτερου\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"του Oρείχαλκου\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"του Μπρούτζου\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"του Σιδήρου\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"του Ατσαλιού\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"του Ασημιού\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"της Πλατίνας\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"του Μίθριλ\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"του Μετεωρίτη\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"του Παράξενου\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"του Άχρηστου\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"του Λυγισμένου\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"του Αδύναμου\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"της Οδόντωσης\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"του Θανατηφόρου\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"της Ενίσχυσης\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"του Φαύλου\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"της Κτηνωδίας\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"του Ογκού\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"της Αγριότητας\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"του Αδίστακτου\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"του Ανελέητου\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"του Άτσαλου\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"της Άμβλυσης\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"της Αιχμηρότητας\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"της Εξοχότητας\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"του Μαχητή\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"του Στρατιώτη\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"του Άρχονα\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"του Ιππότη\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"του Μαέστρου\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"του Πρωταθλητή\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"του Βασιλιά\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"του Ευάλωτου\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"της Σκουριάς\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"της Δύναμης\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"της Μεγαλότητας\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"του Θάρρους\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"της Δόξας\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"της Ευλογίας\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"του Άγιου\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"του Φανταστικού\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"του Θεού\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"του Κόκκινου\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"του Πορφυρού\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"του Λυχνίτη\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"του Ρουμπινιού\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"του Μπλέ\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"του Γαλάζιου\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"του Λάπις\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"του Κοβάλτιου\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"του Ζαφειριού\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"του Λευκού\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"του Μαργαριταριού\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"του Ελεφαντόδοτου\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"του Κρυστάλου\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"του Διαμαντιού\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"του Τόπαζ\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"του Κεχριμπαριού\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"του Νεφρίτη\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"του Οψιανού\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"του Σμαραγδιού\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"της Ύαινας\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"του Βατράχου\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"της Αράχνης\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"του Κόρακα\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"του Φιδιού\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"του Ερπετού\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"της Σαύρας\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"του Δρακόμορφου\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"του Δράκοντα\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"της Ύδρας\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"των Αγγέλων\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"των Αρχαγγέλων\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"της Αφθονίας\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"της Πλουσιότητας\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"της Φλόγας\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"του Κεραυνού\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"της Ποιότητας\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"της Ακρωτηρίασης\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"του Φόνου\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"της Αιματοχυσίας\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"του Μακελιού\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"της Σφαγής\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"του Πόνου\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"των Δακρύων\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"της Υγείας\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"της Προστασίας\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"της Απορόφησης\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"της Απόκρουσης\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"της Όσμωσης\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"της Ευθραυστότητας\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"της Αδυναμίας\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"της Δύναμης\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"της Ισχύς\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"της Εξουσίας\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"των Γιγάντων\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"των Τιτάνων\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"της Παράλυσης\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"της Ατροφίας\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"της Επιδεξιότητας\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"της Δεξιότητας\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"της Ευστοχίας\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"της Ακρίβειας\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"της Τελειότητας\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"του Χαζού\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"της Δυσλεξίας\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"της Μαγείας\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"του Μυαλού\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"της Λαμπρότητας\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"της Βασκανείας\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"των Μάγιστρων\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"της Αρρώστιας\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"της Επιδημίας\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"της Ζωτικότητας\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"του Πάθους\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"της Ζωντάνιας\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"του Σφρίγους\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"της Ζωής\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"του Μπελά\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"της Τρύπας\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"του Ουρανού\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"της Σελήνης\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"των Άστρων\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"των Ουρανών\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"του Ζωδιακού Κύκλου\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"του Αρπακτικού\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"του Τσακαλιού\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"της Αλεπούς\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"του Ιαγουάρου\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"του Αετού\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"του Λύκου\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"της Τίγρης\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"του Λιονταριού\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"του Μαμούθ\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"της Φάλαινας\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"της Ευθραυστότητας\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"της Διαλύσης\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"της Ανθεκτικότητας\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"της Αριστοτεχνείας\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"της Δομής\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"των Εποχών\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"του Σκότους\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"της Νύχτας\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"του Φωτός\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"της Ακτινοβολίας\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"της Φλόγας\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"της Φωτιάς\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"της Ανάφλεξης\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"του Ηλεκτροσόκ\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"της Βροντής\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"του Κεραυνού\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"των Πολλών\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"της Αφθονίας\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"των Αγκαθιών\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"της Διαφθόρας\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"των Κλεφτών\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"της Αρκούδας\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"της Νυχτερίδας\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"του Βρυκόλακα\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"της Βδέλλας\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"του Αίματος\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"της Διαπέρασης\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"του Τρυπήματος\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"του Ξυλοδαρμού\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"της Ετοιμότητας\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"της Σβελτάδας\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"της Ταχύτητας\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"της Βιασύνης\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"της Ισορροπίας\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"της Σταθερότητας\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"της Αρμονίας\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"της Παρεμπόδισης\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Ο Μαγικός Βράχος\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Γκάρμπάντ Ο Αδύναμος\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Ζάρ ο Τρελός\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Λακντάναν\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Ο Χασάπης\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Η Ταμπέλα του Όγκντεν\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Η Αίθουσες των Τυφλών\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Ανδρεία\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Ο Πολέμαρχος του Αίματος\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Η Κατάρα του Βασιλιά Λεόρικ\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Λάζαρος Ο Αρχιεπίσκοπος\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Τα ζητήματα του Τάφου\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Ο Οπωρώνας του Αγρότη\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Μικρό Κοριτσάκι\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Πλανόδιος Έμπορας\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Ο Βεβηλωτής\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Να-Κρούλ\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Η Στολή της Αγελάδας\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Σφαιρίδιο Φωτιάς\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Θεραπεία\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Κεραυνός\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Λάμψη\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Ταυτοποίηση\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Τείχος Φωτιάς\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Πύλη Πόλης\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Κατάρα Πέτρωσης\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Υπέρυθρη Όραση\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Φασική Μεταφορά\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Ασπίδα από Μάνα\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Οβίδα Φωτιάς\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Προστάτης\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Αλυσιδωτοί Κεραυνοί\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Κύμα Φωτιάς\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Ερπετά του Χαμού\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Τελετή Αίματος\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Αστρική Έκρηξη\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Εξαφάνιση\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Λαίλαπα\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Πήλινος Μαχητής\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Οργή\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Τηλεμεταφορά\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Αποκάλυψη\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Αιθεροποιήση\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Επισκευή Αντικειμένου\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Επαναφόρτιση Ράβδου\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Αφόπλιση Παγίδας\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Στοιχείο Φωτιάς\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Φορτισμένα Σφαιρίδια\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Ιερό Σφαιρίδιο\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Ανάστηση\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Τηλεκίνηση\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Θεραπεία Άλλου\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Άστρο Αίματος\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Πνεύμα των Οστών\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh blow \"\n\"to this land. The people always loved the King, and now they live in mortal \"\n\"fear of him. The question that I keep asking myself is how he could have \"\n\"fallen so far from the Light, as Leoric had always been the holiest of men. \"\n\"Only the vilest powers of Hell could so utterly destroy a man from within...\"\nmsgstr \"\"\n\" Αχχ, η ιστορία του βασιλιά μας; Η τραγική πτώση του Λεόρικ ήταν ένα βάναυσο \"\n\"χτύπημα για την χώρα. Ο Λαός πάντα αγαπούσε τον Βασιλιά, αλλά τώρα ζούνε με \"\n\"θανάσιμο φόβο για αυτόν. Η ερώτηση που κάνω συνέχεια στον εαυτό μου είναι πώς \"\n\"μπόρεσε και έπεσε τόσο μακριά από το φώς, γιατί ο Λεόρικ ήταν από τους πιο \"\n\"άγιους  άντρες. Μόνο οι πιο χυδαίες δυνάμεις την Κολάσεως μπορούν κα \"\n\"καταστρέψουν έναν άνθρωπο εκ των έσω...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Το χωριό χρειάζεται την βοήθεια σου, καλέ/ή μου άρχοντα/ίσσα! Πρίν μερικούς \"\n\"μήνες ο γιός του Βασιλιά Λεόρικ, ο Πρίγκιπάς Άλμπρεχτ απήχθη. Ο Βασιλιάς \"\n\"εξαγριώθηκε και όργωσε το χωριό μας ψάχνοντας το αγνοούμενο παιδί. Καθώς \"\n\"περνούσαν οι μέρες, ο Λεόρικ φαινόταν να γλιστράει πιο βαθιά στην τρέλα. \"\n\"Προσπάθησε να κατηγορήσει τους αθώους κατοίκους της πόλης για την εξαφάνιση \"\n\"του αγοριού και άρχισε να τους εκτελεί με βάναυσο τρόπο. Λιγότεροι από τους \"\n\"μισούς από εμάς επέζησαν από την παραφροσύνη του...\\n\"\n\"Οι Ιππότες και οι Ιερείς του Βασιλιά προσπάθησαν να τον κατευνάσουν, αλλά \"\n\"στράφηκε εναντίον τους και δυστυχώς, αναγκάστηκαν να τον σκοτώσουν. Με την \"\n\"ετοιμοθάνατη ανάσα του, ο Βασιλιάς έριξε μια τρομερή κατάρα στους πρώην \"\n\"ακόλουθους του. Ορκίστηκε ότι θα τον υπηρετήσουν στο σκοτάδι για πάντα...\\n\"\n\"\\n\"\n\"Εδώ είναι που τα πράγματα παίρνουν μια ακόμη πιο σκοτεινή τροπή από ό,τι \"\n\"νόμιζα ότι είναι δυνατόν! Ο πρώην βασιλιάς μας έχει σηκωθεί από τον αιώνιο \"\n\"ύπνο του και τώρα διοικεί μια λεγεώνα από απέθαντους μέσα στον Λαβύρινθο. Το \"\n\"σώμα του θάφτηκε σε έναν τάφο τρία επίπεδα κάτω από τον καθεδρικό ναό. Σε \"\n\"παρακαλώ, καλέ/ή μου άρχοντα/ίσσα, ηρέμησε την ψυχή του καταστρέφοντας την \"\n\"καταραμένη πλέον μορφή του...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Όπως σου είπα, καλέ/ή μου άρχοντα/ίσσα, ο Βασιλιάς ήταν ενταφιασμένος τρία \"\n\"επίπεδα πιο κάτω. Είναι εκεί κάτω, περιμένοντας στο σάπιο σκοτάδι την ευκαιρία \"\n\"του να καταστρέψει αυτή τη γη...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Η κατάρα του Βασιλιά μας πέρασε, αλλά φοβάμαι ότι ήταν μόνο ένα μικρό μέρος \"\n\"ενός μεγαλύτερου κακού. Ωστόσο, μπορεί ακόμη να σωθούμε από το σκοτάδι που \"\n\"κατατρώει τη γη μας, γιατί η νίκη μας είναι καλός οιωνός. Είθε το Φως να σε \"\n\"καθοδηγήσει στο δρόμο σου, καλέ/ή μου άρχοντα/ίσσα.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over this \"\n\"kingdom from that day forward, but perhaps if you were to free his spirit from \"\n\"his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Η απώλεια του γιου του ήταν υπερβολική για τον Βασιλιά Λέορικ. Έκανα ό,τι \"\n\"μπορούσα για να απαλύνω την τρέλα του, αλλά στο τέλος αυτή τον νίκησε. Μια \"\n\"μαύρη κατάρα κρεμόταν πάνω από αυτό το βασίλειο από εκείνη την ημέρα και μετά, \"\n\"αλλά ίσως αν απελευθερώσεις το πνεύμα του από την επίγεια φυλακή του, η κατάρα \"\n\"θα αρθεί...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for the \"\n\"kind and just ruler that he was. His death was so sad and seemed very wrong, \"\n\"somehow.\"\nmsgstr \"\"\n\"Δεν μου αρέσει να σκέφτομαι πώς πέθανε ο Βασιλιάς. Μου αρέσει να τον θυμάμαι \"\n\"για τον ευγενικό και δίκαιο κυβερνήτη που ήταν. Ο θάνατός του ήταν τόσο \"\n\"λυπηρός και φαινόταν πολύ λάθος, κατά κάποιο τρόπο.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe how \"\n\"he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Έφτιαξα πολλά από τα όπλα και τις περισσότερες από τις πανοπλίες που \"\n\"χρησιμοποιούσε ο Βασιλιάς Λεόρικ για να εξοπλίσει τους ιππότες του. Έφτιαξα \"\n\"ακόμη και ένα τεράστιο δίχειρο σπαθί από το καλύτερο μίθριλ για εκείνον, καθώς \"\n\"και ένα πολύτιμο στέμμα για να ταιριάζει. Ακόμα δεν μπορώ να πιστέψω πώς \"\n\"πέθανε, αλλά πρέπει να ήταν κάποια απαίσια δύναμη που τον τρέλανε!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Δεν με νοιάζει αυτό. Άκου, κανένας σκελετός δεν θα γίνει ο βασιλιάς ΜΟΥ. Ο \"\n\"Λέορικ είναι βασιλιάς. Βασιλιά, με ακούς; ΧΑΙΡΕ ΒΑΣΙΛΙΑ!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the power \"\n\"to raise yet more warriors for an ever growing army of the undead. If you do \"\n\"not stop his reign, he will surely march across this land and slay all who \"\n\"still live here.\"\nmsgstr \"\"\n\"Οι νεκροί που περπατούν ανάμεσα στους ζωντανούς ακολουθούν τον καταραμένο \"\n\"Βασιλιά. Έχει τη δύναμη να σηκώσει ακόμα περισσότερους πολεμιστές για έναν \"\n\"ολοένα αυξανόμενο στρατό από νεκρούς. Εάν δεν σταματήσεις τη βασιλεία του, \"\n\"σίγουρα θα βαδίσει σε αυτή τη γη και θα σκοτώσει όλους όσοι ζουν ακόμα εδώ.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't care \"\n\"about some King that's been dead longer than I've been alive. If you need \"\n\"something to use against this King of the undead, then I can help you out...\"\nmsgstr \"\"\n\"Κοίτα, τρέχω μια επιχείρηση εδώ. Δεν πουλάω πληροφορίες και δεν με νοιάζει \"\n\"κάποιος Βασιλιάς που είναι νεκρός περισσότερο από όσο έχω ζήσει εγώ. Εάν \"\n\"χρειάζεσαι κάτι να χρησιμοποιήσεις εναντίον αυτού του Βασιλιά των απέθαντων, \"\n\"τότε μπορώ να σε βοηθήσω...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve my \"\n\"Master for eternity!\"\nmsgstr \"\"\n\"Η ζεστασιά της ζωής έχει μπει στον τάφο μου. Ετοιμάσου, θνητέ, να υπηρετήσεις \"\n\"τον Κύριό μου στην αιώνιότητα!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has led \"\n\"them to believe that it too holds some arcane powers. Hmm, perhaps they are \"\n\"not all as smart as we had feared...\"\nmsgstr \"\"\n\"Βλέπω ότι αυτή η περίεργη συμπεριφορά σε προβληματίζει και εσένα. Θα υπέθετα \"\n\"ότι εφόσον πολλοί δαίμονες φοβούνται το φως του ήλιου και πιστεύουν ότι έχει \"\n\"μεγάλη δύναμη, ότι μπορεί ο ανατέλλοντας ήλιος που απεικονίζεται στην πινακίδα \"\n\"για την οποία αναφέρεσαι, να τους έκανε να πιστέψουν ότι έχει αντίστοιχες \"\n\"απόκρυφες δυνάμεις. Χμ, ίσως δεν είναι όλοι τους τόσο έξυπνοι όσο φοβόμασταν \"\n\"τελικά...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I looked \"\n\"out from my bedroom, I saw the shapes of small demon-like creatures in the inn \"\n\"yard. After a short time, they ran off, but not before stealing the sign to my \"\n\"inn. I don't know why the demons would steal my sign but leave my family in \"\n\"peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Άρχοντα/ίσσα, έχω μια περίεργη εμπειρία να διηγηθώ. Ξέρω ότι έχεις μεγάλη \"\n\"γνώση αυτών των τεράτων που κατοικούν στον λαβύρινθο, αλλά αυτό είναι κάτι που \"\n\"δεν μπορώ να καταλάβω, μα τη ζωή μου... Με ξύπνησε κατά τη διάρκεια της νύχτας \"\n\"ένας ήχος ξυσίματος ακριβώς έξω από την ταβέρνα μου. Όταν κοίταξα έξω από την \"\n\"κρεβατοκάμαρά μου, είδα τις φιγούρες μικρών πλασμάτων που έμοιαζαν με δαίμονες \"\n\"στην αυλή του πανδοχείου. Μετά από λίγο, έφυγαν τρέχοντας, αλλά όχι πριν \"\n\"κλέψουν την ταμπέλα του πανδοχείου μου. Δεν ξέρω γιατί οι δαίμονες έκλεψαν την \"\n\"πινακίδα μου ενώ άφησαν την οικογένειά μου απείραχτη... Είναι περίεργο, όχι;\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save me \"\n\"the expense of having another one made. Well, let me see, what could I give \"\n\"you as a fee for finding it? Hmmm, what have we here... ah, yes! This cap was \"\n\"left in one of the rooms by a magician who stayed here some time ago. Perhaps \"\n\"it may be of some value to you.\"\nmsgstr \"\"\n\"Ω, δεν χρειάστηκε να φέρεις πίσω την πινακίδα μου, αλλά υποθέτω ότι με \"\n\"γλιτώνεις από τα έξοδα να φτιάξω άλλη μία. Λοιπόν, για να δω, τι θα μπορούσα \"\n\"να σου δώσω ως αμοιβή που την βρήκες; Χμμμ, τι έχουμε εδώ... αχ, ναι! Αυτός ο \"\n\"σκούφος ξεχάστηκε σε ένα από τα δωμάτια μου από έναν μάγο που έμεινε εδώ πριν \"\n\"από λίγο καιρό. Ίσως έχει κάποια αξία για σένα.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes - \"\n\"is nothing sacred? I hope that Ogden and Garda are all right. I suppose that \"\n\"they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Θεέ μου, δαίμονες τρέχουν στο χωριό τη νύχτα, λεηλατούν τα σπίτια μας - δεν \"\n\"είναι τίποτα ιερό; Ελπίζω ότι ο Όγκντεν και η Γκάρντα είναι καλά. Υποθέτω ότι \"\n\"θα είχαν έρθει να με δουν αν είχαν πληγωθεί...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept right \"\n\"through the whole thing. Thank the Light that those monsters didn't attack the \"\n\"inn.\"\nmsgstr \"\"\n\"Ω θεε μου! Εκεί βρέθηκε η ταμπέλα; Η γιαγιά μου και εγώ πρέπει να κοιμηθήκαμε \"\n\"χωρίς να το πάρουμε χαμπάρι. Ευχαριστώ το Φως που αυτά τα τέρατα δεν \"\n\"επιτέθηκαν στο πανδοχείο.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Λες ότι οι δαίμονες έκλεψαν την πινακίδα του Όγκντεν; Αυτό δεν μοιάζει καθόλου \"\n\"με τις φρικαλεότητες που έχω ακούσει - ή έχω δει.\\n\"\n\" \\n\"\n\"Οι δαίμονες ενδιαφέρονται να ξεσκίσουν την καρδιά σου, όχι την ταμπέλα σου.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece of \"\n\"cheese...\"\nmsgstr \"\"\n\"Ξέρεις τι σκέφτομαι; Κάποιος πήρε την ταμπέλα και θα θέλει πολλά χρήματα για \"\n\"αυτήν. Αν ήμουν ο Όγκντεν... και δεν είμαι, αλλά αν ήμουν... θα αγόραζα απλώς \"\n\"μια νέα πινακίδα με ένα όμορφο σχέδιο πάνω της. Ίσως μια ωραία κούπα μπύρας ή \"\n\"ένα κομμάτι τυρί...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Κανένας θνητός δεν μπορεί να καταλάβει πραγματικά το μυαλό του δαίμονα.\\n\"\n\" \\n\"\n\"Μην αφήσετε ποτέ τις ακανόνιστες ενέργειές τους να σε μπερδέψουν, καθώς αυτό \"\n\"μπορεί να είναι και το σχέδιό τους.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on a \"\n\"piece of wood.\"\nmsgstr \"\"\n\"Τι; - λέει ότι το πήρα εγώ; Μάλλον και ο Γκρίσγουαλντ είναι μαζί του.\\n\"\n\" \\n\"\n\"Κοίτα, ξεπέρασα την απλή κλοπή πριν από μήνες. Δεν μπορείς να αποφέρεις κέρδος \"\n\"με ένα κομμάτι ξύλο.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You no \"\n\"leave with life! You kill big uglies and give back Magic. Go past corner and \"\n\"door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Ε, εσύ - εσύ που σκοτώνεις όλα! Μου δίνεις Μαγικό Πανό ή κάνουμε επίθεση! Δεν \"\n\"φεύγεις με ζωή σου! Σκοτώνεις μεγάλους άσχημους και δίνεις πίσω Μαγικό. Πέρασε \"\n\"από γωνία δεξιά και στην πόρτα, βρες άσχημους. Μου δίνεις, περνάς!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Σκοτώνεις άσχημους, παίρνεις πανό. Θα το φέρεις, αλλιώς...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Δώστε μου! Ναι, όμορφα! Πήγαινε τώρα, είμαστε δυνατοί. Σκοτώνουμε όλους με \"\n\"μεγάλη Μαγεία!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of them \"\n\"escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden him \"\n\"within the Labyrinth. I do not understand why the Archbishop turned to the \"\n\"darkness, or what his interest is in the child, unless he means to sacrifice \"\n\"him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say that \"\n\"Lazarus was last seen running into the deepest bowels of the labyrinth. You \"\n\"must hurry and save the prince from the sacrificial blade of this demented \"\n\"fiend!\"\nmsgstr \"\"\n\"Αυτό δεν προμηνύεται καλό, γιατί επιβεβαιώνει τους πιο σκοτεινούς φόβους μου. \"\n\"Ενώ δεν επέτρεψα στον εαυτό μου να πιστέψει τους αρχαίους θρύλους, δεν μπορώ \"\n\"να τους αρνηθώ τώρα. Ίσως ήρθε η ώρα να αποκαλύψω ποιος είμαι.\\n\"\n\" \\n\"\n\"Το αληθινό μου όνομα είναι Ντέκαρντ Κάιν ο Πρεσβύτερος και είμαι ο τελευταίος \"\n\"απόγονος μιας αρχαίας Αδελφότητας που ήταν αφιερωμένη στη διαφύλαξη των \"\n\"μυστικών ενός διαχρονικού κακού. Ένα κακό που προφανώς έχει πλέον \"\n\"απελευθερωθεί.\\n\"\n\" \\n\"\n\"Ο Αρχιεπίσκοπος Λάζαρος, κάποτε ο πιο έμπιστος σύμβουλος του βασιλιά Λέορικ, \"\n\"οδήγησε μια ομάδα απλών αστών στον Λαβύρινθο για να βρει τον εξαφανισμένο γιο \"\n\"του Βασιλιά, τον Άλμπρεχτ. Πέρασε αρκετός καιρός μέχρι να επιστρέψουν, και \"\n\"μόνο λίγοι από αυτούς γλίτωσαν με τη ζωή τους.\\n\"\n\" \\n\"\n\"Ανάθεμα με τον ανόητο! Θα έπρεπε να είχα υποψιαστεί την καλυμμένη προδοσία του \"\n\"τότε. Πρέπει να ήταν ο ίδιος ο Λάζαρος που απήγαγε τον Άλμπρεχτ και έκτοτε τον \"\n\"έκρυψε μέσα στον Λαβύρινθο. Δεν καταλαβαίνω γιατί ο Αρχιεπίσκοπος στράφηκε στο \"\n\"σκοτάδι, ή ποιο είναι το ενδιαφέρον του για το παιδί, εκτός κι αν θέλει να το \"\n\"θυσιάσει στα σκοτεινά αφεντικά του!\\n\"\n\" \\n\"\n\"Αυτό πρέπει να είναι το σχεδόν του! Οι επιζώντες της \\\"ομάδας διάσωσης\\\" του, \"\n\"λένε ότι ο Λάζαρος εθεάθη τελευταία φορά να τρέχει στα βαθύτερα σπλάχνα του \"\n\"λαβύρινθου. Πρέπει να βιαστείς και να σώσεις τον πρίγκιπα από τη θυσιαστική \"\n\"λεπίδα αυτού του παραφρονημένου κακούργου!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Πρέπει να βιαστείς και να σώσεις τον Άλμπρεχτ από τα χέρια του Λάζαρου. Ο \"\n\"πρίγκιπας και οι άνθρωποι αυτού του βασιλείου βασίζονται σε σένα!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for his \"\n\"horrific deed. The boy that you describe is not our prince, but I believe that \"\n\"Albrecht may yet be in danger. The symbol of power that you speak of must be a \"\n\"portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once again \"\n\"sow chaos in the realm of mankind. You must venture through the portal and \"\n\"destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Η ιστορία σου είναι πολύ ζοφερή φίλε/η μου. Ο Λάζαρος σίγουρα θα καεί στην \"\n\"Κόλαση για τη φρικτή πράξη του. Το αγόρι που περιγράφεις δεν είναι ο πρίγκιπας \"\n\"μας, αλλά πιστεύω ότι ο Άλμπρεχτ μπορεί ακόμα να βρίσκεται σε κίνδυνο. Το \"\n\"σύμβολο της δύναμης για το οποίο μιλάς πρέπει να είναι μια πύλη που οδηγεί \"\n\"στην ίδια την καρδιά του λαβύρινθου.\\n\"\n\" \\n\"\n\"Μάθε αυτό, φίλε/η μου - Το κακό στο οποίο εναντιώνεσαι είναι ο σκοτεινός \"\n\"Άρχοντας του Τρόμου. Είναι γνωστός στους θνητούς άντρες ως Ντιάμπλο. Αυτός \"\n\"ήταν που φυλακίστηκε μέσα στον Λαβύρινθο πριν από πολλούς αιώνες και φοβάμαι \"\n\"ότι επιδιώκει να σπείρει ξανά το χάος στον κόσμο της ανθρωπότητας. Πρέπει να \"\n\"περάσεις από την πύλη και να καταστρέψεις τον Ντιάμπλο πριν να είναι πολύ αργά!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the labyrinth. \"\n\"I lost many good friends that day, and Lazarus never returned. I suppose he \"\n\"was killed along with most of the others. If you would do me a favor, good \"\n\"master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Ο Λάζαρος ήταν ο Αρχιεπίσκοπος που οδήγησε πολλούς από τους κατοίκους της \"\n\"πόλης στον λαβύρινθο. Έχασα πολλούς καλούς φίλους εκείνη την ημέρα και ο \"\n\"Λάζαρος δεν επέστρεψε ποτέ. Υποθέτω ότι σκοτώθηκε μαζί με τους άλλους. Κάνε \"\n\"μου τη χάρη, Άρχοντα/ίσσα - σε παρακαλώ μην μιλήσεις στον Φάρνχαμ για εκείνη \"\n\"την ημέρα.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Σοκαρίστηκα όταν άκουσα τι σχεδίαζαν να κάνουν οι κάτοικοι της πόλης εκείνο το \"\n\"βράδυ. Νόμιζα ότι από όλους τους ανθρώπους, ο Λάζαρος θα είχε περισσότερη \"\n\"λογική από αυτό. Ήταν Αρχιεπίσκοπος και πάντα φαινόταν να νοιάζεται τόσο πολύ \"\n\"για τους κατοίκους της πόλης της Τρίστραμ. Τόσοι πολλοί τραυματίστηκαν, που \"\n\"δεν μπόρεσα να τους σώσω όλους...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Θυμάμαι τον Λάζαρο ως έναν πολύ ευγενικό και χαρισματικό άνθρωπο. Μίλησε στην \"\n\"κηδεία της μητέρας μου και στήριξε τη γιαγιά μου και εμένα σε μια πολύ \"\n\"ταραγμένη περίοδο. Προσεύχομαι κάθε βράδυ, με κάποιο τρόπο, να είναι ακόμα \"\n\"ζωντανός και ασφαλής.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so much \"\n\"as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Ήμουν εκεί όταν ο Λάζαρος μας οδήγησε στον λαβύρινθο. Μίλησε για ιερή \"\n\"ανταπόδοση, αλλά όταν αρχίσαμε να πολεμάμε αυτά τα κολασμένα πλάσματα, δεν \"\n\"σήκωσε το μαχαίρι του εναντίον τους. Απλώς έτρεξε πιο βαθιά μέσα στους \"\n\"σκοτεινούς, ατελείωτους θαλάμους που ήταν γεμάτοι με τους υπηρέτες του σκότους!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their blood \"\n\"spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Μαχαιρώνουν, μετά δαγκώνουν και μετά είναι παντού γύρω σου. Ψεύτης! ΨΕΥΤΗΣ! \"\n\"Είναι όλοι νεκροί! Νεκροί! Με ακούς? Συνεχίζουν να πέφτουν και να πέφτουν... \"\n\"το αίμα τους χύνεται και γεμίζουν τα πατώματα... Αυτός φταίει...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great conflict \"\n\"within his being. He poses a great danger, and will stop at nothing to serve \"\n\"the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Δεν ξέρω αυτόν τον Λάζαρο για τον οποίο μιλάς, αλλά αισθάνομαι μια μεγάλη \"\n\"σύγκρουση μέσα στην ύπαρξή του. Αποτελεί έναν μεγάλο κίνδυνο και δεν θα \"\n\"σταματήσει με τίποτα να υπηρετεί τις δυνάμεις του σκότους που τον έχουν \"\n\"διεκδικήσει ως δικό τους.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters down \"\n\"there. Didn't help save my leg, did it? Look, I'll give you a free piece of \"\n\"advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Ναι, ο δίκαιος Λάζαρος, ο οποίος ήταν τόόόσο αποτελεσματικός εναντίον εκείνων \"\n\"των τεράτων εκεί κάτω. Δεν με βοήθησε να σώσω το πόδι μου, σωστά; Κοίτα, θα \"\n\"σου δώσω μια δωρεάν συμβουλή. Ρωτήστε τον Φάρνχαμ, ήταν εκεί.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! You \"\n\"are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Εγκαταλείψε την ανόητη αναζήτησή σου. Το μόνο που σε περιμένει είναι η οργή \"\n\"του Άρχοντα μου! Είναι πολύ αργά για να σώσεις το παιδί. Τώρα θα το \"\n\"συναντήσεις στην Κόλαση!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I have \"\n\"heard of a tunnel that leads to a great lake - perhaps they are one and the \"\n\"same. Unfortunately, I do not know what would cause our water supply to be \"\n\"tainted.\"\nmsgstr \"\"\n\"Χμμ, δεν ξέρω τι μπορώ πραγματικά να σου πω για αυτό, που θα βοηθούσε. Το νερό \"\n\"που γεμίζει τα πηγάδια μας προέρχεται από μια υπόγεια πηγή. Έχω ακούσει για \"\n\"ένα τούνελ που οδηγεί σε μια μεγάλη λίμνη - ίσως είναι ένα και το αυτό. \"\n\"Δυστυχώς, δεν γνωρίζω τι θα μπορούσε να προκαλέσει τη μόλυνση του νερού μας.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, even \"\n\"our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Πάντα προσπαθούσα να διατηρήσω μια μεγάλη προσφορά τροφίμων και ποτών στο \"\n\"κελάρι μας, αλλά καθώς ολόκληρη η πόλη δεν έχει πηγή γλυκού νερού, ακόμη και \"\n\"τα αποθέματα μου σύντομα θα τελειώσουν.\\n\"\n\" \\n\"\n\"Σε παρακαλώ, κάνε ό,τι μπορείς γιατί δεν ξέρω τι θα απογίνουμε.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Χαίρομαι που σε πρόλαβα εγκαίρως! Τα πηγάδια μας έχουν γίνει υφάλμυρα και \"\n\"στάσιμα και κάποιοι από τους κατοίκους της πόλης έχουν αρρωστήσει πίνοντας από \"\n\"αυτά. Τα αποθέματα πόσιμου νερού, μας τελειώνουν γρήγορα. Πιστεύω ότι υπάρχει \"\n\"ένα πέρασμα που οδηγεί στις πηγές που προμηθεύουν την πόλη μας. Παρακαλώ βρες \"\n\"τι προκάλεσε αυτή την καταστροφή, διαφορετικά θα χαθούμε όλοι.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Σε παρακαλώ, πρέπει να βιαστείς. Κάθε ώρα που περνάει μας φέρνει πιο κοντά στο \"\n\"να μην έχουμε νερό να πιούμε.\\n\"\n\" \\n\"\n\"Δεν μπορούμε να επιβιώσουμε για πολύ χωρίς τη βοήθειά σου.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water to \"\n\"become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Τι είναι αυτό που λες - η απλή παρουσία των δαιμόνων είχε κάνει το νερό να \"\n\"μολυνθεί; Ω, πραγματικά ένα μεγάλο κακό κρύβεται κάτω από την πόλη μας, αλλά η \"\n\"επιμονή και το θάρρος σου μας δίνουν ελπίδα. Πάρε αυτό το δαχτυλίδι - ίσως θα \"\n\"σε βοηθήσει στην καταστροφή αυτών των άθλιων πλασμάτων.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Η γιαγιά μου είναι πολύ αδύναμη και η Γκάρντα λέει ότι δεν μπορούμε να πιούμε \"\n\"το νερό από τα πηγάδια. Σε παρακαλώ, μπορείς να κάνεις κάτι για να μας \"\n\"βοηθήσεις;\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I have \"\n\"tried to clear one of the smaller wells, but it reeks of stagnant filth. It \"\n\"must be getting clogged at the source.\"\nmsgstr \"\"\n\"Ο Πεπίν σου είπε την αλήθεια. Θα χρειαστούμε πολύ πόσιμο νερό και μάλιστα \"\n\"σύντομα. Προσπάθησα να καθαρίσω ένα από τα μικρότερα πηγάδια, αλλά μυρίζει \"\n\"στάσιμη βρωμιά. Πρέπει να έχει βουλώσει και βρωμίσει στην πηγή.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Πίνεις νερό;\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Οι κάτοικοι της Τρίστραμ θα πεθάνουν εάν δεν μπορέσεις να επαναφέρεις το \"\n\"πόσιμο νερό στα πηγάδια τους.\\n\"\n\" \\n\"\n\"Να ξέρεις - Δαίμονες βρίσκονται στο επίκεντρο αυτού του ζητήματος, αλλά είναι \"\n\"ανίδεοι για το τι έχουν προκαλέσει.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Για πρώτη φορά είμαι μαζί σου. Η επιχείρησή μου στεγνώνει - να το πω έτσι - αν \"\n\"δεν έχω αγορά να πουλήσω. Καλύτερα να μάθεις τι συμβαίνει και σύντομα!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in the \"\n\"attempt to steal that treasure would be forever bound to defend it. A twisted, \"\n\"but strangely fitting, end?\"\nmsgstr \"\"\n\"Ένα βιβλίο που μιλάει για θάλαμο ανθρώπινων οστών; Λοιπόν, ένας θάλαμος των \"\n\"οστών αναφέρεται σε ορισμένες αρχαϊκές γραφές που μελέτησα στις βιβλιοθήκες \"\n\"της Ανατολής. Αυτοί οι τόμοι συμπέραναν ότι όταν οι Άρχοντες του κάτω κόσμου \"\n\"ήθελαν να προστατεύσουν μεγάλους θησαυρούς, θα δημιουργούσαν περιοχές όπου \"\n\"όσοι πέθαιναν, στην προσπάθεια να κλέψουν αυτόν τον θησαυρό, θα ήταν για πάντα \"\n\"δεσμευμένοι για να τον προστατέψουν. Ένα διεστραμμένο, αλλά παράξενα ταιριαστό \"\n\"τέλος;\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has many \"\n\"books that may be of some help.\"\nmsgstr \"\"\n\"Φοβάμαι ότι δεν ξέρω τίποτα για αυτό, καλέ/ή μου άρχοντα/ίσσα. Ο Κάιν έχει \"\n\"πολλά βιβλία που μπορεί να σε βοηθήσουν.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Αυτό μου ακούγεται σαν ένα πολύ επικίνδυνο μέρος. Εάν τολμήσεις να πας εκεί, \"\n\"σε παρακαλώ να είσαι πολύ προσεκτικός/ή.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Φοβάμαι ότι δεν έχω ακούσει τίποτα για αυτό. Ίσως ο Κάιν ο Αφηγητής θα \"\n\"μπορούσε να βοηθήσει.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about many \"\n\"things, and it would not surprise me if he had some answers to your question.\"\nmsgstr \"\"\n\"Δεν ξέρω τίποτα για αυτό το μέρος, αλλά μπορείς να δοκιμάσεις να ρωτήσεις τον \"\n\"Κάιν. Μιλάει για πολλά πράγματα και δεν θα με εξέπληξε αν είχε κάποιες \"\n\"απαντήσεις στην ερώτησή σου.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Εντάξει, άκου λοιπόν. Υπάρχει αυτός ο θάλαμος από ξύλο, βλέπεις. Και η γυναίκα \"\n\"του, ξέρεις - αυτή - λέει στο δέντρο... γιατί, πρέπει να περιμένεις. Μετά λέω, \"\n\"αυτό μπορεί να λειτουργήσει εναντίον του, αλλά αν νομίζεις ότι θα ΠΛΗΡΩΣΩ γι' \"\n\"αυτό... εσύ... ε... ναι.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish within \"\n\"this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Θα γίνεις αιώνιος υπηρέτης των σκοτεινών αρχόντων αν πέσεις μέσα σε αυτόν τον \"\n\"καταραμένο μέρος.\\n\"\n\" \\n\"\n\"Μπες στον Θάλαμο των Οστών με δική σου ευθύνη.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Ένας τεράστιος και μυστηριώδης θησαυρός, λες; Ίσως θα με ενδιέφερε να πάρω \"\n\"μερικά πράγματα από σένα... ή καλύτερα, δεν χρειάζεσαι σπάνιες και ακριβές \"\n\"προμήθειες εξοπλισμού για να ξεπεράσεις αυτή τη δοκιμασία;\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - left \"\n\"in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Φαίνεται ότι ο Αρχιεπίσκοπος Λάζαρος παρότρυνε πολλούς από τους κατοίκους της \"\n\"πόλης να τολμήσουν να μπουν στον Λαβύρινθο για να βρουν τον εξαφανισμένο γιο \"\n\"του Βασιλιά. Έπαιξε πάνω στους φόβους τους και τους μετάτρεψε σε έναν ξέφρενο \"\n\"όχλο. Κανείς τους δεν ήταν προετοιμασμένος για αυτό που βρισκόταν μέσα στην \"\n\"κρύα γη... Ο Λάζαρος τους εγκατέλειψε εκεί κάτω - αφημένους στα νύχια \"\n\"ανείπωτων τρόμων - για να πεθάνουν.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a fierce \"\n\"weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Ναι, ο Φάρνχαμ μουρμούρισε κάτι για ένα ογκώδες θηρίο που κρατούσε ένα άγριο \"\n\"όπλο. Πιστεύω ότι τον ονόμασε χασάπη.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Μα το Φως, γνωρίζω αυτόν τον ποταπό δαίμονα. Υπήρχαν πολλοί που έφεραν τα \"\n\"σημάδια της οργής του στα σώματά τους, όταν οι λίγοι επιζώντες της επίθεσης με \"\n\"επικεφαλής τον Λάζαρο, σύρθηκαν από τον Καθεδρικό Ναό. Δεν ξέρω με τι συνήθιζε \"\n\"να τεμαχίζει τα θύματά του, αλλά δεν θα μπορούσε να ήταν όπλο αυτού του \"\n\"κόσμου. Άφηνε πληγές που γεμίζαν από ασθένειες και ακόμη και εγώ, τις έβρισκα \"\n\"σχεδόν αδύνατο να τις θεραπεύσω. Προσοχή αν σκοπεύεις να πολεμήσεις αυτό το \"\n\"κτήνος...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Όταν ο Φάρνχαμ είπε κάτι για έναν χασάπη που σκότωσε ανθρώπους, το αγνόησα \"\n\"αμέσως. Αλλά μιας και το ανέφερες εσύ, ίσως είναι αλήθεια.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and cutting \"\n\"down brave men where they stood. I was separated from the fray by a host of \"\n\"small screeching demons and somehow found the stairway leading out. I never \"\n\"saw that hideous beast again, but his blood-stained visage haunts me to this \"\n\"day.\"\nmsgstr \"\"\n\"Είδα αυτό που ο Φάρνχαμ αποκαλεί χασάπη, καθώς διέσχιζε ένα μονοπάτι ανάμεσα \"\n\"από τα πτώματα των φίλων μου. Κουνούσε ένα μαχαίρι μεγάλο όσο ένα τσεκούρι, \"\n\"κόβοντας μέλη και κόβοντας γενναίους άνδρες εκεί που στέκονταν. Με χώρισαν από \"\n\"τη μάχη μια σειρά από μικρούς δαίμονες που ουρλιάζουν και με κάποιο τρόπο \"\n\"βρήκα τη σκάλα που οδηγεί έξω. Δεν είδα ποτέ ξανά αυτό το αποτρόπαιο θηρίο, \"\n\"αλλά το αιματοβαμμένο πρόσωπό του με στοιχειώνει μέχρι σήμερα.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Μεγάλος! Μεγάλος μπαλτάς σκοτώνει όλους τους φίλους μου. Δεν μπορώ να τον \"\n\"σταματήσω, έπρεπε να τρέξω μακριά, δεν μπορώ να τους σώσω. Παγιδευμένος σε ένα \"\n\"δωμάτιο, με τόσα κορμιά... τόσους φίλους... ΟΧΙΙΙΙΙΙΙΙΙ!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Ο χασάπης είναι ένα σαδιστικό πλάσμα που απολαμβάνει τα βασανιστήρια και τον \"\n\"πόνο των άλλων. Έχεις δει τη \\\"δουλειά\\\" του στον μεθυσμένο Φάρνχαμ. Η \"\n\"καταστροφή του θα κάνει πολλά για να διασφαλίσει την ασφάλεια αυτού του χωριού.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got a \"\n\"hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to his \"\n\"collection.\"\nmsgstr \"\"\n\"Ξέρω περισσότερα από όσα θα φανταζόσουν για αυτό το φρικτό Θηρίο. Οι μικροί \"\n\"του \\\"φίλοι\\\" με έπιασαν και κατάφεραν να μου κόψουν το πόδι, πριν με βγάλει ο \"\n\"Γκρίσγουαλντ από εκείνη την τρύπα.\\n\"\n\" \\n\"\n\"Θα το πω ευθέως - σκότωσε το πριν σε σκοτώσει και προσθέσει το πτώμα σου στη \"\n\"συλλογή του.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find the \"\n\"lost prince. The bastard led us into a trap! Now everyone is dead... killed by \"\n\"a demon he called the Butcher. Avenge us! Find this Butcher and slay him so \"\n\"that our souls may finally rest...\"\nmsgstr \"\"\n\"Παρακαλώ, άκουσε με. Ο Αρχιεπίσκοπος Λάζαρος, μας οδήγησε εδώ κάτω για να \"\n\"βρούμε τον χαμένο πρίγκιπα. Το κάθαρμα μας οδήγησε σε παγίδα! Τώρα όλοι είναι \"\n\"νεκροί... σκοτωμένοι από έναν δαίμονα που τον ανέφερε ως Χασάπη. Εκδικήσου \"\n\"μας! Βρες αυτόν τον Χασάπη και σκότωσε τον για να αναπαυθούν επιτέλους οι \"\n\"ψυχές μας...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the Halls \"\n\"of the Blind...\"\nmsgstr \"\"\n\"Απαγγέλλεις ένα ενδιαφέρον στιχάκι γραμμένο σε ύφος που μου θυμίζει άλλα έργα. \"\n\"Κάτσε να σκεφτώ τώρα - πώς ήταν;\\n\"\n\" \\n\"\n\"...Το σκοτάδι σκεπάζει το Κρυφό. Μάτια που λάμπουν αόρατα μόνο με τους ήχους \"\n\"των κοφτερών νυχιών που ξύνουν στιγμιαία για να βασανίσουν εκείνες τις φτωχές \"\n\"ψυχές που έχουν μείνει αόματες για όλη την αιωνιότητα. Η φυλακή για αυτούς που \"\n\"είναι τόσο καταραμένοι ονομάζεται η Αίθουσα των Τυφλών...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Ποτέ δεν ασχολήθηκα πολύ με την ποίηση. Περιστασιακά, είχα λόγο να προσλάβω \"\n\"βάρδους όταν το πανδοχείο πήγαινε καλά, αλλά αυτό μοιάζει πλέον ότι έγινε εδώ \"\n\"και πολύ καιρό πριν.\\n\"\n\" \\n\"\n\"Τι? Α, ναι... ε, καλά, υποθέτω ότι θα μπορούσες να δεις τι ξέρει κάποιος άλλος.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very much \"\n\"like that poem while researching the history of demonic afflictions. It spoke \"\n\"of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Αυτό κατά κάποιο τρόπο μου ακούγεται γνωστό. Φαίνεται να θυμάμαι ότι διάβασα \"\n\"κάτι πολύ παρόμοιο με αυτό το ποίημα ενώ ερευνούσα την ιστορία των δαιμονικών \"\n\"δεινών. Μίλησε για ένα μέρος μεγάλου κακού που... περίμενε - δεν σκοπεύεις να \"\n\"πας εκεί;\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he can \"\n\"help you, too.\"\nmsgstr \"\"\n\"Εάν έχεις ερωτήσεις σχετικά με την τύφλωση, θα πρέπει να μιλήσετε με τον \"\n\"Πέπιν. Ξέρω ότι έδωσε στη γιαγιά μου ένα φίλτρο που της βοήθησε να καθαρίσει \"\n\"την όρασή της, οπότε ίσως μπορεί να βοηθήσει και εσένα.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your vivid \"\n\"description, my friend. Perhaps Cain the Storyteller could be of some help.\"\nmsgstr \"\"\n\"Φοβάμαι ότι ούτε έχω ακούσει ούτε έχω δει ένα μέρος που να ταιριάζει με τη \"\n\"ζωντανή περιγραφή σου, φίλε μου. Ίσως ο Κάιν ο αφηγητής ιστοριών θα μπορούσε \"\n\"να βοηθήσει.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Κοίτα εδώ... είναι πολύ αστείο, ε; Το έπιασες; Τυφλός - κοιτά εδώ;\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Αυτό είναι ένα μέρος μεγάλης αγωνίας και τρόμου, και έτσι εξυπηρετεί καλά τον \"\n\"Άρχοντα του.\\n\"\n\" \\n\"\n\"Περπάτα προσεκτικά, διαφορετικά μπορεί να μείνεις πολύ περισσότερο από όσο \"\n\"περίμενες.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell you \"\n\"about this? No. Are you now leaving and going to talk to the storyteller who \"\n\"lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Για να δούμε, σου πουλάω κάτι; Όχι. Μου δίνεις χρήματα για να σου πω γι' αυτό; \"\n\"Όχι. Φεύγεις τώρα, για να μιλήσεις με τον αφηγητή ιστοριών που ζει για κάτι \"\n\"τέτοιο; Ναι.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his life. \"\n\"Lachdanan was an honorable and just man who served his King faithfully for \"\n\"years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan would \"\n\"be the least likely to submit to the darkness without a fight, so I suppose \"\n\"that your story could be true. If I were in your place, my friend, I would \"\n\"find a way to release him from his torture.\"\nmsgstr \"\"\n\"Υποστηρίζεις ότι έχεις μιλήσει με τον Λακντάναν; Υπήρξε μεγάλος ήρωας όταν \"\n\"ζούσε. Ο Λακντάναν ήταν ένας έντιμος και δίκαιος άνθρωπος που υπηρέτησε πιστά \"\n\"τον Βασιλιά του για χρόνια. Αλλά φυσικά, το γνωρίζεις ήδη αυτό.\\n\"\n\" \\n\"\n\"Από αυτούς που πιάστηκαν στην Κατάρα του Βασιλιά, ο Λακντάναν θα ήταν λιγότερο \"\n\"πιθανό να υποταχθεί στο σκοτάδι χωρίς μάχη, οπότε υποθέτω ότι η ιστορία σου θα \"\n\"μπορούσε να είναι αληθινή. Αν ήμουν στη θέση σου, φίλε μου, θα έβρισκα τρόπο \"\n\"να τον απαλλάξω από το μαρτύριο του.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Μιλάς για έναν γενναίο πολεμιστή που είναι νεκρός εδώ και καιρό! Δεν θα κάνω \"\n\"κουβέντα για ψυχές που έχουν φύγει, στην αυλή του πανδοχείου μου, σε ευχαριστώ \"\n\"πολύ.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Χρυσό ελιξίριο, λες. Δεν έχω φτιάξει ποτέ ένα φίλτρο αυτού του χρώματος, οπότε \"\n\"δεν μπορώ να σου πω πώς θα σε επηρέαζε αν προσπαθούσες να το πιείς. Ως \"\n\"θεραπευτής σου, σε συμβουλεύω ανεπιφύλακτα ότι εάν βρείτε ένα τέτοιο ελιξίριο, \"\n\"να κάνετε ό,τι σας ζητήσει ο Λακντάναν και ΜΗΝ προσπαθήσετε να το \"\n\"χρησιμοποιήσεις.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Δεν έχω ξανακούσει για κάποιον Λακντάναν. Λυπάμαι, αλλά δεν νομίζω ότι μπορώ \"\n\"να σε βοηθήσω.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest and \"\n\"loyal in nature. The curse that fell upon the followers of King Leoric would \"\n\"fall especially hard upon him.\"\nmsgstr \"\"\n\"Εάν όντως συνάντησες τον Λακντάναν, τότε θα σε συμβούλευα να τον βοηθήσεις. \"\n\"Ασχολήθηκα μαζί του πολλές φορές και είναι ειλικρινής και πιστός. Η κατάρα που \"\n\"έπεσε πάνω στους ακόλουθους του βασιλιά Λεόρικ θα είναι ιδιαίτερα σκληρή πάνω \"\n\"του.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into thinking \"\n\"any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Ο Λακντάναν είναι νεκρός. Όλοι το ξέρουν αυτό και δεν μπορείς να με \"\n\"ξεγελάσεις να σκεφτώ αλλιώς. Δεν μπορείς να μιλήσεις στους νεκρούς. Το ξέρω!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Μπορεί να συναντήσεις άτομα που είναι παγιδευμένα μέσα στον Λαβύρινθο, όπως \"\n\"τον Λακντάναν.\\n\"\n\" \\n\"\n\"Νιώθω μέσα του μεγάλη τιμή και μεγάλη ενοχή. Βοήθησέ τον, και θα βοήθησες όλο \"\n\"το Τρίστραμ.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be buying \"\n\"something or you'll be on your way.\"\nmsgstr \"\"\n\"Περίμενε, άσε με να μαντέψω. Ο Κάιν καταβροχθίστηκε από μια γιγαντιαία σχισμή \"\n\"που άνοιξε κάτω από τα πόδια του. Αποτεφρώθηκε μέσα σε μια μπάλα κολασμένης \"\n\"φωτιάς και δεν μπορεί πλέον να απαντήσει στις ερωτήσεις σου. Α, δεν έγινε \"\n\"αυτό; Τότε υποθέτω ότι θα αγοράσεις κάτι ή διαφορετικά σου εύχομαι καλό δρόμο.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his dark \"\n\"Curse fell upon us for the role we played in his tragic death. As my fellow \"\n\"Knights succumbed to their twisted fate, I fled from the King's burial \"\n\"chamber, searching for some way to free myself from the Curse. I failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul to \"\n\"rest, but I have been unable to find it. My strength now wanes, and with it \"\n\"the last of my humanity as well. Please aid me and find the Elixir. I will \"\n\"repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Σε παρακαλώ, μη με σκοτώσεις, απλώς άκουσέ με. Ήμουν κάποτε Λοχαγός των \"\n\"Ιπποτών του Βασιλιά Λέορικ, και υπηρετούσα τους νόμους αυτής της χώρας με \"\n\"δικαιοσύνη και τιμή. Τότε η σκοτεινή του κατάρα έπεσε πάνω μας για τον ρόλο \"\n\"που παίξαμε στον τραγικό θάνατό του. Καθώς οι συνάδελφοί μου Ιππότες υπέκυψαν \"\n\"στη διεστραμμένη μοίρα τους, έφυγα από τον ταφικό θάλαμο του Βασιλιά, \"\n\"αναζητώντας κάποιον τρόπο να ελευθερωθώ από την Κατάρα. Απέτυχα...\\n\"\n\" \\n\"\n\"Έχω ακούσει για ένα Χρυσό Ελιξίριο που θα μπορούσε να σηκώσει την Κατάρα και \"\n\"να αφήσει την ψυχή μου να ξεκουραστεί, αλλά δεν κατάφερα να το βρω. Η δύναμή \"\n\"μου τώρα μειώνεται, και μαζί της και η τελευταία ανθρωπιά μου. Παρακαλώ \"\n\"βοήθησε με και βρες το Ελιξίριο. Θα σε ανταμείψω για την προσπάθεια σου - \"\n\"ορκίζομαι στην τιμή μου.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Δεν έχεις βρει το Χρυσό Ελιξίριο. Φοβάμαι ότι είμαι καταδικασμένος στην \"\n\"αιωνιότητα. Σε παρακαλώ, συνέχισε να προσπαθείς...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find it, \"\n\"but for now - take my helm. On the journey I am about to take I will have \"\n\"little use for it. May it protect you against the dark powers below. Go with \"\n\"the Light, my friend...\"\nmsgstr \"\"\n\"Έσωσες την ψυχή μου από την καταδίκη, και γι' αυτό είμαι υπόχρεος σου. Αν \"\n\"υπάρχει ποτέ τρόπος να σου το ανταποδώσω πέρα από τον τάφο, θα τον βρω, αλλά \"\n\"προς το παρόν - πάρε το κράνος μου. Στο ταξίδι που πρόκειται να κάνω δεν θα το \"\n\"χρειαστώ καθόλου. Είθε να σε προστατεύσει από τις σκοτεινές δυνάμεις του κάτω \"\n\"κόσμου. Περπάτα με το φως φίλε μου...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched for, \"\n\"but never found. Crafted from the metallic bones of the Razor Pit demons, the \"\n\"Anvil of Fury was smelt around the skulls of the five most powerful magi of \"\n\"the underworld. Carved with runes of power and chaos, any weapon or armor \"\n\"forged upon this Anvil will be immersed into the realm of Chaos, imbedding it \"\n\"with magical properties. It is said that the unpredictable nature of Chaos \"\n\"makes it difficult to know what the outcome of this smithing will be...\"\nmsgstr \"\"\n\"Ο Γκρίσγουαλντ μιλάει για το Αμόνι της Οργής- ένα θρυλικό τεχνούργημα που το \"\n\"αναζητούσαν εδώ και πολύ καιρό, αλλά δεν βρέθηκε ποτέ. Φτιαγμένο από τα \"\n\"μεταλλικά οστά των δαιμόνων του λάκκου του ξυραφιού, το Αμόνι της Οργής \"\n\"χυτεύθηκε γύρω από τα κρανία των πέντε πιο ισχυρών μάγων του κάτω κόσμου. \"\n\"Σκαλισμένο με ρούνους δύναμης και χάους, οποιοδήποτε όπλο ή πανοπλία \"\n\"σφυρηλατηθεί πάνω σε αυτό το Αμόνι θα βυθιστεί στο βασίλειο του Χάους, \"\n\"εμβαπτίζοντάς το με μαγικές ιδιότητες. Λέγεται ότι η απρόβλεπτη φύση του Χάους \"\n\"καθιστά δύσκολο να γνωρίζουμε ποιο θα είναι το αποτέλεσμα αυτής της \"\n\"σφυρηλάτησης...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? He's \"\n\"quite handy, you know.\"\nmsgstr \"\"\n\"Δεν πιστεύεις ότι ο Γκρίσγουαλντ θα ήταν το καλύτερο άτομο να ρωτήσεις γι' \"\n\"αυτό; Είναι πολύ χρήσιμος, ξέρεις.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the Silver \"\n\"Chalice of Purification, I could have assisted you, my friend. However, in \"\n\"this matter, you would be better served to speak to either Griswold or Cain.\"\nmsgstr \"\"\n\"Αν έψαχνες για πληροφορίες για το Γουδοχέρι της Θεραπείας ή το Ασημένιο \"\n\"Δισκοπότηρο της Κάθαρσης, θα μπορούσα να σε βοηθήσω, φίλε μου. Ωστόσο, σε αυτό \"\n\"το θέμα, θα ήταν καλύτερα να μιλήσεις είτε με τον Γκρίσγουαλντ είτε με τον \"\n\"Κάιν.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. Whenever \"\n\"the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Ο πατέρας του Γκρισγουάλντ συνήθιζε να λέει σε μερικούς από εμάς όταν \"\n\"μεγαλώναμε μικροί για ένα γιγάντιο αμόνι που χρησιμοποιήθηκε για την κατασκευή \"\n\"πανίσχυρων όπλων. Είπε ότι όταν χτυπούσαν ένα σφυρί σε αυτό το αμόνι, το \"\n\"έδαφος ταρακουνούσε με μεγάλη οργή. Όποτε ταρακουνάει η γη, πάντα θυμάμαι αυτή \"\n\"την ιστορία.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know that \"\n\"you have been venturing deeper into the Labyrinth, and there is a story I was \"\n\"told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of legends \"\n\"I had heard in my youth about the burning Hellforge where powerful weapons of \"\n\"magic are crafted. The legend had it that deep within the Hellforge rested the \"\n\"Anvil of Fury! This Anvil contained within it the very essence of the demonic \"\n\"underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with great \"\n\"power. If this anvil is indeed the Anvil of Fury, I may be able to make you a \"\n\"weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Χαιρετισμούς! Είναι πάντα χαρά να βλέπω τον καλύτερο μου πελάτη! Ξέρω ότι \"\n\"έχεις μπει πιο βαθιά στον Λαβύρινθο και υπάρχει μια ιστορία που μου είχαν πει, \"\n\"που μπορεί να αξίζει τον χρόνο να την ακούσεις...\\n\"\n\" \\n\"\n\"Ένας από τους άντρες που επέστρεψαν από τον Λαβύρινθο μου είπε για ένα \"\n\"μυστικιστικό αμόνι που είδε κατά την απόδρασή του. Η περιγραφή του μου θύμισε \"\n\"θρύλους που είχα ακούσει στα νιάτα μου για το φλεγόμενο σιδηρουργείο της \"\n\"κολάσεως όπου κατασκευάζονται ισχυρά όπλα μαγείας. Ο θρύλος έλεγε ότι βαθιά \"\n\"μέσα στο σιδηρουργείο βρισκόταν το Αμόνι της Οργής! Αυτό το Αμόνι περιείχε \"\n\"μέσα του την ίδια την ουσία του δαιμονικού κάτω κόσμου...\\n\"\n\" \\n\"\n\"Λέγεται ότι κάθε όπλο που κατασκευάζεται πάνω στο φλεγόμενο αμόνι είναι \"\n\"εμποτισμένο με μεγάλη δύναμη. Αν αυτό το αμόνι είναι πράγματι το Αμόνι της \"\n\"Οργής, ίσως μπορέσω να σου φτιάξω ένα όπλο ικανό να νικήσει ακόμα και τον πιο \"\n\"σκοτεινό Άρχοντα της Κόλασης!\\n\"\n\" \\n\"\n\"Βρές μου το Αμόνι και θα πιάσω δουλειά!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could be \"\n\"your best hope, and I am sure that I can make you one of legendary proportions.\"\nmsgstr \"\"\n\"Τίποτα ακόμα, ε; Λοιπόν, συνέχισε να ψάχνεις. Ένα όπλο σφυρηλατημένο στο Αμόνι \"\n\"θα μπορούσε να είναι η καλύτερη ελπίδα σου, και είμαι σίγουρος ότι μπορώ να \"\n\"σου σφυρηλατήσω ένα, θρυλικών διαστάσεων.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. Now \"\n\"we'll show those bastards that there are no weapons in Hell more deadly than \"\n\"those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Δεν μπορώ να το πιστέψω! Αυτό είναι το Αμόνι της Οργής - καλή δουλειά, φίλε \"\n\"μου. Τώρα θα δείξουμε σε αυτά τα καθάρματα ότι δεν υπάρχουν όπλα στην Κόλαση \"\n\"πιο θανατηφόρα από αυτά που φτιάχνουν οι άνθρωποι! Πάρε αυτό και εύχομαι το \"\n\"Φως να σε προστατεύσει.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Ο Γκρίσγουαλντ δεν μπορεί να πουλήσει το αμόνι του. Τι θα κάνει τότε; Και εγώ \"\n\"θα θύμωνα και εγώ αν κάποιος μου έπαιρνε το αμόνι μου!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be used \"\n\"by either the Light or the Darkness. Securing the Anvil from below could shift \"\n\"the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Υπάρχουν πολλά τεχνουργήματα μέσα στον Λαβύρινθο που έχουν δυνάμεις πέρα από \"\n\"την κατανόηση των θνητών. Μερικά από αυτά έχουν φανταστική δύναμη που μπορεί \"\n\"να χρησιμοποιηθεί είτε από το Φως είτε από το Σκοτάδι. Η εξασφάλιση του \"\n\"αμονιού από τον κάτω κόσμο θα μπορούσε να μετατοπίσει την πορεία του Πολέμου \"\n\"της Αμαρτίας προς το Φως.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious damper \"\n\"on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Εάν έβρισκες αυτό το τεχνούργημα για τον Γκρίσγουαλντ, θα μπορούσε να θέσει \"\n\"σοβαρά προβλήματα στην επιχείρησή μου εδώ. Ωχ τι λέω, δεν θα το βρεις ποτέ.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a pool \"\n\"of boiling blood atop its bone encrusted surface. There are also allusions to \"\n\"Stones of Blood that will open a door that guards an ancient treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and chase \"\n\"the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don Valor \"\n\"once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Η Πύλη του Αίματος και οι Αίθουσες της Φωτιάς είναι ορόσημα μυστικιστικής \"\n\"προέλευσης. Από όπου κι αν προέρχεται αυτό το βιβλίο που διάβασες, είναι \"\n\"σίγουρα ένα μέρος με μεγάλη δύναμη.\\n\"\n\" \\n\"\n\"Οι θρύλοι μιλούν για ένα βάθρο που είναι λαξευμένο από πέτρα οψιανού και έχει \"\n\"μια λίμνη από βραστό αίμα στην επιφανειακή επιφάνειά του που είναι από \"\n\"κόκκαλα. Υπάρχουν επίσης νύξεις για Πέτρες από Αίμα που θα ανοίξουν μια πόρτα \"\n\"που φυλάει έναν αρχαίο θησαυρό...\\n\"\n\" \\n\"\n\"Η φύση αυτού του θησαυρού καλύπτεται από εικασίες, φίλε μου, αλλά λέγεται ότι \"\n\"ο αρχαίος ήρωας Αρκάϊν τοποθέτησε την Ιερή Πανοπλία της Τιμής σε ένα μυστικό \"\n\"θησαυροφυλάκιο. Ο Αρκάϊν ήταν ο πρώτος θνητός που αντέστρεψε την ροή του \"\n\"Πολέμου της Αμαρτίας και κυνήγησε τις λεγεώνες του σκότους πίσω στις \"\n\"Φλεγόμενες Κολάσεις.\\n\"\n\" \\n\"\n\"Λίγο πριν πεθάνει ο Αρκάϊν, η πανοπλία του κρύφθηκε σε ένα μυστικό \"\n\"θησαυροφυλάκιο. Λέγεται ότι όταν αυτή η ιερή πανοπλία θα χρειαστεί ξανά, ένας \"\n\"ήρωας θα αναδυθεί για να φορέσει την Τιμή για άλλη μια φορά. Ίσως εσύ να είσαι \"\n\"αυτός ο ήρωας...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor known \"\n\"as Valor. If you could find its resting place, you would be well protected \"\n\"against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Κάθε παιδί ακούει την ιστορία του πολεμιστή Αρκάϊν και της μυστικιστικής \"\n\"πανοπλίας του, γνωστής ως Τιμή. Αν μπορούσες να βρεις τον τόπο ανάπαυσής της, \"\n\"θα είσαι καλά προστατευμένος/η από το κακό στον Λαβύρινθο.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Χμ... ακούγεται σαν κάτι που πρέπει να θυμάμαι, αλλά ήμουν τόσο απασχολημένος \"\n\"με το να μαθαίνω νέες θεραπείες και να δημιουργώ καλύτερα ελιξίρια που πρέπει \"\n\"να το έχω ξεχάσει. Συγνώμη...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the boys \"\n\"talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Η ιστορία της μαγικής πανοπλίας που ονομάζεται Τιμή είναι κάτι για το οποίο \"\n\"άκουσα συχνά τα αγόρια να μιλάνε. Καλύτερα να ρωτήσεις έναν από τους άντρες \"\n\"του χωριού.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it well, \"\n\"my friend, and it will take more than a bit of luck to unlock the secrets that \"\n\"have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Η πανοπλία γνωστή ως Τιμή θα μπορούσε να είναι αυτό που γείρει τη ζυγαριά υπέρ \"\n\"σου. Θα σου πω ότι πολλοί το έχουν ψάξει - συμπεριλαμβανομένου και του εαυτού \"\n\"μου. Ο Αρκάϊν την έκρυψε καλά, φίλε μου, και θα χρειαστεί περισσότερο από λίγη \"\n\"τύχη για να ξεκλειδώσεις τα μυστικά που την κράτησαν κρυμμένη, ω, τόσα χρόνια.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Ζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζ...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self trust.\"\nmsgstr \"\"\n\"Εάν βρεις αυτές τις Πέτρες του Αίματος, χρησιμοποίησέ τες προσεκτικά.\\n\"\n\" \\n\"\n\"Ο δρόμος είναι γεμάτος κινδύνους και η μόνη σου ελπίδα βρίσκεται στην \"\n\"εμπιστοσύνη του εαυτού σου.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Σκοπεύεις να βρεις την πανοπλία γνωστή ως Τιμή;\\n\"\n\" \\n\"\n\"Κανείς δεν έχει καταλάβει ποτέ πού είχε κρύψει ο Αρκάϊν το πράμα, και αφού οι \"\n\"επαφές μου δεν μπορούσαν να την βρουν, αμφιβάλλω σοβαρά ότι θα την βρεις εσύ.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a black \"\n\"curse to the living; a tortured invitation to any who would stand before this \"\n\"Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his insatiable \"\n\"hunger for blood.\"\nmsgstr \"\"\n\"Ξέρω μόνο έναν θρύλο που μιλά για έναν τέτοιο πολεμιστή όπως περιγράφεις. Η \"\n\"ιστορία του βρίσκεται στα αρχαία χρονικά του Πολέμου της Αμαρτίας...\\n\"\n\" \\n\"\n\"Λεκιασμένος από χίλια χρόνια πολέμου, αίματος και θανάτου, ο Πολέμαρχος του \"\n\"Αίματος στέκεται πάνω σε ένα βουνό με τα κουρελιασμένα θύματά του. Η σκοτεινή \"\n\"του λεπίδα φωνάζει μια μαύρη κατάρα στους ζωντανούς, μια βασανισμένη πρόσκληση \"\n\"σε όποιον θα σταθεί μπροστά σε αυτόν τον Δήμιο της Κόλασης.\\n\"\n\" \\n\"\n\"Γράφεται επίσης ότι αν και κάποτε ήταν θνητός που πολέμησε δίπλα στη Λεγεώνα \"\n\"του Σκότους κατά τη διάρκεια του Πολέμου της Αμαρτίας, έχασε την ανθρωπιά του \"\n\"από την ακόρεστη πείνα του για αίμα.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Φοβάμαι ότι δεν έχω ακούσει τίποτα για έναν τόσο μοχθηρό πολεμιστή, καλέ/ή μου \"\n\"Άρχοντα/ίσσα. Ελπίζω να μην χρειαστεί να τον πολεμήσεις, γιατί ακούγεται \"\n\"εξαιρετικά επικίνδυνος.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Ο Κάιν θα μπορούσε να σου πει πολύ περισσότερα για κάτι τέτοιο, από όσα θα \"\n\"ήθελα ποτέ να μάθω εγώ.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and your \"\n\"defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Εάν πρόκειται να πολεμήσετε έναν τόσο σκληρό αντίπαλο, είθε το Φως να είναι ο \"\n\"οδηγός και ο υπερασπιστής σας. Θα σε έχω στις σκέψεις μου.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well prepared, \"\n\"my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Σκοτεινοί και πονηροί θρύλοι περιβάλλουν τον Πολέμαρχο του Αίματος. Να είσαι \"\n\"καλά προετοιμασμένος, φίλε/η μου, γιατί δεν δείχνει έλεος και δεν χαρίζεται.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and that \"\n\"pretty girl that brings the drinks. Listen here, friend - you're obsessive, \"\n\"you know that?\"\nmsgstr \"\"\n\"Πρέπει πάντα να μιλάς για το αίμα; Τι έχεις να πεις για τα λουλούδια, τον \"\n\"ήλιο, και αυτό το όμορφο κορίτσι που φέρνει τα ποτά. Άκου εδώ, φίλε - είσαι \"\n\"εμμονικός, το ξέρεις;\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of years \"\n\"knowing only warfare. I am sorry... I can not see if you will defeat him.\"\nmsgstr \"\"\n\"Η ικανότητα του με τη λεπίδα είναι φοβερή και έχει ζήσει για χιλιάδες χρόνια \"\n\"γνωρίζοντας μόνο τον πόλεμο. Λυπάμαι... Δεν μπορώ να προβλέψω αν θα τον \"\n\"νικήσεις.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Δεν έχω ασχοληθεί ποτέ με αυτόν τον Πολέμαρχο για τον οποίο μιλάς, αλλά \"\n\"ακούγεται σαν να έχει χρησιμοποιήσει πολλά ξίφη. Δεν θα με πείραζε να \"\n\"τροφοδοτήσω τον στρατό του...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not be \"\n\"denied.\"\nmsgstr \"\"\n\"Η λεπίδα μου τραγουδά για το αίμα σου, θνητέ, και μα τους σκοτεινούς αφέντες \"\n\"μου, δεν θα της το αρνηθώ.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave located \"\n\"in the east. It was being taken there for further study. This stone glowed \"\n\"with an energy that somehow granted vision beyond that which a normal man \"\n\"could possess. I do not know what secrets it holds, my friend, but finding \"\n\"this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Ο Γκρίσγουαλντ μιλά για την Ουράνια Πέτρα που προοριζόταν για το ενκλάβιο που \"\n\"βρίσκεται στα ανατολικά. Μεταφέρθηκε εκεί για περαιτέρω μελέτη. Αυτή η πέτρα \"\n\"έλαμψε με μια ενέργεια που με κάποιον τρόπο προσέφερε όραση πέρα από αυτό που \"\n\"μπορούσε να έχει ένας κανονικός άνθρωπος. Δεν ξέρω τι μυστικά κρύβει, φίλε/η \"\n\"μου, αλλά η εύρεση αυτής της πέτρας σίγουρα θα αποδειχτεί πολύτιμη.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to them...\"\nmsgstr \"\"\n\"Το καραβάνι σταμάτησε εδώ για να πάρει μερικές προμήθειες για το ταξίδι του \"\n\"προς τα ανατολικά. Τους πούλησα μια σειρά από φρέσκα φρούτα και μερικά \"\n\"εξαιρετικά γλυκά που μόλις τελείωσε η Γκάρντα να ψήνει. Κρίμα αυτό που \"\n\"πάθανε...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but I \"\n\"will say this. If rocks are falling from the sky, you had better be careful!\"\nmsgstr \"\"\n\"Δεν ξέρω τι είναι αυτό που νόμιζαν ότι μπορούσαν να δουν με αυτόν τον βράχο, \"\n\"αλλά θα πω αυτό: Αν πέφτουν βράχοι από τον ουρανό, καλύτερα να προσέχεις!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Λοιπόν, ένα καραβάνι μερικών πολύ σημαντικών ανθρώπων σταμάτησε εδώ, αλλά αυτό \"\n\"έγινε πριν από αρκετό καιρό. Είχαν περίεργες προφορές και ξεκινούσαν ένα μακρύ \"\n\"ταξίδι, όπως θυμάμαι.\\n\"\n\" \\n\"\n\"Δεν καταλαβαίνω πώς θα μπορούσες να ελπίζεις ότι θα βρεις κάτι που κουβαλούσαν.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan that \"\n\"was bound for the eastern kingdoms passed through here some time ago. It was \"\n\"supposedly carrying a piece of the heavens that had fallen to earth! The \"\n\"caravan was ambushed by cloaked riders just north of here along the roadway. I \"\n\"searched the wreckage for this sky rock, but it was nowhere to be found. If \"\n\"you should find it, I believe that I can fashion something useful from it.\"\nmsgstr \"\"\n\"Κάτσε για λίγο - Έχω μια ιστορία που μπορεί να σου φανεί ενδιαφέρουσα. Από εδώ \"\n\"πέρασε πριν λίγο καιρό ένα καραβάνι που είχε προορισμό τα ανατολικά βασίλεια. \"\n\"Υποτίθεται ότι κουβαλούσε ένα κομμάτι του ουρανού που είχε πέσει στη γη! Το \"\n\"καραβάνι έπεσε σε ενέδρα από καβαλάρηδες που φορούσαν μανδύες ακριβώς βόρεια \"\n\"από εδώ κατά μήκος του δρόμου. Έψαξα στα συντρίμμια για αυτόν τον ουράνιο \"\n\"βράχο, αλλά δεν τον βρήκα πουθενά. Αν το βρεις, πιστεύω ότι μπορώ να φτιάξω \"\n\"κάτι χρήσιμο από αυτό.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Ακόμα περιμένω να μου φέρεις εκείνη την πέτρα από τον ουρανό. Ξέρω ότι μπορώ \"\n\"να φτιάξω κάτι δυνατό από αυτό.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that my \"\n\"father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Επίτρεψε μου να το δω - ναι... ναι, είναι όπως πίστευα. Δώσε μου ένα λεπτό...\\n\"\n\" \\n\"\n\"Α, ορίστε. Διαρρύθμισα κομμάτια της πέτρας μέσα σε ένα ασημένιο δαχτυλίδι που \"\n\"μου άφησε ο πατέρας μου. Ελπίζω ότι θα σε υπηρετήσει καλά.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and green \"\n\"and red and silver. Don't remember what happened to it, though. I really miss \"\n\"that ring...\"\nmsgstr \"\"\n\"Είχα ένα ωραίο δαχτυλίδι. ήταν πολύ ακριβό, με μπλε και πράσινο και κόκκινο \"\n\"και ασημί. Δεν θυμάμαι τι του συνέβη, όμως. Μου λείπει πολύ αυτό το \"\n\"δαχτυλίδι...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Η Ουράνια Πέτρα είναι πολύ ισχυρή, και αν ήταν κάποιος εκτός από τον \"\n\"Γκρίσγουαλντι που σου πρότεινε να την βρεις, θα σε απέτρεπα. Θα αξιοποιήσει \"\n\"τις δυνάμεις της και η χρησιμότητα της θα είναι για το καλό όλων μας.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what he \"\n\"is doing, and as much as I try to steal his customers, I respect the quality \"\n\"of his work.\"\nmsgstr \"\"\n\"Αν κάποιος μπορεί να φτιάξει κάτι από αυτήν την πέτρα, ο Γκρισγουάλντ μπορεί. \"\n\"Ξέρει τι κάνει και όσο και αν προσπαθώ να κλέψω τους πελάτες του, σέβομαι την \"\n\"ποιότητα της δουλειάς του.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, but \"\n\"this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Η μάγισσα η Άντρια αναζητά ένα μαύρο μανιτάρι; Ξέρω τόσα για τα Μαύρα \"\n\"Μανιτάρια όσο και για τις Κόκκινες Ρέγγες. Ίσως ο Πέπιν ο Θεραπευτής θα \"\n\"μπορούσε να σου πει περισσότερα, αλλά αυτό δεν είναι κάτι που μπορεί να βρεθεί \"\n\"σε κάποια από τις ιστορίες ή στα βιβλία μου.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black mushrooms \"\n\"to our honored guests. If Adria wants some mushrooms in her stew, then that is \"\n\"her business, but I can't help you find any. Black mushrooms... disgusting!\"\nmsgstr \"\"\n\"Επίτρεψε μου να πω μόνο αυτό. Τόσο η Γκάρντα όσο και εγώ δεν θα σερβίραμε ποτέ \"\n\"μαύρα μανιτάρια στους τιμημένους καλεσμένους μας. Αν η Άντρια θέλει μερικά \"\n\"μανιτάρια στο στιφάδο της, τότε είναι δική της δουλειά, αλλά δεν μπορώ να σε \"\n\"βοηθήσω να τα βρεις. Μαύρα μανιτάρια... αηδιαστικό!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect that \"\n\"its alchemy holds. If you can remove the brain of a demon when you kill it, I \"\n\"would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Η μάγισσα μου είπε ότι έψαχνες για τον εγκέφαλο ενός δαίμονα για να με \"\n\"βοηθήσει να δημιουργήσω το ελιξίριο μου. Θα πρέπει να έχει μεγάλη αξία για \"\n\"τους πολλούς που τραυματίζονται από αυτά τα αποκρουστικά θηρία, αν μπορούσα \"\n\"απλώς να ξεκλειδώσω τα μυστικά που υποπτεύομαι ότι κρύβει η αλχημεία του. Εάν \"\n\"μπορείς να αφαιρέσεις τον εγκέφαλο ενός δαίμονα όταν τον σκοτώσεις και να μου \"\n\"τον φέρεις, θα σου ήμουν ευγνώμων.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please carry \"\n\"this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Εξαιρετικό, αυτό ακριβώς είχα στο μυαλό μου. Μπόρεσα να τελειώσω το ελιξίριο \"\n\"χωρίς αυτό, αλλά δεν είναι κακό να το μελετήσω. Θα το μεταφέρεις σε παρακαλώ \"\n\"στη μάγισσα; Πιστεύω ότι το περιμένει.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Νομίζω ότι ο Όγκντεν μπορεί να έχει μερικά μανιτάρια στην αποθήκη του στο \"\n\"κελάρι. Γιατί δεν τον ρωτάς;\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. I \"\n\"can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Εάν η Άντρια δεν έχει ένα από αυτό, μπορείς να στοιχηματίσεις ότι είναι \"\n\"πράγματι σπάνιο. Δεν μπορώ να σου προσφέρω περισσότερη βοήθεια από αυτή, αλλά \"\n\"ακούγεται σαν... ένα τεράστιο, γιγαντιαίο, πρησμένο, φουσκωμένο μανιτάρι! Καλό \"\n\"κυνήγι, υποθέτω.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ο Όγκντεν ανακατεύει ένα ΚΑΚΟ μαύρο μανιτάρι, αλλά θα αρρωστήσω αν το πιώ. \"\n\"Άκου, άκου... εδώ είναι το μυστικό - το να έχεις μέτρο είναι το κλειδί!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep your \"\n\"eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Τι έχουμε εδώ? Είναι ενδιαφέρον, μοιάζει με ένα βιβλίο συστατικών. Κράτα τα \"\n\"μάτια σου ανοιχτά για ένα μαύρο μανιτάρι. Θα πρέπει να είναι αρκετά μεγάλο και \"\n\"να αναγνωρίζεται εύκολα. Αν το βρεις, φέρε το μου, έτσι;\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so that \"\n\"I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Είναι ένα μεγάλο, μαύρο μανιτάρι που χρειάζομαι. Τώρα τρέξε και βρες το για \"\n\"μένα, ώστε να το χρησιμοποιήσω σε ένα ειδικό παρασκεύασμα που δουλεύω.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat those \"\n\"who have been afflicted by their poisonous venom. I believe that he intends to \"\n\"make an elixir from it. If you help him find what he needs, please see if you \"\n\"can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Ναι, αυτό είναι τέλειο για ένα παρασκεύασμα που δημιουργώ. Παρεμπιπτόντως, ο \"\n\"θεραπευτής ψάχνει τον εγκέφαλο κάποιου δαίμονα ή κάτι άλλο για να μπορέσει να \"\n\"θεραπεύσει όσους έχουν πληγεί από το δηλητηριώδες φαρμάκι. Πιστεύω ότι \"\n\"σκοπεύει να φτιάξει ένα ελιξίριο με αυτό. Αν τον βοηθήσεις να βρει αυτό που \"\n\"χρειάζεται, δες αν μπορείς να πάρεις και ένα δείγμα από το ελιξίριο για μένα \"\n\"σε παρακαλώ.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Γιατί το έφερες αυτό εδώ; Δεν έχω ανάγκη για εγκέφαλο δαίμονα αυτή τη στιγμή. \"\n\"Χρειάζομαι λίγο από το ελιξίριο στο οποίο εργάζεται ο Θεραπευτής. Χρειάζεται \"\n\"αυτό το γκροτέσκο όργανο που κρατάς και μετά να μου φέρεις το ελιξίριο. Απλό \"\n\"όταν το σκεφτείς, έτσι δεν είναι;\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Τι? Τώρα μου φέρνεις αυτό το ελιξίριο από τον θεραπευτή; Μπόρεσα να ολοκληρώσω \"\n\"την παρασκευή μου χωρίς αυτό. Γιατί δεν το κρατάς...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about something \"\n\"a bit more useful?\"\nmsgstr \"\"\n\"Δεν έχω προς πώληση μανιτάρια οποιουδήποτε μεγέθους ή χρώματος. Τι θα έλεγες \"\n\"για κάτι λίγο πιο χρήσιμο;\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the secrets \"\n\"of a timeless evil. An evil that quite obviously has now been released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the time \"\n\"when Diablo would rise again from his imprisonment. When the two stars on that \"\n\"map align, Diablo will be at the height of his power. He will be all but \"\n\"invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of his \"\n\"evil again!\"\nmsgstr \"\"\n\"Ώστε, ο θρύλος του Χάρτη είναι πραγματικός. Ακόμα κι εγώ δεν πίστεψα ποτέ \"\n\"τίποτα από αυτά! Υποθέτω ότι ήρθε η ώρα να σου πω την αλήθεια για το ποιος \"\n\"είμαι, φίλε/η μου. Βλέπεις, δεν είμαι μόνο όλο αυτό που φαίνομαι...\\n\"\n\" \\n\"\n\"Το αληθινό μου όνομα είναι Ντέκαρντ Κάιν ο Πρεσβύτερος και είμαι ο τελευταίος \"\n\"απόγονος μιας αρχαίας Αδελφότητας που ήταν αφιερωμένη στο να κρατά και να \"\n\"προστατεύει τα μυστικά ενός διαχρονικού κακού. Ένα κακό που προφανώς έχει \"\n\"πλέον απελευθερωθεί...\\n\"\n\" \\n\"\n\"Το κακό στο οποίο εναντιώνεσαι είναι ο σκοτεινός Άρχοντας του Τρόμου - γνωστός \"\n\"στους θνητούς ως Ντιάμπλο. Ήταν αυτός που φυλακίστηκε μέσα στον Λαβύρινθο πριν \"\n\"από πολλούς αιώνες. Ο Χάρτης που κρατάς τώρα δημιουργήθηκε πριν από πολλά \"\n\"χρόνια για να σηματοδοτήσει την εποχή που ο Ντιάμπλο θα σηκωθεί ξανά από τη \"\n\"φυλάκισή του. Όταν τα δύο αστέρια σε αυτόν τον χάρτη ευθυγραμμιστούν, ο \"\n\"Ντιάμπλο θα είναι στο απόγειο της δύναμής του. Θα είναι ανίκητος...\\n\"\n\" \\n\"\n\"Τώρα είσαι σε αγώνα δρόμου ενάντια στο χρόνο φίλε/η μου! Βρες τον Ντιάμπλο και \"\n\"καταστρέψτε τον πριν ευθυγραμμιστούν τα αστέρια, γιατί μπορεί να μην έχουμε \"\n\"ποτέ ξανά την ευκαιρία να απαλλάξουμε από τον κόσμο το κακό του!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Ο χρόνος μας είναι λίγος! Αισθάνομαι τη σκοτεινή ισχύ του και μόνο εσύ μπορείς \"\n\"να τον εμποδίσεις να αποκτήσει την πλήρη δύναμή του.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, and \"\n\"you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Είμαι σίγουρος ότι έκανες το καλύτερο δυνατό, αλλά φοβάμαι ότι ακόμη και η \"\n\"δύναμη και η θέλησή σου μπορεί να μην είναι αρκετή. Ο Ντιάμπλο βρίσκεται τώρα \"\n\"στο απόγειο της γήινης ισχύος του και θα χρειαστείς όλο σας το θάρρος και τη \"\n\"δύναμή σου για να τον νικήσεις. Είθε το Φως να σε προστατεύει και να σε \"\n\"καθοδηγεί, φίλε/η μου. Θα βοηθήσω με όποιον τρόπο μπορώ.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. You \"\n\"should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Αν η μάγισσα δεν μπορεί να σε βοηθήσει και σου προτείνει να δεις τον Κάιν, τι \"\n\"σε κάνει να πιστεύεις ότι θα ήξερα τίποτα εγώ; Φαίνεται ότι αυτό είναι ένα \"\n\"πολύ σοβαρό θέμα. Θα πρέπει να βιαστείς και να δεις τον αφηγητή ιστοριών όπως \"\n\"προτείνει η Άντρια.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain could \"\n\"help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that is \"\n\"beyond my talents.\"\nmsgstr \"\"\n\"Δεν μπορώ να καταλάβω από τα γραπτά σε αυτόν τον χάρτη, αλλά ίσως η Άντρια ή ο \"\n\"Κάιν θα μπορούσαν να σε βοηθήσουν να αποκρυπτογραφήσεις και να μάθεις σε τι \"\n\"αναφέρεται.\\n\"\n\" \\n\"\n\"Μπορώ να δω ότι είναι ένας χάρτης των αστεριών στον ουρανό μας, αλλά κάτι \"\n\"περισσότερο από αυτό είναι πέρα ​από τα ταλέντα μου.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Το καλύτερο άτομο για να ρωτήσεις για κάτι τέτοιο θα ήταν ο αφηγητής ιστοριών \"\n\"μας.\\n\"\n\" \\n\"\n\"Ο Κάιν γνωρίζει πολύ καλά τα αρχαία γραπτά, και αυτό είναι εύκολα το πιο παλιό \"\n\"χαρτί που έχω δει ποτέ.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Δεν έχω ξαναδεί τέτοιο χάρτη. Πού τον βρήκες; Αν και δεν έχω ιδέα πώς να τον \"\n\"διαβάσω, ο Κάιν ή η Άντρια μπορεί να είναι σε θέση να σου δώσουν τις \"\n\"απαντήσεις που αναζητάς.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Άκου εδώ, έλα κοντά. Δεν ξέρω αν ξέρεις αυτό που ξέρω, αλλά έχεις κάτι εδώ \"\n\"πραγματικά. Αυτός είναι ένας χάρτης.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars portends \"\n\"great disaster, but its secrets are not mine to tell. The time has come for \"\n\"you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Ω, φοβάμαι ότι αυτό δεν προμηνύεται καθόλου καλό. Αυτός ο χάρτης των αστεριών \"\n\"προμηνύει μεγάλη καταστροφή, αλλά τα μυστικά του δεν είναι δικά μου να τα πω. \"\n\"Ήρθε η ώρα να κάνετε μια πολύ σοβαρή συζήτηση με τον αφηγητή ιστοριών...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show that \"\n\"to Adria - she can probably tell you what it is. I'll say one thing; it looks \"\n\"old, and old usually means valuable.\"\nmsgstr \"\"\n\"Έψαχνα για έναν χάρτη, αλλά σίγουρα δεν είναι αυτός. Θα πρέπει να τον δείξεις \"\n\"στην Άντρια - πιθανότατα μπορεί να σου πει τι είναι. Θα πω ένα πράγμα. \"\n\"φαίνεται παλιός και παλιό συνήθως σημαίνει πολύτιμο.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Σε παρακαλωωωωώ, μην με πονέσεις. Όχι σκότωμα. Να είμαι ζωντανός και την \"\n\"επόμενη φορά το καλό πράμα θα σου φέρω.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Κάτι για σένα φτιάχνω. Και πάλι, μην σκοτώσετε τον Γκάρμπαντ. Να ζήσω και σου \"\n\"δώσω καλό πράμα.\\n\"\n\" \\n\"\n\"Πάρε αυτό ως απόδειξη ότι κρατάω τη λέξη μου...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Τίποτα ακόμη! Σχεδόν τελείωσε.\\n\"\n\" \\n\"\n\"Πολύ δυνατό, πολύ δυνατό. Να ζήσω! Ζήσω!\\n\"\n\" \\n\"\n\"Χωρίς πόνο και υπόσχεση κρατώ!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Αυτό είναι πολύ καλό για σένα. Πολύ δυνατό! Το θέλεις - έλα πάρε το!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Τι?! Γιατί είσαι εδώ? Όλες αυτές οι διακοπές είναι αρκετές για να τρελαθεί \"\n\"κανείς. Ορίστε, πάρε αυτό και άφησε με στη δουλειά μου. Μην με ταλαιπωρείς \"\n\"άλλο!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Αρρρργκ! Η περιέργειά σου θα είναι ο θάνατος σου!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Γειά σου, άνθρωπε μου. Ξαπόστασε για λίγο και άκου...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of great \"\n\"knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Ενώ κατεβαίνεις βαθύτερα στον Λαβύρινθο, μπορεί να βρεις κρυμμένους τόμους με \"\n\"σπουδαία γνώση.\\n\"\n\" \\n\"\n\"Διάβασε τους προσεκτικά γιατί μπορούν να σου πουν πράγματα που ακόμη και εγώ \"\n\"δεν μπορώ.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Γνωρίζω πολλούς μύθους και θρύλους που μπορεί να περιέχουν απαντήσεις σε \"\n\"ερωτήσεις που μπορεί να προκύψουν στα ταξίδια σου στον Λαβύρινθο. Αν \"\n\"συναντήσεις προκλήσεις και ερωτήσεις για τις οποίες αναζητάς γνώση, αναζητήστε \"\n\"με και θα σου πω ότι μπορώ.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He is \"\n\"a skilled craftsman, and if he claims to be able to help you in any way, you \"\n\"can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Ο Γκρίσγουαλντ - ένας άνθρωπος δράσης και με μεγάλο θάρρος. Βάζω στοίχημα ότι \"\n\"δεν σου είπε ποτέ για την εποχή που πήγε στον Λαβύρινθο για να σώσει τον \"\n\"Ουίρτ, σωστά; Ξέρει από τους κινδύνους που υπάρχουν εκεί, αλλά πάλι - το ίδιο \"\n\"και εσύ. Είναι επιδέξιος τεχνίτης και αν ισχυρίζεται ότι μπορεί να σε βοηθήσει \"\n\"με οποιονδήποτε τρόπο, μπορείς να βασιστείς στην ειλικρίνεια και την ικανότητά \"\n\"του.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ο Όγκντεν κατέχει και διευθύνει το πανδοχείο και ταβέρνα του Ανατέλλοντος \"\n\"Ηλίου εδώ και σχεδόν τέσσερα χρόνια. Το αγόρασε λίγους μήνες πριν όλα πάνε \"\n\"κατά διαόλου. Αυτός και η σύζυγός του η Γκάρντα δεν έχουν τα χρήματα να φύγουν \"\n\"καθώς επένδυσαν ό,τι είχαν για να φτιάξουν την ζωή τους εδώ. Είναι καλός \"\n\"άνθρωπος με βαθύ αίσθημα ευθύνης.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that entered \"\n\"into the Cathedral with Lazarus on that dark day. He escaped with his life, \"\n\"but his courage and much of his sanity were left in some dark pit. He finds \"\n\"comfort only at the bottom of his tankard nowadays, but there are occasional \"\n\"bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Ο καημένος ο Φάρνxαμ. Είναι μια ανησυχητική υπενθύμιση της καταδικασμένης \"\n\"ομάδας που μπήκε στον καθεδρικό ναό με τον Λάζαρο εκείνη τη σκοτεινή μέρα. \"\n\"Ξέφυγε με τη ζωή του, αλλά το θάρρος του και μεγαλύτερο μέρος της λογικής του \"\n\"έμειναν σε κάποιο σκοτεινό λάκκο. Βρίσκει παρηγοριά μόνο στον πάτο του \"\n\"μπουκαλιού του σήμερα, αλλά υπάρχουν περιστασιακά κομμάτια αλήθειας θαμμένα \"\n\"μέσα στις συνεχείς ασυναρτησίες του.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has access \"\n\"to many strange and arcane artifacts and tomes of knowledge that even I have \"\n\"never seen before.\"\nmsgstr \"\"\n\"Η μάγισσα, Άντρια, είναι μια ιδιαιτερότητα εδώ στην Τρίστραμ. Έφτασε λίγο μετά \"\n\"τη βεβήλωση του καθεδρικού ναού, ενώ περίπου όλοι οι άλλοι τράπηκαν σε φυγή. \"\n\"Έχει χτίσει μια μικρή καλύβα στην άκρη της πόλης, σχεδόν μέσα σε μια νύχτα, \"\n\"και έχει πρόσβαση σε πολλά παράξενα και απόκρυφα τεχνουργήματα και τόμους \"\n\"γνώσης που ακόμη και εγώ δεν έχω ξαναδεί.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the arms \"\n\"of his mother and dragged into the labyrinth by the small, foul demons that \"\n\"wield wicked spears. There were many other children taken that day, including \"\n\"the son of King Leoric. The Knights of the palace went below, but never \"\n\"returned. The Blacksmith found the boy, but only after the foul beasts had \"\n\"begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Η ιστορία του Ουίρτ είναι τρομακτική και τραγική. Τον πήραν από την αγκαλιά \"\n\"της μητέρας του και τον έσυραν στον λαβύρινθο οι μικροί, βρωμεροί δαίμονες που \"\n\"κρατούσαν άσχημες λόγχες. Πολλά άλλα παιδιά απήχθησαν εκείνη την ημέρα, \"\n\"συμπεριλαμβανομένου και του γιου του βασιλιά Λεόρικ. Οι Ιππότες του παλατιού \"\n\"πήγαν κάτω, αλλά δεν επέστρεψαν ποτέ. Ο Σιδηρουργός βρήκε το αγόρι, αλλά μόνο \"\n\"αφού τα θηρία είχαν αρχίσει να το βασανίζουν για τις σαδιστικές απολαύσεις \"\n\"τους.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. He \"\n\"is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Α, ο Πέπιν. Τον θεωρώ αληθινό φίλο μου - ίσως τον πιο κοντινό που έχω εδώ. \"\n\"Είναι λίγο μπερδεμένος κατά καιρούς, αλλά ποτέ δεν υπήρξε η πιο φροντιστική ή \"\n\"προσεκτική ψυχή. Οι γνώσεις και οι δεξιότητές του εξισώνονται με λίγους, και η \"\n\"πόρτα του είναι πάντα ανοιχτή.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick laugh, \"\n\"she holds a special place in my heart. She stays on at the tavern to support \"\n\"her elderly grandmother who is too sick to travel. I sometimes fear for her \"\n\"safety, but I know that any man in the village would rather die than see her \"\n\"harmed.\"\nmsgstr \"\"\n\"Η Γκίλιαν είναι μια ωραία γυναίκα. Πολύ λατρεμένη για την καλή της διάθεση και \"\n\"το γρήγορο γέλιο της, κατέχει μια ξεχωριστή θέση στην καρδιά μου. Μένει στην \"\n\"ταβέρνα για να στηρίξει την ηλικιωμένη γιαγιά της που είναι πολύ άρρωστη για \"\n\"να ταξιδέψει. Μερικές φορές φοβάμαι για την ασφάλειά της, αλλά ξέρω ότι \"\n\"οποιοσδήποτε άντρας στο χωριό προτιμά να πεθάνει παρά να τη δει να παθαίνει \"\n\"κακό.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"\"\n\"Χαιρετισμούς, καλέ/ή μου άρχοντα/ισσα Καλώς ήρθες στην Ταβέρνα του \"\n\"Ανατέλλοντος Ηλίου!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard any \"\n\"of them agree on was this old axiom. Perhaps it will help you. You can cut the \"\n\"flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Πολλοί τυχοδιώκτες έχουν κοσμήσει τα τραπέζια της ταβέρνας μου και έχουν \"\n\"ειπωθεί δέκα φορές περισσότερες ιστορίες πάνω από μπίρες. Το μόνο πράγμα στο \"\n\"οποίο άκουσα ποτέ κάποιον από αυτούς να συμφωνεί ήταν αυτό το παλιό αξίωμα. \"\n\"Ίσως θα σε βοηθήσει. Μπορεί να κόψεις τη σάρκα, αλλά πρέπει να συνθλίψεις το \"\n\"κόκαλο.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. If \"\n\"you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Ο Γκρίσγουαλντ ο σιδηρουργός είναι εξαιρετικός γνώστης των όπλων και της \"\n\"Θωράκισης. Αν χρειαστείς ποτέ δουλειά στον εξοπλισμό σου, είναι σίγουρα ο \"\n\"άνθρωπος που πρέπει να δεις.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Ο Φάρνχαμ ξοδεύει πάρα πολύ χρόνο εδώ, πνίγοντας τις λύπες του σε φτηνή μπύρα. \"\n\"Θα τον έδιωχνα, αλλά υπέφερε τόσο πολύ όταν πήγε στον Λαβύρινθο.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Η Άντρια είναι πολύ σοφή πέρα ​​από τα χρόνια της, αλλά πρέπει να ομολογήσω - με \"\n\"τρομάζει λίγο.\\n\"\n\" \\n\"\n\"Λοιπόν, δεν έχει σημασία. Αν ποτέ χρειαστεί να εμπορευθείς είδη μαγείας, \"\n\"διατηρεί μια περίεργα καλά εφοδιασμένη καλύβα ακριβώς απέναντι από το ποτάμι.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Αν θέλετε να μάθεις περισσότερα για την ιστορία του χωριού μας, ο αφηγητής \"\n\"ιστοριών μας ο Κάιν γνωρίζει αρκετά για το παρελθόν.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Ο Ουίρτ είναι ένα παλιόπαιδο και ένας μικρός απατεώνας. Πάντα έμπαινε σε \"\n\"μπελάδες και δεν αποτελεί έκπληξη αυτό που του συνέβη.\\n\"\n\" \\n\"\n\"Μάλλον έμπλεξε κάπου που δεν έπρεπε να ήταν. Λυπάμαι για το αγόρι, αλλά δεν \"\n\"αντέχω την παρέα του.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Ο Πέπιν είναι καλός άνθρωπος - και σίγουρα ο πιο γενναιόδωρος στο χωριό. \"\n\"Φροντίζει πάντα τις ανάγκες των άλλων, αλλά κάποιου είδους προβλήματα φαίνεται \"\n\"να τον ακολουθούν όπου κι αν πάει...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after the \"\n\"old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Η Γκίλιαν, η σερβιτόρα μου; Αν δεν ήταν για την αίσθηση του καθήκοντός της \"\n\"προς τη γιαγιά της, θα είχε φύγει από εδώ, εδώ και πολύ καιρό.\\n\"\n\" \\n\"\n\"Μα το καλό μου, την παρακάλεσα να φύγει, λέγοντάς της ότι θα πρόσεχα τη \"\n\"ηλικιωμένη, αλλά είναι πολύ γλυκιά και περιποιητική για να έφευγε.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Τι σε ταλαιπωρεί άνθρωπε μου;\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you hurt \"\n\"one of the monsters, make sure it is dead or it very well may regenerate \"\n\"itself.\"\nmsgstr \"\"\n\"Έχω κάνει μια πολύ ενδιαφέρουσα ανακάλυψη. Σε αντίθεση με εμάς, τα πλάσματα \"\n\"στον Λαβύρινθο μπορούν να θεραπεύσουν τον εαυτό τους χωρίς τη βοήθεια φίλτρων \"\n\"ή μαγείας. Εάν πληγώσεις ένα από τα τέρατα, βεβαιώσου ότι είναι νεκρό \"\n\"διαφορετικά μπορεί να αναγεννήσει τις σάρκες του.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Πριν καταληφθεί από... ό,τι κρύβεται από κάτω, ο καθεδρικός ναός ήταν ένας \"\n\"τόπος μεγάλης μάθησης. Υπάρχουν πολλά βιβλία που μπορείς να βρεις εκεί. Αν \"\n\"βρεις κάποια, σου προτείνω να τα διαβάσεις, γιατί μπορεί να κρατούν μυστικά \"\n\"για τον Λαβύρινθο.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of healing. \"\n\"He is a shrewd merchant, but his work is second to none. Oh, I suppose that \"\n\"may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Ο Γκρίσγουαλντ γνωρίζει τόσα πολλά για την τέχνη του πολέμου όσο κι εγώ για \"\n\"την τέχνη της θεραπείας. Είναι οξυδερκής έμπορος, και η δουλειά του είναι \"\n\"πρώτης ποιότητας. Α, υποθέτω ότι αυτό μπορεί να οφείλεται στο ότι είναι ο \"\n\"μόνος σιδηρουργός που έχει απομείνει εδώ.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has an \"\n\"innate ability to discern the true nature of many things. If you ever have any \"\n\"questions, he is the person to go to.\"\nmsgstr \"\"\n\"Ο Κάιν είναι αληθινός φίλος και σοφός γνώστης. Διατηρεί μια τεράστια \"\n\"βιβλιοθήκη και έχει μια έμφυτη ικανότητα να διακρίνει την αληθινή φύση πολλών \"\n\"πραγμάτων. Αν έχεις ποτέ απορίες, είναι το άτομο στο οποίο πρέπει να πας.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able to \"\n\"mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Ακόμη και οι ικανότητές μου δεν μπόρεσαν να θεραπεύσουν πλήρως τον Φάρνχαμ. Ω, \"\n\"μπόρεσα να ιάσω το σώμα του, αλλά το μυαλό και το πνεύμα του είναι πέρα ​​από \"\n\"οτιδήποτε μπορώ να κάνω.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may be \"\n\"much more than the hovel it appears to be, but I can never seem to get inside \"\n\"the place.\"\nmsgstr \"\"\n\"Ενώ εγώ χρησιμοποιώ μερικές περιορισμένες μορφές μαγείας για να δημιουργήσω τα \"\n\"φίλτρα και τα ελιξίρια που αποθηκεύω εδώ, η Άντρια είναι μια αληθινή μάγισσα. \"\n\"Δεν φαίνεται να κοιμάται ποτέ και έχει πάντα πρόσβαση σε πολλούς \"\n\"μυστικιστικούς τόμους και τεχνουργήματα. Πιστεύω ότι η καλύβα της μπορεί να \"\n\"είναι πολύ περισσότερο από την παράγκα που φαίνεται να είναι, αλλά δεν έχω \"\n\"καταφέρει ποτέ να μπω μέσα εκεί.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Ο φτωχός Ουίρτ. Έκανα ό,τι ήταν δυνατό για το παιδί, αλλά ξέρω ότι περιφρονεί \"\n\"αυτό το ξύλινο παλούκι που αναγκάστηκα να βάλω στο πόδι του. Οι πληγές του \"\n\"ήταν φρικτές. Κανείς - και ειδικά ένα τόσο μικρό παιδί - δεν θα έπρεπε να \"\n\"υποφέρει όπως έπαθε.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from a \"\n\"slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the many \"\n\"murders that happen in the surrounding countryside, or perhaps the wishes of \"\n\"his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Πραγματικά δεν καταλαβαίνω γιατί ο Όγκντεν μένει εδώ στην Τρίστραμ. Πάσχει από \"\n\"μια ελαφριά νευρική πάθηση, αλλά είναι ένας έξυπνος και εργατικός άνθρωπος που \"\n\"θα τα πήγαινε πολύ καλά όπου κι αν πήγαινε. Υποθέτω ότι μπορεί να είναι ο \"\n\"φόβος των πολλών δολοφονιών που συμβαίνουν στη γύρω ύπαιθρο ή ίσως οι \"\n\"επιθυμίες της γυναίκας του που κρατούν αυτόν και την οικογένειά του εδώ.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Η σερβιτόρα του Όγκντεν είναι ένα γλυκό κορίτσι. Η γιαγιά της είναι αρκετά \"\n\"άρρωστη και υποφέρει από παραισθήσεις.\\n\"\n\" \\n\"\n\"Ισχυρίζεται ότι βλέπει οράματα, αλλά δεν υπάρχει καμία απόδειξη γι' αυτά με \"\n\"κανέναν τρόπο.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Καλημέρα! Πώς μπορώ να σε υπηρετήσω;\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Η γιαγιά μου είχε ένα όνειρο ότι θα έρθεις να μου μιλήσεις. Έχει οράματα \"\n\"ξέρεις, και μπορεί να δει στο μέλλον.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her name, \"\n\"Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Η γυναίκα στην άκρη της πόλης είναι μάγισσα! Φαίνεται αρκετά ωραία, και το \"\n\"όνομά της, Άντρια, είναι πολύ ευχάριστο στο αυτί, αλλά τη φοβάμαι πολύ.\\n\"\n\" \\n\"\n\"Θα χρειαζόταν κάποιος αρκετά γενναίος/α, όπως εσύ, για να δει τι κάνει εκεί \"\n\"έξω.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he a \"\n\"master craftsman who has won many contests within his guild, but he received \"\n\"praises from our King Leoric himself - may his soul rest in peace. Griswold is \"\n\"also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Ο Σιδηρουργός μας είναι ορόσημο υπερηφάνειας για τους κατοίκους της Τρίστραμ. \"\n\"Όχι μόνο είναι ένας τεχνίτης που έχει κερδίσει πολλούς διαγωνισμούς στην \"\n\"συντεχνία του, αλλά έλαβε επαίνους από τον ίδιο τον Βασιλιά μας τον Λεόρικ - \"\n\"ας αναπαύεται η ψυχή του εν ειρήνη. Ο Γκρίσγουαλντ είναι επίσης μεγάλος ήρωας. \"\n\"απλά ρώτα τον Κάιν.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Ο Κάιν είναι ο αφηγητής Ιστοριών της Τρίστραμ για όσο μπορώ να θυμηθώ. Ξέρει \"\n\"τόσα πολλά και μπορεί να σου πει σχεδόν τα πάντα για... σχεδόν τα πάντα.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor every \"\n\"night.\"\nmsgstr \"\"\n\"Ο Φάρνχαμ είναι ένας μεθυσμένος που γεμίζει την κοιλιά του με μπύρα και τα \"\n\"αυτιά όλων μας με ανοησίες.\\n\"\n\" \\n\"\n\"Ξέρω ότι τόσο ο Πέπιν όσο και ο Όγκντεν αισθάνονται συμπάθεια γι' αυτόν, αλλά \"\n\"απογοητεύομαι τόσο πολύ βλέποντάς τον να γλιστράει όλο και πιο βαθιά σε ένα \"\n\"μπερδεμένο μεθύσι κάθε βράδυ.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in need \"\n\"of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Ο Πέπιν έσωσε τη ζωή της γιαγιάς μου και ξέρω ότι δεν μπορώ ποτέ να του το \"\n\"ανταποδώσω. Η ικανότητά του να θεραπεύει οποιαδήποτε ασθένεια είναι πιο ισχυρή \"\n\"από το ισχυρότερο σπαθί και πιο μυστηριώδης από οποιοδήποτε ξόρκι που μπορείς \"\n\"να ονομάσεις. Εάν ποτέ χρειαστείς θεραπεία, ο Πέπιν μπορεί να σε βοηθήσει.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt when \"\n\"those hideous creatures stole him, she never recovered. I think she died of a \"\n\"broken heart. Wirt has become a mean-spirited youngster, looking only to \"\n\"profit from the sweat of others. I know that he suffered and has seen horrors \"\n\"that I cannot even imagine, but some of that darkness hangs over him still.\"\nmsgstr \"\"\n\"Μεγάλωσα με τη μητέρα του Ουίρτ, την Κάνας. Αν και αυτή μόνο τραυματίστηκε \"\n\"ελαφρά, όταν της έκλεψαν το γιό αυτά τα απαίσια πλάσματα, δεν συνήλθε ποτέ. \"\n\"Νομίζω ότι πέθανε από ραγισμένη καρδιά. Ο Ουίρτ έχει γίνει ένας κακότροπος \"\n\"νεαρός, που θέλει μόνο να επωφεληθεί από τον ιδρώτα των άλλων. Ξέρω ότι \"\n\"υπέφερε και έχει δει φρίκες που δεν μπορώ καν να φανταστώ, αλλά κάποιο από \"\n\"αυτό το σκοτάδι κρέμεται ακόμα από πάνω του.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ο Όγκντεν και η γυναίκα του πήραν εμένα και τη γιαγιά μου στο σπίτι τους και \"\n\"με άφησαν να κερδίσω μερικά χρυσά νομίσματα δουλεύοντας στο πανδοχείο. Τους \"\n\"χρωστάω τόσα πολλά και ελπίζω μια μέρα να φύγω από αυτό το μέρος και να τους \"\n\"βοηθήσω να ξεκινήσουν ένα μεγάλο ξενοδοχείο στα ανατολικά.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Λοιπόν, τι μπορώ να κάνω για σένα;\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your basic \"\n\"blunt weapon, such as a mace. Works like a charm against most of those undying \"\n\"horrors down there, and there's nothing better to shatter skinny little \"\n\"skeletons!\"\nmsgstr \"\"\n\"Αν ψάχνεις για ένα καλό όπλο, επίτρεψε μου να σου δείξω αυτό. Πάρτε το βασικό \"\n\"σας αμβλύ όπλο, όπως τον κεφαλοθραύστη. Λειτουργεί τέλεια ενάντια στους \"\n\"περισσότερους από αυτούς τους αθάνατους τρόμους εκεί κάτω, και δεν υπάρχει \"\n\"τίποτα καλύτερο για να θρυμματίσεις τους μικρούς αδύνατους σκελετούς!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy blow!\"\nmsgstr \"\"\n\"Το τσεκούρι; Ναι, αυτό είναι ένα καλό όπλο, ισορροπημένο ενάντια σε κάθε \"\n\"εχθρό. Κοίταξε πώς κόβει τον αέρα και μετά φαντάσου ένα ωραίο χοντρό κεφάλι \"\n\"δαίμονα στο πέρασμά του. Λάβε υπόψη, ωστόσο, ότι αργεί στο κτύπημα - αλλά \"\n\"μιλάμε για ένα βαρύ και καίριο χτύπημα!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Κοίτα αυτή την λεπίδα, αυτή την ισορροπία. Ένα ξίφος στα σωστά χέρια, και \"\n\"ενάντια στον σωστό εχθρό, είναι ο κύριος όλων των όπλων. Η κοφτερή λεπίδα του \"\n\"βρίσκει λίγα για να κόψει ή να διαπεράσει στους απέθαντους, αλλά ενάντια σε \"\n\"έναν ζωντανό εχθρό που αναπνέει, ένα σπαθί θα κόψει εύκολα τη σάρκα του!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Τα όπλα και η πανοπλία σου θα φέρουν τα σημάδια των αγώνων σου ενάντια στο \"\n\"Σκοτάδι. Αν μου τα φέρεις, με λίγη δουλειά στο ζεστό σιδηρουργείο μου, μπορώ \"\n\"να τα επαναφέρω στην κορυφαία αγωνιστική τους κατάσταση.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how to \"\n\"harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Ενώ πρέπει κυριολεκτικά να μεταφέρω λαθραία τα μέταλλα και τα εργαλεία που \"\n\"χρειάζομαι από τα καραβάνια που περνούν απο τις άκρες της καταραμένης πόλης \"\n\"μας, αυτή η μάγισσα, η Άντρια, φαίνεται να παίρνει πάντα ό,τι χρειάζεται. Αν \"\n\"ήξερα έστω και το παραμικρό για το πώς να αξιοποιώ τη μαγεία όπως εκείνη, θα \"\n\"μπορούσα να φτιάξω μερικά πραγματικά απίστευτα πράγματα.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Η Γκίλιαν είναι μια ωραία κοπέλα. Κρίμα που η ηλικιωμένη μάνα της είναι τόσο \"\n\"άρρωστη, διαφορετικά θα κανόνιζα να φύγουν και οι δύο από εδώ σε ένα από τα \"\n\"εμπορικά καραβάνια.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling in \"\n\"life. If I could bend steel as well as he can bend your ear, I could make a \"\n\"suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Μερικές φορές νομίζω ότι ο Κάιν μιλάει πάρα πολύ, αλλά υποθέτω ότι αυτό είναι \"\n\"το κάλεσμα του στη ζωή. Αν μπορούσα να λυγίσω το ατσάλι όπως αυτός μπορεί να \"\n\"λυγίσει το αυτί σου, θα μπορούσα να φτιάξω μια αυλική ολομεταλλική πανοπλία \"\n\"αρκετά καλή για έναν Αυτοκράτορα!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never saw \"\n\"the Archbishop again, and I may not have survived if Farnham was not at my \"\n\"side. I fear that the attack left his soul as crippled as, well, another did \"\n\"my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Ήμουν με τον Φάρνχαμ εκείνο το βράδυ που ο Λάζαρος μας οδήγησε στον Λαβύρινθο. \"\n\"Δεν είδα ποτέ ξανά τον Αρχιεπίσκοπο και μπορεί να μην είχα επιζήσει αν ο \"\n\"Φάρνχαμ δεν ήταν δίπλα μου. Φοβάμαι ότι η επίθεση άφησε την ψυχή του τόσο \"\n\"ανάπηρη όσο και το πόδι μου. Δεν μπορώ να δώσω αυτή τη μάχη για αυτόν τώρα, \"\n\"αλλά θα το έκανα αν μπορούσα.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Ένας καλός άνθρωπος που βάζει τις ανάγκες των άλλων πάνω από τις δικές του. \"\n\"Δεν θα βρεις κανέναν στην Τρίστραμ - ή πουθενά αλλού για αυτό το θέμα - που να \"\n\"έχει κάτι κακό να πει για τον θεραπευτή.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an honest \"\n\"trade, but he prefers the high profits of dealing in goods of dubious origin. \"\n\"I cannot hold that against him after what happened to him, but I do wish he \"\n\"would at least be careful.\"\nmsgstr \"\"\n\"Αυτό το παλικάρι θα βάλει τον εαυτό του σε σοβαρό μπελά... ή μάλλον πρέπει να \"\n\"πω θα ξαναβάλει. Προσπάθησα να τον κινήσω το ενδιαφέρον να δουλέψει εδώ και να \"\n\"μάθει ένα τίμιο επάγγελμα, αλλά προτιμά τα υψηλά κέρδη από την εμπορία \"\n\"εμπορευμάτων αμφιβόλου προέλευσης. Δεν μπορώ να τον κατηγορήσω για αυτό μετά \"\n\"από αυτό που του συνέβη, αλλά εύχομαι να ήταν τουλάχιστον προσεκτικός.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of grains \"\n\"and dried meats he kept in his cellar, why, most of us would have starved \"\n\"during that first year when the entire countryside was overrun by demons.\"\nmsgstr \"\"\n\"Ο πανδοχέας έχει ελάχιστες δουλειές και δεν έχει πραγματικό τρόπο να βγάλει \"\n\"κέρδος. Καταφέρνει να τα βγάλει πέρα ​​παρέχοντας φαγητό και κατάλυμα σε όσους \"\n\"περιστασιακά περνούν στο χωριό, αλλά είναι τόσο πιθανό να φύγουν κρυφά τη \"\n\"νύχτα όπως και να τον πληρώσουν. Αν δεν υπήρχαν οι αποθήκες με σιτηρά και \"\n\"αποξηραμένα κρέατα που κρατούσε στο κελάρι του, ω, οι περισσότεροι από εμάς θα \"\n\"είχαμε πεινάσει κατά τη διάρκεια του πρώτου έτους, όταν ολόκληρη η ύπαιθρος \"\n\"είχε κατακλυστεί από δαίμονες.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Δεν μπορεί ένα φιλαράκι να πιεί με την ησυχία του;\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"Το κορίτσι που φέρνει τα ποτά; Ω, ναι, τι όμορφη κυρία. Τόσο καλή επίσης.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat or \"\n\"drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Γιατί αυτή η παλιόγρια δεν κάνει κάτι για μια φορά. Σίγουρα, σίγουρα, έχει \"\n\"πράγματα, αλλά άκουσε με... είναι αφύσικη. Δεν την έχω δει ποτέ να τρώει ή να \"\n\"πίνει - και δεν μπορείς να εμπιστευτείς κάποιον που δεν πίνει τουλάχιστον λίγο.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Ο Κάιν δεν είναι αυτό που λέει ότι είναι. Σίγουρα, σίγουρα, λέει μια καλή \"\n\"ιστορία... μερικές από αυτές είναι πραγματικά τρομακτικές ή αστείες... αλλά \"\n\"νομίζω ότι ξέρει περισσότερα από όσα ξέρει ότι ξέρει.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Ο Γκρίσγουαλντ; Ο παλιός καλός Γκρίσγουαλντ. Τον αγαπώ σαν αδερφό! Μαζί \"\n\"πολεμήσαμε, ξέρεις τότε όταν... εμείς... Λάζαρε... Λάζαρε... Λάζαρε!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should make \"\n\"sure you get to know him. Good fella like that with people always wantin' \"\n\"help. Hey, I guess that would be kinda like you, huh hero? I was a hero too...\"\nmsgstr \"\"\n\"Χεχχε, μου αρέσει ο Πέπιν. Προσπαθεί πραγματικά, ξέρεις. Άκουσε με, θα πρέπει \"\n\"να φροντίσεις να τον γνωρίσεις. Καλό τυπάκι για ανθρώπους που πάντα θέλουν \"\n\"βοήθεια. Ε, υποθέτω ότι μοιάζει σαν εσένα, ε ήρωα/ίδα; Ήμουν κι εγώ ήρωας...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about problems. \"\n\"Listen here - that kid is gotta sweet deal, but he's been there, you know? \"\n\"Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Ο Ουίρτ είναι ένα παιδί με περισσότερα προβλήματα ακόμα και από εμένα, και \"\n\"ξέρω τα πάντα για προβλήματα. Άκουσε εδώ - αυτό το παιδί έχει βρει μια καλή \"\n\"συμφωνία, αλλά ήταν εκεί, ξέρεις; Έχασε ένα πόδι! Πρέπει να περπατά με ένα \"\n\"κομμάτι ξύλο. Τόσο λυπηρό, τόσο λυπηρό...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ο Όγκντεν είναι ο καλύτερος άντρας της πόλης. Δεν νομίζω ότι η γυναίκα του με \"\n\"συμπαθεί, αλλά όσο συνεχίζει να ανοίγει βαρέλια, θα μου αρέσει μια χαρά. \"\n\"Φαίνεται ότι περνάω περισσότερο χρόνο με τον Όγκντεν σε σχέση με τους άλλους, \"\n\"αλλά είναι τόσο καλός μαζί μου...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no good \"\n\"since those stupid dogs...\"\nmsgstr \"\"\n\"Θέλω να σου πω κάτι τις, γιατί ξέρω τα πάντα για αυτό το πράγμα. Είναι η \"\n\"ειδικότητά μου. Αυτό εδώ είναι το καλύτερο... τοοοο καλύτερο! Αυτή η άλλη \"\n\"μπύρα δεν είναι καλή, αφού αυτά τα ανόητα σκυλιά...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but somewhere \"\n\"under the church is a whole pile o' gold. Gleamin' and shinin' and just \"\n\"waitin' for someone to get it.\"\nmsgstr \"\"\n\"Κανείς δεν με ακούει ποτέ. Κάπου - δεν είμαι και πολύ σίγουρος - αλλά κάπου \"\n\"κάτω από την εκκλησία είναι μια ολόκληρη στοίβα από χρυσάφι. Γυαλίζει και \"\n\"λάμπει και απλώς περιμένει κάποιος να την μαζέψει.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, but \"\n\"that weapon you got there - it just ain't no good against those big brutes! \"\n\"Oh, I don't care what Griswold says, they can't make anything like they used \"\n\"to in the old days...\"\nmsgstr \"\"\n\"Ξέρω ότι έχεις τις δικές σου ιδέες και ξέρω ότι δεν θα το πιστέψεις αυτό, αλλά \"\n\"αυτό το όπλο που έχεις εκεί - απλά δεν είναι καλό ενάντια σε αυτά τα μεγάλα \"\n\"βάναυσα θηρία! Α, δεν με νοιάζει τι λέει ο Γκρίσγουαλντ, δεν τα φτιάχνουν όπως \"\n\"τις παλιές μέρες πια...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, but \"\n\"you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Αν ήμουν στη θέση σου... και δεν είμαι... αλλά αν ήμουν, θα πουλούσα όλα αυτά \"\n\"που βρήκες και θα έφευγα από εδώ. Αυτό το αγόρι εκεί έξω... Έχει πάντα κάτι \"\n\"καλό, αλλά πρέπει να του δώσεις λίγο χρυσό αλλιώς δεν θα σου δείξει καν τι \"\n\"έχει.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Αισθάνομαι μια ψυχή που αναζητά απαντήσεις...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Η σοφία κερδίζεται, δεν δίνεται. Εάν ανακαλύψεις ένα τόμο με γνώση, \"\n\"καταβροχθίστε τα λόγια του. Εάν έχεις ήδη γνώση των απόκρυφων μυστηρίων που \"\n\"είναι εγγεγραμμένα σε ένα βιβλίο, θυμήσου - αυτό το επίπεδο μαεστρίας μπορεί \"\n\"πάντα να αυξάνεται.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words of \"\n\"power written upon scrolls of parchment. The strength of these scrolls lies in \"\n\"the ability of either apprentice or adept to cast them with equal ability. \"\n\"Their weakness is that they must first be read aloud and can never be kept at \"\n\"the ready in your mind. Know also that these scrolls can be read but once, so \"\n\"use them with care.\"\nmsgstr \"\"\n\"Η μεγαλύτερη δύναμη έχει συχνά την πιο σύντομη ζωή. Μπορείς να βρεις αρχαίες \"\n\"λέξεις δύναμης γραμμένες σε πάπυρο από περγαμηνή. Η δύναμη αυτών των πάπυρων \"\n\"έγκειται στην ικανότητα είτε του μαθητευόμενου είτε του έμπειρου να ρίχνει τα \"\n\"ξόρκια με την ίδια ικανότητα. Η αδυναμία τους είναι ότι πρέπει πρώτα να \"\n\"διαβαστούν δυνατά και δεν μπορούν ποτέ να διατηρηθούν σε ετοιμότητα στο μυαλό \"\n\"σου. Ξέρε επίσης ότι αυτοί οι πάπυροι μπορούν να διαβαστούν μόνο μία φορά, γι' \"\n\"αυτό χρησιμοποιήσε τους με προσοχή.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is of \"\n\"greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with magical \"\n\"energies many times over. I have the ability to restore their power - but know \"\n\"that nothing is done without a price.\"\nmsgstr \"\"\n\"Αν και η θερμότητα του ήλιου είναι απεριόριστη, η απλή φλόγα ενός κεριού είναι \"\n\"μεγαλύτερος κίνδυνος. Καμία από τις ενέργειες, όσο μεγάλες κι αν είναι, δεν \"\n\"μπορεί να χρησιμοποιηθούν χωρίς την κατάλληλη εστίαση. Για πολλά ξόρκια, οι \"\n\"μαγικές Ράβδοι μπορούν να φορτίζονται με μαγικές ενέργειες πολλές φορές. Έχω \"\n\"τη δυνατότητα να αποκαταστήσω τη δύναμή τους - αλλά να ξέρεις ότι τίποτα δεν \"\n\"γίνεται χωρίς τίμημα.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Το άθροισμα της γνώσης μας βρίσκεται στο άθροισμα των ανθρώπων της. Αν βρεις \"\n\"ένα βιβλίο ή πάπυρο που δεν μπορείς να αποκρυπτογραφήσεις, μη διστάσεις να μου \"\n\"το φέρεις. Αν μπορώ να το κατανοήσω, θα μοιραστώ μαζί σου ό,τι βρω.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Για έναν άνθρωπο που γνωρίζει μόνο το Σίδηρο, δεν υπάρχει μεγαλύτερη μαγεία \"\n\"από το Ατσάλι. Ο σιδηρουργός ο Γκρίσγουαλντ είναι περισσότερο μάγος από όσο \"\n\"ξέρει. Η ικανότητά του να συγχωνεύει φωτιά και μέταλλο είναι απαράμιλλη σε \"\n\"αυτή τη χώρα.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Η διαφθορά έχει τη δύναμη της εξαπάτησης, αλλά η αθωότητα κατέχει τη δύναμη \"\n\"της αγνότητας. Η νεαρή Γκίλιαν έχει αγνή καρδιά, βάζοντας τις ανάγκες της \"\n\"μητέρας της πάνω από τις δικές της. Με φοβάται, αλλά είναι μόνο επειδή δεν με \"\n\"καταλαβαίνει.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened in \"\n\"the light. The storyteller Cain is an enigma, but only to those who do not \"\n\"look. His knowledge of what lies beneath the cathedral is far greater than \"\n\"even he allows himself to realize.\"\nmsgstr \"\"\n\"Ένα σεντούκι που ανοίγει στο σκοτάδι δεν έχει μεγαλύτερο θησαυρό από όταν \"\n\"ανοίγει στο φως. Ο αφηγητής ιστοριών ο Κάιν είναι ένα αίνιγμα, αλλά μόνο για \"\n\"όσους δεν κοιτούν. Η γνώση του για το τι κρύβεται κάτω από τον καθεδρικό ναό \"\n\"είναι πολύ μεγαλύτερη από ό,τι αφήνει τον ίδιο τον εαυτό του να \"\n\"συνειδητοποιήσει.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to be \"\n\"gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Όσο πιο ψηλά βάζεις την πίστη σου σε έναν άνθρωπο, τόσο πιο μακριά πρέπει να \"\n\"πέσει. Ο Φάρνχαμ έχει χάσει την ψυχή του, αλλά όχι από κανένα δαίμονα. Χάθηκε \"\n\"όταν είδε τους συμπολίτες του να προδίδονται από τον Αρχιεπίσκοπο Λάζαρο. Έχει \"\n\"γνώσεις που πρέπει να σταχυολογηθούν, αλλά πρέπει να διαχωρίσεις τα γεγονότα \"\n\"από τη φαντασία του πρώτα.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in perfect \"\n\"harmony. The healer Pepin sees into the body in a way that even I cannot. His \"\n\"ability to restore the sick and injured is magnified by his understanding of \"\n\"the creation of elixirs and potions. He is as great an ally as you have in \"\n\"Tristram.\"\nmsgstr \"\"\n\"Το χέρι, η καρδιά και το μυαλό μπορούν να κάνουν θαύματα όταν βρίσκονται σε \"\n\"τέλεια αρμονία. Ο θεραπευτής Πέπιν βλέπει μέσα στο σώμα με τρόπο που ούτε εγώ \"\n\"δεν μπορώ. Η ικανότητά του να αποκαθιστά τους άρρωστους και τους τραυματίες \"\n\"μεγεθύνεται από την κατανόησή του για τη δημιουργία ελιξιρίων και φίλτρων. \"\n\"Είναι τόσο σπουδαίος σύμμαχος όσο εσύ στην Τρίστραμ.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be the \"\n\"children who wield it. The boy Wirt has a blackness upon his soul, but he \"\n\"poses no threat to the town or its people. His secretive dealings with the \"\n\"urchins and unspoken guilds of nearby towns gain him access to many devices \"\n\"that cannot be easily found in Tristram. While his methods may be reproachful, \"\n\"Wirt can provide assistance for your battle against the encroaching Darkness.\"\nmsgstr \"\"\n\"Υπάρχουν πολλά για το μέλλον που δεν μπορούμε να δούμε, αλλά όταν έρθει θα \"\n\"είναι τα παιδιά που θα το χειριστούν. Το αγόρι ο Ουίρτ έχει μια μαυρίλα στην \"\n\"ψυχή του, αλλά δεν αποτελεί απειλή για την πόλη ή τους ανθρώπους της. Οι \"\n\"μυστικοπαθείς συναλλαγές του με τα αλάνια και τις ανείπωτες συντεχνίες των \"\n\"κοντινών πόλεων, του δίνουν πρόσβαση σε πολλά μέσα που δεν μπορούν εύκολα να \"\n\"βρεθούν στην Τρίστραμ. Αν και οι μέθοδοί του μπορεί να είναι καταδικαστέες, ο \"\n\"Ουίρτ μπορεί να σε βοηθήσει στη μάχη σου ενάντια στο σκοτάδι που εισβάλει.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left to \"\n\"him, and provides an anchor for all who are left in the town to what Tristram \"\n\"once was. His tavern, and the simple pleasures that can still be found there, \"\n\"provide a glimpse of a life that the people here remember. It is that memory \"\n\"that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Οι πήλινοι τοίχοι με μία αχυρένια σκεπή δεν δημιουργούν ένα σπίτι. Ο ξενοδόχος \"\n\"Όγκντεν εξυπηρετεί μεγαλύτερο σκοπό σε αυτή την πόλη από ό,τι πολλοί \"\n\"καταλαβαίνουν. Παρέχει καταφύγιο για την Γκίλιαν και την μητέρα της, διατηρεί \"\n\"ότι ζωή έχει απομείνει στον Φάρνχαμ και παρέχει μια άγκυρα για όλους όσοι \"\n\"έχουν μείνει στο χωριό σε αυτό που ήταν κάποτε η Τρίστραμ. Η ταβέρνα του, και \"\n\"οι απλές απολαύσεις που μπορούν να βρεθούν ακόμα εκεί, παρέχουν μια ματιά από \"\n\"μια ζωή που θυμούνται οι άνθρωποι εδώ. Είναι αυτή η μνήμη που συνεχίζει να \"\n\"τρέφει τις ελπίδες τους για την επιτυχία σου.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Ψσστ… εδώ πέρα...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Δεν έχουν όλοι στην Τρίστραμ μια χρησιμότητα - ή μια αγορά - για όλα όσα θα \"\n\"βρεις στον λαβύρινθο. Ούτε εγώ, όσο δύσκολο κι αν είναι να το πιστέψεις.\\n\"\n\" \\n\"\n\"Μερικές φορές, μόνο εσύ θα μπορείς να βρεις χρήση για κάποια πράγματα.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Μην εμπιστεύεσαι όλα όσα λέει ο μεθυσμένος. Πάρα πολλές μπίρες έχουν θολώσει \"\n\"την όρασή του και το μυαλό του.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up whatever \"\n\"you can bring them...\"\nmsgstr \"\"\n\"Σε περίπτωση που δεν το έχεις προσέξει, δεν αγοράζω τίποτα από την Τρίστραμ. \"\n\"Είμαι εισαγωγέας ποιοτικών προϊόντων. Αν θέλεις να πουλήσεις σκουπίδια, θα \"\n\"πρέπει να δεις τον Γκρίσγουαλντ, τον Πέπιν ή εκείνη τη μάγισσα, την Άντρια. \"\n\"Είμαι σίγουρος ότι θα αγοράσουν ό,τι μπορείς να τους φέρεις...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Υποθέτω ότι οφείλω τη ζωή μου στον σιδηρουργό - τι έχει απομείνει από αυτή. \"\n\"Σίγουρα, ο Γκρίσγουαλντ μου πρόσφερε μια μαθητεία στο σιδηρουργείο, και είναι \"\n\"αρκετά καλός τύπος, αλλά δεν θα πάρω ποτέ αρκετά χρήματα για να... καλά, ας \"\n\"πούμε απλώς ότι έχω συγκεκριμένα σχέδια που απαιτούν μεγάλη ποσότητα χρυσού.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Αν ήμουν μερικά χρόνια μεγαλύτερος, θα την έλουζα με ό,τι πλούτη μπορούσα να \"\n\"συγκεντρώσω, και επίτρεψέ μου να σε διαβεβαιώσω ότι μπορώ να πάρω στα χέρια \"\n\"μου μερικά πολύ ωραία πράγματα. Η Γκίλιαν είναι ένα όμορφο κορίτσι που πρέπει \"\n\"να φύγει από το Τρίστραμ μόλις είναι ασφαλές. Χμμ... ίσως την πάρω μαζί μου \"\n\"όταν πάω...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that woman \"\n\"across the river. He keeps telling me about how lucky I am to be alive, and \"\n\"how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Ο Κάιν ξέρει πάρα πολλά. Με τρομάζει πολύ - ακόμα περισσότερο από εκείνη τη \"\n\"γυναίκα απέναντι από το ποτάμι. Μου λέει συνέχεια για το πόσο τυχερός είμαι \"\n\"που είμαι ζωντανός και πώς η ιστορία μου προμηνύεται στο θρύλο. Νομίζω ότι δεν \"\n\"πάει καλά.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, and \"\n\"Lazarus led him into the very jaws of death. Oh, I know what it's like down \"\n\"there, so don't even start telling me about your plans to destroy the evil \"\n\"that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Ο Φάρνχαμ - τώρα μιλάμε για έναν άνθρωπο με σοβαρά προβλήματα, και ξέρω τα \"\n\"πάντα για το πόσο σοβαρά μπορεί να είναι τα προβλήματα. Εμπιστευόταν πάρα πολύ \"\n\"την ακεραιότητα ενός ανθρώπου και ο Λάζαρος τον οδήγησε στα ίδια τα σαγόνια \"\n\"του θανάτου. Ω, ξέρω πώς είναι εκεί κάτω, οπότε μην αρχίσεις καν να μου μιλάς \"\n\"για τα σχέδιά σου να καταστρέψεις το κακό που κατοικεί σε αυτόν τον Λαβύρινθο. \"\n\"Απλά πρόσεχε τα πόδια σου...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Εφόσον δεν χρειάζεται να ξανακολλήσεις τίποτα, ο γερο-Πέπιν είναι το καλύτερο \"\n\"που θα σου τύχει.\\n\"\n\" \\n\"\n\"Αν είχα πάρει μερικά από αυτά τα φίλτρα που φτιάχνει, μπορεί να είχα ακόμα το \"\n\"πόδι μου...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about the \"\n\"past, but that witch can see into your past. She always has some way to get \"\n\"whatever she needs, too. Adria gets her hands on more merchandise than I've \"\n\"seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Η Άντρια με ενοχλεί πραγματικά. Σίγουρα, ο Κάιν είναι ανατριχιαστικός σε ό,τι \"\n\"μπορεί να σου πει για το παρελθόν, αλλά αυτή η μάγισσα μπορεί να δει το \"\n\"παρελθόν σου. Έχει πάντα τρόπο να πάρει ό,τι χρειάζεται. Η Άντρια παίρνει στα \"\n\"χέρια της περισσότερα εμπορεύματα από όσα έχω δει να περνούν από τις πύλες του \"\n\"Παζαριού του Βασιλιά κατά τη διάρκεια του Μεγάλου Πανηγυριού.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that stupid \"\n\"tavern. I guess at the least he gives Gillian a place to work, and his wife \"\n\"Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ο Όγκντεν είναι ανόητος που μένει εδώ. Θα μπορούσα να τον βγάλω από την πόλη \"\n\"σε πολύ λογική τιμή, αλλά επιμένει να προσπαθεί να τα βγάλει πέρα ​​με αυτή την \"\n\"ηλίθια ταβέρνα. Υποθέτω ότι τουλάχιστον προσφέρει στην Γκίλιαν ένα μέρος να \"\n\"δουλέψει και η σύζυγός του η Γκάρντα φτιάχνει μια υπέροχη κρεατόπιτα...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks the \"\n\"Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Πέρα από τον Θάλαμο των Ηρώων βρίσκεται ο Θάλαμος των Οστών. Ο αιώνιος θάνατος \"\n\"περιμένει όποιον θα ήθελε να κλέψει τους θησαυρούς που είναι ασφαλισμένοι σε \"\n\"αυτό το δωμάτιο. Έτσι λέει ο Άρχοντας του Τρόμου, και έτσι είναι γραμμένο.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor \"\n\"awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...και έτσι, κλειδωμένη πέρα ​​από την Πύλη του Αίματος και πέρα ​​από την Αίθουσα \"\n\"της Φωτιάς, η Τιμή περιμένει τον Ήρωα του Φωτός να ξυπνήσει...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Βλέπω εκεί, που δεν βλέπουν μάτια...\\n\"\n\"Γαλακτώδης όραση αλλά σαπίζουν μάτια,\\n\"\n\"Όταν γυρίσεις, θα έχουν φύγει...\\n\"\n\"Ψιθυρίζοντας κρυφό τραγούδι, έχουν ξεφύγει,\\n\"\n\"Τότε βλέπεις αυτό, που αδύνατον είναι...\\n\"\n\"Σκιές κινούνται, όταν φως πρέπει να είναι,\\n\"\n\"Έξω από το σκοτάδι, και πέρα της γνώσης των μυαλών,\\n\"\n\"Εξόριστοι κάτω, μέσα στην Αίθουσες των Τυφλών.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Τα οπλοστάσια της Κόλασης είναι το σπίτι του Πολέμαρχου του Αίματος. Στο \"\n\"πέρασμά του κείτονται τα ακρωτηριασμένα σώματα χιλιάδων. Άγγελοι και άνθρωποι \"\n\"έχουν σφαγιαστεί για να εκπληρώσουν τις ατελείωτες θυσίες του, στους \"\n\"Σκοτεινούς, που ουρλιάζουν για ένα πράγμα - αίμα.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond the \"\n\"fields that we know - between the utopian kingdoms of the High Heavens and the \"\n\"chaotic pits of the Burning Hells. This war is known as the Great Conflict, \"\n\"and it has raged and burned longer than any of the stars in the sky. Neither \"\n\"side ever gains sway for long as the forces of Light and Darkness constantly \"\n\"vie for control over all creation.\"\nmsgstr \"\"\n\"Προσέξτε και δώστε μαρτυρία για τις αλήθειες που γράφονται εδώ, γιατί είναι η \"\n\"τελευταία κληρονομιά των Χοράντριμ. Υπάρχει ένας πόλεμος που μαίνεται ακόμη \"\n\"και τώρα, πέρα ​από τον κόσμο που γνωρίζουμε - μεταξύ των ουτοπικών βασιλείων \"\n\"των Υψηλών Ουρανών και των χαοτικών λάκκων των Φλεγόμενων Κολάσεων. Αυτός ο \"\n\"πόλεμος είναι γνωστός ως η Μεγάλη Σύγκρουση, και κρατάει και καίει, \"\n\"περισσότερο από οποιοδήποτε από τα αστέρια στον ουρανό. Καμία πλευρά δεν \"\n\"κερδίζει ποτέ επιρροή για μεγάλο χρονικό διάστημα, καθώς οι δυνάμεις του Φωτός \"\n\"και του Σκότους αγωνίζονται συνεχώς για τον έλεγχο όλης της δημιουργίας.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in secret, \"\n\"away from the prying eyes of mortals. Some daring, powerful mortals have even \"\n\"allied themselves with either side, and helped to dictate the course of the \"\n\"Sin War.\"\nmsgstr \"\"\n\"Προσέξτε και δώστε μαρτυρία για τις αλήθειες που γράφονται εδώ, γιατί είναι η \"\n\"τελευταία κληρονομιά των Χοράντριμ. Όταν η Αιώνια Σύγκρουση μεταξύ των Υψηλών \"\n\"Ουρανών και των Φλεγόμενων Κολάσεων πέφτει στο θνητό έδαφος, ονομάζεται ως \"\n\"Πόλεμος της Αμαρτίας. Άγγελοι και Δαίμονες περπατούν ανάμεσα στην ανθρωπότητα \"\n\"μεταμφιεσμένοι, πολεμώντας κρυφά, μακριά από τα αδιάκριτα βλέμματα των θνητών. \"\n\"Μερικοί τολμηροί, ισχυροί θνητοί συμμάχησαν και με τις δύο πλευρές και \"\n\"βοήθησαν να υπαγορευτεί η πορεία του Πολέμου της Αμαρτίας.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come to \"\n\"our world. The Three Brothers ravaged the lands of the east for decades, while \"\n\"humanity was left trembling in their wake. Our Order - the Horadrim - was \"\n\"founded by a group of secretive magi to hunt down and capture the Three Evils \"\n\"once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the Horadrim \"\n\"in pursuit. The Third Evil - known as Diablo, the Lord of Terror - was \"\n\"eventually captured, his essence set in a Soulstone and buried within this \"\n\"Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Προσέξτε και δώστε μαρτυρία για τις αλήθειες που γράφονται εδώ, γιατί είναι η \"\n\"τελευταία κληρονομιά των Χοράντριμ. Πριν από σχεδόν τριακόσια χρόνια, έγινε \"\n\"γνωστό ότι τα Τρία Πρωταρχικά Κακά των Φλεγόμενων Κολάσεων είχαν έρθει \"\n\"μυστηριωδώς στον κόσμο μας. Οι Τρεις Αδερφοί ρήμαξαν τα εδάφη της ανατολής για \"\n\"δεκαετίες, ενώ η ανθρωπότητα έμενε να τρέμει στο πέρασμά τους. Το Τάγμα μας - \"\n\"οι Χοράντριμ - ιδρύθηκε από μια ομάδα μυστικών μάγων για να κυνηγήσουν και να \"\n\"συλλάβουν τα Τρία Κακά μια για πάντα.\\n\"\n\"Οι αρχικοί Χοράντριμ συνέλαβαν δύο από τα Τρία μέσα σε ισχυρά τεχνουργήματα \"\n\"γνωστά ως Λίθους των Ψυχών και τα έθαψαν βαθιά κάτω από την έρημη ανατολική \"\n\"έρημο. Το τρίτο Κακό διέφυγε τη σύλληψη και διέφυγε προς τα δυτικά με πολλούς \"\n\"από τους Χοράντριμ να το καταδιώκουν. Το Τρίτο Κακό - γνωστό ως ο Ντιάμπλο, ο \"\n\"Άρχοντας του Τρόμου - τελικά αιχμαλωτίστηκε, η ουσία του τοποθετήθηκε σε ένα \"\n\"Λίθο της Ψυχής και θάφτηκε σε αυτόν εδώ τον Λαβύρινθο.\\n\"\n\"\\n\"\n\"Σας προειδοποιώ ότι ο Λίθος της Ψυχής δεν πρέπει να ανακαλυφθεί από εκείνους \"\n\"που δεν είναι της πίστης μας. Αν ο Ντιάμπλο απελευθερωνόταν, θα αναζητούσε ένα \"\n\"σώμα που να ελέγχεται εύκολα καθώς θα ήταν πολύ αδύναμος - ίσως αυτό ενός \"\n\"γέρου ή ενός παιδιού.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils and \"\n\"banished their spirit forms to the mortal realm. The demons Belial (the Lord \"\n\"of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of Hell \"\n\"during the absence of the Three Brothers. All of Hell polarized between the \"\n\"factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Έτσι έγινε γνωστό ότι μια μεγάλη επανάσταση έλαβε χώρα μέσα στις Φλεγόμενες \"\n\"Κολάσεις, γνωστή ως Η Σκοτεινή Εξορία. Τα Μικρότερα Κακά ανέτρεψαν τα Τρία \"\n\"Πρωτεύοντα Κακά και εξόρισαν τις πνευματικές τους μορφές στον θνητό κόσμο. Οι \"\n\"δαίμονες Μπελίαλ (ο Άρχοντας του Ψέματος) και ο Άζμονταν (ο Άρχοντας της \"\n\"Αμαρτίας) πολέμησαν για να διεκδικήσουν την κυριαρχία της Κόλασης κατά την \"\n\"απουσία των Τριών Αδελφών. Όλη η Κόλαση πολώθηκε μεταξύ των φατριών του \"\n\"Μπελίαλ και του Άζμονταν ενώ οι δυνάμεις των Υψηλών Ουρανών μάχονταν και \"\n\"χτυπούσαν αδιάκοπα τις ίδιες τις Πύλες της Κόλασης.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept at \"\n\"hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Πολλοί δαίμονες ταξίδεψαν στο βασίλειο των θνητών αναζητώντας τους Τρεις \"\n\"Αδερφούς. Αυτούς τους δαίμονες ακολούθησαν στην διάσταση των θνητών Άγγελοι, \"\n\"που τους κυνήγησαν σε όλες τις απέραντες πόλεις της Ανατολής. Οι Άγγελοι \"\n\"συμμάχησαν με ένα μυστικό Τάγμα θνητών μάγων που ονομάζονταν Χοράντριμ, οι \"\n\"οποίοι γρήγορα έγιναν έμπειροι στο κυνήγι δαιμόνων. Έκαναν επίσης πολλούς \"\n\"σκοτεινούς εχθρούς στους κάτω κόσμους.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they were \"\n\"hunted down by the cursed Order of the mortal Horadrim. The Horadrim used \"\n\"artifacts called Soulstones to contain the essence of Mephisto, the Lord of \"\n\"Hatred and his brother Baal, the Lord of Destruction. The youngest brother - \"\n\"Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and buried \"\n\"him under an ancient, forgotten Cathedral. There, the Lord of Terror sleeps \"\n\"and awaits the time of his rebirth. Know ye that he will seek a body of youth \"\n\"and power to possess - one that is innocent and easily controlled. He will \"\n\"then arise to free his Brothers and once more fan the flames of the Sin War...\"\nmsgstr \"\"\n\"Έτσι συνέβη ότι τα Τρία Πρωτεύοντα Κακά εκδιώχθηκαν με τη μορφή πνεύματων στο \"\n\"βασίλειο των θνητών και αφού έσπειραν το χάος σε όλη την Ανατολή για \"\n\"δεκαετίες, κυνηγήθηκαν από το καταραμένο Τάγμα των θνητών Χοράντριμ. Οι \"\n\"Χοράντριμ χρησιμοποίησαν τεχνουργήματα που ονομάστηκαν Λίθοι των Ψυχών για να \"\n\"αποθηκεύσουν την ουσία του Μεφίστο, του Άρχοντα του Μίσους και του αδελφού του \"\n\"Βαάλ, του Άρχοντα της Καταστροφής. Ο μικρότερος αδερφός - ο Ντιάμπλο, ο \"\n\"Άρχοντας του Τρόμου - διέφυγε στη δύση.\\n\"\n\"\\n\"\n\"Τελικά οι Χοράντριμ φυλάκισαν τον Ντιάμπλο μέσα σε μια Λίθο της Ψυχής επίσης, \"\n\"και τον έθαψαν κάτω από έναν αρχαίο, ξεχασμένο Καθεδρικό ναό. Εκεί κοιμάται ο \"\n\"Άρχοντας του Τρόμου και περιμένει την ώρα της αναγέννησής του. Να ξέρετε ότι \"\n\"θα αναζητήσει ένα σώμα νεότητας και δύναμης για να το καταβάλει - ένα που \"\n\"είναι αθώο και εύκολα ελεγχόμενο. Στη συνέχεια θα σηκωθεί για να ελευθερώσει \"\n\"τα αδέρφια του και να αναζωπυρώσει ξανά τις φλόγες του Πολέμου της Αμαρτίας...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When he \"\n\"awakened from his long slumber, my Lord and Master spoke to me of secrets that \"\n\"few mortals know. He told me the kingdoms of the High Heavens and the pits of \"\n\"the Burning Hells engage in an eternal war. He revealed the powers that have \"\n\"brought this discord to the realms of man. My lord has named the battle for \"\n\"this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Όλοι οι έπαινοι για τον Ντιάμπλο - Άρχοντα του Τρόμου και επιζώντα της \"\n\"Σκοτεινής Εξορίας. Όταν ξύπνησε από τον μακρύ ύπνο του, ο Κύριος και ο \"\n\"Άρχοντας μου, μου μίλησε για μυστικά που λίγοι θνητοί γνωρίζουν. Μου είπε ότι \"\n\"τα βασίλεια των Υψηλών Ουρανών και οι λάκκοι των Φλεγόμενων Κολάσεων, \"\n\"εμπλέκονται σε έναν αιώνιο πόλεμο. Μου αποκάλυψε τις δυνάμεις που έφεραν αυτή \"\n\"τη διχόνοια στα βασίλεια του ανθρώπου. Ο Κύριός μου ονόμασε τη μάχη για τον \"\n\"κόσμο μας, και για όλους όσους υπάρχουν εδώ, ως τον Πόλεμο της Αμαρτίας.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished to \"\n\"this world long ago. My Lord wishes to bide his time and harness his awesome \"\n\"power so that he may free his captive brothers from their tombs beneath the \"\n\"sands of the east. Once my Lord releases his Brothers, the Sin War will once \"\n\"again know the fury of the Three.\"\nmsgstr \"\"\n\"Δόξα και Επιδοκιμασία στον Ντιάμπλο - Άρχοντα του Τρόμου και Ηγέτη των Τριών. \"\n\"Ο Κύριός μου, μου μίλησε για τους δύο Αδερφούς του, τον Μεφίστο και τον Βαάλ, \"\n\"που εξορίστηκαν σε αυτόν τον κόσμο πριν από πολύ καιρό. Ο Κύριός μου θέλει να \"\n\"αφιερώσει το χρόνο του και να αξιοποιήσει τη φοβερή δύναμή του, ώστε να \"\n\"μπορέσει να ελευθερώσει τους αιχμάλωτους αδελφούς του από τους τάφους τους \"\n\"κάτω από την έρημο της ανατολής. Μόλις ο Κύριός μου απελευθερώσει τους \"\n\"Αδερφούς του, ο Πόλεμος της Αμαρτίας θα γνωρίσει ξανά την οργή των Τριών.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too weak \"\n\"from his imprisonment. My Lord required a simple and innocent anchor to this \"\n\"world, and so found the boy Albrecht to be perfect for the task. While the \"\n\"good King Leoric was left maddened by Diablo's unsuccessful possession, I \"\n\"kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as the \"\n\"Lord of this world.\"\nmsgstr \"\"\n\"Χαιρετισμός και Θυσία για τον Ντιάμπλο - Άρχοντα του Τρόμου και Καταστροφέα \"\n\"των Ψυχών. Όταν ξύπνησα τον Δάσκαλό μου από τον ύπνο του, προσπάθησε να \"\n\"αποκτήσει τη μορφή ενός θνητού. Ο Ντιάμπλο προσπάθησε να διεκδικήσει το σώμα \"\n\"του βασιλιά Λεόρικ, αλλά ο Άρχοντας μου ήταν πολύ αδύναμος από τη φυλάκισή \"\n\"του. Ο Κύριός μου ζήτησε μια απλή και αθώα άγκυρα σε αυτόν τον κόσμο, και έτσι \"\n\"βρήκε το αγόρι τον Άλμπρεχτ τέλειο για το έργο αυτό. Ενώ ο καλός βασιλιάς \"\n\"Λεόρικ έμεινε τρελός από την ανεπιτυχή προσπάθεια κατοχής του Ντιάμπλο, \"\n\"απήγαγα τον γιο του τον Άλμπρεχτ και τον έφερα ενώπιον του Άρχοντα μου. Τώρα \"\n\"περιμένω την προσκλήση του Ντιάμπλο και προσεύχομαι να ανταμειφθώ όταν \"\n\"επιτέλους αναδειχθεί ως ο Κύριος αυτού του κόσμου.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become slaves \"\n\"- or worse. The church at the edge of town has been desecrated and is being \"\n\"used for dark rituals. The screams that echo in the night are inhuman, but \"\n\"some of our townsfolk may yet survive. Follow the path that lies between my \"\n\"tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Δόξα τω Θεώ που επέστρεψες!\\n\"\n\"Πολλά έχουν αλλάξει από τότε που έμενες εδώ, φίλε/η μου. Όλα ήταν ήρεμα μέχρι \"\n\"που ήρθαν οι σκοτεινοί καβαλάρηδες και κατέστρεψαν το χωριό μας. Πολλοί \"\n\"σκοτώθηκαν εκεί που στέκονταν και όσοι άρπαξαν τα όπλα σφαγιάσθηκαν ή τους \"\n\"πήραν μαζί τους για σκλάβους -ή χειρότερα. Η εκκλησία στην άκρη της πόλης έχει \"\n\"βεβηλωθεί και χρησιμοποιείται για σκοτεινές τελετουργίες. Οι κραυγές που \"\n\"αντηχούν τη νύχτα είναι απάνθρωπες, αλλά κάποιοι από τους κατοίκους μας μπορεί \"\n\"να έχουν επιβιώσει ακόμα. Ακολούθα το μονοπάτι που βρίσκεται ανάμεσα στην \"\n\"ταβέρνα μου και το σιδηρουργείο για να βρεις την εκκλησία και να σώσεις όποιον \"\n\"μπορείς.\\n\"\n\"\\n\"\n\"Ίσως Θα σου πω περισσότερα, αν μιλήσουμε ξανά αργότερα. Καλή τύχη.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding a \"\n\"treasure that is hidden less so.  I will leave you with this.  Do not let the \"\n\"sands of time confuse your search.\"\nmsgstr \"\"\n\"Διατήρησε την αποστολή σου. Το να βρεις έναν θησαυρό που έχει χαθεί δεν είναι \"\n\"εύκολο. Το να βρεις έναν θησαυρό που είναι κρυμμένος είναι ακόμα πιο δύσκολο. \"\n\"Θα σε αφήσω με αυτό. Μην αφήσετε τις άμμους του χρόνου να μπερδέψουν την \"\n\"αναζήτησή σου.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in Tristram.  \"\n\"Let me see that!!  Ah, Look these drawings are inaccurate.  They don't match \"\n\"our town at all.  I'd keep my mind on what lies below the cathedral and not \"\n\"what lies below our topsoil.\"\nmsgstr \"\"\n\"Ενα τι?! Αυτό είναι ανοησία. Δεν υπάρχει θησαυρός θαμμένος εδώ στην Τρίστραμ. \"\n\"Άσε με να το δω αυτό!! Α, κοίτα αυτά τα σχέδια είναι ανακριβή. Δεν ταιριάζουν \"\n\"καθόλου με την πόλη μας. Έχε στο μυαλό σου σε αυτά που βρίσκονται κάτω από τον \"\n\"καθεδρικό ναό και όχι σε αυτά που βρίσκονται άμεσα κάτω από τα χωράφια μας.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have many \"\n\"sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Πραγματικά δεν έχω χρόνο να συζητήσω κάποιο χάρτη που ψάχνεις. Έχω πολλούς \"\n\"άρρωστους που χρειάζονται τη βοήθειά μου και τη δική σας επίσης.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  His \"\n\"honor stripped and his visage altered.  He is trapped in immortal torment.  \"\n\"Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"O άλλοτε περήφανος Ίσγουαλ είναι παγιδευμένος βαθιά κάτω από την επιφάνεια \"\n\"αυτού του κόσμου. Απογυμνωμένος από την τιμή του, και με αλλαγμένη όψη. Είναι \"\n\"παγιδευμένος σε αθάνατο μαρτύριο. Είναι εξαναγκασμένος να κρύψει τον τρόπο που \"\n\"θα μπορούσε να τον απελευθερώσει.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh at \"\n\"you later when you were running around the town with your nose in the dirt.  \"\n\"I'd ignore it.\"\nmsgstr \"\"\n\"Βάζω στοίχημα ότι ο Ουίρτ σε είδε να έρχεσαι και σου κάνει φάρσα μόνο και μόνο \"\n\"για να μπορεί να γελάσει μαζί σου αργότερα, όταν θα τρέχεις στην πόλη με τη \"\n\"μύτη σου στο χώμα ψάχνοντας. Θα το αγνοούσα.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far and \"\n\"wide.  Much has changed since then.  But hidden caves and buried treasure are \"\n\"common fantasies of any child.  Wirt seldom indulges in youthful games.  So it \"\n\"may just be his imagination.\"\nmsgstr \"\"\n\"Υπήρχε μια εποχή που αυτή η πόλη ήταν μια συχνή στάση για ταξιδιώτες από πολύ \"\n\"μακριά. Πολλά έχουν αλλάξει από τότε. Όμως οι κρυμμένες σπηλιές και οι \"\n\"θαμμένοι θησαυροί είναι κοινές φαντασιώσεις κάθε παιδιού. Ο Ουίρτ σπάνια \"\n\"επιδίδεται σε νεανικά παιχνίδια. Οπότε μπορεί να είναι απλώς η φαντασία του.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Άκου εδώ. Έλα κοντά. Δεν ξέρω αν ξέρεις αυτά που ξέρω, αλλά έχεις πραγματικά \"\n\"κάτι εδώ. Αυτός είναι ένας χάρτης.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear one \"\n\"of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Η γιαγιά μου, μου λέει συχνά ιστορίες για τις παράξενες δυνάμεις που κατοικούν \"\n\"στο νεκροταφείο έξω από την εκκλησία. Και μπορεί κάλλιστα να σε ενδιαφέρει να \"\n\"ακούσεις μια από αυτές. Είπε ότι αν άφηνες την κατάλληλη θυσία στο \"\n\"νεκροταφείο, και μπεις στον καθεδρικό ναό για να προσευχηθείς για τους νεκρούς \"\n\"και μετά επιστρέψεις, η θυσία θα αλλοιωνόταν με κάποιο περίεργο τρόπο. Δεν \"\n\"ξέρω αν αυτό είναι μόνο λόγια μιας ηλικιωμένης άρρωστης γυναίκας, αλλά όλα \"\n\"φαίνονται πιθανά αυτές τις μέρες.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you need \"\n\"some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Χμμμ. Ένας τεράστιος και μυστηριώδης θησαυρός μου λες. Μμμμ. Ίσως θα μπορούσα \"\n\"να με ενδιαφέρει να πάρω μερικά πράγματα από σένα. Ή ακόμα καλύτερα, δεν \"\n\"χρειάζεσαι κάποιες σπάνιες και ακριβές προμήθειες για να ξεπεράσεις αυτή τη \"\n\"δοκιμασία;\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Λοιπόν, είσαι ο ήρωας/ίδα για τον οποίο/α μιλούν όλοι. Ίσως θα μπορούσες να \"\n\"βοηθήσεις έναν φτωχό, απλό αγρότη να λύσει ένα τρομερό πρόβλημα; Στην άκρη του \"\n\"οπωρώνα μου, ακριβώς νότια από εδώ, υπάρχει ένα φρικτό πράγμα που φουσκώνει \"\n\"από το έδαφος! Δεν μπορώ να φτάσω στις καλλιέργειές μου ή στα σανοδέματα μου, \"\n\"και οι φτωχές αγελάδες μου θα πεινάσουν. Η μάγισσα μου έδωσε αυτό και μου είπε \"\n\"ότι θα έσκαγε, καταστρέφοντας αυτό το πράγμα από το χωράφι μου. Αν μπορούσες \"\n\"να το βγάλεις, θα σου ήμουν για πάντα ευγνώμων. Θα το έκανα μόνος μου, αλλά \"\n\"κάποιος πρέπει να μείνει εδώ με τις αγελάδες...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Ήξερα ότι δεν θα μπορούσε να είναι τόσο απλό όσο το έκανε να ακούγεται εκείνη \"\n\"η μάγισσα. Είναι ένας θλιβερός κόσμος όταν δεν μπορείς να εμπιστευτείς ούτε \"\n\"τους γείτονές σου.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Έφυγε; Το έστειλες πίσω στις σκοτεινές εσοχές του Άδη που το γέννησαν; Εσύ τι? \"\n\"Α, μη μου πεις ότι το έχασες! Αυτά τα πράγματα δεν είναι φτηνά, ξέρεις. Πρέπει \"\n\"να τον βρεις και μετά να τον διώξεις αυτόν τον τρόμο από την πόλη μας.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What with \"\n\"all these things comin' out of the ground, monsters taking over the church, \"\n\"and so forth, these are trying times. I am but a poor farmer, but here -- take \"\n\"this with my great thanks.\"\nmsgstr \"\"\n\"Άκουσα την έκρηξη από εδώ! Ευχαριστώ πολύ, ευγενικέ ξένε. Με όλα αυτά τα \"\n\"πράγματα που βγαίνουν από τη γη, τα τέρατα που καταλαμβάνουν την εκκλησία, και \"\n\"ούτω καθεξής, είναι δύσκολοι καιροί. Δεν είμαι παρά ένας φτωχός αγρότης, αλλά \"\n\"εδώ -- πάρε αυτό με τις ευχαριστίες μου.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a poor \"\n\"farmer?\"\nmsgstr \"\"\n\"Ω, τέτοιο μπελά έχω...ίσως...Όχι, δεν θα μπορούσα να σου το επιβάλλω, τι με \"\n\"όλα τα άλλα δεινά. Ίσως αφού καθαρίσετε την εκκλησία από κάποια από αυτά τα \"\n\"πλάσματα, θα μπορούσες να επιστρέψεις... και να αφιερώσεις λίγο χρόνο για να \"\n\"βοηθήσεις έναν φτωχό αγρότη;\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Ουααα! (σνίφ) Ουααα! (σνίφ)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away but \"\n\"Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Έχασα τον Θέο! Έχασα τον καλύτερό μου φίλο! Παίζαμε δίπλα στο ποτάμι, και ο \"\n\"Θέο είπε ότι ήθελε να πάει να δει το μεγάλο πράσινο πράγμα. Είπα ότι δεν \"\n\"πρέπει, αλλά κρυφο-πήγαμε από εκεί, και ξαφνικά βγήκε αυτό το ΕΝΤΟΜΟ! Τρέξαμε \"\n\"μακριά αλλά ο Θέο έπεσε κάτω και το ζωύφιο τον ΑΡΠΑΞΕ και τον πήρε μακριά!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He can't \"\n\"take care of himself!  Please!\"\nmsgstr \"\"\n\"Τον βρήκες; Πρέπει να βρεις τον Θεόδωρο, σε παρακαλώ! Είναι απλά μικρός. Δεν \"\n\"μπορεί να φροντίσει τον εαυτό του! Σε παρακαλώ!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Τον βρήκες! Τον βρήκες! Ευχαριστώ! Ω Θέο, σε τρόμαξαν αυτά τα άσχημα έντομα; \"\n\"Έιι! Ούφ! Κάτι έχει κολλήσει στη γούνα σου! μπλιάχ! Έλα, Θέο, πάμε σπίτι! \"\n\"Ευχαριστώ και πάλι, ήρωα άνθρωπε!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Παραμείναμε σε λήθαργο και ήρθε η ώρα να ξυπνήσουμε. Μετά τον μακρύ ύπνο μας, \"\n\"έχουμε μεγάλη πείνα. Σύντομα, τώρα, θα φάμε...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Διασκέδασες, μικρό θηλαστικό; Πόσο αξιολύπητο. Ο μικρός σας κόσμος δεν θα \"\n\"είναι πρόκληση για μας.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that men \"\n\"call home.  Our tendrils shall envelop this world, and we will feast on the \"\n\"flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Αυτά τα εδάφη θα μολυνθούν, και ο γόνος μας θα κατακλύσει τα χωράφια που οι \"\n\"άνθρωποι αποκαλούν σπίτι. Τα πλοκάμια μας θα τυλίξουν αυτόν τον κόσμο και θα \"\n\"γλεντήσουμε με τη σάρκα των κατοίκων του. Ο άνθρωπος θα γίνει δουλοκτησία και \"\n\"διατροφή μας.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Αχ μπορώ να σε μυρίσω...είσαι κοντά! Κοντά! Σσσς...το άρωμα του αίματος και \"\n\"του φόβου...πόσο δελεαστικό...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great Cathedral \"\n\"be raised.  The cornerstone of this holy place was to be carved from the \"\n\"translucent stone Antyrael, named for the Angel who shared his power with the \"\n\"Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Και στο έτος του Χρυσού Φωτός, ορίστηκε με διάγγελμα να υψωθεί ένας μεγάλος \"\n\"Καθεδρικός Ναός. Ο ακρογωνιαίος λίθος αυτού του ιερού τόπου επρόκειτο να \"\n\"λαξευτεί από την ημιδιαφανή πέτρα Αντίραελ, που πήρε το όνομά του από τον \"\n\"Άγγελο που μοιραζόταν τη δύναμή του με τους Χοράντριμ.\\n\"\n\" \\n\"\n\"Στο Έτος του Ερχομού των Σκιών, το έδαφος σείστηκε και ο Καθεδρικός Ναός \"\n\"γκρεμίστηκε και έπεσε. Καθώς άρχισε η οικοδόμηση των κατακομβών και των \"\n\"κάστρων και ο άνθρωπος στάθηκε ενάντια στις καταστροφές του Πολέμου της \"\n\"Αμαρτίας, τα ερείπια είχαν καθαριστεί για τις πέτρες τους. Και έτσι ήταν που ο \"\n\"ακρογωνιαίος λίθος εξαφανίστηκε από τα μάτια του ανθρώπου.\\n\"\n\" \\n\"\n\"Η πέτρα ήταν αυτού του κόσμου -- και όλων των κόσμων -- καθώς το Φως είναι \"\n\"τόσο μέσα σε όλα τα πράγματα όσο και πέρα ​​από όλα τα πράγματα. Το φως και η \"\n\"ενότητα είναι τα προϊόντα αυτού του ιερού θεμελίου, μιας ενότητας σκοπού και \"\n\"μιας ενότητας της κατοχής.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Μοο.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Είπα, Μοο.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Κοίτα είμαι απλά μια αγελάδα, εντάξει;\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around like \"\n\"this; but, I was sitting at home minding my own business and all of a sudden \"\n\"these bugs & vines & bulbs & stuff started coming out of the floor... it was \"\n\"horrible!  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Could you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't want \"\n\"anyone seeing me like this.  Here, take this, you might need it... to kill \"\n\"those things that have overgrown everything.  You can't miss my house, it's \"\n\"just south of the fork in the river... you know... the one with the overgrown \"\n\"vegetable garden.\"\nmsgstr \"\"\n\"Εντάξει, εντάξει. Δεν είμαι πραγματικά αγελάδα. Συνήθως δεν κυκλοφορώ έτσι. \"\n\"αλλά, απλά καθόμουν στο σπίτι και κοιτούσα τη δουλειά μου όταν ξαφνικά αυτά τα \"\n\"ζωύφια, οι κληματσίδες, οι βολβοί και άλλα πράγματα άρχισαν να βγαίνουν από το \"\n\"έδαφος... ήταν φρικτό! Αν είχα μόνο κάτι κανονικό να φορέσω, δεν θα ήταν τόσο \"\n\"κακό. Έι! Θα μπορούσες να πας στο σπίτι μου και να μου φέρεις την στολή μου; \"\n\"Την καφέ, όχι την γκρι, είναι για βραδινό. Θα το έκανα μόνος μου, αλλά δεν \"\n\"θέλω να με βλέπει κανείς έτσι. Ορίστε, πάρε αυτό, μπορεί να το χρειαστείς... \"\n\"για να σκοτώσεις εκείνα τα πράγματα που έχουν κατακλύσει τα πάντα. Είναι \"\n\"αδύνατον να σου ξεφύγει το σπίτι μου, είναι νότια της διχάλας στο ποτάμι... \"\n\"ξέρεις... εκείνο με τον κατάφυτο λαχανόκηπο.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Για τι χάνεις χρόνο; Πήγαινε να πάρεις την στολή μου! Και βιάσου! Αυτή η \"\n\"αγελάδα Χόλστειν εκεί πέρα ​​μου κλείνει το μάτι!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Έι, έχεις την στολή μου εκεί; Γρήγορα, δώστε την μου! Αυτά τα αυτιά μου \"\n\"φέρνουν μια απίστευτη φαγούρα!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need the \"\n\"BROWN suit.\"\nmsgstr \"\"\n\"Οχι όχι όχι όχι! Αυτό είναι η ΓΚΡΙ στολή μου! Είναι για βραδινό ντύσιμο! \"\n\"Επίσημες περιστάσεις! Δεν μπορώ να το φορέσω ΑΥΤΟ. Τι είσαι, τρελαμένος; \"\n\"Χρειάζομαι τη ΚΑΦΕ στολή.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as a \"\n\"gift; and, you know... a little fashion tip... you could use a little... you \"\n\"could use a new... yknowwhatImean?  The whole adventurer motif is just so... \"\n\"retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Αχ, τώρα είμαι ΠΟΛΥ καλύτερο. Ούφ! Επιτέλους, λίγη αξιοπρέπεια! Είναι τα \"\n\"κέρατα μου σε ευθεία; Καλός. Κοίτα, ευχαριστώ πολύ που με βοήθησες. Εδώ, πάρτε \"\n\"αυτό ως δώρο. και, για να ξέρεις... μια μικρή συμβουλή μόδας... θα μπορούσατε \"\n\"να χρησιμοποιήσετε λίγο... θα μπορούσατε να χρησιμοποιήσετε μια νέα... \"\n\"ξερειςτιλέωτώρα; Το όλο μοτίβο του ήρωα είναι απλά τόσο... ρετρό. Απλά μια \"\n\"συμβουλή, ε; Τσάοοο.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Κοίτα. Είμαι αγελάδα. Κι εσύ, είσαι δόλωμα τέρας. Αποκτήστε λίγη εμπειρία! Θα \"\n\"μιλήσουμε...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Πρέπει να είναι πραγματικά ένα τρομερό καθήκον που έχω θέσει πάνω σου. Αν \"\n\"υπήρχε κάποιος τρόπος με τον οποίο θα μπορούσα... θα βοηθούσε μια καράφα με \"\n\"ωραίο, φρέσκο ​​γάλα;\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Ω, θα μπορούσα να είχα την βοήθειά σου, αλλά ίσως αφού πρώτα σώσεις τις \"\n\"κατακόμβες από τη βεβήλωση αυτών των θηρίων.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Χρειάζομαι κάποιον να κάνει κάτι, αλλά δεν μπορούσα να επιβληθώ σε έναν \"\n\"εντελώς ξένο. Ίσως μετά από λίγο καιρό που είσαι εδώ, να νιώσω πιο άνετα και \"\n\"να ζητήσω μια χάρη.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Βλέπω σε σένα τη δυνατότητα για μεγαλεία. Ίσως κάποια στιγμή ενώ εκπληρώνεις \"\n\"το πεπρωμένο σου, θα μπορούσες να περάσεις και να κάνεις μια μικρή χάρη για \"\n\"μένα;\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to destroy \"\n\"the menace in the church!\"\nmsgstr \"\"\n\"Νομίζω ότι θα μπορούσες πιθανώς να με βοηθήσεις, αλλά ίσως αφού γίνεις λίγο \"\n\"πιο δυνατός/ή. Δεν θα ήθελα να τραυματίσω τη μοναδική ευκαιρία του χωριού να \"\n\"καταστρέψει την απειλή στην εκκλησία!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Εγώ, είμαι μια αυτοδημιούργητη αγελάδα. Κάνε τον εαυτό σου κάτι στον κόσμο, \"\n\"και μετά θα μιλήσουμε.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you have \"\n\"some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Δεν χρειάζεται να εξηγώ τον εαυτό μου σε κάθε τουρίστα που περνάει! Δεν έχεις \"\n\"μερικά τέρατα να σκοτώσεις; Ίσως τα πούμε αργότερα. Αν ζεις...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not it.  \"\n\"I can't trust you, you're going to get eaten by monsters any day now... I need \"\n\"someone who's an experienced hero.\"\nmsgstr \"\"\n\"Σταμάτα να με ενοχλείς. Ψάχνω για κάποιον πραγματικά ηρωικό. Και δεν είσαι \"\n\"εσύ. Δεν μπορώ να σε εμπιστευτώ, θα σε φάνε τα τέρατα όπου να ναι τώρα... \"\n\"Χρειάζομαι κάποιον που να έχει εμπειρία σαν ήρωας/ίδα.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened to \"\n\"be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, not \"\n\"the gray one, that's for evening wear.  I'd do it myself, but I don't want \"\n\"anyone seeing me like this.  Here, take this, you might need it... to kill \"\n\"those things that have overgrown everything.  You can't miss my house, it's \"\n\"just south of the fork in the river... you know... the one with the overgrown \"\n\"vegetable garden.\"\nmsgstr \"\"\n\"Εντάξει, δεν μουλαρώνω. Δεν είχα σκοπό να σε σταβλίσω. Καθόμουν στο σπίτι, και \"\n\"μού-γκρισα, όταν τα πράγματα έγιναν πραγματικά ασταθή. μια ορδή από τέρατα \"\n\"βγήκε από το πάτωμα! Απλά γελάδεψα! Έτυχε να φοράω αυτή τη φανέλα όταν έτρεξα \"\n\"έξω, και τώρα φαίνομαι απίστευτα αγελαδινός-γελοίος, μα τα μαστάρια μου. Αν \"\n\"είχα μόνο κάτι κανονικό να φορέσω, δεν θα ήταν τόσο κακό. Έι! Θα μπορούσες να \"\n\"πας στο σπίτι μου και να μου φέρεις την στολή μου; Την καφέ, όχι την γκρι, \"\n\"είναι για βραδινό. Θα το έκανα μόνος μου, αλλά δεν θέλω να με βλέπει κανείς \"\n\"έτσι. Ορίστε, πάρε αυτό, μπορεί να το χρειαστείς... για να σκοτώσεις εκείνα τα \"\n\"πράγματα που έχουν κατακλύσει τα πάντα. Είναι αδύνατον να σου ξεφύγει το σπίτι \"\n\"μου, είναι νότια της διχάλας στο ποτάμι... ξέρεις... εκείνο με τον κατάφυτο \"\n\"λαχανόκηπο.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Έχω δοκιμάσει ξόρκια, απειλές, αφορισμούς και διαπραγματεύσεις με αυτό το \"\n\"αποκρουστικό πλάσμα -- χωρίς αποτέλεσμα. Οι μέθοδοι μου για την υποδούλωση των \"\n\"μικρότερων δαιμόνων δεν φαίνεται να έχουν καμία επίδραση σε αυτό το τρομερό \"\n\"θηρίο.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners of \"\n\"my vision.  The faint scrabble of claws dances at the edges of my hearing. \"\n\"They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Το σπίτι μου διαφθείρεται σιγά σιγά από την κακία αυτού του ανεπιθύμητου \"\n\"κρατούμενου. Οι κρύπτες είναι γεμάτες σκιές που κινούνται λίγο πιο πέρα ​​από \"\n\"τις γωνίες της οράσεως μου. Το αχνό ξύσιμο των νυχιών, χορεύει στις άκρες της \"\n\"ακοής μου. Ψάχνουν, νομίζω, για αυτό το ημερολόγιο.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow destroyed \"\n\"my library.  Na-Krul... The name fills me with a cold dread.  I prefer to \"\n\"think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Μέσα στο παραλήρημα του, το πλάσμα άφησε να ξεφύγει το όνομά του -- Να-Κρούλ. \"\n\"Προσπάθησα να ερευνήσω το όνομα, αλλά οι μικρότεροι δαίμονες κατά κάποιο τρόπο \"\n\"κατέστρεψαν τη βιβλιοθήκη μου. Να-Κρούλ... Το όνομα με γεμίζει κρύο τρόμο. \"\n\"Προτιμώ να το σκέφτομαι μόνο ως Το Πλάσμα παρά να αναλογιστώ το πραγματικό του \"\n\"όνομα.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, and \"\n\"yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Τα ουρλιαχτά της οργής του παγιδευμένου πλάσματος με εμποδίζουν να αποκτήσω \"\n\"τον τόσο απαραίτητο ύπνο μου. Μαίνεται εναντίον αυτού που το έστειλε στο Κενό, \"\n\"και με βρίζει που το παγίδευσα εδώ. Τα λόγια του γεμίζουν την καρδιά μου με \"\n\"τρόμο, κι δεν μπορώ να αποκλείσω τη φωνή του από το μυαλό μου.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my knowledge \"\n\"to free their lord.  I hope that whoever finds this journal will seek the \"\n\"knowledge.\"\nmsgstr \"\"\n\"Ο χρόνος μου τελειώνει γρήγορα. Πρέπει να καταγράψω τους τρόπους για να \"\n\"αποδυναμώσω τον δαίμονα και μετά να κρύψω αυτό το κείμενο, μήπως οι δαιμονικοί \"\n\"υπηρέτες του βρουν κάποιο τρόπο να χρησιμοποιήσουν τις γνώσεις μου για να \"\n\"ελευθερώσουν τον κύριό τους. Ελπίζω ότι όποιος βρει αυτό το ημερολόγιο θα \"\n\"αναζητήσει τη γνώση.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions claw \"\n\"at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great walls, \"\n\"but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance to \"\n\"his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Όποιος βρει αυτόν τον πάπυρο χρεώνεται με το βάρος να σταματήσει το δαιμονικό \"\n\"πλάσμα που βρίσκεται μέσα σε αυτά τα τείχη. Ο χρόνος μου τελείωσε. Ακόμα και \"\n\"τώρα, τα κολασμένα διαβολάκια του νυχιώνουν την εύθραυστη πόρτα πίσω από την \"\n\"οποία κρύβομαι.\\n\"\n\" \\n\"\n\"Έχω στριμώξει τον δαίμονα με απόκρυφη μαγεία και τον έχω εγκλωβίσει μέσα σε \"\n\"μεγάλα τείχη, αλλά φοβάμαι ότι δεν θα είναι αρκετό.\\n\"\n\" \\n\"\n\"Τα ξόρκια που βρίσκονται στα τρία Γραμματικά μου θα σας προσφέρουν \"\n\"προστατευμένη είσοδο στην φυλακή του, αλλά μόνο εάν τεθούν με τη σωστή σειρά. \"\n\"Οι μοχλοί στην είσοδο θα αφαιρέσουν τα μαγικά εμπόδια και θα απελευθερώσουν \"\n\"τον δαίμονα. μην τα αγγίζετε! Χρησιμοποιήστε μόνο αυτά τα ξόρκια για να \"\n\"αποκτήσετε είσοδο, διαφορετικά η δύναμή του μπορεί να είναι πολύ μεγάλη για να \"\n\"μπορέσεις να νικήσεις.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Αγριόχοιρος της Κολάσεως\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Κεντρί\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Ψυχόσφαιρος\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Αραχνόμος\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Έκπτωτος Δίδυμος\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Γόνος Σαρκοδαίμονα\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Δηλητηριώδες Ουρά\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Νεκρόσφαιρος\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Άρχοντας της Αράχνης\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Μαστιγοσκώληκας\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Πυρσοδαίμονας\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Έντομο της Κολάσεως\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Νεκροθάφτης\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Αρουραίος Τάφων\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Νυχτερίδα της Φωτιάς\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Φτερωτό Κρανίο\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Απέθαντος Μάγος\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Δαίμονας της Κρύπτης\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Κολασμένη Νυχτερίδα\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Δαίμονας των Οστών\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Απέθαντος Αρχιμάγος\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Δικέφαλος Κύκλωπας\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Πράγμα Σάρκας\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Θεριστής\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"H Άρθρωση των Δακτύλων του Γίγαντα\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Το Υδραργυρικό Δακτυλίδι\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Το Δακτυλίδι του Ξορίνε\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Το Δακτυλίδι του Κάρικ\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Το Δακτυλίδι του Μάγματος\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Το Δακτυλίδι των Μυστών\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Το Δακτυλίδι του Κεραυνού\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Το Φυλακτό της Προστασίας\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Το Κεντρί της Σκνίπας\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Η Φλεγόμενη Δάδα\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Θωράκιση της Θλίψης\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Κεραυνοβόλο Τόξο\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Το Μπουμπουνητό\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Σιροτάτσι\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Ο Φάγος των Ψυχών\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Η Άκρη του Διαμαντιού\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Η Κοκάλινη Αλυσιδωτή Πανοπλία\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Ο Δαιμονικός Ολομεταλλικός Θώρακας\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Το Φυλακτό του Ακόλουθου\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Το Δαχτυλίδι του Μονομάχου\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"του Γελωτοποιού\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"του Κρυσταλλινικού\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"του Σωσία\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"της Καταστροφής\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"της Σήψης\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"του Κινδύνου\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Μάνα\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"ο Μάγος\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"ο Γελωτοποιός\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Τείχος Κεραυνού\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Πυρπόληση\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Αναδίπλωση\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Αντανάκλαση\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Μπερσέκερος\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Κύκλος Φωτιάς\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Αναζήτηση\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Ρούνος Φωτιάς\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Ρούνος Φωτός\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Ρούνος Αστρικής Έκρηξης\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Ρούνος Πυρπόλησης\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Ρούνος Πέτρας\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"/help\"\n#~ msgstr \"/βοήθεια\"\n\n#~ msgid \"({command})\"\n#~ msgstr \"({command})\"\n\n#~ msgid \"/arena\"\n#~ msgstr \"/αρένα\"\n\n#~ msgid \"/arenapot\"\n#~ msgstr \"/φίλτρααρένας\"\n\n#~ msgid \"/inspect\"\n#~ msgstr \"/επιθεώρηση\"\n\n#~ msgid \"/seedinfo\"\n#~ msgstr \"/πληροφορίασπόρου\"\n\n#~ msgid \"Command \\\"\"\n#~ msgstr \"Εντολή \\\"\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Μείωση συντελεστή φωτεινότητας Gamma\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Αύξηση συντελεστή φωτεινότητας Gamma\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Ο χάρτης δεν είναι διαθέσιμος στην πόλη\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Ανάσταση στην Πόλη\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Καρδιά\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Προσπαθείς να ρίξεις αντικείμενο που είναι ήδη στο πάτωμα;\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Ενεργοποιεί την αναμονή για Οριζόντιο Συγχρονισμό. Αποτρέπει το σχίσιμο \"\n#~ \"οθόνης στην εμφάνιση του κάθε καρέ. Η απενεργοποίηση του μπορεί να βοηθήσει \"\n#~ \"με πιθανόν καθυστέρηση ποντικιού σε κάποια συστήματα.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Όριο KΑΔ(FPS)\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Τα ΚΑΔ(Καρέ ανά Δευτερόλεπτο) περιορίζονται για την αποφυγή υπερφόρτωσης \"\n#~ \"της ΚΜΕ. Το όριο λαμβάνει υπόψιν τον ρυθμό ανανέωσης της οθόνης.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"% για χτύπημα\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Άφθαρτο, \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Δεν απαιτούνται στατιστικά\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Συννεφιά και πιο δροσερά σήμερα. Ρίχνοντας τα δίχτυα της νεκρομαντείας στην \"\n#~ \"διάσταση του κενού έπιασα δύο νέα υποείδη ιπτάμενων τρόμων, μια καλή μέρα \"\n#~ \"στη δουλειά. Πρέπει να θυμηθώ να παραγγείλω επιπλέον κουτσουλιές νυχτερίδας \"\n#~ \"και μαύρα κεριά από την Άντρια. Μου τελειώνουν.\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Επιλογές\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"έκδοση {:s}\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"ανάκτηση ζωής\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"θανατηφόρα θεραπεία\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"μειώνει την δύναμη\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"μειώνει την επιδεξιότητα\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"μειώνει την ζωτικότητα\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"δεν μπορείς να θεραπευθείς\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"ο κτύπος δεν επιτρέπει θεραπεία\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Γρηγορότερη κίνηση επίθεσης\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"βλέπεις με υπέρυθρη όραση\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Αποτυχία ανοίγματος αρχείου παίκτη για εγγραφή.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Αποτυχία ανάγνωσης από αρχείο παιχνιδιού\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Αποτυχία εγγραφής σε αρχείο παιχνιδιού\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"Πέρα από τον Θάλαμο των Ηρώων βρίσκεται ο Θάλαμος των Οστών. Ο αιώνιος \"\n#~ \"θάνατος περιμένει όποιον θα ήθελε να κλέψει τους θησαυρούς που είναι \"\n#~ \"ασφαλισμένοι σε αυτό το δωμάτιο. Έτσι λέει ο Άρχοντας του Τρόμου, και έτσι \"\n#~ \"είναι γραμμένο.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay the \"\n#~ \"mutilated bodies of thousands.  Angels and man alike have been cut down to \"\n#~ \"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n#~ \"blood.\"\n#~ msgstr \"\"\n#~ \"Τα οπλοστάσια της Κόλασης είναι το σπίτι του Πολέμαρχου του Αίματος. Στο \"\n#~ \"πέρασμά του κείτονται τα ακρωτηριασμένα σώματα χιλιάδων. Άγγελοι και \"\n#~ \"άνθρωποι έχουν σφαγιαστεί για να εκπληρώσουν τις ατελείωτες θυσίες του, \"\n#~ \"στους Σκοτεινούς, που ουρλιάζουν για ένα πράγμα - αίμα.\"\n"
  },
  {
    "path": "Translations/es.po",
    "content": "# Translation of DevilutionX to Spanish\n# Emiliano Augusto Gonzalez <emigonza@gmail.com>, 2021.\n# egonzalez, 2021.\n# Mad-Soft <mad.soft@gmail.com>, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:19+0200\\n\"\n\"PO-Revision-Date: 2025-10-02 15:19+0200\\n\"\n\"Last-Translator: Oleksandr Kalko (tsunami_state) <tsunami.wave@ukr.net>\\n\"\n\"Language-Team: Spanish\\n\"\n\"Language: es\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Diseño del Juego\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Diseñadores Senior\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Diseño adicional\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Programador Principal\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Programadores Senior\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programación\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Programadores Invitados Especiales\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Programación Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Programación de Comunicaciones en Serie\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Programación del Instalador\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Directores de Arte\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Arte\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Técnico de Arte\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Directores de Arte Cinematográfico\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"Arte Cinematográfico 3D\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Técnico de Arte Cinematográfico\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Productor Ejecutivo\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Productor\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Productor Asociado\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Música\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Diseño de sonido\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Música y Sonido Cinematográfico\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Producción de Voz, Dirección y Casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Guion e historia\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Edición de voz\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Voces\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Ingeniero de Grabación\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Diseño y Maquetación del Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Arte del Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Director Provisional de Control de Calidad (Probador Jefe)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Escuadrón de Asalto del Control de Calidad (Probadores)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"\"\n\"Equipo de Operaciones Especiales del Control de Calidad (Probadores de \"\n\"Compatibilidad)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Soporte de Artillería del Control de Calidad (probadores adicionales) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Contrainteligencia del Control de Calidad\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Pedido de los Servicios de Información de la Red\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Atención al cliente\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Ventas\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Inútil\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Vocalistas de Fondo del Sr. Dabiri\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Relaciones públicas\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Márketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Ventas internacionales\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Ventas en EEUU\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Fabricación\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Legal y Comercial\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Agradecimientos especiales a\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Gracias a\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"En memoria de\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Un agradecimiento muy especial a\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Gerente General\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Ingeniería de Software\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Director de Arte\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Artistas\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Diseño\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Diseño de Sonido, SFX e Ingeniería de Audio\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Responsable de la Garantía de Calidad\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Probadores\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tTrabajo Adicional\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Escritura de Texto de Búsqueda\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Gracias a\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tUn Agradecimiento Especial a Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Noroeste\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Gerente de Garantía de Calidad\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Probador Principal de Garantía de Calidad\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Probadores Principales\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Probadores Adicionales\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Gerente de Marketing del Producto\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Director de Relaciones Públicas\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Gerente de Producto Asociado\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"El Anillo de los Mil\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tNingún alma fue vendida para la realización de este juego.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Elegir Clase\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Cancelar\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Nuevo Héroe Multijugador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Nuevo Héroe para un Jugador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Existe juego guardado\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Cargar\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Nueva Partida\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Personajes de un Jugador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"El Ladrón y el Hechicero solo están disponibles en la versión comercial \"\n\"completa de Diablo. Visite https://www.gog.com/game/diablo para comprar.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Introduzca nombre\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Nombre inválido. El nombre no puede contener espacios, ni caracteres o \"\n\"palabras reservadas.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Imposible crear personaje.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Nivel:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Fuerza:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magia:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Destreza:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalidad:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Juego guardado:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Elije Héroe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Nuevo Héroe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Eliminar\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Personajes Multijugador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Eliminar Héroe Multijugador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Eliminar Héroe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"¿Seguro que quieres eliminar el personaje \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Un Jugador\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Multijugador\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Ajustes\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Soporte\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Créditos\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Salir\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Salir\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Cliente-Servidor (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Fuera de línea\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Partida Multijugador\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Requisitos:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"sin puerta de enlace\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Conexión\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Cambiar puerta de enlace\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"\"\n\"Todas las computadoras deben estar conectadas a una red compatible con TCP.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Todas las computadoras deben estar conectadas a Internet.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Juegar solo sin exposición a la red.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Jugadores soportados: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"El anfitrión está ejecutando un juego diferente al tuyo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"\"\n\"El anfitrión está ejecutando un modo de juego ({:s}) diferente al tuyo.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Su versión {:s} no coincide con el anfitrión {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Descripción:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Seleccione acción\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Crear Juego\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Crear Juego Público\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Unirse al Juego\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Juegos público\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Cargando...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Ninguno\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"Cancelar\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Crear un nuevo juego con la dificultad que elijas.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Crear un nuevo juego público donde cualquiera puede unirse con la dificultad \"\n\"que elijas.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Introduzca un ID de juego para unirse a un juego en curso.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Introduzca una IP o un nombre de equipo para unirse a un juego en curso.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Unirse a un juego público que ya esté en curso.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Pesadilla\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Infierno\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Dificultad {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Velocidad: Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Velocidad: Rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Velocidad: Más rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Velocidad: Lo más rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Jugadores: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Dificultad\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Unirse a los juegos {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Introduzca su ID de juego\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Introduzca la dirección\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Dificultad normal\\n\"\n\"Aquí es donde un personaje inicial debe comenzar la búsqueda para derrotar a \"\n\"Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Dificultad de pesadilla\\n\"\n\"Los habitantes del Laberinto se han reforzado y demostrarán ser un desafío \"\n\"mayor. Esto se recomienda solo para personajes experimentados.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Dificultad del infierno\\n\"\n\"La más poderosa de las criaturas del inframundo acecha en la entrada al \"\n\"infierno. Solo los personajes más experimentados deberían aventurarse en \"\n\"este reino.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Su personaje debe alcanzar el nivel 20 antes de que pueda ingresar a un \"\n\"juego multijugador de dificultad Pesadilla.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Su personaje debe alcanzar el nivel 30 antes de que pueda ingresar a una \"\n\"partida multijugador de dificultad infernal.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Seleccionar velocidad de juego\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Más rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Lo más rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Velocidad normal\\n\"\n\"Aquí es donde un personaje inicial debe comenzar la búsqueda para derrotar a \"\n\"Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Velocidad Rápida\\n\"\n\"Los habitantes del Laberinto se han acelerado y demostrarán ser un desafío \"\n\"mayor. Esto se recomienda solo para personajes experimentados.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Velocidad más rápida\\n\"\n\"La mayoría de los monstruos de la mazmorra te buscarán más rápido que nunca. \"\n\"Solo un campeón experimentado debería probar suerte a esta velocidad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Velocidad más rápida\\n\"\n\"Los esbirros del inframundo se apresurarán a atacar sin dudarlo. Solo un \"\n\"verdadero demonio de la velocidad debería entrar a este ritmo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Introduzca la contraseña\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Entrar a Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Cambiar a Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Si\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"No\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Presiona los botones del gamepad para cambiar.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Enlazar tecla:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Presiona una tecla para cambiar.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Liberar tecla\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Agrupar combinación de botones:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Desagrupar combinación de botones\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Menú Anterior\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Mantenemos un servidor en Discord.gg/devilutionx Sigue los enlaces para \"\n\"unirte a nuestra comunidad donde hablamos de cosas relacionadas con Diablo, \"\n\"y la expansión Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX es mantenido por Diasurgical, los problemas y fallos pueden ser \"\n\"reportados en esta dirección: https://github.com/diasurgical/devilutionX \"\n\"Para ayudarnos a servirle mejor, por favor asegúrese de incluir el número de \"\n\"versión, el sistema operativo y la naturaleza del problema.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Descargo de responsabilidad:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX no está soportado ni mantenido por Blizzard Entertainment, ni \"\n\"por GOG.com. Ni Blizzard Entertainment ni GOG.com han probado o certificado \"\n\"la calidad o compatibilidad de DevilutionX. Todas las preguntas relacionadas \"\n\"con DevilutionX deben dirigirse a Diasurgical, no a Blizzard Entertainment \"\n\"ni a GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tEsta adaptación hace uso de Charis SIL, New Athena Unicode, Unifont, y \"\n\"Noto que están licenciados bajo la SIL Open Font License, así como Twitmoji \"\n\"que está licenciado bajo CC-BY 4.0.  También hace uso de SDL que está \"\n\"licenciado bajo la licencia zlib. Para más detalles, consulte el Léame.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Error\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"El error ocurrió en: {:s} línea {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Error de Archivo de Datos\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Imposible abrir el archivo de datos principal ({:s}).\\n\"\n\"\\n\"\n\"Asegúrese de que esté en la carpeta del juego.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Error de Directorio de Solo Lectura\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"No se puede escribir en la ubicación:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Juego: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Juego sin conexión\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Contraseña: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Juego público\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Nivel: Guarida {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Nivel: Cripta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Pueblo\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Nivel: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Intro\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Información del Personaje\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Registro de Misiones\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Automapa\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Menú Principal\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventario\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Libro de Hechizos\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Enviar Mensaje\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Comandos Disponibles:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Comando \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" es desconocido.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Descripción: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parametros No se necesitan parámetros adicionales.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parametros: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Las Arenas solo están soportadas en multijugador.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"¿Cuál arena quieres visitar?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Número de Arena inválido. Los números válidos son:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"Para entrar a una arena debes estar en el pueblo o en otra arena.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Inspección solo está soportado en multijugador.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Parar jugadores de inspectores.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"No se encontraron jugadoras con tal nombre\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Jugador inspector: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\"Imprime una descripción general de la ayuda o ayuda para un comando \"\n\"específico.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[comando]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Enttrar a una Arena PvP.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"{arena-número}\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Da pociones de arena.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<número>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Inspecciona las estadísticas y el equipamiento de otro jugador.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<nombre del jugador>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Mostrar información inicial para el nivel actual.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Jugador amigable\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Ataque del jugador\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Tecla de acceso rápido: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Seleccionar botón de hechizo actual\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Tecla de acceso rápido: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"Habilidad {:s}\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"Hechizo {:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Nivel 0 - Inutilizable\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Nivel {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Pergamino de {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Pergamino\"\nmsgstr[1] \"{:d} Pergaminos\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Bastón de {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Carga\"\nmsgstr[1] \"{:d} Cargas\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} pieza de oro\"\nmsgstr[1] \"{:s} piezas de oro\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Requisitos no cumplidos\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Nivel: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Vida {:d} de {:d}\"\n\n#: Source/control.cpp:1525\nmsgid \"Right click to inspect\"\nmsgstr \"Clic derecho para inspeccionar\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Subir Nivel\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"Has muerto\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"ESC\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"Botón de Menú\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"Presiona {} para cargar la última grabación.\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"Presiona {} para volver al Menú Principal.\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"Presiona {} para reiniciar en el pueblo.\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Tiene {:s} moneda de oro. ¿Cuanto quiere eliminar?\"\nmsgstr[1] \"Tiene {:s} monedas de oro. ¿Cuantas quiere eliminar?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Portal del pueblo\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"de {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal a\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"El Altar Impío\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"nivel 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"No se pueden cargar datos del archivo {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} está incompleto, verifique el contenido del archivo.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"Su archivo {0} no tiene las columnas esperadas; asegúrese de que coincida \"\n\"con el formato documentado.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Valor no numérico {0} para {1} en {2} en la fila {3} y la columna {4}\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Valor fuera de rango {0} para {1} en {2} en la fila {3} y la columna {4}\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Valor no válido {0} para {1} en {2} en la fila {3} y la columna {4}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Imprime este mensaje y sal\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Imprime la versión y sal\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Especifique la carpeta de diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Especifique la carpeta de archivos guardados\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Especifique la ubicación de diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Especifique el código de idioma (ej. en ó pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Omitir videos de inicio\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Mostrar fotogramas por segundo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Habilitar el registro detallado\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"Log en un archivo en lugar de stderr\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Grabar un archivo de demostración\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Jugar un archivo de demostración\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Desactivar la limitación de FPS durante la reproducción de la demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Selección de juego:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Forzar modo shareware\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Forzar modo Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Forzar modo Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Opciones de Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Reportar errores a https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\"Por favor a\\n\"\n\"ctualice devilutionx.mpq y fonts.mpq a la última versión\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"No se pudieron cargar los recursos de la IU.\\n\"\n\"\\n\"\n\"Asegúrese que Devilutionx.mpq se encuentra en la carpeta del juego y está \"\n\"actualizado.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\"Por favor ac\\n\"\n\"tualice fonts.mpq a la última versión\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Tiempo de espera de la red terminado --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Esperando jugadores --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"No hay ayuda disponible\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"mientras que en las tiendas\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Objeto del cinturón {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Usar objeto del cinturón.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Hechizo rápido {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Tecla rápida para habilidad o hechizo.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Hechizo rápido anterior\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Selecciona el hechizo rápido anterior (ciclos).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Siguiente hechizo rápido\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Selecciona el siguiente hechizo rápido (ciclos).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Usar poción de curación\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Usar pociones de salud del cinturón.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Usar poción de maná\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Usar poción de maná del cinturón.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Libro rápido\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Abrir libro rápido.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Grabación rápida\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Grabar el juego.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Carga rápida\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Cargar el Juego.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Salir\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Cerrar el juego.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Detener héroe\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Dejar de caminar y cancelar acciones pendientes.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Resaltado de elementos\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Mostrar/ocultar elementos en el suelo.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Alternar resaltado de elementos\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Mostrar/ocultar elementos permanentes en el suelo.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Alternar mapa automático\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Alterna si se muestra el mapa automático.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Tipo de mapa de ciclo\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Opaco -> Transparente -> Minimapa -> Ninguno\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Abrir la pantalla de Inventario.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Personaje\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Abrir pantalla de Personaje.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"Grupo\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"Abrir panel lateral de Grupo\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Registro de Misiones\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Abrir Registro de Misiones.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Libro de Hechizos\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Abrir Libro de Hechizos.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Mensaje rápido {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Usar Mensaje rápido en el chat.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Ocultar las pantallas de información\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Ocultar todas las pantallas de información.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Ampliar\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Ampliar de la pantalla del juego.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Pausar Juego\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Pausar el juego.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pausar juego (alternativo)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\nmsgid \"Decrease Brightness\"\nmsgstr \"Disminuir el brillo de la pantalla.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Reducir el brillo de la pantalla.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\nmsgid \"Increase Brightness\"\nmsgstr \"Aumentar el Brillo\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Aumentar el brillo de la pantalla.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Ayuda\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Abrir pantalla de ayuda.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Captura de pantalla\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Toma una captura de pantalla.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Información del Juego\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Mostrar información del juego.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Log del Chat\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Mostrar log del Chat.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Ordenar Inventario\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Ordenar el Inventario.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Consola\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Abrir consola de LUA.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Acción primaria\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Ataca a los monstruos, habla con los habitantes, levanta y coloca artículos \"\n\"de inventario.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Ación secundaria\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Abre cofres, interactúa con las puertas, recoge objetos.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Acción de hechizo\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Lanzar hechizo activo.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Cancelar acción\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Cerrar menús.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Ascender\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Mueve el personaje del jugador hacia arriba.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Descender\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Mueve el personaje del jugador hacia abajo.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Mover a la izquierda\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Mueve el personaje del jugador a la izquierda.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Mover a la derecha\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Mueve el personaje del jugador a la derecha.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Estar en tierra\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Mantén presionado para evitar que el jugador se mueva.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Alternar mantener en tierra\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Alternar mientras el jugador se mueve.\"\n\n#: Source/diablo.cpp:2310\nmsgid \"Automap Move Up\"\nmsgstr \"Subir Automapa\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"Mueve el automapa hacia arriba cuando está activo.\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"Bajar Automapa\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"Mueve el automapa hacia abajo cuando está activo.\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"Mover Automapa a la izquierda\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Mueve el automapa hacia la izquierda cuando está activo.\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"Mover Automapa a la derecha\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"Mueve el automapa hacia la derecha cuando está activo.\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Mover el mouse hacia arriba\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Simula el movimiento ascendente del ratón.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Mover el ratón hacia abajo\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Simula el movimiento del ratón hacia abajo.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Mover el mouse hacia la izquierda\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Simula el movimiento del ratón hacia la izquierda.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Mover el ratón a la derecha\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Simula el movimiento del ratón hacia la derecha.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Clic izquierdo del ratón\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Simula el botón izquierdo del ratón.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Clic derecho del mouse\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Simula el botón derecho del ratón.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Menú de hechizos de gamepad\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\"Mantener presionado para configurar o usar las teclas de acceso rápido de \"\n\"hechizos.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Navegador de menú Gamepad\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Mantén presionado para acceder a la navegación del menú del gamepad.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Alternar el menú del juego\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Abre el menú del juego.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Juego guardado\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"No hay funciones multi jugador en la demostración\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Falló la creación de Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"No disponible en la versión shareware\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"No hay suficiente espacio para grabar\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Sin Pausa en el pueblo\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Se recomienda copiar a un disco duro\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Problema de sincronización multi jugador\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Sin pausa en multi jugador\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Grabando...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Algunos se debilitan a medida que uno se hace más fuerte\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Nueva fuerza se forja a través de la destrucción\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Aquellos que defienden raras veces atacan\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"La espada de la justicia es rápida y afilada\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Mientras el espíritu está alerta, el cuerpo prospera\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Los poderes del maná reenfocado se renuevan\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"El tiempo no puede disminuir el poder del acero\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"La Magia no siempre es lo que parece\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Lo que una vez estuvo abierto ahora está cerrado\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"La intensidad viene a costa de la sabiduría\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"El poder arcano trae destrucción\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Lo que no se puede sujetar, no se puede dañar\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Crarmesí y Azur se vuelven como el sol\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Conocimiento y sabiduría a costa de uno mismo\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Bebe y refréscate\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Dondequiera que vayas, ahí estás\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"La energía viene a costa de la sabiduría\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Las riquezas abundan cuando menos se espera\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Donde la avaricia falla, la paciencia gana recompensa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"¡Bendecido por un compañero benevolente!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Las manos de los hombres pueden ser guiadas por el destino\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"La fuerza se ve reforzada por la fe celestial\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"La esencia de la vida fluye desde dentro\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"El camino se aclara cuando se ve desde arriba\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"La salvación viene a costa de la sabiduría\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Los misterios se revelan a la luz de la razón\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Los que son los últimos pueden ser los primeros\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"La generosidad trae sus propias recompensas\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Debes tener al menos el nivel 8 para usar esto.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Debes tener al menos el nivel 13 para usar esto.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Debes tener al menos el nivel 17 para usar esto.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"¡Conocimiento arcano adquirido!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Eso que no te mata ...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"El conocimiento es poder.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Da y recibirás.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Se adquiere algo de experiencia mediante el tacto.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"No hay lugar como el hogar.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Se restaura la energía espiritual.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Te sientes más ágil.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Te sientes más fuerte.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Te sientes más sabio.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Te sientes renovado.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Aquello que puede romper la voluntad.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Catedral\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Catacumbas\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Cuevas\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Nido\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Crípta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Niv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} dificultad\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"En Menú\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"No puede conectarse\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"error: leidos 0 bytes del servidor\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\"No se pudo abrir el archivo:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"Es posible que los archivos MPQ estén dañados. Verifique la integridad de \"\n\"los archivos.\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq o spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Faltan algunos MPQ de Hellfire\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"No se encontraron todos los MPQ de Hellfire.\\n\"\n\"Copie todos los archivos hf * .mpq.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Resolución\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Correr en el pueblo\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"La misión de Theo\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"La misión de la vaca\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Auto recoger oro\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Auto recoger elixir\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Recolección automática de aceite\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Auto recoger en el pueblo\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria recarga maná\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Auto equiparse con armas\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Auto equiparse con armadura\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Auto equiparse con yelmo\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Auto equiparse con escudos\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Auto equiparse con joyería\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Misiones aleatorias\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Mostrar etiquetas de artículos\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Auto recargar cinturón\"\n\n# La traduccion debe ser corta para que entre en el cuadro de dialogo\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Desact. santuarios paralizantes\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Recoger poción de salud\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Recoger poción de salud completa\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Recoger poción de maná\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Recoger poción de maná completo\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Recoger poción de rejuvenecimiento\"\n\n# La traduccion debe ser corta para que entre en el cuadro de dialogo\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Recoger poción de rejuvenec. completo\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Opciones\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Guardar\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\nmsgid \"Exit to Main Menu\"\nmsgstr \"Salir al Menú Principal\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Salir\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gama\"\n\n# Mantener corto. Texto de menú\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Veloc.\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Música Desactivada\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Sonido\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Sonido Desactivado\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pausa\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Atajos de Teclado:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Abrir Pantalla de Ayuda\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Mostrar Menú Principal\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Pestaña:   Mostrar Mapa Automático\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Espacio: Ocultar todas las pantallas de información\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Abrir libro rápido\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Abrir Libro de Hechizos\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Abrir Pantalla de Inventario\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Abrir pantalla de Personaje\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Abrir Registro de Misiones\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Reducir el brillo de la pantalla\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Aumentar el brillo de la pantalla\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Zoom de la pantalla del juego\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Zoom Automapa\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Usar elemento del Cinturón\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"\"\n\"F5, F6, F7, F8:     Establecer tecla de acceso rápido para habilidad o \"\n\"hechizo\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Mayús + Clic izquierdo: Atacar sin moverse\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Mayús + Click Izquierdo (en la pantalla del personaje): Asignar todos los \"\n\"puntos de estadística\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Mayús + Click Izquierdo (en el inventario) Mover objeto al cinturón o \"\n\"equipar/desequipar objeto\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Mayús + Click Izquierdo (en el cinturón)): Mover objeto al inventario\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Movimiento:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Si mantienes presionado el botón del mouse mientras se mueve, el personaje \"\n\"continuará moviéndose en esa dirección.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Combate:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Manteniendo presionado la tecla Mayús y luego hacer clic con el botón \"\n\"izquierdo permite que el personaje ataque sin moverse.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Automapa:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Para acceder al auto-mapa, haga clic en el botón 'MAP' en la barra de \"\n\"información o presione 'TAB' en el teclado. Acercar y alejar el mapa se \"\n\"realiza con las teclas + y -. Para desplazarse por el mapa se utilizan las \"\n\"teclas de flecha.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Recoger Objetos:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Los elementos utilizables que son de tamaño pequeño, como pociones o \"\n\"pergaminos, se colocan automáticamente en su 'cinturón' ubicado en la parte \"\n\"superior de la barra de Interfaz. Cuando se coloca un objeto en el cinturón, \"\n\"aparece un pequeño número en ese recuadro. Los artículos se pueden usar \"\n\"presionando el número correspondiente o haciendo clic derecho en el objeto.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Oro:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Puedes seleccionar una cantidad específica de oro para soltar haciendo clic \"\n\"derecho en un montón de oro de su inventario.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Habilidades y Hechizos:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Puedes acceder a tu lista de habilidades y hechizos haciendo clic izquierdo \"\n\"en el botón 'HECHIZOS' en la barra de la interfaz. Aquí se enumeran los \"\n\"hechizos memorizados y los disponibles a través de las varas. Al hacer clic \"\n\"con el botón izquierdo en el hechizo que desea lanzar, se preparará el \"\n\"hechizo. Se puede lanzar un hechizo preparado simplemente haciendo clic con \"\n\"el botón derecho en el área de juego.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Uso del libro rápido para Hechizos:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Al hacer clic con el botón izquierdo en el botón 'hechizo listo' se abrirá \"\n\"el 'libro rápido' que le permite seleccionar una habilidad o hechizo de uso \"\n\"inmediato.  Para usar la habilidad o el hechizo, simplemente haga clic con \"\n\"el botón derecho en el área de juego principal.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Mayús + Click Izquierdo en el botón 'seleccionar hechizo actual' borrará el \"\n\"hechizo preparado.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Configurar teclas de acceso rápido para Hechizos:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Puede asignar hasta cuatro teclas de Acceso Rápido para habilidades, \"\n\"hechizos o pergaminos. Empiece por abrir el 'libro rápido' como se describe \"\n\"en la sección anterior. Presione las teclas F5, F6, F7 o F8 después de \"\n\"resaltar el hechizo que desea asignar.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Libros de hechizos:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Leer más de un libro aumenta su conocimiento de ese hechizo, lo que le \"\n\"permite lanzar el hechizo de manera más efectiva.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Ayuda de Hellfire Shareware\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Ayuda de Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Ayuda de Diablo Shareware\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Ayuda de Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Presione ESC para finalizar o las teclas de flecha para desplazarse.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"No se pudo crear la ventana principal\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"No hay espacio para el artículo\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Aceite de Precisión\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Aceite de Maestría\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Aceite de Nitidez\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Aceite de Muerte\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Aceite de Habilidad\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Aceite de Herrero\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Aceite de Entereza\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Aceite de Permanencia\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Aceite de Endurecimiento\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Aceite de Impermeabilidad\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} de {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1} {0} de {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1} {0} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{1} {0}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"en el arma aumenta\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"probabilidad de acertar\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"aumenta enormemente un\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"posibilidad de que el arma golpee\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"daño potencial\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"aumenta en gran medida la de un arma\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"daño potencial - no arcos\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"reduce los atributos necesarios\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"para usar armaduras o armas\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"restaura el 20% de la\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"durabilidad del artículo\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"aumenta la de un artículo\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"durabilidad actual y máxima\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"hace que un artículo sea indestructible\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"aumenta la clase de armadura\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"de armaduras y escudos\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"aumenta enormemente la armadura\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"clase de armaduras y escudos\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"pone trampa de fuego\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"establece trampa de rayos\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"establece trampa de petrificación\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"restaura toda la vida\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"restaura algo de vida\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"restaura algo de maná\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"restaura todo el maná\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"aumenta la fuerza\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"aumenta la magia\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"aumenta la destreza\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"aumenta la vitalidad\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"restaura algo de vida y maná\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"restaura toda la vida y maná\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(funciona solo en arenas)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Clic derecho para ver\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Clic derecho para usar\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Haga clic derecho para leer, luego\\n\"\n\"clic izquierdo para apuntar\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Haga clic derecho para leer\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Activar para ver\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Abrir inventario para usar\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Activar para usar\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Seleccione del libro de hechizos, luego\\n\"\n\"lance el hechizo para leer\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Activar para leer\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} para ver\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} para usar\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Seleccione del libro de hechizos,\\n\"\n\"luego {} para leer\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} para leer\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Nivel: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Duplica la capacidad de oro\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Requiere:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Fue\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Des\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Libro de {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Oído de {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"probabilidad de acertar: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% daño\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"al golpear: {:+d}%, {:+d} daño\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% armadura\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"clase de armadura: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Resistencia al Fuego: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Resistencia al Fuego: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Resistencia a Relámpagos: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Resistencia a Relámpagos: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Resistencia a la Magia: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Resistencia a la Magia: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Resistencia a Todo: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Resistencia a Todo: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"los hechizos aumentan {:d} nivel\"\nmsgstr[1] \"los hechizos aumentan {:d} niveles\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"los hechizos se reducen {:d} nivel\"\nmsgstr[1] \"los hechizos se reducen {:d} niveles\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"niveles de hechizo sin cambios (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Cargas extras\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} carga\"\nmsgstr[1] \"{:d} {:s} cargas\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Daño por impacto de fuego: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Daño por impacto de fuego: {:d}- {:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Daño por impacto de rayo: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Daño por impacto de rayo: {:d}- {:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} a la fuerza\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} a la magia\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} a la destreza\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} a la vitalidad\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} a todos los atributos\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} de daño de enemigos\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Puntos de Vida: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Maná: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"alta durabilidad\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"durabilidad disminuida\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"indestructible\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% radio de luz\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% radio de luz\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"múltiples flechas por disparo\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"daño de las flechas de fuego: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"daño de las flechas de fuego: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"daño de las flechas de rayo {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"daño de las flechas de rayo {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"daño de bola de fuego: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"daño de bola de fuego: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"el atacante recibe 1-3 daños\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"el usuario pierde todo el maná\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"absorbe la mitad del daño de la trampa\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"hace retroceder al objetivo\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% de daño contra demonios\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Toda la Resistencia es igual a 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"el golpe roba 3% de maná\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"el golpe roba 5% de maná\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"el golpe roba el 3% de vida\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"el golpe roba 5% de vida\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"penetra la armadura del objetivo\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"ataque rápido\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"ataque rápido\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"ataque más rápido\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"ataque más rápido posible\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Otra habilidad (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"recuperación rápida de golpes\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"recuperación de golpes más rápida\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"recuperación de golpe más rápida posible\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"bloqueo rapido\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"agrega {:d} punto al daño\"\nmsgstr[1] \"agrega {:d} puntos al daño\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"dispara flechas de velocidad aleatoria\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"daño inusual del artículo\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"durabilidad alterada\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"espada de una mano\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"pierde puntos de vida constantemente\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"robo de vida\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"sin requisito de fuerza\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"daño por rayo: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"daño por rayo: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"rayos por cada golpe\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"triple daño ocasional\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"{:+d}% de daño de descomposición\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x dañ al mes, 1x a ti\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Daño aleatorio 0 - 600%\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"baja dur, {:+d}% de daño\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"extra CA contra demonios\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"extra CA contra muertos vivientes\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% de Maná se movió a Salud\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% de Salud se movió a Maná\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"daño: {:d}  Indestructible\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"daño: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"daño: {:d}-{:d}  Indestructible\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"daño: {:d}-{:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"defensa: {:d}  Indestructible\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"defensa: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Cargas: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"artículo único\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"No Identificado\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Guarida del Rey Esqueleto\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Cámara de Hueso\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Laberinto\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Red de Agua Envenenada\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Guarida del Arzobispo Lazarus\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Arena de la Iglesia\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Arena Hellfire\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Arena Círculo de la Vida\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Bajar a la mazmorra\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Bajar a las catacumbas\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Bajar a las cuevas\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Bajar al infierno\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Bajar a la colmena\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Bajar a la Cripta\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Sube al nivel {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Sube al pueblo\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Baja al nivel {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Baja a Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Sube al nivel de la Colmena {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Sube al nivel de la Cripta {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Piedra Angular del Mundo\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Baja al nivel de la Cripta {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Volver al nivel {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"No se puede abrir el archivo guardado\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"Versión del guardado no válida. Si intentas acceder a él se sobrescribirán \"\n\"los datos.\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"El tamaño del guardado no es válido. Si intentas acceder a él, se \"\n\"sobrescribirán los datos.\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Archivo guardado no válido\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"El jugador está en un nivel único Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Estado de juego no válido\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"No se puede mostrar el menú principal\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"Error al cargar los datos del monstruo\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\"No se pudo agregar un monstruo, ya que el número máximo de tipo de monstruo \"\n\"de {} ha sido alcanzado.\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"Ya existe un tipo de monstruo para el ID \\\"{}\\\".\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Animal\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demonio\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Muerto viviente\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Tipo: {:s}  Muertes: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Muertes totales: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Puntos de Golpe: {:d}- {:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Sin resistencia mágica\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Resiste:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magia\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Fuego\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Rayo\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Inmune:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Tipo: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Sin resistencias\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Sin Inmunidades\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Algunas Resistencias Mágicas\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Algunas Inmunidades Mágicas\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"No se pudo abrir el archivo para escribir.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} ha lanzado un hechizo inválido.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} ha lanzado un hechizo ilegal.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Jugador ' {:s}' (nivel {:d}) acaba de unirse\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"El juego terminó\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"No se pueden obtener datos del nivel\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"El jugador ' {:s}' acaba de salir del juego\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"¡El jugador ' {:s}' mató a Diablo y abandonó el juego!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"El jugador ' {:s}' desconectado debido al tiempo de espera\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"El jugador ' {:s}' (nivel {:d}) ya está en el juego\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Misterioso\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Oculto\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Sombrío\"\n\n# **\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"misterioso\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Mágico\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Piedra\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Religioso\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Encantada\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Taumatúrgico\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Fascinante\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Críptico\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Espeluznante\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Inquietante\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Divino\"\n\n# **\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"sagrado\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Sagrado\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Espiritual\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Escalofriante\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Abandonado\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Siniestro\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Tranquilo\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Aislado\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Decorado\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Resplandeciente\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Contaminado\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Aceitoso\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Brillante\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Del Mendicante\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Centelleante\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Reluciente\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Solar\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"De Murphy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"El Gran Conflicto\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"La Paga del Pecado es la Guerra\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"El Cuento de los Horadrim\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"El Exilio Oscuro\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"La Guerra del Pecado\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"La Unión de los Tres\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Los Reinos del Más Allá\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Cuento de los Tres\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"El Rey Negro\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Diario: El Hechizado\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Diario: El Encuentro\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Diario: La Diatriba\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Diario: Su Poder Crece\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Diario: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Diario: El Fin\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Un libro de Hechizos\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Esqueleto Crucificado\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Palanca\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Puerta Abierta\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Puerta Cerrada\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Puerta Bloqueada\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Tomo Antiguo\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Libro de la Vileza\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Palanca de Cráneo\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Libro Mítico\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Cofre Pequeño\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Cofre\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Arcón\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarcófago\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Estante para Libros\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Estantería\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Barril\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Vaina\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"Santuario {:s}\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Tomo de Esqueleto\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Libro de la Biblioteca\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Fuente de Sangre\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Cuerpo Decapitado\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Libro de los Ciegos\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Libro de Sangre\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Manantial Purificante\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Armadura\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Estante de Armas\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Santuario de las Cabras\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Caldero\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Piscina Turbia\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Fuente de las Lágrimas\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Tomo de Acero\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Pedestal de Sangre\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Parche de Hongos\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Vil Estante\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Héroe Asesinado\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} Trampa\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (deshabilitado)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"ENCENDIDO\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"APAGADO\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Modo de juego\"\n\n#: Source/options.cpp:422\nmsgid \"Game Mode Settings\"\nmsgstr \"Configuraciones del modo de juego\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Jugar Diablo o Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Restringir a modo shareware\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Hace que el juego sea compatible con la demostración. Habilita el modo \"\n\"multijugador con amigos que no poseen una copia completa de Diablo.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Inicio\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Configuraciones de inicio\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Introducción\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Mostrar cinemática de introducción.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Pantalla de bienvenida\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Mostrar pantalla de bienvenida.\"\n\n# La traducción no es exacta para reducir el largo.\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo y título\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Pantalla de título\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Configuraciones específicas de Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Configuraciones específicas de Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Audio\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Configuraciones de audio\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Sonido al caminar\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Los jugadores emiten sonido cuando caminan.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Sonido de auto equipo\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\"Al equiparse automáticamente con un objeto se emite el sonido de \"\n\"equipamiento.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Sonido de recoger objeto\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Al recoger un objeto se emite el sonido de recoger.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Frecuencia de muestreo\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Frecuencia de muestreo de salida (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Canales\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Número de canales de salida.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Tamaño del buffer\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Tamaño del buffer (numero de cuadros por segundo).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Calidad de remuestreo\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Calidad de remuestreo, desde 0 (el más bajo) a 5 (el más alto).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Afecta a la resolución interna del juego y determina su área de visión. \"\n\"Nota: Esto puede diferir de la resolución de la pantalla cuando se utiliza \"\n\"Aumento de escala, Escala de entera o Ajustar a la pantalla.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Remuestreador\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Remuestreador de audio\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Dispositivo\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Dispositivo de audio\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Gráficos\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Configuración de gráficos\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Pantalla completa\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Muestra el juego en modo ventana o pantalla completa.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Ajustar a la pantalla\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Ajusta automáticamente la venta del juego a la relación de aspecto y \"\n\"resolución del escritorio actual.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Aumento de escala\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Permite escalar la imagen de la resolución del juego a la resolución de su \"\n\"monitor. Evita cambiar la resolución del monitor y permite cambiar el tamaño \"\n\"de la ventana.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Calidad de escalado\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Habilita filtros opcionales para la imagen de salida al ampliar la escala.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Pixel más cercano\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilineal\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotrópico\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Escalado entero\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Escala la imagen usando una proporción de píxeles de números enteros.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"Control de Velocidad de Cuadros\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\"Administra la velocidad de cuadros para equilibrar el rendimiento, reducir \"\n\"el desgarro o ahorrar energía.\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Sincronismo vertical\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"Limitar FPS\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Acercar cuando está habilitado.\"\n\n#: Source/options.cpp:738\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Iluminación por píxel\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"Iluminación de subtejas para gradientes de luz más suaves.\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Ciclo de color\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Efecto de ciclo de color usado para la animación del agua, lava y ácido.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternar arte alternativa\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"El juego usará una paleta alternativa para el juego de fichas alternativo de \"\n\"Hellfire.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Cursor por hardware\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Usar cursor HW\"\n\n# la traduccion debe ser corta para que entre en el cuado de menu\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Cursor HW para objetos\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Usa un cursor HW para los objetos.\"\n\n# Mantener corto. Menu de configuración\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Tamaño máximo del cursor HW\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Máximo ancho/alto del cursor por hardware. Cursores muy grandes se \"\n\"sustituyen por software.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Mostrar FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Muestra los FPS en la esquina superior izquierda de la pantalla.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Juego\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Configuraciones durante el juego\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Habillita trotar/caminar veloz en el pueblo para Diablo y Hellfire. Esta \"\n\"opción fue introducida en la expansión.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Capturar entrada\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Cuando está habilitado el ratón se captura en la ventana de juego.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Pausar el juego cuando la ventana pierde el foco\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"Cuando está habilitado, el juego se detendrá cuando se pierda el foco.\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Habilita la misión de la Niñita.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Habilita la misión de Jersey. El granjero Lester es reemplazado por el Loco \"\n\"de Remate.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Fuego amigo\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Permite que las flechas/hechizos produzcan daño entre los jugadores en un \"\n\"juego multijugador aun cuando el modo amigo está habilitado.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Misiones completas en multijugador\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\"Habilita la versión completa/sin cortes de las misiones para un jugador.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Probar Bardo\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\"Fuerza al tipo de personaje Bardo a aparecer en el menú de selección del \"\n\"personaje.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Probar Bárbaro\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\"Fuerza al tipo de personaje Bárbaro a aparecer en el menú de selección del \"\n\"personaje.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Barra de experiencia\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\"Se agrega la barra de experiencia a la UI en la parte inferior de la \"\n\"pantalla.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Mostrar gráficos de artículos en tiendas\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\"Mostrar gráficos de artículos a la izquierda de las descripciones de los \"\n\"artículos en los menús de la tienda.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Muestra valores de salud\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Muestra el valor de salud actual/máximo en el globo de salud.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Muestra valores de maná\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Muestra el valor de maná actual/máximo en el globo de maná.\"\n\n#: Source/options.cpp:797\nmsgid \"Show Party Information\"\nmsgstr \"Mostrar Información del Grupo\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\"Muestra la salud y el maná de todos los miembros del grupo multijugador \"\n\"conectados.\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Barra de salud del enemigo\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"\"\n\"Se muestra la barra de salud del enemigo en la parte superior de la pantalla.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"Cuadro de información de elemento flotante\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\"Muestra la información del artículo en un cuadro flotante al pasar el cursor \"\n\"sobre un artículo.\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"El oro es automáticamente recogido cuando se encuentra en proximidad del \"\n\"jugador.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Los elixires son automáticamente recogidos cuando se encuentran en \"\n\"proximidad del jugador.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Los aceites se recogen automáticamente cuando está cerca del jugador.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Automáticamente recoge los objetos en el pueblo.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria recargará tu maná cuando la visites en su tienda.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Si está habilitado las armas serán automáticamente equipadas al recogerse o \"\n\"comprarse.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Si está habilitado las armaduras serán automáticamente equipadas al \"\n\"recogerse o comprarse.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Si está habilitado los yelmos serán automáticamente equipadas al recogerse o \"\n\"comprarse.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Si está habilitado los escudos serán automáticamente equipadas al recogerse \"\n\"o comprarse.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Si está habilitado las joyerías serán automáticamente equipadas al recogerse \"\n\"o comprarse.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"\"\n\"Selecciona aleatoriamente las misiones disponibles en las nuevas partidas.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Mostrar el tipo de monstruo\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Al pasar el cursor sobre un monstruo, se mostrará el tipo de monstruo en el \"\n\"cuadro de descripción de la interfaz de usuario.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Mostrar etiquetas para artículos en el suelo cuando está habilitado.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Recarga el cinturón desde el inventario cuando el objeto ha sido consumido.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Cuando están habilitados, no se puede hacer clic en Calderos, Santuarios \"\n\"fascinantes, Santuarios de cabras, Santuarios ornamentados, Santuarios \"\n\"sagrados y Santuarios de Murphy y etiquetarlos como deshabilitados.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Lanzamiento rápido\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Las teclas rápidas de hechizos los lanzan inmediatamente en vez de cambiar a \"\n\"hechizo leído.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Número de pociones de salud que se recogerán automáticamente.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Número de pociones de salud completa que se recogerán automáticamente.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Número de pociones de maná que se recogerán automáticamente.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Número de pociones de maná completo que se recogerán automáticamente.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Número de pociones de rejuvenecimiento que se recogerán automáticamente.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Número de pociones de rejuvenecimiento completo que se recogerán \"\n\"automáticamente.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Habilitar números flotantes\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"Habilita números flotantes al ganar XP/infligir daño, etc.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Apagado\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Ángulos aleatorios\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Solo vertical\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Controlador\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Configuraciones del controlador\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Red\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Configuraciones de red\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chat\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Configuraciones del chat\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Idioma\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Define el idioma que se utilizará en el juego.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Configuración de idioma\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Mapeo de teclas\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Configuración de mapeo de teclas\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Mapeo del pad\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Configuración de mapeo del pad\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"Mods\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"Configuraciones de Mods\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Nivel\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Experiencia\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Siguiente Nivel\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Base\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Ahora\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Fuerza\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magia\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Destreza\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalidad\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Puntos a distribuir\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Oro\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Clase armadura\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"Probabilidad de acertar\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Daño\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Vida\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Maná\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Resist magia\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Resist fuego\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Resist rayos\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"personaje\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"misiones\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"mapa\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menú\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"inv\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"hechizos\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"voz\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"silenciar\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Inutilizable\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Daño: 1/3 tgt hp\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Sana: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Daño: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Habilidad\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Bastón ({:d} carga)\"\nmsgstr[1] \"Bastón ({:d} cargas)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Nivel: {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Maná: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Hechizo\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Solo daña muertos vivientes\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Pergamino\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Bastón\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Tecla de acceso rápido de Hechizo {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"No se puede abrir el archivo\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"No se puede cargar el personaje\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"Error al cargar datos de la clase\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\"No se pudo agregar una clase, ya que se alcanzó el número máximo de clases \"\n\"de {}.\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (nivel {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Historia del Chat (Mensajes: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} oro\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"¿Cuántas piezas de oro quieres retirar?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Nivel: {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Experiencia: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Nivel Máximo\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Siguiente Nivel: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} al Nivel {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Tumba del Rey Leoric\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"La Cámara de Hueso\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Un Pasadizo Oscuro\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Altar Impío\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"A {:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"¡Necesito ayuda! ¡Ven aquí!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Sígueme.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Aquí hay algo para ti.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"¡Ahora MUERES!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"¡Cúrate a ti mismo!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"¡Cuidado!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Gracias .\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"¡Retírate!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Lo siento.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Estpy esperando.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Atrás\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Daño: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Defensa: {:d}  \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Dur: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Indestructible\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Bienvenido a la\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Herrería\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Te gustaría:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Comprar\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Comprar mercancía selecta\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Vender\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Reparar\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Dejar la herrería\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Tengo esto a la venta:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Ésta es mi mercancía de primera calidad:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"No tienes nada que me interese.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"¿Qué tienes a la venta?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"No tienes nada que reparar.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"¿Qué objeto quieres reparar?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Choza de la Bruja\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Comprar\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Recargar bastones\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Dejar la choza\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"No tienes nada que recargar.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"¿Qué objeto quieres recargar?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"No tienes oro suficiente\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"No tienes espacio suficiente en el inventario\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"¿Tenemos un trato?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"¿Seguro que quieres identificar esto?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"¿Seguro que quieres comprar esto?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"¿Seguro que quieres recargar esto?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"¿Seguro que quieres vender esto?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"¿Seguro que quieres reparar esto?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt el Patapalo\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Tengo algo en venta,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"te costará 50 de oro\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"sólo echar un vistazo. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"¿Qué es lo que tienes?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Despedirte\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Esto es lo que tengo:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Irse\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Botica\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Dejar la Botica\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"El Sabio del Pueblo\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identificar objetos\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"No tienes nada que identificar.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"¿Qué objeto quieres identificar?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Este objeto es:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Hecho\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Habla con {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Hablando con {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"no está disponible\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"en el shareware\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"versión\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Chismorrear\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Taberna del Sol Naciente\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Dejar la taberna\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Examinar Alijo\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnham el Borracho\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Hablar\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Despedirte\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Tu oro: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"Error al cargar datos de texto\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"Ya existe una entrada de datos de texto para el ID \\\"{}\\\".\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Aldeano Asesinado\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Griswold el Herrero\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin el Curandero\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Aldeano Herido\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden el Tabernero\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Caín el Sabio\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Adria la Bruja\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian la Camarera\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Vaca\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester el granjero\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Loco de Remate\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Guerrero\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Arpía\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Hechicero\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Monje\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bardo\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Bárbaro\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Necrófago\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Cádaver Podrido\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Muerte Negra\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"El Caído\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Trinchante\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Pariente del Demonio\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"El Oscuro\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Esqueleto\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Hacha Cadáver\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Muerte Ardiente\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Horror\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Carroñero\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Devorador de la Plaga\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Bestia de las Sombras\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Desgarrador de Huesos\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Arquero Cadáver\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Capitán Esqueleto\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Capitán Cadáver\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Capitán Muerte Ardiente\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Capitán del Horror\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Señor Invisible\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Oculto\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Acechador\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Invisible\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Tejedor de Ilusiones\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Señor Sátiro\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Clan de Carne\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Clan de Piedra\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Clan de Fuego\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Clan Nocturno\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Maligno\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Murciélago destellante\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Murciélago oscuro\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Familiar\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Bestia Ácida\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Escupidor de Veneno\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Bestia del Foso\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Fauces de Lava\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Rey Esqueleto\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"El Carnicero\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Cacique\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Hombre de Barro\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Demonio Sapo\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"El Desollado\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Pequeño Dragón\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Babosa de la Cueva\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Pequeño Dragón Demoníaco\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Devorador\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Demonio de Magma\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Piedra de Sangre\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Piedra del Infierno\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Señor de la Lava\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Demonio Cornudo\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Corredor de Barro\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Cargador de Escarcha\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Señor de Obsidiana\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"envejecido\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Muerte Roja\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Demonio Exánime\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Balrog Zombi\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Incinerador\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Señor de las Llamas\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Fuego de Destrucción\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Quemador del Infierno\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Tormenta Roja\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Jinete de Tormenta\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Señor de las Tormentas\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Remolino\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Pariente del Demonio Bruto\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Demonio Alado\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gárgola\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Garra de Sangre\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Ala de la Muerte\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Asesino\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Guardián\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Señor del Vórtice\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Víbora de Cueva\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Dragón de Fuego\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Víbora de Oro\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Dragón Azur\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Caballero Negro\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Guardia de la Destrucción\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Señor de Acero\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Caballero de Sangre\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"El Destrozado\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"El Hueco\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Maestro del Dolor\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Tejedora de Realidad\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Súcubo\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Bruja de la Nieve\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Engendro del Infierno\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Quemador de Almas\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Consejero\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Magistrado\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Cabalista\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Defensor\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Gólem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"El Señor Oscuro\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"El Archi Exánime Maligno\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad el Débil\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar el Loco\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Derrame de Mocos\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Arzobispo Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Molestia Roja\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Jade Negro\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Señor de la Guerra de Sangre\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Demonio Hork\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"El Profanador\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Hacha Afilada de Cabeza de Hueso\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Bladeskin el Descuartizador\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Pus del Alma\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Pukerat el Inmundo\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Desgarrador de Huesos\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Rotfeast el Hambriento\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Gutshank el Veloz\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Brokenhead Bangshield\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Carnicería de Putrefacción\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Mordedura de Sombra\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Vigota\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Madeye el Muerto\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Calavera de Fuego\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Warpskull\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Lengua Sangrienta\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Rastreador de Pulsos\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Moonbender\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Cuervo de la Ira\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Comedor de Columna\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Blackash el Quemado\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Cuervo de Sombra\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Blightstone el Débil\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Bilefroth el Maestro del Foso\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Arco oscuro Piel de Sangre\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Foulwing\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Bebedor de Sombras\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Cambiador de Neblina\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Escupidor de Muerte\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Bloodgutter\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Deathshade Fleshmaul\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Warmaggot el Loco\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Glasskull el Dentado\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Añublo\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Nightwing el Frio\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Piedra de Sangre\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Piedra de Fuego Puño de Bronce\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Wrathfire el Condenado\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Firewound el Siniestro\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Barón Lodo\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Maza de acero Cuerno de Plaga\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Aullador del Caos\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Doomgrin el Podrido\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Quemador Loco\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Bonesaw el Litch\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Rompe Columna\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Hueso Afilado del Cráneo del Diablo\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Tormenta Rota\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Stormbane\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Exuda Baba\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Dorado de la Llama\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Tormenta Negra\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Ira de la Peste\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"El Desollador\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Cuerno Azul\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Engendro del Infierno del Fuego de la Disformidad\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Colmillo\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Festerskull\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Lionskull el Doblado\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Lengua Negra\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Toque Vil\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Vivora Llamenate\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Fangskin\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Witchfire el Profano\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Calavera Negra\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Corte de Alma\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Engendro del Viento\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Señor del Pozo\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Tejedor de Óxido\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Howlingire la Sombra\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Nube de la Fatalidad\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Fuego del Alma de la Luna de Sangre\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Luna de la Bruja\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Fiesta de Sangre\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Graywar el Asesino\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Juez Aterrador\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Stareye la Bruja\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Steelskull el Cazador\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"El Visir\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamphir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Bloodlust\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Webwidow\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Bailarín de la Carne\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Pico Sombrío\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Cerradura de la Condenación\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Espada Corta\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Rodela\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Porra\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Arco Corto\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Bastón Corto de Maná\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Cuchilla de carnicero\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"La Corona de los Muertos Vivientes\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Banda Empírea\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Roca Mágica\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Amuleto Óptico\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Anillo de la Verdad\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Cartel de la Taberna\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Cresta del Arlequín\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Velo de Acero\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Elixir Dorado\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Yunque de Furia\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Hongo Negro\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Cerebro\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Tomo de Hongos\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Elixir Espectral\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Piedra de Sangre\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Mapa de la Catedral\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"Oreja\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Poción Curativa\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Poción de Maná\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Pergamino de la Identidad\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Pergamino del Portal de la Ciudad\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Valor de Arkaine\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Poción Curativa Completa\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Poción de Maná Completa\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Hoja de Griswold\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Armadura de Bovino\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Bastón de Lazarus\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Pergamino de Resurrección\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Bastón Corto\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Espada\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Daga\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Bomba Rúnica\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Teodoro\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Amuleto Áurico\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Nota Rasgada 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Nota Rasgada 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Nota Rasgada 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Nota Reconstruida\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Traje Marrón\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Traje Gris\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Gorro\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Gorro Metálico\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Yelmo\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Yelmo Completo\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Corona\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Gran Yelmo\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Capa\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Andrajo\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Manto\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Túnica\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Armadura Acolchada\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Armadura de Cuero\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Armadura de Cuero Duro\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Cuero Tachonado\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Cota de Anillos\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Cota\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Cota de Malla\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Cota de Escamas\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Coraza Blindada\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Coraza\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Cota de Láminas\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Cota de Placas\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Coraza de Campaña\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Coraza Gótica\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Cota de Placas Completa\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Escudo\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Escudo Pequeño\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Escudo Grande\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Escudo de Vértices\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Escudo de la Torre\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Escudo Gótico\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Poción Rejuvenecedora\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Poción Rejuvenecedora Completa\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Aceite\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Elixir de Fuerza\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Elixir de Magia\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Elixir de Destreza\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Elixir de Vitalidad\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Pergamino de curación\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Pergamino de Búsqueda\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Pergamino de Relámpago\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Pergamino de Muro de Fuego\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Pergamino de Infierno\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Pergamino de Flash\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Pergamino de Infravisión\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Pergamino de Fase\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Pergamino de Escudo de Maná\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Pergamino de Ola de Llamas\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Pergamino de Bola de Fuego\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Pergamino de Maldición de Piedra\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Pergamino de Cadena de Relámpagos\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Pergamino de Guardián\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Pergamino de Nova\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Pergamino de Golem\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Pergamino de Teletransporte\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Pergamino de Apocalipsis\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Chafarote\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Cimitarra\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Claymore\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Hoja\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Sable\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Espada Larga\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Espada Ancha\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Espada Bastarda\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Mandoble\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Gran Espada\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Hacha Pequeña\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Hacha\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Hacha Grande\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Hacha Ancha\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Hacha de Batalla\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Gran Hacha\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Maza\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Estrella del Alba\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Martillo de Guerra\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Martillo\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Porra con puntas\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Rompecabezas\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Almádena\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Arco\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Arco de Cazador\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Arco Largo\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Arco Compuesto\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Arco Corto de Batalla\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Arco Largo de Batalla\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Arco Corto de Guerra\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Arco Largo de Guerra\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Bastón Largo\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Bastón Plegable\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Bastón de Mando\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Bastón de Guerra\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Anillo\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amuleto\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Runa de Fuego\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Runa\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Runa de Relámpago\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Gran Runa de Fuego\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Gran Runa de Relámpago\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Runa de Piedra\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Bastón Corto de la Centella\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Poción de arena\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"La Cuchilla del Carnicero\"\n\n#: Source/translation_dummy.cpp:370\nmsgid \"Lightforge\"\nmsgstr \"Forja de luz\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"El Arco de la Desaveniencia\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"El Insoportable\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"El Arco Celestial\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Cazador Mortal\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Arco de la Muerte\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"El Arco de Roble negro\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Dardo de Fuego\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Aguijoneador de Carne\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Fuerza del Viento\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Cuerno de Águila\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Puñal de Gonnagal\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"El Defensor\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Garra del Grifo\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Navaja Negra\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Luna Gibosa\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Mango de Hielo\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"La Espada del Verdugo\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"La Sierra de Hueso\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Halcón de las Sombras\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Pico de Mago\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Sable de Luz\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"La Garra del Halcón\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Infierno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Portador de Destrucción\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"El Grizzly\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"El Abuelo\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"El Destrozador\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Pico Afilado\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Asesino de Sangre\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"El Hacha Celestial\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Hacha Malvada\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Cuchilla de Piedra\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Destral de Aguinara\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Asesino del Infierno\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Atracador de Messerschmidt\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Crackrust\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Martillo de Jholm\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Garrote de Civerb\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"La Estrella Celestial\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Estrella de Baranar\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Raíz Nudosa\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"El Aplastador de Cráneo\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Martillo de Schaefer\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Brida de Ensueño\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Bastón de las Sombras\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Inmolador\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Aguja de la Tormenta\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Canción de Brillo\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Llamada de Trueno\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"El Protector\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Rompecabezas de Naj\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Mindcry\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Vara de Onan\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Yelmo de los Espíritus\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Gorro del Pensamiento\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Yelmo del Señor Supremo\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Cresta del Tonto\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"El Ocaso de los Dioses\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Aro Real\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Carne de Almas Desgarradas\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"El Flagelo del Gladiador\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"La Capa Arcoíris\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Armadura de Cuero\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Manto de la Sabiduría\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Coraza Brillante\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Caparazón de Carroñero\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Paisaje Nocturno\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Armadura Liviana de Naj\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Manto de Demonspike\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"El Deflector\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Escudo de Cráneo Dividido\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Brecha del Dragón\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Escudo de Roble Negro\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Santo Defensor\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Escudo de Tormenta\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Zarza\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Anillo de Regha\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"El Sangrante\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Anillo de Constricción\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Anillo de Compromiso\"\n\n# ** Adjetivo sensible a cambio de género, terminaciones o/a\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"de estaño\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"de latón\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"de bronce\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"de hierro\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"de acero\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"de plata\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"de platino\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"de mithril\"\n\n# **\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"meteórico\"\n\n# **\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"extraño\"\n\n# **\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"estropeado\"\n\n# **\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"mellado\"\n\n# **\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"desgastado\"\n\n# **\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"dentado\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"mortal\"\n\n# **\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"pesado\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"atroz\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"brutal\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"descomunal\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"cruel\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"implacable\"\n\n# **\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"despiadado\"\n\n# **\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"roñoso\"\n\n# **\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"mohoso\"\n\n# **\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"afilado\"\n\n# **\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"fino\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"de guerrero\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"de soldado\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"del señor\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"de caballero\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"de maestro\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"de campeón\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"real\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"frágil\"\n\n# **\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"oxidado\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"fuerte\"\n\n# **\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"grandioso\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"valiente\"\n\n# **\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"glorioso\"\n\n# **\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"bendito\"\n\n# **\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"santo\"\n\n# **\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"asombroso\"\n\n# **\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"piadoso\"\n\n# **\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"rojo\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"carmesí\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"granate\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"rubí\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"azul\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"celeste\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"lapislázuli\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"cobalto\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"zafiro\"\n\n# **\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"blanco\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"perla\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"marfil\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"cristal\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"diamante\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"topacio\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"ámbar\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"jade\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"obsidiana\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"esmeralda\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"de la hiena\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"de la rana\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"de la araña\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"del cuervo\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"de la culebra\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"de la serpiente\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"del pequeño dragón\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"del dragón\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"del gran dragón\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"de la hidra\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"del ángel\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"del arcángel\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"cuantioso\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"colmado\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"llameante\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"centelleante\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"de la calidad\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"de la mutilación\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"del asesinato\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"de sangre\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"de la matanza\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"de la tortura\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"del dolor\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"del llanto\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"de salud\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"de protección\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"de absorción\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"de desvío\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"de ósmosis\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"de la endeblez\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"de la debilidad\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"de fuerza\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"del poder\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"del buey\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"del gigante\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"del titán\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"de la parálisis\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"de la atrofia\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"de la destreza\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"de la habilidad\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"de la exactitud\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"de la precisión\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"de la perfección\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"del mentecato\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"de la dislexia\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"de la energía\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"de la mente\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"de la brillantez\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"de la brujería\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"de la hechicería\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"de la dolencia\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"de la enfermedad\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"de la vitalidad\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"de la vivacidad\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"del brío\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"del vigor\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"de la vida\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"del problema\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"del hoyo\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"del cielo\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"de la luna\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"de las estrellas\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"de los cielos\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"del zodiaco\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"del buitre\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"del chacal\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"del zorro\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"del jaguar\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"del águila\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"del lobo\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"del tigre\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"del león\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"del mamut\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"de la ballena\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"de la fragilidad\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"de la inconsistencia\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"de la robustez\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"de la artesanía\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"de la solidez\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"de las eras\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"de la oscuridad\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"de la noche\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"de la luz\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"del resplandor\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"de la llama\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"del fuego\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"de la combustión\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"de la conmoción\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"del relámpago\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"del trueno\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"de la abundancia\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"de la infinidad\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"de espinas\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"de la corrupción\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"del ladrón\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"del oso\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"del murciélago\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"del vampiro\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"de la sanguijuela\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"de la langosta\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"de la perforación\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"del pinchazo\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"del golpe\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"de la buena voluntad\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"de la presteza\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"de la velocidad\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"de la rapidez\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"del equilibrio\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"de la estabilidad\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"de la armonía\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"de bloqueo\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"La Roca Mágica\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad el Débil\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar el Loco\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"El Carnicero\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Signo de Ogden\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Pasillos de los Ciegos\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Valor\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Señor de la Guerra de Sangre\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"La Maldición del Rey Leoric\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Arzobispo Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Asuntos de Tumbas\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Huerto del Granjero\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Niñita\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Comerciante Errante\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"El Profanador\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"El Jersey de Jersey\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Flecha de fuego\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Curación\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Rayo\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Destello\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identificar\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Muro de Fuego\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Portal al pueblo\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Maldición de Piedra\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infravisión\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Ajuste de Fase\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Escudo de Maná\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Bola de Fuego\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Guardián\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Cadena de Relámpagos\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Ola de Llamas\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Serpientes de la Condenación\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Ritual de Sangre\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Invisibilidad\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Infierno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Gólem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Furia\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teletransporte\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apocalipsis\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Etéreo\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Reparación de Artículo\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Recarga de Bastón\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Desarmar Trampa\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elemental\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Rayo Cargado\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Rayo Santo\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Resucitar\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telequinesis\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Sanar a Otros\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Estrella de Sangre\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Espíritu de Hueso\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ah, la historia de nuestro Rey, ¿verdad? La trágica caída de Leoric fue un \"\n\"duro golpe para esta tierra. La gente siempre amó al Rey, y ahora vive con \"\n\"un miedo mortal hacia él. La pregunta que me sigo haciendo es cómo pudo \"\n\"haber caído tan lejos de la Luz, ya que Leoric siempre había sido el más \"\n\"santo de los hombres. Sólo los poderes más viles del Infierno podrían \"\n\"destruir tan completamente a un hombre desde dentro ...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"¡El pueblo necesita tu ayuda, buen maestro! Hace algunos meses, el hijo del \"\n\"rey Leoric, el Príncipe Albrecht, fue secuestrado. El rey se enfureció y \"\n\"recorrió el pueblo en busca de su hijo desaparecido. Con cada día que \"\n\"pasaba, Leoric parecía hundirse cada vez más en la locura. Trató de culpar a \"\n\"los habitantes inocentes de la desaparición del niño y los ejecutó \"\n\"brutalmente. Menos de la mitad de nosotros sobrevivimos a su locura ...\\n\"\n\" \\n\"\n\"Los Caballeros y Sacerdotes del Rey intentaron aplacarlo, pero él se volvió \"\n\"contra ellos y, lamentablemente, se vieron obligados a matarlo. Con su \"\n\"último aliento, el Rey lanzó una terrible maldición sobre sus antiguos \"\n\"seguidores. Juró que lo servirían en la oscuridad para siempre ...\\n\"\n\" \\n\"\n\"¡Aquí es donde las cosas toman un giro aún más oscuro de lo que creía \"\n\"posible! Nuestro antiguo Rey se ha levantado de su sueño eterno y ahora \"\n\"comanda una legión de esbirros de muertos vivientes dentro del Laberinto. Su \"\n\"cuerpo fue enterrado en una tumba tres niveles debajo de la Catedral. Por \"\n\"favor, buen maestro, tranquilice su alma destruyendo su forma ahora \"\n\"maldita ...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Como le dije, buen maestro, el Rey fue sepultado tres niveles más abajo. \"\n\"Está ahí abajo, esperando en la pútrida oscuridad su oportunidad de destruir \"\n\"esta tierra ...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"La maldición de nuestro Rey ha terminado, pero me temo que fue solo una \"\n\"parte de un mal mayor en acción. Sin embargo, aún podemos salvarnos de la \"\n\"oscuridad que consume nuestra tierra, porque tu victoria es un buen augurio. \"\n\"Que la Luz te guíe en tu camino, buen maestro.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"La pérdida de su hijo fue demasiado para el Rey Leoric. Hice lo que pude \"\n\"para aliviar su locura, pero al final lo superó. Una maldición negra se \"\n\"cierne sobre este reino desde ese día, pero tal vez si liberaras su espíritu \"\n\"de su prisión terrenal, la maldición se levantaría ...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"No me gusta pensar en cómo murió el Rey. Me gusta recordarlo como el \"\n\"gobernante amable y justo que era. Su muerte fue tan triste y parecía muy \"\n\"mal, de alguna manera.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Hice muchas de las armas y la mayor parte de las armaduras que el rey Leoric \"\n\"usó para equipar a sus caballeros. Incluso le elaboré una enorme espada a \"\n\"dos manos del mejor mithril, así como una corona de campo a juego. Todavía \"\n\"no puedo creer cómo murió ¡Pero debe haber sido alguna fuerza siniestra lo \"\n\"que lo volvió loco!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Eso no me importa. Escucha, ningún esqueleto será MI rey. Leoric es el Rey. \"\n\"Rey, ¿me escuchas? ¡VIVA EL REY!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Los muertos que caminan entre los vivos siguen al Rey maldito. Tiene el \"\n\"poder de crear aún más guerreros para un ejército de muertos vivientes en \"\n\"constante crecimiento. Si no detienes su reinado, seguramente marchará a \"\n\"través de esta tierra y matará a todos los que todavía viven aquí.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Mira, tengo un negocio aquí. No vendo información, y no me importa un Rey \"\n\"que ha estado muerto más tiempo que yo vivo. Si necesitas algo para usar \"\n\"contra este Rey de los muertos vivientes, entonces puedo ayudarte ...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"El calor de la vida ha entrado en mi tumba. ¡Prepárate, mortal, para servir \"\n\"a mi Maestro por la eternidad!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Veo que este comportamiento extraño también te desconcierta. Supongo que, \"\n\"dado que muchos demonios temen la luz del sol y creen que tienen un gran \"\n\"poder, es posible que el sol naciente representado en el letrero del que \"\n\"hablas les haya llevado a creer que también tiene algunos poderes arcanos. \"\n\"Mmm, quizás no todos sean tan inteligentes como nos temíamos ...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Maestro, tengo una experiencia extraña que contarle. Sé que tiene un gran \"\n\"conocimiento de esas monstruosidades que habitan el laberinto, y esto es \"\n\"algo que no puedo entender, por mi vida ... Me desperté durante la noche por \"\n\"un sonido de rascado justo afuera de mi taberna. Cuando miré desde mi \"\n\"habitación, vi las formas de pequeñas criaturas parecidas a demonios en el \"\n\"patio de la posada. Poco tiempo después, se fueron corriendo, no sin antes \"\n\"robar el cartel de mi posada. No sé por qué los demonios robarían mi cartel \"\n\"y dejarían a mi familia en paz ... es extraño, ¿no?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Oh, no tenías que traer mi letrero, pero supongo que me ahorra el gasto de \"\n\"hacer otro. Bueno, déjame ver, ¿qué puedo darte como tarifa por encontrarlo? \"\n\"Hmmm, qué tenemos aquí ... ¡ah, sí! Este gorro fue dejado en una de las \"\n\"habitaciones por un mago que se quedó aquí hace algún tiempo. Quizás pueda \"\n\"tener algún valor para ti.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Dios mío, los demonios que corren por la aldea de noche, saquean nuestras \"\n\"casas, ¿no es nada sagrado? Espero que Ogden y Garda estén bien. Supongo que \"\n\"vendrían a verme si les hubieran hecho daño ...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"¡Oh Dios! ¿Es ahí donde fue el letrero? Mi Abuela y yo debimos haber dormido \"\n\"todo el rato. Gracias a la Luz que esos monstruos no atacaron la posada.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"¿Dices que los demonios robaron el letrero de Ogden? Eso no se parece mucho \"\n\"a las atrocidades de las que he oído, o visto. \\n\"\n\" \\n\"\n\"A los demonios les preocupa arrancarte el corazón, no tu letrero.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"¿Sabes lo que pienso? Alguien tomó ese letrero y querrán mucho dinero por \"\n\"él. Si yo fuera Ogden ... y no lo soy, pero si fuera ... compraría un nuevo \"\n\"cartel con un bonito dibujo. Quizás una buena jarra de cerveza o un trozo de \"\n\"queso ...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Ningún mortal puede comprender verdaderamente la mente del demonio. \\n\"\n\" \\n\"\n\"Nunca dejes que sus acciones erráticas te confundan, ya que ese también \"\n\"puede ser su plan.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"¿Qué? ¿Está diciendo que me llevé eso? Supongo que Griswold también está de \"\n\"su lado. \\n\"\n\" \\n\"\n\"Mira, superé el simple robo de letreros hace meses. No puede obtener \"\n\"ganancias con un trozo de madera.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"¡Oye, tú eres el que mata a todos! ¡Consígueme el Estandarte Mágico o \"\n\"atacamos! ¡No dejes con vida! Matas a los grandes feos y devuelves la magia. \"\n\"Pasa la esquina y la puerta, encuentra a los feos. ¡Das, te vas!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Matas a los feos, obtienes estandarte. Me lo traes, o si no ...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"¡Das! ¡Si, bien! Vete ahora, somos fuertes. ¡Matamos a todos con gran Magia!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Esto no augura nada bueno, ya que confirma mis temores más oscuros. Si bien \"\n\"no me permití creer las leyendas antiguas, no puedo negarlas ahora. Quizás \"\n\"ha llegado el momento de revelar quién soy.\\n\"\n\" \\n\"\n\"Mi verdadero nombre es Deckard Cain el Sabio, y soy el último descendiente \"\n\"de una antigua Hermandad que se dedicó a salvaguardar los secretos de un mal \"\n\"atemporal. Un mal que obviamente ahora se ha liberado.\\n\"\n\" \\n\"\n\"El arzobispo Lazarus, una vez el consejero más confiable del Rey Leoric, \"\n\"condujo a un grupo de simples habitantes del pueblo al Laberinto para \"\n\"encontrar al hijo desaparecido del Rey, Albrecht. Pasó bastante tiempo antes \"\n\"de que regresaran, y solo unos pocos escaparon con vida.\\n\"\n\" \\n\"\n\"¡Maldito sea por tonto! Entonces debería haber sospechado su velada \"\n\"traición. Debe haber sido el mismo Lazarus quien secuestró a Albrecht y \"\n\"desde entonces lo ha escondido dentro del Laberinto. No entiendo por qué el \"\n\"Arzobispo se volvió hacia la oscuridad, ni cuál es su interés en el niño. ¡a \"\n\"menos que tenga la intención de sacrificarlo a sus amos oscuros!\\n\"\n\" \\n\"\n\"¡Eso debe ser lo que ha planeado! Los sobrevivientes de su 'grupo de \"\n\"rescate' dicen que Lazarus fue visto por última vez corriendo hacia las \"\n\"entrañas más profundas del laberinto. ¡Debes darte prisa y salvar al \"\n\"príncipe de la espada sacrifical de este demonio demente!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Debes darte prisa y rescatar a Albrecht de las manos de Lazarus. ¡El \"\n\"príncipe y la gente de este reino cuentan contigo!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Tu historia es bastante sombría, amigo. Lazarus seguramente arderá en el \"\n\"Infierno por su horrible acto. El chico que describe no es nuestro príncipe, \"\n\"pero creo que Albrecht aún puede estar en peligro. El símbolo de poder del \"\n\"que hablas debe ser un portal en el corazón mismo del laberinto.\\n\"\n\" \\n\"\n\"Debes saber esto, amigo mío: el mal contra el que te mueves es el oscuro \"\n\"Señor del Terror. Es conocido por los hombres mortales como Diablo. Fue él \"\n\"quien fue encarcelado dentro del Laberinto hace muchos siglos y me temo que \"\n\"busca sembrar una vez más el caos en el reino de la humanidad. ¡Debes \"\n\"aventurarte a través del portal y destruir a Diablo antes de que sea \"\n\"demasiado tarde!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus fue el Arzobispo que condujo a muchos de los habitantes del pueblo \"\n\"al laberinto. Ese día perdí muchos buenos amigos y Lazarus nunca regresó. \"\n\"Supongo que lo mataron junto con la mayoría de los demás. Si quiere hacerme \"\n\"un favor, buen maestro, por favor no hable con Farnham sobre ese día.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Me sorprendió cuando me enteré de lo que la gente del pueblo planeaba hacer \"\n\"esa noche. Pensé que, de todas las personas, Lazarus habría tenido más \"\n\"sentido común. Era Arzobispo y siempre pareció preocuparse mucho por la \"\n\"gente del pueblo de Tristram. Tantos resultaron heridos, no pude salvarlos a \"\n\"todos ...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Recuerdo a Lazarus como un hombre muy amable y generoso. Habló en el funeral \"\n\"de mi madre y nos apoyó a mi abuela y a mí en un momento muy difícil. Rezo \"\n\"todas las noches para que, de alguna manera, todavía esté vivo y a salvo.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Estaba allí cuando Lazarus nos condujo al laberinto. Habló de la santa \"\n\"retribución, pero cuando empezamos a luchar contra esos engendros del \"\n\"infierno, ni siquiera levantó su maza contra ellos. ¡Simplemente corrió más \"\n\"profundamente en las oscuras e interminables cámaras que estaban llenas de \"\n\"los sirvientes de la oscuridad!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Te apuñalan, luego muerden y luego te rodean. ¡Mentiroso! ¡MENTIROSO! ¡Están \"\n\"todos muertos! ¡Muertos! ¿Me escuchas? Siguen cayendo y cayendo ... su \"\n\"sangre se derrama por todo el suelo ... todo es culpa suya ...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"No conocía a este Lazarus de quien hablas, pero siento un gran conflicto \"\n\"dentro de su ser. Representa un gran peligro y no se detendrá ante nada para \"\n\"servir a los poderes de las tinieblas que lo han reclamado como suyo.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Sí, el justo Lazarus, que fue taaan eficaz contra esos monstruos de allí. No \"\n\"ayudó a salvar mi pierna, ¿verdad? Mira, te daré un consejo gratis. \"\n\"Pregúntale a Farnham, él estaba allí.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Abandona tu tonta búsqueda. ¡Todo lo que les espera es la ira de mi Maestro! \"\n\"Es demasiado tarde para salvar al niño. ¡Ahora te unirás a él en el Infierno!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, no sé qué puedo decirte realmente que sea de alguna ayuda. El agua que \"\n\"llena nuestros pozos proviene de un manantial subterráneo. He oído hablar de \"\n\"un túnel que conduce a un gran lago - tal vez sean lo mismo. \"\n\"Desafortunadamente, no sé qué pasaría si nuestro suministro de agua \"\n\"estuviera contaminado.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Siempre he tratado de mantener una gran cantidad de alimentos y bebidas en \"\n\"nuestro sótano de almacenamiento, pero como todo el pueblo no tiene una \"\n\"fuente de agua dulce, incluso nuestras tiendas se secarán pronto. \\n\"\n\" \\n\"\n\"Por favor, haz lo que puedas o no sé qué haremos.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"¡Me alegro de haberte encontrado a tiempo! Nuestros pozos se han vuelto \"\n\"salobres, estancados y algunos de los habitantes del pueblo han enfermado al \"\n\"beber de ellos. Nuestras reservas de agua dulce se están secando \"\n\"rápidamente. Creo que hay un pasadizo que conduce a los manantiales que \"\n\"sirven a nuestro pueblo. Por favor, averigua qué ha causado esta calamidad, \"\n\"o seguramente todos moriremos.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Por favor, debes darse prisa. Cada hora que pasa nos acerca a no tener agua \"\n\"para beber. \\n\"\n\" \\n\"\n\"No podemos sobrevivir por mucho tiempo sin tu ayuda.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"¿Qué dices? ¿La mera presencia de los demonios provocó que el agua se \"\n\"contaminara? Oh, verdaderamente un gran mal acecha debajo de nuestro pueblo, \"\n\"pero tu perseverancia y coraje nos dan esperanza. Por favor, toma este \"\n\"anillo, tal vez te ayude a destruir a esas criaturas tan viles.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Mi abuela está muy débil y Garda dice que no podemos beber el agua de los \"\n\"pozos. Por favor, ¿puedes hacer algo para ayudarnos?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin te ha dicho la verdad. Necesitaremos agua dulce con urgencia, y \"\n\"pronto. He intentado limpiar uno de los pozos más pequeños, pero huele a \"\n\"suciedad estancada. Debe estar obstruido en la fuente.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"¿Tu bebes agua?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"La gente de Tristram morirá si no puedes devolver agua fresca a sus pozos. \\n\"\n\" \\n\"\n\"Sepa esto: los demonios están en el centro de este asunto, pero siguen \"\n\"ignorando lo que han engendrado.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Por una vez, estoy contigo. Mi negocio se seca, por así decirlo, si no tengo \"\n\"un mercado al que vender. ¡Será mejor que averigüe lo que está pasando, y \"\n\"pronto!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"¿Un libro que habla de una cámara de huesos humanos? Bueno, una Cámara de \"\n\"Hueso se menciona en ciertos escritos arcaicos que estudié en las \"\n\"bibliotecas del Este. Estos tomos inferían que cuando los Señores del \"\n\"inframundo desearan proteger grandes tesoros, crearían dominios donde \"\n\"aquellos que murieran en el intento de robar ese tesoro estarían obligados a \"\n\"defenderlo para siempre. ¿Un final retorcido, pero extrañamente apropiado?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Me temo que no sé nada de eso, buen maestro. Caín tiene muchos libros que \"\n\"pueden ser de alguna ayuda.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"Parece un lugar muy peligroso. Si te aventuras allí ten mucho cuidado.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Me temo que no he escuchado nada al respecto. Quizás Caín el Narrador podría \"\n\"ser de alguna ayuda.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"No sé nada de este lugar, pero puedes intentar preguntarle a Caín. Habla de \"\n\"muchas cosas y no me sorprendería que tuviera algunas respuestas a tu \"\n\"pregunta.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Bien, escucha. Ahí está esta cámara de madera ¿ves? Y su esposa, ya sabes, \"\n\"ella, le dice al árbol ... porque tienes que esperar. Entonces digo, eso \"\n\"podría funcionar en su contra, pero si crees que voy a PAGAR por esto ... \"\n\"tú ... eh ... sí.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Te convertirás en un sirviente eterno de los señores oscuros si pereces \"\n\"dentro de este dominio maldito. \\n\"\n\" \\n\"\n\"Ingresa a la Cámara de Hueso bajo tu propio riesgo.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"¿Un tesoro vasto y misterioso, dices? Tal vez podría estar interesado en \"\n\"recoger algunas cosas de ti ... o mejor aún, ¿no necesita algunos \"\n\"suministros raros y costosos para superar este calvario?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Parece que el Arzobispo Lazarus incitó a muchos de los habitantes del pueblo \"\n\"a aventurarse en el Laberinto para encontrar al hijo desaparecido del Rey. \"\n\"Jugó con sus miedos y los convirtió en una multitud frenética. Ninguno de \"\n\"ellos estaba preparado para lo que había dentro de la tierra fría ... \"\n\"Lazarus los abandonó allí - dejados en las garras de indescriptibles \"\n\"horrores - para morir.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Sí, Farnham ha murmurado algo sobre un enorme bruto que empuñaba un arma \"\n\"feroz. Creo que lo llamó carnicero.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Por la Luz, conozco a este vil demonio. Hubo muchos que llevaron las \"\n\"cicatrices de su ira en sus cuerpos cuando los pocos supervivientes de la \"\n\"carga encabezada por Lazarus salieron arrastrándose de la Catedral. No sé \"\n\"qué utilizó para cortar a sus víctimas, pero no pudo haber sido de este \"\n\"mundo. Dejó heridas infectadas por la enfermedad e incluso yo las encontré \"\n\"casi imposibles de tratar. Cuidado si planeas luchar contra este demonio ...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Cuando Farnham dijo algo sobre un carnicero matando gente, inmediatamente lo \"\n\"descarté. Pero ya que lo mencionaste, tal vez sea cierto.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Vi lo que Farnham llama el Carnicero mientras se abría camino a través de \"\n\"los cuerpos de mis amigos. Blandió una cuchilla del tamaño de un hacha, \"\n\"cortando miembros y cortando a hombres valientes donde estaban. Me separaron \"\n\"de la refriega una multitud de pequeños demonios que chillaban y, de alguna \"\n\"manera, encontré la escalera que conducía hacia afuera. Nunca volví a ver a \"\n\"esa horrible bestia, pero su rostro manchado de sangre me persigue hasta el \"\n\"día de hoy.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"¡Grande! Una cuchilla grande matando a todos mis amigos. No pude detenerlo, \"\n\"tuve que huir, no pude salvarlos. Atrapado en una habitación con tantos \"\n\"cuerpos ... tantos amigos ... ¡NOOOOOOOOOO!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"El Carnicero es una criatura sádica que se deleita con la tortura y el dolor \"\n\"de los demás. Has visto su obra en el borracho Farnham. Su destrucción hará \"\n\"mucho para garantizar la seguridad de esta aldea.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Sé más de lo que piensas sobre ese demonio espantoso. Sus amiguitos me \"\n\"agarraron y lograron sacarme la pierna antes de que Griswold me sacara de \"\n\"ese agujero. \\n\"\n\" \\n\"\n\"Lo diré sin rodeos: mátalo antes de que te mate y agregue tu cadáver a su \"\n\"colección.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Por favor escúchame. El arzobispo Lazarus, nos llevó hasta aquí para \"\n\"encontrar al príncipe perdido. ¡El bastardo nos llevó a una trampa! Ahora \"\n\"todo el mundo está muerto ... asesinados por un demonio que llamó el \"\n\"Carnicero. ¡Vénganos! Encuentra a este Carnicero y mátalo para que nuestras \"\n\"almas finalmente descansen ...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Recitas una rima interesante escrita en un estilo que me recuerda a otras \"\n\"obras. Déjame pensar ahora, ¿qué fue?\\n\"\n\" \\n\"\n\"... La oscuridad envuelve lo Oculto. Ojos que brillan sin ser vistos con \"\n\"solo el sonido de las garras como navajas raspando brevemente para \"\n\"atormentar a esas pobres almas que han quedado ciegas por toda la eternidad. \"\n\"La prisión para los condenados se llama las Cámaras de los Ciegos ...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Nunca me interesó mucho la poesía. De vez en cuando, tenía motivos para \"\n\"contratar juglares cuando la posada iba bien, pero eso parece que fue hace \"\n\"mucho tiempo. \\n\"\n\" \\n\"\n\"¿Qué? Oh, sí ... eh, bueno, supongo que podrías ver lo que alguien más sabe.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Esto parece familiar, de alguna manera. Me parece recordar haber leído algo \"\n\"muy parecido a ese poema mientras investigaba la historia de las aflicciones \"\n\"demoníacas. Hablaba de un lugar de gran maldad que ... espera, no vas a ir \"\n\"allí, ¿verdad?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Si tienes preguntas sobre la ceguera, debes hablar con Pepin. Sé que le dio \"\n\"a mi abuela una poción que ayudó a aclarar su visión, así que tal vez él \"\n\"también pueda ayudarte.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Me temo que no he escuchado ni visto un lugar que coincida con su vívida \"\n\"descripción, amigo mío. Quizás Caín el Narrador podría ser de alguna ayuda.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\"Mira aquí ... eso es muy gracioso, ¿eh? ¿Conseguirlo? Ciego, ¿mira aquí?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Este es un lugar de gran angustia y terror, y por eso sirve bien a su amo. \\n\"\n\" \\n\"\n\"Pisa con cuidado o puede que tu mismo te quedes mucho más tiempo de lo que \"\n\"habías anticipado.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Veamos, ¿te estoy vendiendo algo? No. ¿Me estás dando dinero para contarte \"\n\"esto? No. ¿Ahora te vas y vas a hablar con el narrador que vive para este \"\n\"tipo de cosas? Si.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"¿Afirmas haber hablado con Lachdanan? Fue un gran héroe durante su vida. \"\n\"Lachdanan fue un hombre honorable y justo que sirvió fielmente a su Rey \"\n\"durante años. Pero claro, eso ya lo sabes.\\n\"\n\" \\n\"\n\"De aquellos que quedaron atrapados en las garras de la Maldición del Rey, \"\n\"Lachdanan sería el menos propenso a someterse a la oscuridad sin luchar, así \"\n\"que supongo que tu historia podría ser cierta. Si estuviera en tu lugar, \"\n\"amigo mío, encontraría la manera de liberarlo de su tortura.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"¡Hablas de un valiente guerrero muerto hace mucho tiempo! No diré nada de \"\n\"hablar con los difuntos en el patio de mi posada, muchas gracias.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Un elixir dorado, dices. Nunca antes había preparado una poción de ese \"\n\"color, así que no puedo decirte cómo te afectaría si intentaras beberla. \"\n\"Como su sanador, le recomiendo encarecidamente que, si encuentra un elixir \"\n\"de este tipo, haga lo que le pide Lachdanan y NO trate de usarlo.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Nunca antes había oído hablar de un Lachdanan. Lo siento, pero no creo que \"\n\"pueda ser de mucha ayuda.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Si realmente es Lachdanan a quien encontraste, te aconsejo que lo ayudes. \"\n\"Traté con él en varias ocasiones y descubrí que era honesto y leal por \"\n\"naturaleza. La maldición que cayó sobre los seguidores del Rey Leoric caería \"\n\"especialmente sobre él.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan está muerto. Todo el mundo lo sabe, y no puedes engañarme para \"\n\"que piense de otra manera. No puedes hablar con los muertos. ¡Lo sé!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Es posible que encuentres a personas atrapadas dentro del Laberinto, como \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"Siento en él honor y una gran culpa. Ayúdale y ayudarás a todo Tristram.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Espera, déjame adivinar. Cain fue tragado por una gigantesca fisura que se \"\n\"abrió debajo de él. Fue incinerado en una bola de fuego del infierno y ya no \"\n\"puede responder a tus preguntas. Oh, ¿no es eso lo que pasó? Entonces \"\n\"supongo que comprarás algo o seguirás tu camino.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Por favor, no me mates, solo escúchame. Una vez fui Capitán de los \"\n\"Caballeros del Rey Leoric, defendiendo las leyes de esta tierra con justicia \"\n\"y honor. Entonces su oscura Maldición cayó sobre nosotros por el papel que \"\n\"jugamos en su trágica muerte. Mientras mis compañeros Caballeros sucumbían a \"\n\"su retorcido destino, huí de la cámara funeraria del Rey, buscando alguna \"\n\"forma de liberarme de la Maldición. Fallé...\\n\"\n\" \\n\"\n\"He oído hablar de un Elixir Dorado que podría levantar la Maldición y \"\n\"permitir que mi alma descanse, pero no he podido encontrarlo. Mi fuerza \"\n\"ahora se desvanece, y con ella también lo último de mi humanidad. Por favor \"\n\"ayúdame y encuentra el Elixir. Te pagaré tus esfuerzos, lo juro por mi honor.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"No has encontrado el Elixir Dorado. Temo estar condenado por la eternidad. \"\n\"Por favor, sigue intentándolo ...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Has salvado mi alma de la condenación, y por eso estoy en deuda contigo. Si \"\n\"alguna vez hay una forma de recompensarte desde más allá de la tumba, la \"\n\"encontraré, pero por ahora, toma mi yelmo. En el viaje que estoy a punto de \"\n\"emprender, lo utilizaré poco. Que te proteja contra los poderes oscuros de \"\n\"abajo. Ve con la Luz, amigo mío ...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold habla de El yunque de la furia, un artefacto legendario buscado \"\n\"durante mucho tiempo, pero nunca encontrado. Elaborado a partir de los \"\n\"huesos metálicos de los demonios del Pozo de la Navaja, el Yunque de la \"\n\"Furia se fundió alrededor de los cráneos de los cinco magos más poderosos \"\n\"del inframundo. Tallado con runas de poder y caos, cualquier arma o armadura \"\n\"forjada en este Yunque se sumergirá en el reino del Caos, dándole \"\n\"propiedades mágicas. Se dice que la naturaleza impredecible del Caos \"\n\"dificulta saber cuál será el resultado de esta herrería ...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"¿No crees que Griswold sería una mejor persona para preguntarle sobre esto? \"\n\"Es bastante hábil, ¿sabes?.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Si hubiera estado buscando información sobre el Mortero de Curación o el \"\n\"Cáliz de Plata de la Purificación, podría haberte ayudado, amigo mío. Sin \"\n\"embargo, en este asunto, sería mejor que hablaras con Griswold o Caín.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"El padre de Griswold solía contarnos a algunos de nosotros, cuando éramos \"\n\"pequeños, acerca de un yunque gigante que se usaba para fabricar armas \"\n\"poderosas. Dijo que cuando se golpeaba un martillo en este yunque, el suelo \"\n\"temblaba con gran furia. Cada vez que la tierra se mueve, siempre recuerdo \"\n\"esa historia.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"¡Saludos! ¡Siempre es un placer ver a uno de mis mejores clientes! Sé que te \"\n\"has estado aventurando más profundamente en el Laberinto, y hay una historia \"\n\"que me contaron que puede que valga la pena escucharla ...\\n\"\n\" \\n\"\n\"Uno de los hombres que regresó del Laberinto me habló de un yunque místico \"\n\"que encontró durante su fuga. Su descripción me recordó las leyendas que \"\n\"había escuchado en mi juventud sobre la ardiente Forja Infernal donde se \"\n\"fabrican poderosas armas mágicas. ¡La leyenda decía que en lo profundo de la \"\n\"Forja Infernal descansaba el Yunque de la Furia! Este Yunque contenía la \"\n\"esencia misma del inframundo demoníaco ...\\n\"\n\" \\n\"\n\"Se dice que cualquier arma fabricada sobre el Yunque en llamas está imbuida \"\n\"de un gran poder. Si este yunque es de hecho el Yunque de la Furia, ¡podría \"\n\"crearte en un arma capaz de derrotar incluso al señor más oscuro del \"\n\"infierno! \\n\"\n\" \\n\"\n\"¡Encuentra el Yunque para mí y me pondré manos a la obra!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Nada todavía, ¿eh? Bueno, sigue buscando. Un arma forjada en el Yunque \"\n\"podría ser tu mejor esperanza, y estoy seguro de que puedo crearte una de \"\n\"proporciones legendarias.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"¡Casi no puedo creerlo! Este es el Yunque de la Furia. Buen trabajo, amigo. \"\n\"¡Ahora les mostraremos a esos bastardos que no hay armas en el infierno más \"\n\"mortíferas que las fabricadas por los hombres! Toma esto y que la Luz te \"\n\"proteja.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold no puede vender su yunque. ¿Qué hará entonces? ¡Y también me \"\n\"enojaría si alguien me quitara el yunque!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Hay muchos artefactos dentro del Laberinto que tienen poderes más allá de la \"\n\"comprensión de los mortales. Algunos de estos tienen un poder fantástico que \"\n\"puede ser utilizado tanto por la Luz como por la Oscuridad. Asegurar el \"\n\"Yunque desde abajo podría cambiar el curso de la Guerra del Pecado hacia la \"\n\"Luz.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Si encuentras este artefacto para Griswold, podrías poner en serios \"\n\"problemas a mi negocio. Awwww, nunca lo encontrarás.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"La Puerta de la Sangre y las Cámaras del Fuego son hitos de origen místico. \"\n\"Dondequiera que resida este libro que lea, seguramente es un lugar de gran \"\n\"poder.\\n\"\n\" \\n\"\n\"Las leyendas hablan de un pedestal que está tallado en piedra de obsidiana y \"\n\"tiene un charco de sangre hirviendo sobre su superficie incrustada de \"\n\"huesos. También hay alusiones a unas Piedras de sangre que abrirán una \"\n\"puerta que guarda un antiguo tesoro ...\\n\"\n\" \\n\"\n\"La naturaleza de este tesoro está envuelta en especulaciones, amigo mío, \"\n\"pero se dice que el antiguo héroe Arkaine colocó la armadura sagrada Valor \"\n\"en una bóveda secreta. Arkaine fue el primer mortal en cambiar el rumbo de \"\n\"la Guerra del Pecado y perseguir a las legiones de la oscuridad de regreso a \"\n\"los Infiernos Ardientes.\\n\"\n\" \\n\"\n\"Justo antes de que Arkaine muriera, su armadura estaba escondida en una \"\n\"bóveda secreta. Se dice que cuando se necesite de nuevo esta armadura \"\n\"sagrada, un héroe se levantará para don Valor una vez más. Quizás eres ese \"\n\"héroe ...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Todos los niños escuchan la historia del guerrero Arkaine y su armadura \"\n\"mística conocida como Valor. Si pudieras encontrar su lugar de descanso, \"\n\"estarías bien protegido contra el mal en el Laberinto.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm ... suena como algo que debería recordar, pero he estado tan ocupado \"\n\"aprendiendo nuevas curas y creando mejores elixires que debí haberlo \"\n\"olvidado. Lo siento ...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"La historia de la armadura mágica llamada Valor es algo de lo que a menudo \"\n\"escuché decir a los chicos. Será mejor que pregunte a uno de los hombres del \"\n\"pueblo.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"La armadura conocida como Valor podría ser la que incline la balanza a tu \"\n\"favor. Les diré que muchos lo han buscado, incluyéndome a mí. Arkaine lo \"\n\"escondió bien, amigo mío, y se necesitará más que un poco de suerte para \"\n\"descubrir los secretos que lo han mantenido oculto, oh, he aquí hace muchos \"\n\"años.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz ...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Si encuentras estas Piedras de Sangre, úsalas con cuidado. \\n\"\n\" \\n\"\n\"El camino está plagado de peligros y tu única esperanza reside en la \"\n\"confianza en ti mismo.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"¿Tienes la intención de encontrar la armadura conocida como Valor? \\n\"\n\" \\n\"\n\"Nadie ha descubierto nunca dónde escondió Arkaine las cosas, y si mis \"\n\"contactos no pudieron encontrarlo, dudo seriamente que tú tampoco lo hagas.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Solo conozco una leyenda que habla de un guerrero como el que usted \"\n\"describe. Su historia se encuentra dentro de las antiguas crónicas de la \"\n\"Guerra del Pecado ...\\n\"\n\" \\n\"\n\"Manchado por mil años de guerra, sangre y muerte, el Señor de la Guerra de \"\n\"la Sangre se alza sobre una montaña de sus destrozadas víctimas. Su espada \"\n\"oscura grita una maldición negra a los vivos; una torturada invitación a \"\n\"cualquiera que se presente ante este Verdugo del Infierno.\\n\"\n\" \\n\"\n\"También está escrito que, aunque una vez fue un mortal que luchó junto a la \"\n\"Legión de la Oscuridad durante la Guerra del Pecado, perdió su humanidad \"\n\"debido a su insaciable hambre de sangre.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Me temo que no he oído nada sobre un guerrero tan despiadado, buen maestro. \"\n\"Espero que no tengas que pelear con él, porque parece extremadamente \"\n\"peligroso.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain podría contarte mucho más sobre algo como esto de lo que yo jamás \"\n\"desearía saber.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Si vas a luchar contra un oponente tan feroz, que la Luz sea tu guía y tu \"\n\"defensora. Te llevaré en mis pensamientos.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Leyendas oscuras y malvadas rodean al único Señor de la Guerra de la Sangre. \"\n\"Debes estar bien preparado, amigo mío, porque no muestra piedad ni cuartel.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"¿Siempre tienes que hablar de Sangre? ¿Qué pasa con las flores, el sol y esa \"\n\"chica bonita que trae las bebidas? Escucha, amigo, eres obsesivo, ¿lo sabías?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Su destreza con la espada es asombrosa, y ha vivido durante miles de años \"\n\"conociendo solo la guerra. Lo siento ... no puedo ver si lo derrotarás.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Nunca he tratado con este Señor de la Guerra del que hablas, pero parece que \"\n\"necesite muchas espadas. No me importaría abastecer a sus ejércitos ...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Mi espada canta por tu sangre, mortal, y mis oscuros maestros no la negarán.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold habla de la Piedra del Cielo que estaba destinada al enclave \"\n\"ubicado en el este. Se estaba llevando allí para estudiarla más a fondo. \"\n\"Esta piedra brillaba con una energía que de alguna manera otorgaba una \"\n\"visión más allá de la que un hombre normal podría poseer. No sé qué secretos \"\n\"encierra, amigo mío, pero encontrar esta piedra sin duda resultaría de lo \"\n\"más valioso.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"La caravana se detuvo aquí para hacerse con algunos suministros para su \"\n\"viaje hacia el este. Les vendí una gran variedad de frutas frescas y \"\n\"excelentes mollejas que Garda acababa de hornear. Es una lástima lo que les \"\n\"pasó ...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"No sé qué es lo que pensaron que podían ver con esa piedra, pero diré esto: \"\n\"Si caen rocas del cielo, ¡es mejor que tengas cuidado!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Bueno, una caravana de personas muy importantes se detuvo aquí, pero eso fue \"\n\"hace bastante tiempo. Tenían acentos extraños y estaban iniciando un largo \"\n\"viaje, según recuerdo. \\n\"\n\" \\n\"\n\"No veo cómo podrías esperar encontrar algo que hubieran estado cargando.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Quédate un momento, tengo una historia que puede resultarte interesante. Una \"\n\"caravana que se dirigía a los reinos del este pasó por aquí hace algún \"\n\"tiempo. ¡Supuestamente llevaba un pedazo de los cielos que había caído a la \"\n\"tierra! La caravana fue emboscada por jinetes encapuchados justo al norte de \"\n\"aquí a lo largo de la carretera. Busqué entre los escombros esta roca \"\n\"celeste, pero no la encontré por ningún lado. Si la encuentra, creo que \"\n\"puedo crear algo útil a partir de ella.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Todavía estoy esperando que me traigas esa piedra del cielo. Sé que puedo \"\n\"hacer algo poderoso con eso.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Déjame ver eso - sí ... sí, es como yo creía. Dame un momento...\\n\"\n\" \\n\"\n\"Ah, aquí tienes. Acomodé pedazos de la piedra dentro de un anillo de plata \"\n\"que me dejó mi padre. Espero que te sirva bien.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Solía tener un bonito anillo; era muy caro, con azul, verde, rojo y \"\n\"plateado. Sin embargo, no recuerdo qué le pasó. Realmente extraño ese \"\n\"anillo ...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"La Piedra del Cielo es muy poderosa, y si alguien que no sea Griswold te \"\n\"pidiera que la encontraras, yo lo evitaría. El aprovechará sus poderes y su \"\n\"uso será para el bien de todos nosotros.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Si alguien puede hacer algo con esa roca, ese es Griswold. Él sabe lo que \"\n\"hace y, por mucho que trato de robar a sus clientes, respeto la calidad de \"\n\"su trabajo.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"¿La bruja Adria busca un hongo negro? Sé tanto sobre Hongos Negros como \"\n\"sobre Arenques Rojos. Quizás Pepin el Curandero podría contarte más, pero \"\n\"esto es algo que no se puede encontrar en ninguna de mis historias o libros.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Déjame decirte esto. Tanto Garda como yo nunca, NUNCA serviríamos hongos \"\n\"negros a nuestros invitados de honor. Si Adria quiere hongos en su estofado, \"\n\"entonces es asunto suyo, pero no puedo ayudarte a encontrar ninguno. Hongos \"\n\"negros ... ¡repugnantes!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"La bruja me dijo que estabas buscando el cerebro de un demonio para ayudarme \"\n\"a crear mi elixir. Debería ser de gran valor para los muchos que resultan \"\n\"heridos por esas horribles bestias, si pudiera descubrir los secretos que \"\n\"sospecho guarda su alquimia. Si puedes quitarle el cerebro a un demonio \"\n\"cuando lo mates, te agradecería que me lo trajeras.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Excelente, esto es justo lo que tenía en mente. Pude terminar el elixir sin \"\n\"esto, pero no está de más tener esto para estudiar. ¿Podrías llevarle esto a \"\n\"la bruja? Creo que lo está esperando.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Creo que Ogden podría tener algunos hongos en el sótano de almacenamiento. \"\n\"¿Por qué no le preguntas?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Si Adria no tiene uno de estos, puedes apostar que es algo raro. No puedo \"\n\"ofrecerte más ayuda que esa, pero suena como ... ¡un hongo enorme, \"\n\"gigantesco, hinchado y desmesurado! Bueno, buena caza, supongo.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden mezcla un INFAME hongo negro, pero me enfermaré si bebo eso. Escucha, \"\n\"escucha ... aquí está el secreto: ¡La moderación es la clave!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"¿Qué tenemos aquí? Interesante, parece un libro de reactivos. Mantén los \"\n\"ojos abiertos para un hongo negro. Debe ser bastante grande y fácil de \"\n\"identificar. Si lo encuentras, tráemelo, ¿quieres?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Es un hongo negro grande el que necesito. Ahora corre y consíguelo para que \"\n\"pueda usarlo en un brebaje especial en el que estoy trabajando.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Sí, será perfecto para una infusión que estoy creando. Por cierto, el \"\n\"sanador está buscando el cerebro de algún demonio para poder tratar a los \"\n\"que han sido afectados por su ponzoña venenosa. Creo que tiene la intención \"\n\"de hacer un elixir con eso. Si lo ayudas a encontrar lo que necesita, fíjate \"\n\"si puedes conseguirme una muestra del elixir.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"¿Por qué has traído eso aquí? No necesito el cerebro de un demonio en este \"\n\"momento. Necesito algo del elixir en el que está trabajando el Curandero. \"\n\"Necesita ese órgano grotesco que estás sosteniendo, y luego tráeme el \"\n\"elixir. Simple cuando lo piensas, ¿no?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"¿Qué? ¿Ahora me traes ese elixir del sanador? Pude terminar mi infusión sin \"\n\"él. ¿Por qué no te lo quedas? ...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"No tengo hongos de ningún tamaño o color a la venta. ¿Qué tal algo un poco \"\n\"más útil?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Entonces, la leyenda del Mapa es real. ¡Incluso yo nunca creí realmente nada \"\n\"de eso! Supongo que es hora de que te diga la verdad sobre quién soy, amigo \"\n\"mío. Verás, no soy todo lo que parezco ...\\n\"\n\" \\n\"\n\"Mi verdadero nombre es Deckard Cain el Sabio, y soy el último descendiente \"\n\"de una antigua Hermandad que se dedicó a conservar y salvaguardar los \"\n\"secretos de un mal atemporal. Un mal que obviamente ahora ha sido \"\n\"liberado ...\\n\"\n\" \\n\"\n\"El mal contra el que te mueves es el oscuro Señor del Terror, conocido por \"\n\"los mortales como Diablo. Fue él quien fue encarcelado dentro del Laberinto \"\n\"hace muchos siglos. El Mapa que tienes ahora fue creado hace siglos para \"\n\"marcar el momento en que Diablo se levantaría nuevamente de su \"\n\"encarcelamiento. Cuando las dos estrellas en ese mapa se alineen, Diablo \"\n\"estará en el apogeo de su poder. Será casi invencible ...\\n\"\n\" \\n\"\n\"¡Ahora estás en una carrera contra el tiempo, amigo! Encuentra a Diablo y \"\n\"destrúyelo antes de que las estrellas se alineen, ¡porque es posible que \"\n\"nunca más tengamos la oportunidad de librar al mundo de su maldad!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"¡Nuestro tiempo se está acabando! Siento que su poder oscuro se está \"\n\"acumulando y solo tú puedes evitar que logre todo su poder.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Estoy seguro de que hiciste todo lo posible, pero me temo que ni siquiera tu \"\n\"fuerza y voluntad serán suficientes. Diablo está ahora en el apogeo de su \"\n\"poder terrenal, y necesitarás todo tu coraje y fuerza para derrotarlo. Que \"\n\"la Luz te proteja y te guíe, amigo mío. Ayudaré en todo lo que pueda.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Si la bruja no puede ayudarte y te sugiere que veas a Caín, ¿qué te hace \"\n\"pensar que yo sabría algo? Parece que este es un asunto muy serio. Debes \"\n\"darte prisa y ver al narrador como sugiere Adria.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"No puedo hacer mucho de lo escrito en este mapa, pero tal vez Adria o Caín \"\n\"podrían ayudarlo a descifrar a qué se refiere esto. \\n\"\n\" \\n\"\n\"Puedo ver que es un mapa de las estrellas en nuestro cielo, pero está más \"\n\"allá de mis talentos.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"La mejor persona para preguntar sobre ese tipo de cosas sería nuestro \"\n\"narrador. \\n\"\n\" \\n\"\n\"Caín está muy bien informado sobre los escritos antiguos, y ese es \"\n\"fácilmente el pedazo de papel más antiguo que he visto en mi vida.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Nunca antes había visto un mapa de este tipo. ¿Dónde lo conseguiste? Aunque \"\n\"no tengo ni idea de cómo leer esto, Caín o Adria pueden darte las respuestas \"\n\"que buscas.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Escúchame, acércate. No sé si sabes lo que yo sé, pero realmente tienes algo \"\n\"aquí. Eso es un mapa.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"¡Oh! Me temo que esto no augura nada bueno. Este mapa de las estrellas \"\n\"presagia un gran desastre, pero sus secretos no son míos como para \"\n\"contarlos. Ha llegado el momento de que tengas una conversación muy seria \"\n\"con el Narrador ...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"He estado buscando un mapa, pero ciertamente no es así. Deberías mostrárselo \"\n\"a Adria; probablemente ella pueda decirte lo que es. Diré una cosa; parece \"\n\"viejo, y viejo por lo general significa valioso.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Por favooor, no herir. No matar. Mantener con vida y la próxima vez te \"\n\"ayudaré.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Estoy haciendo algo nuevo para ti. Nuevamente, no mates a Gharbad. Vive y \"\n\"haz el bien. \\n\"\n\" \\n\"\n\"Toma esto como prueba de que cumplo la palabra ...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"¡Nada aún! Casi termino. \\n\"\n\" \\n\"\n\"Muy poderoso, muy fuerte. ¡Vivir! ¡Vivir! \\n\"\n\" \\n\"\n\"¡Sin dolor y la promesa mantengo!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Esto es demasiado bueno para ti. ¡Muy poderoso! Tu quieres - tu tomas!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"¿Qué? ¿Por qué estás aquí? Todas estas interrupciones son suficientes para \"\n\"volverse loco. Toma, toma esto y déjame con mi trabajo. ¡No me molestes más!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"¡Arrrrgh! ¡Tu curiosidad te matará !!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Hola mi amigo. Quédate un rato y escucha ...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Mientras te adentres más profundo en el Laberinto, es posible que encuentres \"\n\"tomos de gran conocimiento escondidos allí. \\n\"\n\" \\n\"\n\"Léelos atentamente porque pueden decirte cosas que incluso yo no puedo.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Conozco muchos mitos y leyendas que pueden contener respuestas a preguntas \"\n\"que puedan surgir en tus viajes al Laberinto. Si te encuentras con desafíos \"\n\"y preguntas sobre las que buscas conocimiento, búscame y te diré lo que \"\n\"pueda.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold: un hombre de gran acción y gran coraje. Apuesto a que nunca te \"\n\"contó de la vez que entró en el Laberinto para salvar a Wirt, ¿verdad? Él \"\n\"conocía los peligros que se encuentran allí, pero, de nuevo, tu también. Es \"\n\"un hábil artesano, y si dice poder ayudarlo de alguna manera, puede contar \"\n\"con su honestidad y habilidad.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden es propietario y dirige la Posada y Taberna del Sol Naciente desde \"\n\"hace casi cuatro años. Lo compró unos pocos meses antes de que todo se fuera \"\n\"al diablo. Él y su esposa Garda no tienen dinero para irse, ya que \"\n\"invirtieron todo lo que tenían para ganarse la vida aquí. Es un buen hombre \"\n\"con un profundo sentido de responsabilidad.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Pobre Farnham. Es un inquietante recordatorio de la condenada asamblea que \"\n\"entró en la Catedral con Lazarus en ese día oscuro. Escapó con vida, pero su \"\n\"coraje y gran parte de su cordura quedaron en algún pozo oscuro. Hoy en día \"\n\"encuentra consuelo solo en el fondo de su jarra, pero hay fragmentos \"\n\"ocasionales de verdad enterrados en sus constantes divagaciones.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"La bruja, Adria, es una anomalía aquí en Tristram. Llegó poco después de que \"\n\"la Catedral fuera profanada mientras la mayoría de los demás huían. Ella \"\n\"hizo construir una pequeña cabaña en las afueras del pueblo, aparentemente \"\n\"de la noche a la mañana, y tiene acceso a muchos artefactos extraños y \"\n\"arcanos y tomos de conocimiento que ni siquiera yo había visto antes.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"La historia de Wirt es aterradora y trágica. Fue arrancado de los brazos de \"\n\"su madre y arrastrado al laberinto por los pequeños e inmundos demonios que \"\n\"empuñan malvadas lanzas. Se llevaron a muchos otros niños ese día, incluido \"\n\"el hijo del Rey Leoric. Los Caballeros del palacio bajaron, pero nunca \"\n\"regresaron. El herrero encontró al niño, pero solo después de que las \"\n\"horribles bestias comenzaran a torturarlo para sus sádicos placeres.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Lo considero un verdadero amigo, quizás el más cercano que tengo \"\n\"aquí. A veces está un poco confundido, pero nunca ha existido un alma más \"\n\"cariñosa o considerada. Sus conocimientos y habilidades son igualados por \"\n\"pocos, y su puerta siempre está abierta.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian es una buena mujer. Muy querida por su buen humor y su risa rápida, \"\n\"ocupa un lugar especial en mi corazón. Se queda en la taberna para ayudar a \"\n\"su abuela anciana, que está demasiado enferma para viajar. A veces temo por \"\n\"su seguridad, pero sé que cualquier hombre de la aldea preferiría morir \"\n\"antes que verla lastimada.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Saludos, buen maestro. ¡Bienvenido a la Taberna del Sol Naciente!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Muchos aventureros han honrado las mesas de mi taberna, y diez veces se han \"\n\"contado tantas historias como bebido cerveza. Lo único que escuché de todos \"\n\"ellos fue el estar de acuerdo con este viejo axioma. Quizás te ayude. Puedes \"\n\"cortar la carne, pero debes triturar el hueso.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Griswold, el herrero, está muy bien informado sobre armas y armaduras. Si \"\n\"alguna vez necesitas trabajar en tu equipo, definitivamente es el hombre \"\n\"para ver.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham pasa demasiado tiempo aquí, ahogando sus penas en cerveza barata. Lo \"\n\"echaría, pero sufrió tanto durante su tiempo en el Laberinto.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria es sabia para su edad, pero debo admitirlo: Ella me asusta un poco. \\n\"\n\" \\n\"\n\"Bueno, no importa. Si alguna vez necesitas intercambiar objetos de \"\n\"hechicería, ella mantiene una choza extrañamente bien abastecida al otro \"\n\"lado del río.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Si quieres saber más sobre la historia de nuestro pueblo, el narrador Cain \"\n\"sabe bastante sobre el pasado.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt es un canalla y un pequeño sinvergüenza. Siempre se estaba metiendo en \"\n\"problemas, y no es de extrañar lo que le sucedió. \\n\"\n\" \\n\"\n\"Probablemente se fue a hacer el tonto por ahí donde no debería haber estado. \"\n\"Lo siento por el chico, pero no acepto la compañía que tiene.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin es un buen hombre y, sin duda, el más generoso del pueblo. Siempre \"\n\"está atendiendo las necesidades de los demás, pero los problemas de una u \"\n\"otra clase parecen seguirlo dondequiera que vaya ...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, mi Camarera? Si no fuera por su sentido del deber hacia su abuela, \"\n\"habría huido de aquí hace mucho tiempo. \\n\"\n\" \\n\"\n\"Dios sabe que le rogué que se fuera, diciéndole que cuidaría de la anciana, \"\n\"pero ella es demasiado dulce y cariñosa para haberlo hecho.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"¿Qué te aflige, amigo mío?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"He hecho un descubrimiento muy interesante. A diferencia de nosotros, las \"\n\"criaturas del Laberinto pueden curarse a sí mismas sin la ayuda de pociones \"\n\"o magia. Si hieres a uno de los monstruos, asegúrate de que esté muerto o \"\n\"podría regenerarse.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Antes de que fuera tomada por, bueno, lo que sea que esté al acecho debajo, \"\n\"la Catedral era un lugar de gran aprendizaje. Allí se pueden encontrar \"\n\"muchos libros. Si encuentra alguno, debe leerlos todos, ya que algunos \"\n\"pueden tener secretos sobre el funcionamiento del Laberinto.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold sabe tanto sobre el arte de la guerra como yo sobre el arte de \"\n\"curar. Es un comerciante astuto, pero su trabajo es insuperable. Oh, supongo \"\n\"que puede deberse a que es el único herrero que queda aquí.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Caín es un verdadero amigo y un sabio sensato. Mantiene una vasta biblioteca \"\n\"y tiene una habilidad innata para discernir la verdadera naturaleza de \"\n\"muchas cosas. Si alguna vez tienes alguna pregunta, él es la persona a la \"\n\"que debes dirigirse.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Incluso mis habilidades no han podido curar completamente a Farnham. Oh, he \"\n\"podido reparar su cuerpo, pero su mente y su espíritu están más allá de \"\n\"cualquier cosa que pueda hacer.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Si bien utilizo algunas formas limitadas de magia para crear las pociones y \"\n\"elixires que guardo aquí, Adria es una verdadera hechicera. Parece que nunca \"\n\"duerme y siempre tiene acceso a muchos libros y artefactos místicos. Creo \"\n\"que su cabaña puede ser mucho más de lo que parece ser, pero parece que \"\n\"nunca puedo entrar al lugar.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Pobre Wirt. Hice todo lo posible por el niño, pero sé que desprecia ese \"\n\"broche de madera que me vi obligado a sujetar a su pierna. Sus heridas eran \"\n\"horribles. Nadie, y especialmente un niño tan pequeño, debería tener que \"\n\"sufrir como él lo hizo.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Realmente no entiendo por qué Ogden se queda aquí en Tristram. Sufre de una \"\n\"leve condición nerviosa, pero es un hombre inteligente y trabajador que le \"\n\"iría muy bien donde quiera que fuera. Supongo que puede ser el miedo a los \"\n\"muchos asesinatos que ocurren en el campo circundante, o quizás los deseos \"\n\"de su esposa lo que lo mantiene a él y a su familia donde están.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"La camarera de Ogden es una chica dulce. Su abuela está bastante enferma y \"\n\"sufre delirios \\n\"\n\" \\n\"\n\"Ella afirma que son visiones, pero no tengo pruebas de eso de una forma u \"\n\"otra.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"¡Buenos días! ¿Cómo puedo servirte?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Mi abuela soñó que vendrías a hablar conmigo. Ella tiene visiones, sabes, y \"\n\"puedes ver el futuro.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"¡La mujer de las afueras del pueblo es una bruja! Parece bastante agradable \"\n\"y su nombre, Adria, es muy agradable al oído, pero le temo. \\n\"\n\" \\n\"\n\"Se necesitaría alguien bastante valiente, como tú, para ver lo que está \"\n\"haciendo ahí fuera.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Nuestro herrero es un motivo de orgullo para la gente de Tristram. No solo \"\n\"es un maestro artesano que ha ganado muchos concursos dentro de su gremio, \"\n\"sino que recibió elogios de nuestro Rey Leoric en persona, que su alma \"\n\"descanse en paz. Griswold también es un gran héroe; pregúntale a Caín.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain ha sido el narrador de Tristram desde que tengo uso de razón. Él sabe \"\n\"mucho y puede decirte casi cualquier cosa sobre casi todo.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham es un borracho que llena su barriga de cerveza y los oídos de los \"\n\"demás de tonterías. \\n\"\n\" \\n\"\n\"Sé que tanto Pepin como Ogden sienten simpatía por él, pero me frustra tanto \"\n\"verlo caer cada vez más en un aturdido estupor cada noche.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin salvó la vida de mi abuela y sé que nunca podré pagarle por eso. Su \"\n\"habilidad para curar cualquier enfermedad es más poderosa que la espada más \"\n\"potente y más misteriosa que cualquier hechizo que puedas nombrar. Si alguna \"\n\"vez necesitas curarte, Pepin puede ayudarte.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Crecí con la madre de Wirt, Canace. Aunque solo se sintió levemente herida \"\n\"cuando esas horribles criaturas se lo robaron, nunca se recuperó. Creo que \"\n\"murió con el corazón roto. Wirt se ha convertido en un joven mezquino que \"\n\"solo busca sacar provecho del sudor de los demás. Sé que sufrió y ha visto \"\n\"horrores que ni siquiera puedo imaginar, pero algo de esa oscuridad aún se \"\n\"cierne sobre él.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden y su esposa nos han llevado a mi abuela y a mí a su casa e incluso me \"\n\"han dejado ganar algunas piezas de oro trabajando en la posada. Les debo \"\n\"mucho y espero algún día dejar este lugar y ayudarlos a comenzar un gran \"\n\"hotel en el este.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Bueno, ¿qué puedo hacer por ti?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Si estás buscando un buen arma, déjame mostrarte esto. Toma tu arma básica \"\n\"contundente, como una maza. Funciona como un encanto contra la mayoría de \"\n\"esos horrores eternos que hay allí, ¡y no hay nada mejor para destrozar \"\n\"pequeños esqueletos delgados!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"¿El hacha? Sí, esa es un buen arma, equilibrada contra cualquier enemigo. \"\n\"Mira cómo corta el aire y luego imagina una bonita y gorda cabeza de demonio \"\n\"en su camino. Sin embargo, ten en cuenta que el giro es lento, ¡pero habla \"\n\"de asestar un golpe fuerte!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Mira ese filo, ese equilibrio. Una espada en la mano derecha, y contra el \"\n\"enemigo correcto, es el amo de todas las armas. Su hoja afilada encuentra \"\n\"poco para cortar o perforar en los muertos vivientes, pero contra un enemigo \"\n\"vivo que respira, ¡una espada cortará su carne mucho mejor!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Tus armas y armaduras mostrarán los signos de tus luchas contra la \"\n\"Oscuridad. Si me las traes, con un poco de trabajo y una fragua en caliente, \"\n\"puedo restaurarlas a su mejor forma de lucha.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Mientras prácticamente tengo que pasar de contrabando los metales y \"\n\"herramientas que necesito de las caravanas que bordean los límites de \"\n\"nuestro maldito pueblo, esa bruja, Adria, siempre parece conseguir lo que \"\n\"necesita. Si supiera lo más mínimo sobre cómo aprovechar la magia como ella \"\n\"lo hizo, podría hacer algunas cosas realmente increíbles.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian es una buena chica. Es una pena que su abuela tenga tan mala salud o \"\n\"haría los arreglos para sacarlos a ambos de aquí en una de las caravanas \"\n\"comerciales.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"A veces pienso que Caín habla demasiado, pero supongo que esa es su vocación \"\n\"en la vida. ¡Si pudiera doblar el acero tan bien como puede doblar tu oreja, \"\n\"podría hacer una armadura de placas lo suficientemente buena para un \"\n\"Emperador!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Estaba con Farnham esa noche que Lazarus nos condujo al Laberinto. Nunca \"\n\"volví a ver al Arzobispo y es posible que no hubiera sobrevivido si Farnham \"\n\"no hubiera estado a mi lado. Me temo que el ataque dejó su alma tan lisiada \"\n\"como, bueno, otro dejó mi pierna. No puedo pelear esta batalla por él ahora, \"\n\"pero lo haría si pudiera.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Un buen hombre que antepone las necesidades de los demás a las suyas. No \"\n\"encontraras a nadie en Tristram, ni en ningún otro lugar, que tenga algo \"\n\"malo que decir sobre el sanador.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Ese chico se va a meter en serios problemas ... o creo que debería decirlo, \"\n\"de nuevo. He tratado de interesarle en trabajar aquí y aprender un oficio \"\n\"honesto, pero prefiere las altas ganancias de comerciar con bienes de origen \"\n\"dudoso. No puedo reprocharle eso después de lo que le sucedió, pero desearía \"\n\"que al menos tuviera cuidado.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"El Posadero tiene pocos negocios y ninguna forma real de obtener ganancias. \"\n\"Se las arregla para llegar a fin de mes proporcionando comida y alojamiento \"\n\"a aquellos que, de vez en cuando, deambulan por la aldea, pero es tan \"\n\"probable que se escapen por noche como que le paguen. Si no fuera por las \"\n\"reservas de cereales y carnes secas que guarda en su bodega, la mayoría de \"\n\"nosotros habríamos muerto de hambre durante ese primer año en que todo el \"\n\"campo fue invadido por demonios.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"¿No puede un colega beber en paz?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"¿La chica que trae las bebidas? Oh, sí, qué hermosa dama. Muy agradable \"\n\"también.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"¿Por qué esa vieja bruja no hace algo para variar? Claro, claro, tiene sus \"\n\"cosas, pero escúchame ... es antinatural. Nunca la he visto comer o beber, y \"\n\"no puedes confiar en alguien que no bebe al menos un poco.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Caín no es lo que dice ser. Claro, claro, él cuenta una buena historia ... \"\n\"algunas de ellas son realmente aterradoras o divertidas ... pero creo que él \"\n\"sabe más de lo que sabe.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? El bueno de Griswold. ¡Lo quiero como a un hermano! Luchamos \"\n\"juntos, ya sabes, cuando ... nosotros ... Lazarus ... Lazarus ... Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Jejeje, me gusta Pepin. Realmente lo intenta, ya sabes. Escucha, debes \"\n\"asegurarte de conocerlo. Buen tipo como la gente que siempre quiere ayudar. \"\n\"Oye, supongo que sería un poco propio de ti, ¿eh héroe? Yo también fui un \"\n\"héroe ...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt es un niño que tiene incluso más problemas que yo, y yo sé todo sobre \"\n\"los problemas. Escucha, ese chico es afable, pero ha estado allí, ¿sabes? \"\n\"¡Perdió una pierna! Tiene que caminar sobre un trozo de madera. Es tan \"\n\"triste, tan triste ...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden es el mejor hombre del pueblo. No creo que yo le guste mucho a su \"\n\"esposa, pero mientras ella siga golpeando barriles, supongo que estará bien. \"\n\"Parece que he pasado más tiempo con Ogden que la mayoría, pero es tan bueno \"\n\"conmigo ...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Quiero decirte algo, porque sé todo sobre estas cosas. Es mi especialidad. \"\n\"Esto de aquí es lo mejor ... ¡looo mejor! Esa otra cerveza no es buena ya \"\n\"que esos estúpidos perros ...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Nunca nadie me esc... escucha. En algún lugar, no estoy muy seguro, pero en \"\n\"algún lugar debajo de la iglesia hay un gran montón de oro. Reluciendo y \"\n\"brillando y esperando a que alguien lo consiga.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Sé que tienes tus propias ideas, y sé que no vas a creer esto, pero ese arma \"\n\"que tienes allí, ¡simplemente no es buena contra esos grandes brutos! Oh, no \"\n\"me importa lo que diga Griswold, no pueden hacer nada como solían hacer en \"\n\"los viejos tiempos ...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Si yo fuera tú ... y no lo soy ... pero si lo fuera, vendería todas esas \"\n\"cosas que tienes y me largaría de aquí. Ese chico de ahí fuera ... Siempre \"\n\"tiene algo bueno, pero tienes que darle algo de oro o ni siquiera te \"\n\"mostrará lo que tiene.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Siento un alma en busca de respuestas ...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"La sabiduría se gana, no se da. Si descubres un tomo de conocimiento, devora \"\n\"sus palabras. Si ya tienes conocimiento de los misterios arcanos escritos en \"\n\"un libro, recuerda, ese nivel de maestría siempre puede aumentar.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"El mayor poder es a menudo el de menor duración. Puede encontrar antiguas \"\n\"palabras de poder escritas en rollos de pergamino. La fuerza de estos \"\n\"pergaminos radica en la capacidad del aprendiz o del adepto para lanzarlos \"\n\"con igual habilidad. Su debilidad es que primero se deben leer en voz alta y \"\n\"nunca se pueden tener listos en la mente. Debes saber también que estos \"\n\"pergaminos se pueden leer una sola vez, así que utilízalos con cuidado.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Aunque el calor del sol es inconmensurable, la mera llama de una vela es de \"\n\"mayor peligro. Ninguna energía, por grande que sea, puede usarse sin el \"\n\"enfoque adecuado. Para muchos hechizos, los Bastones encantados pueden \"\n\"cargarse muchas veces con energías mágicas. Tengo la capacidad de restaurar \"\n\"su poder, pero sé que nada se hace sin un precio.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"La suma de nuestro conocimiento está en la suma de su gente. Si encuentras \"\n\"un libro o un pergamino que no puedas descifrar, no dude en traérmelo. Si \"\n\"puedo encontrarle sentido, compartiré lo que encuentre.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Para un hombre que solo conoce el Hierro, no hay mayor magia que el Acero. \"\n\"El herrero Griswold es más hechicero de lo que él cree. Su habilidad para \"\n\"fusionar el fuego y el metal es inigualable en esta tierra.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"La corrupción tiene la fuerza del engaño, pero la inocencia tiene el poder \"\n\"de la pureza. La joven Gillian tiene un corazón puro, anteponiendo las \"\n\"necesidades de su matriarca sobre las suyas. Ella me teme, pero es solo \"\n\"porque no me comprende.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Un cofre abierto en la oscuridad no guarda mayor tesoro que cuando se abre a \"\n\"la luz. El narrador Caín es un enigma, pero solo para quienes no miran. Su \"\n\"conocimiento de lo que hay debajo de la catedral es mucho mayor de lo que él \"\n\"mismo se permite darse cuenta.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Cuanto más alto pongas tu fe en un hombre, más debe caer. Farnham ha perdido \"\n\"su alma, pero no ante ningún demonio. Se perdió cuando vio a la gente del \"\n\"pueblo traicionados por el Arzobispo Lazarus. Él tiene conocimientos para \"\n\"cosechar, pero debes separar los hechos de las fantasías.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"La mano, el corazón y la mente pueden realizar milagros cuando están en \"\n\"perfecta armonía. El sanador Pepin ve el interior del cuerpo de una manera \"\n\"que ni siquiera yo puedo. Su capacidad para restaurar a los enfermos y \"\n\"heridos se ve magnificada por su comprensión en la creación de elixires y \"\n\"pociones. Es un aliado tan grande como tú en Tristram.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Hay mucho sobre el futuro que no podemos ver, pero cuando llegue serán los \"\n\"niños quienes lo manejen. El niño Wirt tiene algo oscuro en el alma, pero no \"\n\"representa una amenaza para el pueblo o su gente. Sus tratos secretos con \"\n\"los rufianes y los inconfesables gremios de los pueblos cercanos le permiten \"\n\"acceder a muchos dispositivos que no se pueden encontrar fácilmente en \"\n\"Tristram. Si bien sus métodos pueden ser reprochables, Wirt puede ayudarte \"\n\"en tu batalla contra la Oscuridad que nos invade.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Las paredes de tierra y el dosel de paja no crean una casa. El posadero \"\n\"Ogden tiene un mayor propósito en este pueblo de lo que muchos creen. \"\n\"Proporciona refugio para Gillian y su matriarca, mantiene la vida que le \"\n\"dejó Farnham y proporciona un ancla para todos los que quedan en el pueblo a \"\n\"lo que Tristram fue una vez. Su taberna, y los placeres sencillos que aún se \"\n\"pueden encontrar allí, dan una idea de una vida que la gente de aquí \"\n\"recuerda. Es ese recuerdo el que sigue alimentando sus esperanzas de éxito.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst ... por aquí ...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"No todo el mundo en Tristram tiene un uso, o un mercado, para todo lo que \"\n\"encontrará en el laberinto. Ni siquiera yo, por más difícil que sea de \"\n\"creer. \\n\"\n\" \\n\"\n\"A veces, solo tú podrás encontrar un propósito para algunas cosas.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"No te fíes de todo lo que dice el borracho. Demasiadas cervezas han empañado \"\n\"su visión y su sentido común.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Por si no lo has notado, no compro nada de Tristram. Soy un importador de \"\n\"productos de calidad. Si quieres vender basura, tendrás que ver a Griswold, \"\n\"Pepin o esa bruja, Adria. Estoy seguro de que te sacarán de las manos todo \"\n\"lo que les puedas llevar ...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Supongo que le debo la vida al herrero, lo que queda de ella. Claro, \"\n\"Griswold me ofreció un aprendizaje en la herrería, y es un tipo bastante \"\n\"agradable, pero nunca obtendré suficiente dinero para ... bueno, digamos que \"\n\"tengo planes definidos que requieren una gran cantidad de oro.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Si tuviera unos años más, la colmaría con todas las riquezas que pudiera \"\n\"reunir, y déjame asegurarte que puedo conseguir algunas cosas muy buenas. \"\n\"Gillian es una hermosa chica que debería salir de Tristram tan pronto como \"\n\"sea seguro. Hmmm ... tal vez me la lleve conmigo cuando me vaya ...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Caín sabe demasiado. Me asusta de muerte, incluso más que esa mujer al otro \"\n\"lado del río. No deja de contarme lo afortunado que soy de estar vivo y cómo \"\n\"mi historia está predicha en la leyenda. Creo que está loco.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham: ahora hay un hombre con problemas graves y sé todo acerca de lo \"\n\"graves que pueden ser los problemas. Confió demasiado en la integridad de un \"\n\"hombre, y Lazarus lo llevó a las mismas fauces de la muerte. Oh, sé lo que \"\n\"es ahí abajo, así que ni siquiera empieces a contarme tus planes para \"\n\"destruir el mal que habita en ese Laberinto. Cuida tus piernas ...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Siempre que no necesites volver a colocar nada, el viejo Pepin es tan bueno \"\n\"como pocos. \\n\"\n\" \\n\"\n\"Si hubiera tenido algunas de esas pociones que él prepara, aún podría tener \"\n\"mi pierna ...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria realmente me molesta. Claro, Cain es espeluznante en lo que puede \"\n\"contarte sobre el pasado, pero esa bruja puede ver tu pasado. Ella siempre \"\n\"tiene alguna forma de conseguir lo que necesita también. Adria consigue más \"\n\"mercadería de la que he visto pasar por las puertas del Bazar del Rey \"\n\"durante el Festival Mayor.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden es un tonto por quedarse aquí. Podría sacarlo del pueblo por un precio \"\n\"muy razonable, pero él insiste en intentar salir adelante con esa estúpida \"\n\"taberna. Supongo que al menos le da a Gillian un lugar para trabajar, y su \"\n\"esposa Garda hace un excelente Pastel de cordero ...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Más allá del Salón de los Héroes se encuentra la Cámara de Hueso. La muerte \"\n\"eterna aguarda a cualquiera que busque robar los tesoros guardados dentro de \"\n\"esta habitación. Así habla el Señor del Terror, y así está escrito.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"... y así, encerrado más allá de la Puerta de la Sangre y más allá del Salón \"\n\"del Fuego, Valor espera a que el Héroe de la Luz despierte ...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Puedo ver lo que tú no ves.\\n\"\n\"Visión lechosa, luego los ojos se pudren.\\n\"\n\"Cuando te vuelvas se habrán ido,\\n\"\n\"Susurrando su canción oculta.\\n\"\n\"Entonces ves lo que no puede ser,\\n\"\n\"Las sombras se mueven donde debería estar la luz.\\n\"\n\"Fuera de la oscuridad, fuera de la mente,\\n\"\n\"Arrojados a los Pasillos del Ciego.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Las armerías del Infierno son el hogar del Señor de la Guerra de la Sangre. \"\n\"A su paso yacían los cuerpos mutilados de miles. Tanto los ángeles como los \"\n\"hombres han sido cortados para cumplir con sus sacrificios interminables a \"\n\"los Oscuros que gritan por una cosa: sangre.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Presta atención y da testimonio de las verdades que se encuentran aquí, \"\n\"porque son el último legado de los Horadrim. Hay una guerra que continúa \"\n\"incluso ahora, más allá de los campos que conocemos, entre los reinos \"\n\"utópicos de los Altos Cielos y los caóticos pozos de los Infiernos \"\n\"Ardientes. Esta guerra se conoce como el Gran Conflicto, y ha durado y \"\n\"ardido durante más tiempo que cualquiera de las estrellas del cielo. Ninguno \"\n\"de los bandos logrará dominar mientras las fuerzas de la Luz y la Oscuridad \"\n\"compitan constantemente por el control de toda la creación.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Presta atención y da testimonio de las verdades que se encuentran aquí, \"\n\"porque son el último legado de los Horadrim. Cuando el Conflicto Eterno \"\n\"entre los Altos Cielos y los Infiernos Ardientes cae sobre suelo mortal, se \"\n\"llama la Guerra del Pecado. Ángeles y demonios caminan entre la humanidad \"\n\"disfrazados, luchando en secreto, lejos de las miradas indiscretas de los \"\n\"mortales. Algunos mortales atrevidos y poderosos incluso se han aliado con \"\n\"ambos bandos y han ayudado a dictar el curso de la Guerra del Pecado.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Presta atención y da testimonio de las verdades que se encuentran aquí, \"\n\"porque son el último legado de los Horadrim. Hace casi trescientos años, se \"\n\"supo que los Tres Malignos Principales de los Infiernos Ardientes habían \"\n\"llegado misteriosamente a nuestro mundo. Los Tres Hermanos asolaron las \"\n\"tierras del este durante décadas, mientras que la humanidad quedó temblando \"\n\"a su paso. Nuestra Orden, los Horadrim, fue fundada por un grupo de magos \"\n\"secretos para perseguir y capturar a los Tres Malignos de una vez por \"\n\"todas.\\n\"\n\" \\n\"\n\"El Horadrim original capturó a dos de los Tres dentro de poderosos \"\n\"artefactos conocidos como Piedras del Alma y los enterró profundamente bajo \"\n\"las desoladas arenas del este. El tercer Maligno escapó de la captura y huyó \"\n\"hacia el oeste con muchos de los Horadrim persiguiéndolo. El Tercer Mal, \"\n\"conocido como Diablo, el Señor del Terror, finalmente fue capturado, su \"\n\"esencia colocada en una Piedra del Alma y enterrada dentro de este \"\n\"Laberinto.\\n\"\n\" \\n\"\n\"Se advierte que debe evitarse que la Piedra del Alma sea descubierta por \"\n\"aquellos que no son de la fe. Si Diablo fuera liberado, buscaría un cuerpo \"\n\"que fuera fácil de controlar, y que fuera muy débil, tal vez el de un \"\n\"anciano o un niño.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Así sucedió que hubo una gran revolución dentro de los Infiernos Ardientes \"\n\"conocida como El Exilio Oscuro. Los Malignos Menores derrocaron a los Tres \"\n\"Malignos Principales y desterraron sus formas espirituales al reino de los \"\n\"mortales. Los demonios Belial (el Señor de las Mentiras) y Azmodan (el Señor \"\n\"del Pecado) lucharon para reclamar el poder del Infierno durante la ausencia \"\n\"de los Tres Hermanos. Todo el Infierno se polarizó entre las facciones de \"\n\"Belial y Azmodan mientras las fuerzas de los Altos Cielos golpeaban \"\n\"continuamente las mismas Puertas del Infierno.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Muchos demonios viajaron al reino de los mortales en busca de los Tres \"\n\"Hermanos. Estos demonios fueron seguidos al plano mortal por Ángeles que los \"\n\"cazaron por las vastas pueblos del Este. Los Ángeles se aliaron con una \"\n\"Orden secreta de magos mortales llamada Los Horadrim, quienes rápidamente se \"\n\"volvieron expertos en cazar demonios. Estos también se hicieron muchos \"\n\"enemigos oscuros en los inframundos.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Así sucedió que los Tres Malignos Principales fueron desterrados en forma \"\n\"espiritual al reino de los mortales y después de sembrar el caos en el Este \"\n\"durante décadas, fueron perseguidos por la Orden maldita de los mortales \"\n\"Horadrim. Los Horadrim usaron artefactos llamados Piedras del Alma para \"\n\"contener la esencia de Mephisto, el Señor del Odio y su hermano Baal, el \"\n\"Señor de la Destrucción. El hermano menor, Diablo, el Señor del Terror, \"\n\"escapó hacia el oeste.\\n\"\n\" \\n\"\n\"Finalmente, los Horadrim capturaron a Diablo dentro de una Piedra del Alma y \"\n\"lo enterraron bajo una antigua y olvidada Catedral. Allí, el Señor del \"\n\"Terror duerme y espera el momento de su renacimiento. Sepan que buscará un \"\n\"cuerpo de juventud y poder para poseer, uno que sea inocente y fácil de \"\n\"controlar. Luego se levantará para liberar a sus Hermanos y avivar una vez \"\n\"más las llamas de la Guerra del Pecado ...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Todas las alabanzas a Diablo, Señor del Terror y Sobreviviente del Exilio \"\n\"Oscuro. Cuando despertó de su largo letargo, mi Señor y Maestro me habló de \"\n\"secretos que pocos mortales conocen. Me dijo que los reinos de los Altos \"\n\"Cielos y los pozos de los Infiernos Abrasadores se enzarzan en una guerra \"\n\"eterna. Él reveló los poderes que han traído esta discordia a los reinos del \"\n\"hombre. Mi señor ha llamado a la batalla por este mundo, y a todos los que \"\n\"existen aquí, la Guerra del Pecado.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Gloria y Aprobación a Diablo, Señor del Terror y Líder de los Tres. Mi Señor \"\n\"me habló de sus dos hermanos, Mefisto y Baal, que fueron desterrados a este \"\n\"mundo hace mucho tiempo. Mi Señor desea esperar el momento oportuno y \"\n\"aprovechar su asombroso poder para liberar a sus hermanos cautivos de sus \"\n\"tumbas bajo las arenas del este. Una vez que mi Señor libere a sus Hermanos, \"\n\"la Guerra del Pecado volverá a conocer la furia de los Tres.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Aclamación y Sacrificio a Diablo, Señor del Terror y Destructor de Almas. \"\n\"Cuando desperté a mi Maestro de su sueño, intentó poseer la forma de un \"\n\"mortal. Diablo intentó reclamar el cuerpo del Rey Leoric, pero mi Maestro \"\n\"estaba demasiado débil por su encarcelamiento. Mi señor necesitaba un ancla \"\n\"simple e inocente a este mundo, y por eso encontró que el niño Albrecht era \"\n\"perfecto para la tarea. Mientras el buen Rey Leoric estaba enloquecido por \"\n\"la posesión fallida de Diablo, yo secuestré a su hijo Albrecht y lo llevé \"\n\"ante mi Maestro. Ahora espero la llamada de Diablo y rezo para ser \"\n\"recompensado cuando él finalmente emerja como el Señor de este mundo.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"¡Gracias a Dios que has vuelto!\\n\"\n\"Mucho ha cambiado desde que viviste aquí, amigo. Todo estaba en paz hasta \"\n\"que llegaron los jinetes oscuros y destruyeron nuestra aldea. Muchos fueron \"\n\"asesinados donde estaban, y los que tomaron las armas fueron asesinados o \"\n\"arrastrados para convertirse en esclavos, o algo peor. La iglesia en las \"\n\"afueras del pueblo ha sido profanada y se utiliza para rituales oscuros. Los \"\n\"gritos que resuenan en la noche son inhumanos, pero es posible que algunos \"\n\"de nuestros habitantes hayan sobrevivido. Sigue el camino que se encuentra \"\n\"entre mi taberna y la herrería para encontrar la iglesia y salvar a quien \"\n\"puedas. \\n\"\n\" \\n\"\n\"Quizás pueda contarte más si volvemos a hablar. Buena suerte.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Mantén tu búsqueda. Encontrar un tesoro perdido no es fácil. Encontrar un \"\n\"tesoro que está escondido, aún menos. Te dejaré con esto. No permitas que \"\n\"las arenas del tiempo confundan tu búsqueda.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"¿Un qué? ¡Esto es una tontería!. No hay ningún tesoro enterrado aquí en \"\n\"Tristram. ¡Déjame ver eso! Ah, mira, estos dibujos son inexactos. No \"\n\"coinciden en absoluto con nuestro pueblo. Me concentraría en lo que hay \"\n\"debajo de la catedral y no en lo que hay debajo de nuestra capa superficial \"\n\"del suelo.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Realmente no tengo tiempo para discutir sobre algún mapa que estás buscando. \"\n\"Tengo muchos enfermos que necesitan mi ayuda y la tuya también.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"El otrora orgulloso Iswall está atrapado en las profundidades de este mundo. \"\n\"Su honor fue despojado y su rostro alterado. Está atrapado en un tormento \"\n\"inmortal. Encargado de ocultar lo mismo que podría liberarlo.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Apuesto a que Wirt te vio venir y fingió un acto para poder reírse de ti más \"\n\"tarde, cuando estabas corriendo por el pueblo con la nariz en la tierra. Yo \"\n\"lo ignoraría.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Hubo un tiempo en que este pueblo era una parada frecuente para los viajeros \"\n\"de todas partes. Mucho ha cambiado desde entonces. Pero las cuevas \"\n\"escondidas y los tesoros enterrados son fantasías comunes de cualquier niño. \"\n\"Wirt rara vez se entrega a juegos juveniles. Así que puede que sea sólo su \"\n\"imaginación.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Escucha. Acércate. No sé si sabes lo que yo sé, pero realmente tienes algo \"\n\"aquí. Eso es un mapa.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Mi abuela a menudo me cuenta historias sobre las extrañas fuerzas que \"\n\"habitan el cementerio fuera de la iglesia. Y puede que le interese escuchar \"\n\"uno de ellos. Dijo que si dejaba la ofrenda adecuada en el cementerio, \"\n\"entraba a la catedral para rezar por los muertos y luego regresaba, la \"\n\"ofrenda se alteraría de alguna manera extraña. No sé si esto es solo la \"\n\"charla de una anciana enferma, pero todo parece posible en estos días.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Mmmm ¿Un tesoro vasto y misterioso, dices? Mmmm. Tal vez podría estar \"\n\"interesado en adquirir algunas cosas tuyas... o mejor aún, ¿no necesitas \"\n\"algunos suministros raros y costosos para superar esta prueba?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Entonces, eres el héroe del que todos han estado hablando. ¿Quizás podrías \"\n\"ayudar a un simple granjero pobre a salir de un lío terrible? En el borde de \"\n\"mi huerto, al sur de aquí, ¡hay una cosa horrible que se hincha en el suelo! \"\n\"No puedo llegar a mis cultivos ni a mis fardos de heno, y mis pobres vacas \"\n\"se morirán de hambre. La bruja me dio esto y dijo que volaría esa cosa fuera \"\n\"de mi campo. Si pudieras destruirlo, te estaré eternamente agradecido. Lo \"\n\"haría yo mismo, pero alguien tiene que quedarse aquí con las vacas ...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Sabía que no podía ser tan simple como lo decía la bruja. Es un mundo triste \"\n\"cuando ni siquiera puedes confiar en tus vecinos.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"¿Se ha ido? ¿Lo enviaste de vuelta a los oscuros recovecos del Hades que lo \"\n\"engendraron? ¿Tu que? ¡Oh, no me digas que lo perdiste! Esas cosas no son \"\n\"baratas, ¿sabes? Tienes que encontrarlo y luego sacar ese horror de nuestro \"\n\"pueblo.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"¡Escuché la explosión desde aquí! Muchas gracias a ti, amable extraño. Con \"\n\"todas estas cosas que salen de la tierra, los monstruos que se apoderan de \"\n\"la iglesia, y esas cosas, estos son tiempos difíciles. No soy más que un \"\n\"agricultor pobre, pero toma esto con gran agradecimiento.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Oh, qué problema tengo ... tal vez ... No, no podría imponértelo, con todos \"\n\"los otros problemas. Quizás, después de haber limpiado la iglesia de algunas \"\n\"de esas criaturas, ¿podrías regresar ... y dedicar un poco de tiempo para \"\n\"ayudar a un pobre agricultor?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Waaaah! (sniff) Waaaah! (sniff)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"¡Perdí a Theo! ¡Perdí a mi mejor amigo! Estábamos jugando junto al río, y \"\n\"Theo dijo que quería ir a ver la gran cosa verde. Dije que no deberíamos, \"\n\"pero nos colamos allí, ¡y de repente salió este INSECTO! ¡Huimos, pero Theo \"\n\"se cayó y el insecto lo agarró y se lo llevó!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"¿Didja lo encontró? ¡Tienes que encontrar a Theodore, por favor! Es solo \"\n\"pequeño. ¡No puede cuidarse solo! ¡Por favor!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"¡Lo encontraste! ¡Lo encontraste! ¡Gracias! Oh Theo, ¿esos bichos \"\n\"desagradables te asustaron? ¡Oye! ¡Puaj! ¡Hay algo pegado a tu pelaje! ¡Agh! \"\n\"¡Vamos, Theo, vámonos a casa! ¡Gracias de nuevo, héroe!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Llevamos mucho tiempo dormidos y ha llegado el momento de despertar. Después \"\n\"de nuestro largo sueño, nos llena un gran hambre. Pronto, ahora, nos \"\n\"alimentaremos ...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"¿Te has estado divirtiendo, pequeño mamífero? Que patético. Tu pequeño mundo \"\n\"no será ningún desafío.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Estas tierras serán contaminadas y nuestra prole invadirá los campos que los \"\n\"hombres llaman hogar. Nuestros zarcillos envolverán este mundo y nos \"\n\"deleitaremos con la carne de sus habitantes. El hombre se convertirá en \"\n\"nuestro esclavos y sustento.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, te puedo oler... ¡estás cerca! ¡Cerca! Ssss... el olor a sangre y \"\n\"miedo... qué tentador...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Y en el año de la Luz Dorada, se decretó que se levantara una gran Catedral. \"\n\"La piedra angular de este lugar sagrado debía ser tallada en la piedra \"\n\"translúcida Antyrael, llamada así por el Ángel que compartía su poder con \"\n\"los Horadrim.\\n\"\n\" \\n\"\n\"En el Año designado a las Sombras, el suelo tembló y la Catedral se hizo \"\n\"añicos y cayó. Cuando comenzó la construcción de catacumbas y castillos y el \"\n\"hombre se enfrentó a los estragos de la Guerra del Pecado, las ruinas fueron \"\n\"escarbadas en busca de sus piedras. Y así fue como la piedra angular \"\n\"desapareció de los ojos del hombre.\\n\"\n\" \\n\"\n\"La piedra era de este mundo , y de todos los mundos , ya que la Luz está \"\n\"tanto dentro de todas las cosas como más allá de todas las cosas. La luz y \"\n\"la unidad son los productos de este fundamento santo, una unidad de \"\n\"propósito y una unidad de posesión.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Dije, Muu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Mira, solo soy una vaca, ¿de acuerdo?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Bien, bien. Realmente no soy una vaca. Normalmente no ando así; pero, estaba \"\n\"sentado en casa ocupándome de mis propios asuntos y, de repente, estos \"\n\"insectos, enredaderas, bulbos y cosas empezaron a salir del suelo ... ¡fue \"\n\"horrible! Si tan solo tuviera algo normal para ponerme, no estaría tan mal. \"\n\"¡Oye! ¿Podrías volver a mi casa y traerme mi traje? El marrón, no el gris, \"\n\"es para la noche. Lo haría yo mismo, pero no quiero que nadie me vea así. \"\n\"Ten, toma esto, puede que lo necesites ... para matar a esas cosas que han \"\n\"crecido demasiado. No puedes perderte, mi casa está justo al sur de la \"\n\"bifurcación del río ... ya sabes ... la del huerto descuidado.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"¿En qué estás perdiendo el tiempo? ¡Ve por mi traje! ¡Y date prisa! ¡Ese \"\n\"Holstein de allí no deja de guiñarme el ojo!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Oye, ¿tienes mi traje ahí? ¡Rápido, pásalo! ¡Estos oídos pican como no lo \"\n\"creerías!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"¡No no no no! ¡Este es mi traje GRIS! ¡Es para la noche! ¡Ocasiones \"\n\"formales! No puedo usar ESTO. ¿Qué eres, una especie de bicho raro? Necesito \"\n\"el traje MARRÓN.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, eso es MUCHO mejor. ¡Uf! ¡Por fin, algo de dignidad! ¿Mis astas están \"\n\"rectas? Bien. Mira, muchas gracias por ayudarme. Ten, toma esto como un \"\n\"regalo; y, ya sabes ... un pequeño consejo de moda ... te vendría bien un \"\n\"poco ... podrías usar un nuevo ... ¿sabes lo que quiero decir? Todo el \"\n\"motivo de los aventureros es tan ... retro. Solo un consejo, ¿eh? Chao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Mirar Soy una vaca. Y tú, eres un cebo para monstruos. ¡Consigue algo de \"\n\"experiencia debajo de tu cinturón! Hablaremos ...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Realmente debe ser una tarea temible la que te he propuesto. Si hubiera \"\n\"alguna manera de que pudiera ... ¿ayudaría una jarra de leche fresca?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Oh, me vendría bien tu ayuda, pero quizás después de que hayas salvado las \"\n\"catacumbas de la profanación de esas bestias.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Necesito que se haga algo, pero no podría obligar a un perfecto desconocido. \"\n\"Quizás después de que hayas estado aquí un tiempo me sienta más cómodo \"\n\"pidiendo un favor.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Veo en ti el potencial de grandeza. ¿Quizás en algún momento mientras estás \"\n\"cumpliendo tu destino, podrías pasar y hacerme un pequeño favor?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Creo que probablemente podrías ayudarme, pero quizás después de que te hayas \"\n\"vuelto un poco más poderoso. ¡No quisiera dañar la única oportunidad que \"\n\"tiene el pueblo de destruir la amenaza en la iglesia!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Yo soy una vaca hecha a sí misma. Haz algo de ti mismo y ... luego \"\n\"hablaremos.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"¡No tengo que dar explicaciones a todos los turistas que pasan! ¿No tienes \"\n\"algunos monstruos que matar? Quizás hablemos más tarde. Si sigues vivo ..\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Deja de molestarme. Busco a alguien realmente heroico. Y no lo eres. No \"\n\"puedo confiar en ti, vas a ser devorado por monstruos en cualquier \"\n\"momento ... Necesito a alguien que sea un héroe experimentado.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Muy bien, iré al grano. No quise guiarte mal. Estaba sentado en casa, \"\n\"sintiéndome malhumorado, cuando las cosas se pusieron realmente inestables; \"\n\"¡Toda una estampida de monstruos salió del suelo! Solo me acobarde. Estaba \"\n\"usando esta camiseta cuando salí corriendo por la puerta, y ahora me veo \"\n\"terriblemente ridículo. Si tan solo tuviera algo normal para ponerme, no \"\n\"estaría tan mal. ¡Oye! ¿Puedes volver a mi casa y traerme mi traje? El \"\n\"marrón, no el gris, es para la noche. Lo haría yo mismo, pero no quiero que \"\n\"nadie me vea así. Ten, toma esto, puede que lo necesites ... para matar esas \"\n\"cosas que han crecido demasiado. No puedes perderte, mi casa está justo al \"\n\"sur de la bifurcación del río ... ya sabes ... la del huerto descuidado.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"He intentado hechizos, amenazas, abjuración y regateo con esta criatura \"\n\"repugnante, sin éxito. Mis métodos para esclavizar a los demonios menores \"\n\"parecen no tener ningún efecto sobre esta temible bestia.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Mi hogar se está corrompiendo lentamente por la vileza de este prisionero no \"\n\"deseado. Las criptas están\\tllenas de sombras que se mueven un poco más allá \"\n\"de las esquinas de mi visión. El leve roce de las garras baila en los bordes \"\n\"de mi oído. Están buscando, creo, este diario.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"En su despotricar, la criatura ha dejado escapar su nombre: Na-Krul. Intenté \"\n\"investigar el nombre, pero los demonios más pequeños de alguna manera \"\n\"destruyeron mi biblioteca. Na-Krul ... El nombre me llena de un pavor frío. \"\n\"Prefiero pensar en él solo como La Criatura en lugar de reflexionar sobre su \"\n\"verdadero nombre.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Los aullidos de furia de la criatura atrapada me impiden conseguir el sueño \"\n\"que tanto necesitaba. Se enfurece contra quien la envió al Vacío, y me \"\n\"maldice por haberla atrapado aquí. Sus palabras me llenan el corazón de \"\n\"terror y, sin embargo, no puedo bloquear su voz.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Mi tiempo se acaba rápidamente. Debo registrar las formas de debilitar al \"\n\"demonio y luego ocultar ese texto, no sea que sus secuaces encuentren alguna \"\n\"manera de usar mi conocimiento para liberar a su señor. Espero que quien \"\n\"encuentre este diario busque el conocimiento.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Quien encuentre este pergamino está encargado de detener a la criatura \"\n\"demoníaca que se encuentra dentro de estos muros. Mi tiempo se acabado. \"\n\"Incluso ahora, sus infernales secuaces se aferran a la frágil puerta detrás \"\n\"de la cual me escondo.\\n\"\n\" \\n\"\n\"He restringido al demonio con magia arcana y lo he encerrado dentro de \"\n\"grandes muros, pero me temo que eso no será suficiente.\\n\"\n\" \\n\"\n\"Los hechizos que se encuentran en mis tres grimorios te proporcionarán una \"\n\"entrada protegida a su dominio, pero solo si se lanzan en la secuencia \"\n\"adecuada. Las palancas en la entrada quitarán las barreras y liberarán al \"\n\"demonio ¡No las toques! Usa solo estos hechizos para lograr entrar o su \"\n\"poder puede ser demasiado grande para derrotarlo.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Jabinfierno\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Escorpión\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psychorb\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Arachnon\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Felltwin\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Engendro de Hork\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Cola Venenosa\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Necromorb\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Señor Araña\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Gusano de Pestañas\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Torchant\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Insecto del Infierno\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Sepulturero\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Rata de Tumba\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Murciélago de Fuego\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Calavera Alada\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lich\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Demonio de la Cripta\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Murciélago Infernal\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Demonio de Hueso\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Arch Lich\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biclope\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Cosa de Carne\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Segador\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Nudillo de Gigante\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Anillo Mercurial\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Anillo de Xorine\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Anillo de Karik\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Anillo de Magma\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Anillo de los Místicos\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Anillo de Trueno\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Amuleto de Protección\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Picadura de Mosquito\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Antorcha\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Armadura de Penumbra\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Rayo\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Tronido\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Devorador de Almas\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Filo Diamantado\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Cota de Malla de Hueso\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Armadura de Placas de Demonio\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Amuleto de Acólito\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Anillo de Gladiador\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"del bufón\"\n\n# **\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"cristalino\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"del doppelgänger\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"de la devastación\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"de la decadencia\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"del riesgo\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Maná\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"los Magos\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"el Bufón\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Pared de Relámpagos\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Inmolación\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Deformación\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Reflejar\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Berserk\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Anillo de Fuego\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Buscar\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Runa de Fuego\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Runa de Luz\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Runa de Nova\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Runa de Inmolación\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Runa de Piedra\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"¿Está intentando lanzar un objeto al suelo?\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Corazón\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Disminuir Gamma\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Incrementar Gamma\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Reiniciar en el pueblo\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Fuerzas la espera de sincronización vertical. Evita el efecto de desgarro \"\n#~ \"al dibujar un marco. Deshabilitarlo puede ayudar con el retraso del mouse \"\n#~ \"en algunos sistemas.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Limitador de FPS\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Los FPS están limitados para evitar altas cargas de CPU. El límite \"\n#~ \"considera la frecuencia de actualización.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Atacar\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Indestructible,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"No requiere atributos\"\n\n#~ msgid \"/help\"\n#~ msgstr \"/ayuda\"\n\n#~ msgid \"({command})\"\n#~ msgstr \"({command})\"\n\n#~ msgid \"/arena\"\n#~ msgstr \"/arena\"\n\n#~ msgid \"Command \\\"\"\n#~ msgstr \"Comando \\\"\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Automapa no disponible en la ciudad\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"Más allá del Salón de los Héroes se encuentra la Cámara de Hueso. La \"\n#~ \"muerte eterna aguarda a cualquiera que busque robar los tesoros guardados \"\n#~ \"dentro de esta habitación. Así habla el Señor del Terror, y así está \"\n#~ \"escrito.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"Las armerías del Infierno son el hogar del Señor de la Guerra de la \"\n#~ \"Sangre. A su paso yacían los cuerpos mutilados de miles. Tanto los \"\n#~ \"Ángeles como los hombres han sido liquidados para cumplir con sus \"\n#~ \"sacrificios interminables a los Oscuros que gritan por una cosa: sangre.\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Hoy nublado y fresco. Lanzando las redes de la nigromancia en el vacío \"\n#~ \"caerán dos nuevas subespecies de terror volador; un buen día de trabajo. \"\n#~ \"Debes recordar pedir más guano de murciélago y velas negras de Adria; Me \"\n#~ \"estoy quedando un poco bajo.\"\n\n#~ msgid \"left-click to target\"\n#~ msgstr \"clic izquierdo para apuntar\"\n\n#~ msgid \"Select from spell book, then\"\n#~ msgstr \"Seleccionar desde el libro de hechizos, entonces\"\n\n#~ msgid \"cast to read\"\n#~ msgstr \"lanzar para leer\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Opciones\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"versión {:s}\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"recuperar la vida\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"curación mortal\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"disminuiye la fuerza\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"disminuye la destreza\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"disminuye la vitalidad\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"no puedes curar\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"golpear al monstruo no cura\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Giro de ataque más rápido\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"ver con infravision\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"No se pudo abrir el archivo del reproductor para escribir.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"No se puede leer para guardar el archivo de archivo\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"No se puede escribir para guardar el archivo\"\n"
  },
  {
    "path": "Translations/et.po",
    "content": "#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: gpt-po v1.1.1\\n\"\n\"Language-Team: \\n\"\n\"Language: et\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: ;_;N_;ngettext:1,2;pgettext:1c,2;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Mängu disain\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Vanemdisainerid\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Lisakujundus\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Pearmarenduse juht\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Vanemprogrammeerijad\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programmeerimine\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Eri Külalisprogrammeerijad\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net programmeerimine\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Jadaside kommunikatsiooni programmeerimine\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Paigaldaja programmeerimine\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Kunstijuhid\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Kunstiteos\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Tehniline Kunstiteos\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Kinematograafilise kunsti direktorid\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D kinematograafilised kunstiteosed\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Kinemaatiline tehniline kunstiteos\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Tegevprodutsent\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Produtsent\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Produtsendi assistent\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Muusika\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Helikujundus\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Kinemaatiline muusika ja heli\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Hääle tootmine, lavastus ja casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Stsenaarium ja lugu\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Hääle redigeerimine\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Hääled\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Heliinsener\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Käsitsi kujundamine ja paigutus\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Käsitsi valmistatud kunstiteos\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"QA ajutine direktor (peatestija)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA rünnakumeeskond (testijad)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA erioperatsioonide meeskond (ühilduvuse testijad)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA suurtükiväe tugi (lisatestijad) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA vastuluure\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Võrguteabe Teenuste Ordu\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Klienditugi\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Müük\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Hr. Dabiri taustalauljad\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Avalikud suhted\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Turundus\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Rahvusvaheline müük\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"USA müük\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Tootmine\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Õigus ja äri\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Erilised tänud\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Tänu\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Mälestuseks\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Eriti suured tänud\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Peadirektor\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Tarkvarainsener\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Kunstijuht\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Kunstnikud\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Disain\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Helidisain, heliefektid ja audiotehnika\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Kvaliteedikontrolli juht\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testijad\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Käsiraamat\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tLisatöö\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Missiooni teksti kirjutamine\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Tänu\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tEritingilised tänud Blizzard Entertainmentile\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Kvaliteedikontrolli juht\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Kvaliteedi tagamise juhttestija\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Peamised testijad\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Lisatestijad\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Tooteturunduse juht\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Avalike suhete juht\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Tootejuhi assistent\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Tuhande Sõrmus\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tSelle mängu loomisel ei müüdud ühtegi hinge.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"Olgu\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Vali klass\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Tühista\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Uus mitmikmängu kangelane\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Uus üksikmängija kangelane\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Salvestusfail olemas\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Laadi mäng\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Uus mäng\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Üksikmängija tegelased\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Rogue ja Sorcerer on saadaval ainult Diablo täisversioonis. Külastage \"\n\"https://www.gog.com/game/diablo, et osta.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Sisesta nimi\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Vigane nimi. Nimi ei tohi sisaldada tühikuid, reserveeritud märke ega \"\n\"reserveeritud sõnu.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Ei saa tegelast luua.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Tase:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Jõud:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Maagia:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Osavus:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Elujõud:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Salvestusmäng:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Vali Kangelane\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Uus Kangelane\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Kustuta\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Mitmikmängu tegelased\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Kustuta mitmikmängu kangelane\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Kustuta üksikmängija kangelane\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Kas oled kindel, et soovid kustutada tegelase \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Üksikmängija\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Mitu mängijaga\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Seaded\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Tugi\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Kuva krediidid\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Välju Hellfire'ist\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Välju Diablos\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Jagamisvara\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Klient-server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Võrguühenduseta\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Mitmikmäng\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Nõuded:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"väravat pole vaja\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Vali ühendus\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Muuda lüüs\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Kõik arvutid peavad olema ühendatud TCP-ühilduva võrguga.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Kõik arvutid peavad olema internetiga ühendatud.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Mängi üksi ilma võrguühenduseta.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Mängijate tugi: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo jagamisversioon\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Põrgutule jagamisvara\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Host käitab teistsugust mängu kui sina.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Host töötab erinevas mängurežiimis ({:s}) kui sina.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Teie versioon {:s} ei ühti hosti versiooniga {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Kirjeldus:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Vali Tegevus\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Loo mäng\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Loo avalik mäng\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Liitu mänguga\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Avalikud mängud\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Laadimine...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Puudub\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"TÜHISTA\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Loo uus mäng oma valitud raskusastmega.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Loo uus avalik mäng, millega saavad liituda kõik, ja vali ise raskusaste.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Sisestage mängu ID, et liituda juba käimasoleva mänguga.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Sisestage IP-aadress või hostinimi, et liituda juba käimasoleva mänguga.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Liitu juba käimasoleva avaliku mänguga.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Tavaline\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Õudusunenägu\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Põrgu\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Raskusaste: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Kiirus: Tavaline\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Kiirus: Kiire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Kiirus: Kiirem\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Kiirus: Kõige kiirem\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Mängijad: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Vali Raskusaste\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Liitu {:s} mängudega\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Sisesta mängu ID\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Sisesta aadress\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Tavaline raskusaste\\n\"\n\"Siin peaks alustama oma teekonda Diablo alistamiseks algaja tegelane.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Õudusunenäo raskusaste\\n\"\n\"Labürindi elanikud on tugevdatud ja pakuvad suuremat väljakutset. See on \"\n\"soovitatav ainult kogenud tegelastele.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Põrgu Raskusaste\\n\"\n\"Allilma kõige võimsamad olendid varitsevad Põrgu väravas. Ainult kõige \"\n\"kogenumad tegelased peaksid sellesse valdkonda sisenema.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Sinu tegelane peab jõudma 20. tasemele, enne kui saad siseneda mitmikmängu \"\n\"Nightmare raskusastmel.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Sinu tegelane peab jõudma 30. tasemele, enne kui saad siseneda mitmikmängu \"\n\"Põrgu raskusastmel.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Vali mängu kiirus\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Kiire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Kiirem\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Kiireim\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Tavaline kiirus\\n\"\n\"Siin peaks algaja tegelane alustama oma teekonda Diablo alistamiseks.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Kiire kiirus\\n\"\n\"Labürindi elanikud on kiirendatud ja pakuvad suuremat väljakutset. See on \"\n\"soovitatav ainult kogenud tegelastele.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Kiirem kiirus\\n\"\n\"Enamik koopas elavaid koletisi otsib sind üles kiiremini kui kunagi varem. \"\n\"Ainult kogenud meister peaks proovima oma õnne sellel kiirusel.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Kiireim kiirus\\n\"\n\"Allilma käsilased tormavad ründama kõhklemata. Ainult tõeline kiirusdeemon \"\n\"peaks sellise tempoga sisenema.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Sisesta parool\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Sisene Põrgutulle\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Lülita Diablole\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Jah\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Ei\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Vajutage mängupuldi nuppe, et muuta.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Seotud klahv:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Vajuta suvalist klahvi, et muuta.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Eemalda klahv\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Seotud nupu kombinatsioon:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Eemalda nupu kombinatsioon\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Eelmine menüü\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Meil on Discord.gg/devilutionx vestlusserver. Järgige linke, et liituda meie \"\n\"kogukonnaga, kus arutame Diablo ja Hellfire'i laiendusega seotud teemasid.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX-i haldab Diasurgical, probleeme ja vigu saab raporteerida sellel \"\n\"aadressil: https://github.com/diasurgical/devilutionX Et saaksime teid \"\n\"paremini teenindada, palun lisage kindlasti versiooninumber, \"\n\"operatsioonisüsteem ja probleemi olemus.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Vastutusest loobumine:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX-i ei toeta ega halda Blizzard Entertainment ega GOG.com. Ei \"\n\"Blizzard Entertainment ega GOG.com pole testinud ega sertifitseerinud \"\n\"DevilutionX-i kvaliteeti või ühilduvust. Kõik DevilutionX-iga seotud \"\n\"päringud tuleks suunata Diasurgicalile, mitte Blizzard Entertainmentile ega \"\n\"GOG.com-ile.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tSee port kasutab fonte Charis SIL, New Athena Unicode, Unifont ja Noto, \"\n\"mis on litsentsitud SIL Open Font License'i alusel, samuti Twitmoji, mis on \"\n\"litsentsitud CC-BY 4.0 alusel. Port kasutab ka SDL-i, mis on litsentsitud \"\n\"zlib-litsentsi alusel. Täpsemat teavet leiate ReadMe failist.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Autoriõigus © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Viga\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Viga ilmnes: {:s} rida {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Andmefaili viga\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Peamine andmearhiiv ei saa avada ({:s}).\\n\"\n\"\\n\"\n\"Veendu, et see on mängu kaustas.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Kirjutuskaitstud kataloogi viga\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Ei saa asukohta kirjutada:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Mäng: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Võrguühenduseta mäng\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Parool: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Avalik mäng\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Tase: Pesa {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Tase: Krüpt {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Linn\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Tase: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Vahekaart\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Sisene\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Tegelase teave\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Ülesannete logi\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Automaatkaart\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Põhimenüü\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventuur\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Loitsuraamat\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Saada sõnum\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Saadaolevad käsud:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Käsklus \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" on tundmatu.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Kirjeldus: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parameetrid: Täiendavaid parameetreid pole vaja.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parameetrid: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Areenid on toetatud ainult mitmikmängus.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Millist areeni sa külastada tahad?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Vigane areeni number. Kehtivad numbrid on:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"Arena sisenemiseks pead olema linnas või teises arenas.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Uurimine on toetatud ainult mitmikmängus.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Mängijate kontrollimine peatatud.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Sellise nimega mängijaid ei leitud\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Mängija kontrollimine: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Prindib abi ülevaate või abi konkreetse käsu jaoks.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[käsk]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Sisene PvP areenile.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<arena-number>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Annab areeni potioneid.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<number>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Uurib teise mängija statistikat ja varustust.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<mängija nimi>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Kuva praeguse taseme seemneinfo.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Mängijasõbralik\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Mängija rünnak\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Kiirklahv: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Vali praegune loitsu nupp\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Kiirklahv: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} oskus\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} loits\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Loitsu tase 0 - Kasutuskõlbmatu\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Loitsu tase {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"{:s} kerimine\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Kirjarull\"\nmsgstr[1] \"{:d} Kirjarullid\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"{:s} sau\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Laeng\"\nmsgstr[1] \"{:d} Laengut\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} kuldmünt\"\nmsgstr[1] \"{:s} kuldmünti\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Nõuded ei ole täidetud\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Tase: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Elupunktid {:d} / {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Paremklõpsake kasutamiseks\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Taseme tõus\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Sul on {:s} kuldmünt. Mitu soovid eemaldada?\"\nmsgstr[1] \"Sul on {:s} kuldmünti. Mitu soovid eemaldada?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Linnaportaal\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"pärit {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portaal siia\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Püha Altar\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"tase 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Ei saa laadida andmeid failist {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} on puudulik, palun kontrollige faili sisu.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"Teie {0} failis ei ole oodatud veerge, palun veenduge, et see vastab \"\n\"dokumenteeritud vormingule.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Mittearvuline väärtus {0} jaoks {1} failis {2} reas {3} ja veerus {4}\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Väärtus {0} on vahemikust väljas {1} failis {2} reas {3} ja veerus {4}\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Vigane väärtus {0} {1} jaoks failis {2} reas {3} ja veerus {4}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Prindi see sõnum ja välju\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Prindi versioon ja välju\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Määrake diabdat.mpq kaust\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Määrake salvestusfailide kaust\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Määrake diablo.ini asukoht\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Määrake keelekood (nt en või pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Jäta käivitamise videod vahele\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Kuva kaadreid sekundis\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Luba üksikasjalik logimine\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Salvesta demo fail\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Esita demofaili\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Lülita demo taasesituse ajal kõik kaadrisageduse piirangud välja\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Mängu valik:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Sunni jagatud tarkvara režiimi\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Sunni Diablo režiim\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Sunniviige Hellfire-režiim\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Põrgutule valikud:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Teata vigadest aadressil https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"Palun uuenda devilutionx.mpq ja fonts.mpq uusimale versioonile\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Kasutajaliidese ressursside laadimine ebaõnnestus.\\n\"\n\"\\n\"\n\"Veenduge, et devilutionx.mpq on mängu kaustas ja et see on ajakohane.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Palun uuenda fonts.mpq uusimale versioonile\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Võrgu ajutine katkestus --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Ootan mängijaid --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Abi pole saadaval\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"kauplustes olles\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Vöö ese {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Kasutage vöö eset.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Kiirloits {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Klahvivajutus oskuse või loitsu jaoks.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Eelmine kiire loits\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Valib eelmise kiire loitsu (tsüklis).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Järgmine kiire loits\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Valib järgmise kiire loitsu (tsüklitena).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Kasutage tervise eliksiiri\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Kasutage tervise potioneid vööst.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Kasutage mana jooki\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Kasutage vööst mana potioneid.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Kiirraamat\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Ava kiirusraamat.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Kiirsalvestus\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Salvestab mängu.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Kiirlaadimine\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Laeb mängu.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Lõpeta mäng\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Sulgeb mängu.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Peatu, kangelane\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Lõpetab kõndimise ja tühistab ootel olevad toimingud.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Esemete esiletõstmine\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Kuva/peida maas olevaid esemeid.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Lülita esiletõstetud esemed sisse/välja\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Püsivalt näita/peida esemeid maapinnal.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Lülita automaatkaart sisse/välja\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Lülitab sisse/välja automaadi kuvamise.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Vaheta kaarditüüpi\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Läbipaistmatu -> Läbipaistev -> Minikaart -> Puudub\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Ava laoseis.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Tegelane\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Ava tegelase ekraan.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Ülesannete logi\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Ava ülesannete logi.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Loitsuraamat\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Ava loitsuraamat.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Kiire sõnum {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Kasutage vestluses kiirsõnumit.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Peida infoekraanid\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Peida kõik infoekraanid.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Suumi\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Suumi mänguekraani.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Pausi mäng\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Peatab mängu.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pausi mäng (alternatiivne)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Suurenda ekraani heledust.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Vähenda ekraani heledust.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Suurenda ekraani heledust.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Suurenda ekraani heledust.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Aita\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Ava Abi-ekraan.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Kuvatõmmis\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Teeb ekraanipildi.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Mängu info\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Kuvab mängu infot.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Vestluse logi\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Kuvab vestluslogi.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Sorteeri inventar\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Järjestab inventari.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Konsool\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Avab Lua konsooli.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Põhitegevus\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Ründa koletisi, räägi linnaelanikega, tõsta ja paiguta inventari esemeid.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Teisene tegevus\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Ava kirste, suhtle ustega, korja esemeid.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Loitsu tegevus\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Loitsu aktiivne loits.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Tühista toiming\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Sulge menüüd.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Liigu üles\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Liigutab mängijategelast üles.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Liigu alla\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Liigutab mängijategelast alla.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Liigu vasakule\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Liigutab mängijategelast vasakule.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Liigu paremale\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Liigutab mängijategelast paremale.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Seisa paigal\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Hoia all, et takistada mängijal liikumist.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Lülita paigale jäämine sisse/välja\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Lülita mängija liikumine sisse või välja.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Automaatkaart\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Liigu alla\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Liigu vasakule\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Liigutab mängijategelast üles.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Liigu paremale\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Liiguta hiirt üles\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Simuleerib hiire liikumist ülespoole.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Liiguta hiirt alla\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Simuleerib hiire liikumist allapoole.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Liiguta hiirt vasakule\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Simuleerib hiire liikumist vasakule.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Liiguta hiirt paremale\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Simuleerib hiire liikumist paremale.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Vasaku hiireklõps\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Simuleerib vasaku hiireklahvi.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Parem hiireklõps\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Simuleerib parema hiireklahvi.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Mängupuldi kiirloitsude menüü\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Hoia all, et määrata või kasutada loitsu kiirklahve.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Mängupuldi menüü navigeerija\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Hoia all, et pääseda mängupuldi menüü navigeerimisele.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Lülita mängumenüü\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Avab mängu menüü.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Mäng salvestatud\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Demos pole mitmikmängu funktsioone\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Direct Soundi loomine ebaõnnestus\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Pole saadaval jagamisversioonis\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Pole piisavalt ruumi salvestamiseks\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Linnas ei saa pausi teha\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Soovitatav on kopeerida kõvakettale\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Mitmikmängu sünkroonimise probleem\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Mitmikmängus pole pausi\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Salvestamine...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Mõned nõrgenevad, kui üks tugevneb\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Uus jõud sepistatakse hävingu kaudu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Need, kes kaitsevad, ründavad harva\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Õigluse mõõk on kiire ja terav\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Kui vaim on valvas, siis keha õitseb\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Mana jõudude keskendumine uuendab\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Aeg ei suuda terase jõudu kahandada\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Maagia ei ole alati see, mis ta näib olevat\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Mis kord oli avatud, on nüüd suletud\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Intensiivsus tuleb tarkuse hinnaga\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Arkaaniline jõud toob hävingu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Seda, mida ei saa hoida, ei saa ka kahjustada\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Karmiin ja asuur muutuvad kui päike\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Teadmised ja tarkus enese arvelt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Joo ja tunne end värskena\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Kuhu iganes sa lähed, seal sa oled\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Energia tuleb tarkuse hinnaga\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Rikkus tuleb siis, kui seda kõige vähem ootad\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Kus ahnus jääb hätta, seal kannatlikkus toob tasu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Õnnistatud heatahtliku kaaslase poolt!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Inimeste käsi võib saatus juhtida\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Jõud on taevasest usust tugevdatud\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Elu olemus voolab seestpoolt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Tee saab selgeks, kui vaadata ülevalt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Pääsemine tuleb tarkuse hinnaga\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Mõistuse valguses paljastuvad saladused\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Need, kes on viimased, võivad veel esimesteks saada\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Heldus toob endaga kaasa oma tasu\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Selle kasutamiseks peab sul olema vähemalt 8. tase.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Sa pead olema vähemalt 13. tasemel, et seda kasutada.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Sa pead olema vähemalt 17. tasemel, et seda kasutada.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Salapärane teadmine omandatud!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"See, mis sind ei tapa...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Teadmine on jõud.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Anna ja sulle antakse.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Mõningaid kogemusi saadakse puudutuse kaudu.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Kodu pole kusagil mujal.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Vaimne energia on taastatud.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Sa tunned end väledamana.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Sa tunned end tugevamana.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Sa tunned end targemana.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Sa tunned end värskena.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"See, mis võib puruneda, purunebki.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedraal\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Katakombid\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Koopad\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Pesa\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Krüpt\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Tase {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} raskusaste\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Menüüs\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"tagasiside\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Ühendamine ebaõnnestus\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"viga: serverilt loeti 0 baiti\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq või spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Mõned Hellfire MPQ-d on puudu\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Mitte kõiki Hellfire MPQ-sid ei leitud. Palun kopeerige kõik hf*.mpq failid.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Lahendus\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Jookse linnas\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Theo Otsing\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Lehma ülesanne\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Automaatne kulla korjamine\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Automaatne eliksiiri korjamine\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Automaatne õli korjamine\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Automaatne korjamine linnas\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria täidab mana\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Relvade automaatne varustamine\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Automaatne soomuse varustamine\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Kiivrite automaatne varustamine\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Automaatne kilpide varustus\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Ehete automaatne varustamine\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Juhuslikud ülesanded\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Kuva üksuste sildid\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Vöö automaatne täitmine\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Keela halvavad pühamud\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Tervendamisjoogi korjamine\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Täieliku tervendamise joogi korje\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Mana poti valimine\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Täis mana poti korjamine\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Noorendamise joogi korjamine\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Täieliku noorendamise joogi korjamine\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Valikud\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Salvesta mäng\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Põhimenüü\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Lõpeta mäng\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Kiirus\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Muusika on keelatud\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Heli\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Heli on keelatud\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Paus\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Klaviatuuri otseteed:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Ava abiaken\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Kuva põhimenüü\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Kuva automaatkaarti\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Tühik: Peida kõik infoekraanid\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Ava kiirusraamat\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Ava loitsuraamat\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Ava inventari ekraan\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Ava oma tegelaskuju ekraan\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"K: Ava ülesannete logi\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Vähenda ekraani heledust\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Suurenda ekraani heledust\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Suurenda mänguekraani\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Suumi automaatkaarti\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Kasuta vöö eset\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Määra oskuse või loitsu kiirklahv\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Vasak hiireklahv: Ründa ilma liikumata\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Vasak hiireklõps (tegelase ekraanil): Määra kõik statistika punktid\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Vasak hiireklõps (inventaris): Liiguta ese vööle või varusta/eemalda \"\n\"ese\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Vasak hiireklõps (vööl): Liiguta ese inventari\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Liikumine:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Kui hoiad hiire nuppu all liikumise ajal, liigub tegelane jätkuvalt selles \"\n\"suunas.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Võitlus:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Shift-klahvi all hoidmine ja seejärel vasakklõpsamine võimaldab tegelasel \"\n\"rünnata ilma liikumata.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Automaatkaart:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Automaatkaardi avamiseks klõpsa teaberibal nupule 'MAP' või vajuta \"\n\"klaviatuuril 'TAB'. Kaardi sisse- ja väljasuumimine toimub + ja - \"\n\"klahvidega. Kaardi kerimiseks kasuta nooleklahve.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Esemete korjamine:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Kasutatavad esemed, mis on väikesed, nagu näiteks joogid või rullid, \"\n\"paigutatakse automaatselt sinu 'vööle', mis asub liideseriba ülaosas. Kui \"\n\"ese asetatakse vööle, ilmub sellesse kasti väike number. Esmeid saab \"\n\"kasutada kas vastava numbri vajutamisega või esemel paremklõpsuga.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Kuld:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Sa saad valida konkreetse koguse kulda, mida maha panna, klõpsates oma \"\n\"inventaris kulla kuhjal parema hiireklahviga.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Osavused ja Loitsud:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Oma oskuste ja loitsude loendi saad avada, klõpsates liideseribal \"\n\"vasakklõpsuga nupul 'LOITSUD'. Siin on loetletud meelde jäetud loitsud ja \"\n\"need, mis on saadaval keppide kaudu. Loitsu, mida soovid kasutada, saad \"\n\"valmis seada, klõpsates sellel vasakklõpsuga. Valmis seatud loitsu saab \"\n\"kasutada, klõpsates mängualal lihtsalt parema hiireklõpsuga.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Loitsude kiirraamatu kasutamine:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Vasakklõps 'valmis loitsu' nupul avab 'Kiiraamatu', mis võimaldab valida \"\n\"oskuse või loitsu koheseks kasutamiseks. Valmis oskuse või loitsu \"\n\"kasutamiseks klõpsa lihtsalt parema hiireklahviga mänguala peal.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + vasakklõps nupul 'vali praegune loits' tühistab valmis pandud loitsu.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Loitsuklahvide seadistamine:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Saate määrata kuni neli kiirklahvi oskuste, loitsude või rullide jaoks. \"\n\"Alustage 'kiirraamatu' avamisega, nagu on kirjeldatud ülaltoodud jaotises. \"\n\"Vajutage F5, F6, F7 või F8 klahve pärast loitsu esiletõstmist, mille soovite \"\n\"määrata.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Loitsuraamatud:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Rohkem kui ühe raamatu lugemine suurendab sinu teadmisi sellest loitsust, \"\n\"võimaldades sul loitsu tõhusamalt kasutada.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Shareware Hellfire Abi\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Põrgutule Abi\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Shareware Diablo Abi\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Diablo Abi\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Vajuta ESC, et lõpetada, või nooleklahve, et kerida.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Peaakna loomine ebaõnnestus\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Pole ruumi esemele\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Täpsuse õli\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Meisterlikkuse õli\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Teravuse õli\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Surmaõli\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Oskuste õli\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Sepa õli\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Vastupidavuse õli\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Püsivuse õli\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Kõvastamise õli\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Läbimatuse õli\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}-st\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}-st\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}-st\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"suureneb relva\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"tabamuse tõenäosus\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"suuresti suurendab a\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"relva tabamuse tõenäosus\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"kahjustuste potentsiaal\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"suuresti suurendab relva\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"kahjustuste potentsiaal - mitte vibud\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"vähendab vajalikke atribuute\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"kasutada turvist või relvi\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"taastab 20%\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"eseme vastupidavus\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"suurendab eseme\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"praegune ja maksimaalne vastupidavus\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"muudab eseme purunematuks\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"suurendab soomusklassi\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"rüüde ja kilpide\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"suurendab oluliselt turvist\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"rüüde ja kilpide klass\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"seab püünise põlema\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"seab välgu lõksu\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"seab kivistamise lõksu\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"taasta kogu elu\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"taasta veidi elu\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"taasta veidi mana\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"taasta kogu mana\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"tõsta jõudu\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"suurenda maagiat\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"suurenda osavust\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"suurenda vitaalsust\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"taasta veidi elu ja mana\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"taasta kogu elu ja mana\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(toimib ainult areenidel)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Paremklõpsake, et vaadata\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Paremklõpsake kasutamiseks\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Paremklõps lugemiseks, seejärel\\n\"\n\"vasakklõps sihtimiseks\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Paremklõpsake, et lugeda\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Aktiveeri vaatamiseks\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Ava laoseis kasutamiseks\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Aktiveeri kasutamiseks\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Vali loitsuraamatust, seejärel\\n\"\n\"loitsu lugemiseks kasuta loitsu\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Aktiveeri lugemiseks\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} vaatamiseks\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} kasutada\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"Vali loitsuraamatust, seejärel {} lugemiseks\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} lugemiseks\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Tase: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Kahekordistab kulla mahutavuse\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Nõutud:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Jõud\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mana\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Osavus\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"{:s} raamat\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s} kõrv\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"tabamuse tõenäosus: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% kahju\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"tabamus: {:+d}%, {:+d}% kahju\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% soomus\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"soomusklass: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Tulekindluse vastupanu: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Tulekindluse vastupanu: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Vastupanu välgule: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Vastupanu välgule: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Maagiakindlus: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Võlujõu vastupanu: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Kõikide vastupanu: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Kõikide vastupanu: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"loitsud on suurendatud {:d} tase\"\nmsgstr[1] \"loitsud on suurendatud {:d} tasemele\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"loitsud on vähendatud {:d} tase\"\nmsgstr[1] \"loitsud on vähendatud {:d} tasemele\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"loitsutasemed muutmata (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Lisatasud\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} laeng\"\nmsgstr[1] \"{:d} {:s} laengut\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Tulekahju tabamiskahju: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Tulekahju tabamiskahju: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Välgu tabamiskahju: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Välgu tabamiskahju: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} jõudu\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} maagiale\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} osavusele\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} vitaalsusele\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} kõigile atribuutidele\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} kahju vaenlastelt\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Elupunktid: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"kõrge vastupidavus\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"vähenenud vastupidavus\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"hävimatu\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% valgusraadius\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% valgusraadius\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"mitu noolt ühe lasu kohta\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"tule noolte kahju: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"tule noolte kahju: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"välgu nooled teevad kahju {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"välgunooled teevad kahju {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"tulepalli kahju: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"tulepalli kahju: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"rünnakut sooritaja saab 1-3 kahju\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"kasutaja kaotab kogu mana\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"neelab poole lõksu tekitatud kahjust\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"lööb sihtmärgi tagasi\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% kahju deemonite vastu\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Kõik vastupidavused on 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"tabamus röövib 3% mana\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"tabamus röövib 5% mana\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"tabamus varastab 3% elu\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"tabamus varastab 5% elu\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"läbib sihtmärgi soomust\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"kiire rünnak\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"kiire rünnak\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"kiirem rünnak\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"kiireim rünnak\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Teine oskus (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"kiire löögist taastumine\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"kiirem löögist taastumine\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"kiireim löögist taastumine\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"kiire blokeerimine\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"lisab {:d} punkti kahjustusele\"\nmsgstr[1] \"lisab {:d} punkti kahjustusele\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"laseb juhusliku kiirusega nooli\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"ebatavaline eseme kahjustus\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"muudetud vastupidavus\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"ühekäeline mõõk\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"kaotab pidevalt elupunkte\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"eluvargus varastamine\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"jõu nõue puudub\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"välgu kahjustus: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"välgu kahjustus: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"laetud poldid tabamustel\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"aeg-ajalt kolmekordne kahju\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"mädanev {:+d}% kahju\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x kahju koletistele, 1x sulle\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Juhuslik 0 - 600% kahju\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"madal vastupidavus, {:+d}% kahju\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"lisakaitse vs deemonid\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"lisakaitse vs elavad surnud\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Manast kantakse tervisesse\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% tervisest kantakse manasse\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"kahju: {:d}  Hävimatu\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"kahju: {:d}  Kestvus: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"kahju: {:d}-{:d}  Hävimatu\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"kahju: {:d}-{:d}  Kestvus: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"turvis: {:d}  Hävimatu\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"turvis: {:d}  Kestvus: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Laengud: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"ainulaadne ese\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Pole tuvastatud\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Skeletikuningas Luur\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Luukambrikamber\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labürint\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Mürgitatud veevarustus\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Peapiiskop Lazaruse Luur\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Kirikuvõitlusareen\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Põrgu Areen\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Eluringi Elu Areen\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Alla koopasse\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Alla katakombidesse\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Alla koobastesse\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Alla põrgusse\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Alla Tarusse\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Alla Krüpti\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Kuni tasemeni {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Linna poole\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Alla tasemele {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Alla Diablo juurde\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Kuni pesa tasemeni {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Kuni krüpti tasemeni {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Maailma nurgakivi\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Alla Krüpti tasemele {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Tagasi tasemele {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Ei saa salvestusfaili arhiivi avada\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Vigane salvestusfail\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Mängija on ainult Hellfire'i tasemel\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Kehtetu mänguseisund\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Peamenüüd ei saa kuvada\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Loom\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demon\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Elavad surnud\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Tüüp: {:s}  Tapmised: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Kokku tapetud: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Elupunktid: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Pole maagilist vastupanu\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Vastupanu:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Maagia\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Tuli\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Välk\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Immuunne:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Tüüp: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Pole vastupanuvõimet\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Pole immuunsusi\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Mõned maagilised vastupidavused\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Mõned maagilised immuunsused\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Arhiivi avamine kirjutamiseks ebaõnnestus.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} on teinud kehtetu loitsu.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} on lausunud ebaseadusliku loitsu.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Mängija '{:s}' (tase {:d}) liitus just mänguga\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Mäng lõppes\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Ei saa taseme andmeid kätte\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Mängija '{:s}' lahkus just mängust\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Mängija '{:s}' tappis Diablo ja lahkus mängust!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Mängija '{:s}' eemaldati ajapiirangu tõttu\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Mängija '{:s}' (tase {:d}) on juba mängus\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Müstiline\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Peidetud\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Sünge\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Kummaline\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Maagiline\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Kivi\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Religioosne\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Lummatud\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Taumaturgiline\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Põnev\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Salapärane\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Eldritch\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Õudne\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Jumalik\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Püha\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Püha\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Vaimne\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Kummituslik\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Mahajäetud\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"<translatedÕudne\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Vaikne\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Eraldatud\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Uhke\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Särav\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Rikutud\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Õline\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Helendav\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Kerjuse\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Sädelev\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Särav\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Päikese\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Murphy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Suur Konflikt\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Patu palk on sõda\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Horadrimi lugu\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Tume Pagendus\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Patu sõda\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Kolme sidumine\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Maailmad Teispool\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Kolme lugu\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Must Kuningas\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Päevik: Nõidus\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Päevik: Kohtumine\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Päevik: Tirade\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Päevik: Tema jõud kasvab\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Päevik: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Päevik: Lõpp\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Loitsuraamat\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Ristilöödud luukere\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Hoob\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Ava uks\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Suletud uks\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Blokeeritud uks\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Muinastome\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Rõveduse raamat\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Koljuka hoob\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Müütiline raamat\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Väike kirst\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Kirst\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Suur kirst\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarkofaag\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Raamaturiiul\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Raamatukapp\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Tünn\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Kapsel\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urn\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} pühamu\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Skeleti Tom\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Raamatukogu raamat\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Verikaev\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Peata keha\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Pimedate raamat\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Vere raamat\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Puhastav Allikas\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Rüü\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Relvastend\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Kitsesümbol\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Katel\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Hägune bassein\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Pisarate allikas\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Terastome\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Vere altar\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Seeneplats\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"<translated:Jõle Seis>\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Tapetud kangelane\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"Lõksus {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (keelatud)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"SEES\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"VÄLJAS\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Mängurežiim\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Mängu seaded\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Mängi Diablo või Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Piira jagatavaks tarkvaraks\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Muudab mängu demoga ühilduvaks. Võimaldab mitmikmängu sõpradega, kellel pole \"\n\"Diablo täisversiooni.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Käivita\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Käivitamise seaded\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Sissejuhatus\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Kuvatud sissejuhatav filmikunst.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Plärtsatus\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Kuvatud avakuva.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo ja tiitliekraan\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Tiitli ekraan\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Diablo spetsiifilised seaded\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Põrgutule spetsiifilised seaded\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Heli\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Heliseaded\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Kõndimise heli\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Mängija teeb kõndides häält.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Automaatne varustuse heli\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Esemete automaatne varustamine peale korjamist tekitab varustuse heli.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Eseme korjamise heli\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Esemete üleskorjamine tekitab esemete üleskorjamise heli.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Proovivõtu sagedus\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Väljundproovi sagedus (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanalid\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Väljundkanalite arv.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Puhvri suurus\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Puhvri suurus (kaadrite arv kanali kohta).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Ümberproovide kvaliteet\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Resampleri kvaliteet, vahemikus 0 (madalaim) kuni 10 (kõrgeim).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Mõjutab mängu sisemist resolutsiooni ja määrab sinu vaateala. Märkus: See \"\n\"võib erineda ekraani resolutsioonist, kui kasutatakse üleskaalumist, \"\n\"täisarvulist skaleerimist või ekraanile sobitamist.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Ümberproovija\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Heli resampler\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Seade\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Heliseade\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Graafika\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Graafika seaded\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Täisekraan\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Kuva mäng akna- või täisekraanirežiimis.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Sobita ekraanile\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Kohanda mänguaken automaatselt vastavalt sinu praeguse töölaua ekraani \"\n\"kuvasuhtele ja resolutsioonile.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Kvaliteetne\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Võimaldab pildi skaleerimist mängu resolutsioonist teie monitori \"\n\"resolutsioonini. Takistab monitori resolutsiooni muutmist ja võimaldab akna \"\n\"suuruse muutmist.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Skaleerimise kvaliteet\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"Võimaldab valikulisi filtreid väljundpildile, kui suurendatakse.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Lähim piksel\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilineaarne\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotroopne\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Täisarvu skaleerimine\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Skaalib pilti, kasutades täisarvulist pikslite suhet.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Vertikaalne sünkroonimine\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Suumi sisse, kui lubatud.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Välk\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Värvide tsükkel\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Vee, laava ja happe animatsiooni jaoks kasutatav värvide tsükliefekt.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternatiivne pesa kunst\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"Mäng kasutab Hellfire'i pesa plaatide komplekti jaoks alternatiivset paletti.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Riistvaraline kursor\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Kasutage riistvaralist kursorit\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Riistvara kursor esemete jaoks\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Kasutage esemete jaoks riistvaralist kursorit.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Riistvara kursori maksimaalne suurus\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Riistvaralise kursoriga maksimaalne laius / kõrgus. Suuremad kursorid \"\n\"langevad tagasi tarkvaralisele.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Kuva FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Kuvab FPS-i ekraani vasakus ülanurgas.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Mängukogemus\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Mängu seaded\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Luba Diablo ja Hellfire'is linnas sörkimine/kiirkõndimine. See valik toodi \"\n\"sisse laienduses.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Haara sisend\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Kui see on lubatud, on hiir lukustatud mänguaknasse.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Peata mängu, kui aken kaotab fookuse\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"Kui see on lubatud, peatub mäng fookuse kaotamisel.\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Luba Tüdruku ülesande lubamine.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"Luba Jersey ülesanne. Lester talunik asendatakse Täieliku Pähkliga.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Sõbralik Tuli\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Luba noole/kirja kahju mängijate vahel mitmikmängus isegi siis, kui sõbralik \"\n\"režiim on sisse lülitatud.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Täielikud ülesanded mitmikmängus\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Võimaldab ülesannete täispika/lõikamata üksikmängu versiooni.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Testi Bard\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Sunni Bard tegelase tüüp ilmuma kangelase valiku menüüs.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Testi Barbar\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Sunni barbaari tegelase tüüp kangelase valiku menüüs ilmuma.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Kogemuste riba\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Kogemuste riba lisatakse kasutajaliidesele ekraani alaossa.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Kuva poodides esemete graafika\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"Kuva poe menüüdes esemete kirjelduste vasakul pool esemete graafika.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Kuva tervise väärtused\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Kuvab tervisekeral praeguse / maksimaalse tervise väärtuse.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Kuva mana väärtused\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Kuvab mana globil praeguse / maksimaalse mana väärtuse.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Tegelase teave\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Vaenlase terviseriba\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Vaenlase terviseriba kuvatakse ekraani ülaosas.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Kuld kogutakse automaatselt, kui see on mängijale lähedal.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Eliksiirid kogutakse automaatselt, kui mängija on neile lähedal.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Õlid korjatakse automaatselt üles, kui mängija on neile lähedal.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Korjas automaatselt esemeid linnas üles.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria täidab su mana, kui sa tema poodi külastad.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Relvad varustatakse automaatselt peale korjamist või ostmist, kui see on \"\n\"lubatud.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Kaitsevarustus varustatakse automaatselt peale võtmist või ostmist, kui see \"\n\"on lubatud.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Kiivrid varustatakse automaatselt peale korjamist või ostmist, kui see on \"\n\"lubatud.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Kilbid varustatakse automaatselt, kui need on lubatud, kas korjamisel või \"\n\"ostmisel.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Ehted varustatakse automaatselt peale korjamist või ostmist, kui see on \"\n\"lubatud.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Uute mängude jaoks saadaval olevate ülesannete juhuslik valimine.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Kuva koletise tüüp\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Kui liigud koletise kohale, kuvatakse kasutajaliideses kirjelduskastis \"\n\"koletise tüüp.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Kuva maas olevate esemete sildid, kui see on lubatud.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Vöö täitmine inventarist, kui vöö ese on tarbitud.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Kui need on lubatud, ei saa katlaid, lummavaid pühamuid, kitsepühamuid, \"\n\"kaunistatud pühamuid, pühasid pühamuid ja Murphy pühamuid klõpsata ning need \"\n\"on märgitud keelatuks.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Kiirvalamine\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Loitsu kiirklahvid lasevad loitsu koheselt, selle asemel et vahetada \"\n\"valmisolekus olevat loitsu.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Tervendamisjoogide arv, mida automaatselt üles korjata.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Täis tervendamise jookide arv, mida automaatselt üles korjata.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Automaatne manapudelite kogus, mida üles korjata.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Täis mana jookide arv, mida automaatselt üles korjata.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Elustamisjoogi automaatseks korjamiseks mõeldud arv.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Täis elustamisjoogi automaatseks korjamiseks mõeldud arv.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Luba hõljuvad numbrid\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"Võimaldab ujuvaid numbreid XP saamisel / kahju tekitamisel jne.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Väljas\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Juhuslikud nurgad\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Ainult vertikaalne\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Kontroller\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Kontrolleri seaded\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Võrk\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Võrgu seaded\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Vestlus\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Vestluse seaded\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Keel\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Määrake, millist keelt mängus kasutada.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Keelesätted\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Klahvivajutus\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Klahvivajutuse seaded\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Padi kaardistamine\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Puldimapi seaded\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Seaded\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Tase\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Kogemus\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Järgmine tase\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Alus\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Nüüd\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Jõud\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Maagia\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Osavus\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Elujõud\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Punkte jagamiseks\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Kuld\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Rüü klass\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"tabamuse tõenäosus\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Kahju\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Elu\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Võlujõu kaitse\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Tule kaitse\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Välgu kaitse\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"tegelane\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"ülesanded\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"kaart\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menüü\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"inv\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"loitsud\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"hääl\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"vaigistama\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Kasutamiskõlbmatu\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Kahju: 1/3 sihtmärgi hp\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Ravib: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Kahju: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Oskus\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Kepp ({:d} laeng)\"\nmsgstr[1] \"Kepp ({:d} laengut)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Tase {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Loits\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Kahjustab ainult elavaid surnuid\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Käsk\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Kepp\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Loitsu kiirklahv {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Arhiivi avamine ebaõnnestus\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Ei saa tegelast laadida\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (tase {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Vestluse ajalugu (Sõnumid: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} kuld\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Mitu kuldtükki soovite välja võtta?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Tase {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Kogemus: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Maksimaalne tase\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Järgmine tase: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} tasemele {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Kuningas Leorici haud\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Luukambrike\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Tume läbikäik\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Püha altar\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Asukohta {:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Mul on abi vaja! Tule siia!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Järgne mulle.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Siin on midagi sinu jaoks.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Nüüd sa SURED!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Tervenda end!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Ole ettevaatlik!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Aitäh.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Tagasi!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Vabandust.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Ma ootan.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Kain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Tagasi\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \", \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Kahju: {:d}-{:d} \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Rüü: {:d} \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Vastupidavus: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Purunematu\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Tere tulemast\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Sepa pood\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Kas soovite:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Räägi Griswoldiga\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Osta põhiesemeid\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Osta premium-esemeid\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Müü esemeid\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Paranda esemeid\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Lahku poest\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Mul on need esemed müügiks:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Mul on müüa need esmaklassilised esemed:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Sul pole midagi, mida ma tahaksin.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Milline ese on müügil?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Sul pole midagi parandada.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Millist eset parandada?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Nõiaonn\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Räägi Adriaga\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Osta esemeid\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Laadige sauasid\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Jäta hütt\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Sul pole midagi laadida.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Millist eset laadida?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Sul pole piisavalt kulda\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Sul pole piisavalt ruumi oma varudes\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Kas meil on kokkulepe?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Kas oled kindel, et soovid selle eseme tuvastada?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Kas oled kindel, et soovid seda eset osta?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Kas olete kindel, et soovite seda eset laadida?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Kas oled kindel, et soovid selle eseme müüa?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Kas olete kindel, et soovite seda eset parandada?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt, puujalaga poiss\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Räägi Wirtiga\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Mul on midagi müügiks,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"aga see maksab 50 kulda\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"lihtsalt pilgu heitmiseks. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Mida sul on pakkuda?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Ütle hüvasti\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Mul on see ese müügiks:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Lahku\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Tervendaja kodu\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Räägi Pepiniga\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Lahku Ravitseja kodust\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Linna vanem\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Räägi Cainiga\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Tuvasta ese\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Sul pole midagi tuvastada.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Määrake, milline ese?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"See ese on:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Valmis\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Räägi {:s}-ga\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Vestlus {:s}-ga\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"ei ole saadaval\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"jagatud tarkvaras\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"versioon\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Klatš\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Tõusev Päike\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Räägi Ogdeniga\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Lahku kõrtsist\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Räägi Gillianiga\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Juurdepääs laole\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Joodik Farnham\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Räägi Farnhamiga\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Ütle hüvasti\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Sinu kuld: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Tapetud linnamees\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Sepp Griswold\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin Ravitseja\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Haavatud linnakodanik\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden kõrtsi omanik\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Vanem Cain\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Nõid Adria\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian, kõrtsitüdruk\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Lehm\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester talunik\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Täielik Mutrike\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Sõdalane\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Varas\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Võlur\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Munk\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bard\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbar\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Koll\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Mädanev korjus\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Must Surm\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Langenud\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Raiuja\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Kuratipoeg\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Tume Üks\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Skelett\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Laiba Kirves\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Põlev Surnu\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Õudus\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Röövel\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Katkuõgija\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Varjuelukas\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Luu Purustaja\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Laibavibu\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Skeletikapten\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Laiba kapten\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Põlevate Surnute Kapten\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Õuduse kapten\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Nähtamatu isand\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Peidetud\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Jälitaja\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Nähtamatu\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Illusioonikuduja\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Saatüürisand\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Lihaklann\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Kiviklan\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Tule klann\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Ööklann\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Deemon\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Pilgutõmme\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Hämarus\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Tuttav\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Happemadu elajas\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Mürgiprits\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Koopabeast\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Lava Lõug\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Luukuningas\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Lihunik\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Ülemus\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Mudamees\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Konnadeemon\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Nülitud\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Loheuss\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Koobas\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Kuradi Uss\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Neelaja\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Magma deemon\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Verikivi\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Põrgu Kivi\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Lava Isand\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Sarviline deemon\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Mudajooks\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Külmalaadija\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obsidiaanist Isand\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"vanaluine\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Punane Surm\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Litsidemon\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Elav Balrog\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Põletaja\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Leegilord\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Hukatusetuli\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Põrgu Põletaja\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Punane Torm\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Tormisõitja\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Tormisandur\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Maelstrom\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Kuradi Kinni Brutaal\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Tiivul-demon\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargoil\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Veriküünis\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Surmatiib\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Tapja\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Kaitsja\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Vortexi isand\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Koobas Madu\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Tulelohe\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Kuldne Madu\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Asuurdrake\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Must rüütel\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Hukatusvalvur\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Terasisandur\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Vererüütel\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Rebitud\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Tühi Üks\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Valumeister\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Reaalsuse Kuduja\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Sukkubus\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Lumewiit\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Põrgu Sigitis\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Hingepõletaja\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Nõunik\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Magistraat\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Kabalist\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Advokaat\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Tume Isand\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Ülilits Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Nõrk Gharbad\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar Hullumeelne\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Tatiprits\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Ülempiiskop Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Punane Vex\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Must jadeiit\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Verelord\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Hork deemon\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Rüvetaja\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Luukere Teravkirves\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Viilutaja Teranahk\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Hingemäda\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Pukerat Rüve\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Kondirabaja\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Näljas Mädapidu\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Kiire Gutshank\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Murtudpea Kilpimüts\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Verelõikur\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Varjuhammustus\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Surnusilm\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Surnud Hullsilme\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Koljuleek\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Sõjakolju\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Verikeel\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Pulssipug\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Kuu Painutaja\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Raevuviha\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Selgroogija\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Põlev Musttuha\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Varjukaar\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Nõrkuse Rõhukivi\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Bilefroth, Sügaviku Isand\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Verinahk Nahkjas\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"<translated:Rikutis>\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Varjudejooja\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Udusenihe\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Surmasülg\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Verelõikur\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Surmavarju Lihanuia\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Hullumeelne Warmaggot\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Klaaskolju Sakiline\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Kõduleek\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Öötiib Tihe Külm\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Verikivi\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Tulekivi Pronksinupp\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Hukatuslik Vihatuled\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Firewound, See Sünge\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Parun Lörts\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Blighthorni Terasnuia\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Kaosikarjeja\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Mädanik Doomgrin\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Hullupõletaja\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Luuasaag Lits\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Selgroogmurdja\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Kuradikolju Teravluu\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Murtudtorm\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Tormivits\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Limaoige\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Leegikuma Leegitseja\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Musttorm\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Katkupõlgus\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Nülgija\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Sinisarv\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Tulepõrgu Järeltulija\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Kihvapiik\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Mädakolju\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Kõver Lõvikolju\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Mustkeel\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Vilepuude\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Viperileek\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Kihvnahk\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Nõiatuli Pühaduseta\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Mustkolju\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Hingelõige\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Tuulekülv\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Augu isand\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Roostekuduja\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Ulguvari Varjund\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Hukatuspilv\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Veremoon Hingetuli\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Nõiakuu\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Veremöll\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Tapja Hallusõdalane\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Kohutavkohtunik\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Nõid Tähetäht\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Teraskolju Jahimees\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Vezier\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamphir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Verejanu\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Veebilesk\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Lihavõlur\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Grimspike\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Hukatuslukk\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Lühike mõõk\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Väike kilp\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Nuia\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Lühike vibu\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Mana Lühiõõts\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Lihunikirves\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Undeadi kroon\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Empyrean Band\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Maagiline Kivi\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Optiline amulett\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Tõe sõrmus\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Kõrtsi silt\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Harlekiini Hari\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Teraseloor\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Kuldne Eliksiir\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Raevualasi\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Must seen\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Aju\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Seenetome\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Spektraalne eliksiir\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Verikivi\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Katedraali kaart\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Tervendamise jook\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Mana jook\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Identifitseerimise rull\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Linna Portaali Rull\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Arkaine'i Vapruse\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Täieliku tervendamise jook\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Täismana jook\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Griswoldi Serv\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Veiseplaat\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Lazari sau\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Ülestõusmise rull\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Lühike sau\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Mõõk\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Pistoda\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Ruunipomm\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodore\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Auriku amulett\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Rebitud Märkus 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Rebitud Märkus 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Rebitud Märkus 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Rekonstrueeritud märkus\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Pruun ülikond\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Hallikas ülikond\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Müts\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Kolju kiiver\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Kiiver\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Täis kiiver\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Kroon\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Suur kiiver\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Keep\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Kaltsud\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Keep\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Rüü\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Vatevattest soomusrüü\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Nahksoomus\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Kõva nahast turvis\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Nahknastudega turvis\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Rõõmsoomus\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Rüü\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Rüü\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Soomusrüü\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Rinnaturvis\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Rüü\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Liistturvis\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Plaatsoomusrüü\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Plaatsoomusrüü\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gooti plaatrüü\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Täisplaatrüü\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Kilp\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Väike kilp\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Suur kilp\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Loorskilp\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Tornikaitse\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gooti kilp\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Noorendamise jook\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Täieliku noorendamise eliksiir\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Õli\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Tugevuse eliksiir\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Maagia eliksiir\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Osavuse eliksiir\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Eliksiir Elujõust\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Tervendamise rull\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Otsingurull\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Välgu rull\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Tulemüüri rull\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Põrgu kerimine\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Välgu rull\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Infranägemise rull\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Faasi kerimine\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Mana Kilbi Rull\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Leegilaine rull\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Tulepalli kerimine\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Kivineeduse rull\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Ahelkiri Kettvälk\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Valvuri rull\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Nova kerimine\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Golemi rull\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Teleporteerimise rull\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Apokalüpsise rull\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Falchion\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Kaheterane mõõk\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Claymore\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Tera\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Saabel\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Pikk mõõk\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Lai mõõk\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Pärispea mõõk\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Kahesekäeline mõõk\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Suur mõõk\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Väike kirves\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Kirves\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Suur kirves\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Lai kirves\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Lahingukirves\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Võimas kirves\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Nuia\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Hommikutäht\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Sõjahaamer\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Vasar\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Ogalikuga nui\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Vihmapiits\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Nuia\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Vibu\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Küti vibu\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Pikk vibu\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Komposiitvibu\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Lühike lahinguvibu\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Pikk lahinguvibu\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Lühike sõjasõrmus\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Pikk sõjasulg\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Pikk sau\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Komposiitkepp\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Veerandkepp\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Sõjasau\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Sõrmus\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amulett\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Tuleruuna\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Ruun\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Välgu ruun\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Suurem Tuleruun\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Suurem välgu ruun\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Kiviruuni\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Laetud noole lühike sau\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Arena jook\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Lihuniku kirves\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Valgusemõõk\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Lõhe Vibu\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Nõelaja\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Taevalik vibu\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Surmav Kütt\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Surnute vibu\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Musttamme vibu\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Tuleodav\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Lihasõel\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Tuulejõud\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Kotkasarv\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Gonnagali pistoda\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Kaitsja\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Grüfoni Küünis\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Must Razor\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Kahane Kuu\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Jääteravik\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Timuka Mõõk\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Luunasaag\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Varjukull\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Võluripiik\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Valgusemõõk\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Pistrikuküünis\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Põrgu\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Hukatusetooja\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Grisli\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Vanaisa\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Purustaja\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Terav Nokk\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Veretapja\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Taevalik kirves\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"<translated:Paha Kirves\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Kivikõmblaja\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Aguinara kirves\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Põrgutapja\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Messerschmidti raider\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Mõranerooste\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Jholmi vasar\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Civerbi nuia\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Taevalik Täht\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Baranari Täht\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Kõver Juure\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Kolju Purustaja\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Schaeferi vasar\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Unenäopits\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Varjude sau\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Põletaja\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Tormitorn\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Säralaul\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Äikesekutse\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Kaitsja\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Naji Mõistatus\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Meeltemurdja\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Onani sau\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Vaimude kiiver\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Mõtlemismüts\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Ülemisanda kiiver\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Lolli Märk\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Gotterdamerung\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Kuninglik Peaehe\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Hingede rebitud liha\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Gladiaatori hukatus\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Vikerkaare Keep\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Auti nahk\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Tarkuse rüü\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Sädelev Rüü\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Röövli Kest\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Öömaastik\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Naj'i Rüü\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Demonspike'i kuub\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Peegeldaja\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Lõhestatud Kolju Kilp\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Draakoni Murd\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Musttamme kilp\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Püha Kaitsja\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Tormikilp\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Ogalik\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Regha sõrmus\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Verejooksja\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Ahendav Sõrmus\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Kihlasõrmus\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Plekk\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Messing\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Pronks\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Raud\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Teras\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Hõbe\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platina\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteoriline\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Kummaline\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Kasutud\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Kõver\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Nõrk\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Sakiline\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Surmav\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Raske\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Raevukas\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Brutaalne\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Massiivne\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Metsik\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Halastamatu\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Halastamatu\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Kohmakas\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Nüri\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Terav\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Hea\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Sõdalase\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Sõduri\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Isanda\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Rüütli\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Meistri\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Meistri\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Kuningas\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Haavatav\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Rohkine\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Tugev\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Suurepärane\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Vapper\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Auline\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Õnnistatud\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Pühalik\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Vinge\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Jumalik\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Punane\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Karmiinpunane\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Granaat\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubiin\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Sinine\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Asuur\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lapis\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Kobalt\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Safiir\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Valge\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Pärl\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"<translated Elevandiluu\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Kristall\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Teemant\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topaas\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Merevaik\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Jadeiit\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Obsidiaan\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Smaragd\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Hüääni\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Konna\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Ämbliku\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Ronga\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Mao oma\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Mao\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Drake'i\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Draakoni\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Lohe\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hydra\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Inglite\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Peaingli\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Rohkesti\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Rikkalik\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Põlev\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Välk\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"kvaliteet\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"sandistamine\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"maha\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"veri\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"veresaun\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"veresaun\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"valu\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"pisarad\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"tervis\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"kaitse\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"imendumine\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"hajutamine\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"osmoos\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"nõrkus\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"nõrkus\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"jõud\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"võimsus\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"jõud\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"hiiglased\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"titaanid\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"halvatus\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"atroofia\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"osavus\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"oskus\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"täpsus\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"täpsus\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"täiuslikkus\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"loll\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"düsleksia\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"maagia\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"meel\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"sära\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"nõidus\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"nõidus\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"haigus\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"haigus\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"vitaalsus\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"õhin\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"vim\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"elujõud\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"elu\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"häda\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"auk\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"taevas\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"kuu\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"tähed\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"taevad\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"sodiaak\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"raisakotkas\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"šakaal\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"rebane\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"jaguaar\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"kotkas\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"hunt\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tiiger\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"lõvi\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mammut\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"vaal\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"haprus\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"haprus\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"vastupidavus\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"meistriteos\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"struktuur\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"ajastud\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"pimedus\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"öö\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"valgus\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"sära\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"leek\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"tuli\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"põletav\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"šokk\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"välk\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"äike\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"palju\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"palju\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"ogad\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"rikkumine\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"vargad\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"karu\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"nahkhiir\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"vampiirid\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"verd\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"veri\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"läbistav\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"läbistav\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"materdamine\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"valmidus\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"kiirus\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"kiirus\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"kiirustamine\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"tasakaal\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"stabiilsus\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"harmoonia\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"blokeerimine\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Maagiline Kivi\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad Nõrk\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar Hullumeelne\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Lihunik\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Ogdeni märk\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Pimeduse Saalid\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Vapruse\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Verelord\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Kuningas Leorici needus\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Peapiiskop Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Hauaküsimused\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Taluniku Aed\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Väike Tüdruk\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Rändav Kaupmees\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Rüvetaja\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Jersey särk\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Tulepold\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Tervendamine\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Välk\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Välgatus\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Tuvasta\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Tulesein\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Linnaportaal\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Kivine needus\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infranägemine\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Faasimine\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Mana kilp\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Tulepall\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Kaitsja\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Ahelkett-kõu\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Leegilainetus\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Hukatusmaod\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Vererituaal\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Nähtamatus\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Põrgu\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Raev\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleporteerimine\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apokalüpsis\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Eeterialiseerima\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Eseme Parandus\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Keppi laadimine\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Lõksu kahjutuks tegemine\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elementaalne\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Laetud polt\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Püha nool\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Elusta\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekinees\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Tervenda Teist\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Veretäht\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Luukvaim\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ahh, meie kuninga lugu, kas pole? Leoricu traagiline langus oli sellele \"\n\"maale karm hoop. Rahvas armastas alati kuningat, ja nüüd elavad nad tema ees \"\n\"surmahirmus. Küsimus, mida ma endalt pidevalt küsin, on see, kuidas ta võis \"\n\"nii kaugele valgusest langeda, sest Leoric oli alati olnud kõige püham mees. \"\n\"Ainult põrgulikud jõud suudaksid inimest seestpoolt nii täielikult \"\n\"hävitada...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Küla vajab teie abi, hea meister! Mõned kuud tagasi rööviti kuningas Leorici \"\n\"poeg, prints Albrecht. Kuningas läks raevu ja kammis küla läbi oma kadunud \"\n\"lapse otsinguil. Iga mööduva päevaga näis Leoric üha sügavamale hullusesse \"\n\"vajuvat. Ta püüdis süüdistada süütuid külaelanikke poisi kadumises ja lasi \"\n\"nad julmalt hukata. Vähem kui pooled meist jäid tema hullusest ellu...\\n\"\n\"\\n\"\n\"Kuningas rüütlid ja preestrid püüdsid teda rahustada, kuid ta pöördus nende \"\n\"vastu ja kahjuks olid nad sunnitud ta tapma. Oma viimase hingetõmbega \"\n\"langetas kuningas kohutava needuse oma endiste järgijate peale. Ta vandus, \"\n\"et nad teenivad teda igavesti pimeduses...\\n\"\n\"\\n\"\n\"Siin võtavad asjad veelgi tumedama pöörde, kui ma arvasin võimalikuks! Meie \"\n\"endine kuningas on tõusnud oma igavesest unest ja juhib nüüd surnute \"\n\"leegioni labürindis. Tema keha maeti katedraali alla kolm taset sügavale \"\n\"hauakambrisse. Palun, hea meister, rahustage tema hing, hävitades tema \"\n\"nüüdseks neetud kuju...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Nagu ma teile ütlesin, hea meister, kuningas maeti kolm taset allapoole. Ta \"\n\"on seal all, oodates mädanenud pimeduses oma võimalust selle maa \"\n\"hävitamiseks...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Meie kuninga needus on möödas, kuid ma kardan, et see oli vaid osa suuremast \"\n\"kurjusest, mis tegutseb. Kuid meid võib veel päästa pimedusest, mis meie \"\n\"maad neelab, sest sinu võit on hea enne. Olgu valgus sinu teel juhatamas, \"\n\"hea meister.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Oma poja kaotus oli kuningas Leoricule liialt raske. Ma tegin, mis suutsin, \"\n\"et tema hullust leevendada, kuid lõpuks võttis see temast võimust. Must \"\n\"needus on sellest päevast alates selle kuningriigi kohal rippunud, kuid võib-\"\n\"olla, kui sa vabastaksid tema vaimu maapealsest vanglast, saaks needus \"\n\"murtud...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Ma ei taha mõelda, kuidas kuningas suri. Ma tahan teda meenutada kui lahket \"\n\"ja õiglast valitsejat, kes ta oli. Tema surm oli nii kurb ja tundus kuidagi \"\n\"väga vale.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Ma tegin paljusid relvi ja enamikku turvistest, mida kuningas Leoric kasutas \"\n\"oma rüütlite varustamiseks. Ma meisterdasin talle isegi tohutu kahekäemõõga \"\n\"parimast mithrillist, samuti sobiva lahingukrooni. Ma ei suuda ikka veel \"\n\"uskuda, kuidas ta suri, kuid see pidi olema mingi kuri jõud, mis ajas ta \"\n\"hulluks!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Mind ei huvita see. Kuula, ükski luukere ei hakka minu kuningaks. Leoric on \"\n\"kuningas. Kuningas, kas kuuled mind? ELAGU KUNINGAS!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Elavad surnud järgivad neetud kuningat. Tal on võime äratada veelgi rohkem \"\n\"sõdalasi, et kasvatada oma elavate surnute armeed. Kui sa ei peata tema \"\n\"valitsemist, marsib ta kindlasti üle selle maa ja tapab kõik, kes siin veel \"\n\"elavad.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Kuule, ma ajan siin äri. Ma ei müü infot ja mind ei huvita mingi kuningas, \"\n\"kes on surnud kauem kui mina olen elus olnud. Kui sul on midagi vaja selle \"\n\"surnute kuninga vastu, siis saan sind aidata...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Elu soojus on sisenenud minu hauakambrisse. Valmistu, surelik, teenima minu \"\n\"Meistrit igavesti!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Näen, et see kummaline käitumine paneb ka sind kukalt kratsima. Ma oletan, \"\n\"et kuna paljud deemonid kardavad päikesevalgust ja usuvad, et see omab suurt \"\n\"jõudu, siis võib-olla on päikesetõus, mida sa mainisid, pannud neid uskuma, \"\n\"et ka see omab mingisuguseid salapäraseid jõude. Hmm, võib-olla nad ei olegi \"\n\"kõik nii targad, kui me kartsime...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Meister, mul on üks kummaline kogemus, mida jagada. Ma tean, et sul on suur \"\n\"teadmistepagas nende koletiste kohta, kes labürindis elavad, ja see on \"\n\"midagi, millest ma ei suuda aru saada... Mind äratas öösel kraapiv heli otse \"\n\"mu kõrtsi juures. Kui ma oma magamistoast välja vaatasin, nägin kõrtsiõuel \"\n\"väikeste deemonilaadsete olendite kujusid. Mõne aja pärast nad jooksid \"\n\"minema, kuid mitte enne, kui nad mu kõrtsi sildi varastasid. Ma ei tea, miks \"\n\"deemonid mu sildi varastaksid, kuid jätaksid mu pere rahule... see on \"\n\"kummaline, kas pole?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Oh, sa ei pidanudki mu silti tagasi tooma, aga ma arvan, et see säästab mind \"\n\"uue valmistamise kuludest. Noh, las ma vaatan, mida ma võiksin sulle tasuks \"\n\"anda selle leidmise eest? Hmmm, mis meil siin on... ah, jah! See müts jäeti \"\n\"ühte tuppa maagiku poolt, kes peatus siin mõnda aega tagasi. Võib-olla on \"\n\"see sulle väärtuslik.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Oh sa püha taevas, deemonid jooksevad öösel külas ringi, rüüstavad meie \"\n\"kodusid - kas miski pole püha? Ma loodan, et Ogden ja Garda on korras. Ma \"\n\"arvan, et nad tuleksid minu juurde, kui nad oleksid viga saanud...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Oh sa mu meie! Kas sinna see silt kaduski? Minu vanaema ja mina magasime \"\n\"vist kogu selle asja maha. Tänu Valgusele, et need koletised ei rünnanud \"\n\"kõrtsi.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Deemonid varastasid Ogdeni märgi, sa ütled? See ei kõla just nagu need \"\n\"õudused, millest olen kuulnud - või näinud. \\n\"\n\" \\n\"\n\"Deemonid on huvitatud pigem su südame välja rebimisest, mitte su \"\n\"sildipostist.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Tead, mis ma arvan? Keegi võttis selle sildi ja nad tahavad selle eest palju \"\n\"raha. Kui ma oleksin Ogden... ja ma ei ole, aga kui ma oleksin... siis ma \"\n\"ostaksin lihtsalt uue sildi, millel oleks ilus joonistus. Võib-olla kena \"\n\"õllekruus või tükk juustu...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Ükski surelik ei suuda tõeliselt mõista deemoni meelt. \\n\"\n\" \\n\"\n\"Ära lase nende ettearvamatutel tegudel end segadusse ajada, sest ka see võib \"\n\"olla nende plaan.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Mida - kas ta ütleb, et mina võtsin selle? Ma arvan, et Griswold on ka tema \"\n\"poolel. \\n\"\n\" \\n\"\n\"Kuule, ma lõpetasin lihtsa sildi varastamise juba kuid tagasi. Sa ei saa \"\n\"puutükiga kasumit teenida.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hei - Sina oled see, kes kõik tapab! Too mulle Maagiline Lipp või me \"\n\"ründame! Sa ei lahku eluga! Tapa suured koletised ja too Maagiline tagasi. \"\n\"Mine nurgast mööda ja uksest sisse, leia koletised. Annad, siis lähed!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Sa tapad koledaid, saad lipu. Too too mulle, või muidu...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Sina anna! Jah, hea! Mine nüüd, me oleme tugevad. Me tapame kõik suure \"\n\"Maagiaga!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"See ei tõota head, sest see kinnitab mu kõige süngemaid hirme. Kuigi ma ei \"\n\"lubanud endal iidseid legende uskuda, ei saa ma neid nüüd eitada. Võib-olla \"\n\"on aeg avaldada, kes ma tegelikult olen.\\n\"\n\"\\n\"\n\"Minu tõeline nimi on Deckard Cain Vanem ja ma olen viimne järeltulija \"\n\"iidsest Vennaskonnast, mis oli pühendunud ajatu kurjuse saladuste \"\n\"kaitsmisele. Kurjus, mis on nüüd ilmselgelt valla päästetud.\\n\"\n\"\\n\"\n\"Peapiiskop Lazarus, kuningas Leorici kõige usaldusväärsem nõuandja, juhtis \"\n\"lihtsate linnarahva rühma Labürinti, et leida kuninga kadunud poeg Albrecht. \"\n\"Möödus üsna palju aega, enne kui nad naasid, ja vaid vähesed neist pääsesid \"\n\"eluga.\\n\"\n\"\\n\"\n\"Neetud olgu ma lollina! Ma oleksin pidanud tema varjatud reeturlikkust siis \"\n\"kahtlustama. See pidi olema Lazarus ise, kes röövis Albrechti ja on teda \"\n\"sellest ajast alates Labürindis peitnud. Ma ei mõista, miks peapiiskop \"\n\"pimedusse pöördus või mis on tema huvi lapse vastu, kui ta ei kavatse teda \"\n\"oma tumedatele isandatele ohverdada!\\n\"\n\"\\n\"\n\"See peab olema see, mida ta plaanib! Tema 'päästegrupi' ellujäänud ütlevad, \"\n\"et Lazarust nähti viimati jooksmas labürindi sügavaimatesse soppidesse. Sa \"\n\"pead kiirustama ja päästma printsi selle hullumeelse kurjami ohvrinoast!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Sa pead kiirustama ja päästma Albrechti Lazaruse käest. Prints ja selle \"\n\"kuningriigi rahvas loodavad sinu peale!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Sinu lugu on üsna sünge, mu sõber. Lazarus põleb kindlasti põrgus oma \"\n\"kohutava teo eest. Poiss, keda sa kirjeldad, ei ole meie prints, kuid ma \"\n\"usun, et Albrecht võib siiski ohus olla. Võimu sümbol, millest sa räägid, \"\n\"peab olema portaal labürindi südames.\\n\"\n\"\\n\"\n\"Tea seda, mu sõber - Kurjus, mille vastu sa astud, on Terrori tume isand. \"\n\"Surelikud mehed tunnevad teda nimega Diablo. Tema oli see, kes vangistati \"\n\"labürinti paljude sajandite eest ja ma kardan, et ta püüab taas külvata \"\n\"kaost inimkonna valdustesse. Sa pead minema läbi portaali ja hävitama \"\n\"Diablo, enne kui on liiga hilja!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus oli peapiiskop, kes viis paljud linnaelanikud labürinti. Ma kaotasin \"\n\"sel päeval palju häid sõpru ja Lazarus ei tulnud kunagi tagasi. Ma arvan, et \"\n\"ta tapeti koos enamiku teistega. Kui saaksid mulle teene teha, hea meister - \"\n\"palun ära räägi Farnhamiga sellest päevast.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Ma olin šokeeritud, kui kuulsin, mida linnarahvas sel ööl plaanis teha. Ma \"\n\"arvasin, et kõigist inimestest oleks Lazarusel rohkem mõistust olnud. Ta oli \"\n\"peapiiskop ja tundus alati hoolivat Tristrami linnarahvast. Nii paljud said \"\n\"vigastada, ma ei suutnud neid kõiki päästa...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Ma mäletan Lazarust kui väga lahket ja heldet meest. Ta kõneles mu ema \"\n\"matustel ja toetas mu vanaema ja mind väga raskel ajal. Ma palvetan igal \"\n\"õhtul, et kuidagi on ta ikka veel elus ja turvaliselt.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Ma olin seal, kui Lazarus meid labürinti juhtis. Ta rääkis pühast \"\n\"kättemaksust, aga kui me hakkasime nende põrgulistega võitlema, ei tõstnud \"\n\"ta nende vastu isegi oma nuia. Ta lihtsalt jooksis sügavamale hämaratesse, \"\n\"lõpututesse kambritesse, mis olid täidetud pimeduse teenritega!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Nad torkavad, siis hammustavad, siis on nad kõikjal sinu ümber. Valevorst! \"\n\"VALEVORST! Nad on kõik surnud! Surnud! Kas kuuled mind? Nad lihtsalt kukuvad \"\n\"ja kukuvad... nende veri voolab kõikjale põrandale... kõik tema süü...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Ma ei tundnud seda Lazarust, kellest sa räägid, kuid ma tajun tema olemuses \"\n\"suurt konflikti. Ta kujutab endast suurt ohtu ja ei peatu millegi ees, et \"\n\"teenida pimeduse jõude, mis on ta enda omaks kuulutanud.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Jah, see õiglane Lazarus, kes oli nii tõhus nende koletiste vastu seal all. \"\n\"Ei aidanud mu jalga päästa, eks? Kuule, ma annan sulle ühe tasuta nõuande. \"\n\"Küsi Farnhami käest, tema oli seal.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Loobu oma rumalast otsingust. Kõik, mis sind ootab, on minu Meistri viha! Sa \"\n\"oled liiga hilja, et last päästa. Nüüd liitud temaga Põrgus!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, ma ei tea, mida ma sulle sellest rääkida saaksin, mis oleks abiks. \"\n\"Vesi, mis täidab meie kaevud, tuleb maa-alusest allikast. Olen kuulnud \"\n\"tunnelist, mis viib suure järveni - võib-olla on need üks ja sama. Kahjuks \"\n\"ei tea ma, mis võiks meie veevarustuse saastumise põhjustada.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Olen alati püüdnud hoida meie keldris suurt varu toiduaineid ja jooke, kuid \"\n\"kuna kogu linnal pole värske vee allikat, saavad ka meie varud peagi otsa. \\n\"\n\" \\n\"\n\"Palun, tee, mis saad, või ma ei tea, mida me teeme.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Mul on hea meel, et jõudsin sinuni õigel ajal! Meie kaevud on muutunud \"\n\"soolaseks ja seisvaks ning mõned linnaelanikud on haigestunud, juues sealt \"\n\"vett. Meie värske vee varud hakkavad kiiresti otsa saama. Ma usun, et on \"\n\"olemas käik, mis viib allikateni, mis teenivad meie linna. Palun leia, mis \"\n\"on selle õnnetuse põhjustanud, või me kõik hukkume kindlasti.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Palun, te peate kiirustama. Iga mööduv tund viib meid lähemale olukorrale, \"\n\"kus meil pole enam joogivett. \\n\"\n\" \\n\"\n\"Me ei suuda kaua ilma teie abita ellu jääda.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Mida sa ütled - deemonite pelk kohalolek on põhjustanud vee saastumise? Oh, \"\n\"tõepoolest suur kurjus varitseb meie linna all, kuid sinu visadus ja julgus \"\n\"annavad meile lootust. Palun võta see sõrmus - ehk aitab see sind selliste \"\n\"õelate olendite hävitamisel.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Mu vanaema on väga nõrk ja Garda ütleb, et me ei saa kaevude vett juua. \"\n\"Palun, kas saaksid midagi teha, et meid aidata?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin on sulle tõtt rääkinud. Meil on varsti hädasti vaja värsket vett. Olen \"\n\"proovinud ühte väiksemat kaevu puhastada, aga see haiseb seisva saasta \"\n\"järele. See peab olema allikas ummistunud.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Kas sa jood vett?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Tristrami rahvas sureb, kui sa ei suuda nende kaevudele värsket vett \"\n\"taastada. \\n\"\n\" \\n\"\n\"Tea seda - deemonid on selle asja südames, kuid nad jäävad teadmatusse \"\n\"sellest, mida nad on esile kutsunud.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Seekord olen sinuga nõus. Minu äri jääb kuivaks - nii öelda - kui mul pole \"\n\"turgu, kellele müüa. Sa parem uuri välja, mis toimub, ja kiiresti!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Raamat, mis räägib inimluude kambrist? Noh, Luukamber on mainitud teatud \"\n\"vanades kirjutistes, mida ma uurisin Idamaa raamatukogudes. Need teosed \"\n\"vihjasid, et kui allilma isandad soovisid kaitsta suuri aardeid, lõid nad \"\n\"valdkondi, kus need, kes surid püüdes seda aaret varastada, oleksid \"\n\"igaveseks seotud selle kaitsmisega. Väänatud, kuid kummaliselt sobiv lõpp?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Kardan, ma kardan, ma ei tea sellest midagi, hea isand. Cainil on palju \"\n\"raamatuid, mis võivad abiks olla.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"See kõlab väga ohtliku kohana. Kui sa sinna lähed, ole palun väga \"\n\"ettevaatlik.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Kardan, ma pole sellest midagi kuulnud. Võib-olla saaks Jutustaja Cain \"\n\"aidata.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Ma ei tea sellest kohast midagi, aga sa võid proovida küsida Cainilt. Ta \"\n\"räägib paljudest asjadest ja mind ei üllataks, kui tal oleks mõni vastus \"\n\"sinu küsimusele.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Kuule nüüd. Seal on üks puidust kamber, tead. Ja tema naine, tead küll - \"\n\"tema - räägib puuga... sest sa pead ootama. Siis ma ütlen, et see võib tema \"\n\"vastu töötada, aga kui sa arvad, et ma selle eest MAKSAN... sa... ee... jah.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Sa saad igavesti pimeduse isandate teenriks, kui hukkud selles neetud \"\n\"valdkonnas. \\n\"\n\" \\n\"\n\"Sisene Luukambrisse omal vastutusel.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Sa ütled, et seal on tohutu ja salapärane aare? Võib-olla võiksin ma olla \"\n\"huvitatud mõne asja hankimisest sinult... või veel parem, kas sa ei vaja \"\n\"mõnda haruldast ja kallist varustust, et sellest katsumusest läbi saada?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Tundub, et peapiiskop Lazarus meelitas paljusid linnakodanikke Labürinti, et \"\n\"leida kuninga kadunud poeg. Ta mängis nende hirmudel ja ajas nad pöörasesse \"\n\"rahvahulka. Keegi neist polnud valmis selleks, mis külmas maa-aluses neid \"\n\"ootas... Lazarus hülgas nad seal - jättes nad kirjeldamatute õuduste küüsi - \"\n\"surema.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Jah, Farnham on pomisenud midagi suurest jõhkardist, kes vehkis metsiku \"\n\"relvaga. Ma usun, et ta nimetas teda lihunikuks.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Valguse nimel, ma tean sellest õelast deemonist. Paljud kandsid tema raevu \"\n\"arme oma kehal, kui vähesed ellujäänud Lazaruse juhitud rünnakust \"\n\"katedraalist välja roomasid. Ma ei tea, mida ta kasutas oma ohvrite lõhki \"\n\"lõikamiseks, kuid see ei saanud olla sellest maailmast. See jättis haavad \"\n\"mädanema haigusega ja isegi mina leidsin, et neid on peaaegu võimatu ravida. \"\n\"Ole ettevaatlik, kui plaanid selle kurjategijaga võidelda...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Kui Farnham rääkis midagi lihunikust, kes inimesi tapab, siis ma kohe \"\n\"eirasin seda. Aga kuna sa tõid selle üles, siis võib-olla on see tõsi.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Ma nägin, kuidas Farnham nimetas Lihunikuks seda, kes raius teed läbi mu \"\n\"sõprade surnukehade. Ta vehkis kirve suuruse lihunikukirvega, raiudes \"\n\"jäsemeid ja langetades vapraid mehi seal, kus nad seisid. Mind eraldas \"\n\"lahingust hulk väikseid kriiskavaid deemoneid ja kuidagi leidsin trepi, mis \"\n\"viis välja. Ma ei näinud seda jubedat elajat enam kunagi, kuid tema verine \"\n\"nägu kummitab mind tänaseni.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Suur! Suur kirves tappis kõik mu sõbrad. Ei suutnud teda peatada, pidin \"\n\"põgenema, ei suutnud neid päästa. Lõksus toas nii paljude kehadega... nii \"\n\"paljude sõpradega... EIIIIIIII!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Lihunik on sadistlik olend, kes naudib teiste piinamist ja valu. Sa oled \"\n\"näinud tema kätetööd joodik Farnhami peal. Tema hävitamine aitab palju kaasa \"\n\"selle küla turvalisuse tagamisele.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Ma tean sellest jubedast koletisest rohkem, kui sa arvata oskad. Tema \"\n\"väikesed sõbrad said mind kätte ja suutsid mu jala saada, enne kui Griswold \"\n\"mind sellest august välja tõmbas.\\n\"\n\"\\n\"\n\"Ma ütlen otse - tapa ta enne, kui ta sind tapab ja su laiba oma \"\n\"kollektsiooni lisab.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Palun, kuula mind. Peapiiskop Lazarus, ta viis meid siia alla, et leida \"\n\"kadunud prints. See lurjus vedas meid lõksu! Nüüd on kõik surnud... tapetud \"\n\"deemoni poolt, keda ta kutsus Lihunikuks. Kosta meie eest! Leia see Lihunik \"\n\"ja tapa ta, et meie hinged saaksid lõpuks rahu leida...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Sa loed ette huvitavat riimi, mis on kirjutatud stiilis, mis meenutab mulle \"\n\"teisi teoseid. Las ma mõtlen nüüd - mis see oli?\\n\"\n\"\\n\"\n\"...Pimedus katab Varjatut. Silmad helendavad nähtamatult, ainult habemenoa \"\n\"küüniste helid kriibivad lühidalt, et piinata neid vaeseid hingi, kes on \"\n\"tehtud igaveseks pimedaks. Nende neetud vangla nimi on Pimeduse Saalid...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Ma pole kunagi eriti luulet armastanud. Mõnikord oli mul põhjust palgata \"\n\"minstreleid, kui kõrtsil hästi läks, aga see tundub nüüd nii ammu olevat. \\n\"\n\" \\n\"\n\"Mis? Oh, jah... noh, ma arvan, et sa võiksid vaadata, mida keegi teine teab.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"See tundub kuidagi tuttav. Mäletan, et lugesin midagi väga sarnast sellele \"\n\"luuletusele, kui uurisin deemonlike hädade ajalugu. See rääkis kohast, kus \"\n\"valitseb suur kurjus, mis... oota - sa ei kavatse sinna minna, eks?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Kui sul on küsimusi pimeduse kohta, peaksid rääkima Pepiniga. Ma tean, et ta \"\n\"andis mu vanaemale eliksiiri, mis aitas tal nägemist parandada, nii et võib-\"\n\"olla saab ta ka sind aidata.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Kardan, ma sõber, ma pole kuulnud ega näinud kohta, mis vastaks sinu \"\n\"värvikale kirjeldusele. Ehk oskab Jutustaja Cain sind aidata.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Vaata siia... see on päris naljakas, eks? Said aru? Pime - vaata siia?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"See on suurte piinade ja õuduste paik, mis teenib oma isandat hästi. \\n\"\n\" \\n\"\n\"Astu ettevaatlikult, muidu võid ise siia jääda palju kauemaks, kui oled \"\n\"oodanud.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Vaatame, kas ma müün sulle midagi? Ei. Kas sa annad mulle raha, et ma sulle \"\n\"sellest räägiksin? Ei. Kas sa nüüd lahkud ja lähed rääkima jutuvestjaga, kes \"\n\"elab selliste asjade jaoks? Jah.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Sa väidad, et oled Lachdananiga rääkinud? Ta oli oma eluajal suur kangelane. \"\n\"Lachdanan oli auväärne ja õiglane mees, kes teenis oma kuningat aastaid \"\n\"ustavalt. Aga muidugi tead sa seda juba.\\n\"\n\"\\n\"\n\"Nendest, kes sattusid Kuningakese needuse haardesse, oleks Lachdanan kõige \"\n\"vähem tõenäoline, et alistuks pimedusele ilma võitluseta, seega arvan, et \"\n\"sinu lugu võib tõsi olla. Kui ma oleksin sinu asemel, mu sõber, siis \"\n\"leiaksin viisi, kuidas vabastada ta tema piinadest.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Sa räägid vaprast sõdalasest, kes on ammu surnud! Ma ei taha oma kõrtsiõuel \"\n\"kuulda jutte surnud hingedega rääkimisest, aitäh.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Kuldne eliksiir, ütlete. Ma pole kunagi varem sellist värvi jooki \"\n\"valmistanud, seega ei oska ma öelda, kuidas see teid mõjutaks, kui \"\n\"prooviksite seda juua. Teie ravitsejana soovitan tungivalt, et kui leiate \"\n\"sellise eliksiiri, tehke nagu Lachdanan palub ja ÄRGE proovige seda kasutada.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Ma pole kunagi varem Lachdananist kuulnud. Mul on kahju, aga ma ei usu, et \"\n\"saan teile palju abiks olla.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Kui sa tõepoolest kohtusid Lachdananiga, siis soovitan sul teda aidata. Olen \"\n\"temaga mitmel korral kokku puutunud ja leidnud, et ta on aus ja truu \"\n\"loomusega. Needus, mis langes kuningas Leorici järgijate peale, tabaks teda \"\n\"eriti rängalt.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan on surnud. Kõik teavad seda, ja sa ei saa mind petta, et ma \"\n\"arvaksin teisiti. Sa ei saa surnutega rääkida. Ma tean!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Sa võid kohata inimesi, kes on Labürindis lõksus, nagu Lachdanan. \\n\"\n\" \\n\"\n\"Ma tajun temas au ja suurt süüd. Aita teda, ja sa aitad kogu Tristramit.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Oota, las ma arvan. Cain neelati alla hiiglaslik lõhe, mis tema all avanes. \"\n\"Ta põles ära põrgutules ja ei saa enam su küsimustele vastata. Oh, see pole \"\n\"see, mis juhtus? Siis arvan, et sa kas ostad midagi või lähed oma teed.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Palun, ära tapa mind, kuula mind ära. Ma olin kunagi kuningas Leorici \"\n\"rüütlite kapten, kaitstes selle maa seadusi õigluse ja au nimel. Siis langes \"\n\"tema tume needus meie peale rolli eest, mida me tema traagilises surmas \"\n\"mängisime. Kui mu kaasrüütlid alistusid oma moonutatud saatusele, põgenesin \"\n\"ma kuninga matmiskambrist, otsides viisi, kuidas end needusest vabastada. Ma \"\n\"ebaõnnestusin...\\n\"\n\"\\n\"\n\"Olen kuulnud Kuldse Eliksiiri kohta, mis võiks needuse tõsta ja mu hinge \"\n\"rahu tuua, kuid ma pole suutnud seda leida. Mu jõud kahaneb nüüd ja sellega \"\n\"koos ka viimane osa mu inimlikkusest. Palun aita mind ja leia Eliksiir. Ma \"\n\"tasun su pingutused - vannun oma au nimel.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Sa pole leidnud Kuldset Eliksiiri. Ma kardan, et olen igaveseks hukule \"\n\"määratud. Palun, jätka proovimist...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Sa oled päästnud mu hinge hukatusest ja selle eest olen ma sulle võlgu. Kui \"\n\"on kunagi võimalus, kuidas ma saan sind haua tagant tasuda, siis ma leian \"\n\"selle, aga praegu - võta mu kiiver. Teekonnal, millele ma asun, pole mul \"\n\"sellest suurt kasu. Olgu see sulle kaitseks allpoolsete tumedate jõudude \"\n\"vastu. Mine valgusega, mu sõber...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold räägib Raevualasest - legendaarne artefakt, mida on kaua otsitud, \"\n\"kuid kunagi ei leitud. Valmistatud Razor Piti deemonite metallist luudest, \"\n\"Raevualas valati ümber allilma viie võimsaima maagia koljude. Võimu ja kaose \"\n\"ruunidega kaunistatud, iga relv või turvis, mis selle alasi peal \"\n\"sepistatakse, sukeldub Kaose valdkonda, andes sellele maagilisi omadusi. \"\n\"Öeldakse, et Kaose ettearvamatu olemus teeb raskeks teada, milline on selle \"\n\"sepistamise tulemus...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Kas sa ei arva, et Griswold oleks parem inimene, kellelt selle kohta küsida? \"\n\"Ta on üsna osav, tead.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Kui sa oleksid otsinud teavet Ravimördi või Puhastamise Hõbekarika kohta, \"\n\"oleksin saanud sind aidata, mu sõber. Kuid selles asjas oleks parem, kui \"\n\"räägiksid kas Griswoldi või Cainiga.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Griswoldi isa rääkis meile, kui me üles kasvasime, hiiglaslikust alasist, \"\n\"mida kasutati võimsate relvade valmistamiseks. Ta ütles, et kui sellele \"\n\"alasile löödi haamriga, värises maa suure raevuga. Iga kord, kui maa liigub, \"\n\"meenub mulle see lugu.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Tervist! Alati on rõõm näha üht oma parimat klienti! Ma tean, et oled \"\n\"sügavamale Labürinti seiklemas, ja mul on sulle üks lugu, mida tasub \"\n\"kuulata...\\n\"\n\"\\n\"\n\"Üks meestest, kes Labürindist tagasi tuli, rääkis mulle müstilisest alasi, \"\n\"mille ta oma põgenemise ajal leidis. Tema kirjeldus meenutas mulle legende, \"\n\"mida kuulsin nooruses põlevast Põrgusepast, kus võimsad maagilised relvad \"\n\"sepistatakse. Legend rääkis, et sügaval Põrgusepas puhkab Raevu Alasi! See \"\n\"Alasi sisaldab endas deemonliku allilma olemust...\\n\"\n\"\\n\"\n\"Öeldakse, et iga relv, mis sepistatakse põleval Alasil, on täidetud suure \"\n\"väega. Kui see alasi on tõesti Raevu Alasi, võin ma sulle valmistada relva, \"\n\"mis suudab võita isegi kõige pimedama Põrgu isanda!\\n\"\n\"\\n\"\n\"Leia mulle see Alasi ja ma asun tööle!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Pole veel midagi, jah? Noh, otsi edasi. Alasi peal sepistatud relv võiks \"\n\"olla su parim lootus, ja ma olen kindel, et suudan sulle valmistada ühe \"\n\"legendaarsete mõõtmetega.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Ma ei suuda seda uskuda! See on Raevualasi - tubli töö, mu sõber. Nüüd \"\n\"näitame neile lurjustele, et põrgus pole ühtegi relva, mis oleks surmavam \"\n\"kui need, mida inimesed teevad! Võta see ja las Valgus kaitseb sind.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold ei saa oma alasit müüa. Mis ta siis teeb? Ja ma oleksin ka vihane, \"\n\"kui keegi minu alasi ära võtaks!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Labürindi sees on palju artefakte, mis omavad surelike mõistmisest kaugemale \"\n\"ulatuvaid jõude. Mõned neist sisaldavad fantastilist jõudu, mida saab \"\n\"kasutada nii Valguse kui Pimeduse poolt. Alasi kindlustamine allpoolt võiks \"\n\"muuta Patuse Sõja kulgu Valguse kasuks.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Kui sa selle eseme Griswoldile leiad, võib see mu äri siin tõsiselt \"\n\"kahjustada. Awwww, sa ei leia seda kunagi üles.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Vere ja Tule Saalid on müstilise päritoluga maamärgid. Kus iganes see \"\n\"raamat, millest sa loed, asub, on see kindlasti suurte jõudude paik.\\n\"\n\"\\n\"\n\"Legendid räägivad obsidiaankivist tahutud alusest, mille luudega kaetud \"\n\"pinnal on keevast verest bassein. Samuti viidatakse Verekividele, mis avavad \"\n\"ukse, mis kaitseb iidset aaret...\\n\"\n\"\\n\"\n\"Selle aarde olemus on spekulatsioonidega varjutatud, mu sõber, kuid \"\n\"räägitakse, et iidne kangelane Arkaine paigutas püha soomuse Valor salajasse \"\n\"varakambrisse. Arkaine oli esimene surelik, kes pööras Patuse Sõja käigu ja \"\n\"ajas pimeduse leegionid tagasi Põlevatesse Põrgutesse.\\n\"\n\"\\n\"\n\"Vahetult enne Arkaine'i surma peideti tema soomus salajasse varakambrisse. \"\n\"Räägitakse, et kui seda püha soomust taas vajatakse, tõuseb kangelane, kes \"\n\"kannab Valorit veel kord. Võib-olla oled sina see kangelane...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Iga laps kuuleb lugu sõdalasest Arkaine'ist ja tema müstilisest soomusrüüst \"\n\"nimega Valor. Kui sa suudaksid leida selle puhkepaiga, oleksid sa hästi \"\n\"kaitstud Labürindi kurjuse eest.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... see kõlab nagu midagi, mida ma peaksin mäletama, aga ma olen olnud \"\n\"nii hõivatud uute ravimeetodite õppimise ja paremate eliksiiride loomisega, \"\n\"et ma pean olema unustanud. Vabandust...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Maagilise soomusrüü Valori lugu on midagi, millest ma sageli poiste juttu \"\n\"kuulsin. Sa peaksid parem küsima mõnelt küla mehelt.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Soomus nimega Valor võib olla see, mis kallutab kaalukausid sinu kasuks. Ma \"\n\"ütlen sulle, et paljud on seda otsinud - sealhulgas mina ise. Arkaine peitis \"\n\"selle hästi, mu sõber, ja selle saladuste avamiseks, mis on seda kõik need \"\n\"aastad varjanud, on vaja enamat kui natuke õnne.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Kui leiad need Verekivid, kasuta neid ettevaatlikult. \\n\"\n\" \\n\"\n\"Tee on täis ohte ja sinu ainus lootus peitub sinu enese usalduses.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Kas sa kavatsed leida soomust, mida tuntakse kui Valor? \\n\"\n\" \\n\"\n\"Keegi pole kunagi välja selgitanud, kuhu Arkaine selle kraami peitis, ja kui \"\n\"minu kontaktid ei suutnud seda leida, siis ma tõsiselt kahtlen, et sina seda \"\n\"suudad.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Ma tean ainult üht legendi, mis räägib sellisest sõdalasest, nagu sa \"\n\"kirjeldad. Tema lugu on kirjas iidsetes Patu Sõja kroonikates...\\n\"\n\"\\n\"\n\"Tuhande aasta sõja, vere ja surma poolt määrdunud, seisab Vere Sõjapealik \"\n\"oma räsitud ohvrite mäel. Tema tume mõõk karjub elavatele musta needust; \"\n\"piinatud kutse kõigile, kes julgeksid seista selle Põrgu Timuka ees.\\n\"\n\"\\n\"\n\"Samuti on kirjas, et kuigi ta oli kunagi surelik, kes võitles Pimeduse \"\n\"Leegioni kõrval Patu Sõja ajal, kaotas ta oma inimlikkuse oma kustutamatu \"\n\"verejanu tõttu.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Kardan, ma pole kuulnud midagi sellisest kurjast sõdalasest, hea isand. \"\n\"Loodan, et sa ei pea temaga võitlema, sest ta kõlab äärmiselt ohtlikult.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain oskaks sulle sellise asja kohta palju rohkem rääkida, kui ma iialgi \"\n\"teada tahaksin.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Kui sa lähed võitlema nii raevuka vastasega, siis olgu valgus sinu teejuht \"\n\"ja kaitsja. Ma hoian sind oma mõtetes.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Pimedad ja kurjad legendid ümbritsevad üht Veresõdalast. Ole hästi ette \"\n\"valmistatud, mu sõber, sest ta ei näita halastust ega anna armu.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Kas sa pead alati verest rääkima? Aga lilled, päikesepaiste ja see kena \"\n\"tüdruk, kes jooke toob. Kuula, sõber - sa oled kinnisideeline, tead seda?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Ta oskused mõõgaga on vapustavad ja ta on elanud tuhandeid aastaid, tundes \"\n\"ainult sõjapidamist. Mul on kahju... Ma ei näe, kas sa suudad teda võita.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Ma pole kunagi selle sõjapealikuga, kellest sa räägid, kokku puutunud, aga \"\n\"tundub, et tal kulub palju mõõku. Ei oleks midagi selle vastu, et tema \"\n\"armeed varustada...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Mu mõõk laulab sinu vere järele, surelik, ja minu tumedad isandad ei luba \"\n\"seda keelata.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold räägib Taeva Kivist, mis oli määratud idaosas asuvasse enklaavi. \"\n\"Seda viidi sinna edasiseks uurimiseks. See kivi kiirgas energiat, mis \"\n\"kuidagi andis nägemise kaugemale kui tavaline inimene võiks omada. Ma ei \"\n\"tea, milliseid saladusi see peidab, mu sõber, kuid selle kivi leidmine oleks \"\n\"kindlasti väga väärtuslik.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Karavan peatus siin, et võtta teel itta mõned varud peale. Ma müüsin neile \"\n\"päris palju värskeid puuvilju ja mõned suurepärased magusad saiad, mille \"\n\"Garda just küpsetas. Kahju, mis nendega juhtus...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Ma ei tea, mida nad arvasid, et nad selle kiviga näha saavad, aga ma ütlen \"\n\"seda. Kui kivid taevast alla kukuvad, siis ole parem ettevaatlik!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Noh, üks väga tähtsate inimeste karavan peatus siin tõesti, aga see oli üsna \"\n\"ammu. Neil olid kummalised aktsendid ja nad alustasid pikka teekonda, kui ma \"\n\"õigesti mäletan.\\n\"\n\"\\n\"\n\"Ma ei näe, kuidas sa võiksid loota leida midagi, mida nad oleksid kaasa \"\n\"võtnud.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Peatu korraks - mul on lugu, mis võib sulle huvi pakkuda. Karavan, mis \"\n\"suundus idapoolsetesse kuningriikidesse, läbis siit mõni aeg tagasi. \"\n\"Väidetavalt vedas see taevatükki, mis oli maa peale langenud! Karavan sattus \"\n\"varjatud ratsanike rünnaku alla siinsamas põhja pool teel. Ma otsisin \"\n\"rusudest seda taevakivi, kuid seda polnud kusagil. Kui sa selle peaksid \"\n\"leidma, usun, et suudan sellest midagi kasulikku meisterdada.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Ma ikka veel ootan, et sa mulle selle taevast pärit kivi tooksid. Ma tean, \"\n\"et suudan sellest midagi võimsat teha.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Lase ma vaatan seda - jah... jah, see on nii, nagu ma arvasin. Anna mulle \"\n\"hetk...\\n\"\n\"\\n\"\n\"Ah, siin see on. Ma seadsin kivi tükid hõbesõrmuse sisse, mille mu isa mulle \"\n\"jättis. Loodan, et see teenib sind hästi.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Mul oli kunagi kena sõrmus; see oli tõesti kallis, sinise, rohelise, punase \"\n\"ja hõbedasega. Ei mäleta, mis sellega juhtus, aga ma tõesti igatsen seda \"\n\"sõrmust...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Taevakivi on väga võimas ja kui see oleks keegi muu kui Griswold, kes palus \"\n\"sul selle leida, siis ma takistaksin seda. Ta kasutab selle jõudu ja see on \"\n\"meile kõigile kasulik.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Kui keegi suudab sellest kivist midagi teha, siis Griswold suudab. Ta teab, \"\n\"mida ta teeb, ja kuigi ma püüan tema kliente varastada, austan ma tema töö \"\n\"kvaliteeti.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Nõid Adria otsib musta seent? Ma tean mustadest seentest sama palju kui \"\n\"punastest heeringatest. Võib-olla oskab Pepin Ravitseja sulle rohkem \"\n\"rääkida, kuid see on midagi, mida ei leia ühestki minu loost ega raamatust.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Las ma ütlen nii. Nii mina kui ka Garda ei serveeriks kunagi, MITTE KUNAGI \"\n\"musti seeni meie austatud külalistele. Kui Adria tahab oma hautisesse seeni, \"\n\"siis see on tema asi, aga ma ei saa sind nende leidmisel aidata. Mustad \"\n\"seened... vastikud!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Nõid ütles mulle, et sa otsisid deemonit, et aidata mul oma eliksiiri luua. \"\n\"See peaks olema suureks väärtuseks paljudele, keda need roojased elukad on \"\n\"vigastanud, kui ma suudan avada saladused, mida ma kahtlustan, et selle \"\n\"alkeemia peidab. Kui sa suudad deemonilt tema aju eemaldada, kui sa ta \"\n\"tapad, oleksin tänulik, kui sa selle mulle tooksid.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Suurepärane, see on täpselt see, mida ma silmas pidasin. Ma suutsin \"\n\"eliksiiri ilma selleta lõpetada, kuid sellest ei tee paha, kui mul on see \"\n\"uurimiseks. Kas sa viiksid selle nõiale? Ma usun, et ta ootab seda.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Ma arvan, et Ogdenil võib keldris mõned seened olla. Miks sa ei küsi tema \"\n\"käest?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Kui Adrial seda pole, siis võid kihla vedada, et see on tõesti haruldane \"\n\"asi. Ma ei saa sulle rohkem abi pakkuda, aga see kõlab nagu... tohutu, \"\n\"hiiglaslik, paistes, pundunud seen! Noh, head jahti, ma arvan.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden segab kokku VÄGA kange musta seene, aga ma jään haigeks, kui seda \"\n\"joon. Kuula, kuula... saladus on selles - mõõdukus on võti!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Mida me siin näeme? Huvitav, see näeb välja nagu reagendiraamat. Hoia silmad \"\n\"lahti musta seene jaoks. See peaks olema üsna suur ja kergesti äratuntav. \"\n\"Kui leiad selle, too see mulle, eks?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"See on suur must seen, mida mul vaja on. Nüüd jookse ja too see mulle, et \"\n\"saaksin seda kasutada spetsiaalse segu jaoks, mille kallal ma töötan.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Jah, see sobib ideaalselt ühe joogi jaoks, mida ma loon. Muide, ravitseja \"\n\"otsib mõne deemoni aju, et ravida neid, keda on nende mürgine mürk tabanud. \"\n\"Ma usun, et ta kavatseb sellest eliksiiri valmistada. Kui sa aitad tal \"\n\"leida, mida ta vajab, siis palun vaata, kas saaksid mulle eliksiiri proovi.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Miks sa selle siia tõid? Mul pole praegu deemonite aju vaja. Küll aga vajan \"\n\"ma tervendaja eliksiiri, mille kallal ta töötab. Ta vajab seda groteskset \"\n\"organit, mida sa käes hoiad, ja siis too mulle eliksiir. Kui järele mõelda, \"\n\"on see ju lihtne, kas pole?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Misasja? Nüüd tood sa mulle selle eliksiiri ravitsejalt? Ma sain oma keeduse \"\n\"ilma selleta valmis. Miks sa seda lihtsalt endale ei jäta...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Mul pole müüa ühtegi seent, ei suuruses ega värvis. Kuidas oleks millegi \"\n\"veidi kasulikumaga?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Nii et, kaardi legend on tõsi. Isegi mina ei uskunud seda kunagi täielikult! \"\n\"Arvan, et on aeg, et ma räägiksin sulle tõtt selle kohta, kes ma tegelikult \"\n\"olen, mu sõber. Näed, ma ei ole see, kes ma paistan olevat...\\n\"\n\"\\n\"\n\"Minu tõeline nimi on Deckard Cain Vanem, ja ma olen iidse Vennaskonna \"\n\"viimane järeltulija, mis oli pühendunud ajatu kurjuse saladuste hoidmisele \"\n\"ja kaitsmisele. Kurjus, mis on nüüd ilmselgelt valla päästetud...\\n\"\n\"\\n\"\n\"Kurjus, mille vastu sa astud, on Pimeduse Hirmu Isand - surelikele meestele \"\n\"tuntud kui Diablo. Tema oli see, kes vangistati Labürinti paljude sajandite \"\n\"eest. Kaart, mida sa nüüd käes hoiad, loodi ammu, et märkida aega, mil \"\n\"Diablo tõuseks taas oma vangistusest. Kui kaardil olevad kaks tähte \"\n\"joondavad, on Diablo oma võimu tipul. Ta on peaaegu võitmatu...\\n\"\n\"\\n\"\n\"Sa oled nüüd ajaga võidu jooksmas, mu sõber! Leia Diablo ja hävita ta enne, \"\n\"kui tähed joondavad, sest meil ei pruugi kunagi enam olla võimalust tema \"\n\"kurjusest maailma vabastada!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Meie aeg hakkab otsa saama! Ma tunnen, kuidas tema tume jõud kasvab, ja \"\n\"ainult sina saad takistada teda saavutamast oma täielikku väge.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Ma olen kindel, et sa andsid endast parima, kuid kardan, et isegi sinu jõud \"\n\"ja tahe ei pruugi olla piisavad. Diablo on nüüd oma maise võimu tipul ja sa \"\n\"vajad kogu oma julgust ja jõudu, et teda võita. Olgu valgus sinu kaitseks ja \"\n\"juhatuseks, mu sõber. Ma aitan sind igal võimalikul viisil.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Kui nõid ei saa sind aidata ja soovitab sul Caini juurde minna, siis miks sa \"\n\"arvad, et mina midagi teaksin? Tundub, et see on väga tõsine asi. Sa peaksid \"\n\"kiirustama ja minema jutuvestja juurde, nagu Adria soovitab.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Ma ei suuda selle kaardi kirjutisest palju aru saada, kuid võib-olla Adria \"\n\"või Cain saaksid sind aidata selle tähenduse lahtimõtestamisel. \\n\"\n\" \\n\"\n\"Ma näen, et see on kaart meie taeva tähtedest, kuid rohkem kui see on minu \"\n\"võimetest üle.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Sellise asja kohta oleks kõige parem küsida meie jutuvestjalt. \\n\"\n\" \\n\"\n\"Cain teab väga palju iidsetest kirjutistest ja see on kindlasti kõige vanem \"\n\"välja nägev paberitükk, mida ma kunagi näinud olen.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Ma pole kunagi varem sellist kaarti näinud. Kust sa selle said? Kuigi mul \"\n\"pole aimugi, kuidas seda lugeda, võivad Cain või Adria sulle vajalikke \"\n\"vastuseid anda.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Kuule nüüd, tule lähemale. Ma ei tea, kas sa tead seda, mida mina tean, aga \"\n\"sul on siin tõesti midagi erilist. See on kaart.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Oh, ma kardan, et see ei tõota üldse head. See tähtede kaart ennustab suurt \"\n\"katastroofi, kuid selle saladused pole minu omad, mida rääkida. On aeg, et \"\n\"sa peaksid väga tõsise vestluse Jutustajaga...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Olen otsinud kaarti, aga see kindlasti ei ole see. Sa peaksid seda Adrialle \"\n\"näitama - ta oskab sulle tõenäoliselt öelda, mis see on. Üht asja ma ütlen; \"\n\"see näeb vana välja ja vana tähendab tavaliselt väärtuslikku.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Palun, ärge tehke haiget. Ärge tapke. Jätke ellu ja järgmisel korral toon \"\n\"teile midagi head.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Midagi sinu jaoks ma teen. Jälle, ära tapa Gharbadi. Ela ja anna head. \\n\"\n\" \\n\"\n\"Võta see tõestuseks, et ma pean sõna...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Veel mitte! Peaaegu valmis. \\n\"\n\" \\n\"\n\"Väga võimas, väga tugev. Ela! Ela! \\n\"\n\" \\n\"\n\"Ei mingit valu ja lubadust ma pean!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"See on sinu jaoks liiga hea. Väga võimas! Tahad - võta!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Mida?! Miks sa siin oled? Kõik need katkestused ajavad inimese hulluks. \"\n\"Siin, võta see ja jäta mind mu tööle. Ära mind enam tülita!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Su uudishimu saab teile saatuslikuks!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Tere, mu sõber. Peatu hetkeks ja kuula...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Kui sa seikled sügavamale Labürinti, võid leida sealt peidetud suure \"\n\"teadmistega raamatuid. \\n\"\n\" \\n\"\n\"Loe neid hoolikalt, sest need võivad sulle rääkida asju, mida isegi mina ei \"\n\"suuda.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Ma tean paljusid müüte ja legende, mis võivad sisaldada vastuseid \"\n\"küsimustele, mis võivad teie teekonnal Labürinti tekkida. Kui kohtate \"\n\"väljakutseid ja küsimusi, millele te teadmisi otsite, otsige mind üles ja ma \"\n\"räägin teile, mida oskan.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold - mees, kes on täis tegusid ja julgust. Ma kihla vean, et ta pole \"\n\"sulle kunagi rääkinud ajast, mil ta läks Labürinti, et Wirt päästa, kas \"\n\"pole? Ta teab seal peituvaid ohte üsna hästi, aga samas - nii tead ka sina. \"\n\"Ta on osav käsitöömeister ja kui ta väidab, et suudab sind kuidagi aidata, \"\n\"võid tema aususele ja oskustele kindel olla.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden on olnud Tõusva Päikese kõrtsi ja võõrastemaja omanik ja juht peaaegu \"\n\"neli aastat. Ta ostis selle vaid mõned kuud enne, kui kõik siin põrguks \"\n\"muutus. Tema ja ta naine Garda ei saa lahkuda, kuna nad investeerisid kõik, \"\n\"mis neil oli, et siin endale elu luua. Ta on hea mees, kellel on sügav \"\n\"vastutustunne.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Vaene Farnham. Ta on rahutukstegev meeldetuletus hukule määratud \"\n\"seltskonnast, kes sisenes katedraali koos Lazarusega tol pimedal päeval. Ta \"\n\"pääses eluga, kuid tema julgus ja suur osa mõistusest jäid mingisse \"\n\"pimedasse auku. Tänapäeval leiab ta lohutust vaid oma kannu põhjast, kuid \"\n\"tema pideva lobisemise sees on aeg-ajalt peidus tõe killukesi.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Nõid Adria on siin Tristramis tõeline anomaalia. Ta saabus vahetult pärast \"\n\"seda, kui katedraal rüvetati, samal ajal kui enamik inimesi põgenes. Ta lasi \"\n\"ehitada väikese onni linna servale, näiliselt üleöö, ja tal on ligipääs \"\n\"paljudele kummalistele ja salapärastele artefaktidele ning teadmiste \"\n\"raamatutele, mida isegi mina pole varem näinud.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Wirti lugu on hirmutav ja traagiline. Ta kisti oma ema käte vahelt ja veeti \"\n\"labürinti väikeste, roojaste deemonite poolt, kes kandsid kurje odasid. Sel \"\n\"päeval viidi ära palju teisi lapsi, sealhulgas kuningas Leorici poeg. Palee \"\n\"rüütlid läksid alla, kuid ei naasnud kunagi. Sepis leidis poisi, kuid alles \"\n\"pärast seda, kui roojased elukad olid hakanud teda oma sadistliku naudingu \"\n\"nimel piinama.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Ma pean teda tõeliseks sõbraks - võib-olla kõige lähedasemaks, \"\n\"kes mul siin on. Ta on vahel veidi hajameelne, kuid pole kunagi olnud \"\n\"hoolivamat või tähelepanelikumat hinge. Tema teadmised ja oskused on \"\n\"vähestel võrdsed ning tema uks on alati avatud.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian on tore naine. Tema kõrge vaim ja kiire naer on väga hinnatud ning \"\n\"tal on minu südames eriline koht. Ta jääb kõrtsi, et toetada oma vanaema, \"\n\"kes on liiga haige, et reisida. Mõnikord kardan tema turvalisuse pärast, \"\n\"kuid tean, et iga mees külas pigem sureks, kui laseks tal viga saada.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Tervist, hea meister. Tere tulemast Tõusva Päikese Kõrtsi!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Paljud seiklejad on istunud minu kõrtsi laudade taga ja kümme korda rohkem \"\n\"lugusid on räägitud sama palju õlle kõrvale. Ainus asi, milles ma kunagi \"\n\"kuulsin neid kõiki nõustuvat, oli see vana tõdemus. Võib-olla aitab see \"\n\"sind. Sa võid lõigata liha, aga sa pead purustama luu.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Sepp Griswold, sepp, teab relvade ja turviste kohta kõike. Kui sul on kunagi \"\n\"vaja oma varustust parandada, siis on tema kindlasti see, kelle poole \"\n\"pöörduda.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham veedab siin liiga palju aega, uputades oma muresid odavasse õllesse. \"\n\"Ma ajaksin ta minema, kuid ta kannatas labürindis viibimise ajal nii palju.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria on oma aastatest targem, kuid pean tunnistama - ta hirmutab mind \"\n\"veidi. \\n\"\n\" \\n\"\n\"Noh, pole hullu. Kui sul kunagi on vaja nõiduse esemeid vahetada, siis tal \"\n\"on jõe teisel kaldal kummaliselt hästi varustatud onn.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Kui sa tahad rohkem teada meie küla ajaloost, siis jutuvestja Cain teab \"\n\"minevikust üsna palju.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt on üks väänik ja väike kelm. Ta sattus alati pahandustesse ja pole ime, \"\n\"mis temaga juhtus. \\n\"\n\" \\n\"\n\"Ta läks ilmselt lollitama kohta, kus ta poleks pidanud olema. Mul on poisist \"\n\"kahju, aga ma ei salli seltskonda, kellega ta läbi käib.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin on hea mees - ja kindlasti kõige heldem külas. Ta hoolitseb alati \"\n\"teiste vajaduste eest, kuid mingisugused probleemid näivad teda kõikjal \"\n\"saatvat...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, minu baaridaam? Kui poleks tema kohusetunnet oma vanaema vastu, \"\n\"oleks ta siit ammu põgenenud. \\n\"\n\" \\n\"\n\"Hea taevas teab, et ma palusin tal lahkuda, öeldes, et hoolitsen vana naise \"\n\"eest ise, kuid ta on liiga armas ja hooliv, et seda teha.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Mis sind vaevab, mu sõber?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Olen teinud väga huvitava avastuse. Erinevalt meist suudavad Labürindi \"\n\"olendid end tervendada ilma jookide või maagia abita. Kui sa vigastad ühte \"\n\"koletist, veendu, et see on surnud, muidu võib see end uuesti tervendada.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Enne kui see, noh, miski, mis seal allpool varitseb, üle võttis, oli \"\n\"katedraal suurte teadmiste paik. Seal leidub palju raamatuid. Kui sa mõne \"\n\"leiad, peaksid need kõik läbi lugema, sest mõned võivad sisaldada saladusi \"\n\"Labürindi toimimise kohta.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold teab sõjakunstist sama palju kui mina ravikunstist. Ta on kaval \"\n\"kaupmees, kuid tema töö on ületamatu. Oh, ma arvan, et see võib olla \"\n\"sellepärast, et ta on ainus sepp, kes siia jäänud on.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain on tõeline sõber ja tark õpetlane. Tal on suur raamatukogu ja \"\n\"kaasasündinud võime eristada paljude asjade tõelist olemust. Kui sul on \"\n\"kunagi küsimusi, siis tema poole tasub pöörduda.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Isegi minu oskused pole suutnud Farnhamit täielikult tervendada. Oh, ma olen \"\n\"suutnud tema keha parandada, kuid tema meel ja vaim on väljaspool seda, mida \"\n\"ma suudan teha.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Kuigi ma kasutan siin hoitavate jookide ja eliksiiride loomiseks mõningaid \"\n\"piiratud maagia vorme, on Adria tõeline nõid. Tundub, et ta ei maga kunagi \"\n\"ja tal on alati ligipääs paljudele müstilistele raamatutele ja \"\n\"artefaktidele. Ma usun, et tema onn võib olla palju enamat kui see, mis \"\n\"paistab, kuid ma ei suuda kunagi sinna sisse pääseda.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Vaene Wirt. Ma tegin kõik, mis võimalik, et last aidata, kuid ma tean, et ta \"\n\"põlgab seda puujalga, mille ma pidin tema jalale kinnitama. Tema haavad olid \"\n\"kohutavad. Keegi - ja eriti nii noor laps - ei peaks kannatama nii, nagu \"\n\"tema seda tegi.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Ma tõesti ei mõista, miks Ogden siia Tristrami jääb. Tal on kerge \"\n\"närvihäire, kuid ta on intelligentne ja töökas mees, kes saaks igal pool \"\n\"hästi hakkama. Ma arvan, et see võib olla hirm paljude mõrvade ees, mis \"\n\"ümbritsevas maapiirkonnas toimuvad, või ehk tema naise soovid, mis hoiavad \"\n\"teda ja tema perekonda seal, kus nad on.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogdeni baaridaam on armas tüdruk. Tema vanaema on üsna haige ja kannatab \"\n\"luulude all. \\n\"\n\" \\n\"\n\"Ta väidab, et need on nägemused, kuid mul pole selle kohta tõendeid ei üht \"\n\"ega teistpidi.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Tere päevast! Kuidas saan teid aidata?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Mu vanaemal oli unenägu, et sa tuled ja räägid minuga. Tal on nägemused, \"\n\"tead, ja ta suudab tulevikku näha.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"See naine linna serval on nõid! Ta tundub küllaltki kena ja tema nimi, \"\n\"Adria, kõlab väga meeldivalt, kuid ma kardan teda väga. \\n\"\n\" \\n\"\n\"Vaja oleks kedagi üsna julget, nagu sina, et näha, mida ta seal teeb.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Meie sepp on Tristrami rahva uhkuse allikas. Ta ei ole mitte ainult \"\n\"meisterlik käsitööline, kes on oma gildis võitnud palju võistlusi, vaid ta \"\n\"on saanud kiitust ka meie kuningas Leoricult endalt - rahu tema hingele. \"\n\"Griswold on ka suur kangelane; küsi ainult Cainilt.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain on olnud Tristrami jutuvestja nii kaua, kui ma mäletan. Ta teab nii \"\n\"palju ja oskab sulle rääkida peaaegu kõigest kõike.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham on joodik, kes täidab oma kõhtu õllega ja teiste kõrvu jamaga. \\n\"\n\" \\n\"\n\"Ma tean, et nii Pepin kui ka Ogden tunnevad talle kaasa, kuid mind ajab nii \"\n\"närvi, kui näen teda igal õhtul üha sügavamale segadusse vajumas.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin päästis mu vanaema elu ja ma tean, et ma ei suuda teda selle eest \"\n\"kunagi piisavalt tänada. Tema võime ravida igasuguseid haigusi on võimsam \"\n\"kui kõige võimsam mõõk ja salapärasem kui ükski loits, mida sa nimetada \"\n\"oskad. Kui sul kunagi on tervendamist vaja, siis Pepin saab sind aidata.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Kasvasin üles Wirti ema, Canace'iga. Kuigi ta sai vaid veidi viga, kui need \"\n\"jubedad olendid ta röövisid, ei paranenud ta kunagi. Ma arvan, et ta suri \"\n\"murtud südame tõttu. Wirtist on saanud pahatahtlik nooruk, kes otsib vaid \"\n\"kasu teiste vaevast. Ma tean, et ta on kannatanud ja näinud õudusi, mida ma \"\n\"ei suuda ette kujutada, kuid osa sellest pimedusest ripub tema kohal \"\n\"endiselt.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden ja tema naine on võtnud mind ja mu vanaema oma koju ning isegi lubanud \"\n\"mul kõrtsis töötades mõned kuldtükid teenida. Ma olen neile nii palju võlgu \"\n\"ja loodan, et ühel päeval saan siit lahkuda ja aidata neil idas suure \"\n\"hotelli avada.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Noh, mis ma sinu heaks teha saan?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Kui otsid head relva, siis las ma näitan sulle seda. Võta näiteks tavaline \"\n\"nüri relv, nagu nui. Toimib nagu võluväel enamiku nende all olevate \"\n\"surematute õuduste vastu ja pole midagi paremat, millega purustada kondiseid \"\n\"väikseid skelette!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Kirves? Jah, see on hea relv, tasakaalus iga vaenlase vastu. Vaata, kuidas \"\n\"see õhku lõikab, ja kujuta ette kena paksu deemoni pead selle teel. Pea \"\n\"siiski meeles, et see on aeglane kiigutada - aga räägi raskest löögist!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Vaata seda tera, seda tasakaalu. Õiges käes ja õige vaenlase vastu on mõõk \"\n\"kõigi relvade meister. Selle terav tera ei leia palju raiuda ega torgata \"\n\"elavate surnute peal, kuid elava ja hingava vaenlase vastu lõikab mõõk \"\n\"paremini nende liha!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Sinu relvad ja turvised näitavad märke sinu võitlustest Pimeduse vastu. Kui \"\n\"sa tood need mulle, siis natukese töö ja kuuma ahju abil saan ma need taas \"\n\"parimasse võitlusvormi taastada.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Kuigi ma pean praktiliselt salakaubana sisse tooma metallid ja tööriistad, \"\n\"mida ma vajan, karavanidelt, mis meie neetud linna serva mööda liiguvad, \"\n\"näib see nõid Adria alati saavat, mida iganes ta vajab. Kui ma teaksin isegi \"\n\"vähimatki sellest, kuidas maagiat valitseda nagu tema, suudaksin ma teha \"\n\"tõeliselt uskumatuid asju.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian on kena neiu. Kahju, et tema vanaema tervis on nii kehv, muidu \"\n\"korraldaksin, et nad mõlemad saaksid siit ühe kaubakaravaniga minema.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Mõnikord ma arvan, et Cain räägib liiga palju, aga ma arvan, et see on tema \"\n\"kutsumus elus. Kui ma suudaksin terast painutada sama hästi, kui tema suudab \"\n\"su kõrva painutada, siis ma võiksin teha keisrile sobiva turvisesärgi!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Ma olin koos Farnhamiga sel ööl, kui Lazarus meid Labürinti juhtis. Ma ei \"\n\"näinud enam kunagi peapiiskoppi ja ma ei pruukinud ellu jääda, kui Farnham \"\n\"poleks minu kõrval olnud. Ma kardan, et rünnak jättis tema hinge sama \"\n\"vigaseks kui, noh, teine tegi minu jalaga. Ma ei saa seda lahingut tema eest \"\n\"nüüd pidada, aga ma teeksin seda, kui saaksin.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Hea mees, kes seab teiste vajadused enda omadest ettepoole. Sa ei leia \"\n\"Tristramist - ega kuskilt mujaltki - kedagi, kellel oleks ravitseja kohta \"\n\"midagi halba öelda.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"See poiss satub endale tõsisesse jamasse... või peaksin ütlema, jälle. Olen \"\n\"püüdnud teda huvitada siin töötamises ja ausa ameti õppimises, kuid talle \"\n\"meeldivad rohkem kahtlase päritoluga kaupade kõrged kasumid. Ma ei saa talle \"\n\"seda pahaks panna pärast seda, mis temaga juhtus, kuid ma soovin, et ta \"\n\"oleks vähemalt ettevaatlik.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Võõrastemaja pidajal on vähe äri ja pole tõelist võimalust kasumit teenida. \"\n\"Ta suudab ots-otsaga kokku tulla, pakkudes toitu ja majutust neile, kes aeg-\"\n\"ajalt külast läbi rändavad, kuid nad on sama tõenäoliselt öösel minema \"\n\"hiilimas kui talle maksmas. Kui poleks olnud teravilja- ja kuivatatud liha \"\n\"varusid, mida ta oma keldris hoidis, siis oleks enamik meist esimesel \"\n\"aastal, kui kogu maapiirkond oli deemonite poolt üle ujutatud, nälga surnud.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Kas ei saa mees rahus juua?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"See neiu, kes jooke toob? Oh, jah, milline kena daam. Nii tore ka veel.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Miks see vana nõid midagi ei tee. Jah, jah, tal on kraami, aga kuula mind... \"\n\"ta on ebaloomulik. Ma pole teda kunagi söömas ega joomas näinud - ja sa ei \"\n\"saa usaldada kedagi, kes vähemalt natuke ei joo.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain ei ole see, kelleks ta end väidab. Jah, jah, ta räägib häid lugusid... \"\n\"mõned neist on tõeliselt hirmutavad või naljakad... aga ma arvan, et ta teab \"\n\"rohkem, kui ta ise arvab, et teab.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Hea vana Griswold. Ma armastan teda nagu venda! Me võitlesime \"\n\"koos, tead, tagasi siis kui... me... Lazarus... Lazarus... Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, mulle meeldib Pepin. Ta tõesti pingutab, tead. Kuula, sa peaksid \"\n\"kindlasti temaga tuttavaks saama. Hea mees, kes alati tahab aidata. Hei, ma \"\n\"arvan, et see oleks natuke nagu sina, eks kangelane? Ma olin ka kunagi \"\n\"kangelane...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt on poiss, kellel on rohkem probleeme kui minul, ja ma tean kõike \"\n\"probleemidest. Kuula nüüd - sellel poisil on magus äri, aga ta on seal \"\n\"olnud, tead? Kaotas jala! Peab ringi käima puutükiga. Nii kurb, nii kurb...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden on linna parim mees. Ma ei usu, et tema naine minust eriti hoolib, aga \"\n\"seni, kuni ta vaatevaateid täidab, meeldib ta mulle küll. Tundub, et olen \"\n\"Ogdeniga rohkem aega veetnud kui enamikega, aga ta on minuga nii hea...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Ma tahan sulle midagi öelda, sest ma tean kõike sellest kraamist. See on \"\n\"minu eriala. See siin on parim... paaaaarim! See teine õlu pole enam hea, \"\n\"sest need rumalad koerad...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Keegi ei kuula mind kunagi... kusagil - ma pole päris kindel - aga kusagil \"\n\"kiriku all on terve hunnik kulda. Läikiv ja särav ning ootab vaid, et keegi \"\n\"selle kätte saaks.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Ma tean, et sul on omad mõtted, ja ma tean, et sa ei usu mind, aga see relv, \"\n\"mis sul seal on - see lihtsalt ei kõlba nende suurte jõmmide vastu! Oh, mind \"\n\"ei huvita, mida Griswold ütleb, nad ei suuda enam teha asju nii nagu \"\n\"vanasti...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Kui mina oleksin sina... ja ma ei ole... aga kui oleksin, siis ma müüksin \"\n\"kogu selle kraami maha ja läheksin siit minema. See poiss seal väljas... Tal \"\n\"on alati midagi head, aga sa pead talle kulda andma, muidu ta ei näita sulle \"\n\"isegi, mis tal on.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Ma tunnen hinge, kes otsib vastuseid...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Tarkus on välja teenitud, mitte antud. Kui leiad teadmiste raamatu, neela \"\n\"selle sõnad alla. Kui sul on juba teadmisi raamatusse kirjutatud \"\n\"salapärastest saladustest, pea meeles - see meisterlikkuse tase saab alati \"\n\"kasvada.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Suurim jõud on sageli kõige lühemaealine. Sa võid leida iidseid võlusõnu \"\n\"kirjutatuna pärgamendirullidele. Nende rullide tugevus peitub selles, et nii \"\n\"õpipoiss kui ka meister suudavad neid võrdselt kasutada. Nende nõrkus \"\n\"seisneb aga selles, et neid tuleb esmalt valjusti ette lugeda ja neid ei saa \"\n\"kunagi oma mõttes valmis hoida. Tea ka, et neid rulle saab lugeda vaid \"\n\"korra, seega kasuta neid hoolikalt.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Kuigi päikese kuumus on mõõtmatu, on küünla leek suurem oht. Ükskõik kui \"\n\"suured energiad, neid ei saa kasutada ilma õige keskendumiseta. Paljude \"\n\"loitsude jaoks saab võluväelisi sauasid korduvalt maagiliste energiatega \"\n\"laadida. Mul on võime nende jõudu taastada - kuid tea, et midagi ei tehta \"\n\"ilma hinnata.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Meie teadmiste summa peitub meie inimeste summas. Kui leiad raamatu või \"\n\"kirjarulli, mida sa ei suuda lahti mõtestada, ära kõhkle seda mulle toomast. \"\n\"Kui ma suudan sellest aru saada, jagan ma leitud teadmisi sinuga.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Mehele, kes tunneb ainult rauda, pole suuremat maagiat kui teras. Sepistaja \"\n\"Griswold on rohkem nõid, kui ta ise teab. Tema oskus tuld ja metalli \"\n\"ühendada on selles maal võrreldamatu.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Rikkumine omab pettuse jõudu, kuid süütus kannab puhtuse väge. Noor naine \"\n\"Gillian on puhta südamega, seades oma matriarhaadi vajadused enda omadest \"\n\"ettepoole. Ta kardab mind, kuid see on ainult sellepärast, et ta ei mõista \"\n\"mind.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Pimeduses avatud kirst ei sisalda suuremat aaret kui valguses avatud kirst. \"\n\"Jutustaja Cain on mõistatus, kuid ainult neile, kes ei vaata. Tema teadmised \"\n\"sellest, mis peitub katedraali all, on palju suuremad, kui ta ise endale \"\n\"tunnistada lubab.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Mida kõrgemale sa oma usu ühte inimesse asetad, seda kaugemale on tal \"\n\"kukkuda. Farnham on kaotanud oma hinge, kuid mitte ühelegi deemonile. See \"\n\"kadus, kui ta nägi, kuidas peapiiskop Lazarus reetis oma kaaslinlasi. Tal on \"\n\"teadmisi, mida saab ammutada, kuid sa pead eristama fakti fantaasiast.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Käsi, süda ja meel võivad korda saata imesid, kui nad on täiuslikus \"\n\"harmoonias. Ravitseja Pepin näeb kehasse viisil, mida isegi mina ei suuda. \"\n\"Tema võime taastada haigeid ja vigastatuid on võimendatud tema arusaamast \"\n\"eliksiiride ja jookide loomisest. Ta on sama suur liitlane kui sina \"\n\"Tristramis.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Tulevikust on palju, mida me ei näe, kuid kui see saabub, on lapsed need, \"\n\"kes seda juhivad. Poisil Wirt'il on hingel mustus, kuid ta ei kujuta linnale \"\n\"ega selle rahvale ohtu. Tema salajased tehingud lähedal asuvate linnade \"\n\"tänavalaste ja sõnatu gildidega annavad talle juurdepääsu paljudele \"\n\"seadmetele, mida Tristramis pole lihtne leida. Kuigi tema meetodid võivad \"\n\"olla taunitavad, võib Wirt pakkuda abi sinu võitluses läheneva Pimeduse \"\n\"vastu.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Maa-seinad ja õlgkatus ei loo kodu. Kõrtsmik Ogden täidab selles linnas \"\n\"suuremat eesmärki, kui paljud mõistavad. Ta pakub peavarju Gillianile ja \"\n\"tema matriarhile, hoiab elus Farnhami jäänuseid ja on ankruks kõigile, kes \"\n\"on linna jäänud, meenutades, milline Tristram kunagi oli. Tema kõrts ja \"\n\"lihtsad naudingud, mida seal veel leida võib, pakuvad pilguheitu elule, mida \"\n\"inimesed siin mäletavad. Just see mälestus toidab nende lootusi sinu edule.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... siia poole...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Mitte kõigil Tristrami elanikel pole kasutust - ega turgu - kõigele, mida sa \"\n\"labürindist leiad. Isegi minul mitte, kuigi seda on raske uskuda. \\n\"\n\" \\n\"\n\"Mõnikord oled ainult sina see, kes suudab mõnele asjale otstarbe leida.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Ära usalda kõike, mida purjus mees räägib. Liiga palju õlut on tema nägemise \"\n\"ja terve mõistuse hägustanud.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Kui sa pole veel märganud, siis ma ei osta Tristramist midagi. Olen \"\n\"kvaliteetkaupade importija. Kui tahad rämpsu müüa, pead pöörduma Griswoldi, \"\n\"Pepini või selle nõia, Adria poole. Olen kindel, et nad haaravad kinni \"\n\"kõigest, mida neile tood...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Ma arvan, et ma võlgnen sepa oma elu - mis sellest veel järel on. Kindlasti \"\n\"pakkus Griswold mulle sepa juures õpipoisi kohta ja ta on küllaltki tore \"\n\"mees, aga ma ei saa kunagi piisavalt raha, et... noh, ütleme lihtsalt, et \"\n\"mul on kindlad plaanid, mis nõuavad suurt hulka kulda.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Kui ma oleksin paar aastat vanem, siis ma kataksin teda kõigi nende \"\n\"rikkustega, mida suudaksin kokku ajada, ja las ma kinnitan sulle, et ma saan \"\n\"kätte väga kena kraami. Gillian on ilus tüdruk, kes peaks Tristramist \"\n\"lahkuma niipea, kui see on ohutu. Hmmm... võib-olla võtan ta endaga kaasa, \"\n\"kui ma lähen...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain teab liiga palju. Ta ajab mulle hirmu nahka - isegi rohkem kui see \"\n\"naine üle jõe. Ta räägib mulle pidevalt, kui õnnelik ma olen, et olen elus, \"\n\"ja kuidas minu lugu on legendides ette kuulutatud. Ma arvan, et ta on peast \"\n\"segi.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - nüüd on seal mees, kellel on tõsiseid probleeme, ja ma tean kõike, \"\n\"kui tõsised need probleemid võivad olla. Ta usaldas liiga palju ühe mehe \"\n\"ausust ja Lazarus viis ta otse surma lõugade vahele. Oh, ma tean, mis seal \"\n\"all toimub, nii et ära hakka mulle rääkima oma plaanidest hävitada kurjus, \"\n\"mis elab selles Labürindis. Hoia lihtsalt oma jalgu...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Niikaua kui sa ei vaja midagi tagasi kinnitada, on vana Pepin nii hea kui \"\n\"nad tulevad. \\n\"\n\" \\n\"\n\"Kui mul oleks olnud mõni neist jookidest, mida ta keedab, võiks mul ikka \"\n\"veel jalg olla...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria ajab mind tõesti närvi. Muidugi, Cain on veider oma teadmistega \"\n\"minevikust, aga see nõid suudab näha sinu minevikku. Tal on alati mingi \"\n\"viis, kuidas saada, mida iganes ta vajab. Adria saab oma käed rohkemale \"\n\"kaubale kui ma olen näinud kuninga turu väravatest läbi minemas Suure \"\n\"Pidustuse ajal.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden on rumal, et siia jääb. Ma võiksin ta väga mõistliku hinnaga linnast \"\n\"välja viia, aga ta nõuab, et proovib selle rumala kõrtsiga hakkama saada. Ma \"\n\"arvan, et vähemalt annab ta Gillianile töökoha ja tema naine Garda teeb \"\n\"suurepärast lambakoera pirukat...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Kangelaste Saali taga asub Luu Kamber. Igavene surm ootab neid, kes püüavad \"\n\"varastada selles ruumis peidetud aardeid. Nii räägib Hirmu Isand, ja nii on \"\n\"see kirja pandud.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...ja nii, lukustatud Verevärava taha ja Tule Saali taha, ootab Vapruse \"\n\"kangelast, et valguse kangelane ärkaks...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Ma näen seda, mida sina ei näe.\\n\"\n\"Nägemine piimjas, siis silmad mädanevad.\\n\"\n\"Kui pöörad, on nad kadunud,\\n\"\n\"Salalaulu sosistades.\\n\"\n\"Siis näed, mida ei saa olla,\\n\"\n\"Varjud liiguvad seal, kus peaks olema valgus.\\n\"\n\"Pimedusest, meelest ära,\\n\"\n\"Heidetud Pimedate Saalidesse.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Põrgu relvaladudes elab Vereisand. Tema järel lebavad tuhandete moonutatud \"\n\"kehad. Inglid ja inimesed on langenud, et täita tema lõputuid ohverdusi \"\n\"Pimedatele, kes karjuvad ühe asja järele - vere.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Olge ettevaatlik ja tunnistage tõdesid, mis siin peituvad, sest need on \"\n\"Horadrimi viimane pärand. On sõda, mis möllab ka praegu, kaugemal kui meile \"\n\"tuntud väljad - utoopiliste Kõrgtaevade kuningriikide ja Põrgupõhjade \"\n\"kaootiliste sügavuste vahel. Seda sõda tuntakse kui Suurt Konflikti ja see \"\n\"on möllanud ja põlenud kauem kui ükski täht taevas. Kumbki pool ei saa \"\n\"kunagi pikaks ajaks ülekaalu, sest Valguse ja Pimeduse jõud võitlevad \"\n\"pidevalt kogu loodu üle kontrolli saavutamise nimel.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Olge tähele ja tunnistage tõdesid, mis siin peituvad, sest need on Horadrimi \"\n\"viimane pärand. Kui Igavene Konflikt Kõrgemate Taevaste ja Põlevate Põrgute \"\n\"vahel langeb surelike maale, nimetatakse seda Patuseks Sõjaks. Inglid ja \"\n\"Deemonid kõnnivad inimkonna seas maskeeritult, võideldes salaja, eemal \"\n\"surelike uudishimulikest pilkudest. Mõned julged ja võimsad surelikud on \"\n\"isegi liitunud ühe või teise poolega ning aidanud määrata Patuse Sõja kulgu.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Olge hoolega ja tunnistage tõdesid, mis siin peituvad, sest need on \"\n\"Horadrimi viimane pärand. Peaaegu kolmsada aastat tagasi sai teatavaks, et \"\n\"Põrgupõhja Kolm Peamist Kurjust olid salapäraselt meie maailma tulnud. Kolm \"\n\"Venda laastasid idamaid aastakümneid, samal ajal kui inimkond värises nende \"\n\"järel. Meie Ordu - Horadrim - asutati salapäraste maagide grupi poolt, et \"\n\"jahtida ja vangistada Kolm Kurjust lõplikult.\\n\"\n\"\\n\"\n\"Algne Horadrim vangistas kaks Kolmest võimsatesse artefaktidesse, mida \"\n\"tuntakse Hingekividena, ja mattis need sügavale idapoolsete kõrbeliivade \"\n\"alla. Kolmas Kurjus pääses vangistusest ja põgenes läände, paljud Horadrimi \"\n\"liikmed jälitasid teda. Kolmas Kurjus - tuntud kui Diablo, Hirmu Isand - \"\n\"vangistati lõpuks, tema olemus pandi Hingekivisse ja maeti selle Labürindi \"\n\"sisse.\\n\"\n\"\\n\"\n\"Olge hoiatatud, et hingekivi tuleb hoida avastamise eest nende poolt, kes ei \"\n\"kuulu usku. Kui Diablo vabastataks, otsiks ta keha, mida on lihtne \"\n\"kontrollida, kuna ta oleks väga nõrk - võib-olla vana mehe või lapse oma.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Nii juhtuski, et Põrgus toimus suur revolutsioon, mida tunti kui Pimedat \"\n\"Pagendust. Väiksemad Kurjused kukutasid Kolm Peamist Kurjust ja pagendasid \"\n\"nende vaimuvormid surelikku maailma. Deemonid Belial (Valede Isand) ja \"\n\"Azmodan (Patu Isand) võitlesid, et nõuda Põrgu valitsemist Kolme Venna \"\n\"puudumise ajal. Kogu Põrgu polariseerus Beliali ja Azmodani fraktsioonide \"\n\"vahel, samal ajal kui Kõrgemate Taevaste jõud pidevalt ründasid Põrgu \"\n\"Väravaid.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Paljud deemonid rändasid surelikku maailma Kolme Venna otsinguil. Neid \"\n\"deemoneid jälitasid surelikku maailma Inglid, kes jahtisid neid läbi Idamaa \"\n\"avarate linnade. Inglid liitusid salapärase surelike maagide orduga, mida \"\n\"kutsuti Horadrimiks, kes said kiiresti osavaks deemonite jahtimisel. Nad \"\n\"tegid ka palju tumedaid vaenlasi allilmas.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Nii juhtuski, et Kolm Peamist Kurjust saadeti vaimudena surelikku maailma ja \"\n\"pärast aastakümneid kaose külvamist Idas, jälitas need needuse all olev \"\n\"surelike Horadrimi Ordu. Horadrimid kasutasid artefakte, mida kutsuti \"\n\"Hingekivideks, et vangistada Mephisto, Vihkamise Isanda, ja tema venna \"\n\"Baali, Hävingu Isanda, olemus. Noorem vend - Diablo, Hirmu Isand - põgenes \"\n\"läände.\\n\"\n\"\\n\"\n\"Lõpuks püüdsid Horadrimid ka Diablo Hingekivi sisse ja matsid ta iidse, \"\n\"unustatud katedraali alla. Seal magab Hirmu Isand ja ootab oma taassünni \"\n\"aega. Teadke, et ta otsib nooruse ja jõu kehastust, mida valitseda - kedagi, \"\n\"kes on süütu ja kergesti kontrollitav. Seejärel tõuseb ta, et vabastada oma \"\n\"Vennad ja taas õhutada Patuse Sõja leeke...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Kõik kiitused Diablole - Hirmu Isandale ja Pimeduse Pagenduse Ellujääjale. \"\n\"Kui ta ärkas oma pikast unest, rääkis minu Isand ja Meister mulle \"\n\"saladustest, mida vähesed surelikud teavad. Ta ütles mulle, et Kõrgemate \"\n\"Taevaste kuningriigid ja Põlevate Põrgude sügavused peavad igavest sõda. Ta \"\n\"paljastas jõud, mis on toonud selle lahkhelid inimeste valdustesse. Minu \"\n\"isand on nimetanud selle maailma ja kõigi siin elavate olendite lahingu \"\n\"Patuse Sõjaks.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Au ja kiitus Diablole - Hirmu isandale ja Kolme juhile. Minu isand rääkis \"\n\"mulle oma kahest vennast, Mephistost ja Baalist, kes pagendati siia maailma \"\n\"ammu aega tagasi. Minu isand soovib oodata oma aega ja kasutada oma võimsat \"\n\"jõudu, et vabastada oma vangistatud vennad nende hauakambritest idapoolsete \"\n\"liivade all. Kui minu isand vabastab oma vennad, tunneb Patuse sõda taas \"\n\"Kolme raevu.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Tervitus ja ohverdus Diablocle - Hirmu Isandale ja Hingede Hävitajale. Kui \"\n\"ma äratasin oma Meistri tema unest, püüdis ta võtta sureliku kuju. Diablo \"\n\"püüdis nõuda endale kuningas Leorici keha, kuid mu Meister oli oma \"\n\"vangistusest liiga nõrk. Mu Isand vajas lihtsat ja süütut ankrut sellesse \"\n\"maailma ning leidis, et poiss Albrecht sobib selleks ülesandeks ideaalselt. \"\n\"Kuigi hea kuningas Leoric jäi Diablo ebaõnnestunud valdamise tõttu hulluks, \"\n\"röövisin ma tema poja Albrechti ja tõin ta oma Meistri ette. Ma ootan nüüd \"\n\"Diablo kutset ja palvetan, et mind premeeritaks, kui ta lõpuks ilmub selle \"\n\"maailma Isandana.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Tänu taevale, et sa oled tagasi tulnud!\\n\"\n\"Palju on muutunud ajast, mil sa siin elasid, mu sõber. Kõik oli rahulik, \"\n\"kuni tumedad ratsanikud tulid ja hävitasid meie küla. Paljud langesid seal, \"\n\"kus nad seisid, ja need, kes relvad haarasid, tapeti või viidi minema, et \"\n\"saada orjadeks - või veel hullemaks. Linna servas asuv kirik on rüvetatud ja \"\n\"seda kasutatakse tumedate rituaalide jaoks. Öösiti kajavad karjed on \"\n\"ebainimlikud, kuid mõned meie linnaelanikest võivad veel ellu jääda. Järgi \"\n\"teed, mis asub minu kõrtsi ja sepa töökoja vahel, et leida kirik ja päästa, \"\n\"keda saad. \\n\"\n\" \\n\"\n\"Võib-olla saan sulle rohkem rääkida, kui me uuesti räägime. Edu.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Hoia oma ülesannet.  Kadunud aarde leidmine pole lihtne.  Peidetud aarde \"\n\"leidmine veelgi vähem.  Ma jätan sulle selle.  Ära lase aja liival su \"\n\"otsingut segada.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Mis asi?!  See on rumalus.  Tristramis pole mingit aaret maetud.  Lase ma \"\n\"vaatan seda!!  Ah, vaata, need joonised on ebatäpsed.  Need ei vasta üldse \"\n\"meie linnale.  Ma keskenduksin sellele, mis asub katedraali all, mitte \"\n\"sellele, mis asub meie pinnase all.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Mul pole tõesti aega arutada mingit kaarti, mida sa otsid. Mul on palju \"\n\"haigeid inimesi, kes vajavad minu abi ja ka sinu oma.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Kunagi uhke Iswall on lõksus sügaval selle maailma pinna all.  Tema au on \"\n\"röövitud ja välimus muudetud.  Ta on lõksus igaveses piinas.  Talle on \"\n\"pandud ülesandeks varjata seda, mis võiks teda vabastada.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Ma pakun, et Wirt nägi sind tulemas ja tegi näitemängu, et saaks hiljem sinu \"\n\"üle naerda, kui sa mööda linna ringi jooksed ja oma nina poris lohistad. Ma \"\n\"jätaks selle tähelepanuta.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Oli aeg, mil see linn oli kaugete ja lähedaste rändurite sagedane \"\n\"peatuspaik. Palju on sellest ajast muutunud. Kuid peidetud koopad ja maetud \"\n\"aarded on iga lapse tavalised fantaasiad. Wirt harva lubab endale \"\n\"nooruslikke mänge. Nii et see võib olla lihtsalt tema kujutlusvõime.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Kuule nüüd. Tule lähemale. Ma ei tea, kas sa tead, mida mina tean, aga sul \"\n\"on siin tõesti midagi erilist. See on kaart.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Mu vanaema räägib mulle tihti lugusid kummalistest jõududest, mis asustavad \"\n\"kiriku kõrval asuvat surnuaeda. Ja võib-olla huvitab sind kuulda ühte neist. \"\n\"Ta ütles, et kui jätad surnuaeda õige ohvrianni, sisened katedraali, et \"\n\"surnute eest palvetada, ja siis tagasi tuled, on ohvriand mingil kummalisel \"\n\"moel muutunud. Ma ei tea, kas see on lihtsalt vana haige naise jutt, aga \"\n\"tänapäeval tundub kõik võimalik.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Hmm.  Sa ütled, et seal on tohutu ja salapärane aare.  Mmm.  Võib-olla \"\n\"võiksin olla huvitatud mõne asja ostmisest sinult.  Või veel parem, kas sa \"\n\"ei vaja mõnda haruldast ja kallist varustust, et sellest katsumusest läbi \"\n\"saada?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Niisiis, sina oledki see kangelane, kellest kõik räägivad. Ehk saaksid \"\n\"aidata vaest, lihtsat talumeest kohutavast jamast välja? Minu viljapuuaia \"\n\"serval, siit lõuna pool, on maapinnast välja paisuv kohutav asi! Ma ei pääse \"\n\"oma põldudele ega heinapallide juurde ja mu vaesed lehmad jäävad nälga. Nõid \"\n\"andis mulle selle ja ütles, et see lööb selle asja mu põllult minema. Kui sa \"\n\"suudaksid selle hävitada, oleksin igavesti tänulik. Ma teeksin seda ise, aga \"\n\"keegi peab lehmade juures olema...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Ma teadsin, et see ei saanud olla nii lihtne, nagu see nõid seda kõlas. See \"\n\"on kurb maailm, kui sa ei saa isegi oma naabreid usaldada.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Kas see on läinud? Kas sa saatsid selle tagasi Hadese pimedatesse \"\n\"soppidesse, kust see pärit on? Mis sa tegid? Oh, ära ütle mulle, et sa \"\n\"kaotasid selle! Need asjad ei ole odavad, tead. Sa pead selle leidma ja siis \"\n\"selle õuduse meie linnast välja ajama.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Ma kuulsin plahvatust siit! Suur tänu teile, lahke võõras. Kõigi nende \"\n\"asjadega, mis maast välja tulevad, koletised kirikut üle võtmas ja nii \"\n\"edasi, on need rasked ajad. Ma olen vaid vaene talunik, aga siin -- võtke \"\n\"see minu suure tänuga.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Oh, selline mure mul on... võib-olla... Ei, ma ei saaks sulle seda peale \"\n\"suruda, arvestades kõiki teisi muresid. Võib-olla pärast seda, kui oled \"\n\"kiriku neist olenditest puhastanud, võiksid tagasi tulla... ja leida natuke \"\n\"aega, et aidata vaest talunikku?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Uuuuh! (nuusk) Uuuuh! (nuusk)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Ma kaotasin Theo! Ma kaotasin oma parima sõbra! Me mängisime jõe ääres ja \"\n\"Theo ütles, et tahab minna vaatama seda suurt rohelist asja. Ma ütlesin, et \"\n\"me ei peaks, aga me hiilisime sinna ja siis äkki tuli see PUTUKAS välja! Me \"\n\"jooksime minema, aga Theo kukkus maha ja putukas HAARAS ta ja viis ta minema!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Kas sa leidsid ta üles? Sa pead Theodore'i leidma, palun! Ta on alles väike. \"\n\"Ta ei saa enda eest hoolitseda! Palun!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Sa leidsid ta üles! Sa leidsid ta üles! Aitäh! Oh Theo, kas need vastikud \"\n\"putukad ehmatasid sind? Hei! Uhh! Midagi on su karvades kinni! Iu! Tule, \"\n\"Theo, lähme koju! Tänan veel kord, kangelane!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Oleme kaua uinunud ja aeg ärgata on käes. Pärast pikka und oleme täis suurt \"\n\"nälga. Varsti, nüüd, me toitume...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Kas oled end hästi tundnud, väike imetaja?  Kui hale. Sinu väike maailm ei \"\n\"paku üldse mingit väljakutset.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Need maad rüvetatakse ja meie järglased vallutavad põllud, mida inimesed \"\n\"koduks nimetavad. Meie kombitsad haaravad selle maailma ja me pidutseme \"\n\"selle elanike lihal. Inimene saab meie karjaks ja toiduks.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, ma tunnen su lõhna...sa oled lähedal! Lähedal! Ssss...vere ja hirmu \"\n\"lõhn...kui ahvatlev...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Ja Kuldse Valguse aastal määrati, et tuleb püstitada suur Katedraal. Selle \"\n\"püha paiga nurgakivi pidi olema tahutud läbipaistvast kivist Antyrael, mis \"\n\"sai nime Inglilt, kes jagas oma jõudu Horadrimiga.  \\n\"\n\"\\n\"\n\"Varjude Joonistamise aastal värises maa ja Katedraal purunes ning langes. \"\n\"Kui algas katakombide ja losside ehitamine ning inimene seisis Patuse Sõja \"\n\"hävituste vastu, otsiti varemetest kive. Ja nii juhtuski, et nurgakivi kadus \"\n\"inimeste silme alt.  \\n\"\n\"\\n\"\n\"Kivi oli sellest maailmast – ja kõigist maailmadest – nagu Valgus on nii \"\n\"kõiges sees kui ka kõigest väljaspool. Valgus ja ühtsus on selle püha aluse \"\n\"viljad, eesmärgi ühtsus ja omandi ühtsus.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Ammu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Ma ütlesin, Ammu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Kuule, ma olen lihtsalt lehm, eks?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Olgu, olgu. Ma ei ole tegelikult lehm. Ma ei käi tavaliselt niimoodi ringi; \"\n\"aga ma istusin kodus, oma asju ajades, ja äkki hakkasid põrandast välja \"\n\"tulema mingid putukad ja viinapuud ja sibulad ja muud asjad... see oli \"\n\"kohutav! Kui mul oleks midagi normaalset selga panna, ei oleks see nii hull. \"\n\"Hei! Kas sa saaksid minu juurde tagasi minna ja mu ülikonna tuua? Pruuni, \"\n\"mitte halli, see on õhtuseks kandmiseks. Ma teeksin seda ise, aga ma ei \"\n\"taha, et keegi mind niimoodi näeks. Siin, võta see, sul võib seda vaja \"\n\"minna... et tappa neid asju, mis on kõik üle kasvanud. Sa ei saa mu maja \"\n\"mööda vaadata, see on kohe jõe hargnemise lõuna pool... tead küll... see, \"\n\"millel on ülekasvanud köögiviljaaed.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Mida sa aega raiskad?  Mine too mu ülikond!  Ja kiirusta!  See Holstein seal \"\n\"pilgutab mulle silma!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hei, kas sul on mu ülikond seal? Kiiresti, anna see siia! Need kõrvad \"\n\"sügelevad nagu sa ei usukski!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Ei ei ei ei!  See on minu HALL ülikond!  See on õhtuseks kandmiseks!  \"\n\"Ametlikeks puhkudeks!  Ma ei saa SEDA kanda.  Mis sa oled, mingi imelik?  \"\n\"Mul on vaja PRUUNI ülikonda.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, see on PALJU parem.  Uhh!  Lõpuks ometi, natuke väärikust!  Kas mu \"\n\"sarved on sirged?  Hea.  Kuule, tänud, et mind aitasid.  Siin, võta see \"\n\"kingituseks; ja, tead... väike moenõuanne... sul võiks olla natuke... sul \"\n\"võiks olla uus... teadküllmismõtlen?  Kogu see seikleja stiil on lihtsalt \"\n\"nii... retro.  Lihtsalt väike nõuanne, eks?  Tšau.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Vaata.  Ma olen lehm.  Ja sina, sa oled koletise sööt. Saa natuke kogemusi \"\n\"juurde!  Siis räägime...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"See peab tõesti olema hirmuäratav ülesanne, mille olen teie ette seadnud. \"\n\"Kui oleks vaid mingi viis, kuidas ma saaksin... kas tassike kena, värsket \"\n\"piima aitaks?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Oh, ma võiksin su abi kasutada, aga võib-olla pärast seda, kui oled päästnud \"\n\"katakombid nende elajate rüvetamise eest.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Mul on vaja midagi ära teha, aga ma ei saa seda paluda täiesti võõralt \"\n\"inimeselt. Võib-olla, kui oled siin veidi aega olnud, tunnen end mugavamalt, \"\n\"et paluda teene.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Ma näen sinus suurt potentsiaali. Ehk saaksid sa oma saatust täites vahepeal \"\n\"peatuda ja mulle väikese teene teha?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Ma arvan, et sa võiksid mind aidata, aga võib-olla pärast seda, kui oled \"\n\"veidi võimsamaks saanud. Ma ei tahaks vigastada küla ainsat võimalust \"\n\"kirikus oleva ohu hävitamiseks!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Mina, ma olen iseenda tehtud lehm. Tee midagi endast, ja... siis räägime.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Ma ei pea end iga turisti ees õigustama, kes mööda jalutab! Kas sul pole \"\n\"mingeid koletisi, keda tappa? Võib-olla räägime hiljem. Kui sa ellu jääd...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Lõpeta mu tüütamine.  Ma otsin kedagi tõeliselt kangelaslikku.  Ja sina seda \"\n\"ei ole.  Ma ei saa sind usaldada, sa saad iga hetk koletiste poolt nahka \"\n\"pistetud... Mul on vaja kedagi, kes on kogenud kangelane.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Olgu, ma lõpetan jamamise. Ma ei tahtnud sind valesti juhatada. Istusin \"\n\"kodus, tundsin end meeleolus, kui asjad läksid tõeliselt ebastabiilseks; \"\n\"terve kari koletisi tuli põrandast välja! Ma lihtsalt ehmusin. Juhtus nii, \"\n\"et kandsin seda Jersey't, kui uksest välja jooksin, ja nüüd näen täiesti \"\n\"naeruväärne välja. Kui mul oleks midagi normaalset selga panna, poleks asi \"\n\"nii hull. Hei! Kas sa saaksid minu juurde tagasi minna ja mu ülikonna tuua? \"\n\"Selle pruuni, mitte halli, see on õhtuseks kandmiseks. Ma teeksin seda ise, \"\n\"aga ma ei taha, et keegi mind sellisena näeks. Siin, võta see, sul võib seda \"\n\"vaja minna... nende asjade tapmiseks, mis on kõik üle kasvanud. Sa ei saa mu \"\n\"maja mööda vaadata, see on kohe lõuna pool jõe hargnemiskohast... tead \"\n\"küll... see, millel on ülekasvanud köögiviljaaed.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Olen proovinud loitse, ähvardusi, tõrjumist ja kauplemist selle jälgi \"\n\"olendiga -- tulutult. Minu meetodid madalamate deemonite orjastamiseks ei \"\n\"näi selle hirmuäratava eluka puhul mõjuvat.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Mu kodu muutub aeglaselt selle soovimatu vangi kurjuse tõttu rikutuks.  \"\n\"Krüptid on täis varje, mis liiguvad just minu nägemise äärealadel.  Küüniste \"\n\"nõrk krabistamine tantsib minu kuulmise äärealadel. Nad otsivad, ma arvan, \"\n\"seda päevikut.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Oma raevus on olend oma nime välja öelnud -- Na-Krul.  Olen püüdnud selle \"\n\"nime kohta uurida, kuid väiksemad deemonid on kuidagi mu raamatukogu \"\n\"hävitanud.  Na-Krul... See nimi täidab mind külma hirmuga.  Ma eelistan \"\n\"mõelda sellest kui Olendist, mitte mõelda selle tõelisele nimele.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Lõksu jäänud olendi raevukad ulgumised ei lase mul hädavajalikku und saada. \"\n\"See möllab selle vastu, kes ta Tühjusesse saatis, ja sajatab mind, et ma ta \"\n\"siia lõksu püüdsin. Selle sõnad täidavad mu südame hirmuga, kuid ma ei suuda \"\n\"selle häält välja lülitada.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Mu aeg hakkab kiiresti otsa saama. Ma pean üles kirjutama viise, kuidas \"\n\"deemoni nõrgestada, ja seejärel selle teksti peitma, et tema käsilased ei \"\n\"leiaks viisi, kuidas minu teadmisi kasutada oma isanda vabastamiseks. \"\n\"Loodan, et see, kes selle päeviku leiab, otsib teadmisi.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Kes iganes selle kirjarulli leiab, on kohustatud peatama deemonliku olendi, \"\n\"kes peitub nende seinte vahel. Minu aeg on läbi. Isegi nüüd kraabivad tema \"\n\"põrgulikud käsilased habrast ust, mille taga ma peitun.  \\n\"\n\"\\n\"\n\"Olen deemoni halvanud arkaanilise maagiaga ja sulgenud ta suurte seinte \"\n\"vahele, kuid kardan, et sellest ei piisa. \\n\"\n\"\\n\"\n\"Minu kolme grimuaari loitsud annavad sulle kaitstud sissepääsu tema \"\n\"valdustesse, kuid ainult siis, kui neid õigesti järjestuses lausuda. \"\n\"Sissepääsu juures olevad kangid eemaldavad tõkked ja vabastavad deemoni; ära \"\n\"puutu neid! Kasuta ainult neid loitse, et pääseda sisse, vastasel juhul võib \"\n\"tema jõud olla sinu jaoks liiga suur, et teda võita.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Ettenähtud Puhkus.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Põrguseak\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Astel\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psühhoorb\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Arachnon\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Langetapja\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Horki järglane\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Mürgihäbelik\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Necromorb\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Ämbliklord\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Piitsuss\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Põletusants\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Põrgu Viga\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Hauakaevaja\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Hauarott\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Tuleleek\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Koljutiib\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lits\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Krüpti deemon\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Põrgulepatriinu\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Luudeemon\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Ülikõrts\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Bikloob\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Lihasasi\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Vikatimees\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Hiiglase Nukid\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Elavhõbedane sõrmus\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Xorine'i sõrmus\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Kariku sõrmus\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Magma sõrmus\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Müstikute sõrmus\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Äikese sõrmus\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Võluväe amulett\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Sääse nõel\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Flambeau\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Hämaruse turvis\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Blitzen\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Äikeselöök\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Hingede Neelaja\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Teemanttera\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Luukettsoomusrüü\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Demon Plate'i turvis\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Akolüüdi Amulett\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Gladiaatori sõrmus\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Narride\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Kristalne\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Doppelgängeri\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"häving\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"mädanik\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"oht\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Magi\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Narr\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Välgusein\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Enesesüttimine\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Väänamine\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Peegelda\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Berserk\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Tulerõnga\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Otsi\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Tuleruuna\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Valguse ruun\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Nova ruun\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Immolatsiooni ruun\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Kivi ruun\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Vähenda gamma\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Suurenda gamma\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Alusta linnas uuesti\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Kas üritad põrandale eset panna?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Jõud ootavad vertikaalset sünkroonimist. Takistab rebenemise efekti \"\n#~ \"kaadri joonistamisel. Selle keelamine võib mõnel süsteemil aidata hiire \"\n#~ \"viivitusega.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"KPS piiraja\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Kuvade sagedus on piiratud, et vältida suurt protsessori koormust. \"\n#~ \"Piirang arvestab värskendussagedust.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Tabamine\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Süda\"\n"
  },
  {
    "path": "Translations/fi.po",
    "content": "#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:22+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: fi_FI\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.8\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: ;_;N_;ngettext:1,2;pgettext:1c,2;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Pelisuunnitelu\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Kokeneet suunnittelijat\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Lisäsuunnitelu\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Pääohjelmoija\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Kokenneet ohjelmoijat\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Ohjelmointi\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Vierasohjelmointi\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net Ohjelmointi\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Sarjaliikenneohjelmointi\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Asennusohjelman ohjelmointi\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Taideohjaajat\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Taide\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Tekninen kuvitus\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Elokuvalliset taidejohtajat\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D-elokuvallinen kuvitus\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Elokuvallinen tekninen kuvitus\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Vastaava tuottaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Tuottaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Tuotantoavustaja\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Musiikki\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Äänisuunnitelu\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Elokuvallinen Musiikki & Ääni\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Äänituotanto, Ohjaus & Roolijako\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Käsikirjoitus & Tarina\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Äänimuokkaus\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Äänet\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Äänittäjä\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Ohjekirjan suunnittelu & Taitto\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Ohjekirjan kuvitus\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Väliaikainen laadunvarmistaja (päätestaaja)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA Iskuryhmä (Testaajat)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA Erikoisjoukko (Yhteensopivuustestaajat)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA Tykistötuki (Lisätestaajat) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA Vastatiedustelu\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Verkkopalvelujen osasto\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Asiakastuki\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Liikevaihto\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Hyödytön ja paska työntekijä\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Herra Dabirin taustalaulajat\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Viestintä\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Markkinointi\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Kansainvälinen liikevaihto\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Yhdysvailtain liikevaihto\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Valmistus\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Lakiasiat ja Liiketoiminta\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Erityiskiitokset\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Kiitokset\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Muistolle\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Erityis Erityiskiitokset\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Toimitusjohtaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Ohjelmistoinsinööri\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Taidejohtaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Taiteilija\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Suunnitelu\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Ääni suunnittelu, SFX & Äänitekniikka\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Laadunvastaava\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testaajat\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Ohjekirja\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tLisätyö\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Tehtävä tekstien kirjoitus\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Kiitokset\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tErityiskiitokset Blizzard Entertainment:ille\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Laadunvastaava\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Laadunvastaavan johtava testaaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Pää testaajat\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Lisä testaajat\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Tuotemarkkinointivastaava\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Julkisen viestinnän vastaava\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Tuotevastaava\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Tuhannen Sormus\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tYhtään sielua ei myyty pelin tekemisen aikana.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Valitse Luokka\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Peruuta\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Uusi Moninpeli Hahmo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Uusi Yksinpeli Hahmo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Tallennustiedosto on olemassa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Lataa peli\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Uusi peli\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Yksinpeli hahmot\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Rosvo ja Velho ovat saatavilla vain Diablon kokoversiossa. Vieraile sivulla \"\n\"https://www.gog.com/game/diablo ostaaksesi pelin.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Syötä nimi\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Kelvoton nimi. Nimi ei saa sisältää välilyöntejä, varattuja kirjamia, tai \"\n\"varattuja sanoja.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Hahmoa ei voitu luoda.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Taso:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Vahvuus:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magia:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Näppäryys:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Puhti:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Tallenna peli:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Valitse hahmo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Uusi hahmo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Poista\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Moninpeli hahmot\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Poista moninpeli hahmo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Poista yksinpeli hahmo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Oletko varma, että haluat poistaa hahmon\\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Yksinpeli\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Moninpeli\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Asetukset\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Tuki\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Tekijätiedot\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Poistu Hellfirestä\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Poistu Diablosta\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Osuusohjelma\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Client-Palvelin (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Offline-Tilassa\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Moninpeli\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Vaatimukset:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"porttia ei tarvita\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Valitse Yhteys\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Vaihda portti\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Kaikki tietokoneet tulee olla kytkettynä TCP-yhteensopivaan verkkoon.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Kaikki tietokoneet tulee olla kytkettynä verkkoon.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Pelaa itseksesi ilman verkon alttiuksia.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Pelaajamäärä: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo:n Osuusohjelma\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire:n Osuusohjelma\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Pitäjä pyörittää eri peliä kuin sinä.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Pitäjä pyörittää eri pelimuotoa ({:s}) kuin sinä.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Sinun versiosi {:s} ei täsmää pitäjän {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Kuvaus:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Valitse toiminto\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Luo Peli\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Luo Julkinen Peli\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Liity Peliin\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Julkiset Pelit\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Ladataan...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Ei mitään\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"PERUUTA\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Luo uusi peli valitsemallasi vaikeusasteella.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Luo uusi julkinen peli valitsemallasi vaikeusasteella johon kuka tahansa voi \"\n\"liittyä.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Syötä pelin tunnus liittyäksesi peliin joka on jo menossa.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Syötä tunnus tai pitäjänimi liittyäksesi peliin joka on jo menossa.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Liity julkiseen peliin joka on jo menossa.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Tavallinen\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Hornankattila\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Helvetin vaikea\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Vaikeus: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Nopeus: Tavallinen\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Nopeus: Nopea\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Nopeus: Nopeampi\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Nopeus: Nopein\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Pelaajat: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Valitse Vaikeusaste\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Liity {:s} Peleihin\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Syötä Pelin ID\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Syötä Osoite\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Tavallinen Vaikeusaste\\n\"\n\"Tässä kohtaa luodun hahmon pitäisi aloittaa tehtävän jossa Diablo on \"\n\"päihittettävä.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Hornankattila vaikeustaso\\n\"\n\"Labyrintin asukkaat ovat vahvistuneet ja tulevat olemaan entistä suurempi \"\n\"haaste. Tämä on suositeltavaa vain kokeneille hahmoille.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"\\\"Helvetin vaikea\\\" Vaikeustaso\\n\"\n\".\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Hahmosi tulee saavuttaa taso 20 ennen kuin voit liittyä \\\"hornankattila\\\" \"\n\"vaikeustasolla olevaan moninpeliin.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Hahmosi tulee saavuttaa taso 30 ennen kuin voit liittyä \\\"Helvetin vaikea\\\" \"\n\"vaikeustasolla olevaan moninpeliin.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Valitse pelin nopeus\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Nopea\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Nopeampi\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Nopein\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Tavallinen nopeus\\n\"\n\"Tässä kohtaa luodun hahmon pitäisi aloittaa tehtävän, jossa Diablo on \"\n\"päihittettävä.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Nopea nopeus\\n\"\n\"Labyrintin asukkaat ovat nostaneet vauhtiaan ja osoittautuvat entistä \"\n\"suuremmaksi haasteeksi. Tämä on suositeltavaa vain kokeneille hahmoille.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Nopeampi nopeus\\n\"\n\"Useimmat luolaston hirviöt löytävät sinut nopeammin kuin koskaan ennen. Vain \"\n\"kokenut mestari voi kokeilla onneaan tällä nopeudella.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Nopein nopeus\\n\"\n\"Alamaailman kätyrit ryntäävät hyökkäämään epäröimättä. Vain todellinen \"\n\"nopeuden rakastaja voi astua sisään tällä vauhdilla.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Syötä salasana\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Astu Hellfire:en\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Vaihda Diablo:n\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Kyllä\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Ei\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Paina peliohjaimen painikkeita vaihtaaksesi.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Sidottu näppäin:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Paina mitä tahansa näppäintä vaihtaaksesi.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Irrota näppäin\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Sidottu painikeyhdistelmä:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Irrota painikeyhdistelmä\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Edellinen valikko\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Ylläpidämme chat-palvelinta osoitteessa Discord.gg/devilutionx. Seuraa \"\n\"linkkejä liittyäksesi yhteisöömme, jossa keskustelemme Diabloon ja Hellfire-\"\n\"laajennukseen liittyvistä asioista.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX on Diasurgical:in ylläpitämä, ongelmat ja viat voi ilmoittaa \"\n\"tähän osoitteseen: https://github.com/diasurgical/devilutionX.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Tiedoite:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX ei ole Blizzard Entertainment:in tai GOG.com:n tukema. \"\n\"Blizzard Entertainment tai GOG.com ei ole testannut eikä varmentanut \"\n\"DevilutionX:n laatua tai yhteensopivuutta. Kaikki tiedustelut liittyen \"\n\"DevilutionX:n pitäisi suunnata Diasurgical:ille, ei Blizzard \"\n\"Entertainment:ille taikka GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tTämä portti käyttää Charis SIL-, New Athena Unicode-, Unifont- ja Noto-\"\n\"fontteja, jotka ovat SIL Open Font -lisenssin alaisia, sekä Twitmoji-\"\n\"fonttia, joka on CC-BY 4.0 -lisenssin alainen. Portti käyttää myös SDL:ää, \"\n\"joka on zlib-lisenssin alainen. Katso lisätietoja ReadMe-tiedostosta.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Tekijänoikeus © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Virhe\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Virhe ilmentyi: {:s} rivillä {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Datatiedosto virhe\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Päätietokantaa ({:s}) ei voi avata.\\n\"\n\"\\n\"\n\"Varmista, että se on pelikansiossa.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Vain luku -hakemistovirhe\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Kirjoittaminen sijaintiin ei onnistu:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Peli: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Offline Peli\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Salasana: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Julkinen Peli\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Taso: Pesä {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Taso: Hautaholvi {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Kylä\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Taso: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Hahmo tiedot\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Tehtävälista\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Autokartta\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Päävalikko\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Tavaraluettelo\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Loitsukirja\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Lähetä viesti\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Saatavilla olevat komennot:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Komento \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" on tuntematon.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Kuvaus: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parametrit: Lisäparametrejä ei tarvita.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parametrit: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Areenat ovat tuettuja vain moninpelissa.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Millä areenalla haluat käydä?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Virheellinen areena numero. Sallitut numerot ovat:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\"Astuaksesi areenalle, sinun täytyy olla kylässä tai toisella areenalla.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Tarkastelu on tuettu vain moninpelissa.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Pelaajien tarkastaminen on lopetettu.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Pelaajia tällä nimellä ei löytynyt\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Tarkasteleva pelaaja: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Printtaukset auttavat yleiskatsauksessa tai tietyn komennon käytössä.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[komento]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Astu Pvp areenalle.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<areena numero>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Antaa areenajuomaa.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<numero>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Tarkastaa toisen pelaajan tilastot ja varusteet.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<pelaajan nimi>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Näytä nykyisen tason siemenetiedot.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Pelaajaystävällinen\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Pelaajan hyökkäys\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Pikanäppäin: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Valitse nykyinen loitsu -näppäin\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Pikanäppäin: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Taito\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Loitsu\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Loitsutaso 0 - Käyttökelvoton\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Loitsutaso {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"{:s} Käärö\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Käärö\"\nmsgstr[1] \"{:d} Kääröt\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"{:s} Sauva\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Lataus\"\nmsgstr[1] \"{:d} Lataukset\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} kulta\"\nmsgstr[1] \"{:s} kullat\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Vaatimukset eivät täsmää\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Taso: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Vahinkopisteet {:d} of {:d}\"\n\n#: Source/control.cpp:1525\nmsgid \"Right click to inspect\"\nmsgstr \"Paina hiiren oikeaa näppäintä tarkastellaksesi\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Uusi taso\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"Sinä kuolit\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"ESC\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"Valikko näppäin\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"Paina {} lataaksesi viimeisin tallennus.\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"Paina {} palataksesi päävalikkoon.\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"Paina {} aloittaaksesi uudestaan kylästä.\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Sinulla on {:s} kultaa. Kuinka monta haluat jättää pois?\"\nmsgstr[1] \"Sinulla on {:s} kultaa. Kuinka monta haluat jättää pois?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Kylän portaali\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"käyttäjältä {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portaali\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Epäpyhyydyen Alttari\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"taso 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Tiedostoa ei voitu ladata {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} on puutteellinen, tarkista tiedoston sisältö.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"Tiedostossasi {0} ei ole odotettuja sarakkeita. Varmista, että se vastaa \"\n\"dokumentoitua muotoa.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Ei-numeerinen arvo {0} kohdassa {1} rivillä {2} sarakkeessa {3} ja \"\n\"sarakkeessa {4}\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Arvo {0} on alueen ulkopuolella kohdassa {1} rivillä {2} sarakkeessa {3} ja \"\n\"sarakkeessa {4}\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Virheellinen arvo {0} kohdassa {1} rivillä {2} sarakkeessa {3} ja \"\n\"sarakkeessa {4}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Printtaa tämä viesti ja poistu\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Printtaa versio ja poistu\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Määritä diabdat.mpq-tiedoston kansio\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Määritä tallennustiedostojen kansio\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Määritä diablo.ini-tiedoston sijainti\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Määritä kielikoodi (esim. en tai pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Ohita käynnistysvideot\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Näytä kuvataajuus\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Ota käyttöön yksityiskohtainen lokitallennus\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"Kirjaa tiedostoon stderr:n sijaan\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Nauhoita demo tiedosto\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Pyöritä demo tiedosto\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Poista kaikki\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Peli Valinta:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Pakota Osuusmoodi\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Pakota Diablo:n moodi\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Pakota Hellfire:n moodi\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Hellfire:n asetukset:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"\"\n\"Ilmoita vioista osoitteessa https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"Päivitä devilutionx.mpq ja fonts.mpq viimeisimpään versioon\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"UI-resurssien lataaminen epäonnistui.\\n\"\n\"\\n\"\n\"Varmista, että devilutionx.mpq on pelikansiossa ja että se on ajan tasalla.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Päivitä fonts.mpq viimeisimpään versioon\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Verkkoyhteyden aikakatkaisu --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Odotetaan pelaajia --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Apua ei saatavilla\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"kaupassa\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Vyö esine {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Käytä vyöesinettä.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Pikaloitsu {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Pikanäppäin taidolle tai loitsulle.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Edellinen pikaloitsu\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Valitsee edellisen pikaloitsun (vaihtelee).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Seuraava pikaloitsu\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Valitsee seuraavan pikaloitsun (vaihtelee).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Käytä parannusjuoma\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Käytä parannusjuomia vyöltä.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Käytä manapullo\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Käytä manapulloja vyöltä.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Pikapäiväkirja\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Avaa pikapäiväkirja.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Pikatallennus\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Tallentaa pelin.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Pikalataus\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Lataa pelin.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Poistu pelistä\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Sulkee pelin.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Pysäytä hahmo\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Lopeta kävely ja peruuta odottavat toimet.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Tavaran korostus\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Näytä/piilota tavarat maassa.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Kytke tavaran korostus päälle\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Pysyvästi näytä/piilota tavarat maassa.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Vaihda automaattinen kartta päälle\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Vaihtaa automaattisen kartan näyttämisen.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Syklaa kartan tyyppi\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Läpinäkymätön -> Läpinäkyvä -> Minikartta -> Ei mitään\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Avaa tavaraluettelo.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Hahmo\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Avaa hahmoruutu.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"Ryhmä\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"Avaa ryhmän sivupaneeli.\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Tehtävälista\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Avaa tehtävälista.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Loitsukirja\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Avaa Loitsukirja.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Pikaviesti {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Käytä pikaviestiä chatissä.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Piilota tietoikkunat\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Piilota kaikki tietoikkunat.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Tarkenna\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Tarkenna peliruutua.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Keskeytä Peli\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Pysäyttää pelin.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pysäytä Peli (Vaihtoehtoinen)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\nmsgid \"Decrease Brightness\"\nmsgstr \"Laske kirkautta\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Laske ruudun kirkautta.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\nmsgid \"Increase Brightness\"\nmsgstr \"Nosta kirkkautta\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Nosta näytön kirkautta.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Apu\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Avaa apu ruutu.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Näyttökuva\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Ottaa näyttökuvan.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Pelintiedot\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Näytä pelin tiedot.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Chat loki\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Näyttää chat-lokin.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Järjestä tavaraluettelo\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Järjestää tavaraluettelon.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Konsoli\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Avaa lua konsolin.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Ensisijainen toiminta\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Hyökkää hirviöitä vastaan, keskustele kaupunkilaisten kanssa, nosta ja \"\n\"sijoita esineitä.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Toissijainen toiminta\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Avaa arkkuja, avaa ovia, poimi esineitä.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Loitsun toiminta\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Käytä aktiivista loitsua.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Peruuta toiminto\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Sulje valikot.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Liiku ylös\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Siirtää pelaajahahmoa ylöspäin.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Liiku alas\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Moves the player character down.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Liiku vasemalle\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Moves the player character left.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Liiku oikealle\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Siirtää pelaajahahmoa oikealle.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Pysy paikallasi\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Pidä painettuna estääksesi pelaajaa liikkumasta.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Kytke pysyminen paikallaan\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Kytke pelaajan liikkuminen päälle tai pois.\"\n\n#: Source/diablo.cpp:2310\nmsgid \"Automap Move Up\"\nmsgstr \"Automaattikartan siirto ylös\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"Siirtää automaattikartan ylöspäin, kun se on aktiivinen.\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"Automaattikartan siirto alas\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"Siirtää automaattikartan alas, kun se on aktiivinen.\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"Automaattikartan siirto vasemalle\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Siirtää automaattikarttaa vasemmalle, kun se on aktiivinen.\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"Automaattikartan siiro oikealle\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"Siirtää automaattikarttaa oikealle, kun se on aktiivinen.\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Siirrä hiirtä ylöspäin\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Simuloi hiiren liikettä ylöspäin.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Siirrä hiirtä alaspäin\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Simuloi hiiren liikettä alaspäin.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Siirrä hiirtä vasemmalle\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Simuloi hiiren liikettä vasemmalle.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Siirrä hiirtä oikealle\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Simuloi hiiren liikettä oikealle.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Vasen hiiren painike\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Simuloi hiiren vasenta painiketta.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Oikea hiiren painike\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Simuloi hiiren oikeaa painiketta.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Ohjainasettelun pikavalikko\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Pidä painettuna asettaaksesi tai käyttääksesi loitsujen pikanäppäimiä.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Ohjainasettelu-valikon navigaattori\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Pidä painettuna päästäksesi ohjainasettelu valikkoon.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Kytke pelivalikko\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Avaa pelivalikon.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Peli talennettu\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Demossa ei ole moninpelitoimintoja\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Direct äänen luominen epäonnistui\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Ei saatavana osuusohjelma-versiona\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Tallennustilaa ei ole riittävästi\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Ei keskeytystä kylässä\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Kopiointi kiintolevylle on suositeltavaa\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Moninpelin synkronointiongelma\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Ei keskeytystä moninpelissä\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Tallennetaan...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Jotkut heikkenevät, kun toinen vahvistuu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Uusi voima syntyy tuhon kautta\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Ne, jotka puolustavat, hyökkäävät harvoin\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Oikeuden miekka on nopea ja terävä\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Kun henki on valpas, keho kukoistaa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Manavoimat uudistuvat\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Aika ei voi heikentää teräksen voimaa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Taikuus ei aina ole sitä, miltä se näyttää\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Se, mikä kerran oli avoinna, on nyt suljettu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Intensiteetti tulee viisauden kustannuksella\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Arkanen voima tuo tuhoa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Sitä, mitä ei voi pitää, ei voi vahingoittaa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Karmiininpunainen ja Taivaansininen muuttuvat auringoksi\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Tieto ja viisaus itsensä kustannuksella\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Juo ja virkisty\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Minne ikinä menetkin, siellä sinä olet\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Energia tulee viisauden kustannuksella\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Rikkaudet ovat runsaat, kun niitä vähiten odottaa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Kun ahneus epäonnistuu, kärsivällisyys palkitaan\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Hyväsydämisen seuralaisen! siunaama!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Miesten kädet olkoon kohtalon ohjaamia\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Voima vahvistuu taivaallisella uskolla\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Elämän ydin virtaa sisältäpäin\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Ylhäältä katsottuna tie on selvä\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Pelastus tulee viisauden hinnalla\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Mysteerit paljastuvat järjen valossa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Viimeiset voivat vielä olla ensimmäisiä\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Anteliaisuus tuo mukanaan omat palkintonsa\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Sinun täytyy olla vähintään tasolla 8 käyttääksesi tätä.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Sinun täytyy olla vähintään tasolla 13 käyttääksesi tätä.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Sinun täytyy olla vähintään tasolla 17 käyttääksesi tätä.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Salaperäinen tieto hankittu!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Se, mikä ei tapa sinua...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Tieto on voima.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Anna, niin sinulle annetaan.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Jotkut kokemukset hankitaan kosketuksen kautta.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Koti on paras paikka.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Henkinen energia on palautettu.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Tunnet olosi ketterämmäksi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Tunnet itsesi voimakkaammaksi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Tunnet itsesi viisammaksi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Tunnet olosi virkistyneeksi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Se, mikä voi rikkoutua, rikkoutuu.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedraali\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Katakombit\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Kaivokset\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Pesä\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Hautaholvi\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Tas {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} vaikeustaso\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Valikossa\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"silmukka\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Ei voitu yhdistää\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"virhe: luettu 0 tavua palvelimelta\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\"Tiedoston avaaminen epäonnistui:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"MPQ-tiedosto(t) saattaa olla vioittunut. Tarkista tiedoston eheys.\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq tai spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Jotkut Hellfire MPQ:t puuttuvat\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Kaikkia Hellfire MPQ-tiedostoja ei löytynyt.\\n\"\n\"Kopioi kaikki hf*.mpq-tiedostot.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Resoluutio\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Kylässä juoksu\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Theo tehtävä\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Lehmä tehtävä\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Automaattinen kullan kerääminen\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Automaattinen eliksiirin kerääminen\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Automaattinen öljyn kerääminen\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Automaattinen nosto kylässä\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria palauttaa manan\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Automaattinen aseiden käyttöönotto\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Automaattinen haarniskan käyttöönotto\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Automaattinen kypärien käyttöönotto\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Automaattinen kilpien käyttöönotto\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Automaattinen korujen kerääminen\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Satunnaista tehtävät\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Näytä tavaran tunnisteet\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Automaattinen vyön täyttö\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Poista käytöstä lamauttavat pyhäköt\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Parantavan juoman kerääminen\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Täydellisten parantavien juomien kerääminen\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Mana-juoman kerääminen\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Täydellisen mana juoman kerääminen\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Nuorentavan juoman kerääminen\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Täydellisen nuorentavan kerääminen\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Asetukset\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Tallenna Peli\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\nmsgid \"Exit to Main Menu\"\nmsgstr \"Poistu Päävalikkoon\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Postu Pelistä\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Nopeus\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Musiikki pois\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Ääni\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Äänet pois\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Keskeytä\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Näppäimistön pikakuvakkeet:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Avaa apuruutu\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Näytä Päävalikko\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Näytä autokartta\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Piilota kaikki tietoikkunat\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Avaa nopeuskirja\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Avaa loitsukirja\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Avaa tavaraluetteloruutu\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Avaa hahmoruutu\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Avaa tehtävälista\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Laske näytön kirkautta\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Nosta näytön kirkautta\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Zoomaa Peliruutua\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Zoomaa Autokarttaa\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Käytä vyö esinettä\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Aseta pikanäppäin taidolle tai loitsulle\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Hiiren vasen: Hyökkää liikumatta\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"Shift + Hiiren vasen: (hahmo näytöllä): Määritä kaikki tilasto-pisteet\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Hiiren vasen: (tavaraluettelossa): Siirrä esine vyöhön tai varusta/\"\n\"poista varuste\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Hiiren vasen: (vyöllä): Siirra tavara tavaraluetteloon\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Liikkuminen:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Jos pidät hiiren painikkeen painettuna liikkuessasi, hahmo jatkaa \"\n\"liikkumistaan kyseiseen suuntaan.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Taistelu:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Pitämällä shift-näppäintä painettuna ja napsauttamalla hiiren vasemmalla \"\n\"painikkeella hahmo voi hyökätä liikkumatta.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Automaattikartta:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Voit avata automaattikartan napsauttamalla tietopalkin MAP-painiketta tai \"\n\"painamalla näppäimistön TAB-näppäintä. Karttaa voi suurentaa ja pienentää + \"\n\"ja - näppäimillä. Karttaa voi vierittää nuolinäppäimillä.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Tavaroiden nostaminen:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Pienikokoiset käyttökelpoiset esineet, kuten juomat tai kääröt, sijoitetaan \"\n\"automaattisesti käyttöliittymän palkin yläosassa olevaan ”vyöhön”. Kun esine \"\n\"sijoitetaan vyöhön, kyseiseen ruutuun ilmestyy pieni numero. Esineitä voi \"\n\"käyttää joko painamalla vastaavaa numeroa tai napsauttamalla esinettä hiiren \"\n\"oikealla painikkeella.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Kulta:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Voit valita pudotettavan kullan määrän napsauttamalla hiiren oikealla \"\n\"painikkeella kullan kasaa inventaarissasi.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Taidot ja loitsut:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Voit tarkastella taitojesi ja loitsujesi luetteloa napsauttamalla hiiren \"\n\"vasemmalla painikkeella käyttöliittymän palkissa olevaa SPELLS-painiketta. \"\n\"Tähän luetteloon on koottu muistamasi loitsut ja sauvojen avulla \"\n\"käytettävissä olevat loitsut. Valitse loitsu, jonka haluat käyttää, \"\n\"napsauttamalla sitä hiiren vasemmalla painikkeella. Valitsemasi loitsu \"\n\"voidaan käyttää napsauttamalla hiiren oikealla painikkeella pelialueella.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Speedbookin käyttö loitsujen kanssa:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Valmistellun loitsun painiketta vasemmalla hiiren painikkeella \"\n\"napsauttamalla avautuu Speedbook, josta voit valita taidon tai loitsun \"\n\"välittömään käyttöön. Valmistellun taidon tai loitsun käytät napsauttamalla \"\n\"hiiren oikealla painikkeella pääpelialueella.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + vasen hiiren painike ”valitse nykyinen loitsu” -painikkeella \"\n\"tyhjentää valmiina olevan loitsun.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Loitsujen pikanäppäinten asettaminen:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Voit määrittää enintään neljä pikanäppäintä taitoja, loitsuja tai kääröjä \"\n\"varten. Aloita avaamalla ”speedbook” edellä olevassa osiossa kuvatulla \"\n\"tavalla. Korosta haluamasi loitsu ja paina sitten F5-, F6-, F7- tai F8-\"\n\"näppäintä.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Loitsukirjat:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Useamman kuin yhden kirjan lukeminen lisää tietämystäsi kyseisestä \"\n\"loitsusta, jolloin voit käyttää loitsua tehokkaammin.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Osuusohjelma Hellfire -ohje\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Hellfire apu\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Osuusohjelma Diablo apu\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Diablo apu\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Paina ESC-näppäintä lopettaaksesi tai nuolinäppäimiä selataksesi.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Pääikkunaa ei voi luoda\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Ei tilaa tavaralle\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Tarkkuuden öljy\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Mestaruuden öljy\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Terävyyden öljy\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Kuoleman öljy\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Taidon öljy\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Seppäöljy\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Sinnikkyyden öljy\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Pysyvyyden öljy\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Kovettumisen öljy\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Läpäisemättömyyden öljy\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0}  {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1}  {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1}  {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0}  {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"nostaa aseen\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"osumistodennäkoisyyttä\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"lisää huomattavasti\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"aseen osumistodennäköisyys\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"vahingon mahdollisuus\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"lisää huomattavasti aseen\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"vahinkopotentiaalia - ei jousia\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"vähentää tarvittavia ominaisuuksia\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"käyttääksesi haarniskaa tai aseita\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"palauttaa 20 %\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"tavaran kestävyyttä\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"nostaa tavaran\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"nykyinen ja maksimaalinen kestävyys\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"tekee esineestä tuhoutumattoman\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"lisää haarniskaluokkaa\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"haarniskoiden ja kilpien\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"lisää huomattavasti suojausta\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"haarniska- ja kilpiluokka\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"asettaa tuliansan\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"asentaa salamansyötin\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"asettaa kivettymisansan\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"palauta terveys kokonaan\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"palauta osa terveydestä\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"palauta osa manasta\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"palauta mana kokonaan\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"lisää vahvuutta\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"lisää magiaa\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"lisää näppäryyttä\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"lisää puhtia\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"palauta osa terveydestä ja manasta\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"palauta terveys ja mana kokonaan\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(toimii vain areenoilla)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Paina hiiren oikeaa tarkastellaksesi\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Paina hiiren oikeaa käyttääksesi\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Paina hiiren oikeaa lukeaksei ja sitten\\n\"\n\"paina hiiren vasempaa kohdistaaksesi\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Paina hiiren oikeaa lukeaksesi\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Aktivoi tarkastellaksesi\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Avaa tavaraluettelo käyttääksesi tätä\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Aktivoi käyttääksesi\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Valitse loitsukirjasta, sitten\\n\"\n\"käytä luettua loitsua\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Aktivoi lukeaksesi\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} tarkastellaksesi\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} käyttääksesi\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Valitse loitsukirjasta,\\n\"\n\"sitten paina {} käyttääksesi luettua loitsua\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} lukeaksesi\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Taso: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Kaksinkertaistaa kullankapasiteetin\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Vaaditaan:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Vah\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Näp\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"{:s} kirja\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s} korva\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"osumismahdollisuus: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% vahinko\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"osumistodennäköisyys: {:+d}%, {:+d}% vahinko\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% suojaus\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"haarniskaluokka: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Tulenkestävyys: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Tulenkestävyys: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Salaman kestävyys: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Salaman kestävyys: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Magiankestävyys: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Magiankestävyys: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Vastusta kaikkea: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Vastusta kaikkea: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"loitsujen tasoa on nostettu {:d} verran\"\nmsgstr[1] \"loitsujen tasoja on nostettu {:d} verran\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"loitsujen taso on alennettu {:d} verran\"\nmsgstr[1] \"loitsujen tasoja on alennettu {:d} verran\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"loitsujen tasot ovat muuttumattomat (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Lisälataukset\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} lataus\"\nmsgstr[1] \"{:d} {:s} lataukset\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Palovauriot: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Palovauriot: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Salamaniskuvahinko: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Salamaniskuvahinko: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} vahvuuteen\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} magiaan\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} näppäryyteen\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} puhtiin\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} kaikkiin ominaisuuksiin\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} saatu vahinko vihollisilta\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Vahinkopisteet: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"kova kestävyys\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"vähennetty kestävyys\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"tuhoutumaton\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% valon etäisyys\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% valon etäisyys\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"useita nuolia per laukaus\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"tulinuolien vahinko: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"tulinuolien vahinko: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"salamanuolien vahinko {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"salamanuolien vahinko {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"palopallon vahinko: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"tulipallon vahinko: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"hyökkääjä ottaa vastaan 1-3 vahinkopistettä\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"käyttäjä menettää kaiken manan\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"imee puolet ansan aiheuttamasta vahingosta\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"lyö kohteen taaksepäin\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% Vahinkoa\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Kaikki vastukset ovat 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"osuma varastaa 3% lisää manaa\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"osuma varastaa 5% lisää manaa\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"osuma varastaa 3% lisää terveyttä\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"osuma varastaa 5% lisää terveyttä\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"lävistää kohteen panssarin\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"pikahyökkäys\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"nopea hyökkäys\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"nopeampi hyökkäys\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"nopein hyökkäys\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Toinen kyky (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"nopea palautuminen\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"nopeampi palautuminen\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"nopein palautuminen\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"nopea torjunta\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"lisää {:d} pisteen vahinkoon\"\nmsgstr[1] \"lisää {:d} pisteitä vahinkoon\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"ampuu satunnaisia nopeusnuolia\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"epätavallinen vahinko\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"muuttunut kestävyys\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"yksikätinen miekka\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"menetä jatkuvasti vahinkopisteitä\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"terveyden riisto\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"ei vahvuus vaatimuksia\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"salamointivahinko: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"salamointivahinko: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"ladatut vasamat osumishetkellä\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"satunnainen kolminkertaisettu vahinko\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"rappeutuminen {:+d}% vahinko\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x vahinko hirviölle, 1x sinulle\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Satunnainen 0–600 % vahinko\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"heikko kes, {:+d}% vahinko\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"ylimääräinen AC vs demonit\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"ylimääräinen AC vs. epäkuolleet\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Manasta siiretty Terveyteen\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Terveydestä siiretty Manaan\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"vahinko: {:d}  Tuhoutumaton\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"vahinko: {:d}  Kes: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"vahinko: {:d}-{:d}  Tuhoutumaton\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"vahinko: {:d}-{:d}  Kes: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"suojaus: {:d}  Tuhoutumaton\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"suojaus:{:d} Kes: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Lataukset: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"uniikki tavara\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Ei tunnistettu\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Luurankokuninkaan leiri\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Luun kammio\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labyrintti\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Myrkytetty vesilähde\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Arkkipiispa Lazaruksen leiri\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Kirkon areena\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Helvetin Areena\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Elämänkaaren areena\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Tyrmään\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Katakombit\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Kaivokset\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Helvetti\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Pesään\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Hautaholviin\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Tasolle {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Kylään\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Tasolle {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Diablon luokse\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Pesän tasolle {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Hautaholvin tasolle {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Maailman kulmakivi\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Hautaholvin tasolle {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Takaisin tasolle {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Tallennustiedostoarkistoa ei voi avata\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"Stash-versio ei kelpaa. Jos yrität käyttää stashia, tiedot korvataan!\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"Stashin koko ei kelpaa. Jos yrität käyttää stashia, tiedot korvataan!!\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Virheellinen tallennustiedosto\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Pelaaja on Hellfire-tasolla\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Virheellinen pelitila\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Päävalikkoa ei voi näyttää\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"Monster-tietojen lataaminen epäonnistui\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\"Hirviötä ei voitu lisätä, koska hirviötyyppien enimmäismäärä {} on jo \"\n\"saavutettu.\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"ID:lle ”{}” on jo olemassa hirviötyyppi.\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Eläin\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demoni\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Epäkuollut\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Tyyppi: {:s} Tapot: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Tappoja yhteensä: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Vahinkopisteet: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Ei maagisia vastuksia\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Vastukset:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magia\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Tuli\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Salama\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Immuuni:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Tyyppi: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Ei vastuksia\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Ei immuuneja\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Joitain maagisia vastuksia\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Joitain maagisia immuuneja\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Arkistoa ei voitu avata kirjoittamista varten.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} on käyttänyt virheellisen loitsun.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} on käyttänyt laitonta loitsua.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Pelaaja '{:s}' (taso {:d}) liittyi juuri peliin\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Peli loppui\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Tasotietoja ei voitu hakea\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Pelaaja '{:s}' poistui juuri pelistä\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Pelaaja '{:s}' tappoi Diablon ja poistui pelistä!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Pelaaja '{:s} poistui aikakatkaisun takia\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Pelaaja '{:s}' (taso {:d}) on jo pelissä\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Mysteerinen\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Salainen\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Synkkä\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Outo\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Maaginen\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Kivi\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Uskonnollinen\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Lumottu\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Taikavoimainen\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Mielenkiintoinen\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Kryptinen\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Eldritch\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Aavemainen\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Divine\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Pyhä\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Pyhä\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Hengellinen\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Kammottava\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Hylätty\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Pelottava\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Hiljainen\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Eristetty\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Ornate\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Kimaltava\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Saastunut\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Öljyinen\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Hohtava\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Kerjäläisen\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Kipinöivä\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Kimaltava\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Solaarinen\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Murphyn\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Suuri konflikti\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Synnin palkka on sota\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Horadrimin tarina\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Pimeä karkoitus\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Syntiensota\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Kolmen sitoumus\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Tuonpuoleiset maailmat\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Puun tarina\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Musta kuningas\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Päiväkirja: Enssorcellment\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Päiväkirja: Tapaaminen\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Päiväkirja Tirade\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Päiväkirja: Hänen voimansa kasvaa\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Päiväkirja: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Päiväkirja: Loppu\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Loitsukirja\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Ristiinnaulittu luuranko\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Vipu\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Avattu ovi\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Suljettu ovi\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Tukittu ovi\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Muinainen kirja\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Pahuuden kirja\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Kallovipu\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Myyttinen kirja\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Pieni arkku\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Arkku\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Iso arkku\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sargofaki\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Kirjahylly\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Kirjahylly\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Tynnyri\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Kapseli\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Uurna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Pyhäkkö\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Luurankokirja\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Kirjaston Kirja\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Veren Lähde\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Päätön ruumis\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Sokeuden Kirja\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Veren Kirja\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Puhdistava lähde\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Haarniska\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Aseteline\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Vuohien pyhäkkö\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Pata\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Samea allas\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Kyynelten Lähde\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Teräskirja\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Veren Jalusta\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Sienipaikka\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Vile Stand\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Surmattu sankari\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"Loukussa {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (pois)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"Päällä\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"Pois\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Pelimoodi\"\n\n#: Source/options.cpp:422\nmsgid \"Game Mode Settings\"\nmsgstr \"Pelimoodin asetukset\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Pelaa Diablo:a tai Hellfire:ä.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Rajoita osuusohjelmaan\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"Pistää pelin yhteensopivaksi demon kanssa.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Käynnistys\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Käynnistys asetukset\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Alkuesittely\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Esitetty Intro-elokuva.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Aloitus\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Näkyvä aloitusnäyttö.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo ja otsikkoruutu\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Päävalikko\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Diablo-kohtaiset asetukset\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Hellfire-kohtaiset asetukset\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Ääni\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Ääni Asetukset\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Askel Ääni\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Pelaaja päästää ääntä kävellessään.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Automaattisen keräyksen ääni\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Kun tavarat otetaan käyttöön.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Tavaran keräämis ääni\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Tavaroiden kerääminen päästää \\\"tavaroiden nostamis\\\" äänen.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Näytteenottotaajuus\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Lähtönäytteen ottotaajuus (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanavat\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Lähtökanavien lukumäärä.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Puskuri koko\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Puskuri koko (kuvataajuuden määrä kanavaa kohden).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Resamplerin laatu\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Resamplerin laatu, asteikolla 0 (alin) – 5 (korkein).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Vaikuttaa pelin sisäiseen resoluutioon ja määrittää näkymäalueen. Huomaa: \"\n\"Tämä voi poiketa näytön resoluutiosta, kun käytetään skaalausta, \"\n\"kokonaislukuskaalausta tai näytön mukautusta.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Resampleri\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Ääni resampleri\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Laite\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Äänilaite\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafiikka\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Grafiikka Asetukset\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Kokonäyttö\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Näytä peli ikkunatilassa tai kokonäytöllä.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Sovita näyttöön\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Säädä pelin ikkuna automaattisesti nykyisen työpöydän näytön kuvasuhteeseen \"\n\"ja tarkkuuteen.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Skaalaus\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Mahdollistaa kuvan skaalauksen pelin resoluutiosta näytön resoluutioon. \"\n\"Estää näytön resoluution muuttamisen ja mahdollistaa ikkunan koon \"\n\"muuttamisen.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Skaalauksen laatu\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Mahdollistaa valinnaisten suodattimien käytön ulostulevassa kuvassa \"\n\"skaalattaessa.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Lähin pixelitarkkuus\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilineaarinen\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotrooppinen\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Kokonaislukuskaalaus\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Skaalaa kuvan käyttämällä kokonaislukuisia pikselisuhteita.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"Kuvataajuuden hallinta\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\"Hallitsee kuvanopeutta suorituskyvyn tasapainottamiseksi, repeytymisen \"\n\"vähentämiseksi tai virran säästämiseksi.\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Vertikaalinen synkronointi\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"Lukitse kuvataajuus\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Zoomaus, kun toiminto on käytössä.\"\n\n#: Source/options.cpp:738\nmsgid \"Per-pixel Lighting\"\nmsgstr \"Pikselikohtainen valaistus\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\"Hienovarainen valaistus tasaisempien valogradienttien aikaansaamiseksi.\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Värisykli\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Veden, laavan ja hapon animaatioissa käytetty värisykli-efekti.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternate nest art\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"Peli käyttää vaihtoehtoista palettia Hellfiren pesä -grafiikkasarjaan.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Laitteistokohdistin\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Käytä laitteistokohdistinta\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Laitteiston kohdistin tavaroille\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Käytä laitteistokohdistinta tavaroihin.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Laitteiston kohdistimen enimmäiskoko\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Laitteistokohdistimen suurin leveys/korkeus. Suuremmat kohdistimet siirtyvät \"\n\"ohjelmistokohdistimiksi.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Näytä Kuvataajuus\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Näyttää Kuvataajuuden näytön vasemmassa yläkulmassa.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Pelattavuus\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Pelin asetukset\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Ota käyttöön hölkkäily/nopea kävely kaupungissa Diablossa ja Hellfiressä. \"\n\"Tämä vaihtoehto esiteltiin laajennuksessa.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Hae Syöte\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Kun tämä toiminto on käytössä, hiiri lukittuu pelin ikkunaan.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Keskeytä peli, kun ikkuna menettää keskityksen\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\"Kun tämä toiminto on käytössä, peli keskeytyy, kun keskitys menetetään.\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Ota käyttöön Pikkutyttö-tehtävä.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Ota Jersey'n tehtävä käyttöön. Maanviljelijä Lester korvataan Idiootilla.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Oma tuli\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Salli nuoli-/loitsuvahingot pelaajien välillä moninpelissä, vaikka \\\"Oma \"\n\"tuli\\\" tila olisi päällä.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Täys tehtävät moninpelissä\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\"Mahdollistaa tehtävien täysimittaisen/leikkaamattoman yksinpeliversion.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Kokeile Bardihahmoa\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Pakota Bardi-hahmotyyppi näkyviin sankarivalintavalikossa.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Kokeile Barbaarihahmoa\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Pakota Barbaari-hahmotyyppi näkyviin valintavalikossa.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Kokemuspalkki\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Kokemuspalkki lisätään käyttöliittymään näytön alareunaan.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Näytä tavaroiden kuvakkeet myymälöissä\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\"Näytä tavaroiden kuvakkeet tavaroiden kuvauksien vasemmalla puolella \"\n\"myymälän valikoissa.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Näytä terveysarvot\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Näyttää nykyisen / maksimaalisen terveysarvon terveyspallossa.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Näytä mana-arvot\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Näyttää nykyisen / maksimaalisen manan arvon manapallossa.\"\n\n#: Source/options.cpp:797\nmsgid \"Show Party Information\"\nmsgstr \"Näytä ryhmän tiedot\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"Näyttää kaikkien yhdistäneiden moninpelijäsenten terveyden ja manan.\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Vastustajan Terveyspalkki\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Vihollisen terveyspalkki näkyy näytön yläosassa.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"Tuotetietolaatikko\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"Näyttää kohteen tiedot ruudussa, kun hiiri viedään kohteen päälle.\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Kulta kerätään automaattisesti, kun se on lähellä pelaajaa.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Eliksiirit kerätään automaattisesti, kun ne ovat lähellä pelaajaa.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Öljyt kerätään automaattisesti, kun ne ovat lähellä pelaajaa.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Kerää tavarat automaattisesti kaupungista.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria täyttää manasi, kun vierailet hänen kaupassaan.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Aseet otetaan käyttöön automaattisesti, kun ne nostetaan tai ostetaan, jos \"\n\"tämä toiminto on käytössä.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Haarniskat otetaan käyttöön automaattisesti, kun ne nostetaan tai ostetaan, \"\n\"jos tämä toiminto on käytössä.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Kypärät otetaan käyttöön automaattisesti, kun ne nostetaan tai ostetaan, jos \"\n\"tämä toiminto on käytössä.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Kilvet otetaan käyttöön automaattisesti, kun ne nostetaan tai ostetaan, jos \"\n\"tämä toiminto on käytössä.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Korut otetaan käyttöön automaattisesti, kun ne nostetaan tai ostetaan, jos \"\n\"tämä toiminto on käytössä.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Valitse satunnaisesti käytettävissä olevat tehtävät uusille peleille.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Näytä hirviötyyppi\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Kun viet hiiren hirviön päälle, sen tyyppi näkyy käyttöliittymän \"\n\"kuvauskentässä.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Näytä maassa olevien tavaroiden tunnisteet, kun toiminto on käytössä.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Täytä vyö varastosta, kun vyö on kulunut loppuun.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Kun tämä toiminto on käytössä, kattiloita, kiehtovia alttareita, \"\n\"vuohialttareita, koristeellisia alttareita, pyhiä alttareita ja Murphyn \"\n\"alttareita ei voi klikata, ja ne merkitään käytöstä poistetuiksi.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Pikaloitsu\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Loitsun pikanäppäimet laukaisevat loitsun välittömästi, sen sijaan että \"\n\"vaihtaisivat valmiina olevan loitsun.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Automaattisesti kerättävien parantavien juomien määrä.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Automaattisesti kerättävien täysien parantavien juomien määrä.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Automaattisesti kerättävien manajuomien määrä.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Automaattisesti kerättävien täysien mana juomien määrä.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Automaattisesti kerättävien nuorentamisjuomien määrä.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Automaattisesti kerättävien täyden nuorentamisen juomien määrä.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Ota liukuluvut käyttöön\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\"Mahdollistaa liukulukjen numerot XP:n ansaitsemisen / vahingon aiheuttamisen \"\n\"jne. yhteydessä.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Pois\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Sattumanvaraiset kulmat\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Vain vertikaali\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Ohjain\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Ohjainasetukset\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Verkko\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Verkkoasetukset\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chatti\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Chatin Asetukset\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Kieli\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Määritä mitä kieltä pelissä käytetään.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Kieliasetukset\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Näppäimistöasettelu\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Näppäinasetukset\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Ohjainasettelu\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Ohjainasettelu-asetukset\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"Modit\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"Modiasetukset\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Taso\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Kokemus\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Seuraava taso\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Pohja\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Nyt\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Vahvuus\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magia\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Näppäryys\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Puhti\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Jaettavat pisteet\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Kulta\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Haarniskaluokka\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"Mahdollisuus osua\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Vahinko\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Terveys\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Magiankesto\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Tulenkesto\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Salamankesto\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"hahmo\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"tehtävät\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"kartta\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"valikko\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"tavaral\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"loitsut\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"ääni\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"mykistä\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Käyttökelvoton\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Vah: 1/3 kohteen terveys\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Parannus: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Vahinko: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Taito\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Sauvan ({:d} lataus)\"\nmsgstr[1] \"Sauvan ({:d} lataukset)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Taso {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Loitsu\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Vahingoittaa vain epäkuolleita\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Käärö\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Sauva\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Pikakomento {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Arkistoa ei voi avata\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Hahmoa ei voi ladata\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"Luokka datan lataus epäonnistui\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\"Luokkaa ei voitu lisätä, koska luokan enimmäismäärä {} on jo saavutettu.\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (tas {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Chatin Historia (Viestit: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} kulta\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Kuinka monta kultaa haluat nostaa?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Taso {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Kokemus: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Korkein Taso\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Seuraava taso: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} Tasolle {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Kuningas Leorickin Hauta\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Luun kammio\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Pimeä väylä\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Epäpyhyyden alttari\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"{:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Tarvitsen apua! Tule tänne!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Seuraa minua.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Tässä on sinulle jotain.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Nyt sinä KUOLET!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Paranna itsesi!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Varo!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Kiitos.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Peräänny!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Anteeksi.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Minä odotan.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Takaisin\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Vahinko: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Haarniska: {:d}  \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Kes: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Tuhoutumaton\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Tervetuloa\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Sepän pajaan\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Haluaisitko:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Puhu Griswoldille\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Osta perustavaroita\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Osta korkealuokkaisia tavaroita\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Myy tavaroita\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Korjaa tavaroita\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Poistu kaupasta\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Minulla on nämä tavarat myynissä:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Minulla on nämä korkealuokkaiset tavarat myynissä:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Sinulla ei ole mitään mitä haluan.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Mikä tavara on alennuksessa?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Sinulla ei ole mitään korjattavaa.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Korjaa mikä tavara?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Noidan mökki\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Puhu Adrialle\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Osta tavaroita\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Uudelleenlataa sauvat\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Poistu mökistä\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Sinulla ei ole mitään uudelleenladattavaa.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Uudelleenlataa mikä tavara?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Sinulla ei ole tarpeeksi kultaa\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Sinulla ei ole tarpeeksi tilaa tavaraluettelossa\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Tuliko kaupat?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Oletko varma että haluat tunnistaa tämän tavaran?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Oletko varma että haluat ostaa tämän tavaran?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Oletko varma että haluat uudelleenladata tämän tavaran?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Oletko varma että haluat myydä tämän tavaran?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Oletko varma että haluat korjata tämän tavaran?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt, puujalkainen poika\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Puhu Wirtille\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Minulla on jotain alennuksessa,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"mutta se maksaa 50 kultaa\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"vilkaisehan. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Mitä sinulla on?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Sano hyvästi\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Minulla on tämä tavara alennuksessa:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Poistu\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Parantajan talo\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Puhu Pepinille\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Poistu Parantajan talosta\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Kylän vanhin\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Puhu Cainille\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Tunnista tavara\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Sinulla ei ole mitään tunnistettavaa.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Mikä tavara pitää tunnistaa?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Tämä tavara on:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Valmis\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Puhu {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Puhuu {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"ei ole saatavilla\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"osuusohjelmassa\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"versio\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Juoru\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Nouseva aurinko\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Puhu Ogdenelle\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Poistu\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Puhu Gillianille\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Varasto\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnharn, juoppo\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Puhu Farnhamille\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Sano hyvästi\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Sinun kultasi: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"Teksti datan lataus epäonnistui\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"Tekstidataa on jo syötetty tunnukselle ”{}”.\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Tapettu kyläläinen\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Grisworld, Seppä\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin Parantaja\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Haavoittunut kyläläinen\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden, Majatalon omistaja\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Cain, Vanhempi\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Adria, Noita\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian Baaripalvelija\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Lehmä\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester, Maanviljelijä\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Idiootti\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Soturi\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Roisto\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Velho\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Munkki\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bardi\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Raakalainen\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Ghouli\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Mätänevä ruho\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Musta Kuolema\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Langennut\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Veistäjä\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Pikku piru\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Varjo\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Luuranko\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Ruumikirves\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Palava Kuollut\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Kammotus\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Jäännöspeto\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Ruttosyöjä\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Varjo Peto\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Luunmurskaaja\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Ruumisjousi\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Luurankopäälikkö\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Ruumispäälikkö\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Palava ja kuollut kapteeni\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Kauhukapteeni\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Näkymätön lordi\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Piiloutunut\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Vaanija\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Näkymätön\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Illuusionkutoja\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Satyyripäälikkö\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Lihaheimolainen\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Kiviklaanilainen\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Tuliklaanilainen\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Yöklaanilainen\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Riiviö\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Vilahdus\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Kalmo\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Riivolepakko\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Happopeto\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Myrkkykoura\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Kuoppakoura\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Lavasuutaja\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Luuranko Kuningas\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Butcher\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Ylivaltias\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Mutahirmu\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Rupihirmu\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Nyljittyhirmu\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Imumato\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Luolamato\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Paholaismato\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Ahmija\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Magmademoni\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Verikivi\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Helvetin kivitys\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Laavavaltias\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Sarvidemoni\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Mutakonnaaja\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Jääpuuskija\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obsidiaanivaltias\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"ikiluu\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Punasurma\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Kuolodemoni\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Tuliblorgi\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Polttaja\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Tulivaltias\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Tuhonlieska\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Helvetinlieke\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Verituuli\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Myrskynratsastaja\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Myrskyvaltias\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Varjopeto\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Demonisoturi\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Siivekäs demoni\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargoili\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Verikoura\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Kuolonsiipi\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Teurastaja\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Hirmuvartija\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Pyörrehirmu\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Tulisiipi\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Luolakyy\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Tulipeto\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Kultapeto\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Sinipeto\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Musta ritari\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Tuhonvartija\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Teräspäällikkö\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Veriritari\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Repalehirviö\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Onttoolento\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Tuskanherra\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Todellisuudenpunoja\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Naisdemoni\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Luminoita\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Helvetinalku\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Sielunkäristäjä\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Neuvonantaja\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Valtias\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Kabalisti\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Puoltaja\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golemi\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Diablo\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Arkkilich Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad Heikko\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar Mielipuoli\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Räkäpurske\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Arkkipiispa Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Verivihuri\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Musta Jademoni\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Veren Sotajumala\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Horkkidemoni\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Pilkkaaja\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Kirvesluu\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Leikkaajaterä\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Sielunpursi\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Pukerat Saastainen\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Luurajaja\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Rotuavaaja\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Nopea Teräleikkaaja\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Päätäräys\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bonko\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Mätökaaos\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Varjapurija\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Tarkkasilmä\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Kuolohullsilmän\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"Verisyöjä\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Tulikallo\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Sotakallo\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Verikieli\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Sykeröyömijä\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Kuuveltoja\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Raivokorppi\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Selkäravitsija\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Mustapolttaja\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Varjokorppi\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Saastakivi\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Myrkkykuopanpäälikkö\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Verijousi\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Saastasiipi\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Varjoimijä\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Usvamuuttaja\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Kuolesylki\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Verikouru\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Varjolihahirmu\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Matahullu\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Sirpakallo\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Mätätuli\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Nightwing Kylmä\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Murtokivi\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Tulikiven Nyrkki\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Wrathfire Tuomittu\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Synkkä Tulihirmu\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Liejuparoni\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Saastasarvi Teräsnuija\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Kaaosulvoja\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Mätävirne\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Tulihullu\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Sahaluu Lich\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Selkämurtaja\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Teräsluu Demonikallo\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Murtumyrsky\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Myrskyntuoja\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Liejusylki\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Tulimätä Kulta\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Mustamyrsky\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Ruttoraivo\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Nylkijä\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Sinisarvi\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Tulivääntäjä Helvetsestä\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Torapiikki\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Ruttokallo\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Vääntynyt Leijonkallo\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Mustakieli\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Iljetyskosketus\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Tulikäärme\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Hammasnahka\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Witchfire Epäpyhä\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Varjokallo\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Sieluviilooja\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Tuulihirmu\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Kuopan lordi\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Ruostonkutoja\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Varjoulvaja\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Tuomiopilvi\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Verikuu Sielutuli\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Kuunoita\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Verinälkä\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Graywar Teurastaja\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Kauhutalttaja\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Stareeye Noita\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Steelskull Metsästäjä\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Ritari Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Vizieeri\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamfiri\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Verenhimoinen\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Myrkkyverkko\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Lihautaja\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Piikkihirmu\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Kuolonloitsu\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Lyhyt Miekka\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Kilpi\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Nuija\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Lyhytjousi\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Lyhytvartinen Manan sauva\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Hakkuuveitsi\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Kuolemattomuuden kruunu\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Taivaan rannekoru\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Maaginen kivi\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Optinen amuletti\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Totuuden sormus\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Kapakan kyltti\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Harlequin-tunnus\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Teräksen verho\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Kultainen Eliksiiri\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Raivon Alasin\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Mustasieni\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Aivot\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Sienikirja\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Spektrinen eliksiiri\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Verikivi\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Katedraalin Kartta\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"Korva\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Parannuksen juoma\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Manan juoma\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Tunnistuksen käärö\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Kyläportaalin käärö\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Arkaineen Valor haarniska\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Täydellisen parantumisen juoma\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Täyden manan juoma\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Griswoldin Terä\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Naudanlaatta\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Lazaruksen Sauva\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Ylösnousemuksen käärö\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Lyhyt sauva\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Miekka\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Tikari\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Riimupommi\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Tero\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Auric-amuletti\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Revitty Lappu 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Revitty Lappu 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Revitty Lappu 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Uudelleen kasattu lappu\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Ruskea puku\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Harmaa puku\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Hattu\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Luuhattu\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Kypärä\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Täyskypärä\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Kruunu\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Suurkypärä\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Viitta\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Lumppu\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Viitta\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Kaapu\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Tikkattu haarniska\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Nahkahaarniska\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Kova nahkainen haarniska\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Nastoitettu nahkahaarniska\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Rengashaarniska\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Haarniska\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Rengaspanssari\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Suomuhaarniska\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Rintapanssari\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Panssari\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Liuskapanssari\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Levyhaarniska\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Kenttäpanssari\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Goottilainen levyhaarniska\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Täysi levyhaarniska\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Kilpi\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Pieni kilpi\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Iso kilpi\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Leijakilpi\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Tornikilpi\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Goottilainen kilpi\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Nuorentamisen juoma\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Täydellisen nuorentamisen juoma\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Öljy\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Vahvuuden eliksiiri\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Magian eliksiiri\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Näppäryyden eliksiiri\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Elinvoiman eliksiiri\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Parannuksen käärö\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Paljastuksen käärö\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Salamoinnin käärö\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Tuliseinän käärö\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Infernon käärö\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Välähdyksen käärö\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Pimeänäön käärö\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Siirtymisen käärö\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Manakilven käärö\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Lieska-aallon käärö\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Tulipallon käärö\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Kivisen kirouksen käärö\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Ketjusalaman käärö\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Suojelijan käärö\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Novan käärö\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Golemin käärö\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Teleporttauksen käärö\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Täystuhon käärö\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Falkion\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Käyrämiekka\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Klaymoori\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Terä\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Sapeli\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Pitkämiekka\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Piilumiekka\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Pitkämiekka\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Kaksikätinen miekka\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Suurmiekka\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Pieni Kirves\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Kirves\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Suuri Kirves\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Piilukirves\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Sotakirves\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Suurkirves\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Rautanuija\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Aamutähti\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Sotavasara\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Vasara\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Piikinuija\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Varsta\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Moukari\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Jousipyssy\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Metsästäjän jousipyssy\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Pitkäjousi\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Komposiittijousi\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Lyhyt taistelujousi\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Pitkä taistelujousi\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Lyhyt sotajousi\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Pitkä sotajousi\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Pitkäsauva\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Komposiittisauva\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Neljännessauva\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Sotasauva\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Sormus\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amuletti\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Tulen riimu\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Riimu\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Salamoinnin riimu\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Suurempi tuliriimu\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Suurempi salamoinnin riimu\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Kiven riimu\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Ladatun vasaman sauva\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Areena juoma\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Butcherin Hakkuuveitsi\"\n\n#: Source/translation_dummy.cpp:370\nmsgid \"Lightforge\"\nmsgstr \"Valotako\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Rift-jousi\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Neulakone\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Taivaallinen jousi\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Tappava metsästäjä\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Kuolleiden jousi\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Blackoak-jousi\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Tulitikka\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Lihaspistäjä\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Tuulenvoima\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Kotkansarvi\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Gonnagalin tikari\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Puolustaja\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Gryphonin\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Mustanerä\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Kuperankuun terä\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Jääterä\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Teloittajan terä\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Luusaha\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Varjohaukka\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Velhontikari\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Magiasäde\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Haukan kynsi\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Turmion tuoja\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Karhuterä\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Isoisä\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Silppuri\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Teränokka\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Verimurskaaja\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Taivaallinen kirves\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Turmakirves\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Kiviterä\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Aguinaran kirves\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Helvetinkirves\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Messerschmidtin verikirves\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Murskanuija\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Jholmijn vasara\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Civerbin rautanuija\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Taivaallinen tähti\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Barnarin tähti\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Kähäräjuuri\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Kallonmurskaaja\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Schafaerin vasara\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Nukkumatti\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Varjojen sauva\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Liekittäjä\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Myrskynpiikki\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Kimmelsauva\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Silppuri\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Suojelija\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Najin pulmuri\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Mielenitku\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Onanin sauva\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Sielujenkypärä\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Ajattelukypärä\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"OverLordin kypärä\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Hölmön vaakuna\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Jumalten tuho\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Kuninkaallinen kruunu\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Sielujen revitty liha\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Gladiaattorin kirous\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Sateenkaarikaapu\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Aut:in nahka\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Viisauden kääre\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Kipinöivä panssari\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Keräilijän Karapassi\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Yökaapu\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Najin kevytpanssari\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Demonspike-takki\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Deflektori\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Halkaistu kallo-kilpi\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Lohikäärmeen murtuma\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Mustametsän kilpi\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Pyhä puolustaja\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Myrskykilpi\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Bramble\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Reghan sormus\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Vuotaja\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Kiristävä sormus\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Kihlasormus\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Tina\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Messinki\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Pronssi\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Rauta\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Teräs\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Hopea\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platina\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithrilli\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteorinen\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Outo\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Hyödytön\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Väännetty\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Heikko\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Rosoinen\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Tappava\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Painava\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Häijy\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Brutaali\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Massiivinen\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Villi\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Häikäilemätön\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Armoton\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Kömpelö\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Tylsä\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Terävä\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Hyvä\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Soturin\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Sotilaan\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Herran\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Ritarin\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Mestarin\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Mestarin\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Kuninkaan\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Haavoittuvainen\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Ruostunut\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Vahva\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Hienoa\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Uljas\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Kunniakas\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Siunattu\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Pyhä\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Mahtavaa\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Jumalainen\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Punainen\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Purppuranpunainen\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Granaatti\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubiini\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Sininen\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Taivaansininen\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lapis\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Koboltti\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Safiiri\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Valkoinen\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Helmi\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Norsunluu\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Kristalli\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Timantti\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topaasi\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Keltainen\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Jade\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Laavalasi\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Smaragdi\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Hyeenan\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Sammakon\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Hämähäkin\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Korpin\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Käärmeen\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Käärmeen\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Draken\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Lohikäärmeen\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Lohikäärmeen\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hydran\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Enkelin\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Arkkienkelin\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Runsaasti\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Runsas\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Liekehtivä\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Salamoiva\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"laatu\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"silpominen\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"surmaus\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"hurme\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"verilöyly\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"teurastus\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"tuska\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"kyyneleet\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"terveys\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"suojaus\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"imu\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"poiskääntö\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"osmoosi\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"heikkous\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"heikkous\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"vahvuus\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"mahti\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"voima\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"jättiläiset\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"titaanit\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"halvaus\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"näivetys\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"näppäryys\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"taito\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"täsmällisyys\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"tarkkuus\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"täydellisyys\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"pöyristys\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"ajatuskaaos\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"magia\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"mieli\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"loisto\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"taikuus\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"velhomainen\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"tauti\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"sairaus\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"elinvoima\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"ilo\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"energia\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"vireys\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"elämä\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"ongelma\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"monttu\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"taivas\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"kuu\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"tähdet\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"ylämaailma\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"zodiac\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"korppikotka\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"sakaali\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"kettu\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"jaguaari\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"kotka\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"susi\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tiikeri\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"leijona\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mamutti\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"valas\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"hauraus\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"herkkyys\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"vankkuus\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"käsityötaito\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"rakennelma\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"iät\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"pimeys\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"yö\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"valo\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"loiste\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"lieska\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"tuli\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"palaa\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"salamanisku\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"salama\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"ukkonen\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"monta\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"paljon\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"piikit\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"mätäneminen\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"varkaat\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"karhu\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"lepakko\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"vampyyrit\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"iilimato\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"veri\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"lävistävä\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"puhkaiseva\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"iskevä\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"valmius\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"nopeus\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"nopeus\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"kiire\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"tasapaino\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"vakaus\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"harmonia\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"torjunta\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Maaginen kivi\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbard, Heikko\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar Mielipuoli\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Butcher\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Ogdenin Merkki\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Sokeuden käytävät\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Urheus\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Veren Sotajumala\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Kuningas Leroric:n Kirous\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Arkkipiispa Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Kuollonkysymykset\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Viljelijän Hedelmäpuutarha\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Pikkutyttö\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Vaeltava kauppias\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Saastuttaja\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Jerseyn Takki\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Tulivasama\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Parannus\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Salama\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Välähdys\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Tunnistus\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Tuliseinä\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Kylän Portaali\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Kivinen kirous\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Pimeänäkö\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Siirtymä\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Manakilpi\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Tulipallo\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Vartiuus\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Ketjusalama\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Liekkiaalto\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Tuomion käärmeet\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Veren Rituaali\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Näkymättömyys\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golemi\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Raivo\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleportti\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Täystuho\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Eterioida\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Paikkaus\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Sauvan Uudelleenlataus\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Ansan poisto\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elementaalinen\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Sähköistetty vasama\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Pyhävasama\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Ylösnousu\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekineesi\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Paranna toista\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Veritähti\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Luusielu\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ahh, tarina kuninkaastamme, vai? Leoricin traaginen lankeaminen oli kova \"\n\"isku tälle maalle. Kansalaiset rakastivat aina kuningasta, ja nyt he elävät \"\n\"kuolemanpelossa häntä kohtaan. Kysymys, jota kysyn itseltäni yhä uudelleen, \"\n\"on se, kuinka hän saattoi langeta niin kauas Valosta, sillä Leoric oli aina \"\n\"ollut pyhin kaikista miehistä. Vain helvetin ilkeimmät voimat voisivat \"\n\"tuhota miehen niin täydellisesti sisältäpäin...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Kylä tarvitsee apuasi! Muutama kuukausi sitten kuningas Leoricin poika, \"\n\"prinssi Albrecht, siepattiin. Kuningas raivostui ja etsi kadonnutta lastaan \"\n\"kylästä. Päivä päivältä Leoric näytti vajoavan yhä syvemmälle hulluuteen. \"\n\"Hän syytti viattomia kyläläisiä pojan katoamisesta ja teloitti heidät \"\n\"julmasti. Alle puolet meistä selvisi hänen hulluudestaan...\\n\"\n\"\\n\"\n\"Kuninkaan ritarit ja papit yrittivät rauhoittaa häntä, mutta hän kääntyi \"\n\"heitä vastaan, ja valitettavasti he joutuivat tappamaan hänet. \"\n\"Kuolemanhetkellään kuningas langetti kauhean kirouksen entisille \"\n\"seuraajilleen. Hän vannoi, että he palvelisivat häntä ikuisesti \"\n\"pimeydessä...\\n\"\n\"\\n\"\n\"Tässä vaiheessa asiat ottavat vieläkin synkemmän käänteen kuin olisin voinut \"\n\"kuvitellakaan! Entinen kuninkaamme on herännyt ikuisesta unestaan ja \"\n\"komentaa nyt labyrintissä epäkuolleita legioonalais alaisiaan. Hänen \"\n\"ruumiinsa on haudattu kolme kerrosta katedraalin alapuolella olevaan \"\n\"hautakammioon. Pyydän, anna hänen sielulleen rauha tuhoamalla hänet...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Kuten sanoin, kuningas haudattiin kolme tasoa alemmas. Hän on siellä \"\n\"alhaalla, odottaen mädäntyneessä pimeydessä tilaisuutta tuhota tämän maan...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Kuninkaamme kirous on ohi, mutta pelkään, että se oli vain osa suurempaa \"\n\"pahuutta. Voimme kuitenkin vielä pelastua maamme valtaavasta pimeydestä, \"\n\"sillä voittonne on hyvä enne. Valo opastakoon teitä matkallanne.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Poikansa menetys oli liikaa kuningas Leoricille. Tein mitä pystyin \"\n\"lievittääkseni hänen hulluuttaan, mutta lopulta se voitti hänet. Mustan \"\n\"kirouksen varjo on leijunut tämän kuningaskunnan yllä siitä päivästä \"\n\"lähtien, mutta ehkä jos vapauttaisit hänen henkensä maallisesta \"\n\"vankilastaan, kirous poistuisikin...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"En halua ajatella, miten kuningas kuoli. Haluan muistaa hänet ystävällisenä \"\n\"ja oikeudenmukaisena hallitsijana. Hänen kuolemansa oli niin surullinen ja \"\n\"tuntui jotenkin hyvin väärältä.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Valmistin monia aseita ja suurimman osan Leoric-kuninkaan ritareiden \"\n\"käyttämistä haarniskoista. Valmistin hänelle jopa valtavan kaksikätisen \"\n\"miekan hienoimmasta mithrilistä sekä siihen sopivan taistelukruunun. En \"\n\"vieläkään voi uskoa, miten hän kuoli, mutta hänen hulluutensa takana on \"\n\"täytynyt olla jokin paha voima!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"En välitä siitä. Kuuntele, mikään luuranko ei tule olemaan MINUN kuninkaani. \"\n\"Leoric on kuningas. Kuningas, kuuletko? ELÄKÖÖN KUNINGAS!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Elävien joukossa vaeltavat kuolleet seuraavat kirottua kuningasta. Hänellä \"\n\"on valta herättää lisää sotureita yhä kasvavaan kuolleiden armeijaan. Jos et \"\n\"pysäytä häntä, hän marssii varmasti tämän maan halki ja surmaa kaikki, jotka \"\n\"vielä elävät täällä.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Kuules, minulla on täällä liiketoimintaa. En myy tietoja, enkä välitä \"\n\"kuninkaasta, joka on ollut kuolleena kauemmin kuin minä olen elänyt. Jos \"\n\"tarvitset jotain, mitä voit käyttää tätä \\\"kuolleiden kuningasta\\\" vastaan, \"\n\"voin auttaa sinua...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Elämän lämpö on tullut hautaani. Kuolevainen, valmistaudu palvelemaan \"\n\"Mestaria ikuisesti!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Huomaan, että tämä outo käytös hämmentää sinuakin. Arvelisin, että koska \"\n\"monet demonit pelkäävät auringonvaloa ja uskovat sen sisältävän suurta \"\n\"voimaa, on mahdollista, että mainitsemassasi kyltissä kuvattu nouseva \"\n\"aurinko on saanut heidät uskomaan, että myös siinä on salaperäisiä voimia. \"\n\"Hmm, ehkä he eivät olekaan niin älykkäitä kuin pelkäsimme...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Mestari, minun on kerrottava eräs outo kokemus. Tiedän, että teillä on laaja \"\n\"tietämys labyrintissä asuvista hirviöistä, ja tämä on asia, jota en millään \"\n\"voi ymmärtää... Yöllä minut herätti raapiva ääni kapakkani ulkopuolella. Kun \"\n\"katsoin ulos makuuhuoneestani, näin pienen demonimaisen olennon hahmot \"\n\"majatalon pihalla. Hetken kuluttua ne juoksivat pois, mutta eivät ennen kuin \"\n\"olivat varastaneet majataloni kyltin. En tiedä, miksi demonit varastivat \"\n\"kyltini, mutta jättivät perheeni rauhaan... Eikö se ole outoa?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Ei sinun olisi tarvinnut tuoda kylttiäni takaisin, mutta se säästää minulta \"\n\"uuden kylttien valmistuskustannukset. No, katsotaanpa, mitä voisin antaa \"\n\"sinulle palkkioksi sen löytämisestä? Hmmm, mitä meillä täällä on... ah, \"\n\"kyllä! Tämä lippalakki jäi yhteen huoneista, kun eräs taikuri majoittui \"\n\"täällä jonkin aikaa sitten. Ehkä se on sinulle jonkin arvoinen.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Voi luoja, demonit juoksentelevat yöllä kylässä ja ryöstelevät kotejamme – \"\n\"eikö mikään ole pyhää? Toivottavasti Ogden ja Garda ovat kunnossa. \"\n\"Luultavasti he tulisivat kertomaan minulle, jos he olisivat loukkaantuneet...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Voi ei! Sinnekkö kylttini katosi? Isoäiti ja minä olimme varmaan nukkuneet \"\n\"koko tapahtuneen ohi. Onneksi ne hirviöt eivät hyökänneet majataloon.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Demonit varastivat Ogdenin kyltin, vai? Se ei kuulosta kovin paljon niiltä \"\n\"julmuuksilta, joista olen kuullut tai nähnyt. \\n\"\n\"\\n\"\n\"Demonit haluavat repiä sydämesi irti, eivät kylttejäsi.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Tiedätkö mitä mieltä olen? Joku on vienyt kyltin ja vaatii siitä paljon \"\n\"rahaa. Jos olisin Ogden... en ole, mutta jos olisin... ostaisin vain uuden \"\n\"kyltin, jossa olisi kaunis kuva. Ehkä mukava olutmuki tai pala juustoa...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Kukaan kuolevainen ei voi todella ymmärtää demonin mieltä.\\n\"\n\" \\n\"\n\"Älä koskaan anna heidän arvaamattomien tekojensa hämmentää sinua, sillä \"\n\"sekin voi olla heidän suunnitelmansa.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Mitä - väittääkö hän, että otin sen? Griswold on varmaan myös hänen \"\n\"puolellaan.\\n\"\n\"\\n\"\n\"Kuules, pääsin yli yksinkertaisesta merkkien varastamisesta kuukausia \"\n\"sitten. Puupalasta ei voi saada voittoa.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hei, sinä, joka tapat kaikki! Anna minulle maaginen lippu tai hyökkäämme! Et \"\n\"pääse täältä hengissä! Tapa isot rumilukset ja palauta maaginen lippu. Mene \"\n\"kulman ja oven ohi, etsi rumilukset. Anna lippu, niin pääset menemään!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Tapa rumilukset, hanki lippu. Tuo se minulle, tai muuten...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Anna mennä! Kyllä, hyvä! Mene nyt, me olemme vahvoja. Me tapamme kaikki \"\n\"suurella taikuudella!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Tämä ei lupaa hyvää, sillä se vahvistaa pahimmat pelkoni. En ole halunnut \"\n\"uskoa muinaisiin legendoihin, mutta nyt en voi enää kieltää niitä. Ehkä on \"\n\"tullut aika paljastaa, kuka olen.\\n\"\n\" \\n\"\n\"Oikea nimeni on Deckard Cain vanhempi, ja olen muinaisen veljeskunnan \"\n\"viimeinen jälkeläinen. Veljeskunta oli omistautunut ajattoman pahuuden \"\n\"salaisuuksien suojelemiseen. Pahuus, joka on nyt selvästi vapautunut.\\n\"\n\" \\n\"\n\"Arkkipiispa Lazarus, joka oli aikoinaan kuningas Leoricin luotetuin \"\n\"neuvonantaja, johti joukon tavallisia kaupunkilaisia labyrinttiin etsimään \"\n\"kuninkaan kadonnutta poikaa Albrechtia. Kesti kauan, ennen kuin he \"\n\"palasivat, ja vain harvat heistä selvisivät hengissä.\\n\"\n\" \\n\"\n\"Kirottu olkoon minun typeryys! Minun olisi pitänyt epäillä hänen salattua \"\n\"petostaan jo silloin. Lazarus on varmasti itse siepannut Albrechtin ja \"\n\"piilottanut hänet labyrinttiin. En ymmärrä, miksi arkkipiispa kääntyi \"\n\"pimeyden puoleen tai miksi hän on kiinnostunut lapsesta, ellei hän aio \"\n\"uhrata tätä pimeille mestareilleen!\\n\"\n\" \\n\"\n\"Sen hän on varmasti suunnitellut! Hänen ”pelastuspartionsa” selviytyneet \"\n\"kertovat, että Lazarus nähtiin viimeksi juoksevan labyrintin syvimpiin \"\n\"syövereihin. Sinun on kiirehdittävä pelastamaan prinssi tämän mielipuolen \"\n\"uhrausveitseltä!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Sinun on kiirehdittävä pelastamaan Albrecht Lazaruksen käsistä. Prinssi ja \"\n\"tämän valtakunnan kansa luottavat sinuun!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Tarinasi on varsin synkkä, ystäväni. Lazarus tulee varmasti palamaan \"\n\"helvetissä kauheiden tekojensa vuoksi. Poika, josta kerrot, ei ole \"\n\"prinssimme, mutta uskon, että Albrecht voi silti olla vaarassa. Voiman \"\n\"symboli, josta puhut, on varmasti portaali labyrintin sydämessä.\\n\"\n\" \\n\"\n\"Tiedä tämä, ystäväni: pahuus, jota vastaan taistelet, on pimeyden kauhun \"\n\"herra. Kuolevaiset tuntevat hänet nimellä Diablo. Hänet vangittiin \"\n\"labyrinttiin vuosisatoja sitten, ja pelkään, että hän pyrkii jälleen \"\n\"kylvämään kaaosta ihmiskunnan valtakuntaan. Sinun on uskallettava kulkea \"\n\"portaalin läpi ja tuhota Diablo, ennen kuin on liian myöhäistä!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus oli arkkipiispa, joka johti monet kaupunkilaiset labyrinttiin. \"\n\"Menetin sinä päivänä monia hyviä ystäviä, eikä Lazarus koskaan palannut. \"\n\"Luulen, että hän kuoli muiden mukana. Jos voisit tehdä minulle palveluksen, \"\n\"älä puhu Farnhamille siitä päivästä.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Olin järkyttynyt kuullessani, mitä kaupunkilaiset aikoivat tehdä sinä yönä. \"\n\"Luulin, että juuri Lazarus olisi ollut järkevämpi kuin muut. Hän oli \"\n\"arkkipiispa ja näytti aina välittävän niin paljon Tristramin \"\n\"kaupunkilaisista. Niin monet loukkaantuivat, etten voinut pelastaa heitä \"\n\"kaikkia...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Muistan Lazaruksen erittäin ystävällisenä ja anteliaana miehenä. Hän piti \"\n\"puheen äitini hautajaisissa ja tuki isoäitiäni ja minua hyvin vaikeana \"\n\"aikana. Rukoilen joka ilta, että hän olisi jotenkin vielä elossa ja turvassa.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Olin paikalla, kun Lazarus johdatti meidät labyrinttiin. Hän puhui pyhästä \"\n\"kostosta, mutta kun aloimme taistella helvetin sikiöitä vastaan, hän ei edes \"\n\"nostanut nuijaansa niitä vastaan. Hän vain juoksi syvemmälle hämärään, \"\n\"loputtomaan kammioon, joka oli täynnä pimeyden palvelijoita!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"He puukottavat, sitten purevat, ja sitten he ovat kaikki ympärilläsi. \"\n\"Valehtelija! VALEHTELIJA! He ovat kaikki kuolleet! Kuolleet! Kuuletko minua? \"\n\"He vain kaatuvat ja kaatuvat... heidän verensä valuu lattialle... kaikki on \"\n\"hänen syytään...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"En tunne tätä Lazarusta, josta puhut, mutta aistin hänen sisällään suuren \"\n\"ristiriidan. Hän on suuri vaara, eikä hän kaihda keinoja palvellakseen \"\n\"pimeyden voimia, jotka ovat ottaneet hänet omakseen.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Kyllä, vanhurskas Lazarus, joka oli niin tehokas noita hirviöitä vastaan. Se \"\n\"ei auttanut pelastamaan jalkaani, eihän? Kuules, annan sinulle ilmaisen \"\n\"neuvon. Kysy Farnhamilta, hän oli siellä.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Luovu typerästä pyrkimyksestäsi. Sinua odottaa vain mestarini viha! Olet \"\n\"liian myöhässä pelastaaksesi lapsen. Nyt pääset hänen seuraansa helvettiin!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, en tiedä mitä voisin kertoa sinulle tästä, mikä olisi sinulle avuksi. \"\n\"Kaivoihimme täyttyvä vesi tulee maanalaisesta lähteestä. Olen kuullut \"\n\"tunnelista, joka johtaa suureen järveen – ehkä ne ovat yksi ja sama. \"\n\"Valitettavasti en tiedä, mikä voisi aiheuttaa vesivarantomme pilaantumisen.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Olen aina yrittänyt pitää varastokellarissamme runsaasti elintarvikkeita ja \"\n\"juomia, mutta koska koko kaupungissa ei ole makean veden lähdettä, jopa \"\n\"varastomme tyhjenevät pian.\\n\"\n\" \\n\"\n\"Tee mitä voit, tai en tiedä mitä me teemme.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Onneksi sain sinut kiinni ajoissa! Kaivomme ovat muuttuneet suolaisiksi ja \"\n\"seisoviksi, ja osa kaupunkilaisista on sairastunut juotuaan niistä. Makean \"\n\"veden varastomme ovat nopeasti ehtymässä. Uskon, että on olemassa käytävä, \"\n\"joka johtaa kaupunkimme lähteille. Selvitä, mikä on aiheuttanut tämän \"\n\"onnettomuuden, tai me kaikki kuolemme varmasti.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Ole kiltti, sinun on kiirehdittävä. Jokainen kulunut tunti vie meidät \"\n\"lähemmäksi tilannetta, jossa meillä ei ole enää juomavettä.\\n\"\n\" \\n\"\n\"Emme voi selviytyä pitkään ilman apuasi.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Mitä sinä sanot - pelkästään demonien läsnäolo oli saastuttanut veden? Voi, \"\n\"todellakin suuri pahuus vaanii kaupunkimme alla, mutta sinun sinnikkyytesi \"\n\"ja rohkeutesi antavat meille toivoa. Ota tämä sormus - ehkä se auttaa sinua \"\n\"tuhoamaan nämä ilkeät olennot.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Isoäitini on hyvin heikko, ja Garda sanoo, että emme voi juoda kaivojen \"\n\"vettä. Voitteko auttaa meitä jotenkin?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin on kertonut sinulle totuuden. Tarvitsemme kipeästi puhdasta vettä, ja \"\n\"pian. Olen yrittänyt puhdistaa yhden pienemmistä kaivoista, mutta se haisee \"\n\"seisovalle likalle. Se on varmaan tukkeutunut lähteellä.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Sinä, juot vettä?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Tristramin asukkaat kuolevat, jos et pysty palauttamaan puhdasta vettä \"\n\"heidän kaivoihinsa.\\n\"\n\" \\n\"\n\"Tiedä tämä: demonit ovat tämän asian ytimessä, mutta he eivät ole tietoisia \"\n\"siitä, mitä ovat synnyttäneet.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Tällä kertaa olen samaa mieltä kanssasi. Liiketoimintani kuivuu – niin \"\n\"sanotusti – jos minulla ei ole markkinoita, joille myydä. Sinun on parasta \"\n\"selvittää, mitä on meneillään, ja pian!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Kirja, joka kertoo ihmisluiden kammiosta? No, luukammio mainitaan tietyissä \"\n\"vanhoissa kirjoituksissa, joita olen tutkinut itämaisten kirjastojen \"\n\"kokoelmissa. Näissä teoksissa viitataan siihen, että kun manalan herrat \"\n\"halusivat suojella suuria aarteita, he loivat alueita, joissa ne, jotka \"\n\"kuolivat yrittäessään varastaa aarteita, joutuivat puolustamaan niitä \"\n\"ikuisesti. Kieroutunut, mutta oudosti sopiva loppu?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Pelkäänpä, että en tiedä siitä mitään. Cainilla on monia kirjoja, joista voi \"\n\"olla apua.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Tämä kuulostaa erittäin vaaralliselta paikalta. Jos uskaltaudut sinne, ole \"\n\"erittäin varovainen.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Pelkäänpä, etten ole kuullut siitä mitään. Ehkä tarinankertoja Cain voisi \"\n\"olla avuksi.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"En tiedä mitään tästä paikasta, mutta voit kysyä Cainilta. Hän puhuu monista \"\n\"asioista, eikä minua yllättäisi, jos hänellä olisi vastauksia kysymykseesi.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Okei, kuuntele. Siellä on puinen kammio. Ja hänen vaimonsa, tiedätkö, hän \"\n\"sanoo puulle... koska sinun täytyy odottaa. Sitten sanon, että se saattaa \"\n\"toimia häntä vastaan, mutta jos luulet, että aion maksaa tästä... sinä... \"\n\"ööh... joo.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Jos kuolet tässä kirotussa valtakunnassa, sinusta tulee pimeyden herrojen \"\n\"ikuinen palvelija.\\n\"\n\" \\n\"\n\"Astu luukammioon omalla vastuulla.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Valtava ja salaperäinen aarre, sanotko? Ehkä voisin olla kiinnostunut \"\n\"ostamaan muutaman tavaran sinulta... tai vielä parempi, etkö tarvitse \"\n\"harvinaisia ja kalliita tarvikkeita selviytyäksesi tästä koettelemuksesta?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Arkkipiispa Lazarus näyttää yllyttäneen monet kaupunkilaiset lähtemään \"\n\"labyrinttiin etsimään kuninkaan kadonnutta poikaa. Hän hyödynsi heidän \"\n\"pelkojaan ja kiihotti heidät raivoisaksi väkijoukoksi. Kukaan heistä ei \"\n\"ollut valmistautunut siihen, mitä kylmän maan alla odotti... Lazarus hylkäsi \"\n\"heidät sinne – jätti heidät sanoinkuvaamattomien kauhujen armoille – \"\n\"kuolemaan.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Kyllä, Farnham mutisi jotain jostakin valtavasta raakalaisesta, joka \"\n\"heilutti hurjaa asetta. Luulen, että hän kutsui sitä Butcheriksi.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Valon nimeen, tiedän tämän ilkeän demonin. Monien ruumiissa oli hänen vihan \"\n\"jälkiä, kun Lazaruksen johtaman hyökkäyksen harvat selviytyjät ryömivät ulos \"\n\"katedraalista. En tiedä, mitä hän käytti uhriensa viiltämiseen, mutta se ei \"\n\"voinut olla tästä maailmasta. Se jätti haavoihin märkiviä haavoja, joita \"\n\"jopa minä pidin lähes mahdottomina hoitaa. Ole varovainen, jos aiot \"\n\"taistella tätä hirviötä vastaan...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Kun Farnham sanoi jotain Butcherista, joka tappaa ihmisiä, en uskonut sitä \"\n\"heti. Mutta nyt kun otit asian esille, ehkä se onkin totta.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Näin sen, jota Farnham kutsuu Butcheriksi, kun se raivasi tiensä ystävieni \"\n\"ruumiiden läpi. Se heilutti hakkuuveistä, joka oli yhtä suuri kuin kirves, \"\n\"katkoen raajoja ja kaataen rohkeita miehiä paikoilleen. Joukko pieniä \"\n\"kirkuvia demoneja erotti minut taistelusta, ja jotenkin löysin portaat, \"\n\"jotka johtivat ulos. En ole nähnyt sitä kauheaa petoa sen jälkeen, mutta sen \"\n\"verinen ilme kummittelee mielessäni vielä tänäkin päivänä.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Iso! Iso veitsikaveri tappoi kaikki ystäväni. En voinut estää sitä, jouduin \"\n\"pakenemaan, en voinut pelastaa heitä. Olin loukussa huoneessa, jossa oli \"\n\"niin paljon ruumiita... niin paljon ystäviä... EI!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Butcher on sadistinen olento, joka nauttii muiden kiduttamisesta ja \"\n\"kärsimyksestä. Olet nähnyt hänen tekonsa juoppo Farnhamissa. Hänen \"\n\"tuhoamisensa varmistaa paljolti tämän kylän turvallisuuden.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Tiedän enemmän kuin luuletkaan siitä kammottavasta hirviöstä. Hänen pikku \"\n\"ystävänsä saivat minut kiinni ja onnistuivat tarttumaan jalastani, ennen \"\n\"kuin Griswold veti minut ulos siitä kuopasta.\\n\"\n\" \\n\"\n\"Sanon sen suoraan: tapa hänet, ennen kuin hän tappaa sinut ja lisää ruumiisi \"\n\"kokoelmaansa.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Kuuntele minua. Arkkipiispa Lazarus johdatti meidät tänne etsimään \"\n\"kadonnutta prinssiä. Se paskiainen johdatti meidät ansaan! Nyt kaikki ovat \"\n\"kuolleet... sen demonin takia, jota hän kutsui Butcheriksi. Kosta meidän \"\n\"puolestamme! Etsi tämä Butcher ja surmaa hänet, jotta sielumme voivat \"\n\"vihdoin levätä rauhassa...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Sinä lausut mielenkiintoisen runon, jonka tyyli muistuttaa minua muista \"\n\"teoksista. Anna minun miettiä – mikä se olikaan?\\n\"\n\" \\n\"\n\"...Pimeys peittää piilotetun. Silmät loistavat näkymättöminä, ja vain \"\n\"terävien kynsien ääni raapii hetkellisesti kiduttaakseen niitä köyhiä \"\n\"sieluja, jotka on tehty sokeiksi ikuisiksi ajoiksi. Niiden kirottujen \"\n\"vankila on nimeltään Sokeiden salit...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"En ole koskaan välittänyt runoudesta. Joskus, kun majatalo menestyi, minulla \"\n\"oli syytä palkata trubaduurit, mutta se tuntuu nyt niin kaukaiselta ajalta.\\n\"\n\" \\n\"\n\"Mitä? Ai, niin... No, kai se on mahdollista, että joku muu tietää.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Tämä tuntuu jotenkin tutulta. Muistan lukeneeni jotain hyvin samanlaista \"\n\"runoa tutkiessani demonien aiheuttamien kärsimysten historiaa. Siinä \"\n\"kerrottiin paikasta, jossa vallitsi suuri pahuus... Hetkinen, et kai aio \"\n\"mennä sinne?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Jos sinulla on kysymyksiä sokeudesta, sinun pitäisi puhua Pepinin kanssa. \"\n\"Tiedän, että hän antoi isoäidilleni juoman, joka auttoi parantamaan hänen \"\n\"näkönsä, joten ehkä hän voi auttaa sinuakin.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Pelkäänpä, että en ole kuullut tai nähnyt paikkaa, joka vastaisi elävää \"\n\"kuvailuasi, ystäväni. Ehkä tarinankertoja Cain voisi olla avuksi.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Katso tätä... aika hauskaa, eikö? Tajusitko? Sokea - katso tätä?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Katsotaanpa, myynkö sinulle jotain? En. Annatko minulle rahaa, jotta kerron \"\n\"sinulle tästä? En. Lähdetkö nyt puhumaan tarinankertojalle, joka elää \"\n\"tällaisesta? Kyllä.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Väität puhuneesi Lachdananin kanssa? Hän oli elinaikanaan suuri sankari. \"\n\"Lachdanan oli kunniallinen ja oikeudenmukainen mies, joka palveli \"\n\"kuningastaan uskollisesti vuosikausia. Mutta tietysti sinä tiedät sen jo.\\n\"\n\" \\n\"\n\"Niistä, jotka joutuivat kuninkaan kirouksen valtaan, Lachdanan olisi vähiten \"\n\"todennäköinen alistumaan pimeyteen taistelematta, joten luulen, että \"\n\"tarinasi voisi olla totta. Jos olisin sinun sijassasi, ystäväni, etsisin \"\n\"keinon vapauttaa hänet kidutuksestaan.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Puhut kauan sitten kuolleesta urheasta soturista! En halua kuulla puhetta \"\n\"kuolleiden sielujen kanssa keskustelemisesta majataloni pihalla, kiitos \"\n\"paljon.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Kultaista eliksiiriä, sanot. En ole koskaan valmistanut tuonväristä juomaa, \"\n\"joten en voi kertoa, miten se vaikuttaisi sinuun, jos yrittäisit juoda sitä. \"\n\"Parantajana suosittelen vahvasti, että jos löydät tällaisen eliksiirin, tee \"\n\"kuten Lachdanan pyytää ja ÄLÄ yritä käyttää sitä.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"En ole koskaan ennen kuullut Lachdananista. Valitan, mutta en usko voivani \"\n\"olla sinulle avuksi.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Jos olet todella tavannut Lachdananin, suosittelen, että autat häntä. Olen \"\n\"ollut tekemisissä hänen kanssaan useaan otteeseen ja havainnut hänet \"\n\"rehelliseksi ja lojaaliksi. Kuningas Leoricin seuraajille langennut kirous \"\n\"koituu erityisesti hänen kohtalokseen.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan on kuollut. Kaikki tietävät sen, etkä voi kääntää päätäni asian \"\n\"suhteen. Kuolleille ei voi puhua. Minä tiedän!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Saatat tavata ihmisiä, jotka ovat jääneet loukkuun labyrinttiin, kuten \"\n\"Lachdanan.\\n\"\n\" \\n\"\n\"Aistin hänessä kunniaa ja suurta syyllisyyttä. Auttamalla häntä autat koko \"\n\"Tristramia.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Odota, anna kun arvaan. Cain joutui valtavan halkeaman uhriksi, joka avautui \"\n\"hänen allaan. Hän paloi helvetin tulessa eikä voi enää vastata kysymyksiisi. \"\n\"Eikö niin? Sitten kai ostat jotain tai jatkat matkaasi.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Älkää tappako minua, kuunnelkaa minua. Olin kerran kuningas Leoricin \"\n\"ritarikunnan kapteeni, joka puolusti tämän maan lakeja oikeudenmukaisesti ja \"\n\"kunniakkaasti. Sitten hänen pimeä kirous langetettiin meidän päällemme, \"\n\"koska olimme osallisina hänen traagisessa kuolemassaan. Kun ritarikunnan \"\n\"toverini alistuivat kieroutuneeseen kohtaloonsa, minä pakenin kuninkaan \"\n\"hautakammiosta etsimään keinoa vapautua kirouksesta. Epäonnistuin...\\n\"\n\" \\n\"\n\"Olen kuullut kultaisesta eliksiiristä, joka voisi poistaa kirouksen ja antaa \"\n\"sielulleni rauhan, mutta en ole onnistunut löytämään sitä. Voimani ovat nyt \"\n\"hiipumassa, ja niiden mukana myös viimeisetkin ihmisyyteni rippeet. Auta \"\n\"minua ja etsi eliksiiri. Korvaan ponnistuksesi – vannon sen kunniasanallani.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Et ole löytänyt kultaista eliksiiriä. Pelkään, että olen tuomittu \"\n\"ikuisuuteen. Ole kiltti, jatka yrittämistä...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Olet pelastanut sieluni kadotukselta, ja siitä olen sinulle velkaa. Jos \"\n\"joskus löydän tavan korvata sinulle tämän kuoleman jälkeen, teen sen, mutta \"\n\"nyt ojennan sinulle kypäräni. Matkalla, jolle olen lähdössä, minulla ei ole \"\n\"sille juurikaan käyttöä. Suojelkoon se sinua alhaalla olevilta pimeiltä \"\n\"voimilta. Olkoon valo kanssasi, ystäväni...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold puhuu Raivon alasimesta – legendaarisesta esineestä, jota on \"\n\"etsitty pitkään, mutta jota ei ole koskaan löydetty. Raivon alasin on \"\n\"valmistettu Razor Pit -demonien metallisista luista, ja se on sulatettu \"\n\"viiden alamaailman voimakkaimman magin kalloista. Voiman ja kaaoksen \"\n\"riimukirjaimilla kaiverrettu alusta upottaa kaikki sillä taotut aseet ja \"\n\"haarniskat kaaoksen valtakuntaan, antaen niille maagisia ominaisuuksia. \"\n\"Kaaoksen arvaamattoman luonteen vuoksi on vaikea tietää, millainen \"\n\"lopputulos tällä taonnalla on...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Eikö Griswold olisi parempi henkilö, jolta kysyä tästä? Hän on aika kätevä, \"\n\"tiedätkö.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Jos olisit etsinyt tietoa parantavan nuijan tai puhdistavan hopeamaljan \"\n\"suhteen, olisin voinut auttaa sinua, ystäväni. Tässä asiassa sinun olisi \"\n\"kuitenkin parempi puhua joko Griswoldin tai Cainin kanssa.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Griswoldin isä kertoi joillekin meistä lapsuudessamme jättimäisestä \"\n\"alasimesta, jota käytettiin mahtavien aseiden valmistamiseen. Hän sanoi, \"\n\"että kun vasara iski tätä alasinta, maa järisi raivoisasti. Aina kun maa \"\n\"liikkuu, muistan tuon tarinan.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Tervehdys! On aina ilo nähdä yksi parhaista asiakkaistani! Tiedän, että olet \"\n\"seikkaillut syvemmälle labyrinttiin, ja minulle on kerrottu tarina, joka \"\n\"saattaa kiinnostaa sinua...\\n\"\n\" \\n\"\n\"Yksi labyrintistä palannut mies kertoi minulle mystisestä alasimesta, jonka \"\n\"hän löysi pakonsa aikana. Hänen kuvauksensa muistutti minua nuoruudessani \"\n\"kuulemistani legendoista palavasta Helvetin takomosta, jossa valmistetaan \"\n\"voimakkaita maagisia aseita. Legendan mukaan Helvetin takomon syvyyksissä \"\n\"lepää Vihan alasin! Tämä alasin sisältää demonisen alamaailman \"\n\"ydinolemuksen...\\n\"\n\" \\n\"\n\"Sanotaan, että kaikki polttavalla alasimella valmistetut aseet ovat täynnä \"\n\"suurta voimaa. Jos tämä alasin on todellakin Raivon alasin, voin ehkä \"\n\"valmistaa sinulle aseen, jolla voit voittaa jopa helvetin pimeimmän herran!\\n\"\n\" \\n\"\n\"Etsi alasin minulle, niin ryhdyn töihin!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Ei vielä mitään, vai? No, jatka etsimistä. Alasimessa taottu ase voisi olla \"\n\"paras toivosi, ja olen varma, että voin valmistaa sinulle legendaarisen \"\n\"aseen.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"En voi uskoa tätä! Tämä on Raivon alasin – hyvää työtä, ystäväni. Nyt \"\n\"näytämme noille kusipäille, että helvetissä ei ole ihmisten valmistamia \"\n\"aseita tappavampia aseita! Ota tämä ja valo suojelkoon sinua.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold ei voi myydä alasintaan. Mitä hän sitten tekee? Minäkin olisin \"\n\"vihainen, jos joku veisi alasimeni!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Labyrintissä on monia esineitä, joiden voimat ylittävät kuolevaisten \"\n\"ymmärryksen. Joissakin niistä on fantastinen voima, jota voivat käyttää joko \"\n\"Valo tai Pimeys. Alasimen turvaaminen alhaalta voisi muuttaa Synnin sodan \"\n\"kulun Valon suuntaan.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Jos löytäisit tämän esineen Griswoldille, se voisi haitata vakavasti \"\n\"liiketoimintani täällä. Älä huoli, et löydä sitä koskaan.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Veriportti ja Tulihallit ovat mystisen alkuperän maamerkkejä. Missä tahansa \"\n\"tämä kirja, jota luet, sijaitsee, se on varmasti paikka, jossa on suuri \"\n\"voima.\\n\"\n\" \\n\"\n\"Legendoissa kerrotaan jalustasta, joka on veistetty obsidiaanikivestä ja \"\n\"jonka luiden peittämän pinnan päällä on kiehuvaa verta. On myös viittauksia \"\n\"Verikiviin, jotka avaavat oven, joka vartioi muinaista aarretta...\\n\"\n\" \\n\"\n\"Aarteen luonne on spekulaatioiden verhoama, ystäväni, mutta sanotaan, että \"\n\"muinainen sankari Arkaine sijoitti pyhän Valor-haarniskan salaiseen holviin. \"\n\"Arkaine oli ensimmäinen kuolevainen, joka käänsi synnin sodan kulun ja ajoi \"\n\"pimeyden legioonat takaisin palavaan helvettiin.\\n\"\n\" \\n\"\n\"Juuri ennen Arkaineen kuolemaa hänen haarniskansa kätkettiin salaiseen \"\n\"holviin. Sanotaan, että kun tätä pyhää haarniskaa tarvitaan jälleen, sankari \"\n\"nousee pukemaan Valor-haarniskan ylleen. Ehkä sinä olet se sankari...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Jokainen lapsi kuulee tarinan soturista Arkaineesta ja hänen mystisestä \"\n\"haarniskastaan, joka tunnetaan nimellä Valor. Jos löytäisit sen \"\n\"sijaintipaikan, olisit hyvin suojattu labyrintin pahuudelta.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... kuulostaa siltä, että minun pitäisi muistaa se, mutta olen ollut niin \"\n\"kiireinen kun olen opetellut uusia parannuskeinoja ja luomassa parempia \"\n\"eliksiirejä, että olen varmaan unohtanut sen. Anteeksi...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Miehien keskuudessa kuulin usein puhuttavan maagisesta Valor-haarniskasta. \"\n\"Kysy siitä joltakin kylän miehistä.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Valor-niminen haarniska voi olla se tekijä, joka käännetään kuin vaakakuppi \"\n\"sinun eduksesi. Voin kertoa, että monet ovat etsineet sitä – minä mukaan \"\n\"lukien. Arkaine on piilottanut sen hyvin, ystäväni, ja sen löytämiseen \"\n\"tarvitaan enemmän kuin vain vähän onnea, jotta sen salaisuudet, jotka ovat \"\n\"pitäneet sen piilossa kaikki nämä vuodet, paljastuvat.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Jos löydät nämä Verikivet, käytä niitä varovasti.\\n\"\n\" \\n\"\n\"Matka on täynnä vaaroja, ja ainoa toivosi on itseluottamuksesi.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Aiotko etsiä Valor-nimisen haarniskan?\\n\"\n\" \\n\"\n\"Kukaan ei ole koskaan keksinyt, mihin Arkaine on piilottanut sen, ja jos \"\n\"minun kätyrini eivät ole löytäneet sitä, epäilen vahvasti, että sinäkään et \"\n\"löydä.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Tiedän vain yhden legendan, joka kertoo sinun kuvaamastasi soturista. Hänen \"\n\"tarinansa löytyy muinaisista Synninsota -kronikoista...\\n\"\n\" \\n\"\n\"Tuhatvuotisen sodan, veren ja kuoleman tahraama Verinen sotapäällikkö seisoo \"\n\"silvottujen uhriensa muodostaman vuoren päällä. Hänen tumma miekka huutaa \"\n\"mustaa kirousta eläville; kiduttava kutsu kaikille, jotka uskaltavat astua \"\n\"tämän helvetin teloittajan eteen.\\n\"\n\" \\n\"\n\"On myös kirjoitettu, että vaikka hän oli kerran kuolevainen, joka taisteli \"\n\"Pimeyden legioonan rinnalla Synninsodassa, hän menetti ihmisyytensä \"\n\"kyltymättömän verenjanonsa vuoksi.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Pelkäänpä, että en ole kuullut mitään tästä \\\"julmasta soturista\\\". Toivon, \"\n\"että teidän ei tarvitse taistella häntä vastaan, sillä hän kuulostaa \"\n\"erittäin vaaralliselta.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain voisi kertoa sinulle paljon enemmän tällaisesta asiasta kuin minä ikinä \"\n\"haluaisin tietää.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Jos joudut taistelemaan niin hurjaa vastustajaa vastaan, olkoon Valo oppaasi \"\n\"ja puolustajasi. Pidän sinut mielessäni.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Pimeät ja pahanlaatuiset legendat ympäröivät tätä \\\"Verisoturia\\\". \"\n\"Valmistaudu hyvin, ystäväni, sillä hän ei tunne armoa eikä armahda.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Pitääkö sinun aina puhua verestä? Entä kukat, auringonpaiste ja se kaunis \"\n\"tyttö, joka tuo juomat? Kuuntele, ystäväni – olet pakkomielteinen, tiedätkö \"\n\"sen?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Hänen miekkailutaitonsa on mahtava, ja hän on elänyt tuhansia vuosia tuntien \"\n\"vain sodankäynnin. Olen pahoillani... En ole varma, voitatko hänet.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"En ole koskaan ollut tekemisissä tämän sotapäällikön kanssa, josta puhut, \"\n\"mutta hän kuulostaa kuluttavan paljon miekkoja. En olisi vastenmielinen \"\n\"toimittamaan niitä hänen armeijoilleen...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Miekkani janoaa vertasi, kuolevainen, ja pimeiden mestarieni nimeen, sitä ei \"\n\"voi kieltää.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold puhuu taivaskivestä, joka oli tarkoitettu itäisessä erillisalueella \"\n\"sijaitsevaan paikkaan. Se oli vietävänä sinne lisätutkimuksia varten. Kivi \"\n\"hehkui energialla, joka jotenkin antoi tavallista ihmistä suuremman \"\n\"näkökyvyn. En tiedä, mitä salaisuuksia se kätkee, ystäväni, mutta tämän \"\n\"kiven löytäminen olisi varmasti erittäin arvokasta.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Karavaani pysähtyi täällä ottamaan varusteita itään suuntautuvalle \"\n\"matkalleen. Myin heille melkoisen määrän tuoreita hedelmiä ja erinomaisen \"\n\"makeita leivonnaisia, jotka Garda oli juuri leiponut. Harmi, mitä heille \"\n\"tapahtui...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"En tiedä, mitä he luulivat näkevänsä tuon kiven avulla, mutta sanonpa tämän: \"\n\"jos taivaalta putoaa kiviä, on parasta olla varovainen!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"No, eräs hyvin tärkeiden henkilöiden karavaani pysähtyi täällä, mutta siitä \"\n\"on jo jonkin aikaa. Heillä oli outo aksentti ja he olivat lähdössä pitkälle \"\n\"matkalle, jos muistan oikein.\\n\"\n\" \\n\"\n\"En näe, miten voisit toivoa löytäväsi mitään, mitä he olisivat kuljettaneet \"\n\"mukanaan.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Odota hetki – minulla on sinulle mielenkiintoinen tarina. Karavaani, joka \"\n\"oli matkalla itäisiin kuningaskuntiin, kulki tästä ohi jonkin aikaa sitten. \"\n\"Sen mukana oli kuulemma pala taivaasta, joka oli pudonnut maahan! Karavaani \"\n\"joutui verhottujen ratsastajien väijytyksen uhriksi hieman pohjoiseen \"\n\"täältä, erään tien varrella. Etsin romuista tätä \\\"Taivaskiveä\\\", mutta en \"\n\"löytänyt sitä mistään. Jos löydät sen, uskon voivani valmistaa siitä jotain \"\n\"hyödyllistä.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Odotan yhä, että tuot minulle sen \\\"Taivaskiven\\\". Tiedän, että voin tehdä \"\n\"siitä jotain voimakasta.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Anna minun katsoa... Kyllä, se on juuri niin kuin arvelinkin. Odota \"\n\"hetki...\\n\"\n\" \\n\"\n\"Ah, tässä se on. Asetin kivenpalaset isäni jättämään hopeiseen sormukseen. \"\n\"Toivottavasti se palvelee sinua hyvin.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Minulla oli ennen kaunis sormus; se oli todella kallis, sini, vihreä, puna \"\n\"ja hopeinen. En kuitenkaan muista, mitä sille tapahtui. Kaipaan sitä \"\n\"sormusta todella paljon...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Taivaskivi on erittäin voimakas, ja jos joku muu kuin Griswold olisi \"\n\"pyytänyt sinua etsimään sen, olisin estänyt sen. Hän hyödyntää sen voimat, \"\n\"ja sen käyttö on meidän kaikkien edun mukaista.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Jos joku voi tehdä jotain tuosta kivestä, niin se on Griswold. Hän tietää \"\n\"mitä tekee, ja vaikka yritänkin varastaa hänen asiakkaitaan, kunnioitan \"\n\"hänen työnsä laatua.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Noita Adria etsii mustaa sieniä? Tiedän mustista sienistä yhtä paljon kuin \"\n\"punaisista harjusta. Ehkä parantaja Pepin voisi kertoa sinulle enemmän, \"\n\"mutta tätä asiaa ei löydy mistään tarinoistani tai kirjoistani.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Sanon vain tämän: Garda ja minä emme ikinä, ikinä tarjoaisi mustia sieniä \"\n\"arvokkaille vieraillemme. Jos Adria haluaa sieniä pataansa, se on hänen \"\n\"asiansa, mutta en voi auttaa sinua löytämään niitä. Mustat sienet... \"\n\"inhottavaa!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Noita kertoi minulle, että etsit demonin aivoja auttaaksesi minua luomaan \"\n\"eliksiirini. Se olisi erittäin arvokasta monille, jotka ovat loukkaantuneet \"\n\"noiden ilkeiden petojen toimesta, jos vain voisin avata sen alkemian \"\n\"salaisuudet. Jos pystyt poistamaan demonin aivot, kun tapat sen, olisin \"\n\"kiitollinen, jos voisit tuoda ne minulle.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Erinomaista, juuri tämä olikin päämääränä. Pystyin valmistamaan eliksiirin \"\n\"ilman tätäkin, mutta eihän se haittaa ketään, jos tutkin tätä. Voisitko \"\n\"viedä tämän noidalle? Luulen, että hän odottaa sitä.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Luulen, että Ogdenilla saattaa olla sieniä varastokellarissa. Kysy häneltä?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Jos Adrialla ei ole sellaista, voit olla varma, että se on todella \"\n\"harvinainen. En voi tarjota sinulle enempää apua, mutta se kuulostaa... \"\n\"valtavalta, jättimäiseltä, paisuneelta ja turvonneelta sieneltä! No, hyvää \"\n\"metsästystä, kai.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden sekoittaa ison ja mustan sienen, mutta minua alkaa oksettaa, jos juon \"\n\"sitä. Kuuntele, kuuntele... tässä on salaisuus: kohtuullisuus on avain!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Mitäs täällä on? Mielenkiintoista, näyttää reagenssikirjalta. Pidä silmät \"\n\"auki mustan sienen varalta. Sen pitäisi olla melko suuri ja helppo \"\n\"tunnistaa. Jos löydät sen, tuo se minulle. Jooko?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Tarvitsen ison, mustan sienen. Hae se minulle, jotta voin käyttää sitä \"\n\"erityiseen keittoon, jota olen valmistamassa.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Kyllä, tämä sopii täydellisesti juomaan, jota olen kehittämässä. Muuten, \"\n\"parantaja etsii jonkin demonin aivoja, jotta hän voi hoitaa niitä, jotka \"\n\"ovat kärsineet niiden myrkyllisestä myrkystä. Uskon, että hän aikoo \"\n\"valmistaa niistä eliksiirin. Jos autat häntä löytämään tarvitsemansa, yritä \"\n\"saada minulle näyte eliksiiristä.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Miksi toit sen tänne? En tarvitse demonin aivoja. Tarvitsen sen eliksiirin, \"\n\"jota Parantaja on valmistamassa. Hän tarvitsee sen groteskielimen, joka \"\n\"sinulla on, sitten tuo minulle eliksiiri. Yksinkertaista, kun ajattelee \"\n\"asiaa, eikö vain?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Mitä? Tuotko minulle nyt sen parantajan eliksiirin? Pystyin valmistamaan \"\n\"juomani ilman sitä. Pidä hyvänäsi...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Minulla ei ole myytävänä minkään kokoisia tai värisiä sieniä. Entäpä jotain \"\n\"hieman hyödyllisempää?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Joten kartan legenda on totta. Edes minä en koskaan uskonut siihen! Luulen, \"\n\"että on aika kertoa sinulle totuus siitä, kuka olen, ystäväni. Katsos, en \"\n\"ole aivan se, miltä näytän...\\n\"\n\" \\n\"\n\"Oikea nimeni on Deckard Cain vanhempi, ja olen muinaisen veljeskunnan \"\n\"viimeinen jälkeläinen, joka oli omistautunut ajattoman pahuuden \"\n\"salaisuuksien säilyttämiseen ja suojelemiseen. Pahuuden, joka on nyt \"\n\"selvästi vapautunut...\\n\"\n\" \\n\"\n\"Pahuus, jota vastaan taistelet, on pimeyden kauhun herra, joka on \"\n\"kuolevaisille tunnettu nimellä Diablo. Hänet vangittiin labyrinttiin monta \"\n\"vuosisataa sitten. Kartta, joka sinulla nyt on, luotiin kauan sitten \"\n\"merkitsemään hetki, jolloin Diablo nousisi jälleen vankeudestaan. Kun kartan \"\n\"kaksi tähteä ovat samassa linjassa, Diablo on voimansa huipulla. Hän on \"\n\"lähes voittamaton...\\n\"\n\" \\n\"\n\"Olet nyt kilpajuoksussa aikaa vastaan, ystäväni! Etsi Diablo ja tuhoa hänet \"\n\"ennen kuin tähdet ovat samassa linjassa, sillä emme ehkä koskaan enää saa \"\n\"tilaisuutta vapauttaa maailmaa hänen pahuudestaan!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Aikamme on loppumassa! Tunnen hänen pimeän voimansa kasvavan, ja vain sinä \"\n\"voit estää häntä saavuttamasta sitä.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Olen varma, että yritit parhaasi, mutta pelkään, että edes sinun voimasi ja \"\n\"tahdonvoimasi eivät riitä. Diablo on nyt maallisen voimansa huipulla, ja \"\n\"tarvitset kaiken rohkeutesi ja voimasi voittaaksesi hänet. Valo suojelkoon \"\n\"ja opastakoon sinua, ystäväni. Autan sinua kaikin tavoin, mihin kykenen.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Jos noita ei voi auttaa sinua, ehdotan, että menisit Cainin luo, miksi \"\n\"luulet, että minä tietäisin jotain? Kuulostaa siltä, että kyseessä on hyvin \"\n\"vakava asia. Sinun pitäisi kiiruhtaa kertomaan tarinankertojalle, kuten \"\n\"Adria ehdottaisi.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"En ymmärrä tämän kartan kirjoituksia, mutta ehkä Adria tai Cain voisivat \"\n\"auttaa sinua tulkitsemaan, mihin tämä viittaa.\\n\"\n\" \\n\"\n\"Näen, että se on kartta taivaamme tähdistä, mutta en osaa tulkita sitä \"\n\"enempää.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Paras henkilö, jolta kysyä tällaisia asioita, olisi tarinankertojamme.\\n\"\n\" \\n\"\n\"Cain on hyvin perehtynyt muinaisiin kirjoituksiin, ja tuo on helposti vanhin \"\n\"näkemäni paperi.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"En ole koskaan ennen nähnyt tällaista karttaa. Mistä sait sen? En osaa lukea \"\n\"tätä, mutta Cain tai Adria saattaisivat osata vastata kysymyksiisi.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Kuuntele, tule lähemmäs. En tiedä tiedätkö mitä minä tiedän, mutta sinulla \"\n\"on jotain todella arvokasta. Se on kartta.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Voi, pelkäänpä, että tämä ei lupaa mitään hyvää. Tämä tähtikartta ennustaa \"\n\"suurta katastrofia, mutta sen salaisuuksia en voi paljastaa. Sinun on tullut \"\n\"aika käydä vakava keskustelu Tarinankertojan kanssa...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Olen etsinyt karttaa, mutta tämä se ei ole. Näytä se Adrianille – hän voi \"\n\"varmaan kertoa, mikä se on. Sanon vain yhden asian: se näyttää vanhalta, ja \"\n\"vanha tarkoittaa yleensä arvokasta.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Ole kiltti, älä satuta. Älä tapa. Pysy hengissä, niin ensi kerralla hyvyys \"\n\"tuokoon sinulle jotain.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Teen sinulle jotain. Toistan, älä tapa Gharbadia. Elä ja tee hyvää.\\n\"\n\" \\n\"\n\"Ota tämä todisteeksi siitä, että pidän sanani...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Ei vielä mitään! Melkein valmis.\\n\"\n\" \\n\"\n\"Erittäin voimakas, erittäin vahva. Elä! Elä!\\n\"\n\" \\n\"\n\"Ei kipua ja lupaus, jonka pidän!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Tämä on liian hyvä sinulle. Erittäin voimakas! Haluatko sen, ota se!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Mitä?! Miksi olet täällä? Kaikki nämä keskeytykset ovat tarpeeksi ajakseen \"\n\"jonkun jo hulluksi. Tässä, ota tämä ja jätä minut rauhaan. Älä häiritse \"\n\"minua enää!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Uteliasuutesi koituu kohtaloksesi!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Hei, ystäväni. Jää hetkeksi kuuntelemaan...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Kun etenet syvemmälle labyrinttiin, saatat löytää sieltä piilotettuja \"\n\"tietokirjoja.\\n\"\n\" \\n\"\n\"Lue ne huolellisesti, sillä ne voivat kertoa sinulle asioita, joita edes \"\n\"minä en tiedä.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Tiedän monia myyttejä ja legendoja, jotka saattavat sisältää vastauksia \"\n\"kysymyksiin, joita voi nousta esiin matkallasi labyrinttiin. Jos kohtaat \"\n\"haasteita ja kysymyksiä, joihin etsit vastauksia, etsi minut, niin kerron \"\n\"sinulle, mitä voin.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold – mies, jolla on suuri toimintakyky ja rohkeus. Hän ei varmaankaan \"\n\"ole kertonut sinulle siitä kerrasta, kun hän meni labyrinttiin pelastamaan \"\n\"Wirtin, eihän? Hän tietää hyvin, millaisia vaaroja siellä on, mutta \"\n\"toisaalta – niin tiedät sinäkin. Hän on taitava käsityöläinen, ja jos hän \"\n\"väittää voivansa auttaa sinua jollain tavalla, voit luottaa hänen \"\n\"rehellisyyteensä ja taitoihinsa.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden on omistanut ja pyörittänyt Rising Sunia ja majataloa jo lähes neljä \"\n\"vuotta. Hän osti sen vain muutama kuukausi ennen kuin kaikki täällä meni \"\n\"päin helvettiä. Hänellä ja hänen vaimollaan Gardalla ei ole varaa lähteä, \"\n\"koska he ovat sijoittaneet kaiken omaisuutensa uuden elämän rakentamiseen \"\n\"täällä. Ogden on hyvä mies, jolla on syvä vastuuntunto.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Farnham-parka. Hän on huolestuttava muistutus tuhoon tuomituista, jotka \"\n\"astuivat katedraaliin Lasaruksen kanssa sinä pimeänä päivänä. Hän selvisi \"\n\"hengissä, mutta hänen rohkeutensa ja suurin osa hänen järjestään jäivät \"\n\"johonkin pimeään kuiluun. Nykyään hän löytää lohtua vain olutkannunsa \"\n\"pohjalta, mutta hänen jatkuvassa höpötyksessään on satunnaisesti totuuden \"\n\"jyväsiä.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Adria on poikkeus Tristramissa. Hän saapui pian sen jälkeen, kun katedraali \"\n\"oli häväisty, kun taas kaikki muut olivat pakenemassa. Hän rakennutti pienen \"\n\"majan kaupungin laidalle, ilmeisesti yhdessä yössä, ja hänellä on käytössään \"\n\"monia outoja ja salaperäisiä esineitä ja tietokirjoja, joita edes minä en \"\n\"ole ennen nähnyt.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Wirtin tarina on pelottava ja traaginen. Pienet, ilkeät demonit, jotka \"\n\"heiluttivat keihäitänsä, veivät hänet äitinsä sylistä ja raahasivat \"\n\"labyrinttiin. Sinä päivänä vietiin monia muita lapsia, mukaan lukien \"\n\"kuningas Leoricin poika. Palatsin ritarit menivät alas, mutta eivät koskaan \"\n\"palanneet. Seppä löysi pojan, mutta vasta sen jälkeen, kun ilkeät pedot \"\n\"olivat alkaneet kiduttaa häntä sadistisen mielihyvänsä vuoksi.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Pidän häntä hyvänä ystävänä – ehkäpä lähimpänä ystävänäni täällä. \"\n\"Hän on toisinaan hieman sekava, mutta kukaan ei ole koskaan ollut \"\n\"huolehtivainen tai huomaavainen. Hänen tietonsa ja taitonsa ovat \"\n\"harvinaisia, ja hänen ovensa on aina avoinna.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian on hieno nainen. Hän on rakastettu iloisesta luonteestaan ja \"\n\"naurustaan, ja hänellä on erityinen paikka sydämessäni. Hän pysyy \"\n\"majatalossa tukeakseen vanhaa isoäitiään, joka on liian sairas matkustamaan. \"\n\"Pelkään joskus hänen turvallisuutensa puolesta, mutta tiedän, että kukaan \"\n\"kylän miehistä ei haluaisi nähdä hänen kärsivän.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Tervehdys! Tervetuloa Nousevan auringon majataloon!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Monet seikkailijat ovat kunnioittaneet majataloni pöytiä, ja \"\n\"kymmenkertaisesti niin monta tarinaa on kerrottu yhtä monen oluen äärellä. \"\n\"Ainoa asia, josta he kaikki olivat yhtä mieltä, oli tämä vanha sananlasku. \"\n\"Ehkä se auttaa sinua. \\\"Voit leikata lihaa, mutta luu sinun on murskattava\\\".\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Seppä Griswold on erittäin perehtynyt aseisiin ja haarniskoihin. Jos \"\n\"varusteesi tarvitsevat korjausta, hän on ehdottomasti oikea henkilö, jonka \"\n\"puoleen kääntyä.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham viettää täällä aivan liikaa aikaa, hukuttaen surunsa halpaan \"\n\"olueeseen. Pakottaisin hänet lähtemään, mutta hän kärsi niin paljon \"\n\"labyrintissä käynnin jälkeen.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria on ikäistään viisaampi, mutta minun on myönnettävä, että hän pelottaa \"\n\"minua hieman.\\n\"\n\" \\n\"\n\"No, ei se haittaa. Jos joskus tarvitset taika esineitä, hänellä on oudon \"\n\"hyvin varustettu mökki joen toisella puolella.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Jos haluat tietää enemmän kylämme historiasta, tarinankertoja Cain tietää \"\n\"melko paljon menneisyydestä.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt on veijari ja pieni roisto. Hän joutui aina vaikeuksiin, joten ei ole \"\n\"mikään yllätys, mitä hänelle tapahtui.\\n\"\n\" \\n\"\n\"Hän luultavasti meni pelleilemään johonkin paikkaan, jossa hänen ei olisi \"\n\"pitänyt olla. Minun käy häntä sääliksi, mutta en siedä hänen seuraansa.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin on hyvä mies – ja varmasti kylän anteliain. Hän huolehtii aina muiden \"\n\"tarpeista, mutta jonkinlaiset ongelmat näyttävät seuraavan häntä minne hän \"\n\"meneekin...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, baaritarjoilijani? Jos hänellä ei olisi velvollisuudentuntoa \"\n\"isoäitiään kohtaan, hän olisi paennut täältä jo kauan sitten.\\n\"\n\" \\n\"\n\"Luoja tietää, että rukoilin häntä lähtemään ja sanoin huolehtivani vanhasta \"\n\"naisesta, mutta hän on liian kiltti ja huolehtivainen tehdäkseen niin.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Mikä sinua vaivaa, ystäväni?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Olen tehnyt erittäin mielenkiintoisen löydön. Toisin kuin me, labyrintin \"\n\"olennot voivat parantaa itsensä ilman taikajuomien tai taikuuden apua. Jos \"\n\"satutat jotakin hirviötä, varmista, että se on kuollut.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Ennen kuin se joutui sen mitä katedraalin alapuolella on, oli se suuri \"\n\"oppimisen paikka. Siellä on paljon kirjoja. Jos löydät niitä, sinun pitäisi \"\n\"lukea ne kaikki, sillä jotkut saattavat sisältää salaisuuksia labyrintin \"\n\"toiminnasta.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold tietää sodankäynnistä yhtä paljon kuin minä tiedän parantamisesta. \"\n\"Hän on ovela kauppias, mutta hänen työnsä on vertaansa vailla. No, se johtuu \"\n\"varmaan siitä, että hän on ainoa jäljellä oleva seppä täällä.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain on todellinen ystävä ja viisas mies. Hän ylläpitää laajaa kirjastoa ja \"\n\"hänellä on luontainen kyky havaita monien asioiden todellinen luonne. Jos \"\n\"sinulla on kysyttävää, hän on oikea henkilö, jonka puoleen kääntyä.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Jopa minun taitoni eivät ole pystyneet parantamaan Farnhamia täysin. Olen \"\n\"pystynyt parantamaan hänen ruumiinsa, mutta hänen mielensä ja henkensä ovat \"\n\"oman parantamiskykyni yläpuolella.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Vaikka käytänkin joitakin rajoitettuja taikuuden muotoja luodakseni täällä \"\n\"säilyttämiäni juoma- ja eliksiirejä, Adria on todellinen noita. Hän ei näytä \"\n\"koskaan nukkuvan, ja hänellä on aina käytettävissään monia mystisiä kirjoja \"\n\"ja esineitä. Uskon, että hänen majansa kätkee sisäänsä paljon enemmän kuin \"\n\"mitä hän ulospäin näyttää, mutta en ole koskaan päässyt sisälle.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Wirt-parka. Tein kaiken mahdollisen lapsen hyväksi, mutta tiedän, että hän \"\n\"halveksii sitä puutappia, jonka jouduin kiinnittämään hänen jalkaansa. Hänen \"\n\"haavansa olivat kauhistuttavia. Kenenkään – etenkään niin pienen lapsen – ei \"\n\"pitäisi joutua kärsimään niin kuin hän.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"En todellakaan ymmärrä, miksi Ogden pysyy täällä Tristramissa. Hän kärsii \"\n\"lievästä hermostollisesta sairaudesta, mutta on älykäs ja ahkera mies, joka \"\n\"menestyisi hyvin missä tahansa. Luultavasti hän ja hänen perheensä pysyvät \"\n\"täällä ympäröivällä maaseudulla tapahtuvien lukuisten murhien pelon tai ehkä \"\n\"vaimonsa toiveiden vuoksi.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogdenin baaritarjoilija on suloinen tyttö. Hänen isoäitinsä on melko sairas \"\n\"ja kärsii harhoista.\\n\"\n\" \\n\"\n\"Hän väittää, että ne ovat näkyjä, mutta minulla ei ole todisteita sen \"\n\"puolesta tai sitä vastaan.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Hyvää päivää! Kuinka voin auttaa?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Isoäitini näki unessa, että tulit puhumaan minulle. Hänellä on näkyjä, ja \"\n\"hän voi nähdä niillä tulevaisuuteen.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Kaupungin laidalla asuva nainen on noita! Hän vaikuttaa mukavalta, ja hänen \"\n\"nimensä, Adria, on hyvin miellyttävä kuulla, mutta pelkään häntä kovasti.\\n\"\n\" \\n\"\n\"Tarvitaan joku sinun kaltaisesi rohkea ihminen, jotta voi nähdä, mitä hän \"\n\"siellä tekee.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Seppämme on Tristramin asukkaiden ylpeys. Hän on paitsi \"\n\"mestarikäsityöläinen, joka on voittanut useita kilpailuja kiltansa sisällä, \"\n\"myös saanut kiitosta itse kuningas Leoricilta – rauha hänen sielulleen. \"\n\"Griswold on myös suuri sankari; kysy vaikka Cainilta.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain on ollut Tristramin tarinankertoja niin kauan kuin muistan. Hän tietää \"\n\"niin paljon ja voi kertoa melkein mitä tahansa melkein mistä tahansa.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham on juoppo, joka täyttää vatsansa oluella ja kaikkien muiden korvat \"\n\"hölynpölyllä.\\n\"\n\" \\n\"\n\"Tiedän, että sekä Pepin että Ogden tuntevat myötätuntoa häntä kohtaan, mutta \"\n\"minua turhauttaa nähdä, kuinka hän joka ilta vajoaa yhä syvemmälle sekavaan \"\n\"horrokseen.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin pelasti isoäitini hengen, enkä voi koskaan korvata sitä hänelle. Hänen \"\n\"kykynsä parantaa kaikki sairaudet on voimakkaampi kuin mahtavin miekka ja \"\n\"salaperäisempi kuin mikään tunnettu loitsu. Jos joskus tarvitset parannusta, \"\n\"Pepin voi auttaa sinua.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Kasvoin Wirtin äidin, Canacen, kanssa. Vaikka hän loukkaantui vain lievästi, \"\n\"kun ne kauheat olennot veivät Wirtin, hän ei koskaan toipunut siitä. Luulen, \"\n\"että hän kuoli sydänsurusta. Wirtistä on tullut ilkeämielinen nuorukainen, \"\n\"joka haluaa vain hyötyä muiden työstä. Tiedän, että hän on kärsinyt ja \"\n\"nähnyt kauheuksia, joita en voi edes kuvitella, mutta osa siitä pimeydestä \"\n\"leijuu yhä hänen yllään.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden ja hänen vaimonsa ovat ottaneet minut ja isoäitini kotiinsa ja \"\n\"antaneet minun ansaita muutaman kultakolikon työskentelemällä majatalossa. \"\n\"Olen heille niin paljon velkaa, ja toivon voivani jonain päivänä lähteä \"\n\"täältä ja auttaa heitä perustamaan suuren hotellin itään.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"No, miten voin auttaa?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Jos etsit hyvää asetta, anna minun näyttää sinulle tämä. Ota tavallinen \"\n\"tylppä ase, kuten nuija. Se toimii loistavasti useimpia tuolla alhaalla \"\n\"olevia kuolemattomia kauhuja vastaan, maailmassa ei ole parempaa tekemistä \"\n\"kuin murskata niitä pirun perkeleen luurankoja murskasi!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Kirves? Se on hyvä ase, joka sopii vastustajaan kuin vastustajaan. Katso, \"\n\"kuinka se läpäisee halki ilman, ja kuvittele sitten sen tiellä oleva lihava \"\n\"demonin pää. Muista kuitenkin, että sen heilauttaminen on hidasta – mutta se \"\n\"antaa todella kovan iskun!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Katso tuota terää, tuota tasapainoa. Oikeissa käsissä ja oikeaa vihollista \"\n\"vastaan miekka on kaikkien aseiden mestari. Sen terävä terä ei juurikaan \"\n\"leikkaa tai lävistä eläviäkuolleita, mutta elävää, hengittävää vihollista \"\n\"vastaan miekka leikkaa heidän lihaansa raivokkaasti!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Aseesi ja haarniskasi kantavat merkkejä taisteluistasi pimeyttä vastaan. Jos \"\n\"tuot ne minulle, voin hieman työstämällä ja kovalla takomisella palauttaa ne \"\n\"huippukuntoon.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Minun on käytännössä salakuljetettava tarvitsemani metallit ja työkalut \"\n\"karavaanareilta, jotka kiertelevät kirotun kaupunkimme laitamilla, mutta se \"\n\"noita, Adria, näyttää aina saavan kaiken tarvitsemansa. Jos osaisin edes \"\n\"vähänkin käyttää taikuutta kuten hän, voisin tehdä todella uskomattomia \"\n\"asioita.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian on mukava tyttö. Harmi, että hänen isoäitinsä on niin huonossa \"\n\"kunnossa, muuten järjestäisin heille molemmille paikan \"\n\"kaupankäyntikaravaanista.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Joskus minusta tuntuu, että Cain puhuu liikaa, mutta se taitaa olla hänen \"\n\"kutsumuksensa elämässä. Jos osaisin taivuttaa terästä yhtä hyvin kuin hän \"\n\"taivuttaa korviasi, voisin valmistaa keisarille kelvollisen haarniskan!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Olin Farnhamin kanssa sinä yönä, kun Lazarus johdatti meidät Labyrinthiin. \"\n\"En ole nähnyt arkkipiispaa sen jälkeen, enkä\\n\"\n\"olisi ehkä selvinnyt, jos Farnham ei olisi ollut vierelläni. Pelkään, että \"\n\"hyökkäys vahingoitti hänen sieluaan yhtä pahasti kuin toinen vahingoitti \"\n\"jalkaani. En voi taistella tätä taistelua hänen puolestaan nyt, mutta \"\n\"taistelisin, jos voisin.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Hyvä mies, joka asettaa muiden tarpeet omiensa edelle. Tristramissa – tai \"\n\"missään muuallakaan – ei löydy ketään, joka sanoisi mitään pahaa tästä \"\n\"parantajasta.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Se poika joutuu vielä vakaviin vaikeuksiin... tai pitäisi kai sanoa, jälleen \"\n\"kerran. Olen yrittänyt saada hänet kiinnostumaan työnteosta täällä ja \"\n\"rehellisen ammatin oppimisesta, mutta hän mieluummin ansaitsee suuria \"\n\"voittoja kauppaamalla epäilyttävää alkuperää olevia tavaroita. En voi \"\n\"syyttää häntä siitä, mitä hänelle on tapahtunut, mutta toivon, että hän \"\n\"ainakin olisi varovainen.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Majatalonpitäjällä on vähän asiakkaita eikä hänellä ole todellisia \"\n\"mahdollisuuksia ansaita voittoa. Hän onnistuu tulemaan toimeen tarjoamalla \"\n\"ruokaa ja majoitusta satunnaisesti kylään saapuville vieraille, mutta he \"\n\"ovat yhtä todennäköisesti karkaamassa yöllä kuin maksamaan hänelle. Ilman \"\n\"hänen kellarissaan säilyttämiään vilja- ja kuivattua lihavarastoja useimmat \"\n\"meistä olisivat nääntyneet nälkään ensimmäisenä vuonna, kun koko maaseutu \"\n\"oli demonien valtaama.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Eikö sais juoda rauhassa?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"Se tyttö, joka tuo juomat? Ai niin, kaunis nainen. Ja niin mukava myös.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Miksi se vanha akka ei tekisi jotain muutakin vaihteeksi? Toki, toki, \"\n\"hänellä on tavaraa, mutta kuuntele minua... hän on luonnoton. En ole koskaan \"\n\"nähnyt hänen syövän tai juovan - eitkä voi luottaa johonkuhun, joka ei juo \"\n\"edes vähän.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain ei ole se, mitä hän väittää olevansa. Toki, toki, hän kertoo hyviä \"\n\"tarinoita... jotkut niistä ovat todella pelottavia tai hauskoja... mutta \"\n\"luulen, että hän tietää enemmän kuin hän itse tietää tietävänsä.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Vanha kunnon Griswold. Rakastan häntä kuin veljeä! Taistelimme \"\n\"yhdessä, kun... me... Lazarus... Lazarus... Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, pidän Pepinistä. Hän todella yrittää, tiedätkö. Kuuntele, sinun \"\n\"pitäisi tutustua häneen. Sellainen hyvä kaveri, jota ihmiset aina haluavat \"\n\"auttaa. Hei, se taitaa olla vähän kuin sinä. Minäkin olin sankari...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt on poika, jolla on enemmän ongelmia kuin minulla, ja minä tiedän \"\n\"ongelmista kaiken. Kuuntele nyt - sillä pojalla on hyvä tilanne, mutta hän \"\n\"on kokenut paljon, tiedätkö? Menettänyt jalan! Pitää kävellä puupalan \"\n\"päällä. Se on todella surullista.\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden on kaupungin paras mies. En usko, että hänen vaimonsa pitää minusta \"\n\"kovin paljon, mutta niin kauan kuin hän jatkaa tynnyrien avaamista, pidän \"\n\"hänestä oikein paljon. Tuntuu siltä, että olen viettänyt enemmän aikaa \"\n\"Ogdenin kanssa kuin useimmat muut, mutta hän on niin ystävällinen minulle...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Haluan kertoa sinulle jotain, koska tiedän kaiken tästä asiasta. Se on \"\n\"erikoisalaani. Tämä tässä on parasta... parasta! Se toinen olut ei ole hyvä, \"\n\"niiden tyhmien koirien takia...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Kukaan ei koskaan kuuntele minua. Jossain – en ole ihan varma missä – mutta \"\n\"jossain kirkon alla on iso kasa kultaa. Se kimaltelee ja loistaa ja odottaa \"\n\"noutajaansa.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Tiedän, että sinulla on omat ajatuksesi, ja tiedän, että et usko tätä, mutta \"\n\"se ase, joka sinulla on, siitä ei ole mitään hyötyä noita isoja raakalaisia \"\n\"vastaan! En välitä siitä, mitä Griswold sanoo, he eivät osaa tehdä mitään \"\n\"sellaista kuin ennen vanhaan...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Jos olisin sinä... en ole, mutta jos olisin, myisin kaikki tavarasi ja \"\n\"lähtisin täältä. Tuo poika tuolla... Hänellä on aina jotain hyvää, mutta \"\n\"sinun on annettava hänelle kultaa, muuten hän ei edes näytä sinulle, mitä \"\n\"hänellä on.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Aistin sielun, joka etsii vastauksia...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Viisaus ansaitaan, sitä ei anneta. Jos löydät tietojen aarrearkun, ahmi sen \"\n\"sanat. Jos sinulla on jo tietoa kirjassa kuvatuista salaperäisistä \"\n\"mysteereistä, muista, että mestaruuden taso voi aina nousta.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Suurin voima on usein lyhytikäisin. Saatat löytää muinaisia voimasanoja \"\n\"kirjoitettuina pergamenttikääröihin. Näiden kääröjen vahvuus piilee siinä, \"\n\"että sekä oppipoika että mestari voivat käyttää niitä yhtä taitavasti. \"\n\"Niiden heikkous on, että ne on ensin luettava ääneen, eikä niitä voi pitää \"\n\"valmiina mielessä. Huomaa myös, että näitä kääröjä voi lukea vain kerran, \"\n\"joten käytä niitä varovasti.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Vaikka auringon lämpö on mittaamaton, pelkkä kynttilän liekki on suurempi \"\n\"vaara. Mitään energiaa, riippumatta sen suuruudesta, ei voi käyttää ilman \"\n\"asianmukaista keskittymistä. Monissa loitsuissa lumotut sauvat voidaan \"\n\"ladata useita kertoja maagisella energialla. Minulla on kyky palauttaa \"\n\"niiden voima, mutta tiedän, että mikään ei tapahdu ilman hintaa.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Tietomme on sen kansan summa. Jos löydät kirjan tai käärön, jota et osaa \"\n\"tulkita, tuo se minulle. Jos pystyn ymmärtämään sen, jaan löydökseni \"\n\"kanssasi.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Miehelle, joka tuntee vain rautaa, ei ole suurempaa taikaa kuin teräs. Seppä \"\n\"Griswold on enemmän velho kuin hän itse tietää. Hänen kykynsä yhdistää tuli \"\n\"ja metalli on vertaansa vailla tässä maassa.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Korruptiolla on petoksen voima, mutta viattomuudella on puhtauden voima. \"\n\"Nuori nainen Gillian on sydämeltään puhdas ja asettaa matriarkan tarpeet \"\n\"omien tarpeidensa edelle. Hän pelkää minua, mutta se johtuu vain siitä, että \"\n\"hän ei ymmärrä minua.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Pimeässä avattu arkku ei sisällä suurempaa aarretta kuin valossa avattu \"\n\"arkku. Tarinankertoja Cain on arvoitus, mutta vain niille, jotka eivät \"\n\"katso. Hänen tietonsa katedraalin alla olevasta on paljon suurempi kuin hän \"\n\"itse edes uskaltaa tajuta.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Mitä enemmän uskot yhteen ihmiseen, sitä syvemmälle se voi pudota. Farnham \"\n\"on menettänyt sielunsa, mutta ei minkään demonin vuoksi. Se katosi, kun hän \"\n\"näki arkkipiispa Lazaruksen pettävän hänen kaupunkilaisensa. Hänellä on \"\n\"tietoa, jota voi hyödyntää, mutta sinun on erotettava faktat fantasiasta.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Käsi, sydän ja mieli voivat tehdä ihmeitä, kun ne ovat täydellisessä \"\n\"harmoniassa. Parantaja Pepin näkee kehon sisälle tavalla, johon edes minä en \"\n\"pysty. Hänen kykynsä parantaa sairaita ja loukkaantuneita vahvistuu hänen \"\n\"ymmärryksellään eliksiirien ja taikajuomien valmistuksesta. Hän on yhtä \"\n\"suuri liittolainen kuin sinä Tristramissa.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Tulevaisuudessa on paljon asioita, mitä emme voi nähdä, mutta kun se \"\n\"koittaa, se on lasten käsissä. Pojan Wirtin sielu on pimeä, mutta hän ei ole \"\n\"uhka kaupungille tai sen asukkaille. Hänen salaiset kaupat katulasten ja \"\n\"läheisten kaupunkien salaseurojen kanssa antavat hänelle pääsyn moniin \"\n\"laitteisiin, joita ei ole helppo löytää Tristramista. Vaikka hänen \"\n\"menetelmänsä voivat olla moitittavia, Wirt voi auttaa sinua taistelussa \"\n\"lähestyvää pimeyttä vastaan.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Maanseinät ja olkikatto eivät vielä tee kotia. Majatalonpitäjä Ogdenilla on \"\n\"tässä kaupungissa suurempi merkitys kuin monet ymmärtävät. Hän tarjoaa \"\n\"Gillianille ja hänen äidilleen suojan, ylläpitää sitä, mitä Farnham on \"\n\"hänelle jättänyt, ja tarjoaa kaikille kaupungissa jäljellä oleville ankkurin \"\n\"siihen, mitä Tristram kerran oli. Hänen majatalonsa ja siellä yhä \"\n\"löydettävissä olevat yksinkertaiset nautinnot tarjoavat vilauksen elämästä, \"\n\"jonka ihmiset täällä muistavat. Juuri se muisto ruokkii heidän toiveitaan \"\n\"sinun menestyksestäsi.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Psst… täällä...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Kaikilla Tristramin asukkailla ei ole käyttöä – tai markkinoita – kaikelle, \"\n\"mitä labyrintistä löytyy. Edes minulla ei ole, vaikka se onkin vaikea \"\n\"uskoa.\\n\"\n\" \\n\"\n\"Joskus vain sinä pystyt löytämään tarkoituksen joillekin asioille.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Älä usko kaikkea, mitä juoppo sanoo. Liian monet oluet ovat sumuttaneet \"\n\"hänen näkönsä ja järkensä.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Jos et ole huomannut, en osta mitään Tristramista. Olen laadukkaiden \"\n\"tavaroiden maahantuoja. Jos haluat myydä roskaa, sinun täytyy mennä \"\n\"Griswoldin, Pepinin tai sen noidan, Adrian, luo. Olen varma, että he ostavat \"\n\"kaiken, mitä voit heille tuoda...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Luulen, että olen sepälle velkaa henkeni – sen, mitä siitä on jäljellä. \"\n\"Totta, Griswold tarjosi minulle oppisopimuskoulutusta sepänpajassa, ja hän \"\n\"on mukava kaveri, mutta en koskaan saisi tarpeeksi rahaa... No, sanotaan \"\n\"vain, että minulla on tarkat suunnitelmat, jotka vaativat paljon kultaa.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Jos olisin muutaman vuoden vanhempi, lellisin hänet kaikella rikkaudella, \"\n\"jonka voisin kerätä, ja voin vakuuttaa, että saan käsiini todella hienoja \"\n\"tavaroita. Gillian on kaunis tyttö, jonka pitäisi lähteä Tristramista heti, \"\n\"kun on turvallista. Hmmm... ehkä otan hänet mukaani, kun lähden...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain tietää liikaa. Hän pelottaa minua – jopa enemmän kuin se nainen joen \"\n\"toisella puolella. Hän toistelee minulle, kuinka onnekas olen, että olen \"\n\"elossa, ja kuinka tarinani on ennustettu legendassa. Luulen, että hän on \"\n\"seonnut.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham – siinä on mies, jolla on vakavia ongelmia, ja minä tiedän hyvin, \"\n\"kuinka vakavia ongelmat voivat olla. Hän luotti liikaa yhden miehen \"\n\"rehellisyyteen, ja Lazarus johti hänet kuoleman syliin. Voi, minä tiedän, \"\n\"millaista siellä on, joten älä edes yritä kertoa minulle suunnitelmistasi \"\n\"tuhota pahuus, joka asuu siinä labyrintissä. Varo vain jalkojasi...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Kunhan mitään ei tarvitse kiinnittää uudelleen, vanha Pepin on paras \"\n\"mahdollinen valinta.\\n\"\n\" \\n\"\n\"Jos olisin saanut maistaa hänen keittämiään juomia, jalkani olisi ehkä vielä \"\n\"tallella...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria todella häiritsee minua. Toki, Cain on kammottava siinä, mitä hän voi \"\n\"kertoa sinulle menneisyydestä, mutta tuo noita voi nähdä menneisyyteesi. \"\n\"Hänellä on myös aina jokin keino saada mitä tahansa hän tarvitsee. Adria saa \"\n\"käsiinsä enemmän tavaraa kuin kulkeva Kuningas basaarin porttien läpi Suuren \"\n\"juhlan aikana.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden on hölmö, kun jää tänne. Voisin saada hänet lähtemään pois kaupungista \"\n\"hyvin kohtuulliseen hintaan, mutta hän haluaa ehdottomasti jatkaa sen \"\n\"typerän tavernan pyörittämistä. Ainakin hän tarjoaa Gillianille työpaikan, \"\n\"ja hänen vaimonsa Garda tekee todella erinomaisen paistettua lihapiirakkaa...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Sankarien salin takana sijaitsee Luukammio. Ikuinen kuolema odottaa kaikkia, \"\n\"jotka yrittävät varastaa tämän huoneen aarteita. Niin sanoo Kauhun Herra, ja \"\n\"niin on kirjoitettu.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"Lukittuna Veren portin ja Tulen salin takana, Valor-haarniska odottaa \"\n\"sankarin heräämistä...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Näen sen, mitä sinä et näe.\\n\"\n\"Näkö sumenee, silmät mätänevät.\\n\"\n\"Kun käännyt, ne ovat poissa,\\n\"\n\"kuiskaten salattua lauluaan.\\n\"\n\"Sitten näet sen, mitä ei voi olla,\\n\"\n\"varjot liikkuvat siellä, missä valon pitäisi olla.\\n\"\n\"Pimeydestä, mielestä,\\n\"\n\"heitetty alas sokeiden saliin.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Helvetin asevarastot ovat Verisoturin koti. Hänen jälkeensä jäävät tuhansien \"\n\"silvotut ruumiit. Enkelit ja ihmiset ovat joutuneet hänen loputtomien \"\n\"uhraustensa kohteeksi pimeyden voimille, jotka huutavat yhtä asiaa: verta.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Ottakaa neuvosta vaari ja todistakaa tämän kirjan sisältämät totuudet, sillä \"\n\"ne ovat Horadrimin viimeinen perintö. Tälläkin hetkellä raivoaa sota, \"\n\"kaukana meidän tuntemistamme maista – utopististen Korkeiden Taivaiden \"\n\"valtakuntien ja kaoottisten Palavien Helvetin kuilujen välillä. Tätä sotaa \"\n\"kutsutaan Suureksi konfliktiksi, ja se on raivonnut ja palanut kauemmin kuin \"\n\"mikään tähti taivaalla. Kumpikaan osapuoli ei koskaan saa pitkäaikaista \"\n\"valtaa, sillä valon ja pimeyden voimat kilpailevat jatkuvasti koko \"\n\"luomakunnan hallitsemisesta.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Ottakaa neuvosta vaari ja todistakaa tämän kirjan sisältämät totuudet, sillä \"\n\"ne ovat Horadrimin viimeinen perintö. Kun korkeiden taivaiden ja palavien \"\n\"helvetin ikuinen konflikti leviää kuolevaisten maalle, sitä kutsutaan synnin \"\n\"sodaksi. Enkelit ja demonit kulkevat ihmisten joukossa naamioituneina ja \"\n\"taistelevat salaa, kaukana kuolevaisten uteliaista katseista. Jotkut \"\n\"rohkeat, voimakkaat kuolevaiset ovat jopa liittoutuneet jommankumman puolen \"\n\"kanssa ja auttaneet sanelemaan synnin sodan kulun.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Ottakaa neuvosta vaari ja todistakaa tämän kirjan sisältämät totuudet, sillä \"\n\"ne ovat Horadrimin viimeinen perintö. Lähes kolmesataa vuotta sitten tuli \"\n\"tietoon, että Palavan Helvetin kolme suurta pahuutta olivat mystisesti \"\n\"saapuneet maailmaamme. Kolme veljestä tuhosivat itäisiä maita vuosikymmenten \"\n\"ajan, ja ihmiskunta jäi vapisemaan heidän jälkeensä. Meidän ritarikuntamme – \"\n\"Horadrim – perustettiin salaperäisten magien toimesta, jotta he voisivat \"\n\"metsästää ja vangita Kolme Pahuutta lopullisesti.\\n\"\n\" \\n\"\n\"Alkuperäinen Horadrim vangitsi kaksi Kolmesta voimakkaisiin esineisiin, \"\n\"joita kutsutaan Sielukiviksi, ja hautasi ne syvälle aution itäisen aavikon \"\n\"hiekkaan. Kolmas Pahuus pakeni vangitsemista ja pakeni länteen, ja monet \"\n\"Horadrimista lähtivät sen perään. Kolmas pahuus – tunnetaan nimellä Diablo, \"\n\"kauhun herra, joka vangittiin lopulta, ja sen olemus suljettiin sielukiveen \"\n\"ja haudattiin tähän labyrinttiin.\\n\"\n\" \\n\"\n\"Varo, sielukiviä ei saa paljastaa niille, jotka eivät ole uskovaisia. Jos \"\n\"Diablo vapautuisi, hän etsisi helposti hallittavaa ruumista, koska hän olisi \"\n\"hyvin heikko – ehkä vanhan miehen tai lapsen ruumista.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Niinpä Palavassa Helvetissä tapahtui suuri vallankumous, joka tunnetaan \"\n\"nimellä Pimeä Karkoitus. Pienemmät paholaiset kukistivat kolme suurta \"\n\"paholaista ja karkottivat heidän henkimuotonsa kuolevaisten maailmaan. \"\n\"Demonit Belial (valheiden herra) ja Azmodan (synnin herra) taistelivat \"\n\"helvetin hallitsemisesta kolmen veljeksen poissa ollessa. Koko helvetti \"\n\"jakautui Belialin ja Azmodanin ryhmittymiin, kun taas korkeiden taivaiden \"\n\"joukot pommittivat jatkuvasti helvetin portteja.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Monet demonit matkustivat kuolevaisten maailmaan etsimään Kolmea Veljestä. \"\n\"Näitä demoneja seurasivat kuolevaisten maailmaan enkelit, jotka jahtasivat \"\n\"niitä itäisten suurkaupunkien halki. Enkelit liittoutuivat salaisen \"\n\"kuolevaisten maagien järjestön, Horadrimin, kanssa, joka oppi nopeasti \"\n\"demonien metsästämisen salat. He saivat myös monia pimeitä vihollisia \"\n\"alamaailmasta.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Niinpä kolme suurta pahuutta karkotettiin henkimuodossa kuolevaisten \"\n\"maailmaan, ja levitettyään kaaosta idässä vuosikymmenten ajan ne joutuivat \"\n\"kirottujen kuolevaisten Horadrim-ritarikunnan jahtaamiksi. Horadrim käytti \"\n\"sielukiviä hillitsemään vihamielisyyden herran Mephiston ja hänen veljensä \"\n\"tuhon herran Baalin olemusta. Nuorin veli, kauhun herra Diablo, pakeni \"\n\"länteen.\\n\"\n\" \\n\"\n\"Lopulta Horadrim vangitsi myös Diablon sielukiveen ja hautasi hänet \"\n\"muinaisen, unohdetun katedraalin alle. Siellä kauhun herra nukkuu ja odottaa \"\n\"uudelleensyntymänsä hetkeä. Tietäkää, että hän etsii nuoren ja voimakkaan \"\n\"ruumiin, joka on viaton ja helposti hallittavissa. Sitten hän nousee \"\n\"vapauttamaan veljensä ja sytyttämään jälleen synnin sodan liekit...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Kaikki ylistys Diablolle – kauhun herralle ja pimeän karkoituksen \"\n\"selviytyjälle. Kun hän heräsi pitkästä unestaan, herrani ja mestarini kertoi \"\n\"minulle salaisuuksia, joita harvat kuolevaiset tietävät. Hän kertoi minulle, \"\n\"että korkeiden taivaiden valtakunnat ja palavien helvetin kuilut ovat \"\n\"ikuisessa sodassa. Hän valjasti voimat, jotka ovat tuoneet tämän riidan \"\n\"ihmisten valtakuntiin. Herrani on nimennyt tämän maailman ja kaikkien täällä \"\n\"elävien taistelun synnin sodaksi.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Kunnia ja kiitos Diablolle – kauhun herralle ja kolmesta veljeksestä \"\n\"johtajain. Herrani kertoi minulle kahdesta veljestään, Mephistosta ja \"\n\"Baalista, jotka karkotettiin kauan sitten tähän maailmaan. Herrani haluaa \"\n\"odottaa oikeaa hetkeä ja kerätä voimansa, jotta hän voi vapauttaa vangitut \"\n\"veljensä haudoistaan idän hiekkojen alta. Kun herrani vapauttaa veljensä, \"\n\"synninsota kokee jälleen kolmen veljeksen raivon.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Ylistys ja uhraus Diablolle – kauhun herralle ja sielujen tuhoajalle. Kun \"\n\"herätin mestarini unesta, hän yritti ottaa haltuunsa kuolevaisen ruumiin. \"\n\"Diablo yritti vallata kuningas Leoricin ruumiin, mutta mestarini oli liian \"\n\"heikko. Herrani tarvitsi yksinkertaisen ja viattoman ankkurin tähän \"\n\"maailmaan, ja löysi pojan nimeltä Albrecht, joka oli täydellinen tähän \"\n\"tehtävään. Kun hyvä kuningas Leoric tuli hulluksi Diablon epäonnistuneen \"\n\"riivauksen jälkeen, sieppasin hänen poikansa Albrechtin ja toin hänet \"\n\"mestarini eteen. Odotan nyt Diablon kutsua ja rukoilen, että saan palkkioni, \"\n\"kun hän vihdoin nousee tämän maailman herraksi.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Onneksi olet palannut!\\n\"\n\"Paljon on muuttunut sen jälkeen, kun asuit täällä, ystäväni. Kaikki oli \"\n\"rauhallista, kunnes pimeyden ratsastajat saapuivat ja tuhosivat kylämme. \"\n\"Monet surmattiin paikan päällä, ja ne, jotka tarttuivat aseisiin, tapettiin \"\n\"tai raahattiin pois orjiksi – tai pahempaa. Kylän laidalla oleva kirkko on \"\n\"häväisty ja sitä käytetään pimeisiin rituaaleihin. Yöllä kaikuvat huudot \"\n\"ovat epäinhimillisiä, mutta osa kyläläisistämme saattaa vielä olla hengissä. \"\n\"Seuraa polkua, joka kulkee tavernani ja sepän pajan välissä, niin löydät \"\n\"kirkon ja voit pelastaa ne, jotka voit.\\n\"\n\" \\n\"\n\"Ehkä voin kertoa sinulle lisää, jos puhumme uudelleen. Onnea matkaan.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Jatka etsintääsi. Kadonneen aarteen löytäminen ei ole helppoa. Piilotetun \"\n\"aarteen löytäminen on vielä vaikeampaa. Jätän sinulle tämän vinkin: älä anna \"\n\"ajan kulun hämmentää etsintääsi.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Mitä?!  Tämä on hölynpölyä.  Tristramiin ei ole haudattu aarteita.  Anna \"\n\"minun katsoa sitä!  Ah, katso, nämä piirustukset ovat epätarkkoja.  Ne eivät \"\n\"vastaa lainkaan kaupunkiamme.  Keskittyisin mieluummin siihen, mitä \"\n\"katedraalin alla on, eikä siihen, mitä maaperän alla on.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Minulla ei todellakaan ole aikaa keskustella jostain kartasta, jota etsit.  \"\n\"Minulla on paljon sairaita ihmisiä, jotka tarvitsevat minun ja sinun apuasi.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Aikaisemmin ylpeä Iswall on vangittuna syvällä tämän maailman pinnan alla.  \"\n\"Hänen kunniansa on riistetty ja hänen ulkonäkönsä muuttunut.  Hän on \"\n\"vangittuna ikuiseen piinaan.  Hänen tehtävänään on salata se, mikä voisi \"\n\"vapauttaa hänet.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Veikkaan, että Wirt näki sinun tulevan ja esitti vain, jotta voisi myöhemmin \"\n\"nauraa sinulle, kun juoksit ympäri kaupunkia pää kolmantena jalkana.  En \"\n\"välittäisi siitä.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Aikaisemmin tämä kaupunki oli suosittu pysähdyspaikka kaukaa tuleville \"\n\"matkailijoille.  Siitä lähtien asiat ovat muuttuneet.  Mutta piilotetut \"\n\"luolat ja haudatut aarteet ovat yleisiä lasten fantasioita.  Wirt harvoin \"\n\"harrastaa nuorekkaita leikkejä.  Joten se voi olla vain hänen \"\n\"mielikuvitustaan.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Kuuntele. Tule lähemmäs. En tiedä, tiedätkö mitä minä tiedän, mutta sinulla \"\n\"on jotain todella arvokasta. Se on kartta.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Isoäitini kertoo minulle usein tarinoita kirkkoa ympäröivällä hautausmaalla \"\n\"asuvista oudoista voimista.  Yksi niistä saattaa kiinnostaa sinuakin.  Hän \"\n\"sanoi, että jos jätät hautausmaalle asianmukaisen uhrilahjan, menet \"\n\"katedraaliin rukoilemaan kuolleiden puolesta ja palaat sitten takaisin, \"\n\"uhrilahja on muuttunut jollain oudolla tavalla.  En tiedä, onko tämä vain \"\n\"vanhan sairaan naisen puhetta, mutta nykyään kaikki tuntuu mahdolliselta.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Hmmm.  Valtava ja salaperäinen aarre, vai?  Mmmm.  Ehkä voisin olla \"\n\"kiinnostunut ostamaan muutaman asian sinulta.  Tai vielä parempi, etkö \"\n\"tarvitsisi joitakin harvinaisia ja kalliita tarvikkeita selviytyäksesi tästä \"\n\"koettelemuksesta?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Sinä olet siis se sankari, josta kaikki puhuvat. Voisitko auttaa köyhää, \"\n\"maanviljelijää pääsemään ojasta allikkoon? Hedelmätarhani reunalla, hieman \"\n\"etelämpänä, maasta nousee kauhea olio! En pääse viljelyksilleni tai \"\n\"heinäpaaleilleni, ja lehmä parkani kuolevat nälkään. Noita antoi tämän \"\n\"minulle ja sanoi, että se räjäyttäisi sen otuksen pois pelloltani. Jos \"\n\"voisit tuhota sen, olisin ikuisesti kiitollinen. Tekisin sen itse, mutta \"\n\"jonkun on jäätävä tänne lehmien luo...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Tiesin, että se ei voinut olla niin yksinkertaista kuin noita antoi \"\n\"ymmärtää. On surullista, kun ei voi luottaa edes naapureihinsa.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Onko se kadonnut? Lähetitkö sen takaisin sen synnyttäneeseen Hadesin pimeään \"\n\"syövereen? Mitä? Älä sano, että kadotit sen! Ne eivät ole halpoja, tiedätkö. \"\n\"Sinun on löydettävä se ja sitten hävitettävä se kauheus kaupungistamme.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Kuulin räjähdyksen täältä asti! Paljon kiitoksia, muukalainen. Maasta \"\n\"nousevat olennot, kirkkoa valtaavat hirviöt ja muut vastaavat asiat tekevät \"\n\"näistä vaikeita aikoja. Olen vain köyhä maanviljelijä, mutta tässä – ota \"\n\"tämä kiitollisuuteni lahjana.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Voi, minulla on niin paljon ongelmia... ehkä... Ei, en voi vaatia sinulta \"\n\"sitä, kun sinulla on jo niin paljon muuta ajateltavaa. Ehkä kun olet \"\n\"puhdistanut kirkon noista olennoista, voisit palata... ja piipahtaa ja \"\n\"auttaa köyhää maanviljelijää?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Waaaah! (niisk) Waaaah! (niisk)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Kadotin Teron! Kadotin parhaan ystäväni! Leikimme joen rannalla, ja Tero \"\n\"sanoi haluavansa mennä katsomaan isoa vihreää juttua. Sanoin, että meidän ei \"\n\"pitäisi mennä, mutta hiivimme sinne, ja yhtäkkiä tämä HYÖNTEINEN ilmestyi! \"\n\"Juoksimme karkuun, mutta Tero kaatui, ja hyönteinen TARTTUI häneen ja vei \"\n\"hänet pois!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Löysitkö hänet?  Sinun täytyy löytää Tero, ole kiltti!  Hän on niin pieni.  \"\n\"Hän ei osaa huolehtia itsestään!  Ole kiltti!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Löysit hänet! Löysit hänet! Kiitos! Voi Tero, pelottivatko ne ilkeät ötökät \"\n\"sinua? Hei! Yök! Sinun turkkiisi on tarttunut jotain! Yök! Tule, Tero, \"\n\"mennään kotiin! Kiitos vielä kerran!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Olemme pitkään olleet horroksessa, ja nyt on tullut aika herätä. Pitkän unen \"\n\"jälkeen olemme nälkäisiä. Pian, me syömme...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Oletko nauttinut olostasi, pikku nisäkäs? Kuinka säälittävää. Pieni \"\n\"maailmasi ei ole minkäänlainen haaste.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Nämä maat saastuvat, ja jälkeläisemme valtaavat pellot, joita ihmiset \"\n\"kutsuvat kodikseen.  Vartemme kietoutuvat tämän maailman ympärille, ja me \"\n\"syömme sen asukkaiden lihaa.  Ihmiset tulevat olemaan omaisuuttamme ja \"\n\"ravintomme.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, haistan sinut... olet lähellä! Lähellä! Ssss... veren ja pelon tuoksu... \"\n\"kuinka houkuttelevaa...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Ja Kultaisen Valon vuonna määrättiin, että suuri katedraali \"\n\"rakennettaisiin.  Tämän pyhän paikan kulmakivi oli tarkoitus veistää \"\n\"läpikuultavasta Antyrael-kivestä, joka oli nimetty enkelin mukaan, joka \"\n\"jakoi voimansa Horadrimin kanssa.  \\n\"\n\" \\n\"\n\"Varjojen vuodenaikana maa järisi ja katedraali romahti ja tuhoutui. Kun \"\n\"katakombien ja linnojen rakentaminen alkoi ja ihmiset vastustivat Synnin \"\n\"sodan tuhoja, raunioista kerättiin kiviä. Ja niin kulmakivi katosi ihmisten \"\n\"silmistä. \\n\"\n\" \\n\"\n\"Kivi oli tästä maailmasta – ja kaikista maailmoista – kuten Valo on sekä \"\n\"kaikessa että kaiken yläpuolella. Valo ja ykseys ovat tämän pyhän perustan \"\n\"tuotteita, tarkoituksen ykseys ja omistuksen ykseys.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Sanoin, \\\"Muu\\\".\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Kuules olen vain lehmä, Okei?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Hyvä on, hyvä on.  En ole oikeasti lehmä. En yleensä kulje ympäriinsä \"\n\"tällaisena, mutta istuin kotona omissa oloissani, kun yhtäkkiä lattian alta \"\n\"alkoi tulla esiin hyönteisiä, köynnöksiä, sipuleita ja muuta... Se oli \"\n\"kauheaa! Jos minulla olisi jotain normaalia päällepantavaa, se ei olisi niin \"\n\"paha.  Hei! Voisitko mennä takaisin kotiini ja hakea minulle puvun? Ruskean, \"\n\"ei harmaan, se on iltapuku. Tekisin sen itse, mutta en halua kenenkään \"\n\"näkevän minua tällaisena. Tässä, ota tämä, saatat tarvita sitä... tappamaan \"\n\"ne otukset, jotka ovat kasvaneet kaikkialle.  Et voi olla huomaamatta \"\n\"taloani, se on joen haaran eteläpuolella... tiedätkö... se, jossa on \"\n\"kasvanut umpeen kasvimaa.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Miksi tuhlaat aikaa?  Hae pukuni!  Ja nopeasti!  Tuo holstein iskee minulle \"\n\"silmää!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hei, onko sinulla minun pukuni?  Anna se nopeasti tänne!  Korvat kutisevat \"\n\"uskomattoman paljon!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Ei, ei, ei, ei!  Tämä on minun HARMAA pukuni!  Se on iltapuku!  Virallisiin \"\n\"tilaisuuksiin!  En voi pukeutua TÄHÄN.  Mikä sinä olet, joku outo tyyppi?  \"\n\"Tarvitsen RUSKEAN puvun.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, nyt on paljon parempi.  Vihdoinkin vähän arvokkuutta!  Ovatko sarveni \"\n\"suorassa?  Hyvä.  Kiitos paljon avusta.  Ota tämä lahjaksi, ja... pieni \"\n\"muotivinkki... sinulle voisi olla hyötyä... sinulle voisi olla hyötyä \"\n\"uudesta... jos tiedät mitä tarkoitan? Koko seikkailijateema on niin... \"\n\"retro. Vain pieni neuvo, eikö? Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Kuule.  Minä olen lehmä.  Ja sinä olet hirviöiden syötti. Hanki vähän \"\n\"kokemusta!  Puhutaan sitten...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Se on varmasti todella pelottava tehtävä, jonka olen sinulle antanut. Jos \"\n\"vain olisi jokin keino, jolla voisin... auttaisiko pullo hyvää, tuoretta \"\n\"maitoa?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Apusi olisi tarpeen, mutta ehkä sen jälkeen, kun olet pelastanut katakombit \"\n\"noiden petojen häpäisyltä.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Minulla yksi asia joka pitäisi tehdä, mutta en voinut vaatia sitä täysin \"\n\"tuntemattomalta henkilöltä. Ehkä kun olet ollut täällä jonkin aikaa, voin \"\n\"pyytää sinulta palvelusta helpommin.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Näen sinussa potentiaalia suuruuteen.  Ehkä joskus, kun olet täyttämässä \"\n\"kohtaloasi, voisit poiketa käymään ja tehdä minulle pienen palveluksen?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Luulen, että voisit auttaa minua, mutta ehkä vasta, kun olet saanut hieman \"\n\"lisää voimaa. En haluaisi vaarantaa kylän ainoaa mahdollisuutta tuhota \"\n\"kirkossa oleva uhka!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Minä olen itseoppinut lehmä. Tee itsestäsi jotain, ja sitten voimme puhua.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Minun ei tarvitse selitellä itseäni jokaiselle ohikulkevalle turistille!  \"\n\"Eikö sinulla ole hirviöitä tapettavana?  Ehkä puhumme myöhemmin.  Jos jäät \"\n\"henkiin...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Älä kiusaa minua. Etsin todella sankarillista henkilöä. Etkä sinä ole \"\n\"sellainen. En voi luottaa sinuun, sinut syödään pian hirviöiden toimesta... \"\n\"Tarvitsen kokeneen sankarin.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Hyvä on, lopetan höpötyksen.  En tarkoittanut johtaa sinua harhaan.  Istuin \"\n\"kotona, olin huonolla tuulella, kun tilanne muuttui todella epävakaaksi; \"\n\"lattialta tuli esiin kokonainen hirviöiden lauma!  Minä vain pelästyin.  \"\n\"Minulla sattui olemaan tämä paita päällä, kun juoksin ulos ovesta, ja nyt \"\n\"näytän täysin naurettavalta.  Jos minulla olisi jotain normaalia päällä, se \"\n\"ei olisi niin paha.  Hei!  Voitko mennä takaisin kotiini ja hakea minulle \"\n\"puvun?  Ruskean, ei harmaata, se on iltapuku.  Tekisin sen itse, mutta en \"\n\"halua kenenkään näkevän minua tällaisena.  Ota tämä, saatat tarvita sitä... \"\n\"tappamaan ne otukset, jotka ovat kasvaneet kaikkialle.  Et voi olla \"\n\"huomaamatta taloani, se on joen haaran eteläpuolella... tiedätkö... se, \"\n\"jossa on kasvanut kasvimaa.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Olen kokeillut loitsuja, uhkauksia, kirouksia ja neuvotteluja tämän ilkeän \"\n\"olennon kanssa – turhaan.  Menetelmäni alempien demonien orjuuttamiseksi \"\n\"eivät näytä vaikuttavan tähän pelottavaan petoon.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Kotini on vähitellen turmeltumassa tämän ei-toivotun vangin iljettömyyden \"\n\"vuoksi.  Hautaholvit ovat täynnä varjoja, jotka liikkuvat juuri näkökentän \"\n\"reunalla.  Heikko kynsien raapiminen tanssii kuuloni rajalla. Luulen, että \"\n\"ne etsivät tätä päiväkirjaa.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Rauhoittumattomassa tilassaan olento on paljastanut nimensä – Na-Krul.  Olen \"\n\"yrittänyt tutkia nimeä, mutta pienemmät demonit ovat jotenkin tuhonneet \"\n\"kirjastoni.  Na-Krul... Nimi täyttää minut kylmällä pelolla.  Mieluummin \"\n\"ajattelen sitä vain Olentona kuin pohdin sen oikeaa nimeä.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Loukkuun jääneen olennon raivoiset ulvonnat estävät minua saamasta kaivattua \"\n\"unta. Se raivoaa sitä vastaan, joka lähetti sen Tyhjyyteen, ja kiroaa minua, \"\n\"koska vangitsin sen tänne. Sen sanat täyttävät sydämeni kauhulla, mutta en \"\n\"pysty sulkemaan sen ääntä pois mielestäni.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Aikani on nopeasti loppumassa.  Minun on kirjattava muistiin keinot demonin \"\n\"heikentämiseksi ja piilotettava sitten teksti, jotta hänen kätyrinsä eivät \"\n\"löydä keinoa käyttää tietojani vapauttaakseen herraansa.  Toivon, että kuka \"\n\"tahansa tämän päiväkirjan löytää, etsii tietoa.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Kuka tahansa tämän käärön löytää, on velvollinen pysäyttämään näiden muurien \"\n\"sisällä piilevän demonisen olennon.  Aikani on ohi. Juuri nytkin sen \"\n\"helvetilliset kätyrit raapivat heikkoa ovea, jonka takana piilottelen.  \\n\"\n\" \\n\"\n\"Olen lamauttanut demonin salaperäisellä taikuudella ja sulkenut sen suurten \"\n\"muurien sisään, mutta pelkään, että se ei riitä.\\n\"\n\" \\n\"\n\"Kolmesta grimoiristani löytyvät loitsut suojaavat sinua hänen valtakuntaansa \"\n\"astuessasi, mutta vain jos ne lausutaan oikeassa järjestyksessä.  \"\n\"Sisäänkäynnin vivut poistavat esteet ja vapauttavat demonin; älä kosketa \"\n\"niitä!  Käytä vain näitä loitsuja päästäksesi sisään, tai hänen voimansa voi \"\n\"olla liian suuri sinulle voitettavaksi.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"Pyhässä Hengessä.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Ennustettu vapaa-aika.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Tuon kuoleman vihollisena.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Manalankarju\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Piikittäjä\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Mielensilmä\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Hämähäkkipeto\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Kammokaksipää\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Hork-sikiö\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Myrkkypyrstö\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Nekromörssi\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Hämähäkki Kuningas\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Ruoskamato\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Tulivihto\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Helvetin ötökkä\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Haudankaivaja\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Hautarotta\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Tulilepakko\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Kallosiipi\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Kuolomaagi\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Kryptademoni\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Helvetin lepakko\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Luu Demoni\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Arkki Kuolomaagi\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biklootti\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Lihamöhkäle\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Niittäjä\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Jättiläisen Rystynen\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Häilyvä sormus\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Xiorin sormus\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Karik:n sormus\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Magman sormus\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Mystikoiden sormus\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Ukkosen sormus\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Suojelun amuletti\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Hyttysenpisto\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Flambeau\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Synkkyyden haarniska\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Blitzen\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Ukkosjyrähdys\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Sielujensyöjä\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Timanttiterä\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Luuhaarniska\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Demonihaarniska\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Noviisin amuletti\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Gladiattorien areena\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Narrin\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Kiteinen\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Kaksoisolennot\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"murskaus\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"kuihtua\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"uhka\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"magin siunaus\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"narrin temppu\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Salama seinä\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Pätsin nousu\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Teleportti\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Heijastus\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Raivo\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Tulen Sormus\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Paljastus\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Tulen Riimu\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Valon Riimu\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Novan Riimu\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Tuliroihun Riimu\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Kiven Riimu\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n"
  },
  {
    "path": "Translations/fr.po",
    "content": "# Translation of DevilutionX to French\n# Mathieu Maret <mathieu.maret@gmail.com>, 2021.\n# @Phalcon22, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Mathieu Maret <mathieu.maret@gmail.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: fr\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Design du jeu\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Designers Seniors\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Design Additionnel\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Programmeur Principal\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Programmeurs Seniors\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programmation\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Invités Spéciaux Programmeurs\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Programmeur Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Programmeur Communication Sénior\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Programmation de l'installateur\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Directeurs Artistiques\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Illustration\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Illustration Technique\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Directeurs Artistiques Cinématographiques\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"Artwork 3D Cinématique\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Illustration Technique Cinématographique\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Producteur exécutif\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Producteur\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Producteur Associé\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Equipe d'intervention Diablo\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Musique\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Conception Sonore\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Musique & Son des Cinématiques\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Production, Réalisation et Casting des Voix\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Scénario & Histoire\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Montage des Voix\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Voix\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Ingénieur d'Enregistrement\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Conception et Mise en page du Manuel\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Illustration du Manuel\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Directeur Provisoire d'Assurance-Qualité (Testeur en Chef)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Équipe de Testeurs Assurance-Qualité (QA)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Équipe Spéciale Compatibilité de Testeurs Assurance-Qualité (QA)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Support Additionnel de Testeurs Assurance-Qualité (QA) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Contre-Espionnage Assurance-Qualité (QA)\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Ordre des Services d'informations réseaux\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Support Client\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Ventes\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Choristes de Mr. Dabiri\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Relations Publiques\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Ventes Internationales\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Ventes U.S.\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Manufacturing\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Juridique & Affaires\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Remerciements Spéciaux à\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Remerciements à\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"À la mémoire de\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Remerciements tout particuliers à\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Manager Général\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Ingénieurs Logiciel\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Directeur Artistique\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Artistes\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Conception\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Conception sonore, Effets Audio et Ingénierie Audio\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Responsable Assurance Qualité\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testeurs\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Manuel\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tTravaux Additionnels\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Écriture des Textes de Quête\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Remerciements à\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tRemerciements particuliers à Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Responsable Assurance-Qualité\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Testeur en Chef Assurance-Qualité\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Testeurs Principaux\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Testeurs Supplémentaires\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Responsable Marketing Produit\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Responsable des Relations Publiques\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Chef de Produit Associé\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"L'Anneau des Mille\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tAucune âme n'a été vendue durant le développement de ce jeu.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Choisissez la classe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Annuler\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Nouveau Héros Multijoueur\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Nouveau Héros Solo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Une Partie Existe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Charger Partie\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Nouvelle Partie\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Personnages Solo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"La Rogue et le Sorcier ne sont disponibles que dans la version commerciale \"\n\"complète de Diablo. Visitez https://www.gog.com/game/diablo pour l'acheter.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Entrez le Nom\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Nom incorrect. Un nom ne peut pas contenir d'espaces, de caractères réservés \"\n\"ou de mots réservés.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Impossible de créer le personnage.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Niveau :\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Force :\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magie :\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Dextérité :\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalité :\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Sauvegarder :\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Sélectionnez un Héros\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Nouveau Héros\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Effacer\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Personnages Multijoueurs\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Effacer un Personnage Multi\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Effacer un Personnage Solo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Voulez-vous vraiment supprimer le personnage \\\"{:s}\\\" ?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Solo\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Multijoueur\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Paramètres\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Support\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Afficher les crédits\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Quitter Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Quitter Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Client-Serveur (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"Rebouclage (Loopback)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Partie Multijoueur\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Prérequis:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"sans passerelle\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Sélection Connexion\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Changer de Passerelle\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"\"\n\"Tous les ordinateurs doivent être connectés à un réseau compatible TCP.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Tous les ordinateurs doivent être connectés à internet.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Jouez en solo sans connexion à internet.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Joueurs Max : {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"L'hôte utilise un jeu différent du vôtre.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"L'hôte utilise un mode de jeu ({:s}) différent du vôtre.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Votre version {:s} ne correspond pas à celle de l'hôte {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Description:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Sélectionner l'Action\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Créer une Partie\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Créer une Partie Publique\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Rejoindre une Partie\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Parties Publiques\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Chargement...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Rien\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ANNULER\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Créer une nouvelle partie avec le niveau de difficulté de votre choix.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Créer une nouvelle partie, que tout le monde peut rejoindre, avec le niveau \"\n\"de difficulté de votre choix.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Entrez un ID de partie pour rejoindre une partie déjà en cours.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Entrez une adresse IP ou un nom d'hôte pour rejoindre une partie déjà en \"\n\"cours.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Rejoindre une partie publique déjà en cours.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normale\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Cauchemar\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Enfer\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Difficulté : {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Vitesse : Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Vitesse : Rapide\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Vitesse : plus rapide\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Vitesse : Le plus rapide\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Joueurs : \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Sélection Difficulté\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Rejoignez une Partie {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Entrez l'ID de la partie\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Entrez l'adresse\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Difficulté Normale\\n\"\n\"C'est le mode avec lequel un personnage débutant devrait commencer sa quête \"\n\"pour vaincre Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Difficulté Cauchemar\\n\"\n\"Les occupants du Labyrinthe ont été renforcés et se révéleront être un plus \"\n\"grand défi. Ce mode est recommandé uniquement pour les personnages \"\n\"expérimentés.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Difficulté Enfer\\n\"\n\"Les créatures les plus puissantes des bas-fonds rôdent aux portes de \"\n\"l'enfer. Seuls les personnages les plus expérimentés devraient relever ce \"\n\"défi.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Votre personnage doit atteindre le niveau 20 avant de pouvoir entrer dans \"\n\"une partie multijoueur en difficulté Cauchemar.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Votre personnage doit atteindre le niveau 30 avant de pouvoir entrer dans \"\n\"une partie multijoueur en difficulté Enfer.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Sélection Vitesse\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Rapide\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Plus Rapide\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"La Plus Rapide\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Vitesse normale\\n\"\n\"C'est le mode avec lequel un personnage débutant devrait commencer sa quête \"\n\"pour vaincre Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Vitesse rapide\\n\"\n\"Les habitants du Labyrinthe ont été accélérés et s'avéreront être un plus \"\n\"grand défi. Ce mode est recommandé uniquement pour les personnages \"\n\"expérimentés.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Vitesse plus rapide\\n\"\n\"La plupart des monstres du donjon vous chercheront plus vite que jamais. \"\n\"Seul un champion expérimenté devrait tenter sa chance à cette vitesse.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Vitesse la plus rapide\\n\"\n\"Les sbires des souterrains se précipiteront pour attaquer sans hésitation. \"\n\"Seul un vrai démon de vitesse devrait relever ce défi.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Entrez le Mot de passe\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Utiliser Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Passer à Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Oui\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Non\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\n#, fuzzy\n#| msgid \"Press any key to change.\"\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Pressez une touche pour changer.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Touche assignée :\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Pressez une touche pour changer.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Désassigner la touche\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Menu Précédent\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Nous maintenons un serveur de chat sur Discord.gg/devilutionx Suivez ce lien \"\n\"pour rejoindre notre communauté où nous parlons de choses liées à Diablo et \"\n\"à l'extension Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX est développé par Diasurgical. Les problèmes peuvent être \"\n\"signalés à cette adresse: https://github.com/diasurgical/devilutionX Merci \"\n\"de bien vouloir inclure le numéro de version ainsi que le système \"\n\"d'exploitation utilisé afin que nous puissions mieux vous aider.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Avertissement :\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX n'est pas supporté ni maintenu par Blizzard Entertainment, ou \"\n\"GOG.com. Ni Blizzard Entertainment ni GOG.com n'ont testé ou certifié la \"\n\"qualité ou la compatibilité de DevilutionX. Toutes demandes concernant \"\n\"DevilutionX doivent être adressées à Diasurgical et non à Blizzard \"\n\"Entertainment ou GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tCe portage utilise Charis SIL, New Athena Unicode, Unifont et Noto qui \"\n\"sont sous licence SIL Open Font License, ainsi que Twitmoji qui est sous \"\n\"licence CC-BY 4.0. Le portage utilise également la SDL qui est sous licence \"\n\"zlib-license. Voir le fichier ReadMe pour plus de détails.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Droits d'auteur © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Erreur\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Erreur dans : {:s} ligne {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Erreur de fichier de données\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Impossible d'ouvrir l'archive de données principale ({:s}).\\n\"\n\"\\n\"\n\"Assurez-vous qu'elle se trouve dans le dossier du jeu.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Erreur de répertoire en lecture seule\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Impossible d'écrire dans l'emplacement :\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Partie : \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"Rebouclage (Loopback)\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Mot de passe : \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Partie Publique\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Niveau : Nid {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Niveau : Crypte {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Ville\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Niveau : {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Échap\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Entrez\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Profil du Personnage\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Journal des quêtes\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Carte\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Menu Principal\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventaire\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Livre des sorts\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Envoyer un Message\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\n#, fuzzy\n#| msgid \"Description:\"\nmsgid \"Description: \"\nmsgstr \"Description:\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\n#, fuzzy\n#| msgid \"Players: \"\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"Joueurs : \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to buy this item?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Voulez-vous vraiment acheter cet objet ?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\n#, fuzzy\n#| msgid \"Amber\"\nmsgid \"<number>\"\nmsgstr \"d'Ambre\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\n#| msgctxt \"monster\"\n#| msgid \"Flayed One\"\nmsgid \"<player name>\"\nmsgstr \"Écorché\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Joueur Amical\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Joueur Hostile\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Touche : {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Sélection du sort courant\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Touche: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Compétence\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Sort\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Sort Niveau 0 – Inutilisable\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Sort Niveau {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Parchemin: {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Parchemin\"\nmsgstr[1] \"{:d} Parchemins\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Bâton : {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Charge\"\nmsgstr[1] \"{:d} Charges\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} pièce d'or\"\nmsgstr[1] \"{:s} pièces d'or\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Vous n'avez pas les conditions requises\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Niveau: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Dommages {:d} sur {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Clic-droit pour utiliser\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Niveau Supérieur\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Vous avez {:s} pièce d'or. Combien voulez-vous en retirer ?\"\nmsgstr[1] \"Vous avez {:s} pièces d'or. Combien voulez-vous en supprimer ?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Portail de ville\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"de {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portail vers\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"L'Autel Impie\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"level 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Impossible de charger le personnage\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Affiche ce message et quitte\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Affiche le numéro de version et quitte\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Spécifie le dossier de diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Spécifie le dossier des sauvegardes\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Spécifie l'emplacement de diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Saute les vidéos d'intro\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Affiche le nombre d'images par seconde\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Active les logs détaillés\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Enregistrer une démo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Jouer une démo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"\"\n\"Désactiver toutes les limitations d'images pendant la lecture de la démo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Sélection de la Partie :\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Forcer le mode Shareware\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Forcer le mode Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Forcer le mode Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Options Hellfire :\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Signalez les bogues sur https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Échec du chargement des ressources de l'interface (UI).\\n\"\n\"\\n\"\n\"Assurez-vous que devilutionx.mpq soit bien dans le dossier du jeu et à jour.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Timeout réseau--\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- En attente de joueurs --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Pas d'aide disponible\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"dans les magasins\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Objet à la ceinture {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Utiliser l'objet à la ceinture.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Sort Rapide {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Raccourci pour la compétence ou le sort.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Menu Précédent\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Sort Rapide {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Livre rapide\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Ouvrir le Livre rapide.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Sauvegarde rapide\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Sauvegarde la Partie.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Chargement rapide\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Charge la Partie.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Quitter\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Ferme le Jeu.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Arrêter le héros\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Arrêter de marcher et annuler les actions en attente.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Surbrillance des Objets\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Montrer/cacher les objets au sol.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Basculer la surbrillance des objets\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Toujours monter/cacher les objets au sol.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Activer/Désactiver Carte\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Active/Désactive l'affichage de la carte.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Ouvrir l'inventaire.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Personnage\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Ouvrir l'Écran du Personnage.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Journal des quêtes\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Ouvrir le Journal des quêtes.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Livre des sorts\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Ouvrir le livre des sorts.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Message Rapide {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Permet d'envoyer un message rapide dans le chat.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Masquer les Écrans d'informations\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Masquer tous les Écrans d'informations.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Zoom\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Zoom l'écran de jeu.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Mettre le jeu en pause\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Met le jeu en pause.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Mettre le jeu en pause\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Augmenter la Luminosité.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Réduire la Luminosité.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Augmenter la Luminosité.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Augmenter la Luminosité.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Aide\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Ouvrir l'Écran d'Aide.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Capture d'écran\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Prend une capture d'écran.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Info du jeu\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Afficher les infos du jeu.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Journal des Messages\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Affiche l'historique des messages.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Inventaire\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"Sélectionner l'Action\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"Sélectionner l'Action\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"Annuler\"\n\n#: Source/diablo.cpp:2175\n#, fuzzy\n#| msgid \"Closes the game.\"\nmsgid \"Close menus.\"\nmsgstr \"Ferme le Jeu.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"Personnages Multijoueurs\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"Personnages Multijoueurs\"\n\n#: Source/diablo.cpp:2212\n#, fuzzy\n#| msgid \"$Movement:\"\nmsgid \"Move left\"\nmsgstr \"$Mouvement :\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"Personnages Multijoueurs\"\n\n#: Source/diablo.cpp:2218\n#, fuzzy\n#| msgid \"the night\"\nmsgid \"Move right\"\nmsgstr \"de la Nuit\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"Personnages Multijoueurs\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Carte\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\n#, fuzzy\n#| msgid \"The game ended\"\nmsgid \"Toggle game menu\"\nmsgstr \"Le jeu s'est terminé\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Saves the game.\"\nmsgid \"Opens the game menu.\"\nmsgstr \"Sauvegarde la Partie.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"Vague de Flammes\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Pas de multi dans la démo\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Échec à la Création Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Pas disponible dans le shareware\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Pas assez de place pour sauvegarder\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Pas de Pause en ville\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"La copie sur un disque dur est recommandée\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Problème de Synchro Multijoueur\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Pas de pause en multijoueur\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Sauvegarde...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Certains s'affaiblissent tandis que d'autres se renforcent\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Une nouvelle force est forgée par la destruction\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Ceux qui défendent attaquent rarement\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"L'épée de la justice est preste et tranchante\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Pendant que l'esprit est vigilant, le corps s'épanouit\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Les pouvoirs de la mana recentrés se renouvellent\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Le temps ne peut ternir la puissance de l'acier\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"La magie n'est pas toujours ce qu'elle semble être\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Ce qui fut autrefois ouvert est maintenant fermé\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"L'intensité naît au détriment de la sagesse\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Le pouvoir arcanique apporte la destruction\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Ce qui ne peut être tenu ne peut être blessé\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Pourpre et Azur deviennent tels le Soleil\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"La connaissance et la sagesse au détriment de soi\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Bois et rafraîchis-toi\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Où que tu ailles, t'y voilà\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"L'énergie naît au prix de la sagesse\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Les richesses abondent quand on s'y attend le moins\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Là où l'avarice échoue, la patience est récompensée\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Béni par un compagnon bienveillant !\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"La main de l'homme peut être guidée par le destin\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"La force est gonflée par la foi céleste\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"L'essence de la vie sourd de l'intérieur\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Le chemin se fait clair vu d'en haut\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Le salut s'obtient au prix de la sagesse\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Les mystères se révèlent à la lumière de la raison\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Ceux qui sont les derniers peuvent encore être les premiers\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"La générosité apporte ses propres récompenses\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Vous devez avoir au moins le niveau 8 pour l'utiliser.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Vous devez avoir au moins le niveau 13 pour l'utiliser.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Vous devez avoir au moins le niveau 17 pour l'utiliser.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Connaissance des arcanes acquise !\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Ce qui ne tue pas ...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"La connaissance est le pouvoir.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Donne et tu recevras.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Certaine expérience s'acquiert par le toucher.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"On n'est jamais mieux que chez soi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"L'énergie spirituelle est restaurée.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Vous vous sentez plus agile.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Vous vous sentez plus fort.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Vous vous sentez plus sage.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Vous vous sentez rafraîchi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Ce qui peut se briser se brisera.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Cathédrale\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Catacombes\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Grottes\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Nid\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Crypte\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Nv {} – {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"Difficulté {}\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Dans le Menu\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"rebouclage (loopback)\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Impossible de se connecter\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"erreur: 0 octet lu du serveur\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq ou spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Certain MPQs Hellfire sont manquants\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Tous les MPQ Hellfire n'ont pas été trouvés.\\n\"\n\"Veuillez copier tous les fichiers hf*.mpq.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Résolution\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Courir en Ville\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Quêtes de Theo\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Quête de la Vache\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Récupération Auto de l'Or\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Récupération Auto d'Élixir\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\n#| msgid \"Auto Gold Pickup\"\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Récupération Auto de l'Or\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Ramassage auto en ville\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria restaure le mana\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Équipement Auto des Armes\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Équipement Auto des Armures\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Équipement Auto des Heaumes\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Équipement Auto des Boucliers\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Équipement Auto des Bijoux\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Quêtes Aléatoires\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\n#, fuzzy\n#| msgid \"Show mana values\"\nmsgid \"Show Item Labels\"\nmsgstr \"Afficher la quantité de mana\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Remplissage auto de la ceinture\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Désactiver les Sanctuaires avec Malus\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Ramassage de Potions de Soin\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Ramassage de P. de Soin Totales\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Ramassage de Potions de Mana\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Ramassage de P. de Mana Totales\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Ramassage de P. de Rajeunissement\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Ramassage de P. de Rajeunissement Totales\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Options\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Sauvegarder\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Menu Principal\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Quitter\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Vitesse\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Musique Désactivée\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Son\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Son Désactivé\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pause\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Raccourcis Clavier :\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1 :    Ouvrir l'Écran d'Aide\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Échap :   Afficher Menu Principal\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab :   Afficher la Carte\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Espace : Masquer tous les Écrans d'informations\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S : Ouvrir Livre rapide\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B : Ouvrir le livre des sorts\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I : Ouvrir l'inventaire\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C : Ouvrir l'Écran du Personnage\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q : Ouvrir le Journal des quêtes\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F : Réduire la Luminosité\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G : Augmenter la luminosité\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z : Zoom\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / - : Zoom Carte\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 – 8 : Utiliser l'objet à la ceinture\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"\"\n\"F5, F6, F7, F8 :     configure le raccourci pour la compétence ou le sort\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Maj + Clic Gauche: Attaque sans bouger\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Maj + Clic Gauche (dans l'écran du personnage) : Assigne tous les points de \"\n\"stat\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Maj + Clic Gauche (dans l'inventaire) : Déplace l'objet vers la ceinture ou \"\n\"équipe/déséquipe l'objet\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\"Maj + Clic Gauche (sur la ceinture) : Déplace l'objet dans l'inventaire\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Mouvement :\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Si vous maintenez le bouton de la souris enfoncé pendant un déplacement, le \"\n\"personnage continuera à se déplacer dans cette direction.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Combat :\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Maintenir la touche Maj enfoncée puis faire un clic gauche permet au \"\n\"personnage d'attaquer sans bouger.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Carte-auto :\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Pour accéder à la carte, cliquer sur le bouton 'Carte' dans la barre \"\n\"d'informations ou appuyer sur 'TAB' sur le clavier. Le zoom avant et arrière \"\n\"sur la carte se fait avec les touches + et -. Utiliser les touches fléchées \"\n\"pour déplacer la carte.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Prendre Objet :\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Les objets consommables de petite taille, tels que les potions ou les \"\n\"parchemins, sont automatiquement placés dans votre 'ceinture' située en haut \"\n\"de la barre d'interface . Lorsqu'un objet est placé dans la ceinture, un \"\n\"petit nombre apparaît dans cette case. Les objets peuvent être utilisés en \"\n\"appuyant sur le numéro correspondant ou en cliquant avec le bouton droit sur \"\n\"l'objet.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Or :\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Vous pouvez sélectionner une quantité spécifique d'or à déposer en faisant \"\n\"un clic droit sur une pile d'or dans votre inventaire.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Compétences & Sorts :\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Vous pouvez accéder à votre liste de compétences et de sorts en faisant un \"\n\"clic gauche sur le bouton 'SORTS' dans la barre d'interface. Les sorts \"\n\"appris et ceux disponibles via les bâtons sont listés ici. Un clic gauche \"\n\"sur le sort que vous souhaitez lancer prépare le sort. Un sort préparé peut \"\n\"être lancé par un simple clic droit dans la zone de jeu.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Utiliser le Livre rapide pour les sorts :\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Un clic gauche sur le bouton 'sort prêt' ouvrira le 'Speedbook' qui vous \"\n\"permet de sélectionner une compétence ou un sort pour une utilisation \"\n\"immédiate. Pour utiliser une compétence ou un sort préparé, faites \"\n\"simplement un clic droit dans la zone de jeu principale.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Maj + clic gauche sur le bouton 'sélectionner le sort actuel' effacera le \"\n\"sort préparé.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Configurer le raccourci pour un sort:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Vous pouvez attribuer jusqu'à quatre raccourcis clavier pour les \"\n\"compétences, les sorts ou les parchemins. Commencez par ouvrir le \"\n\"'speedbook' comme décrit dans la section ci-dessus. Appuyez sur les touches \"\n\"F5, F6, F7 ou F8 après avoir mis en surbrillance le sort que vous souhaitez \"\n\"attribuer.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Livres de sort :\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Lire plus d'un livre augmente votre connaissance de ce sort, vous permettant \"\n\"de lancer le sort plus efficacement.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Aide Hellfire Shareware\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Aide Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Aide Diablo Shareware\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Aide Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Appuyez sur Échap pour terminer ou sur les flèches pour faire défiler.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Impossible de créer la fenêtre principale\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Huile de Précision\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Huile de Maîtrise\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Huile d'Affutage\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Huile de Mort\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Huile de Compétence\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Huile de Forgeron\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Huile de Courage\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Huile de Durabilité\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Huile de Durcissement\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Huile d'Imperméabilité\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} – {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1} {0} – {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1} {0} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{1} {0}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"augmente les\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"chance de toucher\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"augmente beaucoup\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"chances de toucher d'une arme\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"potentiel de dommage\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"augmente beaucoup les\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"dommage potentiel – pas les arcs\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"attributs nécessaire réduits\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"pour utiliser des armes ou armures\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"restaure 20% de\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"la durabilité de l'objet\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"augmente d'un objet\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"durabilité courante et maximale\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"rend un objet indestructible\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"augmente la classe d'une armure\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"d'armure et de bouclier\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"augmente beaucoup l'armure\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"classe d'armure et de bouclier\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"pose un piège à feu\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"pose un piège à foudre\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"pose un piège de pétrification\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"restaure toute la vie\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"restaure de la vie\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"restaurer un peu de mana\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"restaure tout le mana\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"augmente la force\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"augmente la magie\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"augmente la dextérité\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"augmente la vitalité\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"restaure de la vie et du mana\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"restaure toute la vie et le mana\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Clic-droit pour voir\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Clic-droit pour utiliser\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Clic-droit pour lire, puis\\n\"\n\"clic-gauche pour cibler\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Clic-droit pour lire\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Activer pour visualiser\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Ouvrez l'inventaire pour l'utiliser\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Activer pour utiliser\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Sélectionner depuis le livre des sorts, puis\\n\"\n\"lancer le sort pour le lire\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Activer pour lire\"\n\n#: Source/items.cpp:1800\n#, fuzzy, c++-format\n#| msgid \"Activate to view\"\nmsgid \"{} to view\"\nmsgstr \"Activer pour visualiser\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\n#| msgid \"{:+d} to strength\"\nmsgid \"{} to use\"\nmsgstr \"{:+d} en force\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Sélectionner depuis le livre des sorts, puis\\n\"\n\"lancer le sort pour le lire\"\n\n#: Source/items.cpp:1811\n#, fuzzy, c++-format\n#| msgid \"Activate to read\"\nmsgid \"{} to read\"\nmsgstr \"Activer pour lire\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Niveau : {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Double la capacité en Or\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Requis :\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} For\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Dex\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Livre : {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Oreille de {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"toucher : {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% dégâts\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"toucher : {:+d}%, {:+d}% dégâts\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% armure\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"classe d'armure : {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Résistance au Feu : {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Résistance au Feu : {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Résistance à la Foudre : {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Résistance à la Foudre : {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Résistance à la Magie : {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Résistance à la Magie : {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Résistance à tout : {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Résistance à tout : {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"sorts augmentés de {:d} niveau\"\nmsgstr[1] \"sorts augmentés de {:d} niveaux\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"sorts diminués de {:d} niveau\"\nmsgstr[1] \"sorts diminués de {:d} niveaux\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"niveaux de sorts inchangés ( ?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Charges supplémentaires\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} charge\"\nmsgstr[1] \"{:d} {:s} charges\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Dégâts de Feu : {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Dégâts de Feu : {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Dégâts de Foudre : {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Dégâts de Foudre : {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} en force\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} en magie\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} en dexterité\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} en vitalité\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} à tous les attributs\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} dégâts des ennemis\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Points de vie : {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana : {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"haute durabilité\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"durabilité diminuée\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"indestructible\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% portée lumineuse\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% portée lumineuse\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"plusieurs flèches par tir\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"dégâts de flèches de feu : {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"dégâts de flèches de feu : {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"dégâts de flèches de foudre : {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"dégâts de flèches de foudre : {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"dégâts boule de feu : {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"dégâts boule de feu : {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"l'attaquant subit 1 à 3 dégâts\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"l'utilisateur perd tout son mana\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"-50% des dégâts de piège\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"repousse la cible\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% dégâts vs. démons\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Toute résistance réduite à 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"frapper vole 3% de mana\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"frapper vole 5% de mana\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"frapper vole 3% de vie\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"frapper vole 5% de vie\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"pénètre l'armure de la cible\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"attaque prompte\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"attaque rapide\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"attaque plus rapide\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"attaque la plus rapide\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Une autre Capacité (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"récup rapide après coup\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"récup plus rapide après coup\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"récup la plus rapide après coup\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"blocage rapide\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"+{:d} dégâts\"\nmsgstr[1] \"+{:d} dégâts\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"tire des flèches de vitesse aléatoire\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"dégâts inhabituels\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"durabilité amoindrie\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"épée à une main\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"perd constamment des points de vie\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"vole la vie\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"pas d'exigence de force\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"dégâts de foudre : {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"dégâts de foudre : {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"trait de foudre à l'impact\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"chance de tripler les dégâts\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"putréfiant {:+d}% dommage\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2× dgt au monstre, 1× à vous\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Dégâts aléatoire entre 0-600%\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"faible dur, {:+d}% de dégât\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"extra CA vs Démons\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"extra CA vs Morts-Vivants\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% de mana transféré à la santé\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% de santé transféré au Mana\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"dégâts : {:d}  Indestructible\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"dégâts : {:d}  Dur : {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"dégâts : {:d}-{:d}  Indestructible\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"dégâts : {:d}-{:d} Dur : {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"armure : {:d} Indestructible\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"armure : {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Charges : {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"objet unique\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Non identifié\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"L'Antre du Roi Squelette\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Chambre des Ossements\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Dédale\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Réserve d'Eau Empoisonnée\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"L'Antre de l’Archevêque Lazarus\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\n#| msgid \"Hellfire\"\nmsgid \"Hell Arena\"\nmsgstr \"Hellfire\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Descendre dans le donjon\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Descendre dans les catacombes\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Descendre dans les grottes\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Descendre en enfer\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Descendre dans la Ruche\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Descendre dans la Crypte\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Monter au niveau {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Monter en ville\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Descendre au niveau {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Descendre vers Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Monter vers le Nid niveau {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Monter vers la Crypte niveau {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Pierre Angulaire du Monde\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Descendre vers la crypte niveau {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Retourner au Niveau {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Impossible d'ouvrir l'archive de sauvegarde\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Sauvegarde invalide\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Le joueur est dans un niveau uniquement Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"État du jeu invalide\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Impossible d'afficher le menu principal\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Animal\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Démon\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Mort-vivant\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Type : {:s}  Tués : {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Total Victimes : {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Points de vie :{:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Pas de résistance magique\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Résiste :\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magie\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Feu\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Foudre\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Immunisé :\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Type : {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Pas de résistances\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Pas d'immunités\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Quelques Résistances Magiques\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Quelques Immunités Magiques\"\n\n#: Source/mpq/mpq_writer.cpp:174\n#, fuzzy\n#| msgid \"Failed to open stash archive for writing.\"\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Échec de l'ouverture de l'archive de la cachette (écriture)\"\n\n#: Source/msg.cpp:1701\n#, fuzzy, c++-format\n#| msgid \"{:s} has cast an illegal spell.\"\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} a lancé un sort interdit.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} a lancé un sort interdit.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Joueur '{:s}' (niveau  {:d}) a rejoint le jeu\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Le jeu s'est terminé\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Impossible d'acquérir les données du niveau\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Joueur '{:s}' a quitté le jeu\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Joueur '{:s}' a tué Diablo et quitté le jeu !\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Joueur '{:s}' a été éjecté du jeu (délai dépassé)\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Joueur '{:s}' (niveau {:d}) est déjà en jeu\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Mystérieux\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Caché\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Glauque\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Bizarre\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Magique\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"de Pierre\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Religieux\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Enchanté\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Thaumaturgique\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Fascinant\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Cryptique\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Étrange\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Inquiétant\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Divin\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"d'Apôtre\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Sacré\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Spirituel\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Sinistre\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Abandonné\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Sinistre\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Calme\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Isolé\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Orné\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Scintillant\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Souillé\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Huileux\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Brillant\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"de Mendiant\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Pétillant\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Chatoyant\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Solaire\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"de Murphy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Le Grand Conflit\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Le Salaire du Péché est la Guerre\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Le Conte des Horadrim\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Le Sombre Exil\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"La Guerre du Péché\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"L'Emprisonnement des Trois\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Les Royaumes Au-Delà\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Conte des Trois\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Le Roi Noir\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Journal : L'Ensorcellement\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Journal : La Réunion\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Journal : La Tirade\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Journal : Ses Pouvoirs Grandissent\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Journal : NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Journal : La Fin\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Un Livre de Sort\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Squelette Crucifié\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Levier\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Porte Ouverte\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Porte Fermée\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Porte Bloquée\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Tome Ancien\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Livre de la Bassesse\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Levier-Crâne\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Livre Mythique\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Petit Coffre\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Coffre\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Coffre Large\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarcophage\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Étagère à livres\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Bibliothèque\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Baril\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Cosse\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urne\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"Sanctuaire {:s}\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Tome du Squelette\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Livre de la Bibliothèque\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Fontaine de Sang\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Corps Décapité\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Livre des Aveugles\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Livre de Sang\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Bassin Purifiant\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Armure\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Râtelier d'Armes\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Sanctuaire de la Chèvre\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Chaudron\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Bassin Trouble\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Fontaine des Larmes\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Tome d'Acier\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Piédestal de Sang\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Parterre de Champignon\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Pupitre Ignoble\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Héros Tué\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"Piégé {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (désactivé)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"OUI\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"NON\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Mode de Jeu\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Options de jouabilité\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Jouer à Diablo ou Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Limiter au Shareware\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Rend le jeu compatible avec la démo. Permet de jouer en multijoueur avec des \"\n\"amis qui ne possèdent pas le jeu complet.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Démarrage\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Options de Démarrage\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Intro\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Visionner la cinématique d'introduction.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Écran d'accueil\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Visionner les logos.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo et Titre\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Écran Titre\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Options spécifiques à Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Options spécifiques à Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Audio\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Options Audio\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Bruit de pas\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Le joueur émet un son en marchant.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Son Équipement Automatique\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Équiper automatiquement un objet émet un son.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Son Récupération d'objet\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Récupérer un objet émet un son.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Taux d'échantillonnage\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Choix du taux d'échantillonnage (Hz)\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Canaux\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Nombre de canaux de sortie.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Taille du tampon\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Taille du tampon (nombre d'image par canal)\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Qualité de rééchantillonnage\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"\"\n\"Qualité de rééchantillonnage, de 0 (basse qualité) à 10 (haute qualité)\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Change la résolution interne du jeu et détermine le champ de vision. \"\n\"Remarque : Il ne s'agira pas forcément de la résolution de l'écran, selon si \"\n\"Upscaling, Integer Scaling ou Fit to Screen est utilisé.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\n#, fuzzy\n#| msgid \"Audio Settings\"\nmsgid \"Audio device\"\nmsgstr \"Options Audio\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Graphismes\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Options Graphiques\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Plein écran\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Affiche le jeu en plein écran ou en fenêtré.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Ajusté à l'écran\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Ajuste automatiquement la fenêtre de jeu au format et à la résolution \"\n\"actuels de votre bureau.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Upscale\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Active la mise à l'échelle de la résolution du jeu à la résolution de votre \"\n\"moniteur. Empêche la modification de la résolution du moniteur et permet le \"\n\"redimensionnement de la fenêtre.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Qualité d'Upscaling\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Active des filtres facultatifs sur l'image de sortie en cas d'Upscaling.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Pixel le plus proche\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilinéaire\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotropique\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Integer Scaling\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"\"\n\"Met l'image à l'échelle à l'aide d'un rapport de pixels entiers (pas de \"\n\"nombres décimaux).\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Synchronisation verticale\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Foudre\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Color Cycling\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Effet de cycle de couleurs utilisé pour l'animation de l'eau, de la lave et \"\n\"de l'acide.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Version alternative du Nid\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"Le jeu utilisera une palette de texture alternative pour le Nid de Hellfire.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Curseur Matériel\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Utilise le curseur matériel\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Curseur Matériel pour les objets\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Utilise le curseur matériel pour les objets.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Taille Max. du Curseur Matériel\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Largeur/hauteur maximale du curseur matériel. De grandes valeurs rendent le \"\n\"curseur logiciel.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Afficher IPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"\"\n\"Affiche le nombre d'image par seconde dans le coin supérieur gauche de \"\n\"l'écran.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Jouabilité\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Options de jouabilité\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Active la possibilité de courir/marcher vite en ville dans Diablo et \"\n\"Hellfire. Cette option fut introduite dans l'extension.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Verrouiller le curseur\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"\"\n\"Lorsque cette option est activée, le curseur ne peut plus quitter la fenêtre \"\n\"du jeu.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Activer la quête de la Petite Fille.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Active la quête de Jersey. Lester le fermier est remplacé par le Cinglé.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Tir Ami\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Autorise les flèches/sorts à faire des dégâts aux joueur alliés en \"\n\"multijoueur même si le mode ami est activé.\"\n\n#: Source/options.cpp:790\n#, fuzzy\n#| msgid \"No pause in multiplayer\"\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Pas de pause en multijoueur\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Héros Barde (Test)\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Permet de choisir le Barde dans le menu de sélection du Héros.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Héros Barbare (Test)\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Permet de choisir le Barbare dans le menu de sélection du Héros.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Barre d'expérience\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\"La Barre d'expérience est ajoutée sur l'interface dans la partie inférieure \"\n\"de l'écran.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Afficher les points de vie\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Affiche le nombre de point de vie actuel sur le globe de santé.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Afficher la quantité de mana\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Affiche la quantité de mana sur le globe de mana.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Profil du Personnage\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Barre de Santé de l'Ennemi\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Affiche la Barre de Santé de l'Ennemi en haut de l'écran.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"L'Or est automatiquement collecté lorsque le joueur est à proximité.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Les Élixirs sont automatiquement collectés lorsque le joueur est tout près.\"\n\n#: Source/options.cpp:802\n#, fuzzy\n#| msgid \"\"\n#| \"Elixirs are automatically collected when in close proximity to the player.\"\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Les Élixirs sont automatiquement collectés lorsque le joueur est tout près.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Ramasser automatiquement les objets en ville.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria va restaurer votre jauge de mana lorsque vous lui rendez visite.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Les armes seront automatiquement équipées lorsqu'elles sont achetées ou \"\n\"ramassées.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Les armures seront automatiquement équipées lorsqu'elles sont achetées ou \"\n\"ramassées.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Les heaumes seront automatiquement équipés lorsqu'ils sont achetés ou \"\n\"ramassés.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Les boucliers seront automatiquement équipés lorsqu'ils sont achetés ou \"\n\"ramassés.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Les bijoux seront automatiquement équipés lorsqu'ils sont achetés ou \"\n\"ramassés.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Choisit aléatoirement les quêtes disponibles à chaque nouvelle partie.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Afficher le Type de Monstre\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Survoler un monstre avec le curseur affichera le type du monstre dans \"\n\"l'interface.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Remplit automatiquement la ceinture avec l'inventaire lorsque des objets \"\n\"sont consommés.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Lorsque cette option est activée, les Chaudrons, Les Sanctuaires Fascinants, \"\n\"Les Sanctuaires de la Chèvre, Les Sanctuaires Ornés et les Sanctuaires \"\n\"Sacrés ne sont plus cliquables et sont décrits comme désactivés.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Sort Rapide\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Les raccourcis clavier de sorts lancent instantanément le sort, plutôt que \"\n\"de changer le sort équipé.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Nombre de Potions de Soin à ramasser automatiquement.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Nombre de Potions de Soin Totale à ramasser automatiquement.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Nombre de Potions de Mana à ramasser automatiquement.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Nombre de Potions de Mana Totale à ramasser automatiquement.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Nombre de Potions de Rajeunissement à ramasser automatiquement.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Nombre de Potions de Rajeun. Totale à ramasser automatiquement.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\nmsgid \"Off\"\nmsgstr \"Rebouclage (Loopback)\"\n\n#: Source/options.cpp:825\n#, fuzzy\n#| msgid \"Randomize Quests\"\nmsgid \"Random Angles\"\nmsgstr \"Quêtes Aléatoires\"\n\n#: Source/options.cpp:826\n#, fuzzy\n#| msgid \"Vertical Sync\"\nmsgid \"Vertical Only\"\nmsgstr \"Synchronisation verticale\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Manette\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Options de la Manette\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Réseau\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Paramètres Réseaux\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chat\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Options du Chat\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Langue\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Définit quelle langue utiliser.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Options Linguistiques\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Attribution des Touches\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Options d'Attribution des Touches\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping\"\nmsgid \"Padmapping\"\nmsgstr \"Attribution des Touches\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping Settings\"\nmsgid \"Padmapping Settings\"\nmsgstr \"Options d'Attribution des Touches\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Paramètres\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Niveau\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Expérience\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Prochain Niveau\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Base\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Actuel\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Force\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magie\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Dextérité\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalité\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Points à distribuer\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"d'Or\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Classe d'armure\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"chance de toucher\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Dégâts\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Vie\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Résistance Magie\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Résistance Feu\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Résistance Foudre\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"perso\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"quêtes\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"carte\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menu\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"inv\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"sorts\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"voix\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"rendre muet\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Inutilisable\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Dég : 1/3 PV cible\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Soin : {:d} – {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Dégâts : {:d}-{:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Compétence\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Bâton ({:d} charge)\"\nmsgstr[1] \"Bâton ({:d} charges)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Niveau {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana : {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Sort\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Morts-Vivants uniquement\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Parchemin\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Bâton\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Raccourci Sort : {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Impossible d'ouvrir l'archive\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Impossible de charger le personnage\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (lvl {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Historique des Messages (Messages: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} or\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Combien de pièces d'or voulez-vous retirer ?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Niveau: {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Expérience: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Niveau Maximum\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Prochain Niveau : {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} vers le Niveau : {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Tombe du Roi Leoric\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"La Chambre des Ossements\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Un Passage Obscur\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"L'Autel impie\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Vers {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"J'ai besoin d'aide ! Venez !\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Suivez-moi.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Voici quelque chose pour vous.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"MEURS, à présent !\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Remerciements à\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Odgen\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Retour\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Dégâts : {:d}-{:d} \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Armure : {:d} \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Dur : {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"indestructible\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Bienvenue dans la\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Boutique du forgeron\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Souhaitez-vous :\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Parler à Griswold\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Acheter des objets de base\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Acheter des objets extra\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Vendre des objets\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Réparer des objets\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Quitter la boutique\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"J'ai ces objets à vendre :\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"J'ai ces objets extra à vendre :\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Vous n'avez rien pour moi.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Quel objet est à vendre ?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Vous n'avez rien à réparer.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Réparer quel objet ?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Cabane de la sorcière\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Parler à Adria\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Acheter des objets\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Recharger des bâtons\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Quitter la cabane\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Vous n'avez rien à recharger.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Recharger quel objet ?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Vous n'avez pas assez d'or\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Vous n'avez pas assez de place dans votre inventaire\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Marché conclu ?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Voulez-vous vraiment identifier cet objet ?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Voulez-vous vraiment acheter cet objet ?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Voulez-vous vraiment recharger cet objet ?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Voulez-vous vraiment vendre cet objet ?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Voulez-vous vraiment réparer cet objet ?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt à la jambe de bois\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Parler à Wirt\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"J'ai quelque chose à vendre,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"mais ça fera 50 pièces\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"rien que pour voir. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Qu'est-ce que tu as ?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Dire au revoir\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"J'ai cet objet à vendre :\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Partir\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Maison du Guérisseur\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Parler à Pepin\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Quitter le Guérisseur\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"L'Ancien de la Ville\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Parler à Cain\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identifier un objet\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Vous n'avez rien à identifier.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Identifier quel objet ?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Cet objet est :\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Fait\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Parler à {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Parler à {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"n'est pas disponible\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"dans le shareware\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"version\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Potins\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Soleil Levant\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Parler à Ogden\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Quitter la tarvene\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Parler à Gillian\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Accéder à la Cachette\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnham l'Ivrogne\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Parler à Farnham\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Dire Au Revoir\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Votre or : {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Villageois mort\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Griswold le Forgeron\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin le Guérisseur\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Villageois Blessé\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden le Tavernier\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Cain l'Ancien\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Adria la Sorcière\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian la Serveuse\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Vache\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester le Fermier\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Cinglé\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Guerrier\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Rogue\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Sorcier\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Moine\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Barde\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbare\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombie\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Goule\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Carcasse Putride\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Mort Noire\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Déchu\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Découpeur\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Démonoïde\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Sombre\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Squelette\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Hache de Cadavre\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Mort Ardent\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Horreur\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Charognard\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Mangeur de Peste\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Bête de l'Ombre\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Déchiqueteuse d'Os\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Arc de cadavre\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Capitaine Squelette\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Capitaine Cadavre\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Capitaine Mort Ardent\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Capitaine Horreur\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Seigneur Invisible\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Caché\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Harceleur\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Invisible\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Tisseur d'illusion\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Seigneur Satyre\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Clan de la Chair\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Clan de la Pierre\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Clan du Feu\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Clan de la Nuit\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Démon\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Clignoteur\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Ténébreux\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Familier\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Bête Acide\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Cracheur de Poison\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Bête des Fosses\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Gueule de Lave\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Roi Squelette\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Le Boucher\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Suzerain\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Homme de Boue\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Démon Crapaud\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Écorché\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Wyrm\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Limace des Cavernes\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Démon Wyrm\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Dévoreur\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Démon Magmatique\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Pierre de Sang\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Pierre de l'Enfer\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Seigneur de Lave\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Démon Cornu\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Coureur de Boue\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Chargeur de Givre\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Seigneur d'Obsidienne\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"Vieux Os\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Mort Rouge\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Démon Liche\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Balrog Mort-Vivant\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Incinérateur\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Seigneur des Flammes\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Feu Funeste\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Brûleur de l'Enfer\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Orage Rouge\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Cavalier des Tempêtes\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Seigneur des Tempêtes\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Maelström\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Démonoïde Brute\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Démon Ailé\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargouille\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Griffe de sang\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Aile de la Mort\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Pourfendeur\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Gardien\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Seigneur du Vortex\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Vipère des Cavernes\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Drake de Feu\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Vipère d'Or\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Drake d'Azur\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Chevalier Noir\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Gardien Funeste\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Seigneur d'Acier\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Chevalier de Sang\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Emmailloté\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Caverneux\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Maître de la Douleur\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Tisseur de Réalité\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Succube\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Sorcière des Neiges\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Engeance de l'Enfer\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Brûleur d'Âmes\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Conseiller\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Magistrat\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Cabaliste\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Avocat\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Le Seigneur des Ténèbres\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"L'Archi-Liche Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad le Faible\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar le Fou\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Morvure\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Archevêque Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Vex Rouge\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Jade Noir\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Seigneur de Guerre de Sang\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Démon Hork\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Le Sacrilège\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Chef d'Os la Hache Affutée\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Cuirlame le Massacreur\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Âmefuroncle\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Dégueulerat l'Impur\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Éventreur d'Os\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Bâfrescrofule L'Affamé\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Taillebide le Prompt\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Têterompue le Bouclier-Fracas\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Carnagebubon\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Morsure de l'Ombre\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Œil-Mort\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Fol-Œil le Mort\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Crâne de Feu\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Crânetors\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Tripelangue\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Grouillefusant\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Courbe-Lune\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Corbeau du Châtiment\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Mangeur d'Échine\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Cendre-Noire l'Ardent\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Corbeau des Ombres\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Pierre-Flétrie le Faible\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Bile-Crémeuse le Maître des Fosses\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Peau-de-Sang l'Arc Sombre\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Aile-Fétide\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Boit-l'Ombre\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Gruge-Brume\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Crache-Mort\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Goutte-le-Sang\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Deathshade le Cogne-Chair\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Larveguerre le Fou\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Crâne-de-Verre le Déchiqueté\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Feu-Fléau\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Ailenuit le Glacé\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Pierre-Gore\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Poing-d'Airain la Pierre Enflammée\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Flamme-Courroux le Condamné\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Ulcère-de-Feu le Sinistre\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Baron Vase\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Corne-d'Anthrax la Masse d'Acier\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Hurleur du Chaos\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Rictus Maudit le Pourrissant\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Brûleur-Fou\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Bonesaw la Liche\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Brise-Échine\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Crâne-Démon l'Os Tranchant\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Tempête-Brisée\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Fléau-Tempête\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Glaviot\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Gâte-l'Or de la Flamme\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Orage noir\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Courroux de la Peste\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"L'Écorcheur\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Corne-Bleue\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Warpfire l'Engeance infernale\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Flèche-de-Croc\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Crâne-Bubon\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Crânelion le Biaisé\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Langue-Noire\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Frappe-Vile\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Viperflamme\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Fangskin\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Flamme-Sorcière l'Impie\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Crâne Noir\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Taille-l'Âme\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Fils du Vent\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Seigneur de la Fosse\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Tisse-rouille\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Hurlant l'Ombre\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Nuage Funeste\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Lune de Sang Feu de l'Âme\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Sorcière de Lune\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Bâfretripe\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Grise-Guerre le Tueur\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Juge de l'Effroi\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Œil Céleste la Sorcière\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Crâne d'Acier le Chasseur\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Le Vizir\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamphir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Soif de Sang\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Veuve-Toile\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Danseur de Chair\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Pic Sinistre\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Serrure Funeste\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Epée Courte\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Écu\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Gourdin\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Arc Court\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Bâton Court – Mana\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Couperet\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"La Couronne des Morts-vivants\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Chevalière Empyréenne\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Roche Céleste\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Amulette Optique\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Anneau de Vérité\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Enseigne de la Taverne\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Cimier Arlequin\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Voile d'Acier\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Élixir Doré\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Enclume de Fureur\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Champignon Noir\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Cerveau\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Tome Fongique\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Élixir Spectral\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Pierre de Sang\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Carte de la Cathédrale\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Potion de Soin\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Potion de Mana\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Parchemin d'Identification\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Parchemin de Portail de Ville\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"La Vaillance d'Arkaine\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Potion de Soin Totale\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Potion de Mana Totale\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Épée de Griswold\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Plaque Bovine\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Bâton de Lazarus\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Parchemin de Résurrection\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Bâton Court\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Épée\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Dague\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Bombe Runique\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodore\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Amulette Aurique\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Note Déchirée 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Note Déchirée 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Note Déchirée 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Note Reconstituée\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Costume Marron\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Costume Gris\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Capuchon\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Cervellière\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Heaume\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Grand Heaume\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Couronne\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Bassinet\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Cape\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Guenilles\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Cape à Capuche\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Robe\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Armure Matelassée\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Armure en Cuir\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Armure en Cuir Bouilli\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Armure en Cuir Clouté\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Cotte de Mailles\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Maille\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Tunique de Mailles\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Armure en Écailles\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Cuirasse\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Armure\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Brigandine\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Demi Armure\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Armure de Tournoi\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Armure Gothique\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Harnois\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Bouclier\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Petit Bouclier\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Grand Bouclier\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Bouclier Normand\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Pavois\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Bouclier Gothique\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Potion de Rajeunissement\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Potion de Rajeunissement Totale\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Huile\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Élixir de Force\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Élixir de Magie\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Élixir de Dextérité\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Élixir de Vitalité\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Parchemin de Soin\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Parchemin de Recherche\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Parchemin de Foudre\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Parchemin de Mur de Feu\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Parchemin d'Inferno\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Parchemin de Flash\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Parchemin d'Infravision\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Parchemin de Phasage\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Parchemin de Bouclier de Mana\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Parchemin de Vague de Flammes\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Parchemin de Boule de Feu\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Parchemin de Malédiction de Pierre\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Parchemin d’Éclairs en série\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Parchemin de Gardien\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Parchemin de Nova\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Parchemin de Golem\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Parchemin de Téléportation\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Parchemin d'Apocalypse\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Falchion\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Cimeterre\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Claymore\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Lame\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Sabre\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Rapière\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Épée Large\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Fauchard\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Épée à Deux Mains\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Grande Épée\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Petite Hache\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Hache\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Grosse Hache\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Hache Large\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Hache Danoise\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Grande Hache\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Masse d'Armes\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Étoile du Matin\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Marteau de Guerre\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Marteau\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Gourdin Clouté\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Fléau\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Maul\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Arc\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Arc de Chasse\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Arc Long\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Arc à Poulies\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Arc Court de Bataille\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Arc Long de Bataille\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Arc Court de Guerre\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Arc Long de Guerre\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Bâton Long\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Bâton Composite\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Bâton de Quart\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Bâton de Guerre\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Bague\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amulette\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Rune de Feu\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Rune\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Rune de Foudre\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Rune Supérieure de Feu\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Rune Supérieure de Foudre\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Rune de Pierre\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Bâton Court – Trait de Foudre\"\n\n#: Source/translation_dummy.cpp:368\n#, fuzzy\n#| msgid \"Mana Potion Pickup\"\nmsgid \"Arena Potion\"\nmsgstr \"Ramassage de Potions de Mana\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Le Couperet du Boucher\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Sabre-Laser\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Arc de le Faille\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"L'Aiguilleteuse\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"L'Arc Céléste\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Chasseur Mortel\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"L'Arc des Morts\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Arc de Chêne Noir\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Fléchette de Flamme\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Dard de Chair\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Cyclone\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Corne d'Aigle\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Poignard de Gonnagal\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Le Défenseur\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Griffe de Griffon\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Rasoir Noir\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Lune Gibbeuse\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Surin de Glace\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"La Lame du Bourreau\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"La Scie à Amputation\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Faucon des Ombres\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Pointe du Sorcier\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Sabre-Laser\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"La Serre du Faucon\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Porte-Malheur\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Le Grizzly\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Le Grand-Père\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"L'Écharpeur\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Bec Pointu\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Pourfendeur de Sang\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"La Hache Céleste\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Hache Malfaisante\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Couperet de Pierre\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Hachette d'Aguinara\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Pourfendeur de l'Enfer\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Saccageur de Messerschmidt\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Craquerouille\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Marteau de Jholm\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Massue de Civerb\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"L'Étoile Céleste\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"L'Étoile de Baranar\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Racine Noueuse\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Le Cabosse-Crâne\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Marteau de Schaefer\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Bride des Rêves\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Bâton des Ombres\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Immolateur\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Pinacle de Tempête\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Mélopée Scintillante\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Appel du Tonnerre\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Le Protecteur\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Casse-tête de Naj\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Pleur d'Esprit\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Baguette d'Onan\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Heaume des Esprits\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Calot de Pensée\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Heaume de Suzerain\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Crête du Bouffon\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Götterdämmerung\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Diadème Royal\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Chair Déchirée des Âmes\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Le Fléau du Gladiateur\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"La Cape Arc-en-ciel\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Cuir d'Aut\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Enveloppe de Sagesse\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Cotte de Mailles Étincelante\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Carapace de Charognard\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Paysage Nocturne\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Plaque légère de Naj\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Manteau de Piques de Démon\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Le Déflecteur\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Bouclier de Crâne Écartelé\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Brèche du Dragon\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Bouclier de Chêne Noir\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Saint Défenseur\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Bouclier de Tempête\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Roncier\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Anneau de Regha\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Le Saigneur\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Anneau Garrottant\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Anneau d'Engagement\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"en Étain\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"en Laiton\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"en Bronze\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"en Fer\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"en Acier\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"en Argent\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"en Platine\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"en Mithril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"en Météore\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Étrange\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Inutile\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Courbe\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Faible\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"de Déchirure\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"de Violence\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"de Cruauté\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"d'Atrocité\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"de Brutalité\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Énorme\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Féroce\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Implacable\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Impitoyable\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"de Maladresse\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"de Gaucherie\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"de Boucher\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"de Fantassin\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"de Guerrier\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"de Soldat\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"de Seigneur\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"de Chevalier\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"de Maître\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"de Champion\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"de Roi\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Vulnérable\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Fragile\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Solide\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Grandiose\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"de Vaillance\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"de Gloire\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"de Bénédiction\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"de Sainteté\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Fantastique\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"de Dieux\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"de Jaspe\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"de Cornaline\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"de Grenat\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"de Rubis\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"de Turquoise\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"d'Azurite\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"de Lapis\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"de Cobalt\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"de Saphir\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"de Porcelaine\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"de Perle\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"d'Ivoire\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"de Cristal\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"de Diamant\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"de Topaze\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"d'Ambre\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"de Jade\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"d'Obsidienne\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"d'Émeraude\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"de la Hyène\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"de la Grenouille\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"de l'Araignée\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"du Corbeau\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"du Lézard\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"du Serpent\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"de la Manticore\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"du Dragon\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"du Wyrm\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"de l'Hydre\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"d'Ange\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"d'Arch-Ange\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Prolifique\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Intarissable\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"de Flamme\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"de Foudre\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"de Qualité\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"de Blessure\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"d'Extermination\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"de Tuerie\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"de Carnage\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"de Massacre\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"de Douleur\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"de Larmes\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"de Santé\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"de Protection\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"d'Absorption\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"de Déviation\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"d'Osmose\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"de Fragilité\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"de Faiblesse\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"de Force\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"de Puissance\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"de Pouvoir\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"de Géant\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"de Titan\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"de Paralysie\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"d'Atrophie\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"de Dextérité\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"d'Aptitude\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"d'Exactitude\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"de Précision\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"de Perfection\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"du Sot\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"de Dyslexie\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"de Magie\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"de l'Esprit\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"d'Intelligence\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"de Sorcellerie\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"d'Archimagie\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"de Maladie\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"de Nausée\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"de Vitalité\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"d'Entrain\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"d'Ardeur\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"de Vigueur\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"de Vie\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"de Difficulté\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"de la Fosse\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"du Ciel\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"de la Lune\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"des Étoiles\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"du Paradis\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"du Zodiaque\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"du Vautour\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"du Chacal\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"du Renard\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"du Jaguar\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"de l'Aigle\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"du Loup\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"du Tigre\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"du Lion\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"du Mammouth\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"de la Baleine\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"de Verre\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"de Fragilité\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"de Solidité\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"d'Artisan\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"de Maître\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"des Âges\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"des Ténèbres\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"de la Nuit\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"de Lumière\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"d'Éclat\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"de Flamme\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"de Feu\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"de Brûlure\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"de Choc\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"de Foudre\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"du Tonnerre\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"Durable\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"Insatiable\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"d'Épines\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"de Corruption\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"du Voleur\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"de l'Ours\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"de la Chauve-Souris\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"du Vampire\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"de la Sangsue\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"de Sang\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"de Perçage\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"de Perforation\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"d'Empalement\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"de Préparation\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"de Rapidité\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"de Vitesse\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"de Précipitation\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"d'Équilibre\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"de Stabilité\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"d'Harmonie\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"de Blocage\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"La Roche Céleste\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad le Faible\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar le Fou\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Le Boucher\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Enseigne d'Ogden\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Hall des Aveugles\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Vaillance\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Seigneur de Guerre de Sang\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"La Malédiction du Roi Leoric\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Archevêque Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Affaires de Tombe\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Verger du Fermier\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Petite Fille\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Marchand Errant\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Le Profanateur\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Le Jersey du Jersey\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Trait de Feu\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Soin\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Foudre\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Flash\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identifier\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Mur de Feu\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Portail de Ville\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Malédiction de Pierre\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infravision\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Phasage\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Bouclier de Mana\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Boule de feu\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Gardien\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Éclairs en série\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Vague de Flammes\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Serpents Mortels\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Rituel du Sang\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Invisibilité\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Rage\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Téléportation\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apocalypse\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Éthéréaliser\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Répare les Objets\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Recharge les Bâtons\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Désactive les Pièges\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Élémentaire\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Trait de Foudre\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Trait Sacré\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Résurrection\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Télékinésie\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Soin d'Autrui\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Étoile de Sang\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Esprit d'Os\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\"Ahh, l'histoire du Roi, hein ? La déchéance tragique de Leoric a été un coup \"\n\"dur pour ce pays. Le peuple a toujours aimé le Roi, et maintenant il en a \"\n\"une peur mortelle. La question que je n'arrête pas de me poser est de savoir \"\n\"comment il a pu s'éloigner autant de la Lumière, lui qui a toujours été le \"\n\"plus pieux de tous. Seules les plus noires puissances des Enfers peuvent \"\n\"détruire un homme de l'intérieur aussi résolument...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Le village a besoin de votre aide, mon bon maître ! Il y a quelques mois, le \"\n\"fils du roi Léoric, le prince Albrecht, a été enlevé. Le roi s'est mis en \"\n\"rage et a ratissé tout le village à la recherche de son enfant. Au fil des \"\n\"jours, Léoric semblait sombrer toujours plus dans la démence. Il a même \"\n\"cherché à incriminer d'innocents villageois de la disparition du petit et \"\n\"les a fait brutalement exécuter. Moins de la moitié d'entre nous ont survécu \"\n\"à sa folie...\\n\"\n\" \\n\"\n\"Les chevaliers et les prêtres du roi ont essayé de le calmer, mais il s'est \"\n\"retourné contre eux et, malheureusement, ils ont été contraints de le tuer. \"\n\"Dans son dernier souffle, le roi a lancé une terrible malédiction sur ses \"\n\"anciens compagnons. Il a juré qu'ils le serviraient dans les ténèbres pour \"\n\"l'éternité...\\n\"\n\" \\n\"\n\"C'est là que les choses prennent une tournure encore plus sombre que je ne \"\n\"l'imaginais ! Notre ancien roi est sorti de son sommeil éternel et il \"\n\"commande désormais une légion de damnés à l'intérieur du labyrinthe. Son \"\n\"corps a été enterré dans une tombe trois niveaux sous la Cathédrale. Par \"\n\"pitié, mon bon maître, libérez son âme en détruisant son enveloppe \"\n\"corporelle maudite...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Comme je vous l'ai dit, mon bon maître, le Roi a été inhumé trois niveaux \"\n\"sous le sol. Il est là-bas, attendant dans les ténèbres putrides l'occasion \"\n\"de détruire ce pays...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"La malédiction de notre roi est levée, mais je crains que cela n'ait été \"\n\"qu'une partie d'un plus grand mal à l'œuvre. Cependant, nous pouvons encore \"\n\"être préservés des ténèbres qui consument notre pays, car votre victoire est \"\n\"un bon présage. Que la Lumière vous guide sur votre chemin, mon bon maître.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"La perte de son fils a porté un coup fatal au Roi Leoric. J'ai fait de mon \"\n\"mieux pour atténuer sa folie, mais elle a fini par prendre le dessus. Une \"\n\"sombre malédiction pèse sur le royaume depuis ce jour, mais peut-être que si \"\n\"vous libériez son âme de sa prison terrestre, cette malédiction serait \"\n\"levée...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Je n'aime pas me rappeler la fin du Roi. Je préfère me souvenir du roi juste \"\n\"et bon qu'il avait été. J'ai été attristée par sa mort et quelque part, je \"\n\"me dis qu'elle était injuste.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"J'ai fabriqué la plupart des armes et des armures que le roi Leoric \"\n\"fournissait à ses chevaliers. J'ai même fabriqué pour lui une énorme épée à \"\n\"deux mains du meilleur mithril, ainsi qu'une couronne de bataille assortie. \"\n\"Je n'arrive toujours pas à croire la façon dont il est mort, mais ce doit \"\n\"être une force maléfique qui l'a rendu fou !\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"M'en fiche. Écoutez, aucun squelette sera MON roi. Leoric est roi. Roi, \"\n\"alors vous m'entendez ? VIVE LE ROI !\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Les morts qui marchent parmi les vivants suivent le roi maudit. Il détient \"\n\"le pouvoir de lever encore plus de guerriers pour une armée de morts-vivants \"\n\"toujours plus nombreuse. Si vous n'arrêtez pas son règne, il traversera \"\n\"sûrement ce pays et fauchera tous ceux qui y vivent encore.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Dites, j'ai un bizness ici. Je ne vends pas d'informations, et je me \"\n\"contrefiche d'un roi mort avant ma naissance. Si vous avez besoin de quelque \"\n\"chose à utiliser contre ce roi des morts-vivants, alors là je peux peut-être \"\n\"vous aider...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"La chaleur de la vie est entrée dans ma tombe. Prépare-toi, mortel, à servir \"\n\"mon Maître pour l'éternité !\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Je vois que ce comportement étrange vous intrigue également. Je subodore que \"\n\"puisque de nombreux démons craignent la lumière du soleil et croient qu'elle \"\n\"détient un grand pouvoir, il se peut que le soleil levant tracé sur \"\n\"l'enseigne dont vous parlez les ait amenés à croire qu'elle détient aussi \"\n\"quelque pouvoir ésotérique. Hum, peut-être ne sont-ils pas tous aussi \"\n\"intelligents qu'on le craignait…\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Maître, il m'est arrivé quelque chose dont j'aimerais vous entretenir. Je \"\n\"sais que vous avez une solide connaissance de ces monstruosités qui habitent \"\n\"le labyrinthe, et c'est quelque chose qui me dépasse totalement… J'ai été \"\n\"réveillé pendant la nuit par un bruit de grattement juste à l'extérieur de \"\n\"ma taverne. Quand j'ai regardé depuis ma chambre, j'ai vu comme des formes \"\n\"de petits démons dans la cour de l'auberge. Peu de temps après, ils ont \"\n\"filé, mais pas avant d'avoir volé mon enseigne. Je ne vois pas pourquoi les \"\n\"démons voleraient mon enseigne mais laisseraient ma famille tranquille… \"\n\"étrange, non ?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Oh, mais ce n'était pas la peine de rapporter mon enseigne. Enfin, j'imagine \"\n\"que ça m'évitera d'avoir à en faire faire une nouvelle. Voyons, laissez-moi \"\n\"voir, qu'est-ce que je pourrais vous donner en récompense ? Hmmm, qu'avons-\"\n\"nous là… ah, oui ! Ce bonnet a été oublié dans une des chambres par un \"\n\"magicien qui y a séjourné il y a quelque temps. Peut-être qu'il peut vous \"\n\"être utile.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Mon Dieu, des démons qui vont et viennent dans le village de nuit, pillant \"\n\"nos maisons – n'y a-t-il rien de sacré ? J'espère qu'Ogden et Garda vont \"\n\"bien. Je suppose qu'ils viendraient me voir s'ils étaient blessés...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Mon Dieu ! C'est donc ça qui était arrivé à l'enseigne ? Ma grand-mère et \"\n\"moi devions dormir pendant tout ce temps. La Lumière soit louée, \"\n\"heureusement qu'ils n'ont pas attaqué l'auberge.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Comment, des démons ont volé la pancarte d'Ogden ? Ça ne ressemble pas \"\n\"beaucoup aux atrocités dont j'ai entendu parler – ou que j'ai vues.\\n\"\n\" \\n\"\n\"Ce qui intéresse les démons, c'est de vous arracher le cœur, pas votre \"\n\"enseigne.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Vous savez c'que je pense ? Quéqu'un a pris cette enseigne, et va réclamer \"\n\"plein d'argent pour la rendre. Si j'étais Ogden... et je l'suis pas, mais si \"\n\"je l'étais... j'achèterais juste une nouvelle enseigne avec un joli dessin \"\n\"dessus. P't-être une bonne chope de bière ou un bout d'fromage...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Nul mortel ne peut vraiment se mettre dans l'esprit d'un démon.\\n\"\n\" \\n\"\n\"Ne laissez jamais leurs actions désorganisées vous troubler, car cela peut \"\n\"aussi être leur plan.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Quoi ? Il dit que c'est moi qui l'avais prise ? J'imagine que Griswold est \"\n\"aussi avec lui .\\n\"\n\" \\n\"\n\"Écoutez, ça fait plusieurs mois que j'ai arrêté de faucher des enseignes. On \"\n\"ne peut pas faire de profit en vendant un bout de bois.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hé – Toi qui tue tout ! Trouve-moi la bannière magique ou nous attaque ! Tu \"\n\"pars pas vivant ! Tu tue gros affreux et tu rapporte magie. Passe le coin et \"\n\"la porte, trouve les affreux. Tu donne, tu pars !\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Tu tue affreux et récupère bannière. Tu ramène à moi, ou sinon...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Tu donne ! Oui bien ! Pars maintenant, nous fort. Nous tue tout avec grand \"\n\"magie !\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Cela ne présage rien de bon, car cela confirme mes peurs les plus sombres. \"\n\"Bien que je me m'interdisais de croire aux anciennes légendes, je ne peux \"\n\"plus les nier maintenant. Le moment est peut-être venu de révéler qui je \"\n\"suis.\\n\"\n\" \\n\"\n\"Mon vrai nom est Deckard Cain l'Ancien, et je suis le dernier descendant \"\n\"d'une ancienne Confrérie qui avait pour vocation la sauvegarde des secrets \"\n\"d'un mal intemporel. Un mal qui manifestement est désormais libéré.\\n\"\n\" \\n\"\n\"L'archevêque Lazarus, autrefois le conseiller le plus sûr du roi Léoric, \"\n\"mena un groupe de simples villageois dans le labyrinthe pour retrouver le \"\n\"fils disparu du roi, Albrecht. Beaucoup de temps a passé avant leur retour, \"\n\"et seuls quelques-uns d'entre eux en ont réchappé vivants.\\n\"\n\" \\n\"\n\"Quel idiot j'ai été ! J'aurais dû soupçonner sa perfidie dès lors. Ce doit \"\n\"être Lazarus lui-même qui a enlevé Albrecht et le cache depuis dans le \"\n\"Labyrinthe. Je ne comprends pas pourquoi l'archevêque s'est tourné vers les \"\n\"ténèbres, ou ce qu'il veut à l'enfant, à moins qu'il n'entende le sacrifier \"\n\"à ses sombres maîtres !\\n\"\n\" \\n\"\n\"C'est sûrement ce qu'il mijote ! Les survivants de son 'équipe de sauvetage' \"\n\"disent que Lazarus a été vu pour la dernière fois en train de courir au fin \"\n\"fond du labyrinthe. Vous devez vous dépêcher et sauver le prince de la lame \"\n\"sacrificielle de ce dément !\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Vous devez vous dépêcher et sauver Albrecht des mains de Lazarus. Le prince \"\n\"et le peuple de ce royaume comptent sur vous !\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Votre histoire est bien lugubre, mon ami. Lazarus brûlera sûrement en enfer \"\n\"pour son geste horrible. Le garçon que vous décrivez n'est pas notre prince, \"\n\"mais je pense qu'Albrecht est peut-être en danger. Le symbole de puissance \"\n\"dont vous parlez doit être un portail au cœur même du labyrinthe.\\n\"\n\" \\n\"\n\"Sachez ceci, mon ami – Le mal contre lequel vous vous dressez est le sombre \"\n\"Seigneur de la Terreur. Il est connu des mortels hommes sous le nom de \"\n\"Diablo. C'est lui qui a été emprisonné dans le Labyrinthe il y a bien des \"\n\"siècles et je crains qu'il ne cherche une fois de plus à semer le chaos dans \"\n\"le royaume des Hommes. Vous devez vous aventurer à travers le portail et \"\n\"détruire Diablo avant qu'il ne soit trop tard !\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus était l'archevêque qui a entraîné de nombreux villageois dans le \"\n\"labyrinthe. J'ai perdu beaucoup de bons amis ce jour-là, et Lazarus n'est \"\n\"jamais revenu. J'imagine qu'il a été tué avec la plupart des autres. Si je \"\n\"peux vous demander une faveur, mon bon maître, ne parlez pas de ce jour-là à \"\n\"Farnham.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Je n'en revenais pas quand j'ai appris ce que les habitants se préparaient à \"\n\"faire cette nuit-là. Je pensais que d'entre tous, Lazarus au moins aurait eu \"\n\"plus de jugeote que ça. Il était archevêque et semblait tant se soucier des \"\n\"habitants de Tristram. Il y a eu tant de blessés, je n'ai pas pu tous les \"\n\"sauver...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Pour moi, Lazarus a toujours été un homme bon et généreux. Il a fait une \"\n\"oraison à l'inhumation de ma mère, et a été d'un grand soutien pour ma grand-\"\n\"mère et moi en des temps difficiles. Je prie chaque nuit en espérant qu'il \"\n\"ne lui soit rien arrivé.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"J'étais là quand Lazarus nous a emmenés dans le labyrinthe. Il a parlé de \"\n\"châtiment sacré, mais quand on a commencé à combattre ces engeances, il n'a \"\n\"même pas levé sa masse contre eux. Il s'est juste enfoncé plus vite dans ces \"\n\"cellules sans fin bourrées de serviteurs des ténèbres !\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Ils piquent, puis mordent, puis ils sont tout autour de vous. Menteur ! \"\n\"MENTEUR ! Ils sont tous morts ! Morts ! Vous m'entendez ? Ils tombaient, et \"\n\"tombaient encore... leur sang recouvrait le sol... tout est sa faute...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Je ne connaissais pas ce Lazarus dont vous me parlez, mais oui je sens qu'il \"\n\"est la proie d'un grand conflit intérieur. Il représente un grand danger et \"\n\"ne reculera devant rien pour servir les puissances des ténèbres qui se le \"\n\"sont accaparées.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Oui, le vertueux Lazarus, qui a été teeellement efficace contre ces monstres \"\n\"là-bas. Il n'a pas aidé à sauver ma jambe, pas vrai ? Allez, je vous file un \"\n\"conseil gratuit. Demandez à Farnham, il y était.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Abandonnez votre quête insensée. Tout ce qui vous attend, c'est la colère de \"\n\"mon Maître ! Il est trop tard pour sauver l'enfant. Vous allez maintenant le \"\n\"rejoindre en Enfer !\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, je ne vois pas bien ce que je pourrai vous apprendre d'utile. L'eau qui \"\n\"remplit nos puits provient d'une source souterraine. J'ai entendu parler \"\n\"d'un tunnel qui mène à un grand lac – peut-être qu'ils ne font qu'un. \"\n\"Malheureusement, je ne sais pas ce qui pourrait polluer notre \"\n\"approvisionnement en eau.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"J'ai toujours essayé de garder une bonne réserve de denrées alimentaires et \"\n\"de boissons dans le cellier, mais si toute la ville n'a plus de source d'eau \"\n\"potable, même nos citernes seront bientôt à sec.\\n\"\n\" \\n\"\n\"S'il vous plaît, faites quelque chose ou je ne sais pas comment nous allons \"\n\"faire.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Heureusement que je vous attrape à temps ! Nos puits sont devenus saumâtres \"\n\"et croupis et certains habitants en sont tombés malades. Nos réserves d'eau \"\n\"potable s'épuisent rapidement. Je crois qu'il y a un passage qui mène aux \"\n\"sources qui alimentent notre ville. Je vous en prie, trouvez ce qui a causé \"\n\"cette calamité, ou nous périrons tous sans faute.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Je vous en prie, faites vite. Plus le temps passe, moins nous avons d'eau.\\n\"\n\" \\n\"\n\"Nous ne survivrons pas longtemps sans votre aide.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Qu'est-ce que vous dites ? La simple présence des démons a suffi à \"\n\"empoisonner notre eau ? Oh, décidément un grand mal nous guette sous notre \"\n\"ville, mais votre persévérance et votre courage nous donnent de l'espoir. \"\n\"Prenez cet anneau – il vous aidera peut-être à détruire ces atroces \"\n\"créatures.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Ma grand-mère est très faible et Garda dit que nous ne pouvons pas boire \"\n\"l'eau des puits. Vous pouvez faire quelque chose pour nous ?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin ne vous a pas menti. On va salement manquer d'eau potable, et vite. \"\n\"J'ai essayé de nettoyer l'un des plus petits puits, mais il empeste la \"\n\"fange. Il doit se boucher à la source.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Vous buvez de l'eau ?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Les habitants de Tristram vont mourir si vous ne parvenez pas à rétablir \"\n\"l'alimentation en eau des puits.\\n\"\n\" \\n\"\n\"Sachez-le – les démons sont au cœur de cette affaire, mais ils ne sont pas \"\n\"au courant de ce qu'ils ont provoqué.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Pour une fois, je suis avec vous. Mon bizness va s'assécher – au sens propre \"\n\"– si je n'ai plus de clientèle. Vous avez intérêt à trouver ce qui cloche, \"\n\"et vite !\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Un livre qui parle d'une chambre d'ossements humains ? Eh bien, une Chambre \"\n\"d'Ossements est mentionnée dans certains écrits archaïques que j'ai étudiés \"\n\"dans les bibliothèques de l'Orient. Ces tomes en concluaient que lorsque les \"\n\"seigneurs des enfers voulaient protéger de grands trésors, ils créaient des \"\n\"domaines où ceux qui périssaient en tentant de voler ce trésor seraient à \"\n\"jamais tenus de le défendre. Une fin ironique, mais étrangement de \"\n\"circonstance, non ?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"J'ai peur de ne rien savoir là-dessus, mon bon maître. Cain a beaucoup de \"\n\"livres, il pourra peut-être vous aider.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Ça a l'air d'être un endroit très dangereux. Si vous vous y risquez, prenez \"\n\"bien garde à vous.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Je n'en ai jamais entendu parler, j'en ai peur. Peut-être que Cain le \"\n\"Conteur pourrait être utile.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Je ne sais rien de cet endroit, mais vous ferez peut-être bien de demander à \"\n\"Cain. Il parle de beaucoup de choses, et je ne serais pas étonné qu'il ait \"\n\"des réponses à vous apporter.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Bon, alors écoutez. Y'a cette chambre de bois, quoi. Et sa femme, vous savez \"\n\"– elle – dit à l'arbre... pasque vous devez attendre. Alors, que je dis, ça \"\n\"pourrait marcher contre lui, mais si vous croyez que je vais PAYER pour \"\n\"ça... vous... euh... ouais.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Vous deviendrez un serviteur éternel des seigneurs des ténèbres si jamais \"\n\"vous périssez dans ce domaine maudit.\\n\"\n\" \\n\"\n\"Entrez dans la Chambre des Ossements à vos risques et périls.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Un vaste et mystérieux trésor, vous dites ? Ça pourrait peut-être \"\n\"m'intéresser de vous prendre quelques bricoles... ou mieux encore, vous \"\n\"n'avez pas besoin de fournitures rares et chères pour vous aider à traverser \"\n\"cette épreuve ?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Il semble que l'archevêque Lazarus ait poussé de nombreux habitants à \"\n\"s'aventurer dans le labyrinthe pour retrouver le fils disparu du roi. En \"\n\"jouant sur leur peurs, il en a fait un troupeau d'excités. Aucun d'eux \"\n\"n'était préparé à ce qui se trouvait dans la terre froide... Lazarus les y a \"\n\"abandonnés – dans les griffes d'horreurs indescriptibles – pour mourir.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Oui, Farnham a bredouillé quelque chose à propos d'une immense brute \"\n\"brandissant une arme terrible. Je crois qu'il l'appelait le Boucher.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Par la Lumière, je connais ce maudit démon. Nombreux étaient ceux qui \"\n\"portaient les cicatrices de sa fureur dans leur chair lorsque les rares \"\n\"survivants de la charge menée par Lazarus ont rampé hors de la cathédrale. \"\n\"Je ne sais avec quoi il tailladait ses victimes, mais ça ne pouvait pas être \"\n\"de ce monde. Cela laissait des plaies gangrenées et même moi j'ai eu toutes \"\n\"les peines du monde à les traiter. Prenez garde à vous si vous comptez \"\n\"affronter ce monstre...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Quand Farnham a parlé d'un boucher qui tuait les gens, je l'ai d'abord \"\n\"ignoré. Mais maintenant que vous en parlez, peut-être que c'est vrai.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"J'ai vu ce que Farnham appelle le Boucher alors qu'il se taillait un passage \"\n\"à travers les corps de mes amis. Il brandissait un couperet gros comme une \"\n\"hache, tranchant des membres et abattant sur place des hommes courageux. Je \"\n\"me suis trouvé séparé de la mêlée par une meute de petits démons hurlants et \"\n\"je suis tombé par hasard sur l'escalier de la sortie. Je n'ai jamais revu \"\n\"cette bête épouvantable, mais son visage plein de sang me travaille encore \"\n\"aujourd'hui.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Gros ! Gros couperet qui tue tous mes amis. Impossible de l'arrêter, fallait \"\n\"s'enfuir, impossible de les sauver. Piégé dans une pièce avec tous ces \"\n\"corps... tant d'amis... NAAAAAAAAAAN !\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Le Boucher est une créature sadique qui se régale de la torture et de la \"\n\"douleur d'autrui. Vous avez vu son œuvre en Farnham l'ivrogne. Le détruire \"\n\"facilitera grandement la sécurité de ce village.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"J'en sais plus que vous ne pensez sur cette horreur. Ses petits copains \"\n\"m'avaient attrapé et avaient réussi à me niquer la jambe avant que Griswold \"\n\"me tire de ce trou.\\n\"\n\" \\n\"\n\"Je vais le dire franco – tuez-le avant qu'il ne vous tue et n'ajoute votre \"\n\"cadavre à sa collection.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"S'il vous plaît, écoutez moi. L'archevêque Lazarus, il nous a conduits ici \"\n\"pour retrouver le prince. Ce chien nous a entraînés dans un piège ! \"\n\"Maintenant, tout le monde est mort... tué par un démon qu'il a appelé le \"\n\"Boucher. Vengez-nous ! Trouvez ce Boucher et tuez-le, que nos âmes puissent \"\n\"reposer en paix…\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Vous récitez là une comptine intéressante écrite dans un style qui me \"\n\"rappelle d'autres œuvres. Voyons – qu'est-ce que c'était ?\\n\"\n\" \\n\"\n\"…Les ténèbres enveloppent le Caché. Des yeux brillants inaperçus avec seul \"\n\"perceptible le son de griffes acérées grattant à petits coups pour \"\n\"tourmenter ces pauvres âmes rendues aveugles pour l'éternité. La prison pour \"\n\"ceux qui ont ainsi été damnés s'appelle le Hall des Aveugles…\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Je n'ai jamais été féru de poésie. À l'occasion, je pouvais prendre des \"\n\"ménestrels quand l'auberge marchait bien, mais ça paraît si lointain \"\n\"maintenant.\\n\"\n\" \\n\"\n\"Hein ? Oh, oui... euh, bon, je suppose que vous devriez voir ce que d'autres \"\n\"savent.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Ça me dit quelque chose. Je crois me souvenir avoir lu quelque chose de tout \"\n\"à fait semblable à ce poème en faisant des recherches sur l'histoire des \"\n\"affections démoniaques. Ça parlait d'un endroit diabolique qui... attendez – \"\n\"vous ne comptez tout de même pas y aller, dites ?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Si vous avez des questions sur la cécité, vous devriez demander à Pepin. Je \"\n\"sais qu'il a donné à ma grand-mère une potion qui a aidé à éclaircir sa vue, \"\n\"alors peut-être qu'il peut vous aider, aussi.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Je crains bien n'avoir jamais vu ni entendu parler d'un endroit qui \"\n\"ressemble à votre description expressive, mon ami. Peut-être que Cain le \"\n\"Conteur pourra vous aider.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\"Regardez voir... c'est marrant, hein ? Vous pigez ? Aveugle – regardez voir ?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"C'est un lieu de grande angoisse et de terreur, et sert ainsi bien son \"\n\"maître.\\n\"\n\" \\n\"\n\"Avancez prudemment ou vous pourriez y rester bien plus longtemps que vous ne \"\n\"l'escomptiez.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Voyons, est-ce que je suis en train de vous vendre quelque chose ? Non. Est-\"\n\"ce que vous me donnez de l'argent pour vous en parler ? Non. Est-ce que vous \"\n\"allez partir en parler au conteur qui ne vit que pour ce genre de trucs ? \"\n\"Oui.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Vous dites avoir parlé avec Lachdanan ? C'était un grand héros de son \"\n\"vivant. Lachdanan était un homme d'honneur ; il était juste, et il a \"\n\"fidèlement servi son roi pendant des années. Mais bien sûr, vous savez déjà \"\n\"tout ça.\\n\"\n\" \\n\"\n\"De tous ceux qui ont été pris sous l'emprise de la Malédiction du Roi, \"\n\"Lachdanan serait le moins susceptible de se soumettre aux ténèbres sans \"\n\"combattre, aussi votre histoire me semble vraisemblable. Si j'étais à votre \"\n\"place, mon ami, je tâcherais de trouver un moyen de le libérer de son \"\n\"supplice.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Vous parlez d'un courageux guerrier mort depuis longtemps ! Pas question de \"\n\"parler de l'âme des morts dans la cour de mon auberge, merci beaucoup.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Un élixir doré, dites-vous. Je n'ai encore jamais concocté une potion de \"\n\"cette couleur, donc je ne peux pas vous dire ce qu'elle vous ferait si vous \"\n\"essayiez de la boire. En tant que guérisseur, je vous recommande fortement, \"\n\"si vous trouviez un tel élixir, de faire ce que demande Lachdanan et de \"\n\"SURTOUT PAS le boire.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Je n'ai jamais entendu parler d'un Lachdanan auparavant. Je suis désolée, \"\n\"mais je ne pense pas pouvoir vous être d'une grande aide.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Si c'est bien Lachdanan que vous avez rencontré, je serais d'avis que vous \"\n\"l'aidiez. J'ai eu affaire à lui à plusieurs reprises et j'ai vu en lui un \"\n\"homme honnête et loyal. La malédiction qui frappe les compagnons du roi \"\n\"Leoric doit être encore plus terrible pour lui.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\"Lachdanan est mort. Tout le monde sait ça, et vous pouvez pas me berner en \"\n\"me faisant croire autre chose. On peut pas parler aux morts. Je le sais \"\n\"bien !\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Il est possible que vous croisiez des gens piégés dans le Labyrinthe, comme \"\n\"Lachdanan.\\n\"\n\" \\n\"\n\"Je sens en lui de l'honneur et une grande culpabilité. Secourez-le, et vous \"\n\"aiderez Tristram tout entier.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Attendez, attendez. Cain a été englouti dans une gigantesque faille qui \"\n\"s'est ouverte sous ses pieds. Il a été réduit en cendres par une boule de \"\n\"feu des enfers, et ne peut plus répondre à vos questions. Ah non, ce n'est \"\n\"pas ça ? Dans ce cas, je pense que vous allez m'acheter quelque chose ou \"\n\"bien aller voir ailleurs.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"S'il vous plaît, ne me tuez pas, écoutez-moi juste. J'ai été le capitaine \"\n\"des chevaliers du roi Leoric, faisant respecter les lois de ce pays avec \"\n\"justice et honneur. Puis sa sombre malédiction est tombée sur nous pour le \"\n\"rôle que nous avions joué dans sa mort tragique. Alors que mes compagnons \"\n\"chevaliers succombaient à leur destin cruel, je me suis enfui de la chambre \"\n\"funéraire du roi, à la recherche d'un moyen de me libérer de la malédiction. \"\n\"J'ai échoué...\\n\"\n\" \\n\"\n\"J'ai entendu parler d'un Élixir Doré qui pourrait lever la malédiction et \"\n\"donner le repos à mon âme, mais j'ai été incapable de le trouver. À présent \"\n\"ma force décline, et avec elle ce qui reste de mon humanité. Aidez-moi, par \"\n\"pitié, trouvez l'élixir. Je récompenserai vos efforts – je le jure sur mon \"\n\"honneur.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Vous n'avez pas trouvé l'Élixir Doré. Je crains d'être condamné pour \"\n\"l'éternité. S'il vous plaît, continuez d'essayer...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Vous avez sauvé mon âme de la damnation, et je vous en suis redevable. S'il \"\n\"y a quelque moyen de vous rembourser depuis l'au-delà, je le trouverai, mais \"\n\"pour l'instant – prenez mon casque. Pour le voyage que j'entreprends, je \"\n\"n'en aurai guère l'usage. Puisse-t-il vous protéger contre les puissances \"\n\"obscures d'en bas. Allez avec la Lumière, mon ami...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold parle de l'Enclume de Fureur – un artefact légendaire longtemps \"\n\"recherché, mais jamais trouvé. Fabriquée à partir des os métalliques de \"\n\"démons de la Fosse aux Rasoirs, l'Enclume de Fureur a été fondue autour des \"\n\"crânes des cinq mages les plus puissants des enfers. Ciselée de runes de \"\n\"puissance et de chaos, toute arme ou armure forgée sur cette Enclume sera \"\n\"immergée dans le royaume du Chaos, l'imprégnant de propriétés magiques. On \"\n\"dit que de par la nature imprévisible du Chaos, il est difficile de dire ce \"\n\"qui ressortira de cette manœuvre...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Vous ne pensez pas que Griswold serait plus à même de répondre à ceci ? Il \"\n\"est assez habile, vous savez.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Si vous aviez cherché des informations sur le Pilon de Guérison ou le Calice \"\n\"d'Argent de Purification, j'aurais pu vous aider, mon ami. En revanche, dans \"\n\"ce domaine, vous feriez mieux de parler à Griswold ou à Cain.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Quand nous étions enfants, le père de Griswold nous parlait d'une enclume \"\n\"géante qui servait à forger des armes redoutables. Il disait que lorsqu'on \"\n\"frappait d'un marteau sur cette enclume, le sol était secoué d'une grande \"\n\"fureur. À chaque fois que la terre tremble, ça me rappelle cette histoire.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Salutations ! C'est toujours un plaisir de voir un de mes plus fidèles \"\n\"clients ! Je sais que vous vous enfoncez dans le Labyrinthe, et on m'a dit \"\n\"une histoire qui pourrait mériter votre attention...\\n\"\n\" \\n\"\n\"Un des hommes qui est revenu du Labyrinthe m'a parlé d'une enclume mystique \"\n\"qu'il a trouvée en s'échappant. Sa description m'a rappelé des légendes \"\n\"entendues dans ma jeunesse au sujet d'une Forge de l'Enfer ardente où \"\n\"étaient créées de puissantes armes magiques. Selon la légende, au plus \"\n\"profond de la Forge de l'Enfer reposerait l'Enclume de Fureur ! Cette \"\n\"Enclume recèlerait l'essence même du monde souterrain démoniaque...\\n\"\n\" \\n\"\n\"On dit que toute arme forgée sur l'enclume ardente est dotée d'un grand \"\n\"pouvoir. Si cette Enclume est bien l'Enclume de Fureur, je devrais pouvoir \"\n\"vous faire une arme capable de vaincre même le plus sombre des seigneurs de \"\n\"l'enfer !\\n\"\n\"\\n\"\n\"Trouvez-moi l'Enclume et je m'y mets !\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Toujours rien ? Alors continuez à chercher. Une arme forgée sur l'Enclume \"\n\"pourrait être votre meilleur espoir, et je suis sûr de pouvoir vous en faire \"\n\"une digne de légendes.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"J'y crois pas ! C'est l'Enclume de Fureur – beau travail, mon ami. \"\n\"Maintenant, nous allons montrer à ces ordures qu'il n'y a pas d'armes en \"\n\"enfer plus meurtrières que celles forgées par les humains ! Prenez ceci et \"\n\"que la Lumière vous protège.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold peut pas vendre son enclume. Qu'est-ce qu'il pourrait faire, \"\n\"alors ? Et je serais pas content non plus si on me volait mon enclume !\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Il existe de nombreux artefacts dans le Labyrinthe qui détiennent des \"\n\"pouvoirs au-delà de la compréhension des mortels. Certains d'entre eux \"\n\"détiennent un pouvoir fantastique qui peut être utilisé par la Lumière ou \"\n\"les Ténèbres. Sécuriser l'Enclume pourrait faire pencher le cours de la \"\n\"guerre du péché vers la lumière.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Si vous deviez trouver cet artefact pour Griswold, cela pourrait mettre à \"\n\"mal mon bizness. Awwww, vous ne le trouverez jamais.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Le Portail du Sang et les Salles du Feu sont des repères d'origine mystique. \"\n\"Où que se trouve ce livre que vous avez lu, c'est certainement un site d'une \"\n\"grande puissance.\\n\"\n\" \\n\"\n\"Les légendes parlent d'un piédestal sculpté dans de la pierre obsidienne et \"\n\"avec une mare de sang bouillonnant au sommet de sa surface incrustée d'os. \"\n\"Il y a aussi des allusions aux Pierres de Sang qui ouvriront une porte qui \"\n\"garde un trésor antique...\\n\"\n\" \\n\"\n\"La nature de ce trésor est enveloppée de spéculations, mon ami, mais on dit \"\n\"que l'ancien héros Arkaine a placé l'armure sacrée Vaillance dans une \"\n\"chambre forte secrète. Arkaine a été le premier mortel à inverser le cours \"\n\"de la guerre du péché et à repousser les légions des ténèbres jusqu'aux \"\n\"enfers ardents.\\n\"\n\" \\n\"\n\"Juste avant la mort d'Arkaine, son armure fut cachée dans une chambre forte \"\n\"secrète. Il est dit que lorsque cette armure sacrée sera à nouveau \"\n\"nécessaire, un héros apparaîtra pour revêtir Vaillance à nouveau. Peut-être \"\n\"êtes-vous ce héros...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Tous les enfants connaissent l'histoire d'Arkaine le guerrier et de \"\n\"Vaillance, son armure mystique. Si vous pouviez trouver où elle repose, vous \"\n\"seriez bien protégé contre le mal dans le Labyrinthe.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... cela m'évoque vaguement quelque chose, mais j'ai été tellement occupé \"\n\"à développer de nouveaux remèdes et à créer de meilleurs élixirs que j'ai dû \"\n\"oublier. Désolé...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"L'histoire de Vaillance l'armure magique est quelque chose dont j'ai souvent \"\n\"entendu les garçons parler. Vous feriez mieux de demander à l'un des hommes \"\n\"du village.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"L'armure connue sous le nom de Vaillance pourrait être ce qui fera pencher \"\n\"la balance en votre faveur. Je peux vous dire que beaucoup l'ont cherchée – \"\n\"moi y compris. Arkaine l'a bien cachée, mon ami, et il faudra plus qu'un peu \"\n\"de chance pour percer les secrets qui l'ont gardée cachée ces nombreuses \"\n\"années.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Si vous trouvez ces Pierres de Sang, utilisez-les avec précaution.\\n\"\n\" \\n\"\n\"Le chemin est parsemé d'embûches et votre seul espoir réside en votre \"\n\"confiance en vous-même.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Vous avez l'intention de trouver Vaillance, l'armure ?\\n\"\n\" \\n\"\n\"Personne n'a jamais découvert où Arkaine l'a planquée, et si mes contacts \"\n\"n'ont pas pu la trouver, je doute franchement que vous y arriviez.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Je ne connais qu'une seule légende qui parle d'un guerrier tel que vous le \"\n\"décrivez. On trouve son histoire dans les anciennes chroniques de la Guerre \"\n\"du Péché...\\n\"\n\" \\n\"\n\"Taché par mille ans de guerre, de sang et de mort, le Seigneur de Guerre de \"\n\"Sang se dresse sur une montagne de victimes en lambeaux. Sa lame sombre crie \"\n\"une malédiction noire aux vivants ; une invitation torturée à tous ceux qui \"\n\"se présenteraient devant cet Exécuteur de l'Enfer.\\n\"\n\" \\n\"\n\"Il est également écrit que même s'il était autrefois un mortel qui a \"\n\"combattu aux côtés de la Légion des Ténèbres pendant la guerre du péché, il \"\n\"a perdu son humanité à cause de sa faim insatiable de sang.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Je crains de n'avoir jamais entendu parler d'un guerrier aussi vicieux, mon \"\n\"bon maître. J'espère que vous n'aurez pas à le combattre, car il semble \"\n\"terriblement dangereux.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain sera en mesure de vous en dire bien plus sur ce genre de chose que je \"\n\"ne souhaiterais jamais en savoir.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Si vous devez combattre un adversaire aussi féroce, que la Lumière guide vos \"\n\"pas et vous protège. Je serai avec vous en pensées.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Des légendes sombres et cruelles entourent le Seigneur de Guerre de Sang. \"\n\"Préparez-vous bien, mon ami, car il n'a ni pitié ni merci.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Faut toujours que vous parliez de sang ? Et les fleurs, alors, le soleil, et \"\n\"cette jolie nénette qui sert les boissons. Écoutez voir, mon pote, vous êtes \"\n\"obsédé, vous le savez, ça ?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Ses prouesses à l'épée sont prodigieuses et il a vécu des milliers d'années \"\n\"en ne connaissant que la guerre. Je suis désolée... je ne vois pas comment \"\n\"vous pourriez le battre.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Je n'ai jamais eu affaire à votre Seigneur de Guerre, mais il a l'air \"\n\"d'avoir besoin de beaucoup d'épées. Ça ne me dérangerait pas de fournir ses \"\n\"armées...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Ma lame chante pour ton sang, mortel, et par mes maîtres des ténèbres elle \"\n\"ne sera pas déçue.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold parle de la Roche Céleste qui était destinée à l'enclave d'Orient. \"\n\"Elle y était emmenée pour une étude plus approfondie. Cette pierre brillait \"\n\"d'une énergie qui donnait d'une certaine manière une vision supérieure à \"\n\"celle d'un homme normal. Je ne sais quels secrets elle recèle, mon ami, mais \"\n\"trouver cette pierre serait certainement fort appréciable.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"La caravane s'est arrêtée ici le temps de prendre des provisions pour leur \"\n\"voyage vers l'Orient. Je leur ai vendu un bel assortiment de fruits frais et \"\n\"d'excellents ris de veau que Garda venait de finir de cuire. C'est \"\n\"malheureux ce qui leur est arrivé…\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Je ne sais pas ce qu'ils s'imaginaient pouvoir voir avec cette roche, mais \"\n\"je vais vous dire une chose. Si des pierres commencent à tomber du ciel, il \"\n\"vaut mieux être prudent !\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Eh bien, une caravane avec des personnes très importantes s'est arrêtée ici, \"\n\"mais c'était il y a un moment, déjà. Ils avaient de drôles d'accents et \"\n\"entamaient un long voyage, dans mon souvenir.\\n\"\n\" \\n\"\n\"Je ne vois pas comment vous pourriez espérer retrouver quelque chose qu'ils \"\n\"auraient emporté.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Restez un instant – j'ai une histoire qui pourrait vous intéresser. Une \"\n\"caravane en route vers les royaumes de l'Orient est passée par ici il y a \"\n\"quelque temps. Il paraît qu'elle transportait un morceau du paradis qui \"\n\"serait tombé sur terre ! La caravane a été prise en embuscade par des \"\n\"cavaliers encapuchonnés pas loin au nord sur la chaussée. J'ai fouillé les \"\n\"décombres pour trouver cette roche céleste, mais impossible de la trouver. \"\n\"Si vous la trouvez, je pense pouvoir en faire quelque chose d'utile.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"J'attends toujours que vous m'apportiez cette roche céleste. Je sais que je \"\n\"peux en faire quelque chose de puissant.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Laissez-moi voir – oui... oui, c'est bien ce que je pensais. Laissez-moi un \"\n\"moment...\\n\"\n\" \\n\"\n\"Ah, voilà. J'ai serti des morceaux de la roche dans une chevalière en argent \"\n\"que mon père m'avait laissée. J'espère qu'elle vous sera bien utile.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"J'avais une belle bague ; elle avait coûté cher, avec du bleu et du vert et \"\n\"du rouge et de l'argent. Sauf que j'me souviens pas de c'qu'elle est \"\n\"devenue. Qu'est-ce qu'elle me manque, cette bague…\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"La Roche Céleste est très puissante, et si c'était n'importe qui d'autre que \"\n\"Griswold qui vous demandait de la trouver, je l'en empêcherais. Il va \"\n\"réussir à dominer ses pouvoirs et elle servira pour notre bien à tous.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"S'il y a une personne qui peut faire quelque chose de cette roche, c'est \"\n\"bien Griswold. Il sait ce qu'il fait, et j'ai beau essayer de lui piquer ses \"\n\"clients, je respecte la qualité de son travail.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Adria la sorcière cherche un champignon noir ? J'en sais autant sur les \"\n\"champignons noirs que sur les harengs saurs. Peut-être que Pepin le \"\n\"Guérisseur pourrait vous en dire plus, mais c'est quelque chose qu'on ne \"\n\"trouve nulle part dans mes histoires ou dans mes livres.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Je n'ai qu'une chose à dire. Garda et moi-même ne servirons jamais au grand \"\n\"jamais de champignons noirs à nos honorables hôtes. Si Adria veut des \"\n\"champignons dans sa tambouille, c'est son affaire, mais je n'en chercherai \"\n\"pas pour vous. Des champignons noirs... quelle horreur !\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"La sorcière m'a dit que vous cherchiez le cerveau d'un démon pour m'aider à \"\n\"élaborer mon élixir. Il devrait être d'une aide inestimable pour tous ceux \"\n\"qui ont été blessés par ces bêtes immondes, si seulement je pouvais \"\n\"découvrir les secrets que je pressens en son alchimie. Si vous pouviez \"\n\"extraire le cerveau d'un démon lorsque vous en tuerez un, je vous serais \"\n\"reconnaissant de bien vouloir me l'apporter.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Excellent, c'est exactement ce que j'avais en tête. J'ai réussi à mettre au \"\n\"point l'élixir sans ça, mais ça ne peut pas faire de mal de l'étudier. \"\n\"Voudriez-vous s'il vous plaît porter ceci à la sorcière ? Je crois qu'elle \"\n\"l'attend.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"P'têt' ben qu'Ogden pourrait avoir des champignons dans le cellier. Pourquoi \"\n\"vous lui demandez pas ?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Si Adria n'en a pas, vous pouvez être sûr que LÀ, c'est rare. Je ne peux pas \"\n\"vous offrir plus d'aide, mais ça m'a l'air d'un... champignon dodu, énorme, \"\n\"colossal, gargantuesque ! Eh bien, bonne chasse, j'imagine.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden fait du champi noir drôlement raide, mais ça me fout en l'air quand \"\n\"j'en bois. Écoutez, écoutez... je vous donne le secret – la clé, c'est la \"\n\"modération !\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Qu'avons-nous ici ? Intéressant, cela ressemble à un livre de réactifs. \"\n\"Gardez les yeux ouverts pour un champignon noir. Il devrait être bien gros \"\n\"et facile à reconnaître. Si vous le trouvez, apportez-le-moi, vous voulez \"\n\"bien ?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"C'est un gros champignon noir qu'il me faut. Allez, disparaissez et trouvez-\"\n\"le-moi, que je puisse l'utiliser pour une concoction spéciale que je prépare.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Oui, ce sera parfait pour un breuvage que je suis en train de concevoir. Au \"\n\"fait, le guérisseur cherche le cerveau de je ne sais quel démon afin de \"\n\"pouvoir soigner ceux qui souffrent de leur venin empoisonné. Je crois qu'il \"\n\"a l'intention d'en faire un élixir. Si vous l'aidez à trouver ce dont il a \"\n\"besoin, voyez si vous pouvez m'avoir un échantillon de l'élixir.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Mais qu'est ce que vous voulez que j'en fasse ? Je n'ai pas besoin d'un \"\n\"cerveau de démon pour l'instant. J'ai besoin d'un peu de l'élixir sur lequel \"\n\"travaille le Guérisseur. Il a besoin de cet organe grotesque que vous tenez, \"\n\"et ensuite apportez-moi l'élixir. C'est pas si compliqué, quand même, si ?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Quoi ? C'est maintenant que vous m'apportez l'élixir du guérisseur ? J'ai pu \"\n\"finir mon breuvage sans elle. Vous n'avez qu'à le garder...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Je n'ai pas de champignons, d'aucune taille ni d'aucune couleur que ce soit \"\n\"à vendre. Que diriez-vous de quelque chose d'un peu plus utile ?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Ainsi, la légende de la carte est véridique. Même moi, je n'y ai jamais \"\n\"vraiment cru ! J'imagine qu'il est temps que je vous révèle la vérité à mon \"\n\"sujet, mon ami. Voyez-vous, je ne suis pas ce qu'il y paraît…\\n\"\n\" \\n\"\n\"Mon vrai nom est Deckard Cain l'Ancien, et je suis le dernier descendant \"\n\"d'une ancienne Confrérie dont la vocation était de garder et préserver des \"\n\"secrets d'un mal intemporel. Un mal qui bien manifestement est désormais \"\n\"libéré.\\n\"\n\" \\n\"\n\"Le mal que vous affrontez est le sombre Seigneur de la Terreur – connu des \"\n\"mortels sous le nom de Diablo. C'est lui qui fut emprisonné dans le \"\n\"Labyrinthe il y a bien des siècles. Cette carte que vous avez là a été \"\n\"tracée il y a des éons de cela pour marquer le moment où Diablo sortirait de \"\n\"son emprisonnement. Lorsque les deux étoiles sur cette carte s'aligneront \"\n\"ainsi, Diablo sera au sommet de sa puissance, pour ainsi dire invincible...\\n\"\n\" \\n\"\n\"Vous êtes maintenant dans une course contre le temps, mon ami ! Trouvez \"\n\"Diablo et détruisez-le avant que les étoiles ne s'alignent, car nous \"\n\"n'aurons peut-être plus jamais l'occasion de débarrasser le monde de ce mal !\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Le temps presse ! Je sens que son pouvoir obscur grandit et vous seul pouvez \"\n\"l'empêcher d'atteindre sa pleine puissance.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Je suis sûr que vous avez fait votre possible, mais je crains que même votre \"\n\"force et votre volonté ne suffisent pas. Diablo est maintenant au faîte de \"\n\"sa puissance terrestre, et vous aurez besoin de tout votre courage et de \"\n\"votre force pour le vaincre. Que la Lumière vous protège et vous guide, mon \"\n\"ami. Je vous aiderai dans la mesure de mes capacités.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Si la sorcière ne peut pas vous aider et vous suggère de voir Cain, qu'est-\"\n\"ce qui vous fait croire que je saurais quelque chose ? Ça a l'air d'une \"\n\"affaire très sérieuse. Vous devriez vous dépêcher et aller voir le conteur \"\n\"comme le suggère Adria.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Je ne peux pas tirer grand-chose de l'écriture sur cette carte, mais peut-\"\n\"être qu'Adria ou Cain pourraient vous aider à déchiffrer ce que ça dit.\\n\"\n\" \\n\"\n\"Je peux voir que c'est une carte des étoiles dans notre ciel, mais après, \"\n\"cela dépasse mes talents.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"La meilleure personne à consulter sur ce genre de chose serait notre \"\n\"conteur.\\n\"\n\" \\n\"\n\"Cain connaît très bien les écrits anciens, et c'est de loin le plus vieux \"\n\"morceau de papier que j'aie jamais vu.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Je n'ai jamais vu de carte de ce genre auparavant. Où l'avez-vous eue ? Beau \"\n\"que je n'aie aucune idée de comment lire ça, Cain ou Adria devraient pouvoir \"\n\"fournir les réponses que vous cherchez.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Écoutez voir, approchez. Je sais pas si vous savez c'que je sais, mais vous \"\n\"tenez vraiment quéqu'chose là. C'est une carte.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Oh, j'ai bien peur que cela ne présage rien de bon du tout. Cette carte des \"\n\"étoiles laisse présager un grand malheur, mais ce n'est pas à moi de \"\n\"raconter ses secrets. Il est temps pour vous d'avoir une conversation très \"\n\"sérieuse avec le Conteur...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"J'ai cherché une carte, mais ce n'est certainement pas ça. Vous devriez \"\n\"montrer ça à Adria – elle peut probablement vous dire ce que c'est. Je dirai \"\n\"une chose ; ça a l'air vieux, et vieux rime souvent avec précieux.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"S'il vous plaît, pas mal. Pas tuer. Laisser vivre et prochain fois, bon \"\n\"apporté à vous.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Quelque chose pour vous je fais. Encore, pas tuer Gharbad. Vivre et donner \"\n\"bon.\\n\"\n\" \\n\"\n\"Toi prend ça comme preuve je tiens parole...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Rien encore ! Presque fini.\\n\"\n\" \\n\"\n\"Très puissant, très fort. Vivre ! Vivre !\\n\"\n\" \\n\"\n\"Pas douleur et promesse je tiens !\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Ça trop bien pour vous. Très puissant ! Toi veut – toi prend !\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Quoi ? ! Qu'est-ce que vous faites ici ? Toutes ces interruptions, c'est à \"\n\"vous rendre fou. Tenez, prenez ceci et laissez-moi travailler. Ne venez plus \"\n\"m' !\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh ! Votre curiosité sera votre perte ! ! !\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Bonjour mon ami. Restez un instant et écoutez-moi...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"En vous vous aventurant plus loin dans le Labyrinthe, vous y trouverez peut-\"\n\"être des livres de grande connaissance.\\n\"\n\" \\n\"\n\"Lisez-les attentivement car ils pourront vous apprendre des choses que même \"\n\"moi, j'ignore.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Je connais bien des mythes et légendes qui peuvent contenir des réponses aux \"\n\"questions qui pourront se poser lors de vos voyages dans le Labyrinthe. Si \"\n\"vous rencontrez des difficultés et des questions que vous cherchez à \"\n\"élucider, venez me voir et je vous dirai ce que je sais.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold – un homme entreprenant et d'un grand courage. Je parie qu'il ne \"\n\"vous a jamais parlé de la fois où il est allé dans le Labyrinthe pour sauver \"\n\"Wirt ? Il connaît sa juste part des dangers qui s'y trouvent, mais encore \"\n\"une fois, vous aussi. C'est un artisan talentueux, et s'il prétend pouvoir \"\n\"vous être utile d'une quelconque façon, vous pouvez compter sur son \"\n\"honnêteté et son habileté.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden possède et gère la Taverne et Auberge du Soleil Levant depuis près de \"\n\"quatre ans maintenant. Il l'a achetée quelques mois seulement avant que tout \"\n\"ici ne dégénère. Sa femme Garda et lui n'ont pas les moyens de partir car \"\n\"ils ont tout investi pour s'établir ici. C'est un homme bon avec un grand \"\n\"sens des responsabilités.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Pauvre Farnham. Il est un rappel perturbant des pauvres hères qui sont \"\n\"entrés dans la cathédrale avec Lazarus en cette triste journée. Il a eu la \"\n\"vie sauve, mais son courage et une grande partie de sa santé mentale sont \"\n\"restées au fond d'un trou. Il ne trouve de réconfort qu'au fond de sa chope \"\n\"désormais, mais il a de temps en temps quelques éclairs de lucidité au \"\n\"milieu des vapeurs d'alcool.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"La sorcière, Adria, est une anomalie ici à Tristram. Elle est arrivée peu \"\n\"après la profanation de la cathédrale alors que presque tout le monde \"\n\"fuyait. Elle s'est fait construire une petite hutte à la sortie de la ville, \"\n\"apparemment du jour au lendemain, et a accès à de nombreux artefacts \"\n\"étranges et mystérieux et à des livres de connaissance que même moi, je n'ai \"\n\"jamais vus auparavant.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"L'histoire de Wirt est effrayante et tragique. Il a été arraché des bras de \"\n\"sa mère et traîné dans le labyrinthe par les immondes petits démons armés de \"\n\"vilaines lances. Bien d'autres enfants ont été emmenés ce jour-là, dont le \"\n\"fils du roi Léoric. Les chevaliers du palais sont descendus, mais ne sont \"\n\"jamais revenus. Le forgeron a trouvé le garçon, mais seulement après que ces \"\n\"démons ont commencé à le torturer par pur sadisme.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Je le vois comme un véritable ami – peut-être le plus proche que \"\n\"j'ai ici. Il est parfois un peu brouillon, mais il n'y a jamais eu personne \"\n\"de plus attentionné ou prévenant. Ses connaissances et ses compétences sont \"\n\"égalées par peu, et sa porte est toujours ouverte.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian est une brave femme. On l'adore pour sa bonne humeur et son rire \"\n\"facile, elle a une place particulière dans mon cœur. Elle reste à la taverne \"\n\"pour s'occuper de sa grand-mère âgée qui est trop malade pour voyager. J'ai \"\n\"parfois peur pour sa sécurité, mais je sais que n'importe quel homme du \"\n\"village préférerait mourir plutôt que de la savoir en danger.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Salutations, mon bon maître. Bienvenue à la Taverne du Soleil Levant !\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"De nombreux aventuriers ont honoré les tables de ma taverne, et dix fois \"\n\"plus d'histoires ont été racontées avec autant de bière. La seule chose sur \"\n\"laquelle j'en ai jamais entendu s'entendre était ce vieux dicton. Peut-être \"\n\"que cela vous aidera. Vous pouvez couper la chair, mais vous devez écraser \"\n\"l'os.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Griswold le forgeron en connaît un rayon sur les armes et les armures. Si \"\n\"jamais vous avez besoin de faire arranger votre équipement, c'est clairement \"\n\"l'homme de la situation.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham passe bien trop de temps ici, noyant son chagrin dans de la bière \"\n\"bon marché. Je le ferais bien partir, mais il a tant souffert dans le \"\n\"Labyrinthe.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria est plus sage que son âge ne le laisse penser, mais je dois admettre \"\n\"qu'elle me fait un peu peur.\\n\"\n\" \\n\"\n\"Enfin, peu importe. Si jamais vous avez besoin de marchander des objets de \"\n\"sorcellerie, elle tient une hutte étrangement bien approvisionnée juste de \"\n\"l'autre côté de la rivière.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Si vous voulez en savoir plus sur l'histoire de notre village, le conteur \"\n\"Cain en sait long sur le passé.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt est un vaurien doublé d'un petit scélérat. Il s'attirait toujours des \"\n\"ennuis, et ce qui lui est arrivé n'a rien d'étonnant .\\n\"\n\" \\n\"\n\"Il a dû aller faire l'imbécile là où il n'aurait pas dû se trouver. Je suis \"\n\"désolé pour le garçon, mais je ne tolère pas ses fréquentations.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin est un homme bien – et certainement le plus généreux du village. Il \"\n\"est toujours attentif aux besoins d'autrui, mais il semble attirer toutes \"\n\"sortes de problèmes où qu'il aille...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, ma serveuse ? Sans son sens du devoir envers sa grand-mère, elle se \"\n\"serait enfuie d'ici depuis longtemps.\\n\"\n\" \\n\"\n\"Dieu sait que je l'ai suppliée de partir, lui disant que je veillerais sur \"\n\"sa grand-mère, mais elle est trop gentille et attentionnée pour ça.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"De quoi souffrez-vous, mon ami ?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"J'ai fait une découverte fort intéressante. Contrairement à nous, les \"\n\"créatures du Labyrinthe peuvent guérir sans l'aide de potions ou de magie. \"\n\"Si vous blessez un monstre, assurez-vous qu'il soit mort ou il pourrait très \"\n\"bien se régénérer.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Avant qu'elle ne soit envahie par, eh bien, tout ce qui se cache en dessous, \"\n\"la cathédrale était un grand lieu d'apprentissage. On y trouve de nombreux \"\n\"livres. Si vous en trouvez, vous devriez les lire tous, car certains \"\n\"pourraient receler des secrets sur le fonctionnement du Labyrinthe.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold en sait autant sur l'art de la guerre que moi sur l'art de la \"\n\"guérison. C'est un commerçant avisé, mais son travail est sans égal. Oh, \"\n\"peut-être aussi parce que c'est le seul forgeron qui soit resté.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain est un véritable ami et un vrai sage. Sa bibliothèque est bien fournie \"\n\"et il a une capacité innée à discerner la vraie nature de beaucoup de \"\n\"choses. Si jamais vous avez des questions, il est la personne à qui vous \"\n\"adresser.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Même mon savoir-faire n'a pu guérir complètement Farnham. Oh, j'ai certes pu \"\n\"réparer son corps, mais son esprit et son âme sont hors de ma portée.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Si j'emploie certaines formes de magie limitées pour créer les potions et \"\n\"les élixirs que je conserve ici, Adria, elle, est une véritable sorcière. On \"\n\"dirait qu'elle ne dort jamais et elle a toujours à sa disposition à de \"\n\"nombreux grimoires et artefacts mystiques. À mon avis sa hutte est bien plus \"\n\"que le gourbi qu'on croirait, mais pas moyen d'y entrer.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Pauvre Wirt. J'ai fait tout ce qui était possible pour ce pauvre enfant, \"\n\"mais je sais qu'il déteste ce pilon de bois que j'ai dû lui mettre à la \"\n\"jambe. Ses plaies étaient hideuses. Personne – et surtout pas un enfant – ne \"\n\"devrait avoir à souffrir comme ça.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Je ne comprends vraiment pas pourquoi Ogden reste ici à Tristram. Il a beau \"\n\"avoir les nerfs un peu à fleur de peau, c'est un homme intelligent et \"\n\"industrieux qui réussirait partout où il irait. Je suppose que ça pourrait \"\n\"être la peur des nombreux meurtres qui se produisent dans les environs, ou \"\n\"peut-être la volonté de sa femme qui le gardent lui et sa famille là où ils \"\n\"sont.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"La serveuse d'Ogden est une fille adorable. Sa grand-mère est très malade et \"\n\"est sujette aux délires.\\n\"\n\" \\n\"\n\"Elle prétend que ce sont des visions, mais je n'ai aucune preuve dans un \"\n\"sens ou dans l'autre.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Bonjour ! Que puis-je pour votre service ?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Ma grand-mère a rêvé que vous viendriez me voir. Elle a des visions, vous \"\n\"savez, elle peut voir dans l'avenir.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"La femme au bout de la ville est une sorcière ! Elle a l'air plutôt \"\n\"gentille, et son nom, Adria, est très agréable à l'oreille, mais elle me \"\n\"fait très peur.\\n\"\n\" \\n\"\n\"Il faudrait quelqu'un d'assez courageux, comme vous, pour aller voir ce \"\n\"qu'elle fait là-bas.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Notre forgeron est une fierté pour les habitants de Tristram. Non seulement \"\n\"c'est un maître artisan qui a remporté de nombreux concours au sein de sa \"\n\"guilde, mais il a également reçu les éloges de notre roi Leoric lui-même – \"\n\"que son âme repose en paix. Griswold est aussi un grand héros ; allez \"\n\"demander à Cain.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain a toujours été le Conteur de Tristam, autant que je m'en souvienne. Il \"\n\"en sait tellement et il peut vous parler de presque tout sur tout.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham est un ivrogne qui se remplit la panse de bière et inonde de bêtises \"\n\"les oreilles de tout le monde.\\n\"\n\" \\n\"\n\"Je sais que Pepin et Ogden ont de la sympathie pour lui, mais qu'est-ce que \"\n\"ça m'insupporte de le voir sombrer chaque nuit un peu plus dans \"\n\"l'abrutissement.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin a sauvé ma grand-mère, et je sais que je lui en serai toujours \"\n\"redevable. Sa capacité à guérir n'importe quelle maladie est plus puissante \"\n\"que l'épée la plus tranchante et plus mystérieuse que n'importe quel sort \"\n\"que vous connaissez. Si jamais vous avez besoin de soins, Pepin peut vous \"\n\"aider.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"J'ai grandi avec la mère de Wirt, Canace. Bien qu'elle n'ait été que \"\n\"légèrement blessée lorsque ces hideuses créatures ont enlevé son fils, elle \"\n\"ne s'en est jamais remise. Je pense qu'elle est morte de chagrin. Wirt est \"\n\"devenu un jeune homme méchant, ne cherchant qu'à profiter du labeur des \"\n\"autres. Je sais qu'il a souffert et qu'il a vu des horreurs que je ne peux \"\n\"même pas imaginer, mais une partie de cette obscurité plane toujours sur lui.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden et sa femme m'ont accueillie chez eux avec ma grand-mère et m'ont même \"\n\"laissé gagner quelques pièces d'or en travaillant à l'auberge. Je leur dois \"\n\"tant et j'espère un jour quitter cet endroit et les aider à ouvrir un grand \"\n\"hôtel en Orient.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Alors, qu'est-ce que je peux faire pour vous ?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Si vous cherchez une bonne arme, laissez-moi vous montrer ceci. Prenez une \"\n\"arme contondante de base, comme une masse. Ça fonctionne à merveille contre \"\n\"la plupart de ces horreurs mortes-vivantes en bas, et il n'y a rien de mieux \"\n\"pour fracasser de petits squelettes tout secs !\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"La hache ? Ah, ça c'est une bonne arme, équilibrée contre n'importe quel \"\n\"ennemi. Regardez comme elle fend l'air, puis imaginez une bonne tête de \"\n\"démon bien grasse sur son passage. Gardez à l'esprit, quand même, qu'elle \"\n\"est lente à manier – mais elle fait de sacrés dégâts !\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Regardez ce tranchant, cet équilibre. Une épée dans les bonnes mains, et \"\n\"contre le bon adversaire, est la reine de toutes les armes. Sa lame \"\n\"tranchante a du mal à trouver quoi tailler ou percer chez un mort-vivant, \"\n\"mais contre un ennemi bien vivant et respirant, une épée tranchera mieux \"\n\"leur chair !\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Vos armes et armures porteront les stigmates de vos luttes contre les \"\n\"Ténèbres. Si vous me les apportez, avec un peu de travail et une forge bien \"\n\"chaude, je peux les remettre aux mieux de leur forme.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Alors que je dois pratiquement faire passer en contrebande les métaux et les \"\n\"outils dont j'ai besoin avec les caravanes qui longent notre maudite ville, \"\n\"cette sorcière, Adria, a toujours l'air d'obtenir tout ce qu'il lui faut. Si \"\n\"j'avais ne serait-ce qu'un dixième de ses compétences en magie, je pourrais \"\n\"faire des choses vraiment incroyables.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian est une brave pépée. Dommage que sa mémère soit si mal en point, \"\n\"sinon je me serais arrangé pour les tirer d'ici dans une caravane.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Parfois, je pense que Cain parle trop, mais j'imagine que c'est sa vocation. \"\n\"Si je savais rabattre l'acier comme il me rebat les oreilles, je pourrais \"\n\"faire une armure de cour digne d'un empereur !\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"J'étais avec Farnham cette nuit-là où Lazarus nous a entraînés dans le \"\n\"Labyrinthe. Je n'ai jamais revu l'archevêque depuis et je n'aurais peut-être \"\n\"pas survécu si Farnham n'avait pas été à mes côtés. Je crains que l'attaque \"\n\"n'ait laissé son esprit aussi estropié que, eh bien, une autre attaque l'a \"\n\"fait pour ma jambe. Je ne peux pas mener cette bataille pour lui, mais je le \"\n\"ferais si je le pouvais.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Un homme bon qui met les besoins des autres avant les siens. Vous ne \"\n\"trouverez personne à Tristram – ni où que ce soit d'ailleurs – qui aura à \"\n\"redire du guérisseur.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Ce moutard va se mettre dans un sérieux pétrin... ou je devrais peut-être \"\n\"dire “encore”. J'ai bien essayé de l'intéresser à travailler ici et à lui \"\n\"apprendre un métier honnête, mais il préfère les gains faciles du trafic \"\n\"d'objets d'origine douteuse. Je ne peux pas lui en vouloir après ce qui lui \"\n\"est arrivé, mais j'aimerais qu'au moins il fasse attention.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"L'aubergiste n'a pas beaucoup de travail et n'a pas vraiment moyen de faire \"\n\"de l'argent. Il réussit à joindre les deux bouts en fournissant de la \"\n\"nourriture et un logement à ceux qui passent occasionnellement au village, \"\n\"mais ils peuvent tout aussi bien s'enfuir dans la nuit que le payer. S'il \"\n\"n'y avait pas eu les réserves de céréales et de viandes séchées qu'il \"\n\"gardait dans son cellier, eh bien, la plupart d'entre nous seraient morts de \"\n\"faim la première année où tous les environs étaient envahis par les démons.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"On peut même plus boire en paix ?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"La fille qu'apporte les boissons ? Oh, ouais, quelle jolie dame. Et \"\n\"drôlement gentille aussi.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Pourquoi qu'cette vieille peau fait pas quéqu'chose pour changer. Ouais, \"\n\"ouais, elle a des trucs, mais écoutez-moi... elle est pas normale. J'l'ai \"\n\"jamais vue manger ou boire – et on peut pas faire confiance à quéqu'un qui \"\n\"boit pas un minimum.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain est pas çui qu'y dit qu'il est. Ouais, ouais, y raconte des bonnes \"\n\"histoires... Y'en a qui sont vraiment flippantes ou marrantes... mais \"\n\"j'pense qu'il en sait plus qu'y sait qu'y sait.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold ? Ce bon vieux Griswold. Je l'aime comme un frère ! On s'est battu \"\n\"côte à côte, vous savez, quand... on... Lazarus... Lazarus... Lazarus ! ! !\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Héhéhé, j'aime bien Pepin. Il donne tout, vous savez. Écoutez voir, vous \"\n\"d'vriez vraiment essayer de l'connaître. Un bon gars comme ça avec des gens \"\n\"qui veulent toujours de l'aide. Hé, j'pense qu'ça s'rait un peu comme vous, \"\n\"hein héros ? Moi aussi, j'ai été un héros...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt est un môme avec plus de problèmes que moi, et pourtant les problèmes, \"\n\"ça me connaît. Écoutez voir, ce môme est une bonne pâte, mais il en a vu, \"\n\"vous savez ? L'a perdu une jambe ! Y doit marcher avec un morceau de bois. \"\n\"Triste, triste...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden est le meilleur gars de la ville. J'crois pas qu'sa femme m'aime \"\n\"beaucoup, mais tant qu'elle perce les fûts… J'ai l'impression de passer plus \"\n\"de temps avec Ogden qu'la plupart, mais il est tellement gentil avec moi...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Je veux vous dire un truc, pasque j'sais tout là-d'sus. C'est ma spécialité. \"\n\"C'est la meilleure... laaaa meilleure ! C't'autre bière vaut rien depuis \"\n\"qu'ces stupides chiens...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Personne m'é... m'écoute jamais. Quéque part – ch'suis pas trop sûr – mais \"\n\"quéqu'part sous l'église, y'a tout un tas d'or. Qui brille et qui scintille \"\n\"et qu'attend juste que quéqu'un l'prenne.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"J'sais qu'vous avez vos idées à vous, et j'sais qu'vous allez pas m'croire, \"\n\"mais cette arme que vous avez là – elle vaut rien contre ces grosses \"\n\"brutes ! Oh, j'me fiche de c'que dit Griswold, y savent pu rien faire comme \"\n\"avant...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Si j'étais vous... et je l'suis pas... mais si j'l'étais, j'vendrais tout \"\n\"c'barda que vous avez et je me barrerais d'ici. Ce garçon là-bas... Il a \"\n\"toujours quéque chose de bien, mais faut y filer un peu d'or sinon y vous \"\n\"montrera même pas c'qu'il a.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Je sens une âme en quête de réponses...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"La sagesse s'acquiert, elle ne se donne pas. Si vous trouvez un livre de \"\n\"savoir, dévorez ses mots. Si vous deviez déjà avoir une connaissance des \"\n\"mystères des arcanes décrits dans un livre, rappelez-vous – ce niveau de \"\n\"maîtrise peut toujours augmenter.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"La plus grande puissance est souvent la plus courte. Vous trouverez peut-\"\n\"être d'anciens mots de puissance écrits sur des rouleaux de parchemin. La \"\n\"force de ces parchemins réside dans la capacité de l'apprenti ou de l'adepte \"\n\"à les lancer avec la même efficacité. Leur faiblesse est qu'ils doivent \"\n\"d'abord être lus à haute voix et ne peuvent jamais être gardés en tête. \"\n\"Sachez aussi que ces parchemins ne peuvent être lus qu'une seule fois, alors \"\n\"utilisez-les avec parcimonie.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Bien que la chaleur du soleil soit sans commune mesure, la simple flamme \"\n\"d'une bougie est un danger plus redoutable encore. Aucune énergie, aussi \"\n\"grande soit-elle, ne peut être utilisée sans être correctement focalisée. \"\n\"Pour de nombreux sorts, les bâtons ensorcelés peuvent être chargés \"\n\"d'énergies magiques plusieurs fois. J'ai la capacité de restaurer leur \"\n\"puissance – mais sachez que tout a un prix.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"La somme de notre savoir est dans la somme de son peuple. Si vous deviez \"\n\"trouver un livre ou un parchemin que vous ne savez pas déchiffrer, n'hésitez \"\n\"pas à me l'apporter. Si j'arrive à le comprendre, je partagerai mes \"\n\"découvertes.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Pour un homme qui ne connaît que le Fer, il n'y a pas de plus grande magie \"\n\"que l'Acier. Griswold le forgeron est plus sorcier qu'il ne l'imagine. Sa \"\n\"capacité à mêler le feu et le métal est inégalée dans ce pays.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"La corruption a la force de la tromperie, mais l'innocence détient le \"\n\"pouvoir de la pureté. La jeune Gillian a un cœur pur, elle place les besoins \"\n\"de sa matriarche avant les siens. Elle me craint, mais c'est seulement parce \"\n\"qu'elle ne me comprend pas.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Un coffre ouvert dans les ténèbres ne contient pas de plus grand trésor que \"\n\"lorsqu'il est ouvert dans la lumière. Le conteur Cain est une énigme, mais \"\n\"seulement pour ceux qui ne regardent pas. Sa connaissance de ce qui se cache \"\n\"sous la cathédrale est bien plus grande qu'il ne veut bien se l'avouer à lui-\"\n\"même.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Plus haute sera votre foi en un homme, et plus elle tombera de haut. Farnham \"\n\"a perdu son âme, mais pas contre n'importe quel démon. Elle s'est perdue \"\n\"lorsqu'il a vu ses concitoyens trahis par l'Archevêque Lazarus. Il a des \"\n\"connaissances à glaner, mais vous devrez démêler les faits de la divagation.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"La main, le cœur et l'esprit sont capables de miracles lorsqu'ils sont en \"\n\"parfaite harmonie. Pepin le guérisseur lit dans le corps d'une manière dont \"\n\"moi-même suis incapable. Sa capacité à remettre sur pied les malades et les \"\n\"blessés est amplifiée par sa compréhension de la création d'élixirs et de \"\n\"potions. C'est l'un de vos meilleurs alliés dans Tristram.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Il est de nombreuses choses sur l'avenir que l'on ne peut voir, mais le \"\n\"moment venu, ce seront les enfants qui s'en chargeront. Wirt a l'âme \"\n\"noircie, mais il ne représente aucune menace pour la ville ou ses habitants. \"\n\"Ses relations secrètes avec les gamins et les guildes tacites des villes \"\n\"voisines lui permettent d'accéder à de nombreux objets difficiles à trouver \"\n\"à Tristram. Bien que ses méthodes puissent être répréhensibles, Wirt peut \"\n\"vous aider dans votre combat contre les ténèbres envahissantes.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Des murs de terre et un couvert de chaume ne créent pas un foyer. Ogden \"\n\"l'aubergiste est bien plus utile dans cette ville que beaucoup ne le \"\n\"réalisent. Il fournit un abri à Gillian et à sa matriarche, maintient le peu \"\n\"de vie qu'il reste en Farnham et maintient une partie de ce qu'était \"\n\"Tristram autrefois pour tous ceux qui restent dans la ville. Sa taverne, et \"\n\"les plaisirs simples qu'on y trouve encore, donnent un aperçu d'une vie dont \"\n\"les gens d'ici se souviennent. C'est ce souvenir qui continue de nourrir les \"\n\"espoirs qu'ils fondent en vous.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... Par ici...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Tout le monde à Tristram n'a pas une utilité – ou un marché – pour tout ce \"\n\"que vous trouverez dans le labyrinthe. Même pas moi, même si c'est dur à \"\n\"croire.\\n\"\n\" \\n\"\n\"Parfois, il n'y a que vous qui trouverez quoi faire de certaines choses.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Ne croyez pas à tout ce que dit l'ivrogne. Trop de bières ont brouillé sa \"\n\"vue et son bon sens.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Des fois que vous ne l'auriez pas remarqué, je n'achète rien à Tristram. \"\n\"J'importe des produits de qualité. Si vous voulez refourguer de la camelote, \"\n\"voyez ça avec Griswold, Pepin ou cette sorcière, Adria. Je suis sûr qu'ils \"\n\"se jetteront sur tout ce que vous pourrez leur apporter...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Je crois que je dois la vie – ou ce qu'il en reste – au forgeron . Bien sûr, \"\n\"Griswold m'a proposé d'être son apprenti à la forge, et c'est un gars assez \"\n\"chouette, mais je ne me ferai jamais assez d'argent pour... enfin, disons \"\n\"simplement que j'ai des projets particuliers qui demandent pas mal d'argent.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Si j'avais quelques années de plus, je la couvrirais de toutes les richesses \"\n\"que je pourrais rassembler, et croyez-moi, je peux mettre la main sur des \"\n\"trucs très chouettes. Gillian est une fille superbe qui devrait quitter \"\n\"Tristram dès que ça ira. Hmmm... peut-être que je l'emmènerai avec moi quand \"\n\"je m'en irai...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain en sait trop. Il me fait peur, encore plus que cette femme de l'autre \"\n\"côté de la rivière. Il n'arrête pas de me dire à quel point j'ai de la \"\n\"chance d'être en vie et comment mon histoire est prédite dans la légende. À \"\n\"mon avis il déraille.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham – ça c'est un gars qui a de méchants problèmes, et je sais à quel \"\n\"point les problèmes peuvent être sérieux. Il faisait trop confiance à \"\n\"l'intégrité d'un seul homme, et Lazarus l'a conduit dans la gueule du loup. \"\n\"Oh, je sais à quoi ça ressemble là-bas, alors ne commencez pas à me parler \"\n\"de vos plans pour détruire le mal qui habite ce Labyrinthe. Faites juste \"\n\"attention à vos jambes...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Tant que vous n'avez de vous faire recoller quelque chose, il n'y a pas \"\n\"mieux que le vieux Pepin.\\n\"\n\" \\n\"\n\"Si j'avais eu quelques-unes de ces potions qu'il prépare, j'aurais peut-être \"\n\"encore ma jambe...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria me perturbe vraiment. Bien sûr, Cain est flippant avec ce qu'il peut \"\n\"vous dire sur le passé, mais cette sorcière peut voir dans votre passé. Elle \"\n\"aussi, elle a toujours un moyen de trouver tout ce qu'il lui faut. Adria met \"\n\"la main sur plus de marchandises que je n'en ai vu passer les portes du \"\n\"Bazar du Roi pendant le Haut Festival.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden est un imbécile de rester ici. Je pourrais le faire sortir de la ville \"\n\"pour un prix très raisonnable, mais il persiste à essayer de vivre de cette \"\n\"stupide taverne. Je suppose qu'au moins il donne un boulot à Gillian, et \"\n\"puis sa femme Garda fait une tourte du berger épatante...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Au-delà du Panthéon des Héros se trouve la Chambre des Ossements. La mort \"\n\"éternelle attend quiconque chercherait à voler les trésors se trouvant dans \"\n\"cette pièce. Ainsi parle le Seigneur de la Terreur, et ainsi est-il écrit.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"... et ainsi, enfermé derrière le Portail du Sang et au-delà de la Salle du \"\n\"Feu, Vaillance attend que le Héros de la Lumière se réveille...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Tu ne peux le voir,\\n\"\n\"          mais moi je le puis.\\n\"\n\"Vision laiteuse et\\n\"\n\"          prunelles pourries.\\n\"\n\"Quand tu te retournes,\\n\"\n\"          ils s'en sont allés,\\n\"\n\"Tout en chuchotant\\n\"\n\"          leur chanson cachée.\\n\"\n\"Puis l'impossible\\n\"\n\"          tu vois qui t'entoure,\\n\"\n\"Des ombres qui dansent,\\n\"\n\"          où était le jour.\\n\"\n\"À force de nuit,\\n\"\n\"          sans force tu beugles,\\n\"\n\"Abandonné dans le Hall des Aveugles.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Les armureries de l'Enfer abritent le Seigneur de Guerre de Sang. Dans son \"\n\"sillage gisaient les corps mutilés de multitudes. Anges et hommes ont été \"\n\"abattus pour accomplir ses sacrifices sans fin envers les Ténèbres qui \"\n\"crient pour une seule chose : du sang.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Voyez et soyez témoins des vérités ci-après, car elles sont le dernier \"\n\"héritage des Horadrim. Il est une guerre qui fait rage encore aujourd'hui, \"\n\"au-delà des domaines que nous connaissons – entre les royaumes utopiques du \"\n\"Paradis Céleste et les profondeurs chaotiques des Enfers Ardents. Cette \"\n\"guerre est connue sous le nom de Grand Conflit, et elle a fait rage et a \"\n\"brûlé plus longtemps que n'importe quelle étoile dans le ciel. Aucun des \"\n\"deux partis ne prend jamais longtemps l'avantage car les forces de la \"\n\"Lumière et des Ténèbres se disputent sans cesse le contrôle de toute la \"\n\"création.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Voyez et soyez témoins des vérités ci-après, car elles sont le dernier \"\n\"héritage des Horadrim. Lorsque le conflit éternel entre le Paradis Céleste \"\n\"et les Enfers Ardents s'abattit sur le sol des mortels, on l'appela la \"\n\"Guerre du Péché. Des anges et des démons se mêlèrent à l'humanité sous une \"\n\"fausse apparence, combattant en secret, loin des regards indiscrets des \"\n\"mortels. Certains mortels audacieux et puissants s'allièrent même à l'un ou \"\n\"l'autre parti et contribuèrent à orienter le cours de la guerre du péché.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Voyez et soyez témoins des vérités ci-après, car elles sont le dernier \"\n\"héritage des Horadrim. Il y a près de trois cents ans, on apprit que les \"\n\"Trois Démons Primordiaux des Enfers Ardents étaient mystérieusement arrivés \"\n\"dans notre monde. Les Trois Frères ravagèrent les terres de l'Est des \"\n\"décennies durant, tandis que l'humanité tremblait dans leur sillage. Notre \"\n\"Ordre – les Horadrim – fut fondé par un groupe de mages discrets pour \"\n\"traquer et capturer les Trois Démons une fois pour toutes.\\n\"\n\" \\n\"\n\"Les Horadrim originels capturèrent deux des Trois au sein de puissants \"\n\"artefacts connus sous le nom de Pierre d'âmes et les enfouirent profondément \"\n\"sous les sables désolés de l'Est. Le troisième Mal échappa à la capture et \"\n\"s'enfuit vers l'ouest avec de nombreux Horadrim à ses trousses. Le troisième \"\n\"mal – connu sous le nom de Diablo, le Seigneur de la Terreur – fut \"\n\"finalement capturé, et son essence placée dans une Pierre d'âme et enterrée \"\n\"dans ce labyrinthe.\\n\"\n\" \\n\"\n\"Soyez prévenus que la pierre d'âme ne doit pas être découverte par ceux qui \"\n\"ne sont pas de la foi. Si Diablo devait être libéré, il chercherait un corps \"\n\"facilement contrôlable car il serait très faible – peut-être celui d'un \"\n\"vieillard ou d'un enfant.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Or donc il arriva qu'une grande révolution se fit au sein des Enfers \"\n\"Ardents, qu'on nomma le Sombre Exil. Les Démons Inférieurs renversèrent les \"\n\"Trois Démons Primordiaux et bannirent leur forme spirituelle dans le royaume \"\n\"des mortels. Les démons Belial (le Seigneur du Mensonge) et Azmodan (le \"\n\"Seigneur du Péché) s'affrontèrent pour revendiquer la souveraineté sur \"\n\"l'Enfer en l'absence des Trois Frères. Tout l'Enfer se polarisa entre les \"\n\"factions de Belial et d'Azmodan tandis que les forces du Paradis Céleste \"\n\"s'abattaient sans relâche sur les Portes mêmes de l'Enfer.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"De nombreux démons voyagèrent jusqu'au royaume des mortels à la recherche \"\n\"des Trois Frères. Ces démons furent suivis jusque dans le plan des mortels \"\n\"par des Anges qui les traquèrent à travers les vastes cités de l'Est. Les \"\n\"Anges s'allièrent à un Ordre discret de mages mortels nommé les Horadrim, \"\n\"qui devinrent rapidement versés dans la chasse aux démons. Ceux-là se firent \"\n\"également de nombreux et implacables ennemis dans les enfers.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Or donc il arriva que les Trois Démon Primordiaux furent bannis sous forme \"\n\"d'esprit dans le royaume des mortels et après avoir semé le chaos à travers \"\n\"l'Est pendant des décennies, ils furent pourchassés par l'Ordre maudit des \"\n\"mortels Horadrim. Les Horadrim firent usage d'artefacts nommés Pierres d'âme \"\n\"pour contenir l'essence de Mephisto, le Seigneur de la Haine et de son frère \"\n\"Baal, le Seigneur de la Destruction. Le plus jeune frère – Diablo, le \"\n\"Seigneur de la Terreur – s'échappa vers l'ouest.\\n\"\n\" \\n\"\n\"Finalement, les Horadrim capturèrent à son tour Diablo dans une pierre d'âme \"\n\"et l'ensevelirent sous une ancienne Cathédrale oubliée. C'est là que le \"\n\"Seigneur de la Terreur dort, attendant le jour de sa renaissance. Sachez \"\n\"qu'il cherchera à posséder un corps jeune et puissant – un corps innocent et \"\n\"facilement contrôlable. Il se relèvera alors pour libérer ses frères et \"\n\"attiser à nouveau les flammes de la Guerre du Péché...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Louanges à Diablo – Seigneur de la Terreur et survivant du Sombre Exil. \"\n\"Lorsqu'il sortit de son long sommeil, mon Seigneur et Maître me parla de \"\n\"secrets que peu de mortels connaissent. Il me dit que les royaumes du \"\n\"Paradis Céleste et les fosses des Enfers Ardents étaient engagés dans une \"\n\"guerre éternelle. Il révéla les pouvoirs qui avaient causé cette discorde \"\n\"dans les royaumes des Hommes. Mon seigneur a nommé la bataille pour gagner \"\n\"ce monde et tous ceux qui y vivent la Guerre du Péché.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Gloire et Approbation à Diablo – Seigneur de la Terreur et Chef des Trois. \"\n\"Mon Seigneur m'a parlé de ses deux Frères, Méphisto et Baal, qui furent \"\n\"bannis de ce monde il y a longtemps. Mon Seigneur souhaite attendre son \"\n\"heure et atteler sa puissance inouïe à la libération de ses frères captifs \"\n\"de leurs tombes sous les sables de l'Orient. Une fois que mon Seigneur aura \"\n\"libéré ses frères, la Guerre du Péché connaîtra à nouveau la fureur des \"\n\"Trois.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Salutation et Sacrifice pour Diablo – Seigneur de la terreur et Destructeur \"\n\"d'Âmes. Lorsque je tirai mon Maître de son sommeil, il tenta de prendre la \"\n\"forme d'un mortel. Diablo tenta de s'emparer du corps du roi Leoric, mais \"\n\"mon maître était trop faible en raison de son emprisonnement. Mon Seigneur \"\n\"avait besoin d'un ancrage simple et innocent dans ce monde, et trouva alors \"\n\"le petit Albrecht parfait pour cette tâche. Alors que le bon roi Leoric \"\n\"avait été rendu fou par la tentative de possession infructueuse de Diablo, \"\n\"j'enlevai son fils Albrecht et l'amenai devant mon Maître. J'attends \"\n\"maintenant l'appel de Diablo et prie pour que je sois récompensé quand il \"\n\"apparaîtra enfin comme le Seigneur de ce monde.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Dieu merci, vous êtes de retour !\\n\"\n\"Beaucoup de choses ont changé depuis que vous ne vivez plus ici, mon ami. \"\n\"Tout était paisible jusqu'à ce que les cavaliers noirs arrivent et \"\n\"détruisent notre village. Beaucoup de gens ont été abattus sur place, et \"\n\"ceux qui s'étaient armés ont été tués ou emmenés de force pour devenir des \"\n\"esclaves – ou pire encore. L'église au bout de la ville a été profanée et \"\n\"sert à de sombres rituels. Les cris qui résonnent dans la nuit sont \"\n\"inhumains, mais certains de nos concitoyens pourraient encore être en vie. \"\n\"Suivez le chemin entre ma taverne et la forge pour trouver l'église et \"\n\"sauver qui vous pouvez.\\n\"\n\" \\n\"\n\"Je pourrai peut-être vous en dire plus si nous reparlons. Bonne chance.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Continuez votre quête. Trouver un trésor perdu n'est pas facile. Trouver un \"\n\"trésor caché encore moins. Je vous laisse avec ceci. Ne laissez pas les \"\n\"sables du temps troubler votre recherche.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Un quoi ? ! C'est de la folie. Il n'y a pas de trésor enterré ici à \"\n\"Tristram. Faites voir ça ! ! Ah, tenez, ces dessins sont inexacts. Ils ne \"\n\"correspondent pas du tout à notre ville. Si j'étais vous je resterais \"\n\"concentré sur ce qui se trouve sous la cathédrale et non sur ce qui se \"\n\"trouve sous la glèbe.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Je n'ai vraiment pas le temps de discuter d'une carte que vous \"\n\"rechercheriez. J'ai beaucoup de malades qui ont besoin de mon aide et aussi \"\n\"de la vôtre.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Izual autrefois fier est piégé loin sous la surface de ce monde. Dépouillé \"\n\"de son honneur avec le visage modifié. Il est piégé dans un tourment \"\n\"immortel. Chargé de cacher la chose même qui pourrait le libérer.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Je parie que Wirt vous a vu arriver et a voulu vous jouer un tour afin de se \"\n\"moquer de vous plus tard quand vous auriez couru dans la ville le nez dans \"\n\"la boue. Si j'étais vous je l'ignorerais.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Il fut un temps où cette ville était une étape fréquente pour les voyageurs \"\n\"venus de partout. Cela a bien changé depuis. Mais les grottes cachées et les \"\n\"trésors enfouis sont des fantasmes communs à tous les enfants. Wirt se livre \"\n\"rarement à des jeux d'enfant. C'est peut-être simplement son imagination.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Écoutez voir. Rapprochez-vous. Je sais pas si vous savez ce que je sais, \"\n\"mais vous avez vraiment quelque chose. C'est une carte.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Ma grand-mère me raconte souvent des histoires sur les forces étranges qui \"\n\"hantent le cimetière aux abords de l'église. Et cela pourrait bien vous \"\n\"intéresser d'entendre l'une d'entre elles. Elle a dit que si vous laissez \"\n\"une offrande appropriée dans le cimetière, entrez dans la cathédrale prier \"\n\"pour les morts, puis revenez, l'offrande serait alors devenue étrangement \"\n\"différente. Je ne sais pas s'il s'agit simplement du discours d'une vieille \"\n\"femme malade, mais tout semble possible de nos jours.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Hmmm. Un trésor immense et mystérieux vous dites. Mmmm. Peut-être que ça \"\n\"pourrait m'intéresser de faire affaire avec vous. Ou mieux encore, n'avez-\"\n\"vous pas besoin de fournitures rares et chères pour surmonter cette épreuve ?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Alors, vous êtes le héros dont tout le monde parle. Peut-être pourriez-vous \"\n\"aider un pauvre et simple fermier à sortir d'une très mauvaise situation ? \"\n\"Au bord de mon verger, juste au sud d'ici, il y a une chose horrible qui \"\n\"sort du sol ! Je ne peux plus accéder à mes récoltes ni à mes bottes de \"\n\"foin, mes pauvres vaches vont mourir de faim. La sorcière m'a donné ceci et \"\n\"a dit que cela ferait exploser cette chose hors de mon champ. Si vous \"\n\"pouviez la détruire, je vous en serais éternellement reconnaissant. Je le \"\n\"ferais bien moi-même, mais quelqu'un doit rester ici avec les vaches...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Je savais bien que ça ne pouvait pas être aussi simple que le disait cette \"\n\"sorcière. C'est un triste monde quand vous ne pouvez même pas faire \"\n\"confiance à vos voisins.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Cette chose est partie ? L'avez-vous renvoyée dans les recoins sombres \"\n\"d'Hadès qui l'ont engendrée ? Vous avez quoi ? Oh, ne me dites pas que vous \"\n\"l'avez perdu ! Ces choses ne sont pas bon marché, vous savez. Vous devez la \"\n\"trouver, puis faire exploser cette horreur hors de notre village.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"J'ai entendu l'explosion d'ici ! Un grand merci à vous, brave étranger. Avec \"\n\"toutes ces choses qui sortent de terre, les monstres qui s'emparent de \"\n\"l'église, tout ça... Ce sont des temps difficiles. Je ne suis qu'un pauvre \"\n\"fermier, mais prenez ceci avec toute ma gratitude.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Oh, j'ai un grave problème... peut-être que... Non, je ne pourrais pas vous \"\n\"imposer cela, en plus des autres problèmes. Peut-être qu'après avoir nettoyé \"\n\"l'église d'une partie de ces créatures, vous pourriez revenir... et trouver \"\n\"un peu de temps pour aider un pauvre fermier ?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Waaaah ! (sniff) Waaaah ! (sniff)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"J'ai perdu Théo ! J'ai perdu mon meilleur ami ! On jouait au bord de la \"\n\"rivière, et Theo a dit qu'il voulait aller voir le gros truc vert. Je lui ai \"\n\"dit qu'il ne fallait pas, mais on y est allé en cachette, et puis d'un coup, \"\n\"cette BESTIOLE est sortie ! On s'est sauvé mais Théo est tombé et la \"\n\"bestiole l'a CHOPÉ et l'a emmené !\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Vous l'avez trouvé ? Vous devez retrouver Theodore, s'il vous plaît ! C'est \"\n\"qu'un petit. Il sait pas prendre soin de lui ! S'il vous plaît !\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Vous l'avez retrouvé ! Vous l'avez retrouvé ! Merci ! Oh Theo, ces méchants \"\n\"insectes t'ont fait peur ? Hé ! Beurk ! T'as un truc collé sur les poils ! \"\n\"Dégueu ! Allez, Theo, on rentre à la maison ! Merci encore, héros !\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Nous avons dormi longtemps et le temps est venu de nous réveiller. Après \"\n\"notre long sommeil nous sommes épris d'une faim insatiable. Bientôt, \"\n\"maintenant, nous allons nous nourrir...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"T'es-tu bien amusé, petit mammifère ? Pathétique. Ton petit monde ne posera \"\n\"aucune difficulté.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Ces terres seront souillées et notre progéniture envahira ces étendues que \"\n\"les hommes appellent leur maison. Nos vrilles envelopperont ce monde, et \"\n\"nous nous régalerons de la chair de ses habitants. L'homme deviendra notre \"\n\"bétail et notre subsistance.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, je peux te sentir... tu es proche ! Proche ! Ssss... l'odeur du sang et \"\n\"de la peur... comme c'est alléchant...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Et durant l'année de la Lumière Dorée, il fut ainsi décrété qu'une grande \"\n\"Cathédrale serait érigée. La pierre angulaire de ce lieu saint devait être \"\n\"taillée dans la pierre translucide Antyrael, du nom de l'Ange qui partageait \"\n\"son pouvoir avec les Horadrim.\\n\"\n\" \\n\"\n\"Durant l'année du Dessin des Ombres, le sol trembla et la cathédrale se \"\n\"fissura puis tomba. Alors que la construction de catacombes et de châteaux \"\n\"commençait et que l'homme se dressait contre les ravages de la Guerre du \"\n\"Péché, les ruines furent récupérées pour leurs pierres. Et c'est ainsi que \"\n\"la pierre angulaire disparut des yeux de l'homme.\\n\"\n\" \\n\"\n\"La pierre était de ce monde – et de tous les mondes – car la Lumière est à \"\n\"la fois en toutes choses et au-delà de toutes choses. La lumière et l'unité \"\n\"sont les produits de ce fondement saint, une unité de but et une unité de \"\n\"possession.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Meuh.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"J'ai dit, Meuh.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Bon, je suis juste une vache, OK ?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"D'accord, d'accord. Je ne suis pas vraiment une vache. En temps normal, je \"\n\"ne me promène pas comme ça ; mais, alors que j'étais assis à la maison à \"\n\"vaquer à mes occupations, d'un coup, ces insectes, vignes, bulbes et autres \"\n\"trucs ont commencé à surgir du sol... c'était horrible ! Si seulement \"\n\"j'avais quelque chose de normal à porter, ce ne serait pas si mal. Hé ! \"\n\"Pourriez-vous retourner chez moi et me chercher mon costume ? Le marron, pas \"\n\"le gris, il est pour les tenues de soirée. Je le ferais bien moi-même, mais \"\n\"je ne veux pas qu'on me voie comme ça. Tenez, prenez ceci, vous pourriez en \"\n\"avoir besoin... pour tuer ces choses qui ont tout envahi. Vous ne pouvez pas \"\n\"manquer ma maison, elle est juste au sud de la fourche de la rivière... vous \"\n\"savez... celle avec le potager envahi par la végétation.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Pourquoi perdez-vous du temps ? Allez chercher mon costume ! Et dépêchez-\"\n\"vous ! Ce Holstein là-bas n'arrête pas de me faire des clins d'œil !\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hé, vous avez mon costume ? Vite, donnez-le moi ! Vous n'imaginez même pas à \"\n\"quel point ces oreilles me démangent !\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Non Non Non Non ! C'est mon costume GRIS ! C'est pour les tenues de soirée ! \"\n\"Les occasions formelles ! Je ne peux pas porter CECI. Mais qui êtes-vous, \"\n\"une sorte de cinglé ? J'ai besoin du costume MARRON.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, c'est BEAUCOUP mieux. Ouf ! Enfin un peu de dignité ! Mes bois sont-ils \"\n\"droits ? Bon. Écoutez, merci beaucoup de m'avoir aidé. Tenez, prenez ceci \"\n\"comme cadeau ; et, vous savez... un petit conseil de mode... vous pourriez \"\n\"utiliser un petit... vous pourriez utiliser un nouveau... vous savez ce que \"\n\"je veux dire ? Tout ces motifs d'aventurier sont tellement... rétro. Juste \"\n\"un conseil, hein ? Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Regardez. Je suis une vache. Et vous, vous êtes un appât à monstre. Allez \"\n\"acquérir de l'expérience ! Nous reparlerons...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Cela doit être une tâche vraiment redoutable que je vous ai assignée. S'il y \"\n\"avait un moyen que je puisse... est-ce qu'un flacon de bon lait frais \"\n\"aiderait ?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Oh, j'aurais besoin de votre aide, mais peut-être après que vous aurez sauvé \"\n\"les catacombes de la profanation de ces bêtes.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"J'ai besoin que quelque chose soit fait, mais je ne pouvais pas m'imposer à \"\n\"un parfait inconnu. Peut-être qu'après certain temps ici, je me sentirais \"\n\"plus à l'aise à l'idée de demander une faveur.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Je vois en vous le potentiel de la grandeur. Peut-être qu'un jour alors que \"\n\"vous accomplirez votre destin, vous pourriez passer et me faire une petite \"\n\"faveur ?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Je pense que vous pourriez m'aider, mais peut-être après que vous serez \"\n\"devenu un peu plus puissant. Je ne voudrais pas nuire à la seule chance du \"\n\"village de détruire la menace qui réside dans l'église !\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Moi, je suis une vache qui s'est faite toute seule. Faites quelque chose de \"\n\"vous-même, et... ensuite nous parlerons.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Je n'ai pas à m'expliquer à chaque touriste qui passe ! N'avez-vous pas des \"\n\"monstres à tuer ? Peut-être que nous parlerons plus tard. Si vous survivez...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Arrêtez de m'embêter. Je cherche quelqu'un de vraiment héroïque. Et vous ne \"\n\"l'êtes pas. Je ne peux pas vous faire confiance, vous allez vous faire \"\n\"dévorer par des monstres d'un jour à l'autre... J'ai besoin d'un héros \"\n\"expérimenté.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"D'accord, je vais être honnête. Je ne voulais pas vous tromper. J'étais \"\n\"assis chez moi, me sentant de meuh-vaise humeur, quand les choses se sont \"\n\"gâtées ; toute une vague de monstres est sortie du sol ! C'est vache. Il se \"\n\"trouve que je portais ce maillot quand je suis sorti en courant, et \"\n\"maintenant j'ai l'air complètement ridicule. Si seulement j'avais quelque \"\n\"chose de normal à porter, ce ne serait pas si mal. Hé ! Pouvez-vous \"\n\"retourner chez moi et me chercher mon costume ? Le marron, pas le gris, il \"\n\"est pour les tenues de soirée. Je le ferais bien moi-même, mais je veux ne \"\n\"veux pas qu'on me voie comme ça. Tenez, prenez ceci, vous pourriez en avoir \"\n\"besoin... pour tuer ces choses qui ont tout envahi. Vous ne pouvez pas \"\n\"manquer ma maison, elle est juste au sud de la fourche de la rivière... vous \"\n\"savez... celle avec le potager envahi par la végétation.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"J'ai essayé les sorts, les menaces, l'abjuration et le marchandage avec \"\n\"cette créature immonde – en vain. Mes méthodes pour asservir ces démons \"\n\"mineurs semblent n'avoir aucun effet sur cette bête redoutable.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Ma maison se voit lentement corrompre par la turpitude de ce prisonnier \"\n\"indésirable. Les cryptes sont pleines d'ombres qui se déplacent au-delà de \"\n\"mon champ de vision. Les grattements de griffes dansent aux limites de mon \"\n\"ouïe. Ils cherchent, je pense, ce journal.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Dans sa diatribe, la créature a laissé échapper son nom – Na-Krul. J'ai \"\n\"essayé de faire des recherches sur ce nom, mais ces démons mineurs ont \"\n\"malheureusement détruit ma bibliothèque. Na-Krul... Ce nom me remplit d'une \"\n\"terreur froide. Je préfère ne l'appeler que la Créature plutôt que de \"\n\"prononcer son vrai nom.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Les hurlements de fureur de la créature piégée m'empêchent de dormir malgré \"\n\"la fatigue. Il enrage contre celui qui l'a envoyé dans le Néant, et il \"\n\"invoque d'ignobles malédictions contre moi pour l'avoir piégé ici. Ses mots \"\n\"emplissent mon cœur de terreur, et malgré ça je n'arrive pas à bloquer sa \"\n\"voix.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Il ne me reste plus beaucoup de temps. Je dois écrire les moyens d'affaiblir \"\n\"le démon, puis cacher ce texte, de peur que ses serviteurs ne trouvent un \"\n\"moyen d'utiliser mes connaissances pour libérer leur seigneur. J'espère que \"\n\"quiconque trouvera ce journal cherchera la connaissance.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Celui qui trouve ce parchemin est chargé d'arrêter la créature démoniaque \"\n\"qui se trouve entre ces murs. Mon temps est écoulé. Aujourd'hui encore, ses \"\n\"serviteurs infernaux griffent la frêle porte derrière laquelle je me cache.\\n\"\n\" \\n\"\n\"J'ai entravé le démon avec de la magie des arcanes et je l'ai enfermé dans \"\n\"de grands murs, mais je crains que cela ne suffise pas.\\n\"\n\" \\n\"\n\"Les sorts trouvés dans mes trois grimoires vous fourniront un accès protégée \"\n\"vers son domaine, mais seulement s'ils sont lancés dans le bon ordre. Les \"\n\"leviers à l'entrée lèveront les barrières et libéreront le démon ; ne les \"\n\"touchez pas ! N'utilisez que ces sorts pour entrer ou j'ai bien peur que son \"\n\"pouvoir ne soit trop grand pour que vous puissiez le vaincre.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Sanglier Infernal\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Piqueur\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psychorbe\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Arachnon\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Frères Déchus\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Engeance d'Hork\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Queue de venin\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Nécromorbe\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Seigneur Araignée\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Ver Tordu\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Flamboyant\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Insecte de l'Enfer\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Fossoyeur\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Rat des tombes\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Chauve-souris de Feu\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Aile-Crâne\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Liche\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Démon de la Crypte\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Chauve-souris Infernale\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Démon Osseux\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Archi-Liche\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biclops\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Monstre de Chair\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Faucheur\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Poing du Géant\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Anneau Mercuriel\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Anneau de Xorine\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Anneau de Karik\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Anneau de Magma\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Anneau des Mystiques\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Anneau du Tonnerre\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Amulette de Tutelle\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Piqûre de Moucheron\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Flambeau\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Armure des Ténèbres\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Blitzen\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Coup de Tonnerre\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Mangeur d'Âmes\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Fil de Diamant\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Armure en Mailles d'os\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Armure de plaques de démon\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Amulette d'Acolyte\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Anneau de Gladiateur\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"du Fou\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"d'Outre-Terre\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"du Métamorphe\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"de Dévastation\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"de Flétrissure\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"de Péril\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"le Mage\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"le Fou\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Mur de Foudre\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Immolation\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Déplacement\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Déviation\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Berserk\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Anneau de Feu\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Recherche\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Rune de Feu\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Rune de Lumière\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Rune de Nova\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Rune d'Immolation\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Rune de Pierre\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \" \"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Options:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"version {:s}\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Réduire le Gamma\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Augmenter le Gamma\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Pas de carte en ville\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Redémarrer en ville\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Cœur\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"récupère de la vie\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"guérison mortelle\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"diminue la force\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"diminue la dextérité\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"diminue la vitalité\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"vous ne pouvez pas guérir\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"le monstre touché ne guérit pas\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Attaque plus rapide\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"voir avec infravision\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Vous essayez de déposer un objet au sol ?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Force la synchronisation verticale. Empêche l'effet de déchirure lors de \"\n#~ \"mouvement verticaux. La désactiver peut réduire la latence du curseur sur \"\n#~ \"certains systèmes.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Limiter les IPS\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Le nombre d'images par seconde est limité pour éviter une charge \"\n#~ \"processeur élevée. La limite tient compte du taux de rafraîchissement.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Toucher\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Échec de l'ouverture de l'archive du joueur (écriture)\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Impossible de lire l'archive de sauvegarde\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Impossible d'écrire l'archive de sauvegarde\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Indestructible, \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Aucun attribut requis\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"Après le Corridor des Héros se trouve la Chambre d'Os. La mort éternelle \"\n#~ \"attend quiconque chercherait à s'emparer des trésors conservés dans cette \"\n#~ \"pièce. Ainsi parle le Seigneur de la Terreur, et ainsi est-il écrit.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"Les armureries de l'Enfer abritent le Seigneur de Guerre de Sang. Dans \"\n#~ \"son sillage gisaient les corps mutilés de multitudes. Anges et hommes ont \"\n#~ \"été abattus pour accomplir ses sacrifices sans fin envers les Ténèbres \"\n#~ \"qui crient pour une seule chose : du sang.\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Nuageux et plus frais aujourd'hui. Jeter les filets de la nécromancie \"\n#~ \"dans le vide a fait tomber deux nouvelles sous-espèces de ces horreurs \"\n#~ \"volantes ; une bonne journée de travail. Ne pas oublier de commander \"\n#~ \"encore plus de guano de chauve-souris et de bougies noires à Adria ; je \"\n#~ \"vais commencer à manquer.\"\n"
  },
  {
    "path": "Translations/glossary.md",
    "content": "# Translations glossary\n\n## Variables\n\nThere are two types of variables in the text files: `%s`, `%i`. All of these will add something within the single string, here are some examples.\n\n`%s` will always be another word. Example: `%s of %s` refers to an created Item which includes affixes. `Tin Cap of the Fool` would be such an item.\n`%i` will always be a number. Example: `Fire hit damage: %i-%i` will indicate how much fire damage a weapon will deal.\n\n**IMPORTANT**: You have to keep those intact and in the same order.\n\n### Example\n\nWorking:\n\n\t`%s' (level %i) just joined the game`\nchanged to\n\t`%s' (level %i) is now with you.`\n\nNot working:\n\n\t`%s' (level %i) just joined the game`\nchanged to\n\t`A level %i Character named % s' is now with you.`\n\n## %s of %s\n\nThe rather tricky line `%s of %s` is used to create items with pre- and suffixes as mentioned in examples above. If your language has gendered articles it might be advisable to remove the \"of\" but add a gendered article to each suffix instead. If you do so the line should be changed to `%s %s` and you will have to add the appropriate article to each suffix.\n\n## Adding lines\n\nUnfortunately it is not possible to add new lines for languages outside of quest texts.\n\n## Names\n\nPlease try to keep original names intact, however it's up to your judgment to change something that sounds completely wrong in the language you are translating to.\n\n## Coherence\n\nMake sure that you use the same terminology where it's applicable. \n\nExample:\n\nGood:\n\t`fully recover life`\n\t`recover life`\n\t`fully recover mana`\n\t`recover mana`\n\nBad:\n\t`recover all life points`\n\t`recover partial life`\n\t`fully recover mana`\n\t`recover mana`\n\n## References\n\nDon't worry – we all forget details. Here's a list of resources you can use if you are unsure about a thing.\n\n### Creatures\n\n* Diablo Creatures - [Diablo Archive](https://diablo-archive.fandom.com/wiki/Monsters_(Diablo_I))\n* Diablo Unique Creatures - [Diablo Archive](https://diablo-archive.fandom.com/wiki/Category:Diablo_I_Unique_Monsters)\n* Hellfire Creatures - [Diablo Wiki](https://diablo.fandom.com/wiki/Hellfire_Bestiary)\n\n### Items and Equipment References and Pictures\n\n* Diablo Unique Weapons - [Diablo Archive](https://diablo-archive.fandom.com/wiki/Unique_Weapons_(Diablo_I))\n* Diablo Normal Weapons - [Diablo Archive](https://diablo-archive.fandom.com/wiki/Normal_Weapons_(Diablo_I))\n* Diablo and Hellfire Unique Armor - [Diablo Wiki](https://diablo.fandom.com/wiki/List_of_Unique_Body_Armor_(Diablo_I))\n* Diablo Normal Armor - [Diablo Archive](https://diablo-archive.fandom.com/wiki/Normal_Armor_(Diablo_I))\n* Diablo and Hellfire Unique Rings - [Diablo Wiki](https://diablo.fandom.com/wiki/List_of_Unique_Rings_(Diablo_I))\n* Diablo and Hellfire Unique Amulets - [Diablo Wiki](https://diablo.fandom.com/wiki/List_of_Unique_Amulets_(Diablo_I))\n* Affixes - [diablowiki.net](https://diablo2.diablowiki.net/D1_Modifiers)\n"
  },
  {
    "path": "Translations/hr.po",
    "content": "# Translation of DevilutionX to Croatian\n# gogo <trebelnik2@gmail.com>, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: 2025-10-02 15:20+0200\\n\"\n\"Last-Translator: gogo <trebelnik2@gmail.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: hr\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && \"\n\"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Dizajn igre\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Stariji dizajneri\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Dodatni dizajn\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Vodeći programer\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Senior programeri\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programiranje\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Posebni gostujući programeri\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net programiranje\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Programiranje serijske komunikacije\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Programiranje instalacijskog programa\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Grafički redatelji\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Grafika\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Tehnička grafika\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Filmski redatelji\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D filmski redatelji\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Filmska tehnička grafika\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Izvršni producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Pomoćni producent\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo udarni tim\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Glazba\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Dizajn zvuka\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Filmska glazba i zvuk\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Produkcija glasova, režija i raspoređivanje uloga\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Scenarij i priča\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Montaža glasova\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Glasove dali\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Inženjer snimanja\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Dizajn priručnika i omota\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Grafika priručnika\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Privremeni upravitelj kvalitete (Vodeći testiratelj)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Ispitivanje kvalitete - napadački tim (Testiratelji)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"\"\n\"Ispitivanje kvalitete - tim za posebne operacije (Testiratelji \"\n\"kompatibilnosti)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Ispitivanje kvalitete - podrška artiljerije (Dodatni testiratelji) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Ispitivanje kvalitete - kontraobavještajna služba\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Naručivanje mrežnih informacijskih usluga\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Korisnička podrška\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Prodaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Prateći vokali gospodina Dabiria\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Odnosi s javnošću\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Međunarodna prodaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"SAD prodaja\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Proizvodnja\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Pravne i poslovne djelatnosti\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Posebne zahvale\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Zahvale\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"U sjećanje na\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Veoma posebna zahvala\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Generalni voditelj\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Softverski inžinjeri\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Umjetnički redatelji\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Umjetnici\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Dizajn\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Dizajn zvuka, SFX i inžinjering zvuka\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Voditelj osiguranja kvalitete\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testiratelji\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Priručnik\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tDodatni rad\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Pisanje teksta zadataka\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Zahvale\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tPosebna zahvala Blizzard Entertainmentu\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Voditelj osiguranja kvalitete\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Voditelj testiranja osiguranja kvalitete\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Glavni testiratelji\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Dodatni testiratelji\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Voditelj marketinga proizvoda\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Glasnogovornik\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Suradnik voditelja proizvoda\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Prsten od jedne tisuće\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tTijekom izrade ove igre nije bilo prodanih duša.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"U redu\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Odabir klase\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Odustani\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Novi heroj među više igrača\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Novi heroj jednog igrača\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Spremljena igra postoji\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Učitaj igru\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Nova igra\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Lik jednog igrača\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Čarobnjak i Lutalica samo su dostupni u cjelovitom maloprodajnom izdanju \"\n\"Diabla. Posjetite https://www.gog.com/game/diablo kako bi ga kupili.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Upiši ime\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Neispravno ime. Ime ne može sadržavati razmake, rezervirane znakove ili \"\n\"rezervirane riječi.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Nemoguće stvaranje lika.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Razina:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Snaga:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magija:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Vještina:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalnost:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Broj igre:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Odabir heroja\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Novi heroj\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Obriši\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Lik među više igrača\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Obriši heroja s više igrača\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Obriši heroja jednog igrača\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Sigurno želite obrisati \\\"{:s}\\\" lik?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Jedan igrač\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Više igrača\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Postavke\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Podrška\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Zasluge\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Zatvori Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Zatvori Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Klijent-Poslužitelj (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"Izvanmrežno\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Igra za više igrača\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Zahtjevi:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"pristupnik ne treba\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Odabir povezivanja\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Promijeni pristupnika\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Sva računala moraju biti povezana u TCP kompatibilnu mrežu.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Sva računala moraju biti povezana s internetom.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Igrajte sami sa sobom bez pristupa mreži.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Podržano igrača: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Na poslužitelju je pokrenuta drugačija igra nego kod vas.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Na poslužitelju je pokrenuta drugačija igra ({:s}) nego kod vas.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Vaša inačica {:s} ne podudara se s poslužiteljevom {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Opis:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Odabir radnje\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Stvori igru\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Stvori javnu igru\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Pridruži se igri\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Javna igra\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Učitavanje...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Nepoznato\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"Odustani\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Stvorite novu igru s težinom po vašem izboru.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Stvorite novu javnu igru kojoj se bilo tko može pridružiti s težinom po \"\n\"vašem izboru.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Upišite ID igre kako bi se pridružili već pokrenutoj igri.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Upišite IP adresu ili naziv poslužitelja kako bi se pridružili već \"\n\"pokrenutoj igri.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Pridružite se javnoj igri koja je već pokrenuta.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normalna\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Noćna mora\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Pakao\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Težina: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Brzina: Normalna\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Brzina: Brza\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Brzina: Brža\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Brzina: Najbrža\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Igrači: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Odabir težine\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Pridruži se {:s} igrama\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Upis ID igre\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Upis adrese\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normalna težina\\n\"\n\"Ovdje bi novi lik trebao započeti potragu za porazom Diabla.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Težina noćne more\\n\"\n\"Stanovnici Labirinta su ojačali i pokazat će se kao veći izazov. Ovo je \"\n\"preporučljivo samo za iskusne likove.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Paklena težina\\n\"\n\"Najmoćnija bića iz podzemlja vrebaju na ulazu u Pakao. U ovo bi carstvo \"\n\"trebali ući samo najiskusniji likovi.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Vaš lik mora prije dostići razinu 20 kako bi mogao ući u igru s više igrača \"\n\"ili u težinu noćne more.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Vaš lik mora prije dostići razinu 30 kako bi mogao ući u igru s više igrača \"\n\"ili u paklenu težinu.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Odabir brzine igre\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Brza\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Brža\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Najbrža\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normalna brzina\\n\"\n\"Ovdje bi novi lik trebao započeti potragu za porazom Diabla.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Brza brzina\\n\"\n\"Stanovnici Labirinta su ubrzani i pokazat će se kao veći izazov. Ovo je \"\n\"preporučljivo samo za iskusne likove.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Brža brzina\\n\"\n\"Većina čudovišta u tamnici će vas tražiti bržije nego ikad prije. Samo \"\n\"iskusni šampioni bi trebali iskusiti sreću na ovoj brzini.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Najbrža brzina\\n\"\n\"Sluge podzemlja napast će vas bez oklijevanja. Samo istinski demon bi trebao \"\n\"ući u ovaj tempo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Upis lozinke\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Pokreni Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Prebaci na Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Da\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Ne\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\n#, fuzzy\n#| msgid \"Press any key to change.\"\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Pritisni bilo koju tipku za promjenu.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Tipka prečaca:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Pritisni bilo koju tipku za promjenu.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Ukloni tipku prečaca\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Prijašnji izbornik\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Mi održavamo poslužitelj razgovora na Discord.gg/devilutionx Slijedite \"\n\"poveznice kako bi se pridružili našoj zajednici gdje raspravljamo o stvarima \"\n\"povezanima s Diablom i Hellfire proširenjem.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX je održavan od strane Diasurgical, problemi i greške se mogu \"\n\"prijaviti na adresi: https://github.com/diasurgical/devilutionX Kako bi nam \"\n\"bolje pomogli, uključite broj inačice, operativni sustav i prirodu problema.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Odricanje od odgovornosti:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX nije podržan ili održavan od strane Blizzard Entertainmenta \"\n\"ili GOG.com. Niti Blizzard Entertainment ili GOG.com nisu testirali ili \"\n\"certificirali DevilutionX kvalitetu ili kompatibilnost. Svi upiti u povezani \"\n\"s DevilutionX trebaju biti usmjereni na Diasurgical, a ne na Blizzard \"\n\"Entertainment ili GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tOvaj port koristi Charis SIL, New Athena Unicode, Unifont i Noto koji su \"\n\"licencirani pod SIL Licencom Otvorenog Fonta, kao i Twitmoji koji je \"\n\"licenciran pod CC-BY 4.0. Port još koristi SDL koji je licenciran pod zlib-\"\n\"licencom. Pogledjte ReadMe za više pojedinosti.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Autorsko pravo © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Greška\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Greška se dogodila na: {:s} redak {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Greška datoteke podataka\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Nemoguće je otvoriti glavnu podatkovnu arhivu ({:s}).\\n\"\n\"\\n\"\n\"Provjerite nalazi li se u mapi igre.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Greška, direktorij ima samo dozvolu čitanja\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Nemoguće zapisivanje lokacije:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Igra: \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"Izvanmrežno\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Lozinka: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Javna igra\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Razina: Skrovište {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Razina: Kripta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Grad\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Razina: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Informacije lika\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Popis zadataka\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Automatska mapa\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Glavni izbornik\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventar\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Knjiga čarolija\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Pošalji poruku\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\n#, fuzzy\n#| msgid \"Description:\"\nmsgid \"Description: \"\nmsgstr \"Opis:\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\n#, fuzzy\n#| msgid \"Players: \"\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"Igrači: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to buy this item?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Sigurno želite kupiti ovaj predmet?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\n#, fuzzy\n#| msgid \"Amber\"\nmsgid \"<number>\"\nmsgstr \"Jantarni\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\n#| msgid \"Multi Player Game\"\nmsgid \"<player name>\"\nmsgstr \"Igra za više igrača\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Prijateljski igrač\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Napadač\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Prečac: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Odaberi trenutnu tipku čarolije\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Prečac: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} vještina\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} čarolija\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Razina čarolije 0 - Neupotrebljivo\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Razina čarolije {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Svitak {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} svitak\"\nmsgstr[1] \"{:d} svitka\"\nmsgstr[2] \"{:d} svitaka\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Štap {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} napunjen\"\nmsgstr[1] \"{:d} napunjena\"\nmsgstr[2] \"{:d} napunjeno\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} zlatnik\"\nmsgstr[1] \"{:s} zlatnika\"\nmsgstr[2] \"{:s} zlatnika\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Zahtjevi nisu ispunjeni\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Razina: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Pogoci {:d} od {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Desno klikni za korištenje\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Povećaj razinu\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Imate {:s} zlatnik. Koliko ih želite izdvojiti?\"\nmsgstr[1] \"Imate {:s} zlatnika. Koliko ih želite izdvojiti?\"\nmsgstr[2] \"Imate {:s} zlatnika. Koliko ih želite izdvojiti?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Gradski portal\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"od {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal u\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Neposvećen oltar\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"razina 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Nemoguće učitavanje lika\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Prikaži ovu pomoć i izađi\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Prikaži inačicu i izađi\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Navedite mapu za diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Navedite mapu za spremanje datoteka\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Navedite lokaciju za diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Preskoči uvodni video\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Prikaži sličice u sekundi\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Omogući opširnije zapisivanje\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Snimi demo datoteku\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Reproduciraj demo datoteku\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Onemogući sva ograničenja sličica tijekom demo reprodukcije\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Odabir igre:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Prisli Shareware izdanje\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Prisili Diablo izdanje\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Prisili Hellfire izdanje\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Hellfire mogućnosti:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Prijavite greške na https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Neuspjelo učitavanje resursa korisničkog sučelja.\\n\"\n\"\\n\"\n\"Pobrinite se da je devilutionx.mpq u mapi igre i da je najnovije inačice.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Mrežno čekanje --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Čekanje igrača --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Pomoć nije dostupna\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"u trgovini\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Predmet pojasa {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Korištenje predmeta pojasa.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Brza magija {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Prečac za vještinu ili magiju.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Prijašnji izbornik\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Brza magija {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Brza knjiga\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Otvara brzu knjigu.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Brzo spremanje\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Sprema igru.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Brzo učitavanje\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Učitava igru.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Zatvori Diablo\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Zatvara igru.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Zaustavi heroja\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Zaustavi hodanje i prekini radnje na čekanju.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Isticanje predmeta\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Prikaži/Sakrij predmete na zemlji.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Uklj/Isklj isticanje predmeta\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Trajno prikaži/sakrij predmete na zemlji.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Uklj/Isklj automatsku kartu\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Uklj/Isklj prikaz karte.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Otvori inventar.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Lik\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Otvori informacije lika.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Popis zadataka\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Otvori popis zadataka.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Knjiga magije\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Otvori knjigu magije.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Brza poruka {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Koristi brzu poruku u razgovoru.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Sakrij prozore informacija\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Sakrij sve prozore informacija.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Uvećaj/Smanji\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Uvećava/Smanjuje zaslon igre.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Pauziraj igru\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Pauzira igru.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pauziraj igru\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Povećava svjetlinu zaslona.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Smanjuje svjetlinu zaslona.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Povećava svjetlinu zaslona.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Povećava svjetlinu zaslona.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Pomoć\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Otvori pomoć.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Uslikaj igru\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Uslikaj igru.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Informacije igre\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Prikazuje informacije igre.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Zapis razgovora\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Prikazuje zapis razgovora.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Inventar\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"Odabir radnje\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"Odabir radnje\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"Odustani\"\n\n#: Source/diablo.cpp:2175\n#, fuzzy\n#| msgid \"Closes the game.\"\nmsgid \"Close menus.\"\nmsgstr \"Zatvara igru.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"Lik među više igrača\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"Lik među više igrača\"\n\n#: Source/diablo.cpp:2212\n#, fuzzy\n#| msgid \"$Movement:\"\nmsgid \"Move left\"\nmsgstr \"$Kretnja:\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"Lik među više igrača\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"Lik među više igrača\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Automatska mapa\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\n#, fuzzy\n#| msgid \"The game ended\"\nmsgid \"Toggle game menu\"\nmsgstr \"Igra je završila\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Saves the game.\"\nmsgid \"Opens the game menu.\"\nmsgstr \"Sprema igru.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgid \"Game Mode\"\nmsgid \"Game saved\"\nmsgstr \"Izdanje igre\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Igranje više igrača nije dostupno u demo inačici\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Stvaranje izravnog zvuka neuspjelo\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Nije dostupno u sharware inačici\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Nedovoljno prostora za spremanje\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Nema pauze u gradu\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Kopiranje na čvrsti disk je preporučeno\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Problem usklađivanja više igrača\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Nema pauze u igri više igrača\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Spremanje...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Tajanstvena moć donosi uništenje\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Grimizno i Azurno postaju kao sunce\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Gdje god kreneš, tamo stigneš\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Znanje je moć.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Najbolje je kod kuće.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedrala\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Katakombe\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Spilje\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Skrovište\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Kripta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Razina {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} težina\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"U izbornik\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"izvanmrežno\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Nemoguće povezivanje\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"greška: očitano 0 bajta sa poslužitelja\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq ili spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Određeni Hellfire MPQ-ovi nedostaju\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Nisu svi Hellfire MPQ-ovi pronađeni.\\n\"\n\"Kopirajte sve hf*.mpq datoteke.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Razlučivost\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Trčanje u gradu\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Potraga za Theom\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Potraga za kravom\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Automatsko uzimanje zlata\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Automatsko uzimanje eliksira\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\n#| msgid \"Auto Gold Pickup\"\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Automatsko uzimanje zlata\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Automatsko uzimanje u gradu\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria puni manu\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Automatsko opremanje oružjem\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Automatsko opremanje oklopom\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Automatsko opremanje šljemom\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Automatsko opremanje štitom\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Automatsko opremanje nakitom\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Naizmjenični odabir zadataka\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Prikaži nazive stvari\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Automatski popuni pojas\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Onemogući svetišta sakaćenja\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Uzimanje napitka zdravlja\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Uzimanje napitka potpunog zdravlja\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Uzimanje napitka mane\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Uzimanje napitka potpune mane\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Uzimanje napitka oporavka\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Uzimanje napitka potpunog oporavka\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Mogućnosti\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Spremi igru\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Glavni izbornik\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Zatvori Diablo\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gama\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Brzina\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Glazba isključena\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Zvuk\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Zvuk isključen\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pauza\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Prečaci tipkovnice:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Otvori pomoć\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Prikaži glavni izbornik\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Prikaži automatsku mapu\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Sakrij sve prozore informacija\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Otvara brzu knjigu\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Otvori knjigu magije\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Otvori inventar\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Otvori informacije lika\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Otvori popis zadataka\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Smanji svjetlinu zaslona\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Povećaj svjetlinu zaslona\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Uvećaj/Smanji zaslon igre\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Uvećaj/Smanji kartu\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Korištenje predmeta pojasa\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Postavi prečace za vještinu ili magiju\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Lijeva tipka miša: Napad bez kretanja\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Lijeva tipka miša: (na zaslon lika): Rasporedi sve bodove automatski\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Lijeva tipka miša (na inventar): Premješta predmete u pojas ili \"\n\"uzima/odbacuje predmet\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Lijeva tipka miša (na pojas): Premješta predmet u inventar\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Kretnja:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Ako držite pritisnutu tipku miša pri kretanju, lik će se nastaviti kretati u \"\n\"zadanome smjeru.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Borba:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Držanje pritisnute Shift tipke i zatim lijevo klikanje omogućuje liku napad \"\n\"bez kretanja.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Automatska karta:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Za pristup automatskoj karti, kliknite na 'KARTA' tipku u traci informacija \"\n\"ili pritisnite 'TAB' na tipkovnici. Uvećanje i smanjenje se obavlja pomoću + \"\n\"i - tipka. Pomicanje karte se obavlja pomoću tipki strelica.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Uzimanje objekta:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Upotrebljivi predmeti male veličine, poput napitaka i svitaka se automatski \"\n\"smještaju u vaš 'pojas' koji se nalazi na vrhu trake sučelja. Kada se \"\n\"predmet smjesti u pojas, pojavi se mali broj u tome okviru. Predmeti se mogu \"\n\"koristiti ili pritiskom na odgovarajući broj ili desnim klikom na njega.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Zlato:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Možete odabrati određenu količinu zlata za preraspodjelu desnim klikom na \"\n\"gomilu zlata u vašem inventaru.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Vještine i magija:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Možete pristupiti vašem popisu vještina i magija lijevim klikom na 'MAGIJA' \"\n\"tipku u vašoj traci sučelja. Trajna magija i ona dostupna putem štapova je \"\n\"prikazana ovdje. Lijevi klik na magiju koju želite koristiti učinit će ju \"\n\"spremnom za bacanje. Spremna magija može se baciti jednostavno desnim klikom \"\n\"na odabrano područje.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Korištenje brze knjige za magiju:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Lijevi klik na tipku 'spremne magije' će otvoriti 'Brzu knjigu' koja vam \"\n\"omogućuje odabir vještine ili magije za trenutno korištenje. Za korištenje \"\n\"spremne vještine ili magije, jednostavno kliknite na glavno područje igranja.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + Lijevi klik na tipku 'odaberi trenutnu magiju' će ukloniti spremnu \"\n\"magiju.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Postavljanje prečaca magije:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Možete dodijeliti do četiri prečaca za vještine, magiju ili svitke. \"\n\"Započinjete otvaranjem 'brze knjige' kao što je opisano u odjeljku iznad. \"\n\"Pritisnite F5, F6, F7 ili F8 tipke nakon naglašavanja magije koju želite \"\n\"dodijeliti.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Knjige magije:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Čitanje više knjiga proširuje vaše znanje odabrane magije, što omogućuje \"\n\"učinkovitije bacanje magije.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Shareware Hellfire pomoć\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Hellfire pomoć\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Shareware Diablo pomoć\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Diablo pomoć\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Pritisnite ESC za završetak ili tipku strelice za pomicanje.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Nemoguće stvaranje glavnog prozora\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Ulje preciznosti\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Ulje majstorstva\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Ulje oštroumnosti\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Ulje smrti\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Ulje vještine\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Kovačko ulje\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Ulje hrabrosti\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Ulje postojanosti\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Ulje stvrdnjavanja\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Ulje nepropusnosti\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} od {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} od {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} od {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} od {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"smanjuje potrebna svojstva\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"djelomično obnavlja život\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"djelomično obnavlja manu\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"potpuno obnavlja manu\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"povećava snagu\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"povećava magiju\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"povećava vještinu\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"povećava vitalnost\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"djelomično obnavlja život i manu\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"potpuno obnavlja život i manu\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Desno klikni za pogledati\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Desno klikni za korištenje\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Desno klikni za čitanje, zatim\\n\"\n\"lijevo klikni na metu\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Desno klikni za čitanje\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Aktiviraj za prikaz\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Otvori inventar za korištenje\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Aktiviraj za korištenje\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Odaberi iz knjige čarolije, zatim\\n\"\n\"bacite čaroliju za čitanje\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Aktiviraj za čitanje\"\n\n#: Source/items.cpp:1800\n#, fuzzy, c++-format\n#| msgid \"Activate to view\"\nmsgid \"{} to view\"\nmsgstr \"Aktiviraj za prikaz\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\n#| msgid \"{:+d} to strength\"\nmsgid \"{} to use\"\nmsgstr \"{:+d} na snagu\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Odaberi iz knjige čarolije, zatim\\n\"\n\"bacite čaroliju za čitanje\"\n\n#: Source/items.cpp:1811\n#, fuzzy, c++-format\n#| msgid \"Activate to read\"\nmsgid \"{} to read\"\nmsgstr \"Aktiviraj za čitanje\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Razina: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Udvostručuje kapacitet zlata\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Potrebno:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Snage\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Magije\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Vještine\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Knjiga: {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Uho od {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"šanse za pogodak: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% oštećenje\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"pogodak: {:+d}%, {:+d}% oštećenje\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% oklop\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"klasa oklopa: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Otpor na vatru: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Otpor na vatru: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Otpor na svjetlost: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Otpor na svjetlost: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Otpor na magiju: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Otpor na magiju: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Otpor na sve: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Otpor na sve: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"magija je povećana za {:d} razinu\"\nmsgstr[1] \"magija je povećana za {:d} razine\"\nmsgstr[2] \"magija je povećana za {:d} razina\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"magija je smanjena za {:d} razinu\"\nmsgstr[1] \"magija je smanjena za {:d} razine\"\nmsgstr[2] \"magija je smanjena za {:d} razina\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"razina magije nepromijenjena (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Dodatna punjenja\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} punjenje\"\nmsgstr[1] \"{:d} {:s} punjenja\"\nmsgstr[2] \"{:d} {:s} punjenja\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Oštećenje na pogodak vatre: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Oštećenje na pogodak vatre: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Oštećenje na pogodak svjetlosti: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Oštećenje na pogodak svjetlosti: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} na snagu\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} na magiju\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} na vještinu\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} na vitalnost\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} na sve vještine\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} na štetu od neprijatelja\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Pogodci: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"visoka izdržljivost\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"smanjena izdržljivost\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"neuništivo\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% radijus svjetlosti\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% radijus svjetlosti\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"više strijela pri pogodku\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"oštećenje od strijele: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"oštećenje od strijele: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"oštećenje od strijele svjetlosti: {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"oštećenje od strijele svjetlosti: {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"dodaje {:d} bod na oštećenje\"\nmsgstr[1] \"dodaje {:d} boda na oštećenje\"\nmsgstr[2] \"dodaje {:d} boda na oštećenje\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"neobično oštećenje predmeta\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"promijenjena izdržljivost\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"jednoruki mač\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"oštećenje od svjetlosti: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"oštećenje od svjetlosti: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"pražnjenja naboja pri pogodku\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"povremeno trostruko oštećenje\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"raspadanje {:+d}% oštećenje\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x ošteć. na čudovište, 1x na vas\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Naizmjenično 0 - 600% oštećenje\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"niska izdrž, {:+d}% oštećenje\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"dodatna AC protiv demona\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"dodatna AC protiv nemrtvih\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Mane premješteno u Zdravlje\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Zdravlja premješteno u Manu\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"oštećenje: {:d}  neuništivo\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"oštećenje: {:d}  Izdrž: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"oštećenje: {:d}-{:d}  neuništivo\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"oštećenje: {:d}-{:d}  Izdrž: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"oklop: {:d}  neuništivo\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"oklop: {:d}  Izdrž: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Punjenje: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"unikat\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Nije identificirano\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Brlog kralja kostura\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labirint\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Zatrovane zalihe vode\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Brlog nadbiskupa Lazara\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\n#| msgid \"Hellfire\"\nmsgid \"Hell Arena\"\nmsgstr \"Hellfire\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Dolje u spilju\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Dolje u katakombe\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Dolje u spilje\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Dolje u pakao\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Dolje u košnicu\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Dolje u kriptu\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Gore na razinu {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Gore u grad\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Dolje na razinu {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Dolje u Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Dolje na razinu skrovišta {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Gore na razinu kripte {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Dolje na razinu kripte {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Natrag na razinu {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Nemoguće otvaranje arhive datoteke spremanja\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Nevaljana datoteka spremanja\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Igrač je na Hellfire razini\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Nevaljano stanje igre\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Nemoguć prikaz glavnog izbornika\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Životinja\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demon\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Živi mrtvac\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Vrsta: {:s}  Ubijeno: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Ukupno ubijeno: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Pogodci: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Nema otpora na magiju\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Otpor:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magija\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Vatra\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Svjetlost\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Imunost:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Vrsta: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Bez otpora\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Bez imunosti\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Nešto otpora na magiju\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Nešto imunosti na magiju\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Neuspjelo otvaranje arhive za zapisivanje.\"\n\n#: Source/msg.cpp:1701\n#, fuzzy, c++-format\n#| msgid \"{:s} has cast an illegal spell.\"\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} je bacio neučinkovitu čaroliju.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} je bacio neučinkovitu čaroliju.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Igrač '{:s}' (razina {:d}) se upravo pridruži igri\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Igra je završila\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Nemoguće dobivanje podataka razine\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Igrač '{:s}' je upravo napustio igru\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Igrač '{:s}' je ubio Diabla i napustio igru!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Igrač '{:s}' je odustao zbog isteka vremena\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Igrač '{:s}' (razina {:d}) je već u igri\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Mistično\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Skriveno\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Turobno\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Čudno\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Magično\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Kriptično\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Sveto\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\n#, fuzzy\n#| msgid \"The Ring of One Thousand\"\nmsgid \"The Binding of the Three\"\nmsgstr \"Prsten od tisuće\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Knjiga magije\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4799\n#, fuzzy\n#| msgid \"Level:\"\nmsgid \"Lever\"\nmsgstr \"Razina:\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Otvorena vrata\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Zatvorena vrata\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Blokirana vrata\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Mala škrinja\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Škrinja\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Velika škrinja\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarkofag\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Ormarić za knjige\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Polica za knjige\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Bačva\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} svetište\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Oklop\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4899\n#, fuzzy\n#| msgid \"Select Hero\"\nmsgid \"Slain Hero\"\nmsgstr \"Odaberi heroja\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"U zamci {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (onemogućeno)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"UKLJ\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"ISKLJ\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Izdanje igre\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Postavke igre\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Igrajte Diablo ili Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Ograniči na Shareware\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Čini igru kompatibilnu s demo izdanjem. Omogućuje igranje više igrača s \"\n\"prijateljima koji ne posjeduju punu kopiju Diabla.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Pokretanje\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Postavke pokretanja\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Uvod\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Prikazan uvodni film.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Uvodni zaslon\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Prikaži uvodni zaslon.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logotip i naslovni zaslon\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Naslovni zaslon\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Diablo specifične postavke\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Hellfire specifične postavke\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Zvuk\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Postavke zvuka\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Zvuk hodanja\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Lik emitira zvuk pri hodanju.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Zvuk automatskog opremanja\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Automatsko opremanje predmetima pri uzimanju emitira zvuk opremanja.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Zvuk uzimanja predmeta\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Uzimanje predmeta emitira zvuk uzimanja.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Frekvencija\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Izlazna frekvencija (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanali\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Broj izlaznih kanala.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Veličina međuspremnika\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Veličina međuspremnika (broj sličica po kanalu)\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Normalzacija zvuka\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Kvaliteta normalizacije zvuka, od 0 (najmanja) do 10 (najveća).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Utječe na unutrašnju razlučivost igre i određuje vaše područje prikaza. \"\n\"Napomena: To se može razlikovati od razlučivosti zaslona, kada se koristi \"\n\"Uvećanje, Cjelobrojno uvećanje ili Prilagodba po zaslonu.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Normalizacija\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Normalizacija zvuka\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Uređaj\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Zvučni uređaj\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafika\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Postavke grafike\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Cjelozaslonski prikaz\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Prikaži igru u prozoru ili preko cijelog zaslona.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Prilagodi po zaslonu\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Automatski prilagođuje prozor igre prema omjeru slike i razlučivosti vašeg \"\n\"trenutnog zaslona računala.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Uvećanje\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Omogućuje uvećanje slike iz razlučivosti igre na razlučivost vašeg monitora. \"\n\"Sprječava promjenu razlučivosti monitora i dopušta promjenu veličine prozora.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Kvaliteta uvećanja\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"Omogućuje dodatne filtre za izlaznu sliku pri uvećanju.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Najbliži piksel\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilinearno\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anizotropno\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Cjelobrojno uvećanje\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Uvećava sliku koristeći cijeli broj omjera piksela.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Okomito usklađivanje\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Svjetlost\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Kruženje boja\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Efekt kruženja boja korišten za vodu, lavu i animacije kiseline.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Zamjenska nest paleta\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"Igra će koristiti zamjensku nest paletu za Hellfire nest skup pločica.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Hardverski pokazivač\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Koristi hardverski pokazivač\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Hardverski pokazivač za predmete\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Koristi hardverski pokazivač za predmete.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Najveća veličina hardverskog pokazivača\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Najveća širina / visina hardverskog pokazivača. Veći pokazivač koristi \"\n\"softverski prikaz.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Prikaži broj sl/s\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Prikazuje broj sličica (FPS) u sekundi u gornjem lijevom kutu zaslona.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Igra\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Postavke igre\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Omogućuje đogiranje/brzo trčanje u gradu za Diablo i Hellfire. Ova mogućnost \"\n\"je predstavljena u Hellfire izdanju.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Obuhvati pokazivač\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Kada je omogućeno miš je zaključan u prozoru igre.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Omogući potragu za malom djevojčicom.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Omogući Jerseyjevu potragu. Farmer Lester je zemijenjen potpunim idiotom.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Prijateljska vatra\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Dopusti strijeli/čaroliji oštećenje između igrača u igri više igrača čak i \"\n\"kada je prijateljski način igranja uključen.\"\n\n#: Source/options.cpp:790\n#, fuzzy\n#| msgid \"No pause in multiplayer\"\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Nema pauze u igri više igrača\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Testiraj Barda\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Prisili pojavljivanje lika Barda u izborniku odabira heroja.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Testiraj Barbarina\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Prisili pojavljivanje lika Barbarina u izborniku odabira heroja.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Traka iskustva\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Traka iskustva je dodana u grafičko sučelje na dnu zaslona.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Prikaži vrijednosti zdravlja\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Prikazuje trenutnu / najveću vrijednost zdravlja na kugli zdravlja.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Prikaži vrijednosti mane\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Prikazuje trenutnu / najveću vrijednost mane na kugli mane.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Informacije lika\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Traka zdravlja neprijatelja\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Traka zdravlja neprijatelja je prikazana na vrhu zaslona.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Zlato se automatski prikuplja kada je u blizini lika.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Eliksir se automatski prikuplja kada je u blizini lika.\"\n\n#: Source/options.cpp:802\n#, fuzzy\n#| msgid \"\"\n#| \"Elixirs are automatically collected when in close proximity to the player.\"\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Eliksir se automatski prikuplja kada je u blizini lika.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Automatsko uzimanje predmeta u gradu.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria će napuniti vašu manu kada posjetite njenu trgovinu.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Automatsko opremanje oružjem pri uzimanju ili kupovini.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Automatsko opremanje oklopom pri uzimanju ili kupovini.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Automatsko opremanje šljemom pri uzimanju ili kupovini.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Automatsko opremanje štitom pri uzimanju ili kupovini.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Automatsko opremanje nakitom pri uzimanju ili kupovini.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Naizmjenično odaberi dostupne zadatke za nove igre.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Prikaži vrstu čudovišta\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Lebdenjem pokazivačem preko čudovišta će prikazati vrstu čudovišta u okviru \"\n\"opisa u grafičkom sučelju.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Prikazuje nazive stvari na zemlji kada je omogućeno.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Popuni pojas iz inventara kada se predmet iz pojasa potroši.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Kada su omogućeni kotlovi, fascinantna svetišta, svetišta koza, okićena \"\n\"svetišta i sveta svetišta ne može se kliknuti na njih i označiti ih kao \"\n\"onemogućenima.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Bacanje čarolije\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Prečaci za čarolije odmah bacaju čaroliju, umjesto da prebacivaju spremnu \"\n\"čaroliju.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Automatsko uzimanje napitaka zdravlja.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Automatsko uzimanje napitaka potpunog zdravlja.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Automatsko uzimanje napitaka mane.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Automatsko uzimanje napitaka potpune mane.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Automatsko uzimanje napitaka oporavka.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Automatsko uzimanje napitaka potpunog oporavka.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\nmsgid \"Off\"\nmsgstr \"Izvanmrežno\"\n\n#: Source/options.cpp:825\n#, fuzzy\n#| msgid \"Randomize Quests\"\nmsgid \"Random Angles\"\nmsgstr \"Naizmjenični odabir zadataka\"\n\n#: Source/options.cpp:826\n#, fuzzy\n#| msgid \"Vertical Sync\"\nmsgid \"Vertical Only\"\nmsgstr \"Okomito usklađivanje\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Upravljači\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Postavke upravljača\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Mreža\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Mrežne postavke\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Razgovor\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Postavke razgovora\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Jezik\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Odaberite jezik koji će se koristiti u igri.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Postavke jezika\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Tipke prečaca\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Postavke tipka prečaca\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping\"\nmsgid \"Padmapping\"\nmsgstr \"Tipke prečaca\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping Settings\"\nmsgid \"Padmapping Settings\"\nmsgstr \"Postavke tipka prečaca\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Postavke\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Razina\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Iskustvo\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Sljedeća razina\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Bod.\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Ras.\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Snaga\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magija\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Vještina\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalnost\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Bodovi za raspodjelu\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Zlato\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Klasa oklopa\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Oštećenje\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Život\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Otpor na magiju\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Otpor na vatru\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Otpor na svjetlost\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"lik\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"zadaci\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"karta\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"izbornik\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"inventar\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"magija\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"glas\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"utišaj\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Neupotrebljivo\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Ošt: 1/3 pog. mete\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Izlječenje: {:d}-{:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Oštećenje: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Vještina\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Štap ({:d} napunjen)\"\nmsgstr[1] \"Štap ({:d} napunjena)\"\nmsgstr[2] \"Štap ({:d} napunjeno)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Razina {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Čarolija\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Oštećuje samo mrtve\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Svitak\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Štap\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Prečac čarolije {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Nemoguće otvaranje arhive\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Nemoguće učitavanje lika\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (razina {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Povijest razgovora (Poruka: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} zlato\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Koliko zlatnika želite izdvojiti?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Razina {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Iskustvo: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Najveća razina\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Sljedeća razina: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} do razine {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Grobnica kralja Leorika\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Mračni prolaz\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"U {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Trebam pomoć! Dođi ovdje!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Slijedi me.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Imam nešto za tebe.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Sada UMRI!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Zahvale\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Natrag\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Oštećenje: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Oklop: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Izdržljivost: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"neuništivo\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Dobrodošli\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Kovačnica\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Želite li:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Razgovarati s Griswoldom\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Kupovati osnovne predmete\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Kupovati napredne predmete\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Prodavati predmete\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Popravljati predmete\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Napustiti kovačnicu\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Imam ove predmete za prodaju:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Imam ove napredne predmete za prodaju:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Nemaš ništa što mi je potrebno.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Koji predmet je za prodaju?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Nemaš ništa za popraviti.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Koji predmet je potrebno popraviti?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Vještičina koliba\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Razgovarati s Adriom\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Kupovati predmete\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Napuniti predmete\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Napustiti kolibu\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Nemaš ništa za napuniti.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Koji predmet treba napuniti?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Nemate dovoljno zlata\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Nemate dovoljno mjesta u inventaru\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Jesmo li se dogovorili?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Sigurno želite identificirati ovaj predmet?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Sigurno želite kupiti ovaj predmet?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Sigurno želite ponovno napuniti ovaj predmet?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Sigurno želite prodati ovaj predmet?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Sigurno želite popraviti ovaj predmet?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt dječak s drvenom nogom\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Razgovaraj s Wirtom\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Imam nešto za prodaju,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"ali koštat će te 50 zlata\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"samo da pogledaš. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Što to imaš?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Pozdravi se\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Imam ove predmete za prodaju:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Napusti\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Iscjelitelj\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Razgovarati s Pepinom\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Napustiti iscjelitelja\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Gradski starješina\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Razgovarati s Cainom\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identificirati predmet\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Nemaš ništa za identifikaciju.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Koji predmet je za identifikaciju?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Taj predmet je:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Završi\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Razgovarj s {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Razgovaraš s {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"nije dostupno\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"u shareware\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"izdanju\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Glasine\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Gostionica izlazećeg sunca\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Razgovarati s Ogdenom\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Napustiti gostionicu\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Razgovarati s Gillian\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnham pijandura\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Razgovarati s Farnhamom\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Pozdravi se\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Vaše zlato: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Ubijeni mještanin\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Griswold kovač\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin iscjelitelj\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Ranjeni mještanin\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden vlasnik gostionice\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Cain gradski starješina\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Adria vještica\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian konobarica\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Krava\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester farmer\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Potpuni idiot\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Ratnik\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Lutalica\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Čarobnjak\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Redovnik\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bard\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbarin\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Pali\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Rezbar\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Đavolji rođak\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Mračni\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Kostur\"\n\n#: Source/translation_dummy.cpp:26\n#, fuzzy\n#| msgid \"Create Game\"\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Stvori igru\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Zapaljivi mrtvac\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Horor\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Strvinar\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Žderač kuge\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Kapetan kostura\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Kapetan mrtvaca\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Kapetan zapaljivih mrtvaca\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Kapetan horora\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Nevidljiv gospodar\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Skriveni\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Klan mesa\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Klan kamena\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Klan vatre\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Klan noći\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Pljuvač otrova\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Mesar\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Demon magme\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Krvavi kamen\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Pakleni kamen\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Gospodar lave\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Rogati demon\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Blatnjavi trkač\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Crvena smrt\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Gospodar plamena\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:81\n#, fuzzy\n#| msgid \"Hell\"\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Pakao\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:91\n#, fuzzy\n#| msgid \"Single Player\"\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Jedan igrač\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:103\n#, fuzzy\n#| msgid \"The Town Elder\"\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Gradski starješina\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:105\n#, fuzzy\n#| msgid \"Faster\"\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Brže\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:109\n#, fuzzy\n#| msgid \"Sell items\"\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Prodavati predmete\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:127\n#, fuzzy\n#| msgid \"The Town Elder\"\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Gradski starješina\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:130\n#, fuzzy\n#| msgid \"Cain the Elder\"\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Cain gradski starješina\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Precizan strijelac\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:163\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Noćna mora\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:174\n#, fuzzy\n#| msgid \"Adria the Witch\"\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Adria vještica\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:183\n#, fuzzy\n#| msgid \"Single Player\"\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Jedan igrač\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:206\n#, fuzzy\n#| msgid \"Adria the Witch\"\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Adria vještica\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:209\n#, fuzzy\n#| msgid \"Single Player\"\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Jedan igrač\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Kratki mač\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Štit\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Palica\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Kratki luk\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Kratak štap čarolije\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Satara\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Kruna mrtvih\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Rajska skupina\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Čaroban kamen\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Optička amajlija\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Prsten istine\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Znak gostionice\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Napitak iscjeljenja\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Napitak mane\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Svitak identifikacije\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Svitak gradskog portala\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Napitak potpunog iscjeljenja\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Napitak potpune mane\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:248\n#, fuzzy\n#| msgid \"Single Player\"\nmsgid \"Bovine Plate\"\nmsgstr \"Jedan igrač\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Štap od Lazara\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Svitak uskrsnuća\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Kratak štap\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Mač\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Bodež\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Kapa\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Kapa od lubanje\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Šljem\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Potpuni šljem\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Kruna\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Veliki šljem\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Plašt\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Dronjak\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Ogrtač\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Mantija\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Prošiveni oklop\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Kožni okop\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Prstenasti oklop\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Oklop\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Lančasti oklop\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Pločasti oklop\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Prsna ploča\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Ploča\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Metalno kožni oklop\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Pleteno pločasti oklop\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Metalni oklop\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gotički oklop\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Potpuni metalni oklop\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Štit\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Mali štit\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Veliki štit\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gotički štit\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Napitak oporavka\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Napitak potpunog oporavka\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Ulje\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Eliksir snage\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Eliksir čarolije\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Eliksir vještine\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Svitak vitalnosti\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Svitak iscjeljenja\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Svitak potrage\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Svitak svjetlosti\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Svitak vatrenog zida\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Svitak pakla\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Svitak bljeska\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Svitak štita mane\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Svitak vatrene kugle\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Svitak kamene kletve\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Svitak teleportiranja\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Svitak apokalipse\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Zakrivljena sablja\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Sječivo\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Sablja\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Dugi mač\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Široki mač\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Dvoruki mač\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Veliki mač\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Mala sjekira\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Sjekira\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Veća sjekira\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Široka sjekira\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Borbena sjekira\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Velika sjekira\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Buzdovan\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Zvjezdoliki buzdovan\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Ratnički čekić\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Čekić\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Luk\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Lovački luk\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Dugi luk\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Kompozitni luk\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Kratki bojni luk\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Dugi bojni luk\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Kratki ratni luk\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Dugi ratni luk\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Dugi štap\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Kompozitni štap\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Četvrtina štapa\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Ratni štap\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Prsten\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amajlija\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Kratki štap pražnjenja naboja\"\n\n#: Source/translation_dummy.cpp:368\n#, fuzzy\n#| msgid \"Mana Potion Pickup\"\nmsgid \"Arena Potion\"\nmsgstr \"Uzimanje napitka mane\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Mesarska satara\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgid \"Lightforge\"\nmsgstr \"Noćna mora\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:382\n#, fuzzy\n#| msgid \"The Town Elder\"\nmsgid \"The Defender\"\nmsgstr \"Gradski starješina\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:391\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgid \"Lightsabre\"\nmsgstr \"Noćna mora\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:397\n#, fuzzy\n#| msgid \"The Town Elder\"\nmsgid \"The Mangler\"\nmsgstr \"Gradski starješina\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Šljem duhova\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Gospodarov šljem\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:437\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgid \"Nightscape\"\nmsgstr \"Noćna mora\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:448\n#, fuzzy\n#| msgid \"The Town Elder\"\nmsgid \"The Bleeder\"\nmsgstr \"Gradski starješina\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Zaručnički prsten\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Kositar\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Mjed\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Brončani\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Željezo\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Čelik\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Srebro\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platina\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mitril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteor\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Neobično\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Beskorisno\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Savijeno\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Slabo\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Nazubljeno\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Smrtonosno\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Teško\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Zlobno\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Brutalno\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Masivno\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Divlje\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Nemilostivo\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Nemilosrdno\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Nespretno\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Tupo\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Oštro\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Precizan\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Ratnički\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Vojnički\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Gospodnji\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Vitezov\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Gospodarov\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Šampionov\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Kraljev\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Slavni\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Blagoslovljena\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Granat\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Plavi\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Kobaltni\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Safirni\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Jantarni\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Hijenski\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Žablji\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Paukov\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Gavranov\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Zmijski\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Zmijina\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Zmajeva\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hidrina\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Anđeoska\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Arhanđelova\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Obilan\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"kvaliteta\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"boli\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"suza\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"zdravlja\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"apsorpcije\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"skretanja\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"osmoze\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"krhkosti\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"slabosti\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"snage\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"paralize\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"vještine\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"vještine\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"točnosti\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"preciznosti\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"perfekcije\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"disleksije\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"magije\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"uma\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"briljantnosti\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"čaranja\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"čarobnjaštva\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"bolesti\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"bolesti\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"vitalnosti\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"života\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"nesreće\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"neba\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"mjeseca\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"zvijezda\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"nebesa\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"zodijaka\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"strvinara\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"šakala\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"lisice\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"jaguara\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"orla\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"vuka\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tigra\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"lava\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mamuta\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"kita\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"oštećenje\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:616\n#, fuzzy\n#| msgid \"Manufacturing\"\nmsgid \"puncturing\"\nmsgstr \"Proizvodnja\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"brzina\"\n\n#: Source/translation_dummy.cpp:621\n#, fuzzy\n#| msgid \"Faster\"\nmsgid \"haste\"\nmsgstr \"Brže\"\n\n#: Source/translation_dummy.cpp:622\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"balance\"\nmsgstr \"Odustani\"\n\n#: Source/translation_dummy.cpp:623\n#, fuzzy\n#| msgid \"Vitality:\"\nmsgid \"stability\"\nmsgstr \"Vitalnost:\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Čaroban kamen\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Mesar\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Prokletstvo kralja Leorika\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Vatreni pojas\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Iscjeljenje\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Munja\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Bljesak\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identifikacija\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Vatreni zid\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Gradski portal\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Kamena kletva\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infravizija\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Štita mane\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Vatrena kugla\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Nevidljivost\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Pakao\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Bijes\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleportiranje\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apokalipsa\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Eteriziranje\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Popravak predmeta\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Punjenje štapa\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Onesposobljavanje zamke\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elementarno\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Pražnjenje naboja\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Sveti pojas\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Uskrsnuće\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekineza\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Izliječi ostale\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Krvava zvijezda\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Koštani duh\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ah, priča o našem Kralju, zar ne? Tragičan pad Leorika bio je težak udarac \"\n\"za ovu zemlju. Narod je uvijek volio kralja, a sada živi u smrtnom strahu od \"\n\"njega. Pitanje koje si stalno postavljam je kako se mogao tako udaljiti od \"\n\"Svjetle strane, jer je Leorik uvijek bio najsvetiji među ljudima. Samo \"\n\"najmračnije sile pakla mogu tako potpuno uništiti čovjeka iznutra...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Selo treba tvoju pomoć, dobri gospodaru! Prije nekoliko mjeseci otet je sin \"\n\"kralja Leorika, princ Albrecht. Razbješnjeli Kralj tražio je po selu svoje \"\n\"nestalo dijete. Svakim proteklim danom, Leorik kao da je klizio sve dublje u \"\n\"ludilo. Okrivio je nedužne mještane za dječakov nestanak i brutalno ih je \"\n\"pogubio. Manje od polovice nas je preživjelo njegovo ludilo...\\n\"\n\" \\n\"\n\"Kraljevi vitezovi i svećenici pokušali su ga umiriti, ali on se okrenuo \"\n\"protiv njih i nažalost, bili su prisiljeni ubiti ga. Zadnjim dahom na samrti \"\n\"kralj je prokleo svoje bivše sljedbenike. Zakleo se da će mu služiti u tami \"\n\"zauvijek...\\n\"\n\" \\n\"\n\"Ovdje stvari dobivaju još mračniji obrat nego što sam mislio! Naš bivši \"\n\"Kralj je ustao iz svog vječnog sna i sada zapovijeda legijom nemrtvih sluga \"\n\"unutar Labirinta. Njegovo tijelo je pokopano u grobnici tri razine ispod \"\n\"katedrale. Molim te, dobri gospodaru, odriješi mu dušu uništenjem njegova \"\n\"sada ukletog oblika...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Kao što sam ti rekao, dobri gospodaru, Kralj je pokopan tri razine ispod. On \"\n\"je tamo dolje, čeka u truloj tami svoju priliku da uništi ovu zemlju...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Gubitak sina bio je prevelik za kralja Leorika. Učinio sam sve što sam mogao \"\n\"da ublažim njegovo ludilo, ali ga je na kraju svladalo. Crno prokletstvo se \"\n\"nadvilo nad ovim kraljevstvom od tog dana, ali možda, ako bi ti oslobodio \"\n\"njegov duh iz ovozemaljskog zatvora, kletva bi bila skinuta...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Ne volim razmišljati o tome kako je Kralj umro. Želim ga pamtiti kao \"\n\"ljubaznog i pravednog vladara kakav je bio. Njegova smrt je tako tužna, čini \"\n\"se nekako pogrešnom.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Napravio sam mnoga oružja i većinu oklopa kojima je kralj Leorik opremio \"\n\"svoje vitezove. Čak sam za njega izradio i golemi dvoručni mač od najfinijeg \"\n\"mitrila, kao i poljsku krunu za njega. Još uvijek ne mogu vjerovati kako je \"\n\"umro, ali sigurno ga je neka zlokobna sila dovela do ludila!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Nije me briga za to. Slušaj, nijedan kostur neće biti MOJ Kralj. Leorik je \"\n\"moj kralj. Kralju, čuješ li me? POZDRAV KRALJU!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Mrtvi koji hodaju među živima slijede prokletog Kralja. On ima moć da \"\n\"prikupi još više ratnika za sve veću vojsku nemrtvih. Ako ne zaustaviš \"\n\"njegovu vladavinu, on će sigurno marširati ovom zemljom i pobiti sve ovdje \"\n\"još živuće.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Gledaj, ovdje vodim posao. Ne prodajem informacije i nije me briga za nekog \"\n\"Kralja koji je mrtav duže nego što sam ja živ. Ako trebaš nešto da \"\n\"iskoristiš protiv tog Kralja nemrtvih, onda ti mogu pomoći...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, ne znam što bih ti stvarno mogao korisnog reći o ovome. Voda koja puni \"\n\"naše bunare dolazi iz podzemnog izvora. Čuo sam za tunel koji vodi do \"\n\"velikog jezera - možda su jedno te isto. Nažalost, ne znam što je uzrok \"\n\"trovanju naše vode.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Uvijek sam pokušavao držati velike zalihe hrane i pića u našem podrumu, ali \"\n\"pošto cijeli grad više nema izvora svježe vode, i naše zalihe će uskoro \"\n\"nestati. \\n\"\n\" \\n\"\n\"Molim te, učini što možeš, ili ne znam što ćemo dalje.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Drago mi je što si stigao na vrijeme! Naši bunari su postali bočati i \"\n\"ustajali, a neki mještani su se razboljeli pijući iz njih. Naše zalihe \"\n\"svježe vode brzo se troše. Vjerujem da postoji prolaz koji vodi do izvora \"\n\"koji opslužuju naš grad. Molim te, pronađi uzrok ove nesreće ili ćemo \"\n\"sigurno svi izginuti.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Molim te, požuri. Svaki protekli sat približava nas nestanku vode za piće. \\n\"\n\" \\n\"\n\"Ne možemo dugo preživjeti bez tvoje pomoći.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Što to kažeš - sama prisutnost demona prouzročila je onečišćenje vode? Oh, \"\n\"iskonski veliko zlo vreba pod našim gradom, ali tvoja upornost i hrabrost \"\n\"daje nam nadu. Molim te, uzmi ovaj prsten - možda će ti pomoći u uništenju \"\n\"takvih podlih stvorenja.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Moja baka je jako slaba, a Garda kaže da ne smijemo piti vodu iz bunara. \"\n\"Molim te, možeš li nam nekako pomoći?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin ti je rekao istinu. Očajnički trebamo svježu vodu, i to uskoro. \"\n\"Pokušao sam očistiti jedan od manjih bunara, ali smrdi na ustajalu \"\n\"prljavštinu. Sigurno je začepljen na izvoru.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Ti piješ vodu?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Ljudi u Tristramu će umrijeti ako ne možeš vratiti svježu vodu u njihove \"\n\"bunare. \\n\"\n\" \\n\"\n\"Znaj ovo - demoni stoje iza ovoga, ali nisu svjesni što su iznjedrili.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Barem jednom, sam uz tebe. Moj posao tako reći posustaje, ako nemam tržište \"\n\"za robu. Bolje saznaj što se događa, čim prije!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Čini se da je nadbiskup Lazar potaknuo mnoge mještane da se spuste u \"\n\"labirint kako bi pronašli nestalog kraljeva sina. Poigravao se njihovim \"\n\"strahovima i pretvorio ih u mahnitu gomilu. Nitko od njih nije bio spreman \"\n\"za ono što je ležalo u hladnoj zemlji... Lazar ih je ostavio tamo dolje, u \"\n\"kandžama neizreciva užasa - da umru.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Tako mi svjetlosti, znam tog podlog demona. Mnoštvo je nosilo ožiljke \"\n\"njegova gnjeva na svojim tijelima, kada je nekoliko preživjelih od napada \"\n\"pod vodstvom Lazara ispuzalo iz katedrale. Ne znam čime je osakatio svoje \"\n\"žrtve, ali to nije s ovoga svijeta. Ostavljao je gnojne rane praćene \"\n\"bolešću, čak sam i ja mislio da ih je gotovo nemoguće liječiti. Čuvaj se, \"\n\"ako se namjeravaš boriti s tim demonom...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Kad je Farnham govorio nešto o mesaru koji ubija ljude, mislila sam da priča \"\n\"gluposti. Ali pošto si ti to spomenuo, možda je istina.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Vidio sam ono što Farnham naziva Mesarom dok se provlačio preko tijela mojih \"\n\"prijatelja. Mahao je satarom velikom poput sjekire, sakačeći udove i \"\n\"sijekući hrabre ljude na licu mjesta. Od tučnjave me odvojilo mnoštvo malih \"\n\"škripavih demona i nekako sam pronašao stube za izlaz. Više nikada nisam \"\n\"vidio tu gnusnu zvijer, ali njegovo krvlju umrljano lice me proganja do dan \"\n\"danas.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Velika! Velika satara ubija sve moje prijatelje. Nisam ju mogao zaustaviti, \"\n\"morao sam pobjeći, nisam ih mogao spasiti. Zarobljeni u sobi s mnogo tijela, \"\n\"mnogo prijatelja... NEEEEEEEEEE!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Mesar je sadističko stvorenje koje uživa u mučenju i boli drugih. Vidio si \"\n\"njegovo djelo kod pijandure Farnhama. Njegovo uništenje, osigurat će \"\n\"sigurnost ovog sela.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Znam mnogo više nego što misliš o tom jezivom demonu. Njegovi mali \"\n\"prijatelji držali su me i uspjeli su mi isčupati nogu prije nego što me \"\n\"Griswold izvukao iz te rupe. \\n\"\n\" \\n\"\n\"Otvoreno ću ti reći - ubij ga prije nego što on ubije tebe i doda tvoj leš u \"\n\"svoju kolekciju.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Molim te, saslušaj me. Nadbiskup Lazar, doveo nas je ovdje da pronađemo \"\n\"izgubljenog princa. Gad nas je odveo u zamku! Sada su svi mrtvi... ubijeni \"\n\"od strane demona kojeg je zvao Mesar. Osveti nas! Pronađi tog Mesara i ubij \"\n\"ga tako da naše duše konačno mogu na počinak...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Dok se spuštaš sve dublje u labirint, možda ćeš tamo naći skrivene knjige \"\n\"velikog znanja. \\n\"\n\" \\n\"\n\"Pažljivo ih pročitaj, jer ti mogu reći stvari, čak i meni nepoznate.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Poznajem mnoge mitove i legende koje mogu sadržavati odgovore na pitanja \"\n\"koja se mogu pojaviti na tvojim putovanjima po Labirintu. Ako naiđeš na \"\n\"izazove i pitanja u potrazi za znanjem, potraži me i reći ću ti što znam.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden posjeduje i vodi Gostionicu izlazećeg sunca već skoro četiri godine. \"\n\"Kupio ju je samo nekoliko mjeseci prije nego što je sve otišlo kvragu. On i \"\n\"njegova supruga Garda nemaju novca za odlazak, jer su sve uložili u bolji \"\n\"život ovdje. On je dobar i vrlo odgovoran čovjek.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Siroti Farnham. On je uznemirujući podsjetnik na prokletu skupinu koja je \"\n\"tog mračnog dana s Lazarom ušla u katedralu. Uspio je pobjeći, ali njegova \"\n\"hrabrost i velik dio razuma ostali su u nekoj mračnoj jami. Danas utjehu \"\n\"nalazi samo na dnu svoje čašice, ali povremeno se u njegovu trabunjanju \"\n\"kriju djelići istine.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Vještica Adria, je anomalija ovdje u Tristramu. Stigla je nedugo nakon što \"\n\"je katedrala oskrnavljena dok je većina mještana bježala. Sagradila je malu \"\n\"kolibu preko noći na rubu grada, ima pristup mnogim čudnim i tajanstvenim \"\n\"artefaktima i knjigama znanja, čak meni nepoznatima.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Priča o Wirtu je zastrašujuća i tragična. Uzeli su ga iz naručja majke i \"\n\"odvukli u labirint mali, gadni demoni koji rukuju opakim kopljima. Tog je \"\n\"dana odvedeno mnogo druge djece, uključujući sina kralja Leorika. Vitezovi \"\n\"palače su otišli dolje, ali se nikada nisu vratili. Kovač je pronašao \"\n\"dječaka, ali tek nakon što su ga zle zvijeri počele mučiti iz svojih \"\n\"sadističkih užitaka.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Smatram ga pravim prijateljem, možda najbližim ovdje. Ponekad je \"\n\"pomalo zbunjen, ali nikad nije postojala brižnija ili pažljivija duša. \"\n\"Njegovo znanje i vještine su rijetki, a vrata su mu uvijek otvorena za \"\n\"svakoga.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian je dobra žena. Obožavana zbog svog dobrog duha i vedrog osmijeha, \"\n\"zauzima posebno mjesto u mom srcu. Ostala je u gostionici kako bi uzdržavala \"\n\"svoju staru baku koja je previše bolesna da bi otputovala. Ponekad se bojim \"\n\"za njenu sigurnost, ali znam da bi svaki muškarac u selu radije umro, nego \"\n\"da je vidi ozljeđenu.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria je mudra za svoje godine, ali moram priznati - malo me plaši. \\n\"\n\" \\n\"\n\"Ali, nije bitno. Ako ikada budeš trebao trgovati predmetima magije, ona \"\n\"posjeduje neobično dobro opskrbljenu kolibu odmah preko rijeke.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt je bitanga i mali nitkov. Uvijek je upadao u nevolje, i nije čudno to, \"\n\"što mu se dogodilo. \\n\"\n\" \\n\"\n\"Vjerojatno se glupirao negdje gdje nije trebao. Žao mi je dječaka, ali ne \"\n\"podnosim njegovo društvo.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin je dobar čovjek - i svakako najvelikodušniji u selu. Uvijek se brine \"\n\"za potrebe drugih, ali čini se da ga svakojake nevolje sustignu kamo god \"\n\"pođe...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Došao sam do vrlo zanimljiva otkrića. Za razliku od nas, stvorenja u \"\n\"Labirintu mogu se izliječiti bez pomoći napitaka ili magije. Ako ozlijediš \"\n\"jedno od čudovišta, provjeri je li mrtvo ili će se vrlo brzo regenerirati.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Prije nego što ju je preuzelo to, što god da vreba ispod. Katedrala je bila \"\n\"mjesto velikog učenja. Tamo se može naći mnogo knjiga. Ako ih pronađeš, \"\n\"trebao bi ih sve pročitati, jer neke možda kriju tajnu o radu Labirinta.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold se razumije u umijeće ratovanja koliko i ja u umijeće liječenja. On \"\n\"je lukav trgovac, a u njegovu poslu mu nema ravna. Valjda zato što je on \"\n\"jedini preostali kovač ovdje.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain je pravi prijatelj i vrlo je mudar. Održava ogromnu knjižnicu i ima \"\n\"urođenu sposobnost raznanja prave prirode mnogih stvari. Ako ikada imaš \"\n\"pitanja, on je prava osoba za odgovore.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Dok koristim neke ograničene oblike magije za stvaranje napitaka i eliksira \"\n\"koje ovdje pohranjujem, Adria je prava čarobnica. Ona nikada ne spava i \"\n\"uvijek ima pristup mnogim mističnim knjigama i artefaktima. Vjerujem da je \"\n\"njena koliba mnogo više od kolibe kakvom se čini, ali nikako ne mogu ući u \"\n\"to mjesto.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Siroti Wirt. Učinio sam sve moguće za to dijete, ali znam da prezire onu \"\n\"drvenu nogu koju sam mu bio prisiljen pričvrstiti. Rane su bile grozne. \"\n\"Nitko, a posebno tako malo dijete ne bi trebalo patiti na taj način.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Stvarno ne shvaćam zašto je Ogden ostao ovdje u Tristramu. Pati od blage \"\n\"nervoze, ali je inteligentan i marljiv čovjek koji bi se dobro snašao gdje \"\n\"god da ode. Pretpostavljam da je to zbog straha od brojnih ubojstava koja se \"\n\"događaju u obližnjem selu, ili možda želje njegove supruge da njihova \"\n\"obitelj ostane na okupu u svome domu.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogdenova konobarica je slatka djevojka. Njena baka je prilično bolesna i \"\n\"pati od deluzija. \\n\"\n\" \\n\"\n\"Ona tvrdi da su to vizije, ali ja ionako nemam dokaza za to.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Dobar dan! Kako vam mogu pomoći?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Moja baka je sanjala da ćeš doći i razgovarati sa mnom. Ona ima vizije znaš, \"\n\"i vidi budućnost.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Žena na rubu grada je vještica! Čini se simpatičnom, a njeno ime Adria \"\n\"ugodno je uhu, ali ja je se jako bojim. \\n\"\n\" \\n\"\n\"Trebao bi netko hrabar, poput tebe, da provjeri što ona tamo radi.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Naš kovač je ponos stanovnika Tristrama. Ne samo da je majstor koji je \"\n\"pobijedio na mnogim natjecanjima unutar svog ceha, nego ga je pohvalio i naš \"\n\"kralj Leorik, neka mu je spokoj duši. Griswold je isto veliki junak, samo \"\n\"pitaj Caina.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain je pripovjedač Tristrama otkad znam za sebe. On zna puno toga i može \"\n\"vam reći sve, o gotovo svemu.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham je pijandura koja svoju trbušinu puni pivom, a ostalima puni uši \"\n\"glupostima. \\n\"\n\" \\n\"\n\"Znam da se i Pepin i Ogden suosjećaju s njim, ali postajem frustrirana \"\n\"gledajući ga kako sve više i više svake noći gubi razum.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin je spasio život moje bake, znam da mu se za to nikad neću moći \"\n\"odužiti. Njegova sposobnost da izliječi svaku bolest moćnija je od \"\n\"najmoćnijeg mača i tajanstvenija od bilo koje čarolije koja postoji. Ako ti \"\n\"ikada zatreba liječenje, Pepin ti može pomoći.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Odrasla sam s Wirtovom majkom, Canace. Iako je bila lakše ozlijeđena kada su \"\n\"ga ta grozna stvorenja otela, nikad se nije oporavila. Mislim da je umrla od \"\n\"slomljenog srca. Wirt je postao mladić podlog duha, koji samo želi \"\n\"profitirati na tuđem trudu. Znam da je patio i vidio nezamislive strahote, \"\n\"ali nešto od tog mraka je još uvijek nadvito nad njim.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden i njegova žena primili su mene i moju baku u svoj dom, čak su mi \"\n\"dopustili da zaradim nekoliko zlatnika radeći u pivnici. Toliko im dugujem, \"\n\"nadam se da ću jednog dana napustiti ovo mjesto i pomoći im da pokrenu \"\n\"veliki hotel na istoku.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Što mogu učiniti za vas?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Sjekira? To je dobro oružje, izbalansirano protiv svakog neprijatelja. \"\n\"Pogledaj kako cijepa zrak, a onda zamisli lijepu debelu demonsku glavu \"\n\"ispred nje. Zapamti, međutim, da se sporo zamahuje, ali zadaje težak udarac!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Na tvome oružju i oklopu vidjet će se znakovi borbe protiv sila Tame. Ako mi \"\n\"ih doneseš, uz malo rada i vrućine iz kovačnice, mogu ih vratiti u vrhunsko \"\n\"borbeno stanje.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Dok moram praktički krijumčariti potrebne metale i alate iz karavana koje se \"\n\"nalaze po rubovima našeg ukletog grada, čini se da ta vještica Adria, uvijek \"\n\"dobije ono što joj treba. Kad bih znao i malo koristiti magiju kao ona, \"\n\"mogao bih napraviti neke doista nevjerojatne stvari.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian je dobra djevojka. Šteta što je njena baka tako lošeg zdravlja, \"\n\"inače bih ih obje izvukao odavde na jednoj od trgovačkih karavana.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Ponekad pomislim da Cain previše priča, ali valjda je to njegov životni \"\n\"poziv. Kad bih mogao saviti čelik kao što on može saviti tvoje uho, mogao \"\n\"bih napraviti odijelo od dvorskih tanjura dostojno i za cara!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Bio sam s Farnhamom te noći kada nas je Lazar odveo u Labirint. Nikada više \"\n\"nisam vidio nadbiskupa ponovno, možda ne bih preživio da Farnham nije bio uz \"\n\"mene. Bojim se da je napad ostavio njegovu dušu tako obogaljenu kao, eto i \"\n\"moju nogu. Ne mogu voditi ovu bitku za njega, ali da mogu, bih.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Dobar čovjek koji potrebe drugih stavlja iznad svojih. Nećete naći u \"\n\"Tristramu ili van njega, na nekoga tko bi imao nešto loše reći o \"\n\"iscjelitelju.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Taj dečko će se uvaliti u ozbiljnu nevolju, ponovno. Pokušao sam ga \"\n\"zainteresirati za rad i učenje poštenog zanata, ali više voli veliku zaradu \"\n\"od trgovine sumnjivom robom. Ne mogu mu to zamjeriti nakon onoga što mu se \"\n\"dogodilo, ali bih volio da je malo oprezniji.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"Djevojka koja donosi piće? Oh da, tako lijepa dama. I ljubazna, isto.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Zašto ta stara baba ne učini nešto za promjenu. Naravno, naravno, posjeduje \"\n\"stvari, ali slušaj me, ona je neprirodna. Nikad je nisam vidio da jede ili \"\n\"pije, a ne možeš vjerovati nekome tko ne pije, barem malo.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain nije onakav kakvim se predstavlja. Naravno, naravno, priča dobre \"\n\"pričice... neke od njih su stvarno strašne ili smiješne... ali mislim da on \"\n\"zna više, nego što misli, da zna.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Dobri stari Griswold. Volim ga kao brata! Zajedno smo se borili, \"\n\"znaš, kada smo... mi... Lazar...  Lazar... Lazar!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Ha ha, volim Pepina. Stvarno se trudi, znaš. Slušaj me, trebao bi ga bolje \"\n\"upoznati. On je dobar momak koji ljudima uvijek želi pomoći. Hej, \"\n\"pretpostavljam da je on poput tebe, heroj? I ja sam nekoć bio heroj...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt je dijete s više problema od mene, a ja znam sve o problemima. Slušaj \"\n\"me, taj klinac ima dobre pogodbe, ali on je bio tamo, znaš? Izgubio je nogu! \"\n\"Mora hodati uokolo na komadu drveta. Tako tužno, tako tužno...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden je najbolji čovjek u gradu. Mislim da se njegovoj ženi ne sviđam \"\n\"previše, ali sve dok ona ima pune bačve, ne smeta mi. Čini se da provodim \"\n\"više vremena s Ogdenom od ostalih, a on je tako dobar prema meni...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Želim ti nešto reći, jer znam sve o ovim stvarima. To je moja specijalnost. \"\n\"Ovo ovdje je najbolje... najbolje! Ono drugo pivo nije dobro, zbog onih \"\n\"glupih psa...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Nitko me nikad ne... sluša. Negdje, nisam baš siguran, ali negdje ispod \"\n\"crkve je cijela hrpa zlata. Sjaji i blista, i samo čeka da ju netko pronađe.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Znam da imaš vlastite ideje, i znam da nećeš vjerovati ovome, ali to oružje \"\n\"koje imaš - jednostavno nije dobro protiv tih velikih zvijeri! Oh, baš me \"\n\"briga što Griswold kaže, ne mogu napraviti više ništa dobro kao nekada...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Mudrost se zaslužuje, a ne daje. Ako otkriješ knjigu znanja, upamti njezine \"\n\"riječi. Ako već imaš znanja o tajanstvenim misterijama zapisanim u knjizi, \"\n\"zapamti - ta se razina majstorstva uvijek uvećava.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Najveća moć često traje najkraće. Možda ćeš pronaći snažne drevne riječi \"\n\"ispisane na svicima pergamenta. Snaga ovih svitaka je u sposobnosti učenjaka \"\n\"ili vještini da baca čari s jednakom sposobnošću. Njihova je slabost što se \"\n\"prvo trebaju pročitati naglas i nikada se ne mogu zapamtiti. Imaj na umu da \"\n\"se ovi svici mogu pročitati samo jednom, stoga ih pažljivo koristi.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Premda je sunčeva toplina opasno neizdrživa, veću opasnost predstavlja sam \"\n\"plamen svijeće. Nijedna energija, ma koliko velika, ne može se koristiti bez \"\n\"odgovarajućeg fokusa. Za mnoge čarolije, začarani štapovi mogu se puniti \"\n\"čarobnom energijom više puta. Imam sposobnost obnove njihove moći, ali znaj \"\n\"da ništa nije besplatno.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Veličina našeg znanja ovisi o brojnosti naših ljudi. Ako nađeš knjigu ili \"\n\"svitak koji ne možeš dešifrirati, ne ustručavaj se donijeti ih meni. Ako ih \"\n\"uspijem shvatiti, podijelit ću ta saznanja s tobom.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Za čovjeka koji poznaje samo željezo, nema veće magije od čelika. Kovač \"\n\"Griswold je veći čarobnjak nego što misli. Njegova sposobnost spajanja vatre \"\n\"i metala je bez premca u ovoj zemlji.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Korupcija ima snagu prijevare, ali nevinost ima snagu čistoće. Mlada žena \"\n\"Gillian ima čisto srce, stavljajući potrebe svoga matrijarha iznad svojih. \"\n\"Boji me se, ali samo zato što me ne razumije.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Škrinja otvorena u tami ne sadrži veće blago nego kad je otvorena na \"\n\"svjetlu. Pripovjedač Cain je enigma, ali samo za one koji ne vide. Njegovo \"\n\"znanje o onome ispod katedrale daleko je veće nego što čak i on sam shvaća.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Što više vjerujete u jednog čovjeka, vjera je sve slabija. Farnham je \"\n\"izgubio svoju dušu, ali ne zbog demona. Izgubio ju je kad je vidio svoje \"\n\"sumještane koje je izdao nadbiskup Lazar. On ima znanje koje treba \"\n\"prikupiti, ali ti moraš odvojiti činjenice od fantazija.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Ruka, srce i um mogu činiti čuda kad su u savršenoj harmoniji. Iscjelitelj \"\n\"Pepin vidi tijelo na način na koji ni ja ne mogu. Njegova sposobnost \"\n\"oporavka bolesnih i ozlijeđenih je povećana njegovim znanjem o pripravku \"\n\"eliksira i napitaka. On je veliki saveznik, kao što si i ti u Tristramu.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Mnogo toga o budućnosti ne znamo, ali budućnost na djeci ostaje. Dječak Wirt \"\n\"ima crnilo na duši, ali on nije prijetnja gradu ni njegovim ljudima. Njegov \"\n\"tajnoviti odnos sa švercerima i mutnim cehovima obližnjih gradova omogućuju \"\n\"mu pristup mnogim uređajima koji se ne mogu lako nabaviti u Tristramu. Iako \"\n\"su njegove metode nedopustive, Wirt ti može pomoći u borbi protiv nadolazeće \"\n\"tame.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Zemljani zidovi i slamnate nadstrešnice ne čine dom. Gostioničar Ogden ima \"\n\"više svrhe u ovom gradu nego što mnogi misle. On pruža utočište Gillian i \"\n\"njenoj baki, vodi život kakav mu je Farnham ostavio i osigurava okupljalište \"\n\"za sve koji su ostali u gradu. Njegova gostionica i jednostavni užici koji \"\n\"se tamo još uvijek mogu pronaći, daju uvid u život kakav ljudi ovdje pamte. \"\n\"To sjećanje hrani njihove nade u tvoj uspjeh.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst, dođi ovdje...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Nema svatko u Tristramu koristi, ili tržište za sve što ćeš pronaći u \"\n\"labirintu. Čak ni ja, koliko god je to nevjerojatno. \\n\"\n\" \\n\"\n\"Ponekad ćeš samo ti moći pronaći svrhu za određenu stvar.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Ne vjeruj svemu što ona pijandura kaže. Previše pića pomutilo mu je pamet i \"\n\"zdrav razum.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Valjda kovaču dugujem svoj život, ili ono što je ostalo od njega. Griswold \"\n\"mi je ponudio šegertovanje u kovačnici, on je vrlo pristojan tip, ali nikad \"\n\"neću dobiti dovoljno novca za... pa, recimo samo da imam određene planove \"\n\"koji zahtijevaju veću količinu zlata.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Da sam nekoliko godina stariji, obasuo bih je svim bogatstvom koje mogu \"\n\"prikupiti i uvjeravam te da se mogu dočepati nekih vrlo lijepih stvari. \"\n\"Gillian je prelijepa djevojka koja bi trebala napustiti Tristram čim bude \"\n\"sigurno. Hmmm... možda ću je povesti sa sobom kad odem...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain zna previše. Silno me plaši, čak i više od one žene preko rijeke. \"\n\"Stalno mi govori da sam sretan što sam živ i da je moja priča prorečena u \"\n\"legendi. Mislim da je sišao s uma.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham, je čovjek s ozbiljnim problemima, a ja znam koliko ozbiljni \"\n\"problemi mogu biti. Previše je vjerovao u integritet jednog čovjeka, a Lazar \"\n\"ga je odveo u same ralje smrti. A znam kako je dolje, stoga mi ne govori \"\n\"svoje planove o uništenju zla koje obitava u tom Labirintu. Samo pripazi na \"\n\"noge...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Sve dok ne trebaš nešto pričvrstiti, stari Pepin je dobar. \\n\"\n\" \\n\"\n\"Da sam imao neke od onih napitaka koje priprema, možda bih još uvijek imao \"\n\"nogu...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Od Adrie se stvarno naježim. Naravno, Cain je jeziv u onome što vam može \"\n\"reći o prošlosti, ali ta vještica vidi u vašu prošlost. Uvijek ima neki \"\n\"način da dobije sve što treba. Adria se dočepa više robe nego što prođe kroz \"\n\"vrata Kraljeve tržnice tijekom Velikog festivala.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden je budala zato što je ostao ovdje. Mogao bih ga izvući iz grada za \"\n\"razumnu cijenu, ali je uporan u pokušaju da se izvuče s tom glupom \"\n\"gostionicom. Barem je omogućio Gillian radno mjesto, a njegova supruga Garda \"\n\"radi odličnu pastirsku pitu...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Hvala nebesima što si se vratio!\\n\"\n\"Mnogo toga se promijenilo otkad ne živiš ovdje, prijatelju. Sve je bilo \"\n\"mirno dok mračni jahači nisu došli i uništili naše selo. Mnogi su osakaćeni \"\n\"na mjestu, a oni koji su uzeli oružje ubijeni su ili odvučeni u roblje. Ili \"\n\"još gore, crkva na rubu grada je oskrnavljena i koristi se za mračne \"\n\"rituale. Krici koji odjekuju u noći nisu ljudski, ali neki od naših mještana \"\n\"možda su još živi. Slijedi put između moje gostionice i kovačnice kako bi \"\n\"pronašao crkvu i spasio ih što više. \\n\"\n\" \\n\"\n\"Možda ti mogu reći nešto više, ako ponovno razgovaramo. Sretno.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Rekao sam, muu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Gledaj, ja sam samo krava, u redu?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:979\n#, fuzzy\n#| msgid \"Hell\"\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Pakao\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:990\n#, fuzzy\n#| msgid \"Hell\"\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Pakao\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:997\n#, fuzzy\n#| msgid \"Hell\"\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Pakao\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Prsten munje\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Gladijatorov prsten\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Pepin iscjelitelj\"\n\n#: Source/translation_dummy.cpp:1031\n#, fuzzy\n#| msgid \"Pepin the Healer\"\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Pepin iscjelitelj\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1035\n#, fuzzy\n#| msgid \"Select Action\"\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Odaberi radnju\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Prsten vatre\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Potraga\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1043\n#, fuzzy\n#| msgid \"Sell items\"\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Prodavati predmete\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"inačica {:s}\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Smanji gamu\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Povećaj gamu\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Karta nije dostupna u gradu\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Ponovno pokreni u gradu\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Srce\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"obnavlja život\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"diže iz mrtvih\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"smanjuje snagu\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"smanjuje vještinu\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"smanjuje vitalnost\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Pokušavate ispustiti podni predmet?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Prisiljava čekanje okomitog usklađivanje (Vertical Sync). Sprječava efekt \"\n#~ \"kidanja slike pri iscrtavanju slike. Onemogućavanje može pomoći pri \"\n#~ \"zapinjanju miša na određenim sustavima.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Ograniči broj sl/s\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Broj sličica (FPS) je ograničen u svrhu izbjegavanja povišenog CPU \"\n#~ \"korištenja. Ograničenje uzima u obzir brzinu osvježavanja.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Pogodci\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Neuništivo,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Nema potrebnih svojstava\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Mogućnosti:\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Neuspjelo otvaranje arhive igrača za zapisivanje.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Nemoguće čitanje arhive datoteke spremanja\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Nemoguće zapisivanje arhive datoteke spremanja\"\n"
  },
  {
    "path": "Translations/hu.po",
    "content": "#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: hu\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Játéktervezés\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Senior tervezők\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"További tervezés\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Főprogramozó\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Senior programozók\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programozás\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Vendég programozók\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net programozás\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Sorkommunikációs programozás\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Telepítő programozás\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Grafikus rendezők\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Rajzolók\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Technikai rajzok\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Filmes rendezők\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D filmes rendezők\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Filmes technikai rajzok\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Főproducer\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Producer\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Segédproducer\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Zene\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Hangtervezés\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Filmes zene és hang\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Szinkronhangok, rendezés és casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Forgatókönyv és történet\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Hangszerekztés\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Szinkronhangok\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Hangmérnök\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Kézikönyv tervezés és szerkeztés\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Kézikönyv rajz\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Minőségbiztosítási vezető (Főtesztelő)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Minőségbiztosítási rohamosztag (Tesztelők)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Minőségbiztosítási különleges alakulat (Kompatibilitás tesztelők)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Minőségbiztosítási tűzérség (További tesztelők) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Minőségbiztosítási hírszerzés\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Hálózati Információs Szolgáltatások Rendje\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Vevőszolgálat\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Eladás\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Dabiri úr háttérénekesei\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"PR\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Nemzetközi eladás\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Amerikai eladás\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Gyártás\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Jogi- és üzletitanácsadás\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Külön köszönet\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Köszönet\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Emlékére\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Nagyon különleges köszönet\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Általános menedzsment\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Szoftver mérnökség\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Grafikus rendező\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Grafikusok\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Tervezés\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Hangtervezés és hangmérnökség\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Minőségbiztosítási vezető\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Tesztelők\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Kézikönyv\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tTovábbá\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Küldetések írása\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Köszönet\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tKülönleges köszönet: Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Minőségbiztosítási vezető\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Minőségbiztosítási főtesztelő\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"További főtesztelők\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Tesztelők\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Termék marketing menedzser\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"PR menedzser\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Termék almenedzser\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Az ezrek gyűrűje\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tEgy lélek sem lett eladva a játék készítése során.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"Rendben\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Válassz osztályt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Mégse\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Új többjátékos hős\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Új egyjátékos hős\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"A mentés már létezik\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Játék betöltése\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Új játék kezdése\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Egyjátékos hősök\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"A zsivány és a mágus csak a teljes változatban elérhetőek. Vedd meg a \"\n\"játékot a https://www.gog.com/game/diablo oldalon.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Írd be a nevedet\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Érvénytelen név. Nem tartalmazhat szóközt és bizonyos karaktereket, \"\n\"szavakat.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Nem sikerült létrehozni a hős.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Szint:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Erősség:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Mágia:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Ügyesség:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Egészség:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Mentés:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Válassz hőst\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Új hős\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Töröl\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Többjátékos hősök\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Többjátékos hős törlése\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Egyjátékos hős törlése\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Biztosan ki akarod őt törölni: \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Egyjátékos Mód\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Többjátékos Mód\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Beállítások\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Segítség\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Készítők\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Kilépés\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Kilépés\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Próbaváltozat\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Kliens-Szerver (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Egyedül\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Többjátékos Mód\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Szükséges:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"nem kell gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Kapcsolat típusa\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Gateway cseréje\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Minden eszköz egy TCP-kompatibilis hálózathoz csatlakozzon.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Minden eszköz az internethez csatlakozzon.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Semmi. Játszhatsz magadban többjátékos szabályok szerint.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Játékosok száma: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diabló\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diabló Próbaváltozat\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Próbaváltozat\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"A gazda más játékot futtat.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"A gazda más játékváltozatot ({:s}) futtat, mint te.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"A verziód {:s} nem egyezik a gazdáéval: {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Leírás:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Válassz opciót\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Új játék\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Új nyilvános játék\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Csatlakozás\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Nyilvános játékok\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Töltés...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Semmi\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"MÉGSE\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"\"\n\"Hozz létre egy új játékot az általad választott nehézségen. Ide csak az \"\n\"csatlakozhat, aki ismeri a címet.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Hozz létre egy nyilvános játékot az általad választott nehézségen. Ide bárki \"\n\"csatlakozhat.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Írd be a játék azonosítóját, hogy csatlakozz egy már meglévő játékhoz.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Írd be az IP címet vagy a gazdagép nevét, hogy csatlakozz egy már meglévő \"\n\"játékhoz.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Csatlakozz egy nyilvános játékhoz.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Alap\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Lidércnyomás\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Pokoli\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Nehézség: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Sebesség: Alapértelmezett\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Sebesség: Gyors\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Sebesség: Gyorsabb\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Sebesség: Leggyorsabb\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Játékosok: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Válassz nehézséget\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Csatlakozz {:s} játékokhoz\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Írd be a játék azonosítóját\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Írd be a címet\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Alap Nehézség\\n\"\n\"Itt kezdheti meg egy új hős az útját Diabló legyőzése felé.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Lidércnyomás Nehézség\\n\"\n\"A labirintus lakói megerősödtek és nagyobb akadályt fognak jelenteni. Csak \"\n\"tapasztalt hősöknek ajánlott.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Pokoli Nehézség\\n\"\n\"Az alvilág legerősebb lényei ólálkodnak a pokol kapujánál. Csak a legméltóbb \"\n\"hősök barangolhatnak ebbe a vidékbe.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"A hősöd el kell, hogy érje a 20-as szintet ahhoz, hogy csatlakozhass egy \"\n\"többjátékos játszmába Lidércnyomás nehézségen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"A hősöd el kell, hogy érje a 30-as szintet ahhoz, hogy csatlakozhass egy \"\n\"többjátékos játszmába Pokoli nehézségen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Válassz sebességet\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Gyors\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Gyorsabb\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Leggyorsabb\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Alap sebesség\\n\"\n\"Itt kezdheti meg egy új hős az útját Diabló legyőzése felé.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Gyors sebesség\\n\"\n\"A labirintus lakói gyorsabbak és nagyobb kihívást fognak jelenteni. \"\n\"Tapasztalt hősöknek javasolt csak.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Gyorsabb sebesség\\n\"\n\"A rémségek a tömlöcben gyorsabban fognak elkapni mint valaha. Csak egy \"\n\"tehetséges bajnoknak szabad szerencsét próbálni ilyen sebesség mellett.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Leggyorsabb sebesség\\n\"\n\"Az alvilág csatlósai szünet nélkül támadnak. Csak a legjobbak tehetnek \"\n\"próbát ilyen sebességen.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Írd be a jelszót\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Kiegészítő indítása\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Alapjáték indítása\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Igen\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Nem\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Nyomj be bármilyen gombot a gamepaden.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Beállított gomb:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Nyomj be bármilyen gombot.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Gomb törlése\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Beállított kombináció:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Kombináció törlése\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Előző ablak\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Van egy Discord szerverünk Discord.gg/devilutionx címen, ahol Diablóval és a \"\n\"kiegészítővel kapcsolatos dolgokról beszélünk.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"A DevilutionX fenntartója Diasurgical, hibákat és problémákat ezen a címen \"\n\"lehet jelenteni: https://github.com/diasurgical/devilutionX\\n\"\n\"\\n\"\n\"Hogy jobban tudjunk segíteni, kérünk ne felejtsd el megadni a verzió számot, \"\n\"az operációs rendszert és a probléma jellegét.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Figyelmeztetés:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tA DevilutionX nem támogatott és nincs karbantartva a Blizzard \"\n\"Entartainment, se nem a GOG.com által. Egyikük sem tesztelte vagy \"\n\"tanusította a DevilutionX minőségét vagy kompatibilitását. Minden kérvényt a \"\n\"DevilutionX-szel kapcsolatban Diasurgicalnak kell továbbítani, nem a \"\n\"Blizzard Entertainment-nek vagy a GOG.com-nak.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tEz a port használja a következő betűket, amelyek SIL Open Font License \"\n\"egyezménnyel rendelkeznek: Charis SIL, New Athena Unicode, Unifont, Noto. \"\n\"Továbbá használ Twitmoji-t, amely pedig CC-BY 4.0 egyezménnyel bír. A port \"\n\"SDL-t használ, ami zlib egyezménnyel rendelkezik. Részletekért lásd az \"\n\"olvass-el fájlt.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Szerzői Jog © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Hiba\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Hiba történt: {:s} {:d}. sor\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Adatfájl hiba\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Nem sikerült a fő adatarchívumot megnyitni: ({:s}).\\n\"\n\"\\n\"\n\"Ellenőrizzük le, hogy valóban a játék mappájában található-e.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Csak olvasható mappa hiba\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Nem lehet a következő helyre írni:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Játék: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Egyedül\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Jelszó: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Nyilvános játék\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Szint: Fészek {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Szint: Kripta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Város\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Szint: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tabulátor\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Escape\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Saját hős\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Küldetések\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Térkép\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Főmenü\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Eszköztár\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Varázsigék könyve\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Üzenet küldése\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Elérhető parancsok:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Parancs \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" egy ismeretlen parancs.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Leírás: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Paraméterek: nincs szükség további paraméterekre.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Paraméterek: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Az arénák csak többjátékos módban elérhetőek.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Melyik arénát szeretnéd meglátogatni?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Érvénytelen aréna-szám. Az érvényes számok:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\"Ahhoz, hogy belépj egy arénába, a városban vagy egy másik arénában kell \"\n\"lenned.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"A megvizsgálás csak többjátékos módban támogatott.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Abbahagytad a játékosok megvizsgálását.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Nincs ilyen nevű játékos\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Játékos megvizsgálása: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\"Kiírja az elérhető parancsokat vagy a segítséget egy konkrét parancshoz.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[parancs]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Játékos aréna\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<aréna-szám>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Aréna fiolákat ad.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<szám>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Megvizsgálja egy másik játékos készségeit és felszerelését.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<játékos név>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Megmutatja a jelenlegi szint által használt véletlen magokat.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Tilos játékosokat támadni\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Szabad játékosokat támadni\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Gyorsbillentyű: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Válassz más varázsigét\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Gyorsbillentyű: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} készség\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"A {:s} igéje\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"0. szintű varázsige - használhatatlan\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"{:d}. szintű varázsige\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"A {:s} tekercse\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} darab tekercs\"\nmsgstr[1] \"{:d} darab tekercs\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"A {:s} pálcája\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} töltés\"\nmsgstr[1] \"{:d} töltés\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} szem arany\"\nmsgstr[1] \"{:s} szem arany\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Nem értük el a követelményeket\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, {:d}. szint\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Életerő {:d} az {:d}-ből\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Jobb kattintással használod\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Szintlépés\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"{:s} szem arany van itt. Mennyit szeretnél elvenni?\"\nmsgstr[1] \"{:s} szem arany van itt. Mennyit szeretnél elvenni?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Varázskapu\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"{:s}től\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Kapu\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"A beszennyezett oltárhoz\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"a 15. szinthez\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Nem sikerült betölteni az adatot a fájlból {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} befejezetlen, ellenőrizd a fájl tartalmát.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"A {0} fájlodnak hiányoznak az elvárt oszlopai, ellenőrizd, hogy a \"\n\"dokumentált formátumot használja-e.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"{1} kulcshoz nem-numerikus érték {0} a {3}. sor, {4}. oszlopánál a {2} \"\n\"fájlban\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"{1} kulcshoz intervallumon kívüli érték {0} a {3}. sor, {4}. oszlopánál a \"\n\"{2} fájlban\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"{1} kulcshoz érvénytelen érték {0} a {3}. sor, {4}. oszlopánál a {2} fájlban\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Nyomtassa ki ezt az üzenetet, majd lépjen ki\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Nyomtassa ki a verziót, majd lépjen ki\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Határozza meg a diabdat.mpq mappáját\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Határozza meg a mentések mappáját\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Határozza meg a diablo.ini mappáját\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Határozza meg a nyelvi kódot (például: en vagy hu)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Ugorja át a kezdő videókat\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Rajzolja ki a képrátát\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Engedélyezze a részletes naplózást\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Demófájl felvétele\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Demófájl lejátszása\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Minden képráta korlátozás kikapcsolása demók végigjátszása során\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Játék kiválasztása:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Próbaváltozat indítása\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Alapjáték indítása\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Kiegészítő indítása\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Kiegészítő beállításai:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"\"\n\"Jelentsd be a hibákat itt: https://github.com/diasurgical/deevilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\"Kérlek frissítsd a devilutionx.mpq és a fonts.mpq fájlokat a legfrissebb \"\n\"verzióra\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Nem sikerült betölteni a kezelőfelülethez szükséges adatokat.\\n\"\n\"\\n\"\n\"Győződj meg róla, hogy a devilutionx.mpq a játék mappájában található és a \"\n\"legfrissebb verzióval bír.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Kérlek frissítsd a fonts.mpq fájlt a legfrissebb verzióra\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Válaszidő túllépés --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Várunk a játékosokra --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"A segítség nem elérhető\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"az üzletekben\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Övön található tárgy {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Használjuk az övön található tárgyat.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Gyorsvarázs {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Gyorsbillentyű a készségnek vagy varázsigének.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Előző ige\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Kiválasztja az előző igét.\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Következő ige\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Kiválasztja a következő igét.\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Gyógyító fiola használata\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Elhasznál egy gyógyító fiolát az övünkről.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Varázs fiola használata\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Elhasznál egy varázs fiolát az övünkről.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Gyorsvarázs\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Nyissuk ki a varázsigék gyűjtőtárát.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Gyorsmentés\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Elmenti a játékot.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Gyorstöltés\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Betölti a játékot.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Kilépés\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Bezárja a játékot.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Hős megállítása\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Megállítja a hős mozgását és a fennmaradt akciókat.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Tárgyak világítása\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Mutatja a tárgyakat a padlón.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Tárgyak állandó világítása\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Folyamatosan mutatja a tárgyakat a padlón.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Térkép kepcsolása\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Átkapcsolja a térképet.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Térkép típus változtatása\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Áttetsző -> Átlátszó -> Minimap -> Semmi\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Nézd meg az eszköztárad.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Szereplő\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Nézd meg a szereplődet.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Küldetések\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Nézd meg a küldetéseket.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Varázsige könyv\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Nézd meg a varázskönyvet.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Gyors üzenet {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Használjunk egy gyorsüzenetet a csevegésben.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Információs ablakok elrejtése\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Elrejti az összes információs ablakot.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Nagyítás\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Nagyít a játék képernyőjére.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Szünet\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Leszüneteli a játékot.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Szünet (másodlagos)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Növeli a képernyő világosságát.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Csökkenti a képernyő világosságát.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Növeli a képernyő világosságát.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Növeli a képernyő világosságát.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Segítség\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Kinyitja a segítséget.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Fénykép\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Fényképet készít.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Játék információ\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Megmutatja a szükséges információkat a játékról.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Üzenetek\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Megmutatja a régi üzeneteket.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Eszköztár sorba rendezése\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Sorba rendezi az eszköztárat hatékony helykihasználás végett.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Konzol\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Kinyitja a Lua konzolt.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Elsődleges akció\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"Szörnyek megtámadása, tárgyak mozgatása, beszélgetés a városiakkal.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Másodlagos akció\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Ládák kinyitása, ajtók mozgatása, tárgyak felvétele.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Varázs akció\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"A kiválasztott varázsigék megidézi.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Akció visszavonása\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Bezárja a menüket.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Mozgatás fel\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Felfelé mozgatja a hősödet.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Mozgatás le\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Lefelé mozgatja a hősödet.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Mozgatás balra\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Balra mozgatja a hősödet.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Mozgatás jobbra\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Jobbra mozgatja a hősődet.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Megállás helyben\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Megakadályozza, hogy a hős elmozdulhasson a helyéről.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Megállás helyben kapcsolása\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Be- és kikapcsolja a hős mozgását.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Térkép\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Mozgatás le\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Mozgatás balra\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Felfelé mozgatja a hősödet.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Mozgatás jobbra\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Egér felfelé\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Felfelé menő egérmozgást imitál.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Egér lefelé\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Lefelé menő egérmozgást imitál.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Egér balra\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Balra menő egérmozgást imitál.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Egér jobbra\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Jobbra menő egérmozgást imitál.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Bal kattintás\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Bal egérkattintást imitál.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Jobb kattintás\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Jobb egérkattintást imitál.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Gamepad gyorsvarázs menü\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Tartsd nyomva, hogy előhozd a varázsigés gyorsbillentyűket.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Gamepad menü navigáló\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Tartsd nyomva, hogy hozzáférj a gamepad-es menü navigációhoz.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Játék menü felhozása\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Kinyitja a játékmenüt.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Játék elmentve\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Nincsenek többjátékos funkciók a demóban\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Hang létrehozása nem sikerült\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Nem érhető el a próbaváltozatban\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Nincs elég hely mentésre\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Nem lehet szünetelni a városban\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Ajánlott a merevlemezre másolni\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Többjátékos szinkronizációs hiba\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Nem lehet szünetelni többjátékos módban\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Mentés...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"\"\n\"Amíg sokak szíve gyenge\\n\"\n\"\\n\"\n\"Egy növekszik folyton egyre\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"\"\n\"Ha itt kő kövön nem marad\\n\"\n\"\\n\"\n\"Ragadd meg jól, mi nem szakad\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"\"\n\"Ahol sok a védelem\\n\"\n\"\\n\"\n\"Kevés ott az féktelen\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"\"\n\"Isten kardja fürge, éles\\n\"\n\"\\n\"\n\"Igaz útja ettől fényes\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"\"\n\"Amíg a hű szellem éber\\n\"\n\"\\n\"\n\"Büszke teste mint egy ékszer\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"\"\n\"Varázslatom ereje\\n\"\n\"\\n\"\n\"Hű munkámnak kenyere\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"\"\n\"Fénylő acélt ottan soha\\n\"\n\"\\n\"\n\"Nem rág meg a kor vasfoga\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"\"\n\"Nem az összes régi varázs\\n\"\n\"\\n\"\n\"Izzik úgy mint forró parázs\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"\"\n\"Ami egy ily fosztást kibírt\\n\"\n\"\\n\"\n\"Ragyogva az ismét kinyílt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"\"\n\"Itt az elmém sírhelye\\n\"\n\"\\n\"\n\"Szabadságom színtere\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"\"\n\"Titkos erő majd egy dögvész\\n\"\n\"\\n\"\n\"Csak az nyer itt aki fölnéz\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"\"\n\"Csak az tud megtörni\\n\"\n\"\\n\"\n\"Ki próbál feljönni\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"\"\n\"Kék víz, vörös vér, s minden mi ömlik\\n\"\n\"\\n\"\n\"Nappá lesz mind az utolsó csöppig\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"\"\n\"Tudás és bölcsesség\\n\"\n\"\\n\"\n\"Mind ez csak önteltség\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"\"\n\"Bűnös lelked ha szomjazik\\n\"\n\"\\n\"\n\"Az Úr fényezi rongyaid\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"\"\n\"Ahová téved a lelked\\n\"\n\"\\n\"\n\"Ott találod ezt a verset\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"\"\n\"Csodás erő jő majd bukás\\n\"\n\"\\n\"\n\"Nesze neked, kellett tudás\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"\"\n\"Az ember olykor hontalan\\n\"\n\"\\n\"\n\"De mindig talál rá arany\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"\"\n\"Amíg szeplőtlen a lélek\\n\"\n\"\\n\"\n\"Ifjú, s szép marad a képed\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"\"\n\"Mellettem egy hű honfitárs\\n\"\n\"\\n\"\n\"Nincsen nála jobb útitárs\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"\"\n\"Az ember kezét megmozdítja\\n\"\n\"\\n\"\n\"Aki a rosszat megfordítja\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"\"\n\"Mennyei erő gazdája\\n\"\n\"\\n\"\n\"Az igazak hű rabtársa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"\"\n\"Az élet esszenciája\\n\"\n\"\\n\"\n\"Egy jegy a szellemvilágba\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"\"\n\"Az utunk már fentről látszik\\n\"\n\"\\n\"\n\"Minek legyen bennünk pánik?\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"\"\n\"Megváltásunk drága ára\\n\"\n\"\\n\"\n\"Szellemünknek magas kára\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"\"\n\"Aki erre megy egyedül\\n\"\n\"\\n\"\n\"Szíve fényben nem feketül\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"\"\n\"Utolsóból is lehet még első\\n\"\n\"\\n\"\n\"Hiszen az is volt még egyszer kezdő\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"\"\n\"Nagyságos szív kicsiny bére\\n\"\n\"\\n\"\n\"Emberré lett Isten képe\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Legalább 8. szint szükséges, hogy használhasd.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Legalább 13. szint szükséges, hogy használhasd.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Legalább 17. szint szükséges, hogy használhasd.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"\"\n\"Rejtett tudás nyeresége\\n\"\n\"\\n\"\n\"Nélkülözött menedéke\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"\"\n\"Ami mostan nem öl meg téged\\n\"\n\"\\n\"\n\"Az aranyozza meg a véred\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"\"\n\"A tudás bizony hatalom\\n\"\n\"\\n\"\n\"A lelked éltesd szabadon\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"\"\n\"Gondolj rá amikor így adsz\\n\"\n\"\\n\"\n\"Másoknak te nyújtasz vigaszt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"\"\n\"Látni szépet tapasztalat\\n\"\n\"\\n\"\n\"A balgák meg kacagjanak\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"\"\n\"Mindenütt jó, de legjobb otthon\\n\"\n\"\\n\"\n\"Ezt kiáltotta a beteg gyomrom\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"\"\n\"A nagy gonosz legyőzhető\\n\"\n\"\\n\"\n\"Amíg van itt varázserő\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Fürgébbnek érzed magad.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Erősebbnek érzed magad.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Bölcsebbnek érzed magad.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Felfrissültnek érzed magad.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Ami eltörhet az el is fog.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedrális\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Sírkamra\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Barlang\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Fészek\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Kripta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}. szintje\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"{}. szintű {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} nehézség\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Menüben\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"loopback cím\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Nem tud csatlakozni\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"hiba: 0 bájt olvasva a szerverről\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq vagy spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Néhány kiegészítős MPQ fájl hiányzik\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Nem mindegyik kiegészítős MPQ lett megtalálva\\n\"\n\"Kérlek másold az összes hf*.mpq fájlt a megfelelő helyre.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Felbontás\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Futás a városban\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Tivadar küldetés\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Tehén küldetés\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Gyors arany felvétel\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Gyors csodaszer felvétel\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Gyors olaj felvétel\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Gyors felvétel a városban\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria újratölti a varázserőt\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Fegyverek gyors felvétele\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Páncélok gyors felvétele\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Sisakok gyors felvétele\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Pajzsok gyors felvétele\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Ékszerek gyors felvétele\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Küldetések véletlen sorsolása\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Tárgyak címkéjének mutatása\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Öv automatikus újratöltése\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Rontó szentélyek kikapcsolása\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Gyógyító fiolák felvétele\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Nagy gyógyító fiolák felvétele\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Varázs fiolák felvétele\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Nagy varázs fiolák felvétele\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Megújulás fiolák felvétele\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Teljes megújulás fiolák felvétele\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Beállítások\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Játék mentése\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Főmenü\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Kilépés a játékból\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Sebesség\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Zene kikapcsolva\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Hang\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Hang kikapcsolva\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Szünet\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Billentyűkombinációk:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:   Segítség\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Főmenü\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Térkép\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Szóköz: Minden ablak elrejtése\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Gyors igék\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Varázsige könyv\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Eszköztár megnézése\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Szereplő megnézése\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Küldetések megnézése\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: fényerő csökkentése\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: fényerő növelése\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: játék nagyítása\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ /-: térkép nagyítása\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: övön található tárgyak\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     gyorsbillentyűk varázsigékhez\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + bal kattintás: támadás mozgás nélkül\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"Shift + bal kattintás (szintlépésnél): összes pont allokálása\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + bal kattintás (eszköztárban): tárgy mozgatása az övre vagy felvétele \"\n\"magunkra\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\"Shift + bal kattintás (az övön): tárgyak mozgatása vissza az eszköztárba\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Mozgás:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Ha nyomva tartod a bal egérgombot mozgás közben, a hősöd továbbra is abba az \"\n\"irányba fog mozogni.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Harc:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"A shift gomb letartása kattintás közben lehetővé teszi, hogy egy helyben \"\n\"támadj.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Térkép:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"A térkép eléréséhez nyomd be a 'TÉRKÉP' gombot lent vagy a 'TAB' gombot a \"\n\"billentyűzeten. A nagyítás + és - gombokkal lehetséges, a mozgatás pedig a \"\n\"nyilakkal.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Tárgyak felvétele:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"A kis felhasználható tárgyak, mint a fiolák és tekercsek az övedbe kerülnek \"\n\"a felület tetején. Az ott tárolt tárgyak mellett kis számok találhatóak, \"\n\"amelyekkel jobb kattintás mellett is tudod használni őket.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Arany:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Kiválaszthatsz bizonyos mennyiségű aranyat eldobásra jobb kattintással az \"\n\"eszköztáradban.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Készségek és varázsigék:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Hozzáférhetsz az elérhető készségekhez és varázsigékhez bal kattintással az \"\n\"'IGÉK' gombra kattintva a kezelő felületen. A megtanult varázsigék és a \"\n\"boton találhatóak itt lesznek felsorolva. Bal kattintással kiválasztod a \"\n\"varázsigék. A kiválasztott igét a jobb kattintással tudod előhívni.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Gyorsvarázs:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Egy bal kattintás a kiválasztott varázsigére kinyitja a varázsigék \"\n\"gyorstárát, ahol azonnal választhatsz a varázsigék, készségek, tekercsek és \"\n\"a bot képessége közül. A kiválasztás után a használathoz nyomd meg a jobb \"\n\"egérgombot a játéktéren.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + bal kattintás a jelenleg kiválasztott varázsigére törli azt abból a \"\n\"helyből.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Varázsigékhez gyorsbillentyűk:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Gyorsbillentyűket rendelhetsz varázsigékhez,készségekhez és tekercsekhez. \"\n\"Kezdd a varázsigék gyorstárának kinyitásával a fent leírt szakasz alapján. \"\n\"Ezt követően nyomd be az F5, F6, F7 vagy F8 gombok egyikét a kiválasztott \"\n\"varázsige felett, hogy a gombhoz rendeld azt.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Varázskönyvek:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Egynél több könyv elolvasása növeli az adott varázsigéről szerzett \"\n\"ismeretedet, amitől még hatékonyabban tudod előígézni azt.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Segítség a kiegészítő próbaváltozatjához\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Segítség a kiegészítőhöz\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Segítség a próbaváltozathoz\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Segítség az alapjátékhoz\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"A nyilakkal mozogsz és az ECS gombbal lépsz vissza.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Nem sikerült az elsődleges ablak létrehozása\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Nincs hely a tárgynak\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"A pontosság olaja\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"A tehetség olaja\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Az élesség olaja\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"A halál olaja\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"A készség olaja\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Kézműves olaj\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Az erő olaja\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"A kitartás olaja\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Az edzettség olaja\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Az állhatatosság olaja\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"A {1} {0}ja\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"A {2} {0} {1}ja\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{2} {0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{1} {0}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"növeli a fegyver\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"találati esélyét\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"nagyban növeli\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"a fegyver találati esélyét\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"a sebzési lehetőségét\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"nagyban növeli egy fegyver\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"- kivétel az íjak - sebzési lehetőségét\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"kevesebb képesség szükséges hozzá\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"hogy tárgyakat használhass\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"visszaállítja 20 százalékát\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"egy tárgy állapotának\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"javítja egy tárgy\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"állapotát és szívósságát\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"elpusztíthatatlanná tesz egy tárgyat\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"növeli a hatékonyságát\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"a pajzsoknak és páncéloknak\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"nagyban növeli a hatékonyságát\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"a pajzsoknak és páncéloknak\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"felállít egy tűzcsapdát\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"felállít egy villámcsapdát\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"felállít egy Medúza csapdát\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"visszatölt minden életerőt\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"visszatölt némi életerőt\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"visszatölt némi varázserőt\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"visszatölt minden varázserőt\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"növeli az erőt\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"növeli a mágiát\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"növeli az ügyességet\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"növeli az egészséget\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"ad némi élet- és varázserőt\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"teleölti az élet- és varázserőt\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(csak arénákban működik)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Jobb kattintással megnézed\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Jobb kattintással használod\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Jobb kattintással elolvasod,\\n\"\n\"majd ballal kiválasztod a célt\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Jobb kattintással elolvasod\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Kattints rá, hogy megnézd\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Nyisd ki az eszköztárad a használat előtt\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Kattins rá a használathoz\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Válassz a varázsigék könyvéből\\n\"\n\"majd olvasd fel az igét\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Kattints rá, hogy elolvasd\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{}, hogy megnézd\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{}, hogy használd\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Válassz a varázsigék könyvéből\\n\"\n\"majd {} segítségével olvasd fel az igét\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{}, hogy elolvasd\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Szint: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Dupla arany fér egy mezőbe\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Szükséges:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Erő\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mág\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Ügy\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Könyv - {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s} levágott füle\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"találat esélye: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% sebzés\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"találat esélye: {:+d}%, {:+d}% sebzés\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% páncélzat\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"páncélzat: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Tűz ellenállás: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Tűz ellenállás: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Villám ellenállás: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Villám ellenállás: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Bűbűj ellenállás: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Bűbűj ellenállás: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Minden ellenállás: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Minden ellenállás: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"a varázsigék {:d} szinttel jobbak\"\nmsgstr[1] \"a varázsigék {:d} szinttel jobbak\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"a varázsigék {:d} szinttel rosszabbak\"\nmsgstr[1] \"a varázsigék {:d} szinttel rosszabbak\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"a varázsigék változatlanok\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Plusz töltések\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} töltés\"\nmsgstr[1] \"{:d} {:s} töltés\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Tűzsebzés: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Tűzsebzés: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Villámsebzés: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Villámsebzés: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} pont az erősséghez\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} pont a mágiához\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} pont az ügyességhez\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} pont az egészséghez\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} pont minden tulajdonsághoz\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} sérülés az ellenfelektől\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Életerő: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Varázserő: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"különösen szívós\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"kimondottan törékeny\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"megsemmisíthetetlen\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% fényerő\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% fényerő\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"több nyíl lövésenként\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"tüzes nyíl sebzése: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"tüzes nyíl sebzése: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"villámló nyíl sebzése: {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"villámló nyíl sebzése: {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"tűzbomba sebzése: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"tűzbomba sebzése: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"a támadó 1-3 sérülést szenved el\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"a felhasználó elveszíti az összes varázserejét\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"a kelepcék fele annyit sebeznek\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"visszalöki a célpontot\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"háromszoros sebzés démonok ellen\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Minden ellenállás nullázódik\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"egy találat 3% varázserőt lop\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"egy találat 5% varázserőt lop\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"egy találat 3% életerőt lop\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"egy találat 5% életerőt lop\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"áttöri a célpont páncélját\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"gyors támadás\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"pörgős támadás\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"nagyon gyors támadás\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"villámgyors támadás\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Más képesség (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"gyors visszaállás\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"gyorsabb visszaállás\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"leggyorsabb visszaállás\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"gyors védekezés\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"további {:d} sebzés\"\nmsgstr[1] \"további {:d} sebzés\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"váltakozó sebességű nyílak\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"szokatlan sebzés\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"szokatlan szívósság\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"egykezes kard\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"folyamatosan életerőt veszítesz\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"életerő rabló\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"nem szükséges hozzá erő\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"villámsebzés: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"villámsebzés: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"gömbvillámok keletkeznek találat után\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"néha háromszorosat sebez\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"csökkenő {:+d}% sebzés\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"kétszeres sebzés a célpontra, egyszeres neked\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Véletlen sebzés 0 és 600% között\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"törékeny, de {:+d}% sebzés\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"plusz páncélzat démonok ellen\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"plusz páncélzat élőhalottak ellen\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"a varázserő 50%-a életerővé válik\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"az életserő 40%-a varázserővé válik\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"sebzés: {:d}  megsemmisíthetetlen\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"sebzés: {:d}  állapot: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"sebzés: {:d}-{:d}  megsemmisíthetetlen\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"sebzés: {:d}-{:d}  állapot: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"páncélzat: {:d}  megsemmisíthetetlen\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"páncélzat: {:d}  állapot: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Töltések: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"különleges tárgy\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Azonosítatlan\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"A Csontváz Király Nyugvóhelye\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"A Koponya Kamra\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labirintus\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Mérgezett Kút\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Lázár főérsek Lakhelye\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Katedrális aréna\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Pokol aréna\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Az élet köre aréna\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Le a tömlöcbe\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Le a sírkamrába\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Le a barlangba\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Le a pokolba\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Le a fészekbe\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Le a kriptába\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Fel a {:d}. szintre\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Fel a városba\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Le a {:d}. szintre\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Le Diablóhoz\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Fel a fészek {:d}. szintjére\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Fel a kripta {:d}. szintjére\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"A világ sarkköve\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Le a kripta {:d}. szintjére\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Vissza a {:d}. szintre\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Nem sikerült a mentés megnyitása\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Érvénytelen mentés\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"A játékos egy kiegészítős szinten található\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Érvénytelen mentés\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Nem sikerült a főmenü kirajzolása\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Állat\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Démon\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Élőhalott\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Típus: {:s} Ölések: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Ölések: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Életerő: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Nincs mágikus ellenállás\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Ellenáll:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" bűbáj\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" tűz\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" villám\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Immunis:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Típus: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Nincs ellenállás\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Nincs immunitás\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Pár mágikus ellenállás\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Pár mágikus immunitás\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Nem sikerült megnyitni a fájlt írásara.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} tiltott átkot használt.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} tiltott átkot használt.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"'{:s}' ({:d}. szint) csatlakozott a játszmába\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"A játék véget ért\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Nem sikerült a szint adatának kiolvasása\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"'{:s}' elhagyta a játékot\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"'{:s}' megölte Diablót, majd elhagyta a játékot!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"'{:s}' időkorlát túllépése miatt kilépett\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"'{:s}' ({:d}. szint) már játékban van\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Titokzatos\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Rejtett\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Borús\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Szokatlan\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Mágikus\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Kő\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Vallásos\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Megbűvölt\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Csodatevő\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Lenyűgöző\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Rejtélyes\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Természetfeletti\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Vészjósló\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Isteni\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Mennyei\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Patinás\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Spirituális\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Ijesztő\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Elhagyatott\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Nyomasztó\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Halk\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Elszigelt\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Díszes\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Tündöklő\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Beszennyezett\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Olajos\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Ragyogó\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Kolduló\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Csillámló\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Fénylő\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Nap\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Murphy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"A nagy küzdelem\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"A bűn fizetsége a háború\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Horadrim története\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"A sötét száműzetés\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"A bűn háborúja\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"A hármak szövetsége\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Messzi vidékek\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"A hármak története\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"A fekete király\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Napló: a megbűvölés\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Napló: a találkozó\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Napló: a dühöngés\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Napló: a hatalma nő\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Napló: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Napló: a vég\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Varázskönyv\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Megfeszített csontváz\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Kar\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Nyitott ajtó\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Csukott ajtó\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Eltorlaszolt ajtó\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Ősi állvány\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"A romlottság könyve\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Koponya kar\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Mitikus Könyv\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Ládikó\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Láda\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Kincsesláda\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sírhely\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Könyvesszekrény\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Könyvespolc\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Hordó\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Báb\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} szentély\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Csont állvány\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Könyvtári könyv\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Vérkút\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Lefejezett holttest\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"A vakok könyve\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"A vér könyve\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Tisztító forrás\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Páncél\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Fegyvertároló\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Kecske Kút\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Üst\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Fátyolos víz\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Könnyek kútja\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Acéltartó\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"A vér piedesztája\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Gombák\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Vészjósló állvány\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Legyilkolt hős\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"Kelepcével ellátott {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (kikapcsolva)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"BE\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"KI\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Játékváltozat\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Játékmenet beállításai\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Szabadon játszhatsz az alapjátékkal vagy a kiegészítővel.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Csak a próbaváltozat\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Kompatibilissá teszi a játékot a próbaváltozattal, így azokkal is \"\n\"játszhatsz, akiknek nincs meg a Diabló teljes változata.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Indítás\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Indítás beállításai\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Bevezető mutatása\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Megmutatja az bevezető filmet induláskor.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Indítókép\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Miket mutathat induláskor.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Gyártó és indítókép\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Csak az indítókép\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Alapjátékkal kapcsolatos beállítások\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"A kiegészítővel kapcsolatos beállítások\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Hang\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Hangbeállítások\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Séta hangja\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"A játékos lépés hangokat ad ki amikor sétál.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Gyors felvétel hangja\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Az automatikusan felvett tárgyak mellé társul hang.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Tárgyak felvételének a hangja\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"A tárgyak felvétele egy hangot játszik le.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Mintavételi frekvencia\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"A kimeneti hang mintavételi frekvenciája Hz-ben.\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Sávok\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Kimeneti hangsávok száma.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Puffer méret\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"A puffer mérete (képek száma csatornánként).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Átalakítás minősége\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Az alakítás minősége, ahol 0 a legalacsonyabb és 10 a legmagasabb.\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"A játék belső felbontása, ami a látható kép méretét is meghatározza. Ez \"\n\"eltérhet a monitor felbontásától, ha a 'Felfújás', 'Pontos Felfújás' és a \"\n\"'Képernyőre Illesztés' beállításokat használjuk.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Átalakító\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Hang átalakító\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Készülék\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Hangkészülék\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafika\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Grafikai beállítások\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Teljes képernyő\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"\"\n\"Választhatunk, hogy teljes képernyőn szeretnénk-e játszani vagy ablakozott \"\n\"üzemmódban.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Képernyőre Illesztés\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Automatikusan úgy igazítja a játék ablakát, hogy a képernyő méreteinek \"\n\"megfeleljen.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Felfújás\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Lehetővé teszi, hogy a játék át legyen méretezve a képernyő felbontásunknak \"\n\"megfelelően. Többé már nem tudjuk a képernyő felbontást állítani, de az \"\n\"ablakot továbbra is újraméretezhetjük ablakos üzemmódban.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Felfújás minősége\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Választhatunk több lehetőség közül, hogy meghatározzuk a felfújás kívánt \"\n\"minőségét.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Legközelebbi\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilineáris\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anizotróp\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Pontos Felfújás\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"A képernyő felbontása az átméretezés során egész számokat fog követni.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Függőleges szinkronizáció\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Nagyít, ha be van kapcsolva.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" villám\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Színforgás\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Színforgató hatás víznél, lávánál és savnál.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternatív fészek paletta\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"Más paletta használata a kiegészítős fészek szinteken.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Hardware Kurzor\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Hardware kurzor használata\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Hardware Kurzor tárgyaknál\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Hardware-es kurzor használata tárgyaknál.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Hardware kurzor max mérete\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Hardware-es kurzor maximális mérete. A nagyobbak szoftveressé állnak vissza.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Képráta mutatása\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Mutatja az aktuális képrátát a képernyő bal felső sarkában.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Játékmenet\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Játékmenet beállításai\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Bekapcsolja a gyorsított gyaloglást a városban. Ez a beállítás még a \"\n\"kiegészítőből származik.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Egér megfogása\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Az egeret a játék ablakán belül tartja.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Bekapcsolja a kislány küldetését.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Bekapcsolja a tehenes küldetést. Leszter a gazda helyettesítve lesz Golyós \"\n\"Gáspárral.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Baráti tűz\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Engedélyezi, hogy a nyilak, varázsigék megsebezzék a többi játékost is \"\n\"minden esetben.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Teljes küldetések többj. módban\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\"A teljes egyjátékos küldetések többjátékos módban is elérhetőek lesznek.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Bárd osztály\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Engedélyezi a bárd osztály kiválasztását.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Barbár osztály\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Engedélyezi a barbár osztály kiválasztását.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Tapasztalat csík\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Egy tapasztalat csík lesz a képernyő aljához adva.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Tárgyak kirajzolása az üzletben\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"Kirajzolja a tárgyakat a leírás mellett balra az üzletekben.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Életerő szám mutatása\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Mutatja az aktuális életerőt számszerűen is a bal, piros gömbön.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Varázserő szám mutatása\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Mutatja az aktuális varázserőt számszerűen is a jobb, kék gömbön.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Saját hős\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Ellenséges életcsík\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Kirajzol a képernyő tetején egy ellenséges életcsíkot.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Az arany magától össze lesz gyűjtve, ha közel van hozzá a játékos.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Az csodaszerek maguktól össze lesznek gyűjtve, ha közel van hozzájuk a \"\n\"játékos.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Az olajok maguktól össze lesznek gyűjtve, ha közel van hozzájuk a játékos.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Automatikusan felveszel minden tárgyat a városban\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"\"\n\"Adria Pipinhez hasonlóan újratölti a varázserődet, amikor meglátogatod a \"\n\"viskóját.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"A fegyvereket felvételkor vagy vásárláskor automatikusan magunkhoz vesszük.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"A páncél felvételkor vagy vásárláskor automatikusan magunkhoz vesszük.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"A sisakokat felvételkor vagy vásárláskor automatikusan magunkhoz vesszük.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"A pajzsokat felvételkor vagy vásárláskor automatikusan magunkhoz vesszük.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Az ékszereket felvételkor vagy vásárláskor automatikusan magunkhoz vesszük.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"\"\n\"Véletlenszerűen változik, hogy milyen küldetések lesznek új játékoknál.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Szörnyek típusának a mutatása\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"Megmutatja a leírásnál, hogy milyen típusú a kiválasztott szörny.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Mutatja a címkéjét a földön található tárgyaknak.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Automatikusan fel lesz töltve az öv az eszköztárunkból a tárgyak használata \"\n\"után.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Bekapcsolás esetén az üstök, kecske kutak, valamint bizonyos szentélyek \"\n\"(díszes, lenyűgöző, patinás, Murphy) ki lesznek kapcsolva.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Gyors varázslás\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"A gyorsbillentyű benyomása egyből meg is hívja a kiválasztott igét \"\n\"készenlétbe helyezés helyett.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Legfeljebb ennyi gyógyító fiolát fogunk felvenni automatikusan.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Legfeljebb ennyi nagy gyógyító fiolát fogunk felvenni automatikusan.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Legfeljebb ennyi varázs fiolát fogunk felvenni automatikusan.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Legfeljebb ennyi nagy varázs fiolát fogunk felvenni automatikusan.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Legfeljebb ennyi megújulás fioláját fogunk felvenni automatikusan.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Legfeljebb ennyi teljes megújulás fioláját fogunk felvenni automatikusan.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Lebegő számok bekapcsolása\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\"Engedélyezi a lebegő számokat a képernyőn sebzés, tapasztalatszerzés és \"\n\"egyéb dolgok esetén.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Kikapcsolva\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Véletlen szögekbe\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Csak vízszintesen\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Gamepad\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Gamepad beállítások\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Hálózat\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Hálózati beállítások\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Csevegés\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Csevegés beállításai\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Nyelv\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Válaszd ki a kívánt nyelvet.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Nyelvi beállítások\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Billentyűzet\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Billentyűzet beállítások\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Gamepad\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Gamepad gombok beállítása\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Beállítások\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Szint\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Tapasztalat\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Következő szint\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Alap\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Most\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Erősség\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Mágia\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Ügyesség\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Egészség\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"További pontok\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Arany\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Páncél\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"találati esélyét\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Sebzés\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Életerő\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Varázserő\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Bűbáj ellenállás\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Tűz ellenállás\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Villám ellenállás\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"hős\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"küldetés\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"térkép\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menü\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"eszköz\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"mágia\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"hang\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"némít\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Használhatatlan\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Seb: életerő 1/3-a\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Gyógyít: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Sebzés: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Készség\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Pálca ({:d} töltés)\"\nmsgstr[1] \"Pálca ({:d} töltés)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Szint: {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Varázs: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Ige\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Csak élőhalottak ellen\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Tekercs\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Bot\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Varázsige billentyű: {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Nem sikerült megnyitni a fájlt\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Nem sikerült betölteni a hőst\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} ({:d}. szint): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Üzenetek ({:d} darab)\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} arany\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Mennyi aranyat szeretnél kivenni?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Szint: {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Tapasztalat: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Legmagasabb szint\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Következő: {:s} pont\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"Még {:s} pont a {:d}. szintig\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Leorik király nyugvóhelye\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"A Koponya Kamra\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Egy sötét járat\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"A beszennyezett oltár\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"{:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Segítség! Jöjjön valaki!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Kövess.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Van nálam valami.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Most MEGHALSZ!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Gyógyítsd meg magad!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Vigyázz!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Köszönöm.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Visszavonulás!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Sajnálom.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Itt várok.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pipin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Káin\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Júlia\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Vissza\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Sebzés: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Páncél: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Áll: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"megsemmisíthetetlen\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Isten hozott a\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Kovácsműhelyben!\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Szeretnél:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Beszélni Griswolddal\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Egyszerű tárgyakat venni\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Különleges tárgyakat venni\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Tárgyakat eladni\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Tárgyakat javítani\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Távozni a műhelyből\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Ezeket adom el:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Ezeket adom el:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Nincs semmid ami érdekelne.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Miket szeretnél eladni?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Nincs amit meg tudnék javítani.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Mit szeretnél megjavíttatni?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"A boszorkány viskója\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Beszélni Adriával\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Tárgyakat vásárolni\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Pálcákat újratölteni\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Távozni a viskóból\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Nincs amit újra tudnék tölteni.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Melyik pálcákat óhajtod újratölteni?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Nincs elég arany\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Nincs nálad elég hely\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Áll az alku?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Biztosan beazonosítsam ezt a tárgyat?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Biztosan megveszed ezt a tárgyat?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Biztosan újratöltsem ezt a tárgyat?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Biztosan eladod ezt a tárgyat?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Biztosan megjavítod ezt a tárgyat?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Féllábú Wirt\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Beszélgetni \"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Kincsem neked itt áll várva,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"de ötven arany lesz az ára,\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"hogy lássad mi a szíved vágya. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Szeretném megnézni\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Elköszönni\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Ez van, csak neked:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Vissza\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"a gyógyító házában!\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Beszélni Pipinnel\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Távozni a gyógyítótól\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"A Rangidős\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Beszélni Káinnal\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Azonosítani egy tárgyat\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Nincs mit azonosítanom.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Melyik tárgyat óhajtja azonosítani?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Ez a tárgy:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Kész\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"{:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Beszél vele: {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"nem elérhető a\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"próbaváltozatban!\"\n\n# Direkt üres\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \" \"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Pletykák\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"a Szürkület Fogadóban!\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Beszélni Ogdennel\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Távozni a fogadóból\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Beszélni Júliával\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Megnézni a tárhelyem\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnham az Iszákos\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Beszélni Farnhammel\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Elköszönni\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Rendelkezésre áll: {:s} arany\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Elhunyt férfi\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Griswold a Kovács\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pipin a Gyógyító\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Szenvedő férfi\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden a Kocsmáros\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Káin a Rangidős\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Adria a Boszorkány\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Júlia a Csaposlány\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Tehén\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Leszter a Gazda\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Cecília\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Marha Marci\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Harcos\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Zsivány\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Mágus\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Szerzetes\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bárd\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbár\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Hullarabló\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Oszló Tetem\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Pestis\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Bukott\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Vájó\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Ördögfi\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Elfeketült\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Csontváz\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Fejszés Tetem\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Égőhalott\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Rettenet\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Guberáló\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Járványevő\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Árnylény\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Csontrágó\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Íjász Tetem\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Csontváz Tizedes\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Tetem Őrmester\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Égőhalott Kapitány\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Rettenet Hadnagy\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Láthatatlan Úr\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Rejtett\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Üldöző\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Láthatatlan\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Bűvölő\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Szatír Nagyúr\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Hús‑vér népség\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Szikla népség\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Láng népség\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Hold népség\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Denevér\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Pislantás\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Ború\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Házi szellem\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Savokádó\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Méregköpő\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"A mélység fenevada\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Lávaszáj\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"A Csont Király\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"A Mészáros\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Démon nagyúr\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Sárember\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Varangydémon\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Megnyúzott\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Sárkány\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Barlangi Csiga\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Ördög Sárkány\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Csócsáló\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Magma Démon\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Vérkő\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Pokol Köve\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Láva Nagyúr\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Bika Démon\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Sárfutó\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Jégrepesztő\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obszidián Nagyúr\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"ócsont\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Vörös halál\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Feltámasztott démon\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Élőhalott ősdémon\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Lánggyújtó\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Lángok úra\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"A végzet tűze\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"A pokol lángőrzője\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Vörösvihar\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Viharlovas\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Vihar Nagyúr\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Örvényfia\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Érett ördögfi\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Szárnyas démon\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Vízköpő\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Vérkarom\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Halálszárny\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Démonszárny\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Őrszem\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Mélységek Úra\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Ősdémon\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Barlangi vipera\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Tűzsárkány\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Aranyvipera\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Azúr sárkány\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Fekete Lovag\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"A végzet őrzője\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Acél nagyúr\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Vérlovag\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Széttépett\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Üreges\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"A féjdalom úra\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Valóságszövő\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Szukkubusz\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Hóboszorkány\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Pokolszülött\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Lélekégető\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Tanácsadó\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Magisztrátus\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Szektatag\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Szektahívő\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Gólem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"A Sötét Nagyúr\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Malignusz\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad a gyenge\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar az őrült\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Takonyfoly\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Lázár főérsek\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Vörös Átok\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Fekete Jáde\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanán\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"A vér fejedelme\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Pattanásfej\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"A Megbecstelenítő\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Csontfej vígfejsze\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Pengebőrű a gyilkos\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Lélekcsáp\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Patkányhányás a piszkos\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Csonttépő\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Penészlakoma az éhes\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Gyomorszúró a gyors\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Pajzsdöngető a törött fejű\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongó\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Penészvérengzés\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Árnyékharapás\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Holtszem\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Az elhunyt rémszemű\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"A Chupacabra\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Koponyatűz\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Torzkoponya\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Vérnyelv\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Szívverés vadász\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Holdhajlító\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"A harag hollója\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Gerincevő\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"A lángoló fekete hamu\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Árnyékholló\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Pusztulatkő a gyenge\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Habhányás a Állatidomár\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Vérbőrű Sötétíj\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Romlottszárny\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Árnyivó\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Hőmozgató\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Halálköpés\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Vérhörgés\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Húspöröly Vészárnyék\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Harcféreg az őrült\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Üvegkoponya a kihegyezett fejű\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Pusztulattűz\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"A hűvös Éjjeliszárny\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Vérkő\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Bronzöklű Tűzkő\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Bosszútűz a megátkozott\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Zord Tűzseb\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Szennybáró\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Vészszarvú Acélbuzogány\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Káoszvonyító\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"A rothadó halálvigyor\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Őrültkályha\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"A reszelt csontú gróf\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Gerinctörés\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Hegyes csontú ördögkoponya\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Töröttvihar\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Viharvész\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Guminyál\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"A lángoló aranyvész\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Feketevihar\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Játványbosszú\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"A nyúzógép\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Kékszarv\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Pokol-szülte Pusztítótűz\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Méregfogú kérkedő\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Feslett koponya\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Meggörbült Oroszlánkoponya\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Feketenyelv\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Bűnös érintés\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Viperaláng\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Méregfogbőr\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Boszorkánytűz a száműzött\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Feketekoponya\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Lélekvágó\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Szélszülött\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"A mélység Atyja\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Rozsdaszabó\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Árnyéküvöltés\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Végzetfelhő\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Vérhold Lelke\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Boszorkányhold\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Vérlakoma\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"A gyilkos Szürkehalál\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Ítéletbíró\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Csillagszemű Boszorka\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Acélkoponya a vadölő\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Lord Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"A Vezér\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamfír\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Vérszomj\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Pókhálók Hitvese\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Vértáncos\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Zordpenge\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Halálzár\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Rövid kard\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Könnyű kőrpajzs\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Deszkalap\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Rövid íj\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Varázspálca\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Bárd\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Az élőhalottak koronája\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Empireumi gyűrű\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Varázskő\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"A fény amulettje\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Az igazság gyűrűje\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"A fogadó táblája\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Bohócsipka\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Az acél fátyla\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Az arany varázsital\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"A harag üllője\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Fekete gomba\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Agy\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Gombás tekercs\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"A színek varázsfőzete\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Vérkő\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"A katedrális térképe\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Gyógyító fiola\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Varázs fiola\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"A beazonosítás tekercse\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"A varázskapu tekercse\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Arkaine Vírtusa\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Nagy gyógyító fiola\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Nagy varázs fiola\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Griswold pengéje\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Tőgy tunika\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Lázár varázsbotja\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"A feltámasztás tekercse\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Pálca\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Kard\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Tőr\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Csodabomba\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Tivadar\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Arany Nyaklánc\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Széttépett papír első darabja\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Széttépett papír második darabja\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Széttépett papír harmadik darabja\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Összeragasztott papír\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Barna Ruha\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Szürke Ruha\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Fejfedő\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Kalap\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Sisak\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Lovagi sisak\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Korona\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Légiós sisak\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Palást\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Rongy\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Kabát\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Habitus\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Steppelt mellény\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Bőr mellény\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Bőr páncél\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Kitömött bőr páncél\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Gyűrűzött páncél\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Lemezes mellény\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Páncéling\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Lemezes páncél\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Mellény\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Mellvért\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Szamuráj páncél\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Nemesi mellény\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Nemesi páncél\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gótikus páncél\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Nemesi díszpáncél\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Pajzs\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Nehéz kőrpajzs\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Könnyű lovagi pajzs\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Nehéz lovagi pajzs\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Légiós pajzs\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gótikus pajzs\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"A megújulás fiolája\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"A teljes megújulás fiolája\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Olaj\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Az erő csodaszere\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"A mágia csodaszere\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Az ügyesség csodaszere\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Az egészség csodaszere\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"A gyógyítás tekercse\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"A keresés tekercse\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"A mennydörgés tekercse\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"A tűzfal tekercse\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"A láncsóva tekercse\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"A villanás tekercse\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"A hőlátás tekercse\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"A kámfor tekercse\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"A csodapajzs tekercse\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"A tűzhullám tekercse\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"A tűzbomba tekercse\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"A Medúza tekercse\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"A sorvillám tekercse\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"A Hidra tekercse\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"A nóva tekercse\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"A Gólem tekercse\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"A teleportáció tekercse\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"A végzet tekercse\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Falchion\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Handzsár\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Claidheamh-mór\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Penge\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Szabja\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Hosszúkard\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Pallos\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Fattyúkard\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Kétkezes kard\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Szamuráj kard\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Szekerce\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Balta\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Kétélű balta\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Fejsze\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Bárd\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Csatabárd\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Buzogány\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Morgenstern\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Martel\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Kalapács\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Bunkósbot\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Láncos buzogány\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Pöröly\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Íj\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Vadász íj\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Hosszú íj\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Összetett íj\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Harci íj\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Harci hosszú íj\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Háborús íj\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Háborús hosszú íj\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Rúd\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Összetett rúd\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Szálfa\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Alabárd\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Gyűrű\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Nyaklánc\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Tűzcsapda\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Csapda\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Villámcsapda\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Pokolcsapda\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Viharcsapda\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Medúza csapda\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"A gömbvillám pálcája\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Aréna fiola\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"A Mészáros Pengéje\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Fénykard\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"A szakadás íja\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"A szögbelövő\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"A fellegek íja\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Halálos vadász\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"A holtak íja\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Feketetölgy íj\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Lángdárda\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Hússzúró\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Szélerő\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Sasszarv\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Gonnagal tőrje\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"A védelmező\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Griffkarom\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Fekete borotva\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Domború hold\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Jégszurony\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"A hóhér pengéje\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"A csontfűrész\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Árnysólyom\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Varázslótüske\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Fénykard\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Sólyom talon\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Lángcsóva\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Halálhozó\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"A barnamedve\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"A Nagyapa\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"A csonkoló\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Élescsőr\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Vérvadász\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"A fellegek fejszéje\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Eszeveszett Fejsze\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Kőbárd\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Aguinara szekercéje\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Pokolgyilkos\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Messerschmidt bárdja\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Rozsdarepedés\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Jholm pörölye\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Civerb buzogánya\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Az esthajnalcsillag\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Baranár csillagja\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Torz gyökér\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Agylebeny zúzó\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Schaefer kalapácsa\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Álomnyúzó\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Árnyakpálcája\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Lobbantó\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Viharpózna\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Fénysugárdal\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Viharhívó\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"A Védelmező\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Naj csodatevő pálcája\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Az elme sikolya\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Onán rúdja\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Szellemek sisakja\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Gondolkodó Sapka\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"A nagyúr sisakja\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"A bolond sapkája\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Az istenek alkonya\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Királyi körsisak\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Lelkek tépett húsa\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Gladiátor átka\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Tarkabarka kabát\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Aut bőre\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Bölcsesség kabátja\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Csillámló Láncing\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"A guberáló mellvértje\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Éjjeli táj\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Naj fénypáncélja\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Démontüske kabát\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Az elhárító\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Törtkoponya pajzs\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Sárkánypajzs\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Feketetölgy pajzs\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Szent Védelmező\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Viharpajzs\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Tövisgyűrű\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Regha gyűrűje\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"A véreztető\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Fojtó gyűrű\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Az elköteleződés gyűrűje\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Bádog\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Réz\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Bronz\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Vas\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Acél\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Ezüst\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platinum\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteorit\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Furcsa\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Haszontalan\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Görbe\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Gyenge\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Ordas\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Halálos\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Súlyosbított\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Veszedelmes\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Kegyetlen\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Hatalmas\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Veszett\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Kíméletlen\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Könyörtelen\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Ügyetlen\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Tompa\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Éles\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Finomított\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Gladiátor\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Úri\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Lovagi\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Keresztes\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Mesteri\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Bajnoki\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Királyi\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Sebezhető\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Rozsdás\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Erős\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Méltó\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Daliás\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Dicsőséges\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Áldott\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Megszentelt\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Lenyűgöző\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Isteni\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Vörös\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Karmazsin\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Gránát\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubint\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Kék\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Azúr\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lazúrkő\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Kobalt\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Zafír\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Fehér\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Gyöngy\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Elefántcsont\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Kristály\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Gyémánt\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topáz\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Borostyán\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Jáde\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Obszidián\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Smaragd\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Hiéna\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Béka\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Pók\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Holló\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Kígyó\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Vipera\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Unikornis\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Sárkány\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Szkülla\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hidra\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Angyali\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Arkangyali\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Bőkezű\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Bőséges\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Lángoló\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Villámló\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"minőségi\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"csonkító\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"öldöklő\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"kaszaboló\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"gyilkos\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"mészáros\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"fájdalmas\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"könnyes\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"egészséges\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"óvó\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"nyelő\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"hárító\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"szerencsehozó\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"esendő\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"gyenge\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"méretes\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"nagy\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"hatalmas\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"óriási\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"rettenetes\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"béna\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"sorvadt\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"ügyes\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"jártas\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"pontos\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"precíz\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"tökéletes\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"együgyű\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"tudatlan\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"varázs\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"elmés\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"zseniális\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"bűbájos\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"mágikus\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"beteges\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"kóros\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"élénk\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"egészséges\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"életerős\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"virilis\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"éltető\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"megátkozott\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"elkeserítő\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"égi\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"holdvilági\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"hullócsillagos\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"mennyei\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"isteni\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"keselyű\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"sakál\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"róka\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"párducmintás\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"sasszárnyú\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"farkasszülött\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tigriscsíkos\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"oroszlánszívű\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"elefántbőrű\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"bálnazsíros\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"törékeny\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"sérült\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"szívós\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"megmunkált\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"zömök\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"örök\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"sötét\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"éjszakai\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"fényes\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"sugárzó\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"forró\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"égő\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"lángoló\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"töltött\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"villámló\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"mennydörgő\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"számos\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"bőséges\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"tövis\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"romlott\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"svindler\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"medveölő\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"denevérszárnyú\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"vámpír\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"parazita\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"véres\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"szúrós\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"páncélrepesztő\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"zúzó\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"gyors\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"fürge\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"rohanó\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"vágtató\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"kemény\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"szilárd\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"nyugtató\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"őrző\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"A Varázskő\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad a gyenge\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar az őrült\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"A Mészáros\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Ogden táblája\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"A vakok csarnoka\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Vírtus\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"A vér fejedelme\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Leorik király átka\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Lázár főérsek\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Holtodiglan\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"A gazda ellensége\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Kislány\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Vándorló Kereskedő\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"A Megbecstelenítő\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Kiborult az aludttej\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Tűzgolyó\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Gyógyítás\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Mennydörgés\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Villanás\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Beazonosítás\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Tűzfal\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Varázskapu\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Medúza\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Hőlátás\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Kámfor\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Csodapajzs\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Tűzbomba\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Hidra\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Sorvillám\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Tűzhullám\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Halálkígyó\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Vérszerződés\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nóva\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Láthatatlanság\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Lángcsóva\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Gólem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Dühöngés\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleportáció\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Végzet\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Szétporlás\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Kovács\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Újratöltő\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Hatástalanító\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Tűzlény\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Gömbvillám\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Szentvillám\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Feltámasztás\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Mozgatás\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Mások gyógyítása\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Vércsillag\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Csontszellem\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" A jó királyunk története, igaz? Leorik tragikus bukása súlyos csapással \"\n\"bírt erre a vidékre. A nép mindig is szerette a királyát, de most már \"\n\"pusztán félelemmel mernek ránézni. Azt a kérdést teszem fel magamnak \"\n\"ismételten is, hogy egy olyan patinás lelkületű férfi mint Leorik király, \"\n\"hogyan kerülhetett ilyen távol a fényesség útjától? Csak a Pokol leggyarlóbb \"\n\"erői lehetnek képesek ilyen módon elpusztítani egy embert belülről...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"A falunak szüksége van az ön segítségére, jó uram! Pár hónapja Leorik király \"\n\"fiát, Albert herceget elrabolták, amire a király haragba szált és feltúrta a \"\n\"falut az eltűnt gyermekét kutatva. Minden egyes nap Leorik király egyre \"\n\"mélyebbre süllyedt az őrületbe. Ártatlan falusiakat okolt, majd végeztetett \"\n\"ki a fiú eltűnése miatt. Hajszáj híján felünk élte csak túl ezt a tébolyt...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Ahogy én mondtam, jó uram, a Király három szinttel mélyebben van eltemetve. \"\n\"Ott vár a romlott sötétségben, várva az alkalomra, hogy végleg elpusztítsa \"\n\"az életet ezen a vidéken...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"A király átka véget ért, de félek még nagyobb gonosz ólálkodik a \"\n\"közelünkben. Mégis, van remény, a ön győzelme egy csodás jel. A fény vezesse \"\n\"az útját, jó uram.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"A drága fiának az elvesztése túl sok volt Leorik király számára. Megtettem \"\n\"amit csak tudtam az őrülete ellen, de a végén még az is túl kevés volt. Egy \"\n\"sötét átok trónolt a királyságon attól a naptól kezdve, de talán ha \"\n\"sikerülne kiszabadítania a lelkét a földi rabságból, akkor az átok is vele \"\n\"együtt tovább szállna...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Nem is szeretnék arra gondolni, hogy milyen módon veszett oda a király. Úgy \"\n\"akarok emlékezni rá, mint egy jólelkű, igazságos uralkodó, aki mindig is \"\n\"volt. A halála csak olyan szomorúnak és helytelennek tűnt.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Sok-sok fegyvert és a legtöbb páncélt is a király lovagjainak én magam \"\n\"gyártottam, tudod-e? Csináltam még őfelségének személyesen is egy hatalmas \"\n\"kétkezes bestiát, együtt egy hozzátársuló koronával a harctérre. Nem is \"\n\"hiszem el, hogy így halt meg. Bizonyára valami alantas erő munkálkodhatott a \"\n\"tébolyának kialakulásában.\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Engem ne érdekeljen már az. Figyelj, egy csontváz nem lesz az ÉN királyom, \"\n\"tudod, nem lesz. Leorik az én királyom. Hallod? ÉLJEN A KIRÁLY!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Holtak járnak az élők között a megátkozott királyuk nyomában. Az ő \"\n\"birtokában van a hatalom, hogy még több harcost toborozzon az élőhalottak \"\n\"egyre csak növekvő seregébe. Ha nem vetsz véget az uralmának, el fogja \"\n\"pusztítani ezt a vidéket.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Nézd, én itt éppen üzletelek. Nem adok el információt és nem érdekel engem \"\n\"valami király aki már akkor is halott volt, amikor én még nem is éltem. Ha \"\n\"viszont kell valami eszköz e király ellen, talán éppen segíthetek...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Az élet melegsége járja át a sírhelyem. Készülj, halandó, mert a sötétséget \"\n\"fogod szolgálni az idők végezetéig!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Úgy látom ön is furcsállja ezt a fura viselkedést. Mivel sok démon fél a nap \"\n\"fényétől és úgy vélik hatalmas erővel bír, lehet, hogy a táblán található \"\n\"jelölés miatt vélték úgy, hogy az valami varázserővel rendelkezhet. Lehet \"\n\"nem is olyan eszesek, mint gondoltuk volna...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Uram, egy furcsa módon tudok ezzel azonosulni. Tisztában vagyok a hatalmas \"\n\"ismeretével azokról a rémségekről ott lent, de valami nekem sehogy sem fér a \"\n\"fejembe... egyik este felriadtam egy reszelő hangra a fogadóm előtt. \"\n\"Kinéztem a hálószobámból és azt hiszem kicsi démonokat láttam az udvaron. \"\n\"Egy kis idő múlva elmentek együtt a fogadóm táblájával. Nem tudom miért \"\n\"vinnék el éppen a táblát, de hagynának minket nyugodtan békében. Furcsaság, \"\n\"nem?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Jaj, nem is kellett volna visszahoznia a táblámat, de bizony ez segít neked \"\n\"egy kicsit a költségekkel. Nos, hadd lássam, mit adhatok ezért a \"\n\"szívességért cserébe? Nézzük... lenne nálam valami, igen. Ezt a sapkát egy \"\n\"mágus hagyta az egyik szobában még egy kicsit régebben. Talán a hasznára \"\n\"válna.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Te jó ég, démonok szaladgálnak az éjszaka és fosztogatják az otthonainkat?! \"\n\"Semmi sem szent már? Remélem Ogden és a felesége Gárda jól vannak. \"\n\"Feltételezem jöttek volna, ha baj történt volna...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Te jóságos! Tényleg odakerült a tábla? A nagyanyám és én biztos átaludtuk az \"\n\"egészet. Hála a Fénynek, hogy azok a rémségek nem jöttek a fogadó közelébe.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Démonok ellopták Ogden tábláját? Erről lenne szó? Nem hangzik olyan nagy \"\n\"gaztettnek, mint amikhez én vagyok szokva, tudod...\\n\"\n\"\\n\"\n\"Inkább jobban el vannak foglalva azzal, hogy megegyék a szívedet egy kis \"\n\"vandálkodás helyett.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Tudja mit gondolok? Aki elvitte a táblát, sok pénzt akar vele csinálni. Ha \"\n\"én lennék Ogden... nem én vagyok... de ha én lennék... vennék egy újat \"\n\"valami szép képpel rajta. Talán egy korsó ital vagy egy darab sajt...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Egy halandó sem értheti meg egy démon gondolkodását\\n\"\n\"\\n\"\n\"Sose hagyd, hogy a kiszámíthatatlan viselkedésük összezavarjon, mert lehet, \"\n\"hogy ez is a tervük része.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Mi, ezzel arra utal, hogy én csináltam? Feltételezem Griswold is az oldalán \"\n\"áll.\\n\"\n\"\\n\"\n\"Nézd, én már túl vagyok puszta tábla lopkodáson. Nem lehet túl nagy hasznot \"\n\"húzni egy darab korhadt deszkával.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hé, hé - te aki megölni mind! Te hozni nekem varázs zászló, ha nem, mi \"\n\"támadni! Te nem menni el élet! Te megölni nagy csúnyák és adni vissza mágia. \"\n\"Menni sarkon túl és ajtó, találni csúnyák. Te adni, te menni!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Te öl csúnyák, hozni zászló. Te hozni nekem. Vagy különben...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"Te adni. Igen, jó. Menj, mi erős. Mi ölni mind nagy mágia!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Ez bizony baljós jel és igazolja a legmélyebb félelmeimet. Amíg nem voltam \"\n\"hajlandó engedni, hogy megvezessenek engem ősi regékkel, most már látom \"\n\"tagadhatatlan a tényük.\\n\"\n\"\\n\"\n\"Az én valódi nevem Dékárd Káin, a rangidős. Én vagyok az utolsó \"\n\"leszármazottja egy ősi testvériségnek, melynek a célja az időtlen gonosz \"\n\"titkainak megőrzése volt, a gonosznak, mely most most kiszabadult...\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Siessen, mentse meg Albert herceget Lázár markaiból! A herceg és a nép \"\n\"számít magára!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"A ön története eléggé morbid, jó barátom. Lázár bizonyára a pokol kebleiben \"\n\"fog raboskodni a rémtette miatt. A szegény fiú akit leírt, szerencsére nem a \"\n\"mi hercegünk, de félek Albert még mindig veszélyben van. Az erő szimbóluma, \"\n\"amelyről beszélt, bizonyára egy kapu a labirintus legmélyebb gyomrába.\\n\"\n\"\\n\"\n\"Tudja meg ezt, barátom: a gonosz ott lent az a Sötétség Nagyura. Halandók \"\n\"számára csak az Diabló néven ismeretes. Ő volt a labirintus fogságába zárva \"\n\"századokkal ezelőtt és most félek, hogy ismét előjött, hogy pusztulást \"\n\"okozzon az emberi világban. Át kell mennei a kapun és meg kell állítania \"\n\"Diablót, míg nem túl késő!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lázár a főérsek volt mikor egy kisebb tömeget csalt le a labirintusba. Sok \"\n\"jó barátot vesztettem el aznap és Lázárt sem láttuk többé. Feltételezem \"\n\"megölték a többiekkel együtt. Ha tenne nekem egy szívességet, jó uram, \"\n\"kérem, ne beszéljem Farnhammal erről a napról.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Megrázkódtam, mikor hallottam mit tervezett a tömeg azon az éjszaka. Azt \"\n\"gondoltam, hogy az összes ember közül Lázárnak lenne több esze ennél. Ő egy \"\n\"főérsek volt, mindig törődött a falu lakóival. Annyi sérült volt, nem tudtam \"\n\"mindenkit megmenteni...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Emlékszem, Lázár egy nagy kedves és bőkezű ember volt. Beszélt az édesanyám \"\n\"temetésén és mindig sokban segítette a nagymamámat és engem is ezekben a \"\n\"bajlós időkben. Imádkozom minden éjszaka, hogy még él és biztonságban van.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Ott voltam amikor Lázár levezetett minket a labirintusba. Szent megtorlásról \"\n\"beszélt, de amikor elkezdtünk harcolni a fenevadakkal még az ujját sem \"\n\"mozdította! Csak becsalt minket a mély sötétségbe, végtelen kamrákba, tele a \"\n\"sötétség szolgáival!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Szúrnak, majd harapnak, majd körülvesznek. Hazug, hazug, HAZUG! Mind \"\n\"halottak! Halottak! Hallasz te engem? Csak mind összeesnek újra és újra... \"\n\"véres az egész terem... mind ő miatta...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Nem ismerem ezt a Lázárt akiről te beszélsz, de érzek egy nagy viaskodást a \"\n\"lényében. Hatalmas veszélyt jelent ránk és semmi sem fogja megállítani \"\n\"abban, hogy a sötétséget szolgálja, mivel már ő is a részévé vált.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Igen, a jóságos Lázár, aki oooolyan hasznos volt a szörnyek ellen ott lent. \"\n\"Nem tett sokat azért, hogy megmentse a lában, nem? Adok egy jó tanácsot: \"\n\"kérdezd Farnhamot, ő ott volt.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Hagyj fel a bolond elhívásoddal. Már csak a gazdám pusztító haragja vár rád. \"\n\"Elkéstél és nem tudtad megmenteni a gyereket. Most te is csatlakozni fogsz \"\n\"hozzá a kárhozatba!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Nos, nem tudom tudok-e mondani bármit ami hasznára válna. A víz, amely \"\n\"megtölti a kútjainkat egy földalatti forrásból származik. Hallottam azt is, \"\n\"hogy van ott egy alagút amely egy nagy tóhoz vezet. Sajnos fogalmam sincs, \"\n\"hogy mi okozhatja ezt a szennyeződést a vízben.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Mindig próbáltam bőségesen felraktározni étellel és itallal a pincénkben, de \"\n\"így, hogy az egész város víz híján maradt, még a mi készleteink is hamarosan \"\n\"kifogynak.\\n\"\n\"\\n\"\n\"Kérem, tegye meg amit tud, máskülönben nem is tudom, hogy mi történne velünk.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Örülök, hogy időben elérhettem magát! A kútjaink vize romlott és veszélyes \"\n\"lett. Páran már meg is betegedtek miután ittak belőle. A tartalékjaink \"\n\"gyorsan kezdenek elapadni. Úgy hiszem van egy ösvény, amely a város \"\n\"forrásaihoz vezet. Kérem, derítse ki mi okozza ezt a katasztrófát vagy mind \"\n\"itt pusztulunk!\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Kérem, siessen. Minden órával csak egyre csökkennek a tartalékaink.\\n\"\n\"\\n\"\n\"Nem bírjuk már sokáig a segítsége nélkül.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Mit mond maga, hogy a démonok puszta jelenlététől szennyeződött meg a víz? \"\n\"Igaz, tényleg nagy gonosz ólálkodik a városunk alatt, de a bátorsága és \"\n\"kitartása erőt ad. Kérem vegye el ezt a gyűrűt! Talán segíteni fog a \"\n\"rémségek legyőzésében.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"A nagymamám nagyon gyenge és Gárda azt mondja nem ihatunk többet a kútból. \"\n\"Kérlek, nem tudsz valahogy segíteni nekünk?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pipin elmondta már néked az igazat. Kell nekünk friss víz, de gyorsan. \"\n\"Megpróbáltam az egyik kisebb kúthoz hozzáférni, de árad belőle az állott \"\n\"bűz. A forrásánál lehet bedugulva, én azt mondom.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Te... vizet iszol!?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Tristram népe el fog pusztulni, ha nem tudsz nekik friss vizet szerezni.\\n\"\n\"\\n\"\n\"Halld meg ezt: a démonok az okozói ennek, de nem tudják mivel fog ez járni.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Most az egyszer egyetértek. Az üzletemnek nem tehet sok jó, ha nem marad \"\n\"ügyfélköröm. Jobban teszed ha kitalálod mi történik, de gyorsan!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"A könyv, amely emberi koponyák kamrájáról mesél? Nos, a koponyák kamráját \"\n\"egyes ősi források is említek, amelyekkel a nagy keleti könyvtárakban \"\n\"találkoztam. Azok a tekercsek arra sugalltak, hogy amikor az alvilág urai \"\n\"óvni szerették volna a nagy kincseiket, akkor olyan igéket\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Félek semmit sem tudok erről, jó uram. Káinnak sok hasonló könyve van, amely \"\n\"talán segítségül szolgálhat.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Ez aztán egy veszedelmes helynek hangzik így, Ha oda kíván merészkedni, \"\n\"kérem legyen nagyon óvatos!\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"Félek semmi ilyesmiről nem hallottam. Talán Káin mesélhetne róla.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Semmit sem tudok arról a helyről, de talán kérdezt Káint. Sok dologról \"\n\"beszél mindig, nem lepne meg, ha erről is tudna.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Rendben, na, hallgasson. Itt van ez a fakamra, látja-e. És a felesége, \"\n\"tudja, ő, aztat mondja a fának... mert várnod kell. És én aztán azt mondom: \"\n\"lehet nem használ, de ha még fizetnem is kellene érte... na, bizony.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"A sötét urak örökös szolgája leszel és el fogsz hunyni abban a megátkozott \"\n\"helységben.\\n\"\n\"\\n\"\n\"Csak a saját károdra lépj be a koponyák kamrájába.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Nagy és titokzatos kincs, azt mondod? Lehet talán engem is érdekelne, ha \"\n\"beszerezhetnék pár dolgot... vagy még jobb: nincs szükséged inkább neked \"\n\"valami ritka és drága felszerelésre, hogy túléld ezt a hatalmas veszedelmet?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Úgy tűnik Lázár főérsek sokakat becsalt a labirintusba, hogy megtalálják a \"\n\"király eltűnt fiát. Rájátszott a félelmeikre és egy bőszült tömeget csinált \"\n\"belőlük. Egyikük sem volt felkészülve arra ami várt rájuk a hideg \"\n\"mélységekben és Lázár pusztulni hagyta őket a kimondhatatlan rémségek között.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Igen, Farnham motyogott valamit egy hatalmas rettenetről egy pusztító \"\n\"fegyverrel. Azt hiszem a mészárosnak hívták.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"A fény igazára, ismerem ezt az álnok démont. Sokan hordozzák a haragjának \"\n\"sebeit a testükön, amikor pár túlélője a Lázár által vezetett rohamnak \"\n\"visszakúszott a katedrálisból. Nem tudom mit használtak az áldozatok \"\n\"feldarabolására, de biztos nem lehetett eme világi. Olyan fertőzött sebeket \"\n\"hagyott, amelyeket szinte én sem tudtam kezelni. Óvatosan, ha ezzel a \"\n\"fenevaddal akarsz harcolni...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Amikor Farnham mondott valamit arról, hogy a mészáros embereket ölt, azonnal \"\n\"semmibe vettem. De mivel te is felhoztad, lehet igaz.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Láttam azt amit Farnham a mészárosnak hívott ahogy az átszelte a barátaim \"\n\"testét. Egy akkora bárdot lóbált, mint egy fejsze. Ott helyben lecsapta a \"\n\"végtagjait számos bátor embernek egyetlen egy mozdulattal! Engem egy pár \"\n\"kisebb szörnyecske választott el a tömegtől és szerencsére megtaláltam a \"\n\"kijáratot menekülés közben. Soha többé nem láttam azt a rémséges bestiát, de \"\n\"a véres képe még ma is kísért bizony.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Nagy! Nagy bárd megöli a barátaimat! Nem tudtam mit tenni, futottam, nem \"\n\"tudtam megmenteni senkit sem. Be voltam zárva, olyan sok halottal... \"\n\"barátokkal... NEEE!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"A mészáros egy kegyetlen lény, amely élvez fájdalmat és szenvedést okozni \"\n\"másoknak. Láttam a munkásságát a részeges Farnhamon. A rémség elpusztítása \"\n\"sokat tenne a falu biztonsága érdekében.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Többet tudok arról a rémségről, mint te azt gondolnád. A kis pajtásai \"\n\"lefogtak és elkapták a lábamat mielőtt Griswold kihúzott abból a lyukból.\\n\"\n\"\\n\"\n\"Öld meg, mielőtt ő öl meg téged és szobadíszt csinál a holttestedből.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Kérem, hallgasson meg... Lázár főérsek, levezetett minket ide, hogy \"\n\"megtaláljuk az eltűnt herceget. A mocsok csapdába csalt mindnyájunkat! Most \"\n\"már mindenki halott... megölte őket egy mészárosnak nevezett démon. Találja \"\n\"meg ezt a mészárost és ölje meg, hogy a lelkeink békében nyugodjanak.\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Egy érdekes rímet mesél. Olyan stílusban íródott, mellyel már találkozhattam \"\n\"régebben. Hadd töprengjek, mi lehetett?\\n\"\n\"\\n\"\n\"Éj lepi a rejtőzőket.\\n\"\n\"Erről ön is meggyőződhet\\n\"\n\"Láthatatlan, fényes szemek\\n\"\n\"Hogy ejthetnek véres sebet?\\n\"\n\"Kárhozottak karma éles\\n\"\n\"Minden út ki innen téves\\n\"\n\"Szemem marják ki vad kezek\\n\"\n\"Vakok csarnoka ez lehet\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Sose érdekel nagyon a költészet. Időnként hívtam bárdokat a fogadómba amikor \"\n\"jobban ment a sorunk, de az már oly rég volt.\\n\"\n\"\\n\"\n\"Hogyan? Igen, szóval... próbálkozzon valaki mással, ki esetleg többet tudhat.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Ez ismerősen hat valami csoda folytán. Emlékszem, olvashattam valami nagyon \"\n\"hasonló verset mikor a démoni károkozók ellen olvastam. Egy nagyon \"\n\"elvetemült helyről beszélt, amely... várjunk, csak nem óhajt odamenni, igaz?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Ha kérdéseid vannak a vakságról, Pipinnel kellene beszélned. Tudom, hogy \"\n\"adott a nagymamámnak egy varázsfőzetet, aminek segítségével ismét tisztábban \"\n\"látott. Talán neked is segíthet.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Félek sose hallottam vagy láttam erről az élénken leírt helyről, barátom. \"\n\"Talán a jó öreg Káin segítségedre válhat.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Nézz ide... elég vicces, nem? Érted? Vak, nézz ide...?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Az a hely nagy kínt és félelmet tartalmaz, ezért jól szolgálja a gazdáját.\\n\"\n\"\\n\"\n\"Járj óvatosan vagy tovább fogsz ott maradni, mint terveznéd.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Nézzük, adok-e el neked valamit? Nem. Pénzt adsz nekem azért, hogy ezt \"\n\"elmondhassam. Nem. Most már úgy látod ideje távoznod és inkább a \"\n\"történetmesélőt zaklatnod ezekkel a kérdésekkel? Igen.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Azt állítja beszélt Lachdanánnal? Nagy hős volt bizony az élete során. \"\n\"Lachdanán egy becsületes, igazságos férfi volt, aki hűségesen szolgálta a \"\n\"királyát hosszú éveken keresztül. Természetesen maga ezt már tudja.\\n\"\n\"\\n\"\n\"Akik a király átkának a hatása alá kerültek, Lachdanán volt a legesélyesebb, \"\n\"hogy csak küzdelem árán hódoljon be a sötétségnek, így feltételezem ez a \"\n\"történet igaz is lehet. Ha az ön helyében lennék barátom, keresnék egy \"\n\"módot, hogy kiszabadítsam őt e kínzás alól.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Egy rég halott hősi harcosról beszélsz! Nem kérek az ilyen beszédből a \"\n\"holtakról a fogadóm udvarában, köszönöm szépen.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Egy arany varázsital, azt mondja? Sose találtam fel ilyen színű bájital, \"\n\"tehát meg nem tudnám mondani, hogy milyen hatással lenne a fogyasztójára. A \"\n\"gyógyítójaként, erősen javasolnám, ha a keze ügyébe bukkanna egy ilyen ital, \"\n\"tegyen, ahogy Lachdanán kéri és NE igyon belőle!\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Sose hallottam erről a Lachdanánról. Sajnálom, nem hiszem, hogy nagy \"\n\"segítségedre lehetnék.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Ha tényleg Lachdanán azt akivel találkozott, akkor azt javasolnám, hogy \"\n\"segítsen neki. Volt már dolgom vele pár alkalommal és igaz, őszinte \"\n\"természetnek ismertem meg. Az átok ami Leorik király követőit súlytotta \"\n\"különösen nehezen érintette őt emiatt.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\"Lachdanán halott. Mindenki tudja ezt és nem tudsz átverni, hogy másként \"\n\"gondoljam. Nem tudsz a holtakkal beszélni. Tudom!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Lehet találkozol olyan emberekkel, akik a labirintusban ragadtak, akár csak \"\n\"Lachdanán.\\n\"\n\"\\n\"\n\"Becsületet és nagy bűntudatot érzek benne. Segítsd őt és az egész várost \"\n\"segíted.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Nos, hadd találjam ki. Káint lenyelte egy hatalmas nagy lyuk, ami hirtelen \"\n\"megnyílt alatta. Felemésztette a pokol tüze, így nem tud többé a kérdéseidre \"\n\"válaszolni. Jaj, nem ez történt? Akkor gondolom venni szeretnél valamit vagy \"\n\"tovább állsz.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Kérem, ne öljön meg... hallgasson végig. Egyszer a kapitánya voltam Leorik \"\n\"király lovagjainak, fenntartva e vidék törvényeit igaz akarattal és \"\n\"becsülettel. Ezt követően a sötét átka azonban minket is utolért és így \"\n\"szerepet játszottunk a tragikus halálában. Ahogy a lovagtársaim elszenvedték \"\n\"ezt a kegyetlen ítéletet, én elmenekültem a király sírkamrájából és \"\n\"megpróbáltam megszabadítani magamat az átoktól. Nem jártam sikerrel...\\n\"\n\"\\n\"\n\"Hallottam egy arany varázsitalról, amely felemelheti az átkot és \"\n\"megnyugodhat neki köszönhetően a lelkem, de sajnos sehogy sem sikerült rá \"\n\"lelnem. Az erőm mos kezd elhalni és vele együtt az utolsó csepp emberségem \"\n\"is. Kérem, segítsen nekem megtalálni ezt a varázsitalt. Meg fogom fizetni, a \"\n\"becsületemre esküszöm fel.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Nem találta még meg az arany varázsitalt? Félek örök kárhozatra vagyok \"\n\"ítélve. Kérem, próbálkozzon még...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Megmentette a lelkem a kárhozattól és ezért adósa vagyok. Ha lenne bármi \"\n\"mód, hogy visszafizessem a sírból, meg fogom találni. Addig is, kérem, vegye \"\n\"el a sisakomat. Az én utamon már kis hasznát fogom látni. Védelmezze önt a \"\n\"sötét erőktől. Menjen a fénnyel, barátom...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold beszél a harag üllőjéről. Egy legendás ereklye, amely után régóta \"\n\"kutatnak, de sose találták meg azt. A borotvagödör démonjainak a fémes \"\n\"csontjaiból faragták ezt az üllőt és az alvilág öt legerősebb mágusának a \"\n\"koponyájából készült. Televésve erőt és káoszt hozó feliratokkal, bármely \"\n\"fegyver, amely ezen az üllőn lesz kovácsolva, találkozni fog a káosz \"\n\"birodalmával és így varázs tulajdonságokra fog szert tenni. Azt mondják a \"\n\"káosz kiszámíthatatlan természete miatt nehéz megmondani, hogy mi lesz az \"\n\"eredmény.\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Nem gondolja, hogy jobb lenne talán Griswoldot keresni ilyen ügyben? Elég \"\n\"kezes, bizonyára tudja.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Ha többet szeretne megtudni a gyógyító mozsártörőről vagy a megtisztulás \"\n\"ezüst kelyhéről, akkor tudtam volna segíteni, barátom. Viszont ez ügyben \"\n\"lehet jobban járna Káin vagy Griswold felkeresésével.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Griswold apja mesélte párunknak amikor gyerekek voltunk, hogy létezik egy \"\n\"óriás üllő amellyel régen hatalmas fegyvereket készítettek. Azt mondták \"\n\"amikor egy kalapács csapott arra az üllőre, az egész föld nagy haraggal \"\n\"remegett. Mindig amikor megmozdul a föld, erre a történetre gondolok.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Üdvözletem! Mindig egy öröm látni az egyik legjobb vásárlómat! Tudom, hogy \"\n\"egyre mélyebbre merészkedtél a labirintusba és van egy történetem, amelyet \"\n\"talán meg szeretnél hallgatni...\\n\"\n\"\\n\"\n\"Az egyik ember ki visszatért a labirintusból mesélt nekem egy titokzatos \"\n\"üllőről amelyre a menekülése során bukkant. A leírása emlékeztetett engem \"\n\"azokra a legendákra, amelyekről ifjúként hallottam egy égő, pokoli \"\n\"kohászatról, ahol erős és mágikus fegyvereket lehetett készíteni. A legenda \"\n\"úgy tartja, hogy ennek a kohászatnak a mélyén nyugszik a düh üllője. Ez az \"\n\"üllő tartalmazza a démoni alvilág legbelső esszenciáját...\\n\"\n\"\\n\"\n\"Azt mondják, hogy bármily fegyver amely e parázsló üllőn készül nagy \"\n\"hatalommal lesz felruházva. Ha ez az üllő tényleg az melyre gondolok, lehet \"\n\"képes leszek neked a segítségével egy olyan fegyvert kovácsolni, amely még a \"\n\"sötét nagyurat is segíthet legyőzni!\\n\"\n\"\\n\"\n\"Találd meg nekem azt az üllőt és én rögvest munkához is látok!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Még mindig semmi? Na, keresgélj csak. Egy üllőn kovácsolt fegyver lenne a \"\n\"legjobb reményed és a saját szavamat adom: legendásat fogok alkotni neked!\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"Alig hiszem el! EZa gard\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold nem tudja eladni az üllőjét. Mit fog akkor tenni? Mérges lennék én \"\n\"is, ha valaki elvette volna az üllőmet.\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Sok kincs rejlik a labirintus mélyen, amelyek mi halandók számára \"\n\"elképzelhetetlen hatalommal ruházhatják fel a viselőjüket. Közülük egy pár \"\n\"olyan erővel bír, hogy a fény és a sötétség is áhítozik rá. Az üllőt \"\n\"megszerzése a fény javára fordítaná a bűn harcának kimenetelét.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Ha megtalálnád azt az ereklyét Griswoldnak, akkor elég nagy bajba kerülne az \"\n\"üzletem. Jaj, csak meg ne találd.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"A vér kapuja és a tűz csarnoka mind titokzatos eredetű képződmények. A könyv \"\n\"ahol ezekről olvashattál biztos nagy hatalommal bír.\\n\"\n\"\\n\"\n\"A regék meséltek egy piedesztálról melyet obszidiánból faragtak és a \"\n\"csontból vájt felszínén egy izzó vérből álló tó nyugszik. Vannak még \"\n\"sugallatok is a vér köveire, melyek kinyitják az ajtót mely egy ősi kincset \"\n\"őriz...\\n\"\n\"\\n\"\n\"E kincs természetét rejtély ötvözi, barátom. Azt mondják egy ősi hős, \"\n\"Arkaine, elhelyezte a Virtus nevű páncélját egy titkos kamrába. Ő volt az \"\n\"első halandó aki hatással volt a bűn harcára és visszazavarta a sötétség \"\n\"seregét a pokol mélyére.\\n\"\n\"\\n\"\n\"Mielőtt Arkaine meghalt, a páncélja el lett rejtve egy titkos kamrába. Azt \"\n\"rebesgetik, mikor ismét szükség lesz a szent páncélra, egy hős fog jönni, ki \"\n\"ismét hordhatja. Talán épp maga az a hős...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Minden gyermek hallotta a harcias Arkaine és a titokzatos páncéljának a \"\n\"történetét, amelyet úgy neveznek: Vírtus. Ha sikerül megtalálni a \"\n\"nyugvóhelyét, védve lesz a labirintus gonoszaitól.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Valami olyasminak hangzik, amire nekem is emlékeznem kellene, de olyan \"\n\"elfoglalt voltam az új gyógyírek és bájitalok készítésével, hogy biztos \"\n\"elfelejtettem. Elnézést...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Ennek a Virtus nevű varázspáncélnak a története valami olyasmi, amiről a \"\n\"fiúkat szoktam hallani beszélni. Lehet jobban tennéd, ha az egyik férfit \"\n\"kérdeznéd a faluból.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"A Virtus nevű páncél bizonyára az irányodba billentené a dolgokat. \"\n\"Megmondom: sokan keresték már, jómagamat is beleértve. Arkaine jól \"\n\"elrejtette barátom és többre lesz szükség szerencsénél ahhoz, hogy \"\n\"felfedődjenek a titkok, amelyek őrzik a páncél hollétét.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Ha megtalálod a vér köveit, bánj velük óvatosan.\\n\"\n\"\\n\"\n\"Az út veszéllyel van szegezve és a reménységed pusztán az önmagadba vetett \"\n\"hit lesz.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"A Virtus nevű páncél után szaglászol?\\n\"\n\"\\n\"\n\"Soha senki sem jött rá, hogy Arkaine hova rejtette azt a cuccot és ha az én \"\n\"ismerőseim sem tudtak róla semmit sem kideríteni, akkor szerintem te sem \"\n\"fogsz.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Ismerek egy legendát mely egy ilyen harcosról beszél, melyet maga is leír. A \"\n\"történetét a bűn háborújának az ősi megemlékezéseiből származik.\\n\"\n\"\\n\"\n\"Meggyalázva egy ezer éves háborútól, vértől és haláltól, a vér hadura \"\n\"magasan áll az áldozataiból formált hegyen. A sötét pengéje egy átkot szór \"\n\"az élőkre. Gyötrelem vár mindenkire, ki útjába áll a pokol hóhérjának.\\n\"\n\"\\n\"\n\"Meg van írva az is, hogy egyszer volt egy halandó ki a bűnháborúja során \"\n\"mellette harcolt és elvesztette az emberségétől a végtelen vérszomja miatt.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Félek semmit sem hallottam erről a veszedelmes harcosról, jó uram. Remélem \"\n\"nem lesz szükséges harcolnia vele, mert az kockázatosnak tűnne.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Káin lehet sokkal többet tudna magának mondani valami ilyesmiről, mint \"\n\"amennyit én valaha is szeretnék tudni.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Amennyiben egy ilyen veszedelmes ellenféllel kell megküzdened, akkor \"\n\"kívánom, hogy a fény fog vezetni és védelmezni. Gondolni fogok rád.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Sötét és beteges regék ötvözik a vér hadurának személyét. Légy jól \"\n\"felkészült barátom, mert ő nem ismer kegyelmet és megnyugvást.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Mindig a vérről akarsz beszélni? Mi van a virágokkal, a napfénnyel és azzal \"\n\"a szép leánnyal ki hozza az italokat. Figyelj ide barátom, megszállott vagy, \"\n\"ugye tudod?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Az ő kardforgató készsége elképesztő, hisz már ezer éve járja a földet csak \"\n\"háborút ismerve. Sajnálom... nem látom, hogy hogyan tudnád legyőzni.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Soha nem volt dolgom még ezzel a hadúrral, de úgy hangzik sok kardot \"\n\"elhasznált már. Szívesen ellátnám a hadseregét...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"A pengém a véredre áhítozik, halandó és nem tagadhatom meg a kérését.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold beszél egy mennyei kőrül, amelyet egy közösségnek szántak innen \"\n\"keletre, ahol tovább óhajtották tanulmányozni. Ez a kő erős kisugárzással \"\n\"bírt és lehetővé tette, hogy a puszta emberek is olyan dolgokat lássanak, \"\n\"amelyeket elképzelni sem tudtak volna. Nem tudom milyen titkokat rejt ez az \"\n\"ereklye, de a megtalálása hasznunkra válna.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"A karaván itt állt meg, hogy vigyel felszerelést keletre. Adtam nekik friss \"\n\"gyümölcsöt és kalácsot, amelyet Gárda épp most készített. Kár, hogy mi lett \"\n\"annak a társaságnak a sorsa...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Nem tudom, hogy mit gondoltak mit látnának abban a kőben, de azt mondom \"\n\"önnek: ha kövek hullanak az égből, jobb óvatosnak lenni!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Nos, egy karaván tele fontos emberekkel tényleg megállt itt, de az még elég \"\n\"régen volt. Fura kiejtésük volt és egy hosszú utazásra készültek, ha én jól \"\n\"emlékszem.\\n\"\n\"\\n\"\n\"Nem értem hogyan remélheted, hogy sikerülne bármit megtalálnod abból, amit \"\n\"maguknál hordoztak.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Maradj egy pillanatra! Van egy történetem, amit lehet érdekesnek találhatsz. \"\n\"Egy karaván haladt a keleti királyságok felé nem régiben. Állítólag egy kis \"\n\"darabkát vitt magával, egyenesen a mennyekből! Egy darabot, ami lehullott a \"\n\"földre! A karavánra köpenyes lovasok ütöttek rajta északra az út mentén. \"\n\"Átkutattam a romokat az égi kőért, de sehol sem tudtuk megtalálni. Ha neked \"\n\"sikerülni, talán sikerülne valami hasznosat összecsapnom belőle.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Még mindig várok arra, hogy elhozd nekem azt a követ a mennyekből. Tudom \"\n\"biztosan, hogy valami igazán erőset tudnék belőle faragni.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Lássuk csak... igen, igen. Pont, ahogy gondoltam. Kérek egy pillanatot...\\n\"\n\"\\n\"\n\"Itt is vagy. Belehelyeztem a kő darabkáit ebbe az ezüst gyűrűbe, amelyet még \"\n\"az apám hagyott rám. Remélem jól fog szolgálni.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Volt egy szép gyűrűm, egy tényleg drága. Kék, zöld, vörös, ezüst. Nem \"\n\"emlékszem mi történt vele viszont. Tényleg hiányolom...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"A mennyei kő hihetetlen erős és senki másra nem bíznám rá, csakis \"\n\"Griswoldra. Ő képes lenne az erejét kinyerni és mindnyájunk számára \"\n\"hasznosítani azt.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Ha bárki is képes lenne valamit csinálni abból a kőből, akkor az csakis \"\n\"Griswold lenne. Ő aztán tudja mit csinál. Noha próbálom elcsalogatni a \"\n\"vásárlóit, tisztelem a minőségét az ő munkájának.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Adria a boszorka is a fekete gombát keresi? Annyit tudok a fekete gombákról, \"\n\"mint a vörös heringekről. Talán Pipin a gyógyító többet tudna mesélni \"\n\"magának, de ez egy olyas valami téma, amiről nem hallana sok mindent tőlem.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Hadd mondjam csak ezt: se nem én, se nem Gárda, soha, SOHA nem szolgálnánk \"\n\"fekete gombát a becses vendégeinknek. Ha Adria akar valamiféle gombát a \"\n\"főztjeibe, hát az az ő dolga, de én nem segíthetek ebben. Fekete gombák... \"\n\"visszataszító!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Egy boszorkány mondta nekem, hogy egy démonnak az agyát kereste, ami \"\n\"segíthet nekem abban, hogy létrehozzam a varázsfőzetemet. Nagy hasznára \"\n\"válna sokaknak, akiket megkárosítottak ezek a romlott lények, csak fel \"\n\"kellene hozzá törnöm az alkímia titkait. Ha el tudná távolítani az agyát egy \"\n\"ilyen démonnak mikor megöli és ide tudná hozni, akkor mélyen le lennék \"\n\"kötelezve.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Kiváló, pont ez volt a fejemben... sikerült befejeznem a varázsfőzetet \"\n\"nélküle, de nem árthat, ha egy kicsit tanulmányozom, igaz? El tudnád ezt itt \"\n\"vinni a boszorkányhoz? Úgy hiszem épp most várja.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Szerintem lehet Ogdennek vannak gombái a pincekamrájában. Miért nem kérdezed \"\n\"meg?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Ha Adriának nincs egy ilyene, akkor lefogadhatod, hogy ez bizony egy ritka \"\n\"dolog. Ennél többet nem tudok segíteni, de ez bizony egy igen... hatalmas, \"\n\"termetes, terebélyes, bitang nagy gombának hangzik. Jó vadászatot, azt \"\n\"hiszem!\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden aztán egy UNDOK fekete gombát tud keverni, de belebetegednék, ha \"\n\"meginnám. Figyelj, figyelj... itt a titok: fő a mértékletesség!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Mi dolgunk van itt? Érdekes, egy bájitalkönyvnek néz ki. Hegyezd jól a \"\n\"szemeidet, egy fekete gombára lesz szükségem. Eléggé nagy, könnyű lesz \"\n\"azonosítani. Ha megtalálod, hozd el nekem, rendben?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Egy nagy, fekete gombára áhítozom. Most fuss, fuss, hozd el nekem, hogy \"\n\"befejezhessem ezt a különleges összetételt, amin épp nagyban dolgozom.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Igen, ez tökéletes lesz a főzetnek, amit csinálok. Egyébként, a gyógyító \"\n\"valamilyen démonnak az agyát keresi, hogy kezelhesse azokat, akiket az undok \"\n\"mérgük gyötör. Úgy hiszem egy varázsfőzetet akarna belőle csinálni. Ha \"\n\"sikerül megtalálnod neki ami kell, kérlek, hogy ez kortyot nekem is a kész \"\n\"főzetéből.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Miért hoztad ezt ide? Nincs szükségem most semmiféle démon agyára. A \"\n\"gyógyító varázsfőzetére viszont igen. Szüksége van arra a torz testrészre, \"\n\"melyet most a kezeidben tartasz. Utána hozhatsz nekem a varázsfőzetből. \"\n\"Egyszerű így, nem?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Mi? Csak most hoztad ide el azt a varázsfőzetet a gyógyítótól? Kár, már be \"\n\"tudtam fejezni a sajátomat enélkül is. Miért nem tartod csak meg...?\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Nem semekkora méretű, színű vagy formájú eladó gombám. Mit szólnál valami \"\n\"kicsit hasznosabbhoz?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Szóval a térkép legendája valóságos, pedig még én sem hittem egy szót sem \"\n\"belőle! Úgy feltételezem eljött az ideje, hogy elmondjam az igazságot arról, \"\n\"hogy ki is vagyok, barátom. Nem az ám, akinek tűnők...\\n\"\n\"\\n\"\n\"Az én valódi nevem Dékárd Káin, a rangidős. Én vagyok az utolsó \"\n\"leszármazottja egy ősi testvériségnek, melynek a célja az időtlen gonosz \"\n\"titkainak megőrzése volt, a gonosznak, mely most most kiszabadult...\\n\"\n\"\\n\"\n\"A gonosz kivel szembe maga száll nem más, mint a rettenet sötét ura, kit a \"\n\"halandók csak Diablónak hívnak. Ő volt a labirintus fogságában tartva \"\n\"évszázadokon keresztül. A térkép melyet most a kezeid közt tartasz, réges-\"\n\"régóta készült és megjósolta, hogy Diablo mikor fog ismét kiszabadulni a \"\n\"börtönéből. Mikor a két csillag a térképen fedi egymást, Diablo ereje akkor \"\n\"fog kiteljesedni és elpusztíthatatlanná válik akkora.\\n\"\n\"\\n\"\n\"Az idővel kell versenyeznie barátom! Találja meg Diablot és pusztítsa el \"\n\"mielőtt találkoznak a csillagok vagy soha többé nem lesz lehetőségünk \"\n\"megszabadítani a világot ettől a gonosztól!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Fogy az időnk! Érzem, hogy a sötét ereje növekszik és csak maga tudja \"\n\"megállítani mielőtt eléri a hatalmának csúcsát.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Biztos vagyok benne, hogy megpróbált minden tőle telhetőt, de félek, hogy a \"\n\"maga ereje sem lesz elég. Diabló épp a földi hatalmának csúcsán van és \"\n\"minden bátorságra és erőre szüksége lesz, hogy legyőzze őt. A fény \"\n\"védelmezze és fedezze magát, barátom. Segíteni fogok, ahogyan csak tudok.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Ha a boszorkány nem tud segíteni és azt javasolja, hogy látogassa meg Káint, \"\n\"akkor miért gondolja, hogy én tudnék bármit is? Nagyon komoly ügynek \"\n\"hangzik. Siessen és lássa a öreget, ahogy Adria is javasolja!\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Nem tudom nagyon értelmezni az írást ezen a térképen, de esetleg Adria vagy \"\n\"Káin lehet tudna segíteni.\\n\"\n\"\\n\"\n\"Látom, hogy ez egy csillagászati térkép, de eddig terjed a tudásom sajnos.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"A legjobb ember akit ezzel kereshetsz az Káin lenne.\\n\"\n\"\\n\"\n\"Nagyon jártas ezekben az ősi írásokban és senki mást nem ismerek, aki ilyen \"\n\"relikviákkal foglalkozna.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Még sose láttam ilyen térképet. Honnan szerezted? Fogalmam sincs hogyan \"\n\"kellene elolvasni. Talán Káin vagy Adria több válasszal tud szolgáltatni.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Figyelj, gyere közel. Nem tudom, hogy tudod-e amit én, de tényleg \"\n\"Istenigazából van itt valami. Egy térkép.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Jaj, félek ez egyáltalán nem jó jel. Ez a csillagjegyes térkép nagy \"\n\"katasztrófára sugall, de a titkait még nekem sem árulja el. Eljött az időd, \"\n\"hogy egy komoly beszélgetésben vegyél részt Káinnal...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Egy térképet kerestem, de biztosan nem ezt. Meg kellene mutatnod Adriának, \"\n\"valószínűleg tudja mi az. Én csak egyet tudok: réginek néz ki és a \"\n\"régiségekre nagy a kereslet.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Kééééérlek. Nem bántani. Nem ölni. Éééélni hagyni és legközelebb jó hozni \"\n\"neked.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Valamit neked kééééészítek. Ismééét, nem ölni Gharbad. Éééélni és adni \"\n\"jóóót.\\n\"\n\"\\n\"\n\"Te elvenni bizonyíítéék, één megtartani szóót...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Semmi mééég! Majdnem kééész.\\n\"\n\"\\n\"\n\"Nagyon erőőős, nagyon veszééélyes. Éélni! Ééélni!\\n\"\n\"\\n\"\n\"Nincs kín és ígééret megtartani.\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Ez túúúl jó neked. Nagyon eeerős. Akarni... elveenni!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Mi?! Miért vagy te itt? Ez az összes zavarás, beleőrülök! Itt van, vidd ezt \"\n\"és hagyj már magamra. Ne zavarj többet!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Aaaaa! A kíváncsiságod legyen a veszted is, te bolond!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Adjon Isten, cimbora! Pihenjen meg és hegyezze a fület...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Ahogy egyre mélyebbre merül a labirintusba, találhat nagy tudást rejtő \"\n\"tekercseket is.\\n\"\n\"\\n\"\n\"Olvassa őket figyelmesen, mert olyat taníthatnak, melyet még én sem.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Sok titkos és legendát hallottam melyek lehet választ adhatnak a \"\n\"labirintussal kapcsolatos kérdésekre. Ha kihívásokba ütközöl vagy tudásra \"\n\"szomjazol, keress fel engem és én elmondom amit csak tudok.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold: nagy tettek és nagy bátorság jellemzi. Úgy vélem sose mesélt önnek \"\n\"arról, mikor lement a labirintusba, hogy megvédje Wirtet, nem igaz? Tudja \"\n\"jól, hogy milyen veszélyre lehet lent számítani, de bizonyára maga is. Egy \"\n\"tehetséges kovács és ha ő azt állítja, hogy tud segíteni, akkor biztosan \"\n\"számíthat az elhivatott munkájára.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden már lassan négy éve birtokolja és futtatja a Szürkület Fogadót. Pár \"\n\"hónappal azelőtt vásárolta, hogy elszabadult a pokol. Ő és a drága felesége \"\n\"Gárda nem rendelkeznek elég pénzzel, hogy távozzanak innen, mert minden \"\n\"befektetésüket abba tették, hogy itt megélhetésre leljenek. Egy jó ember, \"\n\"mély felelősségtudattal.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Szegény Farnham. Egy megrendítő emlékeztető arra a szerencsétlen csoportra \"\n\"kik lemerészkedtek a katedrálisba Lázárral azon a sötét nap. Ő még élve \"\n\"elmenekült, de a bátorsága és a józan esze abban a sötét kamrában maradt. \"\n\"Csak a korsója mélyén talál megnyugvást manapság, de a szövegelése során \"\n\"időnként előjön belőle az igazság.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"A boszorkány, Adria, egy szokatlan jelenség még itt Tristramban is. Nem \"\n\"sokkal azután érkezett, hogy a katedrálist szégyenteljes módon meggyalázták, \"\n\"miközben mindenki más éppen menekült. Egy kis kunyhót épített a város \"\n\"szélén, látszólag egyetlen éjszaka alatt és számos olyan furcsa és \"\n\"titokzatos ereklyéhez és könyvhöz van hozzáférése, amelyeket még én sem \"\n\"fogtam soha a kezeim között.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Wirt története bizony egy rémisztő és sajnálatos eset. Az édesanyjának a \"\n\"karjából elragadták és a labirintusba hurcolta pár kis visszataszító démon \"\n\"görbe lándzsákkal. Sok más gyereket vittek el aznap, köztük Leorik király \"\n\"fiát is. A palota lovagjai lementek megmenteni, de sose tértek vissza. A \"\n\"kovács megtalálta a fiút, de csak miután azok a fenevadak már elkezdték \"\n\"megkínozni őt a saját romlott örömükre.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ó, Pipin. Egy igaz barátként tekintek rá, talán a legközelebbire a helyiek \"\n\"közül. Kicsit türelmetlen tud lenni időnként, de nála odaadóbb és \"\n\"nagylelkűbb lélek még nem létezett a földön. A tág tudásával és \"\n\"tapasztalatával kevesen vehetik fel a versenyt és az ajtaja mindig nyitva \"\n\"áll bárki számára.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Júlia bizony egy szép asszony. Sokan szeretik őt a lelkesedése miatt, \"\n\"valamint, hogy milyen könnyű megnevettetni. Nekem is egy különleges helye \"\n\"van a szívemben. A fogadóban él, hogy gondozza a beteg nagymamáját, aki túl \"\n\"beteg ahhoz, hogy utazzon. Néha féltem a biztonságát, de tudom, hogy bármely \"\n\"férfi a városban inkább meghalna, sem minthogy baja essék annak a lánynak.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Áldás, békesség, jó uram. Üdvözölöm az Alkonyat Fogadóban!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Sok kalandor tette gazdagabbá a fogadóm asztalait és legalább tucat annyi \"\n\"történetet meséltek már egy hűs ital felett. Az egyetlen dolog, amelyben \"\n\"mind egyetértettek, az egy a régi népi bölcsesség. Talán segít neked is. A \"\n\"húst vághatod, de a csontot csak zúzhatod.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Griswold a kovácsunk hihetetlen jártas fegyverek és páncélzat terén. Ha \"\n\"valaha segítségre van szükséget felszerelés kapcsán, világosan ő lesz az ön \"\n\"embere.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham túl sok, túl sok időt tölt itt, olcsó italba fordítva a bánatát. Rá \"\n\"szeretném venni, hogy hagyja abba, de tudom milyen sokat szenvedett a \"\n\"labirintusban.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria bölcsebb a koránál és bevallom, kicsit megrémiszt.\\n\"\n\"\\n\"\n\"Nem számít. Ha kereskedni akarsz valaha is varázslatos eszközökkel, ő egy \"\n\"igen jelentős készlettel bír a folyó túlsó partján.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"Ha kíváncsi vagy a falunk történetére, Káin elég sokat tud a múltról.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt egy rosszcsont és egy kis taknyos kis kölyök. Mindig valami bajba \"\n\"kerül, nem is csoda, hogy mi történt vele.\\n\"\n\"\\n\"\n\"Valószínűleg valahol hülyéskedett, ahol nem kellett volna. Sajnálom őt, de \"\n\"nem kedvelem a társaságot, akivel körülveszi magát.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pipin egy jó ember, kérdés nélkül a legbőkezűbb a faluban. Mindig igyekszik \"\n\"mások bajait orvosolni, de valami baj mindig kísérti őt, bárhova is megy.\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Júlia, a csaposnőm? Ha nem lenne kötelességtudata a nagyanyját illetően, \"\n\"szerintem már rég elmenekült volna.\\n\"\n\"\\n\"\n\"Jóisten tudja hányszor könyörögtem neki, hogy menjen el és én majd gondozom \"\n\"az öreglányt, ő egyszerűen túl édes és törődő ahhoz, hogy így tegyen.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Mi nyomja a lelkét, barátom?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Egy nagyon érdekes felderítést sikerült tennem. Velünk ellentétben, a \"\n\"labirintus teremtményei bájitalok és varázslat nélkül is képesek gyógyulni. \"\n\"Ha megsebez egy szörnyet, fejezze is be a munkát, mert könnyen lehetséges, \"\n\"hogy hamar maguktól rendbe jönnek.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Mielőtt elfoglalta a lent ólálkodó gonosz, a katedrális nagy tudás helye \"\n\"volt. Sok-sok könyv található ott. Ha talál egyet, olvassa el, értékes \"\n\"titkokat őrizhet a labirintus működéséről.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold annyit tud a háború művészetéről, mint én a gyógyításéról. Egy \"\n\"ravasz kereskedő és a munkájának minősége párra nem lel. Lehet ez pusztán \"\n\"csak azért van, mert ő itt az egyetlen kovács...\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Káin egy igaz barát és egy bölcs látnok. Terjedelmes nagy könyvtárat \"\n\"birtokol és ösztönösen megérni sok dolog igaz mivoltát. Ha valaha is \"\n\"kérdései vannak, ő lesz a maga embere.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Még az én tudásom sem volt elég, hogy teljesen rendbe hozzam Farnhamot. Jaj, \"\n\"a testét meggyógyítottam, de az elméjével és a szellemével már én sem tudok \"\n\"mihez kezdeni.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Amíg a varázslat korlátozott formáit használom az itt található bájitalok \"\n\"elkészítéshez, Adria az igazi mágus. Úgy tűnik sose alszik és mindig \"\n\"hozzáférése van különféle titokzatos kincsekhez, valamint tekercsekhez. A \"\n\"kunyhója szerintem többet tartogat a külsejénél, de sose sikerült közelebb \"\n\"férkőznöm, hogy lássam.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Szegény, szegény Wirt. Minden tőlem telhetőt megtettem, de tudom, hogy \"\n\"mennyire gyűlöli azt a falábat, amit rá kellett szerelnem a testére. A sebei \"\n\"olyan csúfosak voltak. Senki, főleg egy gyermek, nem lenne szabad, hogy \"\n\"olyan módon szenvedjen, mint ahogy ő szenvedett.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Tényleg nem tudom megérteni, hogy Ogden miért marad itt Tristram falujában. \"\n\"Enyhén neurotikus jellem, de egy okos, szorgalmas férfi és elboldogulna \"\n\"bárhol is van. Feltételezem, hogy tart a gyilkosságoktól, amelyek a környező \"\n\"vidéken történnek, de lehet csak a felesége kívánsága, hogy itt maradjanak.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogden csapotlánya egy édes teremtés. A nagymamája igen beteg és tébolytól \"\n\"szenved.\\n\"\n\"\\n\"\n\"Ő azt állítja, hogy azok látomások, de én nem tudom ezt megerősíteni vagy \"\n\"cáfolni.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Szép napot! Mivel szolgálhatok?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"A nagymamámnak volt egy álma arról, hogy te jönni fogsz és beszélni fogsz \"\n\"velem. Látomásai vannak, tudod és a olvasni tud a jövőbe.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"A hölgy a város szélén egy boszorkány! Bár elég rendesnek tűnik. A neve \"\n\"Adria, nagyon szép név, de eléggé félek tőle.\\n\"\n\"\\n\"\n\"Valaki olyan bátorra lenne szükség, mint te, hogy lássad mit csinál ott.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"A kovácsunk a falu büszkesége. Nem csak egy mestere a szakmájának, ki sok-\"\n\"sok versenyt nyert a céhén belül, de még maga Leorik király is kitűntette, \"\n\"nyugodjék békében a lelke. Griswold mi tovább egy igazi hős is; csak kérdezd \"\n\"Káint.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Káin a rangidőse volt Tristram falujának mióta csak az eszemet tudom. Olyan \"\n\"sokat tud, szerintem szinte mindenről tudna valamit mondani.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham a részeges, minden nap a gyomrát sörrel, az emberek füleit pedig \"\n\"eszetlenségekkel tömi.\\n\"\n\"\\n\"\n\"Tudom, hogy mind Pipin és Ogden sajnálják, de engem annyira zavar látni őt, \"\n\"ahogy egyre mélyebbre és mélyebbre süllyed a zavaros elkeseredettségbe \"\n\"minden egyes éjszaka.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pipin megmentette a nagymamám életét és tudom, hogy semmivel sem tudnám ezt \"\n\"meghálálni neki. A képessége, hogy bármilyen betegséget meggyógyítson \"\n\"erősebb, mint a leghatalmasabb kard; titokzatosabb, mint bármilyen létező \"\n\"varázsige. Ha valaha gyógyításra van szükséged, Pipin segíthet.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Wirt anyjával, Canaceszal nőttem fel. Noha őt csak enyhén bántották azok a \"\n\"csúfságos rémek, mikor a gyerekét elrabolták, végleg összeomlott és hamar \"\n\"elpusztult szegény lelke a gyászban. Wirtből egy undok fiatalember lett, aki \"\n\"csak hasznot akar húzni mindenki más bőrén. Tudom, hogy sokat szenvedett és \"\n\"olyan retteneteket látott, melyeket én el sem tudnék képzelni, de a sötétség \"\n\"mindig árnyékban tartja.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden és a felesége befogadták a nagymamámat és engem az otthonukba és \"\n\"voltak olyan kedvesek, hogy egy kis kenyérre valót is tudok keresni azzal, \"\n\"hogy a fogadójukban dolgozhatok. Olyan sokkal tartozom nekik, remélem egy \"\n\"nap otthagyhatom ezt a helyet és segíthetek nekik egy nagy szállót \"\n\"létrehozni ott keleten.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Na, mit tehetek érted?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Ha egy ütős fegyvert keresel, hadd mutassam meg neked ezt. Fogj egy sima \"\n\"ütőeszközt, mint egy buzogányt. Csodálatosan működik a legtöbb élőhalott \"\n\"ellen odalent. Semmi jobb nincs is a pici, vékony csontjaik összezúzására!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"A balta? Bizony, jó fegyver, remek lehet bármi ellen. Nézd hogyan szeli a \"\n\"levegőt. Majd, képzelj el egy szép, dagadt ördögfejet az útjában! Tartsd \"\n\"észben viszont, hogy elég lassan mozdul... de amikor aztán becsapódik!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Nézd ezt a pengét, ezt a finom egyensúlyt! Egy kard a megfelelő kezekben, a \"\n\"megfelelő ellenfél ellen, minden fegyver ura. Egy minőségi penge nem használ \"\n\"sokat a kemény csontvázak ellen, de az élő, hús-vér szörnyek húsát, bármi \"\n\"valamire való kard szétnyesi!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"A fegyvereden és páncélodon megmutatkozik már az idő vasfoga. Hozd el őket \"\n\"hozzam, egy kis munkával és egy forró kemencével pillanatok alatt rendbe \"\n\"hozom, hogy jobb legyen, mint új korában!\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Amíg gyakorlatilag csempésznem kell a fémeket és a szerszámokat a \"\n\"megátkozott városunk széléről a karavánoktól, az a boszorka, Adria, valahogy \"\n\"mindig megszerez mindent ami kell neki. Ha tudnám a lehető legkevesebbet is \"\n\"arról, hogy hogyan hasznosítsam azt a varázslatot, amit ő használ, ó, milyen \"\n\"csodálatos dolgokat is tudnék akkor én létrehozni!\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Júlia egy olyan helyes leány. Kár, hogy a nagyija olyan rossz állapotban \"\n\"van, különben már mindkettőnket kicsempésztem volna innen az egyik karavánon \"\n\"keresztül\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Néha úgy vélem Káin túl sokat beszél, de ez az élete, ez a hivatása. Ha \"\n\"olyan jól tudnám dolgozni az acélt, mint ő az emberek füleit, még a \"\n\"császárnak is én csinálnám a páncélját!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Farnhammal voltam az éjszaka mikor Lázár levezetett minket abba a \"\n\"labirintusba. Soha többet nem láttam a főérseket többet és lehet nem is \"\n\"éltem volna túl én sem, ha nincs Farnham mellettem. Félek az a támadás úgy \"\n\"megtépázta a lelkét, mint ahogy én lábamat. Én már nem tudom helyette \"\n\"megvívni ezt a harcot, de megtenném, ha tudnám.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Egy jó ember önmagát adja mások szükségleteiért. Senki sem találhatsz \"\n\"Tristramban vagy bárhol máshol, kinek egy rossz szava is lenne a gyógyítóról.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Az a gyerek még egyszer nagy bajba fogja magát juttatni... vagy mondhatni, \"\n\"ismét. Megpróbáltam megkenni, ösztönözni, hogy itt dolgozzon és legyen egy \"\n\"tisztes hivatása, de jobban szereti a magas hasznokat a kétes eredetű \"\n\"tárgyak forgalmazásából. Nem tudom okolni azok után ami történt vele, de \"\n\"jobban szeretném, ha legalább csak óvatos lenne.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"A fogadósnak nem megy jól az üzlete és nem tud hasznot csinálni. Élelemmel, \"\n\"szállással szolgál azon keveseknek kik a városunkba tévednek, de amazok \"\n\"legalább olyan valószínű, hogy lelépnek az éjszaka közepén, mint hogy \"\n\"fizessenek neki. Ha nem gyűjtött volna olyan nagy mennyiségű gabonát és \"\n\"szárított húst a pincéjében, lehet már mind elpusztultunk volna a rémségek \"\n\"támadásának a legelső évében mikor azok elárasztották a vidéket.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Már nem is ihat egy jóember békében?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"A lány aki hozza az italokat? Igen, szép hölgy az. Kedves is.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Miért nem csinál valamit az a vén kuruzsló már végre? Persze, vannak \"\n\"holmijai, de figyelj rám... természetellenes. Sose láttam őt enni, inni... \"\n\"senkiben sem bízhatsz, aki nem iszik egy kicsit!\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Káin nem az akinek vallja magát. Persze, jó történetmesélő... néhány tényleg \"\n\"elég vicces vagy ijesztő... de szerintem valójában többet tud, mint amennyit \"\n\"ő is gondolna.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Jó öreg Griswold. Testvéremként szeretem. Együtt harcoltunk \"\n\"mikor... mi... Lázár... Lázár, Lázár, Lázár!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hahaha... szeretem Pipint. Tényleg próbálkozik, tudod. Figyelj ide, jobban \"\n\"meg kellene ismerned. Egy olyan jólélek mindig segíteni akar. Ettől épp \"\n\"olyan lesz, mint te, nem? Egy hős? Én is hős voltam egyszer...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt egy gyerek akinek még nálam is több problémája van, pedig azokban én is \"\n\"bővelkedem. Figyelj ide: az a gyerek sokszor megpróbál lehúzni, de tudom hol \"\n\"járt, érted...? Elvesztett egy lábat! Egy darab fával a helyén kell \"\n\"járkálnia. Olyan szomorú, annyira szomorú...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden a legjobb ember az egész városban. Szerintem a felesége engem annyira \"\n\"nem kedvel, de amíg teletölti a korsómat, engem ő sem fog zavarni. Úgy néz \"\n\"ki, hogy a legtöbb időmet Ogdennel töltöm, de ha egyszer ő annyira jó \"\n\"hozzám...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"El akarok mondani valamit, mert én tudok minden ilyesmiről. Ez a \"\n\"különlegességem. Ez itt a legjobb... a legeslegjobb! A többi semmire sem jó \"\n\"amióta azok mocskos fenevadak...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Senki sem figyel... figyel rám. Valahol, nem vagyok biztos hol, de valahol a \"\n\"templom alatt van egy nagy halom arany. Ragyog, csillog és csak arra vár, \"\n\"hogy valaki elvigye.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Tudom megvannak a saját ötleteid és nem fogod ezt elhinni, de az a fegyvered \"\n\"ottan... nem jó a nagy bestiák ellen! Jaj, nem érdekel mit mond Griswold, ma \"\n\"már semmi sem olyan, mint régen volt.\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Ha te lennék... nem vagyok... de ha lennék, eladnám minden holmidat és \"\n\"eltűnnék innen. Az a fiú ott... mindig van nála valami jó, de adnod kell \"\n\"némi aranyat vagy sose fogja megmutatni, hogy mije van éppen.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Érzem egy lélek közeledését, aki válaszokra vár...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"A bölcsességet ki kell érdemelni, nem lehet megkapni. Ha felfedezel egy \"\n\"írást, fald fel a szavait. Ha már van tudásod azokról a titkokról, jegyezd \"\n\"meg: mindig van hova növekednie a jártasságunknak.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"A legnagyobb hatalom gyakran a legrövidebb életű is. Találhatsz ősi \"\n\"varázsigéket, rég pergamenekre írva. Ezeknek a tekercseknek az ereje abban \"\n\"rejlik, hogy még egy gyakorlatlan mágus is megidézheti őket. A hátrányuk \"\n\"viszont az, hogy ehhez hangosan fel kell olvasni őket és nem tudod az \"\n\"elmédben eltárolni a jelentésüket. Tudd, hogy ezeket a tekercseket csak \"\n\"egyszer használhatod, szóval fontold meg jól, hogy mikor lesz ez.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"A nap hője felmérhetetlen nagy, de mégis egy puszta gyertyaláng nagyobb \"\n\"veszélyt jelent. Nincsen olyan erő, nem számít mekkora az, melyet nem lehet \"\n\"használni megfelelő összpontosítás nélkül. Sok varázsige megbűvölt pálcákba \"\n\"ültethető, amelyek számottevő varázserővel bírhatnak. Én vissza tudom őket \"\n\"állítani a régibe, de annak is meglesz majd a saját ára.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"A tudásunk összessége az emberek összessége. Ha találsz egy könyvet vagy \"\n\"tekercset mit nem tudsz értelmezni, ne félj, hozd ide hozzám. Én megpróbálom \"\n\"értelmezni és megosztom veled amit látok.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Egy férfinak ki csak a vasat ismeri, az acélnál nagyobb varázslat nem \"\n\"létezhet. A kovács Griswold nagyobb mágus, mint önmaga azt gondolná. A \"\n\"képessége, hogy irányítsa a tüzet és a fémet páratlan ezen a vidéken.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"A romlásnak az ereje az ármánykodásban rejlik, viszont az ártatlanság őrzi \"\n\"meg a tisztaság erejét. Ez a Júlia nevű fiatal hölgy tiszta szívű, a \"\n\"szükségleteit háttérbe helyezi a szülőjével szemben. Ő fél tőlem, de csak \"\n\"mert nem ért meg.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Egy láda nyílt ki a sötétségben, mely nagyobb kincset nem tartalmaz, mint a \"\n\"tény, hogy a világosságban nyitották ki. Káin egy fejtörő, de csak azoknak, \"\n\"akik nem figyelnek. A tudása a katedrális kapcsán nagyobb, mint amennyire \"\n\"azt ő is elmerné képzelni.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Minél magasabbra helyezed a hitedet egy emberben, annál mélyebbre tudsz \"\n\"zuhanni. Farnham elvesztette a lelkét, de nem valamiféle ördög miatt. Akkor \"\n\"veszett el, mikor látta, hogy a társait elárulja Lázár főérsek. Van tudása, \"\n\"mely olykor ránk ragyoghat, de el kell különítened a tényeket a \"\n\"képzelgésektől.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"A keze, a szíve és az elméje csodákra képes mikor tökéletes együttműködésben \"\n\"vannak. A gyógyító Pipin olyan dolgokat is lát a testen, miket még én sem. A \"\n\"képessége, hogy visszahozza a betegeket és sérülteket még nagyobb a széles \"\n\"rálátásától, melynek segítségével még bájitalokat is tud készíteni. \"\n\"Nagyszerű szövetséges ő itt Tristramban.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Sok dolog van a jövőben melyet nem láthatunkk, de mikor a gyerekekről van \"\n\"szó, ők lesznek azok, akik annak súlyát hordozni fogják. A kisfiú, Wirt \"\n\"lelkén sötétség hódol, de nem jelent veszélyt a városra vagy a lakóira. A \"\n\"titkos alkudozásai a kétes céhekkel sok olyan eszközhöz juttatják, melyhez \"\n\"Tristram nem férkőzhetne hozzá. Míg a módjai kicsit erőteljesen, Wirt nagy \"\n\"segítséget nyújthat a csatában a közelgő gonosszal szemben.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Puszta vályogfalak és szalmatetők nem tesznek ki egy otthont. A fogadós, \"\n\"Ogden fontosabb szerepet vállal a közösség szívében, mint azt sokan értenék. \"\n\"Menedéket ad Júliának és a szülőjének, fenntartja a megmaradt életet \"\n\"Farnhamban és egy fedezék mindenki számára, aki itt maradt ebben az elmúlt \"\n\"városban. A fogadója és az egyszerű örömök mik találhatóak ott, egy \"\n\"pillanatképet adnak arról az életről, amire az emberek emlékezni \"\n\"szeretnének. Egy emléket, mely táplálja bennük a reménységet, hogy lesznek \"\n\"még jobb idők ezen a helyen.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Hé... jer ide!\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Nem tudja mindenki hasznát venni, pláne nem megvenni, az összes dolognak mit \"\n\"találsz a labirintusban. Még én sem, ha nehéz is lehet elhinni.\\n\"\n\"\\n\"\n\"Néha csak te leszel egyedül képes jelentőséget adni egyes holmiknak.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Ne higgy el mindent amit az a részeg mond. A túl sok ital elködösítette a \"\n\"látását és a józan eszét.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Ha nem vetted volna észre, semmit sem veszek Tristramból. Én minőségi \"\n\"termékeket hozok be. Ha szemetet akarsz másra rásózni, látogasd meg \"\n\"Griswoldot, Pipint vagy azt a boszorkát, Adriát. Biztos vagyok benne, hogy \"\n\"felhappolnak mindent, bármit is tennél le eléjük...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Azt hiszem a kovácsmesternek köszönhetem az életemet... amennyi jutott \"\n\"belőle. Persze, Griswold felajánlott egy gyakornokságot a műhelyében és egy \"\n\"rendes fickó, de sose tudtam volna ott elég pénzt szerezni... nos, maradjunk \"\n\"csak annyiban, hogy vannak konkrét terveim, melyek nagyon, nagyon sok pénzt \"\n\"igényelnek.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Ha egy pár évvel idősebb lennék, elárasztanám minden széppel mivel csak \"\n\"bírnám és hidd el, nagyon értékes dolgokra bírok ám szert tenni. Júlia egy \"\n\"gyönyörű lány és el kellene hagyni Tristramit amint csak lehetséges. Talán \"\n\"magammal viszem majd mikor én is megyek...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Káin túl sokat tud. Halálra rémít, még jobban mint az az asszony a folyó \"\n\"túlpartján. Azt mondja, hogy milyen szerencsés vagyok, hogy élek, meg a \"\n\"történetemet megjósolták a legendák... szerintem csak elgu\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham, na ő egy komoly problémákkal küszködő ember és tudom milyen az. Túl \"\n\"sokat tett egy ember becsületére és Lázár a halál torkáig vezette. Tudom \"\n\"milyen ott lent, szóval ne is kezd el mesélni, hogy milyen terveid vannak a \"\n\"labirintusban rejlő gonosz elpusztítására. Csak vigyázz a lábadra inkább...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Amíg nem kell semmit sem visszavarratnod, Pipinnél jobb nincs is.\\n\"\n\"\\n\"\n\"Ha lett volna egy kicsit a főzeteiből, talán még mindig meglenne a lábam...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria tényleg nagyon zavar. Persze, Káin ijesztő, mert mindenféléket mond a \"\n\"múltadról, de az a boszorkány tényleg bele is lát a múltadba! Mindig \"\n\"megszerez mindent amit akar is valahogy. Több árúja van mint amit a királyi \"\n\"vásáron láttam, még a fesztiválok idején.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden egy bolond, hogy itt marad. Ki tudnám juttatni innen egy nagyon \"\n\"méltányos áron, de ragaszkodik az ostoba fogadójához. Gondolom legalább ad \"\n\"Júliának valami munkát és a felesége, Gárda is remek pitét süt...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"A hősök csarnokán túl nyúlik a koponya kamra. Örök halál vár mindenkire ki \"\n\"annak a teremnek a kincseire áhítozik. Így szólott a pusztulás ura és így is \"\n\"lesz.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...és így a vér kapuján túl, a lángok csarnokán át, a Virtus vár a fény \"\n\"hősére, hogy feltámadjon...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Látni látom mit te épp nem\\n\"\n\"fénylik s hamvas lesz a szép szem\\n\"\n\"Ahová fordulsz, ott nincsen\\n\"\n\"a halk fütty mögötted sincsen\\n\"\n\"\\n\"\n\"Ott meglátod mit nem lenne szabad\\n\"\n\"Hol fény lenne ott csak árny marad\\n\"\n\"Gyere világosság hű bajnoka\\n\"\n\"Mert itt vár rád a vakok csarnoka\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"A pokol fegyvertára ad otthon a vér hadurának. Nyomában ezer s ezer holttest \"\n\"hever. Angyalok és férfiak egyaránt hullottak, minden áldozat egyetlen egy \"\n\"célért: magáért a vérért.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Vésd eszedbe jól az igazat, mit itt látsz, mert ez a híres Horadrim végső \"\n\"hagyatéka. Egy háború dühöng itt éppen még most is, túl a mezőkön, melyeket \"\n\"ismerünk, a mennyek mesés királyságain és a poklok pusztító vereméin is túl. \"\n\"A háború, melyet a nagy küzdelemnek hívnak, mely régebb óta tart, mint mióta \"\n\"bármely csillag is ég az égen. Egyik oldal sem tud túl sokáig felülmaradni; \"\n\"a fény és a sötétség erői örökké viaskodni fognak maga az egész teremtés \"\n\"felett.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Vésd eszedbe jól az igazat, mit itt látsz, mert ez a híres Horadrim végső \"\n\"hagyatéka. Mikor az örökké tartó küzdelem a mennyek és poklok között a \"\n\"halandók földjére került, elnevezték a bűn háborújának. Angyalok és démonok \"\n\"járnak az emberiség között álcában, titokban harcolva, távol az esendők \"\n\"kíváncsiskodó szemeik elől. Pár merész, erős lélek szövetkezett is egyik-\"\n\"másik oldallal, vezetve ezzel a háború további alakulását.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Vésd eszedbe jól az igazat, mit itt látsz, mert ez a híres Horadrim végső \"\n\"hagyatéka. Közel háromszáz éve, az égő poklok három elsődleges gonosza \"\n\"rejtélyesen a mi világunkba érkezett. A három testvér évtizedeken keresztül \"\n\"pusztított a kelet vidékjein, míg az emberi faj csak reszketve menekült. A \"\n\"rendünket, a Horadrimot, egy csoport bölcs alkotta titokban, hogy egyszer s \"\n\"mindenkorra kelepcébe csalják és ismét elfogják a három gonoszt.\\n\"\n\"\\n\"\n\"Az eredeti Horadrim sikeresen megszerzett kettőt a három erős ereklye közül, \"\n\"melyeket lélekkőnek hívnak és elásták őket a kietlen sivatagi homok mélyére. \"\n\"A harmadik gonosz viszont elmenekült és nyugatra ment, nyomában sokakkal a \"\n\"Horadrim tagjai közül. Ez a harmadik gonosz, Diabló, a rettenet nagyura, a \"\n\"végén el lett fogva és az esszenciája egy lélekkőbe lett fogva, eltemetve a \"\n\"labirintus legmélyén.\\n\"\n\"\\n\"\n\"Légy figyelmeztetve, hogy a lélekkövet nem találhatja meg senki sem ki nem \"\n\"ebből a hitből van. Ha Diablo kiszabadulna, hamar találna magának egy \"\n\"gyenge, könnyen irányítható testet, talán egy öregemberét vagy egy gyerekét.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Szóval úgy lett, volt egy nagy forradalom az égő pokol mélyén melyet úgy \"\n\"hívtak, hogy a sötét száműzetés. Az alsóbb rosszak legyőzték a három nagy \"\n\"gonoszt és száműzték a szellemüket a halandók világába. Két démon, Belial, a \"\n\"hazugságok istene, és Azmodán, a bűn ura, maguknak követelték a pokol \"\n\"uralmát a három testvér hiányában. Az egész pokol megoszlott a két uralkodó \"\n\"érdekcsoportjai között és a mennyek sikeresen ostromolni tudták magának a \"\n\"pokolnak a kapuit is.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Sok démon utazott az élők világába a három testvér nyomában. Ezeket a \"\n\"démonokat a halandó világba követték az angyalok, akik szerte a kelet nagy \"\n\"városai között kiszagolták és levadászták őket. Az angyalok szövetkeztek a \"\n\"Horadrimme, a halandó mágusok titkos szövetségével, akik hamar mesterei \"\n\"lettek a démonok vadászatának. Sok-sok ellenségre tettek szert az alvilágban.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Szóval úgy történt, hogy a három nagy gonosz száműzve lett lelkek formájában \"\n\"a halandók világába és viszályt kezdtek okozni az emberek között évtizedeken \"\n\"keresztül, míg le nem vadászta a halandó Horadrim megátkozott rendje. A \"\n\"Horadrimok különleges ereklyéket használtak, melyek nevei a lélekkövek \"\n\"voltak. Ezen kövek segítségével sikerült elkapni Mephisto, a gyűlölet urának \"\n\"és Baalnak, a pusztítás urának az esszenciáját. A legfiatalabb testvér, \"\n\"Diabló, a rettenet nagyura, viszont elmenekült nyugatra.\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Minden dícséret Diablónak, a sötétség nagyurának, a sötét száműzetés \"\n\"túlélőjének. Mikor ő felébred a hosszú álmából, az uram és gazdám szólt \"\n\"nekem olyan titkokról, melyekről oly kevés halandó bír. Mesélt arról, hogy a \"\n\"mennyek és a poklok egy örökös küzdelemben állnak. Felfedte nekem azokat a \"\n\"rettenetes erőket, melyek viszályt hoztak az emberek világába. Az uram a \"\n\"harcot e világért úgy nevezte: a bűn háborúja.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Dicsőség és dicséret Diablónak, a sötétség nagyurának és a hármak vezérének. \"\n\"Az uram szólott nekem a két testvéréről: Mefisztóról és Baálról, akik már \"\n\"régóta száműzve lettek erről a világról. Az uram úgy óhajtotta, hogy \"\n\"szeretné összegyűjteni minden elérhető erejét mielőtt kiszabadítja a \"\n\"testvéreit a keleti sivatagok sírjaiból. Miután az uram kiengedi a \"\n\"testvéreit, a bűn háborúja még egyszer ismét a hármak haragja lesz.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Hála és áldozat Diablónak, a sötétség nagyurának és a lelkek rombolójának. \"\n\"Mikor felébresztettem a gazdámat az álmából, megpróbálta egy halandó testét \"\n\"magáénak tenni. Diabló előszőr megpróbálta Leorik királyét megszerezni, de \"\n\"túl gyenge volt a hosszú rabságtól. A sötét úrnak egy jámbor és egyszerű \"\n\"horgonyra van szüksége és a fiú kit Albernek hívnak, ideálisnak tűnt a \"\n\"számára. Amíg a jó Leorik király megbolondult Diabló sikertelen \"\n\"megszállásától, addig elloptam a fiút és a gazdám elé hoztam. Várom most \"\n\"türelmesen a parancsát és imádkozom érte, hogy meg fog jutalmazni mikor \"\n\"ennek a világnak az ura lesz.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Hála az égnek, hogy maga ismét itt van!\\n\"\n\"Sok minden változott azóta, barátom. Mindenütt békesség uralkodott, míg nem \"\n\"jöttek a sötét lovasok a semmiből és pusztítottál el a falunkat. Sokakat \"\n\"helyben lekaszaboltak, az ellenállókat pedig megölték, elvitték szolgának \"\n\"vagy egy még ennél is rosszabb lét várt rájuk. A templom a város szélén meg \"\n\"lett gyalázva és most sötét szertartások színhelyéül szolgál. Elkeseredett \"\n\"sikolyok vízhangja jön fel a mélységből, de lehet, hogy vannak még \"\n\"szerencsés túlélők odalent. Kövesse ezt az ösvényt a fogadóm és a műhely \"\n\"között mely egyenesen levisz a templomba és mentsen meg akit csak tud.\\n\"\n\"\\n\"\n\"Mesélni fogok még többet majd legközelebb, de most siessen! Sok sikert.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Kövesd a küldetésed.  Megtalálni az elveszett kincset nem könnyű.  \"\n\"Megtalálni egy elrejtett kincset még kevésbé.  Ennyit tehetek most.  Ne \"\n\"hagyd, hogy az idő homokja elbizonytalanítson a keresésedben.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Micsoda?!  Mekkora bolondság.  Nincs semmiféle kincs itt Tristramban.  Hadd \"\n\"lássam!  Á, ezek a rajzok pontatlannak tűnnek.  Ez egyáltalán nem hasonlít a \"\n\"városunkra.  Emlékeztetnélek, hogy mi rejlik a katedrális alatt és ne \"\n\"foglalkozz azzal, hogy mi rejlik itt a gyep alatt.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Tényleg nincs most időm erről a térképről beszélni.  Sok-sok beteg embernek \"\n\"kell segítség és ők is számítanak magára.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Az egykor oly büszke Iswall csapdába esett e világ mélységeiben.  A \"\n\"becsületétől megfosztották és a képét eltorzították.  Halhatatlan kárhozatba \"\n\"lett zárva.  Megszállott módon próbálja elrejteni az egyetlen dolgot, mi \"\n\"kiszabadíthatja.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Lefogom, hogy Wirt látta, hogy jössz és csak azért adta elő ezt a \"\n\"színjátékot, hogy később nevethessen rajtad, hogy a városban szimatolsz a \"\n\"nagy semmiért.  Én nem foglalkoznék vele.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Volt egy időszak mikor a városunk egy gyakori megálló volt utazók számára a \"\n\"világ minden tájáról.  Sok-sok minden változott azóta.  De barlangok mélyén \"\n\"elrejtett és elásott kincsek; gyermekek gyakran képzelnek ilyeneket.  Wirt \"\n\"nem szokott gyerekes játékokkal foglalkozni.  Lehet csak a képzeletének a \"\n\"szüleménye.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Figyelj, gyere közel.  Nem tudom, hogy tudod-e amit én, de tényleg \"\n\"Istenigazából van itt valami.  Egy térkép.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"A nagymamám gyakran mesél történeteket furcsa erőkről, melyek a templom \"\n\"közelében található temetőt lakják.  Lehet szívesen meghallgatnád az \"\n\"egyiket.  Azt mondta, hogy ha egy elégséges áldozatot hagysz a temetőben, \"\n\"bemész a katedrálisba imádkozni a holtakért, majd visszatérsz, az áldozatod \"\n\"valamilyen fura módon meg lesz változtatva...  Nem tudom, hogy ezek csak egy \"\n\"öreg, beteg asszony képzelgéseie, de manapság bármi lehetséges lehet.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Egy hatalmas, titokzatos kincs, azt mondod.  Talán szívesen beszereznék \"\n\"egyet s mást tőled.  Vagy még jobb, elláthatlak ritka és értékes \"\n\"felszerelésekkel ehhez a feladathoz?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Szóval, te vagy az a hős, akiről mindenki beszélt. Talán segíthetnél egy \"\n\"szegény gazdának is egy szorult helyzetben. A kertem végében, pont délen, \"\n\"valami borzasztó dolog duzzadt ki a földből! Nem tudok eljutni a szénámhoz \"\n\"és a szegény tehenek éhezni fognak. A boszorkány ezt adta nekem és azt \"\n\"mondta, hogy azzal fel lehet robbantani azt a dolgot ott a mezőn. Ha valaki \"\n\"el tudná pusztítani azt ott, nagyon hálás lennék. Magam is megtudnám, de \"\n\"valakinek őriznie kell a teheneket...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Tudtam, hogy nem lesz olyan egyszerű, mint ahogy a boszorkány mondta. \"\n\"Szomorú világ, ahol már a szomszédjainkban sem bízhatunk.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Eltűnt? Visszaküldted a Hadész mélyére? Hogy? Ne mondd, hogy elvesztetted! \"\n\"Nem lehet olcsón egy olyat beszerezni, ugye tudod? Keresd meg és robbantsd \"\n\"ki azokat a rémségeket a városból.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Egy robbanást hallottam onnan! Sok köszönet, kedves idegen. Azokkal a \"\n\"rémségekkel a földből, a szörnyek amik elfoglalták a templomot, satöbbi, \"\n\"igen nehéz időket élünk. Én csak egy szegény gazda vagyok, de fogadd el ezt, \"\n\"együtt az őszinte hálámmal.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Jaj, mekkora bajban vagyok... esetleg... nem, nem tenném rád ezt a terhet a \"\n\"többi mellé. Talán ha sikerült kitisztítanod a templomot azoktól a \"\n\"rémségektől, akkor esetleg lenne egy kis időd segíteni ennek a szegény \"\n\"gazdának?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Uuuááá! (szip) Uuuááá! (szip)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Elvesztettem Tiót!  Elvesztettem a legjobb bavátomat!  Együtt játszottunk a \"\n\"folyónál és Tió azt mondta, látni szeretné ott azt a zöld dolgot. Én azt \"\n\"mondtam, szevintem nem kellene, de odamentünk és hivtelen egy nagy BOGÁJ \"\n\"jött elő a semmiből! Megpvóbáltunk elmenekülni, de Tió elesett és a bogáj \"\n\"MEGVAGADTA és elvitte magával!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Nem találtad meg?  Meg kell találnod Tivadavt, kéjlek!  Olyan kicsi.  Nem \"\n\"élné túl egyedül...  Kéjlek!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Megtaláltad!  Megtaláltad!  Köszönöm!  Jaj, Tió, nagyon megijesztettek azok \"\n\"a csúnya bogajak?  Jaj!  Fúj!  Valami a bundádhoz vagadt!  Gyejünk, Tíó, \"\n\"menjünk haza.  Köszönöm ismét, hősembej!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Régóta vártunk nyugovóban és az óránk végre elérkezett.  A hosszú álmot \"\n\"követően mélyen éhezünk és hamarosan lakmározni fogunk...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Jól érzed magad, kisemlős?  Szánalmas. Ha ez a legtöbb mit e világ nyújtani \"\n\"tud, akkor könnyebb dolgunk lesz, mint gondoltuk volna.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Ezek a vidék meg lesz gyalázva, a fajunk el fogja lepni e földeket, melyeket \"\n\"az embernép otthonának nevezett.  A csápjaink szét fogják tépni e világot és \"\n\"lakmározni fogunk a lakóinak húsán.  Szolgasor vár rátok és ti lesztek a \"\n\"táplálékunk.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"Érzünk téged... közel vagy! Közel! A vér és félelem szaga!\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"És az arany fény évében úgy lett határozva, hogy egy nagy katedrális legyen \"\n\"megépítve itt. E megszentelt hely sarkköve egy átlátszó, Antyrael nevezetű \"\n\"kőből készült, mely a nevét arról az angyalról kapta, ki a Horadrim renddel \"\n\"megosztotta az erejét.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Mú.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Mondom: mú.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Nézd, csak egy közönséges marha vagyok, rendicsek?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Jó, jó.  Igazából nem is vagyok egy marha.  Általában nem szoktam így \"\n\"öltözködni.  Otthon voltam, tettem a dolgomat és hirtelen ezek a bogarak és \"\n\"tövisek és csírák és minden más cuccos kezdett kijönni a padlóból... rémes, \"\n\"rémes volt.  Ha legalább lenne valami rendes göncöm, talán akkor nem lenne \"\n\"olyan rossz.  Hé... vissza tudnám menni a házamba és el tudnád hozni nekem a \"\n\"ruhámat?  A barnát, ne a szürkét, az ünnepi alkalmakra van, tudod.  Magam is \"\n\"megtenném, de nem akarom, hogy bárki is így meglásson...  Itt van, vidd ezt, \"\n\"lehet szükséged lesz rá, hogy megöld azokat a cuccokat, amik mindent \"\n\"benőttek.  A házamat nem fogod tudni eltéveszteni. Ott van a \"\n\"folyótalálkozástól délre, az amelyre rátelepedett az a zöldséges kert.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Mire vársz még?  Hozd már el a ruhámat!  És siess!  Az a marha ott egyre \"\n\"gyorsabban kacsintgat rám!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hé, itt van a ruha?  Gyorsan add ide!  Úgy viszket a fülem, hogy el sem \"\n\"hinnéd!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Ne! Nem, nem, nem!  Ez a SZÜRKE ruhám!  Ünnepi alkalmakra!  Esküvőkre!  \"\n\"Mégis hogyan hordhatnám ezt?  Valami bolondnak tartasz?  A BARNA ruhára van \"\n\"szükségem.  Hozd!\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Sokkal jobb.  Hú!  Végre.  Egy kis méltóság!  Egyenesen állnak a szarvaim?  \"\n\"Jól van.  Nézd, köszi a segítséget.  Itt van, vidd el ezt az ajándékot.  És \"\n\"tudod, egy kis... divat tanács... rád férne egy kis... tudod... új... tudod, \"\n\"hogy értem!  Ez az egész kalandor stíl manapság olyan... túl retró, tudod?  \"\n\"Csak egy gyors tipp volt, oké?  Csaó!\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Nézd.  Én egy marha vagyok.  Te meg egy szörnycsali. Legyen még egy kicsit \"\n\"több év az önéletrajzodban és utána beszélhetünk.\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Tényleg félelmetes feladatot tehetettem most eléd. Bárcsak tudnék \"\n\"segíteni... egy kis friss tej esetleg?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Jaj, szükség lenne a segítségedre, de talán előbb mentsd meg a sírkamrákat \"\n\"azoknak a fenevadaknak a gyalázásától. Kicsit nagyobb biztonságban érezném \"\n\"magam.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Valamit meg kellene tenni, de nem tudnám jó szívvel egy idegenre bízni ezt. \"\n\"Talán miután kicsit jobban belejössz az itteni dolgokba, akkor én is \"\n\"kényelmesebben ruháználak fel egy ilyesmi feladattal.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Látom a nagy lehetőségeket benned.  Talán miközben beteljesíted a \"\n\"végzetedet, be tudnál egy kicsit ide is ugrani és megtenni nekem egy \"\n\"szívességet?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Szerintem tudnál nekem segíteni, de talán csak miután egy icipicit erősebb \"\n\"leszel. Nem tudnék együtt élni azzal a tudattal, hogy én miattam sérült meg \"\n\"a város egyetlen reménysége!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Én? Csak egy feltörekvő tehén vagyok.  Kezdj te is valamihez magaddal és \"\n\"utána beszélhetünk.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Nem kell szabadkoznom minden erre tévedt turistának!  Nincsenek ilyen \"\n\"szörnyek vagy mik, amiket meg kellene ölnöd?  Talán később beszélünk.  Ha \"\n\"addig túléled...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Ne zavarj már!  Egy igazi hősre várok.  És te nem vagy az.  Nem tudlak \"\n\"ilyenekkel megbízni, bármelyik pillanatban felfalhatnak a szörnyek.  Nekem \"\n\"egy tapasztalt hős kell.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Jó, nem húzlak többet a szarvadnál.  Nem akartalak félre vezetni.  Otthon \"\n\"űltem, múúslakodva, mikor hirtelen megremegett minden és egy egész csorda \"\n\"szörny mászott ki a padlóból.  Épp ez a gönc volt rajtam mikor kirohantam és \"\n\"most úgy tűnhetek, mint egy marha.  Általában nem szoktam így öltözködni.  \"\n\"Ha legalább lenne valami rendes holmim, talán akkor nem lenne olyan rossz.  \"\n\"Hé... vissza tudnám menni a házamba és el tudnád hozni nekem a ruhámat?  A \"\n\"barnát, ne a szürkét, az ünnepi alkalmakra van, tudod.  Magam is megtenném, \"\n\"de nem akarom, hogy bárki is így meglásson...  Itt van, vidd ezt, lehet \"\n\"szükséged lesz rá, hogy megöld azokat a cuccokat, amik mindent benőttek.  A \"\n\"házamat nem fogod tudni eltéveszteni. Ott van a folyótalálkozástól délre, az \"\n\"amelyre rátelepedett az a zöldséges kert.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Próbáltam varázsigéket, fenyegetéseket, zsarolást, alkudozást ezzel a rút \"\n\"lénnyel, mindhiába. A módszereim melyekkel gyengébb démonokat szolgasorba \"\n\"taszíthatok, félek ennél a borzasztó rémségnél már nem használnak.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Az otthonomat lassan megrontja ennek a kéretlen fogolynak a romlottsága.  A \"\n\"kripták tele vannak árnyakkal, melyek a szemem sarkában mozognak.  Karmok \"\n\"halk kaparása táncol és gyötri a hallásomat.  Kutatnak. Úgy vélem ez a napló \"\n\"kell nekik.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"A dühöngése közben e teremtmény elszólta a nevét: Na-Krul.  Megpróbáltam \"\n\"utána kutatni ennek a névnek, de más démonok valahogy az egész könyvtáramat \"\n\"megsemmisítették.  Na-Krul... ez a név hűs rettenettel jár át.  Inkább \"\n\"gondolok rá úgy, mint a Teremtmény, semmint töprengek tovább a valódi nevén.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"A foglyul ejtett teremtmény ordítása miatt képtelen vagyok még alvásra is.  \"\n\"Dühösen kiállt afelé, ki ebbe az ürességbe száműzte és rút átkokat bocsát \"\n\"rám, hogy itt tartom.  A szívemet rettenettel tölti el, de mégsem tudom \"\n\"kizárni sehogy sem a hangját.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Az időm gyorsan kifogy.  Le kell jegyeznem a módját annak, hogy mivel \"\n\"lehetne ezt a démont legyengíteni, majd elrejteni ezt a szöveget, nehogy a \"\n\"csatlósai felhasználják ezt a tudást az uruknak a kiszabadítására.  Remélem, \"\n\"hogy ki megtalálja ezt a naplót, keresni fogja ezt a tudást.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Ki megtalálja ezt a tekercset hasonlóan elkötelezett lehet a szörnyszülött \"\n\"megállítását illetően.  Az én időm lejárt. A pokoli csatlósainak a karmai \"\n\"ebben a pillanatban is ezt a rozoga ajtót kaparásszak itt előttem.\\n\"\n\"\\n\"\n\"Megbűvöltem ezt a démont és hatalmas vastag falak mögé zártam, de félek az \"\n\"sem lesz elég.\\n\"\n\"\\n\"\n\"A varázsigék a három iratban a kamrája előtt védelmet fognak neked nyújtani, \"\n\"de csak ha a megfelelő sorrendben olvasod el őket.  A karok kiszabadítják a \"\n\"démont; hozzájuk ne nyúlj!  Csak a varázsigéket használd, különben az ereje \"\n\"lehet túl hatalmas lesz még neked is!\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Pokoldisznó\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Fullánk\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Árgus\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Pók\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Kétfejű\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Pattanásszülött\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Méregfarok\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Halálgömb\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Pók királynő\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Bélféreg\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Fáklyalény\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Pokolpoloska\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Sírásó\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Koporsópatkány\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Tűzvér\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Koponyaszárny\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Szellem\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Kripta démon\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Pokolvér\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Csont démon\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Ősszellem\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biklopsz\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Húslény\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Kaszás\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Óriás ökle\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Merkúr gyűrűje\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Xorine gyűrűje\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Karik gyűrűje\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"A magma gyűrűje\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"A látnokok gyűrűje\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"A vihar gyűjűre\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"A távolságtartó nyaklánc\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Szúnyogfullánk\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Tűzfáklya\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"A borússág páncélja\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Villámostor\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Vihartaps\"\n\n# Fehér kard\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Lélekfaló\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Gyémántpenge\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Csont láncing\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Démonkovácsolt páncél\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"A szektavezér nyaklánca\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"A gladiátor gyűrűje\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Bolondos\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Üveg\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Alakváltó\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"veszélyes\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"rothadó\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"fertőző\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Feltöltődés\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"a napkeleti bölcstől egy\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"bolondos\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Villámfal\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Felgyújtás\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Menekülés\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Visszaverés\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Téboly\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Tűzgyűrű\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Keresés\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"A tűz rúnája\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"A fény rúnája\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"A nóva rúnája\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"A felgyújtás rúnája\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"A kő rúnája\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \".\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Gamma csökkentése\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Gamma növelése\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Folytatás a városból\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Megpróbál a padlóra dobni egy tárgyat?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Az új kép kirajzolása előtt vár a függőleges szinkronizációra. Ha \"\n#~ \"szakadást észlelünk a képernyőn, segíthet a bekapcsolása. A kikapcsolása \"\n#~ \"egyes rendszereknél segíthet, ha az egerünk akadozik.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Képráta korlátozó\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Korlátozza a képrátát a magas processzor kihasználtság elkerülése végett. \"\n#~ \"Figyelembe veszi a képfrissítése rátát is.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Találat\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Megsemmisíthetetlen,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Nem szükséges hozzá semmi\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Szív\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Beállítások:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"verzió {:s}\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"A térkép nem érhető el a városban\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"visszahoz valakit az életbe\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"halálos gyógyítás\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"csökkenti az erőt\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"csökkenti az ügyességet\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"csökkenti az egészséget\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"nem tudsz gyógyítani\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"az eltalált szörny nem gyógyul (?)\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Gyorsabb támadás\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"hőlátás\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Nem sikerült kinyitni a játékos fájlját írásra.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Nem sikerült a mentés fájl olvasása\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Nem sikerült a mentés fájl írása\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"A hősök csarnokán túl nyúlik a koponyák kamrája.  Örök halál vár bárkire, \"\n#~ \"ki e terem kincseit magáénak akarja tudni. Így szólott a rettenet \"\n#~ \"nagyura, így is lett.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"A pokol fegyvertára ad otthon a vér hadurának.  Nyomában ezer s ezer \"\n#~ \"holttest hever.  Angyalok és férfiak egyaránt hullottak, minden áldozat \"\n#~ \"egyetlen egy célért: magáért a vérért.\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Felhős és hűvös a mai nap.  Az alvilág hálóit vetve az ürességbe, két \"\n#~ \"újfajta szálló rettenetre bukkantam.  Nem rossz egy napra.  Eszembe kell, \"\n#~ \"hogy jusson, hogy szerezzek még egy kis denevér guanót és fekete \"\n#~ \"gyertyákat Adriátől, lassan elfogy.\"\n"
  },
  {
    "path": "Translations/it.po",
    "content": "# Translation of DevilutionX to Italian\n# ZUMA <ztg.zuma@gmail.com>, 2003.\n# Krenim, 2003.\n# Kaire, 2003.\n# RoBBiE, 2003.\n# EXECUTOR, 2003.\n# Supervinny, 2003.\n# Y3k...again, 2003.\n# RoBBiE, 2003.\n# NightRainbow, 2003.\n# Gianluca Boiano <morf3089@gmail.com>, 2022.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: 2025-10-02 15:20+0200\\n\"\n\"Last-Translator: Gianluca Boiano <morf3089@gmail.com>\\n\"\n\"Language-Team: zuminator.altervista.org\\n\"\n\"Language: it\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Design di Gioco\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Designer Senior\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Design Supplementare\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Programmatore Principale\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Programmatori Senior\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programmazione\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Programmatori Ospiti Speciali\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Programmazione Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Programmazione Comunicazioni Seriali\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Sviluppo Installer\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Direttori Artistici\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Grafica\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Illustrazione Tecnica\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Direttori Artistici Cinematiche\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"Grafica Filmati 3D\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Illustrazione Tecnica Cinematiche\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Produttore Esecutivo\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Produttore\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Produttore Associato\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Musica\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Design Suono\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Musica e Suono Cinematiche\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Produzione Voci, Regia e Casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Sceneggiatura e Storia\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Elaborazione Voce\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Voci\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Tecnico di Registrazione\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Progetto e Impaginazione Manuale\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Grafica Manuale\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Direttore Provvisorio QA (Responsabile Tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Squadra d'Assalto QA (Tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Squadra Special Ops QA (Tester Compatibilità)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Supporto d'Artiglieria QA (Tester Aggiuntivi) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Controspionaggio QA\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Ordine dei Servizi di Informazione di Rete\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Assistenza Clienti\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Vendite\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Babbeo\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Cori di Sottofondo di Mr. Dabiri\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Pubbliche Relazioni\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Vendite Internazionali\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Vendite in US\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Produzione\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Legale e Commerciale\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Ringraziamenti Speciali\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Ringraziamenti\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"In ricordo di\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Ringraziamenti Speciali\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Responsabile Generale\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Ingegnere del Software\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Direttore Artistico\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Artisti\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Progettazione\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Sonoro, Effetti e Ingegneria del Suono\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Responsabile Controllo Qualità\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Tester\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Manuale\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tLavoro Supplementare\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Sceneggiatura Missioni\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Ringraziamenti\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tRingraziamenti Speciali a Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Responsabile Controllo Qualità\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Tester Responsabile Controllo Qualità\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Tester Principali\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Tester Supplementari\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Responsabile Marketing di Prodotto\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Responsabile Pubbliche Relazioni\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Responsabile Prodotto Associato\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"L'Anello dei Mille\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\"\n\"\\tNessuna anima è stata venduta durante la realizzazione di questo gioco.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Scegli Classe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Annulla\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Nuovo Eroe Multi Giocatore\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Nuovo Eroe Giocatore Singolo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Salvataggio Esistente\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Carica Partita\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Nuova Partita\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Personaggi Giocatore Singolo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Il Ladro e il Mago sono disponibili solo nella versione completa di Diablo. \"\n\"Visita https://www.gog.com/game/diablo per acquistare.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Inserisci Nome\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Nome non valido. Non può contenere spazi, caratteri speciali, o parole \"\n\"speciali.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Impossibile creare il personaggio.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Livello:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Forza:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magia:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Destrezza:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalità:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Salvataggio:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Eroe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Nuovo Eroe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Elimina\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Personaggi Multi Giocatore\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Elimina Eroe Multi Giocatore\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Elimina Eroe Giocatore Singolo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Sei sicuro di voler eliminare il personaggio \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Giocatore Singolo\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Multi Giocatore\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Impostazioni\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Supporto\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Ringraziamenti\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Esci da Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Esci da Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Demo\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Client-Server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Non In Linea\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Multi Giocatore\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Requisiti:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"senza gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Connessione\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Cambia Gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Tutti i computer devono essere connessi ad una rete TCP compatibile.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Tutti i computer richiedono una connessione ad internet.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Gioca da solo senza esporti sulla rete.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Giocatori Supportati: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Demo Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Demo Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"L'host sta eseguendo un gioco diverso dal tuo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"L'host sta eseguendo una modalità di gioco ({:s}) diversa dalla tua.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"La tua versione {:s} non corrisponde all'host {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Descrizione:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Azione\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Crea Partita\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Crea Partita Pubblica\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Unisciti alla Partita\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Partite Pubbliche\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Caricamento...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Nessuno\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ANNULLA\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Crea una nuova partita con difficoltà a tua scelta.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Crea una nuova partita pubblica dove chiunque può partecipare con difficoltà \"\n\"a tua scelta.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Inserisci l'ID Partita per unirti ad una partita già in corso.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Inserisci un IP o host per unirti ad una partita già in corso.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Unisciti ad una partita già in corso.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normale\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Incubo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Inferno\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Difficoltà: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Ritmo: Normale\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Ritmo: Veloce\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Ritmo: Molto veloce\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Ritmo: Velocissimo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Giocatori: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Difficoltà\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Unisciti a Partite {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Inserisci ID Partita\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Inserisci indirizzo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Difficoltà Normale\\n\"\n\"Qui è dove un personaggio agli inizi dovrebbe intraprendere la missione per \"\n\"sconfiggere Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Difficoltà Incubo\\n\"\n\"Gli abitanti del Labirinto sono stati rafforzati e la sfida si dimostrerà \"\n\"ardua. Raccomandato solo per personaggi esperti.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Difficoltà Inferno\\n\"\n\"La più potente delle creature degli inferi si nasconde alle porte \"\n\"dell'Inferno. Solo i personaggi più esperti dovrebbero avventurarsi in \"\n\"questo regno.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Il tuo personaggio deve raggiungere il livello 20 prima di poter partecipare \"\n\"al multi giocatore di difficoltà Incubo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Il tuo personaggio deve raggiungere il livello 30 prima di poter partecipare \"\n\"al multi giocatore di difficoltà Inferno.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Ritmo di Gioco\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Veloce\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Molto Veloce\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Velocissimo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normale\\n\"\n\"Qui è dove un personaggio agli inizi dovrebbe intraprendere la missione per \"\n\"sconfiggere Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Veloce\\n\"\n\"Gli abitanti del Labirinto sono stati velocizzati e la sfida si dimostrerà \"\n\"ardua. Raccomandato solo per personaggi esperti.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Molto Veloce\\n\"\n\"La maggior parte dei mostri del sotterraneo ti cercheranno più velocemente \"\n\"che mai. Solo un campione esperto dovrebbe tentare la fortuna a questa \"\n\"velocità.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Velocissimo\\n\"\n\"I tirapiedi degli inferi si precipiteranno ad attaccare senza esitazione. \"\n\"Solo un vero demone della velocità dovrebbe entrare a questo ritmo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Inserisci Password\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Entra in Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Passa a Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Si\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"No\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Premi i tasti del gamepad per cambiare.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Tasto associato:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Premi qualsiasi tasto per cambiare.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Disassocia tasto\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Associa combinazione di tasti:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Disassocia combinazione di tasti\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Menu Precedente\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Gestiamo un server di chat su Discord.gg/devilutionx Segui i link per unirti \"\n\"alla nostra community dove parliamo di cose relative a Diablo e \"\n\"all'espansione Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX è gestito da Diasurgical, ogni problema può essere segnalato a \"\n\"questo indirizzo: https://github.com/diasurgical/devilutionX Per aiutarci a \"\n\"servirti meglio, assicurati di includere il numero di versione, sistema \"\n\"operativo, e la natura del problema.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Avvertenze:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX non è supportato o gestito da Blizzard Entertainment, o da \"\n\"GOG.com. Né Blizzard Entertainment né GOG.com hanno testato o certificato la \"\n\"qualità o la compatibilità di DevilutionX. Tutte le domande su DevilutionX \"\n\"dovrebbero essere dirette a Diasurgical, non a Blizzard Entertainment o \"\n\"Gog.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tQuesto port utilizza Charis SIL, New Athena Unicode, Unifont e Noto \"\n\"concessi in licenza SIL Open Font License, nonché Twitmoji concesso in \"\n\"licenza CC-BY 4.0. Il port utilizza anche SDL, concesso in licenza zlib-\"\n\"license. Consulta il ReadMe per ulteriori dettagli.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Errore\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Si è verificato un errore alla linea: {:s} {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Errore File Dati\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Impossibile aprire l'archivio dati principale ({:s}).\\n\"\n\"\\n\"\n\"Assicurati che sia nella cartella del gioco.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Errore di Cartella in Sola Lettura\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Impossibile scrivere nella posizione:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Partita: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Partita Non In Linea\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Password: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Partita Pubblica\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Livello: Covo {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Livello: Cripta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Città\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Liv. : {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Invio\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Dettagli Personaggio\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Missioni\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Mappa\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Menu Principale\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventario\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Libro di magia\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Invia Messaggio\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Comandi Disponibili:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Comando \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" sconosciuto.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Descrizione: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parametri: Nessun parametro ulteriore richiesto.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parametri: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Le arene sono supportate solo in multigiocatore.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Quale arena vuoi visitare?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Numero di arena non valido. I numeri validi sono:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"Per entrare in un'arena, devi essere in città o in un'altra arena.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Ispezione supportata solo in multigiocatore.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Ispezione giocatori interrotta.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Nessun giocatore trovato con un nome simile\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Ispezione del giocatore: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Mostra guida generale o la guida per un comando specifico.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[comando]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Entra in un'Arena PvP.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<numero-arena>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Fornisce Pozioni in Arena.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<numero>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Ispeziona le statistiche e l'equipaggiamento di un altro giocatore.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<nome giocatore>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Mostra dettagli seed per il livello attuale.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Amichevole\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Attacco giocatore\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Tasto: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Seleziona magia corrente\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Tasto: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Abilità\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Magia\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Liv. Magia 0 - Inusabile\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Livello Magia {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Pergamena {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Pergamena\"\nmsgstr[1] \"{:d} Pergamene\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Verga di {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Carica\"\nmsgstr[1] \"{:d} Cariche\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} moneta\"\nmsgstr[1] \"{:s} monete\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Requisiti inadeguati\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Livello: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Punti Ferita {:d} di {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Clic destro per usare\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Su di Livello\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Possiedi {:s} moneta d'oro. Quante ne vuoi rimuovere?\"\nmsgstr[1] \"Possiedi {:s} monete d'oro. Quante ne vuoi rimuovere?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Portale Cittadino\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"da {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portale verso\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"L'Altare Sacrilego\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"livello 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Impossibile caricare dati dal file {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} è incompleto, per favore controlla il contenuto del file.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"Il tuo file {0} non ha le colonne attese, per favore assicurati che \"\n\"corrisponda al formato documentato.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Valore non numerico {0} per {1} in {2} alla riga {3} e alla colonna {4}\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Valore fuori intervallo {0} per {1} in {2} alla riga {3} e alla colonna {4}\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Valore non valido {0} per {1} in {2} alla riga {3} e alla colonna {4}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Mostra questo messaggio ed esci\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Mostra versione ed esci\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Specifica la cartella di diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Specifica la cartella dei salvataggio\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Specifica la posizione di diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Specifica il codice lingua (ad es. en o pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Salta video iniziali\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Mostra fotogrammi al secondo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Abilita log dettagliato\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Registra un file demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Riproduci un file demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Disabilita limitazioni di frame in riproduzione demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Selezione gioco:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Forza modalità Demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Forza modalità Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Forza modalità Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Opzioni Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Segnala gli errori a https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"Aggiorna devilutionx.mpq e fonts.mpq all'ultima versione\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Caricamento risorse di interfaccia fallito.\\n\"\n\"\\n\"\n\"Assicurati che devilutionx.mpq sia nella cartella di gioco e aggiornato.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Aggiorna fonts.mpq all'ultima versione\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Timeout di rete --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- In attesa di giocatori --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Nessun aiuto disponibile\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"mentre nei negozi\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Oggetto cintura {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Usa oggetto in cintura.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Magia rapida {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Tasti per abilità o magia.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Magia rapida precedente\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Seleziona la precedente magia rapida (cicla).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Magia rapida successiva\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Seleziona la successiva magia rapida (cicla).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Usa pozione di guarigione\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Usa pozioni di guarigione dalla cintura.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Usa pozione del mana\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Usa pozioni del mana dalla cintura.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Speedbook\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Apri Speedbook.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Salvataggio rapido\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Salva la partita.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Caricamento rapido\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Carica la partita.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Esci dal gioco\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Chiude la partita.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Ferma eroe\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Interrompe la camminata e annulla le azioni in sospeso.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Visibiltà oggetto\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Mostra/nascondi oggetti a terra.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Attiva la visibilità di un oggetto\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Mostra/nasconde sempre gli oggetti a terra.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Attiva mappa\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Attiva se la mappa è disponibile.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Cicla tipo di mappa\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Opaco -> Trasparente -> Minimap -> Nessuno\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Apri Inventario.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Profilo\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Apri Dettagli Personaggio.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Missioni\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Apri Missioni.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Libro di magia\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Apri Libro di Magia.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Messaggio Rapido {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Usa Messaggio Rapido in chat.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Nascondi Finestre Informative\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Nasconde tutte le finestre informative.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Ingrandimento\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Ingrandisci Area di Gioco.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Sospendi Partita\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Sospende la partita.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Sospendi Partita (Alternativo)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\nmsgid \"Decrease Brightness\"\nmsgstr \"Riduci Luminosità\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Riduci luminosità schermo.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\nmsgid \"Increase Brightness\"\nmsgstr \"Aumenta Luminosità\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Aumenta luminosità schermo.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Aiuto\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Apri Guida.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Schermata\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Cattura una schermata.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Dettagli partita\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Mostra dettagli partita.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Registro Chat\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Mostra registro chat.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Ordina Inventario\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Ordina l'inventario.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Console\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Apre la console Lua.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Azione primaria\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Attacca mostri, parla coi cittadini, solleva e posiziona oggetti \"\n\"dell'inventario.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Azione secondaria\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Apri forzieri, interagisci con le porte, raccogli oggetti.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Azione di magia\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Lancia la magia attiva.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Annulla azione\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Chiudi menu.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Vai su\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Sposta il personaggio del giocatore in alto.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Vai giù\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Sposta il personaggio del giocatore in basso.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Vai a sinistra\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Sposta il personaggio del giocatore a sinistra.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Vai a destra\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Sposta il personaggio del giocatore a destra.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Resta fermo\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Tieni premuto per impedire al giocatore di muoversi.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Attiva/disattiva resta fermo\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Attiva o disattiva il movimento del giocatore.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Mappa\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Vai giù\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Vai a sinistra\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Sposta il personaggio del giocatore in alto.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Vai a destra\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Sposta mouse su\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Simula il movimento del mouse verso l'alto.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Sposta mouse giù\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Simula il movimento del mouse verso il basso.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Sposta mouse a sinistra\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Simula il movimento del mouse verso sinistra.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Sposta mouse a destra\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Simula il movimento del mouse verso destra.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Clic sinistro del mouse\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Simula il tasto sinistro del mouse.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Clic destro del mouse\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Simula il tasto destro del mouse.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Menu magia rapida con gamepad\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Tieni premuto per impostare o usare i tasti rapidi per la magia.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Navigazione menu con gamepad\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Tieni premuto per accedere alla navigazione del menu del gamepad.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Attiva/disattiva menu di gioco\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Apre il menu di gioco.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Partita salvata\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Nessuna funzione multigiocatore in demo\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Problemi con Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Non disponibile nella demo\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Spazio per salvare insufficiente\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Nessuna Pausa in città\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Si consiglia la copia su disco fisso\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Sincronizzazione fallita in multigiocatore\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Nessuna pausa in multigiocatore\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Salvataggio...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Stando fra i deboli si diventa forti\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Dalla distruzione si forgia nuova forza\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Chi difende raramente attacca\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"La spada della giustizia è impeccabile\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Il corpo prospera se lo spirito è guardingo\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Il potere del mana viene ricaricato\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Il tempo non può diminuire il potere dell'acciaio\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Non sempre la magia è come ci sembra\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Ciò che ebbe inizio ora ha fine\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"L'intensità vien data dalla saggezza\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"L'Arcano porta alla distruzione\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Che non può essere danneggiato o posseduto da nessuno\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Cremisi e Azzurro come il sole\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Conoscenza e saggezza al solito costo\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Bevi e rinfrescati\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Ovunque tu vada, eccoti qua\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"L'Energia viene dalla tua saggezza\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"La ricchezza inattesa fa sorpresa\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"La pazienza ti ricompensa se non sei avido\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Benedetto da un compagno benevolo!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Il fato può guidare le mani dell'uomo\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"La Forza è sostenuta dalla divina fede\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Il flusso della vita ti pervade\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"La strada è sgombra solo se vista dall'alto\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"La salvezza costa molta saggezza\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"La luce dell'intelletto ti rivela molte cose\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Gli ultimi potranno essere i primi\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"La generosità porta le sue ricompense\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Per usarlo devi essere di Livello 8.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Per usarlo devi essere di Livello 13.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Per usarlo devi essere di Livello 17.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Appresi arcani segreti!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Quello che non ti uccide...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"La conoscenza è potere.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Date e riceverete.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Si acquisisce una certa esperienza col tocco.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Non c'è nessun posto come casa.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"L'energia spirituale è ristorata.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Ti senti più agile.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Ti senti più forte.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Ti senti più saggio.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Ti senti più rinvigorito.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Ciò che può spezzare la volontà.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Cattedrale\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Catacombe\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Caverne\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Covo\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Cripta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Liv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"Difficoltà {}\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Nel Menu\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Impossibile collegarsi\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"errore: 0 byte ricevuti dal server\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\"Impossibile aprire il file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"I file MPQ potrebbero essere danneggiati. Si prega di verificare l'integrità \"\n\"dei file.\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq o spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Mancano alcuni MPQ di Hellfire\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Non tutti gli MPQ Hellfire sono stati trovati.\\n\"\n\"Si prega di copiare tutti i file hf*.mpq.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Risoluzione\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Corsa in Città\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Missione di Theo\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Missione della Mucca\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Raccolta Automatica Oro\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Raccolta Automatica Elisir\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Raccolta Automatica Unguento\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Raccolta Automatica in Città\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Ricarica Mana da Adria\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Auto Equipaggia Armi\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Auto Equipaggia Armatura\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Auto Equipaggia Elmi\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Auto Equipaggia Scudi\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Auto Equipaggia Monili\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Missioni Casuali\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Mostra Etichette Oggetto\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Auto Ricarica Cintura\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Disabilita Santuari Paralizzanti\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Raccolta Pozione di Guarigione\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Raccolta Pozione di Guarigione Totale\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Raccolta Pozione del Mana\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Raccolta Pozione del Mana Totale\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Raccolta Pozione di Giovinezza\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Raccolta Pozione di Giovinezza Totale\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Opzioni\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Salva Partita\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Menu Principale\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Esci dal Gioco\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Ritmo\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Musica Spenta\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Suoni\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Suoni Spenti\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pausa\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Tasti Rapidi:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Apri Guida\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Mostra Menu\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab: Mostra Mappa\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Spazio: Nascondi finestre\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Apri Speedbook\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Apri Libro di Magia\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Apri Inventario\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Dettagli Personaggio\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Apri Missioni\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Riduci luminosità\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Aumenta luminosità\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Ingrandisci Area di Gioco\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Ingrandisci Mappa\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Usa oggetto in Cintura\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:    Imposta tasti per abilità o magie\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Maiusc + Clic Sinistro: Attacca senza muoverti\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Maiusc + Clic Sinistro (in dettagli personaggio): Assegna tutti i punti\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Maiusc + Clic Sinistro (in inventario): Sposta oggetto nella cintura o \"\n\"equipaggia\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Maiusc + Clic Sinistro (in cintura): Sposta oggetto nell'inventario\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Movimento:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Tieni premuto il mouse durante un movimento, il personaggio continuerà a \"\n\"spostarsi in quella direzione.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Combattimento:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Tieni premuto 'Maiusc' e clicca col sinistro del mouse per attaccare senza \"\n\"muoverti.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Mappa:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Per accedere alla mappa, fai clic sul pulsante 'MAP' sulla Barra dei \"\n\"Dettagli o premi 'TAB' sulla tastiera. L'ingrandimento e la riduzione della \"\n\"mappa si effettuano con i tasti + e -. Lo scorrimento con i tasti freccia.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Raccolta di Oggetti:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Gli oggetti utilizzabili di piccole dimensioni, come pozioni o pergamene, \"\n\"vengono automaticamente posizionati nella tua cintura situata nella parte \"\n\"superiore della barra dell'Interfaccia. Quando un oggetto viene inserito \"\n\"nella cintura, in quella casella appare un piccolo numero. Gli oggetti \"\n\"possono essere utilizzati premendo il numero corrispondente o facendo clic \"\n\"destro del mouse sull'oggetto.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Oro:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Puoi selezionare una quantità specifica di monete da rilasciare facendo clic \"\n\"destro del mouse su una pila d'oro nell'inventario.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Abilità e Magie:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Puoi accedere alle abilità e magie facendo clic sinistro del mouse sul \"\n\"pulsante 'SPELLS' nella barra dell'interfaccia. Le magie memorizzate e \"\n\"quelle disponibili tramite la verga sono elencate qui. Fare clic sinistro \"\n\"del mouse sulla magia che si desidera lanciare renderà pronta la magia. Una \"\n\"magia pronta può essere lanciata semplicemente col clic destro del mouse \"\n\"nell'area di gioco.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Uso dello Speedbook per le Magie:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Facendo clic sinistro sul pulsante 'magia pronta' si aprirà lo 'Speedbook' \"\n\"che ti consente di selezionare un'abilità o una magia per uso immediato. Per \"\n\"usare un'abilità o una magia pronta, fai semplicemente clic destro del mouse \"\n\"nell'area di gioco.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Maiusc + Clic sinistro sul pulsante 'seleziona magia corrente' cancellerà la \"\n\"magia pronta.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Impostazione Tasti Magia:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Puoi assegnarne fino a quattro Tasti Rapidi per abilità, magie o pergamene. \"\n\"Inizia aprendo lo 'speedbook' come descritto nella sezione precedente. Premi \"\n\"i tasti F5, F6, F7 o F8 dopo aver evidenziato la magia che desideri \"\n\"assegnare.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Libri di Magia:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Leggere più di un libro aumenta la tua conoscenza di quella magia, \"\n\"permettendoti di lanciarla in modo più efficace.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Guida Hellfire Demo\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Guida Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Guida Diablo Demo\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Guida Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Premi ESC per uscire o le frecce per scorrere.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Impossibile creare la finestra principale\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Non c'è spazio per l'oggetto\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Unguento di Precisione\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Unguento di Maestria\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Unguento d'Acume\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Unguento di Morte\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Unguento d'Abilità\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Unguento da Fabbro\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Unguento di Fortezza\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Unguento di Permanenza\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Unguento di Tempra\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Unguento d'Impermeabilità\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} di {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1} {0} di {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} di {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{1} {0}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} di {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"dell'arma, aumenta\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"possibilità di colpire\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"aumenta di molto\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"possibilità di colpire dell'arma\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"potenziale danno\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"aumenta di molto dell'arma\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"potenziale danno - archi esclusi\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"riduce attributi richiesti\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"per usare armature o armi\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"ripristina 20% di\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"durabilità dell'oggetto\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"dell'oggetto, aumenta\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"durabilità corrente e massima\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"rende indistruttibile un oggetto\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"aumenta la classe armatura\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"di armatura e scudi\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"aumenta di molto la classe\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"armatura di armature e scudi\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"imposta trappola fuoco\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"imposta trappola fulmine\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"imposta trappola pietrificazione\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"recupero totale vita\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"recupero paziale vita\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"recupero parziale mana\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"recupero totale mana\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"aumenta forza\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"aumenta magia\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"aumenta destrezza\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"aumenta vitalità\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"recupero parziale vita e mana\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"recupero totale vita e mana\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(funziona solo nelle arene)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Clic destro per vedere\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Clic destro per usare\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Clic destro per leggere, poi\\n\"\n\"clic sinistro per bersaglio\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Clic destro per leggere\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Attiva per visualizzare\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Apri inventario\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Attiva per usare\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Seleziona dal libro di magia, poi\\n\"\n\"lancia per leggere\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Attiva per leggere\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} to mostrare\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} per usare\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Seleziona dal libro di magia,\\n\"\n\"poi {} per leggere\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} per leggere\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Liv. : {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Raddoppia le scorte d'oro\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Richiede:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Frz\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Des\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Libro di {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Orecchio di {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"possibilità di colpire: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% danno\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"colpo: {:+d}%, {:+d}% danno\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% armatura\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"classe armatura: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Resistenza Fuoco: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Resistenza Fuoco: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Resistenza Fulmine: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Resistenza Fulmine: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Resistenza Magia: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Resistenza Magia: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Resistenza Tutto: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Resistenza Tutto: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"magie aumentate di {:d} livello\"\nmsgstr[1] \"magie aumentate di {:d} livelli\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"magie ridotte di {:d} livello\"\nmsgstr[1] \"magie ridotte di {:d} livelli\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"livelli magia invariati (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Cariche extra\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} carica\"\nmsgstr[1] \"{:d} {:s} cariche\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Danno fuoco: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Danno Fuoco: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Danno Fulmine : {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Danno Fulmine : {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} alla forza\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} alla magia\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} alla destrezza\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} alla vitalità\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} a ogni attributo\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} danno dai nemici\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Punti Ferita: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana : {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"alta durabilità\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"durabilità ridotta\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"indistruttibile\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% bagliore\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% bagliore\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"frecce multiple per tiro\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"danno dardi infuocati: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"danno dardi infuocati: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"danno frecce fulminee: {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"danno frecce fulminee: {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"danno sfera infuocata: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"danno sfera infuocata: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"attaccante riceve1-3 danni\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"l'utente perde tutto il mana\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"assorbe metà danni trappola\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"respinge il bersaglio\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% danno contro demoni\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Ogni Resistenza è 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"colpo ruba 3% mana\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"colpo ruba 5% mana\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"colpo ruba 3% vita\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"colpo ruba 5% vita\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"penetra l'armatura dell'obiettivo\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"attacco rapido\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"attacco veloce\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"attacco molto veloce\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"attacco velocissimo\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Altra abilità (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"recupero veloce\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"recupero molto veloce\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"recupero velocissimo\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"blocco veloce\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"aggiunge {:d} punto al danno\"\nmsgstr[1] \"aggiunge {:d} punti al danno\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"velocità di gittata casuale\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"danno non comune\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"durabilità alterata\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"spada a una mano\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"perdita costante di punti ferita\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"sottrae vita\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"nessun requisito di forza\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"danno fulmineo: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"danno fulmineo: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"scariche fulminee al colpo\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"danno triplo occasionale\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"riduzione {:+d}% danno\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x danno a mostro, 1x a te\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Danno casuale 0 - 600%\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"dur ridotta, {:+d}% danno\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"extra AC contro demoni\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"extra AC contro non morti\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Mana spostato a Salute\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Salute spostato a Mana\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"danno: {:d}  Invulnerabile\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"danno: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"danno: {:d}-{:d}  Indistruttibile\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"danno: {:d}-{:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"armatura: {:d}  Indistruttibile\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"armatura: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Cariche: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"oggetto unico\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Sconosciuto\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Covo di Re Scheletro\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Camera d'Ossa\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Il Labirinto\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"L'Acqua Contaminata\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Covo dell'Arcivescovo Lazarus\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Arena della Chiesa\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Arena Inferno\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Arena del Cerchio della Vita\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Giù nel sotterraneo\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Per le catacombe\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Giù alle caverne\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Giù all'inferno\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Giù all'Alveare\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Giù nella Cripta\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Su al livello {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Su in città\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Giù al livello {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Giù da Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Su al livello del Covo {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Giù al livello della Cripta {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"La Pietra Angolare del Mondo\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Giù al livello della Cripta {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Torna al Livello {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Impossibile aprire file di salvataggio\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Salvataggio non valido\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Il Giocatore è in un livello esclusivo di Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Stato del gioco non valido\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Impossibile mostrare menu\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Bestia\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demone\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Non morto\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Tipo: {:s}  Uccisioni: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Tot. uccisioni : {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Punti Ferita: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Nessuna resistenza magica\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Resiste:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magia\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Fuoco\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Fulmine\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Immune:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Tipo: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Nessuna resistenza\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Nessuna Immunità\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Alcune Resistenze Magiche\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Alcune Immunità Magiche\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Impossibile aprire archivio in scrittura.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} ha usato una magia non valida.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} ha usato una magia illegale.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"'{:s}' (livello {:d}) si è unito alla partita\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"La partita è finita\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Impossibile ottenere dati di livello\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"'{:s}' ha abbandonato la partita\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"'{:s}' ha ucciso Diablo e ha lasciato la partita!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"'{:s}' disconnesso per timeout\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"'{:s}' (liv. {:d}) è già in partita\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Misterioso\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Nascosto\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Cupo\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Buffo\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Magico\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Sasso\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Religioso\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Incantato\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Taumaturgico\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Avvenente\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Sibillino\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Arcano\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Inquietante\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Divino\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Sacro\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Sacro\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Spirituale\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Sinistro\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Abbandonato\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Pauroso\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Calmo\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Segreto\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Ornato\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Luccicante\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Contaminato\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Untuoso\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Brillante\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"del Mendicante\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Sfavillante\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Scintillante\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Solare\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"di Murphy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Il Grande Conflitto\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"La Guerra: il Prezzo del Peccato\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"La Storia degli Horadrim\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"L'Esilio Oscuro\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"La Guerra del Peccato\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Il Legame dei Tre\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"I Reami dell'Aldilà\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"La Storia dei Tre\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Il Re Nero\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Diario: L'Incantesimo\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Diario: L'Incontro\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Diario: La Filippica\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Diario: Il Suo Potere Cresce\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Diario: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Diario: La Fine\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Un Libro di Magia\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Scheletro Crocifisso\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Leva\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Porta Aperta\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Porta Chiusa\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Porta Bloccata\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Tomo Antico\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Libro della Viltà\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Leva con Teschio\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Libro Mitico\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Cofanetto\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Baule\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Scrigno\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarcofago\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Scaffale\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Libreria\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Barile\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Capsula\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Santuario\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Tomo dello Scheletro\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Libro di Biblioteca\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Fonte del Sangue\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Corpo Decapitato\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Libro degli Orbi\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Libro del Sangue\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Primavera Purificante\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Armatura\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Rastrelliera\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Santuario della Capra\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Calderone\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Pozza Buia\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Fonte del Pianto\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Tomo d'Acciaio\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Colonna di Sangue\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Pugno di Funghi\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Stallo del Vile\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Eroe Ucciso\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"Trappola {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (disabilitato)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"Attivo\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"Disattivo\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Modalità Gioco\"\n\n#: Source/options.cpp:422\nmsgid \"Game Mode Settings\"\nmsgstr \"Impostazioni di Gioco\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Gioca a Diablo o Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Limita alla Demo\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Rende il gioco compatibile con la demo. Abilita il multigiocatore con amici \"\n\"che non possiedono una copia completa di Diablo.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Avvio\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Impostazioni di Avvio\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Introduzione\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Mostra cinematica introduttiva.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Schermata Iniziale\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Mostra schermata iniziale.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo e Schermata Titolo\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Schermata Titolo\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Impostazioni di Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Impostazioni di Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Audio\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Impostazioni Audio\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Rumore di Passi\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Il giocatore un suono quando cammina.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Suono Auto Equipaggiamento\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"L'equipaggiamento automatico di oggetti raccolti emette un suono.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Suono Raccolta Oggetto\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"La raccolta di oggetti emette un suono.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Frequenza di Campionamento\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Frequenza di campionamento uscita (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Canali\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Numero di canali di uscita.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Dimensione Buffer\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"DImensione buffer (numero di frame per canale).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Qualità di Ricampionamento\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Qualità del ricampionatore, da 0 (minimo) a 10 (massimo).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Influenza la risoluzione interna del gioco e determina l'area di \"\n\"visualizzazione. Nota: può differire dalla risoluzione dello schermo quando \"\n\"si utilizza Upscaling, Ridimensionamento a Intero o Adatta a Schermo.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Ricampionatore\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Ricampionatore audio\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Dispositivo\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Dispositivo audio\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafica\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Impostazioni Grafiche\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Schermo intero\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Visualizza il gioco in finestra o a schermo intero.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Adatta allo Schermo\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Regola automaticamente la finestra di gioco in base alle proporzioni e alla \"\n\"risoluzione dello schermo del tuo desktop corrente.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Miglioramento\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Consente il ridimensionamento dell'immagine dalla risoluzione del gioco a \"\n\"quella del monitor. Impedisce la modifica della risoluzione del monitor e \"\n\"consente il ridimensionamento della finestra.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Qualità di Ridimensionamento\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Abilita filtri facoltativi per l'immagine di output durante l'upscaling.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Pixel Prossimo\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilineare\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotropico\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Ridimensionamento a Intero\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"\"\n\"Ridimensiona l'immagine utilizzando un rapporto tra pixel a quoziente intero.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"Controllo Frame Rate\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\"Gestisce il frame rate per bilanciare le prestazioni, ridurre il tearing o \"\n\"risparmiare energia.\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Sincronizzazione Verticale\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"Limita FPS\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Ingrandisce quando abilitato.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Fulmine\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Ciclo Colori\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Effetto di ciclo dei colori utilizzato per animazioni di acqua, lava e acido.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Tavolozza grafica alternativa\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"Il gioco utilizzerà una tavolozza alternativa per Hellfire.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Cursore Hardware\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Usa cursore hardware\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Cursore Hardware Per Oggetti\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Usa cursore hardware per gli oggetti.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Dimensione Massima Cursore Hardware\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Larghezza / altezza massima per il cursore hardware. I cursori più grandi \"\n\"ripiegano sul software.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Mostra FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Visualizza FPS nell'angolo superiore sinistro dello schermo.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Gioco\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Impostazioni di Gioco\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Abilita camminata veloce in città per Diablo e Hellfire. Opzione introdotta \"\n\"nell'espansione.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Cattura Input\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Quando abilitato, il puntatore è catturato dalla finestra di gioco.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Sospendi Partita Su Finestra Non Attiva\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\"Se abilitato, la partita si sospende quando la finestra non è selezionata.\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Abilita missione La Fanciulla.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Abilita la missione di Jersey. Lester l'agricoltore è sostituito dal Matto \"\n\"Svitato.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Fuoco Amico\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Consenti danni da freccia/incantesimo in multigiocatore anche in modalità \"\n\"amichevole attiva.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Missioni intere in multigiocatore\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\"Abilita la versione per giocatore singolo completa/non tagliata delle \"\n\"missioni.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Prova Bardo\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Forza comparsa del personaggio Bardo nel menu di selezione dell'eroe.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Prova Barbaro\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\"Forza comparsa del personaggio Barbaro nel menu di selezione dell'eroe.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Barra Esperienza\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\"La Barra Esperienza compare nell'interfaccia utente nella parte inferiore \"\n\"dello schermo.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Mostra Grafica degli Articoli nei Negozi\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\"Mostra grafica degli articoli a sinistra delle loro descrizioni nei menu del \"\n\"negozio.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Mostra valori salute\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Mostra valore salute corrente / massimo nel globo.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Mostra valori mana\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Mostra valore mana corrente / massimo nel globo.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Dettagli Personaggio\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Barra Salute Nemico\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"\"\n\"La Barra Salute Nemico viene mostrata nella parte superiore dello schermo.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"L'oro viene raccolto automaticamente in prossimità del giocatore.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Gli elisir vengono raccolti automaticamente in prossimità del giocatore.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Gli unguenti vengono raccolti automaticamente in prossimità del giocatore.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Raccolta automatica degli oggetti in città.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria riempirà il tuo mana alla visita del suo negozio.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Le armi saranno automaticamente equipaggiate alla raccolta o all'acquisto.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Le armature saranno automaticamente equipaggiate alla raccolta o \"\n\"all'acquisto.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Gli elmi saranno automaticamente equipaggiati alla raccolta o all'acquisto.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Gli scudi saranno automaticamente equipaggiati alla raccolta o all'acquisto.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"I monili saranno automaticamente equipaggiati alla raccolta o all'acquisto.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Seleziona casualmente le missioni disponibili per nuove partite.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Mostra Tipo Mostro\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Passando il mouse su di un mostro verrà visualizzata una casella di \"\n\"descrizione col tipo di mostro.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Mostra etichette per oggetti a terra quando abilitato.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Ricarica cintura dall'inventario quando l'oggetto della cintura viene \"\n\"consumato.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Quando abilitato i Calderoni, Santuari Avvenenti, di Capra, Ornati, Sacri e \"\n\"di Murphy non possono essere cliccati ed etichettati come disabilitati.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Magia Rapida\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"I tasti di scelta rapida della magia lanciano istantaneamente la magia, \"\n\"invece di cambiare la magia preparata.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Numero di pozioni di Guarigione da raccogliere automaticamente.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Numero di pozioni di Guarigione Totale da raccogliere automaticamente.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Numero di pozioni del Mana da raccogliere automaticamente.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Numero di pozioni del Mana Totale da raccogliere automaticamente.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Numero di pozioni di Giovinezza da raccogliere automaticamente.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Numero di pozioni di Giovinezza Totale da raccogliere automaticamente.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Abilita numeri in virgola mobile\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\"Abilita numeri in virgola mobile guadagnando XP / infliggendo danni ecc.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Disattivo\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Angoli Casuali\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Solo Verticale\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Controller\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Impostazioni Controller\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Rete\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Impostazioni Rete\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chat\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Impostazioni Chat\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Lingua\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Stabilisce quale lingua usare nel gioco.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Impostazioni Lingua\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Tasti associati\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Impostazioni Tasti Associati\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Tasti associati gamepad\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Impostazioni Tasti Associati Gamepad\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"Mod\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"Impostazioni Mod\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Livello\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Esperienza\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Livello Successivo\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Base\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Ora\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Forza\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magia\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Destrezza\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalità\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Punti da distribuire\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Oro\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Classe armatura\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"possibilità di colpire\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Danno\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Vita\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Resistenza Magia\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Resistenza fuoco\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Resistenza fulmine\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"profilo\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"missioni\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"mappa\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menu\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"inv\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"magie\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"vocale\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"silenzia\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Inusabile\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Dan: 1/3 tgt hp\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Guarigioni: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Danno: {:d}-{:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Abilità\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Verga ({:d} carica)\"\nmsgstr[1] \"Verga ({:d} cariche)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Livello {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Magia\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Danneggia solo non morti\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Pergamena\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Verga\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Tasto Rapido {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Impossibile aprire archivio\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Impossibile caricare personaggio\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (liv {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Cronologia Chat (Messaggi: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} monete\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Quante monete d'oro vuoi ritirare?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Livello {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Esperienza: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Livello Massimo\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Livello Successivo: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} al Livello {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"La Tomba di Re Leoric\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"La Camera d'Ossa\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Un Tunnel Oscuro\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"L'Empio Altare\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Verso {:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Mi serve aiuto! Vieni!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Seguimi.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Ecco qualche cosa per te.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Ora MUORI!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Curati!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Presta attenzione!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Grazie.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Ritirata!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Scusa.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Sto aspettando.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Indietro\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Danno : {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Armat: {:d}  \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Dur: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Indistruttibile\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Benvenuti alla\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Bottega del fabbro\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Cosa intendi fare:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Parla con Griswold\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Compra armi\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Compra armi speciali\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Vendi merce\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Ripara armi\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Lascia bottega\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Merce in vendita:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Armi speciali in vendita:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Non mi interessa nulla.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Cosa proponi in vendita?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Nulla da riparare.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Cosa vuoi riparare?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Baracca della strega\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Parla con Adria\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Compra merce\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Ricarica verghe\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Lascia baracca\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Nulla da ricaricare.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Cosa vuoi ricaricare?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Non hai abbastanza oro\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Non hai abbastanza spazio in inventario\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Facciamo l'affare?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Sei sicuro di voler identificare l'oggetto?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Sei sicuro di voler comprare l'oggetto?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Sei sicuro di voler ricaricare l'oggetto?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Sei sicuro di voler vendere l'oggetto?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Sei sicuro di voler riparare l'oggetto?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt Gamba di Legno\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Parla con Wirt\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Ho qualcosa in vendita,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"ma ti costerà 50 monete\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"solo sbirciare. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Di cosa si tratta?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Saluta\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Oggetti in vendita:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Lascia\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Dimora del Guaritore\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Parla con Pepin\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Lascia dimora del Guaritore\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Il Saggio della Città\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Parla con Cain\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identifica oggetti\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Nulla da identificare.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Cosa vuoi identificare?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Questo oggetto è:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Fatto\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Parla con {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Parlare con {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"non è disponibile\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"nella demo\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"versione\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Pettegolezzo\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Il Sol Levante\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Parla con Ogden\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Lascia taverna\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Parla con Gillian\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Accesso Archiviazione\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnham l'Ubriaco\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Parla con Farnham\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Saluta\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Monete: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Cittadino Morto\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Griswold il Fabbro\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin il Guaritore\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Cittadino Ferito\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden il Taverniere\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Cain il Saggio\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Adria la Strega\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian la Locandiera\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Mucca\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester il contadino\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Matto Svitato\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Guerriero\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Ladro\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Mago\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Monaco\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bardo\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbaro\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Ghoul\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Carcassa in Decomposizione\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Morte Nera\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Dannato\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Intagliatore\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Stirpe del Diavolo\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Oscuro\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Scheletro\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Cadavere con Ascia\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Morto al Rogo\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Orrore\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Necrofago\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Divoratore di Peste\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Bestia d'Ombra\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Sfregia Ossa\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Cadavere con Arco\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Scheletro Capo\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Cadavere Capo\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Morto al Rogo Capo\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Orrore Capo\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Lord Invisibile\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Nascosto\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Molestatore\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Inosservato\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Tessitore di Illusione\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Lord dei Satiri\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Clan delle Viscere\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Clan di Pietra\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Clan del Fuoco\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Clan delle Tenebre\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Demone\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Guizzo\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Tenebra\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Sfacciato\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Bestia d'Acido\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Sputa Veleno\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Bestia da Fossa\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Fauci di Lava\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Scheletro Re\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Il Macellaio\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Lord Supremo\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Uomo Melma\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Demone Rospo\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Scuoiato\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Verme\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Lumaca di Caverna\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Verme Demoniaco\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Divoratore\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Demone di Magma\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Pietra di Sangue\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Roccia Infernale\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Lord di Lava\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Demone Cornuto\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Velocista di Fango\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Portatore di Gelo\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Lord di Ossidiana\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"dissossato\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Morte Rossa\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Demone Litch\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Balrog Non Morto\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Inceneritore\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Lord di Fiamma\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Fuoco di Sventura\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Fucina Infernale\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Tempesta Rossa\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Velocista della Tempesta\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Lord della Tempesta\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Maelstrom\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Bruto Stirpe del Diavolo\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Demone Alato\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargoyle\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Artiglio Insanguinato\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Morte Alata\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Assassino\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Custode\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Lord del Vortice\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Vipera di Caverna\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Drago di Fuoco\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Vipera d'Oro\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Drago Azzurro\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Cavaliere Nero\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Custode del Destino\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Lord d'Acciaio\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Cavaliere di Sangue\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Il Triturato\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Incavato\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Signore del Dolore\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Tessitore di Realtà\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Succube\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Strega della Neve\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Prole Infernale\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Fucina di Anime\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Consigliere\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Magistrato\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Cabalista\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Difensore\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Il Signore Oscuro\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Il Maligno Arci Litch\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad il Fiacco\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar il Folle\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Moccio\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Arcivescovo Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Tormento Rosso\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Giada Nera\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Comandante del Sangue\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Hork il Demone\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Il Profanatore\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Bonehead Keenaxe\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Bladeskin lo Squartatore\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Purulento\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Pukerat l'Impuro\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Squarta Ossa\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Rotfeast il Famelico\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Gutshank il Lesto\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Brokenhead Bangshield\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Strage di Marciume\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Morso di Tenebra\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Occhio Morto\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Madeye il Morto\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"Chupacabra\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Teschio Infuocato\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Teschio Deforme\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Lingua Cruenta\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Pulsecrawler\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Moonbender\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Corvo d'Ira\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Mangia Vertebre\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Blackash il Bruciato\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Corvo Ombra\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Blightstone il Fiacco\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Bilefroth Padron del Fosso\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Bloodskin Darkbow\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Turpe Alato\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Succhia Ombra\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Foschia Mutevole\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Sputa Morte\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Bloodgutter\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Deathshade Fleshmaul\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Warmaggot il Pazzo\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Glasskull il Dentato\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Fuoco di Sventura\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Nightwing il Gelido\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Masso Cruento\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Bronzefist Firestone\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Wrathfire il Dannato\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Firewound il Bieco\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Barone di Melma\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Blighthorn Steelmace\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Chaoshowler\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Doomgrin il Marcio\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Madburner\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Bonesaw il Litch\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Spacca Vertebre\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Devilskull Sharpbone\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Brokenstorm\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Stormbane\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Oozedrool\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Goldblight di Fiamma\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Tempesta Nera\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Appestato\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Lo Scuoiato\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Corno Blu\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Warpfire Hellspawn\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Fangspeir\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Teschio Marcio\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Lionskull il Curvo\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Lingua Nera\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Vil Tocco\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Serpe di Fuoco\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Fangskin\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Witchfire l'Empio\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Teschio Nero\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Soulslash\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Windspawn\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Lord della Fossa\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Rustweaver\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Howlingire l'Ombra\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Doomcloud\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Bloodmoon Soulfire\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Witchmoon\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Gorefeast\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Graywar l'Assassino\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Dreadjudge\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Stareye La Strega\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Steelskull il Cacciatore\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Il Visir\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamphir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Bloodlust\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Rete di Vedova\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Fleshdancer\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Grimspike\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Doomlock\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Spada Corta\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Brocchiero\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Clava\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Arco Corto\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Verga Corta del Mana\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Mannaia\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Corona Immortale\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Banda Empirea\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Gemma Magica\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Amuleto Ottico\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Anello della Verità\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"L'Insegna\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Elmo Arlecchino\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Velo d'Acciaio\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Elisir Dorato\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Incudine del Furore\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Fungo Nero\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Cervello\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Tomo Fungino\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Elisir Spettrale\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Pietra di Sangue\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Mappa Cattedrale\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Pozione di Guarigione\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Pozione del Mana\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Pergamena dell'Identità\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Pergamena del Portale\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Valor di Arkaine\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Pozione di Guarigione Totale\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Pozione del Mana Totale\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Lama di Griswold\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Armatura di Bovino\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Verga di Lazarus\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Pergamena di Resurrezione\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Verga Corta\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Spada\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Daga\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Runa Esplosiva\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodore\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Amuleto Aurico\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Pergamena Strappata 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Pergamena Strappata 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Pergamena Strappata 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Pergamena Ricostruita\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Abito Marrone\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Abito Grigio\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Cappuccio\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Copricapo\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Elmo\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Elmo Intero\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Corona\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Elmo Superiore\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Cappa\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Vestito\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Mantello\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Tunica\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Gambesone\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Armatura di Cuoio\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Armatura di Cuoio Duro\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Armatura di Cuoio Borchiata\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Corazza ad Anelli\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Corazza\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Cotta di Maglia\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Corazza a Scaglie\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Pettorale\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Busto\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Corazza Lamellare\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Corazza a Piastre\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Corazza da Campo\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Armatura Gotica\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Corazza Intera a Piastre\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Scudo\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Scudo Piccolo\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Scudo Grande\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Scudo a Goccia\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Scudo a Torre\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Scudo Gotico\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Pozione di Giovinezza\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Gran Pozione di Giovinezza\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Unguento\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Elisir di Forza\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Elisir di Magia\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Elisir di Destrezza\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Elisir di Vitalità\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Pergamena di Guarigione\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Pergamena della Ricerca\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Pergamena del Fulmine\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Pergamena Muro di Fuoco\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Pergamena Inferno\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Pergamena del Lampo\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Pergamena di Infravisione\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Pergamena della Fase\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Pergamena Scudo Magico\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Pergamena Ondata di Fuoco\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Pergamena Sfera Infuocata\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Pergamena Pietra Malefica\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Pergamena della Tempesta\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Pergamena del Guardiano\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Pergamena Nova\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Pergamena del Golem\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Pergamena Teletrasporto\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Pergamena Apocalisse\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Falcione\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Scimitarra\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Claymore\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Lama\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Sciabola\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Spada Lunga\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Spada Larga\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Spada Bastarda\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Spada a Due Mani\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Spada Superiore\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Ascia Piccola\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Ascia\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Ascia Grande\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Ascia Larga\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Ascia da Battaglia\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Ascia Superiore\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Mazza\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Mazza Chiodata\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Martello d'Arme\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Martello\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Mazza Chiodata\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Flagello\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Maglio\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Arco\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Arco da Caccia\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Arco Lungo\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Arco Composito\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Arco Piccolo da Battaglia\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Arco Lungo da Battaglia\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Arco Corto da Guerra\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Arco Lungo da Guerra\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Verga Lunga\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Verga Composita\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Picca\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Verga da Guerra\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Anello\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amuleto\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Runa di Fuoco\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Runa\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Runa del Fulmine\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Runa Maggiore del Fuoco\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Runa Maggiore del Fulmine\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Runa di Pietra\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Verga Corta del Fulmine\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Pozione Arena\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Mannaia Del Macellaio\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Lama di Luce\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Arco del Dissenso\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Pungitore\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Arco Celestiale\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Cacciatore Letale\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Arco del Morto\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Arco di Rovere Nero\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Dardo di Fuoco\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Pungicarne\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Forza del Vento\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Corno d'Aquila\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Pugnale di Gonnagal\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Il Difensore\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Artiglio di Grifoni\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Rasoio Nero\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Luna Gibbosa\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Stinco di Ghiaccio\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"La Lama Del Carnefice\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Il Segaossa\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Falco Ombra\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Picca del Mago\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Lama di Luce\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Artiglio di Falco\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Iettatore\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Il Grizzly\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Il Nonno\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Il Divoratore\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Becco Affilato\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Assassino Cruento\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Ascia Celestiale\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Ascia Nefasta\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Fendiroccia\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Accetta di Aguinara\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Assassino Infernale\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Preda di Messerschmidt\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Crackrust\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Maglio di Jholm\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Clava di Civerb\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Stella Celestiale\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Stella di Baranar\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Radice Nodosa\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Sfascia Cranio\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Maglio di Schaefer\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Dreamflange\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Verga delle Ombre\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Immolatore\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Spira della Bufera\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Gleamsong\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Invoca Tuoni\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Il Protettore\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Enigma di Naj\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Mindcry\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Verga di Onan\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Elmo di Sprits\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Cappuccio del Pensiero\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Elmo del Lord Supremo\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Cresta del Giullare\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Crepuscolo degli Dei\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Cerchio Regale\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Brandelli di Anime\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Rovina Del Gladiatore\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Manto Arcobaleno\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Cuoio di Aut\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Mantello di Saggezza\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Corazza Lucente\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Corazza Necrofaga\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Paesaggio Notturno\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Busto di Naj's\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Manto Demonspike\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Il Deviatore\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Scudo Osseo Rotto\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Varco del Dragone\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Scudo di Rovere Nero\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Sacro Difensore\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Scudo Tempesta\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Rovo\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Anello di Regha\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Salassatore\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Anello Costrittivo\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Anello del Dovere\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Stagno\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Rame\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Bronzo\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Ferro\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Acciaio\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Argento\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platino\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteorico\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Strano\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Inutile\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Ricurvo\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Debole\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Dentato\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Letale\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Grave\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Violento\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Brutale\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Massivo\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Ferino\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Atroce\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Spietato\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Goffo\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Cupo\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Affilato\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Fine\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"del Guerriero\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"del Soldato\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"del Signore\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"del Cavaliere\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"del Maestro\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"del Campione\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"del Re\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Inerme\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Arrugginito\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Forte\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Prode\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Audace\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Glorioso\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Santo\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Solenne\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Eccezionale\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Leale\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Rosso\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Cremisi\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Granato\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubino\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Blu\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Azzurrite\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lapislazzuli\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Cobalto\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Zaffiro\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Bianco\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Perla\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Avorio\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Cristallo\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Diamante\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topazio\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Ambra\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Giada\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Ossidiana\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Smeraldo\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"di Iena\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"di Rospo\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"di Ragno\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"di Corvo\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"di Serpe\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"di Serpente\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"di Drago\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"di Dragone\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"di Verme\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"di Idra\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"d'Angelo\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"d'Arcangelo\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Cospicuo\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Munifico\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Fiamma\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Fulmine\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"qualità\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"reciso\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"delitto\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"sangue\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"eccidio\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"macello\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"male\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"lacrime\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"salute\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"protezione\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"assorbimento\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"deviazione\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"osmosi\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"fragilità\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"debolezza\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"forza\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"potenza\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"potere\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"giganti\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"titani\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"paralisi\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"atrofia\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"destrezza\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"abilità\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"precisione\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"precisione\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"perfezione\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"stolto\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"dislessia\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"magia\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"mente\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"splendore\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"sortilegio\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"magia\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"malattia\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"morbo\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"vitalità\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"gusto\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"energia\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"vigore\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"vita\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"problema\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"fossa\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"cielo\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"luna\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"stelle\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"paradiso\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"zodiaco\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"avvoltoio\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"sciacallo\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"volpe\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"giaguaro\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"aquila\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"lupo\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tigre\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"leone\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mammut\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"balena\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"fragilità\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"debolezza\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"solidità\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"maestria\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"struttura\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"epoche\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"oscurità\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"notte\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"luce\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"bagliore\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"fiamma\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"fuoco\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"ardente\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"shock\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"fulmine\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"tuono\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"molto\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"parecchio\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"spine\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"corruzione\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"ladri\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"orso\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"pipistrello\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"vampiri\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"sanguisuga\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"sangue\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"perforazione\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"penetrazione\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"stordimento\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"prontezza\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"celerità\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"velocità\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"fretta\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"equilibrio\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"stabilità\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"armonia\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"blocco\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"La Gemma Magica\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad il Fiacco\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar il Folle\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Il Macellaio\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"L'Insegna di Ogden\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"La Camera dei Ciechi\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Valor\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Comandante del Sangue\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"La Maledizione di Re Leoric\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"L'Arcivescovo Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Questioni di Tomba\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"L'Orto del Contadino\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"La Fanciulla\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Il Commerciante Errante\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Il Profanatore\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Il Jersey di Jersey\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Fulmine Infuocato\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Guarigione\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Fulmine\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Bagliore\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identifica\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Muro Infuocato\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Portale Cittadino\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Inganno di Pietra\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infravisione\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Fase\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Scudo Magico\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Sfera Infuocata\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Custode\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Catena di Fulmini\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Ondata di Fiamme\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Serpenti del Fato\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Rito di Sangue\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Invisibilità\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Ira\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teletrasporto\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apocalisse\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Eterealizza\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Ripara Oggetto\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Ricarica Verga\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Disarma Trappola\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elementale\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Scarica Fulminea\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Scarica Energetica\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Resurrezione\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telecinesi\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Cura\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Stella Cruenta\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Spirito Osseo\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ahh, la storia del nostro Re? La caduta di Leoric è stata un duro colpo per \"\n\"questa terra. La gente ha sempre amato il Re e ora vivono nel terrore di \"\n\"lui. Quello che non capisco è come è stato possibile che sia caduto così \"\n\"lontano dalla luce, dato che Leoric è sempre stato il più santo degli \"\n\"uomini. Solo i più malvagi poteri infernali avrebbero potuto cambiarlo \"\n\"così...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"La città necessita del tuo aiuto, signore! Alcuni mesi fa il figlio di Re \"\n\"Leoric, il Principe Albrecht, venne rapito. Il Re, furioso, fece perquisire \"\n\"il villaggio per ritrovare il figlio. Col passare dei giorni, il Re sembrò \"\n\"scivolare sempre più nella pazzia. Incolpò cittadini innocenti della \"\n\"scomparsa del figlio e li giustiziò. Meno della metà di noi scamparono alla \"\n\"sua follia...\\n\"\n\"\\n\"\n\"I Cavalieri e i Sacerdoti provarono a placarlo, ma si rivoltò contro di loro \"\n\"e purtroppo, furono costretti ad ucciderlo. Con il suo ultimo respiro invocò \"\n\"una terribile maledizione contro i suoi passati seguaci. Giurò che lo \"\n\"avrebbero servito per sempre nell'oscurità... \\n\"\n\"\\n\"\n\"Da qui le cose prendono una piega ancora peggiore di quello che pensavo \"\n\"possibile! Il nostro ex Re è sorto dal suo sonno eterno e comanda una \"\n\"legione di non morti nel Labirinto. Il suo corpo fu sepolto tre livelli \"\n\"sotto la Cattedrale. Ti prego, signore, distruggi il suo corpo così che la \"\n\"sua anima possa riposare in pace...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Come ti ho detto signore, il Re fu seppellito tre livelli qui sotto. Giù \"\n\"egli attende nella putrida oscurità l'opportunità per distruggere questa \"\n\"terra...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"La maledizione del Re è finita, ma temo che fosse parte di un male più \"\n\"grande. Comunque possiamo ancora salvarci dall'oscurità che consuma la \"\n\"nostra terra, la tua vittoria è un buon auspicio. Possa la luce guidarti sul \"\n\"tuo cammino, signore.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"La perdita del figlio fu troppo per Re Leoric. Tentai quel che potei per \"\n\"calmare la sua pazzia, ma alla fine venni sopraffatto. Da quel giorno su \"\n\"questo Regno pesa una nera maledizione, ma magari se tu liberassi la sua \"\n\"anima dalla sua prigione terrena la maledizione cesserebbe...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Non mi piace pensare a come morì il Re. Preferisco ricordarlo per l'uomo \"\n\"buono e giusto che era. La sua morte è stata tanto triste quanto ingiusta.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Forgiai la maggior parte delle armi e delle armature che Re Leoric forniva \"\n\"ai suoi cavalieri. Usai la mia maestria per forgiargli una spada a due mani \"\n\"del miglior mithril e una corona da battaglia. Non riesco ancora a credere \"\n\"che sia morto, di sicuro qualche forza malvagia lo portò alla pazzia!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Non m'importa! Ascolta, Nessuno scheletro diventerà il MIO re. Leoric è il \"\n\"RE. Re, mi senti? LUNGA VITA AL RE!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"La morte cammina fra i vivi a causa della maledizione del Re. Egli ha il \"\n\"potere di sollevare altri guerrieri in una crescente armata di non-morti. Se \"\n\"non lo fermerai, marcerà su questa terra e massacrerà tutti quelli che \"\n\"ancora vivono qui.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Senti, sto lavorando. Non vendo informazioni e non m'importa di nessun Re \"\n\"che è morto da più tempo di quanto io sia stato in vita. Se ti occorre \"\n\"qualcosa da usare contro questo Re dei non-morti, allora ti posso anche \"\n\"aiutare...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"La fiamma della vita è tornata a me. Preparati mortale, a servire il mio \"\n\"Padrone per l'eternità!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Vedo che quello strano comportamento ti ha confuso. Suppongo che dato che \"\n\"molti demoni temono la luce del sole e pensano che contenga una grande \"\n\"forza, può essere che il sole nascente dipinto sull'insegna di cui parli \"\n\"abbia fatto loro credere che essa contenga arcani poteri. Hmm, forse non \"\n\"tutti sono così abili come temevamo...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Signore, vorrei raccontarti cosa mi è accaduto. So che tu conosci bene le \"\n\"mostruosità che vivono nel labirinto e quello che sto per raccontarti è una \"\n\"cosa che non riesco a capire... Ieri notte un rumore stridulo proveniente \"\n\"appena fuori dalla mia taverna mi ha tenuto sveglio. Guardando fuori ho \"\n\"notato delle sagome di piccoli demoni somiglianti a creaturine. Poco tempo \"\n\"dopo, sono fuggiti, ma non prima di avermi rubato l'insegna. Non voglio \"\n\"sapere perché i demoni hanno rubato la mia insegna, ma perché non lasciano \"\n\"in pace la mia famiglia... è strano, no?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Oh, non dovevi riportarmi l'insegna, suppongo che questo mi risparmi il \"\n\"costo di doverne fare un'altra. Bene, fammi pensare, cosa poso darti in \"\n\"cambio? Hmmm, cosa abbiamo qui?... ah, si! Questo copricapo è stato lasciato \"\n\"in una delle stanze da un mago che passò di qui qualche tempo fa. Forse per \"\n\"te potrebbe avere qualche utilità.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Signore, demoni che girano per il villaggio di notte, saccheggiando le \"\n\"nostre case - non c'è più niente di sacro? Spero che Ogden e Garda stiano \"\n\"bene. Penso sarebbero venuti da me se fossero feriti...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"..Oh, dio! È questa la fine che ha fatto l'insegna? Io e mia nonna dobbiamo \"\n\"aver dormito mentre accadeva. Grazie al Signore della Luce quei mostri non \"\n\"hanno attaccato la locanda.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"I demoni hanno rubato l'insegna di Ogden? Questo non combacia con le \"\n\"atrocità di cui ho sentito, e a cui ho assistito. \\n\"\n\" \\n\"\n\"Ai demoni interessa strapparti il cuore, non l'insegna.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Sai cosa penso? Qualcuno ha preso l'insegna, e ora vuole molti soldi per \"\n\"restituirla. Se fossi Ogden... e non lo sono, ma se lo fossi... Ne comprerei \"\n\"una nuova con un bel disegno. Un boccale di birra o un pezzo di formaggio, \"\n\"per esempio...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Nessun uomo può capire la mente di un demone. \\n\"\n\" \\n\"\n\"Non lasciarti confondere dalle loro azioni, potrebbe essere il loro piano.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Cosa - dice che l'ho presa io? Scommetto che anche Griswold è dalla sua \"\n\"parte. \\n\"\n\" \\n\"\n\"Senti, ho superato la fase del ladro di insegne mesi fa. Non trarrai \"\n\"profitto da un pezzo di legno.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Ehi - Tu quello che uccide tutti! Tu porta me Stendardo Magico o \"\n\"attacchiamo! Tu non sopravvivi! Uccidi grossi cattivi e riporta Magia. Passa \"\n\"angolo e porta, trova cattivi. Tu dai, tu vai!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Uccidi cattivi, porta stendardo. Tu porta me, altrimenti...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"Tu dai! Bene! Vai ora, noi forti. Uccidiamo tutti con grande Magia!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Questo non promette bene, perché conferma le mie paure più profonde. Anche \"\n\"se non ho mai creduto alle antiche leggende, ora non posso negarle. Forse è \"\n\"il momento di rivelare chi sono.\\n\"\n\" \\n\"\n\"Il mio vero nome è Deckard Cain il Saggio, e sono l'ultimo discendente di \"\n\"un'antica Fratellanza il cui compito era custodire i segreti di un male \"\n\"senza tempo. Un male che apparentemente è stato liberato.\\n\"\n\" \\n\"\n\"L'Arcivescovo Lazarus, un tempo il consigliere più fidato del Re Leoric, \"\n\"guidò un gruppo di paesani nel labirinto, per ritrovare il figlio scomparso \"\n\"del re, Albrecht. Passò molto tempo prima del loro ritorno, e solo pochi \"\n\"ritornarono vivi.\\n\"\n\" \\n\"\n\"Maledicimi per la mia stupidità! Avrei dovuto sospettare il suo inganno \"\n\"allora. Dev'essere stato Lazarus stesso a rapire Albrecht e a nasconderlo \"\n\"nel labirinto. Non capisco perché l'Arcivescovo sia diventato malvagio, o \"\n\"quale sia il suo interesse per il bambino. A meno che non intenda \"\n\"sacrificarlo ai suoi signori oscuri! \\n\"\n\"\\n\"\n\"Questo dev'essere il suo piano! I sopravvissuti del suo gruppo di \"\n\"salvataggio! Dicono di aver visto Lazarus per l'ultima volta mentre correva \"\n\"nelle viscere più profonde del labirinto. Devi sbrigarti e salvare il \"\n\"principe dalla lama sacrificale di quel pazzo!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Devi affrettarti a liberare Albrecht dalle mani di Lazarus. Il principe e le \"\n\"persone di questo regno contano su di te!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"La tua storia è strana, amico mio. Lazarus brucerà all'Inferno per quel che \"\n\"ha fatto. Il ragazzo che descrivi non è il nostro principe, ma credo che \"\n\"Albrecht possa essere ancora in pericolo. Il simbolo di potere di cui parli \"\n\"dev'essere un portale per il cuore del labirinto.\\n\"\n\" \\n\"\n\"Sappi questo - amico mio - Il male che affronterai è l'oscuro Signore del \"\n\"Terrore. Meglio conosciuto fra i mortali come Diablo. È lui che venne \"\n\"imprigionato nel Labirinto molti secoli fa, e temo che cerchi di seminare di \"\n\"nuovo il caos fra l'umanità. Devi avventurarti attraverso il portale e \"\n\"sconfiggere Diablo prima che sia troppo tardi!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus era l'Arcivescovo che guidò molti dei paesani nel labirinto. Persi \"\n\"molti buoni amici quel giorno, e Lazarus non tornò mai. Suppongo sia stato \"\n\"ucciso assieme alla maggior parte degli altri. Se puoi farmi un favore, \"\n\"signore - ti prego, non parlare a Farnham di quel giorno.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Fui scioccato quando seppi quello che i paesani stavano progettando di fare \"\n\"quella notte. Pensavo che fra tutti, Lazarus avesse più buonsenso. Era \"\n\"Arcivescovo e sembrava sempre preoccuparsi molto per la gente di Tristram. \"\n\"Molti furono feriti, e non potei salvarli tutti...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Ricordo Lazarus come un uomo buono e gentile. Celebrò il funerale di mia \"\n\"madre, e aiutò mia nonna e me a superare quel bruttissimo momento. Prego \"\n\"ogni notte che in qualche modo, sia ancora vivo e al sicuro.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Ero là quando Lazarus ci guidò nel labirinto. Parlò di punizione divina, ma \"\n\"quando cominciammo a lottare contro quelle creature infernali, lui non alzò \"\n\"un dito su di loro. Proseguì sempre più in profondità nelle buie, infinite \"\n\"stanze piene di servitori dell'oscurità!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Pugnalano, poi mordono, poi ti sono tutti attorno. Bugiardo! BUGIARDO! Sono \"\n\"tutti morti! MORTI! Mi senti? Continuano a cadere e a cadere... il loro \"\n\"sangue si sparge sul pavimento... tutta colpa sua...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Non conoscevo questo Lazarus di cui parli, ma sento un gran conflitto nel \"\n\"suo essere. Pone un grave pericolo, e non si fermerà davanti a nulla per \"\n\"servire i poteri dell'oscurità che l'hanno reclamato per loro.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Si, l'onesto Lazarus, che fu di grande aiuto contro quei mostri. Come no! \"\n\"Come mai non mi aiutò a salvare la mia gamba? Guarda, ti do un consiglio. \"\n\"Chiedi a Farnham, anche lui era lì.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Abbandona la tua folle cerca. Quello che t'aspetta è l'ira del mio Padrone. \"\n\"È tardi per salvare il bambino. Unisciti a lui all'Inferno!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, non so se quello che sto per dirti ti potrà essere di aiuto. L'acqua \"\n\"che noi usiamo proviene da una sorgente sotterranea. Ho sentito parlare di \"\n\"un tunnel che conduce ad un grande lago - forse è quella la sorgente. \"\n\"Sfortunatamente, non so che cosa abbia causato l'avvelenamento dell'acqua.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Ho sempre cercato di avere delle provviste di cibo e bevande in magazzino, \"\n\"ma con l'intera città senza una fonte d'acqua fresca, presto le mie scorte \"\n\"finiranno. \\n\"\n\" \\n\"\n\"Ti prego, aiutaci come puoi, o non sapremo più che fare.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Sono fortunato ad averti trovato in tempo! La nostra acqua è diventata \"\n\"torbida e stagnante e alcuni paesani bevendola si sono ammalati. Le riserve \"\n\"di acqua fresca si stanno esaurendo in fretta. Credo ci sia un passaggio che \"\n\"porta alla fonte che serve il villaggio. Ti prego, scopri chi ha causato \"\n\"questo disastro, o per noi sarà di certo la fine.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Ti prego, sbrigati. Man mano che passano le ore anche l'acqua da bere inizia \"\n\"a diminuire.\\n\"\n\"\\n\"\n\"Senza il tuo aiuto non sopravviveremo a lungo.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Cosa stai dicendo - la mera presenza dei demoni ha contaminato l'acqua? Oh, \"\n\"davvero un grande male deve giacere sotto la città, ma il tuo coraggio e la \"\n\"tua perseveranza ci fanno sperare, ti prego, accetta questo anello - forse \"\n\"ti aiuterà a eliminare quelle vili creature.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Mia nonna è molto debole, e Garda dice che non possiamo bere l'acqua delle \"\n\"fonti. Per favore, puoi fare qualcosa per aiutarci?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin ti ha detto la verità. Abbiamo davvero bisogno di acqua, e subito. Ho \"\n\"tentato di rendere potabile quella di una piccola fonte, ma era troppo \"\n\"putrida. Deve essere inquinata alla fonte.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Bevi dell'acqua?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Se non fai tornare pura l'acqua della fonte, la gente di Tristram morirà. \\n\"\n\" \\n\"\n\"Sappi solo che i demoni sono gli artefici di quello che sta accadendo, anche \"\n\"se loro ignorano di averlo fatto.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Per stavolta, sono con te. I miei affari vanno male, ti dirò, se non ho \"\n\"nessun mercato a cui vendere. Scopri in fretta che sta succedendo!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Un libro che narra di una camera di ossa umane? Beh, una Camera d'Ossa è \"\n\"narrata in alcune scritture arcaiche da me studiate nelle biblioteche \"\n\"dell'Est. Questi tomi raccontano che quando i Signori dell'Aldilà desiderano \"\n\"proteggere i loro tesori, creano luoghi dove chi muore nel tentativo di \"\n\"saccheggiarli viene condannato a proteggerli per sempre. Una fine contorta, \"\n\"ma meritata, no?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Temo di non sapere niente su questo, signore. Cain però ha molti libri che \"\n\"potrebbero esserti d'aiuto.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Sembra un posto molto pericoloso. Ti prego, se decidi di andarci, fai molta \"\n\"attenzione.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Ho paura di non aver mai sentito nulla a riguardo. Forse Cain il Narratore \"\n\"potrebbe esserti d'aiuto...\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Non so nulla di quel posto, ma puoi provare a chiederlo a Cain. Lui sa molte \"\n\"cose, e non mi sorprenderebbe se avesse delle risposte alla tua domanda.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Ok, senti. C'è questa gabbia di legno, vedi. E sua moglie... mi ha detto \"\n\"l'albero che tu lo sai... perché devi aspettare. Poi io dico, è facile che \"\n\"funzioni su di lui, ma se pensi che io paghi per questo... uh... già.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Diventerai eterno schiavo dei Signori Oscuri se morirai all'interno di \"\n\"questo luogo maledetto.\\n\"\n\"\\n\"\n\"Entra nella Camera d'Ossa a tuo rischio e pericolo.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Come dici? Un grande e misterioso tesoro? Potrei essere interessato \"\n\"all'acquisto di alcune cose da te... o ancora meglio, non sei interessato ad \"\n\"alcuni rari e costosi oggetti per aiutarti nell'impresa?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Sembra che l'Arcivescovo Lazarus spinse molti paesani ad avventurarsi nel \"\n\"labirinto per ritrovare il figlio scomparso del re. Sfruttò le loro paure \"\n\"per trasformarli in una folla scatenata. Nessuno di loro era preparato per \"\n\"quello che giaceva sottoterra. Lazarus li abbandonò - fra le grinfie di \"\n\"orrori inenarrabili - a morire laggiù.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Si, Farnham disse qualcosa a proposito di un goffo mostro che brandiva una \"\n\"grossa arma. Mi pare lo chiamasse il macellaio.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Per Dio, io so di questo vile demone! Molti erano terrorizzati dalle ferite \"\n\"che egli fece sui loro corpi, quando i pochi sopravvissuti dell'assalto \"\n\"guidato da Lazarus fuggirono dalla cattedrale. Non so cosa esso usi per \"\n\"squartare le sue vittime, ma sicuramente non è un'arma di questo mondo. \"\n\"Lascia ferite infettate di malattie impossibili da curare. Attento se pensi \"\n\"di combattere contro questo nemico...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Quando Farnham raccontò di un macellaio assassino, non gli diedi peso. Ma \"\n\"visto che anche tu ne parli, forse diceva la verità.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Ho visto quello che Farnham chiama il Macellaio mentre si scavava un \"\n\"passaggio fra i miei amici. Impugnava una Mannaia Grossa come un'Ascia \"\n\"squartando le persone in un attimo. Fui separato dal combattimento da una \"\n\"folla di piccoli demoni urlanti e in qualche modo trovai le scale che \"\n\"conducevano all'esterno. Da allora non l'ho più visto, ma non scorderò mai \"\n\"quel Viso sporco di Sangue.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Grande! Grande mannaia uccide i miei amici. Non posso fermarla, devo \"\n\"fuggire, non posso salvarli. Intrappolato in una stanza piena di cadaveri \"\n\"Piena di amici NOOOOOO!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Il Macellaio è una creatura sadica che si diverte a torturare e a far \"\n\"soffrire gli altri. Hai visto cosa ha fatto a Farnham l'ubriacone. Ucciderlo \"\n\"garantirebbe di certo la sicurezza del villaggio.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"So più di quel che pensi su quel mostro. I suoi piccoli amici mi catturarono \"\n\"e riuscirono a prendermi la gamba prima che Griswold mi tirasse fuori da \"\n\"quel buco. \\n\"\n\" \\n\"\n\"Te la metto giù dura - uccidilo prima che lo faccia lui e ti aggiunga alla \"\n\"sua collezione.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Ti prego, ascoltami. L'Arcivescovo Lazarus ci condusse laggiù per ritrovare \"\n\"il principe. Il bastardo ci guidò in trappola! Ora sono tutti morti. Uccisi \"\n\"da un demone chiamato Macellaio. Vendicaci! Trova il demone e fermalo così \"\n\"che le nostre anime possano riposare...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Reciti dei versi interessanti scritti in uno stile che mi ricorda di altre \"\n\"opere. Fammi pensare - come faceva?\\n\"\n\" \\n\"\n\"... L'Oscurità copre l'ignoto. Occhi invisibili brillano, mentre il rumore \"\n\"di artigli affilati tormenta quelle povere anime rese cieche per l'eternità. \"\n\"La prigione per quelle anime dannate è detta la Sala degli Accecati...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"La poesia non mi ha mai interessato molto. Qualche volta ho pagato un \"\n\"menestrello per ravvivare la locanda quando gli affari andavano bene ma è \"\n\"stato tempo fa. \\n\"\n\" \\n\"\n\"Cosa? Oh, si... Penso tu debba vedere se gli altri sanno qualcosa.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Quel che dici sembra familiare. Mi pare di aver trovato qualcosa di simile a \"\n\"quel poema mentre ricercavo la storia delle malattie demoniache. Parlava di \"\n\"un luogo dalla grande malvagità... aspetta - non vorrai andare là?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Se hai domande sulla cecità, dovresti parlare a Pepin. So che diede a mia \"\n\"nonna una pozione che l'aiutò a schiarirsi la vista, forse potrebbe essere \"\n\"d'aiuto anche a te.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Temo di non aver mai visto o sentito parlare di un luogo che corrisponda \"\n\"alla tua descrizione, amico mio. Forse Cain il Narratore potrebbe darti un \"\n\"aiuto.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Guarda qua... Buffo, huh? Capito? Cieco - vedi?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Questo è un posto di grande angoscia e terrore, ciò è molto utile al suo \"\n\"Padrone. \\n\"\n\" \\n\"\n\"Fai attenzione o potresti rimanervi più a lungo di quanto avessi previsto.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Vediamo, ti sto vendendo qualcosa? No! Mi dai del denaro per parlarti di \"\n\"questo? No! Te ne stai andando a parlare col Narratore che vive per questo \"\n\"genere di cose? Si.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Dici di aver parlato con Lachdanan? Fu un grande eroe quando era in vita. \"\n\"Lachdanan era un uomo giusto e onorevole che servì fedelmente il suo Re per \"\n\"anni. Ma poi come già saprai.\\n\"\n\" \\n\"\n\"Fra tutti quelli colpiti dalla Maledizione del Re, Lachdanan difficilmente \"\n\"si sarebbe arreso senza combattere quindi posso credere alla tua storia. Se \"\n\"fossi in te, amico mio. Cercherei un modo per liberarlo dal suo tormento.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Stai parlando di un guerriero morto da tempo! Non ho nessuna intenzione di \"\n\"parlare di questo nel cortile della mia locanda, Grazie.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Un elisir dorato, dici. Non ho mai preparato una pozione di quel colore, \"\n\"quindi non posso dirti che effetto avrebbe se tu decidessi di berlo. Come \"\n\"tuo guaritore, ti metto in guardia nel caso dovessi trovarlo, fai quel che \"\n\"ti ha chiesto Lachdanan, ma non tentare di usarlo.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Non ho mai sentito parlare prima di questo Lachdanan. Sono spiacente, ma non \"\n\"posso esserti di aiuto.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Se era davvero Lachdanan la persona da te incontrata, allora ti raccomando \"\n\"di aiutarlo. Ho avuto spesso a che fare con lui, e l'ho trovato onesto e \"\n\"fedele per natura. La Maledizione calata sui seguaci di Re Leoric, \"\n\"dev'essere stata particolarmente dura per lui.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan è morto. Tutti lo sanno, non puoi trovare alcun modo per farmi \"\n\"cambiare idea. Non puoi parlare a un morto. Lo so!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Potresti incontrare persone che sono intrappolate nel Labirinto, come \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"Percepisco in lui onore e grande senso di colpa. Aiutalo e aiuti tutta \"\n\"Tristram.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Aspetta, fammi indovinare. Cain è stato ingoiato da un baratro gigantesco \"\n\"che si è aperto sotto di lui. È stato incenerito in una palla di fuoco \"\n\"infernale, e non può più darti delle risposte. Non è forse successo questo? \"\n\"Ora o comprerai qualcosa o te ne andrai.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Per favore, non uccidermi, solo ascoltami. Una volta ero il Capitano dei \"\n\"Cavalieri di Re Leoric, e mantenevo le leggi di questa terra con giustizia e \"\n\"onore. Poi la sua Oscura Maledizione cadde su di noi. Mentre i miei compagni \"\n\"soccombevano al loro triste fato, io fuggii dal sepolcro del Re, per cercare \"\n\"un modo per porre fine alla Maledizione. Ma fallii...\\n\"\n\" \\n\"\n\"Ho sentito parlare di un Elisir Dorato che dovrebbe sollevare la Maledizione \"\n\"e permettere alla mia anima di riposare, ma non sono riuscito a trovarlo. La \"\n\"mia forza ora svanisce, e con essa la mia umanità. Ti prego, aiutami e trova \"\n\"l'elisir. Ricompenserò i tuoi sforzi - lo giuro sul mio onore.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Non hai trovato l'Elisir Dorato. Temo di essere condannato per l'eternità. \"\n\"Per favore, tieni duro.\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Tu hai salvato la mia anima dalla dannazione e per questo ti sono debitore. \"\n\"Se troverò un modo per sdebitarmi dall'oltretomba lo farò, ma per ora... \"\n\"prendi il mio elmo. Nel viaggio che sto per fare mi servirà ben poco. Che \"\n\"possa proteggerti dagli Oscuri Poteri. Ora vai e che la Luce ti assista nel \"\n\"tuo cammino, amico mio...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold mi ha parlato dell'Incudine della Furia, un manufatto leggendario \"\n\"che molti cercano, ma che nessuno ha mai trovato. Forgiato con le ossa \"\n\"metalliche dei demoni dei pozzi taglienti, l'Incudine della Furia venne fusa \"\n\"circondata dai crani dei cinque più potenti stregoni dell'aldilà. Cesellata \"\n\"con rune di Caos e Potere, qualsiasi arma forgiata su questa Incudine \"\n\"acquista proprietà magiche ignote. Si dice che la natura imprevedibile del \"\n\"Caos, renda impossibile sapere quali saranno le conseguenze della forgiatura.\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Non pensi che Griswold sia la persona più adatta a cui domandarlo? Dopotutto \"\n\"questo è il suo campo.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Se tu stessi cercando informazioni sul Pestello della Cura o sul Calice \"\n\"d'Argento della Purificazione, ti avrei potuto assistere, amico mio. Ma in \"\n\"questo caso, ti converrebbe di più parlare con Griswold o addirittura con \"\n\"Cain.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Il padre di Griswold era solito raccontarci quando eravamo piccoli, di una \"\n\"gigantesca incudine usata per fabbricare potenti armi. Diceva che quando un \"\n\"martello colpiva quest'incudine il suolo tremava con una grande furia. \"\n\"Ricordo questa storia ogni volta che la terra si muove.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Benvenuto! è sempre un piacere vedere uno dei miei migliori clienti! So che \"\n\"stai penetrando sempre più nel Labirinto, e c'è una storia che mi hanno \"\n\"raccontato che potrebbe interessarti...\\n\"\n\" \\n\"\n\"Uno degli uomini che tornò dal Labirinto parlò di un'Incudine Mistica, in \"\n\"cui si imbatté durante la fuga. Il suo racconto mi ricordò alcune leggende \"\n\"che avevo sentito durante l'infanzia riguardo la fornace Infernale, nella \"\n\"quale venivano forgiate potenti armi magiche. Si narra che nelle profondità \"\n\"della fornace giaccia l'incudine della Furia! Quest'incudine contiene al suo \"\n\"interno l'essenza del mondo demoniaco...\\n\"\n\" \\n\"\n\"Qualunque arma forgiata su di essa si imbeve di un grande potere. Se \"\n\"quell'incudine è davvero l'Incudine della Furia, potrei essere in grado di \"\n\"fabbricarti un'arma capace di sconfiggere anche il più Oscuro Signore \"\n\"dell'Inferno!...\\n\"\n\" \\n\"\n\"Trovala, e mi metterò al lavoro!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Ancora niente,eh? Continua a cercare. Un'arma fatta su quell'incudine puo \"\n\"essere la nostra sola speranza e so di potertene fare una di proporzioni \"\n\"leggendarie.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Non riesco a crederci! Questa è l'Incudine della Furia, ottimo lavoro, amico \"\n\"mio. Ora mostreremo a quei bastardi che nessuna arma Infernale è più letale \"\n\"di una fatta da un uomo! Tieni, e che la luce ti protegga.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold non può vendere l'incudine. Poi cosa farebbe? Sarei infuriato se \"\n\"rubassero la mia incudine!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Ci sono molti manufatti nel labirinto con poteri oltre la comprensione dei \"\n\"mortali. Alcuni contengono fantastici poteri che possono essere usati sia \"\n\"dalla Luce che dall'Oscurità. Mettere al sicuro l'incudine potrebbe cambiare \"\n\"il corso della Guerra del Peccato verso la luce.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Se tu trovassi quel manufatto per Griswold, potresti rovinare l'andamento \"\n\"dei miei affari. Awww, tanto non lo troverai mai.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Il Cancello di Sangue e le Sale di Fuoco sono riferimenti di origine \"\n\"mistica. Ovunque tu abbia letto quel libro è sicuramente un luogo di grande \"\n\"potere.\\n\"\n\" \\n\"\n\"Le leggende parlano di un piedistallo d'ossidiana scolpita con una pozza di \"\n\"sangue ribollente sulla sua sommità d'ossa. Ci sono anche allusioni a Pietre \"\n\"di Sangue che apriranno una porta che cela un antico tesoro...\\n\"\n\" \\n\"\n\"La natura di questo tesoro è avvolta nel mistero, amico mio, ma si narra che \"\n\"l'antico eroe Arkaine nascose la sua armatura sacra Valor in un sotterraneo \"\n\"segreto. Arkaine fu il primo mortale che cambiò il corso della Guerra del \"\n\"Peccato ricacciando le legioni dell'oscurità negli Inferi Fiammeggianti.\\n\"\n\" \\n\"\n\"Poco prima che morisse, la sua armatura fu nascosta in un luogo segreto. Si \"\n\"dice che quando ce ne sarà bisogno, sorgerà un eroe che indosserà Valor \"\n\"ancora una volta. Forse tu sei quell'eroe...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Ogni bambino conosce la storia del guerriero Arkaine e della sua mistica \"\n\"Armatura Valor. Se tu trovassi il posto dov'è conservata, saresti ben \"\n\"protetto contro il male del Labirinto.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... Sembra qualcosa che dovrei sapere, ma sono stato così occupato a \"\n\"cercare nuove cure e a creare migliori elisir che ora non ricordo. Mi \"\n\"spiace...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Ho sentito spesso i ragazzi raccontarsi la storia dell'armatura magica \"\n\"chiamata Valor. Prova a chiederlo a uno degli uomini del villaggio.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"L'armatura nota come Valor potrebbe essere la cosa che aumenterà le \"\n\"opportunità a tuo favore. Molti l'hanno cercata - me compreso. Ma Arkaine la \"\n\"nascose bene, amico mio, ti servirà più di un pizzico di fortuna per svelare \"\n\"i segreti che l'hanno celata per tutti questi anni.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Se dovessi trovare queste Pietre di Sangue, usale con attenzione. \\n\"\n\" \\n\"\n\"La strada sarà piena di pericoli e dovrai avere molta fiducia in te stesso.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Intendi trovare l'armatura nota come Valor? \\n\"\n\" \\n\"\n\"Nessuno ha mai capito dove Arkain l'abbia nascosta, e se i miei contatti non \"\n\"l'hanno potuta trovare, dubito fortemente che tu ci riuscirai.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"So solo di una leggenda che narra del guerriero che hai descritto. La sua \"\n\"storia si può trovare nelle Antiche Cronache della Guerra del Peccato...\\n\"\n\" \\n\"\n\"Macchiato da mille anni di guerra, sangue e morte, il Comandante del Sangue \"\n\"si erge su una montagna di vittime lacerate. La sua Lama nera lancia \"\n\"un'oscura Maledizione ai vivi; un tormentoso invito per chiunque incontri \"\n\"questo Carnefice dell'Inferno.\\n\"\n\" \\n\"\n\"Si dice che anche se un tempo fu un mortale che combatté con l'oscurità \"\n\"durante la guerra del peccato, perse l'umanità per la sua insaziabile sete \"\n\"di sangue.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Temo di non aver mai sentito parlare di un Guerriero così Perverso, Signore. \"\n\"Spero che tu non debba lottare contro di lui, mi sembra sia estremamente \"\n\"pericoloso.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain saprà dirti più cose a riguardo, di quante io possa mai sperare di \"\n\"conoscere.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Se devi batterti contro un così feroce avversario, che la luce sia la tua \"\n\"guida e la tua protezione. Pregherò per te.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Oscure e malvagie leggende circondano il Comandante del Sangue. Preparati \"\n\"amico mio, egli non esita e non ha pietà.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Devi sempre parlare di Sangue? Perché non di fiori, della luce del sole, o \"\n\"di quella bella ragazza che porta da bere. Ascolta, amico, sei davvero \"\n\"ossessionante, sai?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"La sua abilità con la spada è terrificante, ha vissuto per migliaia d'anni \"\n\"conoscendo solo guerra. Mi spiace... ma non so predire se lo sconfiggerai.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Non ho mai avuto a che fare con questo Comandante, ma da come ne parli pare \"\n\"che necessiti di molte spade. Mi piacerebbe armare il suo esercito...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"La mia spada brama il tuo sangue, mortale, e per i miei padroni non la \"\n\"deluderò.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold parlò della Pietra Celeste destinata all'Enclave situata ad \"\n\"oriente. Sarebbe stata portata là per ulteriori studi. Questa pietra arde di \"\n\"un'energia che concede di vedere al di là delle normali possibilità di un \"\n\"uomo. Non so che segreti contenga, amico mio, ma il ritrovamento di questa \"\n\"pietra si dimostrerebbe certamente molto importante.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"La carovana si fermò qui per rifornirsi per il loro viaggio verso est. Ho \"\n\"venduto loro della frutta fresca e delle eccellenti animelle che Garda aveva \"\n\"appena sfornato. Fu un peccato quello che capitò loro...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Io non so cosa pensano di poter trovare in quella pietra, ma ti dirò una \"\n\"cosa. Se le pietre iniziano a cadere dal cielo, tu faresti meglio a stare \"\n\"attento!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Si, una carovana composta da delle persone importanti si fermò qui, ma \"\n\"accadde tanto tempo fa. Avevano accenti strani e stavano per fare un lungo \"\n\"viaggio, per quel che mi ricordo. \\n\"\n\" \\n\"\n\"Non vedo come potresti sperare di trovare quello che stavano trasportando.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Fermati un momento, ho una storia che potresti trovare interessante. Una \"\n\"carovana diretta ai regni orientali, passò da qui qualche tempo fa. Si \"\n\"presume portasse un pezzo di Paradiso caduto sulla terra! La carovana fu \"\n\"assalita da cavalieri incappucciati appena a nord di qui lungo il tragitto. \"\n\"Ispezionai tra i rottami per trovare questa pietra del cielo, ma non c'era. \"\n\"Se tu dovessi trovarla, credo di poterti creare qualcosa di utile.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Sto ancora aspettando che tu mi porti la Pietra del Paradiso. So di poterti \"\n\"creare qualcosa di molto potente con essa.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Fammi dare un'occhiata... si... si, è come credevo. Aspetta...\\n\"\n\" \\n\"\n\"Ah, eccolo qua. Ho sistemato alcuni frammenti della pietra in un anello \"\n\"d'argento lasciatomi da mio padre. Spero possa aiutarti.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Avevo un bell'Anello; uno molto prezioso, con pietre blu e verdi e rosse e \"\n\"d'argento. Però non ricordo che fine fece. Mi manca molto quell'anello...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"La Pietra del Paradiso è molto potente, se altri al posto di Griswold ti \"\n\"avessero chiesto di trovarla, l'avrei impedito. Lui vuole usare quei poteri \"\n\"per il bene di noi tutti.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Se c'è qualcuno che può trarre qualcosa da quella pietra, quello è Griswold. \"\n\"Sa quello che fa, e rispetto il suo lavoro per quanto cerchi di rubargli i \"\n\"clienti.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Adria la strega sta cercando un fungo nero? So tanto di funghi neri quanto \"\n\"di aringhe rosse. Forse Pepin il Guaritore può dirti di più, purtroppo \"\n\"questo è qualcosa che non può essere trovato in nessuno dei miei libri.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Permettimi di dire solo una cosa. Né Garda né io, potremmo mai servire \"\n\"funghi neri ai nostri stimati ospiti. Se Adria vuole funghi per il suo \"\n\"stufato, sono affari suoi, ma non posso aiutarti a trovarli. Funghi neri... \"\n\"disgustoso!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"La strega mi ha detto che stai cercando il cervello di un demone per \"\n\"aiutarmi nella creazione del mio elisir. Sarebbe di grande aiuto per i tanti \"\n\"che sono stati feriti da quelle orribili bestie, se potessi svelare i \"\n\"segreti che penso contenga la sua alchimia. Se rimuoverai il cervello di un \"\n\"demone dopo averlo ucciso, ti sarei grato se me lo portassi.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Eccellente, proprio quello che avevo in mente. Sono stato in grado di finire \"\n\"l'elisir senza questo, ma non farà male studiarlo. Per favore potresti \"\n\"portare questo alla strega? Credo che lo stia aspettando.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Penso che Ogden possa avere dei funghi in cantina. Perché non chiedi a lui?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Se Adria non ne ha nemmeno uno, puoi scommettere che è davvero una cosa \"\n\"rara. Non posso offrirti molto più aiuto di questo ma sembra che sia... un \"\n\"grosso, enorme, gigantesco fungo! Beh, buona caccia, allora.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden ha fatto una mistura con un CATTIVO fungo nero, mi ammalerei \"\n\"bevendolo. Ascolta, ascolta... ecco il segreto - la moderazione è la chiave!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Cosa abbiamo qui? Interessante, sembra un libro di reagenti. Tieni gli occhi \"\n\"aperti per un Fungo Nero. Dovrebbe essere abbastanza grande e facile da \"\n\"identificare. Se lo trovi, portamelo, lo farai?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Ho bisogno di un grosso fungo nero. Ora vai a cercarlo e portamelo, così che \"\n\"possa ultimare una mistura speciale a cui sto lavorando.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Si, questo è perfetto per l'infuso che sto preparando. A proposito, il \"\n\"Guaritore sta cercando il cervello di un demone così da curare chi è stato \"\n\"intossicato dal loro veleno. Credo voglia preparare un antidoto. Se lo \"\n\"aiuterai a procurarsi ciò di cui ha bisogno, per favore, vedi se puoi farti \"\n\"dare un campione di quell'elisir per me.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Perché lo hai portato da me? Non ho bisogno del cervello di un demone. Mi \"\n\"serve solo l'elisir al quale il Guaritore sta lavorando. È lui che ha \"\n\"bisogno di questo bizzarro organo, e ricordati di portarmi un po' di elisir. \"\n\"Pensi di farcela?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Cosa? Ora mi porti l'elisir del guaritore? Sono stata in grado di finire il \"\n\"mio infuso anche senza. Puoi anche tenertelo...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Non vendo alcun tipo di fungo di qualsiasi forma o colore. Che ne dici di \"\n\"qualcosa di più utile?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Quindi la leggenda della mappa è vera. Non credevo esistesse veramente! \"\n\"Penso sia il tempo che ti riveli chi sono, amico mio. Vedi, non sono quello \"\n\"che sembro...\\n\"\n\" \\n\"\n\"Il mio vero nome è Deckard Cain il Saggio, l'ultimo discendente di una \"\n\"antica Fratellanza che ha il compito di custodire i segreti di un male senza \"\n\"tempo. Un male che a quanto pare è riuscito a liberarsi...\\n\"\n\" \\n\"\n\"Sappi solo che il male contro cui ti batterai è l'Oscuro Signore del Terrore \"\n\"- conosciuto fra i mortali col nome di Diablo. Fu lui che venne imprigionato \"\n\"nel Labirinto molti secoli fa. La Mappa che ti porti appresso fu creata \"\n\"molti anni fa per indicare il tempo in cui Diablo sarebbe risorto dalla sua \"\n\"prigionia. Quando le due stelle si allineeranno, Diablo giungerà al massimo \"\n\"del suo potere. E potrebbe diventare invincibile...\\n\"\n\" \\n\"\n\"Ora sei in corsa contro il tempo, amico mio! Trova Diablo e distruggilo \"\n\"prima dell'allineamento, forse non avrai altre possibilità di liberare di \"\n\"nuovo il mondo dal male!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Il tempo stringe! Sento crescere la sua Energia Oscura e solo tu puoi \"\n\"fermarlo dal raggiungere la sua piena potenza.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Sono sicuro che farai del tuo meglio, ma temo che nemmeno la tua forza potrà \"\n\"bastare. Diablo ora è al massimo del suo potere, e tu avrai bisogno di tutto \"\n\"il tuo coraggio e della tua forza per sconfiggerlo. Che possa la luce \"\n\"guidarti e proteggerti, amico mio. Io farò quel che posso per aiutarti.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Se la strega non ti ha aiutato e ti ha suggerito di vedere Cain, cosa ti fa \"\n\"pensare che io possa farlo? Questa, sembra una questione molto seria. Ti \"\n\"dovresti sbrigare, e dovresti consultare Cain come ha detto Adria.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Non so dirti molto su questa mappa, ma forse Adria o Cain potrebbero \"\n\"aiutarti a decifrarla, e a capire che cosa essa rappresenti realmente. \\n\"\n\" \\n\"\n\"Io posso solo dirti che illustra le stelle del nostro cielo, altro non so.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Faresti meglio a chiedere questo genere di cose al Narratore. \\n\"\n\" \\n\"\n\"Cain è molto informato sulle scritture antiche, di sicuro quello che mi hai \"\n\"mostrato è il pezzo di carta più vecchio che abbia mai visto.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Non ho mai visto prima d'ora una mappa di questo tipo. Dove l'hai trovata? \"\n\"Non ho idea di come si legga, ma penso che Cain o Adria potrebbero essere in \"\n\"grado di farlo.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Ascolta, vieni qui. Io non so se tu sai quello che so, ma hai trovato \"\n\"davvero qualcosa. Quella è una mappa.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Oh, non è un buon segno. Questa mappa delle stelle predice un grande \"\n\"disastro, ma non tocca me rivelarti i suoi segreti. È giunto il momento per \"\n\"te di fare una conversazione molto seria col Narratore...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Sto cercando una mappa, ma certamente non è quella. Dovresti mostrarla ad \"\n\"Adria - lei probabilmente può dirti cos'è. Ti dirò una cosa; sembra antica, \"\n\"e di solito antico vuol dire prezioso.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Per favoreeee, no male. No uccidere. Prossima volta fare bel dono per te.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Sto facendo qualcosa per te. Ancora, non uccidere Gharbad. Lascialo vivere.\\n\"\n\" \\n\"\n\"Tieni questo come prova di fiducia...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Ancora Niente! Quasi fatto. \\n\"\n\" \\n\"\n\"Molto potente, molto forte. Si! Si! \\n\"\n\" \\n\"\n\"No dolore, e promessa mantengo!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Questo troppo per te. Molto Potente! Se vuoi - tu prendere!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Cosa? Perché sei qui? Tutte queste interruzioni mi faranno impazzire. Ecco, \"\n\"prendi questo e lasciami lavorare. E non disturbarmi più!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! La tua curiosità ti porterà alla morte!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Ciao, amico mio. Resta un po' e ascolta...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Mentre ti avventuri sempre più nel Labirinto potresti trovare dei Tomi di \"\n\"grande conoscenza. \\n\"\n\" \\n\"\n\"Leggili attentamente perché possono dirti cose che nemmeno io so.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Conosco molti miti e leggende che possono contenere risposte a domande che \"\n\"ti farai durante i tuoi viaggi nel Labirinto. Se ti imbatti in qualche sfida \"\n\"o domanda della quale ti serve una risposta, chiedimelo e io ti dirò quello \"\n\"che posso.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold? è un uomo d'azione e di grande coraggio. Scommetto che non ti ha \"\n\"raccontato di quando lui è andato nel Labirinto per salvare Wirt, Vero? \"\n\"Sapeva a quali pericoli andava in contro, andando là, e ora anche tu... fai \"\n\"lo stesso. Lui è un artigiano specializzato, e se dice di poterti aiutare, \"\n\"conta pure sulla sua abilità e la sua onestà.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden ha comprato e gestisce la Locanda del Sol Levante da quasi quattro \"\n\"anni. La comprò alcuni mesi prima che le cose qui diventassero un inferno. \"\n\"Lui e sua moglie Garda non hanno i soldi per andarsene perché hanno \"\n\"investito tutti i loro averi per farsi una vita qui. È un brav'uomo e con un \"\n\"profondo senso di responsabilità.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Povero Farnham. Lui è un inquietante promemoria del gruppo condannato ad \"\n\"entrare nella Cattedrale con Lazarus, in quel nero giorno. Riuscì a \"\n\"salvarsi, ma il suo coraggio e la sua sanità mentale rimasero laggiù \"\n\"nell'oscurità. Oggi trova conforto solo sul fondo del suo boccale, ma a \"\n\"volte si distinguono brandelli di verità nel suo vaneggiare.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"La strega, Adria, è un'anomalia qui a Tristram. Giunse poco dopo che la \"\n\"Cattedrale venne sconsacrata, mentre molti di noi se ne stavano andando. \"\n\"Costruì, a quanto pare in una notte, una piccola capanna ai limiti della \"\n\"città e ha accesso a strani e arcani manufatti e tomi di conoscenza, che \"\n\"nemmeno io avevo mai visto prima.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Quella di Wirt è una storia tanto spaventosa quanto tragica. Venne rapito \"\n\"alla madre e trascinato nel Labirinto, lasciato preda di piccoli e orribili \"\n\"demoni. Furono presi molti altri bambini quel giorno, incluso il figlio di \"\n\"Re Leoric. I Cavalieri del palazzo andarono la sotto, ma non ritornarono \"\n\"mai. Fu il Fabbro a ritrovare il ragazzo, ma solo dopo che le bestie avevano \"\n\"incominciato a torturarlo per i loro sadici piaceri.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Lui per me è un vero amico, forse il migliore che ho. A volte è \"\n\"un po' confuso, ma non esiste nessuno con un animo così premuroso. Pochi \"\n\"eguagliano la sua conoscenza e le sue abilità, e la sua porta è sempre \"\n\"aperta.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian è una bella donna. Molto amata per il suo spirito e la risata \"\n\"facile, ha un posto speciale nel mio cuore. Lavora alla taverna per aiutare \"\n\"sua nonna, che è troppo malata per viaggiare. A volte temo per la sua \"\n\"sicurezza, ma so che ogni uomo del villaggio morirebbe piuttosto che vederla \"\n\"ferita.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Salve, signore. Benvenuto alla Taverna del Sol Levante!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Molti avventurieri hanno onorato le tavole della mia taverna, e le storie \"\n\"raccontate sono state dieci volte la birra consumata. L'unica cosa su cui \"\n\"tutti erano d'accordo era questo vecchio assioma. Forse ti aiuterà. Puoi \"\n\"tagliare la carne, ma devi spezzare le ossa.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Griswold il fabbro è bene informato su armi e armature. Se hai bisogno di \"\n\"fare modifiche al tuo equipaggiamento, lui è di sicuro l'uomo che cerchi.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham passa fin troppo tempo qui, affogando i suoi dolori con birra da due \"\n\"soldi. Io lo manderei via, ma ha sofferto troppo mentre era nel Labirinto.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria è molto saggia per la sua età, ma devo ammettere che mi spaventa un \"\n\"po'. \\n\"\n\" \\n\"\n\"Beh, non importa. Se hai bisogno di trattare articoli magici, lei possiede \"\n\"una capanna stranamente ben fornita al di là del fiume.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Se vuoi saperne di più sulla storia del nostro villaggio, Cain il narratore \"\n\"sa un bel po' di cose sul passato.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt è un furfante e un piccolo farabutto. Si mette sempre nei guai, non fui \"\n\"sorpreso per quello che gli accadde. \\n\"\n\" \\n\"\n\"Probabilmente si aggirava in qualche posto dove non sarebbe mai dovuto \"\n\"andare. Mi dispiace per il ragazzo, ma non sopporto le compagnie che \"\n\"frequenta.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin è una brava persona - certamente il più generoso del villaggio. Cerca \"\n\"sempre di prestare attenzione ai bisogni degli altri, ma problemi di ogni \"\n\"sorta sembrano seguirlo ovunque lui vada...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, la mia Cameriera? Sarebbe fuggita da qui tempo fa, se non fosse per \"\n\"la sua riconoscenza verso la nonna. \\n\"\n\" \\n\"\n\"Dio sa se non l'ho implorata di andar via, dicendole che avrei pensato io a \"\n\"lei, ma è troppo dolce e premurosa, per comportarsi così.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Come ti senti, amico mio?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Ho fatto una scoperta molto interessante. Diversamente da noi, le creature \"\n\"nel Labirinto possono guarirsi senza l'aiuto di pozioni o magie. Se tu \"\n\"ferissi uno di quei mostri, assicurati che sia morto, perché potrebbe \"\n\"rigenerarsi.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Prima di essere presa da qualunque cosa si celi lì sotto, la Cattedrale era \"\n\"un luogo di cultura. Potresti scoprire molti libri nella tua cerca. Leggili \"\n\"tutti, alcuni potrebbero contenere segreti di quello che sta succedendo nel \"\n\"Labirinto.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold conosce tanto dell'arte della guerra quanto io dell'arte curativa. \"\n\"È un mercante astuto, ma il suo lavoro non ha rivali. Oh, penso che potrebbe \"\n\"essere perché è l'unico fabbro rimasto qui.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain è un vero amico ed un saggio avveduto. Possiede una vasta biblioteca e \"\n\"l'abilità di discernere la vera natura di molte cose. Se avessi mai una \"\n\"domanda, lui è la persona a cui rivolgersi.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Persino le mie abilità sono state incapaci di guarire pienamente Farnham. \"\n\"Curai il suo corpo, ma mente e spirito sono aldilà delle mie capacità.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Anche se uso alcune forme limitate di magia per creare le pozioni che tengo \"\n\"qui, Adria è una vera incantatrice. Non sembra dormire mai, e ha sempre \"\n\"accesso a molti artefatti e tomi mistici. Credo che la sua capanna sia molto \"\n\"più del tugurio a cui assomiglia, ma non sono mai riuscito ad entrarvi.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Povero Wirt. Feci tutto il possibile per il ragazzo, ma so che lui disprezza \"\n\"quel piolo di legno che sono stato costretto ad attaccagli alla gamba. Le \"\n\"sue ferite erano orrende, nessuno dovrebbe soffrire così, tanto meno un \"\n\"ragazzo giovane.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Non capisco perché Ogden rimanga a Tristram. Ha qualche problema di nervi, \"\n\"ma un uomo intelligente e ingegnoso come lui avrebbe successo ovunque \"\n\"andasse. Forse è la paura dei molti omicidi che si verificano nella campagna \"\n\"circostante, o forse è la volontà della moglie che trattengono qui lui e la \"\n\"sua famiglia.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"La Cameriera di Ogden è una ragazza dolce. Sua nonna è piuttosto malata, e \"\n\"soffre di allucinazioni.\\n\"\n\"\\n\"\n\"Lei afferma che sono visioni, ma io non ho nessuna prova che sia vero.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Buondì! Come posso servirti?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Mia nonna ha sognato che saresti venuto e avresti parlato con me, ha delle \"\n\"visioni, sai, e può scorgere il futuro.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"La donna ai confini della città è una strega! Sembra simpatica, e il suo \"\n\"nome, Adria, è piacevole all'orecchio, ma mi terrorizza. \\n\"\n\"\\n\"\n\"Ci vorrebbe qualcuno di coraggioso, come te, per sapere cosa fa laggiù.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Il nostro Fabbro è un punto d'orgoglio alle persone di Tristram. Non solo è \"\n\"un ottimo artigiano che ha vinto molte dispute all'interno della sua gilda, \"\n\"ma ricevette encomi da Re Leoric stesso - Pace all'anima sua. Griswold è \"\n\"anche un grande eroe; Domandalo a Cain.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain è stato il cantastorie di Tristram da quando riesco a ricordare. Sa \"\n\"molto, e ti può informare su tutto quel che c'è da sapere riguardo ogni cosa.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham è un ubriacone che si riempie la pancia di birra e le orecchie degli \"\n\"altri con sciocchezze. \\n\"\n\" \\n\"\n\"So che sia Pepin che Ogden provano simpatia per lui, ma è frustrante vederlo \"\n\"scivolare sempre più profondamente in un confuso torpore ogni notte.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin salvò la vita di mia nonna, e so che non potrò mai ripagarlo per \"\n\"questo. La sua abilità di guarire i malati è più potente della spada più \"\n\"maestosa, e più misteriosa di ogni incantesimo che puoi nominare. Se hai \"\n\"bisogno di cure, Pepin può aiutarti.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Sono cresciuta con la madre di Wirt, Canace. Anche se era solo lievemente \"\n\"ferita quando quelle orrende creature lo rapirono, non si riprese più. Penso \"\n\"sia morta di crepacuore. Wirt è diventato un cattivo ragazzo, cerca solo il \"\n\"profitto attraverso gli sforzi degli altri. So che ha sofferto e ha visto \"\n\"orrori che non posso nemmeno immaginare, ma l'oscurità incombe ancora su di \"\n\"lui.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden e sua moglie hanno accolto me e la nonna in casa loro, permettendomi \"\n\"di guadagnare qualche soldo lavorando alla locanda. Devo molto a loro, e \"\n\"spero un giorno di lasciare questo posto ed aiutarli ad aprire un grande \"\n\"albergo all'est.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Bene, che posso fare per te?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Se cerchi una buona arma, lascia che ti faccia vedere questo. Prendi un \"\n\"corpo contundente, come una mazza. Funziona alla perfezione contro molti di \"\n\"quegli orrori non-morti laggiù, e non c'è niente di meglio per schiantare \"\n\"scheletrini!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"L'Ascia? Ah, quella è una buona arma, bilanciata rispetto ad ogni nemico. \"\n\"Guarda come fende l'aria, e ora immagina la testa di un demone sul suo \"\n\"cammino. Ricorda, però, che il colpo è lento da vibrare - ma lascia un bel \"\n\"segno!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Osserva questo filo e questo bilanciamento. Una spada nelle mani giuste, e \"\n\"contro il nemico giusto, è la signora di tutte le armi. La sua lama affilata \"\n\"trova poco da tagliare o trafiggere sui non-morti, ma affetterà le carni dei \"\n\"nemici vivi e respiranti!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Le tue armi e la tua armatura porteranno i segni della lotta contro \"\n\"l'oscurità. Se me li porterai, un po' di lavoro e una fornace calda, li \"\n\"riporteranno alla loro migliore condizione.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Mentre io devo praticamente contrabbandare i metalli e gli strumenti di cui \"\n\"ho bisogno dalle carovane che passano per i limiti della nostra maledetta \"\n\"città, Adria ha sempre quello di cui necessita. Se potessi controllare solo \"\n\"un po' della sua magia, potrei fare cose veramente incredibili.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian è una brava ragazza. Peccato che sua nonna sia in poca salute, \"\n\"altrimenti avrei cercato di farle andare lontano da qui con una delle \"\n\"carovane.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"A volte credo che Cain parli troppo, ma credo sia il suo destino. Se potessi \"\n\"piegare l'acciaio come lui è in grado di far tendere le orecchie. Potrei \"\n\"fare un'armatura decorata degna di un imperatore!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Ero con Farnham la notte in cui Lazarus ci guidò nel Labirinto. Non ho più \"\n\"rivisto l'Arcivescovo, e potrei non essere qui se Farnham non fosse stato al \"\n\"mio fianco. Ho paura che l'attacco abbia lasciato un segno nella sua anima. \"\n\"Non posso combattere questa battaglia per lui, ma se potessi lo farei.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Un buon uomo che mette i problemi degli altri al di sopra dei suoi. Non \"\n\"troverai nessuno a Tristram - o da qualsiasi altra parte - che abbia brutte \"\n\"cose da dire sul guaritore.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Quel ragazzo sta per ficcarsi in guai seri... e aggiungerei, di nuovo. Ho \"\n\"provato ad appassionarlo al lavoro qui e a fargli imparare un commercio \"\n\"onesto, ma preferisce ottenere alti guadagni trafficando con beni di dubbia \"\n\"origine. Non posso biasimarlo dopo quello che gli è accaduto, ma vorrei che \"\n\"facesse almeno attenzione.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Il Taverniere fa pochi affari e non ha nessun modo di trarre un profitto. \"\n\"Cerca di guadagnare qualcosa fornendo vitto e alloggio per quelli che \"\n\"passano di tanto in tanto per il villaggio, ma è più probabile che fuggano \"\n\"nella notte piuttosto che lo paghino. Se non fosse per le riserve di \"\n\"granaglie e carne secca che teneva in cantina, molti di noi sarebbero morti \"\n\"di fame durante il primo anno quando l'intera campagna era infestata dai \"\n\"demoni.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Un uomo non può bere in pace?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"La ragazza che porta da bere? Oh, si, Che ragazza carina. Così attraente.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Perché quella vecchiaccia non fa qualcosa tanto per cambiare. D'accordo, ha \"\n\"delle qualità, ma ascoltami... non è normale. Non l'ho mai vista bere o \"\n\"mangiare - e non puoi fidarti di qualcuno che non beve almeno un po'.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain non è chi dice di essere. Certo, racconta belle storie... alcune sono \"\n\"davvero paurose o divertenti... ma penso che lui sappia più di quanto ci \"\n\"mostri.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Buon Vecchio Griswold! L'amo come un fratello! Lottammo insieme, \"\n\"sai, quando... noi... Lazarus...  Lazarus... Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, mi piace Pepin. A volte ci prova veramente. Ascoltami, devi \"\n\"assolutamente conoscerlo. Una brava persona a cui piacciono le persone in \"\n\"cerca d'aiuto. Ehi, credo che sia un po' come te, huh, eroe? Anch'io ero un \"\n\"eroe...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt è un ragazzo con più problemi di me, e conosco tutto sui problemi. \"\n\"Ascolta, il ragazzo sta facendo buoni affari, ma è stato là, sai? Ha perso \"\n\"una gamba! Cammina su un pezzo di legno. Molto triste, molto triste...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden è il miglior uomo in città. Non penso di piacere a sua moglie, ma \"\n\"finché continuerà a spillare vino, mi starà simpatica. Sembra che io passi \"\n\"con Ogden la maggior parte del tempo, ma è così buono con me...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Voglio dirti una cosa, perché so tutto a riguardo. È la mia specialità. \"\n\"Questa è la migliore... laaa migliore! L'altra birra è disgustosa da quando \"\n\"quegli stupidi cani...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Nessuno mi as... ascolta. Da qualche parte - non sono sicuro - ma da qualche \"\n\"parte sotto la chiesa c'è un'enorme montagna d'oro. Splende, brilla e \"\n\"aspetta che qualcuno se la prenda.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"So che hai le tue idee, e so che non crederai a questo, ma quell'arma che \"\n\"hai lì - non è buona contro quei grossi mostri! Oh, non m'importa di quello \"\n\"che dice Griswold, non faranno mai le cose come si usava una volta...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Se fossi in te... e non lo sono... ma se lo fossi, venderei tutte le cose \"\n\"che hai e me ne andrei da qui. Il ragazzo là fuori... Ha sempre qualcosa di \"\n\"buono, ma devi dargli dell'oro o non ti mostrerà nemmeno quello che ha.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Sento un'anima in cerca di risposte...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"La saggezza si guadagna, non è data. Se scopri tomi di conoscenza,divora le \"\n\"loro parole. Se avessi già nozione dei misteri arcani scritti in un libro, \"\n\"ricorda - il tuo padroneggiarli può sempre migliorare.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Il potere maggiore è spesso quello dalla vita più corta. Potresti trovare \"\n\"parole di potere scritte su pergamene. La loro forza giace nella possibilità \"\n\"per chiunque sia di lanciare incantesimi con uguale abilità. La loro \"\n\"debolezza sta nel fatto che prima devono essere lette ad alta voce e non \"\n\"possono essere ripetute. Sappi che questi rotoli possono essere letti solo \"\n\"una volta, quindi usali con cautela.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Anche se il calore del sole è oltre misura, la mera fiamma di una candela è \"\n\"un pericolo maggiore. Nessuna energia, per quanto grande, può essere usata \"\n\"senza una focalizzazione. Per molti incantesimi, Verghe istoriate possono \"\n\"essere ricaricate più volte con energie magiche. Ho la capacità di \"\n\"ristabilire quel potere, ma a pagamento ovviamente.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"La conoscenza è la somma di quella di tutte le persone. Se dovessi trovare \"\n\"un libro o una pergamena che non riesci a decifrare, non esitare a \"\n\"portarmela. Se posso trarne un senso lo spartirò con te.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Per chi conosce solo il ferro non c'è miglior magia dell'acciaio. C'è più \"\n\"del mago in Griswold di quanto non sappia. La sua abilità di unire fuoco e \"\n\"metallo è insuperata in questa zona.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"La corruzione ha la forza dell'inganno, ma l'innocenza detiene il potere \"\n\"della purezza. La giovane donna Gillian ha un cuore puro, ponendo gli \"\n\"interessi della sua patriarca sopra i propri. Mi teme, ma solo perché non mi \"\n\"comprende.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Uno scrigno aperto al buio, non contiene un tesoro maggiore di quando lo è \"\n\"alla luce. Cain il cantastorie è un enigma, ma solo per chi non osserva. La \"\n\"sua conoscenza di ciò che giace sotto la cattedrale è più grande di quanto \"\n\"lui si permetta di realizzare.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Più fiducia riponi in una persona, più è dura sopportare il tradimento. \"\n\"Farnham ha perso la sua anima, ma non per via di un demone. L'ha persa \"\n\"quando ha visto i suoi concittadini traditi dall'Arcivescovo Lazarus. Sa \"\n\"qualcosa, ma devi distinguere la realtà dalla fantasia.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Mente, corpo e anima possono compiere miracoli quando sono in perfetta \"\n\"armonia. Pepin il guaritore vede il corpo in una maniera a me sconosciuta. \"\n\"La sua capacità di curare malati e feriti è amplificata dalla sua conoscenza \"\n\"nella creazione di elisir e pozioni. È uno dei più grandi alleati che hai a \"\n\"Tristram.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"C'è molto del futuro che non sappiamo, ma quando arriverà, saranno i giovani \"\n\"che dovranno affrontarlo. Wirt ha un peso sull'animo, ma non è una minaccia \"\n\"per la città o per chi vi abita. I suoi affari segreti con misteriose gilde \"\n\"delle città vicine gli garantiscono accesso a molti oggetti che non possono \"\n\"essere facilmente trovati a Tristram. Anche se i suoi metodi sono \"\n\"riprovevoli, Wirt può fornirti assistenza per la tua battaglia contro \"\n\"l'oscurità.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Mura di pietra e tetti di paglia non fanno una casa. Ogden il locandiere ha \"\n\"più ruoli in questa città di quanti molti comprendano. Fornisce assistenza a \"\n\"Gillian e a sua nonna, mantiene la poca vita che Farnham ha ancora in sé, e \"\n\"garantisce un ricordo di quello che Tristram era a tutti quelli rimasti in \"\n\"città. La sua taverna, e i semplici piaceri che vi si possono trovare, danno \"\n\"un barlume di vita che la gente qui ricorda. È questo ricordo che continua a \"\n\"nutrire le loro speranze di un tuo successo.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... per di qua...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Non tutti in Tristram trovano un'utilità, o un mercato, per tutto quello che \"\n\"troverai nel labirinto. Nemmeno io, per quanto sia duro da credere.\\n\"\n\"\\n\"\n\"A volte solo tu sarai capace di trovare un uso per certi oggetti.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Non credere a tutto quel che dice l'ubriaco. Troppe birre annebbiano la \"\n\"vista e il buon senso.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"In caso non l'avessi notato, non compro niente a Tristram. Sono un \"\n\"importatore di beni di qualità. Se vuoi vendere spazzatura, rivolgiti a \"\n\"Griswold, Pepin o alla strega, Adria. Sono sicuro che addenteranno qualsiasi \"\n\"cosa tu possa portar loro...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Penso di dovere al fabbro la vita, o almeno quel che ne è rimasto. È vero, \"\n\"Griswold mi ha offerto un apprendistato alla fucina, ed è un buon tipo, ma \"\n\"non potrò mai fare abbastanza soldi da... beh, diciamo solo che ho dei piani \"\n\"che richiedono un vasto ammontare d'oro.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Se fossi solo un po' più vecchio, la coprirei di ricchezze, e ti assicuro \"\n\"che posso mettere le mani su oggetti molto preziosi. Gillian è una \"\n\"bellissima ragazza che dovrebbe lasciare Tristram finché è ancora sicuro. \"\n\"Hmm... forse la porterò con me quando me ne andrò...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain sa troppe cose. Mi terrorizza - anche più della donna aldilà del fiume. \"\n\"Continua a ripetermi quanto sono fortunato ad essere vivo, e come la mia \"\n\"storia sia profetizzata nelle leggende. Penso sia mezzo impazzito.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - quello è un uomo con seri problemi, e io so quanto seri possono \"\n\"esserlo. Ha creduto troppo nell'onestà di un uomo, e Lazarus l'ha guidato \"\n\"verso la morte. Oh, so come stanno le cose laggiù, quindi non iniziare \"\n\"nemmeno a parlarmi dei tuoi progetti d'eliminare il male che dimora nel \"\n\"Labirinto. Solo, fa attenzione alle tue gambe...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Finché non hai bisogno di riattaccarti qualcosa il vecchio Pepin è il \"\n\"migliore. \\n\"\n\"\\n\"\n\"Se avessi avuto alcune delle pozioni che rimesta, forse avrei ancora la \"\n\"gamba...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria fa paura. Cain dà i brividi per quello che può dirti sul passato, ma \"\n\"quella strega può vedere nel tuo passato. Inoltre, ha sempre un modo per \"\n\"avere quello di cui ha bisogno. Adria mette le mani su più mercanzia di \"\n\"quella che ho visto passare per i cancelli del Bazar Reale in piena festa.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden è un pazzo a rimanere qui. Posso farlo uscire dalla città ad un prezzo \"\n\"ragionevole, ma continua ad insistere a mandare avanti quella stupida \"\n\"taverna. Almeno da a Gillian un lavoro, e sua moglie Garda prepara una \"\n\"superba torta del pastore a base di carne e patate.\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Oltre la Sala degli Eroi si trova la Camera d'Ossa. Morte eterna attende \"\n\"coloro che cercassero di rubare i tesori protetti in essa. Così parla il \"\n\"Signore del Terrore, e così è scritto.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...e così, chiusa oltre l'Ingresso di Sangue e la Sala di Fuoco, Valor \"\n\"attende l'Eroe della Luce per svegliarsi...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Posso veder quel che tu non puoi.\\n\"\n\"S'offusca la vista negli occhi tuoi.\\n\"\n\"Se ti giri spariranno.\\n\"\n\"Canzon segrete sussurreranno.\\n\"\n\"Tu vedrai ciò che esser non può.\\n\"\n\"Ombre in luce muoversi un po'.\\n\"\n\"Lontani da luce e oscurità.\\n\"\n\"La Camera dei Ciechi ti opprimerà.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Nelle armerie infernali risiede il Signore del Sangue. Sul suo cammino \"\n\"giacciono migliaia di corpi mutilati. Senza distinzione angeli e uomini sono \"\n\"stati trucidati per i suoi sacrifici agli Oscuri che esigono solo una cosa - \"\n\"sangue.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Presta attenzione e porta testimonianza della verità che qui leggerai, \"\n\"perché sono l'ultimo lascito dell'Horadrim. C'è una guerra che infuria,ben \"\n\"oltre quello che conosciamo - fra gli utopici Regni Celesti e i pozzi \"\n\"caotici degli Inferni - Questa guerra è conosciuta come il Grande Conflitto, \"\n\"e dura da molto più delle stelle. Nessuna parte ha guadagnato influenza a \"\n\"lungo mentre la luce e l'oscurità continuano a gareggiare per il controllo \"\n\"su tutto il creato.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Presta attenzione e porta testimonianza delle verità che qui leggerai, \"\n\"perché sono l'ultimo lascito dell'Horadrim. Quando il Conflitto Eterno fra i \"\n\"Regni Celesti e gli Inferni Fiammeggianti si sposta su suolo mortale, è \"\n\"detta la Guerra del Peccato. Angeli e demoni girano in incognito fra gli \"\n\"uomini, combattendo in segreto lontani da occhi mortali. Alcuni potenti \"\n\"mortali si allearono con l'una o l'altra parte, e aiutarono a dettare il \"\n\"corso della guerra.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Presta attenzione e porta testimonianza delle verità che qui leggerai, \"\n\"perché sono l'ultimo lascito dell'Horadrim. Quasi trecento anni fa, i Tre \"\n\"Mali Maggiori degli Inferni Fiammeggianti giunsero misteriosamente nel \"\n\"nostro mondo. I tre fratelli devastarono l'oriente per decadi, mentre \"\n\"l'umanità tremava al loro passaggio. Il nostro ordine - l'Horadrim - fu \"\n\"fondato da un gruppo segreto di maghi per catturare i tre mali una volta per \"\n\"tutte.\\n\"\n\"\\n\"\n\"Gli Horadrim catturarono due dei tre all'interno di potenti artefatti noti \"\n\"come Pietre dell'Anima e li seppellirono nelle profondità dei deserti \"\n\"orientali. Il terzo male evitò la cattura e fuggì ad ovest con molti \"\n\"Horadrim sulle sue tracce. Il terzo male - conosciuto come Diablo, il \"\n\"Signore del Terrore - venne poi catturato, la sua essenza intrappolata in \"\n\"una pietra dell'anima e sepolta in questo Labirinto.\\n\"\n\"\\n\"\n\"Fai attenzione, la pietra dell'anima dev'essere celata a chi non è \"\n\"preparato. Se Diablo venisse liberato, cercherebbe un corpo facilmente \"\n\"controllabile perché sarebbe molto debole - probabilmente quello di un \"\n\"vecchio o di un bambino.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Così ebbe inizio un grande tumulto negli inferni fiammeggianti conosciuto \"\n\"come Esilio Oscuro. I Mali Minori spodestarono i Tre Mali Maggiori e \"\n\"bandirono le loro forme spirituali nel reame dei mortali. I demoni Belial \"\n\"(il Signore della Menzogna) e Azmodan (il Signore del Peccato) combatterono \"\n\"per affermare il proprio dominio sull'Inferno durante l'assenza dei tre. \"\n\"L'Inferno si divise fra le fazioni di Belial e Azmodan, mentre le forze \"\n\"celesti continuavano a premere sui Cancelli Infernali.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Molti demoni si spostarono nel reame dei mortali in cerca dei tre fratelli. \"\n\"Questi demoni vennero seguiti da Angeli che li perseguitarono attraverso le \"\n\"vaste città d'oriente. Gli angeli si allearono con un ordine segreto di \"\n\"maghi mortali chiamato Horadrim, che divennero ben presto maestri nel \"\n\"cacciare demoni. Si fecero anche molti oscuri nemici nei regni d'oltretomba.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Così accadde che i Tre Mali Maggiori furono banditi in forma spirituale nel \"\n\"reame dei mortali e dopo aver sparso caos in oriente per decadi, vennero \"\n\"cacciati dal maledetto Ordine Horadrim. L'Horadrim usò artefatti chiamati \"\n\"Pietre dell'Anima per contenere l'essenza di Mephisto, il Signore dell'Odio \"\n\"e di Baal, il Signore della Distruzione. Il fratello più giovane - Diablo, \"\n\"il Signore del Terrore - fuggì ad ovest.\\n\"\n\"\\n\"\n\"L'Horadrim riuscì poi a catturare anche Diablo in una Pietra dell'Anima, che \"\n\"venne sepolta sotto un'antica Cattedrale dimenticata. Qui, il Signore del \"\n\"Terrore dorme e attende il tempo della sua rinascita. Egli cercherà un corpo \"\n\"giovane e forte da possedere - uno che sia innocente e facile da \"\n\"controllare. Sorgerà quindi per liberare i suoi fratelli e attizzare le \"\n\"fiamme della Guerra del Peccato...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Tutti adorino Diablo - Signore del Terrore e Superstite dell'Esilio Oscuro. \"\n\"Quando si svegliò dal suo sonno, il mio Signore e Padrone mi parlò di \"\n\"segreti che pochi mortali conoscono. Mi raccontò di come i Regni Celesti e i \"\n\"Pozzi dell'Inferno si scontrarono in una eterna guerra. Mi rivelò i fatti \"\n\"che portarono questa lotta nei reami umani. Egli ha chiamato questa \"\n\"battaglia per questo mondo e per tutti quelli che vi abitano Guerra del \"\n\"Peccato.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Gloria e Onori a Diablo - Signore del Terrore e Capo dei Tre. Il mio Signore \"\n\"mi parlò dei suoi fratelli, Mephisto e Baal, banditi in questo mondo secoli \"\n\"fa. Egli attende per scatenare il suo immenso potere che può liberare i suoi \"\n\"fratelli rinchiusi nei loro sepolcri sotto le sabbie dell'est. Una volta che \"\n\"il mio Signore avrà liberato i suoi Fratelli, la Guerra del Peccato \"\n\"conoscerà di nuovo la furia dei Tre.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Saluti e onori a Diablo - Signore del Terrore e Distruttore d'Anime. Quando \"\n\"ho destato il mio Padrone dal suo sonno, tentò di possedere una forma \"\n\"mortale. Diablo provò a reclamare il corpo di Re Leoric, ma il mio Padrone \"\n\"era troppo provato dalla sua prigionia. Il mio Signore abbisognava di un \"\n\"innocente legame a questo mondo, e trovò il giovane Albrecht perfetto in \"\n\"questo ruolo. Mentre Re Leoric impazziva, per il fallito tentativo di \"\n\"possessione di Diablo, rapii Albrecht e lo donai al mio Padrone. Ora aspetto \"\n\"la chiamata di Diablo e spero in una ricompensa quando alla fine si ergerà \"\n\"come Signore del mondo.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Grazie al cielo sei tornato!\\n\"\n\"Molto è cambiato da quando vivevi qui amico mio. Tutto era pacifico fin \"\n\"quando i cavalieri neri non razziarono il villaggio. Molti vennero uccisi \"\n\"subito e quelli che si difesero furono trucidati o trascinati via per \"\n\"diventare schiavi, o peggio. La chiesa ai limiti del paese è stata \"\n\"sconsacrata ed è usata per oscuri rituali. Le urla che risuonano nella notte \"\n\"sono inumane, ma alcuni dei nostri compaesani potrebbero ancora essere vivi. \"\n\"Per trovare la chiesa segui il sentiero fra la mia taverna e la fucina, \"\n\"cerca di salvarli. \\n\"\n\" \\n\"\n\"Forse la prossima volta saprò dirti di più. Buona fortuna.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Perdura nella tua missione.  Trovare un tesoro disperso non è facile.  \"\n\"Scovare un tesoro celato ancor meno.  Ti lascio con questo.  Non lasciare \"\n\"che le sabbie del tempo confondano la tua ricerca.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Un cosa?!  Questa è follia.  Non c'è tesoro sepolto a Tristram.  Fammi \"\n\"vedere!  Ah, guarda questi disegni inesatti.  Non combaciano con la nostra \"\n\"città.  Rimarrò con la mente su ciò che si trova sotto la cattedrale e non \"\n\"su ciò che sta nel nostro sottosuolo.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Non ho veramente tempo di discutere sulla mappa che stai cercando.  Ho molta \"\n\"gente malata che richiede il mio aiuto e anche il tuo.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Il fiero Iswall è intrappolato nelle profondità di questo mondo.  Spogliato \"\n\"dell'onore e sfigurato in viso.  Egli è intrappolato in un tormento \"\n\"immortale.  Incaricato a celare la cosa che potrebbe liberarlo.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Scommetto che Wirt vedendoti arrivare improvvisò una sceneggiata per \"\n\"deriderti più tardi, quando avresti girato in città col tuo naso \"\n\"nell'immondizia.  Io l'ignorerei.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Ci fu un tempo in cui la città era meta frequente per viaggiatori \"\n\"provenienti da ogni dove.  Molto è cambiato da allora.  Ma caverne ignote e \"\n\"tesori sepolti sono fantasie comuni nei bambini.  Wirt fa di raro giochi \"\n\"infantili.  Quindi può esserselo solo immaginato.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Ascolta.  Vieni qui.  Io non so se tu sai quello che so, ma hai trovato \"\n\"davvero qualcosa.  Quella è una mappa.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Mia nonna mi racconta spesso storie riguardo strane forze sconosciute che \"\n\"popolano il cimitero al di fuori della chiesa.  Potrebbe interessarti \"\n\"sentirne una.  Ha detto che se lasci un'offerta adeguata nel cimitero, entri \"\n\"nella cattedrale per pregare i morti, e ritorni, l'offerta si sarebbe \"\n\"alterata in qualche strano modo.  Io non so se questi sono solo i \"\n\"vaneggiamenti di un'anziana donna malata, ma qualsiasi cosa pare possibile \"\n\"di questi giorni.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Hmmm.  Un tesoro vasto e misterioso, dici.  Mmmm.  Forse potrei essere \"\n\"interessato a raccogliere alcune cose da te.  O meglio ancora, non hai \"\n\"bisogno di rifornimenti rari e costosi per superare questo calvario?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Quindi, sei tu l'eroe di cui tutti parlano. Forse potresti aiutare un \"\n\"povero, umile contadino a uscire da un terribile guaio? Al confine del mio \"\n\"orto, appena a sud di qui, un terribile rigonfiamento è sbucato dal suolo! \"\n\"Non posso recarmi al mio raccolto o alle balle di fieno, le mie povere \"\n\"mucche moriranno di fame. La strega mi ha dato questo dicendo che avrebbe \"\n\"dilaniato quella cosa nel mio campo. Se potessi eliminarla, te ne sarei \"\n\"grato. Lo farei io, ma qualcuno deve badare alle mucche...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Sapevo che non sarebbe stato semplice come la strega l'ha fatto sembrare. \"\n\"Che mondo triste se non puoi fidarti del prossimo.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"È andato? L'hai rispedito negli oscuri recessi dell'Ade da dove era venuto? \"\n\"Tu cosa? Oh, non dirmi che l'hai perso! Queste cose sono sconvenienti, sai. \"\n\"Devi trovarlo, e distruggere quell'orrore scacciandolo dalla nostra città.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Ho udito l'esplosione fin qui! Grazie, generoso straniero. Con tutte queste \"\n\"cose provenienti dal sottosuolo, mostri che corrompono la chiesa, e così \"\n\"via, questi sono tempi duri. Sono solo un povero contadino, ma ecco, prendi \"\n\"questo con mia somma gratitudine.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Oh, che problema che ho...forse...No, non posso importelo, con tutti i \"\n\"problemi che hai. Forse dopo che avrai ripulito la chiesa da queste creature \"\n\"potresti ritornare... e dedicare un po' del tuo tempo per aiutare un povero \"\n\"contadino?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Waaaah! (sniff) Waaaah! (sniff)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Ho perso Theo!  Ho perso il mio migliore amico!  Giocavamo sul fiume, e Theo \"\n\"disse di voler andare a vedere la grande cosa verde.  Dissi che non \"\n\"dovevamo, ma sgattaiolammo fino a là, e improvvisamente questo INSETTO \"\n\"uscì!  Siamo fuggiti ma Theo cadde e l'insetto l'AFFERRò portandoselo via!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"L'hai trovato?  Ritrova Theodore, per favore!  È piccolo.  Non è in grado di \"\n\"prendersi cura di sé.  Ti prego!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"L'hai trovato!  L'hai trovato!  Grazie!  Oh Theo, quei brutti insetti ti \"\n\"hanno spaventato? Ehi! Ugh! Hai qualcosa attaccato alla pelle!  Ick!  Su, \"\n\"Theo, torniamo a casa!  Grazie di nuovo, eroico individuo!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Siamo rimasti a lungo sopiti, il tempo del risveglio è ormai giunto.  Dopo \"\n\"il nostro lungo sonno, siamo affamati.  Presto, ora, ci nutriremo...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Ti diverti, piccolo mammifero?  Com'è patetico. Il tuo piccolo mondo non \"\n\"sarà minimamente una minaccia.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Contamineremo queste terre, la nostra stirpe invaderà le distese che gli \"\n\"uomini chiamano casa.  I nostri viticci avvolgeranno il mondo, e noi \"\n\"banchetteremo con la carne dei suoi abitanti.  L'uomo sarà il nostro \"\n\"nutrimento.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, sento il tuo odore...sei vicino! Vicino! Ssss...odore di sangue e \"\n\"paura...com'è allettante...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"E nell'anno della Luce Dorata, fu decretato che una maestosa Cattedrale \"\n\"fosse eretta.  La pietra angolare di questo sacro luogo doveva essere \"\n\"scavata nella pietra traslucida di Antyrael, così chiamata in nome \"\n\"dell'Angelo che ha condiviso il suo potere con gli Horadrim.  \\n\"\n\"\\n\"\n\"Nell'anno designato all'Oscurità, la terra tremò e la Cattedrale cadde in \"\n\"frantumi.  Quando iniziò la costruzione di catacombe e castelli e l'uomo si \"\n\"oppose alle devastazioni della Guerra del Peccato, le rovine vennero \"\n\"spazzate via da tutte le loro pietre.  E così la pietra angolare svanì. \\n\"\n\"\\n\"\n\"La pietra era di questo mondo - e di tutti i mondi - come la luce è sia \"\n\"dentro che fuori da ogni cosa. La luce e l'unità sono le fondamenta di \"\n\"questa sacra creazione, un'unione di scopi e di beni.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Ho detto, Muu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Sono solo una mucca, OK?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Va bene, va bene.  Non sono una mucca.  Di solito non giro in questo modo; \"\n\"ero seduto a casa a farmi gli affari miei quando a un tratto questi insetti, \"\n\"tralci e bulbi e altro sono iniziati ad uscire fuori dal pavimento... \"\n\"orribile!  Se soltanto avessi qualcosa di decente da indossare, non sarebbe \"\n\"così male.  Ehi!  Potresti tornare alla mia dimora a prendere il mio \"\n\"vestito?  Quello marrone, non il grigio, che sfrutto solo di sera.  Lo farei \"\n\"io, ma non voglio che mi vedano conciato così.  Ecco, prendi questo, \"\n\"potrebbe servirti... per uccidere quelle cose che hanno invaso tutto.  Non \"\n\"puoi mancare la mia casa, è poco più a sud del biforcarsi del fiume... \"\n\"sai... quella con l'orto incolto.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Perché perdi tempo?  Riportami il vestito!  Sbrigati!  Quella Holstein \"\n\"laggiù continua a farmi l'occhiolino!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Ehi, hai preso il mio vestito?  Presto, passamelo!  Queste orecchie prudono \"\n\"come non crederesti mai!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"No no no no! Questo è l'abito GRIGIO!  È per la sera!  Da occasioni \"\n\"formali!  Non posso indossarlo.  Cosa sei, un tipo strambo?  Ho bisogno \"\n\"dell'abito MARRONE.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, MOLTO meglio.  Wow! Infine, un po' di dignità!  Le mie corna son \"\n\"dritte?  Bene.  Guarda, grazie dell'aiuto.  Ecco, prendi questo dono; e, \"\n\"sai.. una piccola dritta sulla moda... potresti usarne uno piccolo.. \"\n\"potresti usarne uno nuovo.. sai cosa intendo? Il vero motto \"\n\"dell'avventuriero è solo questo... retrò.  È solo un consiglio eh?  Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Guarda.  Io sono una mucca.  E tu, sei un'esca da mostro. Fai un po' di \"\n\"esperienza!  E poi parleremo...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"È veramente un terribile compito che ti ho posto innanzi. Se solamente \"\n\"potessi fare qualcosa... una caraffa di buon latte fresco, aiuterebbe?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Oh, potrei servirmi del tuo aiuto, ma solo dopo che salverai le catacombe \"\n\"dalla profanazione di quelle bestie.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Mi serve aiuto per una cosa, ma non posso imporlo a un perfetto estraneo. \"\n\"Forse dopo che sarai ambientato mi sentirò più a mio agio a esigere un \"\n\"favore.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Io vedo in te un potenziale di grandezza.  Forse un giorno mentre adempirai \"\n\"al tuo destino, potresti fermarti e farmi un piccolo favore?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Penso che potresti aiutarmi,ma forse dopo che sarai diventato un po' più \"\n\"potente. Non vorrei pregiudicare al villaggio l'unica possibilità di \"\n\"distruggere la minaccia nella chiesa!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Io, sono una mucca fatta da sé.  Realizzati pure tu, e... poi ne parleremo.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Non sono tenuto a giustificarmi con ogni turista che passa da qui!  Non hai \"\n\"dei mostri da uccidere?  Forse ne riparleremo dopo.  Se sarai vivo...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Smettila di irritarmi.  Sto cercando qualcuno di veramente eroico.  E tu non \"\n\"lo sei.  Non posso fidarmi di te, sarai mangiato dai mostri a giorni... \"\n\"Necessito di un eroe di una certa esperienza.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Va bene, diamoci un taglio col toro.  Non voglio sviarti.  Stavo seduto a \"\n\"casa, di malumore, quando le cose sono degenerate, un gruppo di mostri in \"\n\"fuga uscì dal pavimento!  Ero atterrito.  A malapena ho indossato questo \"\n\"travestimento da mucca del Jersey uscendo dalla porta, e ora guardo queste \"\n\"ridicole mammelle.  Se solo avessi qualcosa di normale da indossare, non \"\n\"sarebbe così male.  Ehi!  Potresti tornare alla mia dimora a prendere il mio \"\n\"vestito?  Quello marrone, non quello grigio, che sfrutto solo di sera.  Lo \"\n\"farei io, ma non voglio che nessuno mi veda conciato così.  Ecco, prendi \"\n\"questo, potrebbe servirti... per uccidere quella cosa che ha invaso tutto.  \"\n\"Non puoi mancare la mia casa, è poco più a sud del biforcarsi del fiume... \"\n\"sai... quella con l'orto incolto.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Ho provato incantesimi, minacce, abiura e negoziazione con questa disgustosa \"\n\"creatura -- inutilmente.  I miei metodi di costrizione dei demoni non hanno \"\n\"effetto su questa spaventosa bestia.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"La mia casa si sta lentamente contaminando dall'abiezione di questo \"\n\"prigioniero indesiderato.  Le cripte sono\\tpiene di ombre che si muovono \"\n\"svanendo dalla mia vista.  Il languido strisciare di artigli pulsa nelle mie \"\n\"orecchie. Loro stanno cercando, credo, questo diario.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Nel suo sbraitare, alla creatura è sfuggito il suo nome -- Na-Krul.  Ho \"\n\"indagato sul suo nome, ma i demoni minori hanno in qualche modo distrutto la \"\n\"mia biblioteca.  Na-Krul... Il nome mi fa raggelare.  Preferisco pensare a \"\n\"lui solamente come La Creatura piuttosto che al suo vero nome.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"La creatura intrappolata ulula con furia negandomi il sonno.  È accanita \"\n\"contro colui che l'ha segregata nel vuoto,e fa appello a sleali maledizioni \"\n\"su di me per intrappolarmi qui.  Le sue parole mi riempono il cuore di \"\n\"terrore,e non riesco a ignorare la sua voce.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Il mio tempo è giunto al termine.  Devo tramandare i modi per indebolire il \"\n\"demone, e nascondere i testi, affinché i suoi servitori non li usino per \"\n\"liberare il loro signore.  Mi auguro che chiunque trovi questo diario sia in \"\n\"cerca del sapere.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Chi trova questo libro ha il dovere di fermare la creatura demoniaca che si \"\n\"cela all'interno di queste mura.  Il mio tempo è finito. Anche ora, i suoi \"\n\"tirapiedi infernali graffiano da dietro la porta che li nasconde.  \\n\"\n\"\\n\"\n\"Ho bloccato il demone con arcane magie segregandolo dietro delle grandi \"\n\"mura, ma temo non sarà sufficiente. \\n\"\n\"\\n\"\n\"Gli incantesimi ritrovati nei miei tre grimori proteggeranno il suo \"\n\"possessore, ma solo se lanciati nel giusto ordine.  Le leve all'entrata \"\n\"rimuovono le barriere liberando il demone; non toccarle!  Usa solo questi \"\n\"incantesimi per entrare o il suo potere potrebbe essere troppo grande da \"\n\"sconfiggere.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Cinghiale infernale\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Pungiglione\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psychorb\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Arachnon\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Felltwin\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Prole di Hork\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Coda Velenosa\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Necromorb\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Lord Ragno\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Lashworm\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Torchant\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Insetto Infernale\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Becchino\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Ratto di Tomba\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Pipistrello Infuocato\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Teschio Alato\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lich\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Demone della Cripta\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Pipistrello Infernale\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Demone di Ossa\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Arci Lich\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biciclope\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Pasticcio di Carne\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Mietitore\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Nocca del Gigante\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Anello Mercuriale\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Anello di Xorine\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Anello di Karik\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Anello di Magma\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Anello dei Mistici\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Anello del Tuono\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Amuleto di Protezione\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Puntura di Moscerino\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Fiaccola\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Armatura delle Tenebre\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Fulmine\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Rombo di Tuono\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Divoratore di Anime\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Filo Diamantato\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Armatura di Osso\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Armatura Demoniaca a Piastre\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Amuleto del Chierico\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Anello del Gladiatore\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"di Jester\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Cristallino\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"del Sosia\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"ecatombe\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"decadenza\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"pericolo\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"il Magi\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Jester\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Muro Fulmineo\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Sacrificio\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Deformazione\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Riflesso\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Berserk\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Anello di Fuoco\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Ricerca\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Runa di Fuoco\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Runa della Luce\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Runa\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Runa del Sacrificio\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Runa di Pietra\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \".\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Riavvia In Città\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Abbandonare un oggetto a terra?\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Al colpo\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Cuore\"\n"
  },
  {
    "path": "Translations/ja.po",
    "content": "# Translation of DevilutionX to Japanese\n# bubio <bubio@gmail.com>, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2026-01-15 20:54+0900\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: bubio <bubio@gmail.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: ja\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: Poedit 3.8\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Game Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Senior Designers\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Additional Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Lead Programmer\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Senior Programmers\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programming\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Special Guest Programmers\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net Programming\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Serial Communications Programming\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Installer Programming\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Art Directors\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Artwork\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Technical Artwork\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Cinematic Art Directors\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D Cinematic Artwork\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Cinematic Technical Artwork\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Executive Producer\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Producer\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Associate Producer\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:83\nmsgid \"Music\"\nmsgstr \"音楽\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Sound Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Cinematic Music & Sound\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Voice Production, Direction & Casting\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Script & Story\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Voice Editing\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Voices\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Recording Engineer\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Manual Design & Layout\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Manual Artwork\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Provisional Director of QA (​Lead Tester​)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA Assault Team (​Testers​)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA Special Ops Team (​Compatibility Testers​)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA Artillery Support (​Additional Testers​) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA Counterintelligence\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Order of Network Information Services\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Customer Support\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Sales\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Mr. Dabiri’s Background Vocalists\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Public Relations\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"International Sales\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"U.S. Sales\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Manufacturing\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Legal & Business\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Special Thanks To\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Thanks To\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"In memory of\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Very Special Thanks to\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"General Manager\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Software Engineering\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Art Director\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Artists\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Sound Design, SFX & Audio Engineering\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Quality Assurance Lead\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testers\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tAdditional Work\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Quest Text Writing\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Thanks to\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Quality Assurance Manager\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Quality Assurance Lead Tester\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Main Testers\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Additional Testers\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Product Marketing Manager\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Public Relations Manager\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Associate Product Manager\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"The Ring of One Thousand\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tNo souls were sold in the making of this game.\"\n\n#: Source/DiabloUI/dialogs.cpp:108 Source/DiabloUI/dialogs.cpp:120\n#: Source/DiabloUI/hero/selhero.cpp:204 Source/DiabloUI/hero/selhero.cpp:230\n#: Source/DiabloUI/hero/selhero.cpp:315 Source/DiabloUI/hero/selhero.cpp:555\n#: Source/DiabloUI/multi/selconn.cpp:99 Source/DiabloUI/multi/selgame.cpp:194\n#: Source/DiabloUI/multi/selgame.cpp:362 Source/DiabloUI/multi/selgame.cpp:388\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/DiabloUI/multi/selgame.cpp:607\n#: Source/DiabloUI/selok.cpp:86\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:173\nmsgid \"Choose Class\"\nmsgstr \"クラス​選択\"\n\n#: Source/DiabloUI/hero/selhero.cpp:207 Source/DiabloUI/hero/selhero.cpp:233\n#: Source/DiabloUI/hero/selhero.cpp:318 Source/DiabloUI/hero/selhero.cpp:563\n#: Source/DiabloUI/multi/selconn.cpp:102 Source/DiabloUI/progress.cpp:57\nmsgid \"Cancel\"\nmsgstr \"キャンセル\"\n\n#: Source/DiabloUI/hero/selhero.cpp:213 Source/DiabloUI/hero/selhero.cpp:303\nmsgid \"New Multi Player Hero\"\nmsgstr \"新しい​マルチ​プレイヤー​ヒーロー\"\n\n#: Source/DiabloUI/hero/selhero.cpp:213 Source/DiabloUI/hero/selhero.cpp:303\nmsgid \"New Single Player Hero\"\nmsgstr \"新しい​シングルプレイヤー​ヒーロー\"\n\n#: Source/DiabloUI/hero/selhero.cpp:222\nmsgid \"Save File Exists\"\nmsgstr \"セーブ​ファイル​が​あり​ます\"\n\n#: Source/DiabloUI/hero/selhero.cpp:225 Source/gamemenu.cpp:54\nmsgid \"Load Game\"\nmsgstr \"ゲーム​の​ロード\"\n\n#: Source/DiabloUI/hero/selhero.cpp:226 Source/multi.cpp:876\nmsgid \"New Game\"\nmsgstr \"新規​ゲーム\"\n\n#: Source/DiabloUI/hero/selhero.cpp:236 Source/DiabloUI/hero/selhero.cpp:569\nmsgid \"Single Player Characters\"\nmsgstr \"シングルプレイヤー​キャラクター\"\n\n#: Source/DiabloUI/hero/selhero.cpp:295\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"ローグ​と​ソーサラー​は、ディアブロ​の​製品​版​で​のみ​使用​可能​です。ご​購入​は https://\"\n\"www.gog.com/game/diablo を​ご覧​ください。\"\n\n#: Source/DiabloUI/hero/selhero.cpp:309 Source/DiabloUI/hero/selhero.cpp:312\nmsgid \"Enter Name\"\nmsgstr \"名前​を​入力\"\n\n#: Source/DiabloUI/hero/selhero.cpp:341\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"名前​が​無効​です。名前​に​スペース、予約​文字、予約​語​を​含む​こと​は​でき​ませ​ん。\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:348\nmsgid \"Unable to create character.\"\nmsgstr \"キャラクター​を​作る​こと​が​でき​ませ​ん。\"\n\n#: Source/DiabloUI/hero/selhero.cpp:514\nmsgid \"Level:\"\nmsgstr \"レベル:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:518\nmsgid \"Strength:\"\nmsgstr \"STR:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:518\nmsgid \"Magic:\"\nmsgstr \"MAG:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:518\nmsgid \"Dexterity:\"\nmsgstr \"DEX:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:518\nmsgid \"Vitality:\"\nmsgstr \"VIT:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:520\nmsgid \"Savegame:\"\nmsgstr \"セーブ​回数:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:539\nmsgid \"Select Hero\"\nmsgstr \"ヒーロー​の​選択\"\n\n#: Source/DiabloUI/hero/selhero.cpp:547\nmsgid \"New Hero\"\nmsgstr \"新しい​ヒーロー\"\n\n#: Source/DiabloUI/hero/selhero.cpp:558\nmsgid \"Delete\"\nmsgstr \"削除\"\n\n#: Source/DiabloUI/hero/selhero.cpp:567\nmsgid \"Multi Player Characters\"\nmsgstr \"マルチ​プレイヤー​キャラクター\"\n\n#: Source/DiabloUI/hero/selhero.cpp:618\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"マルチ​プレイヤー​ヒーロー​を​削除\"\n\n#: Source/DiabloUI/hero/selhero.cpp:620\nmsgid \"Delete Single Player Hero\"\nmsgstr \"シングルプレイヤー​ヒーロー​を​削除\"\n\n#: Source/DiabloUI/hero/selhero.cpp:622\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"キャラクター​「​{:s}​」​を​削除​し​て​よろしい​です​か？\"\n\n#: Source/DiabloUI/mainmenu.cpp:53\nmsgid \"Single Player\"\nmsgstr \"シングルプレイヤー\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Multi Player\"\nmsgstr \"マルチ​プレイヤー\"\n\n#: Source/DiabloUI/mainmenu.cpp:55 Source/DiabloUI/settingsmenu.cpp:392\nmsgid \"Settings\"\nmsgstr \"設定\"\n\n#: Source/DiabloUI/mainmenu.cpp:56\nmsgid \"Support\"\nmsgstr \"サポート\"\n\n#: Source/DiabloUI/mainmenu.cpp:57\nmsgid \"Show Credits\"\nmsgstr \"クレジット​を​見る\"\n\n#: Source/DiabloUI/mainmenu.cpp:59\nmsgid \"Exit Hellfire\"\nmsgstr \"ヘルファイア​を​終了\"\n\n#: Source/DiabloUI/mainmenu.cpp:59\nmsgid \"Exit Diablo\"\nmsgstr \"ディアブロ​を​終了\"\n\n#: Source/DiabloUI/mainmenu.cpp:76\nmsgid \"Shareware\"\nmsgstr \"シェアウェア\"\n\n#: Source/DiabloUI/multi/selconn.cpp:31\nmsgid \"Client-Server (TCP)\"\nmsgstr \"クライアント - サーバー (​TCP​)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:32\nmsgid \"Offline\"\nmsgstr \"オフライン\"\n\n#: Source/DiabloUI/multi/selconn.cpp:73 Source/DiabloUI/multi/selgame.cpp:674\n#: Source/DiabloUI/multi/selgame.cpp:700\nmsgid \"Multi Player Game\"\nmsgstr \"マルチ​プレイヤー​ゲーム\"\n\n#: Source/DiabloUI/multi/selconn.cpp:79\nmsgid \"Requirements:\"\nmsgstr \"必要条件:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:85\nmsgid \"no gateway needed\"\nmsgstr \"ゲートウェイ​不要\"\n\n#: Source/DiabloUI/multi/selconn.cpp:91\nmsgid \"Select Connection\"\nmsgstr \"コネクション​を​選択\"\n\n#: Source/DiabloUI/multi/selconn.cpp:94\nmsgid \"Change Gateway\"\nmsgstr \"ゲートウェイ​の​変更\"\n\n#: Source/DiabloUI/multi/selconn.cpp:127\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"\"\n\"すべて​の​コンピューター​が​TCP​対応​の​ネットワーク​に​接続​さ​れ​て​いる​必要​が​あり​ます。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:131\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"すべて​の​コンピューター​が​インターネット​に​接続​さ​れ​て​いる​必要​が​あり​ます。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"ひとり​で​プレイ​し​て​も、ネットワーク​に​触れる​こと​は​あり​ませ​ん。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:140\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"サポート​プレイヤー​数: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:107 Source/options.cpp:436\n#: Source/options.cpp:484 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"ディアブロ\"\n\n#: Source/DiabloUI/multi/selgame.cpp:110\nmsgid \"Diablo Shareware\"\nmsgstr \"ディアブロ​・​シェアウェア\"\n\n#: Source/DiabloUI/multi/selgame.cpp:113 Source/options.cpp:438\n#: Source/options.cpp:498\nmsgid \"Hellfire\"\nmsgstr \"ヘルファイア\"\n\n#: Source/DiabloUI/multi/selgame.cpp:116\nmsgid \"Hellfire Shareware\"\nmsgstr \"ヘルファイア​・​シェアウェア\"\n\n#: Source/DiabloUI/multi/selgame.cpp:119\nmsgid \"The host is running a different game than you.\"\nmsgstr \"ホスト​は​あなた​と​は​別​の​ゲーム​を​し​て​い​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:121\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"ホスト​は​あなた​と​違う​ゲーム​モード​(​{:s}​)​を​実行​し​て​い​ます。\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:123\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"あなた​の​バージョン​{:s}​は、ホスト​{:d}.{:d}.{:d}​と​一致​し​ませ​ん。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:160 Source/DiabloUI/multi/selgame.cpp:593\nmsgid \"Description:\"\nmsgstr \"説明:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:166\nmsgid \"Select Action\"\nmsgstr \"アクション​を​選択\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169 Source/DiabloUI/multi/selgame.cpp:350\n#: Source/DiabloUI/multi/selgame.cpp:511\nmsgid \"Create Game\"\nmsgstr \"ゲーム​の​作成\"\n\n#: Source/DiabloUI/multi/selgame.cpp:171\nmsgid \"Create Public Game\"\nmsgstr \"パブリック​ゲーム​の​作成\"\n\n#: Source/DiabloUI/multi/selgame.cpp:172\nmsgid \"Join Game\"\nmsgstr \"ゲーム​に​参加\"\n\n#: Source/DiabloUI/multi/selgame.cpp:176\nmsgid \"Public Games\"\nmsgstr \"パブリック​・​ゲーム\"\n\n#: Source/DiabloUI/multi/selgame.cpp:181 Source/diablo_msg.cpp:78\nmsgid \"Loading...\"\nmsgstr \"ロード​中​…\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:183 Source/discord/discord.cpp:86\n#: Source/options.cpp:470 Source/options.cpp:781\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"なし\"\n\n#: Source/DiabloUI/multi/selgame.cpp:197 Source/DiabloUI/multi/selgame.cpp:365\n#: Source/DiabloUI/multi/selgame.cpp:391 Source/DiabloUI/multi/selgame.cpp:533\n#: Source/DiabloUI/multi/selgame.cpp:610\nmsgid \"CANCEL\"\nmsgstr \"キャンセル\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"お​好み​の​難易度​を​設定​し​て、新しい​ゲーム​を​作成​し​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:239\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"誰​で​も​参加​できる​新しい​パブリック​ゲーム​を​作成​し、お​好み​の​難易度​を​設定​し​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"すでに​進行中​の​ゲーム​に​参加​する​場合​は、ゲーム​ID​を​入力​し​て​ください。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:245\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"IP​また​は​ホスト​名​を​入力​する​と、すでに​進行中​の​ゲーム​に​参加​でき​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:250\nmsgid \"Join the public game already in progress.\"\nmsgstr \"すでに​進行中​の​パブリック​・​ゲーム​に​参加​する。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:256 Source/DiabloUI/multi/selgame.cpp:355\n#: Source/DiabloUI/multi/selgame.cpp:416 Source/DiabloUI/multi/selgame.cpp:522\n#: Source/DiabloUI/multi/selgame.cpp:542 Source/automap.cpp:1470\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"通常\"\n\n#: Source/DiabloUI/multi/selgame.cpp:259 Source/DiabloUI/multi/selgame.cpp:356\n#: Source/DiabloUI/multi/selgame.cpp:420 Source/automap.cpp:1473\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"ナイトメア\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/DiabloUI/multi/selgame.cpp:357\n#: Source/DiabloUI/multi/selgame.cpp:424 Source/automap.cpp:1476\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"ヘル\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/automap.cpp:1480\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"難易度 {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:269 Source/gamemenu.cpp:169\nmsgid \"Speed: Normal\"\nmsgstr \"スピード: 通常\"\n\n#: Source/DiabloUI/multi/selgame.cpp:272 Source/gamemenu.cpp:167\nmsgid \"Speed: Fast\"\nmsgstr \"スピード: 速い\"\n\n#: Source/DiabloUI/multi/selgame.cpp:275 Source/gamemenu.cpp:165\nmsgid \"Speed: Faster\"\nmsgstr \"スピード: より​速い\"\n\n#: Source/DiabloUI/multi/selgame.cpp:278 Source/gamemenu.cpp:163\nmsgid \"Speed: Fastest\"\nmsgstr \"スピード: 最速\"\n\n#: Source/DiabloUI/multi/selgame.cpp:286\nmsgid \"Players: \"\nmsgstr \"プレイヤー: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:293\n#, c++-format\nmsgid \"Ping: {:d} ms (RELAYED)\"\nmsgstr \"Ping​：​{:d} ms​（​リレー​経由​）\"\n\n#: Source/DiabloUI/multi/selgame.cpp:295\n#, c++-format\nmsgid \"Ping: {:d} ms\"\nmsgstr \"Ping​：​{:d} ms\"\n\n#: Source/DiabloUI/multi/selgame.cpp:353\nmsgid \"Select Difficulty\"\nmsgstr \"難易度​の​選択\"\n\n#: Source/DiabloUI/multi/selgame.cpp:371\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"{:s}​ゲーム​に​参加\"\n\n#: Source/DiabloUI/multi/selgame.cpp:376\nmsgid \"Enter Game ID\"\nmsgstr \"ゲーム​ID​を​入力\"\n\n#: Source/DiabloUI/multi/selgame.cpp:378\nmsgid \"Enter address\"\nmsgstr \"アドレス​を​入力\"\n\n#: Source/DiabloUI/multi/selgame.cpp:417\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"通常​の​難易度​\\n\"\n\"​最初​の​キャラクター​が​Diablo​を​倒す​ため​の​クエスト​を​始める​の​に​適し​た​難易度​です。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:421\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"ナイトメア​の​難易度​\\n\"\n\"​迷宮​の​住人​たち​は​さらに​強化​さ​れ、より​大きな​挑戦​と​なる​でしょう。経験​豊富​な​キャ\"\n\"ラクター​に​のみ​お勧め​です。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:425\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"ヘル​の​難易度​\\n\"\n\"​地獄​へ​の​入り口​に​は、地下​世界​の​最強​の​生物​が​潜ん​で​い​ます。経験​豊富​な​キャラク\"\n\"ター​だけ​が、この​領域​に​足​を​踏み入れる​こと​が​でき​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:440\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"キャラクター​の​レベル​が​20​に​達し​て​い​ない​と、ナイトメア​難易度​の​マルチ​プレイヤー​\"\n\"ゲーム​に​参加​でき​ませ​ん。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:442\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"キャラクター​の​レベル​が​30​に​なる​と、ヘル​難易度​の​マルチ​プレイヤー​ゲーム​に​参加​で\"\n\"きる​よう​に​なり​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:520\nmsgid \"Select Game Speed\"\nmsgstr \"ゲーム​スピード\"\n\n#: Source/DiabloUI/multi/selgame.cpp:523 Source/DiabloUI/multi/selgame.cpp:546\nmsgid \"Fast\"\nmsgstr \"高速\"\n\n#: Source/DiabloUI/multi/selgame.cpp:524 Source/DiabloUI/multi/selgame.cpp:550\nmsgid \"Faster\"\nmsgstr \"超​高速\"\n\n#: Source/DiabloUI/multi/selgame.cpp:525 Source/DiabloUI/multi/selgame.cpp:554\nmsgid \"Fastest\"\nmsgstr \"神速\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"通常​\\n\"\n\"​ここ​で​は、主人公​が​Diablo​を​倒す​ため​の​クエスト​を​開始​し​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:547\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"高速​\\n\"\n\"​迷宮​の​住人​たち​は、より​速く、より​大きな​挑戦​と​なる​でしょう。経験​豊富​な​キャラク\"\n\"ター​に​のみ​お勧め​です。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:551\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"超​高速​\\n\"\n\"​ダンジョン​内​の​ほとんど​の​モンスター​は、これ​まで​以上​に​素早く​あなた​を​探し出し​ま\"\n\"す。経験​豊富​な​チャンピオン​だけ​が、この​スピード​で​運​を​試す​こと​が​でき​ます。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:555\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"神速​\\n\"\n\"​冥界​の​手下​たち​は、迷う​こと​なく​攻撃​を​仕掛け​て​くる。この​ペース​で​進入​する​の​は、\"\n\"真​の​スピード​・​デーモン​だけ​に​し​て​ください。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:599 Source/DiabloUI/multi/selgame.cpp:604\nmsgid \"Enter Password\"\nmsgstr \"パスワード​を​入力\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"ヘルファイア​へ\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"ディアブロ​に​切り替え\"\n\n#: Source/DiabloUI/selyesno.cpp:72 Source/stores.cpp:940\nmsgid \"Yes\"\nmsgstr \"はい\"\n\n#: Source/DiabloUI/selyesno.cpp:73 Source/stores.cpp:941\nmsgid \"No\"\nmsgstr \"いいえ\"\n\n#: Source/DiabloUI/settingsmenu.cpp:170\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"ゲーム​パッド​の​ボタン​を​押し​て​変更。\"\n\n#: Source/DiabloUI/settingsmenu.cpp:447\nmsgid \"Bound key:\"\nmsgstr \"キーバインド:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:496\nmsgid \"Press any key to change.\"\nmsgstr \"いずれ​か​の​キー​を​押す​と​変更​さ​れ​ます。\"\n\n#: Source/DiabloUI/settingsmenu.cpp:498\nmsgid \"Unbind key\"\nmsgstr \"キーバインド​解除\"\n\n#: Source/DiabloUI/settingsmenu.cpp:502\nmsgid \"Bound button combo:\"\nmsgstr \"コンボ​ボタン​の​バインド:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:511\nmsgid \"Unbind button combo\"\nmsgstr \"コンボ​ボタン​の​バインド​解除\"\n\n#: Source/DiabloUI/settingsmenu.cpp:555 Source/gamemenu.cpp:77\nmsgid \"Previous Menu\"\nmsgstr \"前​の​メニュー\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"私たち​は​Discord.gg/devilutionx​で​チャット​サーバー​を​管理​し​て​い​ます。リンク​を​た\"\n\"どっ​て​コミュニティ​に​参加​し、Diablo​や​Hellfire​エクスパンション​に​関する​こと​を​話\"\n\"し​ましょう。\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX​は​Diasurgical​に​よっ​て​管理​さ​れ​て​い​ます。問題​や​バグ​は​この​アドレス​で​\"\n\"報告​する​こと​が​でき​ます​： https://github.com/diasurgical/devilutionX より​良い​\"\n\"サービス​を​提供​する​ため​に、バージョン​番号、オペレーティングシステム、問題​の​内\"\n\"容​を​必ず​明記​し​て​ください。\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"免責​事項:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX​は、Blizzard Entertainment​および​GOG.com​に​よっ​て​サポート​また​は​メ\"\n\"ンテナンス​さ​れ​て​い​ませ​ん。Blizzard Entertainment​および​GOG.com​の​いずれ​も、\"\n\"DevilutionX​の​品質​や​互換性​を​テスト​また​は​認定​し​て​い​ませ​ん。DevilutionX​に​関する​\"\n\"すべて​の​お​問い合わせ​は、Blizzard Entertainment​や​GOG.com​で​は​なく、Diasurgical​\"\n\"に​お​願い​し​ます。\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\t​この​移植​版​で​は、SIL Open Font License​に​基づい​て​ライセンス​さ​れ​た​Charis SIL、\"\n\"New Athena Unicode、Unifont、Noto、および​CC-BY 4.0​に​基づい​て​ライセンス​さ​れ​た​\"\n\"Twitmoji​を​使用​し​て​い​ます。また、この​移植​版​で​は、zlib-license​で​ライセンス​さ​れ​\"\n\"て​いる​SDL​も​使用​し​て​い​ます。詳細​は、ReadMe​を​ご覧​ください。\"\n\n#: Source/DiabloUI/title.cpp:74\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:72\nmsgid \"Error\"\nmsgstr \"Error\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:86\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\n\n#: Source/appfat.cpp:92\nmsgid \"Data File Error\"\nmsgstr \"データファイル​・​エラー\"\n\n#: Source/appfat.cpp:93\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"メイン​データ​アーカイブ​(​{:s}​)​を​開く​こと​が​でき​ませ​ん。\\n\"\n\"\\n\"\n\"​ゲーム​フォルダ​に​入っ​て​いる​か​確認​し​て​ください。\"\n\n#: Source/appfat.cpp:102\nmsgid \"Read-Only Directory Error\"\nmsgstr \"読み取り専用​ディレクトリ​エラー\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:103\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"書き込み​が​でき​ませ​ん:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1429\nmsgid \"Game: \"\nmsgstr \"ゲーム: \"\n\n#: Source/automap.cpp:1436\nmsgid \"Offline Game\"\nmsgstr \"オフライン​ゲーム\"\n\n#: Source/automap.cpp:1438\nmsgid \"Public Game\"\nmsgstr \"パブリック​ゲーム\"\n\n#: Source/automap.cpp:1440\nmsgid \"Password: \"\nmsgstr \"パスワード: \"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"レベル: 巣 {:d}\"\n\n#: Source/automap.cpp:1455\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"レベル: 地下​聖堂 {:d}\"\n\n#: Source/automap.cpp:1458 Source/discord/discord.cpp:81 Source/objects.cpp:156\nmsgid \"Town\"\nmsgstr \"タウン\"\n\n#: Source/automap.cpp:1461\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"レベル: {:d}\"\n\n#: Source/control/control_chat_commands.cpp:36\nmsgid \"Available Commands:\"\nmsgstr \"使用​できる​コマンド: \"\n\n#: Source/control/control_chat_commands.cpp:44\n#: Source/control/control_chat_commands.cpp:266\nmsgid \"Command \"\nmsgstr \"コマンド \"\n\n#: Source/control/control_chat_commands.cpp:44\n#: Source/control/control_chat_commands.cpp:266\nmsgid \" is unknown.\"\nmsgstr \"は​不明。\"\n\n#: Source/control/control_chat_commands.cpp:47\n#: Source/control/control_chat_commands.cpp:48\nmsgid \"Description: \"\nmsgstr \"説明: \"\n\n#: Source/control/control_chat_commands.cpp:47\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"​パラメータ:  追加​の​パラメータ​は​必要​あり​ませ​ん。\"\n\n#: Source/control/control_chat_commands.cpp:48\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"​パラメータ: \"\n\n#: Source/control/control_chat_commands.cpp:62\n#: Source/control/control_chat_commands.cpp:94\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"アリーナ​は​マルチ​プレイ​のみ​対応​し​て​い​ます。\"\n\n#: Source/control/control_chat_commands.cpp:67\nmsgid \"What arena do you want to visit?\"\nmsgstr \"行っ​て​み​たい​アリーナ​は​どこ​です​か？\"\n\n#: Source/control/control_chat_commands.cpp:75\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"アリーナ​番号​が​無効​です。有効​な​番号​は​次​の​とおり​です: \"\n\n#: Source/control/control_chat_commands.cpp:81\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"アリーナ​に​入る​に​は、街​か​他​の​アリーナ​に​いる​必要​が​あり​ます。\"\n\n#: Source/control/control_chat_commands.cpp:119\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"インスペクト​は​マルチプレーヤー​のみ​対応。\"\n\n#: Source/control/control_chat_commands.cpp:124\n#: Source/control/control_panel.cpp:316\nmsgid \"Stopped inspecting players.\"\nmsgstr \"プレイヤー​の​インスペク​と​を​中止。\"\n\n#: Source/control/control_chat_commands.cpp:139\n#: Source/control/control_chat_commands.cpp:226\nmsgid \"No players found with such a name\"\nmsgstr \"ぞ​の​よう​な​名前​の​プレイヤー​は​見つかり​ませ​ん​でし​た\"\n\n#: Source/control/control_chat_commands.cpp:145\nmsgid \"Inspecting player: \"\nmsgstr \"プレイヤー​の​インスペクト : \"\n\n#. TRANSLATORS: {:s} means: Character Name\n#: Source/control/control_chat_commands.cpp:233\n#, c++-format\nmsgid \"Latency statistics for {:s}:\"\nmsgstr \"{:s} の​遅延​統計​：\"\n\n#. TRANSLATORS: Network connectivity statistics\n#: Source/control/control_chat_commands.cpp:235 Source/diablo.cpp:1578\n#, c++-format\nmsgid \"Echo latency: {:d} ms\"\nmsgstr \"エコー​遅延​：​{:d} ms\"\n\n#. TRANSLATORS: Network connectivity statistics\n#: Source/control/control_chat_commands.cpp:239 Source/diablo.cpp:1582\n#, c++-format\nmsgid \"Provider latency: {:d} ms (Relayed)\"\nmsgstr \"プロバイダ​遅延​：​{:d} ms​（​リレー​経由​）\"\n\n#. TRANSLATORS: Network connectivity statistics\n#: Source/control/control_chat_commands.cpp:241 Source/diablo.cpp:1584\n#, c++-format\nmsgid \"Provider latency: {:d} ms\"\nmsgstr \"プロバイダ​遅延​：​{:d} ms\"\n\n#: Source/control/control_chat_commands.cpp:249\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"ヘルプ​の​概要​また​は​特定​の​コマンド​の​ヘルプ​を​表示​し​ます。\"\n\n#: Source/control/control_chat_commands.cpp:249\nmsgid \"[command]\"\nmsgstr \"[​コマンド​]\"\n\n#: Source/control/control_chat_commands.cpp:250\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"PvP​アリーナ​に​入る。\"\n\n#: Source/control/control_chat_commands.cpp:250\nmsgid \"<arena-number>\"\nmsgstr \"<​アリーナ​番号​>\"\n\n#: Source/control/control_chat_commands.cpp:251\nmsgid \"Gives Arena Potions.\"\nmsgstr \"アリーナ​ポーション​を​与える。\"\n\n#: Source/control/control_chat_commands.cpp:251\nmsgid \"<number>\"\nmsgstr \"<​番号​>\"\n\n#: Source/control/control_chat_commands.cpp:252\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"他​の​プレーヤー​の​体力​や​装備​を​調べる。\"\n\n#: Source/control/control_chat_commands.cpp:252\n#: Source/control/control_chat_commands.cpp:254\nmsgid \"<player name>\"\nmsgstr \"<​プレイヤー​名​>\"\n\n#: Source/control/control_chat_commands.cpp:253\nmsgid \"Show seed infos for current level.\"\nmsgstr \"現在​の​レベル​の​シード​情報​を​表示。\"\n\n#: Source/control/control_chat_commands.cpp:254\nmsgid \"Show latency statistics for another player.\"\nmsgstr \"他​の​プレイヤー​の​遅延​統計​を​表示​し​ます。\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control/control_gold.cpp:60\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"あなたは{:s}ゴールドを持っています。何枚削除しますか？\"\n\n#: Source/control/control_infobox.cpp:295\nmsgid \"Player friendly\"\nmsgstr \"プレイヤー​は​味方\"\n\n#: Source/control/control_infobox.cpp:297\nmsgid \"Player attack\"\nmsgstr \"プレイヤー​の​攻撃\"\n\n#: Source/control/control_infobox.cpp:300\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"ホットキー: {:s}\"\n\n#: Source/control/control_infobox.cpp:312\nmsgid \"Select current spell button\"\nmsgstr \"正しい​呪文​ボタン​を​選択​し​て​ください\"\n\n#: Source/control/control_infobox.cpp:315\nmsgid \"Hotkey: 's'\"\nmsgstr \"ホットキー: ’s’\"\n\n#: Source/control/control_infobox.cpp:321 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} スキル\"\n\n#: Source/control/control_infobox.cpp:324 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} スペル\"\n\n#: Source/control/control_infobox.cpp:326 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"スペル​レベル 0 - 使え​ない\"\n\n#: Source/control/control_infobox.cpp:326 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"スペル​レベル {:d}\"\n\n#: Source/control/control_infobox.cpp:329 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"{:s}​の​スクロール\"\n\n#: Source/control/control_infobox.cpp:333 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} スクロール\"\n\n#: Source/control/control_infobox.cpp:336 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"{:s}​・​スタッフ\"\n\n#: Source/control/control_infobox.cpp:337 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d}チャージ\"\n\n#: Source/control/control_infobox.cpp:369 Source/inv.cpp:1986\n#: Source/inv.cpp:1987 Source/items.cpp:3815\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} ゴールド\"\n\n#: Source/control/control_infobox.cpp:371\nmsgid \"Requirements not met\"\nmsgstr \"能力​値​が​不足​し​て​い​ます\"\n\n#: Source/control/control_infobox.cpp:400\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, レベル: {:d}\"\n\n#: Source/control/control_infobox.cpp:401\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"ヒット​ポイント: {:d}/{:d}\"\n\n#: Source/control/control_infobox.cpp:407\nmsgid \"Right click to inspect\"\nmsgstr \"右​クリック​で​詳細​を​表示\"\n\n#: Source/control/control_panel.cpp:106\nmsgid \"Character Information\"\nmsgstr \"キャラクター​情報\"\n\n#: Source/control/control_panel.cpp:107\nmsgid \"Quests log\"\nmsgstr \"クエスト​の​記録\"\n\n#: Source/control/control_panel.cpp:108\nmsgid \"Automap\"\nmsgstr \"オート​マップ\"\n\n#: Source/control/control_panel.cpp:109\nmsgid \"Main Menu\"\nmsgstr \"メインメニュー\"\n\n#: Source/control/control_panel.cpp:110 Source/diablo.cpp:1948\n#: Source/diablo.cpp:2300\nmsgid \"Inventory\"\nmsgstr \"所持品​の​一覧\"\n\n#: Source/control/control_panel.cpp:111\nmsgid \"Spell book\"\nmsgstr \"スペル​ブック\"\n\n#: Source/control/control_panel.cpp:112\nmsgid \"Send Message\"\nmsgstr \"メッセージ​送信\"\n\n#: Source/control/control_panel.cpp:117\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control/control_panel.cpp:117\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control/control_panel.cpp:117\nmsgid \"Enter\"\nmsgstr \"入力\"\n\n#: Source/control/control_panel.cpp:673\nmsgid \"Level Up\"\nmsgstr \"レベルアップ\"\n\n#: Source/control/control_panel.cpp:795\nmsgid \"You have died\"\nmsgstr \"あなた​は​死に​まし​た\"\n\n#: Source/control/control_panel.cpp:803\nmsgid \"ESC\"\nmsgstr \"ESC\"\n\n#: Source/control/control_panel.cpp:809\nmsgid \"Menu Button\"\nmsgstr \"メニュー​ボタン\"\n\n#: Source/control/control_panel.cpp:817\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"{} を​押す​と、最後​の​セーブ​データ​を​読み込み​ます。\"\n\n#: Source/control/control_panel.cpp:819\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"{} を​押す​と、メインメニュー​に​戻り​ます。\"\n\n#: Source/control/control_panel.cpp:822\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"{} を​押す​と、町​で​再開​し​ます。\"\n\n#: Source/cursor.cpp:629\nmsgid \"Town Portal\"\nmsgstr \"タウン​ポータル\"\n\n#: Source/cursor.cpp:630\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"{:s}​から\"\n\n#: Source/cursor.cpp:643\nmsgid \"Portal to\"\nmsgstr \"ポータル\"\n\n#: Source/cursor.cpp:644\nmsgid \"The Unholy Altar\"\nmsgstr \"ラザルス​の​間\"\n\n#: Source/cursor.cpp:644\nmsgid \"level 15\"\nmsgstr \"レベル​15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"{0} ファイル​から​データ​を​読み込め​ませ​ん。\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} が​不完全​です。ファイル​内容​を​確認​し​て​ください。\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"{0} ファイル​に​期待​さ​れる​列​が​あり​ませ​ん。ドキュメント​の​形式​と​一致​し​て​いる​こと​\"\n\"を​確認​し​て​ください。\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"{2} の​行 {3} 列 {4} に​おけ​る {1} の​値 {0} が​数値​で​は​あり​ませ​ん。\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"{2} の​行 {3} 列 {4} に​おけ​る {1} の​値 {0} が​範囲​外​です。\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"{2} の​行 {3} 列 {4} に​おけ​る {1} の​値 {0} は​無効​です。\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Print this message and exit\"\nmsgstr \"Print this message and exit\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Print the version and exit\"\nmsgstr \"Print the version and exit\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1005\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Specify the folder of diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1006\nmsgid \"Specify the folder of save files\"\nmsgstr \"Specify the folder of save files\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Specify the location of diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1008\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Specify the language code (​e.g. en or pt_BR​)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Skip startup videos\"\nmsgstr \"Skip startup videos\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Display frames per second\"\nmsgstr \"Display frames per second\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Enable verbose logging\"\nmsgstr \"Enable verbose logging\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1013\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"Log to a file instead of stderr\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1016\nmsgid \"Record a demo file\"\nmsgstr \"Record a demo file\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1017\nmsgid \"Play a demo file\"\nmsgstr \"Play a demo file\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1018\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Disable all frame limiting during demo playback\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1021\nmsgid \"Game selection:\"\nmsgstr \"Game selection:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1023\nmsgid \"Force Shareware mode\"\nmsgstr \"Force Shareware mode\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1024\nmsgid \"Force Diablo mode\"\nmsgstr \"Force Diablo mode\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1025\nmsgid \"Force Hellfire mode\"\nmsgstr \"Force Hellfire mode\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1026\nmsgid \"Hellfire options:\"\nmsgstr \"Hellfire options:\"\n\n#: Source/diablo.cpp:1036\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Report bugs at https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1216\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"devilutionx.mpq​と​fonts.mpq​を​最新​の​バージョン​に​更新​し​て​ください。\"\n\n#: Source/diablo.cpp:1218\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"UI​リソース​の​読み込み​に​失敗​し​まし​た。\\n\"\n\"\\n\"\n\"devilutionx.mpq​が​ゲーム​フォルダ​内​に​あり、最新​の​状態​で​ある​こと​を​確認​し​て​くださ\"\n\"い。\"\n\n#: Source/diablo.cpp:1222\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"fonts.mpq​を​最新​の​バージョン​に​更新​し​て​ください。\"\n\n#: Source/diablo.cpp:1565\nmsgid \"-- Network timeout --\"\nmsgstr \"— Network timeout —\"\n\n#: Source/diablo.cpp:1566\nmsgid \"-- Waiting for players --\"\nmsgstr \"— Waiting for players —\"\n\n#. TRANSLATORS: {:s} means: Character Name\n#: Source/diablo.cpp:1575\n#, c++-format\nmsgid \"Player {:s} is timing out!\"\nmsgstr \"プレイヤー {:s} が​タイムアウト​し​て​い​ます！\"\n\n#: Source/diablo.cpp:1611\nmsgid \"No help available\"\nmsgstr \"ヘルプ​は​使え​ませ​ん\"\n\n#: Source/diablo.cpp:1612\nmsgid \"while in stores\"\nmsgstr \"店​で\"\n\n#: Source/diablo.cpp:1810 Source/diablo.cpp:2130\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"ベルト​アイテム {}\"\n\n#: Source/diablo.cpp:1811 Source/diablo.cpp:2131\nmsgid \"Use Belt item.\"\nmsgstr \"ベルト​アイテム​を​使い​ます。\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2146\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"クイック​スペル {}\"\n\n#: Source/diablo.cpp:1827 Source/diablo.cpp:2147\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"スキル​や​スペル​の​ホットキー​です。\"\n\n#: Source/diablo.cpp:1845\nmsgid \"Previous quick spell\"\nmsgstr \"前​の​クイック​スペル\"\n\n#: Source/diablo.cpp:1846\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"前​の​クイック​スペル​を​選択​し​ます​（​サイクル​し​ます​）。\"\n\n#: Source/diablo.cpp:1853\nmsgid \"Next quick spell\"\nmsgstr \"次​の​クイック​スペル\"\n\n#: Source/diablo.cpp:1854\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"次​の​クイック​スペル​を​選択​し​ます​（​サイクル​し​ます​）。\"\n\n#: Source/diablo.cpp:1861 Source/diablo.cpp:2274\nmsgid \"Use health potion\"\nmsgstr \"ヘルス​ポーション​を​使用​する\"\n\n#: Source/diablo.cpp:1862 Source/diablo.cpp:2275\nmsgid \"Use health potions from belt.\"\nmsgstr \"ベルト​から​ヘルス​ポーション​を​使用​する。\"\n\n#: Source/diablo.cpp:1869 Source/diablo.cpp:2282\nmsgid \"Use mana potion\"\nmsgstr \"マナポーション​を​使用​する\"\n\n#: Source/diablo.cpp:1870 Source/diablo.cpp:2283\nmsgid \"Use mana potions from belt.\"\nmsgstr \"ベルト​から​マナポーション​を​使用​する。\"\n\n#: Source/diablo.cpp:1877 Source/diablo.cpp:2330\nmsgid \"Speedbook\"\nmsgstr \"スピード​ブック\"\n\n#: Source/diablo.cpp:1878 Source/diablo.cpp:2331\nmsgid \"Open Speedbook.\"\nmsgstr \"スピード​ブック​を​開き​ます。\"\n\n#: Source/diablo.cpp:1885 Source/diablo.cpp:2487\nmsgid \"Quick save\"\nmsgstr \"クイック​セーブ\"\n\n#: Source/diablo.cpp:1886 Source/diablo.cpp:2488\nmsgid \"Saves the game.\"\nmsgstr \"ゲーム​を​セーブ​し​ます。\"\n\n#: Source/diablo.cpp:1893 Source/diablo.cpp:2495\nmsgid \"Quick load\"\nmsgstr \"クイック​ロード\"\n\n#: Source/diablo.cpp:1894 Source/diablo.cpp:2496\nmsgid \"Loads the game.\"\nmsgstr \"ゲーム​を​ロード​し​ます。\"\n\n#: Source/diablo.cpp:1902\nmsgid \"Quit game\"\nmsgstr \"ゲーム​の​終了\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Closes the game.\"\nmsgstr \"ゲーム​を​終了​し​ます。\"\n\n#: Source/diablo.cpp:1909\nmsgid \"Stop hero\"\nmsgstr \"ヒーロー​停止\"\n\n#: Source/diablo.cpp:1910\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"歩行​を​停止​し、保留中​の​アクション​を​キャンセル​し​ます。\"\n\n#: Source/diablo.cpp:1917 Source/diablo.cpp:2503\nmsgid \"Item highlighting\"\nmsgstr \"アイテム​の​強調​表示\"\n\n#: Source/diablo.cpp:1918 Source/diablo.cpp:2504\nmsgid \"Show/hide items on ground.\"\nmsgstr \"地上​に​ある​アイテム​の​表示​/​非表示​を​切り替え​ます。\"\n\n#: Source/diablo.cpp:1924 Source/diablo.cpp:2510\nmsgid \"Toggle item highlighting\"\nmsgstr \"アイテム​の​ハイライト​の​切り替え\"\n\n#: Source/diablo.cpp:1925 Source/diablo.cpp:2511\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"地上​に​ある​アイテム​の​常時​表示​/​非表示​を​切り替え​ます。\"\n\n#: Source/diablo.cpp:1931 Source/diablo.cpp:2340\nmsgid \"Toggle automap\"\nmsgstr \"オート​マップ​の​切り替え\"\n\n#: Source/diablo.cpp:1932 Source/diablo.cpp:2341\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"オート​マップ​を​表示​する​か​どう​か​を​切り替え​ます。\"\n\n#: Source/diablo.cpp:1939\nmsgid \"Cycle map type\"\nmsgstr \"マップ​タイプ​の​切替\"\n\n#: Source/diablo.cpp:1940\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"不​透過 -​> 透過 -​> ミニマップ -​> なし\"\n\n#: Source/diablo.cpp:1949 Source/diablo.cpp:2301\nmsgid \"Open Inventory screen.\"\nmsgstr \"インベントリ​画面​を​開き​ます。\"\n\n#: Source/diablo.cpp:1956 Source/diablo.cpp:2290\nmsgid \"Character\"\nmsgstr \"キャラクター\"\n\n#: Source/diablo.cpp:1957 Source/diablo.cpp:2291\nmsgid \"Open Character screen.\"\nmsgstr \"キャラクター​画面​を​開き​ます。\"\n\n#: Source/diablo.cpp:1964\nmsgid \"Party\"\nmsgstr \"パーティー\"\n\n#: Source/diablo.cpp:1965\nmsgid \"Open side Party panel.\"\nmsgstr \"パーティー​の​サイド​パネル​を​開く。\"\n\n#: Source/diablo.cpp:1972 Source/diablo.cpp:2310\nmsgid \"Quest log\"\nmsgstr \"クエストログ\"\n\n#: Source/diablo.cpp:1973 Source/diablo.cpp:2311\nmsgid \"Open Quest log.\"\nmsgstr \"クエストログ​を​開き​ます。\"\n\n#: Source/diablo.cpp:1980 Source/diablo.cpp:2320\nmsgid \"Spellbook\"\nmsgstr \"スペル​ブック\"\n\n#: Source/diablo.cpp:1981 Source/diablo.cpp:2321\nmsgid \"Open Spellbook.\"\nmsgstr \"スペル​ブック​を​開き​ます。\"\n\n#: Source/diablo.cpp:1989\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"クイック​メッセージ {}\"\n\n#: Source/diablo.cpp:1990\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"チャット​で​クイック​メッセージ​を​使用​し​ます。\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2517\nmsgid \"Hide Info Screens\"\nmsgstr \"情報​画面​の​非表示\"\n\n#: Source/diablo.cpp:2000 Source/diablo.cpp:2518\nmsgid \"Hide all info screens.\"\nmsgstr \"すべて​の​情報​画面​を​非表示​に​し​ます。\"\n\n#: Source/diablo.cpp:2023 Source/diablo.cpp:2541 Source/options.cpp:788\nmsgid \"Zoom\"\nmsgstr \"拡大\"\n\n#: Source/diablo.cpp:2024 Source/diablo.cpp:2542\nmsgid \"Zoom Game Screen.\"\nmsgstr \"ゲーム​画面​を​拡大​し​ます。\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2552\nmsgid \"Pause Game\"\nmsgstr \"ゲーム​の​一時停止\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Pauses the game.\"\nmsgstr \"ゲーム​を​一時停止​し​ます。\"\n\n#: Source/diablo.cpp:2040\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"ゲーム​の​一時停止\"\n\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\nmsgid \"Decrease Brightness\"\nmsgstr \"明るさ​を​下げる\"\n\n#: Source/diablo.cpp:2047 Source/diablo.cpp:2559\nmsgid \"Reduce screen brightness.\"\nmsgstr \"画面​の​輝度​を​下げ​ます。\"\n\n#: Source/diablo.cpp:2054 Source/diablo.cpp:2566\nmsgid \"Increase Brightness\"\nmsgstr \"明るさ​を​上げる\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2567\nmsgid \"Increase screen brightness.\"\nmsgstr \"画面​の​輝度​を​上げ​ます。\"\n\n#: Source/diablo.cpp:2062 Source/diablo.cpp:2574\nmsgid \"Help\"\nmsgstr \"ヘルプ\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2575\nmsgid \"Open Help Screen.\"\nmsgstr \"ヘルプ​画面​を​開き​ます。\"\n\n#: Source/diablo.cpp:2070 Source/diablo.cpp:2582\nmsgid \"Screenshot\"\nmsgstr \"スクリーンショット\"\n\n#: Source/diablo.cpp:2071 Source/diablo.cpp:2583\nmsgid \"Takes a screenshot.\"\nmsgstr \"スクリーンショット​を​撮り​ます。\"\n\n#: Source/diablo.cpp:2077 Source/diablo.cpp:2589\nmsgid \"Game info\"\nmsgstr \"ゲーム​情報\"\n\n#: Source/diablo.cpp:2078 Source/diablo.cpp:2590\nmsgid \"Displays game infos.\"\nmsgstr \"ゲーム​情報​を​表示​し​ます。\"\n\n#. TRANSLATORS: {:s} means: Project Name, Game Version.\n#: Source/diablo.cpp:2082 Source/diablo.cpp:2594\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2091 Source/diablo.cpp:2611\nmsgid \"Chat Log\"\nmsgstr \"チャットログ\"\n\n#: Source/diablo.cpp:2092 Source/diablo.cpp:2612\nmsgid \"Displays chat log.\"\nmsgstr \"チャットログ​を​表示​し​ます。\"\n\n#: Source/diablo.cpp:2099 Source/diablo.cpp:2603\nmsgid \"Sort Inventory\"\nmsgstr \"所持品​の​一覧\"\n\n#: Source/diablo.cpp:2100 Source/diablo.cpp:2604\nmsgid \"Sorts the inventory.\"\nmsgstr \"インベントリ​を​整理​し​ます。\"\n\n#: Source/diablo.cpp:2108\nmsgid \"Console\"\nmsgstr \"コンソール\"\n\n#: Source/diablo.cpp:2109\nmsgid \"Opens Lua console.\"\nmsgstr \"Lua​コンソール​を​開き​ます。\"\n\n#: Source/diablo.cpp:2165\nmsgid \"Primary action\"\nmsgstr \"主​アクション\"\n\n#: Source/diablo.cpp:2166\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"モンスター​を​攻撃​し​たり、街​の​人​に​話しかけ​たり、インベントリー​アイテム​を​持ち上\"\n\"げ​て​置い​たり。\"\n\n#: Source/diablo.cpp:2180\nmsgid \"Secondary action\"\nmsgstr \"副​アクション\"\n\n#: Source/diablo.cpp:2181\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"チェスト​を​開け​たり、ドア​と​対話​し​たり、アイテム​を​拾っ​たり。\"\n\n#: Source/diablo.cpp:2195\nmsgid \"Spell action\"\nmsgstr \"スペル​・​アクション\"\n\n#: Source/diablo.cpp:2196\nmsgid \"Cast the active spell.\"\nmsgstr \"アクティブ​な​呪文​を​唱える。\"\n\n#: Source/diablo.cpp:2210\nmsgid \"Cancel action\"\nmsgstr \"キャンセル​・​アクション\"\n\n#: Source/diablo.cpp:2211\nmsgid \"Close menus.\"\nmsgstr \"メニュー​を​閉じる。\"\n\n#: Source/diablo.cpp:2236\nmsgid \"Move up\"\nmsgstr \"上​へ​移動\"\n\n#: Source/diablo.cpp:2237\nmsgid \"Moves the player character up.\"\nmsgstr \"プレイヤー​キャラクター​を​上​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2242\nmsgid \"Move down\"\nmsgstr \"下​へ​移動\"\n\n#: Source/diablo.cpp:2243\nmsgid \"Moves the player character down.\"\nmsgstr \"プレイヤー​キャラクター​を​下​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2248\nmsgid \"Move left\"\nmsgstr \"左​に​移動\"\n\n#: Source/diablo.cpp:2249\nmsgid \"Moves the player character left.\"\nmsgstr \"プレイヤー​キャラクター​を​左​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2254\nmsgid \"Move right\"\nmsgstr \"右​へ​移動\"\n\n#: Source/diablo.cpp:2255\nmsgid \"Moves the player character right.\"\nmsgstr \"プレイヤー​キャラクター​を​右​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2260\nmsgid \"Stand ground\"\nmsgstr \"踏ん張る\"\n\n#: Source/diablo.cpp:2261\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"ホールド​する​と​プレーヤー​が​動か​なく​なり​ます。\"\n\n#: Source/diablo.cpp:2266\nmsgid \"Toggle stand ground\"\nmsgstr \"踏ん張る​の​切り替え\"\n\n#: Source/diablo.cpp:2267\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"プレイヤー​移動​の​切り替え\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Automap Move Up\"\nmsgstr \"オート​マップ​を​上​に​移動\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Moves the automap up when active.\"\nmsgstr \"有効​に​する​と、オート​マップ​が​上​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Automap Move Down\"\nmsgstr \"オート​マップ​を​下​に​移動\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Moves the automap down when active.\"\nmsgstr \"有効​に​する​と、オート​マップ​が​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2358\nmsgid \"Automap Move Left\"\nmsgstr \"オート​マップ​を​左​に​移動\"\n\n#: Source/diablo.cpp:2359\nmsgid \"Moves the automap left when active.\"\nmsgstr \"有効​に​する​と、オート​マップ​が​左​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2364\nmsgid \"Automap Move Right\"\nmsgstr \"オート​マップ​を​右​に​移動\"\n\n#: Source/diablo.cpp:2365\nmsgid \"Moves the automap right when active.\"\nmsgstr \"有効​に​する​と、オート​マップ​が​方向​に​移動​し​ます。\"\n\n#: Source/diablo.cpp:2370\nmsgid \"Move mouse up\"\nmsgstr \"マウス​を​上​に​移動\"\n\n#: Source/diablo.cpp:2371\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"マウス​の​上​方向​の​動き​を​シミュレート​し​ます。\"\n\n#: Source/diablo.cpp:2376\nmsgid \"Move mouse down\"\nmsgstr \"マウス​を​下​に​移動\"\n\n#: Source/diablo.cpp:2377\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"マウス​の​下​方向​の​動き​を​シミュレート​し​ます。\"\n\n#: Source/diablo.cpp:2382\nmsgid \"Move mouse left\"\nmsgstr \"マウス​を​左​へ​移動\"\n\n#: Source/diablo.cpp:2383\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"マウス​の​左​方向​の​動き​を​シミュレート​し​ます。\"\n\n#: Source/diablo.cpp:2388\nmsgid \"Move mouse right\"\nmsgstr \"マウス​を​右​へ​移動\"\n\n#: Source/diablo.cpp:2389\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"マウス​の​右​方向​の​動き​を​シミュレート​し​ます。\"\n\n#: Source/diablo.cpp:2407 Source/diablo.cpp:2414\nmsgid \"Left mouse click\"\nmsgstr \"マウス​の​左​クリック\"\n\n#: Source/diablo.cpp:2408 Source/diablo.cpp:2415\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"マウス​の​左​ボタン​を​シミュレート​し​ます。\"\n\n#: Source/diablo.cpp:2432 Source/diablo.cpp:2439\nmsgid \"Right mouse click\"\nmsgstr \"マウス​の​右​クリック\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2440\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"マウス​の​右​ボタン​を​シミュレート​し​ます。\"\n\n#: Source/diablo.cpp:2446\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"ゲーム​パッド​の​ホット​スペル​メニュー\"\n\n#: Source/diablo.cpp:2447\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"ホールド​し​て​呪文​ホットキー​を​設定​また​は​使用​し​ます。\"\n\n#: Source/diablo.cpp:2453\nmsgid \"Gamepad menu navigator\"\nmsgstr \"ゲーム​パッド​メニュー​ナビゲーター\"\n\n#: Source/diablo.cpp:2454\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"長押し​で​ゲーム​パッド​メニュー​ナビゲーション​に​アクセス​し​ます。\"\n\n#: Source/diablo.cpp:2469 Source/diablo.cpp:2478\nmsgid \"Toggle game menu\"\nmsgstr \"ゲーム​メニュー​の​切り替え\"\n\n#: Source/diablo.cpp:2470 Source/diablo.cpp:2479\nmsgid \"Opens the game menu.\"\nmsgstr \"ゲーム​メニュー​を​開き​ます。\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Game saved\"\nmsgstr \"ゲーム​の​セーブ\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"デモ​で​は​マルチ​プレイ​機能​は​あり​ませ​ん\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Direct Sound Creation Failed\"\n\n#: Source/diablo_msg.cpp:72\nmsgid \"Not available in shareware version\"\nmsgstr \"シェアウェア​版​で​は​使用​でき​ませ​ん\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Not enough space to save\"\nmsgstr \"保存​する​ため​の​十分​な​スペース​が​あり​ませ​ん\"\n\n#: Source/diablo_msg.cpp:74\nmsgid \"No Pause in town\"\nmsgstr \"町中​で​は​ポーズ​でき​ませ​ん\"\n\n#: Source/diablo_msg.cpp:75\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"ハードディスク​へ​の​コピー​を​推奨\"\n\n#: Source/diablo_msg.cpp:76\nmsgid \"Multiplayer sync problem\"\nmsgstr \"マルチ​プレイヤー​同期​の​問題\"\n\n#: Source/diablo_msg.cpp:77\nmsgid \"No pause in multiplayer\"\nmsgstr \"マルチ​プレイ​で​は​ポーズ​が​でき​ませ​ん\"\n\n#: Source/diablo_msg.cpp:79\nmsgid \"Saving...\"\nmsgstr \"セーブ​中​…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"幾多​の​犠牲​の​上、新た​なる​力​は​得​られる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"New strength is forged through destruction\"\nmsgstr \"新た​なる​力、破壊​に​より​鍛え​られる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"Those who defend seldom attack\"\nmsgstr \"厚​き​盾、矛先​は​鈍る\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"義​を​以​て​振ら​れる​剣、鋭​き​刃​は​宿る\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"油断​おこたら​ず​ば、その​身​は​守ら​れる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"広がり​し​マナ​の​力、再び​寄り集う\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"時​の​流れ、鋼​の​力​を​奪う​は​叶わ​ず\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"目​に​見える​もの、常​なら​ざる​が​魔術​なり\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"What once was opened now is closed\"\nmsgstr \"開か​れ​し​物、今、再び​閉じる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"高揚​は​知識​の​代価​に​与え​られる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Arcane power brings destruction\"\nmsgstr \"神秘​の​力​が​災い​を​もたらす\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"その​何れ​か、保た​れる​こと​なく​傷つく​こと​なく\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"深紅​と​淡青、太陽​と​なる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"知恵​と​知識​に​己​を​賭けよ\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"Drink and be refreshed\"\nmsgstr \"これ​を​飲み、しばし​休ま​れよ\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Wherever you go, there you are\"\nmsgstr \"何処​へ​行く​とも、汝​は​汝\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"その​力、知識​の​代価​に​与え​られる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"Riches abound when least expected\"\nmsgstr \"ちり​も​積もれ​ば​山​と​なる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"強欲​は​朽ち、忍耐​は​報わ​れる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"仲間​より​の​慈愛​の​祈り​を​受ける\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"人​の​手​は、時折​運命​に​よっ​て​導か​れる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"その​力、神​へ​の​信仰​に​よっ​て​支え​られる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:102\nmsgid \"The essence of life flows from within\"\nmsgstr \"生命​の​本質、その​内​より​湧き出る\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:103\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"天​より​の​眺め、道​は​明らか​と​なる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:104\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"救済​は​知識​の​代価​に​与え​られる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"神秘​は​道理​の​光​の​下、明らか​に​さ​れる\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"Those who are last may yet be first\"\nmsgstr \"人​より​先んずれ​ど​も​…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"寛大​なる​心、いつ​の​日​か​報わ​れん\"\n\n#: Source/diablo_msg.cpp:108\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"この​レベル​は、最低​8​レベル​以上​で​なく​て​は​なり​ませ​ん。\"\n\n#: Source/diablo_msg.cpp:109\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"この​レベル​は、最低​13​レベル​以上​で​なく​て​は​なり​ませ​ん。\"\n\n#: Source/diablo_msg.cpp:110\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"この​レベル​は、最低​17​レベル​以上​で​なく​て​は​なり​ませ​ん。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"神秘​なる​知識​が​授け​られ​た​!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"That which does not kill you...\"\nmsgstr \"死な​ない​もの​は​…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"Knowledge is power.\"\nmsgstr \"知識​は​力​なり\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"Give and you shall receive.\"\nmsgstr \"与えよ、さらば​与え​られ​ん\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"触れる​こと​で​得​られる​経験​も​ある。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"There's no place like home.\"\nmsgstr \"家​の​よう​な​場所​は​ない。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:117\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"精神的​な​エネルギー​が​回復​する。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:118\nmsgid \"You feel more agile.\"\nmsgstr \"より​機敏​な​感じ​が​する。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:119\nmsgid \"You feel stronger.\"\nmsgstr \"強く​なっ​た​と​感じる。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:120\nmsgid \"You feel wiser.\"\nmsgstr \"賢く​なっ​た​と​感じる。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:121\nmsgid \"You feel refreshed.\"\nmsgstr \"爽快感​が​ある。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:122\nmsgid \"That which can break will.\"\nmsgstr \"壊せる​もの​は​壊す。\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"大聖堂\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"カタコンベ\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"洞窟\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"巣\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"地下​聖堂\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Lv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} 難易度\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"メニュー​に​ある\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"ループ​バック\"\n\n#: Source/dvlnet/tcp_client.cpp:118\nmsgid \"Unable to connect\"\nmsgstr \"接続​でき​ませ​ん\"\n\n#: Source/dvlnet/tcp_client.cpp:156\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"エラー​：​サーバー​から​データ​を​読み込め​ませ​ん\"\n\n#: Source/dvlnet/tcp_client.cpp:216\nmsgid \"\"\n\"Server failed to decrypt your packet. Check if you typed the password \"\n\"correctly.\"\nmsgstr \"\"\n\"サーバー​が​パケット​の​復号​に​失敗​し​まし​た。パスワード​が​正しく​入力​さ​れ​て​いる​か​確\"\n\"認​し​て​ください。\"\n\n#: Source/engine/assets.cpp:252\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\"ファイル​を​開け​ませ​ん​でし​た​：​\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"MPQ​ファイル​が​破損​し​て​いる​可能性​が​あり​ます。ファイル​の​整合性​を​確認​し​て​くださ\"\n\"い。\"\n\n#: Source/engine/assets.cpp:434\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq​また​は​spawn.mpq\"\n\n#: Source/engine/assets.cpp:472\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"いくつ​か​の​Hellfire MPQ​が​欠落​し​て​い​ます\"\n\n#: Source/engine/assets.cpp:472\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"すべて​の​Hellfire MPQ​が​見つから​ない。\\n\"\n\"​すべて​の hf​*​.mpq ファイル​を​コピー​し​て​ください。\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:546\nmsgid \"Resolution\"\nmsgstr \"解像度\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:835\nmsgid \"Run in Town\"\nmsgstr \"街​で​走る\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:838\nmsgid \"Theo Quest\"\nmsgstr \"テオクエスト\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:839\nmsgid \"Cow Quest\"\nmsgstr \"牛​クエスト\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:851\nmsgid \"Auto Gold Pickup\"\nmsgstr \"自動​ゴールド​回収\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:852\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"自動​エリクサー​回収\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:853\nmsgid \"Auto Oil Pickup\"\nmsgstr \"自動​オイル​回収\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:854\nmsgid \"Auto Pickup in Town\"\nmsgstr \"街中​で​自動​回収\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:855\nmsgid \"Auto Equip Weapons\"\nmsgstr \"武器​の​自動​装備\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:856\nmsgid \"Auto Equip Armor\"\nmsgstr \"アーマー​の​自動​装備\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:857\nmsgid \"Auto Equip Helms\"\nmsgstr \"ヘルム​の​自動​装備\"\n\n#: Source/engine/demomode.cpp:200 Source/options.cpp:858\nmsgid \"Auto Equip Shields\"\nmsgstr \"シールド​の​自動​装備\"\n\n#: Source/engine/demomode.cpp:201 Source/options.cpp:859\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"ジュエリー​の​自動​装備\"\n\n#: Source/engine/demomode.cpp:202 Source/options.cpp:860\nmsgid \"Randomize Quests\"\nmsgstr \"クエスト​の​ランダム化\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:862\nmsgid \"Show Item Labels\"\nmsgstr \"アイテム​ラベル​を​表示\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:863\nmsgid \"Auto Refill Belt\"\nmsgstr \"ベルト​の​自動​補充\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:864\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"被害​を​与える​祭壇​を​無効化\"\n\n#: Source/engine/demomode.cpp:209 Source/options.cpp:866\nmsgid \"Heal Potion Pickup\"\nmsgstr \"ヒーリング​・​ポーション​回収\"\n\n#: Source/engine/demomode.cpp:210 Source/options.cpp:867\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"フルヒーリング​・​ポーション​回収\"\n\n#: Source/engine/demomode.cpp:211 Source/options.cpp:868\nmsgid \"Mana Potion Pickup\"\nmsgstr \"マナ​・​ポーション​を​回収\"\n\n#: Source/engine/demomode.cpp:212 Source/options.cpp:869\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"フルマナ​・​ポーション​回収\"\n\n#: Source/engine/demomode.cpp:213 Source/options.cpp:870\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"回復​ポーション​回収\"\n\n#: Source/engine/demomode.cpp:214 Source/options.cpp:871\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"フル​回復​ポーション​回収\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:64\nmsgid \"Options\"\nmsgstr \"オプション\"\n\n#: Source/gamemenu.cpp:53\nmsgid \"Save Game\"\nmsgstr \"ゲーム​の​セーブ\"\n\n#: Source/gamemenu.cpp:55 Source/gamemenu.cpp:65\nmsgid \"Exit to Main Menu\"\nmsgstr \"メインメニュー​に​戻る\"\n\n#: Source/gamemenu.cpp:56 Source/gamemenu.cpp:66\nmsgid \"Quit Game\"\nmsgstr \"ゲーム​の​終了\"\n\n#: Source/gamemenu.cpp:75\nmsgid \"Gamma\"\nmsgstr \"明るさ\"\n\n#: Source/gamemenu.cpp:76 Source/gamemenu.cpp:175\nmsgid \"Speed\"\nmsgstr \"スピード\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Music Disabled\"\nmsgstr \"音楽​を​禁止\"\n\n#: Source/gamemenu.cpp:88\nmsgid \"Sound\"\nmsgstr \"効果音\"\n\n#: Source/gamemenu.cpp:89\nmsgid \"Sound Disabled\"\nmsgstr \"効果音​を​禁止\"\n\n#: Source/gmenu.cpp:190\nmsgid \"Pause\"\nmsgstr \"ポーズ\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$​キーボード​ショートカット:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    ヘルプ​を​開く\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   メインメニュー​を​表示\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   オート​マップ​を​表示\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: 全て​の​情報​画面​を​非表示\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: スピード​ブック​を​開く\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: スペル​ブック​を​開く\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: インベントリ​画面​を​開く\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: キャラクター​画面​を​開く\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: クエストログ​を​開く\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: 画面​の​明るさ​を​下げる\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G​：​画面​の​明るさ​を​上げる\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: ゲーム​画面​の​拡大\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: ズーム オート​マップ\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: ベルト​アイテム​を​使う\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     スキル、スペル​の​ホットキー​設定\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + マウス​の​左​ボタン。動か​ず​に​攻撃\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + 左​マウス​ボタン​（​キャラクター​画面​上​）。すべて​の​ステータス​ポイント​を​割\"\n\"り当てる\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + 左​マウス​ボタン​（​インベントリ​上​）。アイテム​の​ベルト​へ​の​移動、また​は​ア\"\n\"イテム​の​装備​・​非​装備\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + 左​マウス​ボタン​（​ベルト​上​）。アイテム​を​インベントリ​に​移動\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$​移動:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"移動中​に​マウス​ボタン​を​押し​た​まま​に​する​と、キャラクター​は​その​方向​に​移動​し​続け​\"\n\"ます。\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$​戦闘:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"シフトキー​を​押し​ながら​左​クリック​を​する​と、キャラクター​が​動か​ず​に​攻撃​する​こと​\"\n\"が​でき​ます。\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$​オート​マップ:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"オート​マップ​に​アクセス​する​に​は、情報​バー​の​「​MAP​」​ボタン​を​クリック​する​か、キー\"\n\"ボード​の​「​TAB​」​を​押し​ます。地図​の​拡大​・​縮小​は​＋​キー​と​-​キー​で​行い​ます。地図​の​\"\n\"スクロール​は、矢印​キー​で​行い​ます。\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$​オブジェクト​を​拾う:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"ポーション​や​巻物​など、サイズ​の​小さい​使用​可能​な​アイテム​は、インターフェイス\"\n\"バー​の​上部​に​ある​「​ベルト​」​に​自動的​に​配置​さ​れ​ます。ベルト​に​アイテム​を​入れる​\"\n\"と、その​ボックス​に​小さな​数字​が​表示​さ​れ​ます。アイテム​は、対応​する​番号​を​押す​\"\n\"か、アイテム​上​で​右​クリック​する​こと​で​使用​でき​ます。\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$​ゴールド:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"インベントリ​内​の​ゴールド​の​山​を​右​クリック​する​と、ドロップ​する​ゴールド​の​量​を​指\"\n\"定​する​こと​が​でき​ます。\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$​スキル​と​呪文:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"インターフェースバー​の​「​呪文​」​ボタン​を​左​クリック​する​と、自分​の​スキル​や​呪文​の​\"\n\"リスト​に​アクセス​でき​ます。覚え​て​いる​呪文​や​杖​で​使える​呪文​は​ここ​に​表示​さ​れ​て​い​\"\n\"ます。唱え​たい​呪文​を​左​クリック​する​と、その​呪文​を​準備​する​こと​が​でき​ます。準備​\"\n\"さ​れ​た​呪文​は、プレイ​エリア​内​で​右​クリック​する​だけ​で​唱える​こと​が​でき​ます。\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$​呪文​の​ため​の​スピード​ブック​の​使用:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"準備​さ​れ​た​呪文​」​ボタン​を​左​クリック​する​と、「​スピード​ブック​」​が​開き、すぐ​に​使\"\n\"える​スキル​や​呪文​を​選ぶ​こと​が​でき​ます。準備​し​た​スキル​や​呪文​を​使用​する​に​は、メ\"\n\"イン​の​プレイ​エリア​で​右​クリック​する​だけ​です。\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + 左​クリック​で​「​現在​の​呪文​を​選択​」​ボタン​を​押す​と、準備​し​て​い​た​呪文​が​ク\"\n\"リア​さ​れ​ます\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$​スペルホットキー​の​設定:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"スキル​や​呪文、巻物​など​の​ホットキー​を​4​つ​まで​割り当てる​こと​が​でき​ます。上​の​セク\"\n\"ション​で​説明​し​た​よう​に、「​スピード​ブック​」​を​開く​こと​から​始め​ます。割り当て​た\"\n\"い​呪文​を​ハイライト​し​た​後、F5、F6、F7、F8​キー​を​押し​ます。\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$​スペル​ブック:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"2​冊​以上​の​本​を​読む​こと​で、その​呪文​の​知識​が​増え、より​効果的​に​呪文​を​唱える​こと​が​\"\n\"でき​ます。\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"シェアウェア ヘルファイア ヘルプ\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"ヘルファイア ヘルプ\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"シェアウェア ディアブロ ヘルプ\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"ディアブロ ヘルプ\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"ESC​を​押し​て​終了​する​か、矢印​キー​で​スクロール​し​ます。\"\n\n#: Source/init.cpp:136\nmsgid \"Unable to create main window\"\nmsgstr \"メイン​ウィンドウ​を​作成​でき​ませ​ん\"\n\n#: Source/inv.cpp:2235\nmsgid \"No room for item\"\nmsgstr \"アイテム​が​入る​余地​が​ない\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"アキュラシー​・​オイル\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Mastery\"\nmsgstr \"マスタリー​・​オイル\"\n\n#: Source/items.cpp:219 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"シャープネス​・​オイル\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Death\"\nmsgstr \"デス​・​オイル\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Skill\"\nmsgstr \"スキル​・​オイル\"\n\n#: Source/items.cpp:222 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"鍛冶屋​の​オイル\"\n\n#: Source/items.cpp:223\nmsgid \"Oil of Fortitude\"\nmsgstr \"フォルチュード​・​オイル\"\n\n#: Source/items.cpp:224\nmsgid \"Oil of Permanence\"\nmsgstr \"パーマネンス​・​オイル\"\n\n#: Source/items.cpp:225\nmsgid \"Oil of Hardening\"\nmsgstr \"ハーデニング​・​オイル\"\n\n#: Source/items.cpp:226\nmsgid \"Oil of Imperviousness\"\nmsgstr \"インプレビュスネス​・​オイル\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1109\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{1}​の​{0}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1121\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{2}​の​{0}{1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1159\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{2}​の​{0}{1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1163\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1167\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{1}​の​{0}\"\n\n#: Source/items.cpp:1648 Source/items.cpp:1656\nmsgid \"increases a weapon's\"\nmsgstr \"武器​の​命中​率​を\"\n\n#: Source/items.cpp:1649\nmsgid \"chance to hit\"\nmsgstr \"上昇​さ​せる\"\n\n#: Source/items.cpp:1652\nmsgid \"greatly increases a\"\nmsgstr \"武器​の​命中​率​を\"\n\n#: Source/items.cpp:1653\nmsgid \"weapon's chance to hit\"\nmsgstr \"大幅​に​上昇​さ​せる\"\n\n#: Source/items.cpp:1657\nmsgid \"damage potential\"\nmsgstr \"増大​さ​せる\"\n\n#: Source/items.cpp:1660\nmsgid \"greatly increases a weapon's\"\nmsgstr \"武器​の​ダメージ​を​大幅​に\"\n\n#: Source/items.cpp:1661\nmsgid \"damage potential - not bows\"\nmsgstr \"増大​さ​せる​-​ボウ​を​除く\"\n\n#: Source/items.cpp:1664\nmsgid \"reduces attributes needed\"\nmsgstr \"防具​や​武器​の​必要​能力​値\"\n\n#: Source/items.cpp:1665\nmsgid \"to use armor or weapons\"\nmsgstr \"の​値​を​引き下げる\"\n\n#: Source/items.cpp:1668\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"を​20​%​回復\"\n\n#: Source/items.cpp:1669\nmsgid \"item's durability\"\nmsgstr \"アイテム​の​耐久​度\"\n\n#: Source/items.cpp:1672\nmsgid \"increases an item's\"\nmsgstr \"次​の​もの​を​増大​さ​せ​ます:\"\n\n#: Source/items.cpp:1673\nmsgid \"current and max durability\"\nmsgstr \"20​%​増大​さ​せる\"\n\n#: Source/items.cpp:1676\nmsgid \"makes an item indestructible\"\nmsgstr \"アイテム​を​壊れ​ない​よう​に​し​ます\"\n\n#: Source/items.cpp:1679\nmsgid \"increases the armor class\"\nmsgstr \"防具​と​盾​の​防御​力​を\"\n\n#: Source/items.cpp:1680\nmsgid \"of armor and shields\"\nmsgstr \"増大​さ​せる\"\n\n#: Source/items.cpp:1683\nmsgid \"greatly increases the armor\"\nmsgstr \"防具​と​盾​の​防御​力​を\"\n\n#: Source/items.cpp:1684\nmsgid \"class of armor and shields\"\nmsgstr \"大幅​に​増大​さ​せる\"\n\n#: Source/items.cpp:1687 Source/items.cpp:1694\nmsgid \"sets fire trap\"\nmsgstr \"ファイヤー​トラップ​を​設置\"\n\n#: Source/items.cpp:1691\nmsgid \"sets lightning trap\"\nmsgstr \"ライトニング​トラップ​を​設置\"\n\n#: Source/items.cpp:1697\nmsgid \"sets petrification trap\"\nmsgstr \"石化​トラップ​を​設置\"\n\n#: Source/items.cpp:1700\nmsgid \"restore all life\"\nmsgstr \"ライフ​を​全​回復\"\n\n#: Source/items.cpp:1703\nmsgid \"restore some life\"\nmsgstr \"ライフ​を​回復\"\n\n#: Source/items.cpp:1706\nmsgid \"restore some mana\"\nmsgstr \"マナ​を​回復\"\n\n#: Source/items.cpp:1709\nmsgid \"restore all mana\"\nmsgstr \"マナ​を​全​回復\"\n\n#: Source/items.cpp:1712\nmsgid \"increase strength\"\nmsgstr \"STR を​増大\"\n\n#: Source/items.cpp:1715\nmsgid \"increase magic\"\nmsgstr \"MAG を​増大\"\n\n#: Source/items.cpp:1718\nmsgid \"increase dexterity\"\nmsgstr \"DEX を​増大\"\n\n#: Source/items.cpp:1721\nmsgid \"increase vitality\"\nmsgstr \"VIT を​増大\"\n\n#: Source/items.cpp:1724\nmsgid \"restore some life and mana\"\nmsgstr \"ライフ​と​マナ​を​回復\"\n\n#: Source/items.cpp:1727 Source/items.cpp:1730\nmsgid \"restore all life and mana\"\nmsgstr \"ライフ​と​マナ​を​全​回復\"\n\n#: Source/items.cpp:1731\nmsgid \"(works only in arenas)\"\nmsgstr \"(​アリーナ​のみ​）\"\n\n#: Source/items.cpp:1766\nmsgid \"Right-click to view\"\nmsgstr \"右​クリック​で​表示\"\n\n#: Source/items.cpp:1769\nmsgid \"Right-click to use\"\nmsgstr \"右​クリック​で​使用\"\n\n#: Source/items.cpp:1771\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"右​クリック​で​読み、\\n\"\n\"​左​クリック​で​ターゲット\"\n\n#: Source/items.cpp:1773\nmsgid \"Right-click to read\"\nmsgstr \"右​クリック​で​読む\"\n\n#: Source/items.cpp:1780\nmsgid \"Activate to view\"\nmsgstr \"アクティベート​し​て​表示​する\"\n\n#: Source/items.cpp:1784 Source/items.cpp:1809\nmsgid \"Open inventory to use\"\nmsgstr \"使用​する​インベントリ​を​開く\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to use\"\nmsgstr \"アクティベート​し​て​使う\"\n\n#: Source/items.cpp:1789\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"スペル​ブック​から​選択​し​\\n\"\n\"​読ん​で​キャスト\"\n\n#: Source/items.cpp:1791\nmsgid \"Activate to read\"\nmsgstr \"アクティベート​し​て​読む\"\n\n#: Source/items.cpp:1805\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} を​見る\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} を​使用​する\"\n\n#: Source/items.cpp:1814\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"スペル​ブック​から​選択、\\n\"\n\"​そして​{}​を​読む\"\n\n#: Source/items.cpp:1816\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} を​読む\"\n\n#: Source/items.cpp:1823\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"レベル: {:d}\"\n\n#: Source/items.cpp:1827\nmsgid \"Doubles gold capacity\"\nmsgstr \"ゴールド​の​容量​を​2​倍​に​する\"\n\n#: Source/items.cpp:1860 Source/stores.cpp:329\nmsgid \"Required:\"\nmsgstr \"必要​能力:\"\n\n#: Source/items.cpp:1862 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Str\"\n\n#: Source/items.cpp:1864 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1866 Source/stores.cpp:335\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Dex\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2222\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"呪文​の​書: {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2225\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s}​の​耳\"\n\n#: Source/items.cpp:3881\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"命中​率: {:+d}​%\"\n\n#: Source/items.cpp:3884\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}​%​ダメージ\"\n\n#: Source/items.cpp:3887 Source/items.cpp:4069\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"命中​率:{:+d}​%​, {:+d}​% ダメージ\"\n\n#: Source/items.cpp:3890\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}​%​防護​力\"\n\n#: Source/items.cpp:3893\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"防御​力: {:d}\"\n\n#: Source/items.cpp:3897\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"耐火​炎: {:+d}​%\"\n\n#: Source/items.cpp:3899\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"耐火​炎: {:+d}​% MAX\"\n\n#: Source/items.cpp:3903\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"耐​電撃: {:+d}​%\"\n\n#: Source/items.cpp:3905\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"耐​電撃: {:+d}​% MAX\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"耐​魔法: {:+d}​%\"\n\n#: Source/items.cpp:3911\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"耐​魔法: {:+d}​% MAX\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"全​耐性: {:+d}​%\"\n\n#: Source/items.cpp:3916\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"全​耐性: {:+d}​% MAX\"\n\n#: Source/items.cpp:3919\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"全呪文{:d} レベルアップ\"\n\n#: Source/items.cpp:3921\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"全呪文{:d}レベルダウン\"\n\n#: Source/items.cpp:3923\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"呪文​の​レベル​に​変化​なし​(​?​)\"\n\n#: Source/items.cpp:3925\nmsgid \"Extra charges\"\nmsgstr \"追加​チャージ\"\n\n#: Source/items.cpp:3927\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s}チャージ\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"追加​火炎​ダメージ:{:d}\"\n\n#: Source/items.cpp:3932\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"追加​火炎​ダメージ: {:d}-{:d}\"\n\n#: Source/items.cpp:3935\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"追加​電撃​ダメージ: {:d}\"\n\n#: Source/items.cpp:3937\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"追加​電撃​ダメージ: {:d}-{:d}\"\n\n#: Source/items.cpp:3940\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"STR{:+d}\"\n\n#: Source/items.cpp:3943\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"MAG{:+d}\"\n\n#: Source/items.cpp:3946\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"DEX{:+d}\"\n\n#: Source/items.cpp:3949\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"VIT{:+d}\"\n\n#: Source/items.cpp:3952\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"全​能力​値​{:+d}\"\n\n#: Source/items.cpp:3955\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"敵​から​受ける​ダメージ​{:+d}\"\n\n#: Source/items.cpp:3958\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"ヒット​ポイント: {:+d}\"\n\n#: Source/items.cpp:3961\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"マナ: {:+d}\"\n\n#: Source/items.cpp:3963\nmsgid \"high durability\"\nmsgstr \"高い​耐久​度\"\n\n#: Source/items.cpp:3965\nmsgid \"decreased durability\"\nmsgstr \"低い​耐久​度\"\n\n#: Source/items.cpp:3967\nmsgid \"indestructible\"\nmsgstr \"壊れ​ない\"\n\n#: Source/items.cpp:3969\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"視界​+{:d}​%\"\n\n#: Source/items.cpp:3971\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"視界​-{:d}​%\"\n\n#: Source/items.cpp:3973\nmsgid \"multiple arrows per shot\"\nmsgstr \"一回​の​射撃​で​複数​の​矢​を​放つ\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"火炎​矢​の​ダメージ: {:d}\"\n\n#: Source/items.cpp:3978\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"火炎​矢​の​ダメージ: {:d}-{:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"電撃​矢​の​ダメージ: {:d}\"\n\n#: Source/items.cpp:3983\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"電撃​矢​の​ダメージ: {:d}-{:d}\"\n\n#: Source/items.cpp:3986\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"ファイヤーボールダメージ: {:d}\"\n\n#: Source/items.cpp:3988\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"ファイヤーボールダメージ: {:d}-{:d}\"\n\n#: Source/items.cpp:3990\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"ダメージ​時​に​反撃:1-3\"\n\n#: Source/items.cpp:3992\nmsgid \"user loses all mana\"\nmsgstr \"全て​の​マナ​を​失う\"\n\n#: Source/items.cpp:3994\nmsgid \"absorbs half of trap damage\"\nmsgstr \"罠​に​よる​ダメージ​半減\"\n\n#: Source/items.cpp:3996\nmsgid \"knocks target back\"\nmsgstr \"ノック​バック​効果\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"対​悪魔​族​ダメージ​+200​%\"\n\n#: Source/items.cpp:4000\nmsgid \"All Resistance equals 0\"\nmsgstr \"全て​の​耐性​を​失う\"\n\n#: Source/items.cpp:4003\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"マナ​を​3​%​吸収\"\n\n#: Source/items.cpp:4005\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"マナ​を​5​%​吸収\"\n\n#: Source/items.cpp:4009\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"ライフ​を​3​%​吸収\"\n\n#: Source/items.cpp:4011\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"ライフ​を​5​%​吸収\"\n\n#: Source/items.cpp:4014\nmsgid \"penetrates target's armor\"\nmsgstr \"ターゲット​の​アーマー​を​貫通\"\n\n#: Source/items.cpp:4017\nmsgid \"quick attack\"\nmsgstr \"速い​攻撃\"\n\n#: Source/items.cpp:4019\nmsgid \"fast attack\"\nmsgstr \"高速​攻撃\"\n\n#: Source/items.cpp:4021\nmsgid \"faster attack\"\nmsgstr \"超​高速​攻撃\"\n\n#: Source/items.cpp:4023\nmsgid \"fastest attack\"\nmsgstr \"神速​攻撃\"\n\n#: Source/items.cpp:4024 Source/items.cpp:4032 Source/items.cpp:4079\nmsgid \"Another ability (NW)\"\nmsgstr \"別​の​能力​（​NW​）\"\n\n#: Source/items.cpp:4027\nmsgid \"fast hit recovery\"\nmsgstr \"高速​体勢​回復\"\n\n#: Source/items.cpp:4029\nmsgid \"faster hit recovery\"\nmsgstr \"早い​体勢​回復\"\n\n#: Source/items.cpp:4031\nmsgid \"fastest hit recovery\"\nmsgstr \"神速​体勢​回復\"\n\n#: Source/items.cpp:4034\nmsgid \"fast block\"\nmsgstr \"早い​防御\"\n\n#: Source/items.cpp:4036\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"追加ダメージ: {:d}\"\n\n#: Source/items.cpp:4038\nmsgid \"fires random speed arrows\"\nmsgstr \"発射​間隔​が​一定​で​ない\"\n\n#: Source/items.cpp:4040\nmsgid \"unusual item damage\"\nmsgstr \"魔法​の​アイテム​に​ダメージ\"\n\n#: Source/items.cpp:4042\nmsgid \"altered durability\"\nmsgstr \"特殊​な​耐久​度\"\n\n#: Source/items.cpp:4044\nmsgid \"one handed sword\"\nmsgstr \"片手​持ち​ソード\"\n\n#: Source/items.cpp:4046\nmsgid \"constantly lose hit points\"\nmsgstr \"少し​ずつ​ライフ​を​失う\"\n\n#: Source/items.cpp:4048\nmsgid \"life stealing\"\nmsgstr \"直接​攻撃​で​ライフ​吸収\"\n\n#: Source/items.cpp:4050\nmsgid \"no strength requirement\"\nmsgstr \"筋力​を​必要​と​し​ない\"\n\n#: Source/items.cpp:4053\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"電撃​ダメージ: {:d}\"\n\n#: Source/items.cpp:4055\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"電撃​ダメージ: {:d}-{:d}\"\n\n#: Source/items.cpp:4057\nmsgid \"charged bolts on hits\"\nmsgstr \"チャージド​ボルト\"\n\n#: Source/items.cpp:4059\nmsgid \"occasional triple damage\"\nmsgstr \"たまに​3​倍​の​ダメージ\"\n\n#: Source/items.cpp:4061\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"崩壊​{:+d}​%​ダメージ\"\n\n#: Source/items.cpp:4063\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"モンスター​に​2​倍​の​ダメージ、自分​に​1​倍​の​ダメージ\"\n\n#: Source/items.cpp:4065\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"ランダム​に​0​～​600​％​の​ダメージ\"\n\n#: Source/items.cpp:4067\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"低い​耐久性、{:+d}​%​の​ダメージ\"\n\n#: Source/items.cpp:4071\nmsgid \"extra AC vs demons\"\nmsgstr \"対​悪魔​族​の​追加​AC\"\n\n#: Source/items.cpp:4073\nmsgid \"extra AC vs undead\"\nmsgstr \"対​アンデッド​用​の​追加​AC\"\n\n#: Source/items.cpp:4075\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50​%​の​マナ​を​ヘルス​に​移動\"\n\n#: Source/items.cpp:4077\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40​%​の​ヘルス​を​マナ​に​移動\"\n\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"ダメージ:{:d}  壊れ​ない\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4122 Source/items.cpp:4163\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"ダメージ:{:d}  耐久​度:{:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4166\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"ダメージ: {:d}-{:d}  壊れ​ない\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4168\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"ダメージ:{:d}-{:d}  耐久​度:{:d}/{:d}\"\n\n#: Source/items.cpp:4132 Source/items.cpp:4178\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"防御​力:{:d}  壊れ​ない\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4134 Source/items.cpp:4180\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"防御​力: {:d}  耐久​度: {:d}/{:d}\"\n\n#: Source/items.cpp:4137 Source/items.cpp:4171 Source/items.cpp:4184\n#: Source/stores.cpp:303\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"チャージ: {:d}/{:d}\"\n\n#: Source/items.cpp:4146\nmsgid \"unique item\"\nmsgstr \"ユニーク​アイテム\"\n\n#: Source/items.cpp:4174 Source/items.cpp:4182 Source/items.cpp:4188\nmsgid \"Not Identified\"\nmsgstr \"未​鑑定\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"スケルトン​キング​の​間\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"納骨堂\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:80\nmsgid \"Maze\"\nmsgstr \"迷宮\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"汚れ​た​水源\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"大司教​ラザルス​の​間\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"教会​アリーナ\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"ヘル​・​アリーナ\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"サークル​・​オブ​・​ライフ​・​アリーナ\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"ダンジョン​へ​の​入り口\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"カタコンベ​へ​の​入り口\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"ケイブ​へ​の​入り口\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"ヘル​へ​の​入り口\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"ハイブ​へ​の​入り口\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"地下​聖堂​へ​の​入り口\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"レベル​{:d}​へ​上がる\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"町​へ​戻る\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"レベル​{:d}​へ​下りる\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"ディアブロ​の​もと​へ\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"巣​レベル {:d}​へ​上がる\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"地下​聖堂​レベル {:d}​へ​上がる\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"世界​の​礎\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"地下​聖堂​へ​の​入り口 レベル {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"レベル​{:d}​へ​戻る\"\n\n#: Source/loadsave.cpp:2016 Source/loadsave.cpp:2473\nmsgid \"Unable to open save file archive\"\nmsgstr \"保存​ファイル​の​アーカイブ​を​開け​ませ​ん\"\n\n#: Source/loadsave.cpp:2427\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"スタッシュ​の​バージョン​が​不正​です。スタッシュ​に​アクセス​する​と、データ​が​上書き​\"\n\"さ​れ​ます！！」\"\n\n#: Source/loadsave.cpp:2446\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"スタッシュ​の​サイズ​が​不正​です。スタッシュ​に​アクセス​する​と、データ​が​上書き​さ​れ​\"\n\"ます！！\"\n\n#: Source/loadsave.cpp:2477\nmsgid \"Invalid save file\"\nmsgstr \"無効​な​保存​ファイル\"\n\n#: Source/loadsave.cpp:2509\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"プレイヤー​は​Hellfire​のみ​の​レベル​に​い​ます\"\n\n#: Source/loadsave.cpp:2775\nmsgid \"Invalid game state\"\nmsgstr \"無効​な​ゲーム​状態\"\n\n#: Source/menu.cpp:164\nmsgid \"Unable to display mainmenu\"\nmsgstr \"メインメニュー​を​表示​でき​ませ​ん\"\n\n#: Source/monster.cpp:2997\nmsgid \"Animal\"\nmsgstr \"アニマル\"\n\n#: Source/monster.cpp:2999\nmsgid \"Demon\"\nmsgstr \"デーモン\"\n\n#: Source/monster.cpp:3001\nmsgid \"Undead\"\nmsgstr \"アンデッド\"\n\n#: Source/monster.cpp:4420\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"タイプ: {:s}  殺傷​数: {:d}\"\n\n#: Source/monster.cpp:4422\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"殺傷​数: {:d}\"\n\n#: Source/monster.cpp:4448\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"ヒット​ポイント: {:d}-{:d}\"\n\n#: Source/monster.cpp:4453\nmsgid \"No magic resistance\"\nmsgstr \"魔法​耐性​無し\"\n\n#: Source/monster.cpp:4456\nmsgid \"Resists:\"\nmsgstr \"耐性:\"\n\n#: Source/monster.cpp:4458 Source/monster.cpp:4468\nmsgid \" Magic\"\nmsgstr \" 魔法\"\n\n#: Source/monster.cpp:4460 Source/monster.cpp:4470\nmsgid \" Fire\"\nmsgstr \" 火炎\"\n\n#: Source/monster.cpp:4462 Source/monster.cpp:4472\nmsgid \" Lightning\"\nmsgstr \" ライトニング\"\n\n#: Source/monster.cpp:4466\nmsgid \"Immune:\"\nmsgstr \"無効:\"\n\n#: Source/monster.cpp:4483\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"タイプ: {:s}\"\n\n#: Source/monster.cpp:4488 Source/monster.cpp:4494\nmsgid \"No resistances\"\nmsgstr \"耐性​無し\"\n\n#: Source/monster.cpp:4489 Source/monster.cpp:4498\nmsgid \"No Immunities\"\nmsgstr \"無効​無し\"\n\n#: Source/monster.cpp:4492\nmsgid \"Some Magic Resistances\"\nmsgstr \"魔法​耐性​あり​(​属性​不明​)\"\n\n#: Source/monster.cpp:4496\nmsgid \"Some Magic Immunities\"\nmsgstr \"魔法​無効化​(​属性​不明​)\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"書き込み​の​ため​の​アーカイブ​を​開く​の​に​失敗​し​まし​た。\"\n\n#: Source/msg.cpp:1693\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} が​無効​な​呪文​を​唱え​た。\"\n\n#: Source/msg.cpp:1697\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} が​不正​な​呪文​を​唱え​た。\"\n\n#: Source/msg.cpp:2298 Source/multi.cpp:877 Source/multi.cpp:937\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"プレイヤー​「​{:s}​」​（​レベル​{:d}​）​が​ゲーム​に​参加​し​まし​た\"\n\n#: Source/msg.cpp:2730\nmsgid \"The game ended\"\nmsgstr \"ゲーム​終了\"\n\n#: Source/msg.cpp:2736\nmsgid \"Unable to get level data\"\nmsgstr \"レベル​データ​が​取得​でき​ませ​ん\"\n\n#: Source/multi.cpp:294\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"プレイヤー​「​{:s}​」​が​ゲーム​から​離脱​し​まし​た\"\n\n#: Source/multi.cpp:299\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"プレイヤー​「​{:s}​」​が​Diablo​を​殺し​て​ゲーム​を​去っ​た​!\"\n\n#: Source/multi.cpp:303\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"プレイヤー​「​{:s}​」​が​タイムアウト​で​脱落\"\n\n#: Source/multi.cpp:941\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"プレイヤー​「​{:s}​」​（​レベル​{:d}​）​は​すでに​ゲーム​に​参加​し​て​い​ます\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:126\nmsgid \"Mysterious\"\nmsgstr \"奇怪​な\"\n\n#: Source/objects.cpp:127\nmsgid \"Hidden\"\nmsgstr \"ヒドゥン\"\n\n#: Source/objects.cpp:128\nmsgid \"Gloomy\"\nmsgstr \"漆黒​の\"\n\n#: Source/objects.cpp:129 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"ウィアード\"\n\n#: Source/objects.cpp:130 Source/objects.cpp:137\nmsgid \"Magical\"\nmsgstr \"魔術​の\"\n\n#: Source/objects.cpp:131\nmsgid \"Stone\"\nmsgstr \"石​の\"\n\n#: Source/objects.cpp:132\nmsgid \"Religious\"\nmsgstr \"信仰​の\"\n\n#: Source/objects.cpp:133\nmsgid \"Enchanted\"\nmsgstr \"帯​魔​の\"\n\n#: Source/objects.cpp:134\nmsgid \"Thaumaturgic\"\nmsgstr \"奇跡​の\"\n\n#: Source/objects.cpp:135\nmsgid \"Fascinating\"\nmsgstr \"魅了​の\"\n\n#: Source/objects.cpp:136\nmsgid \"Cryptic\"\nmsgstr \"秘密​の\"\n\n#: Source/objects.cpp:138\nmsgid \"Eldritch\"\nmsgstr \"妖魔​の\"\n\n#: Source/objects.cpp:139\nmsgid \"Eerie\"\nmsgstr \"不審​な\"\n\n#: Source/objects.cpp:140\nmsgid \"Divine\"\nmsgstr \"神々しい\"\n\n#: Source/objects.cpp:141 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"ホーリー\"\n\n#: Source/objects.cpp:142\nmsgid \"Sacred\"\nmsgstr \"厳粛​なる\"\n\n#: Source/objects.cpp:143\nmsgid \"Spiritual\"\nmsgstr \"魂​の\"\n\n#: Source/objects.cpp:144\nmsgid \"Spooky\"\nmsgstr \"憑霊​の\"\n\n#: Source/objects.cpp:145\nmsgid \"Abandoned\"\nmsgstr \"荒涼​たる\"\n\n#: Source/objects.cpp:146\nmsgid \"Creepy\"\nmsgstr \"陰湿​な\"\n\n#: Source/objects.cpp:147\nmsgid \"Quiet\"\nmsgstr \"終了\"\n\n#: Source/objects.cpp:148\nmsgid \"Secluded\"\nmsgstr \"隠遁​の\"\n\n#: Source/objects.cpp:149\nmsgid \"Ornate\"\nmsgstr \"華麗​なる\"\n\n#: Source/objects.cpp:150\nmsgid \"Glimmering\"\nmsgstr \"燐光​の\"\n\n#: Source/objects.cpp:151\nmsgid \"Tainted\"\nmsgstr \"穢れ​た\"\n\n#: Source/objects.cpp:152\nmsgid \"Oily\"\nmsgstr \"油性\"\n\n#: Source/objects.cpp:153\nmsgid \"Glowing\"\nmsgstr \"光る\"\n\n#: Source/objects.cpp:154\nmsgid \"Mendicant's\"\nmsgstr \"メンディキャンズ\"\n\n#: Source/objects.cpp:155\nmsgid \"Sparkling\"\nmsgstr \"スパークリング\"\n\n#: Source/objects.cpp:157\nmsgid \"Shimmering\"\nmsgstr \"煌めき\"\n\n#: Source/objects.cpp:158\nmsgid \"Solar\"\nmsgstr \"ソーラー\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:160\nmsgid \"Murphy's\"\nmsgstr \"マーフィーズ\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:213\nmsgid \"The Great Conflict\"\nmsgstr \"偉大​なる​闘争\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Wages of Sin are War\"\nmsgstr \"罪​深き​闘い\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"ホラドリム​の​物語\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Dark Exile\"\nmsgstr \"闇​の​追放\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Sin War\"\nmsgstr \"罪​深き​闘い\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Binding of the Three\"\nmsgstr \"三​兄弟​の​呪縛\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Realms Beyond\"\nmsgstr \"彼方​の​王国\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"Tale of the Three\"\nmsgstr \"三​大​邪悪​の​物語\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"The Black King\"\nmsgstr \"暗黒​の​王\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"ジャーナル: 包囲\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Meeting\"\nmsgstr \"ジャーナル: 会議\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Tirade\"\nmsgstr \"ジャーナル: ティラード\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: His Power Grows\"\nmsgstr \"ジャーナル: 勢力​拡大\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"ジャーナル: ナ​・​クルル\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: The End\"\nmsgstr \"ジャーナル: 終焉\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"A Spellbook\"\nmsgstr \"スペル​ブック\"\n\n#: Source/objects.cpp:4792\nmsgid \"Crucified Skeleton\"\nmsgstr \"はりつけ​の​スケルトン\"\n\n#: Source/objects.cpp:4796\nmsgid \"Lever\"\nmsgstr \"レバー\"\n\n#: Source/objects.cpp:4806\nmsgid \"Open Door\"\nmsgstr \"開い​た​ドア\"\n\n#: Source/objects.cpp:4808\nmsgid \"Closed Door\"\nmsgstr \"閉じ​た​ドア\"\n\n#: Source/objects.cpp:4810\nmsgid \"Blocked Door\"\nmsgstr \"閉じ​られ​ない​ドア\"\n\n#: Source/objects.cpp:4815\nmsgid \"Ancient Tome\"\nmsgstr \"太古​の​書\"\n\n#: Source/objects.cpp:4817\nmsgid \"Book of Vileness\"\nmsgstr \"外道​の​書\"\n\n#: Source/objects.cpp:4822\nmsgid \"Skull Lever\"\nmsgstr \"ドクロ​の​レバー\"\n\n#: Source/objects.cpp:4824\nmsgid \"Mythical Book\"\nmsgstr \"神話​の​書\"\n\n#: Source/objects.cpp:4827\nmsgid \"Small Chest\"\nmsgstr \"小さな​チェスト\"\n\n#: Source/objects.cpp:4830\nmsgid \"Chest\"\nmsgstr \"チェスト\"\n\n#: Source/objects.cpp:4834\nmsgid \"Large Chest\"\nmsgstr \"大きな​チェスト\"\n\n#: Source/objects.cpp:4837\nmsgid \"Sarcophagus\"\nmsgstr \"棺\"\n\n#: Source/objects.cpp:4839\nmsgid \"Bookshelf\"\nmsgstr \"読​台\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookcase\"\nmsgstr \"本棚\"\n\n#: Source/objects.cpp:4845\nmsgid \"Barrel\"\nmsgstr \"樽\"\n\n#: Source/objects.cpp:4848\nmsgid \"Pod\"\nmsgstr \"ポッド\"\n\n#: Source/objects.cpp:4851\nmsgid \"Urn\"\nmsgstr \"Urn\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4854\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} 祭壇\"\n\n#: Source/objects.cpp:4856\nmsgid \"Skeleton Tome\"\nmsgstr \"スケルトン​の​書\"\n\n#: Source/objects.cpp:4858\nmsgid \"Library Book\"\nmsgstr \"蔵書\"\n\n#: Source/objects.cpp:4860\nmsgid \"Blood Fountain\"\nmsgstr \"血色​の​泉\"\n\n#: Source/objects.cpp:4862\nmsgid \"Decapitated Body\"\nmsgstr \"首​無し​の​死体\"\n\n#: Source/objects.cpp:4864\nmsgid \"Book of the Blind\"\nmsgstr \"盲目​の​書\"\n\n#: Source/objects.cpp:4866\nmsgid \"Book of Blood\"\nmsgstr \"血潮​の​書\"\n\n#: Source/objects.cpp:4868\nmsgid \"Purifying Spring\"\nmsgstr \"清浄​なる​泉\"\n\n#: Source/objects.cpp:4871 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"防具\"\n\n#: Source/objects.cpp:4873 Source/objects.cpp:4890\nmsgid \"Weapon Rack\"\nmsgstr \"武器​架\"\n\n#: Source/objects.cpp:4875\nmsgid \"Goat Shrine\"\nmsgstr \"山羊​の​祭壇\"\n\n#: Source/objects.cpp:4877\nmsgid \"Cauldron\"\nmsgstr \"地獄​の​大釜\"\n\n#: Source/objects.cpp:4879\nmsgid \"Murky Pool\"\nmsgstr \"濁っ​た​池\"\n\n#: Source/objects.cpp:4881\nmsgid \"Fountain of Tears\"\nmsgstr \"涙​の​源泉\"\n\n#: Source/objects.cpp:4883\nmsgid \"Steel Tome\"\nmsgstr \"刀剣​の​書\"\n\n#: Source/objects.cpp:4885\nmsgid \"Pedestal of Blood\"\nmsgstr \"血​の​台座\"\n\n#: Source/objects.cpp:4892\nmsgid \"Mushroom Patch\"\nmsgstr \"キノコ​の​群生\"\n\n#: Source/objects.cpp:4894\nmsgid \"Vile Stand\"\nmsgstr \"忌まわし​き​台座\"\n\n#: Source/objects.cpp:4896\nmsgid \"Slain Hero\"\nmsgstr \"死​せ​る​勇者\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4909\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"トラップ​の​掛かっ​た​{:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4914\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (​無効​)\"\n\n#: Source/options.cpp:321 Source/options.cpp:458 Source/options.cpp:464\nmsgid \"ON\"\nmsgstr \"オン\"\n\n#: Source/options.cpp:321 Source/options.cpp:456 Source/options.cpp:462\nmsgid \"OFF\"\nmsgstr \"オフ\"\n\n#: Source/options.cpp:433 Source/options.cpp:434\nmsgid \"Game Mode\"\nmsgstr \"ゲーム​モード\"\n\n#: Source/options.cpp:433\nmsgid \"Game Mode Settings\"\nmsgstr \"ゲーム​モード​設定\"\n\n#: Source/options.cpp:434\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"ディアブロ、また​は​ヘルファイア​を​選択​し​ます。\"\n\n#: Source/options.cpp:440\nmsgid \"Restrict to Shareware\"\nmsgstr \"シェアウェア​の​制限\"\n\n#: Source/options.cpp:440\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"ゲーム​を​体験版​と​互換性​の​ある​もの​に​し​ます。ディアブロ​の​製品​版​を​持っ​て​い​ない​友\"\n\"人​と​の​マルチ​プレイ​が​可能​に​なり​ます。\"\n\n#: Source/options.cpp:453\nmsgid \"Start Up\"\nmsgstr \"起動\"\n\n#: Source/options.cpp:453\nmsgid \"Start Up Settings\"\nmsgstr \"起動​時​の​設定\"\n\n#: Source/options.cpp:454 Source/options.cpp:460\nmsgid \"Intro\"\nmsgstr \"イントロ\"\n\n#: Source/options.cpp:454 Source/options.cpp:460\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"イントロ​・​シネマ​ティック​を​表示​し​ます。\"\n\n#: Source/options.cpp:466\nmsgid \"Splash\"\nmsgstr \"スプラッシュ\"\n\n#: Source/options.cpp:466\nmsgid \"Shown splash screen.\"\nmsgstr \"スプラッシュ​画面​を​設定​し​ます。\"\n\n#: Source/options.cpp:468\nmsgid \"Logo and Title Screen\"\nmsgstr \"ロゴ​と​タイトル​画面\"\n\n#: Source/options.cpp:469\nmsgid \"Title Screen\"\nmsgstr \"タイトル​画面\"\n\n#: Source/options.cpp:484\nmsgid \"Diablo specific Settings\"\nmsgstr \"ディアブロ​固有​の​設定\"\n\n#: Source/options.cpp:498\nmsgid \"Hellfire specific Settings\"\nmsgstr \"ヘルファイア​固有​の​設定\"\n\n#: Source/options.cpp:512\nmsgid \"Audio\"\nmsgstr \"オーディオ\"\n\n#: Source/options.cpp:512\nmsgid \"Audio Settings\"\nmsgstr \"オーディオ​設定\"\n\n#: Source/options.cpp:515\nmsgid \"Walking Sound\"\nmsgstr \"歩行​音\"\n\n#: Source/options.cpp:515\nmsgid \"Player emits sound when walking.\"\nmsgstr \"歩行​時​に​音​が​出る​よう​に​なり​ます。\"\n\n#: Source/options.cpp:516\nmsgid \"Auto Equip Sound\"\nmsgstr \"自動​装備​サウンド\"\n\n#: Source/options.cpp:516\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"ピックアップ​時​に​自動的​に​アイテム​を​装備​する​と、装備​音​が​鳴り​ます。\"\n\n#: Source/options.cpp:517\nmsgid \"Item Pickup Sound\"\nmsgstr \"アイテム​回収​音\"\n\n#: Source/options.cpp:517\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"アイテム​を​拾う​と、効果音​が​鳴り​ます。\"\n\n#: Source/options.cpp:518\nmsgid \"Sample Rate\"\nmsgstr \"サンプリングレート\"\n\n#: Source/options.cpp:518\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"出力​サンプリングレート (​Hz​)。\"\n\n#: Source/options.cpp:519\nmsgid \"Channels\"\nmsgstr \"チャンネル\"\n\n#: Source/options.cpp:519\nmsgid \"Number of output channels.\"\nmsgstr \"出力​チャンネル​数​です。\"\n\n#: Source/options.cpp:520\nmsgid \"Buffer Size\"\nmsgstr \"バッファ​サイズ\"\n\n#: Source/options.cpp:520\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"バッファ​サイズ​（​1​チャンネル​あたり​の​フレーム​数​）​です。\"\n\n#: Source/options.cpp:521\nmsgid \"Resampling Quality\"\nmsgstr \"再​サンプリング​品質\"\n\n#: Source/options.cpp:521\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"再​サンプラー​の​品質​を​0​（​最低​）​から​5​（​最高​）​まで​で​設定​し​ます。\"\n\n#: Source/options.cpp:546\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"ゲーム​の​内部​解像度​に​影響​を​与え、表示​領域​を​決定​し​ます。注意​：​アップ​スケーリン\"\n\"グ、整数​倍​スケーリング、画面​に​合わせる​を​使用​し​た​場合、画面​解像度​と​は​異なる​場\"\n\"合​が​あり​ます。\"\n\n#: Source/options.cpp:585\nmsgid \"Resampler\"\nmsgstr \"リサンプラ\"\n\n#: Source/options.cpp:585\nmsgid \"Audio resampler\"\nmsgstr \"オーディオ​・​リサンプラ\"\n\n#: Source/options.cpp:642\nmsgid \"Device\"\nmsgstr \"デバイス\"\n\n#: Source/options.cpp:642\nmsgid \"Audio device\"\nmsgstr \"オーディオ​・​デバイス\"\n\n#: Source/options.cpp:739\nmsgid \"Graphics\"\nmsgstr \"グラフィックス\"\n\n#: Source/options.cpp:739\nmsgid \"Graphics Settings\"\nmsgstr \"グラフィックス​設定\"\n\n#: Source/options.cpp:740\nmsgid \"Fullscreen\"\nmsgstr \"フルスクリーン\"\n\n#: Source/options.cpp:740\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"ゲーム​を​ウィンドウ​モード​また​は​フルスクリーンモード​で​表示​し​ます。\"\n\n#: Source/options.cpp:742\nmsgid \"Fit to Screen\"\nmsgstr \"画面​に​合わせる\"\n\n#: Source/options.cpp:742\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"ゲーム​ウィンドウ​を​現在​の​デスクトップ​画面​の​アスペクト​比​と​解像度​に​自動的​に​調整​\"\n\"し​ます。\"\n\n#: Source/options.cpp:751\nmsgid \"Upscale\"\nmsgstr \"アップ​スケーリング\"\n\n#: Source/options.cpp:751\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"ゲーム​の​解像度​から​モニター​の​解像度​へ​の​画像​の​スケーリング​を​可能​に​し​ます。モニ\"\n\"ター​解像度​の​変更​を​防ぎ、ウィンドウ​の​リサイズ​を​可能​に​し​ます。\"\n\n#: Source/options.cpp:758\nmsgid \"Scaling Quality\"\nmsgstr \"スケーリング​品質\"\n\n#: Source/options.cpp:758\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"アップス​ケール​時​の​出力​画像​に​オプション​の​フィルター​を​有効​に​し​ます。\"\n\n#: Source/options.cpp:760\nmsgid \"Nearest Pixel\"\nmsgstr \"近接​ピクセル\"\n\n#: Source/options.cpp:761\nmsgid \"Bilinear\"\nmsgstr \"バイリニア\"\n\n#: Source/options.cpp:762\nmsgid \"Anisotropic\"\nmsgstr \"異方​性\"\n\n#: Source/options.cpp:764\nmsgid \"Integer Scaling\"\nmsgstr \"整数​倍​スケーリング\"\n\n#: Source/options.cpp:764\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"整数​の​比率​で​画像​を​スケーリング​し​ます。\"\n\n#: Source/options.cpp:772\nmsgid \"Frame Rate Control\"\nmsgstr \"フレーム​レート​制御\"\n\n#: Source/options.cpp:773\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\"画面​表示​の​乱れ​を​抑え、パフォーマンス​と​消費​電力​の​バランス​を​取る​ため​に​フレーム​\"\n\"レート​を​管理​し​ます。\"\n\n#: Source/options.cpp:783\nmsgid \"Vertical Sync\"\nmsgstr \"垂直​同期\"\n\n#: Source/options.cpp:785\nmsgid \"Limit FPS\"\nmsgstr \"フレーム​レート​制限\"\n\n#: Source/options.cpp:788\nmsgid \"Zoom on when enabled.\"\nmsgstr \"有効​な​場合​は​ズーム。\"\n\n#: Source/options.cpp:789\nmsgid \"Per-pixel Lighting\"\nmsgstr \"ピクセル​単位​の​ライティング\"\n\n#: Source/options.cpp:789\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"光​の​グラデーション​を​より​滑らか​に​する​ため​の​繊細​な​ライティング。\"\n\n#: Source/options.cpp:790\nmsgid \"Color Cycling\"\nmsgstr \"カラー​サイクル\"\n\n#: Source/options.cpp:790\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"水、溶岩、酸​の​アニメーション​に​使用​さ​れる​カラー​サイクリング​効果​です。\"\n\n#: Source/options.cpp:791\nmsgid \"Alternate nest art\"\nmsgstr \"異なる​巣​の​画像\"\n\n#: Source/options.cpp:791\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"ヘルファイア​の​巣​の​タイル​セット​に​別​の​パレット​が​使用​さ​れ​ます。\"\n\n#: Source/options.cpp:793\nmsgid \"Hardware Cursor\"\nmsgstr \"ハードウェア​カーソル\"\n\n#: Source/options.cpp:793\nmsgid \"Use a hardware cursor\"\nmsgstr \"ハードウェア​カーソル​を​使用​し​ます。\"\n\n#: Source/options.cpp:794\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"アイテム​用​ハードウェア​カーソル\"\n\n#: Source/options.cpp:794\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"アイテム​に​ハードウェア​カーソル​を​使用​し​ます。\"\n\n#: Source/options.cpp:795\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"ハードウェア​カーソル​の​最大​サイズ\"\n\n#: Source/options.cpp:795\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"ハードウェア​カーソル​の​最大​幅​/​高さ。それ​以上​の​ソフトウェア​カーソル​に​なり​ます。\"\n\n#: Source/options.cpp:797\nmsgid \"Show FPS\"\nmsgstr \"フレーム​レート​を​表示\"\n\n#: Source/options.cpp:797\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"画面​左上​に​FPS​を​表示​し​ます。\"\n\n#: Source/options.cpp:833\nmsgid \"Gameplay\"\nmsgstr \"ゲーム​プレイ\"\n\n#: Source/options.cpp:833\nmsgid \"Gameplay Settings\"\nmsgstr \"ゲーム​プレイ​設定\"\n\n#: Source/options.cpp:835\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"ディアブロ​と​ヘルファイア​で​街中​で​の​ジョギング​/​早歩き​を​有効​に​し​ます。この​オプ\"\n\"ション​は​拡張​版​で​導入​さ​れ​まし​た。\"\n\n#: Source/options.cpp:836\nmsgid \"Grab Input\"\nmsgstr \"入力​捕捉\"\n\n#: Source/options.cpp:836\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"有効​に​する​と、マウス​が​ゲーム​ウィンドウ​に​ロック​さ​れ​ます。\"\n\n#: Source/options.cpp:837\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"非​アクティブ​時​に​ゲーム​を​一時停止\"\n\n#: Source/options.cpp:837\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"有効​に​する​と、フォーカス​を​失っ​た​とき​に​ゲーム​が​一時停止​し​ます。\"\n\n#: Source/options.cpp:838\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"リトル​ガール​クエスト​を​有効​に​し​ます。\"\n\n#: Source/options.cpp:839\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"ジャージー​の​クエスト​を​有効​に​する。農家​の​レスター​の​代わり​に​コンプリート​ナット​\"\n\"が​登場​し​ます。\"\n\n#: Source/options.cpp:840\nmsgid \"Friendly Fire\"\nmsgstr \"フレンドリー​ファイア\"\n\n#: Source/options.cpp:840\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"フレンドリー​モード​が​オン​に​なっ​て​い​て​も、マルチ​プレイヤー​の​プレイヤー​間​で​弓矢​\"\n\"や​呪文​の​ダメージ​を​許容​し​ます。\"\n\n#: Source/options.cpp:841\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"マルチ​プレイ​で​の​フルクエスト\"\n\n#: Source/options.cpp:841\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"シングルプレイヤー​版​クエスト​の​フル​/​ノーカット​を​有効​に​する。\"\n\n#: Source/options.cpp:842\nmsgid \"Test Bard\"\nmsgstr \"テスト​・​バード\"\n\n#: Source/options.cpp:842\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"ヒーロー​選択​メニュー​に​バード​の​キャラクター​タイプ​を​強制的​に​表示​し​ます。\"\n\n#: Source/options.cpp:843\nmsgid \"Test Barbarian\"\nmsgstr \"テスト​・​バーバリアン\"\n\n#: Source/options.cpp:843\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\"ヒーロー​選択​メニュー​に​バーバリアン​の​キャラクター​タイプ​を​強制的​に​表示​し​ます。\"\n\n#: Source/options.cpp:844\nmsgid \"Experience Bar\"\nmsgstr \"経験値​バー\"\n\n#: Source/options.cpp:844\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"画面​下​の​UI​に​経験値​バー​を​追加​し​ます。\"\n\n#: Source/options.cpp:845\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"ストア​で​アイテム​画像​を​表示​する\"\n\n#: Source/options.cpp:845\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"ストア​メニュー​の​アイテム​説明​の​左側​に​アイテム​画像​を​表示​し​ます。\"\n\n#: Source/options.cpp:846\nmsgid \"Show health values\"\nmsgstr \"ヘルス​値​を​表示\"\n\n#: Source/options.cpp:846\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"ヘルス​・​グローブ​上​に​ヘルス​の​現在地​/​最大値​を​表示​し​ます。\"\n\n#: Source/options.cpp:847\nmsgid \"Show mana values\"\nmsgstr \"マナ​値​を​表示\"\n\n#: Source/options.cpp:847\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"マナ​・​グローブ​上​に​マナ​の​現在​値​/​最大値​を​表示​し​ます。\"\n\n#: Source/options.cpp:848\nmsgid \"Show Party Information\"\nmsgstr \"パーティー​情報​を​表示\"\n\n#: Source/options.cpp:848\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\"接続​し​て​いる​マルチ​プレイ​の​パーティー​メンバー​全員​の​体力​と​マナ​を​表示​し​ます。\"\n\n#: Source/options.cpp:849\nmsgid \"Enemy Health Bar\"\nmsgstr \"敵​の​ヘルスバー\"\n\n#: Source/options.cpp:849\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"画面​上部​に​敵​の​ヘルスバー​を​表示​し​ます。\"\n\n#: Source/options.cpp:850\nmsgid \"Floating Item Info Box\"\nmsgstr \"フローティング​アイテム​情報​ボックス\"\n\n#: Source/options.cpp:850\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\"アイテム​に​カーソル​を​合わせる​と、フローティング​アイテム​情報​ボックス​に​アイテム​\"\n\"情報​を​表示​し​ます。\"\n\n#: Source/options.cpp:851\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"プレイヤー​付近​の​ゴールド​を​自動的​に​回収​し​ます。\"\n\n#: Source/options.cpp:852\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"プレイヤー​付近​の​エリクサー​を​自動的​に​回収​し​ます。\"\n\n#: Source/options.cpp:853\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"プレイヤー​付近​の​オイル​を​自動的​に​回収​し​ます。\"\n\n#: Source/options.cpp:854\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"街中​で​自動的​に​アイテム​を​回収​し​ます。\"\n\n#: Source/options.cpp:855\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"有効​に​する​と、武器​を​ピックアップ​や​購入​時​に​自動的​に​装備​さ​れ​ます。\"\n\n#: Source/options.cpp:856\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"有効​に​する​と、アーマー​を​ピックアップ​や​購入​時​に​自動的​に​装備​さ​れ​ます。\"\n\n#: Source/options.cpp:857\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"有効​に​する​と、ヘルム​を​ピックアップ​や​購入​時​に​自動的​に​装備​さ​れ​ます。\"\n\n#: Source/options.cpp:858\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"有効​に​する​と、シールド​を​ピックアップ​や​購入​時​に​自動的​に​装備​さ​れ​ます。\"\n\n#: Source/options.cpp:859\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"有効​に​する​と、ジュエリー​を​ピックアップ​や​購入​時​に​自動的​に​装備​さ​れ​ます。\"\n\n#: Source/options.cpp:860\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"新規​ゲーム​で​クエスト​が​ランダム​に​選択​さ​れ​ます。\"\n\n#: Source/options.cpp:861\nmsgid \"Show Monster Type\"\nmsgstr \"モンスター​の​種類​を​表示\"\n\n#: Source/options.cpp:861\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"モンスター​に​カーソル​を​合わせる​と、UI​の​説明​欄​に​モンスター​の​種類​が​表示​さ​れ​ま\"\n\"す。\"\n\n#: Source/options.cpp:862\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"有効​な​場合、アイテム​の​ラベル​を​表示​し​ます。\"\n\n#: Source/options.cpp:863\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"ベルト​アイテム​が​消費​さ​れる​と、在庫​から​ベルト​を​補充​し​ます。\"\n\n#: Source/options.cpp:864\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"有効​に​する​と、地獄​の​大釜、魅了​の​祭壇、山羊​の​祭壇、華麗​なる​祭壇、神聖​なる​祭壇​\"\n\"と​マーフィー​の​祭壇​が​クリック​でき​なく​なり、無効​と​表示​さ​れ​ます。\"\n\n#: Source/options.cpp:865\nmsgid \"Quick Cast\"\nmsgstr \"クイック​キャスト\"\n\n#: Source/options.cpp:865\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"呪文​の​ホットキー​は、準備​さ​れ​た​呪文​を​切り替える​の​で​は​なく、瞬時​に​呪文​を​唱え​ま\"\n\"す。\"\n\n#: Source/options.cpp:866\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"自動的​に​拾う​ヒーリング​・​ポーション​の​数​です。\"\n\n#: Source/options.cpp:867\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"自動的​に​拾う​フルヒーリング​・​ポーション​の​数​です。\"\n\n#: Source/options.cpp:868\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"自動的​に​拾う​マナ​・​ポーション​の​数​です。\"\n\n#: Source/options.cpp:869\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"自動的​に​拾う​フルマナ​・​ポーション​の​数​です。\"\n\n#: Source/options.cpp:870\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"自動的​に​拾う​回復​ポーション​の​数​です。\"\n\n#: Source/options.cpp:871\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"自動的​に​拾う​フル​回復​ポーション​の​数​です。\"\n\n#: Source/options.cpp:922\nmsgid \"Controller\"\nmsgstr \"コントローラー\"\n\n#: Source/options.cpp:922\nmsgid \"Controller Settings\"\nmsgstr \"コントローラー​設定\"\n\n#: Source/options.cpp:931\nmsgid \"Network\"\nmsgstr \"ネットワーク\"\n\n#: Source/options.cpp:931\nmsgid \"Network Settings\"\nmsgstr \"ネットワーク​設定\"\n\n#: Source/options.cpp:943\nmsgid \"Chat\"\nmsgstr \"チャット\"\n\n#: Source/options.cpp:943\nmsgid \"Chat Settings\"\nmsgstr \"チャット​設定\"\n\n#: Source/options.cpp:952 Source/options.cpp:1069\nmsgid \"Language\"\nmsgstr \"言語\"\n\n#: Source/options.cpp:952\nmsgid \"Define what language to use in game.\"\nmsgstr \"ゲーム​内​で​使用​する​言語​を​定義​し​ます。\"\n\n#: Source/options.cpp:1069\nmsgid \"Language Settings\"\nmsgstr \"言語​設定\"\n\n#: Source/options.cpp:1080\nmsgid \"Keymapping\"\nmsgstr \"キーマッピング\"\n\n#: Source/options.cpp:1080\nmsgid \"Keymapping Settings\"\nmsgstr \"キー​・​マップ​設定\"\n\n#: Source/options.cpp:1300\nmsgid \"Padmapping\"\nmsgstr \"パッド​・​マッピング\"\n\n#: Source/options.cpp:1300\nmsgid \"Padmapping Settings\"\nmsgstr \"パッド​・​マップ​設定\"\n\n#: Source/options.cpp:1552\nmsgid \"Mods\"\nmsgstr \"MOD\"\n\n#: Source/options.cpp:1552\nmsgid \"Mod Settings\"\nmsgstr \"MOD​設定\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"レベル\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"経験値\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"次​の​レベル\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"基本\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"現在\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"STR\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"MAG\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"DEX\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"VIT\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"配布​ポイント\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"ゴールド\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"防御​力\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"命中​率\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"ダメージ\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"ライフ\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"マナ\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"耐​魔法\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"耐火​炎\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"耐​電撃\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"キャラ\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"クエスト\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"マップ\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"メニュー\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"持ち物\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"呪文\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"ボイス\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"ミュート\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"使え​ない\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"1/3 ターゲット​HP\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"回復​量 {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"ダメージ {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"スキル\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"スタッフ ({:d} チェージ)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Lvl {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"マナ {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"スペル\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"アンデッド​系​に​のみ​ダメージ\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"スクロール\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"スタッフ\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"スペルホットキー {:s}\"\n\n#: Source/pfile.cpp:767\nmsgid \"Unable to open archive\"\nmsgstr \"アーカイブ​を​開け​ませ​ん\"\n\n#: Source/pfile.cpp:769\nmsgid \"Unable to load character\"\nmsgstr \"キャラクター​を​ロード​でき​ませ​ん\"\n\n#: Source/plrmsg.cpp:85 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (​レベル {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"チャット​履歴 (​メッセージ: {:d}​)\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} ゴールド\"\n\n#: Source/qol/stash.cpp:657\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"ゴールド​を​どれ​だけ​引き出し​ます​か？\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"レベル {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"経験値: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"最大​レベル\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"次​の​レベル: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s}​レベル​{:d}​へ\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:78\nmsgid \"King Leoric's Tomb\"\nmsgstr \"レオリック​王​の​墓所\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"納骨堂\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:81\nmsgid \"A Dark Passage\"\nmsgstr \"暗き​通廊\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:82\nmsgid \"Unholy Altar\"\nmsgstr \"ラザルス​の​間\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:357\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"{:s}​へ\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"助け​が​必要​だ！こっち​だ！\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"つい​て​き​て。\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"これ​は、あなた​の​ため​に​用意​し​た​もの​です。\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"さあ、死ぬ​ん​だ​!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"回復​し​て​くれ！\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"気​を​つけ​て！\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"ありがとう。\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"撤退！\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"すま​ない。\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"待機​中。\"\n\n#: Source/stores.cpp:133\nmsgid \"Griswold\"\nmsgstr \"グリズウォルド\"\n\n#: Source/stores.cpp:134\nmsgid \"Pepin\"\nmsgstr \"ペピン\"\n\n#: Source/stores.cpp:136\nmsgid \"Ogden\"\nmsgstr \"オグデン\"\n\n#: Source/stores.cpp:137\nmsgid \"Cain\"\nmsgstr \"ケイン\"\n\n#: Source/stores.cpp:138\nmsgid \"Farnham\"\nmsgstr \"ファーンハム\"\n\n#: Source/stores.cpp:139\nmsgid \"Adria\"\nmsgstr \"エイドリア\"\n\n#: Source/stores.cpp:140 Source/stores.cpp:1237\nmsgid \"Gillian\"\nmsgstr \"ジリアン\"\n\n#: Source/stores.cpp:141\nmsgid \"Wirt\"\nmsgstr \"ワート\"\n\n#: Source/stores.cpp:267 Source/stores.cpp:274\nmsgid \"Back\"\nmsgstr \"戻る\"\n\n#: Source/stores.cpp:296 Source/stores.cpp:302 Source/stores.cpp:328\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"ダメージ: {:d}-{:d}  \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"防御​力: {:d}  \"\n\n#: Source/stores.cpp:317\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"耐久​度: {:d}/{:d},  \"\n\n#: Source/stores.cpp:319\nmsgid \"Indestructible\"\nmsgstr \"壊れ​ない\"\n\n#: Source/stores.cpp:385 Source/stores.cpp:1008 Source/stores.cpp:1224\nmsgid \"Welcome to the\"\nmsgstr \"ようこそ​!\"\n\n#: Source/stores.cpp:386\nmsgid \"Blacksmith's shop\"\nmsgstr \"グリズウォルド​の​鍛冶屋​へ\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:662 Source/stores.cpp:1010\n#: Source/stores.cpp:1050 Source/stores.cpp:1226 Source/stores.cpp:1238\n#: Source/stores.cpp:1251\nmsgid \"Would you like to:\"\nmsgstr \"何​を​する​?\"\n\n#: Source/stores.cpp:388\nmsgid \"Talk to Griswold\"\nmsgstr \"グリズウォルド​と​話す\"\n\n#: Source/stores.cpp:389\nmsgid \"Buy basic items\"\nmsgstr \"ベーシック​アイテム​を​買う\"\n\n#: Source/stores.cpp:390\nmsgid \"Buy premium items\"\nmsgstr \"プレミアム​アイテム​を​買う\"\n\n#: Source/stores.cpp:391 Source/stores.cpp:665\nmsgid \"Sell items\"\nmsgstr \"アイテム​を​売る\"\n\n#: Source/stores.cpp:392\nmsgid \"Repair items\"\nmsgstr \"アイテム​の​修理\"\n\n#: Source/stores.cpp:393\nmsgid \"Leave the shop\"\nmsgstr \"店​を​出る\"\n\n#: Source/stores.cpp:421 Source/stores.cpp:701 Source/stores.cpp:1030\nmsgid \"I have these items for sale:\"\nmsgstr \"さて、何​が​欲しい​ん​だ​い\"\n\n#: Source/stores.cpp:464\nmsgid \"I have these premium items for sale:\"\nmsgstr \"どれ​も​珍しい​アイテム​だろう\"\n\n#: Source/stores.cpp:560 Source/stores.cpp:791\nmsgid \"You have nothing I want.\"\nmsgstr \"何​も​買える​物​は​ない​よう​だ​が。\"\n\n#: Source/stores.cpp:571 Source/stores.cpp:803\nmsgid \"Which item is for sale?\"\nmsgstr \"何​を​売っ​て​くれる​ん​だ​い​?\"\n\n#: Source/stores.cpp:639\nmsgid \"You have nothing to repair.\"\nmsgstr \"何​も​壊れ​ちゃ​い​ない​ぞ。\"\n\n#: Source/stores.cpp:650\nmsgid \"Repair which item?\"\nmsgstr \"どれ​を​直す​ん​だ​?\"\n\n#: Source/stores.cpp:661\nmsgid \"Witch's shack\"\nmsgstr \"魔女​の​小屋\"\n\n#: Source/stores.cpp:663\nmsgid \"Talk to Adria\"\nmsgstr \"エイドリア​と​話す\"\n\n#: Source/stores.cpp:664 Source/stores.cpp:1012\nmsgid \"Buy items\"\nmsgstr \"アイテム​を​買う\"\n\n#: Source/stores.cpp:666\nmsgid \"Recharge staves\"\nmsgstr \"リチャージ​する\"\n\n#: Source/stores.cpp:667\nmsgid \"Leave the shack\"\nmsgstr \"小屋​を​立ち去る\"\n\n#: Source/stores.cpp:865\nmsgid \"You have nothing to recharge.\"\nmsgstr \"リチャージ​できる​もの​は​無い​よ。\"\n\n#: Source/stores.cpp:876\nmsgid \"Recharge which item?\"\nmsgstr \"どれ​に​リチャージ​する​ん​だ​い​?\"\n\n#: Source/stores.cpp:889\nmsgid \"You do not have enough gold\"\nmsgstr \"所持金​が​足り​ませ​ん\"\n\n#: Source/stores.cpp:897\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"置く​場所​が​あり​ませ​ん\"\n\n#: Source/stores.cpp:915\nmsgid \"Do we have a deal?\"\nmsgstr \"よろしい​です​か​?\"\n\n#: Source/stores.cpp:918\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"これ​を​鑑定​する​の​だ​ね​?\"\n\n#: Source/stores.cpp:924\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"これ​を​買う​の​だ​ね​?\"\n\n#: Source/stores.cpp:927\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"これ​に​リチャージ​する​ん​だ​ね​?\"\n\n#: Source/stores.cpp:931\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"これ​を​売っ​て​くれる​ん​だ​ね​?\"\n\n#: Source/stores.cpp:934\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"これ​を​直す​ん​だ​な​?\"\n\n#: Source/stores.cpp:948\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"義足​の​少年​ワート\"\n\n#: Source/stores.cpp:951 Source/stores.cpp:958\nmsgid \"Talk to Wirt\"\nmsgstr \"ワート​と​話す\"\n\n#: Source/stores.cpp:952\nmsgid \"I have something for sale,\"\nmsgstr \"俺​は​いい​もの​を​持っ​て​いる。\"\n\n#: Source/stores.cpp:953\nmsgid \"but it will cost 50 gold\"\nmsgstr \"で​も、50​ゴールド​払わ​なきゃ\"\n\n#: Source/stores.cpp:954\nmsgid \"just to take a look. \"\nmsgstr \"見せ​て​やら​ない​ぜ。\"\n\n#: Source/stores.cpp:955\nmsgid \"What have you got?\"\nmsgstr \"払う​?\"\n\n#: Source/stores.cpp:956 Source/stores.cpp:959 Source/stores.cpp:1053\n#: Source/stores.cpp:1241\nmsgid \"Say goodbye\"\nmsgstr \"立ち去る\"\n\n#: Source/stores.cpp:969\nmsgid \"I have this item for sale:\"\nmsgstr \"さて、何​が​欲しい​ん​だ​い\"\n\n#: Source/stores.cpp:986\nmsgid \"Leave\"\nmsgstr \"去る\"\n\n#: Source/stores.cpp:1009\nmsgid \"Healer's home\"\nmsgstr \"治療​師​の​家\"\n\n#: Source/stores.cpp:1011\nmsgid \"Talk to Pepin\"\nmsgstr \"ペピン​と​話す\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave Healer's home\"\nmsgstr \"治療​師​の​家​を​去る\"\n\n#: Source/stores.cpp:1049\nmsgid \"The Town Elder\"\nmsgstr \"町​の​語り部\"\n\n#: Source/stores.cpp:1051\nmsgid \"Talk to Cain\"\nmsgstr \"ケイン​と​話す\"\n\n#: Source/stores.cpp:1052\nmsgid \"Identify an item\"\nmsgstr \"鑑定​し​て​もらう\"\n\n#: Source/stores.cpp:1145\nmsgid \"You have nothing to identify.\"\nmsgstr \"何​も​鑑定​する​もの​は​無い​よう​だ​が。\"\n\n#: Source/stores.cpp:1156\nmsgid \"Identify which item?\"\nmsgstr \"何​を​鑑定​する​の​か​ね​?\"\n\n#: Source/stores.cpp:1171\nmsgid \"This item is:\"\nmsgstr \"何​を​する​?\"\n\n#: Source/stores.cpp:1174\nmsgid \"Done\"\nmsgstr \"終わる\"\n\n#: Source/stores.cpp:1183\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"{:s}​と​話す\"\n\n#: Source/stores.cpp:1186\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"{:s}​と​話し​て​いる\"\n\n#: Source/stores.cpp:1187\nmsgid \"is not available\"\nmsgstr \"使用​不能\"\n\n#: Source/stores.cpp:1188\nmsgid \"in the shareware\"\nmsgstr \"シェアウェア​で\"\n\n#: Source/stores.cpp:1189\nmsgid \"version\"\nmsgstr \"バージョン\"\n\n#: Source/stores.cpp:1216\nmsgid \"Gossip\"\nmsgstr \"噂話\"\n\n#: Source/stores.cpp:1225\nmsgid \"Rising Sun\"\nmsgstr \"日の出​亭\"\n\n#: Source/stores.cpp:1227\nmsgid \"Talk to Ogden\"\nmsgstr \"オグデン​と​話す\"\n\n#: Source/stores.cpp:1228\nmsgid \"Leave the tavern\"\nmsgstr \"宿屋​を​去る\"\n\n#: Source/stores.cpp:1239\nmsgid \"Talk to Gillian\"\nmsgstr \"ジリアン​と​話す\"\n\n#: Source/stores.cpp:1240\nmsgid \"Access Storage\"\nmsgstr \"スレレージ​に​アクセス\"\n\n#: Source/stores.cpp:1250\nmsgid \"Farnham the Drunk\"\nmsgstr \"よっぱらい​の​ファーンハム\"\n\n#: Source/stores.cpp:1252\nmsgid \"Talk to Farnham\"\nmsgstr \"ファーンハム​と​話す\"\n\n#: Source/stores.cpp:1253\nmsgid \"Say Goodbye\"\nmsgstr \"立ち去る\"\n\n#: Source/stores.cpp:2373\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"所持金: {:s}\"\n\n#: Source/tables/monstdat.cpp:331 Source/tables/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"モンスター​データ​の​読み込み​に​失敗​し​まし​た\"\n\n#: Source/tables/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\"最大​モンスター​種類​数 {} に​達し​て​いる​ため、モンスター​を​追加​でき​ませ​ん​でし​た。\"\n\n#: Source/tables/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"ID ”​{}​” の​モンスター​タイプ​は​すでに​存在​し​ます。\"\n\n#: Source/tables/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"クラス​データ​の​読み込み​に​失敗​し​まし​た\"\n\n#: Source/tables/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"最大​クラス​数 {} に​達し​て​いる​ため、クラス​を​追加​でき​ませ​ん​でし​た。\"\n\n#: Source/tables/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"テキストデータ​の​読み込み​に​失敗​し​まし​た\"\n\n#: Source/tables/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"ID “​{}​” の​テキストデータ​は​すでに​存在​し​ます。\"\n\n#: Source/towners.cpp:200\nmsgid \"Slain Townsman\"\nmsgstr \"住人​の​遺体\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"ウォー​リアー\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"ローグ\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"ソーサラー\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"モンク\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"バード\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"バーバリアン\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"ゾンビ\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"グール\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"ロッティング​・​カーカス\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"ブラックデス\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"フォールンワン\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"カーバ\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"デビルキン\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"ダークワン\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"スケルトン\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"コープス​・​アックス\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"バーニング​デッド\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"ホラー\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"スカベンジャー\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"プレイグイーター\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"シャドウ​ビースト\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"ボーンガッシャー\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"コープス​・​ボウ\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"スケルトン​・​キャプテン\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"コープス​・​キャプテン\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"バーニング​デッド​・​キャプテン\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"ホラー​・​キャプテン\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"インビジブル​・​ロード\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"ヒドゥン\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"ストーカー\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"アンシーン\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"イリュージョン​・​ウィーバー\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"サティアル​・​ロード\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"フレッシュ​クラン\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"ストーン​クラン\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"ファイヤー​クラン\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"ナイト​クラン\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"フィーンド\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"ブリンク\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"グルーム\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"ファミリアー\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"アシッド​ビースト\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"ポイゾンスピッター\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"ピット​ビースト\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"ラバ​・​マウ\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"スケルトン​キング\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"ブッチャー\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"オーバーロード\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"マッドマン\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"トードデーモン\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"フレイドワン\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"ウィルム\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"ケイブ​スラッグ\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"デビルウィルム\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"ディバウアー\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"マグマ​デーモン\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"ブラッド​ストーン\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"ヘルス​トーン\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"ラバ​・​ロード\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"ホーンドデーモン\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"マッド​ランナー\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"フロスト​チャージャー\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"オブシディアンロード\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"オールド​ボンド\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"レッドデス\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"リッチ​デーモン\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"アンデッド​・​バルログ\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"インシネレーター\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"フレイム​ロード\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"ドゥーム​ファイヤー\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"ヘルバーナー\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"レッド​ストーム\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"ストーム​ライダー\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"ストーム​・​ロード\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"メイルシュトロム\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"デビルキン​・​ブルート\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"ウィングド​・​デーモン\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"ガーゴイル\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"ブラッド​クロウ\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"デスウィング\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"スレイヤー\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"ガーディアン\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"ボルテックス​・​ロード\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"バルログ\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"ケイブ​・​バイパー\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"ファイヤー​・​ドレイク\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"ゴールド​・​バイパー\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"アジャー​・​ドレイク\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"ブラック​ナイト\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"ドゥーム​ガード\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"スチール​ロード\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"ブラッド​ナイト\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"ザ​・​シュレッド\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"ホロウワン\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"ペイン​マスター\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"リアリティ​・​ウィーバー\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"サキュバス\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"スノウ​・​ウィッチ\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"ヘルス​ポーン\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"ソウル​バーナー\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"カウンセラー\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"マジストレイト\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"カバリスト\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"アドボケイト\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"ゴーレム\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"ザ​・​ダーク​ロード\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"ジ​・​アーク​リッチ​・​メリグヌス\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"弱虫​ガーバッド\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"狂人​ザール\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"スノッツピル\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"大司教​ラザルス\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"レッドヴェックス\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"ブラック​・​ジェイド\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"ラック​ダナン\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"鮮血​の​将軍\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"ホーク​・​デーモン\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"デファイラー\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"ナ​・​クルル\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"ボーン​ヘッド​・​キーン​アックス\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"ブレード​スキン​・​ザ​・​スラッシャー\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"ソウルパス\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"ピュー​クラット​・​ジ​・​アンクリーン\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"ボーン​リッパー\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"ロットフィースト​・​ザ​・​ハングリー\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"ガット​シャンク​・​ザ​・​クイック\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"ブロークン​ヘッド​・​バンシールド\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"ボンゴ\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"ロットカルネージ\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"シャドー​バイト\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"デッドアイ\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"マッドアイ​・​ザ​・​デッド\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"エル​・​チュパ​カブラ\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"スカル​ファイヤー\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"ワープ​スカル\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"ゴアータン\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"パルスクロウラー\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"ムーン​ベンダー\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"ラスレイブン\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"スパイン​イーター\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"ブラッカス​・​ザ​・​バーニング\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"シャドウ​クロウ\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"ブライト​ストーン​・​ザ​・​ウィーク\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"ビルフロス​・​ザ​・​ピット​マスター\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"ブラッド​スキン​・​ダークボウ\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"ファウル​ウィング\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"シャドウ​・​ドリンカー\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"ヘイズ​シフター\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"デススピット\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"ブラッドガッター\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"デスシェイド​・​フレッシュ​モール\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"ウォーマガット​・​ザ​・​マッド\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"グラス​スカル​・​ザ​・​ジャギッド\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"ブライト​ファイヤー\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"ナイト​ウィング​・​ザ​・​コールド\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"ゴアストーン\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"ブロンズ​フィスト​・​ファイヤー​ストーン\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"ラスファイヤー​・​ザ​・​ドゥームド\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"ファイヤーウーンド​・​ザ​・​グリム\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"バロン​・​スラッジ\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"ブライト​ホーン​・​スチール​メイス\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"カオス​ハウラー\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"ドゥーム​グリン​・​ザ​・​ロッティング\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"マッド​バーナー\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"ボーンソウ​・​ザ​・​リッチ\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"ブレイク​スパイン\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"デビル​スカル​・​シェイプ​ボーン\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"ブロークン​ストーム\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"ストーム​ベイン\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"ウーズ​ドロール\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"ゴールド​ブライト​・​オブ​・​ザ​・​フレイム\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"ブラック​ストーム\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"プレイ​グラス\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"ザ​・​フレイヤー\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"ブルー​ホーン\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"ワープ​ファイヤ​・​ヘルス​ポーン\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"ファング​スピア\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"フェスタースカル\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"ライオン​スカル​・​ザ​・​ベント\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"ブラックタン\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"ヴァイル​タッチ\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"バイパー​フレーム\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"ファング​スキン\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"ウィッチ​ファイヤー​・​ジ​・​アンホーリー\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"ブラック​スカル\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"ソウル​スラッシュ\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"ウインド​スポーン\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"ロード​・​オブ​・​ザ​・​ピット\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"ラスト​ウィーバー\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"ハウリング​・​ザ​・​シェイド\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"ドゥーム​クラウド\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"ブラッド​ムーン​・​ソウル​ファイヤー\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"ウィッチ​ムーン\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"ゴアーフィースト\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"グレイ​ウォー​・​ザ​・​スレイヤー\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"ドレッド​ジャッジ\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"スターアイ​・​ザ​・​ウィッチ\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"スチール​スカル​・​ザ​・​ハンター\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"サー​・​ゴラッシュ\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"ザ​・​ヴァイザー\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"ザンピール\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"ブラッド​ラスト\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"ウェブ​・​ウィドウ\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"フレッシュ​ダンサー\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"グリム​スパイク\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"ドゥーム​ロック\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"ショート​ソード\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"バックラー\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"クラブ\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"ショートボウ\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"ショート​スタッフ​・​オブ​・​マナ\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"クリーバー\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"アンデッド​・​クラウン\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"エンペリアン​・​バンド\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"天界​の​石\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"オプティック​・​アミュレット\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"リング​・​オブ​・​トゥルース\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"宿屋​の​看板\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"ハーレクイン​・​クレスト\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"ベイル​・​オブ​・​スチール\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"ゴールデン​・​エリクサー\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"憤激​の​鉄床\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"黒い​キノコ\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"脳味噌\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"菌類​に​関する​研究\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"スペクトラルエリクサー\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"ブラッド​ストーン\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"大聖堂​の​マップ\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"Ear\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"ヒーリング​・​ポーション\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"マナ​・​ポーション\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"鑑定​の​スクロール\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"タウン​ポータル​・​スクロール\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"アルケイン​の​鎧​・​ヴァロー\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"フルヒーリング​・​ポーション\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"フルマナ​・​ポーション\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"グリズウォルド​の​剣\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"ウシ​の​プレート\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"ラザルス​の​杖\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"リザレクション​・​スクロール\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"ショート​スタッフ\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"ソード\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"ダガー\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"ルーン​爆弾\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"テオドア\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"オーリック​・​アミュレット\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"トーン​・​ノート​1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"トーン​・​ノート​2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"トーン​・​ノート​3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"復元​さ​れ​た​ノート\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"ブラウン​・​スーツ\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"グレイ​・​スーツ\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"キャップ\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"スカル​キャップ\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"ヘルム\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"フルヘルム\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"クラウン\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"グレートヘルム\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"ケープ\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"ラグ\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"クローク\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"ローブ\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"キルテッドアーマー\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"レザー​アーマー\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"ハード​レザー​アーマー\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"スタデッドレザーアーマー\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"リング​メイル\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"メイル\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"チェイン​メイル\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"スケイルメイル\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"ブレスト​プレート\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"プレート\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"スプリント​メイル\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"プレート​メイル\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"フィールド​プレート\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"ゴシック​プレート\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"フルプレートメイル\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"シールド\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"スモール​シールド\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"ラージ​シールド\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"カイト​シールド\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"タワー​シールド\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"ゴシック​シールド\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"回復​ポーション\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"フル​回復​ポーション\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"オイル\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"STR の​エリクサー\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"MAG の​エリクサー\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"DEX の​エリクサー\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"VIT の​エリクサー\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"ヒーリング​・​スクロール\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"サーチ​・​スクロール\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"ライトニング​・​スクロール\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"ファイヤー​ウォール​・​スクロール\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"インフェルノ​・​スクロール\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"フラッシュ​・​スクロール\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"インフラ​ビジョン​・​スクロール\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"フェイジング​・​スクロール\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"マナシールド​・​スクロール\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"フレイム​ウェーブ​・​スクロール\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"ファイヤー​ボール​・​スクロール\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"ストーン​カース​・​スクロール\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"チェイン​ライトニング​・​スクロール\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"ガーディアン​・​スクロール\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"ノヴァ​・​スクロール\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"ゴーレム​・​スクロール\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"テレポート​・​スクロール\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"アポカリプス​・​スクロール\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"ファルシオン\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"シミター\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"クレイモア\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"ブレード\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"サーベル\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"ロング​ソード\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"ブロード​ソード\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"バスタード​ソード\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"ツーハンデッドソード\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"グレート​ソード\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"スモール​アックス\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"アックス\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"ラージ​アックス\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"ブロード​アックス\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"バトル​アックス\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"グレート​アックス\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"メイス\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"モーニングスター\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"ウォー​ハンマー\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"ハンマー\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"スパイクドクラブ\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"フレイル\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"モール\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"ボウ\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"ハンターズボウ\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"ロングボウ\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"コンポジットボウ\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"ショートバトルボウ\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"ロングバトルボウ\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"ショートウォーボウ\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"ロングウォーボウ\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"ロング​スタッフ\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"コンポジット​スタッフ\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"クォーター​スタッフ\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"ウォー​スタッフ\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"リング\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"アミュレット\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"ルーン​・​オブ​・​ファイヤー\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"ルーン\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"ルーン​・​オブ​・​ライトニング\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"グレーター​・​ルーン​・​オブ​・​ファイヤー\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"グレーター​・​ルーン​・​オブ​・​ライトニング\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"ルーン​・​オブ​・​ストーン\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"ショート​スタッフ​・​オブ​・​チャージド​ボルト\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"アリーナ​ポーション\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"ブッチャーズ​・​クリーバー\"\n\n#: Source/translation_dummy.cpp:370\nmsgid \"Lightforge\"\nmsgstr \"ライトフォージ\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"ザ​・​リフトボウ\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"ザ​・​ニードラー\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"ザ​・​セレスティアル​・​ボウ\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"デッドリー​ハンター\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"ボウ​・​オブ​・​ザ​・​デッド\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"ザ​・​ブラックオークボウ\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"フレイムダート\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"フレッシュ​スティンガー\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"ウインド​フォース\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"イーグル​ホーン\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"ゴナーガルズ​・​ダーク\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"ザ​・​ディフェンダー\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"グリフォン​の​爪\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"ブラック​・​レイザー\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"ギバス​・​ムーン\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"アイス​シャンク\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"ジ​・​エクスキュージョナーズ​・​ブレード\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"ザ​・​ボーンソウ\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"シャドウ​ホーク\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"ウィザード​スパイク\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"ライト​サーベル\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"ザ​・​ファルコンズ​・​タロン\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"インフェルノ\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"ドゥームブリンガー\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"ザ​・​グリズリー\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"ザ​・​グランドファーザー\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"ザ​・​マングラー\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"シャープ​ビーク\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"ブラッドスレイヤー\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"セレスティアル​・​アックス\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"ウィキッドアックス\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"ストーンクリーバー\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"アグイナラズ​・​ハチェット\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"ヘルス​レイヤー\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"メッサーシュミッツ​・​リーバー\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"クラック​ラスト\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"ハンマー​・​オブ​・​ギョーム\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"シバーブス​・​カッジェル\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"ザ​・​セレスティアル​・​スター\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"バルナーズ​・​スター\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"ナールド​・​ルート\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"ザ​・​クラニュウム​・​バッシャー\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"シャイファーズ​・​ハンマー\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"ドリームフランジュ\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"スタッフ​・​オブ​・​シャドウズ\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"イモレイター\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"ストーム​・​スパイア\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"グリーム​ソング\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"サンダー​コール\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"ザ​・​プロテクター\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"ナジズ​・​パズラー\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"マインド​クライ\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"ロッド​・​オブ​・​オーナン\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"ヘルム​・​オブ​・​スピリッツ\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"シンキング​キャップ\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"オーバーローズヘルム\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"食料\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"ゴッタダマルング\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"ロイヤル​クレスト\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"トーン​フレッシュ​・​オブ​・​ソウル\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"ザ​・​グラディエーターズ​・​ベイン\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"ザ​・​レインボウ​・​クローク\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"レザー​・​オブ​・​オータ\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"ウィズダムズ​・​ラップ\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"スパーキング​・​メイル\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"スカベンジャー​・​カラペイス\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"ナイト​スケープ\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"ナジズ​・​ライト​プレート\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"デーモン​スパイク​コート\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"ディフ​レクター\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"スピリット​・​スカル​・​シールド\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"ドラゴンズ​・​ブリーチ\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"ブラック​オーク​・​シールド\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"ホーリー​ディフェンダー\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"ストーム​・​シールド\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"ブランブル\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"リング​・​オブ​・​レガー\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"ザ​・​ブリーダー\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"コンストリクティング​・​リング\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"リング​・​オブ​・​エンゲージメント\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"ティン\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"ブラス\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"ブロンズ\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"アイアン\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"スチール\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"シルバー\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"プラチナ\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"ミスリル\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"メテオ​リック\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"ストレンジ\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"ユースレス\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"ベント\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"ウィーク\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"ジャギッド\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"デッドリー\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"ヘビー\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"ヴィシャス\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"ブルータル\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"マッシブ\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"サベッジ\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"ルースレス\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"マーシレス\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"クラムジィ\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"ダル\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"シャープ\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"ファイン\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"ウォーリアーズ\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"ソルジャーズ\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"ローズ\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"ナイツ\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"マスターズ\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"チャンピオンズ\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"キングス\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"バルネラブル\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"ラステッド\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"ストロング\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"グランド\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"バリアント\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"グロー​リアス\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"ブレスド\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"セイントリィ\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"オウサム\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"ゴッドリィ\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"レッド\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"クリムゾン\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"ガーネット\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"ルビー\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"ブルー\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"アジャー\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"ラピス\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"コバルト\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"サファイア\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"ホワイト\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"パール\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"アイボリー\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"クリスタル\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"ダイアモンド\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"トパーズ\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"アンバー\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"ジェイド\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"オブシディアン\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"エメラルド\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"ハイエナズ\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"フロッグス\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"スパイダーズ\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"レイブンズ\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"スネークス\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"サーペンツ\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"ドレイクス\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"ドラゴンズ\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"ワームズ\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"ヒドラズ\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"エンジェルズ\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"アーク​エンジェルズ\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"プレンティフル\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"バウンティフル\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"フレイミング\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"ライトニング\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"クオリティ\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"メイミング\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"スレイング\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"ゴア\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"カルネージ\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"スローター\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"ペイン\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"ティアーズ\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"ヘルス\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"プロテクション\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"アブソープション\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"ディフレクション\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"アズモシス\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"フレイリティ\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"ウィークネス\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"ストレングス\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"マイト\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"パワー\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"ジャイアント\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"タイタン\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"パラリシス\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"アトロフィ\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"デクスタリティー\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"スキル\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"アキュラシー\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"プリシジョン\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"パーフェクション\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"ザ​・​フール\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"ディスレクシア\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"マジック\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"ザ​・​マインド\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"ブリリアンス\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"ソーサリー\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"ウィザードリー\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"イルネス\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"ディジーズ\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"バイタリティ\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"ゼスト\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"ヴィム\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"ビガー\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"ライフ\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"ザ​・​トラブル\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"ザ​・​ピット\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"ザ​・​スカイ\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"ザ​・​ムーン\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"ザ​・​スター\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"ザ​・​ヘイブン\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"ザ​・​ゾディアック\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"ザ​・​ヴァル​チャー\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"ザ​・​ジャッカル\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"ザ​・​フォックス\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"ザ​・​ジャガー\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"ザ​・​イーグル\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"ザ​・​ウルフ\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"ザ​・​タイガー\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"ザ​・​ライオン\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"ザ​・​マンモス\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"ザ​・​ホエール\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"フラジリティ\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"ブリトレネス\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"スタディネス\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"クラフトマンシップ\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"ストラクチャー\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"ザ​・​エイジス\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"ザ​・​ダーク\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"ザ​・​ナイト\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"ライト\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"ラディアンス\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"フレイム\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"ファイヤー\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"バーニング\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"ショック\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"ライトニング\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"サンダー\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"メニー\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"プレンティ\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"ソーン\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"コラプション\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"シーブス\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"ザ​・​ベアー\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"ザ​・​バット\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"バンパイア\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"ザ​・​リーチ\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"ブラッド\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"ピアシング\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"パンクチュアリング\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"バッシング\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"レディニス\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"スイフトネス\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"スピード\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"ヘイスト\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"バランス\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"スタビリティ\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"ハーモニー\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"ブロッキング\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"天界​の​石\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"弱虫​ガーバッド\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"狂人​ザール\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"ラック​ダナン\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"ブッチャー\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"オグデン​の​看板\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"盲目​の​広間\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"ヴァロー\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"鮮血​の​将軍\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"レオリック​王​の​呪い\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"大司教​ラザルス\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"墓​の​問題\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"ファーマーズ​・​オーチャード\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"小さな​女の子\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"ワンダリング​・​トレーダー\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"デファイラー\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"ナ​・​クルル\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"ジャージ​の​ジャージ\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"ファイヤー​ボルト\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"ヒーリング\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"ライトニング\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"フラッシュ\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"鑑定\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"ファイヤー​ウォール\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"タウン​ポータル\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"ストーン​カース\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"インフラ​ビジョン\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"フェイジング\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"マナシールド\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"ファイヤー​ボール\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"ガーディアン\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"チェイン​ライトニング\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"フレイム​ウェーブ\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"ドゥーム​サーペント\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"ブラッド​リチュアル\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"ノヴァ\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"インビジビリティ\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"インフェルノ\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"ゴーレム\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"レイジ\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"テレポート\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"アポカリプス\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"エーテリアライズ\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"アイテム​の​修理\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"スタッフ​の​リチャージ\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"トラップ​の​解除\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"エレメンタル\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"チャージド​ボルト\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"ホーリー​ボルト\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"リザレクション\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"テレキネシス\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"ヒール​アザー\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"ブラッド​スター\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"ボーン​スピリット\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" おお、王​の​物語​か。レオリック​王​の​堕落​は​土地​の​者​に​は​大いなる​悲劇​じゃっ​た。王​を​\"\n\"敬愛​し​て​き​た​人々​も、今​は​王​の​殺戮​に​おびえる​日々。誰​より​も​高潔​で​あっ​た​あの​レオ\"\n\"リック​王​が、どう​し​て​光​の​世界​から​はずれ​て​しまっ​た​の​か​不思議​で​なら​ぬ。あの​方​の​\"\n\"精神​を​あそこ​まで​破壊​する​と​は、地獄​で​も​最強​の​力​に​違い​ない。\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"この​町​を​救える​の​は​あなた​だけ​です。数カ月​前、アルブレヒト​王子​が​誘拐​さ​れ​て​か\"\n\"ら、レオリック​王​は​狂い​始め​まし​た。王​は、罪​も​ない​人々​を​拷問​し、次々​に​処刑​し​た​\"\n\"ため、町​の​人​は​半分​も​残っ​て​い​ませ​ん。王​に​仕える​騎士​や​司祭​は、見る​に​見​かね​て、\"\n\"とうとう​王​を​殺し​て​しまい​まし​た。息​を​引き取る​前​に、王​は​呪い​の​言葉​を​吐き​まし​\"\n\"た。\\n\"\n\"\\n\"\n\"​家来​達​が​闇​の​世界​に​堕ち​て、永遠​に​彼​に​仕える​と​いう​もの​です。それ​から、想像​を​絶\"\n\"する​よう​な​恐ろしい​できごと​が​おき​まし​た。王​は​蘇り、迷宮​の​死体​を​操る​よう​に​なっ​\"\n\"た​の​です。王​の​遺体​は​修道院​の​地下墓地​の​第​三階層​に​埋葬​さ​れ​て​い​ます。どう​か、王​\"\n\"の​姿​を​し​た​おぞましい​怪物​を​倒し、王​の​魂​を​安らか​に​眠ら​せ​て​あげ​て​ください。\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"前​に​お​話し​し​た​よう​に、王​は​地下​第​三階層​に​い​ます。腐っ​た​闇​の​中​で、この​地​を​滅ぼ\"\n\"す​機会​を​狙っ​て​いる​の​です。\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"レオリック​王​の​呪い​は​解け​まし​た​が、もっと​恐ろしい​悪​が​背後​に​いる​よう​な​気​が​し​ま\"\n\"す。で​も、あなた​の​勝利​は​縁起​が​いい。この​地​を​闇​から​守れる​か​も​しれ​ませ​ん。光​の​\"\n\"お​導き​が​あり​ます​よう​に。\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"レオリック​王​は、息子​の​死​に​耐え​られ​なかっ​た。私​も​王​の​狂気​が​癒さ​れる​よう​努力​し​\"\n\"た​が、とうとう​王​は​狂気​に​負け​て​しまっ​た。その​日​から、この​王国​に​暗黒​の​呪い​が​か\"\n\"かっ​た​の​だ。君​が​王​の​魂​を​肉体​の​牢獄​から​解放​する​こと​が​できれ​ば、その​呪い​は​解か​\"\n\"れる​ん​だ​よ​…\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"王様​は​むごい​最期​でし​た​わ。本当​に​心​優しい、公正​な​方​でし​た。王​様​の​死​は、悲しい​\"\n\"し、何​だ​か​納得​でき​ない​わ。\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"レオリック​王​に​仕える​騎士​の​ため​に​武器​や​鎧​を​山ほど​作っ​た。王​に​は、巨大​な​両手​持\"\n\"ち​の​剣​と、おそろい​の​兜​も​お​作り​し​た​ほど​だ。しかし​何​と​いう​無残​な​死に様。王​が​\"\n\"狂っ​た​の​は、何​か​不吉​な​力​に​とりつか​れ​た​から​に​違い​ない。\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"知っ​た​こっ​ちゃ​ねえ​って​ん​だ。よく​聞けよ、がい骨​なんて​俺​の​王様​じゃぁ​ねぇ​ん​だ。\"\n\"そう​だろう​! レオリック​様​こそ​が​俺​の​王様​だ。分かっ​た​か​ぃ。王​様​バンザ​～​イ​!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"生け​る​屍​は、忌まわしい​王​の​忠実​なる​僕。王​は​次々​と​戦士​を​蘇ら​せ、死​の​軍団​を​増強​\"\n\"する​だろう。やつ​の​支配​に​終止符​を​打た​ね​ば、この​地​に​生きる​者​は​皆殺し​に​さ​れ​て​し\"\n\"まう​ぞ。\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"俺​は​まとも​な​商売​し​てる​ん​だ。情報​なんて​売っ​て​ねえ​よ。とっく​の​昔​に​死ん​じまっ​た​\"\n\"王​様​なんて​興味​ねえ​し​な。だ​が、その​死​に​損ない​を​やっつける​武器​が​欲しい​って​言う​\"\n\"なら​相談​に​のる​ぜ。\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"我が​墓所​に、生暖かい​生命​が​吹き込ま​れ​た。覚悟​せよ、永遠​の​支配者​に​仕える​の​だ​!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"全く​おかしな​こと​を​する​もの​じゃ。お主​も​悩ん​どる​な。魔物​ども​は​日​の​光​に​は​大いな\"\n\"る​力​が​秘め​られ​て​いる​と​信じ、恐れ​て​おる​の​じゃ。おそらく、お主​の​言う​看板​に​描か​\"\n\"れ​て​あっ​た​日の出​に、神秘​の​力​が​宿っ​て​おる​と​で​も​思っ​た​ん​じゃろう。し​て​みる​と、\"\n\"きゃつ​ら​は​人間​が​恐れる​ほど​賢く​は​ない​よう​じゃ​な。\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"実​は、奇妙​な​こと​が​あり​まし​て。あなた​は、迷宮​に​棲む​怪物​ども​に​つい​て​は​よく​御存\"\n\"知​でしょう​から、私​に​は​見当​も​つか​ない​こと​も​わかる​か​も​しれ​ませ​ん。ある夜、外​で​\"\n\"なに​やら​引っかく​よう​な​音​が​する​の​で​見​ます​と、小さな​魔物​の​よう​な​もの​が​逃げ​て​い\"\n\"き​まし​た。そいつ​は、うち​の​看板​を​持ち去っ​た​の​です。なぜ、私達​に​手​を​出さ​ず​に、\"\n\"看板​だけ​盗ん​だ​の​か、何​か​変​じゃ​ない​です​か​?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"わざわざ​看板​を​取り返し​て​くれ​た​おかげ​で、新しい​の​を​買わ​ず​に​すみ​ます​よ。お礼​を​\"\n\"し​たい​が、何​が​いい​でしょう​か。そう​だ、この​帽子​が​いい。前​に​うち​に​泊っ​た​魔術師​\"\n\"が​置い​て​いっ​た​ん​です​よ。多分​何​か​の​お​役​に​立つ​と​思い​ます。\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"何​て​こと​だ、魔物​が​夜​の​町​を​駆けめぐっ​て​略奪​し​て​いる​ぞ。何​て​こと​だ、オグデン​と​\"\n\"ガーダ​は​無事​だろう​か。怪我​で​も​し​てれ​ば、私​の​所​へ​くる​だろう​が​…\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"まあ、看板​は​どこ​に​行っ​た​の​? お​ばあ​さま​も​私​も​眠っ​て​い​た​の​ね。宿屋​が​魔物​に​襲わ​\"\n\"れ​なく​て​よかっ​た​わ。\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"魔物​が​オグデン​の​看板​を​盗ん​だ​だ​と​? 生身​の​心臓​を​掴み取ら​れ​た​なら​わかる​が、看板​\"\n\"て​の​は​変​だ​な。\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"俺​が​思う​に​よぉ、あの​看板​を​盗ん​だ​の​は、きっと​金​目当て​だ​と​思う​ぜ、金​目当て​さ​! \"\n\"それ​より​も、俺​が​オグデン​だっ​たら​新しい​看板​を​買っ​ちまう​ねぇ。きれい​な​絵​を​描い​\"\n\"て​ある​やつ​を​よぉ。うん​うん、そう​だ​な、えー​とぉ、ビール​の​ジョッキ​と​か​チーズ​と​\"\n\"か​さ​…\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"人間​に​は、悪魔​の​考え​を​理解​する​こと​など​でき​ない。\\n\"\n\"\\n\"\n\"​連中​の​不可解​な​行動​に​惑わさ​れ​て​は​なら​ぬ。それ​こそ​が​連中​の​狙い​な​の​じゃ。\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"俺​が​何​を​盗ん​だ​って​? グリズウォルド​が​言っ​た​の​か​? \\n\"\n\"\\n\"\n\"​売りさばい​て​も​一​文​に​も​なりゃ​し​ない​そんな​看板、誰​が​盗む​もん​か。\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"おい​! みんな​を​殺し​た​奴​だ​な​! 魔力​の​紋章​を​持っ​て​こ​ない​と​命​は​ない​ぞ。でっかい​化\"\n\"物​を​ぶっ殺し​て​紋章​を​取り戻す​ん​だ。そいつ​は​角​を​曲がっ​た​扉​の​中​に​いる。奴​ら​を​\"\n\"ぶっ殺し​て​紋章​を​持っ​て​き​たら​通し​て​やる​!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"化物​を​ぶっ殺し​て​紋章​を​取り戻せ。さも​ない​と​…\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"よこせ​! やっ​た​ぜ​! 俺​たちゃ​強い​ん​だ。大いなる​魔法​で​ぶっ殺し​て​やる​! ヒャハハハ\"\n\"ハ​..\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"何​と​不吉​な。これ​ぞ​まさしく​わし​が​最も​恐れ​て​い​た​こと​じゃ。できれ​ば​古い​伝説​など​\"\n\"信じ​たく​なかっ​た​が、もう​それ​を​否定​する​わけ​に​は​いか​ぬ。そろそろ​正体​を​明かす​と\"\n\"き​が​来​た​よう​じゃ​な。\\n\"\n\"\\n\"\n\"​わし​の​真​の​名​は​デッカード​・​ケイン。永遠​の​悪​の​封印​を​守る​古き​結社​の​最後​の​末裔​\"\n\"じゃ。だ​が​どう​やら​その​封印​が​解か​れ​た​よう​じゃ。\\n\"\n\"\\n\"\n\"​かつて​助言者​と​し​て​レオリック​王​が​最も​信頼​し​た​大司教​ラザルス​は、行方​知れ​ず​に​\"\n\"なっ​た​アルブレヒト​王子​を​捜す​ため、町​の​人々​を​迷宮​へ​と​導い​て​いっ​た。しかし、迷\"\n\"宮​より​無事​戻っ​て​こ​られ​た​の​は、ほんの​数​名​…。\\n\"\n\"\\n\"\n\"​わし​が​愚か​じゃっ​た​! ラザルス​の​裏切り​に​気づい​て​おれ​ば​! アルブレヒト​王子​を​誘拐​\"\n\"し​迷宮​に​隠し​た​の​も、きっと​ラザルス​に​違い​ない。大司教​ほど​の​男​が​悪​に​屈する​と​\"\n\"は。やつ​は​きっと、王子​を​恐怖​の​帝王​に​捧げる​つもり​じゃろう。\\n\"\n\"\\n\"\n\"​生き​て​戻っ​た​者​の​話​で​は、ラザルス​は​迷宮​の​奥深く​へ​と​入っ​て​いっ​た​そう​だ。悪魔​の​\"\n\"生け贄​に​さ​れる​前​に、一刻​も​早く​王子​を​助け出す​の​じゃ​!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"急げ、ラザルス​の​手​から​アルブレヒト​王子​を​救い出せ​! 王子​も​民衆​も​お主​が​頼り​な​の​\"\n\"じゃ​!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"何​と​も​ぞっと​する​話​じゃ。ラザルス​は​恐ろしい​所業​の​報い​を​受け、地獄​の​業火​に​焼か​\"\n\"れ​た​の​じゃろう。お主​の​言う​その​少年​は​王子​で​は​ない、アルブレヒト​王子​は​まだ​囚わ\"\n\"れ​て​おる​に​違い​ない​ぞ。床​に​描か​れ​た​その​紋章​と​いう​の​は​きっと、迷宮​の​最​中心​部​へ​\"\n\"の​入口​に​違い​ない。\\n\"\n\"\\n\"\n\"​よい​か、お主​が​相手​に​する​の​は​恐怖​の​帝王​じゃ。人間界​で​は​ディアブロ​と​呼ば​れ​て​お\"\n\"る。こやつ​は​何​世紀​も​前​に​迷宮​に​幽閉​さ​れ​た​が、今​一度​人間界​に​混沌​の​渦​を​巻き起こ\"\n\"そう​としとる​よう​じゃ​な。手遅れ​に​なら​ぬ​うち​に​その​門​から​入り、ディアブロ​を​倒す​\"\n\"の​じゃ​!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"ラザルス​大司教​は​町​の​人々​を​迷宮​に​連れ込ん​だ​ん​です。あの​日、数多く​の​仲間​が​失わ​\"\n\"れ、ラザルス​様​も​二​度​と​は​戻り​ませ​ん​でし​た。きっと​殺さ​れ​て​しまっ​た​の​でしょう。\"\n\"それ​から、お願い​です。ファーンハム​に​は​あの​日​の​こと​を、聞か​ない​で​やっ​て​くださ\"\n\"い。\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"町​の​人々​が​あの​晩​に​やろう​と​し​て​い​た​こと​を​聞い​て、耳​を​疑っ​た​よ。より​に​よっ​て​あ\"\n\"の​ラザルス​が​あの​よう​な​ひどい​こと​を​する​と​は。あいつ​は​大司教​だ​し、いつも​トリス\"\n\"トラム​の​人々​の​世話​を​焼い​て​い​た​の​に。負傷者​が​あまり​に​多く​て、全員​は​助け​られ​な\"\n\"かっ​た​…\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"ラザルス​様​は​親切​で、慈悲​深い​方​でし​た​わ。母さん​の​葬式​も​執り行っ​て​くれ​て、心細\"\n\"く​なっ​て​い​た​私​と​お​ばあ​さま​の​支え​に​なっ​て​下さっ​た。毎晩​お​祈り​する​の​よ、ご​無事​\"\n\"です​よう​に​って。\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"魔物​へ​の​聖​なる​報復​と​称し​て、皆​を​迷宮​に​連れ​て​いっ​た​の​は​ラザルス​だっ​た。だ​が、\"\n\"いざ​魔物​ども​と​の​戦い​が​始まる​と、奴​は​その​メイス​を​振るう​こと​なく​さっさと​魔物​の​\"\n\"棲む​暗黒​の​奥深く​へ​と​姿​を​消し​ちまっ​た​ん​だ。\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"奴​等​は​武器​で​突っつき、噛みつい​て​そして​取り囲ん​だ​ん​だ。取り囲ん​だ。ウソつき、\"\n\"ウソつき​め​! みんな​死ん​だ​! 死ん​じまっ​た​ん​だ​! おい​聞い​てん​の​か​よ​! みんな​次々​に​\"\n\"やら​れ​ちまっ​て​… 床​が​血​で​染まっ​た​… あいつ​の​せい​で​よ​…\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"その​ラザルス​に​会っ​た​こと​は​ない​が、そ​やつ​の​内面​に​大いなる​葛藤​を​感じる​こと​が​で\"\n\"きる。気​を​付けろ、やつ​は​非常​に​危険​じゃ。闇​の​力​に​屈服​し​た​者​は、何​も​失う​もの​は​\"\n\"ない​の​だ​から​な。\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"お​偉い​ラザルス​様​は、怪物​ども​を​遠ざける​魔力​を​持っ​てる。だ​の​に、俺​の​足​を​守っ​\"\n\"ちゃ​くれ​なかっ​た。知り​たい​ん​なら​ファーンハム​に​聞い​て​み​な。奴​も​居合わせ​た​ん​だ​\"\n\"から​な。\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"くだら​ん​お​遊び​は​もう​やめろ。待ち受ける​の​は​我が​主​の​怒り​だ​! 王子​を​救う​に​は​遅​す\"\n\"ぎ​た。地獄​で​会せ​て​やろう。\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"ふうむ、わし​の​知っ​とる​こと​が​役​に​立つ​じゃろう​か​の。町​の​井戸水​は​地下​水脈​から​湧\"\n\"い​て​おる​の​じゃ。大きな​湖​に​通じる​トンネル​が​ある​と​いう​話​を​聞い​た​こと​が​ある​が、\"\n\"恐らく​この​こと​な​の​じゃろう。なぜ​水源​が​汚染​さ​れ​た​の​か​は、残念​じゃ​が​わし​に​も​わ\"\n\"から​ん。\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"ふうむ、わし​の​知っ​とる​こと​が​役​に​立つ​じゃろう​か​の。町​の​井戸水​は​地下​水脈​から​湧\"\n\"い​て​おる​の​じゃ。大きな​湖​に​通じる​トンネル​が​ある​と​いう​話​を​聞い​た​こと​が​ある​が、\"\n\"恐らく​この​こと​な​の​じゃろう。\\n\"\n\"\\n\"\n\"​なぜ​水源​が​汚染​さ​れ​た​の​か​は、残念​じゃ​が​わし​に​も​わから​ん。\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"君​が​い​て​くれ​て​よかっ​た​! 井戸​の​水​が​濁っ​て​き​て、それ​を​飲ん​だ​人々​が​病気​に​かかっ​\"\n\"て​いる​ん​だ。きれい​な​水​の​蓄え​は​なくなろう​と​し​て​いる。町​に​水​を​ひい​て​いる​泉​へ​通\"\n\"じる​道​が​あっ​た​はず​だ。この​災難​の​原因​を​究明​し​て​くれ。さも​なく​ば、我​ら​は​全滅​\"\n\"だ。\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"どう​か​急い​で​くれ。もう​すぐ​飲み水​が​底​を​つい​て​しまう。\\n\"\n\"\\n\"\n\"​君​の​助け​なく​て​は、我々​は​もう​これ​以上​生き延び​られ​ない。\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"何​と​? 魔物​の​存在​自体​が​水​を​汚し​て​い​た​だ​と​? この​町​の​地下​に​は​大いなる​邪悪​が​潜ん​\"\n\"で​いる​が、君​の​忍耐​と​勇気​に、我々​は​希望​を​抱い​て​いる。この​指輪​を​受け取っ​て​く\"\n\"れ。大いなる​悪​の​退治​に​役立つ​か​も​しれ​ない。\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"お​ばあ​さま​は​とても​体​が​弱い​の​に、井戸​の​水​は​飲め​ない​って​ガーダ​が​言う​の​よ。どう​\"\n\"か、助け​て​下さい。\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"ぺ​ピン​の​言う​通り、喉​から​手​が​出る​ほど​真水​が​欲しい​ん​だ。井戸​から​よどん​だ​水​が​し\"\n\"みだし​て​くる​の​は、水源​に​何​か​が​詰まっ​て​いる​から​だ。\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"おい、水​飲む​か​?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"お前​が​井戸​を​元​に​戻さ​ね​ば、トリストラム​の​人々​は​死に絶える​こと​に​なる​だろう。一​\"\n\"つ​教え​て​やる。原因​は​魔物​ども​に​ある​が、連中​は​その​こと​に​気づい​て​は​おら​ぬ​の​だ。\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"今度​ばかり​は、あんた​に​味方​する​よ。買い手​が​い​なきゃ、この​商売​も​あがったり​だ。\"\n\"いったい​何​が​あっ​た​の​か、すぐ​調べ​て​くれ。\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"「​人間​の​骨​を​収め​た​部屋​の​こと​が​書い​て​ある​本​」​か​… お​お​納骨堂​の​こと​なら、東方​の​\"\n\"図書館​で​読ん​だ​古い​書物​に​あっ​た。黄泉​の​国​の​王​が​莫大​な​財宝​を​守ろう​と​し​て、特別​\"\n\"な​場所​を​作っ​た​の​だ​そう​じゃ。「​財宝​を​盗み​に​来​た​者​は​命​を​落とし、永遠​に​その​宝​を​\"\n\"守り​続ける​」​と​記し​て​あっ​た。複雑​な​話​じゃ​が、妙​に​つじつま​が​合っ​て​いる​と​は​思わ​\"\n\"ん​か​?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"残念​ながら、私​に​は​分かり​ませ​ん。で​も​ケイン​の​持っ​てる​本​に​なら​のっ​て​いる​か​も​し\"\n\"れ​ませ​ん​な。\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"非常​に​危険​な​場所​の​よう​だ。行く​の​なら、充分​に​気​を​つけ​て​くれ。\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"見​た​こと​も​聞い​た​こと​も​ない​話​だ​が、この​町​の​語り部​の​ケイン​なら、それ​が​どこ​だ​か​\"\n\"分かる​か​も​しれ​ん。\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"わし​は​そんな​所​は​知ら​ん​が、ケイン​なら​物知り​だ​から、あんた​の​疑問​に​も​答え​られる​\"\n\"だろう。\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"へ​へ、よく​聞け​よ。木​の​部屋​が​あっ​て​だ​な、やつ​の​女房​が​木​が、どう​と​か​言っ​て​よ​… \"\n\"あ​そう​だ、ちょっと​待っ​て​くれ​や。やつ​の​ため​に​は​なら​ん​か​も​しれ​ん​が​金​は​…​払う​ぜ​… \"\n\"払う​とも​…\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"この​呪わ​れ​た​領域​で​命​を​落とし​た​が​最後、お前​は​永遠​に​闇​の​王​の​しもべ​と​なる​の​\"\n\"じゃ。\\n\"\n\"​納骨堂​に​入る​つもり​なら​ば、覚悟​し​なされ​よ。\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"莫大​な​お​宝​だ​って​? 分け前​は​もらえる​ん​だろう​な。それ​より​世​に​も​珍しい​ブツ​が​ある​\"\n\"ん​だ​けど、どう​だ​い​? これ​が​ありゃあ​鬼​に​金棒​だ​ぞ。\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"大司教​ラザルス​は​行方知れず​に​なっ​た​王​の​息子​を​捜す​と​偽り、大勢​迷宮​へ​と​差し向け​\"\n\"た​の​じゃ。人々​の​恐怖​に​つけ込み、彼​ら​を​凶暴​な​暴徒​と​し​て​しまい。地中​に​何​が​待ち\"\n\"受ける​の​か、知る​者​は​なかっ​た​…。ラザルス​は​皆​を​置き去り​に​し、いい知れ​ぬ​恐怖​の​中​\"\n\"で​人々​は​死ん​で​いっ​た​の​じゃ。\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"ええ、ファーンハム​は、たしか​ブッチャー​と​か​言う、恐ろしい​武器​を​振り回す、野蛮​\"\n\"な​大男​の​こと​を​ぶつぶつ​言っ​て​まし​た。\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"あの​堕落​し​た​悪魔​の​こと​は​知っ​て​いる​ぞ。ラザルス​の​罠​を​生き残っ​た​人々​が​修道院​か\"\n\"ら​這い出​て​き​た​時、多く​が​その​怒り​の​爪痕​を​負っ​て​い​た。やつ​が​犠牲者​を​切り裂く​の​\"\n\"に​何​を​使っ​た​か​は​分から​ない​が、この世​の​もの​で​は​ない​よ。傷口​は​ただれ、私​で​さえ​\"\n\"治療​でき​ない​ほど​ひどかっ​た。この​悪魔​と​戦う​の​なら、用心​し​て​くれ。\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"ブッチャー​が​人々​を​殺し​て​いる​って​ファーンハム​が​言っ​て​た​の、信じ​なかっ​た​けど、\"\n\"あなた​が​同じ​こと​を​言う​なら、本当​な​の​ね。\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"そいつ​を​ファーンハム​は​ブッチャー​と​呼ん​で​い​た​が、わし​の​仲間​を​巨大​な​肉​切り​包丁​\"\n\"で​皆殺し​に​し​おっ​た。わし​は​子鬼​ども​の​相手​を​し​て​い​て、助かっ​た​の​さ。地上​へ​続く​\"\n\"階段​を​見つけ、なん​と​か​無事​逃げ​おおせる​こと​が​でき​た​が、あの​けだもの​の​血​に​まみ\"\n\"れ​た​顔​は、いまだ​に​目​に​焼き付い​てる​よ。\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"そう​よ、バカ​でっけえ​包丁​で​友達​は​みんな​殺さ​れ​た​ぃ。逃げ回る​だけ​で、助け​られ​な\"\n\"かっ​た​ん​だ。閉じ込め​られ​た​部屋​は​な、死体​の​山​だっ​た​…​友達​の​な​… くそ​ぉ​ぉ​ぉ​!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"ブッチャー​は​人々​に​苦悩​と​苦痛​を​与える​こと​に​喜び​を​見いだす、残虐​な​怪物​じゃ。\"\n\"酔っ払い​の​ファーンハム​を​見れ​ば​分かる​で​あろう。ブッチャー​を​倒せ​ば、この​町​の​平\"\n\"和​を​多少​は​取り戻せる​の​だ。\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"あの​悪魔​に​つい​ちゃ、俺​は​知り​すぎる​ほど​知っ​てる。俺​の​足​を​もぎとっ​た​の​は、あい\"\n\"つ​の​仲間​な​ん​だ。グリズウォルド​が​広間​から​救い出し​て​くれ​た​ん​だ​けど​な。\\n\"\n\"\\n\"\n\"​はっきり​言おう。やつ​を​殺さ​なけれ​ば、お前​が​やら​れる​ぞ。\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"聞い​て​くれ。大司教​ラザルス​は、王子​を​探す​と​言っ​て​我々​を​連れ込ん​だ。しかし、罠​\"\n\"だっ​た​ん​だ​! みんな​死ん​で​しまっ​た。ブッチャー​と​いう​化物​に​殺さ​れ​た​ん​だ。か​たき​\"\n\"を​うっ​て​くれ​! 我々​の​魂​が​安らか​に​眠れる​よう、ブッチャー​を​殺し​て​くれ。\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"お主、面白い​詩​を​読む​の​お。それ​に​似​た​詩​を​思い出し​た​よ。…​はて、どんな​詩​じゃっ​た​\"\n\"か​のう。\\n\"\n\"\\n\"\n\"​…​「​秘密​を​覆い隠す。その​目​の​輝き​は​見え​ず、ただ​鋭い​爪​の​立てる​音​のみ​が、永遠​に​見\"\n\"る​こと​の​でき​ぬ​哀れ​な​者​を​苦しめる。永遠​の​断罪​を​受け​た​者​の​牢獄、その​名​を​「​盲目​\"\n\"の​広間​」​と​いう​」\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"お主、面白い​詩​を​読む​の​お。それ​に​似​た​詩​を​思い出し​た​よ。…​はて、どんな​詩​じゃっ​た​\"\n\"か​のう。…​「​秘密​を​覆い隠す。その​目​の​輝き​は​見え​ず、ただ​鋭い​爪​の​立てる​音​のみ​が、\"\n\"永遠​に​見る​こと​の​でき​ぬ​哀れ​な​者​を​苦しめる。永遠​の​断罪​を​受け​た​者​の​牢獄、その​名​\"\n\"を​「​盲目​の​広間​」​と​いう​」\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"これ​は​どこ​か​見覚え​が​ある​ぞ。悪魔​の​苦悩​の​歴史​に​つい​て​調べ​て​いる​とき​に、その​詩​\"\n\"に​よく​似​た​の​を​見かけ​た​よう​な​気​が​する​な。内容​は​…​確か​邪悪​に​満ち​た​場所​… 待て、ま\"\n\"さか​行く​気​な​の​か​?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"目​が​見え​ない​こと​に​つい​て​知り​たい​なら、ペピン​に​聞く​の​ね。彼​の​薬​で​お​ばあ​さま​の​\"\n\"眼​が​見える​よう​に​なっ​た​の。きっと​助け​て​くれる​わ。\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"見​た​こと​も​聞い​た​こと​も​ない​話​だ​が、この​町​の​語り部​の​ケイン​なら、それ​が​どこ​だ​か​\"\n\"分かる​か​も​しれ​ん。\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\"見ろ​よ。ハハハ、笑える​だろ​? お前​さん​にゃ、どう​だ​い​?​見える​の​か​い​?​ヒャー​ハハハ\"\n\"ハ​…\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"この​場所​に​は、その​主人​の​思う​が​まま​の​苦悩​と​恐怖​が​蔓延​し​て​おる。\\n\"\n\"\\n\"\n\"​用心​し​て​足​を​踏み入れ​なけれ​ば、思いの外、永く​留まる​こと​に​なろう​ぞ。\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"おっと、俺​は​あんた​に​売る​もの​は​ない​し、あんた​も​俺​の​話​に​金​を​払う​つもり​は​ない​ん​\"\n\"だろ。じゃあ、この​手​の​話​で​飯​を​食っ​てる​奴​は​だれ​だ​? 語り部​に​会い​に​行け​よ。\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"お主、ラック​ダナン​と​話し​た​と​いう​の​か。ラック​ダナン​は​偉大​な​英雄​じゃっ​た。何​年​\"\n\"も​の​間、王​に​忠誠​を​尽くし​た​と​いう​こと​は、お主​も​先刻​承知​じゃろう。\\n\"\n\"\\n\"\n\"​少なから​ぬ​者​達​が​王​に​呪い​を​かけ​られ​た​が、あの​男​なら、闘い​も​せ​ず​暗黒​面​に​降伏​す\"\n\"る​こと​は​ある​まい。お主​の​話​は​本当​じゃろう​な。わし​が​お主​の​立場​に​あれ​ば、地獄​の​\"\n\"責め苦​から​解き放っ​て​やる​道​を​探し​て​やる​ところ​じゃ。\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"大昔​に​死ん​だ​勇者​と​口​を​きい​た​なんて​話、うち​の​庭先​で​し​ない​で​ください​!\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"ゴールデン​・​エリクサー​って​言っ​た​の​か​い​? 私​は​そんな​色​の​薬​を​調合​し​た​こと​が​ない​\"\n\"から、飲ん​だら​どう​なる​か​は​分から​ぬ​な。だ​が​治療​師​と​し​て​の​私​の​忠告​は、その​よう​\"\n\"な​エリクサー​を​見つけ​た​の​なら、ラック​ダナン​の​言う​とおり​に​し​て​使わ​ない​こと​だ​\"\n\"ね。\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"ラック​ダナン​なんて、聞い​た​こと​ない​わ。ごめん​なさい。お​役​に​立て​そう​も​ない​わ。\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"もし、そいつ​が​紛れ​も​なく​ラック​ダナン​だっ​たら、助け​て​やっ​て​くれ。あれ​は​誠実​で​\"\n\"義理​堅い​男​だっ​た​よ。あの​レオリック​王​の​家臣​の​中​で​ただ​一人、特別​な​呪い​を​かけ​ら\"\n\"れ​て​いる​ん​だ。\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" ラクダナン​は​死ん​だ。みーんな​知っ​て​いる​こと​だ​し、わし​を​騙そう​たって​そう​は​いか​\"\n\"ない。死ん​だ​やつ​と​は​話せ​ない。知っ​てる​よ！\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"迷宮​に​閉じ込め​られ​た​ラック​ダナン​に​は、道​義心​と​深い​自責​の​念​を​感じる​こと​が​でき\"\n\"る。彼​を​助けれ​ば​トリストラム​の​救い​と​なろう。\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"ちょっと​待て​よ。ケイン​が​巨大​な​裂け目​に​飲み込ま​れ​て、地獄​の​火の玉​で​焼き殺さ​れ​\"\n\"ちまっ​て、あんた​の​質問​に​答え​られ​ねえ​って​の​か​? なに​ちがう​? なん​だ、何​か​買っ​て​\"\n\"くれ​ん​なら​いい​けど、そう​じゃ​ない​なら、さっさと​どっ​か​へ​行っ​て​くれ​よ。\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"待て。武器​を​収め、話​を​聞い​て​くれ。私​は​レオリック​騎士団​長​ラック​ダナン​だ。正義​\"\n\"と​名誉​に​かけ​て​この​国​の​法​を​守っ​て​き​た​者​だ。しかし、レオリック​王​を​非業​の​死​に​追\"\n\"いやっ​た​ため、呪い​を​かけ​られ​て​しまっ​た。騎士団​の​団員​は​みな​死ん​で​しまい、私​は​\"\n\"王​の​葬ら​れ​た​部屋​から​唯​一人​逃げ出し​て、この​呪い​から​逃れる​方法​を​探し​て​いる。\\n\"\n\"\\n\"\n\"​呪い​を​解き、魂​を​安らか​な​眠り​に​つか​せ​て​くれる​と​いう​ゴールデン​・​エリクサー​に​つ\"\n\"い​て​聞い​た​こと​が​ある​が、見つける​こと​は​でき​なかっ​た。力​も​衰え、わずか​な​理性​も​\"\n\"また、衰え​つつ​ある。エリクサー​を​探しだし、私​を​助け​て​欲しい。礼​は​さ​せ​て​もら\"\n\"う。名誉​に​かけ​て​誓おう。\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"まだ​ゴールデン​・​エリクサー​が​見つから​ない​よう​だ​な。私​は​永遠​に​この​まま​な​の​だろ\"\n\"う​か。頼む、探し​続け​て​くれ。\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"そなた​は​私​の​魂​を​破滅​から​救っ​て​くれ​た。感謝​する。この​借り​を​返す​すべ​が​見つかっ​\"\n\"たら、墓​の​中​に​はいっ​て​から​で​も​力​に​なろう。しかし、今​は​この​兜​を​受けとっ​て​く\"\n\"れ。私​の​これ​から​の​旅​に​は​もう​必要​ない。きっと​悪​なる​力​から​あなた​を​守っ​て​くれる​\"\n\"だろう。さあ​行く​の​だ。友​よ、光​と​とも​に​あら​ん​こと​を。\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"グリズウォルド​が​言っ​とる​の​は​「​憤激​の​鉄床​」​の​こと​じゃ​よ。永い​間​探し求め​て​いる​\"\n\"伝説​の​魔導​器​じゃ。「​カミソリ​の​穴​」​に​おる​悪魔​の​金属​質​の​骨​で​でき​て​おっ​て、地下​\"\n\"の​国​で​最も​力​の​ある​5​人​の​魔術師​の​ドクロ​の​そば​に​ある​と​いう。この​鉄床​に​は​力​と​混沌​\"\n\"を​表す​ルーン​文字​が​刻み込ま​れ、これ​に​よっ​て​作ら​れ​た​武器​や​鎧​は、混沌​の​世界​の​魔\"\n\"力​を​与え​られる​の​だ​そう​じゃ。混沌​の​力​は​予測​が​つか​ん​から​な、一体​どんな​力​を​秘め​\"\n\"て​いる​の​か​…\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"この​こと​は、グリズウォルド​に​きく​ほう​が、よく​あり​ませ​ん​か。親切​だ​し。\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"治療​の​器具​や​清め​の​銀​の​聖​さん​杯​の​情報​を​探し​て​い​た​の​なら、私​が​教え​て​やれ​た​の​\"\n\"に。しかし、詳しく​は​グリズウォルド​か​ケイン​に​聞い​た​方​が​いい​だろう。\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"子供​の​ころ、グリズウォルド​の​お父様​が、強力​な​武器​を​造る​大きな​鉄床​の​話し​を​し​て​\"\n\"くれ​た​わ。ハンマー​を​その​鉄床​に​振り下ろす​と、地面​が​怒り狂っ​た​よう​に、激しく​揺\"\n\"れる​ん​です​って。地震​が​ある​度​に、思い出す​わ。\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"やあ、いらっしゃい。また​来​て​くれ​た​の​か​い。迷宮​の​奥深く​へ​行っ​て​き​た​と​か​聞い​た​\"\n\"が​とっておき​の​話​が​ある。迷宮​から​戻っ​た​奴​が、逃げる​途中​で​魔法​の​鉄床​を​見​た​って​\"\n\"言う​ん​だ​が、これ​は​若い​ころ​わし​が​聞い​た​伝説​に​ぴったり​あてはまる​ん​だ。\\n\"\n\"\\n\"\n\"​その​伝説​と​いう​の​は、灼熱​地獄​の​奥深く​に​は​憤激​の​鉄床​と​いう​の​が​あっ​て、強力​な​魔\"\n\"法​の​武器​を​作り出し​て​いる​と​いう​ん​だ。鉄床​は​黄泉​の​国​の​悪魔​の​力​を​秘め​て​い​て、そ\"\n\"こ​で​作ら​れ​た​武器​は​最強​の​攻撃力​を​得る​ん​だ​と。\\n\"\n\"\\n\"\n\"​もし​その​鉄床​が​本物​なら、あんた​に​恐怖​の​帝王​を​も​倒せる​武器​を​作っ​て​やる​ぞ。鉄床​\"\n\"を​探しだし​て​くれ、おれ​の​腕前​を​見せ​て​やる​!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"まだ​見つから​ん​の​か​? 鉄床​さえ​ありゃ、あんた​に​伝説​の​武器​を​作っ​て​やれる​ん​だ。何​\"\n\"と​か​探し​て​くれ​よ。\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"おぉ、ついに​鉄床​を​手​に​入れ​た​か​! 見​てろ​よ。人間​様​の​作っ​た​武器​が​どれ​ほど​恐ろし\"\n\"い​か​思い知ら​せ​て​やる。さあ、これ​を​もっ​て​行け。光​の​御​加護​が​あり​ます​よう​に。\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"グリズウォルド​は​鉄床​は​売ら​ねえ。売っ​たら​何​も​出来​ねぇ​から​な。第​一、鉄床​を​取ら​\"\n\"れ​そう​に​なれ​ば、この​俺​だ​って​怒る​さ​!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"迷宮​に​は、人智​を​越え​た​力​を​持つ​魔導​器​が​数多く​眠っ​て​おる。中​に​は、光​の​者​で​も​闇​\"\n\"の​者​で​も​使える、途方​も​ない​力​を​持っ​た​物​も​ある。地下​で​鉄床​を​見つけ​られれ​ば、罪​\"\n\"深き​闘い​の​バランス​は、光​の​方​へ​傾く​や​も​知れ​ぬ。\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"もし​あんた​が​鉄床​を​見つけ​て​グリズウォルド​に​やっ​たら、俺​は​商売​あがったり​だ。ま\"\n\"ずい​な​… 見つかりゃ​し​ない​さ。\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"「​血​の​門​」​と​「​炎​の​広間​」​は、神秘​の​起源​と​なる​重要​な​建造物​じゃ。お主​が​読ん​だ​書\"\n\"物​の​出所​が​どこ​か​知ら​ん​が、そこ​に​は​偉大​なる​力​が​ある​の​じゃ。\\n\"\n\"\\n\"\n\"​伝説​に​よれ​ば、黒曜石​を​切り出し​た​台座​に​骨​の​細工​が​施さ​れ、その​上​に​は​煮えたぎる​\"\n\"血​が​たまっ​て​いる​そう​じゃ。伝説​は​古代​の​財宝​を​守る​扉​を​開ける​と​いう​ブラッド​ス\"\n\"トーン​に​つい​て​も​触れ​て​おる。\\n\"\n\"\\n\"\n\"​この​財宝​に​つい​て​は​様々​な​憶測​が​さ​れ​とる​が、いにしえ​の​英雄​アルケイン​が、秘密​の​\"\n\"場所​に​収め​た​聖​なる​鎧、ヴァロー​じゃ​と​も​言わ​れ​て​おる。アルケイン​は​「​罪​深き​闘い​\"\n\"」​に​最初​に​身​を​投じ​た​人間​で、暗黒​の​軍隊​を​地獄​まで​追い返し​た。\\n\"\n\"\\n\"\n\"​それ​が​亡くなる​直前、鎧​を​秘密​の​場所​に​隠し​た​の​じゃ。この​聖​なる​鎧​が​再び​必要​と​\"\n\"なっ​た​とき、英雄​が​現れ​て​これ​を​身​に​つける​そう​な。お主​の​こと​か​も​しれ​ぬ​な。\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"戦士​アルケイン​と​彼​の​ヴァロー​の​鎧​の​こと​なら​子供​だ​って​知っ​て​い​ます​よ。もし​鎧​の​\"\n\"在り​か​が​分かれ​ば、迷宮​の​怪物​から​身​を​守る​こと​が​でき​ます​な。\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"うーん、どう​も​思い出せ​ない​な。最近​は​新しい​治療​法​を​覚え​たり、エリクサー​を​作る​\"\n\"の​に​忙しく​て、忘れ​て​しまっ​た​よう​だ。すま​ぬ​な​..\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"ヴァロー​と​いう​名​の​鎧​の​話​なら、男の子​たち​が​よく​話し​て​い​た​から、町​の​男​たち​に​聞\"\n\"い​て​みる​と​いい​わ。\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"ヴァロー​の​鎧​を​探し​てる​の​か​? アルケイン​め、どこ​へ​隠し​やがっ​た​の​か、誰​に​も​わか\"\n\"ら​ねえ。俺​の​手下​に​も​見つけ​られ​ねえ​ん​だ、あんた​に​望み​は​ねえ​な。\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz​…\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"この “​血​の​石 “​を​見つけ​たら、慎重​に​使っ​て​ほしい。\\n\"\n\" \\n\"\n\"​この​道​は​危険​に​満ち​て​おり、唯一​の​希望​は​あなた​の​自己信頼​に​あり​ます。\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"ヴァロー​の​鎧​を​探し​てる​の​か​? アルケイン​め、どこ​へ​隠し​やがっ​た​の​か、誰​に​も​わか\"\n\"ら​ねえ。\\n\"\n\"\\n\"\n\"​俺​の​手下​に​も​見つけ​られ​ねえ​ん​だ、あんた​に​望み​は​ねえ​な。\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"そんな​戦士​の​伝説​なら、わし​が​知っ​て​おる​の​は​一​つ​だけ​じゃ。「​罪​深き​闘い​」​に​つい​\"\n\"て​の​古い​歴史書​に​よる​と​…。\\n\"\n\"\\n\"\n\"​「​千​年​の​戦い​の​血​と​死​と​に​まみれ、鮮血​の​将軍​は​自ら​倒し​た​死体​の​山​に​立っ​た。暗黒​\"\n\"の​剣​が​生け​る​者​へ、呪い​の​叫び​を​上げる。この​地獄​の​死刑​執行​人​の​前​に​立ちはだかる​\"\n\"者​は​全て、地獄​の​責め苦​を​味わう​こと​と​なっ​た​…。\\n\"\n\"\\n\"\n\"​さらに​「​罪​深き​闘い​」​で​は​暗黒​の​軍勢​と​闘っ​た​が、理性​を​失い、ついえる​こと​の​ない​\"\n\"血​へ​の​欲求​へ​と​走っ​た​」​と​書い​て​ある。\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"そんな​物騒​な​戦士​は​初耳​です​が、そんな​やつ​と​戦わ​ず​に​すむ​と​いい​です​ね。命​が​いく\"\n\"つ​あっ​て​も​足り​ませ​ん​よ。\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"この​よう​な​こと​は、よく​分から​ない​が、ケイン​なら​詳しい​だろう。\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"そんな​に​すごい​相手​と​闘う​なら、光​が​あなた​を​お守り​下さる​よう​に、お​祈り​し​て​いる​\"\n\"わ。\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"鮮血​の​将軍​に​は​邪悪​な​伝説​が​つきまとっ​て​いる。用心​を​怠る​ん​じゃ​ない。やつ​は​情け​\"\n\"容赦​ない​ぞ。\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"血​の​話​ばっかり​じゃ​ねぇ​か。たまに​はな、花​と​か​天気​と​か、美人​の​メイド​の​話​で​も​し\"\n\"ろ​ぉ​い​! 全く​よ​…​お前​ちょっと​お​かい​しい​ぜ、ほんと​に。\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"やつ​の​剣​の​腕前​は​それ​は​すごい​もの​さ。何千​年​も​の​時​を​戦い​だけ​に​費やし​て​き​た​の​だ​\"\n\"から。悪い​が、お前​の​敵う​相手​で​は​ない​か​も​しれ​ぬ​わ。\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"その​将軍​と​やら​は、おれ​の​客​じゃ​ねえ​が、そうとう​剣​を​つぶし​てる​な。もっとも、そ\"\n\"いつ​に​剣​を​売る​つもり​は​ねえ​けど​よ。\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"私​の​剣​は​人間​の​血​を​求め​て​いる。暗黒​の​支配者​たち​も、止め​は​し​ない​だろう。\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"グリズウォルド​が​言っ​て​おる​の​は、東方​へ​と​運ば​れる​はず​だっ​た​天界​の​石​の​こと​じゃ​\"\n\"な。詳しく​調べる​途中​ここ​に​運ば​れ​て​き​た​の​じゃ。この​石​は​普通​の​人間​に​は​見え​ない​\"\n\"エネルギー​で​輝い​とる。そこ​に​秘め​られ​た​謎​は​分から​ん​が、ともかく​この​石​を​見つけ\"\n\"る​こと​が​重要​な​の​は​確か​じゃろう。\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"キャラバン​が、東​へ​の​旅​に​備え​て、買い物​に​来​た​ん​です。新鮮​な​果物​を​どっさり​と、\"\n\"焼き立て​の​肉​を​買っ​て​くれ​た​の​に、お​気の毒​です。\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"その​石​を​使っ​て​何​を​しよう​と​し​て​い​た​の​か​は​知ら​ない​が、本当​に​石​が​空​から​落ち​て​く\"\n\"る​の​なら、気​を​つけ​た​方​が​よい​!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"ええ、何​か​偉い​人​たち​の​キャラバン​が、確か​に​ここ​へ​寄っ​た​けど、大分​前​の​話​よ。変\"\n\"わっ​た​訛り​が​あっ​て、長旅​に​出る​と​か​言っ​て​た​かしら。え​?​あの​人​たち​の​持っ​て​い​た​も\"\n\"の​を​探し​て​いる​の​?\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"面白い​話​が​ある​ん​だ。昔、東​の​王国​へ​向かう​キャラバン​が​ここ​を​通っ​た。どう​やら、\"\n\"連中​は​空​から​落ち​て​き​た​天界​の​かけら​を​持っ​て​い​た​らしい​が、ここ​から​北​の​地点​で、\"\n\"マント​を​まとっ​た​騎士団​に​待ち伏せ​さ​れ​て​襲わ​れ​た​ん​だ。その​時​以来、天界​の​かけら​\"\n\"は​姿​を​消し​て​しまっ​た​ん​だ​よ。もし​あんた​が​見つけ​たら、役​に​立つ​物​を​作っ​て​やろ\"\n\"う。\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"天界​の​かけら​は​まだか​? わし​なら、その​石​で​すごい​力​を​秘め​た​もの​を​作っ​て​やれる​の​\"\n\"に。\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"どれ、見せ​て​み​な。やっぱり​思っ​た​とおり​だ。\\n\"\n\"\\n\"\n\"​ほら、おやじ​から​もらっ​た​銀​の​指輪​に​この​石​を​はめ込む​と​ぴったり​じゃ​ない​か。こい\"\n\"つ​が​あんた​の​役​に​立つ​と​いい​な。\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"いい​指輪​を​持っ​て​た​よ。値​の​張る​やつ​で​色​は、青​と​緑​と​赤​と​銀色​だ。あれ​は、ええ​\"\n\"と、どう​し​た​っけ​な。無くし​ちまっ​た​…\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"天界​の​石​は​強い​力​を​持つ。決して​グリズウォルド​以外​の​者​に、それ​を​引き渡し​て​は​な\"\n\"ら​ぬ。グリズウォルド​なら​ば、我​ら​の​ため​に、その​良き​力​を​引き出す​こと​が​できる​で​\"\n\"あろう。\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"その​石​で​何​か​作れる​と​し​たら、グリズウォルド​しか​い​ねえ​な。やつ​は​頭​が​いい​から​\"\n\"よ。たしか​に​やつ​は​商売敵​だ​けど、腕​は​確か​さ。\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"「​魔女​の​エイドリア​が​黒​キノコ​を​探し​とる​」​だ​と​? 黒い​キノコ​だ​か​赤い​ニシン​だ​か、\"\n\"そんな​物​わし​は​全然​知ら​ん​ぞ。治療​師​の​ペピン​なら​色々​教え​て​くれる​じゃろう​が、わ\"\n\"し​は​聞い​た​こと​も​読ん​だ​こと​も​ない。\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"うち​の​大事​な​お客様​に、黒い​キノコ​なんて、絶対​出し​ませ​ん​よ。エイドリア​が​シ\"\n\"チュー​に​入れる​の​は、彼女​の​勝手​です​が、そんな​もの​探す​手伝い​は​ご免​です​から​ね。\"\n\"黒い​キノコ​だ​なんて​気持ち​悪い​!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"私​の​エリクサー​作り​を​助ける​ため​に、君​が​デーモン​の​脳味噌​を​探し​て​いる​と、エイド\"\n\"リア​から​聞い​た​よ。悪魔​の​魔力​の​秘密​を​解明​できれ​ば、あの​汚れ​た​獣​ども​に​傷つけ​ら\"\n\"れ​た​人々​を​助け​られる​と​思う​の​だ。悪魔​を​倒し​た​とき​に、その​脳味噌​を​取り出せ​た\"\n\"ら、私​に​届け​て​もらえ​ない​か​…\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"すばらしい、よく​やっ​て​くれ​た​ね。これ​なし​で​エリクサー​は​完成​し​た​が、これ​は​研究​\"\n\"用​に​重宝​する​よ。この​エリクサー​を​エイドリア​に​渡し​て​くれ​ない​か​? 待っ​て​いる​と​思\"\n\"う​から。\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"キノコ​なら、オグデン​さん​の​倉庫​に​いろいろ​あっ​た​はず​よ​? 聞い​て​み​たら​?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"エイドリア​で​も​持っ​て​ない​って​こと​なら、こいつ​は​そうとう​珍しい​代物​だ​ぞ。すま​ん​\"\n\"が​わし​は​何​の​力​に​も​なれ​そう​も​ない。だ​が、そりゃ、どう​やら、やたら​バカ​でかい​\"\n\"マッシュルーム​の​よう​だ​な。せいぜい​頑張っ​て​キノコ​を​採っ​て​き​て​お​くれ。\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"オグデン​は​怪しい​黒い​キノコ​で​何​か、作る​が​あれ​を​飲ん​だら、きっと​きっと​病気​に​な\"\n\"る​ぞ。いい​か、ほどほど​に​し​て​おけ​よ。\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"これ​は​何​じゃ​? なるほど、ポーション​の​製法​を​示し​た​本​の​よう​だ​ね。よし​黒い​キノコ​\"\n\"を​探し​て​き​て​お​くれ。大きな​キノコ​だ​から、お前​に​で​も​すぐ​に​分かる​よ。見つけ​た\"\n\"ら、私​の​ところ​へ​持っ​て​き​て​お​くれ。\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"今​調合​し​て​いる​ポーション​に​は、黒く​て​大きな​キノコ​が​必要​な​ん​じゃ。さあ、ボヤボ\"\n\"ヤ​し​とら​ん​で​早く​採っ​て​き​て​お​くれ。\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"ああ、これ​こそ、今​私​の​調合​し​て​いる​ポーション​に​必要​な​物​だ​よ。ところ​で、治療​師​\"\n\"が​デーモン​の​脳味噌​を​探し​て​おる​ぞ。毒​に​犯さ​れ​た​者​を​治療​する​ため​の​エリクサー​を​\"\n\"作る​の​に​必要​らしい​ね。お前​が​見つけ​て​やっ​た​なら、その​エリクサー​の​サンプル​を​一​\"\n\"つ​もらっ​て​き​て​お​くれ。\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"なぜ、そんな​もの​を​持っ​て​き​た​の​じゃ​? 今​は​デーモン​の​脳味噌​なんぞ​要ら​ない​よ。私​\"\n\"が​欲しい​の​は、治療​師​の​エリクサー​だ​よ​! その​気味​悪い​脳味噌​を​待っ​て​いる​の​は、あ\"\n\"の​治療​師​だ。私​に​は​やつ​の​エリクサー​を​持っ​て​き​て​お​くれ。分かっ​た​か​い​?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"なん​だ​い、今ごろ​エリクサー​を​持っ​て​き​た​の​か​い​? ポーション​は​もう​完成​し​ちまっ​た​\"\n\"よ。それ​は、お前​さん​が​持っ​て​おき​な。\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"俺​ん​とこ​は、キノコ​なんか​ひと​つ​も​ねえ​よ。それ​より、もっと​すぐ​に​役​に​立つ​もの​が​\"\n\"ある​けど、ひと​つ​どう​だ​い​?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"する​と​地図​の​伝説​は​本当​じゃっ​た​の​か。この​わし​で​すら、今まで​信じ​た​こと​も​なかっ​\"\n\"た​が​の​お​… そろそろ​正体​を​明かす​とき​が​来​た​よう​じゃ​な。\\n\"\n\"\\n\"\n\"​わし​の​真​の​名​は​デッカード​・​ケイン。永遠​の​悪​の​封印​を​守る​古き​結社​の、最後​の​末裔​\"\n\"じゃ。だ​が​どう​やら​その​封印​が​解か​れ​た​よう​じゃ。\\n\"\n\"\\n\"\n\"​お主​が​相手​に​する​の​は​恐怖​の​帝王。人間界​で​は​ディアブロ​と​呼ば​れ​て​おる。こやつ​こ\"\n\"そ​何​世紀​も​前​に​迷宮​に​幽閉​さ​れ​た​やつ​じゃ。お主​が​手​に​入れ​た​その​古い​地図​に​は、\"\n\"ディアブロ​が​幽閉​から​解き放た​れ、再び​立ち上がる​時​が​記さ​れ​て​おる。地図​に​ある​2​つ​\"\n\"の​星​が​一直線​に​並ぶ​とき、その​時​こそ​ディアブロ​は、その​力​を​最大限​に​発揮​する​の​\"\n\"じゃ。こと​は​一刻​を​争う。星​が​並ぶ​前​に​ディアブロ​を​見つけ、倒さ​ね​ば、もう​決して​\"\n\"やつ​を​止める​こと​は​でき​ぬ。\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"もう​時間​が​ない​ぞ​! きゃつ​は​暗黒​の​力​を​蓄え​て​おる。止め​られる​の​は​お主​だけ​じゃ​…\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"よく​やっ​とる​が、お主​の​その​力​と​精神力​で​は​まだ​足り​ぬ。ディアブロ​は​今​や​その​力​を​\"\n\"最大限​に​増大​し​て​いる、これ​に​打ち勝つ​に​は​勇気​と​力​を​振り絞ら​ね​ば​なら​ん​の​じゃ。\"\n\"光​の​加護​と​導き​あれ。わし​も​何​と​か​力​を​貸そう。\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"魔女​に​も​わから​なく​て、ケイン​に​聞け​と​言わ​れ​た​なら、私​の​出る​幕​じゃ​ない​です​よ。\"\n\"こと​は​重大​の​よう​です​から、はやく​語り部​に​会い​に​行き​なさい。\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"この​地図​の​文字​は、私​に​は​分から​ない​が、エイドリア​か​ケイン​なら​解読​し​て​くれる​の​\"\n\"で​は​ない​か​な。空​の​星​を​描い​た​地図​と​いう​こと​は​分かる​が、それ​以上​の​こと​は​分から​\"\n\"ぬ。\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"そう​いう​こと​は、語り部​に​聞く​の​が​一番​だ​わ。ケイン​は​古代​の​書物​に​は​とても​詳しい​\"\n\"の。それ​に​し​て​も、そんな​古​そう​な​紙切れ、見​た​こと​ない​わ​!\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"こんな​地図​は​見​た​こと​も​ない​ぞ。どこ​で​手​に​入れ​た​ん​だ​? わし​に​は​さっぱり​わから​ん​\"\n\"が​ケイン​か​エイドリア​に​聞い​て​みる​こと​だ​な。\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"話​が​ある。もっと​寄れ。お前​さん​が​知っ​てる​か​どう​か、知ら​ん​が​よぉ、ここ​に​いい​も\"\n\"の​が​ある​ん​だ。地図​だ。\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"おお、凶兆​が​出​て​おる​ぞ。星​に​よれ​ば、お前​の​前​に​大難​が​待ち受け​て​おる。すま​ぬ​が​\"\n\"それ​が​何​か​は​分から​ぬ。語り部​を​訪ね​て、彼​に​相談​する​の​が​良かろう。\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"俺​も​地図​を​探し​てる​ん​だ​が、それ​じゃ​ねえ​な。エイドリア​に​見せ​たら、多分​何​だ​か​解\"\n\"る​よ。古​そう​な​地図​だ​けど、古い​って​の​は​それ​だけ​で​値打​が​ある​もん​だ。\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"頼む、殺さ​ない​で​くれ​! 助け​て​くれ​たら、つぎ​来​た​とき​に​いい​もの​を​やる。\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"いま​作っ​てる​ところ​だ。殺さ​ない​で​くれ。いい​もの​を​やる​から​さ。\\n\"\n\"\\n\"\n\"​ほら、やる​よ。約束​は​守っ​た​よ。\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"まだ​だ​! もう​少し​で​できる。\\n\"\n\"\\n\"\n\"​もの凄い​力​を​持っ​てる​ぞ。\\n\"\n\"\\n\"\n\"​だ​から​殺さ​ない​で​くれ​! 助け​て​くれ​たら​約束​は​守る​よ。\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"いい​でき​だろ​? もの凄い​力​を​もっ​てる​ぞ​! 欲しい​か​? やる​よ。\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"何​だ​? 何​し​に​来​た​?! 邪魔​を​さ​れる​と​おかしく​なり​そう​だ。ウヘヘ、これ​を​持っ​てけ。\"\n\"わし​の​事​は​ほっ​とい​て​くれ​! ウァハハハ​!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"ウァハハハ​! その​好奇心​が​死​を​招く​の​だ​! ウァハハハ​!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"よう​来​た。まあ​聞き​なさい​…\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"迷宮​の​奥​へ​歩​を​進める​と、そこ​に​隠さ​れ​た​書物​が​ある。注意​深く​読み​なさい。\\n\"\n\"\\n\"\n\"​わし​で​すら​知ら​ぬ​よう​な​こと​が​書い​て​ある​はず​じゃ。\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"迷宮​を​進む​うち​に​生じる​疑問​の​答え​と​なる​神話​や​伝説​なら、わし​は​たくさん​知っ​とる​\"\n\"よ。知り​たい​こと​が​あれ​ば​わし​を​訪ね​なさい、知っ​て​いる​限り​の​こと​は​教え​て​進ぜよ\"\n\"う。\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"グリズウォルド​は​勇気​ある​立派​な​男​だ。ワート​を​助ける​ため​迷宮​に​分け入っ​た​話​な\"\n\"ど、自分​で​は​し​なかっ​たろう​? 自分​の​危険​も​省み​ず​に​な​…​そして​今度​は​お主​が​行く​か。\"\n\"あの​男​は​正直​で​腕​の​いい​武器​屋​じゃ。手助け​を​得​られれ​ば、その​誠意​と​技術​は​頼り​に​\"\n\"できる​ぞ。\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"オグデン​が​日の出​亭​と​酒場​の​主人​に​なっ​て​じき​四​年。宿屋​と​酒場​を​買い取っ​た​ほんの​\"\n\"数カ月​後、ここ​は​地獄​と​化し​た​の​じゃ。女房​の​ガーダ​共々​ここ​へ​越し​て​くる​の​に​財産​\"\n\"を​使い果たし、この​町​を​去る​金​など​残っ​て​おら​ん。責任感​の​強い、善良​な​男​じゃ​よ。\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"ファーンハム、可哀想​に。あの​暗黒​の​日、ラザルス​と​共​に​修道院​に​入っ​て​いっ​た​不幸​\"\n\"な​人々​の​こと​を​思い出す​よ。あの​男​は​生き​て​戻り​は​し​た​が、勇気​も​正気​も​あの​闇​の​中​\"\n\"に​置い​て​き​た​の​じゃ​な。今​で​は​酒​が​ない​と​心​が​安まら​ない​よう​じゃ。いつも​ぶつぶつ​\"\n\"言っ​て​いる​が​中​に​は​真実​が​込め​られ​て​いる​こと​も​ある​ぞ。\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"魔女​の​エイドリア​は、この​トリストラム​の​町​の​変わり者​じゃ。\\n\"\n\"​ここ​に​やっ​て​き​た​の​は​修道院​が​悪​に​冒涜​さ​れ、誰​も​が​ここ​を​離れよう​と​し​て​い​た​頃​の​\"\n\"こと​じゃっ​た。一​晩​で​町外れ​に​小さな​小屋​を​建て​て​の​お、わし​で​すら​見​た​こと​も​ない​\"\n\"よう​な​不思議​な​道具​や​書物​を​たくさん​持っ​て​おる​ぞ。\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"ワート​は​全く​恐ろしい、悲しい​目​に​あっ​た​もの​じゃ。邪悪​な​槍​を​振り回す​魔物​ども​に​\"\n\"よっ​て​母親​の​手​から​引き離さ​れ、迷宮​に​引きずり​込ま​れ​た​の​じゃ​よ。他​に​も​レオリッ\"\n\"ク​王​の​息子​を​初め​大勢​の​子供​ら​が​連れ去ら​れ​た。救出​に​向かっ​た​近衛兵​は​ついに​戻ら​\"\n\"なんだ。鍛冶屋​が​見つけ​た​とき​は​既に、魔物​ども​に​いたぶら​れ、苦しめ​られ​て​おっ​た​\"\n\"ん​じゃ。\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"おお​ペピン​か。あれ​こそ​真​の​友、町​一​番​の​わし​の​親友​じゃ。少々​頭​が​混乱​し​とる​時​も​\"\n\"ある​が、あれ​ほど​思いやり​の​ある​奴​は​そう​は​おら​ん。知識​も​腕​も​ぬきんで​て​おる​し、\"\n\"いつ​で​も​面倒​を​見​て​もらえる​ぞ。\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"ああ、ジリアン​は​人​の​いい​娘​だ。上機嫌​で​笑う​声​など、多く​の​人々​に​愛さ​れ​て​おる。\"\n\"も​ちんこ​の​わし​も​じゃ。体​の​具合​が​悪く​て​町​を​離れ​られ​ない​婆​さん​を​助け​て、酒場​で​\"\n\"働い​とる。身​の​安全​に​つい​て​は​心配​も​ある​が、町​の​男衆​が​みんな​で​守っ​て​やる​じゃろ\"\n\"う。\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"いらっしゃい​ませ。日の出​亭​へ​ようこそ。\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"うち​に​お​泊り​の​冒険者​は​数​知れ​ず、ビール​片手​に​冒険​談​に​華​を​咲か​せ​た​もの​でし​た。\"\n\"ど​な​も​肝​に​銘じ​て​い​た​教訓​が​「​肉​を​斬っ​たら、骨​まで​つぶせ​」​でし​た。御​参考​まで​\"\n\"に。\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"グリズウォルド​は​武器​や​防具​に​大変​詳しく、仕事​を​頼む​なら​絶対​お勧め​です。\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"ファーンハム​に​長々​と​居座ら​れ​ちゃ、迷惑​な​ん​です​が、迷宮​で​あんな​目​に​あっ​たら、\"\n\"酒​で​憂さ​を​はらす​しか​あり​ませ​ん​よ。\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"エイドリア​は、とても​頭​が​いい​らしい​の​です​が、不気味​な​人​です​ね。\\n\"\n\"\\n\"\n\"​で​も、魔法​の​アイテム​を​引き取っ​て​もらい​たい​なら、川​の​向こう​の​小屋​を​訪ねる​しか​\"\n\"あり​ませ​ん。あんな​に​色々​どう​やっ​て​手​に​入れ​た​ん​でしょう​ね​?\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"この​町​の​歴史​を​知り​たい​なら、語り部​の​ケイン​が​詳しい​です​よ。\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"ワート​は、絶え​ず​厄介​事​を​おこす​タイプ​です​から、彼​の​身​に​何​が​おき​て​も​おかしく​あ\"\n\"り​ませ​ん。うっかり​危険​な​場所​に​で​も​入っ​た​ん​でしょう。\\n\"\n\"\\n\"\n\"​可哀想​な​奴​です​が、とりまき​連中​に​は​我慢​なり​ませ​ん。\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"ぺ​ピン​は​善良​な​人​で、村​一​番​の​気前​の​良​さ​を​持っ​て​い​ます。しかし、彼​の​行く​ところ​\"\n\"に​は​必ず​と​言っ​て​いい​ほど、何​ら​か​の​トラブル​が​付きまとう​…。\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"うち​で​働い​てる​ジリアン​です​か​? この​町​を​でる​よう​に​説得​し​た​ん​です​が、思いやり​の​\"\n\"ある​子​です​から、年老い​た​お​婆​さん​を​後​に​は​置い​て​いけ​ない​ん​でしょう​ね。\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"調子​は​どう​か​ね​?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"興味​深い​発見​を​し​た​ぞ。我​ら​と​は​違っ​て、迷宮​の​獣​ども​は​ポーション​や​魔法​を​使わ​ず​\"\n\"に​傷​を​癒せる​よう​だ。\\n\"\n\"\\n\"\n\"​怪物​に​痛手​を​与え​たら、確実​に​殺さ​ない​と、自分​で​再生​する​か​も​しれ​ない​ぞ。\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"地下​に​潜む​..​その​何者​か​に​乗っ取ら​れる​以前​は、修道院​は​偉大​なる​知識​の​宝庫​だっ​\"\n\"た。そこ​に​は​沢山​の​本​が​ある。本​を​見つけ​たら、全部​読ん​だ​ほう​が​いい​ぞ。迷宮​の​秘\"\n\"密​が​記さ​れ​て​いる​か​も​しれ​ない​から​な。\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"私​が​癒し​の​術​に​詳しい​の​と​同じ​くらい、グリズウォルド​は​戦​の​術​に​詳しい。料金​は​高\"\n\"い​が、一番​の​腕利き​だ。まあ、他​に​鍛冶屋​は​い​ない​の​だ​けど​ね​…\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"ケイン​は​真​の​友​で​あり、賢人​で​ある。たくさん​の​蔵書​を​揃え​て、物事​の​本質​を​見極め\"\n\"る​天性​の​力​を​持っ​て​いる​の​だ。聞き​たい​こと​が​でき​たら、彼​の​所​へ​行く​が​いい。\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"私​の​技術​を​以​て​し​て​も、ファーンハム​を​完全​癒す​こと​は​でき​ない​の​だ。\\n\"\n\"​体​は​回復​し​た​が、心​と​魂​は​どう​する​こと​も​でき​ない。\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"私​も​ある​種​の​魔法​を​駆使​し​て​ポーション​や​エリクサー​を​調合​する​が、エイドリア​こ\"\n\"そ、真​の​魔法​使い​だ​よ。彼女​は​眠る​こと​も​し​ない​し、多く​の​神秘​の​霊廟​や​魔導​器​に​も​\"\n\"通じ​て​いる。彼女​の​小屋​に​は​見かけ​から​は​分から​ない​何​か​が​あり​そう​な​ん​だ​が、中​は​\"\n\"見せ​て​もらえ​ぬ​の​だ。\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"かわいそう​な​ワート。あの​子​の​ため​に​できる限り​の​こと​を​し​まし​た​が、私​が​無理矢理​\"\n\"足​に​つけ​た​木​の​釘​を​嫌​がっ​て​いる​の​は​知っ​て​い​ます。彼​の​傷​は​ひどかっ​た。誰​も​が、\"\n\"特に​幼い​子供​が、彼​の​よう​な​苦しみ​を​味わう​べき​で​は​あり​ませ​ん。\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"オグデン​は​なぜ、トリストラム​に​留まっ​て​いる​の​だろう​か。多少、情緒​不安定​な​所​は​\"\n\"ある​に​せよ、あの​よう​に​聡明​で​勤勉​な​男​なら、どこ​へ​行っ​て​も​成功​する​だろう​に。周\"\n\"辺​地域​で​殺人​が​多く​起き​て​いる​から​な​の​か​も​しれ​ない​し、妻​が​そう​望む​ため​に、留\"\n\"まっ​て​いる​の​か​も​しれ​ぬ。\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"オグデン​の​所​の​メイド​は​いい​娘​だ​な。祖母​が​重い​病​で、妄想​に​苦しん​で​いる​そう​\"\n\"だ。\\n\"\n\"\\n\"\n\"​本人​は​予知夢​だ​と​言っ​て​いる​が、本当​か​どう​か​は​知ら​ぬ。\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"私​で​何​か​お​役​に​立ち​ます​?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"お​ばあ​さま​が、あなた​が​私​と​話し​に​来る​夢​を​見​た​の。お​ばあ​さま​は​予知夢​を​見る​の​\"\n\"よ。\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"町外れ​の​あの​女​は、魔女​な​の​! いい​人​みたい​だ​し、エイドリア​と​いう​名前​も​素敵​だ​け\"\n\"ど、何​だ​か​怖い​わ。\\n\"\n\"\\n\"\n\"​あなた​は​勇気​が​ある​から、そこ​で​何​を​し​て​いる​の​か、見​に​行っ​て​くれる​?\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"鍛冶屋​の​グリズウォルド​は​トリストラム​の​人々​の​誇り​よ。何度​も​賞​を​とっ​た​腕​の​いい​\"\n\"職人​だ​し、亡くなっ​た​レオリック​王​も​自ら​お​褒め​に​なっ​た​の​よ。それ​に、グリズウォ\"\n\"ルド​は​立派​な​英雄​で​も​ある​の。ケイン​も​きっと​そう​言う​わ。\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"ケイン​は​ずっと​昔​から​トリストラム​の​語り部​よ。とにかく​博識​で、たいてい​の​こと​な\"\n\"ら​知っ​てる​わ​よ。\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"ファーンハム​は​自分​の​お腹​に​ビール​を、みんな​の​耳​に​無意味​な​言葉​を​詰め込む​酔っぱ\"\n\"らい​よ。\\n\"\n\"\\n\"\n\"​ペピン​と​オグデン​さん​は​同情​し​てる​よう​だ​けど、毎晩​うだうだ​と​酔っ払っ​て​いる​の​を​\"\n\"見る​と、イライラ​し​て​くる​わ​…\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"ペピン​は​お​ばあ​さま​の​命​の​恩人​で、いくら​感謝​し​て​も​し​きれ​ない​わ。病​を​癒す​彼​の​力​\"\n\"は、どんな​剣​より​も​強く​て、どんな​魔法​より​も​不思議​ね。もし​治療​が​必要​に​なっ​た\"\n\"ら、あなた​も​ペピン​に​頼む​と​いい​わ。\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"私​は​ワート​の​お母さん​の​キャナス​と​一緒​に​育っ​た​の​よ。ワート​が​あの​忌まわしい​怪物​\"\n\"に​さらわ​れ​た​とき、キャナス​は​軽傷​で​済ん​だ​の​に、結局​回復​し​なかっ​た​の。絶望​が​彼\"\n\"女​の​命​を​奪っ​た​ん​だ​わ。ワート​は、他人​の​働き​を​当て​に​する、さもしい​若者​に​育っ​て​\"\n\"しまっ​た​の。私​に​は​想像​すら​でき​ない​よう​な​苦しみ​や​恐怖​を​彼​は​味わっ​た​ん​でしょう​\"\n\"けど、その​暗​さ​を​今​で​も​引きずっ​て​いる​みたい。\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"オグデン​夫婦​は​私​と​お​ばあ​さま​を​自分​たち​の​家​に​迎え​て​くれ​て、私​に​は​宿​で​の​仕事​ま\"\n\"で​与え​て​くれ​た​恩人​よ。いつ​か​ここ​を​離れ​て、ご​夫婦​が​東部​で​立派​な​宿屋​を​始める​の​\"\n\"を、手伝い​たい​わ​ね。\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"やあ、いらっしゃい。\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"いい​武器​を​探し​て​いる​なら、これ​は​どう​だ。この​メイス​の​様​な​鈍器​は、アンデッド​ど\"\n\"も​に​良く​効く​ん​だ。スケルトン​ども​なんぞ​木っ端​みじん​に​し​て​くれる​ぞ。\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"なに​斧​? 斧​って​の​は、どんな​魔物​と​も​戦える​すぐれ物​だ。空気​を​切り裂く​こと​も​でき\"\n\"る。悪魔​の​首​なぞ​一​振り​で​すっ飛ぶ​だろう​よ。素早く​扱う​の​は​無理​だ​が、破壊力​は​抜\"\n\"群​さ。\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"どう​だいこ​の​刃​は。バランス​が​とれ​て​い​て​見事​だろう。剣​て​の​は、ふさわしい​者​が​使\"\n\"え​ば、最強​の​武器​と​なる。この​鋭い​切っ先​は、アンデッド​に​は​向い​て​い​ない​が、相手​\"\n\"が​生き物​なら​その​肉​を​簡単​に​断ち切っ​て​くれる。\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"魔物​相手​に​相当​激しく​戦っ​た​ん​だ​な。あんた​の​武器​や​鎧​を​見れ​ば​一目​で​わかる​よ。わ\"\n\"し​なら、新品​同様​に​打ち直し​て​やる​よ。\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"わし​が、町外れ​に​来る​キャラバン​から、金属​や​工具​を​こっそり​仕入れ​て​いる​って​の​\"\n\"に、魔女​の​エイドリア​と​き​たら、欲しい​もの​なら​なん​で​も​簡単​に​手​に​入れ​て​いる。あ\"\n\"の​女​みたい​に​魔法​が​使え​たら、すごい​代物​を​作っ​て​やる​ん​だ​が。\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"ジリアン​は​いい​娘​だ。ばあ​さん​が​あれ​ほど​弱っ​て​なかっ​たら、キャラバン​に​頼ん​で、\"\n\"この​町​から​逃がし​て​やり​たい​よ。\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"ケイン​は​しゃべり​すぎる​の​が​珠​に​傷​だ​が、あれ​が​商売​な​ん​だ​から​しょう​が​ない。やっ\"\n\"こ​さん​の​長話​に​付き合っ​てる​と、まぶた​が​だんだん​鉛​みたい​に​重く​なっ​て​くる​ん​だ​\"\n\"よ。\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"ラザルス​が​わし​ら​を​連れ​て​迷宮​に​行っ​た​とき、わし​は​ファーンハム​と​一緒​だっ​た。あ\"\n\"れ​っきり​大司教​は​姿​を​消し​ちまっ​た。わし​は​ファーンハム​の​おかげ​で、命拾い​し​た​\"\n\"が、やつ​は​ショック​で​あれ​以来​変​に​なっ​た。わし​も​足​を​悪く​し​た​が、やつ​の​ため​な\"\n\"ら、今​で​も​喜ん​で​戦う​ぞ。\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"自分​の​こと​より​先​に、他人​の​こと​を​考える​立派​な​お​方​だ。トリストラム​の​町​で​治療​師​\"\n\"の​ペピン​を​悪く​言う​者​は​一人​も​おら​ん。\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"あの​若造、やっかい​ごと​に​巻きこま​れる​ぞ。こり​ない​奴​だ。わし​の​ところ​で、額​に​汗​\"\n\"し​て​まじめ​に​働く​より、密輸​で​がっぽり​儲ける​ほう​が​性​に​あう​ん​だ​と。あんな​ひどい​\"\n\"目​に​合っ​た​後​だ​から、奴​に​厳しく​当たる​の​も​なん​だ​が、もう​少し​慎重​に​やっ​て​欲しい​\"\n\"もん​だ​な。\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"宿屋​の​主人、オグデン​は​商売​あがったり​だ。たまに​町​を​通りかかる​旅人​が、食事​し​た\"\n\"り​泊っ​たり​する​ん​で、なん​と​か​やりくり​し​てる​が、代金​を​踏み倒し​て​いく​やから​が​多\"\n\"く​て​な。魔物​が​この​あたり​一帯​を​支配​し​た​とき、オグデン​が​倉庫​に​穀物​や​乾燥​肉​を​蓄\"\n\"え​て​い​なかっ​たら、わし​ら​は​皆、飢え死に​する​ところ​だっ​た​って​いう​の​に。\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"静か​に​飲ま​せろ​ぃ。\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"酒​を​運ん​で​き​た​コ​か​? ああ、かわいい​ね。うん​! いい​コ​だ​よ、フハハハ。\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"あの​しわくちゃ​婆​さん​は、代わり​に​何​も​し​ねえ​の​か​よぉ​? そう​! モノ​は​持っ​てる​が、\"\n\"よっく​考え​て​みる​と​…​あの​婆​さん​は​全く​変​だ。第​一、飲み食い​する​ところ​を​見​た​事​が​無\"\n\"い。何​も​飲ま​ない​奴​なんて​信じ​られ​ない​ぜ。そう​思う​だろう​?\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"ケイン​は​正体​を​隠し​てる。確か​に​話​は​面白い​よ​…​怖い​話​と​か​笑い話​と​か、イヒヒ。で​も​\"\n\"実​は​もっと​色々​と​知っ​て​ん​じゃ​ねえ​か​と​おら​ぁ​思う​ぜ。\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"グリズウォルド​? いい​奴​だ、いい​奴​さぁ​! 兄弟​同然​に​愛し​てる​よ。共​に​戦っ​た​仲​さ、\"\n\"ほら​あの​時​…​俺​たち​…​ラザルス​…​ラザルス​! ラザルス​! ラザルス​め​えっ​!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"ヒャハハ、ペピン​は​好き​だ。よく​頑張っ​てる。ぜひ​知り合い​に​なる​と​いい​よ。いつも​\"\n\"人​を​助ける​いい​奴​な​ん​だ。ヒャハハ、いや​お前​さん​みたい​だ​な。え​?​勇者​?​俺​も​勇者​\"\n\"だっ​た​が​…\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"ワート​って​ガキ​は​俺​より、もっと​辛い​目​に​あっ​てる。俺​は​全部​知っ​てる。色々​持っ​て\"\n\"る​が​よ、以前、あそこ​に​行っ​た​ん​だ。片脚​を​無し​て​…​何​を​する​に​も、杖​が​いる​ん​だ。本\"\n\"当​に​可哀想​だ、本当​に​…\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"オグデン​は、町​で​一番​良い​やつ​だ。あの​女房​は​俺​に​気​が​ある​よう​だ​が、酒​を​持っ​て​来​\"\n\"て​くれる​限り​俺​は​ちっとも​構わ​ねえ​よ。俺​は​オグデン​と​一緒​に​生き​て​き​た​みたい​な​も\"\n\"ん​だ​が​な、あー、あいつ​は​本当​に​良く​し​て​くれ​た​よ​..\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"言い​たい​こと​が​ある。俺​は​こいつ​の​こと​は​何​で​も​知っ​てる。これ​が​一番​! 最​っ高​の​上\"\n\"物​だぁ​! 他​の​酒​は​まるっきり​駄目​さぁ​駄目​駄目​! だ​って​そこ​ら​の​バカ​犬​が​よぉ​…\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"誰​も​…​ヒック​…​聞きゃ​し​ねえ​が​よぉ、実​は​ある​場所​に​な​…​どこ​か​の​修道院​の​下​に​さ​…​金塊​\"\n\"の​山​が​ある​ん​だ。キラキラ​キラキラ​光っ​て、鎮座​ましまし​て​いる​ぜ。へへへ。\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"お前​さん​に​も​そりゃあ​考え​が​ある​だろう​し、きっと​信じ​ない​と​思う​けど​な、あそこ​で​\"\n\"手​に​入れ​た​武器​は、あの​大きな​ケダモノ​に​は​通用​し​ない​ぜ。グリズウォルド​の​奴​が​何​\"\n\"と​言っ​た​か​知ら​ん​が、やつ​ら​の​作る​もの​は​古​すぎる​ん​だ​ぃ。\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"もし​も、もし​も​だ​ぞ​…​もし​俺​だっ​たら、持ち物​を​売っ払っ​て​出​て​いく​ね。あそこ​の​小僧​\"\n\"なら​何​かしら​いい​もの​持っ​てる​が、金​を​幾ら​か​渡さ​ねぇ​と​な、見せ​て​も​貰え​ねぇ​だろ\"\n\"う​よ。\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"答え​を​追い求める​魂​よ​…\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"智恵​と​は、努力​し​て​得る​もの​じゃ。知識​の​霊廟​に​遭遇​し​た​の​なら、その​言葉​を​自分​の​\"\n\"もの​に​する​が​よろしい。その​本​の​中​の​神秘​が​既に​知り​え​た​もの​なら、更なる​力​を​得る​\"\n\"こと​が​できる​だろう。\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"強い​力​ほど、短命​な​もの​じゃ。お前​は​古代​の​力​の​呪文​が​書か​れ​た​巻物​を​見つける​か​も​\"\n\"しれ​ぬ。巻物​の​強み​は、熟練​者​で​あろう​と​初心者​で​あろう​と、同じ​効果​が​生み出せる​\"\n\"と​いう​こと。逆​に​弱み​は、その​場​で​読み上げ​なけれ​ば​なら​ず、前もって​覚え​て​おく​こ\"\n\"と​が​でき​ない​点​じゃ。また、巻物​は​一度​しか​使う​こと​が​でき​ん。よく​考え​て​使い​なさ\"\n\"れ。\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"太陽​の​熱​は​計り知れ​ぬ。だ​が、ロウソク​の​かすか​な​炎​の​方​が​危険​な​とき​も​ある。いか\"\n\"に​強大​な​エネルギー​も、的確​に​まとめ​ね​ば、使う​こと​は​あたわ​ぬ。杖​に​込め​られ​た​多\"\n\"く​の​呪文​は、再び​魔法​の​エネルギー​で​満たす​こと​が​できる。私​は​呪文​の​力​を​復活​さ​せ\"\n\"る​術​を​知っ​て​おる。が、代償​を​払う​覚悟​は​必要​じゃ​よ。\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"人々​が​一​つ​に​まとまれ​ば、それ​だけ​知識​も​増す​と​いう​こと​じゃ。解読​でき​ぬ​本​や​巻物​\"\n\"は、私​の​所​へ​持っ​て​き​なされ。解読​でき​たら、皆​に​も​伝えよう​ぞ。\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"鉄​しか​知ら​ぬ​者​に​とり、鋼鉄​こそ​は​最強​の​魔法。奴​が​気付く​こと​は​ある​まい​が​鍛冶屋​\"\n\"の​グリズウォルド​は、まさに​魔術師​じゃ。火​と​金属​を​融合​さ​せる​やつ​の​力​に​は、誰​も​\"\n\"敵わ​ぬ。\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"腐敗​に​は​ごまかし​の​強さ​が​ある​が、純潔​に​は​無垢​の​力​が​宿る。あの​ジリアン​と​いう​娘​\"\n\"の​無垢​な​心​は​な、祖母​の​望み​を​己​より​優先​さ​せ​て​いる。彼女​が​私​を​恐れる​の​は、ただ​\"\n\"理解​でき​ぬ​から​に​過ぎ​ぬ。\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"闇​の​中​で​開こう​と、光​の​中​で​開こう​と、チェスト​の​宝​は​変わる​こと​は​ない。語り部​の​\"\n\"ケイン​は、謎​に​包ま​れ​て​おる​が、注意​し​て​見れ​ば​分かる​こと​も​ある​ぞ。修道院​の​地下​\"\n\"に​ある​もの​に​つい​て、彼​は​自分​で​も​気づか​ぬ​ほど、多く​の​こと​を​知っ​て​おる​の​じゃ。\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"一人​の​男​に​多く​の​信頼​を​寄せれ​ば、それ​だけ​裏切ら​れ​た​とき​の​落胆​も​大きい。ファー\"\n\"ンハム​の​魂​を​奪っ​た​の​は、悪魔​で​は​ない。ラザルス​大司教​に​裏切ら​れ​た​とき、やつ​は​\"\n\"魂​を​失っ​た​の​じゃ。ファーンハム​は​情報​を​持っ​て​おる​が、事実​と​空想​を​区別​し​て​聞か​\"\n\"ね​ば​なら​ぬ。\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"手、心、精神​が​完全​に​調和​し​た​とき、奇跡​を​起こす​こと​が​できる。治癒​師​の​ペピン​\"\n\"は、私​で​さえ​でき​ない​方法​で​体​の​中​を​見る​こと​が​でき​ます。病人​や​負傷者​を​回復​さ​せ\"\n\"る​彼​の​能力​は、万能薬​や​ポーション​の​作り方​を​理解​し​て​いる​から​こそ​発揮​さ​れ​ます。\"\n\"彼​は​トリストラム​の​よう​な​偉大​な​同盟​者​です。\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"未来​に​おい​て​何​が​起こる​か​は​見え​ぬ​が、その​時​が​来​た​の​なら、世​を​支配​する​の​は​子供\"\n\"達​じゃ。ワート​は​魂​に​悪しき​部分​を​持っ​て​おる​が、町​や​人々​の​脅威​と​は​なら​ぬ。近隣​\"\n\"の​仲間達​や​後ろ暗い​ギルド​と​秘密裏​に​通じ​て​おり、トリストラム​で​は​手​に​入り​にくい​\"\n\"品物​を​得る​こと​が​できる​の​じゃ。やり方​は​いかがわしい​もの​だ​が、お前​が​しのびよる​\"\n\"闇​の​勢力​と​闘う​時、ワート​は​きっと​役​に​立つ​はず​じゃ。\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"土​の​壁​と​草ぶき​屋根​だけ​で​は、温もり​は​生まれ​ぬ。宿屋​の​主人​オグデン​は、町​の​人々​\"\n\"が​思う​以上​に​この​町​に​とっ​て​重要​な​存在​な​の​じゃ。ジリアン​と​その​祖母​を​住まわ​せ、\"\n\"ファーンハム​の​命​の​残り火​を​守り、町​に​残さ​れ​た​人々​に​とっ​て​は、かつて​の​トリスト\"\n\"ラム​と​の​最後​の​つながり​と​なっ​て​おる。あの​宿屋​は​懐かしい​かつて​の​暮らし​を​一時、\"\n\"人々​に​味​あわせ、よみがえる​思い出​に​励まさ​れ​ながら、お前​の​成功​を​願っ​て​おる​の​\"\n\"じゃ。\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"おい、こっち​だ。\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"迷宮​で​見つけ​た​もの​に​は、使い道​や​価値​が​ある​の​か​わから​ねえ​もの​も​ある。この​俺​だ​\"\n\"って、頭​を​ひねる​こと​も​ある​ん​だ。\\n\"\n\"\\n\"\n\"​使い道​が​わかる​の​は、あんた​だけ​って​こと​も​ある​ぜ。\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"酔っ払い​の​言う​こと​なんか、真​に​受け​ねえ​ほう​が​いい​ぞ。酒​は​判断力​を​鈍ら​せる​から​\"\n\"な。\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"言っ​とく​けど、俺​は​高級​品​しか​扱わ​ねえ。だ​から​トリス​トラム​で​は​何​も​買わ​ねえ​の​\"\n\"さ。その​ガラクタ​を​売り​たい​なら、グリズウォルド​か​ぺ​ピン​か、魔女​の​エイドリア​に​\"\n\"持っ​て​き​な。連中、飛び付く​ぜ。\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"グリズウォルド​は​命​の​恩人​だ。この​ちっぽけ​な​命​の​な。俺​を​鍛冶屋​に​弟子​入り​さ​せ​て​\"\n\"くれ​た。いい​やつ​だ​よ、あいつ​は。だ​が​俺​に​は​莫大​な​金​が​必要​な​ん​だ。何故​か​って、\"\n\"それ​は​その​…​計画​が​ある​の​さ。\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"もう​ちょっと​年​取っ​て​たら、リッチ​な​プレゼント​で​ジリアン​を​バンバン​攻め​まくっ​\"\n\"て、何​が​何​で​も​俺​の​もの​に​し​て​た​ぜ。あんな​きれい​な​人​が、こんな​に​危険​な​トリスト\"\n\"ラム​に​残っ​て​い​ちゃ​いけ​ねえ​よ。んー、そう​だ、俺​が​ここ​を​出る​とき、あの​人​を​連れ​\"\n\"て​行こう。\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"ケイン​の​やつ、散々​俺​を​おどかし​やがっ​た。川​の​向こう​に​住ん​でる​あの​女​より​ひで\"\n\"え。俺​が​生き​て​帰っ​た​の​が​奇跡​だ​と​か、伝説​の​中​で​すべて​予言​さ​れ​て​い​た​だ​と​か、く\"\n\"どくど​言い​やがる。\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"ファーンハム​は​まったく​厄介​な​こと​に​なっ​た​ぜ。ああ​なる​と​人間、とことん​深み​に​は\"\n\"まっ​て​いく​もん​だ。信じ​て​い​た​ラザルス​に、地獄​の​底​へ​突き落とさ​れ​そう​に​なっ​た​ん​\"\n\"だ​から​な。あそこ​は​恐ろしい​とこ​だ。いい​か​迷宮​に​潜む​魔物​ども​を​退治​する​なんて、\"\n\"バカ​な​考え​は​やめ​て、へっ、足下​に​気​を​つけろ​よ。\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"ばらばら​に​なっ​た​手足​を​くっつけろ​って​の​は​理​だ​けど、ぺ​ピン​は​とびっきり​腕​が​い\"\n\"い。あいつ​の​薬​を​飲ん​で​たら、俺​の​足​も​ぴんぴん​し​て​た​か​も​な。\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"エイドリア​に​は​うんざり​だ。ケイン​の​話す​伝説​も​不気味​だ​けど、あの​女​は​俺​の​過去​を​\"\n\"お​見通し​な​ん​だ。おまけ​に​欲しい​もの​は​全て​手​に​入れる。あの​女​は​ど​えらい​数​の​商品​\"\n\"を​持っ​てる。祭り​の​最中​の​バザー​で​売ら​れ​て​た​商品​より​多い​ん​だ。\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"オグデン​は​バカ​だ​ぜ。格安​で​ここ​から​脱出​さ​せ​て​やる​って​の​に、宿屋​を​閉め​たく​ない​\"\n\"だ​と​よ。ま、おかげ​で​ジリアン​は​働ける​し、かみさん​の​ガーダ​お​手製​の​うまい​パイ​に​\"\n\"も​ありつける​ん​だ​けど​な。\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"英雄​の​広間​の​奥​に​は​納骨堂​が​ある。そこ​の​財宝​を​盗もう​と​する​者​に​は、永遠​の​死​が​訪\"\n\"れる​だろう。恐怖​の​帝王​の​言葉​通り、そして​ここ​に​記さ​れ​て​いる​通り​に。\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"…​そして​血​の​門​の​向こう、炎​の​広間​の​その​先​で、ヴァロー​は​光​の​英雄​が​目覚める​の​を​\"\n\"待っ​て​いる​…\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"汝​に​見え​ぬ​物​が​私​に​見える。\\n\"\n\"​視界​が​濁り、瞳​は​腐る。\\n\"\n\"​汝​が​振り向け​ば、彼​ら​は​神秘​の​歌​を​ささやき​ながら​消える​だろう。\\n\"\n\"​そして​汝​は​見え​ぬ​はず​の​もの​を​目​に​する。\\n\"\n\"​光​ある​べき​ところ​に​影。\\n\"\n\"​闇​の​外​に​は​狂気​の​世界。\\n\"\n\"​盲目​の​広間​にて​悲嘆​に​暮れ​よ。\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"地獄​の​武器​庫​は​鮮血​の​将軍​の​棲み家。彼​が​目覚める​と​辺り​に​は​幾​千​の​死体​が​横たわっ​\"\n\"て​い​た。天使​も​人間​も、血​のみ​を​求める​暗黒​の​支配者​へ​の​生け贄​と​し​て、次​から​次​へ​\"\n\"と​切り裂か​れ​て​いっ​た。\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"ここ​に​書か​れ​て​いる​真実​は、ホラドリム​の​最後​の​遺産​です。今​も​なお、我々​の​知る​\"\n\"フィールド​を​超え​て、高天原​の​理想的​な​王国​と​灼熱​の​地獄​の​混沌​と​し​た​穴​の​間​で、戦\"\n\"争​が​続い​て​いる。この​戦争​は​「​大いなる​対立​」​と​し​て​知ら​れ​て​おり、天空​の​どの​星​よ\"\n\"り​も​長く​猛威​を​振るい、燃え​続け​て​い​ます。光​と​闇​の​力​が​すべて​の​創造物​を​支配​しよ\"\n\"う​と​常​に​争っ​て​いる​ため、どちら​の​側​も​長く​支配​する​こと​は​でき​ませ​ん。\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"ここ​に​書か​れ​て​いる​真実​は、ホラドリム​の​最後​の​遺産​です。高天原​と​灼熱​の​地獄​の​間​\"\n\"の​永遠​の​争い​が​人間​の​土​に​落ちる​とき、それ​は​罪​の​戦争​と​呼ば​れ​ます。天使​と​悪魔​は​\"\n\"変装​し​て​人間​の​中​を​歩き回り、人間​の​詮索​好き​な​目​から​逃れ​て​秘密裏​に​戦い​ます。天\"\n\"使​と​悪魔​は​変装​し​て​人間​の​間​を​行き来​し、人間​の​目​に​触れ​ない​よう​に​秘密裏​に​戦っ​て​\"\n\"いる。大胆​で​強力​な​人間​の​中​に​は、どちら​か​に​味方​し​て​罪​の​戦争​の​行方​を​決める​者​も​\"\n\"いる。\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"ここ​に​書か​れ​て​いる​真実​は、ホラドリム​の​最後​の​遺産​です。約​300​年​前、灼熱​地獄​の​三​\"\n\"大​悪​が​謎​に​包ま​れ​て​この​世界​に​やっ​て​き​た​こと​が​知ら​れる​よう​に​なり​まし​た。三​兄弟​\"\n\"は​何十​年​に​も​わたっ​て​東方​の​土地​を​荒らし、人類​は​その​後遺症​で​震え上がっ​た。私た\"\n\"ち​の​教団、ホラドリム​は、三​兄弟​を​追い詰め​て​捕らえる​ため​に、秘密​主義​の​マジシャ\"\n\"ン​たち​に​よっ​て​設立​さ​れ​まし​た。\\n\"\n\" \\n\"\n\"​オリジナル​の​ホラドリム​は、3​人​の​うち​2人​を​ソウル​ストーン​と​呼ば​れる​強力​な​アー\"\n\"ティファクト​で​捕らえ、荒涼​と​し​た​東​の​砂​の​下​に​埋め​た。3​体​目​の​エビル​は​捕らえ​られ​\"\n\"ず、多く​の​ホラドリム​が​追いかける​中、西​へ​と​逃げ​て​いっ​た。恐怖​の​帝王​ディアブロ​\"\n\"と​呼ば​れる​第​三​の​悪​は、やがて​捕らえ​られ、その​魂​を​ソウル​ストーン​に​封じ込め​て​こ\"\n\"の​迷宮​に​埋め​られ​た。\\n\"\n\" \\n\"\n\"​魂​の​石​は、信仰心​の​ない​者​に​は​発見​さ​れ​ない​よう​に​し​なけれ​ば​なら​ない。もし​ディア\"\n\"ブロ​が​解放​さ​れる​と​し​たら、彼​は​非常​に​弱っ​て​いる​の​で、コントロール​し​やすい​体​を​\"\n\"求める​だろう。\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"灼熱​の​地獄​で​は、「​暗黒​の​亡命​」​と​呼ば​れる​大革命​が​起こっ​た。小​悪党​が​三​大​悪党​を​\"\n\"倒し、その​霊体​を​人間界​に​追放​し​た​の​で​ある。ベリアル​（​嘘​の​神​）​と​アズモダン​（​罪​\"\n\"の​神​）​は、3​兄弟​が​不在​の​間、地獄​の​支配権​を​主張​し​て​争い​まし​た。地獄​全体​が​ベリア\"\n\"ル​と​アズモダン​の​派閥​に​分かれ、高天原​の​力​が​地獄​の​門​を​叩き​続け​て​い​た。\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"三​兄弟​を​捜し​て​多く​の​悪魔​が​人間界​に​やっ​て​き​た。後​を​追っ​て​き​た​天使​たち​は​東方​中​\"\n\"の​悪魔​狩り​を​始め​た。天使​は、人間​の​魔術師​に​よる​ホラドリム​と​いう​秘密​組織​と​手​を​\"\n\"組ん​だ。ホラドリム​は​急速​に​悪魔​狩り​の​腕​を​上げ、黄泉​の​国​に​暗黒​の​敵​を​数多く​作っ​\"\n\"た。\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"その​結果、三​大​悪​は​霊​の​形​で​人間界​に​追放​さ​れ、何十​年​に​も​わたっ​て​東洋​を​混乱​に​陥\"\n\"れ​た​後、呪わ​れ​た​人間​の​ホラドリム​教団​に​追わ​れる​こと​に​なっ​た​の​です。ホラドリム​\"\n\"は、憎しみ​の​神​メフィスト​と​破壊​の​神​バアル​の​エッセンス​を​封じ込め​た​ソウル​ストー\"\n\"ン​と​呼ば​れる​アーティファクト​を​使用​し​て​い​まし​た。末​の​弟​で​ある​恐怖​の​帝王​ディア\"\n\"ブロ​は​西​へ​逃亡​し​た。\\n\"\n\" \\n\"\n\"​やがて​ホラドリム​は​ディアブロ​も​ソウル​ストーン​に​捕らえ、忘れ去ら​れ​た​古代​の​大聖\"\n\"堂​の​下​に​埋葬​し​た。そこ​で​は​恐怖​の​帝王​が​眠り、再生​の​時​を​待っ​て​いる。彼​は​無垢​で​\"\n\"簡単​に​コントロール​できる​若​さ​と​力​の​ある​肉体​を​求め​て​憑依​する​こと​を​知る。そし\"\n\"て、彼​は​兄弟​たち​を​解放​する​ため​に​立ち上がり、再び​罪​の​戦争​の​炎​を​燃え上がら​せる​\"\n\"だろう​…。\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"闇​の​追放​の​生き残り​で​ある​恐怖​の​帝王、ディアブロ​に​栄光​あれ。永い​眠り​から​覚め​た​\"\n\"時、我が​王​は​人間​に​知ら​れ​て​い​ない​秘密​の​話し​を​し​て​くださっ​た。天界​の​王国​と、業\"\n\"火​燃え盛る​地獄​と​の​永遠​の​戦い​の​話​を。そして​人間界​に​争い​を​もたらし​た​その​力​を​示\"\n\"し、この世​と、この世​に​存在​する​全て​の​もの​に​ちなん​で、その​争い​は​「​罪​深き​闘い​」​\"\n\"と​名付け​られ​た​の​だ​..\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"三​兄弟​の​リーダー​に​し​て​恐怖​の​帝王、ディアブロ​に​栄光​あれ。我が​王​は、はるか​昔​に​\"\n\"この世​に​追放​さ​れ​た​兄弟、メフィスト​と​バール​の​話​を​し​て​くださっ​た。今​は、機​が​熟\"\n\"する​の​を​待ち、恐る​べき​力​を​身​に​つけ、囚われ​て​東方​の​砂漠​に​葬ら​れ​た​兄弟​たち​を​救\"\n\"い出す​こと​を​願っ​て​いる。兄弟​を​解放​し​た​あかつき​に​は、「​罪​深き​闘い​」​に​再び​三​兄\"\n\"弟​の​怒り​が​吹き荒れる​だろう​…\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"魂​の​破壊​者​に​し​て​恐怖​の​帝王、ディアブロ​万歳​! お​目覚め​に​なら​れ​た、我が​主​は​まず​\"\n\"肉体​を​手​に​入れよう​と​し​た。そこ​で​レオリック​王​の​身体​に​目​を​付け​た​が、まだ​力​及ば​\"\n\"ず、手​に​入れる​こと​は​でき​なかっ​た。この世​に​根​を​下ろす​に​は​無垢​な​錨​が​必要​な​の​\"\n\"だ。我が​王​は​アルブレヒト​王子​を​選ば​れ​た。高潔​な​レオリック​王​は​ディアブロ​が​乗り\"\n\"移ろう​と​し​た​とき​に​発狂​し​た。私​は​アルブレヒト​王子​を​誘拐​し、我が​主​の​許​へ​連れ\"\n\"帰っ​た。今​私​は、ディアブロ​の​呼び声​を​待っ​て​いる。我が​王​が​この​世界​の​支配者​と​な\"\n\"れ​ば、私​も​報わ​れる​と​いう​もの​だ​…\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"戻っ​て​来​て​くれ​た​ん​です​ね​! \\n\"\n\"​あんな​に​平和​だっ​た​町​に、邪悪​な​騎士​が​やっ​て​き​て、何​も​か​も​破壊​し​た​の​です。刃向\"\n\"かっ​た​者​は​殺さ​れる​か、連れ去ら​れ​て​奴隷​に​さ​れ​て​しまい​まし​た。町外れ​の​修道院​\"\n\"は、暗黒​の​儀式​に​使わ​れ、夜な夜な​金切り声​が、あたり​に​こだま​し​ます。まだ​何人​か​\"\n\"生き​て​いる​か​も​しれ​ませ​ん。宿屋​と​鍛冶場​の​間​の​小道​を​ぬけれ​ば​修道院​です。\\n\"\n\"\\n\"\n\"​どう​か、一人​で​も​多く​救っ​て​ください。幸運​を​祈り​ます。\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"探求​心​を​持ち​続ける​こと。 失わ​れ​た​宝​を​探す​の​は​簡単​で​は​あり​ませ​ん。 隠れ​て​いる​\"\n\"宝​を​見つける​の​は​もっと​難しい。 私​は​あなた​に​これ​を​残し​ます。 時​の​砂​に​惑わさ​れ\"\n\"る​こと​なく、あなた​の​探求​を​続け​て​ください。\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"なん​と​愚か​な。 トリストラム​に​は​宝​なんか​埋まっ​てる​もん​か。 それ​を​見せ​て​み​な！ \"\n\"こりゃ​デタラメ​だ。この​街​の​もの​じゃ​ない​な。 俺​は​大聖堂​の​下​に​ある​ん​じゃ​ない​か​と​\"\n\"踏ん​でる​ん​だ、表土​じゃ​なく​て​な。\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"私​に​は、あなた​が​探し​て​いる​地図​に​つい​て​話し合う​時間​が​ない​の​だ​よ。 私​に​は​私​の​助\"\n\"け​を​必要​と​する​多く​の​病人​が​い​て、あなた​の​助け​も​必要​な​の​です。\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"かつて​誇り​高かっ​た​イスウォール​は、この​世界​の​地下​深く​に​閉じ込め​られ​た​わ。 名誉​\"\n\"を​剥奪​さ​れ、姿​も​変え​られ​た​の。\\n\"\n\"​彼​は、不滅​の​苦しみ​に​陥っ​て​いる​わ。彼​を​解放​する​こと​が​できる​もの​を​隠す​よう​に​課\"\n\"せ​られ​た​わ。\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"ワート​は​あなた​が​来る​の​を​見​て、後​で​あなた​が​町中​を​鼻息​荒く​走り回っ​て​いる​の​を​笑\"\n\"う​ため​に​演技​を​し​た​ん​でしょう​ね。 私​なら​無視​し​ます。\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"かつて​この​町​に​は、遠く​から​の​旅人​が​頻繁​に​立ち寄っ​て​い​た​時代​が​あっ​て​な。 それ​か\"\n\"ら、いろいろ​と​変わっ​て​しまっ​た​ん​じゃ。 しかし、隠さ​れ​た​洞窟​や​埋蔵金​の​話​は、子\"\n\"供たち​の​空想​じゃ​よ。 ワート​は​子供​の​遊び​に​は​あまり​付き合わ​ん​から​彼​が​想像​し​た​産\"\n\"物​か​も​しれ​ん​な。\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"話​が​ある。もっと​寄れ。お前​さん​が​知っ​てる​か​どう​か、知ら​ん​が​よぉ、ここ​に​いい​も\"\n\"の​が​ある​ん​だ。地図​だ。\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"お​ばあ​さま​は、教会​の​外​に​ある​墓地​に​生息​する​奇妙​な​力​に​つい​て、よく​話​を​し​て​くれ\"\n\"る​の。 その​うち​の​一​つ​に​興味​が​湧く​か​も​しれ​ない​わ。 墓地​に​お​供え物​を​置い​て​大聖\"\n\"堂​に​入っ​て、死者​の​ため​に​祈り​を​捧げ​て​から​戻っ​て​くる​と、お​供え物​が​不思議​な​方法​\"\n\"で​変え​られ​て​しまう​そう​よ。 病気​の​老婆​の​戯言​か​も​しれ​ない​けれど、最近​は​何​で​も​あ\"\n\"り​の​よう​だ​わ。\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"莫大​な​お​宝​だ​って​? 分け前​は​もらえる​ん​だろう​な。それ​より​世​に​も​珍しい​ブツ​が​ある​\"\n\"ん​だ​けど、どう​だ​い​? これ​が​ありゃあ​鬼​に​金棒​だ​ぞ。\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"お前​が​みんな​が​噂​し​て​いる​英雄​か。\\n\"\n\"​俺​を​助け​て​くれ​ない​か、ただ​の​貧しい​農夫​が​恐ろしい​事態​に​陥っ​て​いる​ん​だ！\\n\"\n\"​俺​の​果樹園​の​端、ここ​から​南​に​行っ​た​ところ​に、地面​から​うごめく​恐ろしい​もの​が​い\"\n\"る！\\n\"\n\"​作物​や​干し草​に​たどり着け​なく​て、俺​の​可愛い​牛​たち​が​餓死​し​ちまう。魔女​が​これ​を​\"\n\"くれ​て、あの​怪物​を​畑​から​吹き飛ばせる​と​言っ​た​ん​だ。もし​それ​を​壊し​て​くれ​たら、\"\n\"永遠​に​感謝​する​よ。\\n\"\n\"​俺​も​自分​で​やり​たい​が、牛​たち​と​世話​が​ある​から​な​…\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"魔女​が​言っ​た​ほど​簡単​じゃ​ない​と​は​思っ​て​い​た。ご​近所​さん​すら​信じ​られ​ない​なん\"\n\"て、悲しい​世界​だ​な。\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"もう​い​なく​なっ​た​の​か？あの​恐ろしい​もの​を​冥界​の​闇​に​送り返し​て​くれ​た​の​か？\\n\"\n\"​何​だ​って？ まさか、失くし​た​なんて​言わ​ない​よ​な！あれ​は​安く​ない​ん​だ​から​な。見つ\"\n\"け​て、あの​恐怖​を​街​から​叩き出し​て​くれ！\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"ここ​から​で​も​爆発​音​が​聞こえ​た​ぞ！親切​な​見知ら​ぬ​人、心​から​感謝​する。地面​から​\"\n\"次々​と​出​て​くる​もの​や、教会​を​乗っ取る​モンスター​たち、そして​その​他​もろもろ、今​\"\n\"は​厳しい​時代​だ。俺​は​ただ​の​貧しい​農夫​だ​が、これ​を​受け取っ​て​くれ。心​から​の​感謝​\"\n\"を​込め​て。\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"本当​に​困っ​た​こと​に​なっ​た​…​で​も​…​いや、他​に​も​いろいろ​ある​し、お前​に​頼む​わけ​に​は​\"\n\"いか​ない。もし​か​し​たら、教会​から​あの​怪物​を​追い払っ​た​後​に、少し​だけ​貧しい​農夫​\"\n\"を​助け​て​くれ​ない​か？\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"ワァー​! (​鼻息​)​ワァーッ​! (​鼻息​)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"テオ​が​い​なく​なっ​ちゃっ​た！ 親友​だっ​た​の​に！ 川​の​そば​で​遊ん​で​たら、テオ​が​大き\"\n\"な​緑​の​もの​を​見​に​行き​たい​って​言っ​た​の。 ダメ​って​言っ​た​の​に、こっそり​行っ​ちゃっ​\"\n\"た​の。そ​し​たら​突然、虫​が​出​て​き​て！ 逃げ​た​けど、テオ​が​転ん​じゃっ​て、その​虫​に​掴\"\n\"ま​れ​ちゃっ​て​連れ​て​行か​れ​た​の！\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"彼​を​見つけ​た？ テオ​を​見つけ​て！お願い！ まだ​小さい​の。 自分​の​世話​も​でき​ない​の​\"\n\"よ！ お願い​だ​から！\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"見つけ​た！ テオ​を​見つけ​た！ ありがとう！ ああ、テオ、あの​ひどい​虫​たち​に​怖​がら​\"\n\"せ​られ​た​の？ ねえ！ うわ！ 毛皮​に​何​か​くっつい​てる​よ！ きもち​わるい！ さあ、テ\"\n\"オ、帰ろう！ もう​一度​ありがとう、ヒーロー​さん！\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"長き​眠り​から​我々​は​ついに​目覚める​時​が​来​た。\\n\"\n\"​長い​眠り​の​後、我々​は​大いなる​飢え​に​満ち​て​いる。\\n\"\n\"​もう​すぐ、その​飢え​を​満たす​時​が​来る​だろう​…\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"楽しん​で​いる​の​か、小さな​哺乳類​よ？ なん​と​哀れ​な​こと​だ。貴様​の​小さな​世界​など、\"\n\"我々​に​とっ​て​何​の​挑戦​に​も​なら​ぬ。\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"この​地​は​汚さ​れ、我々​の​種族​は​人間​が​故郷​と​呼ぶ​野​を​蹂躙​する​だろう。我々​の​触手​は​\"\n\"この​世界​を​包み込み、そこ​に​住む​人々​の​肉​を​食らう​だろう。 人間​は​我々​の​家畜​と​な\"\n\"り、糧​と​なる​の​だ。\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"ああ、お前​の​匂い​が​する​…​近く​に​いる​な​! 近い​! す​ぅ​ー​…​血​と​恐怖​の​香り​…​なんて​魅力的​\"\n\"な​こと​か​…。\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"そして、黄金​の​光​の​年​に、偉大​な​大聖堂​を​建てる​こと​が​決定​さ​れ​た。 その​礎​と​なる​の​\"\n\"は、ホラドリム​と​力​を​分かち合っ​た​天使​の​名​を​冠し​た​半透明​の​石​「​アンティ​ラエル​」​\"\n\"で​あっ​た。 \\n\"\n\" \\n\"\n\"​影​を​描く​年​に、地面​が​揺れ、大聖堂​は​粉々​に​なっ​て​落ち​た。 地下墓地​や​城​の​建設​が​始\"\n\"まり、人間​が​罪​の​戦争​の​荒廃​に​立ち向かう​よう​に​なる​と、廃墟​は​石​を​拾い集め​られ​\"\n\"た。 そして、その​礎石​は​人間​の​目​から​消え​て​しまっ​た。\\n\"\n\" \\n\"\n\"​その​石​は​この世​の​もの​で​あり、すべて​の​世界​の​もの​で​あり、光​が​すべて​の​もの​の​中​に​\"\n\"あり、すべて​の​もの​を​超え​て​いる​よう​に。光​と​統一性​は、この​聖​なる​礎​の​産物​で​あ\"\n\"り、目的​の​統一​と​所有​の​統一​で​ある。\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"モー。\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"俺​が​言っ​た​の​は、モー​だ。\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"ほら、俺​は​ただ​の​牛​な​ん​だ、分かっ​た？\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"はい​はい、分かっ​た。俺​は​実際​に​は​牛​じゃ​ねぇ​ん​だ。普段​は​こんな​格好​で​出歩く​こと​\"\n\"は​ねぇ​ん​だ​けど、家​で​自分​の​こと​を​し​て​たら、突然​床​から​虫​や​つる​植物、球根​なんか​\"\n\"が​出​て​き​て​…​…​もう​大変​だっ​た​ぜ！普通​の​服​が​あれ​ば、こんな​こと​に​は​なら​なかっ​た​の​\"\n\"に​な。おい！俺​の​ところ​に​戻っ​て、スーツ​を​取っ​て​き​て​くれ​ねぇ​か？茶色​の​やつ​で、\"\n\"グレー​の​は​ダメ​だ、あれ​は​夜​用​な​ん​だ​から。自分​で​行き​たい​ところ​だ​けど、こんな​姿​\"\n\"を​見​られ​たく​ねぇ​ん​だ。はい、これ​を​どうぞ、役​に​立つ​か​も​しれ​ねぇ​…​…​あの、すべて​\"\n\"を​覆い​尽くし​てる​や​つら​を​倒す​ため​に​な。俺​の​家​は​見逃す​こと​は​ねぇ、川​の​分かれ道​\"\n\"の​すぐ​南​だ​…​…​そう、あの​育ち​すぎ​た​野菜​庭​が​ある​家​だ。\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"なに​時間​を​無駄​に​し​て​ん​だ？俺​の​スーツ​を​取り​に​行け​よ！早く！あそこ​の​ホルスタイ\"\n\"ン​が​俺​に​ウインク​し​てる​ん​だ！\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"おい、俺​の​スーツ​は​持っ​てる​か？早く、渡し​て​くれ！この​耳​が​信じ​られ​ない​くらい​か\"\n\"ゆい​ん​だ！\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"いやいや​いやいや！これ​は​俺​の​グレー​の​スーツ​だ！夜​用​な​ん​だ​よ！フォーマル​な​場​に​\"\n\"着る​やつ​だ！俺​は​これ​を​着​られ​ねぇ。お前、変​な​奴​か？俺​が​必要​な​の​は​茶色​の​スーツ​\"\n\"だ。\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"おお、ずいぶん​良く​なっ​た​な。ふぅ！やっと​少し​は​威厳​が​戻っ​た​ぜ！俺​の​ツノ​は​真っ\"\n\"直ぐ​か？いい​感じ​だ。ほら、手伝っ​て​くれ​て​本当​に​ありがとう​な。これ、お礼​と​し​て​\"\n\"受け取っ​て​くれ。それ​と、ちょっと​し​た​ファッション​の​アドバイス​な​ん​だ​が​…​少し​新し\"\n\"い​の​が​必要​か​も​な​…​わかる​だろ？その​冒険者​の​モチーフ​は​さ​…​ちょっと​レトロ​すぎる​\"\n\"ぜ。まあ、一言​の​アドバイス​って​こと​で​な？じゃあ​な。\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"ほら、俺​は​牛​だ。お前​は​モンスター​の​餌​だ​な。もう​少し​経験​を​積ん​で​こい！そ​し​たら​\"\n\"また​話そう​ぜ​…\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"お前​に​は​本当​に​恐ろしい​任務​を​与え​ちまっ​た​よう​だ​な。俺​に​できる​こと​と​いえ​ば​…​新鮮​\"\n\"な​ミルク​を​一杯​どう​だ？\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"お前​の​助け​が​欲しい​ところ​だ​が、まず​は​あの​獣​ども​から​カタコンベ​を​救っ​て​から​に​し​\"\n\"て​くれ。\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"頼み​たい​こと​が​ある​ん​だ​が、全く​の​他人​に​頼む​の​は​気​が​引ける​な。もう​少し​ここ​に​留\"\n\"まる​なら、お​願い​し​やすく​なる​か​も​しれ​ん。\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"お前​に​は​偉大​な​可能性​が​ある​と​見​て​いる。運命​を​全う​し​て​いる​間​に、ちょっと​し​た​頼\"\n\"み​を​聞き​に​寄っ​て​くれ​ない​か？\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"お前​なら​助け​て​くれ​そう​だ​が、もう​少し​力​を​つけ​て​から​の​方​が​いい​か​も​な。この​村​の​\"\n\"教会​に​潜む​脅威​を​打破​する​唯一​の​チャンス​を​傷つけ​たく​は​ない​から​な！\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"俺​は​自分​で​成り上がっ​た​牛​さ。お前​も​何​か​を​成し遂げ​て​から、また​話そう​ぜ。\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"通りすがり​の​旅人​に​説明​する​必要​なんて​ない​だろ！ 殺す​べき​モンスター​は​い​ない​の​か​\"\n\"よ？ 後​で​話そう​ぜ。 あんた​が​生き​て​いれ​ば​な​…\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"うるせぇ​な。俺​は​本当​に​ヒーロー​らしい​奴​を​探し​てる​ん​だ。お前​じゃ​ねぇ。お前​は​信\"\n\"頼​でき​ねぇ、モンスター​に​食わ​れる​の​も​時間​の​問題​だ​な​…​俺​に​は​経験​豊富​な​ヒーロー​が​\"\n\"必要​な​ん​だ​よ。\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"よし、無駄​な​話​は​やめる​ぜ。お前​を​誤解​さ​せる​つもり​は​なかっ​た​ん​だ。俺​は​家​で​くつ\"\n\"ろい​で​い​た​時、いきなり​変​に​なっ​て、モンスター​の​大群​が​床​から​出​て​き​た​ん​だ！俺​は​\"\n\"ただ​驚い​て​た。ドア​を​飛び出す​時​に​この​ジャージ​を​着​て​た​から、今​は​まったく​馬鹿​み\"\n\"たい​な​格好​に​なっ​てる。普通​の​服​が​あれ​ば、こんな​に​ひどく​は​ない​ん​だ​が。おい！俺​\"\n\"の​スーツ​を​取り​に​家​まで​戻っ​て​くれ​ない​か？茶色​の​やつ​な、グレー​の​は​夜​用​だ​から。\"\n\"自分​で​取り​に​行く​気​は​ある​けど、こんな​姿​を​誰​か​に​見​られ​たく​ない​ん​だ。ほら、これ​\"\n\"を​持っ​て​いけ、あいつ​ら​を​倒す​の​に​役立つ​か​も​しれ​ない​から。俺​の​家​は、川​の​分岐点​\"\n\"の​南​に​ある​から、すぐ​分かる​ぜ​…​ほら​…​野菜​畑​が​茂っ​てる​やつ​だ。\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"呪文、脅し、魔術、交渉​を​試み​まし​た​が、この​汚い​生き物​に​は​効果​が​あり​ませ​ん。 小​\"\n\"悪魔​を​奴隷​に​し​た​手法​も、この​恐ろしい​獣​に​は​効果​が​ない​よう​です。\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"私​の​家​は、この​望ま​れ​ざる​囚人​の​悪意​に​よっ​て、ゆっくり​と​堕落​し​て​いく。 墓場​に​\"\n\"は、私​の​視界​の​隅​で​動く​影​が​たくさん​ある。 かすか​な​爪​の​音​が​私​の​聴覚​の​端​で​踊っ​て​\"\n\"いる。彼​ら​は、この​日記​を​探し​て​いる​の​だ​と​思う。\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"怒号​の​中、その​生物​は​自分​の​名前​を​漏らし​た​—​ナ​・​クルル。 私​は​その​名前​を​調べよう​\"\n\"と​し​た​が、小​悪魔​たち​が​何​ら​か​の​方法​で、私​の​図書館​を​破壊​し​て​しまっ​た。 ナ​・​クル\"\n\"ル​…。その​名​は​私​を​冷たい​恐怖​で​満たし​た。 本当​の​名前​で​考える​より​も、”​クリー\"\n\"チャー “​と​しか​考え​たく​ない。\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"閉じ込め​られ​た​生物​の​怒り​の​遠吠え​で、ほとんど​眠る​こと​が​でき​ない。 それ​は、自分​\"\n\"を​ボイド​に​送っ​た​者​に​対する​怒り​で​あり、自分​を​ここ​に​閉じ込め​た​私​に​対する​汚い​呪\"\n\"い​の​言葉​で​ある。 その​言葉​は​私​の​心​を​恐怖​で​満たす​が、その​声​を​遮断​する​こと​は​でき​\"\n\"ない。\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"私​の​時間​は​すぐ​に​尽き​て​しまう。 悪魔​を​弱める​方法​を​記録​し​た​書物​を​隠さ​なけれ​ば​な\"\n\"ら​ない。悪魔​の​手下​が、私​の​知識​を​使っ​て​主君​を​解放​する​方法​を​見つけ​ない​よう​に。 \"\n\"この​日記​を​見つけ​た​人​が、その​知識​を​求め​て​くれる​こと​を​願っ​て​いる。\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"この​巻物​を​見つけ​た​者​は、この​壁​の​中​に​潜む​悪魔​の​よう​な​生き物​を​止める​責任​が​あ\"\n\"る。 私​の​時代​は​終わっ​た。今​も​その​悪魔​の​手下​たち​は、私​が​隠れ​て​いる​弱い​扉​を​引っ\"\n\"掻い​て​いる。 \\n\"\n\" \\n\"\n\"​私​は​魔術​で​悪魔​を​操り、大きな​壁​の​中​に​閉じ込め​た​が、それ​だけ​で​は​不十分​だ​と​思\"\n\"う。\\n\"\n\" \\n\"\n\"3​つ​の​魔道​書​に​ある​呪文​は、正しい​順序​で​唱え​た​場合​に​のみ。やつ​の​領域​へ​の​入口​を​開\"\n\"く。 入口​に​ある​レバー​は​障壁​を​取り除き、悪魔​を​解放​する。 それ​に​触れ​て​は​なら​\"\n\"ぬ！呪文​を​使っ​た​後​で​なけれ​ば、やつ​の​力​が​強大​すぎ​て​倒せ​ない​だろう。\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"ヘルボア\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"スティンガー\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"サイコ​-​ブ\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"アラクノン\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"フェルト​ウィン\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"ホーク​・​スポーン\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"ヴェノム​テール\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"ネクロモーブ\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"スパイダー​・​ロード\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"ラッシュ​ワーム\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"トーチャント\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"ヘルバグ\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"グレイブディガー\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"トゥーム​・​ラット\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"ファイヤー​バット\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"スカル​ウィング\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"リッチ\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"クリプト​・​デーモン\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"ヘルバット\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"ボーン​デーモン\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"アーチ​・​リッチ\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"バイク​ロップス\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"フレッシュ​・​シング\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"リーパー\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"ジャイアント​・​ナックル\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"マーキュリアルリング\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"キソリーヌ​の​指輪\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"カリック​の​指輪\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"リング​・​オブ​・​マグマ\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"リング​・​オブ​・​ザ​・​ミスティック\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"リング​・​オブ​・​サンダー\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"結界​の​アミュレット\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"グナートスティング\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"フランボー\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"アーマー​・​オブ​・​グローム\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"ブリッツェン\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"サンダークラップ\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"白​太刀\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"イーター オブ ソウルズ\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"ダイヤモンド​エッジ\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"ボーン​チェーン​・​アーマー\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"デーモン​・​プレート​・​アーマー\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"アコライト​の​アミュレット\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"グラディエーターズ​・​リング\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"ジェス​ターズ\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"結晶\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"ドッペルゲンガーズ\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"壊滅\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"崩壊\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"ペリル\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"マナ\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"ザ​・​マギ\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"ザ​・​ジェスター\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"ライトニング​ウォール\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"イモレーション\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"ワープ\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"リフレクト\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"バーサク\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"リングオブファイヤー\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"サーチ\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"ルーン​・​オブ​・​ファイヤー\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"ライト​・​オブ​・​ルーン\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"ルーン​・​オブ​・​ノヴァ\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"ルーン​・​オブ​・​イモレーション\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"ルーン​・​オブ​・​ストーン\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Adria Refills Mana\"\n#~ msgstr \"エイドリア​の​マナ​補充\"\n\n#~ msgid \"Adria will refill your mana when you visit her shop.\"\n#~ msgstr \"エイドリア​の​店​を​訪れる​と、マナ​を​補充​し​て​くれ​ます。\"\n\n#~ msgid \"Enable floating numbers\"\n#~ msgstr \"浮動​小数​点数​を​有効​に​する\"\n\n#~ msgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\n#~ msgstr \"経験値​や​ダメージ​など​に​浮動​小数​点数​を​使用​する。\"\n\n#~ msgid \"Off\"\n#~ msgstr \"オフ\"\n\n#~ msgid \"Random Angles\"\n#~ msgstr \"ランダム​アングル\"\n\n#~ msgid \"Vertical Only\"\n#~ msgstr \"垂直​のみ\"\n\n#~ msgid \"Griswold the Blacksmith\"\n#~ msgstr \"鍛冶屋​の​グリズウォルド\"\n\n#~ msgid \"Pepin the Healer\"\n#~ msgstr \"治療​師​の​ペピン\"\n\n#~ msgid \"Wounded Townsman\"\n#~ msgstr \"傷つい​た​住人\"\n\n#~ msgid \"Ogden the Tavern owner\"\n#~ msgstr \"宿屋​の​オグデン\"\n\n#~ msgid \"Cain the Elder\"\n#~ msgstr \"語り部​の​ケイン\"\n\n#~ msgid \"Adria the Witch\"\n#~ msgstr \"魔女​の​エイドリア\"\n\n#~ msgid \"Gillian the Barmaid\"\n#~ msgstr \"ウェイトレス​の​ジリアン\"\n\n#~ msgid \"Cow\"\n#~ msgstr \"牛\"\n\n#~ msgid \"Lester the farmer\"\n#~ msgstr \"農家​の​レスター\"\n\n#~ msgid \"Celia\"\n#~ msgstr \"セリア\"\n\n#~ msgid \"Complete Nut\"\n#~ msgstr \"コンプリート​・​ナット\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"ガンマ​値​を​下げる\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"ガンマ​値​を​上げる\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"町​から​やり直す\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"フロア​アイテム​を​落とそう​と​し​て​いる​の​か？\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"垂直​同期​を​強制的​に​待ち​ます。フレーム​描画​時​の​ティア​リング​を​防止​し​ます。これ​\"\n#~ \"を​無効​に​する​と、システム​に​よっ​て​は​マウス​の​遅延​が​改善​さ​れる​こと​が​あり​ます。\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"FPS​リミッター\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"CPU​負荷​が​高く​なら​ない​よう​に​FPS​を​制限​し​ます。制限​は​リフレッシュ​レート​を​考慮​\"\n#~ \"し​て​い​ます。\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"命中​率\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"ハート\"\n\n#~ msgid \"/help\"\n#~ msgstr \"/help\"\n\n#~ msgid \"/arena\"\n#~ msgstr \"/arena\"\n\n#~ msgid \"/arenapot\"\n#~ msgstr \"/arenapot\"\n\n#~ msgid \"/inspect\"\n#~ msgstr \"アリーナ​ポーション​を​与える。\"\n\n#~ msgid \"/seedinfo\"\n#~ msgstr \"/seedinfo\"\n\n#~ msgid \"Command \\\"\"\n#~ msgstr \"コマンド “\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"壊れ​ない​,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"必要​能力:​無し\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"今日​は​曇っ​て​い​て​涼しい。 虚空​に​死​霊術​の​網​を​張っ​て、空​飛ぶ​ホラー​の​新しい​亜\"\n#~ \"種​を​2​つ​見つけ​まし​た。 エイドリア​に​バット​グアノ​と​ブラック​キャンドル​を​注文​す\"\n#~ \"る​の​を​忘れ​て​ない​で。少し​足り​ない​から。\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"町中​で​は​オート​マップ​を​使え​ませ​ん\"\n\n#~ msgid \"({command})\"\n#~ msgstr \"(​{command}​)\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"英雄​の​広間​の​奥​に​は​納骨堂​が​ある。そこ​の​財宝​を​盗もう​と​する​者​に​は、永遠​の​死​が​\"\n#~ \"訪れる​だろう。恐怖​の​帝王​の​言葉​通り、そして​ここ​に​記さ​れ​て​いる​通り​に。\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"地獄​の​武器​庫​は​鮮血​の​将軍​の​棲み家。彼​が​目覚める​と​辺り​に​は​幾​千​の​死体​が​横た\"\n#~ \"わっ​て​い​た。天使​も​人間​も、血​のみ​を​求める​暗黒​の​支配者​へ​の​生け贄​と​し​て、次​か\"\n#~ \"ら​次​へ​と​切り裂か​れ​て​いっ​た。\"\n\n#~ msgid \"left-click to target\"\n#~ msgstr \"左​クリック​で​ターゲット\"\n\n#~ msgid \"cast spell to read\"\n#~ msgstr \"スペル​を​かける。\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"ライフ​を​回復​でき​ない\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"攻撃​を​受け​た​モンスター​は​回復​でき​ない\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"早い​攻撃​準備\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"インフラ​ビジョン​の​効果\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"version {:s}\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"ライフ​の​回復\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"デッドリー​ヒール\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"STR を​減少\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"DEX を​減少\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"VIT を​減少\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Failed to open player archive for writing.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Unable to read to save file archive\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Unable to write to save file archive\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"オプション:\"\n\n#~ msgid \"Right click to read\"\n#~ msgstr \"右​クリック​で​読む\"\n"
  },
  {
    "path": "Translations/ko.po",
    "content": "# Translation of DevilutionX to Korean\n# @nsm53project, 2021.\n# @bcko, 2021.\n# @cholovesdata, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: NSM53PROJECT <nsm53project@gmail.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: ko\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"게임 디자인\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"수석 디자이너\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"추가 디자인\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"책임 프로그래머\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"수석 프로그래머\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"프로그래밍\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"특별 초빙 프로그래머\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"배틀넷 프로그래밍\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"직렬 통신 프로그래밍\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"인스톨러 프로그래밍\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"미술 연출\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"삽화\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"기술 삽화\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"영상 미술 연출\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D 영상 삽화\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"영상 기술 삽화\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"총괄 제작\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"제작\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"제작보\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"디아블로 스트라이크 팀\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"음악\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"음향 설계\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"영상 음악 & 음향\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"성우 프로덕션, 제작 & 섭외\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"대본\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"음성 편집\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"성우\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"녹음 기술\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"메뉴얼 디자인 및 레이아웃\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"메뉴얼 삽화\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"QA 임시 연출 (책임 테스터)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA 유격대 (테스터)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA 특수 작전조 (호환성 테스터)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA 포격 지원 (추가 테스터) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA 방첩대\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"네트워크 정보 서비스 관리\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"고객 지원\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"판매\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"바지사장\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"다비리 씨의 백보컬\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"홍보\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"마케팅\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"해외 판매\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"U.S. 판매\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"제조\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"법무 & 사업부문\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"특히 감사한 분들\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"감사한 분들\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"이들을 추모하며\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"너무나도 특히 감사한 분들\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"총관리\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"소프트웨어 기술\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"미술 연출\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"미술\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"디자인\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"음향 설계, SFX & 기술\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"품질 보증 책임\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"테스터\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"매뉴얼\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\t추가 작업\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"퀘스트 대본 작성\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"감사한 분들\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\t정말 고마워요, 블리자드 엔터테인먼트\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\t시에라 온라인 주식회사. 노스웨스트\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"품질 보증 관리\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"품질 보증 책임 테스터\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"주요 테스터\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"추가 테스터\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"제품 마케팅 관리\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"홍보 관리\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"제품 관리보\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"천의 반지\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\t이 게임 제작에 영혼을 팔지는 않았다.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"결정\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"직업 선택\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"취소\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"새로운 멀티 플레이어 영웅\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"새로운 싱글 플레이어 영웅\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"기존 저장 파일 존재\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"게임 불러오기\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"새로운 게임\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"싱글 플레이어 캐릭터\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"도적과 마법사는 디아블로 정품에서만 사용할 수 있습니다. https://www.gog.com/\"\n\"game/diablo 에서 구매할 수 있습니다.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"이름 입력\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"잘못된 이름입니다. 이름에는 공백이나 특수 문자를 사용할 수 없습니다.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"캐릭터 생성이 불가능합니다.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"레벨:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"힘:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"마력:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"민첩:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"활력:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"게임 저장하기:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"영웅 선택\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"새로운 영웅\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"삭제\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"멀티 플레이어 캐릭터\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"멀티 플레이어 영웅 삭제\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"싱글 플레이어 영웅 삭제\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"\\\"{:s}\\\" 캐럭터를 정말로 삭제하겠습니까?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"싱글 플레이어\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"멀티 플레이어\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"설정\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"지원\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"제작진 보기\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"헬파이어 종료\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"디아블로 종료\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"체험판\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"클라이언트-서버 (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"오프라인\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"멀티 플레이어 게임\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"요구사항:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"게이트웨이 필요 없음\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"연결 선택\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"게이트웨이 변경\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"모든 컴퓨터는 TCP 호환 네트워크에 연결되어 있어야 합니다.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"모든 컴퓨터는 인터넷에 연결되어 있어야 합니다.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"네트워크 공개 없이 혼자서 즐깁니다.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"지원되는 플레이어: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"디아블로\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"디아블로 체험판\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"헬파이어\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"헬파이어 체험판\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"실행하는 게임이 호스트와 다릅니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"실행하는 게임 모드 ({:s})이(가) 호스트와 다릅니다.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"현재 버전 {:s}이 호스트 {:d}.{:d}.{:d}와 맞지 않습니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"설명:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"메뉴 선택\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"게임 생성\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"공개 게임 생성\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"게임 참여\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"공개 게임\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"불러오는 중...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"없음\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"취소\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"선택한 난이도 설정으로 새 게임을 생성합니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"선택한 난이도 설정으로 누구나 참여할 수 있는 새 공개 게임을 생성합니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"진행 중인 게임에 참여하려면 게임 ID를 입력해 주세요.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"진행 중인 게임에 참여하려면 IP나 호스트명을 입력해 주세요.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"진행 중인 게임에 참여합니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"보통\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"악몽\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"지옥\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"난이도: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"속도: 보통\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"속도: 빠르게\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"속도: 아주 빠르게\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"속도: 가장 빠르게\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"플레이어: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"난이도 선택\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"{:s} 게임 참여\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"게임 ID 입력\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"주소 입력\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"보통 난이도\\n\"\n\"초보자는 이 난이도에서 디아블로를 쓰러트리기 위한 퀘스트를 시작해야 합니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"악몽 난이도\\n\"\n\"미궁의 괴물들이 강회되었으므로 더 큰 도전이 될 것입니다. 숙련자에게 권장합니\"\n\"다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"지옥 난이도\\n\"\n\"황천에서 가장 강한 괴물들이 지옥으로 가는 문에 도사리고 있습니다. 경험이 풍부\"\n\"한 사람만이 이러한 곳으로 모험을 떠날 수 있습니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"악몽 난이도 멀티 플레이어 게임에 참여하려면 레벨 20에 도달해야 합니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"지옥 난이도 멀티 플레이어 게임에 참여하려면 레벨 30에 도달해야 합니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"게임 속도 선택\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"빠르게\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"매우 빠르게\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"가장 빠르게\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"보통 속도\\n\"\n\"초보자는 이 속도에서 디아블로를 쓰러트리기 위한 퀘스트를 시작해야 합니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"빠른 속도\\n\"\n\"미궁의 괴물들이 강회되었으므로 더 큰 도전이 될 것입니다. 숙련자에게 권장합니\"\n\"다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"매우 빠른 속도\\n\"\n\"던전에 있는 대부분의 괴물들이 그 어느 때보다 재빨리 당신을 찾아낼 것입니다. \"\n\"숙련된 챔피언만이 이 속도에서 행운을 시험할 수 있습니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"가장 빠른 속도\\n\"\n\"황천의 하수인들이 가차없이 공격을 가해 옵니다. 진정한 속도광만이 이 속도를 감\"\n\"당할 수 있을 것입니다.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"패스워드 입력\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"헬파이어 입장\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"디아블로로 변경\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"예\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"아니요\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"적용하려면 게임패드의 아무 버튼이나 눌러 주세요.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"키 지정:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"적용하려면 아무 키나 눌러 주세요.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"키 지정 해제\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"버튼 콤보 지정:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"버튼 콤보 해제\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"이전 메뉴\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Discord.gg/devilutionx에 채팅 서버를 개설해 놓았습니다. 링크를 따라 커뮤니티\"\n\"에 가입하여 디아블로와 헬파이어 확장팩에 관해 이야기를 나누세요.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX는 Diasurgical이 관리하며 문제 및 버그를 보고 받습니다 주소는 다음\"\n\"과 같습니다: https://github.com/diasurgical/devilutionX 더 나은 서비스를 제공\"\n\"을 위해 버전 정보, 운영체제, 문제 유형을, 포함해 주시기 바랍니다.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"책임 부인:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX는 Blizzard Entertainment에서 지원받거나 운영되지 않습니다, \"\n\"GOG.com 또한 마찬가지입니다. Blizzard Entertainment와 GOG.com은 DevilutionX\"\n\"의 품질 또는 호환성을 테스트하거나 인증하지 않았습니다 DevilutionX에 관한 문\"\n\"의 일체는 Blizzard Entertainment나 GOG.com이 아닌 Diasurgical에 해야 합니다.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\t이 포팅은 SIL Open Font License에 의해 허가된 Charis SIL, New Athena \"\n\"Unicode, Unifont, Noto와 CC-BY 4.0에 의해 허가된 Twitmoji를 사용합니다. 또한 \"\n\"zlib-license에 의해 허가된 SDL을 사용합니다. 자세한 내용은 ReadMe를 참조하세\"\n\"요.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"에러\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"오류 발생: {:s} 줄 {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"데이터 파일 오류\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"메인 데이터 아카이브({:s})\\n\"\n\"\\n\"\n\"게임 폴더 안에 있는지 확인해 주십시오.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"읽기 전용 디렉토리 오류\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"다음 위치에 기록할 수 없습니다:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"게임: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"오프라인 게임\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"패스워드: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"공개 게임\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"둥지 지하 {:d}층\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"지하성당 지하 {:d}층\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"마을\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"지하 {:d}층\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"탭\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"ESC\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"엔터\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"캐릭터 정보\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"퀘스트 기록\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"지도\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"메인 메뉴\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"소지품\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"주문서\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"메시지 보내기\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"사용 가능한 명령어:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"명령어 \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" 은(는) 알 수 없는 명령어입니다.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"설명: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"매개변수: 추가 매개변수가 필요하지 않습니다.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"매개변수: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"투기장은 멀티플레이어만 지원됩니다.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"방문하고 싶은 투기장은 어느 곳입니까?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"잘못된 투기장 번호입니다. 올바른 번호:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"투기장에 입장하려면 마을이나 다른 투기장에 있어야 합니다.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"플레이어 상태 확인은 멀티플레이어에서만 가능합니다.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"플레이어 상태 확인을 중단했습니다.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"해당 이름의 플레이어를 찾을 수 없습니다\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"플레이어 상태 확인: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"도움말 개요 또는 특정 명령어의 도움말을 표시합니다.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[명령어]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"PvP 투기장에 입장합니다.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<arena-number>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"투기장 물약을 제공합니다.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<number>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"다른 플레이어의 상태와 장비를 확인합니다.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<player name>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"현재 레벨의 대진 정보를 표시합니다.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"우호\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"적대\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"단축키: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"현재 주문 버튼 선택\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"단축키: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} 기술\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} 주문\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"주문 레벨 0 - 사용 불가\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"주문 레벨 {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"{:s} 두루마리\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} 두루마리\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"{:s} 지팡이\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d}회 충전\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"금화 {:s}개\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"요구 사항 미충족\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, 레벨: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"히트 포인트 {:d} / {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"우클릭으로 사용\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"레벨업\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"금화 {:s}개를 갖고 있습니다. 몇 개를 버리겠습니까?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"마을 차원문\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"생성자: {:s}\"\n\n# 조합 확인 필요\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"차원문\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"불경한 제단\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"지하 15층\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"캐릭터를 불러올 수 없습니다\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"이 메시지를 출력하고 종료\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"버전을 출력하고 종료\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"diabdat.mpq가 있는 폴더 지정\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"저장 파일 폴더 지정\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"diablo.ini의 경로 지정\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"언어 코드 지정 (e.g. en 또는 pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"실행 시 오프닝 재생 안 함\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"초당 프레임 표시\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"상세한 기록 사용\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"데모 파일 기록\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"데모 파일 플레이\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"데모 플레이 프레임 제한 해제\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"게임 선택:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"강제 체험판 모드\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"강제 디아블로 모드\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"강제 헬파이어 모드\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"헬파이어 설정:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"https://github.com/diasurgical/devilutionX/ 에 버그 리포트하기\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"최신 버전으로 devilutionx.mpq와 fonts.mpq를 업데이트 해 주십시오\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"UI 리소스를 불러오지 못했습니다.\\n\"\n\"\\n\"\n\"Devilutionx.mpq가 게임 폴더 내에 있고 최신 상태인지 확인해 주세요.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"최신 버전으로 fonts.mpq를 업데이트 해 주십시오\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- 네트워크 시간 초과 --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- 플레이어 대기 중 --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"상점에서는 도움을\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"받을 수 없습니다\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"벨트 물품 {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"벨트 물품을 사용합니다.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"빠른 주문 {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"기술이나 주문용 단축키입니다.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"이전 메뉴\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"빠른 주문 {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"생명력 회복 물약 사용\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"벨트에서 생명력 회복 물약을 사용합니다.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"마나 회복 물약 사용\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"벨트에서 마나 회복 물약을 사용합니다.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"신속서\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"신속서를 엽니다.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"빠른 저장\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"게임을 저장합니다.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"빠른 불러오기\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"게임을 불러옵니다.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"게임 종료\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"게임을 종료합니다.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"영웅 멈추기\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"이동을 멈추고 진행할 행동을 취소합니다.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"물품 강조 표시\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"바닥에 있는 물품 표시 여부를 설정합니다.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"물품 강조 표시 설정\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"바닥에 있는 물품의 상시 표시 여부를 설정합니다.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"지도 설정\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"지도 표시 여부를 설정합니다.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"소지품 화면을 엽니다.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"캐릭터\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"캐릭터 화면을 엽니다.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"퀘스트 기록\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"퀘스트 기록을 엽니다.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"주문서\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"주문서를 엽니다.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"빠른 메시지 {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"채팅에서 빠른 메시지를 사용합니다.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"정보창 숨기기\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"정보창을 표시하지 않습니다.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"확대\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"게임 화면을 확대합니다.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"게임 일시 정지\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"게임을 일시 정지합니다.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"게임 일시 정지\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"화면 밝기를 높입니다.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"화면 밝기를 낮춥니다.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"화면 밝기를 높입니다.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"화면 밝기를 높입니다.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"도움말\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"도움말 화면을 엽니다.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"스크린샷\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"스크린샷을 찍습니다.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"게임 정보\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"게임 정보를 표시합니다.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"채팅 기록\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"채팅 기록을 표시합니다.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"소지품\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"주요 행동\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"괴물 공격, 마을 주민과 대화, 소지품 관리 등의 행동입니다.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"부가 행동\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"상자 열기, 문 여닫기, 물품 습득 등의 행동입니다.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"주문 행동\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"활성화된 주문을 시전합니다.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"행동 취소\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"메뉴를 닫습니다.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"위로 이동\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"플레이어 캐릭터를 위로 이동합니다.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"아래로 이동\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"플레이어 캐릭터를 아래로 이동합니다.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"왼쪽으로 이동\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"플레이어 캐릭터를 왼쪽으로 이동합니다.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"오른쪽으로 이동\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"플레이어 캐릭터를 오른쪽으로 이동합니다.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"제자리 서있기\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"버튼을 누르고 있으면 플레이어가 움직이지 않습니다.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"제자리 서있기 전환\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"플레이어의 이동 여부를 전환합니다.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"지도\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"아래로 이동\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"왼쪽으로 이동\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"플레이어 캐릭터를 위로 이동합니다.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"오른쪽으로 이동\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"마우스를 위로 이동\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"마우스를 위로 이동을 시뮬레이트합니다.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"마우스를 아래로 아동\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"마우스를 아래로 이동을 시뮬레이트합니다.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"마우스를 왼쪽으로 이동\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"마우스를 왼쪽으로 이동을 시뮬레이트합니다.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"마우스를 오른쪽으로 이동\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"마우스를 오른쪽으로 이동을 시뮬레이트합니다.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"마우스 좌클릭\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"마우스 좌클릭을 시뮬레이트합니다.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"마우스 우클릭\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"마우스 우클릭을 시뮬레이트합니다.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"게임패드 빠른 주문 메뉴\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"길게 눌러 주문 단축키를 설정하거나 사용합니다.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"게임패드 메뉴 네이게이터\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"길게 눌러게임패드 메뉴 탐색에 접근합니다.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"게임 메뉴 전환\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"게임 메뉴를 엽니다.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"화염파\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"데모에서 멀티 플레이어 기능이 없습니다\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"다이렉스 사운드 생성 실패\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"셰어웨어 버전에서는 사용할 수 없습니다\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"저장할 공간이 충분하지 않습니다\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"마을에서는 일시 정지가 불가능합니다\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"하드 디스크에 복사하는 것이 필수입니다\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"멀티플레이어 동기화 장애\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"멀티플레이어는 일시 정지 불가\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"저장하는 중...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"강해지는 것이 있으면 약해지는 것도 있는 법이다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"새로운 힘은 파괴를 거쳐 단련된다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"때로는 방어가 공격이다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"정의의 검은 빠르고 날카롭다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"방심하지 않으면 육신을 건사할 수 있다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"마나의 힘이 새로이 다시 모인다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"강철의 힘은 시간으로도 막을 수 없다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"마법이 항상 눈에 보이는 것은 아니다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"열렸던 것이 지금 다시 닫힌다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"빛의 강렬함은 지혜의 희생으로 얻어진다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"신비한 힘이 파멸을 부른다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"잡을 수 없는 것은 해를 끼칠 수 없다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"붉은 빛과 푸른 빛은 태양이 된다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"지식과 지혜를 직접 희생한다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"마시고 기운 내라\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"어디를 가더라도 그대는 그대이다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"원기는 지혜의 희생으로 얻어진다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"부는 기대하지 않았을 때 찾아온다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"탐욕은 실패하고 인내는 보답받는다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"자비로운 동반자에게 축복받았다!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"사람의 손은 때때로 운명에 이끌린다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"힘은 신에 대한 신앙으로 북돋아진다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"생명의 본질은 그 내면에서 샘솟는다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"위에서 내려다볼 때 길은 명확해진다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"구원은 지식의 희생으로 이루어진다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"신비는 이치의 광명 아래 드러난다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"마지막 사람이 첫 번째일 수도 있다\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"관용은 언젠가 보답받는다\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"레벨 8 이상부터 사용할 수 있습니다.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"레벨 13 이상부터 사용할 수 있습니다.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"레벨 17 이상부터 사용할 수 있습니다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"신비한 지식을 습득했다!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"그대를 죽이려는 것이 아니다...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"아는 것이 힘이다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"가는 정이 있으면 오는 정이 있다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"촉감으로 얻는 경험도 있는 법이다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"집만한 곳이 없다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"영적 기운이 회복된다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"더 민첩해진 기분이다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"더 강해진 기분이다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"더 현명해진 기분이다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"상쾌한 기분이다.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"의지를 꺾을 수 있는 바로 그것.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"대성당\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"지하묘지\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"동굴\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"둥지\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"지하성당\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Lv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} 난이도\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"메뉴\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"루프백\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"접속 불가\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"오류: 서버로부터 0 바이트 수신\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq 또는 spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"헬파이어 관련된 일부 MPQ 파일들이 존재하지 않습니다\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"헬파이어 관련 모든 MPQ 파일들을 찾을수 없습니다.\\n\"\n\"hf*.mpq 파일들을 모두 복사해주세요.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"해상도\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"마을에서 뛰기\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"테오 퀘스트\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"젖소 퀘스트\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"금화 자동 입수\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"영약 자동 입수\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"기름 자동 입수\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"마을에서 자동 입수\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"마나 재충전\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"무기 자동 장비\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"갑옷 자동 장비\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"투구 자동 장비\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"방패 자동 장비\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"장신구 자동 장비\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"랜덤 퀘스트\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"물품명 표시\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"벨트 자동 보충\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"피해를 받는 신단 비활성\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"생명력 회복 물약 입수\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"생명력 완전 회복 물약 입수\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"마나 회복 물약 입수\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"마나 완전 회복 물약\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"회복 물약\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"완전 회복 물약\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"설정\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"게임 저장하기\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"메인 메뉴\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"게임 종료\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"밝기\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"속도\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"음악 끄기\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"효과음\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"효과음 끄기\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"일시 정지\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$키보드 단축키:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    도움말 화면 열기\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   게임 메뉴 표시\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"탭:   지도 표시\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"스페이스: 모든 정보 화면 숨기기\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: 신속서 열기\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: 주문서 열기\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: 소지품 화면 열기\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: 캐릭터 화면 열기\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: 퀘스트 기록 열기\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: 화면 밝기 감소\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: 화면 밝기 증가\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: 게임 화면 확대/축소\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: 지도 확대/축소\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: 벨트 물품 사용\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     기술이나 주문용 단축키 설정\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"시프트 + 마우스 왼쪽 버튼: 제자리에서 공격\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"시프트 + 마우스 왼쪽 버튼 (캐릭터 화면): 모든 능력치 할당\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"시프트 + 마우스 왼쪽 버튼 (소지품 화면): 물품을 벨트로 옮기거나 장비/해제\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"시프트 + 마우스 왼쪽 버튼 (벨트 화면): 소지품으로 물품 이동\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$이동:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"캐릭터가 움직이는 동안 마우스 버튼을 누르고 있으면, 계속 그 방향으로 이동합니\"\n\"다.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$전투:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Shift 키를 누른 상태에서 마우스 좌클릭은 캐릭터가 움직이지 않은 상태에서 공격\"\n\"을 가능하게 해줍니다.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$지도:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"지도를 표시하려면 정보창의 '지도' 버튼을 클릭하거나 'TAB' 키를 누릅니다. 지도\"\n\"의 확대와 축소는 +와 - 키를 사용하며 스크롤은 방향키를 사용합니다.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$물건 줍기:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"물약이나 두루마리와 같은 작은 크기의 물품은 인터페이스창 상단에 위치한 '벨\"\n\"트'에 자동으로 배치됩니다. 벨트에 물품을 배치하면 해당 칸에 작은 숫자가 표시\"\n\"됩니다. 해당 숫자를 누르거나 마우스 우클릭으로 사용할 수 있습니다.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$금화:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"소지품에서 금화 뭉치를 마우스 우클릭으로 지정한 만큼 떨굴 수 있습니다.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$기술과 주문:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"인터페이스창에서 '주문' 버튼을 마우스로 좌클릭하면 기술과 주문 목록을 볼 수 \"\n\"있습니다. 습득한 주문과 지팡이를 통해 사용할 수 있는 주문이 이곳에 표시됩니\"\n\"다. 시전할 주문을 마우스로 좌클릭하면 주문이 선택되며, 마우스 우클릭으로 전\"\n\"투 지역에서 시전할 수 있습니다.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$주문용 신속서 사용:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"'선택한 주문' 버튼을 마우스로 좌클릭하면 '신속서'가 열리며 즉시 사용할 기술이\"\n\"나 주문을 선택할 수 있습니다. 선택한 기술이나 주문의 사용은 주요 전투 지역에\"\n\"서 간단히 마우스를 우클릭하면 됩니다.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"'현재 선택한 주문' 버튼에서 Shift + 마우스 좌클릭을 하면 선택된 주문이 삭제됩\"\n\"니다.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$주문 단축키 설정:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"기술, 주문, 두루마리에 4개의 단축키를 할당할 수 있습니다. 이전 섹션에서 설명\"\n\"한 대로 '신속서'를 열어, 할당하려는 주문을 활성화 후 F5, F6, F7, F8 키 중 하\"\n\"나를 누릅니다.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$주문서:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"책을 읽으면 해당 주문에 대한 지식이 늘어 주문을 더욱 효과적으로 시전할 수 있\"\n\"습니다.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"체험판 헬파이어 도움말\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"헬파이어 도움말\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"체혐판 디아블로 도움말\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"디아블로 도움말\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"ESC를 눌러 종료하거나 방향키를 이용해 스크롤해 주세요.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"메인 윈도우를 생성할 수 없습니다\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"아이템을 넣을 공간이 없습니다\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"정확도의 기름\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"숙련의 기름\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"날카로움의 기름\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"죽음의 기름\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"기술의 기름\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"대장장이 기름\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"불굴의 기름\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"영구성의 기름\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"경화의 기름\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"불침투성의 기름\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{1}의 {0}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {2}의 {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {2}의 {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{1}의 {0}\"\n\n# 어순이 문제가 됨\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"무기 명중률\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"증가\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"무기 명중률\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"대폭 증가\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"대폭 증가\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"무기의 피해 가능성\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"대폭 증가 - 활 제외\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"갑옷이나 무기 사용에\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"필요한 요구치 감소\"\n\n# 정확한 문장 출력 확인 필요\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"물품 내구도\"\n\n# 정확한 문장 출력 확인 필요\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"20% 복구\"\n\n# 정확한 문장 출력 확인 필요\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"물품의 현재와 최대 내구도\"\n\n# 정확한 문장 출력 확인 필요\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"증가\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"물품이 파괴되지 않도록 만듦\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"갑옷과 방패의 방어력\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"증가\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"갑옷과 방패의 방어력\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"대폭 증가\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"화염 함정 설치\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"번개 함정 설치\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"석화 함정 설치\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"생명력 전체 회복\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"생명력 일부 회복\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"마나 일부 회복\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"마나 전체 회복\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"힘 증가\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"마력 증가\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"민첩 증가\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"활력 증가\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"생명력과 마나 일부 회복\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"생명력과 마나 전부 회복\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(투기장에서만 가능)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"우클릭으로 표시\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"우클릭으로 사용\"\n\n# 조합 방식 확인 필요\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"우클릭으로 읽고\\n\"\n\"좌클릭으로 목표 지정\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"우클릭으로 읽기\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"활성화해서 표시\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"사용할 소지품 열기\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"활성화해서 사용\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"주문서에서 선택 후\\n\"\n\"주문 시전\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"활성화해서 읽기\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} 표시\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} 사용\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"주문서에서 선택 후\\n\"\n\"{} 읽기\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} 읽기\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"지하 {:d}층\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"금화 수용력 두배\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"요구치:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} 힘\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} 마력\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} 민첩\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"주문서: {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s}의 귀\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"명중률: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% 피해\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"명중률: {:+d}%, {:+d}% 피해\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% 방어력\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"방어력: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"화염 저항: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"화염 저항: {:+d}% 최대치\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"번개 저항: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"번개 저항: {:+d}% 최대치\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"마법 저항: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"마법 저항: {:+d}% 최대치\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"전체 저항: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"전체 저항: {:+d}% 최대치\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"주문이 {:d} 레벨로 상승했다\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"주문이 {:d} 레벨로 하락했다\"\n\n# 확인 필요\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"변동 없는 주문 레벨 (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"충전 추가분\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} 충전\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"화염 피해: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"화염 피해: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"번개 피해: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"번개 피해: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"힘 {:+d}\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"마력 {:+d}\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"민첩 {:+d}\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"활력 {:+d}\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"모든 능력치 {:+d}\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} 적에게서 받는 피해\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"히트포인트: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"마나: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"높은 내구도\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"내구도 감소\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"영구적\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% 불빛 반경\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% 불빛 반경\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"한 번에 여러 발의 화살 쏘기\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"화염 화살 피해: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"화염 화살 피해: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"번개 화살 피해 {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"번개 화살 피해 {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"화염구 피해: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"화염구 피해: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"공격자가 피해를 1-3 받음\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"사용자가 모든 마나를 잃음\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"함정 피해 절반 흡수\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"목표물을 뒤로 밀침\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"악마 상대 시 +200% 피해\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"모든 저항 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"적중 시 마나 3% 흡수\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"적중 시 마나 5% 흡수\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"적중 시 생명력 3% 흡수\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"적중 시 생명력 5% 흡수\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"목표물의 갑옷을 관통\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"민첩한 공격\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"빠른 공격\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"매우 빠른 공격\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"가장 빠른 공격\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"또 다른 능력 (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"빠른 피해 회복\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"매우 빠른 피해 회복\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"가장 빠른 피해 회복\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"빠른 막기\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"피해에 {:d} 포인트 추가\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"무작위 속사\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"비정상적 물품 손상\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"내구도 변화\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"한손검\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"지속적인 히트 포인트 상실\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"생명력 흡수\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"힘 요구치 없음\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"번개 피해: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"번개 피해: {:d}-{:d}\"\n\n# 마법명 미확정\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"적중 시 돌격탄\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"가끔 3배의 피해\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"{:+d}% 피해 감소\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"괴물에게 2배, 본인에게 1배의 피해\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"0 - 600% 무작위 피해\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"낮은 내구도, {:+d}% 피해\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"악마 상대 시 추가 방어력\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"언데드 상대 시 추가 방어력\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"마나 50%를 생명력으로 전환\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"생명력 40%를 마나로 전환\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"피해: {:d}  영구적\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"피해: {:d}  내구도: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"피해: {:d}-{:d}  영구적\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"피해: {:d}-{:d}  내구도: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"방어력: {:d}  영구적\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"방어력: {:d}  내구도: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"충전: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"희귀 물품\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"미식별\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"해골왕의 본거지\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"뼈의 방\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"미로\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"오염된 수원\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"대주교 라자루스의 본거지\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"교회 투기장\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"지옥 투기장\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"생명의 고리 투기장\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"던전으로 내려간다\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"지하묘지로 내려간다\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"동굴로 내려간다\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"지옥으로 내려간다\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"중심부로 내려간다\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"지하성당으로 내려간다\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"지하 {:d} 층으로 올라간다\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"마을로 올라간다\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"지하 {:d} 층으로 내려간다\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"디아블로에게 향한다\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"둥지 지하 {:d} 층으로 올라간다\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"지하성당 지하 {:d} 층으로 올라간다\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"세계의 초석\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"지하성당 지하 {:d} 층으로 내려간다\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"지하 {:d} 층으로 돌아간다\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"세이브 파일을 열 수 없습니다\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"잘못된 저장 파일입니다\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"플레이어가 불지옥 전용 레벨에 있습니다\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"잘못된 게임 상태입니다\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"메인 메뉴를 표시할 수 없습니다\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"짐승\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"악마\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"언데드\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"종류: {:s}  토벌 수: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"총 토벌 수: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"히트 포인트: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"마법 저항 없음\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"저항:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" 마법\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" 화염\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" 번개\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"면역:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"종류: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"저항 없음\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"면역 없음\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"일부 마법 저항\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"일부 면역 저항\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"기록용 아카이브를 열지 못했습니다.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s}이(가) 확인되지 않은 주문을 시전했습니다.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s}이(가) 불법적인 주문을 시전했습니다.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"플레이어 '{:s}' (레벨 {:d})이(가) 게임에 참여했습니다\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"게임이 종료되었습니다\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"레벨 데이터를 가져올 수 없습니다\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"플레이어 '{:s}'이(가) 게임을 퇴장했습니다\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"플레이어 '{:s}'이(가) 디아블로를 물리치고 게임을 퇴장했습니다!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"플레이어 '{:s}'이(가) 시간초과로 퇴장되었습니다\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"플레이어 '{:s}' (레벨 {:d})은(는) 이미 게임에 참여 중입니다\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"신비한\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"비밀의\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"음침한\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"기이한\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"마법의\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"석조\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"경건한\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"매혹의\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"요술의\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"흥미로운\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"의문의\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"무시무시한\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"섬뜩한\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"거룩한\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"신성한\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"신성한\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"숭고한\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"으스스한\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"버려진\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"오싹한\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"고요한\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"호젓한\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"화려한\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"미광의\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"부패한\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"기름진\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"찬란한\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"탁발 수도사의\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"반짝이는\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"희미하게 빛나는\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"태양의\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"머피의\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"위대한 투쟁\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"죄악의 대가는 전쟁이다\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"호라드림 이야기\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"어둠의 대추방\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"죄악의 전쟁\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"세 대악마의 봉인\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"아득한 저편의 왕국\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"세 대악마 이야기\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"암흑의 왕\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"학술서: 마술\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"학술서: 회의\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"학술서: 장광설\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"학술서: 그의 힘의 증대\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"학술서: 나-크룰\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"학술서: 종말\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"주문서\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"못 박힌 해골\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"지렛대\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"열린 문\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"닫힌 문\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"잠긴 문\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"고대서\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"비열의 서\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"해골 지렛대\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"신화서\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"작은 궤짝\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"궤짝\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"큰 궤짝\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"석관\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"책장\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"책장\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"나무통\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"고치\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"단지\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} 신단\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"해골 고서\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"도서\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"피의 분수\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"참수된 시체\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"눈먼 자의 서\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"피의 서\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"정화의 활기\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"갑옷\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"무기 거치대\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"염소 신단\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"가마솥\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"탁한 웅덩이\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"눈물의 샘\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"강철 고서\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"피의 받침대\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"버섯 군락\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"비열한 진열대\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"살해된 영웅\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"갇힌 {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (비활성화)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"켜기\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"끄기\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"게임 모드\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"게임플레이 설정\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"디아블로나 헬파이어를 선택해 플레이합니다.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"체험판 호환\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"체험판과 호횐되도록 합니다. 디아블로 체험판만 보유한 친구와 멀티플레이를 할 \"\n\"수 있습니다.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"구동\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"구동 설정\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"인트로 영상\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"인트로 영상을 재생합니다.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"스플래시\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"스플래시 스크린을 표시합니다.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"로고와 타이틀 화면\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"타이틀 화면\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"디아블로 설정\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"헬파이어 설정\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"오디오\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"오디오 설정\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"발자국 소리\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"플레이어가 이동할 때 효과음이 납니다.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"자동 장비 소리\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"입수한 물품을 자동으로 장비하면 효과음이 납니다.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"물품 입수 소리\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"물품을 입수하면 효과음이 납니다.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"샘플 레이트\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"출력 샘플 레이트(Hz)입니다.\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"채널\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"출력 채널 수입니다.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"버퍼 크기\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"버퍼 크기(채널 당 프레임 수)입니다.\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"리샘플링 품질\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"0 (최소)에서 최대 (10)까지 리샘플러 품질을 설정합니다.\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"게임 내부 해상도에 영향을 주어 표시 영역을 설정합니다. 주의: 업스케일링, 정\"\n\"수 스케일링, 화면에 맞춤을 사용한 경우에는 화면 해상도와 다를 수 있습니다.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"리샘플러\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"오디오 리샘플러\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"장치\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"오디오 장치\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"그래픽\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"그래픽 설정\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"전체 화면\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"전체 화면이나 창 모드로 게임을 표시합니다.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"화면에 맞춤\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"게임 창을 현재 데스크탑 화면비 및 해상도에 맞춰 자동으로 조정합니다.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"업스케일링\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"게임 해상도를 모니터 해상도로 조정할 수 있습니다. 모니터 해상도 변경을 방지하\"\n\"고 창 크기를 조정할 수 있습니다.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"스케일링 품질\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"업스케일링 출력 화면에 적용할 옵션 필터를 활성화합니다.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"근접 픽셀\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"바이리니어\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"이방성\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"정수 스케일링\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"정수 비율로 이미지를 스케일링합니다.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"수직 동기화\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"유효한 경우 확대합니다.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" 번개\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"색상 순환\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"물, 용암, 산성 에니메이션에 사용되는 색상 순환 효과입니다.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"둥지 그래픽 대체\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"헬파이어의 둥지 타일셋에 대체 팔레트를 사용합니다.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"하드웨어 커서\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"하드웨어 커서를 사용합니다\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"물품용 하드웨어 커서\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"물품에 하드웨어 커서를 사용합니다.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"하드웨어 커서 최대 크기\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"하드웨어 커서 크기의 최대치입니다. 더 큰 커서는 소프트웨서 커서로 변경됩니다.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"FPS 표시\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"화면 좌측 상단에 FPS를 표시합니다.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"게임플레이\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"게임플레이 설정\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"마을에서 달리기 / 빠른 걸음을 활성화합니다. 이 설정은 확장판에서 도입되었습니\"\n\"다.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"마우스 가두기\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"마우스를 게임 창에 가둡니다.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"어린 소녀 퀘스트를 활성화합니다.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"젖소 퀘스트를 활성화합니다. 농부 레스터 대신 완전 미친놈이 등장합니다.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"아군 피해\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"친선 모드가 켜져 있어도 멀티플레이에서 플레이이 간에 화살/주문 피해를 줄 수 \"\n\"있습니다.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"멀티플레이어 전체 퀘스트\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"싱글 플레이어 버전의 전체/무삭제 퀘스트를 활성화합니다.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"음유시인 테스트\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"영웅 선택 화면에서 음유시인을 선택할 수 있습니다.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"야만용사 테스트\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"영웅 선택 화면에서 야만용사를 선택할 수 있습니다.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"경험치 바\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"경험치 바를 화면 하단 UI에 표시합니다.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"상점에서 물품 그래픽 표시\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"상점 메뉴에서 물품 설명 좌측에 그래픽을 표시합니다\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"체력 수치 표시\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"체력 구슬에 체력의 현재 / 최대치를 표시합니다.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"마나 수치 표시\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"마나 구슬에 마나의 현재 / 최대치를 표시합니다.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"캐릭터 정보\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"적 체력 바\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"적 체력 바를 화면 상단에 표시합니다.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"플레이어 근처에 있는 금화를 자동으로 입수합니다.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"플레이어 근처에 있는 영약을 자동으로 입수합니다.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"플레이어 근처에 있는 기름을 자동으로 입수합니다.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"마을에서 물품을 자동으로 입수합니다.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"아드리아의 상점을 방문하면 마나가 재충전됩니다.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"무기를 입수하거나 구매하면 자동으로 장비합니다.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"갑옷을 입수하거나 구매하면 자동으로 장비합니다.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"투구를 입수하거나 구매하면 자동으로 장비합니다.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"방패를 입수하거나 구매하면 자동으로 장비합니다.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"장신구를 입수하거나 구매하면 자동으로 장비합니다.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"새로운 게임에서 랜덤으로 퀘스트가 선택됩니다.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"괴물 유형 표시\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"괴물 위로 마우스를 커서를 가져가면 UI의 설명 상자에 괴물의 유형을 표시합니다.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"바닥에 있는 물품의 명칭을 표시합니다.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"벨트에 있는 물품을 사용하면 소지품에서 자동으로 보충합니다.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"가마솥, 흥미로운 신단, 염소 신단, 화려한 신단, 신성한 신단을 클릭할 수 없고, \"\n\"비활성으로 표시됩니다.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"빠른 시전\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"주문 단축키는 주문을 전환하지 않고 바로 시전합니다.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"자동으로 입수하는 생명력 회복 물약의 수량입니다.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"자동으로 입수하는 생명력 완전 회복 물약의 수량입니다.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"자동으로 입수하는 마나 회복 물약의 수량입니다.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"자동으로 입수하는 마나 완전 회복 물약의 수량입니다.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"자동으로 입수하는 회복 물약의 수량입니다.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"자동으로 입수하는 완전 회복 물약의 수량입니다.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"화면에 숫자 표시 활성화\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"경험치 획득 / 피해량 등을 화면 상에 숫자로 표시합니다.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"끄기\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"무작위 방향\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"수직 방향\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"컨트롤러\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"컨트롤러 설정\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"네트워크\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"네트워크 설정\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"채팅\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"채팅 설정\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"언어\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"게임에서 사용할 언어를 설정합니다.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"언어 설정\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"키매핑\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"키매핑 설정\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"게임패드 매핑\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"게임패드 매핑 설정\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"설정\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"레벨\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"경험치\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"다음 레벨\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"기본\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"현재\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"힘\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"마력\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"민첩\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"활력\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"배분치\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"금화\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"방어력\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"증가\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"피해\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"생명력\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"마나\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"마법저항\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"화염저항\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"번개저항\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"캐릭터\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"퀘스트\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"지도\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"메뉴\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"소지품\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"주문\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"음성\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"음소거\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"사용 불가\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"피해: 대상 HP 1/3\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"회복: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"피해: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"기술\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"지팡이 ({:d}회 충전)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"레벨 {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"마나: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"주문\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"언데드에게만 피해\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"두루마리\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"지팡이\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"주문 단축키 {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"아카이브를 열 수 없습니다\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"캐릭터를 불러올 수 없습니다\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (lvl {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"채팅 내역 (메시지: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} 금화\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"금화를 얼마나 인출하겠습니까?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"레벨 {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"경험치: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"최대 레벨\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"다음 레벨: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} 레벨 {:d}까지\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"레오릭 왕의 무덤\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"뼈의 방\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"암흑 통로\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"불경한 제단\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"{:s}(으)로\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"도와 줘! 여기야!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"날 따라와.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"자, 여기.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"그럼 이제 죽어!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"감사한 분들\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"그리스월드\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"페핀\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"오그덴\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"케인\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"파넘\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"아드리아\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"질리언\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"워트\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"이전\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"피해: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"방어력: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"내구도: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"영구적\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"어서 오십시오\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"대장장이의 상점\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"무엇을 하겠습니까?:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"그리스월드와 대화\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"기본 물품 구매\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"고급 물품 구매\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"물품 매각\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"물품 수리\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"상점을 떠난다\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"이런 물품들이 구비되어 있습니다:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"이런 특별 물품들이 구비되어 있습니다:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"매각할 물품이 없습니다.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"무엇을 매각하겠습니까?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"수리할 것이 없습니다.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"무엇을 수리하겠습니까?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"마녀의 오두막\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"아드리아와 대화\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"물품 구매\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"지팡이 충전\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"오두막을 떠난다\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"충전할 것이 없습니다.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"무엇을 충전하겠습니까?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"소지금이 충분하지 않습니다\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"소지품 공간이 충분하지 않습니다\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"거래하겠습니까?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"이 물품을 감별하겠습니까?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"이 물품을 구매하겠습니까?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"이 물품을 충전하겠습니까?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"이 물품을 매각하겠습니까?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"이 물품을 수리하겠습니까?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"외다리 소년 워트\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"워트와 대화\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"좋은 물건이 있는데,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"금화 50 개만 내세요\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"보고 싶다면 말이죠. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"지불한다\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"작별한다\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"이런 물품들이 구비되어 있습니다:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"떠난다\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"치료사의 집\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"페핀과 대화\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"치료사의 집을 떠난다\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"마을 장로\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"케인과 대화\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"물품 감별\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"감별할 물품이 없습니다.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"감별할 물품이 없습니다.\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"이 물품은:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"완료\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"{:s}와(과) 대화\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"{:s}와(과) 대화 중\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"사용할 수 없습니다\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"체험판에서는\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"버전\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"화젯거리\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"해오름 여관\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"오그덴과 대화\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"여관을 떠난다\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"질리언과 대화\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"창고 관리\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"주정뱅이 파넘\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"파넘과 대화\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"작별한다\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"소지금: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"살해당한 마을사람\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"대장장이 그리스월드\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"치료사 페핀\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"부상당한 마을 주민\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"여관 주인 오그덴\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"케인 장로\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"마녀 아드리아\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"여급 질리언\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"소\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"농부 레스터\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"셀리아\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"완전 미친놈\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"전사\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"도적\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"원소술사\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"수도사\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"음유시인\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"야만용사\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"좀비\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"구울\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"썩은 시체\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"검은 망자\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"몰락자\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"저미는 자\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"악마 일족\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"어둠에 속한 자\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"해골\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"시체 도끼\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"불타는 망자\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"공포\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"시체청소부\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"역병 포식자\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"그림자 야수\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"뼈 찌르는 자\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"시체 활\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"해골 대장\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"시체 대장\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"불타는 망자 대장\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"공포 대장\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"투명 대장\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"숨은자\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"추적자\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"보이지 않는 자\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"환영술사\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"사티로스 대장\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"살점 조직\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"석재 조직\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"화염 조직\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"야간 조직\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"마귀\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"깜박\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"침울\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"친숙\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"산성 야수\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"독 뱉는 자\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"구덩이 야수\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"용암 구멍\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"해골왕\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"도살자\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"오버로드\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"진흙 인간\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"두꺼비 악마\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"가죽이 벗겨진 자\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"웜\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"동굴 민달팽이\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"악마 웜\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"포식자\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"마그마 악마\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"혈석\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"지옥석\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"용암 대장\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"뿔 달린 악마\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"진흙 돌진자\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"서리 충전자\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"흑요석 대장\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"낡은뼈대\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"붉은 망자\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"매혹의 악마\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"언데드 발로그\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"소각자\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"화염 대장\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"파멸의 화염\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"지옥 태우는 자\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"붉은 폭풍\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"폭풍 기수\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"폭풍 대장\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"소용돌이\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"악마 일족 짐승\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"날개 달린 악마\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"가고일\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"피투성이 발톱\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"죽음의 날개\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"살해자\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"수호자\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"소용돌이 대장\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"발로그\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"동굴 독사\"\n\n# 드레이크를 고유명사로 봐야할지 고민\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"화염 드레이크\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"황금 독사\"\n\n# 드레이크를 고유명사로 봐야할지 고민\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"푸른 드레이크\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"검은 기사\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"파멸 수호자\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"강철 대장\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"유혈 기사\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"절단된 자\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"텅 빈 자\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"고통의 주인\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"현실술사\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"서큐버스\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"눈 마녀\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"지옥 산란\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"영혼을 태우는 자\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"지도자\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"판결자\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"카발라 마법사\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"주창자\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"골렘\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"어둠의 군주\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"아크리치 말리그누스\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"힘없는 가바드\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"미치광이 자르\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"코흘리개\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"대주교 라자루스\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"붉은 골칫거리\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"흑옥\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"라크다난\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"피의 전쟁군주\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"구토 악마\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"모독자\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"나-크룰\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"깨진머리 날카로운도끼\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"살해자 칼날가죽\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"영혼고름\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"불결한 구토쥐\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"뼈살인광\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"굶주린 썩은포식\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"재빠른 구트생크\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"깨진머리 방패강타\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"봉고\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"썩은대학살\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"그림자이빨\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"죽음눈\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"망자 미친눈\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"엘 추파카프라\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"해골화염\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"뒤틀린해골\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"피투성이혀\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"고동 탐색자\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"달흥청망청\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"분노까마귀\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"척추포식자\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"불타는 검은재\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"그림자까마귀\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"연약한 역병바위\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"구덩이 대장 쓸개거품\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"핏빛가죽 어둠활\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"타락날개\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"그림자주정뱅이\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"실안개변환자\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"죽음꼬챙이\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"피 빼는 자\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"죽음그늘 살점망치\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"미치광이 전쟁구더기\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"거친 유리해골\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"역병불\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"차가운 밤의날개\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"피투성이바위\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"청동주먹 화염바위\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"파멸의 분노화염\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"음산한 화염흉터\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"오물 남작\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"역병뿔 강철철퇴\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"혼돈원숭이\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"부패한 파멸미소\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"미친태우는자\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"매혹의 뼈절단자\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"척추파괴자\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"악마해골 날카로운뼈\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"부서진폭풍\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"폭풍재해\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"수액질질\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"화염의 황금역병\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"검은폭풍\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"역병분노\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"가죽을 벗기는 자\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"파랑뿔\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"뒤틀린불 지옥산란\"\n\n# 추정 : 타락발톱에 해당하는 괴물이 없음\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"타락발톱\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"곪은해골\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"사자해골\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"검은혀\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"불쾌한접촉\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"독사불길\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"송곳니가죽\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"불경한 마녀불\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"검은해골\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"영혼베기\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"바람산란\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"구덩이 대장\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"녹술사\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"그림자울음\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"파멸구름\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"핏빛달 영혼불\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"마녀달\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"송곳니잡이\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"학살자 회색전쟁\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"두려운심판자\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"마녀 별눈\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"사냥꾼 강철해골\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"고라시 경\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"고관\"\n\n# 찾을 수 없음\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"잠피르\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"강한욕정\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"거미줄과부\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"살점춤꾼\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"음산한쐐기\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"파멸자물쇠\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"단검\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"소형 방패\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"곤봉\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"단궁\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"마나의 단지팡이\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"식칼\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"언데드 왕관\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"최고천 머리테\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"마석\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"눈동자 목걸이\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"진실의 반지\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"여관 간판\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"할리퀸 관모\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"강철의 베일\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"황금 영약\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"분노의 모루\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"검은 버섯\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"뇌\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"균류학 고서\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"무지갯빛 영약\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"혈석\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"대성당 지도\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"생명력 회복 물약\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"마나 회복 물약\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"감별 두루마리\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"마을 차원문 두루마리\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"아르케인의 용맹\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"생명력 완전 회복 물약\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"마나 완전 회복 물약\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"그리스월드의 날\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"졌소 판금갑옷\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"라자루스의 지팡이\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"부활 두루마리\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"단지팡이\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"검\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"단도\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"룬 폭탄\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"테오도르\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"금 목걸이\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"찢어진 쪽지 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"찢어진 쪽지 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"찢어진 쪽지 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"복원된 쪽지\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"갈색 옷\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"회색 옷\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"모자\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"해골 모자\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"투구\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"전면 투구\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"왕관\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"대형 투구\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"덧망토\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"천\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"망토\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"장포\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"누빔 갑옷\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"가죽 갑옷\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"경피 갑옷\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"징 가죽 갑옷\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"쇠미늘 갑옷\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"사슬 갑옷\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"쇠사슬 갑옷\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"비늘 갑옷\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"흉곽 판갑\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"판금\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"미늘 갑옷\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"판금 갑옷\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"야전 판갑\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"고딕 판갑\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"전신 판금 갑옷\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"방패\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"소형 방패\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"대형 방패\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"연 방패\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"탑 방패\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"고딕 방패\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"회복 물약\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"완전 회복 물약\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"기름\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"힘 영약\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"마력 영약\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"민첩 영약\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"활력 영약\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"치료 두루마리\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"탐색 두루마리\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"번개 두루마리\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"화염 방벽 두루마리\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"불지옥 두루마리\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"섬광 두루마리\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"초월 시야 두루마리\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"위치 변경 두루마리\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"마나 방패 두루마리\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"화염파 두루마리\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"화염구 두루마리\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"석화 저주 두루마리\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"연쇄 번개 두루마리\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"수호자 두루마리\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"초신성 두루마리\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"골렘 두루마리\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"순간 이동 두루마리\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"파멸 두루마리\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"언월도\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"신월도\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"십자 검\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"칼\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"굽이칼\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"장검\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"넓적검\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"용병 검\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"양손 검\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"대형 검\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"작은 도끼\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"도끼\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"큰 도끼\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"넓적도끼\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"전투 도끼\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"대형 도끼\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"철퇴\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"샛별 곤봉\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"전쟁 망치\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"망치\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"쐐기 곤봉\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"도리깨\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"쇠메\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"활\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"사냥꾼 활\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"장궁\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"합성궁\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"전투 단궁\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"전투 장궁\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"전쟁 단궁\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"전쟁 장궁\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"장지팡이\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"합성 지팡이\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"육척봉\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"전쟁 지팡이\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"반지\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"목걸이\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"화염의 룬\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"룬\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"번개의 룬\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"거대 화염의 룬\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"거대 번개의 룬\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"석화의 룬\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"돌격탄 단지팡이\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"투기장 포션\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"도살자 식칼\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"라이트세이버\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"균열 활\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"바늘궁\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"천상의 활\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"죽음의 사냥꾼\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"죽음의 활\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"검은참나무 활\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"화염살\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"살점쐐기\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"바람살\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"수리뿔\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"곤나갈의 더크\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"수호자\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"그리폰의 발톱\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"검은 서슬\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"철월\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"얼음살\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"집행자의 칼\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"뼈톱\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"그림자매\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"마법사의 쐐기검\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"라이트세이버\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"매의 발톱\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"불지옥\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"궤멸자\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"회색곰\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"한아비\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"육절기\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"날카로운 부리\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"유혈학살자\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"천상의 도끼\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"사악한 도끼\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"돌가르개\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"아귀나라의 손도끼\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"지옥학살자\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"메셔슈미트의 도끼\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"군열녹\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"졸름의 망치\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"시버브의 곤봉\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"천상의 별\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"바라나르의 별\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"울퉁불퉁한 뿌리\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"두개골 분쇄망치\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"섀퍼의 망치\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"꿈테\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"그림자의 지팡이\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"불태우는 자\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"폭풍 첨탑\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"서광찬가\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"천둥부름\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"보호구\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"나즈의 수수께끼\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"마음의비명\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"오난의 장대\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"기백의 투구\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"생각하는 모자\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"오버로드의 투구\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"광대의 관모\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"신들의 황혼\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"왕실 띠관\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"영혼의 찢긴 살점\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"검투사의 재앙\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"무지개 망토\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"오트의 가죽 갑옷\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"지혜의 싸개\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"불꽃 튀는 사슬 갑옷\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"시체청소부 돌가죽\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"밤하늘 망토\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"나즈의 경판갑\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"악마쐐기 전신 판갑\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"모면\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"분열 해골 방패\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"용의 비상\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"검은참나무 방패\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"신성한 방어자\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"폭풍막이\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"가시덤블\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"레가의 반지\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"출혈반지\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"죄어오는 반지\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"교전의 반지\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"주석\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"황동\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"청동\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"철\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"강철\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"은\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"백금\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"미스릴\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"유성\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"이상한\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"쓸모 없는\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"휜\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"무른\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"톱날\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"치명적인\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"육중한\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"잔인한\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"잔혹한\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"거대한\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"야만적인\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"가차없는\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"무자비한\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"투박한\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"둔한\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"예리한\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"섬세한\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"전사의\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"병사의\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"군주의\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"기사의\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"장인의\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"투사의\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"왕의\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"취약한\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"녹슨\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"튼튼한\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"웅장한\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"용맹한\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"영예로운\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"축복받은\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"성스러운\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"경이로운\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"경건한\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"붉은색\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"진홍색\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"석류석\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"루비\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"파란색\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"푸른색\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"보석\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"청록색\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"사파이어\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"백색\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"진주\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"상아\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"수정\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"다이아몬드\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"토파즈\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"호박\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"비취\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"흑요석\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"에메랄드\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"하이에나의\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"개구리의\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"거미의\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"큰까마귀의\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"뱀의\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"구렁이의\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"드레이크의\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"용의\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"웜의\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"히드라의\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"천사의\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"대천사의\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"풍부한\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"너그러운\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"화염\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"번개\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"고급\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"불구\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"학살\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"피투성이\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"대학살\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"살육\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"고통\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"눈물\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"건강\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"보호\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"흡수\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"굴절\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"삼투\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"노쇠\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"쇠약\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"힘\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"완력\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"동력\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"거인\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"티탄\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"마비\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"퇴화\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"민첩\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"기술\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"정확\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"정밀\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"완벽\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"바보\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"난독\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"마력\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"정신\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"광휘\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"원소술\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"마법\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"질환\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"질병\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"활력\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"열정\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"정력\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"생기\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"생명\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"통증\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"갱\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"하늘\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"달\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"별\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"천상\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"황도대\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"독수리\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"자칼\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"여우\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"표범\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"수리\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"늑대\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"호랑이\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"사자\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"맘모스\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"고래\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"연약\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"불안정\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"견고\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"솜씨\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"구조\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"시대\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"어둠\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"밤\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"빛\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"광휘\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"불\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"화염\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"이글거림\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"충격\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"번개\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"천둥\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"다수\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"풍부\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"가시\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"타락\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"도적\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"곰\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"박쥐\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"흡혈귀\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"거머리\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"피\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"관통\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"천공\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"강타\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"준비\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"급속\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"고속\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"신속\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"균형\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"안정\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"조화\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"저지\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"마석\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"힘없는 가바드\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"미치광이 자르\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"라크다난\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"도살자\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"오그덴의 간판\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"눈먼 자의 전당\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"용맹\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"피의 전쟁군주\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"레오릭 왕의 저주\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"대주교 라자루스\"\n\n# Grave Matters\n# 무덤 문제와 중대사, 중의적 의미\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"무덤 중대사\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"농부의 과수원\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"어린 소녀\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"방랑상인\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"모독자\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"나-크룰\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"저지 젖소의 저지 옷\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"화염탄\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"회복\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"번개\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"섬광\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"감별\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"화염 방벽\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"마을 차원문\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"석화 저주\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"초월 시야\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"위치 변화\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"마나 방패\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"화염구\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"수호자\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"연쇄 번개\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"화염파\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"파멸의 뱀\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"피의 의식\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"초신성\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"투명\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"불지옥\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"골렘\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"분노\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"순간 이동\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"파멸\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"영묘화\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"물품 수리\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"지팡이 충전\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"함정 해제\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"전열\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"돌격탄\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"신성 화살\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"부활\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"염력\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"타인 치료\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"유혈의 별\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"뼈 영혼\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" 아, 레오릭 왕 이야기 말인가? 레오릭 왕의 비참한 몰락은 이 세상에 있어 커다\"\n\"란 비극이었네. 백성들은 항시 왕을 경애했으나 이제는 왕의 살육을 두려워하며 살\"\n\"고 있지. 그 고결하던 레오릭 왕이 어째서 빛에서 멀어져 타락하게 되었는지는 의\"\n\"문일세. 지독히도 비열한 지옥의 힘만이 왕의 정신을 그토록 산산히 파멸시킬 수 \"\n\"있을 테지.\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"선생님, 이 마을을 구할 수 있는 건 당신뿐입니다! 몇 개월 전, 레오릭 왕의 아들\"\n\"인 알베르히트 왕자가 유괴되었습니다. 레오릭 왕은 자식을 잃은 분노로 마을에 폭\"\n\"정을 가했고 나날이 광기에 휩싸여 갔습니다. 왕자의 유괴를 무고한 마을 사람들 \"\n\"탓으로 돌리고 잔인하게 처형해서 지금은 그 절반도 남아 있지 않게 되었습니\"\n\"다... 왕국의 기사들과 성직자들이 진정시키려 노력했지만 레오릭 왕은 그들을 적\"\n\"대시했고, 불행히도 그들이 왕을 시해하는 사태에 이르게 되었습니다. 레오릭 왕\"\n\"은 숨을 거두면서 신하들에게 끔찍한 저주를 내렸습니다. 영원히 어둠 속에서 자신\"\n\"을 섬기도록 말이죠... 그리고서 상상도 못할 끔찍한 일이 벌어졌습니다. 레오릭 \"\n\"왕이 영원한 잠에서 깨어나 미궁의 언데드 군단을 통솔하게 된 겁니다. 왕의 시신\"\n\"은 대성당 지하묘지 3층에 안치되어 있습니다. 선생님, 부디 저주받은 왕을 거두\"\n\"어 그 영혼에 평온이 깃들도록 해주십시오.\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"말씀드린 대로 왕의 시신은 지하 3층에 안치되어 있습니다. 그 썩은 내 풍기는 어\"\n\"둠 속에서 이 땅을 멸망시킬 기회만을 노리고 있는 거죠...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"레오릭 왕의 저주는 사라졌지만 거대한 악의 일부에 불과했던 건 아닌지 걱정됩니\"\n\"다. 어쨌든 당신의 승리는 좋은 징조입니다. 아직은 이 땅을 뒤덮은 어둠으로부터 \"\n\"몸을 건사할 수 있나 봅니다. 빛이 당신의 길을 이끌어 주시길.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"레오릭 왕은 아들 잃은 걸 견디지 못했지. 나도 왕의 광기를 치료하려 했지만 결\"\n\"국 왕은 광기에 굴복하고 말았어. 그날부터 이 땅에 암흑의 저주가 씌었지만 자네\"\n\"가 왕의 영혼을 속세에서 해방시킨다면 저주는 사라질 게야.\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"레오릭 왕의 죽음에 대한 건 떠올리고 싶지 않아요. 상냥하고 공정한 분이었다는 \"\n\"것만 기억하고 싶답니다. 그분의 죽음은 너무도 안타깝고 도저히 납득할 수가 없네\"\n\"요.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"레오릭 왕을 받드는 기사단을 위해 무기와 갑옷을 정말 많이 만들었지. 왕에겐 거\"\n\"대한 최고급 미스릴 양손 검과 투구를 헌상한 적도 있어. 그 양반 죽은 게 아직도 \"\n\"믿기지 않지만 사악한 기운에 사로잡힌 게 틀림없다고!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"그딴 거 알 게 뭐야. 봐봐, 해골 따윈 왕이 아니야. 레오릭이 왕이지. 왕 말이야, \"\n\"알겠어? 레오릭 전하 만세!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"산 자 속을 방황하는 망자들은 저주받은 왕을 추종하죠. 그자는 전사들을 되살려 \"\n\"언데드 군대의 증강을 도모할 힘을 쥐었어요. 당신이 그자의 지배에 종지부를 찍\"\n\"지 않으면 그자는 이 땅을 유린하며 살아 있는 모든 것을 베어 버릴 테죠.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"이봐요, 난 여기서 장사를 하는 거지 정보팔이를 하는 게 아니에요. 옛날에 죽은 \"\n\"왕 따위는 관심도 없고요. 언데드 왕을 상대로 싸울 무기가 필요한 거라면 도와줄 \"\n\"수도 있지만 말이죠...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"산 것의 온기가 내 무덤에 들어왔다. 필멸자여, 영원토록 나의 주인을 섬길 준비\"\n\"나 하거라!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"정말로 이상한 일이로군. 자네도 당혹스럽겠어. 마귀들은 햇빛에 엄청난 힘이 내재\"\n\"되어 있다고 믿어서 햇빛을 두려워할 텐데, 아마도 간판에 그려진 떠오르는 태양\"\n\"에 신비한 힘이 깃들어 있다고 여겼나 보네. 흐음, 녀석들, 우리가 두려워할 정도\"\n\"로 영리하진 않은가 보구만...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"선생님, 이상한 일을 겪었습니다. 저는 도무지 짐작도 못 하겠습니다. 미궁에 사\"\n\"는 괴물에 대해 잘 아시죠? 밤에 삐걱거리는 소리가 가게 밖에서 들려서 잠을 깼는\"\n\"데, 밖을 보니 가게 앞에 마귀처럼 보이는 것들이 있더군요. 순식간에 제 여관 간\"\n\"판을 훔쳐서 도망갔습니다. 왜 마귀들이 제 가족에게는 손대지 않고 간판만 훔쳐\"\n\"서 달아났는지 모르겠습니다... 정말 이상하지 않습니까?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"오, 일부러 찾아주시지 않아도 됐는데... 덕분에 새로운 걸 만들지 않아도 되겠습\"\n\"니다. 어디 보자, 답례를 해야겠는데, 흐음, 뭐가 좋으려나... 아, 그래! 예전에 \"\n\"묵었던 마법사가 두고간 모자인데 아마도 당신에게 도움이 되지 않을까 싶습니다.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"맙소사, 마귀들이 밤에 마을을 약탈하며 돌아다녔다니, 이게 무슨 변인가? 오그덴\"\n\"과 가르다가 무사해야 할 텐데. 물론 다치기라도 했다면 나한테 왔겠지만 말이\"\n\"야...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"세상에! 간판이 어디론가 사라졌다고요? 할머니와 저는 자고 있었는데 괴물들이 여\"\n\"관을 습격하지 않아서 다행이에요.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"마귀들이 오그덴의 간판을 훔쳐갔다고? 우리 심장이 아니라 간판을 노리다니 살면\"\n\"서 별일을 다 보는군 그래.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"내 생각에는 누군가 돈을 노리고 간판을 훔쳐간 거야. 내가 오그덴이면... 물론 아\"\n\"니지만 어쨌든 내가 그렇다면... 예쁜 그림이 있는 간판을 새로 사겠어. 멋진 맥주\"\n\"잔이나 치즈 같은 게 그려진 걸로 말야...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"마귀의 생각을 제대로 이해할 수 있는 인간은 없죠. 놈들의 기이한 행동에 절대 현\"\n\"혹되어선 안 돼요. 그게 바로 놈들의 목적이니까요.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"뭐요? 내가 훔쳤다고 그리스월드가 그러던가요? 이봐요, 팔아 봐야 돈도 안 되는 \"\n\"그딴 간판을 뭐 하러 훔치겠어요.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"야, 전부 죽이고 다니는 놈! 마법 현판을 가져와라. 안 그럼 공격한다. 살아 못 돌\"\n\"아간다! 커다란 못난이들 죽이고 마법 현판 되찾아라. 모통이 돌면 문 안에 못난이\"\n\"들 있다. 현판 찾아오면 보내준다!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"못난이들 죽이고 간판 가져와라. 나한테 안 가져오면...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"가져왔나! 그래, 좋다! 이제 가라, 우린 강하다. 센 마법으로 다 죽일 테다!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"불길한 징조야. 내가 가장 두려워하던 일이 일어났어. 옛 전설 같은 걸 믿고 싶지\"\n\"는 않지만 지금에서는 부정할 수가 없군그래. 내가 누구인지 밝혀야 할 때가 온 \"\n\"것 같군. \\n\"\n\"\\n\"\n\"내 진짜 이름은 데커드 케인으로 영원한 악의 봉인을 수호하는 고대 결사대의 마지\"\n\"막 후예라네. 허나 아무래도 악마의 봉인이 풀린 듯하군. 대주교 라자루스는 일찍\"\n\"이 레오릭 왕이 총애하던 참모로, 행방불명된 알브레히트 왕자를 찾으러 마을 사람\"\n\"들을 미궁으로 이끌고 갔지. 하지만 살아 돌아온 사람은 그저 몇 사람뿐... \\n\"\n\"\\n\"\n\"내가 어리석었어! 라자루스의 배신을 눈치챘어야 했는데 말일세. 알브레히트 왕자\"\n\"를 납치해 미궁에 숨긴 것도 필시 라자루스의 짓일 터. 대주교씩이나 되는 사람이 \"\n\"어째서 어둠의 세력으로 전향해 왕자에게 흥미를 가졌는지 납득은 안 가네만, 어둠\"\n\"의 지배자에게 왕자를 제물로 바치려는 속셈이 틀림없네! \\n\"\n\"\\n\"\n\"생존자들 말로는 라자루스가 미궁 깊숙한 곳으로 들어간 게 마지막 모습이었다는\"\n\"군. 이 광기들린 악마의 희생의 칼끝에서 서둘러 왕자를 구하게나!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"라자루스의 손아귀에서 서둘러 알브레히트 왕자를 구하게. 왕자와 이 왕국 사람들 \"\n\"모두 자네만 믿고 있다네!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"참으로 끔직한 이야기일세. 라자루스는 죄악의 대가로 틀림없이 지옥불에 떨어질 \"\n\"테지. 자네가 말한 소년은 왕자가 아니네. 알브레히트 왕자는 여전히 곤경에 처해 \"\n\"있을 테지. 바닥에 그려진 힘의 문양은 틀림없이 미궁의 중심으로 가는 차원문일 \"\n\"거네.\\n\"\n\"\\n\"\n\"이걸 알아 두게나. 자네가 맞설 상대는 공포의 군주라 불리는 악마라네. 사람들에\"\n\"겐 디아블로라고 알려져 있지. 놈은 몇 세기 전 미궁에 유폐되었지만 다시 한번 \"\n\"이 세상에 혼란을 초래하진 않을까 염려스럽군. 너무 늦기 전에 자네가 그 차원문\"\n\"으로 가서 디아블로를 쓰러트리게!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"대주교 라자루스는 마을 사람들을 이끌고 미궁에 들어갔습니다. 그날 많은 친구들\"\n\"을 잃게 되었고 라자루스도 돌아오지 않았죠. 다른 사람들과 마찬가지로 살해당했\"\n\"을 겁니다. 부탁이니 파넘에게는 그날 일을 묻지 말아 주십시오.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"그날 밤 마을 사람들이 하려는 계획을 듣고 귀를 의심했지. 라자루스가 그 같은 짓\"\n\"을 저지를 거라고는 생각도 못했는데 말이야. 대주교로서 언제나 트리스트럼 사람\"\n\"들을 보살펴 주었거든. 부상자도 너무 많아 그들 모두를 구할 수는 없었네...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"라자루스 님은 친절하고 자비로운 분이셨어요. 제 어머니 장례식에서 송사를 맡아 \"\n\"주셨고, 곤경에 처한 저와 제 할머니의 버팀목이 되어 주셨죠. 그분이 무사하기를 \"\n\"매일 밤 기도한답니다.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"라자루스가 우리를 이끌고 미궁에 갔을 때 나도 거기 있었지. 천벌을 내리는 거라\"\n\"고 외치던 인간이 막상 마귀들하고 싸움이 시작되자 전곤 한번 안 휘두르더군. 그\"\n\"러더니 마귀들이 가득한 끝 모를 어둠 속으로 냅다 튀었지 뭐야!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"놈들은 찌르고 물어뜯으며 우리를 포위했어. 거짓말쟁이! 거짓말쟁이! 거짓말쟁\"\n\"이! 전부 죽었어! 죽었다고! 알겠어? 차례대로 쓰러지고... 바닥이 피로 물들어 갔\"\n\"어... 전부 그놈 탓이야...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"당신이 말하는 라자루스를 만난 적은 없지만 그자의 내면에서 크나큰 갈등이 느껴\"\n\"지는군요. 그자는 매우 위험한 존재예요. 자신을 사로잡은 어둠의 힘을 섬기기 위\"\n\"해 그 어떠한 짓도 서슴지 않을 테니까요.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"그래요, 정의의 라자루스는 저 지하 괴물들과 맞서기에 아주아주 제격이었던 양반\"\n\"이죠. 내 다리 하나 못 구했으면서, 그렇잖아요? 공짜로 하나 가르져 주죠. 파넘한\"\n\"테 물어봐요. 거기 있었으니까요.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"어리석은 수색 따위는 그만 포기해라. 네놈을 기다리는 건 오직 내 주인의 분노\"\n\"뿐! 그 아이를 구하기엔 너무 늦었으니 그만 지옥에서 만나 보거라!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"흐음, 내가 어떻게 도움을 줘야 할지 모르겠군. 마을 우물물은 지하 수맥에서 비롯\"\n\"된다네. 큰 호수로 통하는 터널이 있다는 얘기를 들은 적이 있는데 아마도 그거겠\"\n\"지. 유감이네만 수원지가 오염된 이유는 모르겠네.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"전 항상 식료품과 물을 창고에 대량으로 비축하지만, 마을 전체에 신선한 물이 공\"\n\"급되지 않으니 창고 비축분도 바닥날 지경입니다.\\n\"\n\"\\n\"\n\"제발 어떻게든 부탁드립니다. 어찌하면 좋을지 모르겠습니다.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"때마침 자네가 있어서 정말 다행이야! 우물이 오염돼서 마을 사람들이 그걸 마시\"\n\"고 병에 걸렸지. 신선한 물이 빠르게 고갈되고 있어. 마을에 물을 공급하는 수맥으\"\n\"로 통하는 길이 있다네. 부디 이 재난의 원인을 규명해 주게. 안 그러면 우리 모\"\n\"두 죽게 될 테니 말이야.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"부디 서두르게. 이제 곧 물이 바닥나니 말이야.\\n\"\n\"\\n\"\n\"자네 도움 없이 더는 버티기 어렵네.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"그게 무슨 말인가? 물이 오염된 원인이 그저 마귀 때문이었다고? 이 마을 지하에 \"\n\"거대한 악이 잠복해 있다지만 자네의 인내와 용기는 우리에게 희망을 주네. 이 반\"\n\"지를 가져가게. 악귀를 물리치는 데 도움이 될 거야.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"제 할머니는 매우 편찮으신데 가르다가 우물물을 마실 수 없다고 하네요. 제발 우\"\n\"리를 도와주시겠어요?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"페핀 영감님이 형씨한테 말한 대로야. 신선한 물이 절실하지. 작은 우물을 정화해 \"\n\"보려고 했는데 오물이 고여서 악취를 풍기더군. 수원지에서부터 막혀 있는 게 틀림\"\n\"없어.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"물을 마신다고?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"당신이 우물을 원상 복구하지 못하면 트리스트럼 사람들은 죽게 되겠죠.\\n\"\n\"\\n\"\n\"이걸 알아 두세요. 이 문제의 중심에는 마귀들이 있지만 놈들은 자신들이 초래한 \"\n\"사태를 깨닫지 못하고 있어요.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"이번만은 그쪽 편이 되죠. 구매자가 없으면 내 장사도 끝장이니까요. 무슨 일이 일\"\n\"어나고 있는지 조사해 보는 게 좋을 거예요, 어서요!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"뼈의 방에 대한 책 말인가? 뼈의 방이라면 내가 동방의 도서관에서 연구한 고서에 \"\n\"언급이 있었지. 황천의 왕이 막대한 보물을 지킬 욕심에 특별한 장소를 만들었다\"\n\"고 하더군. 보물을 훔치러 온 사람은 목숨을 잃고 영원히 그 보물을 지키게 된다\"\n\"고 적혀 있었네. 엄한 이야기지만 묘하게 조리가 맞다고 생각되지 않는가?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"유감이지만 저는 전혀 모르겠습니다, 선생님. 케인 어르신이 갖고 있는 책이라면 \"\n\"도움이 될지도 모르겠군요.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"매우 위험한 장소인 것 같군. 가게 된다면 정말로 조심하게.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"죄송한데 전혀 들어본 적이 없네요. 이야기꾼인 케인 할아버지라면 알고 계실지도\"\n\"요.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"그런 데는 모르겠군. 케인 영감님한테 물어보지 그래? 그 영감님 박식하니까 형씨 \"\n\"궁금증을 풀어 주는 건 일도 아닐걸.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"좋아, 잘 들어. 나무 방이 있어. 그리고 녀석의 마누라가... 알지? 그 여자... 나\"\n\"무에 대해 말할 거야... 기다리면 말야. 녀석 때문은 아닐지 몰라도 돈을 내야 한\"\n\"다고 생각하면... 네가... 어... 그래.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"그 저주받은 땅에서 죽게 된다면 어둠의 왕의 영원한 종이 될 터.\\n\"\n\"\\n\"\n\"뼈의 방에 들어갈 생각이라면 단단히 각오하도록 하세요.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"신비롭고 막대한 보물이라고 그랬나요? 몫을 좀 나눠 준다면 흥미가 있겠는데... \"\n\"그보단 고생하는 그쪽한테 딱인 진귀한 물건이 있는데 안 살래요?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"대주교 라자루스는 실종된 왕의 아들을 찾기 위해 마을 주민들을 미궁으로 몰아넣\"\n\"었다네. 사람들의 공포심을 이용해 그들을 흉폭한 폭도로 돌변하게 만들었지. 땅속\"\n\"에서 무엇이 기다리고 있을지 아는 사람은 아무도 없었지만 말일세... 라자루스는 \"\n\"사람들을 그곳에 내버려 두었고 형언할 수 없는 공포 속에서 그들은 죽어 갔지.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"예, 파넘은 섬뜩한 무기를 휘두르는 흉측한 괴물에 대해 중얼거렸죠. 그 괴물을 도\"\n\"살자라고 불렀던 것 같습니다.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"그 사악한 악마는 당연히 알고 있지. 라자루스의 함정에서 살아남은 사람들이 대성\"\n\"당에서 나왔을 때, 사람들 대부분이 녀석의 분노가 서린 상처를 입고 있었어. 녀석\"\n\"이 희생자들을 도륙할 때 사용한 게 뭔지는 모르겠지만 이 세상에 존재하는 물건\"\n\"은 아닐 거야. 상처가 곪아 나조차도 손쓸 수 없었거든. 자네가 그 악마와 싸울 생\"\n\"각이라면 부디 조심하게.\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"파넘이 사람 잡는 도살자에 대해 말했지만 전 믿지 않았죠. 하지만 당신도 그러는 \"\n\"걸 보니 사실일지도 모르겠네요.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"내 친구들을 몰살시켰던 그놈을 파넘은 도살자라고 부르더군. 놈은 도끼 마냥 거대\"\n\"한 식칼을 휘두르며 거기에 있던 친구들의 사지를 도륙해댔지. 난 잡놈들을 상대하\"\n\"느라 그 난동에서 떨어져 있었기 때문에 그 끔찍한 괴물과 마주치지 않고 밖으로 \"\n\"나가는 계단을 찾았지만 말이야. 피투성이가 된 그놈의 얼굴이 아직도 잊혀지지가 \"\n\"않아.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"너무 거대한 식칼로 내 친구들을 전부 죽였어. 놈을 막기는커녕 친구들도 못 구하\"\n\"고 도망쳐야만 했어. 갇혀 있던 방 안에 가득한 시체들은... 전부 친구들이었... \"\n\"으아아아아아!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"도살자는 타인을 고문하고 고통을 주는 것에서 쾌락을 느끼는 가학적인 괴물이죠. \"\n\"주정뱅이 파넘을 봤다면 알 수 있을 터. 그 괴물을 쓰러트려야 이 마을의 평안을 \"\n\"어느 정도 되찾을 수 있을 거예요.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"그 끔찍한 악마라면 당신보다 더 잘 알아요. 그리스월드가 저 구렁텅이에서 날 끌\"\n\"어내기 전에 그 자식의 친구들이 내 다리를 앗아갔으니까요. \\n\"\n\"\\n\"\n\"장담하는데 그 자식을 먼저 못 죽이면 녀석이 그쪽을 죽여서 시체를 수집할걸요.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"부디 제 얘기를 들어 주십시오. 대주교 라자루스는 실종된 왕자를 찾기 위해 우리\"\n\"를 여기로 내려보냈습니다. 하지만 그 개자식의 함정이었습니다! 이제 모두 죽어 \"\n\"버렸지요... 도살자라는 악마에게 말입니다. 복수를 해주십시오! 우리의 영혼이 편\"\n\"히 쉴 수 있게 도살자를 찾아 쓰러트려 주십시오...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"자네가 재미있는 시를 읊는 걸 보니 그와 비슷한 시가 생각나는군. 어디 보자, 어\"\n\"떤 내용이었더라...\\n\"\n\"\\n\"\n\"...어둠은 숨은자를 가릴지니, 그 눈의 빛남은 보이지 않고, 그저 날카로이 손톱 \"\n\"할퀴는 소리만이, 영원히 눈먼 가련한 영혼들을 고문한다. 영원한 단죄를 받은 자\"\n\"들의 감옥, 눈먼 자의 전당이라 하노라...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"전 시에 그다지 조예가 없습니다. 경기가 좋던 무렵에는 음유시인도 고용을 했었지\"\n\"만 먼 옛날 일이로군요. 예? 아, 그렇죠... 시라면 다른 분들에게 물어보는 게 좋\"\n\"겠습니다.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"이걸 어디선가 본 기억이 있어. 악마적 대환에 대한 역사를 조사하고 있었을 때 \"\n\"그 시와 아주 흡사한 걸 읽은 기억이 나네. 대단히 사악한 장소라고 하던데... 여\"\n\"보게, 잠깐만. 설마 갈 생각은 아니겠지?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"실명에 대해 궁금한 게 있으면 페핀 선생님한테 여쭤보세요. 페핀 선생님이 주신 \"\n\"약 덕분에 할머니 눈이 보이게 되었거든요. 당신도 도와줄 수 있을 거예요.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"형씨가 말한 곳을 본 적도, 들은 적도 없지만 이야기꾼인 케인 영감님이라면 뭔가 \"\n\"도움이 될지도 모르겠군.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"이거 봐봐... 정말 웃기지? 어때? 장님이 이게 보인다고?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"그곳은 그 주인의 뜻에 따라 크나큰 고통과 공포가 만연한 곳죠.\\n\"\n\"\\n\"\n\"신중히 행동하지 않으면 예상보다 더 오래 머물게 될 거예요.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"가만 있자, 내가 그쪽한테 뭔가를 파는 건가요? 아니죠. 그에 대한 얘기를 해주면 \"\n\"나한테 돈을 낼 건가요? 그것도 아니죠. 그럼 이런 얘기로 먹고사는 이야기꾼한테 \"\n\"가야 할까요? 맞아요.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"자네가 라크다난과 얘기했단 말인가? 그는 위대한 영웅이었다네. 라크다난은 명예\"\n\"로운 데다 왕을 충실히 섬겼었지. 물론 그 얘기는 자네도 알고 있을 걸세.\\n\"\n\"\\n\"\n\"많은 이들이 왕의 저주에 걸렸지만 적어도 라크다난만큼은 순순히 어둠에 복종하지\"\n\"는 않았을 터, 자네가 말한 얘기는 틀림없는 사실이겠지. 내가 자네 입장이라면 그\"\n\"를 고통에서 해방시킬 방법을 찾아보겠네.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"먼 옛날에 죽은 용사와 얘기를 했다고요? 제 여관 앞에서 죽은 영혼과 대화 같은 \"\n\"걸 하지는 않을 겁니다. 감사합니다.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"황금 영약이라고 했나? 그런 색상의 물약을 제조한 적이 없어서 마시면 어떤 효과\"\n\"가 있을지는 나도 모르겠군. 치료사로서 조언하자면 그런 영약을 찾거든 다른 용도\"\n\"로 사용 말고 라크다난이 말한 대로 하게.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"라크다난에 대해 들어본 적이 없어요. 죄송하지만 별로 도움이 못 될 것 같네요.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"형씨가 만난 사람이 정말 라크다난이라면 그를 도와주라고 말하고 싶군. 그 친구\"\n\"와 몇 번 상대해 봤는데 정말 정직하고 충직한 친구였거든. 레오릭 왕의 신하 중에\"\n\"서도 특히나 모진 저주에 걸렸을 테지.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" 라크다난은 죽었어. 누구나 다 안다고. 날 속일 생각 마. 죽은 사람과 얘기할 순 \"\n\"없어. 당연하잖아!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"라크다난처럼 미궁에 갖힌 사람들을 만나게 될 수도 있어요. 라크다난에게선 명예\"\n\"와 크나큰 죄의식이 느껴지는군요. 그를 돕도록 하세요. 그게 트리스트럼 전체를 \"\n\"돕는 길이에요.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"잠깐만요. 케인이 커다란 구멍에 빠져서 지옥불에 불타 죽으면 그쪽 질문에 더는 \"\n\"대답 못하겠죠. 오, 그럴 일 없다고요? 그럼 뭔가 사려는 게 아니면 가던 길이나 \"\n\"마저 가세요.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"무기를 거두고 내 이야기를 들어 주시오. 나는 레오릭 왕의 기사단장으로, 정의와 \"\n\"명예로 이 땅의 법을 수호해 왔소. 그러나 왕의 비극적인 죽음을 초래한 까닭에 저\"\n\"주에 걸리게 되었다오. 기사단은 얄궂은 운명에 굴복했고 나는 왕의 무덤에서 피신\"\n\"해 저주에서 벗어날 방법을 찾아봤으나 헛된 일이었소... 저주를 풀어 영혼을 편\"\n\"히 잠들게 할 황금 영약에 대해 들은 적이 있지만 찾을 수가 없었소. 이제 기력도 \"\n\"쇠약해지고 내 남은 이성 또한 그러하니 부디 나를 도와 영약을 찾아 주시오. 그 \"\n\"수고에 반드시 보답할 것이오. 내 명예를 걸고 맹세하오.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"아직 황금 영약을 못 찾은 것이오? 영원히 불행 속에 살게 될까 두렵소. 부디 계\"\n\"속 찾아봐 주시오...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"그대가 나의 영혼을 파멸에서 구해 주었소. 감사를 표하는 바이오. 무덤 속에서라\"\n\"도 이 빚을 갚을 방법을 찾을 수 있다면 그러겠으나 일단은 이 투구를 받아 주시\"\n\"오. 앞으로 나의 여행에 있어서는 필요없는 물건이나 어둠의 힘으로부터 그대를 지\"\n\"켜 줄 것이오. 빛이 함께 하기를, 친구여..\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"그리스월드가 말한 분노의 모루는 오래도록 찾지 못한 전설의 유물이라네. 분노의 \"\n\"모루는 악마의 날카로운 금속질 뼈로 만들어졌는데, 황천에서 가장 강력한 다섯 마\"\n\"법사의 해골 근처에 있다고 하지. 힘과 혼돈의 상징이 새겨져 있어서 그 모루로 만\"\n\"들어진 무기에는 혼돈의 마력이 깃든다더군. 혼돈의 본질은 예측하기 어려운지라 \"\n\"그 모루로 제조를 하면 결과가 어떻게 될지는 모른다고 하네...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"이 얘기는 그리스월드에게 묻는 편이 더 나을 것 같습니다. 아시겠지만 유능한 사\"\n\"람이죠.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"의료기구나 정화의 은 성배에 대한 정보라면 가르쳐 줄 수 있을 텐데 말이야. 어쨌\"\n\"든 그런 건 그리스월드나 케인에게 물어보게.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"어렸을 적에 그리스월드의 아버님이 강력한 무기를 만드는 데 쓰는 큰 모루 얘기\"\n\"를 해주셨죠. 모루를 망치로 내려치면 지면이 광분한 것처럼 흔들린다고 했어요. \"\n\"그래서 지진이 있을 때마다 항상 그 얘기가 떠오른답니다.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"어서 오라고! 형씨는 최고의 고객이라 언제든 환영이야! 미궁 깊숙한 곳까지 갔다\"\n\"왔다며? 그래서 긴히 하는 얘긴데 말야... \\n\"\n\"\\n\"\n\"미궁에서 살아 돌아온 녀석이 그러는데, 도망치던 도중에 마법의 모루를 봤다는\"\n\"군. 내가 젊었을 때 들었던 전설과 딱 들어맞지 뭐야. 전설에는 불타는 지옥용광\"\n\"로 깊숙한 곳에 분노의 모루라는 게 있어서 강력한 마법의 무기를 만들어 낸다고 \"\n\"해. 모루에는 황천 악마의 정수가 담겨 있어서... 그걸로 만든 무기에는 엄청난 힘\"\n\"이 스며든다지.\\n\"\n\"\\n\"\n\"그 모루가 진짜 분노의 모루라면 지옥의 군주도 물리칠 수 있는 무기를 만들 수 있\"\n\"다고! \\n\"\n\"\\n\"\n\"모루를 찾아 주겠나, 형씨? 그럼 내 솜씨를 보여 주지!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"아직 못 찾았나? 계속 찾아보라고. 그 모루만 있으면 내가 형씨한테 딱인 전설적\"\n\"인 무기를 만들어 줄 테니까.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"믿기질 않는군! 이게 분노의 모루라니. 정말 잘했어, 형씨. 이제 지옥에 있는 저 \"\n\"개자식들에게 인간이 만든 무기가 얼마나 무서운지 깨닫게 해줘야겠어! 이걸 가져 \"\n\"가. 빛의 가호가 있기를 빌지.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"그리스월드는 모루를 팔면 안 돼. 그거 팔아서 어쩔라고? 내 모루를 판다면 나라\"\n\"도 화낼 거야!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"미궁에는 인간의 이해를 넘어서는 많은 유물들이 있어요. 개중에는 빛이나 어둠에 \"\n\"이용될 수도 있는 엄청난 힘을 지닌 것도 있죠. 지하에서 모루를 찾게 된다면 죄악\"\n\"의 전쟁의 균형은 빛 쪽으로 기울 거예요.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"그쪽이 모루를 찾아서 그리스월드한테 줬다간 내 사업에 심각한 차질이 생길 게 뻔\"\n\"하잖아요. 아으으, 절대 못 찾을 거예요.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"피의 관문과 불의 전당은 신비의 기원이 되는 기념비적인 건축물이라네. 자네가 책\"\n\"을 어디서 읽었는지는 모르겠네만 틀림없이 위대한 힘이 깃든 장소일 것이야.\\n\"\n\"\\n\"\n\"전설에 따르면 흑요석으로 만든 대좌의 표면은 뼈로 드리워져 있으며 펄펄 끓는 피\"\n\"가 고여 있다고 하지. 또한 전설에는 고대의 보물을 지키는 관문을 여는 혈석에 대\"\n\"해서도 언급되어 있네... \\n\"\n\"\\n\"\n\"이 보물에 대해서는 여러 억측이 무성하지만 옛 영웅 아르케인이 비밀의 장소에 안\"\n\"치한 성스러운 용맹의 갑옷이라 일컬어진다네. 아르케인은 죄악의 전쟁 전세를 뒤\"\n\"집은 최초의 인간으로 어둠의 군단을 불타는 지옥으로 되돌려 보냈지. \\n\"\n\"\\n\"\n\"아르케인은 죽기 직전, 갑옷을 비밀 장소에 감추었고 성스러운 갑옷이 필요한 시기\"\n\"가 다시 오면 용맹의 갑옷을 입으러 영웅이 나타난다고 했는데, 자네가 그 영웅일\"\n\"지도 모르겠구만...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"전사 아르케인과 용맹이라는 신비한 갑옷 이야기는 아이들도 알 정도입니다. 갑옷\"\n\"이 있는 곳을 찾게 되면 미궁의 마귀로부터 몸을 보호할 수 있겠지요.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"흠... 들어 본 거 같긴 한데, 요즘 새로운 치료법을 익히고 영약을 제조하느라 바\"\n\"빠서 잊어버렸나 보네. 미안하군...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"용맹이라는 마법 갑옷 이야기라면 사내 아이들이 자주 얘기하는 걸 들었어요. 마\"\n\"을 남자들에게 물어보는 게 좋겠네요.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"용맹이라는 갑옷이 있으면 상당한 도움이 될 거야. 나도 그렇고 많은 사람들이 그\"\n\"걸 찾았지만 소용없었지. 아르케인이 정말 잘 숨겨 놨어. 오랜 세월 동안 감추어\"\n\"진 비밀을 밝히기 위해선 운도 제법 있어야 할 거야, 형씨.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"드르렁 드르렁 쿨쿨...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"혈석을 찾았다면 아무쪼록 조심히 다루세요.\\n\"\n\"\\n\"\n\"이제부터 만나게 될 수많은 위험을 벗어나려면 자신을 믿는 수밖에 없죠.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"용맹이란 갑옷을 찾는 건가요? \\n\"\n\"\\n\"\n\"아르케인이 어디다 감췄는지 아무도 못 알아냈죠. 내 연줄들도 못 찾았고요. 그쪽\"\n\"한테는 기대도 안 해요.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"자네가 말한 전사에 관해서라면 내가 알고 있는 전설이 하나 있다네. 죄악의 전쟁\"\n\"에 관한 오랜 역사서에 따르면...\\n\"\n\"\\n\"\n\" 천년의 전쟁을 통해 피의 전쟁군주는 자신이 쓰러트린 시체의 산위에 올라설 정도\"\n\"로 피와 죽음에 얼룩졌다고 하지. 전쟁군주의 암흑 검은 산 자에게 저주의 절규를 \"\n\"안겼고 이 지옥의 망나니 앞을 가로막는 자들은 모두 지옥 같은 고통을 맛보게 되\"\n\"었다고 하는군.\\n\"\n\"\\n\"\n\"더욱이 인간이었을 때는 죄악의 전쟁에서 암흑의 군단에 맞서 싸웠지만 피에 대한 \"\n\"끝없는 갈망으로 인간성을 인간성을 잃었다고 적혀 있네.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"그토록 잔인한 전사 얘기는 금시초문입니다. 듣기만 해도 위험해 보이는 그런 녀석\"\n\"과 싸우게 되는 일이 없길 빌겠습니다.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"이런 건 나보다 케인이 자세히 알고 있을 거네.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"그렇게 흉폭한 상대와 싸우게 된다면 빛이 당신을 이끌어 보호하길 기원할게요.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"피의 전쟁군주한텐 항상 사악한 전설이 따라다니지. 무자비한 놈이니까 철저히 준\"\n\"비하라고, 형씨.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"왜 맨날 피 얘기만 하는 거야? 꽃이나 날씨라든지, 술 가져오는 예쁜 아가씨라든\"\n\"지, 많이 있잖아. 이봐, 친구, 강박 관념에 사로잡혀 있는 거라고, 알겠어?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"녀석의 칼 솜씨는 정말 대단하죠. 전쟁만 하며 천년을 살아왔으니까요. 유감이지\"\n\"만... 당신이 녀석을 쓰러트릴 수 있을 것 같지는 않군요.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"그 전쟁군주란 녀석랑 거래는 안 해봤지만 칼을 꽤나 해먹나 보네요. 뭐, 녀석한\"\n\"테 칼을 팔 생각은 없지만요...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"내 칼이 네놈의 피를 갈구한다, 필멸자여. 내 어둠의 주인께서도 그것을 막지 않\"\n\"을 것이다.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"그리스월드가 말한 천상석은 동방으로 이송될 예정이었으나, 자세히 조사하기 위\"\n\"해 그리로 옮겨졌다네. 그 돌은 인간이 볼 수 없는 원기로 빛을 뿜어내지. 그것에 \"\n\"어떤 비밀이 담겨 있는지는 모르겠네만 그 돌을 찾는 것이 무척 중요한 일임은 틀\"\n\"림없네.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"그 대상은 동방 여정을 대비해 물자를 갖추러 여기에 들렀습니다. 신선한 과일과 \"\n\"제 처인 가르다가 구운 빵을 많이 사주었는데 그런 일이 일어났다니 안됐습니다...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"그 돌로 뭘 하려고 했는지는 모르겠지만 하늘에서 돌이 떨어진다면 조심하는 게 좋\"\n\"겠네!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"예, 뭔가 있어 보이는 대상 사람들이 여기에 들르긴 했지만 벌써 꽤 예전 일이네\"\n\"요. 이상한 억양이랑 오랜 여행 중이라고 말했던 게 기억이 나요. 그 사람들이 운\"\n\"반하던 걸 어떻게 찾을 수 있을지 모르겠네요.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"잠깐만 형씨, 재미있는 이야기가 있어. 옛날에 동방의 왕국으로 가던 대상이 여기\"\n\"를 지나갔는데 지상으로 떨어진 천상의 파편을 싣고 있었다나 봐! 그 대상은 여기 \"\n\"북쪽 지점에서 망토를 두른 기사들에게 습격을 당했지. 하늘 돌이 남아 있나 싶어 \"\n\"잔해를 뒤져 봤지만 없어졌더군. 형씨가 그걸 찾아내면 내가 아주 쓸만한 걸로 만\"\n\"들어 주지.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"천상석은 아직 못 찾았나 보지? 그걸로 엄청난 무기를 만들어 줄 수 있는데 말야.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"어디 보자고. 그래, 그래... 역시 생각했던 대로야. 잠깐만 기다려 봐...\\n\"\n\"\\n\"\n\"자, 여기. 아버지가 주신 은반지를 이 돌에 박아 넣었더니 딱이군. 유용하게 쓰이\"\n\"길 바라.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"난 멋진 반지를 갖고 있었어. 파랑에 초록에 빨강에 은빛까지... 정말 비싼 거였\"\n\"어. 어떻게 됐는지 생각이 안 나는데, 아마 잃어버린 것 같아...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"천상석은 매우 강한 힘을 지니고 있기에 그리스월드에게만 양도해야 해요. 그 사람\"\n\"이라면 우리 모두를 위해서 천상석의 힘을 올바르게 이끌어 낼 수 있을 거예요.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"그 돌로 뭔가 만들 수 있는 사람은 그리스월드밖에 없겠죠. 재주가 좋으니까요. 그\"\n\"쪽 손님을 빼오려는 입장이지만 그리스월드 솜씨만큼은 정말 대단해요.\"\n\n# Red Herring\n# 정체 모를 것, 논점을 벗어난 것, 훈제 청어\n# 검은 버섯처럼 자기 전문이 아닌 분야는\n# 잘 모르겠다는 뜻의 말장난.\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"마녀 아드리아가 검은 버섯을 찾는다고? 검은 버섯이나 훈제 청어 같은 건 잘 모른\"\n\"다네. 치료사 페핀이라면 조언을 줄 수 있을 테지만, 이건 내가 듣거나 읽은 적이 \"\n\"없는 거로군.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"이것만 말씀드리죠. 저희 부부는 귀한 발걸음을 하신 손님들에게 절대, 절대로 검\"\n\"은 버섯을 제공하지 않습니다. 아드리아가 자기 스튜에 무슨 버섯을 넣고 싶어하든\"\n\"지 간에 그건 아드리아 소관이죠. 아무튼 도움이 못 되어 드릴 것 같습니다. 검은 \"\n\"버섯이라니... 역겹군요!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"영약 만드는 걸 돕기 위해 자네가 마귀의 뇌를 찾고 있다고 아드리아에게 들었네. \"\n\"마귀들이 가진 마의 비밀을 풀 수만 있다면 그 사악한 괴수들에게 당한 사람들을 \"\n\"돕는 데 큰 도움이 될 거야. 마귀를 죽여서 뇌를 구하게 되거든 내게 가져다 주었\"\n\"으면 싶네만.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"대단해, 내 마음에 쏙 드는구만. 뇌 없이 영약은 완성했지만 연구용으로 사용하고 \"\n\"싶군. 이 영약을 아드리아에게 전해 주겠나? 틀림없이 이걸 기대하고 있을 테니 말\"\n\"이야.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"제 생각엔 오그덴의 창고에 있을 것 같은데, 한번 물어보지 그래요?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"아드리아가 갖고 있지 않은 거라면 상당히 귀한 물건인가 보군. 도움은 안 되겠지\"\n\"만... 아주 엄청 무지막지하게 큰 버섯인가 보던데! 한번 잘 찾아보라고.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"오그덴이 수상한 검은 버섯으로 뭔가를 만드는데, 그걸 마시면 병이 날 거야. 들어\"\n\"봐, 들어보라고... 이건 비밀인데... 적당히 하는 게 핵심이야!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"이게 과연 무엇일까요? 흥미롭게도 시약에 관한 책 같군요. 검은 버섯을 찾아보세\"\n\"요. 제법 커서 발견하기 쉬울 거예요. 찾으면 제게 가져오도록 하세요. 알겠나요?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"지금 만들고 있는 특별 조제약에 커다란 검은 버섯이 필요하니 어서 찾아오도록 하\"\n\"세요.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"그래요, 이거야말로 제가 조제하는 약에 필요한 거죠. 그나저나 치료사가 마귀의 \"\n\"뇌를 찾고 있어요. 독에 중독된 사람들을 치료하기 위한 영약 제조에 필요한 것 같\"\n\"더군요. 치료사가 필요로 하는 걸 찾으면, 영약 샘플을 하나 부탁해요.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"어째서 그런 걸 가져왔죠? 지금 마귀의 뇌 같은 건 필요하지 않아요. 치료사가 만\"\n\"들고 있는 영약이 필요한 거죠. 괴이한 장기 같은 건 치료사에게나 주고 제게는 영\"\n\"약을 가져오세요. 간단한 일이지 않나요?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"뭔가요? 치료사에게서 영약을 받아 온 건가요? 약은 이미 완성되었죠. 영약은 그\"\n\"냥 갖도록 하세요.\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"버섯 같은 건 취급 안 해요. 그보다 좀 더 좋은 게 있는데 어때요?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"그렇다면 그 지도의 전설이 사실이로군. 여지껏 진짜라고 믿었던 적은 없었지만 말\"\n\"일세! 내가 누구인지 밝혀야 할 때가 온 것 같구만...\\n\"\n\"\\n\"\n\"내 진짜 이름은 데커드 케인으로 영원한 악의 봉인을 수호하는 고대 결사대의 마지\"\n\"막 후예라네. 허나 아무래도 악마의 봉인이 풀린 듯하군...\\n\"\n\"\\n\"\n\"자네가 맞설 상대는 공포의 군주라 불리는 악마라네. 사람들에겐 디아블로라고 알\"\n\"려져 있는 있지. 녀석은 몇 세기 전 미궁에 유폐되었네. 자네가 손에 넣은 그 지도\"\n\"는 몇 세대 전에 만들어진 것으로 디아블로가 유폐에서 벗어나 다시 일어서는 시기\"\n\"가 기록되어 있네. 지도에 있는 두 개의 별이 일직선으로 늘어설 때가 바로 디아블\"\n\"로의 힘이 극에 달할 때이지.\\n\"\n\"\\n\"\n\"일각을 다투는 일이라네! 별이 늘어서기 전에 디아블로를 찾아 쓰러트리게. 놈에게\"\n\"서 벗어날 기회를 다시는 얻지 못할 수도 있으니 말일세!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"시간이 없네! 녀석이 어둠의 힘을 키우고 있는 게 느껴져. 녀석을 저지할 수 있는 \"\n\"건 자네뿐이야.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"자네가 최선을 다했다는 건 알지만 자네의 힘과 의지가 충분하지 못한 것 같아 걱\"\n\"정스럽네. 디아블로는 지금 속세의 힘이 극에 달했으니 녀석을 쓰러트리기 위해선 \"\n\"자네의 용기와 힘을 다해야만 해. 빛의 가호와 인도가 있기를 바라네. 나도 어떻게\"\n\"든 도와주겠네.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"마녀가 당신을 도울 수 없으니 케인 어르신을 만나 보라고 했다면 제가 나설 문제\"\n\"가 아니겠군요. 매우 심각한 문제인 것 같은데 아드리아 말대로 서둘러 이야기꾼\"\n\"을 만나 보십시오.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"이 지도의 문자는 나도 모르겠지만 아드리아나 케인이라면 해독할 수 있지 않을까 \"\n\"싶네. 하늘의 별을 그린 지도라는 건 알겠는데 그 이상은 모르겠군.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"그런 건 이야기꾼에게 물어보는 게 최고죠. 케인 할아버지는 고서에 정통하니까\"\n\"요. 그나저나 그렇게 낡은 종잇조각은 처음 보네요.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"이런 지도는 본 적이 없군. 어디서 입수한 거지? 나야 이걸 읽을 뾰족한 방법이 없\"\n\"지만 케인 영감님이나 아드리아라면 형씨가 찾는 해답을 줄 수 있을 거야.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"들어 봐. 좀 더 가까이 오라고. 아는진 모르겠지만 여기 정말 좋은 게 있어. 바로 \"\n\"지도야.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"아, 불길한 징조군요. 이 지도의 별은 대재앙을 예고하고 있으나 그것이 무엇인지\"\n\"는 알 수가 없어요. 이야기꾼과 진지하게 상담토록 하세요.\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"나도 지도를 찾고 있지만 그건 아니네요. 아드리아한테 보여 주면 아마 그게 뭔지 \"\n\"알려 줄 거예요. 하나 알려주자면, 낡아 보이는 지도지만 낡은 그 자체로 가치가 \"\n\"있는 거예요.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"부탁이야, 해치지 마. 죽이지 말아 줘. 살려 주면 다음에 좋은 걸 줄게.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"지금 만들고 있어. 그니까 가바드를 죽이지 말아 줘. 살려 주면 좋은 걸 줄 테니\"\n\"까.\\n\"\n\"\\n\"\n\"약속한 대로 이걸 가져가.\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"아직이야! 거의 다 됐어.\\n\"\n\"\\n\"\n\"정말 강하고 정말 튼튼한 거야. 그니까 살려 달라고!\\n\"\n\"\\n\"\n\"안 아프게 하면 난 약속을 지켜!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"정말 좋은 물건이야. 정말 강력한 거지! 갖고 싶어? 그럼 가져가 봐!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"뭐야? 여기서 뭐 하는거야? 방해받으면 미쳐 버릴 것 같단 말야. 자, 이거 갖고 그\"\n\"만 가 봐. 더는 방해하지 말고!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"으아아아! 그 호기심이 죽음을 부르는 거야!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"반갑네, 잠시 얘기 좀 들어보게나...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"미궁 속 깊이 돌아다니다 보면 위대한 지식이 담긴 책들이 숨겨져 있는 것을 발견\"\n\"할 수 있을 걸세. \\n\"\n\"\\n\"\n\"나조차도 생소한 것들이 쓰여 있을 테니 유심히 읽어 보게나.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"미궁을 탐색하다 보면 여러 의문이 들 수도 있을 텐데, 내가 아는 수많은 전설이\"\n\"나 신화 속에 그 답이 있을지도 모르니 궁금한 게 생기면 나를 찾아오게나. 아는 \"\n\"대로 가르쳐 줄 테니 말일세.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"그리스월드는 굳센 기백을 지닌 사내라네. 워트를 구하기 위해 미궁에 들어갔던 \"\n\"걸 본인 입으로 말했을 리는 없을 테지? 위험을 무릅쓰고 그랬건만... 이번엔 자네\"\n\"가 그러는군. 솜씨 좋은 장인이니 도움을 받을 일이 있으면 그 성의와 기술에 의지\"\n\"할 수 있을 걸세.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"오그덴이 해오름이라는 여관을 운영한 지 벌써 4년이 다 되어 가는군. 가게를 매입\"\n\"한 지 얼마 지나지 않아 이곳은 지옥으로 변해 버렸다네. 처인 가르다와 함께 이곳\"\n\"에 터를 잡느라 재산을 다 소진해서 떠날 여력이 없을 테지. 책임감이 강하고 선량\"\n\"한 사람인데 말일세.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"딱하지만 파넘을 보고 있자면 그 암흑의 날, 라자루스와 함께 대성당에 들어간 사\"\n\"람들이 떠올라 마음이 편치 않다네. 파넘은 간신히 살아 돌아왔으나 그만 정신줄\"\n\"을 놓고 무기력해졌지. 지금이야 술에만 의지하며 횡설수설하지만 개중에는 진실\"\n\"이 담겨 있는 말도 있을 걸세.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"마녀 아드리아는 이곳 트리스트럼의 별종이라네. 대성당이 악에 오염되어 다들 떠\"\n\"나던 무렵에 이곳에 왔지. 마을 변두리에 작은 오두막을 밤새워 지은 데다, 나조차\"\n\"도 본 적 없는 별스러운 유물과 학술서를 많이 갖고 있더군.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"워트에 관한 얘기는 끔찍하면서도 비극적이라네. 그 아인 제 어미와 떨어져 사악\"\n\"한 창을 휘두르는 마귀들에게 미궁으로 끌려갔지. 그날, 레오릭 왕의 아들을 포함\"\n\"해 많은 아이들이 끌려갔어. 근위병들이 구출하러 갔지만 아무도 돌아오지 못했\"\n\"지. 대장장이가 그 아이를 찾아냈지만 이미 마귀들에게 가학적인 고문을 당한 후였\"\n\"네.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"아, 페핀 말인가. 내가 여지껏 살아오면서 손에 꼽는 진정한 친구일세. 간혹 정신 \"\n\"없을 때가 있긴 해도 사려 깊고 이해심이 많은 친구이지. 학식과 기술도 대단해서 \"\n\"항시 사람들에게 도움을 준다네.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"질리언은 참한 처자라네. 신명난 웃음소리로 많은 이들에게 사랑받지. 나 또한 그\"\n\"리 여기고 말이야. 몸이 아파 거동이 불편한 할머니를 돌보기 위해 오그덴의 가게\"\n\"에서 일하고 있지. 종종 질리언의 안전이 염려스럽지만 이 마을 사내놈들 모두 그 \"\n\"아이를 지켜줄 거라 믿네.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"반갑습니다, 선생님. 해오름 여관에 오신 걸 환영합니다!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"수많은 모험가들이 제 가게를 거쳐 가며, 맥주잔이 넘처 날 정도로 많은 이야기들\"\n\"을 꽃피웠죠. 제가 들었던 것 중에 가장 와닿았던 건 바로 이 격언이었습니다. '고\"\n\"기를 썰려면 뼈를 부숴야 한다.' 선생님한테도 도움이 되실 겁니다.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"대장장이 그리스월드는 무기와 방어구에 정통하죠. 장비를 수선할 일이 있다면 그 \"\n\"사람이 적임자입니다.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"파넘은 슬픔에 젖어 싸구려 술로 허송세월하고 있습니다. 제가 도우려 하고는 있지\"\n\"만 미궁에서 그런 경험을 하면 그럴 수밖에 없겠지요.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"아드리아는 나이에 비해 무척 똑똑하지만 좀 꺼림직한 게 사실입니다. \\n\"\n\"\\n\"\n\"뭐, 큰 문제는 아니지만요. 마법 물품을 거래하려면 강 건너편에 있는 아드리아의 \"\n\"오두막에 가 보십시오.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"이 마을 역사에 관한 거라면 이야기꾼인 케인 어르신이 제법 상세히 알고 있습니\"\n\"다.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"워트는 골칫덩이가 아닐 수 없습니다. 항상 말썽을 부리는지라 무슨 변을 당한다 \"\n\"해도 놀랄 일도 아니죠.\\n\"\n\"\\n\"\n\"어리석게도 들이지 말아야 할 곳에 발을 들인 모양입니다. 안됐기는 해도 용납은 \"\n\"못하겠군요.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"페핀 선생님은 정말 좋은 분입니다. 마을에서 가장 인자한 분이기도 하고요. 늘 도\"\n\"움이 필요한 사람들을 돌보고 있지만 어째 그분이 가는 곳마다 자잘한 말썽이 잇따\"\n\"르는군요.\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"종업원 질리언 말입니까? 할머니를 돌볼 생각이 없었다면 진작에 떠났겠지요. 제\"\n\"가 할머니를 돌볼 테니 여기를 뜨라고 간곡히 부탁했건만, 참으로 마음씨 곱고 배\"\n\"려심 깊은 아가씨라 그러질 못하더군요.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"어디가 편찮으신가?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"무척이나 흥미로운 걸 발견했네. 우리와는 달리 미궁의 괴물들은 물약이나 마법 없\"\n\"이 스스로 상처를 치료할 수 있더군. 괴물을 잡을 때, 숨통을 확실히 끊지 않으면 \"\n\"스스로 재생할지도 모르는 일이야.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"지하에 잠복한 그 무언가에게 빼앗기기 전까지 대성당은 위대한 지식의 보고였어. \"\n\"거기엔 많은 책이 있지. 책을 찾게 되거든 전부 읽어 보게나. 미궁의 비밀이 기록\"\n\"되어 있을지도 모르니 말이야.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"내가 치료술에 박식한 것처럼 그리스월드는 무기와 갑옷에 정통하지. 영리한 장사\"\n\"꾼이기도 하지만 일 처리도 둘 째 가라면 서러울 정도야. 아, 그러니까 내말은 그 \"\n\"사람이 여기 남은 유일한 대장장이라서 그럴 거라는 뜻이네.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"케인은 진정한 친구이자 현자라네. 방대한 장서를 보존하는 데다 사물의 본질을 통\"\n\"찰하는 타고난 능력도 있으니 말이야. 궁금한 게 생기거든 그 친구에게 가 보게.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"내 실력으로도 파넘을 온전히 치료할 수가 없었어. 육신은 치료할 수 있었지만 마\"\n\"음과 정신은 어떻게 할 도리가 없었지.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"나도 특정 마법을 사용해 비축할 물약과 영약을 제조하지만 아드리아는 진짜 마법\"\n\"사야. 잠도 안 잘뿐더러 다수의 신비한 학술서와 유물에도 정통하더라고. 그 여자 \"\n\"오두막엔 겉보기와 달리 뭔가가 더 있을 것 같은데, 그 안에 좀처럼 들어가 볼 수\"\n\"가 없군.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"가엾은 워트. 그 아이를 위해 최선을 다했지만 의족을 달 수밖에 없었지. 그 아이\"\n\"가 의족을 혐오하는 건 알았지만 상처가 너무 심했어. 그토록 어린아이가 그런 괴\"\n\"로움을 겪어선 안 될 일인데.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"오그덴이 왜 트리스트럼에 머물고 있는지 도통 이해가 안 가. 정서가 다소 불안정\"\n\"한 면이 있지만 총명한 데다 근면해서 어디를 가도 성공할 텐데 말이야. 인근 지역\"\n\"에서 살인이 빈번히 일어나는 게 두려워서 그럴 수도 있겠지만 가족들이 그대로 머\"\n\"물기를 아내가 바라서 그럴지도 모르지.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"오그덴이 고용한 여급은 정말 참한 아가씨야. 그 아가씨 할머니는 병이 중한데다 \"\n\"망상을 겪고 있지. 본인 말로는 예지몽이라고 하는데 증명할 방법이 없지 않겠나.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"안녕하세요! 뭘 도와드릴까요?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"할머니는 당신이 저와 얘기하러 오는 꿈을 꾸셨어요. 예지몽을 꾸신 거죠. 미래를 \"\n\"볼 수 있는 거 말이에요.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"마을 끝에 사는 그 여자는 마녀예요! 좋은 사람인 것 같고 아드리아라는 이름도 예\"\n\"쁘지만 어쩐지 그 여자가 무섭네요. 그 여자가 거기서 뭘 하는지, 당신처럼 용기 \"\n\"있는 사람이 보러 가 주면 좋겠는데 말이죠.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"대장장이 그리스월드는 트리스트럼의 자랑이에요. 수많은 경연 대회를 휩쓴 장인\"\n\"일 뿐만 아니라 지금은 고인이 된 레오릭 왕에게 직접 찬사를 받기도 했죠. 그리스\"\n\"월드는 훌륭한 영웅이기도 하답니다. 케인 할아버지에게 물어봐도 그렇다고 할걸\"\n\"요.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"케인 할아버지는 옛부터 쭉 트리스트럼의 이야기꾼이었죠. 정말 박식해서 대개는 \"\n\"알고 있을 거예요.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"파넘은 맥주로 배를 채우고 쓸데없는 말만 지껄이는 술고래죠. 페핀 선생님과 오그\"\n\"덴이 그 사람을 동정하는 건 알지만 매일 밤 술에 취해 정신 못 차리는 걸 보면 짜\"\n\"증스러울 따름이에요.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"페핀 선생님은 제 할머니의 목숨을 구해 주셨죠. 그 은혜를 다 갚을 수 있을런지 \"\n\"모르겠네요. 병을 다스리는 그분의 힘은 그 어떤 칼보다도 강하며 그 어떤 마법보\"\n\"다도 신비롭답니다. 혹시 치료가 필요하면 페핀 선생님이 도와줄실 거예요.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"전 워트의 엄마인 캐너스와 함께 자랐죠. 워트가 저 끔찍한 괴물들에게 끌려갔을 \"\n\"때, 캐너스는 가벼운 부상에 그쳤지만 결국 회복하지 못했어요. 절망감이 그녀를 \"\n\"죽게 만든 것이겠죠. 워트는 타인의 노력을 가로채서 이득만 챙기는 비열한 아이\"\n\"가 되어 버렸더군요. 그 아이에게는 여전히 어둠이 드리워진 것 같네요.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"오그덴 부부는 저와 할머니를 자신들 집으로 데려가 저에게 가게 일자리까지 마련\"\n\"해 주셨죠. 신세 진 게 너무 많아서, 언젠가 여기를 떠나 그분들이 동부에서 훌륭\"\n\"한 호텔을 여는 걸 돕고 싶어요.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"그래, 뭘 도와드릴까, 형씨?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"괜찮은 무기를 찾는 거라면 이건 어떤가, 형씨? 전곤 같은 둔기는 언데드에게 효과\"\n\"가 아주 그만이지. 비실비실한 해골들을 작살낼 때도 이만한 게 없다고!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"도끼? 그래, 좋은 무기라 어떤 적과 맞서도 부족함이 없지. 허공을 가르기만 해도 \"\n\"바닥에 널부러져 있을 악마 놈 대가리가 눈앞에 선하군. 잽싸게 휘두르는 건 무리\"\n\"지만 파괴력은 발군이니 염두에 두도록 해!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"어때? 날이 살아 있고 균형미가 있다고. 검이라는 건 말야, 적격인 사람이 쓰면 최\"\n\"강의 무기가 되거든. 언데드에겐 날카로운 칼날이 잘 안 먹히지만 상대가 생명체라\"\n\"면 놈들의 몸뚱이를 간단히 썰어 버릴 수 있지!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"형씨의 무기와 갑옷을 보니 어둠의 세력에 맞서 얼마나 고군분투했는가를 한눈에 \"\n\"알겠군. 약간의 수고로 신품처럼 고칠 수 있으니 나한테 가져오라고.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"난 이 젠장할 마을 변두리에 오는 대상들에게서 금속이나 공구를 밀수해야 하는\"\n\"데, 마녀 아드리아는 필요한 걸 항상 손에 넣는 거 같더군. 그 여자처럼 마법을 조\"\n\"금만이라도 알았으면 정말 끝내주는 물건을 만들 수 있을 텐데 말이야.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"질리언은 괜찮은 아가씨지. 그 아가씨 할매가 저렇게 아프지만 않았어도 대상들에\"\n\"게 부탁해 여기를 벗어나게 해주고 싶은데 말이야.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"케인 영감님은 때때로 말이 너무 많은 거 아닌가 싶지만 그게 자기 천성이니 어쩔 \"\n\"수 없겠지. 케인 영감님이 형씨 귀를 닫게 만드는 것처럼 내가 강철을 다룰 수 있\"\n\"다면, 황제한테도 어울릴 왕실 갑옷을 만들 수 있을 텐데 말이야!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"라자루스가 우리를 이끌고 미궁에 갔던 날 밤에 난 파넘과 함께였지. 대주교는 종\"\n\"적을 감춘데다 파넘이 곁에 없었다면 난 아마 죽었을 거야. 안됐지만 녀석은 영혼\"\n\"에 상처를 입었어. 내가 다리를 다친 것처럼 말야. 그래서 이제는 파넘을 위해 싸\"\n\"울 수 없지만, 그럴 수 있다면 기꺼이 싸우겠어.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"페핀 영감님은 자신보다 남을 먼저 생각하는 훌륭한 분이지. 트리스트럼뿐만 아니\"\n\"라 그 어디에도 그분을 험담하는 사람은 아무도 없다고.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"저 애송이 새낀 언제 한번 크게 혼날 거야. 여기서 일하며 정직하게 장사하는 걸 \"\n\"가르치려 했는데, 밀수품 거래로 돈 좀 만지는 쪽이 성미에 맞는다나. 큰일을 겪었\"\n\"으니 뭐라고는 못 하겠지만 좀 더 신중했으면 좋겠는데 말야.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"여관 주인 오그덴은 밑지면서 장사를 해. 이따금 마을을 지나는 여행자들에게 숙식\"\n\"을 제공하면서 근근이 꾸려가기는 하는데 요금을 떼어먹고 튀는 새끼들이 있거든. \"\n\"그 양반이 창고에 곡물과 육포를 비축해 놓지 않았더라면 마귀놈들이 이 일대를 장\"\n\"악했을 때 모두 굶어 죽었을 거야.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"술 마시게 좀 내버려 두겠어?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"그 술 갖다주는 여자? 아, 그래, 예쁘장한 처자지, 성격도 좋고.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"그 쭈그렁탱이 할망구는 왜 아무것도 안 하고 있나 몰라. 맞아, 맞아, 그 할망구\"\n\"가 물건을 갖고는 있지만... 정말 이상해. 뭔가를 먹거나 마시는 걸 본 적이 없\"\n\"어. 그러게 아무것도 마시지 않는 놈들은 믿으면 안 돼.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"케인은 정체를 숨기고 있어. 그래, 그래, 그 영감 하는 얘기가 재미는 있지... 정\"\n\"말 무서운 얘기라든지, 만담이라든지... 그래도 실은 더 많은 걸 알고 있지 않나 \"\n\"싶어.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"그리스월드? 정말 좋은 녀석이야. 내 형제나 다름없으니까! 우린 함께 싸웠지. 그\"\n\"러니까 그때... 우린... 라자루스... 라자루스... 라자루스!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"히히히, 난 페핀이 좋아. 알겠지만 그 양반 정말 열심이거든. 알아 두면 좋을 거\"\n\"야. 항상 사람들을 돕는 착한 양반이니까. 그래, 당신 같은 부류군. 뭐? 영웅? 나\"\n\"도 영웅이었지...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"워트 녀석은 나보다 더 지독한 걸 겪었지. 난 다 알아. 밀수품 거래를 하는 건 거\"\n\"기에 있었기 때문이야. 알겠어? 한쪽 다리를 잃었다고! 돌아다니려면 나무 지팡이\"\n\"가 있어야 해. 정말 안됐어, 정말로...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"오그덴은 마을에서 제일 좋은 녀석이야. 그 친구 마누라는 날 별로 안 좋아하는 눈\"\n\"치지만 나한테 술을 주는 한, 난 그 여자가 좋기만 한걸. 내가 오그덴하고 한식구\"\n\"처럼 보이나 본데, 그 친구가 나한테 정말 잘하긴 해...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"말하고 싶은 게 있는데 난 이 술에 대해 정말 잘 알아. 특제품이거든. 최고의 물건\"\n\"이라고... 최-----고 말야! 다른 술은 개나 주라지...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"아무도 내 말을... 딸꾹... 안 믿지만 말야, 어딘가에, 그러니까 장담은 못하지만 \"\n\"대성당 지하 어딘가에 금덩어리가 쌓여 있어. 반짝반짝 빛나는 데다가 줍는 놈이 \"\n\"임자라고.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"당신도 나름대로 생각하는 바가 있을 테니 이 얘기를 안 믿겠지만 저기서 산 무기\"\n\"는 큰 괴물한테 안 먹혀. 아, 그리스월드가 뭐라든 상관없어. 실력이 예전만 못하\"\n\"니까...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"내가 당신이면... 물론 아니지만... 어쨌든 당신이라면 가진 걸 다 팔고 여길 떠나\"\n\"겠어. 저 밖에 있는 꼬맹이 녀석은... 항상 뭔가 좋은 걸 갖고 있지만 돈을 좀 쥐\"\n\"어 줘야 갖고 있는 걸 보여 줄 거야.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"답을 찾아 헤매는 영혼이 느껴지는군요...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"지혜란 구하는 것이지 그냥 주어지는 것이 아니죠. 지식이 담긴 서적을 발견하면 \"\n\"그 책을 탐독하도록 하세요. 책에 담긴 신비한 지식을 이해할 수 있다면 숙련도가 \"\n\"더욱 증가할 테니까요.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"강력한 힘은 대게 단명하는 법이죠.. 고대 힘의 언어가 쓰인 양피지 두루마리를 발\"\n\"견하는 경우가 있을 거예요. 두루마리의 장점은 숙련자든 초보자든 같은 능력을 발\"\n\"휘할 수 있다는 거고, 단점은 그 자리에서 소리 내어 읽어야 하기에 미리 기억해 \"\n\"둘 수 없다는 거죠. 또한 두루마리는 딱 한 번만 읽을 수 있으니 잘 생각해서 사용\"\n\"해야 해요.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"태양의 그 뜨거움을 가늠할 길은 없지만, 한낱 양초의 불길이 더 위험할 때도 있\"\n\"는 법이죠. 아무리 강력한 에너지라도 한데 모으지 않으면 소용이 없어요. 지팡이\"\n\"에 담겼던 많은 주문을 마법 에너지로 다시 충전할 수 있죠. 나에겐 그 힘을 되돌\"\n\"릴 능력이 있지만 금전적인 대가가 필요해요.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"머리를 맞대면 지식도 그 만큼 늘어나는 법이죠. 해석할 수 없는 책이나 두루마리\"\n\"를 찾으면 망설이지 말고 제게 가져오도록 하세요. 해석해서 그 내용을 함께 나눌 \"\n\"테니까요.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"강철밖에 모르는 자에겐 강철이야말로 최강의 마법인 셈이죠. 본인은 자각 못 하지\"\n\"만 대장장이 그리스월드는 정말로 마술사 그 이상이에요. 불과 금속을 융합시키는 \"\n\"그의 능력은 견줄 자가 없죠.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"타락에는 기만의 기운이 담겨 있지만 순결에는 맑은 기운이 서려 있어요. 질리언이\"\n\"라는 젊은 여성은 순수한 마음을 지니고 있어서 자신보다 조모를 먼저 생각하죠. \"\n\"질리언이 저를 두려워하는 건 그저 저를 이해하지 못하기 때문이에요.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"어둠 속이든 빛 속이든 상자 속의 보물은 변함이 없는 법이죠. 이야기꾼 케인은 수\"\n\"수께끼 같은 인물이지만 겉만 보고 하는 소리예요. 케인은 자신이 생ㄱ하는 것보\"\n\"다 대성당 지하에 있는 것에 대해 훨씬 더 많이 알고 있어요.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"신뢰가 깊을수록 그 절망감은 더욱 깊은 법이죠. 파넘의 영혼을 앗아 간 건 마귀 \"\n\"따위가 아니에요. 대주교 라자루스가 마을 사람들을 배신한 걸 보고 그렇게 되었\"\n\"죠. 파넘에게서 정보를 얻을 수도 있겠지만 진실과 허구를 잘 가려서 들도록 하세\"\n\"요.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"기술과 마음 그리고 정신이 완벽하게 조화를 이룰 때, 기적을 일으킬 수 있는 법이\"\n\"죠. 치료사 페핀은 몸속을 훤히 꿰뚫어 보지만 저로선 불가능한 일이에요. 환자를 \"\n\"치료하는 페핀의 능력은 영약과 물약 제조에 대한 이해를 바탕으로 더욱 증대하고 \"\n\"있죠. 트리스트럼에서 그만큼 든든한 아군은 없을 거예요.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"알 수 없는 다양한 미래가 있지만 그때가 오면 세상을 지배하는 건 아이들이죠. 워\"\n\"트는 영혼에 어둠이 드리워졌지만 마을이나 주민들에게 해가 될 정도는 아니에요. \"\n\"이웃 마을의 부랑아나 비밀스러운 길드와 은밀한 거래를 하기에 트리스트럼에서는 \"\n\"쉽게 구할 수 없는 것들을 접할 수 있죠. 방법이 좀 그럴지는 몰라도 잠식해오는 \"\n\"어둠과 맞섬에 있어 워트가 도움이 될 거예요.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"벽과 지붕이 있다고 해서 집이 되는 건 아니죠. 여관 주인 오그덴은 사람들이 생각\"\n\"하는 것보다 이 마을에서 훨씬 더 많은 역할을 하고 있어요. 질리언과 그 조모에\"\n\"게 보금자리를 마련해 주고 파넘의 남은 생애를 돌볼 뿐만 아니라 남은 마을 사람\"\n\"들에게 옛 트리스트럼과의 유대를 이어 주고 있죠. 오그덴의 여관에는 소박한 즐거\"\n\"움이 여전히 남아 있기에 그리운 옛 기억을 상기시키는 거죠. 그러한 추억이 당신\"\n\"의 성공을 기원하는 원동력이 되는 거예요.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"쉬잇... 여기예요...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"트리스트럼엔 그쪽이 미궁에서 발견한 걸 쓰려는 사람이 아무도 없어요. 못 믿을\"\n\"진 몰라도 난 아니지만요.\\n\"\n\"\\n\"\n\"때론 그쪽한테 필요한 걸 발견할 수도 있을 거예요.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"주정뱅이들이 하는 말은 하나도 믿지 마요. 술은 판단력을 흐리게 하니까요.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"그쪽이 아직 몰라서 그러나 본데 난 트리스트럼에서 어떤 것도 매입하지 않아요. \"\n\"품질 좋은 제품만 들인다고요. 고물딱지를 팔고 싶으면 그리스월드나 페핀, 아니\"\n\"면 아드리아한테나 가 봐요. 그딴 걸 가져가도 틀림없이 응해 줄 테니까요...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"대장장이 그리스월드는 내 생명의 은인이에요. 게다가 날 대장간 도제로 들였죠. \"\n\"정말 멋진 사나이에요. 하지만 난 돈이 정말 많이 필요하거든요... 뭐, 막대한 돈\"\n\"이 드는 계획이 있어서라고 해두죠.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"내가 좀만 더 나이가 많았으면 질리언한테 값비싼 것들을 한아름 안겨 줘서 내 여\"\n\"자로 만들었을 텐데 말이죠. 질리안은 예쁜 여자라서 트리스트럼처럼 위험한 데 있\"\n\"으면 안 돼요. 흐음... 내가 여기를 떠날 때 데리고 가면 되겠죠...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"케인 영감은 너무 많이 알아서 탈이에요. 정말 오싹하게 만든다니까요. 심지어 강 \"\n\"건너 사는 아줌마보다 더하죠. 내가 살아 돌아온 게 기적이라느니, 전설에 이미 예\"\n\"견된 일이라느니 이런 말만 해대요. 늙다리가 어련하겠어요.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"파넘은 심각한 문제를 안고 있죠. 그게 얼마나 심각한 건지 나도 잘 알아요. 전적\"\n\"으로 믿었던 라자루스가 파넘을 죽음의 문턱까지 이르게 했거든요. 아, 난 그게 어\"\n\"떤 건지 알고 있으니까 미궁에 있는 악귀를 어떻게 쓸어버릴 건지 굳이 나한테 말\"\n\"할 필요는 없어요. 그쪽 다리나 조심하세요...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"떨어져 나간 손발을 다시 붙인 것처럼 느껴질 정도로 페핀 영감은 정말 솜씨가 좋\"\n\"아요.\\n\"\n\"\\n\"\n\"페핀이 만든 물약이 있었더라면 내 다리는 멀쩡했겠죠...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"아드리아는 정말 성가셔요. 물론 케인 영감이 해주는 옛날 얘기도 오싹하지만 저 \"\n\"마녀는 과거를 볼 수 있거든요. 게다가 필요한 건 항상 손에 넣더군요. 아드리아\"\n\"는 축제 때 열리는 시장에서 본 것보다도 더 많은 상품을 갖고 있더라고요.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"오그덴은 바보예요. 비교적 싼 가격에 이 마을을 벗어나게 해주겠다고 했는데 저 \"\n\"거지 같은 가게를 계속 운영해야 한다더군요. 뭐, 적어도 질리언은 계속 일할 수 \"\n\"있는 데다 가르다 아줌마는 끝내주는 셰퍼드 파이를 만들어 주긴 하지만요...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"영웅의 전당 너머에는 뼈의 방이 있다. 그 방의 보물을 훔치려 하는 자에게는 영원\"\n\"한 죽음이 기다릴지니, 이는 공포의 군주께서 하신 말씀이자 이곳에 기록되어 있\"\n\"는 바이다.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...그리하여 피의 관문 넘어 불의 전당을 지난 곳에서 용맹은 빛의 영웅이 눈뜨기\"\n\"를 기다리고 있노라...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"그대가 보지 못하는 것을 나는 볼 수 있다.\\n\"\n\"시야는 흐려지고 눈은 썩어든다.\\n\"\n\"뒤돌면 그들은 신비한 노래를 속삭이며 사라질 것이다.\\n\"\n\"그리하면 그대는 불가능한 것을 보게 된다.\\n\"\n\"빛이 있어야 할 곳에 드리우는 그림자.\\n\"\n\"어둠의 밖은 광기의 세계,\\n\"\n\"눈먼 자의 전당에서 절망하리라.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"지옥의 무기고는 피의 전쟁군주의 장군의 거처이다. 그의 각성으로 기천의 시체가 \"\n\"줄을 잇는다. 천사와 인간도 피만을 갈구하는 어둠의 존재의 제물로서 잇달아 찢기\"\n\"어 갔다.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"유념하라. 그리고 여기 놓인 진실을 증언하라. 그것은 호라드림 최후의 유산이기 \"\n\"때문이다. 이상향 천국과 무저갱 업화 지옥 간의 전쟁은 지금도 이 땅에 퍼져 가\"\n\"고 있다. 저 하늘의 별보다도 오래도록 지속되어 온 이 전쟁은 위대한 투쟁이라 알\"\n\"려져 있다. 어느 한쪽도 승부를 내지 못한 채, 빛과 어둠의 군세는 숨쉬는 모든 것\"\n\"을 지배하기 위해 끝없이 겨루고 있다.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"유념하라. 그리고 여기 놓인 진실을 증언하라. 그것은 호라드림 최후의 유산이기 \"\n\"때문이다. 죄악의 전쟁이라 불리는 천국과 불타는 지옥 간의 영원한 분쟁이 일어났\"\n\"을 때, 천사와 악마가 인간의 모습으로 이 땅에 나타나 인간의 눈을 피해 비밀리\"\n\"에 싸웠다. 용기 있고 강인한 인간들도 양측과 각각 연합해 죄악의 전쟁의 향방을 \"\n\"이끄는 것에 힘을 빌려 주었다.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"유념하라. 그리고 여기 놓인 진실을 증언하라. 그것은 호라드림 최후의 유산이기 \"\n\"때문이다. 지금으로부터 약 300 년 전, 지옥의 대악마 셋이 느닷없이 이 땅에 강림\"\n\"했다. 삼 형제는 수십 년에 걸쳐 동방을 황폐화시켰고 인류는 그들 앞에서 그저 숨\"\n\"을 죽일 수밖에 없었다. 악마 삼 형제를 저지하기 위해 마법사들은 호라드림이라\"\n\"는 비밀 조직을 결성하였다.\\n\"\n\"\\n\"\n\"호라드림은 영혼석이라 불리는 강력한 유물로 삼 형제 중 둘을 봉인, 동방의 사막 \"\n\"깊숙이 매장하였다. 남은 하나는 도주하였고 호라드림의 많은 이들이 그 뒤를 추적\"\n\"하였다. 공포의 군주 디아블로라고 알려진 그 세 번째 악마도 결국에는 잡혔고 그 \"\n\"영혼을 영혼석에 거두어 이 미궁에 매장하였다.\\n\"\n\"\\n\"\n\"영혼석이 진실되지 못한 자들에게 발견되는 것을 경계해야 한다. 디아블로가 해방\"\n\"된다면 쇠약해졌을 것이기에 지배하기 쉬운 노약자의 육신을 갈구할 것이다.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"그리하여 어둠의 대추방이라 알려진 지옥의 대혁명이 일어났다. 고위 악마들이 연\"\n\"합하여 대악마 삼 형제를 타도, 그 영혼을 인간 세상으로 추방하였던 것이다. 삼 \"\n\"형제가 사라지자 거짓의 군주 벨리알과 죄악의 군주 아즈모단은 지옥의 패권을 두\"\n\"고 싸우기 시작하였다. 천국의 군대가 지옥문을 끊임없이 포격하던 그때, 지옥은 \"\n\"벨리알과 아즈모단의 내분으로 양분되었다.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"삼 형제를 찾아 많은 악마가 인간 세상으로 왔다. 뒤따라온 천사들은 동방의 도처\"\n\"에서 악마 사냥을 시작하였다. 천사들은 호라드림이라고 하는 인간 마법사들의 비\"\n\"밀 조직과 손을 잡았다. 악마 사냥이 주특기인 호라드림은 황천에서 많은 어둠의 \"\n\"적을 만들어 갔다.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"그리하여 인간 세계로 추방된 대악마 삼 형제의 영혼은 수십 년에 걸쳐 동방에 혼\"\n\"란을 야기시킨 끝에 호라드림에게 저지당하였다. 호라드림은 영혼석이라는 유물을 \"\n\"이용하여 증오의 군주 메피스토와 그의 형제인 파괴의 군주 바알의 영혼을 봉인하\"\n\"였다. \\n\"\n\"\\n\"\n\"막내인 공포의 군주 디아블로는 서방으로 도주하였으나 디아블로 또한 영혼석에 봉\"\n\"인되어 잊힌 고대의 대성당 지하에 안치되었다. 공포의 군주는 잠들어 소생의 때\"\n\"를 기다리고 있다. 디아블로는 순수하고 지배하기 쉬운 젊은 육신를 갈구할 것임\"\n\"을 기억하라. 그가 자신의 형제를 해방시켜 다시 한번 죄악의 전쟁의 불씨를 지피\"\n\"리라...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"어둠의 추방자이자 생존자인 공포의 군주 디아블로를 찬양할지어다. 나의 주군이시\"\n\"자 주인께서는 기나긴 잠에서 깨어나 인간에게 알려지지 않은 비밀을 내게 말씀해 \"\n\"주셨다. 바로 천국과 업화로 불타는 지옥과의 영원한 전쟁에 관한 것이다. 그리고 \"\n\"인간 세상에 분쟁을 초래한 그 힘을 계시하시니, 이 세상과 세상에 존재하는 모든 \"\n\"것에 말미된 그 싸움을 죄악의 전쟁이라 명명하셨다.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"삼 형제의 선도이자 공포의 군주인 디아블로에게 영광이 있으리라. 나의 주군께서\"\n\"는 아득한 옛날 이 세상에서 추방된 자신의 형제, 메피스토와 바알에 대해 말씀해 \"\n\"주셨다. 주군께서는 때가 무르익기를 기다리며 무시무시한 힘을 비축하여 동방의 \"\n\"사막 밑에 매장된 형제들을 자유롭게 하려 하시니, 주군께서 자신의 형제를 해방하\"\n\"는 날, 죄악의 전쟁에는 다시 한번 삼 형제의 분노가 서릴지어다.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"영혼의 파괴자이자 공포의 군주인 디아블로에게 헌신하고 경배하라! 나의 주인을 \"\n\"잠에서 깨웠을 때, 그분께서는 인간의 육신를 갈구하셨다. 레오릭 왕의 육신을 취\"\n\"하려 하셨으나 오랜 구속으로 심히 쇠약하셨다. 주군께서는 이 세상에 뿌리내리기 \"\n\"위해 순진무구한 닻을 필요로 하셨고 알브레히트 왕자가 그러한 닻에 적합한 자임\"\n\"을 알게 되셨다. 디아블로 님의 빙의 실패로 덕망 있던 레오릭 왕이 미쳐 버린 사\"\n\"이, 나는 알프레히트 왕자를 납치해 나의 주인 앞으로 데려갔다. 나는 지금 디아블\"\n\"로 님의 부름을 기다리며 그분께서 이 세상의 제왕으로 군림하는 날, 내게 보답하\"\n\"실 것을 기도한다.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"세상에나, 돌아오셨군요! \\n\"\n\"당신이 떠난 후로 많은 게 변했습니다. 이토록 평화로웠던 마을에 어둠의 기수들\"\n\"이 나타나 마을을 파괴해 버렸죠. 그들이 지나간 자리는 초토화되었고 무기를 들\"\n\"고 맞선 사람들은 살해당하거나 끌려가 노예가 되기도 했습니다. 마을 끝에 있는 \"\n\"대성당도 악으로 오염돼 어둠의 의식에 이용되고 있습니다. 밤마다 울려퍼지는 비\"\n\"명소리가 너무도 끔찍하지만 마을 주민 몇몇은 아직 살아 있는 것 같더군요. 제 가\"\n\"게와 대장장이 상점 사이에 있는 길을 따라가면 대성당이 있으니 부디 한 사람이라\"\n\"도 더 많은 이들을 구해 주십시오. \\n\"\n\"\\n\"\n\"다시 만나게 되면 더 많은 걸 말씀드릴 수 있을 테죠. 행운을 빌겠습니다.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"탐험을 계속하세요. 잃어버린 보물을 찾는다는 건 쉬운 일이 아니니 그보다는 상대\"\n\"적으로 좀 더 드러난 보물을 찾아보세요. 이건 당신에게 맡기도록 하죠. 시간의 모\"\n\"래가 당신의 탐색을 흐트리지 않도록 하세요.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"뭐?! 아이고 이 양반아. 여기 트리스트럼에 보물 같은 게 묻혀 있을 리가 있나. 어\"\n\"디 보자고!! 어째 그림이 틀린 거 같은데. 우리 마을하고 전혀 맞질 않잖아. 우리 \"\n\"발밑에 있는 것보단 대성당 밑에 있는 게 난 더 신경쓰이는군.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"자네가 찾고 있는 지도에 관해 얘기할 시간이 도무지 나질 않는군 그래. 나와 자\"\n\"네 도움이 필요한 환자들이 넘치니 말이야.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"한때 자만하던 이즈월은 이 세상 땅속 깊숙이 갇혀 있어요. 그의 명예는 실추되었\"\n\"고 얼굴은 변한 채, 불멸의 고통 속에 갇혀 있죠. 자신을 자유롭게 할 그 무언가\"\n\"를 은폐했다는 혐의를 받고 있죠.\"\n\n# your nose in the dirt\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"워트 녀석은 당신이 오는 걸 알고선, 당신이 마을 여기저기서 애먹는 걸 보고 비웃\"\n\"으려 했던 게 틀림없습니다. 무시해야겠군요.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"이 마을은 먼 곳에서 온 여행자들이 자주 들르던 시절이 있었네. 그 이래로 많은 \"\n\"것이 변했지만, 숨겨진 동굴과 보물 같은 건 아이들이 흔히 할 법한 공상이지. 워\"\n\"트는 아이들 놀이에 좀처럼 끼질 않았네. 그러니 그건 그저 그 아이의 상상일 수\"\n\"도 있을 테지.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"들어봐. 좀 더 가까이 오라고. 아는진 모르겠지만 여기 정말 좋은 게 있어. 바로 \"\n\"지도야.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"할머니는 교회 밖 묘지에 서식하는 기이한 힘에 대해 종종 말씀하세요. 당신이 듣\"\n\"기엔 흥미로운 얘기일 테죠. 적당한 공물을 묘지에 둔 다음, 대성당에 가서 죽은 \"\n\"자를 위해 기도하고 돌아오면 공물이 기이하게 바뀔 거라고 할머니가 그러셨어요. \"\n\"아프신 할머니가 그냥 하는 얘기겠지만, 요사이 일들을 보면 말도 안 되는 일 같\"\n\"진 않네요.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"흐음. 신비롭고 막대한 보물이라고 그랬나요? 몫을 좀 나눠 준다면 흥미가 있겠는\"\n\"데... 그보단 고생하는 그쪽한테 딱인 진귀한 물건이 있는데 안 살래요?\"\n\n# 아드리아가 농부한테 준 걸 주인공한테 주는지 모르겠음.\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"그러니까 당신이 모두가 말하는 영웅이시군요. 그저 가난하고 평범한 이 농부를 심\"\n\"각한 곤경에서 벗어나게 해 주시겠습니까? 제 과수원 모퉁이에, 그러니까 여기서 \"\n\"바로 남쪽에 땅 위으로 부풀어 오른 끔찍한 것이 있습니다. 농작품이나 건초를 수\"\n\"확할 수 없어서 불쌍한 소들이 굶어 죽게 생겼죠. 마녀가 이걸 주며 이게 제 땅에\"\n\"서 그 끔찍한 걸 날려 버릴 거라더군요. 당신이 없애만 주신다면 그 은혜를 영원\"\n\"히 잊지 않겠습니다. 제가 직접하고 싶지만 누군가는 소와 함께 있어야 해서 말이\"\n\"죠...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"마녀 말처럼 간단히 될 거라고는 생각하지 않았습니다. 이웃도 못 믿을 슬픈 세상\"\n\"이로군요.\"\n\n# 문맥상 it이 아드라이가 준 거 같긴 한데 헬파이어를 해보지 않아서 정확히 모르겠음.\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"없앴습니까? 그게 태어난 하데스의 깊숙한 곳으로 돌려보내셨나요? 뭐라고요? 마녀\"\n\"가 준 걸 잃어버렸단 소린 하지 마세요! 그냥 공으로 얻을 수 있는 것들이 아니라\"\n\"고요. 마녀가 준 걸 찾아서 우리 마을에서 그 끔찍한 걸 날려 버리셔야 합니다.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"여기서 폭발 소리가 들렸습니다! . 친절하신 이방인분께 그저 감사할 따름입니다. \"\n\"이런 것들이 땅 위에 생기질 않나, 괴물들이 교회를 장악하질 않나, 힘든 시기가 \"\n\"아닐 수 없군요. 전 그저 가난한 농부에 불과하지만 부디 제 정성을 받아 주십시\"\n\"오.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"아, 그런 문제가 있습니다... 어쩌면... 아닙니다, 다른 문제들까지 전부 당신에\"\n\"게 떠맡길 순 없죠. 교회에서 괴물들을 좀 정리하고 돌아오시면... 가난한 농부를 \"\n\"도울 시간 좀 내주실 수 있을까요?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"우와아아앙! (훌쩍) 우와아아앙! (훌쩍)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"테오를 잃어버렸어요. 내 가장 소중한 친구를 잃어버렸다고요! 같이 강가에서 놀\"\n\"고 있었는데 테오가 커다란 녹색 물체를 보러 가고 싶다고 그랬거든요. 내가 그러\"\n\"면 안 된다고 말했지만, 결국 거기에 같이 몰래 들어갔는데 갑자기 이런 벌레가 나\"\n\"타났어요! 도망치다가 테오가 넘어졌고 벌레가 테오를 데려간 거예요!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"테오를 찾았나요? 제발 테오도어를 찾아 주세요! 아직 어린애예요. 혼자 못 있는다\"\n\"고요! 제발요!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"테오를 찾아주셨군요! 찾아주셨어요! 고마워요! 테오야, 그 못된 벌레들 땜에 많\"\n\"이 놀랐지? 어머! 으앗! 겉에 뭐가 묻었잖아! 으이구! 어서 집에 가자, 테오야! 정\"\n\"말 고마워요, 영웅 아저씨!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"우리는 오래도록 동면하였으나 이제 깨어날 시간이 왔다. 기나긴 잠이었기에 우리\"\n\"는 너무도 굶주려 있다. 이제 곧 먹이를 먹어야 한다...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"즐거운 시간을 보냈나, 하찮은 포유류여? 애처롭구나. 너희들의 작은 세계는 일거\"\n\"리조차 되지 못할 테니 말이야.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"이 대지는 더렵혀질 것이며, 우리 무리는 인간들이 집이라 부르는 들판을 뒤덮을 \"\n\"것이다. 우리의 덩굴손이 이 세계를 장악할 것이며 그곳 생물들의 살점으로 축제\"\n\"를 벌이리다. 인간들은 우리의 식량이 될 터이다.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"아, 난 네놈의 냄새를 맡을 수 있다...가깝구나! 가까워! 스스스스... 피와 공포\"\n\"의 향기가... 매혹적이로다...\"\n\n# 성경식 표현으로 보이므로 실제 용어 확인 필요.\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"그리하여 황금빛 해에는 대성당이 세워지게 될 포고령이 내려졌다. 이 성소의 초석\"\n\"은 반투명한 안티리엘석을 가공해 만든 것으로, 그 초석의 이름은 호라드림과 힘\"\n\"을 나눈 천사에게서 유래되었다.\\n\"\n\"\\n\"\n\"암운 해에는 대지가 흔들리고 대성당이 산산이 무너져내렸다. 지하묘지와 성의 건\"\n\"립이 시작되고 인간들이 죄악의 전쟁의 참화에 맞서는 동안, 폐허는 돌을 찾기 위\"\n\"해 쓸려나갔고, 그렇게 초석은 사람들 눈에서 사라졌다.\\n\"\n\"\\n\"\n\"빛이 만물과 그 너머에도 존재하듯, 그 돌은 이 모든 세상의 것이었다. 빛과 하나\"\n\"됨은 이 거룩한 기초의 산물이자, 목적 통일과 무리 통합의 산물이다.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"음메.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"음메라고 했잖아.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"잘 봐, 난 그냥 소라고, 알겠어?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"그래, 그래. 사실 난 소가 아니야. 평상시엔 이렇게 다니지 않아. 그런데 집에 앉\"\n\"아서 내 자신에 대해 생각 중이었는데, 갑자기 이런 벌레랑 덩굴이랑 뿌리랑 오만 \"\n\"것들이 바닥에서 나오기 시작하더라고... 정말 끔찍했지! 평상시 입는 옷이었으면 \"\n\"괜찮았을 텐데 말이야. 이봐! 내 집에 가서 내 양복 좀 가져다 주지 않겠어? 회색 \"\n\"옷 말고 갈색 옷이야. 회색은 야회복이거든. 내가 해도 되지만 남들한테 이런 모습\"\n\"을 보이고 싶진 않아. 이걸 가져가, 전부 뒤덮은 그것들을 없애려면...필요할 테니\"\n\"까. 내 집은 찾기 쉬워. 강가 갈림길 바로 남쪽에 있거든... 보면 알 거야... 채소\"\n\"밭이 무성한 집이니까.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"왜 시간 낭비를 하고 있는 거야? 가서 내 옷이나 가져와! 서두르라고! 저기 있는 \"\n\"젖소가 나한테 계속 윙크하고 있으니까 말이야!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"이봐, 내 양복 갖고 있어? 빨리 넘기라고! 말도 못 하게 귀가 가렵단 말야!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"아냐 아니라고 아니라니까! 이건 내 회색 옷이잖아! 야회복이라고! 공식 행사에 입\"\n\"는! 이런 건 못 입어. 미친 거 아냐? 갈색 옷이 필요해.\"\n\n# 정확한 상황 확인 필요\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"아, 한결 낫네. 어휴! 이제야 위엄이 좀 서는군! 내 뿔이 똑바로 서 있나? 좋아. \"\n\"도와줘서 정말 고마워. 이걸 받으라고... 약간의 패션 팁이랄까... 조금만 써도 되\"\n\"고... 새로 써도 되고... 뭔 말인지 알겠지? 모든 모험가 주제는 말하자면... 복고\"\n\"풍이야. 조언? 잘가시게나.\"\n\n# under your belt\n# 캐릭터를 보면 말장난일 거 같은데 상황을 모르겠음.\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"잘 봐, 난 소야. 그리고 넌 괴물 미끼고. 경험 좀 쌓지 그래. 얘기 좀 해야겠어...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"제가 당신에게 맡긴 일은 참으로 무시무시한 일이 아닐 수 없죠. 제가 할 수 있을 \"\n\"만한 거라면... 신선하고 깨끗한 우유 한 잔이면 도움이 될런지요?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"오, 도움을 받아도 되지만 저 짐승들이 신성 모독을 범한 지하묘지를 당신이 구한 \"\n\"다음이 좋겠군요.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"뭔가 조치를 취해야 하지만 생판 남에게 떠맡길 순 없는 노릇이죠. 여기서 좀 더 \"\n\"머무르신 다음, 부탁을 드리는 게 나을 것 같습니다.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"당신한테선 엄청난 가능성이 엿보이는군요. 당신의 운명을 따르다 여유가 생기면 \"\n\"저에게 호의를 좀 베풀어 주시겠습니까?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"좀 더 강해지신 다음에 저를 도와주시는 게 좋을 것 같습니다. 교회의 위협을 물리\"\n\"칠 유일한 기회를 망치고 싶진 않거든요!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"난 자수성가한 소야. 너도 뭔가를 이뤄 봐... 그런 다음 얘기하자고.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"지나가는 사람들한테 일일이 날 설명할 필요는 없잖아! 죽일 괴물들이 없나 보지? \"\n\"다음에 얘기할 일이 있겠지. 살다 보면 말이야...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"그만 좀 괴롭혀. 난 진짜 영웅을 찾고 있다고. 그치만 넌 아니야. 넌 못 미덥거\"\n\"든, 언제고 괴물들한테 잡아먹힐 테니까 말이야... 경험 많은 영웅이 필요해.\"\n\n# 소 관련 말장난들. 살리기 어려움.\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"알았어, 헛소린 닥칠게. 널 잘못된 길로 이끌려던 건 아니었어. 집에 앉아 있었는\"\n\"데 상황이 정말 불안정해서 기분이 영 좋지 않았지. 괴물들이 바닥에서 쇄도했거\"\n\"든! 난 그저 겁먹었을 뿐이라, 문밖으로 뛰쳐나가다 보니 우연찮게 젖소 옷을 입\"\n\"고 있었는데, 지금 보니 영 우스꽝스럽네. 평상시 입는 옷이었으면 괜찮았을 텐데 \"\n\"말이야. 이봐! 내 집에 가서 내 양복 좀 가져다 주지 않겠어? 회색 옷 말고 갈색 \"\n\"옷이야. 회색은 야회복이거든. 내가 해도 되지만 남들한테 이런 모습을 보이고 싶\"\n\"진 않아. 이걸 가져가, 전부 뒤덮은 그것들을 없애려면...필요할 테니까. 내 집은 \"\n\"찾기 쉬워. 강가 갈림길 바로 남쪽에 있거든... 보면 알 거야... 채소밭이 무성한 \"\n\"집이니까.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"나는 이 추악한 생명체에게 주문, 협박, 포기, 교섭을 시도했지만 아무 소용이 없\"\n\"었다. 하급 악마를 노예로 삼는 내 방법은 이 끔찍한 짐승에게 아무 효과도 없어 \"\n\"보인다.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"내 집은 이 달갑지 않은 포로의 비열함으로 서서히 오염되고 있다. 지하성당은 내 \"\n\"시야를 벗어나 움직이는 그림자로 가득하다. 어지러이 후벼파는 발톱은 내 귓가를 \"\n\"휘젓는다. 그들은 이 일지를 찾고 있는 것 같다.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"외침 속에서 그 생명체의 이름이 흘러나왔다... 나-크룰. 이름을 알아내려 한 적\"\n\"이 있지만 작은 악마들이 내 서고를 파괴했다. 나-크룰... 그 이름은 나를 공포에 \"\n\"떨게 만든다. 난 그것의 진명을 생각하기보단 한낱 생명체로서만 인지하고 싶을 뿐\"\n\"이다.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"가둬 놓은 생명체의 분노의 울부짖음은 나를 잠들지 못하게 한다. 자신을 그 공간\"\n\"으로 보낸 자에게 분노하고, 자신을 여기에 가둔 나에게 추악한 저주를 퍼붓는다. \"\n\"그 말들은 내 심장을 공포로 얼어붙게 만들지만 여전히 그 소리를 막을 수가 없다.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"내 시간은 빠르게 흘러가고 있다. 악마를 약화시킬 방법을 기록한 다음, 그 하수인\"\n\"들이 내 지식을 이용해 그들의 군주를 자유롭게 하는 방법을 찾지 못하도록 그 기\"\n\"록을 숨겨야 한다. 이 일지를 찾는 사람이 누가 되었든 지식을 탐구하기만을 바란\"\n\"다.\"\n\n# 실제 상황 확인 필요\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"이 두루마리를 찾은 사람은 이 벽 안에 있는 악의 생명체를 막아야 할 책임이 있\"\n\"다. 나는 이제 틀렸다. 지금도 지옥의 하수인들이 내가 숨어 있는 문을 긁어대고 \"\n\"있다.\\n\"\n\"\\n\"\n\"나는 신비한 마법으로 악마를 묶어 두고 거대한 벽 안에 가두었지만 충분치 못할 \"\n\"것 같아 두렵다.\\n\"\n\"\\n\"\n\"세 마법서에서 발견한 주문들은 악의 영역으로 향하는 보호된 출입구를 제공하지\"\n\"만 올바른 순서대로 시전해야 한다. 입구에 있는 지렛대는 방벽을 제거하고 악마\"\n\"를 자유롭게 하니 절대 손대지 마라! 쓰러트리기엔 그자의 힘이 너무도 강력하기\"\n\"에, 진입하려면 이 주문들만 사용해야 한다.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"인 스피리투 상툼.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"프래딕툼 오티움.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"에피치오 오비투스 우트 이니미쿠스.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"지옥돼지\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"찌르는 자\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"착란구체\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"아라크논\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"쌍두\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"구토 산란\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"독꼬리\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"시체병균\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"거미 대장\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"채찍벌레\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"방화개미\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"지옥 벌레\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"무덤 파는 자\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"무덤 쥐\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"화염박쥐\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"해골날개\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"리치\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"지하 악마\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"지옥박쥐\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"뼈 악마\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"아크 리치\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"쌍두 키클롭스\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"살덩이\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"거두는 자\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"거인의 손마디\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"메르쿠리우스의 반지\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"조린의 반지\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"카릭의 반지\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"마그마의 반지\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"신비의 반지\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"천둥의 반지\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"막이의 목걸이\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"각다귀 침\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"횃불\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"어둠의 갑옷\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"집중공세\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"천둥소리\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"백태도\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"영혼 포식자\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"다이아몬드날\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"해골 사슬 갑옷\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"악마 판금 갑옷\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"시종의 목걸이\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"검투사의 반지\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"광대의\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"수정\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"도플갱어의\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"초토화\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"부패\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"위협\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"마나\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"마법사\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"광대\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"번개 방벽\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"불사름\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"초광속 이동\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"반사\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"광폭화\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"화염 고리\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"탐색\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"화염의 룬\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"빛의 룬\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"초신성의 룬\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"불사름의 룬\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"석화의 룬\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"/help\"\n#~ msgstr \"/help\"\n\n#~ msgid \"/arena\"\n#~ msgstr \"/arena\"\n\n#~ msgid \"/arenapot\"\n#~ msgstr \"/arenapot\"\n\n#~ msgid \"/inspect\"\n#~ msgstr \"/inspect\"\n\n#~ msgid \"/seedinfo\"\n#~ msgstr \"/seedinfo\"\n\n#~ msgid \"Command \\\"\"\n#~ msgstr \"명령어 \\\"\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"감마 감소\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"감마 증가\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"마을에서는 지도를 사용할 수 없습니다\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"마을에서 재시작\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"심장\"\n\n# 언제 나오는 말인지 확인 필요\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"물품을 바닥에 떨구려 합니까?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"수직 동기화를 활성화하여 티어링을 방지합니다. 비활성화하면 일부 시스템에서\"\n#~ \"는 마우스 지연이 개선될 수도 있습니다.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"FPS 제한\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"CPU의 과부하를 막기 위해 FPS를 제한합니다. 제한은 리플레시 레이트를 반영합\"\n#~ \"니다.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"명중률\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"영구적, \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"요구치 없음\"\n\n# 뭔 소리임?\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"오늘은 날이 흐리고 선선하군요. 공간을 가로지르는 강령술의 그물을 던져서 날\"\n#~ \"아다니는 공포의 새로운 두 아종을 낚았습니다. 좋은 하루 일과죠. 아드리아한\"\n#~ \"테서 박쥐 배설물과 검은 양초를 더 주문하는 걸 잊으면 안 됩니다. 좀 모자르\"\n#~ \"거든요.\"\n\n#~ msgid \"({command})\"\n#~ msgstr \"({command})\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"선택 사항:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"버전 {:s}\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"생명력 회복\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"치명적 치료\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"힘 감소\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"민첩 감소\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"활력 감소\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"치료할 수 없음\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"적중 시 괴물이 회복하지 않음\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"매우 빠른 휘두르기 공격\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"초월 시야\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"기록용 플레이어 아카이브를 열지 못했습니다.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"저장 파일을 읽을 수 없습니다\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"저장 파일을 기록할 수 없습니다\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"영웅의 전당 너머에는 뼈의 방이 있다.  그 방의 보물을 훔치려 하는 자에게는 \"\n#~ \"영원한 죽음이 기다릴지니,  이는 공포의 군주께서 하신 말씀이자 이곳에 기록\"\n#~ \"되어 있는 바이다.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"지옥의 무기고는 피의 전쟁군주의 거처이다.  그의 각성으로 기천의 시체가 줄\"\n#~ \"을 잇는다.  천사와 인간도 피만을 갈구하는 어둠의 존재의 제물로서 잇달아 찢\"\n#~ \"기어 갔다.\"\n\n#~ msgid \"Right click to read\"\n#~ msgstr \"우클릭으로 읽기\"\n"
  },
  {
    "path": "Translations/pl.po",
    "content": "# Translation of DevilutionX to Polish\n# @wiafilms, 2021.\n# @qndel, 2021.\n# @zutmkr, 2021.\n# @BuildTools, 2021.\n# @nelchael, 2023\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: pl_PL\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 \"\n\"|| n%100>14) ? 1 : 2);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Projekt Gry\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Starsi Projektanci\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Dodatkowe Projektowanie\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Główny Programista\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Starsi Programiści\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programowanie\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Programiści - Goście Specjalni\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Programowanie Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Progamowanie Komunikacji Szeregowej\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Programowanie Instalatora\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Dyrektorzy Artystyczni\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Rysunki\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Rysunki Techniczne\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Dyrekorzy Artystyczni Filmów\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"Projekt Filmów 3D\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Projekt Techniczny Filmów\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Producent Wykonawczy\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Młodszy Producent\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Muzyka\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Dźwięk\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Muzyka i Dźwięk Filmów\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Kasting, Produkcja oraz Reżyseria Głosu\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Scenariusz i Fabuła\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Obróbka Głosu\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Głosy\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Inżynier Nagrań\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Projekt Instrukcji\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Rysunki do Instrukcji\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Tymczasowy Dyrektor ds. Jakości (Główny Tester)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Ekipa Szturmowa ds. Jakości (Testerzy)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Drużyna Specjalna ds. Jakości (Testerzy Kompatybilności)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Wsparcie Artlyleryjne ds. Jakości (Dodatkowi Testerzy) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Kontrwywiad ds. Jakości\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Zakon Sieciowych Serwisów Informacyjnych\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Wsparcie\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Sprzedaż\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Chórki Pana Dabiriego\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"PR\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Sprzedaż Międzynarodowa\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Sprzedaż w Stanach Zjednoczonych\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Produkcja\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Działalność Prawna i Biznesowa\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Specjalne Podziękowania dla\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Podziękowania dla\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Ku pamięci\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Bardzo Specjalne Podziękowania dla\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Główny Menadżer\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Inżynieria Oprogramowania\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Dyrektor Artystyczny\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Artyści\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Projekt\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Inżynieria Dźwięku i Efekty Dźwiękowe\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Kierownik ds. Jakości\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testerzy\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Instrukcja\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tDodatkowa Praca\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Teksty Zadań\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Podziękowania dla\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tSpecjalne Podziękowania dla Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Menadżer ds. Jakości\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Główny Tester Jakości\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Testerzy\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Dodatkowi Testerzy\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Menadżer Marketingu\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Menadżer PR\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Młodszy Menadżer Produktu\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Krąg Tysiąca\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tŻadne dusze nie zostały zaprzedane podczas tworzenia tej gry.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Wybierz Klasę\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Anuluj\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Nowa Postać - Gra Sieciowa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Nowa Postać - Gra Jednoosobowa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Znaleziono Plik Zapisu\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Wczytaj Grę\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Nowa Gra\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Postacie - Gra Jednoosobowa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Łotrzyca i Czarodziej są dostępni tylko w pełnej wersji gry Diablo. Odwiedź \"\n\"https://www.gog.com/game/diablo by ją zakupić.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Wpisz Imię\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Niepoprawne imię. Nazwa nie może zawierać spacji, znaków specjalnych i \"\n\"niektórych słów.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Nie udało się stworzyć postaci.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Poziom:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Siła:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magia:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Zręczność:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Witalność:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Zapis Gry:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Wybierz Postać\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Nowa Postać\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Usuń\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Postacie - Gra Sieciowa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Usuń Postać - Gra Sieciowa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Usuń Postać - Gra Jednoosobowa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Czy na pewno chcesz usunąć postać \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Jeden Gracz\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Wielu Graczy\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Ustawienia\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Wsparcie\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Twórcy\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Wyjdź z Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Wyjdź z Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Demo\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Klient-Serwer (TCP)\"\n\n# NOTES(nelchael): Pojawia się w menu \"wybierz połączenie\", stąd \"lokalne\" połączenie.\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Lokalne\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Gra Wieloosobowa\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Wymagania:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"bez bramki\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Wybierz Połączenie\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Zmień Bramkę\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Wszystkie komputery muszą być połączone z siecią kompatybilną z TCP.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Wszystkie komputery muszą być połączone z internetem.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Graj samemu bez łączenia się z internetem.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Liczba graczy: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Demo Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Demo Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Host używa innej gry niż ty.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Host używa innej gry ({:s}) niż ty.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Twoja wersja {:s} nie pasuje do wersji hosta {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Opis:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Czynność\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Stwórz grę\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Stwórz publiczną grę\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Dołącz do gry\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Publiczne Gry\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Wczytywanie...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Brak\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ANULUJ\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Stwórz nową grę z wybranym poziomem trudności.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Stwórz nową publiczną grę z wybranym poziomem trudności do której każdy może \"\n\"dołączyć.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Wprowadź ID gry, aby dołączyć do trwającej już gry.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Wprowadź adres IP lub nazwę hosta, aby dołączyć do trwającej już gry.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Dołącz do trwającej już gry publicznej.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normalny\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Koszmar\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Piekło\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Poziom Trudności: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Tempo: Normalne\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Tempo: Szybkie\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Tempo: Szybsze\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Tempo: Najszybsze\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Gracze: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Poziom Trudności\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Dołącz do gry przez {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Wpisz ID gry\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Wpisz adres\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normalny\\n\"\n\"Poziom dla postaci, która pierwszy raz chce się zmierzyć z Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Koszmar\\n\"\n\"Potwory zamieszkujące Labirynt stają się mocniejsze i stanowią większe \"\n\"wyzwanie. Poziom trudności zalecany dla doświadczonej postaci.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Piekło\\n\"\n\"Najpotężniejsze kreautry podziemi strzegą piekielnych bram. Tylko \"\n\"najbardziej doświadczone postacie mogą zapuścić się w głąb tego świata.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Twoja postać musi osiągnąć co najmniej 20 poziom żeby grać na poziomie \"\n\"trudności Koszmar w trybie sieciowym.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Twoja postać musi osiągnąć co najmniej 30 poziom żeby grać na poziomie \"\n\"trudności Piekło w trybie sieciowym.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Wybierz Tempo Gry\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Szybkie\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Szybsze\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Najszybsze\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normalne Tempo Gry\\n\"\n\"Dla postaci, która pierwszy raz chce się zmierzyć z Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Szybka Gra\\n\"\n\"Potwory zamieszkujące Labirynt stają się szybsze. Są większym wyzwaniem. \"\n\"Prędkość zalecana dla doświadczonej postaci.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Szybsza Gra\\n\"\n\"Większość potworów będzie usiłować dorwać cię szybciej niż zwykle. Tylko \"\n\"doświadczony czempion powinien spróbować swych sił na tej prędkości.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Najszybsza Gra\\n\"\n\"Sługi piekielne będą nieustannie się za tobą uganiać. Tylko dla prawdziwych \"\n\"demonów prędkości.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Wpisz Hasło\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Wejdź do Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Przełącz na Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Tak\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Nie\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Naciśnij przycisk na kontrolerze aby zmienić.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Powiązany klawisz:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Naciśnij dowolny klawisz by zmienić.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Usuń wiązanie klawisza\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Powiązana kombinacja przycisków:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Usuń powiązanie kombinacji przycisków\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Powrót\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Utrzymujemy serwer czatu pod adresem Discord.gg/devilutionx Podążaj za \"\n\"linkami, aby dołączyć do naszej społeczności, gdzie rozmawiamy o rzeczach \"\n\"związanych z Diablo i dodatkiem Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX jest zarządzane przez Diasurgical, wszelkie problemy należy \"\n\"przesyłać na adres https://github.com/diasurgical/devilutionX Abyśmy mogli \"\n\"Ci lepiej pomóc, pamiętaj o podaniu numeru wersji, systemu operacyjnego i \"\n\"typu problemu.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Uwaga:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX nie jest wspierane ani przez Blizzard Entertainment, ani przez \"\n\"GOG.com. Blizzard Entertainment i GOG.com nie testowali i nie sprawdzali \"\n\"jakości bądź kompatybilności DevilutionX. Wszelkie pytania dotyczące \"\n\"DevilutionX powinny być kierowane tylko do Diasurgical, nie do Blizzard \"\n\"Entertainment lub GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tPort korzysta z czcionek Charis SIL, New Athena Unicode, Unifont i Noto, \"\n\"które są dostępne na licencji SIL Open Font License, a także z Twitmoji, \"\n\"które jest dostępne na licencji CC-BY 4.0. Port korzysta również z języka \"\n\"SDL, który jest objęty licencją zlib-license. Więcej szczegółów można \"\n\"znaleźć w ReadMe.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Błąd\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Nastąpił błąd w: {:s} linia {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Błąd Pliku z Danymi\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Otwarcie pliku {:s} nie powiodło się.\\n\"\n\"\\n\"\n\"Upewnij się, że plik znajduje się w folderze.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Błąd Folderu Tylko do Odczytu\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Nie da się zapisać do:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Gra: \"\n\n# NOTES(nelchael): Wyświetlane zamiast nazwy gry gdy widoczna jest mapa.\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Gra lokalna\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Hasło: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Publiczna Gra\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Gniazdo - Poziom {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Krypta - Poziom {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Miasteczko\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Poziom: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Informacje o postaci\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Dziennik Zadań\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Automapa\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Menu Główne\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Ekwipunek\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Księga zaklęć\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Wyślij Wiadomość\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Dostępne Polecenia:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Polecenie \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" jest nieznane.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Opis: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parametry: Brak wymaganych dodatkowych parametrów.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parametry: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Areny są obsługiwane tylko w grach wieloosobowych.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Którą arenę chcesz odwiedzić?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Błędny numer areny. Poprawne numery to:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"Aby wejść na arenę musisz być w mieście lub na innej arenie.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Inspekcja graczy jest obsługiwana tylko w grach wieloosobowych.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Zakończono inspekcję graczy.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Nie znaleziono graczy z tą nazwą\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Inspekcja gracza: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Wypisuje przegląd pomocy lub pomoc dla konkretnego polecenia.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[polecenie]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Wejdź na Arenę PvP.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<numer-areny>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Daje Mikstury Areny.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<liczba>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Przeprowadza inspekcję statystyk i ekwipunku innego gracza.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<nazwa gracza>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Pokaż informację o ziarnie dla aktualnego poziomu.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Neutralność\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Wrogość\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Klawisz: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Wybierz zaklęcie\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Klawisz: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"Umiejętność: {:s}\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"Czar: {:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Poziom Czaru: 0 - Bezużyteczny\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Poziom Czaru: {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Zwój: {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"Zwój: {:d}\"\nmsgstr[1] \"Zwoje: {:d}\"\nmsgstr[2] \"Zwoje: {:d}\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Kostur: {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"Ładunek: {:d}\"\nmsgstr[1] \"Ładunki: {:d}\"\nmsgstr[2] \"Ładunki: {:d}\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} złota\"\nmsgstr[1] \"{:s} złota\"\nmsgstr[2] \"{:s} złota\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Nie spełniono wymagań\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Poziom: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Punkty Życia {:d} / {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"PPM by użyć\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Nowy Poziom\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Masz {:s} złota. Ile monet chcesz oddzielić?\"\nmsgstr[1] \"Masz {:s} złota. Ile monet chcesz oddzielić?\"\nmsgstr[2] \"Masz {:s} złota. Ile monet chcesz oddzielić?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Miejski Portal\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"od: {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal do\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Przeklęty Ołtarz\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"poziom 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Nie można wczytać danych z pliku {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} jest niekompletny, proszę sprawdzić zawartość pliku.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"Twój plik {0} nie ma oczekiwanych kolumn, proszę upewnić się, że pasuje do \"\n\"udokumentowanego formatu.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Nienumeryczna wartość {0} dla {1} w pliku {2}, rząd {3} kolumna {4}\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Wartość spoza zakresu {0} dla {1} w pliku {2}, rząd {3} kolumna {4}\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Nieprawidłowa wartość {0} dla {1} w pliku {2}, rząd {3} kolumna {4}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Wyświetl tę wiadomość i wyjdź\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Wyświetl numer wersji i wyjdź\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Określ folder dla diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Określ folder dla plików zapisu\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Określ lokalizację diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Podaj kod języka (na przykład en lub pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Pomiń loga i wprowadzenie\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Wyświetl ilość klatek na sekundę\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Włącz szczegółowy log\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Nagraj demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Odtwórz plik z nagranym demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Wyłącz limit klatek podczas odtwarzania demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Wybór gry:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Wymuś tryb demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Wymuś tryb Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Wymuś tryb Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Opcje Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Zgłoś błędy na https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"Proszę zaktualizować devilutionx.mpq i fonts.mpq do najnowszych wersji\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Błąd podczas wczytywania danych.\\n\"\n\"\\n\"\n\"Upewnij się, że najnowsza wersja pliku devilutionx.mpq znajduje się w \"\n\"folderze z grą.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Proszę zaktualizować fonts.mpq do najnowszej wersji\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Przekroczono limit czasu oczekiwania --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Oczekiwanie na graczy --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Pomoc niedostępna\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"podczas przebywania w sklepie\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Przedmiot pasa {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Użycie przedmiotu z pasa.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Szybki czar {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Ustawianie skrótu klawiszowego umiejętności.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Poprzedni szybki czar\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Wybiera poprzedni szybki czar (w kolejności).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Następny szybki czar\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Wybiera następny szybki czar (w kolejności).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Użyj mikstury leczenia\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Użyj mikstury leczenia z pasa.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Użyj mikstury many\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Użyj mikstury many z pasa.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Podręczna Księga\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Wyświetla Podręczną Księgę.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Szybki zapis\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Zapisuje grę.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Szybki odczyt\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Wczytuje grę.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Wyjdź z gry\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Zamyka grę.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Zatrzymaj bohatera\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Zatrzymuje chodzenie i anuluje oczekujące działania.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Podświetlenie przedmiotów\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Pokaż/ukryj przedmioty na ziemi.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Przełączanie podświetlania przedmiotów\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Stałe pokazywanie/ukrywanie przedmiotów na ziemi.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Przełączanie automapy\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Przełącza, czy wyświetlana jest automapa.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Przełącz typ mapy\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Nieprzezroczysta -> Przezroczysta -> Mini mapa -> Brak\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Wyświetla ekran Ekwipunku.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Postać\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Wyświetla panel postaci.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Dziennik Zadań\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Wyświetla Dziennik Zadań.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Księga zaklęć\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Wyświetla księgę zaklęć.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Szybka wiadomość {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Użyj funkcji Szybka Wiadomość na czacie.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Ukryj ekrany informacyjne\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Ukryj wszystkie ekrany informacyjne.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Powiększenie\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Przybliżenie ekranu.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Wstrzymaj grę\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Wstrzymuje grę.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Wstrzymaj grę (alternatywnie)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Zwiększa jasność ekranu.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Zmniejsza jasność ekranu.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Zwiększa jasność ekranu.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Zwiększa jasność ekranu.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Pomoc\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Wyświetl Okno Pomocy.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Zrzut ekranu\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Wykonuje zrzut ekranu.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Informacje o grze\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Wyświetla informacje o grze.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Dziennik czatu\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Wyświetla dziennik czatu.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Sortuj ekwipunek\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Sortuje ekwipunek.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Konsola\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Otwiera konsolę Lua.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Główna akcja\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Atakuj potwory, rozmawiaj z mieszkańcami, podnoś i umieszczaj przedmioty w \"\n\"ekwipunku.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Drugorzędna akcja\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Otwieraj skrzynie, używaj drzwi, podnoś przedmioty.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Akcja czaru\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Rzuć aktywny czar.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Akcja anulowania\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Zamknij menu.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Ruch do góry\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Porusza postacią gracza do góry.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Ruch w dół\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Porusza postacią gracza w dół.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Ruch w lewo\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Porusza postacią gracza w lewo.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Ruch w prawo\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Porusza postacią gracza w prawo.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Utrzymaj pozycję\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Przytrzymaj by powstrzymać postać przed poruszaniem się.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Przełącznik utrzymania pozycji\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Przełącza między staniem w miejscu a swobodnym ruchem gracza.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Automapa\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Ruch w dół\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Ruch w lewo\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Porusza postacią gracza do góry.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Ruch w prawo\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Ruch myszy w górę\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Symuluje ruch myszą w górę.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Ruch myszy w dół\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Symuluje ruch myszą w dół.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Ruch myszy w lewo\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Symuluje ruch myszą w lewo.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Ruch myszy w prawo\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Symuluje ruch myszą w prawo.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Kliknięcie lewym przyciskiem myszy\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Symuluje kliknięcie lewym przyciskiem myszy.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Kliknięcie prawym przyciskiem myszy\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Symuluje kliknięcie prawym przyciskiem myszy.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Menu szybkiego wyboru zaklęć na kontrolerze\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Przytrzymaj by przypisać bądź użyć skrót klawiszowy zaklęcia.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Nawigacja menu na kontrolerze\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Przytrzymaj by otworzyć nawigację menu na kontrolerze.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Przełącza menu gry\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Otwiera menu gry.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Gra zapisana\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Brak funkcji gry sieciowej w demo\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Błąd Utworzenia Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Niedostępne w wersji shareware\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Brak miejsca do zapisu\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Brak pauzy w mieście\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Zalecane skopiowanie na dysk twardy\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Błąd synchronizacji gry sieciowej\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Brak pauzy w rozgrywce sieciowej\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Zapisywanie...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Przypływ sił również ma swą cenę\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Przekucie w moc wymaga zniszczenia\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Atak nie zawsze jest najlepszą obroną\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Miecz sprawiedliwości jest szybki i ostry\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Harmonia ducha przynosi ukojenie dla ciała\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Utracona energia powraca\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Czas nie naruszy najlepszej stali\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Magia nie zawsze jest tym, na co wygląda\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Co raz było otwarte, znów jest zamknięte\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Żywiołowość zyskana kosztem mądrości\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Tajemna moc przynosi zniszczenie\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"To, czego nie można trzymać, nie może być uszkodzone\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Szkarłat i lazur błyszczą niczym słońce\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Wiedza i mądrość poprzez zatracenie\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Napij się i poczuj odnowienie\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Pójdź w nieznane\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Energia zyskana kosztem mądrości\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Bogactwo przybywa nieoczekiwanie\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Gdzie chciwość zawodzi, tam cierpliwość popłaca\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Błogosławieństwo od towarzysza!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Los jest w twoich rękach\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Głęboka wiara zwiększa siłę\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Istota życia leży we wnętrzu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Droga widziana z góry jest przejrzystsza\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Zbawienie kosztem mądrości\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Mądrość znajdziecie jedynie wśród uczonych\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Ostatni mogą być jeszcze pierwszymi\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Hojność zostaje nagrodzona\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Dostępne od poziomu 8.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Dostępne od poziomu 13.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Dostępne od poziomu 17.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Zdobyto tajemną wiedzę!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Co cię nie zabije…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Wiedza to potęga.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Coś za coś.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Niektórych rzeczy trzeba doświadczyć.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Wszędzie dobrze, ale w domu najlepiej.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Energia duchowa została przywrócona.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Czujesz przypływ zwinności.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Czujesz przypływ sił.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Czujesz przypływ mądrości.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Czujesz pobudzenie.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Co może się zepsuć, na pewno się zepsuje.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedra\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Katakumby\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Jaskinie\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Gniazdo\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Krypta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Poz. {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} Poziom Trudności\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"W Menu\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Nie udało się połączyć\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"błąd: wczytano 0 bajtów z serwera\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\"Nie udało się otworzyć pliku:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"Plik MPQ może być uszkodzony. Proszę sprawdzić spójność pliku.\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq lub spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Brakuje części plików MPQ do Hellfire\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Nie znaleziono wszystkich plików MPQ do Hellfire.\\n\"\n\"Skopiuj wszystkie pliki hf*.mpq do folderu.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Rozdzielczość\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Bieg w mieście\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Zadanie Theo\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Zadanie Krowie\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Auto podnoszenie złota\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Auto podnoszenie eliksirów\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Auto podnoszenie olejów\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Auto podnoszenie w mieście\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria Uzupełnia Manę\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Automatycznie Załóż Broń\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Automatycznie Załóż Pancerz\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Automatycznie Załóż Hełmy\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Automatycznie Załóż Tarcze\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Automatycznie Załóż Biżuterię\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Losuj Zadania\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Pokaż etykiety przedmiotów\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Automatycznie uzupełnij pas\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Wyłącz kaleczące kapliczki\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Podnoszenie mikstur Leczenia\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Podnoszenie mikstur Pełn. Leczenia\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Podnoszenie mikstur Many\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Podnoszenie mikstur Pełnej Many\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Podnoszenie mikstur Wzmocnienia\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Podnoszenie mikstur Pełn. Wzmocnienia\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Opcje\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Zapisz Grę\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Menu Główne\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Wyjdź z Gry\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Jasność\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Tempo\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Muzyka Wyłączona\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Dźwięk\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Dźwięk Wyłączony\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pauza\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Skróty Klawiszowe:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Wyświetl okno pomocy\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Wyświetl menu główne\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Wyświetl mapę\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Ukryj wszystkie okna\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Wyświetla podręczną księgę\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Wyświetla księgę zaklęć\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Wyświetla ekwipunek\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Wyświetla panel postaci\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Wyświetla dziennik zadań\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Zmniejsza jasność ekranu\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Zwiększa jasność ekranu\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Przybliżenie ekranu\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Skalowanie mapy\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Sięgnięcie po przedmiot z pasa\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Ustawianie skrótu klawiszowego umiejętności\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Lewy Przycisk Myszy: Atak w miejscu\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Lewy Przycisk Myszy (na panelu postaci): Przydziel wszystkie punkty\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Lewy Przycisk Myszy (w ekwipunku): Przenieś na pas lub przygotuj/\"\n\"schowaj przedmiot\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\"Shift + Lewy Przycisk Myszy (na pasie): Przenieś przedmiot do ekwipunku\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Poruszanie się:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Wciśnięty Lewy Przycisk Myszy wskazuje kierunek, w który ma podążać postać.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Walka:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Wciśnięcie Shift powoduje, że po kliknięciu postać atakuje bez poruszania \"\n\"się.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Mapa:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Aby wyświetlić mapę, użyj przycisku 'MAPA' w panelu postaci albo naciśnij \"\n\"przycisk 'TAB' na klawiaturze. Przyciski + oraz - umożliwiają jej \"\n\"powiększanie i oddalanie. Klawiszami strzałek można ją również przemieszczać.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Podnoszenie Obiektów:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Małe rzeczy, takie jak mikstury i zwoje, automatycznie umieszczane są w \"\n\"pasie widocznym na panelu postaci w dolnej części ekranu. Można ich użyć \"\n\"wciskając na klawiaturze numer, który się przy nich pojawia lub klikając na \"\n\"nie Prawym Przyciskiem Myszy.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Złoto:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Kliknięcie prawym przyciskiem myszy na złocie w ekwipunku umożliwia jego \"\n\"rozdzielenie.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Umiejętności i Czary:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Możesz zobaczyć listę dostępnych czarów i umiejętności klikając w przycisk \"\n\"'Czary' na panelu postaci. Po kliknięciu lewym przyciskiem myszy na danym \"\n\"zaklęciu, staje się ono aktywne i gotowe do użycia. Kliknięcie prawym \"\n\"przyciskiem myszy na danym terenie, umożliwia rzucenie go.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Użycie podręcznej księgi czarów:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Kliknięcie lewym przyciskiem myszy na 'przygotowany czar' otworzy 'podręczną \"\n\"księgę' pozwalającą wybrać umiejętność. By ją użyć kliknij prawym \"\n\"przyciskiem myszy w głównym oknie rozgrywki.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + kliknięcie lewym przyciskiem myszy na przycisku \\\"wybierz bieżące \"\n\"zaklęcie\\\" spowoduje usunięcie przygotowanego zaklęcia.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Ustawianie skrótów klawiszowych umiejętności:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Istnieje możliwość przypisania klawiszy do umiejętności. Po wyświetleniu ich \"\n\"klawiszem S najedź myszką na wybrany czar. Następnie naciśnij klawisz F5, \"\n\"F6, F7 albo F8, aby przypisać go do wybranej umiejętności.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Księgi czarów:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Czytanie wielu ksiąg zwiększa twą wiedzę o czarze, dzięki czemu może być ono \"\n\"jeszcze skuteczniejsze.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Pomoc Wersji Shareware Hellfire\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Pomoc Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Pomoc Wersji Shareware Diablo\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Pomoc Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Naciśnij ESC aby wyjść lub strzałki aby przewijać.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Nie udało się utworzyć głównego okna\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Brak miejsca na przedmiot\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Olej Precyzji\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Olej Opanowania\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Olej Wyostrzenia\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Olej Śmierci\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Olej Umiejętności\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Olej Rzemieślnika\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Olej Wytrzymałości\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Olej Niezniszczalności\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Olej Wzmocnienia\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Olej Nieprzenikalności\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"znacznie zwiększa\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"celność broni\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"znacznie zwiększa\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"celność broni\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"możliwe obrażenia\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"znacznie zwiększa\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"możliwe obrażenia (bez łuków)\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"zmniejsza wymagane atrybuty\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"i pozwala używać przedmioty\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"przywraca 20%\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"wytrzymałości przedmiotu\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"zwiększa\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"bieżącą i maks. wytrzymałość\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"czyni rzecz niezniszczalną\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"zwiększa klasę pancerza\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"tarcz i zbroi\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"znacznie zwiększa pancerz\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"klasę tarcz i zbroi\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"ustawia ognistą pułapkę\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"ustawia pułapkę z błyskawic\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"ustawia pułapkę Petryfikacji\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"odnawia całe życie\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"odnawia część życia\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"odnawia część many\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"odnawia całą manę\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"zwiększa siłę\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"zwiększa magię\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"zwiększa zręczność\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"zwiększa witalność\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"odnawia część życia i many\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"odnawia całe życie i manę\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(działa tylko na arenach)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"PPM by wyświetlić\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"PPM by użyć\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"PPM by odczytać, następnie\\n\"\n\"LPM na cel\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"PPM by odczytać\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Aktywuj, aby wyświetlić\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Otwórz ekwipunek, aby użyć\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Aktywuj, aby użyć\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Wybierz z księgi zaklęć, a następnie\\n\"\n\"rzuć zaklęcie, aby przeczytać\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Aktywuj, aby przeczytać\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} aby wyświetlić\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} aby użyć\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Wybierz z księgi zaklęć,\\n\"\n\"a następnie {} aby przeczytać\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} aby przeczytać\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Poziom: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Podwaja objętość sakwy\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Wymagania:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Siły\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Magii\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Zręcz.\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Księga czaru: {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Ucho ({:s})\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"celność: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% do obrażeń\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"celność: {:+d}%, obrażenia: {:+d}%\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% do obrony\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"klasa pancerza: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Odporność na Ogień {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Odporność na Ogień {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Odp. na Błyskawice {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Odp. na Błyskawice {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Odporność na Magię {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Odporność na Magię {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Odporność na wszystko: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Odporność na wszystko {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"poziom czarów zwiększony o {:d}\"\nmsgstr[1] \"poziom czarów zwiększony o {:d}\"\nmsgstr[2] \"poziom czarów zwiększony o {:d}\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"poziom czarów zmniejszony o {:d}\"\nmsgstr[1] \"poziom czarów zmniejszony o {:d}\"\nmsgstr[2] \"poziom czarów zmniejszony o {:d}\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"poziom czarów bez zmian (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Dodatkowe ładunki\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"Ładunki: {:d} {:s}\"\nmsgstr[1] \"Ładunki: {:d} {:s}\"\nmsgstr[2] \"Ładunki: {:d} {:s}\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Obr. od ognia: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Obr. od ognia: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Obr. od błyskawic: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Obr. od błyskawic: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} do siły\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} do magii\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} do zręczności\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} do żywotności\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} do wszystkich atrybutów\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} obrażeń od wrogów\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Punkty życia: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"wysoka wytrzymałość\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"zmniejszona wytrzymałość\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"niezniszczalność\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% do promienia światła\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% do promienia światła\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"wielostrzał\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"obr. płonących strzał {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"obr. płonących strzał: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"obr. strzał błyskawic {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"obr. strzał błyskawic {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"obr. ognistej kuli {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"obr. ognistej kuli {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"atakujący otrzymuje 1-3 obrażeń\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"gracz traci całą manę\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"2x mniej obrażeń od pułapek\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"odrzuca przeciwnika\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% obrażeń wobec demonów\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Odporności spadają do 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"uderzenie kradnie 3% many\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"uderzenie kradnie 5% many\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"uderzenie kradnie 3% życia\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"uderzenie kradnie 5% życia\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"przebija pancerz wroga\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"szybki atak\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"szybki atak\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"szybszy atak\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"najszybszy atak\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Inna zdolność\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"szybko wznawia atak\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"szybsze wznowienie ataku\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"najszybsze wznowienie ataku\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"szybki blok\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"+{:d} pkt. obrażeń\"\nmsgstr[1] \"+{:d} pkt. obrażeń\"\nmsgstr[2] \"+{:d} pkt. obrażeń\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"losowe szybkie strzały\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"nietypowe obrażenia\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"zmieniona wytrzymałość\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"miecz jednoręczny\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"stale tracisz punkty życia\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"kradzież życia\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"brak wymogu siły\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"obrażenia błyskawic: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"obrażenia błyskawic: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"rzuca Wiązkę Błyskawic\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"okazyjnie potraja obrażenia\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"rozkład {:+d}% obrażeń\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x obr. dla potw, 1x dla cb\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Losowo 0 - 600% obrażeń\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"mała wyt, {:+d}% obrażeń\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"ekstra pancerz przeciwko demonom\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"ekstra pancerz przeciwko nieumarłym\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Many przechodzi do Życia\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Życia przechodzi do Many\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"obr: {:d}  Niezniszczalność\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"obr: {:d}  Wyt: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"obr: {:d}-{:d}  Niezniszczalność\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"obr: {:d}-{:d}  Wyt: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"pancerz: {:d}  Niezniszczalność\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"pancerz: {:d}  Wyt: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Ładunki: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"unikat\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Nie zidentyfikowano\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Siedziba Króla Szkieletów\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Komnata Kości\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labirynt\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Zatrute Źródło Wody\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Siedziba Arcybiskupa Lazarusa\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Arena Kościoła\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Arena Piekła\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Arena Kręgu Życia\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Zejdź do lochu\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Zejdź do katakumb\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Zejdź do jaskiń\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Zejdź do piekła\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Zejdź do Gniazda\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Zejdź do Krypty\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Wejdź na poziom {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Wejdź do miasta\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Zejdź na poziom {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Staw czoła Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Do Gniazda - poziom {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Do Krypty - poziom {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Fundament Świata\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Do Krypty - poziom {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Wróć na poziom {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Nie można otworzyć pliku zapisu\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Nieprawidłowy plik zapisu\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Gracz przebywa na poziomie z dodatku Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Nieprawidłowy stan gry\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Nie można wyświetlić głównego menu\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Zwierzę\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demon\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Nieumarły\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Rodzaj: {:s}  Zabitych: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Suma zabitych: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Punkty życia: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Brak odporności na magię\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Odporności:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magię\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Ogień\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Błyskawice\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Niewrażliwość na:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Rodzaj: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Brak odporności\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Brak niewrażliwości\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Lekka odporność na magię\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Częściowa niewraż. na magię\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Błąd otwarcia archiwum do zapisu.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} rzucił niewłaściwe zaklęcie.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} rzucił nielegalne zaklęcie.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Gracz '{:s}' (poziom {:d}) dołączył do gry\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Gra została zakończona\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Nie można wczytać danych poziomu\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Gracz '{:s}' opuścił grę\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Gracz '{:s}' pokonał Diablo i opuścił grę!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Gracz '{:s}' opuścił grę z powodu limitu czasu\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Gracz '{:s}' (poziom {:d}) jest już w grze\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Tajemnicza\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Ukryta\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Ponura\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Dziwny\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Magiczna\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Kamienna\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Zakonna\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Zaczarowana\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Taumaturgiczna\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Czarująca\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Zagadkowa\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Koszmarna\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Niesamowita\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Boska\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Święta\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Uświęcona\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Duchowa\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Upiorna\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Porzucona\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Straszna\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Cicha\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Odosobniona\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Ozdobna\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Migocząca\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Splugawiona\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Wzmacniająca\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Świecąca\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Matczyna\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Błyszcząca\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Lśniąca\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Promienista\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Czarnowidząca\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Wielki Konflikt\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Wojna Karą za Grzechy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Historia Horadrimów\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Mroczne Wygnanie\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Wojna Grzechu\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Schwytanie Trójcy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Nieznane Krainy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Historia Trójcy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Czarny Król\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Dziennik: Wpływ Magii\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Dziennik: Konfrontacja\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Dziennik: Tyrada\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Dziennik: Jego Siła Wzrasta\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Dziennik: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Dziennik: Zakończenie\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Księga Zaklęć\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Ukrzyżowany Szkielet\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Dźwignia\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Otwarte Drzwi\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Zamknięte Drzwi\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Zablokowane Drzwi\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Starożytna Księga\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Księga Obłudy\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Kościana dźwignia\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Mityczna Księga\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Mała Skrzynia\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Skrzynia\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Duża Skrzynia\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarkofag\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Regał\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Biblioteczka\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Beczka\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Kokon\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Kapliczka\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Kościana Księga\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Księga Biblioteczna\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Fontanna Krwi\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Okaleczone Ciało\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Księga Ślepców\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Księga Krwi\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Źródło Oczyszczenia\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Zbroja\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Stojak na Broń\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Koźla Kapliczka\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Kocioł\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Mętna Sadzawka\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Fontanna Łez\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Żelazna Księga\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Piedestał Krwi\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Skupisko grzybów\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Stojak Nikczemnego\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Zabity Bohater\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} (pułapka)\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (wył.)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"TAK\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"NIE\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Tryb gry\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Ustawienia Rozgrywki\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Zagraj w Diablo lub Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Ogranicz do wersji Demo\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Sprawia, że gra jest kompatybilna z wersją demonstracyjną. Umożliwia grę \"\n\"wieloosobową z przyjaciółmi, którzy nie posiadają pełnej kopii Diablo.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Uruchomienie\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Ustawienia uruchamiania\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Intro\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Pokaż intro.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Powitanie\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Pokaż ekran powitalny.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo i ekran tytułowy\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Ekran Tytułowy\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Ustawienia specyficzne dla Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Opcje Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Audio\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Ustawienia Audio\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Dźwięk chodzenia\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Gracz wydaje dźwięki podczas chodzenia.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Auto Wyposażenie Dźwięk\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\"Automatyczne zakładanie przedmiotów przy podniesieniu powoduje emisję \"\n\"dźwięku.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Dźwięk podnoszenia przedmiotu\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"\"\n\"Podnoszenie przedmiotów powoduje emisję dźwięku podnoszenia przedmiotów.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Częstotliwość próbkowania\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Częstotliwość próbkowania wyjścia (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanały\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Liczba kanałów wyjścia.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Rozmiar Bufora\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Rozmiar bufora (liczba ramek na kanał).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Jakość powtórnego próbkowania\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Jakość próbnika, od 0 (najniższa) do 10 (najwyższa).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Wpływa na wew. rozdzielczość gry i określa obszar widzenia użytkownika. \"\n\"Uwaga: Rozdzielczość ta może się różnić od roz. ekranu, dla funkcji - \"\n\"Zwiększanie, Skalowanie Całkowite, Dopasuj do Ekranu.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Próbnik\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Próbnik audio\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Urządzenie\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Urządzenie audio\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafika\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Ustawienia Graficzne\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Pełny Ekran\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Wyświetlanie gry w trybie okienkowym lub pełnoekranowym.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Dopasuj do ekranu\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Automatycznie dostosuj okno gry do bieżących proporcji i rozdzielczości \"\n\"ekranu pulpitu.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Zwiększanie Rozdzielczości\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Umożliwia skalowanie obrazu z rozdzielczości gry do rozdzielczości monitora. \"\n\"Zapobiega zmianie rozdzielczości monitora i umożliwia zmianę rozmiaru okna.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Rodzaj skalowania\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Włącza opcjonalne filtry dla obrazu wyjściowego podczas skalowania w górę.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Najbliższy piksel\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilinearne\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anizotropowe\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Skalowanie Całkowite\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Skaluje obraz przy użyciu współczynnika liczby całkowitej pikseli.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Synchronizacja pionowa\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Włącza zbliżenie na okno rozgrywki.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Błyskawice\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Przełączanie kolorów\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Efekt cyklicznych zmian kolorów stosowany w animacjach wody, lawy i kwasu.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Użyj alternatywnej grafiki gniazda\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"W grze zostanie wykorzystana alternatywna paleta kafelków gniazda Hellfire.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Kursor sprzętowy\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Użyj kursora sprzętowego\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Kursor sprzęt. dla przedmiotów\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Użyj kursora sprzętowego dla przedmiotów.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Maks. rozmiar kursora sprzętowego\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Maksymalna szerokość / wysokość kursora sprzętowego. Większe kursory są \"\n\"przełączane z powrotem do programowego.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Pokaż FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Wyświetlanie liczby FPS w lewym górnym rogu ekranu.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Rozgrywka\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Ustawienia Rozgrywki\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Włączenie biegania/szybkiego chodzenia w mieście dla Diablo i Hellfire. \"\n\"Opcja ta została wprowadzona w dodatku.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Chwytanie Wejścia\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Po włączeniu tej funkcji mysz jest zablokowana w oknie gry.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Wstrzymanie Gry Gdy Okno Jest Nieaktywne\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\"Po włączeniu tej funkcji wstrzymuje grę, jeśli okno gry jest nieaktywne.\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Włącz zadanie Mała Dziewczynka.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Włącz zadanie Jersey. Rolnik Lester zostaje zastąpiony przez Kompletnego \"\n\"Wariata.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Przyjacielski ogień\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Umożliwienie zadawania obrażeń od strzał/czarów między graczami w trybie \"\n\"wieloosobowym, nawet jeśli włączony jest tryb przyjazny.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Pełne zadania w grach wieloosobowych\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Włącza pełne wersje zadań z gry jednoosobowej.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Testuj Barda\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Wymuś wyświetlanie typu postaci Bard w menu wyboru bohatera.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Testuj Barbarzyńcę\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\"Wymuszenie wyświetlania typu postaci Barbarzyńca w menu wyboru bohatera.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Pasek Doświadczenia\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\"Pasek doświadczenia zostanie dodany do interfejsu użytkownika w dolnej \"\n\"części ekranu.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Pokaż grafiki przedmiotów w sklepach\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"Pokaż grafiki przedmiotów na lewo od opisu w menu sklepów.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Pokaż punkty życia\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Wyświetla aktualną / maksymalną wartość stanu zdrowia na kuli zdrowia.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Pokaż punkty many\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Wyświetla aktualną / maksymalną wartość many na kuli many.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Informacje o postaci\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Pasek zdrowia wroga\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Pasek zdrowia wroga zostanie wyświetlony w górnej części ekranu.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Złoto jest automatycznie zbierane, gdy znajduje się w pobliżu gracza.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Eliksiry są automatycznie zbierane, gdy znajdują się w pobliżu gracza.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Oleje są automatycznie zbierane, gdy znajdują się w pobliżu gracza.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Automatycznie podnoś przedmioty w mieście.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria uzupełni twoją manę, gdy odwiedzisz jej sklep.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Broń zostanie automatycznie założona przy podnoszeniu lub zakupie, jeśli \"\n\"dana opcja jest włączona.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Pancerze będą automatycznie zakładane przy podnoszeniu lub zakupie, jeśli \"\n\"dana opcja jest włączona.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Hełmy będą automatycznie zakładane przy podnoszeniu lub zakupie, jeśli dana \"\n\"opcja jest włączona.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Tarcze będą automatycznie zakładane przy podnoszeniu lub zakupie, jeśli dana \"\n\"opcja jest włączona.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Biżuteria zostanie automatycznie założona przy podnoszeniu lub zakupie, \"\n\"jeśli dana opcja jest włączona.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Losowe wybieranie dostępnych zadań dla nowych gier.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Pokaż typ potwora\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Najechanie kursorem myszy na potwora spowoduje wyświetlenie jego typu w polu \"\n\"opisu w interfejsie użytkownika.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\"Pokazuje etykiety przedmiotów znajdujących się na ziemi kiedy włączone.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Uzupełnij pasek z ekwipunku, gdy przedmiot w nim zostanie zużyty.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Po włączeniu opcji Kociołki, Fascynujące Kapliczki, Kozie Kapliczki, \"\n\"Zdobione Kapliczki, Święte Kapliczki i Kapliczki Murphy'ego nie mogą zostać \"\n\"kliknięte i są one oznaczane jako wyłączone.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Szybki Czar\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Naciśnięcie klawisza skrótu zaklęcia powoduje natychmiastowe rzucenie \"\n\"zaklęcia, zamiast przełączania gotowego zaklęcia.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Liczba mikstur Leczenia, które są podnoszone automatycznie.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Liczba mikstur Pełnego Leczenia, które są podnoszone automatycznie.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Liczba mikstur Many, które będą podnoszone automatycznie.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Liczba mikstur Pełnej Many, które będą podnoszone automatycznie.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Liczba mikstur Wzmocnienia, które będą podnoszone automatycznie.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Liczba mikstur Pełnego Wzmocnienia, które będą podnoszone automatycznie.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Pokazuj liczbowe wartości\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\"Pokazuje liczbowe wartości przy zdobywaniu doświadczenia / zadawaniu obrażeń \"\n\"etc.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Wyłączone\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Losowy kierunek\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Tylko w pionie\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Kontroler\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Ustawienia Kontrolera\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Sieć\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Ustawienia Sieciowe\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Czat\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Ustawienia czatu\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Język\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Określ, jakiego języka należy używać w grze.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Ustawienia Języka\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Mapowanie Klawiszy\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Ustawienia mapowania klawiszy\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Mapowanie kontrolera\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Ustawienia mapowania kontrolera\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Ustawienia\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Poziom\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Doświad.\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Następny poziom\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Baza\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Teraz\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Siła\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magia\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Zręczność\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Witalność\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Punkty do rozdania\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Złoto\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Klasa pancerza\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"celność broni\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Obrażenia\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Życie\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Odp. na magię\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Odp. na ogień\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Odp. na błysk.\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"postać\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"zadania\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"mapa\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menu\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"ekwipunek\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"czary\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"czat\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"cisza\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Nieprzydatny\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Obr: 1/3 PŻ celu\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Uzdrawia: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Obrażenia: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Umiejętność\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Kostur ({:d} ładunek)\"\nmsgstr[1] \"Kostur ({:d} ładunki)\"\nmsgstr[2] \"Kostur ({:d} ładunków)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Poziom {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Czar\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Rani tylko nieumarłych\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Zwój\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Kostur\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Klawisz Czaru: {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Nie udało się wczytać zawartości\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Nie udało się wczytać postaci\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (lvl {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Historia czatu (Wiadomości: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} złota\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Ile sztuk złota chcesz wypłacić?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Poziom {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Doświadczenie: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Maksymalny Poziom\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Następny poziom: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} do Poziomu {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Grobowiec Króla Leoryka\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Komnata Kości\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Ciemne Przejście\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Przeklęty Ołtarz\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"{:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Potrzebuję pomocy! Chodź tu!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Idź za mną.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Mam coś dla ciebie.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Teraz ZGINIESZ!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Uzdrów się!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Uważaj!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Dziękuję.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Wycofać się!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Przepraszam.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Czekam.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Powrót\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Obrażenia: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Pancerz: {:d}  \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Wyt: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Niezniszczalne\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Witaj\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Warsztat Kowala\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Czynność:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Kup zwykłe przedmioty\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Kup wyjątkowe przedmioty\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Sprzedaż\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Naprawa\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Wyjdź\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Podstawowe przedmioty na sprzedaż:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Wyjątkowe przedmioty na sprzedaż:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Nie masz rzeczy, których potrzebuję.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Który przedmiot chcesz sprzedać?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Nie masz nic do naprawy.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Który przedmiot naprawić?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Chata Wiedźmy\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Kup przedmioty\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Naładowanie kosturów\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Wyjdź\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Nie masz niczego do regeneracji.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Który przedmiot zregenerować?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Brakuje ci złota\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Nie masz miejsca w ekwipunku\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Umowa stoi?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Czy na pewno chcesz zidentyfikować ten przedmiot?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Czy na pewno chcesz kupić ten przedmiot?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Czy na pewno chcesz zregenerować ten przedmiot?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Czy na pewno chcesz sprzedać ten przedmiot?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Czy na pewno chcesz naprawić ten przedmiot?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt - kulejący chłopiec\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Pokażę ci co oferuję,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"jeśli dasz mi zaliczkę:\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"50 szt. złota. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Zgoda, co tam masz?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Wyjdź\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Mogę ci to sprzedać:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Wyjdź\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Dom Uzdrowiciela\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Wyjdź\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Miejski Kronikarz\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identyfikacja\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Nie masz nic do identyfikacji.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Który przedmiot zidentyfikować?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Ten przedmiot to:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Akceptuj\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Rozmawiaj z {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Rozmowa z {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"jest niedostępna\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"w wersji\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"shareware\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Plotki\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Wschodzące Słońce\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Wyjdź\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Otwórz Skrytkę\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Pijak Farnham\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Rozmowa\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Wyjdź\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Twoje złoto: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Zabity Mieszkaniec\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Kowal Griswold\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Uzdrowiciel Pepin\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Ranny Mieszkaniec\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden - Właściciel Gospody\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Mędrzec Cain\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Wiedźma Adria\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Barmanka Gillian\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Krowa\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Farmer Lester\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Skończony Wariat\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Wojownik\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Łotrzyca\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Czarodziej\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Mnich\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Barda\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbarzyńca\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombie\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Ghul\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Gnijące Truchło\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Czarna Śmierć\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Upadły\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Podrzynacz\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Diablik\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Mroczny\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Szkielet\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Trupi Topornik\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Płonący Trup\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Kościej\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Ścierwojad\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Pożeracz Zarazy\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Bestia Cienia\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Miażdżyciel Kości\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Trupi Łucznik\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Kapitan Szkieletów\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Kapitan Zwłok\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Kapitan Płonących Trupów\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Kapitan Kościejów\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Niewidzialny Władca\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Ukryty\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Prześladowca\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Niewidoczny\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Tkacz Iluzji\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Władca Satyrów\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Klan Rozpruwaczy\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Klan Kamienia\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Klan Ognia\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Klan Nocy\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Bies\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Migon\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Ponurzec\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Chowaniec\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Żrąca Bestia\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Trujopluj\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Wżerobestia\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Ogniopaszczy\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Król Szkieletów\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Rzeźnik\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Nadzorca\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Błotoczłek\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Ropuszy Demon\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Obdzieracz Skór\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Żmijowiec\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Podziemny Czerw\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Diabelski Żmijowiec\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Pożeracz\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Demon Magmy\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Kamień Krwi\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Piekielny Kamień\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Władca Lawy\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Rogaty Demon\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Błotowiec\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Mroźny Szarżownik\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obsydianowy Władca\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"staruszek\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Czerwona Zaraza\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Diabelski Mag\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Nieumarły Balrog\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Kremator\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Władca Płomieni\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Płonąca Zagłada\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Piekielny Pomiot\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Czerwony Burzowiec\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Burzowy Jeździec\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Władca Burz\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Cyklon\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Oprych Diablików\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Skrzydlaty Demon\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargulec\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Krwawoszpon\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Śmiercioskrzydły\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Pogromca\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Strażnik\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Władca Wiru\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Jaskiniowy Żmij\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Ognisty Jaszczur\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Złoty Żmij\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Lazurowy Jaszczur\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Czarny Rycerz\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Strażnik Zagłady\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Stalowy Władca\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Rycerz Krwi\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Związany\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Pusta Istota\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Mistrz Bólu\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Tkacz Rzeczywistości\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Sukkub\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Śnieżna Wiedźma\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Córa Piekieł\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Wypalaczka Dusz\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Kanclerz\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Mediator\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Kabalista\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Adwokat\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Mroczny Władca\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Arcy-Lisz Złośliwiec\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Garbad Słaby\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar Szalony\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Śluzoglut\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Arcybiskup Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Czerwona Dręczycielka\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Nefrytoczerń\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Marszałek Krwi\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Przeżartuch\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Profanator\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Bezmózgi Topornik\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Twardoskóry Zabójca\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Ropiejąca Dusza\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Plugawy Szujożerca\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Kościorwij\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Pleśniożer\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Zwinny Patroszyciel\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Czaszkołup Tarczownik\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Rzezimieszek\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Kąsacz Cieni\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Martwooki\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Trup Szalonooki\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Ognistogłowy\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Wypaczona Czaszka\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Krwiopijca\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Rozdrażniony Pełzacz\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Zaklinacz Księżyca\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Kruk Gniewu\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Kręgojad\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Spopielacz\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Cieniowron\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Osłabiony Niszczyciel\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Rządca Czeluści\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Krwawoskóry Łucznik\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Plugawoskrzydły\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Spijacz Cieni\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Dręczyciel\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Śmierciopluj\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Krwiopijca\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Cień Rozpruwacza\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Wojenny Czerw\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Kościany Okruch\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Płomień Zniszczenia\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Mroźny Nocoskrzydły\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Rzezikamień\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Ognisty Pięściarz\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Zgładzony Furiat\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Poparzony Pustelnik\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Błotnisty Magnat\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Cień Zniszczenia\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Skowytnik\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Gnijący Chichot\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Wściekły Podpalacz\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Lisz Piłognat\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Łamikark\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Pożeracz Kości\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Burzowiec\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Szturmująca Zguba\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Szlamożer\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Płomienny Złotognij\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Czarny Sztorm\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Plagoupiór\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Obdzieracz\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Błękitnorogi\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Piekielne Plugastwo\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Ostrokieł\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Pęknięta Czaszka\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Krętacz Lwia Czaszka\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Czarny Jęzorak\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Plugawion\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Ogniożmij\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Zęboskóry\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Wiedźma Profanacji\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Czarnokostny\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Rozpruwacz Dusz\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Porywisty Niegodziwiec\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Pan Czeluści\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Tkacz Rdzy\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Wyjący Cień\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Powiew Zagłady\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Księżycowa Dusza\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Księżycowa Wiedźma\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Żywiciel Krwi\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Pogromiciel\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Sędzia Grozy\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Gwiezdnooka Wiedźma\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Łowca Stalowa Czaszka\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Generał Gorasz\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Wezyr\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamphir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Żądna Krwi\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Wdowa Sieci\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Pożeracz Zwłok\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Ostrze Grozy\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Zaklęta Śmierć\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Krótki Miecz\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Puklerz\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Maczuga\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Krótki Łuk\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Kostur Many\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Tasak\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Korona Nieumarłych\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Pierścień Niebios\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Magiczny Kamień\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Optyczny Amulet\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Pierścień Prawdy\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Szyld Gospody\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Przyodziewek Arlekina\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Stalowy Woal\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Złoty Eliksir\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Kowadło Gniewu\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Czarny Grzyb\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Mózg\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Atlas Grzybów\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Widmowy Eliksir\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Kamień Krwi\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Mapa Katedry\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Mikstura Leczenia\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Mikstura Many\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Zwój Identyfikacji\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Zwój Miejskiego Portalu\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Odwaga Arkaina\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Mikstura Pełnego Leczenia\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Mikstura Pełnej Many\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Ostrze Griswolda\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Byczy Pancerz\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Kostur Lazarusa\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Zwój Wskrzeszenia\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Krótki Kostur\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Miecz\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Sztylet\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Magiczna Bomba\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Teodor\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Amulet Dobrobytu\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Podarta Notatka, cz. 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Podarta Notatka, cz. 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Podarta Notatka, cz. 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Odtworzona Notatka\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Brązowy Strój\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Szary Strój\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Kaptur\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Szyszak\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Hełm\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Zamknięty Hełm\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Korona\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Wielki Hełm\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Peleryna\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Łach\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Szata\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Habit\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Pikowana Zbroja\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Skórzana Zbroja\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Ciężka Skórzana Zbroja\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Ćwiekowana Zbroja\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Pierścieniowa Zbroja\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Zbroja\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Kolczuga\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Łuskowa Zbroja\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Napierśnik\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Zbroja\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Karacenowa Zbroja\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Płytowa Zbroja\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Turniejowa Zbroja\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gotycka Płytowa Zbroja\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Pełna Płytowa Zbroja\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Tarcza\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Mała Tarcza\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Duża Tarcza\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Trójkątna Tarcza\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Ciężka Tarcza\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gotycka Tarcza\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Mikstura Wzmocnienia\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Mikstura Pełnego Wzmocnienia\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Olej\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Eliksir Siły\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Eliksir Magii\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Eliksir Zręczności\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Eliksir Żywotności\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Zwój Uzdrowienia\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Zwój Przeszukiwania\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Zwój Błyskawic\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Zwój Ściany Ognia\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Zwój Inferno\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Zwój Rozbłysku\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Zwój Infrawizji\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Zwój Przenikania\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Zwój Tarczy Many\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Zwój Fali Płomieni\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Zwój Ognistej Kuli\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Zwój Petryfikacji\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Zwój Eksplozji Błyskawic\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Zwój Strażnika\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Zwój Novy\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Zwój Golema\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Zwój Teleportacji\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Zwój Apokalipsy\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Tasak\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Sejmitar\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Claymore\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Klinga\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Szabla\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Długi Miecz\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Pałasz\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Bękarcki Miecz\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Dwuręczny Miecz\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Wielki Miecz\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Ręczny Topór\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Topór\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Duży Topór\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Szeroki Topór\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Bitewny Topór\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Wielki Topór\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Buława\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Wekiera\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Bojowy Młot\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Młot\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Kolczasta Maczuga\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Korbacz\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Kafar\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Łuk\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Myśliwski Łuk\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Długi Łuk\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Refleksyjny Łuk\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Krótki Bitewny Łuk\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Długi Bitewny Łuk\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Krótki Bojowy Łuk\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Długi Bojowy Łuk\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Długi Kostur\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Wygięty Kostur\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Okuty Kostur\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Bojowy Kostur\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Pierścień\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amulet\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Runa Ognia\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Runa\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Runa Błyskawic\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Większa Runa Ognia\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Większa Runa Błyskawic\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Runa Kamienia\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Kostur Wiązki Błyskawic\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Mikstura Areny\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Tasak Rzeźnika\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Miecz Światłości\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Łuk Szybkości\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Iglica\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Niebiański Łuk\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Mroczny Łowca\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Śmiercionośny Łuk\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Łuk z Mrocznego Dębu\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Płomienny Łuk\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Przebijacz\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Siła Wiatru\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Orli Róg\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Sztylet Gonnagala\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Obrońca\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Pazur Gryfa\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Czarna Brzytwa\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Zaćmienie Księżyca\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Ostrze Mrozu\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Miecz Kata\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Przecinacz Kości\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Orła Cień\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Kolec Czarownika\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Miecz Światłości\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Szpon Sokoła\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Herold Zagłady\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Niedźwiedź\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Pradziad\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Okulawiacz\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Zakrzywiony Dziób\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Krwawy Pogromca\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Niebiański Topór\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Niegodziwy Topór\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Kamienny Tasak\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Topór Aguinary\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Pogromca Piekieł\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Rozpruwacz Messerschmidta\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Rdzawy Łomot\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Młot Jholma\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Pałka Civerba\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Niebiańska Gwiazda\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Gwiazda Baranara\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Spaczony Korzeń\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Łamiczerep\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Młot Schaefera\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Poskramiacz Snów\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Kostur Cieni\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Kostur Ofiarny\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Szturmowa Iglica\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Złudna Pieśń\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Zew Burzy\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Orędownik\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Zagadka Naja\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Płacz Umysłu\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Drąg Onana\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Korona Dusz\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Kaptur Umysłu\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Hełm Nadzorcy\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Korona Błazna\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Zmierzch Bogów\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Królewski Diadem\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Strzępek Duszy\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Zguba Gladiatora\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Szata Tęczy\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Zbroja Giermka\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Szata Mądrości\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Iskrząca Kolczuga\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Pancerz Ścierwojada\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Mroczny Uciekinier\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Lekki Pancerz Naja\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Demoniczny Pancerz\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Bariera\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Tarcza Czaszki\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Smocza Osłona\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Tarcza z Mrocznego Dębu\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Święty Obrońca\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Tarcza Burzy\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Cierń\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Pierścień Regha\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Krwotok\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Pierścień Uciśnienia\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Pierścień Zobowiązania\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Blaszany\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Mosiężny\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Brązowy\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Żelazny\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Stalowy\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Srebrny\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platynowy\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithrilowy\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteorytowy\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Nietypowy\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Zbędny\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Wygięty\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Słaby\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Pęknięty\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Zabójczy\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Ciężki\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Wściekły\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Okrutny\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Ogromny\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Dziki\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Bezwzględny\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Bezlitosny\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Nieudany\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Tępy\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Ostry\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Świetny\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Wojowniczy\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Giermkowski\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Lordowski\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Rycerski\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Wyborny\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Przewyborny\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Królewski\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Delikatny\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Stary\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Silny\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Wielki\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Bitny\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Chwalebny\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Zbawienny\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Uświęcony\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Cudowny\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Boski\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Czerwony\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Szkarłatny\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Bordowy\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubinowy\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Niebieski\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Lazurowy\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lapisowy\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Kobaltowy\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Szafirowy\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Biały\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Perłowy\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Kościany\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Brylantowy\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Diamentowy\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topazowy\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Cytrynowy\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Agatowy\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Obsydianowy\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Szmaragdowy\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Wilczy\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Żabi\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Pajęczy\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Kruczy\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Wężowy\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Gadzi\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Sokoli\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Smoczy\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Żmijowy\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Mityczny\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Anielski\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Archanielski\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Obfity\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Dorodny\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Płonący\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Piorunowy\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"jakości\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"ran\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"zagłady\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"sadyzmu\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"zbrodni\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"rzezi\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"udręki\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"smutku\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"zdrowia\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"opieki\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"absorpcji\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"unikania\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"izolacji\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"marności\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"słabości\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"siły\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"mocy\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"władzy\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"giganta\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"tytana\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"paraliżu\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"atrofii\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"zręczności\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"talentu\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"celności\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"precyzji\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"perfekcji\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"głupca\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"dysfunkcji\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"magii\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"myśliciela\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"rozumu\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"czarów\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"iluzji\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"zarazy\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"choroby\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"żywotności\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"witalności\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"werwy\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"wigoru\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"życia\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"utrapienia\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"otchłani\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"łaski\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"księżyca\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"gwiazd\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"niebios\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"zodiaku\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"sępa\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"szakala\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"lisa\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"jaguara\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"orła\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"hieny\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tygrysa\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"lwa\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mamuta\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"wieloryba\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"wątłości\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"kruchości\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"krzepy\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"kunsztu\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"zwięzłości\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"wieków\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"mroku\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"zmierzchu\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"blasku\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"jasności\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"płomienia\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"ognia\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"spopielenia\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"wstrząsu\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"błyskawic\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"gromu\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"pokusy\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"obfitości\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"iglicy\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"skazy\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"złodzieja\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"bizona\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"nietoperza\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"wampira\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"pijawki\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"krwi\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"rozdarcia\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"przebicia\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"natarcia\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"gotowości\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"zwinności\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"szybkości\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"pośpiechu\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"równowagi\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"zaufania\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"harmonii\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"blokowania\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Magiczny Kamień\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Garbad Słaby\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar Szalony\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Rzeźnik\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Szyld Ogdena\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Sale Ślepców\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Odwaga\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Marszałek Krwi\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Klątwa Króla Leoryka\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Arcybiskup Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Sprawa Grobowca\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Sad Farmera\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Mała Dziewczynka\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Wędrujący Handlarz\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Profanator\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Krowia Krowa\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Ognisty Pocisk\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Uzdrowienie\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Błyskawice\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Rozbłysk\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identyfikacja\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Ściana Ognia\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Miejski Portal\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Petryfikacja\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infrawizja\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Przenikanie\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Tarcza Many\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Ognista Kula\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Strażnik\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Eksplozja Błyskawic\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Fala Płomieni\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Hydry\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Krwawy Rytuał\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Niewidzialność\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Furia\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleportacja\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apokalipsa\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Znieczulenie\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Naprawa Przedmiotów\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Naładowanie Kostura\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Rozbrajanie Pułapek\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Żywiołak\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Wiązka Błyskawic\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Święty Pocisk\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Wskrzeszenie\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekineza\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Uzdrowienie Innych\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Krwawa Gwiazda\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Kościane Widmo\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ach, chcesz poznać historię naszego Króla, tak? Tragiczny upadek Leoryka \"\n\"był bolesnym ciosem dla tej krainy. Ludzie od zawsze go wielbili, a teraz \"\n\"panicznie się go boją. Do dzisiaj zastanawia mnie to, jak Król mógł upaść \"\n\"tak nisko. Przecież był tak wielkodusznym władcą. Tylko najgorsze moce \"\n\"piekieł mogły tak doszczętnie zniszczyć jego duszę...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Wioska potrzebuje twojej pomocy! Kilka miesięcy temu porwano syna króla \"\n\"Leoryka, księcia Albrechta. Nasz władca wpadł w szał i przeczesał całą \"\n\"wioskę w poszukiwaniu zaginionego dziecka. Z każdym kolejnym dniem, Leoryk \"\n\"coraz głębiej popadał w obłęd. Doszukiwał się winy u niewinnych mieszczan, \"\n\"których kazał potem brutalnie stracić. Mniej niż połowa z nas przeżyła jego \"\n\"furię...\\n\"\n\" \\n\"\n\"Królewscy rycerze i kapłani próbowali go uspokoić. Wtedy Król zwrócił się \"\n\"przeciwko nim. Nie mając innego wyjścia, byli zmuszeni go zabić. Wraz ze \"\n\"swoim ostatnim tchnieniem, Leoryk nałożył straszliwą klątwę na swą byłą \"\n\"świtę. Poprzysiągł, że będą służyć mu w ciemnościach, na wieczność...\\n\"\n\" \\n\"\n\"W tym momencie sprawy przybrały gorszy obrót, niż sobie wyobrażałem! Nasz \"\n\"były król obudził się z wiecznego snu i przewodzi teraz legionami \"\n\"nieumarłych sług w labiryncie. Jego ciało zostało pochowane w komnacie, trzy \"\n\"poziomy pod katedrą. Błagam, zniszcz jego przeklętą formę i pozwól mu \"\n\"spocząć w pokoju...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Już mówiłem, Król został pochowany trzy poziomy pod katedrą. Oczekuje w \"\n\"mrokach podziemi na okazję, by nas zniszczyć...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Klątwa już minęła, ale obawiam się, że to był dopiero początek większych \"\n\"problemów. Na szczęście, możemy jeszcze zostać uratowani przed nadchodzącym \"\n\"niebezpieczeństwem. Twoje zwycięstwo dobrze nam wróży. Niech prowadzi cię \"\n\"światłość.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Utrata syna przerosła Króla. Próbowałem złagodzić jego obłęd, niestety \"\n\"bezskutecznie. Tamtego dnia, nad królestwem zawisła czarna klątwa. Jeżeli \"\n\"jednak uda ci się oswobodzić jego duszę, to może ta klątwa przeminie...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Nie chcę myśleć o tym, jak zginął nasz Król. Wolę zapamiętać go jako \"\n\"życzliwego i prawego władcę. Jego śmierć była bardzo smutnym wydarzeniem.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Wykułem wiele broni i pancerzy dla świty Króla Leoryka. Sam władca dostał \"\n\"ode mnie ogromny, dwuręczny miecz z najlepszego mithrilu, z koroną do \"\n\"kompletu. Wciąż nie mogę uwierzyć w to, jak zginął. Musiał zostać opętany \"\n\"przez naprawdę potężne i złowrogie siły!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Nie obchodzi mnie to. Słuchaj, żaden kościotrup nie będzie MOIM królem. \"\n\"Leoryk jest królem. Słyszysz? Królem! WIWAT KRÓL!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Martwi kroczący pomiędzy żywymi podążyli za przeklętym Królem. Posiadł moc, \"\n\"dzięki której może pozyskiwać jeszcze większą ilość wojowników. Jego armia \"\n\"nieumarłych wciąż się rozrasta. Jeśli go nie powstrzymasz, z pewnością \"\n\"zaatakuje tę krainę i wybije wszystkich jej mieszkańców.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Słuchaj, ja tu prowadzę interesy. Nie sprzedaję informacji i nie obchodzi \"\n\"mnie jakiś Król, który jest martwy dłużej, niż ja żyję. No, chyba, że \"\n\"potrzebujesz wyposażenia przeciwko niemu. Wtedy pomogę.\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Ciepło życia wpełzło do mego grobowca. Za chwilę cię stłamszę i staniesz się \"\n\"wiecznym sługą mego Pana!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Widzę, że ta dziwna sytuacja zastanawia również ciebie. Demony bojące się \"\n\"światła słonecznego prawdopodobnie wierzą, że drzemie w nim wielka moc. \"\n\"Przypuszczam, że gdy zobaczyły słońce, zobrazowane na wspomnianym przez \"\n\"ciebie szyldzie, pomyślały, że skrywa w sobie tajemniczą energię. Hmm, być \"\n\"może nie są tak bystre, jak się obawialiśmy...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Jeśli mogę... chciałbym opowiedzieć ci dziwną historię. Wiem, że masz \"\n\"ogromną wiedzę o tych potwornościach zamieszkałych w labiryncie, a \"\n\"przydarzyło się coś czego za nic nie potrafię zrozumieć... Pewnej nocy \"\n\"obudziło mnie jakieś dziwne skrzypienie. Kiedy wyjrzałem z sypialni, na \"\n\"dziedzińcu zobaczyłem cienie małych stworzeń, wyglądających jak demony. Po \"\n\"chwili uciekły, ale zdążyły ukraść szyld mojej gospody. Nie pojmuję, czemu \"\n\"zabrały szyld, a nas zostawiły w spokoju... dziwne, nie?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Och, nie trzeba było zwracać mi szyldu, choć dzięki tobie nie muszę kupować \"\n\"nowego. Dobrze, zobaczmy, jak mogę ci to wynagrodzić? Hmmm, co my tu mamy... \"\n\"o, jest! Tę czapkę zostawił po sobie pewien czarodziej, który zatrzymał się \"\n\"tu jakiś czas temu. Może ci się do czegoś przyda.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Wielkie Nieba! Demony biegają nocami po wiosce i grabią nasze domy - czy nie \"\n\"ma już żadnych świętości? Mam nadzieję, że Ogden i Garda są cali. Chyba \"\n\"przyszliby do mnie, gdyby coś im się stało...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"O rety! Zabrały szyld? Musiałyśmy przespać z babcią całe to zamieszanie. \"\n\"Dzięki światłości, że stwory nie zaatakowały gospody.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Że co? Demony ukradły szyld Ogdena? Znam z plotek i widzenia większe \"\n\"potworności, których się dopuszczały. \\n\"\n\" \\n\"\n\"Z reguły wolą wyrywać serca z piersi niż szyldy z fasad.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Wiesz co? Myślę, że ktoś ukradł ten szyld i będzie chciał za niego miliony \"\n\"monet. Gdybym był Ogdenem... choć nie jestem, no ale gdybym był... to \"\n\"kupiłbym nowy szyld, z jakimś ładniejszym malunkiem. Może kuflem piwa, albo \"\n\"kiszonym ogórkiem...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Żaden śmiertelnik nie jest w stanie w pełni zrozumieć demonicznego umysłu. \\n\"\n\" \\n\"\n\"Ich dziwne zachowania mogą być częścią większego planu.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"I co - jeszcze sugeruje, że to moja sprawka? Pewnie Griswold też trzyma jego \"\n\"stronę. \\n\"\n\" \\n\"\n\"Słuchaj, szyldy przestałem kraść dawno temu. Nie dostaniesz wiele za kawałek \"\n\"drewna.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hej - Ty co zabijać wszystkich!  Ty zdobyć mi Czarodziejski Znak albo my \"\n\"atakować!  Ty nie odejść żywo!  \\n\"\n\" \\n\"\n\"Ty zabić dużych brzydali i przynieść nam Magia. Iść za róg i drzwi, znaleźć \"\n\"brzydali. \\n\"\n\" \\n\"\n\"Ty dać, ty odejść!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"\"\n\"Ty zabić brzydali, zdobyć znak. \\n\"\n\" \\n\"\n\"Ty mi go przynieść, bo inaczej...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Oddać!  O taak! \\n\"\n\" \\n\"\n\"Już odejść, my potężni. \\n\"\n\" \\n\"\n\"My zniszczyć wszystkich! \\n\"\n\" \\n\"\n\"Duża magia!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"To nie wróży nam dobrze. Potwierdzają się moje najgorsze obawy. Nie chciałem \"\n\"wierzyć starożytnym przepowiedniom, jednak właśnie zaczynają się \"\n\"urzeczywistniać. Chyba powinienem powiedzieć ci, kim dokładnie jestem. \\n\"\n\" \\n\"\n\"Nazywam się Deckard Cain Starszy, jestem ostatnim potomkiem prastarego \"\n\"Bractwa, chroniącego ludzkość przed odwiecznym złem. Złem, które właśnie się \"\n\"przebudziło. \\n\"\n\" \\n\"\n\"Arcybiskup Lazarus, kiedyś najbardziej zaufany doradca Króla Leoryka, \"\n\"zachęcił grupę prostych mieszczan do zejścia w głąb Labiryntu. Mieli \"\n\"odnaleźć zaginionego księcia, Albrechta. Po długim czasie, z całej grupy, \"\n\"żywych wróciło tylko kilku. \\n\"\n\" \\n\"\n\"Jestem głupcem! Powinienem domyślić się, że coś było nie tak. To pewnie sam \"\n\"Lazarus porwał Albrechta i ukrył go we wnętrzu Labiryntu. Nie rozumiem tylko \"\n\"dlaczego Arcybiskup poddał się mocom ciemności, i czemu wybrał akurat \"\n\"dziecko... No chyba, że chciał złożyć je w ofierze swym mrocznym panom! \\n\"\n\" \\n\"\n\"Tak, to musiał być jego plan od samego początku! Ludzie z 'grupy \"\n\"ratowniczej', którym udało się uwolnić, mówili o tym, że Lazarus na sam \"\n\"koniec zniknął w najdalszych zakątkach Labiryntu. Musisz się pośpieszyć i \"\n\"ocalić księcia przed ofiarnym ostrzem tego obłąkanego potwora!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Pośpiesz się! Albrecht wciąż jest w rękach Lazarusa. Książę i mieszkańcy \"\n\"tego królestwa liczą na ciebie!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"To naprawdę ponura historia. Lazarus bez wątpienia spłonie w piekle za ten \"\n\"potworny czyn. Jednakże chłopiec, którego opisujesz, nie jest naszym \"\n\"księciem. Albrecht nadal może być w niebezpieczeństwie. A ten wielki symbol, \"\n\"o którym mówisz, musi być portalem do samego serca Labiryntu. \\n\"\n\"Posłuchaj uważnie - zło z którym teraz się spotkasz, to mroczny Pan Grozy. \"\n\"śmiertelnicy nazywają go Diablo. To właśnie jego uwięziono wewnątrz \"\n\"Labiryntu wiele wieków temu. Obawiam się, że znowu zacznie siać grozę w \"\n\"krainie śmiertelników. Musisz przejść przez portal i zniszczyć Diablo, nim \"\n\"będzie za późno!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus był arcybiskupem, który zaprowadził wielu spośród mieszkańców do \"\n\"Labiryntu. Tego dnia straciłem mnóstwo dobrych przyjaciół, a Lazarus nigdy \"\n\"już nie powrócił. Przypuszczam, że został po drodze zabity, jak zresztą \"\n\"większość. Mam też do ciebie jedną prośbę - nie rozmawiaj o tym dniu z \"\n\"Farnhamem.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Byłem zszokowany kiedy tamtej nocy usłyszałem o planie mieszkańców. \"\n\"Myślałem, że z tych wszystkich ludzi, to Lazarus ma najwięcej zdrowego \"\n\"rozsądku. W końcu był Arcybiskupem i zawsze troszczył się o tutejszą \"\n\"ludność. Wróciło tylu rannych, że... nie dałem rady wszystkich uratować.\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Pamiętam Lazarusa jako bardzo ciepłego i życzliwego człowieka. Przemawiał na \"\n\"pogrzebie mojej mamy i w tym trudnym czasie wspierał mnie i babcię. \"\n\"Codziennie modlę się o to, żeby jakimś cudem wrócił cały i zdrowy.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Byłem członkiem grupy sprowadzonej do Labiryntu przez Lazarusa. Cały czas \"\n\"mówił coś o świętej zemście, ale gdy pojawiły się demony, to nawet nie \"\n\"wyciągnął broni zza pasa. Zamiast tego uciekł wprost w korytarze wypełnione \"\n\"sługusami zła!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Dźgały, potem gryzły, były wszędzie. Kłamca! KłAMCA! Wszyscy zginęli! Nie \"\n\"żyją! Słyszysz? Po prostu padali, jeden po drugim... ich krew tryskała po \"\n\"całej podłodze... wszystko przez niego...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Choć nie poznałam Lazarusa, wyczuwam w nim głęboki konflikt. Stanowi ogromne \"\n\"niebezpieczeństwo. Nic nie powstrzyma go przed służbą mocom ciemności, które \"\n\"nad nim zapanowały.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Och, szlachetny Lazarus, ten któremu taaak dobrze szło odstraszanie demonów, \"\n\"że straciłem nogę? Wiesz, dam ci bezpłatną radę. Porozmawiaj z Farnhamem, on \"\n\"wszystko widział.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"To koniec twej drogi. Czeka cię już tylko gniew mego Pana! Nie udało ci się \"\n\"uratować dziecka, ale zaraz spotkasz je w piekle!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, nie mam zbyt wielu informacji na ten temat. Słyszałem niegdyś o tunelu, \"\n\"który prowadzi do podziemnego jeziora. Prawdopodobnie jest ono źródłem \"\n\"wypełniającym nasze studnie. Niestety, nie wiem co dokładnie mogło \"\n\"doprowadzić do skażenia naszej wody.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Od zawsze staram się utrzymywać duże zapasy żywności i napitków w naszej \"\n\"piwnicy. Niestety, odkąd miasto nie ma dostępu do świeżej wody, rezerwy \"\n\"szybko się wyczerpują.\\n\"\n\" \\n\"\n\"Błagam, pomóż nam, jesteś naszą jedyną nadzieją.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Właśnie miałem cię wołać! Woda w naszych studniach stała się brudna i \"\n\"cuchnąca. Kilku mieszkańców wioski miało po jej wypiciu objawy zatrucia, a \"\n\"nasze rezerwy świeżej wody błyskawicznie się wyczerpują. Jestem przekonany, \"\n\"że gdzieś w pobliżu jest przejście prowadzące do źródeł zaopatrujących nasze \"\n\"miasto. Proszę, znajdź przyczynę tego problemu, inaczej źle się to dla nas \"\n\"skończy.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Proszę, pośpiesz się. Z każdą godziną mamy coraz mniej wody zdatnej do \"\n\"picia. \\n\"\n\" \\n\"\n\"Nie przetrwamy długo bez twojej pomocy.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Twierdzisz, że sama obecność demonów skaziła nasze wody? Och, podziemia \"\n\"Tristram skrywają naprawdę wielkie zło, lecz twoja wytrwałość i odwaga dają \"\n\"nam jeszcze nadzieję. Proszę, trzymaj ten pierścień - powinien pomóc ci w \"\n\"pokonywaniu tych nikczemnych stworzeń.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Moja babcia źle się czuje, a Garda powiedziała, że woda ze studni nie nadaje \"\n\"się do picia. Proszę, możesz nam jakoś pomóc?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin ma rację, skażona woda to ogromny problem. Próbowałem oczyścić jedną z \"\n\"pomniejszych studni, ale wciąż niesamowicie z niej cuchnie. Problem musi \"\n\"leżeć gdzieś u źródeł.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"No co ty? Wodę pijesz?!\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Mieszkańców Tristram czeka śmierć, jeśli w studni z powrotem nie pojawi się \"\n\"czysta woda. \\n\"\n\" \\n\"\n\"Miej na uwadze, że istotą tego problemu są demony, choć nie są tego świadome.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Tym razem trzymam za ciebie kciuki. że tak powiem: biznes nie może kwitnąć, \"\n\"kiedy nie ma wody. Lepiej szybko zbadaj sytuację!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Komnata z ludzkich kości... Tak, wspomniano o niej w kilku pradawnych \"\n\"tekstach, które studiowałem w bibliotekach Wschodu. Napomknięto w nich, że \"\n\"gdy Władcy Podziemi chcieli chronić swoje wielkie skarby, tworzyli specjalne \"\n\"sfery. Każdy kto zginął w takiej sferze próbując zdobyć skarb, stawał się na \"\n\"wieczność jego strażnikiem. Czyż to nie potworna, a zarazem dość rozsądna \"\n\"metoda?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Niestety, słyszę o niej pierwszy raz. Cain ma wiele ksiąg i może w którejś z \"\n\"nich znajdzie coś na jej temat.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Brzmi niebezpiecznie. Jeżeli tam wejdziesz, to proszę, zachowaj ostrożność.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Chyba nigdy nie słyszałam o takiej Komnacie. Nasz Kronikarz Cain może coś o \"\n\"niej wiedzieć.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Nie słyszałem o tym miejscu. Zapytaj Caina. On gada o tak wielu rzeczach, że \"\n\"pewnie ma już kilka odpowiedzi na to pytanie.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"No dobra, słuchaj. Jest sobie taka komnata z drewna. I jego żona, wiesz, ona \"\n\"mówi, na drzewo... bo musiszz zaczekać. To ja mówię, że tak się nie mówi, a \"\n\"jeśli myślisz, że za to ZAPłACĘ... to... nieważnee.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Jeśli umrzesz w tym przeklętym miejscu, rozpocznie się twa wieczna służba \"\n\"dla władców ciemności.\\n\"\n\" \\n\"\n\"Do Komnaty Kości wchodź na własną odpowiedzialność.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Ogromny i tajemniczy skarb, powiadasz? Może nawet coś bym od ciebie kupił... \"\n\"a nie potrzebujesz może jakiegoś unikalnego i drogiego wyposażenia żeby go \"\n\"zdobyć?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Wygląda na to, że Lazarus zwabił do Labiryntu wielu mieszkańców. Powiedział \"\n\"im, że idą tam, aby odnaleźć zaginionego księcia. Udało mu się wszystkich \"\n\"podburzyć i zmienić w rozszalały tłum, przez co nikt nie myślał o \"\n\"czyhających zagrożeniach... Kiedy cała grupa została osaczona przez \"\n\"przeraźliwe kreatury, Arcybiskup zniknął, pozostawiając swoich ludzi na \"\n\"pewną i potworną śmierć.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Tak, Farnham mamrotał coś o potężnej bestii, władającej straszliwą bronią. Z \"\n\"tego co pamiętam, nazywał ją... rzeźnikiem.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Na światłość, słyszałem o tym podłym demonie. Wielu ze śmiałków, którzy \"\n\"przeżyli wyprawę do katedry, nosiło znamiona jego straszliwego gniewu. Nie \"\n\"mam pojęcia czego używa do ćwiartowania swych ofiar, ale... to nie może być \"\n\"broń z tego świata. Zostawia ropiejące rany, których nawet ja nie jestem w \"\n\"stanie wyleczyć. Miej się na baczności, jeżeli staniesz z nim do walki...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Kiedy Farnham opowiadał coś o rzeźniku zabijającym ludzi, zlekceważyłam to. \"\n\"Jednak skoro teraz ty przychodzisz z tym do mnie... to już sama nie wiem.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Razem z Farnhamem na własne oczy widzieliśmy Rzeźnika. Machał tasakiem \"\n\"wielkim jak topór, rozcinając jednym uderzeniem ciała mych przyjaciół. Od \"\n\"tego przerażającego widoku oddzielała mnie jedynie gromadka małych, \"\n\"skrzeczących stworów. Na szczęście, jakimś cudem, udało mi się odnaleźć \"\n\"drogę ucieczki. Nigdy więcej nie ujrzałem tego ohydnego potwora, ale jego \"\n\"zakrwawione oblicze nawiedza mnie do dzisiaj.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Wielki! Wielki tasak przecinający moich przyjaciół. Nie dało się zatrzymać. \"\n\"Musiałem uciekać... zostawić ich... zamkniętych w komnacie z tyloma \"\n\"ciałami... tylu bliskich... NIEEEEEEEE!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Rzeźnik to brutalny potwór, któremu ból i cierpienie innych sprawiają \"\n\"ogromną przyjemność. Spójrz do czego doprowadził Farnhama. Unicestwienie \"\n\"tego demona na pewno uspokoiłoby mieszkańców wioski.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Wiem o tym potworze więcej, niż ci się wydaje. Jego mali towarzysze złapali \"\n\"mnie i pozbawili nogi, zanim Griswold zdążył mnie stamtąd wydostać. \\n\"\n\" \\n\"\n\"Mówiąc wprost - zabij go, zanim on zabije ciebie i doda twoje zwłoki do \"\n\"swojej kolekcji.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Proszę... wysłuchaj mnie. Arcybiskup Lazarus... to on sprowadził nas na dół, \"\n\"żeby odnaleźć zaginionego księcia. Ten drań wprowadził nas w pułapkę! Teraz \"\n\"wszyscy nie żyją... zabił ich demon nazywany Rzeźnikiem. Pomścij nas! Zgładź \"\n\"Rzeźnika, by nasze dusze mogły zaznać spokoju.\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Recytujesz bardzo ciekawy wiersz, napisany w stylu, który przypomina mi \"\n\"jeden utwór. Poczekaj chwilę - jak on brzmiał?\\n\"\n\" \\n\"\n\"... Ciemność otaczająca ukrytych. Błysk oczu niewidoczny, słyszalny jedynie \"\n\"dźwięk ostrych szponów dręczących biedne dusze, które oślepionona \"\n\"wieczność. \\n\"\n\" \\n\"\n\"Więzienie dla potępionych zwane... Salami ślepców...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Nigdy nie interesowałem się poezją. Zatrudniałem bardów, kiedy gospoda \"\n\"jeszcze dobrze prosperowała, ale to dawne czasy.\\n\"\n\" \\n\"\n\"Co? Och, tak... emm, wiesz, lepiej będzie jak zapytasz kogoś innego.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Brzmi znajomo. Jeśli mnie pamięć nie myli, to natknąłem się na podobny tekst \"\n\"podczas zapoznawania się z historiami chorób powodowanych przez demony. \"\n\"Opisywano tam straszne miejsce, które... czekaj - chyba nie zamierzasz tam \"\n\"iść, co?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Jeśli masz pytania dotyczące ślepoty, zagadaj do Pepina. Pamiętam, że dał \"\n\"mojej babci miksturę, dzięki której zaczęła lepiej widzieć. Może tobie też \"\n\"będzie w stanie jakoś pomóc.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Niestety, nie słyszałem, ani nie widziałem miejsca, które mogłoby pasować do \"\n\"twojego opisu. Porozmawiaj na ten temat z Cainem.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Patrzaj na to... ale jaja, nie? No łapiesz? ślepy - i patrzaj!\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Jest to miejsce wielkiej udręki i grozy. Poruszaj się po nim ostrożnie albo \"\n\"zostaniesz tam dłużej niż myślisz.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Zobaczmy, czy dużo ode mnie kupujesz? Nie. Czy płacisz za informacje? Nie. \"\n\"Czy właśnie wynosisz się stąd, żeby porozmawiać z kronikarzem, który żyje z \"\n\"gadania? Owszem.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Twierdzisz, że przemówił do ciebie Lachdanan? Za życia był wielkim \\n\"\n\"i szanowanym rycerzem. Przez lata wiernie służył swojemu królowi, ale to już \"\n\"pewnie wiesz. \\n\"\n\" \\n\"\n\"Lachdanan na pewno nie poddałby się tak łatwo Klątwie rzuconej przez Króla, \"\n\"dlatego ta historia może być prawdziwa. Na twoim miejscu, spróbowałbym mu \"\n\"jakoś pomóc.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Ten dzielny wojownik, o którym mówisz, od dawna nie żyje! Nie chcę rozmawiać \"\n\"o zmarłych przed moją karczmą, dziękuję.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Złoty eliksir, hm. Nigdy wcześniej nie przyrządzałem mikstury w takim \"\n\"kolorze. Trudno mi przewidzieć, jak mógłby na ciebie zadziałać, więc lepiej \"\n\"go NIE PRÓBUJ. Najlepiej będzie jak po prostu spełnisz ostatnią wolę \"\n\"Lachdanana.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Nigdy wcześniej nie słyszałam o tym Lachdananie. Przykro mi, tym razem nie \"\n\"jestem w stanie pomóc.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Jeśli to faktycznie jest Lachdanan, myślę, że warto mu pomóc. Miałem \"\n\"przyjemność go poznać. Wyglądał na osobę z natury lojalną i uczciwą. Klątwa \"\n\"Króla Leoryka prawdopodobnie najdotkliwiej uderzyła więc właśnie w niego.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan nie żyje. Nie ze mną te numery, wszyscy już o tym wiedzą. A \"\n\"zmarli nie mówią. Sprawdzałem!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"W Labiryncie może być uwięzionych więcej ludzi pokroju Lachdanana. \\n\"\n\" \\n\"\n\"Wyczuwam w nim ogromne wyrzuty sumienia i honor. Pomagając mu, pomożesz \"\n\"Tristram.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Czekaj, niech zgadnę. Pod Cainem pojawiła się gigantyczna szczelina, \"\n\"pochłonęła go, a potem spłonął w ogniu piekielnym i nie odpowie już więcej \"\n\"na twoje pytania. Och, nie trafiłem? Dobra, to zgaduję, że albo coś kupujesz \"\n\"albo stąd idziesz.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Proszę, nie krzywdź mnie. Wszystko ci wyjaśnię. Byłem niegdyś kapitanem \"\n\"rycerzy króla Leoryka. Strzegliśmy sprawiedliwości i honoru tutejszych ziem. \"\n\"Niestety, przez udział w jego tragicznej śmierci, spadła na nas mroczna \"\n\"Klątwa. Chociaż moi towarzysze zaakceptowali swój koszmarny los, ja, chcąc \"\n\"uwolnić się od przekleństwa, uciekłem z królewskiej krypty. Nie potrafiłem \"\n\"jednak sobie pomóc...\\n\"\n\" \\n\"\n\"Słyszałem o Złotym Eliksirze, który mógłby zdjąć ze mnie klątwę. Moja dusza \"\n\"zaznałaby w końcu spokoju. Niestety nie udało mi się go znaleźć. Wciąż \"\n\"słabnę i zanikają we mnie resztki człowieczeństwa. Proszę, pomóż mi odnaleźć \"\n\"Eliksir. Odwdzięczę ci się za twój wysiłek, przysięgam na swój honor.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Nie masz jeszcze Złotego Eliksiru. Boję się, że pozostanę przeklęty na \"\n\"wieczność. Proszę, znajdź go...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Ma dusza została uratowana przed potępieniem, nawet nie wyobrażasz sobie ile \"\n\"ci zawdzięczam. Dołożę wszelkich starań, aby pomóc ci z zaświatów, a \"\n\"tymczasem - weź mój hełm. W drodze, która mnie czeka, na niewiele mi się \"\n\"przyda. Ciebie może za to chronić przed siłami zła, które spotkasz. Niech \"\n\"światłość zostanie twym przewodnikiem...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold mówił o legendarnym Kowadle Gniewu, którego nikomu nie udało się \"\n\"jeszcze odnaleźć. To narzędzie rzemieślnicze zostało wytopione z metalowych \"\n\"kości brzytwodemonów, pośród czaszek pięciu najsilniejszych magów podziemi, \"\n\"a następnie pokryte runami mocy i chaosu. Broń i pancerz wykute na tym \"\n\"Kowadle przesiąkają więc potęgą Chaosu, przez co tak naprawdę nigdy nie \"\n\"wiadomo jakie magiczne właściwości otrzymają...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Nie sądzisz, że lepiej byłoby zapytać o to Griswolda? Ma większą wiedzę na \"\n\"ten temat.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Mógłbym opowiedzieć coś na temat Misy Uzdrowienia albo Srebrnego Kielicha \"\n\"Oczyszczenia, ale w tym wypadku, lepiej będzie jak udasz się do Griswolda \"\n\"albo Caina.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Kiedy byliśmy mali, ojciec Griswolda opowiadał nam o wielkim kowadle, \"\n\"którego używano do wykuwania potężnych broni. Mówił, że po uderzeniu w nie \"\n\"młotem, ziemia zaczynała drżeć tak, jakby wpadała w gniew. Ilekroć czuję, że \"\n\"ziemia się trzęsie, przypominam sobie tę historię.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Witaj! Cieszę się, gdy odwiedzają mnie ulubieni klienci! Podobno schodzisz \"\n\"na coraz niższe poziomy Labiryntu, więc warto byłoby ci opowiedzieć pewną \"\n\"historię. \\n\"\n\" \\n\"\n\"Jeden z mieszkańców, któremu udało się wrócić z Katedry, opowiedział mi o \"\n\"niezwykłym kowadle, które zobaczył w trakcie ucieczki. Opis, który \"\n\"przedstawił, przypomniał mi o legendzie z dzieciństwa. Opowiadała ona o \"\n\"Piekielnej Kuźni, w której wykuwano potężne bronie nasycone magią. Mówiła \"\n\"także o tym, że gdzieś na jej terenie znajduje się Kowadło Gniewu! Podobno \"\n\"zawiera w sobie esencję świata demonów. \\n\"\n\" \\n\"\n\"Mówi się, że broń wykuta na płonącym Kowadle nasycona jest ogromną mocą. \"\n\"Jeśli rzeczywiście było ono tym z legendy, mógłbym za jego pomocą wykuć broń \"\n\"zdolną do zniszczenia nawet najpotężniejszego władcy Piekieł. \\n\"\n\" \\n\"\n\"Przynieś mi to kowadło i od razu biorę się do roboty!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Na razie nic? Nie poddawaj się. Broń wykuta na tym kowadle znacznie zwiększy \"\n\"twoje szanse. Wykonam ją najlepiej jak potrafię, zaufaj mi.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Nie mogę w to uwierzyć! Udało ci się, to jest Kowadło Gniewu. Doskonała \"\n\"robota. Teraz pokażemy tym bydlakom, że broń zrobiona przez człowieka \"\n\"potrafi spuścić dużo większy łomot niż najlepsza broń Piekieł. Weź to. Niech \"\n\"światłość ma cię w swojej opiece.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold nie może sprzedać swojego kowadła. No bo bez niego chyba nie będzie \"\n\"słyszał. Ja to nigdy nie oddałbym mojego kowadełka!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Wewnątrz Labiryntu znajduje się wiele artefaktów o mocach przekraczających \"\n\"pojęcie śmiertelników. Część z nich może być używana zarówno przez siły \"\n\"Cienia jak i światłości. Zabranie tego Kowadła z podziemi może przechylić \"\n\"szalę Wojny Grzechu w stronę światła.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Jeśli znajdziesz artefakt dla Griswolda, poważnie zaszkodzisz moim \"\n\"interesom. Ach, nie uda ci się to.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Brama Krwi i Komnata Ognia to obiekty o mistycznym pochodzeniu. Gdziekolwiek \"\n\"znajduje się miejsce, wspomniane w tej księdze, na pewno emanuje tam wielka \"\n\"moc. \\n\"\n\" \\n\"\n\"Legendy mówią o obsydianowym piedestale ozdobionym kośćmi i zwieńczonym \"\n\"źródłem wrzącej krwi. Mówi się również o Kamieniach Krwi, które umożliwiają \"\n\"otwarcie komnaty strzegącej starożytnego skarbu... \\n\"\n\" \\n\"\n\"Powiadają, że starożytny bohater Arkain, umieścił tam święty pancerz Odwagi. \"\n\"Arkain był pierwszym śmiertelnikiem, któremu udało się przechylić szalę \"\n\"Wojny Grzechu i przegonić legiony ciemności z powrotem do płonących \"\n\"piekieł. \\n\"\n\" \\n\"\n\"Tuż przed jego śmiercią, zbroję ukryto w tajnej krypcie. Mówi się, że gdy \"\n\"ten święty pancerz będzie znowu potrzebny, nadejdzie bohater i ponownie \"\n\"przywdzieje... Odwagę. Być może to będziesz ty...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Każde dziecko słyszało historię o wojowniku Arkainie i jego niezwykłym \"\n\"pancerzu Odwagi. Odnalezienie go zapewni ci dobrą ochronę przed złem z \"\n\"Labiryntu.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... to brzmi znajomo, ale jestem teraz tak pochłonięty nauką tworzenia \"\n\"nowych leków i eliksirów, że za nic nie mogę sobie tego przypomnieć. \"\n\"Wybacz...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Historia o magicznym pancerzu, zwanym Odwagą? Brzmi jak coś z opowieści \"\n\"chłopców. Może zapytaj jednego z nich?\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Pancerz Odwagi może przechylić szalę na twoją stronę. Wielu go już szukało - \"\n\"w tym ja - niestety bezskutecznie. Arkain dobrze go ukrył i żeby go odnaleźć \"\n\"potrzeba będzie raczej czegoś więcej, niż odrobiny szczęścia.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Chrrrrrrrrrrrrrrrrrrrrrrrrrrrr...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Jeśli podczas wędrówki, natrafisz na Kamienie Krwi, korzystaj z nich \"\n\"ostrożnie. \\n\"\n\" \\n\"\n\"Droga pełna jest niebezpieczeństw, a ocalić może cię jedynie wiara we własne \"\n\"siły.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Zamierzasz znaleźć pancerz, zwany Odwagą?\\n\"\n\" \\n\"\n\"Arkaine ukrył go tak dobrze, że nikomu się to jeszcze nie udało. Skoro moje \"\n\"znajomości nic nie zdziałały, to wątpię, by tobie miało się powieść.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Znam tylko jedną legendę, która opowiada o takim wojowniku. Historia o nim \"\n\"znajduje się wewnątrz starożytnych kronik Wojny Grzechu... \\n\"\n\"Splamiony krwią, śmiercią i tysiącami lat wojen, Marszałek Krwi wchodzi na \"\n\"stos swych wypatroszonych ofiar. Za pomocą swego demonicznego ostrza, rzuca \"\n\"na ludzkość tajemniczą klątwę, nawołując do stawienia się przed oblicze \"\n\"Piekielnego Kata.\\n\"\n\" \\n\"\n\"Napisano również, że kiedyś był śmiertelnikiem walczącym w Wojnie Grzechu u \"\n\"boku Legionów Ciemności. Stracił człowieczeństwo przez swą wiecznie \"\n\"niezaspokojoną żądzę krwi.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Obawiam się, że nic nie słyszałem o tak okrutnym wojowniku. Mam nadzieję, że \"\n\"nie spotkasz go na swojej drodze, bo... wydaje się być wyjątkowo \"\n\"niebezpieczny.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain będzie mógł powiedzieć na ten temat więcej niż ja kiedykolwiek \"\n\"chciałbym usłyszeć.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Jeśli staniesz do walki z tak groźnym przeciwnikiem, niech czuwa nad tobą \"\n\"światłość. Wierzę, że ci się uda.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Postać Marszałka Krwi otaczają potworne legendy. Dobrze przygotuj się do \"\n\"starcia z nim, gdyż jest bezwzględny i bezlitosny.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Dlaczego ty chcesz ciągle rozmawiać o Krwi? A co z kwiatkami, słoneczkiem... \"\n\"no i na przykład tą piękną panienką przy barze. Słuchaj no - ty masz już \"\n\"chyba obsesję!\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Jego umiejętność posługiwania się ostrzem jest godna podziwu, w końcu od \"\n\"tysięcy lat poruszał się wyłącznie na polu bitwy. Przykro mi, ale nie \"\n\"potrafię przewidzieć czy wygrasz ten pojedynek.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Nigdy nie widziałem się z tym Marszałkiem, ale ma chyba spory przerób \"\n\"mieczy. Chętnie zaopatrzyłbym jego wojska...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"Lata wojen sprawiły, że pragnę już tylko jednego. Twojej krwi!\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold mówi o Kamieniu Niebios, który miał zostać zawieziony do wschodniej \"\n\"enklawy i poddany tam dalszym badaniom. Emanował energią, która wyzwalała \"\n\"wizje niedostępne zwykłemu człowiekowi. Nie wiem, jakie jeszcze skrywa \"\n\"tajemnice, ale bez wątpienia warto byłoby go odnaleźć.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Karawana zatrzymała się tu, żeby uzupełnić zapasy przed dalszą podróżą na \"\n\"wschód. Sprzedałem im prawie całą skrzynię świeżych owoców i znakomite \"\n\"mięso, przygotowane przez Gardę. Szkoda,że tak skończyli...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Nie wiem po co im był ten kamień, ale skoro spadł z nieba, to lepiej na \"\n\"siebie uważaj!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Tak, kojarzę. Kiedyś zatrzymała się tu karawana z grupą bardzo ważnych \"\n\"ludzi. Pamiętam, że mieli dość specyficzne akcenty i przygotowywali się \"\n\"właśnie do dalekiej podróży. \\n\"\n\" \\n\"\n\"Myślę, że odnalezienie ich rzeczy może być teraz naprawdę trudne.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Zaczekaj chwilę - opowiem ci historię, która może cię zainteresować. Jakiś \"\n\"czas temu przejeżdżała tu karawana zmierzająca w kierunku wschodnich \"\n\"królestw. Rzekomo przewoziła skrawek nieba, który spadł na ziemię! Niestety \"\n\"karawana została okradziona przez zamaskowanych jeźdźców niedaleko północnej \"\n\"granicy naszej wioski. Przeszukałem jej pozostałości, chcąc znaleźć \"\n\"niebiański kamień, lecz nie było już po nim śladu. Znajdź go i przynieś, a \"\n\"wykonam dla ciebie coś naprawdę niesamowitego.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Mam nadzieję, że uda ci się znaleźć ten kamień. Jeśli mi go przyniesiesz, \"\n\"wykonam z niego coś potężnego.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Pokaż mi to - och... tak go sobie wyobrażałem. Daj mi chwilę...\\n\"\n\" \\n\"\n\"Ach, proszę bardzo. Umieściłem kawałki tego kamienia w srebrnym pierścieniu, \"\n\"który odziedziczyłem po ojcu. Mam nadzieję, że będzie ci dobrze służyć.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Miałem kiedyś piękny pierścień; bardzo drogi, był trochę niebieskawy, trochę \"\n\"zieloniutki, czerwoniutki... i srebrny też był. Nie pamiętam już co się z \"\n\"nim stało, ale bardzo mi go brakuje...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"W Kamieniu Niebios drzemie ogromna moc, a Griswold będzie potrafił \"\n\"wykorzystać ją dla naszego wspólnego dobra. Wiedz, że gdyby ktoś inny zlecił \"\n\"ci znalezienie tego kamienia, powstrzymałabym cię.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Jeżeli ktokolwiek mógłby zrobić coś sensownego z tego kamienia, to tylko \"\n\"Griswold. On zna się na swojej robocie. Mimo, że czasami podkradam mu \"\n\"klientów, to szanuję jakość jego towarów.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Wiedźma Adria szuka czarnego grzyba? Wiem o nim tyle samo co o uzbrojonych \"\n\"krowach. W moich księgach nic o tym nie wspominano. Może Pepin będzie \"\n\"wiedział coś na jego temat.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Powiem tylko, że razem z Gardą, nigdy, PRZENIGDY, nie podalibyśmy naszym \"\n\"dostojnym gościom czarnych grzybów. Jeśli Adria chce ich w swoim kotle, to \"\n\"jej sprawa, ja nawet nie wiem gdzie ich szukać. Czarne grzyby... ohyda!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Wiedźma powiedziała, że przyniesiesz mi mózg demona. Potrzebuję go do \"\n\"opracowania antidotum. Dla ludzi, którzy zostali zranieni przez te plugawe \"\n\"bestie, moje lekarstwo będzie na wagę złota. Muszę tylko rozpracować \"\n\"działanie trucizny, którą zostali zakażeni. Wystarczy więc, że wyjmiesz mózg \"\n\"z demona którego zabijesz i mi go dostarczysz. Będę ci za to naprawdę \"\n\"wdzięczny.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Wspaniale, dokładnie taki miałem na myśli. Nie potrzebowałem go do \"\n\"skończenia eliksiru, ale zostanie do badań. Mógłbym cię prosić o zaniesienie \"\n\"tego wiedźmie? Chyba czeka na tę miksturę.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Ogden zapewne ma kilka grzybów w swojej spiżarni. Może więc jego zapytaj?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Skoro Adria go jeszcze nie ma, na pewno jest wyjątkowy. Nic o nim nie wiem, \"\n\"ale to musi być... ogromny, nabrzmiały, gigantyczny i nadęty grzyb! No, \"\n\"życzę udanego grzybobrania.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden przyrządza takie czarne grzyby, że jak wypiję, to od razu mną miota. \"\n\"Słuchaj no, słuchaj... jest na to sposób - trzeba pić z umiarem!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Co my tu mamy? Ciekawe, to wygląda na księgę alchemicznych składników. Jest \"\n\"i czarny grzyb. Powinien być ogromny, na pewno trudno go będzie przeoczyć. \"\n\"Jeśli takowy znajdziesz, przynieś mi go, dobrze?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"To duży i czarny grzyb. Idź go szukać, jest mi potrzebny do specjalnej \"\n\"mikstury.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Tak, ten będzie idealny do mojego wywaru. Nawiasem mówiąc, uzdrowiciel \"\n\"potrzebuje mózgu jednego z demonów, żeby móc wyleczyć ludzi zatrutych jadem. \"\n\"Pewnie zamierza zrobić z niego antidotum. Jeśli pomożesz mu znaleźć to czego \"\n\"szuka, poproś go o odrobinę tego eliksiru dla mnie.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Po co mi to przynosisz? Nie potrzebuję mózgu demona. Chcę trochę eliksiru \"\n\"nad którym pracuje uzdrowiciel. To on potrzebuje tego cudacznego organu, \"\n\"który właśnie trzymasz, do przyrządzenia mikstury. Wystarczy trochę \"\n\"pomyśleć, prawda?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Co? Dopiero teraz przynosisz mi eliksir od uzdrowiciela? Jednak nie był mi \"\n\"potrzebny do wywaru. Zatrzymaj go dla siebie...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"Nie mam żadnych grzybów. Może chcesz coś bardziej użytecznego?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"Usunięty quest!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Cho... Chono tu. Słuchaj. Nie wiem czy ty to widzisz, ale tu jest coś \"\n\"narysowane. To mapa.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"Proooosi nie bij. Nie zabijaj. Daruj życie, a dobro cię spotka.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Dla ciebie coś robi. Prosi zostaw Garbada. On żyje i daje dobro.\\n\"\n\" \\n\"\n\"A ty weź to jako dowód obietnicy...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Jeszcze nic! Kończy! \\n\"\n\" \\n\"\n\"Wielka moc i siła. Żyć! Żyć! \\n\"\n\" \\n\"\n\"Nie męczył, więc spełni obietnicę!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"To za dobre! Zbyt silne! Nie odda tak łatwo!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Co?! Co ty tutaj robisz? Przez takich jak ty nie mogę się skoncentrować. \"\n\"Masz, weź to i daj mi pracować w spokoju. Więcej się tu nie pałętaj!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Ciekawość prowadzi do piekła!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Zostań na chwilę i posłuchaj...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Kiedy zaczniesz schodzić w głąb Labiryntu, prawdopodobnie natrafisz na \"\n\"ukryte tam księgi o wielkiej wiedzy. \\n\"\n\" \\n\"\n\"Czytaj je uważnie, mogą powiedzieć ci o rzeczach, o których nawet ja nie \"\n\"słyszałem.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Znam wiele mitów i legend, które mogą zawierać odpowiedzi na nurtujące cię \"\n\"pytania. Jeżeli podczas podróży obudzą się w tobie wątpliwości, przyjdź z \"\n\"nimi do mnie. Pomogę ci w miarę możliwości.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold to człowiek wielkich czynów. Pewnie nie mówił ci o swojej wyprawie \"\n\"w głąb labiryntu. Uratował wtedy Wirta. Odczuł też na własnej skórze jak tam \"\n\"jest niebezpiecznie. Poza tym jest niezwykle uzdolnionym rzemieślnikiem. \"\n\"Jeżeli twierdzi, że zrobi wszystko, żeby ci pomóc, zaufaj mu.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden jest właścicielem Gospody pod Wschodzącym Słońcem już od prawie \"\n\"czterech lat. Kupił ją kilka miesięcy przed tym jak wszystko poszło w \"\n\"diabły. Wraz z żoną, Gardą, nie mają pieniędzy na wyjazd. Wszystkie \"\n\"oszczędności zainwestowali w ułożenie sobie życia tutaj. Ogden jest dobrym i \"\n\"bardzo odpowiedzialnym człowiekiem.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Biedny Farnham. Jako jeden z nielicznych przetrwał zagładę grupy, która \"\n\"tamtego strasznego dnia wkroczyła do Katedry z Lazarusem. Przeżył, ale jego \"\n\"odwaga i rozsądek pozostały w mrokach podziemi. Teraz spokój odnajduje \"\n\"jedynie na dnie swojego kufla. Słuchaj go uważnie, ponieważ czasami z jego \"\n\"chaotycznego bełkotu można wyciągnąć skrawek prawdy.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Adria wzbudza we mnie niepokój. Przybyła krótko po zbezczeszczeniu katedry, \"\n\"w czasie gdy wszyscy inni uciekali. Zamieszkała w małej chatce na obrzeżach \"\n\"miasta, zbudowanej ponoć z dnia na dzień. Ponadto, wiedźma ta posiada dostęp \"\n\"do wielu dziwnych i tajemniczych artefaktów oraz ksiąg, których nigdy \"\n\"wcześniej nie widziałem.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Historia Wirta jest przerażająca. Został wyrwany z rąk swej matki i \"\n\"zaciągnięty do labiryntu przez małe, plugawe, dzierżące włócznie pomioty. \"\n\"Musisz wiedzieć, że tamtego dnia porwano też wiele innych dzieci, w tym syna \"\n\"Króla Leoryka. Rycerze z pałacu ruszyli im na ratunek, lecz od tamtej pory \"\n\"nie dali już znaku życia. Wirta odnalazł kowal, niestety chłopiec padł już \"\n\"ofiarą potwornych tortur tych plugawych bestii.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ach, Pepin. Uważam go za prawdziwego przyjaciela - chyba najbliższego, \"\n\"jakiego mam. Czasami wydaje się być trochę zagubiony, ale nigdy jeszcze nie \"\n\"spotkałem cieplejszej duszy. Niewielu posiada takie zasoby wiedzy czy \"\n\"umiejętności i chce się nimi dzielić.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian jest wspaniałą kobietą. Zajmuje w moim sercu szczególne miejsce. Ma \"\n\"pogodną duszę, a jej uśmiech niejednego już oczarował. Mieszka w gospodzie i \"\n\"pomaga swojej babci, która jest zbyt chora, żeby się swobodnie poruszać. \"\n\"Choć wiem, że każdy mężczyzna w wiosce oddałby za nią życie, to i tak \"\n\"czasami boję się o jej bezpieczeństwo.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Witaj w mojej Gospodzie!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Wielu śmiałków zasiadało przy stołach mej gospody i opowiedziano tutaj \"\n\"mnóstwo historii zapijając je także mnóstwem piwa. Jedyną rzeczą, z którą \"\n\"prawie każdy się zgadzał, była stara maksyma. Może ci się przyda. Ciało \"\n\"możesz rozciąć, ale kości musisz zmiażdżyć.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Kowal Griswold posiada ogromną wiedzę na temat broni i pancerzy. Koniecznie \"\n\"go odwiedź, jeśli twój ekwipunek będzie wymagał naprawy.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham spędza tu stanowczo za dużo czasu. Nieustannie zapija smutki tanim \"\n\"piwem. Nie mam serca, żeby go wyprosić, bo domyślam się ile wycierpiał w \"\n\"Labiryncie.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria jest zbyt mądra jak na swój wiek i to mnie troszeczkę przeraża. \\n\"\n\" \\n\"\n\"W sumie, to bez znaczenia. Posiada niepokojąco wiele magicznych przedmiotów. \"\n\"Znajdziesz ją w chacie, po drugiej stronie rzeki.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Jeśli chcesz dowiedzieć się więcej o historii naszej wioski, porozmawiaj z \"\n\"naszym kronikarzem, Cainem. On naprawdę dobrze zna jej przeszłość.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt? Ach, to mały urwis. Od zawsze wpadał w tarapaty, więc nie dziwi mnie \"\n\"co go w końcu spotkało. \\n\"\n\" \\n\"\n\"Prawdopodobnie kręcił się w miejscu, w którym nie powinno go być.Szkoda mi \"\n\"tego chłopca, wpadł w całkowicie nieodpowiednie towarzystwo.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin jest dobrym człowiekiem. Z pewnością najbardziej wielkodusznym w \"\n\"wiosce. Zawsze stara się pomagać ludziom w potrzebie, przez co ciężko jest \"\n\"mu znaleźć nawet chwilę wytchnienia...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, moja barmanka? Chyba tylko miłość do babci powstrzymuje ją przed \"\n\"ucieczką.\\n\"\n\" \\n\"\n\"Nie wiem ile już razy przekonywałem ją do wyjazdu i obiecywałem zająć się \"\n\"staruszką. Niestety, ta młoda dziewczyna ma zbyt czułe serce, żeby ją \"\n\"opuścić.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Jak się czujesz?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Dokonałem ostatnio bardzo interesującego odkrycia. W przeciwieństwie do nas, \"\n\"potwory z labiryntu mogą się leczyć bez używania mikstur czy magii. Jeśli \"\n\"zaczniesz walczyć z jednym takim stworem upewnij się, że go zabiłeś, inaczej \"\n\"szybko się zregeneruje.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Zanim Katedra została opanowana przez te szkaradztwa, była wielką skarbnicą \"\n\"wiedzy. Można było w niej znaleźć ogromne zbiory wartościowych ksiąg. Jeżeli \"\n\"jeszcze jakieś znajdziesz, koniecznie je przeczytaj. Niektóre tomy mogą \"\n\"wyjaśniać sekrety labiryntu.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold wie tak dużo o sztuce wojny, ile ja o sztuce leczenia. Jest \"\n\"sprytnym sprzedawcą, a jego dzieła nie mają sobie równych. Och, to \"\n\"prawdopodobnie dlatego, że jest teraz jedynym kowalem pozostałym w wiosce.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain jest prawdziwym mędrcem i przyjacielem. Przechowuje ogromną bibliotekę \"\n\"i ma wrodzoną zdolność dostrzegania prawdziwej natury problemów. Jeżeli \"\n\"kiedykolwiek będą cię jakieś nurtować, nie wahaj się do niego zagadać.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Nawet moje umiejętności nie wystarczyły by w pełni uzdrowić Farnhama. Och, \"\n\"potrafiłem wyleczyć jego ciało, ale nie jestem w stanie naprawić jego umysłu \"\n\"i ducha.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Podczas gdy ja używam magii jedynie do tworzenia mikstur i eliksirów, które \"\n\"tu sprzedaję, Adria zajmuje się prawdziwymi czarami. Wygląda na osobę \"\n\"niezaznającą snu i zawsze ma dostęp do wielu mistycznych ksiąg oraz \"\n\"artefaktów. Podejrzewam, że jej chata kryje więcej niż wydaje się na \"\n\"pierwszy rzut oka, ale nigdy nie miałem okazji wejść do środka.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Biedny Wirt. Zrobiłem dla tego dziecka wszystko co było w mojej mocy. Miał \"\n\"paskudne rany. Wiem, że nie znosi drewnianego kołka, który zastępuje mu \"\n\"nogę. Nikt nie powinien tak cierpieć, a już na pewno nie taki młody chłopiec.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Naprawdę nie rozumiem dlaczego Ogden został w Tristram. Ma słabe nerwy, ale \"\n\"jest inteligentnym i pracowitym człowiekiem, który poradziłby sobie \"\n\"wszędzie. Możliwe, że bał się wyjechać po usłyszeniu wieści o morderstwach w \"\n\"okolicy. Mógł też pozostać tu za namową żony, która nie chciała wyjeżdżać.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Barmanka, z gospody Ogdena, to urocza dziewczyna. Jej babcia jest bardzo \"\n\"chora i cierpi na halucynacje. \\n\"\n\" \\n\"\n\"Uważa je za wizje, ale nie jestem w stanie ocenić czy mówi prawdę.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Dobrego dnia! W czym mogę służyć?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Moja babcia miała sen o tym, że przyjdziesz ze mną porozmawiać. Miewa takie \"\n\"różne wizje i potrafi spojrzeć w przyszłość.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Kobieta na skraju wioski to wiedźma! Wydaje się być miła, a jej imię, Adria, \"\n\"brzmi dość przyjaźnie. Mimo to i tak się jej bardzo boję. \\n\"\n\"\\n\"\n\"Trzeba zdobyć się na wiele odwagi, żeby ją odwiedzić.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Nasz kowal to duma mieszkańców Tristram. Jest niezwykłym mistrzem rzemiosła, \"\n\"wygrywającym wiele konkursów w swojej gildii. Otrzymał nawet osobistą \"\n\"pochwałę od naszego Króla Leoryka, niech mu ziemia lekką będzie. Griswold \"\n\"jest również wielkim bohaterem; wystarczy zapytać Caina.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain jest tutejszym kronikarzem odkąd tylko pamiętam. Posiada przeogromną \"\n\"wiedzę i możesz z nim porozmawiać praktycznie o wszystkim.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham jest pijakiem, który swój brzuch wypełnia piwem, a uszy innych \"\n\"bełkotem. \\n\"\n\" \\n\"\n\"Wiem, że Pepin i Ogden go wspierają. Jest mi jednak bardzo przykro, kiedy \"\n\"widzę, że i tak z każdym dniem stacza się coraz bardziej.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin uratował życie mojej babci i chyba nigdy nie będę w stanie mu się za \"\n\"to odwdzięczyć. Jego umiejętność leczenia każdej choroby jest potężniejsza \"\n\"od najmocniejszego miecza i bardziej zagadkowa niż jakikolwiek czar, który \"\n\"potrafisz nazwać. Jeśli kiedykolwiek odniesiesz obrażenia, Pepin na pewno \"\n\"będzie w stanie ci pomóc.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Dorastałam z matką Wirta. Nazywała się Kanasa. Choć potwory wyrywając jej \"\n\"syna zadały jej tylko powierzchowne rany, to tak naprawdę nigdy już nie \"\n\"wydobrzała. Myślę, że umarła przez złamane serce. Wirt stał się podłym \"\n\"dzieckiem, patrzącym tylko na zysk. Wiem, że dużo wycierpiał i widział \"\n\"rzeczy, które trudno jest mi sobie nawet wyobrazić, jednak mam wrażenie, że \"\n\"nadal spowija go jakiś mrok.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden wraz z żoną przygarnęli mnie i moją babcię do swojego domu. Pozwolili \"\n\"nawet zarobić trochę złota, dając mi pracę w gospodzie. Wiele im \"\n\"zawdzięczam. Mam nadzieję, że kiedyś opuszczę to miejsce i pomogę im założyć \"\n\"wspaniały hotel na wschodzie.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Co mogę dla ciebie zrobić?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Szukasz czegoś do walki? Spójrz na broń podstawową, taką jak ta stępiona \"\n\"maczuga. Potrafi zdziałać cuda w walce przeciwko nieumarłym stworom tam na \"\n\"dole. Nie ma nic lepszego do roztrzaskiwania tych spróchniałych szkieletów!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Topór? Aaachh, to dobra broń, nadaje się do walki z każdym przeciwnikiem. \"\n\"Spójrz, jak przecina powietrze, a potem wyobraź sobie, że spotyka łeb \"\n\"tłustego demona na swojej drodze. Pamiętaj jednak, że ciężko się nim macha - \"\n\"ale mówimy przecież o potężnych ciosach!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Spójrz na to wykończenie, na te proporcje. Miecz we właściwych rękach jest \"\n\"najlepszą bronią. Jego błyszczące ostrze z łatwością przebija i rozcina \"\n\"nieumarłych. Bez problemu rani także żywych przeciwników!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Na twojej broni i pancerzu na pewno nie raz zostaną ślady po walce ze złem. \"\n\"Przynieś je wtedy do mnie, a dzięki odrobinie pracy i gorącej kuźni sprawię, \"\n\"że będą jak nowe!\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Ta wiedźma, Adria, zawsze ma wszystko czego tylko zapragnie. Za to ja muszę \"\n\"przemycać metale i narzędzia z karawan, które zatrzymują się na uboczach \"\n\"tego nieszczęsnego miasta. Gdybym poznał choć trochę jej zaklęć... Mógłbym \"\n\"wykonywać naprawdę nieprawdopodobne rzeczy.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian to miła dziewuszka. Szkoda, że jej babulka jest tak schorowana. \"\n\"Gdyby nie to, zorganizowałbym im wyjazd na jednej z kupieckich karawan.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Czasami odnoszę wrażenie, że Cain jest zbyt gadatliwy. Choć takie już pewnie \"\n\"jego powołanie. Gdybym tylko potrafił kuć stal z takim zacięciem, jak on \"\n\"potrafi paplać... Mógłbym wtedy wykonać zbroję płytową, wystarczająco dobrą \"\n\"dla samego Cesarza!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Tej nocy, kiedy Lazarus sprowadził nas do labiryntu, trzymałem się blisko \"\n\"Farnhama. To był ostatni raz kiedy widziałem Arcybiskupa. Gdyby Farnham nie \"\n\"stał wtedy u mojego boku, mógłbym nie przeżyć. Obawiam się, że te \"\n\"wydarzenia, okaleczyły jego duszę, tak jak mnie okulawiły. Chciałbym mu \"\n\"pomóc, ale nie jestem w stanie stoczyć tej walki za niego.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Ten wspaniały człowiek stawia potrzeby innych ponad swoje. Nie znajdziesz \"\n\"nigdzie osoby, która mogłaby powiedzieć coś złego o naszym uzdrowicielu.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Ten mały wpędzi się kiedyś w jakieś poważne tarapaty... znowu. Próbowałem \"\n\"zaciekawić go swoim zawodem - no wiesz, nauczyć go uczciwej pracy. On jednak \"\n\"woli czerpać zyski z handlu towarami nieznanego pochodzenia. Nie mogę mieć \"\n\"mu tego za złe, po tym co przeszedł, ale chciałbym, żeby bardziej na siebie \"\n\"uważał.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Karczmarz prowadzi tu swój mały interes, ale ciężko mu cokolwiek zarobić. \"\n\"Ledwo wiąże koniec z końcem. Dostarcza jedzenie i oferuje noclegi \"\n\"przyjezdnym. A ci niestety często wymykają się potajemnie i nie płacą mu \"\n\"należności. Gdyby nie zapasy zboża i suszonego mięsa w jego piwnicy, \"\n\"większość z nas już dawno pomarłaby z głodu od czasu najazdu demonów.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Napić się nie mogę w spokoju?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"Dziewuszka przy barze? Och, to dopiero ślicznotka. Do tego taka miła.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Dlaczego ta starucha nie zrobi dla odmiany czegoś ciekawszego. Wiem, wiem, \"\n\"nie ma na to czasu, ale posłuchaj... Ona jest jakaś nienormalna. Nigdy nie \"\n\"widziałem, żeby coś jadła albo piła - a nie możesz ufać komuś, kto nie pije. \"\n\"Nawet troszeczkę.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain nie jest tym za kogo się podaje. Wiem, wiem, opowiada ciekawe \"\n\"historyjki... parę z nich jest naprawdę strasznych. Albo śmiesznych... Wiesz \"\n\"co? On wie więcej niż wie, że wie.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Stary, dobry Griswold. Kocham go jak brata! Walczyliśmy razem, \"\n\"wiesz? Dawniej, kiedy... my... Lazarus... Lazarus... Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, lubię Pepina. Wiesz, on naprawdę robi co może. Słuchaj, musisz go \"\n\"poznać. To miły gość, który zawsze pomaga ludziom w potrzebie. Hej, to chyba \"\n\"tak jak ty, nie? Dawniej też taki byłem...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt jest dzieckiem, które ma więcej problemów ode mnie, a ja wiem wszystko \"\n\"o problemach. Posłuchaj - ten dzieciak robi świetne interesy, ale on też tam \"\n\"był, wiesz? Stracił nogę! Musi teraz chodzić na jakimś kołku. To przykre, \"\n\"naprawdę przykre...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden to najlepszy człowiek w mieście. Jego żona chyba za mną nie przepada, \"\n\"ale dopóki uzupełnia beczki, to da się ją jakoś znieść. Wygląda na to, że to \"\n\"ja spędzam najwięcej czasu z Ogdenem, ale on jest dla mnie taki dobry...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Heeejj chcę zzi coś powiedzieć, wiem o nich wszystko. Są moją specjalnością. \"\n\"Te tutaj są najlepsze... naaaajleeeepsze! Inne piwa są nic warte odkąd te \"\n\"głupie kundle...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Nikt mnie nie chce słu... słuchać. Gdzieś - nie jestem pewien - ale gdzieś \"\n\"pod kościołem leżą całe stosy złota. Błyszczą i brzęczą. I tylko czekają, \"\n\"coby ktoś je zebrał.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Wiem, że masz własne zdanie i wiem, że i tak mi nie uwierzysz, ale ta broń, \"\n\"którą walczysz - ona jest za słaba na tych wielkich bydlaków! Nie obchodzi \"\n\"mnie co mówi Griswold, ale już się nie robi takich rzeczy, co za dawnych \"\n\"czasów...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Gdybym był tobą... no ale nie jestem... no ale gdybym był, to wtedy bym \"\n\"wszystko sprzedał i stąd wyjechał... Ten chłopak, o tam... On zawsze ma \"\n\"dobry towar, ale jak nie masz złota... to ci nawet tego nie pokaże.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Wyczuwam duszę szukającą odpowiedzi...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Mądrość jest nabyta, nie nadana. Dlatego pochłaniaj wiedzę z każdej \"\n\"odnalezionej księgi. Jeśli będzie to wiedza, którą już posiadasz to \"\n\"pamiętaj, że można ją zawsze poszerzyć.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Najpotężniejsza moc często trwa najkrócej. Zapewne natkniesz się na \"\n\"starożytne formuły, o wielkiej sile, zapisane na zwojach pergaminów. Moc \"\n\"tych zwojów pozwala na wykorzystanie ich zarówno przez ucznia, jak i \"\n\"mistrza, z identycznym skutkiem. Wiedz, że trzeba je głośno wyrecytować, a \"\n\"zapisane na nich słowa nie mogą być zachowane w umyśle. Pamiętaj... użyć \"\n\"można ich tylko raz, dlatego wykorzystuj je z rozwagą.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Choć żar słońca jest niezmierzony, niewinny płomień świecy stwarza większe \"\n\"zagrożenie. żadnej energii, nie ważne jak wielkiej, nie wykorzystasz bez \"\n\"odpowiedniego jej skupienia. Magiczna moc zaczarowanych kosturów może być \"\n\"wielokrotnie uzupełniana, co umożliwi dalsze rzucanie zaklęć. Posiadam \"\n\"umiejętność przywracania im energii - lecz wiedz, że wszystko ma swoją cenę.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Granicę mądrości wyznacza społeczeństwo. Jeśli nie uda ci się rozszyfrować \"\n\"znalezionych ksiąg lub pergaminów, nie wahaj się przynieść ich do mnie. \"\n\"Spróbuję je odczytać i podzielę się odkryciami.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Dla człowieka znającego jedynie żelazo, nie ma większej magii niż stal. \"\n\"Kowal Griswold jest większym czarodziejem, niż mu się wydaje. Jego \"\n\"umiejętność spajania ognia z metalem jest zaprawdę niezrównana.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Tak jak zepsucie korzysta z zalet obłudy, tak cnotliwość korzysta z mocy \"\n\"lojalności. Młoda Gillian ma dobre serce. Potrzeby jej babci są dla niej \"\n\"ważniejsze od własnych. Boi się mnie, ale tylko dlatego, że mnie nie rozumie.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Skrzynia otwarta w ciemnościach nie skrywa większych bogactw niż otwarta w \"\n\"blasku światła. Kronikarz Cain jest tajemnicą, ale tylko dla zaślepionych. \"\n\"Jego wiedza o tym, co spoczywa pod katedrą jest dużo większa, niż mu się \"\n\"wydaje.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Im głębszą wiarę pokładasz w jednym człowieku, tym niżej możesz upaść. \"\n\"Farnham zatracił swą duszę, ale nie przez demony. Stało się to po zdradzie \"\n\"Arcybiskupa Lazarusa, gdy zobaczył cierpienie swoich najbliższych \"\n\"przyjaciół. Pamiętaj, że Farnham posiada ogromną wiedzę, musisz tylko \"\n\"oddzielić ziarno od plew.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Dłoń, serce i rozum, tworząc idealną harmonię, potrafią dokonywać cudów. \"\n\"Uzdrowiciel Pepin dostrzega w ciele to, czego nawet ja nie potrafię. Jego \"\n\"zdolność leczenia chorych i rannych wzbogacona jest o umiejętność tworzenia \"\n\"mikstur i eliksirów. Będzie dla ciebie wspaniałym sojusznikiem.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Nie potrafimy wejrzeć w przyszłość, lecz kiedy nadejdzie, dzierżyć ją będą \"\n\"dzieci. W duszy Wirta można dostrzec mrok, jednak nie stanowi on zagrożenia \"\n\"dla miasta ani mieszkańców. Jego kontakty z łotrami i sekretnymi gildiami z \"\n\"pobliskich wiosek zapewniają mu dostęp do wielu przedmiotów, które są rzadko \"\n\"spotykane w Tristram. Możesz potępiać jego metody, ale usługi, które \"\n\"świadczy, mogą okazać się pomocne w walce z nadchodzącą ciemnością.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Domu nie tworzą gliniane ściany i dach pokryty strzechą. Karczmarz Ogden \"\n\"spełnia więcej potrzeb tutejszych mieszkańców, niż są tego świadomi. \"\n\"Zapewnia schronienie Gillian i jej babci, podtrzymuje na duchu Farnhama i \"\n\"przypomina wszystkim o czasach świetności Tristram. Jego gospoda i dostępne \"\n\"tam proste przyjemności są dla wielu ludzi przebłyskiem dawnych i spokojnych \"\n\"czasów. Te wspomnienia rozbudzają w nich nadzieję na twój sukces.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Hej... Tu jestem...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Nie każdy w Tristram potrzebuje rzeczy z Labiryntu. Ja też ich nie chcę, \"\n\"choć pewnie trudno w to uwierzyć. \\n\"\n\" \\n\"\n\"Często tylko ty będziesz w stanie poznać ich prawdziwą naturę.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Nie wierz we wszystko, co mówi ten pijak. Nadmiar alkoholu zdążył już \"\n\"przyćmić jego wzrok i zdrowy rozsądek.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Moje towary nie pochodzą z Tristram. Jestem importerem jakościowych dóbr. \"\n\"Jeżeli chcesz handlować szmelcem, udaj się do Griswolda, Pepina albo tej \"\n\"wiedźmy, Adrii. Założę się, że wezmą wszystko, co im przyniesiesz...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Przypuszczam, że zawdzięczam swoje życie kowalowi, o ile można to jeszcze \"\n\"nazywać... życiem. Jasne, Griswold zaproponował mi naukę rzemiosła w kuźni. \"\n\"Mógłbym się od niego wiele nauczyć, ale w ten sposób nie zdobędę \"\n\"wystarczającej ilości pieniędzy do... dobrze, powiedzmy, że moje plany \"\n\"wymagają większych nakładów finansowych.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Gdybym był trochę starszy, obsypałbym ją wszystkimi skarbami świata. Mogę \"\n\"cię zapewnić, że w moje ręce wpadają naprawdę piękne rzeczy. Gillian jest \"\n\"prześliczną dziewczyną, która powinna opuścić Tristram póki jeszcze jest \"\n\"bezpiecznie. Hmmm... może zabiorę ją ze sobą, kiedy będę odjeżdżał...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain wie zbyt dużo. Przeraża mnie nawet bardziej niż ta kobieta za rzeką. \"\n\"Wciąż mówi jakie to mam szczęście, że przeżyłem oraz że w legendzie \"\n\"przepowiedziano moją historię. Chyba postradał zmysły.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - no, to jest facet z poważnymi problemami, i uwierz mi, wiem co \"\n\"oznaczają poważne problemy. Za bardzo komuś zaufał. Lazarus sprowadził go do \"\n\"samej krainy śmierci. Och, wiem co tam jest, więc nie próbuj nawet mówić mi \"\n\"o swoich planach zniszczenia zła, które miota się po labiryncie. Lepiej \"\n\"uważaj na nogi...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Stary, dobry Pepin... może okazać się pomocny... dopóki nie będzie trzeba ci \"\n\"z powrotem czegoś przyszywać. \\n\"\n\" \\n\"\n\"Gdybym tylko miał wtedy trochę jego eliksirów, to może nie straciłbym nogi...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria naprawdę mnie niepokoi. No jasne, Cain też potrafi przerazić tym co \"\n\"mówi o przeszłości, ale ta wiedźma - potrafi w nią wejrzeć. Zawsze znajduje \"\n\"sposób na zdobycie wszystkiego, czego tylko zapragnie. Adria dostaje w ręce \"\n\"takie rzeczy, których nie widziałem nawet w czasie trwania Największych \"\n\"Targów!\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden zachowuje się jak wariat. Mógłbym wywieść go z miasta za rozsądną \"\n\"cenę, lecz on uparcie próbuje uratować swoją głupią gospodę. Przynajmniej \"\n\"daje Gillian miejsce pracy, a jego żona Garda piecze wyśmienite ciasta...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Za Salą Bohaterów znajduje się Komnata Kości. Wieczne potępienie czeka na \"\n\"każdego, kto odważy się wykraść złożone w niej skarby. Tak oznajmił Pan \"\n\"Grozy, tak też zostało zapisane.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"... I tak, zamknięta za Bramą Krwi i Komnatą Ognia, Odwaga oczekuje na \"\n\"przebudzenie przez Bohatera światłości...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Nie pojmujesz mych wizji,\\n\"\n\"Nie rozróżniasz w nich fikcji.\\n\"\n\"Odwróć wzrok, już zniknęły,\\n\"\n\"Blask światła zniknął naraz.\\n\"\n\"Lecz swą pieśnią cię tknęły,\\n\"\n\"Widzisz już baśni obraz.\\n\"\n\"Kłębi się w sennych marach,\\n\"\n\"W Sal ślepców korytarzach.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Zbrojownie Piekła stały się domem Marszałka Krwi. Gdziekolwiek przejdzie, \"\n\"pozostawia za sobą tysiące okaleczonych ciał. Mordował zarówno aniołów, jak \"\n\"i ludzi. Składa niekończące się ofiary Panom Ciemności, pragnącym tylko \"\n\"jednego. Krwi...\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Daj świadectwo prawdom tu zapisanym, gdyż są one ostatnim dziedzictwem \"\n\"horadrimów. Poza naszym ojczystym światem trwa wojna pomiędzy utopijnym \"\n\"Królestwem Niebios i pogrążonymi w chaosie Płonącymi Piekłami. Wojnę tę \"\n\"nazywa się Wielkim Konfliktem. Zaczęła się jeszcze przed powstaniem gwiazd \"\n\"na niebie. Siły światła i ciemności nieustannie walczą w niej o przejęcie \"\n\"kontroli nad wszelkim stworzeniem, lecz żadna ze stron nigdy nie uzyskała \"\n\"znaczącej przewagi.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Daj świadectwo prawdom tu zapisanym, gdyż są one ostatnim dziedzictwem \"\n\"horadrimów. Kiedy Odwieczny Konflikt pomiędzy Królestwem Niebios i Płonącymi \"\n\"Piekłami przeniósł się do świata śmiertelników, nazwano go Wojną Grzechu. \"\n\"Anioły i demony zaczęły krążyć pomiędzy ludźmi w ukryciu, walcząc pod inną \"\n\"postacią. Kilku potężniejszym śmiałkom udało się sprzymierzyć ze stronami \"\n\"konfliktu i wpłynąć na przebieg Wojny Grzechu.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Daj świadectwo prawdom tu zapisanym, gdyż są one ostatnim dziedzictwem \"\n\"horadrimów. Około trzystu lat temu, dowiedzieliśmy się, że nasz świat \"\n\"nawiedziła Mroczna Trójca z Płonących Piekieł.Trzej bracia zapanowali na \"\n\"dekady nad ziemiami Wschodu, a miejscowa ludność żyła tam w panicznym \"\n\"strachu. Nasz zakon - horadrimowie - został stworzony przez tajemną grupę \"\n\"magów, by odnaleźć i raz na zawsze pojmać Trójcę Zła.\\n\"\n\" \\n\"\n\"Dawni Horadrimowie schwytali dwóch \\n\"\n\"z Trójcy za pomocą potężnych artefaktów znanych jako Kamienie Dusz\\n\"\n\"i zakopali je głęboko pod piaskami wschodnich pustkowi.\\n\"\n\"Trzeci Zły zdołał uciec na zachód. Wtedy podążył za nim nasz zakon. \\n\"\n\"Trzeci Zły - znany jako Diablo, Pan Grozy - został ostatecznie schwytany, a \"\n\"jego esencja została umieszczona w Kamieniu Dusz i ukryta w tym Labiryncie.\\n\"\n\"\\n\"\n\"Strzeż się, Kamień Dusz musi być trzymany z dala od niepowołanych. Gdyby \"\n\"Diablo zdołał się z niego wydostać, próbowałby przejąć ciało, którym mógłby \"\n\"z łatwością zawładnąć. Najlepszym celem dla osłabionego demona byłoby \"\n\"dziecko lub starzec.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Dokonało się. W Płonących Piekłach nastał czas wielkiej rewolucji, nazywanej \"\n\"Mrocznym Wygnaniem. Pomniejsze Zła obaliły Wielką Trójcę i wygnały ich dusze \"\n\"do krainy śmiertelników. Podczas nieobecności trzech braci, demony Belial, \"\n\"Pan Kłamstwa, i Azmodan, Pan Grzechu, zaczęły walczyć o władzę. Cała kraina \"\n\"podzieliła się na wyznawców Beliala i Azmodana, a siły Niebios nieustannie \"\n\"próbowały rozbić Wrota Piekieł.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Wiele demonów przybyło do krainy śmiertelników w poszukiwaniu Trzech Braci. \"\n\"Ich poczynania na ziemi śledziły anioły, które rozpoczęły polowania na nie w \"\n\"wielkich miastach Wschodu. Anioły sprzymierzyły się ze śmiertelnikami i \"\n\"zawarły pakt z tajemniczym zakonem horadrimów. Jego członkowie szybko stali \"\n\"się znakomitymi łowcami zła i błyskawicznie zdobyli w krainie podziemi wielu \"\n\"wrogów.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Dokonało się. Duchy Wielkiej Trójcy zostały wygnane do świata śmiertelników. \"\n\"Po trwającym dekady sianiu spustoszenia na Wschodzie, zostali wytropieni \"\n\"przez zakon śmiertelników. Horadrimowie użyli artefaktów nazywanych \"\n\"Kamieniami Dusz i umieścili w nich esencje Mefisto, Pana Nienawiści i jego \"\n\"brata Baala, Pana Zniszczenia. Najmłodszy brat, Diablo - Pan Grozy, uciekł \"\n\"na zachód.\\n\"\n\" \\n\"\n\"Ostatecznie Horadrimowie schwytali do Kamienia Dusz również Diablo, a \"\n\"następnie ukryli go pod starożytną, zapomnianą katedrą. Tam oto Pan Grozy \"\n\"pozostaje uśpiony i oczekuje na przebudzenie. Wiedzcie o tym, że potrzebuje \"\n\"młodego i energicznego ciała, naiwnej osoby, którą łatwo będzie opętać. \"\n\"Odrodzi się wtedy, by uwolnić swych Braci i ponownie wzniecić ogień Wojny \"\n\"Grzechu...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Chwała Diablo - Panu Grozy, który przetrwał Mroczne Wygnanie. Mój Pan i \"\n\"Mistrz przebudził się wreszcie z głębokiego snu. Wyjawił mi sekrety znane \"\n\"niewielu śmiertelnikom. Opowiedział mi o Królestwie Niebios i Płonących \"\n\"Piekłach, ścierających się w odwiecznej wojnie. Pokazał moce, które \"\n\"sprowadziły ten konflikt do krainy ludzi, a samą walkę za ten świat i każde \"\n\"jego istnienie nazwał Wojną Grzechu.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Chwała i uwielbienie dla Diablo - Pana Grozy, który przewodzi całej Trójcy. \"\n\"Mój Pan opowiadał mi o swych dwóch braciach, Mefisto i Baalu, z którymi \"\n\"dawno temu został wygnany do naszego świata. Czeka teraz na odpowiedni \"\n\"moment, by wykorzystać swą niesamowitą moc do uwolnienia pojmanych braci, \"\n\"znajdujących się w grobowcach pod piaskami Wschodu. Kiedy mój Pan oswobodzi \"\n\"swych braci, Wojna Grzechu jeszcze raz zazna gniewu Trójcy.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Oddajcie cześć i pokłon Diablo - Panu Grozy i niszczycielowi dusz. Kiedy \"\n\"przebudziłem mego mistrza, spróbował opętać śmiertelnika. Diablo chciał \"\n\"posiąść ciało Króla Leoryka, jednak był jeszcze zbyt słaby. Potrzebował \"\n\"ofiary słabszej i naiwniejszej, by powrócić w pełni do tego świata. Uznał \"\n\"chłopca, Albrechta, za idealny cel. Podczas gdy Król Leoryk tracił zmysły po \"\n\"nieudanej próbie opętania, ja porwałem jego syna Albrechta i zaprowadziłem \"\n\"go przed mojego Mistrza. Teraz oczekuję rozkazu od Diablo i modlę się o to, \"\n\"by zostać nagrodzonym kiedy zostanie Panem tego świata.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Dobrze znów cię widzieć!\\n\"\n\"Dużo się zmieniło od czasu twojej ostatniej wizyty. Żyliśmy tu spokojnie, do \"\n\"momentu, w którym przybyły te diabelskie stworzenia i zniszczyły naszą \"\n\"wioskę. Wielu zginęło na miejscu. Tych co chwycili za broń zabito albo \"\n\"porwano na niewolników - jak nie gorzej. Kościół na skraju miasta \"\n\"zbezczeszczono i służy teraz mrocznym rytuałom. Nocami po osadzie roznoszą \"\n\"się nieludzkie krzyki. Mimo to wciąż mamy nadzieję, że część naszych ludzi \"\n\"przeżyła. Udaj się ścieżką wiodącą między gospodą a kuźnią, tam znajdziesz \"\n\"katedrę. Uratuj kogo tylko zdołasz. \\n\"\n\" \\n\"\n\"Więcej opowiem ci przy następnym spotkaniu. Powodzenia.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Pamiętaj o tym zadaniu.  Znalezienie utraconego skarbu nie jest proste.  Tym \"\n\"bardziej znalezienie skarbu, który został ukryty.  Nie pozwól, aby \"\n\"upływający czas wpłynął na twoje poszukiwania.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Co?  To bzdura.  Pod Tristram nie ma ukrytych skarbów.  Pokaż mi to! Ach, \"\n\"spójrz, te rysunki nie pasują do naszego miasta.  Na twoim miejscu skupiłbym \"\n\"się nad tym co jest pod katedrą, a nie na tej mapie.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Nie mam czasu na przeglądanie map.  Wielu ludzi potrzebuje teraz mojej \"\n\"pomocy, twojej zresztą też.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"Usunięty quest.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Założę się, że to Wirt robi sobie z ciebie żarty.  Pewnie pęknie ze śmiechu, \"\n\"gdy się dowie, jak pytasz wszystkich o te bazgroły, które ci podrzucił. Ja \"\n\"bym sobie dał z tym spokój.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Kiedyś często zatrzymywali się tu podróżni z dalekich stron, jednak wiele \"\n\"się od tego czasu zmieniło. Ale dzieci często fantazjują o ukrytych \"\n\"jaskiniach i zakopanych skarbach. Choć Wirt rzadko daje się ponieść \"\n\"młodzieńczym zabawom, to nadal możliwe, że to tylko jego wymysł.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Cho... Chono tu.  Słuchaj.  Nie wiem czy ty to widzisz, ale tu jest coś \"\n\"narysowane.  To mapa.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Moja babcia często opowiadała mi historie o dziwnych mocach zamieszkujących \"\n\"cmentarz przed kościołem. Opowiem ci jedną z nich. Mówiła, że jeżeli na \"\n\"cmentarzu złoży się właściwą ofiarę, pójdzie do katedry, pomodli się za \"\n\"zmarłego i wróci, złożona ofiara zostanie w tajemniczy sposób przyjęta. Nie \"\n\"wiem czy to tylko gadanie starej schorowanej kobiety, ale teraz wszystko \"\n\"jest możliwe.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Ogromny i tajemniczy skarb, powiadasz?  Może nawet coś bym od ciebie \"\n\"kupił... a nie potrzebujesz może jakiegoś unikalnego i drogiego wyposażenia \"\n\"żeby go zdobyć?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Hej, to chyba o tobie wszyscy wkoło gadają.  Pomożesz biednemu, prostemu \"\n\"farmerowi?  Na skraju mojego gospodarstwa, na południe stąd, z ziemi \"\n\"wypełzło jakieś paskudztwo!  Blokuje mi drogę do upraw i stogów siana, przez \"\n\"co moje krowy zaczynają głodować.  Wiedźma dała mi to coś, żeby wysadzić \"\n\"tamto szkaradztwo w powietrze.  Jeśli mnie wyręczysz, będę ci dozgonnie \"\n\"wdzięczny.  Sam nie dam rady, bo wiesz, ktoś musi pilnować krów...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Wiedziałem, że to nie może być takie proste, jak mówiła wiedźma.  To smutne, \"\n\"że w dzisiejszych czasach nie można ufać już nawet własnym sąsiadom.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Już po wszystkim?  Czy to coś wróciło już do ciemnych otchłani Hadesu, z \"\n\"których przyszło?  Co?!  No nie mów mi, że gdzieś ci się zgubił ładunek!  To \"\n\"nie była tania rzecz.  Musisz go teraz znaleźć.  Inaczej nie pozbędziesz się \"\n\"tego paskudztwa z naszego miasta.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Eksplozję było słychać aż tutaj!  Wielkie dzięki.  Nastały trudne czasy - \"\n\"najpierw te potwory w katedrze, teraz to coś wypełzające z ziemi. Wiesz, \"\n\"może i jestem biednym farmerem, ale potrafię docenić czyjś trud - weź to w \"\n\"podzięce.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Och, mam kłopot... może... Nie, nie, nie... Masz wystarczająco dużo \"\n\"problemów. Ale jeśli możesz to odwiedź mnie, kiedy już oczyścisz kościół z \"\n\"tych kreatur... Znajdziesz wtedy trochę czasu dla biednego farmera, co?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Buuu!  Buuu!\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Zgubiłam Teosia!  To mój najlepszy przyjaciel!  Bawiliśmy się przy rzece, i \"\n\"Teoś powiedział, że idziemy zobaczyć to duże zielone coś.  Mówiłam, że \"\n\"lepiej nie, ale był uparty i poszliśmy.  Nagle wypełzł wielki ROBAL!  \"\n\"Zaczęliśmy uciekać, ale Teoś upadł i to coś go PORWAłO!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Masz go?  Znajdź Teodora, proszę!  Jest taki malutki.  Nie poradzi sobie \"\n\"sam!  Proszę!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Masz go!  Jest bezpieczny!  Dziękuję ci!  Och Teosiu, czy te paskudne robale \"\n\"cię wystraszyły?  Co to?  Blee!  Coś przyczepiło ci się do futerka!  Fuj!  \"\n\"Chodź Teosiu, wracamy do domu!  A tobie jeszcze raz dziękuję!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Przez lata byliśmy pogrążeni w głębokim śnie, ale nadszedł moment \"\n\"przebudzenia.  Po tak długim spoczynku czujemy potworny głód.  Już wkrótce \"\n\"ruszymy na łowy...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"Usunięta kwestia.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Wasza kraina zostanie sprofanowana, a nasza rasa opanuje ziemię, która jest \"\n\"waszym domem.  Nasze macki obejmą cały świat i będziemy ucztować na zwłokach \"\n\"jego mieszkańców.  Ludzie staną się naszymi orędownikami i pożywieniem.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"Usunięta kwestia.\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"I tak, w roku Złotej światłości, podjęto decyzję o wzniesieniu wielkiej \"\n\"Katedry. Kamieniem węgielnym tego świętego miejsca była półprzezroczysta \"\n\"skała, Antyrael, nazwana tak na cześć Anioła, który podzielił się swą wiedzą \"\n\"z horadrimami. \\n\"\n\" \\n\"\n\"W roku Zwodniczych Cieni nastąpiło trzęsienie ziemi, przez które Katedra \"\n\"popadła w ruinę. Gdy budowano katakumby i zamki, a ludzkość walczyła ze \"\n\"spustoszeniem wywołanym przez Wojnę Grzechu, z ruin wygrzebano cenną skałę. \"\n\"Tak właśnie zniknął kamień węgielny. \\n\"\n\" \\n\"\n\"Kamień był jednocześnie z tego świata i ze wszystkich światów. Tak jak \"\n\"światłość jest jednocześnie wewnątrz wszystkiego i ponad wszystkim. \"\n\"Światłość i jedność są świętą podstawą: jedność celu i jedność dziedzictwa.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"No, muu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Słuchaj, jestem krową, kapujesz?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Dobra, dobra.  To tylko przebranie.  Normalnie się tak nie ubieram, ale \"\n\"siedziałem w domu i rozmyślałem nad swoim życiem, gdy nagle te robale, \"\n\"pnącza i inne świństwa zaczęły wypełzać spod podłogi... to było okropne! \"\n\"Szkoda, że nie miałem pod ręką innego ubrania, nie wyglądałbym jak skończony \"\n\"wariat. Hej!  Może wpadniesz do mnie do domu i przyniesiesz mój garniak? Ten \"\n\"brązowy, bo szary jest na wyjścia wieczorowe.  Zrobiłbym to sam, ale nie \"\n\"chcę, żeby ktoś widział mnie w tym przebraniu. Weź to, może się przydać \"\n\"do... przedarcia się przez te wszystkie przerosty.  Ciężko nie zauważyć \"\n\"mojego domu, jest na południu, przy rozwidleniu rzeki... wiesz... taki z \"\n\"przerośniętym ogródkiem.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Na co ty czekasz?  Leć po mój garniak!  Szybko!  Tamten byczek dziwnie się \"\n\"już na mnie patrzy!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hej, masz moje ubranie?  Streszczaj się!  Te uszy tak swędzą, że już nie \"\n\"wytrzymie!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Nie, nie, nie, nie!  Ten strój jest SZARY!  Jest na wyjścia wieczorowe!  Na \"\n\"ważne spotkania!  Nie mogę GO teraz założyć.  Padło ci na mózg?  Przecież \"\n\"mówiłem, że ma być BRĄZOWY.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Aaach, o wiele lepiej.  Wreszcie mogę poczuć się jak poważny człowiek!  Czy \"\n\"rogi są prosto?  świetnie. No, dzięki za pomoc.  Mam dla ciebie prezent... \"\n\"łap; dam ci też małą radę dotyczącą ubioru, no wiesz... twojej stylówki... \"\n\"możesz założyć coś trochę... albo kupić nowe... wiesz o co chodzi? Ten cały \"\n\"motyw poszukiwacza przygód jest trochę... zbyt retro. Taka mała rada, hm?  \"\n\"Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Słuchaj, jestem krową, a ty zwykłą przynętą na potwory.  Nabierz trochę \"\n\"doświadczenia, to pogadamy...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Zadanie, które ci powierzyłem, nie jest łatwe.  Jeśli mógłbym jakoś... co \"\n\"powiesz na dzbanek pysznego, świeżutkiego mleka?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Och, skorzystałbym z twojej pomocy, ale najpierw musisz oczyścić katakumby z \"\n\"bestii, które je splugawiły.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Mam kłopot, ale nie mogę polegać na kimś zupełnie obcym.  Odwiedź mnie, jak \"\n\"nabierzesz doświadczenia.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Widzę w tobie ogromny potencjał.  Mógłbym poprosić cię o przysługę, kiedy \"\n\"już wypełnisz swoje przeznaczenie?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Musisz mieć więcej siły.  Nie chcę, żeby ci się stała krzywda, bo nikt poza \"\n\"tobą nie będzie w stanie oczyścić katedry!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Jestem samozwańczą krową.  Ogarnij się, bo póki co nie dorastasz mi do... \"\n\"kopyt.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Nie będę tłumaczył się wszystkim przyjezdnym!  Nie masz przypadkiem jakichś \"\n\"potworów do zabicia?  Wyjaśnię ci to później.  O ile przeżyjesz...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Przestań mnie dręczyć.  Szukam kogoś naprawdę walecznego.  Ty nie dasz \"\n\"rady.  Nie powierzę ci zadania, bo te potwory w moment cię zeżrą... Musisz \"\n\"nabrać doświadczenia.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Dobra, dobra.  To tylko przebranie.  Normalnie się tak nie ubieram, ale \"\n\"siedziałem w domu i rozmyślałem nad swoim życiem, gdy nagle te robale, \"\n\"pnącza i inne świństwa zaczęły wypełzać spod podłogi... to było okropne! \"\n\"Szkoda, że nie miałem pod ręką innego ubrania, nie wyglądałbym jak skończony \"\n\"wariat. Hej!  Może wpadniesz do mnie do domu i przyniesiesz mój garniak? Ten \"\n\"brązowy, bo szary jest na wyjścia wieczorowe.  Zrobiłbym to sam, ale nie \"\n\"chcę, żeby ktoś widział mnie w tym przebraniu. Weź to, może się przydać \"\n\"do... przedarcia się przez te wszystkie przerosty. Ciężko nie zauważyć \"\n\"mojego domu, jest na południu, przy rozwidleniu rzeki... wiesz... taki z \"\n\"przerośniętym ogródkiem.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Zaklęcia, groźby czy negocjacje zdają się nie mieć sensu.  Wszystkie moje \"\n\"sposoby zniewalania słabszych demonów nie działają na tę przerażającą bestię.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Mój dom ogarnia skażenie spowodowane zepsuciem niechcianego więźnia.  Krypty \"\n\"pełne są cieni czających się na krawędzi wzroku. Piskliwy dźwięk drapania \"\n\"małych kreatur doprowadza mnie już do szaleństwa. Prawdopodobnie szukają \"\n\"mego dziennika.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"W swych tyradach potwór zdradził swe imię... Na-Krul.  Chciałem znaleźć \"\n\"informacje na jego temat, ale demony zniszczyły moją bibliotekę. Na-Krul... \"\n\"sam dźwięk tego imienia przeszywa mnie zimnym dreszczem. Nawet w myślach \"\n\"boję się je powtarzać. Wolę mówić na niego... Potwór.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Uwięziony potwór jest tak rozwścieczony, że przez jego wycie nie mogę zaznać \"\n\"niezbędnego mi teraz snu. Przeklina mnie za zesłanie go do Otchłani. Jego \"\n\"słowa wypełniają moje serce strachem, lecz ani na chwilę nie potrafię \"\n\"zagłuszyć tego dźwięku.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Mój czas już się kończy.  Muszę spisać sposoby na osłabienie demona i ukryć \"\n\"te teksty przed sługami, które mogą chcieć uwolnić swego Pana.  Mam \"\n\"nadzieję, że ten kto odnajdzie dziennik, wykorzysta mą wiedzę.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Ktokolwiek czyta ten zwój, musi powstrzymać demoniczną kreaturę znajdującą \"\n\"się za tamtymi murami. Mój czas się skończył.  Nawet teraz jego upiorne \"\n\"sługi próbują przebić spróchniałe drzwi, za którymi się skryłem. \\n\"\n\" \\n\"\n\"Dzięki tajemnej magii unieruchomiłem, a następnie uwięziłem demona za \"\n\"grubymi murami.  Jednak boję się, że to za mało. \\n\"\n\" \\n\"\n\"Zaklęcia spisane w mych trzech księgach zapewnią ci bezpieczne przejście do \"\n\"jego komnaty, ale tylko rzucone w odpowiedniej kolejności. Dźwignie w \"\n\"przedsionku zniosą bariery i uwolnią demona; nie dotykaj ich! Wystarczy, że \"\n\"użyjesz tamtych trzech zaklęć. W przeciwnym razie jego moc może okazać się \"\n\"zbyt potężna, by pozwolić ci na zwycięstwo.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Piekielny Dzik\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Kąsacz\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Wizjoner\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Pajęczysko\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Wtórnie Upadły\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Pomiot Przeżartucha\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Ogon Jadu\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Nekrokula\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Pajęczy Władca\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Okaleczony Robak\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Zapaleniec\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Piekielny Robak\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Grabarz\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Grobowy Szczur\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Ognisty Nietoperz\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Skrzydlata Czaszka\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lisz\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Demon Krypty\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Piekielny Nietoperz\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Kościany Demon\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Arcylisz\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Dwugłowiec\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Padliniec\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Żniwiarz\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Pierścień Olbrzyma\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Pierścień Merkurego\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Pierścień Xorina\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Pierścień Karika\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Pierścień Magmy\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Pierścień Mistyków\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Pierścień Burzy\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Amulet Ochrony\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Ukąszenie Komara\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Żarliwiec\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Zbroja Posępności\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Przebłysk\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Uderzenie Pioruna\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Pożeracz Dusz\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Diamentowe Ostrze\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Kościana Kolczuga\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Łuska Demona\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Amulet Akolity\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Pierścień Gladiatora\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Błazeński\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Kryształowy\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Rozdwojony\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"destrukcji\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"rozkładu\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"zagrożenia\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Mądrości\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Ironii\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Ściana Błyskawic\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Podpalenie\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Przejście\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Odbicie\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Szał Bojowy\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Pierścień Ognia\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Przeszukiwanie\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Runa Ognia\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Runa Światła\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Runa Novy\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Runa Podpalenia\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Runa Kamienia\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Zmniejsz jasność\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Zwiększ jasność\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Kontynuuj rozgrywkę\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Próbujesz upuścić przedmiot leżący na ziemi?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Wymusza oczekiwanie na synchronizację pionową. Zapobiega efektowi \"\n#~ \"rozrywania podczas rysowania klatki. Wyłączenie tej funkcji może pomóc w \"\n#~ \"eliminacji opóźnień myszy w niektórych systemach.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Ogranicznik FPS\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Liczba FPS jest ograniczona, aby uniknąć dużego obciążenia procesora. \"\n#~ \"Ograniczenie uwzględnia częstotliwość odświeżania.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"\"\n#~ \"Celność\\n\"\n#~ \"ataku\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Serce\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Niezniszczalność,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Brak wymagań atrybutów\"\n"
  },
  {
    "path": "Translations/pt_BR.po",
    "content": "# Translation of DevilutionX to Portuguese (Brazil)\n# Cyro Dubeux <xorycx@gmail.com>, 2021.\n# Altieres Lima da Silva <altieres.lima@gmail.com>, 2021.\n# @yuripourre, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:20+0200\\n\"\n\"PO-Revision-Date: 2025-10-02 15:21+0200\\n\"\n\"Last-Translator: Altieres Lima da Silva <altieres.lima@gmail.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: pt_BR\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Design do Jogo\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Designers Sêniores\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Design Adicional\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Programador Líder\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Programadores Sêniores\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programação\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Programadores Convidados Especiais\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Programação Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Programação de Comunicação Serial\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Programação do Instalador\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Diretores de Arte\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Arte\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Arte Técnica\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Diretores de Arte Cinematográfica\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"Arte Cinematográfica 3D\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Arte Técnica Cinematográfica\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Produtor Executivo\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Produtor\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Produtor Associado\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Equipe Strike Team Diablo\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Música\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Design de Som\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Música Cinematográfica e Som\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Produção de Voz, Direção e Elenco\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Roteiro e História\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Edição de voz\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Vozes\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Engenheiro de Gravação\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Design e Layout do Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Arte do Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Diretor provisório do Controle de Qualidade (Testador Líder)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Equipe de Assalto do Controle de Qualidade (Testadores)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"\"\n\"Forças Especiais do Controle de Qualidade (Testadores de Compatibilidade)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"\"\n\"Suporte de Artilharia do Controle de Qualidade (Testadores Adicionais) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Contrainteligência do Controle de Qualidade\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Ordem dos Serviços de Informações de Rede\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Suporte ao Cliente\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Vendas\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Vocalistas de Apoio do Senhor Dabiri\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Relações Públicas\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marketing\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Vendas Internacionais\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Vendas EUA\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Produção\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Jurídico & Negócios\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Agradecimentos especiais para\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Agradecimentos a\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Em memória de\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Agradecimentos muito especiais a\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Gerente Geral\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Engenharia de Software\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Diretores de Arte\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Artistas\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Projeto\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Projeto de Som, Efeitos Sonoros & Engenharia de Áudio\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Líder do Controle de Qualidade\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testadores\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tArte Adicional\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Escritor dos Textos das Missões\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Agradecimentos a\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tAgradecimentos Especiais à Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Gerente do Controle de Qualidade\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Líder de Teste do Controle de Qualidade\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Testadores Principais\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Testadores Adicionais\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Gerente de Marketing de Produto\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Gerente de Relações Públicas\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Gerente de Produto Associado\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"O Anel dos Mil\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tNenhuma alma foi vendida na criação deste jogo.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Escolha uma Classe\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Cancelar\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Novo Herói Multijogador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Novo Herói\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Jogo Salvo Existente\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Carregar Jogo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Novo Jogo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Personagens\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"A Ladina e o Feiticeiro estão disponíveis apenas na versão comercial \"\n\"completa do Diablo. Visite https://www.gog.com/game/diablo para comprar.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Inserir nome\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Nome inválido. Um nome não pode conter espaços, caracteres reservados ou \"\n\"palavras.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Não foi possível criar o personagem.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Nível:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Força:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magia:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Destreza:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalidade:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Jogo Salvo:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Selecione um Herói\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Novo herói\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Apagar\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Personagens Multijogador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Apagar Herói Multijogador\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Apagar Herói\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Tem certeza de que deseja apagar o personagem \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Um Jogador\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Multijogador\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Configurações\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Suporte\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Exibir Créditos\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Sair do Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Sair do Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Cliente-Servidor (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Offline\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Jogo Multijogador\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Requisitos:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"sem gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Selecione uma conexão\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Mudar Gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"\"\n\"Todos os computadores devem estar conectados a uma rede compatível com TCP.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Todos os computadores devem estar conectados à internet.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Jogue sozinho sem exposição na rede.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Jogadores Suport.: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"O anfitrião está executando um jogo diferente de você.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"O anfitrião está executando o modo de jogo ({:s}) diferente de você.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Sua versão {:s} não corresponde com a do anfitrião {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Descrição:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Selecionar Ação\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Criar jogo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Criar Jogo Público\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Entrar no jogo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Jogos Públicos\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Carregando...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Nenhum\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"CANCELAR\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Crie um novo jogo com uma dificuldade de sua escolha.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Crie um novo jogo público aberto a qualquer pessoa com uma dificuldade de \"\n\"sua escolha.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Insira o ID do Jogo para entrar em um jogo já em andamento.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Insira um IP ou nome do servidor e entre em um jogo já em andamento.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Entrar em um jogo público já em andamento.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Pesadelo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Inferno\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Dificuldade: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Velocidade: Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Velocidade: Rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Velocidade: Muito rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Velocidade: Super rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Jogadores: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Dificuldade\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Entrar em jogos {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Insira ID do Jogo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Inserir endereço\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Dificuldade Normal\\n\"\n\"É aqui que um personagem inicial deve começar a jornada para derrotar Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Dificuldade Pesadelo\\n\"\n\"Os habitantes do Labirinto foram reforçados e provarão ser um grande \"\n\"desafio. Recomendado apenas para personagens experientes.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Dificuldade Inferno\\n\"\n\"As mais poderosas criaturas do submundo se escondem na porta de entrada do \"\n\"Inferno. Somente os personagens mais experientes devem se aventurar nesse \"\n\"reino.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Seu personagem deve atingir o nível 20 antes de poder entrar em um jogo \"\n\"multijogador na dificuldade Pesadelo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Seu personagem deve atingir o nível 30 antes de poder entrar em um jogo \"\n\"multijogador na dificuldade Inferno.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Velocidade do jogo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Muito Rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Super Rápido\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Velocidade: Normal\\n\"\n\"É aqui que um personagem iniciante deve começar a jornada para derrotar \"\n\"Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Velocidade: Rápido\\n\"\n\"Os habitantes do Labirinto foram acelerados e provarão ser um desafio maior. \"\n\"Isso é recomendado apenas para personagens experientes.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Velocidade: Muito Rápido\\n\"\n\"A maioria dos monstros da masmorra irão procurá-lo mais rápido do que nunca. \"\n\"Apenas um campeão experiente deve tentar a sorte nesta velocidade.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Velocidade: Super Rápido\\n\"\n\"Os asseclas do submundo correrão para atacar sem hesitação. Apenas um \"\n\"verdadeiro demônio da velocidade deve entrar neste ritmo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Inserir senha\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Entrar no Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Mudar para Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Sim\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Não\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Pressione qualquer botão do controle para alterar.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Tecla Associada:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Pressione qualquer tecla para mudar.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Desassociar tecla\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Combinação de botões associada:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Remover combo de botões\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Menu anterior\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Nós mantemos um servidor de chat em Discord.gg/devilutionx Clique nos links \"\n\"para se juntar a comunidade onde nós conversamos sobre assuntos relacionados \"\n\"ao Diablo, e a expansão Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX é mantido por Diasurgical, problemas e erros podem ser \"\n\"reportados neste endereço: https://github.com/diasurgical/devilutionX Para \"\n\"nos ajudar a melhor atendê-lo, certifique-se de incluir o número da versão, \"\n\"sistema operacional e a natureza do problema.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Aviso legal:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX não é suportado nem mantido pela Blizzard Entertainment, nem \"\n\"GOG.com. Nem Blizzard Entertainment ou GOG.com testaram ou certificaram a \"\n\"qualidade ou compatibilidade de DevilutionX. Todas as questões com respeito \"\n\"a DevilutionX devem ser dirigidas a Diasurgical, não a Blizzard \"\n\"Entertainment ou GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tEste port faz uso das fontes Charis SIL, New Athena Unicode, Unifont, e \"\n\"Noto que são licenciadas sob a SIL Open Font License, e também a fonte \"\n\"Twitmoji que é licenciada sob CC-BY 4.0. O port também faz uso da SDL, a \"\n\"qual é licenciada sob a zlib-license. Leia o ReadMe para mais detalhes.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Erro\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"O erro ocorreu em: {:s} linha {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Erro de arquivo de dados\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Não foi possível abrir o arquivo de dados principal ({:s}).\\n\"\n\"\\n\"\n\"Certifique-se de que ele esteja na pasta do jogo.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Erro de diretório, somente leitura\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Não foi possível gravar no local:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Jogo: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Partida Offline\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Senha: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Jogo Público\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Nível: Enxame {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Nível: Cripta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Cidade\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Nível: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Informações do personagem\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Registro de missões\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Automapa\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Menu Principal\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventário\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Livro de feitiços\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Enviar Mensagem\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Comandos Disponíveis:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Comando \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" é desconhecido.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Descrição: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parâmetros: Nenhum parâmetro adicional é necessário.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parâmetros: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Arenas só estão disponíveis no modo multijogador.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Qual arena você quer visitar?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Número de arena inválido. Os números válidos são:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\"Para entrar em uma arena, você precisa estar na cidade ou em outra arena.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Inspeção só está disponível no modo multijogador.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Parar de inspecionar os jogadores.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Nenhum jogador encontrado com este nome\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Inspecionar jogador: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Exibe a visão geral da ajuda ou ajuda para um comando específico.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[comando]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Entrar em uma Arena PvP.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<número-da-arena>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Dá Poções de Arena.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<number>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Inspeciona atributos e equipamentos de outro jogador.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<nome do jogador>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Mostrar informações de seed do nível atual.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Amigável a jogadores\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Hostil a jogadores\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Tecla de atalho: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Selecionar feitiço atual\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Tecla de atalho: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"Habilidade de {:s}\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"Feitiço de {:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Nível do feitiço 0 - Inutilizável\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Nível do feitiço {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Pergaminho de {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} pergaminho\"\nmsgstr[1] \"{:d} pergaminhos\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Cajado de {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} carga\"\nmsgstr[1] \"{:d} cargas\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} peça de ouro\"\nmsgstr[1] \"{:s} peças de ouro\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Pré-requisitos não atendidos\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Nível: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Pontos de vida {:d} de {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Clique direito para usar\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Subiu de Nível\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Você tem {:s} peça de ouro. Quanto quer remover?\"\nmsgstr[1] \"Você tem {:s} peças de ouro. Quanto quer remover?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Portal da cidade\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"de {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal para\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"O Altar Profano\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"o nível 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Não é possível carregar o personagem\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Imprime esta mensagem e sai\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Imprime a versão e sai\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Especifique a pasta de diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Especifique a pasta dos arquivos salvos\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Especifique o local do diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Especifique o código do idioma (por exemplo, en ou pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Pular vídeos de abertura\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Exibir quadros por segundo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Habilitar relatório detalhado\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Grava um arquivo de demonstração\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Toca um arquivo de demonstração\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Desabilita todos os limites de frame durante a demonstração\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Seleção do jogo:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Forçar modo Shareware\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Forçar modo Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Forçar modo Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Opções do Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Reportar erros em https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\"Por favor, atualize devilutionx.mpq e fonts.mpq para a versão mais recente\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Falha ao carregar recursos de interface do usuário.\\n\"\n\"\\n\"\n\"Certifique-se de que o arquivo devilutionx.mpq esteja na pasta do jogo e de \"\n\"que esteja atualizado.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Por favor, atualize o fonts.mpq para a versão mais recente\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Tempo limite da rede excedido --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Aguardando jogadores --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Nenhuma ajuda disponível\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"enquanto estiver em lojas\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Item do Cinto {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Usar item do Cinto.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Feitiço rápido {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Tecla de atalho para habilidade ou feitiço.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Menu anterior\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Feitiço rápido {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Usar poção de vida\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Usar poção de vida do cinto.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Usar poção de mana\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Usar poção de mana do cinto.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Livro de Acesso Rápido\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Abrir livro de Acesso Rápido.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Salvamento rápido\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Salvar o jogo.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Carregamento rápido\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Carregar Jogo.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Sair do jogo\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Fechar o jogo.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Parar herói\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Para de andar e cancela ações pendentes.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Destacar Items\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Exibir/esconder items no chão.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Habilitar/desabilitar destaque de Items\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Exibir/esconder items no chão permanetemente.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Habilitar/desabilitar mapa\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Habilitar/desabilitar se mapa está visível.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Abrir tela de inventário.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Person.\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Abrir tela de Personagem.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Registro de Missões\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Abrir registro de missões.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Livro de Feitiços\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Abrir Livro de Feitiços.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Mensagem Rápida {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Usar Mensagem Rápida no chat.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Esconder Telas de Informação\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Esconder todas as telas de informação.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Zoom\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Zoom da Tela do Jogo.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Pausar Jogo\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Pausa o jogo.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pausar Jogo\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Aumentar o brilho da tela.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Reduzir o brilho da tela.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Aumentar o brilho da tela.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Aumentar o brilho da tela.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Ajuda\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Abrir Tela de Ajuda.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Captura de tela\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Captura a tela.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Informações do jogo\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Exibir informações do jogo.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Chat\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Exibe chat.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Inventário\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Ação primária\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Atacar monstros, conversar com os habitantes da cidade, tirar e colocar \"\n\"itens de inventário.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Ação secundária\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Abrir baús, interagir com portas, pegar itens.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Ação de feitiço\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Lança o feitiço ativo.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Cancelar ação\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Fechar os menus.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Mover pra cima\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Move personagem para cima.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Mover pra baixo\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Move personagem para baixo.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Mover pra esquerda\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Move personagem para esquerda.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Mover pra direita\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Move personagem para direita.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Ficar parado\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Segure para evitar que o personagem se mova.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Habilita/Desabilita ficar parado\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Habilita/Desabilita movimento do personagem.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Automapa\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Mover pra baixo\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Mover pra esquerda\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Move personagem para cima.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Mover pra direita\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Mover mouse pra cima\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Simula movimento do mouse para cima.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Mover mouse pra baixo\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Simula movimento do mouse para baixo.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Mover mouse pra esquerda\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Simula movimento do mouse para esquerda.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Mover mouse pra direita\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Simula movimento do mouse para direita.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Clique com botão esquerdo do mouse\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Simula clique com botão esquerdo do mouse.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Clique com botão direito do mouse\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Simula clique com botão direito do mouse.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Menu de feitiços do controle\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Segure para definir ou usar hotkeys de feitiços.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Navegação de menu do controle\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Segure para acessar o menu de navegação do controle.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Abrir/Fechar menu do jogo\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Abre o menu do jogo.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"Onda de Chamas\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Sem funções multijogador na demonstração\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Falha na criação de Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Indisponível na versão shareware\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Espaço insuficiente para salvar\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Pausa não permitida na cidade\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"É recomendado copiar para um disco rígido\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Problema de sincronia do modo multijogador\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Não é permitido pausar no modo multijogador\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Salvando...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Uns são enfraquecidos enquanto um se torna mais forte\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Nova força é forjada pela destruição\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Aqueles que defendem raramente atacam\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"A espada da justiça é veloz e afiada\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Enquanto o espírito é vigilante, o corpo prospera\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Os poderes da mana reorientados se renovam\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"O tempo não pode diminuir o poder do aço\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"A mágica nem sempre é o que parece ser\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"O que antes estava aberto, agora está fechado\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"A intensidade vem à custa de sabedoria\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"O poder arcano traz destruição\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Aquilo que não pode ser agarrado não pode ser ferido\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"O Rubro e Anil se tornam como o sol\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Conhecimento e sabedoria à custa de seu próprio eu\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Beba e refresque-se\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Aonde quer que você vá, lá está você\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"A energia vem à custa de sabedoria\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Riquezas abundam quando menos se espera\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Onde falha a avareza, a paciência é recompensada\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Abençoado por uma companhia benevolente!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"As mãos dos homens podem ser guiadas pelo destino\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"A força é intensificada pela fé celestial\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"A essência da vida flui de dentro\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"O caminho se faz claro quando visto de cima\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"A salvação vem à custa de sabedoria\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Mistérios são revelados à luz da razão\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Aqueles que são últimos ainda poderão ser primeiros\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"A generosidade traz suas próprias recompensas\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Você deve estar ao menos no nível 8 para usar isto.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Você deve estar ao menos no nível 13 para usar isto.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Você deve estar ao menos no nível 17 para usar isto.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Conhecimento arcano obtido!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Aquilo que não o mata...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Conhecimento é poder.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Doe e você receberá.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Um pouco de experiência é obtida através do toque.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Não há lugar como a nossa casa.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"A energia espiritual é restaurada.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Você se sente mais ágil.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Você se sente mais forte.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Você se sente mais sábio.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Você se sente revigorado.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Aquilo que puder ser quebrado, assim o será.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Catedral\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Catacumbas\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Cavernas\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Enxame\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Cripta\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Nvl {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"Dificuldade {}\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"No Menu\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Não foi possível se conectar\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"erro: 0 bytes lidos do servidor\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq ou spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Alguns arquivos MPQs do Hellfire estão faltando\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Nem todos os arquivos MPQs do Hellfire foram encontrados.\\n\"\n\"Por favor, copie todos os arquivos hf*.mpq.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Resolução\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Correr na Cidade\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Missão do Theo\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Missão da Vaca\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Pegar Ouro Automaticamente\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Pegar Elixir Automaticamente\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Pegar Óleo Automaticamente\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Pegar itens na Cidade automaticamente\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria Recupera Mana\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Auto Equipar Armas\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Auto Equipar Armadura\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Auto Equipar Elmos\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Auto Equipar Escudos\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Auto Equipar Jóias\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Randomizar Missões\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Exibir nome dos items\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Auto Abastecer Cinto\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Desabilitar Altares Destrutivos\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Pegar Poção de Cura\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Pegar Poção de Cura Completa\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Pegar Poção de Mana\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Pegar Poção de Mana Completa\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Pegar Poção de Rejuvenescimento\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Pegar Poção de Rejuvenecimento Completo\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Opções\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Salvar jogo\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Menu Principal\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Sair do jogo\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gama\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Veloc.\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Desativar música\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Som\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Desativar som\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pausa\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Atalhos de teclado:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Abrir tela de ajuda\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Mostrar menu principal\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Mostrar automapa\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Espaço: Ocultar todas as telas de informação\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Abrir livro de acesso rápido\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Abrir livro de feitiços\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Abrir tela de inventário\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Abrir tela de personagem\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Abrir registro de missões\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Reduzir o brilho da tela\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Aumentar o brilho da tela\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Zoom da tela do jogo\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Zoom do automapa\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Usar item do cinto\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Definir tecla de atalho para habilidade ou feitiço\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + botão esquerdo do mouse: Atacar sem se mover\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + clique esquerdo do mouse (na tela de personagem): Adicionar todos os \"\n\"pontos em um mesmo atributo estatística\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + clique esquerdo (no inventário): Mover item para cinto ou equipar/\"\n\"desequipar item\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + clique esquerdo (no cinto): Mover item para inventário\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Movimento:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Se mantiver pressionado o botão do mouse enquanto se move, o personagem \"\n\"continuará se movendo nesta direção.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Combate:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Mantendo pressionado a tecla shift e depois clicar com o botão esquerdo \"\n\"permite que o personagem ataque sem se mover.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Auto-mapa:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Para acessar ao auto-mapa, clique no botão 'MAPA' na barra de informação ou \"\n\"pressione 'TAB' no teclado. Aproximar e afastar o mapa é realizado com as \"\n\"teclas + ou -. Para percorrer o mapa são utilizadas as teclas de seta.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Recolher objetos:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Os itens utilizáveis que são de tamanho pequeno, como poções ou pergaminhos, \"\n\"são colocados automaticamente no seu 'cinto' localizado na parte superior da \"\n\"barra de interface. Quando se coloca um item no cinto, aparece um pequeno \"\n\"número nesse quadro. Os itens podem ser usados pressionando o número \"\n\"correspondente ou dando um clique direito no item.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Ouro:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Pode selecionar uma quantidade específica de ouro para colocar com um clique \"\n\"direito em uma pilha de ouro no seu inventário.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Habilidades e feitiços:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Pode acessa sua lista de habilidades e feitiços dando um clique esquerdo no \"\n\"botão 'FEITIÇOS' na barra da interface. Aqui são listados os feitiços \"\n\"memorizados e os disponíveis através de cajados. Ao clicar com o botão \"\n\"esquerdo no feitiço que deseja lançar, o feitiço será preparado. Você pode \"\n\"lançar um feitiço preparado simplesmente clicando com o botão direito na \"\n\"área de jogo.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Usando o Livro de Acesso Rápido para Feitiços:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Ao clicar com o botão esquerdo no botão 'feitiço preparado' será aberto o \"\n\"'Livro de acesso rápido' que lhe permite selecionar uma habilidade ou \"\n\"feitiço para uso imediato. Para usar uma habilidade ou um feitiço preparado, \"\n\"simplesmente clique com o botão direito na área de jogo principal.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + clique esquerdo em 'Selecionar feitiço atual' irá limpar o feitiço \"\n\"selecionado.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Configurando Teclas de Atalho para Feitiços:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Você pode designar até quatro teclas de atalho para habilidades, feitiços ou \"\n\"pergaminhos. Comece abrindo o 'livro de acesso rápido' como descrito na \"\n\"seção anterior. Pressione as teclas F5, F6, F7 ou F8 depois de destacar o \"\n\"feitiço que deseja designar.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Livros de Feitiços:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Ler mais de um livro aumenta seu conhecimento desse feitiço, o que lhe \"\n\"permite lançar o feitiço de maneira mais efetiva.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Ajuda do Hellfire Shareware\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Ajuda do Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Ajuda do Diablo Shareware\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Ajuda do Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Pressione ESC para encerrar ou setas direcionais para rolar.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Não foi possível criar a janela principal\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Não há espaço para o item\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Óleo da Precisão\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Óleo da maestria\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Óleo da Nitidez\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Óleo da morte\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Óleo de habilidade\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Óleo do ferreiro\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Óleo de fortitude\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Óleo de permanência\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Óleo de endurecimento\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Óleo de impermeabilidade\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"aumenta\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"chance de acerto\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"aumenta enormemente um\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"chance de acerto da arma\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"potencial de dano\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"aumenta enormemente\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"potencial de dano - não arcos\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"reduz atributo requerido\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"para usar armaduras ou armas\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"restaura 20% de um\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"durabilidade do item\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"aumenta\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"durabilidade atual e máxima\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"faz com que um item seja indestrutível\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"aumenta a classe de armadura\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"de armaduras e escudos\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"aumenta enormemente a armadura\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"classe de armaduras e escudos\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"coloca armadilha de fogo\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"coloca armadilha de relâmpagos\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"coloca armadilha de petrificação\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"restaura toda a vida\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"restaura alguma vida\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"restaura um pouco de mana\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"restaura toda a mana\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"aumenta força\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"aumenta magia\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"aumenta destreza\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"aumenta vitalidade\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"restaura um pouco de vida e mana\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"restaura toda a vida e mana\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(funciona apenas em arenas)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Clique direito para visualizar\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Clique direito para usar\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Clique direito para ler e então\\n\"\n\"clique esquerdo para golpear\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Clique direito para ler\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Ative para visualizar\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Abrir tela de inventário\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Ative para usar\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Selecione do livro de feitiços, então\\n\"\n\"lance o feitiço para ler\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Ative para ler\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} para visualizar\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} para usar\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Selecionar feitiço atual, \\n\"\n\"então {} para ler\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} para ler\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Nível: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Duplica a capacidade de ouro\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Requerido:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} For\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Des\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Livro de {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Orelha de {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"chance de acerto: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% de dano\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"acerto: {:+d}%, {:+d}% de dano\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% de armadura\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"classe de armadura: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Resistência a fogo: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Resistência a fogo: {:+d}% MÁX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Resistência a raios: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Resistência a raios: {:+d}% MÁX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Resistência à magia: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Resistência à magia: {:+d}% MÁX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Resistência a tudo: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Resistência a tudo: {:+d}% MÁX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"feitiços aumentam {:d} nível\"\nmsgstr[1] \"feitiços aumentam {:d} níveis\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"feitiços diminuem {:d} nível\"\nmsgstr[1] \"feitiços diminuem {:d} níveis\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"níveis de feitiço inalterados (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Cargas extra\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} carga\"\nmsgstr[1] \"{:d} {:s} cargas\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Dano do acerto de fogo: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Dano do acerto de fogo: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Dano do acerto de raios: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Dano do acerto de raios: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} para força\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} para magia\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} para destreza\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} para vitalidade\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} a todos os atributos\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} de dano dos inimigos\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Pontos de vida: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"alta durabilidade\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"durabilidade diminuída\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"indestrutível\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% de alcance de visão\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% de alcance de visão\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"várias flechas por disparo\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"dano das flechas de fogo: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"dano das flechas de fogo: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"dano das flechas de raios {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"dano das flechas de raios {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"dano das bolas de fogo: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"dano das bolas de fogo: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"atacante leva 1-3 de dano\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"usuário perde toda a mana\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"enfraquece armadilhas 50%\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"empurra alvo para trás\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% de dano vs. demônios\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Todas Resistências viram 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"acerto rouba 3% de mana\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"acerto rouba 5% de mana\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"acerto rouba 3% de vida\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"acerto rouba 5% de vida\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"danifica armadura do alvo\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"ataque breve\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"ataque rápido\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"ataque mais rápido\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"ataque muito rápido\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Outra habilidade (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"recupera rápido de ataque\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"rec. mais rápido de ataque\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"rec. muito rápida de atq.\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"bloqueio rápido\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"adiciona {:d} ponto de dano\"\nmsgstr[1] \"adiciona {:d} pontos de dano\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"dá flechas de vel. variada\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"dano de item incomum\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"durabilidade alterada\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"espada de uma mão\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"constantemente perde PV\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"rouba vida\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"força não requerida\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"dano de raio: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"dano de raio: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"raios carregados nos golpes\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"triplo dano ocasional\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"declínio de {:+d}% de dano\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x dano para monst, 1x a você\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Dano aleatório 0 - 600%\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"baixa dur, {:+d}% de dano\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"AC extra vs demônios\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"AC extra vs mortos vivos\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% de Mana foi para a Vida\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% de Mana foi para a Vida\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"dano: {:d}  Indestrutível\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"dano: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"dano: {:d}-{:d}  Indestrutível\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"dano: {:d}-{:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"armadura: {:d}  Indestrutível\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"armadura: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Cargas: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"item único\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Não identificado\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Covil do Rei Esqueleto\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Câmara de Ossos\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labirinto\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Reserv. de água envenenado\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Covil do Arcebispo Lázarus\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Arena da Igreja\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Arena do Inferno\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Arena do Ciclo da Vida\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Descer para as masmorras\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Descer para as catabumbas\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Descer para as cavernas\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Descer para o inferno\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Descer para a Colmeia\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Descer para a Cripta\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Subir para o nível {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Subir para a cidade\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Descer para o nível {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Descer para o Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Subir para o nível {:d} do Enxame\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Subir para o nível {:d} da Cripta\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Pedra angular do mundo\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Descer para o nível {:d} da Cripta\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Voltar ao Nível {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Não foi possível abrir o arquivo salvo\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Jogo salvo inválido\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"O jogador está em um nível somente Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Estado de jogo inválido\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Não é possível mostrar o menu principal\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Animal\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demônio\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Morto-vivo\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Tipo: {:s}  Mortos: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Total de mortos: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Pontos de vida: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Nenhuma resistência a magia\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Resiste a:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magia\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Fogo\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Raios\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Imune a:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Tipo: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Sem resistências\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Sem imunidades\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Algumas Resistências à Magia\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Algumas Imunidades à Magia\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Não foi possível abrir o arquivo para escrita.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} lançou um feitiço inválido.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} lançou um feitiço ilegal.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"O jogador '{:s}' (nível {:d}) acabou de entrar no jogo\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"O jogo terminou\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Não é possível obter dados do nível\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"O jogador '{:s}' acabou de sair do jogo\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"O jogador '{:s}' matou Diablo e saiu do jogo!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"O jogador '{:s}' caiu devido a tempo esgotado\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"O jogador '{:s}' (nível {:d}) já está no jogo\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Misterioso\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Escondido\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Melancólico\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"esquisito(a)\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Mágico\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"de pedra\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Religioso\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Encantado\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Taumatúrgico\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Fascinante\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Críptico\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Insólito\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Esquisito\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Divino\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"sagrado(a)\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Sagrado\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Espiritual\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Pavoroso\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Abandonado\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Assustador\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Quieto\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Isolado\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Ornado\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Vislumbrante\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Maculado\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Oleoso\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Brilhante\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Do Mendicante\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Espumante\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Cintilante\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Solar\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"De Murphy\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"O Grande Conflito\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"O Salário do Pecado é a Guerra\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"O Conto dos Horadrim\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"O Exílio Sombrio\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"A Guerra do Pecado\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"O Aprisionamento dos Três\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Os Reinos Além\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Conto dos Três\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"O Rei Negro\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Diário: O Enfeitiçado\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Diário: O Encontro\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Diário: A Desgraça\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Diário: Seu Poder Cresce\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Diário: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Diário: O Fim\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Um Livro de Feitiços\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Esqueleto Crucificado\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Alavanca\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Porta Aberta\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Porta Fechada\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Porta Bloqueada\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Tomo Antigo\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Livro da Vileza\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Alavanca de Caveira\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Livro Mítico\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Baú Pequeno\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Baú\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Baú Grande\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarcófago\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Estante de Livros\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Estante\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Barril\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Ovo\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"Altar {:s}\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Tomo do Esqueleto\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Livro da Biblioteca\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Fonte de Sangue\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Corpo Decapitado\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Livro dos Cegos\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Livro de Sangue\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Fonte Purificante\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Armadura\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Estante de Armas\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Altar Caprino\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Caldeirão\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Poça Turva\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Fonte de Lágrimas\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Tomo do Aço\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Pedestal de Sangue\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Canteiro de Cogumelos\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Suporte Vil\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Herói Assassinado\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} com armadilha\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (desativado)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"ATIVO\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"INATIVO\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Modo de Jogo\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Configurações de Gameplay\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Jogar Diablo ou Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Restringir ao Shareware\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Torna o jogo compatível com a demonstração. Habilita multiplayer com amigos \"\n\"que não possuem a versão completa do Diablo.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Inicialização\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Configurações de Inicialização\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Introdução\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Exibe vídeo de Introdução.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Tela de Abertura\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Tela de abertura exibida.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Tela com logo e título\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Tela do Título\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Configurações específicas do Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Configurações específicas do Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Áudio\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Configurações de Áudio\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Som dos Passos\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Jogador emite som ao caminhar.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Som ao Auto-Equipar\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\"Equipar os items automaticamente emite o som dos equipamentos ao pegá-los.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Som ao Pegar Item\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Emite o som dos equipamentos ao pegá-los.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Taxa de Amostragem\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Taxa de amostragem de saída (Hz)\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Canais\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Número de canais de saída.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Tamanho do Buffer\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Tamanho do Buffer (número de quadros por canal).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Qualidade de resampling\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Qualidade do resampler, de 0 (pior) to 10 (melhor).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Afeta a resolução interna do jogo e determina sua área de visão. Nota: Isso \"\n\"pode mudar para cada resolução de tela, quando usando Upscaling, Escala de \"\n\"Inteiros ou Ajustar à Tela.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Resampler\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Resampler de áudio\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Dispositivo\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Dipositivo de Áudio\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Gráficos\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Configurações de Gráficos\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Tela cheia\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Exibe o jogo em modo janela ou tela cheia.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Ajustar à Tela\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Ajusta automaticamente a janela do jogo mantendo a mesma proporção e \"\n\"resolução da tela de desktop atual.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Upscale\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Habilita escala de imagem da resolução do jogo para a resolução do seu \"\n\"monitor. Previne mudanças na resolução do monitor e permite redimensionar a \"\n\"janela.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Qualidade de Escala\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Habilita filtros opcionais para a image de saída quando utilizando upscaling.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Pixel mais Próximo\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilinear\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotrópico\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Escala de Inteiros\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Escala a imagem usando a proporção de pixel em número inteiro.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Sincronização Vertical\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Zoom quando habilitado.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Raios\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Ciclagem de Cores\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Efeito de Ciclagem de Cores usado para animação da água, lava e ácido.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Usa paleta alternativa no enxame\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"O jogo irá usar a paleta alternativa para o enxame do Hellfire.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Cursor em Hardware\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Usa um cursor em hardware\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Cursor em Hardware Para Items\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Usa um cursor em hardware para os items.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Tamanho máximo do Cursor em Hardware\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Largura / altura máxima para o cursor em hardware. Cursores maiores são \"\n\"convertidos para software.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Exibir FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Exibe o FPS no canto esquerdo superior da tela.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Gameplay\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Configurações de Gameplay\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Habilita correr/andar rápido na cidade no Diablo e Hellfire. Essa opção foi \"\n\"introduzida na expansão.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Travar Input\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Quando habilitado, mouse fica travado na janela do jogo.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Habilita missão da Garotinha.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"Habilitar missão do Jersey. Lester o fazendeiro é substituído pelo \"\n\"Completamente Louco.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Fogo Amigo\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Permite causar danos por flechas/feitiços entre jogadores no multiplayer \"\n\"mesmo quando o modo amistoso está habilitado.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Todas as quests no modo Multijogador\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Habilita a versão completa/sem cortes das missões de um jogador.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Teste Bardo\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\"Força a classe de personagem Bardo a aparecer no menu de seleção do herói.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Teste Bárbaro\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\"Força a classe de personagem Bárbaro a aparecer no menu de seleção do herói.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Barra de Experiência\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Barra de Experiência é adicionada à UI na parte inferior da tela.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Exibir Gráficos de Itens nas Lojas\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\"Exibir gráficos de itens à esquerda das descrições de itens nos menus das \"\n\"lojas.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Exibir valor de pontos de vida\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Exibe valor atual e máximo de pontos de vida no orbe da vida.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Exibir valor de mana\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Exibe valor atual e máximo de mana no orbe da mana.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Informações do personagem\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Barra de Vida do Inimigo\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Barra de Vida do Inimigo é exibida na parte superior da tela.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Ouro é pego automaticamente quando perto do jogador.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Elixires são pegos automaticamente quando perto do jogador.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Óleos são pegos automaticamente quando perto do jogador.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Itens são pegos automaticamente quando estiver na cidade.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria vai encher sua mana quando você visitar a loja dela.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Armas são equipadas automaticamente quando pegas ou compradas, se habilitado.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Armadura é equipada automaticamente se pega ou comprada, se habilitado.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Elmos são equipados automaticamente se pegos ou comprados, se habilitado.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Escudos são equipados automaticamente se pegos ou comprados, se habilitado.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Jóias são equipadas automaticamente quando pegas ou compradas, se habilitado.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Seleciona missões aleatóriamente para novos jogos.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Exibir Tipo de Monstro\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Quando o cursor estiver sobre o monstro, o seu tipo será exibido na caixa de \"\n\"descrição da UI.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Exibir nome dos items no chão quando habilitado.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Abastece cinto pelo inventário quando um item do cinto é consumido.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Quando habilitado, Caldeirões, Altares Fascinantes, Altares Caprinos, \"\n\"Altares Ornados e Altares Sagrados não podem ser clicadas e são marcados \"\n\"como desabilitados.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Lançamento Rápido\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Teclas de Atalho de feitiços lançam feitiços, ao invés de mudar o fetiço \"\n\"selecionado.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Número de poções de cura a serem pegas automaticamente.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Número de poções de cura completa a serem pegas automaticamente.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Número de poções de mana a serem pegas automaticamente.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Número de poções de mana completa a serem pegas automaticamente.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Número de poções de Rejuvenecimento a serem pegas automaticamente.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Número de poções de Rejuvenecimento Completo a serem pegas automaticamente.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Habilitar números flutuantes\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"Habilita números flutuantes ao ganhar XP / causar dano, etc.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Desligado\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Ângulos Aleatórios\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Somente Vertical\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Controle\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Configurações de Controle\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Rede\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Configurações de Rede\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chat\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Configurações de Chat\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Idioma\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Define qual idioma será usado no jogo.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Configurações de Idioma\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Mapeamento de Teclas\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Configurações de Mapeamento de Teclas\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Mapeamento de Teclas\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Configurações de Mapeamento de Teclas\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Configurações\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Nível\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Experiência\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Próximo nível\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Base\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Atual\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Força\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magia\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Destreza\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalidade\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Pontos a distribuir\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Ouro\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Armadura\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"chance de acerto\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Dano\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Vida\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Resist. à magia\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Resist. a fogo\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Resist. a raios\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"person.\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"missões\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"mapa\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menu\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"invent.\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"feitiços\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"voz\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"mudo\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Inutilizável\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Dano: 1/3 da vida do alvo\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Cura: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Dano: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Habilidade\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Cajado ({:d} carga)\"\nmsgstr[1] \"Cajado ({:d} cargas)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Nível {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Feitiço\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Atinge apenas mortos-vivos\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Pergaminho\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Cajado\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Atalho de feitiço {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Não é possível abrir o arquivo\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Não é possível carregar o personagem\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (nvl {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Histórico do Chat (Mensagens: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} de ouro\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Quantas peças de ouro você quer retirar?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Nível {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Experiência: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Nível máximo\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Próximo nível: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} para o nível {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"A tumba do Rei Leoric\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"A câmara de osso\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Uma passagem negra\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Altar profano\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Para {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Preciso de ajuda! Venha aqui!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Siga-me.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Tenho algo pra você.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Agora você MORRE!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Agradecimentos a\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Voltar\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Dano: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Armadura: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Dur: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"indestrutível\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Boas-vindas à\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Loja do ferreiro\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Você gostaria de:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Falar com Griswold\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Comprar itens básicos\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Comprar itens especiais\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Vender itens\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Reparar itens\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Sair da loja\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Eu tenho estes itens para vender:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Eu tenho estes itens especiais para vender:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Você não tem nada que eu queira.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Qual item está à venda?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Você não tem nada para reparar.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Reparar qual item?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Cabana da bruxa\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Falar com Ádria\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Comprar itens\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Recarregar cajados\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Sair da cabana\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Você não tem nada para recarregar.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Recarregar qual item?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Você não tem ouro o suficiente\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Você não tem espaço o suficiente em seu inventário\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Negócio fechado?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Tem certeza de que quer identificar este item?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Tem certeza de que quer comprar este item?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Tem certeza de que quer recarregar este item?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Tem certeza de que quer vender este item?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Tem certeza de que quer reparar este item?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt, garoto da Perna-de-Pau\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Falar com Wirt\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Eu tenho algo para vender,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"mas lhe custará 50 de ouro\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"só para dar uma olhada. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"O que você tem aí?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Dizer adeus\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Eu tenho este item para vender:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Sair\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Casa do curandeiro\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Falar com Pepin\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Sair da casa do curandeiro\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"O ancião da cidade\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Falar com Cain\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identificar um item\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Você não tem nada para identificar.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Identificar qual item?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Este item é:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Pronto\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Falar com {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Falar com {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"não está disponível\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"na versão\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"versão\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Boatos\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Sol Nascente\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Falar com Ogden\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Sair da taverna\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Falar com Gillian\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Acessar Armazém\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Farnham, o Bêbado\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Falar com Farnham\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Dizer adeus\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Seu ouro: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Aldeão Assassinado\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Griswold, o Ferreiro\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Pepin, o Curandeiro\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Aldeão Ferido\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden, o Dono da Taverna\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Cain, o Ancião\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Ádria, a Bruxa\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Gillian, a Atendente\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Vaca\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Lester, o fazendeiro\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Completamente Louco\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Guerreiro\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Ladina\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Feiticeiro\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Monge\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bardo\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Bárbaro\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zumbi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Carniçal\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Carcaça Apodrecida\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Morte Negra\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Caído\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Talhador\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Cria do Diabo\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Sombrio\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Esqueleto\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Cadáver de Machado\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Morto Calcinante\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Horror\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Escavador\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Devorador de Almas\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Fera das Sombras\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Cortaosso\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Cadáver Arqueiro\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Esqueleto Capitão\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Cadáver Capitão\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Morto Calcinante Capitão \"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Horror Capitão\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Lorde Invisível\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Escondido\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Espreitador\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Despercebido\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Tecelão de Ilusões\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Lorde Sátiro\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Clã Carne Fresca\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Clã de Pedra\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Clã de Fogo\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Clã da Noite\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Demônio\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Cintilador\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Melancolia\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Familiar\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Fera Ácida\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Cospe-Veneno\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Fera do Poço\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Gorja de Lava\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Rei Esqueleto\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"O Açougueiro\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Suserano\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Homem-Lama\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Demônio Sapo\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Esfolado\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Wyrm\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Lesma da Caverna\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Wyrm Demoníaca\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Devorador\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Demônio de Magma\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Pedra Sanguínea\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Pedra do Inferno\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Lorde da Lava\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Demônio com Chifres\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Trilhador da Lama\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Suicida Gélido\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Lorde da Obsidiana\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"Ossovelho\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Morte Rubra\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Demônio Litch\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Balrog Morto-vivo\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Incinerador\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Lorde da Chama\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Fogo da Perdição\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Queimador do Inferno\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Tempestade Rubra\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Tempestuoso\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Lorde da Tempestade\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Redemoinho\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Cria do Diabo Bruta\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Demônio Alado\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gárgula\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Garra Sangrenta\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Asa da Morte\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Homicida\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Guardião\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Lorde do Vórtice\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Víbora da Caverna\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Víbora de Fogo\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Víbora de Ouro\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Víbora Azulada\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Cavaleiro Negro\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Guarda da Perdição\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Lorde de Aço\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Cavaleiro Sangrento\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Desfiador\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Oco\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Mestre da Dor\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Tecelão de Realidades\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Súcubo\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Bruxa da Neve\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Cria do Inferno\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Queimadora de Almas\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Conselheiro\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Magistrado\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Cabalista\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Defensor\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"O Lorde Sombrio\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"O Arce-Litch Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad, o Fraco\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar, o Louco\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Kaikatarro\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Arcebispo Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Apurrinhação Vermelha\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Jade Negra\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Senhor da Guerra Sangrenta\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Demônio Hork\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"O Profanador\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Osteocéfalo Machado\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Laminiderme, o Esfaqueador\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Pus de Alma\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Vomirrato, o Impuro\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Estripa-ossos\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Putrefórico, o Faminto\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Tripernil, o Veloz\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Traumocéfalo Bate-Escudos\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Putrificina\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Mordesombra\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Olho Morto\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Olholouco, o Morto\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Fogo Cranial\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Crânio Torto\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Sanguinolíngue\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Pulsejador\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Verga-Luas\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Corvo da Cólera\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Come-Espinhas\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Cinzascura, o Calcinante\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Corvossombra\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Pedrapraga, o Fraco\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Espumabile, o Mestre do Poço\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Sanguiderme Arco Negro\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Asa Pútrida\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Bebedor das Sombras\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Muda-Névoas\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Cospe-Morte\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Coagulário\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Sombra da Morte Rasga-Carne\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Larvaguerra, o Louco\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Crânio de Vidro, o Serrilhado\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Flagelo de Fogo\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Asa Noturna, o Gélido\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Rochacínio\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Pugibronze Pedra de Fogo\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Irígnea, o Condenado\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Chaga Ígnea, o Tenebroso\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Barão Lodoso\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Guampestífero Maça de Aço\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Berrocaos\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Sorrirruína, o Podre\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Queimador Louco\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Serra Osso, o Litch\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Quebra-Espinha\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Demonicrânio Osso Afiado\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Tempestrago\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Praguestade\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Babujador\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Pragáurea da Chama\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Tempestade Negra\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Pestilérico\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"O Esfolador\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Chifre Azul\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Deformígneo Cria do Inferno\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Presatroz\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Pesticrânio\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"CrânioLeão, o Curvado\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Língua Negra\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Toque Nóxio\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Ignofídico\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Presiderme\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Witchfire, o Pecaminoso\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Caveira Negra\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Corta-Almas\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Ventoso\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Senhor do Poço\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Ferrecelão\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Iruivante, a Sombra\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Nuvem da Desgraça\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Luassangra Fogo de Alma\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Bruxa Lunar\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Banqueticínio\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Belipardo, o Matador\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Temível Juiz\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Estrolha, a Bruxa\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Craniaço, o Caçador\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"O Vizir\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamfir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Sede de Sangue\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Viúvaranha\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Dançarina da Carne\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Espinebroso\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Perdentrave\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Espada Curta\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Broquel\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Clava\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Arco curto\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Cajado curto de mana\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Cutelo\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Coroa dos mortos-vivos\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Anel empíreo\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Rocha mágica\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Amuleto óptico\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Anel da verdade\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Placa da taverna\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Brasão do arlequim\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Véu de aço\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Elixir dourado\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Bigorna da fúria\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Cogumelo negro\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Cérebro\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Tomo fungoso\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Elixir espectral\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Pedra sanguínea\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Mapa da catedral\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Poção de cura\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Poção de mana\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Pergaminho de identificar\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Pergaminho de portal da cidade\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Bravura de Arkaine\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Poção de cura completa\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Poção de mana completa\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Gume de Griswold\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Placa bovina\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Cajado de Lázarus\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Pergaminho de ressuscitar\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Cajado curto\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Espada\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Adaga\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Runa explosiva\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodore\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Amuleto áurico\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Nota rasgada 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Nota rasgada 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Nota rasgada 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Nota reconstruída\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Traje marrom\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Traje cinza\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Quepe\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Cervelliere\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Elmo\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Elmo Completo\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Coroa\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Grande Elmo\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Capa\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Trapo\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Manto\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Túnica\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Armadura Acolchoada\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Armadura de Couro\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Armadura de Couro Duro\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Armad. de Couro Cravejado\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Malha de Anéis\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Malha\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Cota de Malha\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Malha em Escamas\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Armadura Peitoral\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Armadura de Placas\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Cota de Talas\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Malha de Placas\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Placa de Campo\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Placa Gótica\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Malha de Placas Completa\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Escudo\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Escudo Pequeno\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Escudo Grande\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Escudo Gota\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Escudo Torre\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Escudo Gótico\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Poção de Rejuvenescimento\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Poção de Rejuvenescimento Completo\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Óleo\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Elixir da Força\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Elixir da Magia\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Elixir da Destreza\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Elixir da Vitalidade\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Pergaminho de Cura\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Pergaminho de Busca\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Pergaminho de Raio\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Pergaminho de Parede de Fogo\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Pergaminho de Inferno\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Pergaminho de Lampejo\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Pergaminho de Infravisão\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Pergaminho de Fasear\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Pergaminho de Escudo de Mana\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Pergaminho de Onda de Chamas\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Pergaminho de Bola de Fogo\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Pergaminho de Maldição de Pedra\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Pergaminho de Relâmp. Encadeado\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Pergaminho de Guardião\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Pergaminho de Nova\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Pergaminho de Golem\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Pergaminho de Teletransporte\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Pergaminho de Apocalipse\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Alfanje\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Cimitarra\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Espada Escocesa\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Lâmina\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Sabre\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Espada Longa\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Espada Larga\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Espada Bastarda\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Espada de Duas Mãos\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Espada Montante\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Machado Pequeno\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Machado\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Machado Grande\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Machado Largo\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Machado de Batalha\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Grão-machado\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Maça\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Chicote de Roldão\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Martelo de Guerra\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Martelo\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Clava Cravada\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Mangual\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Malho\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Arco\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Arco de Caçador\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Arco Longo\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Arco Composto\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Arco de Batalha Curto\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Arco de Batalha Longo\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Arco de Guerra Curto\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Arco de Guerra Longo\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Cajado longo\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Cajado composto\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Cajado de combate\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Cajado de guerra\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Anel\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amuleto\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Runa de Fogo\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Runa\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Runa de Relâmpago\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Grande Runa de Fogo\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Grande Runa de Relâmpago\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Runa de Pedra\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Cajado Curto de Raio Carregado\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Poção de Arena\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Cutelo do Açougueiro\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Sabre de luz\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Arco da ruptura\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"O agulheiro\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"O arco celestial\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Caçador mortal\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Arco dos mortos\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Arco do carvalho negro\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Dardo das chamas\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Ferroa-carne\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Força do vento\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Chifre de águia\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Punhal de Gonnagal\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"O defensor\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Garra do Grifo\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Navalha negra\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Lua crescente\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Haste de gelo\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Lâmina do carrasco\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"A serra de osso\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Gavião das sombras\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Espinho arcano\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Sabre de luz\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Garra do falcão\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Ruinosa\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"O Urso Pardo\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"O Avô\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"O Estraçalhador\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Bico afiado\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Assassino sangrento\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"O machado celestial\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Machado maligno\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Cutelo de pedra\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Machadinha de Aguinara\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Assassino infernal\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Ceifador de Messerschmidt\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Racharrugem\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Martelo de Jholm\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Tacape de Civerb\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"A estrela celestial\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Estrela de Baranar\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Raiz nodosa\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"O amassador de crânios\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Martelo de Schaefer\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Flange onírico\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Cajado das sombras\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Imolador\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Ápice da tempestade\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Canção do vislumbre\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Chamado do trovão\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"O protetor\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Enigma de Naj\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Grito da mente\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Vara de Onan\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Elmo dos Espíritos\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Quepe de reflexão\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Elmo do Suserano\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Brasão do bobo\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Götterdämerung\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Diadema real\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Carne rasgada de almas\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Flagelo do gladiador\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"O manto arco-íris\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Couro de Aut\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Xale da sabedoria\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Malha faiscante\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Carapaça do Vorazgo\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Paisagem da noite\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Placa leve de Naj\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Casaco de demonispeto\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"O defletor\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Escudo de crânio partido\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Fenda do dragão\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Escudo do carvalho negro\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Defensor santo\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Escudo da tempestade\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Silveira\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Anel de Regha\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"O sangrador\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Anel constringente\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Anel de noivado\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"de lata\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"de latão\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"de bronze\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"de ferro\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"de aço\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"de prata\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"de platina\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"de mithril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"meteórico(a)\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"estranho(a)\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"inútil\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"envergado(a)\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"fraco(a)\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"serrilhado(a)\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"mortal\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"pesado(a)\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"vicioso(a)\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"brutal\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"imenso(a)\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"selvagem\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"implacável\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"impiedoso(a)\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"desajeitado(a)\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"enfadonho(a)\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"afiado(a)\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"fino(a)\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"de guerreiro\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"de soldado\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"do senhor\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"de cavaleiro\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"de mestre\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"de campeão\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"de rei\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"vulnerável\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"enferrujado(a)\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"forte\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"grandioso(a)\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"valente\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"glorioso(a)\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"abençoado(a)\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"santo(a)\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"impressionante\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"divino(a)\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"vermelho(a)\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"carmesim\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"granada\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"rubi\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"azul\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"lazúli\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"lápis-lazúli\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"cobalto\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"safira\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"branco(a)\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"de pérola\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"de marfim\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"de cristal\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"de diamante\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"de topázio\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"de âmbar\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"de jade\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"de obsidiana\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"de esmeralda\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"de hienas\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"de sapos\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"de aranhas\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"de corvos\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"de cobras\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"de serpentes\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"de draco\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"de dragão\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"de serpe\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"de hidra\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"de anjo\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"de arcanjo\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"farto(a)\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"abundante\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"flamejante\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"relampejante\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"de qualidade\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"do aleijamento\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"do homicídio\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"da ultra-violência\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"da carnificina\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"do massacre\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"da dor\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"das lágrimas\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"da saúde\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"da proteção\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"da absorção\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"da deflexão\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"da osmose\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"da fragilidade\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"da fraqueza\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"da força\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"do poder\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"da potência\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"dos gigantes\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"dos titãs\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"da paralisia\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"da atrofia\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"da destreza\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"da habilidade\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"da acurácia\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"da precisão\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"da perfeição\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"do tolo\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"da dislexia\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"da magia\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"da mente\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"do brilhantismo\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"da feitiçaria\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"da bruxaria\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"da enfermidade\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"da doença\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"da vitalidade\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"do ânimo\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"do afinco\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"do vigor\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"da vida\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"da encrenca\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"do poço\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"do céu\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"da lua\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"das estrelas\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"do paraíso\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"do zodíaco\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"do abutre\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"do chacal\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"da raposa\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"do jaguar\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"da águia\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"do lobo\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"do tigre\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"do leão\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"do mamute\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"da baleia\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"da debilidade\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"da ruptilidade\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"da firmeza\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"da competência\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"da estrutura\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"das eras\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"do escuro\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"da noite\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"da luz\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"da radiância\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"da chama\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"do fogo\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"calcinante\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"do choque\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"do relâmpago\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"do trovão\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"dos muitos\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"da abundância\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"dos espinhos\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"da corrupção\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"dos ladrões\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"do urso\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"do morcego\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"dos vampiros\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"do sanguessuga\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"do sangue\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"da perfuração\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"da punção\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"do esmagamento\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"da prontidão\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"da presteza\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"da velocidade\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"da pressa\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"do equilíbrio\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"da estabilidade\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"da harmonia\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"do bloqueio\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"A Rocha Mágica\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad, o Fraco\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar, o Louco\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"O Açougueiro\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"A placa de Ogden\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Câmara dos cegos\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Bravura\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Senhor da Guerra Sangrenta\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"A maldição do Rei Leoric\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Arcebispo Lázarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Assuntos graves\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Pomar do fazendeiro\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Garotinha\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Comerciante errante\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"O Profanador\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"A Fantasia de Jersey\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Raio de Fogo\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Cura\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Relâmpago\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Lampejo\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identificar\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Parede de Fogo\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Portal da cidade\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Petrificar\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infravisão\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Fasear\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Escudo de Mana\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Bola de Fogo\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Guardiã\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Relâmpago encadeado\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Onda de Chamas\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Serpentes da Ruína\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Ritual Sanguíneo\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Invisibilidade\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Fúria\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teletransporte\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apocalipse\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Eterealizar\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Reparar Itens\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Recarregar Cajados\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Desarmar Armadilha\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elemental\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Raio Carregado\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Raio Sagrado\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Ressurreição\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telecinese\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Curar Outro\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Estrela de Sangue\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Espírito de Ossos\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ahh, a história do nosso Rei, não é? A trágica queda de Leoric foi um golpe \"\n\"duro para estas terras. O povo sempre amou o Rei, agora vive com medo mortal \"\n\"dele. A pergunta que continuo me fazendo é como ele pode ter caído para tão \"\n\"longe da Luz, já que Leoric sempre foi o mais santo dos homens. Apenas os \"\n\"poderes mais vis do Inferno poderiam destruir um homem por dentro tão \"\n\"completamente...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"A vila precisa de sua ajuda, bom(a) mestre(a)! Há alguns meses o filho do \"\n\"Rei Leoric, o Príncipe Albrecht, foi sequestrado. O Rei entrou em fúria e \"\n\"vasculhou a vila por seu filho desaparecido. A cada dia que se passava, \"\n\"Leoric parecia decair mais fundo na loucura. Ele buscou culpar aldeões \"\n\"inocentes pelo desaparecimento do garoto e ordenou que fossem brutalmente \"\n\"executados. Menos da metade de nós sobrevivemos à insanidade dele...\\n\"\n\" \\n\"\n\"Os Cavaleiros e Sacerdotes do Rei tentaram pacificá-lo, mas ele se voltou \"\n\"contra eles e, infelizmente, foram forçados a matá-lo. Com seu último \"\n\"suspiro, o Rei invocou uma terrível maldição sobre seus antigos seguidores. \"\n\"Fez um voto de que eles o serviriam nas trevas para sempre...\\n\"\n\" \\n\"\n\"É aqui que as coisas tomam um rumo mais sombrio do que eu pensava ser \"\n\"possível! Nosso antigo Rei se levantou de seu sono eterno e agora comanda \"\n\"uma legião de seguidores mortos-vivos dentro do Labirinto. Seu corpo foi \"\n\"enterrado em uma tumba três andares abaixo da Catedral. Por favor, bom(a) \"\n\"mestre(a), coloque a alma dele em paz ao destruir a sua forma amaldiçoada de \"\n\"agora...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Como eu lhe disse, bom(a) mestre(a), o Rei foi sepultado três andares sob \"\n\"aqui. Ele está lá embaixo, aguardando nas pútridas trevas pela chance de \"\n\"destruir estas terras...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"A maldição do nosso Rei passou, mas eu temo ter sido apenas parte de um mal \"\n\"maior em ação. Contudo, ainda podemos ser salvos da escuridão que consome \"\n\"nossa terra, pois sua vitória é um bom presságio. Que a Luz lhe guie em seu \"\n\"caminho, bom(a) mestre(a).\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"A perda do filho foi demais para o Rei Leoric. Eu fiz o que pude para \"\n\"aliviar sua loucura, mas no final ela o superou. Uma maldição negra pairou \"\n\"sobre este reino daquele dia em diante, mas, se você conseguir libertar o \"\n\"espírito dele desta prisão terrena, talvez a maldição seja removida...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Eu não gosto de pensar sobre como o Rei morreu. Gosto de lembrá-lo pelo \"\n\"governante justo e bondoso que era. Sua morte foi tão triste e pareceu tão \"\n\"errada, de algum modo.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Eu forjei várias das armas e a maioria das armaduras que o Rei Leoric usou \"\n\"para equipar seus cavaleiros. Inclusive confeccionei para ele uma enorme \"\n\"espada de duas mãos do mais fino Mithril, bem como uma coroa de guerra para \"\n\"combinar. Ainda não consigo acreditar em como ele morreu, mas deve ter sido \"\n\"alguma força muito sinistra que o deixou louco!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Eu não me importo com isso. Escuta, nenhum esqueleto vai ser MEU rei. Leoric \"\n\"é Rei. Rei, está me ouvindo? SALVE O REI!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Os mortos que caminham entre os vivos seguem ao Rei amaldiçoado. Ele detém o \"\n\"poder de erguer ainda mais guerreiros para um exército sempre crescente de \"\n\"mortos-vivos. Se você não parar o seu reinado, ele certamente marchará por \"\n\"estas terras e matará a todos que ainda vivem aqui.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Veja, estou administrando um negócio aqui. Eu não vendo informação e eu não \"\n\"ligo para algum Rei que está morto há mais tempo do que estou vivo. Se \"\n\"precisar de algo para usar contra esse Rei dos mortos-vivos, aí eu posso lhe \"\n\"ajudar...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"O calor da vida adentrou a minha tumba. Prepare-se, mortal, para servir a \"\n\"meu Mestre pela eternidade!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Vejo que este comportamento estranho lhe intriga também. Eu suponho que, \"\n\"como muitos demônios temem a luz do sol e acreditam que ele detém muito \"\n\"poder, é possível que o sol nascente representado na placa de que você fala \"\n\"tenha os levado a crer que ela também detém certos poderes arcanos. Hmm, \"\n\"talvez eles não sejam tão espertos quanto temíamos...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Mestre(a), eu tenho uma experiência estranha a relatar. Sei que você tem \"\n\"grandes conhecimentos sobre as monstruosidades que habitam o labirinto e \"\n\"isto aqui é algo que não consigo entender de modo algum... Eu fui acordado \"\n\"durante a noite pelo som de arranhões vindos de fora da minha taverna. \"\n\"Quando olhei a partir da minha cama, vi a forma de pequenas criaturas \"\n\"demoníacas no quintal da estalagem. Após pouco tempo, elas correram, mas não \"\n\"antes de roubarem a placa da minha hospedaria. Eu não sei por que os \"\n\"demônios roubariam a minha placa mas deixariam minha família em paz... \"\n\"Estranho, não?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Ah, você não precisava trazer minha placa de volta, mas imagino que isto me \"\n\"poupe do custo de mandar fazer outra. Bem, deixe-me ver, o que eu poderia \"\n\"lhe dar como pagamento por encontrá-la? Hmmm, o que temos aqui... Ah, sim! \"\n\"Este gorro foi deixado em um dos quartos por um mágico que ficou aqui há \"\n\"algum tempo. Talvez seja de algum valor para você.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Oh Deuses, demônios correndo pela vila à noite, saqueando nossas casas - \"\n\"nada mais é sagrado? Eu espero que Ogden e Garda estejam bem. Imagino que \"\n\"viriam me ver se estivessem feridos...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Pelos Deuses! É lá que a placa foi parar? Minha avó e eu devemos ter dormido \"\n\"durante a coisa toda. Graças à Luz que esses monstros não atacaram a \"\n\"estalagem.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Demônios roubaram a placa de Ogden, você disse? Isso não soa muito como as \"\n\"atrocidades que ouvi - e vi. \\n\"\n\" \\n\"\n\"Demônios estão preocupados em arrancar seu coração, não suas placas.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Você sabe o que eu acho? Alguém pegou aquela placa e vai querer muito \"\n\"dinheiro por ela. Se eu fosse Ogden... e eu não sou, mas se eu fosse... Eu \"\n\"simplesmente compraria outra placa com algum desenho bonito nela. Talvez uma \"\n\"bela caneca de cerveja ou um pedaço de queijo...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Nenhum mortal pode entender de verdade a mente de um demônio. \\n\"\n\" \\n\"\n\"Nunca deixe que as ações erráticas deles lhe confundam, já que isso pode \"\n\"também ser parte de seus planos.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"O quê? Ele está dizendo que eu peguei? Imagino que Griswold esteja do lado \"\n\"dele também. \\n\"\n\" \\n\"\n\"Veja, eu já superei o roubo de placas meses atrás. Não dá pra lucrar com um \"\n\"pedaço de madeira.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Ei - Você aquele que mata tudo! Você me dá Bandeira Mágica ou nós atacar! \"\n\"Você não sair com vida! Você matar feiosos grandes e devolve Magia. Passa \"\n\"pelo canto e porta, acha feiosos. Você dá, você vai!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Você matar feiosos, pegar bandeira. Você trazer para mim, se não...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Você dá! Sim, bom! Vá agora, nós forte. Nós matar tudo com grande Magia!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Isto não é um bom presságio, pois confirma meus medos mais sombrios. Embora \"\n\"eu não me permitisse acreditar nas lendas antigas, não posso negá-las agora. \"\n\"Talvez tenha chegado a hora de revelar quem eu sou.\\n\"\n\" \\n\"\n\"Meu verdadeiro nome é Deckard Cain, o Ancião, e eu sou o último descendente \"\n\"de uma antiga Irmandade que era dedicada a salvaguardar os segredos de um \"\n\"mal atemporal. Um mal que muito obviamente foi agora liberto.\\n\"\n\" \\n\"\n\"O Arcebispo Lázarus, antes o conselheiro mais confiado do Rei Leoric, levou \"\n\"um grupo de simples aldeões até dentro do Labirinto para encontrar o filho \"\n\"desaparecido do Rei, Albrecht. Passou-se um bom tempo até que voltassem e \"\n\"apenas alguns escaparam com suas vidas.\\n\"\n\" \\n\"\n\"Pode me chamar de tolo! Eu devia ter suspeitado de sua traição velada na \"\n\"época. Deve ter sido o próprio Lázarus quem sequestrou Albrecht e desde \"\n\"então o escondeu dentro do Labirinto. Eu não entendo por que o Arcebispo se \"\n\"voltou à escuridão, ou qual é seu interesse na criança. A menos que ele \"\n\"pretenda sacrificá-la a seus mestres sombrios!\\n\"\n\"\\n\"\n\"Deve ser isso o que ele planejou! Os sobreviventes de seu 'grupo de resgate' \"\n\"dizem que Lázarus foi visto pela última vez correndo para as mais profundas \"\n\"entranhas do Labirinto. Você deve se apressar e salvar o príncipe da lâmina \"\n\"sacrificial deste monstro demente!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Você deve se apressar e resgatar Albrecht das mãos de Lázarus. O príncipe e \"\n\"o povo deste reino estão contando com você!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Sua história é bastante grave, meu(inha) amigo(a). Lázarus certamente \"\n\"queimará no Inferno por seu feito horrível. O garoto que você descreveu não \"\n\"é o nosso príncipe, mas acredito que Albrecht ainda pode estar em perigo. O \"\n\"símbolo de poder do qual você fala deve ser um portal para o verdadeiro \"\n\"coração do Labirinto.\\n\"\n\" \\n\"\n\"Saiba disto, meu(inha), amigo(a) - O mal contra o qual você se move é o \"\n\"sombrio Senhor do Terror. Ele é conhecido entre os homens mortais como \"\n\"Diablo. Ele é quem foi aprisionado dentro do Labirinto há muitos séculos \"\n\"atrás, e eu temo que ele busque mais uma vez semear o caos no mundo humano. \"\n\"Você deve se aventurar através do portal e destruir Diablo antes que seja \"\n\"tarde demais!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lázarus foi o Arcebispo que levou muitos dos aldeões para dentro do \"\n\"Labirinto. Eu perdi muitos bons amigos naquele dia e Lázarus nunca mais \"\n\"voltou. Imagino que ele foi morto junto com a maioria dos outros. Se puder \"\n\"me fazer um favor, bom(a) mestre(a) - peço que não fale com Farnham sobre \"\n\"aquele dia.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Eu fiquei chocado ao ouvir o que os aldeões estavam planejando fazer naquela \"\n\"noite. Pensei que, dentre todos, Lázarus é quem mais juízo. Ele era um \"\n\"Arcebispo e sempre pareceu se preocupar muito com os habitantes de Tristram. \"\n\"Tantos foram feridos, eu não pude salvar a todos...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Eu me lembro de Lázarus como um homem muito bom e generoso. Ele falou no \"\n\"funeral da minha mãe e foi solícito comigo e com a minha avó em uma época \"\n\"muito difícil. Eu rezo toda noite para que, de algum modo, ele ainda esteja \"\n\"vivo e seguro.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Eu estava lá quando Lázarus nos levou para o Labirinto. Ele falou de castigo \"\n\"santo, mas quando começamos a lutar contra aqueles infernais, ele sequer \"\n\"levantou sua maça contra eles. Simplesmente correu mais e mais para dentro \"\n\"das câmaras sombrias e intermináveis, repletas de servos das trevas!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Eles furam, depois mordem, depois estão ao seu redor por todos os lados. \"\n\"Mentiroso! MENTIROSO! Estão todos mortos! Mortos! Está me ouvindo? Eles só \"\n\"continuam caindo e caindo... o sangue deles se espalhando pelo chão... tudo \"\n\"culpa dele...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Eu não conheci esse Lázarus de quem você fala, mas sinto um grande conflito \"\n\"dentro dele. Ele representa um grande perigo e nada o impedirá de servir aos \"\n\"poderes das trevas que o tomaram para si.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Sim, o honrado Lázarus, que foi tããão efetivo contra aqueles monstros lá \"\n\"embaixo. Não ajudou a salvar minha perna, ajudou? Olha, eu vou lhe dar um \"\n\"conselho de graça. Pergunte a Farnham, ele estava lá.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Abandone sua missão tola. Tudo o que lhe aguarda é a ira de meu Mestre! Você \"\n\"chegou tarde demais para salvar a criança. Agora vai unir-se a ela no \"\n\"Inferno!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, eu não sei o que posso realmente dizer sobre isso que seja de alguma \"\n\"ajuda. A água que enche nossos poços vem de uma fonte subterrânea. Eu ouvi \"\n\"falar de um túnel que leva a um grande lago - talvez ele seja a nascente. \"\n\"Infelizmente, eu não sei o que pode estar contaminando nosso reservatório de \"\n\"água.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Eu sempre tentei manter uma grande reserva de alimentos e bebidas em nosso \"\n\"depósito no porão, mas com a cidade inteira sem uma fonte de água fresca, \"\n\"mesmo os nossos estoques acabarão em breve. \\n\"\n\" \\n\"\n\"Por favor, faça o que puder ou eu não sei o que faremos.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Ainda bem que consegui falar com você a tempo! Nossos poços ficaram salobros \"\n\"e podres, e alguns dos aldeões ficaram doentes ao beber deles. Nossas \"\n\"reservas de água fresca estão secando rapidamente. Eu acredito que há uma \"\n\"passagem que leva para as fontes que abastecem nossa cidade. Por favor, \"\n\"descubra o que causou esta calamidade ou com certeza todos nós sucumbiremos.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Por favor, tenha pressa. A cada hora que passa ficamos mais perto de não ter \"\n\"água para beber. \\n\"\n\" \\n\"\n\"Nós não poderemos sobreviver por muito tempo sem a sua ajuda.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"O que é isso que está me dizendo - a mera presença dos demônios fez a água \"\n\"se contaminar? Oh, realmente um grande mal está à espreita sob nossa cidade, \"\n\"mas a sua perseverança e coragem nos dão esperança. Por favor, pegue este \"\n\"anel - talvez lhe ajude na destruição de criaturas tão vis.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Minha avó está muito fraca, e Garda diz que não podemos beber a água dos \"\n\"poços. Por favor, você pode fazer algo para nos ajudar?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin lhe disse a verdade. Nós precisaremos muito de água fresca e em breve. \"\n\"Eu tentei limpar um dos poços menores mas ele fede a sujeira parada. Deve \"\n\"haver algo entupindo a fonte.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Você bebe água?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"O povo de Tristram morrerá se você não conseguir restaurar a água fresca de \"\n\"seus poços. \\n\"\n\" \\n\"\n\"Saiba disto - demônios estão no centro desta questão, mas eles permanecem \"\n\"ignorantes do que causaram.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Estou com você desta vez. Meus negócios secam - por assim dizer - se eu não \"\n\"tiver um mercado que compre. É melhor você descobrir o que está acontecendo \"\n\"e logo!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Um livro que fala de uma câmara de ossos humanos? Bom, uma Câmara de Ossos é \"\n\"mencionada em certos escritos arcaicos que estudei nas bibliotecas do \"\n\"Oriente. Esses tomos pressupunham que quando os Senhores do Mundo Inferior \"\n\"desejavam proteger grandes tesouros, eles criavam domínios onde aqueles que \"\n\"morressem na tentativa de roubar o tesouro seriam eternamente obrigados a \"\n\"defendê-lo. Um perverso, mas estranhamente adequado final?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Temo não saber nada sobre isso, bom(a) mestre(a). Cain tem vários livros que \"\n\"podem ajudar em algo.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Isso me soa como um lugar muito perigoso. Caso se aventure por lá, por favor \"\n\"tome muito cuidado.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Temo não ter ouvido nada sobre isso. Talvez Cain, o Contador de Histórias, \"\n\"possa ajudar em algo.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Não sei nada sobre esse lugar, mas você pode tentar perguntar a Cain. Ele \"\n\"fala sobre muitas coisas, e eu não me surpreenderia se ele tivesse algumas \"\n\"respostas para a sua pergunta.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Certo, então ouça. Existe essa câmara de madeira, veja só. E a esposa dele, \"\n\"você sabe - ela - conta à árvore... porque você precisa esperar. Então eu \"\n\"digo, isso pode funcionar contra ele, mas se você pensa que eu vou PAGAR por \"\n\"isso... você... hã... é.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Você se tornará um(a) eterno(a) servo(a) dos Senhores Sombrios caso morra \"\n\"nesse domínio amaldiçoado. \\n\"\n\" \\n\"\n\"Adentre a Câmara de Ossos por sua conta e risco.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Um tesouro vasto e misterioso, é o que disse? Talvez eu tenha interesse em \"\n\"comprar algumas coisas de você... ou, melhor ainda, você não precisa de \"\n\"alguns recursos raros e caros para enfrentar esse desafio?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Parece que o Arcebispo Lázarus incitou vários dos aldeões a se aventurar \"\n\"dentro do Labirinto para encontrar o filho desaparecido do Rei. Ele brincou \"\n\"com seus medos e os instigou a virar uma multidão frenética. Nenhum deles \"\n\"estava preparado para o que jazia sob a terra fria... Lázarus os abandonou \"\n\"lá embaixo - deixados nas garras de horrores indizíveis - para morrerem.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Sim, Farnham balbuciou algo sobre um brutamontes empunhando uma arma feroz. \"\n\"Acredito que o chamou de Açougueiro.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Pela Luz, eu ouvi falar desse demônio vil. Houve muitos que carregavam as \"\n\"cicatrizes de sua ira em seus corpos quando os poucos sobreviventes do \"\n\"ataque liderado por Lázarus se arrastaram para fora da Catedral. Eu não sei \"\n\"o que ele usou para cortar suas vítimas, mas não pode ser algo deste mundo. \"\n\"Deixou feridas podres com doenças, e mesmo eu as achei quase impossíveis de \"\n\"tratar. Cuidado se planeja batalhar contra esse demônio...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Quando Farnham disse algo sobre um açougueiro matando pessoas, eu \"\n\"imediatamente desconsiderei. Mas já que você trouxe o assunto, talvez seja \"\n\"verdade.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Eu vi o que Farnham chama de O Açougueiro quando ele abria caminho através \"\n\"dos corpos dos meus amigos. Ele brandia um cutelo grande como um machado, \"\n\"ceifando membros e mutilando bravos homens ali mesmo onde estavam. Eu fui \"\n\"separado da briga por um bando de pequenos demônios guinchando e de algum \"\n\"modo encontrei a escadaria para o lado de fora. Eu nunca mais vi aquela \"\n\"besta horrenda, mas seu semblante ensanguentado me assombra até hoje.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Grande! Grande cutelo matando todos os meus amigos. Não pude pará-lo, tive \"\n\"que correr, não pude salvá-los. Preso em uma sala com tantos corpos... \"\n\"tantos amigos... NÃÃÃÃÃÃÃÃÃO!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"O Açougueiro é uma criatura sádica que se deleita na tortura e na dor dos \"\n\"outros. Você viu a obra dele no beberrão Farnham. Sua destruição fará muito \"\n\"para assegurar a segurança desta vila.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Eu sei mais do que você pensa sobre aquele demônio horrendo. Os amiguinhos \"\n\"dele me pegaram e conseguiram tirar minha perna antes que Griswold me \"\n\"puxasse para fora daquele buraco. \\n\"\n\" \\n\"\n\"Eu vou ser franco - mate-o antes que ele lhe mate, adicionando seu cadáver à \"\n\"coleção dele.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Por favor, escute o que digo. O Arcebispo Lázarus, ele nos trouxe aqui \"\n\"abaixo para encontrar o príncipe perdido. O desgraçado nos colocou em uma \"\n\"armadilha! Agora estão todos mortos... assassinados por um demônio chamado O \"\n\"Açougueiro. Vingue-nos! Encontre esse Açougueiro e mate-o para que nossas \"\n\"almas possam finalmente descansar...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Você recita uma interessante rima, escrita em um estilo que me lembra de \"\n\"outros trabalhos. Deixe-me pensar agora - o que era?\\n\"\n\" \\n\"\n\"...A escuridão encobre os Escondidos. Olhos brilham ocultos, com apenas o \"\n\"som de garras afiadas arranhando brevemente, para atormentar as pobres almas \"\n\"que se tornaram cegas para toda a eternidade. A prisão para os assim \"\n\"amaldiçoados é chamada de a Câmara dos Cegos...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Eu nunca me importei muito com poesia. Ocasionalmente, eu fazia caso de \"\n\"contratar menestréis quando a estalagem estava indo bem, mas isso parece ter \"\n\"sido há tanto tempo agora. \\n\"\n\" \\n\"\n\"O quê? Oh, sim... hã, bom, imagino que você poderia ir ver o que alguma \"\n\"outra pessoa sabe sobre isso.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Isso parece familiar, de algum modo. Acredito lembrar de ler algo muito \"\n\"parecido com esse poema quando pesquisava a história das aflições \"\n\"demoníacas. Falava de um lugar de grande mal que... espera - você não está \"\n\"indo para lá, está?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Se você tiver perguntas sobre cegueira, você deve falar com Pepin. Eu sei \"\n\"que ele deu para a minha avó uma poção que ajudou a limpar a visão dela, \"\n\"então talvez ele também possa lhe ajudar.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Temo nunca ter ouvido falar sobre, ou visto, um lugar que se assemelhe à sua \"\n\"vívida descrição, meu(inha) amigo(a). Talvez Cain, o Contador de Histórias, \"\n\"possa oferecer alguma ajuda.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Veja bem... é muito engraçado, hein? Entendeu? Cego - veja bem?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Esse é um lugar de grande angústia e terror, portanto serve bem ao seu \"\n\"mestre. \\n\"\n\" \\n\"\n\"Ande com cuidado, ou você pode ficar lá mais tempo do que previa.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Deixa eu ver, eu estou lhe vendendo algo? Não. Você está me dando dinheiro \"\n\"para lhe falar sobre isso? Não. Você vai sair agora e falar com o Contador \"\n\"de Histórias que vive imerso nesse tipo de coisa? Sim.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Você diz ter falado com Lachdanan? Ele foi um grande herói em vida. \"\n\"Lachdanan foi um homem justo e honrado que serviu ao seu Rei fielmente por \"\n\"anos. Mas, é claro, você já sabe disso.\\n\"\n\" \\n\"\n\"Dentre os que foram atingidos pelo domínio da Maldição do Rei, Lachdanan é \"\n\"quem teria menos chances de se render às trevas sem lutar, então imagino que \"\n\"a sua história pode ser verdadeira. Se eu estivesse em seu lugar, meu(inha) \"\n\"amigo(a), eu encontraria uma forma de libertá-lo dessa tortura.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Você fala de um bravo guerreiro, morto há muito tempo! Eu não conversarei \"\n\"sobre falar com gente morta no quintal da minha estalagem, muito obrigado.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Um elixir dourado, você diz. Eu nunca fabriquei uma poção dessa cor antes, \"\n\"então não sei dizer como lhe afetaria se você tentasse bebê-la. Como seu \"\n\"curandeiro, eu recomendo fortemente que, caso encontre tal elixir, faça o \"\n\"que Lachdanan pediu e NÃO tente tomá-lo.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Eu nunca ouvi falar de um Lachdanan antes. Peço desculpas, mas acho que não \"\n\"poderei ajudar muito.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Se é realmente Lachdanan que você encontrou, então eu recomendaria ajudá-lo. \"\n\"Eu lidei com ele em diversas situações e o acho honesto e leal por natureza. \"\n\"A maldição que caiu sobre os seguidores do Rei Leoric cairia de forma \"\n\"especialmente dura sobre ele.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan está morto. Todos sabem disso, e você não pode me enganar e me \"\n\"fazer pensar diferente disso. Não dá para falar com os mortos. Eu sei!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Você pode encontrar pessoas que estão presas dentro do labirinto, como \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"Eu sinto nele honra e uma grande culpa. Ajude-o e ajudará a todos em \"\n\"Tristram.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Espera, deixa eu adivinhar. Cain foi engolido por uma fenda gigante que se \"\n\"abriu embaixo dele. Ele foi incinerado em uma bola de fogo do Inferno e não \"\n\"pode mais responder suas perguntas. Ah, não foi isso o que aconteceu? Então \"\n\"imagino que você ou vai comprar algo ou está de saída.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Por favor, não me mate, apenas me ouça. Eu era antes Capitão dos Cavaleiros \"\n\"do Rei Leoric, defendendo as leis destas terras com justiça e honra. Então a \"\n\"maldição sombria dele caiu sobre nós, pelo papel que tivemos em sua trágica \"\n\"morte. Enquanto meus companheiros Cavaleiros sucumbiam a seu destino \"\n\"perverso, eu fugi da câmara funerária do Rei, buscando algum modo de me \"\n\"libertar da Maldição. Eu falhei...\\n\"\n\" \\n\"\n\"Eu ouvi falar de um Elixir Dourado que removeria a Maldição e permitiria que \"\n\"a minha alma descansasse, mas eu não fui capaz de encontrá-lo. Minha força \"\n\"está minguando, e com ela o que resta da minha humanidade. Por favor ajude-\"\n\"me e encontre o Elixir. Eu recompensarei os seus esforços - eu juro pela \"\n\"minha honra.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Você não achou o Elixir Dourado. Temo estar condenado pelo resto da \"\n\"eternidade. Por favor, continue tentando...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Você salvou a minha alma da danação, e por isso estou agora em dívida com \"\n\"você. Se houver alguma forma pela qual eu possa lhe recompensar do além-\"\n\"túmulo eu a encontrarei, mas, por agora, tome o meu elmo. Na jornada que \"\n\"estou prestes a seguir ele terá pouca serventia. Que lhe proteja contra os \"\n\"poderes sombrios abaixo. Vá com a Luz, meu(inha) amigo(a)...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold fala da Bigorna da Fúria, um artefato lendário há muito procurado, \"\n\"mas nunca achado. Esculpido a partir dos ossos metálicos dos demônios da \"\n\"Cova de Navalhas, a Bigorna da Fúria foi fundida em torno das caveiras dos \"\n\"cinco mais poderosos magos do Mundo Inferior. Entalhada com runas de poder e \"\n\"caos, qualquer arma ou armadura forjada sobre esta Bigorna será imersa no \"\n\"reino no Caos, sendo imbuída com propriedades mágicas. Dizem que a natureza \"\n\"imprevisível do Caos dificulta saber qual será o resultado dessa forja...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Não acha que Griswold seria uma pessoa melhor para se perguntar sobre isto? \"\n\"Ele é bem acessível, você sabe.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Se você estivesse buscando informações sobre o Pilão da Cura ou o Cálice \"\n\"Prateado da Purificação, eu poderia lhe ajudar, meu(inha) amigo(a). Contudo, \"\n\"neste assunto, você será melhor servido se falar com Griwold ou Cain.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"O pai de Griswold costumava contar para alguns de nós, quando éramos \"\n\"crianças, sobre uma bigorna gigante que era usada para fazer armas potentes. \"\n\"Ele disse que quando um machado batia nesta bigorna, o chão tremia em grande \"\n\"fúria. Sempre que a terra se mexe, eu lembro desta história.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Saudações! É sempre um prazer ver um de meus melhores clientes! Eu sei que \"\n\"você esteve se aventurando mais fundo no Labirinto, e há uma história que me \"\n\"contaram que você pode achar que vale o tempo de ouvi-la...\\n\"\n\" \\n\"\n\"Um dos homens que voltou do Labirinto me contou sobre uma bigorna mística \"\n\"pela qual passou durante sua fuga. A descrição que deu me lembrou de lendas \"\n\"que ouvi na juventude sobre uma ardente Forja Infernal, onde poderosas armas \"\n\"mágicas são fabricadas. A lenda diz que nas profundezas da Forja Infernal \"\n\"repousava a Bigorna da Fúria! Esta Bigorna continha dentro dela a própria \"\n\"essência do demoníaco Mundo Inferior...\\n\"\n\" \\n\"\n\"Dizem que qualquer arma construída sobre a ardente Bigorna é imbuída com \"\n\"grandes poderes. Se esta bigorna é de fato a Bigorna da Fúria, eu posso \"\n\"conseguir fazer para você uma arma capaz de derrotar mesmo o senhor mais \"\n\"sombrio do Inferno! \\n\"\n\" \\n\"\n\"Encontre-a para mim e eu começarei os trabalhos!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Nada ainda, né? Bom, continue procurando. Uma arma forjada sobre a Bigorna \"\n\"pode ser a sua melhor esperança, e tenho certeza de que posso fazer para \"\n\"você uma arma de proporções lendárias.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Mal posso acreditar! Esta é a Bigorna da Fúria - bom trabalho, meu(inha) \"\n\"amigo(a). Agora iremos mostrar para esses desgraçados que não há armas no \"\n\"Inferno mais letais do que as feitas pelos homens! Tome isto e que a Luz lhe \"\n\"proteja.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold não pode vender a bigorna dele. O que ele faria depois? E eu também \"\n\"ficaria irritado se alguém pegasse a minha bigorna!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Há muitos artefatos dentro do Labirinto que detém poderes além da \"\n\"compreensão dos mortais. Alguns deles possuem um poder fantástico que pode \"\n\"ser usado tanto para a Luz como para as Trevas. Colocar a Bigorna em \"\n\"segurança pode mudar o curso da Guerra do Pecado em direção à Luz.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Se você encontrar esse artefato para Griswold, poderia dar uma séria \"\n\"esfriada nos meus negócios por aqui. Hmm, você nunca vai achá-lo.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"A Passagem de Sangue e o Salão de Fogo são lugares de origem mística. Onde \"\n\"quer que resida este livro que você leu, é certamente um local de grande \"\n\"poder.\\n\"\n\" \\n\"\n\"Lendas falam de um pedestal entalhado em pedra obsidiana e com uma poça de \"\n\"sangue fervente no topo de sua superfície incrustada de ossos. Há também \"\n\"alusões a Pedras de Sangue que abrirão uma porta que guarda um tesouro \"\n\"antigo...\\n\"\n\" \\n\"\n\"A natureza deste tesouro é coberta de especulações, meu(inha) amigo(a), mas \"\n\"dizem que o antigo herói Arkaine pôs a santa armadura Bravura em um recinto \"\n\"secreto. Arkaine foi o primeiro mortal a virar o jogo da Guerra do Pecado e \"\n\"perseguir as legiões das trevas de volta aos Infernos Ardentes.\\n\"\n\" \\n\"\n\"Logo antes de Arkaine morrer, sua armadura foi escondida em uma câmara \"\n\"secreta. Dizem que quando sua armadura santa for mais uma vez necessária, um \"\n\"herói se erguerá para vestir a Bravura mais uma vez. Talvez seja você...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Toda criança ouve a história do guerreiro Arkaine e sua armadura mística \"\n\"conhecida como Bravura. Se você puder encontrar onde ela repousa, estará bem \"\n\"protegido(a) contra o mal dentro do Labirinto.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... Soa como algo de que eu deveria lembrar, mas estive tão ocupado \"\n\"aprendendo novas curas e criando elixires melhores que eu devo ter \"\n\"esquecido. Peço desculpas...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"A história da armadura mágica chamada Bravura é algo que frequentemente \"\n\"ouvia os garotos falarem sobre. É melhor perguntar a algum dos homens na \"\n\"vila.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"A armadura conhecida como Bravura pode ser o que vai inclinar a balança a \"\n\"seu favor. Eu vou lhe contar que muitos procuraram por ela - incluindo eu \"\n\"mesmo. Arkaine a escondeu bem, meu(inha) amigo(a), e será necessário mais do \"\n\"que um pouco de sorte para desvendar os segredos que a mantiveram oculta por \"\n\"todos esses tantos anos.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Caso encontre essas Pedras de Sangue, use-as com cuidado. \\n\"\n\" \\n\"\n\"O caminho é repleto de perigos e sua única esperança repousa dentro da sua \"\n\"autoconfiança.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Você pretende encontrar a armadura conhecida como Bravura? \\n\"\n\" \\n\"\n\"Ninguém jamais descobriu onde Arkaine guardou a coisa, e se meus contatos \"\n\"não puderam achá-la, eu também duvido seriamente que você a encontre.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Eu conheço apenas uma lenda que fala de um guerreiro tal como você \"\n\"descreveu. Sua história é encontrada dentro de crônicas antigas da Guerra do \"\n\"Pecado...\\n\"\n\" \\n\"\n\"Manchado por mil anos de guerra, sangue e morte, o Senhor da Guerra \"\n\"Sangrenta tem os pés sobre uma montanha de suas vítimas destroçadas. Sua \"\n\"lâmina sombria grita uma maldição negra para os viventes; um convite \"\n\"torturado para qualquer um que queira se opor a este Carrasco do Inferno.\\n\"\n\" \\n\"\n\"Também está escrito que, embora ele tenha sido antes um mortal que lutou ao \"\n\"lado da Legião das Trevas durante a Guerra do Pecado, ele perdeu sua \"\n\"humanidade para sua fome insaciável por sangue.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Temo não ter ouvido nada sobre um guerreiro tão cruel, bom(a) mestre(a). Eu \"\n\"espero que você não tenha que enfrentá-lo, pois ele parece ser extremamente \"\n\"perigoso.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain seria capaz de lhe contar muito mais sobre algo assim do que eu jamais \"\n\"desejaria saber.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Se você vai batalhar contra um oponente tão feroz, que a Luz seja sua guia e \"\n\"defensora. Manterei você em meus pensamentos.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Lendas sombrias e terríveis cercam o Senhor da Guerra Sangrenta. Esteja bem \"\n\"preparado(a), meu(inha) amigo(a), porque ele não demonstra piedade ou \"\n\"limites.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Você sempre tem que falar sobre sangue? Quero saber sobre as flores, os \"\n\"raios de sol e aquela garota bonita que traz as bebidas. Escute aqui, \"\n\"amigo(a) - você está obcecado(a), sabia?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Sua proeza com a lâmina é impressionante e ele viveu por milhares de anos \"\n\"conhecendo apenas a guerra. Peço perdão... Eu não consigo enxergar se você \"\n\"irá derrotá-lo.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Eu nunca lidei com esse Comandante de que você está falando, mas ele parece \"\n\"estar usando muitas espadas. Não me importaria em fornecer para os exércitos \"\n\"dele...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Minha lâmina canta por seu sangue, mortal, e, por meus mestre sombrios, a \"\n\"ela isto não será negado.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold fala da Pedra Celestial que estava destinada para o enclave \"\n\"localizado no leste. Ela estava sendo levada para maiores estudos lá. Esta \"\n\"pedra brilhava com uma energia que de algum modo concedia uma visão além \"\n\"daquela que uma pessoa normal poderia possuir. Eu não sei que segredos ela \"\n\"carrega, meu(inha) amigo(a), mas encontrar esta pedra poderia certamente se \"\n\"mostrar algo muito valioso.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"A caravana parou aqui para pegar alguns suprimentos para sua jornada rumo ao \"\n\"leste. Eu lhes vendi uma boa variedade de frutas frescas e algumas \"\n\"excelentes molejas que Garda havia acabado de assar. É uma pena o que \"\n\"aconteceu com eles...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Eu não sei o que é que eles pensavam que poderiam ver com aquela rocha, mas \"\n\"lhe digo isto. Se rochas estão caindo do céu, é melhor você ter cuidado!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Bom, uma caravana de algumas pessoas muito importantes realmente parou por \"\n\"aqui, mas isso foi há um bom tempo atrás. Eles tinham sotaques estranhos e \"\n\"estavam começando uma longa jornada, pelo que lembro. \\n\"\n\" \\n\"\n\"Eu não vejo como você poderia esperar encontrar qualquer coisa que eles \"\n\"estivessem carregando.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Fique aqui por um momento - eu tenho uma história que você pode achar \"\n\"interessante. Uma caravana que estava em viagem para os reinos orientais \"\n\"passou por aqui há algum tempo. Supostamente carregava um pedaço dos céus \"\n\"que caiu na terra! A caravana foi emboscada por cavaleiros encapuzados logo \"\n\"ao norte daqui, ao longo da estrada. Eu vasculhei os destroços por esta \"\n\"rocha do céu, mas não a achei em lugar algum. Caso a encontre, acredito que \"\n\"posso construir algo útil a partir dela.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Ainda estou esperando que você me traga aquela pedra dos céus. Eu sei que \"\n\"posso fazer algo poderoso com ela.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Deixe-me ver isso - sim... sim, é como eu acreditava. Dê-me um momento...\\n\"\n\" \\n\"\n\"Ah, aqui está. Eu encaixei pedaços da pedra dentro de um anel de prata que \"\n\"meu pai havia me deixado. Espero que lhe sirva bem.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Eu tinha um anel bonito; era um bem caro, com azul e verde e vermelho e \"\n\"prata. Mas não lembro o que aconteceu com ele. Realmente sinto falta daquele \"\n\"anel...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"A Pedra do Céu é realmente muito poderosa, e se fosse qualquer um menos \"\n\"Griswold que lhe pedisse para encontrá-la, eu impediria. Ele irá usufruir \"\n\"dos poderes dela e seu uso será para o bem de todos nós.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Se alguém pode fazer algo a partir daquela rocha, é Griswold. Ele sabe o que \"\n\"está fazendo, e por mais que eu tente roubar seus clientes, respeito a \"\n\"qualidade do trabalho dele.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"A bruxa Ádria busca um cogumelo negro? Eu sei tanto sobre Cogumelos Negros \"\n\"quanto sei sobre Arenques Vermelhos. Talvez Pepin, o Curandeiro, possa lhe \"\n\"contar mais, mas isto é algo que não pode ser encontrado em nenhuma das \"\n\"minhas histórias ou livros.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Eu só vou dizer isso. Tanto Garda como eu nunca, NUNCA serviríamos cogumelos \"\n\"negros para nossos honrados clientes. Se Ádria quiser alguns cogumelos no \"\n\"ensopado, é problema dela, mas eu não tenho como lhe ajudar a achar. \"\n\"Cogumelos negros... que nojo!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"A bruxa me contou que você estava procurando por um cérebro de demônio para \"\n\"me ajudar a criar meu elixir. Seria de grande valia para mim e para os \"\n\"muitos que foram feridos por essas bestas sórdidas, se eu puder simplesmente \"\n\"desvendar os segredos que suspeito que sua alquimia detém. Se puder remover \"\n\"o cérebro de um demônio quando matá-lo, eu ficaria grato se puder trazê-lo \"\n\"para mim.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Excelente, isto é exatamente o que eu queria. Consegui terminar o elixir sem \"\n\"isso, mas não machuca ter por aqui, para estudo. Você poderia por favor \"\n\"levar isto para a bruxa? Acredito que ela esteja esperando por ele.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Eu acho que Ogden pode ter alguns cogumelos no depósito. Por que não \"\n\"pergunta a ele?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Se Ádria não tem um desses, pode apostar que é algo raro de verdade. Eu não \"\n\"posso oferecer muito mais ajuda que isto, mas me soa como um... enorme, \"\n\"gargantuesco, inchado e inflado cogumelo! Bem, boas caças, imagino.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden prepara um cogumelo negro MAGNÍFICO, mas passo mal se beber aquilo. \"\n\"Escute, escute... aqui está o segredo - moderação é a chave!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"O que temos aqui? Interessante, parece ser um livro de reagentes. Mantenha \"\n\"os olhos abertos por um cogumelo negro. Deve ser razoavelmente grande e \"\n\"fácil de identificar. Caso o encontre, traga-o para mim, tudo bem?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"É um cogumelo grande e negro o que preciso. Agora vá e obtenha-o para mim \"\n\"para que eu possa usá-lo em uma beberagem especial na qual estou trabalhando.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Sim, isto vai ser perfeito para a mistura que estou criando. A propósito, o \"\n\"curandeiro está procurando pelo cérebro de um demônio, para tratar quem é \"\n\"afligido pelo veneno deles. Acredito que pretende fazer um elixir a partir \"\n\"disso. Se puder ajudá-lo a encontrar o que precisa, por favor veja se pode \"\n\"obter uma amostra do elixir para mim.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Por que você trouxe isto aqui? Eu não preciso de um cérebro de demônio neste \"\n\"momento. Eu preciso é de um pouco do elixir no qual o Curandeiro está \"\n\"trabalhando. Ele precisa desse órgão grotesco que você leva, só então me \"\n\"traga o elixir. Simples quando se para pra pensar, não acha?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"O quê? Agora é que você traz aquele elixir do curandeiro? Eu consegui \"\n\"terminar a minha infusão sem isso. Por que você não fica com ele...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Eu não tenho cogumelos de nenhum tamanho ou cor à venda. Que tal algo um \"\n\"pouco mais útil?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Então a lenda do Mapa é real. Até eu nunca acreditei em nada sobre ele! \"\n\"Imagino que chegou a hora de lhe dizer a verdade sobre quem eu sou, \"\n\"meu(inha) amigo(a). Eu não sou o que pareço ser...\\n\"\n\" \\n\"\n\"Meu verdadeiro nome é Deckard Cain, o Ancião, e eu sou o último descendente \"\n\"de uma antiga Irmandade que era dedicada a salvaguardar os segredos de um \"\n\"mal atemporal. Um mal que muito obviamente foi agora liberto...\\n\"\n\" \\n\"\n\"O mal contra o qual você se move é o sombrio Senhor do Terror. Ele é \"\n\"conhecido entre os homens mortais como Diablo. Ele é quem foi aprisionado \"\n\"dentro do Labirinto há muitos séculos. O Mapa que você agora possui foi \"\n\"criado eras atrás para marcar o momento em que Diablo se levantaria \"\n\"novamente de sua prisão. Quando as duas estrelas nesse mapa se alinharem, \"\n\"Diablo estará no auge de seu poder. Ele será simplesmente invencível...\\n\"\n\" \\n\"\n\"Você está agora em uma corrida contra o tempo, meu(inha) amigo(a)! Encontre \"\n\"Diablo antes que as estrelas se alinhem, pois talvez nunca mais tenhamos \"\n\"outra chance de livrar o mundo de seu mal!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Nosso tempo está acabando! Eu sinto os poderes sombrios dele crescendo e \"\n\"apenas você pode impedi-lo de conquistar sua potência completa.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Tenho certeza que você deu o seu melhor, mas temo que mesmo sua força e sua \"\n\"determinação não serão o suficiente. Diablo está agora no auge de seus \"\n\"poderes terrenos, e você vai precisar de toda a sua coragem e força para \"\n\"derrotá-lo. Que a Luz lhe proteja e lhe guie, meu(inha) amigo(a). Eu \"\n\"ajudarei de todas as formas que eu puder.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Se a bruxa não pode ajudar e lhe sugere falar com Cain, o que lhe faz crer \"\n\"que eu saberia de alguma coisa? Esse parece ser um assunto muito sério. Você \"\n\"deve se apressar e falar com o Contador de Histórias como sugeriu Ádria.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Eu não consigo entender muito do que está escrito neste mapa, mas talvez \"\n\"Ádria ou Cain possam lhe ajudar a decifrar sobre o que isto se refere. \\n\"\n\" \\n\"\n\"Eu consigo ver que é um mapa das estrelas em nosso céu, porém mais do que \"\n\"isso está além dos meus talentos.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"A melhor pessoa para se perguntar sobre esse tipo de coisa seria o nosso \"\n\"Contador de Histórias. \\n\"\n\" \\n\"\n\"Cain é muito instruído sobre escritos antigos, e esse é facilmente o pedaço \"\n\"de papel mais antigo que já vi.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Eu nunca vi um mapa desse tipo antes. Onde você o conseguiu? Embora eu não \"\n\"tenha ideia de como ler isso, Cain ou Ádria podem ser capazes de oferecer as \"\n\"respostas que procura.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Escuta aqui, chega perto. Eu não sei se você sabe o que eu sei, mas você \"\n\"realmente tem algo aqui. É um mapa.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Oh, temo que isso não seja de modo algum um bom presságio. Este mapa das \"\n\"estrelas prevê um grande desastre, mas seus segredos não são meus para \"\n\"contar. Chegou a hora de você ter uma conversa muito séria com o Contador de \"\n\"Histórias...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Estive procurando por um mapa, mas este certamente não é ele. Você deveria \"\n\"mostrá-lo a Ádria - ela provavelmente pode lhe contar o que é isso. Eu vou \"\n\"dizer uma coisa; parece velho, e velho geralmente significa valioso.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Por favoooor, não machuca. Não mata. Deixa vivo e outra vez trazer bom para \"\n\"você.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Algo para você eu fazendo. De novo, não mata Gharbad. Vive e dá coisa boa. \\n\"\n\" \\n\"\n\"Toma isso como prova eu tenho palavra...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Ainda nada! Quase pronto. \\n\"\n\" \\n\"\n\"Muito poderoso, muito forte. Vive! Vive! \\n\"\n\" \\n\"\n\"Sem dor e promessa eu cumpro!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Isso bom demais para você. Muito Poderoso! Você quer - você pega!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"O quê?! Por que você está aqui? Todas estas interrupções são o bastante para \"\n\"deixar alguém insano. Aqui, tome isto e deixe-me trabalhar. Não me incomode \"\n\"mais!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Sua curiosidade será a sua morte!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Olá, meu(inha) amigo(a). Fique um pouco e escute...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Enquanto estiver se aventurando mais fundo dentro do Labirinto, poderá \"\n\"encontrar tomos de grande conhecimento escondidos por lá. \\n\"\n\" \\n\"\n\"Leia-os com cuidado porque podem lhe contar coisas que mesmo eu não poderia.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Eu conheço muitos mitos e lendas que podem conter respostas para perguntas \"\n\"que podem surgir em suas jornadas dentro do Labirinto. Se você se deparar \"\n\"com desafios e questões sobre as quais deseja ter conhecimento, busque-me e \"\n\"eu lhe contarei o que puder.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold - um homem de grande ação e grande coragem. Eu aposto que ele lhe \"\n\"contou sobre a vez em que ele entrou no Labirinto para salvar Wirt, contou? \"\n\"Ele sabe sua porção de coisas sobre os perigos que encontrou lá, porém, mais \"\n\"uma vez - você também. Ele é um artesão habilidoso, e se ele afirmar ser \"\n\"capaz de lhe ajudar de alguma forma, pode contar com sua honestidade e \"\n\"habilidade.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden possui e administra a Estalagem e Taverna Sol Nascente há quase quatro \"\n\"anos agora. Ele a comprou apenas alguns meses antes de tudo aqui ir para o \"\n\"Inferno. Ele e a sua esposa Garda não têm dinheiro para sair, já que \"\n\"investiram tudo que tinham em construir uma vida por aqui. Ele é um homem \"\n\"bom, com um profundo senso de responsabilidade.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Pobre Farnham. Ele é um lembrete inquietante da assembleia condenada que \"\n\"adentrou a Catedral com Lázarus naquele dia sombrio. Ele escapou com vida, \"\n\"mas sua coragem e muito de sua sanidade foram perdidas em algum abismo \"\n\"escuro. Hoje em dia, ele encontra conforto apenas no fundo de sua caneca, \"\n\"mas há ocasionais pedaços de verdade enterrados em seus balbuceios \"\n\"constantes.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"A bruxa, Ádria, é uma anomalia aqui em Tristram. Ela chegou pouco depois da \"\n\"Catedral ser profanada, enquanto a maioria dos outros estavam fugindo. Ela \"\n\"construiu uma pequena cabana no limite da cidade, aparentemente da noite \"\n\"para o dia, e tem acesso a muitos artefatos arcanos estranhos e tomos de \"\n\"conhecimento que mesmo eu nunca sequer vi antes.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"A história de Wirt é assustadora e trágica. Ele foi tomado dos braços da mãe \"\n\"e arrastado para dentro do Labirinto pelos pequenos e sórdidos demônios que \"\n\"carregam lanças terríveis. Houve muitas outras crianças levadas naquele dia, \"\n\"incluindo o filho do Rei Leoric. Os Cavaleiros do palácio desceram para lá, \"\n\"mas nunca retornaram. O Ferreiro encontrou o garoto, mas só depois de as \"\n\"bestas imundas já terem começado a torturá-lo para seus prazeres sádicos.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Eu conto com ele como um amigo verdadeiro - talvez o mais próximo \"\n\"que tenho por aqui. Ele é um pouco confuso às vezes, mas nunca existiu uma \"\n\"alma mais cuidadosa e atenciosa. Seus conhecimentos e habilidades são \"\n\"igualados por poucos, e sua porta está sempre aberta.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian é uma boa mulher. Muito adorada por seu bom humor e sua risada \"\n\"fácil, tem um lugar especial em meu coração. Ela permanece na taverna para \"\n\"ajudar a sua avó idosa, que está doente demais para viajar. Eu às vezes temo \"\n\"pela segurança dela, mas sei que qualquer homem na vila preferiria morrer a \"\n\"vê-la machucada.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Saudações, Bom(a) mestre(a). Bem-vindo(a) à Taverna do Sol Nascente!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Muitos aventureiros agraciaram as mesas de minha taverna, e dez vezes mais \"\n\"foram as histórias contadas, ao lado do mesmo tanto de cerveja. A única \"\n\"coisa sobre a qual já ouvi eles concordarem foi este velho ditado. Talvez \"\n\"lhe ajude. Você pode cortar a carne, mas deve esmagar o osso.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Griswold, o Ferreiro, é extremamente instruído sobre armas e armaduras. Se \"\n\"alguma vez você precisar de algo feito por seu equipamento, ele é \"\n\"definitivamente o homem para isso.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham passa tempo demais aqui, afogando suas mágoas em cerveja barata. Eu \"\n\"o faria ir embora, mas ele sofreu tanto durante o tempo em que esteve no \"\n\"Labirinto.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Ádria é sábia para além da idade que possui, mas devo admitir - ela me \"\n\"assusta um pouco. \\n\"\n\" \\n\"\n\"Bem, não importa. Se você alguma vez precisar negociar itens de feitiçaria, \"\n\"ela mantém uma cabana estranhamente bem abastecida, logo do outro lado do \"\n\"rio.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Se você quiser saber mais sobre a história desta vila, o Contador de \"\n\"Histórias Cain sabe um bocado sobre o passado.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt é um canalha e um malandrinho. Ele está sempre se metendo em confusão e \"\n\"não me surpreendo com o que aconteceu com ele. \\n\"\n\" \\n\"\n\"Provavelmente foi perambular por algum lugar que não deveria. Eu sinto pena \"\n\"do garoto, mas eu não suporto as companhias que ele mantém.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin é um bom homem - e certamente o mais generoso da vila. Ele está sempre \"\n\"atendendo às necessidades dos outros, mas problemas de um tipo ou de outro \"\n\"parecem segui-lo aonde quer que ele vá...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, minha atendente? Se não fosse por seu grande senso de dever para \"\n\"com a avó, ela teria fugido daqui há muito tempo. \\n\"\n\" \\n\"\n\"Os Céus sabem que eu implorei para que ela partisse, dizendo a ela que eu \"\n\"cuidaria da idosa, mas ela é doce e cuidadosa demais para fazer isso.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"O que lhe aflige, meu(inha) amigo(a)?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Eu fiz uma descoberta muito interessante. Diferente de nós, as criaturas no \"\n\"Labirinto podem se curar sem o auxílio de poções ou magia. Caso machuque \"\n\"algum monstro, certifique-se de que está morto ou ele poderá muito bem se \"\n\"regenerar.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Antes de ser tomada por, bem, o que quer que esteja espreitando abaixo, a \"\n\"Catedral era um lugar de grande aprendizado. Há muitos livros a serem \"\n\"encontrados lá. Caso encontre algum, deveria ler bem, pois vários guardam \"\n\"segredos sobre o funcionamento do Labirinto.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold sabe tanto sobre a arte da guerra quanto sei da arte da cura. Ele é \"\n\"um mercador astuto, mas seu trabalho não fica atrás de nenhum outro. Oh, \"\n\"imagino que pode ser porque ele é o único ferreiro que sobrou por aqui.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain é um amigo de verdade e um inteligente sábio. Ele mantém uma vasta \"\n\"biblioteca e tem a habilidade nata de discernir a verdadeira natureza de \"\n\"muitas coisas. Se alguma vez tiver qualquer pergunta, ele é a pessoa para \"\n\"isso.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Mesmo as minhas habilidades não foram capazes de curar Farnham por inteiro. \"\n\"Oh, eu consegui sarar seu corpo, mas sua mente e espírito estão além de \"\n\"qualquer coisa que eu possa fazer.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Enquanto eu uso algumas formas limitadas de magia para criar as poções e \"\n\"elixires que armazeno aqui, Ádria é a verdadeira feiticeira. Ela parece \"\n\"nunca dormir e sempre tem acesso a muitos tomos e artefatos místicos. \"\n\"Acredito que sua cabana pode ser muito mais do que a palhoça que parece por \"\n\"fora, mas eu nunca tive a chance de entrar no lugar.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Pobre Wirt. Eu fiz todo o possível pela criança, mas eu sei que ele despreza \"\n\"aquela estaca de madeira que fui forçado a fixar em sua perna. Suas feridas \"\n\"são horrendas. Ninguém - especialmente uma criança tão nova - deveria sofrer \"\n\"da forma que ele sofreu.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Eu realmente não entendo por que Ogden continua aqui em Tristram. Ele sofre \"\n\"de uma leve condição nervosa, mas é um homem inteligente e trabalhador, que \"\n\"poderia se dar bem aonde quer que fosse. Imagino que seja o medo dos muitos \"\n\"assassinatos que acontecem nos campos ao redor daqui, ou talvez os desejos \"\n\"de sua esposa sejam de manter ele e sua família onde estão.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"A atendente de Ogden é uma garota doce. Sua avó está bastante doente e sofre \"\n\"de alucinações. \\n\"\n\" \\n\"\n\"Ela afirma que são visões, mas não tenho provas disso, de um jeito ou de \"\n\"outro.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Bom dia! Como posso te servir?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Minha avó sonhou que você viria e falaria comigo. Ela tem visões, sabe, e \"\n\"pode ver o futuro.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"A mulher na fronteira da cidade é uma bruxa! Ela parece boa o suficiente e \"\n\"seu nome, Ádria, é bastante agradável aos ouvidos, mas tenho muito medo \"\n\"dela. \\n\"\n\" \\n\"\n\"Seria preciso alguém bem corajoso, como você, para ir ver o que ela está \"\n\"fazendo por lá.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Nosso Ferreiro é um ponto de orgulho para o povo de Tristram. Ele não só é \"\n\"um mestre artesão que já ganhou muitos campeonatos dentro de sua guilda, \"\n\"como já recebeu elogios do próprio Rei Leoric - que sua alma descanse em \"\n\"paz. Griswold também é um grande herói; apenas pergunte a Cain.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain tem sido o Contador de Histórias de Tristram desde que consigo me \"\n\"lembrar. Ele sabe tanto, e pode lhe contar simplesmente qualquer coisa sobre \"\n\"todas as coisas.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham é um beberrão que enche a barriga com cerveja e a orelha de todos os \"\n\"outros com asneiras. \\n\"\n\" \\n\"\n\"Eu sei que tanto Pepin como Ogden sentem simpatia por ele, mas eu fico muito \"\n\"frustrada ao vê-lo deslizar mais e mais para um torpor confuso a cada noite \"\n\"que passa.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin salvou a vida da minha avó e eu sei que nunca poderei retribuí-lo o \"\n\"bastante por isso. A capacidade dele de curar qualquer doença é mais \"\n\"poderosa do que a espada mais forte e mais misteriosa do que qualquer \"\n\"feitiço que você possa pensar. Caso em algum momento precise de cura, Pepin \"\n\"pode lhe ajudar.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Eu cresci com a mãe de Wirt, Canace. Embora ela tenha se ferido apenas um \"\n\"pouco quando aquelas criaturas horrendas o roubaram, ela nunca se recuperou. \"\n\"Eu acho que ela morreu de coração partido. Wirt se tornou um jovem de \"\n\"espírito mesquinho, buscando apenas lucrar com o suor dos outros. Eu sei que \"\n\"ele sofreu e viu horrores que eu não posso sequer imaginar, mas um pouco \"\n\"dessa escuridão ainda paira sobre ele.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden e sua esposa levaram a mim e a minha avó para a casa deles e ainda me \"\n\"deixaram ganhar algumas peças de ouro trabalhando na estalagem. Eu devo \"\n\"tanto a eles, e espero um dia sair deste lugar e ajudá-los a começar um \"\n\"grande hotel no leste.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Bom, o que posso fazer por você?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Se está procurando por uma boa arma, deixe-me lhe mostrar isto. Pegue uma \"\n\"arma básica de bater, como uma maça. Funciona muito bem contra a maioria dos \"\n\"horrores implacáveis lá embaixo, e não há nada melhor para estilhaçar \"\n\"esqueletinhos magrelos!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"O machado? Sim, é uma boa arma, equilibrado contra qualquer inimigo. Veja \"\n\"como corta o ar, e então imagine a cabeça de um demônio gordo em seu \"\n\"caminho. Tenha em mente, contudo, que ele é lento de brandir - mas pense em \"\n\"um golpe pesado!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Veja esse gume, esse equilíbrio. Uma espada nas mãos certas, e contra o \"\n\"inimigo certo, é a mestra de todas as armas. Sua lâmina afiada tem pouco a \"\n\"cortar ou perfurar em mortos-vivos, mas contra inimigos vivos e respirando, \"\n\"uma espada é o que melhor cortará suas carnes!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Suas armas e armadura mostrarão os sinais de suas lutas contra as Trevas. Se \"\n\"as trouxer para mim, com um pouco de trabalho e uma forja quente, posso \"\n\"restaurá-las às suas melhores formas.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Enquanto eu tenho que praticamente contrabandear os metais e ferramentas de \"\n\"que preciso das caravanas que contornam as fronteiras de nossa cidade \"\n\"condenada, aquela bruxa, Ádria, sempre parece conseguir o que precisa. Se eu \"\n\"soubesse só um pouco sobre como usar magia como ela usa, eu poderia criar \"\n\"coisas realmente inacreditáveis.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian é uma boa jovem. Pena que sua avó esteja com tão pouca saúde, se não \"\n\"eu conseguiria levar ambas para fora daqui em uma das caravanas comerciais.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Às vezes acho que Cain fala demais, mas creio que este seja a missão dele em \"\n\"vida. Se eu pudesse controlar o aço como ele controla sua orelha, poderia \"\n\"fazer uma roupa de placas reais boa o suficiente para um Imperador!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Eu estava com Farnham na noite em que Lázarus nos levou para o Labirinto. \"\n\"Nunca mais vi o Arcebispo, e eu poderia não ter sobrevivido se Farnham não \"\n\"estivesse ao meu lado. Temo que o ataque tenha deixado sua alma tão \"\n\"debilitada quanto, bem, outro deixou a minha perna. Não posso lutar esta \"\n\"batalha por ele agora, mas se pudesse lutaria.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Um homem bom, que coloca as necessidades dos outros acima das dele próprio. \"\n\"Você não vai encontrar ninguém que sobrou em Tristram - ou em qualquer outro \"\n\"lugar, para ser sincero - que tenha algo de ruim a falar sobre o Curandeiro.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Aquele rapaz vai se meter em encrencas sérias... de novo, imagino que posso \"\n\"dizer. Eu tentei estimulá-lo a trabalhar aqui e aprender uma profissão \"\n\"honesta, mas ele prefere os lucros altos de negociar bens de origem \"\n\"duvidosa. Eu não tenho isso contra ele depois do que lhe aconteceu, mas \"\n\"realmente desejo que ele ao menos tenha cuidado.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"O Estalajadeiro tem poucos clientes e nenhuma forma real de lucrar. Ele \"\n\"consegue segurar as pontas provendo comida e alojamento para quem \"\n\"ocasionalmente se desvia através da cidade, mas as chances de que fujam \"\n\"furtivamente pela noite são iguais às de que paguem. Se não fosse pelas \"\n\"reservas de grãos e carnes secas que ele manteve em seu porão, nossa, a \"\n\"maioria de nós teria morrido durante aquele primeiro ano em que os campos \"\n\"inteiros foram invadidos por demônios.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Um camarada não pode beber em paz?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"A garota que traz as bebidas? Ah, sim, que moça bonita. Muito legal, também.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Por que aquela megera velha não faz algo, pra variar? Certo, certo, ela tem \"\n\"coisas, mas me escute aqui... ela é anormal. Eu nunca a vi comer ou beber - \"\n\"e não dá para confiar em alguém que não bebe ao menos um pouquinho.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain não é o que ele diz ser. Certo, certo, ele conta boas histórias... \"\n\"algumas são bem assustadoras ou engraçadas... Mas acho que ele sabe mais do \"\n\"que ele sabe que sabe.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Bom e velho Griswold. Eu o amo como a um irmão! Lutamos juntos, \"\n\"você sabe, lá quando... nós... Lázarus...  Lázarus... Lázarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, eu gosto de Pepin. Ele realmente se esforça, sabe. Escute aqui, você \"\n\"deveria realmente ir conhecê-lo. Um camarada bom daqueles, com gente sempre \"\n\"querendo sua ajuda. Ei, acho que isso é meio como você, hein, herói(na)? Eu \"\n\"fui um herói também...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt é uma criança com mais problemas até do que eu, e eu sei tudo sobre \"\n\"problemas. Escute aqui - aquela criança tem bons negócios, mas ela já esteve \"\n\"lá, sabe? Perdeu uma perna! Precisa andar por aí em um pedaço de madeira. \"\n\"Muito triste, muito triste...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden é o melhor homem da cidade. Não acho que sua esposa goste muito de \"\n\"mim, mas enquanto ela continuar trazendo cerveja dos barris, gostarei dela \"\n\"sem problemas. Parece que estive passando mais tempo com Ogden do que a \"\n\"maioria, mas ele é tão bom comigo...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Quero lhe dizer algo, porque eu sei tudo sobre essas coisas. É a minha \"\n\"especialidade. Esta aqui é a melhor... aaaaaa melhor! A outra cerveja não é \"\n\"tão boa desde que aqueles cachorros estúpidos...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Ninguém nunca me es... escuta. Em algum lugar - não tenho certeza - mas em \"\n\"algum lugar sob a igreja há uma pilha inteira de ouro. Brilhante e reluzente \"\n\"e só esperando que alguém vá lá pegá-la.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Eu sei que você tem suas próprias ideias e sei que você não vai acreditar \"\n\"nisto, mas essa arma que você leva aí - simplesmente não é boa contra \"\n\"aqueles brutamontes! Ah, eu não me importo com o que Griswold diz, eles não \"\n\"conseguem fazer nada como o que faziam nos velhos dias...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Se eu fosse você... e não sou... mas se eu fosse, eu venderia tudo isso que \"\n\"você tem e daria o fora daqui. Aquele garoto lá... Ele sempre tem alguma \"\n\"coisa boa, mas você precisa dar ouro para ele, se não ele nem mostra o que \"\n\"tem.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Eu sinto uma alma sedenta por respostas...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Sabedoria é conquistada, não dada. Se descobrir um tomo de conhecimento, \"\n\"devore suas palavras. Caso já tenha conhecimento dos mistérios arcanos \"\n\"descritos em um livro, lembre-se - esse nível de domínio sempre pode se \"\n\"expandir.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"O maior poder é muitas vezes o que dura menos. Você pode encontrar antigas \"\n\"palavras de poder escritas em rolos de pergaminho. A força desses \"\n\"pergaminhos está na capacidade de tanto aprendizes quanto peritos lançar \"\n\"esses poderes com igual habilidade. A fraqueza deles é que precisam antes \"\n\"ser lidos em voz alta e não podem ser mantidos prontos na sua mente. Saiba \"\n\"também que esses pergaminhos podem ser lidos apenas uma vez, então use-os \"\n\"com cuidado.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Embora o calor do sol esteja além de qualquer medida, a mera chama de uma \"\n\"vela é um perigo maior. Nenhuma energia, não importa o quão grande seja, \"\n\"pode ser usada sem o foco adequado. Para muitos feitiços, Cajados \"\n\"enfeitiçados podem ser carregados com energias mágicas, por diversas vezes. \"\n\"Eu tenho a habilidade de restaurar seus poderes - mas saiba que nada é feito \"\n\"sem um preço.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"A soma do nosso conhecimento está na soma das pessoas. Caso encontre um \"\n\"livro ou pergaminho que não consiga decifrar, não hesite em trazê-lo até \"\n\"mim. Se eu conseguir entendê-lo, compartilharei o que descobrir.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Para um homem que conhece apenas Ferro, não há mágica maior do que o Aço. O \"\n\"ferreiro Griswold é mais feiticeiro do que ele sabe. Sua habilidade de \"\n\"combinar fogo e metal é inigualável nestas terras.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Corrupção tem a força do engano, mas a inocência detém o poder da pureza. A \"\n\"jovem mulher Gillian tem um coração puro, colocando as necessidades de sua \"\n\"matriarca acima das próprias. Ela teme a mim, mas é apenas por não me \"\n\"compreender.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Um baú aberto na escuridão não detém tesouro maior do que se aberto na luz. \"\n\"O Contador de Histórias Cain é um enigma, mas apenas para quem não observa \"\n\"com atenção. Seu conhecimento do que jaz sob a catedral é muito maior do que \"\n\"ele mesmo se permite perceber.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Quanto mais alto puser a sua fé em um homem, mais distante ela terá que \"\n\"cair. Farnham perdeu sua alma, mas não para algum demônio. Ela foi perdida \"\n\"quando ele viu seus companheiros da cidade traídos pelo Arcebispo Lázarus. \"\n\"Ele tem conhecimento a ser colhido, mas você deve saber separar fato de \"\n\"fantasia.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"A mão, o coração e a mente podem executar milagres quando estão em perfeita \"\n\"harmonia. O curandeiro Pepin vê dentro do corpo de uma forma que mesmo eu \"\n\"não consigo. Sua habilidade de recuperar os doentes e feridos é ampliada por \"\n\"seu entendimento da criação de elixires e poções. Ele é um grande aliado que \"\n\"você tem em Tristram.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Há muito sobre o futuro que não podemos ver, mas, quando ele chegar, serão \"\n\"as crianças que o irão exercer. O garoto Wirt tem uma escuridão sobre sua \"\n\"alma, mas ele não representa ameaça alguma para a cidade ou seu povo. Suas \"\n\"negociações secretas com maltrapilhos e guildas obscuras de cidades próximas \"\n\"dão acesso a muitos aparatos que não podem ser encontrados facilmente em \"\n\"Tristram. Embora seus métodos possam ser repreensíveis, Wirt pode prover \"\n\"assistência para a sua batalha contra as Trevas que nos invadem.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Muros terrenos e tetos de palha não criam um lar. O estalajadeiro Ogden \"\n\"serve a um propósito maior nesta cidade do que muitos compreendem. Ele provê \"\n\"abrigo para Gillian e a matriarca dela, mantém qualquer que seja a vida que \"\n\"ainda sobra em Farnham, e provê uma âncora para todos que restaram na cidade \"\n\"ao que Tristram uma vez fora. Sua taverna, e os prazeres simples que ainda \"\n\"se pode encontrar lá, proveem um vislumbre de uma vida da qual as pessoas \"\n\"daqui se lembram. É essa memória que continua a alimentar as esperanças \"\n\"deles pelo seu sucesso.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... vem aqui...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Nem todos em Tristram terão um uso - ou mercado - para tudo o que você \"\n\"encontrar no labirinto. Nem mesmo eu, por mais difícil que seja de \"\n\"acreditar. \\n\"\n\" \\n\"\n\"Às vezes, só você será capaz de encontrar um propósito para algumas coisas.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Não confie em tudo que o bêbado diz. Muitas cervejas embaçaram sua visão e \"\n\"seu bom senso.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Caso não tenha percebido, eu não compro nada de Tristram. Eu sou um \"\n\"importador de bens de qualidade. Se quiser vender porcarias, terá que ir ver \"\n\"Griswold, Pepin ou aquela bruxa, Ádria. Tenho certeza de que aceitarão com \"\n\"facilidade qualquer coisa que levar para eles...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Eu creio que devo a minha vida ao ferreiro - o que quer que haja dela. \"\n\"Certo, Griswold me ofereceu ser aprendiz na ferraria, e ele é um cara legal \"\n\"o suficiente, mas eu nunca conseguiria dinheiro o suficiente para... Bom, \"\n\"digamos apenas que tenho planos definidos que precisarão de uma grande \"\n\"quantia de ouro.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Se eu fosse alguns anos mais velho, eu a banharia em todas as riquezas que \"\n\"eu pudesse reunir, e posso lhe garantir que consigo pôr as mãos em coisas \"\n\"muito boas. Gillian é uma bela garota, que deveria sair de Tristram assim \"\n\"que for seguro. Hmmm... talvez eu a leve comigo quando eu for...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain sabe demais. Ele me assusta muito - mais até do que aquela mulher do \"\n\"outro lado do rio. Ele fica me falando sobre o quão sortudo eu sou por estar \"\n\"vivo, e como a minha história foi prenunciada em lendas. Eu acho que ele \"\n\"está meio doido.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - aí está um homem com problemas sérios, e eu sei tudo sobre o quão \"\n\"sérios problemas podem ser. Ele confiou demais na integridade de um homem, e \"\n\"Lázarus o levou direto para as mandíbulas da morte. Ah, eu sei como é lá \"\n\"embaixo, então nem comece a me contar seus planos de destruir o mal que \"\n\"habita aquele Labirinto. Só tome cuidado com as suas pernas...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Desde que não precise de nada recosturado no lugar, o velho Pepin é o melhor \"\n\"que existe. \\n\"\n\" \\n\"\n\"Se eu tivesse tido algumas dessas poções que ele prepara, talvez ainda \"\n\"estivesse com a minha perna...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Ádria me incomoda de verdade. Certo, Cain é esquisito no que ele pode lhe \"\n\"contar sobre o passado, mas aquela bruxa pode enxergar dentro do seu \"\n\"passado. Ela também sempre tem algum jeito de conseguir o que precisa. Ádria \"\n\"põe as mãos em mais mercadorias do que eu já vi passar pelo Bazar do Rei \"\n\"durante o Alto Festival.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden é um tolo por ficar aqui. Eu poderia tirá-lo da cidade por um preço \"\n\"bastante razoável, mas ele insiste em tentar dar certo com aquela taverna \"\n\"estúpida. Pelo menos ele dá a Gillian um lugar onde trabalhar, e sua esposa \"\n\"Garda de fato faz uma torta de cordeiro esplêndida...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Para além do Salão de Heróis jaz a Câmara de Ossos. A morte eterna aguarda \"\n\"aqueles que queiram roubar os tesouros nesta sala protegidos. Assim fala o \"\n\"Senhor do Terror, e assim está escrito.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...e então, trancada além da Passagem de Sangue e após o Salão de Fogo, a \"\n\"Bravura aguarda pelo Herói de Luz para que desperte...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Eu posso ver o que não podes ver.\\n\"\n\"Visão turva e olhos a apodrecer.\\n\"\n\"Quando virares, lá já não estarão,\\n\"\n\"Sussurrando sua escondida canção.\\n\"\n\"Então vês o que não aconteceria,\\n\"\n\"Sombras andam onde luz haveria.\\n\"\n\"Fora da escuridão, fora de si,\\n\"\n\"A Câmara dos Cegos está aqui.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Os arsenais do Inferno são o lar do Senhor da Guerra Sangrenta. Em seu \"\n\"rastro jazem os corpos mutilados de milhares. Anjos e homens foram mutilados \"\n\"para cumprir seus sacrifícios sem fim para os Sombrios, que gritam por uma \"\n\"só coisa - sangue.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Prestai atenção e testemunhai as verdades que jazem aqui dentro, pois são o \"\n\"último legado dos Horadrim. Há uma guerra que se trava ainda agora, para \"\n\"além dos campos conhecidos - entre os reinos utópicos do Alto Céu e os \"\n\"abismos caóticos do Inferno Ardente. Esta guerra é conhecida como o Grande \"\n\"Conflito, e tem se espalhado e queimado por mais tempo do que qualquer \"\n\"estrela no céu. Nenhum dos lados impera por muito tempo, enquanto forças da \"\n\"Luz e das Trevas disputam constantemente pelo controle sobre toda a criação.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Prestai atenção e testemunhai as verdades que jazem aqui dentro, pois são o \"\n\"último legado dos Horadrim. Quando o Conflito Eterno entre o Alto Céu e o \"\n\"Inferno Ardente cai em solo mortal, chama-se então de a Guerra do Pecado. \"\n\"Anjos e Demônios caminham disfarçados por meio da humanidade, lutando em \"\n\"segredo, longe de olhos intrometidos dos mortais. Alguns mortais ousados e \"\n\"poderosos até mesmo se aliaram com um lado ou outro e ajudaram ao ditar o \"\n\"curso da Guerra do Pecado.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Prestai atenção e testemunhai as verdades que jazem aqui dentro, pois são o \"\n\"último legado dos Horadrim. Há quase trezentos anos, foi sabido que os Três \"\n\"Males Primordiais do Inferno Ardente misteriosamente vieram ao nosso mundo. \"\n\"Os Três Irmãos assolaram as terra do leste por décadas, enquanto a \"\n\"humanidade tremia em seu rastro. Nossa Ordem - os Horadrim - foi fundada por \"\n\"um grupo de magos secretos para caçar e capturar os Três Males de uma vez \"\n\"por todas.\\n\"\n\" \\n\"\n\"Os Horadrim originais capturaram os Três dentro de poderosos artefatos \"\n\"conhecidos como Pedras da Alma e as enterraram fundo abaixo das areias \"\n\"orientais. O terceiro Mal escapou à captura e fugiu para o oeste, com muitos \"\n\"dos Horadrim perseguindo-lhe. O Terceiro Mal - conhecido como Diablo, o \"\n\"Senhor do Terror - foi eventualmente capturado, sua essência posta em uma \"\n\"Pedra da Alma e enterrada dentro deste Labirinto.\\n\"\n\" \\n\"\n\"Estejas em aviso que a Pedra da Alma deve ser protegida da descoberta por \"\n\"aqueles que não forem da fé. Se Diablo for liberado, ele buscaria um corpo \"\n\"que pudesse facilmente controlar, uma vez que estaria muito fraco - talvez o \"\n\"de um velho ou o de uma criança.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Então se passou que houve uma grande revolução dentro do Inferno Ardente, \"\n\"conhecida como o Exílio Sombrio. Os Males Menores destituíram os Três Males \"\n\"Primordiais e baniram suas formas espirituais para o reino mortal. Os \"\n\"demônios Belial (O Senhor das Mentiras) e Azmodan (O Senhor do Pecado) \"\n\"lutaram para reivindicar o governo durante a ausência dos Três Irmãos. O \"\n\"Inferno inteiro se polarizou entre as facções de Belial e Azmodan, enquanto \"\n\"as forças do Alto Céu arietavam continuamente sobre os próprios Portões do \"\n\"Inferno.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Muitos demônios viajaram para o reino mortal em busca dos Três Irmãos. Estes \"\n\"demônios foram seguidos para o plano mortal por Anjos que os caçaram através \"\n\"das vastas cidades do Oriente. Os Anjos se aliaram com uma Ordem Secreta de \"\n\"magos mortais chamados de os Horadrim, que rapidamente se tornaram hábeis em \"\n\"caçar demônios. Também fizeram muitos inimigos sombrios nos Mundos \"\n\"Inferiores.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Então se passou que os Três Males Primordiais foram banidos na forma \"\n\"espiritual para o reino mortal e após semearem o caos através do Oriente por \"\n\"décadas, foram caçados pela amaldiçoada Ordem dos mortais Horadrim. Os \"\n\"Horadrim usaram artefatos conhecidos como Pedras da Alma para conter a \"\n\"essência de Mephisto, o Senhor do Ódio e de seu irmão Baal, o Senhor da \"\n\"Destruição. O irmão mais novo - Diablo, o Senhor do Terror - escapou para o \"\n\"ocidente.\\n\"\n\" \\n\"\n\"Eventualmente os Horadrim também capturaram Diablo dentro de uma Pedra da \"\n\"Alma, e o enterraram sob uma antiga e esquecida Catedral. Lá, o Senhor do \"\n\"Terror dorme e espera a hora de seu renascimento. Sabei vós que ele buscará \"\n\"um corpo de juventude e poder para possuir - um que seja inocente e \"\n\"facilmente controlado. Ele irá então se erguer para libertar seus Irmãos, e \"\n\"mais uma vez agitar as chamas da Guerra do Pecado...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Todo o louvor a Diablo - Senhor do Terror e Sobrevivente do Exílio Sombrio. \"\n\"Quando ele despertou de seu longo repouso, meu Senhor e Mestre falou comigo \"\n\"sobre segredos que poucos mortais conhecem. Ele me contou que os reinos do \"\n\"Alto Céu e os abismos do Inferno Ardente travam uma guerra eterna. Ele me \"\n\"revelou quais poderes trouxeram esta discórdia aos reinos dos homens. Meu \"\n\"Senhor chamou a esta batalha por este mundo e tudo o que aqui existe de a \"\n\"Guerra do Pecado.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Glória e Aprovação a Diablo - Senhor do Terror e Líder dos Três. Meu Senhor \"\n\"falou comigo de seus dois Irmãos, Mephisto e Baal, que foram banidos para \"\n\"este mundo há muito tempo. Meu Senhor deseja levar seu tempo e recuperar \"\n\"seus poderes impressionantes para que possa libertar seus cativos irmãos de \"\n\"suas tumbas abaixo das areias do oriente. Assim que meu Senhor libertar seus \"\n\"Irmãos, a Guerra do Pecado conhecerá mais uma vez a fúria dos Três.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Saudação e Sacrifício a Diablo - Senhor do Terror e Destruidor de Almas. \"\n\"Quando despertei meu Mestre de seu sono, ele tentou possuir uma forma \"\n\"mortal. Diablo tentou obter o corpo do Rei Leoric, mas meu Mestre estava \"\n\"demasiado fraco por seu aprisionamento. Meu Senhor precisava de uma simples \"\n\"e inocente âncora a este mundo, e portanto achou o garoto Albrecht perfeito \"\n\"para a tarefa. Enquanto o bom Rei Leoric foi enlouquecido pela possessão \"\n\"malsucedida de Diablo. Eu sequestrei seu filho Albrecht e o trouxe para \"\n\"diante de meu Mestre. Eu agora aguardo pelo chamado de Diablo e rezo que eu \"\n\"seja recompensado quando ele por fim emergir como o Senhor deste mundo.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Graças aos Deuses você voltou!\\n\"\n\"Muita coisa mudou desde que você morou aqui, meu(inha) amigo(a). Tudo estava \"\n\"pacífico até que cavaleiros sombrios vieram e destruíram nossa vila. Muitos \"\n\"foram abatidos ali mesmo onde estavam e aqueles que pegaram em armas foram \"\n\"assassinados ou levados como escravos - ou pior. A igreja no limiar da \"\n\"cidade foi profanada e está sendo usada para rituais sombrios. Os gritos que \"\n\"ecoam pela noite são inumanos, mas alguns de nossos aldeões ainda podem ter \"\n\"sobrevivido. Siga a trilha que está entre a minha taverna e a loja do \"\n\"ferreiro para encontrar a igreja e salvar quem puder. \\n\"\n\" \\n\"\n\"Talvez eu possa lhe contar mais se nos falarmos novamente. Boa sorte.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Mantenha sua missão. Encontrar um tesouro perdido não é fácil. Encontre um \"\n\"tesouro menos escondido. Vou deixá-lo com isso. Não deixe que as areias do \"\n\"tempo confundam sua busca.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"O quê?! Isso é uma tolice. Não há nenhum tesouro enterrado aqui em Tristram. \"\n\"Deixe-me ver isso! Olha, esses desenhos são imprecisos. Eles não encaixam \"\n\"com a nossa cidade. Eu me concentraria no que está sob a catedral e não no \"\n\"que está sob nossa camada superficial do solo.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Eu realmente não tenho tempo para discutir o mapa que você está procurando. \"\n\"Tenho muitas pessoas doentes que precisam da minha ajuda e da sua também.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"O outrora orgulhoso Iswall está preso nas profundezas da superfície deste \"\n\"mundo. Sua honra foi despojada e seu rosto alterado. Ele está preso em \"\n\"tormento imortal. Encarregado por ocultar a única coisa que poderia libertá-\"\n\"lo.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Aposto que Wirt viu você chegando e te pregou uma peça para rir de você mais \"\n\"tarde, quando você estivesse com o nariz na terra. Eu apenas ignoraria.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Houve um tempo em que esta cidade era uma parada frequente para viajantes de \"\n\"todos os lugares. Muita coisa mudou desde então. Mas as cavernas escondidas \"\n\"e os tesouros enterrados são fantasias comuns de qualquer criança. Wirt \"\n\"raramente se entrega a jogos juvenis. Então talvez seja só sua imaginação.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Ouça aqui. Aproxime-se. Eu não sei se sabe o que eu sei, mas você realmente \"\n\"tem algo aqui. Isso é um mapa.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Minha avó sempre me conta histórias sobre as estranhas forças que habitam o \"\n\"cemitério fora da igreja. E você pode querer ouvir uma delas. Ela disse que \"\n\"se deixasse a oferenda adequada no cemitério, entrasse na catedral para orar \"\n\"pelos mortos, e depois retornasse, a oferenda seria alterada de alguma forma \"\n\"estranha. Não sei se isso é só conversa de uma velha doente, mas tudo parece \"\n\"possível hoje em dia.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Humm. Um vasto e misterioso tesouro, você diz?  Hummm.  Talvez eu esteja \"\n\"interessado em pegar algumas coisas de você... ou melhor ainda, você não \"\n\"precisa de alguns suprimentos raros e caros para passar por esse teste?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Então, você é o herói de quem todos estão falando. Você poderia ajudar um \"\n\"simples e pobre fazendeiro a resolver um problema terrível? Na beira do meu \"\n\"pomar, ao sul daqui, há uma coisa horrível saindo do chão! Não consigo \"\n\"chegar às minhas plantações ou aos fardos de feno, e minhas pobres vacas \"\n\"morrerão de fome. A bruxa me deu isso e disse que explodiria aquela coisa do \"\n\"meu campo. Se puder destruí-la, serei eternamente grato a você. Eu mesmo \"\n\"faria isso, mas alguém tem que ficar aqui com as vacas...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Eu sabia que não podia ser tão simples como a bruxa disse. É um mundo triste \"\n\"quando você não pode nem confiar em seus vizinhos.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"A coisa se foi? Enviou ela de volta aos recantos escuros de Hades de onde \"\n\"veio? Você o quê? Oh, não me diga que você a perdeu! Essas coisas não são \"\n\"baratas, você sabe? Você tem que encontrá-la e depois tirar esse horror da \"\n\"nossa cidade.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Eu ouvi a explosão daqui! Muito obrigado, gentil estranho. Com todas essas \"\n\"coisas saindo da terra, os monstros tomam conta da igreja e assim por \"\n\"diante, estes são tempos difíceis. Sou apenas um pobre fazendeiro, mas leve \"\n\"isso como agradecimento.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Oh, que problema eu tenho... talvez... Não, eu não poderia impor isso a \"\n\"você, com todos esses outros problemas. Será que depois de limpar a igreja \"\n\"de algumas dessas criaturas, você pode voltar... e dedicar algum tempo \"\n\"ajudando um pobre fazendeiro?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Buáááá! (sniff) Buáááá! (sniff)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Eu perdi Theo!  Perdi meu melhor amigo!  Estávamos brincando perto do rio, e \"\n\"Theo disse que queria ir ver a grande coisa verde.  Eu disse que não \"\n\"deveríamos, mas nós nos esgueiramos até lá, e de repente esse INSETO saiu!  \"\n\"Nós fugimos, mas Theo caiu e o inseto o agarrou e o levou embora!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Você o encontrou?  Você tem que encontrar Theodore, por favor!  Ele é \"\n\"pequeno, não consegue se cuidar sozinho!  Por favor!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Você o encontrou! Você o encontrou! Obrigado! Oh Theo, esses insetos \"\n\"nojentos te assustaram? Ei! Ugh! Há algo preso na pele dele! Éca! Vamos, \"\n\"Theo, vamos para casa! Obrigado novamente, herói!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Estamos dormindo há muito tempo e chegou a hora de acordar. Depois do nosso \"\n\"longo sonho, estamos com muita fome. Em breve vamos nos alimentar...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Está se divertindo, pequeno mamífero?  Que patético. Seu mundinho não será \"\n\"nenhum desafio.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Estas terras serão contaminadas, e nossa ninhada invadirá os campos que os \"\n\"homens chamam de lar.  Nossos tentáculos envolverão este mundo, e nós \"\n\"faremos um banquete com a carne de seus habitantes.  O homem se tornará \"\n\"nosso bem e sustento.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, eu posso sentir seu cheiro... Você está perto! Perto! Ssss... o cheiro \"\n\"de sangue e medo... que tentador...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"E no ano da Luz Dourada, foi decretado que uma grande Catedral fosse \"\n\"erguida. A pedra angular deste lugar sagrado deveria ser esculpida na pedra \"\n\"translúcida Antyrael, em homenagem ao Anjo que compartilhava seu poder com \"\n\"os Horadrim.  \\n\"\n\" \\n\"\n\"No Ano do Desenho das Sombras, o chão tremeu e a Catedral se partiu e caiu. \"\n\"Quando a construção das catacumbas e castelos começaram e o homem se ergueu \"\n\"contra as devastações da Guerra do Pecado, as ruínas foram escavadas em \"\n\"busca de suas pedras. E foi assim que a pedra angular desapareceu dos olhos \"\n\"do homem. \\n\"\n\" \\n\"\n\"A pedra era deste mundo, e de todos os mundos, já que a Luz está dentro de \"\n\"todas as coisas e além de todas as coisas. A luz e unidade são os produtos \"\n\"desta fundação sagrada, uma unidade de propósito e uma unidade de posse.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Mu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Eu disse, Mu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Olhe, eu só sou uma vaca, certo?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Tudo bem, tudo bem. Eu não sou realmente uma vaca. Eu não costumo andar \"\n\"assim; mas, eu estava sentado em casa cuidando da minha própria vida e, de \"\n\"repente, esses insetos, videiras, bulbos e coisas começaram a sair do \"\n\"chão... foi horrível! Se eu tivesse algo normal para vestir, não seria tão \"\n\"ruim assim. Ei! Você poderia voltar para minha casa e me trazer meu traje? O \"\n\"marrom, não o cinza, é para ocasiões noturnas. Eu mesmo pegaria, mas não \"\n\"quero que ninguém me veja assim. Aqui, pegue isso, você pode precisar... \"\n\"para matar aquelas coisas que cresceram em tudo.  Você vai achar a minha \"\n\"casa, é ao sul da bifurcação no rio... Você sabe... aquela com a horta \"\n\"crescida.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Por que está perdendo tempo?  Vai pegar meu traje!  E rápido!  Aquele \"\n\"Holstein ali não para de piscar para mim!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Ei, você está com meu traje aí?  Rápido, passa para cá!  Essas orelhas coçam \"\n\"de forma inacreditável!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Não, não, não, não!  Este é o meu traje CINZA!  É para noite!  Ocasiões \"\n\"formais!  Não posso usar isso.  O que você é, algum tipo de esquisitão?  \"\n\"Preciso do traje MARROM.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, isso é muito melhor.  Ufa!  Finalmente, alguma dignidade!  Meus chifres \"\n\"estão alinhados?  Bom.  Olha, muito obrigado por me ajudar.  Aqui, tome isso \"\n\"como um presente; e, você sabe... uma pequena dica de moda... você poderia \"\n\"usar um pouco... você poderia usar um novo... sabe o que quero dizer?  Todo \"\n\"o tema de aventureiro é tão... retrô.  Só um conselho, hein?  Tchau.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Olhe.  Eu sou uma vaca.  E você, você é uma isca de monstro. Obtenha alguma \"\n\"experiência!  E depois nos falamos...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Deve ser realmente uma tarefa terrível que coloquei diante de você. Se \"\n\"houvesse algo que eu pudesse... uma jarra de leite fresco ajudaria?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Oh, eu poderia usar sua ajuda, mas só depois que você salvar as catacumbas \"\n\"da profanação daquelas bestas.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Eu preciso que algo seja feito, mas não posso impor isso a um estranho. \"\n\"Talvez depois de você estiver aqui por um tempo eu me sinta mais confortável \"\n\"pedindo um favor.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Vejo em você o potencial da grandeza.  Talvez em algum momento enquanto \"\n\"estiver cumprindo seu destino, você poderia parar e fazer um pequeno favor \"\n\"para mim?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Eu acho que você provavelmente poderia me ajudar, mas talvez depois que você \"\n\"ficar um pouco mais poderoso. Eu não gostaria de prejudicar a única \"\n\"oportunidade da vila de destruir a ameaça na igreja!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Eu sou uma vaca auto-criada.  Faça algo de si mesmo e... depois nos falamos.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Eu não tenho que dar explicações para todos os turistas que passam por \"\n\"aqui!  Você não tem alguns monstros para matar?  Talvez nos falemos mais \"\n\"tarde.  Se você sobreviver...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Pare de me incomodar.  Estou procurando alguém muito heróico.  E você não \"\n\"é.  Não posso confiar em você, pois será devorado por monstros a qualquer \"\n\"momento... Preciso de alguém que seja um herói experiente.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Tudo bem, vou parar de besteiras.  Eu não queria te enganar.  Eu estava \"\n\"sentado em casa, sentindo muu-ito mal, quando as coisas ficaram realmente \"\n\"instáveis; uma debandada inteira de monstros saiu do chão!  Eu me \"\n\"acovardei.  Aconteceu de eu estar usando esta fantasia quando corri para \"\n\"fora da porta, e agora eu pareço ridículo.  Se eu tivesse algo normal para \"\n\"vestir, não seria tão ruim.  Ei!  Pode voltar para minha casa e pegar meu \"\n\"traje para mim?  O marrom, não o cinza, é para ocasiões noturnas. Eu mesmo \"\n\"pegaria, mas não quero que ninguém me veja assim. Aqui, pegue isso, você \"\n\"pode precisar... para matar aquelas coisas que cresceram em tudo.  Você vai \"\n\"achar a minha casa, é ao sul da bifurcação no rio... Você sabe... aquela com \"\n\"a horta crescida.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Tentei feitiços, ameaças, abjuração e negociação com esta criatura nojenta, \"\n\"sem sucesso.  Meus métodos de escravizar demônios menores parecem não ter \"\n\"efeito sobre esta besta temível.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Minha casa está lentamente se deteriorando devido a vileza deste prisioneiro \"\n\"indesejado.  As criptas estão cheias de sombras que se movem além dos cantos \"\n\"da minha percepção.  O leve ranger das garras dança nas bordas da minha \"\n\"audição. Eu acho que eles estão procurando por este diário.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Em suas conversas, a criatura deixou escapar seu nome: Na-Krul.  Tentei \"\n\"pesquisar o nome, mas os demônios menores de alguma forma destruíram minha \"\n\"biblioteca.  Na-Krul... O nome me enche de medo.  Prefiro pensar nele apenas \"\n\"como 'A Criatura', em vez de refletir sobre seu nome verdadeiro.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Os uivos de fúria da criatura aprisionada me impedem de dormir.  Ela se \"\n\"enfurece contra aquele que a enviou para o Vazio, e me lança horríveis \"\n\"maldições por prendê-la aqui.  Suas palavras enchem meu coração de terror, e \"\n\"ainda assim não posso bloquear sua voz.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Meu tempo está se esgotando rapidamente.  Devo registrar as maneiras de \"\n\"enfraquecer o demônio, e então esconder esse texto, para que seus servos não \"\n\"encontrem alguma maneira de usar meu conhecimento para libertar seu senhor.  \"\n\"Espero que quem encontrar este diário busque o conhecimento.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Quem encontrar este pergaminho tem o dever de parar a criatura demoníaca que \"\n\"se esconde dentro dessas paredes.  Meu tempo acabou. Mesmo agora, seus \"\n\"lacaios infernais arranham por trás da porta que os escondem.  \\n\"\n\" \\n\"\n\"Bloqueei o Demônio com magia arcaica segregando-o atrás das grandes paredes, \"\n\"mas temo que não será o suficiente. \\n\"\n\" \\n\"\n\"Os feitiços encontrados nos meus três grimórios fornecerão uma entrada \"\n\"protegida ao seu domínio, mas só se forem lançados na ordem certa.  As \"\n\"alavancas na entrada removerão as barreiras libertando o demônio; Não toque \"\n\"nelas! Use apenas esses feitiços para entrar ou seu poder pode ser muito \"\n\"grande para ser derrotá-lo.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Hellboar\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Ferroador\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psicorbe\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Arachnon\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Geminígio\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Cria de Hork\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Venomtail\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Necromorb\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Lorde das Aranhas\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Verme-de-chicote\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Torchant\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Inseto do Inferno\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Coveiro\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Rato da Tumba\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Morcego de Fogo\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Asa Esquelética\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lich\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Demônio da Cripta\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Morcego Infernal\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Demônio de Ossos\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Arque Lich\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biclops\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Coisa de Carne Fresca\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Ceifador\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Junta do gigante\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Anel mercurial\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Anel de Xorine\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Anel de Karik\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Anel de magma\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Anel dos místicos\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Anel do trovão\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Amuleto de proteção\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Picada de mosquito\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Tocha\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Armadura da penumbra\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Blitzen\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Trovoada\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Devorador de almas\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Diamondedge\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Armadura de cadeias de ossos\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Armadura de placas de demônio\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Amuleto de acólito\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Anel do gladiador\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"do Bobo\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Cristalino\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"do Impostor\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"da devastação\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"declínio\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"perigo\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"de Magi\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"do Bobo\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Parede Relampejante\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Imolação\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Deformação\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Refletir\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Fúria\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Anel de Fogo\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Procurar\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Runa de fogo\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Runa da Luz\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Runa de Nova\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Runa Explosiva\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Runa de Pedra\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Gostaria de jogar um item do chão?\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Coração\"\n\n#~ msgid \"/help\"\n#~ msgstr \"/help\"\n\n#~ msgid \"/arena\"\n#~ msgstr \"/arena\"\n\n#~ msgid \"/arenapot\"\n#~ msgstr \"/arenapot\"\n\n#~ msgid \"/inspect\"\n#~ msgstr \"/inspect\"\n\n#~ msgid \"/seedinfo\"\n#~ msgstr \"/seedinfo\"\n\n#~ msgid \"Command \\\"\"\n#~ msgstr \"Comando \\\"\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Diminuir Gama\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Aumentar Gama\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Automapa indisponível na cidade\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Reiniciar na cidade\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Força a espera por Sincronização Vertical. Previne efeito de sobreposição \"\n#~ \"de retalhos ao desenhar quadro. Desabilitá-lo pode ajudar com lag no \"\n#~ \"mouse em alguns sistemas.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Limitador de FPS\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"FPS é limitado para evitar alta carga de CPU. O limite considera a taxa \"\n#~ \"de atualização.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Chance de acerto\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Indestrutível,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Nenhum atributo requerido\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Está nublado e fresco hoje.  Lançar as redes de necromancia através do \"\n#~ \"vazio aterrou duas novas subespécies de terror voador; um bom dia de \"\n#~ \"trabalho.  Tenho de me lembrar de pedir mais guano de morcego e velas \"\n#~ \"pretas para Ádria; Estou ficando com pouco.\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Opções:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"versão {:s}\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"recupera vida\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"cura mortalmente\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"diminui força\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"diminui destreza\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"diminui vitalidade\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"você não pode se curar\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"monstro acertado não cura\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Movim. de atq. mais rápido\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"enxerga com infravisão\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Não foi possível abrir o arquivo do jogador para escrita.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Não foi possível ler para salvar o arquivo\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Não foi possível escrever para salvar o arquivo\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"Para além do Salão de Heróis jaz a Câmara de Ossos.  A morte eterna \"\n#~ \"aguarda aqueles que queiram roubar os tesouros nesta sala protegidos.  \"\n#~ \"Assim fala o Senhor do Terror, e assim está escrito.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"Os arsenais do Inferno são o lar do Senhor da Guerra Sangrenta.  Em seu \"\n#~ \"rastro jazem os corpos mutilados de milhares. Anjos e homens foram \"\n#~ \"mutilados para cumprir seus sacrifícios sem fim para os Sombrios, que \"\n#~ \"gritam por uma só coisa - sangue.\"\n\n#~ msgid \"Right click to read\"\n#~ msgstr \"Clique direito para ler\"\n"
  },
  {
    "path": "Translations/ro.po",
    "content": "# Translation of DevilutionX to Romanian\n# @licaon-kter, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:21+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: ro\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n==0 || (n!=1 && n%100>=1 && \"\n\"n%100<=19) ? 1 : 2);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Muzică\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tNici un suflet nu a fost vândut în timpul producerii acestui joc.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"Bine\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Alegeți clasa\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Anulare\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Erou nou multi-jucător\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Nou erou jucător\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Există fișier salvare\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Încarcă joc\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Joc nou\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Personaje jucător\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Personajele Renegat și Vrăjitor sunt disponibile doar în jocul complet \"\n\"Diablo. Vizitați https://www.gog.com/game/diablo pentru a cumpăra.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Introduceți numele\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Nume invalid. Un nume nu poate conține spatii, caractere rezervate sau \"\n\"cuvinte rezervate.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Nu s-a putut crea personajul.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Nivel:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Forță:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magie:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Dexteritate:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Vitalitate:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Salvare:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Selectare erou\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Erou nou\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Șterge\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Personaje multi-jucător\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Șterge erou multi-jucător\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Șterge erou jucător\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Sigur doriți să ștergeți personajul \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Un jucător\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Multi-jucător\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Asistență\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Credite creatori\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Ieșire Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Ieșire Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Mod Demo\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Client-Server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"Local\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Joc multi-jucător\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Cerințe:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"fără portal\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Selectare conexiune\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Schimbare portal\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Toate calculatoarele trebuie să fie într-o rețea de tip TCP.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Toate calculatoarele trebuie să fie conectate la Internet.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Jucați singuri fără expunere la rețea.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Jucători suportați: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\n#, fuzzy\n#| msgid \"Shareware\"\nmsgid \"Diablo Shareware\"\nmsgstr \"Mod Demo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Hellfire\"\nmsgstr \"Ieșire Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\n#, fuzzy\n#| msgid \"Shareware\"\nmsgid \"Hellfire Shareware\"\nmsgstr \"Mod Demo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Gazda rulează un joc diferit de al dumneavoastră.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, fuzzy, c++-format\n#| msgid \"The host is running a different game than you.\"\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Gazda rulează un joc diferit de al dumneavoastră.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"\"\n\"Versiunea dumneavoastră {:s} nu se potrivește cu cea a gazdei {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Descriere:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Selectare acțiune\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Creare joc\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Creare joc public\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Alăturare joc\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\n#, fuzzy\n#| msgid \"Public Game\"\nmsgid \"Public Games\"\nmsgstr \"Joc public\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Se încarcă...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Nicun\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ANULARE\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Creează un nou joc cu o setare de dificultate la alegere.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Creează un nou joc public la care se poate alătura oricine cu o setare de \"\n\"dificultate la alegere.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\n#, fuzzy\n#| msgid \"\"\n#| \"Enter an IP or a hostname and join a game already in progress at that \"\n#| \"address.\"\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"\"\n\"Introduceți adresă IP sau nume gazdă pentru a vă alătura unui joc în \"\n\"desfășurare.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\n#, fuzzy\n#| msgid \"\"\n#| \"Enter an IP or a hostname and join a game already in progress at that \"\n#| \"address.\"\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Introduceți adresă IP sau nume gazdă pentru a vă alătura unui joc în \"\n\"desfășurare.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\n#, fuzzy\n#| msgid \"Join the public game already in progress at this address.\"\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Alăturați-vă unui joc public în desfășurare la această adresă.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normală\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Coșmar\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Iad\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, fuzzy, c++-format\n#| msgid \"Select Difficulty\"\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Sel. dificultate\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Viteză: Normală\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Viteză: Rapid\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Viteză: Mai rapidă\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Viteză: Cea mai repidă\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\n#, fuzzy\n#| msgid \"Player attack\"\nmsgid \"Players: \"\nmsgstr \"Jucător agresiv\"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Sel. dificultate\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Alăturare joc {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Introduceți adresa\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Dificultate Normală\\n\"\n\"Un personaj începător aici ar trebui să pornească în misiunea de a-l învinge \"\n\"pe Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Dificultate Coșmar\\n\"\n\"Locuitorii Labirintului au fost stimulați și se vor dovedi a fi o provocare \"\n\"mai mare. Este recomandată doar pentru personajele experimentate.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Dificultate Iad\\n\"\n\"Cele mai puternice creaturi ale lumii de dincolo bântuie la poarta Iadului. \"\n\"Doar cele mai experimentate personaje ar trebui să riște să intre pe acest \"\n\"tărâm.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Personajul trebuie să atingă nivelul 20 înainte de a putea intra într-un joc \"\n\"multi-jucător pe dificultatea Coșmar.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Personajul trebuie să atingă nivelul 30 înainte de a putea intra într-un joc \"\n\"multi-jucător pe dificultatea Iad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Selectare viteză joc\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Rapidă\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Mai rapidă\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Cea mai rapidă\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Viteză Normală\\n\"\n\"Un personaj începător aici ar trebui să pornească în misiunea de a-l învinge \"\n\"pe Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Viteză Rapidă\\n\"\n\"Locuitorii Labirintului au fost accelerați și se vor dovedi a fi o provocare \"\n\"mai mare. Este recomandată doar pentru personajele experimentate.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Viteză Mai rapidă\\n\"\n\"Cei mai mulți monștrii ai temniței te vor căuta mai repede mai mult ca \"\n\"oricând. Doar cei mai experimentați campioni ar trebui să-și încerce norocul \"\n\"la această viteză.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Viteza Cea mai rapidă\\n\"\n\"Slujitorii lumii de dincolo se vor grăbii să vă atace fără ezitare. Doar \"\n\"adevărații demoni ai vitezei ar trebui să intre la acest ritm.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Introduceți parola\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Intră în Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Schimbă la Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Da\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Nu\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Meniu precedent\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Clauză exonerare de răspundere:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Drepturi de auto © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Eroare\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Eroare s-a produs la: {:s} linia {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Eroare fișier de date\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Nu s-a putut deschide arhiva principală de date ({:s}).\\n\"\n\"\\n\"\n\"Asigurați-vă că este în directorul jocului.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Eroare de director doar-citire\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Nu s-a putut scrie în locația:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\n#, fuzzy\n#| msgid \"game: \"\nmsgid \"Game: \"\nmsgstr \"joc: \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"Local\"\n\n#: Source/automap.cpp:1426\n#, fuzzy\n#| msgid \"password: \"\nmsgid \"Password: \"\nmsgstr \"parolă: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Joc public\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Nivel: Cuibul {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Nivel: Criptă {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Oraș\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Nivel: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Informații personaj\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Jurnal misiuni\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Hartă\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Meniu\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Inventar\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Carte vrăji\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Trimite mesaj\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\n#, fuzzy\n#| msgid \"Description:\"\nmsgid \"Description: \"\nmsgstr \"Descriere:\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\n#, fuzzy\n#| msgid \"Player attack\"\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"Jucător agresiv\"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to buy this item?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Sunteți siguri că vreți să cumpărați acest obiect?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\n#| msgid \"Multi Player Game\"\nmsgid \"<player name>\"\nmsgstr \"Joc multi-jucător\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Jucător prietenos\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Jucător agresiv\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Tasta: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Selectați buton curent de vrajă\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Tasta: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Abilitate\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Vrajă\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Nivel vrajă 0 - Inutilizabil\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Nivel vrajă {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Pergament de {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} pergament\"\nmsgstr[1] \"{:d} pergamente\"\nmsgstr[2] \"{:d} de pergamente\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Toiag de {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} încărcătură\"\nmsgstr[1] \"{:d} încărcături\"\nmsgstr[2] \"{:d} de încărcături\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} galben\"\nmsgstr[1] \"{:s} galbeni\"\nmsgstr[2] \"{:s} de galbeni\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Cerințele nu au fost indeplinite\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Nivel: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Puncte viață {:d} din {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Clic dreapta folosire\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Creștere nivel\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Aveți {:s} galben. Câți doriți sa scoateți?\"\nmsgstr[1] \"Aveți {:s} galbeni. Cați doriți sa scoateți?\"\nmsgstr[2] \"Aveți {:s} de galbeni. Cați doriți sa scoateți?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Portal oraș\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"de la {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal către\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"nivel 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Nu s-a putut încarcă personajul\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Arată acest mesaj și ieși\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Arată versiunea și ieși\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Specifică directorul pentru diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Specifică directorul pentru fișiere de salvări\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Specifică locația pentru diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Sări peste filmele de început\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Arată numărul de cadre pe secundă\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Activează jurnalul detaliat\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Înregistrează un demo în fișier\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Rulează un fișier demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Dezactivează limitările de cadre la rularea unui demo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Forțează modul Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Opțiuni Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Raportați problemele la https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Eroare la încărcarea resurselor interfeței UI.\\n\"\n\"\\n\"\n\"Asigurați-vă ca devilutionx.mpq este în directorul jocului si că este la zi.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Timp așteptare rețea expirat --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Waiting for players --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Ajutor indisponibil\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, fuzzy, c++-format\n#| msgid \"Sell items\"\nmsgid \"Belt item {}\"\nmsgstr \"Vindeți obiecte\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\n#, fuzzy\n#| msgid \"1 - 8: Use Belt item\"\nmsgid \"Use Belt item.\"\nmsgstr \"1 - 8: Folosește obiect de pe centură\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\n#, fuzzy\n#| msgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"F5, F6, F7, F8:     Setare tastă pentru abilitate sau vrajă\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Meniu precedent\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\n#, fuzzy\n#| msgid \"Spell book\"\nmsgid \"Speedbook\"\nmsgstr \"Carte vrăji\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\n#, fuzzy\n#| msgid \"S: Open Speedbook\"\nmsgid \"Open Speedbook.\"\nmsgstr \"S: Deschide Apelarea Rapidă\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\n#, fuzzy\n#| msgid \"Savegame:\"\nmsgid \"Saves the game.\"\nmsgstr \"Salvare:\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\n#, fuzzy\n#| msgid \"Load Game\"\nmsgid \"Loads the game.\"\nmsgstr \"Încarcă joc\"\n\n#: Source/diablo.cpp:1866\n#, fuzzy\n#| msgid \"Quit Game\"\nmsgid \"Quit game\"\nmsgstr \"Ieșire joc\"\n\n#: Source/diablo.cpp:1867\n#, fuzzy\n#| msgid \"Lester the farmer\"\nmsgid \"Closes the game.\"\nmsgstr \"Fermierul Lester\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\n#, fuzzy\n#| msgid \"I: Open Inventory screen\"\nmsgid \"Open Inventory screen.\"\nmsgstr \"I: Deschide panoul de inventar\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\n#, fuzzy\n#| msgid \"Char\"\nmsgid \"Character\"\nmsgstr \"Pers\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\n#, fuzzy\n#| msgid \"C: Open Character screen\"\nmsgid \"Open Character screen.\"\nmsgstr \"C: Deschide panoul personajului\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\n#, fuzzy\n#| msgid \"Quests log\"\nmsgid \"Quest log\"\nmsgstr \"Jurnal misiuni\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\n#, fuzzy\n#| msgid \"Q: Open Quest log\"\nmsgid \"Open Quest log.\"\nmsgstr \"Q: Deschide jurnalul de misiuni\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\n#, fuzzy\n#| msgid \"Spell book\"\nmsgid \"Spellbook\"\nmsgstr \"Carte vrăji\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\n#, fuzzy\n#| msgid \"B: Open Spellbook\"\nmsgid \"Open Spellbook.\"\nmsgstr \"B: Deschide cartea de vrăji\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\n#, fuzzy\n#| msgid \"Z: Zoom Game Screen\"\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Z: Zoom ecran de joc\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"G: Increase screen brightness\"\nmsgid \"Decrease Brightness\"\nmsgstr \"G: Crește strălucirea ecranului\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\n#, fuzzy\n#| msgid \"F: Reduce screen brightness\"\nmsgid \"Reduce screen brightness.\"\nmsgstr \"F: Scade strălucirea ecranului\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"G: Increase screen brightness\"\nmsgid \"Increase Brightness\"\nmsgstr \"G: Crește strălucirea ecranului\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\n#, fuzzy\n#| msgid \"G: Increase screen brightness\"\nmsgid \"Increase screen brightness.\"\nmsgstr \"G: Crește strălucirea ecranului\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\n#, fuzzy\n#| msgid \"F1:    Open Help Screen\"\nmsgid \"Open Help Screen.\"\nmsgstr \"F1:    Deschide ecran ajutor\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, fuzzy, c++-format\n#| msgid \"{:d} {:s} charge\"\n#| msgid_plural \"{:d} {:s} charges\"\nmsgid \"{:s} {:s}\"\nmsgstr \"{:d} {:s} încărcătură\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Inventar\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"Selectare acțiune\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"Selectare acțiune\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"Anulare\"\n\n#: Source/diablo.cpp:2175\n#, fuzzy\n#| msgid \"Lester the farmer\"\nmsgid \"Close menus.\"\nmsgstr \"Fermierul Lester\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"Personaje multi-jucător\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"Personaje multi-jucător\"\n\n#: Source/diablo.cpp:2212\n#, fuzzy\n#| msgid \"$Movement:\"\nmsgid \"Move left\"\nmsgstr \"$Mișcare:\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"Personaje multi-jucător\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"Personaje multi-jucător\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Hartă\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\n#, fuzzy\n#| msgid \"Right click to use\"\nmsgid \"Right mouse click\"\nmsgstr \"Clic dreapta folosire\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Savegame:\"\nmsgid \"Opens the game menu.\"\nmsgstr \"Salvare:\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgid \"game: \"\nmsgid \"Game saved\"\nmsgstr \"joc: \"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Nu există multi-jucător în versiunea Demo\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Eroare creare Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Indisponibil în versiunea Demo\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Nu e îndeajuns de mult spațiu pentru salvare\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Fără pauză în oraș\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Este recomandată copierea pe un hard disc\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Problemă sincronizare multi-jucător\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Fără pauză în multi-jucător\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Se salvează...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Trebuie să fiți cel puțin nivelul 8 pentru a folosi asta.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Trebuie să fiți cel puțin nivelul 13 pentru a folosi asta.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Trebuie să fiți cel puțin nivelul 17 pentru a folosi asta.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\n#, fuzzy\n#| msgid \"Down to catacombs\"\nmsgid \"Catacombs\"\nmsgstr \"Coboară în catacombe\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, fuzzy, c++-format\n#| msgid \"Select Difficulty\"\nmsgid \"{} difficulty\"\nmsgstr \"Sel. dificultate\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"In Menu\"\nmsgstr \"Meniu\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"local\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Nu s-a putut conecta\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"eroare: citire 0 octeti de la server\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Niște fișiere MPQ Hellfire lipsesc\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Nu toate fișierele Hellfire MPQ au fost găsite\\n\"\n\"Vă rugăm să copiați fișierele hf*.mpq.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\n#, fuzzy\n#| msgid \"Restart In Town\"\nmsgid \"Run in Town\"\nmsgstr \"Restart în oraș\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\n#, fuzzy\n#| msgid \"Quests\"\nmsgid \"Theo Quest\"\nmsgstr \"Misiuni\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\n#, fuzzy\n#| msgid \"Quests\"\nmsgid \"Cow Quest\"\nmsgstr \"Misiuni\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\n#| msgid \"No Pause in town\"\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Fără pauză în oraș\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\n#, fuzzy\n#| msgid \"No Pause in town\"\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Fără pauză în oraș\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Opțiuni\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Salvare joc\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Meniu\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Ieșire joc\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Viteză\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Muzică oprită\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Sunet\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Sunet oprit\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Pauză\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Scurtături taste:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Deschide ecran ajutor\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Afișează meniu principal\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Afișează harta\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Ascunde toate panourile de informații\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Deschide Apelarea Rapidă\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Deschide cartea de vrăji\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Deschide panoul de inventar\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Deschide panoul personajului\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Deschide jurnalul de misiuni\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Scade strălucirea ecranului\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Crește strălucirea ecranului\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Zoom ecran de joc\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Zoom hartă\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Folosește obiect de pe centură\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Setare tastă pentru abilitate sau vrajă\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Buton stânga maus: Atacă fără să te miști\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Buton stânga maus (pe panoul personajului): Alocă toate punctele\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Butonul stânga maus (în inventar): Mută obiect pe centură sau dez/\"\n\"echipează obiect\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Buton stânga maus (pe centură): Mută obiect în inventar\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Mișcare:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Dacă țineți butonul mausului apăsat în timpul mișcării, personajul va \"\n\"continua să se miște în acea direcție.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Luptă:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Ținând apăsată tasta Shift și apoi făcând clic-stânga permite personajului \"\n\"să atace fără să se miște.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Hartă:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Pentru a accesa harta apăsați butonul 'HARTĂ' din bara de informații sau \"\n\"apăsați tasta 'TAB'. Mărirea și micșorarea hărții se face cu tastele + și -. \"\n\"Pentru derularea hărții folosiți săgețile.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Ridicare obiecte:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Obiectele utilizabile de dimensiuni mici, precum poțiunile sau pergamentele, \"\n\"sunt automat plasate pe 'centura' localizată în partea de sus a barei de \"\n\"interfață. Când un obiect e pus pe centură, un număr mic apare în acea \"\n\"căsuța. Obiectele pot fi folosite apăsând numărul corespunzător sau făcând \"\n\"clic-dreapta pe obiect.\"\n\n#: Source/help.cpp:70\n#, fuzzy\n#| msgid \"$Gold\"\nmsgid \"$Gold:\"\nmsgstr \"$Galbeni\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Puteți selecta o sumă anume de galbeni pe care să o lăsați, făcând clic-\"\n\"dreapta pe o grămadă de galbeni din inventar.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Abilități & Vrăji:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Puteți să accesați lista de abilitați și vrăji cu clic-stânga pe butonul \"\n\"'VRĂJI' din bara de interfată. Vrăjile memorate și cele disponibile pe \"\n\"toiege sunt listate aici. Clic-stânga pe o vrajă pe care doriți să o \"\n\"folosiți va pregăti vraja. O vrajă pregătită poate fi folosită cu un clic-\"\n\"dreapta în zona de joc.\"\n\n#: Source/help.cpp:81\n#, fuzzy\n#| msgid \"$Using the Speedbook for Spells\"\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Folosind Apelarea Rapidă pentru vrăji\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Clic-stânga pe butonul de 'vrajă pregătită' va deschide 'Apelarea Rapidă' \"\n\"care vă permite să selectați o abilitate sau o vrajă pentru utilizare \"\n\"imediată. Pentru a folosi o abilitate sau vrajă pregătită, apăsați clic-\"\n\"dreapta în zona principală de joc.\"\n\n#: Source/help.cpp:86\n#, fuzzy\n#| msgid \"\"\n#| \"Shift + Left-clicking on the 'select current spell' button will clear the \"\n#| \"readied spell\"\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + clic-stânga pe butonul 'selectare vrajă curentă' elimină vraja \"\n\"pregătită\"\n\n#: Source/help.cpp:88\n#, fuzzy\n#| msgid \"$Setting Spell Hotkeys\"\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Setare taste vrăji\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Puteți aloca pană la patru taste pentru abilitați, vrăji sau pergamente. \"\n\"Începeți prin a deschide 'apelarea rapidă' cum e descris mai sus. Apăsati \"\n\"tastele F5, F6, F7 sau F8 după ce ați selectat vraja pe care doriți să o \"\n\"alocați.\"\n\n#: Source/help.cpp:94\n#, fuzzy\n#| msgid \"$Spell Books\"\nmsgid \"$Spell Books:\"\nmsgstr \"$Cărți vrăji\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Citind mai mult de o carte vă creșteți cunoștințele despre acea vrajă, \"\n\"permițându-vă să o folosiți mai eficient.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Ajutor Demo Hellfire\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Ajutor Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Ajutor Demo Diablo\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Ajutor Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Apăsați ESC pentru a încheia sau săgeți pentru a derula.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Nu s-a putut crea fereastra principală\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} de {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, fuzzy, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{:s} {:s} de {:s}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, fuzzy, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{:s} {:s} de {:s}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} de {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"șansă de lovitură\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"șansele de lovitură ale armei\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"potențial daune\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Clic-dreapta vizualizare\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Clic-dreapta folosire\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Clic-dreapta citire, și apoi\\n\"\n\"clic-stânga țintire\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Clic-dreapta citire\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\n#, fuzzy\n#| msgid \"I: Open Inventory screen\"\nmsgid \"Open inventory to use\"\nmsgstr \"I: Deschide panoul de inventar\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Selectați din cartea de vrăji, apoi\\n\"\n\"vrăjiți pentru a citi\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\n#| msgid \"{:+d} to strength\"\nmsgid \"{} to use\"\nmsgstr \"{:+d} la forță\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Selectați din cartea de vrăji, apoi\\n\"\n\"vrăjiți pentru a citi\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Nivel: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Dublează capacitatea de galbeni\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Necesită:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Put\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Dex\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Cartea de {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"șansă de lovitură: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% daune\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"lovitură: {:+d}%, daună {:+d}%\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% armură\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"clasă armură: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Rezistă la foc: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Rezistă la foc: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Rezistă la fulger: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Rezistă la fulger: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Rezistă la magie: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Rezistă la magie: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Rezistă la toate: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Rezistă la toate: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\nmsgstr[2] \"\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\nmsgstr[2] \"\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Încărcături în plus\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} încărcătură\"\nmsgstr[1] \"{:d} {:s} încărcături\"\nmsgstr[2] \"{:d} {:s} de încărcături\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} la forță\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} la magie\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} la dexteritate\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} la vitalitate\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} la toate atributele\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% rază lumină\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% rază lumină\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"daune minge de foc: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"daune minge de foc: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"lovește ținta inapoi\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\nmsgstr[2] \"\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"daune: {:d}  Indestructibil\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"daune: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"daune: {:d}-{:d}  Indestructibil\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"daune: {:d}-{:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"armură: {:d}  Indestructibil\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"armură: {:d}  Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Încărcături: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Neidentificat\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Bârlogul Regelui Schelet\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Camera oaselor\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labirint\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Bârlogul Arhiepiscopului Lazarus\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Hell Arena\"\nmsgstr \"Ieșire Hellfire\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Coboară în temniță\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Coboară în catacombe\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Coboară în peșteri\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Coboară în iad\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Coboară în Stup\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Coboară în Criptă\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Urcă la nivelul {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Urcă în oraș\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Coboară la nivelul {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Coboară la Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Urcă la nivelul {:d} în Cuib\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Urcă la nivelul {:d} în Criptă\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Coboară la Nivelul {:d} în Criptă\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Înapoi la Nivelul {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Fișier salvare invalid\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Total uciși: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Rezistă:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magie\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"\"\n\n#: Source/mpq/mpq_writer.cpp:174\n#, fuzzy\n#| msgid \"Failed to open player archive for writing.\"\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Eroare la deschiderea pentru scriere a arhivei jucătorului.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Magic\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Ușă deschisă\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Ușă închisă\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Ușă blocată\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Cartea Josnicei\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Butoi\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urnă\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Cartea Oarbei\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Cartea Insângeratei\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Armură\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (dezactivat)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"\"\n\n#: Source/options.cpp:422\nmsgid \"Game Mode Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:423\n#, fuzzy\n#| msgid \"Play a demo file\"\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Rulează un fișier demo\"\n\n#: Source/options.cpp:429\n#, fuzzy\n#| msgid \"Switch to Shareware\"\nmsgid \"Restrict to Shareware\"\nmsgstr \"Schimbă la joc demo\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"\"\n\n#: Source/options.cpp:455\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flash\"\nmsgid \"Splash\"\nmsgstr \"Bliț\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:457\n#, fuzzy\n#| msgid \"Z: Zoom Game Screen\"\nmsgid \"Logo and Title Screen\"\nmsgstr \"Z: Zoom ecran de joc\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:487\n#, fuzzy\n#| msgid \"\"\n#| \"\\n\"\n#| \"Hellfire options:\\n\"\nmsgid \"Hellfire specific Settings\"\nmsgstr \"\"\n\"\\n\"\n\"Opțiuni Hellfire:\\n\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:504\n#, fuzzy\n#| msgid \"Rising Sun\"\nmsgid \"Walking Sound\"\nmsgstr \"Răsărit de Soare\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"\"\n\n#: Source/options.cpp:691\n#, fuzzy\n#| msgid \"Switch to Shareware\"\nmsgid \"Fit to Screen\"\nmsgstr \"Schimbă la joc demo\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\nmsgid \"Per-pixel Lighting\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\n#: Source/options.cpp:740\n#, fuzzy\n#| msgid \"Use alternate nest palette\"\nmsgid \"Alternate nest art\"\nmsgstr \"Folosește o paletă alternativă pentru cuib\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\n#: Source/options.cpp:790\n#, fuzzy\n#| msgid \"No pause in multiplayer\"\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Fără pauză în multi-jucător\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\n#, fuzzy\n#| msgid \"Bard\"\nmsgid \"Test Bard\"\nmsgstr \"Bard\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:792\n#, fuzzy\n#| msgid \"Barbarian\"\nmsgid \"Test Barbarian\"\nmsgstr \"Barbar\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:793\n#, fuzzy\n#| msgid \"Experience: \"\nmsgid \"Experience Bar\"\nmsgstr \"Experiență: \"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Informații personaj\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\nmsgid \"Off\"\nmsgstr \"Local\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Nivel\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Experiență\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Următorul nivel\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Bază\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Acum\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Forță\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magie\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Dexteritate\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Vitalitate\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Puncte de distribuit\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Galbeni\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Clasă armură\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"șansă de lovitură\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Daune\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Viață\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Rezistă la magie\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Rezistă la foc\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Rezistă la fulger\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"personaj\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"misiuni\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"hartă\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"meniu\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"inventar\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"vrăji\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"voce\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"amuțește\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\n#, fuzzy\n#| msgid \"Mana: {:d}  Dam: 1/3 tgt hp\"\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Mana: {:d}  Dam: 1/3 tgt hp\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, fuzzy, c++-format\n#| msgid \"Charges: {:d}/{:d}\"\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Încărcături: {:d}/{:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, fuzzy, c++-format\n#| msgid \"Damage: {:d}-{:d}  \"\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Daune: {:d}-{:d}  \"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Abilitate\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Toiag ({:d} încărcătură)\"\nmsgstr[1] \"Staff ({:d} încărcături)\"\nmsgstr[2] \"Staff ({:d} de încărcături)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, fuzzy, c++-format\n#| msgid \"Level {:d}\"\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Nivel {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, fuzzy, c++-format\n#| msgid \"Mana: {:d}   Dam: n/a\"\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}   Daune: n/a\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Vrajă\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Dăunează numai celor ne-morți\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Pergament\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Toiag\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Tastă vrajă {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Nu s-a putut deschide arhiva\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Nu s-a putut încarcă personajul\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, fuzzy, c++-format\n#| msgid \"{:s} (lvl {:d}): {:s}\"\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (lvl {:d}): {:s}\"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} galbeni\"\n\n#: Source/qol/stash.cpp:648\n#, fuzzy\n#| msgid \"You have {:s} gold piece. How many do you want to remove?\"\n#| msgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Aveți {:s} galben. Câți doriți sa scoateți?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Nivel {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Experiență: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Nivel maxim\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Următorul nivel: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} spre Nivel {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Mormântul Regelui Leoric\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Camera de Os\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Un pasaj întunecos\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Către {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Am nevoie de ajutor! Vino aici!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Urmează-mă.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Uite ceva pentru tine.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Acum MORI!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\n#, fuzzy\n#| msgid \"Talk to Griswold\"\nmsgid \"Griswold\"\nmsgstr \"Vorbiți cu Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"\"\n\n#: Source/stores.cpp:136\n#, fuzzy\n#| msgid \"Talk to Farnham\"\nmsgid \"Farnham\"\nmsgstr \"Vorbiți cu Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\n#, fuzzy\n#| msgid \"Talk to Gillian\"\nmsgid \"Gillian\"\nmsgstr \"Vorbiți cu Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Înapoi\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Daune: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Armură: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Dur: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"Indestructible,  \"\nmsgid \"Indestructible\"\nmsgstr \"Indestructibil,  \"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Bine ați venit la\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Magazinul fierarului\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Ați vrea să:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Vorbiți cu Griswold\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Cumpărați obiecte comune\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Cumpărați obiecte de lux\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Vindeți obiecte\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Reparați obiecte\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Ieșiți din magazin\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Am aceste obiecte de vânzare:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Am aceste obiecte de lux de vânzare:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Nu aveți nimic din ce aș vrea.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Care obiect e de vânzare?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Nu aveți nimic de reparat.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Repar care obiect?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Coliba vrăjitoarei\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Vorbiți cu Adria\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Cumpărați obiecte\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Reîncărcați toiege\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Ieșiți din colibă\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Nu aveți nimic de reîncărcat.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Reîncărcați care obiect?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Nu aveți destui galbeni\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Nu aveți destul loc in inventar\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Deci ne-am înțeles?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Sunteți siguri că vreți să identificați acest obiect?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Sunteți siguri că vreți să cumpărați acest obiect?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Sunteți siguri că vreți să reîncărcați acest obiect?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Sunteți siguri că vreți să vindeți acest obiect?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Sunteți siguri că vreți să reparați acest obiect?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt băiatul cu picior de lemn\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Vorbiți cu Wirt\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Am ceva de vânzare,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"dar te va costa 50 de galbeni\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"doar ca să arunc o privire. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Și ce ai?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Spuneți la revedere\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Am acest obiect de vânzare:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Ieși\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Casa vindecătorului\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Vorbiți cu Pepin\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Ieșiți din casa vindecătorului\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Bătrânul orașului\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Vorbiți cu Cain\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identificați un obiect\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Nu aveți nimic de identificat.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Identific care obiect?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Acest obiect este:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Gata\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Vorbiți cu {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Vorbiți cu {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"nu este disponibil\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"în versiunea Demo\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"versiune\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Bârfă\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Răsărit de Soare\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Vorbiți cu Ogden\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Ieșiți din tavernă\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Vorbiți cu Gillian\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Bețivul Farnham\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Vorbiți cu Farnham\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Spuneți la revedere\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Galbeni: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Orășean ucis\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Fierarul Griswold\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Vindecătorul Pepin\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Orășean rănit\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Ogden patronul tavernei\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Bătrânul Cain\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Vrăjitoarea Adria\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Barmanița Gillian\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Vacă\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Fermierul Lester\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Nebun complet\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Luptător\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Renegat\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Vrăjitor\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Călugăr\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Bard\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbar\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Măcelarul\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Toiag scurt de Mana\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Semn tavernă\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Poțiune de vindecare\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Poțiune de mana\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Pergament de identificare\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Pergament de Portal oraș\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Poțiune de vindecare completă\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Poțiune de mana completă\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Toiagul lui Lazarus\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Pergament de Înviere\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Toiag scurt\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Zdrențe\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Mantie\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Poțiune de întinerire\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Poțiune de întinerire completă\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Pergament de Vindecare\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Pergament de Căutare\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Pergament de Fulger\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Pergament de Perete de foc\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Pergament de Infern\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Pergament de Bliț\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Pergament de Infraviziune\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Pergament de Fazare\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Pergament de Scut Mana\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Pergament de Val de flăcări\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Pergament de Minge de foc\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Pergament de Blestemul pietrei\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Pergament de Fulger în lanț\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Pergament de Gardian\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Pergament de Nova\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Pergament de Golem\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Pergament de Teleportare\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Pergament de Apocalipsă\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Arc\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Toiag lung\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Toiag compozit\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Toiag quarter\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Toiag de război\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Inel\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Toiag scurt de Trăsnet\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Nightmare\"\nmsgid \"Lightforge\"\nmsgstr \"Coșmar\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Toiagul Umbrelor\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Fină\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"calitate\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"lacrimi\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"forță\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"dexteritate\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"magie\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"vitalitate\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"viață\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"lumină\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"urs\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"străpungere\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"viteză\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Măcelarul\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Semnul lui Ogden\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Arhiepiscopul Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Bliț\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identificare\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Perete de foc\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Portal oraș\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Blestemul pietrei\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Minge de foc\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Reîncărcare toiag\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Trăsnet\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Tu bei apă?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Curiozitatea asta a ta te va îngropa!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Salutare, prietene. Zăbovește un pic și ascultă...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Salutări, bunule stăpân. Bine ați venit la Taverna Răsărit de Soare!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Ce te doare prietene?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Bună ziua! Cu ce să vă servesc?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Deci, ce pot să fac pentru tine?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Nu poate un tip să bea liniștit?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Simt un suflet în căutare de răspunsuri...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... aici...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Auuuuu! (își trage nasul) Auuuuu! (își trage nasul)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Muu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Am zis, Muu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Uite eu sunt doar o vacă, bine?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \"\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Opțiuni:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"versiune {:s}\"\n\n#, fuzzy\n#~| msgid \"Create Game\"\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Creare joc\"\n\n#, fuzzy\n#~| msgid \"Create Game\"\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Creare joc\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Harta nu este disponibilă în oraș\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Restart în oraș\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Șansă de lovitură\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Eroare la deschiderea pentru scriere a arhivei jucătorului.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Nu s-a putut citi arhiva fișierului salvat\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Nu s-a putut scrie arhiva fișierului salvat\"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Fără atribute necesare\"\n\n#~ msgid \"Right click to read\"\n#~ msgstr \"Clic dreapta citire\"\n"
  },
  {
    "path": "Translations/ru.po",
    "content": "# Translation of DevilutionX to Russian\n# @ybrbnf2080, 2021.\n# @ktnk-dev, 2021.\n# @dv4mp1r3, 2021.\n# @AAS, 2021.\n# @tsunamistate, 2021.\n# @isage, 2021.\n# @Elidevin, 2021.\n# Dominus Iniquitatis <zerosaiko@gmail.com>, 2021.\n# Maderator Creator, 2025.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-03 17:01+0300\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Maderator Creator\\n\"\n\"Language-Team: \\n\"\n\"Language: ru\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && \"\n\"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\\n\"\n\"X-Generator: Poedit 3.5\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-Bookmarks: 1337,466,-1,-1,-1,-1,-1,-1,-1,-1\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Дизайн игры\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Старшие дизайнеры\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Дополнительный дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Ведущий программист\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Старшие программисты\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Программисты\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Почётные гости-программисты\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Программисты Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Программирование последовательной коммуникации\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Программисты инсталлятора\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Художественные руководители\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Художественное оформление\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Техническое оформление\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Художники-постановщики роликов\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"Оформление 3D роликов\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Техническое оформление роликов\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Исполнительный продюсер\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Продюсер\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Помощник продюсера\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Музыка\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Дизайн звука\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Музыка и звук роликов\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Постановка озвучки, режиссура и пробы\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Сценарий и история\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Обработка озвучки\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Актёры озвучки\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Инженер звукозаписи\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Дизайн и вёрстка руководства\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Оформление руководства\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Временный руководитель QA (Ведущий тестировщик)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Штурмовая команда QA (Тестировщики)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Команда специального назначения QA (Тестировщики совместимости)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Артиллеристская поддержка QA (Дополнительные тестировщики) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Контрразведка QA\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Заказ сетевых информационных услуг\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Поддержка клиентов\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Отдел продаж\"\n\n# Более умной адаптации я не придумал. Более подходящего сарказма из одного слова в руском языке просто нет. А английское слово является жаргонизмом аж из парусного флота.\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"(бес)Полезный\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Фоновые вокалисты Mr. Dabiri\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Связь с общественностью\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Маркетинг\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Международные продажи\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Продажи в США\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Производство\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Юридические и деловые вопросы\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Особая благодарность\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Благодарность\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"В память о\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Исключительная благодарность\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Генеральный менеджер\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Разработка ПО\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Художественный руководитель\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Художники\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Дизайн звука, эффекты и режиссура звука\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Руководитель отдела контроля качества\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Тестировщики\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Руководство\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tДополнительные работы\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Написание текста заданий\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Благодарность\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tОсобая благодарность Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Менеджер по контролю качества\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Ведущий тестировщик отдела контроля качества\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Основные тестировщики\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Дополнительные тестировщики\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Менеджер по маркетингу продукции\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Менеджер по связям с общественностью\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Помощник менеджера продукта\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Круг Одной Тысячи\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tНи одна душа не была продана во время разработки этой игры.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"ОК\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Выберите класс\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Отмена\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Новый герой сетевой игры\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Новый герой одиночной игры\"\n\n# Подобрано под размер меню.\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Есть файл сохранения\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Загрузить игру\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Новая игра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Персонажи одиночной игры\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Разбойница и маг доступны только в полной версии Diablo. Перейдите на \"\n\"https://www.gog.com/game/diablo для покупки.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Введите имя\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Неправильное имя. Имя не должно содержать пробелы, специальные символы, \"\n\"ключевые слова и неанглийские буквы.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Невозможно создать персонажа.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Уровень:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Сила:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Магия:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Ловкость:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Живучесть:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Сохранение:\"\n\n# Подогнано под единый шаблон\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Выбор героя\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Новый герой\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Удалить\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Персонажи сетевой игры\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Удалить персонажа сетевой игры\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Удалить персонажа одиночной игры\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Вы действительно хотите удалить персонажа \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Одиночная игра\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Сетевая игра\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Настройки\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Поддержка\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Титры\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Выйти из Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Выйти из Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Клиент-сервер (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Офлайн\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Сетевая игра\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Требования:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"шлюз не требуется\"\n\n# Подобрано под размер меню\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Выбор подключения\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Сменить шлюз\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Все компьютеры должны быть подключены к TCP-совместимой сети.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Все компьютеры должны быть подключены к Интернету.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Играть в одиночку без подключения к сети.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Количество игроков: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Хост запустил игру, отличную от вашей.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Хост запустил режим игры ({:s}), отличный от вашего.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Ваша версия ({:s}) не соответствует хосту ({:d}.{:d}.{:d})\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Описание:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Выберите действие\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Создать игру\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Публичная игра\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Подключиться к игре\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Публичные игры\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Загрузка...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Нет\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"ОТМЕНА\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Создайте новую игру с настройкой сложности по вашему выбору.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Создайте публичную игру, к которой может присоединиться любой, с настройкой \"\n\"сложности по вашему выбору.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Введите ID игры для подключения к существующей игре.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Введите IP-адрес или имя хоста для подключения с существующей игре.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Присоединиться к существующей публичной игре.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Нормальная\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Кошмарная\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Адская\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Сложность: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Скорость: Нормальная\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Скорость: Быстрая\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Скорость: Очень быстрая\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Скорость: Самая быстрая\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Игроки: \"\n\n# Подобрано под размер меню\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Выбор сложности\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Присоединиться к {:s} играм\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Введите ID игры\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Введите адрес\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нормальная сложность\\n\"\n\"Отсюда новичкам стоит начинать путь к победе над Диабло.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Кошмарная сложность\\n\"\n\"Обитатели Лабиринта стали сильнее прежнего. Рекомендуется только для героев, \"\n\"имеющих опыт в сражениях.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Адская сложность\\n\"\n\"Самые могущественные существа подземного мира скрываются у врат в Ад. Только \"\n\"опытным героям стоит входить в этот мир.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Ваш персонаж должен достигнуть 20 уровня, прежде чем вы сможете войти в \"\n\"сетевую игру на Кошмарной сложности.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Ваш персонаж должен достигнуть 30 уровня, прежде чем вы сможете войти в \"\n\"сетевую игру на Адской сложности.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Скорость игры\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Быстрая\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Очень быстрая\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Самая быстрая\"\n\n# Подобрано под размер меню.\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нормальная скорость\\n\"\n\"Отсюда новичкам стоит начинать путь к победе над Диабло.\"\n\n# Подобрано под размер меню.\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Быстрая скорость\\n\"\n\"Теперь обитатели Лабиринта были ускорены и стали более сложным испытанием. \"\n\"Рекомендуется только для опытных персонажей.\"\n\n# Подобрано под размер меню.\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Очень быстрая скорость\\n\"\n\"Многие монстры будут искать вас быстрее. Только опытный чемпион должен \"\n\"испытать свою удачу на такой скорости.\"\n\n# Подобрано под размер меню.\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Самая быстрая скорость\\n\"\n\"Приспешники преисподней бросятся в атаку без колебаний. Только истинный \"\n\"демон скорости может войти в такой темп.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Введите пароль\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Войти в Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Переключить на Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Да\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Нет\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Нажмите любую кнопку для изменения.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Привязать клавишу:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Нажмите любую клавишу для изменения.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Отвязать клавишу\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Привязать комбинацию кнопок:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Отвязать комбинацию\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Предыдущее меню\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Мы поддерживаем чат-сервер на Discord.gg/devilutionx Перейдите по ссылкам, \"\n\"чтобы присоединиться к нашему сообществу, где мы говорим о вещах, связанных \"\n\"с Diablo и расширением Hellfire.\"\n\n# Логически подразумевается переход на новую строку, но на русском так не получится.\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX поддерживается Diasurgical, вы можете отправить отчёт об ошибке \"\n\"или баге по адресу:\\n\"\n\"https://github.com/diasurgical/devilutionX\\n\"\n\"Чтобы мы смогли вам помочь, прикрепите номер версии, версию операционной \"\n\"системы, и опишите проблему подробнее.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Отказ от ответственности:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX не поддерживается и не обслуживается ни Blizzard \"\n\"Entertainment, ни GOG.com. Ни Blizzard Entertainment, ни GOG.com не \"\n\"тестировали и не сертифицировали DevilutionX. Все запросы по поводу \"\n\"DevilutionX нужно направлять в Diasurgical, а не в Blizzard Entertainment \"\n\"или GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tЭтот порт использует Charis SIL, New Athena Unicode, Unifont и Noto, \"\n\"которые лицензированы по SIL Open Font License, а также Twitmoji, которые \"\n\"лицензированы по CC-BY 4.0. В порте также используется SDL, лицензируемая по \"\n\"zlib-license. Более подробную информацию смотрите в ReadMe.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Ошибка\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Ошибка в: {:s} линия {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Ошибка файла данных\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Невозможно открыть основной архив ({:s}).\\n\"\n\"\\n\"\n\"Убедитесь, что файлы находятся в папке игры.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Папка только для чтения\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Невозможно записать в:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Игра: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Офлайн игра\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Пароль: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Публичная игра\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Уровень: Гнездо {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Уровень: Склеп {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Город\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Уровень: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Информация о персонаже\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Журнал заданий\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Автокарта\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Главное меню\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Инвентарь\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Книга заклинаний\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Отправить сообщение\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Доступные команды:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Команда \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" неизвестна.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Описание: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Параметры: Дополнительные параметры не требуются.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Параметры: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Арены поддерживаются только в сетевой игре.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Какую арену желаете посетить?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Несуществующий номер арены. Существующие номера:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"Чтобы попасть на арену, надо быть в городе или на другой арене.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Проверка поддерживается только в сетевой игре.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Остановить проверку игроков.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Игрок с таким именем не найден\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Проверяется игрок: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Выводит окно помощи или помощь по нужной команде.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[command]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Войти на PvP Арену.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<arena-number>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Даёт Зелья Арены.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<number>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Проверяет статистику и экипировку другого игрока.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<player name>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Показать информацию о сиде для этого уровня.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Игрок дружественен\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Игрок атакует\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Горячая клавиша: {:s}\"\n\n# Оставил именно этот вариант, так как полностью корректный перевод в игре выглядит глупо.\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Выберите текущее заклинание\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Горячая клавиша: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"Навык {:s}\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"Заклинание {:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Уровень заклинания 0 - Неприменимо\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Уровень заклинания {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Свиток {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} свиток\"\nmsgstr[1] \"{:d} свитка\"\nmsgstr[2] \"{:d} свитков\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Посох {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} заряд\"\nmsgstr[1] \"{:d} заряда\"\nmsgstr[2] \"{:d} зарядов\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} золотой\"\nmsgstr[1] \"{:s} золотых\"\nmsgstr[2] \"{:s} золотых\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Требования не выполнены\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Уровень: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Здоровье {:d} из {:d}\"\n\n#: Source/control.cpp:1525\nmsgid \"Right click to inspect\"\nmsgstr \"Правый клик для проверки\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Новый уровень\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"Вы погибли\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"ESC\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"Выход в меню\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"Нажмите {} чтобы загрузить последнее сохранение.\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"Нажмите {} чтобы вернуться в главное меню.\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"Нажмите {} для возрождения в городе.\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"У вас {:s} золотой. Сколько вы хотите забрать?\"\nmsgstr[1] \"У вас {:s} золотых. Сколько вы хотите забрать?\"\nmsgstr[2] \"У вас {:s} золотых. Сколько вы хотите забрать?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Городской портал\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"от {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Портал в\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Нечестивый Алтарь\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"уровень 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Не удаётся загрузить данные из файла {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} является неполным, пожалуйста, проверьте содержимое файла.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"В вашем файле {0} нет нужных столбцов, пожалуйста, убедитесь, что он \"\n\"соответствует документированному формату.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Нечисловое значение {0} для {1} в {2} в строке {3} и столбце {4}\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Значение вне диапазона {0} для {1} в {2} в строке {3} и столбце {4}\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Недопустимое значение {0} для {1} в {2} в строке {3} и столбце {4}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Написать это сообщение и выйти\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Написать версию и выйти\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Указать папку с diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Указать папку с сохранениями\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Указать путь к diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Указать код языка (например en или ru_RU)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Пропустить вступительные ролики\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Отобразить FPS\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Включить подробное логирование\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"Записать лог в файл, вместо stderr\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Записать демо\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Воспроизвести демо\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Отключить ограничение кадров во время проигрывания демо\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Выбор игры:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Запустить режим Shareware\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Запустить режим Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Запустить режим Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Параметры Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Сообщайте об ошибках на https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"Пожалуйста, обновите devilutionx.mpq и fonts.mpq до последней версии\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Не удалось загрузить ресурсы интерфейса.\\n\"\n\"\\n\"\n\"Убедитесь, что devilutionx.mpq находится в папке с игрой и он обновлён.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Пожалуйста, обновите файл fonts.mpq до последней версии\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Тайм-аут сети --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Ожидание игроков --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Помощь недоступна\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"в магазинах\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Предметы на поясе {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Использовать предмет на поясе.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Быстрое заклинание {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Установить горячую клавишу для заклинания.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Предыдущее заклинание\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Выбрать предыдущее заклинание (циклично).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Следующее заклинание\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Выбрать следующее заклинание (циклично).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Использовать зелье здоровья\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Использовать зелье здоровья с поясе.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Использовать зелье маны\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Использовать зелье маны с пояса.\"\n\n# Взял из Diablo II Resurrected, ток там умения, а тут - заклинания\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Панель заклинаний\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Открыть панель заклинаний.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Быстрое сохранение\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Сохраняет игру.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Быстрая загрузка\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Загружает игру.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Выйти из игры\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Закрывает игру.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Остановить персонажа\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Останавливает ходьбу и отменяет отложенные действия.\"\n\n# Подсвечиваем всё-таки не один предмет, а все. Так логичнее.\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Подсветка предметов\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Показать/скрыть предметы на земле (удержание).\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Переключить подсветку предметов\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Показать/скрыть предметы на земле (переключение).\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Переключить автокарту\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Переключает отображение автокарты.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Тип цикла карты\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Непрозрачный -> Прозрачный -> Миникарта -> Нет\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Открыть экран инвентаря.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Информация о персонаже\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Открыть экран с информацией о персонаже.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"Группа\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"Открыть панель группы.\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Журнал заданий\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Открыть журнал заданий.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Книга заклинаний\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Открыть книгу заклинаний.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Быстрое сообщение {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Используйте быстрое сообщение в чате.\"\n\n# Взял из Diablo II Resurrected \n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Очистить экран\"\n\n# Добавил конкретики\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Скрыть все информационные панели (инвентарь, магазин и т.п.).\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Приближение\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Приблизить экран игры.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Пауза\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Ставит игру на паузу.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Пауза (Альтернатива)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\nmsgid \"Decrease Brightness\"\nmsgstr \"Уменьшить яркость\"\n\n# Как будто яркость игры звучит корректнее, чем яркость экрана\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Уменьшает яркость игры.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\nmsgid \"Increase Brightness\"\nmsgstr \"Увеличить яркость\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Увеличивает яркость игры.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Помощь\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Открыть панель помощи.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Снимок экрана\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Делает снимок экрана.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Информация об игре\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Отображает информацию об игре.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"История чата\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Отображает историю чата.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Сортировка инвентаря\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Сортирует инвентарь.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Консоль\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Открывает консоль Lua.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Основное действие\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Атакуйте монстров, разговаривайте с горожанами, поднимайте и размещайте \"\n\"предметы инвентаря.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Вторичное действие\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Открывайте сундуки и двери, подбирайте предметы.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Применить заклинание\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Применяет выбранное заклинание.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Отмена действия\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Закрывает меню.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Движение вверх\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Перемещает персонажа вверх.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Движение вниз\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Перемещает персонажа вниз.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Движение влево\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Перемещает персонажа влево.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Движение вправо\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Перемещает персонажа вправо.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Стоять на месте\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Удерживайте, чтобы персонаж не ходил.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Переключить на стойку смирно\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Переключить на ходьбу.\"\n\n#: Source/diablo.cpp:2310\nmsgid \"Automap Move Up\"\nmsgstr \"Переместить автокарту вверх\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"При активации перемещает автокарту вверх.\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"Переместить автокарту вниз\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"При активации перемещает автокарту вниз.\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"Переместить автокарту влево\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"При активации перемещает автокарту влево.\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"Переместить автокарту вправо\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"При активации перемещает автокарту вправо.\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Движение курсора вверх\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Перемещает курсор вверх.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Движение курсора вниз\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Перемещает курсор вниз.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Движение курсора влево\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Перемещает курсор влево.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Движение курсора вправо\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Перемещает курсор вправо.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Левая кнопка мыши\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Работает как левая кнопка мыши.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Правая кнопка мыши\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Работает как правая кнопка мыши.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Меню быстрых заклинаний\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Удерживать для установки или применения заклинания.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Навигационное меню\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Удерживать для открытия навигационного меню.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Переключение меню\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Открыть меню игры.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Игра сохранена\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Сетевая игра недоступна в демоверсии\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Ошибка создания Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Недоступно в shareware-версии\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Недостаточно места для сохранения\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Пауза недоступна в городе\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Рекомендуется копирование на жёсткий диск\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Проблема синхронизации сетевой игры\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Пауза недоступна в сетевой игре\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Сохранение...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Чем сильнее один, тем слабее другие\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Прочность куётся из обломков\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Те, кто защищаются, редко атакуют\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Меч правосудия быстр и остр\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"В здоровом теле здоровый дух\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Мощь маны воспряла вновь\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Время не уменьшит силу стали\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Магия не всегда то, чем кажется\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Что было открыто - закрыто теперь\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Интенсивность достигается за счёт мудрости\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Тайная сила приносит разруху\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Не сломать того, что не взять\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Кровь и лазурь становятся солнцем\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Знания и мудрость ценой себя\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Пей и освежись\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Куда бы вы ни пошли, вот и вы\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Энергия приходит за счёт мудрости\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Изобилие богатства, когда меньше всего ждёшь\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Где жадность терпит поражение, терпение вознаграждается\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Благословлён великодушным спутником!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Руки человека может направлять судьба\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Сила подкрепляется небесной верой\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Суть жизни течёт изнутри\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"С высоты путь виднее\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Спасение достигается ценой мудрости\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Тайны раскрываются светом разума\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Последние могут быть первыми\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Щедрость приносит свои плоды\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Вы должны быть не ниже 8 уровня, чтобы использовать это.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Вы должны быть не ниже 13 уровня, чтобы использовать это.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Вы должны быть не ниже 17 уровня, чтобы использовать это.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Постигнуты тайные знания!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"То, что тебя не убивает...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Знание - сила.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Давайте - и вам дано будет.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Некоторый опыт приобретается на ощупь.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Нет места лучше дома.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Духовная энергия восстановлена.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Вы чувствуете себя более подвижным.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Вы чувствуете себя сильнее.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Вы чувствуете себя мудрее.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Вы чувствуете себя отдохнувшим.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"То, что может сломать волю.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Собор\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Катакомбы\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Пещеры\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Гнездо\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Склеп\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Ур {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} сложность\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"В меню\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Невозможно соединиться\"\n\n# Счётная форма.\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"ошибка: прочитано 0 байт с сервера\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\"Не удалось открыть файл:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"Возможно, файл(ы) MPQ поврежден(ы). Пожалуйста, проверьте целостность файла.\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq или spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Некоторые MPQ Hellfire отсутствуют\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Не все MPQ Hellfire были найдены.\\n\"\n\"Скопируйте все файлы hf*.mpq.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Разрешение\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Бег в городе\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Задание Тео\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Коровье задание\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Автоподбор золота\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Автоподбор элексиров\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Автоподбор масел\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Автоподбор в городе\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Адрия восполняет ману\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Автоэкипирование оружия\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Автоэкипирование брони\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Автоэкипирование шлемов\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Автоэкипирование щитов\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Автоэкипирование украшений\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Рандомизировать задания\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Показать имя предметов\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Автопополнение пояса\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Отключить калечащие святилища\"\n\n# Пункт здесь и ниже находится в меню перед числом, так что.. так будет логичнее.\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Подбор Зелий Исцеления\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Подбор Зелий Полного Исцеления\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Подбор Зелий Маны\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Подбор Зелий Полной Маны\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Подбор Зелий Омоложения\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Подбор Зелий Полного Омоложения\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Настройки\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Сохранить игру\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\nmsgid \"Exit to Main Menu\"\nmsgstr \"Выйти в главное меню\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Выйти из игры\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Гамма\"\n\n# Более логичный перевод залазит на элемент интерфейса в настройках.\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Темп\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Музыка выключена\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Звук\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Звук выключен\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Пауза\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Горячие клавиши:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Открыть экран помощи\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Показать главное меню\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Показать автокарту\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Space: Очистить экран\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Открыть панель заклинаний\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Открыть книгу заклинаний\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Открыть инвентарь\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Открыть информацию о персонаже\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Открыть журнал заданий\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Уменьшить яркость игры\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Увеличить яркость игры\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Приблизить экран игры\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Масштабировать автокарту\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Использовать предмет на поясе\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Установить горячую клавишу для заклинания\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Левая кнопка мыши: Атака без движения\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Левая кнопка мыши (в экране персонажа): Распределить все очки \"\n\"характеристик\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Левая кнопка мыши (в инвентаре): Переместить предмет на пояс или \"\n\"одеть/снять предмет\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Левая кнопка мыши (на поясе): Переместить предмет в инвентарь\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Передвижение:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Если во время движения удерживать кнопку мыши нажатой, персонаж будет \"\n\"продолжать двигаться в этом направлении.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Бой:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Если удерживать клавишу shift, а затем щёлкнуть левой кнопкой мыши, персонаж \"\n\"будет атаковать, не передвигаясь.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Автокарта:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Чтобы получить доступ к автоматической карте, нажмите кнопку 'КАРТА' на \"\n\"информационной панели или нажмите 'TAB' на клавиатуре. Увеличение и \"\n\"уменьшение карты осуществляется клавишами + и -. Для прокрутки карты \"\n\"используются клавиши со стрелками.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Поднятие предметов:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Полезные предметы небольшого размера, такие как зелья или свитки, \"\n\"автоматически помещаются на ваш 'пояс', расположенный в верхней части панели \"\n\"интерфейса. Когда предмет помещён на пояс, в соответствующей ячейке \"\n\"появляется цифра. Предметы можно использовать, нажав на соответствующую \"\n\"цифру или щёлкнув правой кнопкой мыши на предмете.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Золото:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Вы можете выбрать определённое количество золота для сброса, щёлкнув правой \"\n\"кнопкой мыши по куче золота в инвентаре.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Умения и заклинания:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Вы можете получить доступ к списку навыков и заклинаний, нажав левой кнопкой \"\n\"мыши на кнопку 'МАГИЯ' на панели интерфейса. Здесь перечислены выученные \"\n\"заклинания, а также заклинания, доступные при помощи посохов. Щёлкнув левой \"\n\"кнопкой мыши на заклинании, которое вы хотите произнести, вы подготовите \"\n\"заклинание. Готовое заклинание можно применить, просто щёлкнув правой \"\n\"кнопкой мыши в игровой зоне.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Использование быстрых заклинаний:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Щёлкнув левой кнопкой мыши по кнопке 'готовое заклинание', вы откроете \"\n\"'панель заклинаний', которая позволит выбрать навык или заклинание для \"\n\"немедленного использования. Чтобы использовать готовый навык или заклинание, \"\n\"просто щёлкните правой кнопкой мыши в основной игровой зоне.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + Левая кнопка мыши на кнопке 'текущее выбраное заклинание': Очистить \"\n\"готовое заклинание.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Привязка горячих клавиш:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Вы можете назначить до четырёх горячих клавиш для навыков, заклинаний или \"\n\"свитков. Откройте 'быстрые заклинания', как описано в разделе выше. Нажмите \"\n\"клавиши F5, F6, F7 или F8 после того, как подсветите заклинание, которое вы \"\n\"хотите назначить.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Книги заклинаний:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Чтение более чем одной книги увеличивает ваши знания о заклинании, позволяя \"\n\"вам использовать его более эффективно.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Помощь по Shareware Hellfire\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Помощь по Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Помощь по Shareware Diablo\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Помощь по Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Нажмите ESC для завершения или клавиши со стрелками для прокрутки.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Невозможно создать главное окно\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Не хватает места\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Масло Точности\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Масло Мастерства\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Масло Остроты\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Масло Смерти\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Масло Умения\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Кузнечное Масло\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Масло Стойкости\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Масло Постоянства\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Масло Закалки\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Масло Непроницаемости\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"увеличивает\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"меткость оружия\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"значительно увеличивает\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"меткость оружия\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"потенциал урона\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"сильно улучшает потенциал\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"урона, исключая луки\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"уменьшает требуемые атрибуты\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"для использования брони или оружия\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"восстанавливает 20%\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"прочности предмета\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"увеличивает текущую\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"и максимальную прочность\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"делает предмет неразрушимым\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"улучшает класс защиты\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"брони и щитов\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"значительно улучшает класс\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"защиты брони и щитов\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"устанавливает ловушку\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"устанавливает ловушку-молнию\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"устанавливает ловушку-окаменение\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"восстанавливает всё здоровье\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"восстанавливает часть здоровья\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"восстанавливает часть маны\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"восстанавливает всю ману\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"увеличивает силу\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"увеличивает магию\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"увеличивает ловкость\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"увеличивает живучесть\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"восстанавливает часть здоровья и маны\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"восстанавливает всё здоровье и ману\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(работает только на аренах)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Правый клик для просмотра\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Правый клик для использования\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Правый клик для чтения, затем\\n\"\n\"левый клик по цели\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Правый клик для чтения\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Активируйте для просмотра\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Открыть инвентарь для использования\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Активируйте, чтобы использовать\"\n\n# Оставил именно этот вариант, так как полностью корректный перевод в игре выглядит глупо.\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Выберите в книге заклинаний, затем\\n\"\n\"примените заклинание для чтения\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Активируйте для чтения\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} для осмотра\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} для использования\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Выберите в книге заклинаний\\n\"\n\"и нажмите {} для чтения\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} для чтения\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Уровень: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Удваивает вместимость золота\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Требуется:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Силы\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Маг\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Ловк\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Книга {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Ухо {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"меткость: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% урона\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"меткость: {:+d}%, {:+d}% урона\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% защиты\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"класс защиты: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Сопротивление огню: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Сопротивление огню: {:+d}% МАКС\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Сопротивление молнии: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Сопротивление молнии: {:+d}% МАКС\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Сопротивление магии: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Сопротивление магии: {:+d}% МАКС\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Общее сопротивление: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Общее сопротивление: {:+d}% МАКС\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"заклинания повышены на {:d} уровень\"\nmsgstr[1] \"заклинания повышены на {:d} уровня\"\nmsgstr[2] \"заклинания повышены на {:d} уровней\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"заклинания понижены на {:d} уровень\"\nmsgstr[1] \"заклинания понижены на {:d} уровня\"\nmsgstr[2] \"заклинания понижены на {:d} уровней\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"уровни заклинаний не изменены (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Дополнительные заряды\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} заряд\"\nmsgstr[1] \"{:d} {:s} заряда\"\nmsgstr[2] \"{:d} {:s} зарядов\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Урон огнём: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Урон огнём: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Урон молнией: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Урон молнией: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} к силе\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} к магии\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} к ловкости\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} к живучести\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} ко всем атрибутам\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} урон от врагов\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Здоровье: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Мана: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"высокая прочность\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"пониженная прочность\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"неразрушимое\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% радиуса света\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% радиуса света\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"несколько стрел за выстрел\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"урон огненных стрел: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"урон огненных стрел: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"урон грозовых стрел: {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"урон грозовых стрел: {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"урон огненного шара: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"урон огненного шара: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"атакующий получает 1-3 урона\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"носящий теряет всю ману\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"поглощает половину урона ловушек\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"отталкивает цель назад\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% урона демонам\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Все сопротивления равны 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"удар крадёт 3% маны\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"удар крадёт 5% маны\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"удар крадёт 3% здоровья\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"удар крадёт 5% здоровья\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"пробивает броню цели\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"быстрая атака\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"быстрая атака\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"более быстрая атака\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"наибыстрейшая атака\"\n\n# Что значит \"NW\"?\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Другая способность (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"быстрое восстановление\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"более быстрое восстановление\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"наибыстрейшее восстановление\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"быстрый блок\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"+{:d} очко к урону\"\nmsgstr[1] \"+{:d} очка к урону\"\nmsgstr[2] \"+{:d} очков к урону\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"выпускает случайные быстрые стрелы\"\n\n# этот параметр бесполезен, можно хоть матом писать | Было принято решение привести к общему виду \"изменённая прочность\" и \"изменённый урон\" соответственно\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"изменённый урон\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"изменённая прочность\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"одноручный меч\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"постоянная потеря здоровья\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"крадёт здоровье врагов\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"нет требований силы\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"урон молнией: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"урон молнией: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"выпускает заряженные болты при ударе\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"случайный тройной урон\"\n\n# Не гниющий, так не понятно. Надо подобрать слово, означающие постепенное исчерпывание бонуса к урону, который в итоге идёт в минус. Самое подходящее, что я подобрал - убывающие + урона\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"убывающие {:+d}% урона\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x урона монстрам, 1x вам\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Случайные 0 - 600% урона\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"низк прчн, {:+d}% урона\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"больше защиты против демонов\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"больше защиты против нежити\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% маны становятся здоровьем\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% здоровья становятся маной\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"урон: {:d}  Неразрушимое\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"урон: {:d}  Прчн: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"урон: {:d}-{:d}  Неразрушимое\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"урон: {:d}-{:d}  Прчн: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"защита: {:d}  Неразрушимое\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"защита: {:d}  Прчн:{:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Заряды: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"уникальный предмет\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Не идентифицировано\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Логово Короля Скелетов\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Палата Костей\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Лабиринт\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Отравленный Источник\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Логово Архиепископа Лазаря\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Церковная арена\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Адская арена\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Арена Круга Жизни\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Спуститься в подземелье\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Спуститься в катакомбы\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Спуститься в пещеры\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Спуститься в ад\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Спуститься в Улей\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Спуститься в Склеп\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Подняться на {:d} уровень\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Подняться в город\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Спуститься на {:d} уровень\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Спуститься к Диабло\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Подняться на {:d} уровень Гнезда\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Подняться на {:d} уровень Склепа\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Краеугольный Камень Мира\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Спуститься в Склеп на {:d} уровень\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Вернуться на {:d} уровень\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Невозможно открыть файл сохранения\"\n\n# несколько изменил оригинальную формулировку\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"Недействительная версия хранилища. Если вы попытаетесь что-то положить в \"\n\"хранилище, данные будут перезаписаны!!\"\n\n# несколько изменил оригинальную формулировку\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"Недопустимый размер хранилища. Если вы попытаетесь что-то положить в \"\n\"хранилище, данные будут перезаписаны!!\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Неправильный файл сохранения\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Игрок на уровне Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Неправильное состояние игры\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Невозможно отобразить главное меню\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"Не удалось загрузить данные монстров\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\"Не удалось добавить монстра, так как максимальный номер монстра {} уже \"\n\"достигнут.\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"Тип монстра для ID \\\"{}\\\" уже существует.\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Зверь\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Демон\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Нежить\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Тип: {:s}  Убито: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Убито: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Здоровье: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Нет сопротивления\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Сопротивления:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Магия\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Огонь\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Молния\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Иммунитет:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Тип: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Без сопротивлений\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Без иммунитета\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Малое сопротивление магии\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Малый магический иммунитет\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Не удалось открыть архив для записи.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} применил несуществующее заклинание.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} применил запрещённое заклинание.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Игрок '{:s}' (уровень {:d}) присоединился к игре\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Игра окончена\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Невозможно получить данные уровня\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Игрок '{:s}' покинул игру\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Игрок '{:s}' убил Диабло и покинул игру!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Игрок '{:s}' исключён из-за времени ожидания\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Игрок '{:s}' (уровень {:d}) уже в игре\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Таинственное\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Скрытое\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Хмурое\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Причудливое\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Магическое\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Каменное\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Религиозное\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Заколдованное\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Чудотворное\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Обворожительное\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Загадочное\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Сверхъестественное\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Жуткое\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Божественное\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Святое\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Священное\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Духовное\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Пугающее\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Заброшенное\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Жуткое\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Тихое\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Уединённое\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Украшенное\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Блестящее\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Испорченное\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Маслянистое\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Светящееся\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Нищенское\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Сверкающее\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Мерцающее\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Солнечное\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Мёрфи\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Великий Конфликт\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Возмездие за Грех - Война\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Сказ Хорадримов\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Тёмное Изгнание\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Война Грехов\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Связь Трёх\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Царства за Гранью\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Сказ Трёх\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Чёрный Король\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Журнал: Волшебство\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Журнал: Встреча\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Журнал: Тирада\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Журнал: Его Сила Растёт\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Журнал: НА-КРУЛ\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Журнал: Конец\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Книга Заклинаний\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Распятый скелет\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Рычаг\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Открытая дверь\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Закрытая дверь\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Заблокированная дверь\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Древний фолиант\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Книга подлости\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Череп-рычаг\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Мифическая книга\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Маленький сундук\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Сундук\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Большой сундук\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Саркофаг\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Книжная полка\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Книжный шкаф\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Бочка\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Кокон\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Урна\"\n\n# Взял из Diablo 3.\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} святилище\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Фолиант скелетов\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Библиотечная книга\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Кровавый фонтан\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Обезглавленное тело\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Книга Слепцов\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Книга Крови\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Очищающий источник\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Доспехи\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Стойка с оружием\"\n\n# Взял из Diablo 3.\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Козье святилище\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Котёл\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Тёмный бассейн\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Фонтан слёз\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Стальной фолиант\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Пьедестал крови\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Грибы\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Мерзкий стенд\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Убитый герой\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} с ловушкой\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (отключено)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"ВКЛ\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"ВЫКЛ\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Режим игры\"\n\n#: Source/options.cpp:422\nmsgid \"Game Mode Settings\"\nmsgstr \"Настройки игрового процесса\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Играть в Diablo или Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Ограничить до Shareware\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Делает игру совместимой с демоверсией. Позволяет играть в сетевую игру с \"\n\"друзьями, у которых нет полной версии Diablo.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Запуск\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Параметры запуска\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Интро\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Показ вступительного ролика.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Заставка\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Показ вступительной заставки.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Логотип и титульный экран\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Титульный экран\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Специальные настройки Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Специальные настройки Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Звук\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Настройки звука\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Звук ходьбы\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Персонаж издает звук при ходьбе.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Звук автоэкипирования\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"При автоматическом экипировании предметов издаётся звук.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Звук сбора предметов\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"При сборе предметов издаётся звук.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Частота дискретизации\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Выходная частота дискретизации (Гц)\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Каналы\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Количество выходных каналов.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Размер буфера\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Размер буфера (количество кадров на канал).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Качество передискретизации\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Качество передискретизации, от 0 (самое низкое) до 5 (самое высокое).\"\n\n# Убрал лишнюю инфу\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Влияет на внутреннее разрешение игры и определяет область просмотра. \"\n\"Примечание: зависит от используемого типа масштабирования.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Ресемплер\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Аудио ресемплер\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Устройство\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Аудио устройство\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Графика\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Настройки графики\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"На весь экран\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Отображение игры в оконном или полноэкранном режиме.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"По размеру экрана\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Автоматически настраивает окно игры в соответствии с текущим соотношением \"\n\"сторон и разрешением экрана рабочего стола.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Масштабирование\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Включает масштабирование изображения от разрешения игры до разрешения вашего \"\n\"монитора. Предотвращает изменение разрешения монитора и позволяет изменять \"\n\"размер окна.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Качество масштабирования\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Включает дополнительные фильтры для выходного изображения при \"\n\"масштабировании.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Ближайший пиксель\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Билинейная\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Анизотропная\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Целочисленное масштабирование\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"\"\n\"Масштабирует изображение с использованием целочисленного соотношения \"\n\"пикселей.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"Управление частотой кадров\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\"Управление частотой кадров для сбалансирования производительности, \"\n\"уменьшения разрывов или экономии электроэнергии.\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Вертикальная синхронизация\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"Ограничение FPS\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Приближает, если включено.\"\n\n#: Source/options.cpp:738\nmsgid \"Per-pixel Lighting\"\nmsgstr \"Попиксельное освещение\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"Тонкое освещение для более плавных световых градиентов.\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Цветовой цикл\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Эффект циклического изменения цвета, используемый для анимации воды, лавы и \"\n\"кислоты.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Альтернативное оформление Гнезда\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"В игре будет использована альтернативная палитра для тайлов Гнезда в \"\n\"Hellfire.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Аппаратный курсор\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Использовать аппаратный курсор\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Аппаратный курсор для предметов\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Использовать аппаратный курсор для предметов.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Максимальный размер аппаратного курсора\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Максимальная ширина/высота аппаратного курсора. Курсоры большого размера \"\n\"откатываются к программным.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Показать FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Отображать FPS в верхнем левом углу экрана.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Геймплей\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Настройки игрового процесса\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Включить бег трусцой/быструю ходьбу в городе для Diablo и Hellfire. Эта \"\n\"опция была введена в дополнении.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Захват ввода\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Если включено, мышь фиксируется в окне игры.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Пауза если окно теряет фокус\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\"Если включено, игра встанет на паузу при потере фокуса (переключении на \"\n\"другое окно).\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Включает задание Малышки.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"Включает задание Джерси. Фермер Лестер заменяется на Полного психа.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Дружественный огонь\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Разрешить урон от стрел/заклинаний между игроками в сетевой игре, даже если \"\n\"включен дружественный режим.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Полные квесты в сетевой игре\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Включает полную/не обрезанную версию квестов.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Тестировать Барда\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Даёт возможность выбора вырезанного персонажа Барда.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Тестировать Варвара\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Даёт возможность выбора вырезанного персонажа Варвара.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Полоса опыта\"\n\n# UI как \"пользовательский интерфейс\" – слишком длинно. Адаптировал.\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Полоса опыта добавлена в нижнюю часть панели интерфейса игрока.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Отобразить вид товара в магазине\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"Отображает то, как выглядит продаваемый предмет слева от текста.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Показать значение здоровья\"\n\n# Здесь и ниже – приведение к единообразию во всём меню.\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Отображает текущее/максимальное значение здоровья на шаре здоровья.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Показать значение маны\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Отображает текущее/максимальное значение маны на шаре маны.\"\n\n#: Source/options.cpp:797\nmsgid \"Show Party Information\"\nmsgstr \"Показывать информацию о группе\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\"Отображает уровень здоровья и маны всех участников группы сетевой игры.\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Индикатор здоровья врага\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Полоса здоровья врага отображается в верхней части экрана.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"Всплывающая информация предмета\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\"При наведении курсора мыши на предмет показывает информацию о нём во \"\n\"всплывающем окне.\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Золото автоматически подбирается, когда персонаж находится в \"\n\"непосредственной близости от него.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Эликсиры автоматически подбираются, когда персонаж находится в \"\n\"непосредственной близости от них.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Масла автоматически подбираются, когда персонаж находится в непосредственной \"\n\"близости от них.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Автоподбор предметов в городе.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Адрия пополнит вашу ману, когда вы посетите её магазин.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Оружие будет автоматически экипировано при подборе или покупке, если \"\n\"включено.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Броня будет автоматически экипирована при подборе или покупке, если включено.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Шлемы будут автоматически экипированы при подборе или покупке, если включено.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Щиты будут автоматически экипированы при подборе или покупке, если включено.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Украшения будут автоматически экипированы при подборе или покупке, если \"\n\"включено.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Случайный выбор доступных заданий для новых игр.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Показать тип монстра\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"При наведении курсора на монстра, тип монстра будет отображаться в поле \"\n\"описания панели интерфейса игрока.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Отображает название лежащих на земле предметов, если включено.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Пополнить пояс из инвентаря, если предмет на поясе израсходован.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Если включено, Котлы, Обворожительное Святилище, Козье Святилище, Украшенное \"\n\"Святилище и Святилище Мёрфи будут некликабельны и недоступны к применению.\"\n\n# Что-то лучше не подобрал. Заменить, если будет найдено что-то лучше.\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Быстрое заклинание\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Горячие клавиши заклинаний мгновенно применяют заклинание, а не переключают \"\n\"их.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Количество Зелий Исцеления, которое нужно подобрать автоматически.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"\"\n\"Количество Зелий Полного Исцеления, которое нужно подобрать автоматически.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Количество Зелий Маны, которое нужно подобрать автоматически.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Количество Зелий Полной Маны, которое нужно подобрать автоматически.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Количество Зелий Омоложения, которое нужно подобрать автоматически.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\"Количество Зелий Полного Омоложения, которое нужно подобрать автоматически.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Включить парящие числа урона\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"Выводит числа полученного и нанесённого урона над целью.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Выключено\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Разные направления\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Вертикальное направление\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Контроллер\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Настройки контроллера\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Сеть\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Настройки сети\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Чат\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Настройки чата\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Язык\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Определите, какой язык использовать в игре.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Настройки языка\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Клавиатура\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Настройка привязки клавиш клавиатуры\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Геймпад\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Настройка привязки кнопок геймпада\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"Моды\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"Настройки модов\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"\"\n\"Уро-\\n\"\n\"вень\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Опыт\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"\"\n\"Следующий\\n\"\n\"уровень\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"База\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Общее\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Сила\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Магия\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Ловкость\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Живучесть\"\n\n# Всё-таки поменял на более логиный перевод...\n# А я поменял на ещё более логичный, только не перевод, а вариант интерпритации, т.к. оба варианта не есть перевод фразы\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Свободные очки\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Золото\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Класс защиты\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"Меткость\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Урон\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Здоровье\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n# \"Сопротивление\" не помещается в панель персонажа\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Сопр. магии\"\n\n# \"Сопротивление\" не помещается в панель персонажа\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Сопр. огню\"\n\n# \"Сопротивление\" не помещается в панель персонажа\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Сопр. молнии\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"персонаж\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"задания\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"карта\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"меню\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"инвентарь\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"магия\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"голос\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"мут\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Неиспользовано\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Урн: 1/3 здр цели\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Лечение: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Урон: {:d} - {:d}\"\n\n# Why \"умение\", but \"навык\"? | Потому что \"умение\" в других частях серии\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Умение\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Посох ({:d} заряд)\"\nmsgstr[1] \"Посох ({:d} заряда)\"\nmsgstr[2] \"Посох ({:d} зарядов)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Уровень {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Мана: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Заклинание\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Наносит урон только нежити\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Свиток\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Посох\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Горячая клавиша заклинания {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Невозможно открыть архив\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Невозможно загрузить персонажа\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"Не удалось загрузить данные классов\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\"Не удалось добавить класс, так как максимальный номер класса {} уже \"\n\"достигнут.\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (ур {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"История чата (Сообщения: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} золота\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Сколько золотых монет вы хотите взять?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Уровень {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Опыт: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Максимальный уровень\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Следующий уровень: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} до уровня {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Гробница Короля Леорика\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Палата Костей\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Тёмный Проход\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Нечестивый Алтарь\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"К {:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Мне нужна помощь! Ко мне!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Иди за мной.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Вот кое-что для тебя.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Сейчас ты УМРЁШЬ!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Лечи себя!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Берегись!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Спасибо.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Отступай!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Извини.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Я жду.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Гризвольд\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Пепин\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Огден\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Каин\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Фарнам\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Адрия\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Джиллиан\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Вирт\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Назад\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Урон: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Защита: {:d}  \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Прчн: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Неразрушимое\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Добро пожаловать\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"в кузницу\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Вы хотите:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Поговорить с Гризвольдом\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Купить обычные предметы\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Купить премиальные предметы\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Продать предметы\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Починить предметы\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Покинуть магазин\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"У меня есть на продажу:\"\n\n# “премиальные прдеметы” не влезают в длину строки\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"У меня есть на продажу:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"У вас нет ничего нужного мне.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Какой предмет продать?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"У вас нечего чинить.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Какой предмет починить?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Хижина ведьмы\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Поговорить с Адрией\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Купить предметы\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Зарядить посохи\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Покинуть хижину\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"У вас нечего заряжать.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Какой предмет зарядить?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Нужно больше золота\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"У вас недостаточно места в инвентаре\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"По рукам?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Вы уверены, что хотите идентифицировать этот предмет?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Вы уверены, что хотите купить этот предмет?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Вы уверены, что хотите зарядить этот предмет?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Вы уверены, что хотите продать этот предмет?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Вы уверены, что хотите починить этот предмет?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Одноногий мальчик Вирт\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Поговорить с Виртом\"\n\n# Перефразировал весь диалог с Виртом. Точный перевод хреново выглядит в игре.\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"У меня есть кое-что на продажу,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"но ты должен дать 50 золота\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"чтобы увидеть это. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Что у тебя есть?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Попрощаться\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"У меня есть на продажу:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Уйти\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Дом целителя\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Поговорить с Пепином\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Покинуть дом целителя\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Городской Старейшина\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Поговорить с Каином\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Идентифицировать предмет\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"У вас нечего идентифицировать.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Какой предмет идентифицировать?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Этот предмет:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Готово\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Поговорить с {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Разговор с {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"не доступен\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"в shareware\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"версии\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Сплетни\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"таверну \\\"Восход\\\"\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Поговорить с Огденом\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Покинуть таверну\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Поговорить с Джиллиан\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Доступ к хранилищу\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Пьяница Фарнам\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Поговорить с Фарнамом\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Попрощаться\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Ваше золото: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"Не удалось загрузить данные текста\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"Для ID \\\"{}\\\" уже существует текстовая запись данных.\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Убитый горожанин\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Кузнец Гризвольд\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Целитель Пепин\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Раненый горожанин\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Владелец таверны Огден\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Старейшина Каин\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Ведьма Адрия\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Барменша Джиллиан\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Корова\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Фермер Лестер\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Селия\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Полный псих\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Воин\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Разбойница\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Маг\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Монах\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Бард\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Варвар\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Зомби\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Упырь\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Гниющая Туша\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Чёрная Смерть\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Падший\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Резчик\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Дьяволёнок\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Тёмный\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Скелет\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Мертвец с Топором\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Горящий Мертвец\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Ужас\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Мусорщик\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Пожиратель Душ\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Теневой Зверь\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Костепил\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Мертвец с Луком\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Капитан Скелетов\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Капитан Мертвецов\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Капитан Горящих Мертвецов\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Капитан Ужасов\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Невидимый Лорд\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Скрытый\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Преследователь\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Незримый\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Ткач Иллюзий\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Лорд Сатиров\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Клан Плоти\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Клан Камня\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Клан Огня\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Клан Ночи\"\n\n# это летучая мышь\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Изверг\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Мерцающий\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Мрак\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Фамильяр\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Кислотный Зверь\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Ядовитый Плеватель\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Зверь Преисподней\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Лавовая Пасть\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Король-Скелет\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Мясник\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Владыка\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Грязевой Человек\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Лягушачий Демон\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Ободранный\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Змей\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Пещерный Слизень\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Дьявольский Змей\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Пожиратель\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Демон Магмы\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Кровавый Камень\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Адский Камень\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Лавовый Лорд\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Рогатый Демон\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Грязевой Бегун\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Морозный Бегун\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Обсидиановый Лорд\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"старокостный\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Красная Смерть\"\n\n# \"Li_t_ch\", not \"Licht\".\n# (Also, see the translation of \"The Arch-Litch Malignus\" below.)\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Демон-Лич\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Балрог-Нежить\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Сжигатель\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Пламенный Лорд\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Роковой Огонь\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Адский Сжигатель\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Красная Буря\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Штормовой Всадник\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Повелитель Бури\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Вихрь\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Дьяволёнок-Громила\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Крылатый Демон\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Горгулья\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Кровавый Коготь\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Крыло Смерти\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Убийца\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Хранитель\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Лорд Вихря\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Балрог\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Пещерная Гадюка\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Огненный Дракон\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Золотая Гадюка\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Лазурный Дракон\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Чёрный Рыцарь\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Страж Рока\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Лорд Стали\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Рыцарь Крови\"\n\n# Adjective.\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Дроблёный\"\n\n# Пустой?\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Полый\"\n\n# Можно \"Мастер боли\", но хозяин как-то жутче.\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Хозяин Боли\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Ткач Реальности\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Суккуб\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Снежная Ведьма\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Адское Отродье\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Сжигатель Душ\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Советник\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Магистрат\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Заговорщик\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Адвокат\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Тёмный Лорд\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Архилич Малигнус\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Гарбад Слабый\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Зар Безумец\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Сморкун\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Архиепископ Лазарь\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Красная Ворожея\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Чернодейка\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Лахданан\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Кровавый Генерал\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Блюющий Демон\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Осквернитель\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Костеголовый Кинакс\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Лезвий Полосователь\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Душегной\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Нечистый Блевокрыс\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Костедёр\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Гнилоед Голодный\"\n\n# FIXME: \"Guts\" and \"hank\".\n# \"Моток кишок\"?\n# ---------------------------------------------\n# Есть перевод из WoW, там \"Gutshank\" переведён как \"Потрошмяк\". Оставил свой вариант.\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Кишкокрут Быстрый\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Пусточереп Крепкощит\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Бонго\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Гнилобой\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Тенекус\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Мертвоглаз\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Бесоглаз Мертвец\"\n\n# https://en.wikipedia.org/wiki/Chupacabra\n# \"El\" = \"The\". | Мне кажется преступным убирать это яркое El\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"Эль Чупакабрас\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Огнечереп\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Кривочереп\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Кровояз\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Ползопульс\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Луногиб\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Гневный Ворон\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Спиногрыз\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Чернострел Пылающий\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Крикун Тьмы\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Гнилостень Cлабак\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Желчелей Распорядитель\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Кровошкур Темнолук\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Злокрыл\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Тенеглот\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Дымовёртыш\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Смертеплюй\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Кроводёр\"\n\n# Переводить такое - безумие.\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Смертоносный Свежеватель\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Военоличинка Безумец\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Зубастый Стеклочереп\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Отравленный Огонь\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Леденящий Мрачнокрыл\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Камнемяс\"\n\n# Родственник Deathshade Fleshmaul\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Бронзокулакий Огнекам\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Огнегнев Обречённый\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Огнежёг Беспощадный\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Барон Гнус\"\n\n# Ещё один родственник Deathshade Fleshmaul\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Тленорог Сталебулавный\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Ревун Хаоса\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Судьбоскал Гниющий\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Безумный Сжигатель\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Пилокост Лич\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Спинолом\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Череподьявол Острокост\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Бурелом\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Гиблешторм\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Слюнослиз\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Златомор Пламенный\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Черношторм\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Чумогнев\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Живодёр\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Синерог\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Отродье Искажённого Огня\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Клыкатор\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Гноечереп\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Львочереп\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Чернояз\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Гнилотрог\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Пламений\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Клыкошкур\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Огневедьм Нечестивый\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Черночереп\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Душерез\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Ветрородье\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Повелитель Ямы\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Ржавокрут\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Ревущая Тень\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Судьбокров\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Кровелун Огнедуш\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Луноведьма\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Кровепир\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Блеклобой Палач\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Ужасносуд\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Ведьма Звездоглаз\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Сталеглав Охотник\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Сэр Гораш\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Визирь\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Замфир\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Кровожадина\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Вдовопут\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Плотетанцовщица\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Мрачношип\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Судьбожим\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Короткий Меч\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Круглый Щит\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Дубина\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Короткий Лук\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Короткий Посох Маны\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Тесак\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Корона Нежити\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Эмпирейское Кольцо\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Волшебный Камень\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Оптический Амулет\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Кольцо Истины\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Вывеска Таверны\"\n\n# Или просто шапка/шлем\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Гребень Арлекина\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Стальная Завеса\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Золотой Эликсир\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Дьявольская Наковальня\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Чёрный Гриб\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Мозг\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Грибной Фолиант\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Призрачный Эликсир\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Кровавый Камень\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Карта Собора\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"Ухо\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Зелье Исцеления\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Зелье Маны\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Свиток Идентификации\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Свиток Портала в Город\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Отвага Аркейна\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Зелье Полного Исцеления\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Зелье Полной Маны\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Лезвие Гризвольда\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Бычьи Доспехи\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Посох Лазаря\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Свиток Воскрешения\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Короткий Посох\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Меч\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Кинжал\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Рунная Бомба\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Теодор\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Золотой Амулет\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Обрывок Записки 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Обрывок Записки 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Обрывок Записки 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Восстановленная Записка\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Коричневый Костюм\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Серый Костюм\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Шапка\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Тюбетейка\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Шлем\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Закрытый Шлем\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Корона\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Большой Шлем\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Плащ\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Тряпьё\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Мантия\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Роба\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Стёганые Доспехи\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Кожаная Броня\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Дублёная Кожаная Броня\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Клёпаный Кожаный Доспех\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Кольцевая Кольчуга\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Кольчуга\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Кольчатая Кольчуга\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Чешуйчатая Кольчуга\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Нагрудник\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Латы\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Шинная Кольчуга\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Пластинчатый Доспех\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Полевые Латы\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Готические Латы\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Полная Пластинчатая Кольчуга\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Щит\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Маленький Щит\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Большой Щит\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Треугольный Щит\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Башенный Щит\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Готический Щит\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Зелье Омоложения\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Зелье Полного Омоложения\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Масло\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Эликсир Силы\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Эликсир Магии\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Эликсир Ловкости\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Эликсир Живучести\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Свиток Исцеления\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Свиток Поиска\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Свиток Молнии\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Свиток Стены Огня\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Свиток Преисподней\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Свиток Вспышки\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Свиток Инфразрения\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Свиток Перемещения\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Свиток Щита Маны\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Свиток Волны Огня\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Свиток Огненного Шара\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Свиток Окаменения\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Свиток Цепной Молнии\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Свиток Защитника\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Свиток Новы\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Свиток Голема\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Свиток Телепорта\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Свиток Апокалипсиса\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Фальшион\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Ятаган\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Клеймор\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Клинок\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Сабля\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Длинный Меч\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Широкий Меч\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Полуторный Меч\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Двуручный Меч\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Великий Меч\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Маленький Топор\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Топор\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Большой Топор\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Широкий Топор\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Боевой Топор\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Двуручный Топор\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Булава\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Моргенштерн\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Боевой Молот\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Молот\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Шипованная Дубина\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Цеп\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Кувалда\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Лук\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Охотничий Лук\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Длинный Лук\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Композитный Лук\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Короткий Боевой Лук\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Длинный Боевой Лук\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Короткий Военный Лук\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Длинный Военный Лук\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Длинный Посох\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Композитный Посох\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Короткий Посох\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Военный Посох\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Кольцо\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Амулет\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Руна Огня\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Руна\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Руна Молнии\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Великая Руна Огня\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Великая Руна Молнии\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Руна Камня\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Короткий Посох Заряженной Стрелы\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Зелье Арены\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Тесак Мясника\"\n\n#: Source/translation_dummy.cpp:370\nmsgid \"Lightforge\"\nmsgstr \"Световой Горн\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Лук Разлома\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Игольщик\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Небесный Лук\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Смертоносный Охотник\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Лук Мёртвых\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Лук из Чёрного Дуба\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Пламенный Дротик\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Жало Плоти\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Сила Ветра\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Орлиный Рог\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Кортик Гоннагала\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Защитник\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Коготь Грифона\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Чёрная Бритва\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Лучезарная Луна\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Ледяной Хвостовик\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Клинок Палача\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Костепил\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Теневой Ястреб\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Волшебный Шип\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Световой Меч\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Коготь Сокола\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Преисподняя\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Несущий Гибель\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Гризли\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Дедушка\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Увечитель\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Острый Клюв\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Кровоубийца\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Небесный Топор\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Злой Топор\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Каменный Тесак\"\n\n# I'm pretty sure it pronounced as \"Агинара\", not \"Агуинара\".\n# ---------------------------------------------\n# Так и есть.\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Топор Агинары\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Адский Убийца\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Разоритель Мессершмидта\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Трещины Ржавчины\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Молот Джхольма\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Дубинка Сиверба\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Небесная Звезда\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Звезда Баранара\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Корявый Корень\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Черепобойник\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Молот Шефера\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Кромка Грёз\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Посох Теней\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Поджигатель\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Острие Бури\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Мерцающая Песнь\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Громовой Зов\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Защитник\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Головоломка Наджа\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Крик Разума\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Жезл Онана\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Шлем Духов\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Шапка Размышлений\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Шлем Владыки\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Гребень Дурака\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Гибель Богов\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Королевский Венец\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Разорванная Плоть Душ\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Проклятие Гладиатора\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Радужный Плащ\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Кожа Аута\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Накидка Мудрости\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Сверкающая Кольчуга\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Панцирь Мусорщика\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Ночной Пейзаж\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Лёгкие Латы Наджа\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Покров Демонских Шипов\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Отражатель\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Щит из Расколотого Черепа\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Разлом Дракона\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Щит из Чёрного Дуба\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Святой Защитник\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Грозовой Щит\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Ежевика\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Кольцо Регхи\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Проливатель Крови\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Сужающее Кольцо\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Обручальное Кольцо\"\n\n# Хотелось бы как-то добавить средний и женский род для всех последующих слов до Doppelganger's включительно. Оловянный дубина/кольцо\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Оловянный\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Латунный\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Бронзовый\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Железный\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Стальной\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Серебряный\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Платиновый\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Мифриловый\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Метеоритный\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Странный\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Бесполезный\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Согнутый\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Хлипкий\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Зубчатый\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Смертоносный\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Тяжелый\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Порочный\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Жестокий\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Массивный\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Дикий\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Беспощадный\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Безжалостный\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Неуклюжий\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Тупой\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Острый\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Изящный\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Воинский\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Солдатский\"\n\n# Лордский...\n# ---------------------------------------------\n# Тут либо \"господский\", либо \"властелинский\".\n# --------------------------------------------- Властелинский говно\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Господский\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Рыцарский\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Мастерский\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Чемпионский\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Королевский\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Уязвимый\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Ржавый\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Сильный\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Великий\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Доблестный\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Великолепный\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Благославенный\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Освящённый\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Потрясающий\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Божественный\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Красный\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Багровый\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Гранатовый\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Рубиновый\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Голубой\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Лазурный\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Лазуритовый\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Кобальтовый\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Сапфировый\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Белый\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Жемчужный\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Слоновой Кости\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Кристальный\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Алмазный\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Топазовый\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Янтарный\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Нефритовый\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Обсидиановый\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Изумрудный\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Гиений\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Лягушачий\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Паучий\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Вороний\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Змеиный\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Гадючий\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Змиевый\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Драконий\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Змеевой\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Гидры\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Ангельский\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Архангельский\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Богатый\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Щедрый\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Пылающий\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Светящийся\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"качества\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"увеличения\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"убийства\"\n\n# крови уже есть, если есть адекватный перевод, меняйте немедленно\n# ---------------------------------------------\n# Научное название запёкшейся крови – струп.\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"струпа\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"бойни\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"резни\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"боли\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"слёз\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"здоровья\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"защиты\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"поглощения\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"отклонения\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"осмоса\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"хрупкости\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"слабости\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"силы\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"мощи\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"могущества\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"гигантов\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"титанов\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"паралича\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"атрофии\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"ловкости\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"умения\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"меткости\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"точности\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"совершенства\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"дурака\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"дислексии\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"магии\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"разума\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"блеска\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"колдовства\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"волшебства\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"хвори\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"болезни\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"живучести\"\n\n# Change at will\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"жара\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"напора\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"силы\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"жизни\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"неприятности\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"ямы\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"небес\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"луны\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"звёзд\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"небес\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"зодиака\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"стервятника\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"шакала\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"лисы\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"ягуара\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"орла\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"волка\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"тигра\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"льва\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"мамонта\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"кита\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"хрупкости\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"ломкости\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"прочности\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"мастерства\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"структуры\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"веков\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"тьмы\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"ночи\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"света\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"сияния\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"пламени\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"огня\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"горения\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"шока\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"молнии\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"грома\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"множества\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"достатка\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"шипов\"\n\n# коррупции - слишком в духе уголовного кодекса\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"разложения\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"воров\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"медведя\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"летучей мыши\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"вампиров\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"пиявки\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"крови\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"протыкания\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"прокалывания\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"избиения\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"готовности\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"стремительности\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"скорости\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"спешки\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"баланса\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"стабильности\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"гармонии\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"блокирования\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Небесный Камень\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Гарбад Слабый\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Зар Безумец\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Лахданан\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Мясник\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Вывеска Огдена\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Залы Слепцов\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Доблесть\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Кровавый Генерал\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Проклятье Короля Леорика\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Архиепископ Лазарь\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Серьёзные Вопросы\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Фермерский Сад\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Малышка\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Странствующий Торговец\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Осквернитель\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Джерси Джерси\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Огненная Стрела\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Исцеление\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Молния\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Вспышка\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Идентификация\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Стена Огня\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Городской Портал\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Окаменение\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Инфразрение\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Перемещение\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Щит Маны\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Огненный Шар\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Хранитель\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Цепная Молния\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Волна Огня\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Роковые Змеи\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Кровавый Ритуал\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Нова\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Невидимость\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Преисподняя\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Ярость\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Телепорт\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Апокалипсис\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Эфиризация\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Ремонт Предмета\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Перезарядка Посоха\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Обезвредить Ловушку\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Элементаль\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Заряженная Стрела\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Святая Стрела\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Воскрешение\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Телекинез\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Лечение Другого\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Кровавая Звезда\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Костяной Дух\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ааа, история о нашем Короле? То, что случилось с Леориком - трагедия для \"\n\"всего нашего края. Народ любил Короля, а теперь он ужасно его боиться. Я всё \"\n\"время задаю себе вопрос - как так случилось, что он пал так низко во тьму. \"\n\"Леорик всегда был добродетельным человеком. Только самые ужасные силы Ада \"\n\"могли так разрушить его душу...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Нам нужна твоя помощь. Несколько месяцев назад сын Короля Леорика, Принц \"\n\"Альбрехт, был похищен. Король словно обезумил, он перевернул весь городок в \"\n\"поисках своего пропавшего сына. С каждым днём Леорик становился всё \"\n\"безумнее. Он жестоко казнил ни в чём неповинных людей. Он успел расправиться \"\n\"с половиной населения...\\n\"\n\" \\n\"\n\"Придворные Рыцари и Священники пытались утихомирить Леорика, но он направил \"\n\"свой гнев и против их. Они были вынуждены умертвить Короля. Умирая, Леорик \"\n\"послал страшное проклятие на своих бывших приверженцев. Он поклялся, что они \"\n\"будут служить ему вечно...\\n\"\n\" \\n\"\n\"Дело приняло ещё более ужасный оборот, чем можно было предположить! Наш \"\n\"бывший Король сбросил оковы вечного сна и теперь командует легионом своих \"\n\"приспешников-скелетов. Тело Короля находилось в гробнице, расположенной на \"\n\"третьем уровне под Собором. Прошу тебя, отправь его душу на вечный покой, \"\n\"уничтожив его теперешнее воплощение, над которым довлеет проклятие...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Как я уже и сказал, Король был похоронен на третьем уровне Лабиринта. Он \"\n\"там, внизу. Он только и ждёт удобного момента, чтобы выйти и уничтожить эту \"\n\"землю...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Проклятие Короля снято, но я боюсь, что оно было только малой долей более \"\n\"страшного зла, которое нас подстерегает. Но есть ещё надежда спасти нашу \"\n\"землю от мрака, которая над ней нависла. Твоя победа - это добрый знак. Да \"\n\"прибудет с тобой свет.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Король Леорик не выдержал, когда потерял своего сына. Я сделал всё, что мог, \"\n\"чтобы вылечить его от помешательства, но оно всё-таки одолело его. С того \"\n\"дня королевство постигло чёрное проклятье. Но, может быть, если тебе удастся \"\n\"освободить его дух, то проклятье будет снято.\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Я не люблю думать о том, как умер Король. Я люблю вспоминать, каким он был \"\n\"добрым и справедливым. Его смерть была таким несчастьем. Ну почему это \"\n\"случилось?\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Раньше я ковал много оружия и доспехов. Король Леорик снаряжал ими своих \"\n\"рыцарей. Я даже изготовил лично для него большой двуручный меч из лучшего \"\n\"материала, и корону, которую он надевал во время сражений. До сих пор не \"\n\"могу поверить в то, как он умер. Должно быть, какая-то тёмная сила свела его \"\n\"с ума!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"А мне плевать на это. Слушай, какой-то там скелет не король мне. Леорик - \"\n\"вот король. Ты меня слышишь? СЛАВА КОРОЛЮ!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Мёртвые, которые ходят среди живых, - последователи проклятого Короля. Он \"\n\"способен воскресить новых воинов для растущей армии ходячих мертвецов. Если \"\n\"ты не положишь конец его правлению, он придёт на эту землю и принесёт смерть \"\n\"всему живому.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Слушай, я тут делом занимаюсь. Я не продаю сведения, и мне плевать на какого-\"\n\"то там Короля, который умер ещё до того, как я родился. Если тебе нужно что-\"\n\"нибудь, чтобы победить этого Короля мертвецов, то я смогу тебе помочь...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Чую, человечьим духом запахло. Приготовься навеки стать слугой моего \"\n\"Повелителя, смертный!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Я вижу, тебя тоже удивляет этот странный поступок. Многие демоны боятся \"\n\"солнечного света и верят, что оно обладает великой силой, а на вывеске, о \"\n\"которой ты говоришь, изображено восходящее Солнце. Может быть, демоны \"\n\"подумали, что этот знак обладает волшебной силой и поэтому стащили её. \"\n\"Пхпхпх, похоже, они не слишком умные...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Послушай, со мной произошёл странный случай. Ты многое знаешь о чудовищах, \"\n\"которые населяют лабиринт? Произошло нечто, причину которого я никак не могу \"\n\"понять... Ночью я проснулся от каких-то скребущихся звуков. Я выглянул из \"\n\"окна спальни и увидел очертания маленьких существ, похожих на демонов, \"\n\"которые копошились около моей таверны. Через некоторое время они ушли, но \"\n\"они утащили с собой вывеску от таверны. Ума не приложу, почему демоны украли \"\n\"вывеску, но не тронули мою семью... Странно, да?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Ооо, совсем необязательно было искать мою вывеску, хотя теперь мне не \"\n\"придётся тратить деньги на новую. Постой, я гляну, чем я смогу тебя \"\n\"отблагодарить. Хмм, что тут у нас... ааа, вот! Этот шлем забыл один \"\n\"волшебник, который тут останавливался. Может быть, он тебе пригодиться.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Боже мой, демоны ночью рыщут по деревне, грабят наши дома - неужели не \"\n\"осталось ничего святого? Надеюсь, с Огденом и Гардой ничего не случилось. \"\n\"Они бы пришли ко мне, если бы были ранены...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"О Господи, это туда попала вывеска? Должно быть, мы с бабушкой всё проспали. \"\n\"Слава Богу, что эти чудовища не напали на гостиницу.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Ты говоришь, демоны украли у Огдена вывеску? Это совсем не похоже на то \"\n\"зверство, которыми они занимаются. \\n\"\n\" \\n\"\n\"Демоны больше любят воровать сердца, а не столбики с вывесками.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Знаешь, что я думаю? Кто-то стащил эту вывеску, и продаст её за кучу денег. \"\n\"А если б я был Огденом... а я же не он, но если б я был он... Я бы купил \"\n\"новую вывеску с какой-нибудь красивой картинкой. С кружкой пива например, \"\n\"или куском сыра...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Ни один смертный не способен до конца понять логику демонов. \\n\"\n\" \\n\"\n\"Не позволяй им запугать тебя, это им только на руку.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Что? Он сказал, что я её стащил? Хи, и Гризвольд на его стороне. \\n\"\n\" \\n\"\n\"Послушай, я давным давно перестал красть вывески. От продажи дерева много \"\n\"денег не заработаешь.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Эй, это ты всех убиваешь? Принеси Волшебный Знак или мы нападём! И ты не \"\n\"спасёшься! Убей уродов и верни нам Волшебный Знак. Идти за угол, мимо двери, \"\n\"найти уродов. Дашь нам этот знак - пропустим!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Убей уродов, принеси знак. Отдай его мне, а не то...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"Знак наш! Отлично! Теперь уходи, мы сильные маги. Мы всех убьём!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Это плохая весть. Она подтверждает то, чего я больше всего боялся. Я не \"\n\"решался поверить древним легендам, но теперь я вижу, что это правда. Похоже, \"\n\"пришло время открыть тебе то, кто я такой на самом деле.\\n\"\n\" \\n\"\n\"Моё настоящее имя - Старейшина Декард Каин, и я последний из древнего \"\n\"Братства, которое хранило секреты бесконечного зла, и это зло, по всей \"\n\"видимости, вырвалось наружу.\\n\"\n\" \\n\"\n\"Архиепископ Лазарь, который был самым доверенным советник Короля Леорика, \"\n\"повёл отряд простых жителей деревни в Лабиринт на поиски Альбрехта - \"\n\"похищенного сына Короля. Прошло довольно много времени, прежде чем немногие \"\n\"из них смогли выбраться из подземелья.\\n\"\n\" \\n\"\n\"Будь я проклят! Я был таким глупцом. Я должен был раньше догадаться об \"\n\"измене Лазаря. Должно быть, он сам организовал похищение Альбрехта и прятал \"\n\"его в Лабиринте. Я не могу понять, почему Архиепископ перешёл на сторону \"\n\"тьмы и с какой целью он похитил ребёнка... Возможно, он собирался принести \"\n\"дитя в жертву своим тёмным повелителям!\\n\"\n\" \\n\"\n\"Должно быть, именно это он и задумал! Те из 'спасательной команды', кто \"\n\"остался в живых, говорили, что они видели, как Лазарь бежал всё глубже в \"\n\"мрачные коридоры Лабиринта. Спеши же и спаси принца от жертвенного клинка \"\n\"этого обезумевшего негодяя!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Спеши! Надо спасти Альбрехта от безумного Лазаря. Судьба принца и всего \"\n\"нашего королевства зависит сейчас от тебя!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Твой рассказ заставляет содрогнуться. Лазарь будет гореть в гиене огненной \"\n\"за свои чёрные дела. Тот мальчик не похож на нашего принца, но я думаю, что \"\n\"Альбрехту всё ещё грозит смертельная опасность. Символ, о котором ты \"\n\"говоришь, очевидно является порталом в самое сердце лабиринта.\\n\"\n\" \\n\"\n\"Знай же, друг мой - зло, против которого ты сражаешься, - это порождение \"\n\"тёмного Повелителя Ужаса, имя которого Диабло. Много столетий назад он был \"\n\"заключён в плен внутри Лабиринта. Я боюсь, что он ищет способ опять посеять \"\n\"хаос в мире людей. Тебе необходимо пройти сквозь тот портал и уничтожить \"\n\"Диабло, пока ещё не поздно!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Лазарь был Архиепископом. Он повёл большой отряд горожан в Лабиринт. В тот \"\n\"день я потерял много друзей, и Лазарь тоже не вернулся. Я думаю, что он \"\n\"погиб, как и большинство людей из отряда. Я очень тебя прошу: не говорите с \"\n\"Фарнамом о тех событиях.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Я был поражён, когда услышал, куда жители деревни собрались идти той ночью. \"\n\"Я считал Лазаря здравомыслящим человеком. Но я ошибся. Он был Архиепископом \"\n\"и, казалось, всегда так заботился о жителях Тристрама. Было так много \"\n\"раненых, я не смог всех их спасти...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Я помню Лазаря как очень доброго и щедрого человека. Он произнёс речь на \"\n\"похоронах моей матери, а в тяжёлые времена он очень помогал нам с бабушкой. \"\n\"Я каждый вечер молюсь и надеюсь, что он остался жив и невредим.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Я был одним из тех, кого Лазарь повёл в Лабиринт. Он говорил о святом \"\n\"возмездии, но когда мы дрались с теми адскими отродьями, Лазарь не слишком \"\n\"постарался бить их своей булавой. Он просто углублялся всё дальше и дальше в \"\n\"тёмные нескончаемые коридоры, полные зловещих тварей!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Они колют, потом кусают и окружают со всех сторон! Лжец! ЛЖЕЦ! Они все \"\n\"погибли! Погибли! Слышишь ты? Они всё падают и падают... их кровь бьёт \"\n\"фонтаном и заливает весь пол... это всё его вина...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Я не знала Лазаря, о котором ты говоришь, но я чувствую, что в нём произошла \"\n\"ужасная перемена. Он представляет большую опасность и не остановится ни \"\n\"перед чем, лишь бы услужить тёмным силам, которые им завладели.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"А, праведный Лазарь, как он сражался против тех монстров там, в подземелье. \"\n\"Но это не спасло мою ногу, не так ли? Слушай, я дам тебе бесплатный совет. \"\n\"Спроси Фарнама, он был там.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Оставь свои глупые попытки. Тебя ждёт страшный гнев моего Повелителя! \"\n\"Поздно, ты уже не спасёшь ребёнка. Ты пойдёшь вместе с ним прямо в Ад!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Кгх-кгх, не знаю, что и сказать, чтобы помочь тебе в этом деле. Наши колодцы \"\n\"наполняются водой, которая поступает из подземного источника. Я слышал о \"\n\"туннеле, который ведёт к большому озеру - может быть, это и есть источник. К \"\n\"сожалению, я не знаю, что может являться причиной порчи нашей воды.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Я всегда старался, чтобы у меня в погребе был большой запас продовольствия и \"\n\"питья, но у меня ненадолго хватит воды, когда нужно поить жителей всей \"\n\"деревни. \\n\"\n\" \\n\"\n\"Прошу тебя, помоги нам, иначе я не знаю, что с нами будет.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Как я рад, что встретил тебя! Вода в наших колодцах стала застоявшейся и \"\n\"гадкой, некоторые люди заболели оттого, что выпили её. Наши запасы чистой \"\n\"воды скоро кончатся. Я думаю, что существует проход, ведущий к источникам, \"\n\"которые питают колодцы деревни. Прошу тебя, найди причину этого бедствия, \"\n\"иначе мы все погибнем без воды.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Прошу тебя, поспеши. С каждым часом питьевой воды становится всё меньше и \"\n\"меньше. \\n\"\n\" \\n\"\n\"Если ты не поможешь, мы долго не продержимся.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Что ты говоришь - простое присутствие демонов вызвало порчу воды? О да, в \"\n\"самом деле, ужасное зло притаилось под нашей деревней, но твои упорство и \"\n\"смелость вселяют в нас надежду. Вот, возьми это кольцо - может быть, оно \"\n\"поможет тебе в борьбе с этими отвратительными тварями.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Моя бабушка очень слаба, а Гарда говорит, что нельзя пить воду из колодцев. \"\n\"Если ты можешь как-то нам помочь, то пожалуйста, помоги.\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Пепин правду говорит. Нам очень нужна чистая вода, и как можно быстрее. Я \"\n\"пытался почистить один колодец, но там стоит такая вонь. Должно быть, вода \"\n\"загрязняется у источника.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Ты пьёшь воду?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Жители Тристрама погибнут, если ты не сможешь вернуть в колодцы чистую \"\n\"воду. \\n\"\n\" \\n\"\n\"Знай: это демоны виноваты в случившемся, но им самим неизвестно, что они \"\n\"наделали.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"На этот раз я с тобой согласен. Мои дела идут плохо, если я не буду иметь \"\n\"рынка сбыта. Лучше выясни, что происходит, и поскорее!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"В книге говорится о палате человеческих костей? Палата Костей упоминается в \"\n\"некоторых древних писаниях, которые я изучал в библиотеках Востока. В тех \"\n\"фолиантах написано, что когда Повелители подземного мира желают защитить \"\n\"сокровище от воров, они создают такие места, где душа того, кто погибнет там \"\n\"при попытке похитить сокровища, навечно станет их стражем. Какой парадокс, \"\n\"не правда ли?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Боюсь, мне ничего об этом неизвестно. У Каина есть много книг. Может быть он \"\n\"поможет.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Похоже, это очень опасное место. Будь всё время начеку, если попадёшь туда.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Боюсь, я ничего об этом не слышала. Возможно, Рассказчик Каин сможет вам \"\n\"помочь.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Я ничего не знаю о таком месте, спроси Каина. Он может рассказать много \"\n\"чего, и я не удивлюсь, если у него есть несколько ответов на твой вопрос.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Ладно, слушай. Есть такая палата дерева. И его жена, ты знаешь - говорит, \"\n\"что это дерева... потому как надо подождать. А я ей говорю, это сработает \"\n\"против него, а если ты думаешь, что я ОПЛАЧУСЬ за это... ты... эээ... да.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Ты навечно станешь слугой повелителей тьмы, если тебя постигнет смерть в том \"\n\"проклятом месте. \\n\"\n\" \\n\"\n\"Входи в Палату Костей на свой страх и риск.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Куча сокровищ, говоришь? Хм... Ну, может быть, я и куплю у тебя несколько \"\n\"вещиц... или, куда лучше, если ты купишь у меня что-то редкое и дорогое, что \"\n\"поможет тебе пройти это испытание?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Да, Архиепископ Лазарь заставил многих мужчин деревни отправится в Лабиринт \"\n\"на поиски пропавшего сына Короля Леорика. Он сыграл на их страхе и разжёг их \"\n\"гнев. Но никто из них не был готов к тому, что ожидало их под холодной \"\n\"землёй... Лазарь покинул их, бросил на растерзание ужасным тварям прямо в \"\n\"лапы смерти.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Да, Фарнам бормотал что-то о страшилище, махающим огромным острым топором. \"\n\"Кажется, он называл его мясником.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"О Господи, я знаю об этом гнусном демоне. У тех, кому удалось спастись той \"\n\"ночью выбраться из Собора, были раны, нанесённые этим жестоким чудовищем. Я \"\n\"не знаю, каким оружием он мог искромсать свои жертвы, но оно наверняка не из \"\n\"этого мира. От него оставались раны, гниющие от заразы, и даже я думал, что \"\n\"их невозможно вылечить. Берегись, если собираешься сразиться с этим \"\n\"извергом...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Когда Фарман сказал что-то о Мяснике, который убивает людей, я не поверила. \"\n\"Но если уже ты говоришь о том же, то наверное это правда.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Я видел этого Мясника, как называет его Фарнам. Он косил моих друзей, словно \"\n\"траву. Он махал своим огромным мясницким топором, разрубая отважных бойцов \"\n\"на части прямо на месте. Меня отбросили в сторону толпа маленьких визгливых \"\n\"демонов и я каким-то образом нашёл выход. После того я больше его не видел, \"\n\"но меня в дрожь бросает каждый раз, как я вспоминаю его гримасу, всю в \"\n\"запёкшейся крови.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Огромный! Огромный топор! Он рубил моих друзей, убил их все! Я не мог его \"\n\"остановить, не мог их спасти! Я попался в ловушку, там так много трупов, я \"\n\"хотел убежать... ААГХААГХАА!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Мясник это жестокое чудовище, он получает удовольствие от страданий и боли \"\n\"других. Посмотри, что стало с Фарнамом из-за этого монстра. В деревне станет \"\n\"гораздо безопаснее, если ты его уничтожишь.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Я знаю об этом ужасном демоне куда больше, чем ты думаешь. Его приятели \"\n\"сцапали меня и успели оттяпать мне ногу раньше, чем Гризвольд вытянул меня \"\n\"из этой дыры. \\n\"\n\" \\n\"\n\"Скажу прямо: убей его раньше, чем он убьёт тебя и добавит твой труп к своей \"\n\"коллекции.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Прошу, выслушай меня. Архиепископ Лазарь повёл нас сюда на поиски принца. Но \"\n\"этот подонок заманил нас в ловушку! Все погибли... их убил демон, его зовут \"\n\"Мясник. Отомсти за нас! Найди и убей этого Мясника, чтобы наши души наконец-\"\n\"то нашли покой...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Очень интересно. Этот стих написанный в стиле, который напоминает мне другие \"\n\"произведения. Дай-ка вспомнить - как же там?\\n\"\n\" \\n\"\n\"... Тайна скрыта под саваном темноты. Глаза светятся, но они не видны. \"\n\"Только слышно, как острые когти рвут и пытают души несчастных, которые были \"\n\"навечно лишены зрения. Темница этих обречённых душ зовётся Залом Слепых...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Я никогда не увлекался поэзией. Раньше, когда дела в таверне шли хорошо, я \"\n\"иногда нанимал менестрелей. Ах, это было так давно. \\n\"\n\" \\n\"\n\"Что? Ааа, да... ну... а, я думаю, лучше спроси у кого-нибудь другого.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Я что-то такое припоминаю. Кажется, я уже читал что-то похожее на этот стих, \"\n\"когда изучал историю недугов демонического происхождения. Там говорилось о \"\n\"месте величайшего зла, которое... погоди ка, ты же не собираесся туда пойти?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Если тебя беспокоит слепота, то обратись к Пепину. Он дал моей бабушке \"\n\"снадобье, которое помогло ей поправить зрение. Может быть, он и тебе поможет.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Я никогда не видел места, которое бы было похоже на твоё живописное \"\n\"описание, и ничего такого раньше не слышал. Спроси у Каина, может быть он \"\n\"знает.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"\"\n\"Гляди ка... это так смешно, ха-ха! Понимаешь? Не видишь что-ли? Ахаха. \"\n\"Гляди, ахахахаха!\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Это место страданий и ужаса, оно хорошо служит своему хозяину. \\n\"\n\" \\n\"\n\"Соблюдай там крайнюю осторожность, иначе задержишься там гораздо дольше, чем \"\n\"предполагаешь.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Посмотрим, я тебе что-то продаю? Нет. Ты даёшь мне деньги, чтобы я тебе об \"\n\"этом сказал? Нет. Ты сейчас уходишь, идёшь к рассказчику, которого хлебом не \"\n\"корми, только дай поболтать? Да.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Ты утверждаете, что с тобой говорил Лахдананом? При жизни он был отважным \"\n\"героем, благородным и справедливым человеком. Он много лет верно служил \"\n\"Королю Леорику. Да, ты, наверное, уже знаешь об этом.\\n\"\n\" \\n\"\n\"Я уверен, что именно Лахданан никогда бы не покорился тёмным силам и не \"\n\"смирился бы с проклятой судьбой, которая постигла людей Леорика. Поэтому, я \"\n\"думаю, что эта история правдива. На твоём месте я бы постарался найти способ \"\n\"избавить его от мучений.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Ты говоришь о храбром воине, который давно умер? Я бы ни за что не стал бы \"\n\"беседовать с таким покойником. Нет уж увольте.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Золотой эликсир, говоришь? Я никогда не готовил снадобье такого цвета, и \"\n\"посему не могу знать, как оно на тебя подействует, если ты его выпьешь. Как \"\n\"твой лекарь, я очень тебе советую, если вы найдёте такой эликсир, поступи \"\n\"как просит Лахданан, и НЕ применяй его на себе.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Я никогда раньше не слышала о Лахданане. К сожалению, тут я ничем не могу \"\n\"тебе помочь.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Если то и вправду был Лахданан, то я советую тебе помочь ему. Я несколько \"\n\"раз встречался с ним и считаю, что он был честным человеком, верным своему \"\n\"долгу. Проклятье, постигшее соратников Короля Леорика, было бы особенно \"\n\"тяжело для него.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Лахданан умер. Все об этом знают, и ты меня не надуешь, я своего мнения не \"\n\"изменю. Мертвец не может разговаривать. Я же знаю!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Ты можешь встретить людей, которые остались пленниками лабиринта, как \"\n\"Лахданан. \\n\"\n\" \\n\"\n\"Я чувствую в нём благородство. Помогите ему, и ты поможешь всему Тристраму.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Стой, дай угадаю. Каина проглотила огромная пропасть, которая вдруг \"\n\"разверглась у него под ногами. Или он сгорел в шаре адского огня и больше не \"\n\"смог отвечать на твои вопросы. О, этого не случилось? Ну тогда ты что-нибудь \"\n\"купишь у меня или пойдёшь дальше своей дорогой.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Прошу, не убивай меня, выслушай мой рассказ. Когда-то я был Капитаном \"\n\"Рыцарей Короля Леорика, мы поддерживали законы порядка и справедливости. А \"\n\"потом нас настигло чёрное Проклятие за то, что мы были виноваты в смерти \"\n\"Короля. Мои товарищи покорились своей ужасной судьбе, но я сбежал из \"\n\"королевской усыпальницы, надеясь найти способ снять с себя Проклятие. Но я \"\n\"не смог...\\n\"\n\" \\n\"\n\"Я слышал о Золотом Эликсире, который способен снять Проклятие и дать покой \"\n\"моей душе, но я не смог его найти. Силы покидают меня, а вместе с ними я \"\n\"теряю всё человеческое, что во мне осталось. Прошу тебя, помоги мне, найди \"\n\"Золотой Эликсир. Клянусь честью - я отблагодарю тебя.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Тебе не удалось найти Золотой Эликсир. Боюсь, я проклят навечно. Прошу тебя, \"\n\"продолжай поиски...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Теперь моя душа спасена, я твой должник. Я найду способ отблагодарить тебя \"\n\"за помощь, а пока что - возьми мой шлем. Там, куда я направляюсь, он мне не \"\n\"понадобиться. Пусть он защитит тебя от тёмных сил подземного мира. Да \"\n\"прибудет с тобой Свет, друг мой...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Гризвольд говорит о Дьявольской Наковальне. Ооо, это легендарный артефакт. \"\n\"Многие долго его искали, но так и не нашли. Она выплавлена из металлических \"\n\"костей демонов, обитающих в Яме Лезвий и отделана черепами пяти самых \"\n\"могущественных магов подземного мира. Если оружие изготовлено на Дьявольской \"\n\"Наковальне, на нём есть руны сил Хаоса, и она имеет волшебные свойства. \"\n\"Трудно сказать, что за оружие может получиться у кузнеца, так как природа \"\n\"Хаоса непредсказуема...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Тебе не кажется, что лучше спросить об этом у Гризвольда? Он с радостью тебе \"\n\"поможет.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Если бы тебе хотелось узнать что-нибудь об Исцеляющем Пестике или Серебряной \"\n\"чаше очищения, я мог бы о них рассказать, друг мой. Но в этом деле тебе \"\n\"лучше обратиться за помощью к Гризвольду или Каину.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Когда мы были детьми, отец Гризвольда часто рассказывал нам о гигантской \"\n\"наковальне, на которой ковалось мощное оружие. Он говорил, что когда молот \"\n\"ударял по этой наковальне, земля сильно сотрясалась. И каждый раз, когда \"\n\"трясётся земля, я вспоминаю этот рассказ.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Приветствую тебя! Всегда приятно видеть одного из лучших клиентов! Я знаю о \"\n\"твоём походе в глубину Лабиринта, и хочу рассказать тебе одну историю, \"\n\"которую тебе стоит послушать...\\n\"\n\" \\n\"\n\"Один из людей, которому удалось выбраться из Лабиринта, рассказал мне о \"\n\"волшебной наковальне, которую он там видел. Его рассказ напомнил мне \"\n\"легенду, которую я слышал в юности. В легенде говориться об Адской Кузнице, \"\n\"где ковалось мощное оружие, обладавшее волшебной силой. В той Адской Кузнице \"\n\"была Дьявольская Наковальня! Эта Наковальня содержала в себе самую сущность \"\n\"демонического мира...\\n\"\n\" \\n\"\n\"Любое оружие, изготовленное на Дьявольской Наковальне, обладает огромной \"\n\"силой. Если то в самом деле была Дьявольская Наковальня, я выковал бы на ней \"\n\"для тебя такое оружие, которым можно победить самого повелителя Ада! \\n\"\n\" \\n\"\n\"Найди Дьявольскую Наковальню и принеси её мне, вот тогда я примусь за работу!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Ещё не удалось найти, да? Продолжай поиски. Оружие, сделанное на этой \"\n\"Наковальне, лучшее из всего, что у тебя будет. Я уверен, что смогу сделать \"\n\"нечто легендарное.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Глазам своим не верю! Это же Дьявольская Наковальня - молодец. Теперь мы \"\n\"покажем этим гадам, что даже в Аду нет оружия более смертоносного, чем то, \"\n\"которое может сделать человек! Возьми его, и да прибудет с тобой Свет.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Гризвольд не продаст свою наковальню. Что же он тогда будет делать? Иди \"\n\"набудумбам хаха прф ха!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"В Лабиринте много артефактов, содержащих магию, которую надо осмыслить \"\n\"простым смертным. Некоторые из них обладают фантастической силой, которую \"\n\"можно использовать и в злых, и в добрых целях. Если отобрать Дьявольскую \"\n\"Наковальню у сил зла, можно использовать её для добра.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Если ты найдёшь для Гризвольда этот артефакт, это будет серьёзным ударом по \"\n\"моему бизнесу. А, ты всё равно никогда его не найдёшь.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Ворота Крови и Зал Огня? Это места, покрытые тайной. Без сомнения, в той \"\n\"книге говориться о месте, обладающем великой силой.\\n\"\n\" \\n\"\n\"В легендах говориться о пьедестале, высеченном из обсидиана. На верхушке \"\n\"пьедестала есть чаша, сделанная из резной кости. Та чаша наполнена кипящей \"\n\"кровью. В легендах также упоминаются кровавые камни, открывающие дверь, за \"\n\"которой лежит древнее сокровище...\\n\"\n\" \\n\"\n\"Можно только догадываться, что это за сокровище, но известно, что герой \"\n\"древности Аркейн спрятал священные Доспехи Отвага в тайнике. Аркейн был \"\n\"первым из смертных, которому удалось повернуть ход Войны Грехов и прогнать \"\n\"легионы исчадий тьмы обратно в Ад.\\n\"\n\" \\n\"\n\"Как раз перед своей смертью, Аркейн спрятал свои доспехи в тайник. И \"\n\"сказано, что когда Отвага снова понадобится для борьбы с тёмными силами, \"\n\"придёт герой, облачиться в священные доспехи. Может быть, ты и есть тот \"\n\"герой...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Каждому ребёнку известна легенда о доблестном Аркейне и его волшебных \"\n\"доспехах Отвага. Если ты найдёшь эти доспехи, они будут тебе хорошей защитой \"\n\"от зла, царящего в Лабиринте.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Хм... я, кажется, помнил об этом, но я был так занят изучением новых \"\n\"лекарств и созданием более сильных эликсиров, что, наверное, забыл об этом. \"\n\"Извини...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Я часто слышала, как мальчишки говорили о волшебных доспехах, которые \"\n\"называются Отвага. Ты лучше спроси у какого-нибудь мужчины из деревни.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Доспехи, что называются Отвага, были бы тебе хорошей защитой. Многие \"\n\"пытались найти их, в том числе и я. Аркейн хорошо спрятал их, друг мой. \"\n\"Одного везения недостаточно, чтобы разгадать секреты, которые скрывают эти \"\n\"доспехи уже так много лет.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Хррррррррррррррррррррррррррррррр...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Если найдёшь Кровавые Камни, используй их с умом. \\n\"\n\" \\n\"\n\"Твой путь полон опасностей, но уверенность в своих силах вселяет надежду на \"\n\"успех.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Ты хочешь найти доспехи Отвага?\\n\"\n\" \\n\"\n\"Никто не знает, где Аркейн их спрятал, и никому ещё не удавалось их найти. Я \"\n\"очень сомневаюсь, что тебе это удастся.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Я знаю только одну легенду, в которой говорится об этом воине. Его историю \"\n\"можно прочитать в древних летописях Войны Грехов...\\n\"\n\" \\n\"\n\"Погрязший в жестокости за тысячу лет войны и смерти, Кровавый Генерал \"\n\"попирает ногами гору, сложенную из своих растерзанных жертв. Его тёмный \"\n\"клинок несёт чёрное проклятие всему живому, и мучения тому, кто предстанет \"\n\"перед этим Палачом Преисподней.\\n\"\n\" \\n\"\n\"Когда-то он был простым смертным и во время Войны Грехов воевал в рядах \"\n\"Легиона Тьмы, но его жажда кровопролития была настолько велика, что он \"\n\"потерял свой человеческий облик.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Я никогда не слышал о таком жестоком воине. Я надеюсь, тебе не придётся \"\n\"сражаться с ним. Похоже, он чрезвычайно опасен.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Каин мог бы рассказать тебе об этом гораздо больше, чем я, и даже больше, \"\n\"чем это необходимо.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Если тебе придётся сразиться с таким свирепым врагом, пусть Свет будет твоим \"\n\"проводником и защитником. Я помолюсь за тебя.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Зловещие легенды окружают имя Кровавого Генерала. Хорошо подготовься к \"\n\"встречи с ним, он безжалостный и беспощадный.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Чего ты всё время говоришь о Крови? Поговорим лучше о цветах, о солнышке, о \"\n\"той милашке, которая приносит выпивку. Слушай: у тебя наверное навязчивая \"\n\"идея?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Он мастерски владеет оружием, он тысячи лет не знал ничего, кроме войны. К \"\n\"сожалению... Я не знаю, сможешь ли ты его победить.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Я никогда не встречал этого Генерала, о котором ты говоришь. Похоже, ему \"\n\"нужно много мечей. Я бы не отказался продать ему оружие для его армии...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Мой клинок жаждет твоей крови, смертный, и мои тёмные повелители не \"\n\"отвергнут её.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Гризвольд говорит о Небесном Камне, который везли в королевство на востоке. \"\n\"Тамошние мудрецы должны были заняться изучением этого камня. Он излучал \"\n\"энергию, которая давала человеку способность видеть то, что обычно \"\n\"недоступно его взгляду. Я не знаю, в чём секрет Небесного Камня, но я \"\n\"уверен, что он бы очень тебе пригодился.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Здесь останавливался обоз, чтобы запастись провизией для дальнего \"\n\"путешествия на восток. Я продал им довольно много свежих фруктов и сладких \"\n\"пирогов, которые испекла Гарда. Как жалко, что с ними такое случилось...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Я не знаю, что они собирались увидеть с помощью этого камня, но могу сказать \"\n\"одно - если камни падают с неба , то надо быть осторожным!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Здесь останавливался торговый обоз, его вели какие-то важные люди, но это \"\n\"было довольно давно. Припоминаю, что у этих людей был странный акцент и они \"\n\"готовились к долгому путешествию. \\n\"\n\" \\n\"\n\"Не знаю, как ты можешь надеяться найти что-нибудь из того, что они везли.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Подожди минуту - я расскажу тебе кое-что. Может, это тебя заинтересует. Не \"\n\"так давно тут останавливался торговый обоз, который направлялся на восток. \"\n\"Ходили слухи, что он вёз кусочек небес, который упал на землю! На дороге, к \"\n\"северу отсюда, на тот обоз напали из засады всадники, одетые в плащи. Я \"\n\"потом искал среди обломков тот небесный камень, но так и не нашёл. Если ты \"\n\"его найдёшь, то я смогу сделать из него какую-нибудь полезную вещь.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Я всё ещё жду, что ты принесёшь мне тот камень, упавший с небес. Я уверен, \"\n\"что смогу сделать из него чудесную вещь.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Ну ка посмотрим... Да-да, это то, что я думал. Подожди минутку...\\n\"\n\" \\n\"\n\"Ну вот, держи. Я установил куски камня в серебряное кольцо, которое осталось \"\n\"мне от отца. Надеюсь, оно тебе пригодиться.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"У меня было красивое кольцо; и оно было дорогое, серебряное, с голубым, \"\n\"зелёным и красными камнями. Но я не помню, куда оно подевалось. Мне так \"\n\"нравилось это колечко...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Небесный Камень обладает великой силой, и если бы не Гризвольд, я бы \"\n\"запретила тебе искать его. Гризвольд сможет обуздать его силу и направить её \"\n\"на благо всем нам.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Только Гризвольд способен сделать что-нибудь из этого камня. Он знает, что \"\n\"делает. Хоть я и пытаюсь переманивать его клиентов, я уважаю качество его \"\n\"изделий.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Ведьме Адрии нужен чёрный гриб? Я знаю о Чёрных грибах не больше, чем о \"\n\"красной селёдке. Может быть, лекарь Пепин расскажет тебе больше, а в моих \"\n\"книгах и легендах я ничего такого не встречал.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Вот что я скажу - ни я, ни Гарда, НИКОГДА и ни за что не подаём гостям \"\n\"никаких чёрных грибов. Если Адрии нужны грибы для рагу, это её личное дело, \"\n\"но я ничем не могу тебе помочь. Чёрные грибы... такая гадость!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Адрия сказала, что ты ищешь мозги демона, чтобы помочь мне сделать мой \"\n\"эликсира. Это будет прекрасное лекарство для многих людей, раненых теми \"\n\"грязными тварями, если только мне удастся разгадать секрет его \"\n\"приготовления, которые. Если ты сможешь взять мозги демона, когда убьёшь \"\n\"его, то принеси их мне, я буду очень благодарен.\"\n\n# В озвучке Пепин просит отнести ей мозги, что является ошибкой озвучки Stream\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Отлично, это то, что мне нужно. Правда, я и так уже сделал этот эликсир, но \"\n\"они пригодятся для изучения. Отнеси эликсир пожалуйста Адрии. Я думаю, он \"\n\"может ей понадобиться.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Я думаю, в погребе у Огдена должны быть грибы. Почему бы тебе не спросить у \"\n\"него?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Если даже у Адрии этого нету, то держу пари, что это очень большая редкость. \"\n\"Ни с чем не могу тебе помочь. Скажу только, что это должно быть... большой, \"\n\"огромный, здоровенный, гигантский гриб! Ну, желаю удачной охоты.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Огден делает настойку из чёрного гриба, но мне от неё дурно. Слушай, \"\n\"слушай... вот в чём секрет - во всём нужно знать меру!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Что у нас тут? Интересно. Похоже, это книга о составлении зелий. Вот что. \"\n\"Надо найти чёрный гриб. Он должен быть очень большим и его будет легко \"\n\"распознать. Если найдёшь, принеси его мне, хорошо?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Именно чёрный гриб мне и нужен. Беги и принеси его мне, тогда я смогу \"\n\"сделать из него особое зелье.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Да, это прекрасно подойдёт для моего нового зелья. Кстати, лекарю нужны \"\n\"мозги какого-то демона, чтобы лечить больных, которые отравлены ядом этой \"\n\"твари. Я думаю, что он хочет приготовить какой-то элексир. Если ты \"\n\"раздобудешь для него мозги демона, то постарайся принести мне немного этого \"\n\"элексира.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Зачем было приносить это мне? Мне сейчас не нужны мозги демона. Мне нужен \"\n\"образец эликсира, который приготовит Лекарь. Отнеси ему этот смехотворный \"\n\"орган, который ты сейчас держишь в руках, а мне принеси эликсир. Ведь это же \"\n\"так просто, если пораскинуть мозгами?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Что? Теперь ты приносишь мне элексир Пепина? Я и сама уже смогла изготовить \"\n\"такой элексир. Можешь оставить его себе...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"Я никогда не торгую грибами. Как насчёт чего-нибудь более полезного?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Значит, легенда о Карте не выдумка. Даже я никогда не верил, что это правда! \"\n\"Думаю, пришло время рассказать тебе, кто я такой на самом деле. Понимаешь, я \"\n\"не совсем такой, каким кажусь...\\n\"\n\"\\n\"\n\"Моё настоящее имя - Старейшина Декард Каин, и я последний из древнего \"\n\"Братства, которое хранило в тайне секреты вечного зла. А сейчас это зло, по \"\n\"всей видимости, вырвалось наружу.\\n\"\n\"\\n\"\n\"То зло, против которого ты сражаешься, - это порождение тёмного Повелителя \"\n\"Ужаса, известного для смертных под именем Диабло. Это он попал в плен в \"\n\"глубине Лабиринта много-много столетий тому назад. Карта, которую ты \"\n\"держишь, была сделана очень давно. На ней обозначено время, когда Диабло \"\n\"освободиться из своего заключения. Когда эти две звезды, изображённые на \"\n\"карте, станут в один ряд, Диабло будет в зените своего могущества. Победить \"\n\"его будет почти невозможно...\\n\"\n\" \\n\"\n\"Торопись, друг мой! Сейчас важно выиграть время! Найди и уничтожь Диабло \"\n\"раньше, чем звёзды станут в одну линию, иначе мир никогда не избавиться от \"\n\"его зла!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Наше время на исходе! Я чувствую возрастание его тёмной силы, и только вы \"\n\"можете помешать ему достичь полной мощи.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Я уверен, что вы старались изо всех сил, но боюсь, что даже вашей силы и \"\n\"воли может не хватить. Диабло сейчас находится на пике своего возможного \"\n\"могущества, и вам понадобится вся ваша храбрость и сила, чтобы победить его. \"\n\"Пусть Свет защитит и направит вас, друг мой. Я помогу, чем смогу.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Если ведьма не может тебе помочь и посылает тебя к Каину, то почему ты \"\n\"думаешь, что мне об этом что-либо известно? Похоже, это очень серьёзное \"\n\"дело. Лучше сделать так, как сказала Адрия - поговори с Каином.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Не понимаю, что написано на этой карте. Может быть, Адрия и Каин помогут \"\n\"тебе расшифровать её. \\n\"\n\" \\n\"\n\"Я только вижу, что это карта звёздного неба. Всё остальное я понять не в \"\n\"состоянии.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Лучше всего спросить об этом нашего рассказчика. \\n\"\n\" \\n\"\n\"Каин хорошо разбирается в древних загадочных письменах, а эта бумага \"\n\"выглядит самой старой из всех, что я когда-либо видела.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Что это за карта? Я никогда ещё не видел такой карты. Не могу понять, что \"\n\"тут написано. Может быть, Каин или Адрия помогут тебе разобраться в ней.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Слушай сюда, подойди поближе. Я не знаю, знаешь ли ты, что знаю я, но тут у \"\n\"тебя есть что-то интересное. Эта карта.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Ооо, боюсь, это не предвещает ничего хорошего. Звёзды, изображённые на \"\n\"карте, сулят страшную беду, но я не в праве раскрыть эту тайну. Пришло время \"\n\"откровенно поговорить с Рассказчиком Каином...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Я ищу одну карту, но это не она. Покажи её Адрии - может быть она скажет, \"\n\"что это за карта. Я могу сказать одно: она очень старинная, а старинные вещи \"\n\"дорого ценят.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"Не бееей меня, не убееей меняяя. Обещаааю, я тебеее пригожууусь.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Я тебеее что-то дааам. Не бееей Гарбааада, пожалееей. \\n\"\n\" \\n\"\n\"Бееери это, я выполняю обещанияаа...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Я скоро тебеее что-то дааам. \\n\"\n\" \\n\"\n\"Что-то очень сииильное. Не бееей меняаа! \\n\"\n\" \\n\"\n\"Не бееей, и я сдержууу обещаниеее!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"\"\n\"Слишком хорооошеее для тебяаа. Очень сииильноеее-е-е! Хо-очешь - по-олучааай!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Что такое?! Что ты здесь делаешь? Кого угодно сведут с ума эти непрошенные \"\n\"гости, ге-ге-ге-ге-ге. Вот возьми и убирайся. И больше не мешай мне работать!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Ааааргх! Ты умрёшь из-за своего любопытства!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Здравствуй, друг мой. Послушай мои рассказы...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Когда ты будешь спускаться глубже в Лабиринт, ты будешь находить книги, \"\n\"содержащие великие знания. \\n\"\n\" \\n\"\n\"Внимательно читай их. Там может быть написано то, чего не знаю даже я.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Я знаю много легенд и мифов, в которых можно найти ответы на многие вопросы, \"\n\"которые у тебя возникнут в Лабиринте. Если у тебя будут какие-то \"\n\"затруднения, приходи ко мне и я расскажу тебе всё, что знаю об этом.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Гризвольд - это очень деятельный и смелый человек. Держу пари, что он не \"\n\"рассказывал тебе, как он вытянул Вирта из Лабиринта. Ему пришлось пережить \"\n\"немало опасностей, пока он был там. Кгх-кгх, да, и тебе ведь тоже. Он умелый \"\n\"мастер, и если он говорит, что поможет тебе, то можешь положиться на его \"\n\"честность и мастерство.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Огден почти четыре года назад открыл здесь постоялый дом под названием \"\n\"\\\"Восход\\\". Он купил его всего за несколько месяцев до того, как всё здесь \"\n\"пошло к верху дном . Он и его жена Гарда почти не имеют денег на жизнь, так \"\n\"как они вложили всё своё состояние в обустройство дома и постоялого двора. \"\n\"Огден - хороший и совестливый человек.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Бедняга Фарнам. Он - постоянное напоминание о том проклятом дне, когда \"\n\"Лазарь повёл группу жителей деревни в Собор. Ему удалось спастись, но он \"\n\"навсегда потерял свою храбрость и рассудок в тёмных коридорах Лабиринта. \"\n\"Теперь он ищет забвение на дне пивной кружки, но иногда в его бессвязной \"\n\"речи ещё проскакивают слова правды.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Ведьма Адрия - это нечто особенное в Тристраме. Она приехала сюда вскоре \"\n\"после того, как Собор был осквернён, а большинство людей старались уехать \"\n\"отсюда. Она живёт на краю деревни в небольшой хижине, которую она соорудила \"\n\"за одну ночь. У неё есть много загадочных артефактов и книг, каких даже мне \"\n\"раньше не случалось видеть.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"История о Вирте страшна и трагичная. Отвратительные демонята вырвали его \"\n\"прямо из рук матери и утащили в Лабиринт. В тот день пропало много детей, в \"\n\"том числе и сын Короля Леорика. Королевские рыцари отправились в подземелье, \"\n\"но так и не вернулись. Кузнец нашёл мальчика, но гнусные твари уже пытали \"\n\"его, чтобы доставить себе садистское удовольствие.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"А, Пепин. Это честный человек и мой самый близкий друг. Временами он бывает \"\n\"рассеянным, но у него добрейшая в мире душа. Немногие сравняться с ним в \"\n\"искусстве врачевания. Его дверь всегда открыта.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Джиллиан - прекрасная женщина. Многие любят её за жизнерадостный и весёлый \"\n\"характер. В моём сердце она занимает особое место. Она работает в таверне, \"\n\"чтобы поддерживать свою больную бабушку. Я часто беспокоюсь за Джиллиан, но \"\n\"я знаю, что любой мужчина в деревне ни за что не даст её в обиду.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Приветствую тебя! Добро пожаловать в Таверну \\\"Восход\\\"!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Много путешественников побывало в моей таверне, и ещё больше историй было \"\n\"рассказано за кружкой доброго пива. И всех их объединяет одна непреложная \"\n\"истина - мясо можно резать, но кости нужно рубить. Запомни это на будущее.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Кузнец Гризвольд хорошо разбирается во всевозможном оружии и доспехах. Если \"\n\"тебе будет нужно починить снаряжение, можешь обращаться к нему.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Фарнам проводит здесь много времени, стараясь утопить свои горести в кружке \"\n\"дешёвого пива. Я бы прогнал его, но он так натерпелся в Лабиринте, бедняга.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Адрия - очень мудрая старуха. Должен признаться, я её немного боюсь. \\n\"\n\" \\n\"\n\"Но это не важно. Если тебе нужно купить или продать какие-нибудь волшебные \"\n\"вещи, то иди к ней, у неё полно всякой всячины. Она живёт за рекой.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Если хочешь знать историю нашего края, послушай рассказчика Каина. Он может \"\n\"многое поведать о прошлом.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Вирт - это маленький мошенник и пройдоха. Он всегда попадал в неприятности и \"\n\"неудивительно, что с ним случилось такое несчастье. \\n\"\n\" \\n\"\n\"Наверное, он сунул свой нос не туда, куда следовало бы. Мне жаль мальчишку, \"\n\"но я терпеть не могу его приятелей.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Пепин хороший человек - и самый добрый в нашей деревне. Он всегда заботится \"\n\"о других людях, но на его голову вечно сваливаются какие-нибудь \"\n\"неприятности...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Джиллиан? Моя помощница? Если бы не её чувство долга по отношению к бабушке, \"\n\"она уже б давно уехала отсюда. \\n\"\n\" \\n\"\n\"Бог свидетель - я уговаривал её уехать, обещал, что позабочусь о её бабушке, \"\n\"но она очень хорошая девушка и не захотела так поступить.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Что у тебя болит?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Я сделал очень интересное открытие. В отличие от нас, обитатели Лабиринта \"\n\"могут лечить себя без помощи снадобий и магии. Если ты победишь такое \"\n\"чудовище, убедись, что оно мертво, иначе оно очень скоро само себя излечит.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"До того, как Собор заполнили демоны, он был местом, где хранилось много \"\n\"знаний. Там можно найти множество книг. Если ты будешь находить книги, \"\n\"обязательно читай их. В них могут быть разгадки к тайнам Лабиринта.\"\n\n# Искусство врачевания. Хаха! Stream приколисты\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Гризвольд знает об искусстве ведения боя также много, как я об искусстве \"\n\"врачевания. Он ловкий торговец, но в работе ему нет равных. Наверное это \"\n\"потому, что он единственный кузнец, оставшийся в деревне.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Каин - настоящий друг и мудрый человек. У него огромная библиотека. Он имеет \"\n\"дар видеть истинную природу многих вещей. Если ты не можешь найти ответы на \"\n\"какие-то вопросы, то обращайся к нему.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Даже моего умения не хватило, чтобы вылечить Фарнама. Да, я смог вылечить \"\n\"его телесные раны, но не могу восстановить его дух и рассудок.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Я совсем мало пользуюсь волшебством, когда готовлю свои зелья и эликсиры, а \"\n\"вот Адрия - настоящая колдунья. Кажется, она никогда не спит. У неё всегда \"\n\"много таинственных книг и артефактов. Я думаю, что её домишка не такой уж \"\n\"простой, как выглядит, но я очень сомневаюсь, что когда-нибудь попаду внутрь \"\n\"её жилища.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Бедный Вирт. Я сделал всё что мог для этого ребёнка, но я знаю, что он \"\n\"ненавидит эту деревяшку, которую я был вынужден прикрепить ему вместо ноги. \"\n\"Его раны были ужасными. Никто не должен испытывать такие страдания, особенно \"\n\"такое малое дитя.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Не понимаю, почему Огден не уезжает из Тристрама. У него нервы немного не в \"\n\"порядке, но он очень умный и трудолюбивый человек. Он мог бы хорошо \"\n\"устроиться где-нибудь в другом месте. Я полагаю, он напуган тем, что на \"\n\"просёлочных дорогах часто убивают путников, а может быть, это его жена не \"\n\"хочет сниматься с места и уезжать.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Помощница Огдена - милая девушка. Её бабушка очень больна и страдает \"\n\"галлюцинациями. \\n\"\n\" \\n\"\n\"Она утверждает, что это видения, но я не могу подтвердить - то это или \"\n\"другое.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Добрый день! Чем я могу служить?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Моей бабушке приснился сон, что ты придёшь и будешь разговаривать со мной. \"\n\"Знаешь, у неё бывают видения будущего.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Женщина, живущая на краю деревни - ведьма! Она кажется довольно приятной, её \"\n\"имя, Адрия, ласкает слух, но я её очень боюсь. \\n\"\n\" \\n\"\n\"Только кто-то очень смелый, как ты, может пойти и посмотреть, чем она там \"\n\"занимается.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Наш кузнец - это гордость нашей деревни. Он прославился своим мастерством и \"\n\"победил во многих соревнованиях не только в своей гильдии, но даже заслужил \"\n\"похвалы от самого Короля Леорика - мир его праху. А ещё Гризвольд настоящий \"\n\"герой; вот спроси у Каина.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Сколько себя помню, столько Каин был рассказчиком в Тристраме. Он так много \"\n\"знает, что может рассказать всё обо всём или почти всё почти обо всём.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Фарнам - пьяница, который наполняет своё брюхо пивом, а уши других людей \"\n\"всякой чепухой. \\n\"\n\" \\n\"\n\"Я знаю, что Пепин и Огден жалеют его, но я так расстраиваюсь, когда вижу, \"\n\"как он каждый вечер всё больше и больше впадает в состояние пьяного дурмана.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Пепин спас жизнь моей бабушки. Я никогда не смогу его отблагодарить. Его \"\n\"умение лечить всякие болезни гораздо сильнее самого мощного меча и \"\n\"таинственнее любого заклинания, которое ты можешь назвать. Если тебе когда-\"\n\"нибудь понадобиться лекарь, то Пепин поможет тебе.\"\n\n# В озвучке Канос, хз как правильно\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Я росла вместе с Канос - матерью Вирта. Не смотря на то, те ужасные твари, \"\n\"которые утащили её сына, только слегка её зацепили, она так и не \"\n\"выздоровела. Я думаю, она умерла от горя. Вирт стал злым подростком. Он ищет \"\n\"выгоду только в том, что заставляет других попотеть. Я знаю, что он страдал \"\n\"и видел ужасы, которые я даже не могу себе представить, но в его душе \"\n\"остался след от того мрака.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Огден и его жена взяли меня и бабушку к себе домой и даже дали мне \"\n\"возможность зарабатывать кое-какие деньги в гостинице. Я так многим им \"\n\"обязана. Я надеюсь, что когда-нибудь мы уедем отсюда на восток и я помогу им \"\n\"открыть там большой отель.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Эй, я могу тебе помочь?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Если тебе нужно хорошее оружие, я покажу тебе вот это. Взять, например, \"\n\"простую булаву. Действует безотказно на тех бессмертных уродов, что рыщут в \"\n\"подземельях, и никакое другое оружие не раздробит ходячие скелеты лучше, чем \"\n\"булава!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Топор? Да, это хорошее оружие, сильное против любого врага. Смотри, как он \"\n\"рассекает воздух, и представь, как он обрушивается на голову какого-нибудь \"\n\"жирного демона. Однако надо помнить, что он тяжёл и замедляет движения!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Посмотри как сверкает это лезвие. Меч - это царь оружия, если он в умелых \"\n\"руках и направлен против того врага. Меч причинит мало вреда ходячему \"\n\"мертвецу, но нет ничего лучше меча, чтобы рубить врага из крови и плоти!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Твоё оружие и доспехи будут получать отметины в боях с силами Тьмы. Приноси \"\n\"их ко мне, и я смогу починить их так, что они будут как новенькие после \"\n\"того, как побывают в моём жарком горле.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Мне приходиться заниматься контрабандой, чтобы доставать нужные металлы и \"\n\"инструменты с обозов, которые проходят мимо нашей проклятой деревни, а этой \"\n\"ведьме Адрии всегда удаётся получить всё, что она хочет. Если я бы хоть \"\n\"немножко умел колдовать, как она, я бы мог делать такие потрясающие вещи.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Джиллиан - хорошая девушка. Жаль, что её бабушка так больна, а то бы я помог \"\n\"им собраться и уехать отсюда вместе с одним из торговых обозов.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Иногда мне кажется, что Каин слишком много говорит, но, наверное, это его \"\n\"призвание. Если бы я так работал с металлом, как он с ушами людей, я бы \"\n\"смастерил герб, достойный самого Императора!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Я и Фарнам были в отряде, который Лазарь повёл в Лабиринт той ночью. После \"\n\"того я больше не видел Архиепископа, да и я бы не выжил, если бы Фарнам не \"\n\"был со мной рядом. Боюсь, тот бой так искалечил его душу, как... Ах, что \"\n\"говорить - а мне искалечили ногу. Жаль, но теперь нельзя ничего исправить.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Тот, кто заботиться о других, а не о себе - хороший человек. Никто в \"\n\"Тристраме - да и вообще никто - не скажет худого слова о лекаре Пепине.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Этот парень когда-нибудь попадёт в беду, вернее... опять попадёт в беду. Я \"\n\"пытался привлечь его к работе в кузнице и научить его вести честную \"\n\"торговлю, но ему больше нравиться получать большие прибыли от торговли \"\n\"сомнительным товаром. Я не виню его за это, ведь на его долю выпало такое \"\n\"горе, просто хочу, чтобы он хоть как-то остепенился.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"У хозяина гостиницы дела идут не блестяще - он почти не имеет прибыли. Ему \"\n\"еле удаётся свести концы с концами, обеспечивая пищу и жильё для тех, кто \"\n\"случайно проходит через нашу деревню, но чаще постояльцы тихонько смываются \"\n\"ночью, не заплатив ему. Если бы не запасы пшеницы и вяленого мяса, которое \"\n\"он хранил в погребе, тогда бы почти все жители деревни умерли с голоду в тот \"\n\"первый год, когда демоны заполонили все леса и поля.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Даже выпить не дают спокойно!\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"Девушка, что приносит выпить? О да, она хорошая девушка. И такая милая.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Почему эта старая карга не сделает чего-нибудь взамен? Точно-точно, у неё \"\n\"навалом всякой всячины, но послушай... она ненастоящая. Я никогда не видел, \"\n\"чтобы она ела или пила - и нельзя же доверять тому, кто совсем не пьёт.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Каин не тот, за кого он себя выдаёт. Да, он умеет рассказывать всякие \"\n\"истории... но такие страшные, а то и смешные... но я думаю, он знает гораздо \"\n\"больше.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Гризвольд? Старый добрый Гризвольд. Я люблю его как брата! Мы сражались бок-\"\n\"о-бок, знаешь ли, тогда... мы... Лазарь... Лазарь... Лазарь!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Хехехе, мне нравится Пепин. Он старается, знаешь ли. Послушай, обязательно \"\n\"сходи к нему. Он всегда помогает, чем кого надо лечить. Эй, а ведь тебе \"\n\"часто нужна помощь лекаря, правда. Я тоже когда-то был бравым солдатом, да...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"У Вирта проблемы похлеще, чем у меня, а я уж знаю, что такое проблемы. \"\n\"Послушай, этот паренёк не подарок, но он был там, ну, знаешь где. Потерял \"\n\"ногу! Теперь ходит на деревяшке. Какое несчастье, как жалко...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Огден - самый лучший человек в деревне. Я не очень нравлюсь его жене, но \"\n\"пока она наливает мне из бочонка, я ничего против неё не имею. Кажется, я \"\n\"провожу больше всего времени у Огдена. Он так добр ко мне...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Я тебе скажу кое-что, я всё об этом знаю. Это моя специальность. Это здесь \"\n\"самое лучшее... самое лучшее! Какое другое пиво - дрянь... с тех пор, как \"\n\"эти дурные псы...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Никто меня ни... когда не слушает. Где-то - не помню где - где-то под \"\n\"церковью лежит целая куча золота. Она блестит, сверкает и только и ждёт, \"\n\"чтобы её кто-нибудь забрал.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Я знаю, что ты думаешь, и ты мне, конечно, не поверишь, но вот твоё оружие, \"\n\"- ерунда против тех здоровых скотов. Мне всё равно, что говорит Гризвольд, \"\n\"сейчас уже никто не может делать такого оружия, как в старые добрые \"\n\"времена...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Если б я был ты... а я не ты... но если б я был, я бы продал все свои вещи и \"\n\"убрался отсюда подальше. Тот мальчишка... У него всегда имеется что-то \"\n\"хорошее, но надо дать ему золота, иначе он даже не покажет тебе, что у него \"\n\"там.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Я чую душу в поисках ответов...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Мудростью не одаривают, её надо приобретать. Если ты найдёшь книгу знаний, \"\n\"жадно поглощай её слова. Если же тебе уже известны древние тайны, написанные \"\n\"в книге, то помни: совершенству нет предела.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Самая мощная энергия часто бывает самой кратковременной. Ты можешь найти \"\n\"древние слова волшебной силы, написанные на пергамент. Сила этих свитков \"\n\"зависит от того, использует ли их ученик или мастер. Их недостаток это то, \"\n\"что их можно только раз прочесть в слух и нельзя держать наготове в уме. \"\n\"Помни, что эти свитки можно прочитать только один раз, поэтому используй их \"\n\"мудро.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Хотя жар солнца неизмеримо велик, но пламя простой свечи может быть гораздо \"\n\"опаснее. Невозможно использовать энергию, какой бы мощной она ни была, если \"\n\"её не направить в нужное русло. Многие волшебные посохи можно заряжать \"\n\"энергией снова и снова. Я имею способность пополнять посохи волшебной \"\n\"энергией, но знай - ничего не делается бесплатно.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Наши знания - это знания нашего народа. Если ты найдёшь книгу или свиток, \"\n\"которые не можешь прочитать, без колебаний неси их ко мне. Если я смогу \"\n\"понять, что там написано, я поделюсь этим с тобой.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Для того, кто знает только Железо, нет волшебства более великого, чем Сталь. \"\n\"Кузнец Гризвольд тоже в своём роде волшебник. Никто в этом краю не \"\n\"сравниться с ним в искусстве ковки металла.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Испорченное способно одурачить, а в невинности заключается сила чистоты. У \"\n\"Джиллиан чистое сердце, и она ставит интересы своей бабушки выше своих \"\n\"собственных. Она боится меня, но только потому, что не понимает меня.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Если открыть сундук в темноте, в нём будет не больше богатства, чем если \"\n\"открыть его при свете. Рассказчик Каин - загадочный человек, но лишь для \"\n\"тех, кто не присматривается к нему. Он знает о том, что находится под \"\n\"собором, гораздо больше, чем он сам это осознаёт.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Чем выше возносишь человека, тем ниже он упадёт в твоих глазах. Фарнам \"\n\"загубил свои душу и разум, но не из-за демона. Он потерял их, когда увидел, \"\n\"что Архиепископ Лазарь предал жителей своей деревни. У него бывают проблески \"\n\"разума, но следует отличать факты от фантазии.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Руки, сердце и разум могут совершать чудеса, когда между ними есть гармония. \"\n\"Даже я не могу так хорошо определять и лечить болезни и раны, как это умеет \"\n\"Лекарь Пепин. Кроме того, он создаёт чудесные лекарственные снадобья и \"\n\"элексиры. Он всегда окажет тебе помощь, если ты будешь в Тристраме.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Мы многого не можем знать о будущем, но оно находиться в руках детей. У \"\n\"мальчугана Вирта в душе остался мрак, но он не представляет опасности для \"\n\"жителей деревни. Благодаря своим связям с уличными мальчишками и тайными \"\n\"гильдиями соседних деревень, он может доставать много вещей, которые нелегко \"\n\"найти в Тристраме. И хотя его методы заслуживают осуждения, Вирт может \"\n\"помочь тебе раздобыть что-нибудь, что пригодиться тебе в борьбе с силами \"\n\"надвигающейся Тьмы.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Глиняные стены и соломенная крыша плохой дом для человека. Хозяин гостиницы \"\n\"значит для этой деревни гораздо больше, чем многие думают. Он даёт убежище \"\n\"Джиллиан и её бабушке, как может поддерживает Фарнама, его двери всегда \"\n\"открытые для тех, кто ещё остался в Тристраме. Его таверна и те простые \"\n\"удовольствия, которые всё можно там получить, напоминают людям о жизни, \"\n\"кипевшей тут раньше. Именно эти воспоминания ещё вселяют в людей надежду и \"\n\"веру в твою победу.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Пссс... иди сюда...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Не каждый в Тристраме найдёт применение - или покупателя - для всего, что ты \"\n\"найдёшь в лабиринте. Даже я, хоть в это и трудно поверить. \\n\"\n\" \\n\"\n\"Только для некоторых вещей ты сможешь найти применение.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Не верь всему, что говорит этот пьяница. Пиво залило ему глаза и мозги.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Уже можно было заметить, что я ничего не покупаю в Тристраме. Я достаю товар \"\n\"высшего качества. Если ты хочешь торговать барахлом, пойди к Гризвольду, \"\n\"Пепину или к той ведьме Адрии. Я уверен, что они проглотят всё, что ты им \"\n\"там притащишь...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Кузнец спас мне жизнь - или то, что от неё осталось. Гризвольд предложил мне \"\n\"подмастерьем в кузнице, и вообще он хороший мужик, но там я никогда не смогу \"\n\"заработать достаточно денег, чтобы... ну, скажем , у меня есть кое-какие \"\n\"планы, а для них нужно много золота.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Если бы я был постарше, я бы осыпал её всеми богатствами, какие только смог \"\n\"бы раздобыть, и уверяю тебя, что я могу достать очень ценные вещи. Джиллиан \"\n\"красивая девушка, ей просто надо уехать отсюда, как только это будет \"\n\"достаточно безопасно. Хммм... может быть, я и возьму её с собой, когда \"\n\"уеду...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Каин слишком много знает. Я его до смерти боюсь - даже больше, чем ту \"\n\"ведьму, что живёт за рекой. Он всё время говорит, как мне повезло, что я \"\n\"остался жив, и что моя история станет легендой. Я думаю, у него не все дома.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Фарнам - вот у него серьёзные проблемы, а я уж знаю, что такое серьёзные \"\n\"проблемы. Он слишком сильно верил в честность одного человека - Лазаря - а \"\n\"тот отправил его прямо в когти смерти. О, я знаю, каково там внизу, и не \"\n\"надо рассказывать мне о своих планах уничтожить зло, обитающее Лабиринте. \"\n\"Просто береги свои ноги...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Старик Пепин - хороший лекарь, если дело не касается пришивания \"\n\"конечностей. \\n\"\n\" \\n\"\n\"Вот если бы у меня были те зелья, которые он варит, я может быть и не \"\n\"потерял бы ногу...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Адрия пугает меня. Конечно, Каин может многое рассказать о прошлом, но эта \"\n\"ведьма может видеть всё твоё прошлое. Ей всегда как-то удаётся получить \"\n\"любую вещь, которая ей нужна. Через руки Адрии проходит больше товаров, чем \"\n\"через ворота Королевского Рынка во время ярмарки.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Огден дурак, что не уехал отсюда. Я мог бы вывезти его из города за разумную \"\n\"цену, но он надеется раскрутить дела в своей никчемной Таверне. Хорошо хоть, \"\n\"что дал работу Джиллиан, а его жена Гарда печёт превосходный пастуший \"\n\"пирог...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"За Залом Героев находятся Палата Костей. Вечная смерть постигнет того, кто \"\n\"захочет украсть сокровища, хранящиеся в ней. Так сказал Повелитель Ужаса, и \"\n\"так написано.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...и за Воротами Крови, за Залом Огня, Отвага ждёт прихода Героя Света...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Ты не видишь, вижу я.\\n\"\n\"Взор мутнеет у тебя.\\n\"\n\"Повернёшь - они уйдут,\\n\"\n\"Песню тихую поют.\\n\"\n\"Ты увидишь, чего нет,\\n\"\n\"Тени наползут на свет.\\n\"\n\"Ты и сам от темноты\\n\"\n\"Упадёшь в Зал Слепоты.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Арсеналы Ада - это жилище Кровавого Генерала. Там, где он прошёл, остались \"\n\"лежать тысячи изувеченных тел. Он без разбору резал и людей, и ангелов, \"\n\"чтобы приносить всё новые жертвы Повелителям Тьмы, которые ждут одного: \"\n\"крови.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Узнай и будь свидетелем истин, открывшихся тебе, ибо это - последнее \"\n\"наследие Хорадрима. За пределами этого мира идёт война между Царством \"\n\"Небесным и Преисподней. Эта война называется Великим Противостоянием, и \"\n\"огонь её пылает дольше, чем в небе существуют звёзды. Ни та, ни другая \"\n\"сторона ещё не одерживали верх, так как силы Света и Тьмы постоянно борются \"\n\"за контроль над вселенной.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Узнай и будь свидетелем истин, открывшихся тебе, ибо это - последнее \"\n\"наследие Хорадрима. Когда Вечное Противостояние между Царством Небесным и \"\n\"Преисподней затрагивает душу смертного, это называется Войною Грехов. Ангелы \"\n\"и Демоны ходят среди смертных, надев личины людей. Они ведут борьбу, \"\n\"незаметную для человеческих глаз. Некоторые очень сильные личности вступили \"\n\"в союз с одной из сторон и смогли повлиять на ход Войны Грехов.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Узнай и будь свидетелем истин, открывшихся тебе, ибо это - последнее \"\n\"наследие Хорадрима. Почти триста лет назад стало известно, что Три Верховных \"\n\"Зла Преисподней каким-то образом проникли в наш мир. Эти Три Брата \"\n\"опустошали земли на востоке многие десятилетия, и человечество дрожало в \"\n\"страхе. Наш Орден - Хорадрим - был основан группой тайных магов, целью \"\n\"которых было поймать и пленить эти Три Зла раз и навсегда.\\n\"\n\" \\n\"\n\"Ордену удалось поймать двоих из Трёх и заключить их внутри могущественных \"\n\"артефактов, называемых Камнями Душ. Затем эти камни были глубоко зарыты \"\n\"среди безлюдной пустыни на востоке. Третьему Злу удалось избежать плена и \"\n\"скрыться на западе от преследования из Хорадрима. Третье Зло носит имя \"\n\"Диабло, Повелитель Ужаса. Он всё-таки был пойман в камень души и спрятан где-\"\n\"то в этом лабиринте.\\n\"\n\" \\n\"\n\"Знай же, что этот Камень Души не должен быть найден человеком, чья вера \"\n\"хрупка. Если Диабло вырвется на свободу, он будет искать для себя слабого \"\n\"человека, которым легко завладеть, - возможно, старика или ребёнка.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"И случилось так, что в Преисподней разгорелась междоусобная война, названная \"\n\"Тёмным Изгнанием. Демоны поменьше взяли верх над Тремя Верховными и выгнали \"\n\"их души в мир людей. Демоны Белаил (Повелитель Лжи) и Азмодан (Повелитель \"\n\"Греха) стали драться за престол Ада. Преисподняя разделилась на сторонников \"\n\"Белаила и сторонников Азмодана, а Силы Небесные продолжали наносить удары по \"\n\"Вратам Ада.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Много демонов отправились в мир людей на поиски Трёх Братьев. За демонами \"\n\"следовали Ангелы, которые пытались настичь их и обшаривали большие города \"\n\"Востока вдоль и поперёк. Ангелы вступили в союз с тайным Орденом людей-\"\n\"магов, который назывался Хорадрим. Орден быстро научился ловить демонов, а \"\n\"также он нажил себе множество врагов в подземном мире.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"И случилось так, что Три Верховных Зла были изгнаны в мир людей. Многие \"\n\"десятилетия они сеяли хаос на землях Востока, затем они были пойманы тайным \"\n\"Орденом магов, названных Хорадрим. Орден использовал артефакты, известные \"\n\"как Камни Душ, чтобы держать в них сущность Мефистофеля, Повелителя \"\n\"Ненависти, и Баала, Повелителя Разрушения. Младший брат - Диабло, Повелитель \"\n\"Ужаса - сбежал на запад.\\n\"\n\" \\n\"\n\"Но Хорадрим всё же поймал Диабло в Камень Души и схоронил его под древним, \"\n\"заброшенным Собором. Там Повелитель Ужаса дремлет и ждёт своего \"\n\"освобождения. Знай же, он будет искать себе человека юного и наивного, \"\n\"которым легко завладеть: он будет искать ребёнка. Затем он восстанет, чтобы \"\n\"вызволить своих Братьев и вновь разжечь пламя Войны Грехов...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Хвала Диабло - Повелителю Ужаса, избавившемуся от Тёмного Изгнания. Когда \"\n\"мой Повелитель очнулся от долгого сна, он открыл мне тайны, известные \"\n\"немногим смертным. Он сказал мне, что между Царством Небесным и Преисподней \"\n\"идёт вечная война. Он поведал мне, какие силы принесли эту войну в мир \"\n\"людей. Мой повелитель называет это Войной Грехов.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Хвала и слава Диабло - Повелителю Ужаса и Предводителю Троих. Мой Повелитель \"\n\"рассказал мне о своих двух братьях, Мефистофеле и Баале, которых давно \"\n\"изгнали в этот мир. Мой Повелитель желает выждать время, пока он вновь \"\n\"обретёт своё могущество, чтобы освободить братьев из-под песков востока. \"\n\"Когда мой Повелитель освободит своих Братьев, Война Грехов снова узнает \"\n\"ярость Троих.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Да здравствует Диабло - Повелитель Ужаса и Разрушитель Душ. Когда я пробудил \"\n\"своего Повелителя от сна, он попытался обрести форму человека. Диабло хотел \"\n\"завладеть телом Короля Леорика, но он был ещё слишком слаб после долгого \"\n\"плена. Ему нужно было как-то зацепиться за этот мир, и он нашёл юного \"\n\"Альбрехта, который прекрасно подходил для этой цели. После неудачной попытки \"\n\"Диабло оставил тело обезумевшего Леорика, а я похитил его сына Альбрехта и \"\n\"отдал его своему Повелителю. Теперь я жду, когда Диабло меня позовёт, и \"\n\"молюсь, что он вознаградит меня, когда станет Повелителем этого мира.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Слава богу, ты снова здесь!\\n\"\n\"Многое изменилось со времени твоего последнего посещения таверны. Мы жили \"\n\"хорошо, но потом появились чёрные всадники и опустошили наш городок. Многие \"\n\"жители были убиты прямо на месте, а те, кто взялся за оружие - погибли или \"\n\"были захвачены в рабство, а может и ещё хуже. Нашу церковь осквернили, в ней \"\n\"проводятся чёрные обряды. По ночам оттуда слышны нечеловеческие вопли, но \"\n\"возможно кто-нибудь из наших односельчан всё ещё жив. Иди по тропе, которая \"\n\"пролегает между моей таверной и кузницей, найди церковь и спаси всех, кого \"\n\"сможешь. \\n\"\n\" \\n\"\n\"Буду рад поговорить с тобой ещё раз. Желаю удачи.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Не прекращайте свои поиски. Найти потерянное сокровище непросто. Найти \"\n\"спрятанное сокровище легче. Скажу напоследок: не позволяйте пескам времени \"\n\"мешать вашим поискам.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Что?! Какая чепуха! В Тристраме нет никаких зарытых сокровищ. Дай ка я \"\n\"посмотрю. Ах, видишь? Этот рисунок неточный. Это совсем не похоже на нашу \"\n\"деревню. На твоём месте я бы больше думал о том, что находиться под Собором, \"\n\"а не под нашими огородами.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"У меня нет времени разговаривать о какой-то карте, которую ты ищешь. Много \"\n\"людей нуждается в моей помощи, да и в твоей тоже.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Некогда гордый Исвалл заперт глубоко под поверхностью этого мира. Его честь \"\n\"утрачена и его выражение изменилось. Он в ловушке бессмертных мук. Обязанный \"\n\"скрывать то, что могло его освободить.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Держу пари, что Вирт видел, как ты идёшь и разыграл эту сцену, чтобы потом \"\n\"посмеяться, глядя как ты по всюду роешься в земле, словно крот. Я бы не стал \"\n\"придавать значение.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Когда-то в нашем городке часто останавливались путешественники и торговцы из \"\n\"разных стран, но с тех пор многое изменилось. Дети обычно любят мечтать о \"\n\"всяких тайных пещерах и зарытых сокровищах. Вирт ещё ребёнок. Может быть, он \"\n\"просто выдумал всё это.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Слушай сюда. Подойди ближе. Не знаю, знаешь ли ты то, что знаю я, но у тебя \"\n\"действительно кое-что есть. Эта карта.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Моя бабушка часто рассказывает мне о странных духах, обитающих на кладбище \"\n\"возле церкви. Тебе, наверное, будет интересно послушать об этом. Она \"\n\"говорит, что если оставить на кладбище подобающий дар, зайти в Собор и \"\n\"помолиться за мёртвых, а затем вернуться, то дар странным образом \"\n\"измениться. Я не знаю, возможно, это просто фантазия старой больной женщины, \"\n\"но теперь настало такое время, что всякое может произойти.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Хммм. Огромное и таинственное сокровище, говоришь. Мммм. Возможно, мне было \"\n\"бы интересно получить от тебя кое-что. Или ещё лучше: разве тебе не нужны \"\n\"редкие и дорогие припасы, чтобы пройти через это испытание?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"А, так это о тебе все говорят, как о герое. Сможешь ли ты помочь бедному \"\n\"простому фермеру? На краю моего сада, немного южнее этого места, из земли \"\n\"вылазит ужасная штуковина! Я не могу подойти к своему огороду и к стогам \"\n\"сена. Мои бедные коровы подохнут с голоду. Ведьма дала мне вот это и \"\n\"сказала, что им можно снести ту нечисть напрочь с моего участка. Если ты \"\n\"сможешь её уничтожить, я буду вечно тебе благодарен. Я бы и сам это сделал, \"\n\"но я должен присматривать за коровами...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Я так и знал, что не всё так просто, как говорит ведьма. Куда катиться этот \"\n\"мир, если нельзя доверять даже соседям.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Его больше нет? Тебе удалось отправить его в Преисподнюю, которая его \"\n\"породила. Что? О, только не говори, что ты это потерял! Такие вещи стоят не \"\n\"дёшево. Найди эту вещь, а потом взорви эту ужасную штуковину.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Я слышал взрыв! Огромное тебе спасибо. Что за времена настали - из земли \"\n\"лезет всякая нечисть, монстры заполняют церкви и всякое такое. Я всего лишь \"\n\"бедный фермер, но вот, ну вот - прими это вместе с моей благодарностью.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Ах, у меня такая беда... возможно... Но нет, я не могу возложить это на \"\n\"тебя. У тебя и так полно хлопот. Может быть, после этого, как ты очистишь \"\n\"церковь от тварей, ты придёшь снова... и немного поможешь бедному фермеру?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Уааааа! (хлюп) Уааааа! (хлюп)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Пропал мой Тео!  Пропал мой лучший друг!  Мы игрались возле реки, а Тео \"\n\"захотел посмотреть на ту большую зелёную штуку.  Я сказала, что нельзя, но \"\n\"мы только заглянули туда, и вдруг вылез ЖУК!  Мы побежали, но Тео упал, и \"\n\"жук СХВАТИЛ его и утащил!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Где же он?  Пожалуйста, найди Теодора!  Он ещё такой маленький.  Он не может \"\n\"о себе позаботиться!  Прошу тебя!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Ура!  Он нашёлся!  Спасибо тебе, герой!  О, Тео, эти противные жуки напугали \"\n\"тебя, да?  Ой!  Что прицепилось к твоему меху!  Фу!  Ну давай, Тео, пойдём \"\n\"домой!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Мы долго спали, но пришло время проснуться. После долгой спячки мы очень \"\n\"проголодались. Очень скоро мы утолим свой голод...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Доволен собой, мелкое млекопитающее? Как жалко. Ваш ничтожный мирок вообще \"\n\"не будет проблемой.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Мы оскверним эту землю, мы зальём кровью поля, которые люди называют \"\n\"родиной.  Мы захватим этот мир и будем пировать на останках его жителей.  \"\n\"Люди будут нашей собственностью и пищей.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"Ближе, сладость моя! Я чую твой страх, и я голоден...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"И в год Золотого Света было решено построить великий Собор. Угловой камень \"\n\"этого Собора должны были сделать из прозрачного камня Антирэля, названного \"\n\"так в честь Ангела, который одарил своей силой Хорадрим. \\n\"\n\" \\n\"\n\"В Год Наползающих Теней земля задрожала, и Собор треснул и развалился. Когда \"\n\"началось строительство катакомб и замков, и люди страдали от бедствий Войны \"\n\"Грехов, развалины были перерыты в поисках камней. Но нигде не было видно \"\n\"углового камня собора. \\n\"\n\" \\n\"\n\"Камень принадлежал этому миру - и всем другим мирам - так как Свет имеет \"\n\"отношение ко всем вещам. Свет и целостность - продукт этого священного \"\n\"фундамента - целостность стремлений и целостность характера.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Му.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"А я говорю Муу.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Да я просто корова.\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Ну ладно, ладно. Я совсем не корова. Я обычно так себя не веду; но я просто \"\n\"сидел дома, и думал о всей этой ерунде: вения в лампочке и всякой всячине, \"\n\"начавшей появляться из пола... это был кошмар! Если бы только у меня была \"\n\"нормальная одежда, всё бы было не так плохо. Слушай, а ты бы не мог сходить \"\n\"ко мне и принести мой костюм? Коричневый, но только не серый, серый только \"\n\"для выхода в свет. Я бы и сам это сделал, но не хочу, чтобы кто-то видел \"\n\"меня в таком прикиде. Вот, возьми, это может понадобиться тебе... чтобы \"\n\"убить всех, которые всё переросли. Вы не пройдёшь мимо моего дома, он к югу \"\n\"от развилки реки... ну, знаешь... тот, с неухоженным садом.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Ну что ждёшь? Иди и принеси мой костюм! И поторопись! Этот дебил пялиться на \"\n\"меня!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"Эй, ты принёс мой костюм? Быстрее давай его сюда!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Нет, слышишь?  Нет, это мой СЕРЫЙ костюм!  Это на выход!  Для торжественных \"\n\"случаев!  Я не могу надеть ЕГО.  Ты что, идиот?  Мне нужен КОРИЧНЕВЫЙ костюм.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ааа, ну это НАМНОГО лучше. Да! Наконец-то достойный прикид! Стрелки не \"\n\"помялись? Отлично. Слушай, спасибо за помощь. Вот, возьми это в подарок; ну, \"\n\"знаешь... небольшая такая модная штучка... ты можешь её использовать нуу... \"\n\"ну сам понимаешь? Ведь это стиль искателя приключений такой... старомодный. \"\n\"Маленький совет, а? Чао.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Смотрите. Я корова. А вы - приманка для монстров. Накопите немного опыта за \"\n\"плечами! Тогда поговорим...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Должно быть, я задал тебе трудную задачу. Если бы только я мог чем-нибудь \"\n\"тебе... может быть фляжка свежего молока придаст тебе сил?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"О, я мог бы воспользоваться твоей помощью, но после того, как ты очистишь \"\n\"катакомбы от этих чудовищ.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Необходимо что-то делать, но я не могу возложить это на совершенно \"\n\"незнакомого человека. Может быть, немного позже попрошу тебя и о помощи.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Я вижу ты обладаешь великой силой. Может быть, когда-нибудь, в перерыве \"\n\"между подвигами, ты навесишь меня и окажешь мне небольшую услугу?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Я думаю, ты можешь мне помочь, но возможно, немного позже, когда станешь ещё \"\n\"чуточку сильнее. Я не хочу разрушить надежды людей, что ты уничтожишь зло, \"\n\"поселившееся в церкви!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Я - обязанная за всё самой себе корова.  Стань кем-нибудь и... тогда мы \"\n\"поговорим.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Мне не нужно представлять себя каждому проходящему мимо туристу!  Разве у \"\n\"тебя нет монстров, которых нужно убить?  Может быть, мы поговорим позже.  \"\n\"Если выживешь...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Хватит приставать ко мне.  Я ищу кого-то действительно героического.  И это \"\n\"не ты.  Я не могу доверять тебе, тебя со дня на день сожрут монстры...  Мне \"\n\"нужен опытный герой.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Ну хорошо, я зарежу быка.  Я не имел ввиду то, что ты подумал.  Я сидел \"\n\"дома, мне было хреново, всё поплыло; целая куча монстров вылезла из пола!  Я \"\n\"просто умер.  Просто в этот момент я был одет вот в это и теперь выгляжу \"\n\"крайне бестолково.  Если бы только у меня была нормальная одежда, всё было \"\n\"бы не так плохо.  Слушай!  Не мог бы ты сходить ко мне и принести мой \"\n\"костюм?  Коричневый, не серый, тот только для выхода в свет.  Нет, я бы и \"\n\"сам это сделал, но не хочу, чтобы кто-нибудь видел меня в таком виде.  Вот, \"\n\"возьми, это поможет тебе убить этих, которые всё перерыли.  Ты не пройдёшь \"\n\"мимо моего дома, он к югу от развилки реки... ну, знаете... тот, что с \"\n\"неухоженным садом.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Я пробовал заклинания, угрозы, подкуп, пробовал отречься от этого ужасного \"\n\"существа — но ничего не помогло.  Никакие мои методы не действуют на это \"\n\"бесстрашное существо.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Мой дом постепенно разрушается из-за губительного воздействия этого \"\n\"нежелательного пленника.  Коридоры полны теней, уголками глаз я вижу, как \"\n\"они движутся.  Мне слышится тихий звук царапающих когтей.  Я думаю, что они \"\n\"хотят найти этот дневник.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Как-то раз, среди проклятий и угроз, существо произнесло своё имя - На-\"\n\"Крул.  Я пробовал выяснить, что это за имя, но маленькие демоны каким-то \"\n\"образом уничтожили мою библиотеку.  На-Крул... Звук этого имени наводит на \"\n\"меня ужас.  Я предпочитаю называть его Существом, чем говорить это имя.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Страшный вой пленного существа не даёт мне покоя, лишает сна.  Он посылает \"\n\"мне ужасные проклятия за то, что я сделал его узником Пустоты.  Его слова \"\n\"заставляют моё сердце замирать от холодящего ужаса, но я ничего не могу \"\n\"поделать, чтобы не слышать их.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Моё время быстро истекает.  Я должен записать, как ослабить этого демона и \"\n\"спрятать записи, иначе его приспешники смогут использовать мои знания, чтобы \"\n\"освободить своего хозяина.  Я надеюсь - тот, кто найдёт этот дневник, будет \"\n\"искать и знания.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Тот, кто найдёт этот свиток, должен уничтожить это демоническое создание, \"\n\"которое заключено в этих стенах.  Моё время кончилось.  Даже сейчас его \"\n\"дьявольские приспешники скребуться в непрочные двери, за которыми я \"\n\"прячусь. \\n\"\n\"\\n\"\n\"Я поймал этого демона с помощью тайной магии и упрятал его за крепкие стены, \"\n\"но я боюсь, что этого мало.\\n\"\n\"\\n\"\n\"Заклинания, которые ты можешь здесь найти, обеспечат тебе безопасный вход в \"\n\"его обиталище, но только если ты произнесёшь их в правильном порядке.  \"\n\"Рычаги возле входа убирают барьеры поэтому не прикасайся к ним, иначе демон \"\n\"вырвется на волю!  Используй только эти заклинания, иначе погибнешь.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Адский Вепрь\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Жалитель\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Психорб\"\n\n# FIXME: This creature is not a simple spider, so it might need a different translation.\n# \"Арахнон\"?\n# ---------------------------------------------\n# Да\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Арахнон\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Падшие Близнецы\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Блюющее Отродье\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Скорпион\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Некроморб\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Лорд Пауков\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Плёточный Червь\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Огненный Муравей\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Адский Жук\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Могилокопатель\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Крыса Подземелья\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Огненная Летучая Мышь\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Черепокрыл\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Лич\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Демон Склепа\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Адская Летучая Мышь\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Костяной Демон\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Архилич\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Биклоп\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Плоть\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Жнец\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Кастет Гиганта\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Ртутное Кольцо\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Кольцо Ксорин\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Кольцо Карика\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Кольцо Магмы\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Кольцо Мистики\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Кольцо Грома\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Защитный Амулет\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Жало Комара\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Факел\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Доспех Мрака\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Блитцен\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Удар Грома\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Широтачи\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Пожиратель Душ\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Кромка Алмаза\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Костяная Броня\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Демонический Доспех\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Амулет Приспешника\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Кольцо Гладиатора\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Шутовской\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Кристаллический\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Двойникский\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"опустошения\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"разложения\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"опасности\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Волхв\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Шут\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Стена Молний\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Жертвоприношение\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Искривление\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Отражение\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Берсерк\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Кольцо Огня\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Поиск\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Руна Огня\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Руна Света\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Руна Новы\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Руна Жертвоприношения\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Руна Камня\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Сердце\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Начать в городе\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Пытаетесь выкинуть предмет, лежащий на полу?\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Меткость\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Уменьшить гамму\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Увеличить гамму\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Принудительное ожидание вертикальной синхронизации. Предотвращает эффект \"\n#~ \"разрыва при рисовании кадра. Отключение может помочь с задержкой мыши на \"\n#~ \"некоторых системах.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"Ограничить FPS\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"Ограничить FPS во избежание нагрузки на процессор. Учитывается частота \"\n#~ \"обновления.\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Неразрушимое,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Нет обязательных атрибутов\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Параметры:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"версия {:s}\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Автокарта недоступна в городе\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"восстановит жизнь\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"смертельное исцеление\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"уменьшить силу\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"уменьшить ловкость\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"уменьшить живучесть\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"вы не можете исцелиться\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"удар по монстру не исцеляет\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Быстрый удар\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"видит инфразрением\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Не удалось открыть архив игрока для записи.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Невозможно прочитать архив файла сохранения\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Невозможно записать в архив файла сохранения\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"За Залом Героев лежит Палата Костей. Вечная смерть ожидает любого, кто \"\n#~ \"попытается украсть сокровища, хранимые в этой комнате. Так говорит \"\n#~ \"Повелитель Ужаса, и так предписано.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"Арсеналы Ада - обитель Кровавого Генерала. Вслед за ним лежали \"\n#~ \"изуродованные тела тысяч людей. Ангелы и люди были вырезаны для \"\n#~ \"исполнения его бесконечных жертвоприношений Тёмным, требующим одного: \"\n#~ \"крови.\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Сегодня пасмурно и прохладнее. Забросив сети некромантии через пустоту, \"\n#~ \"мы получили два новых подвида летающего ужаса; хороший рабочий день. Надо \"\n#~ \"не забыть заказать у Адрии ещё немного гуано летучих мышей и чёрных \"\n#~ \"свечей; у меня уже на исходе.\"\n"
  },
  {
    "path": "Translations/sv.po",
    "content": "# Translation of DevilutionX to Swedish\n# John Törnblom, 2021.\n# @SimonCeder, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:21+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: sv\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Speldesign\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Huvuddesigners\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Extra design\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Försteprogrammerare\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Huvudprogrammerare\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programmering\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Extra Gästprogrammerare\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net-programmering\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Serialkommunikationsprogrammering\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Installerarprogrammering\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Grafikregi\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Grafik\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Teknisk Grafik\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Filmklippsregi\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D-filmsregi\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Teknisk Filmgrafik\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Verkställande Producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Producent\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Produktionsassistent\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Musik\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Ljuddesign\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Filmmusik och -ljud\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Röstproduktion, Regi & Rollsättning\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Skript & Story\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Röstredigering\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Röster\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Inspelningstekniker\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Manualdesign & Layout\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Manualgrafik\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Tillförordnad direktör för QA (Huvudtestare)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA Assault Team (Testare)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA Special Ops Team (Kompabilitetstestare)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA Artillery Support (Extra Testare) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA Counterintelligence\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Order of Network Information Services\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Kundtjänst\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Försäljning\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Mr. Dabiri's Bakgrundsröster\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Public Relations\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Marknadsföring\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Internationell Försäljning\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Amerikansk Försäljning\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Tillverkning\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Juridik & Business\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Extra Tack Till\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Tack Till\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Till minne av\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Alldeles Extra Tack till\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Allmän Manager\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Mjukvaruingenjör\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Grafikregissör\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Konstnärer\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Design\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Ljuddesign, SFX & Ljudteknik\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Testningsansvarig\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testare\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Manual\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tYtterligare Arbete\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Uppdragstextförfattare\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Tack Till\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tExtra Tack till Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Testningsmanager\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Förstetestare\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Huvudtestare\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Övriga Testare\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Produktmarknadsföringsmanager\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"PR-Manager\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Assistentproduktmanager\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"De Ett Tusens Ring\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tInga själar såldes vid skapandet av detta spel.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Välj Klass\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Avbryt\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Ny Flerspelarhjälte\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Ny Enspelarhjälte\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Sparad Fil Finns\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Ladda Spel\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Nytt Spel\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Enspelarkaraktärer\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Rövaren och Besvärjaren finns endast tillgängliga i den kompletta versionen \"\n\"av Diablo. Besök https://www.gog.com/game/diablo för att köpa.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Skriv In Namn\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Ogiltigt namn. Ett namn får inte innehålla mellanrum, reserverade tecken \"\n\"eller reserverade ord.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Kunde inte skapa karaktären.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Nivå:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Styrka:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Magi:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Smidighet:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Kropp:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Sparat spel:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Välj Hjälte\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Ny Hjälte\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Ta Bort\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Flerspelarkaraktärer\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Ta Bort Flerspelarhjälte\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Ta Bort Enspelarhjälte\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Är du säker att du vill ta bort karaktären \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"En Spelare\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Flera Spelare\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Inställningar\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Support\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Visa Spelskapare\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Avsluta Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Avsluta Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Klient-Server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Frånkopplad\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Flerspelarsspel\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Krav:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"ingen gateway behövs\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Välj Anslutning\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Ändra Gateway\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Alla datorer måste vara uppkopplade till ett TCP-kompatibelt nätverk.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Alla datorer måste vara uppkopplade till internet.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Spela själv utan nätverkstillgång.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Stött antal Spelare: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Värden håller i ett annat spel än du.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Värden kör ett annat spelläge ({:s}) än du.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Din version {:s} stämmer inte överens med värdens {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Beskrivning:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Välj Handling\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Skapa Spel\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Skapa Offentligt Spel\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Gå Med Spel\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Offentliga Spel\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Laddar...\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Ingen\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"AVBRYT\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Skapa ett nytt spel med valfri svårighetsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"Skapa ett nytt spel som vem som helst kan gå med i med valfri svårighetsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Skriv in ett spel-ID för att gå med ett spel som redan pågår.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"\"\n\"Skriv in IP-adress eller DNS-namn för att ansluta till befintligt spel.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Anslut till befintligt publikt spel.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Mardröm\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Helvete\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Svårighetsgrad: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Hastighet: Normalt\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Hastighet: Snabbt\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Hastighet: Snabbare\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Hastighet: Snabbast\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Spelare: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Välj Svårighetsgrad\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Gå Med {:s}-Spel\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Skriv in spel ID\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Skriv in adress\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normal Svårighetsgrad\\n\"\n\"Här bör en ny karaktär påbörja resan för att besegra Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Mardrömssvårighetsgrad\\n\"\n\"Labyrintens invånare har stärkts och kommer visa sig vara en svårare \"\n\"prövning. Detta rekommenderas endast för erfarna karaktärer.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Helvetessvårighetsgrad\\n\"\n\"Underjordens mäktigaste varelser ligger i bakhåll vid Helvetets portar. \"\n\"Endast de mest erfarna karaktärerna bör våga sig in i denna värld.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Din karaktär måste nå nivå 20 innan du kan gå med ett flerspelarspel med \"\n\"Mardrömssvårighetsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Din karaktär måste nå nivå 30 innan du kan gå med ett flerspelarspel med \"\n\"Helvetessvårighetsgrad.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Välj Spelhastighet\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Snabb\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Snabbare\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Snabbast\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normal Hastighet\\n\"\n\"Här bör en ny karaktär påbörja resan för att besegra Diablo.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Snabb Hastighet\\n\"\n\"Labyrintens invånare har snabbats upp och kommer visa sig vara större \"\n\"utmaningar. Detta rekommenderas endast för erfarna karaktärer.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Snabbare Hastighet\\n\"\n\"De flesta av grottornas monster kommer förfölja dig snabbare än någonsin. \"\n\"Endast en erfaren kämpe bör pröva sin lycka på denna hastighet.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Snabbast Hastighet\\n\"\n\"Underjordens tjänare kommer gå till anfall utan minsta tvekan. Endast en \"\n\"verklig fartdjävul bör prova denna takt.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Skriv In Lösenord\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Gå till Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Byt till Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Ja\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Nej\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\n#, fuzzy\n#| msgid \"Press any key to change.\"\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Tryck på valfri tangent för att ändra.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Tilldelad tangent:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Tryck på valfri tangent för att ändra.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Ta bort tangent\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Föregående Meny\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Vi håller i en chattserver på Discord.gg/devilutionx Följ länkarna för att \"\n\"gå med i vår gemenskap där vi pratar som allt som har att göra med Diablo, \"\n\"och Hellfireexpansionen.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX skapas av Diasurgical, ärenden och buggar kan anmälas på denna \"\n\"adress: https://github.com/diasurgical/devilutionX För att hjälpa oss hjälpa \"\n\"dig var god inkludera versionsnummer, operativsystem, och vad problemet \"\n\"handlar om.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Obs:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX vare sig stöds eller arbetas på av Blizzard Entertainment \"\n\"eller GOG.com. Vare sig Blizzard Entertainment eller GOG.com har testat \"\n\"eller intygat kvaliteten eller kompabiliteten hos DevilutionX. Alla frågor \"\n\"rörande DevilutionX bör riktas till Diasurgical, inte till Blizzard \"\n\"Entertainment eller GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tDenna portning använder Charis SIL, New Athena Unicode, Unifont och Noto \"\n\"vilka licenseras enligt SIL Open Font License, samt Twitmoji vilken \"\n\"licenseras enligt CC-BY 4,0. Porten använder även SDL som licenceras enligt \"\n\"zlib-license.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Upphovsrätt © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Fel\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Felet uppstod vid: {:s} rad {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Datafilsfel\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Kunde inte öppna huvuddataarkiv ({:s}).\\n\"\n\"\\n\"\n\"Försäkra dig att det finns i spelmappen.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Endast Läsbar-mappfel\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Kunde inte skriva till plats:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Spel: \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\n#| msgid \"Offline\"\nmsgid \"Offline Game\"\nmsgstr \"Frånkopplad\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Lösenord: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Offentligt Spel\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Nivå: Näste {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Nivå: Krypta {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Byn\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Nivå: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Karaktärsinformation\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Uppdragslogg\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Autokarta\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Huvudmeny\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Ägodelar\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Magibok\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Skicka Meddelande\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\n#, fuzzy\n#| msgid \"Description:\"\nmsgid \"Description: \"\nmsgstr \"Beskrivning:\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\n#, fuzzy\n#| msgid \"Players: \"\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"Spelare: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to buy this item?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Är du säker på att du vill köpa detta föremål?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\n#, fuzzy\n#| msgid \"Amber\"\nmsgid \"<number>\"\nmsgstr \"Bärnsten\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\n#| msgctxt \"monster\"\n#| msgid \"Flayed One\"\nmsgid \"<player name>\"\nmsgstr \"Skinnflådd\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Spelarvänlig\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Spelaranfall\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Genväg: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Välj nuvarande trollformelsknapp\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Genväg: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Färdighet\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Trollformel\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Trollformelsnivå 0 - Oanvändbar\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Trollformelsnivå {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Skriftrulle med {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d}-Skriftrulle\"\nmsgstr[1] \"{:d}-Skriftrullar\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Stav med {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Laddning\"\nmsgstr[1] \"{:d} Laddningar\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} guldmynt\"\nmsgstr[1] \"{:s} guldmynt\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Kraven uppnås ej\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Nivå: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Livspoäng {:d} av {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Högerklicka för att använda\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Nivåökning\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"Du har {:s} guldmynt. Hur många vill du dra ifrån?\"\nmsgstr[1] \"Du har {:s} guldmynt. Hur många vill du dra ifrån?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Byportal\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"från {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal till\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Det Oheliga Altaret\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"nivå 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Kunde inte ladda karaktär\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Skriv detta meddelande och avsluta\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Skriv ut version och avsluta\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Ange mapp för diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Ange mapp för sparade filer\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Ange plats för diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Hoppa över introduktionsfilmer\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Visa frames per sekund\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Aktivera ordrik loggning\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Spela in en demofil\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Spela upp en demofil\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Stäng av alla framebegränsningar vid demouppspelning\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Spelval:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Tvinga Sharewareläge\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Tvinga Diabloläge\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Tvinga Hellfireläge\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Hellfire-alternativ:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Rapportera buggar på https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Kunde inte ladda gränssnittsresurser.\\n\"\n\"\\n\"\n\"Se till att devilutionx.mpq finns i spelmappen och att den är uppdaterad.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Nätverkstimeout --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Väntar på spelare --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Ingen hjälp finns\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"medan i butiker\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Bältesföremål {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Använd Bältesföremål.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Snabbtrollformel {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Genväg för förmåga eller trollformel.\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"Föregående Meny\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\n#, fuzzy\n#| msgid \"Quick spell {}\"\nmsgid \"Next quick spell\"\nmsgstr \"Snabbtrollformel {}\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Snabbok\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Öppna Snabbok.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Snabbsparning\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Sparar spelet.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Snabbladdning\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Laddar spelet.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Avsluta spelet\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Stänger spelet.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Stoppa hjälte\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Stoppar förflyttning och avbryter väntande handlingar.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Markera föremål\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Visa/dölj föremål på marken.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Slå på/av markering av föremål\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Visa/dölj alltid föremål på marken.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Slå på/av kartan\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Slå på/av om kartan visas.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Öppna Ägodelsskärm.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Karaktär\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Öppna Karaktärsskärm.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Uppdragslogg\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Öppna Uppdragslogg.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Magibok\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Öppna Magibok.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Snabbmeddelande {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Använd Snabbmeddelande i chatten.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Dölj informationsdialoger\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Dölj alla informationsdialoger.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Zoom\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Zooma spelskärmen.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Pausa spel\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Pausar spelet.\"\n\n#: Source/diablo.cpp:2004\n#, fuzzy\n#| msgid \"Pause Game\"\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Pausa spel\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Öka ljusstyrkan.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Minska ljusstyrkan.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Öka ljusstyrkan.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Öka ljusstyrkan.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Hjälp\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Öppna Hjälpskärm.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Skärmdump\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Ta skärmdump.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Spelinfo\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Visar spelinfos.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Chattpanel\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Visa chattpanel.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"Ägodelar\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"Välj Handling\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"Välj Handling\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"Avbryt\"\n\n#: Source/diablo.cpp:2175\n#, fuzzy\n#| msgid \"Closes the game.\"\nmsgid \"Close menus.\"\nmsgstr \"Stänger spelet.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"Flerspelarkaraktärer\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"Flerspelarkaraktärer\"\n\n#: Source/diablo.cpp:2212\n#, fuzzy\n#| msgid \"$Movement:\"\nmsgid \"Move left\"\nmsgstr \"$Förflyttning:\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"Flerspelarkaraktärer\"\n\n#: Source/diablo.cpp:2218\n#, fuzzy\n#| msgid \"the night\"\nmsgid \"Move right\"\nmsgstr \"natten\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"Flerspelarkaraktärer\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Autokarta\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\n#, fuzzy\n#| msgid \"Right click to use\"\nmsgid \"Right mouse click\"\nmsgstr \"Högerklicka för att använda\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\n#, fuzzy\n#| msgid \"The game ended\"\nmsgid \"Toggle game menu\"\nmsgstr \"Spelet tog slut\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Saves the game.\"\nmsgid \"Opens the game menu.\"\nmsgstr \"Sparar spelet.\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgctxt \"spell\"\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"Eldvåg\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Inga flerspelarfunktioner i demot\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Misslyckades med att skapa Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Ej tillgängligt i shareware-versionen\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Inte tillräckligt med utrymme för att spara\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Ingen Paus i byn\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Rekommenderas att kopiera till hårddisk\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Flerspelarsynkproblem\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Ingen paus i flerspelare\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Sparar...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Vissa försvagas medan en stärks\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Ny styrka byggs genom förstörelse\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"De som försvarar anfaller sällan\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Rättvisans svärd är skarpt och kvickt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Medan själen vakar når kroppen välmående\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Den refokuserade manans kraft förnyar\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Tiden kan inte minska stålets kraft\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Trolldom är inte alltid som det verkar\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Vad som en gång öppnats är nu stängt\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Intensitet fås till priset av vishet\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Mystisk kraft förödar\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Det som inte kan hållas kan inte skadas\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Blod och Himmel blir som solen\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Kunskap och vishet på ens egen bekostnad\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Drick och bli vederkvickad\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Vart du än färdas, är var du befinner dig\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Energi fås till priset av vishet\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Rikedomar möts när de är minst anade\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Där snålhet misslyckas, får tålmodigheten sin belöning\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Välsignad av en välvillig följeslagare!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Människornas händer kan styras av ödet\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Styrkan stöds av himmelsk tro\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Livets essens flödar inifrån\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Vägen är tydlig när man ser den från ovan\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Frälsning fås till priset av vishet\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Mysterier avslöjas i förnuftets ljus\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"De sista kan ännu bli de första\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Generositet ger sina egna belöningar\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Du måste vara minst nivå 8 för att använda detta.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Du måste vara minst nivå 13 för att använda detta.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Du måste vara minst nivå 17 för att använda detta.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Mystisk kunskap erhållen!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Det som inte dödar...\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Kunskap är makt.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Ge och du skall få.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"En del erfarenhet fås genom beröring.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Hem ljuva hem.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Själens energi återhämtas.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Du känner dig spänstigare.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Du känner dig starkare.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Du känner dig visare.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Du känner dig vederkvickt.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Det som kan gå sönder kommer göra det.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedralen\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Katakomberna\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Grottorna\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Nästet\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Kryptan\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Nv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} svårighetsgrad\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"I Menyn\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"loopback\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Kunde inte ansluta\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"fel: läste 0 bytes från servern\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq eller spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Vissa Hellfire-MPQ:s saknas\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Hittade inte alla Hellfire-MPQ:s.\\n\"\n\"Vänligen kopiera alla hf*.mpq-filer.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Upplösning\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Springa i Byn\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Theouppdrag\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Kouppdrag\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Autoguldupplockning\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Autoelixirupplockning\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\n#| msgid \"Auto Gold Pickup\"\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Autoguldupplockning\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Autoupplockning i Byn\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria Fyller På Mana\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Autovapenpåtagning\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Autorustningpåtagning\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Autohjälmpåtagning\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Autosköldpåtagning\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Autosmyckepåtagning\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Slumpa Uppdrag\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\n#, fuzzy\n#| msgid \"Show mana values\"\nmsgid \"Show Item Labels\"\nmsgstr \"Visa manavärden\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Autopåfyllning av Bältet\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Förbjud Handikappande Helgedomar\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Läkedrycksupplockning\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Fullkomlig Läkedrycksupplockning\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Manadrycksupplockning\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Fullkomlig Manadrycksupplockning\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Återhämtningsdrycksupplockning\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Fullkomlig Återhämtningsdrycksupplockning\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Alternativ\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Spara Spel\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Huvudmeny\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Avsluta Spel\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Hastighet\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Musik Avstängd\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Ljud\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Ljud Avstängt\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Paus\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Tangentbordsgenvägar:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Öppna Hjälpskärm\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Visa Huvudmeny\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Visa Auto-karta\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Mellanslag: Göm alla informationsskärmar\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Öppna Snabbok\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Öppna Magibok\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Öppna Ägodelsskärm\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Öppna Karaktärsskärm\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Öppna Uppdragslogg\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Minska ljusstyrka\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Öka ljusstyrka\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Zooma spelskärmen\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Zooma Autokarta\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Använd Bältesföremål\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Ställ in genväg för färdighet eller trollformel\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Vänster Musknapp: Anfall utan att flytta dig\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Vänster Musknapp (på karaktärsskärmen): Tilldela alla attributpoäng\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Vänster Musknapp (på ägodelar): Flytta föremål till bältet eller ta \"\n\"på/av föremål\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Vänster Musknapp (på bältet): Flytta föremål till ägodelar\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Förflyttning:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Om du håller ned musknappen medan du förflyttar dig kommer karaktärer \"\n\"fortsätta röra sig i den riktningen.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Strid:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Genom att hålla ned shifttangenten och vänsterklicka kan karaktären anfalla \"\n\"utan att flytta sig.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Autokarta:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Du kan nå autokartan genom att trycka på 'KARTA'-knappen på \"\n\"informationspanelen eller genom att trycka 'TAB' på tangentbordet. Du zoomar \"\n\"in och ut i kartan med tangenterna + och -. Använd pilknapparna för att \"\n\"scrolla.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Ta upp Föremål:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Användbara föremål som är små, såsom drycker eller skriftrullar, placeras \"\n\"automatiskt i ditt 'bälte' högst upp på informationspanelen. När ett föremål \"\n\"placeras i bältet dycker en liten siffra upp i den rutan. Föremålen kan \"\n\"användas genom att trycka på motsvarande siffra eller genom att högerklicka \"\n\"föremålet.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Guld:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Du kan välja en viss mängd guld att kasta genom att högerklicka på en \"\n\"guldhög i dina ägodelar.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Förmågor och Trollformler:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Du kan nå din lista av förmågor och trollformler genom att vänsterklicka \"\n\"'MAGI'-knappen i informationspanelen. Memoriserade trollformler och de som \"\n\"fås från stavar syns här. Genom att vänsterklicka på den trollformel du vill \"\n\"använda kan du förbereda den. En förberedd trollformel kan användas genom \"\n\"att högerklicka i spelområdet.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Använda Snabboken för Trollformler:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Om du vänsterklickar på 'förberedd trollformel'-knappen så öppnas \"\n\"'Snabboken' som låter dig välja en förmåga eller trollformel för omedelbart \"\n\"bruk. För att använda en förberedd förmåga eller trollformel är det bara att \"\n\"högerklicka i spelområdet.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Genom att hålla in Shift + vänsterklicka 'förberedd trollformel'-knappen kan \"\n\"den förberedda trollformeln tas bort.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Ställa in Trollformelsgenvägar:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Du kan tilldela upp till fyra tangentgenvägar för färdigheter, trollformler, \"\n\"eller skriftrullar. Börja genom att öppna 'Snabboken' enligt ovan. Tryck \"\n\"F5-, F6-, F7- eller F8-tangenterna efter att ha markerat den trollformel du \"\n\"vill tilldela.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Magiböcker:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Genom att läsa mer än en bok ökar du din kunskap om den trollformen, vilket \"\n\"låter dig använda den med större verkan.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Shareware Hellfire-Hjälp\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Hellfire-Hjälp\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Shareware Diablo-Hjälp\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Diablo-Hjälp\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Tryck ESC för att avsluta och piltangenterna för att flytta.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Kunde inte skapa huvudfönstret\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Träffsäkerhetsolja\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Mästerolja\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Skärpeolja\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Dödsolja\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Skicklighetsolja\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Smedsolja\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Ståndaktighetsolja\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Permanensolja\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Härdningsolja\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Osårbarhetsolja\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} av {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} av {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} av {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} av {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"ökar ett vapens\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"chans att träffa\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"ökar betydligt ett\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"vapens chans att träffa\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"skadepotential\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"ökar betydligt ett vapens\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"skadepotential - inte bågar\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"minskar behövda attribut\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"för att använda pansar eller vapen\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"återställer 20% av ett\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"föremåls tålighet\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"ökar ett föremåls\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"nuvarande och maximala tålighet\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"gör ett föremål oförstörbart\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"ökar pansarklassen\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"för pansar och sköldar\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"ökar betydligt pansar-\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"klassen för vapen och sköldar\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"sätter en eldfälla\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"sätter en åskfälla\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"sätter en försteningsfälla\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"återställ allt liv\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"återställ en del liv\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"återställ en del mana\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"återställ all mana\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"öka styrka\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"öka magi\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"öka smidighet\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"öka kropp\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"återställ en del liv och mana\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"återställ allt liv och mana\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Högerklicka för att visa\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Högerklicka för att använda\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Högerklicka för att läsa, därefter\\n\"\n\"vänsterklicka för att ange mål\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Högerklicka för att läsa\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Aktivera för att visa\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Öppna ägodelsskärm för att använda\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Aktivera för att använda\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Välj från magibok, därefter\\n\"\n\"använd trollformel för att läsa\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Aktivera för att läsa\"\n\n#: Source/items.cpp:1800\n#, fuzzy, c++-format\n#| msgid \"Activate to view\"\nmsgid \"{} to view\"\nmsgstr \"Aktivera för att visa\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\n#| msgid \"{:+d} to strength\"\nmsgid \"{} to use\"\nmsgstr \"{:+d} till styrka\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Välj från magibok, därefter\\n\"\n\"använd trollformel för att läsa\"\n\n#: Source/items.cpp:1811\n#, fuzzy, c++-format\n#| msgid \"Activate to read\"\nmsgid \"{} to read\"\nmsgstr \"Aktivera för att läsa\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Nivå: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Fördubblar guldkapacitet\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Krävs:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Sty\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Mag\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Smi\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Bok om {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s}s öra\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"träffchans: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% skada\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"att träffa: {:+d}%, {:+d}% skada\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% pansar\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"pansarklass: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Motstå Eld: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Motstå Eld: {:+d}% MAX\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Motstå Åska: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Motstå Åska: {:+d}% MAX\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Motstå Magi: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Motstå Magi: {:+d}% MAX\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Motstå Allt: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Motstå Allt: {:+d}% MAX\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"trollformler ökas {:d} nivå\"\nmsgstr[1] \"trollformler ökas {:d} nivåer\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"trollformler minskas {:d} nivå\"\nmsgstr[1] \"trollformler minskas {:d} nivåer\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"trollformsnivåer oförändrade (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Extra laddningar\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} laddning\"\nmsgstr[1] \"{:d} {:s} laddningar\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Eldträffskada: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Eldträffskada: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Åskträffskada: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Åskträffskada: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} till styrka\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} till magi\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} till smidighet\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} till kropp\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} till alla attribut\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} skada från fiender\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Livspoäng: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"hög tålighet\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"minskad tålighet\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"oförstörbar\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% ljusradie\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% ljusradie\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"flera pilar per skott\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"eldpilsskada: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"eldpilsskada: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"åskpilsskada {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"åskpilsskada {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"eldklotsskada: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"eldklotsskada: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"anfallare tar 1-3 skada\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"användaren förlorar all mana\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"absorberar hälften av fällskada\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"knuffar målet bakåt\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% skada mot demoner\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Allt Motstånd lika med 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"träff stjäl 3% mana\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"träff stjäl 5% mana\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"träff stjäl 3% liv\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"träff stjäl 5% liv\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"går genom målets pansar\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"kvick attack\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"snabb attack\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"snabbare attack\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"snabbast attack\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Annan förmåga (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"snabb återhämtning efter träff\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"snabbare återhämtning efter träff\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"snabbast återhämtning efter träff\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"snabb blockering\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"lägger till {:d} poäng till skada\"\nmsgstr[1] \"lägger till {:d} poäng till skada\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"avfyrar pilar med slumpmässig hastighet\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"skada som ovanligt föremål\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"ändrad tålighet\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"enhänt svärd\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"förlora livspoäng konstant\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"livsstjälande\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"inget styrkekrav\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"åskskada: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"åskskada: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"urladdning vid träff\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"ibland trippel skada\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"avtagande {:+d}% skada\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"dubbel monsterskada, enkel till dig\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Slumpvis 0 - 600% skada\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"låg tål, {:+d}% skada\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"extra PK mot demoner\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"extra PK mot ödöda\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Mana flyttas till Liv\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Liv flyttas till Mana\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"skada: {:d}  Oförstörbar\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"skada: {:d}  Tål: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"skada: {:d}-{:d}  Oförstörbar\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"skada: {:d}-{:d}  Tål: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"pansar: {:d}  Oförstörbar\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"pansar: {:d}  Tål: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Laddningar: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"unikt föremål\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Ej Identifierad\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Skelettkungens Lya\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Benkammaren\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labyrint\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Förgiftad Vattenkälla\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Ärkebiskop Lazarus Lya\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\n#| msgid \"Hellfire\"\nmsgid \"Hell Arena\"\nmsgstr \"Hellfire\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Ned till källaren\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Ned till katakomberna\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Ned till grottorna\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Ned till helvetet\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Ned till nästet\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Ned till kryptan\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Upp till nivå {:d}\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Upp till byn\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Ned till nivå {:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Ned till Diablo\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Upp till Nästets nivå {:d}\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Upp till Kryptans nivå {:d}\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Världens Hörnsten\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Ned till Kryptans nivå {:d}\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Tillbaka till nivå {:d}\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Kunde inte öppna sparat arkiv\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Ogiltig sparfil\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Spelaren är på en nivå endast för Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Ogiltigt speltillstånd\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Kunde inte visa huvudmeny\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Djur\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Demon\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Odöd\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Typ: {:s}  Dödat: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Totalt dödade: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Livspoäng: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Inget magimotstånd\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Står mot:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Magi\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Eld\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Åska\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Immun:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Typ: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Inga motståndskrafter\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Inga Immuniteter\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Vissa Magiska Motståndskrafter\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Vissa Magiska Immuniteter\"\n\n#: Source/mpq/mpq_writer.cpp:174\n#, fuzzy\n#| msgid \"Failed to open stash archive for writing.\"\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Kunde inte öppna förrådsarkivet för att skriva.\"\n\n#: Source/msg.cpp:1701\n#, fuzzy, c++-format\n#| msgid \"{:s} has cast an illegal spell.\"\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} har använt en ogiltig trollformel.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} har använt en ogiltig trollformel.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Spelaren '{:s}' (nivå {:d}) gick nyss med spelet\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Spelet tog slut\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Kunde inte få nivådata\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Spelaren '{:s}' lämnade nyss spelet\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Spelaren '{:s}' dödade Diablo och lämnade spelet!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Spelaren '{:s}' föll ur på grund av timeout\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Spelaren '{:s}' (nivå {:d}) är redan i spelet\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Mystisk\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Gömd\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Dyster\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Konstig\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Magisk\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Stenig\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Religiös\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Förtrollad\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Siande\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Fascinerande\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Kryptisk\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Uråldrig\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Kuslig\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Gudomlig\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Helig\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Helig\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Spirituell\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Spöklik\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Övergiven\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Läskig\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Tyst\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Avskild\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Sirlig\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Glittrande\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Befläckad\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Oljig\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Lysande\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Botgörarens\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Gnistrande\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Strålande\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Solens\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Murphys\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Det Stora Kriget\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Krig är Syndens Lön\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Berättelsen om Horadrim\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Den Mörka Landsflykten\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Syndakriget\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"De Tre Binds Fast\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Världarna Bortom\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Berättelsen om de Tre\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Den Svarta Kungen\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Dagbok: Trollbindelsen\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Dagbok: Mötet\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Dagbok: Utläggningen\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Dagbok: Hans Kraft Växer\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Dagbok: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Dagbok: Slutet\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"En Magibok\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Korsfäst Skelett\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Spak\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Öppen Dörr\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Stängd Dörr\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Spärrad Dörr\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Urgammal Volym\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Uselhetens Bok\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Dödskallespak\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Mytisk Bok\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Liten Kista\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Kista\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Stor Kista\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Sarkofag\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Bokhylla\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Bokhyllor\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Tunna\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Behållare\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Urna\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Helgedom\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Skelettband\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Biblioteksbok\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Blodfontän\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Halshuggen Kropp\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"De Blindas Bok\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Blodboken\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Rengörande Källa\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Pansar\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Vapenräcke\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Gethelgedom\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Kittel\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Mörk Pöl\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Tårfontän\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Stålvolymen\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Blodpiedestal\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Svampsamling\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Uselt Stativ\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Dräpt Hjälte\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} med fälla\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (deaktiverad)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"PÅ\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"AV\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Spelläge\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Spelinställningar\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Spela Diablo eller Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Begränsa till Shareware\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Gör spelet kompatibelt med demot. Möjliggör flerspelare med vänner som inte \"\n\"äger en egen kopia av Diablo.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Start\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Startinställningar\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Intro\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Visad Introfilm.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Laddningsskärm\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Visad Laddningsskärm.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logga och Titelskärm\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Titelskärm\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Diablo-specifika Inställningar\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Hellfire-specifika Inställningar\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Ljud\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Ljudinställningar\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Gångljud\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Spelaren låter vid gång.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Autopåtagningsljud\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\"Föremål som automatiskt tas på vid upplockning låter med utrustningsljudet.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Föremålsupplockningsljud\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Att plocka upp föremål låter med föremålsupplockningsljudet.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Samplingsfrekvens\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Utdatans samplefrekvens (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanaler\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Antal utdatakanaler.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Bufferstorlek\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Bufferstorlek (antal frames per kanal)\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Resamplingskvalitet\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Resamplerns kvalitet från 0 (lägst) till 10 (högst).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Påverkar spelets egen upplösning och bestämmer det visade området. OBS: \"\n\"Detta kan skilja sig från skärmupplösningen, när Uppskalning, \"\n\"Heltalsskalning eller Anpassa till Skärm används.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\n#, fuzzy\n#| msgid \"Audio Settings\"\nmsgid \"Audio device\"\nmsgstr \"Ljudinställningar\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafik\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Grafikinställningar\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Helskärm\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Visa spelet i fönster- eller helskärmsläge.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Anpassa till Skärm\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Justerar automatiskt spelfönstret till din nuvarande skrivbordsupplösning \"\n\"och -förhållande.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Uppskalning\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Aktiverar bildskalning från spelupplösningen till din bildskärms upplösning. \"\n\"Förhindrar bildskärmens upplösning från att ändras och tillåter fönstrets \"\n\"storlek att ändras.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Skalningskvalitet\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"Aktiverar frivilliga filter för den färdiga bilden vid uppskalning.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Närmsta Pixel\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilinjär\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anisotropisk\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Heltalsskalning\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Skalar bilden med en heltalskvot.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Vertikal Synk\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Åska\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Färgcykling\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Färgcyklingseffekt som används för vatten-, lava-, och syraanimationer.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternativ grafik för nästet\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"Spelet kommer använda en alternativ palett för Hellfires nest tileset.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Hårdvarupekare\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Använd hårdvarupekare\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Hårdvarupekare För Föremål\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Använd hårdvarupekare för föremål.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Hårdvarupekarens Maxstorlek\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Maximal bredd / höjd för hårdvarupekaren. Större pekare kommer falla \"\n\"tillbaka på mjukvara.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Visa FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Visar FPS (rutor per sekund) i det övre vänstra hörnet av skärmen.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Spelande\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Spelinställningar\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Aktiverar joggning/snabb gång i byn för Diablo och Hellfire. Detta \"\n\"alternativ introducerades i expansionen.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Fånga Input\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"När detta aktiveras låses musen till spelfönstret.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Aktiverar den Lilla Flickans uppdrag.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"Aktiverar Jerseyuppdraget. Bonden Lester ersätts av Fullkomligt Nöt.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Vådaskott\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Tillåter pil-/trollformelsskada mellan spelare i flerspelarläge även om \"\n\"vänskapsläge är på.\"\n\n#: Source/options.cpp:790\n#, fuzzy\n#| msgid \"No pause in multiplayer\"\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Ingen paus i flerspelare\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Testa Bard\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Tvingar Bardkaraktärstypen att synas i hjältesvalsmenyn.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Testa Barbar\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Tvingar Barbarkaraktärstypen att synas i hjältesvalsmenyn.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Erfarenhetsindikator\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"En Erfarenhetsindikator läggs till gränssnittet längst ned på skärmen.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Visa hälsovärden\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Visa nuvarande / max hälsovärde på hälsoklotet.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Visa manavärden\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Visa nuvarande / max manavärde på manaklotet.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Karaktärsinformation\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Fiendelivsindikator\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"En Fiendelivsindikator visas längst upp på skärmen.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Guld samlas automatiskt in när spelaren är nära.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Elixir samlas automatiskt in när spelaren är nära.\"\n\n#: Source/options.cpp:802\n#, fuzzy\n#| msgid \"\"\n#| \"Elixirs are automatically collected when in close proximity to the player.\"\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Elixir samlas automatiskt in när spelaren är nära.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Plockar automatiskt upp föremål i byn.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria fyller på din mana när du besöker hennes butik.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Vapen tas automatiskt på vid upplockning eller köp om detta är aktiverat.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Rustningar tas automatiskt på vid upplockning eller köp om detta är \"\n\"aktiverat.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Hjälmar tas automatiskt på vid upplockning eller köp om detta är aktiverat.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Sköldar tas automatiskt på vid upplockning eller köp om detta är aktiverat.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Smycken tas automatiskt på vid upplockning eller köp om detta är aktiverat.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Väljer slumpvis tillgängliga uppdrag för nya spel.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Visa Monstertyp\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Ett monsters typ visas i gränssnittets informationsruta då man håller musen \"\n\"över det.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"Fyll på bältet från egendomar då varje bältesföremål konsumeras.\"\n\n#: Source/options.cpp:814\n#, fuzzy\n#| msgid \"\"\n#| \"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines \"\n#| \"and Sacred Shrines are not able to be clicked on and labeled as disabled.\"\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"När detta aktiveras kommer Kittlar, Fascinerande Helgedomar, Gethelgedomar, \"\n\"Sirliga Helgedomar och Heliga Helgedomar inte kunna klickas på och kommer \"\n\"märkas som deaktiverade.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Snabbtrolleri\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Trollformelsgenvägsknappar aktiverar omedelbart trollformeln istället för \"\n\"att byta till den som förberedd trollformel.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Antal Läkedrycker som plockas upp automatiskt.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Antal Fullkomliga Läkedrycker som plockas upp automatiskt.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Antal Manadrycker som plockas upp automatiskt.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Antal Fullkomliga Manadrycker som plockas upp automatiskt.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Antal Återhämtningsdrycker som plockas upp automatiskt.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Antal Fullkommliga Återhämtningsdrycker som plockas upp automatiskt.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\n#| msgid \"Offline\"\nmsgid \"Off\"\nmsgstr \"Frånkopplad\"\n\n#: Source/options.cpp:825\n#, fuzzy\n#| msgid \"Randomize Quests\"\nmsgid \"Random Angles\"\nmsgstr \"Slumpa Uppdrag\"\n\n#: Source/options.cpp:826\n#, fuzzy\n#| msgid \"Vertical Sync\"\nmsgid \"Vertical Only\"\nmsgstr \"Vertikal Synk\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Spelkontroll\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Spelkontrollsinställningar\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Nätverk\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Nätverksinställningar\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Chatt\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Chattinställningar\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Språk\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Bestämmer vilket språk som används i spelet.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Språkinställningar\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Tangentbordskarta\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Tangentbordskarteinställningar\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping\"\nmsgid \"Padmapping\"\nmsgstr \"Tangentbordskarta\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Keymapping Settings\"\nmsgid \"Padmapping Settings\"\nmsgstr \"Tangentbordskarteinställningar\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Inställningar\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Nivå\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Erfarenhet\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Nästa nivå\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Grund\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Nu\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Styrka\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Magi\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Smidighet\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Kropp\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Poäng att fördela\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Guld\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"\"\n\"Pansar-\\n\"\n\"klass\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"chans att träffa\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Skada\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Liv\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Motstå magi\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Motstå eld\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Motstå åska\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"karak\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"uppdr\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"karta\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"meny\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"ägod\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"troll\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"röst\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"tysta\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Oanvändbar\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Skada: 1/3 av målets liv\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Läker: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Skada: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Färdighet\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Stav ({:d} laddning)\"\nmsgstr[1] \"Stav ({:d} laddningar)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Nivå {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Magi\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Skadar endast odöda\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Skriftrulle\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Stav\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Trollformelsgenväg {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Kunde inte öppna arkivet\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Kunde inte ladda karaktär\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (nivå {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Chatthistorik (Meddelanden: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} guld\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Hur många guldmynt vill du dra ifrån?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Nivå {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Erfarenhet: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Maxnivå\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Nästa Nivå: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} till Nivå {:d}\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Kung Leorics Grift\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Benkammaren\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"En Mörk Tunnel\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Oheligt Altare\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"Till {:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"Jag behöver hjälp! Kom Hit!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Följ mig.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Här får du något.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Dags att DÖ!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"Tack Till\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Tillbaka\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Skada: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Pansar: {:d}  \"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Tål: {:d}/{:d},  \"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"oförstörbar\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Välkommen till\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Smedens butik\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Vill du:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Tala med Griswold\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Köpa enkla föremål\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Köpa exklusiva föremål\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Sälja föremål\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Laga föremål\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Lämna butiken\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Jag har dessa föremål till salu:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Jag har dessa specialföremål till salu:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Du har inget jag vill ha.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Vad är till salu?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Du har inget att laga.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Laga vilket föremål?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Häxans hydda\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Tala med Adria\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Köpa föremål\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Ladda om stavar\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Lämna hyddan\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Du har inget att ladda om.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Ladda om vilket föremål?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Du har inte tillräckligt med guld\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Du har inte tillräckligt med utrymme i dina ägodelar\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Är vi överens?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Är du säker på att du vill identifiera detta föremål?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Är du säker på att du vill köpa detta föremål?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Är du säker på att du vill ladda om detta föremål?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Är du säker på att du vill sälja detta föremål?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Är du säker på att du vill laga detta föremål?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Den Träbente pojken Wirt\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Tala med Wirt\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Jag har något att sälja,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"men det kostar 50 guld\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"bara för att se det. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Vad har du?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Säg hejdå\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Jag säljer detta:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Gå därifrån\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Läkarens hus\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Tala med Pepin\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Lämna Läkarens hus\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Byäldsten\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Tala med Cain\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Identifiera ett föremål\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Du har inget att identifiera.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Identifiera vilket föremål?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Detta föremål är:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Klart\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Tala med {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Talar med {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"är inte tillgänglig\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"i shareware\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"version\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Skvaller\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Soluppgången\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Tala med Ogden\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Lämna Krogen\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Tala med Gillian\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Öppna förråd\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Fyllot Farnham\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Tala med Farnham\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Säg Hejdå\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Ditt guld: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Dräpt Bybo\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Smeden Griswold\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Läkaren Pepin\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Skadad Bybo\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Krögaren Ogden\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Cain den Äldste\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Häxan Adria\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Servitrisen Gillian\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Ko\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Bonden Lester\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Fullkomligt Nöt\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Krigare\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Rövare\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Besvärjare\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Munk\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Skald\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbar\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombie\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Ghul\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Ruttnande Kadaver\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Digerdöd\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Fallen\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Uppskärare\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Smådjävel\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Mörking\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Skelett\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Benyxa\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Brinnande Död\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Fasa\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Asätare\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Pestätare\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Skuggdjur\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Bengnagare\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Benbåge\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Skelettkapten\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Benkapten\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Brinnande Död-Kapten\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Faskapten\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Osynlig Herre\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Gömd\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Smygare\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Osedd\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Illusionsvävare\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Satyrherre\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Köttklan\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Stenklan\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Eldklan\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Nattklan\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Djävel\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Blinkare\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Dunkel\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Häxväsen\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Syrbest\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Giftspottare\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Hålbest\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Lavasluk\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Skelettkung\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Slaktaren\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Översittare\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Lerman\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Paddemon\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Skinnflådd\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Lindorm\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Grottsnigel\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Helvetesorm\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Slukare\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Magmademon\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Blodssten\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Helvetessten\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Lavaherre\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Behornad Demon\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Lerrännare\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Frostlöpare\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obsidianherre\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"gammalbent\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Röd Död\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Likdemon\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Odöd Balrog\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Förbrännare\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Eldsherre\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Domedagseld\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Helvetesbrännare\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Röd Storm\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Stormryttare\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Stormherre\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Malström\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Smådjävelskämpe\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Bevingad Demon\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargouille\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Blodklo\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Dödsvinge\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Dräpare\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Väktare\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Virvelherre\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Grottorm\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Elddrake\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Guldorm\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Safirdrake\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Svart Riddare\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Domedagsvakt\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Stålherre\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Blodsriddare\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Sönderriven\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Ihålig\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Smärtmästare\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Verklighetsvävare\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Succuba\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Snöhäxa\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Helvetesyngel\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Själsbrännare\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Rådgivare\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Nämndeman\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Kabbalist\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Advokat\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Mörkrets Furste\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Ärkeliket Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Gharbad den Svage\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar den Galne\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Snorspill\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Ärkebiskop Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Röd Vex\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Svart Jade\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Blodets Krigsherre\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Horkdemon\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Besudlaren\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Benhuvud Skarpyxe\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Svärdhud Uppskäraren\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Själsvar\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Spyråttan den Orene\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Benslitaren\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Rötfest den Hungrige\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Tarmskäraren den Snabbe\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Sprickskalle Slagsköld\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Skrädruttnaren\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Skuggbett\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Dödögat\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Villöga den Döde\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"El Chupacabras\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Skallelden\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Vridskallen\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Äckeltungan\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Pulskryparen\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Månböjaren\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Vredeskorpen\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Ryggradsätaren\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Svartaska den Brinnande\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Skuggkråkan\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Smittsten den Svage\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Gallfradga Avgrundsmästaren\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Blodskinn Mörkbåge\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Fulvinge\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Skuggdrickaren\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Dimmskiftaren\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Dödsspott\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Bloduppskäraren\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Döddskugga Köttslägga\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Stridslarv den Galne\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Glasskalle den Hackiga\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Smittoeld\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Nattvinge den Kalle\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Äckelsten\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Bronsnäve Eldsten\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Vredeseld den Dömde\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Eldssår den Bistre\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Baron Slem\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Smitthorn Stålklubba\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Kaosylaren\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Domedagsflin den Ruttnande\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Galenbrännaren\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Bensåg Liket\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Ryggradsknäckaren\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Djävulsskalle Skarpben\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Knäckstorm\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Stormbane\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Dregelpysaren\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Guldsmitta Lågan\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Svartstormen\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Pestvreden\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Flängaren\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Blåhorn\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Vrideld Helvetesyngel\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Huggtandsppjut\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Mögelskalle\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Lejonskalle den Böjde\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Svarttunga\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Äckelröraren\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Huggormselden\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Huggtandshud\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Häxeld den Ohelige\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Svartskalle\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Själsnittaren\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Vindyngel\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Avgrundens Herre\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Rostvävaren\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Ylvrede Skuggan\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Domedagsmolnet\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Blodmåne Själseld\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Häxmånen\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Slamsfestaren\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Gråvar Dräparen\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Skräckdomaren\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Stjärnöga Häxan\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Stålskalle Jägaren\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Visiren\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zamfir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Blodlust\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Nätänkan\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Köttdansaren\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Bisterspiken\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Domedagslockaren\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Kortsvärd\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Bucklare\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Klubba\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Kortbåge\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Kortstav av Mana\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Köttyxa\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"De Odödas Krona\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Empyreiska Ringen\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Magisk Sten\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Optisk Amulett\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Sanningens Ring\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Krogskylt\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Harlekinkronan\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Stålslöjan\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Det Gyllene Elixiret\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Vredens Städ\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Svartsvamp\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Hjärna\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Svampbandet\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Spökelixir\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Blodsten\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Katedralkarta\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Läkedryck\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Manadryck\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Identifiera-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Byportal-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Arkaines Mod\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Fullkomlig Läkedryck\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Fullkomlig Manadryck\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Griswolds Klinga\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Boskapsharnesk\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Lazarus Stav\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Återuppståndelse-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Kortstav\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Svärd\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Dolk\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Runbomb\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodore\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Gyllne Amulett\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Söndersliten Anteckning 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Söndersliten Anteckning 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Söndersliten Anteckning 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Återställd Anteckning\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Brun Dräkt\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Grå Dräkt\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Hätta\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Järnhätta\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Hjälm\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Helhjälm\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Krona\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Storhjälm\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Kappa\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Trasor\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Mantel\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Skrud\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Vadderat Pansar\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Läderpansar\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Hårt Läderpansar\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Nitläderpansar\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Ringbrynja\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Brynja\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Hauberk\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Fjällpansar\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Bröstharnesk\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Harnesk\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Brigantin\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Harneskrustning\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Fältharnesk\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gotisk Harnesk\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Helharnesk\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Sköld\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Liten Sköld\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Stor Sköld\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Draksköld\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Tornsköld\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gotisk Sköld\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Återhämtningsdryck\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Fullkomlig Återhämtningsdryck\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Olja\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Styrkeelixir\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Magielixir\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Smidighetselixir\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Kroppselixir\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Helbragd-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Sökning-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Åska-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Eldmur-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Inferno-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Blixt-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Infraseende-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Fasning-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Manasköld-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Eldvåg-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Eldklot-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Stenförhäxning-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Kedjeåska-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Väktare-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Nova-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Golem-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Teleportering-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Apokalyps-Skriftrulle\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Kroksabel\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Huggare\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Slagsvärd\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Klinga\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Sabel\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Långsvärd\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Bredsvärd\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Halvhandssvärd\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Tvåhandssvärd\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Jättesvärd\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Handyxa\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Yxa\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Stor Yxa\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Bredyxa\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Stridsyxa\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Långyxa\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Stridsklubba\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Morgonstjärna\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Stridshammare\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Hammare\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Spikklubba\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Stridsgissel\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Slägga\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Båge\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Jaktbåge\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Långbåge\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Kompositbåge\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Kort Stridsbåge\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Lång Stridsbåge\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Kort Krigsbåge\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Lång Krigsbåge\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Långstav\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Kompositstav\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Kvartsstav\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Krigsstav\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Ring\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Amulett\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Eldruna\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Runa\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Åskruna\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Större Eldruna\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Större Åskruna\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Stenruna\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Kortstav av Urladdning\"\n\n#: Source/translation_dummy.cpp:368\n#, fuzzy\n#| msgid \"Mana Potion Pickup\"\nmsgid \"Arena Potion\"\nmsgstr \"Manadrycksupplockning\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Slaktarens Köttyxa\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Ljussabel\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Revbågen\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Nålaren\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Stjärnhimmelsbågen\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Dödliga Jägaren\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"De Dödas Båge\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Svarteksbågen\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Eldpil\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Köttstickaren\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Vindkraft\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Örnhorn\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Gonnagals Dolk\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Försvararen\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Gripklon\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Svarta Rakkniven\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Fullmåne\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Iskniven\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Avrättarens Klinga\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Bensågen\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Skugghöken\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Trollkarlsmärlan\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Ljussabel\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Falkens Klo\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Domedagsbringaren\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Grizzlyn\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Farfarn\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Manglaren\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Vass Näbb\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Bloddödaren\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Stjärnhimmelsyxan\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Elaka Yxan\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Stenhuggaren\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Aguinaras Huggyxa\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Helvetesdödaren\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Messerschmidts Rövare\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Sprickrost\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Jholms Hammare\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Civerbs Påk\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Himlastjärnan\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Baranars Stjärna\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Gnagda Roten\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Skallkrossaren\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Schäfers Hammare\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Drömtaggen\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Skuggstaven\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Förbrännaren\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Stormspiran\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Glimmersången\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Åskanroparen\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Beskyddaren\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Najs Kluring\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Sinnesropet\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Onans Stav\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Andarnas Hjälm\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Tänkarmössan\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Storherrens Hjälm\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Dårens Krona\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Gudars Skymning\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Kungliga Tiaran\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Slitna Själars Kött\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Gladiatorns Bane\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Regnbågsmanteln\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Auts Läder\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Vishetens Förband\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Gnistrande Brynjan\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Samlarens Skal\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Nattkappan\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Najs Lätta Harnesk\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Demontaggskappan\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Deflektorn\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Halva Skallens Sköld\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Drakens Bräsch\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Svarteksskölden\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Heliga Försvararen\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Stormskölden\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Törne\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Reghas Ring\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Blödaren\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Strypande Ringen\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Förlovningsringen\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Tenn\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Mässing\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Brons\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Järn\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Stål\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Silver\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platina\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mitril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteorisk\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Underlig\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Oanvändbar\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Böjd\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Svag\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Hackig\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Dödlig\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Tung\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Hotfull\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Brutal\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Massiv\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Vild\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Hänsynslös\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Skoningslös\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Klumpig\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Slö\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Vass\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Bra\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Krigarens\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Soldatens\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Furstens\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Riddarens\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Mästarens\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Förkämpens\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Kungens\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Sårbar\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Rostig\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Stark\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Utmärkt\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Tapper\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Strålande\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Välsignad\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Hegonaktig\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Härlig\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Gudomlig\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Röd\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Blodröd\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Karmosinröd\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Rubinröd\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Blå\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Marinblå\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lapisblå\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Koboltblå\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Safirblå\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Vit\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Pärlevit\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Elfenbensvit\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Kristall\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Diamant\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topas\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Bärnsten\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Jade\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Obsidian\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Smaragd\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Hyenans\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Grodans\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Spindelns\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Korpens\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Äspingens\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Ormens\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Lindormens\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Drakens\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Nidhöggs\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hydrans\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Ängelns\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Ärkeängelns\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Ymnig\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Översvämmande\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Flammande\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Blixtrande\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"kvalitet\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"lemlästande\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"dräpande\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"blodsspillan\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"sönderslitande\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"slakt\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"smärta\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"tårar\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"hälsa\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"beskydd\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"absorption\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"återspegling\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"osmos\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"skörhet\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"svaghet\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"styrka\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"makt\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"kraft\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"jättar\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"titaner\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"paralys\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"atrofi\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"smidighet\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"skicklighet\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"träffsäkerhet\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"precision\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"perfektion\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"dåren\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"dyslexi\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"magi\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"sinnet\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"briljans\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"besvärjelse\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"trolldom\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"illamående\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"sjukdom\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"livskraft\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"livlighet\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"ork\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"vigör\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"liv\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"problem\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"gropen\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"himlen\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"månen\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"stjärnorna\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"himlen\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"zodiaken\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"gamen\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"schakalen\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"räven\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"jaguaren\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"örnen\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"vargen\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"tigern\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"lejonet\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mammuten\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"valen\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"bräcklighet\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"sprödhet\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"stadighet\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"hantverk\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"struktur\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"tidsåldrarna\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"mörkret\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"natten\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"ljus\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"utstrålning\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"låga\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"eld\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"brinnande\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"stöt\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"åska\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"tordön\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"många\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"flera\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"taggar\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"korrumpering\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"tjuvar\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"björnen\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"fladdermusen\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"vampyrer\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"igeln\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"blod\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"håltagning\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"igenomstickande\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"krossning\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"lätthet\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"snabbhet\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"hastighet\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"skyndsamhet\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"balans\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"stabilitet\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"harmoni\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"blockerande\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Den Magiska Stenen\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Gharbad den Svage\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Zhar den Galne\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Slaktaren\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Ogdens Skylt\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"De Blindas Salar\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Mod\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Blodets Stridsherre\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Kung Leorics Förbannelse\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Ärkebiskop Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Grava Nyheter\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Bondens Fruktträdgård\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Lilla Flickan\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Vandrande Köpman\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Besudlaren\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Jerseys Jersey\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Eldpil\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Helbragd\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Åska\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Blixt\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Identifiera\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Eldmur\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Byportal\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Stenförhäxning\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Infraseende\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Fasning\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Manasköld\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Eldklot\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Väktare\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Kedjeåska\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Eldvåg\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Domedagsormar\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Blodritual\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Nova\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Osynlighet\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Inferno\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Vrede\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Teleportering\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Apokalyps\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Avkroppsliga\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Reparera Föremål\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Ladda Upp Stav\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Desarmera Fälla\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elementar\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Urladdning\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Helig Pil\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Återupplivning\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekinesi\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Hela Annan\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Blodsstjärna\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Benande\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Åh, du vill alltså höra berättelsen om vår Kung? Leorics tragiska öde var \"\n\"ett svårt slag mot detta land. Folket älskade alltid Konungen, och nu lever \"\n\"de i dödsskräck för honom. Frågan jag ställer mig, om och om igen, är hur \"\n\"han kunde fallit så långt undan Ljuset med tanke på att Leoric alltid varit \"\n\"bland de heligaste människorna av alla. Endast Helvetets allra uslaste \"\n\"makter kunde ha förstört en människa så fullkomligt inifrån...\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Byn behöver din hjälp, kära mästare! För några månader sedan kidnappades \"\n\"Kung Leorics son, Prins Albrecht. Kungen blev vansinnig och rannsakade byn \"\n\"efter sitt försvunna barn. Med varje dag som gick verkade Leoric sjunka \"\n\"djupare in i galenskapen. Han försökte skylla pojkens försvinnande på \"\n\"oskyldiga bybor och lät avrätta dem brutalt. Mindre än hälften av oss \"\n\"överlevde hans galenskap...\\n\"\n\"\\n\"\n\"Kungens Riddare och Präster försökte lunga honom, men han vände sig mot dem \"\n\"och tyvärr var de tvugna att döda honom. Med sitt sista andetag nedkallade \"\n\"Kungen en fruktansvärd förbannelse på sina forna följeslagare. Han svor att \"\n\"de skulle tjäna honom för alltid i mörkret...\\n\"\n\"\\n\"\n\"Här tar historien en ännu mörkare vändning än vad jag trodde var möjligt! \"\n\"Vår forne kung har stigit upp från sin eviga sömn och styr nu en legion av \"\n\"odöda tjänare inne i Labyrinten. Hans kropp begravdes i en grift tre \"\n\"våningar under Katedralen. Snälla, kära mästare, släpp hans själ fri genom \"\n\"att förgöra hans förbannade nuvarande form...\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Som jag sade dig, kära mästare, begravdes Kungen tre våningar under mark. \"\n\"Han är därnere och väntar i det stinkande mörkret på sin chans att förstöra \"\n\"hela landet...\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Vår Kungs förbannelse har gått över, men jag är rädd att det bara var en del \"\n\"av en större ondskas verk. Men vi kanske ändå kan räddas från mörkret som \"\n\"förtär vårt land, för din seger är ett gott tecken. Må Ljuset leda dig på \"\n\"din väg, goda mästare.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Förlusten av hans son var för mycket för Kung Leoric. Jag gjorde vad jag \"\n\"kunde för att lugna hans galenskap, men det övervann honom till sist. En \"\n\"nattsvart förbannelse har hängt över detta rike ända sedan den dagen, men \"\n\"den kanske kunde brytas om du lyckas befria hans själ från dess jordiska \"\n\"fängelse...\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Jag vill inte tänka på hur Kungen dog. Jag vill minnas honom för den milde \"\n\"och rättvise härskare han var. Hans död var så sorgsen och kändes på något \"\n\"vis väldigt fel.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Jag gjorde många av de vapen och det mesta av rustningarna som Leoric \"\n\"utstyrde sina riddare med. Jag gjorde till och med ett enormt tvåhandssvärd \"\n\"av finaste mitril för honom, och en matchande fältkrona. Jag kan fortfarande \"\n\"knappt tro på hur han dog, men det måste varit en fruktansvärd kraft som \"\n\"ledde honom till galenskap!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Vad bryr jag mig om det? Hörru, inget skelett får vara MIN kung. Leoric är \"\n\"Kung. Kung, hörru? LEVE KUNGEN!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"De döda som går bland de levande följer den förbannade Kungen. Han har \"\n\"makten att väcka upp ännu fler krigare för de odödas evigt växande armé. Om \"\n\"du inte stoppar hans styre kommer han säkerligen tåga över detta land och \"\n\"slå ned alla som ännu bor här.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Lyssna, jag har affärer att sköta här. Jag säljer inte information, och jag \"\n\"bryr mig inte om någon Kung som varit död längre än jag levat. Men om du \"\n\"behöver något att använda mot den här odöda Kungen, så kanske jag kan hjälpa \"\n\"dig...\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Livets värme har kommit in i min grav. Förbered dig, dödliga, på att tjäna \"\n\"min Herre i all evighet!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Jag kan set att även du förbryllas av detta underliga beteende. Jag skulle \"\n\"vilja framkasta att eftersom många demoner räds solens ljus och tror att det \"\n\"har stor makt, kanske den soluppgång som avbildas på den skylt du talar om \"\n\"fått dem att tro att även den har någon slags mystisk kraft. Hmm, de kanske \"\n\"inte alltid är så smarta som vi fruktat...\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Mästare, jag vill berätta om en underlig upplevelse. Jag vet att du har stor \"\n\"kunskap om de monster som bor i labyrinten, och det här är något som jag \"\n\"överhuvudtaget inte kan förstå... jag vaknade mitt i natten av ett skrapande \"\n\"ljud alldeles utanför min krog. När jag tittade ut från mitt sovrum såg jag \"\n\"formerna av små demonliknande varelser i kroggården. Efter en kort stund \"\n\"sprang de iväg, men inte förrän de stal min krogskylt. Jag vet inte varför \"\n\"demonerna skulle få för sig att stjäla min skylt men lämna min familj \"\n\"ifred... besynnerligt, inte sant?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Åh. du hade inte behövt hämta tillbaka min skylt, men jag antar att det \"\n\"bespar mig kostnaden att låta göra en ny. Nåväl, låt mig se, vad skulle jag \"\n\"kunna ge dig som tack för att du hittade den? Hmmm, vad har vi här... ah, \"\n\"visst! Den här hättan lämnades i ett av rummen av en magiker som bodde här \"\n\"för ett tag sedan. Den kanske kan vara användbar för dig.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Herrejössanes, demoner som springer runt byn på natten och plundrar våra hem \"\n\"- är inget heligt? Jag hoppas Ogden och Garda mår bra. Jag antar att de \"\n\"skulle komma till mig om de blivit skadade...\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Ojdå! Är det så skylten försvann? Min Mormor och jag måste ha sovit under \"\n\"hela tiden. Tacka Ljuset att monstren inte anföll krogen.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Säger du att demoner stal Ogdens skylt? Det låter inte riktigt som de \"\n\"gruvligheter jag hört talas om - eller sett.\\n\"\n\"\\n\"\n\"Demoner bryr sig om att slita ut ditt hjärta, inte din skylt.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Vet du vad jag tror? Nån tog den där skylten, och de kommer kräva mycket \"\n\"pengar för den. Om jag var Ogden... och det är jag inte, men om jag var... \"\n\"skulle jag köpa en ny skylt med en fin bild på. Kanske en snygg ölmygg eller \"\n\"en ostbit...\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Ingen dödlig kan på riktigt förstå demonernas sinne.\\n\"\n\"\\n\"\n\"Låt aldrig deras virriga handlingar förvirra dig, även det kan vara deras \"\n\"plan.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Va - säger han att jag tog den? Antar att Griswold stöder honom såklart.\\n\"\n\"\\n\"\n\"Lyssna nu, jag slutade stjäla skyltar för flera månader sedan. Det finns \"\n\"ingen profitmarginal i trä.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Du - Du den där som döda alla! Du tar mig Magisk Fana eller vi anfalla! Du \"\n\"inte lämna med liv! Du döda stora fula och ge tillbaka Magi. Gå förbi hörn \"\n\"och dörr, hitta fula. Du ge, du går!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Du döda dula, ta fana. Du ge till mig, annars...\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"Du ge! Ja, bra! Gå nu, vi stark. Vi döda alla med stor Magi!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Detta varslar illa, ty det bekräftar mina värsta farhågor. Jag lät mig \"\n\"visserligen inte tro på de gamla legenderna, men jag kan inte tvivla på dem \"\n\"nu. Det kanske är dags att berätta vem jag är.\\n\"\n\"\\n\"\n\"Mitt verkliga namn är Deckard Cain den Äldre, och jag är den sista ättlingen \"\n\"till ett uråldrigt Brödraskap som vigde sig åt att vakta en uråldrig ondskas \"\n\"hemligheter. En ondska som nu uppenbarligen har släppts lös.\\n\"\n\"\\n\"\n\"Ärkebiskopen Lazarus, som en gång var Kung Leorics pålitligaste rådgivare, \"\n\"ledde ett band enkla bybor in i Labyrinten för att hitta Kungens försvunne \"\n\"son, Albrecht. Det dröjde länge innan de återvände, och bara ett fåtal av \"\n\"dem kom undan med livet.\\n\"\n\"\\n\"\n\"Vilken dåre jag varit! Jag borde anat hans hemliga förräderi då. Det måste \"\n\"varit Lazarus själv som kidnappade Albrecht och har gömt honom i Labyrinten \"\n\"ända sedan dess. Jag förstår inte varför Ärkebiskopen vände sig till mörkret \"\n\"eller varför han är intresserad av barnet, försåvitt han inte ämnar offra \"\n\"honom åt sin mörke mästare!\\n\"\n\"\\n\"\n\"Det måste vara vad han har planerat! Överlevarna från hans \"\n\"'räddningsexpedition' säger att Lazarus senast sågs springa mot de djupaste \"\n\"hålorna i labyrinten. Du måste skynda på och rädda prinsen från denna \"\n\"vettvillings offerklinga!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Du måste skynda på och rädda Albrecht från Lazarus grepp. Prinsen och hela \"\n\"rikets folk räknar med dig!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Din berättelse är nedslående, min vän. Lazarus kommer säkerligen brinna i \"\n\"Helvetet för sina hemska dåd. Pojken du beskriver är inte vår prins, men jag \"\n\"tror att Albrecht ännu kan vara i fara. Den kraftsymbol du beskriver måste \"\n\"vara en portal i labyrintens själva hjärta.\\n\"\n\"\\n\"\n\"Vet detta, vän - den ondska du kämpar mot är Fasans mörke Herre. Han kallas \"\n\"för Diablo av dödliga. Det var han som blev instängd i Labyrinten många \"\n\"århundraden sedan och jag är rädd att han än en gång ämnar sprida \"\n\"förstörelse i människornas värld. Du måste färdas igenom portalen och \"\n\"förgöra Diablo innan det är för sent!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus var Ärkebiskopen som ledde många av byborna in i labyrinten. Jag \"\n\"förlorade många goda vänner den dagen, och Lazarus återvände aldrig. Jag \"\n\"antar att han dödades med de flesta av de andra. Om du vill göra mig en \"\n\"tjänst, goda mästare - snälla, tala inte med Farnham om den dagen.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Jag blev chockerad när jag hörde vad byborna tänkte göra den kvällen. Jag \"\n\"trodde att Lazarus av alla människor skulle ha haft mer vett än så. Han var \"\n\"Ärkebiskop, och verkade alltid bry sig så mycket om Tristrams bybor. Så \"\n\"många blev skadade, och jag kunde inte rädda alla...\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Jag kommer ihåg Lazarus som en snäll och givmild man. Han höll tal på min \"\n\"mammas begravning och stödde mig och min mormor när vi hade det svårt. Jag \"\n\"ber varje kväll att han på något vis fortfarande är säker och vid liv.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Jag minns när Lazarus ledde oss in i labyrinten. Han talade om helig hämnd, \"\n\"men när vi började slåss mot de där helvetesvarelserna lyfta han inte ett \"\n\"finger mot dem. Han bara sprang längre ned in i de dunkla, oändliga salarna \"\n\"som var packade med mörkrets tjänare!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"De hugger, sen biter, sen är de överallt runt dig. Lurad! LURAD! Alla är \"\n\"döda! Döda! Hör du mig? De bara faller och faller... deras blod rinner ut \"\n\"över hela golvet... allt är hans fel...\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Jag kände inte denna Lazarus du talar om, men jag kan ana en stor konflikt i \"\n\"hans varelse. Han utgör en stor fara, och kommer inte sky några medel för \"\n\"att tjäna de mörkrets krafter som lagt beslag på honom.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Ja, den rättrådige Lazarus, som gjorde ett sååånt bra jobb mot monstrerna \"\n\"där nere. Räddade inte mitt ben, eller hur? Lyssna, här får du ett gratis \"\n\"råd. Fråga Farnham, han var med.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Överge ditt dåraktiga uppdrag. Det enda som väntar dig är min Mästares \"\n\"vrede! Du kommer för sent för att rädda barnet. Nu kommer du möta honom i \"\n\"Helvetet!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, jag vet inte om jag kan berätta något om det här som är till hjälp. \"\n\"Vattnet som fyller våra brunnar kommer från en underjordisk källa. Jag har \"\n\"hört talas om en tunnel som leder till en stor sjö - kanske de är en och \"\n\"samma sak. Tyvärr så vet jag inte vad som skulle kunna få våra vattenförråd \"\n\"att bli förpestade.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Jag har alltid försökt hålla stora förråd av mat och dryck i vår källare, \"\n\"men om hela byn saknar färskvatten kommer till och med våra förråd sina \"\n\"snart.\\n\"\n\"\\n\"\n\"Snälla, gör vad du kan, annars vet jag inte vad vi ska ta oss till.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Jag är glad att jag hittade dig i tid! Våra brunnar har blivit bräcka och \"\n\"unkna och några av byborna har blivit sjuka av att dricka från dem. Våra \"\n\"färskvattenförråd sinar snabbt. Jag tror att det finns en tunnel som leder \"\n\"till källorna som försörjer vår by. Snälla, hitta vad som orsakat denna \"\n\"katastrof, annars kommer vi säkert alla dö.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Snälla, du måste skynda dig. Varje timme som går närmar vi oss slutet på \"\n\"vårat dricksvatten.\\n\"\n\"\\n\"\n\"Vi kan inte överleva länge utan din hjälp.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Vad säger du - blotta närvaron av demonerna förpestade vattnet? Åh, det är \"\n\"verkligen en enorm ondska som gömmer sig under vår by, men din envishet och \"\n\"mod ger oss hopp. Var god och ta denna ring - den kanske kommer hjälpa dig \"\n\"förgöra sådana hemska varelser.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Min mormor är mycket sjuk, och Garda säger att vi inte får dricka vattnet \"\n\"från brunnarna. Snälla, kan du göra något för att hjälpa oss?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin har sagt sanningen. Vi behöver verkligen färskvatten, och snart. Jag \"\n\"har försökt rensa en av de mindre brunnarna, men den stinker av unken smuts. \"\n\"Det måste vara något som täpper till den vid källan.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Dricker du vatten?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Tristrams folk kommer dö om du inte kan få tillbaka friskt vatten i deras \"\n\"källor.\\n\"\n\"\\n\"\n\"Vet detta - demoner är kärnan i detta problem, men de själva är okunniga om \"\n\"vad de skapat.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"För en gångs skull håller jag med dig. Mina affärer sinar - så att säga - om \"\n\"jag inte har någon marknad att sälja till. Bäst att du tar reda på vad som \"\n\"händer, snart!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"En bok som förtäljer om en kammare av människoben? Nå, en Benkammare nämns i \"\n\"vissa åldrade skrifter som jag läste i Österns bibliotek. Dessa verk antydde \"\n\"att när underjordens Furstar ville skydda stora skatter, skapade de områden \"\n\"där de som dött i försök att stjäla dem bands till att försvara dem för \"\n\"evigt. Ett förfärligt slut, men på något sätt passande?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Jag är rädd att jag inte vet något om det, goda mästare. Cain har många \"\n\"böcker som kanske vore till nytta.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Det låter som en väldigt farlig plats. Om du beger dig dit så se till att \"\n\"vara mycket försiktig.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Jag är rädd att jag inte hört något om det. Kanske Historieberättaren Cain \"\n\"kan hjälpa på något sätt.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Jag vet inget om det stället, men prova att fråga Cain. Han pratar om \"\n\"mycket, och det skulle inte förvåna mig det minsta om han hade svaren till \"\n\"din fråga.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Okej, lyssna nu. Det finns alltså en träkammare, ser du. Och hans fru, du \"\n\"vet - hon - säger till trädet... du måste ju vänta. Sen säger jag, det \"\n\"kanske funkar mot honom, men om du tror att jag ska BETALA för det där... \"\n\"så... eh... japp.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Du kommer bli en tjänare till mörkrets furstar i evighet om du skulle avlida \"\n\"i denna förbannade hägn.\\n\"\n\"\\n\"\n\"Gå in i Benkammaren på egen risk.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"En enorm och mystisk skatt, säger du? Kanske jag vore intresserad av att \"\n\"köpa några saker från dig... eller ännu bättre, behöver du inte några \"\n\"sällsynta och dyra förnödenheter för att ta dig genom den här pärsen?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Det verkar som att Ärkebiskopen Lazarus lockade många av byborna till att gå \"\n\"in i Labyrinten för att hitta Kungens förlorade son. Han spelade på deras \"\n\"rädslor och eldade dem till en vansinnig folkmassa. Inga av dem var \"\n\"förberedda på vad som fanns inom den kalla jorden... Lazarus övergav dem där \"\n\"nere - i klorna på outsägliga fasor - för att dö.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Ja, Farnham har mumlat något om en gigantisk best som använde ett fasligt \"\n\"vapen. Jag tror han kallade honom en slaktare.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Vid Ljuset, jag känner till den här demonen. Det var många vars kroppar bar \"\n\"vittne av hans vrede när de få överlevarna från expeditionen Lazarus ledde \"\n\"kröp upp från Katedralen. Jag vet inte vad han använde för att skära upp \"\n\"sina offer, men det kan inte ha varit av denna värld. Det gjorde att sår \"\n\"fylldes med sjukdom och de var nästan omöjliga att behandla till och med för \"\n\"mig. Var försiktig om du tänker slåss mot denna best...\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"När Farnham sade något om en slaktare som dödade folk, trodde jag inte på \"\n\"det alls. Men eftersom du säger det är det kanske sant.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Jag såg det som Farnham kallar Slaktaren när den högg sig fram genom mina \"\n\"vänners kroppar. Han svingade en köttyxa lika stor som en stridsyxa, och \"\n\"högg loss lemmar och högg ned modiga män rakt av. Jag skildes från striden \"\n\"av en grupp små skrikande demoner och lyckades på något vis hitta trapporna \"\n\"ut. Jag såg aldrig den där fruktansvärda besten igen, men jag har \"\n\"fortfarande mardrömmar om hans blodiga ansikte.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Stor! Stor köttyxa som dödar alla mina vänner. Kunde inte stoppa honom, \"\n\"måste fly, kunde inte rädda dem. Fångad i ett rum med så många kroppar... så \"\n\"många vänner... NEEEEEEJ!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Slaktaren är en sadistisk varelse som älskar att plåga och tortera andra. Du \"\n\"har sett hans hantverk i den nedsupne Farnham. Om du förgör honom kommer det \"\n\"betyda mycket för byns säkerhet.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Jag vet mer än du kanske tror om den där vidriga besten. Hans lilla vänner \"\n\"fick tag i mig och lyckades ta mitt ben innan Griswold drog upp mig ur den \"\n\"där hålan.\\n\"\n\"\\n\"\n\"För att gå rakt på sak - döda honom innan han dödar dig och lägger din kropp \"\n\"till sin samling.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Snälla, lyssna på mig. Ärkebiskopen Lazarus, han ledde oss ned hit för att \"\n\"hitta den försvunna prinsen. Skitstöveln ledde oss in i en fälla! Nu är alla \"\n\"döda... dödade av en demon han kallade Slaktaren. Hämnas oss! Hitta denna \"\n\"Slaktare och dräp honom så att våra själar kan få vila...\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Rimmet du säger är intressant, och skrivet i en stil som påminner mig om \"\n\"andra verk. Låt mig se nu - vad var det?\\n\"\n\"\\n\"\n\"...Mörkret omger de Dolda. Osedda ögon glänser med bara ljudet av \"\n\"rakknivsvassa klors skrapande som plågar de arma själar som gjorts blinda \"\n\"för all evighet. Fängelset som de som förbannats på detta sätt kallas de \"\n\"Blindas Salar...\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Jag tyckte aldrig särskilt mycket om poesi. Ibland fick jag anlita barder \"\n\"när det gick bra för krogen, men det känns som väldigt länge sedan nu.\\n\"\n\"\\n\"\n\"Va? Åh, ja... hmm, tja, du kanske ska höra efter vad de andra vet.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Det verkar nog bekant, på något sätt. Jag tror jag minns att jag läst något \"\n\"ungefär som den där dikten medan jag forskade i demoniska förbannelsers \"\n\"historia. Det nämnde en mycket ondskefull plats som ... vänta - du ska väl \"\n\"inte dit?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Om du har frågor om blindhet borde du prata med Pepin. Jag vet att han gav \"\n\"min mormor en dryck som hjälpte för hennes syn, så han kanske kan hjälpa dig \"\n\"också.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Jag är rädd att jag varken hört eller sett någon plats som liknar den du \"\n\"beskriver så väl, min vän. Kanske Historieberättaren Cain skulle kunna vara \"\n\"till nytta.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Se här... ganska kul, va? Fattaru? Blind - se här?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Detta är en plats med mycket vånda och fasa, och på detta sätt passar den \"\n\"sin mästare bra.\\n\"\n\"\\n\"\n\"Var försiktig, annars kanske du stannar där mycket längre än du tänkt dig.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Låt os se, säljer jag dig nåt? Nej. Ger du mig pengar för att berätta för \"\n\"dig om det här? Nej. Ska du gå nu och prata med historieberättaren som lever \"\n\"för sånt här? Ja.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Du säger att du talat med Lachdanan? Han var en stor hjälte under sin \"\n\"livstid. Lachdanan var en ädel och rättvis man som tjänade sin Kung troget i \"\n\"åratal. Men det vet du förstås redan.\\n\"\n\"\\n\"\n\"Av de som fångades av Kungens förbannelse vore Lachdanan den minst sannolika \"\n\"att ge sig för mörkret utan att kämpa emot, så jag antar att din berättelse \"\n\"kan stämma. Om jag vore i ditt ställe, min vän, skulle jag hitta på ett sätt \"\n\"att befria honom från hans tortyr.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Du pratar om en modig krigare som är död sedan länge! Jag vill inte höra \"\n\"talas om att tala med hädangångna själar i min krog, tack så mycket.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Ett gyllne elixir, säger du. Jag har aldrig bryggt en dryck av den färgen \"\n\"tidigare, så jag kan inte säga dig hur det skulle påverka dig om du försökte \"\n\"dricka det. Som din läkare vill jag bestämt råda dig att om du hittar ett \"\n\"sådant elixir, gör som Lachdanan säger och försök INTE använda det.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Jag har aldrig hört talas om någon Lachdanan tidigare. Ledsen, men jag tror \"\n\"inte att jag kan vara till mycket nytta för dig.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Om det verkligen är Lachdanan du träffat skulle jag föreslå att du hjälper \"\n\"honom. Jag har mött honom vid flera tillfällen och tyckt att han varit ärlig \"\n\"och lojal till sinnet. Förbannelsen som föll över Kung Leorics följeslagare \"\n\"skulle tynga honom särskilt.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan är död. Alla vet det, och du kan inte lura mig att tro på något \"\n\"annat. Du kan inte prata med de döda. Jag vet!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Du kan komma att möta folk som är fängslade i Labyrinten, som Lachdanan.\\n\"\n\"\\n\"\n\"Jag känner heder och stor skuld i honom. Om du hjälper honom, hjälper du \"\n\"hela Tristram.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Vänta, låt mig gissa. Cain svaldes av en gigantisk spricka som öppnade sig \"\n\"under honom. Han brändes levande i ett klot av helveteseld, och kan inte \"\n\"svara på dina frågor längre. Åh, är det inte vad som hände? Isåfall antar \"\n\"jag att du kommer köpa något eller gå härifrån.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Snälla, döda mig inte, bara lyssna på mig. Jag var en gång Kung Leorics \"\n\"Riddares Kapten, och upprätthöl landets lagar med rättvisa och heder. Sen \"\n\"föll hans mörka Förbannelse över oss för den roll vi spelat i hans tragiska \"\n\"död. Medan mina Riddarbröder drabbades av sitt fruktansvärda öde, flydde jag \"\n\"från Kungens gravkammar, och sökte ett sätt ett befria mig från \"\n\"Förbannelsen. Jag misslyckades...\\n\"\n\"\\n\"\n\"Jag har hört talas om ett Gyllene Elixir som kan häva Förbannelsen och låta \"\n\"min själ vila, men jag har inte lyckats finna det. Min styrka sinar nu, och \"\n\"med den min sista mänsklighet. Snälla, hjälp mig och hitta Elixiret. Jag \"\n\"kommer återgälda dig - jag svär på min ära.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Du har inte hittat det Gyllene Elixiret. Jag är rädd att jag är fördömd för \"\n\"all evighet. Snälla, fortsätt försöka...\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Du har räddat min själ från fördömelse och jag står i skuld till dig. Om det \"\n\"någonsin finns ett sätt för mig att återgälda dig från bortom graven ska jag \"\n\"finna det, men till dess - ta min hjälm. På den resa jag nu ska färdas \"\n\"kommer jag inte ha mycket användning för den. Må den skydda dig från de \"\n\"mörka makterna nedan. Gå med Ljuset, vän...\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold talar om Vredens Städ - en legendarisk skatt som länge eftersökts, \"\n\"men aldrig blivit funnen. Den var smidd från Rakbladsavgrundens demoners \"\n\"metalliska ben, och gjuten runt skallarna av fem av underjordens \"\n\"kraftfullaste magiker. Den var inristad med kraftfulla och kaotiska runor, \"\n\"och ett vapen eller pansar som smids på detta städ blir indränkt i Kaos \"\n\"värld och indränkt med magiska krafter. Det sägs att Kaos oförutsägbarhet \"\n\"gör det svårt att veta vad som blir produkten av detta smidesarbete...\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Tror du inte att Griswold vore en bättre person att fråga om detta? Han är \"\n\"rätt händig, vet du.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Om du hade letat information om Läkandets Mortel eller Rengöringens \"\n\"Silverkalk hade jag kunnat hjälpa dig, min vän. Men i sådana här frågor vore \"\n\"det bättre om du talade med Griswold eller Cain.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Griswolds pappa sade till oss när vi var små att det fanns ett enormt städ \"\n\"som användes för att göra mäktiga vapen. Han sade att när en hammare slogs \"\n\"mot städet skakade hela jorden med vrede. Jag tänker alltid på den historien \"\n\"när jag känner marken röra sig.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Hälsningar! Det är alltid ett nöja att se en av mina bästa kunder! Jag vet \"\n\"att du gått djupare in i Labyrinten och det finns en berättelse som jag fått \"\n\"höra och som jag tror du skulle vilja höra på...\\n\"\n\"\\n\"\n\"En av männen som återvände från Labyrinten berättade för mig om ett mystiskt \"\n\"städ som han hittade under sin flykt. Hans beskrivning påminde mig om de \"\n\"legender jag fått höra i min ungdom om den brinnande Hellvetessmedjan där \"\n\"mäktiga magiska vapen smids. Legenden förtäljer att längst ner i \"\n\"Helvetessmedjan fanns Vredens Städ! Detta Städ innehöll själva essensen av \"\n\"den demoniska underjorden...\\n\"\n\"\\n\"\n\"Det sägs att vapen som smids på det brinnande Städet ingjuts med en enorm \"\n\"kraft. Om detta städ verkligen är Vredens Städ, kanske jag skulle kunna göra \"\n\"dig ett vapen som kan besegra själva Helvetets Mörka Furste!\\n\"\n\"\\n\"\n\"Hitta städet åt mig, så sätter jag igång!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Inget än, va? Nå, fortsätt leta. Ett vapen smitt på Städet skulle kunna vara \"\n\"din bästa chans, och jag är säker på att jag kan göra dig ett legendariskt \"\n\"sådant.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Jag kan knappt tro det! Detta är Vredens Städ - bra jobbat, min vän. Nu ska \"\n\"vi visa de där skitstövlarna att det inte finns några värre vapen i Helvetet \"\n\"än de som människor tillverkar! Ta det här och må Ljuset skydda dig.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold kan inte sälja sitt städ. Vad skulle han göra då? Och jag skulle \"\n\"också vara arg om någon tog mitt städ!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Det finns många skatter i Labyrinten som har krafter bortom de dödligas \"\n\"fattningsförmåga. Vissa av dem har fantastiska krafter som kan användas \"\n\"antingen av Ljuset eller Mörkret. Om du lyckas ta Städet där nedifrån skulle \"\n\"det kunna ändra Syndakrigets förlopp till Ljusets fördel.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Om du hittade en sådan skatt åt Griswold, skulle det verkligen utgöra ett \"\n\"hinder för mina affärsverksamheter. Äsch, du kommer aldrig hitta det.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Blodens Port och Eldens Salar är landmärken från ett mystiskt ursprung. Var \"\n\"du än läste den där boken måste vara en plats med stor kraft.\\n\"\n\"\\n\"\n\"Legenderna talar om en piedestal som huggits från obsidiansten och som har \"\n\"en pöl av kokande blod på sin benprydda yta. Det nämns också Blodstenar som \"\n\"kan öppna en dörr som vaktar en uråldrig skatt...\\n\"\n\"\\n\"\n\"Denna skatts art kan vi bara gissa om, min vän, men det sägs att den \"\n\"uråldrige hjälten Arkaine lade det heliga pansaret Mod i en hemlig \"\n\"skattkammare. Arkaine var den förste dödlige som vände tillbaka Syndakriget \"\n\"och jagade tillbaka mörkrets legioner tillbaka till de Brinnande Helvetena.\\n\"\n\"\\n\"\n\"Alldeles innan Arkaine dog, gömdes hans pansar i en hemlig skattkammare. Det \"\n\"sägs att när detta heliga pansar behövs igen, kommer en hjälte dyka upp för \"\n\"att ta på sig Mod än en gång. Kanske du är den hjälten...\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Alla barn har hört historien om krigaren Arkaine och hans mystiska pansar \"\n\"som kallades Mod. Om du kunde hitta dess gömställe skulle du vara väl \"\n\"skyddad mot ondskan i Labyrinten.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm... det låter som något jag borde komma ihåg, men har varit så upptagen \"\n\"med att lära mig nya botemedel och skapa bättre elixir att jag måste ha \"\n\"glömt. Ledsen...\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Historien om det magiska pansaret Mod är något som jag ofta hört pojkarna \"\n\"prata om. Bäst att du frågar någon av karlarna i byn.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Rustningen Mod skulle kunna vara det som vänder jämvikten till din fördel. \"\n\"Jag kan säga dig att många har letat efter den - så även jag. Arkaine gömde \"\n\"den väl, min vän, och det kommer krävas mer än lite tur för att uppdaga \"\n\"hemligheterna som hållit den gömd alla dessa år.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Om du hittar dessa Blodsstenar, använd dem då med försiktighet.\\n\"\n\"\\n\"\n\"Vägen är kantad av fara och ditt enda hopp ligger i din självtillförsikt.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Du tänker hitta rustningen Mod?\\n\"\n\"\\n\"\n\"Ingen har nånsin listat ut var Arkaine la det på lager, och om inte mina \"\n\"kontakter kunde hitta det tror jag knappast att du kommer heller.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Jag känner bara till en krigare som den du beskriver. Hans historia finns i \"\n\"de uråldriga krönikorna över Syndakriget...\\n\"\n\"\\n\"\n\"Befläckad av tusen år av krig, blod och död står Blodets Krigsherre på ett \"\n\"berg av sina sargade offer. Hans mörka klinga skriker ut en svart \"\n\"förbannelse åt de levande; en plågad inbjudan till alla som får för sig att \"\n\"stå framför denne Helvetets Bödel.\\n\"\n\"\\n\"\n\"Det skrivs också att fast han var en dödlig som slogs sida vid sida med \"\n\"Mörkrets Legion under Syndakriget, förlorade han sin mänsklighet åt sin \"\n\"omättliga blodtörst.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Jag är rädd att jag inte hört något om en så fruktansvärd krigare, goda \"\n\"mästare. Jag hoppas att du inte behöver slåss mot honom, för han låter \"\n\"extremt farlig.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Cain skulle kunna berätta mycket mer om något sådant än jag någonsin skulle \"\n\"vilja veta.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Om du ska kämpa mot en så farlig motståndare, må Ljuset leda och försvara \"\n\"dig. Jag kommer tänka på dig.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Mörka och hemska legender berättas om Blodets Krigsherre. Var väl förberedd, \"\n\"min vän, för han visar ingen nåd eller pardon.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Måste du alltid prata om Blod? Vad sägs om blommor, och solsken, och den där \"\n\"söta flickan som kommer med drickat. Lyssna nu, vän - du har snöat in, vet \"\n\"du det?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Hans skicklighet med svärdet är skräckinjagande, och han har levt tusentals \"\n\"år i konstant krig. Jag är ledsen... jag kan inte se om du kommer besegra \"\n\"honom.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Jag har aldrig haft affärer med den här Krigsherren du pratar om, men det \"\n\"låter som om han omsätter många svärd. Skulle gärna utrusta hans armeér...\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Min klinga sjunger för ditt blod, dödliga, och vid min mörke mästare skall \"\n\"det inte förvägras.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold talar om Himlastenen som skulle till enklaven i öst. Den skulle tas \"\n\"dit för vidare undersökningar. Stenen glödde med en energi som på något vis \"\n\"gav syn bortom vad en manlig människa kan äga. Jag vet inte vilka \"\n\"hemligheter den gömmer, min vän, men att hitta denna sten skulle säkert visa \"\n\"sig mycket värdefullt.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Karavanen stannade här för att lasta förnödenheter till sin resa österut. \"\n\"Jag sålde dem mycket färsk frukt och några utmärkta bakelser som garda just \"\n\"hade bakat. Synd vad som hände dem...\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Jag vet inte vad de trodde de kunde se med den där stenen, men jag kan säga \"\n\"detta. Om stenar faller från himlen, är det bäst att se upp!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Visst, en karavan med några mycket viktiga människor stannade här, men det \"\n\"var ett bra tag sedan. De hade konstiga accenter och skulle just på en lång \"\n\"resa, såvitt jag minns.\\n\"\n\"\\n\"\n\"Jag förstår inte hur du kan hoppas hitta något som de hade med sig.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Vänta ett slag - jag har en historia som du kanske tycker är intressant. En \"\n\"karavan som var på väg till rikena i öst färdades härigenom för en tid \"\n\"sedan. Det sägs att den fraktade en bit av himlen som ramlat ned till \"\n\"jorden! Karavanen anfölls av ryttare i mantlar alldeles norr härifrån längs \"\n\"vägen. Jag letade igenom vraken för denna himlasten, men den fanns \"\n\"ingenstans. Om du kunde hitta den, tror jag att jag kan göra något \"\n\"användbart från den åt dig.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Jag väntar fortfarande på att du ska ge mig den där stenen från himen. Jag \"\n\"vet att jag kan göra något kraftfullt från den.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Låt mig se - o ja, o ja, det är som jag trodde. Ge mig ett ögonblick...\\n\"\n\"\\n\"\n\"Ah, här får du. Jag lade in bitar av stenen i en silverring min fader \"\n\"lämnade efter sig. Jag hoppas du får användning för den.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Jag hade en gång en fin ring; det var en riktigt dyr en, med blått och grönt \"\n\"och rött och silver. Men jag kommer inte ihåg vad som hände med den. Jag \"\n\"saknar verkligen den där ringen...\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Himlastenen är mycket kraftfull, och om någon annan en Griswold hade bett \"\n\"dig hitta den, hade jag stoppat dig. Han kommer tygla dess kraft och dess \"\n\"användning kommer vara till godo för oss alla.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Om någon kan göra något från den där stenen så kan Griswold. Han vet vad han \"\n\"gör och fast jag försöker stjäla hans kunder respekterar jag nivån i hans \"\n\"produkter.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Häxan Adria letar efter en svart svamp? Jag vet lika mycket om Svarta \"\n\"Svampar som jag vet om Röda Sillar. Kanske Läkaren Pepin skulle kunna \"\n\"berätta mer, men det här är något som inte finns i mina historier eller \"\n\"böcker.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Låt mig säga detta. Varken Garda eller jag skulle NÅGONSIN servera svarta \"\n\"svampar till våra ädla gäster. Om Adria vill ha svamp i sin gryta så är det \"\n\"hennes ensak, men jag kan inte hjälpa dig hitta några. Svarta svampar... \"\n\"vidrigt!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Häxan berättade för mig att du letade efter en demonhjärna för att hjälpa \"\n\"mig skapa mitt elixir. Det kommer vara mycket användbart för de som skadas \"\n\"av dessa hemska bestar, om jag bara kan upptäcka hemligheterna som jag tror \"\n\"att dess alkemi döljer. Om du kan avlägsna en demons hjärna när du dödar \"\n\"den, skulle jag vara tacksam om du tar den till mig.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Perfekt, det här är precis vad jag tänkte mig. Jag lyckades göra färdigt \"\n\"elixiret utan den, men det kan inte skada att ha den här att studera. Skulle \"\n\"du kunna ge det här till häxan. Jag tror hon väntar på det.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Jag tror Ogden har lite svamp i sin matkällare. Varför inte fråga honom?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Om Adria inte har någon så kan du vara säker på att det är en mycket \"\n\"sällsynt sak. Jag kan inte ge mer hjälp än så, men det låter som en... \"\n\"enorm, gigantisk, övervuxen, uppsvullen svamp! God jaktlycka, antar jag.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden blandar en OTROLIG svart svamp, men jag mår illa om jag dricker sånt. \"\n\"Lyssna, lyssna... här är hemligheten - måttfullhet är nyckeln!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Vad har vi här? Intressant, det ser ut som en bok om reaktanter. Håll ögonen \"\n\"öppna efter en svart svamp. Den bör vara rätt stor och lätt att se. Om du \"\n\"hittar den, skulle du kunna ta den till mig?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Det är en stor, svart svamp jag behöver. Spring och hämta den åt mig nu så \"\n\"att jag kan använda den för en speciell brygd jag jobbar med.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Ja, det här kommer bli perfekt för en brygd jag skapar. Förresten letade \"\n\"läkaren för en hjärna från någon sorts demon så han kan behandla dem som \"\n\"förgiftats av deras etter. Jag tror han tänker göra ett elixir av den. Om du \"\n\"hjälper honom hitta det han behöver, var så vänlig och se om du kan få ett \"\n\"prov av elixiret till mig.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Varför har du tagit hit det? Jag har inget behov av en demonhjärna för \"\n\"närvarande. Men jag behöver lite av elixiret som läkaren framställer. Han \"\n\"behöver det där groteska organet du håller i, och ge mig sedan elixiret. \"\n\"Enkelt när du tänker efter, eller hur?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Va? Ger du mig elixiret från läkaren nu? Jag lyckades göra klart min brygd \"\n\"utan det. Behåll det bara...\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Jag har inga svampar av någon storlek eller färg till salu. Vad sägs om \"\n\"något mer användbart?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Så legenden om Kartan är sann. Fast jag aldrig trodde på något ur den! Jag \"\n\"antar att det är dags att jag berättar sanningen vem jag är, min vän. Du \"\n\"förstår, jag är inte riktigt som jag verkar...\\n\"\n\"\\n\"\n\"Mitt verkliga namn är Deckard Cain den Äldre, och jag är den sista ättlingen \"\n\"till ett uråldrigt Brödraskap som vigde sig åt att vakta en uråldrig ondskas \"\n\"hemligheter. En ondska som nu uppenbarligen har släppts lös.\\n\"\n\"\\n\"\n\"Ondskan som du kämpar mot är den mörke Fasans Herre - som av dödliga kallas \"\n\"Diablo. Det var han som fängslades i Labyrinten för många århundraden sedan. \"\n\"Kartan du håller i nu skapades för evigheter sedan för att visa tiden då \"\n\"Diablo skulle bryta sig fri från sitt fängelse. När de två stjärnorna på den \"\n\"där kartan går i linje med varann, kommer Diablo vara på höjden av sin \"\n\"kraft. Han kommer vara nästan odödlig...\\n\"\n\"\\n\"\n\"Du löper nu mot tiden, min vän! Hitta Diablo och förgör honom innan \"\n\"stjärnorna löper samman, annars kommer vi aldrig igen få en chans att rensa \"\n\"världen från hans ondska igen!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Vår tid är kort! Jag kan känna hans mörka makt öka och det är bara du som \"\n\"kan hindra honom från att nå sin fulla makt.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Jag är säker på att du försökte ditt bästa, men jag är rädd att till och med \"\n\"din styrka och vilja inte är nog. Diablo är nu på höjden av sin jordiska \"\n\"makt, och du kommer behöva all din styrka och mod för att besegra honom. Må \"\n\"Ljuset skydda och vägleda dig, min vän. Jag kommer hjälpa på alla sätt jag \"\n\"kan.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Om häxan inte kan hjälpa dig och föreslår att du pratar med Cain, varför \"\n\"tror du då att jag skulle veta något? Det låter som ett allvarligt problem. \"\n\"Bäst du skyndar dig till historieberättaren som Adria säger.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Jag kan inte läsa mycket av skriften på den här kartan, men kanske Adria \"\n\"eller Cain skulle kunna hjälpa dig uttyda vad den gäller.\\n\"\n\"\\n\"\n\"Jag kan se att det är en karta av stjärnorna i himlen, men vet inte mer än \"\n\"så.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Den bästa personen att fråga om den sortens sak vore vår historieberättare.\\n\"\n\"\\n\"\n\"Cain kan mycket om gamla skrifter, och det där är helt klart det äldsta \"\n\"papper jag någonsin sett.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Jag har aldrig sett den sortens karta tidigare. Var fick du tag på den? Fast \"\n\"jag inte kan läsa den, kanske Cain eller Adria kan ge dig de svar du söker.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Lyssna nu, kom nära. Jag vet inte om du vet vad jag vet, men du har \"\n\"verkligen fått tag på något där. Det där är en karta.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Åh, jag är rädd att det här är mycket illavarslande. Den här stjärnkartan \"\n\"förutspår en stor olycka, med dess hemligheter är inte mina att berätta. \"\n\"Dags för dig att ha ett allvarligt samtal med Historieberättaren...\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Jag har letat efter en karta, med det där är verkligen inte den. Du borde \"\n\"visa den för Adria - hon kan nog berätta vad det är. Jag kan säga en sak; \"\n\"den ser gammal ut, och gammal brukar betyda dyr.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Snääällla, inte skada. Inte Döda. Låt leva och nästa gång bra ge till dig.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Något för dig gör jag. Igen, inte döda Gharbad. Leva och ge bra.\\n\"\n\"\\n\"\n\"Du få den som tecken jag håller ord...\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Inget än! Nästan klar.\\n\"\n\"\\n\"\n\"Mycket kraftig, mycket stark. Leva! Leva!\\n\"\n\"\\n\"\n\"Ingen ont och löfte jag hålla!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Den för bra för dig. Mycket kraftig! Du vill ha - du ta!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Vad!? Varför är du här? Alla dessa avbrott kan få en att bli galen. Här, ta \"\n\"den här och lämna mig ifred. Stör mig inget mer!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Din nyfikenhet kommer bli din död!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Hej, min vän. Stanna ett slag och lyssna...\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Medan du färdas djupare in i Labyrinten kanske du hittar volymer med stor \"\n\"kunskap gömda där.\\n\"\n\"\\n\"\n\"Läs dem noga, för de kan berätta saker för dig som inte ens jag kan.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Jag vet många myter och legender som kan innehålla svaren till frågor som \"\n\"kan uppstå under dina färder i Labyrinten. Om du möter svårigheter och \"\n\"frågor som du vill veta svaren till, leta rätt på mig så kommer jag berätta \"\n\"vad jag kan.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold - en man med stark handlingskraft och stort mod. Jag slår vad om \"\n\"att han aldrig berättat om den gången han gick in i Labyrinten för att rädda \"\n\"Wirt, eller hur? Han vet sin beskärda del om de faror som finns där - fast \"\n\"det gör du med. Han är en skicklig hantverkare, och om han säger att han kan \"\n\"hjälpa dig på något sät kan du lita på hans ärlighet och skicklighet.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden har ägt och drivit Värdshuset och Krogen Soluppgången i snart fyra år \"\n\"nu. Han köpte den bara ett par månader innan allt här gick åt skogen. Han \"\n\"och hans fru Garda har inte pengar för att lämna byn eftersom de investerat \"\n\"allt de hade för att skapa ett liv åt sig här. Han är en bra karl med en \"\n\"djup ansvarskänsla.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Stackars Farnham. Han är en oroväckande påminnelse om den dödsdömda samling \"\n\"som gick in i Katedralen med Lazarus den mörka dagen. Han flydde med sitt \"\n\"liv, men hans mod och mycket av hans vett blev kvar i den mörka avgrunden. \"\n\"Han hittar endast tröst i botten på en sejdel nuförtiden, men ibland kommer \"\n\"fragment av sanning fram i hans ständiga babbel.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Häxan Adria sticker ut här i Tristram. Hon kom strax efter att Katedralen \"\n\"vanhelgats medan de flesta flydde. Hon byggde en liten hydda i byns utkant, \"\n\"över natten vad det verkade, och har tillgång till många konstiga och \"\n\"mystiska artefater och band med kunskap som ens jag aldrig sett innan.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Historien om Wirt är skrämmande och tragisk. Han togs från sin moders armar \"\n\"och drogs in i labyrinten av de små, fula demonerna med sina vassa spjut. \"\n\"Det var många andra barn som togs den dagen, så även Kung Leorics son. \"\n\"Palatsets Riddare gick ned men kom aldrig tillbaka. Smeden hittade pojen, \"\n\"men inte förrän de hemska bestarna börjat tortera honom för sitt sadistiska \"\n\"nöje.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Jag räknar honom som en sann vän - kanske det närmsta jag har \"\n\"här. Han är lite knäpp ibland, men det har aldrig funnits en mer \"\n\"omhändertagande eller vänlig själ. Hans kunskap och skicklighet nås inte av \"\n\"många, och hans dörr står alltid öppen.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillan är en bra kvinna. Hon är älskad för sitt glada lynne och snabba \"\n\"skratt och har en särskild plats i mitt hjärta. Hon fortsätter jobba på \"\n\"krogen för att stöda sin gamla mormor som är för sjuk för att resa. Ibland \"\n\"ororar jag mig för hennes säkerhet, men jag vet att alla män i byn hellre \"\n\"skulle dö en se henne skadas.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Hälsningar, goda mästare. Välkommen till Krogen Soluppgång!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Många äventyrare har gästat borden på min krog, och tio gånger fler \"\n\"berättelser har berättats över lika mycket öl. Det enda jag någonsin hört \"\n\"dem hålla med om var det här gamla talesättet. Kanske det kan hjälpa dig. Du \"\n\"kan skära köttet, men du måste krossa benet.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Smeden Griswold är extremt kunnig om vapen och rustningar. Om du någonsin \"\n\"behöver något gjort med din utrustning är han helt klart den du ska träffa.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham är här alldeles för ofta och dränker sina sorger i billig öl. Jag \"\n\"skulle velat visa ut honom, men han led ju så mycket under sin tid i \"\n\"Labyrinten.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria är vis för sin ålder, men jag måste erkänna - hon skrämmer mig litet.\\n\"\n\"\\n\"\n\"Nåväl, det spelar ingen roll. Om du någonsin behöver handla \"\n\"besvärjelseföremål så har hon en lustigt välsorterad hydda tvärs över ån.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Om du vill veta mer om vår bys historia så vet historieberättaren Cain en \"\n\"hel del om det förflutna.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt är en odåga och en liten skitunge. Han hamnade alltid i problem och det \"\n\"är inte förvånande hur det gick med honom.\\n\"\n\"\\n\"\n\"Han larvade säkert omkring någonstans där han inte skulle ha varit. Jag \"\n\"tycker synd om honom, men jag tycker inte om de han umgås med.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin är en fin människa - och definitivt den mest generöse i byn. Han tar \"\n\"alltid hand om andras behov, fast problem av en eller annan sort verkar \"\n\"följa honom vart han än går...\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Gillian, min Barflicka? Om det inte vore för hennes pliktkänsla till sin \"\n\"mormor skulle hon ha flytt härifrån för länge sedan.\\n\"\n\"\\n\"\n\"Det Goda vet att jag bad henne åka, jag sade till henne att jag skulle ta \"\n\"hand om den gamla kvinnan, men hon är för söt och omhändertagande för att \"\n\"göra det.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Vad plågar dig, min vän?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Jag har upptäckt något mycket intressant. Till skillnad från oss kan \"\n\"varelserna i Labyrinten läka sig själva utan att använda drycker eller magi. \"\n\"Om du skadar ett av monstren så se till att det är dött, annars kan det \"\n\"mycket väl läka.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Innan den togs över av vad det nu är som döljer sig där nere, var Katedralen \"\n\"en viktigt lärocentrum. Det finns många böcker där. Om du hittar några så \"\n\"bör du läsa allihop, för en del kan innehålla hemligheter om Labyrintens \"\n\"funktioner.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold vet lika mycket om krigskonsten som jag vet om läkekonsten. Han är \"\n\"en slug köpman, men hans hantverk är oöverträffat. Fast jag antar att det \"\n\"kan bero på att han är den enda smeden som stannat kvar.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain är en sann vän och en vis lärd man. Han har ett stort bibliotek och en \"\n\"medfödd förmåga att se den sanna naturen hos många saker. Om du har några \"\n\"frågor så är han rätt person att vända sig till.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Inte ens mina förmågor har räckt för att bota Farnham. Jag har visserligen \"\n\"lyckats läka hans kropp, men hans ande och själ är bortom mina förmågor.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Jag använder visserligen en del begränsad magi för att skapa de drycker och \"\n\"elixir jag har här, men Adria är en sann besvärjerska. Hon verkar aldrig \"\n\"sova, och hon har alltid tillgång till många mystiska böcker och skatter. \"\n\"Jag tror hennes hydda är mycket mer än det ruckel det ser ut som, men jag \"\n\"lyckas aldrig ta mig in där.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Stackars Wirt. Jag gjorde allt jag kunde för barnet, men jag vet att han \"\n\"avskyr träbenet jag var tvungen att ge honom. Hans skador var fruktansvärda. \"\n\"Ingen - och särskilt inte ett så litet barn - borde behöva lida som han \"\n\"gjorde.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Jag förstår verkligen inte varför Ogden är kvar här i Tristram. Han är lite \"\n\"nervös av sig, men han är en intelligent och arbetsam man som skulle klara \"\n\"sig väl oavsett vart han reste. Jag antar att det kan vara av rädsla av alla \"\n\"mord som händer i landsbygden runt om, eller kanske det är hans fru och \"\n\"familj som vill stanna.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogdens barflicka är en rar tös. Hennes mormor är mycket sjuk och lider av \"\n\"vanföreställningar.\\n\"\n\"\\n\"\n\"Hon säger att de är syner, men jag har inga bevis vare sig för eller emot.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"God dag! Hur kan jag hjälpa dig?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Min mormor drömde att du skulle komma och prata med mig. Hon har syner, vet \"\n\"du, och kan se in i framtiden.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Kvinnan som bor i utkanten av byn är en häxa! Hon verkar trevlig, och hennes \"\n\"namn, Adria, låter fint för örat, men jag är mycket räd för henne.\\n\"\n\"\\n\"\n\"Kanske någon väldigt modig, som du, skulle kunna se efter vad hon gör där \"\n\"ute.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Vår smed är en stolthet för Tristrams folk. Han är inte bara en \"\n\"mästarhantverare som vunnit många tävlingar i skrået, utan han har till och \"\n\"med fått beröm av vår Kung Leoric själv - må han vila i frid. Griswold är \"\n\"dessutom en stor hjälte; fråga Cain får du se.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain har varit historieberättare i Tristram så länge jag kan minnas. Han vet \"\n\"så mycket, och kan berätta saker för dig om nästan vad som helst.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham är ett fyllo som fyller sin mage med öl och alla andras öron med \"\n\"nonsens.\\n\"\n\"\\n\"\n\"Jag vet att både Pepin och Ogden känner sympati för honom, men jag blir så \"\n\"frustrerad av att se honom glida längre och längre in i en handlös berusning \"\n\"varje kväll.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin räddade min mormors liv, och jag vet att jag alldrig kan gottgöra den \"\n\"skulden. Hans förmåga att läka vilken sjukdom som helst är starkare än det \"\n\"mäktigaste svärdet och mer mystisk än alla trollformler. Om du någonsin \"\n\"behöver läkning så kan Pepin hjälpa dig.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Jag växte upp med Wirts mamma, Canace. Fast hon bara blev lätt skadad när de \"\n\"där hemska varelserna tog honom, återhämtade hon sig aldrig. Jag tror hon \"\n\"dog av ett brustet hjärta. Wirt har blivit en hård och vass yngling som bara \"\n\"är ute efter att tjäna på andras arbete. Jag vet att han lidit och sett \"\n\"fasor som jag inte ens kan föreställa mig, men en del av det där mörkret är \"\n\"fortfarande med honom.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden och hans fru har tagit mig och min mormor till sig i sitt hem och har \"\n\"till och med låtit mig tjäna ett par guldmynt genom att arbeta på krogen. \"\n\"Jag är skyldig dem så mycket, och jag hoppas att jag kan komma härifrån \"\n\"någon gång och hjälpa dem starta ett stort hotell i Östern.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Nå, vad kan jag göra åt dig?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Om du är ute efter ett bra vapen så se här. Ta ett vanligt trubbigt vapen, \"\n\"som en stridsklubba. Funkar utmärkt mot de där odöda fasorna där nere, och \"\n\"det finns inget bättre för att spräcka smala små skelett!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Yxan? Jepp, det är ett bra vapen, funkar bra mot alla fiender. Se hur den \"\n\"klyver luften, och tänk dig ett stort härligt demonhuvud i vägen. Kom ihåg \"\n\"att det tar lång tid att svinga den - men snacka om att slå till med kraft!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Titta på den här klingan, balansen. Ett svärd i rätt händer och mot rätt \"\n\"fiende, är alla vapens mästare. Dess skarpa egg har inte mycket att skära \"\n\"eller hugga igenom mot de odöda, men mot levande fiender kan ett svärd på \"\n\"riktigt skära deras kött!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Dina vapen och rustning kommer bli märkta av din kamp mot Mörkret. Om du tar \"\n\"dem till mig så kan jag, med hjälpen av lite slit och en varm ässja, \"\n\"återställa dem till toppskick.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Fast jag nästan måste smuggla in metallen och de verktyg jag behöver från de \"\n\"karavaner som går runt vår förbannade by, så verkar den där häxan Adria \"\n\"alltid få det hon behöver. Om jag visste det minsta om att tygla magin som \"\n\"hon gör skulle jag kunna skapa verkligt otroliga saker.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian är en så trevlig tös. Synd att hennes momo är så sjuk, annars skulle \"\n\"jag se till att båda kom härifrån med en av handelskaravanerna.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Ibland tycker jag att Cain talar för mycket, men jag antar att det är hans \"\n\"kall i livet. Om jag kunde böja stål lika bra som han kan böja ens öron så \"\n\"skulle jag kunna göra en hovrustning god nog åt en Kejsare!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Jag var med Farnham den där kvällen när Lazarus tog oss in i Labyrinten. Jag \"\n\"såg aldrig Ärkebiskopen igen, och kanske inte skulle överlevt om inte \"\n\"Farnham var med mig. Jag är rädd att anfallet sargade hans själ lika mycket \"\n\"som, tja, ett annat gjorde med mitt ben. Jag kan inte hjälpa honom nu, men \"\n\"jag skulle om jag kunde.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"En bra karl som sätter andra framför sig själv. Du kommer inte höra någon i \"\n\"Tristram - eller någon annanstans för den delen - som har något illa att \"\n\"säga om våran läkare.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Den där pysen kommer hamna i riktiga problem... igen, får man väl säga. Jag \"\n\"har försökt intressera honom i att jobba här och lära sig ett ärligt kneg, \"\n\"men han föredrar att profitera från att sälja gods med tvivelaktig härkomst. \"\n\"Jag kan inte skylla honom för det efter vad som hände, men jag önsakr i alla \"\n\"fall att han vore försiktig.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Krögaren har få affärer och inget riktigt sätt att tjäna pängar. Han lyckas \"\n\"hålla sig ovan ytan genom att erbjuda mat och husrum till de som då och då \"\n\"färdas genom byn, men de försvinner lika ofta under natten som de betalar \"\n\"honom. Om det inte vore för de lager med säd och torrkött som han hade i \"\n\"källaren, tja, då skulle de flesta av oss svultit det där första året när \"\n\"hela landsbygden var full med demoner.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Får man inte dricka i fred?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"Flickan som kommer med kröken? Åh ja, vilken söt tjej. Trevlig också.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Varför gör inte den gamla käringen något för en gångs skull. Visst, visst, \"\n\"hon har grejer, men lyssna nu... hon är onaturlig. Jag har aldrig sett henne \"\n\"äta eller dricka - och man kan inte lita på någon som inte dricker nånting.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain är inte vad han säger att han är. Visst, visst, han berättar bra \"\n\"historier... en del är riktigt läskiga eller roliga... men jag tror han vet \"\n\"mer än han vet han vet.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold? Gamla fina Griswold. Jag älskar honom som en bror! Vi slogs \"\n\"tillsammans vet du, då när vi... vi... Lazarus... Lazarus... Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, jag gillar Pepin. Han försöker verkligen, du vet. Lyssna nu, se till \"\n\"att du lär känna honom. Duktig kille som han med folk som alltid vill ha \"\n\"hjälp. Mm, det är ju lite som du, eller hur hjälte? Jag var en hjälte en \"\n\"gång...\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt är en unge med mer problem än tillochmed mig, och jag vet allt om \"\n\"problem. Lyssna noga - den där killen måste kränga, men han har varit där, \"\n\"vet du? Tappat ett ben! Måste gå runt på en träbit. Så illa, så illa...\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden är den finaste karlen in stan. Jag tror inte hans fru tycker om mig, \"\n\"men så länge hon fortsätter tappa kaggar tycker jag om henne. Känns som om \"\n\"jag hängt med Ogden mer än med de flesta, men han är så snälll mot mig...\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Jag vill berätta nåt, för jag vet allt om det här. Det är min specialitet. \"\n\"Den här är den bästa... deeeeen bästa! Den andra ölen är inget att ha efter \"\n\"att de dumma hundarna...\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Ingen lyss... lyssnar nånsin på mig. Nånstans - vet inte riktigt - men \"\n\"nånstans under kyrkan finns en hel hög guld. Glittrande och glänsande och \"\n\"bara väntar på att någon tar den.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Jag vet att du har dina tankar, och jag vet att du inte kommer tro det här, \"\n\"men det där vapnet du har där - det är inget att ha mot dom där stora \"\n\"typerna! Ja, jag bryr mig inte om vad Griswold säger, dom kan inte göra nåt \"\n\"som dom gjorde förritin...\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Om jag vore du... och det är jag inte... men om jag vore du, skulle jag \"\n\"sälja allt det där och sticka härifrån. Den där pojken därute... han har \"\n\"alltid nåt bra, men du måste ge honom lite guld, annars visar han inte ens \"\n\"vad han har.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Jag anar en själ som söker svar...\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Vishet förtjänas, det fås inte gratis. Om du upptäcker ett band med kunskap, \"\n\"sluka dess ord. Om du redan äger kunskap om de magiska mysterier som \"\n\"inpräntats i boken, minns detta - att ens behärskning alltid kan utökas.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Den största makten är ofta den som varar kortast. Du kan komma att finna \"\n\"uråldriga kraftord skrivna på pergamentrullar. Styrkan i dessa rullar kommer \"\n\"från förmågan hos lärjunge eller mästare att använda dem med likadan verkan. \"\n\"Deras svaghet ligger i att de måste läsas högt och aldrig kan hållas redo i \"\n\"minnet. Vet även att dessa rullar endast kan läsas en gång, så se till att \"\n\"använd dem med urskillning.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Fast solens hetta är omätbar, är en enkel ljuslåga farligare. Inga energier, \"\n\"hur stora de än månde vara, kan användas utan rätt fokus. För många \"\n\"besvärjelser kan förtrollade Stavar laddas med magiska energier flera gånger \"\n\"om. Jag har förmågan att återställa deras kraft - men vet att inget kan \"\n\"göras utan kostnad.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Summan av vår kunskap är i summan av dess folk. Om du hittar en bok eller \"\n\"skriftrulle som du inte kan uttyda, tveka inte att bringa den till mig. Om \"\n\"jag kan nå förståelse om den kommer jag dela med mig.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"För den som endast känner Järn, finns ingen större magi än Stål. Smeden \"\n\"Griswold är en större besvärjare än han själv vet. Hans förmåga att smälta \"\n\"samman eld och metall är utan dess like i detta land.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Fördärvet har slughetens styrka, men oskulden har renhetens makt. Den unga \"\n\"kvinnan Gillian har ett gott hjärta, och sätter sin matriarks behov framför \"\n\"sina egna. Hon räds mig, men det är endast på grund av att hon inte förstår \"\n\"mig.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"En kista som öppnas i mörkret har inte större skatter än då den öppnas i \"\n\"ljuset. Historieberättaren Cain är en gåta, men bara för de som inte ser. \"\n\"Hans kunskap om vad som finns nedom katedralen är betydligt större än ens \"\n\"han själv tillåter sig inse.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Ju högre du sätter din tillit till en man, desto längre måste den falla. \"\n\"Farnham har förlorat sin själ, men inte till någon demon. Den förlorades när \"\n\"han såg sina byfränder svikna av Ärkebiskopen Lazarus. Han har kunskap som \"\n\"kan skönjas, men man måste skilja fakta från fantasi.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Handen, hjärtat och sinnet kan göra mirakel när de står i perfekt balans. \"\n\"Läkaren Pepin ser in i kroppen på ett sätt som inte ens jag kan. Hans \"\n\"förmåga att läka de sjuka och sårade förstärks av hans insikt i skapandet av \"\n\"elixir och drycker. Han är bland de främsta bundsförvanter du kan få i \"\n\"Tristram.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Det finns mycket om framtiden som vi inte kan se, men när den kommer blir \"\n\"det barnen som styr den. Pojken Wirt har en svärta på sin själ, men han \"\n\"utgör ingen risk för byn eller dess folk. Hans hemliga affärer med \"\n\"gatupojkarna och de onämnbara skråna i grannstäderna ger honom tillgång till \"\n\"många objekt som inte utan vidare kan hittas i Tristram. Fast has medel kan \"\n\"vara klandervärda, kan Wirt ge hjälp i din strid mot det annalkande Mörkret.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Väggar av jord och ett stråtak är ännu inte ett hem. Krögaren Ogden är \"\n\"viktigare i den här byn än vad många förstår. Han ger skydd till Gillian och \"\n\"hennes matriark, upprätthåller det lilla liv Farnham har kvar, och utgör en \"\n\"fästpunkt för alla som är kvar i byn till vad Tristram en gång var. Hans \"\n\"krog, och de enkla nöjen som ännu finns där, ger en inblick i ett liv som \"\n\"folket här minns. Det är det minnet som ännu håller levande deras hopp för \"\n\"din framgång.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... här borta...\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Inte alla i Tristram har användning - eller en marknad - för allt som du kan \"\n\"hitta i labyrinten. Inte ens jag, trot eller ej.\\n\"\n\"\\n\"\n\"Ibland kommer bara du kunna hitta användning för vissa saker.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Lita inte på allt som fyllot säger. För mycket öl har skymt hans syn och \"\n\"vett.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Ifall du inte märkt det, så köper jag inget från Tristram. Jag importerar \"\n\"kvalitetsvaror. Om du vill kränga skrot, får du leta rätt på Griswold, Pepin \"\n\"eller den där häxan Adria. Jag är säker på att de tar allt som du kan ge \"\n\"dem...\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Antar att jag är skyldig smeden mitt liv - vad som nu är kvar av det. Visst, \"\n\"Grisswold erbjöd mig lärlingskap i smedjan, och han är väl trevlig, men jag \"\n\"kommer aldrig få tillräckligt med pengar för att... tja, låt oss bara säga \"\n\"att jag har vissa planer som kräver mycket guld.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Om jag vore ett par år äldre, skulle jag låta alla skatter jag kunde få tag \"\n\"på regna över henne, och låt mig försäkra dig om att jag kan få tack på \"\n\"riktigt fina grejer. Gillian är en vacker flicka som borde ta sig från \"\n\"Tristram så fort det är säkert. Hmmm... kanske jag tar med mig henne när jag \"\n\"sticker...\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain vet för mycket. Han skrämmer livet ur mig - ännu mer än den där kvinnan \"\n\"tvärs över ån. Han berättar alltid för mig vilken tur jag har som lever, och \"\n\"hur min historia förutspåddes i legenden. Han har inte alla indianer i \"\n\"kanoten.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - där är en gubbe med allvarliga problem, och jag vet allt om hur \"\n\"allvarliga problem kan bli. Han litade för mycket på en mans integritet, och \"\n\"Lazarus ledde honom rätt in i dödens käftar. Åh, jag vet hur det är där \"\n\"nere, så börja inte ens berätta för mig om dina planer att förgöra ondskan \"\n\"som bor i Labyrinten. Var rädd om dina ben bara...\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Så länge du inte behöver något tillbakasatt, är gamle Pepin den bäste.\\n\"\n\"\\n\"\n\"Om jag hade några av de där dryckerna han brygger, kanske jag fortfarande \"\n\"hade mitt ben...\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria stör mig verkligen. Visst, det är skumt hur mycket Cain kan berätta om \"\n\"förr, men den där häxan kan se rätt in i ditt förflutna. Hon lyckas alltid \"\n\"få allt hon behöver på något sätt, också. Adria får tag i mer varor än jag \"\n\"sett komma genom Kungsmarknadens portar under Högfestivalen.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden är en dåre som stannar här. Jag skulle kunna fixa ut honom för ett \"\n\"rimligt pris, men han insisterar på att ge den där dumma krogen ett försök. \"\n\"Jag antar att han åtminstone ger Gillian en arbetsplats, och hans fru Garda \"\n\"lagar åtminstone en fantastiskt herdepaj...\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Bortom Hjältarnas Sal ligger Benkammaren. Evig död väntar alla som försöker \"\n\"stjäla skatterna förseglade i detta rum. Så säger Fasans Herre, och så är \"\n\"det skrivet.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"...och så, instängd bortom Blodets Port och efter Eldens Sal, väntar Mod på \"\n\"Ljusets Hjälte för att vakna...\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Jag kan se där du ser föga.\\n\"\n\"Mjölkig syn och ruttet öga.\\n\"\n\"Vänd dig om gång på gång,\\n\"\n\"Du hör bara en viskad sång.\\n\"\n\"Sen ser du något utan sans,\\n\"\n\"Skuggor rör sig där ljuset fanns.\\n\"\n\"Ut ur vett och skuggans dalar,\\n\"\n\"nedkastad i De Blindas Salar.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Helvetets arsenaler är hem åt Blodets Krigsherre. I hans spår ligger \"\n\"tusentals lemlästade kroppar. Både änglar och människor har nedhuggits för \"\n\"att mätta hans eviga offrande till de Mörka som skriker efter en sak - blod.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Lyssna noga och bär vittnesmål åt sanningarna som finns häri, ty de är \"\n\"Horadrims sista arv. Det finns ett krig som ännu rasar, bortom de fält vi \"\n\"känner - mellan de utopiska rikena av de Höga Himlarna och den kaotiska \"\n\"avgrunden av de Brinnande Helvetena. Detta krig kallas den Stora Konflikten, \"\n\"och den har rasat och brunnit längre än någon av stjärnorna i himlen. Ingen \"\n\"sida får någonsin övertaget länge medan Ljusets och Mörkrets krafter \"\n\"ständigt kämpar för att få makten över skapelsen.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Lyssna noga och bär vittnesmål åt sanningarna som finns häri, ty de är \"\n\"Horadrims sista arv. När den Eviga Konflikten mellan de Höga Himlarna och de \"\n\"Brinnande Helvetena spiller över på dödlig jord, kallas den Syndakriget. \"\n\"Änglar och Demoner går bland människor i förklädnad och slåss i lönndom, \"\n\"borta från de dödligas nyfikna ögon. Vissa modiga, mäktiga dödliga har \"\n\"rentav allierat sig med endera sidan, och hjälpt styra Syndakrigets kurs.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Lyssna noga och bär vittnesmål åt sanningarna som finns häri, ty de är \"\n\"Horadrims sista arv. Nära tre hundra år sedan blev det uppdagat att de Tre \"\n\"Första Ondskorna från de Brinnande Helvetena mystiskt kommit till vår värld. \"\n\"De Tre Bröderna härjade länderna i öst under decennier, medan mänskligheten \"\n\"darrade i deras fotspår. Vår Orden - Horadrim - grundades av en grupp \"\n\"hemlighetsfulla magiker för att jaga och fånga de Tre Ondskorna en gång för \"\n\"alla.\\n\"\n\"\\n\"\n\"De ursprungliga Horadrim tillfångatog två av de Tre med kraftfulla skatter \"\n\"som kallas Själsstenar och gömde dem djupt under den öde sanden i öst. Den \"\n\"tredje Ondskan flydde fångenskapen och tog sig västerut med många av \"\n\"Horadrim efter sig. Den Tredje Ondskan - som kallas Diablo, Fasans Herre - \"\n\"fångades till sist, och hans essens bands i en Själssten och begravdes i \"\n\"denna Labyrint.\\n\"\n\"\\n\"\n\"Det är viktigt att Själsstenen måste hållas gömd från upptäckt av de som \"\n\"inte delar vår tro. Om Diablo skulle släppas lös, skulle han söka en kropp \"\n\"som är enkel att kontrollera då han skulle vara mycket svag - kanske en \"\n\"gammal man eller ett barn.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"På så vis började en stor revolution i de Brinnande Helvetena som kallades \"\n\"den Mörka Exilen. De Mindre Ondskorna störtade de Tre Första Ondskorna och \"\n\"bannlyste deras andeformer till de dödligas värld. Demonerna Belial \"\n\"(Lögnernas Herre) och Azmodan (Syndens Herre) kämpade för att ta makten över \"\n\"Helvetet under de Tre Brödernas frånvaro. Hela Helvetet polariserades mellan \"\n\"Belials och Azmodans fraktioner medan de Höga Himlarnas styrkor ständigt \"\n\"bultade mot själva Helvetets Portar.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Många demoner reste till de dödligas värld för att söka de Tre Bröderna. \"\n\"Dessa demoner följdes till de dödligas värld av Änglar som jagade dem genom \"\n\"de stora städerna i Öst. Änglarna allierade sig med en hemlightetsfull \"\n\"Magikerorden som kallades Horadrim, och som snabbt blev skickliga \"\n\"demonjägare. De gjorde sig också många mörka fiender i underjorden.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"På så vis hände det att de Tre Första Ondskorna bannlystes i andeform till \"\n\"de dödligas värld och efter att ha sått kaos i Öst under decennier fångades \"\n\"de av den förbannade Horadrimorden. Horadrim använde skatter som kallades \"\n\"Själsstenar för att binda essenserna av Mefisto, Hatets Herre, och hans bror \"\n\"Baal, Förstörelsens Herre. Den yngsta brodern - Diablo, Fasans Herre - \"\n\"flydde väst.\\n\"\n\"\\n\"\n\"Till sist fångade Horadrim även Diablo i en Själssten, och begravde honom \"\n\"under en uråldrig, bortglömd Katedral. Där sover Fasans Herre och inväntar \"\n\"sin pånyttfödelse. Veten i att han kommer söka en ung och kraftfull kropp \"\n\"att besätta - en som är oskyldig och enkel att kontrollera. Han kommer den \"\n\"resa sig för att befria sina Bröder och återigen blästra Syndakrigets \"\n\"lågor...\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Alla lovord åt Diablo - Fasans Herre och överlevare av den Mörka Exilen. När \"\n\"han vaknade från sin långa sömn, berättade min Herre och Mästare för mig om \"\n\"hemligheter som få dödliga känner till. Han berättade för mig att de Höga \"\n\"Himlarnas riken och de Brinnande Helvetenas avgrunder står i evigt krig. Han \"\n\"avslöjade makterna som fört denna konflikt till människornas värld. Min \"\n\"herre har döpt striden om denna värld och alla som finns här Syndakriget.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Ära och Underkastelse åt Diablo - Fasans Herre och de Tres Ledare. Min Herre \"\n\"berättade för mig om sina två Bröder, Mefisto och Baal, som bannlystes till \"\n\"denna värld för länge sedan. Min Herre önskar bida sin tid och få bruk av \"\n\"sin mäktiga styrka så han kan befria sina fångade bröder från deras grifter \"\n\"under österns sand. När min Herre befriar sina Bröder, kommer Syndakriget \"\n\"återigen få se de Tres vrede.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Hälsningar och Offer till Diablo - Fasans Herre och Själarnas Förgörare. När \"\n\"jag väckte min Mästare från hans sömn, försökte han besätta en dödligs form. \"\n\"Diablo försökte inta Kung Leorics kropp, men min Mästare var för svag från \"\n\"sin fångenskap. Min Herre krävde ett enkelt och oskyldigt ankar till denna \"\n\"värld, och fann pojken Albrecht perfekt för ändamålet. Medan den gode Kung \"\n\"Leoric blev galen av Diablos framgångslösa besättning, kidnappade jag hans \"\n\"son Albrecht och tog honom till min Mästare. Jag väntar nu på Diablos kall \"\n\"och ber att jag kommer bli belönad när han till sist träder främ som den här \"\n\"världens Herre.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Tack och lov att du kommit tillbaka!\\n\"\n\"Mycket har ändrats sedan du bodde här, min vän. Allt var frid och fröjd \"\n\"tills de mörka ryttarna kom och förstörde vår by. Många höggs ned där de \"\n\"stod, och de som tog till vapen dräptes eller drogs bort för att bli slavar \"\n\"- eller värre. Kyrkan i byns utkant har blivit vanhelgad och används för \"\n\"mörka ritualer. Skriken som ekar i natten är omänskliga, men en del av \"\n\"byborna kan fortfarande överleva. Följ stigen som ligger mellan min krog och \"\n\"smedens butik för att komma till kyrkan och rädda alla du kan. \\n\"\n\"\\n\"\n\"Kanske kan jag berätta mer om vi talas vid igen. Lycka till.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Fortsätt med ditt uppdrag. Att hitta en skatt som försvunnit är inte lätt. \"\n\"Att hitta en skatt som gömts ännu mindre. Jag lämnar dig med detta. Låt inte \"\n\"tidens sand förvirra ditt sökande.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"En vad? Det här är dårskap. Det finns ingen gömd skatt här i Tristram. Låt \"\n\"mig se det där!! Äh, kolla, den här ritningen stämmer inte. Det liknar inte \"\n\"vår by alls. Jag skulle tänka på vad som finns nedanför katedralen, inte vad \"\n\"som finns nedanför jorden.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Jag har inte riktigt tid att prata om någon karta du letar efter. Jag har \"\n\"många sjuka som behöver min hjälp och din med för den delen.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Den en gång stolte Iswall är fångad djupt under denna världs yta. Hans heder \"\n\"borttagen och hans uppsyn förändrad. Han är fången i odödlig plåga. Satt att \"\n\"vakta just den sak som kunde befria honom.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Jag slår vad om att Wirt anade vad det handlade om och spelade teater bara \"\n\"för att skratta åt dig senare när du springer runt byn med näsan i marken. \"\n\"Jag skulle strunta i det.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Det fanns en gång en tid när den här byn ofta besöktes av långväga resande. \"\n\"Mycket har ändrats sedan dess. Men gömda grottor och skatter är vanliga \"\n\"fantasier hos alla barn. Wirt låter sig sällan leka ungdomens lekar. Så det \"\n\"är kanske bara hans fantasi.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Lyssna nu. Kom när. Jag vet inte om du vet vad jag vet, men du har verkligen \"\n\"fått tag i något där. Det där är en karta.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Min mormor berättar ofta historier om mystiska krafter som bebor kyrkogården \"\n\"utanför byn. Och du kanske vill höra en av dem. Hon sade att om man lämnar \"\n\"en lämplig gåva i kyrkogården, går in i katedralen för att be för de döda, \"\n\"och sedan kommer tillbaka, så skulle gåvan ändrats på något konstigt sätt. \"\n\"Jag vet inte om det bara är en sjuk gammal kvinnas prat, men allt verkar \"\n\"möjligt nuförtiden.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"En enorm och mystisk skatt, säger du? Kanske jag vore intresserad av att \"\n\"köpa några saker från dig... eller ännu bättre, behöver du inte några \"\n\"sällsynta och dyra förnödenheter för att ta dig genom den här pärsen?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Så, du är hjälten som alla talat om. Kanske du skulle kunna hjälpa en enkel, \"\n\"fattig bonde ur en hemsk knipa? I utkanten av min fruktträdgård, en bit \"\n\"söderut, finns det en fruktansvärd sak som sväller ut ur marken! Jag kan \"\n\"inte nå mina grödor eller höbalar, och mina stackars kor kommer svälta. \"\n\"Häxan gav den här till mig och sade att den skulle spränga den där saken ur \"\n\"fältet. Om du kunde förstöra den vore jag evigt tacksam. Jag skulle gjort \"\n\"det själv, men någon måste stanna här med korna...\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Jag visste att det inte kunde vara så enkelt som den där häxan fick det att \"\n\"låta. Det är tragiskt att man inte ens kan lita på sina grannar.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Är den borta? Sprängde du den tillbaka till de mörka vrårna i Hades den kom \"\n\"från? Du vad? Åh, säg inte att du tappat bort den! De där är inte billiga, \"\n\"vet du. Du får leta rätt på den, och spräng bort den där hemskheten från byn.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Jag hörde explosionen härifrån! Många tack till dig, vänliga främling. Med \"\n\"alla saker som kommer upp ur marken, monster som tar över kyrkan, och så \"\n\"vidare, är det här prövande tider. Jag är bara en fattig bonde, men här -- \"\n\"ta det här med mina varmaste tack.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Åh, ett sånt problem jag har...kanske...Nej, jag kan inte tränga mig på dig, \"\n\"med allt annat som händer. Kanske efter att du rensat ur kyrkan från en del \"\n\"av de där monstren skulle du kunna komma tillbaka... och hjälpa en stackars \"\n\"bonde?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Buhuuu! (snyft) Buhuuu! (snyft)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Jag tappade bort Theo! Min bästa vän! Vi lekte borta vid floden, och Theo sa \"\n\"att han ville kolla på den stora gröna saken. Jag sade nej, men vi smög dit, \"\n\"och sen kom en INSEKT ut! Vi sprang iväg men Theo ramlade och insekten TOG \"\n\"honom och tog bort honom!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Hittaru honom? Du måste hitta Theodor, snälla! Han är bara liten. Han kan \"\n\"inte ta hand om sig själv! Snälla!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Du hittade honom! Du hittade honom! Tack! Åh Theo, skrämde de där insekterna \"\n\"dig? Men! Usch! Det sitter nåt i din päls! Fy! Kom Theo, så går vi hem! Tack \"\n\"igen, hjältisen!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Vi har länge legat i dvala, och tiden är kommen för att vakna. Efter vår \"\n\"långa sömn fylls vi med en stor hunger. Snart, nu, ska vi äta...\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Har du haft trevligt, lilla däggdjur? Ynkligt. Din lilla värld blir ingen \"\n\"utmaning alls.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Dessa land kommer bli besudlade, och vår avkommer kommer täcka de fält som \"\n\"människorna kallar sitt hem. Våra spröt kommer inringa denna värld, och vi \"\n\"kommer kalasa på dess invånares kött. Människorna kommer bli vår boskap och \"\n\"proviant.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, jag känner din lukt...du är nära! Nära! Ssss...lukten av blod och \"\n\"skräck...ljuvligt...\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Och i det Gyllne Ljusets år, slogs det fast att en stor Katedral skulle \"\n\"byggas. Hörnstenen till denna heliga plats skulle huggas från den \"\n\"genomskinliga stenen Antyrael, döpt efter Ängeln som delade sin kraft med \"\n\"Horadrim.\\n\"\n\"\\n\"\n\"I de Nalkande Skuggornas år, skakade marken och Katadralen spräcktes och \"\n\"rasade. Medan byggandet av katakomber och borgar började och människan stod \"\n\"mot Syndakrigets härjningar plundrades ruinernas stenar. Och på så vis \"\n\"försvann hörnstenen från människornas blick.\\n\"\n\"\\n\"\n\"Stenen var av denna värld -- och alla världar -- på samma sätt som Ljuset \"\n\"finns både inom allt och bortom allt. Ljus och enighet är detta heliga \"\n\"fundaments produkter, en enighet i strävan och enighet i ägande.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Mu.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Jag sade, Mu.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Hörru, jag är bara en ko, OK?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Okej, okej. Jag är inte en ko på riktigt. Jag går inte vanligtvis runt så \"\n\"här; men, jag satt hemma och brydde mig om mitt när det helt plötsligt \"\n\"började komma kryp och lianer och lökar och grejer ut ur golvet... det var \"\n\"hemskt! Om jag bara hade något vanligt att ha på mig, skulle det inte vara \"\n\"så illa. Men! Skulle du kunna gå tillbaks till mitt hus och hämta min dräkt \"\n\"åt mig? Den bruna, inte den gråa, den är för aftnar. Jag skulle göra det \"\n\"själv, men jag vill inte att någon ser mig så här. Här, ta den här, du kan \"\n\"behöva den... för att döda de där sakerna som växt över allt. Du kan inte ta \"\n\"miste på mitt hus, den är alldeles söder om åns delning... du vet... den med \"\n\"den övervuxna grönsaksträdgården.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Vad slösar du tid för? Gå och hämta min dräkt! Och skynda! Den här \"\n\"låglandsboskapen här flörtar med mig!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Va, har du min dräkt där? Fort, ge den till mig! Du skulle inte tro hur \"\n\"mycket de här öronen kliar!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Nej nej nej nej! Det här är min GRÅA dräkt! Det är en aftonklädsel! Formella \"\n\"tillställningar! Jag kan inte ha den HÄR. Är du nån slags knäppgök? Jag \"\n\"behöver den BRUNA dräkten.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, MYCKET bättre. Pust! Äntligen lite värdighet! Sitter mina horn rakt? \"\n\"Bra. Okej, tack så mycket för hjälpen. Här, ta den här som gåva; och du \"\n\"vet... ett modetips... du kanske behöver lite... du skulle ha en ny... \"\n\"duvetvadjagmenar? Hela äventyrarmotivet är bara så... retro. Bara ett råd, \"\n\"visst? Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Lyssna. Jag är en ko. Och du är monstermat. Skaffa lite erfarenhet! Sen \"\n\"pratar vi...\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Det måste verkligen vara en fruktansvärd uppgift jag satt dig till. Om jag \"\n\"bara kunde... skulle en flaska härlig färsk mjölk hjälpa?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Jo, jag skulle behöva din hjälp, men kanske efter att du räddat katakomberna \"\n\"från de där vilddjuren.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Jag behöver något gjort, men jag kan inte tränga mig på en främling. Kanske \"\n\"jag kommer känna mig mer bekväm med att be om en tjänst efter att du varit \"\n\"här ett tag.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Jag ser en potential för storhet i dig. Kanske du kan komma förbi och göra \"\n\"mig en tjänst någon gång medan du uppfyller ditt öde?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Jag tror att du skulle kunna hjälpa mig, men kanske efter att du blivit lite \"\n\"starkare. Jag skulle inte vilja skada byns enda chans att förgöra hotet i \"\n\"kyrkan!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Jag har byggt upp mig själv från grunden. Bygg upp dig själv... sen pratar \"\n\"vi.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Jag måste inte förklara mig för varje turist som kommer förbi! Har du inte \"\n\"monster att döda! Kanske vi kan prata sen. Om du överlever...\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Sluta tjata på mig. Jag letar efter någon verkligt heroisk. Och du är inte \"\n\"det. Jag kan inte lita på dig, du kommer bli monstermat närsomhelst nu... \"\n\"jag behöver en erfaren hjälte.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Okej, slut med bullshit. Jag ville inte leda dig på fel kosa. Jag satt hemma \"\n\"och tjurade när det helt plötsligt började komma en tjurrusning av monster \"\n\"ur golvet, det var hemskt! Jag hoppade därifrån som en kviga. Om jag bara \"\n\"hade något vanligt att ha på mig, skulle det inte vara så illa. Men! Skulle \"\n\"du kunna gå tillbaks till mitt hus och hämta min dräkt åt mig? Den bruna, \"\n\"inte den gråa, den är för aftnar. Jag skulle göra det själv, men jag vill \"\n\"inte att någon ser mig så här. Här, ta den här, du kan behöva den... för att \"\n\"döda de där sakerna som växt över allt. Du kan inte ta miste på mitt hus, \"\n\"den är alldeles söder om åns delning... du vet... den med den övervuxna \"\n\"grönsaksträdgården.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Jag har försökt trollformler, hot, besvärjelser och förhandling med den här \"\n\"vidriga varelsen -- till ingen lycka. Mina metoder för att förslava mindre \"\n\"demoner verkar inte ha någon verkan på detta skräckinjagande väsen.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Mitt hem blir långsamt förvridet va denna oönskade fånges uselhet. Kryptorna \"\n\"är\\tfulla av skuggor som rör sig i utkanterna av min syn. Det antydda \"\n\"skrapandet av klor dansar ytterst i min hörsel. De letar, tror jag, efter \"\n\"den här dagboken.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"I sitt orerande råkade varelsen nämna sitt namn -- Na-Krul. Jag har försökt \"\n\"efterforska namnet, men de mindre demonerna har på något vis förstört mitt \"\n\"bibliotek. Na-Krul... namnet fyller mig med en kall skräck. Jag tänker \"\n\"hellre på den som helt enkelt Varelsen än att fundera på dess rätta namn.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Den fångade varelsens vredesrop hindrar mig från min välbehövliga sömn. Den \"\n\"rasar mot den som skickade den till Tomheten, och nedkallar hemska \"\n\"förbannelser på mig för att jag håller den fången. Dess ord fyller mitt \"\n\"hjärta med fasa, och ändå kan jag inte stänga ute dess röst.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Min tid är kort. Jag måste nedteckna sätten för att försvaga demonen, och \"\n\"sedan gömma texten, så att inte hans tjänare hittar något sätt att använda \"\n\"min kunskap för att befria sin herre. Jag hoppas att den som hittar den här \"\n\"dagboken kommer leta rätt på kunskapen.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Den som hittar denna skriftrulle åläggs att stoppa den demoniska varelse som \"\n\"finns inom dessa murar. Min tid är över. I denna stund klöser dess \"\n\"helvetiska undersåtar på den svaga dörr jag gömmer mig bakom.\\n\"\n\"\\n\"\n\"Jag har hältat demonen med mystisk magi och förslutit den i dessa murar, men \"\n\"jag är rädd att det inte är nog.\\n\"\n\"\\n\"\n\"Besvärjelserna som finns i mina tre böcker kommer ge dig skyddad tillgång \"\n\"till hans värld, men bara om de används i rätt ordning. Spakarna vid \"\n\"ingången kommer ta undan spärrarna och befria demonen; rör dem inte! Använd \"\n\"endast dessa besvärjelser för att komma in, annars kan hans makt vara för \"\n\"stor för dig att besegra.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Helvetessvin\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Stingare\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psykoklot\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Araknon\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Avtvilling\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Horkyngel\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Giftsvans\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Nekroklot\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Spindelherre\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Piskorm\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Fackelmyra\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Helveteskryp\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Dödgrävare\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Griftråtta\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Eldfladdermus\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Skallvinge\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Lik\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Kryptdemon\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Helvetesfladdermus\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Bendemon\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Ärkelik\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Biklop\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Köttsak\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Skördare\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Jättens Knoge\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Merkuriska Ringen\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Xorines Ring\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Kariks Ring\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Magmaringen\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Mystikernas Ring\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Åskringen\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Skyddamuletten\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Knottbettet\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Flambeau\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Dysterhetens Pansar\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Blitzen\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Åsksmällen\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Själsätaren\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Diamanteggen\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Benbrynja\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Demonharnesk\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Lärjungens Amulett\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Gladiatorns Ring\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Narrens\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Kristallaktig\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Dubbelgångarens\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"förödelse\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"förruttnelse\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"fara\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Magikern\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Narren\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Åskvägg\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Förbränning\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Varpning\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Återspegling\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Bärsärk\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Eldsring\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Sökning\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Eldruna\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Ljusruna\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Novaruna\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Förbränningsruna\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Stenruna\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"Alternativ:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"version {:s}\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Minska Gamma\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Öka Gamma\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"Ingen autokarta tillgänglig i byn\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Starta Om i Byn\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Hjärta\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"återhämta liv\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"dödlig helning\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"minska styrka\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"minska smidighet\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"minska kropp\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"du kan inte läka\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"träffade monster läker inte\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"Snabbare anfallssving\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"se med infraseende\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Försöker du slänga ett föremål från golvet?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Tvingar väntan på Vertikal Synk. Förhindrar rivningseffekter då en bild \"\n#~ \"ritas. Att slå av detta kan minska muslagg på vissa system.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"FPS-Begränsare\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"FPS begränsas för att undvika hög processorbelastning. Gränsen tar \"\n#~ \"uppdateringsfrekvens i beaktning.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"\"\n#~ \"Träff-\\n\"\n#~ \"chans\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"Kunde inte öppna spelararkivet för att skriva.\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"Kunde inte läsa in sparfilsarkivet\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"Kunde inte skriva till sparfilsarkivet\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"Oförstörbar,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"Inga krävda attribut\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"Bortom Hjältarnas Sal ligger Benkammaren. Evig död väntar alla som \"\n#~ \"försöker stjäla skatterna förseglade i detta rum. Så säger Fruktans \"\n#~ \"Herre, och så är det skrivet.\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"Helvetets arsenaler är hem åt Blodets Krigsherre. I hans spår ligger \"\n#~ \"tusentals lemlästade kroppar. Både änglar och människor har nedhuggits \"\n#~ \"för att mätta hans eviga offrande till de Mörka som skriker efter en sak \"\n#~ \"- blod.\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"Molnigt och kallare idag. Fick två nya underarter av flygande fasor genom \"\n#~ \"att kasta nekromantiska nät över tomheten; ett bra dagsverke. Måste komma \"\n#~ \"ihåg att beställa mer fladdermusguano och svara ljus från Adria; de \"\n#~ \"börjar ta slut.\"\n\n#~ msgid \"Right click to read\"\n#~ msgstr \"Högerklicka för att läsa\"\n"
  },
  {
    "path": "Translations/tr.po",
    "content": "#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:21+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: tr\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Oyun Tasarımı\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Kıdemli Tasarımcılar\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"İlave Tasarım\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Baş Programcı\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Kıdemli Programcılar\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Programlama\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Misafir Programcılar\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net Programlama\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Seri İletişim Programlama\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Yükleyici Programlama\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Sanat Yönetmenleri\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Sanatçılar\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Teknik Sanatçılar\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Sinema Sanat Yönetmenleri\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D Sinema Sanatçıları\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Teknik Sinema Sanatçıları\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Baş Yapımcı\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Yapımcı\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Yardımcı Yapımcı\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Ekibi\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Müzik\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Ses Tasarımı\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Sinema Müzik ve Ses\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Ses Prodüksiyon, Yönetmen ve Kast\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Senaryo ve Hikaye\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Ses Kurgusu\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Sesler\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Ses Mühendisi\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Kılavuz Tasarımı & Dizilim\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Kılavuz Sanatçıları\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Geçici QA Yönetmeni (Baş Testçi)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA Hücum Timi (Testler)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA Özel Harekat Timi (Uyumluluk Testleri)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA Topçu Birlikleri (Ek Testler) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA Kontrespiyonaj\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Ağ Bilgi Hizmetleri Tarikatı\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Müşteri Destek\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Satış Birimi\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Bay Dabirinin Yardımcı Vokalistleri\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Halkla İlişkiler\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Pazarlama\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Uluslararası Satış Bilimi\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Birleşik Devletler Satış Birimi\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Üretim\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Hukuk ve İş Birimi\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Özel Teşekkürler\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Teşekkürler\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"Anısına\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Çok Özel Teşekkürler\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Genel Müdür\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Yazılım Mühendisi\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Sanat Yönetmeni\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Sanatçılar\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Tasarım\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Ses Tasarımı, SFX & Ses Mühendisliği\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Kalite Kontrol Sorumlusu\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Testçiler\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Kılavuz\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tEk İşler\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Görev Yazarları\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Teşekkürler\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tBlizzard Entertainmenta Özel Teşekkürler\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Kalite Kontrol Müdürü\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Kalite Kontrol Test Sorumlusu\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Ana Testçiler\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Ek Testçiler\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Ürün Pazarlama Müdürü\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Halkla İlişkiler Müdürü\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Yardımcı Ürün Müdürü\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Binler Kulübü\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tBu oyunun yapımında hiçbir ruh satılmamıştır.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"TAMAM\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Sınıf Seç\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"İptal\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Yeni Çok Oyunculu Kahraman\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Yeni Tek Oyunculu Kahraman\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Oyun Kaydı Bulunuyor\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Oyun Yükle\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Yeni Oyun\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Tek Oyunculu Karakterler\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Haydut ve Büyücü sadece Diablonun tam sürümünde mevcuttur. Satın almak için \"\n\"ziyaret edin: https://www.gog.com/game/diablo\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"İsim Gir\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Geçersiz isim. Karakter ismi boşluk, yasaklı karakterler ve yasaklı \"\n\"kelimeler içeremez.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Karakter oluşturulamıyor.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Seviye:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Güç:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Büyü:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Çeviklik:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Yaşam:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Kayıtlı Oyun:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Kahraman Seç\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Yeni Kahraman\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Sil\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Çoklu Oyuncu Karakterleri\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Çoklu Oyuncu Karakterini Sil\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Tek Oyuncu Karakterini Sil\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Bu karakteri silmek istediğinden emin misin “{:s}”?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Tekli Oyuncu\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Çoklu Oyuncu\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Ayarlar\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Destek\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Emeği Geçenler\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Hellfire’dan Çık\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Diablodan Çık\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Shareware\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Client-Server (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Çevrimdışı\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Çoklu Oyuncu\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Gereksinimler:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"ağgeçidi gerektirmez\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Bağlantı Seç\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Ağ Geçidini Değiştir\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Tüm bilgisayarlar TCP destekleyen bir ağa bağlı olmalıdır.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Tüm bilgisayarlar internete bağlı olmalıdır.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Ağ bağlantısı olmadan kendi başına oyna.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Desteklenen Oyuncu: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Diablo Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Hellfire Shareware\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"Host farklı bir oyun oynuyor.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"Host farklı bir oyun modu ({:s}) oynuyor.\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"Sürümün ({:s}) hostun sürümüyle eşleşmiyor {:d}.{:d}.{:d}.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Açıklama:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Bir Eylem Seç\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Oyun Oluştur\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Açık Oyun Oluştur\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Oyuna Katıl\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Herkese Açık Oyunlar\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Yükleniyor…\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Yok”\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"İPTAL\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"İstediğin zorluk seviyesini seçerek yeni bir oyun oluştur.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"\"\n\"İstediğin zorluk seviyesini seçerek tüm oyuncuların katılabileceği yeni bir \"\n\"herkese açık oyun oluştur.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Devam eden bir oyuna girmek için Oyun ID’sini gir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Devam eden bir oyuna girmek için IP veya host adını gir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Devam eden bir herkese açık oyuna gir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Kabus\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Cehennem\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Zorluk: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Oyun Hızı: Normal\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Oyun Hızı: Hızlı\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Oyun Hızı: Daha Hızlı\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Oyun Hızı: En Hızlı\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Oyuncular: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Zorluk Seç\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Oyunlara Katıl: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Oyun ID’si Gir\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Adres Gir\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normal Zorluk\\n\"\n\"Yeni bir karakter Diabloyu yenme görevine buradan başlamalıdır.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Kabus Zorluğu\\n\"\n\"Labirentin güçlendirilmiş yaratıkları büyük mukavemet gösterir ve daha zor \"\n\"bir mücadele sunar. Sadece tecrübeli karakterler için tavsiye edilir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Cehennem Zorluğu\\n\"\n\"Yeraltında gizlenen canavarların en güçlü hali. Sadece en tecrübeli \"\n\"karakterler bu diyara girmeye teşebbüs etmelidir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Kabus zorluk seviyesindeki bir oyuna girebilmek için karakterin en az \"\n\"20.seviyede olmalıdır.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Cehennem zorluk seviyesindeki bir oyuna girebilmek için karakterin en az \"\n\"30.seviyede olmalıdır.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Oyun Hızı Seç\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Hızlı\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Daha Hızlı\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"En Hızlı\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Normal Oyun Hızı\\n\"\n\"Yeni bir karakter Diabloyu yenme görevine buradan başlamalıdır.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Hızlı Oyun Hızı\\n\"\n\"Yeraltında gizlenen canavarların en güçlü hali. Sadece en tecrübeli \"\n\"karakterler bu diyara girmeye teşebbüs etmelidir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Daha Hızlı Oyun Hızı\\n\"\n\"Zindandaki canavarların çoğu seni her zamankinden daha çabuk bulacak. Sadece \"\n\"tecrübeli bir şampiyon şansını bu hızda denemelidir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"En Hızlı Oyun Hızı\\n\"\n\"Yeraltının yardakçıları sana aceleyle saldırmak için bir an bile tereddüt \"\n\"etmeyecek. Sadece yıldırım hızındakiler böyle bir yarışa girmelidir.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Parola Gir\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Hellfire’a Gir\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Diabloya Geç\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Evet\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Hayır\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Değiştirmek için kontrolcü tuşlarına basın.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Atanan tuş:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Değiştirmek için bir tuşa basın.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Tuş atamasını kaldır\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Atanan tuş kombosu:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Atanan tuş kombosunu kaldır\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Önceki Menü\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"Diablo ve ek paketi Hellfire ile ilgili sohbet ettiğimiz sohbet kanalımıza \"\n\"davetlisiniz. Link: Discord.gg/devilutionx\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX, Diasurgical tarafından idare edilmektedir. Sorunlar ve buglar \"\n\"bu adresten bildirilebilir: https://github.com/diasurgical/devilutionX Size \"\n\"daha iyi yardımcı olabilmemiz için lütfen bildiriminize versiyon numarası, \"\n\"işletim sistemi ve sorunla alakalı ayrıntılı bilgileri ekleyin.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Feragatname:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionx Blizzard Entertainment veya GOG.com tarafından idare \"\n\"edilmemektedir veya desteklenmemektedir. DevilutionX  uyumluluğu veya kalite \"\n\"kontrolü sertifikasyonu Blizzard Entertainment veya GOG.com tarafından \"\n\"yapılmamıştır. DevlilutionX ile ilgili talepler Blizzard Entertainment veya \"\n\"GOG.com’a değil, Diasurgical’a iletilmelidir.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tBu port CC-BY 4.0 lisansı altında olan Twitmojiyi ve SIL Open Font License \"\n\"lisansı altındaki Charis SIL, New Athena Unicode, Unifont ve Notoyu \"\n\"kullanmaktadır. Ayrıca zlib-license lisansı altındaki SDLyi de \"\n\"kullanmaktadır. Ayrıntılı bilgiler için ReadMe dosyasını kontrol edin.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Tüm Hakları Saklıdır©1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Hata\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Hata oluştu: {:s}  {:d}.satır\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Veri Dosyası Hatası\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Ana veri arşivi açılamıyor ({:s}).\\n\"\n\"\\n\"\n\"Oyun klasörü içinde olduğuna emin olun.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Salt-okunur Dizin Hatası\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Bu konuma yazılamıyor:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Oyun: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Çevrimdışı Oyun\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Parola: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Herkese Açık Oyun\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Seviye: Yuva {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Seviye: Türbe {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Kasaba\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Seviye: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Karakter Bilgileri\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Görev Kayıtları\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Harita\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Ana Menü\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Envanter\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Büyü Kitabı\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Mesaj Gönder\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Mevcut Komutlar:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Komut \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" bilinmiyor.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Açıklama: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Parametreler: Ek parametreye gerek yok.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Parametreler: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Sadece çoklu oyuncuda desteklenen arenalar.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Hangi arenayı ziyaret etmek istiyorsun?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Geçersiz arena numarası. Geçerli numaralar:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"Bir arenaya girmek için, kasaba veya başka bir arenada olman gerekir.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"İncelemek sadece çoklu oyuncu modunda desteklenir.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Oyuncuları inceleme durduruldu.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Bu isimli bir oyuncu bulunmadı\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Oyuncu inceleniyor: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Yardım özetini veya belirli bir komutun yardımını yazdırır.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[komut]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Bir PvP Arenasına Gir.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<arena-numarası>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Arena İksirleri Verir.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<numara>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Başka bir oyuncunun istatistiklerini ve ekipmanlarını inceler.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<oyuncu adı>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Bu seviyenin seed bilgilerini gör.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Barışçıl Mod\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Savaş Modu\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Kısayol: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Geçerli büyüyü seç tuşu\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Kısayol: ’s’\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Yetenek\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s} Büyü\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"Büyü Seviyesi 0 - Kullanılamaz\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Büyü Seviyesi {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"{:s} Parşömeni\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Parşömeni\"\nmsgstr[1] \"{:d} Parşömenleri\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"{:s} Asası\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Yükü\"\nmsgstr[1] \"{:d} Yükleri\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} Altın\"\nmsgstr[1] \"{:s} Altın\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Gereksinimler sağlanmıyor\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Seviye: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Can {:d}/{:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"Kullanmak için sağ tıkla\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Seviyen Yükseldi\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"{:s} altının var. Ne kadarını ayırmak istiyorsun?\"\nmsgstr[1] \"{:s} altının var. Ne kadarını ayırmak istiyorsun?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Kasaba Portalı\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"{:s} tarafından\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Portal:\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Habis Sunak\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"seviye 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"{0} dosyasından veri yüklenemedi\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"Eksik dosya: {0}, lütfen dosya içeriğini kontrol et.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"Dosyan {0}, beklenen sütunlara sahip değil, lütfen belgelenmiş formata \"\n\"uyduğundan emin olun.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Sütün {4} satır {3} konumundaki {2} dosyasının {1} sütun başlıklı {0} değeri \"\n\"numerik değil\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Sütün {4} satır {3} konumundaki {2} dosyasının {1} sütun başlıklı {0} değeri \"\n\"kapsam dışı\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Sütün {4} satır {3} konumundaki {2} dosyasının {1} sütun başlıklı {0} değeri \"\n\"geçersiz\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Bu mesajı yazdır ve çıkış yap\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Sürümü yazdır ve çıkış yap\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Lütfen diabdat.mpq klasörünü belirt\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Kayıt dosyalarının klasörünü belirt\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Lütfen diablo.ini dosyasının konumunu belirt\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Dil kodunu belirt (örnek “en” veya “pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Başlangıç videolarını atla\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Saniye başına gösterilen kare\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Ayrıntılı kayıtları etkinleştir\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Bir demo dosyası kaydı al\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Bir demo dosyası oynat\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Demo oynatılırken tüm kare sınırlamalarını devredışı bırak\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Oyun Seçimi:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Shareware modunu zorla\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Diablo modunu zorla\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Hellfire modunu zorla\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Hellfire seçenekleri:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Hata Bildir: https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"Lütfen devilutionx.mpq ve fonts.mpq dosyalarını güncelleyin\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Arayüz kaynakları yüklenemedi.\\n\"\n\"\\n\"\n\"devilutionx.mpq adlı dosyanın oyun klasörü içinde ve güncel olduğuna emin \"\n\"olun.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Lütfen fonts.mpq dosyasını güncelleyin\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"— Ağ zamanaşımı —\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"— Oyuncular bekleniyor —\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Dükkanların içindeyken\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"yardım kullanılamaz\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Kemer Eşyası {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Kemerdeki eşyayı kullan.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Büyü Kısayolu {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Yetenek veya büyüler için kısayol tuşu.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Önceki hızlı büyü\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Önceki hızlı büyüyü seçer(döngü halinde).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Sıradaki hızlı büyü\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Sıradaki hızlı büyüyü seçer(döngü halinde).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Şifa iksiri kullan\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Kemerdeki şifa iksirilerini kullan.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Mana iksiri kullan\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Kemerdeki mana iksirlerini kullan.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Hızlı Büyü Kitabı\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Hızlı Büyü Kitabını aç.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Hızlı Kayıt\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Oyunu kaydeder.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Hızlı yükle\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Kaydedilmiş oyunu yükler.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Oyundan çık\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Oyunu kapatır.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Kahramanı durdur\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Yürümeyi durdurur ve beklenen aksiyonları iptal eder.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Eşya göster\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Yerdeki eşyaların isimlerini göster/gizle.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Eşya göstermeyi aktifleştir\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Yerdeki eşyaların isimlerini kalıcı olarak göster/gizle.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Haritayı aktifleştir\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Haritayı görünür hale getirir.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Harita tipi değiştirme döngüsü\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Opak -> Transparan -> Mini harita -> Hiç\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Envanter penceresini aç.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Karakter\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Karakter ekranını aç.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Görev kayıtları\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Görev kayıtlarını aç.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Büyü Kitabı\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Büyü Kitabı’nı aç.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Hızlı Mesaj {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Sohbette hızlı mesajı kullan.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Bilgi Ekranlarını Sakla\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Tün bilgi ekranlarını saklar.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Zum Yap\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Oyun ekranına zum yapar.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Oyunu Duraklat\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Oyunu duraklatır.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Oyunu Duraklat (Alternatif)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"Ekran parlaklığını yükseltir.\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Ekran parlaklığını düşürür.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"Ekran parlaklığını yükseltir.\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Ekran parlaklığını yükseltir.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Yardım\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Yardım ekranını aç.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Ekran Görüntüsü\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Ekran görüntüsünü kaydet.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Oyun Bilgisi\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Oyun bilgilerini gösterir.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Sohbet Kaydı\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Sohbet kaydını gösterir.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Envanteri Sırala\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Envanterdeki eşyaları sıraya diz.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Konsol\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Lua konsolunu açar.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Birincil eylem\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Canavarlara saldır, kasabalılarla konu, envanterdeki eşyaları kaldır ve \"\n\"yerleştir.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"İkincil eylem\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Sandıkları açar, kapılarla etkileşime geçer, eşyaları yerden al.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Büyü eylemi\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Aktif büyüyü yap.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Eylemi iptal et\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Menüleri kapar.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Yukarı hareket et\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Oyuncu karakterini yukarı hareket ettirir.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Aşağı hareket et\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Oyuncu karakterini aşağı hareket ettirir.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Sola hareket et\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Oyuncu karakterini sola hareket ettirir.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Sağa hareket et\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Oyuncu karakterini sağa hareket ettirir.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Sabit dur\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Oyuncuyu yerinde sabitlemek için basılı tut.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Sabit durmayı aktifleştir\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Oyuncu hareket edeceği zaman aktifleştir.\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"Harita\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"Aşağı hareket et\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"Sola hareket et\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"Oyuncu karakterini yukarı hareket ettirir.\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"Sağa hareket et\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Fareyi yukarı hareket ettir\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Yukarı fare hareketini simüle eder.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Fareyi aşağı hareket ettir\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Aşağı fare hareketini simüle eder.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Fareyi sola hareket ettir\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Sol fare hareketini simüle eder.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Fareyi sağa hareket ettir\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Sağ fare hareketini simüle eder.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Sol fare tıkı\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Sol fare tıkını simüle eder.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Sağ fare tıkı\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Sağ fare tıkını simüle eder.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Kontrolcü hızlı büyü menüsü\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Büyü kısayollarını belirlemek veya kullanmak için basılı tut.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Kontrolcü menü belirteci\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Kontrolcü menü belirtecine erişmek için basılı tut.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Oyun menüsünü aç\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Oyun menüsünü açar.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Oyun kaydedildi\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Demo sürümde çoklu oyuncu özellikleri yoktur\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Direct Sound Başarısız Oldu\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Shareware sürümünde mevcut değildir\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Kaydetmek için yeterince depolama yok\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Oyun kasabada duraklatılamaz\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Sabit bir sürücüye kopyalamak tavsiye edilir\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Çoklu oyuncu senkronizasyon sorunu\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Oyun çoklu oyuncu modunda duraklatılamaz\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Kaydediliyor…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Biri güçlenirken bazıları zayıfladı\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Yeni güç yıkım ile dövüldü\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Nadiren saldırmayı savunan kişiler\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Adaletin kılıcı çabuk ve keskindir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Ruh tetikteyken beden gelişir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Yeniden odaklanan mananın güçleri yenileniyor\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Zaman çeliğin gücünü eksiltemez\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Sihir her zaman göründüğü gibi değildir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Bir zamanlar açılmış olan şimdi kapandı\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Yoğunluk bilgeliğin pahasında gelir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Gizli güç yıkım getirir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Tutulamayan şeye zarar verilemez\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Kıpkızıl vs Gökmavi güneş gibi olur\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Benliğin bedeliyle gelen ilim ve bilgelik\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"İç ve ferahla\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Nereye gidersen git, ordasındır\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Enerji, bilgeliğin beleliyle gelir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Zenginlikler en beklenmedik zamanda bollaşır\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Sabır ödüllendirilir, açgözlülük düştüğünde\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Hayırsever bir yoldaş ile kutsandın!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"İnsanlığın elleri kaderin güdümündedir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Güç, ilahi inanç ile desteklenir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Hayatın özü onun içinden akar\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Bu yol yukardan bakıldığında görülebilir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Kurtuluş bilgeliğin bedeliyle gelir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Sebeplerin ışığında gizemler açığa çıktı\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Sonuncu olanlar birinci de olabilir\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Cömertlik kendi bereketiyle gelir\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Bunu kullanabilmek için en az 8.Seviye olmalısın.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Bunu kullanabilmek için en az 13.Seviye olmalısın.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Bunu kullanabilmek için en az 17.Seviye olmalısın.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Gizli ilim kazanıldı!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Seni öldürmeyen şey…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Bilgi güçtür.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Ver ki alasın.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Dokunarak bazı tecrübeler edinildi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Evin gibisi yoktur.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Ruhani enerji yenilendi.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Daha atik hissediyorsun.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Daha kuvvetli hissediyorsun.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Daha bilge hissediyorsun.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Yenilenmiş hissediyorsun.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"İradeyi kırabilecek olan.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Katedral\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Yeraltı Mezarları\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Mağaralar\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Yuva\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Türbe\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"Sv {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} Zorluk Seviyesi\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"Menüde\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"döngüde\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Bağlanılamıyor\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"hata: sunucudan 0 byte okundu\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq veya spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Bazı Hellfire MPQları eksik\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Tüm Hellfire MPQları bulunamadı.\\n\"\n\"Lütfen tüm hf*.mpq dosyalarını kopyalayın.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Çözünürlük\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Kasabada Koş\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Theo Görevi\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"İnek Görevi\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Otomatik Altın Topla\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Otomatik Eliksir Topla\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Otomatik Yağ Topla\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Kasabada Otomatik Topla\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Adria Mana Yeniler\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Silahları Otomatik Kuşan\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Zırhları Otomatik Kuşan\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Miğferleri Otomatik Kuşan\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Kalkanları Otomatik Kuşan\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Takıları Otomatik Kuşan\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Görevleri Rastgele Seç\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Eşya İsimlerini Göster\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Kemeri Otomatik Doldur\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Zararlı Mabetleri Devredışı Bırak\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Şifa İksiri Toplama\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Büyük Şifa İksiri Toplama\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Mana İksiri Toplama\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Büyük Mana İksiri Toplama\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Yenilenme İksiri Toplama\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Büyük Yenilenme İksiri Toplama\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Seçenekler\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Oyunu Kaydet\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"Ana Menü\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Oyundan Çık\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Gamma\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Hız\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Müzik Devredışı\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Ses\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Ses Devredışı\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Duraklat\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Klavye Kısayolları:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Yardım Ekranını Aç\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Ana Menüyü Göster\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Haritayı Göster\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Boşluk: Tüm bilgi ekranlarını gizle\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Hızlı Büyü Kitabını Aç\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Büyü Kitabını Aç\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Envanter Ekranını Aç\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Karakter Ekranını Aç\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Görev Kayıtlarını Aç\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Ekran Parlaklığını Düşür\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Ekran Parlaklığını Yükselt\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Zum Yapma Ekranı\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Haritayı Zumla\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Kemer Eşyalarını Kullan\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Yetenek veya Büyüler için Kısayollar Belirle\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Sol Fare Tuşu: Hareket etmeden saldır\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Sol Fare Tuşu (karakter ekranında): Tüm istatistik puanlarını ata\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Sol Fare Tuşu (envanterde): Eşyayı envanterden kemere gönder veya \"\n\"ekipman giy/çıkar\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Sol Fare Tuşu (kemerde): Eşyayı envantere gönder\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Hareket:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\"Hareket ederken mouse tuşunu basılı tutarsan, karakter hareket etmeye devam \"\n\"eder.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Dövüş:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Shift tuşuna basılı tutarken sol tıklamak karakterin hareket etmeden \"\n\"saldırmasını sağlar.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Harita:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Haritaya erişmek için Bilgi Bar’ındaki “HARİTA” tuşuna tıkla veya klavyedeki \"\n\"“Tab” tuşuna bas. + ve - tuşları haritada zum yapmak ve uzaklaştırmak için \"\n\"kullanılır. Harita yön tuşları ile hareket ettirilebilir.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Eşyaları Yerden Almak:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Parşömenler ve iksirler gibi küçük boyutlu kullanılabilir eşyalar otomatik \"\n\"olarak Bilgi Barının üstündeki kemere yerleştirilir. Bir eşya kemere \"\n\"yerleştirildiğinde, o kutunun içinde küçük bir rakam belirir. Eşyalar bağlı \"\n\"oldukları rakamlara basılarak veya üzerlerine sağ tıklanarak kullanılabilir.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Altın:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Belli bir miktarda altını ayırmak için envanterinizdeki altın öbeğine sağ \"\n\"tıklayabilirsin.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Yetenekler & Büyüler:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Yeteneklerine ve Büyülerine Bilgi Barındaki “Büyüler” tuşuna tıklayarak \"\n\"erişebilirsin. Daha önce öğrenilen ve asalar ile kullanılabilen büyüler \"\n\"burada listelenir. Gerçekleştirmek istediğin büyünün üstüne sol tıklayarak \"\n\"hazır duruma getirebilirsin. Hazır durumdaki büyüler oyun alanının üzerine \"\n\"sağ tıklanarak kullanılabilirler.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Hızlı Büyü Kitabının Büyüler için Kullanımı:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Hazır durumdaki büyünün üstüne sol tıklamak Büyü Kitabını açar, bu şekilde \"\n\"anlık kullanımlar için bir yetenek veya büyü seçilebilir. Hazır durumdaki \"\n\"büyüler oyun alanının üzerine sağ tıklanarak kolayca kullanılabilirler.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Geçerli büyüyü seç tuşuna Shift tuşuna basılı tutarak sol tıklanırsa, \"\n\"hazırdaki büyü temizlenir.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Büyü Kısayollarını Ayarlama:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Yeteneklerin, büyülerin veya parşömenlerin için dört adete kadar kısayol \"\n\"tuşu atayabilirsin. Yukardaki bölümde anlatıldığı gibi Hızlı Büyü Kitabını \"\n\"aç. Büyülerin üzerine fare imleci ile geldikten sonra F5, F6, F7 veya F8 \"\n\"tuşlarına basarak büyüleri ata.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Büyü Kitapları:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Bir büyünün kitabını birden fazla okuduğunda, o büyü hakkındaki bilgin \"\n\"artar. Bu şekilde büyünü daha etkili şekilde kullanabilirsin.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Shareware Hellfire Yardım\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Hellfire Yardım\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Shareware Diablo Yardım\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Diablo Yardım\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Sonlandırmak için ESC tuşuna bas veya yön tuşlarıyla hareket ettir.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Ana pencere oluşturulamıyor\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Eşya için yeterli yer yok\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"İsabetlilik Yağı\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Ustalık Yağı\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Keskinlik Yağı\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Ölüm Yağı\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Yetenek Yağı\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Demirci Yağı\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Dayanıklılık Yağı\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Kalıcılık Yağı\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Sertleştirme Yağı\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Sızdırmazlık Yağı\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0}: {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1}: {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{1}: {0} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0}: {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"bir silahın\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"vuruş şansını artırır\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"bir silahın vuruş şansını\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"büyük ölçüde artırır\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"hasar potansiyelini artırır\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"bir silahın hasar potansiyelini\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"büyük ölçüde artırır - yaylar hariç\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"zırhların ve silahların\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"nitelik gereksinimi düşürür\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"bir eşyanın sağlamlığının\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"%20 kadarını tamir eder\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"bir eşyanın anlık ve maksimum\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"sağlamlık değerlerini artırır\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"eşyayı yok edilemez yapar\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"zırh ve kalkanların\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"zırh düzeyini artırır\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"zırh ve kalkanların\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"zırh düzeyini büyük ölçüde artırır\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"ateş tuzağı kurar\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"yıldırım tuzağı kurar\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"taşlaştırma tuzağı kurar\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"tüm canı yenile\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"tüm manayı yenile\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"bir miktar manayı yenile\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"tüm manayı yenile\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"güç niteliğini artır\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"büyü niteliğini artır\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"çeviklik niteliğini artır\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"yaşam niteliğini artır\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"bir miktar can ve mana yenile\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"tüm can ve manayı yenile\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(sadece arenalarda çalışır)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Görmek için sağ tıkla\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Kullanmak için sağ tıkla\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Okumak için sağ tıkla, sonra\\n\"\n\"hedefe sol tıkla\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Okumak için sağ tıkla\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Görmek için aktifleştir\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Kullanmak için envanteri aç\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Kullanmak için aktifleştir\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Büyü Kitabı’ndan seç, sonra\\n\"\n\"okumak için büyü yap\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Okumak için aktifleştir\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"Görmek için: {}\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"Kullanmak için: {}\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Büyü Kitabı’ndan seç, sonra\\n\"\n\"okumak için {}\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"Okumak için: {}\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Seviye: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Altın kapasitesini iki katına çıkarır\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Gerekli:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Güç\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Büyü\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Çev\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Büyü Kitabı: {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Kulak, Sahibi: {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"vuruş şansı: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% hasar\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"vuruş şansı: {:+d}%, {:+d}% hasar\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% zırh\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"zırh düzeyi: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Ateş direnci: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Ateş Direnci: {:+d}% MAKS\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Yıldırım Direnci: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Yıldırım Direnci: {:+d}% MAKS\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Büyü Direnci: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Büyü Direnci: {:+d}% MAKS\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Tüm Direnç: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Tüm Direnç: {:+d}% MAKS\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"büyülerin seviyesi {:d} artar\"\nmsgstr[1] \"büyülerin seviyesi {:d} artar\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"büyülerin seviyesi {:d} azalır\"\nmsgstr[1] \"büyülerin seviyesi {:d} azalır\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"büyü seviyeleri değişmez (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Ekstra yük sayısı\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} yük\"\nmsgstr[1] \"{:d} {:s} yük\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Ateş hasarı {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Ateş hasarı: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Yıldırım hasarı: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Yıldırım hasarı: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} güç\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} büyü\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} Çeviklik\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} Yaşam\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} tüm nitelikler\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"düşmanlardan {:+d} hasar al\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Can: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Mana: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"yüksek dayanıklılık\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"azaltılmış dayanıklılık\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"yok edilemez\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"aydınlatma çapı +%{:d}\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"aydınlatma çapı -%{:d}\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"atış başına çoklu ok fırlatma\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"ateş okları hasarı: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"ateş okları hasarı: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"yıldırım okları hasarı {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"yıldırım okları hasarı {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"ateştopu hasarı: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"ateştopu hasarı: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"saldırgan 1-3 hasar alır\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"kullanıcı tüm mana’sını kayberder\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"tuzak hasarının yarısını soğurur\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"hedefi geri iter\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"iblislere karşı +200% hasar\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Tüm dirençler 0’a eşitlenir\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"vuruşlar 3% mana çalar\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"vuruşlar 5% mana çalar\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"vuruşlar 3% can çalar\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"vuruşlar 5% can çalar\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"hedefin zırhını deler\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"çabuk saldırı\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"hızlı saldırı\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"daha hızlı saldırı\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"en hızlı saldırı\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Tanımlanamayan yetenek (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"hızlı toparlanma\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"daha hızlı toparlanma\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"en hızlı toparlanma\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"hızlı blok\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"{:d} hasar puanı ekler\"\nmsgstr[1] \"{:d} hasar puanı ekler\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"ateşlediği oklar rastgele hızda gider\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"olağandışı eşya hasarı\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"azaltılmış sağlamlık\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"tek-elli kılıç\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"sürekli bir şekilde can kaybet\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"can çalma\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"güç gereksinimi yok\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"yıldırım hasarı: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"yıldırım hasarı: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"yüklü akımlı vuruşlar\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"tesadüfen hasar üçe katlanır\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"azalan {:+d}% hasar\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"canavarlara 2x sana 1x hasar\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Rastgele 0 - 600% hasar\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"düşük day, {:+d}% hasar\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"iblislere karşı ekstra ZD\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"yaşayan ölülere karşı ekstra ZD\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"Mananın %50’si Cana aktarılır\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"Canın 40%’ı Manaya aktarılır\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"hasar: {:d}  Yok edilemez\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"hasar: {:d}  Sağ: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"hasar: {:d}-{:d}  Yok edilemez\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"hasar: {:d}-{:d}  Sağ: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"zırh: {:d}  Yok edilemez\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"zırh: {:d}  Sağ: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Yükler: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"eşsiz eşya\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Teşhis Edilmemiş\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"İskelet Kralın İni\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Kemikler Odası\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Labirent\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Zehirlenmiş Su Kaynağı\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Başpiskopos Lazarusun İni\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Kilise Arenası\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Cehennem Arenası\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Yaşam Döngüsü Arenası\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Zindana İn\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Yeraltı Mezarlarına İn\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Mağaralara İn\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Cehenneme İn\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Kovana İn\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Türbeye İn\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"{:d}.Seviyeye Çık\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Kasabaya Çık\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"{:d}.Seviyeye İn\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Diabloya İn\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"{:d}.Yuva Seviyesine Çık\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"{:d}.Türbe Seviyesine Çık\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Dünya’nın Köşetaşı\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"{:d}.Türbe Seviyesine İn\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"{:d}.Seviyeye Geri Dön\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Kayıt dosyası arşivi açılamıyor\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Geçersiz kayıt dosyası\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Oyuncu bir Hellfire özel seviyesinde\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Geçersiz oyun durumu\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Anamenü gösterilemiyor\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Hayvan\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"İblis\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Yaşayan Ölü\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Tip: {:s}  Katletme: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Toplam katletme: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Can: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Büyü direnci yok\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Dirençli:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Büyü\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Ateş\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Şimşek\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Bağışıklılık:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Tip: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Direnç Yok\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Bağışıklık Yok\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Bazı Büyülere Dirençli\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Bazı Büyülere Bağışıklı\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Yazmak için arşivi açma işlemi başarısız.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} kural dışı bir büyü yaptı.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} kural dışı bir büyü yaptı.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Oyuncu ‘{:s}’ (seviye {:d}) oyuna giriş yaptı\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Oyun sonlandı\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Seviye verisi alınamıyor\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Oyuncu ‘{:s}’ oyunudan ayrıldı\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Oyuncu ‘{:s}’ Diablo’yu öldürerek oyundan ayrıldı!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Oyuncu ‘{:s}’ zaman aşımından dolayı oyundan düştü\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Oyuncu ‘{:s}’ (seviye {:d}) zaten oyunda\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Gizemli\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Gizli\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Kasvetli\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Garip\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Sihirli\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Taş\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Dini\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Efsunlu\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Mucizevi\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Büyüleyici\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Şifreli\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Tekinsiz\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Uğursuz\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"İlahi\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Kutsal\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Kutsal\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Ruhani\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Ürkünç\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Terkedilmiş\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Ürpertici\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Sessiz\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Münzevi\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Şatafatlı\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Işıldayan\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Lekelenmiş\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Yağlı\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Parlayan\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Dilenen\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Kıvılcımlı\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Yanardöner\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Güneşli\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Lanetli\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Büyük Çatışma\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Günahın Kefareti Savaştır\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Horadrim’in Öyküsü\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Kara Sürgün\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Günah Savaşı\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Üçlü’nün Bağlanması\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Öte Alemler\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Üç’ün Öyküsü\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Kara Kral\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Günce: Büyülenme\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Günce: Karşılaşma\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Günce: Tirat\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Günce: O Güçleniyor\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Günce: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Günce: Son\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Bir Büyü Kitabı\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Çarmıha Gerilmiş İskelet\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Kol\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Açık Kapı\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Kapalı Kapı\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Bloke Kapı\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Antik Kitap\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Alçaklık Kitabı\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Kurukafa Kolu\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Efsanevi Kitap\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Küçük Sandık\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Sandık\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Büyük Sandık\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Lahit\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Kitap Rafı\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Kitaplık\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Fıçı\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Kapsül\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Kavanoz\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Mabet\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"İskelet Kitabı\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Kütüphane Kitabı\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Kan Çeşmesi\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Kafası Kesilmiş Vücut\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Körler Kitabı\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Kan Kitabı\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Saflaştıran Kaynak\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Zırh\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Silah Askılığı\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Keçi Mabedi\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Kazan\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Bulanık Havuz\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Gözyaşı Çeşmesi\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Çelik Kitap\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"Kan Kaidesi\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Mantar Yığını\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Pis Ayaklık\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Katledilmiş Kahraman\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"Tuzağa Düşmüş {:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (devredışı)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"AÇIK\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"KAPALI\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Oyun Modu\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"Oynanış Ayarları\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Diablo veya Hellfire oyna.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Shareware’a sınırla\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Oyunu demo sürümle uyumlu hale getirir. Tam sürüme sahip olmayan \"\n\"arkadaşlarla çoklu oyunculu oyunları aktifleştirir.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Başlatma\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Başlatma Ayarları\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Tanıtım\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Başlangıç sinematiği gösterilir.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Açılış\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Açılış ekranı görünümü.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Logo ve Başlık Ekranı\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Başlık Ekranı\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Diabloya özel Ayarlar\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Hellfirea özel Ayarlar\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Ses\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Ses Ayarları\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Yürüme Sesi\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"Oyuncu yürürken etrafına ses yayar.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Otomatik Kuşanma Sesi\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Yerden alınan eşyaları otomatik şekilde kuşanmak bir ses çıkarır.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Eşya Alma Sesi\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Eşyaları yerden almak bir ses çıkarır.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Ses Örnekleme Oranı\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Çıkış ses frekansı (Hz).\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Kanallar\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Çıkış kanallarının sayısı.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Tampon Boyutu\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Tampon boyutu (kanal başına kare sayısı).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Yeniden Örneklendirme Kalitesi\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"\"\n\"Yeniden örneklendiricinin kalitesi, en düşük 0’dan en yüksek 10’a kadar.\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Oyunun çözünürlüğünü ve görüş alanınızı değiştirir. Not: Bu, Çözünürlük \"\n\"Yükseltme, Tamsayı Oranlama veya Ekrana Sığdır kullanırken ekran \"\n\"çözünürlüğünden ayrışır.\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Yeniden Örnekleyici\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Ses için yeniden örnekleyici\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Aygıt\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Ses aygıtı\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Grafikler\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Grafik Ayarları\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Tam Ekran\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Oyunu pencere görünümünde veya tam ekranda göster.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Ekrana Sığdır\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Oyun penceresini halihazırdaki masaüstü ekran oranı ve çözünürlüğüne \"\n\"otomatik olarak ayarlar.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Çözünürlük Yükseltme\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Oyun çözünürlüğünden monitörünüzün çözünürlüğüne görüntü ölçeklendirmeyi \"\n\"etkinleştirir. Monitör çözünürlüğünü değiştirmeyi engeller ve pencere \"\n\"boyutunu değiştirmeye izin verir.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Çözünürlük Yükseltme Kalitesi\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\"Çözünürlük Yükseltme kullanırken görüntü çıktısı için opsiyonel filtreleri \"\n\"etkinleştirir.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"En Yakın Piksel\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Bilineer\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Anizotropik\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Tamsayı Ölçeklendirme\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Görüntüyü tam sayı piksel oranlarını kullanarak ölçeklendirir.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Dikey Senkronizasyon\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Aktifleştirildiğinde zumlar.\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" Şimşek\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Renk Döngüsü\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"Renk döngüsü efekti su, lav ve asit animasyonları için kullanılır.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Alternatif Yuva Stili\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"Hellfire’ın Yuva bölümü için alternatif bir renk paleti kullanır.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Donanım İmleci\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Donanım imlecini kullan\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Eşyalar İçin Donanım İmleci\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Eşyalar için donanım imlecini kullan.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Donanım İmleci Maksimum Boyutu\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Donanım imleci için maksimum genişlik / yükseklik değerleri. Çok büyük \"\n\"imleçler yazılımsal imlece düşebilir.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"FPS Göster\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"FPS değerini ekranın sol üst köşesinde gösterir.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Oynanış\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Oynanış Ayarları\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Diablo ve Hellfire için hızlı koşmayı aktifleştirir. Bu özellik Hellfire ile \"\n\"gelmiştir.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Giriş Yakala\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Aktifleştirildiğinde fare imleci oyun penceresine kitlenir.\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Pencere Değişiminde Oyunu Duraklat\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"Aktifleştirildiğinde, oyun penceresi odaktan çıkarsa oyunu duraklatır.\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Küçük Kız görevini aktifleştir.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\"İnek görevini aktifleştir. Çiftçi Lester ile Zırdeli karakterlerini \"\n\"değiştirir.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Dost Ateşi\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"Barışçıl mod açık olsa bile oyuncular arası ok/büyü hasarına izin ver.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Çoklu Oyuncuda görevleri aktifleştir\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Tüm tekli oyuncu görevlerini çoklu oyuncu oyunlarında aktifleştirir.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Ozanı Aktifleştir\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Ozan karakterini kahraman seçim menüsünde aktifleştirir.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Barbarı Aktifleştir\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Barbar karakterini kahraman seçim menüsünde aktifleştirir.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Tecrübe Barı\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\"Tecrübe ilerlemesini gösteren bir bar ekranın en altındaki arayüze eklenir.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Mağazalarda Eşya Resimlerini Göster\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\"Mağaza menülerinde eşyaların resimleri, eşya açıklamalarının solunda \"\n\"gösterilir.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Can Değerlerini Göster\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Anlık ve maksimum can değerlerini can küresinin üzerinde gösterir.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Mana Değerlerini Göster\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Anlık ve maksimum mana değerlerini mana küresinin üzerinde gösterir.\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"Karakter Bilgileri\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Düşman Can Barı\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Düşman can barı ekranın üstünde gösterilir.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"Altınlar oyuncu yakınken otomatik olarak toplanır.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"Eliksirler oyuncu yakınken otomatik olarak toplanır.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Yağlar oyuncu yakınken otomatik olarak toplanır.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Kasabadayken eşyalar otomatik olarak toplanır.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Adria, dükkanını ziyaret ettiğinde tüm mananı yeniler.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Silahlar eğer uygunsa yerden alındıklarında veya satın alındıklarında \"\n\"otomatik olarak kuşanılırlar.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Zırhlar eğer uygunsa yerden alındıklarında veya satın alındıklarında \"\n\"otomatik olarak kuşanılırlar.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Miğferler eğer uygunsa yerden alındıklarında veya satın alındıklarında \"\n\"otomatik olarak kuşanılırlar.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Kalkanlar eğer uygunsa yerden alındıklarında veya satın alındıklarında \"\n\"otomatik olarak kuşanılırlar.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Takılar eğer uygunsa yerden alındıklarında veya satın alındıklarında \"\n\"otomatik olarak kuşanılırlar.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Yeni oyunlar için uygun görevler rastgele seçilir.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Canavar Tipini Göster\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Bir canavarın üzerinde fare imleci ile gezinmek canavarın tipini Bilgi \"\n\"Barında gösterir.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Aktifleştirildiğinde yerdeki eşyaların isimlerini gösterir.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Kemerdeki eşyalar kullanıldığında boşalan yer aynı eşya(envanterde \"\n\"bulunuyorsa) ile doldurulur.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Aktifleştirildiğinde Kazanlar, Büyüleyici Mabetler, Keçi Mabetleri, \"\n\"Şatafatlı Mabetler ve Kutsal Mabetler devredışı bırakılır ve tıklanamaz olur.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Hızlı Büyü\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\"Büyü kısayol tuşlara basmak büyüleri hemen aktifleştirir, sağ tıklamana \"\n\"gerek kalmaz.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Otomatik olarak toplanacak Şifa İksiri sayısı.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Otomatik olarak toplanacak Büyük Şifa İksiri sayısı.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Otomatik olarak toplanacak Mana İksiri sayısı.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Otomatik olarak toplanacak Büyük Mana İksiri sayısı.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Otomatik olarak toplanacak Yenilenme İksiri sayısı.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Otomatik olarak toplanacak Büyük Yenilenme İksiri sayısı.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Ondalık sayıları aktifleştir\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\"Tecrübe Puanı kazanırken, hasar vururken ondalık sayıları aktifleştirir.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Kapalı\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Rastgele Açılar\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Sadece Dikey\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Kontrolcü\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Kontrolcü Ayarları\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Ağ\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Ağ Ayarları\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Sohbet\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Sohbet Ayarları\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Dil\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Oyunda kullanılacak dili seç.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Dil Ayarları\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Tuş Atama\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Tuş Atama Ayarları\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Kontrolcü Tuş Atama\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Kontrolcü Tuş Atama Ayarları\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"Ayarlar\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Seviye\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Tecrübe\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Sıradaki seviye\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"Taban\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Şimdi\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Güç\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Büyü\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Çeviklik\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Yaşam\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Boştaki Puanlar\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Altın\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Zırh Sınıfı\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"vuruş şansını artırır\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Hasar\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Can\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Büyü direnci\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Ateş direnci\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Yıldırım direnci\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"karakter\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"görevler\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"harita\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"menü\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"envanter\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"büyüler\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"ses\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"sessiz\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Kullanılamaz\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Hasar: 1/3 hedef canı\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"İyileştirir: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Hasar: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Yetenek\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Asa ({:d} yük)\"\nmsgstr[1] \"Asa ({:d} yük)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Seviye {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Mana: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Büyü\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Sadece yaşayan ölülere hasar verir\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Parşömen\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Asa\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Büyü Kısayolu {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Arşiv açılamadı\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Karakter yüklenemedi\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (Sv {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Sohbet Geçmişi (Mesajlar: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} altın\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Ne kadar altın çekmek istiyorsun?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Seviye {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Tecrübe: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Maksimum Seviye\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Sonraki Seviye: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} TP {:d}.Seviyeye kalan\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Kral Leoricin Türbesi\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Kemikler Odası\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Karanlık Geçit\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Habis Sunak\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"{:s} Yolu\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Yardıma ihtiyacım var! Gel buraya!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"Beni takip et.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Senin için bir şeyim var.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"Şimdi GEBER!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Kendini iyileştir!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Dikkatli ol!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Teşekkürler.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Geri çekil!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Üzgünüm.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Bekliyorum.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Griswold\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Pepin\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Ogden\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Cain\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Farnham\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Adria\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Gillian\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Wirt\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Geri\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \", \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Hasar: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Zırh: {:d} \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Sağ: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Yok edilemez\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Hoşgeldin!\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Demircinin dükkanı\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Ne yapmak istersin?\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Griswold ile konuş\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Basit eşyalar satın al\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Kaliteli eşyalar satın al\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Eşya sat\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Eşya tamir et\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Dükkandan ayrıl\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"Elimdeki satılık eşyalar:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Elimdeki kaliteli satılık eşyalar:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"İstediğim hiçbir şey yok.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Hangi eşya satılık?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Tamir edilecek hiçbir şeyin yok.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Hangi eşyayı tamir edeyim?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Cadı’nın kulübesi\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Adria ile konuş\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Eşya satın al\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Asa yüklerini yenile\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Kulübeden ayrıl\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Yükleri yenilenecek hiçbir şeyin yok.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Hangi eşyanın yüklerini yenileyeyim?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"Yeterli miktarda altının yok\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"Envanterinde yeterince boş yer yok\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Anlaştık mı?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Bu eşyayı teşhis etmek istediğine emin misin?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Bu eşyayı satın almak istediğine emin misin?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Bu eşyayı yeniden yüklemek istediğine emin misin?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Bu eşyayı satmak istediğine emin misin?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Bu eşyayı tamir etmek istediğine emin misin?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Wirt, Tahta Bacaklı Çocuk\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Wirt ile konuş\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"Elimde satılık bir şey var,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"ama sadece bakmak için bile\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"50 altın vermen gerekiyor. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Elinde ne var?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Elveda\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"Bu eşyayı satıyorum:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Ayrıl\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Şifacı’nın evi\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Pepin ile konuş\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Şifacının evinden ayrıl\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Köyün Yaşlısı\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Cain ile konuş\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Bir eşya teşhis et\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Teşhis edecek hiçbir şeyin yok.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Hangi eşyayı teşhis edeyim?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Bu eşya:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Tamam\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"{:s} ile konuş\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"{:s} ile konuşmak\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"bu Shareware\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"sürümde\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"mevcut değil\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Dedikodu\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Gündoğan\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Ogden ile Konuş\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Hanı terket\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Gillian ile Konuş\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Depoyu Aç\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"Sarhoş Farnham\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Farnham ile Konuş\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Elveda\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Altının: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Katledilmiş Köylü\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Demirci Griswold\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Şifacı Pepin\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Yaralı Köylü\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Hancı Ogden\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Yaşlı Cain\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Cadı Adria\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Garson Gillian\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"İnek\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Çiftçi Lester\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Celia\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Zırdeli\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Savaşçı\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Haydut\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Büyücü\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Keşiş\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Ozan\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Barbar\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Zombi\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Gulyabani\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Çürüyen Karkas\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Kara Ölüm\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Düşkün\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Deşici\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Şeytan Soyu\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Kara İskelet\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"İskelet\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Baltalı Ceset\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Yanan Ölü\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Dehşet\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Leşçil\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Veba Yiyen\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Gölge Yaratığı\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Kemik Yaran\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Yaylı Ceset\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Yüzbaşı İskelet\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Yüzbaşı Ceset\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Yüzbaşı Yanan Ölü\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Yüzbaşı Dehşet\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Görünmez Lord\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Saklı\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"İzsüren\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Görünmeyen\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"İlüzyon Ören\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Satir Lordu\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Et Klanı\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Taş Klanı\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Ateş Klanı\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Gece Klanı\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Zebani\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Kırpık\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Kasvet\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Cinli\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Asit Yaratığı\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Zehir Tüküren\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Çukur Yaratığı\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Lav Çene\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"İskelet Kral\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"Kasap\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Reis\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Çamur Adam\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Kurbağa İblis\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Yüzülmüş\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Solucan\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Mağara Sülüğü\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"İblis Solucan\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Yutucu\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Magma İblisi\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Kan Taşı\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Cehennem Taşı\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Lav Lordu\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Boynuzlu İblis\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Çamur Koşan\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Buzul Koşan\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Obsidiyen Lord\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"yaşlıkemik\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Kızıl Ölüm\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Hortlak İblisi\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Hortlak Balrog\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Yakıcı\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Alev Lordu\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Hüküm Alevi\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Cehennem Yakan\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Kızıl Fırtına\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Fırtına Binici\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Fırtına Lordu\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Girdap\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Yabani Şeytan Soyu\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Kanatlı İblis\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Gargoyl\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Kanlı Pençe\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Ölüm Kanat\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Katleden\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Muhafız\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Girdap Lordu\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Balrog\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Mağara Engereği\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Ateş Ejderi\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Altın Ejder\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Mavi Ejder\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Kara Şövalye\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Hüküm Muhafızı\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Çelik Lord\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Kan Şövalyesi\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Paramparça\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Delinmiş\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Acı Ustası\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Gerçeklik Ören\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Succubus\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Kar Cadısı\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Cehennem Tohumu\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Ruh Yakan\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Rehber\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Yargıç\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Kabalist\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Yandaş\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Karanlık Lord\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Baş Hortlak Malignus\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Zayıf Gharbad\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Deli Zhar\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Akarsümük\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Başpiskopos Lazarus\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Kızıl Hüzün\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Kara Yeşim\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Kan Beyi\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Öğüren İblis\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Kirletici\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Kemikkafa Keskinbalta\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Kesici Bıçakderi\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Ruhirini\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Kirli Kusmukfare\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Kemiksöken\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Aç Çürükziyafet\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Hızlı Karındeşen\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Kırıkkafa Patlakkalkan\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Bongo\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Çürükkatliam\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Gölgeısırığı\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Ölügöz\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Ölü Deligöz\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"Keçiemen\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Ateşkafa\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Çarpıkkafa\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Vahşetlidil\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Nabızsüren\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Aybüken\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Gazapkuzgunu\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Omurgayiyen\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Yanan Karakül\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Gölgekargası\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Zayıf Yanartaş\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Çukur Efendisi Safraköpüğü\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Kanderili Karayay\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Piskanat\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Gölgeiçen\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Pusgeçen\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Ölümtükürüğü\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Kanoluğu\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Ölümgölgesi Ettokmağı\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Deli Savaşkurdu\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Pütürlü Camkafa\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Küfalevi\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Soğuk Gecekanat\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Vahşettaşı\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Bronzyumruk Ateştaşı\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Lanetli Gazapateşi\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Gaddar Ateşyarası\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Çamur Baron\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Küfboynuz Çelikgürz\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Kaosuluyan\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Çürüyen Hükümsırıtışı\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Deliyakan\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Hortlak Kemiktestere\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Omurgasız\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"İbliskafa Keskinkemik\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Kırıkfırtına\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Fırtınacelladı\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Salyasümük\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Alevin Altınküfü\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Karafırtına\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Salgıngazap\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Deriyüzen\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Maviboynuz\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Çarpıkateş Şeytantohumu\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Kulediş\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"İltihapkafa\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Eğri Aslankafa\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Karadil\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Rezildokunuş\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Engerekalevi\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Dişderi\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Habis Cadıalevi\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Karakurukafa\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Ruhkesiği\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Rüzgartohumu\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Çukurun Efendisi\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Pasören\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Gölge Uluyanöfke\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Hükümbulutu\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Kanlıay Ruhateşi\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Cadıayı\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Vahşetşöleni\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Katil Bozsavaş\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Korkuyargıcı\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Cadı Yıldızgöz\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Avcı Çelikkafa\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Sir Gorash\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Vezir\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Zampir\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Kanasusamış\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Ağdulu\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Etdansözü\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Gaddardiken\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Hükümkilidi\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Kısa Kılıç\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Kalkancık\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Sopa\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Kısa Yay\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Kısa Mana Asası\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Satır\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Yaşayan Ölü Tacı\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Cennet Halesi\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Sihirli Kaya\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Mercek Muskası\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Doğruluk Yüzüğü\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Han Tabelası\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Damalı Sorguç\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Çelik Duvak\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Altın Eliksir\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Gazap Örsü\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Siyah Mantar\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Beyin\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Mantar Kitabı\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Tayf Eliksiri\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Kan Taşı\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Katedral Haritası\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Şifa İksiri\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Mana İksiri\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Teşhis Etme Parşömeni\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Kasaba Portalı Parşömeni\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Arkaine’in Yiğitliği\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Büyük Şifa İksiri\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Büyük Mana İksiri\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Griswold’un Yalmanı\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Sığır Plaka\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Lazarusun Asası\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Diriltme Parşömeni\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Kısa Asa\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Kılıç\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Hançer\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Rün Bombası\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Theodore\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Zer Muska\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Yırtılmış Not 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Yırtılmış Not 3\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Yırtılmış Not 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Birleştirilmiş Not\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Kahverengi Elbise\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Gri Elbise\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Başlık\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Bere\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Miğfer\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Tam Miğfer\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Taç\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Büyük Miğfer\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Pelerin\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Paçavra\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Örtü\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Cüppe\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Kapitone Zırh\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Deri Zırhı\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Sert Deri Zırh\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Kakmalı Deri Zırh\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Halkalı Örgü Zırh\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Örgü Zırh\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Zincirli Örgü Zırh\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Pul Örgü Zırh\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Göğüs Plakası\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Plaka\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Levha Örgü Zırh\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Plaka Örgü Zırh\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Geniş Plaka\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Gotik Plaka\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Tam Plaka Örgü Zırh\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Kalkan\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Küçük Kalkan\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Büyük Kalkan\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Uçurtma Kalkan\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Kule Kalkan\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Gotik Kalkan\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Yenilenme İksiri\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Büyük Yenilenme İksiri\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Yağ\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Güç Eliksiri\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Büyü Eliksiri\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Çeviklik Eliksiri\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Yaşam Eliksiri\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Şifa Parşömeni\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Bulma Parşömeni\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Yıldırım Parşömeni\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Ateş Duvarı Parşömeni\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Cehennem Ateşi Parşömeni\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Flaş Parşömeni\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Ötegörü Parşömeni\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Sıçrama Parşömeni\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Mana Kalkanı Parşömeni\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Alev Dalgası Parşömeni\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Ateştopu Parşömeni\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Taş Laneti Parşömeni\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Yıldırım Zinciri Parşömeni\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Muhafız Parşömeni\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Parlama Parşömeni\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Golem Parşömeni\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Işınlanma Parşömeni\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Kıyamet Parşömeni\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Şemşir\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Pala\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Karabela\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Yatağan\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Kama\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Uzun Kılıç\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Geniş Kılıç\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Büyük Kılıç\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Çift-Elli Kılıç\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Dev Kılıç\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Küçük Balta\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Balta\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Büyük Balta\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Geniş Balta\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Savaş Baltası\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Dev Balta\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Gürz\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Seher Yıldızı\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Savaş Çekici\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Çekiç\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Çivili Sopa\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Harmandöveni\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Tokmak\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Yay\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Avcı Yayı\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Uzun Yay\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Kompozit Yay\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Kısa Muharebe Yayı\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Uzun Muharebe Yayı\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Kısa Savaş Yayı\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Uzun Savaş Yayı\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Uzun Asa\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Kompozit Asa\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Dövüş Asası\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Savaş Asası\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Yüzük\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Muska\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Ateş Rünü\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Rün\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Yıldırım Rünü\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Büyük Ateş Rünü\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Büyük Yıldırım Rünü\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Taş Rünü\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Kısa Yüklü Akım Asası\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Arena İksiri\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Kasapın Satırı\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"Işıkkılıcı\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Yarık Yayı\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"İğneleyici\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Semavi Yay\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Ölümcül Avcı\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Ölülerin Yayı\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Ölülerin Yayı\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Alevciriti\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Etdelen\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Rüzgargücü\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Kartalboynuzu\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Gonnagalın Kaması\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Müdafi\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Grifonun Pençesi\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Kara Jilet\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Şişkin Ay\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Buz Sapı\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Cellatın Kılıcı\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Kemik Testeresi\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Gölgeşahini\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Büyücüdikeni\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Işıkkılıcı\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Şahinin Pençesi\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Cehennem Ateşi\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Kıyametgetiren\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Boz\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Büyük Baba\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Doğrayıcı\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Keskin Gaga\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Kankatili\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Semavi Balta\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Aşağılık Balta\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Taşkesen\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Aguinaranın Nacağı\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Cehennemkatili\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Messerschmidtin İstilası\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Çatlakpası\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Jholmün Çekici\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Criverb’in Çomağı\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"İlahi Yıldız\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Baranar’ın Yıldızı\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Budaklı Kök\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Kafa Patlatan\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Schaefer’ın Çekici\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Rüyaperçini\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Gölgeler Asası\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Tutuşturan\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Fırtınabaşı\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Parıltışarkısı\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Fırtınaçağrısı\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Koruyucu\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Najın Muamması\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Akılçığlığı\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Onanın Çubuğu\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Ruhların Miğferi\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Düşünen Başlık\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Reisin Miğferi\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Soytarının Şapkası\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Gotterdamerung\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Kraliyet Tacı\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Ruhların Parçalanmış Etleri\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Gladyatör Celladı\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Gökkuşağı Pelerini\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Autun Derisi\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Bilgelik Örtüsü\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Işıltılı Zırh\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Leşçil Kabuğu\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Geceparçası\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Najın Hafif Plakası\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"İblisdikeni Ceket\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Yansıtıcı\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Yarıkkafa Kalkanı\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Ejderha Gediği\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Karameşe Kalkanı\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Mukaddes Müdafi\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Fırtınakalkanı\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Devedikeni\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Reghanın Yüzüğü\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Kanatan\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Darlayan Yüzük\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Nişan Yüzüğü\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Teneke\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Pirinç\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Bronz\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Demir\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Çelik\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Gümüş\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Platin\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Mithril\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Meteor\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Tuhaf\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Kullanışsız\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Bükülmüş\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Zayıf\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Sivriltilmiş\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Ölümcül\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Ağır\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Kötücül\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Ölümcül\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Muazzam\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Yabani\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Zalim\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Acımasız\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Beceriksiz\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Körelmiş\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Keskin\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Kaliteli\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Savaşçı\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Asker\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Lord\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Şövalyenin\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Ustanın\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Şampiyon\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Kral\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Savunmasız\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Paslı\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Güçlü\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Büyük\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Yiğit\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Muzaffer\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Kutsanmış\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Aziz\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Harika\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Tanrısal\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Kırmızı\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Kızıl\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Lâl\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Yakut\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Mavi\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Gökmavi\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Lapis\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Kobalt\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Safir\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Beyaz\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"İnci\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Fildişi\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Kristal\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Elmas\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Topaz\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Kehribar\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Yeşim\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Obsidiyen\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Zümrüt\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Sırtlan\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Kurbağa\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Örümcek\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Kuzgun\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Yılan\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Sürüngen\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Ejder\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Ejderha\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Solucan\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Hidra\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Meleksi\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Baş Melek\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Bereketli\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Eli Açık\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Alevli\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Şimşek\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"kalite\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"sakat\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"katleden\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"kan\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"vahşi\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"katil\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"acı\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"gözyaşları\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"sağlıklı\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"koruma\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"soğurum\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"yansıtma\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"geçişim\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"zaaf\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"zayıf\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"güç\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"azamet\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"kuvvet\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"dev\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"titan\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"felç\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"kör\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"çevik\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"yetenek\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"isabetli\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"hassas\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"kusursuz\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"aptal\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"disleksi\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"sihir\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"zihin\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"mükemmel\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"büyücü\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"sihirbaz\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"rahatsız\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"hasta\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"yaşam\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"zevk\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"şevk\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"zinde\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"hayat\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"bela\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"çukur\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"gökyüzü\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"ay\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"yıldızlar\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"cennetler\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"zodyak\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"akbaba\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"çakal\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"tilki\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"jaguar\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"kartal\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"kurt\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"kaplan\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"aslan\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"mamut\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"balina\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"narin\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"kırılgan\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"sağlam\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"zanaatkar\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"yapı\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"çağlar\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"karanlık\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"gece\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"ışık\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"ışıma\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"alev\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"ateş\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"yanık\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"şok\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"yıldırım\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"şimşek\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"çoklu\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"yığın\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"diken\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"yoz\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"hırsız\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"ayı\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"yarasa\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"vampir\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"sülük\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"kan\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"deşici\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"delici\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"dayak\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"hazırlık\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"çabukluk\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"hız\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"acele\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"denge\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"istikrar\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"harmoni\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"önleyen\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Sihirli Kaya\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Zayıf Gharbad\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Deli Zhar\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Lachdanan\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"Kasap\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Ogdenın Tabelası\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Körlerin Salonları\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Yiğitlik\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Kan Beyi\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Kral Leoric’in Laneti\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Başpiskopos Lazarus\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Memat Meselesi\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Çiftçinin Bostanı\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Küçük Kız\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Gezgin Tüccar\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Kirletici\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"Na-Krul\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Öküzün Buzağısı\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Ateşoku\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Şifa\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Yıldırım\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Flaş\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Teşhis Etme\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Ateş Duvarı\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Kasaba Portalı\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Taş Laneti\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Ötegörü\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Sıçrama\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Mana Kalkanı\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Ateştopu\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Muhafız\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Yıldırım Zinciri\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Alev Dalgası\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Kıyamet Yılanları\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Kan Ayini\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Parlama\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Görünmezlik\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Cehennem Ateşi\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Golem\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Öfke\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Işınlanma\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Kıyamet\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Soyutlaşma\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Eşya Tamiri\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Asa Yükleme\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Tuzak Bozma\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Elemental\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Yüklü Akım\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Kutsal Ateş\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Diriltme\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Telekinezi\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Başkasını İyileştir\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Kan Yıldızı\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Kemik Ruhu\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" Ahh, Kralımızın hikayesi, değil mi? Leoricin hazin ölümü bu toprakları \"\n\"derinden etkiledi. Halk Kralı hep severdi ama artık ondan ölümüne korkuyor. \"\n\"Leoric aziz gibi bir adamdı, nasıl oldu da Işıktan bu denli uzaklaştı \"\n\"anlayamıyorum. Ancak Cehennemin rezil güçleri bir adamı böyle içten \"\n\"çürütebilir.\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Kasabanın yardımınıza ihtiyacı var efendim! Birkaç ay önce Kral Leoricin \"\n\"oğlu Prens Albrecht kaçırıldı. Kral öfkeden çıldırdı ve kayıp oğlunu \"\n\"bulabilmek için kasabayı didik didik etti. Leoric her geçen gün deliliğe \"\n\"biraz daha meyletti. Oğlunun kaybolmasından masum kasabalıları suçladı ve \"\n\"bazılarını vahşice infaz etti. Deliliğinden sadece azımız kurtulabildi.\\n\"\n\"\\n\"\n\"Kralın Şövalyeleri ve Rahipleri onu yatıştırmaya çalıştılar ama bu Kralın \"\n\"öfkesini onlara yöneltti ve maalesef Kralı öldürmek zorunda kaldılar. Kral, \"\n\"kendi adamlarını son nefesini verirken çok fena bir şekilde lanetledi. \"\n\"Onların, kendisine sonsuza kadar hizmet edeceklerine ant içti.\\n\"\n\"\\n\"\n\"İşler tam da burada düşünebileceğimden bile daha kötü bir yere vardı. Eski \"\n\"Kralımız ebedi uykusundan uyandı ve Labirentte yaşayan ölülerden bir orduya \"\n\"hükmediyor. Cesedi Katedralin üç seviye altına gömülmüştü. Lütfen efendim, \"\n\"Kralın lanetli biçimini yok ederek ruhunu huzura kavuşturun…\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Dediğim gibi, efendim, Kral yerin üç seviye altında gömülü. Orada, kokuşmuş \"\n\"karanlığın içinde, bu toprakları yok edeceği günü bekliyor.\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Kralımızın laneti geçti ama bu çok daha büyük bir kötülüğün parçasıydı \"\n\"sadece. Herneyse, topraklarımızı mahveden büyük bir kötülükten kurtulduk, \"\n\"zaferiniz iyi bir şeylerin alameti olabilir. Işık yolunuzu aydınlatsın \"\n\"efendim.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Oğlunun kaybolması, Kral Leoricin kaldırabileceğinden fazlaydı. Deliliğini \"\n\"yatıştırabilmek için elimden geleni yaptım ancak sonunda onu ele geçirdi. O \"\n\"günden beri, kara bir lanet ülkenin başından eksik olmadı ama belki ruhunu \"\n\"dünyevi hapsinden kurtarırsan lanet kalkabilir.\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Kralın ölümü hakkında düşünmek istemiyorum. Onu eskiden olduğu gibi kibar ve \"\n\"adil bir yönetici olarak yad etmek istiyorum. Ölümü çok yanlış ve üzücü \"\n\"geliyor.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Kralın şövalyeleri için çok silah ve zırh yaptım. Kendisi için de en \"\n\"kaliteli Mithrilden dev bir çift-elli kılıç ve ona uyan bir taç dövdüm. Hala \"\n\"ölmüş olduğuna inanamıyorum ama onu delirten, karanlık bir şey olmalı!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Umrumda değil. Dinle beni, hiçbir iskelet BENİM kralım olamaz. Kral, Leoric. \"\n\"Kral, anladın mı? KRALA SELAM OLSUN!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Yaşayanların arasında yürüyen ölüler Lanetli Kralı takip ediyor. Sürekli \"\n\"büyüyen ordusu için yeni savaşçılar diriltebilecek gücü elinde tutuyor. Eğer \"\n\"saltanatına son vermezsen muhakkak bu diyarlara hücum edecek ve tüm \"\n\"yaşayanları katledecek.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Bak, burda bir işletme yürütüyorum. Bilgi satmıyorum ve hayatta olduğum \"\n\"süreden daha uzun süredir ölü olan bir Kral ilgimi çekmiyor ama eğer yaşayan \"\n\"ölülerin Kralına karşı kullanacak bir şeye ihtiyacın varsa o zaman sana \"\n\"yardımcı olabilirim…\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Hayatın sıcaklığı mezarıma girdi. Ebediyen Efendimin hizmetine girmeye \"\n\"hazırla kendini, ölümlü!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Bu garip davranışın kafanı karıştırdığını görebiliyorum. Çoğu iblisin güneş \"\n\"ışığından korktuğunu ve büyük bir güç sakladığına inandığını zannediyorum. \"\n\"Bahsettiğin tabeladaki doğan güneş tasviri tabelanın bazı gizli güçleri \"\n\"olduğuna inandırmış olabilir. Hmm, belki de tahmin ettiğimiz kadar akıllı \"\n\"değillerdir…\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Efendi, Bir şey anlatacağım. Labirentte gezen yaratıklar hakkında engin \"\n\"bilgi sahibi olduğunu biliyorum ve anlatacağım şeyi bir türlü anlamıyorum. \"\n\"Geçen gece hanımın hemen dışından gelen kazıma seslerine uyandım. Odamdan \"\n\"dışarı baktığımda, hanın bahçesinde iblise benzer küçük yaratıklar gördüm. \"\n\"Kısa bir süre sonra, hanın tabelasını çalıp kaçtılar. İblislerin aileme \"\n\"dokunmayıp, tabelamı çalmasına anlam veremedim. Sence de garip değil mi?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"Ah, tabelamı geri getirmene gerek yoktu ama beni başka bir tabela \"\n\"masrafından kurtarmış oldun. Bakalım, sana bunun karşıllığında ne \"\n\"verebilirim? Hmmm, burada ne varmış… İşte! Bu başlığı, geçenlerde burada \"\n\"kalan bir büyücünün odasında buldum. Belki işine yarayabilir.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Aman Allahım! Kasabada gece iblisler geziyor, evlerimizi yağmalıyor ve bu \"\n\"sizi korkutmuyor mu? Umarım Ogden ve Garda iyilerdir. Onlara bir şey \"\n\"olduysa, mutlaka bana görünmeliler.\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"Amanın! Tabelayı iblisler mi çalmış? Büyükannemle ben de bu sırada uyuyorduk \"\n\"heralde. Işığa Şükürler olsun ki canavarlar hana saldırmamış.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"İblisler Ogdenın tabelasını mı çalmış dedin? Bu duyduğum - veya gördüğüm \"\n\"hiçbir canavarlığa benzemiyor.\\n\"\n\"\\n\"\n\"İblislerden göğsünden kalbini sökerler diye korkarsın, tabelanı değil.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Ne düşündüm biliyor musun? Biri tabelayı çaldı ve karşılığında çok para \"\n\"istiyor. Ben Ogden olsam… ki değilim ama işte olsaydım… Üzerinde güzel \"\n\"çizimler olan yeni bir tabela alırdım. Belki şöyle güzel bir kupa bira veya \"\n\"bir parça peynir…\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Hiçbir ölümlü iblis aklını anlayamaz.\\n\"\n\"\\n\"\n\"Garip davranışları seni yanıltmasın, bu onların planı da olabilir.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Ne? Benim çaldığımı mı söyledi? Kesin Griswold da onun tarafındadır.\\n\"\n\"\\n\"\n\"Bak, ben dandik tabela çalma işlerini aylar önce aştım. Bir parça tahtadan \"\n\"para kazanamazsın.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Hey - her şeyi öldüren! Bana Sihirli Bayrak getirmek yoksa biz saldırmak! \"\n\"Sen canlı gidememek! Sen büyük çirkinleri öldürmek ve Sihiri getirmek! Git \"\n\"köşe dönmek, çirkinleri bulmak! Sen vermek, sen geçmek!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Sen çirkinleri öldürmek, bayrak almak. Bana getirmek, yoksa…\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Sen vermek! Evet iyi! Şimdi git, biz güçlenmek. Biz herkes büyük Sihir \"\n\"öldürmek!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Bu iyiye alamet değil, en karanlık korkularımı doğruluyor. Çok eski \"\n\"efsanelere inanmak istemesem de artık inkar edemem. Belki de kim olduğumu \"\n\"açıklama zamanı gelmiştir.\\n\"\n\"\\n\"\n\"Gerçek ismim Yaşlı Deckard Cain ve ben kendini zamansız bir kötülüğün \"\n\"sırlarının muhafızlığını yapan bir Kardeşlik’in son temsilcisiyim. Açıkça \"\n\"görülüyor ki bir kötülük serbest kalmış.\\n\"\n\"\\n\"\n\"Kral Leoricin bir zamanlar en güvendiği danışmanı Başpiskopos Lazarus, bir \"\n\"grup kasabalıyı Kralın kayıp oğlu Albrecht’i bulmak için Labirente götürdü. \"\n\"Grup geri dönene kadar uzunca bir zaman geçti ve sadece küçük bir kısmı \"\n\"canlarını kurtarabildi.\\n\"\n\"\\n\"\n\"Aptallık ettim! Bu gizli ihanetten daha önce şüphelenmem gerekirdi. \"\n\"Albrechti kaçırıp Labirent’in derinliklerine gizleyen Lazarusun kendisi \"\n\"olmalı. Başpiskoposun neden karanlığa döndüğünü veya çocukla neden \"\n\"ilgilendiğini anlayamıyorum, tabi eğer çocuğu karanlık efendilerine kurban \"\n\"etmeyecekse!\\n\"\n\"\\n\"\n\"Planladığı şey bu olmalı! “Kurtarma” grubundan sağ kalanlar Lazarus’u en son \"\n\"Labirent’in derinliklerine kaçarken görmüşler. Acele et ve prensi bu kaçık \"\n\"iblisin elinden kurtar!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Acele edip Albrechti Lazarus’un elinden kurtarmalısın. Prens ve krallık \"\n\"tebası sana güveniyor!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Anlattıkların çok korkunç, dostum. Lazarus yaptığı rezilliklerin kefareti \"\n\"olarak mutlaka Cehennem’de yanacak. Tarif ettiğin çocuk prensimiz değil ama \"\n\"Albrechtin yine de tehlikede olabileceğini düşünüyorum. Bahsettiğin güç \"\n\"sembolü Labirentin tam kalbine giden bir portal olmalı.\\n\"\n\"\\n\"\n\"Şunu bil, dostum - Karşılaşacağın kötülük Dehşetin Efendisidir. İnsanoğlu \"\n\"arasında Diablo olarak bilinir. Yüzyıllar önce Labirentin derinliklerine \"\n\"hapsedilmişti ama korkarım ki yine insanların dünyasına kaos tohumunu ekmek \"\n\"niyetinde. çok geç olmadan önce portaldan geçip Diabloyu yok etmelisin!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Lazarus, bir sürü kasabalıyı Labirente götüren Başpiskopostu. O gün birçok \"\n\"iyi dost kaybettim ve Lazarus da hiç geri dönmedi. Sanıyorum ki o da \"\n\"diğerleri gibi öldürüldü. Sizden bir istirhamım olacaktı efendim - lütfen \"\n\"Farnham ile o gün hakkında konuşmayın.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Kasabalıların o gece ne yapmayı planladıklarını duyunca şok oldum. O kadar \"\n\"insan içinde en azından Lazarusun yeterince aklı olduğunu düşünüyordum. \"\n\"Kendisi bir Başpiskopostu ve Tristram halkıyla çok ilgilenirdi. Yok \"\n\"yaralanan oldu, hepsini kurtaramadım…\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Lazarusu çok kibar ve cömert bir adam olarak tanıdım. Annemin cenazesinde \"\n\"konuşma yapmıştı, bana ve büyükanneme zor zamanlarda çok destek olmuştu. Bir \"\n\"ihtimal hayatta ve iyi olması için her gece dua ediyorum.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Lazarus bizi Labirente götürdüğünde ben de ordaydım. İlahi adeletten \"\n\"bahsetti ama biz o cehennem tohumlarıyla dövüşürken kolunu kaldırmaya bile \"\n\"tenezzül etmedi. Karanlığa doğru kaçtı, karanlığın hizmetkarlarıyla dolu o \"\n\"sonsuz odalara!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Bıçaklıyorlar, ısırıyorlar, her yerdeler! Yalancı! YALANCI! Hepsi öldü! \"\n\"Öldü! Anlıyor musun? Teker teker düştüler… kanları her yere akıyor… hep onun \"\n\"suçu…\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Bahsettiğin Lazarusu tanımıyorum ama onun varlığında büyük bir çatışma \"\n\"hissediyorum. Büyük tehlike ihtiva ediyor ve onu kimse sahiplenildiği \"\n\"karanlık güçlere hizmet etmekten alıkoyamaz.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"Evet, erdem timsali Lazarus, aşağıda o canavarlara karşı da çoook etkiliydi. \"\n\"Bacağımı kurtaramadı ama değil mi? Bak sana bedavaya bir tavsiye vereceğim. \"\n\"Farnhama sor, o da oradaydı.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Bu aptal maceradan vazgeç. Seni bekleyen tek şey Efendimin gazabı! Çocuğu \"\n\"kurtarmak için çok geç kaldın. Şimdi cehennemde ona katıl!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Hmm, sana bu konuda yardımcı olabilecek ne söyleyebiliyorum bilmiyorum. \"\n\"Kuyularımızı dolduran su bilmediğimiz bir yeraltı kaynağından geliyor. Büyük \"\n\"bir göle çıkan bir tünel olduğunu duymuştum - belki de kaynakları aynıdır. \"\n\"Maalesef su kaynağımızı neyin kirletmiş olabileceğini bilmiyorum.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Her zaman mahzenimizde bol miktarda taze yiyecek ve içecek stoklamaya \"\n\"çalışırım ama tüm kasaba susuz kaldığı için, bizim stoklarımız bile yakında \"\n\"tükenecek.\\n\"\n\"\\n\"\n\"Lütfen elinizden geleni yapın, yoksa ne yapacağımızı bilemiyorum.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Sana zamanında yetişebildiğime sevindim! Kuyu sularımız acıdı ve bazı \"\n\"kasabalılar bu sulardan içtiği için hastalandı. Temiz su rezervlerimiz hızla \"\n\"tükeniyor. Kasabamıza su sağlayan kaynağa giden bir geçit olduğunu \"\n\"sanıyorum. Lütfen bu felakete neyin sebep olduğunu bul, yoksa hepimiz telef \"\n\"olacağız.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Lütfen, acele et. Geçen her saat bizi susuzluğa daha da yaklaştırıyor.\\n\"\n\"\\n\"\n\"Yardımın olmadan uzun süre hayatta kalamayız.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"Ne diyorsun! - İblislerin sadece varlığı varlığı bile suyun kirlenmesine \"\n\"yetmiş mi? Ah, gerçekten büyük bir kötülük kasabamızın altında gizleniyor \"\n\"ama azmin ve cesaretin bize umut veriyor. Lütfen bu yüzüğü al - belki bu, \"\n\"böyle iğrenç yaratıkları yok etmene yardımcı olur.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Büyükannem çok halsiz ve Garda kuyulardaki sulardan içemeyeceğimizi \"\n\"söylüyor. Lütfen, bize yardım etmek için bir şey yapabilir misin?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Pepin sana gerçeği söylemiş. Çok yakında içme suyuna çok ihtiyaç duyacağız. \"\n\"Küçük kuyulardan birini temizlemeye çalıştım ama leş gibi kokuyor. Kaynağı \"\n\"bozulmuş olmalı.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Sen su mu içiyorsun?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Kuyularını temizleyemezsen Tristram halkı ölecek.\\n\"\n\"\\n\"\n\"Şunu bil ki - bu meselenin arkasında iblisler var ama neye sebep \"\n\"olduklarının farkında değiller.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"Bu sefer, ben de seninleyim. Eğer satış yapacağım bir piyasa olmazsa benim \"\n\"de işlerim kuruyacak. Hemen neler olup bittiğini çözsen iyi olur!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"İnsan kemiklerinden oluşan bir odadan bahseden bir kitap mı? Evet, Doğunun \"\n\"kütüphanelerinde incelediğim bazı eski yazılarda Kemikler Odasından \"\n\"bahsediliyor. Bu kitaplar, yeraltı Efendilerinin büyük hazineleri korumak \"\n\"istediklerinde, o hazineyi çalmaya çalışanların sonsuza dek savunmakla \"\n\"yükümlü oldukları alanlar yarattıklarını belirtiyordu. Sapkın ama garip bir \"\n\"şekilde uygun bir son değil mi?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Korkarım ki bunun hakkında hiçbir şey bilmiyorum efendim. Cainin çok kitabı \"\n\"var belki o yardımcı olabilir.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Kulağa çok tehlikeli bir yermiş gibi geliyor. Oraya gidersen lütfen dikkatli \"\n\"ol.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Korkarım ki hakkında hiçbir şey duymadım. Belki Öykücü Cain bu konuda yardım \"\n\"edebilir.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Bu yer hakkında hiçbir şey bilmiyorum ama Cain’e sormayı deneyebilirsin. O \"\n\"birçok şey bilir ve bu soruna bazı cevapları olması beni şaşırtmaz.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Tamam o zaman, dinle. Tahta bir oda var. Ve karısı var, biliyorsun - o \"\n\"kadını - ağaca diyor ki… çünkü beklemen lazım. Sonra ben diyorum ki, ona \"\n\"karşı işe yarayabilir ama düşünürsen bunu sana ÖDEYECEĞİM… sen… ah… evet.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Bu lanetli alanda ölürsen, karanlık Efendilerin sonsuz bir hizmetkârı \"\n\"olacaksın.\\n\"\n\"\\n\"\n\"Kemikler Odasına gideceksen risklerini bilmelisin.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Büyük ve gizemli bir hazine mi diyorsun? Belki senden birkaç şey almayı \"\n\"düşünebilirim… hatta daha iyisi, bu sıkıntılı durumu atlatmak için nadir ve \"\n\"pahalı malzemelere ihtiyacın yok mu?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Görünüşe göre Başpiskopos Lazarus, birçok kasabalıyı Kral’ın kayıp oğlunu \"\n\"bulmak için Labirente girmeye kışkırttı. Korkularını kullanarak onları \"\n\"çılgın bir kalabalığa dönüştürdü. Hiçbiri soğuk toprağın altındakilere \"\n\"hazırlıklı değildi… Lazarus onları orada terk etti - tarif edilemez \"\n\"dehşetlerin pençesinde ölmeye bıraktı.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Evet, Farnham korkunç bir silah kullanan iri yarı bir vahşi ile ilgili \"\n\"şeyler gevelemişti. Sanırım onun bir kasap olduğundan bahsetti.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Işık adına, bu aşağılık iblisi biliyorum. Lazarus’un öncülük ettiği gruptan \"\n\"sağ kurtulan birkaç kişi Katedralden sürünerek çıktığında, pek çoğunun \"\n\"vücudunda onun gazabının izleri vardı. Kurbanlarını neyle doğradığını \"\n\"bilmiyorum ama bu dünyaya ait olamaz. Yaralar hastalıkla iltihaplanmış \"\n\"haldeydi ve onları tedavi etmek neredeyse imkansızdı. Bu yaratıkla savaşmayı \"\n\"planlıyorsan dikkatli olun…\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Farnham bir kasabın insanları öldürdüğünden bahsettiğinde ciddiye \"\n\"almamıştım. Ama sen konuyu açtığına göre, belki de doğrudur.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Farnhamın Kasap dediği yaratığın, dostlarımın cesetleri arasından geçtiğini \"\n\"gördüm. Balta kadar bir satır sallıyordu, uzuvları parçalıyor ve cesur \"\n\"adamları bulundukları yerde kesiyordu. Bu kargaşadan küçük ve zırlayan \"\n\"iblislerden oluşan bir grup tarafından uzaklaştırıldım ve bir şekilde çıkışa \"\n\"giden merdiveni buldum. O iğrenç yaratığı bir daha hiç görmedim ama kanla \"\n\"lekelenmiş yüzü hâlâ rüyalarıma giriyor.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Kocaman! Kocaman satır tüm dostlarımı öldürüyor. Onu durduramadım, kaçmak \"\n\"zorunda kaldım, onları kurtaramadım. Bir odada kapana kısıldım, çok fazla \"\n\"ceset… çok fazla dost… HAYIRRRRRRR!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"Kasap, başkalarının işkence ve acılarından zevk alan sadist bir yaratıktır. \"\n\"Hünerlerini Sarhoş Farnhamda gördün. Yok edilmesi, bu köyün güvenliğini \"\n\"sağlamak için çok faydalı olacaktır.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"O ürkütücü yaratık hakkında tahmininden fazla şey biliyorum. Küçük dostları \"\n\"beni yakaladı ve Griswold beni o çukurdan çıkarana kadar bacağımı yaralamayı \"\n\"başardılar.\\n\"\n\"\\n\"\n\"Açıkça söyleyeceğim - onu öldür, yoksa o seni öldürür ve cesedini \"\n\"koleksiyonuna ekler.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Lütfen, beni dinle. Başpiskopos Lazarus, bizi kayıp prensi bulmak için \"\n\"buraya getirdi. O alçak bizi tuzağa sürükledi! Şimdi herkes öldü… onun Kasap \"\n\"dediği bir iblis tarafından katledildi. İntikamımızı al! Bu Kasabı bul ve \"\n\"öldür ki ruhlarımız sonunda huzura kavuşsun…\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"İlginç bir kafiye, bana başka eserleri hatırlatan bir tarzda yazılmış. \"\n\"Düşüneyim şimdi - neydi?\\n\"\n\"\\n\"\n\"…Karanlık, Gizliyi örtüyor. Gözler, sadece körlüğe mahkûm edilmiş zavallı \"\n\"ruhları kısa bir süre işkence etmek için tırnakların bıçak gibi kazındığı \"\n\"seslerle görünmeden parlıyor. Bu lanetli olanların hapishanesine Körlerin \"\n\"Salonları denir…\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Hiç şiire ilgim olmadı. Ara sıra, han iyi iş yaptığında ozanlar tutardım ama \"\n\"bu artık çok uzun zaman önce gibi geliyor.\\n\"\n\"\\n\"\n\"Ne? Ah, evet… şey, sanırım başkalarına sorabilirsiniz.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Bu bana bir şekilde tanıdık geliyor. Şeytani rahatsızlıkların tarihini \"\n\"araştırırken o şiire çok benzer bir şey okuduğumu hatırlıyorum. Büyük bir \"\n\"kötülüğün olduğu bir yerden bahsediyordu… bekle - oraya gitmiyorsun, değil \"\n\"mi?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Körlük hakkında soruların varsa, Pepin ile konuşmalısın. Büyükanneme görme \"\n\"yetisini düzelten bir iksir verdiğini biliyorum, belki sana da yardımcı \"\n\"olabilir.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Korkarım ki, tarif ettiğin gibi bir yer duymadım veya görmedim dostum. Belki \"\n\"Öykücü Cain size yardımcı olabilir.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Buraya bak… çok komik, di mi? Anladın mı? Kör - buraya bak?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Burası büyük acı ve dehşetin hüküm sürdüğü bir yer, yani efendisine iyi \"\n\"hizmet ediyor.\\n\"\n\"\\n\"\n\"Adımını dikkatli at, yoksa beklediğinden çok daha uzun süre kalabilirsin.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Bakalım, sana bir şey mi satıyorum? Hayır. Bana bunu anlatmam için para mı \"\n\"veriyorsun? Hayır. Şimdi gidip ömrünü bu tür şeylere adayan öykücüyle mi \"\n\"konuşuyorsun? Evet.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Lachdanan ile konuştuğunuzu mu söylüyorsun? Hayatı boyunca büyük bir \"\n\"kahramandı. Lachdanan, yıllarca Kralına sadakatle hizmet eden onurlu ve adil \"\n\"bir insandı. Ama elbette, bunu zaten biliyorsun.\\n\"\n\"\\n\"\n\"Kralın Lanetinin pençesine düşenler arasında, Lachdanan savaşmadan karanlığa \"\n\"teslim olacak en son olan kişiydi, bu yüzden hikayen doğru olabilir. Eğer \"\n\"yerinde olsaydım, dostum, onu işkencesinden kurtarmanın bir yolunu bulurdum.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Uzun zaman önce ölmüş cesur bir savaşçıdan bahsediyorsunuz! Hanımın \"\n\"avlusunda ölü ruhlarla konuşmaktan bahsetmeyeceğim, çok teşekkür ederim.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Altın renkli bir iksir mi? Daha önce hiç böyle bir renkte iksir \"\n\"hazırlamadım, bu yüzden içmeye kalkışırsan seni nasıl etkileyeceğini \"\n\"söyleyemem. Bir şifacı olarak, eğer böyle bir iksir bulursan, Lachdananın \"\n\"dediği gibi yapmanı ve onu kullanmamanı şiddetle tavsiye ederim.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Lachdanan adını daha önce hiç duymadım. Üzgünüm ama pek yardımcı \"\n\"olabileceğimi sanmıyorum.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Eğer gerçekten Lachdanan ile karşılaştıysan, ona yardım etmeni tavsiye \"\n\"ederim. Onunla birkaç kez işim oldu ve gerçekten dürüst ve sadık olduğunu \"\n\"gördüm. Kral Leoricin adamlarını etkileyen lanet, özellikle Lachdananın \"\n\"üzerinde ağır bir şekilde çökecektir.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Lachdanan öldü. Bunu herkes biliyor ve beni aksine inandıramazsın. Ölülerle \"\n\"konuşamazsın. Biliyorum!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Labirentte Lachdanan gibi tuzağa düşmüş insanlarla karşılaşabilirsin.\\n\"\n\"\\n\"\n\"Onda onur ve büyük bir vicdan azabı hissediyorum. Ona yardım et, böylece \"\n\"Tristramın tamamına yardım etmiş olursunuz.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Dur, tahmin edeyim. Cain, altında açılan devasa bir yarık tarafından \"\n\"yutuldu. Cehennem ateşinde yanarak kül oldu ve artık sorularına cevap \"\n\"veremiyor. Ah, öyle olmadı mı? O zaman ya bir şey satın alırsın ya da yoluna \"\n\"gidersin.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Lütfen, beni öldürme, sadece dinle. Bir zamanlar Kral Leoricin \"\n\"Şövalyelerinin Komutanıydım, bu toprakların yasalarını adalet ve onurla \"\n\"savunuyordum. Sonra Kralın karanlık Laneti, trajik ölümündeki rolümüzden \"\n\"dolayı üzerimize çöktü. Şövalyelerim çarpık kaderlerine boyun eğerken, ben \"\n\"Kralın mezar odasından kaçtım, kendimi bu Lanetten kurtaracak bir yol aramak \"\n\"için. Başarısız oldum…\\n\"\n\"\\n\"\n\"Üzerimdeki Laneti Altın bir Eliksirin kaldırabileceğini ve ruhumu huzura \"\n\"kavuşturacağını duydum ama bulamadım. Şimdi, gücüm tükeniyor ve benliğim de \"\n\"kayboluyor. Lütfen bana yardım et ve Eliksiri bul. Çabalarını \"\n\"ödüllendireceğim - onurum üzerine yemin ederim.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Altın Eliksiri bulamamışsın. Sonsuza dek lanetlenmiş olmaktan korkuyorum. \"\n\"Lütfen, denemeye devam et…\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Ruhumu lanetlenmekten kurtardın ve bunun için sana minnettarım. Mezarın \"\n\"ötesinden borcumu ödeyebileceğim bir yol varsa bulacağım ama şimdilik - \"\n\"miğferimi al. Çıkacağım yolculukta ona pek ihtiyacım olmayacak. Karanlık \"\n\"güçlere karşı seni korusun. Işık seninle olsun, dostum…\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Griswold, uzun zamandır aranan ancak asla bulunamayan efsanevi bir eser olan \"\n\"Gazap Örsünden bahsediyor. Jilet Çukuru iblislerinin metalik kemiklerinden \"\n\"yapılmış olan Gazap Örsünün dökümü, yeraltı dünyasının en güçlü beş \"\n\"büyücüsünün kafatasları içinde yapılmıştır. Üzerine güç ve kaos rünleriyle \"\n\"kazınmış olan bu örs üzerinde dövülen herhangi bir silah veya zırh, Kaos \"\n\"Alemine daldırılır ve büyülü özellikler kazandırılır. Kaosun öngörülemez \"\n\"doğasının, bu demirciliğin sonucunu bilmenin zor olduğunu söylediği söylenir…\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Sizce bunu Griswolda sormak daha iyi bir fikir olmaz mı? Kendisi, bu \"\n\"konularda oldukça yetkindir, bilirsiniz.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Eğer İyileştirme Tokmağı veya Arınmanın Gümüş Kadehi hakkında bilgi edinmek \"\n\"isteseydin, yardımcı olabilirdim, dostum. Ancak, bu konuda Griswold veya \"\n\"Cain ile konuşman daha iyi olur.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Griswoldun babası, biz küçükken, güçlü silahlar yapmak için kullanılan \"\n\"devasa bir örsten bahsederdi. Bu örse bir çekiç vurulduğunda, yerin büyük \"\n\"bir öfkeyle sarsılacağını söylerdi. Ne zaman yer sarsılsa, bu hikayeyi \"\n\"hatırlarım.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Selamlar! En iyi müşterilerimden birini görmek benim için büyük zevk! \"\n\"Labirentin derinliklerine indiğini biliyorum ve dinlemeye değer \"\n\"bulabileceğin bir hikayem var…\\n\"\n\"\\n\"\n\"Labirentten dönen adamlardan biri, kaçışı sırasında gizemli bir örse \"\n\"rastladığını söyledi. Tarifi, gençliğimde duyduğum, güçlü büyü silahlarının \"\n\"yapıldığı Cehennem Ocağı efsanelerini hatırlattı. Efsaneye göre, Gazap Örsü, \"\n\"Cehennem Ocağının derinliklerindeydi! Bu Örs, şeytani yeraltı dünyasının \"\n\"özünü içinde barındırıyordu…\\n\"\n\"\\n\"\n\"Gazap Örsü üzerinde dövülen bir silahın büyük güçle dolacağı söylenir. Eğer \"\n\"bu örs gerçekten Gazap Örsü ise, sana Cehennem’in en karanlık lordunu bile \"\n\"yenebilecek bir silah yapabilirim!\\n\"\n\"\\n\"\n\"Örsü benim için bul, işe koyulayım!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Henüz bir şey bulamadın mı? Peki, aramaya devam et. Örs üzerinde dövülen bir \"\n\"silah en iyi umudun olabilir ve eminim ki sana efsanevi bir silah \"\n\"yapabilirim.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"İnanamıyorum! Bu gerçekten de Gazap Örsü - iyi iş çıkardın, dostum. Şimdi o \"\n\"alçaklara Cehennem’de insanlar tarafından yapılan silahlardan daha ölümcül \"\n\"silahlar olmadığını göstereceğiz! Bunu al ve Işık seni korusun.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Griswold örsünü satamaz ki. E, o zaman ne yapacak? Ayrıca biri benim örsümü \"\n\"alsaydı ben de öfkelenirdim!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"Labirentte, ölümlülerin kavrayışının ötesinde güçlere sahip birçok eser var. \"\n\"Bunlardan bazıları, Işık veya Karanlık tarafından kullanılabilecek muazzam \"\n\"güçlere sahip. Örsü güvence altına almak, Günah Savaşının seyrini Işık’tan \"\n\"yana değiştirebilir.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Eğer bu eseri Griswold için bulursan, işlerimi ciddi şekilde baltalayabilir. \"\n\"Aaa, zaten onu asla bulamayacaksın.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Kan Geçidi ve Ateş Salonları mistik kökenli yerlerdir. Bu kitabı her nerede \"\n\"okuduysan, kesinlikle büyük güce sahip bir yerdir.\\n\"\n\"\\n\"\n\"Efsaneler, obsidiyen taşından oyulmuş ve kemiklerle kaplanmış yüzeyinde \"\n\"kaynayan bir kan havuzu olan bir kaideden bahseder. Ayrıca, eski bir \"\n\"hazineyi koruyan bir kapıyı açacak Kan Taşlarına da atıflar vardır…\\n\"\n\"\\n\"\n\"Bu hazinenin doğası duyumlarla örtülmüş, dostum ama antik kahraman \"\n\"Arkaine’in kutsal zırhı Yiğitliki gizli bir mahzene yerleştirdiği söylenir. \"\n\"Arkaine, Günah Savaşının seyrini değiştiren ve karanlık ordularını Yanan \"\n\"Cehennemlere geri süren ilk ölümlüydü.\\n\"\n\"\\n\"\n\"Arkaine ölmeden hemen önce, zırhı gizli bir mahzene saklandı. Bu kutsal \"\n\"zırha tekrar ihtiyaç duyulduğunda, bir kahramanın ortaya çıkıp Yiğitlik'i \"\n\"tekrar kuşanacağı söylenir. Belki de o kahraman sensin…\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Her çocuk, savaşçı Arkaine ve onun gizemli zırhı olan Yiğitlik’in hikayesini \"\n\"dinlemiştir. Eğer onun yattığı yeri bulabilirseniz, Labirentteki kötülüklere \"\n\"karşı korunursunuz.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Hmm… Hatırlamam gereken bir şey gibi geliyor ama yeni tedaviler öğrenmek ve \"\n\"daha iyi iksirler yapmakla o kadar meşguldüm ki, unutmuş olmalıyım. Üzgünüm…\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Yiğitlik adındaki sihirli zırhın hikayesi, çocukların sıkça bahsettiği bir \"\n\"şeydir. Köydeki erkeklerden birine sorman daha iyi olur.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Yiğitlik olarak bilinen zırh, dengelerin senin lehine dönmesini \"\n\"sağlayabilir. Birçok kişinin onu aradığını - ben de dahil olmak üzere - \"\n\"söyleyebilirim. Arkaine onu iyi saklamış, dostum, ve onu bu kadar zaman \"\n\"gizli tutan sırları açığa çıkarmak için biraz şanstan fazlası gerekecek.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Bu Kan Taşlarını bulursan, onları dikkatlice kullan.\\n\"\n\"\\n\"\n\"Yol tehlikelerle dolu ve tek umudun kendine olan güveninde yatıyor.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Yiğitlik olarak bilinen zırhı bulmaya mı niyetlisin?\\n\"\n\"\\n\"\n\"Kimse, Arkaine’in onu nereye sakladığını çözemedi ve eğer benim \"\n\"bağlantılarım bulamadıysa, senin de bulabileceğinden ciddi şüphelerim var.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Tarif ettiğin gibi bir savaşçıdan bahseden yalnızca bir efsane biliyorum. \"\n\"Onun hikayesi, Günah Savaşının antik kroniklerinde yazılıdır…\\n\"\n\"\\n\"\n\"Bin yıllık savaş, kan ve ölümle lekelenmiş olan Kan Beyi, lime lime olmuş \"\n\"kurban cesetlerinin oluşturduğu dağın üstünde durur. Karanlık kılıcı \"\n\"yaşayanlara karşı kara bir lanet fısıldar; Cehennemin Celladı’nın önünde \"\n\"duracak herkese işkence dolu bir davet.\\n\"\n\"\\n\"\n\"Ayrıca, bir zamanlar Günah Savaşı sırasında Karanlık Ordu ile yan yana \"\n\"savaşan bir ölümlü olduğu halde, kana olan doyumsuz açlığıyla insanlığını \"\n\"kaybettiği de yazılıdır.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Korkarım ki böylesine acımasız bir savaşçı hakkında hiçbir şey duymadım, \"\n\"efendim. Umarım onunla savaşmak zorunda kalmazsınız, çünkü kulağa çok \"\n\"tehlikeli geliyor.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Asla bilmek istemeyeceğim böyle bir konuda Cain sana çok daha fazlasını \"\n\"söyleyebilir.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Eğer böyle korkunç bir düşmanla savaşacaksan, Işık senin rehberin ve \"\n\"koruyucun olsun. Hep aklımda olacaksın.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Kan Beyini çevreleyen karanlık ve kötü efsaneler var. İyi hazırlan, dostum, \"\n\"çünkü o hiç acımaz veya merhamet göstermez.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Her zaman Kandan mı bahsetmek zorundasın? Ya çiçekler, güneş ve içkileri \"\n\"getiren güzel kıza ne olacak? Dinle dostum - takıntılısın, biliyorsun değil \"\n\"mi?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Kılıç ustalığındaki mahareti inanılmaz ve binlerce yıl boyunca sadece \"\n\"savaşarak yaşamış. Üzgünüm… Onu yenip yenemeyeceğini göremiyorum.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Bahsettiğin bu Bey ile hiç iş yapmadım ama kulağa çok kılıç harcıyormuş gibi \"\n\"geliyor. Ordularına malzeme sağlamaktan zarar gelmezdi…\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Kılıcım kanın için şarkı söylüyor, ölümlü, ve karanlık efendilerim \"\n\"tarafından reddedilmeyecek.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Griswold, doğudaki şehre gitmesi gereken Göklerin Taşı’ndan bahsediyor. \"\n\"Göklerin Taşı üzerinde çalışmalar yapmak üzere Doğuya götürülüyordu. Bu taş, \"\n\"normal bir insanın sahip olabileceğinden daha fazla görüş sağlayan bir \"\n\"enerjiyle parlıyordu. Taşın hangi sırları barındırdığını bilmiyorum, dostum \"\n\"ama bu taşı bulmak kesinlikle çok değerli olurdu.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Kervan, doğuya olan yolculukları sırasında bazı malzemeler almak üzere \"\n\"burada durdu. Onlara taze meyveler ve Gardanın yeni pişirdiği mükemmel tatlı \"\n\"ekmekler sattım. Başlarına gelenler gerçekten yazık…\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"O taşla neleri görebileceklerini düşündüklerini bilmiyorum ama şunu \"\n\"söyleyeyim. Gökyüzünden taşlar düşüyorsa, dikkatli olman daha iyi!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Evet, çok önemli kişilerden oluşan bir kervan burada durdu ama bu bayağı \"\n\"zaman önceydi. Tuhaf bir aksanları vardı ve hatırladığım kadarıyla uzun bir \"\n\"yolculuğa çıkmışlardı.\\n\"\n\"\\n\"\n\"Onların taşıdığı herhangi bir şeyi nasıl bulabileceğinizi anlayamıyorum.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Biraz bekle - ilgini çekebilecek bir hikayem var. Bir süre önce buradan \"\n\"Doğudaki krallıklara gitmekte olan bir kervan geçti. Dünyaya göklerden düşen \"\n\"bir parça taşıdıkları söyleniyordu! Kervan, buranın hemen kuzeyindeki yolda \"\n\"pelerinli süvariler tarafından pusuya düşürüldü. Gök taşını enkazda aradım \"\n\"ama hiçbir yerde bulamadım. Eğer bulabilirsen, ondan faydalı bir şey \"\n\"yapabileceğime inanıyorum.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Hâlâ bana göklerden gelen o taşı getirmeni bekliyorum. Onunla güçlü bir \"\n\"şeyler yapabileceğimi biliyorum.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Bir bakayım - evet… evet, tahmin ettiğim gibi. Bana bir dakika ver…\\n\"\n\"\\n\"\n\"Ah, işte burada. Babamın bana bıraktığı gümüş yüzük içine taş parçalarını \"\n\"yerleştirdim. Umarım sana iyi hizmet eder.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Eskiden güzel bir yüzüğüm vardı; gerçekten pahalı bir şeydi, mavi, yeşil, \"\n\"kırmızı ve gümüş renklerindeydi. Ne olduğunu hatırlamıyorum gerçi. O yüzüğü \"\n\"gerçekten özlüyorum…\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Göklerin Taşı çok güçlüdür ve eğer sana onu bulmanı söyleyen Griswolddan \"\n\"başkası olsaydı, bunu engellerdim. Griswold taşın güçlerini kontrol altına \"\n\"alacak ve bu, hepimiz için iyi olacak.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Eğer o taştan bir şey yapabilecek biri varsa, o kesinlikle Griswolddur. Ne \"\n\"yaptığını biliyor ve müşterilerini çalmaya çalışsam da, işinin kalitesine \"\n\"saygı duyuyorum.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Cadı Adria siyah bir mantar mı arıyor? Siyah Mantarlar hakkında, Kırmızı \"\n\"Ringa Balıkları hakkında bildiğim kadarını biliyorum. Belki Şifacı Pepin \"\n\"daha fazlasını söyleyebilir ama bu benim hikayelerimde veya kitaplarımda \"\n\"olmayan bir konu.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Şunu söyleyeyim. Garda ve ben, asla ve ASLA, siyah mantarları değerli \"\n\"misafirlerimize sunmayız. Eğer Adria yemeğinde biraz mantar istiyorsa, bu \"\n\"onun bileceği iş ama size mantar bulmada yardımcı olamam. Siyah mantarlar… \"\n\"iğrenç!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Cadı, iksirimde bana yardımcı olmak için bir iblisin beynini aradığını \"\n\"söyledi. Eğer simyasının sırlarını çözebilirsem, o iğrenç yaratıklar \"\n\"tarafından yaralanan birçok kişi için büyük fayda sağlayabilirim. Eğer bir \"\n\"iblisi öldürdüğünde beynini çıkarıp bana getirirsen minnettar olurum.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Mükemmel, tam da aklımdan geçiyordu. Bu olmadan iksiri tamamlayabildim ama \"\n\"bu beyni incelemek de fayda sağlayabilir. Lütfen bunu cadıya götürür müsün? \"\n\"Sanıyorum ki o da bunu bekliyor.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Sanırım Ogdenın kilerinde biraz mantar olabilir. Neden ona sormuyorsun?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Eğer Adrianın elinde olmayan bir şeyse, gerçekten nadir olduğuna bahse \"\n\"girerim. Bundan daha fazla yardımcı olamam ama kulağa… devasa, kocaman, \"\n\"şişmiş, kabarmış bir mantar gibi geliyor! Eh, iyi avlar dilerim sanırım.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Ogden, müthiş bir siyah mantar karışımı yapar ama onu içince hasta oluyorum. \"\n\"Dinle, dinle… işin sırrı şu - her şeyde ölçü anahtardır!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Ne varmış burada? İlginç, bu bir iksir kitabına benziyor. Gözlerini dört aç, \"\n\"siyah bir mantar arıyoruz. Oldukça büyük ve kolayca tanınabilir olmalı. Eğer \"\n\"bulursan, bana getirir misin?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"İhtiyacım olan büyük, siyah bir mantar. Şimdi git ve onu bana getir ki \"\n\"üzerinde çalıştığım özel bir karışımda kullanabileyim.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Evet, bu yaptığım bir karışım için mükemmel olacak. Bu arada, şifacı da bir \"\n\"iblisin beynini arıyor ki onların zehirleriyle etkilenen insanları tedavi \"\n\"edebilsin. Ondan bir iksir yapmaya niyetlendiğini düşünüyorum. Eğer ihtiyacı \"\n\"olan şeyi bulmasına yardım edersen, lütfen benim için de iksirden bir örnek \"\n\"alıver.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Bunu neden buraya getirdin? Şu anda bir iblisin beynine ihtiyacım yok. \"\n\"Şifacının üzerinde çalıştığı iksire ihtiyacım var. Elindeki o garip organa \"\n\"şifacının ihtiyacı var, ve sonra bana iksiri getir. Düşününce basit, değil \"\n\"mi?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Ne? Bana o iksiri şifacıdan şimdi mi getiriyorsun? Karışımımı o olmadan da \"\n\"tamamlayabildim. Neden onu kendine saklamıyorsun…\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Herhangi bir boyutta veya renkte satılık mantarım yok. Daha kullanışlı bir \"\n\"şeye ne dersin?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Demek ki Harita efsanesi gerçekmiş. Buna ben bile gerçekten inanmazdım! \"\n\"Sanırım artık kim olduğum gerçeğini anlatma zamanı geldi, dostum. Görüyorsun \"\n\"ki, ben göründüğüm gibi biri değilim...\\n\"\n\"\\n\"\n\"Gerçek ismim Yaşlı Deckard Cain ve ben kendini zamansız bir kötülüğün \"\n\"sırlarının muhafızlığını yapan bir Kardeşlik’in son temsilcisiyim. Açıkça \"\n\"görülüyor ki bir kötülük serbest kalmış.\\n\"\n\"\\n\"\n\"Şunu bil, dostum - Karşılaşacağın kötülük Dehşetin Efendisidir. İnsanoğlu \"\n\"arasında Diablo olarak bilinir. Yüzyıllar önce Labirentin derinliklerine \"\n\"hapsedilmişti. Şimdi elinde tuttuğun Harita, Diablo’nun tutsaklığından \"\n\"tekrar yükseleceği zamanı göstermek için asırlar önce yaratıldı. O \"\n\"haritadaki iki yıldız hizalandığında, Diablo gücünün zirvesinde olacak. \"\n\"Neredeyse yenilmez olacak!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"Zamanımız daralıyor! Diablonun Karanlık gücünün arttığını hissediyorum ve \"\n\"onu tam gücüne ulaşmaktan alıkoyabilecek tek kişi sensin.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Elinden gelenin en iyisini yaptığından eminim ama korkarım ki senin gücün ve \"\n\"iraden bile yeterli olmayabilir. Diablo, şimdi dünyadaki gücünün zirvesinde \"\n\"ve onu yenmek için tüm cesaretine ve gücüne ihtiyacın olacak. Işık seni \"\n\"korusun ve rehberlik etsin, dostum. Elimden geldiğince yardım edeceğim.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Eğer cadı size yardımcı olamayıp Caini görmeni öneriyorsa, benim bir şey \"\n\"bileceğimi size düşündüren nedir? Bu çok ciddi bir mesele gibi görünüyor. \"\n\"Adrianın önerdiği gibi öykücüyü görmeye gitmelisiniz.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Bu haritadaki yazılardan pek bir şey anlayamıyorum ama belki Adria ya da \"\n\"Cain bunun neye atıfta bulunduğunu çözmene yardımcı olabilir.\\n\"\n\"\\n\"\n\"Gökyüzümüzdeki yıldızların bir haritası olduğunu görebiliyorum ama bundan \"\n\"fazlası benim hünerlerimi aşıyor.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Bunu sorabileceğin en iyi kişi öykücümüzdür.\\n\"\n\"\\n\"\n\"Cain, antik yazılar konusunda çok bilgilidir ve bu, şimdiye kadar gördüğüm \"\n\"en eski kağıt parçası gibi görünüyor.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Böyle bir haritayı daha önce hiç görmedim. Bunu nereden buldun? Nasıl \"\n\"okuyacağım hakkında hiçbir fikrim yok ama Cain veya Adria aradığın cevapları \"\n\"sağlayabilir.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Dinle, yakına gel. Benim ne bildiğimi bilip bilmediğini bilmiyorum ama \"\n\"burada gerçekten bir şey var. Bu bir harita.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"Ah, korkarım ki bu hiç de iyiye işaret değil. Bu yıldız haritası büyük bir \"\n\"felaketi işaret ediyor, bunlar benim anlatabileceğim sırlar değiller. Öykücü \"\n\"ile çok ciddi bir konuşma yapmanın zamanı geldi…\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Ben de bir harita arıyordum ama bu kesinlikle o değil. Bunu Adria’ya \"\n\"göstermelisin - sana ne olduğunu muhtemelen söyleyebilir. Şunu söyleyeyim; \"\n\"eski görünüyor ve eski genellikle değerli demektir.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Lütfeeeeeen, verme zaraaar. Öldürmee. Kal hayatta ve sonraki sefer sana iyi \"\n\"şey vermeek.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Senin için yapıyorum güzel şeey. Yine, öldürme Gharbadı. Yaşar ve verir \"\n\"iyiii.\\n\"\n\"\\n\"\n\"Kanıtı al tuttuğum sözüüün…\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Değil dahaa! Kaldı az.\\n\"\n\"\\n\"\n\"Güçlü çok, kuvvetli çok. Yaşat! yaşat!\\n\"\n\"\\n\"\n\"Verme acı ve ben tuttum sözüüü!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"İyi bu sana. Güçlü çok. İste sen - al sen!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Ne?! Neden buradasın? Bu kadar rahatsızlık bir insanı çıldırtmaya yeter. \"\n\"Bunu al ve beni işimle yalnız bırak. Beni daha fazla rahatsız etme!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Arrrrgh! Merakın senin sonun olacak!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Merhaba, dostum. Biraz dur ve dinle…\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Labirentin derinliklerine inerken orada saklanmış ve çok önemli bilgiler \"\n\"içeren kitaplar bulabilirsin.\\n\"\n\"\\n\"\n\"Onları dikkatlice oku çünkü sana benim bile bilmediğim şeyleri \"\n\"anlatabilirler.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Labirente yaptığın yolculuklarda aklına gelebilecek soruların cevaplarını \"\n\"içeren birçok mit ve efsane biliyorum. Eğer zorluklarla ve bilgi aradığınız \"\n\"sorularla karşılaşırsan, beni bul ve sana elimden geldiğince anlatayım.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Griswold - çok cesur ve tam bir eylem adamı. Wirtü kurtarmak için Labirente \"\n\"girdiği zamanı sana hiç anlatmadığına bahse girerim, anlatmadı değil mi? \"\n\"Orada bulunan tehlikeleri iyi bilir ama tabi - sen de öyle. O, becerikli bir \"\n\"zanaatkar ve eğer sana herhangi bir şekilde yardım edebileceğini iddia \"\n\"ediyorsa, dürüstlüğüne ve becerisine güvenebilirsin.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Ogden, neredeyse dört yıldır Gündoğan Hanı ve Meyhanesi’ni işletiyor. Bu \"\n\"kasabadaki her şey cehenneme dönmeden sadece birkaç ay önce satın aldı. O ve \"\n\"karısı Garda, buradaki yaşamlarını kurmak için tüm varlıklarını yatırdıkları \"\n\"için gidecek paraları yok. Ogden, derin bir sorumluluk duygusuna sahip iyi \"\n\"bir adamdır.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Zavallı Farnham. O karanlık günde Lazarus ile birlikte Katedrale giren \"\n\"talihsiz topluluğun üzücü bir hatırlatıcısı. Hayatıyla kurtarmayı başardı \"\n\"ama cesareti ve aklının büyük bir kısmını karanlık bir çukurda bıraktı. \"\n\"Günümüzde teselliyi sadece şişenin dibinde bulabiliyor, sürekli gevezelik \"\n\"yapsa da, söylediklerinde bazen gerçekler de saklı olabiliyor.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Cadı, Adria, burada Tristramda bir istisna. Katedral kirletildikten kısa bir \"\n\"süre sonra geldi, çoğu kişi kaçarken o buraya yerleşti. Şehrin kenarında, \"\n\"neredeyse bir gecede küçük bir kulübe yaptı ve benim bile daha önce hiç \"\n\"görmediğim birçok garip ve gizemli eser ve ilim kitapları var.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Wirtün hikayesi korkutucu ve trajiktir. Annesinin kollarından alınıp, \"\n\"mızrakı küçük, pis şeytanlar tarafından labirente sürüklendi. O gün anlınan \"\n\"başka çocuklar da vardı, bunlardan biri de Kral Leoricin oğluydu. Sarayın \"\n\"Şövalyeleri aşağıya indi ama bir daha geri dönemedi. Demirci oğlanı buldu \"\n\"ama, pis canavarlar ona çoktan sadistik zevkleri için işkence etmişlerdi \"\n\"bile.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"Ah, Pepin. Onu gerçek bir dost olarak bilirim - belki de burada bana en \"\n\"yakın kişi o. Bazen biraz kafası karışık olabilir ama ondan ilgili ya da \"\n\"düşüncelisini bulamazsın. Bilgisi ve yeteneklerinin eşi az bulunur ve kapısı \"\n\"daima herkese açıktır.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Gillian harika bir kadın. Neşeli hali ve kahkahasıyla çok sevilen Gillian, \"\n\"kalbimde özel bir yere sahiptir. Hasta ve seyahat edemeyecek kadar yaşlı \"\n\"olan büyükannesine destek olmak için handa çalışıyor. Bazen onun güvenliği \"\n\"için endişeleniyorum ama biliyorum ki köydeki hiçbir adam yoktur ki, kendi \"\n\"canı pahasına onun zarar görmesine engel olmasın.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Selamlar, Efendim. Gündoğan Hanına hoş geldiniz!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Şimdiye kadar çok maceracı hanımın masalarını şereflendirdi ve on katı daha \"\n\"fazla hikaye, bir o kadar biranın üstüne anlatıldı, dinlendi. Bu kadar \"\n\"kişinin hemfikir olduğu sadece tek bir şey duydum, bir atasözü. Belki bu, \"\n\"size yardımcı olur. Eti kesebilirsin ama kemiği ezmek zorundasın.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Demirci Griswold silahlar ve zırhlar hakkında son derece bilgilidir. Eğer \"\n\"eşyalarınız ile ilgili yaptırmanız gereken işleriniz varsa, görmeniz gereken \"\n\"kişi kesinlikle odur.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Farnham burada fazlasıyla zaman geçiriyor, ucuz birayla kederlerini boğarak… \"\n\"Onu gönderirdim ama Labirentte başına gelenler çok fenaydı.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Adria yaşıtlarından çok daha bilge ama itiraf etmeliyim - beni biraz \"\n\"korkutuyor.\\n\"\n\"\\n\"\n\"Neyse, önemli değil. Eğer büyü ile ilgili eşyalar almanız gerekiyorsa, \"\n\"nehrin hemen karşısında şaşırtıcı derecede iyi mallarının olduğu bir \"\n\"kulübesi var.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Köyümüzün tarihini daha fazla öğrenmek istiyorsanız, öykücü Cain geçmiş \"\n\"hakkında oldukça fazla şey biliyor.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Wirt yaramaz ve küçük bir düzenbazdır. Başını hep belaya sokardı bu yüzden \"\n\"de başına gelenler şaşırtmıyor.\\n\"\n\"\\n\"\n\"Muhtemelen gezinmemesi gereken bir yerde geziniyordur. O oğlana acıyorum ama \"\n\"etrafındaki arkadaş çevresini onaylamıyorum.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Pepin iyi bir adam - ve kesinlikle köydeki en cömert kişi. Daima \"\n\"başkalarının ihtiyaçlarıyla ilgilenir ama nereye gitse bir bela da onu takip \"\n\"ediyor…\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Garsonum Gillian mı? Kendini büyükannesinin bakımına adamasa, çoktan buradan \"\n\"kaçmış olurdu.\\n\"\n\"\\n\"\n\"Tanrı biliyor, ona gitmesi için yalvardım, yaşlı kadına benim bakacağımı \"\n\"söyledim ama o çok tatlı ve ilgili olduğu için böyle bir şey yapmadı.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Seni rahatsız eden nedir, dostum?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Çok ilginç bir şey keşfettim. Bizim aksimize, Labirentteki yaratıklar iksir \"\n\"veya büyü yardımı olmadan kendilerini iyileştirebiliyorlar. Eğer bir \"\n\"canavarı yaralarsan, öldüğünden emin ol yoksa kendini tamamen \"\n\"iyileştirebilir.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"Katedral, altında yatan şey(artık o şey her ne ise) tarafından ele \"\n\"geçirilmeden önce, büyük bir ilim yuvasıydı. Orada birçok kitap bulunabilir. \"\n\"Eğer herhangi bir kitap bulursan, mutlaka okumalısın, çünkü bazıları \"\n\"Labirentin işleyişi hakkında önemli bilgiler içeriyor olabilir.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Griswold, savaş sanatı hakkında benim şifa sanatı hakkında bildiğim kadar \"\n\"çok şey biliyor. O açıkgöz bir tüccar, ancak zanaatı eşsiz. Ah, belki de bu, \"\n\"kasabada kalan tek demirci olmasındandır.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Cain gerçek bir dost ve arif bir bilgedir. Çok geniş bir kütüphaneye sahip \"\n\"ve birçok şeyin gerçek doğasını ayırt etme konusunda doğuştan bir yeteneğe \"\n\"sahip. Eğer herhangi bir sorun olursa, başvurman gereken kişi odur.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Benim yeteneklerim bile Farnhamı tamamen iyileştirmeye yetmedi. Ah, bedenini \"\n\"iyileştirebildim ama aklı ve ruhu benim hünerimin ötesinde.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Burda iksirlerimi yapmak için bazı cüzi büyüler kullanıyorum ama Adria \"\n\"gerçek bir büyücüdür. Hiç uyumuyor gibi görünüyor ve her zaman birçok mistik \"\n\"kitap ve esere erişimi var. Kulübesinin göründüğü kadar basit bir yer \"\n\"olmadığını düşünüyorum ama içini hiç göremedim.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Zavallı Wirt. Onun için elimden geleni yaptım ama biliyorum ki takmak \"\n\"zorunda kaldığım o tahta bacaktan nefret ediyor. Yaraları çok korkunçtu. Hiç \"\n\"kimse - ve özellikle de böyle genç bir çocuk - onun çektiği acıları \"\n\"çekmemeli.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Ogdenın Tristramda neden kaldığını gerçekten anlamıyorum. Hafif bir \"\n\"gerginlik problemi var ama zeki olduğu kadar çalışkan bir adam ve nereye \"\n\"giderse gitsin başarılı olacağı da kesin. Sanırım çevredeki kırsalda \"\n\"gerçekleşen cinayetlerden duyduğu korku, ya da belki de eşinin isteği onu ve \"\n\"ailesini burada tutuyor olabilir.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Ogdenın garsonu tatlı bir kız. Büyükannesi oldukça hasta ve sanrılar \"\n\"görüyor.\\n\"\n\"\\n\"\n\"Bu görüntülerin önsezi olduğunu iddia ediyor ama bunun ne doğruluğuna ne de \"\n\"yanlışlığına dair ne bir kanıtım var.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"İyi günler! Sana nasıl hizmet edebilirim?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Büyükannem senin gelip benimle konuşacağını rüyasında görmüştü. Biliyorsun, \"\n\"önsezileri var ve geleceği görebiliyor.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Kasabanın ucundaki kadın bir cadı! Adı Adria, kulağa oldukça hoş geliyor ve \"\n\"yeterince nazik görünüyor ama ondan çok korkuyorum.\\n\"\n\"\\n\"\n\"Onun orada ne yaptığını görmek için senin gibi oldukça cesur biri olmak \"\n\"gerekiyor.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Demircimiz Tristram halkı için bir gurur kaynağıdır. Sadece loncasında \"\n\"birçok yarışma kazanmış usta bir zanaatkar değil, aynı zamanda Kralımız \"\n\"Leoricin bizzat övgülerini de almıştır - ruhu şad olsun. Griswold aynı \"\n\"zamanda büyük bir kahramandır; Caine sorabilirsin.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Cain, bildim bileli Tristramın öykücüsüdür. Çok şey biliyor ve hemen hemen \"\n\"her şey hakkında size neredeyse her şeyi anlatabilir.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Farnham, karnını bira, başkalarının kafasını da saçmalıklarla dolduran bir \"\n\"ayyaştır.\\n\"\n\"\\n\"\n\"Pepin ve Ogdenın ona sempati duyduklarını biliyorum ama her gece daha da \"\n\"şaşkın bir sersemlik içine düştüğünü izlemek beni sinir ediyor.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Pepin büyükannemin hayatını kurtardı, bunun karşılığını asla ödeyemeyeceğimi \"\n\"biliyorum. Onun herhangi bir hastalığı iyileştirme yeteneği en güçlü \"\n\"kılıçtan bile daha güçlü ve aklına gelebilecek herhangi bir büyüden de daha \"\n\"gizemlidir. Eğer bir gün şifaya ihtiyaç duyarsan, Pepin sana yardımcı \"\n\"olabilir.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Wirtün annesi Canace ile birlikte büyüdüm. Korkunç yaratıklar Wirtü \"\n\"çaldığında, Canace sadece hafifçe yaralanmıştı ama asla iyileşemedi. Bence \"\n\"kahrından öldü. Wirt, başkalarının alın terinden kazanç sağlamaya çalışan \"\n\"kötü niyetli bir delikanlı haline geldi. Acı çektiğini ve hayal bile \"\n\"edemeyeceğim dehşetleri gördüğünü biliyorum ama o karanlığın bir kısmı hala \"\n\"onun üzerinde geziyor gibi.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Ogden ile karısı beni ve büyükannemi evlerine aldılar ve handa çalışarak \"\n\"biraz para kazanma şansı verdiler. Onlara çok şey borçluyum. Bir gün buradan \"\n\"ayrılıp onlara doğuda büyük bir otel açmalarında yardımcı olmayı umuyorum.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Eh, senin için ne yapabilirim?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"İyi bir silah arıyorsan, sana bunu göstereyim. Ağır bir şey al, mesela bir \"\n\"topuz. Aşağıdaki ölümsüz dehşetlerin çoğuna karşı harikalar yaratır ayrıca \"\n\"incecik iskeletleri parçalamak için daha iyisini bulamazsın!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Balta mı? Evet, iyi bir silah, her düşmana karşı dengelidir. Havayı nasıl \"\n\"yarıp geçtiğine bak ve ardından önüne güzelce şişman bir iblis kafası \"\n\"çıktığını hayal et. Tabi, sallamasının zor olduğunu unutma - ama burda ağır \"\n\"bir darbe indirmekten bahsediyoruz!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Şu keskinliğe, şu dengeye bak. Doğru ellerde ve doğru düşmana karşı bir \"\n\"kılıç, tüm silahların efendisidir. Keskin bıçağı yaşayan ölülerde pek bir \"\n\"şey bulamaz, ancak yaşayan, nefes alan bir düşmanın etlerini kılıç çok daha \"\n\"iyi dilimler!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Silahların ve zırhların, karanlığa karşı verdiğin mücadelelerin izlerini \"\n\"gösterecektir. Onları bana getirirsen, biraz emek ve sıcak bir ocakla, \"\n\"onları ilk hallerine geri getirebilirim.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Gerekli metalleri ve aletleri, lanetli kasabamızın kenarından geçen \"\n\"kervanlardan neredeyse kaçak olarak getirirken, cadı Adria her zaman neye \"\n\"ihtiyacı varsa elde edebiliyor gibi duruyor. Büyüyü onun kullandığının çok \"\n\"azı kadar bile bilsem, gerçekten inanılmaz şeyler yapabilirdim.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Gillian tatlı bir kız. Yazık ki büyükannesi çok hasta, yoksa ikisini de \"\n\"buralardan geçen kervanlardan biriyle buradan gönderirdim.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Bazen Cainin fazla konuştuğunu düşünüyorum ama sanırım onun bu hayatındaki \"\n\"görevi de o. Çeliği onun kulaklarını büktüğü kadar iyi bükebilseydim, \"\n\"imparatorlara layık zırhlar bile yapabilirdim!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Lazarusun bizi Labirente götürdüğü o gece Farnham ile birlikteydim. \"\n\"Başpiskoposu bir daha hiç görmedim ve Farnham yanımda olmasaydı belki de \"\n\"hayatta kalamazdım. O gece aldığımız yaralar benim bacağımı sakatladığı gibi \"\n\"onun da ruhunu sakatladı. Artık onun için savaşamam ama savaşabilseydim \"\n\"kesinlikle bunu yapardım.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Başkalarının ihtiyaçlarını kendi ihtiyaçlarının üstünde tutan iyi bir adam. \"\n\"Tristramda - ya da başka bir yerde - şifacı hakkında kötü bir şey söyleyen \"\n\"kimse bulamazsınız.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"O çocuk kendini ciddi bir belaya sokacak… ya da yine sokacak demeliyim \"\n\"sanırım. Onu burada çalışmaya ve dürüst ticaret öğrenmeye ikna etmeye \"\n\"çalıştım ama nerden geldiği şüpheli mallarla uğraşıp yüksek kâr etmeyi \"\n\"tercih ediyor. Başına gelenlerden sonra ona kızamıyorum ama en azından \"\n\"dikkatli olmasını diliyorum.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"Hancının pek işi olmuyor ve kâr da edemiyor. Köye ara sıra uğrayanlara \"\n\"yiyecek ve konaklama sağlayarak geçimini sağlıyor ama onların geceleyin \"\n\"gizlice kaçma ihtimalleri, en az ödeme yapmaları kadar muhtemel. Mahzeninde \"\n\"tuttuğu tahıl ve kurutulmuş et stokları olmasaydı, köyün çevresi iblisler \"\n\"tarafından sarıldığında çoğumuz ilk yıl açlıktan ölürdük.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Huzur içinde bir yudum içemez miyiz?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"\"\n\"İçecekleri getiren kız mı? Ah, evet, ne kadar güzel bir bayan. Çok da nazik.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Neden o yaşlı kocakarı bir şeyler yapmıyor artık? Tamam, tamam, onda bir \"\n\"şeyler var ama beni dinle… o doğaüstü biri. Onun yemek yediğini ya da \"\n\"içtiğini hiç görmedim - ve en birazcık bile içmeyen birine güvenemezsin.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Cain, söylediği gibi biri değil. Tamam, tamam, iyi hikayeler anlatıyor… \"\n\"bazıları gerçekten korkutucu ya da komik… ama bence bildiğinden daha \"\n\"fazlasını biliyor.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Griswold mu? Ah bizim Griswold. Onu bir kardeş gibi seviyorum! Birlikte \"\n\"savaştık, biliyorsun, o zamanlar… biz… Lazarus… Lazarus… Lazarus!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Hehehe, Pepini severim. Bilirsin, gerçekten çabalıyor. Dinle bak, onunla \"\n\"tanıştığına emin ol. Yardıma ihtiyacı olanlara yardım itmeyi seven iyi bir \"\n\"adam. Kahraman, seni de seviyor gibiyim ne dersin? Ben de ordaydım…\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"Wirt benden bile fazla dertleri olan bir çocuk ve inan bana ben çok dertli \"\n\"biriyimdir. Dinle bak - o çocukta bir şeyler var ama o da ordaydır, \"\n\"biliyorsun değil mi? Bacağını kaybetti! Artık bir parça tahtayla gezmek \"\n\"zorunda. Üzücü, çok üzücü…\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Ogden kasabadaki en iyi adamdır. Sanırım karısı beni pek sevmiyor ama \"\n\"kadehimi doldurduğu sürece sorun yok, ben onu severim. Galiba Ogden ile \"\n\"herkesten çok ben vakit geçiriyorum ama bana çok iyi davranıyor.\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Sana bişey söyleyeyim, bunları en iyi ben bilirim. Benim uzmanlığım bu. \"\n\"Burdaki en iyisi… eeeeen iyisi! O diğer bira hiç güzel değil, aptal köpekler \"\n\"yüzünden…\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Beni kimse din… dinlemez. Bir yerlerde - tam emin değilim - ama kilisenin \"\n\"altında bir yerlerde yığınla altın var. Parlıyor ve ışıldıyor ve birinin \"\n\"almasını bekliyor.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Senin de kendi fikrin olabilir, ve biliyorum bana inanmayacaksın ama senin \"\n\"bu silahın - o büyük yabanilere karşı hiç iyi değil. Ah, Griswold ne diyor \"\n\"umrumda değil, eskiler gibi yapamıyorlar.\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Senin yerinde olsam… ama değilim… ama olsam, elimdeki her şeyi satıp buradan \"\n\"defolurdum. Ordaki çocuk… Hep iyi bir şeyleri olur ama sana göstermesi için \"\n\"bile para vermen lazım yoksa sana göstermez.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Sorularına cevap arayan bir ruh seziyorum…\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Bilgelik kazanılır, verilmez. Eğer bir ilim kitabı bulursan, yala yut. Eğer \"\n\"kitapta yazılı olan esrarlı sırları zaten biliyorsan, unutma - ustalık \"\n\"seviyen her zaman artabilir.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"En güçlüler genellikle kısa yaşar. Deri parşömenlere yazılmış eski güç \"\n\"sözcükleri bulabilirsin. Bu parşömenlerin gücü, hem çırakların hem de \"\n\"ustaların onları eşit yetenekle kullanabilmesindedir. Zayıflıkları ise önce \"\n\"yüksek sesle okunmaları gerektiği ve asla ezberlenememeleridir. Ayrıca bu \"\n\"parşömenlerin yalnızca bir kez okunabileceğini de bil, bu yüzden onları \"\n\"dikkatle kullan.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Güneşin sıcağı ölçüleyemeyecek kadar fazla olsa da, sıradan bir mum alevi \"\n\"daha tehlikedir. Ne kadar büyük olursa olsun hiçbir enerji düzgün bir \"\n\"şekilde odaklanmadan kullanılamaz. Çoğu büyü için, belirli sayıda büyü yükü \"\n\"olan Asalar vardır. Kullandığın asaların yüklerini yenileyebilirim - ama \"\n\"unutma ki hiçbir şey bir bedel olmadan yapılmaz.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Bildiklerimiz, tanıdığımız insanlarının toplamıdır. Eğer ne olduğunu \"\n\"anlayamadığım bir kitap veya parşömen bulursan, bana getirmekte tereddüt \"\n\"etme. Anlayabilirsem sana da aktaracağım.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Sadece demiri bilen bir adam için çelikten daha büyük bir sihir yoktur. \"\n\"Demirci Griswold, bir büyücüye tahmin ettiğinden çok daha fazla benzer. \"\n\"Ateşle metali birleştirme yeteneği bu topraklarda eşsizdir.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Yozlaşma aldatmanın gücüne sahiptir ama saflığın gücünü taşıyan \"\n\"masumiyettir. Genç kadın Gillianın tertemiz bir kalbi var, büyükannesinin \"\n\"ihtiyaçlarını kendi ihtiyaçlarının önüne koyuyor. Benden korkuyor ama bu \"\n\"bunun nedeni beni anlamaması.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Karanlıkta açılan bir sandıktan çıkan hazine, aydınlıkta açılandan daha \"\n\"değerli değildir. Öykücü Cain sadece bakmayanlar için bir muammadır. \"\n\"Katedralin altında yatanlar hakkında bildikleri, kendisinin fark ettiğinden \"\n\"çok daha fazladır.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Bir insana olan inancınız ne kadar yüksekse, düşeceği yer o kadar aşağısı \"\n\"olur. Farnham ruhunu kaybetti lakin bir iblise değil. Ruhunu, Başpiskopos \"\n\"Lazarus tarafından ihanete uğrayan kasabalıları gördüğünde kaybetti. Ondan \"\n\"öğrenilecek bilgiler var ama gerçeği hayalden ayırabiliyor olmalısın.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"El, kalp ve zihin mükemmel uyum içinde olduklarında mucizeler \"\n\"gerçekleştirebilir. Şifacı Pepin, vücuda benim bile yapamadığım bir şekilde \"\n\"bakar. Hastaları ve yaralıları iyileştirme hüneri, iksirler ve ilaçlar \"\n\"yaratma konusundaki hakimiyeti ile artmıştır. Tristramda sahip olabileceğin \"\n\"en büyük müttefiklerden biridir.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Gelecek hakkında göremediğimiz çok şey var ama geldiğinde onu çocuklar \"\n\"şekillendirecek. Wirt adlı çocuğun ruhunda bir karanlık var ama kasaba veya \"\n\"halkı için bir tehdit oluşturmuyor. Komşu kasabalardaki serseriler ve \"\n\"bilinmeyen loncalarla yaptığı gizli anlaşmalar, Tristramda kolay \"\n\"bulunamayacak birçok eşyaya erişim sağlıyor. Yöntemleri eleştirilebilir olsa \"\n\"da, Wirt yaklaşan Karanlıkla olan savaşında sana yardım edebilir.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Evi yapan, toprak duvarları ve sazdan çatısı değildir. Hancı Ogden, birçok \"\n\"kişinin anlamadığı bir amaçla bu kasabada hizmet eder. Gillian ve \"\n\"büyükannesine barınak sağlar, Farnham’ın hayatından kalanları bir arada \"\n\"tutar ve kasabada kalan herkese Tristramın bir zamanlar ne olduğunu \"\n\"hatırlatan bir çapa gibidir. Onun meyhanesi ve orada hâlâ bulunabilen basit \"\n\"zevkler, insanların hatırladığı hayatın bir hatırasını sunar. Senin başarılı \"\n\"olmanı ummalarının en büyük nedeni işte bu hatıradır.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Pssst... buraya bak…\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Tristramdaki herkesin labirentte bulacağın şeyler için bir kullanışlığı ya \"\n\"da piyasası yok. Hatta benim bile, inanması zor olsa da.\\n\"\n\"\\n\"\n\"Bazen, bulduğun şeylerin amacını sadece sen bulabilirsin.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Sarhoşun her söylediğine inanma. Çok fazla bira içmek algısını ve aklını \"\n\"bulanıklaştırdı.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Farketmediysen söyleyeyim, Tristramdan hiçbir şey almıyorum. Kaliteli mallar \"\n\"ithal ediyorum. Dandik mallar satmak istiyorsan Griswold, Pepin veya o cadı \"\n\"Adria’ya sorman gerekiyor. Onlara ne götürürsen götür havada kapacaklarına \"\n\"eminim.\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Sanırım hayatımı demirciye borçluyum - artık ne kadar kaldıysa. Evet, \"\n\"Griswold bana demircide çıraklık teklif etti, iyi de bir adam ama onunla \"\n\"asla yeterince para kazanamam… eh, belirli planlarım var diyelim ve bunlar \"\n\"çok fazla altın gerektiriyor.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Birkaç yaş daha büyük olsaydım, elde edebileceğim tüm zenginliklere boğardım \"\n\"onu, emin olabilirsin ki elimden çok güzel şeyler geçebilir. Gillian güzel \"\n\"bir kız ve güvenli olduğu ilk fırsatta Tristramdan ayrılmalı. Hmmm… belki \"\n\"giderken onu da yanıma alırım…\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Cain çok şey biliyor. Ödümü koparıyor - nehrin öte tarafındaki kadından bile \"\n\"daha çok. Bana sürekli hayatta olduğum için ne kadar şanslı olduğumu ve \"\n\"hikayemin efsanelerde nasıl müjdelendiğini söylüyor. Kafayı yemiş olabilir.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Farnham - işte ciddi sorunları olan bir adam ve böyle ciddi sorunların nasıl \"\n\"çıkabileceğini çok iyi biliyorum. Bir adamın dürüstlüğüne fazla güvendi ve \"\n\"Lazarus onu ölümün pençesine sürükledi. Ah, oraların nasıl olduğunu \"\n\"biliyorum, o yüzden bana Labirentteki kötülüğü yok etme planlarından \"\n\"bahsetmeye başlama bile. Sadece bacaklarına dikkat et…\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Sana bir şeyler takılmasına ihtiyacın yoksa, yaşlı Pepin bulabileceğin en \"\n\"iyisidir.\\n\"\n\"\\n\"\n\"Eğer o zaman elimde yaptığı iksirlerden olsaydı, belki de bacağım bende \"\n\"kalırdı.\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Adria gerçekten beni rahatsız ediyor. Tabii, Cain geçmiş hakkında sana \"\n\"anlatabilecekleriyle korkutabilir ama o cadı geçmişini görebiliyor. Her \"\n\"zaman ihtiyacı olan şeyleri elde etmenin bir yolunu da buluyor. Adriada, \"\n\"Yüksel Festival sırasında Kralın Pazarı’nın kapılarından geçen mallardan \"\n\"daha fazlası var.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Ogden burada kalmakla aptallık ediyor. Çok makul bir fiyata onu şehirden \"\n\"çıkarabilirim ama o aptal han ile iş yapmaya çalışmakta ısrar ediyor. Eh en \"\n\"azından Gilliana çalışacak bir yer sağlıyor, ayrıca eşi Garda harika Çoban \"\n\"turtaları yapıyor…\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"Kahramanların Salonunun ötesinde Kemikler Odası uzanır. Bu odada korunan \"\n\"hazineleri çalmaya çalışacak herkesi sonsuz ölüm bekler. Dehşetin Efendisi \"\n\"böyle söyler ki, böyle yazılmıştır.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"…ve böylece, Kan Geçidinin ötesine kilitlenmiş ve Ateş Salonlarının ardında, \"\n\"Yiğitlik, Işık’ın Kahramanının uyanmasını bekler…\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Senin görmediğini görebilirim,\\n\"\n\"Görüş bulanır, sonra çürür gözlerin.\\n\"\n\"Döndüğünde yok olurlar,\\n\"\n\"Gizli şarkılarını fısıldarlar.\\n\"\n\"Sonra görürsün olamayacak olanı,\\n\"\n\"ışık olması gereken yerde gölgeler dolanır.\\n\"\n\"Karanlıktan, akıldan dışarı,\\n\"\n\"Körlerin Salonları’na atılır.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Cehennemin cephanelikleri Kan Beyine ev sahipliği yapar. Ardında binlerce \"\n\"parçalanmış ceset yatar. Melekler ve insanlar sonu gelmeyen adaklarını \"\n\"gerçekleştirmek için doğranmıştır - kan için çıldıran Karanlık olanların \"\n\"adaklarını.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Kulak verin ve burada yatan gerçeklere tanıklık edin, çünkü bunlar \"\n\"Horadrimin son mirasıdır. Bildiğimiz menzillerin ötesinde, Yüce Cennetlerin \"\n\"ütopik krallıkları ile Yanan Cehennemler’in kaotik çukurları arasında devam \"\n\"eden bir savaş vardır. Bu savaşa Büyük Çatışma denir ve gökyüzündeki \"\n\"yıldızlardan daha uzun süredir devam eder ve yanar. Hiçbir taraf uzun süre \"\n\"üstünlük sağlayamaz çünkü Işık ve Karanlık güçleri, tüm yaratılış üzerinde \"\n\"tam kontrol sağlayıncaya dek sürekli mücadele eder.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Kulak verin ve burada yatan gerçeklere tanıklık edin, çünkü bunlar \"\n\"Horadrimin son mirasıdır. Yüce Cennetler ile Yanan Cehennemler arasındaki \"\n\"Ebedi Çatışma fani topraklara düştüğünde, buna Günah Savaşı dendi. Melekler \"\n\"ve Şeytanlar, insanlar arasına gizlenerek, fani gözlerden uzakta, gizlice \"\n\"savaşır. Bazı cesur ve güçlü faniler, taraflar ile ittifak kurmuş ve Günah \"\n\"Savaşı’nın gidişatını belirlemeye yardımcı olmuştur.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Kulak verin ve burada yatan gerçeklere tanıklık edin, çünkü bunlar \"\n\"Horadrimin son mirasıdır. Yaklaşık üçyüz yıl önce, Yanan Cehennemlerin Üç \"\n\"Baş Kötüsünün gizemli bir şekilde dünyamıza geldiği bilinir oldu. Üç Kardeş, \"\n\"doğu topraklarını onlarca yıl boyunca harap etti, insanlık onların ardından \"\n\"titrerken. Bizim Tarikatımız - Horadrim - gizli bir grup büyücü tarafından \"\n\"sonsuza dek Üç Şeytan’ı avlamak ve yakalamak için kuruldu.\\n\"\n\"\\n\"\n\"İlk Horadrimler, Üçün ikisini Ruh Taşları olarak bilinen güçlü eserler içine \"\n\"hapsedip onları ıssız doğu kumlarının derinliklerine gömdü. Üçüncü Kötü \"\n\"yakalanamadı ve batıya doğru kaçtı, Horadrimin çoğu da takibi sürdürdü. \"\n\"Üçüncü Kötü - Dehşet’in Efendisi olarak bilinen Diablo - nihayetinde \"\n\"yakalandı, ruhunun özü bir Ruhtaşına yerleştirildi ve bu Labirentin içine \"\n\"gömüldü.\\n\"\n\"\\n\"\n\"Ruh taşının inançsızlar tarafından keşfedilmesinden sakının. Eğer Diablo \"\n\"serbest kalırsa, zayıf olacağından kolayca kontrol edilebilecek bir beden \"\n\"arayacaktır - belki yaşlı bir adamın ya da bir çocuğun bedenini.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Böylece, Yanan Cehennemler içinde Kara Sürgün olarak bilinen büyük bir \"\n\"devrim gerçekleşti. Alt Kötüler, Üç Baş Kötüyü devirdi ve ruhlarını fani \"\n\"aleme sürgün etti. Yalanların Efendisi Belial ve Günahların Efendisi \"\n\"Azmodan, Üç Kardeş yokken Cehennemin hükümdarlığını ele geçirmek için \"\n\"savaştı. Tüm Cehennem, Belial ve Azmodanın hizipleri arasında kutuplaştı, bu \"\n\"sırada Yüce Cennetlerin güçleri sürekli olarak Cehennem Kapıları’nı dövmeyi \"\n\"sürdürdü.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Birçok iblis, Üç Kardeşi aramak için ölümlü âleme gitti. Bu iblisler, onları \"\n\"Doğu’nun geniş şehirlerinde avlayan Melekler tarafından takip edildiler. \"\n\"Melekler, kısa sürede iblis avlamada ustalaşan Horadrim adlı gizemli bir \"\n\"ölümlü büyücüler Tarikatı ile ittifak kurdular. Ayrıca yeraltında birçok \"\n\"karanlık düşman da edindiler.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Üç Yüce Kötülük, ruh formunda ölümlü âleme sürgün edildi ve Doğuda onlarca \"\n\"yıl boyunca kaos yaydıktan sonra lanetli Horadrim Tarikatı tarafından \"\n\"avlandılar. Horadrim, Nefret’in Efendisi Mephistonun ve Yıkımın Efendisi \"\n\"kardeşi Baalın özlerini hapsetmek için Ruhtaşları adı verilen eserler \"\n\"kullandı. En genç kardeş - Dehşet’in Efendisi Diablo - batıya kaçtı.\\n\"\n\"\\n\"\n\"Sonunda Horadrim, Diablo’yu da bir Ruhtaşı ile yakaladı ve onu kadim, \"\n\"unutulmuş bir Katedralin altına gömdü. Orada, Dehşetin Efendisi uyur ve \"\n\"yeniden doğuş zamanını bekler. Bilin ki o, genç ve güçlü bir bedeni ele \"\n\"geçirmek isteyecek - masum ve kolayca kontrol edilebilecek birini. Ardından \"\n\"Kardeşlerini özgür bırakmak ve bir kez daha Günah Savaşı’nın alevlerini \"\n\"körüklemek için yükselecek…\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Bütün övgüler Dehşetin Efendisi ve Karanlık Sürgünün Sağ Kalanı Diabloya. \"\n\"Uzun uykusundan uyandığında, Efendim ve Ustam bana çok az sayıda ölümlünün \"\n\"bildiği sırları anlattı. Bana Yüksek Cennetler’in krallıkları ile Yanan \"\n\"Cehennemler’in çukurlarının ebedi bir savaş içinde olduğunu söyledi. Bu \"\n\"düzensizliği insan âlemlerine getiren güçleri açıkladı. Efendim, bu dünya ve \"\n\"burada var olan herkes için yapılan savaşı Günah Savaşı olarak adlandırdı.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Şan ve Takdirler Diabloya - Dehşet’in Efendisi ve Üçün Lideri. Efendim bana \"\n\"uzun zaman önce bu dünyaya sürgün edilen kardeşleri Baal ve Mephistodan \"\n\"bahsetti. Efendim zamanını değerlendirmek ve muazzam gücünü kullanmak \"\n\"istiyor ki, doğunun kumlarının altındaki mezarlarında hapsedilmiş olan \"\n\"kardeşlerini özgür bırakabilsin. Efendim kardeşlerini serbest bıraktığında, \"\n\"Günah Savaşı bir kez daha Üçün öfkesini tadacak.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Selam ve Kurbanlar Diabloya - Dehşetin Efendisi ve Ruhların Yok Edicisi. \"\n\"Ustamı uykusundan uyandırdığımda, bir ölümlünün bedenini ele geçirmeye \"\n\"çalıştı. Diablo Kral Leoricin bedenini ele geçirmeye çalıştı, ancak Efendim \"\n\"mahpusluğundan dolayı çok zayıftı. Efendime bu dünya için basit ve masum \"\n\"vekil gerekiyordu ve bu iş için Albrecht isimli çocuğun mükemmel olduğunu \"\n\"fark etti. İyi Kral Leoric, Diablo’nun başarısız ele geçirme girişiminden \"\n\"delirmişken, ben oğlu Albrechti kaçırdım ve onu Ustama getirdim. Şimdi \"\n\"Diablo’nun çağrısını bekliyorum ve nihayet bu dünyanın Efendisi olarak \"\n\"ortaya çıktığında ödüllendirileceğimi umuyorum.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Çok şükür geri döndünüz!\\n\"\n\"Burada yaşadığınız zamandan beri çok şey değişti. Her şey huzur içindeydi ta \"\n\"ki kara süvariler gelip köyümüzü yok edene kadar. Birçok kişi olduklara \"\n\"yerde öldürüldü ve silahlananlar da ya öldürüldü ya da köle olmaya, belki de \"\n\"daha kötüsüne sürüklendi. Kasabanın kenarındaki kilise kirletildi ve \"\n\"karanlık ayinler için kullanılmaya başladı. Geceleyin yankılanan çığlıklar \"\n\"hiç insani değil ama belki kasabalıların bazıları hayatta olabilir. Kiliseyi \"\n\"bulmak için hanım ile demirci dükkanı arasında kalan yolu takip edin ve \"\n\"lütfen kurtarabileceğiniz kişileri kurtarın.\\n\"\n\"\\n\"\n\"Tekrar konuşursak belki daha fazlasını da anlatabilirim. İyi şanslar.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Görevine devam et. Kayıp bir hazineyi bulmak kolay değildir. Gizli bir \"\n\"hazineyi bulmak ise daha da zordur. Sana şu sözlerle veda ediyorum: Zamanın \"\n\"kumlarının arayışını bozmasına izin verme.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Bir ne?! Bu saçmalık. Tristramda gömülü bir hazine yok. Bir bakayım!! Ah, \"\n\"bak bu çizimler yanlış. Kasabamızla hiç uyuşmuyor. Ben olsam, toprağımızın \"\n\"altında yatanlar yerine katedralin altında yatanlara odaklanırdım.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"Aradığın haritayı konuşacak vaktim yok gerçekten. Yardımımı ve hatta senin \"\n\"yardımını gerektiren birçok hasta insan var.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Bir zamanlar gurur duyulan Iswall, bu dünyanın yüzeyinin derinliklerine \"\n\"hapsedilmiş durumda. Onurundan arındırılmış ve siması bozulmuş. Ölümsüz bir \"\n\"azap içinde tutsak kalmış. Onu özgür bırakabilecek şeyi gizlemekle \"\n\"görevlendirilmiş.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Bahse girerim Wirt sizin geldiğinizi görüp bir oyun sergiledi, sonra siz \"\n\"kasabada oyalanıp dururken arkandanız gülmek için. Ben olsam umursamazdım.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Bir zamanlar bu kasaba, her yerden gelen gezginlerin sık kullandığı bir \"\n\"uğrak yeriydi. O zamandan beri çok şey değişti. Ama gizli mağaralar ve \"\n\"gömülü hazineler, her çocuğun sıradan hayallerindendir. Wirt nadiren gençlik \"\n\"oyunlarına kapılır. O yüzden bu sadece onun hayal gücü olabilir.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Dinle, yakına gel. Benim ne bildiğimi bilip bilmediğini bilmiyorum ama \"\n\"burada gerçekten bir şey var. Bu bir harita.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Büyükannem sıklıkla kilisenin dışındaki mezarlığı işgal eden tuhaf güçler \"\n\"hakkında hikayeler anlatır. Ve bunlardan birini duymak ilgini çekebilir. \"\n\"Eğer mezarlığa uygun bir adak bırakıp, katedrale gidip ölüler için dua eder \"\n\"ve sonra geri dönersen, adağın tuhaf bir şekilde değişmiş olacağını söyledi. \"\n\"Bu sadece yaşlı ve hasta bir kadının lafları mı bilmiyorum ama bu günlerde \"\n\"her şey mümkün gibi görünüyor.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Hmm. Geniş ve gizemli bir hazine diyorsun. Mmmm. Belki senden birkaç şey \"\n\"almakla ilgilenebilirim. Ya da daha iyisi, bu zorlu süreçte sana yardımcı \"\n\"olacak nadir ve pahalı malzemelere ihtiyacın yok mu?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Demek herkesin bahsettiği kahraman sensin. Belki de fakir, basit bir \"\n\"çiftçiye korkunç bir beladan kurtulması için yardım edebilirsin, ne dersin? \"\n\"Bostanımın ucunda, buranın hemen güneyinde, yerden korkunç bir şey \"\n\"fışkırıyor! Mahsullerime veya saman balyalarıma ulaşamıyorum bu yüzden \"\n\"zavallı ineklerim aç kalacak. Cadı bana bunu verip tarlamdaki şeyi patlatıp \"\n\"yok edeceğini söyledi. Bunu yok edebilirsen, sonsuza kadar minnettar \"\n\"kalırım. Kendim yapardım ama birinin ineklere bakması gerekiyor…\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Biliyordum, cadının dediği kadar basit olamazdı. Komşularına bile \"\n\"güvenemediğin zamanlar, gerçekten üzücü bir dünya.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Gitti mi? Onu Hadesin karanlık çukurlarına geri mi gönderdin? Ne? Ah, \"\n\"kaybettiğini söyleme! Bu şeyler ucuz değil, biliyorsun. Onu bulmalı ve sonra \"\n\"o korkunç şeyi patlatarak yok edip kasabamızdan yollamalısın.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Patlamayı ta buradan duydum! Çok teşekkürler, nazik yabancı. Yerden çıkan \"\n\"bütün bu şeyler, kiliseyi ele geçiren canavarlar ve daha fazlası, zor \"\n\"zamanlardayız. Ben fakir bir çiftçiyim ama işte — bunu tüm teşekkürlerimle \"\n\"al.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Ah, başım çok fena belada… belki… Hayır, senin de başka dertlerin varken \"\n\"sana yük olamam. Belki kiliseyi o yaratıklardan temizledikten sonra geri \"\n\"dönersin… ve belki de fakir bir çiftçiye yardım etmek için biraz zaman \"\n\"ayırabilirsin, olur mu?\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Ühüüü! (hımmf) Ühüüü! (hımmf)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Theoyu kaybettim! En iyi arkadaşımı kaybettim! Nehrin kenarında oynuyorduk, \"\n\"Theo şu büyük yeşil şeye bakmak istediğini söyledi. Gitmememiz gerektiğini \"\n\"söyledim ama oraya gizlice gittik, sonra aniden bu BÖCEK çıktı! Kaçtık ama \"\n\"Theo düştü ve böcek onu YAKALADI ve götürdü!\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Onu buldun mu? Theodore’u bulman gerekiyor, lütfen! O daha küçük. Kendine \"\n\"bakamaz! Lütfen!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Bulmuşsun! Bulmuşsun! Teşekkür ederim! Ah Theo, o kötü böcekler seni \"\n\"korkuttu mu? Hey! İğrenç! Tüylerine bir şey yapışmış! Öğk! Hadi Theo, \"\n\"evimize gidelim! Tekrar teşekkürler, kahraman kişi!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Uzun süre uyuduk ve uyanma zamanı geldi. Uzun uykumuzdan sonra büyük bir \"\n\"açlıkla dolduk. Yakında, şimdi, besleneceğiz…\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Keyfin yerinde mi, küçük memeli? Ne acınası. Senin o küçük dünyan çantada \"\n\"keklik olacak.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Bu topraklar kirletilecek ve soyumuz insanların ev dediği bölgeleri istila \"\n\"edecek. Kollarımız bu dünyayı saracak ve sakinlerinin etiyle besleneceğiz. \"\n\"İnsanoğlu, malımız ve besinimiz olacak.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ah, Kokunu alıyorum… yakındasın! Yakın! Ssss… kan ve korkunun kokusu… ne \"\n\"kadar heyecanlı…\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"Altın Işık yılında, büyük bir Katedralin inşa edilmesine karar verildiği \"\n\"ilan edildi. Bu kutsal yerin köşetaşı, Horadrime gücünü paylaşan Melek’in \"\n\"adına ithafen Antyrael denen yarı saydam taştan oyulacaktı.\\n\"\n\"\\n\"\n\"Gölgelerin Çizildiği Yılda, yer sarsıldı, Katedral parçalandı ve yıkıldı. \"\n\"Yeraltı mezarlarının ve kalelerin inşası başladı ve insanoğlu, Günah \"\n\"Savaşının tahribatına karşı durduğunda, harabeler taşları için yağmalandı. \"\n\"Ve böylece, köşetaşı insanların gözlerinden kayboldu.\\n\"\n\"\\n\"\n\"Taş bu dünyaya -- ve tüm dünyalara -- aittir. Tıpkı, Işıkın da her şeyin \"\n\"içinde ve ötesinde olduğu gibi. Işık ve birlik, bu kutsal temelin \"\n\"ürünleridir, bir amaç ve mülkiyet birliği.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Möö.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Möö dedim.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Bak ben bir ineğim, tamam mı?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Peki, tamam. Aslında inek değilim. Normalde böyle dolaşmam ama evde boş boş \"\n\"oturuyordum ve bir anda yerden böcekler, dallar, otlar falan çıkmaya \"\n\"başladı… Tek kelimeyle korkunçtu! Giyecek normal bir şey bulsaydım bu kadar \"\n\"kötü olmazdı. Hey! Evime gidip elbise getirebilir misin? Kahverengi olan \"\n\"ama, gri değil, onu geceleri giyiyorum. Ben de giderdim ama konu komşunun \"\n\"beni böyle görmesini istemem. Al bunu, her şeyi kaplayan yaratıkları \"\n\"öldürmek için ihtiyacın olabilir. Evimi bulamamana imkan yok, nehrin \"\n\"çatalının güneyinde kalıyor ve hani her yeri bitki kaplı olan ev.\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Ne duruyorsun? Git bana kıyafetimi getir! Ve acele et! Şuradaki Holstein \"\n\"bana göz kırpıp duruyor!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Hey, O benim kıyafetim değil mi? Çabuk, ver onu bana! Kulaklarım fena \"\n\"kaşınıyor!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Hayır hayır hayır hayır! Bu GRİ kıyafetim! Geceleri için! Davetler için! \"\n\"BUNU giyemem. Değişik misin sen? Bana KAHVERENGİ olanı getir.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ahh, ÇOK daha iyi oldu. Oh be! Sonunda, biraz asalet! Boynuzlarım düzgün mü? \"\n\"Güzel. Yardım ettiğin için çok sağ ol. Al, hediyem olsun, ve hani anlarsın \"\n\"ya… küçük bir moda tavsiyesi... biraz ihtiyacın var gibi… yeni bir... \"\n\"anlatabiliyor muyum? Şu maceracı teması bayağı bir… demode. Kulağına küpe \"\n\"olsun, tamam mı? Ciao.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Bak. Ben bir ineğim. Ve sen, sen bir canavar yemisin. Biraz deneyim kazan! \"\n\"Sonra konuşuruz…\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Önüne gerçekten korkutucu bir görev koymuş olmalıyım. Keşke yapabileceğim \"\n\"bir şeyler olsa… Güzel, taze bir sürahi süt işine yarar mı?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"Ah, yardımına ihtiyacım olabilir ama belki de önce yeraltı mezarlarını o \"\n\"canavarların kirlerinden kurtarmandan sonra.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Yapılması gereken bir şey var ama tanımadığım birine yük olamam. Belki sen \"\n\"burada bir süre kaldıktan sonra senden bir iyilik rica ederken daha rahat \"\n\"olurum.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"İçindeki büyük potansiyeli görüyorum. Belki kaderini gerçekleştirirken bir \"\n\"ara uğrayıp bana küçük bir iyilik yapabilirsin, olur mu?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Sanırım bana yardım edebilirsin ama belki biraz daha güçlendikten sonra. \"\n\"Kilisedeki tehlikeyi yok etme şansına sahip tek kişiyi sakatlamak istemem!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Kendim, ben kendini yapmış bir ineğim. Sen biraz takıl ve… sonra konuşuruz.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Ben kendimi burdan geçen her turiste açıklamak zorunda değilim! Senin \"\n\"öldürmen gereken canavarlar yok mu? Belki sonra konuşuruz. Eğer yaşıyorsan…\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Beni rahat bırak. Gerçekten kahraman birini arıyorum. Ve sen o değilsin. \"\n\"Sana güvenemem, her an canavarlar tarafından yenilebilirsin… Tecrübeli bir \"\n\"kahraman arıyorum.\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Tamam, lafı dolandırmadan konuşayım. Seni yanlış yönlendirmek istemedim. \"\n\"Evde otururken biraz garip hissettim, sonra işler gerçekten karıştı; yerden \"\n\"bir sürü canavar fışkırdı! Direk sıvıştım. Evden kaçarken bu Jerseyi \"\n\"giyiyordum ve şimdi tamamen gülünç görünüyorum. Normal bir şeyler giysem bu \"\n\"kadar kötü olmazdı. Hey! Evime gidip benim için elbisemi alıp gelebilir \"\n\"misin? Kahverengi olanı, gri olanı değil, o akşam giysisi. Kendim yapardım \"\n\"ama bu halimle kimseye görünmek istemiyorum. Al bunu, ihtiyacın olabilir… \"\n\"her şeyi saran o şeyleri öldürmek için. Evimi kesin farkedersin, nehirdeki \"\n\"çatalın hemen güneyinde… biliyorsun… aşırı büyümüş sebze bahçesi olan.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Bu kötü yaratıkla başa çıkmak için her şeyi denedim. Büyüler, tehditler, \"\n\"yeminler ve pazarlıklar — ama hiçbiri işe yaramadı. Daha zayıf iblisleri \"\n\"köleleştirmek için kullandığım yöntemler, bu korkutucu canavara hiç etki \"\n\"etmiyor.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Evim, bu istenmeyen tutsağın kötülüğü tarafından yavaş yavaş kirletiliyor. \"\n\"Türbeler, görüşümün köşelerinin hemen ötesinde hareket eden gölgelerle dolu. \"\n\"Pençelerin tırmalama sesleri işitme sınırlarımın kenarlarında dans ediyor. \"\n\"Sanırım, bu günlüğü arıyorlar.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"Canavarın sayıklarken adını ağzından kaçırdı — Na-Krul. Bu adı araştırmaya \"\n\"çalıştım ama küçük iblisler kütüphanemi bir şekilde yok ettiler. Na-Krul… Bu \"\n\"isim beni soğuk bir korkuyla dolduruyor. Onu gerçek adıyla değil, sadece \"\n\"Canavar olarak düşünmeyi tercih ederim.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Tutsak edilmiş yaratığın öfke dolu ulumaları, çok ihtiyacım olan uykuyu \"\n\"almamı engelliyor. Onu Boşluğa gönderen kişiye karşı öfke kusuyor ve burada \"\n\"tutsak ettiğim için bana lanetler yağdırıyor. Sözleri kalbimi dehşetle \"\n\"dolduruyor, ancak sesini engelleyemiyorum.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"Vaktim hızla tükeniyor. İblisi zayıflatmanın yollarını kaydetmeli ve sonra \"\n\"bu metni saklamalıyım, yoksa hizmetkarları bilgimi kullanarak efendilerini \"\n\"serbest bırakmanın bir yolunu bulabilirler. Umarım bu günlüğü bulan kişi \"\n\"ilimin peşinden gider.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Bu parşömeni bulan kişi herkimse, bu duvarların içinde yatan şeytani \"\n\"yaratığı durdurmakla görevlidir. Benim vaktim doldu. Hatta şimdi bile, \"\n\"cehennemin hizmetkarları arkasına saklandığım güçsüz kapıyı tırmalıyor.\\n\"\n\"\\n\"\n\"İblise büyülü güçlerle engel oldum ve büyük duvarlar içinde hapsettim ama \"\n\"bunun yeterli olmayacağından korkuyorum.\\n\"\n\"\\n\"\n\"Üç karabüyü kitabımda bulunan büyüler, doğru sırayla yapıldığında onun \"\n\"alanına korunaklı bir giriş sağlayacaktır. Girişteki kollar, engelleri \"\n\"kaldırır ve iblisi serbest bırakır; onlara dokunma! Giriş sağlamak için \"\n\"sadece bu büyüleri kullan, yoksa gücü yenebileceğinden fazla olabilir.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Cehennem Domuzu\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Isırgan\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Psikoküre\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Örücü\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Leş İkiz\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Öğürük\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Zehir Kuyruk\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Ölümtopu\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Örümcek Lord\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Kamçı Solucanı\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Meşaleci\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Cehennem Böceği\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Mezarkazan\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Türbe Faresi\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Ateş Yarasası\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Kurukanat\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Hortlak\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Türbe İblisi\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Cehennem Yarasası\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Kemik İblisi\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Baş Hortlak\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Çiftkafa\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Etli Şey\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Hasatçı\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Devin Muştası\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Civa Yüzük\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Xorinein Yüzüğü\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Karikin Yüzüğü\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Magma Yüzüğü\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Mistiklerin Yüzüğü\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Şimşek Yüzüğü\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Muhafaza Muskası\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Tatarcık İğnesi\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Alevgili\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Kasvet Zırhı\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Yanardöner\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Şimşekçırpma\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Shirotachi\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Ruhları Yiyen\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Elmaskenar\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Kemik Zinciri Zırh\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"İblis Plaka Zırh\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Mürit Muskası\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Gladyatörün Yüzüğü\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Soytarı\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Kristalli\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Kopya\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"kahreden\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"çürüyen\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"risk\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Mana\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Büyücüler\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Soytarı\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Yıldırım Duvarı\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Tutuşturma\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Geçiş\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Yansıt\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Çıldırtma\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Ateş Halkası\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Bulma\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Ateş Rünü\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Yıldırım Rünü\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Parlama Rünü\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Tutuşturma Rünü\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Taş Rünü\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"Gamma’yı Düşür\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"Gamma’yı Yükselt\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"Kasabada Yeniden Başla\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Yere bir eşya mı düşürmeye çalışıyorsun?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"Dikey Senkronizasyonu aktifleştirir. Kareler çizilirken yırtılma efekti \"\n#~ \"oluşmasını önler. Devredışı bırakmak bazı sistemlerde fare gecikmesini \"\n#~ \"iyileştirebilir.\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"FPS Limiti\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"\"\n#~ \"İşlemciye aşırı yüklenmemek için FPS limitlenmiştir. Limit yenileme \"\n#~ \"hızına dikkat eder.\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"Vuruş şansı\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Yürek\"\n"
  },
  {
    "path": "Translations/uk.po",
    "content": "# Translation of DevilutionX to Ukrainian\n# Oleksandr Kalko (tsunami_state) <tsunami.wave@ukr.net>, 2021.\n# @SourceCodeDeleted, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:21+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Oleksandr Kalko (tsunami_state) <tsunami.wave@ukr.net>\\n\"\n\"Language-Team: \\n\"\n\"Language: uk\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && \"\n\"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\\n\"\n\"X-Generator: Poedit 3.7\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"Дизайн Гри\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"Старші Дизайнери\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"Додатковий Дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"Головний Програміст\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"Старші Програмісти\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"Програмісти\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"Спеціальні Гості-Програмісти\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Програмісти Battle.net\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"Програмісти Послідовних Комунікацій\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"Програмісти Інсталлятору\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"Художні Керівники\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"Художники\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"Технічні Художники\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"Художні Керівники Роликів\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D Художники Роликів\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"Технічний Художник Роликів\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"Виконавчий Режисер\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"Режисер\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"Помічник Режисера\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"Diablo Strike Team\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"Музика\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"Звуковий Дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"Музика і Звуки в Роликах\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"Звуковий Продюсер, Режисер і Кастинг\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"Сценаристи\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"Редактор Озвучування\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"Актори Озвучування\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"Інженер Запису\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"Дизайн і Компонування Інстркуції\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"Художники Інструкції\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"Тимчасовий Керівник QA (Головний Тестер)\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"Десант QA (Тестери)\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"Спецпідрозділ QA (Тестери Сумісності)\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"Артилерійська Підтримка QA (Додаткові Тестери) \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"Контррозвідка QA\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"Орден Інформаційних Сервісів Мережі\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"Підтримка Клієнтів\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"Продажі\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Дурень\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Бек-вокал Мр-а. Дабірі\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"Зв'язки з Громадськістю\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"Маркетинг\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"Міжнародні Продажі\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"Продажі в США\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"Виробництво\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"Юристи\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"Особлива Подяка\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"Дякуємо\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"В пам'ять про\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"Дуже Особлива Подяка\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"Генеральний Менеджер\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"Розробка\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"Художній Керівник\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"Художники\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"Дизайн\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"Дизайнер Звуку і Аудіо\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"Керівник Забезпечення Якості\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"Тестери\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"Інстркуція\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\tДодаткова Робота\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"Написання Текстів для Квестів\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"Дякуємо\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\tОсоблива подяка Blizzard Entertainment\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"Менеджер Забезпечення Якості\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"Головний Тестер Забезпечення Якості\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"Основні Тестери\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"Додаткові Тестери\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"Менеджер Маркетингу Продукту\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"Менеджер Зв'язків з Громадськістю\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"Помічник Менеджера Продукту\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"Коло Однієї Тисячі\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\tПід час створення цієї гри не було продано ні однієї душі.\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"ОК\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"Виберіть Клас\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"Відміна\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"Новий Герой для Мережевої Гри\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"Новий Герой\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"Збереження Існує\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"Завантажити Гру\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"Нова Гра\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"Герої\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"Пройдисвітка і Чаклун доступні тільки в повній версії Diablo. Зайдіть на \"\n\"https://www.gog.com/game/diablo щоб купити її.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"Введіть Ім'я\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"\"\n\"Недійсне ім'я. Воно повинне не мати пробіли, спеціальні символи або ключові \"\n\"слова.\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"Неможливо створити героя.\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"Рівень:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"Сила:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"Магія:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"Спритність:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"Живучість:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"Збереження:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"Виберіть Героя\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"Новий Герой\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"Стерти\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"Герої Мережевої Гри\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"Стерти Героя для Мережевої Гри\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"Стерти Героя\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"Ви впевнені, що хочете стерти героя \\\"{:s}\\\"?\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"Грати Одному\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"Грати в Мережі\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"Налаштування\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"Підтримка\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"Показати Авторів\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"Вийти з Hellfire\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"Вийти з Diablo\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"Демо-версія\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"Клієнт-Сервер (TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"Офлайн\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"Гра в Мережі\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"Вимоги:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"шлюз не потрібен\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"Виберіть З'єднання\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"Змінити шлюз\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"Всі комп'ютери мають бути з'єднані через TCP мережу.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"Всі комп'ютери мають бути під'єднані до Інтернету.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"Грайте самостійно без доступу до мереж.\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"Підтримується Гравців: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"Демо-версія Diablo\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"Демо-версія Hellfire\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"На сервері запущена інша гра.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"На сервері запущений інший режим гри ({:s}).\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"\"\n\"Ваша версія {:s} несумісна з версією {:d}.{:d}.{:d} що присутня на сервері.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"Описання:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"Виберіть\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"Створити Гру\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"Відкрита Гра\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"Приєднатися\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"Відкриті Ігри\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"Завантажується…\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"Немає\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"СКАСУВАТИ\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"Створити нову гру з вибором рівня важкості.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"Створити нову відкриту гру без паролю з вибором рівня важкості.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"Введіть ID Гри і приєднайтесь до вже запущеної гри.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"Введіть IP адресу або ім'я домену і приєднайтесь до вже запущеної гри.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"Приєднайтесь до відкритої гри, яка вже запущена.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"Нормальна\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"Кошмарна\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"Пекельна\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"Складність: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"Швикість: Нормальна\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"Швидкість: Швидка\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"Швидкість: Дуже Швидка\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"Швидкість: Найшвидша\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"Гравці: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"Виберіть Складність\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"Приєднатися до {:s} Гри\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"Введіть ID Гри\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"Введіть адресу\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нормальна Складність\\n\"\n\"Рекомендується для нових героїв, що хочуть перемогти Діабло.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Кошмарна Складність\\n\"\n\"Мешканці Лабіринту стали сильніші і їх буде важче перемогти. Рекомендується \"\n\"тільки для досвідчених героїв.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"Пекельна Складність\\n\"\n\"Наймогутніші пекельні створіння підстерігають Вас біля воріт в Пекло. Тільки \"\n\"найбільш досвідчені герої відважаться підти туди.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"\"\n\"Ваш герой має бути 20 рівня щоб приєднатися до мережевої гри Кошмарної \"\n\"складності.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"\"\n\"Ваш герой має бути 30 рівня щоб приєднатися до мережевої гри Пекельної \"\n\"складності.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"Виберіть Швидкість Гри\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"Швидка\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"Дуже Швидка\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"Найшвидша\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"Нормальна Швидкість\\n\"\n\"Рекомендується для нових героїв, що хочуть перемогти Діабло.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"Мешканці Лабіринту стали швидше і їх буде важче перемогти. Рекомендується \"\n\"тільки для досвідчених героїв.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"Дуже Швидка Швидкість\\n\"\n\"Монстри підземелля вишукують тебе набагато швидше. Тільки досвідчені \"\n\"чемпіони спробують удачу на цій швидкості.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"Найшвидша Швидкість\\n\"\n\"Служники Пекла відразу атакують без будь-яких вагань. Тільки справжні \"\n\"безумці будуть встигати за ними.\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"Введіть Пароль\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"Зайти в Hellfire\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"Перейти в Diablo\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"Так\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"Ні\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"Натисніть на кнопку геймпада щоб змінити.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"Прив'язана клавіша:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"Натисніть на бажану клавішу.\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"Прив'язати клавішу\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"Прив'язана комбінація кнопок:\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"Відв'язати комбінацію кнопок\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"Попереднє Меню\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"У нас є чат-сервер за адресою Discord.gg/devilutionx Переходьте по \"\n\"посиланням, щоб приєднатися до нашої громади, де ми розмовляємо про Diablo \"\n\"та розширення Hellfire.\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX підтримується Diasurgical, задавайте питання та пишіть про \"\n\"помилки за цією адресою: https://github.com/diasurgical/devilutionX Не \"\n\"забудьте включати номер версії, операційну систему і опис помилки, щоб ми \"\n\"могли швидше її вирішити.\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"Відмова від відповідальності:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\tDevilutionX не розробляється і не підтримується Blizzard Entertainment або \"\n\"GOG.com. Ні Blizzard Entertainment, ні GOG.com не перевіряли якість або \"\n\"сумісність DevilutionX. Всі питання зв'язані з DevilutionX мають бути \"\n\"адресовані Diasurgical, а не Blizzard Entertainment або GOG.com.\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\tЦей порт використовує шрифти Charis SIL, New Athena Unicode, Unifont, та \"\n\"Noto, що ліцензовані під SIL Open Font License, а також Twitmoji, що \"\n\"ліцензований під CC-BY 4.0. Порт також використовує SDL що ліцензований під \"\n\"zlib-ліцензією. Дивіться файл ReadMe щоб дізнатися більше.\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Авторські права © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"Помилка\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"Сталася помилка в файлі: {:s}, лінія {:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"Помилка Файлу Даних\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"Неможливо відкрити архів даних ({:s}).\\n\"\n\"\\n\"\n\"Впевніться, что він знаходиться в папці зі грою.\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"Папка доступна тільки для читання\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"Неможливо писати дані в:\\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"Гра: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"Офлайн Гра\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"Пароль: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"Відкрита Гра\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"Рівень: Гніздо {:d}\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"Рівень: Склеп {:d}\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"Місто\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"Рівень: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"Інформація про Героя\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"Журнал\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"Автокарта\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"Головне Меню\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"Інвентар\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"Книга Чар\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"Відправити Повідомлення\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"Доступні Команди:\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"Команда \"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \" невідома.\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"Опис: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"Параметри: Додаткові параметри не потрібні.\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"Параметри: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"Арени підтримуються тільки в мережевій грі.\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"Яку арену ви хочете відвідати?\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"Невірний номер арени. Допустимі номери:\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"Щоб потрапити на арену, треба бути в місті або іншій арені.\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"Огляд гравців підтримується тільки в мережевій грі.\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"Припинив огляд гравців.\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"Гравців з таким ім'ям не знайдено\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"Огляд гравця: \"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"Друкує огляд довідки або довідку для конкретної команди.\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[команда]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"Зайти на PvP-арену.\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<номер-арени>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"Дає Зілля Арени.\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<номер>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"Оглядає статистику та спорядження іншого гравця.\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<ім'я гравця>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"Показати інформацію про початкові значення ГВЧ для поточного рівня.\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"Дружній гравець\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"Гравець атакує\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"Гаряча клавіша: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"Виберіть кнопку для чар\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"Гаряча клавіша: 's'\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s} Талант\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"Чари {:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"0-овий Рівень Чар - Невикористовні\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"Рівень Чар {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"Сувій {:s}\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d} Сувій\"\nmsgstr[1] \"{:d} Сувія\"\nmsgstr[2] \"{:d} Сувоїв\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"Посох {:s}\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d} Заряд\"\nmsgstr[1] \"{:d} Заряда\"\nmsgstr[2] \"{:d} Зарядів\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s} золота монета\"\nmsgstr[1] \"{:s} золоті монети\"\nmsgstr[2] \"{:s} золотих монет\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"Вимоги не виконані\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, Рівень {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"Здоров'я {:d} з {:d}\"\n\n#: Source/control.cpp:1525\nmsgid \"Right click to inspect\"\nmsgstr \"Правий клік щоб оглянути\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"Новий Рівень\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"Ви померли\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"ESC\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"Кнопка Меню\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"Натисніть {}, щоб завантажити останнє збереження.\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"Натисніть {}, щоб повернутися до Головного Меню.\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"Натисніть {}, щоб перезапуститися в Місті.\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"У тебе {:s} золота монета. Скільки ти хочеш забрати?\"\nmsgstr[1] \"У тебе {:s} золоті монети. Скільки ти хочеш забрати?\"\nmsgstr[2] \"У тебе {:s} золотих монет. Скільки ти хочеш забрати?\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"Портал в Місто\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"з {:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"Портал в\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"Нечестивий Вівтар\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"рівень 15\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"Не вдалося завантажити дані з файлу {0}\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} є неповним, будь ласка, перевірте вміст файлу.\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\"Ваш файл {0} не містить очікуваних стовпців, будь ласка, переконайтеся, що \"\n\"він відповідає задокументованому формату.\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Нечислове значення {0} для {1} у {2} у рядку {3} та стовпчику {4}\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\"Значення поза діапазоном {0} для {1} в {2} в рядку {3} та стовпчику {4}\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"Невірне значення {0} для {1} в {2} в рядку {3} та стовпчику {4}\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"Показати це повідомлення і вийти\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"Показати версію і вийти\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"Визначити папку з diabdat.mpq\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"Визначити папку з збереженнями\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"Визначити папку з diablo.ini\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"Вкажіть код мови (наприклад, en або pt_BR)\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"Пропустити заставки\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"Показати кадри в секунду\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"Ввімкнути велемовне логування\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"Писати лог в файл, замість stderr\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"Записати демо\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"Зіграти демо\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"Віключити ліміт кадрів під час програшу демо\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"Вибір гри:\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"Примусити режим демо-версії\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"Примусити режим Diablo\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"Примусити режим Hellfire\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"Опції Hellfire:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"Пишіть про помилки на https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"Будь ласка, оновіть devilutionx.mpq та fonts.mpq до останньої версії\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"Неможливо завантажити ресурси UI.\\n\"\n\"\\n\"\n\"Впевніться що devilutionx.mpq в папці гри і актуальної версії.\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"Будь ласка, оновіть fonts.mpq до останньої версії\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"-- Тайм-аут мережі --\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"-- Чекаємо гравців --\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"Допомога недоступна\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"в магазинах\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"Предмет з Поясу {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"Використати предмет з Поясу.\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"Швидкі Чари {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"Гаряча клавіша для чар або таланту.\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"Попередні швидкі чари\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"Вибирає попередні швидкі чари (циклює).\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"Наступні швидкі чари\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"Вибирає наступні швидкі чари (циклює).\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"Використати зілля Зцілення\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"Використати зілля Зцілення з пояса.\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"Використати зілля Мани\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"Використати зілля Мани з пояса.\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"Швидка Книга Чар\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"Відкрити Швидку Книгу Чар.\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"Швидке Збереження\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"Зберігає гру.\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"Швидке Завантаження\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"Завантажує гру.\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"Вийти з Гри\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"Закриває гру.\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"Зупинити героя\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"Зупиняє ходьбу і незакінчені дії.\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"Підствітлення Предметів\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"Показати/Сховати предмети на землі.\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"Постійне підсвітлення предметів\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"Постійно показувати/ховати предмети на землі.\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"Автокарта\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"Перемикає відображення автокарти.\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"Циклювати тип карти\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"Непрозора -> Прозора -> Мінікарта -> Немає\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"Відкрити вікно Інвентаря.\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"Герой\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"Відкрити вікно Героя.\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"Група\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"Відкрити панель Групи.\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"Журнал\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"Відкрити Журнал квестів.\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"Книга Чар\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"Відкрити Книгу Чар.\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"Швидке Повідомлення {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"Відправити Швидке Повідомлення в чат.\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"Сховати Вікна\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"Ховає всі інформаційні вікна.\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"Збільшення\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"Збільшити/зменшити екран гри.\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"Зупинити Гру\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"Ставить гру на паузу.\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"Зупинити гру (Альтернатива)\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\nmsgid \"Decrease Brightness\"\nmsgstr \"Зменшити Яскравість\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"Зменшити яскравість екрану.\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\nmsgid \"Increase Brightness\"\nmsgstr \"Збільшити Яскравість\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"Збільшити яскравість екрану.\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"Допомога\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"Відкрити вікно Допомоги.\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"Знімок екрана\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"Робить знімок екрана.\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"Інформація про гру\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"Показує інформацію про гру.\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"Лог Чату\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"Показує лог чату.\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"Сортувати Інвентар\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"Сортує інвентар.\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"Консоль\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"Відкриває консоль Lua.\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"Основна дія\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\"Атака монстрів, розмови з городянами, підняття та розміщення предметів \"\n\"інвентарю.\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"Вторинна дія\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"Відкриття скринь, взаємодія з дверима, підбір предметів.\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"Дія чарування\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"Чарує активне чарування.\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"Відміна\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"Закриває меню.\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"Ідти нагору\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"Переміщує персонажа гравця вгору.\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"Ідти вниз\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"Переміщує персонажа гравця вниз.\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"Ідти вліво\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"Переміщує персонажа гравця вліво.\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"Ідти вправо\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"Переміщує персонажа гравця вправо.\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"Стояти на місці\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"Утримуйте, щоб не дати гравцеві рухатися.\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"Перемкнути стояння на місці\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"Перемикає, чи може гравець рухатись.\"\n\n#: Source/diablo.cpp:2310\nmsgid \"Automap Move Up\"\nmsgstr \"Перемістити Автокарту Вгору\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"При активації, переміщує автокарту вгору.\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"Перемістити Автокарту Вниз\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"При активації, переміщує автокарту вниз.\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"Перемістити Автокарту Вліво\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"При активації, переміщує автокарту вліво.\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"Перемістити Автокарту Вправо\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"При активації, переміщує автокарту вправо.\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"Перемішення мишу вгору\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"Імітує рух миші вгору.\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"Рухати миш вниз\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"Імітує рух миші вниз.\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"Рухати миш вліво\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"Імітує рух миші вліво.\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"Рухати миш вправо\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"Імітує рух миші вправо.\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"Клік лівою кнопкою миші\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"Імітує ліву кнопку миші.\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"Клік правою кнопкою миші\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"Імітує праву кнопку миші.\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"Меню гарячих чарувань геймпаду\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"Утримуйте, щоб встановити або використати гарячі клавіші чарування.\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"Навігація по меню геймпада\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"Утримуйте для навігації по меню геймпада.\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"Перемкнути ігрове меню\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"Відкриває ігрове меню.\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"Гру збережено\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"Мережева гра недоступна в демо\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Помилка створення Direct Sound\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"Недоступно в демо-версії\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"Недостатньо місця для збереження\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"Пауза недоступна в Місті\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"Рекомендуємо копіювати на жорсткий диск\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"Проблема синхронізації мережі\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"Пауза недоступна в мережевій грі\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"Зберігається…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"Деякі слабшають, коли один стає сильним\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"Через руйнування формується нова сила\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"Ті, хто захищаються, рідко нападають\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"Меч справедливості швидкий і гострий\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"Поки дух пильний, тіло процвітає\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"Сили мани поновлюються\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"Час не може зменшити силу сталі\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"Магія не завжди така, якою здається\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"Те, що було відкрито, зараз закрито\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"Сила приходить ціною мудрості\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"Таємна сила приносить руйнування\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"Те, що не утримаєш — не зламаєш\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"Багряний та Лазурний стають, як сонце\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"Знання і мудрість ціною себе\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"Пий і освіжайся\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"Куди б ти не пішов, ти там\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"Енергія приходить ціною мудрості\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"Рясні багатства коли менше всього їх очікуєш\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"Коли скупість зазнає невдачі, терпіння отримує винагороду\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"Освячений доброзичливим товаришем!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"Доля може керувати руками людей\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"Сила підкріпляється небесною вірою\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"Суть життя випливає зсередини\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"Коли дивишся зверху, шлях стає зрозумілим\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"Спасіння приходить ціною мудрості\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"Таємниці розкриваються у світлі розуму\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"Ті, хто останні, можуть бути першими\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"Щедрість приносить свою винагороду\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"Ти маєш бути принаймні 8 рівня, щоб скористатися цим.\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"Ти маєш бути принаймні 13 рівня, щоб скористатися цим.\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"Ти маєш бути принаймні 17 рівня, щоб скористатися цим.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"Отримані таємні знання!\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"Те, що тебе не вбиває…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"Знання це сила.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"Давай і отримаєш.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"Певний досвід набувається на дотик.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"Усюди добре, а дома найкраще.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"Духовна енергія відновлена.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"Ти відчуваєш спритнішим.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"Ти відчуваєш сильнішим.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"Ти відчуваєш мудрішим.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"Ти відчуваєш себе оновленим.\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"Те, що не ламається — зламається.\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"Собор\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"Катакомби\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"Печери\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"Гніздо\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"Склеп\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"{} {} Рів\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"{} Складність\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"В Меню\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"петльова адреса\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"Неможливо з'єднатися\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"помилка: прочитано 0 байт від сервера\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\"Не вдалося відкрити файл:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"Можливо, файл(и) MPQ пошкоджено. Будь ласка, перевірте цілісність файлів.\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq або spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"Деякі файли MPQ для Hellfire відсутні\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"Не всі файли MPQ для Hellfire були знайдені.\\n\"\n\"Будь ласка скопіюйте всі файли hf*.mpq.\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"Роздільна Здатність\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"Біг в Місті\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"Квест Тео\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"Квест Корови\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"Автопідбір Золота\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"Автопідбір Еліксирів\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"Автопідбір Масел\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"Автопідбір в Місті\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"Адрія Поповнює Ману\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"Автоспорядження Зброї\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"Автоспорядження Броні\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"Автоспорядження Шоломів\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"Автоспорядження Щитів\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"Автоспорядження Коштовностей\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"Рандомізація Квестів\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"Показати Назви Предметів\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"Автозаповнення Пояса\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"Вимкнути Псуючі Вівтарі\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"Підбір Зілля Зцілення\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"Підбір Зілля Повного Зцілення\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"Підбір Зілля Мани\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"Підбір Зілля Повної Мани\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"Підбір Зілля Омолодження\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"Підбір Зілля Повного Омолодження\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"Опції\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"Зберегти Гру\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\nmsgid \"Exit to Main Menu\"\nmsgstr \"Вийти в Головне Меню\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"Вийти з Гри\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"Гамма\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"Швид-ть\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"Музика Вимкнена\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"Звук\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"Звук Вимкнено\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"Пауза\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"$Гарячі Клавіші:\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    Відкрити вікно Допомоги\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   Вікрити Головне Меню\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   Відкрити Автокарту\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"Пробіл: Сховати всі вікна\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: Відкрити Швидку Книгу Чар\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: Відкрити Книгу Чар\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: Відкрити вікно Інвентаря\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: Вікрити вікно Героя\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: Вікрити Журнал квестів\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: Зменшити яскравість екрану\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: Збільшити яскравість екрану\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: Збільшити/зменшити екран гри\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: Збільшити/зменшити Автокарту\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: Використати предмет з Поясу\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     Встановити гарячу клавішу для чар або таланту\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + Ліва кнопка миші: Атакувати не рухаючись\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\"Shift + Ліва кнопка миші (на вікні героя): Призначити всі очки параметру\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\"Shift + Ліва кнопка миші (в інвентарі): Перенести предмет на Пояс або \"\n\"обладнати/зняти предмет\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + Ліва кнопка миші (на поясі): Перенести предмет в інвентар\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"$Пересування:\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"Утримуючи ліву кнопку миші, герой буде рухатися в направленні курсору.\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"$Бій:\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\"Клік лівою кнопкою миші, утримуючи кнопку Shift дозволяє герою атакувати не \"\n\"рухаючись.\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"$Автокарта:\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"Щоб показати Автокарту, клікніть на кнопці 'КАРТА' в Панелі Інформації, або \"\n\"натисніть клавішу 'Tab'. Збільшення і зменшення карти робиться клавішами + і \"\n\"-. Прокрутка робиться клавішами зі стрілками.\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"$Підбирання предметів:\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"Маленькі предмети, що можна використати (наприклад зілля і сувої) \"\n\"автоматично кладуться в Пояс в верхній частині Інформаційної Панелі. Коли \"\n\"предмет кладеться в пояс, над ним з'являється цифра. Предмети в Поясі можна \"\n\"використати натиснувши клавішу з номером, або кліком правої кнопки миші на \"\n\"предметі.\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"$Золото:\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\"Ви можете визначити точну кількість золота для викидання кліком правої \"\n\"кнопки миші на купі золота в інвентарі.\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"$Таланти та Чари:\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"Ви можете знайти повний список чар і талантів Вашого героя кліком лівою \"\n\"кнопкою миші на кнопці 'ЧАРИ' в Інформаційній Панелі. В цьому вікні \"\n\"вказуються чари вивчені напам'ять і доступні через посохи. Клік лівою \"\n\"кнопкою миші на чарах/таланті підготує його. Завороження підготовленими \"\n\"чарами робиться кліком правої кнопки миші в зоні гри.\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"$Використання Швидкої Книги Чар:\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"Клік лівою кнопкою миші на кнопці 'Підготовлені чари' відкриє 'Швидку Книгу \"\n\"Чар'. Вона дозволить вибрати талант або чари для негайного використання. \"\n\"Завороження новими чарами робиться кліком правої кнопки миші в зоні гри.\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\"Shift + Ліва кнопка миші на кнопці \\\"Підготовлені чари\\\" очистить підготовку.\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"$Встановлення гарячих клавіш для чар:\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"Ви можете встановити до чотирьох гарячих клавіш для чар, талантів або \"\n\"сувоїв. Відкрийте 'Швидку Книгу Чар' як описано вище. Наведіть курсор на \"\n\"бажані чари і натисніть клавішу F5, F6, F7 або F8 для призначення.\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"$Книги Чар:\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\"Читання більш ніж однієї книги чар покращує знання про них, що дозволить \"\n\"ворожувати ці чари більш ефективно.\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"Допомога Демо-версії Hellfire\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"Допомога Hellfire\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"Допомога Демо-версії Diablo\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"Допомога Diablo\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"Натисніть ESC щоб закрити або клавіші зі стрілками для прокрутки.\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"Неможливо створити головне вікно\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"Немає місця для предмету\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"Масло Точності\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"Масло Майстерності\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"Масло Гостроти\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"Масло Смерті\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"Масло Таланту\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"Ковальське Масло\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"Масло Стійкості\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"Масло Міцності\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"Масло Гартування\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"Масло Непроникності\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{0} {1} {2}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0} {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"підвищує у зброї\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"шанс удару\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"набагато підвищує\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"шанс удару зброї\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"потенціал шкоди\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"набагато підвищує у зброї\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"потенціал шкоди — крім луків\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"знижує вимоги атрибутів\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"шоб використати броню чи зброю\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"відновлює 20%\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"міцність предмету\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"підвищує у предмета\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"поточну і макс міцність\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"робить предмет неруйновним\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"підвищує клас броні\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"броні і щитів\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"набагато підвищує у броні\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"клас броні і щитів\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"ставить пастку вогню\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"ставить пастку блискавки\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"ставить пастку окам'яніння\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"відновлює все життя\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"відновлює трохи життя\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"відновлює трохи мани\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"відновлює всю ману\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"підвищує силу\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"підвищує магію\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"підвищує спритність\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"підвищує живучість\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"відновлює трохи життя і мани\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"відновлює все життя і ману\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"(працює тільки на аренах)\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"Правий клік щоб оглянути\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"Правий клік щоб використати\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"Правий клік, щоб прочитати,\\n\"\n\"лівий клік, щоб вибрати ціль\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"Правий клік щоб прочитати\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"Активуйте щоб оглянути\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"Відкрийте інвентар щоб використати\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"Активуйте щоб використати\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"Виберіть з книги чарувань, а потім\\n\"\n\"чаруйте, щоб прочитати\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"Активуйте щоб прочитати\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{} щоб оглянути\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} щоб використати\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"Виберіть з книги чар,\\n\"\n\"потім {}, щоб прочитати\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{} щоб прочитати\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"Рівень: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"Подвоює ємність золота\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"Вимоги:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} Сил\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} Маг\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} Спр\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"Книга {:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"Вухо {:s}\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"шанс удару: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% шкоди\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"шанс: {:+d}%, {:+d}% шкоди\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% броні\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"клас броні: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"Спротив Вогню: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"Спротив Вогню: {:+d}% МАКС\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"Спротив Блискавці: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"Спротив Блискавці: {:+d}% МАКС\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"Спротив Магії: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"Спротив Магії: {:+d}% МАКС\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"Спротив Всьому: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"Спротив Всьому: {:+d}% МАКС\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"чари покращені на {:d} рівень\"\nmsgstr[1] \"чари покращені на {:d} рівня\"\nmsgstr[2] \"чари покращені на {:d} рівнів\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"чари погіршені на {:d} рівень\"\nmsgstr[1] \"чари погіршені на {:d} рівня\"\nmsgstr[2] \"чари погіршені на {:d} рівнів\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"рівень чар не змінюється (?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"Додаткові заряди\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} заряд\"\nmsgstr[1] \"{:d} {:s} заряди\"\nmsgstr[2] \"{:d} {:s} зарядів\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"Шкода вогнем: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"Шкода вогнем: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"Шкода блискавкою: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"Шкода блискавкою: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} до сили\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} до магії\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} до спритності\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} до живучості\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} до всіх атрибутів\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} шкоди від ворогів\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"Здоров'я {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"Мана: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"висока міцність\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"зменшена міцність\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"неруйновний\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"радіус світла +{:d}%\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"радіус світла -{:d}%\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"стріляє декілька стріл відразу\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"шкода вогняних стріл: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"шкода вогняних стріл: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"шкода стріл блискавки: {:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"шкода стріл блискавки: {:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"шкода кулі вогню: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"шкода кулі вогню: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"нападник отримує 1-3 шкоди\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"поглинає всю ману\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"поглинає 50% шкоди пасток\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"відбиває ворога назад\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200% шкоди проти демонів\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"Всі Спротиви рівні 0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"удар краде 3% мани\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"удар краде 5% мани\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"удар краде 3% життя\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"удар краде 5% життя\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"пробиває броню\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"моторна атака\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"швидка атака\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"швидша атака\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"найшвидша атака\"\n\n# Що за NW?\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"Інше уміння (NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"швидке відновлення після удару\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"швидше відновлення після удару\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"найшвидше відновлення після удару\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"швидкий блок\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"додає {:d} очко до шкоди\"\nmsgstr[1] \"додає {:d} очка до шкоди\"\nmsgstr[2] \"додає {:d} очків до шкоди\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"стріляє кілька швидких стріл\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"у предмету змінена шкода\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"змінена міцність\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"одноручний меч\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"постійно втрачаєш очки життя\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"краде життя\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"немає вимог по силі\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"шкода блискавкою: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"шкода блискавкою: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"при ударі стріляє зарядженою стрілою\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"випадкова потрійна шкода\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"шкода згасає {:+d}%\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2х шкд монстрам, 1х шкд тобі\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"Випадкова шкода 0 - 600%\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"низька міц, {:+d}% шкоди\"\n\n# ШУ- шанс удару\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"додат. ШУ проти демонів\"\n\n# ШУ - шанс удару\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"додат. ШУ проти нечисті\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50% Мани перенесене в Здоров'я\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40% Здоров'я перенесене в Ману\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"шкода: {:d}  Неруйновний\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"шкода: {:d}  Міц: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"шкода: {:d}-{:d}  Неруйновний\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"шкода: {:d}-{:d}  Міц: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"броня: {:d}  Неруйновний\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"броня: {:d}  Міц: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"Заряди: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"унікальний предмет\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"Не Розпізнано\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"Лігво Короля-Скелета\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"Палата Кості\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"Лабіринт\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"Отруєне Джерело\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"Лігво Архієпископа Лазаря\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"Арена \\\"Церква\\\"\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"Арена \\\"Пекло\\\"\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"Арена \\\"Коло життя\\\"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"Вниз в підземелля\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"Вниз в катакомби\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"Вниз в печери\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"Вниз в пекло\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"Вниз в Гніздо\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"Вниз до Склепу\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"Вверх на {:d} рівень\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"Вверх у Місто\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"Вниз на {:d} рівень\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"Вниз до Діабло\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"Вверх на {:d} рівень Гнізда\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"Вверх на {:d} рівень Склепу\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"Наріжний Камінь Світу\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"Вниз на {:d} рівень Склепу\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"Назад на {:d} рівень\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"Неможливо відкрити архів збереження\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"Версія схованки невірна. Дані будуть перезаписані при спробі зайти до неї!!!\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\"Розмір схованки невірний. Дані будуть перезаписані при спробі зайти до неї!!!\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"Файл збереження зламаний\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"Гравець на рівні, доступному тільки в Hellfire\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"Невірний стан гри\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"Неможливо показати головне меню\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"Не вдалося завантажити дані про монстра\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\"Не вдалося додати монстра, оскільки максимальний номер типу монстра {} вже \"\n\"досягнуто.\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"Для ідентифікатора \\\"{}\\\" вже існує тип монстра.\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"Тварина\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"Демон\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"Нечисть\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"Тип: {:s}  Вбито: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"Всього вбито: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"Життя {:d} з {:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"Не спротивлюється магії\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"Спротив:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" Магія\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" Вогонь\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" Блискавка\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"Імунітет:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"Тип: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"Немає спротиву\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"Немає Імунітету\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"Декілька Магічних Спротивів\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"Декілька Магічних Імунітетів\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"Неможливо відкрити архів для читання.\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s} зворожував заборонені чари.\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s} зворожував заборонені чари.\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"Гравець '{:s}' (рівень {:d}) приєднався до гри\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"Гра закінчилась\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"Неможливо дістати дані рівня\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"Гравець '{:s}' покинув гру\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"Гравець '{:s}' вбив Діабло і покинув гру!\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"Гравець '{:s}' відключився через таймаут\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"Гравець '{:s}' (рівень {:d}) вже в грі\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"Таємний\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"Схований\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"Похмурий\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"Чудний\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"Магічний\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"Кам'яний\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"Релігійний\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"Зачарований\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Чудотворний\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"Чарівливий\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"Загадковий\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"Лиховісний\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"Моторошний\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"Божественний\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"Святий\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"Святий\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"Духовний\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"Лячний\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"Покинутий\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"Страховитий\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"Тихий\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"Відлюдний\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"Барвистий\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"Блимаючий\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"Засмерділий\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"Масляний\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"Світний\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"Жебрака\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"Іскристий\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"Мерехтливий\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"Сонячний\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"Мерфі\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"Великий Конфлікт\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"Розплата за Гріхи — це Війна\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"Розповідь про Хорадріма\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"Темне Заслання\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"Війна Гріхів\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"Зв'язування Трьох\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"Виміри за Межами\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"Оповідь про Трьох\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"Чорний Король\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"Щоденник: Чаклунство\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"Щоденник: Зустріч\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"Щоденник: Тирада\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"Щоденник: Його Сила Росте\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"Щоденник: НА-КРУЛ\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"Щоденник: Кінець\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"Книга Чар\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"Розп'ятий Скелет\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"Важіль\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"Відкриті Двері\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"Закриті Двері\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"Заблоковані Двері\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"Стародавній Том\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"Кинга Підлості\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"Черепний Важіль\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"Міфічна Книга\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"Маленька Скриня\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"Скриня\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"Велика Скриня\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"Саркофаг\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"Полиця з Книгами\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"Шкаф з Книгами\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"Бочка\"\n\n# How does the pod look like?\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"Банка\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"Урна\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s} Вівтар\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"Скелетний Том\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"Бібліотечна Книга\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"Кривавий Фонтан\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"Обезглавлений Труп\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"Книга Сліпих\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"Книга Крові\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"Очищальне Джерело\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"Броня\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"Стелаж зі Зброєю\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"Вівтар Кози\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"Казан\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"Мутний Ставок\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"Фонтан Сліз\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"Сталевий Том\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"П'єдестал Крові\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"Грибна Галявина\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"Огидний Стелаж\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"Вбитий Герой\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"{:s} з пасткою\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s} (не активно)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"УВІМК\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"ВИМК\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"Режим Гри\"\n\n#: Source/options.cpp:422\nmsgid \"Game Mode Settings\"\nmsgstr \"Налаштування Режиму Гри\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"Грати в Diablo або в Hellfire.\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"Обмежити гру до Демо\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\"Робить гру сумісною з демо-версією. Дозволяє гру по мережі з друзями у яких \"\n\"немає повної копії Diablo.\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"Запуск\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"Налаштування Запуску\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"Ролик\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"Показати початковий ролик.\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"Заставка\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"Показана заставка.\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"Логотип і Початковий Екран\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"Початковий Екран\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"Налаштування Diablo\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"Настройки Hellfire\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"Аудіо\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"Налаштування Аудіо\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"Звук Ходьби\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"При ходьбі гравець видає звук.\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"Звук Автоспорядження\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"Автоматичне спорядження предметів видає звук спорядження.\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"Звук Підбору Предмету\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"Підбір предметів видає звук підбору.\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"Частота Дискретизації\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"Частота дискретизації звуку (в Гц)\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"Канали\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"Кількість каналів звуку.\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"Розмір Буферу\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"Розмір буферу (кількість кадрів на канал).\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"Якість Семплування\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"Якість семлеру, від 0 (найнижча) до 5 (найвища).\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"Діє на роздільну здатність гри і визначає видиму область. Примітка: \"\n\"Налаштування може відрізнятись від роздільної здатності монітору коли \"\n\"використовуються \\\"Збільшення Зображення\\\", \\\"Коефіцієнт Масштабування\\\" або \"\n\"\\\"Налаштувати по Екрану\\\".\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"Cемплер\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"Аудіо cемплер\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"Пристрій\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"Пристрій аудіо\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"Графіка\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"Налаштування Графіки\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"Повноекранний Режим\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"Показує гру в режимі повного екрану чи вікна.\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"Налаштувати по Екрану\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\"Автоматично налаштовує вікно гри згідно співвідношення сторін і роздільної \"\n\"здатності екрану.\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"Збільшення Зображення\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"Дозволяє збільшення зображення гри. Забороняє зміну роздільної здатності \"\n\"монітора. Дозволяє міняти розмір вікна.\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"Якість Масштабування\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"Накладає опційні фільтри до збільшеної картинки.\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"Найближчий Піксель\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"Білінійний\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"Анізотропний\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"Коефіцієнт Масштабування\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"Збільшує зображення гри по коефіцієнту.\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"Керування Частотою Кадрів\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\"Керує частотою кадрів, щоб збалансувати продуктивність, зменшити розриви або \"\n\"заощадити енергію.\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"Вертикальна Синхронізація\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"FPS ліміт\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"Коли ввімкнено, наближує екран гри.\"\n\n#: Source/options.cpp:738\nmsgid \"Per-pixel Lighting\"\nmsgstr \"Попіксельне Освітлення\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"Підсвічування суб-плиток для більш плавних градієнтів світла.\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"Циклування Кольорів\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\"Ефект циклування кольорів, що використовується для анімації води, лави та \"\n\"кислоти.\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"Альтернативна палітра для Гнізда\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\"У грі буде використовуватися альтернативна палітра для плиток Гнізда з \"\n\"Hellfire.\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"Апаратний Курсор\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"Використовувати апаратно-прискорений курсор\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"Апаратний Курсор для Предметів\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"Використовувати апаратно-прискорений курсор для предметів.\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"Макс Розмір Аппаратного Курсору\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\"Максимальна широта / висота для апаратно-прискореного курсору. Більші \"\n\"курсори використовують програмний спосіб.\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"Показати Кадри в Секунду\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"Показує лічильник кадрів в секунду в верхньому лівому кутку екрана.\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"Гра\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"Налаштування Гри\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\"Вмикає біг/швидку ходьбу в Місті для Diablo та Hellfire. Цю опцію вперше \"\n\"додали в Hellfire.\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"Захопити Мишу\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"Коли це налаштування ввімкнене, курсор буде прив'язаний до вікна гри .\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"Зупинити гру, коли вікно втрачає фокус\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"Коли увімкнено, гра призупинятиметься, при втраті фокусу.\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"Дозволяє квест Маленької Дівчинки.\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"Дозволяє квест Джерсі. Замість Фермера Лестера буде Повний Псих.\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"Дружній Вогонь\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\"Дозволяє шкоду від чар/стріл гравцям в мережевій грі, навіть якщо ввімкнений \"\n\"дружній режим.\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"Повні квести в Мережевій Грі\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"Вмикає повні/неурізані версії квестів з одиночної гри.\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"Тестовий Бард\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"Примусити \\\"Бард\\\" з'явитися в меню вибору типу героя.\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"Тестовий Варвар\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"Примусити \\\"Варвар\\\" з'явитися в меню вибору типу героя.\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"Шкала Досвіду\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"Додає внизу екрана Шкалу Досвіду.\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"Показувати Іконку Предмету в Магазині\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"Показувати іконку предмету зліва від його опису в меню магазину.\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"Показати значення здоров'я\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"Показує значення поточного/максимального здоров'я на кулі здоров'я.\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"Показати значення мани\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"Показує значення поточної/максимальної мани на кулі мани.\"\n\n#: Source/options.cpp:797\nmsgid \"Show Party Information\"\nmsgstr \"Показати Інформацію про Групу\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\"Відображає рівень здоров'я та мани всіх підключених учасників мережевої \"\n\"групи.\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"Шкала Ворожого Життя\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"Додає внизу екрана Шкалу Ворожого Життя.\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"Плаваюче Інформаційне Вікно Предмету\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\"Відображає інформацію про предмет у плаваючому вікні при наведенні на нього \"\n\"курсору.\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Золото автоматично збирається коли гравець знаходиться близько до нього.\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\"Еліксири автоматично збираються коли гравець знаходиться близько до них.\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"Масла автоматично збираються коли гравець знаходиться близько до них.\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"Предмети в Місті автоматично збираються.\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"Адрія поповнить ману коли гравець відвідує її магазин.\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Зброя буде автоматично споряджена після її підбору або покупки.\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Броня буде автоматично споряджена після її підбору або покупки.\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Шоломи будуть автоматично споряджені після їх підбору або покупки.\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"Щити будуть автоматично споряджені після їх підбору або покупки.\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\"Коштовності будуть автоматично споряджені після їх підбору або покупки.\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"Квести випадково вибираються для нової гри.\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"Показати Тип Монстра\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\"Наведення курсора миші над монстром покаже його тип в Панелі Інформації.\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"Показати назви предметів на землі, коли це налаштування ввімкнене.\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\"Коли предмет з Поясу використовується, Пояс автоматично поповнюється з \"\n\"інвентаря.\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"Коли це налаштування ввімкнене, гравець не зможе клікнути на Казани, \"\n\"Чарівливі, Барвисті, Святі Вівтарі і Вівтарі Кози, які будуть показані як \"\n\"неактивні.\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"Швидке Чаклування\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"Гаряча клавішу чар буде відразу чаклувати попередньо вибрані чари.\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"Кількість Зілля Зцілення щоб автоматично підібрати.\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"Кількість Зілля Повного Зцілення щоб автоматично підібрати.\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"Кількість Зілля Мани щоб автоматично підібрати.\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"Кількість Зілля Повної щоб автоматично підібрати.\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"Кількість Зілля Омолодження щоб автоматично підібрати.\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"Кількість Зілля Повного Омолодження щоб автоматично підібрати.\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"Ввімкнути Плаваючі Числа\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"Вмикає плаваючі числа при отриманні XP / нанесенні шкоди тощо.\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"Вимк\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"Випадкові Кути\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"Тільки Вертикально\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"Контроллер\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"Налаштування Контроллеру\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"Мережа\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"Налаштування Мережі\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"Чат\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"Налаштування Чату\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"Мова\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"Визначте мову гри.\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"Налаштування Мови\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"Клавіатура\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"Налаштування призначення клавіш клавіатури\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"Геймпад\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"Налаштування призначення кнопок геймпаду\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"Модифікації\"\n\n#: Source/options.cpp:1512\nmsgid \"Mod Settings\"\nmsgstr \"Налаштування Модифікацій\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"Рівень\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"Досвід\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"Наступний рівень\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"База\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"Зараз\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"Сила\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"Магія\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"Спринтість\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"Живучість\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"Вільні очки\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"Золото\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"Клас броні\"\n\n#: Source/panels/charpanel.cpp:176\nmsgid \"Chance To Hit\"\nmsgstr \"Шанс Влучити\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"Шкода\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"Життя\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"Спротив магії\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"Спротив вогню\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"Спротив блискавці\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"герой\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"журнал\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"карта\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"меню\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"інвен\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"чари\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"чат\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"заблок\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"Непридатні\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"Шкд: 1/3 життя цілі\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"Зцілює: {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"Шкода: {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"Талант\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"Посох ({:d} заряд)\"\nmsgstr[1] \"Посох ({:d} заряда)\"\nmsgstr[2] \"Посох ({:d} зарядів)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"Рівень: {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"Мана: {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"Чари\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"Б'є тільки нечисть\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"Сувій\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"Посох\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"Гаряча клавіша Чар {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"Неможливо відкрити архів\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"Неможливо завантажити героя\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"Не вдалося завантажити дані класу\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\"Не вдалося додати клас, оскільки максимальний номер класу {} вже досягнуто.\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (рів {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"Історія Чату (Повідомлень: {:d})\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} золота\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"Скільки золотих монет ти хочеш забрати?\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"Рівень {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"Досвід: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"Максимальний Рівень\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"Наступний рівень: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} до {:d} Рівня\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"Гробниця Короля Леоріка\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"Палата Кості\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"Темний Прохід\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"Нечестивий Вівтар\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"До {:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"Мені потрібна допомога! Ідіть сюди!\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"За мною.\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"Ось щось для тебе.\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"А тепер ПОМРИ!\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"Зціли себе!\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"Обережно!\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"Дякую.\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"Відступаємо!\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"Вибач.\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"Я чекаю.\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"Грізволд\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"Пепін\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"Одген\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"Каїн\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"Фарнхем\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"Адрія\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"Гілліан\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"Вірт\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"Назад\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \", \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"Шкода: {:d}-{:d}  \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"Броня: {:d}  \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"Міц: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"Неруйновний\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"Ласкаво просимо\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"Ковальська Майстерня\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"Ви хочете:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"Поговорити з Грізвольдом\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"Купити прості предмети\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"Купити преміальні предмети\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"Продати предмети\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"Відремонтувати предмети\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"Покинути магазин\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"В мене продаються такі предмети:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"Є такі преміальні предмети:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"Вам немає що продати.\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"Який предмет продати?\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"Немає чого ремонтувати.\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"Який предмет ремонтувати?\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"Хатина відьми\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"Поговорити з Адрією\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"Купити предмети\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"Перезарядити посохи\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"Покинути хатину\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"Немає чого заряджати.\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"Який предмет зарядити?\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"У Вас недостатньо золота\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"У Вас недостатньо місця в інвентарі\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"Домовились?\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"Ви впевнені, що хочете розпізнати цей предмет?\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"Ви впевнені, що хочете купити цей предмет?\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"Ви впевнені, що хочете зарядити цей предмет?\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"Ви впевнені, що хочете продати цей предмет?\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"Ви впевнені, що хочете відремонтувати цей предмет?\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"Одноногий хлопчик Вірт\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"Поговорити з Віртом\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"В мене є щось на продаж,\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"але воно коштує 50 золота\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"щоб тільки глянути. \"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"Що в тебе є?\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"Попрощатися\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"В мене продаються такі предмети:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"Покинути\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"Дім цілителя\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"Поговорити з Пепіном\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"Покинути дім цілителя\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"Старець Міста\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"Поговорити з Каїном\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"Розпізнати предмет\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"Немає чого розпізнавати.\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"Який предмет розпізнати?\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"Предмет:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"Готово\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"Поговорити з {:s}\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"Говоримо з {:s}\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"недоступне\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"в демо-версії\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"версії\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"Плітки\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"Світанкове Сонце\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"Поговорити з Огденом\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"Покинути таверну\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"Поговорити з Гілліан\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"Зайти до схованки\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"П'яниця Фарнхем\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"Поговорити з Фарнхемом\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"Попрощатися\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"Ваше золото: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"Не вдалося завантажити текстові дані\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"Для ідентифікатора \\\"{}\\\" вже існує текстовий запис.\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"Вбитий Житель\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"Коваль Грізвольд\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"Цілитель Пепін\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"Поранений Житель\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"Хазяїн таверни Огден\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"Старець Каїн\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"Відьма Адрія\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"Барменша Гілліан\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"Корова\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"Фермер Лестер\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"Селія\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"Повний Псих\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"Воїн\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"Пройдисвітка\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"Чаклун\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"Монах\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"Бард\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"Варвар\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"Зомбі\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"Гуль\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"Гниюча Туша\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"Чорна Смерть\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"Впалий\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"Різьбяр\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"Бісовий Рід\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"Темний\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"Скелет\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"Труп з Сокирою\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"Палаючий Скелет\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"Кошмар\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"Сміттяр\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"Пожирач Чуми\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"Звір Тіні\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"Костогриз\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"Труп з Луком\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"Капітан Скелетів\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"Капітан Трупів\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"Капітан Палаючих Скелетів\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"Капітан Кошмарів\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"Невидимий Лорд\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"Прихований\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"Сталкер\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"Невидимий\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"Ткач Іллюзій\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"Лорд Сатирів\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"Клан Плоті\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"Клан Каменю\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"Клан Вогню\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"Клан Ночі\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"Біс\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"Блимач\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"Похмурень\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"Фамільяр\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"Кислотний Звір\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"Отрутоплюй\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"Ямний Звір\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"Лавова Паща\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"Король-Скелет\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"М'ясник\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"Повелитель\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"Брудолюдина\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"Жабодемон\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"Облуплений\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"Супостат\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"Печерний Слизняк\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"Диявол-Супостат\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"Пожирач\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"Демон Магми\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"Кривавий Камінь\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"Пекельний Камінь\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"Лорд Лави\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"Рогатий Демон\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"Брудобігун\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"Морозний Бігун\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"Лорд Обсидіяну\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"старокостяний\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"Червона Смерть\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"Демон-Ліч\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"Балрог-Нежить\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"Крематор\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"Лорд Вогню\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"Вогонь Долі\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"Пальник Пекла\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"Червоний Шторм\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"Штормовий Вершник\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"Лорд Шторму\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"Вихор\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"Бісовий Рід-Нелюд\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"Крилатий Демон\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"Ґаргулья\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"Кривавий Кіготь\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"Крило Смерті\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"Вбивця\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"Заступник\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"Лорд Вихру\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"Балрог\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"Печерна Гадюка\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"Вогняний Левіятан\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"Золота Гадюка\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"Лазурний Левіятан\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"Чорний Лицар\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"Страж Долі\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"Лорд Сталі\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"Лицар Крові\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"Січений\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"Пустий\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"Майстер Болю\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"Ткач Реальності\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"Суккуб\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"Сніжна Відьма\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"Пекельний Виродок\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"Пальник Душ\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"Радник\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"Магістрат\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"Кабаліст\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"Прибічник\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"Темний Лорд\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"Архі-Ліч Малігнус\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"Слабак Габард\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"Безумний Жар\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"Шмарклі\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"Архієпископ Лазар\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"Червоний Векс\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"Чорний Нефрит\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"Лахданан\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"Воєвода Крові\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"Блювотний Демон\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"Паплюжник\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"Гостросокирний Кістяк\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"Рубака Мечешкура\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"Душогній\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"Нечистий Блювопацюк\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"Костелом\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"Голодний Гнилеїд\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"Швидкий Животоріз\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"Ломочереп зі Щитом\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"Бонго\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"Гнилеріз\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"Тінекус\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"Снайпер\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"Мертвий Влучник\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"Чупакабри\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"Череповогонь\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"Кривочереп\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"Кровоязик\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"Пульсоповз\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"Місячний Маг\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"Ворон Кари\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"Хребетоїд\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"Пекучий Чорнопопіл\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"Тіньоворона\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"Слабак Іржекамінь\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"Господар Ями Жовчепінь\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"Темнолучник Кровошкур\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"Огиднокрил\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"Тінопитій\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"Імлозмін\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"Смертеплюй\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"Кровотрощ\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"Смертетінь Плотеріз\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"Безумний Військохробак\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"Зазублений Скляночереп\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"Іржевогонь\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"Холодний Нічнокрил\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"Кровокамінь\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"Бронзокулачний Вогнекамінь\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"Приречений Гнівовогонь\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"Нещадний Вогнеран\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"Барон Багна\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"Сталебулавовий Іржекіготь\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"Ревун Хаосу\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"Гниючий Оскал Долі\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"Безумний Пальник\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"Ліч-Кістопил\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"Спинолом\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"Гострокіст Чорточереп\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"Ломошторм\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"Прокльоношторм\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"Липкослина\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"Полум'яна Золотоіржа\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"Чорнобуря\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"Чумогнів\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"Шкуродер\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"Синеріг\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"Виродок Кривовогню\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"Кігтяник\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"Гноєчереп\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"Зігнутий Левочереп\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"Чорноязик\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Огиднодотик\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"Вогняна Змія\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"Іклошкур\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"Нечестивий Відьмовогонь\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"Чорночереп\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"Душеріз\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"Виродок Вітру\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"Лорд Ями\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"Іржеткач\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"Виюча Тінь\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"Хмара Загибелі\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"Кровомісяцевий Душевогонь\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"Відьмомісяць\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"Кровобенкет\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"Вбивця Сіробій\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"Суддя\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"Відьма Зоряоко\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"Мисливець Сталечереп\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"Сір Гораш\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"Візир\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"Замфір\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"Кровожад\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"Павуковдова\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"Плотетанцівниця\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"Незламовістря\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"Замок Загибіелі\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"Короткий Меч\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"Круглий Щит\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"Палиця\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"Короткий Лук\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"Короткий Посох Мани\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"Сікач\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"Нечестива Корона\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"Обруч Емпірею\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"Магічний Камінь\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"Оптичний Амулет\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"Перстень Правди\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"Знак Таверни\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"Гребінь Арлекіна\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"Стальна Чадра\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"Золотий Еліксир\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"Ковадло Люті\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"Чорний Гриб\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"Мозок\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"Грибковий Том\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"Примарний Еліксир\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"Кров'яний Камінь\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"Карта Собору\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"Вухо\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"Зілля Зцілення\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"Зілля Мани\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"Сувій Розпізнавання\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"Сувій Порталу в Місто\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"Доблесть Аркейну\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"Зілля Повного Зцілення\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"Зілля Повної Мани\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"Лезо Грізволда\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"Бичачі Лати\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"Посох Лазаря\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"Сувій Воскрешення\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"Короткий Посох\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"Меч\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"Кинджал\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"Рунна Бомба\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"Теодор\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"Золотоносний Амулет\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"Розірвана Записка 1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"Розірвана Записка 2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"Розірвана Записка 3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"Відновлена Записка\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"Коричневий Костюм\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"Сірий Костюм\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"Шапка\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"Черепна Шапка\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"Шолом\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"Повний Шолом\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"Корона\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"Величезний Шолом\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"Накидка\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"Ганчірки\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"Мантія\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"Ряса\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"Стьобана Броня\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"Шкіряна Броня\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"Броня з Твердої Шкіри\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"Броня з Клепаної Шкіри\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"Кільцева Кольчуга\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"Кольчуга\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"Кільчаста Кольчуга\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"Лускова Кольчуга\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"Нагрудник\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"Лати\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"Шинні Лати\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"Пластинчасті Лати\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"Польові Лати\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"Готичні Лати\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"Повні Лати\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"Щит\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"Малий Щит\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"Великий Щит\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"Краплеподібний Щит\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"Баштовий Щит\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"Готичний Щит\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"Зілля Омолодження\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"Зілля Повного Омолодження\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"Масло\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"Еліксир Сили\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"Еліксир Магії\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"Еліксир Спритності\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"Еліксир Живучості\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"Сувій Зцілення\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"Сувій Пошуку\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"Сувій Блискавки\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"Сувій Стіни Вогню\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"Сувій Пекла\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"Сувій Спалаху\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"Сувій Інфрабачення\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"Сувій Фазування\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"Сувій Щита Мани\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"Сувій Хвилі Вогню\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"Сувій Кулі Вогню\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"Сувій Прокляття Каменю\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"Сувій Ланцюгової Блискавки\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"Сувій Охоронця\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"Сувій Нови\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"Сувій Голему\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"Сувій Телепорту\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"Сувій Апокаліпсису\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"Фальшіон\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"Ятаган\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"Клеймор\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"Клинок\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"Шабля\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"Довгий Меч\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"Широкий Меч\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"Меч-Бастард\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"Дворучний Меч\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"Величезний Меч\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"Мала Сокира\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"Сокира\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"Велика Сокира\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"Широка Сокира\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"Бойова Сокира\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"Величезна Сокира\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"Булава\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"Моргенштерн\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"Бойовий Молот\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"Молот\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"Палиця з Гвіздками\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"Ціп\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"Клепач\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"Лук\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"Мисливський Лук\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"Довгий Лук\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"Композитний Лук\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"Короткий Бойовий Лук\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"Довгий Бойовий Лук\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"Короткий Воєнний Лук\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"Довгий Воєнний Лук\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"Довгий Посох\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"Композитний Посох\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"Четвертковий Посох\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"Бойовий Посох\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"Перстень\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"Амулет\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"Руна Вогню\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"Руна\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"Руна Блискавки\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"Більша Руна Вогню\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"Більша Руна Блискавки\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"Руна Каменю\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"Короткий Посох Зарядженої Стріли\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"Зілля Арени\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"Сікач М'ясника\"\n\n#: Source/translation_dummy.cpp:370\nmsgid \"Lightforge\"\nmsgstr \"Горно Світла\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"Лук Розриву\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"Голкостріл\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"Небесний Лук\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"Смертельний Мисливець\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"Лук Мертвих\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"Лук з Чорного Дуба\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"Вогнедротик\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"Жало Плоті\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"Сила Вітру\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"Орлиний Ріг\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"Кинджал Гоннагала\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"Захисник\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"Кіготь Грифона\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"Чорна Бритва\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"Пів-місяць\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"Крижана Заточка\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"Клинок Ката\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"Кісткопил\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"Тіньовий Яструб\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"Вістря Мага\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"Світловий Меч\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"Кіготь Сокола\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"Інферно\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"Погибельник\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"Грізлі\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"Прадід\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"Калічитель\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"Гострий Дзьоб\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"Крововбивця\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"Небесна Сокира\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"Зла Сокира\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"Каменокол\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"Томагавк Агінари\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"Пекельний Вбивця\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"Грабіжник Мессершмідта\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"Іржа\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"Молот Йольма\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"Дубина Циверба\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"Небесна Зоря\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"Зірка Баранара\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"Сучкуватий Корінь\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"Черепний Розбійник\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"Молот Шефера\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"Край Сну\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"Посох Тіней\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"Спалювач\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"Штормовий Шпиль\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"Мерехтюча Пісня\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"Поклик Грому\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"Захисник\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"Головоломка Наджа\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"Крик Розуму\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"Жезл Онана\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"Шлем Духів\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"Думаюча Шапка\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"Шлем Повелителя\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"Герб Дурня\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"Загибель Богів\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"Королівський Вінець\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"Розірвана Плоть Душ\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"Прокляття Гладіатора\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"Веселковий Плащ\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Шкіра Аута\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"Шаль Мудрості\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"Іскряча Броня\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"Панцир Cміттяра\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"Нічний Покров\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"Легкі Лати Наджа\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"Мундир з Демоношипів\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"Дефлектор\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"Щит-Череполом\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"Пролом Дракона\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"Щит з Чорного Дуба\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"Святий Захисник\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"Штормовий Щит\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"Терен\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"Кільце Реги\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"Кровопроливач\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"Тісний Перстень\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"Перстень Заручення\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"Олов'яний\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"Латунний\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"Бронзовий\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"Залізний\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"Стальний\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"Срібний\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"Платиновий\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"Міфріловий\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"Метеоритний\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"Дивний\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"Непотрібний\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"Погнутий\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"Слабий\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"Зазублений\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"Смертельний\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"Важкий\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"Розпутний\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"Брутальний\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"Масивний\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"Дикий\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"Жорстокий\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"Безжалісний\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"Незграбний\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"Тупий\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"Гострий\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"Гарний\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"Воїнський\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"Солдатський\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"Лордський\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"Лицарський\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"Паньский\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"Чемпіонський\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"Королівський\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"Уразливий\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"Іржавий\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"Сильний\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"Величний\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"Доблесний\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"Славетний\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"Благословенний\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"Праведний\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"Фантастичний\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"Божий\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"Червоний\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"Багряний\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"Гранатовий\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"Рубіновий\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"Синій\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"Блакитний\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"Лазурний\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"Кобальтовий\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"Сапфірний\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"Білий\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"Перламутровий\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"Слонової кістки\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"Кришталевий\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"Діамантовий\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"Топазовий\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"Бурштинний\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"Нефритовий\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"Обсидіяновий\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"Смарагдовий\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"Гієнний\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"Жаб'ячий\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"Павучий\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"Воронний\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"Зміїний\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"Гадючий\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"Левіятановий\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"Драконовий\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"Супостатний\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"Гідровий\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"Ангела\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"Архангела\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"Рясний\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"Щедрий\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"Полум'яний\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"Блискавичий\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"якості\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"знівечення\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"убивання\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"крові\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"різанини\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"забою\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"болі\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"сліз\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"здоров'я\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"захисту\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"поглинання\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"відхилення\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"осмосу\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"субтильності\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"слабкості\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"сили\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"могутності\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"міці\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"гіганта\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"титана\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"паралізу\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"атрофії\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"спритності\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"таланту\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"точності\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"влучності\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"досконалості\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"дурня\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"дислексії\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"магії\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"розуму\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"здібності\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"чарівництва\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"чаклунства\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"недуги\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"хвороби\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"жувочості\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"запалу\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"енергії\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"снаги\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"життя\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"лиха\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"ями\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"неба\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"місяця\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"зорей\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"небес\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"зодіаку\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"стерв'ятника\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"шакала\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"лисиці\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"ягуара\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"орла\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"вовка\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"тигра\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"лева\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"мамонта\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"кита\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"крихкості\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"ламкості\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"міцності\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"майстерності\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"структури\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"віків\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"темряви\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"ночі\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"світла\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"сяяння\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"полум'я\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"вогню\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"горіння\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"шоку\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"блискавки\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"грому\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"багатьох\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"безлічі\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"шипів\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"псування\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"крадіїв\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"ведмедя\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"літучої миші\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"вампірів\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"п'явки\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"крові\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"пробивання\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"проколювання\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"побиття\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"готовності\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"хуткості\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"швидкості\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"поспішності\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"балансу\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"стабільності\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"гармонії\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"блокування\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"Магічний Камінь\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"Слабак Габард\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"Схиблений Жар\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"Лахданан\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"М'ясник\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"Знак Огдена\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"Зали Сліпих\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"Доблесть\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"Воєвода Крові\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"Прокляття Короля Леоріка\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"Архієпископ Лазарь\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"Могильні Справи\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"Сад Фермера\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"Маленька Дівчинка\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"Мандруючий Торговець\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"Паплюжник\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"На-Крул\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"Джерсі Джерсі\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"Стріла Вогню\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"Зцілення\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"Блискавка\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"Спалах\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"Розпізнавання\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"Стіна Вогню\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"Портал в Місто\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"Кам'яне Прокляття\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"Інфрабачення\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"Фазування\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"Щит Мани\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"Куля Вогню\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"Охоронець\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"Ланцюгова Блискавка\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"Хвиля Вогню\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"Змії Долі\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"Кривавий Ритуал\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"Нова\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"Невидимість\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"Пекло\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"Голем\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"Лють\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"Телепорт\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"Апокаліпсис\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"Етеризація\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"Ремонт Предмету\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"Перезарядка Посоху\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"Обеззброєння Пастки\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"Елементаль\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"Заряджена Стріла\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"Свята Стріла\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"Воскрешення\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"Телекінез\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"Зцілити Іншого\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"Кривава Зоря\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"Кістлявий Дух\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\" А, історія нашого Короля… Трагічне падіння Леоріка стало великою бідою для \"\n\"наших земель. Люди завжди любили Короля, а тепер живуть в смертельному \"\n\"страху до нього. Я часто сам себе питаю — як так могло статися? Адже Леорік \"\n\"був найбільш праведним серед нас. Тільки найпотворніші та найчорніші сили \"\n\"Пекла могли спотворити сердце Короля…\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"Майстре, селу потрібна твоя допомога! Декілька місяців назад був викрадений \"\n\"син Короля — Принц Альбрехт. Леорік впав у лють і обшукав все село, та \"\n\"нічого не знайшов. З кожним днем він все більше впадав в божевілля. Король \"\n\"звинуватив невинних жителів села у викраденні хлопчика. Їх страти були по \"\n\"звірячому жорстокі. Лише мала частина нас пережила його безумство…\\n\"\n\"\\n\"\n\"Лицарі і Священники Короля намагалися умилостивити його, тоді він обрушив \"\n\"всю свою лють на них. Лицарі були змушені його вбити. На останніх хвилинах \"\n\"життя, Король прокляв свою колишню свиту. Він поклявся, що ті хто \"\n\"воспротивилися йому будуть завжди підчинятися Королю в темряві…\\n\"\n\"\\n\"\n\"Після цього все стало ще гірше ніж було! Мертвий Король встав зі свого \"\n\"вічного сну і тепер керує військом нечисті в Лабіринті. Його тіло поховано у \"\n\"склепі на третьому підземному рівні під Собором. Прошу тебе, Майстре, \"\n\"звільни його заблудшу душу та зруйнуй його осквернене тіло…\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"Мастре, як я вам казав, Король був похований трьома рівнями нижче. Він там, \"\n\"внизу, чекає свого шансу знищити цю землю в гнилій темряві…\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"Прокляття нашого Короля минуло, але я боюся, що тут діє більше зло. Проте \"\n\"твоя перемога — добрий знак, що ми ще можемо бути врятовані від темряви, що \"\n\"поглинає нашу землю. Хай Світло веде тебе на твоєму шляху, майстре.\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"Втрата сина була занадто великою трагедією для Короля Леорика. Я зробив усе, \"\n\"що міг, щоб полегшити його безумство, але врешті-решт воно його подолало. З \"\n\"того дня над цим королівством нависло чорне прокляття, але, можливо, якби ти \"\n\"звільнив його дух із земної в’язниці, прокляття було б знято…\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"Я не хочу думати про те, як помер Король. Я хочу запам'ятати його як добрим \"\n\"і справедливим правителем. Його смерть була такою сумною і якось дуже \"\n\"неправильною.\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"Я зробив багато зброї та більшість обладунків, які Король Леорік \"\n\"використовував для спорядження своїх лицарів. Я навіть зробив для нього \"\n\"величезний дворучний меч з найкращого міфрилу, а також польову корону в \"\n\"придачу. Я досі не можу повірити, як він помер, але, мабуть, якась зловісна \"\n\"сила звела його з розуму!\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"Мене це не хвилює. Слухай, ніякий скелет не буде МОЇМ королем. Леорік — \"\n\"Король. Король, ти мене чуєш? СЛАВА КОРОЛЮ!\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"Мертві, що ходять серед живих, слідують за проклятим Королем. Він володіє \"\n\"силою підняти ще більше воїнів для постійно зростаючої армії нежиті. Якщо ти \"\n\"не зупиниш його правління, він неодмінно пройде по цій землі і вб’є всіх, \"\n\"хто ще тут живе.\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"Дивись, я веду тут бізнес. Я не продаю інформацію, і мені байдуже до якогось \"\n\"Короля, який був мертвий довше, ніж я живу. Якщо тобі потрібна якась зброя \"\n\"проти цього Короля нежиті, то я можу тобі допомогти…\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"\"\n\"Тепло життя увійшло в мою могилу. Приготуйся вічно служити моєму Господарю, \"\n\"смертний!\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"Я бачу, ця дивна поведінка і тебе морочить. Я припускаю, що оскільки демони \"\n\"бояться світла сонця і вірять, що воно володіє великою силою, то можливо, \"\n\"зображення на знаку сонця, що сходить, змусило їх повірити, що знак теж \"\n\"володіє таємними силами. Хм, можливо, не всі вони такі розумні, як ми \"\n\"боялися…\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"Учителю, у мене стався дивний випадок. Я знаю, що ти багато знаєш про тих \"\n\"чудовиськ, які мешкають у лабіринті, але це те, чого я не можу зрозуміти… \"\n\"Уночі мене розбудив шкряпаючий звук біля моєї таверни. Коли я виглянув зі \"\n\"своєї спальні, я побачив тіні маленьких демоноподібних створінь у дворі \"\n\"корчми. Через деякий час вони втекли, але не раніше, ніж вкрали табличку до \"\n\"моєї корчми. Я не знаю, чому демони крадуть мій знак, але залишають мою \"\n\"родину в спокої… дивно, правда?\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"О, тобі не було потрібно повертати мій знак, але виходить, що це мені \"\n\"заощадить витрати на виготовлення нового. Що ж, зараз подивлюсь, що б я міг \"\n\"би дати тобі в винагороду? Хм, що в нас тут є… ах, ось! Колись чарівник \"\n\"залишив цю шапку в кімнаті. Можливо, це тобі пригодиться.\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"Боже мій, демони бігають вночі по селу, грабують наші домівки — хіба немає \"\n\"нічого святого? Сподіваюся, що з Огденом і Гардою все гаразд. Хіба що, вони \"\n\"б прийшли до мене, якби їх поранили…\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"О Боже! Так от куди дівся знак? Напевно, ми з бабусею все це проспали. Слава \"\n\"Світлу, що ті чудовиська не напали на таверну.\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"Ти кажеш, що демони вкрали знак Огдена? Це не дуже схоже на звірства, які я \"\n\"чув або бачив.\\n\"\n\" \\n\"\n\"Демони хочуть вирвати твоє серце, а не якийсь знак таверни.\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"Знаєш, що я думаю? Хтось взяв цей знак, і вони хочуть за нього багато \"\n\"грошей. Якби я був Огденом… А я не він, але якби був… Я б просто купив новий \"\n\"знак із гарним малюнком. Щоб там був гарний кухоль елю або шматочок сиру…\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"Жоден смертний не зможе по-справжньому зрозуміти розум демона.\\n\"\n\" \\n\"\n\"Ніколи не давай їм заплутати тебе своїми непомірними вчинками, оскільки це \"\n\"теж може бути їх планом.\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"Що — він каже, що це я взяв? Думаю, що Грізволд теж на його боці.\\n\"\n\" \\n\"\n\"Я вже кілька місяців тому подолав бажання касти знаки. На шматку дерева \"\n\"прибуток не отримаєш.\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"Гей — Ти той, що всіх вбиваєш! Ти даєш мені Магічний Прапор, або ми \"\n\"атакуємо! Ти не підеш з життям! Ти вбиваєш великих потвор і повертаєш Магію. \"\n\"Пройди повз кут і двері, знайди потвор. Ти даєш, ти йдеш!\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"Ти вбиваєш потвор, береш прапор. Ти принеси мені, а то…\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"\"\n\"Ти даєш! Так, добре! Іди зараз, ми сильні. Ми вб'ємо всіх великою Магією!\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"Це не віщує нічого хорошого і підтверджує мої найгірші страхи. Хоча я не \"\n\"дозволяв собі вірити стародавнім легендам, тепер я не можу їх заперечувати. \"\n\"Можливо, настав час розкрити, хто я.\\n\"\n\" \\n\"\n\"Моє справжнє ім’я — Старійшина Декард Кейн, і я — останній нащадок \"\n\"стародавнього Братства, яке займалося захистом таємниць вічного зла. Зла, \"\n\"яке цілком очевидно тепер вирвалось на волю.\\n\"\n\" \\n\"\n\"Архієпископ Лазар, колись найбільш довірений радник Короля Леоріка, повів \"\n\"групу простих городян у Лабіринт, щоб знайти зниклого сина Короля, \"\n\"Альбрехта. Перш ніж вони повернулися, минуло чимало часу, і лише деяким з \"\n\"них вдалося врятуватися.\\n\"\n\" \\n\"\n\"Прокляття на мене — дурня! Я мав би передчути його замасковану зраду. \"\n\"Мабуть, сам Лазар викрав Альбрехта і з тих пір сховав його в Лабіринті. Я не \"\n\"розумію, чому архієпископ звернувся до темряви, чи в чому його інтерес до \"\n\"дитини, хіба що він хоче принести його в жертву своїм темним господарям!\\n\"\n\" \\n\"\n\"Це, мабуть і є те, що він запланував! Ті, хто залишився в живих із його \"\n\"«рятівної групи», кажуть, що Лазаря востаннє бачили втікаючим у найглибші \"\n\"надра лабіринту. Ти маєш поквапитися і врятувати принца від жертовного леза \"\n\"цього божевільного негідника!\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"Ти повинен поспішити і врятувати Альбрехта з рук Лазаря. Принц і жителі \"\n\"королівства розраховують на тебе!\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"Твоя історія дуже похмура, друже. За свій жахливий вчинок Лазар неодмінно \"\n\"згорить у пеклі. Хлопчик, якого ти описуєш — не наш принц, але я вважаю, що \"\n\"Альбрехту все ще загрожує небезпека. Символ сили, про який ти говориш, має \"\n\"бути порталом у самому серці лабіринту.\\n\"\n\" \\n\"\n\"Знай це, друже мій — Зло, проти якого ти борешся, це темний Володар Жахів. \"\n\"Він відомий смертним як Діабло. Саме він був ув’язнений у Лабіринті багато \"\n\"століть тому, і я боюся, що він знову прагне посіяти хаос у виміру людства. \"\n\"Ти маєш пройти через портал і знищити Діабло поки не пізно!\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"Лазар був Архієпископом, який ввів городян у лабіринт. Того дня я втратив \"\n\"багато хороших друзів, а Лазар так і не повернувся. Думаю, що його вбили \"\n\"разом з іншими. Майстре, якщо ти зробиш мені послугу, будь ласка, не говори \"\n\"про той день з Фарнхемом.\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"Я був шокований, коли почув, що жителі міста планували робити тієї ночі. Я \"\n\"думав, що Лазар мав більше глузду, з усіх людей. Він був Архієпископом і, \"\n\"здавалося, завжди дбав про жителів Трістрама. Було так багато поранених, я \"\n\"не міг їх усіх врятувати…\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"Я пам’ятаю Лазаря як дуже доброго і доброзичливого чоловіка. Він виступав на \"\n\"похороні моєї матері і підтримував мене і мою бабусю в дуже скрутний час. Я \"\n\"молюся щовечора, щоб він як-небудь був живий і в безпеці.\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"Я був там, коли Лазар ввів нас у лабіринт. Він говорив про святу відплату, \"\n\"але коли ми почали боротися з тими пекельними виродками, він їх пальцем не \"\n\"торкнувся. Він просто побіг глибше в ті темні безкінечні палати, що \"\n\"наповнені слугами темряви!\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"Вони колють, потім кусають, потім вони всюди, навколо вас. Брехун! БРЕХУН! \"\n\"Вони всі мертві! Мертві! Ти мене чуєш? Вони падають і падають… їх кров \"\n\"розливається по підлозі… це все його вина…\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"Я не знала Лазаря, про якого ти говориш, але відчуваю великий конфлікт \"\n\"всередині його душі. Він представляє велику небезпеку і ні перед чим не \"\n\"зупиниться, щоб служити силам темряви, які визнали його своїм.\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"А, праведний Лазар, який був таким корисним проти тих чудовиськ внизу. Мою \"\n\"ногу не врятував, так же? Дивись, дам тобі пораду просто так. Спитай \"\n\"Фарнхема, він там був.\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"Відмовся від своїх дурних пошуків. Все, що тебе чекає — лють мого Господаря! \"\n\"Рятувати дитину вже пізно. Тепер ти приєднаєшся до нього в пеклі!\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"Хм, не знаю що тобі сказати і що може стати в нагоді. Вода, яка наповнює \"\n\"наші криниці надходить із підземного джерела. Я чув про тунель, що веде до \"\n\"великого озера, можливо вони — одне й те саме. На жаль, я не знаю, що могло \"\n\"б призвести до забруднення нашого джерела.\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"Я завжди намагався тримати великий запас їжі і напоїв у нашому погребі, але \"\n\"оскільки по всьому місту немає прісної води, то і наші запаси скоро \"\n\"вичерпаються.\\n\"\n\" \\n\"\n\"Будь ласка, зроби все, що можеш, або я не знаю, що ми будемо робити далі.\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"Я радий, що вчасно тебе наздогнав ! Вода в наших колодязях стала солонуватою \"\n\"і застояною, і деякі городяни захворіли через неї. Наші запаси прісної води \"\n\"швидко вичерпуються. Я вірю, що є прохід, який веде до джерел, які \"\n\"постачають наше місто. Будь ласка, знайди що причинило це нещастя, інакше ми \"\n\"всі неодмінно загинемо.\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"Прошу, ти маєш поспішити. Кожна минаюча година наближає нас кінця запасів \"\n\"питної води.\\n\"\n\" \\n\"\n\"Довго прожити без твоєї допомоги ми не зможемо.\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"То ти кажеш, що сама присутність демонів спричинила забруднення води? О, під \"\n\"нашим містом ховається справді велике зло, але твоя наполегливість і \"\n\"мужність дає нам надію. Візьми цей перстень, будь ласка — можливо, він \"\n\"допоможе тобі в знищенні цих підлих істот.\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"\"\n\"Моя бабуся дуже слабка, а Гарда каже, що ми не можемо пити воду з криниці. \"\n\"Прошу, ти можеш нам чимось допомогти?\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"Пепін сказав тобі правду. Прісна вода нам дуже скоро знадобиться. Я пробував \"\n\"очистити один з колодязів поменше, але там пахне застійним брудом. Можливо, \"\n\"засмічення іде з джерела.\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"Ти п'єш воду?\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"Жителі Трістрама загинуть, якщо ти не повернеш прісну воду в криниці.\\n\"\n\" \\n\"\n\"Знай таке — демони знаходяться в центрі цієї справи, але вони не знають, що \"\n\"вони наробили.\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"В цей раз, я з тобою. Мій бізнес, так би мовити, закінчиться, якщо немає \"\n\"кому продавати. Краще дізнайся, що відбувається, і як найшвидше!\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"Книга, що говорить про палату з людських кісток? Ну, Палата Кості згадується \"\n\"в деяких архаїчних творах, які я вивчав у бібліотеках Сходу. У цих томах \"\n\"йшлося про те, що, коли Володарі підземного світу хотіли захистити великі \"\n\"скарби, вони створили ділянки, де ті, хто загинули спробувавши вкрасти \"\n\"скарби, будуть зобов’язані його захищати назавжди. Заплутаний, але на диво \"\n\"відповідний кінець?\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"\"\n\"Боюся, що я нічого про це не знаю, Майстре. У Каїна є багато книг, які \"\n\"можуть стати в нагоді.\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"\"\n\"Звучить як дуже небезпечне місце. Якщо ти ризикнеш підти туди, будь \"\n\"обережним.\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"\"\n\"Боюся, що я нічого про це не чув. Можливо, Каїн Розповідач міг би допомогти.\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"Я нічого не знаю про те місце, але ти можеш спитати у Каїна. Він говорить \"\n\"про багато речей, і я б не здивувався, якби він мав відповіді на твої \"\n\"питання.\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"Гаразд, слухай. Є ось ця дерев'яна палата. А його дружина, ну знаєш, вона, \"\n\"говорить дереву… що треба почекати. Тоді я кажу, що це може спрацювати проти \"\n\"нього, але якщо ти думаєш, що я ЗАПЛАЧУ за це… ти… ем… так.\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"Якщо ти загинеш в цій проклятій ділянці, то станеш вічним слугою темних \"\n\"володарів.\\n\"\n\" \\n\"\n\"Іди в Палату Кості на свій страх і ризик.\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"То ти кажеш, величезний і таємничий скарб? Мені було б цікаво взяти у тебе \"\n\"пару речей… або, ще краще, хіба тобі не потрібні рідкісні та дорогі припаси, \"\n\"щоб пережити це випробування?\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"Схоже, архієпископ Лазар підбурив багатьох городян піти в Лабіринт, щоб \"\n\"знайти зниклого сина Короля. Він зіграв на їхніх страхах і збив їх у шалену \"\n\"юрбу. Жоден з них не був готовий до того, що лежало під землею… Лазар \"\n\"покинув їх там, унизу — залишив у лапах невимовних жахів на смерть.\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"Так, Фарнхем бурмотів щось про незграбного звіра, який володів лютою зброєю. \"\n\"Схоже, він назвав його м’ясником.\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"Заради Світла, я знаю цього мерзенного демона. Коли ті, хто пережив атаку, \"\n\"яку вів Лазарь, виповзли з собору — було багато тих, хто носив шрами його \"\n\"гніву на своїх тілах. Я не знаю, чим він розрізав своїх жертв, але це не \"\n\"могло бути з цього світу. Воно лишало рани, нагноєні хворобою, і я бачив, що \"\n\"їх майже неможливо вилікувати. Будь обережним, якщо плануєш битися з цим \"\n\"негідником…\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"Коли Фарнхем сказав щось про м’ясника, який вбиває людей, я не сприйняла це \"\n\"всерйоз. Але оскільки ти про це кажеш, то можливо, це правда.\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"Я бачив те, що Фарнхем називає М’ясником, коли воно прорізало шлях крізь \"\n\"моїх друзів. Воно махнуло тесаком, завбільшки з сокиру, рубало кінцівки й \"\n\"вирізало хоробрих людей там, де вони стояли. Я був відділений від бою \"\n\"безліччю маленьких верескливих демонів і якось знайшов сходи, що ведуть \"\n\"наверх. Я більше ніколи не бачив цього жахливого звіра, але його \"\n\"закривавлене обличчя переслідує мене і донині.\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"Великий! Великий тесак вбиває всіх моїх друзів. Не міг зупинити його, \"\n\"довелося тікати, не міг їх врятувати. У пастці, так багато трупів… так \"\n\"багато друзів… НІІІІІІІІІІ!\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"М’ясник — садистська істота, яка насолоджується тортурами та болем інших. Ти \"\n\"бачив його роботу в п’яниці Фарнхемі. Його знищення зробить багато щоб \"\n\"забезпечити безпеку цього села.\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"Я знаю більше, ніж ти думаєш про цього жахливого лиходія. Його друзі схопили \"\n\"мене і встигли дістати мою ногу, перш ніж Грізволд витягнув мене з тієї \"\n\"нори.\\n\"\n\" \\n\"\n\"Скажу прямо – вбий його, перш ніж він уб’є тебе і додасть твій труп до своєї \"\n\"колекції.\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"Прошу тебе, вислухай. Архієпископ Лазар, він привів нас сюди, щоб знайти \"\n\"загубленого принца. Мерзотник завів нас у пастку! Тепер усі мертві… убиті \"\n\"демоном, якого він назвав М'ясником. Помстись за нас! Знайди цього М'ясника \"\n\"і вбий його, щоб наші душі нарешті упокоїлись…\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"Ти читаєш цікаву риму, написану в стилі, що нагадує мені інші твори. Дай \"\n\"мені подумати — який це був твір?\\n\"\n\" \\n\"\n\"…Тьма огортає Прихованих. Очі, невидимо світяться, лише звуки гострих \"\n\"кігтів, які шкрябають, щоб мучити ті бідні душі, що втратили зір навіки. \"\n\"В'язниця для тих проклятих називається Залами Сліпих…\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"Я ніколи не цікавився поезією. Колись, коли в корчмі все було добре, я \"\n\"наймав бродячих музикантів, але це було так давно.\\n\"\n\" \\n\"\n\"Що? О, так… ну, ти міг би спитати, що знають інші.\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"Він здається дуже знайомим. Я пам’ятаю, як читав щось дуже схоже на цей \"\n\"вірш, досліджуючи історію демонічних страждань. Там говорилося про місце \"\n\"великого зла, що… почекай, ти ж туди не підеш?\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"Якщо у тебе є питання про сліпоту, поговори з Пепіном. Він давав моїй бабусі \"\n\"зілля, яке допомогло прояснити її зір, тож, можливо, він і тобі допоможе.\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"Боюся, що я не чув і не бачив місце, що б відповідало твоєму яскравому \"\n\"опису, друже. Можливо, Каїн Розповідач міг би допомогти.\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"Глянь сюди… Смішно, правда? Зрозумів? Сліпий — глянь сюди?\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"Це місце великих страждань та жахів, і тому воно добре служить своєму \"\n\"господареві.\\n\"\n\" \\n\"\n\"Будь обережним, інакше ти сам надовго там залишишся.\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"Подивимося, я тобі щось продаю? Ні. Ти даєш мені гроші, щоб я тобі \"\n\"розказував? Ні. Ти зараз підеш і будеш говорити з оповідачем, який живе \"\n\"заради таких речей? Так.\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"Ти стверджуєш, що розмовляв з Лахдананом? За життя він був великим героєм. \"\n\"Лахданан був почесною і справедливою людиною, яка роками вірно служила \"\n\"своєму королю. Але, звісно, ти це все знаєш.\\n\"\n\" \\n\"\n\"З тих, кого охопило прокляття короля, Лахданан найменше би підкорився \"\n\"темряві без бою, тому схоже, що твоя історія правдива. Якби я був на твоєму \"\n\"місці, друже, я б знайшов спосіб, як звільнити його від тортур.\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"Ти говориш про відважного воїна, що давно помер! Ну ні, у моїй корчмі таких \"\n\"балачок про бесіди з померлими не буде.\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"Значить, золотий еліксир. Я ніколи раніше не готував зілля такого кольору, \"\n\"тому не можу сказати що станеться, якщо ти його вип'єш. Як твій цілитель, я \"\n\"настійно раджу, що якщо ти знайдеш такий еліксир, роби так, як просить \"\n\"Лахданан, і НЕ пробуй його на собі.\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"\"\n\"Я ніколи раніше не чула про Лахданана. Пробач, але я не зможу тут тобі \"\n\"допомогти.\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"Якщо ти насправді зустрів Лахданана, я б порадив допомогти йому. Я кілька \"\n\"разів мав з ним справу вважаю його чесним і відданим за своєю природою. \"\n\"Прокляття, яке впало на послідовників Короля Леоріка, особливо тяжко \"\n\"обрушилося на нього.\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\" Лахданан мертвий. Усі це знають, і ти не зможеш обдурити мене, щоб я \"\n\"передумав. З мертвими не можна говорити. Я знаю!\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"Ти можете зустріти людей таких як Лахданан, які опинилися в пастці в \"\n\"Лабіринті.\\n\"\n\" \\n\"\n\"Я відчуваю в ньому честь і велику провину. Допоможи йому, і ти допоможеш \"\n\"всьому Трістраму.\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"Зачекай, дай вгадати. Каїна поглинула гігантська тріщина, що відкрилася під \"\n\"ним. Його спалило кулею пекельного вогню, і він більше не зможе відповідати \"\n\"на твої запитання. О, цього не сталося? Тоді, або щось купуй, або іди звідси.\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"Прошу, не вбивай мене, просто вислухай. Колись я був капітаном лицарів \"\n\"Короля Леоріка, справедливо й честно дотримувався законів цієї землі. Тоді \"\n\"його темне прокляття впало на нас за ту роль, що ми зіграли в його трагічній \"\n\"смерті. Коли мої товариші Лицарі піддалися своїй долі, я втік з похоронної \"\n\"палати Короля, шукаючи якийсь спосіб звільнитися від прокляття. Але не \"\n\"вийшло…\\n\"\n\" \\n\"\n\"Я чув про Золотий еліксир, який міг би зняти прокляття і дати моїй душі \"\n\"спокій, але я не зміг його знайти. Моя сила слабшає, а разом з цим і моя \"\n\"остання людяність. Будь ласка, допоможи мені і знайди еліксир. Твої зусилля \"\n\"я відплачу — клянусь своєю честю.\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"\"\n\"Ти не знайшов Золотий еліксир. Я боюся, що навічно приречений. Прошу, не \"\n\"здавайся…\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"Ти врятував мою душу від прокляття, і за це в тебе в боргу. Якщо колись буде \"\n\"спосіб відплатити тобі з-за могили, я знайду його, але поки — візьми мій \"\n\"шолом. Він не знадобиться меня в подорожі, в яку я піду. Нехай він захистить \"\n\"тебе від темних сил внизу. Іди зі Світлом, друже…\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"Грізволд говорить про Ковадло Люті — легендарний артефакт, який довго \"\n\"шукали, але так і не знайшли. Створене з металевих кісток демонів з Лезової \"\n\"Темниці, Ковадло Люті було виплавлене навколо черепів п’яти наймогутніших \"\n\"магів підземного світу. На нім вирізані руни сили та хаосу, і будь-яка зброя \"\n\"або броня, виковане на цьому ковадлі, буде занурене в вимір Хаосу, \"\n\"наповнюючи її магічними властивостями. Кажуть, що через непередбачуваність \"\n\"Хаосу важко знати, яким буде результат…\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"\"\n\"Хіба не було б краще запитати про це Грізволда? Знаєш, він досить умілий.\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"Якби ти шукав інформацію про Товкачик Зцілення або Срібну Чашу Очищення, я \"\n\"міг би тобі допомогти, друже. Однак у цій справі тобі краще поговорити з \"\n\"Грізволдом або з Каїном.\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"Коли ми росли, батько Грізволда розповідав нам про гігантське ковадло, на \"\n\"якому виготовляли могутню зброю. Він сказав, що коли по цьому ковадлу \"\n\"вдарять молотком, земля трясеться від великої люті. Я завжди згадую цю \"\n\"історію коли земля трясеться.\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"Вітаю! Завжди приємно бачити одного з моїх найкращих клієнтів! Я знаю, що ти \"\n\"глибше зайшов в Лабіринт, і в мене є історія, яка можливо, варта твого \"\n\"часу…\\n\"\n\" \\n\"\n\"Один із тих, хто повернувся з Лабіринту, розповів мені про містичне Ковадло, \"\n\"на яке він натрапив під час втечі. Його опис нагадав мені легенди, які я чув \"\n\"у юності про палаючу Кузню Пекла, де виготовляють могутню магічну зброю. \"\n\"Легенда свідчить, що глибоко в Кузні Пекла спочиває Ковадло Люті! Це ковадло \"\n\"містило в собі саму суть демонічного підземного світу…\\n\"\n\" \\n\"\n\"Кажуть, що будь-яка зброя, створена на палаючому ковадлі буде наповнена \"\n\"великою силою. Якщо це ковадло і справді є Ковадлом Люті, я зможу зробити \"\n\"для тебе зброю, здатну перемогти навіть найтемнішого володаря Пекла!\\n\"\n\" \\n\"\n\"Знайди мені це Ковадло, і я візьмуся за роботу!\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"Ще нічого, а? Ну, продовжуй шукати. Зброя, викована на ковадлі, може бути \"\n\"твоєю найбільшою надією, і я впевнений, що зможу зробити тобі легендарну \"\n\"зброю.\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"Я не можу в це повірити! Це Ковадло Люті - молодець, друже. Зараз ми \"\n\"покажемо тим виродкам, що в пеклі немає зброї більш смертоносної, ніж та, \"\n\"яку створили люди! Візьми це і нехай Світло захистить тебе.\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"Грізволд не може продати своє ковадло. Що він тоді робитиме? І я б теж \"\n\"розсердився, якби хтось узяв моє ковадло!\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"У Лабіринті є багато артефактів, які володіють силами, що незбагненні для \"\n\"смертних. Деякі з них мають фантастичну силу, яку може використати Світло, \"\n\"або Темрява. Здобуття Ковадла з Лабіринту може зрушити хід Війни Гріхів у \"\n\"бік Світла.\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"Якби ти знайшли цей артефакт для Грізволда, це могло б серйозно зашкодити \"\n\"моєму бізнесу. Оооо, ти ніколи його не знайдеш.\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"Ворота крові та Зали вогню — пам’ятки містичного походження. Де б ти не \"\n\"знайшов цю книгу, безумовно являється місцем великої сили.\\n\"\n\" \\n\"\n\"Легенди розповідають про п'єдестал, вирізаний з обсидіанового каменю, на \"\n\"інкрустованій кісткою поверхні якого є калюжа киплячої крові. Є також натяки \"\n\"на Камені Крові, що відкриють двері, за якими є стародавній скарб…\\n\"\n\" \\n\"\n\"Природа цього скарбу оповита припущеннями, друже, але кажуть, що стародавній \"\n\"герой Аркейн поклав святий обладунок Доблесть у таємне сховище. Аркейн був \"\n\"першим смертним, який переломив хід Війни Гріхів і вигнав легіони темряви \"\n\"назад у Палаюче Пекло.\\n\"\n\" \\n\"\n\"Перед смертю Аркейна, його обладунки були заховані в таємному сховищі. \"\n\"Кажуть, що коли цей святий обладунок знову знадобиться, постане герой, що \"\n\"надягне Доблесть. Можливо, ти і є той герой…\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"Кожна дитина чує історію воїна Аркейна та його містичної броні, відомої як \"\n\"Доблесть. Якби ти зміг знайти його могилу, ти був би добре захищений від зла \"\n\"в Лабіринті.\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"Хм… звучить як щось, що я повинен пам’ятати, але я був настільки зайнятий \"\n\"вивченням нових ліків і створенням кращих еліксирів, що, мабуть, забув. \"\n\"Вибач…\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"Я часто чула, як хлопці розповідали про чарівну броню під назвою Доблесть. \"\n\"Краще запитай в когось із чоловіків у селі.\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"Броня, відома як Доблесть, може стати тим, що схилить ваги на твою користь. \"\n\"Скажу тобі, що багато хто її шукав, в тому числі і я. Аркейн добре сховав \"\n\"її, друже, і знадобиться більше ніж трохи удачі, щоб розкрити таємниці що \"\n\"ховали її, ось так багато років.\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Хрррррррррррррррррррррррррррр…\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"Якщо ти знайдеш ті Камені Крові, будь обережним використовуючи їх.\\n\"\n\" \\n\"\n\"Шлях повен небезпеки, і твоя єдина надія полягає у вірі в себе.\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"Ти збираєшся знайти броню, відому як Доблесть?\\n\"\n\" \\n\"\n\"Ніхто ніколи не дізнався, де Аркейн сховав речі, і якщо навіть мої контакти \"\n\"не змогли їх знайти, я сумніваюся, що і ти коли-небудь знайдеш.\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"Я знаю лише одну легенду, що говорить про такого воїна. Ця історія міститься \"\n\"в стародавніх хроніках Війни Гріхів…\\n\"\n\" \\n\"\n\"Забруднений тисячею років війни, крові та смерті, Воєвода Крові стоїть на \"\n\"горі пошматованих трупів. Його темний меч кляне чорне прокляття всьому \"\n\"живому; запрошення на тортури будь-кому, хто стане перед цим Катом Пекла.\\n\"\n\" \\n\"\n\"Також написано, що, хоча він колись був смертним, що воював поруч із \"\n\"Легіоном Темряви під час Війни гріхів, він втратив свою людяність через \"\n\"ненаситну кровожерність.\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"Боюся, що я нічого не чув про такого злісного воїна, добрий майстре. \"\n\"Сподіваюся, вам не доведеться з ним битися, бо він здається дуже небезпечним.\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"\"\n\"Каїн розповість тобі набагато більше про щось подібне, ніж я хотів би знати.\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"Якщо тобі треба битися з таким запеклим супротивником, то нехай Світло буде \"\n\"твоїм провідником і захисником. Я буду думати про тебе.\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"Темні та злі легенди оточують Воєводу Крові. Будь готовим, мій друже, бо він \"\n\"не покаже милосердя і не почує поблажок.\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"Завжди треба говорити про Кров? А як щодо квітів, сонця та тієї гарної \"\n\"дівчини, що приносить випивку. Слухай сюди, друже - ти настирний, ти це \"\n\"знаєш?\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"Його майстерність меча вражає, і він прожив тисячі років, знаючи лише війну. \"\n\"Мені жаль… Я не бачу, чи зможеш ти перемогти його.\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"Я ніколи не мав справи з цим Воєводою, що ти говориш, але здається, що в \"\n\"нього часто ламаються мечі. Я не проти, щоб постачати його армію…\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"\"\n\"Мій клинок співає по твоїй крові, смертний, і моїм темнім господарям не буде \"\n\"відмови.\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"Грізволд говорить про Небесний Камінь, що був призначений для анклаву, \"\n\"розташованому на сході. Його везли туди для подальшого дослідження. Цей \"\n\"камінь світився енергією, яка якимось чином надавала бачення, що виходить за \"\n\"межі того, чим могла володіти звичайна людина. Я не знаю, які секрети він \"\n\"приховує, друже, але знайти цей камінь, безумовно, виявилося б найціннішим.\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"Караван зупинився тут, щоб взяти припаси для їх подорожі на схід. Я продав \"\n\"їм чимало свіжих фруктів і чудового солодкового м'яса, яке Гарда тільки \"\n\"закінчила випікати. Прикро що з ними сталося…\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"Я не знаю, що вони думали, що вони могли побачити з тим каменем, але скажу \"\n\"так. Якщо з неба падає каміння, будь обережним!\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"Що ж, караван якихось дуже важливих людей зупинявся тут, але це було досить \"\n\"давно. У них були дивні акценти, і наскільки я пам’ятаю, вони готувались \"\n\"ідти в далеку подорож.\\n\"\n\" \\n\"\n\"Я не знаю, як ти сподіваєшся знайти те, що вони несли.\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"Залишся на хвилинку — у мене є історія, яка може тебе зацікавити. Якийсь час \"\n\"потому, тут проходив караван, який прямував до східних королівств. Він \"\n\"нібито ніс шматочок неба, що впав на землю! Вершники в плащах напали на \"\n\"караван з засідки на північ звідси, біля дороги. Я обшукав уламки в пошуках \"\n\"цієї небесної скелі, але її ніде не було. Якщо ти знайдеш її, то думаю, що \"\n\"зможу виготовити з неї щось корисне.\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"\"\n\"Я все ще чекаю, коли ти принесеш мені той камінь з небес. Я знаю, що можу \"\n\"зробити з нього щось могутнє.\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"Дай мені подивитись - так… так, він такий, як я уявляв. Дай мені хвилинку…\\n\"\n\" \\n\"\n\"Ах, ось. Я розташував шматки каменю в срібному перстні, який залишив мені \"\n\"батько. Сподіваюся, він добре тобі послужить.\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"Колись у мене був гарний перстень; він був дуже дорогий, синій і зелений, і \"\n\"червоний, і срібний. Не пам’ятаю, що з цим сталося. Я дуже сумую за цим \"\n\"перстнем…\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"Небесний Камінь дуже могутній, і якби хтось, окрім Грізволда, запропонував \"\n\"тобі його знайти, я б запобігла цьому. Він приборкає його силу, і ця сила \"\n\"буде на благо всім нам.\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"Якщо хтось зможе щось зробити з того каменю, то це Грізволд. Він знає, що \"\n\"робить, і я поважаю його майстерність, хай би я і намагаюся вкрасти його \"\n\"клієнтів.\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"Відьма Адрія шукає чорний гриб? Я знаю про Чорні Гриби стільки ж, скільки \"\n\"про Червоних Оселедців. Можливо, Цілитель Пепін розкаже більше, але такого \"\n\"немає в жодній з моїх оповідань чи книжок.\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"Я ось що скажу. Ні Гарда, ні я, НІКОЛИ б не подали чорні гриби нашим \"\n\"почесним гостям. Якщо Адрія хоче гриби у своєму рагу, то це її справа, але я \"\n\"не можу допомогти в їх пошуку. Чорні гриби… Гидота!\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"Відьма сказала мені, що ти шукаєш мозок демона, щоб допомогти мені створити \"\n\"еліксир. Він має бути дуже цінним для тих, хто постраждав від тих мерзенних \"\n\"звірів, якщо я зможу розкрити таємниці їхньої алхімії. Якщо ти зможеш \"\n\"видалити мозок демона, коли його вб'єш, я був би вдячний, якби ти приніс \"\n\"його мені.\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"Чудово, це саме те, що мені потрібно. Я зміг закінчити еліксир без нього, \"\n\"але не завадить мати його для вивчення. Не міг б ти віднести це до відьми? Я \"\n\"думаю, що вона чекає на це.\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"\"\n\"Думаю, в погребі в Огдена можуть бути гриби. Чому б тобі не запитати його?\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"Якщо його немає у Адрії, то можеш бути певним, що це справді рідкість. Я не \"\n\"зможу допомогти тобі більше, але це звучить як… величезний, гігантський, \"\n\"набряклий, роздутий гриб! Ну що ж, гарного полювання.\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"Огден мішає ДОБРИЙ чорний гриб, але якщо я його вип’ю, мені стає погано. \"\n\"Слухай, слухай… ось секрет - головне — помірність!\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"Що ми тут маємо? Цікаво, схоже на книгу реактивів. Добре гляди, щоб знайти \"\n\"чорний гриб. Його легко впізнати, він повинен бути досить великим. Якщо \"\n\"знайдеш, його принеси мені, будь ласка?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"Мені потрібен великий чорний гриб. Тепер біжи і принеси його мені, щоб я \"\n\"могла використати його для спеціального варева, над яким я працюю.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"Так, це ідеально підійде для варева, що я роблю. До речі, цілитель шукає \"\n\"мозок якогось демона, щоб лікувати тих, кого вразила його згубна отрута. \"\n\"Вважаю, що він хоче зробити з нього еліксир. Якщо ти допоможеш йому знайти \"\n\"те, що потрібно, то будь ласка, подивись, чи можеш отримати для мене зразок \"\n\"еліксиру.\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"Чому ти приніс це сюди? Наразі мені не потрібен мозок демона. Мені потрібен \"\n\"еліксир, над яким працює Цілитель. Йому потрібен той гротескний орган, який \"\n\"ти тримаєш, а потім принеси мені еліксир. Доволі просто, якщо подумаєш, чи \"\n\"не так?\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"Що? Тепер ти приніс мені той еліксир від цілителя? Я змогла доробити варево \"\n\"без нього. Чому б тобі не залишити його собі…\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"\"\n\"Я не продаю гриби будь-якого розміру чи кольору. Може тобі потрібне щось \"\n\"більш корисне?\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"Отже, легенда Карти реальна. Навіть я ніколи не вірив у неї! Гадаю, настав \"\n\"час сказати тобі правду про те, хто я, мій друже. Бачиш, я не той, яким себе \"\n\"видаю…\\n\"\n\" \\n\"\n\"Моє справжнє ім’я — Старець Декард Кейн, і я — останній нащадок \"\n\"стародавнього Братства, що було присвячене зберіганню та захисту таємниць \"\n\"вічного зла. Зла, яке, очевидно, тепер вийшло на волю…\\n\"\n\" \\n\"\n\"Зло, якому ви протидієш, це темний Лордом Жаху, відомим смертним людям як \"\n\"Діабло. Саме він був ув’язнений у Лабіринті багато століть тому. Карта, яку \"\n\"ти зараз тримаєш, була створена багато років тому, щоб відзначити час, коли \"\n\"Діабло знову повстане з ув’язнення. Коли дві зірки на цій карті зрівняються, \"\n\"Діабло буде на піку своєї сили. Він буде майже непереможним...\\n\"\n\" \\n\"\n\"Тепер ти в гонці з часом, друже! Знайди Діабло та знищ його до того, як \"\n\"зірки зійдуться, бо можливо у нас ніколи більше не буде шансу позбавити світ \"\n\"від його зла!\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"В нас немає часу! Я відчуваю його темну силу, і тільки ти можеш перешкодити \"\n\"йому досягти повної сили.\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"Я впевнений, що ти старався як міг, але боюся, що навіть твоєї сили і волі \"\n\"не вистачить. Діабло зараз на піку своєї земної могутності, і тобі \"\n\"знадобиться вся твоя мужність і сила, щоб перемогти його. Нехай Світло \"\n\"оберігає і веде тебе, друже. Я допоможу всім, чим зможу.\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"Якщо відьма не може тобі допомогти і пропонує звернутися Каїна, чому ти \"\n\"думаєш, що я щось знаю? Схоже, справа дуже серйозна. Поспіши і зустрінься з \"\n\"розповідачем, як каже Адрія.\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"Я не можу розібрати що написано на цій карті, але, можливо, Адрія чи Каїн \"\n\"допоможуть тобі розібрати, від чого вона.\\n\"\n\" \\n\"\n\"Я бачу, що це карта зірок на нашому небі, але більше за це я не вмію.\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"Найкраще запитати про такі речі нашого розповідача.\\n\"\n\" \\n\"\n\"Каїн дуже добре обізнаний у стародавніх писаннях, а це, безсумнівно, \"\n\"найстаріший папірець, який я коли-небудь бачила.\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"Я ніколи не бачив такої карти. Де ти її взяв? Хоча я поняття не маю, як її \"\n\"читати, можливо Каїн чи Адрія зможуть дати відповіді на твої питання.\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"Слухай сюди, підійди ближче. Не знаю, чи ти знаєш те, що я знаю, але у тебе \"\n\"тут справді щось є. Це карта.\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"О, боюся, це не передвіщає нічого хорошого. Ця карта зірок віщує велике \"\n\"лихо, але не мені розказувати її секрети. Настав твій час для дуже серйозної \"\n\"розмови з Розповідачем…\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"Я шукав карту, але це точно не вона. Ти повинні показати її Адрії — вона, \"\n\"напевно, розповість тобі, що це таке. Я скажу одне; вона виглядає старою, а \"\n\"стара карта зазвичай означає що вона цінна.\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"\"\n\"Прошууу, не бий. Не вбивай. Залиш живим і наступного разу принесу добро тобі.\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"Дещо для тебе я роблю. Ще раз, не вбивай Гарбада. Живу і дарую добро.\\n\"\n\" \\n\"\n\"Візьми це як доказ, що я тримаю слово…\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"Ще нічого! Майже готово.\\n\"\n\" \\n\"\n\"Дуже могутнє, дуже сильне. Жити! Жити!\\n\"\n\" \\n\"\n\"Без болю і обіцянки я дотримаюся!\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"Занадто добре для тебе. Дуже могутнє! Хочеш — забери!\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"Що?! Чому ти тут? Усі цих переривання зведуть мене з розуму. Візьми ось це і \"\n\"дай мені працювати. Не турбуй мене більше!\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"Аааа! Товя цікавість обійтеться тобі смертю!!!\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"Привіт, мій друже. Залишся і послухай…\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"Коли ти заглиблюєшся в Лабіринт, ти можеш знайти там томи великих знань.\\n\"\n\" \\n\"\n\"Читай їх уважно, бо вони розкажуть те, чого навіть я не знаю.\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"Я знаю багато міфів і легенд, які можуть мати відповіді на питання, що \"\n\"виникнуть під час твоїх подорожей у Лабіринт. Якщо ти зіткнешся з задачами \"\n\"чи запитаннями, які не знаєш, знайди мене, і я розскажу, що можу.\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"Грізволд — людина великих дій і великої мужності. Б’юся об заклад, він \"\n\"ніколи не розповідав тобі про те, як пішов у Лабіринт, щоб врятувати Вірта, \"\n\"чи не так? Він знає свою долю небезпек, які там знаходяться, а тепер — і ти. \"\n\"Він вправний майстер, і якщо він стверджує, що може чимось тобі допомогти, \"\n\"то можеш розраховувати на його чесність і майстерність.\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"Огден володіє та керує Таверною і Корчмою Висхідного Сонця вже майже чотири \"\n\"роки. Він придбав його всього за кілька місяців, перш ніж все тут пійшло до \"\n\"біса. У нього та його дружини Гарди немає грошей, щоб виїхати, оскільки вони \"\n\"вклали все, що мали, щоб створити собі тут життя. Він хороша людина з \"\n\"глибоким почуттям відповідальності.\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"Бідний Фарнхем. Він є тривожним нагадуванням про приречене зборище, яке \"\n\"увійшло до собору з Лазарем того темного дня. Він утік живим, але його \"\n\"хоробрість і глузд залишилися в тій темній ямі. Нині він знаходить втіху \"\n\"лише на дні кухля, але час від часу в його нісенітницях є частинки правди.\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"Відьма Адрія — аномалія тут, у Трістрамі. Вона прибула невдовзі після того, \"\n\"як собор було осквернено, поки більшість інших тікали. Вона здавалося б, за \"\n\"ніч побудувала невелику хатину на околиці міста, і має при собі багато \"\n\"дивних та загадкових артефактів і томів знань, яких навіть я ніколи раніше \"\n\"не бачив.\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"Історія Вірта страшна і трагічна. Маленькі мерзенні демони що мали гострі \"\n\"списи забрали його з рук матері і потягли в лабіринт. Того дня забрали \"\n\"багато інших дітей, разом з сином Короля Леоріка. Лицарі палацу пішли вниз, \"\n\"але так і не повернулися. Коваль знайшов хлопчика, але не раніше, як \"\n\"мерзенні звірі почали катувати його для своїх садистських втіх.\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"А, Пепін. Я вважаю його справжнім другом — можливо, найближчим з усіх. Він \"\n\"трохи заплутаний часом, але ніколи не існувало більш турботливої чи уважної \"\n\"душі. Його знання та навички мало кому зрівняються, і його двері завжди \"\n\"відкриті.\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"Гілліан — хороша жінка. Її обожнюють за піднесений настрій і легкий сміх, \"\n\"вона займає особливе місце в моєму серці. Вона залишається в таверні, щоб \"\n\"підтримати свою літню бабусю, яка занадто хвора, щоб подорожувати. Я іноді \"\n\"боюся за її безпеку, але знаю, що будь-який чоловік у селі воліє померти, \"\n\"ніж побачити, як їй нашкодять.\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"Вітаю, добрий майстре. Ласкаво просимо до Таверни Висхідного Сонця!\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"Багато шукачів пригод сідали за столи моєї таверни, і в десять разів більше \"\n\"історій було розказано, скільки елю було випито . Єдине, що я коли-небудь \"\n\"чув, щоб хтось із них погодився, це стара аксіома. Можливо, вона допоможе \"\n\"тобі. Плоть можна розрізати, але кістки треба трощити.\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"Коваль Грізволд дуже добре обізнаний зі зброєю та обладунками. Якщо тобі \"\n\"коли-небудь знадобиться робота зі спорядженням, тоді звісно, треба ідти до \"\n\"нього.\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"Фарнхем проводить тут занадто багато часу, топить свої печалі в дешевому \"\n\"елі. Я б змусив його піти, але він все-таки так страждав в Лабіринті.\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"Адрія мудра не по роках, але, признаюсь, вона мене трохи лякає.\\n\"\n\" \\n\"\n\"Ну, неважливо. Якщо тобі коли-небудь доведеться торгувати зачарованими \"\n\"предметами, вона тримає добре укомплектовану хатину через річку.\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"\"\n\"Якщо ти хочеш дізнатися більше про історію села, Розповідач Каїн чимало знає \"\n\"про наше минуле.\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"Вірт — шахрай і маленький негідник. Він завжди потрапляв у неприємності, і \"\n\"це не сюрприз, що з ним сталося.\\n\"\n\" \\n\"\n\"Напевно, він дурів десь, де йому не слід було бути. Мені шкода хлопця, але \"\n\"мені не подобається його компанія.\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"Пепін — добра людина — і, безперечно, найщедріша в селі. Він завжди \"\n\"піклується про потреби інших, але здається, якісь неприємності супроводжують \"\n\"його, куди б він не пішов…\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"Гілліан, моя барменша? Якби не почуття обов’язку перед бабусею, вона б давно \"\n\"втекла звідси.\\n\"\n\" \\n\"\n\"Бог знає, що я благав її піти, сказавши, що буду стежити за старою, але вона \"\n\"занадто мила й турботлива, щоб це зробити.\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"Що турбує тебе, друже?\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"Я зробив дуже цікаве відкриття. На відміну від нас, істоти в Лабіринті \"\n\"можуть зцілювати себе без допомоги зілля або магії. Якщо ти пораниш монстра, \"\n\"переконайся, що він мертвий, інакше він може відновитися.\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"До того, як Собором заволоділо те, що ховається внизу, він був місцем \"\n\"великого вивчання. Там можна знайти багато книг. Якщо ти знайдеш їх, \"\n\"прочитай їх усі, оскільки деякі з них можуть берегти секрети Лабіринту.\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"Грізволд знає про мистецтво війни стільки ж, скільки я про мистецтво \"\n\"зцілення. Він хитрий купець, але його робота не має собі рівних. О, я \"\n\"припускаю, що це може тому, що він єдиний коваль, що тут залишився.\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"Каїн — справжній друг і великий мудрець. У нього велика бібліотека і він має \"\n\"вроджену здатність розпізнати справжню природу речей. Якщо у тебе коли-\"\n\"небудь виникнуть запитання, звертайся до нього.\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"Навіть мій досвід не допоміг повністю вилікувати Фарнхема. О, я зміг зцілити \"\n\"його тіло, але його розум і дух за межами моїх знань.\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"Хоча я використовую деякі обмежені форми магії для створення зілль та \"\n\"еліксирів, Адрія — справжня чарівниця. Здається, вона ніколи не спить, і \"\n\"вона завжди має багато містичних томів і артефактів. Я вважаю, що її хатина \"\n\"набагато більша всередині, ніж ззовні, хоч я ніколи там і не був.\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"Бідний Вірт. Я зробив для нього все можливе, але знаю, що він зневажає той \"\n\"протез, який я змушений був прикріпити до його ноги. Його рани були \"\n\"жахливими. Ніхто, а особливо такий молодий хлопець, не повинен страждати як \"\n\"він.\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"Я справді не розумію, чому Огден залишається тут, у Трістрамі. Він страждає \"\n\"від легкого нервового збудження, але він розумний і працьовитий чоловік, \"\n\"скрізь досяг би успіху, куди б не пішов. Я припускаю, що це може бути страх \"\n\"перед тими жахіттями, що відбуваються в навколо нашого села, або, можливо, \"\n\"його дружина, не бажає нікуди йти.\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"Барменша Огдена — мила дівчина. Її бабуся досить хвора і страждає від \"\n\"марення.\\n\"\n\" \\n\"\n\"Вона стверджує, що це видіння, але я не маю цьому жодних доказів.\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"Добрий день! Чим я можу тобі услужити?\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"\"\n\"Моїй бабусі наснилося, що ти прийдеш і поговориш зі мною. Знаєш, у неї \"\n\"видіння, і вона бачить майбутнє.\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"Жінка на околиці міста — відьма! Здається, вона досить мила, і її ім’я, \"\n\"Адрія, дуже приємно на слух, але я її дуже боюся.\\n\"\n\" \\n\"\n\"Потрібна була б така смілива людина, як ти, щоб побачити, що вона там робить.\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"Жителі Трістраму гордяться своїм Ковалем. Він не тільки умілий майстер, що \"\n\"переміг у багатьох змаганнях своєї гільдії, але й отримав похвалу від самого \"\n\"нашого Короля Леоріка — нехай його душа спочиває з миром. Грізволд також \"\n\"великий герой; можеш спитати Каїна.\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"Каїн був розповідачем Трістраму, скільки я себе пам’ятаю. Він дуже багато \"\n\"знає і може розповісти тобі майже про все.\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"Фарнхем — п’яниця, який наповнює своє пузо — елем, а вуха слухаючих його \"\n\"людей — нісенітницею.\\n\"\n\" \\n\"\n\"Я знаю, що Пепін, і Огден симпатизують йому, але мене так засмучує, що я \"\n\"бачу, як він щоночі все далі і далі впадає в п'яний дурман.\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"Пепін врятував життя моїй бабусі, і я знаю, що ніколи не зможу йому за це \"\n\"віддячити. Його здатність зцілювати будь-яку хворобу потужніша, ніж \"\n\"наймогутніший меч, і загадковіша, ніж будь-яке заклинання, яке ти можете \"\n\"назвати. Якщо тобі коли-небудь знадобиться зцілення, Пепін тобі допоможе.\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"Я виросла з матір'ю Вірта, Кенас. Хоча її лише трохи поранили, коли ті \"\n\"огидні створіння вкрали його, вона так і не одужала. Я думаю, що вона \"\n\"померла через розбите серце. Вірт став підлим юнаком, який прагне лише \"\n\"наживитися на чужому поті. Я знаю, що він страждав і бачив жахи, які навіть \"\n\"я уявити не можу, але частина цієї темряви нависає над ним досі.\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"Огден та його дружина взяли мене та мою бабусю в свій дім і навіть дозволили \"\n\"мені заробити кілька золотих, працюючи в корчмі. Я дуже багато завдячую їм і \"\n\"сподіваюся, що колись покину це місце і допоможу їм відкрити грандіозний \"\n\"готель на сході.\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"Ну, що я можу тобі зробити?\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"Якщо ти шукаєш добру зброю, дозволь мені показати тобі це. Наприклад, візьми \"\n\"якусь тупу булаву. Проти більшості тих невмирущих жахів піде як по маслу, \"\n\"немає нічого кращого, щоб розбивати сухі скелети!\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"Сокира? Так, це хороша зброя, збалансована проти будь-якого ворога. \"\n\"Подивись, як вона розсікає повітря, а потім уяви собі гарну товстенну голову \"\n\"демона на її шляху. Май на увазі, що вона повільно розмахується — але який \"\n\"удар!\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"Подивись на це лезо, на рівновагу. У правильних руках і проти правильного \"\n\"ворога, меч — майстер усієї зброї. Гострому лезу мало чого рубати чи \"\n\"прорізати в нежиті, але проти живого, дихаючого ворога, немає нічого краще, \"\n\"ніж меч!\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"Твоя зброя та броня показуватимуть ознаки боротьби з Темрявою. Якщо ти \"\n\"принесеш їх мені, трохи попрацювавши в гарячій кузні, я зроблю їх як \"\n\"новенькі.\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"Мені доводиться практично провозити контрабандою потрібні мені метали та \"\n\"інструменти з караванів, що огинають околиці нашого проклятого міста, а ця \"\n\"відьма Адрія завжди отримує все, що їй потрібно. Якби я б хоч трохи знав як \"\n\"приборкати магію, як вона, я б зробив справді неймовірні речі.\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"Гілліан — гарна дівчина. Шкода, що в її бабці таке погане здоров’я, інакше я \"\n\"б влаштував, щоб вивезти їх звідси на торговому каравані.\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"Іноді мені здається, що Каїн забагато говорить, але схоже, що це його \"\n\"покликання в житті. Якби я міг гнути сталь так само, як він може гнути твоє \"\n\"вухо, я б зробив лати, достойні Імператора!\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"Я був з Фарнхемом тоді, коли Лазар повів нас у Лабіринт. Я більше ніколи не \"\n\"бачив Архієпископа, і, можливо б не вижив, якби Фарнхем не був поруч зі \"\n\"мною. Я боюся, що напад залишив його душу так само покаліченою, як і мою \"\n\"ногу. Я бився б за нього в цій битві якби міг, але не можу.\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"Хороший чоловік, що ставить потреби інших вище своїх. Ти не знайдеш нікого в \"\n\"Трістрамі — тай й де завгодно, якщо на те пішло — хто б сказав погане про \"\n\"цілителя.\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"Цей хлопець потрапить в серйозні неприємності… або, я мушу сказати, знову \"\n\"потрапить. Я намагався зацікавити його роботою тут, в кузні, навчити чесному \"\n\"ремеслу, але він віддає перевагу високим прибуткам від торгівлі сумнівними \"\n\"товарами. Я не можу злитися на нього після того, що з ним сталося, але я \"\n\"хотів, щоб він хоча б був обережний.\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"У корчмаря мало бізнесу і немає реального способу заробляти. Йому вдається \"\n\"звести кінці з кінцями, забезпечуючи їжею та житлом тих, хто час від часу \"\n\"ходить через село, але вони можуть втекти, не плативши. Якби не запаси зерна \"\n\"та в’яленого м’яса, які він тримав у своєму погребі, то чому б більшість із \"\n\"нас померли б від голоду в той перший рік, коли всю сільську місцевість \"\n\"заполонили демони.\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"Хіба я не можу спокійно випити?\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"Дівчина, що приносить напої? О, так, яка гарна жінка. І добра теж.\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"Чому б та стара карга щось не зробила. Звісно, звісно, у неї є речі, але \"\n\"послухай мене… вона неприродня. Я ніколи не бачив, щоб вона їла чи пила — і \"\n\"не можна вірити тому, хто хоч трохи не п’є.\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"Каїн не той, ким себе видає. Звичайно, звичайно, він розказує хороші \"\n\"історії… деякі з них справді страшні або смішні… але я думаю, що він знає \"\n\"більше, ніж знає, що знає.\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"Грізволд? Старий добрий Грізволд. Я люблю його як брата! Ми билися разом, \"\n\"знаєш, коли… ми… Лазар…  Лазар… Лазар!!!\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"Хе-хе, мені подобається Пепін. Знаєш, він справді старається. Слухай сюди, \"\n\"ти маєш познайомитися з ним. Такий добрий хлопець з людьми, які завжди \"\n\"хочуть допомоги. Гей, я думаю, це було б схоже на тебе, а герой? Я теж був \"\n\"героєм…\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"У Вірта більше проблем, ніж у мене, а я все знаю про проблеми. Слухай сюди — \"\n\"у того пацана добра угода, але він там був, розумієш? Втратив ногу! Треба \"\n\"ходити на шматку дерева. Так сумно, так сумно…\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"Огден — найкращий чоловік у селі. Не думаю, що я дуже подобаюся його \"\n\"дружині, але поки вона буде відкривати бочки, вона нормальна. Я проводжу з \"\n\"Огденом більше часу, ніж всі, але він такий добрий до мене…\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"Хочу тобі дещо сказати, бо я знаю все про ці штуки. Я в цьому знаюсь. Цей \"\n\"ель ось тут найкращий…наааааайкращий! Той інший не годиться з тих пір, як \"\n\"дурні собаки…\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"Мене ніхто ніколи не слу… слухає. Десь – я не знаю де, – але десь під \"\n\"церквою є ціла купа золота. Блищить і сяє, і я просто чекаю, щоб хтось її \"\n\"забрав.\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"Я знаю, що у тебе свої ідеї, і я знаю, що ти в це не повіриш, але та зброя, \"\n\"що в тебе просто не годиться проти тих нелюдів! О, мені байдуже, що говорить \"\n\"Грізволд, вони нічого не можуть зробити, як у старі часи…\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"Якби я був тобою… а я не ти… але якби був, я б продав усе, що в тебе є, і \"\n\"пішов звідси. Той хлопець ось там… У нього завжди є щось хороше, але тобі \"\n\"треба дати йому трохи золота, інакше він навіть не покаже, що у нього є.\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"Я відчуваю душу в пошуках відповідей…\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"Мудрість заробляється, а не дається. Якщо ти знайдеш том знань, поглинай \"\n\"його слова. Якщо ти вже знаєш про таємні секрети, записані в книзі, то \"\n\"пам’ятай — рівень майстерності завжди може підвищитися.\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"Найбільша сила часто триває найкоротше. Ти можеш знайти стародавні слова \"\n\"сили, написані на пергаментних сувоях. Сила цих сувоїв полягає тому, що і \"\n\"учень, і адепт чарує їх з однаковим умінням. Їх слабкість полягає в тому, що \"\n\"їх треба прочитати вголос, і неможливо втримати в голові. Також знай, що \"\n\"такі сувої можна прочитати лише раз, тому використовуй їх обережно.\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"Хоча сонячна спека безмірна, просте полум’я свічки становить більшу \"\n\"небезпеку. Жодна енергія, якою б великою вона не була, не може бути \"\n\"використана без належного зосередження. Для багатьох заклинань зачаровані \"\n\"Посохи можна заряджати магічною енергією багато раз. Я можу відновити їхню \"\n\"силу - але знай, що нічого не робиться безкоштовно.\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"Сума наших знань — у сумі її людей. Якщо ти знайдеш книгу чи сувій, що ти не \"\n\"можете розшифрувати, не соромся принести його мені. Я поділюся тим, що \"\n\"знайшла, якщо я можу зрозуміти їх.\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"Для людини, що знає лише Залізо, немає більшої магії, ніж Сталь. Коваль \"\n\"Грізволд більше чаклує, ніж знає. Його здатності об'єднувати вогонь і метал \"\n\"не має рівних на цій землі.\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"Псування має силу обману, але невинність володіє могутністю чистоти. Молода \"\n\"жінка Гілліан має чисте серце, ставить потреби свого матріарха над своїми. \"\n\"Вона боїться мене, але тільки тому, що не розуміє мене.\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"Скриня, відкрита в темряві, не має більше скарбу, ніж коли її відкрили на \"\n\"світлі. Розповідач Каїн — загадкова людина, але тільки для тих, хто не \"\n\"дивиться. Його знання про те, що лежить під собором, набагато більше, ніж \"\n\"навіть він собі уявляє.\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"Чим більше ти довіряєш одній людині, тим гірше розчарування. Фарнхем втратив \"\n\"свою душу, але не від якогось демона. Вона була втрачена, коли він побачив \"\n\"своїх односельчан, зраджених Архієпископом Лазарем. У нього є цінні знання, \"\n\"але ти маєш відокремити факти від вигадок.\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"Рука, серце і розум можуть творити чудеса, коли вони в повній гармонії. \"\n\"Цілитель Пепін бачить тіло так, як навіть я не можу. Його здатність цілити \"\n\"хворих і поранених посилюється його розумінням варіння еліксирів і зілля. \"\n\"Він твій найкращий союзник в Трістрамі.\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"Є багато, чого ми не можемо побачити в майбутньому, але коли воно настане, \"\n\"ним володітимуть діти. У хлопчика Вірта темнота на душі, але він не \"\n\"становить загрози ні місту, ні його жителям. Його таємні стосунки з \"\n\"шибениками та негласними гільдіями сусідніх міст дають йому доступ до \"\n\"багатьох пристроїв, що нелегко знайти в Трістрамі. Хоча його методи можуть \"\n\"бути докірливими, Вірт може допомогти тобі в боротьбі з Темрявою, що \"\n\"вторгається.\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"Земляні стіни та солом'яний навіс не зроблять дому. Корчмар Огден грає \"\n\"більшу роль у місті, ніж багато хто розуміє. Він надає притулок для Гілліан \"\n\"і її матріарха, підтримує те життя, що залишилось у Фарнхема, і є якорем для \"\n\"всіх, хто залишився в місті, яким колись був Трістрам. Його таверна та \"\n\"прості задоволення, які ще можна знайти там, дають хоч на мить побачити \"\n\"життя, що було раніше. Саме ця пам’ять продовжує живити їхні надії на твій \"\n\"успіх.\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"Псс… сюди…\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"Не всі у Трістрамі можуть використати – чи купити – речі, що ти знайдеш в \"\n\"лабіринті. Навіть не я, як важко не було б в це повірити.\\n\"\n\" \\n\"\n\"Іноді тільки ти зможеш знайти ціль для деяких речей.\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"\"\n\"Не вір всьому, що говорить п'яниця. Забагато елю затуманило його зір і \"\n\"здоровий глузд.\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"Якщо ти не помітив, я не купую у Трістрамі все підряд. Я імпортер якісних \"\n\"товарів. Якщо ти хочеш торгувати мотлохом, то іди до Грізволда, Пепіна або \"\n\"до тієї відьми, Адрії. Я впевнений, що вони розкуплять все, що ти їм \"\n\"принесеш…\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"Що ж, я зобов'язаний ковалю своїм життям - тим що залишилось. Звісно, \"\n\"Грізволд запропонував мені навчання в кузні, і він доволі добрий, але я \"\n\"ніколи не отримаю достатньо грошей, щоб… ну, скажімо, у мене є певні плани, \"\n\"які потребують багато золота.\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"Якби я був на пару років старшим, я б засипав її всіма багатствами, що \"\n\"зібрав, і дозволь мені тебе запевнити, що в мене є дуже хороші речі. \"\n\"Джилліан — красива дівчина, і вона повинна вибратися з Трістрама якомога \"\n\"скоріше. Хм… можливо, я візьму її з собою, коли піду…\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"Каїн занадто багато знає. Він до смерті мене лякає — навіть більше, ніж та \"\n\"жінка за річкою. Він постійно каже мені про те, як мені пощастило, що вижив, \"\n\"і як моя історія передрікається в легендах. Я думаю, що він зійшов з глузду.\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"Фарнхем — оце чоловік з серйозними проблемами, і я знаю наскільки вони \"\n\"серйозні. Він занадто повірив у непорочність однієї людини, а Лазар ввів \"\n\"його в самі щелепи смерті. О, я знаю, як там унизу, тож навіть не починай \"\n\"мені розказувати про свої плани знищити зло, що живе в тому Лабіринті. \"\n\"Просто стеж за ногами…\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"Старий Пепін найкращий в своїй справі, поки тобі не треба щось прикріпити.\\n\"\n\" \\n\"\n\"Якби у мене були хоч одне з тих зіллів, що він варить, у мене все ще була б \"\n\"нога…\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"Адрія справді турбує мене. Звісно, Каїн кидає в мурашки тим, що може \"\n\"розповісти тобі про минуле, але ця відьма може зазирнути у твоє минуле. Вона \"\n\"завжди якось отримує все, що їй потрібно. Адрія отримує в свої руки більше \"\n\"товарів, ніж я бачив, що проходять через ворота Королівського Базару під час \"\n\"Великого Фестивалю.\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"Огден — дурень, що залишився тут. Я міг би вивезти його з міста за дуже \"\n\"розумну ціну, але він наполягає на тому, щоб заробити за допомогою тієї \"\n\"дурної таверни. Принаймні, він дає Гілліан місце для роботи, а його дружина \"\n\"Гарда робить чудовий Пастуховий пиріг…\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"За Залом Героїв стоїть Палата Кості. Вічна смерть чекає кожного, хто захоче \"\n\"вкрасти скарби, що в цій кімнаті. Так говорить Володар Жахів, і так написано.\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"\"\n\"…і тому, замкнена за Воротами Крові та за Залами Вогню, Доблесть чекає, коли \"\n\"Герой Світла прокинеться...\"\n\n# TBD: Make this rhyme\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"Я бачу те, чого не бачиш ти.\\n\"\n\"Зір туманний, потім очі гниють.\\n\"\n\"Коли ти обернешся, їх вже не буде,\\n\"\n\"Шепочуть свою приховану пісню.\\n\"\n\"Тоді ти побачиш, чого бути не може,\\n\"\n\"Тіні рухаються там, де має бути світло.\\n\"\n\"З темряви, з розуму,\\n\"\n\"Падай в Зали Сліпих.\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"Збройниці Пекла — дім Воєводи Крові. За ним лежать тисячі понівечених тіл. \"\n\"Ангелів і людей вирізали, щоб принести його нескінченні жертви Темним, які \"\n\"вимагають лише одне – кров.\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"Стережись і свідчи про істини, що тут лежать, бо вони є останньою спадщиною \"\n\"Хорадріма. Є війна, яка вирує навіть зараз, за межами відомих нам полів — \"\n\"між утопічними королівствами Високих Небес і хаотичними ямами Палаючого \"\n\"Пекла. Ця війна відома як Великий конфлікт, і вона лютувала і горіла довше, \"\n\"ніж будь-яка з зірок на небі. Жодна зі сторін ніколи не отримує владу \"\n\"надовго, оскільки сили Світла і Темряви постійно змагаються за контроль над \"\n\"усім творінням.\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"Стережись і свідчи про істини, які тут лежать, бо вони є останньою спадщиною \"\n\"Хорадріма. Коли Вічний конфлікт між Високими Небесами і Палаючим Пеклом \"\n\"випаде на землю смертних, це називається Війною Гріха. Ангели і демони \"\n\"ходять замасковані серед людей, воюючи таємно, подалі від допитливих очей \"\n\"смертних. Деякі сміливі, могутні смертні навіть об’єдналися з будь-якою \"\n\"стороною і допомогли вирішити хід Війни Гріхів.\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"Стережись і свідчи про істини, які тут лежать, бо вони є останньою спадщиною \"\n\"Хорадріма. Майже триста років тому стало відомо, що три головні зла \"\n\"палаючого пекла таємничим чином прийшли в наш світ. Три брати десятиліттями \"\n\"спустошували землі сходу, а людство тремтіло від них. Наш Орден – Хорадрім – \"\n\"був заснований групою потайливих магів, щоб вистежити та захопити Три Зла \"\n\"раз і назавжди.\\n\"\n\" \\n\"\n\"Оригінальний Хорадрім захопив два з Трьох Зол у потужних артефактах, відомих \"\n\"як Камені душі, і поховав їх глибоко під пустельними східними пісками. Третє \"\n\"Зло уникнуло полону і втекло на захід разом із багатьма Хорадрімами в \"\n\"погоні. Третє Зло - відоме як Діабло, Володар Жаху - врешті-решт був \"\n\"схоплений, його сутність поміщена в Камінь душі та похований в цьому \"\n\"Лабіринті.\\n\"\n\" \\n\"\n\"Будьте попереджені, що камінь душі слід утримувати від відкриття тими, хто \"\n\"не вірить. Якщо Діабло звільниться, він буде шукати тіло, яким легко \"\n\"керувати, оскільки він дуже слабкий — можливо, тіло старого або дитини.\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"Так сталося, що в Палаючих Пеклах відбулася велика революція, відома як \"\n\"Темне Заслання. Менші Зла повалили Три Перші Зла і вигнали їхні духовні \"\n\"форми в вимір смертних. Демони Беліал (Володар Брехні) і Азмодан (Володар \"\n\"Гріха) боролися за правління Пекла під час відсутності Трьох братів. Усе \"\n\"Пекло поділилося між фракціями Беліала та Азмодана, в той час як сили \"\n\"Високих Небес безперервно били по самих Воротах Пекла.\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"Багато демонів подорожували в вимір смертних у пошуках Трьох Братів. За ними \"\n\"слідували ангели, що полювали на них у великих містах Сходу. Ангели вступили \"\n\"в союз з таємним орденом смертних магів, що зветься Хорадрім, які швидко \"\n\"стали досвідченими в полюванні на демонів. Також вони нажили собі багато \"\n\"темних ворогів у підземних світах.\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"Так сталося, що Три Перших Зла були вигнані у формі духів в вимір смертних, \"\n\"і після того, як вони десятиліттями сіяли хаос на Сході, їх зловив проклятий \"\n\"Орден смертного Хорадріма. Хорадрім використовував артефакти, які \"\n\"називаються Каменями Душі, щоб вмістити сутність Мефісто, Володаря \"\n\"Ненависті, і його брата Ваала, Володаря Руйнування. Наймолодший брат - \"\n\"Діабло, Лорд Жаху - втік на захід.\\n\"\n\" \\n\"\n\"Врешті-решт Хорадрім також захопив Діабло в Камені Душі і поховав його під \"\n\"стародавнім, забутим собором. Там Володар Жаху спить і чекає часу свого \"\n\"відродження. Знайте, що він буде шукати молоде і сильне тіло, яким можна \"\n\"володіти, — тіло, що є невинним і яким легко керувати. Тоді він встане, щоб \"\n\"звільнити своїх братів і ще раз розпалити полум'я Війни Гріхів…\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"Всі похвали Діабло - Лорду Жаху і Тому, Хто Вижив Темне Заслання. Коли він \"\n\"прокинувся від довгого сну, мій Володар і Вчитель розповів мені про \"\n\"таємниці, які небагато смертних знають. Він сказав мені, що царства Високих \"\n\"Небес і палаючі ями Пекла, воюють у вічній війні. Він розкрив сили, які \"\n\"принесли цей розбрат у царства людей. Мій повелитель назвав битву за цей \"\n\"світ і всіх, хто в ньому існує, Війною Гріхів.\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"Слава і Хвала Діабло - Повелителю Жаху і Лідеру Трьох. Мій Повелитель \"\n\"говорив мені про своїх братів, Мефісто і Ваала, які давно були вигнані в цей \"\n\"світ. Мій Володар хоче дочекатися і використати свою дивовижну силу, щоб він \"\n\"міг звільнити своїх полонених братів з їх гробниць під пісками сходу. Як \"\n\"тільки мій Повелитель звільнить своїх братів, Війна гріхів знову пізнає лють \"\n\"Трьох.\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"Радуйся і принеси жертву Діабло - Повелителю Жаху і Винищувачу Душ. Коли я \"\n\"розбудив свого Вчителя від сну, він спробував заволодіти смертним тілом. \"\n\"Діабло намагався заволодіти тілом Короля Леоріка, але мій господар був \"\n\"занадто слабкий від ув’язнення. Моєму Повелителю був потрібен простий і \"\n\"невинний якір у цьому світі, і він знайшов, що хлопчик Альбрехт ідеально \"\n\"підходить для цього. У той час як добрий Король Леорік збожеволів від \"\n\"невдалої спроби вселитись в нього, я викрав його сина Альбрехта і привів \"\n\"його до свого господаря. Тепер я чекаю поклику Діабло і молюся, щоб мене \"\n\"винагородили, коли він нарешті стане Володарем цього світу.\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"Слава Богу, що ти повернувся!\\n\"\n\"Багато чого змінилося з тих пір, як ти тут жив, друже. Усе було мирно, поки \"\n\"не прийшли темні вершники і не знищили наше село. Багатьох вирубали там, де \"\n\"вони стояли, а тих, хто брався за зброю, вбивали або тялги на работоргівлю — \"\n\"а то і гірше. Церква на околиці міста була осквернена і використовується для \"\n\"темних ритуалів. Уночі лунають нелюдські крики, але дехто з городян ще може \"\n\"вижили. Йди стежкою, що лежить між моєю таверною і ковальською майcтернею, \"\n\"щоб знайти церкву і врятуй кого зможеш.\\n\"\n\" \\n\"\n\"Я розповім більше, коли ми знову поговоримо. Удачі.\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"Продовжуй свої звідини.  Знайти втрачений скарб непросто.  Знайти схований \"\n\"скарб ще важче.  Дам тобі ось таку пораду.  Не дозволяй піскам часу \"\n\"заплутати твої пошуки.\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"Що?!  Це дурість.  Тут, у Трістрамі, немає скарбів.  Дай мені подивитись!!  \"\n\"О, подивись, малюнки тут неточні.  Вони зовсім не відповідають нашому \"\n\"місту.  Я б мав на увазі те, що під собором, а не те, що лежить під нашим \"\n\"ґрунтом.\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"\"\n\"У мене немає часу говорити про якусь карту, що ти шукаєш.  У мене багато \"\n\"хворих, яким потрібна моя і твоя допомога.\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"Колись гордий Ісволл піймався в пастку глибоко під землею. Його позбавили \"\n\"честі і змінили обличчя.  Його захопили в пастку безкінечних мук. \"\n\"Призначений ховати саме те, що могло б його звільнити.\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"Б’юся об заклад, що Вірт побачив, як ти ідеш, і прикинувся лише для того, \"\n\"щоб потім сміятися з тебе, як ти бігаєш по місту носом в грунт. Я б його \"\n\"проігнорував.\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"Був час, коли це місто було частою зупинкою для мандрівників звідусіль.  З \"\n\"тих пір багато чого змінилося.  Але приховані печери та закопані скарби – \"\n\"звичайні фантазії будь-якої дитини.  Вірт іноді вдається до юнацьких ігор.  \"\n\"Так що це може бути просто його уява.\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"Слухай сюди.  Підійди ближче.  Не знаю, чи ти знаєш те, що я знаю, але у \"\n\"тебе тут справді щось є.  Це карта.\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"Моя бабуся часто розповідає мені історії про дивні сили, які населяють \"\n\"цвинтар біля церкви.  Може тобі було б цікаво почути одну з них.  Вона \"\n\"сказала, що якби ти залишиш належне подання на цвинтарі, увійдеш до собору, \"\n\"щоб помолитися за померлих, а потім повернешся, то подання якимось дивним \"\n\"чином зміниться.  Я не знаю, чи це лише маразм старої хворої жінки, але \"\n\"сьогодні все здається можливим.\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"Хммм.  Значить, величезний і таємничий скарб.  Мммм.  Можливо, мені було б \"\n\"цікаво взяти в тебе кілька речей.  Або ще краще, хіба тобі не потрібні \"\n\"рідкісні та дорогі припаси, щоб пройти це випробування?\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"Отже, ти герой, про якого всі говорили. Можливо, ти міг би допомогти \"\n\"бідному, простому фермеру вийти з жахливої ситуації? На півдні звідси, на \"\n\"краю мого саду, з землі надулася якась жахлива річ! Я не можу дістатися до \"\n\"своїх посівів чи тюків сіна, і мої бідні корови будуть голодувати. Відьма \"\n\"дала ось це мені і сказала, що це підірве ту штуку з мого поля. Якби ти міг \"\n\"її знищити, я був би навіки вдячний. Я б це зробив сам, але хтось має \"\n\"залишитися тут з коровами…\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"Я знав, що все не може бути так просто, як казала та відьма. Це сумний світ, \"\n\"коли ти не можеш довіряти навіть своїм сусідам.\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"Вона зникло? Ти відправив її назад до темних закутків Аїда, що породили \"\n\"його? Що? О, тільки не кажи мені, що ти її не знайшов! Такі речі коштують \"\n\"недешево. Ти маєш знайти її, а потім підірвати ту жахливу річ.\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"Я почув вибух звідти! Велике тобі спасибі, добрий незнайомець. Що з усіма \"\n\"цими речами, що виходять із землі, монстрами, що захоплюють церкву, і так \"\n\"далі, це важкі часи. Я лише бідний фермер, але ось — візьми це, і мою велику \"\n\"подяку.\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"Ой, така в мене біда... може... Ні, я не можу нав'язуватись тобі, коли у \"\n\"тебе інші неприємності. Може, після того, як ти очистиш церкву від тих \"\n\"створінь, ти повернешся... і виділиш трохи часу, щоб допомогти бідному \"\n\"фермеру?\"\n\n# I you find a better onomatopeia of crying in Ukrainian, I'm all ears\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"Гуууу! (хлип) Гуууу! (хлип)\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"Я загубила Тео!  Я загубила свого найкращого друга!  Ми гралися біля річки, \"\n\"і Тео сказав, що хоче подивитися на велику зелену штуку.  Я сказала, що не \"\n\"треба, але ми прокрались туди, а потім раптом вийшов цей ЖУК!  Ми втекли, \"\n\"але Тео впав, і жук СХОПИВ і забрав його !\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"Ти його знайшов?  Будь ласка, знайди Теодора!  Він просто маленький.  Він не \"\n\"може подбати про себе!  Прошу!\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"Ти знайшов його!  Ти знайшов його!  Дякую!  О, Тео, тебе налякали ті \"\n\"неприємні жучки?  Фе!  Тьфу!  Щось прилипло до твого хутра!  Фу!  Давай, \"\n\"Тео, ходімо додому!  Ще раз дякую, герой!\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"Ми довго дрімали, і настав час пробудження.  Після довгого сну ми сповнені \"\n\"сильний голодом.  Вже скоро, ми поживимося…\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"\"\n\"Тобі сподобалось, ссавцю?  Як жалюгідно. Твій маленький світ не буде для нас \"\n\"проблемою.\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"Ці землі будуть осквернені, і наш виводок заполонить поля, які люди \"\n\"називають домом.  Наші вусики огорнуть цей світ, і ми будемо ласувати плоттю \"\n\"його мешканців.  Людина стане нашим майном і їжею.\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"\"\n\"Ах, я чую тебе…ти близько! Близько! Шшшш…запах крові та страху…як привабливо…\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"І в рік Золотого Світла було так постановлено, щоб був зведений великий \"\n\"Собор.  Наріжний камінь цього святого місця мав бути висічений з \"\n\"напівпрозорого каменю Антіраель, названого на честь ангела, який розділив \"\n\"свою владу з Хорадрімом.\\n\"\n\" \\n\"\n\"У рік довгих тіней земля затряслася, а собор розколовся і рухнув.  Коли \"\n\"розпочалося будівництво катакомб і замків, а людство стояло проти \"\n\"спустошення Війни Гріхів, руїни були знайдені в пошуках каменів.  Так \"\n\"сталося, що наріжний камінь зник з очей людей.\\n\"\n\" \\n\"\n\"Камінь був від цього світу – і від усіх світів – оскільки Світло є у всіх \"\n\"речах, і поза всіма речами. Світло і єдність є наслідками цієї святої \"\n\"основи, єдність мети і єдність володіння.\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"Му.\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"Я сказав Му.\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"Я проста корова, ясно?\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"Ну добре, добре.  Насправді я не корова.  Зазвичай я так не ходжу; але я \"\n\"сидів вдома і займався власними справами, і раптом з підлоги почали вилазити \"\n\"жуки, лози, цибулини... це було жахливо!  Якби в мене був час нормально \"\n\"одягнутися, я б виглядав не так погано.  Гей!  Ти б не міг піти до моєї хати \"\n\"і забрати костюм?  Коричневий, а не сірий, той для вечору.  Я б зробив це \"\n\"сам, але я не хочу, щоб мене бачили в цьому убранні.  Ось візьми це, може \"\n\"знадобиться... щоб вбити ті речі, що обросли на моїй хаті.  Її не пропустиш, \"\n\"вона на півдні від розвилки річки... ну знаєш... та, де город заріс .\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"\"\n\"Що ти тут стоїш?  Іди і знайди мій костюм!  І поспіши!  Той Гольштейн мені \"\n\"весь час підморгує!\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"\"\n\"Гей, у тебе є мій костюм?  Швидко, давай його сюди!  Ти не повіриш як ці \"\n\"вуха сверблять!\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"Ні ні ні ні!  Це мій СІРИЙ костюм!  Це для вечора! На офіційні випадки!  Я \"\n\"не можу ось ЦЕ носити.  Ти що, дивак якийсь?  Мені потрібен КОРИЧНЕВИЙ \"\n\"костюм.\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"Ах, так НАБАГАТО краще.  Хух!  Нарешті трохи гідності! Мої роги прямі?  \"\n\"Добре. Дивись.  Дуже дякую за допомогу.  Ось візьми ось це в подарунок; і, \"\n\"знаєш… невеличка порада по моді… тобі б знадобилось трохи… тобі б краще \"\n\"замінити… нутизнаєшпрощояговорю?  Цей мотив шукача пригод такий… ретро.  \"\n\"Невеличка порада, га?  Чао.\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"Подивись.  Я корова.  А ти, ти приманка.  Наберись досвіду!  Тоді і \"\n\"поговоримо…\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"Мабуть, я дав тобі насправді страшне завдання. Якби я міг якось… Тобі б \"\n\"допоміг глечик смачного свіжого молока?\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"\"\n\"О, мені б знадобилася твоя допомога, але, мабуть, після того, як ти очистиш \"\n\"катакомби від осквернення тих звірів.\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"Мені потрібно щось зробити, але я не буду зобов'язувати незнайомця. Можливо \"\n\"після того, як ти пробув тут деякий час, мені буде зручніше просити про \"\n\"послугу.\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"Я бачу у тобі потенціал для величі.  Можливо, колись, поки ти виконуєш свою \"\n\"долю, ти зможеш зайти і зробити мені невеличку послугу?\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"Я думаю, що ти міг би мені допомогти, але, хіба що після того, як станете \"\n\"трохи сильнішим. Я не хотів би зашкодити єдиному шансу села знищити загрозу \"\n\"в церкві!\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"\"\n\"Я — корова, що сама всього досягла.  Досягни чогось, і… от тоді і поговоримо.\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"Мені не потрібно пояснюватися кожному туристу, що проходить повз!  Хіба тобі \"\n\"не треба вбивати монстрів?  Поговоримо пізніше.  Якщо ти виживеш…\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"Перестань мене турбувати.  Я шукаю когось справді героїчного.  І ти не \"\n\"підходиш.  Я не можу тобі довіряти, тебе будь-коли з’їдять монстри… Мені \"\n\"потрібен досвідчений герой.\"\n\n# Puns are lost in translation :(\n# I'm all ears if you happen to know how to restore them\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"Добре, я перестану з маячнею.  Я не хотів заплутати тебе.  Я сидів вдома в \"\n\"поганому настрої, коли все стало зовсім погано; з підлоги виліз цілий натовп \"\n\"монстрів!  Я злякався. Просто так сталося, що я був одягнений у цю Джерсі, \"\n\"коли вибіг за двері, і тепер я виглядаю вкрай смішно.  Якби в мене був \"\n\"якийсь нормальний одяг, то було б не так погано.  Гей!  Ти б не міг піти до \"\n\"моєї хати і забрати костюм?  Коричневий, а не сірий, той для вечору. Я б \"\n\"зробив це сам, але я не хочу, щоб хтось бачив мене таким.  Я б зробив це \"\n\"сам, але я не хочу, щоб мене бачили в цьому убранні.  Ось візьми це, може \"\n\"знадобиться... щоб вбити ті речі, що обросли на моїй хаті.  Її не пропустиш, \"\n\"вона на півдні від розвилки річки... ну знаєш... та, де город заріс.\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"Я пробував заклинання, погрози, відречення та торг із цим негідним \"\n\"створінням — безрезультатно.  Мої методи поневолення менших демонів, \"\n\"здається, не впливають на цього страшного звіра.\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"Мій дім повільно псується підлістю цього ненависного в’язня.  Склепи повні \"\n\"тіней, що рухаються відразу за кутами зору.  Краєм вуха чується ледве \"\n\"помітне дряпання кігтів. Я думаю, що вони шукають цей щоденник.\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"У своїй тираді істота видала своє ім'я — На-Крул.  Я намагався дослідити це \"\n\"ім'я, але менші демони якимось чином знищили мою бібліотеку.  На-Крул… Ім’я \"\n\"наповнює мене холодним жахом. Я вважаю за краще думати про нього лише як про \"\n\"Істоту, а не розмірковувати про його справжнє ім’я.\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"Гнівне виття істоти, що в пастці, не дає мені виспатись.  Він лютує проти \"\n\"того, хто послав його в Порожнечу, і кличе на мене огидні прокляття за те, \"\n\"що я зловив його. Його слова наповнюють моє серце жахом, але я не можу \"\n\"заглушити його голос.\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"В мене майже немає часу.  Я повинен записати способи як ослабити демона, а \"\n\"потім сховати цей текст, щоб його слуги не використали мої знання, щоб \"\n\"звільнити свого володаря. Я сподіваюся, що той, хто знайде цей журнал, буде \"\n\"шукати знання.\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"Той, хто знайде цей сувій, призначається в тому, щоб зупинити демонічну \"\n\"істоту, що ходить у цих стінах.  Мій час закінчився. Навіть зараз його \"\n\"пекельні слуги шкребуть слабкі двері, за якими я ховаюся.\\n\"\n\" \\n\"\n\"Я поранив демона таємною магією і заточив його у цих стінах, але боюся, що \"\n\"цього буде недостатньо.\\n\"\n\" \\n\"\n\"Заклинання, знайдені в трьох моїх гримуарах, забезпечать тобі захищений вхід \"\n\"до його виміру, але лише якщо їх використати в належній послідовності. \"\n\"Важелі біля входу знімуть бар'єри і звільнять демона; не торкайся їх! \"\n\"Використовуй лише ці заклинання, щоб ввійти, інакше його сила може виявитися \"\n\"занадто великою, щоб перемогти його.\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"Пекельний Кабан\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"Жало\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"Псих-Око\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"Арахнон\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"Фелтвін\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"Блювотний Виродок\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"Отруто-хвіст\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"Некро-Око\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"Лорд-Павук\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"Хльостохробак\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"Торчант\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"Пекельний Жук\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"Могильник\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"Могильний Щур\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"Вогняний Кажан\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"Черепокрило\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"Ліч\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"Демон Склепу\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"Пекельний Кажан\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"Кістяний Демон\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"Архі-Ліч\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"Біклоп\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"Річ із Плоті\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"Жнець\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"Кулак Гіганта\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"Ртутний Перстень\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"Перстень Ксорини\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"Перстень Карика\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"Перстень Магми\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"Перстень Містиків\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"Перстень Грому\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"Амулет Охорони\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"Укус Комара\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"Фламбо\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"Броня Мороку\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"Блітцен\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"Грім\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"Широтачі\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"Пожирач Душ\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"Діамантове Лезо\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"Кістяна Кільчаста Броня\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"Демонська Латна Броня\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"Амулет Прислужника\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"Перстень Гладіатора\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"Блазневий\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"Кристалічний\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"Двійниковий\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"спустошення\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"занепаду\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"небезпеки\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"Мана\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"Волхви\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"Блазень\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"Стіна Блискавки\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"Горіння\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"Викривлення\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"Відбиття\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"Берсерк\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"Кільце Вогню\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"Пошук\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"Руна Вогню\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"Руна Світла\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"Руна Нови\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"Руна Горіння\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"Руна Каменю\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"Пробуєте кинути предмет що на підлозі?\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"Сердце\"\n"
  },
  {
    "path": "Translations/zh_CN.po",
    "content": "# Translation of DevilutionX to Chinese (Simplified)\n# @muziling, 2021.\n# @tytannial, 2021.\n# Aaron Sun <AaronSun.Test@gmail.com>, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:21+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Tytannial <Tytannial@outlook.com>\\n\"\n\"Language-Team: Emiliano Augusto Gonzalez\\n\"\n\"Language: zh_CN\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"游戏​设计\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"高级​设计师\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"附加​设计\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"首席​程序员\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"高级​程序员\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"编程\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"特​邀​程序员\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"战网​编程\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"串行​通信​编程\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"安装​程序​编程\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"艺术​总监\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"艺术品\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"技术​艺术品\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"电影​艺术​导演\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D​电影​艺术品\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"电影​技术​艺术品\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"执行​制片人\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"制作人\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"副​制片人\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"破坏​神​突击队\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"音乐\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"音响​设计\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"电影​音乐​与​声音\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"声音​制作、导演​和​播音\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"脚​本​和​故事\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"语音​编辑\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"声音\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"录音​工程师\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"手动​设计​和​布局\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"手工​艺术品\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"QA​临时​总监​（​首席测试）\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"QA​突击队​（​测试​人员​）\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"QA​特别​行动​小组​（​兼容性​测试​人员​）\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"QA​火力​支援​（​附加​测试​人员​） \"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"QA​反​情报\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"网络​信息​服务​秩序\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"客户​支持\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"销售额\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"邓塞尔\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"达​比​里​先生​的​背景​歌手\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"公共​关系\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"营销\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"国际​销售\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"美国​销售\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"制造业\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"法律​与​商业\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"特别​感谢\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"感谢\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"为了​纪念\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"非常​特别​感谢\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"总经理\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"软件​工程\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"艺术​总监\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"艺术家\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"设计\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"声音​设计、SFX​和​音频​工程\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"质量​保证​负责人\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"测试​人员\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"手册\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\t​附加​工作\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"任务​文本​写作\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"感谢\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\t​特别​感谢​暴雪​娱乐\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\tSierra On-Line Inc. Northwest\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"质量​保证​经理\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"质量​保证​铅​测试仪\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"主要​测试​人员\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"附加​测试​人员\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"产品​营销​经理\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"公共​关系​经理\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"副产品​经理\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"千​人​之​戒\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\t​在​这​个​游戏​的​制作​过程​中​没有​灵魂​被​出卖。\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"确定\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"选择​职业\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"取消\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"新建​多​人​游戏​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"新​建​单人​游戏​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"保存​文件​已​存在\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"加载​游戏\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"新​游戏\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"单人​游戏​角色\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"流亡者​和​巫师​只​在​暗黑​破坏​神​的​完整​零售版​中​提供。前往 https://www.gog.com/game/\"\n\"diablo 购买。\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"输入​名称\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"名称​无效。名称​不​能​包含​空格、保留​字符​或​保留​词语。\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"无法​创建​角色。\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"等级:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"力量:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"魔法:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"敏捷:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"活力:\"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\nmsgid \"Savegame:\"\nmsgstr \"保存​游戏​：\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"选择​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"新​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"删​除\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"多​人​游戏​角色\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"删​除​多​人​游戏​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"删​除​单人​游戏​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"是否​确实​要​删除​角色​\\\"​{:s}​\\\"？\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"单人​游戏\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"多​人​游戏\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\nmsgid \"Settings\"\nmsgstr \"设置\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"支持\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"显示​制作组\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"退出​地狱火\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"退出​暗黑​破坏​神\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\nmsgid \"Shareware\"\nmsgstr \"共​享版\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"客户​端​-​服务器​(​TCP)\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\nmsgid \"Offline\"\nmsgstr \"离线\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"多​人​游戏\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"要求:\"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"不​需要​网关\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"选择​连接\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"更改​网关\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"所有​计算机​必须​连接​到​与​TCP​兼容​的​网络。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"所有​计算机​都​必须​连接​到​因特网。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"在​没有​网络​开放​的​情况​下​自己​游玩。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"支持​的​玩家: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\nmsgid \"Diablo\"\nmsgstr \"迪亚波罗\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\nmsgid \"Diablo Shareware\"\nmsgstr \"《​暗黑​破坏​神​》​共​享版\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\nmsgid \"Hellfire\"\nmsgstr \"地​狱火\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\nmsgid \"Hellfire Shareware\"\nmsgstr \"《​地狱火​》​共​享版\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"主机​运行​的​游戏​与​您​不同。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, c++-format\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"主机​运行​的​({:s})​模式​与​你​当前​的​模式​不同。\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"您​的​版本​{:s}​与​主机{:d}.{:d}.{:d}​不​匹配。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"说明:\"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"选择​操作\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"创建​游戏\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\nmsgid \"Create Public Game\"\nmsgstr \"创建​公开​游戏\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"加入​游戏\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\nmsgid \"Public Games\"\nmsgstr \"公开​游戏\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"加载​中​…​…\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"没有\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"取消\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"从​你​选择​的​难度​设置​创建​游戏。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"创建​一​个​公开​游戏，任何​人​都​可​加入​的，游戏​难度​将​依据​你​的​设定。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"输入​游戏​ID​来​加入​一​个​正在​进行​的​游戏。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"输入​一​个​IP​或者​主机​名称​来​加入​一​个​正在​进行​的​游戏。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\nmsgid \"Join the public game already in progress.\"\nmsgstr \"加入​一​个​正在​进行​的​公开​游戏。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"正常\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"噩​梦\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"地狱\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, c++-format\nmsgid \"Difficulty: {:s}\"\nmsgstr \"难度: {:s}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"速度: 正常\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"速度: 快速\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"速度: 更​快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"速度: 最​快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"玩​家数: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"选择​难度\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"加入 {:s} 游戏\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"输入​游戏​ID\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"输入​地址\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"正常​难度​\\n\"\n\"​一​个​新​角色​应​从此​开始，最终​击败迪亚波罗。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"噩​梦​难度​\\n\"\n\"迷宫​里​的​怪物​将​被​强化，这​将​是​一​个​更​大​的​挑战。只​建议​经验​丰富​的​角色​进行​挑战。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"地狱​困难​\\n\"\n\"​最​强大​的​地底​世界​的​生物​潜伏​在地狱​的​大门。只​有​最​有​经验​的​角色​才​能​在​这个​国度​中​冒\"\n\"险。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"你​的​角色​必须​达到​20​级​才​能​进入​噩梦​难度​的​多​人​游戏。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"你​的​角色​必须​达到​30​级​才​能​进入​地狱​难度​的​多​人​游戏。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"选择​游戏​速度\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"快速\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"更​快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"最​快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"正常​\\n\"\n\"​一​个​新​角色​应​从此​开始，最终​击败迪亚波罗。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"快速​\\n\"\n\"迷宫​的​居民们​已经​被​催促​了，这​将​是​一​个​更​大​的​挑战。只​建议​经验​丰富​的​角色​进行​挑\"\n\"战。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"更​快​\\n\"\n\"​地​牢里​的​大多数​怪物会​比​以前​更​快​地​找到​你。只有​经验​丰富​的​勇士​才​能​在​这个​速度​下​砰\"\n\"砰​运气。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"最​快​\\n\"\n\"​地下​世界​的​仆从们​会​毫​不​犹豫​地​冲​过​来​袭击。只有​真正​的​速度​恶魔​才​能​赶​得​上​脚步。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"输入​密码\"\n\n#: Source/DiabloUI/selstart.cpp:49\nmsgid \"Enter Hellfire\"\nmsgstr \"进入​《​地狱火​》\"\n\n#: Source/DiabloUI/selstart.cpp:50\nmsgid \"Switch to Diablo\"\nmsgstr \"切换​到​原版\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"是\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"否\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"按​下任​意手柄按键​进行​修改。\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"绑​定​键位​：\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"按​下任​意键​进行​修改。\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"取消​绑​定键位\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"绑定按键组合：\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"解绑按键组合\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"上​一​个​菜单\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\"我们​维护​的​聊天​服务器​部署​在 Discord.gg/devilutionx ，点击​连接​加入​我们​的​社群，\"\n\"我们​在​那里​谈论​有关​暗黑​破坏​神​以及​地狱火​资料片。\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX​由​Diasurgical​维护，可以​报告​问题​和​错误​地址: https://github.com/\"\n\"diasurgical/devilutionX​为了​帮助​我们​更​好​地​为​您​服务，请​务必​提供​所​使用​的​版本​号，\"\n\"操作​系统，以及​问题​的​性质。\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"免责​声明:\"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\t​暴雪​娱乐​和​GOG.com​不​提供​支持​和​维护​DevilutionX，他们​也​没有​对​DevilutionX​进行​质\"\n\"量​和​兼容性​测试。所有​相关​问题​咨询，请​直接​联系​Diasurgical，而​不​是​暴雪​娱乐​或​\"\n\"GOG.com。\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\"\\t​这个​移植​使用​了 Charis SIL、New Athena Unicode、Unifont 和 Noto，它们​处于​\"\n\"SIL Open Font License、CC-BY 4.0​和​Twitmoji许可​授权。该​移植​还​使用​了​SDL，处于​\"\n\"zlib-license许可。更​多​细节​请​参见​ReadMe。\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"错误\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"​错误​发生​在: {:s}，行{:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"数据​文件​错误\"\n\n#: Source/appfat.cpp:84\n#, c++-format\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"无法​打开​主​数据​存档​({:s})。\\n\"\n\"\\n\"\n\"​确保​它​在​游戏​文件​夹​中，并且​文件​名​都​是​小​写​的。\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"只​读​目录​错误\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"无法​写入​位置: \\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\nmsgid \"Game: \"\nmsgstr \"游戏: \"\n\n#: Source/automap.cpp:1424\nmsgid \"Offline Game\"\nmsgstr \"离线游戏\"\n\n#: Source/automap.cpp:1426\nmsgid \"Password: \"\nmsgstr \"密码: \"\n\n#: Source/automap.cpp:1429\nmsgid \"Public Game\"\nmsgstr \"公开​游戏\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"巢​穴: {:d} 层\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"墓穴: {:d} 层\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"城镇\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"层​数: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"Tab\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"Esc\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"Enter\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"角色​信息\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"任务​日志\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"自动​地图\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"主​菜​单\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"物品​栏\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"法术书\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"发送​消息\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"可用命令：\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"命令\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"是未知的。\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\nmsgid \"Description: \"\nmsgstr \"说明:\"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\"\\n\"\n\"参数：无需额外参数。\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\"\\n\"\n\"参数: \"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"竞技场仅支持多人模式。\"\n\n#: Source/control.cpp:653\nmsgid \"What arena do you want to visit?\"\nmsgstr \"您​想访问哪个竞技场？\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"无效的竞技场数字。有效的数字是：\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"要进入竞技场，你需要在城镇或其他竞技场。\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"检查仅支持多人模式。\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"停止检查玩家。\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"该游戏中没有发现玩家\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"检查玩家：\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"打印帮助概览或指定命令的帮助信息。\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"[命令]\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"进入一个 PvP 竞技场。\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"<竞技场数字>\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"给与竞技场点数。\"\n\n#: Source/control.cpp:802\nmsgid \"<number>\"\nmsgstr \"<数字>\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"查看另一个玩家的状态和装备。\"\n\n#: Source/control.cpp:803\nmsgid \"<player name>\"\nmsgstr \"<玩家名>\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"显示当前层的种子信息。\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"对​玩家​友好\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"玩​家​攻击\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"热键: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"当前​选择​的​法术​按钮\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"热键: “​s​”\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"技能​：​{:s}\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"法术​：​{:s}\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"法术​等级 0 - 无法​使用\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"法术​等级 {:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"{:s}​卷轴\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, c++-format\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:d}卷轴\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"{:s}​法​杖\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, c++-format\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"{:d}充能\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, c++-format\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"{:s}金币堆\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"未​满足​条件\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}, 等级: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"生命值 {:d} 的 {:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right-click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"右击​使用\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"升级\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"你有 {:s} 金币。你想要取出多少？\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"城镇​传送门\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"从​{:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"通​向\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"不​洁​祭坛\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"15​层\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, c++-format\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"无法从文件 {0} 加载数据\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"{0} 是未完成的，请检查文件内容。\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"你的 {0} 文件没有预期的列数，请确保它符合文档格式。\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"{2} 中用于 {1} 的非数字值 {0} 在  {3} 行  {4} 列\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"{2} 中用于 {1} 的值 {0} 越界，在  {3} 行  {4} 列\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"{2} 中用于 {1} 的值 {0} 无效 在  {3} 行  {4} 列\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"打​印​此​消息​并​退出\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"打​印​版本​并​退出\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"指定​diabdat.mpq​的​文件​夹\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"指定​保存​文件​的​文件​夹\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"指定​diablo.ini​的​位置\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"指定语言代码（例如 en 或 pt_BR）\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"跳​过​启动​视频\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"每​秒​显示​帧数\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"启用​详细​日志​记录\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\nmsgid \"Record a demo file\"\nmsgstr \"记录​一​个​录像​文件\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\nmsgid \"Play a demo file\"\nmsgstr \"播放​录像​文件\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"播放​录像​回放​时​禁​用​帧​数​限制\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"游戏​选项​：\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"强制​共​享版​模式\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"强制​原版​模式\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\nmsgid \"Force Hellfire mode\"\nmsgstr \"强制​地狱火​模式\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"地​狱火​选项:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"报告​错误​https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"请更新 devilutionx.mpq 和 fonts.mpq 到最新版\"\n\n#: Source/diablo.cpp:1204\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"\"\n\"无法​加载​UI​资源。\\n\"\n\"\\n\"\n\"​请​检查​DevilutionX.mpq​是否​在​游戏​目录​为​最新​版本。\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"请更新 fonts.mpq 到最新版\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"--​网络​超时--\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"--​等待​玩​家​--\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"没有​可用​的​帮助\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"在​商店​里\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, c++-format\nmsgid \"Belt item {}\"\nmsgstr \"腰​带​物品 {}\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"使用​腰带​中​的​物品。\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"快捷​施法 {}\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"设置​技能​或​法术​热键。\"\n\n#: Source/diablo.cpp:1809\nmsgid \"Previous quick spell\"\nmsgstr \"上​一​个​快捷施法\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"选择前一个快捷施法（循环）。\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"下一个快捷施法\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"选择后一个快捷施法（循环）。\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"使用生命药水\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"使用腰带的生命药水。\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"使用法力药水\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"使用腰带的玛丽药水。\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\nmsgid \"Speedbook\"\nmsgstr \"快捷​法术书\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\nmsgid \"Open Speedbook.\"\nmsgstr \"打开​快捷​法术​书。\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"快速​保存\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\nmsgid \"Saves the game.\"\nmsgstr \"保存​游戏。\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"快速​加载\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\nmsgid \"Loads the game.\"\nmsgstr \"加载​游戏。\"\n\n#: Source/diablo.cpp:1866\nmsgid \"Quit game\"\nmsgstr \"退出​游戏\"\n\n#: Source/diablo.cpp:1867\nmsgid \"Closes the game.\"\nmsgstr \"关闭​游戏。\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"停止​英雄\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"停止​移动​和​正在​执行​的​动作。\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\nmsgid \"Item highlighting\"\nmsgstr \"物品​高亮\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"显示​/​隐藏​地面​物品。\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"切换​物品​高亮\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"永久​显示​/​隐藏​地面​上​的​物品。\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"开关​自动​地图\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"切换​是否​显示​自动​地图。\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"循环地图类型\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"不透明 -> 透明 -> 小地图 -> 无\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"打开​物品​栏​界面。\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\nmsgid \"Character\"\nmsgstr \"角色\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"打开​角色​界面。\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\nmsgid \"Quest log\"\nmsgstr \"任务​日志\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\nmsgid \"Open Quest log.\"\nmsgstr \"打开​任务​日志​界面。\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\nmsgid \"Spellbook\"\nmsgstr \"法术书\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\nmsgid \"Open Spellbook.\"\nmsgstr \"打开​法术​书。\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"快捷​消息 {}\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"使用​快捷​消息​进行​交谈。\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"隐藏​屏幕​提示\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"隐藏​所有​屏幕​提示。\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"缩放\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"缩放​游戏​界面。\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"暂停​游戏\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"暂停​当前​游戏。\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"暂停​游戏（备用）\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Decrease Brightness\"\nmsgstr \"增加​屏幕​亮度。\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\nmsgid \"Reduce screen brightness.\"\nmsgstr \"减少​屏幕​亮度。\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"Increase screen brightness.\"\nmsgid \"Increase Brightness\"\nmsgstr \"增加​屏幕​亮度。\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\nmsgid \"Increase screen brightness.\"\nmsgstr \"增加​屏幕​亮度。\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"帮助\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"打开​帮助​屏幕。\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"屏幕​截图\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"截取​当前​屏幕​画面​的​图片。\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\nmsgid \"Game info\"\nmsgstr \"游戏​信息\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"显示​游戏​信息。\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, c++-format\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s} {:s}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"聊天​记录\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"显示​聊天​记录。\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\nmsgid \"Sort Inventory\"\nmsgstr \"整理物品​栏\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"整理物品栏。\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"控制台\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"打开 Lua 控制台。\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"主要动作\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"工具怪物，和镇民交谈，捡起物品并放到物品栏。\"\n\n#: Source/diablo.cpp:2144\nmsgid \"Secondary action\"\nmsgstr \"次要动作\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"打开箱子，和门交互，捡起物品。\"\n\n#: Source/diablo.cpp:2159\nmsgid \"Spell action\"\nmsgstr \"咒语动作\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"施放激活的法术。\"\n\n#: Source/diablo.cpp:2174\nmsgid \"Cancel action\"\nmsgstr \"取消动作\"\n\n#: Source/diablo.cpp:2175\nmsgid \"Close menus.\"\nmsgstr \"关闭​菜单。\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"向上移动\"\n\n#: Source/diablo.cpp:2201\nmsgid \"Moves the player character up.\"\nmsgstr \"玩家角色上移。\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"向下移动\"\n\n#: Source/diablo.cpp:2207\nmsgid \"Moves the player character down.\"\nmsgstr \"玩家角色下移。\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"左移\"\n\n#: Source/diablo.cpp:2213\nmsgid \"Moves the player character left.\"\nmsgstr \"玩家角色左移。\"\n\n#: Source/diablo.cpp:2218\nmsgid \"Move right\"\nmsgstr \"右移\"\n\n#: Source/diablo.cpp:2219\nmsgid \"Moves the player character right.\"\nmsgstr \"玩家角色右移。\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"站定\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"按住以防止角色移动。\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"启用站定\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"开关角色是否可移动。\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"自动​地图\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\n#, fuzzy\n#| msgid \"Move down\"\nmsgid \"Automap Move Down\"\nmsgstr \"向下移动\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\n#, fuzzy\n#| msgid \"Move left\"\nmsgid \"Automap Move Left\"\nmsgstr \"左移\"\n\n#: Source/diablo.cpp:2323\n#, fuzzy\n#| msgid \"Moves the player character up.\"\nmsgid \"Moves the automap left when active.\"\nmsgstr \"玩家角色上移。\"\n\n#: Source/diablo.cpp:2328\n#, fuzzy\n#| msgid \"Move right\"\nmsgid \"Automap Move Right\"\nmsgstr \"右移\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"向上移动鼠标\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"模拟鼠标向上移动。\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"向下移动鼠标\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"模拟鼠标向下移动。\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"向左移动鼠标\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"模拟鼠标向左移动。\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"向右移动鼠标\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"模拟鼠标向右移动。\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"鼠标左键点击\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"模拟鼠标左键点击。\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\nmsgid \"Right mouse click\"\nmsgstr \"鼠标右键点击\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"模拟鼠标右键点击。\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"游戏手柄快捷法术菜单\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"按住以设置法术快捷键。\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"游戏手柄菜单导航\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"按住开启手柄菜单导航。\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\nmsgid \"Toggle game menu\"\nmsgstr \"切换游戏菜单\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\nmsgid \"Opens the game menu.\"\nmsgstr \"打开游戏菜单。\"\n\n#: Source/diablo_msg.cpp:63\nmsgid \"Game saved\"\nmsgstr \"游戏已保存\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"演示版​没有​多​人​游戏​功能\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"Direct Sound 创建​失败\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"在​共​享版​中​不​可​用\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"没有​足够​的​空间​保存​游戏\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"城镇​中​无法​暂停\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"建议​复制​到​硬盘\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"多​人​同步​问题\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"多​人​游戏​中​无法​暂停\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"保存​中​…​…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"一​种​力量​变强​的​背后​潜藏​着​其他​力量​的​衰弱\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"毁灭​塑造​了​新​的​力量\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"专注​防御​意味​着​放弃​进攻\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"正义​之​剑​迅捷​而​锋利\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"君子​终日​乾乾夕惕若厉无咎\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"法力​的​能量​奔流​不息\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"时间​也​无法​削弱​钢铁​之​力\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"魔法​并不​总是​看​起来​的​那样\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"曾​今​开启​的，如今​却​关上​了\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"无妄​的​力量，以​智慧​为​代价\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"神秘​力量​带来​毁灭\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"不​能​持有​的​东西​不​能​受到​伤害\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"深​红​和​湛蓝​如​太阳​和​天空\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"以​牺牲​自我​为​代价​的​知识​和​智慧\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"一饮而尽，酣畅​淋漓\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"身​在，心​在\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"能量​是​以​智慧​为​代价​的\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"无​心​插柳柳​成荫\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"贪​婪​导致​失败，谦逊​得到​奖励\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"被​仁慈​的​同伴​祝福！\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"命运​之​手​无形​的​操控​一切\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"天行健​君子​以​自强不息\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"生命​的​本质​来自​内在\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"当局​者迷，旁观者​清\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"拯救​是​以​智慧​为​代价​的\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"神秘​将​在​光芒​中​揭露\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"最后​一​个​可能​还​是​第一​个\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"慷慨​自​有​回报\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"你​必须​至少​达到​8​级​才​能​使用​这个。\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"你​必须​至少​达到​13级​才​能​使用​这个。\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"你​必须​至少​达到​17级​才​能​使用​这个。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"获得​奥术​知识！\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"那​不​会​杀掉​你​…​…\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"知识​就​是​力量。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"付出​才​有​回报。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"通过​触碰​获得​了​一些​经验值。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"没有​比家​更​好​的​地方​了。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"精神​能量​被​恢复。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"你​感觉​更加​敏捷。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"你​感觉​更​加强​壮。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"你​觉得​更加​睿智。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"你​感觉​神清气爽。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"这​会​让​意志​崩溃。\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Cathedral\"\nmsgstr \"大​教堂\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Catacombs\"\nmsgstr \"墓室\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"洞窟\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"巢​穴\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Crypt\"\nmsgstr \"墓穴\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"{} {}\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"层 {} {}\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, c++-format\nmsgid \"{} difficulty\"\nmsgstr \"难度​：​{}\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\nmsgid \"In Menu\"\nmsgstr \"菜​单​中\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"环回\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"无法​连接\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"错误: 从​服务器​读取​了​0​个​字节\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq或spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"一些​地狱火​MPQ​无法​找到\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"地​狱火​MPQ​未​能​全部​找到。\\n\"\n\"​请​复制​所有​hf​*​.mpq​文件。\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\nmsgid \"Resolution\"\nmsgstr \"分辨率\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\nmsgid \"Run in Town\"\nmsgstr \"城镇​中​奔跑\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\nmsgid \"Theo Quest\"\nmsgstr \"西奥​任务\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\nmsgid \"Cow Quest\"\nmsgstr \"奶牛​任务\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"自动​拾取​金币\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"自动​拾取​药剂\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\nmsgid \"Auto Oil Pickup\"\nmsgstr \"自动​拾取​油\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\nmsgid \"Auto Pickup in Town\"\nmsgstr \"城镇​中​自动​拾取\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"艾德莉亚​补充​法​力值\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"自动​装备​武器\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"自动​装备​护甲\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"自动​装备​头盔\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"自动​装备​盾​牌\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"自动​装备​首饰\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"随机化​任务\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"显示​物品标签\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"自动​填充腰​带\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"停用​坑​爹​神殿\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"拾​取 生命​恢复​药剂\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"拾​取 完全​生命​恢复​药剂\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"拾​取 法力​恢复​药剂\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"拾​取 完全​法力​恢复​药剂\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"拾​取 活力​恢复​药​水\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"拾​取 完全​活力​恢复​药​水\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"选​项\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"保存​游戏\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"主​菜​单\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"退出​游戏\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"伽马\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"速度\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"音乐​已​禁​用\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"声音\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"声音​已​禁​用\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"暂停\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"快​捷键​(​$​K):\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"F1:    打开​帮助​屏幕\"\n\n#: Source/help.cpp:30\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"Esc:   无法​显示​主菜​单\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"Tab:   显示​自动​地图\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"空​格: 隐藏​所有​信息​栏\"\n\n#: Source/help.cpp:33\nmsgid \"S: Open Speedbook\"\nmsgstr \"S: 打开​快捷​法术书\"\n\n#: Source/help.cpp:34\nmsgid \"B: Open Spellbook\"\nmsgstr \"B: 打开​法术书\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"I: 打开​物品​栏\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"C: 打开​角色​栏\"\n\n#: Source/help.cpp:37\nmsgid \"Q: Open Quest log\"\nmsgstr \"Q: 任务​日志\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"F: 降低​屏幕​亮度\"\n\n#: Source/help.cpp:39\nmsgid \"G: Increase screen brightness\"\nmsgstr \"G: 提高​屏幕​亮度\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"Z: 缩放​游戏​屏幕\"\n\n#: Source/help.cpp:41\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"+ / -: 缩放​放​自动​映射\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"1 - 8: 使用​腰带​上​的​物品\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"F5, F6, F7, F8:     设置​技能​或​法术​热键\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"Shift + 鼠标​左​键: 静止​攻击\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"Shift + 鼠标​左​键(​在​角色​栏): 分配​所有​统计​点数\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"Shift + 鼠标​左​键(​在​物品​栏): 移动​物品​到​腰带​或​装备​/​卸下​物品\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"Shift + 鼠标​左​键(​在​腰带​栏​): 移动​物品​到​腰带\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"移动​(​$​M)​：\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"如果​你​按​住鼠​标键​并且​移动，角色​会​继续​跟着​鼠标​移动。\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"进攻​(​$​C)​：\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"按​住​shift键​点击​左键，可以​让​角色​攻击​时​不​移动。\"\n\n#: Source/help.cpp:57\nmsgid \"$Auto-map:\"\nmsgstr \"自动​地图​(​$​A)​：\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\"要​访问​自动​地图，点击​信息栏​的​'MAP'​按钮​或​按​一下​'​TAB​'键。使用 + 和 - 来​放大​或​缩\"\n\"小。使用​箭头键​滚动​动图。\"\n\n#: Source/help.cpp:63\nmsgid \"$Picking up Objects:\"\nmsgstr \"拾​起​物品​(​$​P):\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\"常​用​的​物品​都​比较​小，比如​药水​和​卷轴，会​被​自动​放入​面板​上方​的​腰带栏。当​一样​物品​\"\n\"放入腰​带栏，一​个​小小​的​数字会​显示​在​那​一​格。物品​可以​通过​按​对应​的​数字​或​右边​点​击\"\n\"来​使用。\"\n\n#: Source/help.cpp:70\nmsgid \"$Gold:\"\nmsgstr \"金币​(​$​G):\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"你​可以​在​物品​栏​里​的​一​堆​金币​上​点击​右键​以​移动​指定​的​数量。\"\n\n#: Source/help.cpp:74\nmsgid \"$Skills & Spells:\"\nmsgstr \"技能 & 法术​(​$​S):\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\"你​可以​点击​面板​的​'​SPELLS'​按钮​来​查看​技能​和​法术​列表。此​处​列出​了​记忆​的​法术​和​可​通\"\n\"过​法杖​获得​的​法术。 左键​单击​您​要​施放​的​法术​将​使​该​法术​准备​就绪。 一​个​准备​好​的​法\"\n\"术​可以​通过​在​游戏​区域​中​单击​右键​来​施放。\"\n\n#: Source/help.cpp:81\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"使用​快捷​法术​书施法​(​$​U)​：\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\"左键​单击​“​准备​就绪​的​技能​”​按钮​将​打开​“​快捷​法术​书​”，它​将​让​您​能够​选择​技能​或者​法术​\"\n\"快速​使用。要​使用​准备​好​的​技能​或​法术，仅​需​右​键​点击​游戏​可​用​区域。\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"Shift + 左键​单击​“​选择​当前​法术​”​按钮​将​清除​准备​好​的​法术。\"\n\n#: Source/help.cpp:88\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"设置​技能​热键(​$​S)​：\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\"您​最多​可以​为​技能、法术​或​卷轴​分配​四​个​热键。 首先​打开​上​一​节​所述​的​“​快捷​法术书​\"\n\"”。 选​中​施法​目标​后，它​将​高亮，这时​按 F5、F6、F7 或 F8 键施法。\"\n\n#: Source/help.cpp:94\nmsgid \"$Spell Books:\"\nmsgstr \"法术书(​$​S)​：\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"阅读​不止​一​本​书​可以​增加​您​对​该​法术​的​了解，使​您​能够​更​有效​地​施展​该​法术。\"\n\n#: Source/help.cpp:200\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"共​享版​地​狱火​帮助\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"地​狱火​帮助\"\n\n#: Source/help.cpp:202\nmsgid \"Shareware Diablo Help\"\nmsgstr \"共​享版​暗黑​破坏​神​帮助\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"暗​黑​破坏​神​帮助\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"按​ESC键​结束，或​按​方向​键​滚动。\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"无法​创建主​窗口\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"没有存放物品的空间\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"精准​之​油\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"掌控​之​油\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"锐利​之​油\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"死亡​之​油\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"技能​之​油\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"铁匠​之​油\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"坚韧​之​油\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"永恒​之​油\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"硬化​之​油\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"防水​之​油\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{1}{0}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{2}{0}{1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{2}{0}{1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"{0}{1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{1}{0}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"增加​武器​的\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"命​中​概率\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"显著​增加​一​件\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"武器​命​中​概率\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"伤害​潜力\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"大大​提高​非弓类​武器\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"的​伤害​潜力\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"减少​护甲​或​武器\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"使用​所​需​属性\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"恢复​20​%​的\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"物品​耐久度\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"增加​一​件​物品​的\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"当前​和​最​大​耐久度\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"使​物品​坚​不​可​摧\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"增加​护甲​和​盾牌​的\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"护甲​等级\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"极​大​增加​护甲​和​盾牌\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"的​护甲​等级\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"设置​火焰​陷阱\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"设置​闪电​陷阱\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"设置​石化​陷阱\"\n\n#: Source/items.cpp:1695\nmsgid \"restore all life\"\nmsgstr \"恢复​所有​生命​值\"\n\n#: Source/items.cpp:1698\nmsgid \"restore some life\"\nmsgstr \"恢复​部分​生命​值\"\n\n#: Source/items.cpp:1701\nmsgid \"restore some mana\"\nmsgstr \"恢复​部分​法力\"\n\n#: Source/items.cpp:1704\nmsgid \"restore all mana\"\nmsgstr \"恢复​所有​法力\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"增加​力量\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"增加​魔法\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"增加​敏捷\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"增加​活力\"\n\n#: Source/items.cpp:1719\nmsgid \"restore some life and mana\"\nmsgstr \"恢复​部分​生命​和​法力\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\nmsgid \"restore all life and mana\"\nmsgstr \"恢复​所有​生命​和​法力\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"（只在竞技场有效）\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"右击​查看\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"右击​使用\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"右击​阅读，然后\\n\"\n\"左击​目标\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"右击​阅读\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"激活​显示\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"打开​物品​使用\"\n\n#: Source/items.cpp:1781\nmsgid \"Activate to use\"\nmsgstr \"激活​使用\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"从​法术​书​中​选择，之后\\n\"\n\"施放​法术​进行​阅读\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"激活​阅读\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"{}显示\"\n\n#: Source/items.cpp:1806\n#, c++-format\nmsgid \"{} to use\"\nmsgstr \"{} 使用\"\n\n#: Source/items.cpp:1809\n#, c++-format\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"从​法术​书​中​选择，之后\\n\"\n\"{} 进行​阅读\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"{}激活​阅读\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"等级: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"金币​容量​翻倍\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"需求:\"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \" {:d} 力量\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \" {:d} 魔法\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \" {:d} 敏捷\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"{:s}法术​书​\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s}​的​耳朵\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"命​中​几​率: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, no-c-format, c++-format\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}% 伤害\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"命​中: {:+d}%​, {:+d}%​伤害\"\n\n#: Source/items.cpp:3883\n#, no-c-format, c++-format\nmsgid \"{:+d}% armor\"\nmsgstr \"{:+d}% 护甲\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"护甲​等级: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"火焰​抗性: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"火焰​抗性: {:+d}% 最​大​值\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"闪电​抗性: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"闪电​抗性: {:+d}% 最​大​值\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"抵抗​魔法: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"抵抗​魔法: {:+d}% 最​大​值\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"所有​抗性: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, c++-format\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"所有​抗性: {:+d}% 最​大​值\"\n\n#: Source/items.cpp:3912\n#, c++-format\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"法术增加{:d}级\"\n\n#: Source/items.cpp:3914\n#, c++-format\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"法术降低{:d}级\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"法术​等级​不​变(?)\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"额外​充能​次数\"\n\n#: Source/items.cpp:3920\n#, c++-format\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:d} {:s} 充能\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"火焰​伤害: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"火焰​伤害: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"闪电​伤害: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"闪电​伤害: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d} 力量\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d} 魔法\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d} 敏捷\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d} 活力\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d} 所有​属性\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d} 来自​敌人​的​伤害\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"生命​值: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"法力值: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"高​耐​久度\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"耐​久度​降低\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"坚​不​可​摧\"\n\n#: Source/items.cpp:3962\n#, no-c-format, c++-format\nmsgid \"+{:d}% light radius\"\nmsgstr \"+{:d}% 照亮​范围\"\n\n#: Source/items.cpp:3964\n#, no-c-format, c++-format\nmsgid \"-{:d}% light radius\"\nmsgstr \"-{:d}% 照亮​范围\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"多​重​射击\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"火箭​伤害: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"火箭​伤害: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"闪​电箭​伤害​{:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"闪​电箭​伤害​{:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"火球​伤害: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"火球​伤害: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"攻击者​受到​1-3点​伤害\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"使用者​失去​所有​法力值\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"吸收​一半​陷阱​伤害\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"击​退​目标\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+200​% 对​恶魔​的​伤害\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"所有​抗性​变为​0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"命​中时​3​%法力​偷取\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"命​中时​5​%​法力​偷取\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"命​中时​3​%​生命​偷取\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"命​中时​5​%​生命​偷取\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"穿透​目标​的​护甲\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"快速​攻击\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"更​快​攻击\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"极​速​攻击\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"最​快​攻击\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"另​一​种​能力​(​NW)\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"快速​打击​回复\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"更​快​打击​回复\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"最​快​打击​回复\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"快速​格挡\"\n\n#: Source/items.cpp:4029\n#, c++-format\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"增加{:d}点伤害\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"发射​随机​速度​箭矢\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"异常​的​物品​损坏\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"改变​耐​久度\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"单手​剑\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"持续​失去​生命值\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"生命​偷取\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"无​力量​要求\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"闪电​伤害: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"闪电​伤害: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"击​中时​触发电​荷弹\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"有​概率​造成​三​倍​伤害\"\n\n#: Source/items.cpp:4054\n#, no-c-format, c++-format\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"减少​{:+d}%​伤害\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x 对​怪物​伤害，1x 反噬​自身\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"随机​0-600​%​伤害\"\n\n#: Source/items.cpp:4060\n#, no-c-format, c++-format\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"低​耐久，{:+d}% d​伤害\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"对抗​恶魔​的​额外​精准\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"对抗​亡灵​的​额外​精准\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50​%​法​力值​转换​至​生命​值\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40​%​的​生命值​转换​至​法力值\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"伤害: {:d}  坚不​可​摧\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"伤害: {:d} 耐久: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"伤害: {:d}-{:d} 坚不​可​摧\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"伤害: {:d}-{:d} 耐久: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"护​甲: {:d} 坚不​可​摧\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"护​甲: {:d} 耐久: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"充能: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"独特​装备\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"未​鉴定\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"骷​髅王​的​巢穴\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"白骨密室\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"迷宫\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"有毒​的​水源​补给\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"大​主教​拉扎鲁斯​的​巢穴\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"教堂竞技场\"\n\n#: Source/levels/setmaps.cpp:33\nmsgid \"Hell Arena\"\nmsgstr \"地狱竞技场\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"生命之环竞技场\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"下​到​地​牢\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"下​到​墓穴\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"下​到​洞窟\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"下​到​地狱\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"下​到​巢穴\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"下​到​地​穴\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"上​到 {:d} 层\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"上​到​城镇\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"下​到 {:d} 层\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"下​到​迪亚波罗\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"上​到​巢穴 {:d} 层\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"上​到​墓穴 {:d} 层\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"世界​的​基石\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"下​到​墓穴 {:d} 层\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"返回​到 {:d} 层\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"无法​打开​存档​文件\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"无效​的​存档​文件\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"玩​家​处于​地狱火​特有​地图\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"无效​的​游戏​状态\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"无法​显示​主菜​单\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"野兽\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"恶魔\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"亡灵\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"类型: {:s} 击杀: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"击杀​总数: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"生命​值: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"没有​魔法​抗性\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"抗性:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" 魔法\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" 火焰\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" 闪​电\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"免疫:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"类型: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"无​抗性\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"无​免疫\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"部分​魔法​抗性\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"部分​魔法​免疫\"\n\n#: Source/mpq/mpq_writer.cpp:174\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"无法​打开​储藏​档案​进行​写入。\"\n\n#: Source/msg.cpp:1701\n#, c++-format\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s}​施放​了​无效法术。\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s}​施放​了​非法​法术。\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"玩​家​{:s}(​等级​{:d}​)​刚​加入​了​游戏\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"比赛​结束​了\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"无法​获取​场景​数据\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"玩​家​{:s}​刚刚​离开​了​游戏\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"玩​家​{:s}​杀死​了​迪亚波罗​并​离开​了​游戏！\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"由于​超时，玩​家​{:s}​的​掉落物​被​删除\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"玩​家​{:s}(​等级​{:d})​已经​在​游戏​中\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"神秘\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"潜行\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"阴郁\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"诡​异\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"魔力\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"岩石\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"教​法\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"强化\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"奇幻\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"炫​目\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"奥秘\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"奇​异\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"怪诞\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"神灵\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"圣佑\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"圣洁\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"精魂\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"幽灵\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"抛弃\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"怪物\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"静谧\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"隔​世\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"华丽\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"微光\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"污染\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"油腻\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"辉​光\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"乞丐\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"闪亮\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"光鲜\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"日光\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"浑浊\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"大​分歧\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"原罪​的​代价​即​是​战争\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"赫拉迪姆​的​故事\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"黑暗​的​流放\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"原罪​之​战\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"三​位​一体\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"超越​的​王国\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"三​部​曲\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"黑色​国王\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"日记: 感悟\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"日记: 会议\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"日记: 长篇​大论\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"日记: 他​的​力量​在​增长\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"日志: 纳·克鲁\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"日记: 结束\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"一​本法术书\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"钉死​的​骷髅\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"控制​杆\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"打开​的​门\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"关闭​的​门\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"封死​的​门\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"古籍\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"卑鄙​之​书\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"骸​骨​控制杆\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"神秘​之​书\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"小​箱子\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"箱子\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"大​箱子\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"石​棺\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"书架\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"书柜\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"木桶\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"茧\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"罐子\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s}​圣坛\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"骸​骨堆\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"典籍\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"血泉\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"无​头​尸\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"目盲​之​书\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"鲜血​之​书\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"纯​净​之泉\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"护​甲\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"武器​架\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"山​羊​圣坛\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"坩​埚\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"浑浊​的​水池\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"泪泉\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"钢铁​之​书\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"鲜血​底​座\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"蘑菇​碎片\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"卑鄙​旗帜\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"被​杀​英雄\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"机关​{:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s}(​已​禁​用​)\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"开\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"关\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\nmsgid \"Game Mode\"\nmsgstr \"游戏​模式\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Gameplay Settings\"\nmsgid \"Game Mode Settings\"\nmsgstr \"游戏性​设置\"\n\n#: Source/options.cpp:423\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"游玩​暗黑​破坏​神原版​或​地狱火​资料片。\"\n\n#: Source/options.cpp:429\nmsgid \"Restrict to Shareware\"\nmsgstr \"限制​只​使用​共​享版\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"使得​游戏​兼容​DEMO版。使得​那些​没有​完整版​的​玩家​可以​游玩​多​人​模式。\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"起​始​模式\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"起​始​模式​设置\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"开​场​动画\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"播​放​开场​动画。\"\n\n#: Source/options.cpp:455\nmsgid \"Splash\"\nmsgstr \"花絮\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"显示​花絮​界面。\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"标志​和​标题界面\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"标题界面\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"暗​黑​破坏​神原版​特殊​设置\"\n\n#: Source/options.cpp:487\nmsgid \"Hellfire specific Settings\"\nmsgstr \"地​狱火​特殊​设置\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"音​频\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"音​频​设置\"\n\n#: Source/options.cpp:504\nmsgid \"Walking Sound\"\nmsgstr \"行走​音效\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"玩​家​行走​的​时候​发出​的​脚步声。\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"自动​装备​音效\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"拾​取​到​物品​后​自动​装备​物品​时​发出​的​音效。\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"物品​拾取​音效\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"拾​取​物品​时​发出​的​音效。\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"采样率\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"音​频​输出​采样率​(​赫兹)\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"声道​数量\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"音频​输出​使用​的​声道​数量。\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"缓冲​大​小\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"缓冲​大​小​(​每​个​通道​每​帧​)\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"重​采样​质量\"\n\n#: Source/options.cpp:510\n#, fuzzy\n#| msgid \"Quality of the resampler, from 0 (lowest) to 10 (highest).\"\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"重​采样​质量，0​(​最​低​)​至​10(​最​大​)。\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\"分辨率​将​影响​你​在​游戏​中​的​可​见​范围。注意​：​当​使用​缩放、整​倍​缩放​或​适应​屏幕​时​可能​\"\n\"不同​于​屏幕​使用​的​分辨率。\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"重采样\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"音频重采样\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"设备\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"音​频​设备\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"图像\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"图像​设置\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"全​屏幕\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"显示​游戏​以​窗口​或是​全​屏幕​模式。\"\n\n#: Source/options.cpp:691\nmsgid \"Fit to Screen\"\nmsgstr \"适应​屏幕\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"自动​设置​游戏​窗口​大小​为​你​的​桌面​比例​和​对应​分辨率。\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"缩放\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\"允许​图像​按照​游戏​分辨率缩放​到​你​的​显示器​分辨率。在​不​改变​显示器​分辨率​大​小时，调\"\n\"整​窗口​调整​大小。\"\n\n#: Source/options.cpp:707\nmsgid \"Scaling Quality\"\nmsgstr \"缩​放​品质\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"在​输出​缩放​图像​时​启用​可选​的​过滤​方式。\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"近似​采样\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"双线性\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"各​向​异性\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"整​倍​缩放\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"点​对​点​对​图像​进行​缩放。\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"垂直​同步\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"在可能的时候缩放。\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" 闪​电\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"颜色​循环\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"在​水流、岩浆​和​酸​液​动画​上​使用​颜色​循环​特效。\"\n\n#: Source/options.cpp:740\nmsgid \"Alternate nest art\"\nmsgstr \"替​换巢​穴​美术\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"游戏​将​会​使用​一​个​其他​的​调色板​来​显示​地狱火​资料​片​中​的​巢穴​地图​地面​贴图。\"\n\n#: Source/options.cpp:742\nmsgid \"Hardware Cursor\"\nmsgstr \"硬件​指针\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"使用​硬件​鼠​标\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"物品​使用​硬件​鼠​标\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"物品​装备​拾起​的​鼠标​使用​硬件​鼠标​模式。\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"硬件​鼠标​最​大​尺寸\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"硬件​鼠​标的​最​大​宽​高。软件​的​回报​的​最​大​鼠标​尺寸。\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"显示​FPS\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"在​屏幕​的​左上角​显示​每​秒​帧数。\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"游戏性\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"游戏性​设置\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"在​原版​或​地狱​火​的​城镇​中​启用​慢跑​和​快跑。这个​选​项​已经​在​资料​片​中​被​应用。\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"限制​鼠​标\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"启用​后​鼠标​将​被​限制​在​游戏​窗口​中。\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"当窗口失去焦点时暂停游戏\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"当启用时，游戏会在失去焦点时暂停。\"\n\n#: Source/options.cpp:787\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"启动​小​女孩​任务。\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"启用​小丑​任务。农夫​莱斯特​将​被​替换​为​完整​的​纳特。\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"友方​伤害\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"是否​允许​发射物​或​法术​在​多​人​游戏​中​伤害​友方​玩家。\"\n\n#: Source/options.cpp:790\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"多人游戏中启用全部任务\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"启用完整/未删减的单人版本任务。\"\n\n#: Source/options.cpp:791\nmsgid \"Test Bard\"\nmsgstr \"测试​吟游​诗人\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"强制​吟游​诗人​角色​出现​在​英雄​选择​菜单。\"\n\n#: Source/options.cpp:792\nmsgid \"Test Barbarian\"\nmsgstr \"测试​野​蛮​人\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"强制​野蛮人​角色​出现​在​英雄​选择​菜单。\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar\"\nmsgstr \"经验​条\"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"在​用户​界面​的​底部​显示​经验条。\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"在商店显示物品图标\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"在商店界面物品描述的左侧显示物品图标。\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"显示​生命​值\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"在​法力球​上​显示​当前​/​最大​生命值。\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"显示​法力值\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"在​法力球​上​显示​当前​/​最​大​法​力值。\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"角色​信息\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"敌对​生命​条\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"敌人​的​生命​条​将​被​显示​在​屏幕​的​顶部。\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"靠近​玩家​的​金币​将​会​被​自动​拾取。\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"靠近​玩家​的​药剂​将​会​被​自动​拾取。\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"靠近​玩家​的​油将​会​被​自动​拾取。\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"是否​城镇​中​也​会​自动​拾取​物品。\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"艾德莉亚​将​会​在​你​光顾​他​的​商店​时​为​你​完全​回复​你​的​法力值。\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"启用​时​会​自动​装备​拾取​的​武器。\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"启用​时​会​自动​装备​拾取​的​护甲。\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"启用​时​会​自动​装备​拾取​的​头盔。\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"启用​时​会​自动​装备​拾取​的​盾牌。\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"启用​时​会​自动​装备​拾取​的​首饰。\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"在​新​游戏​中​随机化​选择​的​可用​任务。\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"显示​怪物​类型\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"鼠​标悬停​在​怪物​身​上​将​会​在​用户​界面​中​显示​描述框，描述​怪物​类型​等​信息。\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"启用后显示地上物品的标签。\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"背包​中​的​消耗​品会​自动​填充​到​腰带​中。\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\"当​启用​后​药锅、炫目圣坛、山羊圣坛、华丽圣坛​和​破碎​圣坛​将​无法​被​点击，标签​也​将​提\"\n\"示​关闭。\"\n\n#: Source/options.cpp:815\nmsgid \"Quick Cast\"\nmsgstr \"快速​施法\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"法术​快捷键​会​立即​释放​该​法术​而​不​是​切换施法​按钮。\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"生命​恢复​药水​自动​拾取​数量。\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"完全​生命​恢复​药水​自动​拾取​数量。\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"法力​恢复​药水​自动​拾取​数量。\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"完全​法力​恢复​药水​自动​拾取​数量。\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"活力​恢复​药水​自动​拾取​数量。\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"完全​活力​恢复​药水​自动​拾取​数量。\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"允许浮动数字\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"在获得 XP/造成伤害等时启用浮动数字。\"\n\n#: Source/options.cpp:824\nmsgid \"Off\"\nmsgstr \"关\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"随机角度\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"仅垂直\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"控制器\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"控制器​设置\"\n\n#: Source/options.cpp:889\nmsgid \"Network\"\nmsgstr \"网络\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"网络​设置\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"交谈\"\n\n#: Source/options.cpp:901\nmsgid \"Chat Settings\"\nmsgstr \"聊天​设置\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"语言\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"设置​游戏​将​使用​哪​种​语言。\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"语言​设置\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"键鼠键位​映射\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"键鼠键位​映射​设置\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"手柄键位映射\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping Settings\"\nmsgstr \"手柄键位映射​设置\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Settings\"\nmsgid \"Mod Settings\"\nmsgstr \"设置\"\n\n#: Source/panels/charpanel.cpp:133\nmsgid \"Level\"\nmsgstr \"等级\"\n\n#: Source/panels/charpanel.cpp:135\nmsgid \"Experience\"\nmsgstr \"经验\"\n\n#: Source/panels/charpanel.cpp:139\nmsgid \"Next level\"\nmsgstr \"下​一​级\"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"基础值\"\n\n#: Source/panels/charpanel.cpp:149\nmsgid \"Now\"\nmsgstr \"当前\"\n\n#: Source/panels/charpanel.cpp:150\nmsgid \"Strength\"\nmsgstr \"力量\"\n\n#: Source/panels/charpanel.cpp:154\nmsgid \"Magic\"\nmsgstr \"魔法\"\n\n#: Source/panels/charpanel.cpp:158\nmsgid \"Dexterity\"\nmsgstr \"敏捷\"\n\n#: Source/panels/charpanel.cpp:161\nmsgid \"Vitality\"\nmsgstr \"活力\"\n\n#: Source/panels/charpanel.cpp:164\nmsgid \"Points to distribute\"\nmsgstr \"可​分配​点​数\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"金币\"\n\n#: Source/panels/charpanel.cpp:174\nmsgid \"Armor class\"\nmsgstr \"护甲​等级\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"命​中​概率\"\n\n#: Source/panels/charpanel.cpp:178\nmsgid \"Damage\"\nmsgstr \"伤害\"\n\n#: Source/panels/charpanel.cpp:184\nmsgid \"Life\"\nmsgstr \"生命\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"法力\"\n\n#: Source/panels/charpanel.cpp:193\nmsgid \"Resist magic\"\nmsgstr \"魔法​抗性\"\n\n#: Source/panels/charpanel.cpp:195\nmsgid \"Resist fire\"\nmsgstr \"火焰​抗性\"\n\n#: Source/panels/charpanel.cpp:197\nmsgid \"Resist lightning\"\nmsgstr \"闪电​抗性\"\n\n#: Source/panels/mainpanel.cpp:91\nmsgid \"char\"\nmsgstr \"角色\"\n\n#: Source/panels/mainpanel.cpp:92\nmsgid \"quests\"\nmsgstr \"任务\"\n\n#: Source/panels/mainpanel.cpp:93\nmsgid \"map\"\nmsgstr \"地图\"\n\n#: Source/panels/mainpanel.cpp:94\nmsgid \"menu\"\nmsgstr \"菜​单\"\n\n#: Source/panels/mainpanel.cpp:95\nmsgid \"inv\"\nmsgstr \"物品​栏\"\n\n#: Source/panels/mainpanel.cpp:96\nmsgid \"spells\"\nmsgstr \"法术\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\nmsgid \"voice\"\nmsgstr \"语音\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"静​音\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"无法​使用\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"伤害: 1/3 目标​生命\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, c++-format\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"治疗 {:d} - {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, c++-format\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"伤害 {:d} - {:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"技能\"\n\n#: Source/panels/spell_book.cpp:176\n#, c++-format\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"法杖 ({:d} 充能)\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"等级 {:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, c++-format\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"法力 {:d}\"\n\n#: Source/panels/spell_list.cpp:159\nmsgid \"Spell\"\nmsgstr \"法术\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"只​能​伤害​亡灵\"\n\n#: Source/panels/spell_list.cpp:173\nmsgid \"Scroll\"\nmsgstr \"卷轴\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"法​杖\"\n\n#: Source/panels/spell_list.cpp:194\n#, c++-format\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"法术​热键 {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"无法​打开​存档\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"无法​加载​角色\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, c++-format\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s} (​等级 {:d}): \"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"聊天​历史 (​消息: {:d}​)\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"{:s} 金币\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"你​想要​取出​多少​金币？\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"等级 {:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"经验: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"最​大​等级\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"下​一​级: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s} 到 {:d} 级\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"国王​李奥瑞克​的​陵寝\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"白骨密室\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"黑暗​的​通道\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"邪恶​祭坛\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"到​{:s}\"\n\n#: Source/quick_messages.cpp:10\nmsgid \"I need help! Come here!\"\nmsgstr \"我​需要​帮助！过来！\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"跟​着​我。\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"这​是​给​你​的。\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"现在​你​死定​了！\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"治疗你自己！\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"当心！\"\n\n#: Source/quick_messages.cpp:16\nmsgid \"Thanks.\"\nmsgstr \"感谢。\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"撤退！\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"对不起。\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"我在等待。\"\n\n#: Source/stores.cpp:131\nmsgid \"Griswold\"\nmsgstr \"格里斯沃尔德\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"佩​金\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"奥格登\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"凯恩\"\n\n#: Source/stores.cpp:136\nmsgid \"Farnham\"\nmsgstr \"法恩汉\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"艾德莉亚\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\nmsgid \"Gillian\"\nmsgstr \"吉莉安\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"怀​特\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"返回\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",  \"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"伤害: {:d}-{:d} \"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"护​甲: {:d} \"\n\n#: Source/stores.cpp:315\n#, c++-format\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"耐久: {:d}/{:d}\"\n\n#: Source/stores.cpp:317\nmsgid \"Indestructible\"\nmsgstr \"坚​不​可​摧的\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"欢迎​来到\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"铁匠​铺\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"您​想:\"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"与​格里斯沃尔德​交谈\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"购买​基础​物品\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"购买​高级​物品\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"出售​物品\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"修理​物品\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"离开​商店\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"我​有​这些​东西​要​卖:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"我​这​有些​高档品​出售:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"你​没有​我​想要​的​东西。\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"要​出售​哪​件​物品？\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"你​没有​需要​修理​的​物品。\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"哪​件​物品​需要​修理？\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"女​巫小屋\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"与​艾德莉亚​交谈\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"购买​物品\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"给​魔杖​重新​充能\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"离开​小​屋\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"你​没有​物品​需要​充能。\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"给​哪​件​物品​充能？\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"你​没有​足够​的​金币\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"您​的​物品​栏​空间​不​足\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"我们​有​生意​往来​吗？\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"您​确定​要​鉴定​这​件​物品​吗？\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"您​确定​要​购买​这​件​物品​吗？\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"您​确定​要​为​该​物品​充能​吗？\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"您​确定​要​出售​这​件​物品​吗？\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"您​确定​要​修理​这​件​物品​吗？\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"假腿​男孩​怀​特\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"和​怀特​谈​谈\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"我​有​东西​要​出售，\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"但​要​花 50 金币\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"才​能​看上​一​眼。\"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"你​找到​了​什么​东西？\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"再见\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"我​有​这个​东西​要​卖:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"离开\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"治疗者​的​家\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"与​佩金​交谈\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"离开​治疗者​的​家\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"镇​上​的​长老\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"与​凯恩​交谈\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"鉴定​一​件​物品\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"你​没有​可以​鉴定​的​物品。你​的​金币: {:d}\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"鉴定​哪​一​件​物品？\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"这​件​物品​是:\"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"完成\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"与​{:s}​交谈\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"与​{:s}​交谈\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"不​可​用\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"在​共​享版​中\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"版本\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"闲聊\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"朝阳​旅店\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"与​奥格登​交谈\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"离开​酒馆\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"与​吉莉安​交谈\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"访问​储藏\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"醉​汉法恩汉\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"与​法恩汉​交谈\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"再见\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"你​的​金币: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"被​杀​的​镇民\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"铁匠​格里斯沃尔德\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"医治者​佩​金\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"受伤​的​镇民\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"酒馆​老板​奥格登\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"长者​凯恩\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"女​巫艾德莉亚\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"酒吧​女​招待​吉莉安\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"奶牛\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"农夫​莱斯特\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"西莉亚\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"完整​的​纳特\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"战士\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"流亡者\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"巫师\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"武僧\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"吟游​诗人\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"野​蛮​人\"\n\n#: Source/translation_dummy.cpp:17\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"僵尸\"\n\n#: Source/translation_dummy.cpp:18\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"尸鬼\"\n\n#: Source/translation_dummy.cpp:19\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"腐尸\"\n\n#: Source/translation_dummy.cpp:20\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"黑​死​病躯\"\n\n#: Source/translation_dummy.cpp:21\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"堕落者\"\n\n#: Source/translation_dummy.cpp:22\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"剁​肉​魔\"\n\n#: Source/translation_dummy.cpp:23\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"魔皮\"\n\n#: Source/translation_dummy.cpp:24\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"暗​魔\"\n\n#: Source/translation_dummy.cpp:25\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"骷​髅\"\n\n#: Source/translation_dummy.cpp:26\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"尸骸​斧兵\"\n\n#: Source/translation_dummy.cpp:27\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"烈​焰​亡灵\"\n\n#: Source/translation_dummy.cpp:28\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"骇​魔\"\n\n#: Source/translation_dummy.cpp:29\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"食​腐魔\"\n\n#: Source/translation_dummy.cpp:30\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"食疫​魔\"\n\n#: Source/translation_dummy.cpp:31\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"暗​影兽\"\n\n#: Source/translation_dummy.cpp:32\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"噬骨魔\"\n\n#: Source/translation_dummy.cpp:33\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"尸骸​弓兵\"\n\n#: Source/translation_dummy.cpp:34\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"骷​髅​队长\"\n\n#: Source/translation_dummy.cpp:35\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"尸骸​队长\"\n\n#: Source/translation_dummy.cpp:36\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"烈​焰​亡灵​队长\"\n\n#: Source/translation_dummy.cpp:37\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"骇魔队​长\"\n\n#: Source/translation_dummy.cpp:38\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"无形​领主\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"潜行​魔\"\n\n#: Source/translation_dummy.cpp:40\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"追踪​魔\"\n\n#: Source/translation_dummy.cpp:41\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"隐形​魔\"\n\n#: Source/translation_dummy.cpp:42\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"幻像​编织者\"\n\n#: Source/translation_dummy.cpp:43\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"萨特领主\"\n\n#: Source/translation_dummy.cpp:44\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"血​肉氏族\"\n\n#: Source/translation_dummy.cpp:45\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"岩石氏族\"\n\n#: Source/translation_dummy.cpp:46\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"火焰氏族\"\n\n#: Source/translation_dummy.cpp:47\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"暗​夜氏族\"\n\n#: Source/translation_dummy.cpp:48\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"魔翼\"\n\n#: Source/translation_dummy.cpp:49\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"闪翼\"\n\n#: Source/translation_dummy.cpp:50\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"幽翼\"\n\n#: Source/translation_dummy.cpp:51\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"雷翼\"\n\n#: Source/translation_dummy.cpp:52\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"酸​液​兽\"\n\n#: Source/translation_dummy.cpp:53\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"喷毒​兽\"\n\n#: Source/translation_dummy.cpp:54\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"深​渊兽\"\n\n#: Source/translation_dummy.cpp:55\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"岩​浆喉\"\n\n#: Source/translation_dummy.cpp:56\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"骷​髅​王\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"屠夫\"\n\n#: Source/translation_dummy.cpp:58\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"领主\"\n\n#: Source/translation_dummy.cpp:59\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"污泥​魔\"\n\n#: Source/translation_dummy.cpp:60\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"蟾​魔\"\n\n#: Source/translation_dummy.cpp:61\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"剥​皮魔\"\n\n#: Source/translation_dummy.cpp:62\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"游龙\"\n\n#: Source/translation_dummy.cpp:63\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"洞​穴蛞蝓\"\n\n#: Source/translation_dummy.cpp:64\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"邪恶游龙\"\n\n#: Source/translation_dummy.cpp:65\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"吞食​虫\"\n\n#: Source/translation_dummy.cpp:66\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"岩浆​魔\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"鲜​血石\"\n\n#: Source/translation_dummy.cpp:68\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"地​狱石\"\n\n#: Source/translation_dummy.cpp:69\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"岩浆​领主\"\n\n#: Source/translation_dummy.cpp:70\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"长​角​魔\"\n\n#: Source/translation_dummy.cpp:71\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"污泥​奔行​魔\"\n\n#: Source/translation_dummy.cpp:72\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"冰霜​冲锋​魔\"\n\n#: Source/translation_dummy.cpp:73\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"黑​曜​石领主\"\n\n#: Source/translation_dummy.cpp:74\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"老​骨头\"\n\n#: Source/translation_dummy.cpp:75\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"红色​死神\"\n\n#: Source/translation_dummy.cpp:76\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"尸妖​恶魔\"\n\n#: Source/translation_dummy.cpp:77\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"不​死炎​魔\"\n\n#: Source/translation_dummy.cpp:78\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"焚化者\"\n\n#: Source/translation_dummy.cpp:79\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"火焰​领主\"\n\n#: Source/translation_dummy.cpp:80\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"末​日​火焰\"\n\n#: Source/translation_dummy.cpp:81\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"地狱​燃烧者\"\n\n#: Source/translation_dummy.cpp:82\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"红色​风暴\"\n\n#: Source/translation_dummy.cpp:83\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"风暴​骑手\"\n\n#: Source/translation_dummy.cpp:84\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"风暴​领主\"\n\n#: Source/translation_dummy.cpp:85\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"漩涡​魔\"\n\n#: Source/translation_dummy.cpp:86\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"魔族​凶兽\"\n\n#: Source/translation_dummy.cpp:87\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"翼​魔\"\n\n#: Source/translation_dummy.cpp:88\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"石​像​鬼\"\n\n#: Source/translation_dummy.cpp:89\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"血​爪\"\n\n#: Source/translation_dummy.cpp:90\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"死翼\"\n\n#: Source/translation_dummy.cpp:91\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"屠杀者\"\n\n#: Source/translation_dummy.cpp:92\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"守护者\"\n\n#: Source/translation_dummy.cpp:93\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"漩涡​王\"\n\n#: Source/translation_dummy.cpp:94\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"炎​魔\"\n\n#: Source/translation_dummy.cpp:95\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"洞​穴虺​蛇\"\n\n#: Source/translation_dummy.cpp:96\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"火焰​蛟​蛇\"\n\n#: Source/translation_dummy.cpp:97\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"金色​虺​蛇\"\n\n#: Source/translation_dummy.cpp:98\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"碧蓝蛟​蛇\"\n\n#: Source/translation_dummy.cpp:99\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"黑​骑士\"\n\n#: Source/translation_dummy.cpp:100\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"末​日守卫\"\n\n#: Source/translation_dummy.cpp:101\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"钢铁​领主\"\n\n#: Source/translation_dummy.cpp:102\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"血​骑士\"\n\n#: Source/translation_dummy.cpp:103\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"撕​裂者\"\n\n#: Source/translation_dummy.cpp:104\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"空壳​尸魔\"\n\n#: Source/translation_dummy.cpp:105\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"痛楚​大师\"\n\n#: Source/translation_dummy.cpp:106\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"现实​编织者\"\n\n#: Source/translation_dummy.cpp:107\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"魅​魔\"\n\n#: Source/translation_dummy.cpp:108\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"冰雪妖​女\"\n\n#: Source/translation_dummy.cpp:109\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"地​狱妖​女\"\n\n#: Source/translation_dummy.cpp:110\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"燃魂妖​女\"\n\n#: Source/translation_dummy.cpp:111\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"顾问\"\n\n#: Source/translation_dummy.cpp:112\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"执法官\"\n\n#: Source/translation_dummy.cpp:113\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"秘​法师\"\n\n#: Source/translation_dummy.cpp:114\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"检察长\"\n\n#: Source/translation_dummy.cpp:115\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"魔像\"\n\n#: Source/translation_dummy.cpp:116\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"黑暗​之​王\"\n\n#: Source/translation_dummy.cpp:117\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"高​阶​巫妖马利葛奴斯\"\n\n#: Source/translation_dummy.cpp:118\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"虚弱​的​贾巴德\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"疯狂​的​扎尔\"\n\n#: Source/translation_dummy.cpp:120\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"鼻屎\"\n\n#: Source/translation_dummy.cpp:121\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"大​主教​拉扎鲁斯\"\n\n#: Source/translation_dummy.cpp:122\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"红色​暴戾\"\n\n#: Source/translation_dummy.cpp:123\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"黑玉\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"拉齐达​南\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"鲜血​战神\"\n\n#: Source/translation_dummy.cpp:126\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"腐尸恶魔\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"污染者\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"纳·库尔\"\n\n#: Source/translation_dummy.cpp:129\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"骷​髅头​基纳克斯\"\n\n#: Source/translation_dummy.cpp:130\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"刀​刃皮肤·鞭​笞者\"\n\n#: Source/translation_dummy.cpp:131\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"脓​包鬼灵\"\n\n#: Source/translation_dummy.cpp:132\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"普克拉特·肮脏者\"\n\n#: Source/translation_dummy.cpp:133\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"剥​骨者\"\n\n#: Source/translation_dummy.cpp:134\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"饥饿​的​食腐狂\"\n\n#: Source/translation_dummy.cpp:135\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"迅捷​的​古特申克\"\n\n#: Source/translation_dummy.cpp:136\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"碎​颅​·猛盾\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"邦​戈\"\n\n#: Source/translation_dummy.cpp:138\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"腐肉​搅​碎者\"\n\n#: Source/translation_dummy.cpp:139\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"影咬\"\n\n#: Source/translation_dummy.cpp:140\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"死​眼\"\n\n#: Source/translation_dummy.cpp:141\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"疯眼​·亡魂\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"丘帕卡布拉斯\"\n\n#: Source/translation_dummy.cpp:143\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"火骷髅\"\n\n#: Source/translation_dummy.cpp:144\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"扭曲​颅骨\"\n\n#: Source/translation_dummy.cpp:145\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"血​肉舌\"\n\n#: Source/translation_dummy.cpp:146\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"脉​冲​爬行者\"\n\n#: Source/translation_dummy.cpp:147\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"月亮​狂欢者\"\n\n#: Source/translation_dummy.cpp:148\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"饥​渴​怨魂\"\n\n#: Source/translation_dummy.cpp:149\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"刺食者\"\n\n#: Source/translation_dummy.cpp:150\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"燃烧​的​黑色​余烬\"\n\n#: Source/translation_dummy.cpp:151\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"影鸦\"\n\n#: Source/translation_dummy.cpp:152\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"虚弱​的​亮石\"\n\n#: Source/translation_dummy.cpp:153\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"拜弗洛斯·深渊​领主\"\n\n#: Source/translation_dummy.cpp:154\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"血​皮·暗弓\"\n\n#: Source/translation_dummy.cpp:155\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"邪翼\"\n\n#: Source/translation_dummy.cpp:156\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"暗​饮者\"\n\n#: Source/translation_dummy.cpp:157\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"迷​雾​移形​怪\"\n\n#: Source/translation_dummy.cpp:158\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"夺命喷\"\n\n#: Source/translation_dummy.cpp:159\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"刨脏\"\n\n#: Source/translation_dummy.cpp:160\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"死亡​之​影·肉锤\"\n\n#: Source/translation_dummy.cpp:161\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"疯狂​的​战斗蛆​虫\"\n\n#: Source/translation_dummy.cpp:162\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"玻璃​颅​·锯齿\"\n\n#: Source/translation_dummy.cpp:163\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"死疫​之​火\"\n\n#: Source/translation_dummy.cpp:164\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"冰​之​夜翼\"\n\n#: Source/translation_dummy.cpp:165\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"血​肉石\"\n\n#: Source/translation_dummy.cpp:166\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"青铜​拳​·火石\"\n\n#: Source/translation_dummy.cpp:167\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"怒火​·末日\"\n\n#: Source/translation_dummy.cpp:168\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"火伤·凶魔\"\n\n#: Source/translation_dummy.cpp:169\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"污泥​男​爵\"\n\n#: Source/translation_dummy.cpp:170\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"病​角·钢锤\"\n\n#: Source/translation_dummy.cpp:171\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"疯嚎\"\n\n#: Source/translation_dummy.cpp:172\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"末​日微笑·腐烂者\"\n\n#: Source/translation_dummy.cpp:173\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"疯燃者\"\n\n#: Source/translation_dummy.cpp:174\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"骨锯​·巫妖\"\n\n#: Source/translation_dummy.cpp:175\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"断脊\"\n\n#: Source/translation_dummy.cpp:176\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"鬼​颅​锐骨\"\n\n#: Source/translation_dummy.cpp:177\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"破碎​风暴\"\n\n#: Source/translation_dummy.cpp:178\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"风暴​灾​星\"\n\n#: Source/translation_dummy.cpp:179\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"渗​脓\"\n\n#: Source/translation_dummy.cpp:180\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"火​之​金翼\"\n\n#: Source/translation_dummy.cpp:181\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"黑色​风暴\"\n\n#: Source/translation_dummy.cpp:182\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"怒疫\"\n\n#: Source/translation_dummy.cpp:183\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"扒​皮\"\n\n#: Source/translation_dummy.cpp:184\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"蓝角\"\n\n#: Source/translation_dummy.cpp:185\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"地狱​诞生​的​扭曲​烈​焰\"\n\n#: Source/translation_dummy.cpp:186\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"蟠​蛇​牙\"\n\n#: Source/translation_dummy.cpp:187\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"快​颅\"\n\n#: Source/translation_dummy.cpp:188\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"扭曲​的​狮颅\"\n\n#: Source/translation_dummy.cpp:189\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"黑舌\"\n\n#: Source/translation_dummy.cpp:190\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"邪触\"\n\n#: Source/translation_dummy.cpp:191\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"毒​焰\"\n\n#: Source/translation_dummy.cpp:192\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"牙​皮\"\n\n#: Source/translation_dummy.cpp:193\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"巫火·不洁者\"\n\n#: Source/translation_dummy.cpp:194\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"黑​颅\"\n\n#: Source/translation_dummy.cpp:195\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"灵魂​撕​裂者\"\n\n#: Source/translation_dummy.cpp:196\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"风​生\"\n\n#: Source/translation_dummy.cpp:197\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"地​坑领主\"\n\n#: Source/translation_dummy.cpp:198\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"骨锈​编织者\"\n\n#: Source/translation_dummy.cpp:199\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"哀嚎​的​阴魂\"\n\n#: Source/translation_dummy.cpp:200\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"末​日阴云\"\n\n#: Source/translation_dummy.cpp:201\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"血​月​魂火\"\n\n#: Source/translation_dummy.cpp:202\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"巫月\"\n\n#: Source/translation_dummy.cpp:203\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"血​肉盛宴\"\n\n#: Source/translation_dummy.cpp:204\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"格雷沃·屠杀者\"\n\n#: Source/translation_dummy.cpp:205\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"恐惧​法官\"\n\n#: Source/translation_dummy.cpp:206\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"星眼·女魔\"\n\n#: Source/translation_dummy.cpp:207\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"钢颅·​猎杀者\"\n\n#: Source/translation_dummy.cpp:208\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"格拉什​爵士\"\n\n#: Source/translation_dummy.cpp:209\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"维兹尔\"\n\n#: Source/translation_dummy.cpp:210\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"赞菲尔\"\n\n#: Source/translation_dummy.cpp:211\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"嗜​血​者\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"织网​黑​寡妇\"\n\n#: Source/translation_dummy.cpp:213\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"血​肉​舞者\"\n\n#: Source/translation_dummy.cpp:214\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"恐惧​之​钉\"\n\n#: Source/translation_dummy.cpp:215\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"杜姆洛克\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"短​剑\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"圆盾\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"木棒\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"短弓\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"法力​短​杖\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"切肉者\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"不​死​王冠\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"碧空​之​戒\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"魔石\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"明眼​护符\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"实​相之戒\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"酒店​招牌\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"谐​角​之​冠\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"钢铁​面纱\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"金色​药剂\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"愤怒​铁砧\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"黑​蘑菇\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"大脑\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"长满​真菌​的​书\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"幽灵​药剂\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"鲜​血石\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"大​教堂​地图\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"治疗​药​水\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"法力​药​水\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"鉴定​卷轴\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"城镇​传送​卷轴\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"阿凯尼​的​荣耀\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"完全​生命​恢复​药​水\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"完全​法力​恢复​药​水\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"格里斯沃尔德​之锋\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"公牛板甲\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"拉扎鲁斯之​杖\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"复活​卷轴\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"短​杖\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"剑\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"​匕首\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"符文​炸弹\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"西奥多\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"金​项链\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"残破​的​日记​1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"残破​的​日记​2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"残破​的​日记​3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"重新​拼凑​的​日记\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"棕色​大​衣\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"灰色​大衣\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"软帽\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"颅顶盔\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"头盔\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"全​护盔\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"王冠\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"重盔\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"斗篷\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"短​披风\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"披风\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"长​袍\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"内​衬甲\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"皮甲\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"硬​皮甲\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"钉​皮甲\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"环​甲\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"锁​甲\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"锁子​甲\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"鱼鳞甲\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"胸片​甲\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"板​甲\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"板条​甲\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"板链甲\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"全身​板​甲\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"哥特​甲\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"全身​板链甲\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"盾\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"小​盾\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"大​盾\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"鸢盾\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"塔盾\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"哥特盾\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"活力​恢复​药​水\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"完全​活力​恢复​药​水\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"油\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"力量​药剂\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"魔法​药剂\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"敏捷​药剂\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"活力​药剂\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"治疗​卷轴\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"搜索​卷轴\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"闪​电​卷轴\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"火焰​墙​卷轴\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"地​狱火​卷轴\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"闪光​卷轴\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"夜视​卷轴\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"相​位术​卷轴\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"法力​护盾​卷轴\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"火焰​波​卷轴\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"火球​卷轴\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"石化​诅咒​卷轴\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"连锁​闪电​卷轴\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"召唤​守护者​卷轴\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"闪电​新​星​卷轴\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"召唤​魔像​卷轴\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"传​送术​卷轴\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"天​启卷​轴\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"弯​刃剑\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"弯刀\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"双​手​大​剑\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"短​刃\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"军刀\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"长​剑\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"阔​剑\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"手​半​剑\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"双​手​剑\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"重​剑\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"小​斧\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"斧\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"大斧\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"宽刃斧\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"战斗​斧\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"重斧\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"钉​锤\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"流​星锤\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"战​锤\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"锤\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"狼​牙棒\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"连​枷\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"大​锤\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"弓\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"猎弓\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"长​弓\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"复合弓\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"短​战弓\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"长​战弓\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"短​战争​弓\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"长​战争​弓\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"长​杖\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"复合​杖\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"铁头​棒\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"战​杖\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"戒指\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"护符\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"火焰​符文\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"符文\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"闪电符文\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"强效​火焰​符文\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"强​效​闪电符文\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"符文石\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"电​荷弹​短​杖\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"竞技场药水\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"屠夫​的​剁肉刀\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"光​之​军刀\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"裂隙​之​弓\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"穿​针​引线\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"天堂弓\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"致命​猎手\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"死者​之​弓\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"黑色​橡木弓\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"火焰​镖\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"肉​刺\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"风​之​力\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"鹰​之​号​角\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"贡纳加尔​的​匕首\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"防守者\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"狮​鹫​之​爪\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"黑色​剃刀\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"凸月\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"寒冰​削​骨刀\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"刽子手​的​利刃\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"骨锯\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"影隼\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"巫师​之​刺\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"光​之​军刀\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"鹰隼​之​爪\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"地​狱火\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"末​日​使者\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"灰熊\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"祖父\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"磨肉机\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"锐喙\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"血腥​杀戮者\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"天堂战斧\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"邪恶战斧\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"削石者\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"阿吉纳拉斧头\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"地狱​屠​戮者\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"梅​塞施密特​的​劫掠者\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"裂纹\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"霍尔姆​之​锤\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"希弗柏​的​短棍\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"天堂​之​星\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"巴拉纳​之​星\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"多​节根\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"碎​颅\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"舍费尔​之​锤\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"梦​境​边缘\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"暗影​之​杖\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"焚化者\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"风暴​尖刺\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"闪光​之​歌\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"风暴​召唤\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"保护者\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"诺吉​的​解密棒\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"心声\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"奥南​之​棒\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"精魂​头盔\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"思考帽\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"霸主盔\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"愚人​奖章\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"暮光\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"贵族​头环\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"魂​飞魄​散\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"角​斗士​之​祸\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"彩虹​斗篷\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"奥特​之​皮\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"智慧​束带\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"电光锁​甲\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"清道夫​的​甲壳\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"夜色\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"诺吉​的​轻铠​甲\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"恶​魔长​角​外​套\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"偏转者\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"裂颅​盾\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"巨​龙​之息\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"黑​橡木盾\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"神圣​卫士\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"暴风​之​盾\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"刺棘\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"雷加之​戒\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"放​血者\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"紧缩​之​戒\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"订​婚​戒指\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"锡\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"黄​铜\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"青铜\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"精铁\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"钢铁\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"白银\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"铂​金\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"秘银\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"陨​铁\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"奇​异\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"无​用\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"弯曲\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"软弱\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"参差\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"致命\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"沉重\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"凶恶\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"残忍\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"蛮​横\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"野​蛮\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"无情\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"无情\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"笨拙\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"迟钝\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"锋利\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"优良\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"战士​的\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"士兵​的\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"勋爵​的\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"骑士​的\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"大师​的\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"勇士​的\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"国王​的\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"脆弱\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"生锈\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"强​壮\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"巨型\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"勇敢\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"荣耀\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"祝福\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"圣者\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"惊叹\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"神佑\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"丹红\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"猩​红\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"石榴\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"红​宝石\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"蓝色\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"碧空\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"青​金石\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"钴​制\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"蓝宝石\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"白色\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"珍珠\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"象牙\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"水晶\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"钻石\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"黄宝石\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"琥​珀\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"碧玉\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"黑​曜石\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"绿​宝石\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"鬣​狗​的\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"青蛙​的\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"蜘蛛​的\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"乌鸦​的\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"毒​蛇​的\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"巨蛇​的\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"幼龙​的\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"翼龙​的\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"游龙​的\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"九头蛇​的\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"天使​的\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"大​天使​的\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"丰富\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"慷慨\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"烈​焰\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"闪​电\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"质量\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"残废\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"杀​戮\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"血腥\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"屠杀\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"屠宰\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"疼痛\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"眼泪\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"健康\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"保护\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"吸收\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"偏转\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"渗透\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"脆弱\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"弱点\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"强健\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"力量\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"强力\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"巨人\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"泰坦\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"麻痹\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"萎缩\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"敏捷\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"技能\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"精准\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"精确\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"完美\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"傻瓜\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"文​盲\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"魔法\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"头脑\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"辉煌\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"咒术\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"巫术\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"疾病\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"病痛\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"活力\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"热情\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"活跃\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"精力\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"生命\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"麻烦\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"坑​洞\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"天空\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"月亮\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"星星\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"天堂\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"星象\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"秃​鹫\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"豺​狼\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"狐狸\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"捷豹\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"老鹰\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"野​狼\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"老虎\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"狮子\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"猛犸\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"鲸​鱼\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"易​损\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"脆弱\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"稳固\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"工艺\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"结构\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"久远\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"黑暗\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"夜晚\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"光芒\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"光辉\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"火焰\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"火\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"燃烧\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"闪光\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"闪​电\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"雷​电\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"充裕\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"丰足\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"荆棘\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"腐败\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"窃​贼\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"野​熊\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"蝙​蝠\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"吸血​鬼\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"水蛭\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"鲜血\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"穿​刺\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"贯穿\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"猛击\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"乐意\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"迅捷\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"速度\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"匆忙\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"平衡\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"稳定\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"和谐\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"格​挡\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"魔石\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"虚弱​的​贾巴德\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"疯狂​的​扎尔\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"拉齐达​南\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"屠夫\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"奥格登​之​征\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"目盲​之厅\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"荣耀\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"鲜血​战神\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"国王​李奥瑞克​的​诅咒\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"大​主教​拉扎鲁斯\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"大​墓​地​大​问题\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"农夫​的​果园\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"小​女孩\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"旅行​商人\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"污染者\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"纳·库尔\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"小丑​的​愚弄\"\n\n#: Source/translation_dummy.cpp:648\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"火焰弹\"\n\n#: Source/translation_dummy.cpp:649\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"治疗​术\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"闪​电术\"\n\n#: Source/translation_dummy.cpp:651\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"闪光术\"\n\n#: Source/translation_dummy.cpp:652\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"鉴定\"\n\n#: Source/translation_dummy.cpp:653\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"火焰​墙\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"城镇​传送门\"\n\n#: Source/translation_dummy.cpp:655\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"石化​诅咒\"\n\n#: Source/translation_dummy.cpp:656\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"夜​视术\"\n\n#: Source/translation_dummy.cpp:657\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"相​位术\"\n\n#: Source/translation_dummy.cpp:658\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"法力​护盾\"\n\n#: Source/translation_dummy.cpp:659\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"火​球术\"\n\n#: Source/translation_dummy.cpp:660\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"召唤​守护者\"\n\n#: Source/translation_dummy.cpp:661\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"连锁​闪​电\"\n\n#: Source/translation_dummy.cpp:662\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"烈​焰​波\"\n\n#: Source/translation_dummy.cpp:663\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"多​头​蛇\"\n\n#: Source/translation_dummy.cpp:664\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"鲜血​仪式\"\n\n#: Source/translation_dummy.cpp:665\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"闪电​新​星\"\n\n#: Source/translation_dummy.cpp:666\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"隐形​术\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"地​狱火\"\n\n#: Source/translation_dummy.cpp:668\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"召唤​魔像\"\n\n#: Source/translation_dummy.cpp:669\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"狂暴\"\n\n#: Source/translation_dummy.cpp:670\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"传​送术\"\n\n#: Source/translation_dummy.cpp:671\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"天​启\"\n\n#: Source/translation_dummy.cpp:672\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"灵化术\"\n\n#: Source/translation_dummy.cpp:673\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"物品​修理\"\n\n#: Source/translation_dummy.cpp:674\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"魔杖​充能\"\n\n#: Source/translation_dummy.cpp:675\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"解除​陷阱\"\n\n#: Source/translation_dummy.cpp:676\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"召唤​元素\"\n\n#: Source/translation_dummy.cpp:677\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"电​荷弹\"\n\n#: Source/translation_dummy.cpp:678\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"圣光弹\"\n\n#: Source/translation_dummy.cpp:679\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"复活术\"\n\n#: Source/translation_dummy.cpp:680\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"心灵​传动\"\n\n#: Source/translation_dummy.cpp:681\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"治疗​他​人\"\n\n#: Source/translation_dummy.cpp:682\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"血​星\"\n\n#: Source/translation_dummy.cpp:683\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"骨灵\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\"啊，关于​我们​国王​的​故事，是​吧？李奥瑞克​国王​的​堕落​对于​这​王国​来​说​是​一​场​悲剧。人\"\n\"民​一直​热爱​着​国王，但是​从此​人们​反而​生活​在​对​他​的​恐惧​之中。我​一直​反思，他​原来​是​\"\n\"如此​虔诚，如何​堕落​到​离​光明​如此​遥远。只有，来自​地狱​最​邪恶​的​力量​才​能​如此​彻底​的​\"\n\"从​内心​摧毁​他。\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"村子​需要​你​的​帮助，好心​人！几​个​月​前，李奥瑞克​的​儿子，艾伯莱希特​王子​被​绑架​了。\"\n\"国王​勃然大怒，在​村子​中​到处​寻找​他​失踪​的​孩子。日子​一​天天​过去，李奥瑞克​开始​逐渐​\"\n\"陷入​疯狂。他​把​儿子​的​失踪，归咎于​无辜​的​村民，残忍​的​处决​了​他们。只​有​不到​一半​的​\"\n\"人​从​他​的​疯狂​举动​中​幸存​…​…​\\n\"\n\"宫​里​的​骑士​和​祭司​试图​安慰​他，国王​反​到​认为​他们​是​想​谋反。在​国王​即将​咽气​的​时候，\"\n\"对​他​的​追随者们​降下​了​可怕​的​诅咒。他​发誓​要​让​他们​在​黑暗中​永远​的​效忠​自己。\\n\"\n\"​但是​实时​上​发生​的​事情​比​我​想​象​中​的​还​要​黑暗​和​扭曲！现在，我们​的​前任​国王​已经​从​长\"\n\"眠​中​复活​了，并​在​地下​回廊​中​指挥​着​一​只​不​死​军团。他​的​身体​已经​被​火化，埋葬​在​大​教\"\n\"堂​的​地下​墓室​的​第三​层。求​你​了，好心人，摧毁​它​那​现在​被​诅咒​的​身体，让​他​的​灵魂​得\"\n\"到​解放。\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"正​如​之前​我​告诉​你​的，好心人，国王​被​埋葬​在​地下​墓穴​第三​层。他​就​在​那​下面，在​那​腐\"\n\"朽​的​黑暗​中​等待​着​摧毁​这​片​土地​的​机会。\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"我们​国王​的​诅咒​已经​解除，但​我​担心​那​只是​巨大​邪恶​的​冰山​一​角。然而，正​因为​你​的​胜\"\n\"利，我们​还​有​在​被​邪恶​席卷​这​片​土地​前​被​救赎​的​机会。希望​光明​指引​你​的​旅途，好心\"\n\"人。\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"失去​儿子，对于​李奥瑞克​国王​来​说​是​个​沉痛​的​打击。我​尽​我​所能​的​减轻​他​的​疯狂，但是​\"\n\"终究​邪恶​还是​占据​了​他。从​那​天​起，黑色​的​诅咒​笼罩​着​王国，要是​你​也许​能​让​他​的​灵魂​\"\n\"从​人间​解脱，诅咒​便​会​就此​解除。\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"我​不​想​去​回忆​国王​的​驾崩。我​印象中​他​是​一​位​仁慈​且​公正​的​统治者。不止​为​何，他​的​死​\"\n\"是​如此​的​悲痛，就​像是​一​场​悲剧。\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"我​打造​的​武器​和​盔甲​大部分​被​李奥瑞克​国王​武装​他​的​骑士。我​还​为​他​本人​锻造​了​一​把​趁\"\n\"手​的​秘银​双​手​大剑​和​一​顶​与​之​相配​的​王冠。我​始终​无法​接受​他​的​驾崩，一定​是​某​种​强大​\"\n\"的​邪恶​把​他​逼疯​了！\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"我​才​不​在乎​呢。听​着，我​的​国王​才​不​会​是​一​具​骨​架子。李奥瑞克​才​是​国王。什么​是​国\"\n\"王，懂​吗？向​国王​致敬！\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"在​人间​活跃​的​亡灵​跟​随​着​被​诅咒​的​国王。他​它​拥有​着​复生无​尽亡者​大军​的​力量。如果​你​\"\n\"不​能​阻止​他​的​统治，他​一定​会​率领​大军​杀​穿​这​片​土地，屠杀​所有​生者。\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"瞧，我​就​是​来​做​生意​的。我​不​卖​情报，也​不​关心​那死​的​比​我​活​的​还​长​的​国王。如果​你​需\"\n\"要​些​东西​对付​这​死不​了​的​国王，那​我​倒​是​可以​帮​帮​你。\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"温暖​是​生命​气息​来到​了​我​的​墓穴。那​就​来​吧，凡​人，为​我​主效命​终生​吧！\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"我​知道​这​种​奇怪​的​行为​也​让​你​困惑。我​猜想，既然​许多​恶魔​害怕​太阳光并且相信​它​拥有​\"\n\"巨大​的​力量，那么可能​是​你​所​说​的​招牌上​描绘​的​旭日​让​他们​相信​它​也​拥有​一些​神秘​的​力\"\n\"量。嗯，也许​他们​并不​像​我们​担心​的​那么​聪明……\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"大人，我​有​一​个​奇怪​的​经历。我​知道​你​对​迷宫​里​的​怪物​很​了解，这​是​我​一​生​都​无法​理解​\"\n\"的……我​在​晚上​被​酒店​外面​的​刮擦声​吵醒​了。当​我​从​卧室​往外​看​的​时候，我​看到​客栈院子​\"\n\"里​有​一些​像​魔鬼​一样​的​小​动物。过​了​一会儿，他们​跑掉​了，但​还​没​来​得​及​把​招牌​偷​到​我​\"\n\"的​客栈。我​不​知道​为什么​恶魔会​偷走​我​的​标志，却​让​我​的​家人​安然​无恙​…​…​”​很​奇怪，不​是​\"\n\"吗？\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"哦，你​不​必​把​我​的​招牌​拿​回来，但​我​想​它​确实​可以​帮​我​省下​再​做​一​个​牌子​的​费用。好​\"\n\"吧，让​我​想想，我​能​给​你​什么​作为​找到​它​的​费用？嗯，我们​这里​有​什么……啊，是​的！这​\"\n\"顶​帽子​是​一​个​魔法师​不久​前​留​下来​的，他​把​它​放​在​一​个​房间​里。也许它​对​你​有​些价值。\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"我​的​天哪，恶魔们​晚上​在​村子​里​到处​乱​跑，掠夺​我们​的​家园​——​难道​没有​什么​神圣​的​东西​\"\n\"吗？我​希望​奥格登​和​加尔达​没​事。我​想​如果​他们​受伤​了​他们​会​来​看​我​的……\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"天​哪！招牌就​在​那里​吗？我​祖母​和​我​一定​一直​都​在​睡觉。感谢​那些​怪物​没有​攻击​客栈。\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"你​说​恶魔​偷​了​奥格登​的​招牌？这​听​起来​不​像​我​听​说​过​或​见​过​的​暴行。\\n\"\n\" \\n\"\n\"​恶魔​关心​的​是​撕碎​你​的​心，而​不​是​你​的​路标。\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"你​知道​我​怎么​想​吗？有​人​拿​了​那个​牌子，他们​会​想要​很多​钱​的。如果​我​是​奥格登……我​不​\"\n\"是，但​如果​我​是……我​想​买​一​个​新​牌子，上面​画​些​漂亮​的​图案。也许​是​一​杯​啤酒​或者​一​块​\"\n\"奶酪……\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"没有​人​能​真正​理解​恶魔​的​思想。\\n\"\n\" \\n\"\n\"​永远​不​要​让​他们​不​稳定​的​行为​迷惑​你，因为​那​也​可能​是​他们​的​计划。\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"他​是​说​我​拿​了​那个？我​想​格里斯沃尔德​也​站​在​他​这​边。\\n\"\n\" \\n\"\n\"​听​着，我​几​个​月​前​就​忘​了​偷牌子​了。你​不​能​靠​一​块​木头​赚​钱。\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"嘿​-​你​就​是​那个​杀人​狂！你​给​我​拿​魔旗​否则​我们​就​进攻！你​不​能​离开​生命！你​杀​了​大丑八\"\n\"怪​还​了​魔法。穿过​街角​和​门，找到​丑陋​的​东西。你​给，你​走！\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"你​杀​了​丑八怪，得到​横幅。你​给​我​带来，否则……\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"你​给​我！是​的，很​好！走​吧，我们​坚强。我们​用​大​魔法​杀人！\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"这​不​是​好​兆头，因为​它​证实​了​我​最​黑暗​的​恐惧。虽然​我​不​允许​自己​相信​古老​的​传说，但​\"\n\"我​现在​不​能​否认​它们。也许​是​时候​揭露​我​是​谁​了。\\n\"\n\" \\n\"\n\"​我​的​真名​是​迪卡德·凯恩，我​是​一​个​古老​兄弟会​的​最后​一​个​后代，这​个​兄弟​会​致力于​保护​\"\n\"一​个​永恒​邪恶​的​秘密。一​个​很​明显​已经​被​释放​的​恶魔。\\n\"\n\" \\n\"\n\"拉扎鲁斯大​主教​曾经​是​李奥瑞克​国王​最​信任​的​顾问，他​带领​一​队​普通​的​市民​进入​迷宫，\"\n\"寻找​国王​失踪​的​儿子​艾伯莱希特。过​了​很​长​一​段​时间​他们​才​回来，只有​少数​人​带​着​生命​\"\n\"逃走​了。\\n\"\n\" \\n\"\n\"诅咒​我​是​个​傻瓜！我​当时​应该​怀疑​他​暗中​的​背叛。一定​是​拉扎鲁斯​自己​绑架​了​艾伯莱希\"\n\"特，然后​把​他​藏​在​迷宫​里。我​不​明白​大主教​为什么​转向​黑暗，或者​他​对​这​个​孩子​有​什么​\"\n\"兴趣，除非​他​打算​把​他​献给​他​的​黑暗​主人！\\n\"\n\" \\n\"\n\"​那​一定​是​他​的​计划！他​的​“​救援队​”​的​幸存者​说，拉扎鲁斯​最后​一​次​被​看到​跑进​迷宫​最​深​\"\n\"处。你​必须​赶快​把​王子​从​这​个​疯狂​恶魔​的​祭剑​中​救​出来！\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"你​必须​赶快​把​艾伯莱希特​从​拉扎鲁斯​手​中​救​出来。王子​和​这个​王国​的​人民​都​指望​着​你！\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"你​的​故事​很​残酷，我​的​朋友。拉扎鲁斯​一定​会​因为​他​那​可怕​的​行为​在​地狱里​被​烧死。你​\"\n\"描述​的​那​个​男孩​不​是​我们​的​王子，但​我​相信​艾伯莱希特​可能​还​处在​危险​之中。你​所​说​的​\"\n\"权力​的​象征​一定​是​迷宫​中心​的​一​个​入口。\\n\"\n\" \\n\"\n\"​你​要​知道，我​的​朋友，你​所​反对​的​邪恶​是​恐怖​的​黑魔王。他​被​世人​称为​迪亚波罗。几​个​\"\n\"世纪​前，正​是​他​被​囚禁​在​迷宫​里，我​担心​他​又​一​次​企图​在​人类​的​王国​里​制造​混乱。你​必\"\n\"须​冒险​穿过​传送门，在​一切​都太迟之前​​摧毁迪亚波罗！\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"拉扎鲁斯​是​大主教，他​带领​许多​市民​进入​迷宫。那天​我​失去​了​很多​好​朋友，拉扎鲁斯​再​\"\n\"也​没有​回来。我​想​他​是​和​其他​大多数​人​一起​被​杀​的。如果​你​能​帮​我​一​个​忙，好​心人​-​请​不​\"\n\"要​和​法恩汉​谈论​那​一​天。\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"当​我​听说​镇​上​的​人​那天​晚上​打算​干​什么​时，我​很​震惊。我​想​在​所有​人​中，拉扎鲁斯​应该​\"\n\"更​有​理智。他​是​一​位​大主教，似乎​总是​那么​关心​崔斯特姆​的​市民。这么​多​人​受伤，我​救​\"\n\"不​了​他们……\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"我​记得​拉扎鲁斯​是​一​个​非常​和​善​和​乐于​奉献​的​人。他​在​我​母亲​的​葬礼​上​发表​了​讲话，在​\"\n\"非常​困难​的​时候​支持​我​和​我​的​祖母。我​每​晚​都​祈祷，不​知​何故，他​还​活​着，安然​无恙。\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"拉扎鲁斯领​我们​进迷宫​的​时候，我​在​那里。他​谈到​了​神圣​的​报应，但​当​我们​开始​与​那些​\"\n\"地狱​之​子​战斗​时，他​甚至​没有​举起​他​的​狼牙棒​来​对付​他们。他​只不过​是​往​黑暗​的​仆人们​\"\n\"所​住​的​昏暗​无​边​的​房间​里​跑​得​更​深！\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"它们​刺，然后​咬，然后​它们​就​在​你​周围。说谎者！说​谎者！他们​都​死​了！死去​的​你​听见​\"\n\"了​吗？他们​只​是​不断​地​跌倒……他们​的​血洒​得​满​地​都​是……全​是​他​的​错……\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"我​不​认识​你们​所​说​的​拉扎鲁斯，但​我​确实​感觉​到​他​内心​有​很​大​的​矛盾。他​带来​了​巨大​的​\"\n\"危险，他​将​不​择​手段​地​为​黑暗​势力​服务，而黑暗​势力​也将​他​视为自己人。\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"是​的，正义​的​拉扎鲁斯，他​对​那里​的​怪物​非常​有效。没​救​我​的​腿，是​吗？听​着，我​给​你​\"\n\"一​个​免费​的​建议。问问​法恩汉，他​在​那儿。\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"放弃​你​愚蠢​的​追求。等待​你​的​只​有​我​主人​的​愤怒！你​来​不​及​救​孩子​了。现在​你​要​和​他​一\"\n\"起​下​地狱​了！\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"嗯，我​不​知道​我​能​告诉​你​些​什么​对​你​有​帮助。充满​我们​水井​的​水​来自​地下泉水。我​听说​\"\n\"过​一​条​通往​大​湖​的​隧道​——​也许​它们​是​同​一​条。不幸​的​是，我​不​知道​什么​会​导致​我们​的​供\"\n\"水​受到​污染。\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"我​一直​试图​在​我们​的​储藏室​里​储存​大量​的​食品​和​饮料，但​由于​全​镇​没有​淡水​供应，即使​\"\n\"是​我们​的​商店​也​很​快​就​会​干涸。\\n\"\n\" \\n\"\n\"​拜托，做​你​能​做​的，否则​我​不​知道​我们​会​做​什么。\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"很​高兴​我​及时​赶上​了​你！我们​的​水井​变​得​微咸、死气​沉沉，一些​城里人​喝​得​不​好。我们​\"\n\"储备​的​淡水​很​快​就​干涸​了。我​相信​有​一​条​通道​通​向​为​我们​城镇​服务​的​泉水。请​找出​造成​\"\n\"这​场​灾难​的​原因，否则​我们​都​将​灭亡。\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"拜托，你​必须​快点。每​过​一​个​小时，我们​就​更​接近​没有​水​喝​了。\\n\"\n\" \\n\"\n\"​没有​你​的​帮助，我们​活​不​了​多久。\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"你​说​什么？仅仅​是​恶魔​的​存在​就​导致​了​水​被​污染​了？哦，我们​镇下​确实​隐藏​着​一​个​巨大​\"\n\"的​恶魔，但​你​的​毅力​和​勇气​给​了​我们​希望。请​收​下​这​枚​戒指​——​也许​它​能​帮助​你​消灭​这些​\"\n\"邪恶​的​生物。\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"我​祖母​很​虚​弱，嘉达​说​我们​不​能​喝​井​水。拜托，你​能​帮帮我们么？\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"佩金​告诉​了​你​真相。我们​很​快​就​会​急​需​淡水。我​试​过​清理​其中​一​口​小​井，但​它​散发​着​死\"\n\"水​的​臭味。一定​是​源头​堵塞​了。\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"你​想​喝​水​吗？\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"如果​你​不​能​恢复​井​中​的​淡水，崔斯特姆人​就​会​死。\\n\"\n\" \\n\"\n\"​知道​这​一点​-​恶魔​是​这​件​事​的​核心，但​他们​仍然​不​知道​他们​产生​了​什么。\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"这​一​次，我​和​你​在一起。可以​说，如果​我​没有​销路​的话，我​的​生意​就​完​了。你​最好​尽快​\"\n\"弄清楚​发生​了​什么​事！\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"一​本​书​提到​了​一​间​满​是​人类​骸骨​的​密室？嗯，在​我​曾经​研究​学习​的​东方​图书馆，馆藏​的​\"\n\"一些​古籍​中​提到​了​白骨密室。这些​书籍​推断，当下界​领主​想要​保护​大量​宝藏​时，他们​会​\"\n\"创建​一些​结界。在​结界​中，那些​试图​偷窃​宝藏​时​死亡​的​人，将​永远​被​束缚。一​个​扭曲​\"\n\"的，既​在​情理​之​中，又​在​意料​之外​的​结局？\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"我​恐怕​对​此​一无所知，好心​人。凯恩​读​过​很多​书，他​也许​能​提供​帮助。\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"这​听​起来​是​个​非常​危险​的​地方。如果​你​在​那里​冒险，请​小心。\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"恐怕​我​什么​也​没​听​说​过。说​书人凯恩​也许​能​帮​上​忙。\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"我​对​这​地方​一无所知，不过​你​可以​问问​凯恩。他​知道​很多​事情，知道​你​问题​的​答案​也​不​\"\n\"奇怪。\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"看，有​这样​一​个​木屋。你​知道​他​的​妻子，她​告诉​那​棵​树​…​…​因为​你​必须​等​着。然后​我​说，\"\n\"这​可能​对​他​不利，但​如果​你​认为​我​会​为​此​付出​代价​…​…​你​…​…​呃​…​…​对。\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"倘​若​你​死​在​这个​被​诅咒​的​结界​里，你​将​成为​黑暗​领主​永恒​的​仆人。\\n\"\n\"\\n\"\n\"​进入​白骨密室​的​风险​由​你​自行​承担。\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"你​是​说​一​个​巨大​且​神秘​的​宝藏？或许​我​有​兴趣​从​你​那里​拿走​些​东西​…​…​或者​更​好​的。你​难\"\n\"道​不​需要​些​稀有​且​昂贵​的​物资​来​度过​这​场​折磨​吗？\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"大​主教​拉扎鲁斯​似乎​怂恿​过​很多​镇民​冒险​进入​迷宫，去​寻找​国王​失踪​的​儿子。他​以​镇民​\"\n\"的​恐惧​为乐，鞭打​他们​使​其​成为​疯狂​的​暴徒。没有​人​对​倒​在​冰冷​地面​有所​准备​…​…​拉扎鲁\"\n\"斯​抛弃​了​他们，使​留​在​难以​言喻​的​恐怖​中，等死。\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"是​的，法恩汉​含糊​的​地​说到​一些​关于​一​个​笨重​的​畜生​挥舞​着​恐怖​武器​的​事。我​确定​他​称​\"\n\"他​为​屠夫。\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"圣光​在​上，我​知道​这​恶魔​一些​事情。当拉扎鲁斯​带领​少数​幸存者​从​大​教堂​中​逃​出来​时，\"\n\"很多​人​身​上​都​有​着​恐怖​的​伤口。我​清楚，他​用​什么​玩意儿​在​受害者​身​上​割出​这样​的​伤口​\"\n\"的，但​绝对​不​是​来自​这​个​世界。它​留下​的​伤口​全​是​溃烂​与​恶疾，即便​是​我​也​毫​无​办法​去​\"\n\"治疗。如果​你​打算​跟​这​个​恶魔​战斗，当心​…​…\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"当​法恩汉​说起​屠夫​杀人​的​事​时，我​根本​不​信​他。然而​你​的​再次​提到，那​也许​是​真的。\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"我​亲眼​看到​法恩汉​所​说​的​“​屠夫​”，我​那些​被​他​杀死​朋友，尸体​铺成​了​路。他​手​中​挥舞​的​\"\n\"切肉刀​大​的​就​像​一​把​斧子，胆​敢​面对​他​的​勇士​都​被​剁成​了​尸块。在​打斗​中​我​被​另​一​群​尖\"\n\"啸​的​恶魔​拦​住，还好​我​碰巧​找到​了​逃离​的​楼梯。之后​我​再​也​没​见​过​那​可怕​的​怪物，但​他​\"\n\"那​血迹​斑斑​的​面容​让​我​至今​心有余悸。\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"大！大​砍​刀​杀​了​我​所有​的​伙伴。没​法​阻止​他，必须​逃跑，救​不​了​他们。被​关​在​一​间​全​是​\"\n\"尸体​的​房间​…​…​那么​多​的​朋友​…​…​不，不！\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"“​屠夫​”​是​个​彻彻底​底​的​虐待​狂，以​别人​的​痛苦​和​折磨​为​乐。你​已经​看到​他​的​杰作，让​法\"\n\"恩汉​一蹶不振​就此​成​了​醉鬼。消灭​他​能​有效​的​确保​村子​安全。\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"关于​那​个​狰狞​的​恶魔，我​知道​的​远比​你​想象​的​多。他​的​小​伙伴​抓到​了​我，在​格里斯沃尔\"\n\"德​赶来​成功​帮​我​逃出​魔窟​前，成功​的​卸掉​了​我​的​腿。\\n\"\n\"\\n\"\n\"​我​就​直​话​直​说​了，在​他杀​了​你，让​你​的​尸体​成为​他​收藏品​前杀​了​他。\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"请​听​我​说。大主教​拉扎鲁斯，是​他​带领​我们​来​这里​寻找​失踪​的​王子。结果​那​混蛋​把​我们​\"\n\"引入​了​陷阱！现在​所有​人​都​死​了​…​…​被​一​个​叫做​“​屠夫​”​的​恶魔​杀死。为​我们​报仇！找到​这​\"\n\"个​“​屠夫​”，杀​了​他，让​我们​的​灵魂​最终​得到​安息。\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"你​朗诵​了​一​首​有趣​的​诗句，它​的​风格​让​我​想起​了​另​一​个​作品。让​我​好好​想想。\\n\"\n\" \\n\"\n\"​…​黑暗​遮蔽​的​隐秘。那些​可怜​的​灵魂​双目​发光​但​却​无法​看见，只有​被​利爪急促​的​挂磨声​永\"\n\"远​的​折磨。一​座​为​被​诅咒​的​人​所​建立​的​监狱，盲目​之​厅​…​…\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"我​从来​就​不​喜欢​诗词。偶尔，旅店​生意​好​的​时候，我​会​雇上​吟游​诗人。但​那​似乎​是​很​久​\"\n\"以前​的​事情​了。\\n\"\n\"\\n\"\n\"​什么？啊，好​吧​…​…​呃，我​认为​你​可以​问问​别人​知道​什么。\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"不​知​为何，这​听​起来​挺​熟悉​的。我​似乎​回想​起​以前​研究​恶魔​痛楚​历史​时​读到​类似​的​诗\"\n\"句，它​讲述​了​一​个​非常​邪恶​的​地方​…​…​等​下，你​是​不​会​去​那儿​的​对​吧？\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"如果​你​对​失明​有​疑问，你​应该​和​佩金谈谈。我​只​知道​它​给​了​我​祖母​一​瓶​药水，使得​她​能​\"\n\"清晰​的​看到​东西，或许​他​也​能​帮助​你。\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"我​恐怕​从来​没​听​过​和​见​过​一​个​地方​与​你​生动​的​描述​相符，朋友。也许​说​书人凯恩能​提供​\"\n\"些​帮助。\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"看​这里​…​…​好玩​吧？明白？瞎子，看​这？\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"这​是​一​个​极度​折磨​和​恐惧​的​地方，为​它​的​主人​很​好​的​服务。\\n\"\n\"\\n\"\n\"​小心点，不然​你​将​被困​在​那儿，时间​超乎​你​的​想象。\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"我​想想，我​卖给​你​东西​了？没有。你​给​钱​让​我​告诉​你​这​事情​了​吗？没有。你​该​离开​去​找​\"\n\"那​个​活​着​就​是​为了​跟​你​说话​的​说书人​了​吗？是​的。\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"你​声称​和​拉齐达​南​谈​过？他​一生​是​个​伟大​的​英雄。拉齐​达​南​是​一​个​光荣​而​公正​的​人，多​\"\n\"年​来​一直​忠实​地​为​国王​服务。当然，你​已经​知道​了。\\n\"\n\" \\n\"\n\"​在​那些​被​国王​诅咒​的​人​中，拉齐​达南​最​不​可能​不​战​而​屈身​于​黑暗，所以​我​想​你​的​故事​可\"\n\"能​是​真的。如果​我​在​你​的​位置，我​的​朋友，我​会​想​办法​把​他​从​折磨​中​释放​出来。\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"你​说​的​是​一​个​死​了​很​久​的​勇士！我​不​想​在​客栈​院子​里​和​死去​的​灵魂​说话，非常​感谢。\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"你​是​说​一​种​金色​的​药剂。我​从​未​调制​过​那​种​颜色​的​药水，所以​我​没​办法​告诉​你​如果​你​喝​\"\n\"了​它​会​怎样。作为​一​个​治疗者，我​强烈​建议​你​去​寻找​那​种​药剂，照着​拉齐达南​要求​的​\"\n\"做，但​你​绝对​不​要​喝​了​它。\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"我​从来​没​听​说​过​拉齐达南，抱歉​我​帮​不​了​你。\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"如果​你​真的​遇到​了​拉齐达南，我​希望​你​帮​帮​他。我​和​他​打​过​几​次​交道，发现​他​生性​诚实​\"\n\"且​富有​荣誉感。李奥瑞克​国王​的​追随者​遭受​的​诅咒，在​他​身​上​会​更加​糟糕。\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"拉齐达南​已经​死​了。所有​人​都​知道，你​没​法骗​我。你​不​能​和​死人​说话。我​知道！\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"你​也许​能​遇到​被困​在​迷宫​里​的​人，拉齐​达南​只​是​其中​之一。\\n\"\n\"\\n\"\n\"​我​从​他​身​上​感受​到​荣誉​和​巨大​的​内疚。帮助​他​就​是​帮助​崔斯特姆。\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"等等，让​我​猜猜。一​条​巨大​裂缝​出现​在​凯恩脚​下​将​他​吞噬，地狱烈​焰​把​他​烧​得​个​精光，\"\n\"以至于​没​法​回答​你​问题​了。哦，不​是​那样么？那​我​就​只​能​认为​你​是​想​买​点​东西​或是​该​上\"\n\"路​了。\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"手​下​留情，别​杀​我，请​听​我​把​话​说完。我​曾经​是​李奥瑞克​国王​的​骑士​队长，以​正义​和​荣\"\n\"誉​捍卫​着​这​王国​的​律法。后来​他​的​黑暗​诅咒​降临​在​我们​身​上，只​因​我们​在​他​的​悲剧​死亡​\"\n\"中​扮演​的​角色。当​我​的​其他​骑士​同伴​屈服​于​他们​扭曲​命运​的​时，我​逃出​了​国王​的​墓室，\"\n\"寻找​某​种​能​解除​我​身​上​诅咒​的​方法。我​…​…​失败​了​…​…​\\n\"\n\"\\n\"\n\"​我​听说​有​一​种​“​金色​药剂​”​可以​解除​诅咒，让​我​的​灵魂​安息，可惜​我​无法​找到​它。我​的​意\"\n\"志​逐渐​衰弱，我​也​会​因此​最终​失去​人性。请​帮​帮​我，找到​药剂。我​以​荣耀​发誓​一定​会​报\"\n\"答​你​的​帮助。\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"如果​你​还​没​找到​“​金色​药剂​”，我​就​将​承受​永恒​的​诅咒​了。求​你，继续​寻找​吧​…​…\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"你​把​我​的​灵魂​从​诅咒​中​拯救​出来，为​此​我​欠​你​一​个​人情。如果​有​办法​让​死后​的​我​报​答​\"\n\"你，我​一定​会​去​做，但​现在​能​做​的​——​拿走​我​的​头盔​吧。我​今后​的​旅途​里，用​不​到​它​了。\"\n\"愿​它​能​保护​你​免​受​地底​黑暗​力量​的​侵扰。圣光伴​你​同行，我​的​朋友​…​…\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"格里斯沃尔德​谈到​了​“​愤怒铁砧​”​——​一​件​传说​中​的​神器，人们​一直​在​寻找，但​一直​没有​找\"\n\"到。愤怒​铁砧​是​用​剃刀​坑​恶魔​的​金属​骨头​制作​而​成​的，熔铸​在​五​个​最​强大​的​冥界​法师​的​\"\n\"头骨​周围。刻有​力量​和​混乱​符文，任何​在​这个​铁砧​上​锻造​的​武器​或​护甲​都​将​被​浸入​混乱​\"\n\"的​领域，并​将​其​嵌​入​魔法​属性。据说，混沌​的​不​可​预测性​使​人们​很​难​知道​这​场​锻造​会​有​\"\n\"什么​结果……\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"你​不​觉得​格里斯沃尔德会​是​一​个​更​好​的​人问​这​个​问题​吗？你​知道，他​很​能干。\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"如果​你​一直​在​寻找​治疗​杵​或​净化​银圣杯​的​信息，我​可以​帮助​你，我​的​朋友。不过，在​这​\"\n\"件​事​上，你​最好​和​格里斯沃尔德​或​凯恩​谈​谈。\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"格里斯沃尔德​的​父亲​曾经​告诉​我们​中​的​一些​人，当​我们​成长​的​时候，一​个​巨大​的​铁砧​是​\"\n\"用来​制造​强大​的​武器。他​说，当​一​把​锤子​敲​在​这个​铁砧​上​时，地面​会​剧烈​地震动。每​当​\"\n\"地球​移动​时，我​总是​记得​那​个​故事。\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"你好！很​高兴​见到​我​最​好​的​客户​之一！我​知道​你​一直​在​冒险​深入​迷宫，有​一​个​故事​告诉​\"\n\"我，你​可能​觉得​值得​花​时间​听……\\n\"\n\" \\n\"\n\"​一​个​从​迷宫​里​回来​的​人​告诉​我​他​逃跑​时​遇到​的​一​个​神秘​的​铁砧。他​的​描述​让​我​想起​了​我​\"\n\"年轻​时​听到​的​关于​燃烧​的​地狱炉​的​传说，那里​有​强大​的​魔法​武器。传说​在​地狱​熔炉​的​深\"\n\"处​安放​着​“​愤怒铁砧​”！这个​铁砧​里面​包含​着​恶魔​世界​的​精髓……\\n\"\n\" \\n\"\n\"​据说​任何​在​燃烧​的​铁砧​上​制作​的​武器​都​充满​了​巨大​的​力量。如果​这​铁砧​真的​就​是​“​愤怒铁\"\n\"砧​”，我​也许​能​让​你​成为​一​件​武器，甚至​可以​打败​最​黑暗​的​地狱​之​主！\\n\"\n\" \\n\"\n\"帮​我​找​铁砧，我​就​去​干活！\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"还​没有，嗯？好​吧，继续​找。铁砧​上​锻造​的​武器​可能​是​你​最​大​的​希望，我​相信​我​能​让​你​\"\n\"成为​传奇​般​的​人物​之一。\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"我​简直​不​敢​相信！这​是​“​愤怒铁砧​”。干​得​好，我​的​朋友。现在​我们​要​告诉​那些​混蛋，地\"\n\"狱​里​没有​比​人类​制造​的​武器​更​致命​的​武器​了！拿​着​这个，愿光​护佑​你​。\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"格里斯沃尔德​卖​不​出​他​的​铁砧。那​他​会​怎么​做？如果​有​人​拿​了​我​的​铁砧​我​也​会​生气​的！\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"迷宫​里​有​许多​神器，拥有​着​凡​人​无法​理解​的​力量。其中​一些​拥有​神奇​的​力量，可以​被​光\"\n\"明​或​黑暗​所​利用。从​下面​固定​铁砧​可以​将​原罪之战​的​进程​转向​光明。\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"如果​你​为​格里斯沃尔德​找到​这​件​艺术品，它​会​严重​影响​我​在​这里​的​生意。啊，你​永远​找​\"\n\"不​到​它。\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"鲜血​之​门​与​火焰​大厅​都​是​神秘​起源​的​地标。在​你​读到​这​本​书​的​地方，一定​充盈​着​强大​力\"\n\"量。\\n\"\n\"\\n\"\n\"​传说​有​一​个​用​黑曜​石​雕刻​的​底座，装满​了​漂浮​着​骨屑​的​沸腾​鲜血。传说​还​提到​了​鲜血\"\n\"石，它​能​开起​一​道​守护​远古​财宝​的​大门​…​…​\\n\"\n\"\\n\"\n\"​这​件​宝物​的​本质​到底​是​什么​众说纷纭，疑团​重重，我​的​朋友。但​据说​古代​的​英雄​阿凯尼​\"\n\"把​它​的​圣甲​“​荣耀​”​放置​在​一​个​秘密​的​地方。他​是​第一​个​扭转​原罪之战​的​浪潮，将​黑暗​军\"\n\"团​赶回​烈​焰​地狱​的​凡​人。\\n\"\n\"\\n\"\n\"阿凯尼​临死​前，他​的​铠甲​就​被​秘密​地​藏进​了​一​处​密室​中。相传​等到​这​副圣甲​需要​再​一​次​\"\n\"现世​时，一​位​英雄​将​会​挺身而出，并且​再度​荣耀​加身。也许​你​就​是​那​个​英雄​…​…\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"每​个​孩子​听​过​战士​阿凯尼​和​他​被​称作​“​荣耀​”​的​传奇​盔甲​的​故事。如果​你​能​找到​它​沉睡​的​\"\n\"地方，你​就​能​更​好​的​保护​自己​对抗​迷宫​里​的​邪恶。\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"嗯​…​…​这​听​起来​根本​就​记​不​住，因为​我​一直​忙于​学习​新​的​治疗​方法​和​制作​更​好​的​药剂，我​\"\n\"必须​忘掉​这些​事，抱歉​…​…\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"我​经常​听到​男孩们​讨论​关于​魔法​铠甲​“​荣耀​”​的​故事。你​最好​问问​村​里​的​男人们。\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"被​称作​“​荣耀​”​的​盔甲，也许​将​让​天平​向​你​倾斜。我​想​说​的​是，包括​我​在内​的​许多​人​曾经​\"\n\"都​尝试​寻找​它。阿凯尼​把​它​藏得​很​好，我​的​朋友，得​需要​点​运气​去​揭开​隐藏​它​的​秘密，\"\n\"哎，尽管​这么​多​年​过去​了。\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"一旦​你​发现​了​鲜血石，请​小心​谨慎​的​使用​它。\\n\"\n\"\\n\"\n\"​道路​充满​了​危险，你​唯一​的​希望​源自于​你​的​自信。\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"你​想要​找到​那件​被​称作​“​荣耀​”​的​盔甲？\\n\"\n\"\\n\"\n\"​没​人​知道​阿凯尼​把​东​西藏​在​哪里，如果​我​联系​的​人​都​找​不​到，我​很​怀疑​你​怎么​可能​会​找\"\n\"到。\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"据​我​所​知，只有​一​种​传说​提到​过​你​描述​的​那​个​战士。他​的​故事​记录​在​在​古老​的​《​原罪​之​\"\n\"战编年史​》​中​…​…​\\n\"\n\"\\n\"\n\"​持续​千​年​的​战争，鲜血​与​死亡，鲜血​战神​的​受害者​残肢​断臂​堆积如山。他​的​黑暗​之​刃​向​\"\n\"生者​尖啸，散发​黑色​的​诅咒​；​任何​挡​在​地狱​刽子​手​面前​的​人​都​将​受到​酷刑​的​邀请。\\n\"\n\" \\n\"\n\"书​中​还​写到，尽管​他​只​是​一​个​在​原罪​之​战​中​与​黑暗​军团​并肩​作战​凡​人，但​嗜​血​的​欲望​使\"\n\"得​他​失去​了​人性。\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"如此​歹毒​的​战士​我​从​未​听说，好心​人。我​希望​你​不​用​跟​他​战斗，他​听​上去​是​极其​的​危\"\n\"险。\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"凯恩​能​告诉​你​更​多​有关​的​事情，这些​事​真​是​我​从来​愿意​知道​的。\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"如果​你​要​与​如此​凶猛​的​对手​战斗，那​愿​圣光​指引​和​保佑​你。我​会​一直​惦记​着​你。\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"“​鲜血​战神​”​被​黑暗​邪恶​的​传说​笼罩。做好​准备​我​的​朋友，因为​他​既​不​仁慈，也​不​讲​情\"\n\"面。\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"你​总是​不​停​的​提到​血么？不如说​点​鲜花、阳光​和​送​饮料​的​漂亮​女孩。听​着，朋友，你​真​\"\n\"是​执迷不悟，你​知道么？\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"他​的​剑术​令​人​惊叹，千​年​的​岁月​对​他​而​言​只​有​战斗。我​很​抱歉​…​…​我​也​不​好​判断​你​能​不​否​\"\n\"打败​他。\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"我​从​没​跟​那​个​什么​战神​进行​过​买卖，但是​我​听说​他​用​坏​过​很多​剑。你​不​介意​我​卖点​武器​\"\n\"装备​给​他​吧​…​…\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"我​的​刀刃​正在​为​你​的​血​歌唱，凡​人。我​的​黑暗​主人​也​会​很​高兴​听到​这​歌声。\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"格里斯沃尔德​谈到​了​天石，它​是​注定​要​飞​地位​于​东部。它​被​带到​那里​作​进一步​研究。这​\"\n\"块​石头​闪耀​着​一​种​能量，它​以​某​种​方式​赋予​了​一​个​普通​人​无法​拥有​的​视觉。我​不​知道​它​\"\n\"有​什么​秘密，我​的​朋友，但​找到​这​块​石头​肯定​是​最​有​价值​的。\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"商队​在​这里​停​了​下来，为​他们​向东​旅行​带​去​一些​补给。我​卖给​他们​不少​新鲜​水果​和​一些​\"\n\"佳达​刚刚​烤好​的​上​等​甜​面包。可惜​他们​发生​了​什么……\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"我​不​知道​他们​以为​用​那​块​石头​能​看到​什么，但​我​要​说​的​是。如果​岩石​从天而降，你​最好​\"\n\"小心！\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"好​吧，一​队​重要​人物​停​在​这里，但​那​是​很​久​以前​的​事​了。我​记得，他们​的​口音​很​奇怪，\"\n\"正​开始​长途​旅行。\\n\"\n\" \\n\"\n\"​我​不​明白​你​怎么​能​指望​找到​他们​会​带​的​东西。\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"呆​一会儿​-​我​有​个​故事​你​可能​会​觉得​有趣。一​辆​开往​东方​王国​的​大篷​车​前​段​时间​经过​这\"\n\"里。据说​它​带​着​一​片​落​在​地上​的​天空！大篷车​就​在​这​北​边​的​公路​上​被​披着​斗篷​的​骑手​伏\"\n\"击​了。我​在​残骸​中​搜寻​这​块​岩石，但​找​不​到。如果​你​能​找到​它，我​相信​我​能​从中​找到​有\"\n\"用​的​东西。\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"我​还​在​等​你​从天​上​把​那​块​石头​带给​我。我​知道​我​能​从中​制造​出​强大​的​东西。\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"让​我​看看​-​是​的……是​的，正​如​我​所​相信​的。给​我​一点​时间……\\n\"\n\" \\n\"\n\"​啊，给​你。我​把​几​块​石头​放​在​父亲​留给​我​的​银戒指里。希望​对​你​有​好处。\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"我​曾经​有​一​个​漂亮​的​戒指​；​这​是​一​个​非常​昂贵​的，蓝色，绿色，红色​和​银色。不过，我​\"\n\"不​记得​发生​了​什么。我​真的​很​想​念​那​个​戒指……\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"天石​是​非常​强大​的，如果​是​任何​人，但​格里斯沃尔德​谁​叫​你​找到​它，我​会​阻止​它。他​将​\"\n\"利用​它​的​力量，它​的​使用​将​造福于​我们​所有​人。\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"如果​有​人​能​用​那​块​石头​做​点​什么，格里斯沃尔德​也​能。他​知道​自己​在​做​什么，尽管​我​试\"\n\"图​窃取​他​的​客户，但​我​尊重​他​的​工作​质量。\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"女​巫艾德莉亚​想要​一​个​黑​蘑菇？我​对​黑​蘑菇​的​了解​和​对​红鲱​鱼​的​了解​一样​多。也许​治疗\"\n\"者​佩金​可以​告诉​你​更​多，但​这​是​我​的​任何​故事​或​书籍​中​都​找​不​到​的。\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"我​就​这么​说​吧。我​和​嘉达​永远​不​会​给​我们​的​贵宾​提供​黑蘑菇。如果​艾德莉亚​想​在​炖菜​里​\"\n\"放些​蘑菇，那​是​她​的​事，但​我​帮​不​了​你。黑​蘑菇……恶心！\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"巫婆​告诉​我​你​在​寻找​一​个​恶魔​的​大脑​来​帮助​我​制造​长生​不​老药。如果​我​能​解开​我​怀疑​它​\"\n\"的​炼金术​所​掌握​的​秘密，它​对​许多​被​这些​邪恶​野兽​伤害​的​人​来说​应该​是​非常​有​价值​的。\"\n\"如果​你​能​在​杀死​一​个​恶魔​的​时候​把​它​的​大脑取​出来，如果​你​能​把​它​带给​我，我​将​不胜​感\"\n\"激。\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"太​好​了，这​正​是​我​想要​的。没有​这个​我​就​可以​完成​长生不​老药，但是​有​这个​来​学习​也​没​\"\n\"什么​坏处。请​你​把​这个​带给​女​巫好​吗？我​相信​她​在​等​着​呢。\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"我​想​奥格登​的​地窖​里​可能​有​蘑菇。你​为什么​不​问问​他？\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"如果​艾德莉亚​没有​这些，你​可以​打​赌​这​确实​是​一​件​罕见​的​事情。我​不​能​给​你​更​多​的​帮\"\n\"助，但是​听​起来……一​个​巨大​的，巨大​的，肿胀​的，膨胀​的​蘑菇！嗯，我​想​打猎​不错​吧。\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"奥格登​混合​了​一​种​难​吃​的​黑蘑菇，但​如果​我​喝​了​它​我​会​生病​的。听​着，听​着……秘诀​就​在​\"\n\"这里​——​适度​才​是​关键！\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"我们​这里​有​什么？有趣​的​是，它​看​起来​像​一​本​试剂​书。睁大​眼睛​看黑​蘑菇。它​应该​相当​\"\n\"大，并且​易​于​识别。如果​你​找到​了，把​它​带给​我，好​吗?\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"我​需要​一​个​又​大​又​黑​的​蘑菇。现在​跑​去​给​我​拿，这样​我​就​可以​用​它​做​我​正在​做​的​一​种​特\"\n\"殊​的​调味品​了.\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"是​的，这​将​是​完美​的​酿造，我​正在​创建。顺便​说​一​句，治疗者​正​在​寻找​某​种​恶魔​的​大\"\n\"脑，这样​他​就​可以​治疗​那些​被​他们​的​毒液​折磨​的​人。我​相信​他​打算​用​它​做​长生​不​老药。\"\n\"如果​你​帮​他​找到​他​需要​的​东西，请​你​帮​我​拿​一​个​长生​不​老药​的​样品。\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"你​为什么​把​它​带到​这里​来？我​现在​不​需要​恶魔​的​大脑。我​确实​需要​一些​治疗者​正​在​研制​\"\n\"的​长生​不​老药。他​需要​你​拿​着​的​奇怪​的​器官，然后​给​我​拿​长生​不​老药。想​起来​很​简单，\"\n\"不​是​吗？\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"什么？现在​你​把​医治者​的​长生​不​老​药​带给​我？不用​它​我​也能​完成​我​的​酿造。你​为什么​不​\"\n\"留​着​它……\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"我​没有​任何​大小​和​颜色​的​蘑菇​出售。再​来​点​有用​的​怎么样？\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"所以，地图​上​的​传说​是​真实​的。连​我​都​不​相信！我​想​是​时候​告诉​你​我​是​谁​了，我​的​朋\"\n\"友。你​看，我​并不​像​我​看​起来​那样……\\n\"\n\" \\n\"\n\"​我​的​真名​是​老凯恩，我​是​一​个​古老​兄弟会​的​最后​一​个​后代，这​个​兄弟​会​致力于​保守​和​保\"\n\"护​一​个​永恒​邪恶​的​秘密。一​个​很​明显​已经​被​释放​的​恶魔……\\n\"\n\" \\n\"\n\"​你​要​对付​的​恶魔​是​恐怖​的​黑魔王​——​凡​人​都​知道​的​迪亚波罗。几​个​世纪​前​被​囚禁​在​迷宫​里​\"\n\"的​正​是​他。你​现在​持有​的​地图​是​很​久​以前​创造​的，用来​标记迪亚波罗​从​监禁​中​复活​的​时\"\n\"间。当​那​张​地图​上​的​两​颗​星星​对​齐​时，迪亚波罗​将​达到​他​的​能量​顶峰。他​将​所​向​无\"\n\"敌……\\n\"\n\" \\n\"\n\"​你​现在​在​和​时间​赛跑，我​的​朋友！找到​迪亚波罗，在​众​星云集​之前​消灭​他，因为​我们​可\"\n\"能​再​也​没有​机会​摆脱​他​的​邪恶​了！\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"我们​的​时间​不​多​了！我​感觉​到​了​他​的​黑暗​力量，只有​你​才​能​阻止​他​达到​他​的​全部​力量。\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"我​相信​你​已经​尽力​了，但​我​担心​你​的​力量​和​意志​都​不​够。迪亚波罗​现在​正​处于​他​尘世​力\"\n\"量​的​顶峰，你​将​需要​你​所有​的​勇气​和​力量​来​打败​他。愿​光明​保护​和​指引​你，我​的​朋友。\"\n\"我​将​尽​我​所​能​提供​帮助。\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"如果​女​巫帮​不​了​你，建议​你​去见凯恩，你​凭​什么​认为​我​什么​都​知道？听​起来​这​是​一​件​非\"\n\"常​严重​的​事情。你​应该​像​艾德莉亚​建议​的​那样，赶快​去​见​讲​故事​的​人。\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"我​对​这​张​地图​上​的​文字​不​太​了解，但​也许​艾德莉亚​或​凯恩​能​帮​你​破译​这​是​指​什么。\\n\"\n\" \\n\"\n\"​我​可以​看到​这​是​一​张​我们​天空​中​星星​的​地图，但​比​这​更​是​超出​我​的​能力。\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"问​这​类​事情​的​最​佳​人选​是​我们​的​说书​人。\\n\"\n\" \\n\"\n\"凯恩​对​古代​著作​非常​了解，这​是​我​见​过​的​最​古老​的​一​张​纸。\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"我​以前​从​未​见​过​这样​的​地图。你​从​哪儿​弄来​的？虽然​我​不​知道​该​怎么​读​这​篇​文章，但​凯\"\n\"恩​或​艾德莉亚​也许​能​提供​你​所​寻求​的​答案。\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"听​着，靠近点。我​不​知道​你​是否​知道​我​所​知道​的，但​你​真的​有些​东西​在​这里。那​是​一​张​\"\n\"地图。\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"哦，恐怕​这​一点​都​不​是​好​兆头。这​张​星图​预示​着​巨大​的​灾难，但​它​的​秘密不​是​我​说​的。\"\n\"是​时候​让​你​和​讲​故事​的​人​好好​谈​谈​了……\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"我​一直​在​找​地图，但​那​肯定​不是。你​应该​把​这个​给​艾德莉亚​看-​她​可能​会​告诉​你​是​什么。\"\n\"我​要​说​一​件​事​；​它​看​起来​很​老，而且​老​通常​意味​着​有​价值。\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"请​放心，不​要​受伤。不​杀人。保持​活力，下​次​给​你​带来​好​东西。\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"我​正在​为​你​做​些​东西。再说​一​遍，别​杀​了​加尔巴德。活​得​好好​的。\\n\"\n\" \\n\"\n\"​你​把​这​当作​我​遵守​诺言​的​证据……\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"还​没有！差不​多​了。\\n\"\n\" \\n\"\n\"​非常​强大，非常​强大。生存！生存！\\n\"\n\" \\n\"\n\"​没有​痛苦，我​信守​诺言！\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"这​对​你​来说​太​好​了。非常​强大！你​想要​-​你​拿！\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"什么？！你​为什么​在​这里？所有​这些​干扰​都​足以​让​人​发疯。来，拿​着​这个，让​我​继续​工\"\n\"作。别​再​烦​我​了！\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"啊！你​的​好奇心​将给你​​带来​死亡！！！\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"你​好，我​的​朋友。呆​一会儿​听​我​说……\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"当​你​冒险​深入​迷宫​时，你​可能​会​发现​那里​藏​着​大量​的​知识。\\n\"\n\" \\n\"\n\"​仔细​阅读​它们，因为​它们​能​告诉​你​即使​是​我​也​不​能​告诉​你​的​事情。\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"我​知道​许多​神话​和​传说，其中​可能​包含​对​你​在​迷宫​之​旅​中​可能​出现​的​问题​的​答案。如果​\"\n\"你​遇到​挑战​和​问题，你​寻求​知识，寻找​我​出来，我​会​告诉​你​我​能​做​什么。\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"格里斯沃尔德​——​一​个​行动力​和​勇气​都​很​强​的​人。我​打​赌​他​从​没​告诉​过​你​他​进迷宫​救怀特​\"\n\"的​事，是​吗？他​知道​在​那里​会​有​很多​危险，但​话​说​回来，你​也是。他​是​一​个​技艺​高超​的​\"\n\"工匠，如果​他​声称​能​以​任何​方式​帮助​你，你​可以​指望​他​的​诚实​和​他​的​技能。\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"奥格登​已经​拥有​和​经营​旭日​酒店​近​四​年​了。他​买​了​它​就​在​几​个​月​前，这里​的​一切​都​变成​\"\n\"了​地狱。他​和​他​的​妻子​加尔达​没有​钱​离开，因为​他们​把​所有​的​钱​都​投资​在​这里​为​自己​创\"\n\"造​生活。他​是​一​个​很​有​责任感​的​好​人。\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"可怜​的​法恩汉。他​令​人​不安​地​提醒​人们，在​那​黑暗​的​一​天，注定​要​与​拉扎鲁斯一起​进入​\"\n\"大​教堂​的​集会。他​带​着​生命​逃走​了，但​他​的​勇气​和​大部分​的​理智​都​留​在​了​某​个​黑暗​的​坑​\"\n\"里。如今，他​只​在​酒馆​的​最​底​层​找到​安慰，但​在​他​不断​的​闲谈​中，偶尔​也​隐藏​着​一些​真\"\n\"相。\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"女​巫艾德莉亚​是​崔斯特姆​的​一​个​异类。她​是​在​大​教堂​被​亵渎​后​不久​到达​的，而​大多数​人​\"\n\"都​在​逃离。她​在​城镇​边缘​建​了​一​间​小​屋，似乎​是​一​夜​之间​建成​的，她​能​接触​到​许多​奇怪​\"\n\"而​神秘​的​文物​和​知识​的​大部头，连​我​都​从​未​见​过。\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"怀特​的​故事​是​一​个​可怕​而​悲惨​的​故事。他​从​他​母亲​的​怀抱​中​被​带到​迷宫​里，被​那些​挥舞​\"\n\"邪恶​长矛​的​邪恶​小​恶魔们​拖进​了​迷宫。那​天​还​有​许多​孩子​被​带走，包括​李奥瑞克​国王​的​\"\n\"儿子。宫殿​的​骑士们​下楼​去​了，但​再​也​没有​回来。铁匠​找到​了​那个​男孩，但​那​是​在​那些​\"\n\"邪恶​的​野兽​开始​折磨​他​以​获取​他们​的​虐待​狂般​的​快乐​之后。\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"啊，佩金。我​把​他​视为​真正​的​朋友​——​也许​是​我​在​这里​最​亲密​的​朋友。他​有时​有点​烦躁不\"\n\"安，但​从来​没有​一​个​更​关心​和​体贴​的​灵魂​存在​过。他​的​知识​和​技能​为数​不​多，他​的​大门​\"\n\"总是​敞开​的。\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"吉莉安​是​个​好​女人。她​因兴​高采烈​和​爽朗​的​笑声​而​备受​崇拜，在​我​心​中​占有​特殊​的​地\"\n\"位。她​留​在​酒馆​里​养活​年迈​的​祖母，因为​她​病得​不​能​旅行​了。我​有时​担心​她​的​安全，但​\"\n\"我​知道​村​里​的​任何​男人​都​宁愿​死​也​不​愿​看到​她​受到​伤害。\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"你​好，​大人。欢迎​来到​朝阳​酒馆！\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"我​的​酒馆​里​有​许多​冒险家，讲​的​故事​是​喝​啤酒​的​十​倍。我​唯一​听到​他们​一致​同意​的​就​是​\"\n\"这​条​古老​的​公理。也许​这​对​你​有​帮助。你​可以​割肉，但​必须​压碎​骨头。\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"铁匠​格里斯沃尔德​对​武器​和​护甲​非常​了解。如果​你​需要​修理​你​的​装备，他​绝对​是​你​要​找​\"\n\"的​人。\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"法恩汉​在​这里​待​的​时间​太​长​了，他​用​廉价​的​啤酒​来​消愁。我​想​让​他​离开，但​他​在​迷宫​里​\"\n\"的​时候​确实​很​痛苦。\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"艾德莉亚​的​智慧​超过​了​她​的​年龄，但​我​必须​承认​——​她​有点​吓​到​我​了。\\n\"\n\" \\n\"\n\"​好​吧，没​关系。如果​你​需要​交易​巫术​物品，她​在​河​对岸​有​一​个​奇怪​的​仓库。\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"如果​你​想​更​多​地​了解​我们​村子​的​历史，讲​故事​的​凯恩​对​过去​的​事​相当​了解。\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"怀特​是​个​说​唱​歌手​和​小​流氓。他​总是​惹​麻烦，发生​在​他​身​上​的​事​也​就​不足为奇​了。\\n\"\n\" \\n\"\n\"​他​可能​去​了​一​个​他​不​该​去​的​地方。我​为​那个​男孩​感到​难过，但​我​不​愿意​和​他​作伴。\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"佩金​是​个​好​人，当然​也​是​村​里​最​慷慨​的​人。他​总是​关心​别人​的​需要，但​无论​他​走到​哪\"\n\"里，总​有​一些​麻烦​跟着​他……\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"吉莉安，我​的​酒吧​女​招待？如果​不​是​因为​她​对​大坝​的​责任感，她​早​就​从​这里​逃走​了。\\n\"\n\" \\n\"\n\"天​知道​我​求​她​离开，告诉​她​我​会​照顾​那​个​老​妇人，但​她​太​可爱​了，太​体贴​了。\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"你​怎么​了，我​的​朋友？\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"我​有​一​个​非常​有趣​的​发现。与​我们​不同​的​是，迷宫​中​的​生物​不​用药​水​或​魔法​就​能​自愈。\"\n\"如果​你​伤害​了​其中​一​个​怪物，确保​它​已经​死​了，否则​它​很​可能​会​自己​再生。\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"在​它​被​下面​隐藏​的​东西​接管​之前，大​教堂​是​一​个​非常​有​学问​的​地方。那里​有​许多书​可以​\"\n\"找到。如果​你​发现​了​什么，你​应该​把​它们​全部​读​一​遍，因为​有些​可能​掌握​着​迷宫​运作​的​\"\n\"秘密。\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"格里斯沃尔德​对​战争​艺术​的​了解​和​我​对​治疗​艺术​的​了解​一样​多。他​是​个​精明​的​商人，但​\"\n\"他​的​工作​是​首屈一指​的。哦，我​想​那​可能​是​因为​他​是​这里​唯一​的​铁匠。\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"凯恩​是​一​个​真正​的​朋友​和​智慧​的​圣人。他​拥有​一​个​庞大​的​图书馆，有​一​种​与生俱来​的​能\"\n\"力​来​辨别​许多​事物​的​本质。如果​你​有​任何​问题，他​就​是​你​要​找​的​人。\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"就​连​我​的​技能​也​无法​完全​治​愈法恩汉。哦，我​已经​能​修好​他​的​身体​了，但是​他​的​精神​和​\"\n\"精神​我​无​能​为力。\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"当​我​使用​一些​有限​的​魔法​来​创造​我​储​存​在​这里​的​药剂​和​长生​不​老药​时，艾德莉亚​是​一​个​\"\n\"真正​的​女巫。她​似乎​从​不​睡觉，她​总是​能​接触​到​许多​神秘​的​大部头​和​文物。我​相信​她​的​\"\n\"小屋​可能​比​看​上去​的​小屋​要​大​得​多，但​我​似乎​永远​也​进​不​了​这个​地方。\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"可怜​的​怀特。我​为​那​孩子​做​了​一切​可能​的​事，但​我​知道​他​看​不​起​我​被迫​绑​在​他​腿上​的​木\"\n\"钉。他​的​伤口​很​难​看。没有​人​——​尤其是​这么​小​的​孩子​——​应该​像​他​那样​受​苦。\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"我​真​不​明白​奥格登​为什么​留​在​崔斯特姆。他​有点​紧张，但​他​是​一​个​聪明​而​勤奋​的​人，无\"\n\"论​他​去​哪里​都​会​做​得​很​好。我​想​可能​是​因为​害怕​周围​农村​发生​的​许多​谋杀案，也​可能​是​\"\n\"因为​他​妻子​的​愿望，他​和​他​的​家人​一直​呆​在​那里。\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"奥格登​的​酒吧​女​招待​是​个​可爱​的​女孩。她​祖母​病​得​很​重，有​妄想症。\\n\"\n\" \\n\"\n\"​她​声称​那​是​幻觉，但​我​没有​证据​证明​这​一​点。\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"你​好！有​什么​我​能​为​您​效劳​吗？\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"我​祖母​梦​见​你​来​和​我​说话。她​有​远见​卓识，你​知道，而且​能​预见​未来。\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"镇​边​的​那​个​女人​是​个​女巫！她​看​起来​很​好，她​的​名字​叫​艾德莉亚，很​讨人​喜欢，但​我​很​\"\n\"害怕​她。\\n\"\n\" \\n\"\n\"像​你​这样​勇敢​的​人才​能​看到​她​在​外面​干​什么。\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"我们​的​铁匠​是​崔斯特姆​人民​的​骄傲。他​不仅​是​一​个​手艺​大师，在​他​的​行会​中​赢得​了​许多​\"\n\"比赛，而且​他​还​得到​了​我们​国王​李奥瑞克​本人​的​赞扬​——​愿​他​的​灵魂​安息。格里斯沃尔德​\"\n\"也​是​一​位​伟大​的​英雄​；​问问​凯恩。\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"从​我​记事​起，凯恩​一直​是​崔斯特姆​的​说​书​人。他​知道​的​太​多​了，几乎​什么​都​能​告诉​你。\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"法恩汉​是​个​酒鬼，他​的​肚子​里​装满​了​啤酒，其他​人​的​耳朵​里​全​是​废话。\\n\"\n\" \\n\"\n\"​我​知道​佩金​和​奥格登​都​同情​他，但​每​天​晚上​看​着​他​越来越​昏迷​不​醒，我​感到​非常​沮丧。\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"佩金救​了​我​祖母​的​命，我​知道​我​永远​也​报答​不​了​他。他​治愈​任何​疾病​的​能力​比​最​强大​的​\"\n\"剑​更​强大，比​你​能​说出​的​任何​法术​都​更​神秘。如果​你​需要​治疗，佩金​可以​帮助​你。\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"我​和​怀特​的​母亲，加那斯​一​起​长大。虽然​当​那些​可怕​的​生物​偷走​他​时，她​只​是​受到​了​轻\"\n\"微​的​伤害，但​她​始终​没有​康复。我​想​她​死​于​心碎。怀特​成​了​一​个​小气鬼，只​想​从​别人​的​\"\n\"汗水​中​获利。我​知道​他​受苦受难，经历​过​我​无法​想象​的​恐惧，但​他​身​上​仍然​笼罩​着​一些​\"\n\"黑暗。\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"奥格登​和​他​的​妻子​把​我​和​我​的​祖母​带到​他们​家​里，甚至​让​我​在​旅馆​工作​挣​了​几​块​金币。\"\n\"我​欠​他们​太​多​了，希望​有​一​天​离开​这个​地方，帮助​他们​在​东方​开​一​家​大​酒店。\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"你​好，我​能​为​你​做​些​什么？\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"如果​你​想​找​一​件​好​武器，让​我​给​你​看看。带上​你​最​基本​的​钝器，比如​狼牙棒。像​一​个​魅\"\n\"力​对抗​那些​不朽​的​恐惧​在​那里，没有​什么​比​粉碎​瘦小​的​骨架​更​好！\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"斧头？是​的，这​是​一​个​很​好​的​武器，可以​对付​任何​敌人。看看​它​是​如何​劈​开​空气​的，然\"\n\"后​想象​一​个​漂亮​的​胖魔鬼​头​在​它​的​路径​上。但是，请​记住，摇摆​是​很​慢​的，但是​谈论​如\"\n\"何​处理​一​个​沉重​的​打击！\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"看看​那​个​边缘，那个​平衡。右​手​中​的​剑，和​对​的​敌人，是​一切​武器​的​主人。它​锐利​的​刀\"\n\"锋​在​不​死​生物​身上​几乎​找​不​到​可​砍​或​可​刺​的​东西，但​对于​一​个​活生生​的、会​呼吸​的​敌\"\n\"人，一​把​剑会​更​好​地​切开​他们​的​肉！\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"你​的​武器​和​护甲​将​显示​你​与​黑暗​斗争​的​迹象。如果​你​把​它们​带到​我​这里​来，稍加​改造​和​\"\n\"热锻，我​就​能​把​它们​恢复​到​最佳​战斗​状态。\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"当​我​不​得不​从​我们​该​死​的​小​镇​边缘​的​商队​里​偷运​我​所​需要​的​金属​和​工具​时，那​个​女​巫艾\"\n\"德莉亚​似乎​总​能​得到​她​所​需要​的​一切。如果​我​像​她​那样​懂得​如何​运用​魔法，我​就​能​做出​\"\n\"一些​真正​不可​思议​的​事情。\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"吉莉安​是​个​好​姑娘。可惜​她​的​男朋友​身体​这么​差，否则​我​会​安排​他们​两​个​都​乘商队​离开​\"\n\"这里。\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"有时​我​觉得​凯恩​说​得​太​多​了，但​我​想​这​是​他​一​生​的​使命。如果​我​能​像​他​能​弯曲​你​的​耳朵​\"\n\"一样​弯曲​钢铁，我​就​能​做​一​套​足够​好​的​皇帝​用​的​宫廷​盘子！\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"那​天​晚上​我​和​法恩汉​在一起，拉扎鲁斯​把​我们​领进​了​迷宫。我​再​也​见不到​大主教​了，如\"\n\"果​法恩汉​不​在​我​身边，我​可能​就​活​不​下去​了。我​担心​这​次​袭击​使​他​的​灵魂​像​另​一​次​袭击​\"\n\"我​的​腿​一样​残废。我​现在​不​能​为​他​而​战，但​如果​可以​的​话​我​会​的。\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"把​别人​的​需要​放​在​自己​的​需要​之上​的​好​人。你​不​会​发现​任何​人​留​在​崔斯特姆-​或​任何​其他​\"\n\"地方​的​问题​-​谁​有​一​个​坏​东西​说​的​治疗者。\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"那​小子​会​惹​上​大​麻烦​的……或者​我​想​我​应该​再​说​一​遍。我​试​着​让​他​对​在​这里​工作​和​学习​诚\"\n\"实​的​贸易感​兴趣，但​他​更​喜欢​经营​来源​可疑​的​货物​的​高额​利润。我​不​能​在​他​出​事​后​再​对​\"\n\"他​说​这话，但​我​真​希望​他​至少​要​小心点。\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"客栈​老板​没有​什么​生意，也​没有​真正​的​盈利​途径。他​设法​维持​生计，为​那些​偶尔​在​村子​\"\n\"里​漂泊​的​人​提供​食物​和​住宿，但​他们​很​可能​会​偷偷​溜进​夜空，就​像​他们​付​钱​给​他​一样。\"\n\"如果​不​是​因为​他​在​地窖里​储存​了​大量​的​谷物​和​干肉，为什么，我们​大多数​人​会​在​第一​年​\"\n\"饿死，那时​整​个​乡村​都​被​恶魔​蹂​躏。\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"你​个​家伙​就​不​能​安静​地​喝​酒​吗？\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"送​饮料​的​那​个​女孩？哦，是​啊，多​漂亮​的​女人​啊。太​好​了。\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"为什么​那个​老太​婆​不​改变​一下。当然，当然，她​有​东西，但​你​听​我​说……她​很​不​自然。我​\"\n\"从来​没​见​过​她​吃喝​——​你​也​不​能​相信​一​个​不​喝​酒​的​人。\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"凯恩​不​是​他​说​的​那样。当然，当然，他​讲​了​一​个​好​故事……有些​真的​很​吓人​或者​很​有趣……\"\n\"但​我​想​他​知道​的​比​他​知道​的​还​多。\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"格里斯沃尔德？善良​的​老格里斯沃尔德。我​像​兄弟​一样​爱​他！我们​一起​战斗，你​知道，\"\n\"当……我们……拉扎鲁斯……拉扎鲁斯……拉扎鲁斯！！！\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"呵呵，我​喜欢​佩金。他​真的​很​努力，你​知道​的。听​着，你​应该​了解​他。像​这样​的​好​人​总\"\n\"是​有​人​想​帮忙。嘿，我​想​那​会​有点​像​你，英雄？我​也​是​个​英雄……\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"怀特​是​个​问题​比​我​还​多​的​孩子，我​知道​所有​的​问题。听​着​-​那​孩子​一定​是​个​好​人，但​他​去​\"\n\"过​那里，你​知道​吗？丢​了​一​条​腿！得​在​一​块​木头​上​走​来​走去。太​伤心​了，太​伤心​了……\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"奥格登​是​镇​上​最​好​的​男人。我​觉得​他​妻子​不​太​喜欢​我，但​只要​她​不​停​地​敲桶，我​就​很​喜\"\n\"欢​她。似乎​我​和​奥格登​在一起​的​时间​比​大多数​人​都​多，但​他​对​我​很​好……\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"我​想​告诉​你，因为​我​知道​这​一切。这​是​我​的​专长。这​是​最​好​的……最​好​的！其他​的​啤酒​不​\"\n\"好，因为​那些​蠢​狗……\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"从来​没有​人……听​我​说。在​某​个​地方​-​我​不​太​确定​-​但是​在​教堂​下面​的​某​个​地方​有​一​堆​金\"\n\"子。闪闪​发光，只是​等待​有​人​得到​它。\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"我​知道​你​有​自己​的​想法，我​知道​你​不​会​相信​的，但​你​的​武器，你​在​那里​-​它​只​是​不​好​对付​\"\n\"那些​大​畜生！哦，我​不管​格里斯沃尔德​怎么​说，他们​不​能​像​以前​那样​做​任何​东西……\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"如果​我​是​你……我​不​是……但​如果​我​是，我​会​卖掉​你​所有​的​东西​然后​离开​这里。外面​那​个​男\"\n\"孩……他​总是​有​好​东西，但​你​得​给​他​点金子，否则​他​连​他​的​东西​都​不​给​你​看。\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"我​感觉​到​一​个​灵魂​在​寻找​答案……\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"智慧​是​应​得​的，而​不​是​给予​的。如果​你​发现​了​一​本​知识​的​大部头，就​要​吞没​它​的​文字。\"\n\"如果​你​已经​掌握​了​书​中​描述​的​神秘​事物​的​知识，记住​-​掌握​的​水平​总是​可以​提高​的。\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"最​强大​的​力量​往往​是​最​短命​的。你​可以​在​羊​皮纸​的​卷轴​上​找到​古老​的​权力​话语。这些​卷\"\n\"轴​的​力量​在于​学徒​或​熟练​的​施展​能力。他们​的​弱点​是，他们​必须​首先​大声​朗读，永远​不​\"\n\"能​随时​准备​在​你​的​脑海​中。还​要​知道​这些​卷轴​只​能​读​一​次，所以​要​小心​使用。\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"尽管​太阳​的​热量​无法​估量，但​光是​蜡烛​的​火焰​就​更​危险。没有​适当​的​聚焦，任何​能量，\"\n\"无论​多​大，都​不​能​被​使用。对于​许多​法术​来说，被​赋予​灵能​的​杖​可以​被​多​次​充满​魔法​能\"\n\"量。我​有​能力​恢复​他们​的​力量，但​我​知道​没有​代价​是​做​不​到​的。\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"我们​知识​的​总和​就​是​它​的​人民​的​总和。如果​你​发现​一​本​书​或​卷轴，你​不​能​破译，不​要​犹\"\n\"豫，把​它​给​我。如果​我​能​理解​的话，我​会​分享​我​的​发现。\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"对​一​个​只​懂​钢铁​的​人​来​说，没有​什么​比​钢铁​更​神奇​了。铁匠​格里斯沃尔德比​他​所​知道​的​\"\n\"更​像​个​巫师。他​融火​与​金属​的​能力​在​这​片​土地​上​是​无与伦比​的。\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"腐败​有​欺骗​的​力量，而​清白​有​纯洁​的​力量。年轻​的​吉莉安​有​一​颗​纯洁​的​心，把​女​家长​的​\"\n\"需要​凌驾于​自己​的​需要​之上。她​害怕​我，但​那​只​是​因为​她​不​了解​我。\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"在​黑暗中​打开​的​箱子​所​装​的​财宝，并不​比​在​光明​中​打开​的​箱子​更​大。讲​故事​的​凯恩​是​一​\"\n\"个​谜，但​只有​那些​谁​不​看。他​对​大​教堂​下面​的​东西​的​了解​远远​超过​了​他​自己​的​想象。\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"你​对​一​个​人​的​信心​越​高，他​就​越​会​堕落。法恩汉​已经​失去​了​他​的​灵魂，但​不​是​任何​恶\"\n\"魔。当​他​看到​他​的​同乡们​被​拉扎鲁斯大​主教​出​卖​时，他​失去​了​理智。他​有​知识​可以​收\"\n\"集，但​你​必须​把​事实​和​幻想​分开。\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"手、心​和心​在​完美​的​和谐​中​就​能​创造​奇迹。治疗者​佩金​以​一​种​连​我​都​看​不​到​的​方式​观察​\"\n\"身体。他​对​长生​不​老药​和​药水​的​理解​使​他​恢复​病人​和​伤者​的​能力​得到​了​放大。他​和​你​在​\"\n\"崔斯特姆​一样​是​个​伟大​的​盟友。\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"未来​有​很多​我们​看​不​到​的，但​当​它​来​临​时，将​是​孩子们​掌握​着​它。这个​男孩​的​灵魂​是​黑\"\n\"暗​的，但​他​对​这个​城镇​和​它​的​人民​没有​威胁。他​与​附近​城镇​的​顽童​和​不​为​人知​的​行会​的​\"\n\"秘密​交易​使​他​能够​接触​到​许多​在​崔斯特姆​很​难​找到​的​设备。虽然​他​的​方法​可能​会​受到​指\"\n\"责，但​怀特​可以​为​你​对抗​日益​逼近​的​黑暗​提供​帮助。\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"土墙​和​茅草​屋顶​不​是​一​个​家。旅馆​老板​奥格登​在​这个​镇​上​的​作用​比​许多​人​所​理解​的​要​大​\"\n\"得​多。他​为​吉莉安​和​她​的​女族​长​提供​庇护所，维持​法恩汉​留给​他​的​生活，并​为​留​在​镇​上​\"\n\"的​所有人​提供​一​个​锚，让​他们​回到​崔斯特姆​曾经​的​样子。他​的​小酒馆，以及​在​那里​仍然​\"\n\"可以​找到​的​简单​的​乐趣，让​我们​看到​了​这里​的​人们​所​记得​的​生活。正​是​这​段​记忆，让​他\"\n\"们​对​你​的​成功​充满​了​希望。\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"嘿​…​…​过来​这儿​…​…\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"并​不​是​所有​在​崔斯特姆​的​人​都​有​一​个​用途​-​或​市场​-​你​会​发现​在​迷宫​中​的​一切。连​我​都​不​\"\n\"相信。\\n\"\n\" \\n\"\n\"​有时候，只有​你​才​能​为​某些​事情​找到​目标。\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"别​相信​醉汉​说​的​每​一​句​话。太​多​的​啤酒​模糊​了​他​的​视力​和​判断力。\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"如果​你​没​注意​到，我​不​会​从​崔斯特姆​买​任何​东西。我​是​一​个​进口​优质​商品​的​进口商。如\"\n\"果​你​想​兜售​垃圾，你​得​去​看看​格里斯沃尔德，佩金​或​那​个​女巫，艾德莉亚。我​相信​他们​\"\n\"会​抢购​你​能​带给​他们​的​任何​东西……\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"我​想​我​欠铁匠​一​条​命​——​这​是​怎么回​事。当然，格里斯沃尔德​让​我​在​铁匠​铺当​学徒，他​是​\"\n\"个​很​好​的​人，但​我​永远​拿​不​到​足够​的​钱……好​吧，就​说​我​有​明确​的​计划，需要​大量​的​黄\"\n\"金。\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"如果​我​再​大​几​岁，我​会​尽​我​所​能​给​她​带来​财富，让​我​向​你​保证，我​可以​得到​一些​非常​好​\"\n\"的​东西。吉莉安​是​一​个​美丽​的​女孩，她​应该​尽快​离开​崔斯特姆，只要​它​是​安全​的。嗯……\"\n\"也许​我​去​的​时候​会​带​她​一起​去……\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"凯恩​知道​的​太​多​了。他​把​我​吓死​了，甚至​比河​对岸​的​那​个​女人​还​可怕。他​不​停​地​告诉​\"\n\"我，我​活​着​是​多么​幸运，我​的​故事​是​如何​在​传说​中​被​预言​的。我​想​他​是​疯​了。\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"法恩汉-​现在​有​一​个​男人​有​严重​的​问题，我​知道​所有​的​严重​问题​可以。他​过于​相信​一​个​人​\"\n\"的​正直，拉扎鲁斯​就​把​他​带进​了​死亡​的​深渊。哦，我​知道​下面​是​什么样​的，所以​别​告诉​\"\n\"我​你​打算​消灭​迷宫​里​的​恶魔。小心​你​的​腿……\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"只要​你​不​需要​任何​东西​复位，老佩金​是​一样​好，他们​来​了。\\n\"\n\" \\n\"\n\"​如果​我​有​一些​他​酿造​的​药水，我​可能​还​有​腿……\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"艾德莉亚真​让​我​烦恼。当然，凯恩​对​你​说​的​关于​过去​的​事​是​令​人​毛骨悚然​的，但​那​个​女​\"\n\"巫能​看​透​你​的​过去。她​也​总​有​办法​得到​她​需要​的​东西。艾德莉亚​拿到​的​商品​比​我​在​节日​\"\n\"期间​穿过​国王​集市​的​大门​看到​的​还​要​多。\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"奥格登呆​在​这里​真​是​个​傻瓜。我​可以​以​一​个​非常​合理​的​价格​把​他​弄​到​城外​去，但​他​坚持​\"\n\"要​和​那家​愚蠢​的​酒馆​混​过去。我​想​至少​他​给​了​吉莉安​一​个​工作​的​地方，他​的​妻子​嘉达​做​\"\n\"了​一​个​很​棒​的​牧羊派……\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"在​英雄​走廊​的​另​一​端​藏匿​着​白骨密室。任何​胆​敢​盗取​此​地​财宝​的​人，都​将​遭受​永恒​的​死\"\n\"亡。恐惧​之​王​如是​说，本​书​也​如实​写。\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"…​…​于是，打开​鲜血​之​门，穿过​火焰​大厅，荣耀​等待​着​光明​的​英雄​去​唤醒​…​…\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"我​能见​你​所​不​能​见​，\\n\"\n\"​鬼影缭绕​腐蚀​肉眼​。\\n\"\n\"方​一​转身​全数​消散​，\\n\"\n\"​耳边​响起​招魂​童谣。\\n\"\n\"​无形​之​物​即​现眼前​，\\n\"\n\"光影​交叠​怨气弥漫。\\n\"\n\"​撕裂​心灵​冲破​黑暗​，\\n\"\n\"​目盲​之厅​不​见​彼岸。\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"地狱​的​军械库​如同​鲜血​战神​的​私宅。其​所​到​之​处，无​不​留下​成千上万​的​残肢断臂。无论​\"\n\"是​天使​还是​人类​都​将​遭到​残杀，只​为了​能够​呈上​邪魔们​最​渴望​的​东西​——​鲜血。\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"注意​并​见证​这里​的​真理，因为​它们​是​赫拉迪姆​最后​的​遗产。甚至​在​现在，在​我们​所​知​的​\"\n\"领域​之外，在​天堂​的​乌托邦​王国​和​燃烧​地狱​的​混乱​深渊​之间，仍​有​一​场​战争​在​肆虐。这​\"\n\"场​战争​被​称为​大​冲突，它​的​肆虐​和​燃烧​时间​比​天空​中​任何​一​颗​星星​都​要​长。只要​光明​和​\"\n\"黑暗​的​力量​不断​争夺​对​所有​造物​的​控制权，任何​一​方​都​不​会​获得​支配权。\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"注意​并​见证​这里​的​真理，因为​它们​是​赫拉迪姆​最后​的​遗产。当天堂​和​地狱​之间​永恒​的​冲\"\n\"突​落​在​凡人​的​土地​上，这​就​是​原罪之战。天使​和​恶魔​伪​装​着​行走​在​人类​之中，秘密​地​战\"\n\"斗，远离​凡人​窥探​的​眼睛。一些​勇敢、强大​的​凡人​甚至​与​任何​一​方​结盟，并​帮助​指挥​罪\"\n\"恶​战争​的​进程。\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"注意​并​见证​这里​的​真理，因为​它们​是​赫拉迪姆​最后​的​遗产。近​三百​年​前，人们​知道​燃烧​\"\n\"地狱​的​三​大​恶魔​神秘​地​来到​了​我们​的​世界。兄弟​三​人​蹂躏​东方​的​土地​数十​年，而​人类​却​\"\n\"在​他们​身​后​战栗。我们​的​骑士团​——​赫拉迪姆​——​是​由​一​群​神秘​的​法师​建立​的，目的​是​一​劳\"\n\"永逸​地​追捕​和​俘虏​这​三​个​恶魔。\\n\"\n\" \\n\"\n\"​最初​的​赫拉迪姆​在​被​称为​“​灵魂​石​”​的​强大​文物​中​捕获​了​其中​两​个，并​将​它们​深​埋​在​荒凉​\"\n\"的​东部​沙漠​之下。第三​个​恶魔​逃脱​了​追捕，逃到​了​西部，许多​赫拉迪姆人​都​在​追捕。第\"\n\"三​个​恶魔-​被​称为​迪亚波罗，恐惧​之​王​-​最终​被​俘虏，他​的​灵魂石​和​埋​在​这​个​迷宫​的​本\"\n\"质。\\n\"\n\" \\n\"\n\"​要​被​警告，灵魂​之石​必须​防止​被​那些​不​信​的​人​发现。如果​迪亚波罗​被​释放，他​会​寻找​一​\"\n\"个​身体​很​容易​控制，因为​他​会​非常​虚弱-​也许​是​一​个​老人​或​儿童。\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"因此，在​燃烧​的​地狱​里​发生​了​一​场​被​称为​黑暗​放逐​的​伟大​革命。较​小​的​邪恶​推翻​了​三​个​\"\n\"主要​的​邪恶，并​将​他们​的​精神​形式​放逐​到​凡人​的​领域。恶魔彼​列尔​（​谎言之王​）​和​阿兹\"\n\"莫丹​（​罪恶​之​王​）​在​兄弟​三​人​不​在​的​时候​争夺​地狱​的​统治权。所有​的​地狱​恶魔​都​在​彼列\"\n\"尔​和​阿兹莫丹​两​个​派系​之间​分化，而​天堂​的​力量​不断​地​冲击​着​地狱​的​大门。\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"许多​恶魔​为了​寻找​三​兄弟​来到​了​凡间。这些​恶魔​被​天使们​带到​了​凡​间，他们​在​东方​的​广\"\n\"大​城市​里​猎杀​他们。天使们​与​一​个​隐秘​的​名​为​赫拉迪姆​法师​教团​结盟，他​很​快​就​变得​善\"\n\"于​猎杀​恶魔。他们​也​在​阴间​制造​了​许多​黑暗​的​敌人。\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"因此，这​三​个​主要​的​恶魔​以​灵魂​的​形式​被​放逐​到​凡人​的​领域，在​东方​缝​了​几十​年​的​混乱​\"\n\"之后，他们​被​凡人​赫拉迪姆​的​诅咒​的​秩序​所​追捕。赫拉迪姆​使用​了​被​称为​“​灵魂​石​”​的​人\"\n\"工​制品​来​容纳​仇恨​之​主​墨菲斯托​和​他​的​兄弟​毁灭​之​主巴力​的​精髓。最​小​的​弟弟​——​恐惧​之​\"\n\"王迪亚波罗​——​逃到​了​西方。\\n\"\n\" \\n\"\n\"​最终，赫拉迪姆​也​在​一​块​灵魂石中​俘​获​了​迪亚波罗，并​将​他​埋葬​在​一​座​被​遗忘​的​古老大​\"\n\"教堂​下。在​那里，恐怖​之​主​沉睡​着，等待​着​他​的​重生。你们​要​知道，他​要​寻求​一​个​充满​\"\n\"青春​和​力量​的​身体​来​占有，一​个​清白​和​容易​控制​的​身体。然后​他​会​起来​解救​他​的​兄弟\"\n\"们，再​一​次​煽起​原罪之战​的​火焰……\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"所有​赞扬迪亚波罗-恐惧​之​王​和​黑暗​流放​的​幸存者。当​他​从​沉睡​中醒​来​时，我​的​主人​和​主\"\n\"人​对​我​说​了​一些​很​少​有​人​知道​的​秘密。他​告诉​我，天上​的​王国​和​燃烧​的​地狱​的​深坑​正在​\"\n\"进行​一​场​永恒​的​战争。他​揭示​了​将​这​种​不​和谐​带到​人类​领域​的​力量。我​主​已​将​这​场​为​世\"\n\"界​而​战​的​战争​和​所有​在​这里​生存​的​人​命名​为​原罪之战。\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"荣耀​和​赞许​给​迪亚波罗-恐惧​之​王​和​三​人​之​首。我​主​对​我​谈到​他​的​两​个​兄弟，墨菲斯托​和​\"\n\"巴尔，他们​很​久​以前​被​放逐​到​这个​世界​上。我​的​主​希望​等待​时机，利用​他​令​人​敬畏​的​能\"\n\"力，以便​将​他​被​俘​的​兄弟们​从​东方​沙漠下​的​坟墓​中​解救​出来。一旦​我​主​释放​了​他​的​兄\"\n\"弟，原罪​之​战​将​再次​知道​三​人​的​愤怒。\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"向​迪亚波​罗致敬​和​献祭​-​恐惧​之​王​和​灵魂​的​毁灭者。当​我​从​睡梦​中​唤醒​我​的​主人​时，他​试\"\n\"图​拥有​一​个​凡人​的​形体。迪亚波罗​试图​夺走​李奥瑞克​国王​的​尸体，但​我​的​主人​被​囚禁​后​\"\n\"太​虚​弱​了。我​的​主人​需要​一​个​简单​和​无辜​的​锚​到​这个​世界​上，所以​发现​男孩​艾伯莱希特\"\n\"特​是​完美​的​任务。当善良​的​国王​李奥瑞克​被​迪亚波罗的​失败​激怒​时，我​绑架​了​他​的​儿子​\"\n\"艾伯莱希特，把​他​带到​我​的​主人​面​前。我​现在​等待​着​迪亚波罗的​召唤，祈祷​当​他​最终​成\"\n\"为​这​个​世界​的​主​时，我​会​得到​回报。\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"谢天谢地，你​终于​回来​了！\\n\"\n\"​我​的​朋友，你​居住​过​的​这里​发生​了​巨大​的​变化。一切​都​很​平静，直​到​黑暗​骑士​到来，摧\"\n\"毁​了​我们​的​村子。很多​没有​抵抗​的​人​直接​被​砍杀，而​那些​拿起​武器​反抗​的​人​也​被​屠杀​或\"\n\"是​被​抓​走​成为​奴隶，甚至​更​糟。城镇​边​的​教堂​已经​被​亵渎，用​作​黑暗​仪式。回荡​在​叫声​\"\n\"夜晚​不​是​人​可以​忍受​的，也许​一些​镇民​还​活​着。这​条​我​的​旅店​和​这​铁​匠铺​之间​的​路​通​向​\"\n\"教堂，去​拯救​那些​人​吧。\\n\"\n\"\\n\"\n\"​如果​你​想要​知道​更​多​事，就​再​和​我​谈谈，我​也许​能​告诉​你。祝​你​好运。\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"继续​你​的​任务。找到​丢失​的​宝藏​并不​容易。找到​一​个​藏得​不​那么​深​的​宝藏。我​把​这个​留\"\n\"给​你。不​要​让​时间​的​沙子​迷惑​了​你​的​寻找。\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"什么？！这​是​愚蠢​的。崔斯特姆​这里​没有​宝藏。让​我​看看！！啊，看​这些​画​不​准确。他\"\n\"们​根本​不​符合​我们​的​城市。我​会​把​心思放​在​大​教堂​下面，而​不​是​我们​的​表土​下面。\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"我​真的​没有​时间​讨论​你​要​找​的​地图。我​有​许多​病人​需要​我​和​你​的​帮助。\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"曾经​引​以为​傲​的​Iswall​深陷​在​这个​世界​的​表面​之下。他​的​荣誉​被​剥夺​了，面容​也​变​了。\"\n\"他​被困​在​不朽​的​折磨​之中。被​指控​隐瞒​能​让​他​自由​的​事情。\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"我​敢​打赌，怀特​看见​你​来​了，就​装​出​一​副样子，这样​他​就​可以​在​你​鼻子​埋​在​泥土​里​在​城\"\n\"里​跑​的​时候​嘲笑​你​了。我​会​忽略​它。\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"曾经​有​一​段​时间，这​个​城镇​是​远道而​来​的​旅行者​的​常去之​地。从​那​以后​发生​了​很​大​的​变\"\n\"化。但​隐藏​的​洞穴​和​埋藏​的​宝藏​是​任何​孩子​的​共同​幻想。怀特​很少​沉迷​于​年轻​人​的​游\"\n\"戏。所以​这​可​能​只​是​他​的​想象。\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"听​着。靠近点。我​不​知道​你​是否​知道​我​所​知道​的，但​你​真的​有所​收获。那​是​一​张​地图。\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"我​祖母​经常​给​我​讲​一些​关于​居住​在​教堂​外​墓地​的​奇怪​势力​的​故事。你​可能​会​对​其中​一​个​\"\n\"很​感​兴趣。她​说，如果​你​把​合适​的​祭品​留​在​墓地，进入​大​教堂​为​死者​祈祷，然后​再​回\"\n\"来，祭品​会​以​某​种​奇怪​的​方式​改变。我​不​知道​这​是​不​是​一​个​老​病妇​的​谈话，但​最近​似乎​\"\n\"什么​都​有​可能。\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"嗯。你​说​的​是​一​个​巨大​而​神秘​的​宝藏。嗯。也许​我​有​兴趣​从​你​那里​得到​一些​东西。或者​\"\n\"更​好​的​是，你​不​需要​一些​稀有​而​昂贵​的​物资​来​度过​这​场​磨难​吗？\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"所以，你​是​每​个​人​都​在​谈论​的​英雄。也许​你​能​帮助​一​个​贫穷​的​农民​摆脱​困境？在​我​的​果\"\n\"园​的​边缘，就​在​这里​的​南边，有​一​个​可怕​的​东西​从​地​里​冒​出来！我​不​能​得到​我​的​庄稼​或​\"\n\"我​的​捆干草，我​可怜​的​奶牛会​饿死。巫婆​把​这个​给​了​我，说​它​会​把​那​东西​从​我​的​地​里​炸​\"\n\"出来。如果​你​能​毁掉​它，我​将​永远​感激。我​自己​会​做​的，但​总​得​有​人​留​下来​陪奶牛……\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"我​知道​事情​不​会​像​巫婆​说​的​那么​简单。当​你​连​邻居​都​不​能​信任​的​时候，这​是​一​个​悲哀​的​\"\n\"世界。\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"它​不见​了​吗？你​把​它​送回​了​孕育​它​的​阴间​吗？你​什么？哦，别​告诉​我​你​丢​了！你​知道，\"\n\"那些​东西​不便宜。你​一定​要​找到​它，然后​把​那​恐惧​的​东西​轰​出去。\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"我​听到​爆炸声​了！多谢​你，善良​的​陌生人。随着​所有​这些​东西​从​地下​冒​出来，怪物​占领​\"\n\"了​教堂，等等，这些​都​是​艰难​的​时刻。我​只​是​一​个​贫穷​的​农民，但​在​这里​——​请​接受​我​的​\"\n\"谢意。\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"哦，我​有​这么​大​的​麻烦​…​也许​…​不，我​不​能​强加​给​你，还​有​其他​的​麻烦。也许​在​你​清除​了​\"\n\"教堂​里​的​一些​生物​之后​你​可以​回来……抽出​一点​时间​去​帮助​一​个​贫穷​的​农民？\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"哇​啊​(​嗅​）​哇​啊​(嗅嗅​）\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"我​失去​了​西奥！我​失去​了​我​最​好​的​朋友！我们​在​河​边​玩，西奥​说​他​想​去​看看​绿色​的​东\"\n\"西。我​说​我们​不​应该，但​我们​偷偷​溜​过去，然后​突然​这个​虫子​出来​了！我们​逃跑​了，但​\"\n\"西奥​摔倒​了，虫子​抓住​他，把​他​带走​了！\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"你​找到​他​了​吗？你​得​找到​西奥多，求​你​了！他​只​是​个​小​孩子。他​不​能​照顾​自己！求​你​\"\n\"了！\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"你​找到​他​了！你​找到​他​了！非常​感谢。哦，西奥，那些​讨厌​的​虫子吓到​你​了​吗？嘿​啊！\"\n\"有​东西粘​在​你​的​毛上​了！哎呀！来​吧，西奥，我们​回家​吧！再次​感谢你，英雄​！\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"我们​早​已​沉睡，觉醒​的​时刻​已经​到来。长眠​之后，我们​感到​非常​饥饿。很​快，现在，我\"\n\"们​将​喂养……\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"你​玩​得​开心​吗，小​哺​乳​动物？真​可怜。你​的​小​世界​不​会​是​什么​挑战。\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"这些​地必​被​玷污，我们​的​后裔​必漫​过​人们​称为​家​的​田地。我们​的​卷须​要​包裹​这​世界，我\"\n\"们​要​以​其​居民​的​肉为食。人类​将​成为​我们​的​动产​和​食物。\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"啊，我​能​闻到​你​…​你​就​在​附近！接近！血​和​恐惧​的​味道​…​多么​诱​人……\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"在​金光​之​年，一​座​大​教堂​被​立​了​起来。这个​圣地​的​基石​是​用半​透明​的​安提拉​石​雕刻​而​成​\"\n\"的，安提拉石​是​以​与​赫拉迪姆​分享​力量​的​天使​命名​的。\\n\"\n\" \\n\"\n\"​在​画影子​的​那​一​年，大​地​震动，大​教堂​粉碎​倒塌。随着​地下​墓穴​和​城堡​的​建造​开始，人\"\n\"们​开始​抵抗​原罪之战​的​蹂躏，废墟​被​清理​出来​寻找​石头。就​这样，基石​从​人们​的​眼​中​消\"\n\"失​了。\\n\"\n\" \\n\"\n\"​石头​属于​这个​世界，也​属于​所有​的​世界，就​像​光​既​存在​于​万物​之​中，也​存在​于​万物​之\"\n\"外。光明​与​统一​是​这​个​神圣​基础​的​产物，是​目的​的​统一​和​占有​的​统一。\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"哞。\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"我​说​了，哞。\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"听​着，我​只​是​一​头​牛，好​吗？\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"好​吧，好​吧。我​不​是​一​头​牛。我​一般​不​会​这样​到处​走​；​但是，当时​我​正​坐​在​家​里​处理​自\"\n\"己​的​事情，突然​这些​虫​子、藤蔓、球茎​之类​的​东西​开始​从​地板​上​冒​出来……太​可怕​了！如\"\n\"果​我​有​正常​的​衣服​穿，就​不​会​那么​糟糕​了。嘿​你​能回​我​家​帮​我​拿​衣服​吗？棕色​的，不​是​\"\n\"灰色​的，那​是​晚装​的。我​会​自己​做​的，但​我​不​想​让​任何​人​看到​我​这样。给，拿​着​这个，\"\n\"你​可能​需要​它……杀死​那些​长满​一切​的​东西。你​不​会​错过​我​家​的，就​在​河​的​岔口​南​边……你​\"\n\"知道​的……有​杂草​丛生​的​菜园​的​那​个。\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"你​在​浪费​时间​干​什么？去​拿​我​的​衣服！快点！那边​那​个​荷斯坦人​一直​对​我​眨眼！\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"嘿，你​有​我​的​西装​吗？快，传​过来！这些​耳朵​痒​得​你​都​不​敢​相信！\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"不​不​不！这​是​我​的​灰色​西装！这​是​晚装！正式​场合！我​不​能​穿​这个。你​是​什么​怪人？我​\"\n\"需要​那​套​棕色​的​西装。\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"啊，好多​了。呼！终于​有​尊严​了！我​的​鹿角​是​直​的​吗？很​好。听​着，非常​感谢​你​帮​我。\"\n\"来，把​这个​当作​礼物​；​而且，你​知道……一点​时尚​提示……你​可以​用​一点……你​可以​用​一​个​新​\"\n\"的……你​知道​什么​时候？整个​冒险家​的​主题​就​是……复古​的。只​是​一​句​忠告，嗯？再见。\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"你​看。我​是​一​头​牛。而​你，你​是​怪物诱饵。在​你​的​腰带​下​获得​一些​经验！我们​谈​谈……\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"这​一定​是​我​摆​在​你​面前​的​一​项​可怕​的​任务。如果​有​什么​办法​我​可以……喝​一​大杯​新鲜​的​牛\"\n\"奶​好​吗？\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"哦，我​需要​你​的​帮助，但​也许​在​你​从​那些​野兽​的​亵渎​中​拯救​了​地下​墓穴​之后。\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"我​需要​做​点​什么，但​我​不​能​强加​给​一​个​完全​陌生​的​人。也许​在​你​来​了​一​段​时间​之后，我​\"\n\"会​更​乐意​请​你​帮​个​忙。\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"我​从​你​身​上​看到​了​伟大​的​潜力。也许​某​个​时候​你​正在​完成​你​的​命运，你​可以​停​下来​帮​我​\"\n\"一​个​小​忙？\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"我​想​你​也许​可以​帮​我，但​也许​在​你​变得​更​有​力量​之后。我​可​不​想​破坏​村子​里​摧毁​教堂​威\"\n\"胁​的​唯一​机会！\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"我，我​是​一​头​白手​起家​的​母牛。做点​自己，然后……那​我们​谈​谈。\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"我​不​必​向​每​一​个​路​过​的​游客​解释​我​自己！你​不​是​有​怪物​要​杀​吗？也许​我们​以后​再​谈。如\"\n\"果​你​活​着……\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"别烦​我​了。我​在​找​一​个​真正​的​英雄。但​你​不是。我​不​能​相信​你，你​随时​都​会​被​怪物​吃掉​\"\n\"的……我​需要​一​个​有​经验​的​英雄。\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"好​吧，我​来​切​公牛。我​不​是​故意​误导​你​的。我​坐​在​家​里，心情​很​不​好，这时​情况​变得​很​\"\n\"不​稳定​；​一​大​群​怪物​从​地板​上​跑​了​出来！我​只​是​吓​了​一​跳。我​跑出​家门​的​时候​正好​穿​着​\"\n\"这​件​球衣，现在​我​看​起来​很​可笑。如果​我​有​正常​的​衣服​穿，就​不​会​那么​糟糕​了。嘿​你​能\"\n\"回​我​家​帮​我​拿​衣服​吗？棕色​的，不​是​灰色​的，那​是​晚装​的。我​会​自己​做​的，但​我​不​想​让​\"\n\"任何​人​看到​我​这样。给，拿​着​这个，你​可能​需要​它……杀死​那些​长满​一切​的​东西。你​不​会​\"\n\"错过​我​家​的，就​在​河​的​岔口​南​边……你​知道​的……有​杂草​丛生​的​菜园​的​那​个。\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"我​试​过​法术，威胁，放弃​和​这个​肮脏​的​生物​讨价​还价​——​都​没有用。我​奴役​小​恶魔​的​方法​\"\n\"似乎​对​这​个​可怕​的​野兽​没有​效果。\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"我​的​家正​慢慢​被​这个​不​受​欢迎​的​囚犯​的​卑鄙​行径​所​腐蚀。地窖​里​到处​都​是​影子，它们​就​\"\n\"在​我​视线​的​角落​之外。我​耳边​隐约​传来​爪子​的​拼字声。我​想，他们​在​找​这​本​杂志。\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"在​咆哮​中，这​个​生物​漏​了​自己​的​名字​——​纳克鲁尔。我​曾​试图​研究​这个​名字，但​小​恶魔​不​\"\n\"知​何​故毁​了​我​的​图书馆。纳克鲁尔……我​对​这个​名字​充满​了​恐惧。我​宁愿​把​它​当作​一​种​生\"\n\"物，而​不​愿​考虑​它​的​真名。\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"那​被​困住​的​生物​狂怒​的​嚎叫​使​我​无法​获得​急​需​的​睡眠。它​向​那​把​它​送到​虚空​的​人​发怒，\"\n\"因​我​把​它​困​在​这里，就​咒诅​我。它​的​话语​使​我​的​心​充满​恐惧，然而​我​无法​阻挡​它​的​声\"\n\"音。\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"我​的​时间​快​用完​了。我​必须​记录​下​削弱​恶魔​的​方法，然后​隐藏​这​段​文字，以免​他​的​爪牙\"\n\"们​想​办法​利用​我​的​知识​来​解放​他们​的​主。我​希望​找到​这​本​日记​的​人​都​能​找到​知识。\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"无论​谁​找到​这​卷​卷轴，都​将​负责​阻止​这些​墙内​的​恶魔​生物。我​的​时间​到​了。即使​是​现\"\n\"在，它​的​地狱​般​的​爪子​在​脆弱​的​门，我​躲​在​后面​爪。\\n\"\n\" \\n\"\n\"​我​已经​用​神秘​的​魔法​把​恶魔​束​缚​住，把​它​包裹​在​长城​里，但​我​担心​这​还​不​够。\\n\"\n\" \\n\"\n\"​在​我​的​三​个​幽灵​身​上​找到​的​法术​将​为​你​提供​进入​他​的​领地​的​保护，但​前提​是​必须​按​正确​\"\n\"的​顺序​施放。入口​的​杠杆​会​移除​障碍物，释放​恶魔​；​别碰​他们！只​使用​这些​法术​进入，\"\n\"否则​他​的​力量​可能​太​大，你​无法​击败。\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"In Spiritu Sanctum.\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"Praedictum Otium.\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"Efficio Obitus Ut Inimicus.\"\n\n#: Source/translation_dummy.cpp:979\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"地狱猪\"\n\n#: Source/translation_dummy.cpp:980\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"钉​刺者\"\n\n#: Source/translation_dummy.cpp:981\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"癫​狂​球体\"\n\n#: Source/translation_dummy.cpp:982\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"蛛​网​魔\"\n\n#: Source/translation_dummy.cpp:983\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"孪​生者\"\n\n#: Source/translation_dummy.cpp:984\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"腐尸​诞生者\"\n\n#: Source/translation_dummy.cpp:985\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"毒尾\"\n\n#: Source/translation_dummy.cpp:986\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"死​尸\"\n\n#: Source/translation_dummy.cpp:987\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"蜘蛛​领主\"\n\n#: Source/translation_dummy.cpp:988\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"鞭状蠕​虫\"\n\n#: Source/translation_dummy.cpp:989\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"火​蚂蚁\"\n\n#: Source/translation_dummy.cpp:990\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"地​狱恶​虫\"\n\n#: Source/translation_dummy.cpp:991\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"掘​墓者\"\n\n#: Source/translation_dummy.cpp:992\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"墓穴​蝙蝠\"\n\n#: Source/translation_dummy.cpp:993\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"火焰​蝙\"\n\n#: Source/translation_dummy.cpp:994\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"头骨​之翼\"\n\n#: Source/translation_dummy.cpp:995\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"巫妖\"\n\n#: Source/translation_dummy.cpp:996\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"地​穴恶魔\"\n\n#: Source/translation_dummy.cpp:997\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"地狱蝙​蝠\"\n\n#: Source/translation_dummy.cpp:998\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"白​骨恶魔\"\n\n#: Source/translation_dummy.cpp:999\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"高​阶​巫妖\"\n\n#: Source/translation_dummy.cpp:1000\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"双​钩\"\n\n#: Source/translation_dummy.cpp:1001\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"血​肉​造物\"\n\n#: Source/translation_dummy.cpp:1002\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"收割者\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"巨人​的​指节\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"水​银戒指\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"索​克林​之​戒\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"卡里克​之戒\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"熔岩​指环\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"神秘​指环\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"雷电​指环\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"闪避​护符\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"虫​咬\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"烛​台\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"阴​沉护​甲\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"闪​电​迅捷\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"霹​雳\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"白池\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"灵魂​吞噬者\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"钻石利刃\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"骨链​甲\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"恶​魔板​甲\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"侍​从​护符\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"角​斗士​戒指\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"愚弄​法术​的\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"晶状\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"双​生​的\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"毁灭\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"衰退\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"危险\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"法力\"\n\n#: Source/translation_dummy.cpp:1030\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"大​法师​之​力\"\n\n#: Source/translation_dummy.cpp:1031\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"小丑​的​愚弄\"\n\n#: Source/translation_dummy.cpp:1032\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"闪电墙\"\n\n#: Source/translation_dummy.cpp:1033\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"献祭\"\n\n#: Source/translation_dummy.cpp:1034\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"逃脱术\"\n\n#: Source/translation_dummy.cpp:1035\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"反射\"\n\n#: Source/translation_dummy.cpp:1036\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"狂​战士\"\n\n#: Source/translation_dummy.cpp:1037\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"火焰​环\"\n\n#: Source/translation_dummy.cpp:1038\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"搜索\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"火焰​符文\"\n\n#: Source/translation_dummy.cpp:1040\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"闪电符文\"\n\n#: Source/translation_dummy.cpp:1041\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"新​星符文\"\n\n#: Source/translation_dummy.cpp:1042\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"献祭​符文\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"符文石\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \",\"\n\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"减少​伽马\"\n\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"增加​伽马\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"在​城里​重新​开始\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"尝试​扔​掉​一些​物品​?\"\n\n#~ msgid \"\"\n#~ \"Forces waiting for Vertical Sync. Prevents tearing effect when drawing a \"\n#~ \"frame. Disabling it can help with mouse lag on some systems.\"\n#~ msgstr \"\"\n#~ \"强制​等待​垂直​同步。防止​因​绘制帧​时​导致​的​撕裂​效果。关闭​该​项​有助于​在​某些​系统​上​\"\n#~ \"减少​鼠标​延迟。\"\n\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"FPS​限制\"\n\n#~ msgid \"FPS is limited to avoid high CPU load. Limit considers refresh rate.\"\n#~ msgstr \"限制​帧数​以​防止​CPU​的​过​多​占用。推荐​使用​屏幕刷新率。\"\n\n#~ msgid \"To hit\"\n#~ msgstr \"命​中\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"心脏\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"选​项:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"版本​{:s}\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"城镇​中​没有​自动​地图\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"恢复​生命​值\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"治疗​致命​伤\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"降低​力量\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"降低​敏捷\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"降低​活力\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"你​无法治​愈\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"命​中​怪物​无法​自愈\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"更​快​的​挥动\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"夜视​能力\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"无法​加载​玩​家​数据​进行​写入。\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"因​无法​读取，无法​保存​存档\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"因​无法​写入，无法​保存​存档\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"坚​不​可摧​,  \"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"无​需​属性\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"在​英雄​走廊​的​另​一​端​藏匿​着​白骨密室。任何​胆​敢​盗取​此​地​财宝​的​人，都​将​遭受​永恒​的​\"\n#~ \"死亡。恐惧​之​王​如是​说，本​书​也​如实​写。\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"地狱​的​军械库​如同​鲜血​战神​的​私宅。其​所​到​之​处，无​不​留下​成千上万​的​残肢断臂。无\"\n#~ \"论​是​天使​还是​人类​都​将​遭到​残杀，只​为了​能够​呈上​邪魔们​最​渴望​的​东西​——​鲜血。\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"今天​多云​凉爽。将​亡灵​之​网​撒向​虚空，降落​了​两​个​新​的​飞行​恐惧​亚种​；​一​天​的​好​工\"\n#~ \"作。一定​要​记得​从​艾德莉亚​订购​更​多​的​蝙蝠​粪​和​黑​蜡烛​；​我​的​血压​有点​低。\"\n"
  },
  {
    "path": "Translations/zh_TW.po",
    "content": "# Translation of DevilutionX to Chinese (Traditional)\n# Aaron Sun <AaronSun.Test@gmail.com>, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\n\"\n\"POT-Creation-Date: 2025-10-02 15:21+0200\\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Aaron Sun <AaronSun.Test@gmail.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: zh_TW\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-KeywordsList: _;N_;P_:1c,2\\n\"\n\"X-Poedit-Basepath: ..\\n\"\n\"X-Poedit-SearchPath-0: Source\\n\"\n\n#: Source/DiabloUI/credits_lines.cpp:9\nmsgid \"Game Design\"\nmsgstr \"遊​戲設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:12\nmsgid \"Senior Designers\"\nmsgstr \"資​深​設計​師\"\n\n#: Source/DiabloUI/credits_lines.cpp:15 Source/DiabloUI/credits_lines.cpp:234\nmsgid \"Additional Design\"\nmsgstr \"附加​設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:18 Source/DiabloUI/credits_lines.cpp:217\nmsgid \"Lead Programmer\"\nmsgstr \"首席​程式​設計師\"\n\n#: Source/DiabloUI/credits_lines.cpp:21\nmsgid \"Senior Programmers\"\nmsgstr \"資​深​程式​設計師\"\n\n#: Source/DiabloUI/credits_lines.cpp:25\nmsgid \"Programming\"\nmsgstr \"程式​設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:28\nmsgid \"Special Guest Programmers\"\nmsgstr \"特約​程式​設計師\"\n\n#: Source/DiabloUI/credits_lines.cpp:31\nmsgid \"Battle.net Programming\"\nmsgstr \"Battle.net​程式​設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:34\nmsgid \"Serial Communications Programming\"\nmsgstr \"序​列通訊​程式​設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:37\nmsgid \"Installer Programming\"\nmsgstr \"安裝​程式​程式​設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:40\nmsgid \"Art Directors\"\nmsgstr \"美​術總監\"\n\n#: Source/DiabloUI/credits_lines.cpp:43\nmsgid \"Artwork\"\nmsgstr \"美​術設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:50\nmsgid \"Technical Artwork\"\nmsgstr \"技​術​美術設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:54\nmsgid \"Cinematic Art Directors\"\nmsgstr \"影片​美術總監\"\n\n#: Source/DiabloUI/credits_lines.cpp:57\nmsgid \"3D Cinematic Artwork\"\nmsgstr \"3D​影片​美術設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:63\nmsgid \"Cinematic Technical Artwork\"\nmsgstr \"影片​技術​美術設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:66\nmsgid \"Executive Producer\"\nmsgstr \"執​行製​作人\"\n\n#: Source/DiabloUI/credits_lines.cpp:69\nmsgid \"Producer\"\nmsgstr \"製​作人\"\n\n#: Source/DiabloUI/credits_lines.cpp:72\nmsgid \"Associate Producer\"\nmsgstr \"助理​製作人\"\n\n#. TRANSLATORS: Keep Strike Team as Name\n#: Source/DiabloUI/credits_lines.cpp:75\nmsgid \"Diablo Strike Team\"\nmsgstr \"暗​黑破壞​神突擊​小​組\"\n\n#: Source/DiabloUI/credits_lines.cpp:79 Source/gamemenu.cpp:79\nmsgid \"Music\"\nmsgstr \"音​樂\"\n\n#: Source/DiabloUI/credits_lines.cpp:82\nmsgid \"Sound Design\"\nmsgstr \"音效​設​計\"\n\n#: Source/DiabloUI/credits_lines.cpp:85\nmsgid \"Cinematic Music & Sound\"\nmsgstr \"影片​音樂​和​音效\"\n\n#: Source/DiabloUI/credits_lines.cpp:88\nmsgid \"Voice Production, Direction & Casting\"\nmsgstr \"語音​製作、導演​和​配音\"\n\n#: Source/DiabloUI/credits_lines.cpp:91\nmsgid \"Script & Story\"\nmsgstr \"劇​本​和​故事\"\n\n#: Source/DiabloUI/credits_lines.cpp:95\nmsgid \"Voice Editing\"\nmsgstr \"語音編輯\"\n\n#: Source/DiabloUI/credits_lines.cpp:98 Source/DiabloUI/credits_lines.cpp:252\nmsgid \"Voices\"\nmsgstr \"語​音\"\n\n#: Source/DiabloUI/credits_lines.cpp:103\nmsgid \"Recording Engineer\"\nmsgstr \"錄音師\"\n\n#: Source/DiabloUI/credits_lines.cpp:106\nmsgid \"Manual Design & Layout\"\nmsgstr \"使用​手冊設計​和​編排\"\n\n#: Source/DiabloUI/credits_lines.cpp:110\nmsgid \"Manual Artwork\"\nmsgstr \"使用​手冊​美術設計\"\n\n#: Source/DiabloUI/credits_lines.cpp:114\nmsgid \"Provisional Director of QA (Lead Tester)\"\nmsgstr \"短期​品保總監​（​測試​主管​）\"\n\n#: Source/DiabloUI/credits_lines.cpp:117\nmsgid \"QA Assault Team (Testers)\"\nmsgstr \"品​保突擊​小​組​（​測試人員​）\"\n\n#: Source/DiabloUI/credits_lines.cpp:122\nmsgid \"QA Special Ops Team (Compatibility Testers)\"\nmsgstr \"品​保特​別行動​小組​（​相容性測試人員​）\"\n\n#: Source/DiabloUI/credits_lines.cpp:125\nmsgid \"QA Artillery Support (Additional Testers) \"\nmsgstr \"品​保​火力​支援​小組​（​附加​測試人員​）\"\n\n#: Source/DiabloUI/credits_lines.cpp:129\nmsgid \"QA Counterintelligence\"\nmsgstr \"品​保​反情​小​組\"\n\n#. TRANSLATORS: A group of people\n#: Source/DiabloUI/credits_lines.cpp:132\nmsgid \"Order of Network Information Services\"\nmsgstr \"NIS系統​維護​管理\"\n\n#: Source/DiabloUI/credits_lines.cpp:136\nmsgid \"Customer Support\"\nmsgstr \"客​服人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:141\nmsgid \"Sales\"\nmsgstr \"銷​售人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:144\nmsgid \"Dunsel\"\nmsgstr \"Dunsel\"\n\n#: Source/DiabloUI/credits_lines.cpp:147\nmsgid \"Mr. Dabiri's Background Vocalists\"\nmsgstr \"Dabiri​先生​的​和​聲\"\n\n#: Source/DiabloUI/credits_lines.cpp:151\nmsgid \"Public Relations\"\nmsgstr \"公關人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:154\nmsgid \"Marketing\"\nmsgstr \"行​銷人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:157\nmsgid \"International Sales\"\nmsgstr \"國​際​銷​售人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:160\nmsgid \"U.S. Sales\"\nmsgstr \"美​國​銷​售人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:163\nmsgid \"Manufacturing\"\nmsgstr \"製​造商\"\n\n#: Source/DiabloUI/credits_lines.cpp:166\nmsgid \"Legal & Business\"\nmsgstr \"法律​和​商業\"\n\n#: Source/DiabloUI/credits_lines.cpp:169\nmsgid \"Special Thanks To\"\nmsgstr \"特別感謝\"\n\n#: Source/DiabloUI/credits_lines.cpp:173\nmsgid \"Thanks To\"\nmsgstr \"感謝\"\n\n#: Source/DiabloUI/credits_lines.cpp:202\nmsgid \"In memory of\"\nmsgstr \"以​玆紀​念\"\n\n#: Source/DiabloUI/credits_lines.cpp:208\nmsgid \"Very Special Thanks to\"\nmsgstr \"非常​特別感謝\"\n\n#: Source/DiabloUI/credits_lines.cpp:214\nmsgid \"General Manager\"\nmsgstr \"總​經理\"\n\n#: Source/DiabloUI/credits_lines.cpp:220\nmsgid \"Software Engineering\"\nmsgstr \"軟​體​工程\"\n\n#: Source/DiabloUI/credits_lines.cpp:223\nmsgid \"Art Director\"\nmsgstr \"美​術總監\"\n\n#: Source/DiabloUI/credits_lines.cpp:226\nmsgid \"Artists\"\nmsgstr \"美​術\"\n\n#: Source/DiabloUI/credits_lines.cpp:230\nmsgid \"Design\"\nmsgstr \"設​計\"\n\n#: Source/DiabloUI/credits_lines.cpp:237\nmsgid \"Sound Design, SFX & Audio Engineering\"\nmsgstr \"音效​設計、混音​和​音訊​工程\"\n\n#: Source/DiabloUI/credits_lines.cpp:240\nmsgid \"Quality Assurance Lead\"\nmsgstr \"品​保​主管\"\n\n#: Source/DiabloUI/credits_lines.cpp:243\nmsgid \"Testers\"\nmsgstr \"測​試人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:248\nmsgid \"Manual\"\nmsgstr \"使用​手冊\"\n\n#: Source/DiabloUI/credits_lines.cpp:257\nmsgid \"\\tAdditional Work\"\nmsgstr \"\\t​附加​工作\"\n\n#: Source/DiabloUI/credits_lines.cpp:259\nmsgid \"Quest Text Writing\"\nmsgstr \"任務​文字​撰寫\"\n\n#: Source/DiabloUI/credits_lines.cpp:262 Source/DiabloUI/credits_lines.cpp:297\nmsgid \"Thanks to\"\nmsgstr \"感謝\"\n\n#: Source/DiabloUI/credits_lines.cpp:267\nmsgid \"\\t\\t\\tSpecial Thanks to Blizzard Entertainment\"\nmsgstr \"\\t\\t\\t​特別感謝​暴雪娛樂\"\n\n#: Source/DiabloUI/credits_lines.cpp:272\nmsgid \"\\t\\t\\tSierra On-Line Inc. Northwest\"\nmsgstr \"\\t\\t\\t雪樂山線​上\"\n\n#: Source/DiabloUI/credits_lines.cpp:274\nmsgid \"Quality Assurance Manager\"\nmsgstr \"品​保經理\"\n\n#: Source/DiabloUI/credits_lines.cpp:277\nmsgid \"Quality Assurance Lead Tester\"\nmsgstr \"品​保測試​主管\"\n\n#: Source/DiabloUI/credits_lines.cpp:280\nmsgid \"Main Testers\"\nmsgstr \"主要​測試人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:283\nmsgid \"Additional Testers\"\nmsgstr \"附加​測試人​員\"\n\n#: Source/DiabloUI/credits_lines.cpp:288\nmsgid \"Product Marketing Manager\"\nmsgstr \"產​品行​銷​經理\"\n\n#: Source/DiabloUI/credits_lines.cpp:291\nmsgid \"Public Relations Manager\"\nmsgstr \"公關​經理\"\n\n#: Source/DiabloUI/credits_lines.cpp:294\nmsgid \"Associate Product Manager\"\nmsgstr \"助理​產品​經理\"\n\n#: Source/DiabloUI/credits_lines.cpp:303\nmsgid \"The Ring of One Thousand\"\nmsgstr \"最初​的​一千​名​Beta測試人員​（​The Ring of One Thousand​）\"\n\n#: Source/DiabloUI/credits_lines.cpp:549\nmsgid \"\\tNo souls were sold in the making of this game.\"\nmsgstr \"\\t​在​這個​遊戲​的​製作​過程​中​沒​有​任何​靈魂​被​出賣。\"\n\n#: Source/DiabloUI/dialogs.cpp:97 Source/DiabloUI/dialogs.cpp:109\n#: Source/DiabloUI/hero/selhero.cpp:199 Source/DiabloUI/hero/selhero.cpp:225\n#: Source/DiabloUI/hero/selhero.cpp:310 Source/DiabloUI/hero/selhero.cpp:550\n#: Source/DiabloUI/multi/selconn.cpp:94 Source/DiabloUI/multi/selgame.cpp:187\n#: Source/DiabloUI/multi/selgame.cpp:350 Source/DiabloUI/multi/selgame.cpp:376\n#: Source/DiabloUI/multi/selgame.cpp:518 Source/DiabloUI/multi/selgame.cpp:595\n#: Source/DiabloUI/selok.cpp:82\nmsgid \"OK\"\nmsgstr \"好\"\n\n#: Source/DiabloUI/hero/selhero.cpp:168\nmsgid \"Choose Class\"\nmsgstr \"選​擇職業\"\n\n#: Source/DiabloUI/hero/selhero.cpp:202 Source/DiabloUI/hero/selhero.cpp:228\n#: Source/DiabloUI/hero/selhero.cpp:313 Source/DiabloUI/hero/selhero.cpp:558\n#: Source/DiabloUI/multi/selconn.cpp:97 Source/DiabloUI/progress.cpp:50\nmsgid \"Cancel\"\nmsgstr \"取消\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Multi Player Hero\"\nmsgstr \"新​的​多​人​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:208 Source/DiabloUI/hero/selhero.cpp:298\nmsgid \"New Single Player Hero\"\nmsgstr \"新​單人​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:217\nmsgid \"Save File Exists\"\nmsgstr \"儲​存檔案​已​存在\"\n\n#: Source/DiabloUI/hero/selhero.cpp:220 Source/gamemenu.cpp:50\nmsgid \"Load Game\"\nmsgstr \"載入​遊戲\"\n\n#: Source/DiabloUI/hero/selhero.cpp:221 Source/multi.cpp:835\nmsgid \"New Game\"\nmsgstr \"新​遊戲\"\n\n#: Source/DiabloUI/hero/selhero.cpp:231 Source/DiabloUI/hero/selhero.cpp:564\nmsgid \"Single Player Characters\"\nmsgstr \"單​人​角色\"\n\n#: Source/DiabloUI/hero/selhero.cpp:290\nmsgid \"\"\n\"The Rogue and Sorcerer are only available in the full retail version of \"\n\"Diablo. Visit https://www.gog.com/game/diablo to purchase.\"\nmsgstr \"\"\n\"流亡者​和​巫師​只​在​暗​黑破​壞神​的​完整​零售版​中​提供。前往 https://www.gog.com/game/\"\n\"diablo 購買。\"\n\n#: Source/DiabloUI/hero/selhero.cpp:304 Source/DiabloUI/hero/selhero.cpp:307\nmsgid \"Enter Name\"\nmsgstr \"輸​入名稱\"\n\n#: Source/DiabloUI/hero/selhero.cpp:336\nmsgid \"\"\n\"Invalid name. A name cannot contain spaces, reserved characters, or reserved \"\n\"words.\\n\"\nmsgstr \"名稱​無效。名稱​不​能​包含​空格、保留​字元​或​保留​字。\\n\"\n\n#. TRANSLATORS: Error Message\n#: Source/DiabloUI/hero/selhero.cpp:343\nmsgid \"Unable to create character.\"\nmsgstr \"無​法​建立​角色。\"\n\n#: Source/DiabloUI/hero/selhero.cpp:509\nmsgid \"Level:\"\nmsgstr \"等​級: \"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Strength:\"\nmsgstr \"強度: \"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Magic:\"\nmsgstr \"魔術: \"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Dexterity:\"\nmsgstr \"敏​捷: \"\n\n#: Source/DiabloUI/hero/selhero.cpp:513\nmsgid \"Vitality:\"\nmsgstr \"活力: \"\n\n#: Source/DiabloUI/hero/selhero.cpp:515\n#, fuzzy\n#| msgid \"Save Game\"\nmsgid \"Savegame:\"\nmsgstr \"儲​存遊​戲\"\n\n#: Source/DiabloUI/hero/selhero.cpp:534\nmsgid \"Select Hero\"\nmsgstr \"選​擇​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:542\nmsgid \"New Hero\"\nmsgstr \"新​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:553\nmsgid \"Delete\"\nmsgstr \"刪​除\"\n\n#: Source/DiabloUI/hero/selhero.cpp:562\nmsgid \"Multi Player Characters\"\nmsgstr \"多​人​遊戲​角色\"\n\n#: Source/DiabloUI/hero/selhero.cpp:613\nmsgid \"Delete Multi Player Hero\"\nmsgstr \"刪​除​多​人​遊戲​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:615\nmsgid \"Delete Single Player Hero\"\nmsgstr \"刪​除​單人​遊戲​英雄\"\n\n#: Source/DiabloUI/hero/selhero.cpp:617\n#, c++-format\nmsgid \"Are you sure you want to delete the character \\\"{:s}\\\"?\"\nmsgstr \"是否​確實​要​刪除​角色​「​{:s}​」？\"\n\n#: Source/DiabloUI/mainmenu.cpp:48\nmsgid \"Single Player\"\nmsgstr \"單​人\"\n\n#: Source/DiabloUI/mainmenu.cpp:49\nmsgid \"Multi Player\"\nmsgstr \"多​人\"\n\n#: Source/DiabloUI/mainmenu.cpp:50 Source/DiabloUI/settingsmenu.cpp:384\n#, fuzzy\n#| msgid \"Stinger\"\nmsgid \"Settings\"\nmsgstr \"釘​刺者\"\n\n#: Source/DiabloUI/mainmenu.cpp:51\nmsgid \"Support\"\nmsgstr \"支援\"\n\n#: Source/DiabloUI/mainmenu.cpp:52\nmsgid \"Show Credits\"\nmsgstr \"顯示製​作​組\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Hellfire\"\nmsgstr \"退出​地​獄火\"\n\n#: Source/DiabloUI/mainmenu.cpp:54\nmsgid \"Exit Diablo\"\nmsgstr \"退出​暗​黑破壞神\"\n\n#: Source/DiabloUI/mainmenu.cpp:71\n#, fuzzy\n#| msgid \"in the shareware\"\nmsgid \"Shareware\"\nmsgstr \"在​共​享軟​體​中\"\n\n#: Source/DiabloUI/multi/selconn.cpp:26\nmsgid \"Client-Server (TCP)\"\nmsgstr \"客​戶端伺服器​（​TCP​）\"\n\n#: Source/DiabloUI/multi/selconn.cpp:27\n#, fuzzy\nmsgid \"Offline\"\nmsgstr \"環​回\"\n\n#: Source/DiabloUI/multi/selconn.cpp:68 Source/DiabloUI/multi/selgame.cpp:662\n#: Source/DiabloUI/multi/selgame.cpp:688\nmsgid \"Multi Player Game\"\nmsgstr \"多​人​遊戲\"\n\n#: Source/DiabloUI/multi/selconn.cpp:74\nmsgid \"Requirements:\"\nmsgstr \"要求: \"\n\n#: Source/DiabloUI/multi/selconn.cpp:80\nmsgid \"no gateway needed\"\nmsgstr \"不​需要​閘道器\"\n\n#: Source/DiabloUI/multi/selconn.cpp:86\nmsgid \"Select Connection\"\nmsgstr \"選​擇連線\"\n\n#: Source/DiabloUI/multi/selconn.cpp:89\nmsgid \"Change Gateway\"\nmsgstr \"更改​閘​道器\"\n\n#: Source/DiabloUI/multi/selconn.cpp:122\nmsgid \"All computers must be connected to a TCP-compatible network.\"\nmsgstr \"所有​計算​機​必須連線​到​與​TCP​相容​的​網路。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:126\nmsgid \"All computers must be connected to the internet.\"\nmsgstr \"所有​計算機​都​必須​連線​到​因特網。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:130\nmsgid \"Play by yourself with no network exposure.\"\nmsgstr \"自己​玩，沒​有​網路​曝光。\"\n\n#: Source/DiabloUI/multi/selconn.cpp:135\n#, c++-format\nmsgid \"Players Supported: {:d}\"\nmsgstr \"支援​的​玩家: {:d}\"\n\n#: Source/DiabloUI/multi/selgame.cpp:100 Source/options.cpp:425\n#: Source/options.cpp:473 Source/translation_dummy.cpp:630\n#, fuzzy\n#| msgid \"Exit Diablo\"\nmsgid \"Diablo\"\nmsgstr \"退出​暗​黑破壞神\"\n\n#: Source/DiabloUI/multi/selgame.cpp:103\n#, fuzzy\n#| msgid \"in the shareware\"\nmsgid \"Diablo Shareware\"\nmsgstr \"在​共​享軟​體​中\"\n\n#: Source/DiabloUI/multi/selgame.cpp:106 Source/options.cpp:427\n#: Source/options.cpp:487\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Hellfire\"\nmsgstr \"退出​地​獄火\"\n\n#: Source/DiabloUI/multi/selgame.cpp:109\n#, fuzzy\n#| msgid \"in the shareware\"\nmsgid \"Hellfire Shareware\"\nmsgstr \"在​共​享軟​體​中\"\n\n#: Source/DiabloUI/multi/selgame.cpp:112\nmsgid \"The host is running a different game than you.\"\nmsgstr \"主機​執行​的​遊戲與​您​不同。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:114\n#, fuzzy, c++-format\n#| msgid \"The host is running a different game than you.\"\nmsgid \"The host is running a different game mode ({:s}) than you.\"\nmsgstr \"主機​執行​的​遊戲與​您​不同。\"\n\n#. TRANSLATORS: Error message when somebody tries to join a game running another version.\n#: Source/DiabloUI/multi/selgame.cpp:116\n#, c++-format\nmsgid \"Your version {:s} does not match the host {:d}.{:d}.{:d}.\"\nmsgstr \"您​的​版本​{:s}​與​主機{:d}.{:d}.{:d}​不​匹配。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:153 Source/DiabloUI/multi/selgame.cpp:581\nmsgid \"Description:\"\nmsgstr \"說​明: \"\n\n#: Source/DiabloUI/multi/selgame.cpp:159\nmsgid \"Select Action\"\nmsgstr \"選​擇​操作\"\n\n#: Source/DiabloUI/multi/selgame.cpp:162 Source/DiabloUI/multi/selgame.cpp:338\n#: Source/DiabloUI/multi/selgame.cpp:499\nmsgid \"Create Game\"\nmsgstr \"建立​遊戲\"\n\n#: Source/DiabloUI/multi/selgame.cpp:164\n#, fuzzy\n#| msgid \"Create Game\"\nmsgid \"Create Public Game\"\nmsgstr \"建立​遊戲\"\n\n#: Source/DiabloUI/multi/selgame.cpp:165\nmsgid \"Join Game\"\nmsgstr \"加入​遊戲\"\n\n#: Source/DiabloUI/multi/selgame.cpp:169\n#, fuzzy\n#| msgid \"Quit Game\"\nmsgid \"Public Games\"\nmsgstr \"退出​遊戲\"\n\n#: Source/DiabloUI/multi/selgame.cpp:174 Source/diablo_msg.cpp:72\nmsgid \"Loading...\"\nmsgstr \"載入。。。\"\n\n#. TRANSLATORS: type of dungeon (i.e. Cathedral, Caves)\n#: Source/DiabloUI/multi/selgame.cpp:176 Source/discord/discord.cpp:86\n#: Source/options.cpp:459 Source/options.cpp:730\n#: Source/panels/charpanel.cpp:142\nmsgid \"None\"\nmsgstr \"沒​有​一​個\"\n\n#: Source/DiabloUI/multi/selgame.cpp:190 Source/DiabloUI/multi/selgame.cpp:353\n#: Source/DiabloUI/multi/selgame.cpp:379 Source/DiabloUI/multi/selgame.cpp:521\n#: Source/DiabloUI/multi/selgame.cpp:598\nmsgid \"CANCEL\"\nmsgstr \"取消\"\n\n#: Source/DiabloUI/multi/selgame.cpp:229\nmsgid \"Create a new game with a difficulty setting of your choice.\"\nmsgstr \"建立​一​個​新​遊戲​的​難度​設定​你​的​選擇。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:232\n#, fuzzy\n#| msgid \"Create a new game with a difficulty setting of your choice.\"\nmsgid \"\"\n\"Create a new public game that anyone can join with a difficulty setting of \"\n\"your choice.\"\nmsgstr \"建立​一​個​新​遊戲​的​難度​設定​你​的​選擇。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:236\n#, fuzzy\n#| msgid \"\"\n#| \"Enter an IP or a hostname and join a game already in progress at that \"\n#| \"address.\"\nmsgid \"Enter Game ID to join a game already in progress.\"\nmsgstr \"輸入​IP​或​主機名，然​後​在​該​地址​加入​正在​進行​的​遊戲。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:238\n#, fuzzy\n#| msgid \"\"\n#| \"Enter an IP or a hostname and join a game already in progress at that \"\n#| \"address.\"\nmsgid \"Enter an IP or a hostname to join a game already in progress.\"\nmsgstr \"輸入​IP​或​主機名，然​後​在​該​地址​加入​正在​進行​的​遊戲。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:243\n#, fuzzy\n#| msgid \"\"\n#| \"Enter an IP or a hostname and join a game already in progress at that \"\n#| \"address.\"\nmsgid \"Join the public game already in progress.\"\nmsgstr \"輸入​IP​或​主機名，然​後​在​該​地址​加入​正在​進行​的​遊戲。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:249 Source/DiabloUI/multi/selgame.cpp:343\n#: Source/DiabloUI/multi/selgame.cpp:404 Source/DiabloUI/multi/selgame.cpp:510\n#: Source/DiabloUI/multi/selgame.cpp:530 Source/automap.cpp:1461\n#: Source/discord/discord.cpp:114\nmsgid \"Normal\"\nmsgstr \"正常\"\n\n#: Source/DiabloUI/multi/selgame.cpp:252 Source/DiabloUI/multi/selgame.cpp:344\n#: Source/DiabloUI/multi/selgame.cpp:408 Source/automap.cpp:1464\n#: Source/discord/discord.cpp:114\nmsgid \"Nightmare\"\nmsgstr \"噩夢\"\n\n#: Source/DiabloUI/multi/selgame.cpp:255 Source/DiabloUI/multi/selgame.cpp:345\n#: Source/DiabloUI/multi/selgame.cpp:412 Source/automap.cpp:1467\n#: Source/discord/discord.cpp:81 Source/discord/discord.cpp:114\nmsgid \"Hell\"\nmsgstr \"地​獄\"\n\n#. TRANSLATORS: {:s} means: Game Difficulty.\n#: Source/DiabloUI/multi/selgame.cpp:258 Source/automap.cpp:1471\n#, fuzzy, c++-format\n#| msgid \"Select Difficulty\"\nmsgid \"Difficulty: {:s}\"\nmsgstr \"選​擇​難度\"\n\n#: Source/DiabloUI/multi/selgame.cpp:262 Source/gamemenu.cpp:165\nmsgid \"Speed: Normal\"\nmsgstr \"速度: 正常\"\n\n#: Source/DiabloUI/multi/selgame.cpp:265 Source/gamemenu.cpp:163\nmsgid \"Speed: Fast\"\nmsgstr \"速度: 快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:268 Source/gamemenu.cpp:161\nmsgid \"Speed: Faster\"\nmsgstr \"速度: 更​快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:271 Source/gamemenu.cpp:159\nmsgid \"Speed: Fastest\"\nmsgstr \"速度: 最​快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:279\nmsgid \"Players: \"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:341\nmsgid \"Select Difficulty\"\nmsgstr \"選​擇​難度\"\n\n#: Source/DiabloUI/multi/selgame.cpp:359\n#, c++-format\nmsgid \"Join {:s} Games\"\nmsgstr \"加入​{:s}​遊戲\"\n\n#: Source/DiabloUI/multi/selgame.cpp:364\nmsgid \"Enter Game ID\"\nmsgstr \"\"\n\n#: Source/DiabloUI/multi/selgame.cpp:366\nmsgid \"Enter address\"\nmsgstr \"輸入​地址\"\n\n#: Source/DiabloUI/multi/selgame.cpp:405\nmsgid \"\"\n\"Normal Difficulty\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"正常​難度​\\n\"\n\"這​是​一​個​開始​的​角色​應該​開始尋求擊敗迪亞波羅。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:409\nmsgid \"\"\n\"Nightmare Difficulty\\n\"\n\"The denizens of the Labyrinth have been bolstered and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"噩夢​難度​\\n\"\n\"迷宮裡​的​居民​得到​了​支援，這將​是​一​個​更​大​的​挑戰。這隻​建議​有​經驗​的​角色​使用。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:413\nmsgid \"\"\n\"Hell Difficulty\\n\"\n\"The most powerful of the underworld's creatures lurk at the gateway into \"\n\"Hell. Only the most experienced characters should venture in this realm.\"\nmsgstr \"\"\n\"地​獄​般​的​困難​\\n\"\n\"​最​強​大​的​地下​世界​的​生物​潛伏在地獄​的​大門。只有​最​有​經驗​的​人物​才​能​在​這個​領域​冒\"\n\"險。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:428\nmsgid \"\"\n\"Your character must reach level 20 before you can enter a multiplayer game \"\n\"of Nightmare difficulty.\"\nmsgstr \"你​的​角色​必須達​到​20​級​才​能​進入​多​人​遊戲​的​噩夢​難度。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:430\nmsgid \"\"\n\"Your character must reach level 30 before you can enter a multiplayer game \"\n\"of Hell difficulty.\"\nmsgstr \"你​的​角色​必須達​到​30​級​才​能​進入​地獄​難度​的​多​人​遊戲。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:508\nmsgid \"Select Game Speed\"\nmsgstr \"選​擇遊戲​速度\"\n\n#: Source/DiabloUI/multi/selgame.cpp:511 Source/DiabloUI/multi/selgame.cpp:534\nmsgid \"Fast\"\nmsgstr \"快速​的\"\n\n#: Source/DiabloUI/multi/selgame.cpp:512 Source/DiabloUI/multi/selgame.cpp:538\nmsgid \"Faster\"\nmsgstr \"更​快\"\n\n#: Source/DiabloUI/multi/selgame.cpp:513 Source/DiabloUI/multi/selgame.cpp:542\nmsgid \"Fastest\"\nmsgstr \"最​快​的\"\n\n#: Source/DiabloUI/multi/selgame.cpp:531\nmsgid \"\"\n\"Normal Speed\\n\"\n\"This is where a starting character should begin the quest to defeat Diablo.\"\nmsgstr \"\"\n\"正常​速度​\\n\"\n\"這​是​一​個​開始​的​角色​應該​開始尋求擊敗迪亞波羅。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:535\nmsgid \"\"\n\"Fast Speed\\n\"\n\"The denizens of the Labyrinth have been hastened and will prove to be a \"\n\"greater challenge. This is recommended for experienced characters only.\"\nmsgstr \"\"\n\"快速​\\n\"\n\"迷宮​的​居民​們​已​經​被​催促​了，這將​是​一​個​更​大​的​挑戰。這隻​建議​有​經驗​的​角色​使用。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:539\nmsgid \"\"\n\"Faster Speed\\n\"\n\"Most monsters of the dungeon will seek you out quicker than ever before. \"\n\"Only an experienced champion should try their luck at this speed.\"\nmsgstr \"\"\n\"更​快​的​速度​\\n\"\n\"​地​牢里​的​大多​數​怪物會​比​以前​更​快​地​找到​你。只有​有​經驗​的​冠軍​才​能​在​這個​速度​下​碰碰\"\n\"運氣。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:543\nmsgid \"\"\n\"Fastest Speed\\n\"\n\"The minions of the underworld will rush to attack without hesitation. Only a \"\n\"true speed demon should enter at this pace.\"\nmsgstr \"\"\n\"最​快​速度​\\n\"\n\"​黑社​會​的​僕從們會​毫​不​猶​豫​地​趕來​攻擊。只有​真正​的​速度​惡魔​才​能​以​這種​速度​進入。\"\n\n#: Source/DiabloUI/multi/selgame.cpp:587 Source/DiabloUI/multi/selgame.cpp:592\nmsgid \"Enter Password\"\nmsgstr \"輸​入​密碼\"\n\n#: Source/DiabloUI/selstart.cpp:49\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Enter Hellfire\"\nmsgstr \"退出​地​獄火\"\n\n#: Source/DiabloUI/selstart.cpp:50\n#, fuzzy\n#| msgid \"Down to Diablo\"\nmsgid \"Switch to Diablo\"\nmsgstr \"下​到​迪亞波羅\"\n\n#: Source/DiabloUI/selyesno.cpp:68 Source/stores.cpp:967\nmsgid \"Yes\"\nmsgstr \"是\"\n\n#: Source/DiabloUI/selyesno.cpp:69 Source/stores.cpp:968\nmsgid \"No\"\nmsgstr \"否\"\n\n#: Source/DiabloUI/settingsmenu.cpp:162\nmsgid \"Press gamepad buttons to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:439\nmsgid \"Bound key:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:488\nmsgid \"Press any key to change.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:490\nmsgid \"Unbind key\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:494\nmsgid \"Bound button combo:\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:503\nmsgid \"Unbind button combo\"\nmsgstr \"\"\n\n#: Source/DiabloUI/settingsmenu.cpp:547 Source/gamemenu.cpp:73\nmsgid \"Previous Menu\"\nmsgstr \"上​一​個​菜單\"\n\n#: Source/DiabloUI/support_lines.cpp:10\nmsgid \"\"\n\"We maintain a chat server at Discord.gg/devilutionx Follow the links to join \"\n\"our community where we talk about things related to Diablo, and the Hellfire \"\n\"expansion.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/support_lines.cpp:12\nmsgid \"\"\n\"DevilutionX is maintained by Diasurgical, issues and bugs can be reported at \"\n\"this address: https://github.com/diasurgical/devilutionX To help us better \"\n\"serve you, please be sure to include the version number, operating system, \"\n\"and the nature of the problem.\"\nmsgstr \"\"\n\"DevilutionX​由​Diasurgical​維護，可以​報告問題​和​錯誤​地址: https://github.com/\"\n\"diasurgical/devilutionX爲​了​幫助​我​們​更​好​地​為​您​服務，請務​必​包括​版本​號，操作系\"\n\"統，以及​問題​的​性質。\"\n\n#: Source/DiabloUI/support_lines.cpp:15\nmsgid \"Disclaimer:\"\nmsgstr \"免​責​聲​明: \"\n\n#: Source/DiabloUI/support_lines.cpp:16\nmsgid \"\"\n\"\\tDevilutionX is not supported or maintained by Blizzard Entertainment, nor \"\n\"GOG.com. Neither Blizzard Entertainment nor GOG.com has tested or certified \"\n\"the quality or compatibility of DevilutionX. All inquiries regarding \"\n\"DevilutionX should be directed to Diasurgical, not to Blizzard Entertainment \"\n\"or GOG.com.\"\nmsgstr \"\"\n\"\\t​暴雪​娛樂​不​支援​或​維護​DevilutionX，也​不​是​GOG.com。暴雪娛樂​和​GOG.com​都​沒​有​進行\"\n\"測試​或者​證明​了​DevilutionX​的​質量​或​相容性。所有​查詢關​於​DevilutionX，應​直接​向​\"\n\"Diasurgical，而​不​是​暴雪娛樂​或​GOG.com。\"\n\n#: Source/DiabloUI/support_lines.cpp:19\nmsgid \"\"\n\"\\tThis port makes use of Charis SIL, New Athena Unicode, Unifont, and Noto \"\n\"which are licensed under the SIL Open Font License, as well as Twitmoji \"\n\"which is licensed under CC-BY 4.0. The port also makes use of SDL which is \"\n\"licensed under the zlib-license. See the ReadMe for further details.\"\nmsgstr \"\"\n\n#: Source/DiabloUI/title.cpp:67\nmsgid \"Copyright © 1996-2001 Blizzard Entertainment\"\nmsgstr \"Copyright © 1996-2001 Blizzard Entertainment\"\n\n#: Source/appfat.cpp:63\nmsgid \"Error\"\nmsgstr \"錯​誤\"\n\n#. TRANSLATORS: Error message that displays relevant information for bug report\n#: Source/appfat.cpp:77\n#, c++-format\nmsgid \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"The error occurred at: {:s} line {:d}\"\nmsgstr \"\"\n\"{:s}\\n\"\n\"\\n\"\n\"錯誤​發生​在: {:s}，行{:d}\"\n\n#: Source/appfat.cpp:83\nmsgid \"Data File Error\"\nmsgstr \"數​據​檔案​錯誤\"\n\n#: Source/appfat.cpp:84\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Unable to open main data archive ({:s}).\\n\"\n#| \"\\n\"\n#| \"Make sure that it is in the game folder and that the file name is in all \"\n#| \"lowercase.\"\nmsgid \"\"\n\"Unable to open main data archive ({:s}).\\n\"\n\"\\n\"\n\"Make sure that it is in the game folder.\"\nmsgstr \"\"\n\"無​法​打開主數據​存檔​（​{:s}​）。\\n\"\n\"\\n\"\n\"確保​它​在​遊戲​資料夾​中，並且​檔名​都​是​小寫​的。\"\n\n#: Source/appfat.cpp:93\nmsgid \"Read-Only Directory Error\"\nmsgstr \"只​讀目錄​錯誤\"\n\n#. TRANSLATORS: Error when Program is not allowed to write data\n#: Source/appfat.cpp:94\n#, c++-format\nmsgid \"\"\n\"Unable to write to location:\\n\"\n\"{:s}\"\nmsgstr \"\"\n\"無​法​寫入​位置: \\n\"\n\"{:s}\"\n\n#: Source/automap.cpp:1416\n#, fuzzy\n#| msgid \"game: \"\nmsgid \"Game: \"\nmsgstr \"遊​戲: \"\n\n#: Source/automap.cpp:1424\n#, fuzzy\nmsgid \"Offline Game\"\nmsgstr \"環​回\"\n\n#: Source/automap.cpp:1426\n#, fuzzy\n#| msgid \"password: \"\nmsgid \"Password: \"\nmsgstr \"密碼: \"\n\n#: Source/automap.cpp:1429\n#, fuzzy\n#| msgid \"Quit Game\"\nmsgid \"Public Game\"\nmsgstr \"退出​遊戲\"\n\n#: Source/automap.cpp:1443\n#, c++-format\nmsgid \"Level: Nest {:d}\"\nmsgstr \"層​數: {:d}​巢​穴\"\n\n#: Source/automap.cpp:1446\n#, c++-format\nmsgid \"Level: Crypt {:d}\"\nmsgstr \"層​數: {:d}​墓穴\"\n\n#: Source/automap.cpp:1449 Source/discord/discord.cpp:81 Source/objects.cpp:157\nmsgid \"Town\"\nmsgstr \"城鎮\"\n\n#: Source/automap.cpp:1452\n#, c++-format\nmsgid \"Level: {:d}\"\nmsgstr \"等​級: {:d}\"\n\n#: Source/control.cpp:203\nmsgid \"Tab\"\nmsgstr \"標​籤\"\n\n#: Source/control.cpp:203\nmsgid \"Esc\"\nmsgstr \"電子​穩定​控制​系統\"\n\n#: Source/control.cpp:203\nmsgid \"Enter\"\nmsgstr \"輸​入\"\n\n#: Source/control.cpp:206\nmsgid \"Character Information\"\nmsgstr \"角色​資訊\"\n\n#: Source/control.cpp:207\nmsgid \"Quests log\"\nmsgstr \"任​務日誌\"\n\n#: Source/control.cpp:208\nmsgid \"Automap\"\nmsgstr \"自動​對映\"\n\n#: Source/control.cpp:209\nmsgid \"Main Menu\"\nmsgstr \"主​菜單\"\n\n#: Source/control.cpp:210 Source/diablo.cpp:1912 Source/diablo.cpp:2264\nmsgid \"Inventory\"\nmsgstr \"庫​存\"\n\n#: Source/control.cpp:211\nmsgid \"Spell book\"\nmsgstr \"咒​語書\"\n\n#: Source/control.cpp:212\nmsgid \"Send Message\"\nmsgstr \"發​送​訊​息\"\n\n#: Source/control.cpp:622\nmsgid \"Available Commands:\"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \"Command \"\nmsgstr \"\"\n\n#: Source/control.cpp:630 Source/control.cpp:814\nmsgid \" is unknown.\"\nmsgstr \"\"\n\n#: Source/control.cpp:633 Source/control.cpp:634\n#, fuzzy\n#| msgid \"Description:\"\nmsgid \"Description: \"\nmsgstr \"說​明: \"\n\n#: Source/control.cpp:633\nmsgid \"\"\n\"\\n\"\n\"Parameters: No additional parameter needed.\"\nmsgstr \"\"\n\n#: Source/control.cpp:634\nmsgid \"\"\n\"\\n\"\n\"Parameters: \"\nmsgstr \"\"\n\n#: Source/control.cpp:648 Source/control.cpp:680\nmsgid \"Arenas are only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:653\n#, fuzzy\n#| msgid \"Are you sure you want to buy this item?\"\nmsgid \"What arena do you want to visit?\"\nmsgstr \"您​確定​要​購買​此​商品​嗎？\"\n\n#: Source/control.cpp:661\nmsgid \"Invalid arena-number. Valid numbers are:\"\nmsgstr \"\"\n\n#: Source/control.cpp:667\nmsgid \"To enter a arena, you need to be in town or another arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:705\nmsgid \"Inspecting only supported in multiplayer.\"\nmsgstr \"\"\n\n#: Source/control.cpp:710 Source/control.cpp:1001\nmsgid \"Stopped inspecting players.\"\nmsgstr \"\"\n\n#: Source/control.cpp:725\nmsgid \"No players found with such a name\"\nmsgstr \"\"\n\n#: Source/control.cpp:731\nmsgid \"Inspecting player: \"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"Prints help overview or help for a specific command.\"\nmsgstr \"\"\n\n#: Source/control.cpp:800\nmsgid \"[command]\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"Enter a PvP Arena.\"\nmsgstr \"\"\n\n#: Source/control.cpp:801\nmsgid \"<arena-number>\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\nmsgid \"Gives Arena Potions.\"\nmsgstr \"\"\n\n#: Source/control.cpp:802\n#, fuzzy\n#| msgid \"Amber\"\nmsgid \"<number>\"\nmsgstr \"琥​珀\"\n\n#: Source/control.cpp:803\nmsgid \"Inspects stats and equipment of another player.\"\nmsgstr \"\"\n\n#: Source/control.cpp:803\n#, fuzzy\n#| msgid \"Flayed One\"\nmsgid \"<player name>\"\nmsgstr \"單​手劍\"\n\n#: Source/control.cpp:804\nmsgid \"Show seed infos for current level.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1311\nmsgid \"Player friendly\"\nmsgstr \"對​玩​家​友好\"\n\n#: Source/control.cpp:1313\nmsgid \"Player attack\"\nmsgstr \"玩​家​攻擊\"\n\n#: Source/control.cpp:1316\n#, c++-format\nmsgid \"Hotkey: {:s}\"\nmsgstr \"熱​鍵: {:s}\"\n\n#: Source/control.cpp:1328\nmsgid \"Select current spell button\"\nmsgstr \"選​擇​目前​法術​按​鈕\"\n\n#: Source/control.cpp:1331\nmsgid \"Hotkey: 's'\"\nmsgstr \"熱​鍵: 「​s​」\"\n\n#: Source/control.cpp:1337 Source/panels/spell_list.cpp:153\n#, c++-format\nmsgid \"{:s} Skill\"\nmsgstr \"{:s}​技能\"\n\n#: Source/control.cpp:1340 Source/panels/spell_list.cpp:160\n#, c++-format\nmsgid \"{:s} Spell\"\nmsgstr \"{:s}法術\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:165\nmsgid \"Spell Level 0 - Unusable\"\nmsgstr \"法術​等​級​0-無法​使用\"\n\n#: Source/control.cpp:1342 Source/panels/spell_list.cpp:167\n#, c++-format\nmsgid \"Spell Level {:d}\"\nmsgstr \"法術​等​級{:d}\"\n\n#: Source/control.cpp:1345 Source/panels/spell_list.cpp:174\n#, c++-format\nmsgid \"Scroll of {:s}\"\nmsgstr \"{:s}​卷​軸\"\n\n#: Source/control.cpp:1349 Source/panels/spell_list.cpp:178\n#, fuzzy, c++-format\n#| msgid \"{:d} Scroll\"\nmsgid \"{:d} Scroll\"\nmsgid_plural \"{:d} Scrolls\"\nmsgstr[0] \"{:s}卷軸\"\n\n#: Source/control.cpp:1352 Source/panels/spell_list.cpp:185\n#, c++-format\nmsgid \"Staff of {:s}\"\nmsgstr \"{:s}​的​職員\"\n\n#: Source/control.cpp:1353 Source/panels/spell_list.cpp:187\n#, fuzzy, c++-format\n#| msgid \"{:d} Charge\"\nmsgid \"{:d} Charge\"\nmsgid_plural \"{:d} Charges\"\nmsgstr[0] \"生命點{:d}的{:d}\"\n\n#: Source/control.cpp:1487 Source/inv.cpp:1979 Source/inv.cpp:1980\n#: Source/items.cpp:3808\n#, fuzzy, c++-format\n#| msgid \"{:s} gold piece\"\nmsgid \"{:s} gold piece\"\nmsgid_plural \"{:s} gold pieces\"\nmsgstr[0] \"金幣\"\n\n#: Source/control.cpp:1489\nmsgid \"Requirements not met\"\nmsgstr \"未​滿足​條件\"\n\n#: Source/control.cpp:1518\n#, c++-format\nmsgid \"{:s}, Level: {:d}\"\nmsgstr \"{:s}，層數: {:d}\"\n\n#: Source/control.cpp:1519\n#, c++-format\nmsgid \"Hit Points {:d} of {:d}\"\nmsgstr \"生命​點{:d}​的​{:d}\"\n\n#: Source/control.cpp:1525\n#, fuzzy\n#| msgid \"Right click to use\"\nmsgid \"Right click to inspect\"\nmsgstr \"右​擊​使用\"\n\n#: Source/control.cpp:1573\nmsgid \"Level Up\"\nmsgstr \"升級\"\n\n#: Source/control.cpp:1687\nmsgid \"You have died\"\nmsgstr \"\"\n\n#: Source/control.cpp:1695\nmsgid \"ESC\"\nmsgstr \"\"\n\n#: Source/control.cpp:1701\nmsgid \"Menu Button\"\nmsgstr \"\"\n\n#: Source/control.cpp:1709\n#, c++-format\nmsgid \"Press {} to load last save.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1711\n#, c++-format\nmsgid \"Press {} to return to Main Menu.\"\nmsgstr \"\"\n\n#: Source/control.cpp:1714\n#, c++-format\nmsgid \"Press {} to restart in town.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} is a number with separators. Dialog is shown when splitting a stash of Gold.\n#: Source/control.cpp:1732\n#, c++-format\nmsgid \"You have {:s} gold piece. How many do you want to remove?\"\nmsgid_plural \"You have {:s} gold pieces. How many do you want to remove?\"\nmsgstr[0] \"\"\n\n#: Source/cursor.cpp:621\nmsgid \"Town Portal\"\nmsgstr \"城鎮​傳​送門\"\n\n#: Source/cursor.cpp:622\n#, c++-format\nmsgid \"from {:s}\"\nmsgstr \"從​{:s}\"\n\n#: Source/cursor.cpp:635\nmsgid \"Portal to\"\nmsgstr \"通​向\"\n\n#: Source/cursor.cpp:636\nmsgid \"The Unholy Altar\"\nmsgstr \"邪惡​的​祭壇\"\n\n#: Source/cursor.cpp:636\nmsgid \"level 15\"\nmsgstr \"15​級\"\n\n#. TRANSLATORS: Error message when a data file is missing or corrupt. Arguments are {file name}\n#: Source/data/file.cpp:52\n#, fuzzy, c++-format\n#| msgid \"Unable to load character\"\nmsgid \"Unable to load data from file {0}\"\nmsgstr \"無​法​載入​角色\"\n\n#. TRANSLATORS: Error message when a data file is empty or only contains the header row. Arguments are {file name}\n#: Source/data/file.cpp:57\n#, c++-format\nmsgid \"{0} is incomplete, please check the file contents.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when a data file doesn't contain the expected columns. Arguments are {file name}\n#: Source/data/file.cpp:62\n#, c++-format\nmsgid \"\"\n\"Your {0} file doesn't have the expected columns, please make sure it matches \"\n\"the documented format.\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and a text value is encountered when a number is expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:77\n#, c++-format\nmsgid \"Non-numeric value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when parsing a data file and we find a number larger than expected. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:83\n#, c++-format\nmsgid \"Out of range value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Error message when we find an unrecognised value in a key column. Arguments are {found value}, {column heading}, {file name}, {row/record number}, {column/field number}\n#: Source/data/file.cpp:89\n#, c++-format\nmsgid \"Invalid value {0} for {1} in {2} at row {3} and column {4}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:989\nmsgid \"Print this message and exit\"\nmsgstr \"列​印此​訊息並​退出\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:990\nmsgid \"Print the version and exit\"\nmsgstr \"列​印​版本​並​退出\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:991\nmsgid \"Specify the folder of diabdat.mpq\"\nmsgstr \"指定​diabdat.mpq​的​資料​夾\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:992\nmsgid \"Specify the folder of save files\"\nmsgstr \"指定​儲存​檔案​的​資料​夾\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:993\nmsgid \"Specify the location of diablo.ini\"\nmsgstr \"指定​diablo.ini​的​位置\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:994\nmsgid \"Specify the language code (e.g. en or pt_BR)\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:995\nmsgid \"Skip startup videos\"\nmsgstr \"跳過啟動視訊\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:996\nmsgid \"Display frames per second\"\nmsgstr \"每​秒​顯示幀數\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:997\nmsgid \"Enable verbose logging\"\nmsgstr \"啟​用​詳​細​日誌記錄\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:999\nmsgid \"Log to a file instead of stderr\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1002\n#, fuzzy\nmsgid \"Record a demo file\"\nmsgstr \"儲​存檔案​已​存在\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1003\n#, fuzzy\nmsgid \"Play a demo file\"\nmsgstr \"自己​玩，沒​有​網路​曝光。\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1004\nmsgid \"Disable all frame limiting during demo playback\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1007\nmsgid \"Game selection:\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1009\nmsgid \"Force Shareware mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1010\nmsgid \"Force Diablo mode\"\nmsgstr \"\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1011\n#, fuzzy\n#| msgid \"Hellfire Help\"\nmsgid \"Force Hellfire mode\"\nmsgstr \"地​獄火​幫助\"\n\n#. TRANSLATORS: Commandline Option\n#: Source/diablo.cpp:1012\nmsgid \"Hellfire options:\"\nmsgstr \"地​獄火選項:\"\n\n#: Source/diablo.cpp:1022\nmsgid \"Report bugs at https://github.com/diasurgical/devilutionX/\"\nmsgstr \"報​告錯​誤​https://github.com/diasurgical/devilutionX/\"\n\n#: Source/diablo.cpp:1202\nmsgid \"Please update devilutionx.mpq and fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1204\n#, fuzzy\n#| msgid \"\"\n#| \"Failed to load UI resources. Is devilutionx.mpq accessible and up to date?\"\nmsgid \"\"\n\"Failed to load UI resources.\\n\"\n\"\\n\"\n\"Make sure devilutionx.mpq is in the game folder and that it is up to date.\"\nmsgstr \"無​法載入​UI資源。devilutionx.mpq​是否​可​訪問且​是​最​新​的？\"\n\n#: Source/diablo.cpp:1208\nmsgid \"Please update fonts.mpq to the latest version\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1551\nmsgid \"-- Network timeout --\"\nmsgstr \"--網路​超時​--\"\n\n#: Source/diablo.cpp:1552\nmsgid \"-- Waiting for players --\"\nmsgstr \"--​等待​玩​家​--\"\n\n#: Source/diablo.cpp:1575\nmsgid \"No help available\"\nmsgstr \"沒​有​可用​的​幫助\"\n\n#: Source/diablo.cpp:1576\nmsgid \"while in stores\"\nmsgstr \"在​商店​裡\"\n\n#: Source/diablo.cpp:1774 Source/diablo.cpp:2094\n#, fuzzy, c++-format\n#| msgid \"Sell items\"\nmsgid \"Belt item {}\"\nmsgstr \"出售​物品\"\n\n#: Source/diablo.cpp:1775 Source/diablo.cpp:2095\nmsgid \"Use Belt item.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1790 Source/diablo.cpp:2110\n#, c++-format\nmsgid \"Quick spell {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1791 Source/diablo.cpp:2111\nmsgid \"Hotkey for skill or spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1809\n#, fuzzy\n#| msgid \"Previous Menu\"\nmsgid \"Previous quick spell\"\nmsgstr \"上​一​個​菜單\"\n\n#: Source/diablo.cpp:1810\nmsgid \"Selects the previous quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1817\nmsgid \"Next quick spell\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1818\nmsgid \"Selects the next quick spell (cycles).\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1825 Source/diablo.cpp:2238\nmsgid \"Use health potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1826 Source/diablo.cpp:2239\nmsgid \"Use health potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1833 Source/diablo.cpp:2246\nmsgid \"Use mana potion\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1834 Source/diablo.cpp:2247\nmsgid \"Use mana potions from belt.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1841 Source/diablo.cpp:2294\n#, fuzzy\n#| msgid \"Spell book\"\nmsgid \"Speedbook\"\nmsgstr \"咒​語書\"\n\n#: Source/diablo.cpp:1842 Source/diablo.cpp:2295\n#, fuzzy\nmsgid \"Open Speedbook.\"\nmsgstr \"{:s} / {:s}\"\n\n#: Source/diablo.cpp:1849 Source/diablo.cpp:2451\nmsgid \"Quick save\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1850 Source/diablo.cpp:2452\n#, fuzzy\n#| msgid \"Save Game\"\nmsgid \"Saves the game.\"\nmsgstr \"儲​存遊​戲\"\n\n#: Source/diablo.cpp:1857 Source/diablo.cpp:2459\nmsgid \"Quick load\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1858 Source/diablo.cpp:2460\n#, fuzzy\n#| msgid \"Load Game\"\nmsgid \"Loads the game.\"\nmsgstr \"載入​遊戲\"\n\n#: Source/diablo.cpp:1866\n#, fuzzy\n#| msgid \"Quit Game\"\nmsgid \"Quit game\"\nmsgstr \"退出​遊戲\"\n\n#: Source/diablo.cpp:1867\n#, fuzzy\n#| msgid \"Lester the farmer\"\nmsgid \"Closes the game.\"\nmsgstr \"農夫萊​斯特\"\n\n#: Source/diablo.cpp:1873\nmsgid \"Stop hero\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1874\nmsgid \"Stops walking and cancel pending actions.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1881 Source/diablo.cpp:2467\n#, fuzzy\n#| msgid \"lightning\"\nmsgid \"Item highlighting\"\nmsgstr \"閃​電\"\n\n#: Source/diablo.cpp:1882 Source/diablo.cpp:2468\nmsgid \"Show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1888 Source/diablo.cpp:2474\nmsgid \"Toggle item highlighting\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1889 Source/diablo.cpp:2475\nmsgid \"Permanent show/hide items on ground.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1895 Source/diablo.cpp:2304\nmsgid \"Toggle automap\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1896 Source/diablo.cpp:2305\nmsgid \"Toggles if automap is displayed.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1903\nmsgid \"Cycle map type\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1904\nmsgid \"Opaque -> Transparent -> Minimap -> None\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1913 Source/diablo.cpp:2265\nmsgid \"Open Inventory screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1920 Source/diablo.cpp:2254\n#, fuzzy\n#| msgid \"Char\"\nmsgid \"Character\"\nmsgstr \"角色\"\n\n#: Source/diablo.cpp:1921 Source/diablo.cpp:2255\nmsgid \"Open Character screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1928\nmsgid \"Party\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1929\nmsgid \"Open side Party panel.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1936 Source/diablo.cpp:2274\n#, fuzzy\n#| msgid \"Quests log\"\nmsgid \"Quest log\"\nmsgstr \"任​務日誌\"\n\n#: Source/diablo.cpp:1937 Source/diablo.cpp:2275\n#, fuzzy\n#| msgid \"Quests log\"\nmsgid \"Open Quest log.\"\nmsgstr \"任​務日誌\"\n\n#: Source/diablo.cpp:1944 Source/diablo.cpp:2284\n#, fuzzy\n#| msgid \"Spell book\"\nmsgid \"Spellbook\"\nmsgstr \"咒​語書\"\n\n#: Source/diablo.cpp:1945 Source/diablo.cpp:2285\n#, fuzzy\n#| msgid \"A Spellbook\"\nmsgid \"Open Spellbook.\"\nmsgstr \"咒​語書\"\n\n#: Source/diablo.cpp:1953\n#, c++-format\nmsgid \"Quick Message {}\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1954\nmsgid \"Use Quick Message in chat.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1963 Source/diablo.cpp:2481\nmsgid \"Hide Info Screens\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1964 Source/diablo.cpp:2482\nmsgid \"Hide all info screens.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1987 Source/diablo.cpp:2505 Source/options.cpp:737\nmsgid \"Zoom\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1988 Source/diablo.cpp:2506\nmsgid \"Zoom Game Screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1998 Source/diablo.cpp:2516\nmsgid \"Pause Game\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:1999 Source/diablo.cpp:2005 Source/diablo.cpp:2517\nmsgid \"Pauses the game.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2004\nmsgid \"Pause Game (Alternate)\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2010 Source/diablo.cpp:2522\n#, fuzzy\n#| msgid \"increase strength\"\nmsgid \"Decrease Brightness\"\nmsgstr \"增強​力量\"\n\n#: Source/diablo.cpp:2011 Source/diablo.cpp:2523\n#, fuzzy\n#| msgid \"increase strength\"\nmsgid \"Reduce screen brightness.\"\nmsgstr \"增強​力量\"\n\n#: Source/diablo.cpp:2018 Source/diablo.cpp:2530\n#, fuzzy\n#| msgid \"increase strength\"\nmsgid \"Increase Brightness\"\nmsgstr \"增強​力量\"\n\n#: Source/diablo.cpp:2019 Source/diablo.cpp:2531\n#, fuzzy\n#| msgid \"increase strength\"\nmsgid \"Increase screen brightness.\"\nmsgstr \"增強​力量\"\n\n#: Source/diablo.cpp:2026 Source/diablo.cpp:2538\nmsgid \"Help\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2027 Source/diablo.cpp:2539\nmsgid \"Open Help Screen.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2034 Source/diablo.cpp:2546\nmsgid \"Screenshot\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2035 Source/diablo.cpp:2547\nmsgid \"Takes a screenshot.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2041 Source/diablo.cpp:2553\n#, fuzzy\n#| msgid \"Game Design\"\nmsgid \"Game info\"\nmsgstr \"遊​戲設計\"\n\n#: Source/diablo.cpp:2042 Source/diablo.cpp:2554\nmsgid \"Displays game infos.\"\nmsgstr \"\"\n\n#. TRANSLATORS: {:s} means: Character Name, Game Version, Game Difficulty.\n#: Source/diablo.cpp:2046 Source/diablo.cpp:2558\n#, fuzzy, c++-format\n#| msgid \"{:d} {:s} charge\"\nmsgid \"{:s} {:s}\"\nmsgstr \"{:s}，層數: {:d}\"\n\n#: Source/diablo.cpp:2055 Source/diablo.cpp:2575\nmsgid \"Chat Log\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2056 Source/diablo.cpp:2576\nmsgid \"Displays chat log.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2063 Source/diablo.cpp:2567\n#, fuzzy\n#| msgid \"Inventory\"\nmsgid \"Sort Inventory\"\nmsgstr \"庫​存\"\n\n#: Source/diablo.cpp:2064 Source/diablo.cpp:2568\nmsgid \"Sorts the inventory.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2072\nmsgid \"Console\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2073\nmsgid \"Opens Lua console.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2129\nmsgid \"Primary action\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2130\nmsgid \"Attack monsters, talk to towners, lift and place inventory items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2144\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Secondary action\"\nmsgstr \"選​擇​操作\"\n\n#: Source/diablo.cpp:2145\nmsgid \"Open chests, interact with doors, pick up items.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2159\n#, fuzzy\n#| msgid \"Select Action\"\nmsgid \"Spell action\"\nmsgstr \"選​擇​操作\"\n\n#: Source/diablo.cpp:2160\nmsgid \"Cast the active spell.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2174\n#, fuzzy\n#| msgid \"Cancel\"\nmsgid \"Cancel action\"\nmsgstr \"取消\"\n\n#: Source/diablo.cpp:2175\n#, fuzzy\n#| msgid \"Lester the farmer\"\nmsgid \"Close menus.\"\nmsgstr \"農夫萊​斯特\"\n\n#: Source/diablo.cpp:2200\nmsgid \"Move up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2201\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character up.\"\nmsgstr \"多​人​遊戲​角色\"\n\n#: Source/diablo.cpp:2206\nmsgid \"Move down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2207\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character down.\"\nmsgstr \"多​人​遊戲​角色\"\n\n#: Source/diablo.cpp:2212\nmsgid \"Move left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2213\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character left.\"\nmsgstr \"多​人​遊戲​角色\"\n\n#: Source/diablo.cpp:2218\n#, fuzzy\n#| msgid \"the night\"\nmsgid \"Move right\"\nmsgstr \"夜晚\"\n\n#: Source/diablo.cpp:2219\n#, fuzzy\n#| msgid \"Multi Player Characters\"\nmsgid \"Moves the player character right.\"\nmsgstr \"多​人​遊戲​角色\"\n\n#: Source/diablo.cpp:2224\nmsgid \"Stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2225\nmsgid \"Hold to prevent the player from moving.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2230\nmsgid \"Toggle stand ground\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2231\nmsgid \"Toggle whether the player moves.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2310\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"Automap Move Up\"\nmsgstr \"自動​對映\"\n\n#: Source/diablo.cpp:2311\nmsgid \"Moves the automap up when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2316\nmsgid \"Automap Move Down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2317\nmsgid \"Moves the automap down when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2322\nmsgid \"Automap Move Left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2323\nmsgid \"Moves the automap left when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2328\nmsgid \"Automap Move Right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2329\nmsgid \"Moves the automap right when active.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2334\nmsgid \"Move mouse up\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2335\nmsgid \"Simulates upward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2340\nmsgid \"Move mouse down\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2341\nmsgid \"Simulates downward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2346\nmsgid \"Move mouse left\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2347\nmsgid \"Simulates leftward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2352\nmsgid \"Move mouse right\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2353\nmsgid \"Simulates rightward mouse movement.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2371 Source/diablo.cpp:2378\nmsgid \"Left mouse click\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2372 Source/diablo.cpp:2379\nmsgid \"Simulates the left mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2396 Source/diablo.cpp:2403\n#, fuzzy\n#| msgid \"Right click to use\"\nmsgid \"Right mouse click\"\nmsgstr \"右​擊​使用\"\n\n#: Source/diablo.cpp:2397 Source/diablo.cpp:2404\nmsgid \"Simulates the right mouse button.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2410\nmsgid \"Gamepad hotspell menu\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2411\nmsgid \"Hold to set or use spell hotkeys.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2417\nmsgid \"Gamepad menu navigator\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2418\nmsgid \"Hold to access gamepad menu navigation.\"\nmsgstr \"\"\n\n#: Source/diablo.cpp:2433 Source/diablo.cpp:2442\n#, fuzzy\n#| msgid \"The game ended\"\nmsgid \"Toggle game menu\"\nmsgstr \"比賽​結束​了\"\n\n#: Source/diablo.cpp:2434 Source/diablo.cpp:2443\n#, fuzzy\n#| msgid \"Save Game\"\nmsgid \"Opens the game menu.\"\nmsgstr \"儲​存遊​戲\"\n\n#: Source/diablo_msg.cpp:63\n#, fuzzy\n#| msgid \"Flame Wave\"\nmsgid \"Game saved\"\nmsgstr \"火焰​波卷軸\"\n\n#: Source/diablo_msg.cpp:64\nmsgid \"No multiplayer functions in demo\"\nmsgstr \"演示​中​沒​有​多​人​遊戲​功能\"\n\n#: Source/diablo_msg.cpp:65\nmsgid \"Direct Sound Creation Failed\"\nmsgstr \"直接​聲音​建立​失敗\"\n\n#: Source/diablo_msg.cpp:66\nmsgid \"Not available in shareware version\"\nmsgstr \"在​共​享軟​體​版本​中​不​可​用\"\n\n#: Source/diablo_msg.cpp:67\nmsgid \"Not enough space to save\"\nmsgstr \"空間​不​夠​節省\"\n\n#: Source/diablo_msg.cpp:68\nmsgid \"No Pause in town\"\nmsgstr \"不​要​在​城裡​停下​來\"\n\n#: Source/diablo_msg.cpp:69\nmsgid \"Copying to a hard disk is recommended\"\nmsgstr \"建​議複製​到​硬碟\"\n\n#: Source/diablo_msg.cpp:70\nmsgid \"Multiplayer sync problem\"\nmsgstr \"多​人​同步​問題\"\n\n#: Source/diablo_msg.cpp:71\nmsgid \"No pause in multiplayer\"\nmsgstr \"多​人​遊戲​中​無暫​停\"\n\n#: Source/diablo_msg.cpp:73\nmsgid \"Saving...\"\nmsgstr \"正在​儲存。。。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:74\nmsgid \"Some are weakened as one grows strong\"\nmsgstr \"當​一​個​人​變​得​強壯時，有些​人​會​變​得​虛弱\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:75\nmsgid \"New strength is forged through destruction\"\nmsgstr \"新​的​力量​是​通過​破壞鍛造出來​的\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:76\nmsgid \"Those who defend seldom attack\"\nmsgstr \"防禦者​很​少​攻擊\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:77\nmsgid \"The sword of justice is swift and sharp\"\nmsgstr \"正​義​之​劍​迅捷​而​鋒利\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:78\nmsgid \"While the spirit is vigilant the body thrives\"\nmsgstr \"當​精神​保持​警惕時，身體​就​會茁壯​成長\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:79\nmsgid \"The powers of mana refocused renews\"\nmsgstr \"法力​的​力量​重新​聚焦​更新\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:80\nmsgid \"Time cannot diminish the power of steel\"\nmsgstr \"時​間​不​能​削弱​鋼鐵​的​力量\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:81\nmsgid \"Magic is not always what it seems to be\"\nmsgstr \"魔術​並​不​總​是​看起來​的​那​樣\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:82\nmsgid \"What once was opened now is closed\"\nmsgstr \"曾​經​打開​的​現​在​關閉​了\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:83\nmsgid \"Intensity comes at the cost of wisdom\"\nmsgstr \"強度​是​以​智慧​為代價​的\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:84\nmsgid \"Arcane power brings destruction\"\nmsgstr \"神秘​力量​帶來毀滅\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:85\nmsgid \"That which cannot be held cannot be harmed\"\nmsgstr \"不​能​持有​的​東西​不​能​受到​傷害\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:86\nmsgid \"Crimson and Azure become as the sun\"\nmsgstr \"深​紅湛藍​如​太​陽\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:87\nmsgid \"Knowledge and wisdom at the cost of self\"\nmsgstr \"以​犧牲​自我​為代價​的​知識​和​智慧\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:88\nmsgid \"Drink and be refreshed\"\nmsgstr \"喝​酒​提神\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:89\nmsgid \"Wherever you go, there you are\"\nmsgstr \"無論​你​走到​哪​裡，你​都​在​那​裡\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:90\nmsgid \"Energy comes at the cost of wisdom\"\nmsgstr \"能量​是​以​智慧​為代價​的\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:91\nmsgid \"Riches abound when least expected\"\nmsgstr \"財富​在​最​不​經意​的​時候​大量​存在\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:92\nmsgid \"Where avarice fails, patience gains reward\"\nmsgstr \"貪​婪失敗​了，耐心​就​會​得到​回報\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:93\nmsgid \"Blessed by a benevolent companion!\"\nmsgstr \"被​仁慈​的​同伴​祝福！\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:94\nmsgid \"The hands of men may be guided by fate\"\nmsgstr \"人​的​手可能​會​被​命運​所​指引\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:95\nmsgid \"Strength is bolstered by heavenly faith\"\nmsgstr \"力量​是​由​天國​的​信仰​支撐​的\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:96\nmsgid \"The essence of life flows from within\"\nmsgstr \"生命​的​本質來​自內​在\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:97\nmsgid \"The way is made clear when viewed from above\"\nmsgstr \"從​上面​看​清楚​了\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:98\nmsgid \"Salvation comes at the cost of wisdom\"\nmsgstr \"拯救​是​以​智慧​為代價​的\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:99\nmsgid \"Mysteries are revealed in the light of reason\"\nmsgstr \"謎團​在​理性​的​光照​下​顯​露出​來\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:100\nmsgid \"Those who are last may yet be first\"\nmsgstr \"最後​一​個​可能​還​是​第一​個\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:101\nmsgid \"Generosity brings its own rewards\"\nmsgstr \"慷慨​自​有​回報\"\n\n#: Source/diablo_msg.cpp:102\nmsgid \"You must be at least level 8 to use this.\"\nmsgstr \"你​必須​至少​達​到​8​級​才​能​使用​這個。\"\n\n#: Source/diablo_msg.cpp:103\nmsgid \"You must be at least level 13 to use this.\"\nmsgstr \"你​必須​至少​達​到​13級​才​能​使用​這個。\"\n\n#: Source/diablo_msg.cpp:104\nmsgid \"You must be at least level 17 to use this.\"\nmsgstr \"你​必須​至少​達​到​17級​才​能​使用​這個。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:105\nmsgid \"Arcane knowledge gained!\"\nmsgstr \"獲​得​奧術​知識！\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:106\nmsgid \"That which does not kill you...\"\nmsgstr \"不​會殺死​你​的​東西。。。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:107\nmsgid \"Knowledge is power.\"\nmsgstr \"知識​就​是​力量。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:108\nmsgid \"Give and you shall receive.\"\nmsgstr \"付出​你​就​會​得到。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:109\nmsgid \"Some experience is gained by touch.\"\nmsgstr \"一些​經驗​是​通過​接觸​獲得​的。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:110\nmsgid \"There's no place like home.\"\nmsgstr \"沒​有​比家​更​好​的​地方​了。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:111\nmsgid \"Spiritual energy is restored.\"\nmsgstr \"精神​能量​被​恢復。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:112\nmsgid \"You feel more agile.\"\nmsgstr \"你​感覺​更​敏捷。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:113\nmsgid \"You feel stronger.\"\nmsgstr \"你​感覺​更​強壯。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:114\nmsgid \"You feel wiser.\"\nmsgstr \"你​覺得​自己​更​聰明。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:115\nmsgid \"You feel refreshed.\"\nmsgstr \"你​感覺​神清​氣爽。\"\n\n#. TRANSLATORS: Shrine Text. Keep atmospheric. :)\n#: Source/diablo_msg.cpp:116\nmsgid \"That which can break will.\"\nmsgstr \"能​打破​意志​的​東西。\"\n\n#: Source/discord/discord.cpp:81\n#, fuzzy\n#| msgid \"Cathedral Map\"\nmsgid \"Cathedral\"\nmsgstr \"大​教堂​地​圖\"\n\n#: Source/discord/discord.cpp:81\n#, fuzzy\n#| msgid \"Down to catacombs\"\nmsgid \"Catacombs\"\nmsgstr \"下​到​地下​墓穴\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Caves\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\nmsgid \"Nest\"\nmsgstr \"\"\n\n#: Source/discord/discord.cpp:81\n#, fuzzy\n#| msgid \"Cryptic\"\nmsgid \"Crypt\"\nmsgstr \"神秘​的\"\n\n#. TRANSLATORS: dungeon type and floor number i.e. \"Cathedral 3\"\n#: Source/discord/discord.cpp:97\n#, c++-format\nmsgid \"{} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord character, i.e. \"Lv 6 Warrior\"\n#: Source/discord/discord.cpp:104\n#, c++-format\nmsgid \"Lv {} {}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Discord state i.e. \"Nightmare difficulty\"\n#: Source/discord/discord.cpp:116\n#, fuzzy, c++-format\n#| msgid \"Select Difficulty\"\nmsgid \"{} difficulty\"\nmsgstr \"選​擇​難度\"\n\n#. TRANSLATORS: Discord activity, not in game\n#: Source/discord/discord.cpp:197\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"In Menu\"\nmsgstr \"主​菜單\"\n\n#: Source/dvlnet/loopback.cpp:117\nmsgid \"loopback\"\nmsgstr \"環​回\"\n\n#: Source/dvlnet/tcp_client.cpp:112\nmsgid \"Unable to connect\"\nmsgstr \"無​法連線\"\n\n#: Source/dvlnet/tcp_client.cpp:150\nmsgid \"error: read 0 bytes from server\"\nmsgstr \"錯​誤: 從伺​服器​讀​取​0​位​元組\"\n\n#: Source/engine/assets.cpp:244\n#, c++-format\nmsgid \"\"\n\"Failed to open file:\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"{:s}\\n\"\n\"\\n\"\n\"The MPQ file(s) might be damaged. Please check the file integrity.\"\nmsgstr \"\"\n\n#: Source/engine/assets.cpp:426\nmsgid \"diabdat.mpq or spawn.mpq\"\nmsgstr \"diabdat.mpq或spawn.mpq\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"Some Hellfire MPQs are missing\"\nmsgstr \"一些​地​獄火​MPQ​無法​找到\"\n\n#: Source/engine/assets.cpp:464\nmsgid \"\"\n\"Not all Hellfire MPQs were found.\\n\"\n\"Please copy all the hf*.mpq files.\"\nmsgstr \"\"\n\"地​獄火​MPQ​未​能​全部​找到。\\n\"\n\"請​複製​所有​hf​*​.mpq檔案。\"\n\n#: Source/engine/demomode.cpp:181 Source/options.cpp:535\n#, fuzzy\n#| msgid \"absorption\"\nmsgid \"Resolution\"\nmsgstr \"吸收\"\n\n#: Source/engine/demomode.cpp:183 Source/options.cpp:784\n#, fuzzy\n#| msgid \"Restart In Town\"\nmsgid \"Run in Town\"\nmsgstr \"在​城裡​重新​開始\"\n\n#: Source/engine/demomode.cpp:184 Source/options.cpp:787\n#, fuzzy\n#| msgid \"Quests\"\nmsgid \"Theo Quest\"\nmsgstr \"任務\"\n\n#: Source/engine/demomode.cpp:185 Source/options.cpp:788\n#, fuzzy\n#| msgid \"Quests\"\nmsgid \"Cow Quest\"\nmsgstr \"任務\"\n\n#: Source/engine/demomode.cpp:186 Source/options.cpp:800\nmsgid \"Auto Gold Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:187 Source/options.cpp:801\nmsgid \"Auto Elixir Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:188 Source/options.cpp:802\n#, fuzzy\n#| msgid \"No Pause in town\"\nmsgid \"Auto Oil Pickup\"\nmsgstr \"不​要​在​城裡​停下​來\"\n\n#: Source/engine/demomode.cpp:189 Source/options.cpp:803\n#, fuzzy\n#| msgid \"No Pause in town\"\nmsgid \"Auto Pickup in Town\"\nmsgstr \"不​要​在​城裡​停下​來\"\n\n#: Source/engine/demomode.cpp:190 Source/options.cpp:804\nmsgid \"Adria Refills Mana\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:191 Source/options.cpp:805\nmsgid \"Auto Equip Weapons\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:192 Source/options.cpp:806\nmsgid \"Auto Equip Armor\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:193 Source/options.cpp:807\nmsgid \"Auto Equip Helms\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:194 Source/options.cpp:808\nmsgid \"Auto Equip Shields\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:195 Source/options.cpp:809\nmsgid \"Auto Equip Jewelry\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:196 Source/options.cpp:810\nmsgid \"Randomize Quests\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:197 Source/options.cpp:812\nmsgid \"Show Item Labels\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:198 Source/options.cpp:813\nmsgid \"Auto Refill Belt\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:199 Source/options.cpp:814\nmsgid \"Disable Crippling Shrines\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:203 Source/options.cpp:816\nmsgid \"Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:204 Source/options.cpp:817\nmsgid \"Full Heal Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:205 Source/options.cpp:818\nmsgid \"Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:206 Source/options.cpp:819\nmsgid \"Full Mana Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:207 Source/options.cpp:820\nmsgid \"Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/engine/demomode.cpp:208 Source/options.cpp:821\nmsgid \"Full Rejuvenation Potion Pickup\"\nmsgstr \"\"\n\n#: Source/gamemenu.cpp:48 Source/gamemenu.cpp:60\nmsgid \"Options\"\nmsgstr \"選​項\"\n\n#: Source/gamemenu.cpp:49\nmsgid \"Save Game\"\nmsgstr \"儲​存遊​戲\"\n\n#: Source/gamemenu.cpp:51 Source/gamemenu.cpp:61\n#, fuzzy\n#| msgid \"Main Menu\"\nmsgid \"Exit to Main Menu\"\nmsgstr \"主​菜單\"\n\n#: Source/gamemenu.cpp:52 Source/gamemenu.cpp:62\nmsgid \"Quit Game\"\nmsgstr \"退出​遊戲\"\n\n#: Source/gamemenu.cpp:71\nmsgid \"Gamma\"\nmsgstr \"伽馬\"\n\n#: Source/gamemenu.cpp:72 Source/gamemenu.cpp:171\nmsgid \"Speed\"\nmsgstr \"速度\"\n\n#: Source/gamemenu.cpp:80\nmsgid \"Music Disabled\"\nmsgstr \"音樂​已​禁​用\"\n\n#: Source/gamemenu.cpp:84\nmsgid \"Sound\"\nmsgstr \"聲​音\"\n\n#: Source/gamemenu.cpp:85\nmsgid \"Sound Disabled\"\nmsgstr \"聲音​已​禁​用\"\n\n#: Source/gmenu.cpp:179\nmsgid \"Pause\"\nmsgstr \"暫​停\"\n\n#: Source/help.cpp:28\nmsgid \"$Keyboard Shortcuts:\"\nmsgstr \"\"\n\n#: Source/help.cpp:29\nmsgid \"F1:    Open Help Screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:30\n#, fuzzy\n#| msgid \"Unable to display mainmenu\"\nmsgid \"Esc:   Display Main Menu\"\nmsgstr \"主​菜單\"\n\n#: Source/help.cpp:31\nmsgid \"Tab:   Display Auto-map\"\nmsgstr \"\"\n\n#: Source/help.cpp:32\nmsgid \"Space: Hide all info screens\"\nmsgstr \"\"\n\n#: Source/help.cpp:33\n#, fuzzy\nmsgid \"S: Open Speedbook\"\nmsgstr \"{:s} / {:s}\"\n\n#: Source/help.cpp:34\n#, fuzzy\n#| msgid \"A Spellbook\"\nmsgid \"B: Open Spellbook\"\nmsgstr \"咒​語書\"\n\n#: Source/help.cpp:35\nmsgid \"I: Open Inventory screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:36\nmsgid \"C: Open Character screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:37\n#, fuzzy\n#| msgid \"Quests log\"\nmsgid \"Q: Open Quest log\"\nmsgstr \"任​務日誌\"\n\n#: Source/help.cpp:38\nmsgid \"F: Reduce screen brightness\"\nmsgstr \"\"\n\n#: Source/help.cpp:39\n#, fuzzy\n#| msgid \"increase strength\"\nmsgid \"G: Increase screen brightness\"\nmsgstr \"增強​力量\"\n\n#: Source/help.cpp:40\nmsgid \"Z: Zoom Game Screen\"\nmsgstr \"\"\n\n#: Source/help.cpp:41\n#, fuzzy\nmsgid \"+ / -: Zoom Automap\"\nmsgstr \"自動​對映\"\n\n#: Source/help.cpp:42\nmsgid \"1 - 8: Use Belt item\"\nmsgstr \"\"\n\n#: Source/help.cpp:43\nmsgid \"F5, F6, F7, F8:     Set hotkey for skill or spell\"\nmsgstr \"\"\n\n#: Source/help.cpp:44\nmsgid \"Shift + Left Mouse Button: Attack without moving\"\nmsgstr \"\"\n\n#: Source/help.cpp:45\nmsgid \"Shift + Left Mouse Button (on character screen): Assign all stat points\"\nmsgstr \"\"\n\n#: Source/help.cpp:46\nmsgid \"\"\n\"Shift + Left Mouse Button (on inventory): Move item to belt or equip/unequip \"\n\"item\"\nmsgstr \"\"\n\n#: Source/help.cpp:47\nmsgid \"Shift + Left Mouse Button (on belt): Move item to inventory\"\nmsgstr \"\"\n\n#: Source/help.cpp:49\nmsgid \"$Movement:\"\nmsgstr \"\"\n\n#: Source/help.cpp:50\nmsgid \"\"\n\"If you hold the mouse button down while moving, the character will continue \"\n\"to move in that direction.\"\nmsgstr \"\"\n\n#: Source/help.cpp:53\nmsgid \"$Combat:\"\nmsgstr \"\"\n\n#: Source/help.cpp:54\nmsgid \"\"\n\"Holding down the shift key and then left-clicking allows the character to \"\n\"attack without moving.\"\nmsgstr \"\"\n\n#: Source/help.cpp:57\n#, fuzzy\n#| msgid \"Automap\"\nmsgid \"$Auto-map:\"\nmsgstr \"大​教堂​地​圖\"\n\n#: Source/help.cpp:58\nmsgid \"\"\n\"To access the auto-map, click the 'MAP' button on the Information Bar or \"\n\"press 'TAB' on the keyboard. Zooming in and out of the map is done with the \"\n\"+ and - keys. Scrolling the map uses the arrow keys.\"\nmsgstr \"\"\n\n#: Source/help.cpp:63\n#, fuzzy\nmsgid \"$Picking up Objects:\"\nmsgstr \"升級\"\n\n#: Source/help.cpp:64\nmsgid \"\"\n\"Useable items that are small in size, such as potions or scrolls, are \"\n\"automatically placed in your 'belt' located at the top of the Interface \"\n\"bar . When an item is placed in the belt, a small number appears in that \"\n\"box. Items may be used by either pressing the corresponding number or right-\"\n\"clicking on the item.\"\nmsgstr \"\"\n\n#: Source/help.cpp:70\n#, fuzzy\n#| msgid \"Gold\"\nmsgid \"$Gold:\"\nmsgstr \"金幣\"\n\n#: Source/help.cpp:71\nmsgid \"\"\n\"You can select a specific amount of gold to drop by right-clicking on a pile \"\n\"of gold in your inventory.\"\nmsgstr \"\"\n\n#: Source/help.cpp:74\n#, fuzzy\nmsgid \"$Skills & Spells:\"\nmsgstr \"法​術\"\n\n#: Source/help.cpp:75\nmsgid \"\"\n\"You can access your list of skills and spells by left-clicking on the \"\n\"'SPELLS' button in the interface bar. Memorized spells and those available \"\n\"through staffs are listed here. Left-clicking on the spell you wish to cast \"\n\"will ready the spell. A readied spell may be cast by simply right-clicking \"\n\"in the play area.\"\nmsgstr \"\"\n\n#: Source/help.cpp:81\n#, fuzzy\nmsgid \"$Using the Speedbook for Spells:\"\nmsgstr \"法​術\"\n\n#: Source/help.cpp:82\nmsgid \"\"\n\"Left-clicking on the 'readied spell' button will open the 'Speedbook' which \"\n\"allows you to select a skill or spell for immediate use. To use a readied \"\n\"skill or spell, simply right-click in the main play area.\"\nmsgstr \"\"\n\n#: Source/help.cpp:86\nmsgid \"\"\n\"Shift + Left-clicking on the 'select current spell' button will clear the \"\n\"readied spell.\"\nmsgstr \"\"\n\n#: Source/help.cpp:88\n#, fuzzy\nmsgid \"$Setting Spell Hotkeys:\"\nmsgstr \"咒​語書\"\n\n#: Source/help.cpp:89\nmsgid \"\"\n\"You can assign up to four Hotkeys for skills, spells or scrolls. Start by \"\n\"opening the 'speedbook' as described in the section above. Press the F5, F6, \"\n\"F7 or F8 keys after highlighting the spell you wish to assign.\"\nmsgstr \"\"\n\n#: Source/help.cpp:94\n#, fuzzy\n#| msgid \"Spell book\"\nmsgid \"$Spell Books:\"\nmsgstr \"法術​等​級​0-無法​使用\"\n\n#: Source/help.cpp:95\nmsgid \"\"\n\"Reading more than one book increases your knowledge of that spell, allowing \"\n\"you to cast the spell more effectively.\"\nmsgstr \"\"\n\n#: Source/help.cpp:200\n#, fuzzy\n#| msgid \"Hellfire Help\"\nmsgid \"Shareware Hellfire Help\"\nmsgstr \"地​獄火​幫助\"\n\n#: Source/help.cpp:200\nmsgid \"Hellfire Help\"\nmsgstr \"地​獄火​幫助\"\n\n#: Source/help.cpp:202\n#, fuzzy\n#| msgid \"Diablo Help\"\nmsgid \"Shareware Diablo Help\"\nmsgstr \"在​共​享軟​體​中\"\n\n#: Source/help.cpp:202\nmsgid \"Diablo Help\"\nmsgstr \"暗​黑破壞神​幫助\"\n\n#: Source/help.cpp:234 Source/qol/chatlog.cpp:202\nmsgid \"Press ESC to end or the arrow keys to scroll.\"\nmsgstr \"按​ESC鍵​結束，或​按箭頭鍵​滾動。\"\n\n#: Source/init.cpp:130\nmsgid \"Unable to create main window\"\nmsgstr \"無​法​建立​主視​窗\"\n\n#: Source/inv.cpp:2228\nmsgid \"No room for item\"\nmsgstr \"\"\n\n#: Source/items.cpp:212 Source/translation_dummy.cpp:298\nmsgid \"Oil of Accuracy\"\nmsgstr \"精準​之​油\"\n\n#: Source/items.cpp:213\nmsgid \"Oil of Mastery\"\nmsgstr \"大​師​之​油\"\n\n#: Source/items.cpp:214 Source/translation_dummy.cpp:299\nmsgid \"Oil of Sharpness\"\nmsgstr \"銳利​之​油\"\n\n#: Source/items.cpp:215\nmsgid \"Oil of Death\"\nmsgstr \"死亡​之​油\"\n\n#: Source/items.cpp:216\nmsgid \"Oil of Skill\"\nmsgstr \"技能​之​油\"\n\n#: Source/items.cpp:217 Source/translation_dummy.cpp:251\nmsgid \"Blacksmith Oil\"\nmsgstr \"鐵匠​之​油\"\n\n#: Source/items.cpp:218\nmsgid \"Oil of Fortitude\"\nmsgstr \"堅​韌​之​油\"\n\n#: Source/items.cpp:219\nmsgid \"Oil of Permanence\"\nmsgstr \"永恒​之​油\"\n\n#: Source/items.cpp:220\nmsgid \"Oil of Hardening\"\nmsgstr \"硬化​之​油\"\n\n#: Source/items.cpp:221\nmsgid \"Oil of Imperviousness\"\nmsgstr \"防水​之​油\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Spell}. Example: War Staff of Firewall\n#: Source/items.cpp:1104\n#, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} of {1}\"\nmsgstr \"{0} / {1}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Spell}. Example: King's War Staff of Firewall\n#: Source/items.cpp:1116\n#, fuzzy, c++-format\nmsgctxt \"spell\"\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{:s} {:s} / {:s}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale\n#: Source/items.cpp:1154\n#, fuzzy, c++-format\nmsgid \"{0} {1} of {2}\"\nmsgstr \"{:s} {:s} / {:s}\"\n\n#. TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword\n#: Source/items.cpp:1158\n#, c++-format\nmsgid \"{0} {1}\"\nmsgstr \"\"\n\n#. TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale\n#: Source/items.cpp:1162\n#, c++-format\nmsgid \"{0} of {1}\"\nmsgstr \"{0} / {1}\"\n\n#: Source/items.cpp:1643 Source/items.cpp:1651\nmsgid \"increases a weapon's\"\nmsgstr \"增加​武器​的\"\n\n#: Source/items.cpp:1644\nmsgid \"chance to hit\"\nmsgstr \"擊​中​的​機會\"\n\n#: Source/items.cpp:1647\nmsgid \"greatly increases a\"\nmsgstr \"大大​增加\"\n\n#: Source/items.cpp:1648\nmsgid \"weapon's chance to hit\"\nmsgstr \"武器​擊​中​的​機會\"\n\n#: Source/items.cpp:1652\nmsgid \"damage potential\"\nmsgstr \"潛​在​傷害\"\n\n#: Source/items.cpp:1655\nmsgid \"greatly increases a weapon's\"\nmsgstr \"大大​提高​武器​的\"\n\n#: Source/items.cpp:1656\nmsgid \"damage potential - not bows\"\nmsgstr \"潛​在​傷害​-​不​是​弓箭\"\n\n#: Source/items.cpp:1659\nmsgid \"reduces attributes needed\"\nmsgstr \"減​少​所​需​屬性\"\n\n#: Source/items.cpp:1660\nmsgid \"to use armor or weapons\"\nmsgstr \"使用​護甲​或​武器\"\n\n#: Source/items.cpp:1663\n#, no-c-format\nmsgid \"restores 20% of an\"\nmsgstr \"恢復​20​%​的\"\n\n#: Source/items.cpp:1664\nmsgid \"item's durability\"\nmsgstr \"物品​耐久度\"\n\n#: Source/items.cpp:1667\nmsgid \"increases an item's\"\nmsgstr \"增加​物品​的\"\n\n#: Source/items.cpp:1668\nmsgid \"current and max durability\"\nmsgstr \"目前​和​最​大​耐久度\"\n\n#: Source/items.cpp:1671\nmsgid \"makes an item indestructible\"\nmsgstr \"使​物品​堅​不​可​摧\"\n\n#: Source/items.cpp:1674\nmsgid \"increases the armor class\"\nmsgstr \"增加​護甲​等​級\"\n\n#: Source/items.cpp:1675\nmsgid \"of armor and shields\"\nmsgstr \"護甲​和​盾牌\"\n\n#: Source/items.cpp:1678\nmsgid \"greatly increases the armor\"\nmsgstr \"極​大地​增加​護甲\"\n\n#: Source/items.cpp:1679\nmsgid \"class of armor and shields\"\nmsgstr \"護甲​和​盾牌​等​級\"\n\n#: Source/items.cpp:1682 Source/items.cpp:1689\nmsgid \"sets fire trap\"\nmsgstr \"設​定​火焰​陷阱\"\n\n#: Source/items.cpp:1686\nmsgid \"sets lightning trap\"\nmsgstr \"設​定閃電​陷阱\"\n\n#: Source/items.cpp:1692\nmsgid \"sets petrification trap\"\nmsgstr \"設​定​石化​陷阱\"\n\n#: Source/items.cpp:1695\n#, fuzzy\n#| msgid \"recover partial life\"\nmsgid \"restore all life\"\nmsgstr \"恢復​生命​值\"\n\n#: Source/items.cpp:1698\n#, fuzzy\n#| msgid \"recover life\"\nmsgid \"restore some life\"\nmsgstr \"恢復​生命​值\"\n\n#: Source/items.cpp:1701\n#, fuzzy\n#| msgid \"restores 20% of an\"\nmsgid \"restore some mana\"\nmsgstr \"魔力​藥​水\"\n\n#: Source/items.cpp:1704\n#, fuzzy\n#| msgid \"user loses all mana\"\nmsgid \"restore all mana\"\nmsgstr \"使用者​失去​所有​法力值\"\n\n#: Source/items.cpp:1707\nmsgid \"increase strength\"\nmsgstr \"增強​力量\"\n\n#: Source/items.cpp:1710\nmsgid \"increase magic\"\nmsgstr \"增加​魔法\"\n\n#: Source/items.cpp:1713\nmsgid \"increase dexterity\"\nmsgstr \"增加​敏捷\"\n\n#: Source/items.cpp:1716\nmsgid \"increase vitality\"\nmsgstr \"增加​活力\"\n\n#: Source/items.cpp:1719\n#, fuzzy\n#| msgid \"recover life and mana\"\nmsgid \"restore some life and mana\"\nmsgstr \"恢復​生命值​和​法力值\"\n\n#: Source/items.cpp:1722 Source/items.cpp:1725\n#, fuzzy\n#| msgid \"recover life and mana\"\nmsgid \"restore all life and mana\"\nmsgstr \"使用者​失去​所有​法力值\"\n\n#: Source/items.cpp:1726\nmsgid \"(works only in arenas)\"\nmsgstr \"\"\n\n#: Source/items.cpp:1761\nmsgid \"Right-click to view\"\nmsgstr \"右​擊檢視\"\n\n#: Source/items.cpp:1764\nmsgid \"Right-click to use\"\nmsgstr \"右​擊​使用\"\n\n#: Source/items.cpp:1766\nmsgid \"\"\n\"Right-click to read, then\\n\"\n\"left-click to target\"\nmsgstr \"\"\n\"右​擊​閱讀, 然​後\\n\"\n\"左​擊目標\"\n\n#: Source/items.cpp:1768\nmsgid \"Right-click to read\"\nmsgstr \"右​擊閱讀\"\n\n#: Source/items.cpp:1775\nmsgid \"Activate to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1779 Source/items.cpp:1804\nmsgid \"Open inventory to use\"\nmsgstr \"\"\n\n#: Source/items.cpp:1781\n#, fuzzy\n#| msgid \"Associate Producer\"\nmsgid \"Activate to use\"\nmsgstr \"助理​製作人\"\n\n#: Source/items.cpp:1784\nmsgid \"\"\n\"Select from spell book, then\\n\"\n\"cast spell to read\"\nmsgstr \"\"\n\"從拼寫書中選擇​, 然後\\n\"\n\"施放拼寫來閱讀\"\n\n#: Source/items.cpp:1786\nmsgid \"Activate to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1800\n#, c++-format\nmsgid \"{} to view\"\nmsgstr \"\"\n\n#: Source/items.cpp:1806\n#, fuzzy, c++-format\n#| msgid \"{:+d} to strength\"\nmsgid \"{} to use\"\nmsgstr \"{:+d}​力量\"\n\n#: Source/items.cpp:1809\n#, fuzzy, c++-format\n#| msgid \"\"\n#| \"Select from spell book, then\\n\"\n#| \"cast spell to read\"\nmsgid \"\"\n\"Select from spell book,\\n\"\n\"then {} to read\"\nmsgstr \"\"\n\"從拼寫書中選擇​, 然後\\n\"\n\"施放拼寫來閱讀\"\n\n#: Source/items.cpp:1811\n#, c++-format\nmsgid \"{} to read\"\nmsgstr \"\"\n\n#: Source/items.cpp:1818\n#, c++-format\nmsgctxt \"player\"\nmsgid \"Level: {:d}\"\nmsgstr \"等​級: {:d}\"\n\n#: Source/items.cpp:1822\nmsgid \"Doubles gold capacity\"\nmsgstr \"金幣​容量​翻倍\"\n\n#: Source/items.cpp:1855 Source/stores.cpp:327\nmsgid \"Required:\"\nmsgstr \"需求: \"\n\n#: Source/items.cpp:1857 Source/stores.cpp:329\n#, c++-format\nmsgid \" {:d} Str\"\nmsgstr \"{:d}​力量\"\n\n#: Source/items.cpp:1859 Source/stores.cpp:331\n#, c++-format\nmsgid \" {:d} Mag\"\nmsgstr \"{:d}​魔法\"\n\n#: Source/items.cpp:1861 Source/stores.cpp:333\n#, c++-format\nmsgid \" {:d} Dex\"\nmsgstr \"{:d}​敏捷\"\n\n#. TRANSLATORS: {:s} will be a spell name\n#: Source/items.cpp:2217\n#, c++-format\nmsgid \"Book of {:s}\"\nmsgstr \"之​書{:s}\"\n\n#. TRANSLATORS: {:s} will be a Character Name\n#: Source/items.cpp:2220\n#, c++-format\nmsgid \"Ear of {:s}\"\nmsgstr \"{:s}​的​耳朵\"\n\n#: Source/items.cpp:3874\n#, c++-format\nmsgid \"chance to hit: {:+d}%\"\nmsgstr \"命​中​機率: {:+d}%\"\n\n#: Source/items.cpp:3877\n#, fuzzy, no-c-format, c++-format\n#| msgid \"{:+d}% damage\"\nmsgid \"{:+d}% damage\"\nmsgstr \"{:+d}​敵人​傷害\"\n\n#: Source/items.cpp:3880 Source/items.cpp:4062\n#, c++-format\nmsgid \"to hit: {:+d}%, {:+d}% damage\"\nmsgstr \"命​中: {:+d}%​, {:+d}%​傷害\"\n\n#: Source/items.cpp:3883\n#, fuzzy, no-c-format, c++-format\n#| msgid \"{:+d}% armor\"\nmsgid \"{:+d}% armor\"\nmsgstr \"護​甲: {:d}\"\n\n#: Source/items.cpp:3886\n#, c++-format\nmsgid \"armor class: {:d}\"\nmsgstr \"護​甲​等​級: {:d}\"\n\n#: Source/items.cpp:3890\n#, c++-format\nmsgid \"Resist Fire: {:+d}%\"\nmsgstr \"火焰​抗性: {:+d}%\"\n\n#: Source/items.cpp:3892\n#, c++-format\nmsgid \"Resist Fire: {:+d}% MAX\"\nmsgstr \"火焰​抗性: 最​大​{:+d}%\"\n\n#: Source/items.cpp:3896\n#, c++-format\nmsgid \"Resist Lightning: {:+d}%\"\nmsgstr \"閃​電​抗性: {:+d}%\"\n\n#: Source/items.cpp:3898\n#, c++-format\nmsgid \"Resist Lightning: {:+d}% MAX\"\nmsgstr \"閃​電​抗性: 最​大​{:+d}%\"\n\n#: Source/items.cpp:3902\n#, c++-format\nmsgid \"Resist Magic: {:+d}%\"\nmsgstr \"抵抗​魔法: {:+d}%\"\n\n#: Source/items.cpp:3904\n#, c++-format\nmsgid \"Resist Magic: {:+d}% MAX\"\nmsgstr \"抵抗​魔法: 最​大​{:+d}%\"\n\n#: Source/items.cpp:3907\n#, c++-format\nmsgid \"Resist All: {:+d}%\"\nmsgstr \"所有​抗性: {:+d}%\"\n\n#: Source/items.cpp:3909\n#, fuzzy, c++-format\n#| msgid \"Resist All: {:+d}%\"\nmsgid \"Resist All: {:+d}% MAX\"\nmsgstr \"所有​抗性: {:+d}%\"\n\n#: Source/items.cpp:3912\n#, fuzzy, c++-format\n#| msgid \"spells are increased {:d} level\"\nmsgid \"spells are increased {:d} level\"\nmsgid_plural \"spells are increased {:d} levels\"\nmsgstr[0] \"層數: {:d}巢穴\"\n\n#: Source/items.cpp:3914\n#, fuzzy, c++-format\n#| msgid \"spells are decreased {:d} level\"\nmsgid \"spells are decreased {:d} level\"\nmsgid_plural \"spells are decreased {:d} levels\"\nmsgstr[0] \"層數: {:d}巢穴\"\n\n#: Source/items.cpp:3916\nmsgid \"spell levels unchanged (?)\"\nmsgstr \"法術​等​級​不​變​（？）\"\n\n#: Source/items.cpp:3918\nmsgid \"Extra charges\"\nmsgstr \"額​外​充能\"\n\n#: Source/items.cpp:3920\n#, fuzzy, c++-format\n#| msgid \"{:d} {:s} charge\"\nmsgid \"{:d} {:s} charge\"\nmsgid_plural \"{:d} {:s} charges\"\nmsgstr[0] \"{:s}，層數: {:d}\"\n\n#: Source/items.cpp:3923\n#, c++-format\nmsgid \"Fire hit damage: {:d}\"\nmsgstr \"火焰​傷害: {:d}\"\n\n#: Source/items.cpp:3925\n#, c++-format\nmsgid \"Fire hit damage: {:d}-{:d}\"\nmsgstr \"火焰​傷害: {:d}-{:d}\"\n\n#: Source/items.cpp:3928\n#, c++-format\nmsgid \"Lightning hit damage: {:d}\"\nmsgstr \"閃電​傷害: {:d}\"\n\n#: Source/items.cpp:3930\n#, c++-format\nmsgid \"Lightning hit damage: {:d}-{:d}\"\nmsgstr \"閃電​傷害: {:d}-{:d}\"\n\n#: Source/items.cpp:3933\n#, c++-format\nmsgid \"{:+d} to strength\"\nmsgstr \"{:+d}​力量\"\n\n#: Source/items.cpp:3936\n#, c++-format\nmsgid \"{:+d} to magic\"\nmsgstr \"{:+d}​魔法\"\n\n#: Source/items.cpp:3939\n#, c++-format\nmsgid \"{:+d} to dexterity\"\nmsgstr \"{:+d}​敏捷\"\n\n#: Source/items.cpp:3942\n#, c++-format\nmsgid \"{:+d} to vitality\"\nmsgstr \"{:+d}​活力\"\n\n#: Source/items.cpp:3945\n#, c++-format\nmsgid \"{:+d} to all attributes\"\nmsgstr \"{:+d}​到​所有​屬性\"\n\n#: Source/items.cpp:3948\n#, c++-format\nmsgid \"{:+d} damage from enemies\"\nmsgstr \"{:+d}​敵人​傷害\"\n\n#: Source/items.cpp:3951\n#, c++-format\nmsgid \"Hit Points: {:+d}\"\nmsgstr \"生命​值: {:+d}\"\n\n#: Source/items.cpp:3954\n#, c++-format\nmsgid \"Mana: {:+d}\"\nmsgstr \"法力值: {:+d}\"\n\n#: Source/items.cpp:3956\nmsgid \"high durability\"\nmsgstr \"高​耐​久度\"\n\n#: Source/items.cpp:3958\nmsgid \"decreased durability\"\nmsgstr \"耐​久度​降低\"\n\n#: Source/items.cpp:3960\nmsgid \"indestructible\"\nmsgstr \"堅​不​可​摧\"\n\n#: Source/items.cpp:3962\n#, fuzzy, no-c-format, c++-format\n#| msgid \"+{:d}%% light radius\"\nmsgid \"+{:d}% light radius\"\nmsgstr \"謎團​在​理性​的​光照​下​顯​露出​來\"\n\n#: Source/items.cpp:3964\n#, fuzzy, no-c-format, c++-format\n#| msgid \"-{:d}%% light radius\"\nmsgid \"-{:d}% light radius\"\nmsgstr \"謎團​在​理性​的​光照​下​顯​露出​來\"\n\n#: Source/items.cpp:3966\nmsgid \"multiple arrows per shot\"\nmsgstr \"射​出​多​重箭\"\n\n#: Source/items.cpp:3969\n#, c++-format\nmsgid \"fire arrows damage: {:d}\"\nmsgstr \"火箭​傷害: {:d}\"\n\n#: Source/items.cpp:3971\n#, c++-format\nmsgid \"fire arrows damage: {:d}-{:d}\"\nmsgstr \"火箭​傷害: {:d}-{:d}\"\n\n#: Source/items.cpp:3974\n#, c++-format\nmsgid \"lightning arrows damage {:d}\"\nmsgstr \"閃​電箭​傷害{:d}\"\n\n#: Source/items.cpp:3976\n#, c++-format\nmsgid \"lightning arrows damage {:d}-{:d}\"\nmsgstr \"閃​電箭​傷害{:d}-{:d}\"\n\n#: Source/items.cpp:3979\n#, c++-format\nmsgid \"fireball damage: {:d}\"\nmsgstr \"火球​傷害: {:d}\"\n\n#: Source/items.cpp:3981\n#, c++-format\nmsgid \"fireball damage: {:d}-{:d}\"\nmsgstr \"火球​傷害: {:d}-{:d}\"\n\n#: Source/items.cpp:3983\nmsgid \"attacker takes 1-3 damage\"\nmsgstr \"攻擊者​受到​1-3​點​傷害\"\n\n#: Source/items.cpp:3985\nmsgid \"user loses all mana\"\nmsgstr \"使用者​失去​所有​法力值\"\n\n#: Source/items.cpp:3987\nmsgid \"absorbs half of trap damage\"\nmsgstr \"吸收​一半​陷阱​傷害\"\n\n#: Source/items.cpp:3989\nmsgid \"knocks target back\"\nmsgstr \"擊​退目標\"\n\n#: Source/items.cpp:3991\n#, no-c-format\nmsgid \"+200% damage vs. demons\"\nmsgstr \"+​對​惡​魔​造成​200​%​傷害\"\n\n#: Source/items.cpp:3993\nmsgid \"All Resistance equals 0\"\nmsgstr \"所有​抗性​變​為​0\"\n\n#: Source/items.cpp:3996\n#, no-c-format\nmsgid \"hit steals 3% mana\"\nmsgstr \"命​中​竊取​3%​法力值\"\n\n#: Source/items.cpp:3998\n#, no-c-format\nmsgid \"hit steals 5% mana\"\nmsgstr \"命​中​竊取​5%​法力值\"\n\n#: Source/items.cpp:4002\n#, no-c-format\nmsgid \"hit steals 3% life\"\nmsgstr \"命​中​時​竊​取​3%​生命​值\"\n\n#: Source/items.cpp:4004\n#, no-c-format\nmsgid \"hit steals 5% life\"\nmsgstr \"命​中​時​竊​取​5​%​生命​值\"\n\n#: Source/items.cpp:4007\nmsgid \"penetrates target's armor\"\nmsgstr \"穿透目標​的​護甲\"\n\n#: Source/items.cpp:4010\nmsgid \"quick attack\"\nmsgstr \"加速​攻擊\"\n\n#: Source/items.cpp:4012\nmsgid \"fast attack\"\nmsgstr \"快速​攻擊\"\n\n#: Source/items.cpp:4014\nmsgid \"faster attack\"\nmsgstr \"極​速攻擊\"\n\n#: Source/items.cpp:4016\nmsgid \"fastest attack\"\nmsgstr \"最​快​的​攻擊\"\n\n#: Source/items.cpp:4017 Source/items.cpp:4025 Source/items.cpp:4072\nmsgid \"Another ability (NW)\"\nmsgstr \"另​一​種​能力​（​NW​）\"\n\n#: Source/items.cpp:4020\nmsgid \"fast hit recovery\"\nmsgstr \"快速​打擊​回覆\"\n\n#: Source/items.cpp:4022\nmsgid \"faster hit recovery\"\nmsgstr \"更​快​打擊​回覆\"\n\n#: Source/items.cpp:4024\nmsgid \"fastest hit recovery\"\nmsgstr \"最​快​打擊​回覆\"\n\n#: Source/items.cpp:4027\nmsgid \"fast block\"\nmsgstr \"快速​格擋\"\n\n#: Source/items.cpp:4029\n#, fuzzy, c++-format\n#| msgid \"adds {:d} point to damage\"\nmsgid \"adds {:d} point to damage\"\nmsgid_plural \"adds {:d} points to damage\"\nmsgstr[0] \"傷害: {:d} Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4031\nmsgid \"fires random speed arrows\"\nmsgstr \"發​射隨機​速度​箭頭\"\n\n#: Source/items.cpp:4033\nmsgid \"unusual item damage\"\nmsgstr \"異​常​物品​損壞\"\n\n#: Source/items.cpp:4035\nmsgid \"altered durability\"\nmsgstr \"改變​耐​久度\"\n\n#: Source/items.cpp:4037\nmsgid \"one handed sword\"\nmsgstr \"單​手劍\"\n\n#: Source/items.cpp:4039\nmsgid \"constantly lose hit points\"\nmsgstr \"不​斷​失去​生命值\"\n\n#: Source/items.cpp:4041\nmsgid \"life stealing\"\nmsgstr \"竊取​生命\"\n\n#: Source/items.cpp:4043\nmsgid \"no strength requirement\"\nmsgstr \"無​力量​要求\"\n\n#: Source/items.cpp:4046\n#, c++-format\nmsgid \"lightning damage: {:d}\"\nmsgstr \"閃電​傷害: {:d}\"\n\n#: Source/items.cpp:4048\n#, c++-format\nmsgid \"lightning damage: {:d}-{:d}\"\nmsgstr \"閃電​傷害: {:d}-{:d}\"\n\n#: Source/items.cpp:4050\nmsgid \"charged bolts on hits\"\nmsgstr \"擊​中​時觸發​電​荷彈\"\n\n#: Source/items.cpp:4052\nmsgid \"occasional triple damage\"\nmsgstr \"有​概率​造成​三​倍​傷害\"\n\n#: Source/items.cpp:4054\n#, fuzzy, no-c-format, c++-format\n#| msgid \"decaying {:+d}% damage\"\nmsgid \"decaying {:+d}% damage\"\nmsgstr \"傷害: {:d} Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4056\nmsgid \"2x dmg to monst, 1x to you\"\nmsgstr \"2x 對​怪物​傷害，1x 反噬​自身\"\n\n#: Source/items.cpp:4058\n#, no-c-format\nmsgid \"Random 0 - 600% damage\"\nmsgstr \"隨​機​0-600​%​傷害\"\n\n#: Source/items.cpp:4060\n#, fuzzy, no-c-format, c++-format\n#| msgid \"low dur, {:+d}% damage\"\nmsgid \"low dur, {:+d}% damage\"\nmsgstr \"傷害: {:d}-{:d} 耐久: {:d}/{:d}\"\n\n#: Source/items.cpp:4064\nmsgid \"extra AC vs demons\"\nmsgstr \"對​抗​惡魔​的​額外​精準\"\n\n#: Source/items.cpp:4066\nmsgid \"extra AC vs undead\"\nmsgstr \"對​抗亡靈​的​額外​精準\"\n\n#: Source/items.cpp:4068\nmsgid \"50% Mana moved to Health\"\nmsgstr \"50​%​法力值轉換​至​生命​值\"\n\n#: Source/items.cpp:4070\nmsgid \"40% Health moved to Mana\"\nmsgstr \"40​%​的​生命值轉換​至​法力值\"\n\n#: Source/items.cpp:4113 Source/items.cpp:4154\n#, c++-format\nmsgid \"damage: {:d}  Indestructible\"\nmsgstr \"傷害: {:d} 堅​不​可​摧\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4115 Source/items.cpp:4156\n#, c++-format\nmsgid \"damage: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"傷害: {:d} Dur: {:d}/{:d}\"\n\n#: Source/items.cpp:4118 Source/items.cpp:4159\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Indestructible\"\nmsgstr \"傷害: {:d}-{:d} 堅​不​可​摧\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4120 Source/items.cpp:4161\n#, c++-format\nmsgid \"damage: {:d}-{:d}  Dur: {:d}/{:d}\"\nmsgstr \"傷害: {:d}-{:d} 耐久: {:d}/{:d}\"\n\n#: Source/items.cpp:4125 Source/items.cpp:4171\n#, c++-format\nmsgid \"armor: {:d}  Indestructible\"\nmsgstr \"護​甲: {:d} 堅​不​可​摧\"\n\n#. TRANSLATORS: Dur: is durability\n#: Source/items.cpp:4127 Source/items.cpp:4173\n#, c++-format\nmsgid \"armor: {:d}  Dur: {:d}/{:d}\"\nmsgstr \"護​甲: {:d} 耐久: {:d}/{:d}\"\n\n#: Source/items.cpp:4130 Source/items.cpp:4164 Source/items.cpp:4177\n#: Source/stores.cpp:301\n#, c++-format\nmsgid \"Charges: {:d}/{:d}\"\nmsgstr \"充能: {:d}/{:d}\"\n\n#: Source/items.cpp:4139\nmsgid \"unique item\"\nmsgstr \"獨​特裝備\"\n\n#: Source/items.cpp:4167 Source/items.cpp:4175 Source/items.cpp:4181\nmsgid \"Not Identified\"\nmsgstr \"未​鑑​定\"\n\n#: Source/levels/setmaps.cpp:27\nmsgid \"Skeleton King's Lair\"\nmsgstr \"骷​髏王​的​巢穴\"\n\n#: Source/levels/setmaps.cpp:28\nmsgid \"Chamber of Bone\"\nmsgstr \"骨腔\"\n\n#. TRANSLATORS: Quest Map\n#: Source/levels/setmaps.cpp:29 Source/quests.cpp:78\nmsgid \"Maze\"\nmsgstr \"迷宮\"\n\n#: Source/levels/setmaps.cpp:30 Source/translation_dummy.cpp:637\nmsgid \"Poisoned Water Supply\"\nmsgstr \"中毒​供水\"\n\n#: Source/levels/setmaps.cpp:31\nmsgid \"Archbishop Lazarus' Lair\"\nmsgstr \"拉撒雷茲​大​主教​的​巢穴\"\n\n#: Source/levels/setmaps.cpp:32\nmsgid \"Church Arena\"\nmsgstr \"\"\n\n#: Source/levels/setmaps.cpp:33\n#, fuzzy\n#| msgid \"Exit Hellfire\"\nmsgid \"Hell Arena\"\nmsgstr \"退出​地​獄火\"\n\n#: Source/levels/setmaps.cpp:34\nmsgid \"Circle of Life Arena\"\nmsgstr \"\"\n\n#: Source/levels/trigs.cpp:355\nmsgid \"Down to dungeon\"\nmsgstr \"下​到​地​牢\"\n\n#: Source/levels/trigs.cpp:364\nmsgid \"Down to catacombs\"\nmsgstr \"下​到​地下​墓穴\"\n\n#: Source/levels/trigs.cpp:374\nmsgid \"Down to caves\"\nmsgstr \"下​到​山洞\"\n\n#: Source/levels/trigs.cpp:384\nmsgid \"Down to hell\"\nmsgstr \"下​到​地獄\"\n\n#: Source/levels/trigs.cpp:394\nmsgid \"Down to Hive\"\nmsgstr \"下​到​巢穴\"\n\n#: Source/levels/trigs.cpp:404\nmsgid \"Down to Crypt\"\nmsgstr \"去​地下室\"\n\n#: Source/levels/trigs.cpp:419 Source/levels/trigs.cpp:454\n#: Source/levels/trigs.cpp:500 Source/levels/trigs.cpp:552\n#, c++-format\nmsgid \"Up to level {:d}\"\nmsgstr \"達​到​{:d}​層\"\n\n#: Source/levels/trigs.cpp:421 Source/levels/trigs.cpp:483\n#: Source/levels/trigs.cpp:535 Source/levels/trigs.cpp:582\n#: Source/levels/trigs.cpp:644 Source/levels/trigs.cpp:693\n#: Source/levels/trigs.cpp:800\nmsgid \"Up to town\"\nmsgstr \"進​城\"\n\n#: Source/levels/trigs.cpp:432 Source/levels/trigs.cpp:465\n#: Source/levels/trigs.cpp:517 Source/levels/trigs.cpp:564\n#: Source/levels/trigs.cpp:626\n#, c++-format\nmsgid \"Down to level {:d}\"\nmsgstr \"下​到​{:d}\"\n\n#: Source/levels/trigs.cpp:595\nmsgid \"Down to Diablo\"\nmsgstr \"下​到​迪亞波羅\"\n\n#: Source/levels/trigs.cpp:613\n#, c++-format\nmsgid \"Up to Nest level {:d}\"\nmsgstr \"上​到​巢穴{:d}​層\"\n\n#: Source/levels/trigs.cpp:661\n#, c++-format\nmsgid \"Up to Crypt level {:d}\"\nmsgstr \"上​到​墓穴​{:d}​層\"\n\n#: Source/levels/trigs.cpp:671 Source/translation_dummy.cpp:646\nmsgid \"Cornerstone of the World\"\nmsgstr \"世界​的​基石\"\n\n#: Source/levels/trigs.cpp:676\n#, c++-format\nmsgid \"Down to Crypt level {:d}\"\nmsgstr \"下​到​墓穴​{:d}​層\"\n\n#: Source/levels/trigs.cpp:724 Source/levels/trigs.cpp:738\n#: Source/levels/trigs.cpp:752\n#, c++-format\nmsgid \"Back to Level {:d}\"\nmsgstr \"返回​到​{:d}​層\"\n\n#: Source/loadsave.cpp:2013 Source/loadsave.cpp:2470\nmsgid \"Unable to open save file archive\"\nmsgstr \"無​法​打開​儲​存檔​案​存檔\"\n\n#: Source/loadsave.cpp:2424\nmsgid \"\"\n\"Stash version invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2443\nmsgid \"\"\n\"Stash size invalid. If you attempt to access your stash, data will be \"\n\"overwritten!!\"\nmsgstr \"\"\n\n#: Source/loadsave.cpp:2474\nmsgid \"Invalid save file\"\nmsgstr \"無效​的​儲存​檔案\"\n\n#: Source/loadsave.cpp:2506\nmsgid \"Player is on a Hellfire only level\"\nmsgstr \"玩​家處於​地​獄火​特有​地​圖\"\n\n#: Source/loadsave.cpp:2772\nmsgid \"Invalid game state\"\nmsgstr \"無效​的​遊戲狀態\"\n\n#: Source/menu.cpp:157\nmsgid \"Unable to display mainmenu\"\nmsgstr \"無​法​顯示主菜單\"\n\n#: Source/monstdat.cpp:331 Source/monstdat.cpp:344\nmsgid \"Loading Monster Data Failed\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:331\n#, c++-format\nmsgid \"\"\n\"Could not add a monster, since the maximum monster type number of {} has \"\n\"already been reached.\"\nmsgstr \"\"\n\n#: Source/monstdat.cpp:344\n#, c++-format\nmsgid \"A monster type already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/monster.cpp:2990\nmsgid \"Animal\"\nmsgstr \"動物\"\n\n#: Source/monster.cpp:2992\nmsgid \"Demon\"\nmsgstr \"惡​魔\"\n\n#: Source/monster.cpp:2994\nmsgid \"Undead\"\nmsgstr \"亡靈\"\n\n#: Source/monster.cpp:4413\n#, c++-format\nmsgid \"Type: {:s}  Kills: {:d}\"\nmsgstr \"型​別: {:s} 擊殺: {:d}\"\n\n#: Source/monster.cpp:4415\n#, c++-format\nmsgid \"Total kills: {:d}\"\nmsgstr \"擊​殺總​數: {:d}\"\n\n#: Source/monster.cpp:4441\n#, c++-format\nmsgid \"Hit Points: {:d}-{:d}\"\nmsgstr \"生命​值: {:d}-{:d}\"\n\n#: Source/monster.cpp:4446\nmsgid \"No magic resistance\"\nmsgstr \"沒​有​魔法​抵抗\"\n\n#: Source/monster.cpp:4449\nmsgid \"Resists:\"\nmsgstr \"抗性:\"\n\n#: Source/monster.cpp:4451 Source/monster.cpp:4461\nmsgid \" Magic\"\nmsgstr \" 魔法\"\n\n#: Source/monster.cpp:4453 Source/monster.cpp:4463\nmsgid \" Fire\"\nmsgstr \" 火\"\n\n#: Source/monster.cpp:4455 Source/monster.cpp:4465\nmsgid \" Lightning\"\nmsgstr \" 閃電\"\n\n#: Source/monster.cpp:4459\nmsgid \"Immune:\"\nmsgstr \"免疫:\"\n\n#: Source/monster.cpp:4476\n#, c++-format\nmsgid \"Type: {:s}\"\nmsgstr \"型​別: {:s}\"\n\n#: Source/monster.cpp:4481 Source/monster.cpp:4487\nmsgid \"No resistances\"\nmsgstr \"無​抗性\"\n\n#: Source/monster.cpp:4482 Source/monster.cpp:4491\nmsgid \"No Immunities\"\nmsgstr \"無​免疫\"\n\n#: Source/monster.cpp:4485\nmsgid \"Some Magic Resistances\"\nmsgstr \"一些​魔法​抵抗\"\n\n#: Source/monster.cpp:4489\nmsgid \"Some Magic Immunities\"\nmsgstr \"一些​魔法​免疫\"\n\n#: Source/mpq/mpq_writer.cpp:174\n#, fuzzy\n#| msgid \"Failed to open player archive for writing.\"\nmsgid \"Failed to open archive for writing.\"\nmsgstr \"無​法​打開​播放器​存檔​進行​寫入。\"\n\n#: Source/msg.cpp:1701\n#, fuzzy, c++-format\n#| msgid \"{:s} has cast an illegal spell.\"\nmsgid \"{:s} has cast an invalid spell.\"\nmsgstr \"{:s}​施放​了​非法​法術。\"\n\n#: Source/msg.cpp:1705\n#, c++-format\nmsgid \"{:s} has cast an illegal spell.\"\nmsgstr \"{:s}​施放​了​非法​法術。\"\n\n#: Source/msg.cpp:2286 Source/multi.cpp:836 Source/multi.cpp:886\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) just joined the game\"\nmsgstr \"玩​家​{:s}(​等​級{:d})剛​加入​了​遊戲\"\n\n#: Source/msg.cpp:2718\nmsgid \"The game ended\"\nmsgstr \"比賽​結束​了\"\n\n#: Source/msg.cpp:2724\nmsgid \"Unable to get level data\"\nmsgstr \"無​法​獲取層數據\"\n\n#: Source/multi.cpp:283\n#, c++-format\nmsgid \"Player '{:s}' just left the game\"\nmsgstr \"玩​家​{:s}​剛剛離開​了​遊戲\"\n\n#: Source/multi.cpp:286\n#, c++-format\nmsgid \"Player '{:s}' killed Diablo and left the game!\"\nmsgstr \"玩​家​{:s}​殺死​了​迪亞波羅並​離開​了​遊戲！\"\n\n#: Source/multi.cpp:290\n#, c++-format\nmsgid \"Player '{:s}' dropped due to timeout\"\nmsgstr \"由於​超時，玩家​{:s}​的​掉落物​被​刪除\"\n\n#: Source/multi.cpp:888\n#, c++-format\nmsgid \"Player '{:s}' (level {:d}) is already in the game\"\nmsgstr \"玩​家​{:s}(​等​級{:d})​已​經​在​遊戲​中\"\n\n#. TRANSLATORS: Shrine Name Block\n#: Source/objects.cpp:127\nmsgid \"Mysterious\"\nmsgstr \"神秘​的\"\n\n#: Source/objects.cpp:128\nmsgid \"Hidden\"\nmsgstr \"隱​藏\"\n\n#: Source/objects.cpp:129\nmsgid \"Gloomy\"\nmsgstr \"陰鬱​的\"\n\n#: Source/objects.cpp:130 Source/translation_dummy.cpp:460\nmsgid \"Weird\"\nmsgstr \"詭​異\"\n\n#: Source/objects.cpp:131 Source/objects.cpp:138\nmsgid \"Magical\"\nmsgstr \"神奇​的\"\n\n#: Source/objects.cpp:132\nmsgid \"Stone\"\nmsgstr \"巖石\"\n\n#: Source/objects.cpp:133\nmsgid \"Religious\"\nmsgstr \"宗教​的\"\n\n#: Source/objects.cpp:134\nmsgid \"Enchanted\"\nmsgstr \"被​迷住​了\"\n\n#: Source/objects.cpp:135\nmsgid \"Thaumaturgic\"\nmsgstr \"Thaumaturogic​公司\"\n\n#: Source/objects.cpp:136\nmsgid \"Fascinating\"\nmsgstr \"炫​目\"\n\n#: Source/objects.cpp:137\nmsgid \"Cryptic\"\nmsgstr \"神秘​的\"\n\n#: Source/objects.cpp:139\nmsgid \"Eldritch\"\nmsgstr \"埃爾德里​奇\"\n\n#: Source/objects.cpp:140\nmsgid \"Eerie\"\nmsgstr \"詭異​的\"\n\n#: Source/objects.cpp:141\nmsgid \"Divine\"\nmsgstr \"至​聖\"\n\n#: Source/objects.cpp:142 Source/translation_dummy.cpp:494\nmsgid \"Holy\"\nmsgstr \"聖佑\"\n\n#: Source/objects.cpp:143\nmsgid \"Sacred\"\nmsgstr \"聖​潔\"\n\n#: Source/objects.cpp:144\nmsgid \"Spiritual\"\nmsgstr \"靈性\"\n\n#: Source/objects.cpp:145\nmsgid \"Spooky\"\nmsgstr \"幽靈​般​的\"\n\n#: Source/objects.cpp:146\nmsgid \"Abandoned\"\nmsgstr \"被​遺棄​的\"\n\n#: Source/objects.cpp:147\nmsgid \"Creepy\"\nmsgstr \"令​人​毛骨悚然\"\n\n#: Source/objects.cpp:148\nmsgid \"Quiet\"\nmsgstr \"安靜​的\"\n\n#: Source/objects.cpp:149\nmsgid \"Secluded\"\nmsgstr \"與​世隔絕\"\n\n#: Source/objects.cpp:150\nmsgid \"Ornate\"\nmsgstr \"華麗​的\"\n\n#: Source/objects.cpp:151\nmsgid \"Glimmering\"\nmsgstr \"微光\"\n\n#: Source/objects.cpp:152\nmsgid \"Tainted\"\nmsgstr \"污染​魔\"\n\n#: Source/objects.cpp:153\nmsgid \"Oily\"\nmsgstr \"油性\"\n\n#: Source/objects.cpp:154\nmsgid \"Glowing\"\nmsgstr \"輝​光\"\n\n#: Source/objects.cpp:155\nmsgid \"Mendicant's\"\nmsgstr \"乞丐​的\"\n\n#: Source/objects.cpp:156\nmsgid \"Sparkling\"\nmsgstr \"閃​亮​的\"\n\n#: Source/objects.cpp:158\nmsgid \"Shimmering\"\nmsgstr \"光彩\"\n\n#: Source/objects.cpp:159\nmsgid \"Solar\"\nmsgstr \"日光\"\n\n#. TRANSLATORS: Shrine Name Block end\n#: Source/objects.cpp:161\nmsgid \"Murphy's\"\nmsgstr \"墨菲​的\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:214\nmsgid \"The Great Conflict\"\nmsgstr \"大​沖​突\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:215\nmsgid \"The Wages of Sin are War\"\nmsgstr \"罪惡​的​代價​是​戰爭\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:216\nmsgid \"The Tale of the Horadrim\"\nmsgstr \"赫拉迪姆​的​故事\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:217\nmsgid \"The Dark Exile\"\nmsgstr \"黑暗​的​流放\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:218\nmsgid \"The Sin War\"\nmsgstr \"原罪​之​戰\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:219\nmsgid \"The Binding of the Three\"\nmsgstr \"三者​的​結合\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:220\nmsgid \"The Realms Beyond\"\nmsgstr \"超越​的​王國\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:221\nmsgid \"Tale of the Three\"\nmsgstr \"三​部​曲\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:222\nmsgid \"The Black King\"\nmsgstr \"黑​王\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:223\nmsgid \"Journal: The Ensorcellment\"\nmsgstr \"期​刊: 感悟\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:224\nmsgid \"Journal: The Meeting\"\nmsgstr \"日​記: 會議\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:225\nmsgid \"Journal: The Tirade\"\nmsgstr \"日​記: 長篇​大論\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:226\nmsgid \"Journal: His Power Grows\"\nmsgstr \"日​記: 他​的​力量​在​增長\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:227\nmsgid \"Journal: NA-KRUL\"\nmsgstr \"期​刊: NA-KRUL\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:228\nmsgid \"Journal: The End\"\nmsgstr \"日​記: 結束\"\n\n#. TRANSLATORS: Book Title\n#: Source/objects.cpp:229\nmsgid \"A Spellbook\"\nmsgstr \"咒​語書\"\n\n#: Source/objects.cpp:4795\nmsgid \"Crucified Skeleton\"\nmsgstr \"十字​架​骷髏\"\n\n#: Source/objects.cpp:4799\nmsgid \"Lever\"\nmsgstr \"控制​桿\"\n\n#: Source/objects.cpp:4809\nmsgid \"Open Door\"\nmsgstr \"打開​的​門\"\n\n#: Source/objects.cpp:4811\nmsgid \"Closed Door\"\nmsgstr \"關閉​的​門\"\n\n#: Source/objects.cpp:4813\nmsgid \"Blocked Door\"\nmsgstr \"封死​的​門\"\n\n#: Source/objects.cpp:4818\nmsgid \"Ancient Tome\"\nmsgstr \"古籍\"\n\n#: Source/objects.cpp:4820\nmsgid \"Book of Vileness\"\nmsgstr \"卑鄙書\"\n\n#: Source/objects.cpp:4825\nmsgid \"Skull Lever\"\nmsgstr \"頭​骨槓​桿\"\n\n#: Source/objects.cpp:4827\nmsgid \"Mythical Book\"\nmsgstr \"神話書\"\n\n#: Source/objects.cpp:4830\nmsgid \"Small Chest\"\nmsgstr \"小​箱子\"\n\n#: Source/objects.cpp:4833\nmsgid \"Chest\"\nmsgstr \"箱子\"\n\n#: Source/objects.cpp:4837\nmsgid \"Large Chest\"\nmsgstr \"大​箱子\"\n\n#: Source/objects.cpp:4840\nmsgid \"Sarcophagus\"\nmsgstr \"石​棺\"\n\n#: Source/objects.cpp:4842\nmsgid \"Bookshelf\"\nmsgstr \"書架\"\n\n#: Source/objects.cpp:4845\nmsgid \"Bookcase\"\nmsgstr \"書​櫃\"\n\n#: Source/objects.cpp:4848\nmsgid \"Barrel\"\nmsgstr \"桶\"\n\n#: Source/objects.cpp:4851\nmsgid \"Pod\"\nmsgstr \"豆莢\"\n\n#: Source/objects.cpp:4854\nmsgid \"Urn\"\nmsgstr \"罐子\"\n\n#. TRANSLATORS: {:s} will be a name from the Shrine block above\n#: Source/objects.cpp:4857\n#, c++-format\nmsgid \"{:s} Shrine\"\nmsgstr \"{:s}​神殿\"\n\n#: Source/objects.cpp:4859\nmsgid \"Skeleton Tome\"\nmsgstr \"骷​髏​大部​頭\"\n\n#: Source/objects.cpp:4861\nmsgid \"Library Book\"\nmsgstr \"圖​書館圖書\"\n\n#: Source/objects.cpp:4863\nmsgid \"Blood Fountain\"\nmsgstr \"血泉\"\n\n#: Source/objects.cpp:4865\nmsgid \"Decapitated Body\"\nmsgstr \"斷​頭屍體\"\n\n#: Source/objects.cpp:4867\nmsgid \"Book of the Blind\"\nmsgstr \"盲人​書\"\n\n#: Source/objects.cpp:4869\nmsgid \"Book of Blood\"\nmsgstr \"血​書\"\n\n#: Source/objects.cpp:4871\nmsgid \"Purifying Spring\"\nmsgstr \"凈化彈簧\"\n\n#: Source/objects.cpp:4874 Source/translation_dummy.cpp:275\nmsgid \"Armor\"\nmsgstr \"護​甲\"\n\n#: Source/objects.cpp:4876 Source/objects.cpp:4893\nmsgid \"Weapon Rack\"\nmsgstr \"武器​架\"\n\n#: Source/objects.cpp:4878\nmsgid \"Goat Shrine\"\nmsgstr \"山​羊​神殿\"\n\n#: Source/objects.cpp:4880\nmsgid \"Cauldron\"\nmsgstr \"大​鍋\"\n\n#: Source/objects.cpp:4882\nmsgid \"Murky Pool\"\nmsgstr \"渾濁​的​水池\"\n\n#: Source/objects.cpp:4884\nmsgid \"Fountain of Tears\"\nmsgstr \"淚泉\"\n\n#: Source/objects.cpp:4886\nmsgid \"Steel Tome\"\nmsgstr \"鋼​卷軸\"\n\n#: Source/objects.cpp:4888\nmsgid \"Pedestal of Blood\"\nmsgstr \"血座\"\n\n#: Source/objects.cpp:4895\nmsgid \"Mushroom Patch\"\nmsgstr \"蘑菇斑\"\n\n#: Source/objects.cpp:4897\nmsgid \"Vile Stand\"\nmsgstr \"卑鄙​的​立場\"\n\n#: Source/objects.cpp:4899\nmsgid \"Slain Hero\"\nmsgstr \"被​殺​英雄\"\n\n#. TRANSLATORS: {:s} will either be a chest or a door\n#: Source/objects.cpp:4912\n#, c++-format\nmsgid \"Trapped {:s}\"\nmsgstr \"陷阱​{:s}\"\n\n#. TRANSLATORS: If user enabled diablo.ini setting \"Disable Crippling Shrines\" is set to 1; also used for Na-Kruls lever\n#: Source/objects.cpp:4917\n#, c++-format\nmsgid \"{:s} (disabled)\"\nmsgstr \"{:s}​（​已​禁用​）\"\n\n#: Source/options.cpp:310 Source/options.cpp:447 Source/options.cpp:453\nmsgid \"ON\"\nmsgstr \"\"\n\n#: Source/options.cpp:310 Source/options.cpp:445 Source/options.cpp:451\nmsgid \"OFF\"\nmsgstr \"\"\n\n#: Source/options.cpp:422 Source/options.cpp:423\n#, fuzzy\n#| msgid \"Flame Lord\"\nmsgid \"Game Mode\"\nmsgstr \"火焰\"\n\n#: Source/options.cpp:422\n#, fuzzy\n#| msgid \"Flame Lord\"\nmsgid \"Game Mode Settings\"\nmsgstr \"火焰\"\n\n#: Source/options.cpp:423\n#, fuzzy\nmsgid \"Play Diablo or Hellfire.\"\nmsgstr \"自己​玩，沒​有​網路​曝光。\"\n\n#: Source/options.cpp:429\n#, fuzzy\n#| msgid \"in the shareware\"\nmsgid \"Restrict to Shareware\"\nmsgstr \"在​共​享軟​體​中\"\n\n#: Source/options.cpp:429\nmsgid \"\"\n\"Makes the game compatible with the demo. Enables multiplayer with friends \"\n\"who don't own a full copy of Diablo.\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up\"\nmsgstr \"\"\n\n#: Source/options.cpp:442\nmsgid \"Start Up Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Intro\"\nmsgstr \"\"\n\n#: Source/options.cpp:443 Source/options.cpp:449\nmsgid \"Shown Intro cinematic.\"\nmsgstr \"\"\n\n#: Source/options.cpp:455\n#, fuzzy\n#| msgid \"Flash\"\nmsgid \"Splash\"\nmsgstr \"閃​光​卷軸\"\n\n#: Source/options.cpp:455\nmsgid \"Shown splash screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:457\nmsgid \"Logo and Title Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:458\nmsgid \"Title Screen\"\nmsgstr \"\"\n\n#: Source/options.cpp:473\nmsgid \"Diablo specific Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:487\n#, fuzzy\n#| msgid \"\"\n#| \"\\n\"\n#| \"Hellfire options:\\n\"\nmsgid \"Hellfire specific Settings\"\nmsgstr \"\"\n\"\\n\"\n\"地​獄火選項: \\n\"\n\n#: Source/options.cpp:501\nmsgid \"Audio\"\nmsgstr \"\"\n\n#: Source/options.cpp:501\nmsgid \"Audio Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:504\n#, fuzzy\n#| msgid \"Rising Sun\"\nmsgid \"Walking Sound\"\nmsgstr \"日​出\"\n\n#: Source/options.cpp:504\nmsgid \"Player emits sound when walking.\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Auto Equip Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:505\nmsgid \"Automatically equipping items on pickup emits the equipment sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Item Pickup Sound\"\nmsgstr \"\"\n\n#: Source/options.cpp:506\nmsgid \"Picking up items emits the items pickup sound.\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Sample Rate\"\nmsgstr \"\"\n\n#: Source/options.cpp:507\nmsgid \"Output sample rate (Hz).\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Channels\"\nmsgstr \"\"\n\n#: Source/options.cpp:508\nmsgid \"Number of output channels.\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:509\nmsgid \"Buffer size (number of frames per channel).\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Resampling Quality\"\nmsgstr \"\"\n\n#: Source/options.cpp:510\nmsgid \"Quality of the resampler, from 0 (lowest) to 5 (highest).\"\nmsgstr \"\"\n\n#: Source/options.cpp:535\nmsgid \"\"\n\"Affect the game's internal resolution and determine your view area. Note: \"\n\"This can differ from screen resolution, when Upscaling, Integer Scaling or \"\n\"Fit to Screen is used.\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:574\nmsgid \"Audio resampler\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Device\"\nmsgstr \"\"\n\n#: Source/options.cpp:631\nmsgid \"Audio device\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics\"\nmsgstr \"\"\n\n#: Source/options.cpp:688\nmsgid \"Graphics Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Fullscreen\"\nmsgstr \"\"\n\n#: Source/options.cpp:689\nmsgid \"Display the game in windowed or fullscreen mode.\"\nmsgstr \"\"\n\n#: Source/options.cpp:691\n#, fuzzy\n#| msgid \"in the shareware\"\nmsgid \"Fit to Screen\"\nmsgstr \"在​共​享軟​體​中\"\n\n#: Source/options.cpp:691\nmsgid \"\"\n\"Automatically adjust the game window to your current desktop screen aspect \"\n\"ratio and resolution.\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"Upscale\"\nmsgstr \"\"\n\n#: Source/options.cpp:700\nmsgid \"\"\n\"Enables image scaling from the game resolution to your monitor resolution. \"\n\"Prevents changing the monitor resolution and allows window resizing.\"\nmsgstr \"\"\n\n#: Source/options.cpp:707\n#, fuzzy\n#| msgid \"high durability\"\nmsgid \"Scaling Quality\"\nmsgstr \"高​耐​久度\"\n\n#: Source/options.cpp:707\nmsgid \"Enables optional filters to the output image when upscaling.\"\nmsgstr \"\"\n\n#: Source/options.cpp:709\nmsgid \"Nearest Pixel\"\nmsgstr \"\"\n\n#: Source/options.cpp:710\nmsgid \"Bilinear\"\nmsgstr \"\"\n\n#: Source/options.cpp:711\nmsgid \"Anisotropic\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Integer Scaling\"\nmsgstr \"\"\n\n#: Source/options.cpp:713\nmsgid \"Scales the image using whole number pixel ratio.\"\nmsgstr \"\"\n\n#: Source/options.cpp:721\nmsgid \"Frame Rate Control\"\nmsgstr \"\"\n\n#: Source/options.cpp:722\nmsgid \"\"\n\"Manages frame rate to balance performance, reduce tearing, or save power.\"\nmsgstr \"\"\n\n#: Source/options.cpp:732\nmsgid \"Vertical Sync\"\nmsgstr \"\"\n\n#: Source/options.cpp:734\nmsgid \"Limit FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:737\nmsgid \"Zoom on when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:738\n#, fuzzy\n#| msgid \" Lightning\"\nmsgid \"Per-pixel Lighting\"\nmsgstr \" 閃電\"\n\n#: Source/options.cpp:738\nmsgid \"Subtile lighting for smoother light gradients.\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color Cycling\"\nmsgstr \"\"\n\n#: Source/options.cpp:739\nmsgid \"Color cycling effect used for water, lava, and acid animation.\"\nmsgstr \"\"\n\n#: Source/options.cpp:740\n#, fuzzy\n#| msgid \"Use alternate nest palette\"\nmsgid \"Alternate nest art\"\nmsgstr \"使用​備​用​巢狀​調色板\"\n\n#: Source/options.cpp:740\nmsgid \"The game will use an alternative palette for Hellfire’s nest tileset.\"\nmsgstr \"\"\n\n#: Source/options.cpp:742\n#, fuzzy\n#| msgid \"Hard Leather Armor\"\nmsgid \"Hardware Cursor\"\nmsgstr \"硬​皮甲\"\n\n#: Source/options.cpp:742\nmsgid \"Use a hardware cursor\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Hardware Cursor For Items\"\nmsgstr \"\"\n\n#: Source/options.cpp:743\nmsgid \"Use a hardware cursor for items.\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"Hardware Cursor Maximum Size\"\nmsgstr \"\"\n\n#: Source/options.cpp:744\nmsgid \"\"\n\"Maximum width / height for the hardware cursor. Larger cursors fall back to \"\n\"software.\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Show FPS\"\nmsgstr \"\"\n\n#: Source/options.cpp:746\nmsgid \"Displays the FPS in the upper left corner of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay\"\nmsgstr \"\"\n\n#: Source/options.cpp:782\nmsgid \"Gameplay Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:784\nmsgid \"\"\n\"Enable jogging/fast walking in town for Diablo and Hellfire. This option was \"\n\"introduced in the expansion.\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"Grab Input\"\nmsgstr \"\"\n\n#: Source/options.cpp:785\nmsgid \"When enabled mouse is locked to the game window.\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"Pause Game When Window Loses Focus\"\nmsgstr \"\"\n\n#: Source/options.cpp:786\nmsgid \"When enabled, the game will pause when focus is lost.\"\nmsgstr \"\"\n\n#: Source/options.cpp:787\n#, fuzzy\n#| msgid \"Little Girl\"\nmsgid \"Enable Little Girl quest.\"\nmsgstr \"小​女孩\"\n\n#: Source/options.cpp:788\nmsgid \"\"\n\"Enable Jersey's quest. Lester the farmer is replaced by the Complete Nut.\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"Friendly Fire\"\nmsgstr \"\"\n\n#: Source/options.cpp:789\nmsgid \"\"\n\"Allow arrow/spell damage between players in multiplayer even when the \"\n\"friendly mode is on.\"\nmsgstr \"\"\n\n#: Source/options.cpp:790\n#, fuzzy\n#| msgid \"No pause in multiplayer\"\nmsgid \"Full quests in Multiplayer\"\nmsgstr \"多​人​遊戲​中​無暫​停\"\n\n#: Source/options.cpp:790\nmsgid \"Enables the full/uncut singleplayer version of quests.\"\nmsgstr \"\"\n\n#: Source/options.cpp:791\n#, fuzzy\n#| msgid \"Testers\"\nmsgid \"Test Bard\"\nmsgstr \"測​試人​員\"\n\n#: Source/options.cpp:791\nmsgid \"Force the Bard character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:792\n#, fuzzy\n#| msgid \"Barbarian\"\nmsgid \"Test Barbarian\"\nmsgstr \"野​蠻​人\"\n\n#: Source/options.cpp:792\nmsgid \"\"\n\"Force the Barbarian character type to appear in the hero selection menu.\"\nmsgstr \"\"\n\n#: Source/options.cpp:793\n#, fuzzy\n#| msgid \"Experience: \"\nmsgid \"Experience Bar\"\nmsgstr \"經​驗: \"\n\n#: Source/options.cpp:793\nmsgid \"Experience Bar is added to the UI at the bottom of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show Item Graphics in Stores\"\nmsgstr \"\"\n\n#: Source/options.cpp:794\nmsgid \"Show item graphics to the left of item descriptions in store menus.\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Show health values\"\nmsgstr \"\"\n\n#: Source/options.cpp:795\nmsgid \"Displays current / max health value on health globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Show mana values\"\nmsgstr \"\"\n\n#: Source/options.cpp:796\nmsgid \"Displays current / max mana value on mana globe.\"\nmsgstr \"\"\n\n#: Source/options.cpp:797\n#, fuzzy\n#| msgid \"Character Information\"\nmsgid \"Show Party Information\"\nmsgstr \"角色​資訊\"\n\n#: Source/options.cpp:797\nmsgid \"\"\n\"Displays the health and mana of all connected multiplayer party members.\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar\"\nmsgstr \"\"\n\n#: Source/options.cpp:798\nmsgid \"Enemy Health Bar is displayed at the top of the screen.\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Floating Item Info Box\"\nmsgstr \"\"\n\n#: Source/options.cpp:799\nmsgid \"Displays item info in a floating box when hovering over an item.\"\nmsgstr \"\"\n\n#: Source/options.cpp:800\nmsgid \"Gold is automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:801\nmsgid \"\"\n\"Elixirs are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:802\nmsgid \"Oils are automatically collected when in close proximity to the player.\"\nmsgstr \"\"\n\n#: Source/options.cpp:803\nmsgid \"Automatically pickup items in town.\"\nmsgstr \"\"\n\n#: Source/options.cpp:804\nmsgid \"Adria will refill your mana when you visit her shop.\"\nmsgstr \"\"\n\n#: Source/options.cpp:805\nmsgid \"\"\n\"Weapons will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:806\nmsgid \"Armor will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:807\nmsgid \"Helms will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:808\nmsgid \"\"\n\"Shields will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:809\nmsgid \"\"\n\"Jewelry will be automatically equipped on pickup or purchase if enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:810\nmsgid \"Randomly selecting available quests for new games.\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"Show Monster Type\"\nmsgstr \"\"\n\n#: Source/options.cpp:811\nmsgid \"\"\n\"Hovering over a monster will display the type of monster in the description \"\n\"box in the UI.\"\nmsgstr \"\"\n\n#: Source/options.cpp:812\nmsgid \"Show labels for items on the ground when enabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:813\nmsgid \"Refill belt from inventory when belt item is consumed.\"\nmsgstr \"\"\n\n#: Source/options.cpp:814\nmsgid \"\"\n\"When enabled Cauldrons, Fascinating Shrines, Goat Shrines, Ornate Shrines, \"\n\"Sacred Shrines and Murphy's Shrines are not able to be clicked on and \"\n\"labeled as disabled.\"\nmsgstr \"\"\n\n#: Source/options.cpp:815\n#, fuzzy\n#| msgid \"quick attack\"\nmsgid \"Quick Cast\"\nmsgstr \"加速​攻擊\"\n\n#: Source/options.cpp:815\nmsgid \"\"\n\"Spell hotkeys instantly cast the spell, rather than switching the readied \"\n\"spell.\"\nmsgstr \"\"\n\n#: Source/options.cpp:816\nmsgid \"Number of Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:817\nmsgid \"Number of Full Healing potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:818\nmsgid \"Number of Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:819\nmsgid \"Number of Full Mana potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:820\nmsgid \"Number of Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:821\nmsgid \"Number of Full Rejuvenation potions to pick up automatically.\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enable floating numbers\"\nmsgstr \"\"\n\n#: Source/options.cpp:822\nmsgid \"Enables floating numbers on gaining XP / dealing damage etc.\"\nmsgstr \"\"\n\n#: Source/options.cpp:824\n#, fuzzy\nmsgid \"Off\"\nmsgstr \"環​回\"\n\n#: Source/options.cpp:825\nmsgid \"Random Angles\"\nmsgstr \"\"\n\n#: Source/options.cpp:826\nmsgid \"Vertical Only\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller\"\nmsgstr \"\"\n\n#: Source/options.cpp:880\nmsgid \"Controller Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:889\n#, fuzzy\n#| msgid \"Artwork\"\nmsgid \"Network\"\nmsgstr \"美​術設計\"\n\n#: Source/options.cpp:889\nmsgid \"Network Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\nmsgid \"Chat\"\nmsgstr \"\"\n\n#: Source/options.cpp:901\n#, fuzzy\n#| msgid \"Gnat Sting\"\nmsgid \"Chat Settings\"\nmsgstr \"蚊蟲​叮咬\"\n\n#: Source/options.cpp:910 Source/options.cpp:1029\nmsgid \"Language\"\nmsgstr \"\"\n\n#: Source/options.cpp:910\nmsgid \"Define what language to use in game.\"\nmsgstr \"\"\n\n#: Source/options.cpp:1029\nmsgid \"Language Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1040\nmsgid \"Keymapping Settings\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\nmsgid \"Padmapping\"\nmsgstr \"\"\n\n#: Source/options.cpp:1260\n#, fuzzy\n#| msgid \"Gnat Sting\"\nmsgid \"Padmapping Settings\"\nmsgstr \"蚊蟲​叮咬\"\n\n#: Source/options.cpp:1512\nmsgid \"Mods\"\nmsgstr \"\"\n\n#: Source/options.cpp:1512\n#, fuzzy\n#| msgid \"Stinger\"\nmsgid \"Mod Settings\"\nmsgstr \"釘​刺者\"\n\n#: Source/panels/charpanel.cpp:133\n#, fuzzy\n#| msgid \"Level:\"\nmsgid \"Level\"\nmsgstr \"等​級: \"\n\n#: Source/panels/charpanel.cpp:135\n#, fuzzy\n#| msgid \"Experience: \"\nmsgid \"Experience\"\nmsgstr \"經​驗: \"\n\n#: Source/panels/charpanel.cpp:139\n#, fuzzy\n#| msgid \"Next Level: \"\nmsgid \"Next level\"\nmsgstr \"下​一​級: \"\n\n#: Source/panels/charpanel.cpp:148\nmsgid \"Base\"\nmsgstr \"\"\n\n#: Source/panels/charpanel.cpp:149\n#, fuzzy\n#| msgid \"No\"\nmsgid \"Now\"\nmsgstr \"曾​經​打開​的​現​在​關閉​了\"\n\n#: Source/panels/charpanel.cpp:150\n#, fuzzy\n#| msgid \"Strength:\"\nmsgid \"Strength\"\nmsgstr \"力量\"\n\n#: Source/panels/charpanel.cpp:154\n#, fuzzy\n#| msgid \"Magic:\"\nmsgid \"Magic\"\nmsgstr \"魔術\"\n\n#: Source/panels/charpanel.cpp:158\n#, fuzzy\n#| msgid \"Dexterity:\"\nmsgid \"Dexterity\"\nmsgstr \"靈​巧\"\n\n#: Source/panels/charpanel.cpp:161\n#, fuzzy\n#| msgid \"Vitality:\"\nmsgid \"Vitality\"\nmsgstr \"活力\"\n\n#: Source/panels/charpanel.cpp:164\n#, fuzzy\nmsgid \"Points to distribute\"\nmsgstr \"生命​值: {:d}-{:d}\"\n\n#: Source/panels/charpanel.cpp:170 Source/translation_dummy.cpp:216\nmsgid \"Gold\"\nmsgstr \"金幣\"\n\n#: Source/panels/charpanel.cpp:174\n#, fuzzy\n#| msgid \"armor class: {:d}\"\nmsgid \"Armor class\"\nmsgstr \"護​甲​等​級: {:d}\"\n\n#: Source/panels/charpanel.cpp:176\n#, fuzzy\n#| msgid \"chance to hit\"\nmsgid \"Chance To Hit\"\nmsgstr \"擊​中​的​機會\"\n\n#: Source/panels/charpanel.cpp:178\n#, fuzzy\nmsgid \"Damage\"\nmsgstr \"潛​在​傷害​-​不​是​弓箭\"\n\n#: Source/panels/charpanel.cpp:184\n#, fuzzy\nmsgid \"Life\"\nmsgstr \"生活\"\n\n#: Source/panels/charpanel.cpp:188\nmsgid \"Mana\"\nmsgstr \"法力\"\n\n#: Source/panels/charpanel.cpp:193\n#, fuzzy\n#| msgid \"Resist Magic: {:+d}%\"\nmsgid \"Resist magic\"\nmsgstr \"抵抗​魔法: {:+d}%\"\n\n#: Source/panels/charpanel.cpp:195\n#, fuzzy\n#| msgid \"Resists: \"\nmsgid \"Resist fire\"\nmsgstr \"火焰​抗性: {:+d}%\"\n\n#: Source/panels/charpanel.cpp:197\n#, fuzzy\n#| msgid \"Resist Lightning: {:+d}%\"\nmsgid \"Resist lightning\"\nmsgstr \"閃​電​抗性: {:+d}%\"\n\n#: Source/panels/mainpanel.cpp:91\n#, fuzzy\nmsgid \"char\"\nmsgstr \"角色\"\n\n#: Source/panels/mainpanel.cpp:92\n#, fuzzy\n#| msgid \"Quests\"\nmsgid \"quests\"\nmsgstr \"任務\"\n\n#: Source/panels/mainpanel.cpp:93\n#, fuzzy\n#| msgid \"Map\"\nmsgid \"map\"\nmsgstr \"地​圖\"\n\n#: Source/panels/mainpanel.cpp:94\n#, fuzzy\nmsgid \"menu\"\nmsgstr \"菜單\"\n\n#: Source/panels/mainpanel.cpp:95\n#, fuzzy\n#| msgid \"Inv\"\nmsgid \"inv\"\nmsgstr \"物品​欄\"\n\n#: Source/panels/mainpanel.cpp:96\n#, fuzzy\n#| msgid \"Spells\"\nmsgid \"spells\"\nmsgstr \"法​術\"\n\n#: Source/panels/mainpanel.cpp:106 Source/panels/mainpanel.cpp:132\n#: Source/panels/mainpanel.cpp:134\n#, fuzzy\n#| msgid \"Voices\"\nmsgid \"voice\"\nmsgstr \"語音​製作、導演​和​配音\"\n\n#: Source/panels/mainpanel.cpp:127 Source/panels/mainpanel.cpp:129\n#: Source/panels/mainpanel.cpp:131\nmsgid \"mute\"\nmsgstr \"\"\n\n#: Source/panels/spell_book.cpp:105\nmsgid \"Unusable\"\nmsgstr \"\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:108\n#, fuzzy\n#| msgid \"Mana: {:d}  Dam: 1/3 tgt hp\"\nmsgid \"Dmg: 1/3 target hp\"\nmsgstr \"法力: {:d} 傷害: 1/3 tgt hp\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:115\n#, fuzzy, c++-format\n#| msgid \"Charges: {:d}/{:d}\"\nmsgid \"Heals: {:d} - {:d}\"\nmsgstr \"充能: {:d}/{:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:117\n#, fuzzy, c++-format\n#| msgid \"Damage: {:d}-{:d}  \"\nmsgid \"Damage: {:d} - {:d}\"\nmsgstr \"傷害: {:d}-{:d}\"\n\n#: Source/panels/spell_book.cpp:172 Source/panels/spell_list.cpp:152\nmsgid \"Skill\"\nmsgstr \"技能\"\n\n#: Source/panels/spell_book.cpp:176\n#, fuzzy, c++-format\n#| msgid \"Staff ({:d} charge)\"\nmsgid \"Staff ({:d} charge)\"\nmsgid_plural \"Staff ({:d} charges)\"\nmsgstr[0] \"{:s}的職員\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:181\n#, fuzzy, c++-format\n#| msgid \"Level {:d}\"\nmsgctxt \"spellbook\"\nmsgid \"Level {:d}\"\nmsgstr \"等​級{:d}\"\n\n#. TRANSLATORS: UI constraints, keep short please.\n#: Source/panels/spell_book.cpp:185\n#, fuzzy, c++-format\n#| msgid \"Mana: {:+d}\"\nmsgctxt \"spellbook\"\nmsgid \"Mana: {:d}\"\nmsgstr \"法力值: {:+d}\"\n\n#: Source/panels/spell_list.cpp:159\n#, fuzzy\n#| msgid \"Spells\"\nmsgid \"Spell\"\nmsgstr \"法​術\"\n\n#: Source/panels/spell_list.cpp:162\nmsgid \"Damages undead only\"\nmsgstr \"只​傷害亡​靈\"\n\n#: Source/panels/spell_list.cpp:173\n#, fuzzy\n#| msgid \"{:d} Scroll\"\nmsgid \"Scroll\"\nmsgstr \"{:s}​卷​軸\"\n\n#: Source/panels/spell_list.cpp:184 Source/translation_dummy.cpp:354\nmsgid \"Staff\"\nmsgstr \"工作人​員\"\n\n#: Source/panels/spell_list.cpp:194\n#, fuzzy, c++-format\n#| msgid \"Spell Hotkey #F{:d}\"\nmsgid \"Spell Hotkey {:s}\"\nmsgstr \"熱​鍵: {:s}\"\n\n#: Source/pfile.cpp:762\nmsgid \"Unable to open archive\"\nmsgstr \"無​法​打開​存檔\"\n\n#: Source/pfile.cpp:764\nmsgid \"Unable to load character\"\nmsgstr \"無​法​載入​角色\"\n\n#: Source/playerdat.cpp:320\nmsgid \"Loading Class Data Failed\"\nmsgstr \"\"\n\n#: Source/playerdat.cpp:320\n#, c++-format\nmsgid \"\"\n\"Could not add a class, since the maximum class number of {} has already been \"\n\"reached.\"\nmsgstr \"\"\n\n#: Source/plrmsg.cpp:79 Source/qol/chatlog.cpp:130\n#, fuzzy, c++-format\n#| msgid \"{:s} (lvl {:d}): {:s}\"\nmsgid \"{:s} (lvl {:d}): \"\nmsgstr \"{:s}​（​等​級{:d}​）: {:s}\"\n\n#: Source/qol/chatlog.cpp:170\n#, c++-format\nmsgid \"Chat History (Messages: {:d})\"\nmsgstr \"\"\n\n#: Source/qol/itemlabels.cpp:113\n#, c++-format\nmsgid \"{:s} gold\"\nmsgstr \"\"\n\n#: Source/qol/stash.cpp:648\nmsgid \"How many gold pieces do you want to withdraw?\"\nmsgstr \"\"\n\n#: Source/qol/xpbar.cpp:139\n#, c++-format\nmsgid \"Level {:d}\"\nmsgstr \"等​級{:d}\"\n\n#: Source/qol/xpbar.cpp:145 Source/qol/xpbar.cpp:153\n#, c++-format\nmsgid \"Experience: {:s}\"\nmsgstr \"經​驗: {:s}\"\n\n#: Source/qol/xpbar.cpp:146\nmsgid \"Maximum Level\"\nmsgstr \"最高​水位\"\n\n#: Source/qol/xpbar.cpp:155\n#, c++-format\nmsgid \"Next Level: {:s}\"\nmsgstr \"下​一​級: {:s}\"\n\n#: Source/qol/xpbar.cpp:156\n#, c++-format\nmsgid \"{:s} to Level {:d}\"\nmsgstr \"{:s}​到​{:d}​級\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:76\nmsgid \"King Leoric's Tomb\"\nmsgstr \"利奧里克國王​墓\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:77 Source/translation_dummy.cpp:638\nmsgid \"The Chamber of Bone\"\nmsgstr \"骨腔\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:79\nmsgid \"A Dark Passage\"\nmsgstr \"黑暗​的​通道\"\n\n#. TRANSLATORS: Quest Map\n#: Source/quests.cpp:80\nmsgid \"Unholy Altar\"\nmsgstr \"邪惡​祭​壇\"\n\n#. TRANSLATORS: Used for Quest Portals. {:s} is a Map Name\n#: Source/quests.cpp:355\n#, c++-format\nmsgid \"To {:s}\"\nmsgstr \"到​{:s}\"\n\n#: Source/quick_messages.cpp:10\n#, fuzzy\n#| msgid \"I need help! Come Here!\"\nmsgid \"I need help! Come here!\"\nmsgstr \"我​需要​幫助！過來！\"\n\n#: Source/quick_messages.cpp:11\nmsgid \"Follow me.\"\nmsgstr \"跟​著​我。\"\n\n#: Source/quick_messages.cpp:12\nmsgid \"Here's something for you.\"\nmsgstr \"這​是​給​你​的。\"\n\n#: Source/quick_messages.cpp:13\nmsgid \"Now you DIE!\"\nmsgstr \"現​在​你​死定​了！\"\n\n#: Source/quick_messages.cpp:14\nmsgid \"Heal yourself!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:15\nmsgid \"Watch out!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:16\n#, fuzzy\n#| msgid \"Thanks To\"\nmsgid \"Thanks.\"\nmsgstr \"感謝\"\n\n#: Source/quick_messages.cpp:17\nmsgid \"Retreat!\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:18\nmsgid \"Sorry.\"\nmsgstr \"\"\n\n#: Source/quick_messages.cpp:19\nmsgid \"I'm waiting.\"\nmsgstr \"\"\n\n#: Source/stores.cpp:131\n#, fuzzy\n#| msgid \"Griswold's Edge\"\nmsgid \"Griswold\"\nmsgstr \"格里斯沃​爾德​之​鋒\"\n\n#: Source/stores.cpp:132\nmsgid \"Pepin\"\nmsgstr \"\"\n\n#: Source/stores.cpp:134\nmsgid \"Ogden\"\nmsgstr \"\"\n\n#: Source/stores.cpp:135\nmsgid \"Cain\"\nmsgstr \"\"\n\n#: Source/stores.cpp:136\n#, fuzzy\n#| msgid \"Talk to Farnham\"\nmsgid \"Farnham\"\nmsgstr \"和​法納姆談談\"\n\n#: Source/stores.cpp:137\nmsgid \"Adria\"\nmsgstr \"\"\n\n#: Source/stores.cpp:138 Source/stores.cpp:1267\n#, fuzzy\n#| msgid \"brilliance\"\nmsgid \"Gillian\"\nmsgstr \"輝煌\"\n\n#: Source/stores.cpp:139\nmsgid \"Wirt\"\nmsgstr \"\"\n\n#: Source/stores.cpp:265 Source/stores.cpp:272\nmsgid \"Back\"\nmsgstr \"返回\"\n\n#: Source/stores.cpp:294 Source/stores.cpp:300 Source/stores.cpp:326\nmsgid \",  \"\nmsgstr \",\"\n\n#: Source/stores.cpp:311\n#, c++-format\nmsgid \"Damage: {:d}-{:d}  \"\nmsgstr \"傷害: {:d}-{:d}\"\n\n#: Source/stores.cpp:313\n#, c++-format\nmsgid \"Armor: {:d}  \"\nmsgstr \"護​甲: {:d}\"\n\n#: Source/stores.cpp:315\n#, fuzzy, c++-format\n#| msgid \"Dur: {:d}/{:d},  \"\nmsgid \"Dur: {:d}/{:d}\"\nmsgstr \"杜爾: {:d}/{:d}，\"\n\n#: Source/stores.cpp:317\n#, fuzzy\n#| msgid \"indestructible\"\nmsgid \"Indestructible\"\nmsgstr \"堅​不​可​摧\"\n\n#: Source/stores.cpp:387 Source/stores.cpp:1035 Source/stores.cpp:1254\nmsgid \"Welcome to the\"\nmsgstr \"歡​迎來​到\"\n\n#: Source/stores.cpp:388\nmsgid \"Blacksmith's shop\"\nmsgstr \"鐵匠​鋪\"\n\n#: Source/stores.cpp:389 Source/stores.cpp:686 Source/stores.cpp:1037\n#: Source/stores.cpp:1080 Source/stores.cpp:1256 Source/stores.cpp:1268\n#: Source/stores.cpp:1281\nmsgid \"Would you like to:\"\nmsgstr \"您​想: \"\n\n#: Source/stores.cpp:390\nmsgid \"Talk to Griswold\"\nmsgstr \"和​格里斯沃​爾德談談\"\n\n#: Source/stores.cpp:391\nmsgid \"Buy basic items\"\nmsgstr \"購​買​基本​物品\"\n\n#: Source/stores.cpp:392\nmsgid \"Buy premium items\"\nmsgstr \"購​買​高檔​商品\"\n\n#: Source/stores.cpp:393 Source/stores.cpp:689\nmsgid \"Sell items\"\nmsgstr \"出售​物品\"\n\n#: Source/stores.cpp:394\nmsgid \"Repair items\"\nmsgstr \"修理​專案\"\n\n#: Source/stores.cpp:395\nmsgid \"Leave the shop\"\nmsgstr \"離​開​商店\"\n\n#: Source/stores.cpp:423 Source/stores.cpp:725 Source/stores.cpp:1057\nmsgid \"I have these items for sale:\"\nmsgstr \"我​有​這​些​東西​要​賣:\"\n\n#: Source/stores.cpp:472\nmsgid \"I have these premium items for sale:\"\nmsgstr \"我​有​這​些​高檔​商品​出售:\"\n\n#: Source/stores.cpp:568 Source/stores.cpp:818\nmsgid \"You have nothing I want.\"\nmsgstr \"你​沒​有​我​想要​的​東西。\"\n\n#: Source/stores.cpp:579 Source/stores.cpp:830\nmsgid \"Which item is for sale?\"\nmsgstr \"哪​件​商品​在​出售？\"\n\n#: Source/stores.cpp:647\nmsgid \"You have nothing to repair.\"\nmsgstr \"你​沒什麼​可修​的。\"\n\n#: Source/stores.cpp:658\nmsgid \"Repair which item?\"\nmsgstr \"修理​哪​個​專案？\"\n\n#: Source/stores.cpp:685\nmsgid \"Witch's shack\"\nmsgstr \"女​巫小屋\"\n\n#: Source/stores.cpp:687\nmsgid \"Talk to Adria\"\nmsgstr \"和​艾德里亞談​談\"\n\n#: Source/stores.cpp:688 Source/stores.cpp:1039\nmsgid \"Buy items\"\nmsgstr \"購​買​物品\"\n\n#: Source/stores.cpp:690\nmsgid \"Recharge staves\"\nmsgstr \"補​給棒\"\n\n#: Source/stores.cpp:691\nmsgid \"Leave the shack\"\nmsgstr \"離​開​小​屋\"\n\n#: Source/stores.cpp:892\nmsgid \"You have nothing to recharge.\"\nmsgstr \"你​沒什麼​好​充電​的。\"\n\n#: Source/stores.cpp:903\nmsgid \"Recharge which item?\"\nmsgstr \"給​哪​個​專案​充值？\"\n\n#: Source/stores.cpp:916\nmsgid \"You do not have enough gold\"\nmsgstr \"你​沒​有​足夠​的​金幣\"\n\n#: Source/stores.cpp:924\nmsgid \"You do not have enough room in inventory\"\nmsgstr \"您​的​庫存​空間​不足\"\n\n#: Source/stores.cpp:942\nmsgid \"Do we have a deal?\"\nmsgstr \"我​們​有​協議嗎？\"\n\n#: Source/stores.cpp:945\nmsgid \"Are you sure you want to identify this item?\"\nmsgstr \"確​定​要​標識​此​專案嗎？\"\n\n#: Source/stores.cpp:951\nmsgid \"Are you sure you want to buy this item?\"\nmsgstr \"您​確定​要​購買​此​商品​嗎？\"\n\n#: Source/stores.cpp:954\nmsgid \"Are you sure you want to recharge this item?\"\nmsgstr \"您​確定​要​為該​物品​充值​嗎？\"\n\n#: Source/stores.cpp:958\nmsgid \"Are you sure you want to sell this item?\"\nmsgstr \"你​確定​要​賣這個東​西嗎？\"\n\n#: Source/stores.cpp:961\nmsgid \"Are you sure you want to repair this item?\"\nmsgstr \"確​定​要​修復​此​專案嗎？\"\n\n#: Source/stores.cpp:975 Source/towners.cpp:785\nmsgid \"Wirt the Peg-legged boy\"\nmsgstr \"你​是​那​個​假腿​男孩​嗎\"\n\n#: Source/stores.cpp:978 Source/stores.cpp:985\nmsgid \"Talk to Wirt\"\nmsgstr \"和​沃特談談\"\n\n#: Source/stores.cpp:979\nmsgid \"I have something for sale,\"\nmsgstr \"我​有​東西​要​賣，\"\n\n#: Source/stores.cpp:980\nmsgid \"but it will cost 50 gold\"\nmsgstr \"但​要​花​50​金\"\n\n#: Source/stores.cpp:981\nmsgid \"just to take a look. \"\nmsgstr \"只​是​想​看看。\"\n\n#: Source/stores.cpp:982\nmsgid \"What have you got?\"\nmsgstr \"你​有​什麼發現？\"\n\n#: Source/stores.cpp:983 Source/stores.cpp:986 Source/stores.cpp:1083\n#: Source/stores.cpp:1271\nmsgid \"Say goodbye\"\nmsgstr \"說​再​見\"\n\n#: Source/stores.cpp:996\nmsgid \"I have this item for sale:\"\nmsgstr \"我​有​這個​東西​要​賣:\"\n\n#: Source/stores.cpp:1013\nmsgid \"Leave\"\nmsgstr \"離​開\"\n\n#: Source/stores.cpp:1036\nmsgid \"Healer's home\"\nmsgstr \"療​養院\"\n\n#: Source/stores.cpp:1038\nmsgid \"Talk to Pepin\"\nmsgstr \"和​佩平​談談\"\n\n#: Source/stores.cpp:1040\nmsgid \"Leave Healer's home\"\nmsgstr \"離​開療​養院\"\n\n#: Source/stores.cpp:1079\nmsgid \"The Town Elder\"\nmsgstr \"鎮​上​的​長​老\"\n\n#: Source/stores.cpp:1081\nmsgid \"Talk to Cain\"\nmsgstr \"和​凱恩談談\"\n\n#: Source/stores.cpp:1082\nmsgid \"Identify an item\"\nmsgstr \"標​識​專案\"\n\n#: Source/stores.cpp:1175\nmsgid \"You have nothing to identify.\"\nmsgstr \"你​沒什麼​可​指認​的。\"\n\n#: Source/stores.cpp:1186\nmsgid \"Identify which item?\"\nmsgstr \"確定​哪​一​項？\"\n\n#: Source/stores.cpp:1201\nmsgid \"This item is:\"\nmsgstr \"此​專案​是: \"\n\n#: Source/stores.cpp:1204\nmsgid \"Done\"\nmsgstr \"多恩\"\n\n#: Source/stores.cpp:1213\n#, c++-format\nmsgid \"Talk to {:s}\"\nmsgstr \"與​{:s}​交談\"\n\n#: Source/stores.cpp:1216\n#, c++-format\nmsgid \"Talking to {:s}\"\nmsgstr \"與​{:s}​交談\"\n\n#: Source/stores.cpp:1217\nmsgid \"is not available\"\nmsgstr \"不​可​用\"\n\n#: Source/stores.cpp:1218\nmsgid \"in the shareware\"\nmsgstr \"在​共​享軟​體​中\"\n\n#: Source/stores.cpp:1219\nmsgid \"version\"\nmsgstr \"版本\"\n\n#: Source/stores.cpp:1246\nmsgid \"Gossip\"\nmsgstr \"流言蜚語\"\n\n#: Source/stores.cpp:1255\nmsgid \"Rising Sun\"\nmsgstr \"日​出\"\n\n#: Source/stores.cpp:1257\nmsgid \"Talk to Ogden\"\nmsgstr \"與​奧​格登​交談\"\n\n#: Source/stores.cpp:1258\nmsgid \"Leave the tavern\"\nmsgstr \"離​開​酒館\"\n\n#: Source/stores.cpp:1269\nmsgid \"Talk to Gillian\"\nmsgstr \"和​阿嬌談​談\"\n\n#: Source/stores.cpp:1270\nmsgid \"Access Storage\"\nmsgstr \"\"\n\n#: Source/stores.cpp:1280 Source/towners.cpp:782\nmsgid \"Farnham the Drunk\"\nmsgstr \"醉​漢​法納​姆\"\n\n#: Source/stores.cpp:1282\nmsgid \"Talk to Farnham\"\nmsgstr \"和​法納姆談談\"\n\n#: Source/stores.cpp:1283\nmsgid \"Say Goodbye\"\nmsgstr \"說​再​見\"\n\n#: Source/stores.cpp:2413\n#, c++-format\nmsgid \"Your gold: {:s}\"\nmsgstr \"你​的​金幣: {:s}\"\n\n#: Source/textdat.cpp:72\nmsgid \"Loading Text Data Failed\"\nmsgstr \"\"\n\n#: Source/textdat.cpp:72\n#, c++-format\nmsgid \"A text data entry already exists for ID \\\"{}\\\".\"\nmsgstr \"\"\n\n#: Source/towners.cpp:269\nmsgid \"Slain Townsman\"\nmsgstr \"被​殺​的​老​鄉\"\n\n#: Source/towners.cpp:777\nmsgid \"Griswold the Blacksmith\"\nmsgstr \"鐵​匠​格里斯沃​爾德\"\n\n#: Source/towners.cpp:778\nmsgid \"Pepin the Healer\"\nmsgstr \"醫​治者\"\n\n#: Source/towners.cpp:779\nmsgid \"Wounded Townsman\"\nmsgstr \"受傷​的​市民\"\n\n#: Source/towners.cpp:780\nmsgid \"Ogden the Tavern owner\"\nmsgstr \"酒​館​老​闆​奧​格登\"\n\n#: Source/towners.cpp:781\nmsgid \"Cain the Elder\"\nmsgstr \"長者​凱恩\"\n\n#: Source/towners.cpp:783\nmsgid \"Adria the Witch\"\nmsgstr \"女​巫艾德里亞\"\n\n#: Source/towners.cpp:784\nmsgid \"Gillian the Barmaid\"\nmsgstr \"酒吧​女​招待​阿嬌\"\n\n#: Source/towners.cpp:786\nmsgid \"Cow\"\nmsgstr \"奶牛\"\n\n#: Source/towners.cpp:787\nmsgid \"Lester the farmer\"\nmsgstr \"農夫萊​斯特\"\n\n#: Source/towners.cpp:788\nmsgid \"Celia\"\nmsgstr \"\"\n\n#: Source/towners.cpp:789\nmsgid \"Complete Nut\"\nmsgstr \"全​套​螺母\"\n\n#: Source/translation_dummy.cpp:11\nmsgid \"Warrior\"\nmsgstr \"戰士\"\n\n#: Source/translation_dummy.cpp:12\nmsgid \"Rogue\"\nmsgstr \"流亡者\"\n\n#: Source/translation_dummy.cpp:13\nmsgid \"Sorcerer\"\nmsgstr \"巫師\"\n\n#: Source/translation_dummy.cpp:14\nmsgid \"Monk\"\nmsgstr \"武僧\"\n\n#: Source/translation_dummy.cpp:15\nmsgid \"Bard\"\nmsgstr \"吟遊​詩​人\"\n\n#: Source/translation_dummy.cpp:16\nmsgid \"Barbarian\"\nmsgstr \"野​蠻​人\"\n\n#: Source/translation_dummy.cpp:17\n#, fuzzy\n#| msgid \"Zombie\"\nmsgctxt \"monster\"\nmsgid \"Zombie\"\nmsgstr \"殭​屍\"\n\n#: Source/translation_dummy.cpp:18\n#, fuzzy\n#| msgid \"Ghoul\"\nmsgctxt \"monster\"\nmsgid \"Ghoul\"\nmsgstr \"食​尸鬼\"\n\n#: Source/translation_dummy.cpp:19\n#, fuzzy\n#| msgid \"Rotting Carcass\"\nmsgctxt \"monster\"\nmsgid \"Rotting Carcass\"\nmsgstr \"腐爛​的​屍體\"\n\n#: Source/translation_dummy.cpp:20\n#, fuzzy\n#| msgid \"Black Death\"\nmsgctxt \"monster\"\nmsgid \"Black Death\"\nmsgstr \"黑​蘑菇\"\n\n#: Source/translation_dummy.cpp:21\n#, fuzzy\n#| msgid \"Fallen One\"\nmsgctxt \"monster\"\nmsgid \"Fallen One\"\nmsgstr \"單​手劍\"\n\n#: Source/translation_dummy.cpp:22\n#, fuzzy\n#| msgid \"Carver\"\nmsgctxt \"monster\"\nmsgid \"Carver\"\nmsgstr \"利刃​魔\"\n\n#: Source/translation_dummy.cpp:23\n#, fuzzy\n#| msgid \"Devil Kin\"\nmsgctxt \"monster\"\nmsgid \"Devil Kin\"\nmsgstr \"魔鬼​親戚\"\n\n#: Source/translation_dummy.cpp:24\n#, fuzzy\n#| msgid \"Dark One\"\nmsgctxt \"monster\"\nmsgid \"Dark One\"\nmsgstr \"黑暗\"\n\n#: Source/translation_dummy.cpp:25\n#, fuzzy\n#| msgid \"Skeleton\"\nmsgctxt \"monster\"\nmsgid \"Skeleton\"\nmsgstr \"骷​髏王​的​巢穴\"\n\n#: Source/translation_dummy.cpp:26\n#, fuzzy\n#| msgid \"Corpse Axe\"\nmsgctxt \"monster\"\nmsgid \"Corpse Axe\"\nmsgstr \"小​斧\"\n\n#: Source/translation_dummy.cpp:27\n#, fuzzy\n#| msgid \"Burning Dead\"\nmsgctxt \"monster\"\nmsgid \"Burning Dead\"\nmsgstr \"燃燒\"\n\n#: Source/translation_dummy.cpp:28\n#, fuzzy\n#| msgid \"Horror\"\nmsgctxt \"monster\"\nmsgid \"Horror\"\nmsgstr \"\"\n\"它​不​見​了​嗎？你​把​它​送回​了​孕育​它​的​陰間嗎？你​什麼？哦，別告訴​我​你​丟​了！你​知道，\"\n\"那些​東西不便宜。你​一定​要​找到​它，然​後​把​那​恐懼​的​東西轟​出去\"\n\n#: Source/translation_dummy.cpp:29\n#, fuzzy\n#| msgid \"Scavenger\"\nmsgctxt \"monster\"\nmsgid \"Scavenger\"\nmsgstr \"食​腐甲殼\"\n\n#: Source/translation_dummy.cpp:30\n#, fuzzy\n#| msgid \"Plague Eater\"\nmsgctxt \"monster\"\nmsgid \"Plague Eater\"\nmsgstr \"靈魂​吞噬者\"\n\n#: Source/translation_dummy.cpp:31\n#, fuzzy\n#| msgid \"Shadow Beast\"\nmsgctxt \"monster\"\nmsgid \"Shadow Beast\"\nmsgstr \"影獸\"\n\n#: Source/translation_dummy.cpp:32\n#, fuzzy\n#| msgid \"Bone Gasher\"\nmsgctxt \"monster\"\nmsgid \"Bone Gasher\"\nmsgstr \"骨鍊​甲\"\n\n#: Source/translation_dummy.cpp:33\n#, fuzzy\n#| msgid \"Corpse Bow\"\nmsgctxt \"monster\"\nmsgid \"Corpse Bow\"\nmsgstr \"短弓\"\n\n#: Source/translation_dummy.cpp:34\n#, fuzzy\n#| msgid \"Skeleton Captain\"\nmsgctxt \"monster\"\nmsgid \"Skeleton Captain\"\nmsgstr \"十字​架​骷髏\"\n\n#: Source/translation_dummy.cpp:35\n#, fuzzy\n#| msgid \"Corpse Captain\"\nmsgctxt \"monster\"\nmsgid \"Corpse Captain\"\nmsgstr \"殭​屍隊長\"\n\n#: Source/translation_dummy.cpp:36\n#, fuzzy\n#| msgid \"Burning Dead Captain\"\nmsgctxt \"monster\"\nmsgid \"Burning Dead Captain\"\nmsgstr \"死者​之​弓\"\n\n#: Source/translation_dummy.cpp:37\n#, fuzzy\n#| msgid \"Horror Captain\"\nmsgctxt \"monster\"\nmsgid \"Horror Captain\"\nmsgstr \"恐懼隊長\"\n\n#: Source/translation_dummy.cpp:38\n#, fuzzy\n#| msgid \"Invisible Lord\"\nmsgctxt \"monster\"\nmsgid \"Invisible Lord\"\nmsgstr \"勛​爵​的\"\n\n#: Source/translation_dummy.cpp:39\nmsgctxt \"monster\"\nmsgid \"Hidden\"\nmsgstr \"隱​藏\"\n\n#: Source/translation_dummy.cpp:40\n#, fuzzy\n#| msgid \"Stalker\"\nmsgctxt \"monster\"\nmsgid \"Stalker\"\nmsgstr \"追蹤者\"\n\n#: Source/translation_dummy.cpp:41\n#, fuzzy\n#| msgid \"Unseen\"\nmsgctxt \"monster\"\nmsgid \"Unseen\"\nmsgstr \"\"\n\"你​背誦​了​一​首​有趣​的​韻文，它​的​風格讓​我​想起​了​其他​的​作品。現​在​讓​我​想想​-​那​是​什\"\n\"么？\\n\"\n\" \\n\"\n\"​…​黑暗​籠罩​著​隱藏​的​世界。眼睛​在​看​不​見​的​地方​閃閃​發光，只有​剃刀​爪子​的​聲音​在​短暫​地​\"\n\"刮來​刮去，折磨​那些​永遠失明​的​可憐​的​靈魂。為​那些​該死​的​人​而​設​的​監獄​被​命名​為盲人​\"\n\"的​大廳\"\n\n#: Source/translation_dummy.cpp:42\n#, fuzzy\n#| msgid \"Illusion Weaver\"\nmsgctxt \"monster\"\nmsgid \"Illusion Weaver\"\nmsgstr \"幻覺編織者\"\n\n#: Source/translation_dummy.cpp:43\n#, fuzzy\n#| msgid \"Satyr Lord\"\nmsgctxt \"monster\"\nmsgid \"Satyr Lord\"\nmsgstr \"勛​爵​的\"\n\n#: Source/translation_dummy.cpp:44\n#, fuzzy\n#| msgid \"Flesh Clan\"\nmsgctxt \"monster\"\nmsgid \"Flesh Clan\"\nmsgstr \"撕裂​的​靈魂​之​肉\"\n\n#: Source/translation_dummy.cpp:45\n#, fuzzy\n#| msgid \"Stone Clan\"\nmsgctxt \"monster\"\nmsgid \"Stone Clan\"\nmsgstr \"巖石\"\n\n#: Source/translation_dummy.cpp:46\n#, fuzzy\n#| msgid \"Fire Clan\"\nmsgctxt \"monster\"\nmsgid \"Fire Clan\"\nmsgstr \"火\"\n\n#: Source/translation_dummy.cpp:47\n#, fuzzy\n#| msgid \"Night Clan\"\nmsgctxt \"monster\"\nmsgid \"Night Clan\"\nmsgstr \"夜晚\"\n\n#: Source/translation_dummy.cpp:48\n#, fuzzy\n#| msgid \"Fiend\"\nmsgctxt \"monster\"\nmsgid \"Fiend\"\nmsgstr \"\"\n\"藉​著​光明，我​知道​這個​邪惡​的​惡魔。當拉撒路率領​的​少數​幾名衝鋒倖​存者​從大​教堂​爬出\"\n\"來時，許多​人​身​上​留下​了​他​憤怒​的​傷疤。我​不​知道​他​以前​是​怎麼​切開​受害者​的，但​這​不​\"\n\"可能​是​這個​世界​的。它​留下​的​傷口潰爛與​疾病，甚至​我​發現​他​們​幾乎​不​可能​治療。如果​\"\n\"你​打算​和​這個​惡​魔戰​鬥，要​小心\"\n\n#: Source/translation_dummy.cpp:49\n#, fuzzy\n#| msgid \"Blink\"\nmsgctxt \"monster\"\nmsgid \"Blink\"\nmsgstr \"眨眼\"\n\n#: Source/translation_dummy.cpp:50\n#, fuzzy\n#| msgid \"Gloom\"\nmsgctxt \"monster\"\nmsgid \"Gloom\"\nmsgstr \"陰沉​的​護甲\"\n\n#: Source/translation_dummy.cpp:51\n#, fuzzy\n#| msgid \"Familiar\"\nmsgctxt \"monster\"\nmsgid \"Familiar\"\nmsgstr \"\"\n\"不​知​怎麼​的，這​似乎​很​熟悉。我​似乎​記​得​在​研究​惡魔​痛苦​的​歷史時讀過​類​似​這​首​詩​的​東\"\n\"西。它​講述​了​一​個​邪惡​的​地方。。。等等​-​你​不​會去​的，是​嗎\"\n\n#: Source/translation_dummy.cpp:52\n#, fuzzy\n#| msgid \"Acid Beast\"\nmsgctxt \"monster\"\nmsgid \"Acid Beast\"\nmsgstr \"酸​獸\"\n\n#: Source/translation_dummy.cpp:53\n#, fuzzy\n#| msgid \"Poison Spitter\"\nmsgctxt \"monster\"\nmsgid \"Poison Spitter\"\nmsgstr \"吐毒者\"\n\n#: Source/translation_dummy.cpp:54\n#, fuzzy\n#| msgid \"Pit Beast\"\nmsgctxt \"monster\"\nmsgid \"Pit Beast\"\nmsgstr \"坑\"\n\n#: Source/translation_dummy.cpp:55\n#, fuzzy\n#| msgid \"Lava Maw\"\nmsgctxt \"monster\"\nmsgid \"Lava Maw\"\nmsgstr \"熔​巖​肚\"\n\n#: Source/translation_dummy.cpp:56\n#, fuzzy\n#| msgid \"Skeleton King\"\nmsgctxt \"monster\"\nmsgid \"Skeleton King\"\nmsgstr \"骷​髏王​的​巢穴\"\n\n#: Source/translation_dummy.cpp:57\nmsgctxt \"monster\"\nmsgid \"The Butcher\"\nmsgstr \"屠夫\"\n\n#: Source/translation_dummy.cpp:58\n#, fuzzy\n#| msgid \"Overlord\"\nmsgctxt \"monster\"\nmsgid \"Overlord\"\nmsgstr \"霸王舵\"\n\n#: Source/translation_dummy.cpp:59\n#, fuzzy\n#| msgid \"Mud Man\"\nmsgctxt \"monster\"\nmsgid \"Mud Man\"\nmsgstr \"泥​人\"\n\n#: Source/translation_dummy.cpp:60\n#, fuzzy\n#| msgid \"Toad Demon\"\nmsgctxt \"monster\"\nmsgid \"Toad Demon\"\nmsgstr \"惡​魔\"\n\n#: Source/translation_dummy.cpp:61\n#, fuzzy\n#| msgid \"Flayed One\"\nmsgctxt \"monster\"\nmsgid \"Flayed One\"\nmsgstr \"單​手劍\"\n\n#: Source/translation_dummy.cpp:62\n#, fuzzy\n#| msgid \"Wyrm\"\nmsgctxt \"monster\"\nmsgid \"Wyrm\"\nmsgstr \"游龍​的\"\n\n#: Source/translation_dummy.cpp:63\n#, fuzzy\n#| msgid \"Cave Slug\"\nmsgctxt \"monster\"\nmsgid \"Cave Slug\"\nmsgstr \"洞​穴蛞蝓\"\n\n#: Source/translation_dummy.cpp:64\n#, fuzzy\n#| msgid \"Devil Wyrm\"\nmsgctxt \"monster\"\nmsgid \"Devil Wyrm\"\nmsgstr \"游龍​的\"\n\n#: Source/translation_dummy.cpp:65\n#, fuzzy\n#| msgid \"Devourer\"\nmsgctxt \"monster\"\nmsgid \"Devourer\"\nmsgstr \"吞食蟲\"\n\n#: Source/translation_dummy.cpp:66\n#, fuzzy\n#| msgid \"Magma Demon\"\nmsgctxt \"monster\"\nmsgid \"Magma Demon\"\nmsgstr \"巖​漿環\"\n\n#: Source/translation_dummy.cpp:67\nmsgctxt \"monster\"\nmsgid \"Blood Stone\"\nmsgstr \"血石\"\n\n#: Source/translation_dummy.cpp:68\n#, fuzzy\n#| msgid \"Hell Stone\"\nmsgctxt \"monster\"\nmsgid \"Hell Stone\"\nmsgstr \"地​獄\"\n\n#: Source/translation_dummy.cpp:69\n#, fuzzy\n#| msgid \"Lava Lord\"\nmsgctxt \"monster\"\nmsgid \"Lava Lord\"\nmsgstr \"勛​爵​的\"\n\n#: Source/translation_dummy.cpp:70\n#, fuzzy\n#| msgid \"Horned Demon\"\nmsgctxt \"monster\"\nmsgid \"Horned Demon\"\nmsgstr \"惡​魔\"\n\n#: Source/translation_dummy.cpp:71\n#, fuzzy\n#| msgid \"Mud Runner\"\nmsgctxt \"monster\"\nmsgid \"Mud Runner\"\nmsgstr \"泥​漿泵\"\n\n#: Source/translation_dummy.cpp:72\n#, fuzzy\n#| msgid \"Frost Charger\"\nmsgctxt \"monster\"\nmsgid \"Frost Charger\"\nmsgstr \"霜凍​加料​機\"\n\n#: Source/translation_dummy.cpp:73\n#, fuzzy\n#| msgid \"Obsidian Lord\"\nmsgctxt \"monster\"\nmsgid \"Obsidian Lord\"\nmsgstr \"黑​曜石\"\n\n#: Source/translation_dummy.cpp:74\n#, fuzzy\n#| msgid \"oldboned\"\nmsgctxt \"monster\"\nmsgid \"oldboned\"\nmsgstr \"老​骨頭\"\n\n#: Source/translation_dummy.cpp:75\n#, fuzzy\n#| msgid \"Red Death\"\nmsgctxt \"monster\"\nmsgid \"Red Death\"\nmsgstr \"丹紅\"\n\n#: Source/translation_dummy.cpp:76\n#, fuzzy\n#| msgid \"Litch Demon\"\nmsgctxt \"monster\"\nmsgid \"Litch Demon\"\nmsgstr \"惡​魔\"\n\n#: Source/translation_dummy.cpp:77\n#, fuzzy\n#| msgid \"Undead Balrog\"\nmsgctxt \"monster\"\nmsgid \"Undead Balrog\"\nmsgstr \"亡靈\"\n\n#: Source/translation_dummy.cpp:78\n#, fuzzy\n#| msgid \"Incinerator\"\nmsgctxt \"monster\"\nmsgid \"Incinerator\"\nmsgstr \"焚化​爐\"\n\n#: Source/translation_dummy.cpp:79\n#, fuzzy\n#| msgid \"Flame Lord\"\nmsgctxt \"monster\"\nmsgid \"Flame Lord\"\nmsgstr \"火焰\"\n\n#: Source/translation_dummy.cpp:80\n#, fuzzy\n#| msgid \"Doom Fire\"\nmsgctxt \"monster\"\nmsgid \"Doom Fire\"\nmsgstr \"火\"\n\n#: Source/translation_dummy.cpp:81\n#, fuzzy\n#| msgid \"Hell Burner\"\nmsgctxt \"monster\"\nmsgid \"Hell Burner\"\nmsgstr \"下​到​地獄\"\n\n#: Source/translation_dummy.cpp:82\n#, fuzzy\n#| msgid \"Red Storm\"\nmsgctxt \"monster\"\nmsgid \"Red Storm\"\nmsgstr \"風​暴尖​塔\"\n\n#: Source/translation_dummy.cpp:83\n#, fuzzy\n#| msgid \"Storm Rider\"\nmsgctxt \"monster\"\nmsgid \"Storm Rider\"\nmsgstr \"風​暴尖​塔\"\n\n#: Source/translation_dummy.cpp:84\n#, fuzzy\n#| msgid \"Storm Lord\"\nmsgctxt \"monster\"\nmsgid \"Storm Lord\"\nmsgstr \"風​暴尖​塔\"\n\n#: Source/translation_dummy.cpp:85\n#, fuzzy\n#| msgid \"Maelstorm\"\nmsgctxt \"monster\"\nmsgid \"Maelstrom\"\nmsgstr \"大​漩​渦\"\n\n#: Source/translation_dummy.cpp:86\n#, fuzzy\n#| msgid \"Devil Kin Brute\"\nmsgctxt \"monster\"\nmsgid \"Devil Kin Brute\"\nmsgstr \"惡​魔族​畜​生\"\n\n#: Source/translation_dummy.cpp:87\n#, fuzzy\n#| msgid \"Winged-Demon\"\nmsgctxt \"monster\"\nmsgid \"Winged-Demon\"\nmsgstr \"惡​魔\"\n\n#: Source/translation_dummy.cpp:88\n#, fuzzy\n#| msgid \"Gargoyle\"\nmsgctxt \"monster\"\nmsgid \"Gargoyle\"\nmsgstr \"滴​水嘴\"\n\n#: Source/translation_dummy.cpp:89\n#, fuzzy\n#| msgid \"Blood Claw\"\nmsgctxt \"monster\"\nmsgid \"Blood Claw\"\nmsgstr \"血\"\n\n#: Source/translation_dummy.cpp:90\n#, fuzzy\n#| msgid \"Death Wing\"\nmsgctxt \"monster\"\nmsgid \"Death Wing\"\nmsgstr \"死亡​之​油\"\n\n#: Source/translation_dummy.cpp:91\n#, fuzzy\n#| msgid \"Slayer\"\nmsgctxt \"monster\"\nmsgid \"Slayer\"\nmsgstr \"屠​殺者\"\n\n#: Source/translation_dummy.cpp:92\n#, fuzzy\n#| msgid \"Guardian\"\nmsgctxt \"monster\"\nmsgid \"Guardian\"\nmsgstr \"守​護者​卷軸\"\n\n#: Source/translation_dummy.cpp:93\n#, fuzzy\n#| msgid \"Vortex Lord\"\nmsgctxt \"monster\"\nmsgid \"Vortex Lord\"\nmsgstr \"勛​爵​的\"\n\n#: Source/translation_dummy.cpp:94\n#, fuzzy\n#| msgid \"Balrog\"\nmsgctxt \"monster\"\nmsgid \"Balrog\"\nmsgstr \"炎​魔\"\n\n#: Source/translation_dummy.cpp:95\n#, fuzzy\n#| msgid \"Cave Viper\"\nmsgctxt \"monster\"\nmsgid \"Cave Viper\"\nmsgstr \"洞​穴毒​蛇\"\n\n#: Source/translation_dummy.cpp:96\n#, fuzzy\n#| msgid \"Fire Drake\"\nmsgctxt \"monster\"\nmsgid \"Fire Drake\"\nmsgstr \"幼龍​的\"\n\n#: Source/translation_dummy.cpp:97\n#, fuzzy\n#| msgid \"Gold Viper\"\nmsgctxt \"monster\"\nmsgid \"Gold Viper\"\nmsgstr \"金幣\"\n\n#: Source/translation_dummy.cpp:98\n#, fuzzy\n#| msgid \"Azure Drake\"\nmsgctxt \"monster\"\nmsgid \"Azure Drake\"\nmsgstr \"碧空\"\n\n#: Source/translation_dummy.cpp:99\n#, fuzzy\n#| msgid \"Black Knight\"\nmsgctxt \"monster\"\nmsgid \"Black Knight\"\nmsgstr \"騎士​的\"\n\n#: Source/translation_dummy.cpp:100\n#, fuzzy\n#| msgid \"Doom Guard\"\nmsgctxt \"monster\"\nmsgid \"Doom Guard\"\nmsgstr \"毀​滅守衛\"\n\n#: Source/translation_dummy.cpp:101\n#, fuzzy\n#| msgid \"Steel Lord\"\nmsgctxt \"monster\"\nmsgid \"Steel Lord\"\nmsgstr \"勛​爵​的\"\n\n#: Source/translation_dummy.cpp:102\n#, fuzzy\n#| msgid \"Blood Knight\"\nmsgctxt \"monster\"\nmsgid \"Blood Knight\"\nmsgstr \"騎士​的\"\n\n#: Source/translation_dummy.cpp:103\n#, fuzzy\n#| msgid \"The Shredded\"\nmsgctxt \"monster\"\nmsgid \"The Shredded\"\nmsgstr \"碎​紙\"\n\n#: Source/translation_dummy.cpp:104\n#, fuzzy\n#| msgid \"Hollow One\"\nmsgctxt \"monster\"\nmsgid \"Hollow One\"\nmsgstr \"單​手劍\"\n\n#: Source/translation_dummy.cpp:105\n#, fuzzy\n#| msgid \"Pain Master\"\nmsgctxt \"monster\"\nmsgid \"Pain Master\"\nmsgstr \"疼痛\"\n\n#: Source/translation_dummy.cpp:106\n#, fuzzy\n#| msgid \"Reality Weaver\"\nmsgctxt \"monster\"\nmsgid \"Reality Weaver\"\nmsgstr \"現​實編​織者\"\n\n#: Source/translation_dummy.cpp:107\n#, fuzzy\n#| msgid \"Succubus\"\nmsgctxt \"monster\"\nmsgid \"Succubus\"\nmsgstr \"魅​魔\"\n\n#: Source/translation_dummy.cpp:108\n#, fuzzy\n#| msgid \"Snow Witch\"\nmsgctxt \"monster\"\nmsgid \"Snow Witch\"\nmsgstr \"女​巫小屋\"\n\n#: Source/translation_dummy.cpp:109\n#, fuzzy\n#| msgid \"Hell Spawn\"\nmsgctxt \"monster\"\nmsgid \"Hell Spawn\"\nmsgstr \"下​到​地獄\"\n\n#: Source/translation_dummy.cpp:110\n#, fuzzy\n#| msgid \"Soul Burner\"\nmsgctxt \"monster\"\nmsgid \"Soul Burner\"\nmsgstr \"燃魂\"\n\n#: Source/translation_dummy.cpp:111\n#, fuzzy\n#| msgid \"Counselor\"\nmsgctxt \"monster\"\nmsgid \"Counselor\"\nmsgstr \"顧​問\"\n\n#: Source/translation_dummy.cpp:112\n#, fuzzy\n#| msgid \"Magistrate\"\nmsgctxt \"monster\"\nmsgid \"Magistrate\"\nmsgstr \"地方​執​法官\"\n\n#: Source/translation_dummy.cpp:113\n#, fuzzy\n#| msgid \"Cabalist\"\nmsgctxt \"monster\"\nmsgid \"Cabalist\"\nmsgstr \"陰​謀家\"\n\n#: Source/translation_dummy.cpp:114\n#, fuzzy\n#| msgid \"Advocate\"\nmsgctxt \"monster\"\nmsgid \"Advocate\"\nmsgstr \"提倡\"\n\n#: Source/translation_dummy.cpp:115\n#, fuzzy\n#| msgid \"Golem\"\nmsgctxt \"monster\"\nmsgid \"Golem\"\nmsgstr \"傀儡​卷軸\"\n\n#: Source/translation_dummy.cpp:116\n#, fuzzy\n#| msgid \"The Dark Lord\"\nmsgctxt \"monster\"\nmsgid \"The Dark Lord\"\nmsgstr \"\"\n\"所以，地圖​上​的​傳說​是​真實​的。連​我​都​不​相信！我​想​是​時候​告訴​你​我​是​誰​了，我​的​朋\"\n\"友。你​看，我​並​不​像​我​看​起來​那​樣。。。\\n\"\n\" \\n\"\n\"​我​的​真名​是​老凱恩，我​是​一​個​古老​兄弟會​的​最後​一個​後​代，這個​兄弟​會​致力​於​保守​和​保\"\n\"護​一​個​永恒​邪惡​的​秘密。一​個​很​明顯​已​經​被​釋放​的​惡魔。。。\\n\"\n\" \\n\"\n\"​你​要​對付​的​惡魔​是​恐怖​的​黑魔王​——​凡​人​都​知道​的​迪亞波羅。幾個世紀​前​被​囚禁​在​迷宮裡​\"\n\"的​正​是​他。你​現​在​持有​的​地圖​是​很​久​以前​創造​的，用來標​記​迪亞波羅從​監​禁​中​復活​的​時\"\n\"間。當​那​張​地圖​上​的​兩顆​星星對​齊時，迪亞波羅將達​到​他​的​能量​頂峰。他​將​所​向​無\"\n\"敵。。。\\n\"\n\" \\n\"\n\"​你​現​在在​和​時間​賽​跑，我​的​朋友！找到​迪亞波羅，在​眾星​雲集​之前​消滅​他，因​為​我​們​可\"\n\"能​再​也​沒​有​機會擺脫​他​的​邪惡​了\"\n\n#: Source/translation_dummy.cpp:117\n#, fuzzy\n#| msgid \"The Arch-Litch Malignus\"\nmsgctxt \"monster\"\nmsgid \"The Arch-Litch Malignus\"\nmsgstr \"大​天使​的\"\n\n#: Source/translation_dummy.cpp:118\n#, fuzzy\n#| msgid \"Gharbad the Weak\"\nmsgctxt \"monster\"\nmsgid \"Gharbad the Weak\"\nmsgstr \"加巴德弱者\"\n\n#: Source/translation_dummy.cpp:119\nmsgctxt \"monster\"\nmsgid \"Zhar the Mad\"\nmsgstr \"瘋狂​的​扎爾\"\n\n#: Source/translation_dummy.cpp:120\n#, fuzzy\n#| msgid \"Snotspill\"\nmsgctxt \"monster\"\nmsgid \"Snotspill\"\nmsgstr \"鼻涕​丸\"\n\n#: Source/translation_dummy.cpp:121\n#, fuzzy\n#| msgid \"Arch-Bishop Lazarus\"\nmsgctxt \"monster\"\nmsgid \"Arch-Bishop Lazarus\"\nmsgstr \"大​天使​的\"\n\n#: Source/translation_dummy.cpp:122\n#, fuzzy\n#| msgid \"Red Vex\"\nmsgctxt \"monster\"\nmsgid \"Red Vex\"\nmsgstr \"丹紅\"\n\n#: Source/translation_dummy.cpp:123\n#, fuzzy\n#| msgid \"Black Jade\"\nmsgctxt \"monster\"\nmsgid \"Black Jade\"\nmsgstr \"碧玉\"\n\n#: Source/translation_dummy.cpp:124\nmsgctxt \"monster\"\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:125\nmsgctxt \"monster\"\nmsgid \"Warlord of Blood\"\nmsgstr \"鮮​血督軍\"\n\n#: Source/translation_dummy.cpp:126\n#, fuzzy\n#| msgid \"Hork Demon\"\nmsgctxt \"monster\"\nmsgid \"Hork Demon\"\nmsgstr \"惡​魔\"\n\n#: Source/translation_dummy.cpp:127\nmsgctxt \"monster\"\nmsgid \"The Defiler\"\nmsgstr \"污染者\"\n\n#: Source/translation_dummy.cpp:128\nmsgctxt \"monster\"\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:129\n#, fuzzy\n#| msgid \"Bonehead Keenaxe\"\nmsgctxt \"monster\"\nmsgid \"Bonehead Keenaxe\"\nmsgstr \"骷​髏頭\"\n\n#: Source/translation_dummy.cpp:130\n#, fuzzy\n#| msgid \"Bladeskin the Slasher\"\nmsgctxt \"monster\"\nmsgid \"Bladeskin the Slasher\"\nmsgstr \"刀​砍​機​中​的​刀鋒\"\n\n#: Source/translation_dummy.cpp:131\n#, fuzzy\n#| msgid \"Soulpus\"\nmsgctxt \"monster\"\nmsgid \"Soulpus\"\nmsgstr \"靈​魂\"\n\n#: Source/translation_dummy.cpp:132\n#, fuzzy\n#| msgid \"Pukerat the Unclean\"\nmsgctxt \"monster\"\nmsgid \"Pukerat the Unclean\"\nmsgstr \"吐​在​不​乾淨​的​地方\"\n\n#: Source/translation_dummy.cpp:133\n#, fuzzy\n#| msgid \"Boneripper\"\nmsgctxt \"monster\"\nmsgid \"Boneripper\"\nmsgstr \"博內​里​珀\"\n\n#: Source/translation_dummy.cpp:134\n#, fuzzy\n#| msgid \"Rotfeast the Hungry\"\nmsgctxt \"monster\"\nmsgid \"Rotfeast the Hungry\"\nmsgstr \"讓​飢餓​的​人​飽餐​一​頓\"\n\n#: Source/translation_dummy.cpp:135\n#, fuzzy\n#| msgid \"Gutshank the Quick\"\nmsgctxt \"monster\"\nmsgid \"Gutshank the Quick\"\nmsgstr \"加速​攻擊\"\n\n#: Source/translation_dummy.cpp:136\n#, fuzzy\n#| msgid \"Brokenhead Bangshield\"\nmsgctxt \"monster\"\nmsgid \"Brokenhead Bangshield\"\nmsgstr \"斷​頭盾\"\n\n#: Source/translation_dummy.cpp:137\nmsgctxt \"monster\"\nmsgid \"Bongo\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:138\n#, fuzzy\n#| msgid \"Rotcarnage\"\nmsgctxt \"monster\"\nmsgid \"Rotcarnage\"\nmsgstr \"輪​迴​屠殺\"\n\n#: Source/translation_dummy.cpp:139\n#, fuzzy\n#| msgid \"Shadowbite\"\nmsgctxt \"monster\"\nmsgid \"Shadowbite\"\nmsgstr \"暗影\"\n\n#: Source/translation_dummy.cpp:140\n#, fuzzy\n#| msgid \"Deadeye\"\nmsgctxt \"monster\"\nmsgid \"Deadeye\"\nmsgstr \"死​神\"\n\n#: Source/translation_dummy.cpp:141\n#, fuzzy\n#| msgid \"Madeye the Dead\"\nmsgctxt \"monster\"\nmsgid \"Madeye the Dead\"\nmsgstr \"死者​之​弓\"\n\n#: Source/translation_dummy.cpp:142\nmsgctxt \"monster\"\nmsgid \"El Chupacabras\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:143\n#, fuzzy\n#| msgid \"Skullfire\"\nmsgctxt \"monster\"\nmsgid \"Skullfire\"\nmsgstr \"頭​骨火\"\n\n#: Source/translation_dummy.cpp:144\n#, fuzzy\n#| msgid \"Warpskull\"\nmsgctxt \"monster\"\nmsgid \"Warpskull\"\nmsgstr \"頭​骨翹曲\"\n\n#: Source/translation_dummy.cpp:145\n#, fuzzy\n#| msgid \"Goretongue\"\nmsgctxt \"monster\"\nmsgid \"Goretongue\"\nmsgstr \"戈雷通古\"\n\n#: Source/translation_dummy.cpp:146\n#, fuzzy\n#| msgid \"Pulsecrawler\"\nmsgctxt \"monster\"\nmsgid \"Pulsecrawler\"\nmsgstr \"脈​衝​發生器\"\n\n#: Source/translation_dummy.cpp:147\n#, fuzzy\n#| msgid \"Moonbender\"\nmsgctxt \"monster\"\nmsgid \"Moonbender\"\nmsgstr \"登月者\"\n\n#: Source/translation_dummy.cpp:148\n#, fuzzy\n#| msgid \"Wrathraven\"\nmsgctxt \"monster\"\nmsgid \"Wrathraven\"\nmsgstr \"拉瑟拉文\"\n\n#: Source/translation_dummy.cpp:149\n#, fuzzy\n#| msgid \"Spineeater\"\nmsgctxt \"monster\"\nmsgid \"Spineeater\"\nmsgstr \"刺食者\"\n\n#: Source/translation_dummy.cpp:150\n#, fuzzy\n#| msgid \"Blackash the Burning\"\nmsgctxt \"monster\"\nmsgid \"Blackash the Burning\"\nmsgstr \"燃燒\"\n\n#: Source/translation_dummy.cpp:151\n#, fuzzy\n#| msgid \"Shadowcrow\"\nmsgctxt \"monster\"\nmsgid \"Shadowcrow\"\nmsgstr \"暗影烏​鴉\"\n\n#: Source/translation_dummy.cpp:152\n#, fuzzy\n#| msgid \"Blightstone the Weak\"\nmsgctxt \"monster\"\nmsgid \"Blightstone the Weak\"\nmsgstr \"加巴德弱者\"\n\n#: Source/translation_dummy.cpp:153\n#, fuzzy\n#| msgid \"Bilefroth the Pit Master\"\nmsgctxt \"monster\"\nmsgid \"Bilefroth the Pit Master\"\nmsgstr \"大師​的\"\n\n#: Source/translation_dummy.cpp:154\n#, fuzzy\n#| msgid \"Bloodskin Darkbow\"\nmsgctxt \"monster\"\nmsgid \"Bloodskin Darkbow\"\nmsgstr \"血色​暗影\"\n\n#: Source/translation_dummy.cpp:155\n#, fuzzy\n#| msgid \"Foulwing\"\nmsgctxt \"monster\"\nmsgid \"Foulwing\"\nmsgstr \"福林\"\n\n#: Source/translation_dummy.cpp:156\n#, fuzzy\n#| msgid \"Shadowdrinker\"\nmsgctxt \"monster\"\nmsgid \"Shadowdrinker\"\nmsgstr \"暗飲者\"\n\n#: Source/translation_dummy.cpp:157\n#, fuzzy\n#| msgid \"Hazeshifter\"\nmsgctxt \"monster\"\nmsgid \"Hazeshifter\"\nmsgstr \"危險品​搬運​工\"\n\n#: Source/translation_dummy.cpp:158\n#, fuzzy\n#| msgid \"Deathspit\"\nmsgctxt \"monster\"\nmsgid \"Deathspit\"\nmsgstr \"臨​終遺​言\"\n\n#: Source/translation_dummy.cpp:159\n#, fuzzy\n#| msgid \"Bloodgutter\"\nmsgctxt \"monster\"\nmsgid \"Bloodgutter\"\nmsgstr \"血​溝\"\n\n#: Source/translation_dummy.cpp:160\n#, fuzzy\n#| msgid \"Deathshade Fleshmaul\"\nmsgctxt \"monster\"\nmsgid \"Deathshade Fleshmaul\"\nmsgstr \"死​蔭​肉搏\"\n\n#: Source/translation_dummy.cpp:161\n#, fuzzy\n#| msgid \"Warmaggot the Mad\"\nmsgctxt \"monster\"\nmsgid \"Warmaggot the Mad\"\nmsgstr \"瘋狂​的​扎爾\"\n\n#: Source/translation_dummy.cpp:162\n#, fuzzy\n#| msgid \"Glasskull the Jagged\"\nmsgctxt \"monster\"\nmsgid \"Glasskull the Jagged\"\nmsgstr \"參​差\"\n\n#: Source/translation_dummy.cpp:163\n#, fuzzy\n#| msgid \"Blightfire\"\nmsgctxt \"monster\"\nmsgid \"Blightfire\"\nmsgstr \"疫病\"\n\n#: Source/translation_dummy.cpp:164\n#, fuzzy\n#| msgid \"Nightwing the Cold\"\nmsgctxt \"monster\"\nmsgid \"Nightwing the Cold\"\nmsgstr \"寒冷​的​夜晚\"\n\n#: Source/translation_dummy.cpp:165\n#, fuzzy\n#| msgid \"Gorestone\"\nmsgctxt \"monster\"\nmsgid \"Gorestone\"\nmsgstr \"金石\"\n\n#: Source/translation_dummy.cpp:166\n#, fuzzy\n#| msgid \"Bronzefist Firestone\"\nmsgctxt \"monster\"\nmsgid \"Bronzefist Firestone\"\nmsgstr \"青銅​火石\"\n\n#: Source/translation_dummy.cpp:167\n#, fuzzy\n#| msgid \"Wrathfire the Doomed\"\nmsgctxt \"monster\"\nmsgid \"Wrathfire the Doomed\"\nmsgstr \"憤​怒​之​火註​定\"\n\n#: Source/translation_dummy.cpp:168\n#, fuzzy\n#| msgid \"Firewound the Grim\"\nmsgctxt \"monster\"\nmsgid \"Firewound the Grim\"\nmsgstr \"陰森​的​森林​被​火燒​得​團團轉\"\n\n#: Source/translation_dummy.cpp:169\n#, fuzzy\n#| msgid \"Baron Sludge\"\nmsgctxt \"monster\"\nmsgid \"Baron Sludge\"\nmsgstr \"男​爵​污泥\"\n\n#: Source/translation_dummy.cpp:170\n#, fuzzy\n#| msgid \"Blighthorn Steelmace\"\nmsgctxt \"monster\"\nmsgid \"Blighthorn Steelmace\"\nmsgstr \"白頭蒼​蠅\"\n\n#: Source/translation_dummy.cpp:171\n#, fuzzy\n#| msgid \"Chaoshowler\"\nmsgctxt \"monster\"\nmsgid \"Chaoshowler\"\nmsgstr \"朝​紹勒\"\n\n#: Source/translation_dummy.cpp:172\n#, fuzzy\n#| msgid \"Doomgrin the Rotting\"\nmsgctxt \"monster\"\nmsgid \"Doomgrin the Rotting\"\nmsgstr \"腐爛​中​的​惡作​劇\"\n\n#: Source/translation_dummy.cpp:173\n#, fuzzy\n#| msgid \"Madburner\"\nmsgctxt \"monster\"\nmsgid \"Madburner\"\nmsgstr \"瘋子\"\n\n#: Source/translation_dummy.cpp:174\n#, fuzzy\n#| msgid \"Bonesaw the Litch\"\nmsgctxt \"monster\"\nmsgid \"Bonesaw the Litch\"\nmsgstr \"骨頭​鋸\"\n\n#: Source/translation_dummy.cpp:175\n#, fuzzy\n#| msgid \"Breakspine\"\nmsgctxt \"monster\"\nmsgid \"Breakspine\"\nmsgstr \"斷脊\"\n\n#: Source/translation_dummy.cpp:176\n#, fuzzy\n#| msgid \"Devilskull Sharpbone\"\nmsgctxt \"monster\"\nmsgid \"Devilskull Sharpbone\"\nmsgstr \"魔骨\"\n\n#: Source/translation_dummy.cpp:177\n#, fuzzy\n#| msgid \"Brokenstorm\"\nmsgctxt \"monster\"\nmsgid \"Brokenstorm\"\nmsgstr \"破​壞者\"\n\n#: Source/translation_dummy.cpp:178\n#, fuzzy\n#| msgid \"Stormbane\"\nmsgctxt \"monster\"\nmsgid \"Stormbane\"\nmsgstr \"風​暴軌​跡\"\n\n#: Source/translation_dummy.cpp:179\n#, fuzzy\n#| msgid \"Oozedrool\"\nmsgctxt \"monster\"\nmsgid \"Oozedrool\"\nmsgstr \"蛋​黃\"\n\n#: Source/translation_dummy.cpp:180\n#, fuzzy\n#| msgid \"Goldblight of the Flame\"\nmsgctxt \"monster\"\nmsgid \"Goldblight of the Flame\"\nmsgstr \"火焰\"\n\n#: Source/translation_dummy.cpp:181\n#, fuzzy\n#| msgid \"Blackstorm\"\nmsgctxt \"monster\"\nmsgid \"Blackstorm\"\nmsgstr \"黑色​風​暴\"\n\n#: Source/translation_dummy.cpp:182\n#, fuzzy\n#| msgid \"Plaguewrath\"\nmsgctxt \"monster\"\nmsgid \"Plaguewrath\"\nmsgstr \"瘟疫​之​怒\"\n\n#: Source/translation_dummy.cpp:183\n#, fuzzy\n#| msgid \"The Flayer\"\nmsgctxt \"monster\"\nmsgid \"The Flayer\"\nmsgstr \"鞭子\"\n\n#: Source/translation_dummy.cpp:184\n#, fuzzy\n#| msgid \"Bluehorn\"\nmsgctxt \"monster\"\nmsgid \"Bluehorn\"\nmsgstr \"藍​喇叭\"\n\n#: Source/translation_dummy.cpp:185\n#, fuzzy\n#| msgid \"Warpfire Hellspawn\"\nmsgctxt \"monster\"\nmsgid \"Warpfire Hellspawn\"\nmsgstr \"戰​火地獄產​卵\"\n\n#: Source/translation_dummy.cpp:186\n#, fuzzy\n#| msgid \"Fangspeir\"\nmsgctxt \"monster\"\nmsgid \"Fangspeir\"\nmsgstr \"方​斯皮爾\"\n\n#: Source/translation_dummy.cpp:187\n#, fuzzy\n#| msgid \"Festerskull\"\nmsgctxt \"monster\"\nmsgid \"Festerskull\"\nmsgstr \"費​斯特斯庫爾\"\n\n#: Source/translation_dummy.cpp:188\n#, fuzzy\n#| msgid \"Lionskull the Bent\"\nmsgctxt \"monster\"\nmsgid \"Lionskull the Bent\"\nmsgstr \"彎​曲\"\n\n#: Source/translation_dummy.cpp:189\n#, fuzzy\n#| msgid \"Blacktongue\"\nmsgctxt \"monster\"\nmsgid \"Blacktongue\"\nmsgstr \"黑舌\"\n\n#: Source/translation_dummy.cpp:190\n#, fuzzy\n#| msgid \"Viletouch\"\nmsgctxt \"monster\"\nmsgid \"Viletouch\"\nmsgstr \"Viletouch村\"\n\n#: Source/translation_dummy.cpp:191\n#, fuzzy\n#| msgid \"Viperflame\"\nmsgctxt \"monster\"\nmsgid \"Viperflame\"\nmsgstr \"毒​蛇\"\n\n#: Source/translation_dummy.cpp:192\n#, fuzzy\n#| msgid \"Fangskin\"\nmsgctxt \"monster\"\nmsgid \"Fangskin\"\nmsgstr \"牙​皮\"\n\n#: Source/translation_dummy.cpp:193\n#, fuzzy\n#| msgid \"Witchfire the Unholy\"\nmsgctxt \"monster\"\nmsgid \"Witchfire the Unholy\"\nmsgstr \"邪惡​的​祭壇\"\n\n#: Source/translation_dummy.cpp:194\n#, fuzzy\n#| msgid \"Blackskull\"\nmsgctxt \"monster\"\nmsgid \"Blackskull\"\nmsgstr \"黑​頭​骨\"\n\n#: Source/translation_dummy.cpp:195\n#, fuzzy\n#| msgid \"Soulslash\"\nmsgctxt \"monster\"\nmsgid \"Soulslash\"\nmsgstr \"靈魂衝擊\"\n\n#: Source/translation_dummy.cpp:196\n#, fuzzy\n#| msgid \"Windspawn\"\nmsgctxt \"monster\"\nmsgid \"Windspawn\"\nmsgstr \"風​擋\"\n\n#: Source/translation_dummy.cpp:197\n#, fuzzy\n#| msgid \"Lord of the Pit\"\nmsgctxt \"monster\"\nmsgid \"Lord of the Pit\"\nmsgstr \"坑\"\n\n#: Source/translation_dummy.cpp:198\n#, fuzzy\n#| msgid \"Rustweaver\"\nmsgctxt \"monster\"\nmsgid \"Rustweaver\"\nmsgstr \"銹​織​工\"\n\n#: Source/translation_dummy.cpp:199\n#, fuzzy\n#| msgid \"Howlingire the Shade\"\nmsgctxt \"monster\"\nmsgid \"Howlingire the Shade\"\nmsgstr \"在​陰涼​處嚎叫\"\n\n#: Source/translation_dummy.cpp:200\n#, fuzzy\n#| msgid \"Doomcloud\"\nmsgctxt \"monster\"\nmsgid \"Doomcloud\"\nmsgstr \"末​日​之​聲\"\n\n#: Source/translation_dummy.cpp:201\n#, fuzzy\n#| msgid \"Bloodmoon Soulfire\"\nmsgctxt \"monster\"\nmsgid \"Bloodmoon Soulfire\"\nmsgstr \"血月​靈魂​之​火\"\n\n#: Source/translation_dummy.cpp:202\n#, fuzzy\n#| msgid \"Witchmoon\"\nmsgctxt \"monster\"\nmsgid \"Witchmoon\"\nmsgstr \"女​巫​月亮\"\n\n#: Source/translation_dummy.cpp:203\n#, fuzzy\n#| msgid \"Gorefeast\"\nmsgctxt \"monster\"\nmsgid \"Gorefeast\"\nmsgstr \"戈雷弗特\"\n\n#: Source/translation_dummy.cpp:204\n#, fuzzy\n#| msgid \"Graywar the Slayer\"\nmsgctxt \"monster\"\nmsgid \"Graywar the Slayer\"\nmsgstr \"格雷瓦爾​殺手\"\n\n#: Source/translation_dummy.cpp:205\n#, fuzzy\n#| msgid \"Dreadjudge\"\nmsgctxt \"monster\"\nmsgid \"Dreadjudge\"\nmsgstr \"恐懼​法官\"\n\n#: Source/translation_dummy.cpp:206\n#, fuzzy\n#| msgid \"Stareye the Witch\"\nmsgctxt \"monster\"\nmsgid \"Stareye the Witch\"\nmsgstr \"女​巫艾德里亞\"\n\n#: Source/translation_dummy.cpp:207\n#, fuzzy\n#| msgid \"Steelskull the Hunter\"\nmsgctxt \"monster\"\nmsgid \"Steelskull the Hunter\"\nmsgstr \"致命​的​獵人\"\n\n#: Source/translation_dummy.cpp:208\n#, fuzzy\n#| msgid \"Sir Gorash\"\nmsgctxt \"monster\"\nmsgid \"Sir Gorash\"\nmsgstr \"戈拉什​爵士\"\n\n#: Source/translation_dummy.cpp:209\n#, fuzzy\n#| msgid \"The Vizier\"\nmsgctxt \"monster\"\nmsgid \"The Vizier\"\nmsgstr \"維​齊爾\"\n\n#: Source/translation_dummy.cpp:210\n#, fuzzy\n#| msgid \"Sapphire\"\nmsgctxt \"monster\"\nmsgid \"Zamphir\"\nmsgstr \"藍​寶石\"\n\n#: Source/translation_dummy.cpp:211\n#, fuzzy\n#| msgid \"Bloodlust\"\nmsgctxt \"monster\"\nmsgid \"Bloodlust\"\nmsgstr \"嗜​血\"\n\n#: Source/translation_dummy.cpp:212\nmsgctxt \"monster\"\nmsgid \"Webwidow\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:213\n#, fuzzy\n#| msgid \"Fleshdancer\"\nmsgctxt \"monster\"\nmsgid \"Fleshdancer\"\nmsgstr \"肉身​舞者\"\n\n#: Source/translation_dummy.cpp:214\n#, fuzzy\n#| msgid \"Grimspike\"\nmsgctxt \"monster\"\nmsgid \"Grimspike\"\nmsgstr \"格里姆斯派克\"\n\n#: Source/translation_dummy.cpp:215\n#, fuzzy\n#| msgid \"Doomlock\"\nmsgctxt \"monster\"\nmsgid \"Doomlock\"\nmsgstr \"杜姆洛克\"\n\n#: Source/translation_dummy.cpp:217\nmsgid \"Short Sword\"\nmsgstr \"短​劍\"\n\n#: Source/translation_dummy.cpp:218\nmsgid \"Buckler\"\nmsgstr \"小​圓盾\"\n\n#: Source/translation_dummy.cpp:219\nmsgid \"Club\"\nmsgstr \"木棒\"\n\n#: Source/translation_dummy.cpp:220\nmsgid \"Short Bow\"\nmsgstr \"短弓\"\n\n#: Source/translation_dummy.cpp:221\nmsgid \"Short Staff of Mana\"\nmsgstr \"法力​不足\"\n\n#: Source/translation_dummy.cpp:222\nmsgid \"Cleaver\"\nmsgstr \"切肉者\"\n\n#: Source/translation_dummy.cpp:223\nmsgid \"The Undead Crown\"\nmsgstr \"不​死​之​冠\"\n\n#: Source/translation_dummy.cpp:224\nmsgid \"Empyrean Band\"\nmsgstr \"太​陽帶\"\n\n#: Source/translation_dummy.cpp:225\nmsgid \"Magic Rock\"\nmsgstr \"魔石\"\n\n#: Source/translation_dummy.cpp:226\nmsgid \"Optic Amulet\"\nmsgstr \"神聖護​符\"\n\n#: Source/translation_dummy.cpp:227\nmsgid \"Ring of Truth\"\nmsgstr \"真理​之​環\"\n\n#: Source/translation_dummy.cpp:228\nmsgid \"Tavern Sign\"\nmsgstr \"酒店​招牌\"\n\n#: Source/translation_dummy.cpp:229\nmsgid \"Harlequin Crest\"\nmsgstr \"諧角​之​冠\"\n\n#: Source/translation_dummy.cpp:230\nmsgid \"Veil of Steel\"\nmsgstr \"鋼​鐵面紗\"\n\n#: Source/translation_dummy.cpp:231\nmsgid \"Golden Elixir\"\nmsgstr \"金丹\"\n\n#: Source/translation_dummy.cpp:232\nmsgid \"Anvil of Fury\"\nmsgstr \"憤怒​的​鐵砧\"\n\n#: Source/translation_dummy.cpp:233\nmsgid \"Black Mushroom\"\nmsgstr \"黑​蘑菇\"\n\n#: Source/translation_dummy.cpp:234\nmsgid \"Brain\"\nmsgstr \"大​腦\"\n\n#: Source/translation_dummy.cpp:235\nmsgid \"Fungal Tome\"\nmsgstr \"真​菌​切片​機\"\n\n#: Source/translation_dummy.cpp:236\nmsgid \"Spectral Elixir\"\nmsgstr \"光​譜藥劑\"\n\n#: Source/translation_dummy.cpp:237\nmsgid \"Blood Stone\"\nmsgstr \"血石\"\n\n#: Source/translation_dummy.cpp:238\nmsgid \"Cathedral Map\"\nmsgstr \"大​教堂​地​圖\"\n\n#: Source/translation_dummy.cpp:239\nmsgid \"Ear\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:240\nmsgid \"Potion of Healing\"\nmsgstr \"治​療藥劑\"\n\n#: Source/translation_dummy.cpp:241\nmsgid \"Potion of Mana\"\nmsgstr \"魔力​藥​水\"\n\n#: Source/translation_dummy.cpp:242\nmsgid \"Scroll of Identify\"\nmsgstr \"鑑​定​卷軸\"\n\n#: Source/translation_dummy.cpp:243\nmsgid \"Scroll of Town Portal\"\nmsgstr \"城鎮傳​送​卷軸\"\n\n#: Source/translation_dummy.cpp:244\nmsgid \"Arkaine's Valor\"\nmsgstr \"阿凱尼​的​榮耀\"\n\n#: Source/translation_dummy.cpp:245\nmsgid \"Potion of Full Healing\"\nmsgstr \"完全​治癒藥劑\"\n\n#: Source/translation_dummy.cpp:246\nmsgid \"Potion of Full Mana\"\nmsgstr \"全​法力​藥​劑\"\n\n#: Source/translation_dummy.cpp:247\nmsgid \"Griswold's Edge\"\nmsgstr \"格里斯沃​爾德​之​鋒\"\n\n#: Source/translation_dummy.cpp:248\nmsgid \"Bovine Plate\"\nmsgstr \"牛板\"\n\n#: Source/translation_dummy.cpp:249\nmsgid \"Staff of Lazarus\"\nmsgstr \"拉撒雷茲​之​杖\"\n\n#: Source/translation_dummy.cpp:250\nmsgid \"Scroll of Resurrect\"\nmsgstr \"復​活​卷軸\"\n\n#: Source/translation_dummy.cpp:252\nmsgid \"Short Staff\"\nmsgstr \"短​杖\"\n\n#: Source/translation_dummy.cpp:253\nmsgid \"Sword\"\nmsgstr \"劍\"\n\n#: Source/translation_dummy.cpp:254\nmsgid \"Dagger\"\nmsgstr \"匕首\"\n\n#: Source/translation_dummy.cpp:255\nmsgid \"Rune Bomb\"\nmsgstr \"符文​炸彈\"\n\n#: Source/translation_dummy.cpp:256\nmsgid \"Theodore\"\nmsgstr \"西奧​多\"\n\n#: Source/translation_dummy.cpp:257\nmsgid \"Auric Amulet\"\nmsgstr \"金護符\"\n\n#: Source/translation_dummy.cpp:258\nmsgid \"Torn Note 1\"\nmsgstr \"殘破​的​日記​1\"\n\n#: Source/translation_dummy.cpp:259\nmsgid \"Torn Note 2\"\nmsgstr \"殘破​的​日記​2\"\n\n#: Source/translation_dummy.cpp:260\nmsgid \"Torn Note 3\"\nmsgstr \"殘破​的​日記​3\"\n\n#: Source/translation_dummy.cpp:261\nmsgid \"Reconstructed Note\"\nmsgstr \"重​構​日記\"\n\n#: Source/translation_dummy.cpp:262\nmsgid \"Brown Suit\"\nmsgstr \"棕色套裝\"\n\n#: Source/translation_dummy.cpp:263\nmsgid \"Grey Suit\"\nmsgstr \"灰色​套裝\"\n\n#: Source/translation_dummy.cpp:264\nmsgid \"Cap\"\nmsgstr \"軟​帽\"\n\n#: Source/translation_dummy.cpp:265\nmsgid \"Skull Cap\"\nmsgstr \"骷​髏​帽\"\n\n#: Source/translation_dummy.cpp:266\nmsgid \"Helm\"\nmsgstr \"頭盔\"\n\n#: Source/translation_dummy.cpp:267\nmsgid \"Full Helm\"\nmsgstr \"全​護盔\"\n\n#: Source/translation_dummy.cpp:268\nmsgid \"Crown\"\nmsgstr \"王冠\"\n\n#: Source/translation_dummy.cpp:269\nmsgid \"Great Helm\"\nmsgstr \"重盔\"\n\n#: Source/translation_dummy.cpp:270\nmsgid \"Cape\"\nmsgstr \"披肩\"\n\n#: Source/translation_dummy.cpp:271\nmsgid \"Rags\"\nmsgstr \"短​披風\"\n\n#: Source/translation_dummy.cpp:272\nmsgid \"Cloak\"\nmsgstr \"披風\"\n\n#: Source/translation_dummy.cpp:273\nmsgid \"Robe\"\nmsgstr \"長​袍\"\n\n#: Source/translation_dummy.cpp:274\nmsgid \"Quilted Armor\"\nmsgstr \"內​襯​甲\"\n\n#: Source/translation_dummy.cpp:276\nmsgid \"Leather Armor\"\nmsgstr \"皮甲\"\n\n#: Source/translation_dummy.cpp:277\nmsgid \"Hard Leather Armor\"\nmsgstr \"硬​皮甲\"\n\n#: Source/translation_dummy.cpp:278\nmsgid \"Studded Leather Armor\"\nmsgstr \"釘​皮甲\"\n\n#: Source/translation_dummy.cpp:279\nmsgid \"Ring Mail\"\nmsgstr \"環​甲\"\n\n#: Source/translation_dummy.cpp:280\nmsgid \"Mail\"\nmsgstr \"鎖​甲\"\n\n#: Source/translation_dummy.cpp:281\nmsgid \"Chain Mail\"\nmsgstr \"鎖子​甲\"\n\n#: Source/translation_dummy.cpp:282\nmsgid \"Scale Mail\"\nmsgstr \"魚​鱗​甲\"\n\n#: Source/translation_dummy.cpp:283\nmsgid \"Breast Plate\"\nmsgstr \"胸片​甲\"\n\n#: Source/translation_dummy.cpp:284\nmsgid \"Plate\"\nmsgstr \"板​甲\"\n\n#: Source/translation_dummy.cpp:285\nmsgid \"Splint Mail\"\nmsgstr \"板​條​甲\"\n\n#: Source/translation_dummy.cpp:286\nmsgid \"Plate Mail\"\nmsgstr \"板​鍊​甲\"\n\n#: Source/translation_dummy.cpp:287\nmsgid \"Field Plate\"\nmsgstr \"全身​板​甲\"\n\n#: Source/translation_dummy.cpp:288\nmsgid \"Gothic Plate\"\nmsgstr \"哥特​甲\"\n\n#: Source/translation_dummy.cpp:289\nmsgid \"Full Plate Mail\"\nmsgstr \"全身​板鍊​甲\"\n\n#: Source/translation_dummy.cpp:290\nmsgid \"Shield\"\nmsgstr \"之​盾\"\n\n#: Source/translation_dummy.cpp:291\nmsgid \"Small Shield\"\nmsgstr \"小​盾\"\n\n#: Source/translation_dummy.cpp:292\nmsgid \"Large Shield\"\nmsgstr \"大​盾\"\n\n#: Source/translation_dummy.cpp:293\nmsgid \"Kite Shield\"\nmsgstr \"鳶盾\"\n\n#: Source/translation_dummy.cpp:294\nmsgid \"Tower Shield\"\nmsgstr \"塔盾\"\n\n#: Source/translation_dummy.cpp:295\nmsgid \"Gothic Shield\"\nmsgstr \"哥特盾\"\n\n#: Source/translation_dummy.cpp:296\nmsgid \"Potion of Rejuvenation\"\nmsgstr \"活力​恢復​藥​水\"\n\n#: Source/translation_dummy.cpp:297\nmsgid \"Potion of Full Rejuvenation\"\nmsgstr \"完全​活力​恢復​藥​水\"\n\n#: Source/translation_dummy.cpp:300\nmsgid \"Oil\"\nmsgstr \"油\"\n\n#: Source/translation_dummy.cpp:301\nmsgid \"Elixir of Strength\"\nmsgstr \"力量​藥劑\"\n\n#: Source/translation_dummy.cpp:302\nmsgid \"Elixir of Magic\"\nmsgstr \"魔法​藥劑\"\n\n#: Source/translation_dummy.cpp:303\nmsgid \"Elixir of Dexterity\"\nmsgstr \"敏捷藥​劑\"\n\n#: Source/translation_dummy.cpp:304\nmsgid \"Elixir of Vitality\"\nmsgstr \"活力​藥劑\"\n\n#: Source/translation_dummy.cpp:305\nmsgid \"Scroll of Healing\"\nmsgstr \"治​療​卷軸\"\n\n#: Source/translation_dummy.cpp:306\nmsgid \"Scroll of Search\"\nmsgstr \"搜索​卷軸\"\n\n#: Source/translation_dummy.cpp:307\nmsgid \"Scroll of Lightning\"\nmsgstr \"閃​電​卷軸\"\n\n#: Source/translation_dummy.cpp:308\nmsgid \"Scroll of Fire Wall\"\nmsgstr \"火焰​墻​卷軸\"\n\n#: Source/translation_dummy.cpp:309\nmsgid \"Scroll of Inferno\"\nmsgstr \"地​獄​火卷軸\"\n\n#: Source/translation_dummy.cpp:310\nmsgid \"Scroll of Flash\"\nmsgstr \"閃​光​卷軸\"\n\n#: Source/translation_dummy.cpp:311\nmsgid \"Scroll of Infravision\"\nmsgstr \"夜​視​卷軸\"\n\n#: Source/translation_dummy.cpp:312\nmsgid \"Scroll of Phasing\"\nmsgstr \"相位​調​整​卷​軸\"\n\n#: Source/translation_dummy.cpp:313\nmsgid \"Scroll of Mana Shield\"\nmsgstr \"法力​盾​卷軸\"\n\n#: Source/translation_dummy.cpp:314\nmsgid \"Scroll of Flame Wave\"\nmsgstr \"火焰​波卷軸\"\n\n#: Source/translation_dummy.cpp:315\nmsgid \"Scroll of Fireball\"\nmsgstr \"火球卷​軸\"\n\n#: Source/translation_dummy.cpp:316\nmsgid \"Scroll of Stone Curse\"\nmsgstr \"石咒​卷軸\"\n\n#: Source/translation_dummy.cpp:317\nmsgid \"Scroll of Chain Lightning\"\nmsgstr \"連​環閃​電​卷軸\"\n\n#: Source/translation_dummy.cpp:318\nmsgid \"Scroll of Guardian\"\nmsgstr \"守​護者​卷軸\"\n\n#: Source/translation_dummy.cpp:319\nmsgid \"Scroll of Nova\"\nmsgstr \"閃​電​新​星卷軸\"\n\n#: Source/translation_dummy.cpp:320\nmsgid \"Scroll of Golem\"\nmsgstr \"傀儡​卷軸\"\n\n#: Source/translation_dummy.cpp:321\nmsgid \"Scroll of Teleport\"\nmsgstr \"傳​送​卷軸\"\n\n#: Source/translation_dummy.cpp:322\nmsgid \"Scroll of Apocalypse\"\nmsgstr \"啓示錄​卷軸\"\n\n#: Source/translation_dummy.cpp:323\nmsgid \"Falchion\"\nmsgstr \"彎​刃劍\"\n\n#: Source/translation_dummy.cpp:324\nmsgid \"Scimitar\"\nmsgstr \"彎​刀\"\n\n#: Source/translation_dummy.cpp:325\nmsgid \"Claymore\"\nmsgstr \"雙​手​大劍\"\n\n#: Source/translation_dummy.cpp:326\nmsgid \"Blade\"\nmsgstr \"利刃\"\n\n#: Source/translation_dummy.cpp:327\nmsgid \"Sabre\"\nmsgstr \"軍​刀\"\n\n#: Source/translation_dummy.cpp:328\nmsgid \"Long Sword\"\nmsgstr \"長​劍\"\n\n#: Source/translation_dummy.cpp:329\nmsgid \"Broad Sword\"\nmsgstr \"闊​劍\"\n\n#: Source/translation_dummy.cpp:330\nmsgid \"Bastard Sword\"\nmsgstr \"手​半​劍\"\n\n#: Source/translation_dummy.cpp:331\nmsgid \"Two-Handed Sword\"\nmsgstr \"雙​手劍\"\n\n#: Source/translation_dummy.cpp:332\nmsgid \"Great Sword\"\nmsgstr \"重​劍\"\n\n#: Source/translation_dummy.cpp:333\nmsgid \"Small Axe\"\nmsgstr \"小​斧\"\n\n#: Source/translation_dummy.cpp:334\nmsgid \"Axe\"\nmsgstr \"斧\"\n\n#: Source/translation_dummy.cpp:335\nmsgid \"Large Axe\"\nmsgstr \"大斧\"\n\n#: Source/translation_dummy.cpp:336\nmsgid \"Broad Axe\"\nmsgstr \"寬刃斧\"\n\n#: Source/translation_dummy.cpp:337\nmsgid \"Battle Axe\"\nmsgstr \"戰鬥斧\"\n\n#: Source/translation_dummy.cpp:338\nmsgid \"Great Axe\"\nmsgstr \"重斧\"\n\n#: Source/translation_dummy.cpp:339\nmsgid \"Mace\"\nmsgstr \"釘​錘\"\n\n#: Source/translation_dummy.cpp:340\nmsgid \"Morning Star\"\nmsgstr \"流星錘\"\n\n#: Source/translation_dummy.cpp:341\nmsgid \"War Hammer\"\nmsgstr \"戰​錘\"\n\n#: Source/translation_dummy.cpp:342\nmsgid \"Hammer\"\nmsgstr \"錘\"\n\n#: Source/translation_dummy.cpp:343\nmsgid \"Spiked Club\"\nmsgstr \"狼​牙棒\"\n\n#: Source/translation_dummy.cpp:344\nmsgid \"Flail\"\nmsgstr \"連枷\"\n\n#: Source/translation_dummy.cpp:345\nmsgid \"Maul\"\nmsgstr \"大​錘\"\n\n#: Source/translation_dummy.cpp:346\nmsgid \"Bow\"\nmsgstr \"弓\"\n\n#: Source/translation_dummy.cpp:347\nmsgid \"Hunter's Bow\"\nmsgstr \"獵​弓\"\n\n#: Source/translation_dummy.cpp:348\nmsgid \"Long Bow\"\nmsgstr \"長​弓\"\n\n#: Source/translation_dummy.cpp:349\nmsgid \"Composite Bow\"\nmsgstr \"複​合弓\"\n\n#: Source/translation_dummy.cpp:350\nmsgid \"Short Battle Bow\"\nmsgstr \"短​戰弓\"\n\n#: Source/translation_dummy.cpp:351\nmsgid \"Long Battle Bow\"\nmsgstr \"長​戰弓\"\n\n#: Source/translation_dummy.cpp:352\nmsgid \"Short War Bow\"\nmsgstr \"短戰​爭弓\"\n\n#: Source/translation_dummy.cpp:353\nmsgid \"Long War Bow\"\nmsgstr \"長​戰​爭弓\"\n\n#: Source/translation_dummy.cpp:355\nmsgid \"Long Staff\"\nmsgstr \"長​杖\"\n\n#: Source/translation_dummy.cpp:356\nmsgid \"Composite Staff\"\nmsgstr \"綜​合​工作人​員\"\n\n#: Source/translation_dummy.cpp:357\nmsgid \"Quarter Staff\"\nmsgstr \"季度​員工\"\n\n#: Source/translation_dummy.cpp:358\nmsgid \"War Staff\"\nmsgstr \"戰​杖\"\n\n#: Source/translation_dummy.cpp:359\nmsgid \"Ring\"\nmsgstr \"戒指\"\n\n#: Source/translation_dummy.cpp:360\nmsgid \"Amulet\"\nmsgstr \"護​符\"\n\n#: Source/translation_dummy.cpp:361\nmsgid \"Rune of Fire\"\nmsgstr \"火符文\"\n\n#: Source/translation_dummy.cpp:362\nmsgid \"Rune\"\nmsgstr \"符文\"\n\n#: Source/translation_dummy.cpp:363\nmsgid \"Rune of Lightning\"\nmsgstr \"閃​電​符文\"\n\n#: Source/translation_dummy.cpp:364\nmsgid \"Greater Rune of Fire\"\nmsgstr \"大火符文\"\n\n#: Source/translation_dummy.cpp:365\nmsgid \"Greater Rune of Lightning\"\nmsgstr \"大​閃​電​符文\"\n\n#: Source/translation_dummy.cpp:366\nmsgid \"Rune of Stone\"\nmsgstr \"符文石\"\n\n#: Source/translation_dummy.cpp:367\nmsgid \"Short Staff of Charged Bolt\"\nmsgstr \"電​荷彈​短​杖\"\n\n#: Source/translation_dummy.cpp:368\nmsgid \"Arena Potion\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:369\nmsgid \"The Butcher's Cleaver\"\nmsgstr \"屠夫​的​切肉刀\"\n\n#: Source/translation_dummy.cpp:370\n#, fuzzy\n#| msgid \"Lightsabre\"\nmsgid \"Lightforge\"\nmsgstr \"光​劍\"\n\n#: Source/translation_dummy.cpp:371\nmsgid \"The Rift Bow\"\nmsgstr \"裂谷​弓\"\n\n#: Source/translation_dummy.cpp:372\nmsgid \"The Needler\"\nmsgstr \"縫​紉​工\"\n\n#: Source/translation_dummy.cpp:373\nmsgid \"The Celestial Bow\"\nmsgstr \"天弓\"\n\n#: Source/translation_dummy.cpp:374\nmsgid \"Deadly Hunter\"\nmsgstr \"致命​的​獵人\"\n\n#: Source/translation_dummy.cpp:375\nmsgid \"Bow of the Dead\"\nmsgstr \"死者​之​弓\"\n\n#: Source/translation_dummy.cpp:376\nmsgid \"The Blackoak Bow\"\nmsgstr \"黑​橡樹​蝴蝶​結\"\n\n#: Source/translation_dummy.cpp:377\nmsgid \"Flamedart\"\nmsgstr \"火焰​鏢\"\n\n#: Source/translation_dummy.cpp:378\nmsgid \"Fleshstinger\"\nmsgstr \"肉​刺\"\n\n#: Source/translation_dummy.cpp:379\nmsgid \"Windforce\"\nmsgstr \"風​之​力\"\n\n#: Source/translation_dummy.cpp:380\nmsgid \"Eaglehorn\"\nmsgstr \"鷹​之​號​角\"\n\n#: Source/translation_dummy.cpp:381\nmsgid \"Gonnagal's Dirk\"\nmsgstr \"貢​納​加爾​的​德克\"\n\n#: Source/translation_dummy.cpp:382\nmsgid \"The Defender\"\nmsgstr \"防守者\"\n\n#: Source/translation_dummy.cpp:383\nmsgid \"Gryphon's Claw\"\nmsgstr \"鷹​頭​獅​爪\"\n\n#: Source/translation_dummy.cpp:384\nmsgid \"Black Razor\"\nmsgstr \"黑色​剃刀\"\n\n#: Source/translation_dummy.cpp:385\nmsgid \"Gibbous Moon\"\nmsgstr \"凸月\"\n\n#: Source/translation_dummy.cpp:386\nmsgid \"Ice Shank\"\nmsgstr \"冰柄\"\n\n#: Source/translation_dummy.cpp:387\nmsgid \"The Executioner's Blade\"\nmsgstr \"劊子​手​之​刃\"\n\n#: Source/translation_dummy.cpp:388\nmsgid \"The Bonesaw\"\nmsgstr \"骨頭​鋸\"\n\n#: Source/translation_dummy.cpp:389\nmsgid \"Shadowhawk\"\nmsgstr \"暗鷹\"\n\n#: Source/translation_dummy.cpp:390\nmsgid \"Wizardspike\"\nmsgstr \"巫師​之​刺\"\n\n#: Source/translation_dummy.cpp:391\nmsgid \"Lightsabre\"\nmsgstr \"光​劍\"\n\n#: Source/translation_dummy.cpp:392\nmsgid \"The Falcon's Talon\"\nmsgstr \"獵鷹​的​爪子\"\n\n#: Source/translation_dummy.cpp:393\nmsgid \"Inferno\"\nmsgstr \"地​獄火\"\n\n#: Source/translation_dummy.cpp:394\nmsgid \"Doombringer\"\nmsgstr \"末​日​使者\"\n\n#: Source/translation_dummy.cpp:395\nmsgid \"The Grizzly\"\nmsgstr \"灰熊\"\n\n#: Source/translation_dummy.cpp:396\nmsgid \"The Grandfather\"\nmsgstr \"祖父\"\n\n#: Source/translation_dummy.cpp:397\nmsgid \"The Mangler\"\nmsgstr \"馬​槽工\"\n\n#: Source/translation_dummy.cpp:398\nmsgid \"Sharp Beak\"\nmsgstr \"銳利鳥嘴\"\n\n#: Source/translation_dummy.cpp:399\nmsgid \"BloodSlayer\"\nmsgstr \"吸血​鬼\"\n\n#: Source/translation_dummy.cpp:400\nmsgid \"The Celestial Axe\"\nmsgstr \"天斧\"\n\n#: Source/translation_dummy.cpp:401\nmsgid \"Wicked Axe\"\nmsgstr \"邪惡​的​斧頭\"\n\n#: Source/translation_dummy.cpp:402\nmsgid \"Stonecleaver\"\nmsgstr \"石工\"\n\n#: Source/translation_dummy.cpp:403\nmsgid \"Aguinara's Hatchet\"\nmsgstr \"阿吉納拉斧頭\"\n\n#: Source/translation_dummy.cpp:404\nmsgid \"Hellslayer\"\nmsgstr \"地​獄​屠戮者\"\n\n#: Source/translation_dummy.cpp:405\nmsgid \"Messerschmidt's Reaver\"\nmsgstr \"梅​塞施密特​的​劫掠者\"\n\n#: Source/translation_dummy.cpp:406\nmsgid \"Crackrust\"\nmsgstr \"裂紋\"\n\n#: Source/translation_dummy.cpp:407\nmsgid \"Hammer of Jholm\"\nmsgstr \"霍爾姆​之錘\"\n\n#: Source/translation_dummy.cpp:408\nmsgid \"Civerb's Cudgel\"\nmsgstr \"希弗柏​的​短棍\"\n\n#: Source/translation_dummy.cpp:409\nmsgid \"The Celestial Star\"\nmsgstr \"天​上​的​星星\"\n\n#: Source/translation_dummy.cpp:410\nmsgid \"Baranar's Star\"\nmsgstr \"巴拉納​之​星\"\n\n#: Source/translation_dummy.cpp:411\nmsgid \"Gnarled Root\"\nmsgstr \"多​節根\"\n\n#: Source/translation_dummy.cpp:412\nmsgid \"The Cranium Basher\"\nmsgstr \"碎​顱\"\n\n#: Source/translation_dummy.cpp:413\nmsgid \"Schaefer's Hammer\"\nmsgstr \"舍​費爾​之​錘\"\n\n#: Source/translation_dummy.cpp:414\nmsgid \"Dreamflange\"\nmsgstr \"夢​幻法蘭\"\n\n#: Source/translation_dummy.cpp:415\nmsgid \"Staff of Shadows\"\nmsgstr \"暗影​之​杖\"\n\n#: Source/translation_dummy.cpp:416\nmsgid \"Immolator\"\nmsgstr \"固定器\"\n\n#: Source/translation_dummy.cpp:417\nmsgid \"Storm Spire\"\nmsgstr \"風​暴尖​塔\"\n\n#: Source/translation_dummy.cpp:418\nmsgid \"Gleamsong\"\nmsgstr \"格里姆松\"\n\n#: Source/translation_dummy.cpp:419\nmsgid \"Thundercall\"\nmsgstr \"雷鳴​呼叫\"\n\n#: Source/translation_dummy.cpp:420\nmsgid \"The Protector\"\nmsgstr \"保護者\"\n\n#: Source/translation_dummy.cpp:421\nmsgid \"Naj's Puzzler\"\nmsgstr \"諾吉​的​解密棒\"\n\n#: Source/translation_dummy.cpp:422\nmsgid \"Mindcry\"\nmsgstr \"心​聲\"\n\n#: Source/translation_dummy.cpp:423\nmsgid \"Rod of Onan\"\nmsgstr \"奧​南​之​棒\"\n\n#: Source/translation_dummy.cpp:424\nmsgid \"Helm of Spirits\"\nmsgstr \"精靈​之​舵\"\n\n#: Source/translation_dummy.cpp:425\nmsgid \"Thinking Cap\"\nmsgstr \"思考帽\"\n\n#: Source/translation_dummy.cpp:426\nmsgid \"OverLord's Helm\"\nmsgstr \"霸王舵\"\n\n#: Source/translation_dummy.cpp:427\nmsgid \"Fool's Crest\"\nmsgstr \"傻瓜​的​徽章\"\n\n#: Source/translation_dummy.cpp:428\nmsgid \"Gotterdamerung\"\nmsgstr \"戈特達梅隆\"\n\n#: Source/translation_dummy.cpp:429\nmsgid \"Royal Circlet\"\nmsgstr \"皇家​環\"\n\n#: Source/translation_dummy.cpp:430\nmsgid \"Torn Flesh of Souls\"\nmsgstr \"撕裂​的​靈魂​之​肉\"\n\n#: Source/translation_dummy.cpp:431\nmsgid \"The Gladiator's Bane\"\nmsgstr \"角​鬥士​之​禍\"\n\n#: Source/translation_dummy.cpp:432\nmsgid \"The Rainbow Cloak\"\nmsgstr \"彩虹​斗篷\"\n\n#: Source/translation_dummy.cpp:433\nmsgid \"Leather of Aut\"\nmsgstr \"Aut​皮革\"\n\n#: Source/translation_dummy.cpp:434\nmsgid \"Wisdom's Wrap\"\nmsgstr \"智慧​的​包裹\"\n\n#: Source/translation_dummy.cpp:435\nmsgid \"Sparking Mail\"\nmsgstr \"電​光鎖​甲\"\n\n#: Source/translation_dummy.cpp:436\nmsgid \"Scavenger Carapace\"\nmsgstr \"食​腐甲殼\"\n\n#: Source/translation_dummy.cpp:437\nmsgid \"Nightscape\"\nmsgstr \"夜景\"\n\n#: Source/translation_dummy.cpp:438\nmsgid \"Naj's Light Plate\"\nmsgstr \"諾吉​的​輕鎧​甲\"\n\n#: Source/translation_dummy.cpp:439\nmsgid \"Demonspike Coat\"\nmsgstr \"魔鬼​長矛​大衣\"\n\n#: Source/translation_dummy.cpp:440\nmsgid \"The Deflector\"\nmsgstr \"偏轉器\"\n\n#: Source/translation_dummy.cpp:441\nmsgid \"Split Skull Shield\"\nmsgstr \"裂顱​護盾\"\n\n#: Source/translation_dummy.cpp:442\nmsgid \"Dragon's Breach\"\nmsgstr \"龍​穴\"\n\n#: Source/translation_dummy.cpp:443\nmsgid \"Blackoak Shield\"\nmsgstr \"黑​橡樹盾\"\n\n#: Source/translation_dummy.cpp:444\nmsgid \"Holy Defender\"\nmsgstr \"神聖​衛士\"\n\n#: Source/translation_dummy.cpp:445\nmsgid \"Stormshield\"\nmsgstr \"暴風​之​盾\"\n\n#: Source/translation_dummy.cpp:446\nmsgid \"Bramble\"\nmsgstr \"刺棘\"\n\n#: Source/translation_dummy.cpp:447\nmsgid \"Ring of Regha\"\nmsgstr \"雷加之​戒\"\n\n#: Source/translation_dummy.cpp:448\nmsgid \"The Bleeder\"\nmsgstr \"出血​點\"\n\n#: Source/translation_dummy.cpp:449\nmsgid \"Constricting Ring\"\nmsgstr \"緊縮​之​戒\"\n\n#: Source/translation_dummy.cpp:450\nmsgid \"Ring of Engagement\"\nmsgstr \"訂​婚戒指\"\n\n#: Source/translation_dummy.cpp:451\nmsgid \"Tin\"\nmsgstr \"錫​金\"\n\n#: Source/translation_dummy.cpp:452\nmsgid \"Brass\"\nmsgstr \"黃​銅\"\n\n#: Source/translation_dummy.cpp:453\nmsgid \"Bronze\"\nmsgstr \"青銅\"\n\n#: Source/translation_dummy.cpp:454\nmsgid \"Iron\"\nmsgstr \"黑​鐵\"\n\n#: Source/translation_dummy.cpp:455\nmsgid \"Steel\"\nmsgstr \"鋼​鐵\"\n\n#: Source/translation_dummy.cpp:456\nmsgid \"Silver\"\nmsgstr \"白銀\"\n\n#: Source/translation_dummy.cpp:457\nmsgid \"Platinum\"\nmsgstr \"白金\"\n\n#: Source/translation_dummy.cpp:458\nmsgid \"Mithril\"\nmsgstr \"秘銀\"\n\n#: Source/translation_dummy.cpp:459\nmsgid \"Meteoric\"\nmsgstr \"隕​鐵\"\n\n#: Source/translation_dummy.cpp:461\nmsgid \"Strange\"\nmsgstr \"奇異\"\n\n#: Source/translation_dummy.cpp:462\nmsgid \"Useless\"\nmsgstr \"無​用​的\"\n\n#: Source/translation_dummy.cpp:463\nmsgid \"Bent\"\nmsgstr \"彎​曲\"\n\n#: Source/translation_dummy.cpp:464\nmsgid \"Weak\"\nmsgstr \"軟弱​的\"\n\n#: Source/translation_dummy.cpp:465\nmsgid \"Jagged\"\nmsgstr \"參​差\"\n\n#: Source/translation_dummy.cpp:466\nmsgid \"Deadly\"\nmsgstr \"致命\"\n\n#: Source/translation_dummy.cpp:467\nmsgid \"Heavy\"\nmsgstr \"沉重​的\"\n\n#: Source/translation_dummy.cpp:468\nmsgid \"Vicious\"\nmsgstr \"兇​惡\"\n\n#: Source/translation_dummy.cpp:469\nmsgid \"Brutal\"\nmsgstr \"殘​忍\"\n\n#: Source/translation_dummy.cpp:470\nmsgid \"Massive\"\nmsgstr \"蠻​橫\"\n\n#: Source/translation_dummy.cpp:471\nmsgid \"Savage\"\nmsgstr \"野​蠻\"\n\n#: Source/translation_dummy.cpp:472\nmsgid \"Ruthless\"\nmsgstr \"無情​的\"\n\n#: Source/translation_dummy.cpp:473\nmsgid \"Merciless\"\nmsgstr \"無​情\"\n\n#: Source/translation_dummy.cpp:474\nmsgid \"Clumsy\"\nmsgstr \"笨拙​的\"\n\n#: Source/translation_dummy.cpp:475\nmsgid \"Dull\"\nmsgstr \"遲鈍​的\"\n\n#: Source/translation_dummy.cpp:476\nmsgid \"Sharp\"\nmsgstr \"鋒利\"\n\n#: Source/translation_dummy.cpp:477\nmsgid \"Fine\"\nmsgstr \"優​良\"\n\n#: Source/translation_dummy.cpp:478\nmsgid \"Warrior's\"\nmsgstr \"戰士​的\"\n\n#: Source/translation_dummy.cpp:479\nmsgid \"Soldier's\"\nmsgstr \"士兵​的\"\n\n#: Source/translation_dummy.cpp:480\nmsgid \"Lord's\"\nmsgstr \"勛​爵​的\"\n\n#: Source/translation_dummy.cpp:481\nmsgid \"Knight's\"\nmsgstr \"騎士​的\"\n\n#: Source/translation_dummy.cpp:482\nmsgid \"Master's\"\nmsgstr \"大師​的\"\n\n#: Source/translation_dummy.cpp:483\nmsgid \"Champion's\"\nmsgstr \"冠軍​的\"\n\n#: Source/translation_dummy.cpp:484\nmsgid \"King's\"\nmsgstr \"國王​的\"\n\n#: Source/translation_dummy.cpp:485\nmsgid \"Vulnerable\"\nmsgstr \"脆弱​的\"\n\n#: Source/translation_dummy.cpp:486\nmsgid \"Rusted\"\nmsgstr \"生鏽​的\"\n\n#: Source/translation_dummy.cpp:487\nmsgid \"Strong\"\nmsgstr \"強​壯\"\n\n#: Source/translation_dummy.cpp:488\nmsgid \"Grand\"\nmsgstr \"大\"\n\n#: Source/translation_dummy.cpp:489\nmsgid \"Valiant\"\nmsgstr \"勇敢​的\"\n\n#: Source/translation_dummy.cpp:490\nmsgid \"Glorious\"\nmsgstr \"光​輝\"\n\n#: Source/translation_dummy.cpp:491\nmsgid \"Blessed\"\nmsgstr \"祝福\"\n\n#: Source/translation_dummy.cpp:492\nmsgid \"Saintly\"\nmsgstr \"聖者\"\n\n#: Source/translation_dummy.cpp:493\nmsgid \"Awesome\"\nmsgstr \"真​棒\"\n\n#: Source/translation_dummy.cpp:495\nmsgid \"Godly\"\nmsgstr \"神祐\"\n\n#: Source/translation_dummy.cpp:496\nmsgid \"Red\"\nmsgstr \"丹紅\"\n\n#: Source/translation_dummy.cpp:497\nmsgid \"Crimson\"\nmsgstr \"猩​紅\"\n\n#: Source/translation_dummy.cpp:498\nmsgid \"Garnet\"\nmsgstr \"石榴\"\n\n#: Source/translation_dummy.cpp:499\nmsgid \"Ruby\"\nmsgstr \"紅​寶石\"\n\n#: Source/translation_dummy.cpp:500\nmsgid \"Blue\"\nmsgstr \"藍色\"\n\n#: Source/translation_dummy.cpp:501\nmsgid \"Azure\"\nmsgstr \"碧空\"\n\n#: Source/translation_dummy.cpp:502\nmsgid \"Lapis\"\nmsgstr \"青​金石\"\n\n#: Source/translation_dummy.cpp:503\nmsgid \"Cobalt\"\nmsgstr \"鈷​藍\"\n\n#: Source/translation_dummy.cpp:504\nmsgid \"Sapphire\"\nmsgstr \"藍​寶石\"\n\n#: Source/translation_dummy.cpp:505\nmsgid \"White\"\nmsgstr \"白色\"\n\n#: Source/translation_dummy.cpp:506\nmsgid \"Pearl\"\nmsgstr \"珍珠\"\n\n#: Source/translation_dummy.cpp:507\nmsgid \"Ivory\"\nmsgstr \"象牙\"\n\n#: Source/translation_dummy.cpp:508\nmsgid \"Crystal\"\nmsgstr \"水晶\"\n\n#: Source/translation_dummy.cpp:509\nmsgid \"Diamond\"\nmsgstr \"鑽石\"\n\n#: Source/translation_dummy.cpp:510\nmsgid \"Topaz\"\nmsgstr \"黃​寶石\"\n\n#: Source/translation_dummy.cpp:511\nmsgid \"Amber\"\nmsgstr \"琥​珀\"\n\n#: Source/translation_dummy.cpp:512\nmsgid \"Jade\"\nmsgstr \"碧玉\"\n\n#: Source/translation_dummy.cpp:513\nmsgid \"Obsidian\"\nmsgstr \"黑​曜石\"\n\n#: Source/translation_dummy.cpp:514\nmsgid \"Emerald\"\nmsgstr \"綠​寶石\"\n\n#: Source/translation_dummy.cpp:515\nmsgid \"Hyena's\"\nmsgstr \"土​狼\"\n\n#: Source/translation_dummy.cpp:516\nmsgid \"Frog's\"\nmsgstr \"青蛙​的\"\n\n#: Source/translation_dummy.cpp:517\nmsgid \"Spider's\"\nmsgstr \"蜘蛛​的\"\n\n#: Source/translation_dummy.cpp:518\nmsgid \"Raven's\"\nmsgstr \"烏鴉​的\"\n\n#: Source/translation_dummy.cpp:519\nmsgid \"Snake's\"\nmsgstr \"毒​蛇​的\"\n\n#: Source/translation_dummy.cpp:520\nmsgid \"Serpent's\"\nmsgstr \"巨蛇​的\"\n\n#: Source/translation_dummy.cpp:521\nmsgid \"Drake's\"\nmsgstr \"幼龍​的\"\n\n#: Source/translation_dummy.cpp:522\nmsgid \"Dragon's\"\nmsgstr \"翼龍​的\"\n\n#: Source/translation_dummy.cpp:523\nmsgid \"Wyrm's\"\nmsgstr \"游龍​的\"\n\n#: Source/translation_dummy.cpp:524\nmsgid \"Hydra's\"\nmsgstr \"海德拉​的\"\n\n#: Source/translation_dummy.cpp:525\nmsgid \"Angel's\"\nmsgstr \"天使​的\"\n\n#: Source/translation_dummy.cpp:526\nmsgid \"Arch-Angel's\"\nmsgstr \"大​天使​的\"\n\n#: Source/translation_dummy.cpp:527\nmsgid \"Plentiful\"\nmsgstr \"豐​富\"\n\n#: Source/translation_dummy.cpp:528\nmsgid \"Bountiful\"\nmsgstr \"慷慨​的\"\n\n#: Source/translation_dummy.cpp:529\nmsgid \"Flaming\"\nmsgstr \"烈​焰\"\n\n#: Source/translation_dummy.cpp:530\nmsgid \"Lightning\"\nmsgstr \"閃​電術\"\n\n#: Source/translation_dummy.cpp:531\nmsgid \"quality\"\nmsgstr \"質量\"\n\n#: Source/translation_dummy.cpp:532\nmsgid \"maiming\"\nmsgstr \"殘​廢\"\n\n#: Source/translation_dummy.cpp:533\nmsgid \"slaying\"\nmsgstr \"殺​戮\"\n\n#: Source/translation_dummy.cpp:534\nmsgid \"gore\"\nmsgstr \"戈爾\"\n\n#: Source/translation_dummy.cpp:535\nmsgid \"carnage\"\nmsgstr \"大​屠​殺\"\n\n#: Source/translation_dummy.cpp:536\nmsgid \"slaughter\"\nmsgstr \"屠宰\"\n\n#: Source/translation_dummy.cpp:537\nmsgid \"pain\"\nmsgstr \"疼痛\"\n\n#: Source/translation_dummy.cpp:538\nmsgid \"tears\"\nmsgstr \"眼​淚\"\n\n#: Source/translation_dummy.cpp:539\nmsgid \"health\"\nmsgstr \"健康\"\n\n#: Source/translation_dummy.cpp:540\nmsgid \"protection\"\nmsgstr \"保護\"\n\n#: Source/translation_dummy.cpp:541\nmsgid \"absorption\"\nmsgstr \"吸收\"\n\n#: Source/translation_dummy.cpp:542\nmsgid \"deflection\"\nmsgstr \"偏轉\"\n\n#: Source/translation_dummy.cpp:543\nmsgid \"osmosis\"\nmsgstr \"滲​透​作用\"\n\n#: Source/translation_dummy.cpp:544\nmsgid \"frailty\"\nmsgstr \"虛弱\"\n\n#: Source/translation_dummy.cpp:545\nmsgid \"weakness\"\nmsgstr \"弱​點\"\n\n#: Source/translation_dummy.cpp:546\nmsgid \"strength\"\nmsgstr \"力量\"\n\n#: Source/translation_dummy.cpp:547\nmsgid \"might\"\nmsgstr \"可以\"\n\n#: Source/translation_dummy.cpp:548\nmsgid \"power\"\nmsgstr \"權力\"\n\n#: Source/translation_dummy.cpp:549\nmsgid \"giants\"\nmsgstr \"巨人\"\n\n#: Source/translation_dummy.cpp:550\nmsgid \"titans\"\nmsgstr \"泰坦\"\n\n#: Source/translation_dummy.cpp:551\nmsgid \"paralysis\"\nmsgstr \"麻痹\"\n\n#: Source/translation_dummy.cpp:552\nmsgid \"atrophy\"\nmsgstr \"萎縮\"\n\n#: Source/translation_dummy.cpp:553\nmsgid \"dexterity\"\nmsgstr \"靈​巧\"\n\n#: Source/translation_dummy.cpp:554\nmsgid \"skill\"\nmsgstr \"技能\"\n\n#: Source/translation_dummy.cpp:555\nmsgid \"accuracy\"\nmsgstr \"精準\"\n\n#: Source/translation_dummy.cpp:556\nmsgid \"precision\"\nmsgstr \"精確\"\n\n#: Source/translation_dummy.cpp:557\nmsgid \"perfection\"\nmsgstr \"完美\"\n\n#: Source/translation_dummy.cpp:558\nmsgid \"the fool\"\nmsgstr \"傻瓜\"\n\n#: Source/translation_dummy.cpp:559\nmsgid \"dyslexia\"\nmsgstr \"誦​讀困難\"\n\n#: Source/translation_dummy.cpp:560\nmsgid \"magic\"\nmsgstr \"魔術\"\n\n#: Source/translation_dummy.cpp:561\nmsgid \"the mind\"\nmsgstr \"頭​腦\"\n\n#: Source/translation_dummy.cpp:562\nmsgid \"brilliance\"\nmsgstr \"輝煌\"\n\n#: Source/translation_dummy.cpp:563\nmsgid \"sorcery\"\nmsgstr \"巫術\"\n\n#: Source/translation_dummy.cpp:564\nmsgid \"wizardry\"\nmsgstr \"巫術\"\n\n#: Source/translation_dummy.cpp:565\nmsgid \"illness\"\nmsgstr \"疾病\"\n\n#: Source/translation_dummy.cpp:566\nmsgid \"disease\"\nmsgstr \"病\"\n\n#: Source/translation_dummy.cpp:567\nmsgid \"vitality\"\nmsgstr \"活力\"\n\n#: Source/translation_dummy.cpp:568\nmsgid \"zest\"\nmsgstr \"熱​情\"\n\n#: Source/translation_dummy.cpp:569\nmsgid \"vim\"\nmsgstr \"維​姆\"\n\n#: Source/translation_dummy.cpp:570\nmsgid \"vigor\"\nmsgstr \"活力\"\n\n#: Source/translation_dummy.cpp:571\nmsgid \"life\"\nmsgstr \"生活\"\n\n#: Source/translation_dummy.cpp:572\nmsgid \"trouble\"\nmsgstr \"麻煩\"\n\n#: Source/translation_dummy.cpp:573\nmsgid \"the pit\"\nmsgstr \"坑\"\n\n#: Source/translation_dummy.cpp:574\nmsgid \"the sky\"\nmsgstr \"天空\"\n\n#: Source/translation_dummy.cpp:575\nmsgid \"the moon\"\nmsgstr \"月亮\"\n\n#: Source/translation_dummy.cpp:576\nmsgid \"the stars\"\nmsgstr \"星星\"\n\n#: Source/translation_dummy.cpp:577\nmsgid \"the heavens\"\nmsgstr \"天堂\"\n\n#: Source/translation_dummy.cpp:578\nmsgid \"the zodiac\"\nmsgstr \"十二​宮\"\n\n#: Source/translation_dummy.cpp:579\nmsgid \"the vulture\"\nmsgstr \"禿​鷲\"\n\n#: Source/translation_dummy.cpp:580\nmsgid \"the jackal\"\nmsgstr \"豺​狼\"\n\n#: Source/translation_dummy.cpp:581\nmsgid \"the fox\"\nmsgstr \"狐貍\"\n\n#: Source/translation_dummy.cpp:582\nmsgid \"the jaguar\"\nmsgstr \"捷豹\"\n\n#: Source/translation_dummy.cpp:583\nmsgid \"the eagle\"\nmsgstr \"老​鷹\"\n\n#: Source/translation_dummy.cpp:584\nmsgid \"the wolf\"\nmsgstr \"狼\"\n\n#: Source/translation_dummy.cpp:585\nmsgid \"the tiger\"\nmsgstr \"老虎\"\n\n#: Source/translation_dummy.cpp:586\nmsgid \"the lion\"\nmsgstr \"獅子\"\n\n#: Source/translation_dummy.cpp:587\nmsgid \"the mammoth\"\nmsgstr \"猛​犸​象\"\n\n#: Source/translation_dummy.cpp:588\nmsgid \"the whale\"\nmsgstr \"鯨​魚\"\n\n#: Source/translation_dummy.cpp:589\nmsgid \"fragility\"\nmsgstr \"脆弱性\"\n\n#: Source/translation_dummy.cpp:590\nmsgid \"brittleness\"\nmsgstr \"脆性\"\n\n#: Source/translation_dummy.cpp:591\nmsgid \"sturdiness\"\nmsgstr \"堅​固性\"\n\n#: Source/translation_dummy.cpp:592\nmsgid \"craftsmanship\"\nmsgstr \"工藝\"\n\n#: Source/translation_dummy.cpp:593\nmsgid \"structure\"\nmsgstr \"結​構\"\n\n#: Source/translation_dummy.cpp:594\nmsgid \"the ages\"\nmsgstr \"年代\"\n\n#: Source/translation_dummy.cpp:595\nmsgid \"the dark\"\nmsgstr \"黑暗\"\n\n#: Source/translation_dummy.cpp:596\nmsgid \"the night\"\nmsgstr \"夜晚\"\n\n#: Source/translation_dummy.cpp:597\nmsgid \"light\"\nmsgstr \"光\"\n\n#: Source/translation_dummy.cpp:598\nmsgid \"radiance\"\nmsgstr \"光​輝\"\n\n#: Source/translation_dummy.cpp:599\nmsgid \"flame\"\nmsgstr \"火焰\"\n\n#: Source/translation_dummy.cpp:600\nmsgid \"fire\"\nmsgstr \"火\"\n\n#: Source/translation_dummy.cpp:601\nmsgid \"burning\"\nmsgstr \"燃燒\"\n\n#: Source/translation_dummy.cpp:602\nmsgid \"shock\"\nmsgstr \"震驚\"\n\n#: Source/translation_dummy.cpp:603\nmsgid \"lightning\"\nmsgstr \"閃​電\"\n\n#: Source/translation_dummy.cpp:604\nmsgid \"thunder\"\nmsgstr \"打​雷\"\n\n#: Source/translation_dummy.cpp:605\nmsgid \"many\"\nmsgstr \"許​多​的\"\n\n#: Source/translation_dummy.cpp:606\nmsgid \"plenty\"\nmsgstr \"大量\"\n\n#: Source/translation_dummy.cpp:607\nmsgid \"thorns\"\nmsgstr \"荊​棘\"\n\n#: Source/translation_dummy.cpp:608\nmsgid \"corruption\"\nmsgstr \"腐敗\"\n\n#: Source/translation_dummy.cpp:609\nmsgid \"thieves\"\nmsgstr \"小偷\"\n\n#: Source/translation_dummy.cpp:610\nmsgid \"the bear\"\nmsgstr \"熊\"\n\n#: Source/translation_dummy.cpp:611\nmsgid \"the bat\"\nmsgstr \"蝙​蝠\"\n\n#: Source/translation_dummy.cpp:612\nmsgid \"vampires\"\nmsgstr \"吸血​鬼\"\n\n#: Source/translation_dummy.cpp:613\nmsgid \"the leech\"\nmsgstr \"水蛭\"\n\n#: Source/translation_dummy.cpp:614\nmsgid \"blood\"\nmsgstr \"血\"\n\n#: Source/translation_dummy.cpp:615\nmsgid \"piercing\"\nmsgstr \"刺骨​的\"\n\n#: Source/translation_dummy.cpp:616\nmsgid \"puncturing\"\nmsgstr \"穿​刺\"\n\n#: Source/translation_dummy.cpp:617\nmsgid \"bashing\"\nmsgstr \"猛擊\"\n\n#: Source/translation_dummy.cpp:618\nmsgid \"readiness\"\nmsgstr \"準備​就​緒\"\n\n#: Source/translation_dummy.cpp:619\nmsgid \"swiftness\"\nmsgstr \"迅捷\"\n\n#: Source/translation_dummy.cpp:620\nmsgid \"speed\"\nmsgstr \"速度\"\n\n#: Source/translation_dummy.cpp:621\nmsgid \"haste\"\nmsgstr \"匆忙\"\n\n#: Source/translation_dummy.cpp:622\nmsgid \"balance\"\nmsgstr \"平衡\"\n\n#: Source/translation_dummy.cpp:623\nmsgid \"stability\"\nmsgstr \"穩定性\"\n\n#: Source/translation_dummy.cpp:624\nmsgid \"harmony\"\nmsgstr \"和​諧\"\n\n#: Source/translation_dummy.cpp:625\nmsgid \"blocking\"\nmsgstr \"舞臺​排程\"\n\n#: Source/translation_dummy.cpp:626\nmsgid \"The Magic Rock\"\nmsgstr \"魔石\"\n\n#: Source/translation_dummy.cpp:627\nmsgid \"Gharbad The Weak\"\nmsgstr \"加巴德弱者\"\n\n#: Source/translation_dummy.cpp:628\nmsgid \"Zhar the Mad\"\nmsgstr \"瘋狂​的​扎爾\"\n\n#: Source/translation_dummy.cpp:629\nmsgid \"Lachdanan\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:631\nmsgid \"The Butcher\"\nmsgstr \"屠夫\"\n\n#: Source/translation_dummy.cpp:632\nmsgid \"Ogden's Sign\"\nmsgstr \"奧​格​登征\"\n\n#: Source/translation_dummy.cpp:633\nmsgid \"Halls of the Blind\"\nmsgstr \"盲​人大​廳\"\n\n#: Source/translation_dummy.cpp:634\nmsgid \"Valor\"\nmsgstr \"英勇\"\n\n#: Source/translation_dummy.cpp:635\nmsgid \"Warlord of Blood\"\nmsgstr \"鮮​血督軍\"\n\n#: Source/translation_dummy.cpp:636\nmsgid \"The Curse of King Leoric\"\nmsgstr \"李奧瑞克國王​的​詛咒\"\n\n#: Source/translation_dummy.cpp:639\nmsgid \"Archbishop Lazarus\"\nmsgstr \"大​主教​拉撒雷茲\"\n\n#: Source/translation_dummy.cpp:640\nmsgid \"Grave Matters\"\nmsgstr \"重大​事​項\"\n\n#: Source/translation_dummy.cpp:641\nmsgid \"Farmer's Orchard\"\nmsgstr \"農​家果園\"\n\n#: Source/translation_dummy.cpp:642\nmsgid \"Little Girl\"\nmsgstr \"小​女孩\"\n\n#: Source/translation_dummy.cpp:643\nmsgid \"Wandering Trader\"\nmsgstr \"遊​蕩​交易者\"\n\n#: Source/translation_dummy.cpp:644\nmsgid \"The Defiler\"\nmsgstr \"污染者\"\n\n#: Source/translation_dummy.cpp:645\nmsgid \"Na-Krul\"\nmsgstr \"\"\n\n#: Source/translation_dummy.cpp:647\nmsgid \"The Jersey's Jersey\"\nmsgstr \"球衣​是​球衣\"\n\n#: Source/translation_dummy.cpp:648\n#, fuzzy\n#| msgid \"Firebolt\"\nmsgctxt \"spell\"\nmsgid \"Firebolt\"\nmsgstr \"火​栓\"\n\n#: Source/translation_dummy.cpp:649\n#, fuzzy\n#| msgid \"Healing\"\nmsgctxt \"spell\"\nmsgid \"Healing\"\nmsgstr \"完全​治癒藥劑\"\n\n#: Source/translation_dummy.cpp:650\nmsgctxt \"spell\"\nmsgid \"Lightning\"\nmsgstr \"閃​電術\"\n\n#: Source/translation_dummy.cpp:651\n#, fuzzy\n#| msgid \"Flash\"\nmsgctxt \"spell\"\nmsgid \"Flash\"\nmsgstr \"閃​光​卷軸\"\n\n#: Source/translation_dummy.cpp:652\n#, fuzzy\n#| msgid \"Identify\"\nmsgctxt \"spell\"\nmsgid \"Identify\"\nmsgstr \"標​識​專案\"\n\n#: Source/translation_dummy.cpp:653\n#, fuzzy\n#| msgid \"Fire Wall\"\nmsgctxt \"spell\"\nmsgid \"Fire Wall\"\nmsgstr \"火焰​墻​卷軸\"\n\n#: Source/translation_dummy.cpp:654\nmsgctxt \"spell\"\nmsgid \"Town Portal\"\nmsgstr \"城鎮​傳​送門\"\n\n#: Source/translation_dummy.cpp:655\n#, fuzzy\n#| msgid \"Stone Curse\"\nmsgctxt \"spell\"\nmsgid \"Stone Curse\"\nmsgstr \"石咒​卷軸\"\n\n#: Source/translation_dummy.cpp:656\n#, fuzzy\n#| msgid \"Infravision\"\nmsgctxt \"spell\"\nmsgid \"Infravision\"\nmsgstr \"夜視​能力\"\n\n#: Source/translation_dummy.cpp:657\n#, fuzzy\n#| msgid \"Phasing\"\nmsgctxt \"spell\"\nmsgid \"Phasing\"\nmsgstr \"相位​調​整​卷​軸\"\n\n#: Source/translation_dummy.cpp:658\n#, fuzzy\n#| msgid \"Mana Shield\"\nmsgctxt \"spell\"\nmsgid \"Mana Shield\"\nmsgstr \"法力​盾​卷軸\"\n\n#: Source/translation_dummy.cpp:659\n#, fuzzy\n#| msgid \"Fireball\"\nmsgctxt \"spell\"\nmsgid \"Fireball\"\nmsgstr \"火球​傷害: {:d}\"\n\n#: Source/translation_dummy.cpp:660\n#, fuzzy\n#| msgid \"Guardian\"\nmsgctxt \"spell\"\nmsgid \"Guardian\"\nmsgstr \"守​護者​卷軸\"\n\n#: Source/translation_dummy.cpp:661\n#, fuzzy\n#| msgid \"Chain Lightning\"\nmsgctxt \"spell\"\nmsgid \"Chain Lightning\"\nmsgstr \"連​環閃​電​卷軸\"\n\n#: Source/translation_dummy.cpp:662\n#, fuzzy\n#| msgid \"Flame Wave\"\nmsgctxt \"spell\"\nmsgid \"Flame Wave\"\nmsgstr \"火焰​波卷軸\"\n\n#: Source/translation_dummy.cpp:663\n#, fuzzy\n#| msgid \"Doom Serpents\"\nmsgctxt \"spell\"\nmsgid \"Doom Serpents\"\nmsgstr \"末​日​之​蛇\"\n\n#: Source/translation_dummy.cpp:664\n#, fuzzy\n#| msgid \"Blood Ritual\"\nmsgctxt \"spell\"\nmsgid \"Blood Ritual\"\nmsgstr \"血石\"\n\n#: Source/translation_dummy.cpp:665\n#, fuzzy\n#| msgid \"Nova\"\nmsgctxt \"spell\"\nmsgid \"Nova\"\nmsgstr \"閃​電​新​星卷軸\"\n\n#: Source/translation_dummy.cpp:666\n#, fuzzy\n#| msgid \"Invisibility\"\nmsgctxt \"spell\"\nmsgid \"Invisibility\"\nmsgstr \"隱形\"\n\n#: Source/translation_dummy.cpp:667\nmsgctxt \"spell\"\nmsgid \"Inferno\"\nmsgstr \"地​獄火\"\n\n#: Source/translation_dummy.cpp:668\n#, fuzzy\n#| msgid \"Golem\"\nmsgctxt \"spell\"\nmsgid \"Golem\"\nmsgstr \"傀儡​卷軸\"\n\n#: Source/translation_dummy.cpp:669\n#, fuzzy\n#| msgid \"Rage\"\nmsgctxt \"spell\"\nmsgid \"Rage\"\nmsgstr \"\"\n\"村​裡​需要​你​的​幫助，好師傅！幾​個​月​前，萊奧​里克國王​的​兒子​阿爾布雷希特​王子​被​綁\"\n\"架。國王勃然大怒，在​村子​裡​到​處尋​找​他​失蹤​的​孩子。日復​一​日，萊奧​里克​似乎​陷入​了​\"\n\"更​深​的​瘋狂​之中。他​試圖​把​男孩​的​失蹤歸咎於​無辜​的​市民，並殘​忍地處決​了​他​們。只​有​\"\n\"不到​一半​的​人從​他​的​瘋狂​中​倖存​下來。。。\\n\"\n\" \\n\"\n\"國王​的​騎士​和​牧師試​圖安撫​他，但​他​轉​而​反對​他​們，不幸​的​是，他​們​被迫殺​了​他。國王\"\n\"臨終​前​一​口​氣對​他​以前​的​追隨者​下​了​一​個​可怕​的​詛咒。他​發誓​他​們會​永遠​在​黑暗中​為​他​\"\n\"服務。。。\\n\"\n\" \\n\"\n\"這​是​事情​發生​了​比​我​想像​的​更​黑暗​的​轉折！我​們​的​前​國​王​已​經從​永恒​的​睡眠​中​醒來，現​\"\n\"在在​迷宮​中​指揮​著​一​支​不​死​僕從​軍團。他​的​屍體​被​埋​在​大​教堂​下面​三​層​的​墳​墓​里。求​你​\"\n\"了，好​主人，通過摧毀​他​現​在​被​詛咒​的​身體來讓​他​的​靈魂​放鬆\"\n\n#: Source/translation_dummy.cpp:670\n#, fuzzy\n#| msgid \"Teleport\"\nmsgctxt \"spell\"\nmsgid \"Teleport\"\nmsgstr \"傳​送​卷軸\"\n\n#: Source/translation_dummy.cpp:671\n#, fuzzy\n#| msgid \"Apocalypse\"\nmsgctxt \"spell\"\nmsgid \"Apocalypse\"\nmsgstr \"啓示錄​卷軸\"\n\n#: Source/translation_dummy.cpp:672\n#, fuzzy\n#| msgid \"Etherealize\"\nmsgctxt \"spell\"\nmsgid \"Etherealize\"\nmsgstr \"以​太化\"\n\n#: Source/translation_dummy.cpp:673\n#, fuzzy\n#| msgid \"Item Repair\"\nmsgctxt \"spell\"\nmsgid \"Item Repair\"\nmsgstr \"修理​專案\"\n\n#: Source/translation_dummy.cpp:674\n#, fuzzy\n#| msgid \"Staff Recharge\"\nmsgctxt \"spell\"\nmsgid \"Staff Recharge\"\nmsgstr \"補​給棒\"\n\n#: Source/translation_dummy.cpp:675\n#, fuzzy\n#| msgid \"Trap Disarm\"\nmsgctxt \"spell\"\nmsgid \"Trap Disarm\"\nmsgstr \"設​定​火焰​陷阱\"\n\n#: Source/translation_dummy.cpp:676\n#, fuzzy\n#| msgid \"Elemental\"\nmsgctxt \"spell\"\nmsgid \"Elemental\"\nmsgstr \"元素\"\n\n#: Source/translation_dummy.cpp:677\n#, fuzzy\n#| msgid \"Charged Bolt\"\nmsgctxt \"spell\"\nmsgid \"Charged Bolt\"\nmsgstr \"電​荷彈​短​杖\"\n\n#: Source/translation_dummy.cpp:678\n#, fuzzy\n#| msgid \"Holy Bolt\"\nmsgctxt \"spell\"\nmsgid \"Holy Bolt\"\nmsgstr \"電​荷彈​短​杖\"\n\n#: Source/translation_dummy.cpp:679\n#, fuzzy\n#| msgid \"Resurrect\"\nmsgctxt \"spell\"\nmsgid \"Resurrect\"\nmsgstr \"復​活​卷軸\"\n\n#: Source/translation_dummy.cpp:680\n#, fuzzy\n#| msgid \"Telekinesis\"\nmsgctxt \"spell\"\nmsgid \"Telekinesis\"\nmsgstr \"心​靈傳​動\"\n\n#: Source/translation_dummy.cpp:681\n#, fuzzy\n#| msgid \"Heal Other\"\nmsgctxt \"spell\"\nmsgid \"Heal Other\"\nmsgstr \"致命​的​治療\"\n\n#: Source/translation_dummy.cpp:682\n#, fuzzy\n#| msgid \"Blood Star\"\nmsgctxt \"spell\"\nmsgid \"Blood Star\"\nmsgstr \"血\"\n\n#: Source/translation_dummy.cpp:683\n#, fuzzy\n#| msgid \"Bone Spirit\"\nmsgctxt \"spell\"\nmsgid \"Bone Spirit\"\nmsgstr \"骨鍊​甲\"\n\n#: Source/translation_dummy.cpp:684\nmsgid \"\"\n\" Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh \"\n\"blow to this land. The people always loved the King, and now they live in \"\n\"mortal fear of him. The question that I keep asking myself is how he could \"\n\"have fallen so far from the Light, as Leoric had always been the holiest of \"\n\"men. Only the vilest powers of Hell could so utterly destroy a man from \"\n\"within...\"\nmsgstr \"\"\n\"啊，我​們​國王​的​故事，是​嗎？李奧瑞克​的​悲慘​淪​陷對​這片​土地​是​一​個​沉重​的​打擊。人民​\"\n\"一直​愛​著​國王，現​在​他​們​生活​在​對​他​的​極度​恐懼​之中。我​一直​在​問​自己​的​問題​是，他​怎\"\n\"么​會落​在​離光這​麼遠​的​地方，因​為​李奧瑞克​一直​是​最​神聖​的​人。只有​地​獄​中​最​邪惡​的​力\"\n\"量​才​能​如此​徹底​地摧毀​一​個​人\"\n\n#: Source/translation_dummy.cpp:685\nmsgid \"\"\n\"The village needs your help, good master! Some months ago King Leoric's son, \"\n\"Prince Albrecht, was kidnapped. The King went into a rage and scoured the \"\n\"village for his missing child. With each passing day, Leoric seemed to slip \"\n\"deeper into madness. He sought to blame innocent townsfolk for the boy's \"\n\"disappearance and had them brutally executed. Less than half of us survived \"\n\"his insanity...\\n\"\n\" \\n\"\n\"The King's Knights and Priests tried to placate him, but he turned against \"\n\"them and sadly, they were forced to kill him. With his dying breath the King \"\n\"called down a terrible curse upon his former followers. He vowed that they \"\n\"would serve him in darkness forever...\\n\"\n\" \\n\"\n\"This is where things take an even darker twist than I thought possible! Our \"\n\"former King has risen from his eternal sleep and now commands a legion of \"\n\"undead minions within the Labyrinth. His body was buried in a tomb three \"\n\"levels beneath the Cathedral. Please, good master, put his soul at ease by \"\n\"destroying his now cursed form...\"\nmsgstr \"\"\n\"村​裡​需要​你​的​幫助，好師傅！幾​個​月​前，萊奧​里克國王​的​兒子​阿爾布雷希特​王子​被​綁\"\n\"架。國王勃然大怒，在​村子​裡​到​處尋​找​他​失蹤​的​孩子。日復​一​日，萊奧​里克​似乎​陷入​了​\"\n\"更​深​的​瘋狂​之中。他​試圖​把​男孩​的​失蹤歸咎於​無辜​的​市民，並殘​忍地處決​了​他​們。只​有​\"\n\"不到​一半​的​人從​他​的​瘋狂​中​倖存​下來。。。\\n\"\n\" \\n\"\n\"國王​的​騎士​和​牧師試​圖安撫​他，但​他​轉​而​反對​他​們，不幸​的​是，他​們​被迫殺​了​他。國王\"\n\"臨終​前​一​口​氣對​他​以前​的​追隨者​下​了​一​個​可怕​的​詛咒。他​發誓​他​們會​永遠​在​黑暗中​為​他​\"\n\"服務。。。\\n\"\n\" \\n\"\n\"這​是​事情​發生​了​比​我​想像​的​更​黑暗​的​轉折！我​們​的​前​國​王​已​經從​永恒​的​睡眠​中​醒來，現​\"\n\"在在​迷宮​中​指揮​著​一​支​不​死​僕從​軍團。他​的​屍體​被​埋​在​大​教堂​下面​三​層​的​墳​墓​里。求​你​\"\n\"了，好​主人，通過摧毀​他​現​在​被​詛咒​的​身體來讓​他​的​靈魂​放鬆\"\n\n#: Source/translation_dummy.cpp:686\nmsgid \"\"\n\"As I told you, good master, the King was entombed three levels below. He's \"\n\"down there, waiting in the putrid darkness for his chance to destroy this \"\n\"land...\"\nmsgstr \"\"\n\"正​如​我​告訴​你​的，好​主人，國王​被​埋葬​在​下面​三​層。他​在​下面，在​腐朽​的​黑暗​中​等待​著​\"\n\"毀滅​這片​土地​的​機會\"\n\n#: Source/translation_dummy.cpp:687\nmsgid \"\"\n\"The curse of our King has passed, but I fear that it was only part of a \"\n\"greater evil at work. However, we may yet be saved from the darkness that \"\n\"consumes our land, for your victory is a good omen. May Light guide you on \"\n\"your way, good master.\"\nmsgstr \"\"\n\"我​們​國王​的​詛咒​已​經過​去​了，但​我​擔心這​只是​更​大​的​罪惡​的​一​部分。然而，我​們​仍​有​可\"\n\"能​從吞滅​我​們​土地​的​黑暗中​得救，因​為​你​們​的​勝利​是​個好​兆頭。愿​光明​指引​你​前進，好​\"\n\"主人\"\n\n#: Source/translation_dummy.cpp:688\nmsgid \"\"\n\"The loss of his son was too much for King Leoric. I did what I could to ease \"\n\"his madness, but in the end it overcame him. A black curse has hung over \"\n\"this kingdom from that day forward, but perhaps if you were to free his \"\n\"spirit from his earthly prison, the curse would be lifted...\"\nmsgstr \"\"\n\"失去​兒子對​李奧瑞克國王來說​是​太​多​了。我​盡​我​所​能​減輕​他​的​瘋狂，但​最​終還​是​戰勝​了​\"\n\"他。從​那​一​天​起，一​個​黑色​的​詛咒​就​籠罩​著​這個​王國，但是​如果​你​把​他​的​靈魂從​塵世​的​\"\n\"牢獄​中​釋​放出來，詛咒​就​會​解除\"\n\n#: Source/translation_dummy.cpp:689\nmsgid \"\"\n\"I don't like to think about how the King died. I like to remember him for \"\n\"the kind and just ruler that he was. His death was so sad and seemed very \"\n\"wrong, somehow.\"\nmsgstr \"\"\n\"我​不​想​去​想​國​王​是​怎麼死​的。我​喜歡記​住​他​的​善良​和​公正​的​統治者，他​是。他​的​死​是​如\"\n\"此​悲傷，似乎​非常​錯誤，不​知​何​故\"\n\n#: Source/translation_dummy.cpp:690\nmsgid \"\"\n\"I made many of the weapons and most of the armor that King Leoric used to \"\n\"outfit his knights. I even crafted a huge two-handed sword of the finest \"\n\"mithril for him, as well as a field crown to match. I still cannot believe \"\n\"how he died, but it must have been some sinister force that drove him insane!\"\nmsgstr \"\"\n\"我​做​了​很多​武器​和​大部分​護甲，國王李奧瑞克​用​來裝備​他​的​騎士。我​甚至​為​他​製​作​了​一​\"\n\"把​巨大​的​雙手劍，是​最​好​的​秘銀劍，還​有​一​頂​與​之​相配​的​戰地​王冠。我​仍然​無法​相信​他​\"\n\"是​怎麼死​的，但​一定​是​某​種​邪惡​的​力量​把​他​逼瘋​了\"\n\n#: Source/translation_dummy.cpp:691\nmsgid \"\"\n\"I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is \"\n\"King. King, so you hear me? HAIL TO THE KING!\"\nmsgstr \"\"\n\"我​才​不管​呢。聽著，沒​有​骷髏會​是​我​的​國王。利奧里克​是​國王。國王，你​聽見​了​嗎？向​\"\n\"國王​致敬\"\n\n#: Source/translation_dummy.cpp:692\nmsgid \"\"\n\"The dead who walk among the living follow the cursed King. He holds the \"\n\"power to raise yet more warriors for an ever growing army of the undead. If \"\n\"you do not stop his reign, he will surely march across this land and slay \"\n\"all who still live here.\"\nmsgstr \"\"\n\"行​在​活​人​中間​的​死人，都​跟​隨​被​咒詛​的​王。他​有​能力​為​一​支​不​斷壯​大​的​不​死軍​團​培養​更​\"\n\"多​的​戰士。如果​你​不​停止​他​的​統治，他​一定​會​穿過​這片​土地，殺死​所有​仍然​住​在​這裡​的​\"\n\"人\"\n\n#: Source/translation_dummy.cpp:693\nmsgid \"\"\n\"Look, I'm running a business here. I don't sell information, and I don't \"\n\"care about some King that's been dead longer than I've been alive. If you \"\n\"need something to use against this King of the undead, then I can help you \"\n\"out...\"\nmsgstr \"\"\n\"聽​著，我​在​這裡​做​生意。我​不​賣情報，我​也​不​關心​那些​死得​比​我​還久​的​國王。如果​你​需\"\n\"要​什麼東​西來​對​付​不​死​之​王，那​麼​我​可以​幫​你\"\n\n#: Source/translation_dummy.cpp:694\nmsgid \"\"\n\"The warmth of life has entered my tomb. Prepare yourself, mortal, to serve \"\n\"my Master for eternity!\"\nmsgstr \"生命​的​溫暖​已​經進入​我​的​墳​墓。準備​好​你​自己，凡​人，為​我​的​主人服務​到​永遠\"\n\n#: Source/translation_dummy.cpp:695\nmsgid \"\"\n\"I see that this strange behavior puzzles you as well. I would surmise that \"\n\"since many demons fear the light of the sun and believe that it holds great \"\n\"power, it may be that the rising sun depicted on the sign you speak of has \"\n\"led them to believe that it too holds some arcane powers. Hmm, perhaps they \"\n\"are not all as smart as we had feared...\"\nmsgstr \"\"\n\"我​知道​這種​奇怪​的​行為​也​讓​你​困惑。我​猜想，既然​許​多​惡​魔​害怕​太​陽光，相信​它​擁​有​巨\"\n\"大​的​力量，那​可能​是​你​所​說​的​星座​上​描繪​的​旭日​讓​他​們​相信​它​也​擁​有​一些​神秘​的​力量。\"\n\"嗯，也​許​他​們並​不​像​我​們​擔心​的​那​麼​聰明\"\n\n#: Source/translation_dummy.cpp:696\nmsgid \"\"\n\"Master, I have a strange experience to relate. I know that you have a great \"\n\"knowledge of those monstrosities that inhabit the labyrinth, and this is \"\n\"something that I cannot understand for the very life of me... I was awakened \"\n\"during the night by a scraping sound just outside of my tavern. When I \"\n\"looked out from my bedroom, I saw the shapes of small demon-like creatures \"\n\"in the inn yard. After a short time, they ran off, but not before stealing \"\n\"the sign to my inn. I don't know why the demons would steal my sign but \"\n\"leave my family in peace... 'tis strange, no?\"\nmsgstr \"\"\n\"師父，我​有​一​個​奇怪​的​經歷。我​知道​你​對迷宮裡​的​怪物​很​瞭解，這​是​我​一​生​都​無法​理解​\"\n\"的。。。我​在​晚上​被​酒店​外面​的​刮擦聲​吵醒​了。當​我​從​臥室​往外​看​的​時候，我​看到​客棧​\"\n\"院子​里​有​一些​像​魔鬼​一​樣​的​小​動物。過​了​一​會兒，他​們​跑掉​了，但​還沒來​得​及​把​牌子​偷​\"\n\"到​我​的​客棧。我​不​知道​為​什麼​惡​魔會​偷走​我​的​標誌，卻讓​我​的​家人​安然​無恙​…​…​」​很​奇\"\n\"怪，不​是​嗎\"\n\n#: Source/translation_dummy.cpp:697\nmsgid \"\"\n\"Oh, you didn't have to bring back my sign, but I suppose that it does save \"\n\"me the expense of having another one made. Well, let me see, what could I \"\n\"give you as a fee for finding it? Hmmm, what have we here... ah, yes! This \"\n\"cap was left in one of the rooms by a magician who stayed here some time \"\n\"ago. Perhaps it may be of some value to you.\"\nmsgstr \"\"\n\"哦，你​不​必​把​我​的​牌子​拿回來，但​我​想​它​確實​可以​幫​我​省下​再​做​一​個​牌子​的​費用。好​\"\n\"吧，讓​我​想想，我​能​給​你​什麼​作​為​找到​它​的​費用？嗯，我​們這裡​有​什麼。。。啊，是​\"\n\"的！這頂​帽子​是​一​個​魔術​師​不久​前​留下​來​的，他​把​它​放​在​一​個​房間​里。也​許對​你​有​價值\"\n\n#: Source/translation_dummy.cpp:698\nmsgid \"\"\n\"My goodness, demons running about the village at night, pillaging our homes \"\n\"- is nothing sacred? I hope that Ogden and Garda are all right. I suppose \"\n\"that they would come to see me if they were hurt...\"\nmsgstr \"\"\n\"我​的​天哪，惡魔們​晚上​在​村子​裡​到​處亂​跑，掠奪​我​們​的​家園​——​難道沒​有​什麼神聖​的​東西\"\n\"嗎？我​希望​奧格登​和​加爾達​沒​事。我​想​如果​他​們受傷​了​他​們會來​看​我​的\"\n\n#: Source/translation_dummy.cpp:699\nmsgid \"\"\n\"Oh my! Is that where the sign went? My Grandmother and I must have slept \"\n\"right through the whole thing. Thank the Light that those monsters didn't \"\n\"attack the inn.\"\nmsgstr \"\"\n\"天​哪！標誌​就​在​那​裡嗎？我​祖母​和​我​一定​一直​都​在​睡覺。感謝​那些​怪物沒​有​攻擊客棧\"\n\n#: Source/translation_dummy.cpp:700\nmsgid \"\"\n\"Demons stole Ogden's sign, you say? That doesn't sound much like the \"\n\"atrocities I've heard of - or seen. \\n\"\n\" \\n\"\n\"Demons are concerned with ripping out your heart, not your signpost.\"\nmsgstr \"\"\n\"你​說惡​魔偷​了​奧格登​的​招牌？這聽​起來​不​像​我​聽說過​或​見過​的​暴行。\\n\"\n\" \\n\"\n\"惡​魔關​心​的​是​撕碎​你​的​心，而​不​是​你​的​路標\"\n\n#: Source/translation_dummy.cpp:701\nmsgid \"\"\n\"You know what I think? Somebody took that sign, and they gonna want lots of \"\n\"money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a \"\n\"new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece \"\n\"of cheese...\"\nmsgstr \"\"\n\"你​知道​我​怎​麼​想​嗎？有​人​拿​了​那個​牌子，他​們會​想要​很多​錢​的。如果​我​是​奧格登。。。\"\n\"我​不​是，但​如果​我​是。。。我​想​買​一​個​新​牌子，上面​畫​些​漂亮​的​圖案。也​許​是​一​杯​啤酒​\"\n\"或者​一​塊​奶酪\"\n\n#: Source/translation_dummy.cpp:702\nmsgid \"\"\n\"No mortal can truly understand the mind of the demon. \\n\"\n\" \\n\"\n\"Never let their erratic actions confuse you, as that too may be their plan.\"\nmsgstr \"\"\n\"沒​有​人​能​真正​理解​惡魔​的​思想。\\n\"\n\" \\n\"\n\"永遠​不​要​讓​他​們​不​穩定​的​行為​迷惑​你，因​為​那​也​可能​是​他​們​的​計劃\"\n\n#: Source/translation_dummy.cpp:703\nmsgid \"\"\n\"What - is he saying I took that? I suppose that Griswold is on his side, \"\n\"too. \\n\"\n\" \\n\"\n\"Look, I got over simple sign stealing months ago. You can't turn a profit on \"\n\"a piece of wood.\"\nmsgstr \"\"\n\"他​是​說​我​拿​了​那個？我​想​格里斯沃​爾德​也​站​在​他​這邊。\\n\"\n\" \\n\"\n\"​聽​著，我​幾​個​月​前​就​忘​了​偷牌子​了。你​不​能​靠​一​塊木頭​賺錢\"\n\n#: Source/translation_dummy.cpp:704\nmsgid \"\"\n\"Hey - You that one that kill all! You get me Magic Banner or we attack! You \"\n\"no leave with life! You kill big uglies and give back Magic. Go past corner \"\n\"and door, find uglies. You give, you go!\"\nmsgstr \"\"\n\"嘿​-​你​就​是​那​個殺​人狂！你​給​我​拿​魔旗​否則​我​們​就​進攻！你​不​能​離開​生命！你​殺​了​大醜​八\"\n\"怪還​了​魔法。穿過​街角​和​門，找到​醜陋​的​東西。你​給，你​走\"\n\n#: Source/translation_dummy.cpp:705\nmsgid \"You kill uglies, get banner. You bring to me, or else...\"\nmsgstr \"你​殺​了​醜​八怪，得到​橫幅。你​給​我​帶來，否則\"\n\n#: Source/translation_dummy.cpp:706\nmsgid \"You give! Yes, good! Go now, we strong. We kill all with big Magic!\"\nmsgstr \"你​給​我！是​的，很​好！走​吧，我​們​堅強。我​們​用​大​魔法​殺​人\"\n\n#: Source/translation_dummy.cpp:707\nmsgid \"\"\n\"This does not bode well, for it confirms my darkest fears. While I did not \"\n\"allow myself to believe the ancient legends, I cannot deny them now. Perhaps \"\n\"the time has come to reveal who I am.\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to safeguarding the secrets of a \"\n\"timeless evil. An evil that quite obviously has now been released.\\n\"\n\" \\n\"\n\"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party \"\n\"of simple townsfolk into the Labyrinth to find the King's missing son, \"\n\"Albrecht. Quite some time passed before they returned, and only a few of \"\n\"them escaped with their lives.\\n\"\n\" \\n\"\n\"Curse me for a fool! I should have suspected his veiled treachery then. It \"\n\"must have been Lazarus himself who kidnapped Albrecht and has since hidden \"\n\"him within the Labyrinth. I do not understand why the Archbishop turned to \"\n\"the darkness, or what his interest is in the child, unless he means to \"\n\"sacrifice him to his dark masters!\\n\"\n\" \\n\"\n\"That must be what he has planned! The survivors of his 'rescue party' say \"\n\"that Lazarus was last seen running into the deepest bowels of the labyrinth. \"\n\"You must hurry and save the prince from the sacrificial blade of this \"\n\"demented fiend!\"\nmsgstr \"\"\n\"這​不​是​好​兆頭，因​為​它​證實​了​我​最​黑暗​的​恐懼。雖然​我​不​允許​自己​相信​古老​的​傳說，但​\"\n\"我​現​在​不​能否​認​它​們。也​許​是​時候​揭露​我​是​誰​了。\\n\"\n\" \\n\"\n\"​我​的​真名​是​老凱恩，我​是​一​個​古老​兄弟會​的​最後​一個​後​代，這個​兄弟​會​致力​於​保護​一​個​\"\n\"永恒​邪惡​的​秘密。一​個​很​明顯​已​經​被​釋放​的​惡魔。\\n\"\n\" \\n\"\n\"拉撒雷茲​大​主教​曾​經​是​萊奧​里克國王​最​信任​的​顧問，他​帶領​一​隊​普通​的​市民​進入​迷宮，\"\n\"尋​找​國​王失蹤​的​兒子​阿爾布雷希特。過​了​很​長​一​段​時間​他​們​才​回來，只有​少​數人​帶​著​生\"\n\"命​逃走​了。\\n\"\n\" \\n\"\n\"​詛咒​我​是​個​傻瓜！我​當時應該​懷疑​他​暗中​的​背叛。一定​是​拉撒路​自己​綁架​了​阿爾佈​雷希\"\n\"特，然​後​把​他​藏​在​迷宮裡。我​不​明白​大​主教​為什麼轉​向​黑暗，或者​他​對這個​孩子​有​什麼​\"\n\"興趣，除非​他​打算​把​他​獻給​他​的​黑暗​主人！\\n\"\n\" \\n\"\n\"​那​一定​是​他​的​計劃！他​的​「​救援隊​」​的​倖存者​說，拉撒路​最後​一​次​被​看到​跑進迷宮​最​深​\"\n\"處。你​必須​趕​快​把​王子從​這個​瘋狂​惡魔​的​祭劍​中​救出​來\"\n\n#: Source/translation_dummy.cpp:708\nmsgid \"\"\n\"You must hurry and rescue Albrecht from the hands of Lazarus. The prince and \"\n\"the people of this kingdom are counting on you!\"\nmsgstr \"\"\n\"你​必須​趕​快​把​阿爾布雷希特從拉撒路​手​中​救出來。王子​和​這個​王國​的​人民​都​指望​著​你\"\n\n#: Source/translation_dummy.cpp:709\nmsgid \"\"\n\"Your story is quite grim, my friend. Lazarus will surely burn in Hell for \"\n\"his horrific deed. The boy that you describe is not our prince, but I \"\n\"believe that Albrecht may yet be in danger. The symbol of power that you \"\n\"speak of must be a portal in the very heart of the labyrinth.\\n\"\n\" \\n\"\n\"Know this, my friend - The evil that you move against is the dark Lord of \"\n\"Terror. He is known to mortal men as Diablo. It was he who was imprisoned \"\n\"within the Labyrinth many centuries ago and I fear that he seeks to once \"\n\"again sow chaos in the realm of mankind. You must venture through the portal \"\n\"and destroy Diablo before it is too late!\"\nmsgstr \"\"\n\"你​的​故事​很​殘​酷，我​的​朋友。拉撒路​一定​會​因​為​他​那​可怕​的​行為​在地​獄裡​被​燒死。你​描\"\n\"述​的​那​個​男孩​不​是​我​們​的​王子，但​我​相信​阿爾布雷希特​可能​還處​在​危險​之中。你​所​說​的​\"\n\"權力​的​象徵​一定​是​迷宮​中心​的​一​個​入口。\\n\"\n\" \\n\"\n\"​你​要​知道，我​的​朋友，你​所​反對​的​邪惡​是​恐怖​的​黑魔王。他​被​世人​稱為​迪亞波羅。幾個\"\n\"世紀​前，正​是​他​被​囚禁​在​迷宮裡，我​擔心​他​又​一​次​企圖​在​人類​的​王國里​製造​混亂。你​必​\"\n\"須​冒險​穿過傳​送門，在​一切​還​不​到​時候摧毀迪亞波羅\"\n\n#: Source/translation_dummy.cpp:710\nmsgid \"\"\n\"Lazarus was the Archbishop who led many of the townspeople into the \"\n\"labyrinth. I lost many good friends that day, and Lazarus never returned. I \"\n\"suppose he was killed along with most of the others. If you would do me a \"\n\"favor, good master - please do not talk to Farnham about that day.\"\nmsgstr \"\"\n\"拉撒路​是​大主教，他​帶領​許​多​市民​進入​迷宮。那天​我​失去​了​很多​好​朋友，拉撒路​再​也​沒​\"\n\"有​回來。我​想​他​是​和​其他​大多​數​人​一起​被​殺​的。如果​你​能幫​我​一​個​忙，好​主人​-​請​不​要​和​\"\n\"法納​姆談論​那​一​天\"\n\n#: Source/translation_dummy.cpp:711\nmsgid \"\"\n\"I was shocked when I heard of what the townspeople were planning to do that \"\n\"night. I thought that of all people, Lazarus would have had more sense than \"\n\"that. He was an Archbishop, and always seemed to care so much for the \"\n\"townsfolk of Tristram. So many were injured, I could not save them all...\"\nmsgstr \"\"\n\"當​我​聽說鎮​上​的​人​那天​晚上​打算​幹什麼時，我​很​震驚。我​想​在​所有​人​中，拉撒路​應該​更​\"\n\"有​理智。他​是​一​位​大主教，似乎​總​是​那​麼​關​心​特里斯特拉姆​的​市民。這麼​多​人​受傷，我​\"\n\"救​不​了​他​們\"\n\n#: Source/translation_dummy.cpp:712\nmsgid \"\"\n\"I remember Lazarus as being a very kind and giving man. He spoke at my \"\n\"mother's funeral, and was supportive of my grandmother and myself in a very \"\n\"troubled time. I pray every night that somehow, he is still alive and safe.\"\nmsgstr \"\"\n\"我​記​得​拉撒路​是​一​個​非常​和​善​和​樂於​奉獻​的​人。他​在​我​母親​的​葬禮​上​發表​了​講話，在​非\"\n\"常​困難​的​時候​支援​我​和​我​的​祖母。我​每​晚​都​祈禱，不​知​何故，他​還活著，安然​無恙\"\n\n#: Source/translation_dummy.cpp:713\nmsgid \"\"\n\"I was there when Lazarus led us into the labyrinth. He spoke of holy \"\n\"retribution, but when we started fighting those hellspawn, he did not so \"\n\"much as lift his mace against them. He just ran deeper into the dim, endless \"\n\"chambers that were filled with the servants of darkness!\"\nmsgstr \"\"\n\"拉撒路領​我​們​進迷宮​的​時候，我​在​那裡。他​談​到​了​神聖​的​報應，但​當​我​們開​始與​那些​地\"\n\"獄​之​子​戰鬥時，他​甚至​沒​有​舉起​他​的​狼牙棒來​對付​他​們。他​只不​過​是​往​黑暗​的​僕人們​所​\"\n\"住​的​昏暗​無邊​的​房間​里​跑​得​更​深\"\n\n#: Source/translation_dummy.cpp:714\nmsgid \"\"\n\"They stab, then bite, then they're all around you. Liar! LIAR! They're all \"\n\"dead! Dead! Do you hear me? They just keep falling and falling... their \"\n\"blood spilling out all over the floor... all his fault...\"\nmsgstr \"\"\n\"它​們刺，然​後​咬，然​後​它​們​就​在​你​周圍。說謊者！說謊者！他​們​都​死​了！死去​的​你​聽見​\"\n\"了​嗎？他​們​只​是​不​斷​地​跌倒。。。他​們​的​血灑​得​滿​地​都​是。。。全​是​他​的​錯\"\n\n#: Source/translation_dummy.cpp:715\nmsgid \"\"\n\"I did not know this Lazarus of whom you speak, but I do sense a great \"\n\"conflict within his being. He poses a great danger, and will stop at nothing \"\n\"to serve the powers of darkness which have claimed him as theirs.\"\nmsgstr \"\"\n\"我​不​認識​你​們​所​說​的​拉撒路，但​我​確​實感覺​到​他​內​心有​很​大​的​矛盾。他​帶來​了​巨大​的​危\"\n\"險，他​將​不​擇​手段​地為​黑暗​勢力服務，黑暗​勢力將​他​視為​他​們​的\"\n\n#: Source/translation_dummy.cpp:716\nmsgid \"\"\n\"Yes, the righteous Lazarus, who was sooo effective against those monsters \"\n\"down there. Didn't help save my leg, did it? Look, I'll give you a free \"\n\"piece of advice. Ask Farnham, he was there.\"\nmsgstr \"\"\n\"是​的，正義​的​拉撒路，他​對​那​裡​的​怪物​非常​有效。沒救​我​的​腿，是​嗎？聽著，我​給​你​一​\"\n\"個​免費​的​建議。問問法納姆，他​在​那​兒\"\n\n#: Source/translation_dummy.cpp:717\nmsgid \"\"\n\"Abandon your foolish quest. All that awaits you is the wrath of my Master! \"\n\"You are too late to save the child. Now you will join him in Hell!\"\nmsgstr \"\"\n\"放棄​你​愚蠢​的​追求。等待​你​的​只​有​我​主人​的​憤怒！你​來​不​及​救​孩子​了。現​在​你​要​和​他​一\"\n\"起​下地獄​了\"\n\n#: Source/translation_dummy.cpp:718\nmsgid \"\"\n\"Hmm, I don't know what I can really tell you about this that will be of any \"\n\"help. The water that fills our wells comes from an underground spring. I \"\n\"have heard of a tunnel that leads to a great lake - perhaps they are one and \"\n\"the same. Unfortunately, I do not know what would cause our water supply to \"\n\"be tainted.\"\nmsgstr \"\"\n\"嗯，我​不​知道​我​能​告訴​你​些​什麼對​你​有​幫助。充滿​我​們​水​井​的​水來​自​地下泉水。我​聽說​\"\n\"過​一​條​通往​大​湖​的​隧道​——​也​許​它​們​是​同​一​條。不幸​的​是，我​不​知道​什麼會​導致​我​們​的​供\"\n\"水​受到​污染\"\n\n#: Source/translation_dummy.cpp:719\nmsgid \"\"\n\"I have always tried to keep a large supply of foodstuffs and drink in our \"\n\"storage cellar, but with the entire town having no source of fresh water, \"\n\"even our stores will soon run dry. \\n\"\n\" \\n\"\n\"Please, do what you can or I don't know what we will do.\"\nmsgstr \"\"\n\"我​一直​試圖​在​我​們​的​儲藏室​裡​儲存​大量​的​食品​和​飲料，但​由於​全​鎮沒​有​淡水​供應，即使​\"\n\"是​我​們​的​商店​也​很​快​就​會​乾涸。\\n\"\n\" \\n\"\n\"拜託，做​你​能​做​的，否則​我​不​知道​我​們會​做​什麼\"\n\n#: Source/translation_dummy.cpp:720\nmsgid \"\"\n\"I'm glad I caught up to you in time! Our wells have become brackish and \"\n\"stagnant and some of the townspeople have become ill drinking from them. Our \"\n\"reserves of fresh water are quickly running dry. I believe that there is a \"\n\"passage that leads to the springs that serve our town. Please find what has \"\n\"caused this calamity, or we all will surely perish.\"\nmsgstr \"\"\n\"很​高​興​我​及​時趕​上​了​你！我​們​的​水井變​得​微咸、死氣​沉沉，一些​城裡人​喝​得​不​好。我​們​\"\n\"儲備​的​淡水​很​快​就​乾涸​了。我​相信​有​一​條​通道​通向​為​我​們城鎮服務​的​泉水。請​找出​造成​\"\n\"這場​災難​的​原因，否則​我​們​都​將滅亡\"\n\n#: Source/translation_dummy.cpp:721\nmsgid \"\"\n\"Please, you must hurry. Every hour that passes brings us closer to having no \"\n\"water to drink. \\n\"\n\" \\n\"\n\"We cannot survive for long without your help.\"\nmsgstr \"\"\n\"拜託，你​必須​快點。每​過​一​個​小​時，我​們​就​更​接近​沒​有​水​喝​了。\\n\"\n\" \\n\"\n\"沒​有​你​的​幫助，我​們​活​不​了​多久\"\n\n#: Source/translation_dummy.cpp:722\nmsgid \"\"\n\"What's that you say - the mere presence of the demons had caused the water \"\n\"to become tainted? Oh, truly a great evil lurks beneath our town, but your \"\n\"perseverance and courage gives us hope. Please take this ring - perhaps it \"\n\"will aid you in the destruction of such vile creatures.\"\nmsgstr \"\"\n\"你​說什麼？僅僅​是​惡魔​的​存在​就​導致​了​水​被​污染​了？哦，我​們鎮​下​確實​隱​藏​著​一​個​巨大​\"\n\"的​惡魔，但​你​的​毅力​和​勇氣給​了​我​們​希望。請收​下​這​枚​戒指​——​也​許​它​能​幫助​你​消滅​這​些​\"\n\"邪惡​的​生物\"\n\n#: Source/translation_dummy.cpp:723\nmsgid \"\"\n\"My grandmother is very weak, and Garda says that we cannot drink the water \"\n\"from the wells. Please, can you do something to help us?\"\nmsgstr \"我​祖母​很​虛弱，嘉達說​我​們​不​能​喝​井​水。拜託，你​能幫​點​忙嗎\"\n\n#: Source/translation_dummy.cpp:724\nmsgid \"\"\n\"Pepin has told you the truth. We will need fresh water badly, and soon. I \"\n\"have tried to clear one of the smaller wells, but it reeks of stagnant \"\n\"filth. It must be getting clogged at the source.\"\nmsgstr \"\"\n\"佩平告訴​了​你​真相。我​們​很​快​就​會​急​需​淡水。我​試過​清理​其中​一​口​小​井，但​它​散發​著​死​\"\n\"水​的​臭味。一定​是​源頭​堵塞​了\"\n\n#: Source/translation_dummy.cpp:725\nmsgid \"You drink water?\"\nmsgstr \"你​喝​水嗎\"\n\n#: Source/translation_dummy.cpp:726\nmsgid \"\"\n\"The people of Tristram will die if you cannot restore fresh water to their \"\n\"wells. \\n\"\n\" \\n\"\n\"Know this - demons are at the heart of this matter, but they remain ignorant \"\n\"of what they have spawned.\"\nmsgstr \"\"\n\"如果​你​不​能​恢復​井​中​的​淡水，崔斯特瑞姆人​就​會死。\\n\"\n\" \\n\"\n\"​知道​這​一​點​-​惡魔​是​這件​事​的​核心，但​他​們​仍然​不​知道​他​們產生​了​什麼\"\n\n#: Source/translation_dummy.cpp:727\nmsgid \"\"\n\"For once, I'm with you. My business runs dry - so to speak - if I have no \"\n\"market to sell to. You better find out what is going on, and soon!\"\nmsgstr \"\"\n\"這​一​次，我​和​你​在一起。可以​說，如果​我​沒​有​銷路​的​話，我​的​生意​就​完​了。你​最好​儘快​\"\n\"弄清楚​發生​了​什麼​事\"\n\n#: Source/translation_dummy.cpp:728\nmsgid \"\"\n\"A book that speaks of a chamber of human bones? Well, a Chamber of Bone is \"\n\"mentioned in certain archaic writings that I studied in the libraries of the \"\n\"East. These tomes inferred that when the Lords of the underworld desired to \"\n\"protect great treasures, they would create domains where those who died in \"\n\"the attempt to steal that treasure would be forever bound to defend it. A \"\n\"twisted, but strangely fitting, end?\"\nmsgstr \"\"\n\"一​本​關於​藏骨密室​的​書？嗯，我​在​東方圖書館​研究過​的​一些​古代​著作​中​提到​了​骨室。這​\"\n\"些​大部​頭書​推斷，當​地下​世界​的​領主​想要​保護​巨大​的​寶藏時，他​們會​建立​領地，讓​那些​\"\n\"在​試圖​竊取寶​藏時死去​的​人永遠​有​義務​保衛​寶藏。一​個​扭曲​的，但​奇怪​的​適合，結束\"\n\n#: Source/translation_dummy.cpp:729\nmsgid \"\"\n\"I am afraid that I don't know anything about that, good master. Cain has \"\n\"many books that may be of some help.\"\nmsgstr \"恐怕​我​對​此​一​無​所​知，好​師傅。凱恩​有​許​多​書​可能​對​他​有所​幫助\"\n\n#: Source/translation_dummy.cpp:730\nmsgid \"\"\n\"This sounds like a very dangerous place. If you venture there, please take \"\n\"great care.\"\nmsgstr \"這​聽起來​是​個​非常​危險​的​地方。如果​你​在​那裡​冒險，請​小心\"\n\n#: Source/translation_dummy.cpp:731\nmsgid \"\"\n\"I am afraid that I haven't heard anything about that. Perhaps Cain the \"\n\"Storyteller could be of some help.\"\nmsgstr \"恐怕​我​什麼​也​沒聽​說過。說書人​凱恩​也​許能​幫​上​忙\"\n\n#: Source/translation_dummy.cpp:732\nmsgid \"\"\n\"I know nothing of this place, but you may try asking Cain. He talks about \"\n\"many things, and it would not surprise me if he had some answers to your \"\n\"question.\"\nmsgstr \"\"\n\"我​對這​地方​一​無​所​知，不​過​你​可以​問問​凱恩。他​談​了​很多​事情，如果​他​能​回答​你​的​問\"\n\"題，我​也​不​會​感到​驚訝\"\n\n#: Source/translation_dummy.cpp:733\nmsgid \"\"\n\"Okay, so listen. There's this chamber of wood, see. And his wife, you know - \"\n\"her - tells the tree... cause you gotta wait. Then I says, that might work \"\n\"against him, but if you think I'm gonna PAY for this... you... uh... yeah.\"\nmsgstr \"\"\n\"好​吧，聽著。有​一​間​木屋，你​看。他​的​妻子​告訴樹。。。因為​你​得​等。然​後​我​說，這​可\"\n\"能​對​他​不利，但​如果​你​認為​我​會​為​此​付出​代價。。。你。。。UH​是​的\"\n\n#: Source/translation_dummy.cpp:734\nmsgid \"\"\n\"You will become an eternal servant of the dark lords should you perish \"\n\"within this cursed domain. \\n\"\n\" \\n\"\n\"Enter the Chamber of Bone at your own peril.\"\nmsgstr \"\"\n\"如果​你​死​在​這個​被​詛咒​的​領域裡，你​將成為​黑暗​領主​的​永恒​僕​人。\\n\"\n\" \\n\"\n\"​進入骨室​的​風險​由​你​自己​承擔\"\n\n#: Source/translation_dummy.cpp:735\nmsgid \"\"\n\"A vast and mysterious treasure, you say? Maybe I could be interested in \"\n\"picking up a few things from you... or better yet, don't you need some rare \"\n\"and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"你​說​是​一​個​巨大​而​神秘​的​寶藏？也​許​我​有​興趣從​你​那​裡​得到​一些​東西。。。或者​更​好​的​\"\n\"是，你​不​需要​一些​稀有​而​昂貴​的​物資​來度​過這​場​磨難嗎\"\n\n#: Source/translation_dummy.cpp:736\nmsgid \"\"\n\"It seems that the Archbishop Lazarus goaded many of the townsmen into \"\n\"venturing into the Labyrinth to find the King's missing son. He played upon \"\n\"their fears and whipped them into a frenzied mob. None of them were prepared \"\n\"for what lay within the cold earth... Lazarus abandoned them down there - \"\n\"left in the clutches of unspeakable horrors - to die.\"\nmsgstr \"\"\n\"似乎​拉撒路​大​主教​慫恿許​多​市民​冒險進​入​迷宮尋​找​國​王失蹤​的​兒子。他​利用​他​們​的​恐\"\n\"懼，把​他​們鞭​打​成​一​群​瘋狂​的​暴徒。他​們​中​沒​有​一​個人準備​好​面對​冰冷​的​地球​上​的​一\"\n\"切。。。拉撒路​把​他​們丟​在​那裡，丟​在​難​以​形容​的​恐懼​魔爪​里，等​死\"\n\n#: Source/translation_dummy.cpp:737\nmsgid \"\"\n\"Yes, Farnham has mumbled something about a hulking brute who wielded a \"\n\"fierce weapon. I believe he called him a butcher.\"\nmsgstr \"\"\n\"是​的，法納姆喃喃​地說​了​一些​關​於​一​個​笨重​的​畜生​揮​舞著​兇器​的​事。我​相信​他​叫​他​屠夫\"\n\n#: Source/translation_dummy.cpp:738\nmsgid \"\"\n\"By the Light, I know of this vile demon. There were many that bore the scars \"\n\"of his wrath upon their bodies when the few survivors of the charge led by \"\n\"Lazarus crawled from the Cathedral. I don't know what he used to slice open \"\n\"his victims, but it could not have been of this world. It left wounds \"\n\"festering with disease and even I found them almost impossible to treat. \"\n\"Beware if you plan to battle this fiend...\"\nmsgstr \"\"\n\"藉​著​光明，我​知道​這個​邪惡​的​惡魔。當拉撒路率領​的​少數​幾名衝鋒倖​存者​從大​教堂​爬出\"\n\"來時，許多​人​身​上​留下​了​他​憤怒​的​傷疤。我​不​知道​他​以前​是​怎麼​切開​受害者​的，但​這​不​\"\n\"可能​是​這個​世界​的。它​留下​的​傷口潰爛與​疾病，甚至​我​發現​他​們​幾乎​不​可能​治療。如果​\"\n\"你​打算​和​這個​惡​魔戰​鬥，要​小心\"\n\n#: Source/translation_dummy.cpp:739\nmsgid \"\"\n\"When Farnham said something about a butcher killing people, I immediately \"\n\"discounted it. But since you brought it up, maybe it is true.\"\nmsgstr \"\"\n\"當​法納姆說​起​屠夫殺人​的​事時，我​立刻​打消​了​這個​念頭。但​既然​是​你​提出​來​的，也​許​是​\"\n\"真的\"\n\n#: Source/translation_dummy.cpp:740\nmsgid \"\"\n\"I saw what Farnham calls the Butcher as it swathed a path through the bodies \"\n\"of my friends. He swung a cleaver as large as an axe, hewing limbs and \"\n\"cutting down brave men where they stood. I was separated from the fray by a \"\n\"host of small screeching demons and somehow found the stairway leading out. \"\n\"I never saw that hideous beast again, but his blood-stained visage haunts me \"\n\"to this day.\"\nmsgstr \"\"\n\"我​看到​法納姆所說​的​屠夫​在​我​朋友​的​屍體​上​劃​出​一​條​小​路。他​揮​舞​著​一​把​斧頭​般​大​的​砍​\"\n\"刀，砍​斷​四肢，砍​倒​站​在​那裡​的​勇士。我​被​一​群​尖叫​著​的​小​惡​魔從​紛爭​中​分離出來，不​\"\n\"知​怎​的​我​找到​了​通向​外面​的​樓梯。我​再​也​沒見​過​那​可怕​的​野獸，但​他​那​血跡​斑斑​的​面容​\"\n\"至今​縈繞​在​我​心頭\"\n\n#: Source/translation_dummy.cpp:741\nmsgid \"\"\n\"Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, \"\n\"couldn't save them. Trapped in a room with so many bodies... so many \"\n\"friends... NOOOOOOOOOO!\"\nmsgstr \"\"\n\"大​的​大​砍​刀​殺​了​我​所有​的​朋友。阻止​不​了​他，不得不​逃跑，救​不​了​他​們。被困​在​一​個​有​\"\n\"這麼​多​屍體​的​房間​里。。。這麼​多​朋友。。。不，不\"\n\n#: Source/translation_dummy.cpp:742\nmsgid \"\"\n\"The Butcher is a sadistic creature that delights in the torture and pain of \"\n\"others. You have seen his handiwork in the drunkard Farnham. His destruction \"\n\"will do much to ensure the safety of this village.\"\nmsgstr \"\"\n\"屠夫​是​個虐待​狂，喜​歡​別​人​的​折磨​和​痛苦。你​見過​他​在​酒​鬼法納姆​的​作品。他​的​毀滅將\"\n\"對​確​保這個​村莊​的​安全​大​有​幫助\"\n\n#: Source/translation_dummy.cpp:743\nmsgid \"\"\n\"I know more than you'd think about that grisly fiend. His little friends got \"\n\"a hold of me and managed to get my leg before Griswold pulled me out of that \"\n\"hole. \\n\"\n\" \\n\"\n\"I'll put it bluntly - kill him before he kills you and adds your corpse to \"\n\"his collection.\"\nmsgstr \"\"\n\"我​知道​的​比​你​想​的​還​要​多。他​的​小朋友​們​抓住​了​我，設法​在​格里斯沃​爾德​把​我​從洞​里拉​\"\n\"出來​之前​抓住​了​我​的​腿。\\n\"\n\" \\n\"\n\"​我​直截​了​當​地說​——​在​他​殺​了​你​並​把​你​的​屍體​加入​他​的​收藏​之前​殺​了​他\"\n\n#: Source/translation_dummy.cpp:744\nmsgid \"\"\n\"Please, listen to me. The Archbishop Lazarus, he led us down here to find \"\n\"the lost prince. The bastard led us into a trap! Now everyone is dead... \"\n\"killed by a demon he called the Butcher. Avenge us! Find this Butcher and \"\n\"slay him so that our souls may finally rest...\"\nmsgstr \"\"\n\"請聽​我​說。拉撒路​大​主教，他​帶​我​們​到​這裡​來尋​找​失蹤​的​王子。那​混蛋​把​我​們​引入​陷\"\n\"阱！現​在​每​個​人​都​死​了。。。被​一​個​叫​屠夫​的​惡魔​殺死。為​我​們報仇！找到​這個​屠夫，\"\n\"殺​了​他，讓​我​們​的​靈魂​最​終​安息\"\n\n#: Source/translation_dummy.cpp:745\nmsgid \"\"\n\"You recite an interesting rhyme written in a style that reminds me of other \"\n\"works. Let me think now - what was it?\\n\"\n\" \\n\"\n\"...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of \"\n\"razor claws briefly scraping to torment those poor souls who have been made \"\n\"sightless for all eternity. The prison for those so damned is named the \"\n\"Halls of the Blind...\"\nmsgstr \"\"\n\"你​背誦​了​一​首​有趣​的​韻文，它​的​風格讓​我​想起​了​其他​的​作品。現​在​讓​我​想想​-​那​是​什\"\n\"么？\\n\"\n\" \\n\"\n\"​…​黑暗​籠罩​著​隱藏​的​世界。眼睛​在​看​不​見​的​地方​閃閃​發光，只有​剃刀​爪子​的​聲音​在​短暫​地​\"\n\"刮來​刮去，折磨​那些​永遠失明​的​可憐​的​靈魂。為​那些​該死​的​人​而​設​的​監獄​被​命名​為盲人​\"\n\"的​大廳\"\n\n#: Source/translation_dummy.cpp:746\nmsgid \"\"\n\"I never much cared for poetry. Occasionally, I had cause to hire minstrels \"\n\"when the inn was doing well, but that seems like such a long time ago now. \\n\"\n\" \\n\"\n\"What? Oh, yes... uh, well, I suppose you could see what someone else knows.\"\nmsgstr \"\"\n\"我​從​不​太​喜​歡​詩歌。偶爾，當​旅店​經​營​得​很​好​的​時候，我​有​理由​僱​傭吟遊​詩人，但​那​似\"\n\"乎​是​很​久​以前​的​事​了。\\n\"\n\" \\n\"\n\"什麼？哦，是​的。。。呃，好​吧，我​想​你​可以​看看​別人​知道​什麼\"\n\n#: Source/translation_dummy.cpp:747\nmsgid \"\"\n\"This does seem familiar, somehow. I seem to recall reading something very \"\n\"much like that poem while researching the history of demonic afflictions. It \"\n\"spoke of a place of great evil that... wait - you're not going there are you?\"\nmsgstr \"\"\n\"不​知​怎麼​的，這​似乎​很​熟悉。我​似乎​記​得​在​研究​惡魔​痛苦​的​歷史時讀過​類​似​這​首​詩​的​東\"\n\"西。它​講述​了​一​個​邪惡​的​地方。。。等等​-​你​不​會去​的，是​嗎\"\n\n#: Source/translation_dummy.cpp:748\nmsgid \"\"\n\"If you have questions about blindness, you should talk to Pepin. I know that \"\n\"he gave my grandmother a potion that helped clear her vision, so maybe he \"\n\"can help you, too.\"\nmsgstr \"\"\n\"如果​你​對失明有​疑問，你​應該​和​佩平談談。我​知道​他​給​了​我​祖母​一​種​藥​水，幫助​她​消除​\"\n\"視力，所以​也​許​他​也​能​幫​你\"\n\n#: Source/translation_dummy.cpp:749\nmsgid \"\"\n\"I am afraid that I have neither heard nor seen a place that matches your \"\n\"vivid description, my friend. Perhaps Cain the Storyteller could be of some \"\n\"help.\"\nmsgstr \"\"\n\"恐怕​我​既​沒​聽說過​也​沒見過​一​個​地方​與​你​生動​的​描述​相符，我​的​朋友。說書人​凱恩​也​許\"\n\"能​幫​上​忙\"\n\n#: Source/translation_dummy.cpp:750\nmsgid \"Look here... that's pretty funny, huh? Get it? Blind - look here?\"\nmsgstr \"看​這裡。。。很​有趣​吧？瞭解​了？瞎子​-​看這裡\"\n\n#: Source/translation_dummy.cpp:751\nmsgid \"\"\n\"This is a place of great anguish and terror, and so serves its master \"\n\"well. \\n\"\n\" \\n\"\n\"Tread carefully or you may yourself be staying much longer than you had \"\n\"anticipated.\"\nmsgstr \"\"\n\"這​是​一​個​極度​痛苦​和​恐怖​的​地方，因此​很​好​地​為​主人​服務。\\n\"\n\" \\n\"\n\"​小心​踩，否則​你​可能​會​比​你​預期​的​呆​得​久\"\n\n#: Source/translation_dummy.cpp:752\nmsgid \"\"\n\"Lets see, am I selling you something? No. Are you giving me money to tell \"\n\"you about this? No. Are you now leaving and going to talk to the storyteller \"\n\"who lives for this kind of thing? Yes.\"\nmsgstr \"\"\n\"讓​我​想想，我​是​不​是​在​賣東​西給​你？不，你​是​在​給​我​錢告訴​你​這件​事​嗎？不，你​現​在​要​\"\n\"走​了，去​和​為這​種​事活​著​的​說書人談談嗎？是​的\"\n\n#: Source/translation_dummy.cpp:753\nmsgid \"\"\n\"You claim to have spoken with Lachdanan? He was a great hero during his \"\n\"life. Lachdanan was an honorable and just man who served his King faithfully \"\n\"for years. But of course, you already know that.\\n\"\n\" \\n\"\n\"Of those who were caught within the grasp of the King's Curse, Lachdanan \"\n\"would be the least likely to submit to the darkness without a fight, so I \"\n\"suppose that your story could be true. If I were in your place, my friend, I \"\n\"would find a way to release him from his torture.\"\nmsgstr \"\"\n\"你​聲稱​和​拉赫​達南談過？他​一生​是​個偉​大​的​英雄。拉赫​達​南​是​一​個光榮​而​公正​的​人，多​\"\n\"年​來​一直​忠實​地​為國​王服務。當然，你​已​經​知道​了。\\n\"\n\" \\n\"\n\"​在​那些​被​國王詛咒​的​人​中，拉赫​達南​最​不​可能​不​戰​而​屈身​於​黑暗，所以​我​想​你​的​故事​可\"\n\"能​是​真的。如果​我​在​你​的​位置，我​的​朋友，我​會​想​辦法​把​他​從折磨​中​釋​放出​來\"\n\n#: Source/translation_dummy.cpp:754\nmsgid \"\"\n\"You speak of a brave warrior long dead! I'll have no such talk of speaking \"\n\"with departed souls in my inn yard, thank you very much.\"\nmsgstr \"\"\n\"你​說​的​是​一​個​死​了​很​久​的​勇士！我​不​想​在​客棧​院子​里​和​死去​的​靈魂​說話，非常​感謝\"\n\n#: Source/translation_dummy.cpp:755\nmsgid \"\"\n\"A golden elixir, you say. I have never concocted a potion of that color \"\n\"before, so I can't tell you how it would effect you if you were to try to \"\n\"drink it. As your healer, I strongly advise that should you find such an \"\n\"elixir, do as Lachdanan asks and DO NOT try to use it.\"\nmsgstr \"\"\n\"你​說​是​金丹。我​從來沒​有​調製過​那​種​顏色​的​藥水，所以​我​不​能​告訴​你​如果​你​試​著​喝​它​會​\"\n\"有​什麼​影響。作為​你​的​治療​者，我​強烈​建議，如果​你​找到​這樣​一​種​長生不老藥，按照​拉\"\n\"赫​達南​的​要求​去​做，不​要​試圖​使用​它\"\n\n#: Source/translation_dummy.cpp:756\nmsgid \"\"\n\"I've never heard of a Lachdanan before. I'm sorry, but I don't think that I \"\n\"can be of much help to you.\"\nmsgstr \"我​以前​從沒聽說過​拉赫​達南。對​不​起，我​想​我​幫​不​了​你​什麼​忙\"\n\n#: Source/translation_dummy.cpp:757\nmsgid \"\"\n\"If it is actually Lachdanan that you have met, then I would advise that you \"\n\"aid him. I dealt with him on several occasions and found him to be honest \"\n\"and loyal in nature. The curse that fell upon the followers of King Leoric \"\n\"would fall especially hard upon him.\"\nmsgstr \"\"\n\"如果​你​遇到​的​是​拉赫​達南，那​麼​我​建​議​你​幫助​他。我​和​他​打過​幾​次​交道，發現​他​生性​誠\"\n\"實忠誠。落​在​國王李奧瑞克​的​追隨者​身​上​的​詛咒​尤其​會落​在​他​身​上\"\n\n#: Source/translation_dummy.cpp:758\nmsgid \"\"\n\" Lachdanan is dead. Everybody knows that, and you can't fool me into \"\n\"thinking any other way. You can't talk to the dead. I know!\"\nmsgstr \"\"\n\"拉赫達​南死​了。每​個​人​都​知道​這​一​點，你​不​能​騙​我​去​想​別​的。你​不​能​和​死人​說話。我​知\"\n\"道\"\n\n#: Source/translation_dummy.cpp:759\nmsgid \"\"\n\"You may meet people who are trapped within the Labyrinth, such as \"\n\"Lachdanan. \\n\"\n\" \\n\"\n\"I sense in him honor and great guilt. Aid him, and you aid all of Tristram.\"\nmsgstr \"\"\n\"你​可能​會​遇到​被困​在​迷宮裡​的​人，比如​拉赫​達南。\\n\"\n\" \\n\"\n\"​我​從​他​身​上​感受​到​榮譽​和​巨大​的​內疚。幫幫​他，你​就​幫幫​崔斯特瑞姆\"\n\n#: Source/translation_dummy.cpp:760\nmsgid \"\"\n\"Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened \"\n\"beneath him. He was incinerated in a ball of hellfire, and can't answer your \"\n\"questions anymore. Oh, that isn't what happened? Then I guess you'll be \"\n\"buying something or you'll be on your way.\"\nmsgstr \"\"\n\"等等，讓​我​猜猜。凱恩​被​一​條​巨大​的​裂縫​吞沒​了，裂縫​在​他​下面​張開。他​在​地獄​之​火​中​\"\n\"被​燒死​了，再​也​回答​不​了​你​的​問題​了。哦，不​是​這樣嗎？那​我​猜​你​要​買點​東西​了，要​不​\"\n\"就​上路​了\"\n\n#: Source/translation_dummy.cpp:761\nmsgid \"\"\n\"Please, don't kill me, just hear me out. I was once Captain of King Leoric's \"\n\"Knights, upholding the laws of this land with justice and honor. Then his \"\n\"dark Curse fell upon us for the role we played in his tragic death. As my \"\n\"fellow Knights succumbed to their twisted fate, I fled from the King's \"\n\"burial chamber, searching for some way to free myself from the Curse. I \"\n\"failed...\\n\"\n\" \\n\"\n\"I have heard of a Golden Elixir that could lift the Curse and allow my soul \"\n\"to rest, but I have been unable to find it. My strength now wanes, and with \"\n\"it the last of my humanity as well. Please aid me and find the Elixir. I \"\n\"will repay your efforts - I swear upon my honor.\"\nmsgstr \"\"\n\"拜託，別殺​我，聽​我​說​完。我​曾​經​是​萊奧​里克國王騎士團​的​隊長，以​正義​和​榮譽維護​這\"\n\"片​土地​的​法律。然​後​他​的​黑暗​詛咒​降臨​在​我​們​身​上，因​為​我​們​在​他​悲慘​的​死亡​中​扮演​了​\"\n\"角色。當​我​的​騎士​同伴​們​屈服​於​他​們​扭曲​的​命運時，我​逃離​了​國王​的​墓室，尋​找​某​種​方\"\n\"法​來擺脫​詛咒。我​失敗​了。。。\\n\"\n\" \\n\"\n\"​我​聽說​有​一​種​金丹​可以​解除​詛咒，讓​我​的​靈魂​安息，但​我​一直​找​不​到​它。我​的​力量​正在​\"\n\"衰退，伴隨​著​它，我​最後​的​人性​也​在​衰退。請​幫助​我​找到​長生不老藥。我​會​報​答​你​的​努\"\n\"力​-​我​以​我​的​名譽​起​誓\"\n\n#: Source/translation_dummy.cpp:762\nmsgid \"\"\n\"You have not found the Golden Elixir. I fear that I am doomed for eternity. \"\n\"Please, keep trying...\"\nmsgstr \"你​還沒​有​找到​金丹。我​害怕​我​註定​要​永生。請繼續​努力\"\n\n#: Source/translation_dummy.cpp:763\nmsgid \"\"\n\"You have saved my soul from damnation, and for that I am in your debt. If \"\n\"there is ever a way that I can repay you from beyond the grave I will find \"\n\"it, but for now - take my helm. On the journey I am about to take I will \"\n\"have little use for it. May it protect you against the dark powers below. Go \"\n\"with the Light, my friend...\"\nmsgstr \"\"\n\"你​救​了​我​的​靈魂​脫離​了​詛咒，為​此​我​欠​你​的​債。如果​有​什麼​方法​可以​讓​我​從墳​墓​那​邊回\"\n\"報​你​的​話，我​會​找到​的，但是​現​在，請​你​掌舵。在​我​即​將踏​上​的​旅途​中，我​對​它​毫​無​用\"\n\"處。愿​它​保護​你​不​受​黑暗​勢力​的​傷害。跟​著​光​走，我​的​朋友\"\n\n#: Source/translation_dummy.cpp:764\nmsgid \"\"\n\"Griswold speaks of The Anvil of Fury - a legendary artifact long searched \"\n\"for, but never found. Crafted from the metallic bones of the Razor Pit \"\n\"demons, the Anvil of Fury was smelt around the skulls of the five most \"\n\"powerful magi of the underworld. Carved with runes of power and chaos, any \"\n\"weapon or armor forged upon this Anvil will be immersed into the realm of \"\n\"Chaos, imbedding it with magical properties. It is said that the \"\n\"unpredictable nature of Chaos makes it difficult to know what the outcome of \"\n\"this smithing will be...\"\nmsgstr \"\"\n\"格里斯沃​爾德談​到​了​《​憤怒​的​鐵砧​》​——​一​件​傳說​中​的​神器，人們​一直​在​尋找，但​一直​沒​\"\n\"有​找到。憤怒​的​鐵砧​是​用​剃刀​坑​惡魔​的​金屬骨頭製​作​而​成​的，熔鑄​在​五​個​最​強​大​的​冥界​\"\n\"法師​的​頭骨​周圍。刻有​力量​和​混亂​符文，任何​在​這個鐵砧​上​鍛造​的​武器​或​護甲​都​將​被​浸\"\n\"入​混亂​的​領域，並將​其​嵌​入​魔法​屬性。據說，混沌​的​不​可​預測性​使​人們​很​難​知道​這場​鍛​\"\n\"造會​有​什麼​結​果\"\n\n#: Source/translation_dummy.cpp:765\nmsgid \"\"\n\"Don't you think that Griswold would be a better person to ask about this? \"\n\"He's quite handy, you know.\"\nmsgstr \"你​不​覺​得​格里斯沃​爾德會​是​一​個​更​好​的​人問這個問題嗎？你​知道，他​很​能​幹\"\n\n#: Source/translation_dummy.cpp:766\nmsgid \"\"\n\"If you had been looking for information on the Pestle of Curing or the \"\n\"Silver Chalice of Purification, I could have assisted you, my friend. \"\n\"However, in this matter, you would be better served to speak to either \"\n\"Griswold or Cain.\"\nmsgstr \"\"\n\"如果​你​一直​在​尋​找​治​療杵​或​凈化銀聖盃​的​資訊，我​可以​幫助​你，我​的​朋友。不​過，在​這\"\n\"件​事​上，你​最好​和​格里斯沃​爾德​或​凱恩談談\"\n\n#: Source/translation_dummy.cpp:767\nmsgid \"\"\n\"Griswold's father used to tell some of us when we were growing up about a \"\n\"giant anvil that was used to make mighty weapons. He said that when a hammer \"\n\"was struck upon this anvil, the ground would shake with a great fury. \"\n\"Whenever the earth moves, I always remember that story.\"\nmsgstr \"\"\n\"格里斯沃​爾德​的​父親​曾​經告訴​我​們​中​的​一些​人，當​我​們​成長​的​時候，一​個​巨大​的​鐵砧​是​\"\n\"用來​製造強​大​的​武器。他​說，當​一​把​錘子​敲​在​這個鐵砧​上時，地面​會​劇烈​地震​動。每​當​\"\n\"地球​移動時，我​總​是​記​得​那​個​故事\"\n\n#: Source/translation_dummy.cpp:768\nmsgid \"\"\n\"Greetings! It's always a pleasure to see one of my best customers! I know \"\n\"that you have been venturing deeper into the Labyrinth, and there is a story \"\n\"I was told that you may find worth the time to listen to...\\n\"\n\" \\n\"\n\"One of the men who returned from the Labyrinth told me about a mystic anvil \"\n\"that he came across during his escape. His description reminded me of \"\n\"legends I had heard in my youth about the burning Hellforge where powerful \"\n\"weapons of magic are crafted. The legend had it that deep within the \"\n\"Hellforge rested the Anvil of Fury! This Anvil contained within it the very \"\n\"essence of the demonic underworld...\\n\"\n\" \\n\"\n\"It is said that any weapon crafted upon the burning Anvil is imbued with \"\n\"great power. If this anvil is indeed the Anvil of Fury, I may be able to \"\n\"make you a weapon capable of defeating even the darkest lord of Hell! \\n\"\n\" \\n\"\n\"Find the Anvil for me, and I'll get to work!\"\nmsgstr \"\"\n\"問候語！很​高​興見​到​我​最​好​的​客戶​之一！我​知道​你​一直​在​冒險​深入​迷宮，有​一​個​故事​告\"\n\"訴​我，你​可能​覺​得​值得​花時間聽。。。\\n\"\n\" \\n\"\n\"​一​個​從迷宮裡​回來​的​人​告訴​我​他​逃跑​時​遇到​的​一​個​神秘​的​鐵砧。他​的​描述​讓​我​想起​了​我​\"\n\"年輕時​聽到​的​關於​燃燒​的​地​獄爐​的​傳說，那​裡​有​強​大​的​魔法​武器。傳說​在地​獄​熔爐​的​深\"\n\"處​安放​著​憤怒​的​鐵砧！這個鐵砧裡​面​包含​著​惡魔​世界​的​精髓。。。\\n\"\n\" \\n\"\n\"據說​任何​在​燃燒​的​鐵砧​上​製作​的​武器​都​充滿​了​巨大​的​力量。如果​這鐵​砧​真的​是​憤怒​的​鐵\"\n\"砧，我​也​許​能​讓​你​成為​一​件​武器，甚至​可以​打敗​最​黑暗​的​地獄​之​主！\\n\"\n\" \\n\"\n\"幫​我​找​鐵砧，我​就​去​幹活\"\n\n#: Source/translation_dummy.cpp:769\nmsgid \"\"\n\"Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could \"\n\"be your best hope, and I am sure that I can make you one of legendary \"\n\"proportions.\"\nmsgstr \"\"\n\"還​沒​有，嗯？好​吧，繼續​找。鐵砧​上​鍛造​的​武器​可能​是​你​最​大​的​希望，我​相信​我​能​讓​你​\"\n\"成為傳奇​般​的​人物​之一\"\n\n#: Source/translation_dummy.cpp:770\nmsgid \"\"\n\"I can hardly believe it! This is the Anvil of Fury - good work, my friend. \"\n\"Now we'll show those bastards that there are no weapons in Hell more deadly \"\n\"than those made by men! Take this and may Light protect you.\"\nmsgstr \"\"\n\"我​簡​直​不​敢​相信！這​是​憤怒​的​鐵砧​-​幹​得​好，我​的​朋友。現​在​我​們​要​告訴​那些​混蛋，地獄​\"\n\"里​沒​有​比​人類​製造​的​武器​更​致命​的​武器​了！拿​著​這個，光​會​保護​你​的\"\n\n#: Source/translation_dummy.cpp:771\nmsgid \"\"\n\"Griswold can't sell his anvil. What will he do then? And I'd be angry too if \"\n\"someone took my anvil!\"\nmsgstr \"\"\n\"格里斯沃​爾德賣​不​出​他​的​鐵砧。那​他​會​怎麼​做？如果​有​人​拿​了​我​的​鐵砧​我​也​會生氣​的\"\n\n#: Source/translation_dummy.cpp:772\nmsgid \"\"\n\"There are many artifacts within the Labyrinth that hold powers beyond the \"\n\"comprehension of mortals. Some of these hold fantastic power that can be \"\n\"used by either the Light or the Darkness. Securing the Anvil from below \"\n\"could shift the course of the Sin War towards the Light.\"\nmsgstr \"\"\n\"迷宮裡​有​許多神器，擁​有​著​凡​人​無法​理解​的​力量。其中​一些​擁​有​神奇​的​力量，可以​被​光\"\n\"明​或​黑暗​所​利用。從​下面​固定​鐵砧​可以​將罪惡​戰爭​的​程序轉​向​光明\"\n\n#: Source/translation_dummy.cpp:773\nmsgid \"\"\n\"If you were to find this artifact for Griswold, it could put a serious \"\n\"damper on my business here. Awwww, you'll never find it.\"\nmsgstr \"\"\n\"如果​你​為​格里斯沃​爾德​找到​這件藝​術品，它​會嚴​重影響​我​在​這裡​的​生意。啊，你​永遠​找​\"\n\"不​到​它\"\n\n#: Source/translation_dummy.cpp:774\nmsgid \"\"\n\"The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. \"\n\"Wherever this book you read from resides it is surely a place of great \"\n\"power.\\n\"\n\" \\n\"\n\"Legends speak of a pedestal that is carved from obsidian stone and has a \"\n\"pool of boiling blood atop its bone encrusted surface. There are also \"\n\"allusions to Stones of Blood that will open a door that guards an ancient \"\n\"treasure...\\n\"\n\" \\n\"\n\"The nature of this treasure is shrouded in speculation, my friend, but it is \"\n\"said that the ancient hero Arkaine placed the holy armor Valor in a secret \"\n\"vault. Arkaine was the first mortal to turn the tide of the Sin War and \"\n\"chase the legions of darkness back to the Burning Hells.\\n\"\n\" \\n\"\n\"Just before Arkaine died, his armor was hidden away in a secret vault. It is \"\n\"said that when this holy armor is again needed, a hero will arise to don \"\n\"Valor once more. Perhaps you are that hero...\"\nmsgstr \"\"\n\"血​之​門​和​火之殿​是​神秘​起源​的​地標。無論​你​從​哪​裡​讀​到​這​本​書，它​都​是​一​個​充滿​力量​的​\"\n\"地方。\\n\"\n\" \\n\"\n\"傳說​中​有​一​個​底​座​是​用​黑曜​石​雕刻​而​成​的，上面​有​一​灘​沸騰​的​血。也​有​典故​提到​血石會​\"\n\"打開​一​扇​門，守護​著​一​個​古老​的​寶藏。。。\\n\"\n\" \\n\"\n\"​我​的​朋友，這件​寶藏​的​性質​被​猜測​所​掩蓋，但​據說​古代​英雄​阿卡因​把​神聖​的​護甲​英勇​放\"\n\"置​在​一​個​秘密​的​地下室​裡。阿肯​是​第一​個​扭轉​罪惡戰爭​潮流，將​黑暗​軍團趕​回燃燒​地獄​\"\n\"的​凡​人。\\n\"\n\" \\n\"\n\"​就​在​阿凱死​前，他​的​護甲​藏​在​一​個​秘密​的​地下室​裡。據說，當這種​神聖​的​護甲​再次​被​需\"\n\"要​時，一​個​英雄​將​再次​出現​在​勇氣堂。也​許​你​就​是​那​個​英雄\"\n\n#: Source/translation_dummy.cpp:775\nmsgid \"\"\n\"Every child hears the story of the warrior Arkaine and his mystic armor \"\n\"known as Valor. If you could find its resting place, you would be well \"\n\"protected against the evil in the Labyrinth.\"\nmsgstr \"\"\n\"每​個​孩子​都​會聽​到​戰士​阿卡因​和​他​那​被​稱為​英勇​的​神秘​護甲​的​故事。如果​你​能​找到​它​的​\"\n\"安息​之​地，你​就​可以​在​迷宮裡​很​好​地​抵禦​邪惡\"\n\n#: Source/translation_dummy.cpp:776\nmsgid \"\"\n\"Hmm... it sounds like something I should remember, but I've been so busy \"\n\"learning new cures and creating better elixirs that I must have forgotten. \"\n\"Sorry...\"\nmsgstr \"\"\n\"隱​馬爾​可​夫​模型。。。這聽​起來​像​是​我​應該記​住​的，但​我​一直​忙於​學習​新​的​治療​方法​和​\"\n\"創造​更​好​的​長生不老藥，我​一定​忘記​了。對​不​起\"\n\n#: Source/translation_dummy.cpp:777\nmsgid \"\"\n\"The story of the magic armor called Valor is something I often heard the \"\n\"boys talk about. You had better ask one of the men in the village.\"\nmsgstr \"\"\n\"我​經​常聽​到​男孩​們​談論​的​關於​魔法​護甲​的​故事​叫做​英勇。你​最好​問問​村裡​的​一​個​人\"\n\n#: Source/translation_dummy.cpp:778\nmsgid \"\"\n\"The armor known as Valor could be what tips the scales in your favor. I will \"\n\"tell you that many have looked for it - including myself. Arkaine hid it \"\n\"well, my friend, and it will take more than a bit of luck to unlock the \"\n\"secrets that have kept it concealed oh, lo these many years.\"\nmsgstr \"\"\n\"被​稱為​英勇​的​護甲​可能​會​使​天平對​你​有利。我​要​告訴​你，很多​人​都​找過，包括​我​自己。\"\n\"阿肯​把​它​藏得​很​好，我​的​朋友，要​解開​隱藏​了​這麼​多​年​的​秘密還​需要​一​點​運氣​哦，瞧\"\n\n#: Source/translation_dummy.cpp:779\nmsgid \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\nmsgstr \"Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\"\n\n#: Source/translation_dummy.cpp:780\nmsgid \"\"\n\"Should you find these Stones of Blood, use them carefully. \\n\"\n\" \\n\"\n\"The way is fraught with danger and your only hope rests within your self \"\n\"trust.\"\nmsgstr \"\"\n\"如果​你​發現​了​這​些​血石，小心​使用。\\n\"\n\" \\n\"\n\"​道路​充滿​危險，你​唯一​的​希望​在​於​你​的​自信\"\n\n#: Source/translation_dummy.cpp:781\nmsgid \"\"\n\"You intend to find the armor known as Valor? \\n\"\n\" \\n\"\n\"No one has ever figured out where Arkaine stashed the stuff, and if my \"\n\"contacts couldn't find it, I seriously doubt you ever will either.\"\nmsgstr \"\"\n\"你​想​找到​被​稱為​英勇​的​護甲嗎？\\n\"\n\" \\n\"\n\"​沒人​知道​阿凱​把​東​西藏​在​哪​裡，如果​我​的​聯繫​人​找​不​到，我​很​懷疑​你​也​會\"\n\n#: Source/translation_dummy.cpp:782\nmsgid \"\"\n\"I know of only one legend that speaks of such a warrior as you describe. His \"\n\"story is found within the ancient chronicles of the Sin War...\\n\"\n\" \\n\"\n\"Stained by a thousand years of war, blood and death, the Warlord of Blood \"\n\"stands upon a mountain of his tattered victims. His dark blade screams a \"\n\"black curse to the living; a tortured invitation to any who would stand \"\n\"before this Executioner of Hell.\\n\"\n\" \\n\"\n\"It is also written that although he was once a mortal who fought beside the \"\n\"Legion of Darkness during the Sin War, he lost his humanity to his \"\n\"insatiable hunger for blood.\"\nmsgstr \"\"\n\"我​只​知道​一​個傳說像​你​描述​的​那​樣​提到​一​個​戰士。他​的​故事​可以​在​罪惡戰爭​的​古代​編​年\"\n\"史​中​找到。。。\\n\"\n\" \\n\"\n\"​被​一千​年​的​戰爭，鮮血​和​死亡​所​玷污，血​的​軍閥​站​在​他​破舊​的​受害者​的​山​上。他​的​黑暗​\"\n\"之​刃​向​活人​發出​了​黑色​的​詛咒​；​對​任何​站​在​這個​地獄​劊子​手​面前​的​人​的​一​個​嚴​刑拷打​的​\"\n\"邀請。\\n\"\n\" \\n\"\n\"書​中​還寫​到，雖然​他​曾​經​是​一​個​凡​人，在​罪惡戰爭​中​與​黑暗​軍團​並肩作戰，但​他​因對​鮮​\"\n\"血​的​貪​得​無厭​而​失去​了​人性\"\n\n#: Source/translation_dummy.cpp:783\nmsgid \"\"\n\"I am afraid that I haven't heard anything about such a vicious warrior, good \"\n\"master. I hope that you do not have to fight him, for he sounds extremely \"\n\"dangerous.\"\nmsgstr \"\"\n\"恐怕​我​還沒聽說過這麼​惡毒​的​戰士，好​師傅。我​希望​你​不用​和​他​打架，因​為​他​聽起來​非\"\n\"常​危險\"\n\n#: Source/translation_dummy.cpp:784\nmsgid \"\"\n\"Cain would be able to tell you much more about something like this than I \"\n\"would ever wish to know.\"\nmsgstr \"凱恩會告訴​你​比​我​想​知道​的​更​多​的​事情\"\n\n#: Source/translation_dummy.cpp:785\nmsgid \"\"\n\"If you are to battle such a fierce opponent, may Light be your guide and \"\n\"your defender. I will keep you in my thoughts.\"\nmsgstr \"\"\n\"如果​你​要​與​如此​兇猛​的​對手​作戰，愿​光明​成為​你​的​嚮導​和​衛士。我​會​一直​惦​記​著​你\"\n\n#: Source/translation_dummy.cpp:786\nmsgid \"\"\n\"Dark and wicked legends surrounds the one Warlord of Blood. Be well \"\n\"prepared, my friend, for he shows no mercy or quarter.\"\nmsgstr \"\"\n\"黑暗​邪惡​的​傳說圍​繞​著​一​個​血​的​軍閥。我​的​朋友，請​做好​準備，因​為​他​既​不​仁慈​也​不​吝\"\n\"嗇\"\n\n#: Source/translation_dummy.cpp:787\nmsgid \"\"\n\"Always you gotta talk about Blood? What about flowers, and sunshine, and \"\n\"that pretty girl that brings the drinks. Listen here, friend - you're \"\n\"obsessive, you know that?\"\nmsgstr \"\"\n\"你​總​是​說血？鮮花，陽光，還​有​那​個​送​飲料​的​漂亮​女孩​呢。聽著，朋友​-​你​很​癡迷，知道​\"\n\"嗎\"\n\n#: Source/translation_dummy.cpp:788\nmsgid \"\"\n\"His prowess with the blade is awesome, and he has lived for thousands of \"\n\"years knowing only warfare. I am sorry... I can not see if you will defeat \"\n\"him.\"\nmsgstr \"\"\n\"他​的​劍術​令​人​敬畏，他​已​經活​了​幾​千​年，只​知道​戰爭。我​很​抱歉。。。我​看​不​出​你​是否​\"\n\"能​打敗​他\"\n\n#: Source/translation_dummy.cpp:789\nmsgid \"\"\n\"I haven't ever dealt with this Warlord you speak of, but he sounds like he's \"\n\"going through a lot of swords. Wouldn't mind supplying his armies...\"\nmsgstr \"\"\n\"我​從來沒​有​和​你​說​的​那​個軍閥​打過​交道，但​他​聽起來​好像​經歷​了​很多​磨難。不​介意為​他​\"\n\"的​軍隊​提供​補給\"\n\n#: Source/translation_dummy.cpp:790\nmsgid \"\"\n\"My blade sings for your blood, mortal, and by my dark masters it shall not \"\n\"be denied.\"\nmsgstr \"我​的​刀鋒為​你​的​鮮血​歌唱，凡​人，我​的​黑暗​主人​不​會否認​它\"\n\n#: Source/translation_dummy.cpp:791\nmsgid \"\"\n\"Griswold speaks of the Heaven Stone that was destined for the enclave \"\n\"located in the east. It was being taken there for further study. This stone \"\n\"glowed with an energy that somehow granted vision beyond that which a normal \"\n\"man could possess. I do not know what secrets it holds, my friend, but \"\n\"finding this stone would certainly prove most valuable.\"\nmsgstr \"\"\n\"格里斯沃​爾德談​到​了​天石，它​是​註定​要​飛​地位​於​東​部。它​被​帶​到​那​裡​作​進​一​步​研究。這\"\n\"塊石頭​閃耀​著​一​種​能量，它​以​某​種​方式​賦予​了​一​個​普通​人無​法擁​有的​視覺。我​不​知道​它​\"\n\"有​什麼​秘密，我​的​朋友，但​找到​這塊​石頭​肯定​是​最​有​價值​的\"\n\n#: Source/translation_dummy.cpp:792\nmsgid \"\"\n\"The caravan stopped here to take on some supplies for their journey to the \"\n\"east. I sold them quite an array of fresh fruits and some excellent \"\n\"sweetbreads that Garda has just finished baking. Shame what happened to \"\n\"them...\"\nmsgstr \"\"\n\"商隊​在​這裡​停​了​下來，為​他​們​向​東​旅行​帶​去​一些​補給。我​賣給​他​們​不少​新​鮮​水果​和​一些​\"\n\"佳達剛剛​烤好​的​上​等​甜麵包。可惜​他​們發生​了​什麼\"\n\n#: Source/translation_dummy.cpp:793\nmsgid \"\"\n\"I don't know what it is that they thought they could see with that rock, but \"\n\"I will say this. If rocks are falling from the sky, you had better be \"\n\"careful!\"\nmsgstr \"\"\n\"我​不​知道​他​們​以​為​用​那​塊石頭​能​看到​什麼，但​我​要​說​的​是。如果​巖石從天而降，你​最好​\"\n\"小心\"\n\n#: Source/translation_dummy.cpp:794\nmsgid \"\"\n\"Well, a caravan of some very important people did stop here, but that was \"\n\"quite a while ago. They had strange accents and were starting on a long \"\n\"journey, as I recall. \\n\"\n\" \\n\"\n\"I don't see how you could hope to find anything that they would have been \"\n\"carrying.\"\nmsgstr \"\"\n\"好​吧，一​隊​重要​人物​停​在​這裡，但​那​是​很​久​以前​的​事​了。我​記得，他​們​的​口音​很​奇怪，\"\n\"正​開始​長途​旅行。\\n\"\n\" \\n\"\n\"​我​不​明白​你​怎麼​能​指望​找到​他​們會帶​的​東西\"\n\n#: Source/translation_dummy.cpp:795\nmsgid \"\"\n\"Stay for a moment - I have a story you might find interesting. A caravan \"\n\"that was bound for the eastern kingdoms passed through here some time ago. \"\n\"It was supposedly carrying a piece of the heavens that had fallen to earth! \"\n\"The caravan was ambushed by cloaked riders just north of here along the \"\n\"roadway. I searched the wreckage for this sky rock, but it was nowhere to be \"\n\"found. If you should find it, I believe that I can fashion something useful \"\n\"from it.\"\nmsgstr \"\"\n\"呆​一​會​兒​-​我​有​個​故事​你​可能​會​覺​得​有趣。一​輛​開往​東方​王國​的​大篷車​前​段​時間經過這​\"\n\"里。據說​它​帶著​一​片​落​在​地上​的​天空！大篷車​就​在​這北邊​的​公路​上​被​披著​斗篷​的​騎手​伏\"\n\"擊​了。我​在​殘骸​中​搜尋​這塊​巖石，但​找​不​到。如果​你​能​找到​它，我​相信​我​能​從​中​找到​有\"\n\"用​的​東西\"\n\n#: Source/translation_dummy.cpp:796\nmsgid \"\"\n\"I am still waiting for you to bring me that stone from the heavens. I know \"\n\"that I can make something powerful out of it.\"\nmsgstr \"我​還​在​等​你​從天​上​把​那​塊石頭帶給​我。我​知道​我​能​從​中​製​造出​強​大​的​東西\"\n\n#: Source/translation_dummy.cpp:797\nmsgid \"\"\n\"Let me see that - aye... aye, it is as I believed. Give me a moment...\\n\"\n\" \\n\"\n\"Ah, Here you are. I arranged pieces of the stone within a silver ring that \"\n\"my father left me. I hope it serves you well.\"\nmsgstr \"\"\n\"讓​我​看看​-​是​的。。。是​的，正​如​我​所​相信​的。給​我​一​點​時間。。。\\n\"\n\" \\n\"\n\"​啊，給​你。我​把​幾塊石頭​放​在​父親​留給​我​的​銀戒指里。希望​對​你​有​好​處\"\n\n#: Source/translation_dummy.cpp:798\nmsgid \"\"\n\"I used to have a nice ring; it was a really expensive one, with blue and \"\n\"green and red and silver. Don't remember what happened to it, though. I \"\n\"really miss that ring...\"\nmsgstr \"\"\n\"我​曾​經​有​一​個​漂亮​的​戒指​；​這​是​一​個​非常​昂貴​的，藍色，綠色，紅色​和​銀色。不​過，我​\"\n\"不​記得​發生​了​什麼。我​真的​很​想​念​那​個​戒指\"\n\n#: Source/translation_dummy.cpp:799\nmsgid \"\"\n\"The Heaven Stone is very powerful, and were it any but Griswold who bid you \"\n\"find it, I would prevent it. He will harness its powers and its use will be \"\n\"for the good of us all.\"\nmsgstr \"\"\n\"天石​是​非常​強​大​的，如果​是​任何​人，但​格里斯沃​爾德誰​叫​你​找到​它，我​會​阻止​它。他​將​\"\n\"利用​它​的​力量，它​的​使用​將​造福​於​我​們​所有​人\"\n\n#: Source/translation_dummy.cpp:800\nmsgid \"\"\n\"If anyone can make something out of that rock, Griswold can. He knows what \"\n\"he is doing, and as much as I try to steal his customers, I respect the \"\n\"quality of his work.\"\nmsgstr \"\"\n\"如果​有​人​能​用​那塊石頭​做​點什麼，格里斯沃​爾德​也​能。他​知道​自己​在​做​什麼，儘管​我​試\"\n\"圖竊取​他​的​客戶，但​我​尊重​他​的​工作​質量\"\n\n#: Source/translation_dummy.cpp:801\nmsgid \"\"\n\"The witch Adria seeks a black mushroom? I know as much about Black Mushrooms \"\n\"as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, \"\n\"but this is something that cannot be found in any of my stories or books.\"\nmsgstr \"\"\n\"女​巫艾德里亞​想要​一​個​黑​蘑菇？我​對​黑​蘑菇​的​瞭解​和​對紅​鯡魚​的​瞭解​一​樣​多。也​許治療\"\n\"者​佩平​可以​告訴​你​更​多，但​這​是​我​的​任何​故事​或​書籍​中​都​找​不​到​的\"\n\n#: Source/translation_dummy.cpp:802\nmsgid \"\"\n\"Let me just say this. Both Garda and I would never, EVER serve black \"\n\"mushrooms to our honored guests. If Adria wants some mushrooms in her stew, \"\n\"then that is her business, but I can't help you find any. Black mushrooms... \"\n\"disgusting!\"\nmsgstr \"\"\n\"我​就​這麼​說​吧。我​和​嘉達​永遠​不​會給​我​們​的​貴賓​提供​黑蘑菇。如果​艾德里亞​想​在​燉菜​里​\"\n\"放些​蘑菇，那​是​她​的​事，但​我​幫​不​了​你。黑​蘑菇。。。噁心\"\n\n#: Source/translation_dummy.cpp:803\nmsgid \"\"\n\"The witch told me that you were searching for the brain of a demon to assist \"\n\"me in creating my elixir. It should be of great value to the many who are \"\n\"injured by those foul beasts, if I can just unlock the secrets I suspect \"\n\"that its alchemy holds. If you can remove the brain of a demon when you kill \"\n\"it, I would be grateful if you could bring it to me.\"\nmsgstr \"\"\n\"巫婆​告訴​我​你​在​尋​找​一​個​惡魔​的​大​腦來​幫助​我​製造​長生不老藥。如果​我​能解開​我​懷疑​它​\"\n\"的​鍊金術​所​掌握​的​秘密，它​對許​多​被​這​些​邪惡野獸​傷害​的​人來說應該​是​非常​有​價值​的。\"\n\"如果​你​能​在​殺死​一​個​惡魔​的​時候​把​它​的​大腦​取出來，如果​你​能​把​它​帶給​我，我​將​不​勝​感\"\n\"激\"\n\n#: Source/translation_dummy.cpp:804\nmsgid \"\"\n\"Excellent, this is just what I had in mind. I was able to finish the elixir \"\n\"without this, but it can't hurt to have this to study. Would you please \"\n\"carry this to the witch? I believe that she is expecting it.\"\nmsgstr \"\"\n\"太​好​了，這​正​是​我​想要​的。沒​有​這個​我​就​可以​完成​長生不老藥，但是​有​這個來學習​也​沒\"\n\"什麼壞處。請​你​把​這個帶給​女​巫好嗎？我​相信​她​在​等著​呢\"\n\n#: Source/translation_dummy.cpp:805\nmsgid \"\"\n\"I think Ogden might have some mushrooms in the storage cellar. Why don't you \"\n\"ask him?\"\nmsgstr \"我​想​奧格登​的​地窖​里​可能​有​蘑菇。你​為什麼​不​問問​他\"\n\n#: Source/translation_dummy.cpp:806\nmsgid \"\"\n\"If Adria doesn't have one of these, you can bet that's a rare thing indeed. \"\n\"I can offer you no more help than that, but it sounds like... a huge, \"\n\"gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\"\nmsgstr \"\"\n\"如果​阿德里婭沒​有​這​些，你​可以​打賭這確實​是​一​件​罕見​的​事情。我​不​能​給​你​更​多​的​幫\"\n\"助，但是​聽起來。。。一​個​巨大​的，巨大​的，腫脹​的，膨脹​的​蘑菇！嗯，我​想​打獵​不​錯​\"\n\"吧\"\n\n#: Source/translation_dummy.cpp:807\nmsgid \"\"\n\"Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, \"\n\"listen... here's the secret - moderation is the key!\"\nmsgstr \"\"\n\"奧​格登​混合​了​一​種​難​吃​的​黑蘑菇，但​如果​我​喝​了​它​我​會​生病​的。聽著，聽著。。。秘訣​\"\n\"就​在​這裡​——​適度​才​是​關鍵\"\n\n#: Source/translation_dummy.cpp:808\nmsgid \"\"\n\"What do we have here? Interesting, it looks like a book of reagents. Keep \"\n\"your eyes open for a black mushroom. It should be fairly large and easy to \"\n\"identify. If you find it, bring it to me, won't you?\"\nmsgstr \"\"\n\"我​們這裡​有​什麼？有趣​的​是，它​看起​來像​一​本​試劑書。睜大​眼睛​看黑​蘑菇。它​應該​相當​\"\n\"大，並且​易於​識別。如果​你​找到​了，把​它​帶給​我，好嗎\"\n\n#: Source/translation_dummy.cpp:809\nmsgid \"\"\n\"It's a big, black mushroom that I need. Now run off and get it for me so \"\n\"that I can use it for a special concoction that I am working on.\"\nmsgstr \"\"\n\"我​需要​一​個​又​大​又​黑​的​蘑菇。現​在​跑去給​我​拿，這樣​我​就​可以​用​它​做​我​正在​做​的​一​種​特\"\n\"殊​的​調味品​了\"\n\n#: Source/translation_dummy.cpp:810\nmsgid \"\"\n\"Yes, this will be perfect for a brew that I am creating. By the way, the \"\n\"healer is looking for the brain of some demon or another so he can treat \"\n\"those who have been afflicted by their poisonous venom. I believe that he \"\n\"intends to make an elixir from it. If you help him find what he needs, \"\n\"please see if you can get a sample of the elixir for me.\"\nmsgstr \"\"\n\"是​的，這將​是​完美​的​釀造，我​正在​建立。順便​說​一​句，治療者​正​在​尋​找​某​種​惡魔​的​大\"\n\"腦，這樣​他​就​可以​治療​那些​被​他​們​的​毒液​折磨​的​人。我​相信​他​打算​用​它​做​長生不老藥。\"\n\"如果​你​幫​他​找到​他​需要​的​東西，請​你​幫​我​拿​一​個​長生不老藥​的​樣品\"\n\n#: Source/translation_dummy.cpp:811\nmsgid \"\"\n\"Why have you brought that here? I have no need for a demon's brain at this \"\n\"time. I do need some of the elixir that the Healer is working on. He needs \"\n\"that grotesque organ that you are holding, and then bring me the elixir. \"\n\"Simple when you think about it, isn't it?\"\nmsgstr \"\"\n\"你​為什麼​把​它​帶​到​這裡來？我​現​在​不​需要​惡魔​的​大腦。我​確實​需要​一些​治療者​正​在​研製​\"\n\"的​長生不老藥。他​需要​你​拿著​的​奇怪​的​器官，然​後​給​我​拿​長生不老藥。想起來​很​簡單，\"\n\"不​是​嗎\"\n\n#: Source/translation_dummy.cpp:812\nmsgid \"\"\n\"What? Now you bring me that elixir from the healer? I was able to finish my \"\n\"brew without it. Why don't you just keep it...\"\nmsgstr \"\"\n\"什麼？現​在​你​把​醫​治者​的​長生不​老​藥帶給​我？不用​它​我​就​能​喝​完​我​的​啤酒。你​為什麼​不​\"\n\"留著​它\"\n\n#: Source/translation_dummy.cpp:813\nmsgid \"\"\n\"I don't have any mushrooms of any size or color for sale. How about \"\n\"something a bit more useful?\"\nmsgstr \"我​沒​有​任何​大小​和​顏色​的​蘑菇​出售。再​來點​有用​的​怎​麼​樣\"\n\n#: Source/translation_dummy.cpp:814\nmsgid \"\"\n\"So, the legend of the Map is real. Even I never truly believed any of it! I \"\n\"suppose it is time that I told you the truth about who I am, my friend. You \"\n\"see, I am not all that I seem...\\n\"\n\" \\n\"\n\"My true name is Deckard Cain the Elder, and I am the last descendant of an \"\n\"ancient Brotherhood that was dedicated to keeping and safeguarding the \"\n\"secrets of a timeless evil. An evil that quite obviously has now been \"\n\"released...\\n\"\n\" \\n\"\n\"The evil that you move against is the dark Lord of Terror - known to mortal \"\n\"men as Diablo. It was he who was imprisoned within the Labyrinth many \"\n\"centuries ago. The Map that you hold now was created ages ago to mark the \"\n\"time when Diablo would rise again from his imprisonment. When the two stars \"\n\"on that map align, Diablo will be at the height of his power. He will be all \"\n\"but invincible...\\n\"\n\" \\n\"\n\"You are now in a race against time, my friend! Find Diablo and destroy him \"\n\"before the stars align, for we may never have a chance to rid the world of \"\n\"his evil again!\"\nmsgstr \"\"\n\"所以，地圖​上​的​傳說​是​真實​的。連​我​都​不​相信！我​想​是​時候​告訴​你​我​是​誰​了，我​的​朋\"\n\"友。你​看，我​並​不​像​我​看​起來​那​樣。。。\\n\"\n\" \\n\"\n\"​我​的​真名​是​老凱恩，我​是​一​個​古老​兄弟會​的​最後​一個​後​代，這個​兄弟​會​致力​於​保守​和​保\"\n\"護​一​個​永恒​邪惡​的​秘密。一​個​很​明顯​已​經​被​釋放​的​惡魔。。。\\n\"\n\" \\n\"\n\"​你​要​對付​的​惡魔​是​恐怖​的​黑魔王​——​凡​人​都​知道​的​迪亞波羅。幾個世紀​前​被​囚禁​在​迷宮裡​\"\n\"的​正​是​他。你​現​在​持有​的​地圖​是​很​久​以前​創造​的，用來標​記​迪亞波羅從​監​禁​中​復活​的​時\"\n\"間。當​那​張​地圖​上​的​兩顆​星星對​齊時，迪亞波羅將達​到​他​的​能量​頂峰。他​將​所​向​無\"\n\"敵。。。\\n\"\n\" \\n\"\n\"​你​現​在在​和​時間​賽​跑，我​的​朋友！找到​迪亞波羅，在​眾星​雲集​之前​消滅​他，因​為​我​們​可\"\n\"能​再​也​沒​有​機會擺脫​他​的​邪惡​了\"\n\n#: Source/translation_dummy.cpp:815\nmsgid \"\"\n\"Our time is running short! I sense his dark power building and only you can \"\n\"stop him from attaining his full might.\"\nmsgstr \"\"\n\"我​們​的​時間​不​多​了！我​感覺​到​了​他​的​黑暗​力量，只有​你​才​能​阻止​他​達​到​他​的​全部​力量\"\n\n#: Source/translation_dummy.cpp:816\nmsgid \"\"\n\"I am sure that you tried your best, but I fear that even your strength and \"\n\"will may not be enough. Diablo is now at the height of his earthly power, \"\n\"and you will need all your courage and strength to defeat him. May the Light \"\n\"protect and guide you, my friend. I will help in any way that I am able.\"\nmsgstr \"\"\n\"我​相信​你​已​經​盡力​了，但​我​擔心​你​的​力量​和​意志​都​不​夠。迪亞波羅現​在​正處於​他​塵世​力\"\n\"量​的​頂峰，你​將​需要​你​所有​的​勇氣​和​力量​來打敗​他。愿光明​保護​和​指引​你，我​的​朋友。\"\n\"我​將盡​我​所​能​提供​幫助。\"\n\n#: Source/translation_dummy.cpp:817\nmsgid \"\"\n\"If the witch can't help you and suggests you see Cain, what makes you think \"\n\"that I would know anything? It sounds like this is a very serious matter. \"\n\"You should hurry along and see the storyteller as Adria suggests.\"\nmsgstr \"\"\n\"如果​女​巫幫​不​了​你，建議​你​去見凱恩，你​憑什麼​認為​我​什麼​都​知道？聽起​來這​是​一​件​非\"\n\"常​嚴重​的​事情。你​應該​像​阿德里​亞建議​的​那樣，趕快​去​見講​故事​的​人\"\n\n#: Source/translation_dummy.cpp:818\nmsgid \"\"\n\"I can't make much of the writing on this map, but perhaps Adria or Cain \"\n\"could help you decipher what this refers to. \\n\"\n\" \\n\"\n\"I can see that it is a map of the stars in our sky, but any more than that \"\n\"is beyond my talents.\"\nmsgstr \"\"\n\"我​對這張​地​圖​上​的​文字​不​太​瞭解，但​也​許​艾德里亞​或​凱恩​能​幫​你​破譯這​是​指什麼。\\n\"\n\" \\n\"\n\"​我​可以​看到​這​是​一​張​我​們​天空​中​星星​的​地圖，但​比這​更​是​超出​我​的​能力\"\n\n#: Source/translation_dummy.cpp:819\nmsgid \"\"\n\"The best person to ask about that sort of thing would be our storyteller. \\n\"\n\" \\n\"\n\"Cain is very knowledgeable about ancient writings, and that is easily the \"\n\"oldest looking piece of paper that I have ever seen.\"\nmsgstr \"\"\n\"問​這類​事情​的​最​佳​人選​是​我​們​的​說書​人。\\n\"\n\" \\n\"\n\"凱恩對​古代​著作​非常​瞭解，這​是​我​見過​的​最​古老​的​一​張​紙\"\n\n#: Source/translation_dummy.cpp:820\nmsgid \"\"\n\"I have never seen a map of this sort before. Where'd you get it? Although I \"\n\"have no idea how to read this, Cain or Adria may be able to provide the \"\n\"answers that you seek.\"\nmsgstr \"\"\n\"我​以前​從​未​見過​這樣​的​地圖。你​從​哪​兒​弄來​的？雖然​我​不​知道​該​怎​麼讀​這篇​文章，但​凱\"\n\"恩​或​阿德里亞​也​許能​提供​你​所​尋求​的​答案\"\n\n#: Source/translation_dummy.cpp:821\nmsgid \"\"\n\"Listen here, come close. I don't know if you know what I know, but you have \"\n\"really got somethin' here. That's a map.\"\nmsgstr \"\"\n\"聽​著，靠近點。我​不​知道​你​是否​知道​我​所​知道​的，但​你​真的​有些​東西​在​這裡。那​是​一​張​\"\n\"地​圖\"\n\n#: Source/translation_dummy.cpp:822\nmsgid \"\"\n\"Oh, I'm afraid this does not bode well at all. This map of the stars \"\n\"portends great disaster, but its secrets are not mine to tell. The time has \"\n\"come for you to have a very serious conversation with the Storyteller...\"\nmsgstr \"\"\n\"哦，恐怕​這​一​點​都​不​是​好​兆頭。這張​星圖​預​示著​巨大​的​災難，但​它​的​秘密不​是​我​說​的。\"\n\"是​時候讓​你​和​講​故事​的​人​好好​談談​了\"\n\n#: Source/translation_dummy.cpp:823\nmsgid \"\"\n\"I've been looking for a map, but that certainly isn't it. You should show \"\n\"that to Adria - she can probably tell you what it is. I'll say one thing; it \"\n\"looks old, and old usually means valuable.\"\nmsgstr \"\"\n\"我​一直​在​找​地圖，但​那​肯定​不​是。你​應該​把​這個給​艾德里亞​看-​她​可能​會告訴​你​是​什麼。\"\n\"我​要​說​一​件​事​；​它​看​起​來​很​老，而且​老​通常​意味​著​有​價值\"\n\n#: Source/translation_dummy.cpp:824\nmsgid \"\"\n\"Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\"\nmsgstr \"請​放心，不​要​受傷。不​殺​人。保持​活力，下​次​給​你​帶來​好​東​西\"\n\n#: Source/translation_dummy.cpp:825\nmsgid \"\"\n\"Something for you I am making. Again, not kill Gharbad. Live and give \"\n\"good. \\n\"\n\" \\n\"\n\"You take this as proof I keep word...\"\nmsgstr \"\"\n\"我​正在​為​你​做​些​東西。再​說​一​遍，別殺​了​加爾巴德。活​得​好好​的。\\n\"\n\" \\n\"\n\"​你​把​這當作​我​遵守​諾言​的​證據\"\n\n#: Source/translation_dummy.cpp:826\nmsgid \"\"\n\"Nothing yet! Almost done. \\n\"\n\" \\n\"\n\"Very powerful, very strong. Live! Live! \\n\"\n\" \\n\"\n\"No pain and promise I keep!\"\nmsgstr \"\"\n\"還​沒​有！差不​多​了。\\n\"\n\" \\n\"\n\"​非常​強​大，非常​強​大。居住​居住​\\n\"\n\" \\n\"\n\"沒​有​痛苦，我​信守​諾言\"\n\n#: Source/translation_dummy.cpp:827\nmsgid \"This too good for you. Very Powerful! You want - you take!\"\nmsgstr \"這對​你​來說​太​好​了。非常​強​大！你​想要​-​你​拿\"\n\n#: Source/translation_dummy.cpp:828\nmsgid \"\"\n\"What?! Why are you here? All these interruptions are enough to make one \"\n\"insane. Here, take this and leave me to my work. Trouble me no more!\"\nmsgstr \"\"\n\"什麼？！你​為什麼​在​這裡？所有​這​些​干擾​都​足以​讓人​發瘋。來，拿​著​這個，讓​我​繼續​工\"\n\"作。別​再​煩​我​了\"\n\n#: Source/translation_dummy.cpp:829\nmsgid \"Arrrrgh! Your curiosity will be the death of you!!!\"\nmsgstr \"啊！你​的​好奇​心將​是​你​的​死亡\"\n\n#: Source/translation_dummy.cpp:830\nmsgid \"Hello, my friend. Stay awhile and listen...\"\nmsgstr \"你​好，我​的​朋友。呆​一​會​兒聽​我​說\"\n\n#: Source/translation_dummy.cpp:831\nmsgid \"\"\n\"While you are venturing deeper into the Labyrinth you may find tomes of \"\n\"great knowledge hidden there. \\n\"\n\" \\n\"\n\"Read them carefully for they can tell you things that even I cannot.\"\nmsgstr \"\"\n\"當​你​冒險​深入​迷宮時，你​可能​會發現​那​裡​藏著​大量​的​知識。\\n\"\n\" \\n\"\n\"仔細閱讀​它​們，因​為​它​們​能​告訴​你​即使​是​我​也​不​能​告訴​你​的​事情\"\n\n#: Source/translation_dummy.cpp:832\nmsgid \"\"\n\"I know of many myths and legends that may contain answers to questions that \"\n\"may arise in your journeys into the Labyrinth. If you come across challenges \"\n\"and questions to which you seek knowledge, seek me out and I will tell you \"\n\"what I can.\"\nmsgstr \"\"\n\"我​知道​許​多​神話​和​傳說，其中​可能​包含​對​你​在​迷宮​之​旅​中​可​能​出現​的​問題​的​答案。如果​\"\n\"你​遇到​挑戰​和​問題，你​尋求​知識，尋​找​我​出來，我​會​告訴​你​我​能​做​什麼\"\n\n#: Source/translation_dummy.cpp:833\nmsgid \"\"\n\"Griswold - a man of great action and great courage. I bet he never told you \"\n\"about the time he went into the Labyrinth to save Wirt, did he? He knows his \"\n\"fair share of the dangers to be found there, but then again - so do you. He \"\n\"is a skilled craftsman, and if he claims to be able to help you in any way, \"\n\"you can count on his honesty and his skill.\"\nmsgstr \"\"\n\"格里斯沃​爾德​——​一​個行動力​和​勇氣​都​很​強​的​人。我​打賭​他​從沒​告訴過​你​他​進迷宮救​沃特​\"\n\"的​事，是​嗎？他​知道​在​那​裡會​有​很多​危險，但​話說​回來，你​也是。他​是​一​個​技藝​高超​的​\"\n\"工匠，如果​他​聲稱​能​以​任何​方式​幫助​你，你​可以​指望​他​的​誠實​和​他​的​技能\"\n\n#: Source/translation_dummy.cpp:834\nmsgid \"\"\n\"Ogden has owned and run the Rising Sun Inn and Tavern for almost four years \"\n\"now. He purchased it just a few short months before everything here went to \"\n\"hell. He and his wife Garda do not have the money to leave as they invested \"\n\"all they had in making a life for themselves here. He is a good man with a \"\n\"deep sense of responsibility.\"\nmsgstr \"\"\n\"奧​格登​已​經擁​有​和​經營​旭日​酒店​近​四​年​了。他​買​了​它​就​在​幾個​月​前，這裡​的​一切​都​變成​\"\n\"了​地獄。他​和​他​的​妻子​加爾達沒​有​錢離開，因​為​他​們​把​所有​的​錢​都​投資​在​這裡為​自己​創\"\n\"造​生活。他​是​一​個​很​有​責​任感​的​好​人\"\n\n#: Source/translation_dummy.cpp:835\nmsgid \"\"\n\"Poor Farnham. He is a disquieting reminder of the doomed assembly that \"\n\"entered into the Cathedral with Lazarus on that dark day. He escaped with \"\n\"his life, but his courage and much of his sanity were left in some dark pit. \"\n\"He finds comfort only at the bottom of his tankard nowadays, but there are \"\n\"occasional bits of truth buried within his constant ramblings.\"\nmsgstr \"\"\n\"可​憐​的​法納姆。他​令​人​不安​地​提醒​人們，在​那​黑暗​的​一​天，註定​要​與​拉撒路​一起​進入​大​\"\n\"教堂​的​集會。他​帶​著​生命​逃走​了，但​他​的​勇氣​和​大部分​的​理智​都​留​在​了​某​個​黑暗​的​坑​\"\n\"里。如今，他​只​在​酒館​的​最​底​層​找到​安慰，但​在​他​不​斷​的​閑談​中，偶爾​也​隱​藏​著​一些​真\"\n\"相\"\n\n#: Source/translation_dummy.cpp:836\nmsgid \"\"\n\"The witch, Adria, is an anomaly here in Tristram. She arrived shortly after \"\n\"the Cathedral was desecrated while most everyone else was fleeing. She had a \"\n\"small hut constructed at the edge of town, seemingly overnight, and has \"\n\"access to many strange and arcane artifacts and tomes of knowledge that even \"\n\"I have never seen before.\"\nmsgstr \"\"\n\"女​巫艾德里亞​是​特里斯特拉姆​的​一​個​異類。她​是​在​大​教堂​被​褻瀆​后​不久​到達​的，而​大多​\"\n\"數​人​都​在逃離。她​在​城鎮邊​緣​建​了​一​間​小屋，似乎​是​一​夜​之​間​建成​的，她​能​接觸​到​許多​\"\n\"奇怪​而​神秘​的​文物​和​知識​的​大部頭，連​我​都​從​未​見過\"\n\n#: Source/translation_dummy.cpp:837\nmsgid \"\"\n\"The story of Wirt is a frightening and tragic one. He was taken from the \"\n\"arms of his mother and dragged into the labyrinth by the small, foul demons \"\n\"that wield wicked spears. There were many other children taken that day, \"\n\"including the son of King Leoric. The Knights of the palace went below, but \"\n\"never returned. The Blacksmith found the boy, but only after the foul beasts \"\n\"had begun to torture him for their sadistic pleasures.\"\nmsgstr \"\"\n\"維特​的​故事​是​一​個​可怕​而​悲慘​的​故事。他​從​他​母親​的​懷抱​中​被​帶​到​迷宮裡，被​那些​揮舞\"\n\"邪惡​長矛​的​邪惡​小​惡​魔們​拖進​了​迷宮。那​天還​有​許​多​孩子​被​帶走，包括​利奧里克國王​的​\"\n\"兒子。宮殿​的​騎士​們​下樓去​了，但​再​也​沒​有​回來。鐵匠​找到​了​那個​男孩，但​那​是​在​那些​\"\n\"邪惡​的​野獸開​始​折磨​他​以​獲取​他​們​的​虐待​狂​般​的​快樂​之後\"\n\n#: Source/translation_dummy.cpp:838\nmsgid \"\"\n\"Ah, Pepin. I count him as a true friend - perhaps the closest I have here. \"\n\"He is a bit addled at times, but never a more caring or considerate soul has \"\n\"existed. His knowledge and skills are equaled by few, and his door is always \"\n\"open.\"\nmsgstr \"\"\n\"啊，佩平。我​把​他​視為​真正​的​朋友​——​也​許​是​我​在​這裡​最​親密​的​朋友。他​有​時​有​點​煩躁不\"\n\"安，但​從來沒​有​一​個​更​關心​和​體貼​的​靈魂​存在​過。他​的​知識​和​技能​為數​不​多，他​的​大門\"\n\"總​是​敞開​的\"\n\n#: Source/translation_dummy.cpp:839\nmsgid \"\"\n\"Gillian is a fine woman. Much adored for her high spirits and her quick \"\n\"laugh, she holds a special place in my heart. She stays on at the tavern to \"\n\"support her elderly grandmother who is too sick to travel. I sometimes fear \"\n\"for her safety, but I know that any man in the village would rather die than \"\n\"see her harmed.\"\nmsgstr \"\"\n\"阿嬌​是​個好​女人。她​因興​高​采烈​和​爽朗​的​笑聲​而​備受​崇拜，在​我​心​中​佔​有​特殊​的​地位。\"\n\"她​留​在​酒館裡​養活​年邁​的​祖母，因​為​她​病​得​不​能​旅行​了。我​有​時擔心​她​的​安全，但​我​知\"\n\"道​村裡​的​任何​男人​都​寧願死​也​不​願​看到​她​受到​傷害\"\n\n#: Source/translation_dummy.cpp:840\nmsgid \"Greetings, good master. Welcome to the Tavern of the Rising Sun!\"\nmsgstr \"你​好，好​師父。歡​迎來​到​朝陽​酒館\"\n\n#: Source/translation_dummy.cpp:841\nmsgid \"\"\n\"Many adventurers have graced the tables of my tavern, and ten times as many \"\n\"stories have been told over as much ale. The only thing that I ever heard \"\n\"any of them agree on was this old axiom. Perhaps it will help you. You can \"\n\"cut the flesh, but you must crush the bone.\"\nmsgstr \"\"\n\"我​的​酒館裡​有​許​多​冒​險家，講​的​故事​是​喝​啤酒​的​十​倍。我​唯一​聽​到​他​們​一致​同意​的​就​是​\"\n\"這條​古老​的​公理。也​許這對​你​有​幫助。你​可以​割肉，但​必須​壓​碎骨頭\"\n\n#: Source/translation_dummy.cpp:842\nmsgid \"\"\n\"Griswold the blacksmith is extremely knowledgeable about weapons and armor. \"\n\"If you ever need work done on your gear, he is definitely the man to see.\"\nmsgstr \"\"\n\"鐵​匠​格里斯沃​爾德對​武器​和​護甲​非常​瞭解。如果​你​需要​修理​你​的​裝備，他​絕對​是​你​要​找​\"\n\"的​人\"\n\n#: Source/translation_dummy.cpp:843\nmsgid \"\"\n\"Farnham spends far too much time here, drowning his sorrows in cheap ale. I \"\n\"would make him leave, but he did suffer so during his time in the Labyrinth.\"\nmsgstr \"\"\n\"法納姆​在​這裡待​的​時間​太​長​了，他​用​廉價​的​啤酒來​消愁。我​想​讓​他​離開，但​他​在​迷宮裡​\"\n\"的​時候​確實​很​痛苦\"\n\n#: Source/translation_dummy.cpp:844\nmsgid \"\"\n\"Adria is wise beyond her years, but I must admit - she frightens me a \"\n\"little. \\n\"\n\" \\n\"\n\"Well, no matter. If you ever have need to trade in items of sorcery, she \"\n\"maintains a strangely well-stocked hut just across the river.\"\nmsgstr \"\"\n\"艾德里亞​的​智慧​超過​了​她​的​年齡，但​我​必​須​承認​——​她​有​點嚇​到​我​了。\\n\"\n\" \\n\"\n\"​好​吧，沒關係。如果​你​需要​交易​巫術​物品，她​在​河​對岸​有​一​個​奇怪​的​倉庫\"\n\n#: Source/translation_dummy.cpp:845\nmsgid \"\"\n\"If you want to know more about the history of our village, the storyteller \"\n\"Cain knows quite a bit about the past.\"\nmsgstr \"如果​你​想​更​多​地​瞭解​我​們​村子​的​歷史，講​故事​的​凱恩對過去​的​事​相當​瞭解\"\n\n#: Source/translation_dummy.cpp:846\nmsgid \"\"\n\"Wirt is a rapscallion and a little scoundrel. He was always getting into \"\n\"trouble, and it's no surprise what happened to him. \\n\"\n\" \\n\"\n\"He probably went fooling about someplace that he shouldn't have been. I feel \"\n\"sorry for the boy, but I don't abide the company that he keeps.\"\nmsgstr \"\"\n\"維特​是​個說​唱​歌手​和​小​流氓。他​總​是​惹麻煩，發生​在​他​身​上​的​事​也​就​不足為奇​了。\\n\"\n\" \\n\"\n\"​他​可能​去​了​一​個​他​不​該去​的​地方。我​為​那​個​男孩​感到​難過，但​我​不​願意​和​他​作伴\"\n\n#: Source/translation_dummy.cpp:847\nmsgid \"\"\n\"Pepin is a good man - and certainly the most generous in the village. He is \"\n\"always attending to the needs of others, but trouble of some sort or another \"\n\"does seem to follow him wherever he goes...\"\nmsgstr \"\"\n\"佩平​是​個好​人，當然​也​是​村裡​最​慷慨​的​人。他​總​是​關心​別人​的​需要，但​無論​他​走到​哪\"\n\"里，總​有​一些​麻煩​跟​著​他\"\n\n#: Source/translation_dummy.cpp:848\nmsgid \"\"\n\"Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, \"\n\"she would have fled from here long ago. \\n\"\n\" \\n\"\n\"Goodness knows I begged her to leave, telling her that I would watch after \"\n\"the old woman, but she is too sweet and caring to have done so.\"\nmsgstr \"\"\n\"阿嬌，我​的​酒吧​女​招待？如果​不​是​因為​她​對​大壩​的​責任感，她​早​就​從這裡​逃走​了。\\n\"\n\" \\n\"\n\"天​知道​我​求​她​離開，告訴​她​我​會照顧​那​個​老​婦人，但​她​太​可​愛​了，太​體貼​了\"\n\n#: Source/translation_dummy.cpp:849\nmsgid \"What ails you, my friend?\"\nmsgstr \"你​怎麼​了，我​的​朋友\"\n\n#: Source/translation_dummy.cpp:850\nmsgid \"\"\n\"I have made a very interesting discovery. Unlike us, the creatures in the \"\n\"Labyrinth can heal themselves without the aid of potions or magic. If you \"\n\"hurt one of the monsters, make sure it is dead or it very well may \"\n\"regenerate itself.\"\nmsgstr \"\"\n\"我​有​一​個​非常​有趣​的​發現。與​我​們​不同​的​是，迷宮​中​的​生物​不​用​藥水​或​魔法​就​能​自愈。\"\n\"如果​你​傷害​了​其中​一​個​怪物，確保​它​已​經死​了，否則​它​很​可能​會​自己​再生\"\n\n#: Source/translation_dummy.cpp:851\nmsgid \"\"\n\"Before it was taken over by, well, whatever lurks below, the Cathedral was a \"\n\"place of great learning. There are many books to be found there. If you find \"\n\"any, you should read them all, for some may hold secrets to the workings of \"\n\"the Labyrinth.\"\nmsgstr \"\"\n\"在​它​被​下面​隱藏​的​東西​接管​之前，大​教堂​是​一​個​非常​有​學問​的​地方。那裡​有​許​多​書​可以​\"\n\"找到。如果​你​發現​了​什麼，你​應該​把​它​們​全部​讀​一​遍，因​為​有些​可能​掌握​著迷宮​運​作​的​\"\n\"秘密\"\n\n#: Source/translation_dummy.cpp:852\nmsgid \"\"\n\"Griswold knows as much about the art of war as I do about the art of \"\n\"healing. He is a shrewd merchant, but his work is second to none. Oh, I \"\n\"suppose that may be because he is the only blacksmith left here.\"\nmsgstr \"\"\n\"格里斯沃​爾德對戰爭​藝術​的​瞭解​和​我​對治療藝術​的​瞭解​一​樣​多。他​是​個​精明​的​商人，但​\"\n\"他​的​工作​是​首屈一指​的。哦，我​想​那​可能​是​因為​他​是​這裡​唯一​的​鐵匠\"\n\n#: Source/translation_dummy.cpp:853\nmsgid \"\"\n\"Cain is a true friend and a wise sage. He maintains a vast library and has \"\n\"an innate ability to discern the true nature of many things. If you ever \"\n\"have any questions, he is the person to go to.\"\nmsgstr \"\"\n\"凱恩​是​一​個​真正​的​朋友​和​智慧​的​聖人。他​擁​有​一​個​龐​大​的​圖書館，有​一​種​與生俱來​的​能\"\n\"力​來辨別​許​多​事物​的​本質。如果​你​有​任何​問題，他​就​是​你​要​找​的​人\"\n\n#: Source/translation_dummy.cpp:854\nmsgid \"\"\n\"Even my skills have been unable to fully heal Farnham. Oh, I have been able \"\n\"to mend his body, but his mind and spirit are beyond anything I can do.\"\nmsgstr \"\"\n\"就​連​我​的​技能​也​無法​完全​治癒法納姆。哦，我​已​經​能​修好​他​的​身體​了，但是​他​的​精神​和​\"\n\"精神​我​無​能​為力\"\n\n#: Source/translation_dummy.cpp:855\nmsgid \"\"\n\"While I use some limited forms of magic to create the potions and elixirs I \"\n\"store here, Adria is a true sorceress. She never seems to sleep, and she \"\n\"always has access to many mystic tomes and artifacts. I believe her hut may \"\n\"be much more than the hovel it appears to be, but I can never seem to get \"\n\"inside the place.\"\nmsgstr \"\"\n\"當​我​使用​一些​有限​的​魔法​來​創造​我​儲​存在​這裡​的​藥劑​和​長生不​老​藥時，阿德里亞​是​一​個​\"\n\"真正​的​女巫。她​似乎​從​不​睡覺，她​總​是​能​接觸​到​許多​神秘​的​大部頭​和​文物。我​相信​她​的​\"\n\"小屋​可能​比​看​上去​的​小屋​要​大​得​多，但​我​似乎​永遠​也​進​不​了​這個​地方\"\n\n#: Source/translation_dummy.cpp:856\nmsgid \"\"\n\"Poor Wirt. I did all that was possible for the child, but I know he despises \"\n\"that wooden peg that I was forced to attach to his leg. His wounds were \"\n\"hideous. No one - and especially such a young child - should have to suffer \"\n\"the way he did.\"\nmsgstr \"\"\n\"可​憐​的​懷特。我​為​那​孩子​做​了​一切​可能​的​事，但​我​知道​他​看​不​起​我​被迫綁​在​他​腿上​的​木\"\n\"釘。他​的​傷口​很​難​看。沒​有​人​——​尤其是​這麼​小​的​孩子​——​應該​像​他​那​樣​受​苦\"\n\n#: Source/translation_dummy.cpp:857\nmsgid \"\"\n\"I really don't understand why Ogden stays here in Tristram. He suffers from \"\n\"a slight nervous condition, but he is an intelligent and industrious man who \"\n\"would do very well wherever he went. I suppose it may be the fear of the \"\n\"many murders that happen in the surrounding countryside, or perhaps the \"\n\"wishes of his wife that keep him and his family where they are.\"\nmsgstr \"\"\n\"我​真​不​明白​奧格登​為什麼​留​在​特里斯特拉姆。他​有​點緊張，但​他​是​一​個​聰明​而​勤奮​的​\"\n\"人，無論​他​去​哪​裡​都​會​做​得​很​好。我​想​可能​是​因​為​害怕​周圍農​村​發生​的​許多​謀​殺案，也​\"\n\"可能​是​因​為​他​妻子​的​願望，他​和​他​的​家人​一直​呆​在​那​裡\"\n\n#: Source/translation_dummy.cpp:858\nmsgid \"\"\n\"Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers \"\n\"from delusions. \\n\"\n\" \\n\"\n\"She claims that they are visions, but I have no proof of that one way or the \"\n\"other.\"\nmsgstr \"\"\n\"奧​格登​的​酒吧​女​招待​是​個​可​愛​的​女孩。她​祖母​病​得​很​重，有​妄想癥。\\n\"\n\" \\n\"\n\"​她​聲稱​那​是​幻覺，但​我​沒​有​證據​證明這​一​點\"\n\n#: Source/translation_dummy.cpp:859\nmsgid \"Good day! How may I serve you?\"\nmsgstr \"很​好​的​一​天！我​能​為​您​效勞​嗎\"\n\n#: Source/translation_dummy.cpp:860\nmsgid \"\"\n\"My grandmother had a dream that you would come and talk to me. She has \"\n\"visions, you know and can see into the future.\"\nmsgstr \"我​祖母​夢​見​你​來​和​我​說話。她​有​遠見卓識，你​知道，而且​能​預見​未​來\"\n\n#: Source/translation_dummy.cpp:861\nmsgid \"\"\n\"The woman at the edge of town is a witch! She seems nice enough, and her \"\n\"name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n\"\n\" \\n\"\n\"It would take someone quite brave, like you, to see what she is doing out \"\n\"there.\"\nmsgstr \"\"\n\"鎮邊​的​那個​女人​是​個女​巫！她​看起來​很​好，她​的​名字​叫​艾德里亞，很​討人​喜歡，但​我​很​\"\n\"害怕​她。\\n\"\n\" \\n\"\n\"像​你​這樣​勇敢​的​人才​能​看到​她​在​外面​幹什麼\"\n\n#: Source/translation_dummy.cpp:862\nmsgid \"\"\n\"Our Blacksmith is a point of pride to the people of Tristram. Not only is he \"\n\"a master craftsman who has won many contests within his guild, but he \"\n\"received praises from our King Leoric himself - may his soul rest in peace. \"\n\"Griswold is also a great hero; just ask Cain.\"\nmsgstr \"\"\n\"我​們​的​鐵匠​是​特里斯特拉姆​人民​的​驕傲。他​不僅​是​一​個手藝大師，在​他​的​行會​中​贏​得了​\"\n\"許多​比賽，而且​他​還​得到​了​我​們國​王李奧瑞克​本人​的​讚揚​——​愿​他​的​靈魂​安息。格里斯沃​\"\n\"爾德​也​是​一​位​偉​大​的​英雄​；​問問​凱恩\"\n\n#: Source/translation_dummy.cpp:863\nmsgid \"\"\n\"Cain has been the storyteller of Tristram for as long as I can remember. He \"\n\"knows so much, and can tell you just about anything about almost everything.\"\nmsgstr \"\"\n\"從​我​記​事​起，凱恩​一直​是​崔斯特瑞姆​的​說書​人。他​知道​的​太​多​了，幾乎​什麼​都​能​告訴​你\"\n\n#: Source/translation_dummy.cpp:864\nmsgid \"\"\n\"Farnham is a drunkard who fills his belly with ale and everyone else's ears \"\n\"with nonsense. \\n\"\n\" \\n\"\n\"I know that both Pepin and Ogden feel sympathy for him, but I get so \"\n\"frustrated watching him slip farther and farther into a befuddled stupor \"\n\"every night.\"\nmsgstr \"\"\n\"法納姆​是​個​酒鬼，他​的​肚子​里​裝滿​了​啤酒，其他​人​的​耳朵​里​全​是​廢話。\\n\"\n\" \\n\"\n\"​我​知道​佩平​和​奧格登​都​同情​他，但​每​天​晚上​看​著​他​越​來​越​昏迷​不​醒，我​感到​非常​沮喪\"\n\n#: Source/translation_dummy.cpp:865\nmsgid \"\"\n\"Pepin saved my grandmother's life, and I know that I can never repay him for \"\n\"that. His ability to heal any sickness is more powerful than the mightiest \"\n\"sword and more mysterious than any spell you can name. If you ever are in \"\n\"need of healing, Pepin can help you.\"\nmsgstr \"\"\n\"佩平救​了​我​祖母​的​命，我​知道​我​永遠​也​報​答​不​了​他。他​治癒​任何​疾病​的​能力​比​最​強​大​的​\"\n\"劍​更​強​大，比​你​能​說出​的​任何​咒語​都​更​神秘。如果​你​需要​治療，Pepin​可以​幫助​你\"\n\n#: Source/translation_dummy.cpp:866\nmsgid \"\"\n\"I grew up with Wirt's mother, Canace. Although she was only slightly hurt \"\n\"when those hideous creatures stole him, she never recovered. I think she \"\n\"died of a broken heart. Wirt has become a mean-spirited youngster, looking \"\n\"only to profit from the sweat of others. I know that he suffered and has \"\n\"seen horrors that I cannot even imagine, but some of that darkness hangs \"\n\"over him still.\"\nmsgstr \"\"\n\"我​和​沃特​的​母親，加那斯​一起​長​大。雖然當​那些​可怕​的​生物​偷走​他​時，她​只​是​受到​了​輕\"\n\"微​的​傷害，但​她​始終沒​有​康復。我​想​她​死於​心碎。維特​成​了​一​個​小​氣鬼，只​想​從別​人​的​\"\n\"汗水​中​獲利。我​知道​他​受苦受難，經歷過​我​無法​想像​的​恐懼，但​他​身​上​仍然​籠罩​著​一些​\"\n\"黑暗\"\n\n#: Source/translation_dummy.cpp:867\nmsgid \"\"\n\"Ogden and his wife have taken me and my grandmother into their home and have \"\n\"even let me earn a few gold pieces by working at the inn. I owe so much to \"\n\"them, and hope one day to leave this place and help them start a grand hotel \"\n\"in the east.\"\nmsgstr \"\"\n\"奧​格登​和​他​的​妻子​把​我​和​我​的​祖母​帶​到​他​們家裡，甚至​讓​我​在​旅館​工作​掙​了​幾塊​金幣。\"\n\"我​欠​他​們​太​多​了，希望​有​一​天​離開​這個​地方，幫助​他​們​在​東方​開​一​家​大​酒店\"\n\n#: Source/translation_dummy.cpp:868\nmsgid \"Well, what can I do for ya?\"\nmsgstr \"我​能​為​你​做​些​什麼\"\n\n#: Source/translation_dummy.cpp:869\nmsgid \"\"\n\"If you're looking for a good weapon, let me show this to you. Take your \"\n\"basic blunt weapon, such as a mace. Works like a charm against most of those \"\n\"undying horrors down there, and there's nothing better to shatter skinny \"\n\"little skeletons!\"\nmsgstr \"\"\n\"如果​你​想​找​一​件​好​武器，讓​我​給​你​看看。帶上​你​最​基本​的​鈍器，比如​狼牙棒。像​一​個​魅\"\n\"力​對抗​那些​不朽​的​恐懼​在​那裡，沒​有​什麼​比​粉碎​瘦小​的​骨架​更​好\"\n\n#: Source/translation_dummy.cpp:870\nmsgid \"\"\n\"The axe? Aye, that's a good weapon, balanced against any foe. Look how it \"\n\"cleaves the air, and then imagine a nice fat demon head in its path. Keep in \"\n\"mind, however, that it is slow to swing - but talk about dealing a heavy \"\n\"blow!\"\nmsgstr \"\"\n\"斧頭？是​的，這​是​一​個​很​好​的​武器，可以​對付​任何​敵人。看看​它​是​如何​劈​開​空氣​的，然\"\n\"后​想像​一​個​漂亮​的​胖魔鬼​頭​在​它​的​路徑​上。但是，請記​住，搖擺​是​很​慢​的，但是​談論​如\"\n\"何​處理​一​個​沉重​的​打擊\"\n\n#: Source/translation_dummy.cpp:871\nmsgid \"\"\n\"Look at that edge, that balance. A sword in the right hands, and against the \"\n\"right foe, is the master of all weapons. Its keen blade finds little to hack \"\n\"or pierce on the undead, but against a living, breathing enemy, a sword will \"\n\"better slice their flesh!\"\nmsgstr \"\"\n\"看看​那​個​邊緣，那​個​平衡。右​手​中​的​劍，和​對​的​敵人，是​一切​武器​的​主人。它​銳利​的​刀\"\n\"鋒​在​不​死​生物​身上​幾乎​找​不​到​可​砍​或​可​刺​的​東西，但​對​於​一​個​活生生​的、會​呼吸​的​敵\"\n\"人，一​把​劍會​更​好​地​切開​他​們​的​肉\"\n\n#: Source/translation_dummy.cpp:872\nmsgid \"\"\n\"Your weapons and armor will show the signs of your struggles against the \"\n\"Darkness. If you bring them to me, with a bit of work and a hot forge, I can \"\n\"restore them to top fighting form.\"\nmsgstr \"\"\n\"你​的​武器​和​護甲將​顯示​你​與​黑暗​鬥爭​的​跡象。如果​你​把​它​們帶​到​我​這裡來，稍加​改造​和​\"\n\"熱鍛，我​就​能​把​它​們​恢復​到​最​佳​戰鬥狀態\"\n\n#: Source/translation_dummy.cpp:873\nmsgid \"\"\n\"While I have to practically smuggle in the metals and tools I need from \"\n\"caravans that skirt the edges of our damned town, that witch, Adria, always \"\n\"seems to get whatever she needs. If I knew even the smallest bit about how \"\n\"to harness magic as she did, I could make some truly incredible things.\"\nmsgstr \"\"\n\"當​我​不​得不​從​我​們​該死​的​小​鎮​邊緣​的​商隊​里​偷運​我​所​需要​的​金屬​和​工具時，那​個​女​巫艾\"\n\"德里亞​似乎​總​能​得到​她​所​需要​的​一切。如果​我​像​她​那​樣​懂得​如何​運用​魔法，我​就​能​做出​\"\n\"一些​真正​不​可思議​的​事情\"\n\n#: Source/translation_dummy.cpp:874\nmsgid \"\"\n\"Gillian is a nice lass. Shame that her gammer is in such poor health or I \"\n\"would arrange to get both of them out of here on one of the trading caravans.\"\nmsgstr \"\"\n\"阿嬌​是​個好​姑娘。可惜​她​的​男朋友​身體這​麼​差，否則​我​會​安排​他​們兩個​都​乘商隊離開這​\"\n\"里\"\n\n#: Source/translation_dummy.cpp:875\nmsgid \"\"\n\"Sometimes I think that Cain talks too much, but I guess that is his calling \"\n\"in life. If I could bend steel as well as he can bend your ear, I could make \"\n\"a suit of court plate good enough for an Emperor!\"\nmsgstr \"\"\n\"有​時​我​覺​得​凱恩說​得​太​多​了，但​我​想​這​是​他​一​生​的​使命。如果​我​能​像​他​能​彎曲​你​的​耳朵​\"\n\"一​樣​彎曲​鋼鐵，我​就​能​做​一​套足夠​好​的​皇帝​用​的​宮廷​盤子\"\n\n#: Source/translation_dummy.cpp:876\nmsgid \"\"\n\"I was with Farnham that night that Lazarus led us into Labyrinth. I never \"\n\"saw the Archbishop again, and I may not have survived if Farnham was not at \"\n\"my side. I fear that the attack left his soul as crippled as, well, another \"\n\"did my leg. I cannot fight this battle for him now, but I would if I could.\"\nmsgstr \"\"\n\"那​天​晚上​我​和​法納姆​在一起，拉撒路​把​我​們領進​了​迷宮。我​再​也​見​不​到​大主教​了，如果​\"\n\"法納姆​不​在​我​身邊，我​可能​就​活​不​下去​了。我​擔心​這次​襲擊​使​他​的​靈魂​像​另​一​次​襲擊​我​\"\n\"的​腿一樣​殘廢。我​現​在​不​能​為​他​而​戰，但​如果​可以​的​話​我​會​的\"\n\n#: Source/translation_dummy.cpp:877\nmsgid \"\"\n\"A good man who puts the needs of others above his own. You won't find anyone \"\n\"left in Tristram - or anywhere else for that matter - who has a bad thing to \"\n\"say about the healer.\"\nmsgstr \"\"\n\"把​別人​的​需要​放​在​自己​的​需要​之上​的​好​人。你​不​會​發現​任何​人​留​在​崔斯特瑞姆-​或​任何​其\"\n\"他​地方​的​問題​-​誰​有​一​個壞東​西說​的​治療者\"\n\n#: Source/translation_dummy.cpp:878\nmsgid \"\"\n\"That lad is going to get himself into serious trouble... or I guess I should \"\n\"say, again. I've tried to interest him in working here and learning an \"\n\"honest trade, but he prefers the high profits of dealing in goods of dubious \"\n\"origin. I cannot hold that against him after what happened to him, but I do \"\n\"wish he would at least be careful.\"\nmsgstr \"\"\n\"那​小子​會​惹​上​大麻煩​的。。。或者​我​想​我​應該​再​說​一​遍。我​試​著​讓​他​對​在​這裡​工作​和​學\"\n\"習​誠實​的​貿易感​興趣，但​他​更​喜歡經營​來源​可疑​的​貨物​的​高額利潤。我​不​能​在​他​出事​後​\"\n\"再​對​他​說這話，但​我​真​希望​他​至少​要​小心​點\"\n\n#: Source/translation_dummy.cpp:879\nmsgid \"\"\n\"The Innkeeper has little business and no real way of turning a profit. He \"\n\"manages to make ends meet by providing food and lodging for those who \"\n\"occasionally drift through the village, but they are as likely to sneak off \"\n\"into the night as they are to pay him. If it weren't for the stores of \"\n\"grains and dried meats he kept in his cellar, why, most of us would have \"\n\"starved during that first year when the entire countryside was overrun by \"\n\"demons.\"\nmsgstr \"\"\n\"客棧​老​闆沒​有​什麼​生意，也​沒​有​真正​的​盈利​途徑。他​設法維​持生計，為​那些​偶爾​在​村子​\"\n\"里​漂泊​的​人​提供​食物​和​住宿，但​他​們​很​可能​會​偷偷​溜進​夜空，就​像​他​們付錢給​他​一​樣。\"\n\"如果​不​是​因為​他​在​地窖里​儲存​了​大量​的​穀物​和​乾肉，為什麼，我​們​大多​數人會​在​第一​年​\"\n\"餓死，那​時​整​個​鄉​村​都​被​惡​魔蹂​躪\"\n\n#: Source/translation_dummy.cpp:880\nmsgid \"Can't a fella drink in peace?\"\nmsgstr \"一​個​人​不​能​安靜​地​喝​酒​嗎\"\n\n#: Source/translation_dummy.cpp:881\nmsgid \"\"\n\"The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\"\nmsgstr \"送​飲料​的​那個​女孩？哦，是​啊，多​漂亮​的​女人​啊。太​好​了\"\n\n#: Source/translation_dummy.cpp:882\nmsgid \"\"\n\"Why don't that old crone do somethin' for a change. Sure, sure, she's got \"\n\"stuff, but you listen to me... she's unnatural. I ain't never seen her eat \"\n\"or drink - and you can't trust somebody who doesn't drink at least a little.\"\nmsgstr \"\"\n\"為​什麼​那​個​老太​婆​不​改​變​一下。當然，當然，她​有​東西，但​你​聽​我​說。。。她​很​不​自\"\n\"然。我​從來沒見過​她​吃喝​——​你​也​不​能​相信​一​個​不​喝​酒​的​人\"\n\n#: Source/translation_dummy.cpp:883\nmsgid \"\"\n\"Cain isn't what he says he is. Sure, sure, he talks a good story... some of \"\n\"'em are real scary or funny... but I think he knows more than he knows he \"\n\"knows.\"\nmsgstr \"\"\n\"凱恩​不​是​他​說​的​那樣。當然，當然，他​講​了​一​個​好​故事。。。有些​真的​很​嚇人​或者​很​有\"\n\"趣。。。但​我​想​他​知道​的​比​他​知道​的​還​多\"\n\n#: Source/translation_dummy.cpp:884\nmsgid \"\"\n\"Griswold? Good old Griswold. I love him like a brother! We fought together, \"\n\"you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\"\nmsgstr \"\"\n\"格里斯沃​爾德？善良​的​老格里斯沃​爾德。我​像​兄弟​一​樣愛​他！我​們​一起​戰鬥，你​知道，\"\n\"當。。。我​們。。。拉撒路。。。拉撒路。。。拉撒​路\"\n\n#: Source/translation_dummy.cpp:885\nmsgid \"\"\n\"Hehehe, I like Pepin. He really tries, you know. Listen here, you should \"\n\"make sure you get to know him. Good fella like that with people always \"\n\"wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a \"\n\"hero too...\"\nmsgstr \"\"\n\"呵呵，我​喜歡佩平。他​真的​很​努力，你​知道​的。聽著，你​應該​瞭解​他。像​這樣​的​好​人總​\"\n\"是​有​人​想​幫​忙。嘿，我​想​那​會​有​點像​你，英雄？我​也​是​個​英雄\"\n\n#: Source/translation_dummy.cpp:886\nmsgid \"\"\n\"Wirt is a kid with more problems than even me, and I know all about \"\n\"problems. Listen here - that kid is gotta sweet deal, but he's been there, \"\n\"you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\"\nmsgstr \"\"\n\"維特​是​個問題​比​我​還​多​的​孩子，我​知道​所有​的​問題。聽著​-​那​孩子​一定​是​個好​人，但​他​去​\"\n\"過​那​裡，你​知道​嗎？丟​了​一​條腿！得​在​一​塊木頭​上​走​來​走​去。太​傷心​了，太​傷心​了\"\n\n#: Source/translation_dummy.cpp:887\nmsgid \"\"\n\"Ogden is the best man in town. I don't think his wife likes me much, but as \"\n\"long as she keeps tappin' kegs, I'll like her just fine. Seems like I been \"\n\"spendin' more time with Ogden than most, but he's so good to me...\"\nmsgstr \"\"\n\"奧​格登​是​鎮​上​最​好​的​男人。我​覺​得​他​妻子​不​太​喜歡​我，但​只要​她​不​停​地​敲桶，我​就​很​喜\"\n\"歡​她。似乎​我​和​奧格登​在一起​的​時間​比​大多​數​人​都​多，但​他​對​我​很​好\"\n\n#: Source/translation_dummy.cpp:888\nmsgid \"\"\n\"I wanna tell ya sumthin', 'cause I know all about this stuff. It's my \"\n\"specialty. This here is the best... theeeee best! That other ale ain't no \"\n\"good since those stupid dogs...\"\nmsgstr \"\"\n\"我​想​告訴​你，因​為​我​知道​這​一切。這​是​我​的​專長。這​是​最​好​的。。。最​好​的！其他​的​啤\"\n\"酒​不​好，因​為​那些​蠢​狗\"\n\n#: Source/translation_dummy.cpp:889\nmsgid \"\"\n\"No one ever lis... listens to me. Somewhere - I ain't too sure - but \"\n\"somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and \"\n\"just waitin' for someone to get it.\"\nmsgstr \"\"\n\"從​來沒​有​人。。。聽​我​說。在​某​個​地方​-​我​不​太​確定​-​但是​在​教堂​下面​的​某​個​地方​有​一​堆​\"\n\"金子。閃閃​發光，只是​等待​有​人​得到​它\"\n\n#: Source/translation_dummy.cpp:890\nmsgid \"\"\n\"I know you gots your own ideas, and I know you're not gonna believe this, \"\n\"but that weapon you got there - it just ain't no good against those big \"\n\"brutes! Oh, I don't care what Griswold says, they can't make anything like \"\n\"they used to in the old days...\"\nmsgstr \"\"\n\"我​知道​你​有​自己​的​想法，我​知道​你​不​會​相信​的，但​你​的​武器，你​在​那​裡​-​它​只​是​不​好​對付​\"\n\"那些​大​畜生！哦，我​不管​格里斯沃​爾德​怎​麼說，他​們​不​能​像​以前​那​樣​做​任何​東西\"\n\n#: Source/translation_dummy.cpp:891\nmsgid \"\"\n\"If I was you... and I ain't... but if I was, I'd sell all that stuff you got \"\n\"and get out of here. That boy out there... He's always got somethin' good, \"\n\"but you gotta give him some gold or he won't even show you what he's got.\"\nmsgstr \"\"\n\"如果​我​是​你。。。我​不​是。。。但​如果​我​是，我​會​賣掉​你​所有​的​東西然​後​離開​這裡。外\"\n\"面​那​個​男孩。。。他​總​是​有​好​東西，但​你​得給​他​點金子，否則​他​連​他​的​東西​都​不​給​你​看\"\n\n#: Source/translation_dummy.cpp:892\nmsgid \"I sense a soul in search of answers...\"\nmsgstr \"我​感覺​到​一​個​靈魂​在​尋​找​答案\"\n\n#: Source/translation_dummy.cpp:893\nmsgid \"\"\n\"Wisdom is earned, not given. If you discover a tome of knowledge, devour its \"\n\"words. Should you already have knowledge of the arcane mysteries scribed \"\n\"within a book, remember - that level of mastery can always increase.\"\nmsgstr \"\"\n\"智慧​是​應得​的，而​不​是​給予​的。如果​你​發現​了​一​本​知識​的​大部頭，就​要​吞沒​它​的​文字。\"\n\"如果​你​已​經​掌握​了​書中​描述​的​神秘​事物​的​知識，記住​-​掌握​的​水平​總​是​可以​提高​的\"\n\n#: Source/translation_dummy.cpp:894\nmsgid \"\"\n\"The greatest power is often the shortest lived. You may find ancient words \"\n\"of power written upon scrolls of parchment. The strength of these scrolls \"\n\"lies in the ability of either apprentice or adept to cast them with equal \"\n\"ability. Their weakness is that they must first be read aloud and can never \"\n\"be kept at the ready in your mind. Know also that these scrolls can be read \"\n\"but once, so use them with care.\"\nmsgstr \"\"\n\"最​強​大​的​力量​往往​是​最​短命​的。你​可以​在​羊皮紙​的​卷軸​上​找到​古老​的​權力​話語。這​些​卷\"\n\"軸​的​力量​在​於​學徒​或​熟練​的​施展​能力。他​們​的​弱點​是，他​們必​須​首先​大聲朗讀，永遠​不​\"\n\"能​隨時​準備​在​你​的​腦海​中。還​要​知道​這​些​卷軸​只​能​讀​一​次，所以​要​小心​使用\"\n\n#: Source/translation_dummy.cpp:895\nmsgid \"\"\n\"Though the heat of the sun is beyond measure, the mere flame of a candle is \"\n\"of greater danger. No energies, no matter how great, can be used without the \"\n\"proper focus. For many spells, ensorcelled Staves may be charged with \"\n\"magical energies many times over. I have the ability to restore their power \"\n\"- but know that nothing is done without a price.\"\nmsgstr \"\"\n\"儘​管​太​陽​的​熱量​無​法​估量，但​光是​蠟燭​的​火焰​就​更​危險。沒​有​適當​的​聚焦，任何​能量，\"\n\"無論​多​大，都​不​能​被​使用。對於​許​多​咒​語來說，被​賦予​靈能​的​杖​可以​被​多​次​充滿​魔法​能\"\n\"量。我​有​能力​恢復​他​們​的​力量，但​我​知道​沒​有​代價​是​做​不​到​的\"\n\n#: Source/translation_dummy.cpp:896\nmsgid \"\"\n\"The sum of our knowledge is in the sum of its people. Should you find a book \"\n\"or scroll that you cannot decipher, do not hesitate to bring it to me. If I \"\n\"can make sense of it I will share what I find.\"\nmsgstr \"\"\n\"我​們​知識​的​總​和​就​是​它​的​人民​的​總和。如果​你​發現​一​本​書​或​卷軸，你​不​能​破譯，不​要​猶\"\n\"豫，把​它​給​我。如果​我​能​理解​的​話，我​會​分享​我​的​發現\"\n\n#: Source/translation_dummy.cpp:897\nmsgid \"\"\n\"To a man who only knows Iron, there is no greater magic than Steel. The \"\n\"blacksmith Griswold is more of a sorcerer than he knows. His ability to meld \"\n\"fire and metal is unequaled in this land.\"\nmsgstr \"\"\n\"對​一​個​只​懂​鋼鐵​的​人​來說，沒​有​什麼​比鋼鐵​更​神奇​了。鐵匠​格里斯沃​爾德比​他​所​知道​的​\"\n\"更​像​個​巫師。他​融火​與金屬​的​能力​在​這片​土地​上​是​無與倫​比​的\"\n\n#: Source/translation_dummy.cpp:898\nmsgid \"\"\n\"Corruption has the strength of deceit, but innocence holds the power of \"\n\"purity. The young woman Gillian has a pure heart, placing the needs of her \"\n\"matriarch over her own. She fears me, but it is only because she does not \"\n\"understand me.\"\nmsgstr \"\"\n\"腐敗​有​欺騙​的​力量，而​清白​有​純潔​的​力量。年輕​的​阿嬌​有​一​顆​純潔​的​心，把​女​家長​的​需\"\n\"要​凌駕于​自己​的​需要​之上。她​害怕​我，但​那​只​是​因為​她​不​瞭解​我\"\n\n#: Source/translation_dummy.cpp:899\nmsgid \"\"\n\"A chest opened in darkness holds no greater treasure than when it is opened \"\n\"in the light. The storyteller Cain is an enigma, but only to those who do \"\n\"not look. His knowledge of what lies beneath the cathedral is far greater \"\n\"than even he allows himself to realize.\"\nmsgstr \"\"\n\"在​黑暗中​打開​的​箱子​所​裝​的​財寶，並​不​比​在​光明​中​打開​的​箱子​更​大。講​故事​的​凱恩​是​一​\"\n\"個謎，但​只有​那些​誰​不​看。他​對大​教堂​下面​的​東西​的​瞭解遠遠​超過​了​他​自己​的​想像\"\n\n#: Source/translation_dummy.cpp:900\nmsgid \"\"\n\"The higher you place your faith in one man, the farther it has to fall. \"\n\"Farnham has lost his soul, but not to any demon. It was lost when he saw his \"\n\"fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to \"\n\"be gleaned, but you must separate fact from fantasy.\"\nmsgstr \"\"\n\"你​對​一​個​人​的​信心​越​高，他​就​越​會​墮​落。法納姆​已​經​失去​了​他​的​靈魂，但​不​是​任何​惡\"\n\"魔。當​他​看到​他​的​同鄉們​被​拉撒路​大​主教​出賣時，他​失去​了​理智。他​有​知識​可以​收集，\"\n\"但​你​必須​把​事實​和​幻想分開\"\n\n#: Source/translation_dummy.cpp:901\nmsgid \"\"\n\"The hand, the heart and the mind can perform miracles when they are in \"\n\"perfect harmony. The healer Pepin sees into the body in a way that even I \"\n\"cannot. His ability to restore the sick and injured is magnified by his \"\n\"understanding of the creation of elixirs and potions. He is as great an ally \"\n\"as you have in Tristram.\"\nmsgstr \"\"\n\"手、心​和心​在​完美​的​和​諧​中​就​能​創造奇蹟。治療者​佩平​以​一​種連​我​都​看​不​到​的​方式​觀察\"\n\"身體。他​對​長生不​老藥​和​藥水​的​理解​使​他​恢復​病人​和​傷者​的​能力​得到​了​放大。他​和​你​在​\"\n\"特里斯特拉姆​一樣​是​個偉​大​的​盟友\"\n\n#: Source/translation_dummy.cpp:902\nmsgid \"\"\n\"There is much about the future we cannot see, but when it comes it will be \"\n\"the children who wield it. The boy Wirt has a blackness upon his soul, but \"\n\"he poses no threat to the town or its people. His secretive dealings with \"\n\"the urchins and unspoken guilds of nearby towns gain him access to many \"\n\"devices that cannot be easily found in Tristram. While his methods may be \"\n\"reproachful, Wirt can provide assistance for your battle against the \"\n\"encroaching Darkness.\"\nmsgstr \"\"\n\"未​來​有​很多​我​們​看​不​到​的，但​當​它​來臨時，將​是​孩子​們​掌握​著​它。這個​男孩​的​靈魂​是​黑\"\n\"暗​的，但​他​對這​個城鎮​和​它​的​人民​沒​有​威脅。他​與​附近​城鎮​的​頑童​和​不​為​人​知​的​行會​的​\"\n\"秘密​交易​使​他​能​夠​接觸​到​許多​在​特里斯特拉姆​很​難​找到​的​裝置。雖然​他​的​方法​可能​會​受\"\n\"到​指責，但​Wirt​可以​為​你​對抗​日益​逼近​的​黑暗​提供​幫助\"\n\n#: Source/translation_dummy.cpp:903\nmsgid \"\"\n\"Earthen walls and thatched canopy do not a home create. The innkeeper Ogden \"\n\"serves more of a purpose in this town than many understand. He provides \"\n\"shelter for Gillian and her matriarch, maintains what life Farnham has left \"\n\"to him, and provides an anchor for all who are left in the town to what \"\n\"Tristram once was. His tavern, and the simple pleasures that can still be \"\n\"found there, provide a glimpse of a life that the people here remember. It \"\n\"is that memory that continues to feed their hopes for your success.\"\nmsgstr \"\"\n\"土墻​和​茅草屋​頂​不​是​一​個​家。旅館​老​闆​奧​格登​在​這個鎮​上​的​作用​比​許​多​人​所​理解​的​要​大​\"\n\"得​多。他​為​阿嬌​和​她​的​女族長​提供​庇護所，維持​法納姆留給​他​的​生活，併爲​留​在​鎮上​的​\"\n\"所有人​提供​一​個錨，讓​他​們​回到​特里斯特拉姆​曾經​的​樣子。他​的​小酒館，以及​在​那裡​仍\"\n\"然​可以​找到​的​簡單​的​樂趣，讓​我​們​看到​了​這裡​的​人們​所​記得​的​生活。正​是​這段​記憶，讓​\"\n\"他​們對​你​的​成功​充滿​了​希望\"\n\n#: Source/translation_dummy.cpp:904\nmsgid \"Pssst... over here...\"\nmsgstr \"PSST。。。在​這裡\"\n\n#: Source/translation_dummy.cpp:905\nmsgid \"\"\n\"Not everyone in Tristram has a use - or a market - for everything you will \"\n\"find in the labyrinth. Not even me, as hard as that is to believe. \\n\"\n\" \\n\"\n\"Sometimes, only you will be able to find a purpose for some things.\"\nmsgstr \"\"\n\"並​不​是​所有​在​特里斯特拉姆​的​人​都​有​一​個​用途​-​或​市場​-​你​會發現​在​迷宮​中​的​一切。連​我​\"\n\"都​不​相信。\\n\"\n\" \\n\"\n\"​有​時候，只有​你​才​能​為​某些​事情​找到​目標\"\n\n#: Source/translation_dummy.cpp:906\nmsgid \"\"\n\"Don't trust everything the drunk says. Too many ales have fogged his vision \"\n\"and his good sense.\"\nmsgstr \"別​相信​醉漢說​的​每​一​句​話。太​多​的​啤酒​模糊​了​他​的​視力​和​判斷力\"\n\n#: Source/translation_dummy.cpp:907\nmsgid \"\"\n\"In case you haven't noticed, I don't buy anything from Tristram. I am an \"\n\"importer of quality goods. If you want to peddle junk, you'll have to see \"\n\"Griswold, Pepin or that witch, Adria. I'm sure that they will snap up \"\n\"whatever you can bring them...\"\nmsgstr \"\"\n\"如果​你​沒​注意​到，我​不​會從​崔斯特瑞買​任何​東西。我​是​一​個​進口​優質​商品​的​進口商。如\"\n\"果​你​想​兜售​垃圾，你​得​去​看看​格里斯沃​爾德，佩平​或​那個女巫，阿德里亞。我​相信​他​們\"\n\"會​搶購​你​能​帶給​他​們​的​任何​東西\"\n\n#: Source/translation_dummy.cpp:908\nmsgid \"\"\n\"I guess I owe the blacksmith my life - what there is of it. Sure, Griswold \"\n\"offered me an apprenticeship at the smithy, and he is a nice enough guy, but \"\n\"I'll never get enough money to... well, let's just say that I have definite \"\n\"plans that require a large amount of gold.\"\nmsgstr \"\"\n\"我​想​我​欠鐵匠​一​條命​——​這​是​怎麼​回​事。當然，格里斯沃​爾德讓​我​在​鐵匠​鋪當​學徒，他​是​\"\n\"個​很​好​的​人，但​我​永遠​拿​不​到​足夠​的​錢。。。好​吧，就​說​我​有​明確​的​計劃，需要​大量​的​\"\n\"黃​金\"\n\n#: Source/translation_dummy.cpp:909\nmsgid \"\"\n\"If I were a few years older, I would shower her with whatever riches I could \"\n\"muster, and let me assure you I can get my hands on some very nice stuff. \"\n\"Gillian is a beautiful girl who should get out of Tristram as soon as it is \"\n\"safe. Hmmm... maybe I'll take her with me when I go...\"\nmsgstr \"\"\n\"如果​我​再​大​幾歲，我​會盡​我​所​能給​她​帶來​財富，讓​我​向​你​保證，我​可以​得到​一些​非常​好​\"\n\"的​東西。阿嬌​是​一​個​美麗​的​女孩，她​應該​儘​快離​開​特里斯特拉姆，只要​它​是​安全​的。六​\"\n\"羥​甲​基​三​聚氰​胺六甲醚。。。也​許​我​去​的​時候會帶​她​一起​去\"\n\n#: Source/translation_dummy.cpp:910\nmsgid \"\"\n\"Cain knows too much. He scares the life out of me - even more than that \"\n\"woman across the river. He keeps telling me about how lucky I am to be \"\n\"alive, and how my story is foretold in legend. I think he's off his crock.\"\nmsgstr \"\"\n\"凱恩​知道​的​太​多​了。他​把​我​嚇死​了，甚至​比河對岸​的​那​個​女人​還​可怕。他​不​停​地​告訴​\"\n\"我，我​活​著​是​多麼幸運，我​的​故事​是​如何​在​傳說​中​被​預言​的。我​想​他​是​瘋​了\"\n\n#: Source/translation_dummy.cpp:911\nmsgid \"\"\n\"Farnham - now there is a man with serious problems, and I know all about how \"\n\"serious problems can be. He trusted too much in the integrity of one man, \"\n\"and Lazarus led him into the very jaws of death. Oh, I know what it's like \"\n\"down there, so don't even start telling me about your plans to destroy the \"\n\"evil that dwells in that Labyrinth. Just watch your legs...\"\nmsgstr \"\"\n\"法​納姆-現​在​有​一​個​男人​有​嚴重​的​問題，我​知道​所有​的​嚴重​問題​可以。他​過於​相信​一​個​人​\"\n\"的​正直，拉撒路​就​把​他​帶進​了​死亡​的​深淵。哦，我​知道​下面​是​什麼樣​的，所以​別告訴​我​\"\n\"你​打算​消滅迷宮裡​的​惡魔。小心​你​的​腿\"\n\n#: Source/translation_dummy.cpp:912\nmsgid \"\"\n\"As long as you don't need anything reattached, old Pepin is as good as they \"\n\"come. \\n\"\n\" \\n\"\n\"If I'd have had some of those potions he brews, I might still have my leg...\"\nmsgstr \"\"\n\"只要​你​不​需要​任何​東西​復位，老佩平​是​一​樣​好，他​們來​了。\\n\"\n\" \\n\"\n\"​如果​我​有​一些​他​釀造​的​藥水，我​可能​還​有​腿\"\n\n#: Source/translation_dummy.cpp:913\nmsgid \"\"\n\"Adria truly bothers me. Sure, Cain is creepy in what he can tell you about \"\n\"the past, but that witch can see into your past. She always has some way to \"\n\"get whatever she needs, too. Adria gets her hands on more merchandise than \"\n\"I've seen pass through the gates of the King's Bazaar during High Festival.\"\nmsgstr \"\"\n\"阿德里亞​真​讓​我​煩惱。當然，凱恩對​你​說​的​關於​過去​的​事​是​令​人​毛骨悚然​的，但​那​個​女​\"\n\"巫能​看​透​你​的​過去。她​也​總​有​辦法​得到​她​需要​的​東西。阿德里婭​拿到​的​商品​比​我​在​節​日\"\n\"期​間​穿過國​王集市​的​大門​看到​的​還​要​多\"\n\n#: Source/translation_dummy.cpp:914\nmsgid \"\"\n\"Ogden is a fool for staying here. I could get him out of town for a very \"\n\"reasonable price, but he insists on trying to make a go of it with that \"\n\"stupid tavern. I guess at the least he gives Gillian a place to work, and \"\n\"his wife Garda does make a superb Shepherd's pie...\"\nmsgstr \"\"\n\"奧​格登呆​在​這裡​真​是​個​傻瓜。我​可以​以​一​個​非常​合理​的​價格​把​他​弄​到​城外​去，但​他​堅持​\"\n\"要​和​那家​愚蠢​的​酒館​混過​去。我​想​至少​他​給​了​阿嬌​一​個​工作​的​地方，他​的​妻子​嘉達​做​了​\"\n\"一​個​很​棒​的​牧羊派\"\n\n#: Source/translation_dummy.cpp:915\nmsgid \"\"\n\"Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any \"\n\"who would seek to steal the treasures secured within this room. So speaks \"\n\"the Lord of Terror, and so it is written.\"\nmsgstr \"\"\n\"英雄​殿後​是​藏骨密室。永恒​的​死亡​等待​著​任何​想要​偷​走​這間​屋子​裡珍寶​的​人。恐懼​之​王​\"\n\"如此​說，經​上​如此​記​著\"\n\n#: Source/translation_dummy.cpp:916\nmsgid \"\"\n\"...and so, locked beyond the Gateway of Blood and past the Hall of Fire, \"\n\"Valor awaits for the Hero of Light to awaken...\"\nmsgstr \"…​…​所以，在​血​之門​的​外面，在​火之殿​的​前面，勇敢​的​等待​著光​之​英雄​的​覺醒\"\n\n#: Source/translation_dummy.cpp:917\nmsgid \"\"\n\"I can see what you see not.\\n\"\n\"Vision milky then eyes rot.\\n\"\n\"When you turn they will be gone,\\n\"\n\"Whispering their hidden song.\\n\"\n\"Then you see what cannot be,\\n\"\n\"Shadows move where light should be.\\n\"\n\"Out of darkness, out of mind,\\n\"\n\"Cast down into the Halls of the Blind.\"\nmsgstr \"\"\n\"我​能​看到​你​看​不​到​的​東西。\\n\"\n\"​視力​乳白色，然​後​眼睛​腐爛。\\n\"\n\"當​你​轉​過身，他​們​就​不​見​了，\\n\"\n\"​低​語​著​他​們​隱藏​的​歌聲。\\n\"\n\"然​後​你​看到​什麼​是​不​可能​的，\\n\"\n\"​陰影​在​光線應該​在​的​地方​移動。\\n\"\n\"​走出​黑暗，走出​心靈，\\n\"\n\"​扔​到​盲人​的​大廳​里\"\n\n#: Source/translation_dummy.cpp:918\nmsgid \"\"\n\"The armories of Hell are home to the Warlord of Blood. In his wake lay the \"\n\"mutilated bodies of thousands. Angels and men alike have been cut down to \"\n\"fulfill his endless sacrifices to the Dark ones who scream for one thing - \"\n\"blood.\"\nmsgstr \"\"\n\"地獄​的​軍械庫​是​血​之​軍閥​的​家。他​身​後​躺著​成千上​萬具殘缺​的​屍體。天使​和​人類​都​被​砍\"\n\"掉​了，來​完成​他​對​黑暗​勢力無盡​的​犧牲，他​們​只​為​一​件​事​而​尖叫​——​鮮​血\"\n\n#: Source/translation_dummy.cpp:919\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. There is a war that rages on even now, beyond \"\n\"the fields that we know - between the utopian kingdoms of the High Heavens \"\n\"and the chaotic pits of the Burning Hells. This war is known as the Great \"\n\"Conflict, and it has raged and burned longer than any of the stars in the \"\n\"sky. Neither side ever gains sway for long as the forces of Light and \"\n\"Darkness constantly vie for control over all creation.\"\nmsgstr \"\"\n\"注意​並見​證這裡​的​真理，因​為​它​們​是​赫拉迪姆​最後​的​遺產。甚至​在​現在，在​我​們​所​知​的​\"\n\"領域​之外，在​天堂​的​烏托邦王國​和​燃燒​地獄​的​混亂​深​淵​之​間，仍​有​一​場​戰爭​在​肆虐。這\"\n\"場戰爭​被​稱為​大​沖突，它​的​肆虐​和​燃燒時間​比​天空​中​任何​一​顆​星星​都​要​長。只要​光明​和​\"\n\"黑暗​的​力量​不​斷爭奪對​所有​造物​的​控制​權，任何​一​方​都​不​會獲​得​支​配權\"\n\n#: Source/translation_dummy.cpp:920\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. When the Eternal Conflict between the High \"\n\"Heavens and the Burning Hells falls upon mortal soil, it is called the Sin \"\n\"War. Angels and Demons walk amongst humanity in disguise, fighting in \"\n\"secret, away from the prying eyes of mortals. Some daring, powerful mortals \"\n\"have even allied themselves with either side, and helped to dictate the \"\n\"course of the Sin War.\"\nmsgstr \"\"\n\"注意​並見​證這裡​的​真理，因​為​它​們​是​赫拉迪姆​最後​的​遺產。當天堂​和​地獄​之​間​永恒​的​沖​\"\n\"突落​在​凡人​的​土地​上，這​就​是​原罪之戰。天使​和​惡魔偽​裝​著​行走​在​人類​之​中，秘密​地​戰\"\n\"鬥，遠離​凡​人​窺探​的​眼睛。一些​勇敢、強大​的​凡人​甚至​與​任何​一​方​結盟，並幫助​指揮罪\"\n\"惡​戰爭​的​程序\"\n\n#: Source/translation_dummy.cpp:921\nmsgid \"\"\n\"Take heed and bear witness to the truths that lie herein, for they are the \"\n\"last legacy of the Horadrim. Nearly three hundred years ago, it came to be \"\n\"known that the Three Prime Evils of the Burning Hells had mysteriously come \"\n\"to our world. The Three Brothers ravaged the lands of the east for decades, \"\n\"while humanity was left trembling in their wake. Our Order - the Horadrim - \"\n\"was founded by a group of secretive magi to hunt down and capture the Three \"\n\"Evils once and for all.\\n\"\n\" \\n\"\n\"The original Horadrim captured two of the Three within powerful artifacts \"\n\"known as Soulstones and buried them deep beneath the desolate eastern sands. \"\n\"The third Evil escaped capture and fled to the west with many of the \"\n\"Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - \"\n\"was eventually captured, his essence set in a Soulstone and buried within \"\n\"this Labyrinth.\\n\"\n\" \\n\"\n\"Be warned that the soulstone must be kept from discovery by those not of the \"\n\"faith. If Diablo were to be released, he would seek a body that is easily \"\n\"controlled as he would be very weak - perhaps that of an old man or a child.\"\nmsgstr \"\"\n\"注意​並見​證這裡​的​真理，因​為​它​們​是​赫拉迪姆​最後​的​遺產。近​三百​年​前，人們​知道​燃燒​\"\n\"地獄​的​三​大​惡魔​神秘​地來​到​了​我​們​的​世界。兄弟​三​人​蹂躪​東方​的​土地​數​十​年，而​人類卻​\"\n\"在​他​們身​後​戰慄。我​們​的​騎士團​——​赫拉迪姆​——​是​由​一​群​神秘​的​法師​建立​的，目的​是​一​勞​\"\n\"永逸​地​追捕​和​俘虜​這​三​個​惡魔。\\n\"\n\" \\n\"\n\"​最初​的​赫拉德里姆​在​被​稱為​「​靈魂石​」​的​強大​文物​中​捕獲​了​其中​兩個，並將​它​們​深​埋​在​\"\n\"荒涼​的​東部​沙漠​之下。第三​個​惡​魔逃脫​了​追捕，逃到​了​西部，許多赫拉迪姆人​都​在​追\"\n\"捕。第三​個​惡​魔-​被​稱為迪亞波羅，恐懼​之​王-​最​終​被​俘虜，他​的​靈魂石​和​埋​在​這個​迷宮​\"\n\"的​本質。\\n\"\n\" \\n\"\n\"​要​被​警告，靈魂​之石必須​防止​被​那些​不​信​的​人​發現。如果​迪亞波羅​被​釋放，他​會尋​找​一​\"\n\"個身體​很​容易​控制，因​為​他​會​非常​虛弱​-​也​許​是​一​個​老人​或​兒童\"\n\n#: Source/translation_dummy.cpp:922\nmsgid \"\"\n\"So it came to be that there was a great revolution within the Burning Hells \"\n\"known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils \"\n\"and banished their spirit forms to the mortal realm. The demons Belial (the \"\n\"Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of \"\n\"Hell during the absence of the Three Brothers. All of Hell polarized between \"\n\"the factions of Belial and Azmodan while the forces of the High Heavens \"\n\"continually battered upon the very Gates of Hell.\"\nmsgstr \"\"\n\"因此，在​燃燒​的​地獄裡​發生​了​一​場​被​稱為​黑暗​放逐​的​偉大​革命。較​小​的​邪惡​推翻​了​三​個​\"\n\"主要​的​邪惡，並將​他​們​的​精神​形式​放逐​到​凡人​的​領域。惡魔彼​列​爾​（​謊言之​王​）​和​阿茲\"\n\"莫丹​（​罪惡​之​王​）​在​兄弟​三​人​不​在​的​時候爭奪​地獄​的​統治權。所有​的​地獄惡​魔​都​在​彼列\"\n\"爾​和​阿茲​莫丹兩​個​派系​之​間​分化，而​天堂​的​力量​不​斷​地衝擊​著​地獄​的​大門。\"\n\n#: Source/translation_dummy.cpp:923\nmsgid \"\"\n\"Many demons traveled to the mortal realm in search of the Three Brothers. \"\n\"These demons were followed to the mortal plane by Angels who hunted them \"\n\"throughout the vast cities of the East. The Angels allied themselves with a \"\n\"secretive Order of mortal magi named the Horadrim, who quickly became adept \"\n\"at hunting demons. They also made many dark enemies in the underworlds.\"\nmsgstr \"\"\n\"許​多​惡​魔爲​了​尋​找​三​兄弟​來​到​了​凡間。這​些​惡魔​被​天使​們帶​到​了​凡間，他​們​在​東方​的​廣\"\n\"大​城市​裡獵殺​他​們。天使​們與​一​個​隱秘​的​名為​赫拉迪姆法師​教團​結盟，他​很​快​就​變​得​善\"\n\"于​獵殺​惡魔。他​們​也​在​陰間​製造​了​許多​黑暗​的​敵人。\"\n\n#: Source/translation_dummy.cpp:924\nmsgid \"\"\n\"So it came to be that the Three Prime Evils were banished in spirit form to \"\n\"the mortal realm and after sewing chaos across the East for decades, they \"\n\"were hunted down by the cursed Order of the mortal Horadrim. The Horadrim \"\n\"used artifacts called Soulstones to contain the essence of Mephisto, the \"\n\"Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest \"\n\"brother - Diablo, the Lord of Terror - escaped to the west.\\n\"\n\" \\n\"\n\"Eventually the Horadrim captured Diablo within a Soulstone as well, and \"\n\"buried him under an ancient, forgotten Cathedral. There, the Lord of Terror \"\n\"sleeps and awaits the time of his rebirth. Know ye that he will seek a body \"\n\"of youth and power to possess - one that is innocent and easily controlled. \"\n\"He will then arise to free his Brothers and once more fan the flames of the \"\n\"Sin War...\"\nmsgstr \"\"\n\"因此，這​三​個​主要​的​惡魔​以​靈魂​的​形式​被​放逐​到​凡人​的​領域，在​東方縫​了​幾​十​年​的​混亂​\"\n\"之後，他​們​被​凡人​赫拉迪姆​的​詛咒​的​秩序​所​追捕。赫拉德里姆​使用​了​被​稱為​「​靈魂石​」​\"\n\"的​人工​製品來容納​仇恨​之​主​墨菲斯托​和​他​的​兄弟​毀滅​之​主巴力​的​精髓。最​小​的​弟弟​——​恐\"\n\"懼​之​王迪亞波羅​——​逃到​了​西方。\\n\"\n\" \\n\"\n\"​最​終，赫拉德里姆​也​在​一​塊​靈魂石​中​俘獲​了​迪亞波羅，並將​他​埋葬​在​一​座​被​遺忘​的​古老\"\n\"大​教堂​下。在​那裡，恐怖​之​主​沉​睡​著，等待​著​他​的​重生。你​們​要​知道，他​要​尋求​一​個​充\"\n\"滿​青春​和​力量​的​身體來佔​有，一​個​清白​和​容易​控制​的​身體。然後​他​會起​來​解救​他​的​兄弟\"\n\"們，再​一​次​煽起罪惡戰爭​的​火焰\"\n\n#: Source/translation_dummy.cpp:925\nmsgid \"\"\n\"All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When \"\n\"he awakened from his long slumber, my Lord and Master spoke to me of secrets \"\n\"that few mortals know. He told me the kingdoms of the High Heavens and the \"\n\"pits of the Burning Hells engage in an eternal war. He revealed the powers \"\n\"that have brought this discord to the realms of man. My lord has named the \"\n\"battle for this world and all who exist here the Sin War.\"\nmsgstr \"\"\n\"所有​讚揚​迪亞波羅​-​恐懼​之​王​和​黑暗​流放​的​倖​存者。當​他​從​沉睡​中​醒來時，我​的​主人​和​主\"\n\"人​對​我​說​了​一些​很​少​有​人​知道​的​秘密。他​告訴​我，天​上​的​王國​和​燃燒​的​地獄​的​深坑​正在​\"\n\"進行​一​場​永恒​的​戰爭。他​揭示​了​將這種​不和​諧帶​到​人類​領域​的​力量。我​主​已​將這場為​世\"\n\"界​而​戰​的​戰爭​和​所有​在​這裡​生存​的​人​命名​為原罪之戰。\"\n\n#: Source/translation_dummy.cpp:926\nmsgid \"\"\n\"Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My \"\n\"Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished \"\n\"to this world long ago. My Lord wishes to bide his time and harness his \"\n\"awesome power so that he may free his captive brothers from their tombs \"\n\"beneath the sands of the east. Once my Lord releases his Brothers, the Sin \"\n\"War will once again know the fury of the Three.\"\nmsgstr \"\"\n\"榮耀​和​讚許​給​迪亞波羅​-​恐懼​之​王​和​三​人​之​首。我​主對​我​談​到​他​的​兩個​兄弟，墨菲斯托​和​\"\n\"巴爾，他​們​很​久​以前​被​放逐​到​這個​世界​上。我​的​主​希望​等待​時機，利用​他​令​人​敬畏​的​能\"\n\"力，以便​將​他​被​俘​的​兄弟​們從​東方​沙漠​下​的​墳​墓​中​解救​出來。一旦​我​主釋放​了​他​的​兄\"\n\"弟，原罪​之​戰將​再次​知道​三​人​的​憤怒\"\n\n#: Source/translation_dummy.cpp:927\nmsgid \"\"\n\"Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I \"\n\"awoke my Master from his sleep, he attempted to possess a mortal's form. \"\n\"Diablo attempted to claim the body of King Leoric, but my Master was too \"\n\"weak from his imprisonment. My Lord required a simple and innocent anchor to \"\n\"this world, and so found the boy Albrecht to be perfect for the task. While \"\n\"the good King Leoric was left maddened by Diablo's unsuccessful possession, \"\n\"I kidnapped his son Albrecht and brought him before my Master. I now await \"\n\"Diablo's call and pray that I will be rewarded when he at last emerges as \"\n\"the Lord of this world.\"\nmsgstr \"\"\n\"向​迪亞波羅​致敬​和​獻祭​-​恐懼​之​王​和​靈魂​的​毀滅​者。當​我​從​睡​夢​中​喚醒​我​的​主人時，他​試\"\n\"圖擁​有​一​個​凡​人​的​形體。迪亞波羅試圖奪​走​李奧瑞克國王​的​屍體，但​我​的​主人​被​囚禁​后​\"\n\"太​虛弱​了。我​的​主人​需要​一​個​簡單​和​無辜​的​錨​到​這個​世界​上，所以​發現​男孩​阿爾佈​雷希\"\n\"特​是​完美​的​任務。當善良​的​國王李奧瑞克​被​迪亞波羅​的​失敗​激怒​時，我​綁架​了​他​的​兒子​\"\n\"阿爾布雷希特，把​他​帶​到​我​的​主人​面​前。我​現​在​等待​著​迪亞波羅​的​召喚，祈禱當​他​最​終​\"\n\"成為這個​世界​的​主時，我​會​得到​回報\"\n\n#: Source/translation_dummy.cpp:928\nmsgid \"\"\n\"Thank goodness you've returned!\\n\"\n\"Much has changed since you lived here, my friend. All was peaceful until the \"\n\"dark riders came and destroyed our village. Many were cut down where they \"\n\"stood, and those who took up arms were slain or dragged away to become \"\n\"slaves - or worse. The church at the edge of town has been desecrated and is \"\n\"being used for dark rituals. The screams that echo in the night are inhuman, \"\n\"but some of our townsfolk may yet survive. Follow the path that lies between \"\n\"my tavern and the blacksmith shop to find the church and save who you can. \\n\"\n\" \\n\"\n\"Perhaps I can tell you more if we speak again. Good luck.\"\nmsgstr \"\"\n\"謝​天謝​地​你​回來​了​\\n\"\n\"自從​你​住​在​這裡，我​的​朋友，一切​都​變​了。一切​都​很​平靜，直​到​黑暗​騎士​來摧毀​我​們​的​\"\n\"村莊。許多​人​在​原地​被​砍倒，拿起​武器​的​人​被​殺​或​被​拖走​成​為奴隸，甚至​更​糟。城市​邊\"\n\"緣​的​教堂​被​褻瀆，被​用來​舉行​黑暗​的​儀式。夜晚​迴響​的​尖叫​聲​是​不​人道​的，但​我​們​的​一\"\n\"些​市民​可能​還活著。沿​著​我​的​小酒館​和​鐵匠​鋪​之​間​的​小​路​去​尋​找​教堂，拯救​你​能​拯救​的​\"\n\"人。\\n\"\n\" \\n\"\n\"​如果​我​們​再​談​的​話，也​許​我​可以​告訴​你​更​多。祝​你​好運\"\n\n#: Source/translation_dummy.cpp:929\nmsgid \"\"\n\"Maintain your quest.  Finding a treasure that is lost is not easy.  Finding \"\n\"a treasure that is hidden less so.  I will leave you with this.  Do not let \"\n\"the sands of time confuse your search.\"\nmsgstr \"\"\n\"繼續​你​的​任務。找到​丟失​的​寶藏並​不​容易。找到​一​個​藏得​不​那​麼​深​的​寶藏。我​把​這個​留\"\n\"給​你。不​要​讓時間​的​沙子​迷惑​了​你​的​尋​找\"\n\n#: Source/translation_dummy.cpp:930\nmsgid \"\"\n\"A what?!  This is foolishness.  There's no treasure buried here in \"\n\"Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They \"\n\"don't match our town at all.  I'd keep my mind on what lies below the \"\n\"cathedral and not what lies below our topsoil.\"\nmsgstr \"\"\n\"什麼？！這​是​愚蠢​的。特里斯特拉姆​這裡沒​有​寶藏。讓​我​看看！！啊，看這​些​畫​不​準\"\n\"確。他​們​根本​不​符合​我​們​的​城市。我​會​把​心思放​在​大​教堂​下面，而​不​是​我​們​的​表土​下面\"\n\n#: Source/translation_dummy.cpp:931\nmsgid \"\"\n\"I really don't have time to discuss some map you are looking for.  I have \"\n\"many sick people that require my help and yours as well.\"\nmsgstr \"我​真的​沒​有​時間討論​你​要​找​的​地圖。我​有​許​多​病人​需要​我​和​你​的​幫助\"\n\n#: Source/translation_dummy.cpp:932\nmsgid \"\"\n\"The once proud Iswall is trapped deep beneath the surface of this world.  \"\n\"His honor stripped and his visage altered.  He is trapped in immortal \"\n\"torment.  Charged to conceal the very thing that could free him.\"\nmsgstr \"\"\n\"曾​經引​以​為傲​的​Iswall​深陷​在​這個​世界​的​表面​之下。他​的​榮譽​被​剝奪​了，面容​也​變​了。\"\n\"他​被困​在​不朽​的​折磨​之中。被​指控​隱瞞​能​讓​他​自由​的​事情\"\n\n#: Source/translation_dummy.cpp:933\nmsgid \"\"\n\"I'll bet that Wirt saw you coming and put on an act just so he could laugh \"\n\"at you later when you were running around the town with your nose in the \"\n\"dirt.  I'd ignore it.\"\nmsgstr \"\"\n\"我​敢​打賭，沃特​看見​你​來​了，就​裝​出​一​副樣子，這樣​他​就​可以​在​你​鼻子​埋​在​泥土裡​在​城\"\n\"里​跑​的​時候​嘲笑​你​了。我​會​忽略​它\"\n\n#: Source/translation_dummy.cpp:934\nmsgid \"\"\n\"There was a time when this town was a frequent stop for travelers from far \"\n\"and wide.  Much has changed since then.  But hidden caves and buried \"\n\"treasure are common fantasies of any child.  Wirt seldom indulges in \"\n\"youthful games.  So it may just be his imagination.\"\nmsgstr \"\"\n\"曾​經​有​一​段​時間，這個城鎮​是​遠道​而來​的​旅行者​的​常去之​地。從​那​以​後​發生​了​很​大​的​變\"\n\"化。但​隱藏​的​洞穴​和​埋藏​的​寶藏​是​任何​孩子​的​共同​幻想。懷特​很少​沉迷​於​年輕人​的​游\"\n\"戲。所以​這​可能​只​是​他​的​想像\"\n\n#: Source/translation_dummy.cpp:935\nmsgid \"\"\n\"Listen here.  Come close.  I don't know if you know what I know, but you've \"\n\"have really got something here.  That's a map.\"\nmsgstr \"\"\n\"聽​著。靠近​點。我​不​知道​你​是否​知道​我​所​知道​的，但​你​真的​有所​收穫。那​是​一​張​地​圖\"\n\n#: Source/translation_dummy.cpp:936\nmsgid \"\"\n\"My grandmother often tells me stories about the strange forces that inhabit \"\n\"the graveyard outside of the church.  And it may well interest you to hear \"\n\"one of them.  She said that if you were to leave the proper offering in the \"\n\"cemetery, enter the cathedral to pray for the dead, and then return, the \"\n\"offering would be altered in some strange way.  I don't know if this is just \"\n\"the talk of an old sick woman, but anything seems possible these days.\"\nmsgstr \"\"\n\"我​祖母​經​常給​我​講​一些​關於​居住​在​教堂​外​墓地​的​奇怪​勢力​的​故事。你​可能​會對​其中​一​個​\"\n\"很​感​興趣。她​說，如果​你​把​合適​的​祭品​留​在​墓地，進入​大​教堂​為​死者​祈禱，然​後​再​回\"\n\"來，祭品會​以​某​種​奇怪​的​方式​改變。我​不​知道​這​是​不​是​一​個​老​病婦​的​談話，但​最近​似乎​\"\n\"什麼​都​有​可能\"\n\n#: Source/translation_dummy.cpp:937\nmsgid \"\"\n\"Hmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be \"\n\"interested in picking up a few things from you.  Or better yet, don't you \"\n\"need some rare and expensive supplies to get you through this ordeal?\"\nmsgstr \"\"\n\"嗯。你​說​的​是​一​個​巨大​而​神秘​的​寶藏。嗯。也​許​我​有​興趣從​你​那​裡​得到​一些​東西。或者​\"\n\"更​好​的​是，你​不​需要​一些​稀有​而​昂貴​的​物資​來度​過這​場​磨難嗎\"\n\n#: Source/translation_dummy.cpp:938\nmsgid \"\"\n\"So, you're the hero everyone's been talking about. Perhaps you could help a \"\n\"poor, simple farmer out of a terrible mess? At the edge of my orchard, just \"\n\"south of here, there's a horrible thing swelling out of the ground! I can't \"\n\"get to my crops or my bales of hay, and my poor cows will starve. The witch \"\n\"gave this to me and said that it would blast that thing out of my field. If \"\n\"you could destroy it, I would be forever grateful. I'd do it myself, but \"\n\"someone has to stay here with the cows...\"\nmsgstr \"\"\n\"所以，你​是​每​個​人​都​在​談論​的​英雄。也​許​你​能​幫助​一​個​貧窮​的​農民擺脫​困境？在​我​的​果\"\n\"園​的​邊緣，就​在​這裡​的​南邊，有​一​個​可怕​的​東西從​地​裡​冒出​來！我​不​能​得到​我​的​莊稼​或​\"\n\"我​的​捆乾草，我​可​憐​的​奶牛會​餓死。巫婆​把​這個給​了​我，說​它​會​把​那​東​西從​我​的​地裡​炸​\"\n\"出來。如果​你​能​毀掉​它，我​將​永遠​感激。我​自己​會​做​的，但​總​得​有​人​留下​來​陪​奶牛\"\n\n#: Source/translation_dummy.cpp:939\nmsgid \"\"\n\"I knew that it couldn't be as simple as that witch made it sound. It's a sad \"\n\"world when you can't even trust your neighbors.\"\nmsgstr \"\"\n\"我​知道​事情​不​會​像​巫婆說​的​那​麼​簡單。當​你​連鄰居​都​不​能​信任​的​時候，這​是​一​個​悲哀​的​\"\n\"世界\"\n\n#: Source/translation_dummy.cpp:940\nmsgid \"\"\n\"Is it gone? Did you send it back to the dark recesses of Hades that spawned \"\n\"it? You what? Oh, don't tell me you lost it! Those things don't come cheap, \"\n\"you know. You've got to find it, and then blast that horror out of our town.\"\nmsgstr \"\"\n\"它​不​見​了​嗎？你​把​它​送回​了​孕育​它​的​陰間嗎？你​什麼？哦，別告訴​我​你​丟​了！你​知道，\"\n\"那些​東西不便宜。你​一定​要​找到​它，然​後​把​那​恐懼​的​東西轟​出去\"\n\n#: Source/translation_dummy.cpp:941\nmsgid \"\"\n\"I heard the explosion from here! Many thanks to you, kind stranger. What \"\n\"with all these things comin' out of the ground, monsters taking over the \"\n\"church, and so forth, these are trying times. I am but a poor farmer, but \"\n\"here -- take this with my great thanks.\"\nmsgstr \"\"\n\"我​聽​到​爆炸聲​了！多​謝​你，善良​的​陌生人。隨著​所有​這​些​東西從​地下​冒出來，怪物佔領​\"\n\"了​教堂，等等，這​些​都​是​艱難​的​時刻。我​只​是​一​個​貧窮​的​農民，但​在​這裡​——​請​接受​我​的​\"\n\"謝意\"\n\n#: Source/translation_dummy.cpp:942\nmsgid \"\"\n\"Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with \"\n\"all the other troubles. Maybe after you've cleansed the church of some of \"\n\"those creatures you could come back... and spare a little time to help a \"\n\"poor farmer?\"\nmsgstr \"\"\n\"哦，我​有​這麼​大​的​麻煩​…​也​許​…​不，我​不​能​強加給​你，還​有​其他​的​麻煩。也​許​在​你​清除​了​\"\n\"教堂​里​的​一些​生物​之後​你​可以​回來。。。抽出​一​點​時間​去​幫助​一​個​貧窮​的​農民\"\n\n#: Source/translation_dummy.cpp:943\nmsgid \"Waaaah! (sniff) Waaaah! (sniff)\"\nmsgstr \"哇​啊​(​嗅​）​哇​啊​(嗅嗅​）\"\n\n#: Source/translation_dummy.cpp:944\nmsgid \"\"\n\"I lost Theo!  I lost my best friend!  We were playing over by the river, and \"\n\"Theo said he wanted to go look at the big green thing.  I said we shouldn't, \"\n\"but we snuck over there, and then suddenly this BUG came out!  We ran away \"\n\"but Theo fell down and the bug GRABBED him and took him away!\"\nmsgstr \"\"\n\"我​失去​了​西奧！我​失去​了​我​最​好​的​朋友！我​們​在​河邊​玩，西奧說​他​想​去​看看​綠色​的​東\"\n\"西。我​說​我​們​不​應該，但​我​們​偷偷​溜過​去，然後​突然​這個​蟲子​出來​了！我​們​逃跑​了，但​\"\n\"西奧​摔倒​了，蟲子​抓住​他，把​他​帶​走​了\"\n\n#: Source/translation_dummy.cpp:945\nmsgid \"\"\n\"Didja find him?  You gotta find Theodore, please!  He's just little.  He \"\n\"can't take care of himself!  Please!\"\nmsgstr \"\"\n\"你​找到​他​了​嗎？你​得​找到​西奧​多，求​你​了！他​只是​個​小​孩子。他​不​能​照顧​自己！求​你​了\"\n\n#: Source/translation_dummy.cpp:946\nmsgid \"\"\n\"You found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs \"\n\"scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, \"\n\"Theo, let's go home!  Thanks again, hero person!\"\nmsgstr \"\"\n\"你​找到​他​了！你​找到​他​了！非常​感謝。哦，西奧，那些​討厭​的​蟲子嚇​到​你​了​嗎？嘿​啊！\"\n\"有​東​西粘​在​你​的​毛上​了！哎呀！來​吧，西奧，我​們​回家​吧！再次​感謝，英雄​人物\"\n\n#: Source/translation_dummy.cpp:947\nmsgid \"\"\n\"We have long lain dormant, and the time to awaken has come.  After our long \"\n\"sleep, we are filled with great hunger.  Soon, now, we shall feed...\"\nmsgstr \"\"\n\"我​們​早​已​沉睡，覺醒​的​時刻​已​經​到​來。長眠​之後，我​們​感到​非常​飢餓。很​快，現​在，我​\"\n\"們將餵養\"\n\n#: Source/translation_dummy.cpp:948\nmsgid \"\"\n\"Have you been enjoying yourself, little mammal?  How pathetic. Your little \"\n\"world will be no challenge at all.\"\nmsgstr \"你​玩​得​開心嗎，小​哺​乳動物？真​可​憐。你​的​小​世界​不​會​是​什麼​挑戰\"\n\n#: Source/translation_dummy.cpp:949\nmsgid \"\"\n\"These lands shall be defiled, and our brood shall overrun the fields that \"\n\"men call home.  Our tendrils shall envelop this world, and we will feast on \"\n\"the flesh of its denizens.  Man shall become our chattel and sustenance.\"\nmsgstr \"\"\n\"這​些​地​必​被​玷污，我​們​的​後​裔​必​漫過人​們稱​為家​的​田地。我​們​的​捲鬚​要​包裹這​世界，我​\"\n\"們​要​以​其​居民​的​肉為食。人類將​成為​我​們​的​動產​和​食物\"\n\n#: Source/translation_dummy.cpp:950\nmsgid \"\"\n\"Ah, I can smell you...you are close! Close! Ssss...the scent of blood and \"\n\"fear...how enticing...\"\nmsgstr \"啊，我​能​聞​到​你​…​你​就​在​附近！接近！血​和​恐懼​的​味道​…​多​麼​誘​人\"\n\n#: Source/translation_dummy.cpp:951\nmsgid \"\"\n\"And in the year of the Golden Light, it was so decreed that a great \"\n\"Cathedral be raised.  The cornerstone of this holy place was to be carved \"\n\"from the translucent stone Antyrael, named for the Angel who shared his \"\n\"power with the Horadrim.  \\n\"\n\" \\n\"\n\"In the Year of Drawing Shadows, the ground shook and the Cathedral shattered \"\n\"and fell.  As the building of catacombs and castles began and man stood \"\n\"against the ravages of the Sin War, the ruins were scavenged for their \"\n\"stones.  And so it was that the cornerstone vanished from the eyes of man. \\n\"\n\" \\n\"\n\"The stone was of this world -- and of all worlds -- as the Light is both \"\n\"within all things and beyond all things. Light and unity are the products of \"\n\"this holy foundation, a unity of purpose and a unity of possession.\"\nmsgstr \"\"\n\"在​金光​之​年，一​座​大​教堂​被​立​了​起來。這個​聖地​的​基石​是​用半​透明​的​安提拉​石​雕刻​而​成​\"\n\"的，安提拉石​是​以​與​赫拉迪姆​分享​力量​的​天使​命名​的。\\n\"\n\" \\n\"\n\"​在​畫​影子​的​那​一​年，大​地震​動，大​教堂​粉碎​倒塌。隨​著​地下​墓穴​和​城堡​的​建造​開始，人\"\n\"們​開始​抵抗​罪惡戰爭​的​蹂躪，廢墟​被​清理​出來尋​找​石頭。就​這樣，基石​從人們​的​眼​中​消\"\n\"失​了。\\n\"\n\" \\n\"\n\"石頭屬​於​這個​世界，也​屬於​所有​的​世界，就​像​光​既​存在​於​萬物​之​中，也​存在​於​萬物​之\"\n\"外。光明​與​統​一​是​這個神聖基礎​的​產物，是​目的​的​統​一​和​佔有的​統​一。\"\n\n#: Source/translation_dummy.cpp:952\nmsgid \"Moo.\"\nmsgstr \"嗚​嗚\"\n\n#: Source/translation_dummy.cpp:953\nmsgid \"I said, Moo.\"\nmsgstr \"我​說，穆\"\n\n#: Source/translation_dummy.cpp:954\nmsgid \"Look I'm just a cow, OK?\"\nmsgstr \"聽​著，我​只​是​一​頭牛，好嗎\"\n\n#: Source/translation_dummy.cpp:955\nmsgid \"\"\n\"All right, all right.  I'm not really a cow.  I don't normally go around \"\n\"like this; but, I was sitting at home minding my own business and all of a \"\n\"sudden these bugs & vines & bulbs & stuff started coming out of the floor... \"\n\"it was horrible!  If only I had something normal to wear, it wouldn't be so \"\n\"bad.  Hey!  Could you go back to my place and get my suit for me?  The brown \"\n\"one, not the gray one, that's for evening wear.  I'd do it myself, but I \"\n\"don't want anyone seeing me like this.  Here, take this, you might need \"\n\"it... to kill those things that have overgrown everything.  You can't miss \"\n\"my house, it's just south of the fork in the river... you know... the one \"\n\"with the overgrown vegetable garden.\"\nmsgstr \"\"\n\"好​吧，好​吧。我​不​是​一​頭​牛。我​一般​不​會這樣​到​處走​；​但是，當時​我​正​坐​在​家裡​處理​自\"\n\"己​的​事情，突然​這​些​蟲子、藤蔓、球莖​之​類​的​東西開始從​地板​上​冒出來。。。太​可怕​\"\n\"了！如果​我​有​正常​的​衣服​穿，就​不​會​那麼​糟糕​了。嘿​你​能回​我​家​幫​我​拿​衣服​嗎？棕色​\"\n\"的，不​是​灰色​的，那​是​晚裝​的。我​會​自己​做​的，但​我​不​想​讓​任何​人​看到​我​這樣。給，拿​\"\n\"著​這個，你​可能​需要​它。。。殺死​那些​長滿​一切​的​東西。你​不​會​錯過​我​家​的，就​在​河​的​\"\n\"岔口​南邊。。。你​知道​的。。。有​雜草​叢生​的​菜園​的​那​個\"\n\n#: Source/translation_dummy.cpp:956\nmsgid \"\"\n\"What are you wasting time for?  Go get my suit!  And hurry!  That Holstein \"\n\"over there keeps winking at me!\"\nmsgstr \"你​在​浪費​時間​幹​什麼？去​拿​我​的​衣服！快點！那​邊​那​個​荷斯坦人​一直​對​我​眨眼\"\n\n#: Source/translation_dummy.cpp:957\nmsgid \"\"\n\"Hey, have you got my suit there?  Quick, pass it over!  These ears itch like \"\n\"you wouldn't believe!\"\nmsgstr \"嘿，你​有​我​的​西裝嗎？快，傳過來！這​些​耳朵​癢​得​你​都​不​敢​相信\"\n\n#: Source/translation_dummy.cpp:958\nmsgid \"\"\n\"No no no no!  This is my GRAY suit!  It's for evening wear!  Formal \"\n\"occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need \"\n\"the BROWN suit.\"\nmsgstr \"\"\n\"不​不​不！這​是​我​的​灰色​西裝！這​是​晚裝！正式​場合！我​不​能​穿這個。你​是​什麼​怪人？我​\"\n\"需要​那​套​棕色​的​西裝\"\n\n#: Source/translation_dummy.cpp:959\nmsgid \"\"\n\"Ahh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on \"\n\"straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as \"\n\"a gift; and, you know... a little fashion tip... you could use a little... \"\n\"you could use a new... yknowwhatImean?  The whole adventurer motif is just \"\n\"so... retro.  Just a word of advice, eh?  Ciao.\"\nmsgstr \"\"\n\"啊，好多​了。呼！終於​有​尊嚴​了！我​的​鹿角​是​直​的​嗎？很​好。聽著，非常​感謝​你​幫​我。\"\n\"來，把​這個​當作​禮物​；​而且，你​知道。。。一​點​時​尚​提示。。。你​可以​用​一​點。。。你​\"\n\"可以​用​一​個​新​的。。。你​知道​什麼​時候？整​個​冒險家​的​主題​就是。。。復古​的。只​是​一​\"\n\"句​忠告，嗯？再​見\"\n\n#: Source/translation_dummy.cpp:960\nmsgid \"\"\n\"Look.  I'm a cow.  And you, you're monster bait. Get some experience under \"\n\"your belt!  We'll talk...\"\nmsgstr \"\"\n\"你​看。我​是​一​頭​牛。而​你，你​是​怪物誘餌。在​你​的​腰帶​下獲​得​一些​經驗！我​們談談\"\n\n#: Source/translation_dummy.cpp:961\nmsgid \"\"\n\"It must truly be a fearsome task I've set before you. If there was just some \"\n\"way that I could... would a flagon of some nice, fresh milk help?\"\nmsgstr \"\"\n\"這​一定​是​我​擺​在​你​面前​的​一​項​可怕​的​任務。如果​有​什麼辦法​我​可以。。。喝​一​大杯​新鮮​\"\n\"的​牛奶​好​嗎\"\n\n#: Source/translation_dummy.cpp:962\nmsgid \"\"\n\"Oh, I could use your help, but perhaps after you've saved the catacombs from \"\n\"the desecration of those beasts.\"\nmsgstr \"哦，我​需要​你​的​幫助，但​也​許​在​你​從​那些​野獸​的​褻瀆​中​拯救​了​地下​墓穴​之後\"\n\n#: Source/translation_dummy.cpp:963\nmsgid \"\"\n\"I need something done, but I couldn't impose on a perfect stranger. Perhaps \"\n\"after you've been here a while I might feel more comfortable asking a favor.\"\nmsgstr \"\"\n\"我​需要​做​點什麼，但​我​不​能​強​加給​一​個​完全​陌生​的​人。也​許​在​你​來​了​一​段​時間​之後，我​\"\n\"會​更​樂意請​你​幫個​忙\"\n\n#: Source/translation_dummy.cpp:964\nmsgid \"\"\n\"I see in you the potential for greatness.  Perhaps sometime while you are \"\n\"fulfilling your destiny, you could stop by and do a little favor for me?\"\nmsgstr \"\"\n\"我​從​你​身​上​看到​了​偉大​的​潛力。也​許​某​個​時候​你​正在​完成​你​的​命運，你​可以​停下​來幫​我​\"\n\"一​個​小​忙\"\n\n#: Source/translation_dummy.cpp:965\nmsgid \"\"\n\"I think you could probably help me, but perhaps after you've gotten a little \"\n\"more powerful. I wouldn't want to injure the village's only chance to \"\n\"destroy the menace in the church!\"\nmsgstr \"\"\n\"我​想​你​也​許​可以​幫​我，但​也​許​在​你​變​得​更​有​力量​之後。我​可​不​想​破壞​村子​裡摧毀​教堂​威\"\n\"脅​的​唯一​機會\"\n\n#: Source/translation_dummy.cpp:966\nmsgid \"\"\n\"Me, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\"\nmsgstr \"我，我​是​一​頭​白手​起家​的​母牛。做點​自己，然​後。。。那​我​們談談\"\n\n#: Source/translation_dummy.cpp:967\nmsgid \"\"\n\"I don't have to explain myself to every tourist that walks by!  Don't you \"\n\"have some monsters to kill?  Maybe we'll talk later.  If you live...\"\nmsgstr \"\"\n\"我​不​必​向​每​一​個​路過​的​遊客解釋​我​自己！你​不​是​有​怪物​要​殺嗎？也​許​我​們​以​後​再​談。如\"\n\"果​你​活​著\"\n\n#: Source/translation_dummy.cpp:968\nmsgid \"\"\n\"Quit bugging me.  I'm looking for someone really heroic.  And you're not \"\n\"it.  I can't trust you, you're going to get eaten by monsters any day now... \"\n\"I need someone who's an experienced hero.\"\nmsgstr \"\"\n\"別煩​我​了。我​在​找​一​個​真正​的​英雄。但​你​不是。我​不​能​相信​你，你​隨時​都​會​被​怪物​吃掉​\"\n\"的。。。我​需要​一​個​有​經驗​的​英雄\"\n\n#: Source/translation_dummy.cpp:969\nmsgid \"\"\n\"All right, I'll cut the bull.  I didn't mean to steer you wrong.  I was \"\n\"sitting at home, feeling moo-dy, when things got really un-stable; a whole \"\n\"stampede of monsters came out of the floor!  I just cowed.  I just happened \"\n\"to be wearing this Jersey when I ran out the door, and now I look udderly \"\n\"ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  \"\n\"Hey!  Can you go back to my place and get my suit for me?  The brown one, \"\n\"not the gray one, that's for evening wear.  I'd do it myself, but I don't \"\n\"want anyone seeing me like this.  Here, take this, you might need it... to \"\n\"kill those things that have overgrown everything.  You can't miss my house, \"\n\"it's just south of the fork in the river... you know... the one with the \"\n\"overgrown vegetable garden.\"\nmsgstr \"\"\n\"好​吧，我​來切​公牛。我​不​是​故意​誤導​你​的。我​坐​在​家裡，心情​很​不​好，這時​情況變​得​很​\"\n\"不​穩定​；​一​大​群​怪物從​地板​上​跑​了​出來！我​只​是​嚇​了​一​跳。我​跑出家門​的​時候​正好​穿​著​\"\n\"這件​球衣，現​在​我​看​起來​很​可​笑。如果​我​有​正常​的​衣服​穿，就​不​會​那麼​糟糕​了。嘿​你​能\"\n\"回​我​家​幫​我​拿​衣服​嗎？棕色​的，不​是​灰色​的，那​是​晚裝​的。我​會​自己​做​的，但​我​不​想​讓​\"\n\"任何​人​看到​我​這樣。給，拿​著​這個，你​可能​需要​它。。。殺死​那些​長滿​一切​的​東西。你​\"\n\"不​會​錯過​我​家​的，就​在​河​的​岔口​南邊。。。你​知道​的。。。有​雜草​叢生​的​菜園​的​那​個\"\n\n#: Source/translation_dummy.cpp:970\nmsgid \"\"\n\"I have tried spells, threats, abjuration and bargaining with this foul \"\n\"creature -- to no avail.  My methods of enslaving lesser demons seem to have \"\n\"no effect on this fearsome beast.\"\nmsgstr \"\"\n\"我​試過咒​語，威脅，放棄​和​這個​骯髒​的​生物​討價​還價​——​都​沒​有用。我​奴役​小惡魔​的​方法​\"\n\"似乎​對這個​可怕​的​野獸沒​有​效果\"\n\n#: Source/translation_dummy.cpp:971\nmsgid \"\"\n\"My home is slowly becoming corrupted by the vileness of this unwanted \"\n\"prisoner.  The crypts are full of shadows that move just beyond the corners \"\n\"of my vision.  The faint scrabble of claws dances at the edges of my \"\n\"hearing. They are searching, I think, for this journal.\"\nmsgstr \"\"\n\"我​的​家正​慢慢​被​這個​不​受​歡迎​的​囚犯​的​卑鄙行徑​所​腐蝕。地窖里​到​處​都​是​影子，它​們​就​\"\n\"在​我​視線​的​角落​之外。我​耳邊隱約傳​來​爪子​的​拼字聲。我​想，他​們​在​找這​本​雜誌\"\n\n#: Source/translation_dummy.cpp:972\nmsgid \"\"\n\"In its ranting, the creature has let slip its name -- Na-Krul.  I have \"\n\"attempted to research the name, but the smaller demons have somehow \"\n\"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I \"\n\"prefer to think of it only as The Creature rather than ponder its true name.\"\nmsgstr \"\"\n\"在​咆哮​中，這個​生物​漏​了​自己​的​名字​——​納克魯爾。我​曾​試圖​研究​這個​名字，但​小​惡​魔​不​\"\n\"知​何故毀​了​我​的​圖書館。納克魯爾。。。我​對這個​名字​充滿​了​恐懼。我​寧願​把​它​當​作​一​\"\n\"種​生物，而​不​願考慮​它​的​真名\"\n\n#: Source/translation_dummy.cpp:973\nmsgid \"\"\n\"The entrapped creature's howls of fury keep me from gaining much needed \"\n\"sleep.  It rages against the one who sent it to the Void, and it calls foul \"\n\"curses upon me for trapping it here.  Its words fill my heart with terror, \"\n\"and yet I cannot block out its voice.\"\nmsgstr \"\"\n\"那​被​困住​的​生物​狂怒​的​嚎叫​使​我​無法獲​得​急​需​的​睡眠。它​向​那​把​它​送到​虛空​的​人​發怒，\"\n\"因​我​把​它​困​在​這裡，就​咒​詛​我。它​的​話語​使​我​的​心充滿​恐懼，然而​我​無​法​阻擋​它​的​聲音\"\n\n#: Source/translation_dummy.cpp:974\nmsgid \"\"\n\"My time is quickly running out.  I must record the ways to weaken the demon, \"\n\"and then conceal that text, lest his minions find some way to use my \"\n\"knowledge to free their lord.  I hope that whoever finds this journal will \"\n\"seek the knowledge.\"\nmsgstr \"\"\n\"我​的​時間​快​用完​了。我​必​須記錄​下​削弱​惡魔​的​方法，然​後​隱​藏這​段​文字，以免​他​的​爪牙\"\n\"們​想​辦法​利用​我​的​知識來​解放​他​們​的​主。我​希望​找到​這本​日記​的​人​都​能​找到​知識\"\n\n#: Source/translation_dummy.cpp:975\nmsgid \"\"\n\"Whoever finds this scroll is charged with stopping the demonic creature that \"\n\"lies within these walls.  My time is over. Even now, its hellish minions \"\n\"claw at the frail door behind which I hide.  \\n\"\n\" \\n\"\n\"I have hobbled the demon with arcane magic and encased it within great \"\n\"walls, but I fear that will not be enough. \\n\"\n\" \\n\"\n\"The spells found in my three grimoires will provide you protected entrance \"\n\"to his domain, but only if cast in their proper sequence.  The levers at the \"\n\"entryway will remove the barriers and free the demon; touch them not!  Use \"\n\"only these spells to gain entry or his power may be too great for you to \"\n\"defeat.\"\nmsgstr \"\"\n\"無​論誰​找到​這卷​卷軸，都​將負責​阻止​這​些​墻內​的​惡魔​生物。我​的​時間​到​了。即使​是​現​\"\n\"在，它​的​地獄​般​的​爪子​在​脆弱​的​門，我​躲​在​後面​爪。\\n\"\n\" \\n\"\n\"​我​已​經用​神秘​的​魔法​把​惡​魔束​縛住，把​它​包裹​在​長城裡，但​我​擔心這還​不​夠。\\n\"\n\" \\n\"\n\"​在​我​的​三​個​幽靈​身​上​找到​的​法術將為​你​提供​進入​他​的​領地​的​保護，但​前提​是​必須​按​正確​\"\n\"的​順序​施放。入口​的​槓桿​會​移​除障​礙物，釋放​惡魔​；​別碰​他​們！只​使用​這​些​法術​進入，\"\n\"否則​他​的​力量​可能​太​大，你​無法擊敗\"\n\n#: Source/translation_dummy.cpp:976\nmsgid \"In Spiritu Sanctum.\"\nmsgstr \"在​靈堂\"\n\n#: Source/translation_dummy.cpp:977\nmsgid \"Praedictum Otium.\"\nmsgstr \"中​耳前庭\"\n\n#: Source/translation_dummy.cpp:978\nmsgid \"Efficio Obitus Ut Inimicus.\"\nmsgstr \"有效​的​懲罰\"\n\n#: Source/translation_dummy.cpp:979\n#, fuzzy\n#| msgid \"Hellboar\"\nmsgctxt \"monster\"\nmsgid \"Hellboar\"\nmsgstr \"地​獄豬\"\n\n#: Source/translation_dummy.cpp:980\n#, fuzzy\n#| msgid \"Stinger\"\nmsgctxt \"monster\"\nmsgid \"Stinger\"\nmsgstr \"釘​刺者\"\n\n#: Source/translation_dummy.cpp:981\n#, fuzzy\n#| msgid \"Psychorb\"\nmsgctxt \"monster\"\nmsgid \"Psychorb\"\nmsgstr \"精神病\"\n\n#: Source/translation_dummy.cpp:982\n#, fuzzy\n#| msgid \"Arachnon\"\nmsgctxt \"monster\"\nmsgid \"Arachnon\"\nmsgstr \"蛛​網膜\"\n\n#: Source/translation_dummy.cpp:983\n#, fuzzy\n#| msgid \"Felltwin\"\nmsgctxt \"monster\"\nmsgid \"Felltwin\"\nmsgstr \"孿生​兄弟\"\n\n#: Source/translation_dummy.cpp:984\n#, fuzzy\n#| msgid \"Hork Spawn\"\nmsgctxt \"monster\"\nmsgid \"Hork Spawn\"\nmsgstr \"霍克產​卵\"\n\n#: Source/translation_dummy.cpp:985\n#, fuzzy\n#| msgid \"Venomtail\"\nmsgctxt \"monster\"\nmsgid \"Venomtail\"\nmsgstr \"毒尾\"\n\n#: Source/translation_dummy.cpp:986\n#, fuzzy\n#| msgid \"Necromorb\"\nmsgctxt \"monster\"\nmsgid \"Necromorb\"\nmsgstr \"死​屍\"\n\n#: Source/translation_dummy.cpp:987\n#, fuzzy\n#| msgid \"Spider Lord\"\nmsgctxt \"monster\"\nmsgid \"Spider Lord\"\nmsgstr \"蜘蛛​的\"\n\n#: Source/translation_dummy.cpp:988\n#, fuzzy\n#| msgid \"Lashworm\"\nmsgctxt \"monster\"\nmsgid \"Lashworm\"\nmsgstr \"鞭蟲\"\n\n#: Source/translation_dummy.cpp:989\n#, fuzzy\n#| msgid \"Torchant\"\nmsgctxt \"monster\"\nmsgid \"Torchant\"\nmsgstr \"托爾昌特\"\n\n#: Source/translation_dummy.cpp:990\n#, fuzzy\n#| msgid \"Hell Bug\"\nmsgctxt \"monster\"\nmsgid \"Hell Bug\"\nmsgstr \"地​獄\"\n\n#: Source/translation_dummy.cpp:991\n#, fuzzy\n#| msgid \"Gravedigger\"\nmsgctxt \"monster\"\nmsgid \"Gravedigger\"\nmsgstr \"掘​墓​人\"\n\n#: Source/translation_dummy.cpp:992\n#, fuzzy\n#| msgid \"Tomb Rat\"\nmsgctxt \"monster\"\nmsgid \"Tomb Rat\"\nmsgstr \"利奧里克國王​墓\"\n\n#: Source/translation_dummy.cpp:993\n#, fuzzy\n#| msgid \"Firebat\"\nmsgctxt \"monster\"\nmsgid \"Firebat\"\nmsgstr \"火焰​兵\"\n\n#: Source/translation_dummy.cpp:994\n#, fuzzy\n#| msgid \"Skullwing\"\nmsgctxt \"monster\"\nmsgid \"Skullwing\"\nmsgstr \"骷​髏\"\n\n#: Source/translation_dummy.cpp:995\n#, fuzzy\n#| msgid \"Lich\"\nmsgctxt \"monster\"\nmsgid \"Lich\"\nmsgstr \"巫妖\"\n\n#: Source/translation_dummy.cpp:996\n#, fuzzy\n#| msgid \"Crypt Demon\"\nmsgctxt \"monster\"\nmsgid \"Crypt Demon\"\nmsgstr \"去​地下室\"\n\n#: Source/translation_dummy.cpp:997\n#, fuzzy\n#| msgid \"Hellbat\"\nmsgctxt \"monster\"\nmsgid \"Hellbat\"\nmsgstr \"藍​蝙蝠\"\n\n#: Source/translation_dummy.cpp:998\n#, fuzzy\n#| msgid \"Bone Demon\"\nmsgctxt \"monster\"\nmsgid \"Bone Demon\"\nmsgstr \"骨腔\"\n\n#: Source/translation_dummy.cpp:999\n#, fuzzy\n#| msgid \"Arch Lich\"\nmsgctxt \"monster\"\nmsgid \"Arch Lich\"\nmsgstr \"大​天使​的\"\n\n#: Source/translation_dummy.cpp:1000\n#, fuzzy\n#| msgid \"Biclops\"\nmsgctxt \"monster\"\nmsgid \"Biclops\"\nmsgstr \"雙色\"\n\n#: Source/translation_dummy.cpp:1001\n#, fuzzy\n#| msgid \"Flesh Thing\"\nmsgctxt \"monster\"\nmsgid \"Flesh Thing\"\nmsgstr \"撕裂​的​靈魂​之​肉\"\n\n#: Source/translation_dummy.cpp:1002\n#, fuzzy\n#| msgid \"Reaper\"\nmsgctxt \"monster\"\nmsgid \"Reaper\"\nmsgstr \"收割者\"\n\n#: Source/translation_dummy.cpp:1003\nmsgid \"Giant's Knuckle\"\nmsgstr \"巨人​的​指節\"\n\n#: Source/translation_dummy.cpp:1004\nmsgid \"Mercurial Ring\"\nmsgstr \"汞​環\"\n\n#: Source/translation_dummy.cpp:1005\nmsgid \"Xorine's Ring\"\nmsgstr \"克索林​的​戒指\"\n\n#: Source/translation_dummy.cpp:1006\nmsgid \"Karik's Ring\"\nmsgstr \"卡里克戒指\"\n\n#: Source/translation_dummy.cpp:1007\nmsgid \"Ring of Magma\"\nmsgstr \"巖​漿環\"\n\n#: Source/translation_dummy.cpp:1008\nmsgid \"Ring of the Mystics\"\nmsgstr \"神秘​之​戒\"\n\n#: Source/translation_dummy.cpp:1009\nmsgid \"Ring of Thunder\"\nmsgstr \"雷鳴\"\n\n#: Source/translation_dummy.cpp:1010\nmsgid \"Amulet of Warding\"\nmsgstr \"閃​避護符\"\n\n#: Source/translation_dummy.cpp:1011\nmsgid \"Gnat Sting\"\nmsgstr \"蚊蟲​叮咬\"\n\n#: Source/translation_dummy.cpp:1012\nmsgid \"Flambeau\"\nmsgstr \"弗拉姆​博\"\n\n#: Source/translation_dummy.cpp:1013\nmsgid \"Armor of Gloom\"\nmsgstr \"陰沉​的​護甲\"\n\n#: Source/translation_dummy.cpp:1014\nmsgid \"Blitzen\"\nmsgstr \"閃​電\"\n\n#: Source/translation_dummy.cpp:1015\nmsgid \"Thunderclap\"\nmsgstr \"霹​靂\"\n\n#: Source/translation_dummy.cpp:1016\nmsgid \"Shirotachi\"\nmsgstr \"白池\"\n\n#: Source/translation_dummy.cpp:1017\nmsgid \"Eater of Souls\"\nmsgstr \"靈魂​吞噬者\"\n\n#: Source/translation_dummy.cpp:1018\nmsgid \"Diamondedge\"\nmsgstr \"鑽​石邊\"\n\n#: Source/translation_dummy.cpp:1019\nmsgid \"Bone Chain Armor\"\nmsgstr \"骨鍊​甲\"\n\n#: Source/translation_dummy.cpp:1020\nmsgid \"Demon Plate Armor\"\nmsgstr \"惡​魔板​甲\"\n\n#: Source/translation_dummy.cpp:1021\nmsgid \"Acolyte's Amulet\"\nmsgstr \"侍從​護​符\"\n\n#: Source/translation_dummy.cpp:1022\nmsgid \"Gladiator's Ring\"\nmsgstr \"角​鬥士​戒指\"\n\n#: Source/translation_dummy.cpp:1023\nmsgid \"Jester's\"\nmsgstr \"弄臣​的\"\n\n#: Source/translation_dummy.cpp:1024\nmsgid \"Crystalline\"\nmsgstr \"結晶​的\"\n\n#: Source/translation_dummy.cpp:1025\nmsgid \"Doppelganger's\"\nmsgstr \"雙​通道\"\n\n#: Source/translation_dummy.cpp:1026\nmsgid \"devastation\"\nmsgstr \"毀​滅\"\n\n#: Source/translation_dummy.cpp:1027\nmsgid \"decay\"\nmsgstr \"衰退\"\n\n#: Source/translation_dummy.cpp:1028\nmsgid \"peril\"\nmsgstr \"危險\"\n\n#: Source/translation_dummy.cpp:1029\nmsgctxt \"spell\"\nmsgid \"Mana\"\nmsgstr \"法力\"\n\n#: Source/translation_dummy.cpp:1030\n#, fuzzy\n#| msgid \"the Magi\"\nmsgctxt \"spell\"\nmsgid \"the Magi\"\nmsgstr \"\"\n\"注意​並見​證這裡​的​真理，因​為​它​們​是​赫拉迪姆​最後​的​遺產。近​三百​年​前，人們​知道​燃燒​\"\n\"地獄​的​三​大​惡魔​神秘​地來​到​了​我​們​的​世界。兄弟​三​人​蹂躪​東方​的​土地​數​十​年，而​人類卻​\"\n\"在​他​們身​後​戰慄。我​們​的​騎士團​——​赫拉迪姆​——​是​由​一​群​神秘​的​法師​建立​的，目的​是​一​勞​\"\n\"永逸​地​追捕​和​俘虜​這​三​個​惡魔。\\n\"\n\" \\n\"\n\"​最初​的​赫拉德里姆​在​被​稱為​「​靈魂石​」​的​強大​文物​中​捕獲​了​其中​兩個，並將​它​們​深​埋​在​\"\n\"荒涼​的​東部​沙漠​之下。第三​個​惡​魔逃脫​了​追捕，逃到​了​西部，許多赫拉迪姆人​都​在​追\"\n\"捕。第三​個​惡​魔-​被​稱為迪亞波羅，恐懼​之​王-​最​終​被​俘虜，他​的​靈魂石​和​埋​在​這個​迷宮​\"\n\"的​本質。\\n\"\n\" \\n\"\n\"​要​被​警告，靈魂​之石必須​防止​被​那些​不​信​的​人​發現。如果​迪亞波羅​被​釋放，他​會尋​找​一​\"\n\"個身體​很​容易​控制，因​為​他​會​非常​虛弱​-​也​許​是​一​個​老人​或​兒童\"\n\n#: Source/translation_dummy.cpp:1031\n#, fuzzy\n#| msgid \"the Jester\"\nmsgctxt \"spell\"\nmsgid \"the Jester\"\nmsgstr \"弄臣​的\"\n\n#: Source/translation_dummy.cpp:1032\n#, fuzzy\n#| msgid \"Lightning Wall\"\nmsgctxt \"spell\"\nmsgid \"Lightning Wall\"\nmsgstr \"閃​電術\"\n\n#: Source/translation_dummy.cpp:1033\n#, fuzzy\n#| msgid \"Immolation\"\nmsgctxt \"spell\"\nmsgid \"Immolation\"\nmsgstr \"獻​祭\"\n\n#: Source/translation_dummy.cpp:1034\n#, fuzzy\n#| msgid \"Warp\"\nmsgctxt \"spell\"\nmsgid \"Warp\"\nmsgstr \"扭曲\"\n\n#: Source/translation_dummy.cpp:1035\n#, fuzzy\n#| msgid \"Reflect\"\nmsgctxt \"spell\"\nmsgid \"Reflect\"\nmsgstr \"反映\"\n\n#: Source/translation_dummy.cpp:1036\n#, fuzzy\n#| msgid \"Berserk\"\nmsgctxt \"spell\"\nmsgid \"Berserk\"\nmsgstr \"狂​戰士\"\n\n#: Source/translation_dummy.cpp:1037\n#, fuzzy\n#| msgid \"Ring of Fire\"\nmsgctxt \"spell\"\nmsgid \"Ring of Fire\"\nmsgstr \"戒指\"\n\n#: Source/translation_dummy.cpp:1038\n#, fuzzy\n#| msgid \"Search\"\nmsgctxt \"spell\"\nmsgid \"Search\"\nmsgstr \"我​感覺​到​一​個​靈魂​在​尋​找​答案\"\n\n#: Source/translation_dummy.cpp:1039\nmsgctxt \"spell\"\nmsgid \"Rune of Fire\"\nmsgstr \"火符文\"\n\n#: Source/translation_dummy.cpp:1040\n#, fuzzy\n#| msgid \"Rune of Light\"\nmsgctxt \"spell\"\nmsgid \"Rune of Light\"\nmsgstr \"光\"\n\n#: Source/translation_dummy.cpp:1041\n#, fuzzy\n#| msgid \"Rune of Nova\"\nmsgctxt \"spell\"\nmsgid \"Rune of Nova\"\nmsgstr \"符文\"\n\n#: Source/translation_dummy.cpp:1042\n#, fuzzy\n#| msgid \"Rune of Immolation\"\nmsgctxt \"spell\"\nmsgid \"Rune of Immolation\"\nmsgstr \"符文​炸彈\"\n\n#: Source/translation_dummy.cpp:1043\nmsgctxt \"spell\"\nmsgid \"Rune of Stone\"\nmsgstr \"符文石\"\n\n#. TRANSLATORS: Thousands separator\n#: Source/utils/format_int.cpp:28 Source/utils/format_int.cpp:64\nmsgid \",\"\nmsgstr \"\"\n\n#~ msgid \"Options:\"\n#~ msgstr \"選​項:\"\n\n#~ msgid \"version {:s}\"\n#~ msgstr \"版本​{:s}\"\n\n#, fuzzy\n#~| msgid \"increase magic\"\n#~ msgid \"Decrease Gamma\"\n#~ msgstr \"增加​魔法\"\n\n#, fuzzy\n#~| msgid \"increase magic\"\n#~ msgid \"Increase Gamma\"\n#~ msgstr \"增加​魔法\"\n\n#~ msgid \"No automap available in town\"\n#~ msgstr \"城裡沒​有​汽車​地​圖\"\n\n#~ msgid \"Restart In Town\"\n#~ msgstr \"在​城裡​重新​開始\"\n\n#~ msgid \"Heart\"\n#~ msgstr \"心​臟\"\n\n#~ msgid \"recover life\"\n#~ msgstr \"恢復​生命​值\"\n\n#~ msgid \"deadly heal\"\n#~ msgstr \"致命​的​治療\"\n\n#~ msgid \"decrease strength\"\n#~ msgstr \"降低​力量\"\n\n#~ msgid \"decrease dexterity\"\n#~ msgstr \"降低​敏捷\"\n\n#~ msgid \"decrease vitality\"\n#~ msgstr \"降低​活力\"\n\n#~ msgid \"you can't heal\"\n#~ msgstr \"你​無​法治​癒\"\n\n#~ msgid \"hit monster doesn't heal\"\n#~ msgstr \"命​中​怪物無​法治​癒\"\n\n#~ msgid \"Faster attack swing\"\n#~ msgstr \"更​快​的​揮動\"\n\n#~ msgid \"see with infravision\"\n#~ msgstr \"夜視​能力\"\n\n#~ msgid \"Trying to drop a floor item?\"\n#~ msgstr \"想​扔​地板嗎？\"\n\n#, fuzzy\n#~| msgid \"Scimitar\"\n#~ msgid \"FPS Limiter\"\n#~ msgstr \"彎​刀\"\n\n#, fuzzy\n#~ msgid \"To hit\"\n#~ msgstr \"生命​點{:d}​的​{:d}\"\n\n#~ msgid \"Failed to open player archive for writing.\"\n#~ msgstr \"無​法​打開​播放器​存檔​進行​寫入。\"\n\n#~ msgid \"Unable to read to save file archive\"\n#~ msgstr \"無​法​讀取​以​儲存檔​案​存檔\"\n\n#~ msgid \"Unable to write to save file archive\"\n#~ msgstr \"無​法寫​入​以​儲存檔​案​存檔\"\n\n#~ msgid \"Indestructible,  \"\n#~ msgstr \"堅​不​可摧，\"\n\n#~ msgid \"No required attributes\"\n#~ msgstr \"沒​有​必需​的​屬性\"\n\n#~ msgid \"\"\n#~ \"Beyond the Hall of Heroes lies the Chamber of Bone.  Eternal death awaits \"\n#~ \"any who would seek to steal the treasures secured within this room.  So \"\n#~ \"speaks the Lord of Terror, and so it is written.\"\n#~ msgstr \"\"\n#~ \"英雄​殿後​是​藏骨密室。永恒​的​死亡​等待​著​任何​想要​偷​走​這間​屋子​裡珍寶​的​人。恐懼​之​\"\n#~ \"耶​和華​如此​說，經​上​如此​記​著\"\n\n#~ msgid \"\"\n#~ \"The armories of Hell are home to the Warlord of Blood.  In his wake lay \"\n#~ \"the mutilated bodies of thousands.  Angels and man alike have been cut \"\n#~ \"down to fulfill his endless sacrifices to the Dark ones who scream for \"\n#~ \"one thing - blood.\"\n#~ msgstr \"\"\n#~ \"地獄​的​軍械庫​是​血​之​軍閥​的​家。他​身​後​躺著​成千上​萬具殘缺​的​屍體。天使​和​人類​都​被​\"\n#~ \"砍掉​了，來​完成​他​對​黑暗​勢力無盡​的​犧牲，他​們​只​為​一​件​事​而​尖叫​——​血\"\n\n#~ msgid \"\"\n#~ \"Cloudy and cooler today.  Casting the nets of necromancy across the void \"\n#~ \"landed two new subspecies of flying horror; a good day's work.  Must \"\n#~ \"remember to order some more bat guano and black candles from Adria; I'm \"\n#~ \"running a bit low.\"\n#~ msgstr \"\"\n#~ \"今天​多​雲​涼爽。將亡靈​之​網​撒向虛空，降落​了​兩個​新​的​飛行​恐懼​亞種​；​一​天​的​好​工\"\n#~ \"作。一定​要​記​得​從​阿德里亞訂購​更​多​的​蝙蝠糞​和​黑蠟燭​；​我​的​血壓​有​點​低\"\n\n#~ msgid \"Right click to read\"\n#~ msgstr \"右​擊閱讀\"\n\n#~ msgid \"Resist All: 75% MAX\"\n#~ msgstr \"所有​抗性: 最​大{:+d}%\"\n"
  },
  {
    "path": "VERSION",
    "content": "1.6.0-dev\r\n"
  },
  {
    "path": "android-project/.gitignore",
    "content": "# Intellij\n.idea/\n\n# Gradle files\n/.gradle/\nbuild/\n\n# Android\n/app/.cxx/\n\n# Local configuration file (sdk path, etc)\n/local.properties\n\n/app/src/main/assets/*\n"
  },
  {
    "path": "android-project/app/build.gradle",
    "content": "def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY')\r\ndef buildAsApplication = !buildAsLibrary\r\nif (buildAsApplication) {\r\n\tapply plugin: 'com.android.application'\r\n} else {\r\n\tapply plugin: 'com.android.library'\r\n}\r\n\r\nandroid {\r\n\tndkVersion '28.0.13004108'\r\n\tcompileSdk 35\r\n\tdefaultConfig {\r\n\t\tif (buildAsApplication) {\r\n\t\t\tapplicationId \"org.diasurgical.devilutionx\"\r\n\t\t}\r\n\t\tminSdkVersion 21\r\n\t\ttargetSdkVersion 35\r\n\t\tversionCode 29\r\n\t\tversionName project.file('../../VERSION').text.trim()\r\n\t\texternalNativeBuild {\r\n\t\t\tcmake {\r\n\t\t\t\targuments \"-DANDROID_STL=c++_static\"\r\n\t\t\t\tabiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tbuildTypes {\r\n\t\tdebug {\r\n\t\t\tapplicationIdSuffix \".dev\"\r\n\t\t}\r\n\t\trelease {\r\n\t\t\tminifyEnabled false\r\n\t\t\tproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\r\n\t\t}\r\n\t}\r\n\tnamespace 'org.diasurgical.devilutionx'\r\n\tbuildFeatures {\r\n\t\tbuildConfig true\r\n\t}\r\n\tapplicationVariants.all { variant ->\r\n\t\ttasks[\"merge${variant.name.capitalize()}Assets\"]\r\n\t\t\t.dependsOn(\"externalNativeBuild${variant.name.capitalize()}\")\r\n\t}\r\n\tif (!project.hasProperty('EXCLUDE_NATIVE_LIBS')) {\r\n\t\tsourceSets.main {\r\n\t\t\tjniLibs.srcDir 'libs'\r\n\t\t}\r\n\t\texternalNativeBuild {\r\n\t\t\tcmake {\r\n\t\t\t\tpath '../../CMakeLists.txt'\r\n\t\t\t\tversion \"3.31.0+\"\r\n\t\t\t\tbuildStagingDirectory System.env.DevilutionX_Android_StagingDirectory\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tif (buildAsLibrary) {\r\n\t\tlibraryVariants.all { variant ->\r\n\t\t\tvariant.outputs.each { output ->\r\n\t\t\t\tdef outputFile = output.outputFile\r\n\t\t\t\tif (outputFile != null && outputFile.name.endsWith(\".aar\")) {\r\n\t\t\t\t\tdef fileName = \"org.diasurgical.devilutionx.aar\"\r\n\t\t\t\t\toutput.outputFile = new File(outputFile.parent, fileName)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\ndependencies {\r\n\timplementation fileTree(include: ['*.jar'], dir: 'libs')\r\n\timplementation 'com.android.support.constraint:constraint-layout:2.0.4'\r\n}\r\n"
  },
  {
    "path": "android-project/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in [sdk]/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "android-project/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:installLocation=\"auto\">\n\n\t<!-- Detect if device has a file browser -->\n\t<queries>\n\t\t<intent>\n\t\t\t<action android:name=\"android.intent.action.OPEN_DOCUMENT\" />\n\t\t\t<data android:mimeType=\"*/*\" />\n\t\t</intent>\n\t</queries>\n\n    <!-- OpenGL ES 2.0 -->\n    <uses-feature android:glEsVersion=\"0x00020000\" />\n\n    <!-- Touchscreen support -->\n    <uses-feature\n        android:name=\"android.hardware.touchscreen\"\n        android:required=\"false\" />\n\n    <!-- Game controller support -->\n    <uses-feature\n        android:name=\"android.hardware.bluetooth\"\n        android:required=\"false\" />\n    <uses-feature\n        android:name=\"android.hardware.gamepad\"\n        android:required=\"false\" />\n    <uses-feature\n        android:name=\"android.hardware.usb.host\"\n        android:required=\"false\" />\n\n    <!-- External mouse input events -->\n    <uses-feature\n        android:name=\"android.hardware.type.pc\"\n        android:required=\"false\" />\n\n    <uses-feature\n        android:name=\"android.software.leanback\"\n        android:required=\"false\" />\n\n    <!-- Required for downloading shareware data on older devices -->\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" android:maxSdkVersion=\"22\" />\n    <!-- Allow access to Bluetooth devices -->\n    <!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->\n    <!-- <uses-permission android:name=\"android.permission.BLUETOOTH\" android:maxSdkVersion=\"30\" /> -->\n    <!-- <uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\" /> -->\n\n    <!-- Allow access to the vibrator -->\n    <uses-permission android:name=\"android.permission.VIBRATE\" />\n    <!-- Allow access to the network for multiplayer and demo download -->\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application android:label=\"@string/app_name\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:banner=\"@drawable/banner\"\n        android:allowBackup=\"true\"\n        android:fullBackupContent=\"@xml/backup_descriptor\"\n        android:dataExtractionRules=\"@xml/backup_rules\"\n        tools:targetApi=\"s\"\n        android:isGame=\"true\"\n        android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\"\n        android:hardwareAccelerated=\"true\">\n\n        <!-- Example of setting SDL hints from AndroidManifest.xml:\n        <meta-data android:name=\"SDL_ENV.SDL_ACCELEROMETER_AS_JOYSTICK\" android:value=\"0\"/>\n         -->\n\n        <activity android:name=\"org.diasurgical.devilutionx.DevilutionXSDLActivity\"\n            android:label=\"@string/app_name\"\n            android:windowSoftInputMode=\"adjustPan\"\n            android:alwaysRetainTaskState=\"true\"\n            android:launchMode=\"singleInstance\"\n            android:configChanges=\"layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation\"\n            android:preferMinimalPostProcessing=\"true\"\n            android:screenOrientation=\"landscape\"\n            android:exported=\"true\"\n            >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n                <category android:name=\"android.intent.category.LEANBACK_LAUNCHER\" />\n            </intent-filter>\n            <!-- Let Android know that we can handle some USB devices and should receive this event -->\n            <intent-filter>\n                <action android:name=\"android.hardware.usb.action.USB_DEVICE_ATTACHED\" />\n            </intent-filter>\n            <!-- Drop file event -->\n            <!--\n            <intent-filter>\n                <action android:name=\"android.intent.action.VIEW\" />\n                <category android:name=\"android.intent.category.DEFAULT\" />\n                <data android:mimeType=\"*/*\" />\n            </intent-filter>\n            -->\n            <!-- Location where shortcuts for the app are defined -->\n            <meta-data\n                android:name=\"android.app.shortcuts\"\n                android:resource=\"@xml/shortcuts\" />\n        </activity>\n\n        <activity android:name=\".DataActivity\"\n                android:theme=\"@style/Theme.MyApplication\">\n        </activity>\n\n        <activity android:name=\".ImportActivity\"\n            android:theme=\"@style/Theme.MyApplication\">\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java",
    "content": "package org.diasurgical.devilutionx;\r\n\r\nimport android.app.Activity;\r\nimport android.app.DownloadManager;\r\nimport android.content.BroadcastReceiver;\r\nimport android.content.Context;\r\nimport android.content.Intent;\r\nimport android.content.IntentFilter;\r\nimport android.content.pm.PackageManager;\r\nimport android.database.Cursor;\r\nimport android.net.Uri;\r\nimport android.os.Build;\r\nimport android.os.Bundle;\r\nimport android.support.annotation.NonNull;\r\nimport android.text.method.LinkMovementMethod;\r\nimport android.view.View;\r\nimport android.widget.TextView;\r\nimport android.widget.Toast;\r\n\r\nimport java.io.File;\r\nimport java.util.Locale;\r\n\r\npublic class DataActivity extends Activity {\r\n\tprivate ExternalFilesManager fileManager;\r\n\tprivate DownloadReceiver mReceiver;\r\n\tprivate boolean isDownloadingSpawn = false;\r\n\tprivate boolean isDownloadingTranslation = false;\r\n\tprivate boolean isDownloadingFonts = false;\r\n\tprivate int pendingDownloads = 0;\r\n\r\n\t@Override\r\n\tprotected void onCreate(Bundle savedInstanceState) {\r\n\t\tsuper.onCreate(savedInstanceState);\r\n\t\tsetContentView(R.layout.activity_data);\r\n\r\n\t\t((TextView) findViewById(R.id.full_guide)).setMovementMethod(LinkMovementMethod.getInstance());\r\n\t\t((TextView) findViewById(R.id.online_guide)).setMovementMethod(LinkMovementMethod.getInstance());\r\n\r\n\t\tboolean isTelevision = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);\r\n\t\tif (isTelevision) {\r\n\t\t\tfindViewById(R.id.gamepad_text).setVisibility(View.VISIBLE);\r\n\t\t\tfindViewById(R.id.gamepad_icon).setVisibility(View.VISIBLE);\r\n\t\t}\r\n\t}\r\n\r\n\tprotected void onResume() {\r\n\t\tsuper.onResume();\r\n\r\n\t\tfileManager = new ExternalFilesManager(this);\r\n\r\n\t\tstartGame();\r\n\t}\r\n\r\n\tpublic void startGame(View view) {\r\n\t\tstartGame();\r\n\t}\r\n\r\n\tprivate void startGame() {\r\n\t\tif (isMissingGameData()) {\r\n\t\t\tToast toast = Toast.makeText(getApplicationContext(), getString(R.string.missing_game_data), Toast.LENGTH_SHORT);\r\n\t\t\ttoast.show();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tIntent intent = new Intent(this, DevilutionXSDLActivity.class);\r\n\t\tstartActivity(intent);\r\n\t\tthis.finish();\r\n\t}\r\n\r\n\tprotected void onDestroy() {\r\n\t\tif (mReceiver != null)\r\n\t\t\tunregisterReceiver(mReceiver);\r\n\r\n\t\tsuper.onDestroy();\r\n\t}\r\n\r\n\tprotected boolean pendingTranslationFile(String language) {\r\n\t\tString lang = Locale.getDefault().toString();\r\n\t\tif (!lang.startsWith(language)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tString translationFile = language + \".mpq\";\r\n\t\tif (fileManager.hasFile(translationFile)) {\r\n\t\t\tisDownloadingTranslation = false;\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif (isDownloadingTranslation) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tisDownloadingTranslation = true;\r\n\t\tsendDownloadRequest(\r\n\t\t\t\t\"https://github.com/diasurgical/devilutionx-assets/releases/download/v2/\" + language + \".mpq\",\r\n\t\t\t\tlanguage + \".mpq\",\r\n\t\t\t\t\"Translation Data\"\r\n\t\t);\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the game data is present\r\n\t */\r\n\tprivate boolean isMissingGameData() {\r\n\t\tString lang = Locale.getDefault().toString();\r\n\t\tif (pendingTranslationFile(\"pl\") || pendingTranslationFile(\"ru\")) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tFile fonts_mpq = fileManager.getFile(\"/fonts.mpq\");\r\n\t\tif (lang.startsWith(\"ko\") || lang.startsWith(\"zh\") || lang.startsWith(\"ja\") || fonts_mpq.exists()) {\r\n\t\t\tif (!fonts_mpq.exists() || DevilutionXSDLActivity.areFontsOutOfDate(fonts_mpq.getAbsolutePath())) {\r\n\t\t\t\tif (!isDownloadingFonts) {\r\n\t\t\t\t\tfonts_mpq.delete();\r\n\t\t\t\t\tisDownloadingFonts = true;\r\n\t\t\t\t\tsendDownloadRequest(\r\n\t\t\t\t\t\t\"https://github.com/diasurgical/devilutionx-assets/releases/download/v4/fonts.mpq\",\r\n\t\t\t\t\t\t\"fonts.mpq\",\r\n\t\t\t\t\t\t\"Extra Game Fonts\"\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn !fileManager.hasFile(\"diabdat.mpq\") &&\r\n\t\t\t\t!fileManager.hasFile(\"DIABDAT.MPQ\") &&\r\n\t\t\t\t(!fileManager.hasFile(\"spawn.mpq\") || isDownloadingSpawn);\r\n\t}\r\n\r\n\tpublic void importData(View view) {\r\n\t\tIntent intent = new Intent(this, ImportActivity.class);\r\n\t\tstartActivity(intent);\r\n\t}\r\n\r\n\t/**\r\n\t * Start downloading the shareware\r\n\t */\r\n\tpublic void sendDownloadRequest(View view) {\r\n\t\tisDownloadingSpawn = true;\r\n\t\tsendDownloadRequest(\r\n\t\t\t\"https://github.com/diasurgical/devilutionx-assets/releases/download/v2/spawn.mpq\",\r\n\t\t\t\"spawn.mpq\",\r\n\t\t\tgetString(R.string.shareware_data)\r\n\t\t);\r\n\r\n\t\tview.setEnabled(false);\r\n\r\n\t\tToast toast = Toast.makeText(getApplicationContext(), getString(R.string.download_started), Toast.LENGTH_SHORT);\r\n\t\ttoast.show();\r\n\t}\r\n\r\n\tpublic void sendDownloadRequest(String url, String fileName, String description) {\r\n\t\tDownloadManager.Request request = new DownloadManager.Request(Uri.parse(url))\r\n\t\t\t\t.setTitle(fileName)\r\n\t\t\t\t.setDescription(description)\r\n\t\t\t\t.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);\r\n\r\n\t\t// Download to a temp file which will be renamed later\r\n\t\t// See: https://stackoverflow.com/a/48128014\r\n\t\tFile file = fileManager.getFile(fileName + \"~\");\r\n\t\tUri destination = Uri.fromFile(file);\r\n\t\trequest.setDestinationUri(destination);\r\n\r\n\t\tif (mReceiver == null) {\r\n\t\t\tmReceiver = new DownloadReceiver();\r\n\t\t\tIntentFilter filter = new IntentFilter(\"android.intent.action.DOWNLOAD_COMPLETE\");\r\n\t\t\tif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\r\n\t\t\t\tregisterReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);\r\n\t\t\t} else {\r\n\t\t\t\tregisterReceiver(mReceiver, filter);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDownloadManager downloadManager = (DownloadManager)this.getSystemService(Context.DOWNLOAD_SERVICE);\r\n\t\tpendingDownloads++;\r\n\t\tdownloadManager.enqueue(request);\r\n\t}\r\n\r\n\t/**\r\n\t * Start game when download finishes\r\n\t */\r\n\tprivate class DownloadReceiver extends BroadcastReceiver {\r\n\t\t@Override\r\n\t\tpublic void onReceive(@NonNull Context context, @NonNull Intent intent) {\r\n\t\t\tlong receivedID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L);\r\n\t\t\tDownloadManager mgr = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);\r\n\r\n\t\t\tDownloadManager.Query query = new DownloadManager.Query();\r\n\t\t\tquery.setFilterById(receivedID);\r\n\t\t\tCursor cur = mgr.query(query);\r\n\t\t\tint statusIndex = cur.getColumnIndex(DownloadManager.COLUMN_STATUS);\r\n\t\t\tif (cur.moveToFirst()) {\r\n\t\t\t\tint status = cur.getInt(statusIndex);\r\n\t\t\t\tif (status == DownloadManager.STATUS_SUCCESSFUL) {\r\n\t\t\t\t\t// Rename temp file by removing the tilde\r\n\t\t\t\t\t// See: https://stackoverflow.com/a/48128014\r\n\t\t\t\t\tint titleIndex = cur.getColumnIndex(DownloadManager.COLUMN_TITLE);\r\n\t\t\t\t\tString fileName = cur.getString(titleIndex);\r\n\t\t\t\t\tFile temp = fileManager.getFile(fileName + \"~\");\r\n\t\t\t\t\tFile file = fileManager.getFile(fileName);\r\n\t\t\t\t\ttemp.renameTo(file);\r\n\r\n\t\t\t\t\tpendingDownloads--;\r\n\t\t\t\t}\r\n\t\t\t\tif (status == DownloadManager.STATUS_FAILED) {\r\n\t\t\t\t\tisDownloadingSpawn = false;\r\n\t\t\t\t\tisDownloadingFonts = false;\r\n\t\t\t\t\tisDownloadingTranslation = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcur.close();\r\n\r\n\t\t\tif (pendingDownloads == 0) {\r\n\t\t\t\tisDownloadingSpawn = false;\r\n\t\t\t\tisDownloadingFonts = false;\r\n\t\t\t\tisDownloadingTranslation = false;\r\n\t\t\t\tstartGame();\r\n\t\t\t\tfindViewById(R.id.download_button).setEnabled(true);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java",
    "content": "package org.diasurgical.devilutionx;\r\n\r\nimport android.content.Intent;\r\nimport android.graphics.Insets;\r\nimport android.graphics.Rect;\r\nimport android.os.Build;\r\nimport android.os.Bundle;\r\nimport android.util.DisplayMetrics;\r\nimport android.view.SurfaceHolder;\r\nimport android.view.SurfaceView;\r\nimport android.view.ViewTreeObserver;\r\nimport android.view.WindowInsets;\r\nimport android.view.WindowManager;\r\n\r\nimport org.libsdl.app.SDLActivity;\r\n\r\nimport java.io.File;\r\nimport java.util.Locale;\r\n\r\npublic class DevilutionXSDLActivity extends SDLActivity {\r\n\tprivate ExternalFilesManager fileManager;\r\n\tprivate boolean noExit;\r\n\r\n\tprotected void onCreate(Bundle savedInstanceState) {\r\n\t\t// windowSoftInputMode=adjustPan stopped working\r\n\t\t// for fullscreen apps after Android 7.0\r\n\t\tif (Build.VERSION.SDK_INT >= 25)\r\n\t\t\ttrackVisibleSpace();\r\n\r\n\t\t// Force app to overlap with the display cutout\r\n\t\tif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)\r\n\t\t\tgetWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;\r\n\r\n\t\tfileManager = new ExternalFilesManager(this);\r\n\r\n\t\tmigrateSaveGames();\r\n\r\n\t\tsuper.onCreate(savedInstanceState);\r\n\t}\r\n\r\n\t/**\r\n\t * On app launch make sure the game data is present\r\n\t */\r\n\tprotected void onStart() {\r\n\t\tsuper.onStart();\r\n\r\n\t\tif (isMissingGameData()) {\r\n\t\t\tIntent intent = new Intent(this, DataActivity.class);\r\n\t\t\tstartActivity(intent);\r\n\t\t\tnoExit = true;\r\n\t\t\tthis.finish();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * When the user exits the game, use System.exit(0)\r\n\t * to clear memory and prevent errors on restart\r\n\t */\r\n\tprotected void onDestroy() {\r\n\t\tsuper.onDestroy();\r\n\r\n\t\tif (!noExit) {\r\n\t\t\tSystem.exit(0);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void trackVisibleSpace() {\r\n\t\tthis.getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {\r\n\t\t\t@Override\r\n\t\t\tpublic void onGlobalLayout() {\r\n\t\t\t\tSurfaceView surface = mSurface;\r\n\t\t\t\tSurfaceHolder holder = surface.getHolder();\r\n\r\n\t\t\t\tif (!isIMEVisible()) {\r\n\t\t\t\t\tholder.setSizeFromLayout();\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Software keyboard may encroach on the app's visible space so\r\n\t\t\t\t// force the drawing surface to fit in the visible display frame\r\n\t\t\t\tRect visibleSpace = new Rect();\r\n\t\t\t\tgetVisibleSpaceAroundIME(visibleSpace);\r\n\t\t\t\tholder.setFixedSize(visibleSpace.width(), visibleSpace.height());\r\n\t\t\t}\r\n\r\n\t\t\tprivate boolean isIMEVisible() {\r\n\t\t\t\t// Window insets are not available before Android 11 so\r\n\t\t\t\t// we must always assume the software keyboard is visible\r\n\t\t\t\tif (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)\r\n\t\t\t\t\treturn true;\r\n\r\n\t\t\t\tWindowInsets rootInsets = getWindow().getDecorView().getRootWindowInsets();\r\n\t\t\t\treturn rootInsets.isVisible(WindowInsets.Type.ime());\r\n\t\t\t}\r\n\r\n\t\t\tprivate void getVisibleSpaceAroundIME(Rect visibleSpace) {\r\n\t\t\t\tif (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {\r\n\t\t\t\t\tgetWindow().getDecorView().getWindowVisibleDisplayFrame(visibleSpace);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tWindowInsets rootInsets = getWindow().getDecorView().getRootWindowInsets();\r\n\t\t\t\tInsets imeInsets = rootInsets.getInsets(WindowInsets.Type.ime());\r\n\t\t\t\tDisplayMetrics realMetrics = new DisplayMetrics();\r\n\t\t\t\tgetDisplay().getRealMetrics(realMetrics);\r\n\r\n\t\t\t\tvisibleSpace.top = imeInsets.top;\r\n\t\t\t\tvisibleSpace.left = imeInsets.left;\r\n\t\t\t\tvisibleSpace.right = realMetrics.widthPixels - imeInsets.right;\r\n\t\t\t\tvisibleSpace.bottom = realMetrics.heightPixels - imeInsets.bottom;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tprivate boolean isMissingGameData() {\r\n\t\tString lang = Locale.getDefault().toString();\r\n\t\tif (lang.startsWith(\"pl\") && !fileManager.hasFile(\"pl.mpq\"))\r\n\t\t\treturn true;\r\n\t\tif (lang.startsWith(\"ru\") && !fileManager.hasFile(\"ru.mpq\"))\r\n\t\t\treturn true;\r\n\t\tFile fonts_mpq = fileManager.getFile(\"/fonts.mpq\");\r\n\t\tif (lang.startsWith(\"ko\") || lang.startsWith(\"zh\") || lang.startsWith(\"ja\") || fonts_mpq.exists()) {\r\n\t\t\tif (!fonts_mpq.exists() || areFontsOutOfDate(fonts_mpq.getAbsolutePath()))\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\treturn !fileManager.hasFile(\"diabdat.mpq\") &&\r\n\t\t\t\t!fileManager.hasFile(\"DIABDAT.MPQ\") &&\r\n\t\t\t\t!fileManager.hasFile(\"spawn.mpq\");\r\n\t}\r\n\r\n\tprivate void migrateSaveGames() {\r\n\t\tFile[] files = getFilesDir().listFiles();\r\n\t\tif (files == null)\r\n\t\t\treturn;\r\n\t\tfor (File internalFile : files) {\r\n\t\t\tfileManager.migrateFile(internalFile);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * This method is called by SDL using JNI.\r\n\t */\r\n\tpublic String getLocale()\r\n\t{\r\n\t\treturn Locale.getDefault().toString();\r\n\t}\r\n\r\n\tprotected String[] getArguments() {\r\n\t\tString externalDir = fileManager.getExternalFilesDirectory();\r\n\r\n\t\tif (BuildConfig.DEBUG) {\r\n\t\t\treturn new String[]{\r\n\t\t\t\t\"--data-dir\",\r\n\t\t\t\texternalDir,\r\n\t\t\t\t\"--config-dir\",\r\n\t\t\t\texternalDir,\r\n\t\t\t\t\"--save-dir\",\r\n\t\t\t\texternalDir,\r\n\t\t\t\t\"--verbose\",\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\treturn new String[]{\r\n\t\t\t\"--data-dir\",\r\n\t\t\texternalDir,\r\n\t\t\t\"--config-dir\",\r\n\t\t\texternalDir,\r\n\t\t\t\"--save-dir\",\r\n\t\t\texternalDir\r\n\t\t};\r\n\t}\r\n\r\n\tprotected String[] getLibraries() {\r\n\t\treturn new String[]{\r\n\t\t\t\t\"devilutionx\"\r\n\t\t};\r\n\t}\r\n\r\n\tpublic static native boolean areFontsOutOfDate(String fonts_mpq);\r\n}\r\n"
  },
  {
    "path": "android-project/app/src/main/java/org/diasurgical/devilutionx/ExternalFilesManager.java",
    "content": "package org.diasurgical.devilutionx;\r\n\r\nimport android.content.Context;\r\nimport android.os.Build;\r\nimport android.util.Log;\r\n\r\nimport java.io.File;\r\nimport java.io.FileInputStream;\r\nimport java.io.FileOutputStream;\r\nimport java.io.IOException;\r\nimport java.io.InputStream;\r\nimport java.io.OutputStream;\r\nimport java.util.Objects;\r\n\r\npublic class ExternalFilesManager {\r\n\tprivate String externalFilesDirectory;\r\n\r\n\tpublic ExternalFilesManager(Context context) {\r\n\t\texternalFilesDirectory = chooseExternalFilesDirectory(context);\r\n\t}\r\n\r\n\tpublic String getExternalFilesDirectory() {\r\n\t\treturn externalFilesDirectory;\r\n\t}\r\n\r\n\tpublic boolean hasFile(String fileName) {\r\n\t\tFile file = getFile(fileName);\r\n\t\treturn file.exists();\r\n\t}\r\n\r\n\tpublic long fileSize(String fileName) {\r\n\t\tFile file = getFile(fileName);\r\n\t\treturn file.length();\r\n\t}\r\n\r\n\tpublic File getFile(String fileName) {\r\n\t\treturn new File(externalFilesDirectory + \"/\" + fileName);\r\n\t}\r\n\r\n\tpublic void migrateFile(File file) {\r\n\t\tFile newPath = new File(externalFilesDirectory + \"/\" + file.getName());\r\n\r\n\t\tif (newPath.exists()) {\r\n\t\t\tif (file.canWrite()) {\r\n\t\t\t\t//noinspection ResultOfMethodCallIgnored\r\n\t\t\t\tfile.delete();\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!file.renameTo(newPath)) {\r\n\t\t\tif (copyFile(file, newPath) && file.canWrite()) {\r\n\t\t\t\t//noinspection ResultOfMethodCallIgnored\r\n\t\t\t\tfile.delete();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate String chooseExternalFilesDirectory(Context context) {\r\n\t\tif (Build.VERSION.SDK_INT >= 19) {\r\n\t\t\tFile[] externalDirs = context.getExternalFilesDirs(null);\r\n\r\n\t\t\tfor (File dir : externalDirs) {\r\n\t\t\t\tif (dir == null) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tFile[] iniFiles = dir.listFiles((dir1, name) -> name.equals(\"diablo.ini\"));\r\n\t\t\t\tif (iniFiles != null && iniFiles.length > 0) {\r\n\t\t\t\t\treturn dir.getAbsolutePath();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfor (File dir : externalDirs) {\r\n\t\t\t\tif (dir == null) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tFile[] lastFiles = dir.listFiles();\r\n\t\t\t\tif (lastFiles != null && lastFiles.length > 0) {\r\n\t\t\t\t\treturn dir.getAbsolutePath();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Fallback to the primary external storage directory\r\n\t\treturn context.getExternalFilesDir(null).getAbsolutePath();\r\n\t}\r\n\r\n\tprivate boolean copyFile(File src, File dst) {\r\n\t\ttry {\r\n\t\t\tInputStream in = new FileInputStream(src);\r\n\t\t\ttry {\r\n\t\t\t\tOutputStream out = new FileOutputStream(dst);\r\n\t\t\t\ttry {\r\n\t\t\t\t\t// Transfer bytes from in to out\r\n\t\t\t\t\tbyte[] buf = new byte[1024];\r\n\t\t\t\t\tint len;\r\n\t\t\t\t\twhile ((len = in.read(buf)) > 0) {\r\n\t\t\t\t\t\tout.write(buf, 0, len);\r\n\t\t\t\t\t}\r\n\t\t\t\t} finally {\r\n\t\t\t\t\tout.close();\r\n\t\t\t\t}\r\n\t\t\t} finally {\r\n\t\t\t\tin.close();\r\n\t\t\t}\r\n\t\t} catch (IOException exception) {\r\n\t\t\tLog.e(\"copyFile\", Objects.requireNonNull(exception.getMessage()));\r\n\t\t\tif (dst.exists()) {\r\n\t\t\t\t//noinspection ResultOfMethodCallIgnored\r\n\t\t\t\tdst.delete();\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "android-project/app/src/main/java/org/diasurgical/devilutionx/ImportActivity.java",
    "content": "package org.diasurgical.devilutionx;\r\n\r\nimport android.app.Activity;\r\nimport android.app.AlertDialog;\r\nimport android.content.ClipData;\r\nimport android.content.ComponentName;\r\nimport android.content.ContentResolver;\r\nimport android.content.Intent;\r\nimport android.content.pm.PackageManager;\r\nimport android.net.Uri;\r\nimport android.os.Build;\r\nimport android.support.annotation.Nullable;\r\nimport android.os.Bundle;\r\nimport android.support.annotation.RequiresApi;\r\nimport android.support.v4.provider.DocumentFile;\r\nimport android.text.SpannableString;\r\nimport android.text.Spanned;\r\nimport android.text.method.LinkMovementMethod;\r\nimport android.text.style.URLSpan;\r\nimport android.util.Log;\r\nimport android.view.View;\r\nimport android.widget.TextView;\r\n\r\nimport java.io.File;\r\nimport java.io.FileOutputStream;\r\nimport java.io.IOException;\r\nimport java.io.InputStream;\r\nimport java.io.OutputStream;\r\nimport java.util.ArrayList;\r\n\r\npublic class ImportActivity extends Activity {\r\n\r\n\tprivate static final int IMPORT_REQUEST_CODE = 0xD1AB70;\r\n\tprivate static final String TV_STUB_PACKAGE = \"com.android.tv.frameworkpackagestubs\";\r\n\tprivate static final String RECOMMENDED_FILE_BROWSER = \"AnExplorer\";\r\n\tprivate static final String RECOMMENDED_FILE_BROWSER_PACKAGE = \"dev.dworks.apps.anexplorer\";\r\n\tprivate boolean userConfirmed = false;\r\n\r\n\t@RequiresApi(api = Build.VERSION_CODES.KITKAT)\r\n\t@Override\r\n\tprotected void onCreate(Bundle savedInstanceState) {\r\n\t\tsuper.onCreate(savedInstanceState);\r\n\r\n\t\tif (findFileBrowser()) {\r\n\t\t\trunFileBrowser();\r\n\t\t} else {\r\n\t\t\trecommendFileBrowser();\r\n\t\t}\r\n\t}\r\n\r\n\t@Override\r\n\tprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {\r\n\t\tif (requestCode != IMPORT_REQUEST_CODE)\r\n\t\t\treturn;\r\n\r\n\t\tif (resultCode == Activity.RESULT_OK && data != null) {\r\n\t\t\tArrayList<Uri> uriList = getItemUris(data.getClipData());\r\n\r\n\t\t\tUri dataUri = data.getData();\r\n\t\t\tif (dataUri != null)\r\n\t\t\t\turiList.add(dataUri);\r\n\r\n\t\t\tArrayList<String> fileNames = getFileNames(uriList);\r\n\t\t\tArrayList<String> overwrittenFiles = getOverwrittenFiles(fileNames);\r\n\t\t\tif (overwrittenFiles.isEmpty()) {\r\n\t\t\t\timportFiles(uriList);\r\n\t\t\t\tfinish();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tString overwrittenFileList = String.join(\"\\n\", overwrittenFiles);\r\n\t\t\tAlertDialog.Builder builder = new AlertDialog.Builder(this);\r\n\t\t\tbuilder.setMessage(getString(R.string.overwrite_query, overwrittenFileList));\r\n\t\t\tbuilder.setPositiveButton(R.string.continue_button, (dialog, which) -> { importFiles(uriList); });\r\n\t\t\tbuilder.setNegativeButton(R.string.cancel_button, null);\r\n\t\t\tbuilder.setOnDismissListener(dialog -> finish());\r\n\r\n\t\t\tAlertDialog dialog = builder.create();\r\n\t\t\tdialog.show();\r\n\t\t} else {\r\n\t\t\tsuper.onBackPressed();\r\n\t\t}\r\n\t}\r\n\r\n\tprivate boolean findFileBrowser() {\r\n\t\tIntent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);\r\n\t\tintent.addCategory(Intent.CATEGORY_OPENABLE);\r\n\t\tintent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);\r\n\t\tintent.setType(\"*/*\");\r\n\r\n\t\tPackageManager packageManager = getPackageManager();\r\n\t\tComponentName defaultPackage = intent.resolveActivity(packageManager);\r\n\t\treturn defaultPackage != null && !TV_STUB_PACKAGE.equals(defaultPackage.getPackageName());\r\n\t}\r\n\r\n\tprivate void recommendFileBrowser()\r\n\t{\r\n\t\tString noFileBrowserText = getString(R.string.no_file_browser);\r\n\t\tSpannableString message;\r\n\r\n\t\tboolean isTelevision = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);\r\n\t\tif (isTelevision) {\r\n\t\t\tString recommendation = getString(R.string.recommended_file_browser, RECOMMENDED_FILE_BROWSER);\r\n\t\t\tString messageText = noFileBrowserText + \" \" + recommendation;\r\n\t\t\tmessage = new SpannableString(messageText);\r\n\r\n\t\t\tint index = messageText.indexOf(RECOMMENDED_FILE_BROWSER);\r\n\t\t\tif (index >= 0) {\r\n\t\t\t\tString url = \"market://details?id=\" + RECOMMENDED_FILE_BROWSER_PACKAGE;\r\n\t\t\t\tURLSpan urlSpan = new URLSpan(url);\r\n\t\t\t\tmessage.setSpan(urlSpan, index, index + RECOMMENDED_FILE_BROWSER.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tmessage = new SpannableString(noFileBrowserText);\r\n\t\t}\r\n\r\n\t\tAlertDialog.Builder builder = new AlertDialog.Builder(this);\r\n\t\tbuilder.setMessage(message);\r\n\t\tbuilder.setPositiveButton(\"OK\", null);\r\n\t\tbuilder.setOnDismissListener(dialog -> {\r\n\t\t\tif (findFileBrowser()) {\r\n\t\t\t\trunFileBrowser();\r\n\t\t\t} else if (!isFinishing()) {\r\n\t\t\t\tfinish();\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tAlertDialog dialog = builder.create();\r\n\t\tdialog.show();\r\n\r\n\t\tView view = dialog.findViewById(android.R.id.message);\r\n\t\tif (view instanceof TextView) {\r\n\t\t\tTextView textView = (TextView)view;\r\n\t\t\ttextView.setMovementMethod(LinkMovementMethod.getInstance());\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void runFileBrowser() {\r\n\t\tExternalFilesManager fileManager = new ExternalFilesManager(this);\r\n\t\tString externalFilesDir =  fileManager.getExternalFilesDirectory();\r\n\r\n\t\tAlertDialog.Builder builder = new AlertDialog.Builder(this);\r\n\t\tbuilder.setMessage(getString(R.string.import_data_info, externalFilesDir));\r\n\t\tbuilder.setPositiveButton(R.string.ok_button, (dialog, which) -> {\r\n\t\t\tuserConfirmed = true;\r\n\t\t\tIntent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);\r\n\t\t\tintent.addCategory(Intent.CATEGORY_OPENABLE);\r\n\t\t\tintent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);\r\n\t\t\tintent.setType(\"*/*\");\r\n\t\t\tstartActivityForResult(intent, IMPORT_REQUEST_CODE);\r\n\t\t});\r\n\t\tbuilder.setOnDismissListener(dialog -> {\r\n\t\t\tif (!userConfirmed && !isFinishing()) finish();\r\n\t\t});\r\n\r\n\t\tAlertDialog dialog = builder.create();\r\n\t\tdialog.show();\r\n\t}\r\n\r\n\tprivate ArrayList<Uri> getItemUris(ClipData clipData) {\r\n\t\tArrayList<Uri> uriList = new ArrayList<>();\r\n\t\tif (clipData == null)\r\n\t\t\treturn uriList;\r\n\r\n\t\tfor (int i = 0; i < clipData.getItemCount(); i++) {\r\n\t\t\tClipData.Item item = clipData.getItemAt(i);\r\n\t\t\tif (item == null)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tUri itemUri = item.getUri();\r\n\t\t\tif (itemUri == null)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\turiList.add(itemUri);\r\n\t\t}\r\n\r\n\t\treturn uriList;\r\n\t}\r\n\r\n\tprivate ArrayList<String> getFileNames(ArrayList<Uri> uriList) {\r\n\t\tArrayList<String> fileNames = new ArrayList<>();\r\n\t\tfor (Uri uri : uriList) {\r\n\t\t\tDocumentFile file = DocumentFile.fromSingleUri(getApplicationContext(), uri);\r\n\t\t\tif (file == null)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tString fileName = file.getName();\r\n\t\t\tfileNames.add(fileName);\r\n\t\t}\r\n\t\treturn fileNames;\r\n\t}\r\n\r\n\tprivate ArrayList<String> getOverwrittenFiles(ArrayList<String> fileNames) {\r\n\t\tArrayList<String> overwrittenFiles = new ArrayList<>();\r\n\t\tExternalFilesManager fileManager = new ExternalFilesManager(this);\r\n\t\tfor (String fileName : fileNames) {\r\n\t\t\tif (fileManager.hasFile(fileName))\r\n\t\t\t\toverwrittenFiles.add(fileName);\r\n\t\t}\r\n\t\treturn overwrittenFiles;\r\n\t}\r\n\r\n\tprivate void importFiles(ArrayList<Uri> uriList) {\r\n\t\tfor (Uri uri : uriList)\r\n\t\t\timportFile(uri);\r\n\t}\r\n\r\n\tprivate void importFile(Uri fileUri) {\r\n\t\tif (fileUri == null)\r\n\t\t\treturn;\r\n\r\n\t\tDocumentFile file = DocumentFile.fromSingleUri(getApplicationContext(), fileUri);\r\n\t\tif (file == null)\r\n\t\t\treturn;\r\n\r\n\t\tString fileName = file.getName();\r\n\t\tExternalFilesManager fileManager = new ExternalFilesManager(this);\r\n\t\tFile externalFile = fileManager.getFile(fileName);\r\n\r\n\t\ttry {\r\n\t\t\tInputStream inputStream = null;\r\n\t\t\tOutputStream outputStream = null;\r\n\r\n\t\t\ttry {\r\n\t\t\t\tContentResolver contentResolver = getContentResolver();\r\n\t\t\t\tinputStream = contentResolver.openInputStream(fileUri);\r\n\t\t\t\toutputStream = new FileOutputStream(externalFile);\r\n\r\n\t\t\t\t// Transfer bytes from in to out\r\n\t\t\t\tbyte[] buf = new byte[4096];\r\n\t\t\t\tint len;\r\n\t\t\t\twhile ((len = inputStream.read(buf)) > 0) {\r\n\t\t\t\t\toutputStream.write(buf, 0, len);\r\n\t\t\t\t}\r\n\t\t\t} finally {\r\n\t\t\t\tif (inputStream != null)\r\n\t\t\t\t\tinputStream.close();\r\n\t\t\t\tif (outputStream != null)\r\n\t\t\t\t\toutputStream.close();\r\n\t\t\t}\r\n\t\t} catch (IOException exception) {\r\n\t\t\tString message = exception.getMessage();\r\n\t\t\tif (message == null) {\r\n\t\t\t\tLog.e(\"importFile\", \"IOException\", exception);\r\n\t\t\t} else {\r\n\t\t\t\tLog.e(\"importFile\", message);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/HIDDevice.java",
    "content": "package org.libsdl.app;\n\nimport android.hardware.usb.UsbDevice;\n\ninterface HIDDevice\n{\n    public int getId();\n    public int getVendorId();\n    public int getProductId();\n    public String getSerialNumber();\n    public int getVersion();\n    public String getManufacturerName();\n    public String getProductName();\n    public UsbDevice getDevice();\n    public boolean open();\n    public int sendFeatureReport(byte[] report);\n    public int sendOutputReport(byte[] report);\n    public boolean getFeatureReport(byte[] report);\n    public void setFrozen(boolean frozen);\n    public void close();\n    public void shutdown();\n}\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java",
    "content": "package org.libsdl.app;\n\nimport android.content.Context;\nimport android.bluetooth.BluetoothDevice;\nimport android.bluetooth.BluetoothGatt;\nimport android.bluetooth.BluetoothGattCallback;\nimport android.bluetooth.BluetoothGattCharacteristic;\nimport android.bluetooth.BluetoothGattDescriptor;\nimport android.bluetooth.BluetoothManager;\nimport android.bluetooth.BluetoothProfile;\nimport android.bluetooth.BluetoothGattService;\nimport android.hardware.usb.UsbDevice;\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.util.Log;\nimport android.os.*;\n\n//import com.android.internal.util.HexDump;\n\nimport java.lang.Runnable;\nimport java.util.Arrays;\nimport java.util.LinkedList;\nimport java.util.UUID;\n\nclass HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {\n\n    private static final String TAG = \"hidapi\";\n    private HIDDeviceManager mManager;\n    private BluetoothDevice mDevice;\n    private int mDeviceId;\n    private BluetoothGatt mGatt;\n    private boolean mIsRegistered = false;\n    private boolean mIsConnected = false;\n    private boolean mIsChromebook = false;\n    private boolean mIsReconnecting = false;\n    private boolean mFrozen = false;\n    private LinkedList<GattOperation> mOperations;\n    GattOperation mCurrentOperation = null;\n    private Handler mHandler;\n\n    private static final int TRANSPORT_AUTO = 0;\n    private static final int TRANSPORT_BREDR = 1;\n    private static final int TRANSPORT_LE = 2;\n\n    private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;\n\n    static public final UUID steamControllerService = UUID.fromString(\"100F6C32-1735-4313-B402-38567131E5F3\");\n    static public final UUID inputCharacteristic = UUID.fromString(\"100F6C33-1735-4313-B402-38567131E5F3\");\n    static public final UUID reportCharacteristic = UUID.fromString(\"100F6C34-1735-4313-B402-38567131E5F3\");\n    static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };\n\n    static class GattOperation {\n        private enum Operation {\n            CHR_READ,\n            CHR_WRITE,\n            ENABLE_NOTIFICATION\n        }\n\n        Operation mOp;\n        UUID mUuid;\n        byte[] mValue;\n        BluetoothGatt mGatt;\n        boolean mResult = true;\n\n        private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {\n            mGatt = gatt;\n            mOp = operation;\n            mUuid = uuid;\n        }\n\n        private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {\n            mGatt = gatt;\n            mOp = operation;\n            mUuid = uuid;\n            mValue = value;\n        }\n\n        public void run() {\n            // This is executed in main thread\n            BluetoothGattCharacteristic chr;\n\n            switch (mOp) {\n                case CHR_READ:\n                    chr = getCharacteristic(mUuid);\n                    //Log.v(TAG, \"Reading characteristic \" + chr.getUuid());\n                    if (!mGatt.readCharacteristic(chr)) {\n                        Log.e(TAG, \"Unable to read characteristic \" + mUuid.toString());\n                        mResult = false;\n                        break;\n                    }\n                    mResult = true;\n                    break;\n                case CHR_WRITE:\n                    chr = getCharacteristic(mUuid);\n                    //Log.v(TAG, \"Writing characteristic \" + chr.getUuid() + \" value=\" + HexDump.toHexString(value));\n                    chr.setValue(mValue);\n                    if (!mGatt.writeCharacteristic(chr)) {\n                        Log.e(TAG, \"Unable to write characteristic \" + mUuid.toString());\n                        mResult = false;\n                        break;\n                    }\n                    mResult = true;\n                    break;\n                case ENABLE_NOTIFICATION:\n                    chr = getCharacteristic(mUuid);\n                    //Log.v(TAG, \"Writing descriptor of \" + chr.getUuid());\n                    if (chr != null) {\n                        BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString(\"00002902-0000-1000-8000-00805f9b34fb\"));\n                        if (cccd != null) {\n                            int properties = chr.getProperties();\n                            byte[] value;\n                            if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == BluetoothGattCharacteristic.PROPERTY_NOTIFY) {\n                                value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;\n                            } else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) == BluetoothGattCharacteristic.PROPERTY_INDICATE) {\n                                value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;\n                            } else {\n                                Log.e(TAG, \"Unable to start notifications on input characteristic\");\n                                mResult = false;\n                                return;\n                            }\n\n                            mGatt.setCharacteristicNotification(chr, true);\n                            cccd.setValue(value);\n                            if (!mGatt.writeDescriptor(cccd)) {\n                                Log.e(TAG, \"Unable to write descriptor \" + mUuid.toString());\n                                mResult = false;\n                                return;\n                            }\n                            mResult = true;\n                        }\n                    }\n            }\n        }\n\n        public boolean finish() {\n            return mResult;\n        }\n\n        private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {\n            BluetoothGattService valveService = mGatt.getService(steamControllerService);\n            if (valveService == null)\n                return null;\n            return valveService.getCharacteristic(uuid);\n        }\n\n        static public GattOperation readCharacteristic(BluetoothGatt gatt, UUID uuid) {\n            return new GattOperation(gatt, Operation.CHR_READ, uuid);\n        }\n\n        static public GattOperation writeCharacteristic(BluetoothGatt gatt, UUID uuid, byte[] value) {\n            return new GattOperation(gatt, Operation.CHR_WRITE, uuid, value);\n        }\n\n        static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {\n            return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);\n        }\n    }\n\n    public HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {\n        mManager = manager;\n        mDevice = device;\n        mDeviceId = mManager.getDeviceIDForIdentifier(getIdentifier());\n        mIsRegistered = false;\n        mIsChromebook = mManager.getContext().getPackageManager().hasSystemFeature(\"org.chromium.arc.device_management\");\n        mOperations = new LinkedList<GattOperation>();\n        mHandler = new Handler(Looper.getMainLooper());\n\n        mGatt = connectGatt();\n        // final HIDDeviceBLESteamController finalThis = this;\n        // mHandler.postDelayed(new Runnable() {\n        //     @Override\n        //     public void run() {\n        //         finalThis.checkConnectionForChromebookIssue();\n        //     }\n        // }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL);\n    }\n\n    public String getIdentifier() {\n        return String.format(\"SteamController.%s\", mDevice.getAddress());\n    }\n\n    public BluetoothGatt getGatt() {\n        return mGatt;\n    }\n\n    // Because on Chromebooks we show up as a dual-mode device, it will attempt to connect TRANSPORT_AUTO, which will use TRANSPORT_BREDR instead\n    // of TRANSPORT_LE.  Let's force ourselves to connect low energy.\n    private BluetoothGatt connectGatt(boolean managed) {\n        if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) {\n            try {\n                return mDevice.connectGatt(mManager.getContext(), managed, this, TRANSPORT_LE);\n            } catch (Exception e) {\n                return mDevice.connectGatt(mManager.getContext(), managed, this);\n            }\n        } else {\n            return mDevice.connectGatt(mManager.getContext(), managed, this);\n        }\n    }\n\n    private BluetoothGatt connectGatt() {\n        return connectGatt(false);\n    }\n\n    protected int getConnectionState() {\n\n        Context context = mManager.getContext();\n        if (context == null) {\n            // We are lacking any context to get our Bluetooth information.  We'll just assume disconnected.\n            return BluetoothProfile.STATE_DISCONNECTED;\n        }\n\n        BluetoothManager btManager = (BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE);\n        if (btManager == null) {\n            // This device doesn't support Bluetooth.  We should never be here, because how did\n            // we instantiate a device to start with?\n            return BluetoothProfile.STATE_DISCONNECTED;\n        }\n\n        return btManager.getConnectionState(mDevice, BluetoothProfile.GATT);\n    }\n\n    public void reconnect() {\n\n        if (getConnectionState() != BluetoothProfile.STATE_CONNECTED) {\n            mGatt.disconnect();\n            mGatt = connectGatt();\n        }\n\n    }\n\n    protected void checkConnectionForChromebookIssue() {\n        if (!mIsChromebook) {\n            // We only do this on Chromebooks, because otherwise it's really annoying to just attempt\n            // over and over.\n            return;\n        }\n\n        int connectionState = getConnectionState();\n\n        switch (connectionState) {\n            case BluetoothProfile.STATE_CONNECTED:\n                if (!mIsConnected) {\n                    // We are in the Bad Chromebook Place.  We can force a disconnect\n                    // to try to recover.\n                    Log.v(TAG, \"Chromebook: We are in a very bad state; the controller shows as connected in the underlying Bluetooth layer, but we never received a callback.  Forcing a reconnect.\");\n                    mIsReconnecting = true;\n                    mGatt.disconnect();\n                    mGatt = connectGatt(false);\n                    break;\n                }\n                else if (!isRegistered()) {\n                    if (mGatt.getServices().size() > 0) {\n                        Log.v(TAG, \"Chromebook: We are connected to a controller, but never got our registration.  Trying to recover.\");\n                        probeService(this);\n                    }\n                    else {\n                        Log.v(TAG, \"Chromebook: We are connected to a controller, but never discovered services.  Trying to recover.\");\n                        mIsReconnecting = true;\n                        mGatt.disconnect();\n                        mGatt = connectGatt(false);\n                        break;\n                    }\n                }\n                else {\n                    Log.v(TAG, \"Chromebook: We are connected, and registered.  Everything's good!\");\n                    return;\n                }\n                break;\n\n            case BluetoothProfile.STATE_DISCONNECTED:\n                Log.v(TAG, \"Chromebook: We have either been disconnected, or the Chromebook BtGatt.ContextMap bug has bitten us.  Attempting a disconnect/reconnect, but we may not be able to recover.\");\n\n                mIsReconnecting = true;\n                mGatt.disconnect();\n                mGatt = connectGatt(false);\n                break;\n\n            case BluetoothProfile.STATE_CONNECTING:\n                Log.v(TAG, \"Chromebook: We're still trying to connect.  Waiting a bit longer.\");\n                break;\n        }\n\n        final HIDDeviceBLESteamController finalThis = this;\n        mHandler.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                finalThis.checkConnectionForChromebookIssue();\n            }\n        }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL);\n    }\n\n    private boolean isRegistered() {\n        return mIsRegistered;\n    }\n\n    private void setRegistered() {\n        mIsRegistered = true;\n    }\n\n    private boolean probeService(HIDDeviceBLESteamController controller) {\n\n        if (isRegistered()) {\n            return true;\n        }\n\n        if (!mIsConnected) {\n            return false;\n        }\n\n        Log.v(TAG, \"probeService controller=\" + controller);\n\n        for (BluetoothGattService service : mGatt.getServices()) {\n            if (service.getUuid().equals(steamControllerService)) {\n                Log.v(TAG, \"Found Valve steam controller service \" + service.getUuid());\n\n                for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {\n                    if (chr.getUuid().equals(inputCharacteristic)) {\n                        Log.v(TAG, \"Found input characteristic\");\n                        // Start notifications\n                        BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString(\"00002902-0000-1000-8000-00805f9b34fb\"));\n                        if (cccd != null) {\n                            enableNotification(chr.getUuid());\n                        }\n                    }\n                }\n                return true;\n            }\n        }\n\n        if ((mGatt.getServices().size() == 0) && mIsChromebook && !mIsReconnecting) {\n            Log.e(TAG, \"Chromebook: Discovered services were empty; this almost certainly means the BtGatt.ContextMap bug has bitten us.\");\n            mIsConnected = false;\n            mIsReconnecting = true;\n            mGatt.disconnect();\n            mGatt = connectGatt(false);\n        }\n\n        return false;\n    }\n\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n\n    private void finishCurrentGattOperation() {\n        GattOperation op = null;\n        synchronized (mOperations) {\n            if (mCurrentOperation != null) {\n                op = mCurrentOperation;\n                mCurrentOperation = null;\n            }\n        }\n        if (op != null) {\n            boolean result = op.finish(); // TODO: Maybe in main thread as well?\n\n            // Our operation failed, let's add it back to the beginning of our queue.\n            if (!result) {\n                mOperations.addFirst(op);\n            }\n        }\n        executeNextGattOperation();\n    }\n\n    private void executeNextGattOperation() {\n        synchronized (mOperations) {\n            if (mCurrentOperation != null)\n                return;\n\n            if (mOperations.isEmpty())\n                return;\n\n            mCurrentOperation = mOperations.removeFirst();\n        }\n\n        // Run in main thread\n        mHandler.post(new Runnable() {\n            @Override\n            public void run() {\n                synchronized (mOperations) {\n                    if (mCurrentOperation == null) {\n                        Log.e(TAG, \"Current operation null in executor?\");\n                        return;\n                    }\n\n                    mCurrentOperation.run();\n                    // now wait for the GATT callback and when it comes, finish this operation\n                }\n            }\n        });\n    }\n\n    private void queueGattOperation(GattOperation op) {\n        synchronized (mOperations) {\n            mOperations.add(op);\n        }\n        executeNextGattOperation();\n    }\n\n    private void enableNotification(UUID chrUuid) {\n        GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);\n        queueGattOperation(op);\n    }\n\n    public void writeCharacteristic(UUID uuid, byte[] value) {\n        GattOperation op = HIDDeviceBLESteamController.GattOperation.writeCharacteristic(mGatt, uuid, value);\n        queueGattOperation(op);\n    }\n\n    public void readCharacteristic(UUID uuid) {\n        GattOperation op = HIDDeviceBLESteamController.GattOperation.readCharacteristic(mGatt, uuid);\n        queueGattOperation(op);\n    }\n\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    //////////////  BluetoothGattCallback overridden methods\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n\n    public void onConnectionStateChange(BluetoothGatt g, int status, int newState) {\n        //Log.v(TAG, \"onConnectionStateChange status=\" + status + \" newState=\" + newState);\n        mIsReconnecting = false;\n        if (newState == 2) {\n            mIsConnected = true;\n            // Run directly, without GattOperation\n            if (!isRegistered()) {\n                mHandler.post(new Runnable() {\n                    @Override\n                    public void run() {\n                        mGatt.discoverServices();\n                    }\n                });\n            }\n        }\n        else if (newState == 0) {\n            mIsConnected = false;\n        }\n\n        // Disconnection is handled in SteamLink using the ACTION_ACL_DISCONNECTED Intent.\n    }\n\n    public void onServicesDiscovered(BluetoothGatt gatt, int status) {\n        //Log.v(TAG, \"onServicesDiscovered status=\" + status);\n        if (status == 0) {\n            if (gatt.getServices().size() == 0) {\n                Log.v(TAG, \"onServicesDiscovered returned zero services; something has gone horribly wrong down in Android's Bluetooth stack.\");\n                mIsReconnecting = true;\n                mIsConnected = false;\n                gatt.disconnect();\n                mGatt = connectGatt(false);\n            }\n            else {\n                probeService(this);\n            }\n        }\n    }\n\n    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {\n        //Log.v(TAG, \"onCharacteristicRead status=\" + status + \" uuid=\" + characteristic.getUuid());\n\n        if (characteristic.getUuid().equals(reportCharacteristic) && !mFrozen) {\n            mManager.HIDDeviceFeatureReport(getId(), characteristic.getValue());\n        }\n\n        finishCurrentGattOperation();\n    }\n\n    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {\n        //Log.v(TAG, \"onCharacteristicWrite status=\" + status + \" uuid=\" + characteristic.getUuid());\n\n        if (characteristic.getUuid().equals(reportCharacteristic)) {\n            // Only register controller with the native side once it has been fully configured\n            if (!isRegistered()) {\n                Log.v(TAG, \"Registering Steam Controller with ID: \" + getId());\n                mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0);\n                setRegistered();\n            }\n        }\n\n        finishCurrentGattOperation();\n    }\n\n    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {\n    // Enable this for verbose logging of controller input reports\n        //Log.v(TAG, \"onCharacteristicChanged uuid=\" + characteristic.getUuid() + \" data=\" + HexDump.dumpHexString(characteristic.getValue()));\n\n        if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {\n            mManager.HIDDeviceInputReport(getId(), characteristic.getValue());\n        }\n    }\n\n    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {\n        //Log.v(TAG, \"onDescriptorRead status=\" + status);\n    }\n\n    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {\n        BluetoothGattCharacteristic chr = descriptor.getCharacteristic();\n        //Log.v(TAG, \"onDescriptorWrite status=\" + status + \" uuid=\" + chr.getUuid() + \" descriptor=\" + descriptor.getUuid());\n\n        if (chr.getUuid().equals(inputCharacteristic)) {\n            boolean hasWrittenInputDescriptor = true;\n            BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);\n            if (reportChr != null) {\n                Log.v(TAG, \"Writing report characteristic to enter valve mode\");\n                reportChr.setValue(enterValveMode);\n                gatt.writeCharacteristic(reportChr);\n            }\n        }\n\n        finishCurrentGattOperation();\n    }\n\n    public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {\n        //Log.v(TAG, \"onReliableWriteCompleted status=\" + status);\n    }\n\n    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {\n        //Log.v(TAG, \"onReadRemoteRssi status=\" + status);\n    }\n\n    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {\n        //Log.v(TAG, \"onMtuChanged status=\" + status);\n    }\n\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    //////// Public API\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n\n    @Override\n    public int getId() {\n        return mDeviceId;\n    }\n\n    @Override\n    public int getVendorId() {\n        // Valve Corporation\n        final int VALVE_USB_VID = 0x28DE;\n        return VALVE_USB_VID;\n    }\n\n    @Override\n    public int getProductId() {\n        // We don't have an easy way to query from the Bluetooth device, but we know what it is\n        final int D0G_BLE2_PID = 0x1106;\n        return D0G_BLE2_PID;\n    }\n\n    @Override\n    public String getSerialNumber() {\n        // This will be read later via feature report by Steam\n        return \"12345\";\n    }\n\n    @Override\n    public int getVersion() {\n        return 0;\n    }\n\n    @Override\n    public String getManufacturerName() {\n        return \"Valve Corporation\";\n    }\n\n    @Override\n    public String getProductName() {\n        return \"Steam Controller\";\n    }\n\n    @Override\n    public UsbDevice getDevice() {\n        return null;\n    }\n\n    @Override\n    public boolean open() {\n        return true;\n    }\n\n    @Override\n    public int sendFeatureReport(byte[] report) {\n        if (!isRegistered()) {\n            Log.e(TAG, \"Attempted sendFeatureReport before Steam Controller is registered!\");\n            if (mIsConnected) {\n                probeService(this);\n            }\n            return -1;\n        }\n\n        // We need to skip the first byte, as that doesn't go over the air\n        byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);\n        //Log.v(TAG, \"sendFeatureReport \" + HexDump.dumpHexString(actual_report));\n        writeCharacteristic(reportCharacteristic, actual_report);\n        return report.length;\n    }\n\n    @Override\n    public int sendOutputReport(byte[] report) {\n        if (!isRegistered()) {\n            Log.e(TAG, \"Attempted sendOutputReport before Steam Controller is registered!\");\n            if (mIsConnected) {\n                probeService(this);\n            }\n            return -1;\n        }\n\n        //Log.v(TAG, \"sendFeatureReport \" + HexDump.dumpHexString(report));\n        writeCharacteristic(reportCharacteristic, report);\n        return report.length;\n    }\n\n    @Override\n    public boolean getFeatureReport(byte[] report) {\n        if (!isRegistered()) {\n            Log.e(TAG, \"Attempted getFeatureReport before Steam Controller is registered!\");\n            if (mIsConnected) {\n                probeService(this);\n            }\n            return false;\n        }\n\n        //Log.v(TAG, \"getFeatureReport\");\n        readCharacteristic(reportCharacteristic);\n        return true;\n    }\n\n    @Override\n    public void close() {\n    }\n\n    @Override\n    public void setFrozen(boolean frozen) {\n        mFrozen = frozen;\n    }\n\n    @Override\n    public void shutdown() {\n        close();\n\n        BluetoothGatt g = mGatt;\n        if (g != null) {\n            g.disconnect();\n            g.close();\n            mGatt = null;\n        }\n        mManager = null;\n        mIsRegistered = false;\n        mIsConnected = false;\n        mOperations.clear();\n    }\n\n}\n\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java",
    "content": "package org.libsdl.app;\n\nimport android.app.Activity;\nimport android.app.AlertDialog;\nimport android.app.PendingIntent;\nimport android.bluetooth.BluetoothAdapter;\nimport android.bluetooth.BluetoothDevice;\nimport android.bluetooth.BluetoothManager;\nimport android.bluetooth.BluetoothProfile;\nimport android.os.Build;\nimport android.util.Log;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.content.SharedPreferences;\nimport android.content.pm.PackageManager;\nimport android.hardware.usb.*;\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\n\npublic class HIDDeviceManager {\n    private static final String TAG = \"hidapi\";\n    private static final String ACTION_USB_PERMISSION = \"org.libsdl.app.USB_PERMISSION\";\n\n    private static HIDDeviceManager sManager;\n    private static int sManagerRefCount = 0;\n\n    public static HIDDeviceManager acquire(Context context) {\n        if (sManagerRefCount == 0) {\n            sManager = new HIDDeviceManager(context);\n        }\n        ++sManagerRefCount;\n        return sManager;\n    }\n\n    public static void release(HIDDeviceManager manager) {\n        if (manager == sManager) {\n            --sManagerRefCount;\n            if (sManagerRefCount == 0) {\n                sManager.close();\n                sManager = null;\n            }\n        }\n    }\n\n    private Context mContext;\n    private HashMap<Integer, HIDDevice> mDevicesById = new HashMap<Integer, HIDDevice>();\n    private HashMap<BluetoothDevice, HIDDeviceBLESteamController> mBluetoothDevices = new HashMap<BluetoothDevice, HIDDeviceBLESteamController>();\n    private int mNextDeviceId = 0;\n    private SharedPreferences mSharedPreferences = null;\n    private boolean mIsChromebook = false;\n    private UsbManager mUsbManager;\n    private Handler mHandler;\n    private BluetoothManager mBluetoothManager;\n    private List<BluetoothDevice> mLastBluetoothDevices;\n\n    private final BroadcastReceiver mUsbBroadcast = new BroadcastReceiver() {\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            String action = intent.getAction();\n            if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {\n                UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);\n                handleUsbDeviceAttached(usbDevice);\n            } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {\n                UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);\n                handleUsbDeviceDetached(usbDevice);\n            } else if (action.equals(HIDDeviceManager.ACTION_USB_PERMISSION)) {\n                UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);\n                handleUsbDevicePermission(usbDevice, intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false));\n            }\n        }\n    };\n\n    private final BroadcastReceiver mBluetoothBroadcast = new BroadcastReceiver() {\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            String action = intent.getAction();\n            // Bluetooth device was connected. If it was a Steam Controller, handle it\n            if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {\n                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);\n                Log.d(TAG, \"Bluetooth device connected: \" + device);\n\n                if (isSteamController(device)) {\n                    connectBluetoothDevice(device);\n                }\n            }\n\n            // Bluetooth device was disconnected, remove from controller manager (if any)\n            if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {\n                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);\n                Log.d(TAG, \"Bluetooth device disconnected: \" + device);\n\n                disconnectBluetoothDevice(device);\n            }\n        }\n    };\n\n    private HIDDeviceManager(final Context context) {\n        mContext = context;\n\n        HIDDeviceRegisterCallback();\n\n        mSharedPreferences = mContext.getSharedPreferences(\"hidapi\", Context.MODE_PRIVATE);\n        mIsChromebook = mContext.getPackageManager().hasSystemFeature(\"org.chromium.arc.device_management\");\n\n//        if (shouldClear) {\n//            SharedPreferences.Editor spedit = mSharedPreferences.edit();\n//            spedit.clear();\n//            spedit.commit();\n//        }\n//        else\n        {\n            mNextDeviceId = mSharedPreferences.getInt(\"next_device_id\", 0);\n        }\n    }\n\n    public Context getContext() {\n        return mContext;\n    }\n\n    public int getDeviceIDForIdentifier(String identifier) {\n        SharedPreferences.Editor spedit = mSharedPreferences.edit();\n\n        int result = mSharedPreferences.getInt(identifier, 0);\n        if (result == 0) {\n            result = mNextDeviceId++;\n            spedit.putInt(\"next_device_id\", mNextDeviceId);\n        }\n\n        spedit.putInt(identifier, result);\n        spedit.commit();\n        return result;\n    }\n\n    private void initializeUSB() {\n        mUsbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);\n        if (mUsbManager == null) {\n            return;\n        }\n\n        /*\n        // Logging\n        for (UsbDevice device : mUsbManager.getDeviceList().values()) {\n            Log.i(TAG,\"Path: \" + device.getDeviceName());\n            Log.i(TAG,\"Manufacturer: \" + device.getManufacturerName());\n            Log.i(TAG,\"Product: \" + device.getProductName());\n            Log.i(TAG,\"ID: \" + device.getDeviceId());\n            Log.i(TAG,\"Class: \" + device.getDeviceClass());\n            Log.i(TAG,\"Protocol: \" + device.getDeviceProtocol());\n            Log.i(TAG,\"Vendor ID \" + device.getVendorId());\n            Log.i(TAG,\"Product ID: \" + device.getProductId());\n            Log.i(TAG,\"Interface count: \" + device.getInterfaceCount());\n            Log.i(TAG,\"---------------------------------------\");\n\n            // Get interface details\n            for (int index = 0; index < device.getInterfaceCount(); index++) {\n                UsbInterface mUsbInterface = device.getInterface(index);\n                Log.i(TAG,\"  *****     *****\");\n                Log.i(TAG,\"  Interface index: \" + index);\n                Log.i(TAG,\"  Interface ID: \" + mUsbInterface.getId());\n                Log.i(TAG,\"  Interface class: \" + mUsbInterface.getInterfaceClass());\n                Log.i(TAG,\"  Interface subclass: \" + mUsbInterface.getInterfaceSubclass());\n                Log.i(TAG,\"  Interface protocol: \" + mUsbInterface.getInterfaceProtocol());\n                Log.i(TAG,\"  Endpoint count: \" + mUsbInterface.getEndpointCount());\n\n                // Get endpoint details\n                for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++)\n                {\n                    UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);\n                    Log.i(TAG,\"    ++++   ++++   ++++\");\n                    Log.i(TAG,\"    Endpoint index: \" + epi);\n                    Log.i(TAG,\"    Attributes: \" + mEndpoint.getAttributes());\n                    Log.i(TAG,\"    Direction: \" + mEndpoint.getDirection());\n                    Log.i(TAG,\"    Number: \" + mEndpoint.getEndpointNumber());\n                    Log.i(TAG,\"    Interval: \" + mEndpoint.getInterval());\n                    Log.i(TAG,\"    Packet size: \" + mEndpoint.getMaxPacketSize());\n                    Log.i(TAG,\"    Type: \" + mEndpoint.getType());\n                }\n            }\n        }\n        Log.i(TAG,\" No more devices connected.\");\n        */\n\n        // Register for USB broadcasts and permission completions\n        IntentFilter filter = new IntentFilter();\n        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);\n        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);\n        filter.addAction(HIDDeviceManager.ACTION_USB_PERMISSION);\n        mContext.registerReceiver(mUsbBroadcast, filter);\n\n        for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {\n            handleUsbDeviceAttached(usbDevice);\n        }\n    }\n\n    UsbManager getUSBManager() {\n        return mUsbManager;\n    }\n\n    private void shutdownUSB() {\n        try {\n            mContext.unregisterReceiver(mUsbBroadcast);\n        } catch (Exception e) {\n            // We may not have registered, that's okay\n        }\n    }\n\n    private boolean isHIDDeviceInterface(UsbDevice usbDevice, UsbInterface usbInterface) {\n        if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {\n            return true;\n        }\n        if (isXbox360Controller(usbDevice, usbInterface) || isXboxOneController(usbDevice, usbInterface)) {\n            return true;\n        }\n        return false;\n    }\n\n    private boolean isXbox360Controller(UsbDevice usbDevice, UsbInterface usbInterface) {\n        final int XB360_IFACE_SUBCLASS = 93;\n        final int XB360_IFACE_PROTOCOL = 1; // Wired\n        final int XB360W_IFACE_PROTOCOL = 129; // Wireless\n        final int[] SUPPORTED_VENDORS = {\n            0x0079, // GPD Win 2\n            0x044f, // Thrustmaster\n            0x045e, // Microsoft\n            0x046d, // Logitech\n            0x056e, // Elecom\n            0x06a3, // Saitek\n            0x0738, // Mad Catz\n            0x07ff, // Mad Catz\n            0x0e6f, // PDP\n            0x0f0d, // Hori\n            0x1038, // SteelSeries\n            0x11c9, // Nacon\n            0x12ab, // Unknown\n            0x1430, // RedOctane\n            0x146b, // BigBen\n            0x1532, // Razer Sabertooth\n            0x15e4, // Numark\n            0x162e, // Joytech\n            0x1689, // Razer Onza\n            0x1949, // Lab126, Inc.\n            0x1bad, // Harmonix\n            0x20d6, // PowerA\n            0x24c6, // PowerA\n            0x2c22, // Qanba\n            0x2dc8, // 8BitDo\n            0x9886, // ASTRO Gaming\n        };\n\n        if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&\n            usbInterface.getInterfaceSubclass() == XB360_IFACE_SUBCLASS &&\n            (usbInterface.getInterfaceProtocol() == XB360_IFACE_PROTOCOL ||\n             usbInterface.getInterfaceProtocol() == XB360W_IFACE_PROTOCOL)) {\n            int vendor_id = usbDevice.getVendorId();\n            for (int supportedVid : SUPPORTED_VENDORS) {\n                if (vendor_id == supportedVid) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterface) {\n        final int XB1_IFACE_SUBCLASS = 71;\n        final int XB1_IFACE_PROTOCOL = 208;\n        final int[] SUPPORTED_VENDORS = {\n            0x03f0, // HP\n            0x044f, // Thrustmaster\n            0x045e, // Microsoft\n            0x0738, // Mad Catz\n            0x0b05, // ASUS\n            0x0e6f, // PDP\n            0x0f0d, // Hori\n            0x10f5, // Turtle Beach\n            0x1532, // Razer Wildcat\n            0x20d6, // PowerA\n            0x24c6, // PowerA\n            0x2dc8, // 8BitDo\n            0x2e24, // Hyperkin\n            0x3537, // GameSir\n        };\n\n        if (usbInterface.getId() == 0 &&\n            usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&\n            usbInterface.getInterfaceSubclass() == XB1_IFACE_SUBCLASS &&\n            usbInterface.getInterfaceProtocol() == XB1_IFACE_PROTOCOL) {\n            int vendor_id = usbDevice.getVendorId();\n            for (int supportedVid : SUPPORTED_VENDORS) {\n                if (vendor_id == supportedVid) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private void handleUsbDeviceAttached(UsbDevice usbDevice) {\n        connectHIDDeviceUSB(usbDevice);\n    }\n\n    private void handleUsbDeviceDetached(UsbDevice usbDevice) {\n        List<Integer> devices = new ArrayList<Integer>();\n        for (HIDDevice device : mDevicesById.values()) {\n            if (usbDevice.equals(device.getDevice())) {\n                devices.add(device.getId());\n            }\n        }\n        for (int id : devices) {\n            HIDDevice device = mDevicesById.get(id);\n            mDevicesById.remove(id);\n            device.shutdown();\n            HIDDeviceDisconnected(id);\n        }\n    }\n\n    private void handleUsbDevicePermission(UsbDevice usbDevice, boolean permission_granted) {\n        for (HIDDevice device : mDevicesById.values()) {\n            if (usbDevice.equals(device.getDevice())) {\n                boolean opened = false;\n                if (permission_granted) {\n                    opened = device.open();\n                }\n                HIDDeviceOpenResult(device.getId(), opened);\n            }\n        }\n    }\n\n    private void connectHIDDeviceUSB(UsbDevice usbDevice) {\n        synchronized (this) {\n            int interface_mask = 0;\n            for (int interface_index = 0; interface_index < usbDevice.getInterfaceCount(); interface_index++) {\n                UsbInterface usbInterface = usbDevice.getInterface(interface_index);\n                if (isHIDDeviceInterface(usbDevice, usbInterface)) {\n                    // Check to see if we've already added this interface\n                    // This happens with the Xbox Series X controller which has a duplicate interface 0, which is inactive\n                    int interface_id = usbInterface.getId();\n                    if ((interface_mask & (1 << interface_id)) != 0) {\n                        continue;\n                    }\n                    interface_mask |= (1 << interface_id);\n\n                    HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);\n                    int id = device.getId();\n                    mDevicesById.put(id, device);\n                    HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol());\n                }\n            }\n        }\n    }\n\n    private void initializeBluetooth() {\n        Log.d(TAG, \"Initializing Bluetooth\");\n\n        if (Build.VERSION.SDK_INT >= 31 /* Android 12  */ &&\n            mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {\n            Log.d(TAG, \"Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT\");\n            return;\n        }\n\n        if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ &&\n            mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {\n            Log.d(TAG, \"Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH\");\n            return;\n        }\n\n        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18 /* Android 4.3 (JELLY_BEAN_MR2) */)) {\n            Log.d(TAG, \"Couldn't initialize Bluetooth, this version of Android does not support Bluetooth LE\");\n            return;\n        }\n\n        // Find bonded bluetooth controllers and create SteamControllers for them\n        mBluetoothManager = (BluetoothManager)mContext.getSystemService(Context.BLUETOOTH_SERVICE);\n        if (mBluetoothManager == null) {\n            // This device doesn't support Bluetooth.\n            return;\n        }\n\n        BluetoothAdapter btAdapter = mBluetoothManager.getAdapter();\n        if (btAdapter == null) {\n            // This device has Bluetooth support in the codebase, but has no available adapters.\n            return;\n        }\n\n        // Get our bonded devices.\n        for (BluetoothDevice device : btAdapter.getBondedDevices()) {\n\n            Log.d(TAG, \"Bluetooth device available: \" + device);\n            if (isSteamController(device)) {\n                connectBluetoothDevice(device);\n            }\n\n        }\n\n        // NOTE: These don't work on Chromebooks, to my undying dismay.\n        IntentFilter filter = new IntentFilter();\n        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);\n        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);\n        mContext.registerReceiver(mBluetoothBroadcast, filter);\n\n        if (mIsChromebook) {\n            mHandler = new Handler(Looper.getMainLooper());\n            mLastBluetoothDevices = new ArrayList<BluetoothDevice>();\n\n            // final HIDDeviceManager finalThis = this;\n            // mHandler.postDelayed(new Runnable() {\n            //     @Override\n            //     public void run() {\n            //         finalThis.chromebookConnectionHandler();\n            //     }\n            // }, 5000);\n        }\n    }\n\n    private void shutdownBluetooth() {\n        try {\n            mContext.unregisterReceiver(mBluetoothBroadcast);\n        } catch (Exception e) {\n            // We may not have registered, that's okay\n        }\n    }\n\n    // Chromebooks do not pass along ACTION_ACL_CONNECTED / ACTION_ACL_DISCONNECTED properly.\n    // This function provides a sort of dummy version of that, watching for changes in the\n    // connected devices and attempting to add controllers as things change.\n    public void chromebookConnectionHandler() {\n        if (!mIsChromebook) {\n            return;\n        }\n\n        ArrayList<BluetoothDevice> disconnected = new ArrayList<BluetoothDevice>();\n        ArrayList<BluetoothDevice> connected = new ArrayList<BluetoothDevice>();\n\n        List<BluetoothDevice> currentConnected = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT);\n\n        for (BluetoothDevice bluetoothDevice : currentConnected) {\n            if (!mLastBluetoothDevices.contains(bluetoothDevice)) {\n                connected.add(bluetoothDevice);\n            }\n        }\n        for (BluetoothDevice bluetoothDevice : mLastBluetoothDevices) {\n            if (!currentConnected.contains(bluetoothDevice)) {\n                disconnected.add(bluetoothDevice);\n            }\n        }\n\n        mLastBluetoothDevices = currentConnected;\n\n        for (BluetoothDevice bluetoothDevice : disconnected) {\n            disconnectBluetoothDevice(bluetoothDevice);\n        }\n        for (BluetoothDevice bluetoothDevice : connected) {\n            connectBluetoothDevice(bluetoothDevice);\n        }\n\n        final HIDDeviceManager finalThis = this;\n        mHandler.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                finalThis.chromebookConnectionHandler();\n            }\n        }, 10000);\n    }\n\n    public boolean connectBluetoothDevice(BluetoothDevice bluetoothDevice) {\n        Log.v(TAG, \"connectBluetoothDevice device=\" + bluetoothDevice);\n        synchronized (this) {\n            if (mBluetoothDevices.containsKey(bluetoothDevice)) {\n                Log.v(TAG, \"Steam controller with address \" + bluetoothDevice + \" already exists, attempting reconnect\");\n\n                HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);\n                device.reconnect();\n\n                return false;\n            }\n            HIDDeviceBLESteamController device = new HIDDeviceBLESteamController(this, bluetoothDevice);\n            int id = device.getId();\n            mBluetoothDevices.put(bluetoothDevice, device);\n            mDevicesById.put(id, device);\n\n            // The Steam Controller will mark itself connected once initialization is complete\n        }\n        return true;\n    }\n\n    public void disconnectBluetoothDevice(BluetoothDevice bluetoothDevice) {\n        synchronized (this) {\n            HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);\n            if (device == null)\n                return;\n\n            int id = device.getId();\n            mBluetoothDevices.remove(bluetoothDevice);\n            mDevicesById.remove(id);\n            device.shutdown();\n            HIDDeviceDisconnected(id);\n        }\n    }\n\n    public boolean isSteamController(BluetoothDevice bluetoothDevice) {\n        // Sanity check.  If you pass in a null device, by definition it is never a Steam Controller.\n        if (bluetoothDevice == null) {\n            return false;\n        }\n\n        // If the device has no local name, we really don't want to try an equality check against it.\n        if (bluetoothDevice.getName() == null) {\n            return false;\n        }\n\n        return bluetoothDevice.getName().equals(\"SteamController\") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);\n    }\n\n    private void close() {\n        shutdownUSB();\n        shutdownBluetooth();\n        synchronized (this) {\n            for (HIDDevice device : mDevicesById.values()) {\n                device.shutdown();\n            }\n            mDevicesById.clear();\n            mBluetoothDevices.clear();\n            HIDDeviceReleaseCallback();\n        }\n    }\n\n    public void setFrozen(boolean frozen) {\n        synchronized (this) {\n            for (HIDDevice device : mDevicesById.values()) {\n                device.setFrozen(frozen);\n            }\n        }\n    }\n\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n\n    private HIDDevice getDevice(int id) {\n        synchronized (this) {\n            HIDDevice result = mDevicesById.get(id);\n            if (result == null) {\n                Log.v(TAG, \"No device for id: \" + id);\n                Log.v(TAG, \"Available devices: \" + mDevicesById.keySet());\n            }\n            return result;\n        }\n    }\n\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    ////////// JNI interface functions\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n\n    public boolean initialize(boolean usb, boolean bluetooth) {\n        Log.v(TAG, \"initialize(\" + usb + \", \" + bluetooth + \")\");\n\n        if (usb) {\n            initializeUSB();\n        }\n        if (bluetooth) {\n            initializeBluetooth();\n        }\n        return true;\n    }\n\n    public boolean openDevice(int deviceID) {\n        Log.v(TAG, \"openDevice deviceID=\" + deviceID);\n        HIDDevice device = getDevice(deviceID);\n        if (device == null) {\n            HIDDeviceDisconnected(deviceID);\n            return false;\n        }\n\n        // Look to see if this is a USB device and we have permission to access it\n        UsbDevice usbDevice = device.getDevice();\n        if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) {\n            HIDDeviceOpenPending(deviceID);\n            try {\n                final int FLAG_MUTABLE = 0x02000000; // PendingIntent.FLAG_MUTABLE, but don't require SDK 31\n                int flags;\n                if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {\n                    flags = FLAG_MUTABLE;\n                } else {\n                    flags = 0;\n                }\n                if (Build.VERSION.SDK_INT >= 33 /* Android 14.0 (U) */) {\n                   Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION);\n                   intent.setPackage(mContext.getPackageName());\n                   mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags));\n               } else {\n                   mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));\n               }\n            } catch (Exception e) {\n                Log.v(TAG, \"Couldn't request permission for USB device \" + usbDevice);\n                HIDDeviceOpenResult(deviceID, false);\n            }\n            return false;\n        }\n\n        try {\n            return device.open();\n        } catch (Exception e) {\n            Log.e(TAG, \"Got exception: \" + Log.getStackTraceString(e));\n        }\n        return false;\n    }\n\n    public int sendOutputReport(int deviceID, byte[] report) {\n        try {\n            //Log.v(TAG, \"sendOutputReport deviceID=\" + deviceID + \" length=\" + report.length);\n            HIDDevice device;\n            device = getDevice(deviceID);\n            if (device == null) {\n                HIDDeviceDisconnected(deviceID);\n                return -1;\n            }\n\n            return device.sendOutputReport(report);\n        } catch (Exception e) {\n            Log.e(TAG, \"Got exception: \" + Log.getStackTraceString(e));\n        }\n        return -1;\n    }\n\n    public int sendFeatureReport(int deviceID, byte[] report) {\n        try {\n            //Log.v(TAG, \"sendFeatureReport deviceID=\" + deviceID + \" length=\" + report.length);\n            HIDDevice device;\n            device = getDevice(deviceID);\n            if (device == null) {\n                HIDDeviceDisconnected(deviceID);\n                return -1;\n            }\n\n            return device.sendFeatureReport(report);\n        } catch (Exception e) {\n            Log.e(TAG, \"Got exception: \" + Log.getStackTraceString(e));\n        }\n        return -1;\n    }\n\n    public boolean getFeatureReport(int deviceID, byte[] report) {\n        try {\n            //Log.v(TAG, \"getFeatureReport deviceID=\" + deviceID);\n            HIDDevice device;\n            device = getDevice(deviceID);\n            if (device == null) {\n                HIDDeviceDisconnected(deviceID);\n                return false;\n            }\n\n            return device.getFeatureReport(report);\n        } catch (Exception e) {\n            Log.e(TAG, \"Got exception: \" + Log.getStackTraceString(e));\n        }\n        return false;\n    }\n\n    public void closeDevice(int deviceID) {\n        try {\n            Log.v(TAG, \"closeDevice deviceID=\" + deviceID);\n            HIDDevice device;\n            device = getDevice(deviceID);\n            if (device == null) {\n                HIDDeviceDisconnected(deviceID);\n                return;\n            }\n\n            device.close();\n        } catch (Exception e) {\n            Log.e(TAG, \"Got exception: \" + Log.getStackTraceString(e));\n        }\n    }\n\n\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n    /////////////// Native methods\n    //////////////////////////////////////////////////////////////////////////////////////////////////////\n\n    private native void HIDDeviceRegisterCallback();\n    private native void HIDDeviceReleaseCallback();\n\n    native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol);\n    native void HIDDeviceOpenPending(int deviceID);\n    native void HIDDeviceOpenResult(int deviceID, boolean opened);\n    native void HIDDeviceDisconnected(int deviceID);\n\n    native void HIDDeviceInputReport(int deviceID, byte[] report);\n    native void HIDDeviceFeatureReport(int deviceID, byte[] report);\n}\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java",
    "content": "package org.libsdl.app;\n\nimport android.hardware.usb.*;\nimport android.os.Build;\nimport android.util.Log;\nimport java.util.Arrays;\n\nclass HIDDeviceUSB implements HIDDevice {\n\n    private static final String TAG = \"hidapi\";\n\n    protected HIDDeviceManager mManager;\n    protected UsbDevice mDevice;\n    protected int mInterfaceIndex;\n    protected int mInterface;\n    protected int mDeviceId;\n    protected UsbDeviceConnection mConnection;\n    protected UsbEndpoint mInputEndpoint;\n    protected UsbEndpoint mOutputEndpoint;\n    protected InputThread mInputThread;\n    protected boolean mRunning;\n    protected boolean mFrozen;\n\n    public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {\n        mManager = manager;\n        mDevice = usbDevice;\n        mInterfaceIndex = interface_index;\n        mInterface = mDevice.getInterface(mInterfaceIndex).getId();\n        mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());\n        mRunning = false;\n    }\n\n    public String getIdentifier() {\n        return String.format(\"%s/%x/%x/%d\", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterfaceIndex);\n    }\n\n    @Override\n    public int getId() {\n        return mDeviceId;\n    }\n\n    @Override\n    public int getVendorId() {\n        return mDevice.getVendorId();\n    }\n\n    @Override\n    public int getProductId() {\n        return mDevice.getProductId();\n    }\n\n    @Override\n    public String getSerialNumber() {\n        String result = null;\n        if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {\n            try {\n                result = mDevice.getSerialNumber();\n            }\n            catch (SecurityException exception) {\n                //Log.w(TAG, \"App permissions mean we cannot get serial number for device \" + getDeviceName() + \" message: \" + exception.getMessage());\n            }\n        }\n        if (result == null) {\n            result = \"\";\n        }\n        return result;\n    }\n\n    @Override\n    public int getVersion() {\n        return 0;\n    }\n\n    @Override\n    public String getManufacturerName() {\n        String result = null;\n        if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {\n            result = mDevice.getManufacturerName();\n        }\n        if (result == null) {\n            result = String.format(\"%x\", getVendorId());\n        }\n        return result;\n    }\n\n    @Override\n    public String getProductName() {\n        String result = null;\n        if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {\n            result = mDevice.getProductName();\n        }\n        if (result == null) {\n            result = String.format(\"%x\", getProductId());\n        }\n        return result;\n    }\n\n    @Override\n    public UsbDevice getDevice() {\n        return mDevice;\n    }\n\n    public String getDeviceName() {\n        return getManufacturerName() + \" \" + getProductName() + \"(0x\" + String.format(\"%x\", getVendorId()) + \"/0x\" + String.format(\"%x\", getProductId()) + \")\";\n    }\n\n    @Override\n    public boolean open() {\n        mConnection = mManager.getUSBManager().openDevice(mDevice);\n        if (mConnection == null) {\n            Log.w(TAG, \"Unable to open USB device \" + getDeviceName());\n            return false;\n        }\n\n        // Force claim our interface\n        UsbInterface iface = mDevice.getInterface(mInterfaceIndex);\n        if (!mConnection.claimInterface(iface, true)) {\n            Log.w(TAG, \"Failed to claim interfaces on USB device \" + getDeviceName());\n            close();\n            return false;\n        }\n\n        // Find the endpoints\n        for (int j = 0; j < iface.getEndpointCount(); j++) {\n            UsbEndpoint endpt = iface.getEndpoint(j);\n            switch (endpt.getDirection()) {\n            case UsbConstants.USB_DIR_IN:\n                if (mInputEndpoint == null) {\n                    mInputEndpoint = endpt;\n                }\n                break;\n            case UsbConstants.USB_DIR_OUT:\n                if (mOutputEndpoint == null) {\n                    mOutputEndpoint = endpt;\n                }\n                break;\n            }\n        }\n\n        // Make sure the required endpoints were present\n        if (mInputEndpoint == null || mOutputEndpoint == null) {\n            Log.w(TAG, \"Missing required endpoint on USB device \" + getDeviceName());\n            close();\n            return false;\n        }\n\n        // Start listening for input\n        mRunning = true;\n        mInputThread = new InputThread();\n        mInputThread.start();\n\n        return true;\n    }\n\n    @Override\n    public int sendFeatureReport(byte[] report) {\n        int res = -1;\n        int offset = 0;\n        int length = report.length;\n        boolean skipped_report_id = false;\n        byte report_number = report[0];\n\n        if (report_number == 0x0) {\n            ++offset;\n            --length;\n            skipped_report_id = true;\n        }\n\n        res = mConnection.controlTransfer(\n            UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT,\n            0x09/*HID set_report*/,\n            (3/*HID feature*/ << 8) | report_number,\n            mInterface,\n            report, offset, length,\n            1000/*timeout millis*/);\n\n        if (res < 0) {\n            Log.w(TAG, \"sendFeatureReport() returned \" + res + \" on device \" + getDeviceName());\n            return -1;\n        }\n\n        if (skipped_report_id) {\n            ++length;\n        }\n        return length;\n    }\n\n    @Override\n    public int sendOutputReport(byte[] report) {\n        int r = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);\n        if (r != report.length) {\n            Log.w(TAG, \"sendOutputReport() returned \" + r + \" on device \" + getDeviceName());\n        }\n        return r;\n    }\n\n    @Override\n    public boolean getFeatureReport(byte[] report) {\n        int res = -1;\n        int offset = 0;\n        int length = report.length;\n        boolean skipped_report_id = false;\n        byte report_number = report[0];\n\n        if (report_number == 0x0) {\n            /* Offset the return buffer by 1, so that the report ID\n               will remain in byte 0. */\n            ++offset;\n            --length;\n            skipped_report_id = true;\n        }\n\n        res = mConnection.controlTransfer(\n            UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN,\n            0x01/*HID get_report*/,\n            (3/*HID feature*/ << 8) | report_number,\n            mInterface,\n            report, offset, length,\n            1000/*timeout millis*/);\n\n        if (res < 0) {\n            Log.w(TAG, \"getFeatureReport() returned \" + res + \" on device \" + getDeviceName());\n            return false;\n        }\n\n        if (skipped_report_id) {\n            ++res;\n            ++length;\n        }\n\n        byte[] data;\n        if (res == length) {\n            data = report;\n        } else {\n            data = Arrays.copyOfRange(report, 0, res);\n        }\n        mManager.HIDDeviceFeatureReport(mDeviceId, data);\n\n        return true;\n    }\n\n    @Override\n    public void close() {\n        mRunning = false;\n        if (mInputThread != null) {\n            while (mInputThread.isAlive()) {\n                mInputThread.interrupt();\n                try {\n                    mInputThread.join();\n                } catch (InterruptedException e) {\n                    // Keep trying until we're done\n                }\n            }\n            mInputThread = null;\n        }\n        if (mConnection != null) {\n            UsbInterface iface = mDevice.getInterface(mInterfaceIndex);\n            mConnection.releaseInterface(iface);\n            mConnection.close();\n            mConnection = null;\n        }\n    }\n\n    @Override\n    public void shutdown() {\n        close();\n        mManager = null;\n    }\n\n    @Override\n    public void setFrozen(boolean frozen) {\n        mFrozen = frozen;\n    }\n\n    protected class InputThread extends Thread {\n        @Override\n        public void run() {\n            int packetSize = mInputEndpoint.getMaxPacketSize();\n            byte[] packet = new byte[packetSize];\n            while (mRunning) {\n                int r;\n                try\n                {\n                    r = mConnection.bulkTransfer(mInputEndpoint, packet, packetSize, 1000);\n                }\n                catch (Exception e)\n                {\n                    Log.v(TAG, \"Exception in UsbDeviceConnection bulktransfer: \" + e);\n                    break;\n                }\n                if (r < 0) {\n                    // Could be a timeout or an I/O error\n                }\n                if (r > 0) {\n                    byte[] data;\n                    if (r == packetSize) {\n                        data = packet;\n                    } else {\n                        data = Arrays.copyOfRange(packet, 0, r);\n                    }\n\n                    if (!mFrozen) {\n                        mManager.HIDDeviceInputReport(mDeviceId, data);\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/SDL.java",
    "content": "package org.libsdl.app;\n\nimport android.content.Context;\n\nimport java.lang.Class;\nimport java.lang.reflect.Method;\n\n/**\n    SDL library initialization\n*/\npublic class SDL {\n\n    // This function should be called first and sets up the native code\n    // so it can call into the Java classes\n    public static void setupJNI() {\n        SDLActivity.nativeSetupJNI();\n        SDLAudioManager.nativeSetupJNI();\n        SDLControllerManager.nativeSetupJNI();\n    }\n\n    // This function should be called each time the activity is started\n    public static void initialize() {\n        setContext(null);\n\n        SDLActivity.initialize();\n        SDLAudioManager.initialize();\n        SDLControllerManager.initialize();\n    }\n\n    // This function stores the current activity (SDL or not)\n    public static void setContext(Context context) {\n        SDLAudioManager.setContext(context);\n        mContext = context;\n    }\n\n    public static Context getContext() {\n        return mContext;\n    }\n\n    public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {\n        loadLibrary(libraryName, mContext);\n    }\n\n    public static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException {\n\n        if (libraryName == null) {\n            throw new NullPointerException(\"No library name provided.\");\n        }\n\n        try {\n            // Let's see if we have ReLinker available in the project.  This is necessary for \n            // some projects that have huge numbers of local libraries bundled, and thus may \n            // trip a bug in Android's native library loader which ReLinker works around.  (If\n            // loadLibrary works properly, ReLinker will simply use the normal Android method\n            // internally.)\n            //\n            // To use ReLinker, just add it as a dependency.  For more information, see \n            // https://github.com/KeepSafe/ReLinker for ReLinker's repository.\n            //\n            Class<?> relinkClass = context.getClassLoader().loadClass(\"com.getkeepsafe.relinker.ReLinker\");\n            Class<?> relinkListenerClass = context.getClassLoader().loadClass(\"com.getkeepsafe.relinker.ReLinker$LoadListener\");\n            Class<?> contextClass = context.getClassLoader().loadClass(\"android.content.Context\");\n            Class<?> stringClass = context.getClassLoader().loadClass(\"java.lang.String\");\n\n            // Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if \n            // they've changed during updates.\n            Method forceMethod = relinkClass.getDeclaredMethod(\"force\");\n            Object relinkInstance = forceMethod.invoke(null);\n            Class<?> relinkInstanceClass = relinkInstance.getClass();\n\n            // Actually load the library!\n            Method loadMethod = relinkInstanceClass.getDeclaredMethod(\"loadLibrary\", contextClass, stringClass, stringClass, relinkListenerClass);\n            loadMethod.invoke(relinkInstance, context, libraryName, null, null);\n        }\n        catch (final Throwable e) {\n            // Fall back\n            try {\n                System.loadLibrary(libraryName);\n            }\n            catch (final UnsatisfiedLinkError ule) {\n                throw ule;\n            }\n            catch (final SecurityException se) {\n                throw se;\n            }\n        }\n    }\n\n    protected static Context mContext;\n}\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/SDLActivity.java",
    "content": "package org.libsdl.app;\n\nimport android.app.Activity;\nimport android.app.AlertDialog;\nimport android.app.Dialog;\nimport android.app.UiModeManager;\nimport android.content.ClipboardManager;\nimport android.content.ClipData;\nimport android.content.Context;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.content.pm.ActivityInfo;\nimport android.content.pm.ApplicationInfo;\nimport android.content.pm.PackageManager;\nimport android.content.res.Configuration;\nimport android.graphics.Bitmap;\nimport android.graphics.Color;\nimport android.graphics.PorterDuff;\nimport android.graphics.drawable.Drawable;\nimport android.hardware.Sensor;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.text.Editable;\nimport android.text.InputType;\nimport android.text.Selection;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.util.SparseArray;\nimport android.view.Display;\nimport android.view.Gravity;\nimport android.view.InputDevice;\nimport android.view.KeyEvent;\nimport android.view.PointerIcon;\nimport android.view.Surface;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.Window;\nimport android.view.WindowManager;\nimport android.view.inputmethod.BaseInputConnection;\nimport android.view.inputmethod.EditorInfo;\nimport android.view.inputmethod.InputConnection;\nimport android.view.inputmethod.InputMethodManager;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.LinearLayout;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport java.util.Hashtable;\nimport java.util.Locale;\n\n\n/**\n    SDL Activity\n*/\npublic class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {\n    private static final String TAG = \"SDL\";\n    private static final int SDL_MAJOR_VERSION = 2;\n    private static final int SDL_MINOR_VERSION = 32;\n    private static final int SDL_MICRO_VERSION = 8;\n/*\n    // Display InputType.SOURCE/CLASS of events and devices\n    //\n    // SDLActivity.debugSource(device.getSources(), \"device[\" + device.getName() + \"]\");\n    // SDLActivity.debugSource(event.getSource(), \"event\");\n    public static void debugSource(int sources, String prefix) {\n        int s = sources;\n        int s_copy = sources;\n        String cls = \"\";\n        String src = \"\";\n        int tst = 0;\n        int FLAG_TAINTED = 0x80000000;\n\n        if ((s & InputDevice.SOURCE_CLASS_BUTTON) != 0)     cls += \" BUTTON\";\n        if ((s & InputDevice.SOURCE_CLASS_JOYSTICK) != 0)   cls += \" JOYSTICK\";\n        if ((s & InputDevice.SOURCE_CLASS_POINTER) != 0)    cls += \" POINTER\";\n        if ((s & InputDevice.SOURCE_CLASS_POSITION) != 0)   cls += \" POSITION\";\n        if ((s & InputDevice.SOURCE_CLASS_TRACKBALL) != 0)  cls += \" TRACKBALL\";\n\n\n        int s2 = s_copy & ~InputDevice.SOURCE_ANY; // keep class bits\n        s2 &= ~(  InputDevice.SOURCE_CLASS_BUTTON\n                | InputDevice.SOURCE_CLASS_JOYSTICK\n                | InputDevice.SOURCE_CLASS_POINTER\n                | InputDevice.SOURCE_CLASS_POSITION\n                | InputDevice.SOURCE_CLASS_TRACKBALL);\n\n        if (s2 != 0) cls += \"Some_Unknown\";\n\n        s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;\n\n        if (Build.VERSION.SDK_INT >= 23) {\n            tst = InputDevice.SOURCE_BLUETOOTH_STYLUS;\n            if ((s & tst) == tst) src += \" BLUETOOTH_STYLUS\";\n            s2 &= ~tst;\n        }\n\n        tst = InputDevice.SOURCE_DPAD;\n        if ((s & tst) == tst) src += \" DPAD\";\n        s2 &= ~tst;\n\n        tst = InputDevice.SOURCE_GAMEPAD;\n        if ((s & tst) == tst) src += \" GAMEPAD\";\n        s2 &= ~tst;\n\n        if (Build.VERSION.SDK_INT >= 21) {\n            tst = InputDevice.SOURCE_HDMI;\n            if ((s & tst) == tst) src += \" HDMI\";\n            s2 &= ~tst;\n        }\n\n        tst = InputDevice.SOURCE_JOYSTICK;\n        if ((s & tst) == tst) src += \" JOYSTICK\";\n        s2 &= ~tst;\n\n        tst = InputDevice.SOURCE_KEYBOARD;\n        if ((s & tst) == tst) src += \" KEYBOARD\";\n        s2 &= ~tst;\n\n        tst = InputDevice.SOURCE_MOUSE;\n        if ((s & tst) == tst) src += \" MOUSE\";\n        s2 &= ~tst;\n\n        if (Build.VERSION.SDK_INT >= 26) {\n            tst = InputDevice.SOURCE_MOUSE_RELATIVE;\n            if ((s & tst) == tst) src += \" MOUSE_RELATIVE\";\n            s2 &= ~tst;\n\n            tst = InputDevice.SOURCE_ROTARY_ENCODER;\n            if ((s & tst) == tst) src += \" ROTARY_ENCODER\";\n            s2 &= ~tst;\n        }\n        tst = InputDevice.SOURCE_STYLUS;\n        if ((s & tst) == tst) src += \" STYLUS\";\n        s2 &= ~tst;\n\n        tst = InputDevice.SOURCE_TOUCHPAD;\n        if ((s & tst) == tst) src += \" TOUCHPAD\";\n        s2 &= ~tst;\n\n        tst = InputDevice.SOURCE_TOUCHSCREEN;\n        if ((s & tst) == tst) src += \" TOUCHSCREEN\";\n        s2 &= ~tst;\n\n        if (Build.VERSION.SDK_INT >= 18) {\n            tst = InputDevice.SOURCE_TOUCH_NAVIGATION;\n            if ((s & tst) == tst) src += \" TOUCH_NAVIGATION\";\n            s2 &= ~tst;\n        }\n\n        tst = InputDevice.SOURCE_TRACKBALL;\n        if ((s & tst) == tst) src += \" TRACKBALL\";\n        s2 &= ~tst;\n\n        tst = InputDevice.SOURCE_ANY;\n        if ((s & tst) == tst) src += \" ANY\";\n        s2 &= ~tst;\n\n        if (s == FLAG_TAINTED) src += \" FLAG_TAINTED\";\n        s2 &= ~FLAG_TAINTED;\n\n        if (s2 != 0) src += \" Some_Unknown\";\n\n        Log.v(TAG, prefix + \"int=\" + s_copy + \" CLASS={\" + cls + \" } source(s):\" + src);\n    }\n*/\n\n    public static boolean mIsResumedCalled, mHasFocus;\n    public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24  /* Android 7.0 (N) */);\n\n    // Cursor types\n    // private static final int SDL_SYSTEM_CURSOR_NONE = -1;\n    private static final int SDL_SYSTEM_CURSOR_ARROW = 0;\n    private static final int SDL_SYSTEM_CURSOR_IBEAM = 1;\n    private static final int SDL_SYSTEM_CURSOR_WAIT = 2;\n    private static final int SDL_SYSTEM_CURSOR_CROSSHAIR = 3;\n    private static final int SDL_SYSTEM_CURSOR_WAITARROW = 4;\n    private static final int SDL_SYSTEM_CURSOR_SIZENWSE = 5;\n    private static final int SDL_SYSTEM_CURSOR_SIZENESW = 6;\n    private static final int SDL_SYSTEM_CURSOR_SIZEWE = 7;\n    private static final int SDL_SYSTEM_CURSOR_SIZENS = 8;\n    private static final int SDL_SYSTEM_CURSOR_SIZEALL = 9;\n    private static final int SDL_SYSTEM_CURSOR_NO = 10;\n    private static final int SDL_SYSTEM_CURSOR_HAND = 11;\n\n    protected static final int SDL_ORIENTATION_UNKNOWN = 0;\n    protected static final int SDL_ORIENTATION_LANDSCAPE = 1;\n    protected static final int SDL_ORIENTATION_LANDSCAPE_FLIPPED = 2;\n    protected static final int SDL_ORIENTATION_PORTRAIT = 3;\n    protected static final int SDL_ORIENTATION_PORTRAIT_FLIPPED = 4;\n\n    protected static int mCurrentOrientation;\n    protected static Locale mCurrentLocale;\n\n    // Handle the state of the native layer\n    public enum NativeState {\n           INIT, RESUMED, PAUSED\n    }\n\n    public static NativeState mNextNativeState;\n    public static NativeState mCurrentNativeState;\n\n    /** If shared libraries (e.g. SDL or the native application) could not be loaded. */\n    public static boolean mBrokenLibraries = true;\n\n    // Main components\n    protected static SDLActivity mSingleton;\n    protected static SDLSurface mSurface;\n    protected static DummyEdit mTextEdit;\n    protected static boolean mScreenKeyboardShown;\n    protected static ViewGroup mLayout;\n    protected static SDLClipboardHandler mClipboardHandler;\n    protected static Hashtable<Integer, PointerIcon> mCursors;\n    protected static int mLastCursorID;\n    protected static SDLGenericMotionListener_API12 mMotionListener;\n    protected static HIDDeviceManager mHIDDeviceManager;\n\n    // This is what SDL runs in. It invokes SDL_main(), eventually\n    protected static Thread mSDLThread;\n\n    protected static SDLGenericMotionListener_API12 getMotionListener() {\n        if (mMotionListener == null) {\n            if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {\n                mMotionListener = new SDLGenericMotionListener_API26();\n            } else if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n                mMotionListener = new SDLGenericMotionListener_API24();\n            } else {\n                mMotionListener = new SDLGenericMotionListener_API12();\n            }\n        }\n\n        return mMotionListener;\n    }\n\n    /**\n     * This method returns the name of the shared object with the application entry point\n     * It can be overridden by derived classes.\n     */\n    protected String getMainSharedObject() {\n        String library;\n        String[] libraries = SDLActivity.mSingleton.getLibraries();\n        if (libraries.length > 0) {\n            library = \"lib\" + libraries[libraries.length - 1] + \".so\";\n        } else {\n            library = \"libmain.so\";\n        }\n        return getContext().getApplicationInfo().nativeLibraryDir + \"/\" + library;\n    }\n\n    /**\n     * This method returns the name of the application entry point\n     * It can be overridden by derived classes.\n     */\n    protected String getMainFunction() {\n        return \"SDL_main\";\n    }\n\n    /**\n     * This method is called by SDL before loading the native shared libraries.\n     * It can be overridden to provide names of shared libraries to be loaded.\n     * The default implementation returns the defaults. It never returns null.\n     * An array returned by a new implementation must at least contain \"SDL2\".\n     * Also keep in mind that the order the libraries are loaded may matter.\n     * @return names of shared libraries to be loaded (e.g. \"SDL2\", \"main\").\n     */\n    protected String[] getLibraries() {\n        return new String[] {\n            \"SDL2\",\n            // \"SDL2_image\",\n            // \"SDL2_mixer\",\n            // \"SDL2_net\",\n            // \"SDL2_ttf\",\n            \"main\"\n        };\n    }\n\n    // Load the .so\n    public void loadLibraries() {\n       for (String lib : getLibraries()) {\n          SDL.loadLibrary(lib, this);\n       }\n    }\n\n    /**\n     * This method is called by SDL before starting the native application thread.\n     * It can be overridden to provide the arguments after the application name.\n     * The default implementation returns an empty array. It never returns null.\n     * @return arguments for the native application.\n     */\n    protected String[] getArguments() {\n        return new String[0];\n    }\n\n    public static void initialize() {\n        // The static nature of the singleton and Android quirkyness force us to initialize everything here\n        // Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values\n        mSingleton = null;\n        mSurface = null;\n        mTextEdit = null;\n        mLayout = null;\n        mClipboardHandler = null;\n        mCursors = new Hashtable<Integer, PointerIcon>();\n        mLastCursorID = 0;\n        mSDLThread = null;\n        mIsResumedCalled = false;\n        mHasFocus = true;\n        mNextNativeState = NativeState.INIT;\n        mCurrentNativeState = NativeState.INIT;\n    }\n    \n    protected SDLSurface createSDLSurface(Context context) {\n        return new SDLSurface(context);\n    }\n\n    // Setup\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        Log.v(TAG, \"Device: \" + Build.DEVICE);\n        Log.v(TAG, \"Model: \" + Build.MODEL);\n        Log.v(TAG, \"onCreate()\");\n        super.onCreate(savedInstanceState);\n\n        try {\n            Thread.currentThread().setName(\"SDLActivity\");\n        } catch (Exception e) {\n            Log.v(TAG, \"modify thread properties failed \" + e.toString());\n        }\n\n        // Load shared libraries\n        String errorMsgBrokenLib = \"\";\n        try {\n            loadLibraries();\n            mBrokenLibraries = false; /* success */\n        } catch(UnsatisfiedLinkError e) {\n            System.err.println(e.getMessage());\n            mBrokenLibraries = true;\n            errorMsgBrokenLib = e.getMessage();\n        } catch(Exception e) {\n            System.err.println(e.getMessage());\n            mBrokenLibraries = true;\n            errorMsgBrokenLib = e.getMessage();\n        }\n\n        if (!mBrokenLibraries) {\n            String expected_version = String.valueOf(SDL_MAJOR_VERSION) + \".\" +\n                                      String.valueOf(SDL_MINOR_VERSION) + \".\" +\n                                      String.valueOf(SDL_MICRO_VERSION);\n            String version = nativeGetVersion();\n            if (!version.equals(expected_version)) {\n                mBrokenLibraries = true;\n                errorMsgBrokenLib = \"SDL C/Java version mismatch (expected \" + expected_version + \", got \" + version + \")\";\n            }\n        }\n\n        if (mBrokenLibraries) {\n            mSingleton = this;\n            AlertDialog.Builder dlgAlert  = new AlertDialog.Builder(this);\n            dlgAlert.setMessage(\"An error occurred while trying to start the application. Please try again and/or reinstall.\"\n                  + System.getProperty(\"line.separator\")\n                  + System.getProperty(\"line.separator\")\n                  + \"Error: \" + errorMsgBrokenLib);\n            dlgAlert.setTitle(\"SDL Error\");\n            dlgAlert.setPositiveButton(\"Exit\",\n                new DialogInterface.OnClickListener() {\n                    @Override\n                    public void onClick(DialogInterface dialog,int id) {\n                        // if this button is clicked, close current activity\n                        SDLActivity.mSingleton.finish();\n                    }\n                });\n           dlgAlert.setCancelable(false);\n           dlgAlert.create().show();\n\n           return;\n        }\n\n        // Set up JNI\n        SDL.setupJNI();\n\n        // Initialize state\n        SDL.initialize();\n\n        // So we can call stuff from static callbacks\n        mSingleton = this;\n        SDL.setContext(this);\n\n        mClipboardHandler = new SDLClipboardHandler();\n\n        mHIDDeviceManager = HIDDeviceManager.acquire(this);\n\n        // Set up the surface\n        mSurface = createSDLSurface(this);\n\n        mLayout = new RelativeLayout(this);\n        mLayout.addView(mSurface);\n\n        // Get our current screen orientation and pass it down.\n        mCurrentOrientation = SDLActivity.getCurrentOrientation();\n        // Only record current orientation\n        SDLActivity.onNativeOrientationChanged(mCurrentOrientation);\n\n        try {\n            if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {\n                mCurrentLocale = getContext().getResources().getConfiguration().locale;\n            } else {\n                mCurrentLocale = getContext().getResources().getConfiguration().getLocales().get(0);\n            }\n        } catch(Exception ignored) {\n        }\n\n        setContentView(mLayout);\n\n        setWindowStyle(false);\n\n        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);\n\n        // Get filename from \"Open with\" of another application\n        Intent intent = getIntent();\n        if (intent != null && intent.getData() != null) {\n            String filename = intent.getData().getPath();\n            if (filename != null) {\n                Log.v(TAG, \"Got filename: \" + filename);\n                SDLActivity.onNativeDropFile(filename);\n            }\n        }\n    }\n\n    protected void pauseNativeThread() {\n        mNextNativeState = NativeState.PAUSED;\n        mIsResumedCalled = false;\n\n        if (SDLActivity.mBrokenLibraries) {\n            return;\n        }\n\n        SDLActivity.handleNativeState();\n    }\n\n    protected void resumeNativeThread() {\n        mNextNativeState = NativeState.RESUMED;\n        mIsResumedCalled = true;\n\n        if (SDLActivity.mBrokenLibraries) {\n           return;\n        }\n\n        SDLActivity.handleNativeState();\n    }\n\n    // Events\n    @Override\n    protected void onPause() {\n        Log.v(TAG, \"onPause()\");\n        super.onPause();\n\n        if (mHIDDeviceManager != null) {\n            mHIDDeviceManager.setFrozen(true);\n        }\n        if (!mHasMultiWindow) {\n            pauseNativeThread();\n        }\n    }\n\n    @Override\n    protected void onResume() {\n        Log.v(TAG, \"onResume()\");\n        super.onResume();\n\n        if (mHIDDeviceManager != null) {\n            mHIDDeviceManager.setFrozen(false);\n        }\n        if (!mHasMultiWindow) {\n            resumeNativeThread();\n        }\n    }\n\n    @Override\n    protected void onStop() {\n        Log.v(TAG, \"onStop()\");\n        super.onStop();\n        if (mHasMultiWindow) {\n            pauseNativeThread();\n        }\n    }\n\n    @Override\n    protected void onStart() {\n        Log.v(TAG, \"onStart()\");\n        super.onStart();\n        if (mHasMultiWindow) {\n            resumeNativeThread();\n        }\n    }\n\n    public static int getCurrentOrientation() {\n        int result = SDL_ORIENTATION_UNKNOWN;\n\n        Activity activity = (Activity)getContext();\n        if (activity == null) {\n            return result;\n        }\n        Display display = activity.getWindowManager().getDefaultDisplay();\n\n        switch (display.getRotation()) {\n            case Surface.ROTATION_0:\n                result = SDL_ORIENTATION_PORTRAIT;\n                break;\n\n            case Surface.ROTATION_90:\n                result = SDL_ORIENTATION_LANDSCAPE;\n                break;\n\n            case Surface.ROTATION_180:\n                result = SDL_ORIENTATION_PORTRAIT_FLIPPED;\n                break;\n\n            case Surface.ROTATION_270:\n                result = SDL_ORIENTATION_LANDSCAPE_FLIPPED;\n                break;\n        }\n\n        return result;\n    }\n\n    @Override\n    public void onWindowFocusChanged(boolean hasFocus) {\n        super.onWindowFocusChanged(hasFocus);\n        Log.v(TAG, \"onWindowFocusChanged(): \" + hasFocus);\n\n        if (SDLActivity.mBrokenLibraries) {\n           return;\n        }\n\n        mHasFocus = hasFocus;\n        if (hasFocus) {\n           mNextNativeState = NativeState.RESUMED;\n           SDLActivity.getMotionListener().reclaimRelativeMouseModeIfNeeded();\n\n           SDLActivity.handleNativeState();\n           nativeFocusChanged(true);\n\n        } else {\n           nativeFocusChanged(false);\n           if (!mHasMultiWindow) {\n               mNextNativeState = NativeState.PAUSED;\n               SDLActivity.handleNativeState();\n           }\n        }\n    }\n\n    @Override\n    public void onLowMemory() {\n        Log.v(TAG, \"onLowMemory()\");\n        super.onLowMemory();\n\n        if (SDLActivity.mBrokenLibraries) {\n           return;\n        }\n\n        SDLActivity.nativeLowMemory();\n    }\n\n    @Override\n    public void onConfigurationChanged(Configuration newConfig) {\n        Log.v(TAG, \"onConfigurationChanged()\");\n        super.onConfigurationChanged(newConfig);\n\n        if (SDLActivity.mBrokenLibraries) {\n           return;\n        }\n\n        if (mCurrentLocale == null || !mCurrentLocale.equals(newConfig.locale)) {\n            mCurrentLocale = newConfig.locale;\n            SDLActivity.onNativeLocaleChanged();\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        Log.v(TAG, \"onDestroy()\");\n\n        if (mHIDDeviceManager != null) {\n            HIDDeviceManager.release(mHIDDeviceManager);\n            mHIDDeviceManager = null;\n        }\n\n        SDLAudioManager.release(this);\n\n        if (SDLActivity.mBrokenLibraries) {\n           super.onDestroy();\n           return;\n        }\n\n        if (SDLActivity.mSDLThread != null) {\n\n            // Send Quit event to \"SDLThread\" thread\n            SDLActivity.nativeSendQuit();\n\n            // Wait for \"SDLThread\" thread to end\n            try {\n                SDLActivity.mSDLThread.join();\n            } catch(Exception e) {\n                Log.v(TAG, \"Problem stopping SDLThread: \" + e);\n            }\n        }\n\n        SDLActivity.nativeQuit();\n\n        super.onDestroy();\n    }\n\n    @Override\n    public void onBackPressed() {\n        // Check if we want to block the back button in case of mouse right click.\n        //\n        // If we do, the normal hardware back button will no longer work and people have to use home,\n        // but the mouse right click will work.\n        //\n        boolean trapBack = SDLActivity.nativeGetHintBoolean(\"SDL_ANDROID_TRAP_BACK_BUTTON\", false);\n        if (trapBack) {\n            // Exit and let the mouse handler handle this button (if appropriate)\n            return;\n        }\n\n        // Default system back button behavior.\n        if (!isFinishing()) {\n            super.onBackPressed();\n        }\n    }\n\n    // Called by JNI from SDL.\n    public static void manualBackButton() {\n        mSingleton.pressBackButton();\n    }\n\n    // Used to get us onto the activity's main thread\n    public void pressBackButton() {\n        runOnUiThread(new Runnable() {\n            @Override\n            public void run() {\n                if (!SDLActivity.this.isFinishing()) {\n                    SDLActivity.this.superOnBackPressed();\n                }\n            }\n        });\n    }\n\n    // Used to access the system back behavior.\n    public void superOnBackPressed() {\n        super.onBackPressed();\n    }\n\n    @Override\n    public boolean dispatchKeyEvent(KeyEvent event) {\n\n        if (SDLActivity.mBrokenLibraries) {\n           return false;\n        }\n\n        int keyCode = event.getKeyCode();\n        // Ignore certain special keys so they're handled by Android\n        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||\n            keyCode == KeyEvent.KEYCODE_VOLUME_UP ||\n            keyCode == KeyEvent.KEYCODE_CAMERA ||\n            keyCode == KeyEvent.KEYCODE_ZOOM_IN || /* API 11 */\n            keyCode == KeyEvent.KEYCODE_ZOOM_OUT /* API 11 */\n            ) {\n            return false;\n        }\n        return super.dispatchKeyEvent(event);\n    }\n\n    /* Transition to next state */\n    public static void handleNativeState() {\n\n        if (mNextNativeState == mCurrentNativeState) {\n            // Already in same state, discard.\n            return;\n        }\n\n        // Try a transition to init state\n        if (mNextNativeState == NativeState.INIT) {\n\n            mCurrentNativeState = mNextNativeState;\n            return;\n        }\n\n        // Try a transition to paused state\n        if (mNextNativeState == NativeState.PAUSED) {\n            if (mSDLThread != null) {\n                nativePause();\n            }\n            if (mSurface != null) {\n                mSurface.handlePause();\n            }\n            mCurrentNativeState = mNextNativeState;\n            return;\n        }\n\n        // Try a transition to resumed state\n        if (mNextNativeState == NativeState.RESUMED) {\n            if (mSurface.mIsSurfaceReady && mHasFocus && mIsResumedCalled) {\n                if (mSDLThread == null) {\n                    // This is the entry point to the C app.\n                    // Start up the C app thread and enable sensor input for the first time\n                    // FIXME: Why aren't we enabling sensor input at start?\n\n                    mSDLThread = new Thread(new SDLMain(), \"SDLThread\");\n                    mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);\n                    mSDLThread.start();\n\n                    // No nativeResume(), don't signal Android_ResumeSem\n                } else {\n                    nativeResume();\n                }\n                mSurface.handleResume();\n\n                mCurrentNativeState = mNextNativeState;\n            }\n        }\n    }\n\n    // Messages from the SDLMain thread\n    static final int COMMAND_CHANGE_TITLE = 1;\n    static final int COMMAND_CHANGE_WINDOW_STYLE = 2;\n    static final int COMMAND_TEXTEDIT_HIDE = 3;\n    static final int COMMAND_SET_KEEP_SCREEN_ON = 5;\n\n    protected static final int COMMAND_USER = 0x8000;\n\n    protected static boolean mFullscreenModeActive;\n\n    /**\n     * This method is called by SDL if SDL did not handle a message itself.\n     * This happens if a received message contains an unsupported command.\n     * Method can be overwritten to handle Messages in a different class.\n     * @param command the command of the message.\n     * @param param the parameter of the message. May be null.\n     * @return if the message was handled in overridden method.\n     */\n    protected boolean onUnhandledMessage(int command, Object param) {\n        return false;\n    }\n\n    /**\n     * A Handler class for Messages from native SDL applications.\n     * It uses current Activities as target (e.g. for the title).\n     * static to prevent implicit references to enclosing object.\n     */\n    protected static class SDLCommandHandler extends Handler {\n        @Override\n        public void handleMessage(Message msg) {\n            Context context = SDL.getContext();\n            if (context == null) {\n                Log.e(TAG, \"error handling message, getContext() returned null\");\n                return;\n            }\n            switch (msg.arg1) {\n            case COMMAND_CHANGE_TITLE:\n                if (context instanceof Activity) {\n                    ((Activity) context).setTitle((String)msg.obj);\n                } else {\n                    Log.e(TAG, \"error handling message, getContext() returned no Activity\");\n                }\n                break;\n            case COMMAND_CHANGE_WINDOW_STYLE:\n                if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {\n                    if (context instanceof Activity) {\n                        Window window = ((Activity) context).getWindow();\n                        if (window != null) {\n                            if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) {\n                                int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |\n                                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |\n                                        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |\n                                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |\n                                        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |\n                                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;\n                                window.getDecorView().setSystemUiVisibility(flags);\n                                window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);\n                                window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);\n                                SDLActivity.mFullscreenModeActive = true;\n                            } else {\n                                int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;\n                                window.getDecorView().setSystemUiVisibility(flags);\n                                window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);\n                                window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);\n                                SDLActivity.mFullscreenModeActive = false;\n                            }\n                            if (Build.VERSION.SDK_INT >= 28 /* Android 9 (Pie) */) {\n                                window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;\n                            }\n                        }\n                    } else {\n                        Log.e(TAG, \"error handling message, getContext() returned no Activity\");\n                    }\n                }\n                break;\n            case COMMAND_TEXTEDIT_HIDE:\n                if (mTextEdit != null) {\n                    // Note: On some devices setting view to GONE creates a flicker in landscape.\n                    // Setting the View's sizes to 0 is similar to GONE but without the flicker.\n                    // The sizes will be set to useful values when the keyboard is shown again.\n                    mTextEdit.setLayoutParams(new RelativeLayout.LayoutParams(0, 0));\n\n                    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);\n                    imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);\n\n                    mScreenKeyboardShown = false;\n\n                    mSurface.requestFocus();\n                }\n                break;\n            case COMMAND_SET_KEEP_SCREEN_ON:\n            {\n                if (context instanceof Activity) {\n                    Window window = ((Activity) context).getWindow();\n                    if (window != null) {\n                        if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) {\n                            window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);\n                        } else {\n                            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);\n                        }\n                    }\n                }\n                break;\n            }\n            default:\n                if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {\n                    Log.e(TAG, \"error handling message, command is \" + msg.arg1);\n                }\n            }\n        }\n    }\n\n    // Handler for the messages\n    Handler commandHandler = new SDLCommandHandler();\n\n    // Send a message from the SDLMain thread\n    boolean sendCommand(int command, Object data) {\n        Message msg = commandHandler.obtainMessage();\n        msg.arg1 = command;\n        msg.obj = data;\n        boolean result = commandHandler.sendMessage(msg);\n\n        if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {\n            if (command == COMMAND_CHANGE_WINDOW_STYLE) {\n                // Ensure we don't return until the resize has actually happened,\n                // or 500ms have passed.\n\n                boolean bShouldWait = false;\n\n                if (data instanceof Integer) {\n                    // Let's figure out if we're already laid out fullscreen or not.\n                    Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();\n                    DisplayMetrics realMetrics = new DisplayMetrics();\n                    display.getRealMetrics(realMetrics);\n\n                    boolean bFullscreenLayout = ((realMetrics.widthPixels == mSurface.getWidth()) &&\n                            (realMetrics.heightPixels == mSurface.getHeight()));\n\n                    if ((Integer) data == 1) {\n                        // If we aren't laid out fullscreen or actively in fullscreen mode already, we're going\n                        // to change size and should wait for surfaceChanged() before we return, so the size\n                        // is right back in native code.  If we're already laid out fullscreen, though, we're\n                        // not going to change size even if we change decor modes, so we shouldn't wait for\n                        // surfaceChanged() -- which may not even happen -- and should return immediately.\n                        bShouldWait = !bFullscreenLayout;\n                    } else {\n                        // If we're laid out fullscreen (even if the status bar and nav bar are present),\n                        // or are actively in fullscreen, we're going to change size and should wait for\n                        // surfaceChanged before we return, so the size is right back in native code.\n                        bShouldWait = bFullscreenLayout;\n                    }\n                }\n\n                if (bShouldWait && (SDLActivity.getContext() != null)) {\n                    // We'll wait for the surfaceChanged() method, which will notify us\n                    // when called.  That way, we know our current size is really the\n                    // size we need, instead of grabbing a size that's still got\n                    // the navigation and/or status bars before they're hidden.\n                    //\n                    // We'll wait for up to half a second, because some devices\n                    // take a surprisingly long time for the surface resize, but\n                    // then we'll just give up and return.\n                    //\n                    synchronized (SDLActivity.getContext()) {\n                        try {\n                            SDLActivity.getContext().wait(500);\n                        } catch (InterruptedException ie) {\n                            ie.printStackTrace();\n                        }\n                    }\n                }\n            }\n        }\n\n        return result;\n    }\n\n    // C functions we call\n    public static native String nativeGetVersion();\n    public static native int nativeSetupJNI();\n    public static native int nativeRunMain(String library, String function, Object arguments);\n    public static native void nativeLowMemory();\n    public static native void nativeSendQuit();\n    public static native void nativeQuit();\n    public static native void nativePause();\n    public static native void nativeResume();\n    public static native void nativeFocusChanged(boolean hasFocus);\n    public static native void onNativeDropFile(String filename);\n    public static native void nativeSetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float rate);\n    public static native void onNativeResize();\n    public static native void onNativeKeyDown(int keycode);\n    public static native void onNativeKeyUp(int keycode);\n    public static native boolean onNativeSoftReturnKey();\n    public static native void onNativeKeyboardFocusLost();\n    public static native void onNativeMouse(int button, int action, float x, float y, boolean relative);\n    public static native void onNativeTouch(int touchDevId, int pointerFingerId,\n                                            int action, float x,\n                                            float y, float p);\n    public static native void onNativeAccel(float x, float y, float z);\n    public static native void onNativeClipboardChanged();\n    public static native void onNativeSurfaceCreated();\n    public static native void onNativeSurfaceChanged();\n    public static native void onNativeSurfaceDestroyed();\n    public static native String nativeGetHint(String name);\n    public static native boolean nativeGetHintBoolean(String name, boolean default_value);\n    public static native void nativeSetenv(String name, String value);\n    public static native void onNativeOrientationChanged(int orientation);\n    public static native void nativeAddTouch(int touchId, String name);\n    public static native void nativePermissionResult(int requestCode, boolean result);\n    public static native void onNativeLocaleChanged();\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean setActivityTitle(String title) {\n        // Called from SDLMain() thread and can't directly affect the view\n        return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void setWindowStyle(boolean fullscreen) {\n        // Called from SDLMain() thread and can't directly affect the view\n        mSingleton.sendCommand(COMMAND_CHANGE_WINDOW_STYLE, fullscreen ? 1 : 0);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     * This is a static method for JNI convenience, it calls a non-static method\n     * so that is can be overridden\n     */\n    public static void setOrientation(int w, int h, boolean resizable, String hint)\n    {\n        if (mSingleton != null) {\n            mSingleton.setOrientationBis(w, h, resizable, hint);\n        }\n    }\n\n    /**\n     * This can be overridden\n     */\n    public void setOrientationBis(int w, int h, boolean resizable, String hint)\n    {\n        int orientation_landscape = -1;\n        int orientation_portrait = -1;\n\n        /* If set, hint \"explicitly controls which UI orientations are allowed\". */\n        if (hint.contains(\"LandscapeRight\") && hint.contains(\"LandscapeLeft\")) {\n            orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;\n        } else if (hint.contains(\"LandscapeLeft\")) {\n            orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;\n        } else if (hint.contains(\"LandscapeRight\")) {\n            orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;\n        }\n\n        /* exact match to 'Portrait' to distinguish with PortraitUpsideDown */\n        boolean contains_Portrait = hint.contains(\"Portrait \") || hint.endsWith(\"Portrait\");\n\n        if (contains_Portrait && hint.contains(\"PortraitUpsideDown\")) {\n            orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;\n        } else if (contains_Portrait) {\n            orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;\n        } else if (hint.contains(\"PortraitUpsideDown\")) {\n            orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;\n        }\n\n        boolean is_landscape_allowed = (orientation_landscape != -1);\n        boolean is_portrait_allowed = (orientation_portrait != -1);\n        int req; /* Requested orientation */\n\n        /* No valid hint, nothing is explicitly allowed */\n        if (!is_portrait_allowed && !is_landscape_allowed) {\n            if (resizable) {\n                /* All orientations are allowed, respecting user orientation lock setting */\n                req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;\n            } else {\n                /* Fixed window and nothing specified. Get orientation from w/h of created window */\n                req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);\n            }\n        } else {\n            /* At least one orientation is allowed */\n            if (resizable) {\n                if (is_portrait_allowed && is_landscape_allowed) {\n                    /* hint allows both landscape and portrait, promote to full user */\n                    req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;\n                } else {\n                    /* Use the only one allowed \"orientation\" */\n                    req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);\n                }\n            } else {\n                /* Fixed window and both orientations are allowed. Choose one. */\n                if (is_portrait_allowed && is_landscape_allowed) {\n                    req = (w > h ? orientation_landscape : orientation_portrait);\n                } else {\n                    /* Use the only one allowed \"orientation\" */\n                    req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);\n                }\n            }\n        }\n\n        Log.v(TAG, \"setOrientation() requestedOrientation=\" + req + \" width=\" + w +\" height=\"+ h +\" resizable=\" + resizable + \" hint=\" + hint);\n        mSingleton.setRequestedOrientation(req);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void minimizeWindow() {\n\n        if (mSingleton == null) {\n            return;\n        }\n\n        Intent startMain = new Intent(Intent.ACTION_MAIN);\n        startMain.addCategory(Intent.CATEGORY_HOME);\n        startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n        mSingleton.startActivity(startMain);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean shouldMinimizeOnFocusLoss() {\n/*\n        if (Build.VERSION.SDK_INT >= 24) {\n            if (mSingleton == null) {\n                return true;\n            }\n\n            if (mSingleton.isInMultiWindowMode()) {\n                return false;\n            }\n\n            if (mSingleton.isInPictureInPictureMode()) {\n                return false;\n            }\n        }\n\n        return true;\n*/\n        return false;\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean isScreenKeyboardShown()\n    {\n        if (mTextEdit == null) {\n            return false;\n        }\n\n        if (!mScreenKeyboardShown) {\n            return false;\n        }\n\n        InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);\n        return imm.isAcceptingText();\n\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean supportsRelativeMouse()\n    {\n        // DeX mode in Samsung Experience 9.0 and earlier doesn't support relative mice properly under\n        // Android 7 APIs, and simply returns no data under Android 8 APIs.\n        //\n        // This is fixed in Samsung Experience 9.5, which corresponds to Android 8.1.0, and\n        // thus SDK version 27.  If we are in DeX mode and not API 27 or higher, as a result,\n        // we should stick to relative mode.\n        //\n        if (Build.VERSION.SDK_INT < 27 /* Android 8.1 (O_MR1) */ && isDeXMode()) {\n            return false;\n        }\n\n        return SDLActivity.getMotionListener().supportsRelativeMouse();\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean setRelativeMouseEnabled(boolean enabled)\n    {\n        if (enabled && !supportsRelativeMouse()) {\n            return false;\n        }\n\n        return SDLActivity.getMotionListener().setRelativeMouseEnabled(enabled);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean sendMessage(int command, int param) {\n        if (mSingleton == null) {\n            return false;\n        }\n        return mSingleton.sendCommand(command, param);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static Context getContext() {\n        return SDL.getContext();\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean isAndroidTV() {\n        UiModeManager uiModeManager = (UiModeManager) getContext().getSystemService(UI_MODE_SERVICE);\n        if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {\n            return true;\n        }\n        if (Build.MANUFACTURER.equals(\"MINIX\") && Build.MODEL.equals(\"NEO-U1\")) {\n            return true;\n        }\n        if (Build.MANUFACTURER.equals(\"Amlogic\") && Build.MODEL.equals(\"X96-W\")) {\n            return true;\n        }\n        return Build.MANUFACTURER.equals(\"Amlogic\") && Build.MODEL.startsWith(\"TV\");\n    }\n\n    public static double getDiagonal()\n    {\n        DisplayMetrics metrics = new DisplayMetrics();\n        Activity activity = (Activity)getContext();\n        if (activity == null) {\n            return 0.0;\n        }\n        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);\n\n        double dWidthInches = metrics.widthPixels / (double)metrics.xdpi;\n        double dHeightInches = metrics.heightPixels / (double)metrics.ydpi;\n\n        return Math.sqrt((dWidthInches * dWidthInches) + (dHeightInches * dHeightInches));\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean isTablet() {\n        // If our diagonal size is seven inches or greater, we consider ourselves a tablet.\n        return (getDiagonal() >= 7.0);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean isChromebook() {\n        if (getContext() == null) {\n            return false;\n        }\n        return getContext().getPackageManager().hasSystemFeature(\"org.chromium.arc.device_management\");\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean isDeXMode() {\n        if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {\n            return false;\n        }\n        try {\n            final Configuration config = getContext().getResources().getConfiguration();\n            final Class<?> configClass = config.getClass();\n            return configClass.getField(\"SEM_DESKTOP_MODE_ENABLED\").getInt(configClass)\n                    == configClass.getField(\"semDesktopModeEnabled\").getInt(config);\n        } catch(Exception ignored) {\n            return false;\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static DisplayMetrics getDisplayDPI() {\n        return getContext().getResources().getDisplayMetrics();\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean getManifestEnvironmentVariables() {\n        try {\n            if (getContext() == null) {\n                return false;\n            }\n\n            ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA);\n            Bundle bundle = applicationInfo.metaData;\n            if (bundle == null) {\n                return false;\n            }\n            String prefix = \"SDL_ENV.\";\n            final int trimLength = prefix.length();\n            for (String key : bundle.keySet()) {\n                if (key.startsWith(prefix)) {\n                    String name = key.substring(trimLength);\n                    String value = bundle.get(key).toString();\n                    nativeSetenv(name, value);\n                }\n            }\n            /* environment variables set! */\n            return true;\n        } catch (Exception e) {\n           Log.v(TAG, \"exception \" + e.toString());\n        }\n        return false;\n    }\n\n    // This method is called by SDLControllerManager's API 26 Generic Motion Handler.\n    public static View getContentView() {\n        return mLayout;\n    }\n\n    static class ShowTextInputTask implements Runnable {\n        /*\n         * This is used to regulate the pan&scan method to have some offset from\n         * the bottom edge of the input region and the top edge of an input\n         * method (soft keyboard)\n         */\n        static final int HEIGHT_PADDING = 15;\n\n        public int x, y, w, h;\n\n        public ShowTextInputTask(int x, int y, int w, int h) {\n            this.x = x;\n            this.y = y;\n            this.w = w;\n            this.h = h;\n\n            /* Minimum size of 1 pixel, so it takes focus. */\n            if (this.w <= 0) {\n                this.w = 1;\n            }\n            if (this.h + HEIGHT_PADDING <= 0) {\n                this.h = 1 - HEIGHT_PADDING;\n            }\n        }\n\n        @Override\n        public void run() {\n            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(w, h + HEIGHT_PADDING);\n            params.leftMargin = x;\n            params.topMargin = y;\n\n            if (mTextEdit == null) {\n                mTextEdit = new DummyEdit(SDL.getContext());\n\n                mLayout.addView(mTextEdit, params);\n            } else {\n                mTextEdit.setLayoutParams(params);\n            }\n\n            mTextEdit.setVisibility(View.VISIBLE);\n            mTextEdit.requestFocus();\n\n            InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);\n            imm.showSoftInput(mTextEdit, 0);\n\n            mScreenKeyboardShown = true;\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean showTextInput(int x, int y, int w, int h) {\n        // Transfer the task to the main thread as a Runnable\n        return mSingleton.commandHandler.post(new ShowTextInputTask(x, y, w, h));\n    }\n\n    public static boolean isTextInputEvent(KeyEvent event) {\n\n        // Key pressed with Ctrl should be sent as SDL_KEYDOWN/SDL_KEYUP and not SDL_TEXTINPUT\n        if (event.isCtrlPressed()) {\n            return false;\n        }\n\n        return event.isPrintingKey() || event.getKeyCode() == KeyEvent.KEYCODE_SPACE;\n    }\n\n    public static boolean handleKeyEvent(View v, int keyCode, KeyEvent event, InputConnection ic) {\n        int deviceId = event.getDeviceId();\n        int source = event.getSource();\n\n        if (source == InputDevice.SOURCE_UNKNOWN) {\n            InputDevice device = InputDevice.getDevice(deviceId);\n            if (device != null) {\n                source = device.getSources();\n            }\n        }\n\n//        if (event.getAction() == KeyEvent.ACTION_DOWN) {\n//            Log.v(\"SDL\", \"key down: \" + keyCode + \", deviceId = \" + deviceId + \", source = \" + source);\n//        } else if (event.getAction() == KeyEvent.ACTION_UP) {\n//            Log.v(\"SDL\", \"key up: \" + keyCode + \", deviceId = \" + deviceId + \", source = \" + source);\n//        }\n\n        // Dispatch the different events depending on where they come from\n        // Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD\n        // So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD\n        //\n        // Furthermore, it's possible a game controller has SOURCE_KEYBOARD and\n        // SOURCE_JOYSTICK, while its key events arrive from the keyboard source\n        // So, retrieve the device itself and check all of its sources\n        if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {\n            // Note that we process events with specific key codes here\n            if (event.getAction() == KeyEvent.ACTION_DOWN) {\n                if (SDLControllerManager.onNativePadDown(deviceId, keyCode) == 0) {\n                    return true;\n                }\n            } else if (event.getAction() == KeyEvent.ACTION_UP) {\n                if (SDLControllerManager.onNativePadUp(deviceId, keyCode) == 0) {\n                    return true;\n                }\n            }\n        }\n\n        if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {\n            // on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses\n            // they are ignored here because sending them as mouse input to SDL is messy\n            if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {\n                switch (event.getAction()) {\n                case KeyEvent.ACTION_DOWN:\n                case KeyEvent.ACTION_UP:\n                    // mark the event as handled or it will be handled by system\n                    // handling KEYCODE_BACK by system will call onBackPressed()\n                    return true;\n                }\n            }\n        }\n\n        if (event.getAction() == KeyEvent.ACTION_DOWN) {\n            if (isTextInputEvent(event)) {\n                if (ic != null) {\n                    ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);\n                } else {\n                    SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);\n                }\n            }\n            onNativeKeyDown(keyCode);\n            return true;\n        } else if (event.getAction() == KeyEvent.ACTION_UP) {\n            onNativeKeyUp(keyCode);\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static Surface getNativeSurface() {\n        if (SDLActivity.mSurface == null) {\n            return null;\n        }\n        return SDLActivity.mSurface.getNativeSurface();\n    }\n\n    // Input\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void initTouch() {\n        int[] ids = InputDevice.getDeviceIds();\n\n        for (int id : ids) {\n            InputDevice device = InputDevice.getDevice(id);\n            /* Allow SOURCE_TOUCHSCREEN and also Virtual InputDevices because they can send TOUCHSCREEN events */\n            if (device != null && ((device.getSources() & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN\n                    || device.isVirtual())) {\n\n                int touchDevId = device.getId();\n                /*\n                 * Prevent id to be -1, since it's used in SDL internal for synthetic events\n                 * Appears when using Android emulator, eg:\n                 *  adb shell input mouse tap 100 100\n                 *  adb shell input touchscreen tap 100 100\n                 */\n                if (touchDevId < 0) {\n                    touchDevId -= 1;\n                }\n                nativeAddTouch(touchDevId, device.getName());\n            }\n        }\n    }\n\n    // Messagebox\n\n    /** Result of current messagebox. Also used for blocking the calling thread. */\n    protected final int[] messageboxSelection = new int[1];\n\n    /**\n     * This method is called by SDL using JNI.\n     * Shows the messagebox from UI thread and block calling thread.\n     * buttonFlags, buttonIds and buttonTexts must have same length.\n     * @param buttonFlags array containing flags for every button.\n     * @param buttonIds array containing id for every button.\n     * @param buttonTexts array containing text for every button.\n     * @param colors null for default or array of length 5 containing colors.\n     * @return button id or -1.\n     */\n    public int messageboxShowMessageBox(\n            final int flags,\n            final String title,\n            final String message,\n            final int[] buttonFlags,\n            final int[] buttonIds,\n            final String[] buttonTexts,\n            final int[] colors) {\n\n        messageboxSelection[0] = -1;\n\n        // sanity checks\n\n        if ((buttonFlags.length != buttonIds.length) && (buttonIds.length != buttonTexts.length)) {\n            return -1; // implementation broken\n        }\n\n        // collect arguments for Dialog\n\n        final Bundle args = new Bundle();\n        args.putInt(\"flags\", flags);\n        args.putString(\"title\", title);\n        args.putString(\"message\", message);\n        args.putIntArray(\"buttonFlags\", buttonFlags);\n        args.putIntArray(\"buttonIds\", buttonIds);\n        args.putStringArray(\"buttonTexts\", buttonTexts);\n        args.putIntArray(\"colors\", colors);\n\n        // trigger Dialog creation on UI thread\n\n        runOnUiThread(new Runnable() {\n            @Override\n            public void run() {\n                messageboxCreateAndShow(args);\n            }\n        });\n\n        // block the calling thread\n\n        synchronized (messageboxSelection) {\n            try {\n                messageboxSelection.wait();\n            } catch (InterruptedException ex) {\n                ex.printStackTrace();\n                return -1;\n            }\n        }\n\n        // return selected value\n\n        return messageboxSelection[0];\n    }\n\n    protected void messageboxCreateAndShow(Bundle args) {\n\n        // TODO set values from \"flags\" to messagebox dialog\n\n        // get colors\n\n        int[] colors = args.getIntArray(\"colors\");\n        int backgroundColor;\n        int textColor;\n        int buttonBorderColor;\n        int buttonBackgroundColor;\n        int buttonSelectedColor;\n        if (colors != null) {\n            int i = -1;\n            backgroundColor = colors[++i];\n            textColor = colors[++i];\n            buttonBorderColor = colors[++i];\n            buttonBackgroundColor = colors[++i];\n            buttonSelectedColor = colors[++i];\n        } else {\n            backgroundColor = Color.TRANSPARENT;\n            textColor = Color.TRANSPARENT;\n            buttonBorderColor = Color.TRANSPARENT;\n            buttonBackgroundColor = Color.TRANSPARENT;\n            buttonSelectedColor = Color.TRANSPARENT;\n        }\n\n        // create dialog with title and a listener to wake up calling thread\n\n        final AlertDialog dialog = new AlertDialog.Builder(this).create();\n        dialog.setTitle(args.getString(\"title\"));\n        dialog.setCancelable(false);\n        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {\n            @Override\n            public void onDismiss(DialogInterface unused) {\n                synchronized (messageboxSelection) {\n                    messageboxSelection.notify();\n                }\n            }\n        });\n\n        // create text\n\n        TextView message = new TextView(this);\n        message.setGravity(Gravity.CENTER);\n        message.setText(args.getString(\"message\"));\n        if (textColor != Color.TRANSPARENT) {\n            message.setTextColor(textColor);\n        }\n\n        // create buttons\n\n        int[] buttonFlags = args.getIntArray(\"buttonFlags\");\n        int[] buttonIds = args.getIntArray(\"buttonIds\");\n        String[] buttonTexts = args.getStringArray(\"buttonTexts\");\n\n        final SparseArray<Button> mapping = new SparseArray<Button>();\n\n        LinearLayout buttons = new LinearLayout(this);\n        buttons.setOrientation(LinearLayout.HORIZONTAL);\n        buttons.setGravity(Gravity.CENTER);\n        for (int i = 0; i < buttonTexts.length; ++i) {\n            Button button = new Button(this);\n            final int id = buttonIds[i];\n            button.setOnClickListener(new View.OnClickListener() {\n                @Override\n                public void onClick(View v) {\n                    messageboxSelection[0] = id;\n                    dialog.dismiss();\n                }\n            });\n            if (buttonFlags[i] != 0) {\n                // see SDL_messagebox.h\n                if ((buttonFlags[i] & 0x00000001) != 0) {\n                    mapping.put(KeyEvent.KEYCODE_ENTER, button);\n                }\n                if ((buttonFlags[i] & 0x00000002) != 0) {\n                    mapping.put(KeyEvent.KEYCODE_ESCAPE, button); /* API 11 */\n                }\n            }\n            button.setText(buttonTexts[i]);\n            if (textColor != Color.TRANSPARENT) {\n                button.setTextColor(textColor);\n            }\n            if (buttonBorderColor != Color.TRANSPARENT) {\n                // TODO set color for border of messagebox button\n            }\n            if (buttonBackgroundColor != Color.TRANSPARENT) {\n                Drawable drawable = button.getBackground();\n                if (drawable == null) {\n                    // setting the color this way removes the style\n                    button.setBackgroundColor(buttonBackgroundColor);\n                } else {\n                    // setting the color this way keeps the style (gradient, padding, etc.)\n                    drawable.setColorFilter(buttonBackgroundColor, PorterDuff.Mode.MULTIPLY);\n                }\n            }\n            if (buttonSelectedColor != Color.TRANSPARENT) {\n                // TODO set color for selected messagebox button\n            }\n            buttons.addView(button);\n        }\n\n        // create content\n\n        LinearLayout content = new LinearLayout(this);\n        content.setOrientation(LinearLayout.VERTICAL);\n        content.addView(message);\n        content.addView(buttons);\n        if (backgroundColor != Color.TRANSPARENT) {\n            content.setBackgroundColor(backgroundColor);\n        }\n\n        // add content to dialog and return\n\n        dialog.setView(content);\n        dialog.setOnKeyListener(new Dialog.OnKeyListener() {\n            @Override\n            public boolean onKey(DialogInterface d, int keyCode, KeyEvent event) {\n                Button button = mapping.get(keyCode);\n                if (button != null) {\n                    if (event.getAction() == KeyEvent.ACTION_UP) {\n                        button.performClick();\n                    }\n                    return true; // also for ignored actions\n                }\n                return false;\n            }\n        });\n\n        dialog.show();\n    }\n\n    private final Runnable rehideSystemUi = new Runnable() {\n        @Override\n        public void run() {\n            if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {\n                int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |\n                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |\n                        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |\n                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |\n                        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |\n                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;\n\n                SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags);\n            }\n        }\n    };\n\n    public void onSystemUiVisibilityChange(int visibility) {\n        if (SDLActivity.mFullscreenModeActive && ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 || (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0)) {\n\n            Handler handler = getWindow().getDecorView().getHandler();\n            if (handler != null) {\n                handler.removeCallbacks(rehideSystemUi); // Prevent a hide loop.\n                handler.postDelayed(rehideSystemUi, 2000);\n            }\n\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean clipboardHasText() {\n        return mClipboardHandler.clipboardHasText();\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static String clipboardGetText() {\n        return mClipboardHandler.clipboardGetText();\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void clipboardSetText(String string) {\n        mClipboardHandler.clipboardSetText(string);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static int createCustomCursor(int[] colors, int width, int height, int hotSpotX, int hotSpotY) {\n        Bitmap bitmap = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);\n        ++mLastCursorID;\n\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            try {\n                mCursors.put(mLastCursorID, PointerIcon.create(bitmap, hotSpotX, hotSpotY));\n            } catch (Exception e) {\n                return 0;\n            }\n        } else {\n            return 0;\n        }\n        return mLastCursorID;\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void destroyCustomCursor(int cursorID) {\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            try {\n                mCursors.remove(cursorID);\n            } catch (Exception e) {\n            }\n        }\n        return;\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean setCustomCursor(int cursorID) {\n\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            try {\n                mSurface.setPointerIcon(mCursors.get(cursorID));\n            } catch (Exception e) {\n                return false;\n            }\n        } else {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static boolean setSystemCursor(int cursorID) {\n        int cursor_type = 0; //PointerIcon.TYPE_NULL;\n        switch (cursorID) {\n        case SDL_SYSTEM_CURSOR_ARROW:\n            cursor_type = 1000; //PointerIcon.TYPE_ARROW;\n            break;\n        case SDL_SYSTEM_CURSOR_IBEAM:\n            cursor_type = 1008; //PointerIcon.TYPE_TEXT;\n            break;\n        case SDL_SYSTEM_CURSOR_WAIT:\n            cursor_type = 1004; //PointerIcon.TYPE_WAIT;\n            break;\n        case SDL_SYSTEM_CURSOR_CROSSHAIR:\n            cursor_type = 1007; //PointerIcon.TYPE_CROSSHAIR;\n            break;\n        case SDL_SYSTEM_CURSOR_WAITARROW:\n            cursor_type = 1004; //PointerIcon.TYPE_WAIT;\n            break;\n        case SDL_SYSTEM_CURSOR_SIZENWSE:\n            cursor_type = 1017; //PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW;\n            break;\n        case SDL_SYSTEM_CURSOR_SIZENESW:\n            cursor_type = 1016; //PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;\n            break;\n        case SDL_SYSTEM_CURSOR_SIZEWE:\n            cursor_type = 1014; //PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;\n            break;\n        case SDL_SYSTEM_CURSOR_SIZENS:\n            cursor_type = 1015; //PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;\n            break;\n        case SDL_SYSTEM_CURSOR_SIZEALL:\n            cursor_type = 1020; //PointerIcon.TYPE_GRAB;\n            break;\n        case SDL_SYSTEM_CURSOR_NO:\n            cursor_type = 1012; //PointerIcon.TYPE_NO_DROP;\n            break;\n        case SDL_SYSTEM_CURSOR_HAND:\n            cursor_type = 1002; //PointerIcon.TYPE_HAND;\n            break;\n        }\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            try {\n                mSurface.setPointerIcon(PointerIcon.getSystemIcon(SDL.getContext(), cursor_type));\n            } catch (Exception e) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void requestPermission(String permission, int requestCode) {\n        if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {\n            nativePermissionResult(requestCode, true);\n            return;\n        }\n\n        Activity activity = (Activity)getContext();\n        if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {\n            activity.requestPermissions(new String[]{permission}, requestCode);\n        } else {\n            nativePermissionResult(requestCode, true);\n        }\n    }\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {\n        boolean result = (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED);\n        nativePermissionResult(requestCode, result);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static int openURL(String url)\n    {\n        try {\n            Intent i = new Intent(Intent.ACTION_VIEW);\n            i.setData(Uri.parse(url));\n\n            int flags = Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_MULTIPLE_TASK;\n            if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {\n                flags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;\n            } else {\n                flags |= Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;\n            }\n            i.addFlags(flags);\n\n            mSingleton.startActivity(i);\n        } catch (Exception ex) {\n            return -1;\n        }\n        return 0;\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static int showToast(String message, int duration, int gravity, int xOffset, int yOffset)\n    {\n        if(null == mSingleton) {\n            return - 1;\n        }\n\n        try\n        {\n            class OneShotTask implements Runnable {\n                String mMessage;\n                int mDuration;\n                int mGravity;\n                int mXOffset;\n                int mYOffset;\n\n                OneShotTask(String message, int duration, int gravity, int xOffset, int yOffset) {\n                    mMessage  = message;\n                    mDuration = duration;\n                    mGravity  = gravity;\n                    mXOffset  = xOffset;\n                    mYOffset  = yOffset;\n                }\n\n                public void run() {\n                    try\n                    {\n                        Toast toast = Toast.makeText(mSingleton, mMessage, mDuration);\n                        if (mGravity >= 0) {\n                            toast.setGravity(mGravity, mXOffset, mYOffset);\n                        }\n                        toast.show();\n                    } catch(Exception ex) {\n                        Log.e(TAG, ex.getMessage());\n                    }\n                }\n            }\n            mSingleton.runOnUiThread(new OneShotTask(message, duration, gravity, xOffset, yOffset));\n        } catch(Exception ex) {\n            return -1;\n        }\n        return 0;\n    }\n}\n\n/**\n    Simple runnable to start the SDL application\n*/\nclass SDLMain implements Runnable {\n    @Override\n    public void run() {\n        // Runs SDL_main()\n        String library = SDLActivity.mSingleton.getMainSharedObject();\n        String function = SDLActivity.mSingleton.getMainFunction();\n        String[] arguments = SDLActivity.mSingleton.getArguments();\n\n        try {\n            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DISPLAY);\n        } catch (Exception e) {\n            Log.v(\"SDL\", \"modify thread properties failed \" + e.toString());\n        }\n\n        Log.v(\"SDL\", \"Running main function \" + function + \" from library \" + library);\n\n        SDLActivity.nativeRunMain(library, function, arguments);\n\n        Log.v(\"SDL\", \"Finished main function\");\n\n        if (SDLActivity.mSingleton != null && !SDLActivity.mSingleton.isFinishing()) {\n            // Let's finish the Activity\n            SDLActivity.mSDLThread = null;\n            SDLActivity.mSingleton.finish();\n        }  // else: Activity is already being destroyed\n\n    }\n}\n\n/* This is a fake invisible editor view that receives the input and defines the\n * pan&scan region\n */\nclass DummyEdit extends View implements View.OnKeyListener {\n    InputConnection ic;\n\n    public DummyEdit(Context context) {\n        super(context);\n        setFocusableInTouchMode(true);\n        setFocusable(true);\n        setOnKeyListener(this);\n    }\n\n    @Override\n    public boolean onCheckIsTextEditor() {\n        return true;\n    }\n\n    @Override\n    public boolean onKey(View v, int keyCode, KeyEvent event) {\n        return SDLActivity.handleKeyEvent(v, keyCode, event, ic);\n    }\n\n    //\n    @Override\n    public boolean onKeyPreIme (int keyCode, KeyEvent event) {\n        // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event\n        // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639\n        // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not\n        // FIXME: A more effective solution would be to assume our Layout to be RelativeLayout or LinearLayout\n        // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android\n        // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)\n        if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {\n            if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) {\n                SDLActivity.onNativeKeyboardFocusLost();\n            }\n        }\n        return super.onKeyPreIme(keyCode, event);\n    }\n\n    @Override\n    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {\n        ic = new SDLInputConnection(this, true);\n\n        outAttrs.inputType = InputType.TYPE_CLASS_TEXT |\n                             InputType.TYPE_TEXT_FLAG_MULTI_LINE;\n        outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI |\n                              EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;\n\n        return ic;\n    }\n}\n\nclass SDLInputConnection extends BaseInputConnection {\n\n    protected EditText mEditText;\n    protected String mCommittedText = \"\";\n\n    public SDLInputConnection(View targetView, boolean fullEditor) {\n        super(targetView, fullEditor);\n        mEditText = new EditText(SDL.getContext());\n    }\n\n    @Override\n    public Editable getEditable() {\n        return mEditText.getEditableText();\n    }\n\n    @Override\n    public boolean sendKeyEvent(KeyEvent event) {\n        /*\n         * This used to handle the keycodes from soft keyboard (and IME-translated input from hardkeyboard)\n         * However, as of Ice Cream Sandwich and later, almost all soft keyboard doesn't generate key presses\n         * and so we need to generate them ourselves in commitText.  To avoid duplicates on the handful of keys\n         * that still do, we empty this out.\n         */\n\n        /*\n         * Return DOES still generate a key event, however.  So rather than using it as the 'click a button' key\n         * as we do with physical keyboards, let's just use it to hide the keyboard.\n         */\n\n        if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {\n            if (SDLActivity.onNativeSoftReturnKey()) {\n                return true;\n            }\n        }\n\n        return super.sendKeyEvent(event);\n    }\n\n    @Override\n    public boolean commitText(CharSequence text, int newCursorPosition) {\n        if (!super.commitText(text, newCursorPosition)) {\n            return false;\n        }\n        updateText();\n        return true;\n    }\n\n    @Override\n    public boolean setComposingText(CharSequence text, int newCursorPosition) {\n        if (!super.setComposingText(text, newCursorPosition)) {\n            return false;\n        }\n        updateText();\n        return true;\n    }\n\n    @Override\n    public boolean deleteSurroundingText(int beforeLength, int afterLength) {\n        if (Build.VERSION.SDK_INT <= 29 /* Android 10.0 (Q) */) {\n            // Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection\n            // and https://bugzilla.libsdl.org/show_bug.cgi?id=2265\n            if (beforeLength > 0 && afterLength == 0) {\n                // backspace(s)\n                while (beforeLength-- > 0) {\n                    nativeGenerateScancodeForUnichar('\\b');\n                }\n                return true;\n           }\n        }\n\n        if (!super.deleteSurroundingText(beforeLength, afterLength)) {\n            return false;\n        }\n        updateText();\n        return true;\n    }\n\n    protected void updateText() {\n        final Editable content = getEditable();\n        if (content == null) {\n            return;\n        }\n\n        String text = content.toString();\n        int compareLength = Math.min(text.length(), mCommittedText.length());\n        int matchLength, offset;\n\n        /* Backspace over characters that are no longer in the string */\n        for (matchLength = 0; matchLength < compareLength; ) {\n            int codePoint = mCommittedText.codePointAt(matchLength);\n            if (codePoint != text.codePointAt(matchLength)) {\n                break;\n            }\n            matchLength += Character.charCount(codePoint);\n        }\n        /* FIXME: This doesn't handle graphemes, like '🌬️' */\n        for (offset = matchLength; offset < mCommittedText.length(); ) {\n            int codePoint = mCommittedText.codePointAt(offset);\n            nativeGenerateScancodeForUnichar('\\b');\n            offset += Character.charCount(codePoint);\n        }\n\n        if (matchLength < text.length()) {\n            String pendingText = text.subSequence(matchLength, text.length()).toString();\n            for (offset = 0; offset < pendingText.length(); ) {\n                int codePoint = pendingText.codePointAt(offset);\n                if (codePoint == '\\n') {\n                    if (SDLActivity.onNativeSoftReturnKey()) {\n                        return;\n                    }\n                }\n                /* Higher code points don't generate simulated scancodes */\n                if (codePoint < 128) {\n                    nativeGenerateScancodeForUnichar((char)codePoint);\n                }\n                offset += Character.charCount(codePoint);\n            }\n            SDLInputConnection.nativeCommitText(pendingText, 0);\n        }\n        mCommittedText = text;\n    }\n\n    public static native void nativeCommitText(String text, int newCursorPosition);\n\n    public static native void nativeGenerateScancodeForUnichar(char c);\n}\n\nclass SDLClipboardHandler implements\n    ClipboardManager.OnPrimaryClipChangedListener {\n\n    protected ClipboardManager mClipMgr;\n\n    SDLClipboardHandler() {\n       mClipMgr = (ClipboardManager) SDL.getContext().getSystemService(Context.CLIPBOARD_SERVICE);\n       mClipMgr.addPrimaryClipChangedListener(this);\n    }\n\n    public boolean clipboardHasText() {\n       return mClipMgr.hasPrimaryClip();\n    }\n\n    public String clipboardGetText() {\n        ClipData clip = mClipMgr.getPrimaryClip();\n        if (clip != null) {\n            ClipData.Item item = clip.getItemAt(0);\n            if (item != null) {\n                CharSequence text = item.getText();\n                if (text != null) {\n                    return text.toString();\n                }\n            }\n        }\n        return null;\n    }\n\n    public void clipboardSetText(String string) {\n       mClipMgr.removePrimaryClipChangedListener(this);\n       ClipData clip = ClipData.newPlainText(null, string);\n       mClipMgr.setPrimaryClip(clip);\n       mClipMgr.addPrimaryClipChangedListener(this);\n    }\n\n    @Override\n    public void onPrimaryClipChanged() {\n        SDLActivity.onNativeClipboardChanged();\n    }\n}\n\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/SDLAudioManager.java",
    "content": "package org.libsdl.app;\n\nimport android.content.Context;\nimport android.media.AudioDeviceCallback;\nimport android.media.AudioDeviceInfo;\nimport android.media.AudioFormat;\nimport android.media.AudioManager;\nimport android.media.AudioRecord;\nimport android.media.AudioTrack;\nimport android.media.MediaRecorder;\nimport android.os.Build;\nimport android.util.Log;\n\nimport java.util.Arrays;\n\npublic class SDLAudioManager {\n    protected static final String TAG = \"SDLAudio\";\n\n    protected static AudioTrack mAudioTrack;\n    protected static AudioRecord mAudioRecord;\n    protected static Context mContext;\n\n    private static final int[] NO_DEVICES = {};\n\n    private static AudioDeviceCallback mAudioDeviceCallback;\n\n    public static void initialize() {\n        mAudioTrack = null;\n        mAudioRecord = null;\n        mAudioDeviceCallback = null;\n\n        if(Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */)\n        {\n            mAudioDeviceCallback = new AudioDeviceCallback() {\n                @Override\n                public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {\n                    Arrays.stream(addedDevices).forEach(deviceInfo -> addAudioDevice(deviceInfo.isSink(), deviceInfo.getId()));\n                }\n\n                @Override\n                public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {\n                    Arrays.stream(removedDevices).forEach(deviceInfo -> removeAudioDevice(deviceInfo.isSink(), deviceInfo.getId()));\n                }\n            };\n        }\n    }\n\n    public static void setContext(Context context) {\n        mContext = context;\n        if (context != null) {\n            registerAudioDeviceCallback();\n        }\n    }\n\n    public static void release(Context context) {\n        unregisterAudioDeviceCallback(context);\n    }\n\n    // Audio\n\n    protected static String getAudioFormatString(int audioFormat) {\n        switch (audioFormat) {\n            case AudioFormat.ENCODING_PCM_8BIT:\n                return \"8-bit\";\n            case AudioFormat.ENCODING_PCM_16BIT:\n                return \"16-bit\";\n            case AudioFormat.ENCODING_PCM_FLOAT:\n                return \"float\";\n            default:\n                return Integer.toString(audioFormat);\n        }\n    }\n\n    protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {\n        int channelConfig;\n        int sampleSize;\n        int frameSize;\n\n        Log.v(TAG, \"Opening \" + (isCapture ? \"capture\" : \"playback\") + \", requested \" + desiredFrames + \" frames of \" + desiredChannels + \" channel \" + getAudioFormatString(audioFormat) + \" audio at \" + sampleRate + \" Hz\");\n\n        /* On older devices let's use known good settings */\n        if (Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {\n            if (desiredChannels > 2) {\n                desiredChannels = 2;\n            }\n        }\n\n        /* AudioTrack has sample rate limitation of 48000 (fixed in 5.0.2) */\n        if (Build.VERSION.SDK_INT < 22 /* Android 5.1 (LOLLIPOP_MR1) */) {\n            if (sampleRate < 8000) {\n                sampleRate = 8000;\n            } else if (sampleRate > 48000) {\n                sampleRate = 48000;\n            }\n        }\n\n        if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) {\n            int minSDKVersion = (isCapture ? 23 /* Android 6.0 (M) */ : 21 /* Android 5.0 (LOLLIPOP) */);\n            if (Build.VERSION.SDK_INT < minSDKVersion) {\n                audioFormat = AudioFormat.ENCODING_PCM_16BIT;\n            }\n        }\n        switch (audioFormat)\n        {\n        case AudioFormat.ENCODING_PCM_8BIT:\n            sampleSize = 1;\n            break;\n        case AudioFormat.ENCODING_PCM_16BIT:\n            sampleSize = 2;\n            break;\n        case AudioFormat.ENCODING_PCM_FLOAT:\n            sampleSize = 4;\n            break;\n        default:\n            Log.v(TAG, \"Requested format \" + audioFormat + \", getting ENCODING_PCM_16BIT\");\n            audioFormat = AudioFormat.ENCODING_PCM_16BIT;\n            sampleSize = 2;\n            break;\n        }\n\n        if (isCapture) {\n            switch (desiredChannels) {\n            case 1:\n                channelConfig = AudioFormat.CHANNEL_IN_MONO;\n                break;\n            case 2:\n                channelConfig = AudioFormat.CHANNEL_IN_STEREO;\n                break;\n            default:\n                Log.v(TAG, \"Requested \" + desiredChannels + \" channels, getting stereo\");\n                desiredChannels = 2;\n                channelConfig = AudioFormat.CHANNEL_IN_STEREO;\n                break;\n            }\n        } else {\n            switch (desiredChannels) {\n            case 1:\n                channelConfig = AudioFormat.CHANNEL_OUT_MONO;\n                break;\n            case 2:\n                channelConfig = AudioFormat.CHANNEL_OUT_STEREO;\n                break;\n            case 3:\n                channelConfig = AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER;\n                break;\n            case 4:\n                channelConfig = AudioFormat.CHANNEL_OUT_QUAD;\n                break;\n            case 5:\n                channelConfig = AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER;\n                break;\n            case 6:\n                channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;\n                break;\n            case 7:\n                channelConfig = AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;\n                break;\n            case 8:\n                if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) {\n                    channelConfig = AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;\n                } else {\n                    Log.v(TAG, \"Requested \" + desiredChannels + \" channels, getting 5.1 surround\");\n                    desiredChannels = 6;\n                    channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;\n                }\n                break;\n            default:\n                Log.v(TAG, \"Requested \" + desiredChannels + \" channels, getting stereo\");\n                desiredChannels = 2;\n                channelConfig = AudioFormat.CHANNEL_OUT_STEREO;\n                break;\n            }\n\n/*\n            Log.v(TAG, \"Speaker configuration (and order of channels):\");\n\n            if ((channelConfig & 0x00000004) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_FRONT_LEFT\");\n            }\n            if ((channelConfig & 0x00000008) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_FRONT_RIGHT\");\n            }\n            if ((channelConfig & 0x00000010) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_FRONT_CENTER\");\n            }\n            if ((channelConfig & 0x00000020) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_LOW_FREQUENCY\");\n            }\n            if ((channelConfig & 0x00000040) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_BACK_LEFT\");\n            }\n            if ((channelConfig & 0x00000080) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_BACK_RIGHT\");\n            }\n            if ((channelConfig & 0x00000100) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_FRONT_LEFT_OF_CENTER\");\n            }\n            if ((channelConfig & 0x00000200) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_FRONT_RIGHT_OF_CENTER\");\n            }\n            if ((channelConfig & 0x00000400) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_BACK_CENTER\");\n            }\n            if ((channelConfig & 0x00000800) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_SIDE_LEFT\");\n            }\n            if ((channelConfig & 0x00001000) != 0) {\n                Log.v(TAG, \"   CHANNEL_OUT_SIDE_RIGHT\");\n            }\n*/\n        }\n        frameSize = (sampleSize * desiredChannels);\n\n        // Let the user pick a larger buffer if they really want -- but ye\n        // gods they probably shouldn't, the minimums are horrifyingly high\n        // latency already\n        int minBufferSize;\n        if (isCapture) {\n            minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);\n        } else {\n            minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);\n        }\n        desiredFrames = Math.max(desiredFrames, (minBufferSize + frameSize - 1) / frameSize);\n\n        int[] results = new int[4];\n\n        if (isCapture) {\n            if (mAudioRecord == null) {\n                mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate,\n                        channelConfig, audioFormat, desiredFrames * frameSize);\n\n                // see notes about AudioTrack state in audioOpen(), above. Probably also applies here.\n                if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {\n                    Log.e(TAG, \"Failed during initialization of AudioRecord\");\n                    mAudioRecord.release();\n                    mAudioRecord = null;\n                    return null;\n                }\n\n                if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {\n                    mAudioRecord.setPreferredDevice(getOutputAudioDeviceInfo(deviceId));\n                }\n\n                mAudioRecord.startRecording();\n            }\n\n            results[0] = mAudioRecord.getSampleRate();\n            results[1] = mAudioRecord.getAudioFormat();\n            results[2] = mAudioRecord.getChannelCount();\n\n        } else {\n            if (mAudioTrack == null) {\n                mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);\n\n                // Instantiating AudioTrack can \"succeed\" without an exception and the track may still be invalid\n                // Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java\n                // Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()\n                if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {\n                    /* Try again, with safer values */\n\n                    Log.e(TAG, \"Failed during initialization of Audio Track\");\n                    mAudioTrack.release();\n                    mAudioTrack = null;\n                    return null;\n                }\n\n                if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {\n                    mAudioTrack.setPreferredDevice(getInputAudioDeviceInfo(deviceId));\n                }\n\n                mAudioTrack.play();\n            }\n\n            results[0] = mAudioTrack.getSampleRate();\n            results[1] = mAudioTrack.getAudioFormat();\n            results[2] = mAudioTrack.getChannelCount();\n        }\n        results[3] = desiredFrames;\n\n        Log.v(TAG, \"Opening \" + (isCapture ? \"capture\" : \"playback\") + \", got \" + results[3] + \" frames of \" + results[2] + \" channel \" + getAudioFormatString(results[1]) + \" audio at \" + results[0] + \" Hz\");\n\n        return results;\n    }\n\n    private static AudioDeviceInfo getInputAudioDeviceInfo(int deviceId) {\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);\n            return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS))\n                    .filter(deviceInfo -> deviceInfo.getId() == deviceId)\n                    .findFirst()\n                    .orElse(null);\n        } else {\n            return null;\n        }\n    }\n\n    private static AudioDeviceInfo getOutputAudioDeviceInfo(int deviceId) {\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);\n            return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS))\n                    .filter(deviceInfo -> deviceInfo.getId() == deviceId)\n                    .findFirst()\n                    .orElse(null);\n        } else {\n            return null;\n        }\n    }\n\n    private static void registerAudioDeviceCallback() {\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);\n            audioManager.registerAudioDeviceCallback(mAudioDeviceCallback, null);\n        }\n    }\n\n    private static void unregisterAudioDeviceCallback(Context context) {\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);\n            audioManager.unregisterAudioDeviceCallback(mAudioDeviceCallback);\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static int[] getAudioOutputDevices() {\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);\n            return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)).mapToInt(AudioDeviceInfo::getId).toArray();\n        } else {\n            return NO_DEVICES;\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static int[] getAudioInputDevices() {\n        if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);\n            return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).mapToInt(AudioDeviceInfo::getId).toArray();\n        } else {\n            return NO_DEVICES;\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {\n        return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void audioWriteFloatBuffer(float[] buffer) {\n        if (mAudioTrack == null) {\n            Log.e(TAG, \"Attempted to make audio call with uninitialized audio!\");\n            return;\n        }\n\n        if (android.os.Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {\n            Log.e(TAG, \"Attempted to make an incompatible audio call with uninitialized audio! (floating-point output is supported since Android 5.0 Lollipop)\");\n            return;\n        }\n\n        for (int i = 0; i < buffer.length;) {\n            int result = mAudioTrack.write(buffer, i, buffer.length - i, AudioTrack.WRITE_BLOCKING);\n            if (result > 0) {\n                i += result;\n            } else if (result == 0) {\n                try {\n                    Thread.sleep(1);\n                } catch(InterruptedException e) {\n                    // Nom nom\n                }\n            } else {\n                Log.w(TAG, \"SDL audio: error return from write(float)\");\n                return;\n            }\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void audioWriteShortBuffer(short[] buffer) {\n        if (mAudioTrack == null) {\n            Log.e(TAG, \"Attempted to make audio call with uninitialized audio!\");\n            return;\n        }\n\n        for (int i = 0; i < buffer.length;) {\n            int result = mAudioTrack.write(buffer, i, buffer.length - i);\n            if (result > 0) {\n                i += result;\n            } else if (result == 0) {\n                try {\n                    Thread.sleep(1);\n                } catch(InterruptedException e) {\n                    // Nom nom\n                }\n            } else {\n                Log.w(TAG, \"SDL audio: error return from write(short)\");\n                return;\n            }\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void audioWriteByteBuffer(byte[] buffer) {\n        if (mAudioTrack == null) {\n            Log.e(TAG, \"Attempted to make audio call with uninitialized audio!\");\n            return;\n        }\n\n        for (int i = 0; i < buffer.length; ) {\n            int result = mAudioTrack.write(buffer, i, buffer.length - i);\n            if (result > 0) {\n                i += result;\n            } else if (result == 0) {\n                try {\n                    Thread.sleep(1);\n                } catch(InterruptedException e) {\n                    // Nom nom\n                }\n            } else {\n                Log.w(TAG, \"SDL audio: error return from write(byte)\");\n                return;\n            }\n        }\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {\n        return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);\n    }\n\n    /** This method is called by SDL using JNI. */\n    public static int captureReadFloatBuffer(float[] buffer, boolean blocking) {\n        if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {\n            return 0;\n        } else {\n            return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);\n        }\n    }\n\n    /** This method is called by SDL using JNI. */\n    public static int captureReadShortBuffer(short[] buffer, boolean blocking) {\n        if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {\n            return mAudioRecord.read(buffer, 0, buffer.length);\n        } else {\n            return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);\n        }\n    }\n\n    /** This method is called by SDL using JNI. */\n    public static int captureReadByteBuffer(byte[] buffer, boolean blocking) {\n        if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {\n            return mAudioRecord.read(buffer, 0, buffer.length);\n        } else {\n            return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);\n        }\n    }\n\n    /** This method is called by SDL using JNI. */\n    public static void audioClose() {\n        if (mAudioTrack != null) {\n            mAudioTrack.stop();\n            mAudioTrack.release();\n            mAudioTrack = null;\n        }\n    }\n\n    /** This method is called by SDL using JNI. */\n    public static void captureClose() {\n        if (mAudioRecord != null) {\n            mAudioRecord.stop();\n            mAudioRecord.release();\n            mAudioRecord = null;\n        }\n    }\n\n    /** This method is called by SDL using JNI. */\n    public static void audioSetThreadPriority(boolean iscapture, int device_id) {\n        try {\n\n            /* Set thread name */\n            if (iscapture) {\n                Thread.currentThread().setName(\"SDLAudioC\" + device_id);\n            } else {\n                Thread.currentThread().setName(\"SDLAudioP\" + device_id);\n            }\n\n            /* Set thread priority */\n            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);\n\n        } catch (Exception e) {\n            Log.v(TAG, \"modify thread properties failed \" + e.toString());\n        }\n    }\n\n    public static native int nativeSetupJNI();\n\n    public static native void removeAudioDevice(boolean isCapture, int deviceId);\n\n    public static native void addAudioDevice(boolean isCapture, int deviceId);\n\n}\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java",
    "content": "package org.libsdl.app;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\n\nimport android.content.Context;\nimport android.os.Build;\nimport android.os.VibrationEffect;\nimport android.os.Vibrator;\nimport android.util.Log;\nimport android.view.InputDevice;\nimport android.view.KeyEvent;\nimport android.view.MotionEvent;\nimport android.view.View;\n\n\npublic class SDLControllerManager\n{\n\n    public static native int nativeSetupJNI();\n\n    public static native int nativeAddJoystick(int device_id, String name, String desc,\n                                               int vendor_id, int product_id,\n                                               boolean is_accelerometer, int button_mask,\n                                               int naxes, int axis_mask, int nhats, int nballs);\n    public static native int nativeRemoveJoystick(int device_id);\n    public static native int nativeAddHaptic(int device_id, String name);\n    public static native int nativeRemoveHaptic(int device_id);\n    public static native int onNativePadDown(int device_id, int keycode);\n    public static native int onNativePadUp(int device_id, int keycode);\n    public static native void onNativeJoy(int device_id, int axis,\n                                          float value);\n    public static native void onNativeHat(int device_id, int hat_id,\n                                          int x, int y);\n\n    protected static SDLJoystickHandler mJoystickHandler;\n    protected static SDLHapticHandler mHapticHandler;\n\n    private static final String TAG = \"SDLControllerManager\";\n\n    public static void initialize() {\n        if (mJoystickHandler == null) {\n            if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {\n                mJoystickHandler = new SDLJoystickHandler_API19();\n            } else {\n                mJoystickHandler = new SDLJoystickHandler_API16();\n            }\n        }\n\n        if (mHapticHandler == null) {\n            if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {\n                mHapticHandler = new SDLHapticHandler_API26();\n            } else {\n                mHapticHandler = new SDLHapticHandler();\n            }\n        }\n    }\n\n    // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance\n    public static boolean handleJoystickMotionEvent(MotionEvent event) {\n        return mJoystickHandler.handleMotionEvent(event);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void pollInputDevices() {\n        mJoystickHandler.pollInputDevices();\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void pollHapticDevices() {\n        mHapticHandler.pollHapticDevices();\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void hapticRun(int device_id, float intensity, int length) {\n        mHapticHandler.run(device_id, intensity, length);\n    }\n\n    /**\n     * This method is called by SDL using JNI.\n     */\n    public static void hapticStop(int device_id)\n    {\n        mHapticHandler.stop(device_id);\n    }\n\n    // Check if a given device is considered a possible SDL joystick\n    public static boolean isDeviceSDLJoystick(int deviceId) {\n        InputDevice device = InputDevice.getDevice(deviceId);\n        // We cannot use InputDevice.isVirtual before API 16, so let's accept\n        // only nonnegative device ids (VIRTUAL_KEYBOARD equals -1)\n        if ((device == null) || (deviceId < 0)) {\n            return false;\n        }\n        int sources = device.getSources();\n\n        /* This is called for every button press, so let's not spam the logs */\n        /*\n        if ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {\n            Log.v(TAG, \"Input device \" + device.getName() + \" has class joystick.\");\n        }\n        if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) {\n            Log.v(TAG, \"Input device \" + device.getName() + \" is a dpad.\");\n        }\n        if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) {\n            Log.v(TAG, \"Input device \" + device.getName() + \" is a gamepad.\");\n        }\n        */\n\n        return ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 ||\n                ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) ||\n                ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)\n        );\n    }\n\n}\n\nclass SDLJoystickHandler {\n\n    /**\n     * Handles given MotionEvent.\n     * @param event the event to be handled.\n     * @return if given event was processed.\n     */\n    public boolean handleMotionEvent(MotionEvent event) {\n        return false;\n    }\n\n    /**\n     * Handles adding and removing of input devices.\n     */\n    public void pollInputDevices() {\n    }\n}\n\n/* Actual joystick functionality available for API >= 12 devices */\nclass SDLJoystickHandler_API16 extends SDLJoystickHandler {\n\n    static class SDLJoystick {\n        public int device_id;\n        public String name;\n        public String desc;\n        public ArrayList<InputDevice.MotionRange> axes;\n        public ArrayList<InputDevice.MotionRange> hats;\n    }\n    static class RangeComparator implements Comparator<InputDevice.MotionRange> {\n        @Override\n        public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {\n            // Some controllers, like the Moga Pro 2, return AXIS_GAS (22) for right trigger and AXIS_BRAKE (23) for left trigger - swap them so they're sorted in the right order for SDL\n            int arg0Axis = arg0.getAxis();\n            int arg1Axis = arg1.getAxis();\n            if (arg0Axis == MotionEvent.AXIS_GAS) {\n                arg0Axis = MotionEvent.AXIS_BRAKE;\n            } else if (arg0Axis == MotionEvent.AXIS_BRAKE) {\n                arg0Axis = MotionEvent.AXIS_GAS;\n            }\n            if (arg1Axis == MotionEvent.AXIS_GAS) {\n                arg1Axis = MotionEvent.AXIS_BRAKE;\n            } else if (arg1Axis == MotionEvent.AXIS_BRAKE) {\n                arg1Axis = MotionEvent.AXIS_GAS;\n            }\n\n            // Make sure the AXIS_Z is sorted between AXIS_RY and AXIS_RZ.\n            // This is because the usual pairing are:\n            // - AXIS_X + AXIS_Y (left stick).\n            // - AXIS_RX, AXIS_RY (sometimes the right stick, sometimes triggers).\n            // - AXIS_Z, AXIS_RZ (sometimes the right stick, sometimes triggers).\n            // This sorts the axes in the above order, which tends to be correct\n            // for Xbox-ish game pads that have the right stick on RX/RY and the\n            // triggers on Z/RZ.\n            //\n            // Gamepads that don't have AXIS_Z/AXIS_RZ but use\n            // AXIS_LTRIGGER/AXIS_RTRIGGER are unaffected by this.\n            //\n            // References:\n            // - https://developer.android.com/develop/ui/views/touch-and-input/game-controllers/controller-input\n            // - https://www.kernel.org/doc/html/latest/input/gamepad.html\n            if (arg0Axis == MotionEvent.AXIS_Z) {\n                arg0Axis = MotionEvent.AXIS_RZ - 1;\n            } else if (arg0Axis > MotionEvent.AXIS_Z && arg0Axis < MotionEvent.AXIS_RZ) {\n                --arg0Axis;\n            }\n            if (arg1Axis == MotionEvent.AXIS_Z) {\n                arg1Axis = MotionEvent.AXIS_RZ - 1;\n            } else if (arg1Axis > MotionEvent.AXIS_Z && arg1Axis < MotionEvent.AXIS_RZ) {\n                --arg1Axis;\n            }\n\n            return arg0Axis - arg1Axis;\n        }\n    }\n\n    private final ArrayList<SDLJoystick> mJoysticks;\n\n    public SDLJoystickHandler_API16() {\n\n        mJoysticks = new ArrayList<SDLJoystick>();\n    }\n\n    @Override\n    public void pollInputDevices() {\n        int[] deviceIds = InputDevice.getDeviceIds();\n\n        for (int device_id : deviceIds) {\n            if (SDLControllerManager.isDeviceSDLJoystick(device_id)) {\n                SDLJoystick joystick = getJoystick(device_id);\n                if (joystick == null) {\n                    InputDevice joystickDevice = InputDevice.getDevice(device_id);\n                    joystick = new SDLJoystick();\n                    joystick.device_id = device_id;\n                    joystick.name = joystickDevice.getName();\n                    joystick.desc = getJoystickDescriptor(joystickDevice);\n                    joystick.axes = new ArrayList<InputDevice.MotionRange>();\n                    joystick.hats = new ArrayList<InputDevice.MotionRange>();\n\n                    List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();\n                    Collections.sort(ranges, new RangeComparator());\n                    for (InputDevice.MotionRange range : ranges) {\n                        if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {\n                            if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {\n                                joystick.hats.add(range);\n                            } else {\n                                joystick.axes.add(range);\n                            }\n                        }\n                    }\n\n                    mJoysticks.add(joystick);\n                    SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,\n                            getVendorId(joystickDevice), getProductId(joystickDevice), false,\n                            getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, 0);\n                }\n            }\n        }\n\n        /* Check removed devices */\n        ArrayList<Integer> removedDevices = null;\n        for (SDLJoystick joystick : mJoysticks) {\n            int device_id = joystick.device_id;\n            int i;\n            for (i = 0; i < deviceIds.length; i++) {\n                if (device_id == deviceIds[i]) break;\n            }\n            if (i == deviceIds.length) {\n                if (removedDevices == null) {\n                    removedDevices = new ArrayList<Integer>();\n                }\n                removedDevices.add(device_id);\n            }\n        }\n\n        if (removedDevices != null) {\n            for (int device_id : removedDevices) {\n                SDLControllerManager.nativeRemoveJoystick(device_id);\n                for (int i = 0; i < mJoysticks.size(); i++) {\n                    if (mJoysticks.get(i).device_id == device_id) {\n                        mJoysticks.remove(i);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    protected SDLJoystick getJoystick(int device_id) {\n        for (SDLJoystick joystick : mJoysticks) {\n            if (joystick.device_id == device_id) {\n                return joystick;\n            }\n        }\n        return null;\n    }\n\n    @Override\n    public boolean handleMotionEvent(MotionEvent event) {\n        int actionPointerIndex = event.getActionIndex();\n        int action = event.getActionMasked();\n        if (action == MotionEvent.ACTION_MOVE) {\n            SDLJoystick joystick = getJoystick(event.getDeviceId());\n            if (joystick != null) {\n                for (int i = 0; i < joystick.axes.size(); i++) {\n                    InputDevice.MotionRange range = joystick.axes.get(i);\n                    /* Normalize the value to -1...1 */\n                    float value = (event.getAxisValue(range.getAxis(), actionPointerIndex) - range.getMin()) / range.getRange() * 2.0f - 1.0f;\n                    SDLControllerManager.onNativeJoy(joystick.device_id, i, value);\n                }\n                for (int i = 0; i < joystick.hats.size() / 2; i++) {\n                    int hatX = Math.round(event.getAxisValue(joystick.hats.get(2 * i).getAxis(), actionPointerIndex));\n                    int hatY = Math.round(event.getAxisValue(joystick.hats.get(2 * i + 1).getAxis(), actionPointerIndex));\n                    SDLControllerManager.onNativeHat(joystick.device_id, i, hatX, hatY);\n                }\n            }\n        }\n        return true;\n    }\n\n    public String getJoystickDescriptor(InputDevice joystickDevice) {\n        String desc = joystickDevice.getDescriptor();\n\n        if (desc != null && !desc.isEmpty()) {\n            return desc;\n        }\n\n        return joystickDevice.getName();\n    }\n    public int getProductId(InputDevice joystickDevice) {\n        return 0;\n    }\n    public int getVendorId(InputDevice joystickDevice) {\n        return 0;\n    }\n    public int getAxisMask(List<InputDevice.MotionRange> ranges) {\n        return -1;\n    }\n    public int getButtonMask(InputDevice joystickDevice) {\n        return -1;\n    }\n}\n\nclass SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {\n\n    @Override\n    public int getProductId(InputDevice joystickDevice) {\n        return joystickDevice.getProductId();\n    }\n\n    @Override\n    public int getVendorId(InputDevice joystickDevice) {\n        return joystickDevice.getVendorId();\n    }\n\n    @Override\n    public int getAxisMask(List<InputDevice.MotionRange> ranges) {\n        // For compatibility, keep computing the axis mask like before,\n        // only really distinguishing 2, 4 and 6 axes.\n        int axis_mask = 0;\n        if (ranges.size() >= 2) {\n            // ((1 << SDL_GAMEPAD_AXIS_LEFTX) | (1 << SDL_GAMEPAD_AXIS_LEFTY))\n            axis_mask |= 0x0003;\n        }\n        if (ranges.size() >= 4) {\n            // ((1 << SDL_GAMEPAD_AXIS_RIGHTX) | (1 << SDL_GAMEPAD_AXIS_RIGHTY))\n            axis_mask |= 0x000c;\n        }\n        if (ranges.size() >= 6) {\n            // ((1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER) | (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER))\n            axis_mask |= 0x0030;\n        }\n        // Also add an indicator bit for whether the sorting order has changed.\n        // This serves to disable outdated gamecontrollerdb.txt mappings.\n        boolean have_z = false;\n        boolean have_past_z_before_rz = false;\n        for (InputDevice.MotionRange range : ranges) {\n            int axis = range.getAxis();\n            if (axis == MotionEvent.AXIS_Z) {\n                have_z = true;\n            } else if (axis > MotionEvent.AXIS_Z && axis < MotionEvent.AXIS_RZ) {\n                have_past_z_before_rz = true;\n            }\n        }\n        if (have_z && have_past_z_before_rz) {\n            // If both these exist, the compare() function changed sorting order.\n            // Set a bit to indicate this fact.\n            axis_mask |= 0x8000;\n        }\n        return axis_mask;\n    }\n\n    @Override\n    public int getButtonMask(InputDevice joystickDevice) {\n        int button_mask = 0;\n        int[] keys = new int[] {\n            KeyEvent.KEYCODE_BUTTON_A,\n            KeyEvent.KEYCODE_BUTTON_B,\n            KeyEvent.KEYCODE_BUTTON_X,\n            KeyEvent.KEYCODE_BUTTON_Y,\n            KeyEvent.KEYCODE_BACK,\n            KeyEvent.KEYCODE_MENU,\n            KeyEvent.KEYCODE_BUTTON_MODE,\n            KeyEvent.KEYCODE_BUTTON_START,\n            KeyEvent.KEYCODE_BUTTON_THUMBL,\n            KeyEvent.KEYCODE_BUTTON_THUMBR,\n            KeyEvent.KEYCODE_BUTTON_L1,\n            KeyEvent.KEYCODE_BUTTON_R1,\n            KeyEvent.KEYCODE_DPAD_UP,\n            KeyEvent.KEYCODE_DPAD_DOWN,\n            KeyEvent.KEYCODE_DPAD_LEFT,\n            KeyEvent.KEYCODE_DPAD_RIGHT,\n            KeyEvent.KEYCODE_BUTTON_SELECT,\n            KeyEvent.KEYCODE_DPAD_CENTER,\n\n            // These don't map into any SDL controller buttons directly\n            KeyEvent.KEYCODE_BUTTON_L2,\n            KeyEvent.KEYCODE_BUTTON_R2,\n            KeyEvent.KEYCODE_BUTTON_C,\n            KeyEvent.KEYCODE_BUTTON_Z,\n            KeyEvent.KEYCODE_BUTTON_1,\n            KeyEvent.KEYCODE_BUTTON_2,\n            KeyEvent.KEYCODE_BUTTON_3,\n            KeyEvent.KEYCODE_BUTTON_4,\n            KeyEvent.KEYCODE_BUTTON_5,\n            KeyEvent.KEYCODE_BUTTON_6,\n            KeyEvent.KEYCODE_BUTTON_7,\n            KeyEvent.KEYCODE_BUTTON_8,\n            KeyEvent.KEYCODE_BUTTON_9,\n            KeyEvent.KEYCODE_BUTTON_10,\n            KeyEvent.KEYCODE_BUTTON_11,\n            KeyEvent.KEYCODE_BUTTON_12,\n            KeyEvent.KEYCODE_BUTTON_13,\n            KeyEvent.KEYCODE_BUTTON_14,\n            KeyEvent.KEYCODE_BUTTON_15,\n            KeyEvent.KEYCODE_BUTTON_16,\n        };\n        int[] masks = new int[] {\n            (1 << 0),   // A -> A\n            (1 << 1),   // B -> B\n            (1 << 2),   // X -> X\n            (1 << 3),   // Y -> Y\n            (1 << 4),   // BACK -> BACK\n            (1 << 6),   // MENU -> START\n            (1 << 5),   // MODE -> GUIDE\n            (1 << 6),   // START -> START\n            (1 << 7),   // THUMBL -> LEFTSTICK\n            (1 << 8),   // THUMBR -> RIGHTSTICK\n            (1 << 9),   // L1 -> LEFTSHOULDER\n            (1 << 10),  // R1 -> RIGHTSHOULDER\n            (1 << 11),  // DPAD_UP -> DPAD_UP\n            (1 << 12),  // DPAD_DOWN -> DPAD_DOWN\n            (1 << 13),  // DPAD_LEFT -> DPAD_LEFT\n            (1 << 14),  // DPAD_RIGHT -> DPAD_RIGHT\n            (1 << 4),   // SELECT -> BACK\n            (1 << 0),   // DPAD_CENTER -> A\n            (1 << 15),  // L2 -> ??\n            (1 << 16),  // R2 -> ??\n            (1 << 17),  // C -> ??\n            (1 << 18),  // Z -> ??\n            (1 << 20),  // 1 -> ??\n            (1 << 21),  // 2 -> ??\n            (1 << 22),  // 3 -> ??\n            (1 << 23),  // 4 -> ??\n            (1 << 24),  // 5 -> ??\n            (1 << 25),  // 6 -> ??\n            (1 << 26),  // 7 -> ??\n            (1 << 27),  // 8 -> ??\n            (1 << 28),  // 9 -> ??\n            (1 << 29),  // 10 -> ??\n            (1 << 30),  // 11 -> ??\n            (1 << 31),  // 12 -> ??\n            // We're out of room...\n            0xFFFFFFFF,  // 13 -> ??\n            0xFFFFFFFF,  // 14 -> ??\n            0xFFFFFFFF,  // 15 -> ??\n            0xFFFFFFFF,  // 16 -> ??\n        };\n        boolean[] has_keys = joystickDevice.hasKeys(keys);\n        for (int i = 0; i < keys.length; ++i) {\n            if (has_keys[i]) {\n                button_mask |= masks[i];\n            }\n        }\n        return button_mask;\n    }\n}\n\nclass SDLHapticHandler_API26 extends SDLHapticHandler {\n    @Override\n    public void run(int device_id, float intensity, int length) {\n        SDLHaptic haptic = getHaptic(device_id);\n        if (haptic != null) {\n            Log.d(\"SDL\", \"Rtest: Vibe with intensity \" + intensity + \" for \" + length);\n            if (intensity == 0.0f) {\n                stop(device_id);\n                return;\n            }\n\n            int vibeValue = Math.round(intensity * 255);\n\n            if (vibeValue > 255) {\n                vibeValue = 255;\n            }\n            if (vibeValue < 1) {\n                stop(device_id);\n                return;\n            }\n            try {\n                haptic.vib.vibrate(VibrationEffect.createOneShot(length, vibeValue));\n            }\n            catch (Exception e) {\n                // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if\n                // something went horribly wrong with the Android 8.0 APIs.\n                haptic.vib.vibrate(length);\n            }\n        }\n    }\n}\n\nclass SDLHapticHandler {\n\n    static class SDLHaptic {\n        public int device_id;\n        public String name;\n        public Vibrator vib;\n    }\n\n    private final ArrayList<SDLHaptic> mHaptics;\n\n    public SDLHapticHandler() {\n        mHaptics = new ArrayList<SDLHaptic>();\n    }\n\n    public void run(int device_id, float intensity, int length) {\n        SDLHaptic haptic = getHaptic(device_id);\n        if (haptic != null) {\n            haptic.vib.vibrate(length);\n        }\n    }\n\n    public void stop(int device_id) {\n        SDLHaptic haptic = getHaptic(device_id);\n        if (haptic != null) {\n            haptic.vib.cancel();\n        }\n    }\n\n    public void pollHapticDevices() {\n\n        final int deviceId_VIBRATOR_SERVICE = 999999;\n        boolean hasVibratorService = false;\n\n        int[] deviceIds = InputDevice.getDeviceIds();\n        // It helps processing the device ids in reverse order\n        // For example, in the case of the XBox 360 wireless dongle,\n        // so the first controller seen by SDL matches what the receiver\n        // considers to be the first controller\n\n        for (int i = deviceIds.length - 1; i > -1; i--) {\n            SDLHaptic haptic = getHaptic(deviceIds[i]);\n            if (haptic == null) {\n                InputDevice device = InputDevice.getDevice(deviceIds[i]);\n                Vibrator vib = device.getVibrator();\n                if (vib != null) {\n                    if (vib.hasVibrator()) {\n                        haptic = new SDLHaptic();\n                        haptic.device_id = deviceIds[i];\n                        haptic.name = device.getName();\n                        haptic.vib = vib;\n                        mHaptics.add(haptic);\n                        SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);\n                    }\n                }\n            }\n        }\n\n        /* Check VIBRATOR_SERVICE */\n        Vibrator vib = (Vibrator) SDL.getContext().getSystemService(Context.VIBRATOR_SERVICE);\n        if (vib != null) {\n            hasVibratorService = vib.hasVibrator();\n\n            if (hasVibratorService) {\n                SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE);\n                if (haptic == null) {\n                    haptic = new SDLHaptic();\n                    haptic.device_id = deviceId_VIBRATOR_SERVICE;\n                    haptic.name = \"VIBRATOR_SERVICE\";\n                    haptic.vib = vib;\n                    mHaptics.add(haptic);\n                    SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);\n                }\n            }\n        }\n\n        /* Check removed devices */\n        ArrayList<Integer> removedDevices = null;\n        for (SDLHaptic haptic : mHaptics) {\n            int device_id = haptic.device_id;\n            int i;\n            for (i = 0; i < deviceIds.length; i++) {\n                if (device_id == deviceIds[i]) break;\n            }\n\n            if (device_id != deviceId_VIBRATOR_SERVICE || !hasVibratorService) {\n                if (i == deviceIds.length) {\n                    if (removedDevices == null) {\n                        removedDevices = new ArrayList<Integer>();\n                    }\n                    removedDevices.add(device_id);\n                }\n            }  // else: don't remove the vibrator if it is still present\n        }\n\n        if (removedDevices != null) {\n            for (int device_id : removedDevices) {\n                SDLControllerManager.nativeRemoveHaptic(device_id);\n                for (int i = 0; i < mHaptics.size(); i++) {\n                    if (mHaptics.get(i).device_id == device_id) {\n                        mHaptics.remove(i);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    protected SDLHaptic getHaptic(int device_id) {\n        for (SDLHaptic haptic : mHaptics) {\n            if (haptic.device_id == device_id) {\n                return haptic;\n            }\n        }\n        return null;\n    }\n}\n\nclass SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {\n    // Generic Motion (mouse hover, joystick...) events go here\n    @Override\n    public boolean onGenericMotion(View v, MotionEvent event) {\n        float x, y;\n        int action;\n\n        switch ( event.getSource() ) {\n            case InputDevice.SOURCE_JOYSTICK:\n                return SDLControllerManager.handleJoystickMotionEvent(event);\n\n            case InputDevice.SOURCE_MOUSE:\n                action = event.getActionMasked();\n                switch (action) {\n                    case MotionEvent.ACTION_SCROLL:\n                        x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);\n                        y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);\n                        SDLActivity.onNativeMouse(0, action, x, y, false);\n                        return true;\n\n                    case MotionEvent.ACTION_HOVER_MOVE:\n                        x = event.getX(0);\n                        y = event.getY(0);\n\n                        SDLActivity.onNativeMouse(0, action, x, y, false);\n                        return true;\n\n                    default:\n                        break;\n                }\n                break;\n\n            default:\n                break;\n        }\n\n        // Event was not managed\n        return false;\n    }\n\n    public boolean supportsRelativeMouse() {\n        return false;\n    }\n\n    public boolean inRelativeMode() {\n        return false;\n    }\n\n    public boolean setRelativeMouseEnabled(boolean enabled) {\n        return false;\n    }\n\n    public void reclaimRelativeMouseModeIfNeeded()\n    {\n\n    }\n\n    public float getEventX(MotionEvent event) {\n        return event.getX(0);\n    }\n\n    public float getEventY(MotionEvent event) {\n        return event.getY(0);\n    }\n\n}\n\nclass SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 {\n    // Generic Motion (mouse hover, joystick...) events go here\n\n    private boolean mRelativeModeEnabled;\n\n    @Override\n    public boolean onGenericMotion(View v, MotionEvent event) {\n\n        // Handle relative mouse mode\n        if (mRelativeModeEnabled) {\n            if (event.getSource() == InputDevice.SOURCE_MOUSE) {\n                int action = event.getActionMasked();\n                if (action == MotionEvent.ACTION_HOVER_MOVE) {\n                    float x = event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);\n                    float y = event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);\n                    SDLActivity.onNativeMouse(0, action, x, y, true);\n                    return true;\n                }\n            }\n        }\n\n        // Event was not managed, call SDLGenericMotionListener_API12 method\n        return super.onGenericMotion(v, event);\n    }\n\n    @Override\n    public boolean supportsRelativeMouse() {\n        return true;\n    }\n\n    @Override\n    public boolean inRelativeMode() {\n        return mRelativeModeEnabled;\n    }\n\n    @Override\n    public boolean setRelativeMouseEnabled(boolean enabled) {\n        mRelativeModeEnabled = enabled;\n        return true;\n    }\n\n    @Override\n    public float getEventX(MotionEvent event) {\n        if (mRelativeModeEnabled) {\n            return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);\n        } else {\n            return event.getX(0);\n        }\n    }\n\n    @Override\n    public float getEventY(MotionEvent event) {\n        if (mRelativeModeEnabled) {\n            return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);\n        } else {\n            return event.getY(0);\n        }\n    }\n}\n\nclass SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {\n    // Generic Motion (mouse hover, joystick...) events go here\n    private boolean mRelativeModeEnabled;\n\n    @Override\n    public boolean onGenericMotion(View v, MotionEvent event) {\n        float x, y;\n        int action;\n\n        switch ( event.getSource() ) {\n            case InputDevice.SOURCE_JOYSTICK:\n                return SDLControllerManager.handleJoystickMotionEvent(event);\n\n            case InputDevice.SOURCE_MOUSE:\n            // DeX desktop mouse cursor is a separate non-standard input type.\n            case InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN:\n                action = event.getActionMasked();\n                switch (action) {\n                    case MotionEvent.ACTION_SCROLL:\n                        x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);\n                        y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);\n                        SDLActivity.onNativeMouse(0, action, x, y, false);\n                        return true;\n\n                    case MotionEvent.ACTION_HOVER_MOVE:\n                        x = event.getX(0);\n                        y = event.getY(0);\n                        SDLActivity.onNativeMouse(0, action, x, y, false);\n                        return true;\n\n                    default:\n                        break;\n                }\n                break;\n\n            case InputDevice.SOURCE_MOUSE_RELATIVE:\n                action = event.getActionMasked();\n                switch (action) {\n                    case MotionEvent.ACTION_SCROLL:\n                        x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);\n                        y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);\n                        SDLActivity.onNativeMouse(0, action, x, y, false);\n                        return true;\n\n                    case MotionEvent.ACTION_HOVER_MOVE:\n                        x = event.getX(0);\n                        y = event.getY(0);\n                        SDLActivity.onNativeMouse(0, action, x, y, true);\n                        return true;\n\n                    default:\n                        break;\n                }\n                break;\n\n            default:\n                break;\n        }\n\n        // Event was not managed\n        return false;\n    }\n\n    @Override\n    public boolean supportsRelativeMouse() {\n        return (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */);\n    }\n\n    @Override\n    public boolean inRelativeMode() {\n        return mRelativeModeEnabled;\n    }\n\n    @Override\n    public boolean setRelativeMouseEnabled(boolean enabled) {\n        if (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */) {\n            if (enabled) {\n                SDLActivity.getContentView().requestPointerCapture();\n            } else {\n                SDLActivity.getContentView().releasePointerCapture();\n            }\n            mRelativeModeEnabled = enabled;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    @Override\n    public void reclaimRelativeMouseModeIfNeeded()\n    {\n        if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) {\n            SDLActivity.getContentView().requestPointerCapture();\n        }\n    }\n\n    @Override\n    public float getEventX(MotionEvent event) {\n        // Relative mouse in capture mode will only have relative for X/Y\n        return event.getX(0);\n    }\n\n    @Override\n    public float getEventY(MotionEvent event) {\n        // Relative mouse in capture mode will only have relative for X/Y\n        return event.getY(0);\n    }\n}\n"
  },
  {
    "path": "android-project/app/src/main/java/org/libsdl/app/SDLSurface.java",
    "content": "package org.libsdl.app;\n\n\nimport android.content.Context;\nimport android.content.pm.ActivityInfo;\nimport android.hardware.Sensor;\nimport android.hardware.SensorEvent;\nimport android.hardware.SensorEventListener;\nimport android.hardware.SensorManager;\nimport android.os.Build;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.view.Display;\nimport android.view.InputDevice;\nimport android.view.KeyEvent;\nimport android.view.MotionEvent;\nimport android.view.Surface;\nimport android.view.SurfaceHolder;\nimport android.view.SurfaceView;\nimport android.view.View;\nimport android.view.WindowManager;\n\n\n/**\n    SDLSurface. This is what we draw on, so we need to know when it's created\n    in order to do anything useful.\n\n    Because of this, that's where we set up the SDL thread\n*/\npublic class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,\n    View.OnKeyListener, View.OnTouchListener, SensorEventListener  {\n\n    // Sensors\n    protected SensorManager mSensorManager;\n    protected Display mDisplay;\n\n    // Keep track of the surface size to normalize touch events\n    protected float mWidth, mHeight;\n\n    // Is SurfaceView ready for rendering\n    public boolean mIsSurfaceReady;\n\n    // Startup\n    public SDLSurface(Context context) {\n        super(context);\n        getHolder().addCallback(this);\n\n        setFocusable(true);\n        setFocusableInTouchMode(true);\n        requestFocus();\n        setOnKeyListener(this);\n        setOnTouchListener(this);\n\n        mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();\n        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);\n\n        setOnGenericMotionListener(SDLActivity.getMotionListener());\n\n        // Some arbitrary defaults to avoid a potential division by zero\n        mWidth = 1.0f;\n        mHeight = 1.0f;\n\n        mIsSurfaceReady = false;\n    }\n\n    public void handlePause() {\n        enableSensor(Sensor.TYPE_ACCELEROMETER, false);\n    }\n\n    public void handleResume() {\n        setFocusable(true);\n        setFocusableInTouchMode(true);\n        requestFocus();\n        setOnKeyListener(this);\n        setOnTouchListener(this);\n        enableSensor(Sensor.TYPE_ACCELEROMETER, true);\n    }\n\n    public Surface getNativeSurface() {\n        return getHolder().getSurface();\n    }\n\n    // Called when we have a valid drawing surface\n    @Override\n    public void surfaceCreated(SurfaceHolder holder) {\n        Log.v(\"SDL\", \"surfaceCreated()\");\n        SDLActivity.onNativeSurfaceCreated();\n    }\n\n    // Called when we lose the surface\n    @Override\n    public void surfaceDestroyed(SurfaceHolder holder) {\n        Log.v(\"SDL\", \"surfaceDestroyed()\");\n\n        // Transition to pause, if needed\n        SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;\n        SDLActivity.handleNativeState();\n\n        mIsSurfaceReady = false;\n        SDLActivity.onNativeSurfaceDestroyed();\n    }\n\n    // Called when the surface is resized\n    @Override\n    public void surfaceChanged(SurfaceHolder holder,\n                               int format, int width, int height) {\n        Log.v(\"SDL\", \"surfaceChanged()\");\n\n        if (SDLActivity.mSingleton == null) {\n            return;\n        }\n\n        mWidth = width;\n        mHeight = height;\n        int nDeviceWidth = width;\n        int nDeviceHeight = height;\n        try\n        {\n            if (Build.VERSION.SDK_INT >= 17 /* Android 4.2 (JELLY_BEAN_MR1) */) {\n                DisplayMetrics realMetrics = new DisplayMetrics();\n                mDisplay.getRealMetrics( realMetrics );\n                nDeviceWidth = realMetrics.widthPixels;\n                nDeviceHeight = realMetrics.heightPixels;\n            }\n        } catch(Exception ignored) {\n        }\n\n        synchronized(SDLActivity.getContext()) {\n            // In case we're waiting on a size change after going fullscreen, send a notification.\n            SDLActivity.getContext().notifyAll();\n        }\n\n        Log.v(\"SDL\", \"Window size: \" + width + \"x\" + height);\n        Log.v(\"SDL\", \"Device size: \" + nDeviceWidth + \"x\" + nDeviceHeight);\n        SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, mDisplay.getRefreshRate());\n        SDLActivity.onNativeResize();\n\n        // Prevent a screen distortion glitch,\n        // for instance when the device is in Landscape and a Portrait App is resumed.\n        boolean skip = false;\n        int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();\n\n        if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {\n            if (mWidth > mHeight) {\n               skip = true;\n            }\n        } else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {\n            if (mWidth < mHeight) {\n               skip = true;\n            }\n        }\n\n        // Special Patch for Square Resolution: Black Berry Passport\n        if (skip) {\n           double min = Math.min(mWidth, mHeight);\n           double max = Math.max(mWidth, mHeight);\n\n           if (max / min < 1.20) {\n              Log.v(\"SDL\", \"Don't skip on such aspect-ratio. Could be a square resolution.\");\n              skip = false;\n           }\n        }\n\n        // Don't skip in MultiWindow.\n        if (skip) {\n            if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {\n                if (SDLActivity.mSingleton.isInMultiWindowMode()) {\n                    Log.v(\"SDL\", \"Don't skip in Multi-Window\");\n                    skip = false;\n                }\n            }\n        }\n\n        if (skip) {\n           Log.v(\"SDL\", \"Skip .. Surface is not ready.\");\n           mIsSurfaceReady = false;\n           return;\n        }\n\n        /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */\n        SDLActivity.onNativeSurfaceChanged();\n\n        /* Surface is ready */\n        mIsSurfaceReady = true;\n\n        SDLActivity.mNextNativeState = SDLActivity.NativeState.RESUMED;\n        SDLActivity.handleNativeState();\n    }\n\n    // Key events\n    @Override\n    public boolean onKey(View v, int keyCode, KeyEvent event) {\n        return SDLActivity.handleKeyEvent(v, keyCode, event, null);\n    }\n\n    // Touch events\n    @Override\n    public boolean onTouch(View v, MotionEvent event) {\n        /* Ref: http://developer.android.com/training/gestures/multi.html */\n        int touchDevId = event.getDeviceId();\n        final int pointerCount = event.getPointerCount();\n        int action = event.getActionMasked();\n        int pointerFingerId;\n        int i = -1;\n        float x,y,p;\n\n        /*\n         * Prevent id to be -1, since it's used in SDL internal for synthetic events\n         * Appears when using Android emulator, eg:\n         *  adb shell input mouse tap 100 100\n         *  adb shell input touchscreen tap 100 100\n         */\n        if (touchDevId < 0) {\n            touchDevId -= 1;\n        }\n\n        // 12290 = Samsung DeX mode desktop mouse\n        // 12290 = 0x3002 = 0x2002 | 0x1002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN\n        // 0x2   = SOURCE_CLASS_POINTER\n        if (event.getSource() == InputDevice.SOURCE_MOUSE || event.getSource() == (InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN)) {\n            int mouseButton = 1;\n            try {\n                Object object = event.getClass().getMethod(\"getButtonState\").invoke(event);\n                if (object != null) {\n                    mouseButton = (Integer) object;\n                }\n            } catch(Exception ignored) {\n            }\n\n            // We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values\n            // if we are.  We'll leverage our existing mouse motion listener\n            SDLGenericMotionListener_API12 motionListener = SDLActivity.getMotionListener();\n            x = motionListener.getEventX(event);\n            y = motionListener.getEventY(event);\n\n            SDLActivity.onNativeMouse(mouseButton, action, x, y, motionListener.inRelativeMode());\n        } else {\n            switch(action) {\n                case MotionEvent.ACTION_MOVE:\n                    for (i = 0; i < pointerCount; i++) {\n                        pointerFingerId = event.getPointerId(i);\n                        x = event.getX(i) / mWidth;\n                        y = event.getY(i) / mHeight;\n                        p = event.getPressure(i);\n                        if (p > 1.0f) {\n                            // may be larger than 1.0f on some devices\n                            // see the documentation of getPressure(i)\n                            p = 1.0f;\n                        }\n                        SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);\n                    }\n                    break;\n\n                case MotionEvent.ACTION_UP:\n                case MotionEvent.ACTION_DOWN:\n                    // Primary pointer up/down, the index is always zero\n                    i = 0;\n                    /* fallthrough */\n                case MotionEvent.ACTION_POINTER_UP:\n                case MotionEvent.ACTION_POINTER_DOWN:\n                    // Non primary pointer up/down\n                    if (i == -1) {\n                        i = event.getActionIndex();\n                    }\n\n                    pointerFingerId = event.getPointerId(i);\n                    x = event.getX(i) / mWidth;\n                    y = event.getY(i) / mHeight;\n                    p = event.getPressure(i);\n                    if (p > 1.0f) {\n                        // may be larger than 1.0f on some devices\n                        // see the documentation of getPressure(i)\n                        p = 1.0f;\n                    }\n                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);\n                    break;\n\n                case MotionEvent.ACTION_CANCEL:\n                    for (i = 0; i < pointerCount; i++) {\n                        pointerFingerId = event.getPointerId(i);\n                        x = event.getX(i) / mWidth;\n                        y = event.getY(i) / mHeight;\n                        p = event.getPressure(i);\n                        if (p > 1.0f) {\n                            // may be larger than 1.0f on some devices\n                            // see the documentation of getPressure(i)\n                            p = 1.0f;\n                        }\n                        SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);\n                    }\n                    break;\n\n                default:\n                    break;\n            }\n        }\n\n        return true;\n   }\n\n    // Sensor events\n    public void enableSensor(int sensortype, boolean enabled) {\n        // TODO: This uses getDefaultSensor - what if we have >1 accels?\n        if (enabled) {\n            mSensorManager.registerListener(this,\n                            mSensorManager.getDefaultSensor(sensortype),\n                            SensorManager.SENSOR_DELAY_GAME, null);\n        } else {\n            mSensorManager.unregisterListener(this,\n                            mSensorManager.getDefaultSensor(sensortype));\n        }\n    }\n\n    @Override\n    public void onAccuracyChanged(Sensor sensor, int accuracy) {\n        // TODO\n    }\n\n    @Override\n    public void onSensorChanged(SensorEvent event) {\n        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {\n\n            // Since we may have an orientation set, we won't receive onConfigurationChanged events.\n            // We thus should check here.\n            int newOrientation;\n\n            float x, y;\n            switch (mDisplay.getRotation()) {\n                case Surface.ROTATION_90:\n                    x = -event.values[1];\n                    y = event.values[0];\n                    newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE;\n                    break;\n                case Surface.ROTATION_270:\n                    x = event.values[1];\n                    y = -event.values[0];\n                    newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;\n                    break;\n                case Surface.ROTATION_180:\n                    x = -event.values[0];\n                    y = -event.values[1];\n                    newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;\n                    break;\n                case Surface.ROTATION_0:\n                default:\n                    x = event.values[0];\n                    y = event.values[1];\n                    newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT;\n                    break;\n            }\n\n            if (newOrientation != SDLActivity.mCurrentOrientation) {\n                SDLActivity.mCurrentOrientation = newOrientation;\n                SDLActivity.onNativeOrientationChanged(newOrientation);\n            }\n\n            SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,\n                                      y / SensorManager.GRAVITY_EARTH,\n                                      event.values[2] / SensorManager.GRAVITY_EARTH);\n\n\n        }\n    }\n\n    // Captured pointer events for API 26.\n    public boolean onCapturedPointerEvent(MotionEvent event)\n    {\n        int action = event.getActionMasked();\n\n        float x, y;\n        switch (action) {\n            case MotionEvent.ACTION_SCROLL:\n                x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);\n                y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);\n                SDLActivity.onNativeMouse(0, action, x, y, false);\n                return true;\n\n            case MotionEvent.ACTION_HOVER_MOVE:\n            case MotionEvent.ACTION_MOVE:\n                x = event.getX(0);\n                y = event.getY(0);\n                SDLActivity.onNativeMouse(0, action, x, y, true);\n                return true;\n\n            case MotionEvent.ACTION_BUTTON_PRESS:\n            case MotionEvent.ACTION_BUTTON_RELEASE:\n\n                // Change our action value to what SDL's code expects.\n                if (action == MotionEvent.ACTION_BUTTON_PRESS) {\n                    action = MotionEvent.ACTION_DOWN;\n                } else { /* MotionEvent.ACTION_BUTTON_RELEASE */\n                    action = MotionEvent.ACTION_UP;\n                }\n\n                x = event.getX(0);\n                y = event.getY(0);\n                int button = event.getButtonState();\n\n                SDLActivity.onNativeMouse(button, action, x, y, true);\n                return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "android-project/app/src/main/res/drawable/gamepad.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"39.595dp\"\n    android:height=\"27.966dp\"\n    android:viewportWidth=\"39.595\"\n    android:viewportHeight=\"27.966\">\n  <path\n      android:pathData=\"m37.009,7.862 l-0.002,0.001c-0.666,-4.128 -4.233,-7.267 -8.551,-7.267L17.912,0.596l21.42,21.845zM37.009,7.862\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#282b28\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m13.751,0h-3.994v0.876h3.994zM13.751,0\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#0c0c0c\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m29.81,0h-3.994v0.876h3.994zM29.81,0\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#0c0c0c\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m39.501,23.648 l-2.492,-15.637 -0.002,0.001c-0.666,-4.128 -4.233,-7.267 -8.551,-7.267L11.134,0.744c-4.31,0 -7.882,3.138 -8.548,7.266l-2.492,15.637c-0.062,0.261 -0.095,0.533 -0.095,0.812 0,1.936 1.57,3.506 3.506,3.506 0.968,0 1.845,-0.392 2.479,-1.027l6.391,-6.397h14.846l6.389,6.397c0.635,0.634 1.511,1.027 2.479,1.027 1.936,0 3.506,-1.57 3.506,-3.506 0,-0.28 -0.033,-0.552 -0.095,-0.812\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#282b28\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m36.089,27.433c-0.968,0 -1.844,-0.377 -2.479,-0.986L27.222,20.3L12.376,20.3l-6.391,6.147c-0.634,0.609 -1.511,0.986 -2.479,0.986 -1.869,0 -3.397,-1.406 -3.5,-3.178 -0.004,0.068 -0.006,0.136 -0.006,0.205 0,1.936 1.569,3.506 3.506,3.506 0.968,0 1.845,-0.392 2.479,-1.027l6.391,-6.397h14.846l6.389,6.397c0.634,0.634 1.511,1.027 2.479,1.027 1.936,0 3.506,-1.57 3.506,-3.506 0,-0.069 -0.002,-0.137 -0.006,-0.205 -0.103,1.772 -1.63,3.178 -3.5,3.178\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#0c0c0c\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m28.009,18.607c0.538,-0.685 8.89,-11.32 8.89,-11.32 -0.884,-3.848 -4.322,-6.707 -8.441,-6.707h-17.323c-4.113,0 -7.553,2.858 -8.438,6.707 0,0 8.651,10.972 9.016,11.477 0.365,0.505 0.838,0.846 1.697,0.846h12.588c0.757,0 1.474,-0.317 2.012,-1.002\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#454545\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"M28.354,0.58L17.897,0.58l13.536,13.536c2.486,-3.165 5.363,-6.829 5.363,-6.829 -0.884,-3.848 -4.322,-6.707 -8.441,-6.707\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#4c4c4c\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m28.321,9.279c0,0.606 0.49,1.095 1.095,1.095 0.606,0 1.096,-0.489 1.096,-1.095 0,-0.607 -0.49,-1.096 -1.096,-1.096 -0.605,0 -1.095,0.489 -1.095,1.096\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#eeeeee\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m28.321,4.181c0,0.606 0.49,1.095 1.095,1.095 0.606,0 1.096,-0.49 1.096,-1.095 0,-0.607 -0.49,-1.096 -1.096,-1.096 -0.605,0 -1.095,0.489 -1.095,1.096\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#eeeeee\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m25.84,6.73c0,0.606 0.49,1.095 1.095,1.095 0.606,0 1.096,-0.49 1.096,-1.095 0,-0.607 -0.49,-1.096 -1.096,-1.096 -0.605,0 -1.095,0.489 -1.095,1.096\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#eeeeee\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m30.801,6.73c0,0.606 0.49,1.095 1.095,1.095 0.606,0 1.096,-0.49 1.096,-1.095 0,-0.607 -0.49,-1.096 -1.096,-1.096 -0.605,0 -1.095,0.489 -1.095,1.096\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#eeeeee\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m2.697,7.329c0,0 8.651,10.971 9.016,11.477 0.365,0.505 0.838,0.845 1.697,0.845h4.27L4.24,4.038c-0.73,0.959 -1.264,2.075 -1.544,3.291\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#383838\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m11.632,14.21c0,2.016 1.631,3.646 3.646,3.646 2.018,0 3.648,-1.63 3.648,-3.646 0,-2.019 -1.63,-3.648 -3.648,-3.648 -2.015,0 -3.646,1.628 -3.646,3.648\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#282b28\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m12.371,14.31c0,1.608 1.301,2.907 2.908,2.906 1.609,-0 2.908,-1.3 2.908,-2.908 -0,-1.61 -1.3,-2.908 -2.909,-2.908 -1.606,0 -2.907,1.299 -2.906,2.909\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#eeeeee\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <group>\n    <clip-path\n        android:pathData=\"M12.359,11.392l5.83,0l0,3.044l-5.83,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M12.371,11.401L18.186,11.401L18.186,14.4L12.371,14.4ZM12.371,11.401\"/>\n      <path\n          android:pathData=\"m15.278,11.583c1.578,0 2.856,1.25 2.904,2.818 0.001,-0.03 0.005,-0.06 0.005,-0.091 0,-1.61 -1.3,-2.909 -2.909,-2.909 -1.607,0 -2.907,1.298 -2.907,2.909 0,0.031 0.003,0.06 0.005,0.091C12.423,12.833 13.702,11.583 15.278,11.583\"\n          android:fillColor=\"#ffffff\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <group>\n    <clip-path\n        android:pathData=\"M12.359,14.178l5.83,0l0,3.044l-5.83,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M12.371,14.217L18.186,14.217L18.186,17.217L12.371,17.217ZM12.371,14.217\"/>\n      <path\n          android:pathData=\"M18.182,14.217C18.134,15.785 16.856,17.035 15.278,17.035 13.702,17.035 12.423,15.785 12.375,14.217 12.374,14.248 12.371,14.277 12.371,14.308c0,1.61 1.301,2.909 2.907,2.909 1.609,0 2.909,-1.298 2.909,-2.909 0,-0.031 -0.003,-0.06 -0.005,-0.091\"\n          android:fillColor=\"#b3b3b3\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <path\n      android:pathData=\"m20.583,14.21c0,2.016 1.631,3.646 3.646,3.646 2.018,0 3.648,-1.63 3.648,-3.646 0,-2.019 -1.63,-3.648 -3.648,-3.648 -2.015,0 -3.646,1.628 -3.646,3.648\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#282b28\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m21.321,14.31c0,1.608 1.302,2.907 2.908,2.906 1.609,-0 2.908,-1.3 2.908,-2.908 -0,-1.61 -1.3,-2.908 -2.909,-2.908 -1.606,0 -2.907,1.299 -2.907,2.909\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#eeeeee\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <group>\n    <clip-path\n        android:pathData=\"M21.284,14.178l5.881,0l0,3.044l-5.881,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M21.321,14.217L27.137,14.217L27.137,17.217L21.321,17.217ZM21.321,14.217\"/>\n      <path\n          android:pathData=\"M27.133,14.217C27.084,15.785 25.807,17.035 24.229,17.035 22.653,17.035 21.374,15.785 21.326,14.217 21.325,14.248 21.321,14.277 21.321,14.308c0,1.61 1.301,2.909 2.907,2.909 1.609,0 2.909,-1.298 2.909,-2.909 0,-0.031 -0.004,-0.06 -0.005,-0.091\"\n          android:fillColor=\"#b3b3b3\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <path\n      android:pathData=\"M10.812,5.896L10.812,3.457h-1.829v2.439h-2.439v1.829h2.439v2.439h1.829v-2.439h2.439L13.25,5.896ZM10.812,5.896\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#eeeeee\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <group>\n    <clip-path\n        android:pathData=\"M8.955,3.448l1.857,0l0,0.206l-1.857,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M8.982,3.457L10.812,3.457L10.812,3.61L8.982,3.61ZM8.982,3.457\"/>\n      <path\n          android:pathData=\"M10.812,3.457L8.982,3.457l0,0.152l1.829,0zM10.812,3.457\"\n          android:fillColor=\"#ffffff\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <group>\n    <clip-path\n        android:pathData=\"M8.077,5.872l0.929,0l0,0.206l-0.929,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M8.077,5.896L8.982,5.896L8.982,6.049L8.077,6.049ZM8.077,5.896\"/>\n      <path\n          android:pathData=\"m8.982,5.896l-2.439,0l0,0.152l2.439,0zM8.982,5.896\"\n          android:fillColor=\"#ffffff\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <group>\n    <clip-path\n        android:pathData=\"M10.76,5.872l2.528,0l0,0.206l-2.528,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"m10.812,5.896l2.439,0L13.251,6.049L10.812,6.049ZM10.812,5.896\"/>\n      <path\n          android:pathData=\"M13.251,5.896L10.812,5.896l0,0.152l2.439,0zM13.251,5.896\"\n          android:fillColor=\"#ffffff\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <group>\n    <clip-path\n        android:pathData=\"M8.077,7.526l0.929,0l0,0.206l-0.929,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M8.077,7.573L8.982,7.573L8.982,7.725L8.077,7.725ZM8.077,7.573\"/>\n      <path\n          android:pathData=\"M8.982,7.573L6.543,7.573L6.543,7.725l2.439,0zM8.982,7.573\"\n          android:fillColor=\"#b3b3b3\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <group>\n    <clip-path\n        android:pathData=\"M8.955,10.002l1.857,0l0,0.206l-1.857,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M8.982,10.012L10.812,10.012L10.812,10.164L8.982,10.164ZM8.982,10.012\"/>\n      <path\n          android:pathData=\"M10.812,10.012L8.982,10.012l0,0.152l1.829,0zM10.812,10.012\"\n          android:fillColor=\"#b3b3b3\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <group>\n    <clip-path\n        android:pathData=\"M10.76,7.526l2.528,0l0,0.206l-2.528,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"m10.812,7.573l2.439,0L13.251,7.725L10.812,7.725ZM10.812,7.573\"/>\n      <path\n          android:pathData=\"M13.251,7.573L10.812,7.573L10.812,7.725l2.439,0zM13.251,7.573\"\n          android:fillColor=\"#b3b3b3\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n  <path\n      android:pathData=\"m18.077,6.811c0,0.692 -0.561,1.253 -1.253,1.253 -0.692,0 -1.253,-0.561 -1.253,-1.253 0,-0.692 0.561,-1.253 1.253,-1.253 0.692,0 1.253,0.561 1.253,1.253\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#0c0c0c\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m16.872,7.41 l-0.594,-0.599 0.594,-0.6\"\n      android:strokeLineJoin=\"miter\"\n      android:strokeWidth=\"0.143882\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#ffffff\"\n      android:strokeLineCap=\"butt\"/>\n  <path\n      android:pathData=\"m16.278,6.811h1.195\"\n      android:strokeLineJoin=\"miter\"\n      android:strokeWidth=\"0.143882\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#ffffff\"\n      android:strokeLineCap=\"butt\"/>\n  <path\n      android:pathData=\"m23.687,6.811c0,0.692 -0.561,1.253 -1.253,1.253 -0.692,0 -1.253,-0.561 -1.253,-1.253 0,-0.692 0.561,-1.253 1.253,-1.253 0.692,0 1.253,0.561 1.253,1.253\"\n      android:strokeWidth=\"0.0515891\"\n      android:fillColor=\"#0c0c0c\"\n      android:strokeColor=\"#00000000\"\n      android:fillType=\"nonZero\"/>\n  <path\n      android:pathData=\"m23.01,6.785c0,0.318 -0.258,0.575 -0.576,0.575 -0.318,0 -0.575,-0.258 -0.575,-0.575 0,-0.318 0.258,-0.576 0.575,-0.576 0.318,0 0.576,0.258 0.576,0.576zM23.01,6.785\"\n      android:strokeLineJoin=\"miter\"\n      android:strokeWidth=\"0.143882\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#ffffff\"\n      android:strokeLineCap=\"butt\"/>\n  <group>\n    <clip-path\n        android:pathData=\"M21.31,11.392l5.83,0l0,3.044l-5.83,0z\"/>\n    <group>\n      <clip-path\n          android:pathData=\"M21.322,11.401L27.137,11.401L27.137,14.4L21.322,14.4ZM21.322,11.401\"/>\n      <path\n          android:pathData=\"m24.229,11.583c1.578,0 2.856,1.25 2.904,2.818 0.001,-0.03 0.005,-0.06 0.005,-0.091 0,-1.61 -1.3,-2.909 -2.909,-2.909 -1.607,0 -2.907,1.298 -2.907,2.909 0,0.031 0.003,0.06 0.005,0.091C21.374,12.833 22.653,11.583 24.229,11.583\"\n          android:fillColor=\"#ffffff\"\n          android:strokeColor=\"#00000000\"\n          android:fillType=\"nonZero\"/>\n    </group>\n  </group>\n</vector>\n"
  },
  {
    "path": "android-project/app/src/main/res/layout/activity_data.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<android.support.constraint.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n\txmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n\txmlns:tools=\"http://schemas.android.com/tools\"\r\n\tandroid:layout_width=\"match_parent\"\r\n\tandroid:layout_height=\"match_parent\"\r\n\ttools:context=\".DataActivity\">\r\n\r\n\t<TextView\r\n\t\tandroid:id=\"@+id/headline\"\r\n\t\tandroid:layout_width=\"0dp\"\r\n\t\tandroid:layout_height=\"wrap_content\"\r\n\t\tandroid:layout_marginStart=\"16dp\"\r\n\t\tandroid:layout_marginTop=\"16dp\"\r\n\t\tandroid:text=\"@string/title_activity_data\"\r\n\t\tandroid:textSize=\"20sp\"\r\n\t\tandroid:textStyle=\"bold\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\"\r\n\t\tapp:layout_constraintTop_toTopOf=\"parent\" />\r\n\r\n\t<TextView\r\n\t\tandroid:id=\"@+id/full_guide\"\r\n\t\tandroid:layout_width=\"0dp\"\r\n\t\tandroid:layout_height=\"wrap_content\"\r\n\t\tandroid:layout_marginStart=\"16dp\"\r\n\t\tandroid:layout_marginTop=\"16dp\"\r\n\t\tandroid:layout_marginEnd=\"16dp\"\r\n\t\tandroid:text=\"@string/guide_full_installation\"\r\n\t\tapp:layout_constraintEnd_toEndOf=\"parent\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\"\r\n\t\tapp:layout_constraintTop_toBottomOf=\"@+id/headline\" />\r\n\r\n\t<TextView\r\n\t\tandroid:id=\"@+id/spawn_guide\"\r\n\t\tandroid:layout_width=\"0dp\"\r\n\t\tandroid:layout_height=\"wrap_content\"\r\n\t\tandroid:layout_marginStart=\"16dp\"\r\n\t\tandroid:layout_marginTop=\"16dp\"\r\n\t\tandroid:layout_marginEnd=\"16dp\"\r\n\t\tandroid:text=\"@string/guide_shareware\"\r\n\t\tapp:layout_constraintEnd_toEndOf=\"parent\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\"\r\n\t\tapp:layout_constraintTop_toBottomOf=\"@+id/check_data_button\" />\r\n\r\n\t<TextView\r\n\t\tandroid:id=\"@+id/online_guide\"\r\n\t\tandroid:layout_width=\"0dp\"\r\n\t\tandroid:layout_height=\"wrap_content\"\r\n\t\tandroid:layout_marginStart=\"16dp\"\r\n\t\tandroid:layout_marginEnd=\"16dp\"\r\n\t\tandroid:layout_marginBottom=\"16dp\"\r\n\t\tandroid:text=\"@string/faq_link\"\r\n\t\tapp:layout_constraintBottom_toBottomOf=\"parent\"\r\n\t\tapp:layout_constraintEnd_toEndOf=\"parent\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\" />\r\n\r\n\t<LinearLayout\r\n\t\tandroid:id=\"@+id/import_buttons\"\r\n\t\tandroid:layout_width=\"0dp\"\r\n\t\tandroid:layout_height=\"wrap_content\"\r\n\t\tandroid:layout_marginStart=\"16dp\"\r\n\t\tandroid:layout_marginTop=\"16dp\"\r\n\t\tandroid:layout_marginEnd=\"16dp\"\r\n\t\tandroid:gravity=\"center\"\r\n\t\tandroid:orientation=\"horizontal\"\r\n\t\tapp:layout_constraintEnd_toEndOf=\"parent\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\"\r\n\t\tapp:layout_constraintTop_toBottomOf=\"@+id/spawn_guide\">\r\n\r\n\t\t<Button\r\n\t\t\tandroid:id=\"@+id/import_button\"\r\n\t\t\tandroid:layout_width=\"wrap_content\"\r\n\t\t\tandroid:layout_height=\"wrap_content\"\r\n\t\t\tandroid:onClick=\"importData\"\r\n\t\t\tandroid:text=\"Import Data\" />\r\n\t\t<Space\r\n\t\t\tandroid:layout_width=\"16dp\"\r\n\t\t\tandroid:layout_height=\"wrap_content\" />\r\n\r\n\t\t<Button\r\n\t\t\tandroid:id=\"@+id/download_button\"\r\n\t\t\tandroid:layout_width=\"wrap_content\"\r\n\t\t\tandroid:layout_height=\"wrap_content\"\r\n\t\t\tandroid:onClick=\"sendDownloadRequest\"\r\n\t\t\tandroid:text=\"@string/download_spawn\" />\r\n\r\n\t</LinearLayout>\r\n\r\n\t<Button\r\n\t\tandroid:id=\"@+id/check_data_button\"\r\n\t\tandroid:layout_width=\"wrap_content\"\r\n\t\tandroid:layout_height=\"wrap_content\"\r\n\t\tandroid:layout_marginTop=\"16dp\"\r\n\t\tandroid:onClick=\"startGame\"\r\n\t\tandroid:text=\"@string/game_data_retry\"\r\n\t\tapp:layout_constraintEnd_toEndOf=\"parent\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\"\r\n\t\tapp:layout_constraintTop_toBottomOf=\"@+id/full_guide\" />\r\n\r\n\t<ImageView\r\n\t\tandroid:id=\"@+id/gamepad_icon\"\r\n\t\tandroid:layout_width=\"247dp\"\r\n\t\tandroid:layout_height=\"154dp\"\r\n\t\tandroid:layout_marginTop=\"16dp\"\r\n\t\tandroid:src=\"@drawable/gamepad\"\r\n\t\tandroid:visibility=\"gone\"\r\n\t\tapp:layout_constraintEnd_toEndOf=\"parent\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\"\r\n\t\tapp:layout_constraintTop_toBottomOf=\"@+id/gamepad_text\" />\r\n\r\n\t<TextView\r\n\t\tandroid:id=\"@+id/gamepad_text\"\r\n\t\tandroid:layout_width=\"0dp\"\r\n\t\tandroid:layout_height=\"wrap_content\"\r\n\t\tandroid:layout_marginStart=\"16dp\"\r\n\t\tandroid:layout_marginTop=\"16dp\"\r\n\t\tandroid:layout_marginEnd=\"16dp\"\r\n\t\tandroid:text=\"@string/gamepad_tv_text\"\r\n\t\tandroid:visibility=\"gone\"\r\n\t\tapp:layout_constraintEnd_toEndOf=\"parent\"\r\n\t\tapp:layout_constraintStart_toStartOf=\"parent\"\r\n\t\tapp:layout_constraintTop_toBottomOf=\"@+id/import_buttons\" />\r\n\r\n\t<android.support.constraint.Group android:layout_width=\"wrap_content\"\r\n\t\tandroid:layout_height=\"wrap_content\" />\r\n\r\n</android.support.constraint.ConstraintLayout>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@mipmap/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "android-project/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@mipmap/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "android-project/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<color name=\"red\">#FFFC0000</color>\r\n\t<color name=\"darkred\">#FF7E0000</color>\r\n\t<color name=\"black\">#FF000000</color>\r\n\t<color name=\"white\">#FFFFFFFF</color>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values/strings.xml",
    "content": "<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">To play the full version you must place DIABDAT.MPQ from the original game in Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nIf you don\\'t have the original game then you can buy Diablo from <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">Alternatively you can download the spawn version, to play the demo portion of the game.</string>\r\n\t<string name=\"faq_link\">See the <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Installation Instructions</a> for more details.</string>\r\n\t<string name=\"game_data_retry\">Check again</string>\r\n\t<string name=\"title_activity_data\">Game Data</string>\r\n\t<string name=\"download_spawn\">Download Demo Data</string>\r\n\t<string name=\"missing_game_data\">Game data missing</string>\r\n\t<string name=\"download_started\">Download started</string>\r\n\t<string name=\"shareware_data\">Diablo Demo Data</string>\r\n\t<string name=\"import_short_label\">Import Data</string>\r\n\t<string name=\"gamepad_tv_text\">This game requires a gamepad to play</string>\r\n\t<string name=\"no_file_browser\">Please install a file explorer to select the files you want to import.</string>\r\n\t<string name=\"recommended_file_browser\">For Android TV, we recommend %1$s.</string>\r\n\t<string name=\"import_data_info\">On the next screen, select files that will be imported into:\\n\\n%1$s</string>\r\n\t<string name=\"overwrite_query\">The following files will be overwritten. Is this okay?\\n\\n%1$s</string>\r\n\t<string name=\"ok_button\">OK</string>\r\n\t<string name=\"continue_button\">Continue</string>\r\n\t<string name=\"cancel_button\">Cancel</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\r\n\t<!-- Base application theme. -->\r\n\t<style name=\"Theme.MyApplication\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\r\n\t\t<!-- Primary brand color. -->\r\n\t\t<item name=\"colorPrimary\">@color/red</item>\r\n\t\t<item name=\"colorPrimaryDark\">@color/darkred</item>\r\n\t\t<item name=\"colorAccent\">@color/darkred</item>\r\n\t</style>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-be/strings.xml",
    "content": "<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Каб гуляць у поўную версію трэба памясціць DIABDAT.MPQ з арыгінальнай гульні ў Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nКалі не маеце арыгінальнай гульні, то можаце купіць Д\\'ябла на <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">Або можаце спампаваць spawn-версію і пагуляць у дэма.</string>\r\n\t<string name=\"faq_link\">Для больш дэталяў <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">глядзіце Інструкцыі</a> па ўсталяванні.</string>\r\n\t<string name=\"game_data_retry\">Пераправерыць</string>\r\n\t<string name=\"title_activity_data\">Даныя гульні</string>\r\n\t<string name=\"download_spawn\">Спампаваць даныя дэма</string>\r\n\t<string name=\"missing_game_data\">Не хапае даных гульні</string>\r\n\t<string name=\"download_started\">Спампоўка пачалася</string>\r\n\t<string name=\"shareware_data\">Даныя дэма Diablo</string>\r\n\t<string name=\"import_short_label\">Імпартаваць даныя</string>\r\n\t<string name=\"gamepad_tv_text\">Для гульні трэба геймпад</string>\r\n\t<string name=\"no_file_browser\">Калі ласка, усталюйце праваднік каб выбраць файлы, якія хочаце імпартаваць.</string>\r\n\t<string name=\"recommended_file_browser\">Для Android TV рэкамендуем %1$s.</string>\r\n\t<string name=\"import_data_info\">На наступным экране выберыце файлы якія імпартуюцца ў:\\n\\n%1$s</string>\r\n\t<string name=\"overwrite_query\">Наступныя файлы перазапішуцца. Добра?\\n\\n%1$s</string>\r\n\t<string name=\"ok_button\">OK</string>\r\n\t<string name=\"continue_button\">Працягнуць</string>\r\n\t<string name=\"cancel_button\">Адмяніць</string>\r\n</resources>\r\n\r\n\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-bg/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">За да играете пълната версия на играта поставете файла DIABDAT.MPQ (за допълнението Hellfire добавете всички останали MPQ файлове) от оригиналната PC/Mac версия в Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nАко нямате оригиналната версия на играта, можете да закупите Diablo от <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">Като алтернатива можете да изтеглите пробната версия на играта.</string>\r\n\t<string name=\"faq_link\">Вижте <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Упътването за инсталация</a> за повече информация.</string>\r\n\t<string name=\"game_data_retry\">Опитайте отново</string>\r\n\t<string name=\"title_activity_data\">Игрови ресурси</string>\r\n\t<string name=\"download_spawn\">Изтеглете пробна версия</string>\r\n\t<string name=\"missing_game_data\">Липсват игрови ресурси</string>\r\n\t<string name=\"download_started\">Изтеглянето е започнало</string>\r\n\t<string name=\"shareware_data\">Ресурси Diablo пробна версия</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-cs/strings.xml",
    "content": "<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Pro hraní plné verze je potřeba vložit soubor DIABDAT.MPQ z originální hry do Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nPokud nemáte originální hru, můžete si Diablo koupit na <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">Další možnost je stáhnout si spawn verzi souboru, která vám umožní zahrát si demo verzi hry.</string>\r\n\t<string name=\"faq_link\">Pro bližší informace se podívejte na <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Instrukce k Instalaci</a>.</string>\r\n\t<string name=\"game_data_retry\">Zkusit znovu</string>\r\n\t<string name=\"title_activity_data\">Herní data</string>\r\n\t<string name=\"download_spawn\">Stáhnout Demo Data</string>\r\n\t<string name=\"missing_game_data\">Chybí herní data</string>\r\n\t<string name=\"download_started\">Stahování začalo</string>\r\n\t<string name=\"shareware_data\">Diablo Demo Data</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-da/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\">DevilutionX</string>\r\n\t<string name=\"download_spawn\">Download Demo Data</string>\r\n\t<string name=\"game_data_retry\">Tjek igen</string>\r\n\t<string name=\"title_activity_data\">Spil data</string>\r\n\t<string name=\"missing_game_data\">Spildata mangler</string>\r\n\t<string name=\"download_started\">Hent spildata</string>\r\n\t<string name=\"shareware_data\">Diablo demo data</string>\r\n\t<string name=\"faq_link\">Se <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">installations instruktionerne</a> for yderligere detaljer.</string>\r\n\t<string name=\"guide_shareware\">Alternativt kan du hente spawn-versionen for at spille demo-delen af spillet.</string>\r\n\t<string name=\"guide_full_installation\">For at spille den fulde version skal du placere DIABDAT.MPQ fra det originale spil i Android/data/org.diasurgical.devilutionx/files<br/>\\n<br/>\\nHvis du ikke har det originale spil, kan du købe Diablo på <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-de/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Um die Vollversion spielen zu können, musst du die Datei \"DIABDAT.MPQ\" des Originalspiels in das Verzeichnis Android/data/org.diasurgical.devilutionx/files kopieren.<br/>\\n<br/>\\nWenn du das Originalspiel nicht besitzt kannst du ees bei <a href=\"https://www.gog.com/game/diablo\">GOG.com</a> kaufen.</string>\r\n\t<string name=\"guide_shareware\">Alternativ kannst du die Spawn-Version (Demo-Version?) herunterladen um den Demo-Teil von Diablo zu spielen.</string>\r\n\t<string name=\"faq_link\">Weitere Details in der <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Installationsanleitung</a>.</string>\r\n\t<string name=\"game_data_retry\">Erneut versuchen</string>\r\n\t<string name=\"title_activity_data\">Spieldateien</string>\r\n\t<string name=\"download_spawn\">Demo-Daten herunterladen</string>\r\n\t<string name=\"missing_game_data\">Spieldateien fehlen</string>\r\n\t<string name=\"download_started\">Download begonnen</string>\r\n\t<string name=\"shareware_data\">Diablo Demo-Daten</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-es/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\">DevilutionX</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-fi/strings.xml",
    "content": "<resources>\n<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\n<!--  Strings used for fragments for navigation  -->\n<string name=\"guide_full_installation\">\nVoidaksesi pelata kokoversiota, sinun on siirettävä alkuperäisen pelin DIABDAT.MPQ-tiedosto kansioon Android/data/org.diasurgical.devilutionx/files.\n<br/>\n\\n\n<br/>\n\\nJos sinulla ei ole alkuperäistä peliä, voit ostaa Diablon osoitteesta\n<a href=\"https://www.gog.com/game/diablo\">GOG.com.</a>\n</string>\n<string name=\"guide_shareware\">Vaihtoehtoisesti voit ladata spawn-version, jotta voit pelata pelin demoversiota.</string>\n<string name=\"faq_link\">\nKatso\n<a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Asennusohjeet</a>\nlisätietoja varten.\n</string>\n<string name=\"game_data_retry\">Tarkista uudelleen</string>\n<string name=\"title_activity_data\">Pelitiedot</string>\n<string name=\"download_spawn\">Lataa demotiedot</string>\n<string name=\"missing_game_data\">Pelitiedot puuttuvat</string>\n<string name=\"download_started\">Lataus aloitettu</string>\n<string name=\"shareware_data\">Diablo-demotiedot</string>\n<string name=\"import_short_label\">Tuo tiedot</string>\n<string name=\"gamepad_tv_text\">Tämän pelin pelaamiseen tarvitaan peliohjain.</string>\n<string name=\"no_file_browser\">Asenna tiedostoselain, jotta voit valita tuontiin haluamasi tiedostot.</string>\n<string name=\"recommended_file_browser\">Android TV:lle suosittelemme %1$s.</string>\n<string name=\"import_data_info\">Valitse seuraavalla näytöllä tiedostot, jotka haluat tuoda:\\n\\n%1$s</string>\n<string name=\"overwrite_query\">Seuraavat tiedostot korvataan. Onko tämä ok?\\n\\n%1$s</string>\n<string name=\"ok_button\">OK</string>\n<string name=\"continue_button\">Jatka</string>\n<string name=\"cancel_button\">Peruuta</string>\n</resources>\n"
  },
  {
    "path": "android-project/app/src/main/res/values-fr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Pour jouer à la version complete, vous devez placer le fichier DIABDAT.MPQ du jeu original dans le dossier Android/data/org.diasurgical.devilutionx/files.<br />\\n<br/>\\nSi vous n\\'avez pas le jeu original, vous pouvez l\\'acheter chez <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">Vous pouvez également télécharger la version spawn pour jouer à la démo du jeu.</string>\r\n\t<string name=\"faq_link\">Consultez <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">les Instructions d\\'Installation</a> pour plus de détails.</string>\r\n\t<string name=\"game_data_retry\">Revérifier</string>\r\n\t<string name=\"title_activity_data\">Données du Jeu</string>\r\n\t<string name=\"download_spawn\">Télécharger la Démo</string>\r\n\t<string name=\"missing_game_data\">Données du Jeu manquantes</string>\r\n\t<string name=\"download_started\">Le téléchargement a commencé</string>\r\n\t<string name=\"shareware_data\">Démo Diablo</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-hr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\">DevilutionX</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-hu/strings.xml",
    "content": "<resources>\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\n\t<!-- Strings used for fragments for navigation -->\n\n\t<string name=\"guide_full_installation\">Ahhoz, hogy a teljes változattal játssz, másold a DIABDAT.MPQ fájlt az eredi játék mappájából a Android/data/org.diasurgical.devilutionx/files mappába a készülékeden. Ehhez egy USB-kábel lehet szükséges.<br/>\\n<br/>\\nAmennyiben még nincs meg az eredeti játék, megvásárolhatod a <a href=\"https://www.gog.com/game/diablo\">GOG.com</a> nevű oldalon.</string>\n\t<string name=\"guide_shareware\">Máskülönben használhatod az úgynevezett Spawn változatot, amely a játék próbaváltozata.</string>\n\t<string name=\"faq_link\">Lásd még a <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">telepítési útmutatót</a> további részletekért.</string>\n\t<string name=\"game_data_retry\">Próbáld újra</string>\n\t<string name=\"title_activity_data\">Játék adatok</string>\n\t<string name=\"download_spawn\">Próbaváltozat letöltése</string>\n\t<string name=\"missing_game_data\">A játék adatok hiányoznak</string>\n\t<string name=\"download_started\">Letöltés megkezdődött</string>\n\t<string name=\"shareware_data\">Próbaváltozat adatfájl</string>\n\t<string name=\"import_short_label\">Adat importálása</string>\n\t<string name=\"gamepad_tv_text\">A játékhoz gamepad-re van szükség</string>\n\t<string name=\"import_data_info\">A következő képernyőn válaszd ki az importálandó fájlokat:\\n\\n%1$s</string>\n\t<string name=\"overwrite_query\">Az alábbi fájlok felül lesznek írva. Ez így rendben lesz?\\n\\n%1$s</string>\n\t<string name=\"ok_button\">Rendben</string>\n\t<string name=\"continue_button\">Folytatás</string>\n\t<string name=\"cancel_button\">Mégse</string>\n</resources>\n"
  },
  {
    "path": "android-project/app/src/main/res/values-it/strings.xml",
    "content": "<resources>\r\n        <string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n        <!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Per giocare alla versione completa devi inserire DIABDAT.MPQ dal gioco originale in Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nSe non possiedi una copia originale puoi acquistare Diablo su <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">In alternativa puoi scaricare la versione spawn, per giocare alla parte demo del gioco.</string>\r\n\t<string name=\"faq_link\">Consulta <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Istruzioni per l\\'Installazione</a> per ulteriori dettagli.</string>\r\n        <string name=\"game_data_retry\">Controlla di nuovo</string>\r\n        <string name=\"title_activity_data\">Dati Gioco</string>\r\n        <string name=\"download_spawn\">Scarica Dati Demo</string>\r\n        <string name=\"missing_game_data\">Dati gioco mancanti</string>\r\n        <string name=\"download_started\">Download iniziato</string>\r\n        <string name=\"shareware_data\">Dati Diablo Demo</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-ko-rKR/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\">DevilutionX</string>\r\n\r\n\t<string name=\"guide_full_installation\">풀버전을 플레이하려면 게임 원본의 DIABDAT.MPQ 파일을 Android/data/org.diasurgical.devilutionx/files 폴더에 배치해야 합니다.<br/>\\n<br/>\\n디아블로 게임을 가지고 있지 않으면 <a href=\"https://www.gog.com/game/diablo\">GOG.com</a>에서 구입할 수 있습니다.</string>\r\n\t<string name=\"guide_shareware\">또는 스폰 버전을 다운로드 하여, 체험판을 플레이할 수도 있습니다.</string>\r\n\t<string name=\"faq_link\">자세한 내용은 <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">설치 가이드</a>를 참조하세요.</string>\r\n\t<string name=\"game_data_retry\">다시 확인</string>\r\n\t<string name=\"title_activity_data\">게임 데이터</string>\r\n\t<string name=\"download_spawn\">체험판 데이터 다운로드</string>\r\n\t<string name=\"missing_game_data\">게임 데이터 없음</string>\r\n\t<string name=\"download_started\">다운로드 시작됨</string>\r\n\t<string name=\"shareware_data\">디아블로 체험판 데이터</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-pl/strings.xml",
    "content": "<resources>\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\n\t<!-- Strings used for fragments for navigation -->\n\n\t<string name=\"guide_full_installation\">Aby zagrać w pełną wersję, musisz umieścić DIABDAT.MPQ z oryginalnej gry w Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nJeśli nie masz oryginalnej gry, możesz kupić Diablo na <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\n\t<string name=\"guide_shareware\">Alternatywnie możesz pobrać wersję spawn, aby zagrać w część demo gry.</string>\n\t<string name=\"faq_link\">Zobacz <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Instrukcje instalacji</a>, aby uzyskać więcej informacji.</string>\n\t<string name=\"game_data_retry\">Sprawdź ponownie</string>\n\t<string name=\"title_activity_data\">Dane Gry</string>\n\t<string name=\"download_spawn\">Pobierz dane Demo</string>\n\t<string name=\"missing_game_data\">Brak danych gry</string>\n\t<string name=\"download_started\">Pobieranie rozpoczęte</string>\n\t<string name=\"shareware_data\">Dane Demo Diablo</string>\n</resources>\n"
  },
  {
    "path": "android-project/app/src/main/res/values-pt-rBR/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Para jogar a versão completa você deve colocar o arquivo DIABDAT.MPQ do jogo original em Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nSe você não tiver o jogo original, então você pode comprar o Diablo em <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">Alternativamente você pode baixar a versão spawn, para jogar a parte demo do jogo.</string>\r\n\t<string name=\"faq_link\">Veja as <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Instruções de instalação</a> para mais detalhes.</string>\r\n\t<string name=\"game_data_retry\">Verificar novamente</string>\r\n\t<string name=\"title_activity_data\">Dados do jogo</string>\r\n\t<string name=\"download_spawn\">Baixar dados demo</string>\r\n\t<string name=\"missing_game_data\">Faltando dados do jogo</string>\r\n\t<string name=\"download_started\">Download iniciado</string>\r\n\t<string name=\"shareware_data\">Dados demo do Diablo</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-ro-rRO/strings.xml",
    "content": "<resources>\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\n\t<!-- Strings used for fragments for navigation -->\n\n\t<string name=\"guide_full_installation\">Pentru a jucat versiunea completă trebuie să puneți fișierul DIABDAT.MPQ de la jocul original în Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nDacă nu aveți jocul original atunci puteți cumpăra Diablo de la <a href=\"https://www.gog.com/game/diablo\">GOG.com</a>.</string>\n\t<string name=\"guide_shareware\">Alternativ puteți descărca versiunea \"spawn\", pentru a juca porțiunea demonstrativă a jocului.</string>\n\t<string name=\"faq_link\">Citiți <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Instrucțiunile de instalare</a> pentru mai multe detalii.</string>\n\t<string name=\"game_data_retry\">Verifică din nou</string>\n\t<string name=\"title_activity_data\">Fișierele de date ale jocului</string>\n\t<string name=\"download_spawn\">Descărcare fișiere de date versiune Demo</string>\n\t<string name=\"missing_game_data\">Fișierele de date ale jocului lipsesc</string>\n\t<string name=\"download_started\">Descărcarea a început</string>\n\t<string name=\"shareware_data\">Date versiune Demo Diablo</string>\n</resources>\n"
  },
  {
    "path": "android-project/app/src/main/res/values-ru/strings.xml",
    "content": "<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Чтобы играть в полную версию, Вам необходимо поместить файл DIABDAT.MPQ в Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nЕсли у Вас нет полной версии Вы можете приобрести её на <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">В качестве альтернативы Вы можете загрузить spawn-версию, чтобы играть в demo часть игры.</string>\r\n\t<string name=\"faq_link\">Смотрите <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">инструкцию по установке</a> для более подробной информации.</string>\r\n\t<string name=\"game_data_retry\">Проверить снова</string>\r\n\t<string name=\"title_activity_data\">Игровые данные</string>\r\n\t<string name=\"download_spawn\">Загрузить данные Demo-версии</string>\r\n\t<string name=\"missing_game_data\">Игровые данные отсутствуют</string>\r\n\t<string name=\"download_started\">Загрузка начата</string>\r\n\t<string name=\"shareware_data\">Даннные Demo-версии</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-sv/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\t<string name=\"app_name\">DevilutionX</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-tr/strings.xml",
    "content": "<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">Tam sürümü oynayabilmek için orjinal oyunun DIABDAT.MPQ dosyasını Android/data/org.diasurgical.devilutionx/files konumuna atmalısınız.<br/>\\n<br/>\\nEğer orjinal oyuna sahip değilseniz Diablo\\'yu bu linkten satın alabilirsiniz: <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\r\n\t<string name=\"guide_shareware\">Buna alternatif olarak, oyunu denemek için demo sürümünü de indirebilirsiniz.</string>\r\n\t<string name=\"faq_link\">Daha fazla ayrıntı için lütfen kontrol edin: <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">Kurulum Talimatları</a></string>\r\n\t<string name=\"game_data_retry\">Tekrar kontrol et</string>\r\n\t<string name=\"title_activity_data\">Oyun Dosyaları</string>\r\n\t<string name=\"download_spawn\">Demo Dosyalarını İndir</string>\r\n\t<string name=\"missing_game_data\">Oyun dosyaları eksik</string>\r\n\t<string name=\"download_started\">İndirme işlemi başladı</string>\r\n\t<string name=\"shareware_data\">Diablo Demo Dosyaları</string>\r\n\t<string name=\"import_short_label\">Dosyaları İçeri Aktar</string>\r\n\t<string name=\"gamepad_tv_text\">Bu oyun, kontrolcü gerektirir.</string>\r\n\t<string name=\"import_data_info\">On the next screen, select files that will be imported into:\\n\\n%1$s</string>\r\n\t<string name=\"overwrite_query\">Bu dosyalar tekrar yazılacaktır. Emin misiniz?\\n\\n%1$s</string>\r\n\t<string name=\"ok_button\">Tamam</string>\r\n\t<string name=\"continue_button\">Devam Et</string>\r\n\t<string name=\"cancel_button\">İptal</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-uk/strings.xml",
    "content": "<resources>\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\n\t<!-- Strings used for fragments for navigation -->\n\n\t<string name=\"guide_full_installation\">Для того щоб зіграти в повну версію, Вам треба помістити файл з оригінальної гри DIABDAT.MPQ в папку Android/data/org.diasurgical.devilutionx/files.<br/>\\n<br/>\\nЯкщо у вас немає повної версії, то її можна купити в <a href=\"https://www.gog.com/game/diablo\">GOG.com.</a></string>\n\t<string name=\"guide_shareware\">В якості альтернативи Ви можете завантажити spawn, щоб зіграти в частину гри що доступна в демо-версії.</string>\n\t<string name=\"faq_link\">Дивіться <a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">інструкцію по встановленню</a> для більших подробиць.</string>\n\t<string name=\"game_data_retry\">Перевірити ще раз</string>\n\t<string name=\"title_activity_data\">Дані гри</string>\n\t<string name=\"download_spawn\">Завантажити Демо-версію</string>\n\t<string name=\"missing_game_data\">Дані гри відсутні</string>\n\t<string name=\"download_started\">Завантаження почалось</string>\n\t<string name=\"shareware_data\">Дані Демо-версії Diablo</string>\n</resources>\n"
  },
  {
    "path": "android-project/app/src/main/res/values-zh-rCN/strings.xml",
    "content": "<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">要玩完整版，你必须将原版游戏中的DIABDAT.MPQ放到Android/data/org.diasurgical.devilutionx/files中。<br/>\\n<br/>\\n如果你没有原版游戏，那么你可以从<a href=\"https://www.gog.com/game/diablo\">GOG.com</a>购买暗黑破坏神。</string>\r\n\t<string name=\"guide_shareware\">另外，你也可以下载Spawn版来玩游戏的共享软件部分。</string>\r\n\t<string name=\"faq_link\">请参阅<a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">安装说明</a>以了解更多细节。</string>\r\n\t<string name=\"game_data_retry\">再次检查</string>\r\n\t<string name=\"title_activity_data\">游戏数据</string>\r\n\t<string name=\"download_spawn\">下载共享软件数据</string>\r\n\t<string name=\"missing_game_data\">游戏数据丢失</string>\r\n\t<string name=\"download_started\">开始下载</string>\r\n\t<string name=\"shareware_data\">暗黑破坏神共享软件数据</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/values-zh-rTW/strings.xml",
    "content": "<resources>\r\n\t<string name=\"app_name\" translatable=\"false\">DevilutionX</string>\r\n\t<!-- Strings used for fragments for navigation -->\r\n\r\n\t<string name=\"guide_full_installation\">要玩完整版，你必須將原版遊戲中的DIABDAT.MPQ放到Android/data/org.diasurgical.devilutionx/files中。<br/>\\n<br/>\\n如果你没有原版遊戲，那麼你可以從<a href=\"https://www.gog.com/game/diablo\">GOG.com</a>購買暗黑破壞神。</string>\r\n\t<string name=\"guide_shareware\">另外，你也可以下載Spawn版來玩遊戲的共享軟體部分。</string>\r\n\t<string name=\"faq_link\">請參閱<a href=\"https://github.com/diasurgical/devilutionX/blob/master/docs/installing.md#installing\">安裝說明</a>以了解更多細節。</string>\r\n\t<string name=\"game_data_retry\">再次檢查</string>\r\n\t<string name=\"title_activity_data\">遊戲資料</string>\r\n\t<string name=\"download_spawn\">下載共享軟體資料</string>\r\n\t<string name=\"missing_game_data\">遊戲資料遺失</string>\r\n\t<string name=\"download_started\">開始下載</string>\r\n\t<string name=\"shareware_data\">暗黑破壞神共享軟體資料</string>\r\n</resources>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/xml/backup_descriptor.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<full-backup-content>\r\n    <include domain=\"external\" path=\".\" />\r\n    <exclude domain=\"external\" path=\"devilutionx.mpq\" />\r\n    <exclude domain=\"external\" path=\"diabdat.mpq\" />\r\n    <exclude domain=\"external\" path=\"DIABDAT.MPQ\" />\r\n    <exclude domain=\"external\" path=\"fonts.mpq\" />\n    <exclude domain=\"external\" path=\"hellfire.mpq\" />\r\n    <exclude domain=\"external\" path=\"hfmonk.mpq\" />\r\n    <exclude domain=\"external\" path=\"hfmusic.mpq\" />\r\n    <exclude domain=\"external\" path=\"hfvoice.mpq\" />\r\n    <exclude domain=\"external\" path=\"patch_rt.mpq\" />\r\n    <exclude domain=\"external\" path=\"patch_sh.mpq\" />\r\n    <exclude domain=\"external\" path=\"pl.mpq\" />\r\n    <exclude domain=\"external\" path=\"ru.mpq\" />\r\n    <exclude domain=\"external\" path=\"spawn.mpq\" />\r\n</full-backup-content>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/xml/backup_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<data-extraction-rules>\r\n <cloud-backup disableIfNoEncryptionCapabilities=\"false\">\r\n    <include domain=\"external\" path=\".\" />\r\n    <exclude domain=\"external\" path=\"devilutionx.mpq\" />\r\n    <exclude domain=\"external\" path=\"diabdat.mpq\" />\r\n    <exclude domain=\"external\" path=\"DIABDAT.MPQ\" />\r\n    <exclude domain=\"external\" path=\"fonts.mpq\" />\r\n    <exclude domain=\"external\" path=\"hellfire.mpq\" />\r\n    <exclude domain=\"external\" path=\"hfmonk.mpq\" />\r\n    <exclude domain=\"external\" path=\"hfmusic.mpq\" />\r\n    <exclude domain=\"external\" path=\"hfvoice.mpq\" />\r\n    <exclude domain=\"external\" path=\"patch_rt.mpq\" />\r\n    <exclude domain=\"external\" path=\"patch_sh.mpq\" />\r\n    <exclude domain=\"external\" path=\"pl.mpq\" />\r\n    <exclude domain=\"external\" path=\"ru.mpq\" />\r\n    <exclude domain=\"external\" path=\"spawn.mpq\" />\r\n </cloud-backup>\r\n <device-transfer>\r\n    <include domain=\"external\" path=\".\" />\r\n </device-transfer>\r\n</data-extraction-rules>\r\n"
  },
  {
    "path": "android-project/app/src/main/res/xml/shortcuts.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shortcuts xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n\t<shortcut\r\n\t\tandroid:shortcutId=\"import\"\r\n\t\tandroid:enabled=\"true\"\r\n\t\tandroid:icon=\"@mipmap/ic_launcher_import_data\"\r\n\t\tandroid:shortcutShortLabel=\"@string/import_short_label\">\r\n\t\t<intent\r\n\t\t\tandroid:action=\"android.intent.action.VIEW\"\r\n\t\t\tandroid:targetPackage=\"org.diasurgical.devilutionx\"\r\n\t\t\tandroid:targetClass=\"org.diasurgical.devilutionx.ImportActivity\" />\r\n\t</shortcut>\r\n</shortcuts>\r\n"
  },
  {
    "path": "android-project/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\r\n\r\nbuildscript {\r\n\trepositories {\r\n\t\tmavenCentral()\r\n\t\tgoogle()\r\n\t}\r\n\tdependencies {\r\n\t\tclasspath 'com.android.tools.build:gradle:8.13.0'\r\n\r\n\t\t// NOTE: Do not place your application dependencies here; they belong\r\n\t\t// in the individual module build.gradle files\r\n\t}\r\n}\r\n\r\nallprojects {\r\n\trepositories {\r\n\t\tmavenCentral()\r\n\t\tgoogle()\r\n\t}\r\n}\r\n\r\ntasks.register('clean', Delete) {\r\n\tdelete rootProject.layout.buildDirectory\r\n}\r\n"
  },
  {
    "path": "android-project/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Apr 29 13:42:12 EEST 2024\r\ndistributionBase=GRADLE_USER_HOME\r\ndistributionPath=wrapper/dists\r\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.13-bin.zip\r\nzipStoreBase=GRADLE_USER_HOME\r\nzipStorePath=wrapper/dists\r\n"
  },
  {
    "path": "android-project/gradle.properties",
    "content": "android.nonFinalResIds=false\r\nandroid.nonTransitiveRClass=false\r\n"
  },
  {
    "path": "android-project/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|grep -E -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|grep -E -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "android-project/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "android-project/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "assets/ASSETS_VERSION",
    "content": "1\n"
  },
  {
    "path": "assets/data/inv/objcurs-widths.txt",
    "content": "33\r\n32\r\n32\r\n32\r\n32\r\n32\r\n32\r\n32\r\n32\r\n32\r\n23\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n"
  },
  {
    "path": "assets/lua/devilutionx/events.lua",
    "content": "local function CreateEvent()\n  local functions = {}\n  return {\n    ---Adds an event handler.\n    ---\n    ---The handler called every time an event is triggered.\n    ---@param func function\n    add = function(func)\n      table.insert(functions, func)\n    end,\n\n    ---Removes the event handler.\n    ---@param func function\n    remove = function(func)\n      for i, f in ipairs(functions) do\n        if f == func then\n          table.remove(functions, i)\n          break\n        end\n      end\n    end,\n\n    ---Triggers an event.\n    ---\n    ---The arguments are forwarded to handlers.\n    ---@param ... any\n    ---@return any\n    trigger = function(...)\n      local result\n      for _, func in ipairs(functions) do\n        result = func(...)\n      end\n      return result\n    end,\n    __sig_trigger = \"(...)\",\n  }\nend\n\nlocal events = {\n  ---Called after all mods have been loaded.\n  LoadModsComplete = CreateEvent(),\n  __doc_LoadModsComplete = \"Called after all mods have been loaded.\",\n\n  ---Called after the item data TSV file has been loaded.\n  ItemDataLoaded = CreateEvent(),\n  __doc_ItemDataLoaded = \"Called after the item data TSV file has been loaded.\",\n\n  ---Called after the unique item data TSV file has been loaded.\n  UniqueItemDataLoaded = CreateEvent(),\n  __doc_UniqueItemDataLoaded = \"Called after the unique item data TSV file has been loaded.\",\n\n  ---Called after the monster data TSV file has been loaded.\n  MonsterDataLoaded = CreateEvent(),\n  __doc_MonsterDataLoaded = \"Called after the monster data TSV file has been loaded.\",\n\n  ---Called after the unique monster data TSV file has been loaded.\n  UniqueMonsterDataLoaded = CreateEvent(),\n  __doc_UniqueMonsterDataLoaded = \"Called after the unique monster data TSV file has been loaded.\",\n\n  ---Called every time a new game is started.\n  GameStart = CreateEvent(),\n  __doc_GameStart = \"Called every time a new game is started.\",\n\n  ---Called every frame at the end.\n  GameDrawComplete = CreateEvent(),\n  __doc_GameDrawComplete = \"Called every frame at the end.\",\n\n  ---Called when opening a towner store. Passes the towner name as argument (e.g., \"griswold\", \"adria\", \"pepin\", \"wirt\", \"cain\").\n  StoreOpened = CreateEvent(),\n  __doc_StoreOpened = \"Called when opening a towner store. Passes the towner name as argument.\",\n\n  ---Called when a Monster takes damage.\n  OnMonsterTakeDamage = CreateEvent(),\n  __doc_OnMonsterTakeDamage = \"Called when a Monster takes damage.\",\n\n  ---Called when Player takes damage.\n  OnPlayerTakeDamage = CreateEvent(),\n  __doc_OnPlayerTakeDamage = \"Called when Player takes damage.\",\n\n  ---Called when Player gains experience.\n  OnPlayerGainExperience = CreateEvent(),\n  __doc_OnPlayerGainExperience = \"Called when Player gains experience.\",\n}\n\n---Registers a custom event type with the given name.\n---@param name string\nfunction events.registerCustom(name)\n  events[name] = CreateEvent()\nend\n\nevents.__sig_registerCustom = \"(name: string)\"\nevents.__doc_registerCustom = \"Register a custom event type.\"\n\nreturn events\n"
  },
  {
    "path": "assets/lua/inspect.lua",
    "content": "local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table\nlocal inspect = {Options = {}, }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ninspect._VERSION = 'inspect.lua 3.1.0'\ninspect._URL = 'http://github.com/kikito/inspect.lua'\ninspect._DESCRIPTION = 'human-readable representations of tables'\ninspect._LICENSE = [[\n  MIT LICENSE\n\n  Copyright (c) 2022 Enrique García Cota\n\n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the\n  \"Software\"), to deal in the Software without restriction, including\n  without limitation the rights to use, copy, modify, merge, publish,\n  distribute, sublicense, and/or sell copies of the Software, and to\n  permit persons to whom the Software is 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 Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n  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  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n]]\ninspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end })\ninspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end })\n\nlocal tostring = tostring\nlocal rep = string.rep\nlocal match = string.match\nlocal char = string.char\nlocal gsub = string.gsub\nlocal fmt = string.format\n\nlocal _rawget\nif rawget then\n   _rawget = rawget\nelse\n   _rawget = function(t, k) return t[k] end\nend\n\nlocal function rawpairs(t)\n   return next, t, nil\nend\n\n\n\nlocal function smartQuote(str)\n   if match(str, '\"') and not match(str, \"'\") then\n      return \"'\" .. str .. \"'\"\n   end\n   return '\"' .. gsub(str, '\"', '\\\\\"') .. '\"'\nend\n\n\nlocal shortControlCharEscapes = {\n   [\"\\a\"] = \"\\\\a\", [\"\\b\"] = \"\\\\b\", [\"\\f\"] = \"\\\\f\", [\"\\n\"] = \"\\\\n\",\n   [\"\\r\"] = \"\\\\r\", [\"\\t\"] = \"\\\\t\", [\"\\v\"] = \"\\\\v\", [\"\\127\"] = \"\\\\127\",\n}\nlocal longControlCharEscapes = { [\"\\127\"] = \"\\127\" }\nfor i = 0, 31 do\n   local ch = char(i)\n   if not shortControlCharEscapes[ch] then\n      shortControlCharEscapes[ch] = \"\\\\\" .. i\n      longControlCharEscapes[ch] = fmt(\"\\\\%03d\", i)\n   end\nend\n\nlocal function escape(str)\n   return (gsub(gsub(gsub(str, \"\\\\\", \"\\\\\\\\\"),\n   \"(%c)%f[0-9]\", longControlCharEscapes),\n   \"%c\", shortControlCharEscapes))\nend\n\nlocal luaKeywords = {\n   ['and'] = true,\n   ['break'] = true,\n   ['do'] = true,\n   ['else'] = true,\n   ['elseif'] = true,\n   ['end'] = true,\n   ['false'] = true,\n   ['for'] = true,\n   ['function'] = true,\n   ['goto'] = true,\n   ['if'] = true,\n   ['in'] = true,\n   ['local'] = true,\n   ['nil'] = true,\n   ['not'] = true,\n   ['or'] = true,\n   ['repeat'] = true,\n   ['return'] = true,\n   ['then'] = true,\n   ['true'] = true,\n   ['until'] = true,\n   ['while'] = true,\n}\n\nlocal function isIdentifier(str)\n   return type(str) == \"string\" and\n   not not str:match(\"^[_%a][_%a%d]*$\") and\n   not luaKeywords[str]\nend\n\nlocal flr = math.floor\nlocal function isSequenceKey(k, sequenceLength)\n   return type(k) == \"number\" and\n   flr(k) == k and\n   1 <= (k) and\n   k <= sequenceLength\nend\n\nlocal defaultTypeOrders = {\n   ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,\n   ['function'] = 5, ['userdata'] = 6, ['thread'] = 7,\n}\n\nlocal function sortKeys(a, b)\n   local ta, tb = type(a), type(b)\n\n\n   if ta == tb and (ta == 'string' or ta == 'number') then\n      return (a) < (b)\n   end\n\n   local dta = defaultTypeOrders[ta] or 100\n   local dtb = defaultTypeOrders[tb] or 100\n\n\n   return dta == dtb and ta < tb or dta < dtb\nend\n\nlocal function getKeys(t)\n\n   local seqLen = 1\n   while _rawget(t, seqLen) ~= nil do\n      seqLen = seqLen + 1\n   end\n   seqLen = seqLen - 1\n\n   local keys, keysLen = {}, 0\n   for k in rawpairs(t) do\n      if not isSequenceKey(k, seqLen) then\n         keysLen = keysLen + 1\n         keys[keysLen] = k\n      end\n   end\n   table.sort(keys, sortKeys)\n   return keys, keysLen, seqLen\nend\n\nlocal function countCycles(x, cycles)\n   if type(x) == \"table\" then\n      if cycles[x] then\n         cycles[x] = cycles[x] + 1\n      else\n         cycles[x] = 1\n         for k, v in rawpairs(x) do\n            countCycles(k, cycles)\n            countCycles(v, cycles)\n         end\n         countCycles(getmetatable(x), cycles)\n      end\n   end\nend\n\nlocal function makePath(path, a, b)\n   local newPath = {}\n   local len = #path\n   for i = 1, len do newPath[i] = path[i] end\n\n   newPath[len + 1] = a\n   newPath[len + 2] = b\n\n   return newPath\nend\n\n\nlocal function processRecursive(process,\n   item,\n   path,\n   visited)\n   if item == nil then return nil end\n   if visited[item] then return visited[item] end\n\n   local processed = process(item, path)\n   if type(processed) == \"table\" then\n      local processedCopy = {}\n      visited[item] = processedCopy\n      local processedKey\n\n      for k, v in rawpairs(processed) do\n         processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)\n         if processedKey ~= nil then\n            processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)\n         end\n      end\n\n      local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)\n      if type(mt) ~= 'table' then mt = nil end\n      setmetatable(processedCopy, mt)\n      processed = processedCopy\n   end\n   return processed\nend\n\nlocal function puts(buf, str)\n   buf.n = buf.n + 1\n   buf[buf.n] = str\nend\n\n\n\nlocal Inspector = {}\n\n\n\n\n\n\n\n\n\n\nlocal Inspector_mt = { __index = Inspector }\n\nlocal function tabify(inspector)\n   puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level))\nend\n\nfunction Inspector:getId(v)\n   local id = self.ids[v]\n   local ids = self.ids\n   if not id then\n      local tv = type(v)\n      id = (ids[tv] or 0) + 1\n      ids[v], ids[tv] = id, id\n   end\n   return tostring(id)\nend\n\nfunction Inspector:putValue(v)\n   local buf = self.buf\n   local tv = type(v)\n   if tv == 'string' then\n      puts(buf, smartQuote(escape(v)))\n   elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or\n      tv == 'cdata' or tv == 'ctype' then\n      puts(buf, tostring(v))\n   elseif tv == 'table' and not self.ids[v] then\n      local t = v\n\n      if t == inspect.KEY or t == inspect.METATABLE then\n         puts(buf, tostring(t))\n      elseif self.level >= self.depth then\n         puts(buf, '{...}')\n      else\n         if self.cycles[t] > 1 then puts(buf, fmt('<%d>', self:getId(t))) end\n\n         local keys, keysLen, seqLen = getKeys(t)\n\n         puts(buf, '{')\n         self.level = self.level + 1\n\n         for i = 1, seqLen + keysLen do\n            if i > 1 then puts(buf, ',') end\n            if i <= seqLen then\n               puts(buf, ' ')\n               self:putValue(t[i])\n            else\n               local k = keys[i - seqLen]\n               tabify(self)\n               if isIdentifier(k) then\n                  puts(buf, k)\n               else\n                  puts(buf, \"[\")\n                  self:putValue(k)\n                  puts(buf, \"]\")\n               end\n               puts(buf, ' = ')\n               self:putValue(t[k])\n            end\n         end\n\n         local mt = getmetatable(t)\n         if type(mt) == 'table' then\n            if seqLen + keysLen > 0 then puts(buf, ',') end\n            tabify(self)\n            puts(buf, '<metatable> = ')\n            self:putValue(mt)\n         end\n\n         self.level = self.level - 1\n\n         if keysLen > 0 or type(mt) == 'table' then\n            tabify(self)\n         elseif seqLen > 0 then\n            puts(buf, ' ')\n         end\n\n         puts(buf, '}')\n      end\n\n   else\n      puts(buf, fmt('<%s %d>', tv, self:getId(v)))\n   end\nend\n\n\n\n\nfunction inspect.inspect(root, options)\n   options = options or {}\n\n   local depth = options.depth or (math.huge)\n   local newline = options.newline or '\\n'\n   local indent = options.indent or '  '\n   local process = options.process\n\n   if process then\n      root = processRecursive(process, root, {}, {})\n   end\n\n   local cycles = {}\n   countCycles(root, cycles)\n\n   local inspector = setmetatable({\n      buf = { n = 0 },\n      ids = {},\n      cycles = cycles,\n      depth = depth,\n      level = 0,\n      newline = newline,\n      indent = indent,\n   }, Inspector_mt)\n\n   inspector:putValue(root)\n\n   return table.concat(inspector.buf)\nend\n\nsetmetatable(inspect, {\n   __call = function(_, root, options)\n      return inspect.inspect(root, options)\n   end,\n})\n\nreturn inspect\n"
  },
  {
    "path": "assets/lua/mods/Floating Numbers - Damage/init.lua",
    "content": "local floatingnumbers = require(\"devilutionx.floatingnumbers\")\r\nlocal events = require(\"devilutionx.events\")\r\nlocal player = require(\"devilutionx.player\")\r\nlocal system = require(\"devilutionx.system\")\r\nlocal render = require(\"devilutionx.render\")\r\n\r\nlocal DAMAGE_TYPE = {\r\n    PHYSICAL = 0,\r\n    FIRE = 1,\r\n    LIGHTNING = 2,\r\n    MAGIC = 3,\r\n    ACID = 4,\r\n}\r\n\r\nlocal function get_damage_style(damage_val, damage_type)\r\n    local style = 0\r\n    \r\n    local v = damage_val\r\n    if v >= 64 * 300 then\r\n        style = style | render.UiFlags.FontSize30\r\n    elseif v >= 64 * 100 then\r\n        style = style | render.UiFlags.FontSize24\r\n    else\r\n        style = style | render.UiFlags.FontSize12\r\n    end\r\n\r\n    local damage_type_styles = {\r\n        [DAMAGE_TYPE.PHYSICAL] = render.UiFlags.ColorGold,\r\n        [DAMAGE_TYPE.FIRE] = render.UiFlags.ColorUiSilver, -- shows as DarkRed in game\r\n        [DAMAGE_TYPE.LIGHTNING] = render.UiFlags.ColorBlue,\r\n        [DAMAGE_TYPE.MAGIC] = render.UiFlags.ColorOrange,\r\n        [DAMAGE_TYPE.ACID] = render.UiFlags.ColorYellow,\r\n    }\r\n\r\n    local type_style = damage_type_styles[damage_type]\r\n    if type_style then\r\n        style = style | type_style\r\n    end\r\n\r\n    return style\r\nend\r\n\r\nlocal function format_damage(damage_val)\r\n    if damage_val > 0 and damage_val < 64 then\r\n        return string.format(\"%.2f\", damage_val / 64.0)\r\n    else\r\n        return tostring(math.floor(damage_val / 64))\r\n    end\r\nend\r\n\r\nlocal accumulated_damage = {}\r\nlocal MERGE_WINDOW_MS = 100\r\n\r\nevents.OnMonsterTakeDamage.add(function(monster, damage, damage_type)\r\n    local id = monster.id\r\n    local now = system.get_ticks()\r\n    \r\n    local entry = accumulated_damage[id]\r\n    if entry and (now - entry.time) < MERGE_WINDOW_MS then\r\n        entry.damage = entry.damage + damage\r\n    else\r\n        entry = { damage = damage, time = now }\r\n        accumulated_damage[id] = entry\r\n    end\r\n    entry.time = now\r\n\r\n    local text = format_damage(entry.damage)\r\n    local style = get_damage_style(entry.damage, damage_type)\r\n    floatingnumbers.add(text, monster.position, style, id, false) \r\nend)\r\n\r\nevents.OnPlayerTakeDamage.add(function(_player, damage, damage_type)\r\n    if _player == player.self() then\r\n        local id = _player.id\r\n        local now = system.get_ticks()\r\n        \r\n        local entry = accumulated_damage[id]\r\n        if entry and (now - entry.time) < MERGE_WINDOW_MS then\r\n            entry.damage = entry.damage + damage\r\n        else\r\n            entry = { damage = damage, time = now }\r\n            accumulated_damage[id] = entry\r\n        end\r\n        entry.time = now\r\n\r\n        local text = format_damage(entry.damage)\r\n        local style = get_damage_style(entry.damage, damage_type)\r\n        floatingnumbers.add(text, _player.position, style, id, true)\r\n    end\r\nend)\r\n"
  },
  {
    "path": "assets/lua/mods/Floating Numbers - XP/init.lua",
    "content": "local floatingnumbers = require(\"devilutionx.floatingnumbers\")\r\nlocal events = require(\"devilutionx.events\")\r\nlocal player = require(\"devilutionx.player\")\r\nlocal system = require(\"devilutionx.system\")\r\nlocal render = require(\"devilutionx.render\")\r\n\r\nlocal accumulated_xp = {}\r\nlocal MERGE_WINDOW_MS = 100\r\n\r\nevents.OnPlayerGainExperience.add(function(_player, experience)\r\n    if _player == player.self() then\r\n        local id = _player.id\r\n        local now = system.get_ticks()\r\n        \r\n        local entry = accumulated_xp[id]\r\n        if entry and (now - entry.time) < MERGE_WINDOW_MS then\r\n            entry.experience = entry.experience + experience\r\n        else\r\n            entry = { experience = experience, time = now }\r\n            accumulated_xp[id] = entry\r\n        end\r\n        entry.time = now\r\n\r\n        local text = tostring(entry.experience) .. \" XP\"\r\n        floatingnumbers.add(text, _player.position, render.UiFlags.ColorWhite, id, true)\r\n    end\r\nend)\r\n"
  },
  {
    "path": "assets/lua/mods/adria_refills_mana/init.lua",
    "content": "-- Adria Refills Mana Mod\n-- When you visit Adria's shop, your mana is restored to full.\n\nlocal events = require(\"devilutionx.events\")\nlocal player = require(\"devilutionx.player\")\nlocal audio = require(\"devilutionx.audio\")\n\nevents.StoreOpened.add(function(townerName)\n  if townerName ~= \"adria\" then\n    return\n  end\n\n  local p = player.self()\n  if p == nil then\n    return\n  end\n\n  -- Restore mana if player has mana capacity and it's not already full\n  if p.maxMana > 0 and p.mana < p.maxMana then\n    audio.playSfx(audio.SfxID.CastHealing)\n    p:restoreFullMana()\n  end\nend)\n"
  },
  {
    "path": "assets/lua/mods/clock/init.lua",
    "content": "local events = require(\"devilutionx.events\")\nlocal render = require(\"devilutionx.render\")\n\nevents.GameDrawComplete.add(function()\n  render.string(os.date('%H:%M:%S', os.time()), render.screen_width() - 76, 6)\nend)\n"
  },
  {
    "path": "assets/lua/repl_prelude.lua",
    "content": "events = require('devilutionx.events')\ni18n = require('devilutionx.i18n')\nitems = require('devilutionx.items')\nlog = require('devilutionx.log')\naudio = require('devilutionx.audio')\nplayer = require('devilutionx.player')\nrender = require('devilutionx.render')\ntowners = require('devilutionx.towners')\nmessage = require('devilutionx.message')\nif _DEBUG then dev = require('devilutionx.dev') end\ninspect = require('inspect')\n\n-- Expose item enums from items module for easy access in console\nItemIndex = items.ItemIndex\nItemType = items.ItemType\nItemClass = items.ItemClass\nItemEquipType = items.ItemEquipType\nItemMiscID = items.ItemMiscID\nSpellID = items.SpellID\nItemEffectType = items.ItemEffectType\nItemSpecialEffect = items.ItemSpecialEffect\nItemSpecialEffectHf = items.ItemSpecialEffectHf\n"
  },
  {
    "path": "assets/lua_internal/get_lua_function_signature.lua",
    "content": "-- Gets the signature of native (non-C) Lua function\n-- Based on https://stackoverflow.com/a/24216007/181228\n\nlocal function getlocals(l)\n  local i = 0\n  local direction = 1\n  return function()\n    i = i + direction\n    local k, v = debug.getlocal(l, i)\n    if (direction == 1 and (k == nil or k.sub(k, 1, 1) == '(')) then\n      i = -1\n      direction = -1\n      k, v = debug.getlocal(l, i)\n    end\n    return k, v\n  end\nend\n\nlocal function dumpsig(f)\n  assert(type(f) == 'function', \"bad argument #1 to 'dumpsig' (function expected)\")\n  local p = {}\n  pcall(function()\n    local oldhook\n    local hook = function(event, line)\n      for k, v in getlocals(3) do\n        if k == \"(*vararg)\" then\n          table.insert(p, \"...\")\n          break\n        end\n        table.insert(p, k)\n      end\n      debug.sethook(oldhook)\n      error('aborting the call')\n    end\n    oldhook = debug.sethook(hook, \"c\")\n    f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)\n  end)\n  return \"(\" .. table.concat(p, \", \") .. \")\"\nend\n\nreturn dumpsig\n"
  },
  {
    "path": "assets/txtdata/Experience.tsv",
    "content": "Level\tExperience\n1\t2000\n2\t4620\n3\t8040\n4\t12489\n5\t18258\n6\t25712\n7\t35309\n8\t47622\n9\t63364\n10\t83419\n11\t108879\n12\t141086\n13\t181683\n14\t231075\n15\t313656\n16\t424067\n17\t571190\n18\t766569\n19\t1025154\n20\t1366227\n21\t1814568\n22\t2401895\n23\t3168651\n24\t4166200\n25\t5459523\n26\t7130496\n27\t9281874\n28\t12042092\n29\t15571031\n30\t20066900\n31\t25774405\n32\t32994399\n33\t42095202\n34\t53525811\n35\t67831218\n36\t85670061\n37\t107834823\n38\t135274799\n39\t169122009\n40\t210720231\n41\t261657253\n42\t323800420\n43\t399335440\n44\t490808349\n45\t601170414\n46\t733825617\n47\t892680222\n48\t1082908612\n49\t1310707109\n50\t1583495809\n"
  },
  {
    "path": "assets/txtdata/Readme.md",
    "content": "Data files are based on the format used by Diablo 2. This is a format very\nsimilar to [IANA TSV][iana-tsv] but with fewer restrictions. Existing tools\nsuch as AFJ Sheet, Diablo 2 Excel File Editor, [D2ExcelPlus][d2-excel-plus],\nor spreadsheet programs such as Excel and [LibreOffice][libreoffice] Calc can\nbe used to read/modify these files. If using a program like Excel or\nLibreOffice you will need to check that the output matches the expected format\n(tabs as delimiters, field values saved with leading spaces and quote\ncharacters preserved, tabs and newlines in fields stripped or transformed to\nspaces).\n\n## Format Specification\nFor modders, the important thing to keep in mind is that values cannot contain\ntab characters or line breaks. If you make sure the file looks roughly the\nsame after changing your values you shouldn't get any errors.\n\nA formal description of the format using\n[W3C's EBNF for XML notation][w3-xml-ebnf]:\n```\n/*\n  Files MAY start with a UTF8 BOM (mainly to play nicer with Excel).\n  The first record in a file SHOULD be used as a header\n    Implementations are free to treat records however they want, using\n    multiple records as headers or none at all.\n  All files contain at least one record. The last record in a file SHOULD end\n    with a trailing newline, however some spreadsheet applications do not\n    output trailing newlines so we allow flexibility here. This means that an\n    empty file (zero-length or containing only a UTF8 BOM sequence) is valid\n    and is typically interpreted as a header for a single unnamed column with\n    no records.\n  Records SHOULD contain the same number of fields.\n*/\nDXTxtFile     ::= utf8bom? ( singleRecord | record+ finalRecord? )\n\nutf8bom       ::= #xEF #xBB #xBF\n\n/*\n  if parsing reaches EOF and the file has no record terminators then the file\n  MUST be treated as containing a single record with no terminator\n*/\nsingleRecord  ::= fields\n\n/*\n  if for some reason you want to end a file with a record containing a single\n  empty field then the record MUST end with a valid terminator\n*/\nrecord        ::= fields recordterm\n\n/*\n  this means that the terminator is only truly optional for files where the\n  final record contains a single field with at least one character, or at least\n  two fields (as there will then be at least one field separator even if both\n  fields are zero-length)\n*/\nfinalRecord   ::= nonEmptyField | field fieldsep fields\n\n/* an empty line is treated as a single empty field */\nfields        ::= field ( fieldsep field )*\n\n/* fields MAY be zero length */\nfield         ::= character*\n\n/*\n  unless the final record only consists of a single field, in which case it\n  MUST contain at least one character\n*/\nnonEmptyField ::= character+\n\n/*\n  Any Char (see https://www.w3.org/TR/xml/#NT-Char) except Tab (\"\\t\", 0x09),\n  Line Feed (\"\\n\", 0x0A), or Carriage Return (\"\\r\", 0x0D) is allowed as a\n  field value. For maximum portability characters in the discouraged ranges\n  described in the linked section SHOULD NOT be used\n*/\ncharacter     ::= [^#x9#xA#xD]\n\n/* fields MUST be separated by tabs */\nfieldsep      ::= #x9\n\n/*\n  records (other than the final record or the only record in a single-record\n  file) MUST be terminated by line feeds, a cr/lf pair MAY be used\n*/\nrecordterm    ::= #xD? #xA\n```\n\n## File Descriptions\nThe following documentation describes how these files are used in DevilutionX.\nDiablo and Hellfire do not use external text files, you cannot use these files\nto change the behaviour in the original games or the GoG versions. Diablo 2\nuses a similar but distinct format, [ThePhrozenKeep][d2mods-info] provide a\ngood reference for modding that game. Diablo 2 Resurrected uses a different\nformat again, refer to the help files provided alongside the game data\n(`Data/Global/Excel`) (also available online at\n[D2:R Modding][d2rmodding-utilities]).\n\n### Experience.tsv\nExperience contains the experience value thresholds before a character\nadvances to the next level. All numeric values in this file MUST be written in\nbase 10 with no decimal or thousands separators. The first row of this file is\nused as a header and requires the following column names:\n\n#### Level\nA numeric value used to set the order for experience thresholds. The header\nline MUST be the first line in the file. Levels SHOULD proceed in ascending\norder after that starting from level 1. Levels up to 255 are supported, the\nhighest value will be used as the maximum character level. If you leave any\ngaps then characters will not be able to advance past that level and experience\ncaps will not apply.\n\nIf you're familiar with Diablo 2 text files you might expect to use a MaxLevel\nrow to set character level limits and to have a level 0 line, we ignore these\nlines in DevilutionX. As all characters start at level 1 we use the threshold\nfor level 1 to determine when characters advance past level 1. The highest\nlevel defined in the file is the maximum level.\n\n#### Experience\nThis column determines the experience points required for characters to\nadvance past that level. For example a file like:\n```tsv\nLevel\tExperience\n1\t2000\n2\t4000\n3\t6000\n4\t8000\n5\t10000\n```\nCould be used to have characters level up to a max of 5 every 2000 experience\npoints. They would start at level 1, level up to 2 at 2000 exp, level 3 at\n4000 exp, level 4 at 6000 exp, then reach the maxium level of 5 at 8000 exp.\nCharacters would continue gaining experience until they hit 10000 experience\npoints and will not level up any further.\n\nYou should provide a value for every row up to (and including) the maximum\nlevel you intend players to be able to reach. If you have an empty cell for an\nexperience value at a given level then characters will not be able to advance\npast that level. They will continue to gain experience without a cap (up to the\nhard limit of `2^32-1`, 4,294,967,295).\n\n[d2-excel-plus]: https://github.com/Cjreek/D2ExcelPlus\n[d2mods-info]: https://www.d2mods.info/forum/viewtopic.php?t=34455\n[d2rmodding-utilities]: https://www.d2rmodding.com/utilities\n[iana-tsv]: https://www.iana.org/assignments/media-types/text/tab-separated-values\n[libreoffice]: https://www.libreoffice.org\n[w3-xml-ebnf]: https://www.w3.org/TR/xml/#sec-notation\n"
  },
  {
    "path": "assets/txtdata/classes/README.md",
    "content": "# Player class data\n\nThere is one folder per class.\n\n### attributes.tsv\n\n Attribute         | Description\n------------------:|--------------------------------------\n `baseStr`         | Class Starting Strength Stat, uint8_t\n `baseMag`         | Class Starting Magic Stat, uint8_t\n `baseDex`         | Class Starting Dexterity Stat, uint8_t\n `baseVit`         | Class Starting Vitality Stat, uint8_t\n `maxStr`          | Class Maximum Strength Stat, uint8_t\n `maxMag`          | Class Maximum Magic Stat, uint8_t\n `maxDex`          | Class Maximum Dexterity Stat, uint8_t\n `maxVit`          | Class Maximum Vitality Stat, uint8_t\n `blockBonus`      | Class Block Bonus, %\n `adjLife`         | Class Life Adjustment, decimal\n `adjMana`         | Class Mana Adjustment, decimal\n `lvlLife`         | Life gained on level up, decimal\n `lvlMana`         | Mana gained on level up, decimal\n `chrLife`         | Life from base Vitality, decimal\n `chrMana`         | Mana from base Magic, decimal\n `itmLife`         | Life from item bonus Vitality, decimal\n `itmMana`         | Mana from item bonus Magic, decimal\n `baseMagicToHit`  | Starting chance to hit with spells/scrolls, %\n `baseMeleeToHit`  | Starting chance to hit with melee weapons/fists, %\n `baseRangedToHit` | Starting chance to hit with ranged weapons, %\n"
  },
  {
    "path": "assets/txtdata/classes/barbarian/animations.tsv",
    "content": "Variable\tValue\r\nunarmedFrames\t16\r\nunarmedActionFrame\t9\r\nunarmedShieldFrames\t16\r\nunarmedShieldActionFrame\t9\r\nswordFrames\t16\r\nswordActionFrame\t9\r\nswordShieldFrames\t16\r\nswordShieldActionFrame\t9\r\nbowFrames\t16\r\nbowActionFrame\t11\r\naxeFrames\t20\r\naxeActionFrame\t8\r\nmaceFrames\t16\r\nmaceActionFrame\t8\r\nmaceShieldFrames\t16\r\nmaceShieldActionFrame\t8\r\nstaffFrames\t16\r\nstaffActionFrame\t11\r\nidleFrames\t10\r\nwalkingFrames\t8\r\nblockingFrames\t2\r\ndeathFrames\t20\r\ncastingFrames\t20\r\nrecoveryFrames\t6\r\ntownIdleFrames\t20\r\ntownWalkingFrames\t8\r\ncastingActionFrame\t14\r\n"
  },
  {
    "path": "assets/txtdata/classes/barbarian/attributes.tsv",
    "content": "Attribute\tValue\r\nclassFlags\tCriticalStrike,IronSkin,NaturalResistance\r\nbaseStr\t40\r\nbaseMag\t0\r\nbaseDex\t20\r\nbaseVit\t25\r\nmaxStr\t255\r\nmaxMag\t0\r\nmaxDex\t55\r\nmaxVit\t150\r\nblockBonus\t30\r\nadjLife\t18\r\nadjMana\t0\r\nlvlLife\t2\r\nlvlMana\t0\r\nchrLife\t2\r\nchrMana\t1\r\nitmLife\t2.5\r\nitmMana\t1\r\nbaseMagicToHit\t50\r\nbaseMeleeToHit\t50\r\nbaseRangedToHit\t50\r\n"
  },
  {
    "path": "assets/txtdata/classes/barbarian/sounds.tsv",
    "content": "speech\tsfx\r\nChamberOfBoneLore\tWarrior1\r\nHorazonsSanctumLore\tWarrior2\r\nGolemSpellLore\tWarrior3\r\nHorazonsCreatureOfFlameLore\tWarrior4\r\nMortaVespaGaieaInnuminoEvegeenJatanLuaGraton\tWarrior5\r\nGrimspikeLieutenantOfBelialLore\tWarrior6\r\nHorazonsJournal\tWarrior7\r\nYourDeathWillBeAvenged\tWarrior8\r\nRestInPeaceMyFriend\tWarrior9\r\nValorLore\tWarrior10\r\nHallsOfTheBlindLore\tWarrior11\r\nWarlordOfBloodLore\tWarrior12\r\nICantUseThisYet\tWarrior13\r\nICantCarryAnymore\tWarrior14\r\nIHaveNoRoom\tWarrior15\r\nWhereWouldIPutThis\tWarrior16\r\nNoWay\tWarrior17\r\nNotAChance\tWarrior18\r\nIdNeverUseThis\tWarrior19\r\nIdHaveToEquipThat\tWarrior20\r\nICantMoveThis\tWarrior21\r\nICantMoveThisYet\tWarrior22\r\nICantOpenThis\tWarrior23\r\nICantOpenThisYet\tWarrior24\r\nICantLiftThis\tWarrior25\r\nICantLiftThisYet\tWarrior26\r\nICantCastThatHere\tWarrior27\r\nICantCastThatYet\tWarrior28\r\nThatDidntDoAnything\tWarrior29\r\nICanAlreadyDoThat\tWarrior30\r\nIDontNeedThat\tWarrior31\r\nIDontNeedToDoThat\tWarrior32\r\nIDontWantThat\tWarrior33\r\nIDontHaveASpellReady\tWarrior34\r\nNotEnoughMana\tWarrior35\r\nThatWouldKillMe\tWarrior36\r\nICantDoThat\tWarrior37\r\nNo\tWarrior38\r\nYes\tWarrior39\r\nThatWontWork\tWarrior40\r\nThatWontWorkHere\tWarrior41\r\nThatWontWorkYet\tWarrior42\r\nICantGetThereFromHere\tWarrior43\r\nItsTooHeavy\tWarrior44\r\nItsTooBig\tWarrior45\r\nJustWhatIWasLookingFor\tWarrior46\r\nIveGotABadFeelingAboutThis\tWarrior47\r\nGotMilk\tWarrior48\r\nImNotThirsty\tWarrior49\r\nImNoMilkmaid\tWarrior50\r\nICouldBlowUpTheWholeVillage\tWarrior51\r\nYepThatsACowAlright\tWarrior52\r\nTooUghHeavy\tWarrior53\r\nInSpirituSanctum\tWarrior54\r\nPraedictumOtium\tWarrior55\r\nEfficioObitusUtInimicus\tWarrior56\r\nTheEnchantmentIsGone\tWarrior57\r\nOhTooEasy\tWarrior58\r\nBackToTheGrave\tWarrior59\r\nTimeToDie\tWarrior60\r\nImNotImpressed\tWarrior61\r\nImSorryDidIBreakYourConcentration\tWarrior62\r\nVengeanceIsMine\tWarrior63\r\nDie\tWarrior64\r\nYeah\tWarrior65\r\nAh\tWarrior66\r\nPhew\tWarrior67\r\nArgh\tWarrior68\r\nArghClang\tWarrior69\r\nAaaaargh\tWarrior70\r\nOofAh\tWarrior71\r\nHeavyBreathing\tWarrior72\r\nOh\tWarrior73\r\nWow\tWarrior74\r\nThankTheLight\tWarrior75\r\nWhatWasThat\tWarrior76\r\nMmHmm\tWarrior77\r\nHmm\tWarrior78\r\nUhHuh\tWarrior79\r\nTheSpiritsOfTheDeadAreNowAvenged\tWarrior80\r\nTheTownIsSafeFromTheseFoulSpawn\tWarrior81\r\nRestWellLeoricIllFindYourSon\tWarrior82\r\nYourMadnessEndsHereBetrayer\tWarrior83\r\nYoullLureNoMoreMenToTheirDeaths\tWarrior84\r\nReturnToHeavenWarriorOfLight\tWarrior85\r\nICanSeeWhyTheyFearThisWeapon\tWarrior86\r\nThisMustBeWhatGriswoldWanted\tWarrior87\r\nINeedToGetThisToLachdanan\tWarrior88\r\nINeedToGetThisToGriswold\tWarrior89\r\nIveNeverBeenHereBefore\tWarrior90\r\nMayTheSpiritOfArkaineProtectMe\tWarrior91\r\nThisIsAPlaceOfGreatPower\tWarrior92\r\nThisBladeMustBeDestroyed\tWarrior93\r\nYourReignOfPainHasEnded\tWarrior94\r\nNowThatsOneBigMushroom\tWarrior95\r\nTheSmellOfDeathSurroundsMe\tWarrior96b\r\nTheSanctityOfThisPlaceHasBeenFouled\tWarrior97\r\nItsHotDownHere\tWarrior98\r\nIMustBeGettingClose\tWarrior99\r\nMaybeItsLockedFromTheInside\tWarrior100\r\nLooksLikeItsRustedShut\tWarrior101\r\nMaybeTheresAnotherWay\tWarrior102\r\nAuughUh\tWarrior71\r\n"
  },
  {
    "path": "assets/txtdata/classes/barbarian/sprites.tsv",
    "content": "Variable\tValue\r\nclassPath\twarrior\r\nclassChar\tc\r\ntrn\tbarbarian\r\nstand\t96\r\nwalk\t96\r\nattack\t128\r\nbow\t96\r\nswHit\t96\r\nblock\t96\r\nlightning\t96\r\nfire\t96\r\nmagic\t96\r\ndeath\t128\r\n"
  },
  {
    "path": "assets/txtdata/classes/barbarian/starting_loadout.tsv",
    "content": "Variable\tValue\r\nskill\tRage\r\nspell\tNull\r\nspellLevel\t0\r\nitem0\tIDI_BARBARIAN\r\nitem1\tIDI_WARRSHLD\r\nitem2\tIDI_HEAL\r\nitem3\tIDI_HEAL\r\nitem4\tIDI_NONE\r\ngold\t100\r\n"
  },
  {
    "path": "assets/txtdata/classes/bard/animations.tsv",
    "content": "Variable\tValue\r\nunarmedFrames\t18\r\nunarmedActionFrame\t10\r\nunarmedShieldFrames\t18\r\nunarmedShieldActionFrame\t10\r\nswordFrames\t18\r\nswordActionFrame\t10\r\nswordShieldFrames\t18\r\nswordShieldActionFrame\t10\r\nbowFrames\t12\r\nbowActionFrame\t11\r\naxeFrames\t22\r\naxeActionFrame\t13\r\nmaceFrames\t18\r\nmaceActionFrame\t10\r\nmaceShieldFrames\t18\r\nmaceShieldActionFrame\t10\r\nstaffFrames\t16\r\nstaffActionFrame\t11\r\nidleFrames\t8\r\nwalkingFrames\t8\r\nblockingFrames\t4\r\ndeathFrames\t20\r\ncastingFrames\t16\r\nrecoveryFrames\t7\r\ntownIdleFrames\t20\r\ntownWalkingFrames\t8\r\ncastingActionFrame\t12\r\n"
  },
  {
    "path": "assets/txtdata/classes/bard/attributes.tsv",
    "content": "Attribute\tValue\r\nclassFlags\tDualWield\r\nbaseStr\t20\r\nbaseMag\t20\r\nbaseDex\t25\r\nbaseVit\t20\r\nmaxStr\t120\r\nmaxMag\t120\r\nmaxDex\t120\r\nmaxVit\t100\r\nblockBonus\t25\r\nadjLife\t23\r\nadjMana\t3\r\nlvlLife\t2\r\nlvlMana\t2\r\nchrLife\t1\r\nchrMana\t1.5\r\nitmLife\t1.5\r\nitmMana\t1.75\r\nbaseMagicToHit\t60\r\nbaseMeleeToHit\t50\r\nbaseRangedToHit\t60\r\n"
  },
  {
    "path": "assets/txtdata/classes/bard/sounds.tsv",
    "content": "speech\tsfx\r\nChamberOfBoneLore\tRogue1\r\nHorazonsSanctumLore\tRogue2\r\nGolemSpellLore\tRogue3\r\nHorazonsCreatureOfFlameLore\tRogue4\r\nMortaVespaGaieaInnuminoEvegeenJatanLuaGraton\tRogue5\r\nGrimspikeLieutenantOfBelialLore\tRogue6\r\nHorazonsJournal\tRogue7\r\nYourDeathWillBeAvenged\tRogue8\r\nRestInPeaceMyFriend\tRogue9\r\nValorLore\tRogue10\r\nHallsOfTheBlindLore\tRogue11\r\nWarlordOfBloodLore\tRogue12\r\nICantUseThisYet\tRogue13\r\nICantCarryAnymore\tRogue14\r\nIHaveNoRoom\tRogue15\r\nWhereWouldIPutThis\tRogue16\r\nNoWay\tRogue17\r\nNotAChance\tRogue18\r\nIdNeverUseThis\tRogue19\r\nIdHaveToEquipThat\tRogue20\r\nICantMoveThis\tRogue21\r\nICantMoveThisYet\tRogue22\r\nICantOpenThis\tRogue23\r\nICantOpenThisYet\tRogue24\r\nICantLiftThis\tRogue25\r\nICantLiftThisYet\tRogue26\r\nICantCastThatHere\tRogue27\r\nICantCastThatYet\tRogue28\r\nThatDidntDoAnything\tRogue29\r\nICanAlreadyDoThat\tRogue30\r\nIDontNeedThat\tRogue31\r\nIDontNeedToDoThat\tRogue32\r\nIDontWantThat\tRogue33\r\nIDontHaveASpellReady\tRogue34\r\nNotEnoughMana\tRogue35\r\nThatWouldKillMe\tRogue36\r\nICantDoThat\tRogue37\r\nNo\tRogue38\r\nYes\tRogue39\r\nThatWontWork\tRogue40\r\nThatWontWorkHere\tRogue41\r\nThatWontWorkYet\tRogue42\r\nICantGetThereFromHere\tRogue43\r\nItsTooHeavy\tRogue44\r\nItsTooBig\tRogue45\r\nJustWhatIWasLookingFor\tRogue46\r\nIveGotABadFeelingAboutThis\tRogue47\r\nGotMilk\tRogue48\r\nImNotThirsty\tRogue49\r\nImNoMilkmaid\tRogue50\r\nICouldBlowUpTheWholeVillage\tRogue51\r\nYepThatsACowAlright\tRogue52\r\nTooUghHeavy\tRogue53\r\nInSpirituSanctum\tRogue54\r\nPraedictumOtium\tRogue55\r\nEfficioObitusUtInimicus\tRogue56\r\nTheEnchantmentIsGone\tRogue57\r\nOhTooEasy\tRogue58\r\nBackToTheGrave\tRogue59\r\nTimeToDie\tRogue60\r\nImNotImpressed\tRogue61\r\nImSorryDidIBreakYourConcentration\tRogue62\r\nVengeanceIsMine\tRogue63\r\nDie\tRogue64\r\nYeah\tRogue65\r\nAh\tRogue66\r\nPhew\tRogue67\r\nArgh\tRogue68\r\nArghClang\tRogue69\r\nAaaaargh\tRogue70\r\nOofAh\tRogue71\r\nHeavyBreathing\tRogue72\r\nOh\tRogue73\r\nWow\tRogue74\r\nThankTheLight\tRogue75\r\nWhatWasThat\tRogue76\r\nMmHmm\tRogue77\r\nHmm\tRogue78\r\nUhHuh\tRogue79\r\nTheSpiritsOfTheDeadAreNowAvenged\tRogue80\r\nTheTownIsSafeFromTheseFoulSpawn\tRogue81\r\nRestWellLeoricIllFindYourSon\tRogue82\r\nYourMadnessEndsHereBetrayer\tRogue83\r\nYoullLureNoMoreMenToTheirDeaths\tRogue84\r\nReturnToHeavenWarriorOfLight\tRogue85\r\nICanSeeWhyTheyFearThisWeapon\tRogue86\r\nThisMustBeWhatGriswoldWanted\tRogue87\r\nINeedToGetThisToLachdanan\tRogue88\r\nINeedToGetThisToGriswold\tRogue89\r\nIveNeverBeenHereBefore\tRogue90\r\nMayTheSpiritOfArkaineProtectMe\tRogue91\r\nThisIsAPlaceOfGreatPower\tRogue92\r\nThisBladeMustBeDestroyed\tRogue93\r\nYourReignOfPainHasEnded\tRogue94\r\nNowThatsOneBigMushroom\tRogue95\r\nTheSmellOfDeathSurroundsMe\tRogue96\r\nTheSanctityOfThisPlaceHasBeenFouled\tRogue97\r\nItsHotDownHere\tRogue98\r\nIMustBeGettingClose\tRogue99\r\nMaybeItsLockedFromTheInside\tRogue100\r\nLooksLikeItsRustedShut\tRogue101\r\nMaybeTheresAnotherWay\tRogue102\r\nAuughUh\tRogue71\r\n"
  },
  {
    "path": "assets/txtdata/classes/bard/sprites.tsv",
    "content": "Variable\tValue\r\nclassPath\trogue\r\nclassChar\tb\r\ntrn\tbard\r\nstand\t96\r\nwalk\t96\r\nattack\t128\r\nbow\t128\r\nswHit\t96\r\nblock\t96\r\nlightning\t96\r\nfire\t96\r\nmagic\t96\r\ndeath\t128\r\n"
  },
  {
    "path": "assets/txtdata/classes/bard/starting_loadout.tsv",
    "content": "Variable\tValue\r\nskill\tIdentify\r\nspell\tNull\r\nspellLevel\t0\r\nitem0\tIDI_BARDSWORD\r\nitem1\tIDI_BARDDAGGER\r\nitem2\tIDI_HEAL\r\nitem3\tIDI_HEAL\r\nitem4\tIDI_NONE\r\ngold\t100\r\n"
  },
  {
    "path": "assets/txtdata/classes/classdat.tsv",
    "content": "className\tfolderName\tportrait\tinv\r\nWarrior\twarrior\t0\tinv\r\nRogue\trogue\t1\tinv_rog\r\nSorcerer\tsorcerer\t2\tinv_sor\r\nMonk\tmonk\t2\tinv_sor\r\nBard\tbard\t1\tinv_rog\r\nBarbarian\tbarbarian\t0\tinv\r\n"
  },
  {
    "path": "assets/txtdata/classes/monk/animations.tsv",
    "content": "Variable\tValue\r\nunarmedFrames\t12\r\nunarmedActionFrame\t7\r\nunarmedShieldFrames\t12\r\nunarmedShieldActionFrame\t7\r\nswordFrames\t16\r\nswordActionFrame\t12\r\nswordShieldFrames\t16\r\nswordShieldActionFrame\t12\r\nbowFrames\t20\r\nbowActionFrame\t14\r\naxeFrames\t23\r\naxeActionFrame\t14\r\nmaceFrames\t16\r\nmaceActionFrame\t12\r\nmaceShieldFrames\t16\r\nmaceShieldActionFrame\t12\r\nstaffFrames\t13\r\nstaffActionFrame\t8\r\nidleFrames\t8\r\nwalkingFrames\t8\r\nblockingFrames\t3\r\ndeathFrames\t20\r\ncastingFrames\t18\r\nrecoveryFrames\t6\r\ntownIdleFrames\t20\r\ntownWalkingFrames\t8\r\ncastingActionFrame\t13\r\n"
  },
  {
    "path": "assets/txtdata/classes/monk/attributes.tsv",
    "content": "Attribute\tValue\r\nclassFlags\t\r\nbaseStr\t25\r\nbaseMag\t15\r\nbaseDex\t25\r\nbaseVit\t20\r\nmaxStr\t150\r\nmaxMag\t80\r\nmaxDex\t150\r\nmaxVit\t80\r\nblockBonus\t25\r\nadjLife\t23\r\nadjMana\t5.5\r\nlvlLife\t2\r\nlvlMana\t2\r\nchrLife\t1\r\nchrMana\t1\r\nitmLife\t1.5\r\nitmMana\t1.5\r\nbaseMagicToHit\t50\r\nbaseMeleeToHit\t50\r\nbaseRangedToHit\t50\r\n"
  },
  {
    "path": "assets/txtdata/classes/monk/sounds.tsv",
    "content": "speech\tsfx\r\nChamberOfBoneLore\tMonk1\r\nHorazonsSanctumLore\tNone\r\nGolemSpellLore\tNone\r\nHorazonsCreatureOfFlameLore\tNone\r\nMortaVespaGaieaInnuminoEvegeenJatanLuaGraton\tNone\r\nGrimspikeLieutenantOfBelialLore\tNone\r\nHorazonsJournal\tNone\r\nYourDeathWillBeAvenged\tMonk8\r\nRestInPeaceMyFriend\tMonk9\r\nValorLore\tMonk10\r\nHallsOfTheBlindLore\tMonk11\r\nWarlordOfBloodLore\tMonk12\r\nICantUseThisYet\tMonk13\r\nICantCarryAnymore\tMonk14\r\nIHaveNoRoom\tMonk15\r\nWhereWouldIPutThis\tMonk16\r\nNoWay\tNone\r\nNotAChance\tNone\r\nIdNeverUseThis\tNone\r\nIdHaveToEquipThat\tNone\r\nICantMoveThis\tNone\r\nICantMoveThisYet\tNone\r\nICantOpenThis\tNone\r\nICantOpenThisYet\tMonk24\r\nICantLiftThis\tNone\r\nICantLiftThisYet\tNone\r\nICantCastThatHere\tMonk27\r\nICantCastThatYet\tNone\r\nThatDidntDoAnything\tMonk29\r\nICanAlreadyDoThat\tNone\r\nIDontNeedThat\tNone\r\nIDontNeedToDoThat\tNone\r\nIDontWantThat\tNone\r\nIDontHaveASpellReady\tMonk34\r\nNotEnoughMana\tMonk35\r\nThatWouldKillMe\tNone\r\nICantDoThat\tNone\r\nNo\tNone\r\nYes\tNone\r\nThatWontWork\tNone\r\nThatWontWorkHere\tNone\r\nThatWontWorkYet\tNone\r\nICantGetThereFromHere\tMonk43\r\nItsTooHeavy\tNone\r\nItsTooBig\tNone\r\nJustWhatIWasLookingFor\tMonk46\r\nIveGotABadFeelingAboutThis\tNone\r\nGotMilk\tNone\r\nImNotThirsty\tMonk49\r\nImNoMilkmaid\tMonk50\r\nICouldBlowUpTheWholeVillage\tNone\r\nYepThatsACowAlright\tMonk52\r\nTooUghHeavy\tNone\r\nInSpirituSanctum\tMonk54\r\nPraedictumOtium\tMonk55\r\nEfficioObitusUtInimicus\tMonk56\r\nTheEnchantmentIsGone\tNone\r\nOhTooEasy\tNone\r\nBackToTheGrave\tNone\r\nTimeToDie\tNone\r\nImNotImpressed\tMonk61\r\nImSorryDidIBreakYourConcentration\tMonk62\r\nVengeanceIsMine\tNone\r\nDie\tNone\r\nYeah\tNone\r\nAh\tNone\r\nPhew\tNone\r\nArgh\tMonk68\r\nArghClang\tMonk69\r\nAaaaargh\tMonk70\r\nOofAh\tMonk71\r\nHeavyBreathing\tNone\r\nOh\tNone\r\nWow\tNone\r\nThankTheLight\tNone\r\nWhatWasThat\tNone\r\nMmHmm\tNone\r\nHmm\tNone\r\nUhHuh\tMonk79\r\nTheSpiritsOfTheDeadAreNowAvenged\tMonk80\r\nTheTownIsSafeFromTheseFoulSpawn\tNone\r\nRestWellLeoricIllFindYourSon\tMonk82\r\nYourMadnessEndsHereBetrayer\tMonk83\r\nYoullLureNoMoreMenToTheirDeaths\tNone\r\nReturnToHeavenWarriorOfLight\tNone\r\nICanSeeWhyTheyFearThisWeapon\tNone\r\nThisMustBeWhatGriswoldWanted\tMonk87\r\nINeedToGetThisToLachdanan\tMonk88\r\nINeedToGetThisToGriswold\tMonk89\r\nIveNeverBeenHereBefore\tNone\r\nMayTheSpiritOfArkaineProtectMe\tMonk91\r\nThisIsAPlaceOfGreatPower\tMonk92\r\nThisBladeMustBeDestroyed\tNone\r\nYourReignOfPainHasEnded\tMonk94\r\nNowThatsOneBigMushroom\tMonk95\r\nTheSmellOfDeathSurroundsMe\tMonk96\r\nTheSanctityOfThisPlaceHasBeenFouled\tMonk97\r\nItsHotDownHere\tMonk98\r\nIMustBeGettingClose\tMonk99\r\nMaybeItsLockedFromTheInside\tNone\r\nLooksLikeItsRustedShut\tNone\r\nMaybeTheresAnotherWay\tNone\r\nAuughUh\tMonk71\r\n"
  },
  {
    "path": "assets/txtdata/classes/monk/sprites.tsv",
    "content": "Variable\tValue\r\nclassPath\tmonk\r\nclassChar\tm\r\ntrn\tmonk\r\nstand\t112\r\nwalk\t112\r\nattack\t130\r\nbow\t130\r\nswHit\t98\r\nblock\t98\r\nlightning\t114\r\nfire\t114\r\nmagic\t114\r\ndeath\t160\r\n"
  },
  {
    "path": "assets/txtdata/classes/monk/starting_loadout.tsv",
    "content": "Variable\tValue\r\nskill\tSearch\r\nspell\tNull\r\nspellLevel\t0\r\nitem0\tIDI_SHORTSTAFF\r\nitem1\tIDI_HEAL\r\nitem2\tIDI_HEAL\r\nitem3\tIDI_NONE\r\nitem4\tIDI_NONE\r\ngold\t100\r\n"
  },
  {
    "path": "assets/txtdata/classes/rogue/animations.tsv",
    "content": "Variable\tValue\r\nunarmedFrames\t18\r\nunarmedActionFrame\t10\r\nunarmedShieldFrames\t18\r\nunarmedShieldActionFrame\t10\r\nswordFrames\t18\r\nswordActionFrame\t10\r\nswordShieldFrames\t18\r\nswordShieldActionFrame\t10\r\nbowFrames\t12\r\nbowActionFrame\t7\r\naxeFrames\t22\r\naxeActionFrame\t13\r\nmaceFrames\t18\r\nmaceActionFrame\t10\r\nmaceShieldFrames\t18\r\nmaceShieldActionFrame\t10\r\nstaffFrames\t16\r\nstaffActionFrame\t11\r\nidleFrames\t8\r\nwalkingFrames\t8\r\nblockingFrames\t4\r\ndeathFrames\t20\r\ncastingFrames\t16\r\nrecoveryFrames\t7\r\ntownIdleFrames\t20\r\ntownWalkingFrames\t8\r\ncastingActionFrame\t12\r\n"
  },
  {
    "path": "assets/txtdata/classes/rogue/attributes.tsv",
    "content": "Attribute\tValue\r\nclassFlags\tTrapSense\r\nbaseStr\t20\r\nbaseMag\t15\r\nbaseDex\t30\r\nbaseVit\t20\r\nmaxStr\t55\r\nmaxMag\t70\r\nmaxDex\t250\r\nmaxVit\t80\r\nblockBonus\t20\r\nadjLife\t23\r\nadjMana\t5.5\r\nlvlLife\t2\r\nlvlMana\t2\r\nchrLife\t1\r\nchrMana\t1\r\nitmLife\t1.5\r\nitmMana\t1.5\r\nbaseMagicToHit\t50\r\nbaseMeleeToHit\t50\r\nbaseRangedToHit\t70\r\n"
  },
  {
    "path": "assets/txtdata/classes/rogue/sounds.tsv",
    "content": "speech\tsfx\r\nChamberOfBoneLore\tRogue1\r\nHorazonsSanctumLore\tRogue2\r\nGolemSpellLore\tRogue3\r\nHorazonsCreatureOfFlameLore\tRogue4\r\nMortaVespaGaieaInnuminoEvegeenJatanLuaGraton\tRogue5\r\nGrimspikeLieutenantOfBelialLore\tRogue6\r\nHorazonsJournal\tRogue7\r\nYourDeathWillBeAvenged\tRogue8\r\nRestInPeaceMyFriend\tRogue9\r\nValorLore\tRogue10\r\nHallsOfTheBlindLore\tRogue11\r\nWarlordOfBloodLore\tRogue12\r\nICantUseThisYet\tRogue13\r\nICantCarryAnymore\tRogue14\r\nIHaveNoRoom\tRogue15\r\nWhereWouldIPutThis\tRogue16\r\nNoWay\tRogue17\r\nNotAChance\tRogue18\r\nIdNeverUseThis\tRogue19\r\nIdHaveToEquipThat\tRogue20\r\nICantMoveThis\tRogue21\r\nICantMoveThisYet\tRogue22\r\nICantOpenThis\tRogue23\r\nICantOpenThisYet\tRogue24\r\nICantLiftThis\tRogue25\r\nICantLiftThisYet\tRogue26\r\nICantCastThatHere\tRogue27\r\nICantCastThatYet\tRogue28\r\nThatDidntDoAnything\tRogue29\r\nICanAlreadyDoThat\tRogue30\r\nIDontNeedThat\tRogue31\r\nIDontNeedToDoThat\tRogue32\r\nIDontWantThat\tRogue33\r\nIDontHaveASpellReady\tRogue34\r\nNotEnoughMana\tRogue35\r\nThatWouldKillMe\tRogue36\r\nICantDoThat\tRogue37\r\nNo\tRogue38\r\nYes\tRogue39\r\nThatWontWork\tRogue40\r\nThatWontWorkHere\tRogue41\r\nThatWontWorkYet\tRogue42\r\nICantGetThereFromHere\tRogue43\r\nItsTooHeavy\tRogue44\r\nItsTooBig\tRogue45\r\nJustWhatIWasLookingFor\tRogue46\r\nIveGotABadFeelingAboutThis\tRogue47\r\nGotMilk\tRogue48\r\nImNotThirsty\tRogue49\r\nImNoMilkmaid\tRogue50\r\nICouldBlowUpTheWholeVillage\tRogue51\r\nYepThatsACowAlright\tRogue52\r\nTooUghHeavy\tRogue53\r\nInSpirituSanctum\tRogue54\r\nPraedictumOtium\tRogue55\r\nEfficioObitusUtInimicus\tRogue56\r\nTheEnchantmentIsGone\tRogue57\r\nOhTooEasy\tRogue58\r\nBackToTheGrave\tRogue59\r\nTimeToDie\tRogue60\r\nImNotImpressed\tRogue61\r\nImSorryDidIBreakYourConcentration\tRogue62\r\nVengeanceIsMine\tRogue63\r\nDie\tRogue64\r\nYeah\tRogue65\r\nAh\tRogue66\r\nPhew\tRogue67\r\nArgh\tRogue68\r\nArghClang\tRogue69\r\nAaaaargh\tRogue70\r\nOofAh\tRogue71\r\nHeavyBreathing\tRogue72\r\nOh\tRogue73\r\nWow\tRogue74\r\nThankTheLight\tRogue75\r\nWhatWasThat\tRogue76\r\nMmHmm\tRogue77\r\nHmm\tRogue78\r\nUhHuh\tRogue79\r\nTheSpiritsOfTheDeadAreNowAvenged\tRogue80\r\nTheTownIsSafeFromTheseFoulSpawn\tRogue81\r\nRestWellLeoricIllFindYourSon\tRogue82\r\nYourMadnessEndsHereBetrayer\tRogue83\r\nYoullLureNoMoreMenToTheirDeaths\tRogue84\r\nReturnToHeavenWarriorOfLight\tRogue85\r\nICanSeeWhyTheyFearThisWeapon\tRogue86\r\nThisMustBeWhatGriswoldWanted\tRogue87\r\nINeedToGetThisToLachdanan\tRogue88\r\nINeedToGetThisToGriswold\tRogue89\r\nIveNeverBeenHereBefore\tRogue90\r\nMayTheSpiritOfArkaineProtectMe\tRogue91\r\nThisIsAPlaceOfGreatPower\tRogue92\r\nThisBladeMustBeDestroyed\tRogue93\r\nYourReignOfPainHasEnded\tRogue94\r\nNowThatsOneBigMushroom\tRogue95\r\nTheSmellOfDeathSurroundsMe\tRogue96\r\nTheSanctityOfThisPlaceHasBeenFouled\tRogue97\r\nItsHotDownHere\tRogue98\r\nIMustBeGettingClose\tRogue99\r\nMaybeItsLockedFromTheInside\tRogue100\r\nLooksLikeItsRustedShut\tRogue101\r\nMaybeTheresAnotherWay\tRogue102\r\nAuughUh\tRogue71\r\n"
  },
  {
    "path": "assets/txtdata/classes/rogue/sprites.tsv",
    "content": "Variable\tValue\r\nclassPath\trogue\r\nclassChar\tr\r\ntrn\trogue\r\nstand\t96\r\nwalk\t96\r\nattack\t128\r\nbow\t128\r\nswHit\t96\r\nblock\t96\r\nlightning\t96\r\nfire\t96\r\nmagic\t96\r\ndeath\t128\r\n"
  },
  {
    "path": "assets/txtdata/classes/rogue/starting_loadout.tsv",
    "content": "Variable\tValue\r\nskill\tTrapDisarm\r\nspell\tNull\r\nspellLevel\t0\r\nitem0\tIDI_ROGUE\r\nitem1\tIDI_HEAL\r\nitem2\tIDI_HEAL\r\nitem3\tIDI_NONE\r\nitem4\tIDI_NONE\r\ngold\t100\r\n"
  },
  {
    "path": "assets/txtdata/classes/sorcerer/animations.tsv",
    "content": "Variable\tValue\r\nunarmedFrames\t20\r\nunarmedActionFrame\t12\r\nunarmedShieldFrames\t16\r\nunarmedShieldActionFrame\t9\r\nswordFrames\t16\r\nswordActionFrame\t12\r\nswordShieldFrames\t16\r\nswordShieldActionFrame\t12\r\nbowFrames\t20\r\nbowActionFrame\t16\r\naxeFrames\t24\r\naxeActionFrame\t16\r\nmaceFrames\t16\r\nmaceActionFrame\t12\r\nmaceShieldFrames\t16\r\nmaceShieldActionFrame\t12\r\nstaffFrames\t16\r\nstaffActionFrame\t12\r\nidleFrames\t8\r\nwalkingFrames\t8\r\nblockingFrames\t6\r\ndeathFrames\t20\r\ncastingFrames\t12\r\nrecoveryFrames\t8\r\ntownIdleFrames\t20\r\ntownWalkingFrames\t8\r\ncastingActionFrame\t8\r\n"
  },
  {
    "path": "assets/txtdata/classes/sorcerer/attributes.tsv",
    "content": "Attribute\tValue\r\nclassFlags\t\r\nbaseStr\t15\r\nbaseMag\t35\r\nbaseDex\t15\r\nbaseVit\t20\r\nmaxStr\t45\r\nmaxMag\t250\r\nmaxDex\t85\r\nmaxVit\t80\r\nblockBonus\t10\r\nadjLife\t9\r\nadjMana\t-2\r\nlvlLife\t1\r\nlvlMana\t2\r\nchrLife\t1\r\nchrMana\t2\r\nitmLife\t1\r\nitmMana\t2\r\nbaseMagicToHit\t70\r\nbaseMeleeToHit\t50\r\nbaseRangedToHit\t50\r\n"
  },
  {
    "path": "assets/txtdata/classes/sorcerer/sounds.tsv",
    "content": "speech\tsfx\r\nChamberOfBoneLore\tSorceror1\r\nHorazonsSanctumLore\tSorceror2\r\nGolemSpellLore\tSorceror3\r\nHorazonsCreatureOfFlameLore\tSorceror4\r\nMortaVespaGaieaInnuminoEvegeenJatanLuaGraton\tSorceror5\r\nGrimspikeLieutenantOfBelialLore\tSorceror6\r\nHorazonsJournal\tSorceror7\r\nYourDeathWillBeAvenged\tSorceror8\r\nRestInPeaceMyFriend\tSorceror9\r\nValorLore\tSorceror10\r\nHallsOfTheBlindLore\tSorceror11\r\nWarlordOfBloodLore\tSorceror12\r\nICantUseThisYet\tSorceror13\r\nICantCarryAnymore\tSorceror14\r\nIHaveNoRoom\tSorceror15\r\nWhereWouldIPutThis\tSorceror16\r\nNoWay\tSorceror17\r\nNotAChance\tSorceror18\r\nIdNeverUseThis\tSorceror19\r\nIdHaveToEquipThat\tSorceror20\r\nICantMoveThis\tSorceror21\r\nICantMoveThisYet\tSorceror22\r\nICantOpenThis\tSorceror23\r\nICantOpenThisYet\tSorceror24\r\nICantLiftThis\tSorceror25\r\nICantLiftThisYet\tSorceror26\r\nICantCastThatHere\tSorceror27\r\nICantCastThatYet\tSorceror28\r\nThatDidntDoAnything\tSorceror29\r\nICanAlreadyDoThat\tSorceror30\r\nIDontNeedThat\tSorceror31\r\nIDontNeedToDoThat\tSorceror32\r\nIDontWantThat\tSorceror33\r\nIDontHaveASpellReady\tSorceror34\r\nNotEnoughMana\tSorceror35\r\nThatWouldKillMe\tSorceror36\r\nICantDoThat\tSorceror37\r\nNo\tSorceror38\r\nYes\tSorceror39\r\nThatWontWork\tSorceror40\r\nThatWontWorkHere\tSorceror41\r\nThatWontWorkYet\tSorceror42\r\nICantGetThereFromHere\tSorceror43\r\nItsTooHeavy\tSorceror44\r\nItsTooBig\tSorceror45\r\nJustWhatIWasLookingFor\tSorceror46\r\nIveGotABadFeelingAboutThis\tSorceror47\r\nGotMilk\tSorceror48\r\nImNotThirsty\tSorceror49\r\nImNoMilkmaid\tSorceror50\r\nICouldBlowUpTheWholeVillage\tSorceror51\r\nYepThatsACowAlright\tSorceror52\r\nTooUghHeavy\tSorceror53\r\nInSpirituSanctum\tSorceror54\r\nPraedictumOtium\tSorceror55\r\nEfficioObitusUtInimicus\tSorceror56\r\nTheEnchantmentIsGone\tSorceror57\r\nOhTooEasy\tSorceror58\r\nBackToTheGrave\tSorceror59\r\nTimeToDie\tSorceror60\r\nImNotImpressed\tSorceror61\r\nImSorryDidIBreakYourConcentration\tSorceror62\r\nVengeanceIsMine\tSorceror63\r\nDie\tSorceror64\r\nYeah\tSorceror65\r\nAh\tSorceror66\r\nPhew\tSorceror67\r\nArgh\tSorceror68\r\nArghClang\tSorceror69\r\nAaaaargh\tSorceror70\r\nOofAh\tSorceror71\r\nHeavyBreathing\tSorceror72\r\nOh\tSorceror73\r\nWow\tSorceror74\r\nThankTheLight\tSorceror75\r\nWhatWasThat\tSorceror76\r\nMmHmm\tSorceror77\r\nHmm\tSorceror78\r\nUhHuh\tSorceror79\r\nTheSpiritsOfTheDeadAreNowAvenged\tSorceror80\r\nTheTownIsSafeFromTheseFoulSpawn\tSorceror81\r\nRestWellLeoricIllFindYourSon\tSorceror82\r\nYourMadnessEndsHereBetrayer\tSorceror83\r\nYoullLureNoMoreMenToTheirDeaths\tSorceror84\r\nReturnToHeavenWarriorOfLight\tSorceror85\r\nICanSeeWhyTheyFearThisWeapon\tSorceror86\r\nThisMustBeWhatGriswoldWanted\tSorceror87\r\nINeedToGetThisToLachdanan\tSorceror88\r\nINeedToGetThisToGriswold\tSorceror89\r\nIveNeverBeenHereBefore\tSorceror90\r\nMayTheSpiritOfArkaineProtectMe\tSorceror91\r\nThisIsAPlaceOfGreatPower\tSorceror92\r\nThisBladeMustBeDestroyed\tSorceror93\r\nYourReignOfPainHasEnded\tSorceror94\r\nNowThatsOneBigMushroom\tSorceror95\r\nTheSmellOfDeathSurroundsMe\tSorceror96\r\nTheSanctityOfThisPlaceHasBeenFouled\tSorceror97\r\nItsHotDownHere\tSorceror98\r\nIMustBeGettingClose\tSorceror99\r\nMaybeItsLockedFromTheInside\tSorceror100\r\nLooksLikeItsRustedShut\tSorceror101\r\nMaybeTheresAnotherWay\tSorceror102\r\nAuughUh\tSorceror71\r\n"
  },
  {
    "path": "assets/txtdata/classes/sorcerer/sprites.tsv",
    "content": "Variable\tValue\r\nclassPath\tsorceror\r\nclassChar\ts\r\ntrn\tsorcerer\r\nstand\t96\r\nwalk\t96\r\nattack\t128\r\nbow\t128\r\nswHit\t96\r\nblock\t96\r\nlightning\t128\r\nfire\t128\r\nmagic\t128\r\ndeath\t128\r\n"
  },
  {
    "path": "assets/txtdata/classes/sorcerer/starting_loadout.tsv",
    "content": "Variable\tValue\r\nskill\tStaffRecharge\r\nspell\tFirebolt\r\nspellLevel\t2\r\nitem0\tIDI_SORCERER_DIABLO\r\nitem1\tIDI_MANA\r\nitem2\tIDI_MANA\r\nitem3\tIDI_NONE\r\nitem4\tIDI_NONE\r\ngold\t100\r\n"
  },
  {
    "path": "assets/txtdata/classes/warrior/animations.tsv",
    "content": "Variable\tValue\r\nunarmedFrames\t16\r\nunarmedActionFrame\t9\r\nunarmedShieldFrames\t16\r\nunarmedShieldActionFrame\t9\r\nswordFrames\t16\r\nswordActionFrame\t9\r\nswordShieldFrames\t16\r\nswordShieldActionFrame\t9\r\nbowFrames\t16\r\nbowActionFrame\t11\r\naxeFrames\t20\r\naxeActionFrame\t10\r\nmaceFrames\t16\r\nmaceActionFrame\t9\r\nmaceShieldFrames\t16\r\nmaceShieldActionFrame\t9\r\nstaffFrames\t16\r\nstaffActionFrame\t11\r\nidleFrames\t10\r\nwalkingFrames\t8\r\nblockingFrames\t2\r\ndeathFrames\t20\r\ncastingFrames\t20\r\nrecoveryFrames\t6\r\ntownIdleFrames\t20\r\ntownWalkingFrames\t8\r\ncastingActionFrame\t14\r\n"
  },
  {
    "path": "assets/txtdata/classes/warrior/attributes.tsv",
    "content": "Attribute\tValue\r\nclassFlags\tCriticalStrike\r\nbaseStr\t30\r\nbaseMag\t10\r\nbaseDex\t20\r\nbaseVit\t25\r\nmaxStr\t250\r\nmaxMag\t50\r\nmaxDex\t60\r\nmaxVit\t100\r\nblockBonus\t30\r\nadjLife\t18\r\nadjMana\t-1\r\nlvlLife\t2\r\nlvlMana\t1\r\nchrLife\t2\r\nchrMana\t1\r\nitmLife\t2\r\nitmMana\t1\r\nbaseMagicToHit\t50\r\nbaseMeleeToHit\t70\r\nbaseRangedToHit\t60\r\n"
  },
  {
    "path": "assets/txtdata/classes/warrior/sounds.tsv",
    "content": "speech\tsfx\r\nChamberOfBoneLore\tWarrior1\r\nHorazonsSanctumLore\tWarrior2\r\nGolemSpellLore\tWarrior3\r\nHorazonsCreatureOfFlameLore\tWarrior4\r\nMortaVespaGaieaInnuminoEvegeenJatanLuaGraton\tWarrior5\r\nGrimspikeLieutenantOfBelialLore\tWarrior6\r\nHorazonsJournal\tWarrior7\r\nYourDeathWillBeAvenged\tWarrior8\r\nRestInPeaceMyFriend\tWarrior9\r\nValorLore\tWarrior10\r\nHallsOfTheBlindLore\tWarrior11\r\nWarlordOfBloodLore\tWarrior12\r\nICantUseThisYet\tWarrior13\r\nICantCarryAnymore\tWarrior14\r\nIHaveNoRoom\tWarrior15\r\nWhereWouldIPutThis\tWarrior16\r\nNoWay\tWarrior17\r\nNotAChance\tWarrior18\r\nIdNeverUseThis\tWarrior19\r\nIdHaveToEquipThat\tWarrior20\r\nICantMoveThis\tWarrior21\r\nICantMoveThisYet\tWarrior22\r\nICantOpenThis\tWarrior23\r\nICantOpenThisYet\tWarrior24\r\nICantLiftThis\tWarrior25\r\nICantLiftThisYet\tWarrior26\r\nICantCastThatHere\tWarrior27\r\nICantCastThatYet\tWarrior28\r\nThatDidntDoAnything\tWarrior29\r\nICanAlreadyDoThat\tWarrior30\r\nIDontNeedThat\tWarrior31\r\nIDontNeedToDoThat\tWarrior32\r\nIDontWantThat\tWarrior33\r\nIDontHaveASpellReady\tWarrior34\r\nNotEnoughMana\tWarrior35\r\nThatWouldKillMe\tWarrior36\r\nICantDoThat\tWarrior37\r\nNo\tWarrior38\r\nYes\tWarrior39\r\nThatWontWork\tWarrior40\r\nThatWontWorkHere\tWarrior41\r\nThatWontWorkYet\tWarrior42\r\nICantGetThereFromHere\tWarrior43\r\nItsTooHeavy\tWarrior44\r\nItsTooBig\tWarrior45\r\nJustWhatIWasLookingFor\tWarrior46\r\nIveGotABadFeelingAboutThis\tWarrior47\r\nGotMilk\tWarrior48\r\nImNotThirsty\tWarrior49\r\nImNoMilkmaid\tWarrior50\r\nICouldBlowUpTheWholeVillage\tWarrior51\r\nYepThatsACowAlright\tWarrior52\r\nTooUghHeavy\tWarrior53\r\nInSpirituSanctum\tWarrior54\r\nPraedictumOtium\tWarrior55\r\nEfficioObitusUtInimicus\tWarrior56\r\nTheEnchantmentIsGone\tWarrior57\r\nOhTooEasy\tWarrior58\r\nBackToTheGrave\tWarrior59\r\nTimeToDie\tWarrior60\r\nImNotImpressed\tWarrior61\r\nImSorryDidIBreakYourConcentration\tWarrior62\r\nVengeanceIsMine\tWarrior63\r\nDie\tWarrior64\r\nYeah\tWarrior65\r\nAh\tWarrior66\r\nPhew\tWarrior67\r\nArgh\tWarrior68\r\nArghClang\tWarrior69\r\nAaaaargh\tWarrior70\r\nOofAh\tWarrior71\r\nHeavyBreathing\tWarrior72\r\nOh\tWarrior73\r\nWow\tWarrior74\r\nThankTheLight\tWarrior75\r\nWhatWasThat\tWarrior76\r\nMmHmm\tWarrior77\r\nHmm\tWarrior78\r\nUhHuh\tWarrior79\r\nTheSpiritsOfTheDeadAreNowAvenged\tWarrior80\r\nTheTownIsSafeFromTheseFoulSpawn\tWarrior81\r\nRestWellLeoricIllFindYourSon\tWarrior82\r\nYourMadnessEndsHereBetrayer\tWarrior83\r\nYoullLureNoMoreMenToTheirDeaths\tWarrior84\r\nReturnToHeavenWarriorOfLight\tWarrior85\r\nICanSeeWhyTheyFearThisWeapon\tWarrior86\r\nThisMustBeWhatGriswoldWanted\tWarrior87\r\nINeedToGetThisToLachdanan\tWarrior88\r\nINeedToGetThisToGriswold\tWarrior89\r\nIveNeverBeenHereBefore\tWarrior90\r\nMayTheSpiritOfArkaineProtectMe\tWarrior91\r\nThisIsAPlaceOfGreatPower\tWarrior92\r\nThisBladeMustBeDestroyed\tWarrior93\r\nYourReignOfPainHasEnded\tWarrior94\r\nNowThatsOneBigMushroom\tWarrior95\r\nTheSmellOfDeathSurroundsMe\tWarrior96b\r\nTheSanctityOfThisPlaceHasBeenFouled\tWarrior97\r\nItsHotDownHere\tWarrior98\r\nIMustBeGettingClose\tWarrior99\r\nMaybeItsLockedFromTheInside\tWarrior100\r\nLooksLikeItsRustedShut\tWarrior101\r\nMaybeTheresAnotherWay\tWarrior102\r\nAuughUh\tWarriorDeath\r\n"
  },
  {
    "path": "assets/txtdata/classes/warrior/sprites.tsv",
    "content": "Variable\tValue\r\nclassPath\twarrior\r\nclassChar\tw\r\ntrn\twarrior\r\nstand\t96\r\nwalk\t96\r\nattack\t128\r\nbow\t96\r\nswHit\t96\r\nblock\t96\r\nlightning\t96\r\nfire\t96\r\nmagic\t96\r\ndeath\t128\r\n"
  },
  {
    "path": "assets/txtdata/classes/warrior/starting_loadout.tsv",
    "content": "Variable\tValue\r\nskill\tItemRepair\r\nspell\tNull\r\nspellLevel\t0\r\nitem0\tIDI_WARRIOR\r\nitem1\tIDI_WARRSHLD\r\nitem2\tIDI_WARRCLUB\r\nitem3\tIDI_HEAL\r\nitem4\tIDI_HEAL\r\ngold\t100\r\n"
  },
  {
    "path": "assets/txtdata/items/item_prefixes.tsv",
    "content": "name\tpower\tpower.value1\tpower.value2\tminLevel\titemTypes\talignment\tchance\tuseful\tminVal\tmaxVal\tmultVal\r\nTin\tTOHIT_CURSE\t6\t10\t3\tWeapon,Bow,Misc\tAny\t2\tfalse\t0\t0\t-3\r\nBrass\tTOHIT_CURSE\t1\t5\t1\tWeapon,Bow,Misc\tAny\t2\tfalse\t0\t0\t-2\r\nBronze\tTOHIT\t1\t5\t1\tWeapon,Bow,Misc\tAny\t2\ttrue\t100\t500\t2\r\nIron\tTOHIT\t6\t10\t4\tWeapon,Bow,Misc\tAny\t2\ttrue\t600\t1000\t3\r\nSteel\tTOHIT\t11\t15\t6\tWeapon,Bow,Misc\tAny\t2\ttrue\t1100\t1500\t5\r\nSilver\tTOHIT\t16\t20\t9\tWeapon,Bow,Misc\tGood\t2\ttrue\t1600\t2000\t7\r\nGold\tTOHIT\t21\t30\t12\tWeapon,Bow,Misc\tGood\t2\ttrue\t2100\t3000\t9\r\nPlatinum\tTOHIT\t31\t40\t16\tWeapon,Bow\tGood\t2\ttrue\t3100\t4000\t11\r\nMithril\tTOHIT\t41\t60\t20\tWeapon,Bow\tGood\t2\ttrue\t4100\t6000\t13\r\nMeteoric\tTOHIT\t61\t80\t23\tWeapon,Bow\tAny\t2\ttrue\t6100\t10000\t15\r\nWeird\tTOHIT\t81\t100\t35\tWeapon,Bow\tAny\t2\ttrue\t10100\t14000\t17\r\nStrange\tTOHIT\t101\t150\t60\tWeapon,Bow\tAny\t2\ttrue\t14100\t20000\t20\r\nUseless\tDAMP_CURSE\t100\t100\t5\tWeapon,Bow\tAny\t2\tfalse\t0\t0\t-8\r\nBent\tDAMP_CURSE\t50\t75\t3\tWeapon,Bow\tAny\t2\tfalse\t0\t0\t-4\r\nWeak\tDAMP_CURSE\t25\t45\t1\tWeapon,Bow\tAny\t2\tfalse\t0\t0\t-3\r\nJagged\tDAMP\t20\t35\t4\tWeapon,Bow\tAny\t2\ttrue\t250\t450\t3\r\nDeadly\tDAMP\t36\t50\t6\tWeapon,Bow\tAny\t2\ttrue\t500\t700\t4\r\nHeavy\tDAMP\t51\t65\t9\tWeapon,Bow\tAny\t2\ttrue\t750\t950\t5\r\nVicious\tDAMP\t66\t80\t12\tWeapon,Bow\tEvil\t2\ttrue\t1000\t1450\t8\r\nBrutal\tDAMP\t81\t95\t16\tWeapon,Bow\tAny\t2\ttrue\t1500\t1950\t10\r\nMassive\tDAMP\t96\t110\t20\tWeapon,Bow\tAny\t2\ttrue\t2000\t2450\t13\r\nSavage\tDAMP\t111\t125\t23\tWeapon,Bow\tAny\t2\ttrue\t2500\t3000\t15\r\nRuthless\tDAMP\t126\t150\t35\tWeapon,Bow\tAny\t2\ttrue\t10100\t15000\t17\r\nMerciless\tDAMP\t151\t175\t60\tWeapon,Bow\tAny\t2\ttrue\t15000\t20000\t20\r\nClumsy\tTOHIT_DAMP_CURSE\t50\t75\t5\tWeapon,Staff,Bow\tAny\t2\tfalse\t0\t0\t-7\r\nDull\tTOHIT_DAMP_CURSE\t25\t45\t1\tWeapon,Staff,Bow\tAny\t2\tfalse\t0\t0\t-5\r\nSharp\tTOHIT_DAMP\t20\t35\t1\tWeapon,Staff,Bow\tAny\t2\tfalse\t350\t950\t5\r\nFine\tTOHIT_DAMP\t36\t50\t6\tWeapon,Staff,Bow\tAny\t2\ttrue\t1100\t1700\t7\r\nWarrior's\tTOHIT_DAMP\t51\t65\t10\tWeapon,Staff,Bow\tAny\t2\ttrue\t1850\t2450\t13\r\nSoldier's\tTOHIT_DAMP\t66\t80\t15\tWeapon,Staff\tAny\t2\ttrue\t2600\t3950\t17\r\nLord's\tTOHIT_DAMP\t81\t95\t19\tWeapon,Staff\tAny\t2\ttrue\t4100\t5950\t21\r\nKnight's\tTOHIT_DAMP\t96\t110\t23\tWeapon,Staff\tAny\t2\ttrue\t6100\t8450\t26\r\nMaster's\tTOHIT_DAMP\t111\t125\t28\tWeapon,Staff\tAny\t2\ttrue\t8600\t13000\t30\r\nChampion's\tTOHIT_DAMP\t126\t150\t40\tWeapon,Staff\tAny\t2\ttrue\t15200\t24000\t33\r\nKing's\tTOHIT_DAMP\t151\t175\t28\tWeapon,Staff\tAny\t2\ttrue\t24100\t35000\t38\r\nVulnerable\tACP_CURSE\t51\t100\t3\tArmor,Shield\tAny\t2\tfalse\t0\t0\t-3\r\nRusted\tACP_CURSE\t25\t50\t1\tArmor,Shield\tAny\t2\tfalse\t0\t0\t-2\r\nFine\tACP\t20\t30\t1\tArmor,Shield\tAny\t2\ttrue\t20\t100\t2\r\nStrong\tACP\t31\t40\t3\tArmor,Shield\tAny\t2\ttrue\t120\t200\t3\r\nGrand\tACP\t41\t55\t6\tArmor,Shield\tAny\t2\ttrue\t220\t300\t5\r\nValiant\tACP\t56\t70\t10\tArmor,Shield\tAny\t2\ttrue\t320\t400\t7\r\nGlorious\tACP\t71\t90\t14\tArmor,Shield\tGood\t2\ttrue\t420\t600\t9\r\nBlessed\tACP\t91\t110\t19\tArmor,Shield\tGood\t2\ttrue\t620\t800\t11\r\nSaintly\tACP\t111\t130\t24\tArmor,Shield\tGood\t2\ttrue\t820\t1200\t13\r\nAwesome\tACP\t131\t150\t28\tArmor,Shield\tGood\t2\ttrue\t1220\t2000\t15\r\nHoly\tACP\t151\t170\t35\tArmor,Shield\tGood\t2\ttrue\t5200\t6000\t17\r\nGodly\tACP\t171\t200\t60\tArmor,Shield\tGood\t2\ttrue\t6200\t7000\t20\r\nRed\tFIRERES\t10\t20\t4\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t500\t1500\t2\r\nCrimson\tFIRERES\t21\t30\t10\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2100\t3000\t2\r\nCrimson\tFIRERES\t31\t40\t16\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3100\t4000\t2\r\nGarnet\tFIRERES\t41\t50\t20\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t8200\t12000\t3\r\nRuby\tFIRERES\t51\t60\t26\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t17100\t20000\t5\r\nBlue\tLIGHTRES\t10\t20\t4\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t500\t1500\t2\r\nAzure\tLIGHTRES\t21\t30\t10\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2100\t3000\t2\r\nLapis\tLIGHTRES\t31\t40\t16\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3100\t4000\t2\r\nCobalt\tLIGHTRES\t41\t50\t20\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t8200\t12000\t3\r\nSapphire\tLIGHTRES\t51\t60\t26\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t17100\t20000\t5\r\nWhite\tMAGICRES\t10\t20\t4\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t500\t1500\t2\r\nPearl\tMAGICRES\t21\t30\t10\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2100\t3000\t2\r\nIvory\tMAGICRES\t31\t40\t16\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3100\t4000\t2\r\nCrystal\tMAGICRES\t41\t50\t20\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t8200\t12000\t3\r\nDiamond\tMAGICRES\t51\t60\t26\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t17100\t20000\t5\r\nTopaz\tALLRES\t10\t15\t8\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2000\t5000\t3\r\nAmber\tALLRES\t16\t20\t12\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t7400\t10000\t3\r\nJade\tALLRES\t21\t30\t18\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t11000\t15000\t3\r\nObsidian\tALLRES\t31\t40\t24\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t24000\t40000\t4\r\nEmerald\tALLRES\t41\t50\t31\tShield,Weapon,Staff,Bow\tAny\t1\ttrue\t61000\t75000\t7\r\nHyena's\tMANA_CURSE\t11\t25\t4\tStaff,Misc\tAny\t1\tfalse\t100\t1000\t-2\r\nFrog's\tMANA_CURSE\t1\t10\t1\tStaff,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nSpider's\tMANA\t10\t15\t1\tStaff,Misc\tEvil\t1\ttrue\t500\t1000\t2\r\nRaven's\tMANA\t15\t20\t5\tStaff,Misc\tAny\t1\ttrue\t1100\t2000\t3\r\nSnake's\tMANA\t21\t30\t9\tStaff,Misc\tAny\t1\ttrue\t2100\t4000\t5\r\nSerpent's\tMANA\t30\t40\t15\tStaff,Misc\tAny\t1\ttrue\t4100\t6000\t7\r\nDrake's\tMANA\t41\t50\t21\tStaff,Misc\tAny\t1\ttrue\t6100\t10000\t9\r\nDragon's\tMANA\t51\t60\t27\tStaff,Misc\tAny\t1\ttrue\t10100\t15000\t11\r\nWyrm's\tMANA\t61\t80\t35\tStaff\tAny\t1\ttrue\t15100\t19000\t12\r\nHydra's\tMANA\t81\t100\t60\tStaff\tAny\t1\ttrue\t19100\t30000\t13\r\nAngel's\tSPLLVLADD\t1\t1\t15\tStaff\tGood\t1\ttrue\t25000\t25000\t2\r\nArch-Angel's\tSPLLVLADD\t2\t2\t25\tStaff\tGood\t1\ttrue\t50000\t50000\t3\r\nPlentiful\tCHARGES\t2\t2\t4\tStaff\tAny\t1\ttrue\t2000\t2000\t2\r\nBountiful\tCHARGES\t3\t3\t9\tStaff\tAny\t1\ttrue\t3000\t3000\t3\r\nFlaming\tFIREDAM\t1\t10\t7\tWeapon,Staff\tAny\t1\ttrue\t5000\t5000\t2\r\nLightning\tLIGHTDAM\t2\t20\t18\tWeapon,Staff\tAny\t1\ttrue\t10000\t10000\t2\r\n"
  },
  {
    "path": "assets/txtdata/items/item_suffixes.tsv",
    "content": "name\tpower\tpower.value1\tpower.value2\tminLevel\titemTypes\talignment\tchance\tuseful\tminVal\tmaxVal\tmultVal\r\nquality\tDAMMOD\t1\t2\t2\tWeapon,Bow\tAny\t1\ttrue\t100\t200\t2\r\nmaiming\tDAMMOD\t3\t5\t7\tWeapon,Bow\tAny\t1\ttrue\t1300\t1500\t3\r\nslaying\tDAMMOD\t6\t8\t15\tWeapon\tAny\t1\ttrue\t2600\t3000\t5\r\ngore\tDAMMOD\t9\t12\t25\tWeapon\tAny\t1\ttrue\t4100\t5000\t8\r\ncarnage\tDAMMOD\t13\t16\t35\tWeapon\tAny\t1\ttrue\t5100\t10000\t10\r\nslaughter\tDAMMOD\t17\t20\t60\tWeapon\tAny\t1\ttrue\t10100\t15000\t13\r\npain\tGETHIT_CURSE\t2\t4\t4\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-4\r\ntears\tGETHIT_CURSE\t1\t1\t2\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nhealth\tGETHIT\t1\t1\t2\tArmor,Shield,Misc\tGood\t1\ttrue\t200\t200\t2\r\nprotection\tGETHIT\t2\t2\t6\tArmor,Shield\tGood\t1\ttrue\t400\t800\t4\r\nabsorption\tGETHIT\t3\t3\t12\tArmor,Shield\tGood\t1\ttrue\t1001\t2500\t10\r\ndeflection\tGETHIT\t4\t4\t20\tArmor\tGood\t1\ttrue\t2500\t6500\t15\r\nosmosis\tGETHIT\t5\t6\t50\tArmor\tGood\t1\ttrue\t7500\t10000\t20\r\nfrailty\tSTR_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\nweakness\tSTR_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nstrength\tSTR\t1\t5\t1\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t200\t1000\t2\r\nmight\tSTR\t6\t10\t5\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t1200\t2000\t3\r\npower\tSTR\t11\t15\t11\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t2200\t3000\t4\r\ngiants\tSTR\t16\t20\t17\tArmor,Weapon,Bow,Misc\tAny\t1\ttrue\t3200\t5000\t7\r\ntitans\tSTR\t21\t30\t23\tWeapon,Misc\tAny\t1\ttrue\t5200\t10000\t10\r\nparalysis\tDEX_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\natrophy\tDEX_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\ndexterity\tDEX\t1\t5\t1\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t200\t1000\t2\r\nskill\tDEX\t6\t10\t5\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t1200\t2000\t3\r\naccuracy\tDEX\t11\t15\t11\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t2200\t3000\t4\r\nprecision\tDEX\t16\t20\t17\tArmor,Weapon,Bow,Misc\tAny\t1\ttrue\t3200\t5000\t7\r\nperfection\tDEX\t21\t30\t23\tBow,Misc\tAny\t1\ttrue\t5200\t10000\t10\r\nthe fool\tMAG_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\ndyslexia\tMAG_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nmagic\tMAG\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t200\t1000\t2\r\nthe mind\tMAG\t6\t10\t5\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t1200\t2000\t3\r\nbrilliance\tMAG\t11\t15\t11\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2200\t3000\t4\r\nsorcery\tMAG\t16\t20\t17\tArmor,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3200\t5000\t7\r\nwizardry\tMAG\t21\t30\t23\tStaff,Misc\tAny\t1\ttrue\t5200\t10000\t10\r\nillness\tVIT_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\ndisease\tVIT_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nvitality\tVIT\t1\t5\t1\tArmor,Shield,Weapon,Bow,Misc\tGood\t1\ttrue\t200\t1000\t2\r\nzest\tVIT\t6\t10\t5\tArmor,Shield,Weapon,Bow,Misc\tGood\t1\ttrue\t1200\t2000\t3\r\nvim\tVIT\t11\t15\t11\tArmor,Shield,Weapon,Bow,Misc\tGood\t1\ttrue\t2200\t3000\t4\r\nvigor\tVIT\t16\t20\t17\tArmor,Weapon,Bow,Misc\tGood\t1\ttrue\t3200\t5000\t7\r\nlife\tVIT\t21\t30\t23\tMisc\tGood\t1\ttrue\t5200\t10000\t10\r\ntrouble\tATTRIBS_CURSE\t6\t10\t12\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-10\r\nthe pit\tATTRIBS_CURSE\t1\t5\t5\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-5\r\nthe sky\tATTRIBS\t1\t3\t5\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t800\t4000\t5\r\nthe moon\tATTRIBS\t4\t7\t11\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t4800\t8000\t10\r\nthe stars\tATTRIBS\t8\t11\t17\tArmor,Weapon,Bow,Misc\tAny\t1\ttrue\t8800\t12000\t15\r\nthe heavens\tATTRIBS\t12\t15\t25\tWeapon,Bow,Misc\tAny\t1\ttrue\t12800\t20000\t20\r\nthe zodiac\tATTRIBS\t16\t20\t30\tMisc\tAny\t1\ttrue\t20800\t40000\t30\r\nthe vulture\tLIFE_CURSE\t11\t25\t4\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-4\r\nthe jackal\tLIFE_CURSE\t1\t10\t1\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nthe fox\tLIFE\t10\t15\t1\tArmor,Shield,Misc\tAny\t1\ttrue\t100\t1000\t2\r\nthe jaguar\tLIFE\t16\t20\t5\tArmor,Shield,Misc\tAny\t1\ttrue\t1100\t2000\t3\r\nthe eagle\tLIFE\t21\t30\t9\tArmor,Shield,Misc\tAny\t1\ttrue\t2100\t4000\t5\r\nthe wolf\tLIFE\t30\t40\t15\tArmor,Shield,Misc\tAny\t1\ttrue\t4100\t6000\t7\r\nthe tiger\tLIFE\t41\t50\t21\tArmor,Shield,Misc\tAny\t1\ttrue\t6100\t10000\t9\r\nthe lion\tLIFE\t51\t60\t27\tArmor,Misc\tAny\t1\ttrue\t10100\t15000\t11\r\nthe mammoth\tLIFE\t61\t80\t35\tArmor\tAny\t1\ttrue\t15100\t19000\t12\r\nthe whale\tLIFE\t81\t100\t60\tArmor\tAny\t1\ttrue\t19100\t30000\t13\r\nfragility\tDUR_CURSE\t100\t100\t3\tArmor,Shield,Weapon\tEvil\t1\tfalse\t0\t0\t-4\r\nbrittleness\tDUR_CURSE\t26\t75\t1\tArmor,Shield,Weapon\tEvil\t1\tfalse\t0\t0\t-2\r\nsturdiness\tDUR\t26\t75\t1\tArmor,Shield,Weapon\tAny\t1\ttrue\t100\t100\t2\r\ncraftsmanship\tDUR\t51\t100\t6\tArmor,Shield,Weapon\tAny\t1\ttrue\t200\t200\t2\r\nstructure\tDUR\t101\t200\t12\tArmor,Shield,Weapon\tAny\t1\ttrue\t300\t300\t2\r\nthe ages\tINDESTRUCTIBLE\t\t\t25\tArmor,Shield,Weapon\tAny\t1\ttrue\t600\t600\t5\r\nthe dark\tLIGHT_CURSE\t4\t4\t6\tArmor,Weapon,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\nthe night\tLIGHT_CURSE\t2\t2\t3\tArmor,Weapon,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nlight\tLIGHT\t2\t2\t4\tArmor,Weapon,Misc\tGood\t1\ttrue\t750\t750\t2\r\nradiance\tLIGHT\t4\t4\t8\tArmor,Weapon,Misc\tGood\t1\ttrue\t1500\t1500\t3\r\nflame\tFIRE_ARROWS\t1\t3\t1\tBow\tAny\t1\ttrue\t2000\t2000\t2\r\nfire\tFIRE_ARROWS\t1\t6\t11\tBow\tAny\t1\ttrue\t4000\t4000\t4\r\nburning\tFIRE_ARROWS\t1\t16\t35\tBow\tAny\t1\ttrue\t6000\t6000\t6\r\nshock\tLIGHT_ARROWS\t1\t6\t13\tBow\tAny\t1\ttrue\t6000\t6000\t2\r\nlightning\tLIGHT_ARROWS\t1\t10\t21\tBow\tAny\t1\ttrue\t8000\t8000\t4\r\nthunder\tLIGHT_ARROWS\t1\t20\t60\tBow\tAny\t1\ttrue\t12000\t12000\t6\r\nmany\tDUR\t100\t100\t3\tBow\tAny\t1\ttrue\t750\t750\t2\r\nplenty\tDUR\t200\t200\t7\tBow\tAny\t1\ttrue\t1500\t1500\t3\r\nthorns\tTHORNS\t1\t3\t1\tArmor,Shield\tAny\t1\ttrue\t500\t500\t2\r\ncorruption\tNOMANA\t\t\t5\tArmor,Shield,Weapon\tEvil\t1\tfalse\t-1000\t-1000\t2\r\nthieves\tABSHALFTRAP\t\t\t11\tArmor,Shield,Misc\tAny\t1\ttrue\t1500\t1500\t2\r\nthe bear\tKNOCKBACK\t\t\t5\tWeapon,Staff,Bow\tEvil\t1\ttrue\t750\t750\t2\r\nthe bat\tSTEALMANA\t3\t3\t8\tWeapon\tAny\t1\ttrue\t7500\t7500\t3\r\nvampires\tSTEALMANA\t5\t5\t19\tWeapon\tAny\t1\ttrue\t15000\t15000\t3\r\nthe leech\tSTEALLIFE\t3\t3\t8\tWeapon\tAny\t1\ttrue\t7500\t7500\t3\r\nblood\tSTEALLIFE\t5\t5\t19\tWeapon\tAny\t1\ttrue\t15000\t15000\t3\r\npiercing\tTARGAC\t2\t6\t1\tWeapon,Bow\tAny\t1\ttrue\t1000\t1000\t3\r\npuncturing\tTARGAC\t4\t12\t9\tWeapon,Bow\tAny\t1\ttrue\t2000\t2000\t6\r\nbashing\tTARGAC\t8\t24\t17\tWeapon\tAny\t1\ttrue\t4000\t4000\t12\r\nreadiness\tFASTATTACK\t1\t1\t1\tWeapon,Staff,Bow\tAny\t1\ttrue\t2000\t2000\t2\r\nswiftness\tFASTATTACK\t2\t2\t10\tWeapon,Staff,Bow\tAny\t1\ttrue\t4000\t4000\t4\r\nspeed\tFASTATTACK\t3\t3\t19\tWeapon,Staff\tAny\t1\ttrue\t8000\t8000\t8\r\nhaste\tFASTATTACK\t4\t4\t27\tWeapon,Staff\tAny\t1\ttrue\t16000\t16000\t16\r\nbalance\tFASTRECOVER\t1\t1\t1\tArmor,Misc\tAny\t1\ttrue\t2000\t2000\t2\r\nstability\tFASTRECOVER\t2\t2\t10\tArmor,Misc\tAny\t1\ttrue\t4000\t4000\t4\r\nharmony\tFASTRECOVER\t3\t3\t20\tArmor,Misc\tAny\t1\ttrue\t8000\t8000\t8\r\nblocking\tFASTBLOCK\t1\t1\t5\tShield\tAny\t1\ttrue\t4000\t4000\t4\r\n"
  },
  {
    "path": "assets/txtdata/items/itemdat.tsv",
    "content": "id\tdropRate\tclass\tequipType\tcursorGraphic\titemType\tuniqueBaseItem\tname\tshortName\tminMonsterLevel\tdurability\tminDamage\tmaxDamage\tminArmor\tmaxArmor\tminStrength\tminMagic\tminDexterity\tspecialEffects\tmiscId\tspell\tusable\tvalue\r\nIDI_GOLD\t1\tGold\tUnequippable\tGOLD_SMALL\tGold\tNONE\tGold\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\ttrue\t0\r\nIDI_WARRIOR\t0\tWeapon\tOne-handed\tSHORT_SWORD\tSword\tNONE\tShort Sword\t\t2\t24\t2\t6\t0\t0\t18\t0\t0\t\tNONE\tNull\tfalse\t120\r\nIDI_WARRSHLD\t0\tArmor\tOne-handed\tBUCKLER\tShield\tNONE\tBuckler\t\t2\t16\t0\t0\t3\t3\t0\t0\t0\t\tNONE\tNull\tfalse\t30\r\nIDI_WARRCLUB\t0\tWeapon\tOne-handed\tCLUB\tMace\tSPIKCLUB\tClub\t\t1\t20\t1\t6\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t20\r\nIDI_ROGUE\t0\tWeapon\tTwo-handed\tSHORT_BOW\tBow\tNONE\tShort Bow\t\t1\t30\t1\t4\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t100\r\nIDI_SORCERER\t0\tWeapon\tTwo-handed\tSHORT_STAFF\tStaff\tNONE\tShort Staff of Mana\t\t1\t25\t2\t4\t0\t0\t0\t17\t0\t\tSTAFF\tMana\tfalse\t210\r\nIDI_CLEAVER\t0\tWeapon\tTwo-handed\tCLEAVER\tAxe\tCLEAVER\tCleaver\t\t10\t10\t4\t24\t0\t0\t0\t0\t0\t\tUNIQUE\tNull\tfalse\t2000\r\nIDI_SKCROWN\t0\tArmor\tHelm\tTHE_UNDEAD_CROWN\tHelm\tSKCROWN\tThe Undead Crown\t\t0\t50\t0\t0\t15\t15\t0\t0\t0\tRandomStealLife\tUNIQUE\tNull\tfalse\t10000\r\nIDI_INFRARING\t0\tMisc\tRing\tEMPYREAN_BAND\tRing\tINFRARING\tEmpyrean Band\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tUNIQUE\tNull\tfalse\t8000\r\nIDI_ROCK\t0\tQuest\tUnequippable\tMAGIC_ROCK\tMisc\tNONE\tMagic Rock\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_OPTAMULET\t0\tMisc\tAmulet\tOPTIC_AMULET\tAmulet\tOPTAMULET\tOptic Amulet\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tUNIQUE\tNull\tfalse\t5000\r\nIDI_TRING\t0\tMisc\tRing\tRING_OF_TRUTH\tRing\tTRING\tRing of Truth\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tUNIQUE\tNull\tfalse\t1000\r\nIDI_BANNER\t0\tQuest\tUnequippable\tTAVERN_SIGN\tMisc\tNONE\tTavern Sign\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_HARCREST\t0\tArmor\tHelm\tHARLEQUIN_CREST\tHelm\tHARCREST\tHarlequin Crest\t\t0\t15\t0\t0\t0\t0\t0\t0\t0\t\tUNIQUE\tNull\tfalse\t15\r\nIDI_STEELVEIL\t0\tArmor\tHelm\tVEIL_OF_STEEL\tHelm\tSTEELVEIL\tVeil of Steel\t\t0\t60\t0\t0\t18\t18\t0\t0\t0\t\tUNIQUE\tNull\tfalse\t0\r\nIDI_GLDNELIX\t0\tMisc\tUnequippable\tGOLDEN_ELIXIR\tMisc\tELIXIR\tGolden Elixir\t\t15\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_ANVIL\t0\tQuest\tUnequippable\tANVIL_OF_FURY\tMisc\tNONE\tAnvil of Fury\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_MUSHROOM\t0\tQuest\tUnequippable\tBLACK_MUSHROOM\tMisc\tNONE\tBlack Mushroom\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_BRAIN\t0\tQuest\tUnequippable\tBRAIN\tMisc\tNONE\tBrain\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_FUNGALTM\t0\tQuest\tUnequippable\tFUNGAL_TOME\tMisc\tNONE\tFungal Tome\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_SPECELIX\t0\tMisc\tUnequippable\tSPECTRAL_ELIXIR\tMisc\tELIXIR\tSpectral Elixir\t\t15\t0\t0\t0\t0\t0\t0\t0\t0\t\tSPECELIX\tNull\ttrue\t0\r\nIDI_BLDSTONE\t0\tQuest\tUnequippable\tBLOOD_STONE\tMisc\tNONE\tBlood Stone\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_MAPOFDOOM\t0\tQuest\tUnequippable\tMAP_OF_THE_STARS\tMisc\tMAPOFDOOM\tCathedral Map\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tMAPOFDOOM\tNull\ttrue\t0\r\nIDI_EAR\t0\tMisc\tUnequippable\t\tMisc\tNONE\tEar\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tEAR\tNull\tfalse\t0\r\nIDI_HEAL\t0\tMisc\tUnequippable\tPOTION_OF_HEALING\tMisc\tNONE\tPotion of Healing\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tHEAL\tNull\ttrue\t50\r\nIDI_MANA\t0\tMisc\tUnequippable\tPOTION_OF_MANA\tMisc\tNONE\tPotion of Mana\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tMANA\tNull\ttrue\t50\r\nIDI_IDENTIFY\t0\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Identify\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLL\tIdentify\ttrue\t200\r\nIDI_PORTAL\t0\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Town Portal\t\t4\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLL\tTownPortal\ttrue\t200\r\nIDI_ARMOFVAL\t0\tArmor\tArmor\tARKAINES_VALOR\tMediumArmor\tARMOFVAL\tArkaine's Valor\t\t0\t40\t0\t0\t0\t0\t0\t0\t0\t\tUNIQUE\tNull\tfalse\t0\r\nIDI_FULLHEAL\t0\tMisc\tUnequippable\tPOTION_OF_FULL_HEALING\tMisc\tNONE\tPotion of Full Healing\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tFULLHEAL\tNull\ttrue\t150\r\nIDI_FULLMANA\t0\tMisc\tUnequippable\tPOTION_OF_FULL_MANA\tMisc\tNONE\tPotion of Full Mana\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tFULLMANA\tNull\ttrue\t150\r\nIDI_GRISWOLD\t0\tWeapon\tOne-handed\tBROAD_SWORD\tSword\tGRISWOLD\tGriswold's Edge\t\t8\t50\t4\t12\t0\t0\t40\t0\t0\t\tUNIQUE\tNull\tfalse\t750\r\nIDI_LGTFORGE\t0\tArmor\tArmor\tBOVINE\tHeavyArmor\tBOVINE\tBovine Plate\t\t0\t40\t0\t0\t0\t0\t50\t0\t0\t\tUNIQUE\tNull\tfalse\t0\r\nIDI_LAZSTAFF\t0\tMisc\tUnequippable\tSTAFF_OF_LAZARUS\tMisc\tLAZSTAFF\tStaff of Lazarus\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_RESURRECT\t0\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Resurrect\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLLT\tResurrect\ttrue\t250\r\nIDI_OIL\t0\tMisc\tUnequippable\tOIL\tMisc\tNONE\tBlacksmith Oil\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tOILBSMTH\tNull\ttrue\t100\r\nIDI_SHORTSTAFF\t0\tWeapon\tTwo-handed\tSHORT_STAFF\tStaff\tNONE\tShort Staff\t\t1\t25\t2\t4\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t20\r\nIDI_BARDSWORD\t0\tWeapon\tOne-handed\tSHORT_SWORD\tSword\tNONE\tSword\t\t2\t8\t1\t5\t0\t0\t15\t0\t20\t\tNONE\tNull\tfalse\t20\r\nIDI_BARDDAGGER\t0\tWeapon\tOne-handed\tDAGGER\tSword\tNONE\tDagger\t\t1\t16\t1\t4\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t20\r\nIDI_RUNEBOMB\t0\tQuest\tUnequippable\tRUNE_BOMB\tMisc\tNONE\tRune Bomb\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_THEODORE\t0\tQuest\tUnequippable\tTHEODORE\tMisc\tNONE\tTheodore\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_AURIC\t0\tMisc\tAmulet\tAURIC_AMULET\tMisc\tNONE\tAuric Amulet\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tAURIC\tNull\tfalse\t100\r\nIDI_NOTE1\t0\tQuest\tUnequippable\tTORN_NOTE_1\tMisc\tNONE\tTorn Note 1\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_NOTE2\t0\tQuest\tUnequippable\tTORN_NOTE_2\tMisc\tNONE\tTorn Note 2\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_NOTE3\t0\tQuest\tUnequippable\tTORN_NOTE_3\tMisc\tNONE\tTorn Note 3\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_FULLNOTE\t0\tQuest\tUnequippable\tRECONSTRUCTED_NOTE\tMisc\tNONE\tReconstructed Note\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNOTE\tNull\ttrue\t0\r\nIDI_BROWNSUIT\t0\tQuest\tUnequippable\tBROWN_SUIT\tMisc\tNONE\tBrown Suit\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\nIDI_GREYSUIT\t0\tQuest\tUnequippable\tGREY_SUIT\tMisc\tNONE\tGrey Suit\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\n\t1\tArmor\tHelm\tCAP\tHelm\tNONE\tCap\tCap\t1\t15\t0\t0\t1\t3\t0\t0\t0\t\tNONE\tNull\tfalse\t15\r\n\t1\tArmor\tHelm\tSKULL_CAP\tHelm\tSKULLCAP\tSkull Cap\tCap\t4\t20\t0\t0\t2\t4\t0\t0\t0\t\tNONE\tNull\tfalse\t25\r\n\t1\tArmor\tHelm\tHELM\tHelm\tHELM\tHelm\tHelm\t8\t30\t0\t0\t4\t6\t25\t0\t0\t\tNONE\tNull\tfalse\t40\r\n\t1\tArmor\tHelm\tFULL_HELM\tHelm\tNONE\tFull Helm\tHelm\t12\t35\t0\t0\t6\t8\t35\t0\t0\t\tNONE\tNull\tfalse\t90\r\n\t1\tArmor\tHelm\tCROWN\tHelm\tCROWN\tCrown\tCrown\t16\t40\t0\t0\t8\t12\t0\t0\t0\t\tNONE\tNull\tfalse\t200\r\n\t1\tArmor\tHelm\tGREAT_HELM\tHelm\tGREATHELM\tGreat Helm\tHelm\t20\t60\t0\t0\t10\t15\t50\t0\t0\t\tNONE\tNull\tfalse\t400\r\n\t1\tArmor\tArmor\tCAPE\tLightArmor\tCAPE\tCape\tCape\t1\t12\t0\t0\t1\t5\t0\t0\t0\t\tNONE\tNull\tfalse\t10\r\n\t1\tArmor\tArmor\tRAGS\tLightArmor\tRAGS\tRags\tRags\t1\t6\t0\t0\t2\t6\t0\t0\t0\t\tNONE\tNull\tfalse\t5\r\n\t1\tArmor\tArmor\tCLOAK\tLightArmor\tCLOAK\tCloak\tCloak\t2\t18\t0\t0\t3\t7\t0\t0\t0\t\tNONE\tNull\tfalse\t40\r\n\t1\tArmor\tArmor\tROBE\tLightArmor\tROBE\tRobe\tRobe\t3\t24\t0\t0\t4\t7\t0\t0\t0\t\tNONE\tNull\tfalse\t75\r\n\t1\tArmor\tArmor\tQUILTED_ARMOR\tLightArmor\tNONE\tQuilted Armor\tArmor\t4\t30\t0\t0\t7\t10\t0\t0\t0\t\tNONE\tNull\tfalse\t200\r\n\t1\tArmor\tArmor\tLEATHER_ARMOR\tLightArmor\tLEATHARMOR\tLeather Armor\tArmor\t6\t35\t0\t0\t10\t13\t0\t0\t0\t\tNONE\tNull\tfalse\t300\r\n\t1\tArmor\tArmor\tHARD_LEATHER_ARMOR\tLightArmor\tNONE\tHard Leather Armor\tArmor\t7\t40\t0\t0\t11\t14\t0\t0\t0\t\tNONE\tNull\tfalse\t450\r\n\t1\tArmor\tArmor\tSTUDDED_LEATHER_ARMOR\tLightArmor\tSTUDARMOR\tStudded Leather Armor\tArmor\t9\t45\t0\t0\t15\t17\t20\t0\t0\t\tNONE\tNull\tfalse\t700\r\n\t1\tArmor\tArmor\tRING_MAIL\tMediumArmor\tNONE\tRing Mail\tMail\t11\t50\t0\t0\t17\t20\t25\t0\t0\t\tNONE\tNull\tfalse\t900\r\n\t1\tArmor\tArmor\tCHAIN_MAIL\tMediumArmor\tCHAINMAIL\tChain Mail\tMail\t13\t55\t0\t0\t18\t22\t30\t0\t0\t\tNONE\tNull\tfalse\t1250\r\n\t1\tArmor\tArmor\tSCALE_MAIL\tMediumArmor\tNONE\tScale Mail\tMail\t15\t60\t0\t0\t23\t28\t35\t0\t0\t\tNONE\tNull\tfalse\t2300\r\n\t1\tArmor\tArmor\tBREAST_PLATE\tHeavyArmor\tBREASTPLATE\tBreast Plate\tPlate\t16\t80\t0\t0\t20\t24\t40\t0\t0\t\tNONE\tNull\tfalse\t2800\r\n\t1\tArmor\tArmor\tSPLINT_MAIL\tMediumArmor\tNONE\tSplint Mail\tMail\t17\t65\t0\t0\t30\t35\t40\t0\t0\t\tNONE\tNull\tfalse\t3250\r\n\t1\tArmor\tArmor\tFIELD_PLATE\tHeavyArmor\tPLATEMAIL\tPlate Mail\tPlate\t19\t75\t0\t0\t42\t50\t60\t0\t0\t\tNONE\tNull\tfalse\t4600\r\n\t1\tArmor\tArmor\tFIELD_PLATE\tHeavyArmor\tNONE\tField Plate\tPlate\t21\t80\t0\t0\t40\t45\t65\t0\t0\t\tNONE\tNull\tfalse\t5800\r\n\t1\tArmor\tArmor\tGOTHIC_PLATE\tHeavyArmor\tNONE\tGothic Plate\tPlate\t23\t100\t0\t0\t50\t60\t80\t0\t0\t\tNONE\tNull\tfalse\t8000\r\n\t1\tArmor\tArmor\tFULL_PLATE_MAIL\tHeavyArmor\tFULLPLATE\tFull Plate Mail\tPlate\t25\t90\t0\t0\t60\t75\t90\t0\t0\t\tNONE\tNull\tfalse\t6500\r\n\t1\tArmor\tOne-handed\tBUCKLER\tShield\tBUCKLER\tBuckler\tShield\t1\t16\t0\t0\t1\t5\t0\t0\t0\t\tNONE\tNull\tfalse\t30\r\n\t1\tArmor\tOne-handed\tSMALL_SHIELD\tShield\tSMALLSHIELD\tSmall Shield\tShield\t5\t24\t0\t0\t3\t8\t25\t0\t0\t\tNONE\tNull\tfalse\t90\r\n\t1\tArmor\tOne-handed\tLARGE_SHIELD\tShield\tLARGESHIELD\tLarge Shield\tShield\t9\t32\t0\t0\t5\t10\t40\t0\t0\t\tNONE\tNull\tfalse\t200\r\n\t1\tArmor\tOne-handed\tKITE_SHIELD\tShield\tKITESHIELD\tKite Shield\tShield\t14\t40\t0\t0\t8\t15\t50\t0\t0\t\tNONE\tNull\tfalse\t400\r\n\t1\tArmor\tOne-handed\tTOWER_SHIELD\tShield\tGOTHSHIELD\tTower Shield\tShield\t20\t50\t0\t0\t12\t20\t60\t0\t0\t\tNONE\tNull\tfalse\t850\r\n\t1\tArmor\tOne-handed\tGOTHIC_SHIELD\tShield\tGOTHSHIELD\tGothic Shield\tShield\t23\t60\t0\t0\t14\t18\t80\t0\t0\t\tNONE\tNull\tfalse\t2300\r\n\t1\tMisc\tUnequippable\tPOTION_OF_HEALING\tMisc\tNONE\tPotion of Healing\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tHEAL\tNull\ttrue\t50\r\n\t1\tMisc\tUnequippable\tPOTION_OF_FULL_HEALING\tMisc\tNONE\tPotion of Full Healing\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tFULLHEAL\tNull\ttrue\t150\r\n\t1\tMisc\tUnequippable\tPOTION_OF_MANA\tMisc\tNONE\tPotion of Mana\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tMANA\tNull\ttrue\t50\r\n\t1\tMisc\tUnequippable\tPOTION_OF_FULL_MANA\tMisc\tNONE\tPotion of Full Mana\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tFULLMANA\tNull\ttrue\t150\r\n\t1\tMisc\tUnequippable\tPOTION_OF_REJUVENATION\tMisc\tNONE\tPotion of Rejuvenation\t\t3\t0\t0\t0\t0\t0\t0\t0\t0\t\tREJUV\tNull\ttrue\t120\r\n\t1\tMisc\tUnequippable\tPOTION_OF_FULL_REJUVENATION\tMisc\tNONE\tPotion of Full Rejuvenation\t\t7\t0\t0\t0\t0\t0\t0\t0\t0\t\tFULLREJUV\tNull\ttrue\t600\r\n\t1\tMisc\tUnequippable\tOIL\tMisc\tNONE\tBlacksmith Oil\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tOILBSMTH\tNull\ttrue\t100\r\n\t1\tMisc\tUnequippable\tOIL\tMisc\tNONE\tOil of Accuracy\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tOILACC\tNull\ttrue\t500\r\n\t1\tMisc\tUnequippable\tOIL\tMisc\tNONE\tOil of Sharpness\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tOILSHARP\tNull\ttrue\t500\r\n\t1\tMisc\tUnequippable\tOIL\tMisc\tNONE\tOil\t\t10\t0\t0\t0\t0\t0\t0\t0\t0\t\tOILOF\tNull\ttrue\t0\r\n\t1\tMisc\tUnequippable\tELIXIR_OF_STRENGTH\tMisc\tNONE\tElixir of Strength\t\t15\t0\t0\t0\t0\t0\t0\t0\t0\t\tELIXSTR\tNull\ttrue\t5000\r\n\t1\tMisc\tUnequippable\tELIXIR_OF_MAGIC\tMisc\tNONE\tElixir of Magic\t\t15\t0\t0\t0\t0\t0\t0\t0\t0\t\tELIXMAG\tNull\ttrue\t5000\r\n\t1\tMisc\tUnequippable\tELIXIR_OF_DEXTERITY\tMisc\tNONE\tElixir of Dexterity\t\t15\t0\t0\t0\t0\t0\t0\t0\t0\t\tELIXDEX\tNull\ttrue\t5000\r\n\t1\tMisc\tUnequippable\tELIXIR_OF_VITALITY\tMisc\tNONE\tElixir of Vitality\t\t20\t0\t0\t0\t0\t0\t0\t0\t0\t\tELIXVIT\tNull\ttrue\t5000\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Healing\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLL\tHealing\ttrue\t50\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Search\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLL\tSearch\ttrue\t50\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Lightning\t\t4\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLLT\tLightning\ttrue\t150\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Identify\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLL\tIdentify\ttrue\t100\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Resurrect\t\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLLT\tResurrect\ttrue\t250\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Fire Wall\t\t4\t0\t0\t0\t0\t0\t0\t17\t0\t\tSCROLLT\tFireWall\ttrue\t400\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Inferno\t\t1\t0\t0\t0\t0\t0\t0\t19\t0\t\tSCROLLT\tInferno\ttrue\t100\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Town Portal\t\t4\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLL\tTownPortal\ttrue\t200\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Flash\t\t6\t0\t0\t0\t0\t0\t0\t21\t0\t\tSCROLLT\tFlash\ttrue\t500\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Infravision\t\t8\t0\t0\t0\t0\t0\t0\t23\t0\t\tSCROLL\tInfravision\ttrue\t600\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Phasing\t\t6\t0\t0\t0\t0\t0\t0\t25\t0\t\tSCROLL\tPhasing\ttrue\t200\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Mana Shield\t\t8\t0\t0\t0\t0\t0\t0\t0\t0\t\tSCROLL\tManaShield\ttrue\t1200\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Flame Wave\t\t10\t0\t0\t0\t0\t0\t0\t29\t0\t\tSCROLLT\tFlameWave\ttrue\t650\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Fireball\t\t8\t0\t0\t0\t0\t0\t0\t31\t0\t\tSCROLLT\tFireball\ttrue\t300\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Stone Curse\t\t6\t0\t0\t0\t0\t0\t0\t33\t0\t\tSCROLLT\tStoneCurse\ttrue\t800\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Chain Lightning\t\t10\t0\t0\t0\t0\t0\t0\t35\t0\t\tSCROLLT\tChainLightning\ttrue\t750\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Guardian\t\t12\t0\t0\t0\t0\t0\t0\t47\t0\t\tSCROLLT\tGuardian\ttrue\t950\r\n\t0\tMisc\tUnequippable\t\tMisc\tNONE\t\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Nova\t\t14\t0\t0\t0\t0\t0\t0\t57\t0\t\tSCROLL\tNova\ttrue\t1300\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Golem\t\t10\t0\t0\t0\t0\t0\t0\t51\t0\t\tSCROLLT\tGolem\ttrue\t1100\r\n\t0\tMisc\tUnequippable\t\tMisc\tNONE\t\t\t0\t0\t0\t0\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t0\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Teleport\t\t14\t0\t0\t0\t0\t0\t0\t81\t0\t\tSCROLL\tTeleport\ttrue\t3000\r\n\t1\tMisc\tUnequippable\tSCROLL_OF\tMisc\tNONE\tScroll of Apocalypse\t\t22\t0\t0\t0\t0\t0\t0\t117\t0\t\tSCROLL\tApocalypse\ttrue\t2000\r\n\t1\tMisc\tUnequippable\tBOOK_BLUE\tMisc\tNONE\tBook of \t\t2\t0\t0\t0\t0\t0\t0\t0\t0\t\tBOOK\tNull\ttrue\t0\r\n\t1\tMisc\tUnequippable\tBOOK_BLUE\tMisc\tNONE\tBook of \t\t8\t0\t0\t0\t0\t0\t0\t0\t0\t\tBOOK\tNull\ttrue\t0\r\n\t1\tMisc\tUnequippable\tBOOK_BLUE\tMisc\tNONE\tBook of \t\t14\t0\t0\t0\t0\t0\t0\t0\t0\t\tBOOK\tNull\ttrue\t0\r\n\t1\tMisc\tUnequippable\tBOOK_BLUE\tMisc\tNONE\tBook of \t\t20\t0\t0\t0\t0\t0\t0\t0\t0\t\tBOOK\tNull\ttrue\t0\r\n\t1\tWeapon\tOne-handed\tDAGGER\tSword\tDAGGER\tDagger\tDagger\t1\t16\t1\t4\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t60\r\n\t1\tWeapon\tOne-handed\tSHORT_SWORD\tSword\tNONE\tShort Sword\tSword\t1\t24\t2\t6\t0\t0\t18\t0\t0\t\tNONE\tNull\tfalse\t120\r\n\t1\tWeapon\tOne-handed\tFALCHION\tSword\tFALCHION\tFalchion\tSword\t2\t20\t4\t8\t0\t0\t30\t0\t0\t\tNONE\tNull\tfalse\t250\r\n\t1\tWeapon\tOne-handed\tSCIMITAR\tSword\tSCIMITAR\tScimitar\tSword\t4\t28\t3\t7\t0\t0\t23\t0\t23\t\tNONE\tNull\tfalse\t200\r\n\t1\tWeapon\tOne-handed\tCLAYMORE\tSword\tCLAYMORE\tClaymore\tSword\t5\t36\t1\t12\t0\t0\t35\t0\t0\t\tNONE\tNull\tfalse\t450\r\n\t1\tWeapon\tOne-handed\tBLADE\tSword\tNONE\tBlade\tBlade\t4\t30\t3\t8\t0\t0\t25\t0\t30\t\tNONE\tNull\tfalse\t280\r\n\t1\tWeapon\tOne-handed\tSABRE\tSword\tSABRE\tSabre\tSabre\t1\t45\t1\t8\t0\t0\t17\t0\t0\t\tNONE\tNull\tfalse\t170\r\n\t1\tWeapon\tOne-handed\tLONG_SWORD\tSword\tLONGSWR\tLong Sword\tSword\t6\t40\t2\t10\t0\t0\t30\t0\t30\t\tNONE\tNull\tfalse\t350\r\n\t1\tWeapon\tOne-handed\tBROAD_SWORD\tSword\tBROADSWR\tBroad Sword\tSword\t8\t50\t4\t12\t0\t0\t40\t0\t0\t\tNONE\tNull\tfalse\t750\r\n\t1\tWeapon\tOne-handed\tBASTARD_SWORD\tSword\tBASTARDSWR\tBastard Sword\tSword\t10\t60\t6\t15\t0\t0\t50\t0\t0\t\tNONE\tNull\tfalse\t1000\r\n\t1\tWeapon\tTwo-handed\tTWO_HANDED_SWORD\tSword\tTWOHANDSWR\tTwo-Handed Sword\tSword\t14\t75\t8\t16\t0\t0\t65\t0\t0\t\tNONE\tNull\tfalse\t1800\r\n\t1\tWeapon\tTwo-handed\tGREAT_SWORD\tSword\tGREATSWR\tGreat Sword\tSword\t17\t100\t10\t20\t0\t0\t75\t0\t0\t\tNONE\tNull\tfalse\t3000\r\n\t1\tWeapon\tTwo-handed\tSMALL_AXE\tAxe\tSMALLAXE\tSmall Axe\tAxe\t2\t24\t2\t10\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t150\r\n\t1\tWeapon\tTwo-handed\tAXE\tAxe\tNONE\tAxe\tAxe\t4\t32\t4\t12\t0\t0\t22\t0\t0\t\tNONE\tNull\tfalse\t450\r\n\t1\tWeapon\tTwo-handed\tLARGE_AXE\tAxe\tLARGEAXE\tLarge Axe\tAxe\t6\t40\t6\t16\t0\t0\t30\t0\t0\t\tNONE\tNull\tfalse\t750\r\n\t1\tWeapon\tTwo-handed\tBROAD_AXE\tAxe\tBROADAXE\tBroad Axe\tAxe\t8\t50\t8\t20\t0\t0\t50\t0\t0\t\tNONE\tNull\tfalse\t1000\r\n\t1\tWeapon\tTwo-handed\tBATTLE_AXE\tAxe\tBATTLEAXE\tBattle Axe\tAxe\t10\t60\t10\t25\t0\t0\t65\t0\t0\t\tNONE\tNull\tfalse\t1500\r\n\t1\tWeapon\tTwo-handed\tGREAT_AXE\tAxe\tGREATAXE\tGreat Axe\tAxe\t12\t75\t12\t30\t0\t0\t80\t0\t0\t\tNONE\tNull\tfalse\t2500\r\n\t1\tWeapon\tOne-handed\tMACE\tMace\tMACE\tMace\tMace\t2\t32\t1\t8\t0\t0\t16\t0\t0\t\tNONE\tNull\tfalse\t200\r\n\t1\tWeapon\tOne-handed\tMORNING_STAR\tMace\tMORNSTAR\tMorning Star\tMace\t3\t40\t1\t10\t0\t0\t26\t0\t0\t\tNONE\tNull\tfalse\t300\r\n\t1\tWeapon\tOne-handed\tWAR_HAMMER\tMace\tWARHAMMER\tWar Hammer\tHammer\t5\t50\t5\t9\t0\t0\t40\t0\t0\t\tNONE\tNull\tfalse\t600\r\n\t1\tWeapon\tOne-handed\tSPIKED_CLUB\tMace\tSPIKCLUB\tSpiked Club\tClub\t4\t20\t3\t6\t0\t0\t18\t0\t0\t\tNONE\tNull\tfalse\t225\r\n\t1\tWeapon\tOne-handed\tCLUB\tMace\tSPIKCLUB\tClub\tClub\t1\t20\t1\t6\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t20\r\n\t1\tWeapon\tOne-handed\tFLAIL\tMace\tFLAIL\tFlail\tFlail\t7\t36\t2\t12\t0\t0\t30\t0\t0\t\tNONE\tNull\tfalse\t500\r\n\t1\tWeapon\tTwo-handed\tMAUL\tMace\tMAUL\tMaul\tMaul\t10\t50\t6\t20\t0\t0\t55\t0\t0\t\tNONE\tNull\tfalse\t900\r\n\t2\tWeapon\tTwo-handed\tSHORT_BOW\tBow\tSHORTBOW\tShort Bow\tBow\t1\t30\t1\t4\t0\t0\t0\t0\t0\t\tNONE\tNull\tfalse\t100\r\n\t2\tWeapon\tTwo-handed\tHUNTERS_BOW\tBow\tHUNTBOW\tHunter's Bow\tBow\t3\t40\t2\t5\t0\t0\t20\t0\t35\t\tNONE\tNull\tfalse\t350\r\n\t2\tWeapon\tTwo-handed\tHUNTERS_BOW\tBow\tLONGBOW\tLong Bow\tBow\t5\t35\t1\t6\t0\t0\t25\t0\t30\t\tNONE\tNull\tfalse\t250\r\n\t2\tWeapon\tTwo-handed\tCOMPOSITE_BOW\tBow\tCOMPBOW\tComposite Bow\tBow\t7\t45\t3\t6\t0\t0\t25\t0\t40\t\tNONE\tNull\tfalse\t600\r\nIDI_SHORT_BATTLE_BOW\t2\tWeapon\tTwo-handed\tSHORT_BATTLE_BOW\tBow\tNONE\tShort Battle Bow\tBow\t9\t45\t3\t7\t0\t0\t30\t0\t50\t\tNONE\tNull\tfalse\t750\r\n\t2\tWeapon\tTwo-handed\tLONG_BATTLE_BOW\tBow\tBATTLEBOW\tLong Battle Bow\tBow\t11\t50\t1\t10\t0\t0\t30\t0\t60\t\tNONE\tNull\tfalse\t1000\r\n\t2\tWeapon\tTwo-handed\tSHORT_WAR_BOW\tBow\tNONE\tShort War Bow\tBow\t15\t55\t4\t8\t0\t0\t35\t0\t70\t\tNONE\tNull\tfalse\t1500\r\n\t2\tWeapon\tTwo-handed\tLONG_WAR_BOW\tBow\tWARBOW\tLong War Bow\tBow\t19\t60\t1\t14\t0\t0\t45\t0\t80\t\tNONE\tNull\tfalse\t2000\r\n\t1\tWeapon\tTwo-handed\tSHORT_STAFF\tStaff\tSHORTSTAFF\tShort Staff\tStaff\t1\t25\t2\t4\t0\t0\t0\t0\t0\t\tSTAFF\tNull\tfalse\t30\r\n\t1\tWeapon\tTwo-handed\tLONG_STAFF\tStaff\tLONGSTAFF\tLong Staff\tStaff\t4\t35\t4\t8\t0\t0\t0\t0\t0\t\tSTAFF\tNull\tfalse\t100\r\n\t1\tWeapon\tTwo-handed\tCOMPOSITE_STAFF\tStaff\tCOMPSTAFF\tComposite Staff\tStaff\t6\t45\t5\t10\t0\t0\t0\t0\t0\t\tSTAFF\tNull\tfalse\t500\r\n\t1\tWeapon\tTwo-handed\tSHORT_STAFF\tStaff\tQUARSTAFF\tQuarter Staff\tStaff\t9\t55\t6\t12\t0\t0\t20\t0\t0\t\tSTAFF\tNull\tfalse\t1000\r\n\t1\tWeapon\tTwo-handed\tWAR_STAFF\tStaff\tWARSTAFF\tWar Staff\tStaff\t12\t75\t8\t16\t0\t0\t30\t0\t0\t\tSTAFF\tNull\tfalse\t1500\r\n\t1\tMisc\tRing\tRING\tRing\tRING\tRing\tRing\t5\t0\t0\t0\t0\t0\t0\t0\t0\t\tRING\tNull\tfalse\t1000\r\n\t1\tMisc\tRing\tRING\tRing\tRING\tRing\tRing\t10\t0\t0\t0\t0\t0\t0\t0\t0\t\tRING\tNull\tfalse\t1000\r\n\t1\tMisc\tRing\tRING\tRing\tRING\tRing\tRing\t15\t0\t0\t0\t0\t0\t0\t0\t0\t\tRING\tNull\tfalse\t1000\r\n\t1\tMisc\tAmulet\tAMULET\tAmulet\tAMULET\tAmulet\tAmulet\t8\t0\t0\t0\t0\t0\t0\t0\t0\t\tAMULET\tNull\tfalse\t1200\r\n\t1\tMisc\tAmulet\tAMULET\tAmulet\tAMULET\tAmulet\tAmulet\t16\t0\t0\t0\t0\t0\t0\t0\t0\t\tAMULET\tNull\tfalse\t1200\r\n\t1\tMisc\tUnequippable\tRUNE_OF_FIRE\tMisc\tNONE\tRune of Fire\tRune\t1\t0\t0\t0\t0\t0\t0\t0\t0\t\tRUNEF\tNull\ttrue\t100\r\n\t1\tMisc\tUnequippable\tRUNE_OF_LIGHTNING\tMisc\tNONE\tRune of Lightning\tRune\t3\t0\t0\t0\t0\t0\t0\t13\t0\t\tRUNEL\tNull\ttrue\t200\r\n\t1\tMisc\tUnequippable\tGREATER_RUNE_OF_FIRE\tMisc\tNONE\tGreater Rune of Fire\tRune\t7\t0\t0\t0\t0\t0\t0\t42\t0\t\tGR_RUNEF\tNull\ttrue\t400\r\n\t1\tMisc\tUnequippable\tGREATER_RUNE_OF_LIGHTNING\tMisc\tNONE\tGreater Rune of Lightning\tRune\t7\t0\t0\t0\t0\t0\t0\t42\t0\t\tGR_RUNEL\tNull\ttrue\t500\r\n\t1\tMisc\tUnequippable\tRUNE_OF_STONE\tMisc\tNONE\tRune of Stone\tRune\t7\t0\t0\t0\t0\t0\t0\t25\t0\t\tRUNES\tNull\ttrue\t300\r\n\t0\tWeapon\tTwo-handed\tSHORT_STAFF\tStaff\tNONE\tShort Staff of Charged Bolt\t\t1\t25\t2\t4\t0\t0\t0\t25\t0\t\tSTAFF\tChargedBolt\tfalse\t470\r\nIDI_ARENAPOT\t0\tMisc\tUnequippable\tARENA_POTION\tMisc\tNONE\tArena Potion\t\t7\t0\t0\t0\t0\t0\t0\t0\t0\t\tARENAPOT\tNull\ttrue\t0\r\n"
  },
  {
    "path": "assets/txtdata/items/unique_itemdat.tsv",
    "content": "name\tcursorGraphic\tuniqueBaseItem\tminLevel\tvalue\tpower0\tpower0.value1\tpower0.value2\tpower1\tpower1.value1\tpower1.value2\tpower2\tpower2.value1\tpower2.value2\tpower3\tpower3.value1\tpower3.value2\tpower4\tpower4.value1\tpower4.value2\tpower5\tpower5.value1\tpower5.value2\r\nThe Butcher's Cleaver\t\tCLEAVER\t1\t3650\tSTR\t10\t10\tSETDAM\t4\t24\tSETDUR\t10\t10\t\t\t\t\t\t\t\t\t\r\nThe Undead Crown\tHELM_OF_SPIRITS\tSKCROWN\t1\t16650\tRNDSTEALLIFE\t\t\tSETAC\t8\t8\t\t\t\t\t\t\t\t\t\t\t\t\r\nEmpyrean Band\t\tINFRARING\t1\t8000\tATTRIBS\t2\t2\tLIGHT\t2\t2\tFASTRECOVER\t1\t1\tABSHALFTRAP\t\t\t\t\t\t\t\t\r\nOptic Amulet\t\tOPTAMULET\t1\t9750\tLIGHT\t2\t2\tLIGHTRES\t20\t20\tGETHIT\t1\t1\tMAG\t5\t5\t\t\t\t\t\t\r\nRing of Truth\t\tTRING\t1\t9100\tLIFE\t10\t10\tGETHIT\t1\t1\tALLRES\t10\t10\t\t\t\t\t\t\t\t\t\r\nHarlequin Crest\t\tHARCREST\t1\t4000\tAC_CURSE\t3\t3\tGETHIT\t1\t1\tATTRIBS\t2\t2\tLIFE\t7\t7\tMANA\t7\t7\t\t\t\r\nVeil of Steel\t\tSTEELVEIL\t1\t63800\tALLRES\t50\t50\tLIGHT_CURSE\t2\t2\tACP\t60\t60\tMANA_CURSE\t30\t30\tSTR\t15\t15\tVIT\t15\t15\r\nArkaine's Valor\t\tARMOFVAL\t1\t42000\tSETAC\t25\t25\tVIT\t10\t10\tGETHIT\t3\t3\tFASTRECOVER\t3\t3\t\t\t\t\t\t\r\nGriswold's Edge\t\tGRISWOLD\t1\t42000\tFIREDAM\t1\t10\tTOHIT\t25\t25\tFASTATTACK\t2\t2\tKNOCKBACK\t\t\tMANA\t20\t20\tLIFE_CURSE\t20\t20\r\nLightforge\t\tLGTFORGE\t1\t26675\tLIGHT\t4\t4\tDAMP\t150\t150\tTOHIT\t25\t25\tFIREDAM\t10\t20\tINDESTRUCTIBLE\t\t\tATTRIBS\t8\t8\r\nThe Rift Bow\t\tSHORTBOW\t1\t1800\tRNDARROWVEL\t\t\tDAMMOD\t2\t2\tDEX_CURSE\t3\t3\t\t\t\t\t\t\t\t\t\r\nThe Needler\tTHE_NEEDLER\tSHORTBOW\t2\t8900\tTOHIT\t50\t50\tSETDAM\t1\t3\tFASTATTACK\t2\t2\t\t\t\t\t\t\t\t\t\r\nThe Celestial Bow\tCOMPOSITE_BOW\tLONGBOW\t2\t1200\tNOMINSTR\t\t\tDAMMOD\t2\t2\tSETAC\t5\t5\t\t\t\t\t\t\t\t\t\r\nDeadly Hunter\tDEADLY_HUNTER\tCOMPBOW\t3\t8750\t3XDAMVDEM\t\t\tTOHIT\t20\t20\tMAG_CURSE\t5\t5\t\t\t\t\t\t\t\t\t\r\nBow of the Dead\tDEADLY_HUNTER\tCOMPBOW\t5\t2500\tTOHIT\t10\t10\tDEX\t4\t4\tVIT_CURSE\t3\t3\tLIGHT_CURSE\t2\t2\tSETDUR\t30\t30\t\t\t\r\nThe Blackoak Bow\t\tLONGBOW\t5\t2500\tDEX\t10\t10\tVIT_CURSE\t10\t10\tDAMP\t50\t50\tLIGHT_CURSE\t1\t1\t\t\t\t\t\t\r\nFlamedart\t\tHUNTBOW\t10\t14250\tFIRE_ARROWS\t1\t6\tTOHIT\t20\t20\tFIRERES\t40\t40\t\t\t\t\t\t\t\t\t\r\nFleshstinger\t\tLONGBOW\t13\t16500\tDEX\t15\t15\tTOHIT\t40\t40\tDAMP\t80\t80\tDUR\t6\t6\t\t\t\t\t\t\r\nWindforce\tWINDFORCE\tWARBOW\t17\t37750\tSTR\t5\t5\tDAMP\t200\t200\tKNOCKBACK\t\t\t\t\t\t\t\t\t\t\t\r\nEaglehorn\tDEADLY_HUNTER\tBATTLEBOW\t26\t42500\tDEX\t20\t20\tTOHIT\t50\t50\tDAMP\t100\t100\tINDESTRUCTIBLE\t\t\t\t\t\t\t\t\r\nGonnagal's Dirk\tGONNAGALS_DIRK\tDAGGER\t1\t7040\tDEX_CURSE\t5\t5\tDAMMOD\t4\t4\tFASTATTACK\t2\t2\tFIRERES\t25\t25\t\t\t\t\t\t\r\nThe Defender\t\tSABRE\t1\t2000\tSETAC\t5\t5\tVIT\t5\t5\tTOHIT_CURSE\t5\t5\t\t\t\t\t\t\t\t\t\r\nGryphon's Claw\tGRYPHONS_CLAW\tFALCHION\t1\t1000\tDAMP\t100\t100\tMAG_CURSE\t2\t2\tDEX_CURSE\t5\t5\t\t\t\t\t\t\t\t\t\r\nBlack Razor\tBLACK_RAZOR\tDAGGER\t1\t2000\tDAMP\t150\t150\tVIT\t2\t2\tSETDUR\t5\t5\t\t\t\t\t\t\t\t\t\r\nGibbous Moon\t\tBROADSWR\t2\t6660\tATTRIBS\t2\t2\tDAMP\t25\t25\tMANA\t15\t15\tLIGHT_CURSE\t3\t3\t\t\t\t\t\t\r\nIce Shank\t\tLONGSWR\t3\t5250\tFIRERES\t40\t40\tSETDUR\t15\t15\tSTR\t5\t10\t\t\t\t\t\t\t\t\t\r\nThe Executioner's Blade\tTHE_EXECUTIONERS_BLADE\tFALCHION\t3\t7080\tDAMP\t150\t150\tLIFE_CURSE\t10\t10\tLIGHT_CURSE\t1\t1\tDUR\t200\t200\t\t\t\t\t\t\r\nThe Bonesaw\t\tCLAYMORE\t6\t4400\tDAMMOD\t10\t10\tSTR\t10\t10\tMAG_CURSE\t5\t5\tDEX_CURSE\t5\t5\tLIFE\t10\t10\tMANA_CURSE\t10\t10\r\nShadowhawk\t\tBROADSWR\t8\t13750\tLIGHT_CURSE\t2\t2\tSTEALLIFE\t5\t5\tTOHIT\t15\t15\tALLRES\t5\t5\t\t\t\t\t\t\r\nWizardspike\tWIZARDSPIKE\tDAGGER\t11\t12920\tMAG\t15\t15\tMANA\t35\t35\tTOHIT\t25\t25\tALLRES\t15\t15\t\t\t\t\t\t\r\nLightsabre\t\tSABRE\t13\t19150\tLIGHT\t2\t2\tLIGHTDAM\t1\t10\tTOHIT\t20\t20\tLIGHTRES\t50\t50\t\t\t\t\t\t\r\nThe Falcon's Talon\tGRYPHONS_CLAW\tSCIMITAR\t15\t7867\tFASTATTACK\t4\t4\tTOHIT\t20\t20\tDAMP_CURSE\t33\t33\tDEX\t10\t10\t\t\t\t\t\t\r\nInferno\t\tLONGSWR\t17\t34600\tFIREDAM\t2\t12\tLIGHT\t3\t3\tMANA\t20\t20\tFIRERES\t80\t80\t\t\t\t\t\t\r\nDoombringer\t\tBASTARDSWR\t19\t18250\tTOHIT\t25\t25\tDAMP\t250\t250\tATTRIBS_CURSE\t5\t5\tLIFE_CURSE\t25\t25\tLIGHT_CURSE\t2\t2\t\t\t\r\nThe Grizzly\tTHE_GRIZZLY\tTWOHANDSWR\t23\t50000\tSTR\t20\t20\tVIT_CURSE\t5\t5\tDAMP\t200\t200\tKNOCKBACK\t\t\tDUR\t100\t100\t\t\t\r\nThe Grandfather\tTHE_GRANDFATHER\tGREATSWR\t27\t119800\tONEHAND\t\t\tATTRIBS\t5\t5\tTOHIT\t20\t20\tDAMP\t70\t70\tLIFE\t20\t20\t\t\t\r\nThe Mangler\tAXE\tLARGEAXE\t2\t2850\tDAMP\t200\t200\tDEX_CURSE\t5\t5\tMAG_CURSE\t5\t5\tMANA_CURSE\t10\t10\t\t\t\t\t\t\r\nSharp Beak\tGREAT_AXE\tLARGEAXE\t2\t2850\tLIFE\t20\t20\tMAG_CURSE\t10\t10\tMANA_CURSE\t10\t10\t\t\t\t\t\t\t\t\t\r\nBloodslayer\tAXE\tBROADAXE\t3\t2500\tDAMP\t100\t100\t3XDAMVDEM\t\t\tATTRIBS_CURSE\t5\t5\tSPLLVLADD\t-1\t-1\t\t\t\t\t\t\r\nThe Celestial Axe\t\tBATTLEAXE\t4\t14100\tNOMINSTR\t\t\tTOHIT\t15\t15\tLIFE\t15\t15\tSTR_CURSE\t15\t15\t\t\t\t\t\t\r\nWicked Axe\tGREAT_AXE\tLARGEAXE\t5\t31150\tTOHIT\t30\t30\tDEX\t10\t10\tVIT_CURSE\t10\t10\tGETHIT\t1\t6\tINDESTRUCTIBLE\t\t\t\t\t\r\nStonecleaver\tSTONECLEAVER\tBROADAXE\t7\t23900\tLIFE\t30\t30\tTOHIT\t20\t20\tDAMP\t50\t50\tLIGHTRES\t40\t40\t\t\t\t\t\t\r\nAguinara's Hatchet\t\tSMALLAXE\t12\t24800\tSPLLVLADD\t1\t1\tMAG\t10\t10\tMAGICRES\t80\t80\t\t\t\t\t\t\t\t\t\r\nHellslayer\t\tBATTLEAXE\t15\t26200\tSTR\t8\t8\tVIT\t8\t8\tDAMP\t100\t100\tLIFE\t25\t25\tMANA_CURSE\t25\t25\t\t\t\r\nMesserschmidt's Reaver\tMESSERSCHMIDTS_REAVER\tGREATAXE\t25\t58000\tDAMP\t200\t200\tDAMMOD\t15\t15\tATTRIBS\t5\t5\tLIFE_CURSE\t50\t50\tFIREDAM\t2\t12\t\t\t\r\nCrackrust\t\tMACE\t1\t11375\tATTRIBS\t2\t2\tINDESTRUCTIBLE\t\t\tALLRES\t15\t15\tDAMP\t50\t50\tSPLLVLADD\t-1\t-1\t\t\t\r\nHammer of Jholm\t\tMAUL\t1\t8700\tSETDAM\t4\t10\tINDESTRUCTIBLE\t\t\tSTR\t3\t3\tTOHIT\t15\t15\t\t\t\t\t\t\r\nCiverb's Cudgel\t\tMACE\t1\t2000\t3XDAMVDEM\t\t\tDEX_CURSE\t5\t5\tMAG_CURSE\t2\t2\t\t\t\t\t\t\t\t\t\r\nThe Celestial Star\t\tFLAIL\t2\t7810\tNOMINSTR\t\t\tLIGHT\t2\t2\tDAMMOD\t10\t10\tAC_CURSE\t8\t8\t\t\t\t\t\t\r\nBaranar's Star\t\tMORNSTAR\t5\t6850\tTOHIT\t12\t12\tDAMP\t80\t80\tFASTATTACK\t1\t1\tVIT\t4\t4\tDEX_CURSE\t4\t4\tSETDUR\t60\t60\r\nGnarled Root\t\tSPIKCLUB\t9\t9820\tTOHIT\t20\t20\tDAMP\t300\t300\tDEX\t10\t10\tMAG\t5\t5\tALLRES\t10\t10\tAC_CURSE\t10\t10\r\nThe Cranium Basher\t\tMAUL\t12\t36500\tDAMMOD\t20\t20\tSTR\t15\t15\tINDESTRUCTIBLE\t\t\tMANA_CURSE\t150\t150\tALLRES\t5\t5\t\t\t\r\nSchaefer's Hammer\t\tWARHAMMER\t16\t56125\tDAMP_CURSE\t100\t100\tLIGHTDAM\t1\t50\tLIFE\t50\t50\tTOHIT\t30\t30\tLIGHTRES\t80\t80\tLIGHT\t1\t1\r\nDreamflange\t\tMACE\t26\t26450\tMAG\t30\t30\tMANA\t50\t50\tMAGICRES\t50\t50\tLIGHT\t2\t2\tSPLLVLADD\t1\t1\t\t\t\r\nStaff of Shadows\t\tLONGSTAFF\t2\t1250\tMAG_CURSE\t10\t10\tTOHIT\t10\t10\tDAMP\t60\t60\tLIGHT_CURSE\t2\t2\tFASTATTACK\t1\t1\t\t\t\r\nImmolator\t\tLONGSTAFF\t4\t3900\tFIRERES\t20\t20\tFIREDAM\t4\t4\tMANA\t10\t10\tVIT_CURSE\t5\t5\t\t\t\t\t\t\r\nStorm Spire\t\tWARSTAFF\t8\t22500\tLIGHTRES\t50\t50\tLIGHTDAM\t2\t8\tSTR\t10\t10\tMAG_CURSE\t10\t10\t\t\t\t\t\t\r\nGleamsong\t\tSHORTSTAFF\t8\t6520\tMANA\t25\t25\tSTR_CURSE\t3\t3\tVIT_CURSE\t3\t3\tSPELL\t10\t76\t\t\t\t\t\t\r\nThundercall\t\tCOMPSTAFF\t14\t22250\tTOHIT\t35\t35\tLIGHTDAM\t1\t10\tSPELL\t3\t76\tLIGHTRES\t30\t30\tLIGHT\t2\t2\t\t\t\r\nThe Protector\tTHE_PROTECTOR\tSHORTSTAFF\t16\t17240\tVIT\t5\t5\tGETHIT\t5\t5\tSETAC\t40\t40\tSPELL\t2\t86\tTHORNS\t1\t3\t\t\t\r\nNaj's Puzzler\t\tLONGSTAFF\t18\t34000\tMAG\t20\t20\tDEX\t10\t10\tALLRES\t20\t20\tSPELL\t23\t57\tLIFE_CURSE\t25\t25\t\t\t\r\nMindcry\t\tQUARSTAFF\t20\t41500\tMAG\t15\t15\tSPELL\t13\t69\tALLRES\t15\t15\tSPLLVLADD\t1\t1\t\t\t\t\t\t\r\nRod of Onan\t\tWARSTAFF\t22\t44167\tSPELL\t21\t50\tDAMP\t100\t100\tATTRIBS\t5\t5\t\t\t\t\t\t\t\t\t\r\nHelm of Spirits\tHELM_OF_SPIRITS\tHELM\t1\t7525\tSTEALLIFE\t5\t5\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nThinking Cap\tTHINKING_CAP\tSKULLCAP\t6\t2020\tMANA\t30\t30\tSPLLVLADD\t2\t2\tALLRES\t20\t20\tSETDUR\t1\t1\t\t\t\t\t\t\r\nOverLord's Helm\tOVERLORDS_HELM\tHELM\t7\t12500\tSTR\t20\t20\tDEX\t15\t15\tVIT\t5\t5\tMAG_CURSE\t20\t20\tSETDUR\t15\t15\t\t\t\r\nFool's Crest\tFOOLS_CREST\tHELM\t12\t10150\tATTRIBS_CURSE\t4\t4\tLIFE\t100\t100\tGETHIT_CURSE\t1\t6\tTHORNS\t1\t3\t\t\t\t\t\t\r\nGotterdamerung\tVEIL_OF_STEEL\tGREATHELM\t21\t54900\tATTRIBS\t20\t20\tSETAC\t60\t60\tGETHIT\t4\t4\tALLRESZERO\t\t\tLIGHT_CURSE\t4\t4\t\t\t\r\nRoyal Circlet\tROYAL_CIRCLET\tCROWN\t27\t24875\tATTRIBS\t10\t10\tMANA\t40\t40\tSETAC\t40\t40\tLIGHT\t1\t1\t\t\t\t\t\t\r\nTorn Flesh of Souls\tTORN_FLESH_OF_SOULS\tRAGS\t2\t4825\tSETAC\t8\t8\tVIT\t10\t10\tGETHIT\t1\t1\tINDESTRUCTIBLE\t\t\t\t\t\t\t\t\r\nThe Gladiator's Bane\t\tSTUDARMOR\t6\t3450\tSETAC\t25\t25\tGETHIT\t2\t2\tDUR\t200\t200\tATTRIBS_CURSE\t3\t3\t\t\t\t\t\t\r\nThe Rainbow Cloak\tTHE_RAINBOW_CLOAK\tCLOAK\t2\t4900\tSETAC\t10\t10\tATTRIBS\t1\t1\tALLRES\t10\t10\tLIFE\t5\t5\tDUR\t50\t50\t\t\t\r\nLeather of Aut\t\tLEATHARMOR\t4\t10550\tSETAC\t15\t15\tSTR\t5\t5\tMAG_CURSE\t5\t5\tDEX\t5\t5\tINDESTRUCTIBLE\t\t\t\t\t\r\nWisdom's Wrap\tTHE_RAINBOW_CLOAK\tROBE\t5\t6200\tMAG\t5\t5\tMANA\t10\t10\tLIGHTRES\t25\t25\tSETAC\t15\t15\tGETHIT\t1\t1\t\t\t\r\nSparking Mail\t\tCHAINMAIL\t9\t15750\tSETAC\t30\t30\tLIGHTDAM\t1\t10\t\t\t\t\t\t\t\t\t\t\t\t\r\nScavenger Carapace\t\tBREASTPLATE\t13\t14000\tGETHIT\t15\t15\tAC_CURSE\t30\t30\tDEX\t5\t5\tLIGHTRES\t40\t40\t\t\t\t\t\t\r\nNightscape\tTHE_RAINBOW_CLOAK\tCAPE\t16\t11600\tFASTRECOVER\t2\t2\tLIGHT_CURSE\t4\t4\tSETAC\t15\t15\tDEX\t3\t3\tALLRES\t20\t20\t\t\t\r\nNaj's Light Plate\tNAJS_LIGHT_PLATE\tPLATEMAIL\t19\t78700\tNOMINSTR\t\t\tMAG\t5\t5\tMANA\t20\t20\tALLRES\t20\t20\tSPLLVLADD\t1\t1\t\t\t\r\nDemonspike Coat\t\tFULLPLATE\t25\t251175\tSETAC\t100\t100\tGETHIT\t6\t6\tSTR\t10\t10\tINDESTRUCTIBLE\t\t\tFIRERES\t50\t50\t\t\t\r\nThe Deflector\t\tBUCKLER\t1\t1500\tSETAC\t7\t7\tALLRES\t10\t10\tDAMP_CURSE\t20\t20\tTOHIT_CURSE\t5\t5\t\t\t\t\t\t\r\nSplit Skull Shield\tSPLIT_SKULL_SHIELD\tBUCKLER\t1\t2025\tSETAC\t10\t10\tLIFE\t10\t10\tSTR\t2\t2\tLIGHT_CURSE\t1\t1\tSETDUR\t15\t15\t\t\t\r\nDragon's Breach\tDRAGONS_BREACH\tKITESHIELD\t2\t19200\tFIRERES\t25\t25\tSTR\t5\t5\tSETAC\t20\t20\tMAG_CURSE\t5\t5\tINDESTRUCTIBLE\t\t\t\t\t\r\nBlackoak Shield\tBLACKOAK_SHIELD\tSMALLSHIELD\t4\t5725\tDEX\t10\t10\tVIT_CURSE\t10\t10\tSETAC\t18\t18\tLIGHT_CURSE\t1\t1\tDUR\t150\t150\t\t\t\r\nHoly Defender\tBLACKOAK_SHIELD\tLARGESHIELD\t10\t13800\tSETAC\t15\t15\tGETHIT\t2\t2\tFIRERES\t20\t20\tDUR\t200\t200\tFASTBLOCK\t1\t1\t\t\t\r\nStormshield\tGOTHIC_SHIELD\tGOTHSHIELD\t24\t49000\tSETAC\t40\t40\tGETHIT_CURSE\t4\t4\tSTR\t10\t10\tINDESTRUCTIBLE\t\t\tFASTBLOCK\t1\t1\tLIGHTRES\t50\t50\r\nBramble\tBRAMBLE\tRING\t1\t1000\tATTRIBS_CURSE\t2\t2\tDAMMOD\t3\t3\tMANA\t10\t10\t\t\t\t\t\t\t\t\t\r\nRing of Regha\tRING_OF_REGHA\tRING\t1\t4175\tMAG\t10\t10\tMAGICRES\t10\t10\tLIGHT\t1\t1\tSTR_CURSE\t3\t3\tDEX_CURSE\t3\t3\t\t\t\r\nThe Bleeder\tTHE_BLEEDER\tRING\t2\t8500\tMAGICRES\t20\t20\tMANA\t30\t30\tLIFE_CURSE\t10\t10\t\t\t\t\t\t\t\t\t\r\nConstricting Ring\tCONSTRICTING_RING\tRING\t5\t62000\tALLRES\t75\t75\tDRAINLIFE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nRing of Engagement\tRING_OF_ENGAGEMENT\tRING\t11\t12476\tGETHIT\t1\t2\tTHORNS\t1\t3\tSETAC\t5\t5\tTARGAC\t2\t2\t\t\t\t\t\t\r\n"
  },
  {
    "path": "assets/txtdata/missiles/misdat.tsv",
    "content": "id\taddFn\tprocessFn\tcastSound\thitSound\tgraphic\tflags\tmovementDistribution\r\nArrow\tAddArrow\tProcessArrow\t\t\tArrow\tPhysical,Arrow\tBlockable\r\nFirebolt\tAddFirebolt\tProcessGenericProjectile\tSpellFirebolt\tSpellFireHit\tFireball\tFire\tBlockable\r\nGuardian\tAddGuardian\tProcessGuardian\tSpellGuardian\t\tGuardian\tPhysical\t\r\nPhasing\tAddPhasing\tProcessTeleport\tSpellTeleport\t\t\tPhysical,Invisible\t\r\nNovaBall\tAddNovaBall\tProcessNovaBall\t\t\tLightning\tLightning\tUnblockable\r\nFireWall\tAddFireWall\tProcessFireWall\tSpellFireWall\tSpellFireHit\tFireWall\tFire\t\r\nFireball\tAddFireball\tProcessFireball\tSpellFirebolt\tSpellFireHit\tFireball\tFire\tBlockable\r\nLightningControl\tAddLightningControl\tProcessLightningControl\t\t\tLightning\tLightning,Invisible\t\r\nLightning\tAddLightning\tProcessLightning\tSpellLightning\tSpellLightningHit\tLightning\tLightning\t\r\nMagmaBallExplosion\tAddMissileExplosion\tProcessMissileExplosion\t\t\tMagmaBallExplosion\tPhysical\t\r\nTownPortal\tAddTownPortal\tProcessTownPortal\tSpellPortal\t\tTownPortal\tMagic\t\r\nFlashBottom\tAddFlashBottom\tProcessFlashBottom\tSpellNova\tSpellLightningHit\tFlashBottom\tMagic\t\r\nFlashTop\tAddFlashTop\tProcessFlashTop\t\t\tFlashTop\tMagic\t\r\nManaShield\tAddManaShield\t\tSpellManaShield\t\tManaShield\tMagic,Invisible\t\r\nFlameWave\tAddFlameWave\tProcessFlameWave\t\t\tFireWall\tFire\tUnblockable\r\nChainLightning\tAddChainLightning\tProcessChainLightning\tSpellLightning\tSpellLightningHit\tLightning\tLightning\t\r\nChainBall\t\t\t\t\tLightning\tLightning\t\r\nBloodHit\t\t\tSpellBloodStar\tSpellBloodStarHit\tBloodHit\tPhysical\t\r\nBoneHit\t\t\t\t\tBoneHit\tPhysical\t\r\nMetalHit\t\t\t\t\tMetalHit\tPhysical\t\r\nRhino\tAddRhino\tProcessRhino\t\t\t\tPhysical\tBlockable\r\nMagmaBall\tAddMagmaBall\tProcessGenericProjectile\t\t\tMagmaBall\tFire\tBlockable\r\nThinLightningControl\tAddLightningControl\tProcessLightningControl\t\t\tThinLightning\tLightning,Invisible\t\r\nThinLightning\tAddLightning\tProcessLightning\t\t\tThinLightning\tLightning\t\r\nBloodStar\tAddGenericMagicMissile\tProcessGenericProjectile\t\t\tBloodStar\tMagic\tBlockable\r\nBloodStarExplosion\tAddMissileExplosion\tProcessMissileExplosion\t\t\tBloodStarExplosion\tMagic\t\r\nTeleport\tAddTeleport\tProcessTeleport\tSpellElemental\t\t\tPhysical,Invisible\t\r\nFireArrow\tAddElementalArrow\tProcessElementalArrow\t\t\tFireArrow\tFire,Arrow\tBlockable\r\nDoomSerpents\t\t\tSpellDoomSerpents\t\tDoomSerpents\tMagic,Invisible\t\r\nFireOnly\t\t\t\t\tFireWall\tFire\t\r\nStoneCurse\tAddStoneCurse\tProcessStoneCurse\tSpellStoneCurse\t\t\tMagic,Invisible\t\r\nBloodRitual\t\t\t\t\t\tPhysical\t\r\nInvisibility\t\t\tSpellInvisibility\t\t\tPhysical,Invisible\t\r\nGolem\tAddGolem\t\tSpellGolem\t\t\tPhysical,Invisible\t\r\nEtherealize\t\t\tSpellEtherealize\t\tEtherealize\tPhysical\t\r\nSpurt\t\t\t\t\tSpurt\tPhysical\t\r\nApocalypseBoom\tAddApocalypseBoom\tProcessApocalypseBoom\t\t\tApocalypseBoom\tPhysical\t\r\nHealing\tAddHealing\t\t\t\t\tPhysical,Invisible\t\r\nFireWallControl\tAddWallControl\tProcessWallControl\t\t\tFireWall\tFire,Invisible\t\r\nInfravision\tAddInfravision\tProcessInfravision\tSpellInfravision\t\t\tPhysical,Invisible\t\r\nIdentify\tAddIdentify\t\t\t\t\tPhysical,Invisible\t\r\nFlameWaveControl\tAddFlameWaveControl\tProcessFlameWaveControl\tSpellFlameWave\t\tFireWall\tFire\t\r\nNova\tAddNova\tProcessNova\tSpellNova\t\tLightning\tLightning\t\r\nRage\tAddRage\tProcessRage\t\t\t\tPhysical,Invisible\t\r\nApocalypse\tAddApocalypse\tProcessApocalypse\tSpellApocalypse\t\tApocalypseBoom\tMagic\t\r\nItemRepair\tAddItemRepair\t\t\t\t\tPhysical,Invisible\t\r\nStaffRecharge\tAddStaffRecharge\t\t\t\t\tPhysical,Invisible\t\r\nTrapDisarm\tAddTrapDisarm\t\tSpellTrapDisarm\t\t\tPhysical,Invisible\t\r\nInferno\tAddInferno\tProcessInferno\tSpellInferno\t\tInferno\tFire\t\r\nInfernoControl\tAddInfernoControl\tProcessInfernoControl\t\t\t\tFire,Invisible\t\r\nFireMan\t\t\t\t\t\tPhysical\tBlockable\r\nKrull\t\t\t\t\tKrull\tFire,Arrow\tBlockable\r\nChargedBolt\tAddChargedBolt\tProcessChargedBolt\tSpellChargedBolt\t\tChargedBolt\tLightning\tBlockable\r\nHolyBolt\tAddHolyBolt\tProcessHolyBolt\tSpellHolyBolt\tSpellLightningHit\tHolyBolt\tPhysical\tBlockable\r\nResurrect\tAddResurrect\t\t\tSpellResurrect\t\tMagic,Invisible\t\r\nTelekinesis\tAddTelekinesis\t\tSpellEtherealize\t\t\tPhysical,Invisible\t\r\nLightningArrow\tAddElementalArrow\tProcessElementalArrow\t\t\tLightningArrow\tLightning,Arrow\tBlockable\r\nAcid\tAddAcid\tProcessGenericProjectile\tSpellAcid\t\tAcid\tAcid\tBlockable\r\nAcidSplat\tAddMissileExplosion\tProcessAcidSplate\t\t\tAcidSplat\tAcid\t\r\nAcidPuddle\tAddAcidPuddle\tProcessAcidPuddle\tSpellPuddle\t\tAcidPuddle\tAcid\t\r\nHealOther\tAddHealOther\t\t\t\t\tPhysical,Invisible\t\r\nElemental\tAddElemental\tProcessElemental\tSpellElemental\t\tElemental\tFire\tUnblockable\r\nResurrectBeam\tAddResurrectBeam\tProcessResurrectBeam\t\t\tResurrect\tPhysical\t\r\nBoneSpirit\tAddBoneSpirit\tProcessBoneSpirit\tSpellBoneSpirit\tSpellBoneSpiritHit\tBoneSpirit\tMagic\tBlockable\r\nWeaponExplosion\tAddWeaponExplosion\tProcessWeaponExplosion\t\t\t\tPhysical\t\r\nRedPortal\tAddRedPortal\tProcessRedPortal\tSpellPortal\t\tRedPortal\tPhysical\t\r\nDiabloApocalypseBoom\tAddApocalypseBoom\tProcessApocalypseBoom\t\t\tDiabloApocalypseBoom\tPhysical\t\r\nDiabloApocalypse\tAddDiabloApocalypse\t\t\t\t\tPhysical,Invisible\t\r\n"
  },
  {
    "path": "assets/txtdata/missiles/missile_sprites.tsv",
    "content": "id\twidth\twidth2\tname\tnumFrames\tflags\tframeDelay\tframeLength\r\nArrow\t96\t16\tarrows\t1\tNotAnimated\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nFireball\t96\t16\tfireba\t16\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14\r\nGuardian\t96\t16\tguard\t3\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t15,14,3,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nLightning\t96\t16\tlghning\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nFireWall\t128\t32\tfirewal\t2\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t13,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nMagmaBallExplosion\t128\t32\tmagblos\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10\r\nTownPortal\t96\t16\tportal\t2\t\t0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nFlashBottom\t160\t48\tbluexfr\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19\r\nFlashTop\t160\t48\tbluexbk\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19\r\nManaShield\t96\t16\tmanashld\t1\tNotAnimated\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\r\nBloodHit\t96\t16\t\t4\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nBoneHit\t128\t32\t\t3\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nMetalHit\t96\t16\t\t3\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2\t10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10\r\nFireArrow\t96\t16\tfarrow\t16\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4\r\nDoomSerpents\t96\t16\tdoom\t9\tMonsterOwned\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nGolem\t0\t0\t\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nSpurt\t128\t32\t\t2\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nApocalypseBoom\t96\t16\tnewexp\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nStoneCurseShatter\t128\t32\tshatter1\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12\r\nBigExplosion\t160\t48\tbigexp\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nInferno\t96\t16\tinferno\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20\r\nThinLightning\t96\t16\tthinlght\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nBloodStar\t128\t32\tflare\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarExplosion\t128\t32\tflareexp\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\r\nMagmaBall\t128\t32\tmagball\t8\tMonsterOwned\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nKrull\t96\t16\tkrull\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14\r\nChargedBolt\t64\t0\tminiltng\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nHolyBolt\t96\t16\tholy\t16\t\t1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14\r\nHolyBoltExplosion\t160\t48\tholyexpl\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nLightningArrow\t96\t16\tlarrow\t16\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4\r\nFireArrowExplosion\t64\t0\t\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\nAcid\t96\t16\tacidbf\t16\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nAcidSplat\t96\t16\tacidspla\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nAcidPuddle\t96\t16\tacidpud\t2\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nEtherealize\t96\t16\t\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\r\nElemental\t96\t16\tfirerun\t8\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12\r\nResurrect\t96\t16\tressur1\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBoneSpirit\t96\t16\tsklball\t9\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t16,16,16,16,16,16,16,16,8,0,0,0,0,0,0,0\r\nRedPortal\t96\t16\trportal\t2\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nDiabloApocalypseBoom\t160\t48\tfireplar\t1\tMonsterOwned\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17\r\nBloodStarBlue\t96\t16\tscubmisb\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarBlueExplosion\t128\t32\tscbsexpb\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\nBloodStarYellow\t96\t16\tscubmisc\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarYellowExplosion\t128\t32\tscbsexpc\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\nBloodStarRed\t96\t16\tscubmisd\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarRedExplosion\t128\t32\tscbsexpd\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\n"
  },
  {
    "path": "assets/txtdata/monsters/monstdat.tsv",
    "content": "_monster_id\tname\tassetsSuffix\tsoundSuffix\ttrnFile\tavailability\twidth\timage\thasSpecial\thasSpecialSound\tframes[6]\trate[6]\tminDunLvl\tmaxDunLvl\tlevel\thitPointsMinimum\thitPointsMaximum\tai\tabilityFlags\tintelligence\ttoHit\tanimFrameNum\tminDamage\tmaxDamage\ttoHitSpecial\tanimFrameNumSpecial\tminDamageSpecial\tmaxDamageSpecial\treducePlayerStrength\treducePlayerMagic\treducePlayerDexterity\treducePlayerVitality\treducePlayerMaxHP\treducePlayerMaxMana\tarmorClass\tmonsterClass\tresistance\tresistanceHell\tselectionRegion\ttreasure\texp\r\nMT_NZOMBIE\tZombie\tzombie\\zombie\t\t\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t1\t2\t1\t4\t7\tZombie\t\t0\t10\t8\t2\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t54\r\nMT_BZOMBIE\tGhoul\tzombie\\zombie\t\tzombie\\bluered\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t2\t3\t2\t7\t11\tZombie\t\t1\t10\t8\t3\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t10\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t58\r\nMT_GZOMBIE\tRotting Carcass\tzombie\\zombie\t\tzombie\\grey\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t2\t4\t4\t15\t25\tZombie\t\t2\t25\t8\t5\t15\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC,RESIST_FIRE\tBottom,Middle\t\t136\r\nMT_YZOMBIE\tBlack Death\tzombie\\zombie\t\tzombie\\yellow\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t3\t5\t6\t25\t40\tZombie\t\t3\t30\t8\t6\t22\t0\t0\t0\t0\t0\t0\t0\t0\t1\t0\t20\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t240\r\nMT_RFALLSP\tFallen One\tfalspear\\phall\t\tfalspear\\fallent\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t1\t2\t1\t1\t4\tFallen\t\t0\t15\t7\t1\t3\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\tAnimal\t\t\tBottom,Middle\t\t46\r\nMT_DFALLSP\tCarver\tfalspear\\phall\t\tfalspear\\dark\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t2\t3\t3\t4\t8\tFallen\t\t2\t20\t7\t2\t5\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t5\tAnimal\t\t\tBottom,Middle\t\t80\r\nMT_YFALLSP\tDevil Kin\tfalspear\\phall\t\t\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t2\t4\t5\t12\t24\tFallen\t\t2\t25\t7\t3\t7\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t10\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t155\r\nMT_BFALLSP\tDark One\tfalspear\\phall\t\tfalspear\\blue\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t3\t5\t7\t20\t36\tFallen\t\t3\t30\t7\t4\t8\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t15\tAnimal\t\tRESIST_LIGHTNING\tBottom,Middle\t\t255\r\nMT_WSKELAX\tSkeleton\tskelaxe\\sklax\t\tskelaxe\\white\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t5,1,1,1,1,1\t1\t2\t1\t2\t4\tSkeletonMelee\t\t0\t20\t8\t1\t4\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t64\r\nMT_TSKELAX\tCorpse Axe\tskelaxe\\sklax\t\tskelaxe\\skelt\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t4,1,1,1,1,1\t2\t3\t2\t4\t7\tSkeletonMelee\t\t1\t25\t8\t3\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t68\r\nMT_RSKELAX\tBurning Dead\tskelaxe\\sklax\t\t\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t2,1,1,1,1,1\t2\t4\t4\t8\t12\tSkeletonMelee\t\t2\t30\t8\t3\t7\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t154\r\nMT_XSKELAX\tHorror\tskelaxe\\sklax\t\tskelaxe\\black\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t3,1,1,1,1,1\t3\t5\t6\t12\t20\tSkeletonMelee\t\t3\t35\t8\t4\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t264\r\nMT_RFALLSD\tFallen One\tfalsword\\fall\t\tfalsword\\fallent\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t1\t2\t1\t2\t5\tFallen\t\t0\t15\t8\t1\t4\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t10\tAnimal\t\t\tBottom,Middle\t\t52\r\nMT_DFALLSD\tCarver\tfalsword\\fall\t\tfalsword\\dark\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t2\t3\t3\t5\t9\tFallen\t\t1\t20\t8\t2\t7\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t15\tAnimal\t\t\tBottom,Middle\t\t90\r\nMT_YFALLSD\tDevil Kin\tfalsword\\fall\t\t\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t2\t4\t5\t16\t24\tFallen\t\t2\t25\t8\t4\t10\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t20\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t180\r\nMT_BFALLSD\tDark One\tfalsword\\fall\t\tfalsword\\blue\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t3\t5\t7\t24\t36\tFallen\t\t3\t30\t8\t4\t12\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t25\tAnimal\t\tRESIST_LIGHTNING\tBottom,Middle\t\t280\r\nMT_NSCAV\tScavenger\tscav\\scav\t\t\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t1\t3\t2\t3\t6\tScavenger\t\t0\t20\t7\t1\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t10\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t80\r\nMT_BSCAV\tPlague Eater\tscav\\scav\t\tscav\\scavbr\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t2\t4\t4\t12\t24\tScavenger\t\t1\t30\t7\t1\t8\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t20\tAnimal\t\tRESIST_LIGHTNING\tBottom,Middle\t\t188\r\nMT_WSCAV\tShadow Beast\tscav\\scav\t\tscav\\scavbe\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t3\t5\t6\t24\t36\tScavenger\t\t2\t35\t7\t3\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t375\r\nMT_YSCAV\tBone Gasher\tscav\\scav\t\tscav\\scavw\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t4\t6\t8\t28\t40\tScavenger\t\t3\t35\t7\t5\t15\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tRESIST_MAGIC\tRESIST_LIGHTNING\tBottom,Middle\t\t552\r\nMT_WSKELBW\tSkeleton\tskelbow\\sklbw\t\tskelbow\\white\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t4,1,1,1,1,1\t2\t3\t3\t2\t4\tSkeletonRanged\t\t0\t15\t12\t1\t2\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t110\r\nMT_TSKELBW\tCorpse Bow\tskelbow\\sklbw\t\tskelbow\\skelt\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t4,1,1,1,1,1\t2\t4\t5\t8\t16\tSkeletonRanged\t\t1\t25\t12\t1\t4\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t210\r\nMT_RSKELBW\tBurning Dead\tskelbow\\sklbw\t\t\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t2,1,1,1,1,1\t3\t5\t7\t10\t24\tSkeletonRanged\t\t2\t30\t12\t1\t6\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t364\r\nMT_XSKELBW\tHorror\tskelbow\\sklbw\t\tskelbow\\black\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t3,1,1,1,1,1\t4\t6\t9\t15\t45\tSkeletonRanged\t\t3\t35\t12\t2\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t594\r\nMT_WSKELSD\tSkeleton Captain\tskelsd\\sklsr\t\tskelsd\\white\tAlways\t128\t575\ttrue\ttrue\t13,8,12,7,15,16\t4,1,1,1,1,1\t1\t3\t2\t3\t6\tSkeletonMelee\t\t0\t20\t8\t2\t7\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t10\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t90\r\nMT_TSKELSD\tCorpse Captain\tskelsd\\sklsr\t\tskelsd\\skelt\tAlways\t128\t575\ttrue\tfalse\t13,8,12,7,15,16\t4,1,1,1,1,1\t2\t4\t4\t12\t20\tSkeletonMelee\t\t1\t30\t8\t3\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t200\r\nMT_RSKELSD\tBurning Dead Captain\tskelsd\\sklsr\t\t\tAlways\t128\t575\ttrue\tfalse\t13,8,12,7,15,16\t4,1,1,1,1,1\t3\t5\t6\t16\t30\tSkeletonMelee\t\t2\t35\t8\t4\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t393\r\nMT_XSKELSD\tHorror Captain\tskelsd\\sklsr\t\tskelsd\\black\tAlways\t128\t575\ttrue\tfalse\t13,8,12,7,15,16\t4,1,1,1,1,1\t4\t6\t8\t35\t50\tSkeletonMelee\tSEARCH\t3\t40\t8\t5\t14\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tUndead\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t604\r\nMT_INVILORD\tInvisible Lord\ttsneak\\tsneak\t\t\tNever\t128\t800\tfalse\tfalse\t13,13,15,11,16,0\t2,1,1,1,1,1\t19\t20\t14\t278\t278\tSkeletonMelee\tSEARCH,CAN_OPEN_DOOR\t3\t65\t8\t16\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t2000\r\nMT_SNEAK\tHidden\tsneak\\sneak\t\t\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t2\t5\t5\t8\t24\tSneak\tHIDDEN\t0\t35\t8\t3\t6\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tDemon\t\t\tBottom,Middle\t\t278\r\nMT_STALKER\tStalker\tsneak\\sneak\t\tsneak\\sneakv2\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t5\t7\t9\t30\t45\tSneak\tHIDDEN,SEARCH\t1\t40\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\t\t\tBottom,Middle\t\t630\r\nMT_UNSEEN\tUnseen\tsneak\\sneak\t\tsneak\\sneakv3\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t6\t8\t11\t35\t50\tSneak\tHIDDEN,SEARCH\t2\t45\t8\t12\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t935\r\nMT_ILLWEAV\tIllusion Weaver\tsneak\\sneak\t\tsneak\\sneakv1\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t8\t10\t13\t40\t60\tSneak\tHIDDEN,SEARCH\t3\t60\t8\t16\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tRESIST_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,RESIST_FIRE\tBottom,Middle\t\t1500\r\nMT_LRDSAYTR\tSatyr Lord\tgoatlord\\goatl\tnewsfx\\satyr\t\tNever\t160\t800\tfalse\tfalse\t13,13,14,9,16,0\t2,1,1,1,1,1\t21\t22\t28\t160\t200\tSkeletonMelee\tSEARCH\t3\t90\t8\t20\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tAnimal\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t2800\r\nMT_NGOATMC\tFlesh Clan\tgoatmace\\goat\t\t\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t4\t6\t8\t30\t45\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t0\t50\t8\t4\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t40\tDemon\t\t\tBottom,Middle\t\t460\r\nMT_BGOATMC\tStone Clan\tgoatmace\\goat\t\tgoatmace\\beige\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t5\t7\t10\t40\t55\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t1\t60\t8\t6\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t40\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t685\r\nMT_RGOATMC\tFire Clan\tgoatmace\\goat\t\tgoatmace\\red\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t6\t8\t12\t50\t65\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t2\t70\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tRESIST_FIRE\tIMMUNE_FIRE\tBottom,Middle\t\t906\r\nMT_GGOATMC\tNight Clan\tgoatmace\\goat\t\tgoatmace\\gray\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t7\t9\t14\t55\t70\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t3\t80\t8\t10\t20\t15\t0\t30\t30\t0\t0\t0\t0\t0\t0\t50\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t1190\r\nMT_FIEND\tFiend\tbat\\bat\t\tbat\\red\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t2\t3\t3\t3\t6\tBat\t\t0\t35\t5\t1\t6\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tAnimal\t\t\tMiddle,Top\tNone\t102\r\nMT_BLINK\tBlink\tbat\\bat\t\t\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t3\t5\t7\t12\t28\tBat\t\t1\t45\t5\t1\t8\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tAnimal\t\t\tMiddle,Top\tNone\t340\r\nMT_GLOOM\tGloom\tbat\\bat\t\tbat\\grey\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t4\t6\t9\t28\t36\tBat\tSEARCH\t2\t70\t5\t4\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC\tRESIST_MAGIC\tMiddle,Top\tNone\t509\r\nMT_FAMILIAR\tFamiliar\tbat\\bat\t\tbat\\orange\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t6\t8\t13\t20\t35\tBat\tSEARCH\t3\t50\t5\t4\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tRESIST_MAGIC,IMMUNE_LIGHTNING\tMiddle,Top\tNone\t448\r\nMT_NGOATBW\tFlesh Clan\tgoatbow\\goatb\t\t\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t4\t6\t8\t20\t35\tGoatRanged\tCAN_OPEN_DOOR\t0\t35\t13\t1\t7\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\t\t\tBottom,Middle\t\t448\r\nMT_BGOATBW\tStone Clan\tgoatbow\\goatb\t\tgoatbow\\beige\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t5\t7\t10\t30\t40\tGoatRanged\tCAN_OPEN_DOOR\t1\t40\t13\t2\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t645\r\nMT_RGOATBW\tFire Clan\tgoatbow\\goatb\t\tgoatbow\\red\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t6\t8\t12\t40\t50\tGoatRanged\tSEARCH,CAN_OPEN_DOOR\t2\t45\t13\t3\t11\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_FIRE\tIMMUNE_FIRE\tBottom,Middle\t\t822\r\nMT_GGOATBW\tNight Clan\tgoatbow\\goatb\t\tgoatbow\\gray\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t7\t9\t14\t50\t65\tGoatRanged\tSEARCH,CAN_OPEN_DOOR\t3\t50\t13\t4\t13\t15\t0\t0\t0\t0\t0\t0\t0\t0\t0\t40\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t1092\r\nMT_NACID\tAcid Beast\tacid\\acid\t\t\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t6\t8\t11\t40\t66\tAcid\t\t0\t40\t8\t4\t12\t25\t8\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tIMMUNE_ACID\tIMMUNE_MAGIC,IMMUNE_ACID\tBottom,Middle\t\t846\r\nMT_RACID\tPoison Spitter\tacid\\acid\t\tacid\\acidblk\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t8\t10\t15\t60\t85\tAcid\t\t1\t45\t8\t4\t16\t25\t8\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tIMMUNE_ACID\tIMMUNE_MAGIC,IMMUNE_ACID\tBottom,Middle\t\t1248\r\nMT_BACID\tPit Beast\tacid\\acid\t\tacid\\acidb\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t10\t12\t21\t80\t110\tAcid\t\t2\t55\t8\t8\t18\t35\t8\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC,IMMUNE_ACID\tIMMUNE_MAGIC,RESIST_LIGHTNING,IMMUNE_ACID\tBottom,Middle\t\t2060\r\nMT_XACID\tLava Maw\tacid\\acid\t\tacid\\acidr\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t12\t14\t25\t100\t150\tAcid\t\t3\t65\t8\t10\t20\t40\t8\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_ACID\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_ACID\tBottom,Middle\t\t2940\r\nMT_SKING\tSkeleton King\tsking\\sking\t\tskelaxe\\white\tNever\t160\t1010\ttrue\ttrue\t8,6,16,6,16,6\t2,1,1,1,1,2\t4\t4\t9\t140\t140\tSkeletonKing\tSEARCH,CAN_OPEN_DOOR\t3\t60\t8\t6\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tUndead\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\tUniq(SKCROWN)\t570\r\nMT_CLEAVER\tThe Butcher\tfatc\\fatc\t\t\tNever\t128\t980\tfalse\tfalse\t10,8,12,6,16,0\t1,1,1,1,1,1\t1\t1\t1\t320\t320\tButcher\t\t3\t50\t8\t6\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\tUniq(CLEAVER)\t710\r\nMT_FAT\tOverlord\tfat\\fat\t\t\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t5\t7\t10\t60\t80\tFat\t\t0\t55\t8\t6\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t55\tDemon\t\tRESIST_FIRE\tBottom,Middle\t\t635\r\nMT_MUDMAN\tMud Man\tfat\\fat\t\tfat\\blue\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t7\t9\t14\t100\t125\tFat\tSEARCH\t1\t60\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\t\tIMMUNE_LIGHTNING\tBottom,Middle\t\t1165\r\nMT_TOAD\tToad Demon\tfat\\fat\t\tfat\\fatb\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t8\t10\t16\t135\t160\tFat\tSEARCH\t2\t70\t8\t8\t16\t40\t0\t8\t20\t0\t0\t0\t0\t0\t0\t65\tDemon\tIMMUNE_MAGIC\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t1380\r\nMT_FLAYED\tFlayed One\tfat\\fat\t\tfat\\fatf\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t10\t12\t20\t160\t200\tFat\tSEARCH\t3\t85\t8\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t2058\r\nMT_WYRM\tWyrm\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t5\t7\t11\t60\t90\tSkeletonMelee\t\t0\t40\t8\t4\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tAnimal\tRESIST_MAGIC\tRESIST_MAGIC\tBottom,Middle\t\t660\r\nMT_CAVSLUG\tCave Slug\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t6\t8\t13\t75\t110\tSkeletonMelee\t\t1\t50\t8\t6\t13\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tRESIST_MAGIC\tRESIST_MAGIC\tBottom,Middle\t\t994\r\nMT_DVLWYRM\tDevil Wyrm\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t7\t9\t15\t100\t140\tSkeletonMelee\t\t2\t55\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tRESIST_MAGIC,RESIST_FIRE\tRESIST_MAGIC,RESIST_FIRE\tBottom,Middle\t\t1320\r\nMT_DEVOUR\tDevourer\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t8\t10\t17\t125\t200\tSkeletonMelee\t\t3\t60\t8\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC,RESIST_FIRE\tRESIST_MAGIC,RESIST_FIRE\tBottom,Middle\t\t1827\r\nMT_NMAGMA\tMagma Demon\tmagma\\magma\t\t\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t8\t9\t13\t50\t70\tMagma\tSEARCH,CAN_OPEN_DOOR\t0\t45\t4\t2\t10\t50\t13\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t1076\r\nMT_YMAGMA\tBlood Stone\tmagma\\magma\t\tmagma\\yellow\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t8\t10\t14\t55\t75\tMagma\tSEARCH,CAN_OPEN_DOOR\t1\t50\t4\t2\t12\t50\t14\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t1309\r\nMT_BMAGMA\tHell Stone\tmagma\\magma\t\tmagma\\blue\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t9\t11\t16\t60\t80\tMagma\tSEARCH,CAN_OPEN_DOOR\t2\t60\t4\t2\t20\t60\t14\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t1680\r\nMT_WMAGMA\tLava Lord\tmagma\\magma\t\tmagma\\wierd\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t9\t11\t18\t70\t85\tMagma\tSEARCH,CAN_OPEN_DOOR\t3\t75\t4\t4\t24\t60\t14\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2124\r\nMT_HORNED\tHorned Demon\trhino\\rhino\t\t\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t7\t9\t13\t40\t80\tRhino\tSEARCH,CAN_OPEN_DOOR\t0\t60\t7\t2\t16\t100\t0\t5\t32\t0\t0\t0\t0\t0\t0\t40\tAnimal\t\tRESIST_FIRE\tBottom,Middle,Top\t\t1172\r\nMT_MUDRUN\tMud Runner\trhino\\rhino\t\trhino\\orange\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t8\t10\t15\t50\t90\tRhino\tSEARCH,CAN_OPEN_DOOR\t1\t70\t7\t6\t18\t100\t0\t12\t36\t0\t0\t0\t0\t0\t0\t45\tAnimal\t\tRESIST_FIRE\tBottom,Middle,Top\t\t1404\r\nMT_FROSTC\tFrost Charger\trhino\\rhino\t\trhino\\blue\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t9\t11\t17\t60\t100\tRhino\tSEARCH,CAN_OPEN_DOOR\t2\t80\t7\t8\t20\t100\t0\t20\t40\t0\t0\t0\t0\t0\t0\t50\tAnimal\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle,Top\t\t1720\r\nMT_OBLORD\tObsidian Lord\trhino\\rhino\t\trhino\\rhinob\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t10\t12\t19\t70\t110\tRhino\tSEARCH,CAN_OPEN_DOOR\t3\t90\t7\t10\t22\t100\t0\t20\t50\t0\t0\t0\t0\t0\t0\t55\tAnimal\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t1809\r\nMT_BONEDMN\toldboned\tdemskel\\demskl\t\t\tNever\t128\t1740\ttrue\ttrue\t10,8,20,6,24,16\t3,1,1,1,1,1\t24\t24\t12\t70\t70\tStorm\t\t0\t60\t8\t6\t14\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle,Top\t\t1344\r\nMT_REDDTH\tRed Death\tthin\\thin\t\tthin\\thinv3\tNever\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t8\t10\t16\t96\t96\tStorm\t\t1\t75\t5\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2168\r\nMT_LTCHDMN\tLitch Demon\tthin\\thin\t\tthin\\thinv3\tNever\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t9\t11\t18\t110\t110\tStorm\t\t2\t80\t5\t10\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2736\r\nMT_UDEDBLRG\tUndead Balrog\tthin\\thin\t\tthin\\thinv3\tNever\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t11\t13\t22\t130\t130\tStorm\t\t3\t85\t5\t12\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3575\r\nMT_INCIN\tIncinerator\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t21\t22\t16\t30\t45\tFireMan\t\t0\t75\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t1888\r\nMT_FLAMLRD\tFlame Lord\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t22\t23\t18\t40\t55\tFireMan\t\t1\t75\t8\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t2250\r\nMT_DOOMFIRE\tDoom Fire\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t23\t24\t20\t50\t65\tFireMan\t\t2\t80\t8\t12\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t2740\r\nMT_HELLBURN\tHell Burner\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t24\t24\t22\t60\t80\tFireMan\t\t3\t85\t8\t15\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t3355\r\nMT_STORM\tRed Storm\tthin\\thin\t\tthin\\thinv3\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t9\t11\t18\t55\t110\tStorm\tSEARCH,CAN_OPEN_DOOR\t0\t80\t5\t8\t18\t75\t8\t4\t16\t0\t0\t0\t0\t0\t0\t30\tDemon\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2160\r\nMT_RSTORM\tStorm Rider\tthin\\thin\t\t\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t10\t12\t20\t60\t120\tStorm\tSEARCH,CAN_OPEN_DOOR\t1\t80\t5\t8\t18\t80\t8\t4\t16\t0\t0\t0\t0\t0\t0\t30\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2391\r\nMT_STORML\tStorm Lord\tthin\\thin\t\tthin\\thinv2\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t11\t13\t22\t75\t135\tStorm\tSEARCH,CAN_OPEN_DOOR\t2\t85\t5\t12\t24\t75\t8\t4\t16\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2775\r\nMT_MAEL\tMaelstrom\tthin\\thin\t\tthin\\thinv1\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t12\t14\t24\t90\t150\tStorm\tSEARCH,CAN_OPEN_DOOR\t3\t90\t5\t12\t28\t75\t8\t4\t16\t0\t0\t0\t0\t0\t0\t40\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t3177\r\nMT_BIGFALL\tDevil Kin Brute\tbigfall\\fallg\tnewsfx\\kbrute\t\tNever\t128\t800\ttrue\tfalse\t10,8,11,8,17,0\t1,1,1,1,2,2\t21\t22\t27\t120\t160\tSkeletonMelee\tSEARCH,CAN_OPEN_DOOR\t3\t100\t6\t18\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tAnimal\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t2400\r\nMT_WINGED\tWinged-Demon\tgargoyle\\gargo\t\t\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,2\t5\t7\t9\t45\t60\tGargoyle\tCAN_OPEN_DOOR\t0\t50\t7\t10\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tMiddle,Top\t\t662\r\nMT_GARGOYLE\tGargoyle\tgargoyle\\gargo\t\tgargoyle\\gare\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,2\t7\t9\t13\t60\t90\tGargoyle\tCAN_OPEN_DOOR\t1\t65\t7\t10\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tMiddle,Top\t\t1205\r\nMT_BLOODCLW\tBlood Claw\tgargoyle\\gargo\t\tgargoyle\\gargbr\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,1\t9\t11\t19\t75\t125\tGargoyle\tCAN_OPEN_DOOR\t2\t80\t7\t14\t22\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tMiddle,Top\t\t1873\r\nMT_DEATHW\tDeath Wing\tgargoyle\\gargo\t\tgargoyle\\gargb\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,1\t10\t12\t23\t90\t150\tGargoyle\tCAN_OPEN_DOOR\t3\t95\t7\t16\t28\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tMiddle,Top\t\t2278\r\nMT_MEGA\tSlayer\tmega\\mega\t\t\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t10\t12\t20\t120\t140\tMega\tSEARCH,CAN_OPEN_DOOR\t0\t100\t8\t12\t20\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2300\r\nMT_GUARD\tGuardian\tmega\\mega\t\tmega\\guard\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t11\t13\t22\t140\t160\tMega\tSEARCH,CAN_OPEN_DOOR\t1\t110\t8\t14\t22\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2714\r\nMT_VTEXLRD\tVortex Lord\tmega\\mega\t\tmega\\vtexl\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t12\t14\t24\t160\t180\tMega\tSEARCH,CAN_OPEN_DOOR\t2\t120\t8\t18\t24\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3252\r\nMT_BALROG\tBalrog\tmega\\mega\t\tmega\\balr\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t13\t15\t26\t180\t200\tMega\tSEARCH,CAN_OPEN_DOOR\t3\t130\t8\t22\t30\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3643\r\nMT_NSNAKE\tCave Viper\tsnake\\snake\t\t\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t11\t13\t21\t100\t150\tSnake\tSEARCH\t0\t90\t8\t8\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle,Top\t\t2725\r\nMT_RSNAKE\tFire Drake\tsnake\\snake\t\tsnake\\snakr\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t12\t14\t23\t120\t170\tSnake\tSEARCH\t1\t105\t8\t12\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t3139\r\nMT_BSNAKE\tGold Viper\tsnake\\snake\t\tsnake\\snakg\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t13\t14\t25\t140\t180\tSnake\tSEARCH\t2\t120\t8\t15\t26\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3540\r\nMT_GSNAKE\tAzure Drake\tsnake\\snake\t\tsnake\\snakb\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t15\t16\t27\t160\t200\tSnake\tSEARCH\t3\t130\t8\t18\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t3791\r\nMT_NBLACK\tBlack Knight\tblack\\black\t\t\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t12\t14\t24\t150\t150\tSkeletonMelee\tSEARCH\t0\t110\t8\t15\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,RESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t3360\r\nMT_RTBLACK\tDoom Guard\tblack\\black\t\tblack\\blkkntrt\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t13\t15\t26\t165\t165\tSkeletonMelee\tSEARCH\t0\t130\t8\t18\t25\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,RESIST_FIRE\tRESIST_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t3650\r\nMT_BTBLACK\tSteel Lord\tblack\\black\t\tblack\\blkkntbt\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t14\t16\t28\t180\t180\tSkeletonMelee\tSEARCH\t1\t120\t8\t20\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t80\tDemon\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t4252\r\nMT_RBLACK\tBlood Knight\tblack\\black\t\tblack\\blkkntbe\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t13\t14\t30\t200\t200\tSkeletonMelee\tSEARCH\t1\t130\t8\t25\t35\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t85\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t5130\r\nMT_UNRAV\tThe Shredded\tunrav\\unrav\tnewsfx\\shred\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t17\t18\t23\t70\t90\tSkeletonMelee\t\t0\t75\t7\t4\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tUndead\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t900\r\nMT_HOLOWONE\tHollow One\tunrav\\unrav\tacid\\acid\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t18\t19\t27\t135\t240\tSkeletonMelee\t\t1\t75\t7\t12\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tUndead\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t4374\r\nMT_PAINMSTR\tPain Master\tunrav\\unrav\tacid\\acid\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t19\t20\t29\t110\t200\tSkeletonMelee\t\t2\t80\t7\t16\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t80\tUndead\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t5147\r\nMT_REALWEAV\tReality Weaver\tunrav\\unrav\tacid\\acid\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t20\t20\t30\t135\t240\tSkeletonMelee\t\t3\t85\t7\t20\t35\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t85\tUndead\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t5925\r\nMT_SUCCUBUS\tSuccubus\tsucc\\scbs\t\t\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t12\t14\t24\t120\t150\tSuccubus\tCAN_OPEN_DOOR\t0\t100\t10\t1\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC,RESIST_FIRE\tBottom,Middle\t\t3696\r\nMT_SNOWWICH\tSnow Witch\tsucc\\scbs\t\tsucc\\succb\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t13\t15\t26\t135\t175\tSuccubus\tCAN_OPEN_DOOR\t1\t110\t10\t1\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tRESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t4084\r\nMT_HLSPWN\tHell Spawn\tsucc\\scbs\t\tsucc\\succrw\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t14\t16\t28\t150\t200\tSuccubus\tSEARCH,CAN_OPEN_DOOR\t2\t115\t10\t1\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t4480\r\nMT_SOLBRNR\tSoul Burner\tsucc\\scbs\t\tsucc\\succbw\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t15\t16\t30\t140\t225\tSuccubus\tSEARCH,CAN_OPEN_DOOR\t3\t120\t10\t1\t35\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t85\tDemon\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t4644\r\nMT_COUNSLR\tCounselor\tmage\\mage\t\t\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t13\t14\t25\t70\t70\tCounselor\tCAN_OPEN_DOOR\t0\t90\t8\t8\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t4070\r\nMT_MAGISTR\tMagistrate\tmage\\mage\t\tmage\\cnselg\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t14\t15\t27\t85\t85\tCounselor\tCAN_OPEN_DOOR\t1\t100\t8\t10\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t4478\r\nMT_CABALIST\tCabalist\tmage\\mage\t\tmage\\cnselgd\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t15\t16\t29\t120\t120\tCounselor\tCAN_OPEN_DOOR\t2\t110\t8\t14\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t4929\r\nMT_ADVOCATE\tAdvocate\tmage\\mage\t\tmage\\cnselbk\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t16\t16\t30\t145\t145\tCounselor\tCAN_OPEN_DOOR\t3\t120\t8\t15\t25\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t4968\r\nMT_GOLEM\tGolem\tgolem\\golem\tgolem\\golm\t\tNever\t96\t386\ttrue\tfalse\t0,16,12,0,12,20\t1,1,1,1,1,1\t1\t1\t12\t1\t1\tGolem\tCAN_OPEN_DOOR\t0\t0\t7\t1\t1\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t1\tDemon\t\t\t\t\t0\r\nMT_DIABLO\tThe Dark Lord\tdiablo\\diablo\t\t\tNever\t160\t2000\ttrue\ttrue\t16,6,16,6,16,16\t1,1,1,1,1,1\t26\t26\t30\t1666\t1666\tDiablo\tKNOCKBACK,SEARCH,CAN_OPEN_DOOR\t3\t220\t4\t30\t60\t0\t11\t0\t0\t0\t0\t0\t0\t0\t0\t90\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t31666\r\nMT_DARKMAGE\tThe Arch-Litch Malignus\tdarkmage\\dmage\tdarkmage\\dmag\t\tNever\t128\t1060\ttrue\tfalse\t6,1,21,6,23,18\t1,1,1,1,1,1\t21\t21\t30\t160\t160\tCounselor\tCAN_OPEN_DOOR\t3\t120\t8\t20\t40\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t4968\r\n"
  },
  {
    "path": "assets/txtdata/monsters/unique_monstdat.tsv",
    "content": "type\tname\ttrn\tlevel\tmaxHp\tai\tintelligence\tminDamage\tmaxDamage\treducePlayerStrength\treducePlayerMagic\treducePlayerDexterity\treducePlayerVitality\treducePlayerMaxHP\treducePlayerMaxMana\tresistance\tmonsterPack\tcustomToHit\tcustomArmorClass\ttalkMessage\r\nMT_NGOATMC\tGharbad the Weak\tbsdb\t4\t120\tGharbad\t3\t8\t16\t0\t0\t0\t0\t0\t0\tIMMUNE_LIGHTNING\tNone\t0\t0\tTEXT_GARBUD1\r\nMT_SKING\tSkeleton King\tgenrl\t0\t240\tSkeletonKing\t3\t6\t16\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIndependent\t0\t0\t\r\nMT_COUNSLR\tZhar the Mad\tgeneral\t8\t360\tZhar\t3\t16\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tNone\t0\t0\tTEXT_ZHAR1\r\nMT_BFALLSP\tSnotspill\tbng\t4\t220\tSnotspill\t3\t10\t18\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tNone\t0\t0\tTEXT_BANNER10\r\nMT_ADVOCATE\tArch-Bishop Lazarus\tgeneral\t0\t600\tLazarus\t3\t30\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tNone\t0\t0\tTEXT_VILE13\r\nMT_HLSPWN\tRed Vex\tredv\t0\t400\tLazarusSuccubus\t3\t30\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tNone\t0\t0\tTEXT_VILE13\r\nMT_HLSPWN\tBlack Jade\tblkjd\t0\t400\tLazarusSuccubus\t3\t30\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_LIGHTNING\tNone\t0\t0\tTEXT_VILE13\r\nMT_RBLACK\tLachdanan\tbhka\t14\t500\tLachdanan\t3\t0\t0\t0\t0\t0\t0\t0\t0\t\tNone\t0\t0\tTEXT_VEIL9\r\nMT_BTBLACK\tWarlord of Blood\tgeneral\t13\t850\tWarlord\t3\t35\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tNone\t0\t0\tTEXT_WARLRD9\r\nMT_CLEAVER\tThe Butcher\tgenrl\t0\t220\tButcher\t3\t6\t12\t0\t0\t0\t0\t0\t0\tRESIST_FIRE,RESIST_LIGHTNING\tNone\t0\t0\t\r\nMT_HORKDMN\tHork Demon\tgenrl\t19\t300\tHorkDemon\t3\t20\t35\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tNone\t0\t0\t\r\nMT_DEFILER\tThe Defiler\tgenrl\t20\t480\tSkeletonMelee\t3\t30\t40\t0\t0\t0\t0\t0\t0\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tNone\t0\t0\t\r\nMT_NAKRUL\tNa-Krul\tgenrl\t0\t1332\tSkeletonMelee\t3\t40\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_TSKELAX\tBonehead Keenaxe\tbhka\t2\t91\tSkeletonMelee\t2\t4\t10\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC\tLeashed\t100\t0\t\r\nMT_RFALLSD\tBladeskin the Slasher\tbsts\t2\t51\tFallen\t0\t6\t18\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tLeashed\t0\t45\t\r\nMT_NZOMBIE\tSoulpus\tgeneral\t2\t133\tZombie\t0\t4\t8\t0\t0\t0\t0\t0\t0\tRESIST_FIRE,RESIST_LIGHTNING\tNone\t0\t0\t\r\nMT_RFALLSP\tPukerat the Unclean\tptu\t2\t77\tFallen\t3\t1\t5\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tNone\t0\t0\t\r\nMT_WSKELAX\tBoneripper\tbr\t2\t54\tBat\t0\t6\t15\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_NZOMBIE\tRotfeast the Hungry\teth\t2\t85\tSkeletonMelee\t3\t4\t12\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC\tLeashed\t0\t0\t\r\nMT_DFALLSD\tGutshank the Quick\tgtq\t3\t66\tBat\t2\t6\t16\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tLeashed\t0\t0\t\r\nMT_TSKELSD\tBrokenhead Bangshield\tbhbs\t3\t108\tSkeletonMelee\t3\t12\t20\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_YFALLSP\tBongo\tbng\t3\t178\tFallen\t3\t9\t21\t0\t0\t0\t0\t0\t0\t\tLeashed\t0\t0\t\r\nMT_BZOMBIE\tRotcarnage\trcrn\t3\t102\tZombie\t3\t9\t24\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_LIGHTNING\tLeashed\t0\t45\t\r\nMT_NSCAV\tShadowbite\tshbt\t2\t60\tSkeletonMelee\t3\t3\t20\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_WSKELBW\tDeadeye\tde\t2\t49\tGoatRanged\t0\t6\t9\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tNone\t0\t0\t\r\nMT_RSKELAX\tMadeye the Dead\tmtd\t4\t75\tBat\t0\t9\t21\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE\tLeashed\t0\t30\t\r\nMT_BSCAV\tEl Chupacabras\tgeneral\t3\t120\tGoatMelee\t0\t10\t18\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tLeashed\t0\t0\t\r\nMT_TSKELBW\tSkullfire\tskfr\t3\t125\tGoatRanged\t1\t6\t10\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tNone\t0\t0\t\r\nMT_SNEAK\tWarpskull\ttspo\t3\t117\tSneak\t2\t6\t18\t0\t0\t0\t0\t0\t0\tRESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_GZOMBIE\tGoretongue\tpmr\t3\t156\tSkeletonMelee\t1\t15\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC\tNone\t0\t0\t\r\nMT_WSCAV\tPulsecrawler\tbhka\t4\t150\tScavenger\t0\t16\t20\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE,RESIST_LIGHTNING\tLeashed\t0\t45\t\r\nMT_BLINK\tMoonbender\tgeneral\t4\t135\tBat\t0\t9\t27\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_BLINK\tWrathraven\tgeneral\t5\t135\tBat\t2\t9\t22\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_YSCAV\tSpineeater\tgeneral\t4\t180\tScavenger\t1\t18\t25\t0\t0\t0\t0\t0\t0\tIMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_RSKELBW\tBlackash the Burning\tbashtb\t4\t120\tGoatRanged\t0\t6\t16\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_BFALLSD\tShadowcrow\tgeneral\t5\t270\tSneak\t2\t12\t25\t0\t0\t0\t0\t0\t0\t\tLeashed\t0\t0\t\r\nMT_LRDSAYTR\tBlightstone the Weak\tbhka\t4\t360\tSkeletonMelee\t0\t4\t12\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_LIGHTNING\tLeashed\t70\t0\t\r\nMT_FAT\tBilefroth the Pit Master\tbftp\t6\t210\tBat\t1\t16\t23\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_NGOATBW\tBloodskin Darkbow\tbsdb\t5\t207\tGoatRanged\t0\t3\t16\t0\t0\t0\t0\t0\t0\tRESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t55\t\r\nMT_GLOOM\tFoulwing\tdb\t5\t246\tRhino\t3\t12\t28\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tLeashed\t0\t0\t\r\nMT_XSKELSD\tShadowdrinker\tshdr\t5\t300\tSneak\t1\t18\t26\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tNone\t0\t45\t\r\nMT_UNSEEN\tHazeshifter\tbhka\t5\t285\tSneak\t3\t18\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_NACID\tDeathspit\tbfds\t6\t303\tAcidUnique\t0\t12\t32\t0\t0\t0\t0\t0\t0\tRESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_RGOATMC\tBloodgutter\tbgbl\t6\t315\tBat\t1\t24\t34\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_BGOATMC\tDeathshade Fleshmaul\tdsfm\t6\t276\tRhino\t0\t12\t24\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tNone\t0\t65\t\r\nMT_WYRM\tWarmaggot the Mad\tgeneral\t6\t246\tBat\t3\t15\t30\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_STORM\tGlasskull the Jagged\tbhka\t7\t354\tStorm\t0\t18\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_RGOATBW\tBlightfire\tblf\t7\t321\tSuccubus\t2\t13\t21\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_GARGOYLE\tNightwing the Cold\tgeneral\t7\t342\tBat\t1\t18\t26\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_GGOATBW\tGorestone\tgeneral\t7\t303\tGoatRanged\t1\t15\t28\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tLeashed\t70\t0\t\r\nMT_BMAGMA\tBronzefist Firestone\tgeneral\t8\t360\tMagma\t0\t30\t36\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tLeashed\t0\t0\t\r\nMT_INCIN\tWrathfire the Doomed\twftd\t8\t270\tSkeletonMelee\t2\t20\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_NMAGMA\tFirewound the Grim\tbhka\t8\t303\tMagma\t0\t18\t22\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tLeashed\t0\t0\t\r\nMT_MUDMAN\tBaron Sludge\tbsm\t8\t315\tSneak\t3\t25\t34\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t75\t\r\nMT_GGOATMC\tBlighthorn Steelmace\tbhsm\t7\t250\tRhino\t0\t20\t28\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tLeashed\t0\t45\t\r\nMT_RACID\tChaoshowler\tgeneral\t8\t240\tAcidUnique\t0\t12\t20\t0\t0\t0\t0\t0\t0\t\tLeashed\t0\t0\t\r\nMT_REDDTH\tDoomgrin the Rotting\tgeneral\t8\t405\tStorm\t3\t25\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_FLAMLRD\tMadburner\tgeneral\t9\t270\tStorm\t0\t20\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_LTCHDMN\tBonesaw the Litch\tgeneral\t9\t495\tStorm\t2\t30\t55\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_MUDRUN\tBreakspine\tgeneral\t9\t351\tRhino\t0\t25\t34\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tLeashed\t0\t0\t\r\nMT_REDDTH\tDevilskull Sharpbone\tgeneral\t9\t444\tStorm\t1\t25\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_STORM\tBrokenstorm\tgeneral\t9\t411\tStorm\t2\t25\t36\t0\t0\t0\t0\t0\t0\tIMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_RSTORM\tStormbane\tgeneral\t9\t555\tStorm\t3\t30\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_TOAD\tOozedrool\tgeneral\t9\t483\tFat\t3\t25\t30\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_BLOODCLW\tGoldblight of the Flame\tgeneral\t10\t405\tGargoyle\t0\t15\t35\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE\tLeashed\t0\t80\t\r\nMT_OBLORD\tBlackstorm\tgeneral\t10\t525\tRhino\t3\t20\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tLeashed\t0\t90\t\r\nMT_RACID\tPlaguewrath\tgeneral\t10\t450\tAcidUnique\t2\t20\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tLeashed\t0\t0\t\r\nMT_RSTORM\tThe Flayer\tgeneral\t10\t501\tStorm\t1\t20\t35\t0\t0\t0\t0\t0\t0\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_FROSTC\tBluehorn\tgeneral\t11\t477\tRhino\t1\t25\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tLeashed\t0\t90\t\r\nMT_HELLBURN\tWarpfire Hellspawn\tgeneral\t11\t525\tFireMan\t3\t10\t40\t0\t0\t0\t0\t0\t0\tRESIST_MAGIC,IMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_NSNAKE\tFangspeir\tgeneral\t11\t444\tSkeletonMelee\t1\t15\t32\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_UDEDBLRG\tFesterskull\tgeneral\t11\t600\tStorm\t2\t15\t30\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC\tLeashed\t0\t0\t\r\nMT_NBLACK\tLionskull the Bent\tgeneral\t12\t525\tSkeletonMelee\t2\t25\t25\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_COUNSLR\tBlacktongue\tgeneral\t12\t360\tCounselor\t3\t15\t30\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tLeashed\t0\t0\t\r\nMT_DEATHW\tViletouch\tgeneral\t12\t525\tGargoyle\t3\t20\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_LIGHTNING\tLeashed\t0\t0\t\r\nMT_RSNAKE\tViperflame\tgeneral\t12\t570\tSkeletonMelee\t1\t25\t35\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_BSNAKE\tFangskin\tbhka\t14\t681\tSkeletonMelee\t2\t15\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_SUCCUBUS\tWitchfire the Unholy\tgeneral\t12\t444\tSuccubus\t3\t10\t20\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_BALROG\tBlackskull\tbhka\t13\t750\tSkeletonMelee\t3\t25\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_UNRAV\tSoulslash\tgeneral\t12\t450\tSkeletonMelee\t0\t25\t25\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC\tLeashed\t0\t0\t\r\nMT_VTEXLRD\tWindspawn\tgeneral\t12\t711\tSkeletonMelee\t1\t35\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_GSNAKE\tLord of the Pit\tgeneral\t13\t762\tSkeletonMelee\t2\t25\t42\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tLeashed\t0\t0\t\r\nMT_RTBLACK\tRustweaver\tgeneral\t13\t400\tSkeletonMelee\t3\t1\t60\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tNone\t0\t0\t\r\nMT_HOLOWONE\tHowlingire the Shade\tgeneral\t13\t450\tSkeletonMelee\t2\t40\t75\t0\t0\t0\t0\t0\t0\tRESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_MAEL\tDoomcloud\tgeneral\t13\t612\tStorm\t1\t1\t60\t0\t0\t0\t0\t0\t0\tRESIST_FIRE,IMMUNE_LIGHTNING\tNone\t0\t0\t\r\nMT_PAINMSTR\tBloodmoon Soulfire\tgeneral\t13\t684\tSkeletonMelee\t1\t15\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_SNOWWICH\tWitchmoon\tgeneral\t13\t310\tSuccubus\t3\t30\t40\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tNone\t0\t0\t\r\nMT_VTEXLRD\tGorefeast\tgeneral\t13\t771\tSkeletonMelee\t3\t20\t55\t0\t0\t0\t0\t0\t0\tRESIST_FIRE\tNone\t0\t0\t\r\nMT_RTBLACK\tGraywar the Slayer\tgeneral\t14\t672\tSkeletonMelee\t1\t30\t50\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tNone\t0\t0\t\r\nMT_MAGISTR\tDreadjudge\tgeneral\t14\t540\tCounselor\t1\t30\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_HLSPWN\tStareye the Witch\tgeneral\t14\t726\tSuccubus\t2\t30\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tNone\t0\t0\t\r\nMT_BTBLACK\tSteelskull the Hunter\tgeneral\t14\t831\tSkeletonMelee\t3\t40\t50\t0\t0\t0\t0\t0\t0\tRESIST_LIGHTNING\tNone\t0\t0\t\r\nMT_RBLACK\tSir Gorash\tgeneral\t16\t1050\tSkeletonMelee\t1\t20\t60\t0\t0\t0\t0\t0\t0\t\tNone\t0\t0\t\r\nMT_CABALIST\tThe Vizier\tgeneral\t15\t850\tCounselor\t2\t25\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_FIRE\tLeashed\t0\t0\t\r\nMT_REALWEAV\tZamphir\tgeneral\t15\t891\tSkeletonMelee\t2\t30\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\nMT_HLSPWN\tBloodlust\tgeneral\t15\t825\tSuccubus\t1\t20\t55\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tNone\t0\t0\t\r\nMT_HLSPWN\tWebwidow\tgeneral\t16\t774\tSuccubus\t1\t20\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,IMMUNE_FIRE\tNone\t0\t0\t\r\nMT_SOLBRNR\tFleshdancer\tgeneral\t16\t999\tSuccubus\t3\t30\t50\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tNone\t0\t0\t\r\nMT_OBLORD\tGrimspike\tgeneral\t19\t534\tSneak\t1\t25\t40\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE\tLeashed\t0\t0\t\r\nMT_STORML\tDoomlock\tgeneral\t28\t534\tSneak\t1\t35\t55\t0\t0\t0\t0\t0\t0\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tLeashed\t0\t0\t\r\n"
  },
  {
    "path": "assets/txtdata/objects/objdat.tsv",
    "content": "id\tfile\tminLevel\tmaxLevel\tlevelType\ttheme\tquest\tflags\tanimDelay\tanimLen\tanimWidth\tselectionRegion\r\nOBJ_L1LIGHT\tl1braz\t0\t0\tDTYPE_CATHEDRAL\t\t\tAnimated,Solid,MissilesPassThrough\t1\t26\t64\t\r\nOBJ_L1LDOOR\tl1doors\t0\t0\tDTYPE_CATHEDRAL\t\t\tLight,Trap\t1\t0\t64\tBottom,Middle\r\nOBJ_L1RDOOR\tl1doors\t0\t0\tDTYPE_CATHEDRAL\t\t\tLight,Trap\t2\t0\t64\tBottom,Middle\r\nOBJ_SKFIRE\tskulfire\t0\t0\t\tTHEME_SKELROOM\t\tAnimated,Solid,MissilesPassThrough\t2\t11\t96\t\r\nOBJ_LEVER\tlever\t0\t0\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t1\t96\tBottom\r\nOBJ_CHEST1\tchest1\t1\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom\r\nOBJ_CHEST2\tchest2\t1\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom\r\nOBJ_CHEST3\tchest3\t1\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom\r\nOBJ_CANDLE1\tl1braz\t0\t0\t\t\t\t\t0\t0\t0\t\r\nOBJ_CANDLE2\tcandle2\t0\t0\t\tTHEME_SHRINE\tQ_PWATER\tAnimated,Solid,MissilesPassThrough,Light\t2\t4\t96\t\r\nOBJ_CANDLEO\tl1braz\t0\t0\t\t\t\t\t0\t0\t0\t\r\nOBJ_BANNERL\tbanner\t0\t0\t\tTHEME_SKELROOM\t\tSolid,MissilesPassThrough,Light\t2\t0\t96\t\r\nOBJ_BANNERM\tbanner\t0\t0\t\tTHEME_SKELROOM\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\t\r\nOBJ_BANNERR\tbanner\t0\t0\t\tTHEME_SKELROOM\t\tSolid,MissilesPassThrough,Light\t3\t0\t96\t\r\nOBJ_SKPILE\tskulpile\t0\t0\t\t\t\tSolid,MissilesPassThrough,Light\t1\t1\t96\t\r\nOBJ_SKSTICK1\tl1braz\t0\t0\t\t\t\t\t0\t0\t0\t\r\nOBJ_SKSTICK2\tl1braz\t0\t0\t\t\t\t\t0\t0\t0\t\r\nOBJ_SKSTICK3\tl1braz\t0\t0\t\t\t\t\t0\t0\t0\t\r\nOBJ_SKSTICK4\tl1braz\t0\t0\t\t\t\t\t0\t0\t0\t\r\nOBJ_SKSTICK5\tl1braz\t0\t0\t\t\t\t\t0\t0\t0\t\r\nOBJ_CRUX1\tcruxsk1\t0\t0\t\t\t\tSolid,Light,Breakable\t1\t15\t96\tBottom,Middle\r\nOBJ_CRUX2\tcruxsk2\t0\t0\t\t\t\tSolid,Light,Breakable\t1\t15\t96\tBottom,Middle\r\nOBJ_CRUX3\tcruxsk3\t0\t0\t\t\t\tSolid,Light,Breakable\t1\t15\t96\tBottom,Middle\r\nOBJ_STAND\trockstan\t5\t5\t\t\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\t\r\nOBJ_ANGEL\tangel\t0\t0\t\t\t\tSolid,Light\t1\t0\t96\t\r\nOBJ_BOOK2L\tbook2\t0\t0\t\t\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_BCROSS\tburncros\t0\t0\t\t\t\tAnimated,Solid\t0\t10\t160\t\r\nOBJ_NUDEW2R\tnude2\t0\t0\t\t\t\tAnimated,Solid,Light\t3\t6\t128\t\r\nOBJ_SWITCHSKL\tswitch4\t16\t16\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom\r\nOBJ_TNUDEM1\ttnudem\t13\t15\t\t\tQ_BUTCHER\tSolid,Light\t1\t0\t128\t\r\nOBJ_TNUDEM2\ttnudem\t13\t15\t\tTHEME_TORTURE\tQ_BUTCHER\tSolid,Light\t2\t0\t128\t\r\nOBJ_TNUDEM3\ttnudem\t13\t15\t\tTHEME_TORTURE\tQ_BUTCHER\tSolid,Light\t3\t0\t128\t\r\nOBJ_TNUDEM4\ttnudem\t13\t15\t\tTHEME_TORTURE\tQ_BUTCHER\tSolid,Light\t4\t0\t128\t\r\nOBJ_TNUDEW1\ttnudew\t13\t15\t\tTHEME_TORTURE\tQ_BUTCHER\tSolid,Light\t1\t0\t128\t\r\nOBJ_TNUDEW2\ttnudew\t13\t15\t\tTHEME_TORTURE\tQ_BUTCHER\tSolid,Light\t2\t0\t128\t\r\nOBJ_TNUDEW3\ttnudew\t13\t15\t\tTHEME_TORTURE\tQ_BUTCHER\tSolid,Light\t3\t0\t128\t\r\nOBJ_TORTURE1\ttsoul\t13\t15\t\t\tQ_BUTCHER\tMissilesPassThrough,Light\t1\t0\t128\t\r\nOBJ_TORTURE2\ttsoul\t13\t15\t\t\tQ_BUTCHER\tMissilesPassThrough,Light\t2\t0\t128\t\r\nOBJ_TORTURE3\ttsoul\t13\t15\t\t\tQ_BUTCHER\tMissilesPassThrough,Light\t3\t0\t128\t\r\nOBJ_TORTURE4\ttsoul\t13\t15\t\t\tQ_BUTCHER\tMissilesPassThrough,Light\t4\t0\t128\t\r\nOBJ_TORTURE5\ttsoul\t13\t15\t\t\tQ_BUTCHER\tMissilesPassThrough,Light\t5\t0\t128\t\r\nOBJ_BOOK2R\tbook2\t6\t6\t\t\t\tSolid,MissilesPassThrough,Light\t4\t0\t96\tBottom,Middle\r\nOBJ_L2LDOOR\tl2doors\t0\t0\tDTYPE_CATACOMBS\t\t\tLight,Trap\t1\t0\t64\tBottom,Middle\r\nOBJ_L2RDOOR\tl2doors\t0\t0\tDTYPE_CATACOMBS\t\t\tLight,Trap\t2\t0\t64\tBottom,Middle\r\nOBJ_TORCHL\twtorch4\t5\t8\t\t\t\tAnimated,MissilesPassThrough\t1\t9\t96\t\r\nOBJ_TORCHR\twtorch3\t5\t8\t\t\t\tAnimated,MissilesPassThrough\t1\t9\t96\t\r\nOBJ_TORCHL2\twtorch1\t5\t8\t\t\t\tAnimated,MissilesPassThrough\t1\t9\t96\t\r\nOBJ_TORCHR2\twtorch2\t5\t8\t\t\t\tAnimated,MissilesPassThrough\t1\t9\t96\t\r\nOBJ_SARC\tsarc\t1\t4\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t5\t128\tBottom,Middle\r\nOBJ_FLAMEHOLE\tflame1\t0\t0\t\t\t\tMissilesPassThrough,Light\t1\t20\t96\t\r\nOBJ_FLAMELVR\tlever\t0\t0\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t2\t96\tBottom\r\nOBJ_WATER\tminiwatr\t0\t0\t\t\t\tAnimated,Solid,Light\t1\t10\t64\t\r\nOBJ_BOOKLVR\tbook1\t0\t0\t\t\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_TRAPL\ttraphole\t1\t24\t\t\t\tMissilesPassThrough,Light\t1\t0\t64\t\r\nOBJ_TRAPR\ttraphole\t1\t24\t\t\t\tMissilesPassThrough,Light\t2\t0\t64\t\r\nOBJ_BOOKSHELF\tbcase\t0\t0\t\t\t\tSolid,Light\t1\t0\t96\t\r\nOBJ_WEAPRACK\tweapstnd\t0\t0\t\t\t\tSolid,Light\t1\t0\t96\t\r\nOBJ_BARREL\tbarrel\t1\t15\t\t\t\tSolid,MissilesPassThrough,Light,Breakable\t1\t9\t96\tBottom,Middle\r\nOBJ_BARRELEX\tbarrelex\t1\t15\t\t\t\tSolid,MissilesPassThrough,Light,Breakable\t1\t10\t96\tBottom,Middle\r\nOBJ_SHRINEL\tlshrineg\t0\t0\t\tTHEME_SHRINE\t\tLight\t1\t11\t128\tBottom,Middle\r\nOBJ_SHRINER\trshrineg\t0\t0\t\tTHEME_SHRINE\t\tLight\t1\t11\t128\tBottom,Middle\r\nOBJ_SKELBOOK\tbook2\t0\t0\t\tTHEME_SKELROOM\t\tSolid,MissilesPassThrough,Light\t4\t0\t96\tBottom,Middle\r\nOBJ_BOOKCASEL\tbcase\t0\t0\t\tTHEME_LIBRARY\t\tSolid,Light\t3\t0\t96\tBottom,Middle\r\nOBJ_BOOKCASER\tbcase\t0\t0\t\tTHEME_LIBRARY\t\tSolid,Light\t4\t0\t96\tBottom,Middle\r\nOBJ_BOOKSTAND\tbook2\t0\t0\t\tTHEME_LIBRARY\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_BOOKCANDLE\tcandle2\t0\t0\t\tTHEME_LIBRARY\t\tAnimated,Solid,MissilesPassThrough,Light\t2\t4\t96\t\r\nOBJ_BLOODFTN\tbloodfnt\t0\t0\t\tTHEME_BLOODFOUNTAIN\t\tAnimated,Solid,MissilesPassThrough,Light\t2\t10\t96\tBottom,Middle\r\nOBJ_DECAP\tdecap\t13\t15\t\tTHEME_DECAPITATED\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom\r\nOBJ_TCHEST1\tchest1\t1\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom\r\nOBJ_TCHEST2\tchest2\t1\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom\r\nOBJ_TCHEST3\tchest3\t1\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom\r\nOBJ_BLINDBOOK\tbook1\t0\t0\t\t\tQ_BLIND\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_BLOODBOOK\tbook1\t0\t0\t\t\tQ_BLOOD\tSolid,MissilesPassThrough,Light\t4\t0\t96\tBottom,Middle\r\nOBJ_PEDESTAL\tpedistl\t0\t0\t\t\tQ_BLOOD\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_L3LDOOR\tl3doors\t0\t0\tDTYPE_CAVES\t\t\tLight,Trap\t1\t0\t64\tBottom,Middle\r\nOBJ_L3RDOOR\tl3doors\t0\t0\tDTYPE_CAVES\t\t\tLight,Trap\t2\t0\t64\tBottom,Middle\r\nOBJ_PURIFYINGFTN\tpfountn\t0\t0\t\tTHEME_PURIFYINGFOUNTAIN\t\tAnimated,Solid,MissilesPassThrough,Light\t2\t10\t128\tBottom,Middle\r\nOBJ_ARMORSTAND\tarmstand\t0\t0\t\tTHEME_ARMORSTAND\t\tSolid,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_ARMORSTANDN\tarmstand\t0\t0\t\tTHEME_ARMORSTAND\t\tSolid,Light\t2\t0\t96\t\r\nOBJ_GOATSHRINE\tgoatshrn\t0\t0\t\tTHEME_GOATSHRINE\t\tAnimated,Solid,MissilesPassThrough,Light\t2\t10\t96\tBottom,Middle\r\nOBJ_CAULDRON\tcauldren\t13\t15\t\t\t\tSolid,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_MURKYFTN\tmfountn\t0\t0\t\tTHEME_MURKYFOUNTAIN\t\tAnimated,Solid,MissilesPassThrough,Light\t2\t10\t128\tBottom,Middle\r\nOBJ_TEARFTN\ttfountn\t0\t0\t\tTHEME_TEARFOUNTAIN\t\tAnimated,Solid,MissilesPassThrough,Light\t2\t4\t128\tBottom,Middle\r\nOBJ_ALTBOY\taltboy\t0\t0\t\t\tQ_BETRAYER\tSolid,MissilesPassThrough,Light\t1\t0\t128\t\r\nOBJ_MCIRCLE1\tmcirl\t0\t0\t\t\tQ_BETRAYER\tMissilesPassThrough,Light\t1\t0\t96\t\r\nOBJ_MCIRCLE2\tmcirl\t0\t0\t\t\tQ_BETRAYER\tMissilesPassThrough,Light\t1\t0\t96\t\r\nOBJ_STORYBOOK\tbkslbrnt\t0\t0\t\t\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_STORYCANDLE\tcandle2\t0\t0\t\t\tQ_BETRAYER\tAnimated,Solid,MissilesPassThrough,Light\t2\t4\t96\t\r\nOBJ_STEELTOME\tbook1\t0\t0\t\t\tQ_WARLORD\tSolid,MissilesPassThrough,Light\t4\t0\t96\tBottom,Middle\r\nOBJ_WARARMOR\tarmstand\t0\t0\t\t\tQ_WARLORD\tSolid,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_WARWEAP\tweapstnd\t0\t0\t\t\tQ_WARLORD\tSolid,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_TBCROSS\tburncros\t0\t0\t\tTHEME_BRNCROSS\t\tAnimated,Solid\t0\t10\t160\t\r\nOBJ_WEAPONRACK\tweapstnd\t0\t0\t\tTHEME_WEAPONRACK\t\tSolid,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_WEAPONRACKN\tweapstnd\t0\t0\t\tTHEME_WEAPONRACK\t\tSolid,Light\t2\t0\t96\t\r\nOBJ_MUSHPATCH\tmushptch\t0\t0\t\t\tQ_MUSHROOM\tSolid,MissilesPassThrough,Light,Trap\t1\t0\t96\tBottom,Middle\r\nOBJ_LAZSTAND\tlzstand\t0\t0\t\t\tQ_BETRAYER\tSolid,Light\t1\t0\t128\tBottom,Middle\r\nOBJ_SLAINHERO\tdecap\t9\t9\t\t\t\tSolid,MissilesPassThrough,Light\t2\t0\t96\tBottom\r\nOBJ_SIGNCHEST\tchest3\t0\t0\t\t\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom\r\nOBJ_BOOKSHELFR\tbcase\t0\t0\t\t\t\tSolid,Light\t2\t0\t96\t\r\nOBJ_POD\tl6pod1\t17\t20\t\t\t\tSolid,MissilesPassThrough,Light,Breakable\t1\t9\t96\tBottom,Middle\r\nOBJ_PODEX\tl6pod2\t17\t20\t\t\t\tSolid,MissilesPassThrough,Light,Breakable\t1\t10\t96\tBottom,Middle\r\nOBJ_URN\turn\t21\t24\t\t\t\tSolid,MissilesPassThrough,Light,Breakable\t1\t9\t96\tBottom,Middle\r\nOBJ_URNEX\turnexpld\t21\t24\t\t\t\tSolid,MissilesPassThrough,Light,Breakable\t1\t10\t96\tBottom,Middle\r\nOBJ_L5BOOKS\tl5books\t21\t24\t\t\t\tSolid,MissilesPassThrough,Light\t1\t0\t96\tBottom,Middle\r\nOBJ_L5CANDLE\tl5light\t21\t23\t\t\t\tAnimated,Solid,MissilesPassThrough,Light\t2\t4\t96\t\r\nOBJ_L5LDOOR\tl5door\t0\t0\tDTYPE_CRYPT\t\t\tLight,Trap\t1\t0\t64\tBottom,Middle\r\nOBJ_L5RDOOR\tl5door\t0\t0\tDTYPE_CRYPT\t\t\tLight,Trap\t2\t0\t64\tBottom,Middle\r\nOBJ_L5LEVER\tl5lever\t24\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t1\t96\tBottom\r\nOBJ_L5SARC\tl5sarco\t21\t24\t\t\t\tSolid,MissilesPassThrough,Light,Trap\t1\t5\t128\tBottom,Middle\r\n"
  },
  {
    "path": "assets/txtdata/quests/questdat.tsv",
    "content": "qdlvl\tqdmultlvl\tqlvlt\tbookOrder\tqdrnd\tqslvl\tisSinglePlayerOnly\tqdmsg\tqlstr\r\n5\t-1\t\t5\t100\tSL_NONE\ttrue\tTEXT_INFRA5\tThe Magic Rock\r\n9\t-1\t\t10\t100\tSL_NONE\ttrue\tTEXT_MUSH8\tBlack Mushroom\r\n4\t-1\t\t3\t100\tSL_NONE\ttrue\tTEXT_GARBUD1\tGharbad The Weak\r\n8\t-1\t\t9\t100\tSL_NONE\ttrue\tTEXT_ZHAR1\tZhar the Mad\r\n14\t-1\t\t21\t100\tSL_NONE\ttrue\tTEXT_VEIL9\tLachdanan\r\n15\t-1\t\t23\t100\tSL_NONE\tfalse\tTEXT_VILE3\tDiablo\r\n2\t2\t\t0\t100\tSL_NONE\tfalse\tTEXT_BUTCH9\tThe Butcher\r\n4\t-1\t\t4\t100\tSL_NONE\ttrue\tTEXT_BANNER2\tOgden's Sign\r\n7\t-1\t\t8\t100\tSL_NONE\ttrue\tTEXT_BLINDING\tHalls of the Blind\r\n5\t-1\t\t6\t100\tSL_NONE\ttrue\tTEXT_BLOODY\tValor\r\n10\t-1\t\t11\t100\tSL_NONE\ttrue\tTEXT_ANVIL5\tAnvil of Fury\r\n13\t-1\t\t20\t100\tSL_NONE\ttrue\tTEXT_BLOODWAR\tWarlord of Blood\r\n3\t3\tDTYPE_CATHEDRAL\t2\t100\tSL_SKELKING\tfalse\tTEXT_KING2\tThe Curse of King Leoric\r\n2\t-1\tDTYPE_CAVES\t1\t100\tSL_POISONWATER\ttrue\tTEXT_POISON3\tPoisoned Water Supply\r\n6\t-1\tDTYPE_CATACOMBS\t7\t100\tSL_BONECHAMB\ttrue\tTEXT_BONER\tThe Chamber of Bone\r\n15\t15\tDTYPE_CATHEDRAL\t22\t100\tSL_VILEBETRAYER\tfalse\tTEXT_VILE1\tArchbishop Lazarus\r\n17\t17\t\t17\t100\tSL_NONE\tfalse\tTEXT_GRAVE7\tGrave Matters\r\n9\t9\t\t12\t100\tSL_NONE\tfalse\tTEXT_FARMER1\tFarmer's Orchard\r\n17\t-1\t\t14\t100\tSL_NONE\ttrue\tTEXT_GIRL2\tLittle Girl\r\n19\t-1\t\t16\t100\tSL_NONE\ttrue\tTEXT_TRADER\tWandering Trader\r\n17\t17\t\t15\t100\tSL_NONE\tfalse\tTEXT_DEFILER1\tThe Defiler\r\n21\t21\t\t19\t100\tSL_NONE\tfalse\tTEXT_NAKRUL1\tNa-Krul\r\n21\t-1\t\t18\t100\tSL_NONE\ttrue\tTEXT_CORNSTN\tCornerstone of the World\r\n9\t9\t\t13\t100\tSL_NONE\tfalse\tTEXT_JERSEY4\tThe Jersey's Jersey\r\n"
  },
  {
    "path": "assets/txtdata/sound/effects-unused.tsv",
    "content": "id\tflags\tpath\r\nBrutalHit\tMisc\tsfx\\items\\bhit.wav\r\nBrutalHit1\tMisc\tsfx\\items\\bhit1.wav\r\nSpellGuardianHit\tMisc\tsfx\\misc\\grdlanch.wav\r\nGriswold11\tStream\tsfx\\towners\\bsmith11.wav\r\nGriswold54\tStream\tsfx\\towners\\bsmith54.wav\r\nCain32\tStream\tsfx\\towners\\storyt32.wav\r\nOgden42\tStream\tsfx\\towners\\tavown42.wav\r\nWarrior95b\tStream,Warrior\tsfx\\warrior\\wario95b.wav\r\nWarrior95c\tStream,Warrior\tsfx\\warrior\\wario95c.wav\r\nWarrior95d\tStream,Warrior\tsfx\\warrior\\wario95d.wav\r\nWarrior95e\tStream,Warrior\tsfx\\warrior\\wario95e.wav\r\nWarrior95f\tStream,Warrior\tsfx\\warrior\\wario95f.wav\r\nIzual\tStream\tsfx\\monsters\\izual01.wav\r\nLazarusGreetingShort\tStream\tsfx\\monsters\\laz02.wav\r\nWarlock\tStream\tsfx\\monsters\\wlock01.wav\r\n"
  },
  {
    "path": "assets/txtdata/sound/effects.tsv",
    "content": "id\tflags\tpath\r\nWalk\tMisc\tsfx\\misc\\walk1.wav\r\nShootBow\tMisc\tsfx\\misc\\bfire.wav\r\nCastSpell\tMisc\tsfx\\misc\\tmag.wav\r\nSwing\tMisc\tsfx\\misc\\swing.wav\r\nSwing2\tMisc\tsfx\\misc\\swing2.wav\r\nWarriorDeath\tMisc\tsfx\\misc\\dead.wav\r\nQuestDone\tStream\tsfx\\misc\\questdon.wav\r\nBarrelExpload\tMisc\tsfx\\items\\barlfire.wav\r\nBarrelBreak\tMisc\tsfx\\items\\barrel.wav\r\nChestOpen\tMisc\tsfx\\items\\chest.wav\r\nDoorClose\tMisc\tsfx\\items\\doorclos.wav\r\nDoorOpen\tMisc\tsfx\\items\\dooropen.wav\r\nItemAnvilFlip\tMisc\tsfx\\items\\flipanvl.wav\r\nItemAxeFlip\tMisc\tsfx\\items\\flipaxe.wav\r\nItemBloodStoneFlip\tMisc\tsfx\\items\\flipblst.wav\r\nItemBodyPartFlip\tMisc\tsfx\\items\\flipbody.wav\r\nItemBookFlip\tMisc\tsfx\\items\\flipbook.wav\r\nItemBowFlip\tMisc\tsfx\\items\\flipbow.wav\r\nItemCapFlip\tMisc\tsfx\\items\\flipcap.wav\r\nItemArmorFlip\tMisc\tsfx\\items\\flipharm.wav\r\nItemLeatherFlip\tMisc\tsfx\\items\\fliplarm.wav\r\nItemMushroomFlip\tMisc\tsfx\\items\\flipmush.wav\r\nItemPotionFlip\tMisc\tsfx\\items\\flippot.wav\r\nItemRingFlip\tMisc\tsfx\\items\\flipring.wav\r\nItemRockFlip\tMisc\tsfx\\items\\fliprock.wav\r\nItemScrollFlip\tMisc\tsfx\\items\\flipscrl.wav\r\nItemShieldFlip\tMisc\tsfx\\items\\flipshld.wav\r\nItemSignFlip\tMisc\tsfx\\items\\flipsign.wav\r\nItemStaffFlip\tMisc\tsfx\\items\\flipstaf.wav\r\nItemSwordFlip\tMisc\tsfx\\items\\flipswor.wav\r\nItemGold\tMisc\tsfx\\items\\gold.wav\r\nItemAnvil\tMisc\tsfx\\items\\invanvl.wav\r\nItemAxe\tMisc\tsfx\\items\\invaxe.wav\r\nItemBloodStone\tMisc\tsfx\\items\\invblst.wav\r\nItemBodyPart\tMisc\tsfx\\items\\invbody.wav\r\nItemBook\tMisc\tsfx\\items\\invbook.wav\r\nItemBow\tMisc\tsfx\\items\\invbow.wav\r\nItemCap\tMisc\tsfx\\items\\invcap.wav\r\nGrabItem\tMisc\tsfx\\items\\invgrab.wav\r\nItemArmor\tMisc\tsfx\\items\\invharm.wav\r\nItemLeather\tMisc\tsfx\\items\\invlarm.wav\r\nItemMushroom\tMisc\tsfx\\items\\invmush.wav\r\nItemPotion\tMisc\tsfx\\items\\invpot.wav\r\nItemRing\tMisc\tsfx\\items\\invring.wav\r\nItemRock\tMisc\tsfx\\items\\invrock.wav\r\nItemScroll\tMisc\tsfx\\items\\invscrol.wav\r\nItemShield\tMisc\tsfx\\items\\invshiel.wav\r\nItemSign\tMisc\tsfx\\items\\invsign.wav\r\nItemStaff\tMisc\tsfx\\items\\invstaf.wav\r\nItemSword\tMisc\tsfx\\items\\invsword.wav\r\nOperateLever\tMisc\tsfx\\items\\lever.wav\r\nOperateShrine\tMisc\tsfx\\items\\magic.wav\r\nOperateShrine1\tMisc\tsfx\\items\\magic1.wav\r\nReadBook\tMisc\tsfx\\items\\readbook.wav\r\nSarcophagus\tMisc\tsfx\\items\\sarc.wav\r\nMenuMove\tUi\tsfx\\items\\titlemov.wav\r\nMenuSelect\tUi\tsfx\\items\\titlslct.wav\r\nTriggerTrap\tMisc\tsfx\\items\\trap.wav\r\nCastFire\tMisc\tsfx\\misc\\cast2.wav\r\nCastLightning\tMisc\tsfx\\misc\\cast4.wav\r\nCastSkill\tMisc\tsfx\\misc\\cast6.wav\r\nSpellEnd\tMisc\tsfx\\misc\\cast7.wav\r\nCastHealing\tMisc\tsfx\\misc\\cast8.wav\r\nSpellRepair\tMisc\tsfx\\misc\\repair.wav\r\nSpellAcid\tMisc\tsfx\\misc\\acids1.wav\r\nSpellAcid1\tMisc\tsfx\\misc\\acids2.wav\r\nSpellApocalypse\tMisc\tsfx\\misc\\apoc.wav\r\nSpellBloodStar\tMisc\tsfx\\misc\\blodstar.wav\r\nSpellBloodStarHit\tMisc\tsfx\\misc\\blsimpt.wav\r\nSpellBoneSpirit\tMisc\tsfx\\misc\\bonesp.wav\r\nSpellBoneSpiritHit\tMisc\tsfx\\misc\\bsimpct.wav\r\nOperateCaldron\tMisc\tsfx\\misc\\caldron.wav\r\nSpellChargedBolt\tMisc\tsfx\\misc\\cbolt.wav\r\nSpellDoomSerpents\tMisc\tsfx\\misc\\dserp.wav\r\nSpellLightningHit\tMisc\tsfx\\misc\\elecimp1.wav\r\nSpellElemental\tMisc\tsfx\\misc\\elementl.wav\r\nSpellEtherealize\tMisc\tsfx\\misc\\ethereal.wav\r\nSpellFirebolt\tMisc\tsfx\\misc\\fbolt1.wav\r\nSpellFireHit\tMisc\tsfx\\misc\\firimp2.wav\r\nSpellFlameWave\tMisc\tsfx\\misc\\flamwave.wav\r\nOperateFountain\tMisc\tsfx\\misc\\fountain.wav\r\nSpellGolem\tMisc\tsfx\\misc\\golum.wav\r\nOperateGoatShrine\tMisc\tsfx\\misc\\gshrine.wav\r\nSpellGuardian\tMisc\tsfx\\misc\\guard.wav\r\nSpellHolyBolt\tMisc\tsfx\\misc\\holybolt.wav\r\nSpellInfravision\tMisc\tsfx\\misc\\infravis.wav\r\nSpellInvisibility\tMisc\tsfx\\misc\\invisibl.wav\r\nSpellLightning\tMisc\tsfx\\misc\\lning1.wav\r\nSpellManaShield\tMisc\tsfx\\misc\\mshield.wav\r\nSpellNova\tMisc\tsfx\\misc\\nova.wav\r\nSpellPuddle\tMisc\tsfx\\misc\\puddle.wav\r\nSpellResurrect\tMisc\tsfx\\misc\\resur.wav\r\nSpellStoneCurse\tMisc\tsfx\\misc\\scurimp.wav\r\nSpellPortal\tMisc\tsfx\\misc\\sentinel.wav\r\nSpellInferno\tMisc\tsfx\\misc\\spoutstr.wav\r\nSpellTrapDisarm\tMisc\tsfx\\misc\\trapdis.wav\r\nSpellTeleport\tMisc\tsfx\\misc\\teleport.wav\r\nSpellFireWall\tMisc\tsfx\\misc\\wallloop.wav\r\nGillian1\tStream\tsfx\\towners\\bmaid01.wav\r\nGillian2\tStream\tsfx\\towners\\bmaid02.wav\r\nGillian3\tStream\tsfx\\towners\\bmaid03.wav\r\nGillian4\tStream\tsfx\\towners\\bmaid04.wav\r\nGillian5\tStream\tsfx\\towners\\bmaid05.wav\r\nGillian6\tStream\tsfx\\towners\\bmaid06.wav\r\nGillian7\tStream\tsfx\\towners\\bmaid07.wav\r\nGillian8\tStream\tsfx\\towners\\bmaid08.wav\r\nGillian9\tStream\tsfx\\towners\\bmaid09.wav\r\nGillian10\tStream\tsfx\\towners\\bmaid10.wav\r\nGillian11\tStream\tsfx\\towners\\bmaid11.wav\r\nGillian12\tStream\tsfx\\towners\\bmaid12.wav\r\nGillian13\tStream\tsfx\\towners\\bmaid13.wav\r\nGillian14\tStream\tsfx\\towners\\bmaid14.wav\r\nGillian15\tStream\tsfx\\towners\\bmaid15.wav\r\nGillian16\tStream\tsfx\\towners\\bmaid16.wav\r\nGillian17\tStream\tsfx\\towners\\bmaid17.wav\r\nGillian18\tStream\tsfx\\towners\\bmaid18.wav\r\nGillian19\tStream\tsfx\\towners\\bmaid19.wav\r\nGillian20\tStream\tsfx\\towners\\bmaid20.wav\r\nGillian21\tStream\tsfx\\towners\\bmaid21.wav\r\nGillian22\tStream\tsfx\\towners\\bmaid22.wav\r\nGillian23\tStream\tsfx\\towners\\bmaid23.wav\r\nGillian24\tStream\tsfx\\towners\\bmaid24.wav\r\nGillian25\tStream\tsfx\\towners\\bmaid25.wav\r\nGillian26\tStream\tsfx\\towners\\bmaid26.wav\r\nGillian27\tStream\tsfx\\towners\\bmaid27.wav\r\nGillian28\tStream\tsfx\\towners\\bmaid28.wav\r\nGillian29\tStream\tsfx\\towners\\bmaid29.wav\r\nGillian30\tStream\tsfx\\towners\\bmaid30.wav\r\nGillian31\tStream\tsfx\\towners\\bmaid31.wav\r\nGillian32\tStream\tsfx\\towners\\bmaid32.wav\r\nGillian33\tStream\tsfx\\towners\\bmaid33.wav\r\nGillian34\tStream\tsfx\\towners\\bmaid34.wav\r\nGillian35\tStream\tsfx\\towners\\bmaid35.wav\r\nGillian36\tStream\tsfx\\towners\\bmaid36.wav\r\nGillian37\tStream\tsfx\\towners\\bmaid37.wav\r\nGillian38\tStream\tsfx\\towners\\bmaid38.wav\r\nGillian39\tStream\tsfx\\towners\\bmaid39.wav\r\nGillian40\tStream\tsfx\\towners\\bmaid40.wav\r\nGriswold1\tStream\tsfx\\towners\\bsmith01.wav\r\nGriswold2\tStream\tsfx\\towners\\bsmith02.wav\r\nGriswold3\tStream\tsfx\\towners\\bsmith03.wav\r\nGriswold4\tStream\tsfx\\towners\\bsmith04.wav\r\nGriswold5\tStream\tsfx\\towners\\bsmith05.wav\r\nGriswold6\tStream\tsfx\\towners\\bsmith06.wav\r\nGriswold7\tStream\tsfx\\towners\\bsmith07.wav\r\nGriswold8\tStream\tsfx\\towners\\bsmith08.wav\r\nGriswold9\tStream\tsfx\\towners\\bsmith09.wav\r\nGriswold10\tStream\tsfx\\towners\\bsmith10.wav\r\nGriswold12\tStream\tsfx\\towners\\bsmith12.wav\r\nGriswold13\tStream\tsfx\\towners\\bsmith13.wav\r\nGriswold14\tStream\tsfx\\towners\\bsmith14.wav\r\nGriswold15\tStream\tsfx\\towners\\bsmith15.wav\r\nGriswold16\tStream\tsfx\\towners\\bsmith16.wav\r\nGriswold17\tStream\tsfx\\towners\\bsmith17.wav\r\nGriswold18\tStream\tsfx\\towners\\bsmith18.wav\r\nGriswold19\tStream\tsfx\\towners\\bsmith19.wav\r\nGriswold20\tStream\tsfx\\towners\\bsmith20.wav\r\nGriswold21\tStream\tsfx\\towners\\bsmith21.wav\r\nGriswold22\tStream\tsfx\\towners\\bsmith22.wav\r\nGriswold23\tStream\tsfx\\towners\\bsmith23.wav\r\nGriswold24\tStream\tsfx\\towners\\bsmith24.wav\r\nGriswold25\tStream\tsfx\\towners\\bsmith25.wav\r\nGriswold26\tStream\tsfx\\towners\\bsmith26.wav\r\nGriswold27\tStream\tsfx\\towners\\bsmith27.wav\r\nGriswold28\tStream\tsfx\\towners\\bsmith28.wav\r\nGriswold29\tStream\tsfx\\towners\\bsmith29.wav\r\nGriswold30\tStream\tsfx\\towners\\bsmith30.wav\r\nGriswold31\tStream\tsfx\\towners\\bsmith31.wav\r\nGriswold32\tStream\tsfx\\towners\\bsmith32.wav\r\nGriswold33\tStream\tsfx\\towners\\bsmith33.wav\r\nGriswold34\tStream\tsfx\\towners\\bsmith34.wav\r\nGriswold35\tStream\tsfx\\towners\\bsmith35.wav\r\nGriswold36\tStream\tsfx\\towners\\bsmith36.wav\r\nGriswold37\tStream\tsfx\\towners\\bsmith37.wav\r\nGriswold38\tStream\tsfx\\towners\\bsmith38.wav\r\nGriswold39\tStream\tsfx\\towners\\bsmith39.wav\r\nGriswold40\tStream\tsfx\\towners\\bsmith40.wav\r\nGriswold41\tStream\tsfx\\towners\\bsmith41.wav\r\nGriswold42\tStream\tsfx\\towners\\bsmith42.wav\r\nGriswold43\tStream\tsfx\\towners\\bsmith43.wav\r\nGriswold44\tStream\tsfx\\towners\\bsmith44.wav\r\nGriswold45\tStream\tsfx\\towners\\bsmith45.wav\r\nGriswold46\tStream\tsfx\\towners\\bsmith46.wav\r\nGriswold47\tStream\tsfx\\towners\\bsmith47.wav\r\nGriswold48\tStream\tsfx\\towners\\bsmith48.wav\r\nGriswold49\tStream\tsfx\\towners\\bsmith49.wav\r\nGriswold50\tStream\tsfx\\towners\\bsmith50.wav\r\nGriswold51\tStream\tsfx\\towners\\bsmith51.wav\r\nGriswold52\tStream\tsfx\\towners\\bsmith52.wav\r\nGriswold53\tStream\tsfx\\towners\\bsmith53.wav\r\nGriswold55\tStream\tsfx\\towners\\bsmith55.wav\r\nGriswold56\tStream\tsfx\\towners\\bsmith56.wav\r\nCow1\tMisc\tsfx\\towners\\cow1.wav\r\nCow2\tMisc\tsfx\\towners\\cow2.wav\r\nWoundedTownsmanOld\tStream\tsfx\\towners\\deadguy2.wav\r\nFarnham1\tStream\tsfx\\towners\\drunk01.wav\r\nFarnham2\tStream\tsfx\\towners\\drunk02.wav\r\nFarnham3\tStream\tsfx\\towners\\drunk03.wav\r\nFarnham4\tStream\tsfx\\towners\\drunk04.wav\r\nFarnham5\tStream\tsfx\\towners\\drunk05.wav\r\nFarnham6\tStream\tsfx\\towners\\drunk06.wav\r\nFarnham7\tStream\tsfx\\towners\\drunk07.wav\r\nFarnham8\tStream\tsfx\\towners\\drunk08.wav\r\nFarnham9\tStream\tsfx\\towners\\drunk09.wav\r\nFarnham10\tStream\tsfx\\towners\\drunk10.wav\r\nFarnham11\tStream\tsfx\\towners\\drunk11.wav\r\nFarnham12\tStream\tsfx\\towners\\drunk12.wav\r\nFarnham13\tStream\tsfx\\towners\\drunk13.wav\r\nFarnham14\tStream\tsfx\\towners\\drunk14.wav\r\nFarnham15\tStream\tsfx\\towners\\drunk15.wav\r\nFarnham16\tStream\tsfx\\towners\\drunk16.wav\r\nFarnham17\tStream\tsfx\\towners\\drunk17.wav\r\nFarnham18\tStream\tsfx\\towners\\drunk18.wav\r\nFarnham19\tStream\tsfx\\towners\\drunk19.wav\r\nFarnham20\tStream\tsfx\\towners\\drunk20.wav\r\nFarnham21\tStream\tsfx\\towners\\drunk21.wav\r\nFarnham22\tStream\tsfx\\towners\\drunk22.wav\r\nFarnham23\tStream\tsfx\\towners\\drunk23.wav\r\nFarnham24\tStream\tsfx\\towners\\drunk24.wav\r\nFarnham25\tStream\tsfx\\towners\\drunk25.wav\r\nFarnham26\tStream\tsfx\\towners\\drunk26.wav\r\nFarnham27\tStream\tsfx\\towners\\drunk27.wav\r\nFarnham28\tStream\tsfx\\towners\\drunk28.wav\r\nFarnham29\tStream\tsfx\\towners\\drunk29.wav\r\nFarnham30\tStream\tsfx\\towners\\drunk30.wav\r\nFarnham31\tStream\tsfx\\towners\\drunk31.wav\r\nFarnham32\tStream\tsfx\\towners\\drunk32.wav\r\nFarnham33\tStream\tsfx\\towners\\drunk33.wav\r\nFarnham34\tStream\tsfx\\towners\\drunk34.wav\r\nFarnham35\tStream\tsfx\\towners\\drunk35.wav\r\nPepin1\tStream\tsfx\\towners\\healer01.wav\r\nPepin2\tStream\tsfx\\towners\\healer02.wav\r\nPepin3\tStream\tsfx\\towners\\healer03.wav\r\nPepin4\tStream\tsfx\\towners\\healer04.wav\r\nPepin5\tStream\tsfx\\towners\\healer05.wav\r\nPepin6\tStream\tsfx\\towners\\healer06.wav\r\nPepin7\tStream\tsfx\\towners\\healer07.wav\r\nPepin8\tStream\tsfx\\towners\\healer08.wav\r\nPepin9\tStream\tsfx\\towners\\healer09.wav\r\nPepin10\tStream\tsfx\\towners\\healer10.wav\r\nPepin11\tStream\tsfx\\towners\\healer11.wav\r\nPepin12\tStream\tsfx\\towners\\healer12.wav\r\nPepin13\tStream\tsfx\\towners\\healer13.wav\r\nPepin14\tStream\tsfx\\towners\\healer14.wav\r\nPepin15\tStream\tsfx\\towners\\healer15.wav\r\nPepin16\tStream\tsfx\\towners\\healer16.wav\r\nPepin17\tStream\tsfx\\towners\\healer17.wav\r\nPepin18\tStream\tsfx\\towners\\healer18.wav\r\nPepin19\tStream\tsfx\\towners\\healer19.wav\r\nPepin20\tStream\tsfx\\towners\\healer20.wav\r\nPepin21\tStream\tsfx\\towners\\healer21.wav\r\nPepin22\tStream\tsfx\\towners\\healer22.wav\r\nPepin23\tStream\tsfx\\towners\\healer23.wav\r\nPepin24\tStream\tsfx\\towners\\healer24.wav\r\nPepin25\tStream\tsfx\\towners\\healer25.wav\r\nPepin26\tStream\tsfx\\towners\\healer26.wav\r\nPepin27\tStream\tsfx\\towners\\healer27.wav\r\nPepin28\tStream\tsfx\\towners\\healer28.wav\r\nPepin29\tStream\tsfx\\towners\\healer29.wav\r\nPepin30\tStream\tsfx\\towners\\healer30.wav\r\nPepin31\tStream\tsfx\\towners\\healer31.wav\r\nPepin32\tStream\tsfx\\towners\\healer32.wav\r\nPepin33\tStream\tsfx\\towners\\healer33.wav\r\nPepin34\tStream\tsfx\\towners\\healer34.wav\r\nPepin35\tStream\tsfx\\towners\\healer35.wav\r\nPepin36\tStream\tsfx\\towners\\healer36.wav\r\nPepin37\tStream\tsfx\\towners\\healer37.wav\r\nPepin38\tStream\tsfx\\towners\\healer38.wav\r\nPepin39\tStream\tsfx\\towners\\healer39.wav\r\nPepin40\tStream\tsfx\\towners\\healer40.wav\r\nPepin41\tStream\tsfx\\towners\\healer41.wav\r\nPepin42\tStream\tsfx\\towners\\healer42.wav\r\nPepin43\tStream\tsfx\\towners\\healer43.wav\r\nPepin44\tStream\tsfx\\towners\\healer44.wav\r\nPepin45\tStream\tsfx\\towners\\healer45.wav\r\nPepin46\tStream\tsfx\\towners\\healer46.wav\r\nPepin47\tStream\tsfx\\towners\\healer47.wav\r\nWirt1\tStream\tsfx\\towners\\pegboy01.wav\r\nWirt2\tStream\tsfx\\towners\\pegboy02.wav\r\nWirt3\tStream\tsfx\\towners\\pegboy03.wav\r\nWirt4\tStream\tsfx\\towners\\pegboy04.wav\r\nWirt5\tStream\tsfx\\towners\\pegboy05.wav\r\nWirt6\tStream\tsfx\\towners\\pegboy06.wav\r\nWirt7\tStream\tsfx\\towners\\pegboy07.wav\r\nWirt8\tStream\tsfx\\towners\\pegboy08.wav\r\nWirt9\tStream\tsfx\\towners\\pegboy09.wav\r\nWirt10\tStream\tsfx\\towners\\pegboy10.wav\r\nWirt11\tStream\tsfx\\towners\\pegboy11.wav\r\nWirt12\tStream\tsfx\\towners\\pegboy12.wav\r\nWirt13\tStream\tsfx\\towners\\pegboy13.wav\r\nWirt14\tStream\tsfx\\towners\\pegboy14.wav\r\nWirt15\tStream\tsfx\\towners\\pegboy15.wav\r\nWirt16\tStream\tsfx\\towners\\pegboy16.wav\r\nWirt17\tStream\tsfx\\towners\\pegboy17.wav\r\nWirt18\tStream\tsfx\\towners\\pegboy18.wav\r\nWirt19\tStream\tsfx\\towners\\pegboy19.wav\r\nWirt20\tStream\tsfx\\towners\\pegboy20.wav\r\nWirt21\tStream\tsfx\\towners\\pegboy21.wav\r\nWirt22\tStream\tsfx\\towners\\pegboy22.wav\r\nWirt23\tStream\tsfx\\towners\\pegboy23.wav\r\nWirt24\tStream\tsfx\\towners\\pegboy24.wav\r\nWirt25\tStream\tsfx\\towners\\pegboy25.wav\r\nWirt26\tStream\tsfx\\towners\\pegboy26.wav\r\nWirt27\tStream\tsfx\\towners\\pegboy27.wav\r\nWirt28\tStream\tsfx\\towners\\pegboy28.wav\r\nWirt29\tStream\tsfx\\towners\\pegboy29.wav\r\nWirt30\tStream\tsfx\\towners\\pegboy30.wav\r\nWirt31\tStream\tsfx\\towners\\pegboy31.wav\r\nWirt32\tStream\tsfx\\towners\\pegboy32.wav\r\nWirt33\tStream\tsfx\\towners\\pegboy33.wav\r\nWirt34\tStream\tsfx\\towners\\pegboy34.wav\r\nWirt35\tStream\tsfx\\towners\\pegboy35.wav\r\nWirt36\tStream\tsfx\\towners\\pegboy36.wav\r\nWirt37\tStream\tsfx\\towners\\pegboy37.wav\r\nWirt38\tStream\tsfx\\towners\\pegboy38.wav\r\nWirt39\tStream\tsfx\\towners\\pegboy39.wav\r\nWirt40\tStream\tsfx\\towners\\pegboy40.wav\r\nWirt41\tStream\tsfx\\towners\\pegboy41.wav\r\nWirt42\tStream\tsfx\\towners\\pegboy42.wav\r\nWirt43\tStream\tsfx\\towners\\pegboy43.wav\r\nTremain0\tStream\tsfx\\towners\\priest00.wav\r\nTremain1\tStream\tsfx\\towners\\priest01.wav\r\nTremain2\tStream\tsfx\\towners\\priest02.wav\r\nTremain3\tStream\tsfx\\towners\\priest03.wav\r\nTremain4\tStream\tsfx\\towners\\priest04.wav\r\nTremain5\tStream\tsfx\\towners\\priest05.wav\r\nTremain6\tStream\tsfx\\towners\\priest06.wav\r\nTremain7\tStream\tsfx\\towners\\priest07.wav\r\nCain0\tStream\tsfx\\towners\\storyt00.wav\r\nCain1\tStream\tsfx\\towners\\storyt01.wav\r\nCain2\tStream\tsfx\\towners\\storyt02.wav\r\nCain3\tStream\tsfx\\towners\\storyt03.wav\r\nCain4\tStream\tsfx\\towners\\storyt04.wav\r\nCain5\tStream\tsfx\\towners\\storyt05.wav\r\nCain6\tStream\tsfx\\towners\\storyt06.wav\r\nCain7\tStream\tsfx\\towners\\storyt07.wav\r\nCain8\tStream\tsfx\\towners\\storyt08.wav\r\nCain9\tStream\tsfx\\towners\\storyt09.wav\r\nCain10\tStream\tsfx\\towners\\storyt10.wav\r\nCain11\tStream\tsfx\\towners\\storyt11.wav\r\nCain12\tStream\tsfx\\towners\\storyt12.wav\r\nCain13\tStream\tsfx\\towners\\storyt13.wav\r\nCain14\tStream\tsfx\\towners\\storyt14.wav\r\nCain15\tStream\tsfx\\towners\\storyt15.wav\r\nCain16\tStream\tsfx\\towners\\storyt16.wav\r\nCain17\tStream\tsfx\\towners\\storyt17.wav\r\nCain18\tStream\tsfx\\towners\\storyt18.wav\r\nCain19\tStream\tsfx\\towners\\storyt19.wav\r\nCain20\tStream\tsfx\\towners\\storyt20.wav\r\nCain21\tStream\tsfx\\towners\\storyt21.wav\r\nCain22\tStream\tsfx\\towners\\storyt22.wav\r\nCain23\tStream\tsfx\\towners\\storyt23.wav\r\nCain24\tStream\tsfx\\towners\\storyt24.wav\r\nCain25\tStream\tsfx\\towners\\storyt25.wav\r\nCain26\tStream\tsfx\\towners\\storyt26.wav\r\nCain27\tStream\tsfx\\towners\\storyt27.wav\r\nCain28\tStream\tsfx\\towners\\storyt28.wav\r\nCain29\tStream\tsfx\\towners\\storyt29.wav\r\nCain30\tStream\tsfx\\towners\\storyt30.wav\r\nCain31\tStream\tsfx\\towners\\storyt31.wav\r\nCain33\tStream\tsfx\\towners\\storyt33.wav\r\nCain34\tStream\tsfx\\towners\\storyt34.wav\r\nCain35\tStream\tsfx\\towners\\storyt35.wav\r\nCain36\tStream\tsfx\\towners\\storyt36.wav\r\nCain37\tStream\tsfx\\towners\\storyt37.wav\r\nCain38\tStream\tsfx\\towners\\storyt38.wav\r\nOgden0\tStream\tsfx\\towners\\tavown00.wav\r\nOgden1\tStream\tsfx\\towners\\tavown01.wav\r\nOgden2\tStream\tsfx\\towners\\tavown02.wav\r\nOgden3\tStream\tsfx\\towners\\tavown03.wav\r\nOgden4\tStream\tsfx\\towners\\tavown04.wav\r\nOgden5\tStream\tsfx\\towners\\tavown05.wav\r\nOgden6\tStream\tsfx\\towners\\tavown06.wav\r\nOgden7\tStream\tsfx\\towners\\tavown07.wav\r\nOgden8\tStream\tsfx\\towners\\tavown08.wav\r\nOgden9\tStream\tsfx\\towners\\tavown09.wav\r\nOgden10\tStream\tsfx\\towners\\tavown10.wav\r\nOgden11\tStream\tsfx\\towners\\tavown11.wav\r\nOgden12\tStream\tsfx\\towners\\tavown12.wav\r\nOgden13\tStream\tsfx\\towners\\tavown13.wav\r\nOgden14\tStream\tsfx\\towners\\tavown14.wav\r\nOgden15\tStream\tsfx\\towners\\tavown15.wav\r\nOgden16\tStream\tsfx\\towners\\tavown16.wav\r\nOgden17\tStream\tsfx\\towners\\tavown17.wav\r\nOgden18\tStream\tsfx\\towners\\tavown18.wav\r\nOgden19\tStream\tsfx\\towners\\tavown19.wav\r\nOgden20\tStream\tsfx\\towners\\tavown20.wav\r\nOgden21\tStream\tsfx\\towners\\tavown21.wav\r\nOgden22\tStream\tsfx\\towners\\tavown22.wav\r\nOgden23\tStream\tsfx\\towners\\tavown23.wav\r\nOgden24\tStream\tsfx\\towners\\tavown24.wav\r\nOgden25\tStream\tsfx\\towners\\tavown25.wav\r\nOgden26\tStream\tsfx\\towners\\tavown26.wav\r\nOgden27\tStream\tsfx\\towners\\tavown27.wav\r\nOgden28\tStream\tsfx\\towners\\tavown28.wav\r\nOgden29\tStream\tsfx\\towners\\tavown29.wav\r\nOgden30\tStream\tsfx\\towners\\tavown30.wav\r\nOgden31\tStream\tsfx\\towners\\tavown31.wav\r\nOgden32\tStream\tsfx\\towners\\tavown32.wav\r\nOgden33\tStream\tsfx\\towners\\tavown33.wav\r\nOgden34\tStream\tsfx\\towners\\tavown34.wav\r\nOgden35\tStream\tsfx\\towners\\tavown35.wav\r\nOgden36\tStream\tsfx\\towners\\tavown36.wav\r\nOgden37\tStream\tsfx\\towners\\tavown37.wav\r\nOgden38\tStream\tsfx\\towners\\tavown38.wav\r\nOgden39\tStream\tsfx\\towners\\tavown39.wav\r\nOgden40\tStream\tsfx\\towners\\tavown40.wav\r\nOgden41\tStream\tsfx\\towners\\tavown41.wav\r\nOgden43\tStream\tsfx\\towners\\tavown43.wav\r\nOgden44\tStream\tsfx\\towners\\tavown44.wav\r\nOgden45\tStream\tsfx\\towners\\tavown45.wav\r\nAdria1\tStream\tsfx\\towners\\witch01.wav\r\nAdria2\tStream\tsfx\\towners\\witch02.wav\r\nAdria3\tStream\tsfx\\towners\\witch03.wav\r\nAdria4\tStream\tsfx\\towners\\witch04.wav\r\nAdria5\tStream\tsfx\\towners\\witch05.wav\r\nAdria6\tStream\tsfx\\towners\\witch06.wav\r\nAdria7\tStream\tsfx\\towners\\witch07.wav\r\nAdria8\tStream\tsfx\\towners\\witch08.wav\r\nAdria9\tStream\tsfx\\towners\\witch09.wav\r\nAdria10\tStream\tsfx\\towners\\witch10.wav\r\nAdria11\tStream\tsfx\\towners\\witch11.wav\r\nAdria12\tStream\tsfx\\towners\\witch12.wav\r\nAdria13\tStream\tsfx\\towners\\witch13.wav\r\nAdria14\tStream\tsfx\\towners\\witch14.wav\r\nAdria15\tStream\tsfx\\towners\\witch15.wav\r\nAdria16\tStream\tsfx\\towners\\witch16.wav\r\nAdria17\tStream\tsfx\\towners\\witch17.wav\r\nAdria18\tStream\tsfx\\towners\\witch18.wav\r\nAdria19\tStream\tsfx\\towners\\witch19.wav\r\nAdria20\tStream\tsfx\\towners\\witch20.wav\r\nAdria21\tStream\tsfx\\towners\\witch21.wav\r\nAdria22\tStream\tsfx\\towners\\witch22.wav\r\nAdria23\tStream\tsfx\\towners\\witch23.wav\r\nAdria24\tStream\tsfx\\towners\\witch24.wav\r\nAdria25\tStream\tsfx\\towners\\witch25.wav\r\nAdria26\tStream\tsfx\\towners\\witch26.wav\r\nAdria27\tStream\tsfx\\towners\\witch27.wav\r\nAdria28\tStream\tsfx\\towners\\witch28.wav\r\nAdria29\tStream\tsfx\\towners\\witch29.wav\r\nAdria30\tStream\tsfx\\towners\\witch30.wav\r\nAdria31\tStream\tsfx\\towners\\witch31.wav\r\nAdria32\tStream\tsfx\\towners\\witch32.wav\r\nAdria33\tStream\tsfx\\towners\\witch33.wav\r\nAdria34\tStream\tsfx\\towners\\witch34.wav\r\nAdria35\tStream\tsfx\\towners\\witch35.wav\r\nAdria36\tStream\tsfx\\towners\\witch36.wav\r\nAdria37\tStream\tsfx\\towners\\witch37.wav\r\nAdria38\tStream\tsfx\\towners\\witch38.wav\r\nAdria39\tStream\tsfx\\towners\\witch39.wav\r\nAdria40\tStream\tsfx\\towners\\witch40.wav\r\nAdria41\tStream\tsfx\\towners\\witch41.wav\r\nAdria42\tStream\tsfx\\towners\\witch42.wav\r\nAdria43\tStream\tsfx\\towners\\witch43.wav\r\nAdria44\tStream\tsfx\\towners\\witch44.wav\r\nAdria45\tStream\tsfx\\towners\\witch45.wav\r\nAdria46\tStream\tsfx\\towners\\witch46.wav\r\nAdria47\tStream\tsfx\\towners\\witch47.wav\r\nAdria48\tStream\tsfx\\towners\\witch48.wav\r\nAdria49\tStream\tsfx\\towners\\witch49.wav\r\nAdria50\tStream\tsfx\\towners\\witch50.wav\r\nWoundedTownsman\tStream\tsfx\\towners\\wound01.wav\r\nSorceror1\tStream,Sorcerer\tsfx\\sorceror\\mage01.wav\r\nSorceror2\tStream,Sorcerer\tsfx\\sorceror\\mage02.wav\r\nSorceror3\tStream,Sorcerer\tsfx\\sorceror\\mage03.wav\r\nSorceror4\tStream,Sorcerer\tsfx\\sorceror\\mage04.wav\r\nSorceror5\tStream,Sorcerer\tsfx\\sorceror\\mage05.wav\r\nSorceror6\tStream,Sorcerer\tsfx\\sorceror\\mage06.wav\r\nSorceror7\tStream,Sorcerer\tsfx\\sorceror\\mage07.wav\r\nSorceror8\tStream,Sorcerer\tsfx\\sorceror\\mage08.wav\r\nSorceror9\tStream,Sorcerer\tsfx\\sorceror\\mage09.wav\r\nSorceror10\tStream,Sorcerer\tsfx\\sorceror\\mage10.wav\r\nSorceror11\tStream,Sorcerer\tsfx\\sorceror\\mage11.wav\r\nSorceror12\tStream,Sorcerer\tsfx\\sorceror\\mage12.wav\r\nSorceror13\tSorcerer\tsfx\\sorceror\\mage13.wav\r\nSorceror14\tSorcerer\tsfx\\sorceror\\mage14.wav\r\nSorceror15\tSorcerer\tsfx\\sorceror\\mage15.wav\r\nSorceror16\tSorcerer\tsfx\\sorceror\\mage16.wav\r\nSorceror17\tSorcerer\tsfx\\sorceror\\mage17.wav\r\nSorceror18\tSorcerer\tsfx\\sorceror\\mage18.wav\r\nSorceror19\tSorcerer\tsfx\\sorceror\\mage19.wav\r\nSorceror20\tSorcerer\tsfx\\sorceror\\mage20.wav\r\nSorceror21\tSorcerer\tsfx\\sorceror\\mage21.wav\r\nSorceror22\tSorcerer\tsfx\\sorceror\\mage22.wav\r\nSorceror23\tSorcerer\tsfx\\sorceror\\mage23.wav\r\nSorceror24\tSorcerer\tsfx\\sorceror\\mage24.wav\r\nSorceror25\tSorcerer\tsfx\\sorceror\\mage25.wav\r\nSorceror26\tSorcerer\tsfx\\sorceror\\mage26.wav\r\nSorceror27\tSorcerer\tsfx\\sorceror\\mage27.wav\r\nSorceror28\tSorcerer\tsfx\\sorceror\\mage28.wav\r\nSorceror29\tSorcerer\tsfx\\sorceror\\mage29.wav\r\nSorceror30\tSorcerer\tsfx\\sorceror\\mage30.wav\r\nSorceror31\tSorcerer\tsfx\\sorceror\\mage31.wav\r\nSorceror32\tSorcerer\tsfx\\sorceror\\mage32.wav\r\nSorceror33\tSorcerer\tsfx\\sorceror\\mage33.wav\r\nSorceror34\tSorcerer\tsfx\\sorceror\\mage34.wav\r\nSorceror35\tSorcerer\tsfx\\sorceror\\mage35.wav\r\nSorceror36\tSorcerer\tsfx\\sorceror\\mage36.wav\r\nSorceror37\tSorcerer\tsfx\\sorceror\\mage37.wav\r\nSorceror38\tSorcerer\tsfx\\sorceror\\mage38.wav\r\nSorceror39\tSorcerer\tsfx\\sorceror\\mage39.wav\r\nSorceror40\tSorcerer\tsfx\\sorceror\\mage40.wav\r\nSorceror41\tSorcerer\tsfx\\sorceror\\mage41.wav\r\nSorceror42\tSorcerer\tsfx\\sorceror\\mage42.wav\r\nSorceror43\tSorcerer\tsfx\\sorceror\\mage43.wav\r\nSorceror44\tSorcerer\tsfx\\sorceror\\mage44.wav\r\nSorceror45\tSorcerer\tsfx\\sorceror\\mage45.wav\r\nSorceror46\tSorcerer\tsfx\\sorceror\\mage46.wav\r\nSorceror47\tSorcerer\tsfx\\sorceror\\mage47.wav\r\nSorceror48\tSorcerer\tsfx\\sorceror\\mage48.wav\r\nSorceror49\tSorcerer\tsfx\\sorceror\\mage49.wav\r\nSorceror50\tSorcerer\tsfx\\sorceror\\mage50.wav\r\nSorceror51\tStream,Sorcerer\tsfx\\sorceror\\mage51.wav\r\nSorceror52\tStream,Sorcerer\tsfx\\sorceror\\mage52.wav\r\nSorceror53\tStream,Sorcerer\tsfx\\sorceror\\mage53.wav\r\nSorceror54\tStream,Sorcerer\tsfx\\sorceror\\mage54.wav\r\nSorceror55\tStream,Sorcerer\tsfx\\sorceror\\mage55.wav\r\nSorceror56\tStream,Sorcerer\tsfx\\sorceror\\mage56.wav\r\nSorceror57\tSorcerer\tsfx\\sorceror\\mage57.wav\r\nSorceror58\tStream,Sorcerer\tsfx\\sorceror\\mage58.wav\r\nSorceror59\tStream,Sorcerer\tsfx\\sorceror\\mage59.wav\r\nSorceror60\tStream,Sorcerer\tsfx\\sorceror\\mage60.wav\r\nSorceror61\tStream,Sorcerer\tsfx\\sorceror\\mage61.wav\r\nSorceror62\tStream,Sorcerer\tsfx\\sorceror\\mage62.wav\r\nSorceror63\tStream,Sorcerer\tsfx\\sorceror\\mage63.wav\r\nSorceror64\tSorcerer\tsfx\\sorceror\\mage64.wav\r\nSorceror65\tSorcerer\tsfx\\sorceror\\mage65.wav\r\nSorceror66\tSorcerer\tsfx\\sorceror\\mage66.wav\r\nSorceror67\tSorcerer\tsfx\\sorceror\\mage67.wav\r\nSorceror68\tSorcerer\tsfx\\sorceror\\mage68.wav\r\nSorceror69\tSorcerer\tsfx\\sorceror\\mage69.wav\r\nSorceror69b\tSorcerer\tsfx\\sorceror\\mage69b.wav\r\nSorceror70\tSorcerer\tsfx\\sorceror\\mage70.wav\r\nSorceror71\tSorcerer\tsfx\\sorceror\\mage71.wav\r\nSorceror72\tSorcerer\tsfx\\sorceror\\mage72.wav\r\nSorceror73\tSorcerer\tsfx\\sorceror\\mage73.wav\r\nSorceror74\tSorcerer\tsfx\\sorceror\\mage74.wav\r\nSorceror75\tSorcerer\tsfx\\sorceror\\mage75.wav\r\nSorceror76\tSorcerer\tsfx\\sorceror\\mage76.wav\r\nSorceror77\tSorcerer\tsfx\\sorceror\\mage77.wav\r\nSorceror78\tSorcerer\tsfx\\sorceror\\mage78.wav\r\nSorceror79\tSorcerer\tsfx\\sorceror\\mage79.wav\r\nSorceror80\tStream,Sorcerer\tsfx\\sorceror\\mage80.wav\r\nSorceror81\tStream,Sorcerer\tsfx\\sorceror\\mage81.wav\r\nSorceror82\tStream,Sorcerer\tsfx\\sorceror\\mage82.wav\r\nSorceror83\tStream,Sorcerer\tsfx\\sorceror\\mage83.wav\r\nSorceror84\tStream,Sorcerer\tsfx\\sorceror\\mage84.wav\r\nSorceror85\tStream,Sorcerer\tsfx\\sorceror\\mage85.wav\r\nSorceror86\tStream,Sorcerer\tsfx\\sorceror\\mage86.wav\r\nSorceror87\tStream,Sorcerer\tsfx\\sorceror\\mage87.wav\r\nSorceror88\tStream,Sorcerer\tsfx\\sorceror\\mage88.wav\r\nSorceror89\tStream,Sorcerer\tsfx\\sorceror\\mage89.wav\r\nSorceror90\tStream,Sorcerer\tsfx\\sorceror\\mage90.wav\r\nSorceror91\tStream,Sorcerer\tsfx\\sorceror\\mage91.wav\r\nSorceror92\tStream,Sorcerer\tsfx\\sorceror\\mage92.wav\r\nSorceror93\tStream,Sorcerer\tsfx\\sorceror\\mage93.wav\r\nSorceror94\tStream,Sorcerer\tsfx\\sorceror\\mage94.wav\r\nSorceror95\tStream,Sorcerer\tsfx\\sorceror\\mage95.wav\r\nSorceror96\tStream,Sorcerer\tsfx\\sorceror\\mage96.wav\r\nSorceror97\tStream,Sorcerer\tsfx\\sorceror\\mage97.wav\r\nSorceror98\tStream,Sorcerer\tsfx\\sorceror\\mage98.wav\r\nSorceror99\tStream,Sorcerer\tsfx\\sorceror\\mage99.wav\r\nSorceror100\tStream,Sorcerer\tsfx\\sorceror\\mage100.wav\r\nSorceror101\tStream,Sorcerer\tsfx\\sorceror\\mage101.wav\r\nSorceror102\tStream,Sorcerer\tsfx\\sorceror\\mage102.wav\r\nRogue1\tStream,Rogue\tsfx\\rogue\\rogue01.wav\r\nRogue2\tStream,Rogue\tsfx\\rogue\\rogue02.wav\r\nRogue3\tStream,Rogue\tsfx\\rogue\\rogue03.wav\r\nRogue4\tStream,Rogue\tsfx\\rogue\\rogue04.wav\r\nRogue5\tStream,Rogue\tsfx\\rogue\\rogue05.wav\r\nRogue6\tStream,Rogue\tsfx\\rogue\\rogue06.wav\r\nRogue7\tStream,Rogue\tsfx\\rogue\\rogue07.wav\r\nRogue8\tStream,Rogue\tsfx\\rogue\\rogue08.wav\r\nRogue9\tStream,Rogue\tsfx\\rogue\\rogue09.wav\r\nRogue10\tStream,Rogue\tsfx\\rogue\\rogue10.wav\r\nRogue11\tStream,Rogue\tsfx\\rogue\\rogue11.wav\r\nRogue12\tStream,Rogue\tsfx\\rogue\\rogue12.wav\r\nRogue13\tRogue\tsfx\\rogue\\rogue13.wav\r\nRogue14\tRogue\tsfx\\rogue\\rogue14.wav\r\nRogue15\tRogue\tsfx\\rogue\\rogue15.wav\r\nRogue16\tRogue\tsfx\\rogue\\rogue16.wav\r\nRogue17\tRogue\tsfx\\rogue\\rogue17.wav\r\nRogue18\tRogue\tsfx\\rogue\\rogue18.wav\r\nRogue19\tRogue\tsfx\\rogue\\rogue19.wav\r\nRogue20\tRogue\tsfx\\rogue\\rogue20.wav\r\nRogue21\tRogue\tsfx\\rogue\\rogue21.wav\r\nRogue22\tRogue\tsfx\\rogue\\rogue22.wav\r\nRogue23\tRogue\tsfx\\rogue\\rogue23.wav\r\nRogue24\tRogue\tsfx\\rogue\\rogue24.wav\r\nRogue25\tRogue\tsfx\\rogue\\rogue25.wav\r\nRogue26\tRogue\tsfx\\rogue\\rogue26.wav\r\nRogue27\tRogue\tsfx\\rogue\\rogue27.wav\r\nRogue28\tRogue\tsfx\\rogue\\rogue28.wav\r\nRogue29\tRogue\tsfx\\rogue\\rogue29.wav\r\nRogue30\tRogue\tsfx\\rogue\\rogue30.wav\r\nRogue31\tRogue\tsfx\\rogue\\rogue31.wav\r\nRogue32\tRogue\tsfx\\rogue\\rogue32.wav\r\nRogue33\tRogue\tsfx\\rogue\\rogue33.wav\r\nRogue34\tRogue\tsfx\\rogue\\rogue34.wav\r\nRogue35\tRogue\tsfx\\rogue\\rogue35.wav\r\nRogue36\tRogue\tsfx\\rogue\\rogue36.wav\r\nRogue37\tRogue\tsfx\\rogue\\rogue37.wav\r\nRogue38\tRogue\tsfx\\rogue\\rogue38.wav\r\nRogue39\tRogue\tsfx\\rogue\\rogue39.wav\r\nRogue40\tRogue\tsfx\\rogue\\rogue40.wav\r\nRogue41\tRogue\tsfx\\rogue\\rogue41.wav\r\nRogue42\tRogue\tsfx\\rogue\\rogue42.wav\r\nRogue43\tRogue\tsfx\\rogue\\rogue43.wav\r\nRogue44\tRogue\tsfx\\rogue\\rogue44.wav\r\nRogue45\tRogue\tsfx\\rogue\\rogue45.wav\r\nRogue46\tRogue\tsfx\\rogue\\rogue46.wav\r\nRogue47\tRogue\tsfx\\rogue\\rogue47.wav\r\nRogue48\tRogue\tsfx\\rogue\\rogue48.wav\r\nRogue49\tRogue\tsfx\\rogue\\rogue49.wav\r\nRogue50\tRogue\tsfx\\rogue\\rogue50.wav\r\nRogue51\tStream,Rogue\tsfx\\rogue\\rogue51.wav\r\nRogue52\tStream,Rogue\tsfx\\rogue\\rogue52.wav\r\nRogue53\tStream,Rogue\tsfx\\rogue\\rogue53.wav\r\nRogue54\tStream,Rogue\tsfx\\rogue\\rogue54.wav\r\nRogue55\tStream,Rogue\tsfx\\rogue\\rogue55.wav\r\nRogue56\tStream,Rogue\tsfx\\rogue\\rogue56.wav\r\nRogue57\tRogue\tsfx\\rogue\\rogue57.wav\r\nRogue58\tStream,Rogue\tsfx\\rogue\\rogue58.wav\r\nRogue59\tStream,Rogue\tsfx\\rogue\\rogue59.wav\r\nRogue60\tStream,Rogue\tsfx\\rogue\\rogue60.wav\r\nRogue61\tStream,Rogue\tsfx\\rogue\\rogue61.wav\r\nRogue62\tStream,Rogue\tsfx\\rogue\\rogue62.wav\r\nRogue63\tStream,Rogue\tsfx\\rogue\\rogue63.wav\r\nRogue64\tRogue\tsfx\\rogue\\rogue64.wav\r\nRogue65\tRogue\tsfx\\rogue\\rogue65.wav\r\nRogue66\tRogue\tsfx\\rogue\\rogue66.wav\r\nRogue67\tRogue\tsfx\\rogue\\rogue67.wav\r\nRogue68\tRogue\tsfx\\rogue\\rogue68.wav\r\nRogue69\tRogue\tsfx\\rogue\\rogue69.wav\r\nRogue69b\tRogue\tsfx\\rogue\\rogue69b.wav\r\nRogue70\tRogue\tsfx\\rogue\\rogue70.wav\r\nRogue71\tRogue\tsfx\\rogue\\rogue71.wav\r\nRogue72\tRogue\tsfx\\rogue\\rogue72.wav\r\nRogue73\tRogue\tsfx\\rogue\\rogue73.wav\r\nRogue74\tRogue\tsfx\\rogue\\rogue74.wav\r\nRogue75\tRogue\tsfx\\rogue\\rogue75.wav\r\nRogue76\tRogue\tsfx\\rogue\\rogue76.wav\r\nRogue77\tRogue\tsfx\\rogue\\rogue77.wav\r\nRogue78\tRogue\tsfx\\rogue\\rogue78.wav\r\nRogue79\tRogue\tsfx\\rogue\\rogue79.wav\r\nRogue80\tStream,Rogue\tsfx\\rogue\\rogue80.wav\r\nRogue81\tStream,Rogue\tsfx\\rogue\\rogue81.wav\r\nRogue82\tStream,Rogue\tsfx\\rogue\\rogue82.wav\r\nRogue83\tStream,Rogue\tsfx\\rogue\\rogue83.wav\r\nRogue84\tStream,Rogue\tsfx\\rogue\\rogue84.wav\r\nRogue85\tStream,Rogue\tsfx\\rogue\\rogue85.wav\r\nRogue86\tStream,Rogue\tsfx\\rogue\\rogue86.wav\r\nRogue87\tStream,Rogue\tsfx\\rogue\\rogue87.wav\r\nRogue88\tStream,Rogue\tsfx\\rogue\\rogue88.wav\r\nRogue89\tStream,Rogue\tsfx\\rogue\\rogue89.wav\r\nRogue90\tStream,Rogue\tsfx\\rogue\\rogue90.wav\r\nRogue91\tStream,Rogue\tsfx\\rogue\\rogue91.wav\r\nRogue92\tStream,Rogue\tsfx\\rogue\\rogue92.wav\r\nRogue93\tStream,Rogue\tsfx\\rogue\\rogue93.wav\r\nRogue94\tStream,Rogue\tsfx\\rogue\\rogue94.wav\r\nRogue95\tStream,Rogue\tsfx\\rogue\\rogue95.wav\r\nRogue96\tStream,Rogue\tsfx\\rogue\\rogue96.wav\r\nRogue97\tStream,Rogue\tsfx\\rogue\\rogue97.wav\r\nRogue98\tStream,Rogue\tsfx\\rogue\\rogue98.wav\r\nRogue99\tStream,Rogue\tsfx\\rogue\\rogue99.wav\r\nRogue100\tStream,Rogue\tsfx\\rogue\\rogue100.wav\r\nRogue101\tStream,Rogue\tsfx\\rogue\\rogue101.wav\r\nRogue102\tStream,Rogue\tsfx\\rogue\\rogue102.wav\r\nWarrior1\tStream,Warrior\tsfx\\warrior\\warior01.wav\r\nWarrior2\tStream,Warrior\tsfx\\warrior\\warior02.wav\r\nWarrior3\tStream,Warrior\tsfx\\warrior\\warior03.wav\r\nWarrior4\tStream,Warrior\tsfx\\warrior\\warior04.wav\r\nWarrior5\tStream,Warrior\tsfx\\warrior\\warior05.wav\r\nWarrior6\tStream,Warrior\tsfx\\warrior\\warior06.wav\r\nWarrior7\tStream,Warrior\tsfx\\warrior\\warior07.wav\r\nWarrior8\tStream,Warrior\tsfx\\warrior\\warior08.wav\r\nWarrior9\tStream,Warrior\tsfx\\warrior\\warior09.wav\r\nWarrior10\tStream,Warrior\tsfx\\warrior\\warior10.wav\r\nWarrior11\tStream,Warrior\tsfx\\warrior\\warior11.wav\r\nWarrior12\tStream,Warrior\tsfx\\warrior\\warior12.wav\r\nWarrior13\tWarrior\tsfx\\warrior\\warior13.wav\r\nWarrior14\tWarrior\tsfx\\warrior\\warior14.wav\r\nWarrior14b\tWarrior\tsfx\\warrior\\wario14b.wav\r\nWarrior14c\tWarrior\tsfx\\warrior\\wario14c.wav\r\nWarrior15\tWarrior\tsfx\\warrior\\warior15.wav\r\nWarrior15b\tWarrior\tsfx\\warrior\\wario15b.wav\r\nWarrior15c\tWarrior\tsfx\\warrior\\wario15c.wav\r\nWarrior16\tWarrior\tsfx\\warrior\\warior16.wav\r\nWarrior16b\tWarrior\tsfx\\warrior\\wario16b.wav\r\nWarrior16c\tWarrior\tsfx\\warrior\\wario16c.wav\r\nWarrior17\tWarrior\tsfx\\warrior\\warior17.wav\r\nWarrior18\tWarrior\tsfx\\warrior\\warior18.wav\r\nWarrior19\tWarrior\tsfx\\warrior\\warior19.wav\r\nWarrior20\tWarrior\tsfx\\warrior\\warior20.wav\r\nWarrior21\tWarrior\tsfx\\warrior\\warior21.wav\r\nWarrior22\tWarrior\tsfx\\warrior\\warior22.wav\r\nWarrior23\tWarrior\tsfx\\warrior\\warior23.wav\r\nWarrior24\tWarrior\tsfx\\warrior\\warior24.wav\r\nWarrior25\tWarrior\tsfx\\warrior\\warior25.wav\r\nWarrior26\tWarrior\tsfx\\warrior\\warior26.wav\r\nWarrior27\tWarrior\tsfx\\warrior\\warior27.wav\r\nWarrior28\tWarrior\tsfx\\warrior\\warior28.wav\r\nWarrior29\tWarrior\tsfx\\warrior\\warior29.wav\r\nWarrior30\tWarrior\tsfx\\warrior\\warior30.wav\r\nWarrior31\tWarrior\tsfx\\warrior\\warior31.wav\r\nWarrior32\tWarrior\tsfx\\warrior\\warior32.wav\r\nWarrior33\tWarrior\tsfx\\warrior\\warior33.wav\r\nWarrior34\tWarrior\tsfx\\warrior\\warior34.wav\r\nWarrior35\tWarrior\tsfx\\warrior\\warior35.wav\r\nWarrior36\tWarrior\tsfx\\warrior\\warior36.wav\r\nWarrior37\tWarrior\tsfx\\warrior\\warior37.wav\r\nWarrior38\tWarrior\tsfx\\warrior\\warior38.wav\r\nWarrior39\tWarrior\tsfx\\warrior\\warior39.wav\r\nWarrior40\tWarrior\tsfx\\warrior\\warior40.wav\r\nWarrior41\tWarrior\tsfx\\warrior\\warior41.wav\r\nWarrior42\tWarrior\tsfx\\warrior\\warior42.wav\r\nWarrior43\tWarrior\tsfx\\warrior\\warior43.wav\r\nWarrior44\tWarrior\tsfx\\warrior\\warior44.wav\r\nWarrior45\tWarrior\tsfx\\warrior\\warior45.wav\r\nWarrior46\tWarrior\tsfx\\warrior\\warior46.wav\r\nWarrior47\tWarrior\tsfx\\warrior\\warior47.wav\r\nWarrior48\tWarrior\tsfx\\warrior\\warior48.wav\r\nWarrior49\tWarrior\tsfx\\warrior\\warior49.wav\r\nWarrior50\tWarrior\tsfx\\warrior\\warior50.wav\r\nWarrior51\tStream,Warrior\tsfx\\warrior\\warior51.wav\r\nWarrior52\tStream,Warrior\tsfx\\warrior\\warior52.wav\r\nWarrior53\tStream,Warrior\tsfx\\warrior\\warior53.wav\r\nWarrior54\tStream,Warrior\tsfx\\warrior\\warior54.wav\r\nWarrior55\tStream,Warrior\tsfx\\warrior\\warior55.wav\r\nWarrior56\tStream,Warrior\tsfx\\warrior\\warior56.wav\r\nWarrior57\tWarrior\tsfx\\warrior\\warior57.wav\r\nWarrior58\tStream,Warrior\tsfx\\warrior\\warior58.wav\r\nWarrior59\tStream,Warrior\tsfx\\warrior\\warior59.wav\r\nWarrior60\tStream,Warrior\tsfx\\warrior\\warior60.wav\r\nWarrior61\tStream,Warrior\tsfx\\warrior\\warior61.wav\r\nWarrior62\tStream,Warrior\tsfx\\warrior\\warior62.wav\r\nWarrior63\tStream,Warrior\tsfx\\warrior\\warior63.wav\r\nWarrior64\tWarrior\tsfx\\warrior\\warior64.wav\r\nWarrior65\tWarrior\tsfx\\warrior\\warior65.wav\r\nWarrior66\tWarrior\tsfx\\warrior\\warior66.wav\r\nWarrior67\tWarrior\tsfx\\warrior\\warior67.wav\r\nWarrior68\tWarrior\tsfx\\warrior\\warior68.wav\r\nWarrior69\tWarrior\tsfx\\warrior\\warior69.wav\r\nWarrior69b\tWarrior\tsfx\\warrior\\wario69b.wav\r\nWarrior70\tWarrior\tsfx\\warrior\\warior70.wav\r\nWarrior71\tWarrior\tsfx\\warrior\\warior71.wav\r\nWarrior72\tWarrior\tsfx\\warrior\\warior72.wav\r\nWarrior73\tWarrior\tsfx\\warrior\\warior73.wav\r\nWarrior74\tWarrior\tsfx\\warrior\\warior74.wav\r\nWarrior75\tWarrior\tsfx\\warrior\\warior75.wav\r\nWarrior76\tWarrior\tsfx\\warrior\\warior76.wav\r\nWarrior77\tWarrior\tsfx\\warrior\\warior77.wav\r\nWarrior78\tWarrior\tsfx\\warrior\\warior78.wav\r\nWarrior79\tWarrior\tsfx\\warrior\\warior79.wav\r\nWarrior80\tStream,Warrior\tsfx\\warrior\\warior80.wav\r\nWarrior81\tStream,Warrior\tsfx\\warrior\\warior81.wav\r\nWarrior82\tStream,Warrior\tsfx\\warrior\\warior82.wav\r\nWarrior83\tStream,Warrior\tsfx\\warrior\\warior83.wav\r\nWarrior84\tStream,Warrior\tsfx\\warrior\\warior84.wav\r\nWarrior85\tStream,Warrior\tsfx\\warrior\\warior85.wav\r\nWarrior86\tStream,Warrior\tsfx\\warrior\\warior86.wav\r\nWarrior87\tStream,Warrior\tsfx\\warrior\\warior87.wav\r\nWarrior88\tStream,Warrior\tsfx\\warrior\\warior88.wav\r\nWarrior89\tStream,Warrior\tsfx\\warrior\\warior89.wav\r\nWarrior90\tStream,Warrior\tsfx\\warrior\\warior90.wav\r\nWarrior91\tStream,Warrior\tsfx\\warrior\\warior91.wav\r\nWarrior92\tStream,Warrior\tsfx\\warrior\\warior92.wav\r\nWarrior93\tStream,Warrior\tsfx\\warrior\\warior93.wav\r\nWarrior94\tStream,Warrior\tsfx\\warrior\\warior94.wav\r\nWarrior95\tStream,Warrior\tsfx\\warrior\\warior95.wav\r\nWarrior96b\tStream,Warrior\tsfx\\warrior\\wario96b.wav\r\nWarrior97\tStream,Warrior\tsfx\\warrior\\wario97.wav\r\nWarrior98\tStream,Warrior\tsfx\\warrior\\wario98.wav\r\nWarrior99\tStream,Warrior\tsfx\\warrior\\warior99.wav\r\nWarrior100\tStream,Warrior\tsfx\\warrior\\wario100.wav\r\nWarrior101\tStream,Warrior\tsfx\\warrior\\wario101.wav\r\nWarrior102\tStream,Warrior\tsfx\\warrior\\wario102.wav\r\nNarrator1\tStream\tsfx\\narrator\\nar01.wav\r\nNarrator2\tStream\tsfx\\narrator\\nar02.wav\r\nNarrator3\tStream\tsfx\\narrator\\nar03.wav\r\nNarrator4\tStream\tsfx\\narrator\\nar04.wav\r\nNarrator5\tStream\tsfx\\narrator\\nar05.wav\r\nNarrator6\tStream\tsfx\\narrator\\nar06.wav\r\nNarrator7\tStream\tsfx\\narrator\\nar07.wav\r\nNarrator8\tStream\tsfx\\narrator\\nar08.wav\r\nNarrator9\tStream\tsfx\\narrator\\nar09.wav\r\nDiabloGreeting\tStream\tsfx\\misc\\lvl16int.wav\r\nButcherGreeting\tStream\tsfx\\monsters\\butcher.wav\r\nGharbad1\tStream\tsfx\\monsters\\garbud01.wav\r\nGharbad2\tStream\tsfx\\monsters\\garbud02.wav\r\nGharbad3\tStream\tsfx\\monsters\\garbud03.wav\r\nGharbad4\tStream\tsfx\\monsters\\garbud04.wav\r\nLachdanan1\tStream\tsfx\\monsters\\lach01.wav\r\nLachdanan2\tStream\tsfx\\monsters\\lach02.wav\r\nLachdanan3\tStream\tsfx\\monsters\\lach03.wav\r\nLazarusGreeting\tStream\tsfx\\monsters\\laz01.wav\r\nLeoricGreeting\tStream\tsfx\\monsters\\sking01.wav\r\nSnotspill1\tStream\tsfx\\monsters\\snot01.wav\r\nSnotspill2\tStream\tsfx\\monsters\\snot02.wav\r\nSnotspill3\tStream\tsfx\\monsters\\snot03.wav\r\nWarlord\tStream\tsfx\\monsters\\warlrd01.wav\r\nZhar1\tStream\tsfx\\monsters\\zhar01.wav\r\nZhar2\tStream\tsfx\\monsters\\zhar02.wav\r\nDiabloDeath\tStream\tsfx\\monsters\\diablod.wav\r\nAccessibilityWeapon\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityArmor\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityGold\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityPotion\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityScroll\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityChest\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityDoor\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityStairs\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityMonster\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityInteract\tMisc\tsfx\\items\\titlemov.wav"
  },
  {
    "path": "assets/txtdata/spells/spelldat.tsv",
    "content": "id\tname\tsoundId\tbookCost10\tstaffCost10\tmanaCost\tflags\tbookLevel\tstaffLevel\tminIntelligence\tmissiles\tmanaMultiplier\tminMana\tstaffMin\tstaffMax\r\nFirebolt\tFirebolt\tCastFire\t100\t5\t6\tFire,Targeted\t1\t1\t15\tFirebolt\t1\t3\t40\t80\r\nHealing\tHealing\tCastHealing\t100\t5\t5\tMagic,AllowedInTown\t1\t1\t17\tHealing\t3\t1\t20\t40\r\nLightning\tLightning\tCastLightning\t300\t15\t10\tLightning,Targeted\t4\t3\t20\tLightningControl\t1\t6\t20\t60\r\nFlash\tFlash\tCastLightning\t750\t50\t30\tLightning\t5\t4\t33\tFlashBottom,FlashTop\t2\t16\t20\t40\r\nIdentify\tIdentify\tCastSkill\t0\t10\t13\tMagic,AllowedInTown\t-1\t-1\t23\tIdentify\t2\t1\t8\t12\r\nFireWall\tFire Wall\tCastFire\t600\t40\t28\tFire,Targeted\t3\t2\t27\tFireWallControl\t2\t16\t8\t16\r\nTownPortal\tTown Portal\tCastSkill\t300\t20\t35\tMagic,Targeted\t3\t3\t20\tTownPortal\t3\t18\t8\t12\r\nStoneCurse\tStone Curse\tCastFire\t1200\t80\t60\tMagic,Targeted\t6\t5\t51\tStoneCurse\t3\t40\t8\t16\r\nInfravision\tInfravision\tCastHealing\t0\t60\t40\tMagic\t-1\t-1\t36\tInfravision\t5\t20\t0\t0\r\nPhasing\tPhasing\tCastFire\t350\t20\t12\tMagic\t7\t6\t39\tPhasing\t2\t4\t40\t80\r\nManaShield\tMana Shield\tCastFire\t1600\t120\t33\tMagic\t6\t5\t25\tManaShield\t0\t33\t4\t10\r\nFireball\tFireball\tCastFire\t800\t30\t16\tFire,Targeted\t8\t7\t48\tFireball\t1\t10\t40\t80\r\nGuardian\tGuardian\tCastFire\t1400\t95\t50\tFire,Targeted\t9\t8\t61\tGuardian\t2\t30\t16\t32\r\nChainLightning\tChain Lightning\tCastFire\t1100\t75\t30\tLightning\t8\t7\t54\tChainLightning\t1\t18\t20\t60\r\nFlameWave\tFlame Wave\tCastFire\t1000\t65\t35\tFire,Targeted\t9\t8\t54\tFlameWaveControl\t3\t20\t20\t40\r\nDoomSerpents\tDoom Serpents\tCastFire\t0\t0\t0\tLightning\t-1\t-1\t0\t\t0\t0\t40\t80\r\nBloodRitual\tBlood Ritual\tCastFire\t0\t0\t0\tMagic\t-1\t-1\t0\t\t0\t0\t40\t80\r\nNova\tNova\tCastLightning\t2100\t130\t60\tMagic\t-1\t10\t87\tNova\t3\t35\t16\t32\r\nInvisibility\tInvisibility\tCastFire\t0\t0\t0\tMagic\t-1\t-1\t0\t\t0\t0\t40\t80\r\nInferno\tInferno\tCastFire\t200\t10\t11\tFire,Targeted\t3\t2\t20\tInfernoControl\t1\t6\t20\t40\r\nGolem\tGolem\tCastFire\t1800\t110\t100\tFire,Targeted\t11\t9\t81\tGolem\t6\t60\t16\t32\r\nRage\tRage\tCastHealing\t0\t0\t15\tMagic\t-1\t-1\t0\tRage\t1\t1\t0\t0\r\nTeleport\tTeleport\tCastSkill\t2000\t125\t35\tMagic,Targeted\t14\t12\t105\tTeleport\t3\t15\t16\t32\r\nApocalypse\tApocalypse\tCastFire\t3000\t200\t150\tFire\t-1\t15\t149\tApocalypse\t6\t90\t8\t12\r\nEtherealize\tEtherealize\tCastFire\t2600\t160\t100\tMagic\t-1\t-1\t93\tEtherealize\t0\t100\t2\t6\r\nItemRepair\tItem Repair\tCastSkill\t0\t0\t0\tMagic,AllowedInTown\t-1\t-1\t255\tItemRepair\t0\t0\t40\t80\r\nStaffRecharge\tStaff Recharge\tCastSkill\t0\t0\t0\tMagic,AllowedInTown\t-1\t-1\t255\tStaffRecharge\t0\t0\t40\t80\r\nTrapDisarm\tTrap Disarm\tCastSkill\t0\t0\t0\tMagic\t-1\t-1\t255\tTrapDisarm\t0\t0\t40\t80\r\nElemental\tElemental\tCastFire\t1050\t70\t35\tFire\t8\t6\t68\tElemental\t2\t20\t20\t60\r\nChargedBolt\tCharged Bolt\tCastFire\t100\t5\t6\tLightning,Targeted\t1\t1\t25\tChargedBolt\t1\t6\t40\t80\r\nHolyBolt\tHoly Bolt\tCastFire\t100\t5\t7\tMagic,Targeted\t1\t1\t20\tHolyBolt\t1\t3\t40\t80\r\nResurrect\tResurrect\tCastHealing\t400\t25\t20\tMagic,AllowedInTown\t-1\t5\t30\tResurrect\t0\t20\t4\t10\r\nTelekinesis\tTelekinesis\tCastFire\t250\t20\t15\tMagic\t2\t2\t33\tTelekinesis\t2\t8\t20\t40\r\nHealOther\tHeal Other\tCastHealing\t100\t5\t5\tMagic,AllowedInTown\t1\t1\t17\tHealOther\t3\t1\t20\t40\r\nBloodStar\tBlood Star\tCastFire\t2750\t180\t25\tMagic\t14\t13\t70\tBloodStar\t2\t14\t20\t60\r\nBoneSpirit\tBone Spirit\tCastFire\t1150\t80\t24\tMagic\t9\t7\t34\tBoneSpirit\t1\t12\t20\t60\r\n"
  },
  {
    "path": "assets/txtdata/text/textdat-unused.tsv",
    "content": "txtstrid\ttxtstr\tscrlltxt\tsfxnr\r\nTEXT_DEADGUY\tPlease help....! I barely escaped from....... The Butcher...! He killed.... My wife... My children! I beg of you...... In the name of God......... Avenge them.........\ttrue\tWoundedTownsmanOld\r\nTEXT_FARNHAM14\t*retching* Listen, listen. I don't even like worms. Don't tell me about yer worms! I don't want yer worms! Nope, no thanks! *slight hiccup/gag* No worms for me.\ttrue\tFarnham5\r\nTEXT_FARNHAM15\t*SNORE*\ttrue\tFarnham6\r\nTEXT_FARNHAM16\tSounds like a good idea to me. Ya better get started right awaaay.\ttrue\tFarnham8\r\nTEXT_FARNHAM17\t*laugh* Did you ever hear I love that King tale? I love that one.\ttrue\tFarnham9\r\nTEXT_FARNHAM18\t(Crying) No, you can't make me go back there. I won't let you take me. Too much pain, too many dead. Can't... get the blood out of my eyes... my mouth... *wails*\ttrue\tFarnham11\r\nTEXT_FARNHAM19\tYou're gonna hunt down a demon? Is that what you said? I know I didn't hear that 'cuz nobody hunts down a demon, no! Nobody!\ttrue\tFarnham16\r\nTEXT_FARNHAM20\tHey, lemme see that. *blows nose* Thanks!\ttrue\tFarnham18\r\nTEXT_FARNHAM21\tHey you there, come here, listen up. You know about the island where angels watch? Pick the right rocks, but you better shield your eyes; shield everything! I know, 'cause I been there and... Mmmm, ale.\ttrue\tFarnham22\r\nTEXT_FARNHAM22\tI haven't ever see a priest around here. If I did I'd kick him right in the *BBBBUUURRRPPP* Can't even keep a church free of those Hell spawn - bastards. What good are they, those holy men? Liars! Liars!\ttrue\tFarnham33\r\nTEXT_GILLIAN11\tWait, before you say anything, my grandmother had a dream with giant, slithering creatures in it. She also saw Pepin running from a house in the town. Do you think this means anything?\ttrue\tGillian5\r\nTEXT_GILLIAN12\tThis is something that is far beyond anything I have ever learned. I can only think of one person in all of Tristram who could help you... Cain, of course.\ttrue\tGillian7\r\nTEXT_GILLIAN13\tHow could you even think of going back to that place? What could be so important?\ttrue\tGillian9\r\nTEXT_GILLIAN14\tThose are the words of a drunkard. I don't see how they could be true.\ttrue\tGillian14\r\nTEXT_GILLIAN15\tI heard that the priest Tremain was going to perform an exorcism, but I didn't go. I don't see why we all have to spend every moment captive to what is lurking underneath our town. I know that many have died at the hands of these monsters, but we need to try to go on. I know that you have come here to free Tristram from the clutches of darkness, and I hope that one day we can live in peace again.\ttrue\tGillian15\r\nTEXT_GILLIAN16\tA treasure map? Do you have it with you? Let me see... Hmm, it looks like this is pretty old, and some of the buildings in the town are not on this map. Oh, I wish I could go and look for the treasure with you, but I have to start work soon.\ttrue\tGillian17\r\nTEXT_GILLIAN17\tBeg pardon, but have you heard what has been happening? Some of the men have vanished from the village. Dica's sons, Inaius and Roof, claim to have seen strange lights(= blood stars) glowing deep within the woods a few days ago, but no one has heard from them since. I, too, have seen a crimson shimmering from beyond the ash groves, but I've been too afraid to approach it. I fear that Ogden or our healer Pepin may be next. Won't you please find out what has happened?\ttrue\tGillian21\r\nTEXT_GILLIAN18\tHave you looked into what has caused the strange lights yet? There are more men missing since last we spoke, and I'm beginning to fear that soon we may all vanish.\ttrue\tGillian22\r\nTEXT_GILLIAN19\tDemons that assume the form of beautiful women, you say? That's horrible! Thank the Light that you solved this mystery before any more of our men were lured to their deaths. Thank you for keeping us safe from the powers of darkness once again.\ttrue\tGillian23\r\nTEXT_GILLIAN20\tPray your pardon, but I've something to tell you that you may find interesting. It was the strangest thing. While drinking at the tavern, Farnham was rambling about something called Azurewrath. He also said something about a fallen angel. It was hard to understand him because he was very drunk and disoriented, but I seem to remember something about a key in a barrel. He also kept covering his face and repeating the word 'Izual' over and over again.\ttrue\tGillian24\r\nTEXT_GILLIAN21\tYou know, now that I think about it... maybe it wasn't a key in a barrel, but a barrel that was the key. Does that make any more sense?\ttrue\tGillian25\r\nTEXT_GILLIAN22\tAzurewrath and Izual. I don't know why I didn't remember that story earlier. I've heard it often enough from my grandmother and Cain the Storyteller. Well, I hope that my information was still more of a help than a hindrance. May Light guide you, my friend.\ttrue\tGillian26\r\nTEXT_GILLIAN23\tI know that my grandmother’s story seems strange, but the graveyard does have many mysteries surrounding it. It couldn’t hurt you to put something there and see what happens, could it? Maybe you will find out something that will help us all.\ttrue\tGillian28\r\nTEXT_GILLIAN24\tMy grandmother had a dream about you last night, she said that in her dream you used your bare hands to defeat one of those foul monsters that lurk under the church. When it died, it exploded into fabulous treasure! Although she was a bit frightened by her dream, she was able to describe the beast quite clearly to me.\ttrue\tGillian29\r\nTEXT_GILLIAN25\tMy grandmother had that exact same dream again. She said you are quite brave and seemed very pleased with your prize.\ttrue\tGillian30\r\nTEXT_GILLIAN26\tI really don't know much about the priest Tremain. He never visits the tavern, preferring to keep to the company of Pepin and Cain. Perhaps it is because they, too, have more scholarly pursuits.\ttrue\tGillian38\r\nTEXT_PEPIN12\tRoof and Inaius are missing? Light protect us! Is there no place that is safe? Our only hope of returning to a peaceful life rests in you. Please, you must find those boys and bring them home to their family.\ttrue\tPepin4\r\nTEXT_PEPIN13\tHorazon was insane. There are forces with which one does not interfere. It would not surprise me if you found only the charred remains of this damned fool.\ttrue\tPepin6\r\nTEXT_PEPIN14\tFarnham is often confused, but he speaks a powerful name when the word Izual passes his lips. Cain would be able to tell you in much greater detail the legend of this warrior.\ttrue\tPepin7\r\nTEXT_PEPIN15\tI suppose it isn't beyond the realm of possibility if you could bear being in that room again. Your description of the atrocities committed there would be enough to keep me far from it.\ttrue\tPepin9\r\nTEXT_PEPIN16\tFor once I can vouch for Farnham's extraordinary claim. There are many mentions in the books that I have been reading about a place of great healing where warriors of light would go to mend the wounds sustained in the Sin War. If you could find this place it would most assuredly be to the benefit of us all.\ttrue\tPepin14\r\nTEXT_PEPIN17\tI was asked to assist in the exorcism. My skills were able to ease the poor man's suffering as Tremain drove the demon from his body. While I was treating him for an exceptionally high fever, he spoke of a place of searing heat. The tortured fellow cried out about Hell and falling into a pit of flame. I could not make any sense of it, and thankfully he soon recovered.\ttrue\tPepin15\r\nTEXT_PEPIN18\tGood hero, a moment of your time please. While attending one of the townsfolk who had taken quite ill, I noticed something odd about his home. There were strange sounds and a sickly sweet smell rising from the cellar. Thinking perhaps these fumes had something to do with his sickness. In his cellar were monstrous worms shifting and squirming up from the underground. I beg of you, slay these creatures before they can make their way into the town. I left the door to his house open for you. It is the one opposite of mine.\ttrue\tPepin23\r\nTEXT_PEPIN19\tI fear that the worms could soon overrun the village. I know that they are coming up from under the house that is opposite mine. Just the thought of those slimy beasts oozing into my house makes me want to be ill. Please, rid us of them.\ttrue\tPepin24\r\nTEXT_PEPIN20\tOnce again you have saved this humble town from the encroaching evil. We are, as always, forever in your debt.\ttrue\tPepin25\r\nTEXT_PEPIN21\tMy friend, I must speak with you. While going to help a sick villager I came upon a demon in the town. I fled from the house and accidentally left the door open in my haste. I pray that the vial creature is still in there. Please help us before it comes for us all.\ttrue\tPepin28\r\nTEXT_PEPIN22\tThese creatures must be banished from our town. To my shame I left the door open, but that should make all the easier for you to find the house.\ttrue\tPepin29\r\nTEXT_PEPIN23\tOnce again the town is in your debt. It is only your strength and force of will that can leads us out of this evil time.\ttrue\tPepin30\r\nTEXT_PEPIN24\tOnce again I require your strong arm and quick quirks to aid the people of this town. I am in need of certain reagents to help fight the plagues that the demons have unleashed on the land by their very presence. If you could gather these few items, it will save many lives!\ttrue\tPepin31\r\nTEXT_PEPIN25\tThe diseases spread quickly and many are dying. Please, help me by finding the reagents so that I can use it to make an antidote.\ttrue\tPepin32\r\nTEXT_PEPIN26\tThank you so much! You bring hope and light to this dark and troubled times. I wish for you to have this in the hopes that will aid you in your battle against the darkness.\ttrue\tPepin33\r\nTEXT_PEPIN27\tI know that I ask much of you, but I must now ask that you find a pool of clear water. Take these containers, fill them and return them me as soon as you can. With the clear water I can create an elixir of wondrous power that will benefit us all.\ttrue\tPepin34\r\nTEXT_PEPIN28\tHave you brought what I need? The clear water will allow me to create a very power elixir, fill the containers that I gave you and return with them.\ttrue\tPepin35\r\nTEXT_PEPIN29\tVery good, my friend! Very good! Just give a minute to mix these ingredients... Perfect! Here is some of the elixir as promised.\ttrue\tPepin36\r\nTEXT_PEPIN30\tHis Holiness is a wondrous man of great knowledge and understanding. He has shown me many cures for rare and deadly diseases. He brings me books and reagents for my work whenever he can. But I fear that he may some day take on a task that is too great even for him.\ttrue\tPepin44\r\nTEXT_GRISWOLD14\tI've seen no such things in my shop, but I will keep a close watch for them. Perhaps if they come this way, they won't take kindly to the fires of my forge.\ttrue\tGriswold5\r\nTEXT_GRISWOLD15\tI admit that I too have seen these strange lights, but I have not felt pulled towards them. I'll be sure to steer clear of them and will tell everyone that visits here to do likewise.\ttrue\tGriswold6\r\nTEXT_GRISWOLD16\tA bold tale indeed! My limited time beneath the cathedral leaves me poorly equipped to offer you any help with this. But, as always, you'll find Cain well versed in legends and folklore.\ttrue\tGriswold8\r\nTEXT_GRISWOLD17\tThe blade Azurewrath... It's legend! It was cast by the angelic weaponsmith Cinadide and tempered within the fires of judgment! Whoever wields this weapon will find the legions of Hell at his feet! If you found this blade, I would begin to truly believe that you could end the nightmare that has befallen our town.\ttrue\tGriswold9\r\nTEXT_GRISWOLD18\tWhen I found Wirt, he was very near a room that sounds like the vile pit you've described. The stench of death was heavy in the air and, consumed as I was with getting the lad to safety, I did not go further than I had to. If he claims to know something of that place, I would not discount his word easily.\ttrue\tGriswold11\r\nTEXT_GRISWOLD19\tFarnham speaks of a place that exists, at least in legend. Warriors would go to a place at the edge of Hell to gird themselves for battle against the armies of darkness. If the stories are true, untold treasures could lie upon this island of the sunless sea.\ttrue\tGriswold15\r\nTEXT_GRISWOLD20\tAh, you speak of an ancient and evil weapon. Tread lightly in this area, for the legends of Shadowfang are as black as a moonless winter night. Crafted within the Hellforge, Shadowfang can rend the very soul from whoever it strikes. I do not envy you if is in your mind to defeat the one who wields it. May light protect you, brave hero.\ttrue\tGriswold16\r\nTEXT_GRISWOLD21\tI'm in luck! A caravan has stopped just outside of the village and is taking supplies to the lands of the East. Certain items will bring a special price... if you can get them for me.\ttrue\tGriswold27\r\nTEXT_GRISWOLD22\tWe can both turn a nice profit if you can deliver the right goods to me. What do you say?\ttrue\tGriswold28\r\nTEXT_GRISWOLD23\tYou're just in time. The caravan is leaving tonight! Here's your cut, friend.\ttrue\tGriswold29\r\nTEXT_GRISWOLD24\tI believe that I may have found a way to greatly improve some weapons. If you can bring me what I need, I'd be willing to try out my idea and, if it works, it's yours!\ttrue\tGriswold30\r\nTEXT_GRISWOLD25\tI still think I can improve the right weapon!\ttrue\tGriswold31\r\nTEXT_GRISWOLD26\tLet me just do this... and this... and this. Ah, it works! Take this back and give it a try.\ttrue\tGriswold32\r\nTEXT_GRISWOLD27\tI'm working on a method for strengthening armor. Unfortunately, I don't have what I need just now. If you could possibly bring me what I require, the first one is yours!\ttrue\tGriswold33\r\nTEXT_GRISWOLD28\tI still think I can strengthen the right armor. You know what you need to bring me.\ttrue\tGriswold34\r\nTEXT_GRISWOLD29\tGood find! See if this works any better for you.\ttrue\tGriswold35\r\nTEXT_GRISWOLD30\tIf you come across any enchanted equipment, I could try to learn how it was crafted and then use those methods for my own creations. I should probably start with something easy.\ttrue\tGriswold36\r\nTEXT_GRISWOLD31\tI still think that I can strip the knowledge of enchantments... if you bring me a certain item.\ttrue\tGriswold37\r\nTEXT_GRISWOLD32\tThank you, oh great and mighty customer... err... uhh... champion! This will take some study... Done!\ttrue\tGriswold38\r\nTEXT_GRISWOLD33\tKeep your eyes open for a figurine made of iron. I have uncovered some old records concerning a specific type of figurine and the secrets of metalcrafting that it holds.\ttrue\tGriswold39\r\nTEXT_GRISWOLD34\tI know that the right figurine could be quite powerful. If you see what I'm looking for, get it and bring it to me straight away!\ttrue\tGriswold40\r\nTEXT_GRISWOLD35\tThe secrets of this metal are fantastic! Oh, how I could make the right item gleam with power.\ttrue\tGriswold41\r\nTEXT_GRISWOLD36\tIf you deliver to me the right item so I can combine it with this metal, I could craft something worthy of the warriors of Heaven!\ttrue\tGriswold42\r\nTEXT_GRISWOLD37\tYour efforts are not in vain. It seems that all is as I had hoped. I trust you will find this useful in your battles below?\ttrue\tGriswold43\r\n\tHaha, they have you hunting worms now? What's next? Leaf collecting? Picking up mushrooms? Look, friend, you have a whole church full of demons over there to worry about. I don't see how a few little worms could be so bad.\ttrue\tWirt5\r\n\tYou know, I've been looking for those lights, but I can't find them. If Gillian says they're there, I believe her, but I have yet to see them for myself.\ttrue\tWirt6\r\n\tThe care and feeding of demons is definitely not an interest of mine. Here is a piece of friendly advice - if you get the chance, kill anything you see down there.\ttrue\tWirt8\r\n\tIf you were to find any trace of Izual or the blade Azurewrath, even I would be impressed. That is definitely one of a kind.\ttrue\tWirt9\r\n\tThis is one time that you should listen to Farnham. I have heard of this place, and I know a few sorcerers who have tried to create a portal to get there.\ttrue\tWirt15\r\n\tI don't know who this Fleshdoom is, but I have heard rumors of an ebon blade that cleaves a soul from the body. Even I would not try to sell that thing, no matter what the profit. If you find it, you should do as Tremain says and destroy it as quickly as possible.\ttrue\tWirt16\r\n\tHere over... pssst... Chamber butcher the from spell portal town the cast! Saying am I what see?!\ttrue\tWirt21\r\n\tYet out it figured you haven't?! Understand could you even so simple it make to tried I! Chamber butcher the from spell portal town the cast!\ttrue\tWirt22\r\n\tHmm, where is that stupid map? It was supposed to be between the rock and the tree before the bridge. It should be right... Oh, hello there... didn't, uh, see you standing there...\ttrue\tWirt23\r\n\tRock? Tree? Bridge? I have no idea what you're talking about.\ttrue\tWirt24\r\n\tLook, I know my prices are high, but one of my contacts had an... accident, and I need some help refilling my more mundane inventory. I'll trade you a quality item if you can just complete this little list for me.\ttrue\tWirt25\r\n\tListen, I'll make it worth your time if you will get me what I asked you for. Besides, you know you want to find out what I'm going to give you in return.\ttrue\tWirt26\r\n\tThanks! This should hold me over until I can find a new errand boy. Too bad you're so busy. Oh yeah, here's your part of the bargain.\ttrue\tWirt27\r\n\tPssst... over here... I have something very special for sale today! I'm not exactly sure what it is, but I can just tell that it's great. I'm gonna offer you a bargain - a thousand gold takes it. Right now, no questions, and no returns!\ttrue\tWirt28\r\n\tHey, you! Yeah, I'm talking to you! I... acquired this strange book. I know it must do something big, but you need a crystal eyepiece to read it, so it's useless to me. However, I would be willing to trade you this rare and mystical tome, uh, for just a few things.\ttrue\tWirt29\r\n\tLook, this very special book that I have can be yours for so little. Don't tell anyone what a great deal I'm giving you or it would ruin my reputation.\ttrue\tWirt30\r\n\tAmazing, you actually found everything I wanted! Well, here's the book, but you're going to have to find a crystal eyepiece to read it. Good luck!\ttrue\tWirt31\r\n\tYeah, Tremain! He gets around, doesn't he? Or haven't you heard? My friends in some of the other towns say that he passes through, picking up a few books here, a pinch of bat claw there. Never seems to have the problems most do getting in and out of Tristram, that's for sure.\ttrue\tWirt41\r\n\tAll I can do now is pray for us all.\ttrue\tTremain0\r\n\tI seek a champion to undertake a serious duty, and the people of this town speak well of your courage and skill. The Archbishop Lazarus, once King Leoric's most trusted advisor and a member of our order, has taken the path of evil. Not long ago, Lazarus led a party of simple townsfolk into the labyrinth to find the king's missing son, Albrecht. Only a few of them escaped with their lives. Curse me for a fool! I should have suspected his veiled treachery then! For I have learned that it was Lazarus himself who kidnapped Leoric's son and has since hidden him within the labyrinth. I still don't understand why the Archbishop has turned to the darkness, or what his interest is in Albrecht. Unless... he means to sacrifice him at the full moon. That must be what he has planned! The survivors of his rescue party say that Lazarus was last seen in the deepest bowels of the labyrinth, some sixteen levels beneath the Cathedral. You must hurry, and save the prince from the sacrificial blade of this demented fiend!\ttrue\tTremain1\r\n\tWhy do you delay?! Time is of the essence! The prince and the people of this kingdom are counting on you!\ttrue\tTremain2\r\n\tSo, Lazarus has paid the price for his betrayal and justice is served! For your services this day, I bestow this mace unto you. Its name is Lightforge, and it is the holiest of our order's artifacts. As I am the last of this order, I entrust it to you. May the Light guide you.\ttrue\tTremain3\r\n\tThis is terrible! Lazarus will surely burn in Hell for his horrific deed! Although the boy that you describe may not be our prince, I believe that Albrecht may yet be in danger. Whatever vile power lies beneath the ground, has assuredly secured its foothold in our world. All I can do now is pray for us all.\ttrue\tTremain4\r\n\tI have had a most disturbing experience that I must share with you, my friend. Earlier today, I was called upon to help one of the men that escaped from the labyrinth. He was deranged, violent, and kept lashing out at all of those who tried to calm him. I suspected that he was possessed by some sort of demonic entity, and so began to drive the evil from within him. After many hours, I was able to exorcise a demon who called himself Fleshdoom, but the hellion fled into the labyrinth. You may think that I am mad, but after speaking with the man and battling with Fleshdoom, I believe that the labyrinth has somehow become a gateway to the underworld. As you descend deeper, you may find yourself upon the doorstep of Hell itself. Finally, the man who was possessed retained memories of an ancient demonblade named Shadowfang. If you find the demon Fleshdoom, beware this foul sword. While I fear the dangers below grow even greater, you must find Fleshdoom and slay him. Bring the sword to me and I can destroy it, but do not wield it. For its power can corrupt, absolutely.\ttrue\tTremain5\r\n\tFleshdoom's demise is a great good to the world, yet Shadowfang remains! It must be found and destroyed! Do not attempt to use the demonblade, champion. It will corrupt and madden any mortal who wields it. I alone can end its dark evil.\ttrue\tTremain6\r\n\tLight be praised! You found the cursed demonblade! Only its destruction can ensure the safety of us all! Wait... what treachery is this?! Ow, it burns! Hellfire, consuming me! You must take this, to the Hellforge and cast it in before-NOOOOOOO!\ttrue\tTremain7\r\n\tThe evil that you move against is the Dark Lord of Terror, known to mortal man as... Diablo. It was he who was imprisoned within the labyrinth many centuries ago. Find Diablo... or we may never have a chance to rid the world of his evil again!\ttrue\tCain0\r\n\tYes, you speak of Lazarus, one who was once well-respected in our land. Even before King Leoric descended into madness and lost his son, the Archishop Lazarus was acting... strangely. Lazarus seemed to be motivated by unseen forces, clinging to shadows, and acting out some dark plan that was not his own.\ttrue\tCain3\r\n\tWorms that rise up from the ground? Many of the ancient writings speak of poisonous insects, and foul creatures of the skies and seas, plaguing mankind. It is no surprise that the very earth would offer up a similar peril, now that the denizens of the underworld are upon us.\ttrue\tCain5\r\n\tWhile the barmaid may seem a bit confused at times, it is true that men have been disappearing from the village. It reminds me of ancient writings about a demonic temptress called Andariel. Known as the Maiden of Anguish, her thirst for mortal blood was so great, that she sought to learn a spell to breach the mortal realm. By seducing one of the dark sorcerers of the netherworld, Andariel took the knowledge she needed and so began to lure mortal men into her dark corner of Hell. If these legends are true, she's not a creature to be taken lightly.\ttrue\tCain6\r\n\tSo, you seek knowledge concerning the wars of Hell, do you? Cryptic tomes speak of great battles that determined which of the demonic lords are to rule over Hell. They also mention a bitter rivalry between two of these lords - Azmodan, who led the Horned Death against the armies of Light, and Belial, known as the Lord of Lies. Their hatred of each other is eternal - the reasons for their loathing, lost even to themselves. Tales abound, that the mad wizard Horazon somehow trapped the lieutenants of these two Lords of Hell within his sanctum. There can be no more dangerous a path to tread, than the one that falls alongside of demons. Should you also seek this path, watch your life, and your soul - very carefully - my friend.\ttrue\tCain8\r\n\tFarnham has taken to drinking quite heavily since his encounters in the labyrinth. But within the ramblings of this drunken man, rests a legend well steeped in myth and mystery. Sit for a moment, my friend, and let me tell you of Izual and Azurewrath. The saga of Izual takes place during the lost battles in Hell. Izual was an angel who was given charge of the holy ruin blade, Azurewrath. Leading a daring assault on the Hellforge, Izual was set upon by hundreds of blackened demons, and was fatally wounded! The fiends cast the dying angel into a dark pit, where the powers of chaos transformed him, as he drowned in a whirlpool of burning blood! Evil possessed Izual! The feathers of his wings burned away to reveal leathery skin, and horns ripped through the flesh of his head! When he finally arose from that black pit, Izual was an angel no more! Transformed into a creature of evil, he was once again given charge of Azurewrath, assuring that the blade would never again be used against the denizens of Hell!\ttrue\tCain9\r\n\tYou must've been speaking with Wirt! His is a sad story indeed. That poor child was taken into the labyrinth by the demons, ripped from the very arms of his mother, Canace. May her soul rest in peace. The boy managed to escape, but only after they had chewed off his leg, and he has not been quite sane since. He often speaks in riddles, but his knowledge of the labyrinth... may hold some truth.\ttrue\tCain11\r\n\tHmm, an island, where angels watched? Although Farnham's memory is often cloudy these days, that does seem familiar. Perhaps the ancient chronicles of the Sin War can help us... Ah, yes, here is something. In a time long-forgotten, a sea of blue rested on the edge of the fiery netherworld. This was an oasis for those who acted as the watchmen over the gates of Hell. Angels and warriors of Light could use this place to heal themselves, and gather their strength. It was also a staging area where they could train and prepare for the Sin War. Legends speak of a trinity of rocks that hide the path to this island of the sunless sea.\ttrue\tCain16\r\n\tThe priest Tremain is a holy man from an ancient order. Their dealings with the evil forces at work are well respected, and well documented. I, too, have heard legends that speak of the cursed demonblade called Shadowfang. It is said to consume the tortured souls of its victims. These souls are trapped within its ebon blade and augment its unholy power. I have also read of a great Hellforge, where even the mightiest weapon could be created... or destroyed. Tread carefully when dealing with Shadowfang and its master, lest you be drawn into the sword as well!\ttrue\tCain17\r\n\tThat sounds quite disgusting, and I'm afraid that I haven't heard anything about any worms. Perhaps Cain the Storyteller could be of some help.\ttrue\tOgden3\r\n\tGillian has been going on and on about strange lights in the trees, but I haven't been able to make heads nor tails of her story. I certainly haven't seen any strange lights, and if I did, they would be the least of my worries.\ttrue\tOgden4\r\n\tThese sound like dark creatures indeed. I am ignorant to matters of this nature, but I would assume that our storyteller may know of such legends.\ttrue\tOgden6\r\n\tThere is an old story of an angel named Izual, but I don't remember much more than that.\ttrue\tOgden7\r\n\tWirt is talking backwards again? I hate it when he does that! I don't have time to help you decipher his riddle, but I will tell you one thing - don't get involved with that rapscallion.\ttrue\tOgden9\r\n\tYou know, sometimes I wonder how much faith you can put into what Farnham says. He spends so much time reliving his memories of the labyrinth and just being plain drunk, that he doesn't always make much sense. I guess you could ask around, though.\ttrue\tOgden14\r\n\tI saw the exorcism! It was incredible how Tremain drove the evil spirit from that man's racked and tortured body! I pray that something that horrific never happens to anyone here ever again.\ttrue\tOgden15\r\n\tYour brave tales of fighting demons have reminded me of something, good master. A traveller passed through here some time ago. He was quite proud of a very unique weapon he held, and while becoming quite drunk, boasted of its power. I never saw him again, and I suspect that he ventured too close to the Cathedral.\ttrue\tOgden26\r\n\tHave you ever seen that traveller I told you about? The one with the enchanted weapon? Well, I suppose that he left our village as so many others have, or he must be dead.\ttrue\tOgden27\r\n\tYes, that is certainly the weapon that he wore. You know, I've been thinking about something else that traveller said. He inferred that the true powers of the weapon would be unleashed only when it tasted the blood of a very specific kind of creature.\ttrue\tOgden28\r\n\tWere the stories the traveller told us true? Oh, I see you don't know yet. Well, I clearly recall that he said by slaying a certain monster, the weapon you found would become something quite special.\ttrue\tOgden29\r\n\tWhile I understand that your purpose may be of a higher calling, surely some well-earned gold would be welcomed. Some townspeople from a nearby village have offered a reward for the destruction of a creature that razed their homes and property. They demand positive proof that the creature has been slain, and I can only think of one way to do that.\ttrue\tOgden30\r\n\tYou can say whatever you want, but without proof I cannot give you the reward.\ttrue\tOgden31\r\n\tOh, disgusting! But certainly proof enough for anyone. Here's your reward as promised.\ttrue\tOgden32\r\n\tGood master, a moment of your time, please? My tavern was broken into during the night. No one was hurt but many items were stolen, including a chest belonging to a mysterious wanderer who once stayed here. I found the body of a thief near the Cathedral with telltale wounds from one of the creatures below mocking his broken body. Some of the stolen goods were near the body, but the chest, and the key to open it, were nowhere in sight. If you should find those keys while on your brave crusade, you should recover them. Then, if you find the chest, you can open it and see what secrets it contains. Perhaps it will be something that can help you on your quests.\ttrue\tOgden33\r\n\tRemember, good master, the chest is locked and is useless without the key. If you do find the chest and get the key, you should see what's inside. I don't expect the owner back here again.\ttrue\tOgden34\r\n\tI see that you have found the key - now you just need to find the chest that it belongs to.\ttrue\tOgden35\r\n\tSeek out the domicile to which Pepin the Healer has directed you. It is there that your missions will become clear, and your methods evident.\ttrue\tAdria5\r\n\tThe succubus is a demon that feasts upon the essence of mortal men. You will find that Andariel has quite an appetite. The town will soon be devoid of any adult males, unless you stop her feeding now.\ttrue\tAdria6\r\n\tYou must destroy the two demons that Horazon has trapped within his sanctum at all costs! Should they escape from their imprisonment, they will create a link to this world that will make what lies below the Cathedral seem like a children's tale.\ttrue\tAdria8\r\n\tThe lair of the Butcher is steeped in demonic power, and casting any spell or passage there could cause unexpected results.\ttrue\tAdria11\r\n\tThis legendary place is real and great rewards await you should you find it. Nothing more can I say.\ttrue\tAdria16\r\n\tYou must be ever watchful, for Fleshdoom is an enemy who is both cruel and quick. His ebon blade is composed of the essence of evil. If you can destroy both of them, it would do much to weaken his dark master.\ttrue\tAdria17\r\n\tHello, good friend, I have been working on a means to increase the strength of my potions. I believe that I could brew better potions if you could just find me the correct reagents.\ttrue\tAdria27\r\n\tRemember, with the correct reagents, my potions are more powerful.\ttrue\tAdria28\r\n\tExcellent! Just a pinch should do it... Ahh, here is a sample.\ttrue\tAdria29\r\n\tIt seems that there are many uses for the scrolls which are found beneath the church. I should be able to scribe a book of magic if I had enough of the proper scrolls to study.\ttrue\tAdria30\r\n\tRemember, with enough scrolls, I can create a book of magic for you.\ttrue\tAdria31\r\n\tYes, I can see that when I combine these scrolls just so... I will teach what I have learned so that you may also know more secrets of this magic.\ttrue\tAdria32\r\n\tI have a quest for you if you are brave enough to accept it. Great power can be found in some of the devices that may be hidden below the church. With the right ones, I could work wonders!\ttrue\tAdria33\r\n\tRemember, the right device in my hands can become quite powerful.\ttrue\tAdria34\r\n\tThis is amazing! The mystic energies in this crystal are powerful, but unfocused. If you could find for me a specific staff to channel its power through...\ttrue\tAdria35\r\n\tThe crystal holds a magic that is strong, but you need to find the correct staff with which to focus its energy!\ttrue\tAdria36\r\n\tHand me that staff and stand back! Vita te chlorum an duriam! Ahhhh, it is complete.\ttrue\tAdria37\r\n\tFaith is absolute belief in the unseen. The priest Tremain is from a holy order long asleep in this land. He keeps a promise and a charge issued ages ago and sustains a union with realms that even my vision cannot reach. He knows much, but not as much as he believes.\ttrue\tAdria48\r\n"
  },
  {
    "path": "assets/txtdata/text/textdat.tsv",
    "content": "txtstrid\ttxtstr\tscrlltxt\tsfxnr\r\nTEXT_KING1\t Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh blow to this land. The people always loved the King, and now they live in mortal fear of him. The question that I keep asking myself is how he could have fallen so far from the Light, as Leoric had always been the holiest of men. Only the vilest powers of Hell could so utterly destroy a man from within...\ttrue\tCain1\r\nTEXT_KING2\tThe village needs your help, good master! Some months ago King Leoric's son, Prince Albrecht, was kidnapped. The King went into a rage and scoured the village for his missing child. With each passing day, Leoric seemed to slip deeper into madness. He sought to blame innocent townsfolk for the boy's disappearance and had them brutally executed. Less than half of us survived his insanity...\\n \\nThe King's Knights and Priests tried to placate him, but he turned against them and sadly, they were forced to kill him. With his dying breath the King called down a terrible curse upon his former followers. He vowed that they would serve him in darkness forever...\\n \\nThis is where things take an even darker twist than I thought possible! Our former King has risen from his eternal sleep and now commands a legion of undead minions within the Labyrinth. His body was buried in a tomb three levels beneath the Cathedral. Please, good master, put his soul at ease by destroying his now cursed form...\ttrue\tOgden21\r\nTEXT_KING3\tAs I told you, good master, the King was entombed three levels below. He's down there, waiting in the putrid darkness for his chance to destroy this land...\ttrue\tOgden22\r\nTEXT_KING4\tThe curse of our King has passed, but I fear that it was only part of a greater evil at work. However, we may yet be saved from the darkness that consumes our land, for your victory is a good omen. May Light guide you on your way, good master.\ttrue\tOgden23\r\nTEXT_KING5\tThe loss of his son was too much for King Leoric. I did what I could to ease his madness, but in the end it overcame him. A black curse has hung over this kingdom from that day forward, but perhaps if you were to free his spirit from his earthly prison, the curse would be lifted...\ttrue\tPepin1\r\nTEXT_KING6\tI don't like to think about how the King died. I like to remember him for the kind and just ruler that he was. His death was so sad and seemed very wrong, somehow.\ttrue\tGillian1\r\nTEXT_KING7\tI made many of the weapons and most of the armor that King Leoric used to outfit his knights. I even crafted a huge two-handed sword of the finest mithril for him, as well as a field crown to match. I still cannot believe how he died, but it must have been some sinister force that drove him insane!\ttrue\tGriswold1\r\nTEXT_KING8\tI don't care about that. Listen, no skeleton is gonna be MY king. Leoric is King. King, so you hear me? HAIL TO THE KING!\ttrue\tFarnham1\r\nTEXT_KING9\tThe dead who walk among the living follow the cursed King. He holds the power to raise yet more warriors for an ever growing army of the undead. If you do not stop his reign, he will surely march across this land and slay all who still live here.\ttrue\tAdria1\r\nTEXT_KING10\tLook, I'm running a business here. I don't sell information, and I don't care about some King that's been dead longer than I've been alive. If you need something to use against this King of the undead, then I can help you out...\ttrue\tWirt1\r\nTEXT_KING11\tThe warmth of life has entered my tomb. Prepare yourself, mortal, to serve my Master for eternity!\tfalse\tLeoricGreeting\r\nTEXT_BANNER1\tI see that this strange behavior puzzles you as well. I would surmise that since many demons fear the light of the sun and believe that it holds great power, it may be that the rising sun depicted on the sign you speak of has led them to believe that it too holds some arcane powers. Hmm, perhaps they are not all as smart as we had feared...\ttrue\tCain2\r\nTEXT_BANNER2\tMaster, I have a strange experience to relate. I know that you have a great knowledge of those monstrosities that inhabit the labyrinth, and this is something that I cannot understand for the very life of me... I was awakened during the night by a scraping sound just outside of my tavern. When I looked out from my bedroom, I saw the shapes of small demon-like creatures in the inn yard. After a short time, they ran off, but not before stealing the sign to my inn. I don't know why the demons would steal my sign but leave my family in peace... 'tis strange, no?\ttrue\tOgden24\r\nTEXT_BANNER3\tOh, you didn't have to bring back my sign, but I suppose that it does save me the expense of having another one made. Well, let me see, what could I give you as a fee for finding it? Hmmm, what have we here... ah, yes! This cap was left in one of the rooms by a magician who stayed here some time ago. Perhaps it may be of some value to you.\ttrue\tOgden25\r\nTEXT_BANNER4\tMy goodness, demons running about the village at night, pillaging our homes - is nothing sacred? I hope that Ogden and Garda are all right. I suppose that they would come to see me if they were hurt...\ttrue\tPepin2\r\nTEXT_BANNER5\tOh my! Is that where the sign went? My Grandmother and I must have slept right through the whole thing. Thank the Light that those monsters didn't attack the inn.\ttrue\tGillian2\r\nTEXT_BANNER6\tDemons stole Ogden's sign, you say? That doesn't sound much like the atrocities I've heard of - or seen. \\n \\nDemons are concerned with ripping out your heart, not your signpost.\ttrue\tGriswold2\r\nTEXT_BANNER7\tYou know what I think? Somebody took that sign, and they gonna want lots of money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece of cheese...\ttrue\tFarnham2\r\nTEXT_BANNER8\tNo mortal can truly understand the mind of the demon. \\n \\nNever let their erratic actions confuse you, as that too may be their plan.\ttrue\tAdria2\r\nTEXT_BANNER9\tWhat - is he saying I took that? I suppose that Griswold is on his side, too. \\n \\nLook, I got over simple sign stealing months ago. You can't turn a profit on a piece of wood.\ttrue\tWirt2\r\nTEXT_BANNER10\tHey - You that one that kill all! You get me Magic Banner or we attack! You no leave with life! You kill big uglies and give back Magic. Go past corner and door, find uglies. You give, you go!\ttrue\tSnotspill1\r\nTEXT_BANNER11\tYou kill uglies, get banner. You bring to me, or else...\ttrue\tSnotspill2\r\nTEXT_BANNER12\tYou give! Yes, good! Go now, we strong. We kill all with big Magic!\ttrue\tSnotspill3\r\nTEXT_VILE1\tThis does not bode well, for it confirms my darkest fears. While I did not allow myself to believe the ancient legends, I cannot deny them now. Perhaps the time has come to reveal who I am.\\n \\nMy true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released.\\n \\nThe Archbishop Lazarus, once King Leoric's most trusted advisor, led a party of simple townsfolk into the Labyrinth to find the King's missing son, Albrecht. Quite some time passed before they returned, and only a few of them escaped with their lives.\\n \\nCurse me for a fool! I should have suspected his veiled treachery then. It must have been Lazarus himself who kidnapped Albrecht and has since hidden him within the Labyrinth. I do not understand why the Archbishop turned to the darkness, or what his interest is in the child, unless he means to sacrifice him to his dark masters!\\n \\nThat must be what he has planned! The survivors of his 'rescue party' say that Lazarus was last seen running into the deepest bowels of the labyrinth. You must hurry and save the prince from the sacrificial blade of this demented fiend!\ttrue\tCain36\r\nTEXT_VILE2\tYou must hurry and rescue Albrecht from the hands of Lazarus. The prince and the people of this kingdom are counting on you!\ttrue\tCain37\r\nTEXT_VILE3\tYour story is quite grim, my friend. Lazarus will surely burn in Hell for his horrific deed. The boy that you describe is not our prince, but I believe that Albrecht may yet be in danger. The symbol of power that you speak of must be a portal in the very heart of the labyrinth.\\n \\nKnow this, my friend - The evil that you move against is the dark Lord of Terror. He is known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago and I fear that he seeks to once again sow chaos in the realm of mankind. You must venture through the portal and destroy Diablo before it is too late!\ttrue\tCain38\r\nTEXT_VILE4\tLazarus was the Archbishop who led many of the townspeople into the labyrinth. I lost many good friends that day, and Lazarus never returned. I suppose he was killed along with most of the others. If you would do me a favor, good master - please do not talk to Farnham about that day.\ttrue\tOgden1\r\nTEXT_VILE5\t\ttrue\tCain38\r\nTEXT_VILE6\t\ttrue\tCain38\r\nTEXT_VILE7\tI was shocked when I heard of what the townspeople were planning to do that night. I thought that of all people, Lazarus would have had more sense than that. He was an Archbishop, and always seemed to care so much for the townsfolk of Tristram. So many were injured, I could not save them all...\ttrue\tPepin3\r\nTEXT_VILE8\tI remember Lazarus as being a very kind and giving man. He spoke at my mother's funeral, and was supportive of my grandmother and myself in a very troubled time. I pray every night that somehow, he is still alive and safe.\ttrue\tGillian3\r\nTEXT_VILE9\tI was there when Lazarus led us into the labyrinth. He spoke of holy retribution, but when we started fighting those hellspawn, he did not so much as lift his mace against them. He just ran deeper into the dim, endless chambers that were filled with the servants of darkness!\ttrue\tGriswold3\r\nTEXT_VILE10\tThey stab, then bite, then they're all around you. Liar! LIAR! They're all dead! Dead! Do you hear me? They just keep falling and falling... their blood spilling out all over the floor... all his fault...\ttrue\tFarnham3\r\nTEXT_VILE11\tI did not know this Lazarus of whom you speak, but I do sense a great conflict within his being. He poses a great danger, and will stop at nothing to serve the powers of darkness which have claimed him as theirs.\ttrue\tAdria3\r\nTEXT_VILE12\tYes, the righteous Lazarus, who was sooo effective against those monsters down there. Didn't help save my leg, did it? Look, I'll give you a free piece of advice. Ask Farnham, he was there.\ttrue\tWirt3\r\nTEXT_VILE13\tAbandon your foolish quest. All that awaits you is the wrath of my Master! You are too late to save the child. Now you will join him in Hell!\tfalse\tLazarusGreeting\r\nTEXT_VILE14\t\tfalse\tLazarusGreeting\r\nTEXT_POISON1\tHmm, I don't know what I can really tell you about this that will be of any help. The water that fills our wells comes from an underground spring. I have heard of a tunnel that leads to a great lake - perhaps they are one and the same. Unfortunately, I do not know what would cause our water supply to be tainted.\ttrue\tCain4\r\nTEXT_POISON2\tI have always tried to keep a large supply of foodstuffs and drink in our storage cellar, but with the entire town having no source of fresh water, even our stores will soon run dry. \\n \\nPlease, do what you can or I don't know what we will do.\ttrue\tOgden2\r\nTEXT_POISON3\tI'm glad I caught up to you in time! Our wells have become brackish and stagnant and some of the townspeople have become ill drinking from them. Our reserves of fresh water are quickly running dry. I believe that there is a passage that leads to the springs that serve our town. Please find what has caused this calamity, or we all will surely perish.\ttrue\tPepin20\r\nTEXT_POISON4\tPlease, you must hurry. Every hour that passes brings us closer to having no water to drink. \\n \\nWe cannot survive for long without your help.\ttrue\tPepin21\r\nTEXT_POISON5\tWhat's that you say - the mere presence of the demons had caused the water to become tainted? Oh, truly a great evil lurks beneath our town, but your perseverance and courage gives us hope. Please take this ring - perhaps it will aid you in the destruction of such vile creatures.\ttrue\tPepin22\r\nTEXT_POISON6\tMy grandmother is very weak, and Garda says that we cannot drink the water from the wells. Please, can you do something to help us?\ttrue\tGillian4\r\nTEXT_POISON7\tPepin has told you the truth. We will need fresh water badly, and soon. I have tried to clear one of the smaller wells, but it reeks of stagnant filth. It must be getting clogged at the source.\ttrue\tGriswold4\r\nTEXT_POISON8\tYou drink water?\ttrue\tFarnham4\r\nTEXT_POISON9\tThe people of Tristram will die if you cannot restore fresh water to their wells. \\n \\nKnow this - demons are at the heart of this matter, but they remain ignorant of what they have spawned.\ttrue\tAdria4\r\nTEXT_POISON10\tFor once, I'm with you. My business runs dry - so to speak - if I have no market to sell to. You better find out what is going on, and soon!\ttrue\tWirt4\r\nTEXT_BONE1\tA book that speaks of a chamber of human bones? Well, a Chamber of Bone is mentioned in certain archaic writings that I studied in the libraries of the East. These tomes inferred that when the Lords of the underworld desired to protect great treasures, they would create domains where those who died in the attempt to steal that treasure would be forever bound to defend it. A twisted, but strangely fitting, end?\ttrue\tCain7\r\nTEXT_BONE2\tI am afraid that I don't know anything about that, good master. Cain has many books that may be of some help.\ttrue\tOgden5\r\nTEXT_BONE3\tThis sounds like a very dangerous place. If you venture there, please take great care.\ttrue\tPepin5\r\nTEXT_BONE4\tI am afraid that I haven't heard anything about that. Perhaps Cain the Storyteller could be of some help.\ttrue\tGillian6\r\nTEXT_BONE5\tI know nothing of this place, but you may try asking Cain. He talks about many things, and it would not surprise me if he had some answers to your question.\ttrue\tGriswold7\r\nTEXT_BONE6\tOkay, so listen. There's this chamber of wood, see. And his wife, you know - her - tells the tree... cause you gotta wait. Then I says, that might work against him, but if you think I'm gonna PAY for this... you... uh... yeah.\ttrue\tFarnham7\r\nTEXT_BONE7\tYou will become an eternal servant of the dark lords should you perish within this cursed domain. \\n \\nEnter the Chamber of Bone at your own peril.\ttrue\tAdria7\r\nTEXT_BONE8\tA vast and mysterious treasure, you say? Maybe I could be interested in picking up a few things from you... or better yet, don't you need some rare and expensive supplies to get you through this ordeal?\ttrue\tWirt7\r\nTEXT_BUTCH1\tIt seems that the Archbishop Lazarus goaded many of the townsmen into venturing into the Labyrinth to find the King's missing son. He played upon their fears and whipped them into a frenzied mob. None of them were prepared for what lay within the cold earth... Lazarus abandoned them down there - left in the clutches of unspeakable horrors - to die.\ttrue\tCain10\r\nTEXT_BUTCH2\tYes, Farnham has mumbled something about a hulking brute who wielded a fierce weapon. I believe he called him a butcher.\ttrue\tOgden8\r\nTEXT_BUTCH3\tBy the Light, I know of this vile demon. There were many that bore the scars of his wrath upon their bodies when the few survivors of the charge led by Lazarus crawled from the Cathedral. I don't know what he used to slice open his victims, but it could not have been of this world. It left wounds festering with disease and even I found them almost impossible to treat. Beware if you plan to battle this fiend...\ttrue\tPepin8\r\nTEXT_BUTCH4\tWhen Farnham said something about a butcher killing people, I immediately discounted it. But since you brought it up, maybe it is true.\ttrue\tGillian8\r\nTEXT_BUTCH5\tI saw what Farnham calls the Butcher as it swathed a path through the bodies of my friends. He swung a cleaver as large as an axe, hewing limbs and cutting down brave men where they stood. I was separated from the fray by a host of small screeching demons and somehow found the stairway leading out. I never saw that hideous beast again, but his blood-stained visage haunts me to this day.\ttrue\tGriswold10\r\nTEXT_BUTCH6\tBig! Big cleaver killing all my friends. Couldn't stop him, had to run away, couldn't save them. Trapped in a room with so many bodies... so many friends... NOOOOOOOOOO!\ttrue\tFarnham10\r\nTEXT_BUTCH7\tThe Butcher is a sadistic creature that delights in the torture and pain of others. You have seen his handiwork in the drunkard Farnham. His destruction will do much to ensure the safety of this village.\ttrue\tAdria10\r\nTEXT_BUTCH8\tI know more than you'd think about that grisly fiend. His little friends got a hold of me and managed to get my leg before Griswold pulled me out of that hole. \\n \\nI'll put it bluntly - kill him before he kills you and adds your corpse to his collection.\ttrue\tWirt10\r\nTEXT_BUTCH9\tPlease, listen to me. The Archbishop Lazarus, he led us down here to find the lost prince. The bastard led us into a trap! Now everyone is dead... killed by a demon he called the Butcher. Avenge us! Find this Butcher and slay him so that our souls may finally rest...\ttrue\tWoundedTownsman\r\nTEXT_BUTCH10\t\ttrue\tButcherGreeting\r\nTEXT_BLIND1\tYou recite an interesting rhyme written in a style that reminds me of other works. Let me think now - what was it?\\n \\n...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of razor claws briefly scraping to torment those poor souls who have been made sightless for all eternity. The prison for those so damned is named the Halls of the Blind...\ttrue\tCain12\r\nTEXT_BLIND2\tI never much cared for poetry. Occasionally, I had cause to hire minstrels when the inn was doing well, but that seems like such a long time ago now. \\n \\nWhat? Oh, yes... uh, well, I suppose you could see what someone else knows.\ttrue\tOgden10\r\nTEXT_BLIND3\tThis does seem familiar, somehow. I seem to recall reading something very much like that poem while researching the history of demonic afflictions. It spoke of a place of great evil that... wait - you're not going there are you?\ttrue\tPepin10\r\nTEXT_BLIND4\tIf you have questions about blindness, you should talk to Pepin. I know that he gave my grandmother a potion that helped clear her vision, so maybe he can help you, too.\ttrue\tGillian10\r\nTEXT_BLIND5\tI am afraid that I have neither heard nor seen a place that matches your vivid description, my friend. Perhaps Cain the Storyteller could be of some help.\ttrue\tGriswold12\r\nTEXT_BLIND6\tLook here... that's pretty funny, huh? Get it? Blind - look here?\ttrue\tFarnham12\r\nTEXT_BLIND7\tThis is a place of great anguish and terror, and so serves its master well. \\n \\nTread carefully or you may yourself be staying much longer than you had anticipated.\ttrue\tAdria12\r\nTEXT_BLIND8\tLets see, am I selling you something? No. Are you giving me money to tell you about this? No. Are you now leaving and going to talk to the storyteller who lives for this kind of thing? Yes.\ttrue\tWirt11\r\nTEXT_VEIL1\tYou claim to have spoken with Lachdanan? He was a great hero during his life. Lachdanan was an honorable and just man who served his King faithfully for years. But of course, you already know that.\\n \\nOf those who were caught within the grasp of the King's Curse, Lachdanan would be the least likely to submit to the darkness without a fight, so I suppose that your story could be true. If I were in your place, my friend, I would find a way to release him from his torture.\ttrue\tCain13\r\nTEXT_VEIL2\tYou speak of a brave warrior long dead! I'll have no such talk of speaking with departed souls in my inn yard, thank you very much.\ttrue\tOgden11\r\nTEXT_VEIL3\tA golden elixir, you say. I have never concocted a potion of that color before, so I can't tell you how it would effect you if you were to try to drink it. As your healer, I strongly advise that should you find such an elixir, do as Lachdanan asks and DO NOT try to use it.\ttrue\tPepin11\r\nTEXT_VEIL4\tI've never heard of a Lachdanan before. I'm sorry, but I don't think that I can be of much help to you.\ttrue\tGillian11\r\nTEXT_VEIL5\tIf it is actually Lachdanan that you have met, then I would advise that you aid him. I dealt with him on several occasions and found him to be honest and loyal in nature. The curse that fell upon the followers of King Leoric would fall especially hard upon him.\ttrue\tGriswold13\r\nTEXT_VEIL6\t Lachdanan is dead. Everybody knows that, and you can't fool me into thinking any other way. You can't talk to the dead. I know!\ttrue\tFarnham13\r\nTEXT_VEIL7\tYou may meet people who are trapped within the Labyrinth, such as Lachdanan. \\n \\nI sense in him honor and great guilt. Aid him, and you aid all of Tristram.\ttrue\tAdria13\r\nTEXT_VEIL8\tWait, let me guess. Cain was swallowed up in a gigantic fissure that opened beneath him. He was incinerated in a ball of hellfire, and can't answer your questions anymore. Oh, that isn't what happened? Then I guess you'll be buying something or you'll be on your way.\ttrue\tWirt12\r\nTEXT_VEIL9\tPlease, don't kill me, just hear me out. I was once Captain of King Leoric's Knights, upholding the laws of this land with justice and honor. Then his dark Curse fell upon us for the role we played in his tragic death. As my fellow Knights succumbed to their twisted fate, I fled from the King's burial chamber, searching for some way to free myself from the Curse. I failed...\\n \\nI have heard of a Golden Elixir that could lift the Curse and allow my soul to rest, but I have been unable to find it. My strength now wanes, and with it the last of my humanity as well. Please aid me and find the Elixir. I will repay your efforts - I swear upon my honor.\ttrue\tLachdanan1\r\nTEXT_VEIL10\tYou have not found the Golden Elixir. I fear that I am doomed for eternity. Please, keep trying...\ttrue\tLachdanan2\r\nTEXT_VEIL11\tYou have saved my soul from damnation, and for that I am in your debt. If there is ever a way that I can repay you from beyond the grave I will find it, but for now - take my helm. On the journey I am about to take I will have little use for it. May it protect you against the dark powers below. Go with the Light, my friend...\ttrue\tLachdanan3\r\nTEXT_ANVIL1\tGriswold speaks of The Anvil of Fury - a legendary artifact long searched for, but never found. Crafted from the metallic bones of the Razor Pit demons, the Anvil of Fury was smelt around the skulls of the five most powerful magi of the underworld. Carved with runes of power and chaos, any weapon or armor forged upon this Anvil will be immersed into the realm of Chaos, imbedding it with magical properties. It is said that the unpredictable nature of Chaos makes it difficult to know what the outcome of this smithing will be...\ttrue\tCain14\r\nTEXT_ANVIL2\tDon't you think that Griswold would be a better person to ask about this? He's quite handy, you know.\ttrue\tOgden12\r\nTEXT_ANVIL3\tIf you had been looking for information on the Pestle of Curing or the Silver Chalice of Purification, I could have assisted you, my friend. However, in this matter, you would be better served to speak to either Griswold or Cain.\ttrue\tPepin12\r\nTEXT_ANVIL4\tGriswold's father used to tell some of us when we were growing up about a giant anvil that was used to make mighty weapons. He said that when a hammer was struck upon this anvil, the ground would shake with a great fury. Whenever the earth moves, I always remember that story.\ttrue\tGillian12\r\nTEXT_ANVIL5\tGreetings! It's always a pleasure to see one of my best customers! I know that you have been venturing deeper into the Labyrinth, and there is a story I was told that you may find worth the time to listen to...\\n \\nOne of the men who returned from the Labyrinth told me about a mystic anvil that he came across during his escape. His description reminded me of legends I had heard in my youth about the burning Hellforge where powerful weapons of magic are crafted. The legend had it that deep within the Hellforge rested the Anvil of Fury! This Anvil contained within it the very essence of the demonic underworld...\\n \\nIt is said that any weapon crafted upon the burning Anvil is imbued with great power. If this anvil is indeed the Anvil of Fury, I may be able to make you a weapon capable of defeating even the darkest lord of Hell! \\n \\nFind the Anvil for me, and I'll get to work!\ttrue\tGriswold21\r\nTEXT_ANVIL6\tNothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could be your best hope, and I am sure that I can make you one of legendary proportions.\ttrue\tGriswold22\r\nTEXT_ANVIL7\tI can hardly believe it! This is the Anvil of Fury - good work, my friend. Now we'll show those bastards that there are no weapons in Hell more deadly than those made by men! Take this and may Light protect you.\ttrue\tGriswold23\r\nTEXT_ANVIL8\tGriswold can't sell his anvil. What will he do then? And I'd be angry too if someone took my anvil!\ttrue\tFarnham14\r\nTEXT_ANVIL9\tThere are many artifacts within the Labyrinth that hold powers beyond the comprehension of mortals. Some of these hold fantastic power that can be used by either the Light or the Darkness. Securing the Anvil from below could shift the course of the Sin War towards the Light.\ttrue\tAdria14\r\nTEXT_ANVIL10\tIf you were to find this artifact for Griswold, it could put a serious damper on my business here. Awwww, you'll never find it.\ttrue\tWirt13\r\nTEXT_BLOOD1\tThe Gateway of Blood and the Halls of Fire are landmarks of mystic origin. Wherever this book you read from resides it is surely a place of great power.\\n \\nLegends speak of a pedestal that is carved from obsidian stone and has a pool of boiling blood atop its bone encrusted surface. There are also allusions to Stones of Blood that will open a door that guards an ancient treasure...\\n \\nThe nature of this treasure is shrouded in speculation, my friend, but it is said that the ancient hero Arkaine placed the holy armor Valor in a secret vault. Arkaine was the first mortal to turn the tide of the Sin War and chase the legions of darkness back to the Burning Hells.\\n \\nJust before Arkaine died, his armor was hidden away in a secret vault. It is said that when this holy armor is again needed, a hero will arise to don Valor once more. Perhaps you are that hero...\ttrue\tCain15\r\nTEXT_BLOOD2\tEvery child hears the story of the warrior Arkaine and his mystic armor known as Valor. If you could find its resting place, you would be well protected against the evil in the Labyrinth.\ttrue\tOgden13\r\nTEXT_BLOOD3\tHmm... it sounds like something I should remember, but I've been so busy learning new cures and creating better elixirs that I must have forgotten. Sorry...\ttrue\tPepin13\r\nTEXT_BLOOD4\tThe story of the magic armor called Valor is something I often heard the boys talk about. You had better ask one of the men in the village.\ttrue\tGillian13\r\nTEXT_BLOOD5\tThe armor known as Valor could be what tips the scales in your favor. I will tell you that many have looked for it - including myself. Arkaine hid it well, my friend, and it will take more than a bit of luck to unlock the secrets that have kept it concealed oh, lo these many years.\ttrue\tGriswold14\r\nTEXT_BLOOD6\tZzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...\ttrue\tFarnham15\r\nTEXT_BLOOD7\tShould you find these Stones of Blood, use them carefully. \\n \\nThe way is fraught with danger and your only hope rests within your self trust.\ttrue\tAdria15\r\nTEXT_BLOOD8\tYou intend to find the armor known as Valor? \\n \\nNo one has ever figured out where Arkaine stashed the stuff, and if my contacts couldn't find it, I seriously doubt you ever will either.\ttrue\tWirt14\r\nTEXT_WARLRD1\tI know of only one legend that speaks of such a warrior as you describe. His story is found within the ancient chronicles of the Sin War...\\n \\nStained by a thousand years of war, blood and death, the Warlord of Blood stands upon a mountain of his tattered victims. His dark blade screams a black curse to the living; a tortured invitation to any who would stand before this Executioner of Hell.\\n \\nIt is also written that although he was once a mortal who fought beside the Legion of Darkness during the Sin War, he lost his humanity to his insatiable hunger for blood.\ttrue\tCain18\r\nTEXT_WARLRD2\tI am afraid that I haven't heard anything about such a vicious warrior, good master. I hope that you do not have to fight him, for he sounds extremely dangerous.\ttrue\tOgden16\r\nTEXT_WARLRD3\tCain would be able to tell you much more about something like this than I would ever wish to know.\ttrue\tPepin16\r\nTEXT_WARLRD4\tIf you are to battle such a fierce opponent, may Light be your guide and your defender. I will keep you in my thoughts.\ttrue\tGillian16\r\nTEXT_WARLRD5\tDark and wicked legends surrounds the one Warlord of Blood. Be well prepared, my friend, for he shows no mercy or quarter.\ttrue\tGriswold17\r\nTEXT_WARLRD6\tAlways you gotta talk about Blood? What about flowers, and sunshine, and that pretty girl that brings the drinks. Listen here, friend - you're obsessive, you know that?\ttrue\tFarnham17\r\nTEXT_WARLRD7\tHis prowess with the blade is awesome, and he has lived for thousands of years knowing only warfare. I am sorry... I can not see if you will defeat him.\ttrue\tAdria18\r\nTEXT_WARLRD8\tI haven't ever dealt with this Warlord you speak of, but he sounds like he's going through a lot of swords. Wouldn't mind supplying his armies...\ttrue\tWirt17\r\nTEXT_WARLRD9\tMy blade sings for your blood, mortal, and by my dark masters it shall not be denied.\tfalse\tWarlord\r\nTEXT_INFRA1\tGriswold speaks of the Heaven Stone that was destined for the enclave located in the east. It was being taken there for further study. This stone glowed with an energy that somehow granted vision beyond that which a normal man could possess. I do not know what secrets it holds, my friend, but finding this stone would certainly prove most valuable.\ttrue\tCain20\r\nTEXT_INFRA2\tThe caravan stopped here to take on some supplies for their journey to the east. I sold them quite an array of fresh fruits and some excellent sweetbreads that Garda has just finished baking. Shame what happened to them...\ttrue\tOgden18\r\nTEXT_INFRA3\tI don't know what it is that they thought they could see with that rock, but I will say this. If rocks are falling from the sky, you had better be careful!\ttrue\tPepin18\r\nTEXT_INFRA4\tWell, a caravan of some very important people did stop here, but that was quite a while ago. They had strange accents and were starting on a long journey, as I recall. \\n \\nI don't see how you could hope to find anything that they would have been carrying.\ttrue\tGillian18\r\nTEXT_INFRA5\tStay for a moment - I have a story you might find interesting. A caravan that was bound for the eastern kingdoms passed through here some time ago. It was supposedly carrying a piece of the heavens that had fallen to earth! The caravan was ambushed by cloaked riders just north of here along the roadway. I searched the wreckage for this sky rock, but it was nowhere to be found. If you should find it, I believe that I can fashion something useful from it.\ttrue\tGriswold24\r\nTEXT_INFRA6\tI am still waiting for you to bring me that stone from the heavens. I know that I can make something powerful out of it.\ttrue\tGriswold25\r\nTEXT_INFRA7\tLet me see that - aye... aye, it is as I believed. Give me a moment...\\n \\nAh, Here you are. I arranged pieces of the stone within a silver ring that my father left me. I hope it serves you well.\ttrue\tGriswold26\r\nTEXT_INFRA8\tI used to have a nice ring; it was a really expensive one, with blue and green and red and silver. Don't remember what happened to it, though. I really miss that ring...\ttrue\tFarnham19\r\nTEXT_INFRA9\tThe Heaven Stone is very powerful, and were it any but Griswold who bid you find it, I would prevent it. He will harness its powers and its use will be for the good of us all.\ttrue\tAdria20\r\nTEXT_INFRA10\tIf anyone can make something out of that rock, Griswold can. He knows what he is doing, and as much as I try to steal his customers, I respect the quality of his work.\ttrue\tWirt18\r\nTEXT_MUSH1\tThe witch Adria seeks a black mushroom? I know as much about Black Mushrooms as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, but this is something that cannot be found in any of my stories or books.\ttrue\tCain21\r\nTEXT_MUSH2\tLet me just say this. Both Garda and I would never, EVER serve black mushrooms to our honored guests. If Adria wants some mushrooms in her stew, then that is her business, but I can't help you find any. Black mushrooms... disgusting!\ttrue\tOgden19\r\nTEXT_MUSH3\tThe witch told me that you were searching for the brain of a demon to assist me in creating my elixir. It should be of great value to the many who are injured by those foul beasts, if I can just unlock the secrets I suspect that its alchemy holds. If you can remove the brain of a demon when you kill it, I would be grateful if you could bring it to me.\ttrue\tPepin26\r\nTEXT_MUSH4\tExcellent, this is just what I had in mind. I was able to finish the elixir without this, but it can't hurt to have this to study. Would you please carry this to the witch? I believe that she is expecting it.\ttrue\tPepin27\r\nTEXT_MUSH5\tI think Ogden might have some mushrooms in the storage cellar. Why don't you ask him?\ttrue\tGillian19\r\nTEXT_MUSH6\tIf Adria doesn't have one of these, you can bet that's a rare thing indeed. I can offer you no more help than that, but it sounds like... a huge, gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose.\ttrue\tGriswold19\r\nTEXT_MUSH7\tOgden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, listen... here's the secret - moderation is the key!\ttrue\tFarnham20\r\nTEXT_MUSH8\tWhat do we have here? Interesting, it looks like a book of reagents. Keep your eyes open for a black mushroom. It should be fairly large and easy to identify. If you find it, bring it to me, won't you?\ttrue\tAdria22\r\nTEXT_MUSH9\tIt's a big, black mushroom that I need. Now run off and get it for me so that I can use it for a special concoction that I am working on.\ttrue\tAdria23\r\nTEXT_MUSH10\tYes, this will be perfect for a brew that I am creating. By the way, the healer is looking for the brain of some demon or another so he can treat those who have been afflicted by their poisonous venom. I believe that he intends to make an elixir from it. If you help him find what he needs, please see if you can get a sample of the elixir for me.\ttrue\tAdria24\r\nTEXT_MUSH11\tWhy have you brought that here? I have no need for a demon's brain at this time. I do need some of the elixir that the Healer is working on. He needs that grotesque organ that you are holding, and then bring me the elixir. Simple when you think about it, isn't it?\ttrue\tAdria25\r\nTEXT_MUSH12\tWhat? Now you bring me that elixir from the healer? I was able to finish my brew without it. Why don't you just keep it...\ttrue\tAdria26\r\nTEXT_MUSH13\tI don't have any mushrooms of any size or color for sale. How about something a bit more useful?\ttrue\tWirt19\r\nTEXT_DOOM1\tSo, the legend of the Map is real. Even I never truly believed any of it! I suppose it is time that I told you the truth about who I am, my friend. You see, I am not all that I seem...\\n \\nMy true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to keeping and safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released...\\n \\nThe evil that you move against is the dark Lord of Terror - known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago. The Map that you hold now was created ages ago to mark the time when Diablo would rise again from his imprisonment. When the two stars on that map align, Diablo will be at the height of his power. He will be all but invincible...\\n \\nYou are now in a race against time, my friend! Find Diablo and destroy him before the stars align, for we may never have a chance to rid the world of his evil again!\ttrue\tCain22\r\nTEXT_DOOM2\tOur time is running short! I sense his dark power building and only you can stop him from attaining his full might.\ttrue\tCain23\r\nTEXT_DOOM3\tI am sure that you tried your best, but I fear that even your strength and will may not be enough. Diablo is now at the height of his earthly power, and you will need all your courage and strength to defeat him. May the Light protect and guide you, my friend. I will help in any way that I am able.\ttrue\tCain24\r\nTEXT_DOOM4\tIf the witch can't help you and suggests you see Cain, what makes you think that I would know anything? It sounds like this is a very serious matter. You should hurry along and see the storyteller as Adria suggests.\ttrue\tOgden20\r\nTEXT_DOOM5\tI can't make much of the writing on this map, but perhaps Adria or Cain could help you decipher what this refers to. \\n \\nI can see that it is a map of the stars in our sky, but any more than that is beyond my talents.\ttrue\tPepin19\r\nTEXT_DOOM6\tThe best person to ask about that sort of thing would be our storyteller. \\n \\nCain is very knowledgeable about ancient writings, and that is easily the oldest looking piece of paper that I have ever seen.\ttrue\tGillian20\r\nTEXT_DOOM7\tI have never seen a map of this sort before. Where'd you get it? Although I have no idea how to read this, Cain or Adria may be able to provide the answers that you seek.\ttrue\tGriswold20\r\nTEXT_DOOM8\tListen here, come close. I don't know if you know what I know, but you have really got somethin' here. That's a map.\ttrue\tFarnham21\r\nTEXT_DOOM9\tOh, I'm afraid this does not bode well at all. This map of the stars portends great disaster, but its secrets are not mine to tell. The time has come for you to have a very serious conversation with the Storyteller...\ttrue\tAdria21\r\nTEXT_DOOM10\tI've been looking for a map, but that certainly isn't it. You should show that to Adria - she can probably tell you what it is. I'll say one thing; it looks old, and old usually means valuable.\ttrue\tWirt20\r\nTEXT_GARBUD1\tPleeeease, no hurt. No Kill. Keep alive and next time good bring to you.\ttrue\tGharbad1\r\nTEXT_GARBUD2\tSomething for you I am making. Again, not kill Gharbad. Live and give good. \\n \\nYou take this as proof I keep word...\ttrue\tGharbad2\r\nTEXT_GARBUD3\tNothing yet! Almost done. \\n \\nVery powerful, very strong. Live! Live! \\n \\nNo pain and promise I keep!\ttrue\tGharbad3\r\nTEXT_GARBUD4\tThis too good for you. Very Powerful! You want - you take!\ttrue\tGharbad4\r\nTEXT_ZHAR1\tWhat?! Why are you here? All these interruptions are enough to make one insane. Here, take this and leave me to my work. Trouble me no more!\ttrue\tZhar1\r\nTEXT_ZHAR2\tArrrrgh! Your curiosity will be the death of you!!!\ttrue\tZhar2\r\nTEXT_STORY1\tHello, my friend. Stay awhile and listen...\tfalse\tCain25\r\nTEXT_STORY2\tWhile you are venturing deeper into the Labyrinth you may find tomes of great knowledge hidden there. \\n \\nRead them carefully for they can tell you things that even I cannot.\ttrue\tCain26\r\nTEXT_STORY3\tI know of many myths and legends that may contain answers to questions that may arise in your journeys into the Labyrinth. If you come across challenges and questions to which you seek knowledge, seek me out and I will tell you what I can.\ttrue\tCain27\r\nTEXT_STORY4\tGriswold - a man of great action and great courage. I bet he never told you about the time he went into the Labyrinth to save Wirt, did he? He knows his fair share of the dangers to be found there, but then again - so do you. He is a skilled craftsman, and if he claims to be able to help you in any way, you can count on his honesty and his skill.\ttrue\tCain28\r\nTEXT_STORY5\tOgden has owned and run the Rising Sun Inn and Tavern for almost four years now. He purchased it just a few short months before everything here went to hell. He and his wife Garda do not have the money to leave as they invested all they had in making a life for themselves here. He is a good man with a deep sense of responsibility.\ttrue\tCain29\r\nTEXT_STORY6\tPoor Farnham. He is a disquieting reminder of the doomed assembly that entered into the Cathedral with Lazarus on that dark day. He escaped with his life, but his courage and much of his sanity were left in some dark pit. He finds comfort only at the bottom of his tankard nowadays, but there are occasional bits of truth buried within his constant ramblings.\ttrue\tCain30\r\nTEXT_STORY7\tThe witch, Adria, is an anomaly here in Tristram. She arrived shortly after the Cathedral was desecrated while most everyone else was fleeing. She had a small hut constructed at the edge of town, seemingly overnight, and has access to many strange and arcane artifacts and tomes of knowledge that even I have never seen before.\ttrue\tCain31\r\nTEXT_STORY9\tThe story of Wirt is a frightening and tragic one. He was taken from the arms of his mother and dragged into the labyrinth by the small, foul demons that wield wicked spears. There were many other children taken that day, including the son of King Leoric. The Knights of the palace went below, but never returned. The Blacksmith found the boy, but only after the foul beasts had begun to torture him for their sadistic pleasures.\ttrue\tCain33\r\nTEXT_STORY10\tAh, Pepin. I count him as a true friend - perhaps the closest I have here. He is a bit addled at times, but never a more caring or considerate soul has existed. His knowledge and skills are equaled by few, and his door is always open.\ttrue\tCain34\r\nTEXT_STORY11\tGillian is a fine woman. Much adored for her high spirits and her quick laugh, she holds a special place in my heart. She stays on at the tavern to support her elderly grandmother who is too sick to travel. I sometimes fear for her safety, but I know that any man in the village would rather die than see her harmed.\ttrue\tCain35\r\nTEXT_OGDEN1\tGreetings, good master. Welcome to the Tavern of the Rising Sun!\tfalse\tOgden36\r\nTEXT_OGDEN2\tMany adventurers have graced the tables of my tavern, and ten times as many stories have been told over as much ale. The only thing that I ever heard any of them agree on was this old axiom. Perhaps it will help you. You can cut the flesh, but you must crush the bone.\ttrue\tOgden37\r\nTEXT_OGDEN3\tGriswold the blacksmith is extremely knowledgeable about weapons and armor. If you ever need work done on your gear, he is definitely the man to see.\ttrue\tOgden38\r\nTEXT_OGDEN4\tFarnham spends far too much time here, drowning his sorrows in cheap ale. I would make him leave, but he did suffer so during his time in the Labyrinth.\ttrue\tOgden39\r\nTEXT_OGDEN5\tAdria is wise beyond her years, but I must admit - she frightens me a little. \\n \\nWell, no matter. If you ever have need to trade in items of sorcery, she maintains a strangely well-stocked hut just across the river.\ttrue\tOgden40\r\nTEXT_OGDEN6\tIf you want to know more about the history of our village, the storyteller Cain knows quite a bit about the past.\ttrue\tOgden41\r\nTEXT_OGDEN8\tWirt is a rapscallion and a little scoundrel. He was always getting into trouble, and it's no surprise what happened to him. \\n \\nHe probably went fooling about someplace that he shouldn't have been. I feel sorry for the boy, but I don't abide the company that he keeps.\ttrue\tOgden43\r\nTEXT_OGDEN9\tPepin is a good man - and certainly the most generous in the village. He is always attending to the needs of others, but trouble of some sort or another does seem to follow him wherever he goes...\ttrue\tOgden44\r\nTEXT_OGDEN10\tGillian, my Barmaid? If it were not for her sense of duty to her grand-dam, she would have fled from here long ago. \\n \\nGoodness knows I begged her to leave, telling her that I would watch after the old woman, but she is too sweet and caring to have done so.\ttrue\tOgden45\r\nTEXT_PEPIN1\tWhat ails you, my friend?\tfalse\tPepin37\r\nTEXT_PEPIN2\tI have made a very interesting discovery. Unlike us, the creatures in the Labyrinth can heal themselves without the aid of potions or magic. If you hurt one of the monsters, make sure it is dead or it very well may regenerate itself.\ttrue\tPepin38\r\nTEXT_PEPIN3\tBefore it was taken over by, well, whatever lurks below, the Cathedral was a place of great learning. There are many books to be found there. If you find any, you should read them all, for some may hold secrets to the workings of the Labyrinth.\ttrue\tPepin39\r\nTEXT_PEPIN4\tGriswold knows as much about the art of war as I do about the art of healing. He is a shrewd merchant, but his work is second to none. Oh, I suppose that may be because he is the only blacksmith left here.\ttrue\tPepin40\r\nTEXT_PEPIN5\tCain is a true friend and a wise sage. He maintains a vast library and has an innate ability to discern the true nature of many things. If you ever have any questions, he is the person to go to.\ttrue\tPepin41\r\nTEXT_PEPIN6\tEven my skills have been unable to fully heal Farnham. Oh, I have been able to mend his body, but his mind and spirit are beyond anything I can do.\ttrue\tPepin42\r\nTEXT_PEPIN7\tWhile I use some limited forms of magic to create the potions and elixirs I store here, Adria is a true sorceress. She never seems to sleep, and she always has access to many mystic tomes and artifacts. I believe her hut may be much more than the hovel it appears to be, but I can never seem to get inside the place.\ttrue\tPepin43\r\nTEXT_PEPIN9\tPoor Wirt. I did all that was possible for the child, but I know he despises that wooden peg that I was forced to attach to his leg. His wounds were hideous. No one - and especially such a young child - should have to suffer the way he did.\ttrue\tPepin45\r\nTEXT_PEPIN10\tI really don't understand why Ogden stays here in Tristram. He suffers from a slight nervous condition, but he is an intelligent and industrious man who would do very well wherever he went. I suppose it may be the fear of the many murders that happen in the surrounding countryside, or perhaps the wishes of his wife that keep him and his family where they are.\ttrue\tPepin46\r\nTEXT_PEPIN11\tOgden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers from delusions. \\n \\nShe claims that they are visions, but I have no proof of that one way or the other.\ttrue\tPepin47\r\nTEXT_GILLIAN1\tGood day! How may I serve you?\tfalse\tGillian31\r\nTEXT_GILLIAN2\tMy grandmother had a dream that you would come and talk to me. She has visions, you know and can see into the future.\ttrue\tGillian32\r\nTEXT_GILLIAN3\tThe woman at the edge of town is a witch! She seems nice enough, and her name, Adria, is very pleasing to the ear, but I am very afraid of her. \\n \\nIt would take someone quite brave, like you, to see what she is doing out there.\ttrue\tGillian33\r\nTEXT_GILLIAN4\tOur Blacksmith is a point of pride to the people of Tristram. Not only is he a master craftsman who has won many contests within his guild, but he received praises from our King Leoric himself - may his soul rest in peace. Griswold is also a great hero; just ask Cain.\ttrue\tGillian34\r\nTEXT_GILLIAN5\tCain has been the storyteller of Tristram for as long as I can remember. He knows so much, and can tell you just about anything about almost everything.\ttrue\tGillian35\r\nTEXT_GILLIAN6\tFarnham is a drunkard who fills his belly with ale and everyone else's ears with nonsense. \\n \\nI know that both Pepin and Ogden feel sympathy for him, but I get so frustrated watching him slip farther and farther into a befuddled stupor every night.\ttrue\tGillian36\r\nTEXT_GILLIAN7\tPepin saved my grandmother's life, and I know that I can never repay him for that. His ability to heal any sickness is more powerful than the mightiest sword and more mysterious than any spell you can name. If you ever are in need of healing, Pepin can help you.\ttrue\tGillian37\r\nTEXT_GILLIAN9\tI grew up with Wirt's mother, Canace. Although she was only slightly hurt when those hideous creatures stole him, she never recovered. I think she died of a broken heart. Wirt has become a mean-spirited youngster, looking only to profit from the sweat of others. I know that he suffered and has seen horrors that I cannot even imagine, but some of that darkness hangs over him still.\ttrue\tGillian39\r\nTEXT_GILLIAN10\tOgden and his wife have taken me and my grandmother into their home and have even let me earn a few gold pieces by working at the inn. I owe so much to them, and hope one day to leave this place and help them start a grand hotel in the east.\ttrue\tGillian40\r\nTEXT_GRISWOLD1\tWell, what can I do for ya?\tfalse\tGriswold44\r\nTEXT_GRISWOLD2\tIf you're looking for a good weapon, let me show this to you. Take your basic blunt weapon, such as a mace. Works like a charm against most of those undying horrors down there, and there's nothing better to shatter skinny little skeletons!\ttrue\tGriswold45\r\nTEXT_GRISWOLD3\tThe axe? Aye, that's a good weapon, balanced against any foe. Look how it cleaves the air, and then imagine a nice fat demon head in its path. Keep in mind, however, that it is slow to swing - but talk about dealing a heavy blow!\ttrue\tGriswold46\r\nTEXT_GRISWOLD4\tLook at that edge, that balance. A sword in the right hands, and against the right foe, is the master of all weapons. Its keen blade finds little to hack or pierce on the undead, but against a living, breathing enemy, a sword will better slice their flesh!\ttrue\tGriswold47\r\nTEXT_GRISWOLD5\tYour weapons and armor will show the signs of your struggles against the Darkness. If you bring them to me, with a bit of work and a hot forge, I can restore them to top fighting form.\ttrue\tGriswold48\r\nTEXT_GRISWOLD6\tWhile I have to practically smuggle in the metals and tools I need from caravans that skirt the edges of our damned town, that witch, Adria, always seems to get whatever she needs. If I knew even the smallest bit about how to harness magic as she did, I could make some truly incredible things.\ttrue\tGriswold49\r\nTEXT_GRISWOLD7\tGillian is a nice lass. Shame that her gammer is in such poor health or I would arrange to get both of them out of here on one of the trading caravans.\ttrue\tGriswold50\r\nTEXT_GRISWOLD8\tSometimes I think that Cain talks too much, but I guess that is his calling in life. If I could bend steel as well as he can bend your ear, I could make a suit of court plate good enough for an Emperor!\ttrue\tGriswold51\r\nTEXT_GRISWOLD9\tI was with Farnham that night that Lazarus led us into Labyrinth. I never saw the Archbishop again, and I may not have survived if Farnham was not at my side. I fear that the attack left his soul as crippled as, well, another did my leg. I cannot fight this battle for him now, but I would if I could.\ttrue\tGriswold52\r\nTEXT_GRISWOLD10\tA good man who puts the needs of others above his own. You won't find anyone left in Tristram - or anywhere else for that matter - who has a bad thing to say about the healer.\ttrue\tGriswold53\r\nTEXT_GRISWOLD12\tThat lad is going to get himself into serious trouble... or I guess I should say, again. I've tried to interest him in working here and learning an honest trade, but he prefers the high profits of dealing in goods of dubious origin. I cannot hold that against him after what happened to him, but I do wish he would at least be careful.\ttrue\tGriswold55\r\nTEXT_GRISWOLD13\tThe Innkeeper has little business and no real way of turning a profit. He manages to make ends meet by providing food and lodging for those who occasionally drift through the village, but they are as likely to sneak off into the night as they are to pay him. If it weren't for the stores of grains and dried meats he kept in his cellar, why, most of us would have starved during that first year when the entire countryside was overrun by demons.\ttrue\tGriswold56\r\nTEXT_FARNHAM1\tCan't a fella drink in peace?\tfalse\tFarnham27\r\nTEXT_FARNHAM2\tThe gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too.\ttrue\tFarnham28\r\nTEXT_FARNHAM3\tWhy don't that old crone do somethin' for a change. Sure, sure, she's got stuff, but you listen to me... she's unnatural. I ain't never seen her eat or drink - and you can't trust somebody who doesn't drink at least a little.\ttrue\tFarnham29\r\nTEXT_FARNHAM4\tCain isn't what he says he is. Sure, sure, he talks a good story... some of 'em are real scary or funny... but I think he knows more than he knows he knows.\ttrue\tFarnham30\r\nTEXT_FARNHAM5\tGriswold? Good old Griswold. I love him like a brother! We fought together, you know, back when... we... Lazarus...  Lazarus... Lazarus!!!\ttrue\tFarnham31\r\nTEXT_FARNHAM6\tHehehe, I like Pepin. He really tries, you know. Listen here, you should make sure you get to know him. Good fella like that with people always wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a hero too...\ttrue\tFarnham32\r\nTEXT_FARNHAM8\tWirt is a kid with more problems than even me, and I know all about problems. Listen here - that kid is gotta sweet deal, but he's been there, you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad...\ttrue\tFarnham34\r\nTEXT_FARNHAM9\tOgden is the best man in town. I don't think his wife likes me much, but as long as she keeps tappin' kegs, I'll like her just fine. Seems like I been spendin' more time with Ogden than most, but he's so good to me...\ttrue\tFarnham35\r\nTEXT_FARNHAM10\tI wanna tell ya sumthin', 'cause I know all about this stuff. It's my specialty. This here is the best... theeeee best! That other ale ain't no good since those stupid dogs...\ttrue\tFarnham23\r\nTEXT_FARNHAM11\tNo one ever lis... listens to me. Somewhere - I ain't too sure - but somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and just waitin' for someone to get it.\ttrue\tFarnham24\r\nTEXT_FARNHAM12\tI know you gots your own ideas, and I know you're not gonna believe this, but that weapon you got there - it just ain't no good against those big brutes! Oh, I don't care what Griswold says, they can't make anything like they used to in the old days...\ttrue\tFarnham25\r\nTEXT_FARNHAM13\tIf I was you... and I ain't... but if I was, I'd sell all that stuff you got and get out of here. That boy out there... He's always got somethin' good, but you gotta give him some gold or he won't even show you what he's got.\ttrue\tFarnham26\r\nTEXT_ADRIA1\tI sense a soul in search of answers...\tfalse\tAdria38\r\nTEXT_ADRIA2\tWisdom is earned, not given. If you discover a tome of knowledge, devour its words. Should you already have knowledge of the arcane mysteries scribed within a book, remember - that level of mastery can always increase.\ttrue\tAdria39\r\nTEXT_ADRIA3\tThe greatest power is often the shortest lived. You may find ancient words of power written upon scrolls of parchment. The strength of these scrolls lies in the ability of either apprentice or adept to cast them with equal ability. Their weakness is that they must first be read aloud and can never be kept at the ready in your mind. Know also that these scrolls can be read but once, so use them with care.\ttrue\tAdria40\r\nTEXT_ADRIA4\tThough the heat of the sun is beyond measure, the mere flame of a candle is of greater danger. No energies, no matter how great, can be used without the proper focus. For many spells, ensorcelled Staves may be charged with magical energies many times over. I have the ability to restore their power - but know that nothing is done without a price.\ttrue\tAdria41\r\nTEXT_ADRIA5\tThe sum of our knowledge is in the sum of its people. Should you find a book or scroll that you cannot decipher, do not hesitate to bring it to me. If I can make sense of it I will share what I find.\ttrue\tAdria42\r\nTEXT_ADRIA6\tTo a man who only knows Iron, there is no greater magic than Steel. The blacksmith Griswold is more of a sorcerer than he knows. His ability to meld fire and metal is unequaled in this land.\ttrue\tAdria43\r\nTEXT_ADRIA7\tCorruption has the strength of deceit, but innocence holds the power of purity. The young woman Gillian has a pure heart, placing the needs of her matriarch over her own. She fears me, but it is only because she does not understand me.\ttrue\tAdria44\r\nTEXT_ADRIA8\tA chest opened in darkness holds no greater treasure than when it is opened in the light. The storyteller Cain is an enigma, but only to those who do not look. His knowledge of what lies beneath the cathedral is far greater than even he allows himself to realize.\ttrue\tAdria45\r\nTEXT_ADRIA9\tThe higher you place your faith in one man, the farther it has to fall. Farnham has lost his soul, but not to any demon. It was lost when he saw his fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to be gleaned, but you must separate fact from fantasy.\ttrue\tAdria46\r\nTEXT_ADRIA10\tThe hand, the heart and the mind can perform miracles when they are in perfect harmony. The healer Pepin sees into the body in a way that even I cannot. His ability to restore the sick and injured is magnified by his understanding of the creation of elixirs and potions. He is as great an ally as you have in Tristram.\ttrue\tAdria47\r\nTEXT_ADRIA12\tThere is much about the future we cannot see, but when it comes it will be the children who wield it. The boy Wirt has a blackness upon his soul, but he poses no threat to the town or its people. His secretive dealings with the urchins and unspoken guilds of nearby towns gain him access to many devices that cannot be easily found in Tristram. While his methods may be reproachful, Wirt can provide assistance for your battle against the encroaching Darkness.\ttrue\tAdria49\r\nTEXT_ADRIA13\tEarthen walls and thatched canopy do not a home create. The innkeeper Ogden serves more of a purpose in this town than many understand. He provides shelter for Gillian and her matriarch, maintains what life Farnham has left to him, and provides an anchor for all who are left in the town to what Tristram once was. His tavern, and the simple pleasures that can still be found there, provide a glimpse of a life that the people here remember. It is that memory that continues to feed their hopes for your success.\ttrue\tAdria50\r\nTEXT_WIRT1\tPssst... over here...\tfalse\tWirt32\r\nTEXT_WIRT2\tNot everyone in Tristram has a use - or a market - for everything you will find in the labyrinth. Not even me, as hard as that is to believe. \\n \\nSometimes, only you will be able to find a purpose for some things.\ttrue\tWirt33\r\nTEXT_WIRT3\tDon't trust everything the drunk says. Too many ales have fogged his vision and his good sense.\ttrue\tWirt34\r\nTEXT_WIRT4\tIn case you haven't noticed, I don't buy anything from Tristram. I am an importer of quality goods. If you want to peddle junk, you'll have to see Griswold, Pepin or that witch, Adria. I'm sure that they will snap up whatever you can bring them...\ttrue\tWirt35\r\nTEXT_WIRT5\tI guess I owe the blacksmith my life - what there is of it. Sure, Griswold offered me an apprenticeship at the smithy, and he is a nice enough guy, but I'll never get enough money to... well, let's just say that I have definite plans that require a large amount of gold.\ttrue\tWirt36\r\nTEXT_WIRT6\tIf I were a few years older, I would shower her with whatever riches I could muster, and let me assure you I can get my hands on some very nice stuff. Gillian is a beautiful girl who should get out of Tristram as soon as it is safe. Hmmm... maybe I'll take her with me when I go...\ttrue\tWirt37\r\nTEXT_WIRT7\tCain knows too much. He scares the life out of me - even more than that woman across the river. He keeps telling me about how lucky I am to be alive, and how my story is foretold in legend. I think he's off his crock.\ttrue\tWirt38\r\nTEXT_WIRT8\tFarnham - now there is a man with serious problems, and I know all about how serious problems can be. He trusted too much in the integrity of one man, and Lazarus led him into the very jaws of death. Oh, I know what it's like down there, so don't even start telling me about your plans to destroy the evil that dwells in that Labyrinth. Just watch your legs...\ttrue\tWirt39\r\nTEXT_WIRT9\tAs long as you don't need anything reattached, old Pepin is as good as they come. \\n \\nIf I'd have had some of those potions he brews, I might still have my leg...\ttrue\tWirt40\r\nTEXT_WIRT11\tAdria truly bothers me. Sure, Cain is creepy in what he can tell you about the past, but that witch can see into your past. She always has some way to get whatever she needs, too. Adria gets her hands on more merchandise than I've seen pass through the gates of the King's Bazaar during High Festival.\ttrue\tWirt42\r\nTEXT_WIRT12\tOgden is a fool for staying here. I could get him out of town for a very reasonable price, but he insists on trying to make a go of it with that stupid tavern. I guess at the least he gives Gillian a place to work, and his wife Garda does make a superb Shepherd's pie...\ttrue\tWirt43\r\nTEXT_BONER\tBeyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written.\ttrue\tWarrior1\r\nTEXT_BLOODY\t...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken...\ttrue\tWarrior10\r\nTEXT_BLINDING\tI can see what you see not.\\nVision milky then eyes rot.\\nWhen you turn they will be gone,\\nWhispering their hidden song.\\nThen you see what cannot be,\\nShadows move where light should be.\\nOut of darkness, out of mind,\\nCast down into the Halls of the Blind.\ttrue\tWarrior11\r\nTEXT_BLOODWAR\tThe armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and men alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood.\ttrue\tWarrior12\r\nTEXT_MBONER\tBeyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written.\ttrue\tWarrior1\r\nTEXT_MBLOODY\t...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken...\ttrue\tWarrior10\r\nTEXT_MBLINDING\tI can see what you see not.\\nVision milky then eyes rot.\\nWhen you turn they will be gone,\\nWhispering their hidden song.\\nThen you see what cannot be,\\nShadows move where light should be.\\nOut of darkness, out of mind,\\nCast down into the Halls of the Blind.\ttrue\tWarrior11\r\nTEXT_MBLOODWAR\tThe armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and men alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood.\ttrue\tWarrior12\r\nTEXT_RBONER\tBeyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written.\ttrue\tWarrior1\r\nTEXT_RBLOODY\t...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken...\ttrue\tWarrior10\r\nTEXT_RBLINDING\tI can see what you see not.\\nVision milky then eyes rot.\\nWhen you turn they will be gone,\\nWhispering their hidden song.\\nThen you see what cannot be,\\nShadows move where light should be.\\nOut of darkness, out of mind,\\nCast down into the Halls of the Blind.\ttrue\tWarrior11\r\nTEXT_RBLOODWAR\tThe armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and men alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood.\ttrue\tWarrior12\r\nTEXT_COW1\t\tfalse\tCow1\r\nTEXT_COW2\t\tfalse\tCow2\r\nTEXT_BOOK11\tTake heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. There is a war that rages on even now, beyond the fields that we know - between the utopian kingdoms of the High Heavens and the chaotic pits of the Burning Hells. This war is known as the Great Conflict, and it has raged and burned longer than any of the stars in the sky. Neither side ever gains sway for long as the forces of Light and Darkness constantly vie for control over all creation.\ttrue\tNarrator1\r\nTEXT_BOOK12\tTake heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. When the Eternal Conflict between the High Heavens and the Burning Hells falls upon mortal soil, it is called the Sin War. Angels and Demons walk amongst humanity in disguise, fighting in secret, away from the prying eyes of mortals. Some daring, powerful mortals have even allied themselves with either side, and helped to dictate the course of the Sin War.\ttrue\tNarrator2\r\nTEXT_BOOK13\tTake heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. Nearly three hundred years ago, it came to be known that the Three Prime Evils of the Burning Hells had mysteriously come to our world. The Three Brothers ravaged the lands of the east for decades, while humanity was left trembling in their wake. Our Order - the Horadrim - was founded by a group of secretive magi to hunt down and capture the Three Evils once and for all.\\n \\nThe original Horadrim captured two of the Three within powerful artifacts known as Soulstones and buried them deep beneath the desolate eastern sands. The third Evil escaped capture and fled to the west with many of the Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - was eventually captured, his essence set in a Soulstone and buried within this Labyrinth.\\n \\nBe warned that the soulstone must be kept from discovery by those not of the faith. If Diablo were to be released, he would seek a body that is easily controlled as he would be very weak - perhaps that of an old man or a child.\ttrue\tNarrator3\r\nTEXT_BOOK21\tSo it came to be that there was a great revolution within the Burning Hells known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils and banished their spirit forms to the mortal realm. The demons Belial (the Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of Hell during the absence of the Three Brothers. All of Hell polarized between the factions of Belial and Azmodan while the forces of the High Heavens continually battered upon the very Gates of Hell.\ttrue\tNarrator4\r\nTEXT_BOOK22\tMany demons traveled to the mortal realm in search of the Three Brothers. These demons were followed to the mortal plane by Angels who hunted them throughout the vast cities of the East. The Angels allied themselves with a secretive Order of mortal magi named the Horadrim, who quickly became adept at hunting demons. They also made many dark enemies in the underworlds.\ttrue\tNarrator5\r\nTEXT_BOOK23\tSo it came to be that the Three Prime Evils were banished in spirit form to the mortal realm and after sewing chaos across the East for decades, they were hunted down by the cursed Order of the mortal Horadrim. The Horadrim used artifacts called Soulstones to contain the essence of Mephisto, the Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest brother - Diablo, the Lord of Terror - escaped to the west.\\n \\nEventually the Horadrim captured Diablo within a Soulstone as well, and buried him under an ancient, forgotten Cathedral. There, the Lord of Terror sleeps and awaits the time of his rebirth. Know ye that he will seek a body of youth and power to possess - one that is innocent and easily controlled. He will then arise to free his Brothers and once more fan the flames of the Sin War...\ttrue\tNarrator6\r\nTEXT_BOOK31\tAll praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When he awakened from his long slumber, my Lord and Master spoke to me of secrets that few mortals know. He told me the kingdoms of the High Heavens and the pits of the Burning Hells engage in an eternal war. He revealed the powers that have brought this discord to the realms of man. My lord has named the battle for this world and all who exist here the Sin War.\ttrue\tNarrator7\r\nTEXT_BOOK32\tGlory and Approbation to Diablo - Lord of Terror and Leader of the Three. My Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished to this world long ago. My Lord wishes to bide his time and harness his awesome power so that he may free his captive brothers from their tombs beneath the sands of the east. Once my Lord releases his Brothers, the Sin War will once again know the fury of the Three.\ttrue\tNarrator8\r\nTEXT_BOOK33\tHail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I awoke my Master from his sleep, he attempted to possess a mortal's form. Diablo attempted to claim the body of King Leoric, but my Master was too weak from his imprisonment. My Lord required a simple and innocent anchor to this world, and so found the boy Albrecht to be perfect for the task. While the good King Leoric was left maddened by Diablo's unsuccessful possession, I kidnapped his son Albrecht and brought him before my Master. I now await Diablo's call and pray that I will be rewarded when he at last emerges as the Lord of this world.\ttrue\tNarrator9\r\nTEXT_INTRO\tThank goodness you've returned!\\nMuch has changed since you lived here, my friend. All was peaceful until the dark riders came and destroyed our village. Many were cut down where they stood, and those who took up arms were slain or dragged away to become slaves - or worse. The church at the edge of town has been desecrated and is being used for dark rituals. The screams that echo in the night are inhuman, but some of our townsfolk may yet survive. Follow the path that lies between my tavern and the blacksmith shop to find the church and save who you can. \\n \\nPerhaps I can tell you more if we speak again. Good luck.\ttrue\tOgden0\r\nTEXT_HBONER\tBeyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written.\ttrue\tWarrior1\r\nTEXT_HBLOODY\t...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken...\ttrue\tWarrior10\r\nTEXT_HBLINDING\tI can see what you see not.\\nVision milky then eyes rot.\\nWhen you turn they will be gone,\\nWhispering their hidden song.\\nThen you see what cannot be,\\nShadows move where light should be.\\nOut of darkness, out of mind,\\nCast down into the Halls of the Blind.\ttrue\tWarrior11\r\nTEXT_HBLOODWAR\tThe armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and men alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood.\ttrue\tWarrior12\r\nTEXT_BBONER\tBeyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written.\ttrue\tWarrior1\r\nTEXT_BBLOODY\t...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken...\ttrue\tWarrior10\r\nTEXT_BBLINDING\tI can see what you see not.\\nVision milky then eyes rot.\\nWhen you turn they will be gone,\\nWhispering their hidden song.\\nThen you see what cannot be,\\nShadows move where light should be.\\nOut of darkness, out of mind,\\nCast down into the Halls of the Blind.\ttrue\tWarrior11\r\nTEXT_BBLOODWAR\tThe armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and men alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood.\ttrue\tWarrior12\r\nTEXT_GRAVE1\tMaintain your quest.  Finding a treasure that is lost is not easy.  Finding a treasure that is hidden less so.  I will leave you with this.  Do not let the sands of time confuse your search.\ttrue\tAdria19\r\nTEXT_GRAVE2\tA what?!  This is foolishness.  There's no treasure buried here in Tristram.  Let me see that!!  Ah, Look these drawings are inaccurate.  They don't match our town at all.  I'd keep my mind on what lies below the cathedral and not what lies below our topsoil.\ttrue\tGriswold18\r\nTEXT_GRAVE3\tI really don't have time to discuss some map you are looking for.  I have many sick people that require my help and yours as well.\ttrue\tPepin17\r\nTEXT_GRAVE4\tThe once proud Iswall is trapped deep beneath the surface of this world.  His honor stripped and his visage altered.  He is trapped in immortal torment.  Charged to conceal the very thing that could free him.\ttrue\tAdria9\r\nTEXT_GRAVE5\tI'll bet that Wirt saw you coming and put on an act just so he could laugh at you later when you were running around the town with your nose in the dirt.  I'd ignore it.\ttrue\tOgden17\r\nTEXT_GRAVE6\tThere was a time when this town was a frequent stop for travelers from far and wide.  Much has changed since then.  But hidden caves and buried treasure are common fantasies of any child.  Wirt seldom indulges in youthful games.  So it may just be his imagination.\ttrue\tCain19\r\nTEXT_GRAVE7\tListen here.  Come close.  I don't know if you know what I know, but you've have really got something here.  That's a map.\ttrue\tFarnham21\r\nTEXT_GRAVE8\tMy grandmother often tells me stories about the strange forces that inhabit the graveyard outside of the church.  And it may well interest you to hear one of them.  She said that if you were to leave the proper offering in the cemetery, enter the cathedral to pray for the dead, and then return, the offering would be altered in some strange way.  I don't know if this is just the talk of an old sick woman, but anything seems possible these days.\ttrue\tGillian27\r\nTEXT_GRAVE9\tHmmm.  A vast and mysterious treasure you say.  Mmmm.  Maybe I could be interested in picking up a few things from you.  Or better yet, don't you need some rare and expensive supplies to get you through this ordeal?\ttrue\tWirt7\r\nTEXT_GRAVE10\tThe once proud Iswall is trapped deep beneath the surface of this world.  His honor stripped and his visage altered.  He is trapped in immortal torment.  Charged to conceal the very thing that could free him.\ttrue\tAdria9\r\nTEXT_FARMER1\tSo, you're the hero everyone's been talking about. Perhaps you could help a poor, simple farmer out of a terrible mess? At the edge of my orchard, just south of here, there's a horrible thing swelling out of the ground! I can't get to my crops or my bales of hay, and my poor cows will starve. The witch gave this to me and said that it would blast that thing out of my field. If you could destroy it, I would be forever grateful. I'd do it myself, but someone has to stay here with the cows...\ttrue\tFarmer1\r\nTEXT_FARMER2\tI knew that it couldn't be as simple as that witch made it sound. It's a sad world when you can't even trust your neighbors.\ttrue\tFarmer2\r\nTEXT_FARMER3\tIs it gone? Did you send it back to the dark recesses of Hades that spawned it? You what? Oh, don't tell me you lost it! Those things don't come cheap, you know. You've got to find it, and then blast that horror out of our town.\ttrue\tFarmer3\r\nTEXT_FARMER4\tI heard the explosion from here! Many thanks to you, kind stranger. What with all these things comin' out of the ground, monsters taking over the church, and so forth, these are trying times. I am but a poor farmer, but here -- take this with my great thanks.\ttrue\tFarmer4\r\nTEXT_FARMER5\tOh, such a trouble I have...maybe...No, I couldn't impose on you, what with all the other troubles. Maybe after you've cleansed the church of some of those creatures you could come back... and spare a little time to help a poor farmer?\ttrue\tFarmer5\r\nTEXT_GIRL1\tWaaaah! (sniff) Waaaah! (sniff)\ttrue\tCelia1\r\nTEXT_GIRL2\tI lost Theo!  I lost my best friend!  We were playing over by the river, and Theo said he wanted to go look at the big green thing.  I said we shouldn't, but we snuck over there, and then suddenly this BUG came out!  We ran away but Theo fell down and the bug GRABBED him and took him away!\ttrue\tCelia2\r\nTEXT_GIRL3\tDidja find him?  You gotta find Theodore, please!  He's just little.  He can't take care of himself!  Please!\ttrue\tCelia3\r\nTEXT_GIRL4\tYou found him!  You found him!  Thank you!  Oh Theo, did those nasty bugs scare you?  Hey!  Ugh!  There's something stuck to your fur!  Ick!  Come on, Theo, let's go home!  Thanks again, hero person!\ttrue\tCelia4\r\nTEXT_DEFILER1\tWe have long lain dormant, and the time to awaken has come.  After our long sleep, we are filled with great hunger.  Soon, now, we shall feed...\ttrue\tDefiler6\r\nTEXT_DEFILER2\tHave you been enjoying yourself, little mammal?  How pathetic. Your little world will be no challenge at all.\ttrue\tDefiler2\r\nTEXT_DEFILER3\tThese lands shall be defiled, and our brood shall overrun the fields that men call home.  Our tendrils shall envelop this world, and we will feast on the flesh of its denizens.  Man shall become our chattel and sustenance.\ttrue\tDefiler7\r\nTEXT_DEFILER4\tAh, I can smell you...you are close! Close! Ssss...the scent of blood and fear...how enticing...\ttrue\tDefiler4\r\nTEXT_DEFILER5\t\ttrue\tDefiler8\r\nTEXT_NAKRUL1\t\ttrue\tNaKrul1\r\nTEXT_NAKRUL2\t\ttrue\tNaKrul2\r\nTEXT_NAKRUL3\t\ttrue\tNaKrul3\r\nTEXT_NAKRUL4\t\ttrue\tNaKrul4\r\nTEXT_NAKRUL5\t\ttrue\tNaKrul5\r\nTEXT_CORNSTN\tAnd in the year of the Golden Light, it was so decreed that a great Cathedral be raised.  The cornerstone of this holy place was to be carved from the translucent stone Antyrael, named for the Angel who shared his power with the Horadrim.  \\n \\nIn the Year of Drawing Shadows, the ground shook and the Cathedral shattered and fell.  As the building of catacombs and castles began and man stood against the ravages of the Sin War, the ruins were scavenged for their stones.  And so it was that the cornerstone vanished from the eyes of man. \\n \\nThe stone was of this world -- and of all worlds -- as the Light is both within all things and beyond all things. Light and unity are the products of this holy foundation, a unity of purpose and a unity of possession.\ttrue\tNarratorHF3\r\nTEXT_JERSEY1\tMoo.\ttrue\tCompleteNut1\r\nTEXT_JERSEY2\tI said, Moo.\ttrue\tCompleteNut2\r\nTEXT_JERSEY3\tLook I'm just a cow, OK?\ttrue\tCompleteNut3\r\nTEXT_JERSEY4\tAll right, all right.  I'm not really a cow.  I don't normally go around like this; but, I was sitting at home minding my own business and all of a sudden these bugs & vines & bulbs & stuff started coming out of the floor... it was horrible!  If only I had something normal to wear, it wouldn't be so bad.  Hey!  Could you go back to my place and get my suit for me?  The brown one, not the gray one, that's for evening wear.  I'd do it myself, but I don't want anyone seeing me like this.  Here, take this, you might need it... to kill those things that have overgrown everything.  You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.\ttrue\tCompleteNut4\r\nTEXT_JERSEY5\tWhat are you wasting time for?  Go get my suit!  And hurry!  That Holstein over there keeps winking at me!\ttrue\tCompleteNut5\r\nTEXT_JERSEY6\tHey, have you got my suit there?  Quick, pass it over!  These ears itch like you wouldn't believe!\ttrue\tCompleteNut6\r\nTEXT_JERSEY7\tNo no no no!  This is my GRAY suit!  It's for evening wear!  Formal occasions!  I can't wear THIS.  What are you, some kind of weirdo?  I need the BROWN suit.\ttrue\tCompleteNut7\r\nTEXT_JERSEY8\tAhh, that's MUCH better.  Whew!  At last, some dignity!  Are my antlers on straight?  Good.  Look, thanks a lot for helping me out.  Here, take this as a gift; and, you know... a little fashion tip... you could use a little... you could use a new... yknowwhatImean?  The whole adventurer motif is just so... retro.  Just a word of advice, eh?  Ciao.\ttrue\tCompleteNut8\r\nTEXT_JERSEY9\tLook.  I'm a cow.  And you, you're monster bait. Get some experience under your belt!  We'll talk...\ttrue\tCompleteNut9\r\nTEXT_TRADER\t\ttrue\tNone\r\nTEXT_FARMER6\tIt must truly be a fearsome task I've set before you. If there was just some way that I could... would a flagon of some nice, fresh milk help?\ttrue\tFarmer2a\r\nTEXT_FARMER7\tOh, I could use your help, but perhaps after you've saved the catacombs from the desecration of those beasts.\ttrue\tFarmer6\r\nTEXT_FARMER8\tI need something done, but I couldn't impose on a perfect stranger. Perhaps after you've been here a while I might feel more comfortable asking a favor.\ttrue\tFarmer7\r\nTEXT_FARMER9\tI see in you the potential for greatness.  Perhaps sometime while you are fulfilling your destiny, you could stop by and do a little favor for me?\ttrue\tFarmer8\r\nTEXT_FARMER10\tI think you could probably help me, but perhaps after you've gotten a little more powerful. I wouldn't want to injure the village's only chance to destroy the menace in the church!\ttrue\tFarmer9\r\nTEXT_JERSEY10\tMe, I'm a self-made cow.  Make something of yourself, and... then we'll talk.\ttrue\tCompleteNut10\r\nTEXT_JERSEY11\tI don't have to explain myself to every tourist that walks by!  Don't you have some monsters to kill?  Maybe we'll talk later.  If you live...\ttrue\tCompleteNut11\r\nTEXT_JERSEY12\tQuit bugging me.  I'm looking for someone really heroic.  And you're not it.  I can't trust you, you're going to get eaten by monsters any day now... I need someone who's an experienced hero.\ttrue\tCompleteNut12\r\nTEXT_JERSEY13\tAll right, I'll cut the bull.  I didn't mean to steer you wrong.  I was sitting at home, feeling moo-dy, when things got really un-stable; a whole stampede of monsters came out of the floor!  I just cowed.  I just happened to be wearing this Jersey when I ran out the door, and now I look udderly ridiculous.  If only I had something normal to wear, it wouldn't be so bad.  Hey!  Can you go back to my place and get my suit for me?  The brown one, not the gray one, that's for evening wear.  I'd do it myself, but I don't want anyone seeing me like this.  Here, take this, you might need it... to kill those things that have overgrown everything.  You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.\ttrue\tCompleteNut4a\r\nTEXT_SKLJRN\t\ttrue\tNone\r\nTEXT_BOOK4\tI have tried spells, threats, abjuration and bargaining with this foul creature -- to no avail.  My methods of enslaving lesser demons seem to have no effect on this fearsome beast.\ttrue\tNarratorHF6\r\nTEXT_BOOK5\tMy home is slowly becoming corrupted by the vileness of this unwanted prisoner.  The crypts are full of shadows that move just beyond the corners of my vision.  The faint scrabble of claws dances at the edges of my hearing. They are searching, I think, for this journal.\ttrue\tNarratorHF7\r\nTEXT_BOOK6\tIn its ranting, the creature has let slip its name -- Na-Krul.  I have attempted to research the name, but the smaller demons have somehow destroyed my library.  Na-Krul... The name fills me with a cold dread.  I prefer to think of it only as The Creature rather than ponder its true name.\ttrue\tNarratorHF8\r\nTEXT_BOOK7\tThe entrapped creature's howls of fury keep me from gaining much needed sleep.  It rages against the one who sent it to the Void, and it calls foul curses upon me for trapping it here.  Its words fill my heart with terror, and yet I cannot block out its voice.\ttrue\tNarratorHF5\r\nTEXT_BOOK8\tMy time is quickly running out.  I must record the ways to weaken the demon, and then conceal that text, lest his minions find some way to use my knowledge to free their lord.  I hope that whoever finds this journal will seek the knowledge.\ttrue\tNarratorHF9\r\nTEXT_BOOK9\tWhoever finds this scroll is charged with stopping the demonic creature that lies within these walls.  My time is over. Even now, its hellish minions claw at the frail door behind which I hide.  \\n \\nI have hobbled the demon with arcane magic and encased it within great walls, but I fear that will not be enough. \\n \\nThe spells found in my three grimoires will provide you protected entrance to his domain, but only if cast in their proper sequence.  The levers at the entryway will remove the barriers and free the demon; touch them not!  Use only these spells to gain entry or his power may be too great for you to defeat.\ttrue\tNarratorHF4\r\nTEXT_BOOKA\tIn Spiritu Sanctum.\ttrue\tWarrior54\r\nTEXT_BOOKB\tPraedictum Otium.\ttrue\tWarrior55\r\nTEXT_BOOKC\tEfficio Obitus Ut Inimicus.\ttrue\tWarrior56\r\nTEXT_OBOOKA\tIn Spiritu Sanctum.\ttrue\tWarrior54\r\nTEXT_OBOOKB\tPraedictum Otium.\ttrue\tWarrior55\r\nTEXT_OBOOKC\tEfficio Obitus Ut Inimicus.\ttrue\tWarrior56\r\nTEXT_MBOOKA\tIn Spiritu Sanctum.\ttrue\tWarrior54\r\nTEXT_MBOOKB\tPraedictum Otium.\ttrue\tWarrior55\r\nTEXT_MBOOKC\tEfficio Obitus Ut Inimicus.\ttrue\tWarrior56\r\nTEXT_RBOOKA\tIn Spiritu Sanctum.\ttrue\tWarrior54\r\nTEXT_RBOOKB\tPraedictum Otium.\ttrue\tWarrior55\r\nTEXT_RBOOKC\tEfficio Obitus Ut Inimicus.\ttrue\tWarrior56\r\nTEXT_BBOOKA\tIn Spiritu Sanctum.\ttrue\tWarrior54\r\nTEXT_BBOOKB\tPraedictum Otium.\ttrue\tWarrior55\r\nTEXT_BBOOKC\tEfficio Obitus Ut Inimicus.\ttrue\tWarrior56\r\n"
  },
  {
    "path": "assets/txtdata/towners/quest_dialog.tsv",
    "content": "towner_type\tQ_ROCK\tQ_MUSHROOM\tQ_GARBUD\tQ_ZHAR\tQ_VEIL\tQ_DIABLO\tQ_BUTCHER\tQ_LTBANNER\tQ_BLIND\tQ_BLOOD\tQ_ANVIL\tQ_WARLORD\tQ_SKELKING\tQ_PWATER\tQ_SCHAMB\tQ_BETRAYER\tQ_GRAVE\tQ_TRADER\nTOWN_SMITH\tTEXT_INFRA6\tTEXT_MUSH6\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL5\tTEXT_NONE\tTEXT_BUTCH5\tTEXT_BANNER6\tTEXT_BLIND5\tTEXT_BLOOD5\tTEXT_ANVIL6\tTEXT_WARLRD5\tTEXT_KING7\tTEXT_POISON7\tTEXT_BONE5\tTEXT_VILE9\tTEXT_GRAVE2\tTEXT_NONE\nTOWN_HEALER\tTEXT_INFRA3\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL3\tTEXT_NONE\tTEXT_BUTCH3\tTEXT_BANNER4\tTEXT_BLIND3\tTEXT_BLOOD3\tTEXT_ANVIL3\tTEXT_WARLRD3\tTEXT_KING5\tTEXT_POISON4\tTEXT_BONE3\tTEXT_VILE7\tTEXT_GRAVE3\tTEXT_NONE\nTOWN_DEADGUY\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_TAVERN\tTEXT_INFRA2\tTEXT_MUSH2\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL2\tTEXT_NONE\tTEXT_BUTCH2\tTEXT_NONE\tTEXT_BLIND2\tTEXT_BLOOD2\tTEXT_ANVIL2\tTEXT_WARLRD2\tTEXT_KING3\tTEXT_POISON2\tTEXT_BONE2\tTEXT_VILE4\tTEXT_GRAVE5\tTEXT_NONE\nTOWN_STORY\tTEXT_INFRA1\tTEXT_MUSH1\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL1\tTEXT_VILE3\tTEXT_BUTCH1\tTEXT_BANNER1\tTEXT_BLIND1\tTEXT_BLOOD1\tTEXT_ANVIL1\tTEXT_WARLRD1\tTEXT_KING1\tTEXT_POISON1\tTEXT_BONE1\tTEXT_VILE2\tTEXT_GRAVE6\tTEXT_NONE\nTOWN_DRUNK\tTEXT_INFRA8\tTEXT_MUSH7\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL6\tTEXT_NONE\tTEXT_BUTCH6\tTEXT_BANNER7\tTEXT_BLIND6\tTEXT_BLOOD6\tTEXT_ANVIL8\tTEXT_WARLRD6\tTEXT_KING8\tTEXT_POISON8\tTEXT_BONE6\tTEXT_VILE10\tTEXT_GRAVE7\tTEXT_NONE\nTOWN_WITCH\tTEXT_INFRA9\tTEXT_MUSH9\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL7\tTEXT_NONE\tTEXT_BUTCH7\tTEXT_BANNER8\tTEXT_BLIND7\tTEXT_BLOOD7\tTEXT_ANVIL9\tTEXT_WARLRD7\tTEXT_KING9\tTEXT_POISON9\tTEXT_BONE7\tTEXT_VILE11\tTEXT_GRAVE1\tTEXT_NONE\nTOWN_BMAID\tTEXT_INFRA4\tTEXT_MUSH5\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL4\tTEXT_NONE\tTEXT_BUTCH4\tTEXT_BANNER5\tTEXT_BLIND4\tTEXT_BLOOD4\tTEXT_ANVIL4\tTEXT_WARLRD4\tTEXT_KING6\tTEXT_POISON6\tTEXT_BONE4\tTEXT_VILE8\tTEXT_GRAVE8\tTEXT_NONE\nTOWN_PEGBOY\tTEXT_INFRA10\tTEXT_MUSH13\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL8\tTEXT_NONE\tTEXT_BUTCH8\tTEXT_BANNER9\tTEXT_BLIND8\tTEXT_BLOOD8\tTEXT_ANVIL10\tTEXT_WARLRD8\tTEXT_KING10\tTEXT_POISON10\tTEXT_BONE8\tTEXT_VILE12\tTEXT_GRAVE9\tTEXT_NONE\nTOWN_COW\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\n"
  },
  {
    "path": "assets/txtdata/towners/towners.tsv",
    "content": "type\tname\tposition_x\tposition_y\tdirection\tanimWidth\tanimPath\tanimFrames\tanimDelay\tgossipTexts\tanimOrder\nTOWN_SMITH\tGriswold the Blacksmith\t62\t63\tSouthWest\t96\ttowners\\smith\\smithn\t16\t3\tTEXT_GRISWOLD2,TEXT_GRISWOLD3,TEXT_GRISWOLD4,TEXT_GRISWOLD5,TEXT_GRISWOLD6,TEXT_GRISWOLD7,TEXT_GRISWOLD8,TEXT_GRISWOLD9,TEXT_GRISWOLD10,TEXT_GRISWOLD12,TEXT_GRISWOLD13\t4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3\nTOWN_HEALER\tPepin the Healer\t55\t79\tSouthEast\t96\ttowners\\healer\\healer\t20\t6\tTEXT_PEPIN2,TEXT_PEPIN3,TEXT_PEPIN4,TEXT_PEPIN5,TEXT_PEPIN6,TEXT_PEPIN7,TEXT_PEPIN9,TEXT_PEPIN10,TEXT_PEPIN11\t0,1,2,2,1,0,19,18,18,19,0,1,2,2,1,0,19,18,18,19,0,1,2,2,1,0,19,18,18,19,0,1,2,2,1,0,19,18,18,19,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19\nTOWN_DEADGUY\tWounded Townsman\t24\t32\tNorth\t96\ttowners\\butch\\deadguy\t8\t6\t\t\nTOWN_TAVERN\tOgden the Tavern owner\t55\t62\tSouthWest\t96\ttowners\\twnf\\twnfn\t16\t3\tTEXT_OGDEN2,TEXT_OGDEN3,TEXT_OGDEN4,TEXT_OGDEN5,TEXT_OGDEN6,TEXT_OGDEN8,TEXT_OGDEN9,TEXT_OGDEN10\t0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,1,0,15,14,13,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\nTOWN_STORY\tCain the Elder\t62\t71\tSouth\t96\ttowners\\strytell\\strytell\t25\t3\tTEXT_STORY2,TEXT_STORY3,TEXT_STORY4,TEXT_STORY5,TEXT_STORY6,TEXT_STORY7,TEXT_STORY9,TEXT_STORY10,TEXT_STORY11\t0,0,24,24,23,22,21,20,19,18,17,16,15,14,15,16,17,18,19,20,21,22,23,24,24,24,0,0,0,24,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0\nTOWN_DRUNK\tFarnham the Drunk\t71\t84\tSouth\t96\ttowners\\drunk\\twndrunk\t18\t3\tTEXT_FARNHAM2,TEXT_FARNHAM3,TEXT_FARNHAM4,TEXT_FARNHAM5,TEXT_FARNHAM6,TEXT_FARNHAM8,TEXT_FARNHAM9,TEXT_FARNHAM10,TEXT_FARNHAM11,TEXT_FARNHAM12,TEXT_FARNHAM13\t0,0,0,1,2,3,4,5,6,7,8,9,10,10,10,10,11,12,13,14,15,16,17,17,0,0,0,17,16,15,14,13,12,11,10,9,10,11,12,13,14,15,16,17,0,1,2,3,4,4,4,3,2,1\nTOWN_WITCH\tAdria the Witch\t80\t20\tSouth\t96\ttowners\\townwmn1\\witch\t19\t6\tTEXT_ADRIA2,TEXT_ADRIA3,TEXT_ADRIA4,TEXT_ADRIA5,TEXT_ADRIA6,TEXT_ADRIA7,TEXT_ADRIA8,TEXT_ADRIA9,TEXT_ADRIA10,TEXT_ADRIA12,TEXT_ADRIA13\t3,3,3,4,5,5,5,4,3,14,13,12,12,12,13,14,3,4,5,5,5,4,3,3,3,4,5,5,5,4,3,14,13,12,12,12,13,14,3,4,5,5,5,4,3,3,3,4,5,5,5,4,3,14,13,12,12,12,13,14,3,4,5,5,5,4,3,2,1,0,18,17,18,0,1,0,18,17,18,0,1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,14,14,13,12,12,12,12,13,14,14,14,13,12,11,11,11,10,9,9,9,8,7,8,9,9,10,11,12,13,14,15,16,17,18,0,1,0,18,17,18,0,1,0,1,2\nTOWN_BMAID\tGillian the Barmaid\t43\t66\tSouth\t96\ttowners\\townwmn1\\wmnn\t18\t6\tTEXT_GILLIAN2,TEXT_GILLIAN3,TEXT_GILLIAN4,TEXT_GILLIAN5,TEXT_GILLIAN6,TEXT_GILLIAN7,TEXT_GILLIAN9,TEXT_GILLIAN10\t\nTOWN_PEGBOY\tWirt the Peg-legged boy\t11\t53\tSouth\t96\ttowners\\townboy\\pegkid1\t20\t6\tTEXT_WIRT2,TEXT_WIRT3,TEXT_WIRT4,TEXT_WIRT5,TEXT_WIRT6,TEXT_WIRT7,TEXT_WIRT8,TEXT_WIRT9,TEXT_WIRT11,TEXT_WIRT12\t\nTOWN_COW\tCow\t58\t16\tSouthWest\t128\t\t12\t3\t\t\nTOWN_COW\tCow\t56\t14\tNorthWest\t128\t\t12\t3\t\t\nTOWN_COW\tCow\t59\t20\tNorth\t128\t\t12\t3\t\t\n"
  },
  {
    "path": "codecov.yml",
    "content": "codecov:\n  require_ci_to_pass: no\n  notify:\n    wait_for_ci: no\ncomment: no\ncoverage:\n  range: \"45...85\"\n  status:\n    project:\n      default:\n        target: 0%\n        threshold: 0.02%\n    patch: no\nignore:\n  - \"3rdParty\"\n  - \"test\"\nflag_management:\n  default_rules:\n    carryforward: false\n"
  },
  {
    "path": "docs/BACKGROUND.md",
    "content": "# Project background\n\nTo give further background, the Devilution team has primarily relied on these resources:\n\n1. The Japanese Playstation port with debug symbols contained in `DIABPSX.SYM`. (see [[1]]).\n\nExample debug info of the Cathedral dungeon generation algorithm:\n\n```cpp\n// address: 0x801259D0\n// line start: 612\n// line end:   624\nvoid DRLG_L1Floor__Fv() {\n// register: 19\nregister int i;\n// register: 20\nregister int j;\n// register: 3\nregister long rv;\n}\n```\n\n2. The debug release of the PE executable, which contained assert strings (see [[2]]).\n\nExample assert string:\n\n```cpp\n\"plr[myplr].InvGrid[i] <= plr[myplr]._pNumInv\"\n```\n\n3. The Rich header of the PE executable, which details the exact version of the original compilers and linkers used to build `Diablo.exe` (see [[3]], [[4]]).\n\nExample information recovered from the Rich header of `Diablo.exe`:\n\n```\nId  Build  Count  Name       Description\n 0      0    155  Unknown    [---] Number of imported functions (old)\n 1      0    229  Import0    [---] Number of imported functions\n 6   1668      1  Cvtres500  [RES] VS97 (5.0) SP3 cvtres 5.00.1668\n 2   7303     29  Linker510  [IMP] VS97 (5.0) SP3 link 5.10.7303\n 3   7303      1  Cvtomf510        VS97 (5.0) SP3 cvtomf 5.10.7303\n 4   8447      2  Linker600  [LNK] VC++ 6.0 SP3,SP4,SP5,SP6 link 6.00.8447\n48   9044     72  Utc12_2_C  [---] VC++ 6.0 SP5 Processor Pack\n19   9049     12  Linker512        Microsoft LINK 5.12.9049\n```\n\n4. Discovery of the original set of compiler flags used to build `Diablo.exe` (see [[5]]).\n\nPrimarily \"/O1\" was used, but there are also peculiarities such as the use of both Microsoft Visual Studio 6 and Microsoft Visual Code 5 for linking the game.\n\n5. The heartfelt dedication of a team of people. GalaXyHaXz did the initial heavy lifting and succeeded in the tremendous task of getting the decompiled source code of Diablo 1 compiling with the original toolchain. Later on she released the project open source and a community of open source collaborators formed. Most of us have never met in real life prior to joining the project, which stands to show that there is strength in online collaboration that transcends both culture and borders.\n\n6. The Beta release and the Alpha4 release of Diablo 1 has also proved invaluable resources for cross-validation as the compiler optimization level was not set to release mode for these binaries.\n\nInterestingly, in the process a number of bugs in the original implementation of Diablo 1 were discovered. These have been documented in the source code of Devilution with `// BUGFIX: foo` comments, and have also been detailed in [[6]].\n\nTo track the progress of the project, the \"Binary identical functions\" milestone has been used in tandem with an assembly diffing tool developed in Rust (see [[7]], [[8]]).\n\nAnecdotally, it was an incredible moment when we first managed to run the cross-platform port of Diablo 1 (DevilutionX, see [[9]]) natively on Linux and succeeded in playing a multiplayer game connecting our computers in Korea and Denmark. It is equally thrilling to see the modding and porting community picking up the torch and already succeeding in porting Diablo 1 to Nintendo Switch!\n\nThe main reason for conducting this bit of software archeology is to preserve the classic title that is Diablo 1, for generations to come. And to revive it for modern hardware platforms and make it more mod-friendly in the age of open source software.\n\nHappy coding! - The Devilution Team\n\nP.S. the project README explicitly states that to play the game, you still need to have access to the original game assets released on the Diablo 1 CD. To acquire a legal copy, please refer to https://www.gog.com/game/diablo\n\nP.P.S. for the verification process, there have been proposals that are both ambitious at a level of PhD research (see [[10]]) and that made us feel warm and fuzzy <3 In the end, many of the techniques outlined were discussed mostly on a design level, some were included as Proof of Concepts, but most of the work in reverse engineering Diablo 1 was from tender labour of a team that care for Diablo 1 the way you would your firstborn child.\n\nP.P.P.S. you can also view our presentation slides here: https://docs.google.com/presentation/d/1ghmOFFgA3MfuJALMo8hmfNCL6pWWaW3plAbRtmSwfXY/edit?usp=sharing\n\n[1]: https://github.com/diasurgical/scalpel/blob/master/psx/_dump_/_dump_merge_c_src_/diabpsx/source/drlg_l1.cpp\n\n[2]: https://web.archive.org/web/20191129090736/diablo1.se/notes/debug.html\n\n[3]: https://github.com/diasurgical/devilution/issues/111#issuecomment-426059660\n\n[4]: https://bytepointer.com/articles/the_microsoft_rich_header.htm\n\n[5]: https://github.com/diasurgical/devilution/issues/111\n\n[6]: https://github.com/diasurgical/devilution/issues/64\n\n[7]: https://github.com/diasurgical/devilution/milestone/3\n\n[8]: https://github.com/diasurgical/devilution-comparer\n\n[9]: https://github.com/diasurgical/devilutionX\n\n[10]: https://github.com/diasurgical/devilution/issues/171\n"
  },
  {
    "path": "docs/CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## Unreleased\n\n### Features\n\n#### Graphics / Audio\n- Better use of colors to differentiate players in multiplayer\n\n### Bug Fixes\n\n#### Graphics / Audio\n\n- Music doesn't unmute when focus is lost on level transition with Auto Pause On Focus Lost disabled\n- Image ghosting visible on border of map in higher resolutions\n\n#### Stability / Performance / System\n\n- Crashes related to player graphics rendering in death state\n\n## DevilutionX 1.5.2\n\n### Bug Fixes\n\n#### Multiplayer\n\n- Unable to join game due to invalid player data\n\n#### Translations\n\n- Improve rendering of Chinese/Japanese/Korean texts\n\n#### Gameplay\n\n- Hellfire items not saving their identified state\n\n#### Stability / Performance / System\n\n- Amiga: Incorrect rendering of things behind transparent elements\n- Android: Game locking up when switching sound output\n- Linux: Statically link BZIP2 and libsodium on x86_64\n- Stash corrupting when converting a hero between Diablo and Hellfire\n- Xbox: Game crashing unexpectedly\n- Xbox: Improve performance\n\n## DevilutionX 1.5.1\n\n### Features\n\n#### Multiplayer\n\n- Validate player stats\n- Update the pvp arenas\n- Rename \"Loopback\" to \"Offline\"\n\n#### Stability / Performance / System\n\n- Move hp/mana display and item graphics to gameplay options\n- Validate properties when reloading items\n- Demomode: Improve replay stability\n- Update [Discord link](https://discord.gg/devilutionx)\n- Display save game confirmation\n- Reduce ram usage\n\n#### Translations\n\n- Update Simplified Chinese translation\n- Update French translation\n- Update German translation\n- Update Greek translation\n- Update Japanese translation\n- Update Korean translation\n- Update Portuguese translation\n- Update Spanish translation\n- Update Swedish translation\n- Update Ukrainian translation\n\n### Bugfixes\n\n#### Gameplay\n\n- Being able to enter Lazarus' chamber before opening the portal\n- Book requirements not updating\n- Some monsters not walking\n- Missiles not traveling the full distance at some angles\n- Diablo: Incorrect level 4 layout when the Magic Banner quest is active\n- Halls of the Blind not being completed by picking up the amulet\n- Shareware: Bucklers not dropping\n- Player animation stuttering\n\n#### Multiplayer\n\n- Potions dropped by Divine shrines not being synced\n\n#### Platforms\n\n- Linux: Add sdl-image dependency for the deb package\n- Linux: Include discord dependency\n- Xbox One: Missing assets\n\n#### Graphics / Audio\n\n- Incorrect cursor rendering\n- Incorrect outlines at the right edge of the screen\n- NPC speech continuing after starting a new game\n- Correct various font rendering issues\n- Hide the hit indicator when only one player is in the game\n- Issues with flashing lights\n- Floating number still appearing after death\n- Misaligned automap\n\n#### Controls\n\n- Inconsistencies with placing items into the stash\n- Gamepad: Being stuck in dialogs\n- Gamepad: Unable to use some scrolls directly\n\n#### Stability / Performance / System\n\n- Unable to playback new demo files\n- Various crashes\n\n### Bugfixes for original Diablo bugs\n\n#### Gameplay\n\n- Durability overflowing when reloading items\n- Teleporting onto an occupied tile\n- Right-click during dialogs casts spells\n\n#### Graphics / Audio\n\n- Cursor jitter when interacting with the inventory\n- Broken lava tiles\n\n#### Controls\n\n- Inconsistencies with placing items into the inventory\n\n### Bugfixes for original Hellfire bugs\n\n#### Gameplay\n\n- Warping onto a solid tile\n\n## DevilutionX 1.5.0\n\n### Features\n\n#### Gameplay\n\n- Floating damage numbers\n- Option to auto-pick up oils\n- Quest items now drop based on difficulty\n\n#### Multiplayer\n\n- All quests can now be played, enabled from settings menu\n- Add chat commands, use `/help` for options\n- Add PvP arenas that can be accessed via `/arena #`\n- Inspect other players' items using `/inspect <name>`\n- Hellfire: Disabled The Cornerstone of the World\n- Draw hostile players' names in red in the chat panel\n\n#### Platforms\n\n- Added support for the original Xbox\n- Added support for Android TV\n- Added (experimental) support for RG99\n- Provide virtual resolutions for systems with only one native resolution\n- Android: Support loading data from external storage\n- Android: Do not speed up game after suspending if playing alone\n- Windows: Digitally signed executable\n- Support demo playback on SDL1 versions\n\n#### Graphics / Audio\n\n- Option to show item graphics in stores\n- More fluid lighting updates when moving\n- Added map in town\n- Add widescreen load screens (thanks to @Chance4us)\n- Durability icon gradually changing to red\n- Provide sound cue when gold is auto-placed into the open inventory\n- Color inventory slot based on item quality\n- Show cast animation in town\n- Monsters end their invisibility on death\n- Make the ground color of small rejuvenation potions distinct\n- Add setting for choosing a different audio resampler\n- Support for recoloring heroes using trn-files\n- Indicate on which difficulty a hero has defeated Diablo\n- Use decimal separators for gold and XP\n- Improve the monster HP bar for some edge cases\n- Only display resolution height when FitToScreen is enabled\n- Various text rendering improvements\n\n#### Controls\n\n- Do not target monster when casting Heal Other and Resurrect\n- Improve logic for belt auto-refill\n- Adjust the info panel descriptions based on the input device\n- keyboard/mouse: Additional mapping options\n- keyboard/mouse: Support back button in menus\n- gamepad/touch: Improve menu navigation\n- gamepad: Controls can now be mapped\n- gamepad: Autodetect button layout\n\n#### Translations\n\n- Update French translation\n- Update Italian translation\n- Update Japanese translation\n- Update Polish translation\n- Update Spanish translation\n- Update Ukrainian translation\n- Synchronize names of existing items with the current game language\n- Xbox One/Series: Include translations\n- Add `--lang` for specifying the language\n\n#### Stability / Performance / System\n\n- Create submenus for setting groups\n- Date based screenshot names\n- Performance improvement\n- Reduce RAM usage\n- Frame skipping on low end systems\n- Setting for picking audio device\n\n### Bugfixes\n\n#### Gameplay\n\n- Attack speed not always being accurate for specific combinations of effects and actions\n- Hellfire: Books from Adria's shop morphing\n- Petrified monsters shifting position when hit after loading a save game\n- Don't consume mana when double casting Mana Shield\n- Telekinesis respects the Disable Crippling Shrines setting\n\n#### Multiplayer\n\n- Items held by cursor lost due to lag cursor\n- Items lost due to various desync issues\n- Fix multiple desync issues\n- Don't show hostile players on the map\n- Player animations sometimes not being in sync\n- Better handling of latency\n\n#### Platforms\n\n- Windows: Fix ZeroTier always failing for Unicode usernames\n- Vita: Items lost when tapping outside the inventory\n- Fix gold withdrawal on SDL1 versions\n- macOS/iOS translate system texts\n- Translation support on BE systems\n\n#### Graphics / Audio\n\n- Top of screen not being rendered at some resolutions\n- Correct alignment of lightning and inferno\n- Make item labels take UI into consideration\n- Adria's \"you have nothing to recharge\" being misalignment on an empty list\n- Monsters sometimes not being rendered\n- Lighting missing for some areas after loading a saved game\n- Hellfire quests being removed from the quest log when completed\n\n#### Controls\n\n- Hero sometimes not willing to drop an item even when there is still room on the ground\n- touch: Missing buttons on low end devices\n\n#### Stability / Performance / System\n\n- Allow using the built-in screenshot function during text input\n- Various crashes\n- Resolve a few bugs and edge cases with the stash\n- A rare freeze when loading hell levels\n- Various issues with cursor rendering\n- Some additional validation of items when converting saves from Hellfire to Diablo\n\n### Bugfixes for original Diablo bugs\n\n#### Gameplay\n\n- Several issues that would cause missiles to miss when they shouldn't\n- Some wall tiles not blocking missiles and vision\n- The player can spawn in an incorrect location on some levels\n- Missing the extra stats at level 50\n- Guardian not calculating its damage correctly\n- Diablo not giving the intended XP on Hell difficulty\n- Fireball/Elemental not doing damage when monster is not in line of sight\n- Lightning spell being able to pass through some walls\n- Double casting of spells\n- Low quality items on quests after using a town portal\n- Monsters on Nightmare and Hell having too little HP\n- Monsters being immune to non-player missiles\n- Stairs up to level 6 not working sometimes\n- The Deadly Hunter bow not dealing the correct damage\n- Spell remaining unavailable after using a stone shrine until reequipping the staff\n- Fast and faster hit recovery stacking\n- Incorrect calculation for max charges lost with when using the recharge skill\n- Not getting XP after damaging a monster if it dies from a trap\n- Fire Arrows causing monsters to stop healing\n\n#### Multiplayer\n\n- Trapped doors rearming themselves when returning to a level\n- Resolve some sources of dsync\n\n#### Graphics / Audio\n\n- Incorrect Armor Class in Char Panel\n- Petrified monsters turning to face the attacker\n- Petrified monster sliding after having been stone cursed\n- Show portal animation in town\n- Broken corners on some cathedral levels\n- Inconsistent lighting on quest levels\n- Light smearing when walking in certain directions\n- Unique monsters light not always following the monster\n- Unique monster light being left behind when they are removed\n- Minor rendering bugs in UI panels\n- Center 2x2 items that go in 2x3 slots\n- Player moonwalking when talking to monsters\n- Tavern Sign playing the wrong sound when dropped on the floor\n- Poisoned Water not appearing in the quest log if discovered before talking to Pepin\n- Camera shaking when loading a save game after Diablo's death\n- Add scrollbar to help window\n\n#### Controls\n\n- Unable to pick Golem spawn location when right-clicking the scroll\n- Casting spells during level transition will target the old position\n- Help panel staying open while talking to NPCs\n\n#### Stability / Performance / System\n\n- Town portal not always returning to the correct quest level\n- Items lost when triggering a portal while picking them up\n- Optic Amulet and Arkaine's Valor sometimes being misaligned\n- Minor stability issues\n\n### Bugfixes for original Hellfire bugs\n\n#### Gameplay\n\n- Prevent oil of death damage wrap around\n- Reflected damage sometimes being too low\n\n#### Multiplayer\n\n- Desync in Nest when cow quest is enabled\n- Being unable to pick up quest items if you didn't start the game\n- Quest going out of sync\n\n#### Graphics / Audio\n\n- Gillian saying the grave quest start line multiple times\n- Buggy lighting in Nest and Crypt\n- Description of jester's item saying 500% instead of 600% damage\n- Typos in subtitles\n\n## DevilutionX 1.4.1\n\n### Features\n\n#### Graphics / Audio\n\n- Play gold sound effect when depositing in stash\n\n#### Controls\n\n- Add setting for showing item labels\n- Add setting for zoom by default\n\n#### Translations\n\n- Update Chinese Translation\n- Update French Translation\n- Update Japanese Translation\n- Update Polish Translation\n- Update Russian Translation\n- Update Ukrainian Translation\n\n### Bugfixes\n\n#### Gameplay\n\n- Correct behavior for elemental damage on weapons\n- Fallen retreat in the wrong direction\n- Show correct requirements for books in stash\n\n#### Multiplayer\n\n- Issues with joining multiplayer games\n- Refreshing store inventory on new games\n\n#### Platforms\n\n- 3DS: correct C-stick axis mapping\n- 3DS: Package info\n- iOS: Compatibility with Sideloadly\n- iOS/macOS/iPadOS: Show translated error messages\n- OpenDingux: Fix game not starting on some devices\n- PS4: Crashing on startup with no config file\n\n#### Graphics / Audio\n\n- Fix wide screen scenes missing on some platforms\n- Minor graphical issues\n- Misaligned player animation\n\n#### Controls\n\n- Quick cast interrupting the current action\n- Touch: Action buttons sometimes showing the wrong icon\n- Touch/Gamepad: Correct usage description for some spells\n- Touch/Gamepad: Fix targeting berserked monsters\n\n#### Stability / Performance / System\n\n- Improve general game stability\n- Incorrect handling of player names\n- Names on ears not being correct in some translations\n\n### Bugfixes for original Diablo bugs\n\n#### Gameplay\n\n- Fallen not seeing each other in a northern direction\n- Lazarus level resetting when using town portal\n- Shrines effects not being random\n\n#### Multiplayer\n\n- Solve more sources of desync\n\n#### Controls\n\n- Make spell feedback consistent in town and dungeon\n\n### Bugfixes for original Hellfire bugs\n\n#### Gameplay\n\n- Monsters not reacting to being attacked by berserked monster\n\n## DevilutionX 1.4.0\n\n### Features\n\n#### Translations\n\n- Added support for Ukraine 🇺🇦\n- Added Greek localization\n- Added Japanese translation\n- Added Swedish translation\n- Fix some items causing crashes for Spanish and French translations\n- Improve Bulgarian localization\n- Improve Chinese (Simplified) localization\n- Improve Croatian localization\n- Improve Czech localization\n- Improve French localization\n- Improve German localization\n- Improve Italian localization\n- Improve Korean localization\n- Improve Portuguese localization\n- Improve Romanian localization\n- Improve Russian localization ([optional dub](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq) by Stream)\n- Improve Spanish localization\n\n#### Gameplay\n\n- Added a stash at Gillian's house\n- Suppoort for thousands of missiles\n- Added settings menu\n- Added xp share indicator to monster health bar\n- Added option to see exact health/mana\n\n#### Platforms\n\n- Added support for iOS\n- Added support for Nintendo 2DS\n- Added support for PlayStation 4\n- Added support for Xbox One/Series\n- Discord Rich Presence\n- Android: Auto Backup\n- Android: Added game data import shortcut\n- Windows: Auto detect language\n- Windows: Prefer Direct3D 11 for upscaling\n- macOS: Embed assets\n- OpenDingux Lepus: Enable ZeroTier\n\n#### Graphics / Audio\n\n- Always draw hotkeys on spell list\n- Do not stop music when navigating in the main menu\n- Don't hide automap when opening help screen\n- Don't restart music if the same track is played\n- Match unique monster's missiles color to their owner's\n- Show game Difficulty in Automap\n- Use unique unused graphics for Long War Bow\n- Display numeric max resists on character panel\n- Add additional emojis\n- Mute videos when minimized\n- MP3 support\n- Remove stippled transparency option\n\n#### Multiplayer\n\n- Improve how public games are displayed\n- Revamped chat\n- Added a chat log\n- Enable dungeon messages\n- Prevent spells from targeting other players in friendly mode\n\n#### Controls\n\n- A large number of actions can now be mapped to custom keys\n- Increase spell hotkeys from 4 to 12\n- Quick cast option\n- Added support for touch controls on all devices\n- Slightly more responsive player control\n- Add support for multiple lines in quick messages\n- Make main menu react to mouse button up instead of down\n- Android: Auto hide touch UI when not in use\n- mouse: Support for extra buttons\n- gamepad: Hold button to repeat action\n- gamepad: Make scrolls usable from the inventory\n- gamepad: Graphical circle menus\n- touch: Spend stat points when clicking the buttons\n- touch: Disable stand button when in town\n- touch: Enable navigating the spell book\n- 3DS: Add support for the C-stick\n\n#### Stability / Performance / System\n\n- Fine grain control of startup splashes\n- Load custom assets from save folder instead of last known MPQ folder\n- Reduce default debug output\n- Reduce memory consumption during movies\n- Support compressed MPQs\n\n### Bugfixes\n\n#### Gameplay\n\n- Durability overflow not behaving as expected\n- Diablo: Correct Diablo's HP\n- Diablo: Correct the number of items sold by Adria\n- Hellfire: Berserked monsters not fighting each other\n- Hellfire: Ring of Engagement having too high armor penetration\n\n#### Platforms\n\n- Android: Remove broken quit menu\n- Vita/Switch/3DS: Fix support for voice packs\n\n#### Graphics / Audio\n\n- Colored border showing around hardware cursor\n- Hero flickering briefly when dying from a barrel\n- Only use Hardware Cursor if supported\n- Various text rendering improvements\n- Windows: Restore default audio driver (WASAPI)\n- Windows: Fix window scaling\n\n#### Multiplayer\n\n- Correct network error messages\n- Improve handling of high latency\n- Multiplayer being paused after minimizing during loading\n\n#### Controls\n\n- Fix some joysticks not working\n- Item highlighting getting stuck when walking on top of items\n- Missing OK button on error screens\n- Targeting entrances below the original panel height\n- macOS: Mouse confined to a portion of the screen\n- gamepad: Minor improvement to UI navigation\n\n#### Stability / Performance / System\n\n- Fix multiple crashes\n- Improve multiplayer stability\n- Support systems with no GPU\n\n### Bugfixes for original Diablo bugs\n\n#### Gameplay\n\n- Add gold to inventory in a consistent manner\n- Correct cow collision box\n- Final Dungeon Message not playing\n- Knockback being able to push monsters on top of each other\n- Lightning Arrow extra damage not always being applied\n- Mana Shield effectiveness not improving with spell level\n- Minor rounding error in monster damage\n- Negative stats incorrectly preventing use of items\n- Shrines incorrectly lowering Life/Mana below the minimum\n- Some empty tiles in hell blocking movement and missiles\n- Some levels changing layout after loading\n- Some monsters were placed on top of doors\n\n#### Graphics / Audio\n\n- Align various game texts\n- Center panel text when holding red items\n- Correct death animation when wearing armor\n- Missing torches near traps\n\n#### Multiplayer\n\n- Fix multiple desync issues\n\n#### Stability / Performance / System\n\n- Various stability issues\n- Various item corruption issues\n- Various typos\n- Game freezing if low level hero interacts with the slain hero\n\n### Bugfixes for original Hellfire bugs\n\n#### Gameplay\n\n- Mana Shield effectiveness decreasing with spell level\n- Torchant and Hellbat damage range being ignored\n- Monsters dying multiple times from Reflect + Thorn\n- Monk's staff did not take damage when blocking\n\n#### Graphics / Audio\n\n- Blocked arrows always rotate south\n\n#### Multiplayer\n\n- Main quest items disappearing\n- Cow quest getting stuck\n- Auric amulet affecting all players\n\n### Known issues\n\n#### Platform\n\n- PS4: The games fail to launch without a default ini, please see https://github.com/diasurgical/devilutionX/issues/4443\n- Clicking an empty hero slot will crash the game\n- Xbo/s: Missing translation files (download and add [devilutionx.mpq](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/devilutionx.mpq))\n\n## DevilutionX 1.3.0\n\n### Features\n\n#### Platforms\n\n- Added support for [Android](https://play.google.com/store/apps/details?id=org.diasurgical.devilutionx) (please leave us a review 🤗)\n- Added support for the original Nintendo 3DS\n- Added support for Lepus - jz4760/RG300 with multiplayer support\n- Switch: Added TCP/IP multiplayer support\n- Vita: Added TCP/IP multiplayer support\n- OpenDingux: Added TCP/IP multiplayer support\n- 3DS: Added TCP/IP multiplayer support\n- 3DS: Add launcher sound\n\n#### Graphics / Audio\n\n- Animations are now updated at render time for high fps visuals\n- Added support for hardware cursor (solves cursor lag)\n- Quests being ordered logically in the quest panel\n- Quest panel now lists completed quests\n- More fine grained volume slider\n- Added option for pickup sound\n- Shrine reveals map in a different color than your own exploration\n- Automap has drop shadow for better contrast in some levels\n- Added font with support for Extended Latin, Greek, Coptic, Cyrillic, [Chinese, Japanese, and Korean](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq)\n- Item outline color now matches rarity\n- Use gold color to indicate unique items in stores\n- Improved XP bar visuals\n- More widescreen loading scenes\n- Mac: Icon now follow Big Sur style guide\n\n#### Multiplayer\n\n- Added built in support for ZeroTier (no need for port forwarding, no need for an extra application)\n- Added support for unencrypted public games\n- Added auto discovery of public games over ZeroTier\n- Share map exploration (in a different color than your own exploration)\n\n#### Controls\n\n- Press alt to show items on ground with labels\n- Added option for stopping the hero with a key-press\n- Hold click to continue to attack/walk/consume\n- Click ctrl-click to drop an item\n- Click shift-click to swap to the clicked weapon\n- Limit the max width between panels\n- Center align panels\n- Rune bomb and crypt map can be used when standing next to target\n- Added option for disabling crippling shrines\n- Improve inventory filling order\n- Added option to refill belt automatically\n- gamepad: Equip equipment when pressing [use]\n- gamepad: Operate object as last option for primary controller action\n- gamepad: Allow applying oils with secondary action button\n- gamepad: Inventory now takes object size into consideration\n- gamepad: Add joystick dead zone range to ini\n- touch: Add input hint to virtual keyboards\n\n#### Stability / Performance / System\n\n- Add support for translations\n- Run in self-contained (portable) mode if diablo.ini is in the same folder as DevilutionX\n- Chat now supports Unicode, including emojis\n- Several actions can now have their key bindings remapped in the ini\n- Added key bind options for quick save/load\n- Show additional logging with `--verbose`\n- Start directly in Hellfire mode with `--hellfire`\n- Support for MPQs with compressed audio\n- Log errors to the terminal as well\n- Added options to adjust audio quality to ini\n- Update Shareware help text to match retail version\n- Automatically pause and mute the game when put in the background\n- Allow for multiple heroes with the same name\n- Only update diablo.ini if there are changes\n- Windows: Auto detect location of MPQ files from GOG installation\n\n#### Translations\n\n- Added Brazilian Portuguese\n- Added Bulgarian\n- Added Czech\n- Added French\n- Added German\n- Added Italian\n- Added Korean (requires the [additional fonts](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq))\n- Added Polish ([optional dub](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq) by professional voice actors)\n- Added Russian\n- Added Simplified Chinese (requires the [additional fonts](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq))\n- Added Spanish\n- Added Traditional Chinese (requires the [additional fonts](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq))\n\n### Bugfixes\n\n#### Gameplay\n\n- Fix small rooms missing from some levels\n- Golem's to-hit being incorrect after loading a save game\n- Diablo: Correct spells mana cost for the Sorcerer\n- Diablo: Armor piercing was 2x of what it should be\n- Diablo: Barbarian missing his armor piercing bonus\n- Hellfire: Elemental spell was missing\n- Hellfire: Firering spell not creating the correct shape\n\n#### Platforms\n\n- Switch: No longer reacts to touch events\n\n#### Graphics / Audio\n\n- Corrected directional sounds for distant sources\n- Fix sound cut off when exiting game or starting the intro video\n- Entirely new audio mixer to solve audio issues and lower memory usage\n- Fixed rendering issues on 8bit outputs\n- Hellfire: Clearly indicate if it's in shareware mode\n\n#### Multiplayer\n\n- Reverted melee damage, when friendly fire and friendly mode is on\n- Do not show XP bar when chat is open\n- Do not show unbound status in place of game name\n- Show host version when incompatible\n\n#### Controls\n\n- Gamepad: Prevent wasting stat points on maxed out stats\n- Gamepad: Do not reset cursor position when switching between mouse and gamepad\n- Gamepad: Unable to open crypt and hive\n- Gamepad: Close cathedral map when pressing B-button\n- Touch: Open virtual keyboard when text input is needed\n\n#### Stability / Performance / System\n\n- Correctly reset game state if not saved\n- Compatibility with shareware save games\n- Correctly handle folders with non English symbols in them\n- Free network connection after ending game\n- Never require write mode for MPQ files\n- Allow for comments in ini file\n- Load assets from a folder called `assets` next to the application if not found in data paths\n- Added listfile to our MPQs\n- Add ini option for showing FPS\n- Fix name filtering\n- Correct minor memory leaks\n- Further reduced memory usage\n- Performance improvements\n- Windows: Only show network errors once\n\n### Bugfixes for original Diablo bugs\n\n#### Gameplay\n\n- Player becoming immune to stun while using manashield at low health\n- Monsters and players are no-longer immune to missiles when moving horizontally\n- Fix missiles hitting multiple times\n- Fix missiles sometimes skipping hit checks when passing a target\n- Fix charging monsters disappearing from the game if changing levels while they were charging\n- Fix negative AC bonus resulting in +1 AC\n- Do not attack dead monsters\n- Show more accurate `To hit` value in char panel\n- Wake up minions when their leader wakes up\n- Disallow swapping gear while not standing/walking to avoid animation lock\n- Switching of spells during casting changing the cost of the cast\n- Not being able to pick up items after starting a new game for a short amount of time\n- Persist shop inventory shop items when saving and loading\n- Diablo's chamber opening with one lever after level loading\n- Thaumaturgic shrine not restocking trapped chests\n- Scavengers/Gravedigger were only able to search for corpses south of them\n- Scavenger leaders getting stuck if minions started eating\n- Quest monsters level being increased twice\n- Fix gold piles with 0 gold from incorrect treasure room generation\n- Avoid using temporary missiles for game state tracking\n- Object interactions stacking while other actions are being performed\n- Quest items sometimes not being picked up when clicked\n- Teleport spell failing for some valid positions\n- Phasing spell sometime failing or sending you outside the level\n- Phasing not working in Lazarus' chamber\n- Too many monster slots being allocated for golems on levels with quests\n- Golems spawning on top of the player\n- Fix Zhar's bookcase resetting a golem instead of Zhar\n- Zhar saying his line twice in a game\n- Fix stairs up to level 8 sometimes taking the player to town instead\n- Fix random tiles being explored on automap\n- Fixed various typos\n\n#### Graphics / Audio\n\n- Monster light not updating when monster teleports\n- Correctly shorten item names depending on visual length\n- Missing dirt corners on map\n- Wobbling map indicator when walking\n- Fix screen position jumping after loading some saves\n- Some lava still animated despite game pause\n- Fully close the dialog screen when pausing game\n- Changed player saying \"Not enough mana\" to a more fitting message when using a level 0 spell\n- Draw belt item number for unusable scrolls\n\n#### Multiplayer\n\n- Correct desync caused by incorrect vision range for other players\n- Sync monster active state\n- Player attack speed being out of sync\n- Desync when switching items without sufficient inventory space\n- Compensate for desync cause related to player movement\n- Golem desyncing if owner leaves level\n- Prevent golems from fighting each other\n- Play the correct sound when a player is hit by missiles\n\n#### Controls\n\n- Controls [ + ] stat point buttons sometimes not responding to clicks\n\n#### Stability / Performance / System\n\n- Keyboard layout is now correct when entering chat messages\n- Validate network messages to harden security\n- Fix corrupt save games for levels with large amount of entities\n- Game now remembers the last selected hero\n- Added menu for switching between Hellfire / Diablo\n- Make menu navigation wrapping consistent\n- Corrected multiple crashes and stability issues\n\n### Bugfixes for original Hellfire bugs\n\n#### Gameplay\n\n- Range monsters cannot hit target at melee range\n- Monsters could not see firewalls if covered by lightning wall and vice versa\n- Armor piercing affix on ranged weapons decreasing hit chance instead of increasing it\n- Fix stuttering when running in town\n- Firering spell damage not being based on the caster\n- Firering spell giving XP to the wrong player\n- Solar shrine time was off by 1 hour, and did nothing between 4 and 5 am\n- Reflect spell not working after loading a save game\n- Potion trap was not degrading rejuvenation potion into mana or life\n- Barbarian's skill not correctly updating health points\n\n#### Graphics / Audio\n\n- Fix missing player lights when loading Hive level 3\n- Apply lights to all berserked monsters after loading save game\n- Remove light when killing a berserked monster\n- Blood star becoming invisible when blocked\n- Rotate arrows in the appropriate direction when blocking\n- Candles around the storybook sometimes missing in Crypt\n- Celia now leaves after her quest ends\n- Update Celia and Complete Nut graphics when completing their quests\n- Only play \"Uh uh\" sound the first time you pick up the cathedral map\n- Glass breaking sound sometimes not playing for the potion trap\n\n#### Multiplayer\n\n- Open Crypt from the start\n- Restrict access to Hive and Crypt based on level\n- Reflect spell not being synced\n- Search spell affecting all players\n\n### Known issues\n\n- Switch/3DS: Polish dub produces static sounds\n- OpenDingux: Now requires Beta\n\n## DevilutionX 1.2.1\n\n### Bugfixes\n\n#### Gameplay\n\n- Gharbad not having to go out of vision before progressing his quest\n- Diablo: Items with negative AC morphing in multiplayer\n- Diablo: Griswold and Wirt selling unusually expensive items\n- Diablo: Gold not going directly to inventory\n- Hellfire: Some monsters having lower than intended HP\n- Hellfire: Auric Amulet not taking effect in most scenarios\n\n#### Graphics / Audio\n\n- Windows: Glitchy audio\n\n#### Controls\n\n- Vita: Inability to edit hero name on the creation screen\n\n#### Stability / Performance / System\n\n- Quest panel crashing the game for some quests\n- Windows: Some systems getting a sensor permission error\n- Windows: Stability issues and item morphing in Hellfire\n\n### Bugfixes for original Hellfire bugs\n\n#### Gameplay\n\n- Rage/Search/Lightningwall not factoring in the hero level for the first player\n- Sparkling Shrine dealing an incorrect amount of damage\n- Items with negative AC morphing in multiplayer\n\n## DevilutionX 1.2.0\n\n### Features\n\n#### Gameplay\n\n- Hellfire support\n- Shareware support\n- Fully migrate saves between Diablo and Hellfire\n- Gold picked goes to stack even when inventory is open\n- Pepin automatically heals\n- Show other players on the map\n- Preserve list position when buying and selling items in stores\n- Preserve hotkeys and active spell across games\n- Set default active spell for new heroes\n- Experience bar (off by default)\n- Monster health bar (off by default)\n- Auto equip all item types on pickup or purchase (off by default)\n- Auto pickup gold (off by default)\n- Run in town (off by default) (also in multiplayer)\n- Disable friendly fire from arrows an spells (off by default)\n- Disable quest randomization (off by default)\n- Adria refills mana (off by default)\n- Barbarian and Bard heroes in Diablo (off by default)\n\n#### Controls\n\n- Use belt via the numpad\n- Close panels when pressing <kbd>ESC</kbd>\n- <kbd>Shift-click</kbd> to spend all stat points\n- <kbd>Shift-click</kbd> to clear readied spell\n- <kbd>Shift-click</kbd> consumables to move them between the belt and inventory\n- <kbd>Shift-click</kbd> equipment equip/unequip them\n- Controller mapping\n- <kbd>D-Pad</kbd> / Left stick navigation now works in all menus and is more responsive.\n- <kbd>START</kbd> + <kbd>SELECT</kbd> now opens the main menu.\n- Right stick mouse emulation has been improved.\n- Gamepads plugged in while the game is running can be used.\n- All connected gamepads can be used (previously, only the first one).\n\n#### Graphics / Audio\n\n- Widescreen menus\n- Scroll subtitles at the same speed as narration reader\n- Apply sound volume to videos\n- Improved transparency (on by default)\n- Auto-equip sounds (off by default)\n- Show monster type (off by default)\n- Disable walking sounds (off by default)\n\n#### Stability / Performance / System\n\n- Document [ini-file options](https://github.com/diasurgical/devilutionX/wiki/DevilutionX-diablo.ini-configuration-guide)\n- Reorganize ini-file\n- Allow for up to 99 save games of each type\n- Much lower memory usage (now in line with the original)\n- Configurable network port\n- Performance improvements\n- DIABDAT.MPQ may now be upper case\n- Support for portable installs\n- Support file paths longer than 259 characters\n- Add `--ttf-dir` and `--ttf-name` to allow for specifying a different UI font\n- Switch Windows releases to 64-bit\n- Added support for Nintendo 3DS\n- Added support for PlayStation Vita\n- Added support for DragonFly BSD\n- Added AppImage for Linux\n\n### Bugfixes\n\n#### Gameplay\n\n- Catacombs doors never having traps\n\n#### Graphics / Audio\n\n- Incorrect graphics under cave doors in multiplayer\n- Minor color issues in some videos\n- Command-line output missing on Windows\n- Correct visuals and function of the joining-game-dialog\n\n#### Controls\n\n- Mouse jumping to the top of the windows when using the menu\n- Mouse not releasing when exiting the window\n- Dragging on touch devices\n\n#### Stability / Performance / System\n\n- Multiplayer host crashing after beating the game\n\n### Bugfixes for original Diablo bugs\n\n#### Gameplay\n\n- Base damage not being updated when leveling up\n- Player vision radius not updating properly before changing level\n- Tiles not properly being marked as out of visibility when walking\n- Scavengers/Gravediggers taking damage when eating on higher difficulties\n- Flash only dealing 10% damage in some directions\n- Not getting XP for the first monster placed on a level\n- Not getting XP from monsters hit by golems\n- Monsters going inactive when fighting golems offscreen\n- Monsters with hiding ability fleeing in the wrong direction from golems\n- Fallen fleeing in the wrong direction\n- Monsters charge directions being biased for some angles\n- Monsters not being able to properly judge the location of firewalls\n- Some unique items morphing on a new game\n- Incorrectly seeing legit items as duplicates\n- Items being destroyed if held in cursor when entering dungeon\n- Being able to waste gold on red scrolls when not having room for them\n- Gaining mana from reading books despite wearing an item with corruption\n- Gold piles will be filled to their max, before starting a new one\n- Inconsistent repair prices caused by rounding errors\n- Arkaine's Valor brought from previous games breaking the game state\n- Several issues causing Arkaine's Valor to enter a broken state\n- Black Mushroom quest not resetting between games\n- Randomly being teleported from level 15 to Lazarus' chamber\n- Several bugs in Lazarus quest when re-entering the teleport\n- Town portals appearing on two levels when cast in a quest level\n\n#### Controls\n\n- Inconsistent mouse behavior when opening/closing various panels\n\n#### Graphics / Audio\n\n- Gold icons graphics are always correct\n- Arrows graphics not aligning with the move direction\n- Wrong death sound when monster/golem kills another monster\n- Lights not always following unique monsters\n- Lights added on map update not working (Arkaine's Valor, etc.)\n- Player light radius not readjusting when a player is knocked back\n- Loadscreen colors on entering the Poison Water quest\n- Lava pools sometimes having roof tiles in them\n- Doors sometimes missing in Halls of The Blind\n- Broken outline on some inventory items\n\n#### Stability / Performance / System\n\n- Fix more stability issues\n\n#### Bugfixes from Hellfire 1.00 - 1.01\n\n- Monster hitpoints overflowing in Nightmare/Hell difficulty\n- Gharbad the Weak not dropping his item when killed by a golem\n- Some stability issues\n\n### Bugfixes for original Hellfire bugs\n\n#### Gameplay\n\n- Firewall damage calculation being too low\n- Firewall/Lightningwall damage being based on the dungeon level instead of spell level for the first player\n- Right-hand item's decay suffix being applied to the left-hand item in multiplayer\n- Town Shrine would always cast TP from the first player instead of the user\n- Oily Shrine and Sparkling Shrine would cast their traps as if the first player was doing it\n- The farmer would always think he was talking to the local player\n- Scavenger/Gravedigger AI being stuck for a round after eating\n- Sync available quests in multiplayer\n- Correct spell level being ignored for Search and Rage\n\n#### Graphics / Audio\n\n- Monster attack sound sometimes not playing\n- Missing sounds when bards and barbarians talk to cows\n- \"0 Gold\" sometimes spawning on The Cornerstone\n- Minor typography corrections\n\n#### Bugfixes from Diablo 1.03 - 1.09\n\n- The Hidden Shrine freezes when not holding an applicable item\n- Memory corruption when casting town portal\n- Crashes associated with Black Death\n- Players getting stuck in a wall when using Town Portals\n- Some Hell difficulty monsters being too easy to hit\n- Mana Shield bugs that could make a player invulnerable and/or invisible\n- Disarming skill not working on levels 13 through 15\n- Mana Shield permanently using up level missiles\n- Corrected behaviour of Thieves, Speed/Haste, Balance/Stability/Harmony, and Piercing/Bashing/Puncturing\n- Mana Shield becoming less effective with increasing spell level\n- Excessive damage when a Mana Shield expired due to an attack\n- Bows with fire damage prevented the Gargoyles from healing\n- Right-clicking belt item 5-8 not working while the Spellbook is open\n- Mana Shield and Nova not appearing for other players\n- Shields disappearing when worn after wielding two-handed weapons\n- Adria's books appear white even when the player can't read them\n- Equipped shields not appear properly to other players\n- Monster health not appearing correctly on Nightmare and Hell difficulty\n- Diablo's scream being muted if you load a save game during his death throes\n- Multiplayer character files are now located in the data directory, and may be moved between computers\n- Some stability issues\n\n### Known issues\n\n- Save game difficulty does not carry over from 1.1.0\n- Amiga builds are currently unstable\n\n## DevilutionX 1.1.0\n\n### Features\n\n- Proper widescreen (and other aspects) support\n- Select difficulty in single player (remembered in the save game)\n- Adjustable game speed in-game\n- V-sync can now be disabled in the ini\n- Better line drawing function used for the automap\n- Support for loading custom Hell level maps\n- Make all objects and monsters available to custom maps\n- Added support for joining a game via hostname instead of IP\n\n### Bugfixes\n\n- You can now enter and exit fullscreen also when the game is paused\n- [Amiga] Fix double-clicking in menu\n\n### Original Diablo bugs\n\n- Fix some monsters AC and to-hit values on Nightmare/Hell ending up as 0\n- Fix player base block resetting to 0 after loading a save game\n- Correctly render trees in front of the player\n- Fully render sprites that are larger than the floor tiles\n- Fix objects disappearing when walking on the opposite wall\n- Duping via belt has been fixed\n- Correctly detect if the mouse is clicking the world or UI in some areas\n- Minor typography corrections\n- Corrected name of Chamber of Bone in automap\n- Correctly align the inventory slots\n\n## DevilutionX 1.0.3\n\n### Bugfixes\n\n- Fix keyboard input in the menu\n\n## DevilutionX 1.0.2\n\n### Features\n\n- Support for integer scaling\n- Controller: Map Start + L1/R1 to char/inventory\n- Added `--save-dir` to allow for specifying the save game folder\n- Correctly scale the game on systems with a non-standard DPI setting\n\n### Bugfixes\n\n- Some cave levels were generated with an incorrect layout\n- Firebolt mana cost is now correct\n- Allow players to join Nightmare/Hell games without first creating a game\n- Correctly load the full white color\n- Correct navigation in the difficulty select screen\n- The window can now be resized after exiting fullscreen mode\n- Fix memory leak in audio code\n- Fix hanging for 20 sec on the error screen\n\n## DevilutionX 1.0.1\n\n### Features\n\n- Toggle fullscreen at any point by hitting alt+enter (mouse grab can be disabled in diablo.ini)\n- Controller: B button closes the currently active panel.\n- Added a navigation menu for controllers\n- Focus on the exit item before quitting.\n- Minor performance improvements (save/load time and main menu).\n- Add a list of [known mods](https://github.com/diasurgical/devilutionX/blob/master/docs/mods.md)\n\n### Platforms\n\n- Added support for 32bit PowerPc\n- Added support for Amiga\n- Added support Clockwork PI GameShell\n- Added support for GKD350h\n- Switch to OPK for RetroFW (requires 2.0)\n- Update OpenDingux/RetroFW build root\n\n### Bugfixes\n\n- Game crashing on systems that do not report monitor refresh rate.\n- Fixed belt not working correctly when holding shift on us keyboard layouts\n- Always keep track of the latest hero level when selecting difficulty.\n- Correct screenshot path\n- Turn the screen red for 200ms when taking screenshots.\n- Fix town load screen missing on the first load.\n- Fix minor HOM issue at some houses in town.\n- Allow for space as text input\n- Fixed a couple of typos in error messages\n\n### Original Diablo bugs\n\n- Fix belt not working correctly when holding shift on *non-*us keyboard layouts\n- Fix one more rare crash.\n\n## DevilutionX 1.0.0\n\n### Features\n\n- FPS no longer capped at 20hz; smoother mouse and transitions\n- Full-featured gamepad support\n- All movies can now be skipped via ESC\n- Implement `--help`, `--version` and `--data-dir`\n- Implement FPS counter (`-f`)\n- Force windowed mode with `-x`\n- Skip startup movies with `-n`\n- Implement scroll wheel navigation\n- Implement touch support\n- Load assets from the same folder as the mpq\n- Faster loading\n\n### Platforms\n\n- Added Nintendo Switch support\n- Added Retro Gamer Handheld (OpenDingux/Retrofw) support\n- Added OpenBSD support\n- Windows version is now build as GUI an app and has an icon\n\n### Bugfixes\n\n- Fixed random missing sounds\n- Fixed NPCs not talking about the right quest\n- Error messages implemented in GUI\n- Fixed having to restart the game between network sessions\n- Fixed game not working on some Radeon GPUs\n- Fixed panel missing after minimizing game if upscaling is disabled\n- Fixed clicks in the left letterbox being incorrectly handled\n- Fixed end movie not looping\n\n### Original Diablo bugs\n\n- Fixed a large number of rare stability issues from the original game\n- Correctly take open panels into account when casting spells\n- Fix sound some times being muted after Diablo dies\n\n## DevilutionX 0.5.0\n\n### Features\n\n- Sound is now accurate to the original\n- All in-game issues fixed\n- Delete hero, inline dialogs and scrollbars are now implemented\n- Screenshots now have different names\n- Multiple simultaneous dialogs fixed\n- All builds are now 64bit (except for Windows and Raspberry Pi)\n- Memory leaks and crashes fixed\n- All keys are now mapped\n- UI text now has correct shadows\n- Much lower CPU usage\n- diabdat.mpq can now be loaded with read-only access\n\n### Known issues\n\n- Error dialogs not implemented in main UI\n- The game must restart after hosting multiplayer\n\n## [0.10.0](https://github.com/diasurgical/devilution/compare/0.9.6...0.10.0)\n\n### June 22, 2019\n\n- [All functions are now binary identical](https://github.com/diasurgical/devilution/milestone/3) to the 1.09b version\n- Fix buying from Wirt\n- Replace many magic numbers with constants\n- Fix a handful of minor issues\n- Add toggle fullscreen with alt+enter in debug builds\n\n### June 21, 2019\n\n- All functions are now [binary identical](https://github.com/diasurgical/devilution/milestone/3) to Diablo 1.09b\n\n### June 1, 2019\n\n- MVG posts [a video about the project](https://www.youtube.com/watch?v=5tADL_fmsHQ) and releases a Nintendo Switch port\n\n## DevilutionX 0.4.0\n\n### May 20, 2019\n\n- Fixed flickering mouse in caves\n- 32bit ARM build (Raspberry Pi)\n- 32bit FreeBSD build\n- 32bit Haiku support (see HaikuDepot)\n- Included font for rendering credits and progress screen\n- Upscaling quality can be adjusted or fully disabled in diablo.ini\n- Windowed mode can be set in diablo.ini\n- Mouse capture can be set in diablo.ini\n- Direct file access implemented (mods won't need to pack their files in an MPQ)\n- Music and speech memory leaks fixed\n\n## [0.9.6](https://github.com/diasurgical/devilution/compare/0.9.0...0.9.6)\n\n### May 19, 2019\n\n- [96% of functions are now binary identical](https://github.com/diasurgical/devilution/milestone/3) to the 1.09b version\n- Fix several item corruption issues introduced in 0.9.0\n\n## [0.9.0](https://github.com/diasurgical/devilution/compare/0.8.0...0.9.0)\n\n### May 2, 2019\n\n- [90% of functions are now binary identical](https://github.com/diasurgical/devilution/milestone/3) to the 1.09b version\n- Mute buttons now work correctly\n\n### April 15, 2019\n\n- Code is once again compiled as C++ as some parts appear to require despite the indications in Rich header\n\n## [0.8.0](https://github.com/diasurgical/devilution/compare/0.7.0...0.8.0)\n\n### April 12, 2019\n\n- [80% of functions are now binary identical](https://github.com/diasurgical/devilution/milestone/3) to the 1.09b version\n- Fixes a few minor issues with generated items\n\n## [0.7.0](https://github.com/diasurgical/devilution/compare/0.6.0...0.7.0)\n\n### April 9, 2019\n\n- [70% of functions are now binary identical](https://github.com/diasurgical/devilution/milestone/3) to the 1.09b version\n\n### April 9, 2019\n\n- The last of the compiler flags are figured out\n\n### March 22, 2019\n\n- Devilution appears on [Phoronix](https://www.phoronix.com/scan.php?page=news_item&px=DeviluitionX-Open-Diablo)\n\n## DevilutionX 0.3.0\n\n### March 20, 2019\n\n- Fix dialog volume\n- 32bit macOS build\n- Fix crash in town during multiplayer\n- Screenshot implemented\n\n## [0.6.0](https://github.com/diasurgical/devilution/compare/v0.5.0...0.6.0)\n\n### March 19, 2019\n\n- [60% of functions are now binary identical](https://github.com/diasurgical/devilution/milestone/3) to the 1.09b version\n- Added a guide for people wanting to join in [Cleaning the code](https://github.com/diasurgical/devilution/wiki/Cleaning-Code)\n- File size is now only 968 bytes (0.13%) larger than the original Diablo 1.09b.\n\n## DevilutionX 0.2.0\n\n### March 17, 2019\n\n- Fully implemented audio (all issues from 0.1.0 fixed)\n- Fully implemented multiplayer\n- Windows 32bit build\n- Gameplay is fully featured and plays like the original\n- Memory leaks fixed\n- Most known crashes have been fixed\n\n### March 7, 2019\n\n- [GOG re-release Diablo](https://www.gog.com/news/release_diablo)\n\n## DevilutionX 0.1.0\n\n### February 27, 2019\n\n- Linux 32bit build\n- Basic audio\n- Video playback\n- Basic menus\n- Graphics\n- Gameplay\n- Basic multiplayer over TCP/UDP\n- Persistent settings\n- Encrypted network connection with password protection\n\n## [0.5.0](https://github.com/diasurgical/devilution/compare/0.4...v0.5.0)\n\n### January 14, 2019\n\n- [50% of functions are now binary identical](https://github.com/diasurgical/devilution/milestone/3) to the 1.09b version\n- [#456](https://github.com/diasurgical/devilution/pull/456) Assets can now be loaded directly from disk (no need for MPQ-files when modding)\n- [#528](https://github.com/diasurgical/devilution/pull/528) Code ported to C (can still be compiled as C++)\n- [#111](https://github.com/diasurgical/devilution/pull/111) Rich Header no longer contains incorrect sections\n- [#182](https://github.com/diasurgical/devilution/pull/182) defined a [Code Style](https://github.com/diasurgical/devilution/wiki/Code-style-guide) with accompanying clang-format definition\n- `Diabloui.dll` is now also part of the source tree\n- Added [Contribution Guide](https://github.com/diasurgical/devilution/blob/master/docs/CONTRIBUTING.md)\n- Added PDB build option for comparing with [devilution-comparer](https://github.com/diasurgical/devilution-comparer)\n- CI now runs the original build chain\n- Most magic numbers are now replaced by enums\n- The code was reduced by 10,000 lines\n- Fix a few issues, mostly relating to multiplayer\n\n### November 17, 2018\n\n- An older and more original PSX symbol file is discovered\n\n### October 1, 2018\n\n- Compiler version is confirmed to be correct by discovery of the [Rich header](https://bytepointer.com/articles/the_microsoft_rich_header.htm)\n\n### September 18, 2018\n\n- Merge nightly back into devilution\n\n### September 3, 2018\n\n- Travis is configured to report the overall project delta to 1.09b on every change\n\n### September 1, 2018\n\n- Devilution-comparer is developed for comparing binary diff in compiled functions\n\n### August 28, 2018\n\n- The correct compiler combination is found by trial and error plus a bit of luck\n\n## [0.4.0](https://github.com/diasurgical/devilution/compare/0.3...0.4)\n\n### September 16, 2018\n\n- Fix crash\n- Get the first functions bin exact\n- Fix render issues\n- Introduce debug functions from the 1.00 debug release\n- Fix missiles\n- More consts, sizeof and defines\n- Fix several issues with dungeon generation code\n- Fix multiplayer\n- Fix error messages\n- Correct names based on PSX symbols and DX SDK\n\n### August 20, 2018\n\n- Created nightly fork where code clean up can take place until major bugs are fixed in the main project\n\n### July 6, 2018\n\n- Setup a Discord channel\n\n### July 1, 2018\n\n- Diablo 1.09b is determined to have been compiled with the /O1 flag\n\n## [0.3.0](https://github.com/diasurgical/devilution/compare/0.1.0...0.3)\n\n### June 28, 2018\n\n- Windows binary can now be compiled under Linux and Mac OS X\n- Windows binary can now be compiled under VS 5.10\n- Fix multiple crashes\n- Remove cheesy copyright notice\n- Set up continuous building via Travis and AppVeyor\n- Icon added\n- Fix Zhar quest, monster squelching and golems\n- Use consts for various values\n\n### June 20, 2018\n\n- The [media](https://www.pcgamer.com/a-coder-spent-1200-hours-reverse-engineering-diablos-source-code/) catches wind and [several](https://bloody-disgusting.com/video-games/3505673/fan-completes-reverse-engineering-source-code-diablo/) [articles](https://kotaku.com/coder-spends-1-200-hours-piecing-together-diablos-sourc-1827001247) [appear](https://www.diabloii.net/blog/comments/reverse-engineered-diablo-source-code-released)\n\n### June 18, 2018\n\n- Devilution gets posted on [Y Combinator](https://news.ycombinator.com/item?id=17338886)\n\n## 0.1.0\n\n### June 6, 2018\n\n- Devilution is unleashed upon the world! Version 0.1.0!\n\n### June 3, 2018\n\n- Polishing things up for final release\n- Added a cheesy fake copyright notice to dissuade monetary gain\n- Properly integrated Storm and DiabloUI into the project\n\n### May 28, 2018\n\n- Fixed bugs with save files\n- You can now load Devilution saves in the vanilla game\n\n### May 25, 2018\n\n- Finally! Figured it out and now monsters spawn correctly\n- The game can be completed from start to finish with a few tricks\n\n### May 21, 2018\n\n- Took a week break, begin working on monster code again\n- Nearly all quests work now\n- Fixed a bug with Adria\n\n### May 8, 2018\n\n- Fix bugs with character drawing\n- Fix bugs relating to item affix generation\n- Towners no longer crash the game\n\n### May 7, 2018\n\n- Port debugging functions from the debug release\n- Still can't figure out the zombie problem\n\n### May 5, 2018\n\n- Begin fixing quest code and testing completion\n\n### April 26, 2018\n\n- Zombies are spawning in all dungeon types... sigh\n\n### April 20, 2018\n\n- Split code from IDA's C file into separate CPP files\n- All dungeon types can now be entered\n- Objects are now mostly working\n- Begin uncommenting monster code and fixing them\n\n### April 11, 2018\n\n- Begin fixing up dungeon generation and objects\n\n### April 4, 2018\n\n- Fixed many crashing bugs when in town and dungeon\n- Items, missiles, and spells are now drawn\n\n### April 1, 2018\n\n- Finally fixed the render bug, everything draws correctly!\n- Character animation now draws correctly\n- The cathedral is now mostly working\n\n### March 29, 2018\n\n- Fixed tons of bugs\n- You can now walk around in town\n- Entering the dungeon almost always crashes\n\n### March 27, 2018\n\n- Uncommented and fixed lots of broken code\n- The game screen now appears, although very glitchy\n\n### March 22, 2018\n\n- Control panel and inventory now work almost flawlessly\n\n### March 21, 2018\n\n- Temporarily commented out tons of broken code\n- You can now get past the loading screen and into town\n- Music also works\n- Control panel mostly works but game screen is black\n\n### March 18, 2018\n\n- The title screen now works\n- Freezes during the loading screen\n\n### March 16, 2018\n\n- Fixed enough bugs that you can now launch binary\n- Crashes during title screen\n\n### March 14, 2018\n\n- Fix remaining errors in code\n- Code now compiles and produces a non-working binary\n\n### March 13, 2018 -- *!  SPECIAL DAY  !*\n\n- Dump the database to C code via IDA\n\n### March 8, 2018\n\n- Correct various function signatures\n- Correct struct names and types\n- Plug in enumerates\n- Finish correcting and documenting data sections\n\n### February 26, 2018\n\n- Finish documenting functions\n- Begin correcting names to match PSX\n\n### February 18, 2018\n\n- Begin adding enumerates\n- Add more minor structs\n- Clean up data sections\n\n### February 15, 2018\n\n- Almost finished adding every function\n- Begin working on major structs\n\n### February 8, 2018\n\n- Add more functions\n- Begin adding data from Sanctuary project\n\n### February 4, 2018\n\n- IDA disassembly begin\n- Start adding function names from [Sanctuary project](https://github.com/sanctuary/notes)\n\n### January 15, 2018\n\n- The concept of Devilution is born\n- Research into Diablo's code and mechanics\n- Research from [Jarulf's guide](http://www.bigd-online.com/JG/JGFrame.html)\n"
  },
  {
    "path": "docs/CONTRIBUTING.md",
    "content": "# DevilutionX Contribution Guide\nWelcome! Please review our [Contribution Guide](https://github.com/diasurgical/DevilutionX/wiki/Contributing) for more information!\n\n_“A project is only as strong as its contributors. Thank you for helping us keep Diablo 1 alive and better than ever!”_\n"
  },
  {
    "path": "docs/TODO.md",
    "content": "### Comments\n\n- `BUGFIX` known bugs in original (vanilla) code\n- `/* */` block comments are things to be fixed/checked\n- `FIX_ME` bad data\n\nCode issues (incorrect code that still works)\n\n- Critical sections should be constructors using `CCritSect`\n- Some functions/structures have incorrect signing (signed/unsigned BYTE)\n"
  },
  {
    "path": "docs/benchmarking.md",
    "content": "# Benchmarking\n\nOn Linux, use the `tools/linux_reduced_cpu_variance_run.sh` wrapper\nto [reduce CPU variance](https://google.github.io/benchmark/reducing_variance.html).\n\nTimedemo:\n\n```bash\ntools/linux_reduced_cpu_variance_run.sh tools/measure_timedemo_performance.py -n 5 --binary build-rel/devilutionx\n```\n\nIndividual benchmarks (built when `BUILD_TESTING` is `ON`):\n\n```bash\ntools/build_and_run_benchmark.py clx_render_benchmark\n```\n\nYou can pass arguments to the benchmark binary with `--`, e.g.:\n\n```bash\ntools/build_and_run_benchmark.py clx_render_benchmark -- --benchmark_repetitions=5\n```\n\nThe `tools/build_and_run_benchmark.py` script basically does something like this:\n\n```bash\n{ [ -d build-reld ] || cmake -S. -Bbuild-reld -DCMAKE_BUILD_TYPE=RelWithDebInfo; } && \\\ncmake --build build-reld --target clx_render_benchmark && \\\ntools/linux_reduced_cpu_variance_run.sh build-reld/clx_render_benchmark\n```\n\nSee `tools/build_and_run_benchmark.py --help` for more information.\n\nYou can also [profile](profiling-linux.md) your benchmarks.\n\n\n## Comparing benchmark runs\n\nYou can use [compare.py from Google Benchmark](https://github.com/google/benchmark/blob/main/docs/tools.md) to compare 2 benchmarks.\n\nFirst, install the tool:\n\n```bash\ngit clone git@github.com:google/benchmark.git ~/google-benchmark\ncd ~/google-benchmark/tools\npip3 install -r requirements.txt\ncd -\n```\n\nThen, build the 2 binaries that you'd like to compare. For example:\n\n```bash\nBASELINE=master\nBENCHMARK=dun_render_benchmark\n\ngit checkout \"$BASELINE\"\ntools/build_and_run_benchmark.py -B \"build-reld-${BASELINE}\" --no-run \"$BENCHMARK\"\ngit checkout -\n\ntools/build_and_run_benchmark.py --no-run \"$BENCHMARK\"\n\ntools/linux_reduced_cpu_variance_run.sh ~/google-benchmark/tools/compare.py -a benchmarks \\\n  \"build-reld-${BASELINE}/${BENCHMARK}\" \"build-reld/${BENCHMARK}\" \\\n  --benchmark_repetitions=10\n```\n"
  },
  {
    "path": "docs/building.md",
    "content": "# Building from Source\n\nDevilutionX provides a source package with the release (`devilutionx-src.tar.xz`) that contains\nall the dependencies that must be vendored, the version information, and `devilutionx.mpq`.\nThis is the version most appropriate for packaging DevilutionX for Linux distributions.\nFor other use cases, use the git repository.\n\n<details><summary>Linux</summary>\n\nNote that ```pkg-config``` is an optional dependency for finding libsodium, although we have a fallback if necessary.\n\n### Installing dependencies on Debian and Ubuntu\n\n```\nsudo apt-get install cmake g++ libsdl2-dev libsodium-dev libpng-dev libbz2-dev libgtest-dev libgmock-dev libbenchmark-dev libsdl2-image-dev libfmt-dev\n```\n\n### If you want to build the translations (optional)\n\n```\nsudo apt-get install gettext poedit\n```\n\n### If you want to build the devilutionX.mpq File (optional)\n\n```\nsudo apt-get install smpq\n```\n\n### Installing dependencies on Fedora\n\n```\nsudo dnf install cmake gcc-c++ glibc-devel libstdc++-static SDL2-devel SDL2_image-devel libsodium-devel libpng-devel bzip2-devel gmock-devel gtest-devel google-benchmark-devel libasan libubsan fmt-devel\n```\n\n### Compiling\n\n```bash\ncmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(getconf _NPROCESSORS_ONLN)\n```\n\n### Cross-compiling for arm64 (aarch64) on Debian or Ubuntu\n\nFirst, set up the dependencies for cross-compilation:\n\n```bash\nPackaging/nix/debian-cross-aarch64-prep.sh\n```\n\nThen, build DevilutionX using the cross-compilation CMake toolchain file:\n\n```bash\ncmake -S. -Bbuild-aarch64-rel \\\n  -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/aarch64-linux-gnu.toolchain.cmake \\\n  -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DCPACK=ON \\\n  -DDEVILUTIONX_SYSTEM_LIBFMT=OFF\ncmake --build build-aarch64-rel -j $(getconf _NPROCESSORS_ONLN) --target package\n```\n\n</details>\n\n<details><summary>macOS</summary>\n\nMake sure you have [Homebrew](https://brew.sh/) installed, then run:\n\n```bash\nbrew bundle install\ncmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(sysctl -n hw.physicalcpu)\n```\n\n</details>\n<details><summary>iOS</summary>\n\nMake sure you have [Homebrew](https://brew.sh/) installed, then run:\n\n```bash\nbrew install cmake\ncmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=../CMake/Platforms/ios.toolchain.cmake  -DENABLE_BITCODE=0 -DPLATFORM=OS64\ncmake --build build -j $(sysctl -n hw.physicalcpu) --config Release\ncd build\nrm -rf Payload\nmkdir -p Payload\nmv devilutionx.app Payload\nzip -r devilutionx.ipa Payload\n```\n\nFor testing with the Simulator instead run the following:\n\n```bash\ncmake -S. -Bbuild -G Xcode -DCMAKE_TOOLCHAIN_FILE=../CMake/Platforms/ios.toolchain.cmake -DPLATFORM=SIMULATOR64\n```\n\nThen open the generated Xcode project and run things from there.\n</details>\n<details><summary>FreeBSD</summary>\n\n### Installing dependencies\n\n```\npkg install cmake sdl2 libsodium libpng bzip2 googletest\n```\n\n### Compiling\n\n```bash\ncmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(sysctl -n hw.ncpu)\n```\n\n</details>\n<details><summary>NetBSD</summary>\n\n### Installing dependencies\n\n```\npkgin install cmake SDL2 libsodium libpng bzip2 googletest\n```\n\n### Compiling\n\n```bash\ncmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(sysctl -n hw.ncpu)\n```\n\n</details>\n\n<details><summary>OpenBSD</summary>\n\n### Installing dependencies\n\n```\npkg_add cmake sdl2 libsodium png bzip2 gmake gtest\n```\n\n### Compiling\n\n```bash\ncmake -S. -Bbuild -DCMAKE_MAKE_PROGRAM=gmake -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(sysctl -n hw.ncpuonline)\n```\n\n</details>\n\n<details><summary>Windows via MinGW</summary>\n\n<details><summary>Installing Windows Subsystem for Linux</summary>\n\nNote: We currently recommend using Ubuntu 24.04 for the MinGW build. The following instructions will install the recommended version of Ubuntu on WSL.\n\nIf you are building on Windows and do not have WSL already setup this will install WSL and Ubuntu (Requires Windows 10 2004 or higher or Windows 11)\n\nIn an Administrator Command Prompt or Powershell\n\n```wsl --install -d Ubuntu-24.04```\n\nReboot\n\nWait for Command Prompt to pop up and say installing when complete enter your new Linux password\n\nYou can launch WSL anytime by typing wsl or ubuntu in a Command Prompt or Powershell or in the Start Menu launch the Ubuntu App\n\n### Setup git and clone DevilutionX\n\nIn a WSL terminal run these commands to get the source code for DevilutionX\n\n```\nsudo apt-get install git\ngit clone https://github.com/diasurgical/devilutionx\ncd devilutionx\n```\n\n</details>\n\n### Installing dependencies on WSL, Debian and Ubuntu\n\n#### MinGW build tools\n\n```bash\n# Install MinGW build tools\nsudo apt-get update\nsudo apt-get install cmake git libz-mingw-w64-dev mingw-w64 mingw-w64-tools smpq wget\n```\n\n<details><summary>MinGW 32-bit</summary>\n\nThe 32-bit build depends on the 32-bit MinGW Development Libraries for [SDL2](https://www.libsdl.org/download-2.0.php) and [libsodium](https://github.com/jedisct1/libsodium/releases) as well as headers for [zlib](https://zlib.net/zlib-1.2.12.tar.gz). These dependencies will need to be placed in the appropriate subfolders under `/usr/i686-w64-mingw32`.\n\nWhen linking zlib, libpng will always prefer dynamically linking with `libz.dll.a` if it can be found. We recommend renaming or deleting `libz.dll.a` to force libpng to use static linkage. This will prevent errors about missing dlls when you attempt to run the game.\n\nThese can be done automatically by running [`Packaging/windows/mingw-prep.sh`](/Packaging/windows/mingw-prep.sh).\n\nNote: If your `i686-w64-mingw32` directory is not in `/usr` (e.g. when on\nDebian), the mingw-prep scripts and the CMake command won't work. You need\nadjust the mingw-prep scripts and pass `-DCROSS_PREFIX=/path` to CMake to set\nthe path to the parent of the `i686-w64-mingw32` directory.\n\n```bash\n# Download the 32-bit development libraries for SDL2 and libsodium\n# as well as the headers for zlib and place them in subfolders under\n# /usr/i686-w64-mingw32\nPackaging/windows/mingw-prep.sh\n```\n\n### Compiling\n\nBy compiling the `package` target, the build will produce the `devilutionx.zip` archive which should contain all the dlls necessary to run the game. If you encounter any errors suggesting a dll is missing, try extracting the dlls from the zip archive.\n\n```bash\n# Configure the project to disable unit tests,\n# statically link bzip2 and libsodium,\n# and enable Discord integration\ncmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/mingwcc.toolchain.cmake \\\n    -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DDEVILUTIONX_SYSTEM_BZIP2=OFF \\\n    -DDEVILUTIONX_STATIC_LIBSODIUM=ON -DDISCORD_INTEGRATION=ON\n\n# Build the \"package\" target which produces devilutionx.zip\n# containing all the necessary dlls to run the game\ncmake --build build -j $(getconf _NPROCESSORS_ONLN) --target package\n```\n\n</details>\n\n<details open><summary>MinGW 64-bit</summary>\n\nThe 64-bit build depends on the 64-bit MinGW Development Libraries of [SDL2](https://www.libsdl.org/download-2.0.php) and [libsodium](https://github.com/jedisct1/libsodium/releases) as well as headers for [zlib](https://zlib.net/zlib-1.2.12.tar.gz). These dependencies will need to be placed in the appropriate subfolders under `/usr/x86_64-w64-mingw32`.\n\nWhen linking zlib, libpng will always prefer dynamically linking with `libz.dll.a` if it can be found. We recommend renaming or deleting `libz.dll.a` to force libpng to use static linkage. This will prevent errors about missing dlls when you attempt to run the game.\n\nThese can be done automatically by running [`Packaging/windows/mingw-prep64.sh`](/Packaging/windows/mingw-prep64.sh).\n\nNote: If your `x86_64-w64-mingw32` directory is not in `/usr` (e.g. when\non Debian), the mingw-prep scripts and the CMake command won't work. You need\nadjust the mingw-prep scripts and pass `-DCROSS_PREFIX=/path` to CMake to set\nthe path to the parent of the `x86_64-w64-mingw32` directory.\n\n```bash\n# Download the 64-bit development libraries for SDL2 and libsodium\n# as well as the headers for zlib and place them in subfolders under\n# /usr/x86_64-w64-mingw32\nPackaging/windows/mingw-prep64.sh\n```\n\n### Compiling\n\n```bash\n# Configure the project to disable unit tests,\n# statically link bzip2 and libsodium,\n# and enable Discord integration\ncmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/mingwcc64.toolchain.cmake \\\n    -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DDEVILUTIONX_SYSTEM_BZIP2=OFF \\\n    -DDEVILUTIONX_STATIC_LIBSODIUM=ON -DDISCORD_INTEGRATION=ON\n\n# Build the \"package\" target which produces devilutionx.zip\n# containing all the necessary dlls to run the game\ncmake --build build -j $(getconf _NPROCESSORS_ONLN) --target package\n```\n\n</details>\n\n</details>\n\n<details><summary>Windows via Visual Studio</summary>\n\n### Installing dependencies\n\nMake sure to install the workload `Desktop development with C++` and the individual components `C++ CMake tools for Windows` and `Windows SDK` for Visual Studio.\n*Note: `Windows SDK` component should match your Windows build version.*\n\nInstall [Git for Windows](https://gitforwindows.org/)\n\nRun the following commands in Command Prompt or Powershell\n\n~~~ bat\ngit clone https://github.com/microsoft/vcpkg\ncd vcpkg\nbootstrap-vcpkg.bat\nvcpkg integrate install\n~~~\n\nIf you need additional instructions for vcpkg you can find the documentation [here](https://github.com/microsoft/vcpkg#quick-start-windows).\n\n### If you want to build the devilutionX.mpq File (optional)\n\nIn order to build devilutionx.mpq, install smpq from https://launchpad.net/smpq/trunk/1.7/+download/SMPQ-1.7-x86_64.exe.\nThe location of this tool will need to be [added to the system's PATH environment variable](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/).\n\n### Compiling\n\n* **Through Open->CMake in Visual Studio**\n\n1. Go to `File -> Open -> CMake`, select `CMakeLists.txt` from the project root.\n2. Select the `x64-Release` configuration (or `x86` for 32 bit builds, `-Debug` for debug builds).\n3. Select `Build devilution.exe` from the `Build` menu.\n\n* **Through GCC/WSL in Visual Studio**\n\n1. Ensure the WSL environment has the build pre-requisites for both devilutionX (see \"Installing Dependencies on Debian and Ubuntu\" under the \"Linux\" section above) and [WSL remote development](https://docs.microsoft.com/en-us/cpp/linux/connect-to-your-remote-linux-computer?view=msvc-160#connect-to-wsl).\n2. Select the `WSL-GCC-x64-Debug` configuration.\n3. Select `Build devilution` from the `Build` menu.\n\n* **Through cmake-gui**\n\n1. Input the path to devilutionx source directory at `Where is the source code:` field.\n2. Input the path where the binaries would be placed at `Where to build the binaries:` field. If you want to place them inside source directory it's preferable to do so inside directory called `build` to avoid the binaries being added to the source tree.\n3. It's recommended to input `Win32` in `Optional Platform for Generator`, otherwise it will default to x64 build.\n4. In case you're using `vcpkg` select `Specify toolchain file for cross-compiling` and select the file `scripts/buildsystems/vcpkg.cmake` from `vcpkg` directory otherwise just go with `Use default native compilers`.\n5. In case you need to select any paths to dependencies manually do this right in cmake-gui window.\n6. Press `Generate` and open produced `.sln` file using Visual Studio.\n7. Use build/debug etc. commands inside Visual Studio Solution like with any normal Visual Studio project.\n\n</details>\n\n<details><summary>Android</summary>\n\n### Installing dependencies\n\nInstall [Android Studio](https://developer.android.com/studio)\nAfter first launch configuration, go to \"Configure -> SDK Manager -> SDK Tools\".\nSelect \"NDK (Side by side)\" and \"CMake\" checkboxes and click \"OK\".\n\n### Compiling\n\nClick \"Open Existing Project\" and choose \"android-project\" folder in DevilutionX root folder.\nWait until Gradle sync is completed.\nIn Android Studio, go to \"Build -> Make Project\" or use the shortcut Ctrl+F9\nYou can find the compiled APK in `/android-project/app/build/outputs/apk/`\n</details>\n\n<details><summary>Nintendo Switch</summary>\n\n### Installing dependencies\n\nhttps://devkitpro.org/wiki/Getting_Started\n\n- Install (dkp-)pacman: https://devkitpro.org/wiki/devkitPro_pacman\n\n- Install required packages with (dkp-)pacman:\n\n```\nsudo (dkp-)pacman -S --needed - < Packaging/switch/packages.txt\n```\n\n- Install smpq (if building from git or a source archive without devilutionx.mpq)\n  DevilutionX requires some core assets to render UI elements and fonts even if game data is not available. While some\n  platforms can load this from the filesystem as loose files the switch build currently only supports bundling the mpq\n  archive inside the nro. If you're building DevilutionX on a supported platform a prebuilt binary may be available from\n  your package distribution system (e.g. `sudo apt install smpq` or `yum install smpq`), on windows you can\n  [download the latest version from Launchpad.net](https://launchpad.net/smpq/+download), and unix based OSes can build\n  from source using [tools/build_and_install_smpq.sh](../tools/build_and_install_smpq.sh)\n\n### Compiling\n\n```bash\ncmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_ASSETS_MPQ=ON\ncmake --build build -j $(getconf _NPROCESSORS_ONLN)\n```\n\nThe nro-file will be generated in the build folder. Test with an emulator (RyuJinx) or real hardware.\n\n[Nintendo Switch manual](manual/platforms/switch.md)\n</details>\n\n<details><summary>Nintendo 3DS</summary>\n\n### Installing dependencies\n\nhttps://devkitpro.org/wiki/Getting_Started\n\n- Install (dkp-)pacman: https://devkitpro.org/wiki/devkitPro_pacman\n\n- Install required packages with (dkp-)pacman:\n\n```\nsudo (dkp-)pacman -S \\\n    devkitARM general-tools 3dstools libctru \\\n    citro3d 3ds-sdl 3ds-libpng 3ds-bzip2 \\\n    3ds-cmake 3ds-pkg-config picasso 3dslink\n```\n\n- Download or compile [bannertool](https://github.com/diasurgical/bannertool/releases) and [makerom](https://github.com/jakcron/Project_CTR/releases)\n    - Copy binaries to: `/opt/devkitpro/tools/bin/`\n\n### Compiling\n\n_If you are compiling using MSYS2, you will need to run `export MSYS2_ARG_CONV_EXCL=-D` before compiling.\nOtherwise, MSYS will sanitize file paths in compiler flags which will likely lead to errors in the build._\n\n```bash\ncmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(getconf _NPROCESSORS_ONLN)\n```\n\nThe output files will be generated in the build folder.\n\n[Nintendo 3DS manual](/docs/manual/platforms/3ds.md)\n</details>\n\n<details><summary>PlayStation Vita</summary>\n\n### Compiling\n\n```bash\ncmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release\ncmake --build build\n```\n\n[PlayStation Vita manual](/docs/manual/platforms/vita.md)\n</details>\n\n\n<details><summary>Haiku</summary>\n\n### Installing dependencies on 32 bit Haiku\n\n```\npkgman install cmake_x86 devel:libsdl2_x86 devel:libsodium_x86 devel:libpng_x86 devel:bzip2_x86\n```\n\n### Installing dependencies on 64 bit Haiku\n\n```\npkgman install cmake libsdl2_devel libsodium_devel libpng16_devel bzip2_devel gtest_devel gettext getconf\n```\n\n### Compiling on 32 bit Haiku\n\n```bash\nsetarch x86 # Switch to secondary compiler toolchain (GCC8+)\ncmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(getconf _NPROCESSORS_ONLN)\n```\n\n### Compiling on 64 bit Haiku\n\nNo setarch required, as there is no secondary toolchain on x86_64, and the primary is GCC8+\n\n```bash\ncmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j $(getconf _NPROCESSORS_ONLN)\n```\n\n</details>\n\n<details><summary>OpenDingux / RetroFW</summary>\n\nDevilutionX uses buildroot-based toolchains to build packages for OpenDingux and RetroFW.\n\nFor OpenDingux / RetroFW builds, `mksquashfs` needs to be installed on your machine.\n\nTo build, run the following command:\n\n~~~ bash\nTOOLCHAIN=<path/to/toolchain> Packaging/OpenDingux/build.sh <platform>\n~~~\n\nReplace `<platform>` with one of: `lepus`, `retrofw`, `rg99`, `rg350`, or `gkd350h`.\n\nFor example:\n\n~~~ bash\nTOOLCHAIN=/opt/gcw0-toolchain Packaging/OpenDingux/build.sh rg350\n~~~\n\nYou can download the prebuilt toolchains for `x86_64` hosts here:\n\n* OpenDingux: https://github.com/OpenDingux/buildroot/releases\n* RetroFW: https://github.com/Poligraf/retrofw_buildroot_gcc11/releases\n\nRemember to run `./relocate-sdk.sh` in the toolchain directory after unpacking it.\n\nAlternatively, if you do not set `TOOLCHAIN`, the script will\ndownload and compile a partial buildroot toolchain for you\n(stored at `$HOME/buildroot-$PLATFORM-devilutionx`).\nThis requires 8 GiB+ disk space and takes a while.\n\nEnd-user manuals are available [here](manual/platforms) and\nin the package help section.\n\n</details>\n\n<details><summary>Clockwork PI GameShell</summary>\n\nYou can either call\n\n~~~ bash\nPackaging/cpi-gamesh/build.sh\n~~~\n\nto install dependencies and build the code.\n\nOr you create a new directory under `/home/cpi/apps/Menu` and copy [the file](../Packaging/cpi-gamesh/__init__.py) there. After restarting the UI, you can download and compile the game directly from the device itself. See [the readme](../Packaging/cpi-gamesh/readme.md) for more details.\n</details>\n\n<details><summary>Amiga via Docker</summary>\n\n### Build the container from the repo root\n\n~~~ bash\ndocker build -f Packaging/amiga/Dockerfile -t devilutionx-amiga .\n~~~\n\n### Build DevilutionX Amiga binary\n\n~~~ bash\ndocker run -u \"$(id -u \"$USER\"):$(id -g \"$USER\")\" --rm -v \"${PWD}:/work\" devilutionx-amiga\n~~~\n\nThe command above builds DevilutionX in release mode.\nFor other build options, you can run the container interactively:\n\n~~~ bash\ndocker run -u \"$(id -u \"$USER\"):$(id -g \"$USER\")\" -ti --rm -v \"${PWD}:/work\" devilutionx-amiga bash\n~~~\n\nSee the `CMD` in `Packaging/amiga/Dockerfile` for reference.\n\nTo actually start DevilutionX, increase the stack size to 50KiB in Amiga.\nYou can do this by selecting the DevilutionX icon, then hold right mouse button and\nselect Icons -> Information in the top menu.\n</details>\n\n<details><summary>Emscripten</summary>\n\nEmscripten port is a work in progress. It builds but does not do more than that currently.\n\nTo build, install the [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html), then run:\n\n~~~ bash\nemcmake cmake -S. -Bbuild-em -DCMAKE_BUILD_TYPE=Release\ncmake --build build-em -j $(getconf _NPROCESSORS_ONLN)\n~~~\n\nTo then run it:\n\n~~~ bash\ncd build-em\nemrun index.html\n~~~\n\n</details>\n\n<details><summary>Xbox One/Series</summary>\n\n### Dependencies\n\n* Windows 10\n* CMake\n* Git\n* Visual Studio 2022 with the following packages installed:\n    * C++ (v143) Universal Windows Platform tools\n    * Windows 11 SDK (10.0.26100.0)\n    * MSVC v143 - VS 2022 C++ x64/x86 build tools\n\n_Note: Visual Studio Community Edition can be used._\n\n### Building\n\nAdd the following to the PATH:\n\n* CMake\n* GIT\n* VsDevCmd.bat\n\nRun:\n\n```\nPackaging/xbox-one/build.bat\n```\n\n[Xbox One/Series manual](manual/platforms/xbox-one.md)\n</details>\n\n<details><summary>Miyoo Mini</summary>\n\nBuilding for Miyoo Mini must be run from inside the [Toolchain Docker image](https://github.com/MiyooMini/union-toolchain).\nExecuting `Packaging/miyoo_mini/build.sh` will create the folder `build-miyoo-mini/SDROOT` which has the correct structure to be used with\nOnionOS Port Collection.\n</details>\n\n<details><summary>macOS 10.4 Tiger</summary>\n\nFor macOS Tiger, DevilutionX can be compiled using the compiler and libraries from [MacPorts](https://www.macports.org/).\n\nFor PowerPC, you can use precompiled dependencies from here:\n\nhttp://macports-tiger-ppc.glebm.com/\n\nAfter installing MacPorts, run:\n\n~~~ bash\n# Some packages may require you to manually deactivate certain ports during installation.\n# Remember to reactivate them after installing.\nsudo port install curl curl-ca-bundle gcc14 cmake \\\n  libsdl12 libsdl_image libsodium bzip2 zlib lua54\n\n# Set GCC 14 as the default GCC:\nsudo port select --set gcc mp-gcc14\n~~~\n\n<!-- The following packages have issues so we use the vendored versions:\n     libfmt11 google-benchmark gtest -->\n\nThen, build DevilutionX:\n\n~~~ bash\nCC=gcc cmake -S. -Bbuild-rel -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DCPACK=ON -DMACOSX_STANDALONE_APP_BUNDLE=ON\ncmake --build build-rel -j \"$(sysctl -n hw.ncpu)\"\n\n# `sudo` is required to produce a bundle with all the shared libraries.\nsudo cmake --build build-rel --target package -j \"$(sysctl -n hw.ncpu)\"\n~~~\n\nTo run tools from the `tools/` directory (only needed for development), you also need Python:\n\n~~~ bash\nsudo port install python312\nsudo port select --set python python312\nsudo port select --set python3 python312\n~~~\n\n</details>\n\n<details><summary>DOS</summary>\n\nYou can build for DOS from Linux using DJGPP.\n\nFirst, install / compile the dependencies (only needs to be done once):\n\n~~~ bash\nPackaging/windows/dos-prep.sh\n~~~\n\nThen, build DevilutionX:\n\n~~~ bash\ncmake -S. -Bbuild-dos -DCMAKE_TOOLCHAIN_FILE=CMake/platforms/djcpp.toolchain.cmake -DTARGET_PLATFORM=\"dos\" \\\n  -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF\ncmake --build build-dos -j $(getconf _NPROCESSORS_ONLN)\n~~~\n\n</details>\n\n<details><summary><b>CMake build options</b></summary>\n\n### General\n\n- `-DCMAKE_BUILD_TYPE=Release` changed build type to release and optimize for distribution.\n- `-DNONET=ON` disable network support, this also removes the need for the ASIO and Sodium.\n- `-DUSE_SDL1=ON` build for SDL v1 instead of v2, not all features are supported under SDL v1, notably upscaling.\n- `-DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/linux_i386.toolchain..cmake` generate 32bit builds on 64bit platforms (remember to use the `linux32` command if on Linux).\n\n### Debug builds\n\n- `-DDEBUG=OFF` disable debug mode of the Diablo engine.\n- `-DASAN=OFF` disable address sanitizer.\n- `-DUBSAN=OFF` disable undefined behavior sanitizer.\n\n</details>\n"
  },
  {
    "path": "docs/debug.md",
    "content": "## Introduction\n\nIf you compile the game in debug, you have multiple debug features available.\n\n## Debug commands\n\nIn-game you have the possibility to use the chat to trigger debug commands.\nThis is currently a replacement for a console.\n\n| Command | Description |\n| ------- | ----------- |\n| `help` | Shows a list of all debug commands with descriptions. |\n| `god` | Toggles godmode. |\n| ... | For the other commands see `help` ingame and there are a lot. |\n\nTip: Debug commands are also supported in quick messages. If you need a debug command frequently, put it in a quick message. :wink:\n\n## Command-line parameters\n\n| Command | Description |\n| ------- | ----------- |\n| `+` | Executes a debug command when loading the first game. For example `+god` or `+changelevel 1 +spawn 4 skeleton`. |\n| `-f` | Display frames per second. |\n| `-i` | Disable network timeout. |\n| `-n` | Disable startup video. |\n\n## In-game hotkeys\n\n| Hotkey | Description |\n| ------ | ----------- |\n| `Shift` | While holding, you can use the mouse to scroll screen. |\n| `m` | Print debug monster info. |\n| `M` | Switch current debug monster. |\n| `x` | Toggles `DebugToggle` variable. `DebugToggle` is a generic solution for temporary toggles needed for debugging. |\n"
  },
  {
    "path": "docs/github-codespaces.md",
    "content": "# Developing with GitHub Codespaces\n\nA GitHub codespace container with all dependencies and several useful tools preinstalled is configured in the `.devcontainer` directory.\n\nTo develop in a codespace, open the in-browser VS Code editor by either pressing the `.` or going to https://github.dev/diasurgical/devilutionX/.\n\nThen, focus on the terminal window from the Command Palette menu (<kbd>F1</kbd>):\n\n![screenshot](gh-focus-on-terminal.png)\n\nThen, click \"Continue Working in GitHub Codespaces\":\n\n![screenshot](gh-continue-in-codespaces.png)\n\nIt will take a few minutes to build the container.\n\nOnce installed, the page will load back into the in-browser VS Code editor but now with a\ncontainer shell.\n\nTo view the graphical desktop of the container, click Ports > Browser.\n\nThe password is `vscode`.\n\n![screenshot](gh-codespaces-ports-browser.png)\n\nFor more information about the desktop environment, see https://github.com/devcontainers/features/tree/main/src/desktop-lite\n\nOnce you have a codespace set up, you can reuse it in the future by going to \"Your codespaces\" on GitHub (https://github.com/codespaces):\n\n![screenshot](gh-open-codespace.png)\n"
  },
  {
    "path": "docs/installing.md",
    "content": "# Installing\n\nFirst, you will need access to the game's MPQ files.\n\n- Locate `DIABDAT.MPQ` on your CD, or in the [GoG](https://www.gog.com/game/diablo) installation (or [extract it from the GoG installer](https://github.com/diasurgical/devilutionX/wiki/Extracting-MPQs-from-the-GoG-installer)).\n- For the Diablo: Hellfire expansion you will also need `hellfire.mpq`, `hfmonk.mpq`, `hfmusic.mpq`, `hfvoice.mpq`.\n- DevilutionX comes with [devilutionx.mpq](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/devilutionx.mpq) which is required to run the game properly.\n- Chinese, Korean, and Japanese users will also need [fonts.mpq](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq) or the text will be missing.\n- For Polish voice support you need [pl.mpq](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/pl.mpq)\n- For Russian voice support you need [ru.mpq](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/ru.mpq)\n\nDownload the latest [DevilutionX release](https://github.com/diasurgical/devilutionX/releases) for your system (if available) and extract the contents to a location of your choosing, or [build from source](building.md). Then follow the system-specific instructions below.\n\n<details><summary>Android</summary>\n\nFirst install the App via one of these 3 methods:\n\n- [Google Play](https://play.google.com/store/apps/details?id=org.diasurgical.devilutionx)\n- Copy the APK file to the device and tap on it in the device's file explorer and follow the instructions\n- Install via `adb install` (if USB debugging is enabled on the device)\n\nThen launch the App, this will let it create the folder where you need to place the MPQ files.\n\nConnect the device to your computer via USB cable, and allow data access from your device:\n\n![image](https://user-images.githubusercontent.com/204594/139543023-3c45bb22-35f7-41af-8b3d-c714a9542d23.png)\n\nOpen the device's internal storage, and navigate to `Android/data/org.diasurgical.devilutionx/files`, then copy the MPQ-files to this folder.\n\n![image](https://user-images.githubusercontent.com/204594/139542962-4e776854-6ca4-4872-8ed6-6303fc4bf040.png)\n\nWhen the transfer is done you can disconnect your device and press \"Check again\" in the App to start the game.\n\n![image](https://user-images.githubusercontent.com/204594/139541657-d8c1197d-fbef-42b6-a34f-2b17f1ceab5f.png)\n\n**Troubleshooting**: If you encounter some trouble getting the MPQ files onto your Android device, you can refer to\n[our guide](https://github.com/diasurgical/devilutionX/wiki/Extracting-MPQs-from-the-GoG-installer#android) for extracting the MPQ files on the Android device itself.\nNote that Inno Setup Extractor is only available for Android 8+ and the Import Data feature is only available for Android 7.1.1+.\n\n</details>\n\n<details><summary>Windows</summary>\n\n**Note**: if you have the GoG version installed on your Windows machine, you do not need to copy the MPQ files as described in the instructions.\n- Copy the MPQ files to the folder containing the DevilutionX exe, or to the data folder. The data folder path may differ, but will normally be `%AppData%\\diasurgical\\devilution`\n- Run `devilutionx.exe`\n\n</details>\n\n<details><summary>Linux</summary>\n\n- Copy the MPQ files to the folder containing the DevilutionX executable, or to the data folder. The data folder path may differ depending on distro, version, and security settings, but will normally be `~/.local/share/diasurgical/devilution/`, for flatpak installation the path is `~/.var/app/org.diasurgical.DevilutionX/data/diasurgical/devilution/`\n- Install [SDL2](https://www.libsdl.org/download-2.0.php):\n- Ubuntu/Debian/Rasbian `sudo apt install libsdl2-2.0-0 libsdl2-image-2.0-0`\n- Fedora `sudo dnf install SDL2`\n- Run `./devilutionx`\n\n</details>\n\n<details><summary>MacOS X</summary>\n\n- Copy the MPQ files to the folder containing the DevilutionX application, or to the data folder. The data folder path may differ, but will normally be `~/Library/Application Support/diasurgical/devilution`\n- Double-click `devilutionx`\n\n</details>\n\n<details><summary>FreeBSD</summary>\n\n- Copy the MPQ files to the folder containing the DevilutionX application, or to the data folder `~/.local/share/diasurgical/devilution/`\n- To install the port: `cd /usr/ports/games/devilutionX/ && make install clean`\n- To add the package, run one of these commands:\n  `pkg install games/devilutionX` || `pkg install devilutionX`\n- Run `devilutionx`\n\n</details>\n\n<details><summary>iOS & iPadOS</summary>\n\nCertain sideloading applications exist which can let you install IPA packages to your device such as AltStore (https://altstore.io/) and Sideloadly (https://sideloadly.io/). Using such a sideloading application, install the .ipa file to your iDevice.\n\nOnce the App is installed, launch it once. It will say that it cannot find the data file (.MPQ). This is ok. Close the game. Do not skip this step as it will create your Documents folder that you will need to access in later steps.\n\nThere are 3 way to get install the MPQs. Make sure to have installed the app and have launched it once before attempting to copy over the MPQ files.\n\n~~Method 1~~ (***May no longer work***): ~~Using the files.app~~\n\n~~- Using the files.app, navigate to \"On My iPhone / On My iPad\"~~\n\n![ios_mpq_files01](https://user-images.githubusercontent.com/1339414/145088910-5664aed6-3a53-43f4-8088-834796792f68.png)\n\n~~- Copy the MPQs to the devilutionx directory. Your directory should look like on the picture below~~\n\n![ios_mpq_files02](https://user-images.githubusercontent.com/1339414/145089068-2c87887b-58c3-4759-9270-9d8934fe90bb.png)\n\n~~- Go back to your home screen and launch the game~~\n\nMethod 2: Using Finder (MacOS)\n\nOn more recent versions of MacOS, iTunes is no more. Instead you can use Finder to directly copy data to and from your iDevices\n\n- Connect your iDevice to your computer and click on the \"Files\" tab.\n\n  ![ios_mpq_finder01](https://user-images.githubusercontent.com/1339414/145089218-f5424196-f345-45da-aca6-9c2b2e06cdf0.png)\n\n- Drag and drop the MPQ files on the devilutionx directory\n\nMethod 3: Using iTunes (Windows and older MacOS)\n\n- Connect you iDevice to your computer and launch iTunes\n\n- Click on your device and in the files tab drag and drop the MPQ files to the devilutionx directory\n\n</details>\n\n<details><summary>Nintendo Switch</summary>\n\n- Copy `devilutionx.nro` in into `/switch/devilutionx`\n- Copy the MPQ files to `/switch/devilutionx`.\n- Launch `devilutionx.nro` by holding R the installed game. Do not use the album to launch, if you use the album, the homebrew will only have a small amount of memory available, and the touch keyboard won't work. This is true for all homebrew, not just DevilutionX.\n\n</details>\n\n<details><summary>Nintendo 3DS</summary>\n\nDownload `devilutionx.cia` from the [latest release](https://github.com/diasurgical/devilutionX/releases/latest) and place it on your SD card.\nThis file will be used later to install the game on the 3DS console.\n\nCopy the MPQ files to the `devilutionx` subfolder under the `3ds` folder on your SD card (`/3ds/devilutionx`). The game will read these files from this location.\nYou do not need a copy of `devilutionx.mpq` on your SD card to run the game on 3DS.\nTo avoid errors when you run the game, if you have an old version of `devilutionx.mpq` in the folder, you should remove it now. Note, all file and folder names should be lowercase, as shown in the example screenshot below.\n\n![image](https://user-images.githubusercontent.com/9203145/141046152-61be39dc-d14e-4b10-accf-1755a93972f7.png)\n\nPut the SD card back into the 3DS console and then power it on.\nUse a title manager such as [FBI](https://github.com/Steveice10/FBI) to install `devilutionx.cia`.\nYou will no longer need `devilutionx.cia` after this step, and so it can be removed after the installation.\n\n![image](https://user-images.githubusercontent.com/9203145/141047377-789e5f1c-d049-4a25-82bb-8b3572d791cf.png)\n\nFBI provides the `Remote Install` option to download and install a cia in one step by scanning a QR code using the Nintendo 3DS camera.\nThis is most useful when upgrading from a previous version so that you can perform the installation without removing the SD card from the console.\nIf you'd like to use this option, scan the QR code below.\n\n![image](https://user-images.githubusercontent.com/9203145/144300019-e315c05f-515c-484d-975b-ce99da641585.png)\n\n[Nintendo 3DS manual](/docs/manual/platforms/3ds.md)\n\n</details>\n\n<details><summary>Xbox One/Series</summary>\n\n- Go to https://gamr13.github.io/ and follow the instructions in the Discord server\n- Install DevilutionX and FTP-server from the given URLs\n- Open DevilutionX\n- Open and start the FTP-server\n- Press `View` on DevilutionX and select `Manage game and add-ons`\n- Go to `File info` and note `FullName`\n- Copy the MPQ files to `/LOCALFOLDER/*FullName*/LocalState/diasurgical/devilution` using a FTP-client on your PC\n\n![image](https://user-images.githubusercontent.com/204594/187104388-fc5648da-5629-4335-ae8b-403600721e2a.png)\n\n</details>\n\n<details><summary>Playstation 4</summary>\n\n- Install devilutionx-ps4.pkg\n- Copy the MPQ files (e.g., using ftp) to `/user/data/diasurgical/devilution/`\n\n</details>\n\n<details><summary>Playstation Vita</summary>\n\n- Install devilutionx.vpk\n- Copy the MPQ files to `ux0:/data/diasurgical/devilution/`.\n\n</details>\n\n<details><summary>ClockworkPi GameShell</summary>\n\n- Copy the `__init__.py` to a newly created folder under /home/cpi/apps/Menu and run it from the menu. The folder then symbolizes the devilutionX icon.\n- From this menu, you can press 'X' to clone the git repository for devilutionX and compile the code. Dependencies are installed automatically (cmake and SDL development packages).\n- Once installed, 'X' pulls the updated code and does the compiling. Note that any changes made locally to the source are reverted before pulling.\n- When the compile is finished, Copy the MPQ files to `/home/cpi/.local/share/diasurgical/devilution/`\n- You can now play the game from the same icon.\n\n</details>\n\n<details><summary>GKD350h</summary>\n\n- Copy [devilutionx-gkd350h.opk](https://github.com/diasurgical/devilutionX/releases/download/1.0.1/devilutionx-gkd350h.opk) to `/media/data/apps` or `/media/sdcard/apps/`.\n- Copy the MPQ files to `/usr/local/home/.local/share/diasurgical/devilution/`\n\n</details>\n\n<details><summary>RetroFW</summary>\n\n**Requires RetroFW 2.0+.**\n\n- Copy [devilutionx-retrofw.opk](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-retrofw.opk) to the apps directory.\n- Copy the MPQ files to `~/.local/share/diasurgical/devilution`\n\n`~` is your home directory, `/home/retrofw` by default.\n\n</details>\n\n<details><summary>RG350</summary>\n\n**Requires firmware v1.5+**\n\n- Copy [devilutionx-rg350.opk](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-rg350.opk) to `/media/sdcard/APPS/`.\n- Copy the MPQ files to `/media/home/.local/share/diasurgical/devilution/`\n- **NOTE:** You can copy the MPQ files to sdcard instead and create a symlink at the expected location. To do this, SSH into your RG350 and run:\n\n ~~~bash\n ln -sf /media/sdcard/<path_to_MPQ> /media/home/.local/share/diasurgical/devilution/<MPQ>\n ~~~\n\n</details>\n\n<details><summary>Miyoo Mini</summary>\n\n**Requires OnionOS to be installed**\n\n- Activate the ports collection by using the onion installer on the device\n- Copy the contents of the released .zip-file onto the root of your SD card\n- Copy the MPQ files to `/Emu/PORTS/Binaries/Diablo.port/FILES_HERE/`\n</details>\n"
  },
  {
    "path": "docs/manual/platforms/3ds.md",
    "content": "# DevilutionX (Diablo 1) for Nintendo 3DS\n\n## Installation\n\nLook for the latest release on the\n[Releases](https://github.com/diasurgical/devilutionX/releases/latest) page.\n\nInstallation instructions can be found on the [Installing](/docs/installing.md) page.\n\n## Usage\n\n* Launch Diablo from your 3DS Homemenu.\n\n## Controls\n\n* Circle-Pad or D-Pad: move hero\n* A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n* B: select spell, back while in menus\n* X: pickup items, open nearby chests and doors, use item in the inventory\n* Y: cast spell, delete character while in main menu\n* L: use health item from belt\n* R: use mana potion from belt\n* Start + ↑: game menu (alt: Start + Select)\n* Start + ↓: toggle automap\n* Start + ←: character sheet (alt: ZL or Start + L)\n* Start + →: inventory (alt: ZR or Start + R)\n* Start + X: toggle zoom\n* Select + D-Pad: move automap or simulate mouse\n* Select + A/B/X/Y: Spell hotkeys\n* C-stick: move automap or simulate mouse\n* Select + ZL: quest log (alt: Start + Y)\n* Select + ZR: spell book (alt: Start + B)\n\n## Touchpad\n\n* Single finger drag: move the mouse pointer (pointer jumps to finger)\n* Single short tap: left mouse click\n\n## Multiplayer\n\nThe 3DS currently supports cross-platform Multiplayer in TCP mode.\nTo play, you will need to enable Wi-Fi on the console and set up a network connection in System Settings.\nFor more general information about Multiplayer and how to set up your network for TCP games,\nrefer to the [DevilutionX Multiplayer guide](https://github.com/diasurgical/devilutionX/wiki/Multiplayer).\n\nWhen playing Multiplayer, guests will experience better performance than hosts.\nWhen playing cross-platform, it is recommended to host your game session\non another platform with more capable hardware.\n\n## Translations\n\nThe 3DS version of the game will attempt to detect the appropriate\nlanguage based on your 3DS console's language setting.\nChinese, Korean, and Japanese users will need to download\n[fonts.mpq](https://github.com/diasurgical/devilutionx-assets/releases/latest/download/fonts.mpq)\nor the text will be missing.\n\nIt is currently not recommended to use the Chinese, Korean, or Japanese translations on old 3DS models.\nThe game will load additional symbols into system memory as needed while you continue to play the game.\nThere is not enough memory in the old 3DS models to hold all the symbols in memory.\nIt is therefore possible to run out of memory on the console and crash the game simply by using these translations.\n\nTo change the language used by the game, you will need to\n[modify diablo.ini](https://github.com/diasurgical/devilutionX/wiki/DevilutionX-diablo.ini-configuration-guide#language).\nThe config folder path for 3DS is the same as the data folder for the MPQs (`/3ds/devilutionx` on your SD card).\n\n## Performance tips\n\nNew 3DS models have significantly improved hardware compared to old models.\nTo improve the performance of the game on old 3DS models, you will want to\n[modify diablo.ini](https://github.com/diasurgical/devilutionX/wiki/DevilutionX-diablo.ini-configuration-guide).\nThe config folder path for 3DS is the same as the data folder for the MPQs (`/3ds/devilutionx` on your SD card).\n\nIn particular, you will see a significant performance improvement\nif you set the game to Diablo's original resolution of 640x480.\n\n```ini\n[Graphics]\nWidth=640\nHeight=480\n```\n\nAfter making this change, if you would like the game to stretch to fit the full area of the top screen,\nuse `Fit to Screen=1`. If instead you do not like the display to be stretched, use `Fit to Screen=0`.\n\nBecause 3DS uses SDL1, many of the graphics settings do not apply.\nThe following represents the full list of applicable settings.\n\n* Width\n* Height\n* Fit to Screen\n* Blended Transparency\n* Gamma Correction\n* Color Cycling\n* FPS Limiter\n\n## Resources\n\n* Discord: https://discord.gg/devilutionx\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/manual/platforms/gkd350h.md",
    "content": "# DevilutionX (Diablo 1) for GKD350h\n\n![gkd-350h-devilutionx](https://user-images.githubusercontent.com/216339/73123835-32e41080-3f8c-11ea-970c-8dd159c6e4ef.jpg)\n\n## Installation\n\n1. Copy [devilutionx-gkd350h.opk](https://github.com/diasurgical/devilutionX/releases/download/1.0.1/devilutionx-gkd350h.opk) to `/media/data/apps` or `/media/sdcard/apps/`.\n2. Copy `diabdat.mpq` from your CD, or GoG install folder to:\n\n   ~~~\n   /usr/local/home/.local/share/diasurgical/devilution/diabdat.mpq\n   ~~~\n\n## Controls\n\n- Joystick / D-Pad: move hero\n- ○: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- ×: select spell, back while in menus\n- △: pickup items, open nearby chests and doors, use item in the inventory\n- □: cast spell, delete character while in main menu\n- L: use health item from belt\n- R: use mana potion from belt\n- Select + ↑: game menu\n- Select + L or ←: character info\n- Select + R or →: inventory\n- Select + ↓: map\n- Select + □: Quest log\n- Select + ×: Spell book\n- Start + △○×□: Quick spell hotkeys\n\n## Known issues / quirks\n\n* Start and Select are swapped in this version because Start + D-Pad controls backlight on the GKD350h.\n* There is nothing to map mouse emulation to in this version because of this but it isn't necessary to play the game. Unfortunately, this also means that you can't move the automap.\n* This version looks uglier than on RG350 because it uses software scaling because the IPU on the GKD350h doesn't work.\n\nSaves are compatible with PC saves from Diablo 1 and DevilutionX.\n\n## Resources\n\n* Discord: https://discord.gg/devilutionx\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/manual/platforms/retrofw.md",
    "content": "# DevilutionX (Diablo 1) for RetroFW (RG300/RS-97/RS-07/LDK)\n\nDemo video:\n\n<a href=\"https://www.youtube.com/watch?v=fxpdc1iZK94\" target=\"_blank\"><img src=\"https://user-images.githubusercontent.com/216339/66889273-ae234700-efd9-11e9-8746-489f4eece210.jpg\" height=\"300\"></a>\n\n## Installation\n\n**Requires RetroFW 2.0+.**\n\n1. Copy [devilutionx-retrofw.opk](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-retrofw.opk) to the apps directory.\n2. Copy `diabdat.mpq` from your CD, or GoG install folder to:\n\n   ~~~\n   ~/.local/share/diasurgical/devilution\n   ~~~\n\n`~` is your home directory, `/home/retrofw` by default.\n\n## Controls\n\n- D-pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- R: use mana potion from belt\n- L: use health item from belt\n- Start + Select: game menu (alt: Start + ↑)\n- Start + L or ←: character info\n- Start + R or →: inventory\n- Start + ↓: map\n- Start + Y: Quest log\n- Start + B: Spell book\n- Select + A/B/X/Y: hot spell\n- Select + D-pad: move map/cursor\n- Select + L: left mouse click\n- Select + R: right mouse click\n- Suspend: map\n\n---\n\nGame saves and `diablo.ini` are located at:\n\n~~~\n~/.local/share/diasurgical/devilution\n~~~\n\nSaves are compatible with PC saves from Diablo 1 and DevilutionX.\n\n## Resources\n\n* Discord: https://discord.gg/devilutionx\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/manual/platforms/rg350.md",
    "content": "# DevilutionX (Diablo 1) for the RG-350 handheld\n\nDemo video:\n\n<a href=\"https://youtu.be/ItA3TMiqXu8\"><img src=\"https://user-images.githubusercontent.com/216339/66907570-73cda000-f001-11e9-9341-539fda20eff4.jpg\" height=\"300\"></a>\n\n## Installation\n\n**Requires OpenDingux Beta**\n\n1. Copy [devilutionx-rg350.opk](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-rg350.opk) to `/media/sdcard/APPS/`.\n\n2. Copy `diabdat.mpq` from your CD, or GoG install folder to:\n\n   ~~~\n   /media/home/.local/share/diasurgical/devilution/diabdat.mpq\n   ~~~\n\n   **NOTE:** You can copy `diabdat.mpq` to sdcard instead and create a symlink at the expected location. To do this, SSH into your RG350 and run:\n\n   ~~~bash\n   ln -sf /media/sdcard/<path_to_diabdat.mpq> /media/home/.local/share/diasurgical/devilution/diabdat.mpq\n   ~~~\n\n## Controls\n\n- Left analog or D-Pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- L1: use health item from belt\n- R1: use mana potion from belt\n- L2: character sheet (alt: Start + L1 or ←)\n- R2: inventory (alt: Start + R1 or →)\n- Left analog click: toggle automap (alt: Start + ↓)\n- Start + Select: game menu (alt: Start + ↑)\n- Select + A/B/X/Y: Spell hotkeys\n- Right analog: move automap or simulate mouse\n- Right analog click: left mouse click (alt: Select + L1)\n- Select + Right analog click: right mouse click (alt: Select + R1)\n- Select + L2: quest log (alt: Start + Y)\n- Select + R2: spell book (alt: Start + B)\n\n---\n\nGame saves and `diablo.ini` are located at:\n\n~~~\n/media/home/.local/share/diasurgical/devilution/\n~~~\n\nSaves are compatible with PC saves from Diablo 1 and DevilutionX.\n\n## Resources\n\n* Discord: https://discord.gg/devilutionx\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/manual/platforms/rg99.md",
    "content": "# DevilutionX (Diablo 1) for RG99\n\n## Installation\n\n**This version is experimental and requires using an unsupported fork of OpenDingux!**\n\n1. Install the OpenDingux fork from https://github.com/od-contrib/buildroot/releases\n2. Copy [devilutionx-rg99.opk](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-rg99.opk) to the apps directory.\n3. Unpack and minify all the MPQ contents using `unpack_and_minify` from https://github.com/diasurgical/devilutionx-mpq-tools/.\n4. Copy the resulting directories to:\n\n   ~~~\n   /media/data/local/home/.local/share/diasurgical/devilution/\n   ~~~\n\n   You will need to symlink `/media/data/local/home/.local` to your SD card first:\n\n   ~~~\n   mv /media/data/local/home/.local /media/sdcard/dotlocal\n   ln -s /media/data/local/home/.local /media/sdcard/dotlocal\n   ~~~\n\n## Controls\n\n- D-pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- R: use mana potion from belt\n- L: use health item from belt\n- Start + Select: game menu (alt: Start + ↑)\n- Start + L or ←: character info\n- Start + R or →: inventory\n- Start + ↓: map\n- Start + Y: Quest log\n- Start + B: Spell book\n- Select + A/B/X/Y: hot spell\n- Select + D-pad: move map/cursor\n- Select + L: left mouse click\n- Select + R: right mouse click\n- Suspend: map\n\n---\n\nGame saves and `diablo.ini` are located at:\n\n~~~\n/media/home/.local/share/diasurgical/devilution/\n~~~\n\nSaves are compatible with PC saves from Diablo 1 and DevilutionX.\n\n## Resources\n\n* Discord: https://discord.gg/aQBQdDe\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/manual/platforms/switch.md",
    "content": "# DevilutionX (Diablo 1) for Nintendo Switch\n\n## Installation\n\n1. Download and unzip [devilutionx-switch.zip](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-switch.zip).\n2. Put `devilutionx.nro` into `/switch/devilutionx`\n3. Copy `diabdat.mpq` from your CD (or GoG install folder) to `/switch/devilutionx`.\n\n## Usage\n\nLaunch `devilutionx.nro`. (Do not use album to launch; see the note below.)\n\n*Note:* Hold R on any installed game and launch it. Do not use album to launch. If you use album, the homebrew will only have a small amount memory available, and the touch keyboard won't work. This is true for all homebrew, not just DevilutionX.\n\n## Joycon Controls\n\n- Left analog or D-Pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- L: use health item from belt\n- R: use mana potion from belt\n- ZL: character sheet (alt: Start + L or ←)\n- ZR: inventory (alt: Start + R or →)\n- Left analog click: toggle automap (alt: Start + ↓)\n- Start + Select: game menu (alt: Start + ↑)\n- Select + A/B/X/Y: Spell hotkeys\n- Right analog: move automap or simulate mouse\n- Right analog click: left mouse click (alt: Select + L)\n- Select + Right analog click: right mouse click (alt: Select + R)\n- Select + ZL: quest log (alt: Start + Y)\n- Select + ZR: spell book (alt: Start + B)\n\n## Touch Controls\n\n- Single finger drag: move the mouse pointer (pointer jumps to finger)\n- Single short tap: left mouse click\n- Single short tap while holding a second finger down: right mouse click\n- Dual finger drag: drag'n'drop (left mouse button is held down)\n- Three finger drag: drag'n'drop (right mouse button is held down)\n\n## Resources\n\n* Discord: https://discord.gg/devilutionx\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/manual/platforms/vita.md",
    "content": "# devilutionX PS Vita port\n\n## How To Play:\n - Install VPK\n - Copy diabdat.mpq from your CD or GoG installation (or [extract it from the GoG installer](https://github.com/diasurgical/devilutionX/wiki/Extracting-the-.MPQs-from-the-GoG-installer)) to the `ux0:/data/diasurgical/devilution/`.\n\n# Building from Source\n\n```\ncd build\ncmake -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..\nmake\n```\n\n# Multiplayer\n - Supported via direct TCP connections\n\n# Controls\n\n## Default\n\n- Left analog or D-Pad: move hero\n- ○: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, back in menus\n- ×: select spell, OK while in menus\n- △: pickup items, open nearby chests and doors, use item in the inventory\n- □: cast spell, delete character while in main menu\n- L1: use health item from belt\n- R1: use mana potion from belt\n- Left back touch panel: character sheet (alt: Start + ←, alt: L2 on ds4)\n- Right back touch panel: inventory (alt: Start + →, alt: R2 on ds4)\n- Start + ↓: toggle automap\n- Start + Select: game menu (alt: Start + ↑)\n- Select + ×/○/□/△: Spell hotkeys\n- Right analog: move automap or simulate mouse\n- Select + L1: left mouse click\n- Select + R1: right mouse click\n- Start + □: quest log\n- Start + △: spell book\n\n## Options\n\nThere's special section `Controller` in diablo.ini file, that allows you to adjust controls:\n```\n[Controller]\nMapping=\nEnable Rear Touchpad=1\n```\n\n- **Mapping:** allows you to somewhat remap controls. It uses https://github.com/gabomdq/SDL_GameControllerDB syntax. Deprecated, use padmapper menu in-game if you can.\n- **Enable Rear Touchpad:** enable/disable back touch mapping to L2/R2\n"
  },
  {
    "path": "docs/manual/platforms/xbox-one.md",
    "content": "# DevilutionX (Diablo 1) for Microsoft Xbox One/Series\n\n## Installation\n### Dev Mode\n1. Download and unzip [devilutionx-xbox-one-series.zip\n](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-xbox-one-series.zip\n).\n2. In Xbox Device Portal click on `Add` button located at `Home/My games & apps`\n3. In the first popup - called `Deploy or Install Application` choose `devilutionX.appx` and then click `Next`\n4. In the second popup - called `Choose any necessary dependencies` choose `Microsoft.VCLibs.appx` and then click `Start`\n5. In your PC go to the shared folder `WindowsApps` and find the devilutionX folder which should be something like `/LOCALFOLDER/*Gamr13*DevilutionX*/LocalState/diasurgical/devilution`\n6. Copy `diabdat.mpq` from your CD (or GoG install folder) to it.\n7. In the Xbox press `View` on DevilutionX and select `Details` and there change the type from `App` to `Game`.\n\n### Retail Mode\n1. Press `View` on DevilutionX and select `Manage game and add-ons`\n2. Go to `File info` and note `FullName`\n3. Connect to the Xbox via FTP and go to the folder `/LOCALFOLDER/*FullName*/LocalState/diasurgical/devilution`\n4. Send `diabdat.mpq`\n\n## Controls\n\n- Left analog or D-Pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- LB: use health item from belt\n- RB: use mana potion from belt\n- LT: character sheet (alt: Menu + LB or ←)\n- RT: inventory (alt: Menu + RB or →)\n- Left analog click: toggle automap (alt: Menu + ↓)\n- Menu + View: game menu (alt: Menu + ↑)\n- View + A/B/X/Y: Spell hotkeys\n- Right analog: move automap or simulate mouse\n- Right analog click: left mouse click (alt: View + LB)\n- View + Right analog click: right mouse click (alt: View + RB)\n- View + LT: quest log (alt: Menu + Y)\n- View + RT: spell book (alt: Menu + B)\n\n## Resources\n\n* Discord: https://discord.gg/devilutionx\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/manual/platforms/xbox.md",
    "content": "# DevilutionX (Diablo 1) for the original Xbox\n\nDevilutionX is built for the original Xbox using [nxdk](https://github.com/XboxDev/nxdk).\n\n## Installation\n\n1. Download and unzip [devilutionx-xbox.zip](https://github.com/diasurgical/devilutionX/releases/latest/download/devilutionx-xbox.zip).\n2. Copy `diabdat.mpq` (and, optionally, Hellfire MPQs) from your CD (or GoG install folder) to `E:\\UDATA\\devilutionx\\`.\n\n## Controls\n\nNote that Confirm and Cancel are swapped.\n\n- Left analog or D-Pad: move hero\n- A: attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu\n- B: select spell, back while in menus\n- X: pickup items, open nearby chests and doors, use item in the inventory\n- Y: cast spell, delete character while in main menu\n- LB: use health item from belt\n- RB: use mana potion from belt\n- LT: character sheet (alt: Menu + LB or ←)\n- RT: inventory (alt: Menu + RB or →)\n- Left analog click: toggle automap (alt: Menu + ↓)\n- Menu + View: game menu (alt: Menu + ↑)\n- View + A/B/X/Y: Spell hotkeys\n- Right analog: move automap or simulate mouse\n- Right analog click: left mouse click (alt: View + LB)\n- View + Right analog click: right mouse click (alt: View + RB)\n- View + LT: quest log (alt: Menu + Y)\n- View + RT: spell book (alt: Menu + B)\n\n## Resources\n\n* Discord: https://discord.gg/devilutionx\n* GitHub: https://github.com/diasurgical/devilutionX\n"
  },
  {
    "path": "docs/privacy.md",
    "content": "## DevilutionX Privacy Policy\n\n### We don't store your data\n\nDiasurgical does not collect any data from users of DevilutionX\n\n### ZeroTier\n\nBy connecting to the ZeroTier network you allow ZeroTier to see your ISP IP address.\n"
  },
  {
    "path": "docs/profiling-linux.md",
    "content": "# Profiling on Linux\n\nIf you're trying to make DevilutionX run faster or use less memory, profiling can be very helpful.\n\n## gperftools\n\n[gperftools] is a library that provides a heap profiler and a CPU profiler.\n\nTo install gperftools on Debian and Ubuntu, simply run:\n\n```bash\nsudo apt install libgoogle-perftools-dev\n```\n\nYou may also want to install debugging symbols for SDL2:\n\n```bash\nsudo apt install libsdl2-dev-dbgsym\n```\n\ngperftools by default only comes with a basic visualizer.\n[pprof](https://github.com/google/pprof), also from Google, is a more fully-featured profile visualizer\nthat provides an interactive web server with a flame graph, source annotation, etc.\n\nTo install pprof, run:\n\n```bash\ngo install github.com/google/pprof@latest\n```\n\n## CPU profiling with gperftools\n\n```bash\ncmake -S. -Bbuild-gperf -DCMAKE_BUILD_TYPE=RelWithDebInfo -DGPERF=ON -DBUILD_TESTING=ON\n```\n\nTimedemo:\n\n```bash\ntools/build_and_run_benchmark.py --gperf devilutionx -- --diablo --spawn --lang en --demo 0 --timedemo\n```\n\nIndividual benchmarks (built when `BUILD_TESTING` is `ON`):\n\n```bash\ntools/build_and_run_benchmark.py --gperf clx_render_benchmark\n```\n\n## Heap profiling with gperftools\n\nHeap profiling produces a graph of all heap allocations that are alive between two points\nin a program.\n\nDevilutionX has built-in support for heap allocation via [gperftools].\n\nThen, configure and build DevilutionX with the GPERF option:\n\n```bash\ncmake -S. -Bbuild-gperf -DCMAKE_BUILD_TYPE=RelWithDebInfo -DGPERF=ON -DGPERF_HEAP_FIRST_GAME_ITERATION=ON\ncmake --build build-gperf -j $(nproc)\n```\n\nThe `GPERF_HEAP_FIRST_GAME_ITERATION` option will make DevilutionX dump the heap profile of the first game\niteration.\n\nStart DevilutionX and load a game:\n\n```bash\nbuild-gperf/devilutionx\n```\n\nHeap profile data will be generated at `main.0001.heap`.\n\nTo inspect the profile, run:\n\n```bash\ngoogle-pprof --web build-gperf/devilutionx main.0001.heap\n```\n\nSee [gperftools heap profiling documentation] for more information.\n\n[gperftools]: https://github.com/gperftools/gperftools/wiki\n\n[gperftools heap profiling documentation]: https://gperftools.github.io/gperftools/heapprofile.html\n"
  },
  {
    "path": "doxygen.config",
    "content": "PROJECT_NAME           = \"Devilution\"\nPROJECT_BRIEF          = \"Diablo devolved - magic behind the 1996 computer game\"\nUSE_MDFILE_AS_MAINPAGE = ./README.md\nOUTPUT_DIRECTORY       = docs\nINPUT                  = ./ ./Source ./docs\nINPUT_ENCODING         = UTF-8\nFILE_PATTERNS          = *.c \\\n                         *.cpp \\\n                         *.h \\\n                         *.inc \\\n                         *.hpp \\\n                         *.md\nRECURSIVE              = YES\nEXCLUDE                = ./build ./3rdParty ./CMake ./cmake-build-debug\n\nGENERATE_LATEX         = NO\nWARNINGS               = YES\nSOURCE_BROWSER         = YES\nJAVADOC_AUTOBRIEF      = YES\nOPTIMIZE_OUTPUT_FOR_C  = YES\nSEPARATE_MEMBER_PAGES  = YES\nDOT_IMAGE_FORMAT       = svg\nINTERACTIVE_SVG        = YES\nHTML_COLORSTYLE_HUE    = 0\nHTML_COLORSTYLE_SAT    = 125\nHTML_COLORSTYLE_GAMMA  = 200\n\n# Call graphces alows logical navigation of the docs\nCALL_GRAPH             = YES\nCALLER_GRAPH           = YES\n\n# Not all files are documented yet\nEXTRACT_ALL            = YES\nEXTRACT_PRIVATE        = YES\nEXTRACT_STATIC         = YES\nEXTRACT_ANON_NSPACES   = YES\n"
  },
  {
    "path": "mods/Hellfire/data/inv/objcurs2-widths.txt",
    "content": "28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n28\r\n56\r\n56\r\n28\r\n28\r\n28\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n56\r\n"
  },
  {
    "path": "mods/Hellfire/lua/mods/Hellfire/init.lua",
    "content": "local hellfire = require(\"devilutionx.hellfire\")\n\nhellfire.loadData()\nhellfire.enable()\n"
  },
  {
    "path": "mods/Hellfire/txtdata/classes/classdat.tsv",
    "content": "className\tfolderName\tportrait\tinv\r\nWarrior\twarrior\t0\tinv\r\nRogue\trogue\t1\tinv_rog\r\nSorcerer\tsorcerer\t2\tinv_sor\r\nMonk\tmonk\t3\tinv_sor\r\nBard\tbard\t4\tinv_rog\r\nBarbarian\tbarbarian\t0\tinv\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/classes/sorcerer/starting_loadout.tsv",
    "content": "Variable\tValue\r\nskill\tStaffRecharge\r\nspell\tFirebolt\r\nspellLevel\t2\r\nitem0\tIDI_SORCERER\r\nitem1\tIDI_HEAL\r\nitem2\tIDI_HEAL\r\nitem3\tIDI_NONE\r\nitem4\tIDI_NONE\r\ngold\t100\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/items/item_prefixes.tsv",
    "content": "name\tpower\tpower.value1\tpower.value2\tminLevel\titemTypes\talignment\tchance\tuseful\tminVal\tmaxVal\tmultVal\r\nTin\tTOHIT_CURSE\t6\t10\t3\tWeapon,Bow,Misc\tAny\t2\tfalse\t0\t0\t-3\r\nBrass\tTOHIT_CURSE\t1\t5\t1\tWeapon,Bow,Misc\tAny\t2\tfalse\t0\t0\t-2\r\nBronze\tTOHIT\t1\t5\t1\tWeapon,Bow,Misc\tAny\t2\ttrue\t100\t500\t2\r\nIron\tTOHIT\t6\t10\t4\tWeapon,Bow,Misc\tAny\t2\ttrue\t600\t1000\t3\r\nSteel\tTOHIT\t11\t15\t6\tWeapon,Bow,Misc\tAny\t2\ttrue\t1100\t1500\t5\r\nSilver\tTOHIT\t16\t20\t9\tWeapon,Bow,Misc\tGood\t2\ttrue\t1600\t2000\t7\r\nGold\tTOHIT\t21\t30\t12\tWeapon,Bow,Misc\tGood\t2\ttrue\t2100\t3000\t9\r\nPlatinum\tTOHIT\t31\t40\t16\tWeapon,Bow\tGood\t2\ttrue\t3100\t4000\t11\r\nMithril\tTOHIT\t41\t60\t20\tWeapon,Bow\tGood\t2\ttrue\t4100\t6000\t13\r\nMeteoric\tTOHIT\t61\t80\t23\tWeapon,Bow\tAny\t2\ttrue\t6100\t10000\t15\r\nWeird\tTOHIT\t81\t100\t35\tWeapon,Bow\tAny\t2\ttrue\t10100\t14000\t17\r\nStrange\tTOHIT\t101\t150\t60\tWeapon,Bow\tAny\t2\ttrue\t14100\t20000\t20\r\nUseless\tDAMP_CURSE\t100\t100\t5\tWeapon,Staff,Bow\tAny\t2\tfalse\t0\t0\t-8\r\nBent\tDAMP_CURSE\t50\t75\t3\tWeapon,Staff,Bow\tAny\t2\tfalse\t0\t0\t-4\r\nWeak\tDAMP_CURSE\t25\t45\t1\tWeapon,Staff,Bow\tAny\t2\tfalse\t0\t0\t-3\r\nJagged\tDAMP\t20\t35\t4\tWeapon,Staff,Bow\tAny\t2\ttrue\t250\t450\t3\r\nDeadly\tDAMP\t36\t50\t6\tWeapon,Staff,Bow\tAny\t2\ttrue\t500\t700\t4\r\nHeavy\tDAMP\t51\t65\t9\tWeapon,Staff,Bow\tAny\t2\ttrue\t750\t950\t5\r\nVicious\tDAMP\t66\t80\t12\tWeapon,Staff,Bow\tEvil\t2\ttrue\t1000\t1450\t8\r\nBrutal\tDAMP\t81\t95\t16\tWeapon,Staff,Bow\tAny\t2\ttrue\t1500\t1950\t10\r\nMassive\tDAMP\t96\t110\t20\tWeapon,Staff,Bow\tAny\t2\ttrue\t2000\t2450\t13\r\nSavage\tDAMP\t111\t125\t23\tWeapon,Bow\tAny\t2\ttrue\t2500\t3000\t15\r\nRuthless\tDAMP\t126\t150\t35\tWeapon,Bow\tAny\t2\ttrue\t10100\t15000\t17\r\nMerciless\tDAMP\t151\t175\t60\tWeapon,Bow\tAny\t2\ttrue\t15000\t20000\t20\r\nClumsy\tTOHIT_DAMP_CURSE\t50\t75\t5\tWeapon,Staff,Bow\tAny\t2\tfalse\t0\t0\t-7\r\nDull\tTOHIT_DAMP_CURSE\t25\t45\t1\tWeapon,Staff,Bow\tAny\t2\tfalse\t0\t0\t-5\r\nSharp\tTOHIT_DAMP\t20\t35\t1\tWeapon,Staff,Bow\tAny\t2\tfalse\t350\t950\t5\r\nFine\tTOHIT_DAMP\t36\t50\t6\tWeapon,Staff,Bow\tAny\t2\ttrue\t1100\t1700\t7\r\nWarrior's\tTOHIT_DAMP\t51\t65\t10\tWeapon,Staff,Bow\tAny\t2\ttrue\t1850\t2450\t13\r\nSoldier's\tTOHIT_DAMP\t66\t80\t15\tWeapon,Staff\tAny\t2\ttrue\t2600\t3950\t17\r\nLord's\tTOHIT_DAMP\t81\t95\t19\tWeapon,Staff\tAny\t2\ttrue\t4100\t5950\t21\r\nKnight's\tTOHIT_DAMP\t96\t110\t23\tWeapon,Staff\tAny\t2\ttrue\t6100\t8450\t26\r\nMaster's\tTOHIT_DAMP\t111\t125\t28\tWeapon,Staff\tAny\t2\ttrue\t8600\t13000\t30\r\nChampion's\tTOHIT_DAMP\t126\t150\t40\tWeapon,Staff\tAny\t2\ttrue\t15200\t24000\t33\r\nKing's\tTOHIT_DAMP\t151\t175\t28\tWeapon,Staff\tAny\t2\ttrue\t24100\t35000\t38\r\nVulnerable\tACP_CURSE\t51\t100\t3\tArmor,Shield\tAny\t2\tfalse\t0\t0\t-3\r\nRusted\tACP_CURSE\t25\t50\t1\tArmor,Shield\tAny\t2\tfalse\t0\t0\t-2\r\nFine\tACP\t20\t30\t1\tArmor,Shield\tAny\t2\ttrue\t20\t100\t2\r\nStrong\tACP\t31\t40\t3\tArmor,Shield\tAny\t2\ttrue\t120\t200\t3\r\nGrand\tACP\t41\t55\t6\tArmor,Shield\tAny\t2\ttrue\t220\t300\t5\r\nValiant\tACP\t56\t70\t10\tArmor,Shield\tAny\t2\ttrue\t320\t400\t7\r\nGlorious\tACP\t71\t90\t14\tArmor,Shield\tGood\t2\ttrue\t420\t600\t9\r\nBlessed\tACP\t91\t110\t19\tArmor,Shield\tGood\t2\ttrue\t620\t800\t11\r\nSaintly\tACP\t111\t130\t24\tArmor,Shield\tGood\t2\ttrue\t820\t1200\t13\r\nAwesome\tACP\t131\t150\t28\tArmor,Shield\tGood\t2\ttrue\t1220\t2000\t15\r\nHoly\tACP\t151\t170\t35\tArmor,Shield\tGood\t2\ttrue\t5200\t6000\t17\r\nGodly\tACP\t171\t200\t60\tArmor,Shield\tGood\t2\ttrue\t6200\t7000\t20\r\nRed\tFIRERES\t10\t20\t4\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t500\t1500\t2\r\nCrimson\tFIRERES\t21\t30\t10\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2100\t3000\t2\r\nCrimson\tFIRERES\t31\t40\t16\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3100\t4000\t2\r\nGarnet\tFIRERES\t41\t50\t20\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t8200\t12000\t3\r\nRuby\tFIRERES\t51\t60\t26\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t17100\t20000\t5\r\nBlue\tLIGHTRES\t10\t20\t4\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t500\t1500\t2\r\nAzure\tLIGHTRES\t21\t30\t10\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2100\t3000\t2\r\nLapis\tLIGHTRES\t31\t40\t16\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3100\t4000\t2\r\nCobalt\tLIGHTRES\t41\t50\t20\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t8200\t12000\t3\r\nSapphire\tLIGHTRES\t51\t60\t26\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t17100\t20000\t5\r\nWhite\tMAGICRES\t10\t20\t4\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t500\t1500\t2\r\nPearl\tMAGICRES\t21\t30\t10\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2100\t3000\t2\r\nIvory\tMAGICRES\t31\t40\t16\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3100\t4000\t2\r\nCrystal\tMAGICRES\t41\t50\t20\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t8200\t12000\t3\r\nDiamond\tMAGICRES\t51\t60\t26\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t17100\t20000\t5\r\nTopaz\tALLRES\t10\t15\t8\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2000\t5000\t3\r\nAmber\tALLRES\t16\t20\t12\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t7400\t10000\t3\r\nJade\tALLRES\t21\t30\t18\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t11000\t15000\t3\r\nObsidian\tALLRES\t31\t40\t24\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t24000\t40000\t4\r\nEmerald\tALLRES\t41\t50\t31\tShield,Weapon,Staff,Bow\tAny\t1\ttrue\t61000\t75000\t7\r\nHyena's\tMANA_CURSE\t11\t25\t4\tStaff,Misc\tAny\t1\tfalse\t100\t1000\t-2\r\nFrog's\tMANA_CURSE\t1\t10\t1\tStaff,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nSpider's\tMANA\t10\t15\t1\tStaff,Misc\tEvil\t1\ttrue\t500\t1000\t2\r\nRaven's\tMANA\t15\t20\t5\tStaff,Misc\tAny\t1\ttrue\t1100\t2000\t3\r\nSnake's\tMANA\t21\t30\t9\tStaff,Misc\tAny\t1\ttrue\t2100\t4000\t5\r\nSerpent's\tMANA\t30\t40\t15\tStaff,Misc\tAny\t1\ttrue\t4100\t6000\t7\r\nDrake's\tMANA\t41\t50\t21\tStaff,Misc\tAny\t1\ttrue\t6100\t10000\t9\r\nDragon's\tMANA\t51\t60\t27\tStaff,Misc\tAny\t1\ttrue\t10100\t15000\t11\r\nWyrm's\tMANA\t61\t80\t35\tStaff\tAny\t1\ttrue\t15100\t19000\t12\r\nHydra's\tMANA\t81\t100\t60\tStaff\tAny\t1\ttrue\t19100\t30000\t13\r\nAngel's\tSPLLVLADD\t1\t1\t15\tStaff\tGood\t1\ttrue\t25000\t25000\t2\r\nArch-Angel's\tSPLLVLADD\t2\t2\t25\tStaff\tGood\t1\ttrue\t50000\t50000\t3\r\nPlentiful\tCHARGES\t2\t2\t4\tStaff\tAny\t1\ttrue\t2000\t2000\t2\r\nBountiful\tCHARGES\t3\t3\t9\tStaff\tAny\t1\ttrue\t3000\t3000\t3\r\nFlaming\tFIREDAM\t1\t10\t7\tWeapon,Staff\tAny\t1\ttrue\t5000\t5000\t2\r\nLightning\tLIGHTDAM\t2\t20\t18\tWeapon,Staff\tAny\t1\ttrue\t10000\t10000\t2\r\nJester's\tJESTERS\t1\t1\t7\tWeapon\tAny\t1\ttrue\t1200\t1200\t3\r\nCrystalline\tCRYSTALLINE\t30\t70\t5\tWeapon\tAny\t1\ttrue\t1000\t3000\t3\r\nDoppelganger's\tDOPPELGANGER\t81\t95\t11\tWeapon,Staff\tAny\t1\ttrue\t2000\t2400\t10\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/items/item_suffixes.tsv",
    "content": "name\tpower\tpower.value1\tpower.value2\tminLevel\titemTypes\talignment\tchance\tuseful\tminVal\tmaxVal\tmultVal\r\nquality\tDAMMOD\t1\t2\t2\tWeapon,Staff,Bow\tAny\t1\ttrue\t100\t200\t2\r\nmaiming\tDAMMOD\t3\t5\t7\tWeapon,Staff,Bow\tAny\t1\ttrue\t1300\t1500\t3\r\nslaying\tDAMMOD\t6\t8\t15\tWeapon\tAny\t1\ttrue\t2600\t3000\t5\r\ngore\tDAMMOD\t9\t12\t25\tWeapon\tAny\t1\ttrue\t4100\t5000\t8\r\ncarnage\tDAMMOD\t13\t16\t35\tWeapon\tAny\t1\ttrue\t5100\t10000\t10\r\nslaughter\tDAMMOD\t17\t20\t60\tWeapon\tAny\t1\ttrue\t10100\t15000\t13\r\npain\tGETHIT_CURSE\t2\t4\t4\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-4\r\ntears\tGETHIT_CURSE\t1\t1\t2\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nhealth\tGETHIT\t1\t1\t2\tArmor,Shield,Misc\tGood\t1\ttrue\t200\t200\t2\r\nprotection\tGETHIT\t2\t2\t6\tArmor,Shield\tGood\t1\ttrue\t400\t800\t4\r\nabsorption\tGETHIT\t3\t3\t12\tArmor,Shield\tGood\t1\ttrue\t1001\t2500\t10\r\ndeflection\tGETHIT\t4\t4\t20\tArmor\tGood\t1\ttrue\t2500\t6500\t15\r\nosmosis\tGETHIT\t5\t6\t50\tArmor\tGood\t1\ttrue\t7500\t10000\t20\r\nfrailty\tSTR_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\nweakness\tSTR_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nstrength\tSTR\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t200\t1000\t2\r\nmight\tSTR\t6\t10\t5\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t1200\t2000\t3\r\npower\tSTR\t11\t15\t11\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t2200\t3000\t4\r\ngiants\tSTR\t16\t20\t17\tArmor,Weapon,Bow,Misc\tAny\t1\ttrue\t3200\t5000\t7\r\ntitans\tSTR\t21\t30\t23\tWeapon,Misc\tAny\t1\ttrue\t5200\t10000\t10\r\nparalysis\tDEX_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\natrophy\tDEX_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\ndexterity\tDEX\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t200\t1000\t2\r\nskill\tDEX\t6\t10\t5\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t1200\t2000\t3\r\naccuracy\tDEX\t11\t15\t11\tArmor,Shield,Weapon,Bow,Misc\tAny\t1\ttrue\t2200\t3000\t4\r\nprecision\tDEX\t16\t20\t17\tArmor,Weapon,Bow,Misc\tAny\t1\ttrue\t3200\t5000\t7\r\nperfection\tDEX\t21\t30\t23\tBow,Misc\tAny\t1\ttrue\t5200\t10000\t10\r\nthe fool\tMAG_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\ndyslexia\tMAG_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nmagic\tMAG\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t200\t1000\t2\r\nthe mind\tMAG\t6\t10\t5\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t1200\t2000\t3\r\nbrilliance\tMAG\t11\t15\t11\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t2200\t3000\t4\r\nsorcery\tMAG\t16\t20\t17\tArmor,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t3200\t5000\t7\r\nwizardry\tMAG\t21\t30\t23\tStaff,Misc\tAny\t1\ttrue\t5200\t10000\t10\r\nillness\tVIT_CURSE\t6\t10\t3\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\ndisease\tVIT_CURSE\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nvitality\tVIT\t1\t5\t1\tArmor,Shield,Weapon,Staff,Bow,Misc\tGood\t1\ttrue\t200\t1000\t2\r\nzest\tVIT\t6\t10\t5\tArmor,Shield,Weapon,Bow,Misc\tGood\t1\ttrue\t1200\t2000\t3\r\nvim\tVIT\t11\t15\t11\tArmor,Shield,Weapon,Bow,Misc\tGood\t1\ttrue\t2200\t3000\t4\r\nvigor\tVIT\t16\t20\t17\tArmor,Weapon,Bow,Misc\tGood\t1\ttrue\t3200\t5000\t7\r\nlife\tVIT\t21\t30\t23\tMisc\tGood\t1\ttrue\t5200\t10000\t10\r\ntrouble\tATTRIBS_CURSE\t6\t10\t12\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-10\r\nthe pit\tATTRIBS_CURSE\t1\t5\t5\tArmor,Shield,Weapon,Staff,Bow,Misc\tEvil\t1\tfalse\t0\t0\t-5\r\nthe sky\tATTRIBS\t1\t3\t5\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t800\t4000\t5\r\nthe moon\tATTRIBS\t4\t7\t11\tArmor,Shield,Weapon,Staff,Bow,Misc\tAny\t1\ttrue\t4800\t8000\t10\r\nthe stars\tATTRIBS\t8\t11\t17\tArmor,Weapon,Bow,Misc\tAny\t1\ttrue\t8800\t12000\t15\r\nthe heavens\tATTRIBS\t12\t15\t25\tWeapon,Bow,Misc\tAny\t1\ttrue\t12800\t20000\t20\r\nthe zodiac\tATTRIBS\t16\t20\t30\tMisc\tAny\t1\ttrue\t20800\t40000\t30\r\nthe vulture\tLIFE_CURSE\t11\t25\t4\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-4\r\nthe jackal\tLIFE_CURSE\t1\t10\t1\tArmor,Shield,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nthe fox\tLIFE\t10\t15\t1\tArmor,Shield,Misc\tAny\t1\ttrue\t100\t1000\t2\r\nthe jaguar\tLIFE\t16\t20\t5\tArmor,Shield,Misc\tAny\t1\ttrue\t1100\t2000\t3\r\nthe eagle\tLIFE\t21\t30\t9\tArmor,Shield,Misc\tAny\t1\ttrue\t2100\t4000\t5\r\nthe wolf\tLIFE\t30\t40\t15\tArmor,Shield,Misc\tAny\t1\ttrue\t4100\t6000\t7\r\nthe tiger\tLIFE\t41\t50\t21\tArmor,Shield,Misc\tAny\t1\ttrue\t6100\t10000\t9\r\nthe lion\tLIFE\t51\t60\t27\tArmor,Misc\tAny\t1\ttrue\t10100\t15000\t11\r\nthe mammoth\tLIFE\t61\t80\t35\tArmor\tAny\t1\ttrue\t15100\t19000\t12\r\nthe whale\tLIFE\t81\t100\t60\tArmor\tAny\t1\ttrue\t19100\t30000\t13\r\nfragility\tDUR_CURSE\t100\t100\t3\tArmor,Shield,Weapon\tEvil\t1\tfalse\t0\t0\t-4\r\nbrittleness\tDUR_CURSE\t26\t75\t1\tArmor,Shield,Weapon\tEvil\t1\tfalse\t0\t0\t-2\r\nsturdiness\tDUR\t26\t75\t1\tArmor,Shield,Weapon,Staff\tAny\t1\ttrue\t100\t100\t2\r\ncraftsmanship\tDUR\t51\t100\t6\tArmor,Shield,Weapon,Staff\tAny\t1\ttrue\t200\t200\t2\r\nstructure\tDUR\t101\t200\t12\tArmor,Shield,Weapon,Staff\tAny\t1\ttrue\t300\t300\t2\r\nthe ages\tINDESTRUCTIBLE\t\t\t25\tArmor,Shield,Weapon,Staff\tAny\t1\ttrue\t600\t600\t5\r\nthe dark\tLIGHT_CURSE\t4\t4\t6\tArmor,Weapon,Misc\tEvil\t1\tfalse\t0\t0\t-3\r\nthe night\tLIGHT_CURSE\t2\t2\t3\tArmor,Weapon,Misc\tEvil\t1\tfalse\t0\t0\t-2\r\nlight\tLIGHT\t2\t2\t4\tArmor,Weapon,Misc\tGood\t1\ttrue\t750\t750\t2\r\nradiance\tLIGHT\t4\t4\t8\tArmor,Weapon,Misc\tGood\t1\ttrue\t1500\t1500\t3\r\nflame\tFIRE_ARROWS\t1\t3\t1\tBow\tAny\t1\ttrue\t2000\t2000\t2\r\nfire\tFIRE_ARROWS\t1\t6\t11\tBow\tAny\t1\ttrue\t4000\t4000\t4\r\nburning\tFIRE_ARROWS\t1\t16\t35\tBow\tAny\t1\ttrue\t6000\t6000\t6\r\nshock\tLIGHT_ARROWS\t1\t6\t13\tBow\tAny\t1\ttrue\t6000\t6000\t2\r\nlightning\tLIGHT_ARROWS\t1\t10\t21\tBow\tAny\t1\ttrue\t8000\t8000\t4\r\nthunder\tLIGHT_ARROWS\t1\t20\t60\tBow\tAny\t1\ttrue\t12000\t12000\t6\r\nmany\tDUR\t100\t100\t3\tBow\tAny\t1\ttrue\t750\t750\t2\r\nplenty\tDUR\t200\t200\t7\tBow\tAny\t1\ttrue\t1500\t1500\t3\r\nthorns\tTHORNS\t1\t3\t1\tArmor,Shield\tAny\t1\ttrue\t500\t500\t2\r\ncorruption\tNOMANA\t\t\t5\tArmor,Shield,Weapon\tEvil\t1\tfalse\t-1000\t-1000\t2\r\nthieves\tABSHALFTRAP\t\t\t11\tArmor,Shield,Misc\tAny\t1\ttrue\t1500\t1500\t2\r\nthe bear\tKNOCKBACK\t\t\t5\tWeapon,Staff,Bow\tEvil\t1\ttrue\t750\t750\t2\r\nthe bat\tSTEALMANA\t3\t3\t8\tWeapon\tAny\t1\ttrue\t7500\t7500\t3\r\nvampires\tSTEALMANA\t5\t5\t19\tWeapon\tAny\t1\ttrue\t15000\t15000\t3\r\nthe leech\tSTEALLIFE\t3\t3\t8\tWeapon\tAny\t1\ttrue\t7500\t7500\t3\r\nblood\tSTEALLIFE\t5\t5\t19\tWeapon\tAny\t1\ttrue\t15000\t15000\t3\r\npiercing\tTARGAC\t1\t1\t1\tWeapon,Bow\tAny\t1\ttrue\t1000\t1000\t3\r\npuncturing\tTARGAC\t2\t2\t9\tWeapon,Bow\tAny\t1\ttrue\t2000\t2000\t6\r\nbashing\tTARGAC\t3\t3\t17\tWeapon\tAny\t1\ttrue\t4000\t4000\t12\r\nreadiness\tFASTATTACK\t1\t1\t1\tWeapon,Staff,Bow\tAny\t1\ttrue\t2000\t2000\t2\r\nswiftness\tFASTATTACK\t2\t2\t10\tWeapon,Staff,Bow\tAny\t1\ttrue\t4000\t4000\t4\r\nspeed\tFASTATTACK\t3\t3\t19\tWeapon,Staff\tAny\t1\ttrue\t8000\t8000\t8\r\nhaste\tFASTATTACK\t4\t4\t27\tWeapon,Staff\tAny\t1\ttrue\t16000\t16000\t16\r\nbalance\tFASTRECOVER\t1\t1\t1\tArmor,Misc\tAny\t1\ttrue\t2000\t2000\t2\r\nstability\tFASTRECOVER\t2\t2\t10\tArmor,Misc\tAny\t1\ttrue\t4000\t4000\t4\r\nharmony\tFASTRECOVER\t3\t3\t20\tArmor,Misc\tAny\t1\ttrue\t8000\t8000\t8\r\nblocking\tFASTBLOCK\t1\t1\t5\tShield\tAny\t1\ttrue\t4000\t4000\t4\r\ndevastation\tDEVASTATION\t1\t1\t1\tWeapon,Staff,Bow\tAny\t1\ttrue\t1200\t1200\t3\r\ndecay\tDECAY\t150\t250\t1\tWeapon,Staff,Bow\tAny\t1\ttrue\t200\t200\t2\r\nperil\tPERIL\t1\t1\t5\tWeapon,Staff,Bow\tAny\t1\ttrue\t500\t500\t1\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/items/unique_itemdat.tsv",
    "content": "name\tcursorGraphic\tuniqueBaseItem\tminLevel\tvalue\tpower0\tpower0.value1\tpower0.value2\tpower1\tpower1.value1\tpower1.value2\tpower2\tpower2.value1\tpower2.value2\tpower3\tpower3.value1\tpower3.value2\tpower4\tpower4.value1\tpower4.value2\tpower5\tpower5.value1\tpower5.value2\r\nThe Butcher's Cleaver\t\tCLEAVER\t1\t3650\tSTR\t10\t10\tSETDAM\t4\t24\tSETDUR\t10\t10\t\t\t\t\t\t\t\t\t\r\nThe Undead Crown\tHELM_OF_SPIRITS\tSKCROWN\t1\t16650\tRNDSTEALLIFE\t\t\tSETAC\t8\t8\t\t\t\t\t\t\t\t\t\t\t\t\r\nEmpyrean Band\t\tINFRARING\t1\t8000\tATTRIBS\t2\t2\tLIGHT\t2\t2\tFASTRECOVER\t1\t1\tABSHALFTRAP\t\t\t\t\t\t\t\t\r\nOptic Amulet\t\tOPTAMULET\t1\t9750\tLIGHT\t2\t2\tLIGHTRES\t20\t20\tGETHIT\t1\t1\tMAG\t5\t5\t\t\t\t\t\t\r\nRing of Truth\t\tTRING\t1\t9100\tLIFE\t10\t10\tGETHIT\t1\t1\tALLRES\t10\t10\t\t\t\t\t\t\t\t\t\r\nHarlequin Crest\t\tHARCREST\t1\t4000\tAC_CURSE\t3\t3\tGETHIT\t1\t1\tATTRIBS\t2\t2\tLIFE\t7\t7\tMANA\t7\t7\t\t\t\r\nVeil of Steel\t\tSTEELVEIL\t1\t63800\tALLRES\t50\t50\tLIGHT_CURSE\t2\t2\tACP\t60\t60\tMANA_CURSE\t30\t30\tSTR\t15\t15\tVIT\t15\t15\r\nArkaine's Valor\t\tARMOFVAL\t1\t42000\tSETAC\t25\t25\tVIT\t10\t10\tGETHIT\t3\t3\tFASTRECOVER\t3\t3\t\t\t\t\t\t\r\nGriswold's Edge\t\tGRISWOLD\t1\t42000\tFIREDAM\t1\t10\tTOHIT\t25\t25\tFASTATTACK\t2\t2\tKNOCKBACK\t\t\tMANA\t20\t20\tLIFE_CURSE\t20\t20\r\nBovine Plate\t\tBOVINE\t1\t400\tSETAC\t150\t150\tINDESTRUCTIBLE\t\t\tLIGHT\t5\t5\tALLRES\t30\t30\tMANA_CURSE\t50\t50\tSPLLVLADD\t-2\t-2\r\nThe Rift Bow\t\tSHORTBOW\t1\t1800\tRNDARROWVEL\t\t\tDAMMOD\t2\t2\tDEX_CURSE\t3\t3\t\t\t\t\t\t\t\t\t\r\nThe Needler\tTHE_NEEDLER\tSHORTBOW\t2\t8900\tTOHIT\t50\t50\tSETDAM\t1\t3\tFASTATTACK\t2\t2\t\t\t\t\t\t\t\t\t\r\nThe Celestial Bow\tCOMPOSITE_BOW\tLONGBOW\t2\t1200\tNOMINSTR\t\t\tDAMMOD\t2\t2\tSETAC\t5\t5\t\t\t\t\t\t\t\t\t\r\nDeadly Hunter\tDEADLY_HUNTER\tCOMPBOW\t3\t8750\t3XDAMVDEM\t\t\tTOHIT\t20\t20\tMAG_CURSE\t5\t5\t\t\t\t\t\t\t\t\t\r\nBow of the Dead\tDEADLY_HUNTER\tCOMPBOW\t5\t2500\tTOHIT\t10\t10\tDEX\t4\t4\tVIT_CURSE\t3\t3\tLIGHT_CURSE\t2\t2\tSETDUR\t30\t30\t\t\t\r\nThe Blackoak Bow\t\tLONGBOW\t5\t2500\tDEX\t10\t10\tVIT_CURSE\t10\t10\tDAMP\t50\t50\tLIGHT_CURSE\t1\t1\t\t\t\t\t\t\r\nFlamedart\t\tHUNTBOW\t10\t14250\tFIRE_ARROWS\t1\t6\tTOHIT\t20\t20\tFIRERES\t40\t40\t\t\t\t\t\t\t\t\t\r\nFleshstinger\t\tLONGBOW\t13\t16500\tDEX\t15\t15\tTOHIT\t40\t40\tDAMP\t80\t80\tDUR\t6\t6\t\t\t\t\t\t\r\nWindforce\tWINDFORCE\tWARBOW\t17\t37750\tSTR\t5\t5\tDAMP\t200\t200\tKNOCKBACK\t\t\t\t\t\t\t\t\t\t\t\r\nEaglehorn\tDEADLY_HUNTER\tBATTLEBOW\t26\t42500\tDEX\t20\t20\tTOHIT\t50\t50\tDAMP\t100\t100\tINDESTRUCTIBLE\t\t\t\t\t\t\t\t\r\nGonnagal's Dirk\tGONNAGALS_DIRK\tDAGGER\t1\t7040\tDEX_CURSE\t5\t5\tDAMMOD\t4\t4\tFASTATTACK\t2\t2\tFIRERES\t25\t25\t\t\t\t\t\t\r\nThe Defender\t\tSABRE\t1\t2000\tSETAC\t5\t5\tVIT\t5\t5\tTOHIT_CURSE\t5\t5\t\t\t\t\t\t\t\t\t\r\nGryphon's Claw\tGRYPHONS_CLAW\tFALCHION\t1\t1000\tDAMP\t100\t100\tMAG_CURSE\t2\t2\tDEX_CURSE\t5\t5\t\t\t\t\t\t\t\t\t\r\nBlack Razor\tBLACK_RAZOR\tDAGGER\t1\t2000\tDAMP\t150\t150\tVIT\t2\t2\tSETDUR\t5\t5\t\t\t\t\t\t\t\t\t\r\nGibbous Moon\t\tBROADSWR\t2\t6660\tATTRIBS\t2\t2\tDAMP\t25\t25\tMANA\t15\t15\tLIGHT_CURSE\t3\t3\t\t\t\t\t\t\r\nIce Shank\t\tLONGSWR\t3\t5250\tFIRERES\t40\t40\tSETDUR\t15\t15\tSTR\t5\t10\t\t\t\t\t\t\t\t\t\r\nThe Executioner's Blade\tTHE_EXECUTIONERS_BLADE\tFALCHION\t3\t7080\tDAMP\t150\t150\tLIFE_CURSE\t10\t10\tLIGHT_CURSE\t1\t1\tDUR\t200\t200\t\t\t\t\t\t\r\nThe Bonesaw\t\tCLAYMORE\t6\t4400\tDAMMOD\t10\t10\tSTR\t10\t10\tMAG_CURSE\t5\t5\tDEX_CURSE\t5\t5\tLIFE\t10\t10\tMANA_CURSE\t10\t10\r\nShadowhawk\t\tBROADSWR\t8\t13750\tLIGHT_CURSE\t2\t2\tSTEALLIFE\t5\t5\tTOHIT\t15\t15\tALLRES\t5\t5\t\t\t\t\t\t\r\nWizardspike\tWIZARDSPIKE\tDAGGER\t11\t12920\tMAG\t15\t15\tMANA\t35\t35\tTOHIT\t25\t25\tALLRES\t15\t15\t\t\t\t\t\t\r\nLightsabre\t\tSABRE\t13\t19150\tLIGHT\t2\t2\tLIGHTDAM\t1\t10\tTOHIT\t20\t20\tLIGHTRES\t50\t50\t\t\t\t\t\t\r\nThe Falcon's Talon\tGRYPHONS_CLAW\tSCIMITAR\t15\t7867\tFASTATTACK\t4\t4\tTOHIT\t20\t20\tDAMP_CURSE\t33\t33\tDEX\t10\t10\t\t\t\t\t\t\r\nInferno\t\tLONGSWR\t17\t34600\tFIREDAM\t2\t12\tLIGHT\t3\t3\tMANA\t20\t20\tFIRERES\t80\t80\t\t\t\t\t\t\r\nDoombringer\t\tBASTARDSWR\t19\t18250\tTOHIT\t25\t25\tDAMP\t250\t250\tATTRIBS_CURSE\t5\t5\tLIFE_CURSE\t25\t25\tLIGHT_CURSE\t2\t2\t\t\t\r\nThe Grizzly\tTHE_GRIZZLY\tTWOHANDSWR\t23\t50000\tSTR\t20\t20\tVIT_CURSE\t5\t5\tDAMP\t200\t200\tKNOCKBACK\t\t\tDUR\t100\t100\t\t\t\r\nThe Grandfather\tTHE_GRANDFATHER\tGREATSWR\t27\t119800\tONEHAND\t\t\tATTRIBS\t5\t5\tTOHIT\t20\t20\tDAMP\t70\t70\tLIFE\t20\t20\t\t\t\r\nThe Mangler\tAXE\tLARGEAXE\t2\t2850\tDAMP\t200\t200\tDEX_CURSE\t5\t5\tMAG_CURSE\t5\t5\tMANA_CURSE\t10\t10\t\t\t\t\t\t\r\nSharp Beak\tGREAT_AXE\tLARGEAXE\t2\t2850\tLIFE\t20\t20\tMAG_CURSE\t10\t10\tMANA_CURSE\t10\t10\t\t\t\t\t\t\t\t\t\r\nBloodSlayer\tAXE\tBROADAXE\t3\t2500\tDAMP\t100\t100\t3XDAMVDEM\t\t\tATTRIBS_CURSE\t5\t5\tSPLLVLADD\t-1\t-1\t\t\t\t\t\t\r\nThe Celestial Axe\t\tBATTLEAXE\t4\t14100\tNOMINSTR\t\t\tTOHIT\t15\t15\tLIFE\t15\t15\tSTR_CURSE\t15\t15\t\t\t\t\t\t\r\nWicked Axe\tGREAT_AXE\tLARGEAXE\t5\t31150\tTOHIT\t30\t30\tDEX\t10\t10\tVIT_CURSE\t10\t10\tGETHIT\t1\t6\tINDESTRUCTIBLE\t\t\t\t\t\r\nStonecleaver\tSTONECLEAVER\tBROADAXE\t7\t23900\tLIFE\t30\t30\tTOHIT\t20\t20\tDAMP\t50\t50\tLIGHTRES\t40\t40\t\t\t\t\t\t\r\nAguinara's Hatchet\t\tSMALLAXE\t12\t24800\tSPLLVLADD\t1\t1\tMAG\t10\t10\tMAGICRES\t80\t80\t\t\t\t\t\t\t\t\t\r\nHellslayer\t\tBATTLEAXE\t15\t26200\tSTR\t8\t8\tVIT\t8\t8\tDAMP\t100\t100\tLIFE\t25\t25\tMANA_CURSE\t25\t25\t\t\t\r\nMesserschmidt's Reaver\tMESSERSCHMIDTS_REAVER\tGREATAXE\t25\t58000\tDAMP\t200\t200\tDAMMOD\t15\t15\tATTRIBS\t5\t5\tLIFE_CURSE\t50\t50\tFIREDAM\t2\t12\t\t\t\r\nCrackrust\t\tMACE\t1\t11375\tATTRIBS\t2\t2\tINDESTRUCTIBLE\t\t\tALLRES\t15\t15\tDAMP\t50\t50\tSPLLVLADD\t-1\t-1\t\t\t\r\nHammer of Jholm\t\tMAUL\t1\t8700\tSETDAM\t4\t10\tINDESTRUCTIBLE\t\t\tSTR\t3\t3\tTOHIT\t15\t15\t\t\t\t\t\t\r\nCiverb's Cudgel\t\tMACE\t1\t2000\t3XDAMVDEM\t\t\tDEX_CURSE\t5\t5\tMAG_CURSE\t2\t2\t\t\t\t\t\t\t\t\t\r\nThe Celestial Star\t\tFLAIL\t2\t7810\tNOMINSTR\t\t\tLIGHT\t2\t2\tDAMMOD\t10\t10\tAC_CURSE\t8\t8\t\t\t\t\t\t\r\nBaranar's Star\t\tMORNSTAR\t5\t6850\tTOHIT\t12\t12\tDAMP\t80\t80\tFASTATTACK\t1\t1\tVIT\t4\t4\tDEX_CURSE\t4\t4\tSETDUR\t60\t60\r\nGnarled Root\t\tSPIKCLUB\t9\t9820\tTOHIT\t20\t20\tDAMP\t300\t300\tDEX\t10\t10\tMAG\t5\t5\tALLRES\t10\t10\tAC_CURSE\t10\t10\r\nThe Cranium Basher\t\tMAUL\t12\t36500\tDAMMOD\t20\t20\tSTR\t15\t15\tINDESTRUCTIBLE\t\t\tMANA_CURSE\t150\t150\tALLRES\t5\t5\t\t\t\r\nSchaefer's Hammer\t\tWARHAMMER\t16\t56125\tDAMP_CURSE\t100\t100\tLIGHTDAM\t1\t50\tLIFE\t50\t50\tTOHIT\t30\t30\tLIGHTRES\t80\t80\tLIGHT\t1\t1\r\nDreamflange\t\tMACE\t26\t26450\tMAG\t30\t30\tMANA\t50\t50\tMAGICRES\t50\t50\tLIGHT\t2\t2\tSPLLVLADD\t1\t1\t\t\t\r\nStaff of Shadows\t\tLONGSTAFF\t2\t1250\tMAG_CURSE\t10\t10\tTOHIT\t10\t10\tDAMP\t60\t60\tLIGHT_CURSE\t2\t2\tFASTATTACK\t1\t1\t\t\t\r\nImmolator\t\tLONGSTAFF\t4\t3900\tFIRERES\t20\t20\tFIREDAM\t4\t4\tMANA\t10\t10\tVIT_CURSE\t5\t5\t\t\t\t\t\t\r\nStorm Spire\t\tWARSTAFF\t8\t22500\tLIGHTRES\t50\t50\tLIGHTDAM\t2\t8\tSTR\t10\t10\tMAG_CURSE\t10\t10\t\t\t\t\t\t\r\nGleamsong\t\tSHORTSTAFF\t8\t6520\tMANA\t25\t25\tSTR_CURSE\t3\t3\tVIT_CURSE\t3\t3\tSPELL\t10\t76\t\t\t\t\t\t\r\nThundercall\t\tCOMPSTAFF\t14\t22250\tTOHIT\t35\t35\tLIGHTDAM\t1\t10\tSPELL\t3\t76\tLIGHTRES\t30\t30\tLIGHT\t2\t2\t\t\t\r\nThe Protector\tTHE_PROTECTOR\tSHORTSTAFF\t16\t17240\tVIT\t5\t5\tGETHIT\t5\t5\tSETAC\t40\t40\tSPELL\t2\t86\tTHORNS\t1\t3\t\t\t\r\nNaj's Puzzler\t\tLONGSTAFF\t18\t34000\tMAG\t20\t20\tDEX\t10\t10\tALLRES\t20\t20\tSPELL\t23\t57\tLIFE_CURSE\t25\t25\t\t\t\r\nMindcry\t\tQUARSTAFF\t20\t41500\tMAG\t15\t15\tSPELL\t13\t69\tALLRES\t15\t15\tSPLLVLADD\t1\t1\t\t\t\t\t\t\r\nRod of Onan\t\tWARSTAFF\t22\t44167\tSPELL\t21\t50\tDAMP\t100\t100\tATTRIBS\t5\t5\t\t\t\t\t\t\t\t\t\r\nHelm of Spirits\tHELM_OF_SPIRITS\tHELM\t1\t7525\tSTEALLIFE\t5\t5\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nThinking Cap\tTHINKING_CAP\tSKULLCAP\t6\t2020\tMANA\t30\t30\tSPLLVLADD\t2\t2\tALLRES\t20\t20\tSETDUR\t1\t1\t\t\t\t\t\t\r\nOverLord's Helm\tOVERLORDS_HELM\tHELM\t7\t12500\tSTR\t20\t20\tDEX\t15\t15\tVIT\t5\t5\tMAG_CURSE\t20\t20\tSETDUR\t15\t15\t\t\t\r\nFool's Crest\tFOOLS_CREST\tHELM\t12\t10150\tATTRIBS_CURSE\t4\t4\tLIFE\t100\t100\tGETHIT_CURSE\t1\t6\tTHORNS\t1\t3\t\t\t\t\t\t\r\nGotterdamerung\tVEIL_OF_STEEL\tGREATHELM\t21\t54900\tATTRIBS\t20\t20\tSETAC\t60\t60\tGETHIT\t4\t4\tALLRESZERO\t\t\tLIGHT_CURSE\t4\t4\t\t\t\r\nRoyal Circlet\tROYAL_CIRCLET\tCROWN\t27\t24875\tATTRIBS\t10\t10\tMANA\t40\t40\tSETAC\t40\t40\tLIGHT\t1\t1\t\t\t\t\t\t\r\nTorn Flesh of Souls\tTORN_FLESH_OF_SOULS\tRAGS\t2\t4825\tSETAC\t8\t8\tVIT\t10\t10\tGETHIT\t1\t1\tINDESTRUCTIBLE\t\t\t\t\t\t\t\t\r\nThe Gladiator's Bane\t\tSTUDARMOR\t6\t3450\tSETAC\t25\t25\tGETHIT\t2\t2\tDUR\t200\t200\tATTRIBS_CURSE\t3\t3\t\t\t\t\t\t\r\nThe Rainbow Cloak\tTHE_RAINBOW_CLOAK\tCLOAK\t2\t4900\tSETAC\t10\t10\tATTRIBS\t1\t1\tALLRES\t10\t10\tLIFE\t5\t5\tDUR\t50\t50\t\t\t\r\nLeather of Aut\t\tLEATHARMOR\t4\t10550\tSETAC\t15\t15\tSTR\t5\t5\tMAG_CURSE\t5\t5\tDEX\t5\t5\tINDESTRUCTIBLE\t\t\t\t\t\r\nWisdom's Wrap\tTHE_RAINBOW_CLOAK\tROBE\t5\t6200\tMAG\t5\t5\tMANA\t10\t10\tLIGHTRES\t25\t25\tSETAC\t15\t15\tGETHIT\t1\t1\t\t\t\r\nSparking Mail\t\tCHAINMAIL\t9\t15750\tSETAC\t30\t30\tLIGHTDAM\t1\t10\t\t\t\t\t\t\t\t\t\t\t\t\r\nScavenger Carapace\t\tBREASTPLATE\t13\t14000\tGETHIT\t15\t15\tAC_CURSE\t30\t30\tDEX\t5\t5\tLIGHTRES\t40\t40\t\t\t\t\t\t\r\nNightscape\tTHE_RAINBOW_CLOAK\tCAPE\t16\t11600\tFASTRECOVER\t2\t2\tLIGHT_CURSE\t4\t4\tSETAC\t15\t15\tDEX\t3\t3\tALLRES\t20\t20\t\t\t\r\nNaj's Light Plate\tNAJS_LIGHT_PLATE\tPLATEMAIL\t19\t78700\tNOMINSTR\t\t\tMAG\t5\t5\tMANA\t20\t20\tALLRES\t20\t20\tSPLLVLADD\t1\t1\t\t\t\r\nDemonspike Coat\t\tFULLPLATE\t25\t251175\tSETAC\t100\t100\tGETHIT\t6\t6\tSTR\t10\t10\tINDESTRUCTIBLE\t\t\tFIRERES\t50\t50\t\t\t\r\nThe Deflector\t\tBUCKLER\t1\t1500\tSETAC\t7\t7\tALLRES\t10\t10\tDAMP_CURSE\t20\t20\tTOHIT_CURSE\t5\t5\t\t\t\t\t\t\r\nSplit Skull Shield\tSPLIT_SKULL_SHIELD\tBUCKLER\t1\t2025\tSETAC\t10\t10\tLIFE\t10\t10\tSTR\t2\t2\tLIGHT_CURSE\t1\t1\tSETDUR\t15\t15\t\t\t\r\nDragon's Breach\tDRAGONS_BREACH\tKITESHIELD\t2\t19200\tFIRERES\t25\t25\tSTR\t5\t5\tSETAC\t20\t20\tMAG_CURSE\t5\t5\tINDESTRUCTIBLE\t\t\t\t\t\r\nBlackoak Shield\tBLACKOAK_SHIELD\tSMALLSHIELD\t4\t5725\tDEX\t10\t10\tVIT_CURSE\t10\t10\tSETAC\t18\t18\tLIGHT_CURSE\t1\t1\tDUR\t150\t150\t\t\t\r\nHoly Defender\tBLACKOAK_SHIELD\tLARGESHIELD\t10\t13800\tSETAC\t15\t15\tGETHIT\t2\t2\tFIRERES\t20\t20\tDUR\t200\t200\tFASTBLOCK\t1\t1\t\t\t\r\nStormshield\tGOTHIC_SHIELD\tGOTHSHIELD\t24\t49000\tSETAC\t40\t40\tGETHIT_CURSE\t4\t4\tSTR\t10\t10\tINDESTRUCTIBLE\t\t\tFASTBLOCK\t1\t1\tLIGHTRES\t50\t50\r\nBramble\tBRAMBLE\tRING\t1\t1000\tATTRIBS_CURSE\t2\t2\tDAMMOD\t3\t3\tMANA\t10\t10\t\t\t\t\t\t\t\t\t\r\nRing of Regha\tRING_OF_REGHA\tRING\t1\t4175\tMAG\t10\t10\tMAGICRES\t10\t10\tLIGHT\t1\t1\tSTR_CURSE\t3\t3\tDEX_CURSE\t3\t3\t\t\t\r\nThe Bleeder\tTHE_BLEEDER\tRING\t2\t8500\tMAGICRES\t20\t20\tMANA\t30\t30\tLIFE_CURSE\t10\t10\t\t\t\t\t\t\t\t\t\r\nConstricting Ring\tCONSTRICTING_RING\tRING\t5\t62000\tALLRES\t75\t75\tDRAINLIFE\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nRing of Engagement\tRING_OF_ENGAGEMENT\tRING\t11\t12476\tGETHIT\t1\t2\tTHORNS\t1\t3\tSETAC\t5\t5\tTARGAC\t2\t2\t\t\t\t\t\t\r\nGiant's Knuckle\tGIANTS_KNUCKLE\tRING\t8\t8000\tSTR\t60\t60\tDEX_CURSE\t30\t30\t\t\t\t\t\t\t\t\t\t\t\t\r\nMercurial Ring\tMERCURIAL_RING\tRING\t8\t8000\tDEX\t60\t60\tSTR_CURSE\t30\t30\t\t\t\t\t\t\t\t\t\t\t\t\r\nXorine's Ring\tXORINES_RING\tRING\t8\t8000\tMAG\t60\t60\tSTR_CURSE\t30\t30\t\t\t\t\t\t\t\t\t\t\t\t\r\nKarik's Ring\tKARIKS_RING\tRING\t8\t8000\tVIT\t60\t60\tMAG_CURSE\t30\t30\t\t\t\t\t\t\t\t\t\t\t\t\r\nRing of Magma\tRING_OF_MAGMA\tRING\t8\t8000\tFIRERES\t60\t60\tLIGHTRES_CURSE\t30\t30\tMAGICRES_CURSE\t30\t30\t\t\t\t\t\t\t\t\t\r\nRing of the Mystics\tRING_OF_THE_MYSTICS\tRING\t8\t8000\tMAGICRES\t60\t60\tFIRERES_CURSE\t30\t30\tLIGHTRES_CURSE\t30\t30\t\t\t\t\t\t\t\t\t\r\nRing of Thunder\tRING_OF_THUNDER\tRING\t8\t8000\tLIGHTRES\t60\t60\tFIRERES_CURSE\t30\t30\tMAGICRES_CURSE\t30\t30\t\t\t\t\t\t\t\t\t\r\nAmulet of Warding\tAMULET_OF_WARDING\tAMULET\t12\t30000\tALLRES\t40\t40\tLIFE_CURSE\t100\t100\t\t\t\t\t\t\t\t\t\t\t\t\r\nGnat Sting\tGNAT_STING\tHUNTBOW\t15\t30000\tMULT_ARROWS\t3\t3\tSETDAM\t1\t2\tFASTATTACK\t1\t1\tINDESTRUCTIBLE\t\t\t\t\t\t\t\t\r\nFlambeau\tFLAMBEAU\tCOMPBOW\t11\t30000\tFIREBALL\t15\t20\tSETDAM\t0\t0\tINDESTRUCTIBLE\t\t\t\t\t\t\t\t\t\t\t\r\nArmor of Gloom\tARMOR_OF_GLOOM\tFULLPLATE\t25\t200000\tNOMINSTR\t\t\tSETAC\t225\t225\tALLRESZERO\t\t\tLIGHT_CURSE\t2\t2\t\t\t\t\t\t\r\nBlitzen\tBLITZEN\tCOMPBOW\t13\t30000\tADDACLIFE\t10\t15\tSETDAM\t0\t0\tINDESTRUCTIBLE\t\t\t\t\t\t\t\t\t\t\t\r\nThunderclap\tTHUNDERCLAP\tWARHAMMER\t13\t30000\tADDMANAAC\t3\t6\tSTR\t20\t20\tLIGHTRES\t30\t30\tLIGHT\t2\t2\tINDESTRUCTIBLE\t\t\t\t\t\r\nShirotachi\t\tGREATSWR\t21\t36000\tONEHAND\t\t\tFASTATTACK\t4\t4\tTARGAC\t2\t2\tLIGHTDAM\t6\t6\t\t\t\t\t\t\r\nEater of Souls\tEATER_OF_SOULS\tTWOHANDSWR\t23\t42000\tINDESTRUCTIBLE\t\t\tLIFE\t50\t50\tSTEALLIFE\t5\t5\tSTEALMANA\t5\t5\tDRAINLIFE\t\t\t\t\t\r\nDiamondedge\tDIAMONDEDGE\tLONGSWR\t17\t42000\tSETDUR\t10\t10\tTOHIT\t50\t50\tDAMP\t100\t100\tLIGHTRES\t50\t50\tSETAC\t10\t10\t\t\t\r\nBone Chain Armor\tBONE_CHAIN_ARMOR\tCHAINMAIL\t13\t36000\tSETAC\t40\t40\tACUNDEAD\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nDemon Plate Armor\tDEMON_PLATE_ARMOR\tFULLPLATE\t25\t80000\tSETAC\t80\t80\tACDEMON\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nAcolyte's Amulet\tACOLYTES_AMULET\tAMULET\t10\t10000\tMANATOLIFE\t50\t50\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\nGladiator's Ring\tGLADIATORS_RING\tRING\t10\t10000\tLIFETOMANA\t40\t40\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/missiles/misdat.tsv",
    "content": "id\taddFn\tprocessFn\tcastSound\thitSound\tgraphic\tflags\tmovementDistribution\r\nArrow\tAddArrow\tProcessArrow\t\t\tArrow\tPhysical,Arrow\tBlockable\r\nFirebolt\tAddFirebolt\tProcessGenericProjectile\tSpellFirebolt\tSpellFireHit\tFireball\tFire\tBlockable\r\nGuardian\tAddGuardian\tProcessGuardian\tSpellGuardian\t\tGuardian\tPhysical\t\r\nPhasing\tAddPhasing\tProcessTeleport\tSpellTeleport\t\t\tPhysical,Invisible\t\r\nNovaBall\tAddNovaBall\tProcessNovaBall\t\t\tLightning\tLightning\tUnblockable\r\nFireWall\tAddFireWall\tProcessFireWall\tSpellFireWall\tSpellFireHit\tFireWall\tFire\t\r\nFireball\tAddFireball\tProcessFireball\tSpellFirebolt\tSpellFireHit\tFireball\tFire\tBlockable\r\nLightningControl\tAddLightningControl\tProcessLightningControl\t\t\tLightning\tLightning,Invisible\t\r\nLightning\tAddLightning\tProcessLightning\tSpellLightning\tSpellLightningHit\tLightning\tLightning\t\r\nMagmaBallExplosion\tAddMissileExplosion\tProcessMissileExplosion\t\t\tMagmaBallExplosion\tPhysical\t\r\nTownPortal\tAddTownPortal\tProcessTownPortal\tSpellPortal\t\tTownPortal\tMagic\t\r\nFlashBottom\tAddFlashBottom\tProcessFlashBottom\tSpellNova\tSpellLightningHit\tFlashBottom\tMagic\t\r\nFlashTop\tAddFlashTop\tProcessFlashTop\t\t\tFlashTop\tMagic\t\r\nManaShield\tAddManaShield\t\tSpellManaShield\t\tManaShield\tMagic,Invisible\t\r\nFlameWave\tAddFlameWave\tProcessFlameWave\t\t\tFireWall\tFire\tUnblockable\r\nChainLightning\tAddChainLightning\tProcessChainLightning\tSpellLightning\tSpellLightningHit\tLightning\tLightning\t\r\nChainBall\t\t\t\t\tLightning\tLightning\t\r\nBloodHit\t\t\tSpellBloodStar\tSpellBloodStarHit\tBloodHit\tPhysical\t\r\nBoneHit\t\t\t\t\tBoneHit\tPhysical\t\r\nMetalHit\t\t\t\t\tMetalHit\tPhysical\t\r\nRhino\tAddRhino\tProcessRhino\t\t\t\tPhysical\tBlockable\r\nMagmaBall\tAddMagmaBall\tProcessGenericProjectile\t\t\tMagmaBall\tFire\tBlockable\r\nThinLightningControl\tAddLightningControl\tProcessLightningControl\t\t\tThinLightning\tLightning,Invisible\t\r\nThinLightning\tAddLightning\tProcessLightning\t\t\tThinLightning\tLightning\t\r\nBloodStar\tAddGenericMagicMissile\tProcessGenericProjectile\t\t\tBloodStar\tMagic\tBlockable\r\nBloodStarExplosion\tAddMissileExplosion\tProcessMissileExplosion\t\t\tBloodStarExplosion\tMagic\t\r\nTeleport\tAddTeleport\tProcessTeleport\tSpellElemental\t\t\tPhysical,Invisible\t\r\nFireArrow\tAddElementalArrow\tProcessElementalArrow\t\t\tFireArrow\tFire,Arrow\tBlockable\r\nDoomSerpents\t\t\tSpellDoomSerpents\t\tDoomSerpents\tMagic,Invisible\t\r\nFireOnly\t\t\t\t\tFireWall\tFire\t\r\nStoneCurse\tAddStoneCurse\tProcessStoneCurse\tSpellStoneCurse\t\t\tMagic,Invisible\t\r\nBloodRitual\t\t\t\t\t\tPhysical\t\r\nInvisibility\t\t\tSpellInvisibility\t\t\tPhysical,Invisible\t\r\nGolem\tAddGolem\t\tSpellGolem\t\t\tPhysical,Invisible\t\r\nEtherealize\t\t\tSpellEtherealize\t\tEtherealize\tPhysical\t\r\nSpurt\t\t\t\t\tSpurt\tPhysical\t\r\nApocalypseBoom\tAddApocalypseBoom\tProcessApocalypseBoom\t\t\tApocalypseBoom\tPhysical\t\r\nHealing\tAddHealing\t\t\t\t\tPhysical,Invisible\t\r\nFireWallControl\tAddWallControl\tProcessWallControl\t\t\tFireWall\tFire,Invisible\t\r\nInfravision\tAddInfravision\tProcessInfravision\tSpellInfravision\t\t\tPhysical,Invisible\t\r\nIdentify\tAddIdentify\t\t\t\t\tPhysical,Invisible\t\r\nFlameWaveControl\tAddFlameWaveControl\tProcessFlameWaveControl\tSpellFlameWave\t\tFireWall\tFire\t\r\nNova\tAddNova\tProcessNova\tSpellNova\t\tLightning\tLightning\t\r\nRage\tAddRage\tProcessRage\t\t\t\tPhysical,Invisible\t\r\nApocalypse\tAddApocalypse\tProcessApocalypse\tSpellApocalypse\t\tApocalypseBoom\tMagic\t\r\nItemRepair\tAddItemRepair\t\t\t\t\tPhysical,Invisible\t\r\nStaffRecharge\tAddStaffRecharge\t\t\t\t\tPhysical,Invisible\t\r\nTrapDisarm\tAddTrapDisarm\t\tSpellTrapDisarm\t\t\tPhysical,Invisible\t\r\nInferno\tAddInferno\tProcessInferno\tSpellInferno\t\tInferno\tFire\t\r\nInfernoControl\tAddInfernoControl\tProcessInfernoControl\t\t\t\tFire,Invisible\t\r\nFireMan\t\t\t\t\t\tPhysical\tBlockable\r\nKrull\t\t\t\t\tKrull\tFire,Arrow\tBlockable\r\nChargedBolt\tAddChargedBolt\tProcessChargedBolt\tSpellChargedBolt\t\tChargedBolt\tLightning\tBlockable\r\nHolyBolt\tAddHolyBolt\tProcessHolyBolt\tSpellHolyBolt\tSpellLightningHit\tHolyBolt\tPhysical\tBlockable\r\nResurrect\tAddResurrect\t\t\tSpellResurrect\t\tMagic,Invisible\t\r\nTelekinesis\tAddTelekinesis\t\tSpellEtherealize\t\t\tPhysical,Invisible\t\r\nLightningArrow\tAddElementalArrow\tProcessElementalArrow\t\t\tLightningArrow\tLightning,Arrow\tBlockable\r\nAcid\tAddAcid\tProcessGenericProjectile\tSpellAcid\t\tAcid\tAcid\tBlockable\r\nAcidSplat\tAddMissileExplosion\tProcessAcidSplate\t\t\tAcidSplat\tAcid\t\r\nAcidPuddle\tAddAcidPuddle\tProcessAcidPuddle\tSpellPuddle\t\tAcidPuddle\tAcid\t\r\nHealOther\tAddHealOther\t\t\t\t\tPhysical,Invisible\t\r\nElemental\tAddElemental\tProcessElemental\tSpellElemental\t\tElemental\tFire\tUnblockable\r\nResurrectBeam\tAddResurrectBeam\tProcessResurrectBeam\t\t\tResurrect\tPhysical\t\r\nBoneSpirit\tAddBoneSpirit\tProcessBoneSpirit\tSpellBoneSpirit\tSpellBoneSpiritHit\tBoneSpirit\tMagic\tBlockable\r\nWeaponExplosion\tAddWeaponExplosion\tProcessWeaponExplosion\t\t\t\tPhysical\t\r\nRedPortal\tAddRedPortal\tProcessRedPortal\tSpellPortal\t\tRedPortal\tPhysical\t\r\nDiabloApocalypseBoom\tAddApocalypseBoom\tProcessApocalypseBoom\t\t\tDiabloApocalypseBoom\tPhysical\t\r\nDiabloApocalypse\tAddDiabloApocalypse\t\t\t\t\tPhysical,Invisible\t\r\nMana\tAddMana\t\t\t\t\tPhysical,Invisible\t\r\nMagi\tAddMagi\t\t\t\t\tPhysical,Invisible\t\r\nLightningWall\tAddLightningWall\tProcessLightningWall\tSpellLightningWall\tSpellLightningHit\tLightning\tLightning\t\r\nLightningWallControl\tAddWallControl\tProcessWallControl\t\t\tLightning\tLightning,Invisible\t\r\nImmolation\tAddNova\tProcessImmolation\tSpellFirebolt\tSpellFireHit\tFireball\tFire\t\r\nSpectralArrow\tAddSpectralArrow\tProcessSpectralArrow\t\t\tArrow\tPhysical,Arrow\t\r\nFireballBow\tAddImmolation\tProcessFireball\tShootFireballBow\tSpellFireHit\tFireball\tFire\tBlockable\r\nLightningBow\tAddLightningBow\tProcessLightningBow\tShootFireballBow\t\tLightning\tLightning,Invisible\t\r\nChargedBoltBow\tAddChargedBoltBow\tProcessChargedBolt\tSpellChargedBolt\t\tChargedBolt\tLightning\tBlockable\r\nHolyBoltBow\tAddHolyBolt\tProcessHolyBolt\tSpellHolyBolt\tSpellLightningHit\tHolyBolt\tPhysical\tBlockable\r\nWarp\tAddWarp\tProcessTeleport\tSpellEtherealize\t\t\tPhysical,Invisible\t\r\nReflect\tAddReflect\t\tSpellManaShield\t\tReflect\tPhysical,Invisible\t\r\nBerserk\tAddBerserk\t\t\t\t\tPhysical,Invisible\t\r\nRingOfFire\tAddRingOfFire\tProcessRingOfFire\t\t\tFireWall\tFire,Invisible\t\r\nStealPotions\tAddStealPotions\t\t\t\t\tPhysical,Invisible\t\r\nStealMana\tAddStealMana\t\tSpellEnd\t\t\tPhysical,Invisible\t\r\nRingOfLightning\t\t\t\t\tLightning\tLightning,Invisible\t\r\nSearch\tAddSearch\tProcessSearch\t\t\t\tPhysical,Invisible\t\r\nAura\t\t\t\tSpellLightningHit\tFlashBottom\tMagic,Invisible\t\r\nAura2\t\t\t\t\tFlashTop\tMagic,Invisible\t\r\nSpiralFireball\t\t\tSpellFirebolt\tSpellFireHit\tFireball\tFire\t\r\nRuneOfFire\tAddRuneOfFire\tProcessRune\t\t\tRune\tPhysical\t\r\nRuneOfLight\tAddRuneOfLight\tProcessRune\t\t\tRune\tPhysical\t\r\nRuneOfNova\tAddRuneOfNova\tProcessRune\t\t\tRune\tPhysical\t\r\nRuneOfImmolation\tAddRuneOfImmolation\tProcessRune\t\t\tRune\tPhysical\t\r\nRuneOfStone\tAddRuneOfStone\tProcessRune\t\t\tRune\tPhysical\t\r\nBigExplosion\tAddBigExplosion\tProcessBigExplosion\tBigExplosion\tBigExplosion\tBigExplosion\tFire\t\r\nHorkSpawn\tAddHorkSpawn\tProcessHorkSpawn\t\t\t\tPhysical,Invisible\t\r\nJester\tAddJester\t\t\t\t\tPhysical,Invisible\t\r\nOpenNest\tAddOpenNest\t\t\t\t\tPhysical,Invisible\t\r\nOrangeFlare\tAddGenericMagicMissile\tProcessGenericProjectile\t\t\tOrangeFlare\tMagic\tBlockable\r\nBlueFlare\tAddGenericMagicMissile\tProcessGenericProjectile\t\t\tBlueFlare2\tMagic\tBlockable\r\nRedFlare\tAddGenericMagicMissile\tProcessGenericProjectile\t\t\tRedFlare\tMagic\tBlockable\r\nYellowFlare\tAddGenericMagicMissile\tProcessGenericProjectile\t\t\tYellowFlare\tMagic\tBlockable\r\nBlueFlare2\tAddGenericMagicMissile\tProcessGenericProjectile\t\t\tBlueFlare2\tMagic\tBlockable\r\nYellowExplosion\tAddMissileExplosion\tProcessMissileExplosion\tSpellFireHit\t\tYellowFlareExplosion\tPhysical\t\r\nRedExplosion\tAddMissileExplosion\tProcessMissileExplosion\tSpellFireHit\t\tRedFlareExplosion\tPhysical\t\r\nBlueExplosion\tAddMissileExplosion\tProcessMissileExplosion\tSpellFireHit\t\tBlueFlareExplosion\tPhysical\t\r\nBlueExplosion2\tAddMissileExplosion\tProcessMissileExplosion\tSpellFireHit\t\tBlueFlareExplosion2\tPhysical\t\r\nOrangeExplosion\tAddMissileExplosion\tProcessMissileExplosion\tSpellFireHit\t\tOrangeFlareExplosion\tPhysical\t\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/missiles/missile_sprites.tsv",
    "content": "id\twidth\twidth2\tname\tnumFrames\tflags\tframeDelay\tframeLength\r\nArrow\t96\t16\tarrows\t1\tNotAnimated\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nFireball\t96\t16\tfireba\t16\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14\r\nGuardian\t96\t16\tguard\t3\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t15,14,3,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nLightning\t96\t16\tlghning\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nFireWall\t128\t32\tfirewal\t2\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t13,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nMagmaBallExplosion\t128\t32\tmagblos\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10\r\nTownPortal\t96\t16\tportal\t2\t\t0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nFlashBottom\t160\t48\tbluexfr\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19\r\nFlashTop\t160\t48\tbluexbk\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19\r\nManaShield\t96\t16\tmanashld\t1\tNotAnimated\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\r\nBloodHit\t96\t16\t\t4\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nBoneHit\t128\t32\t\t3\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nMetalHit\t96\t16\t\t3\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2\t10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10\r\nFireArrow\t96\t16\tfarrow\t16\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4\r\nDoomSerpents\t96\t16\tdoom\t9\tMonsterOwned\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nGolem\t0\t0\t\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nSpurt\t128\t32\t\t2\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nApocalypseBoom\t96\t16\tnewexp\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nStoneCurseShatter\t128\t32\tshatter1\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12\r\nBigExplosion\t160\t48\tbigexp\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nInferno\t96\t16\tinferno\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20\r\nThinLightning\t96\t16\tthinlght\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nBloodStar\t128\t32\tflare\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarExplosion\t128\t32\tflareexp\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\r\nMagmaBall\t128\t32\tmagball\t8\tMonsterOwned\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nKrull\t96\t16\tkrull\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14\r\nChargedBolt\t64\t0\tminiltng\t1\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nHolyBolt\t96\t16\tholy\t16\t\t1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14\r\nHolyBoltExplosion\t160\t48\tholyexpl\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nLightningArrow\t96\t16\tlarrow\t16\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4\r\nFireArrowExplosion\t64\t0\t\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\nAcid\t96\t16\tacidbf\t16\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nAcidSplat\t96\t16\tacidspla\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\r\nAcidPuddle\t96\t16\tacidpud\t2\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\nEtherealize\t96\t16\t\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\r\nElemental\t96\t16\tfirerun\t8\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12\r\nResurrect\t96\t16\tressur1\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBoneSpirit\t96\t16\tsklball\t9\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t16,16,16,16,16,16,16,16,8,0,0,0,0,0,0,0\r\nRedPortal\t96\t16\trportal\t2\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nDiabloApocalypseBoom\t160\t48\tfireplar\t1\tMonsterOwned\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\t17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17\r\nBloodStarBlue\t96\t16\tscubmisb\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarBlueExplosion\t128\t32\tscbsexpb\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\nBloodStarYellow\t96\t16\tscubmisc\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarYellowExplosion\t128\t32\tscbsexpc\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\nBloodStarRed\t96\t16\tscubmisd\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16\r\nBloodStarRedExplosion\t128\t32\tscbsexpd\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6\r\nHorkSpawn\t96\t16\tspawns\t8\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9\r\nReflect\t160\t64\treflect\t1\tNotAnimated\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\r\nOrangeFlare\t96\t8\tms_ora\t16\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nBlueFlare\t96\t8\tms_bla\t16\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nRedFlare\t96\t8\tms_reb\t16\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nYellowFlare\t96\t8\tms_yeb\t16\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nRune\t96\t8\trglows1\t1\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10\r\nYellowFlareExplosion\t220\t78\tex_yel2\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10\r\nBlueFlareExplosion\t212\t86\tex_blu2\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10\r\nRedFlareExplosion\t292\t114\tex_red3\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\r\nBlueFlare2\t96\t8\tms_blb\t16\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15\r\nOrangeFlareExplosion\t96\t-12\tex_ora1\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13\r\nBlueFlareExplosion2\t292\t114\tex_blu3\t1\tMonsterOwned\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/monsters/monstdat.tsv",
    "content": "_monster_id\tname\tassetsSuffix\tsoundSuffix\ttrnFile\tavailability\twidth\timage\thasSpecial\thasSpecialSound\tframes[6]\trate[6]\tminDunLvl\tmaxDunLvl\tlevel\thitPointsMinimum\thitPointsMaximum\tai\tabilityFlags\tintelligence\ttoHit\tanimFrameNum\tminDamage\tmaxDamage\ttoHitSpecial\tanimFrameNumSpecial\tminDamageSpecial\tmaxDamageSpecial\treducePlayerStrength\treducePlayerMagic\treducePlayerDexterity\treducePlayerVitality\treducePlayerMaxHP\treducePlayerMaxMana\tarmorClass\tmonsterClass\tresistance\tresistanceHell\tselectionRegion\ttreasure\texp\r\nMT_NZOMBIE\tZombie\tzombie\\zombie\t\t\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t1\t2\t1\t4\t7\tZombie\t\t0\t10\t8\t2\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t54\r\nMT_BZOMBIE\tGhoul\tzombie\\zombie\t\tzombie\\bluered\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t2\t3\t2\t7\t11\tZombie\t\t1\t10\t8\t3\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t10\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t58\r\nMT_GZOMBIE\tRotting Carcass\tzombie\\zombie\t\tzombie\\grey\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t2\t4\t4\t15\t25\tZombie\t\t2\t25\t8\t5\t15\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC,RESIST_FIRE\tBottom,Middle\t\t136\r\nMT_YZOMBIE\tBlack Death\tzombie\\zombie\t\tzombie\\yellow\tAlways\t128\t799\tfalse\tfalse\t11,24,12,6,16,0\t4,1,1,1,1,1\t3\t5\t6\t25\t40\tZombie\t\t3\t30\t8\t6\t22\t0\t0\t0\t0\t0\t0\t0\t0\t1\t0\t20\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t240\r\nMT_RFALLSP\tFallen One\tfalspear\\phall\t\tfalspear\\fallent\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t1\t2\t1\t1\t4\tFallen\t\t0\t15\t7\t1\t3\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\tAnimal\t\t\tBottom,Middle\t\t46\r\nMT_DFALLSP\tCarver\tfalspear\\phall\t\tfalspear\\dark\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t2\t3\t3\t4\t8\tFallen\t\t2\t20\t7\t2\t5\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t5\tAnimal\t\t\tBottom,Middle\t\t80\r\nMT_YFALLSP\tDevil Kin\tfalspear\\phall\t\t\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t2\t4\t5\t12\t24\tFallen\t\t2\t25\t7\t3\t7\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t10\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t155\r\nMT_BFALLSP\tDark One\tfalspear\\phall\t\tfalspear\\blue\tAlways\t128\t543\ttrue\ttrue\t11,11,13,11,18,13\t3,1,1,1,1,1\t3\t5\t7\t20\t36\tFallen\t\t3\t30\t7\t4\t8\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t15\tAnimal\t\tRESIST_LIGHTNING\tBottom,Middle\t\t255\r\nMT_WSKELAX\tSkeleton\tskelaxe\\sklax\t\tskelaxe\\white\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t5,1,1,1,1,1\t1\t2\t1\t2\t4\tSkeletonMelee\t\t0\t20\t8\t1\t4\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t64\r\nMT_TSKELAX\tCorpse Axe\tskelaxe\\sklax\t\tskelaxe\\skelt\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t4,1,1,1,1,1\t2\t3\t2\t4\t7\tSkeletonMelee\t\t1\t25\t8\t3\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t68\r\nMT_RSKELAX\tBurning Dead\tskelaxe\\sklax\t\t\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t2,1,1,1,1,1\t2\t4\t4\t8\t12\tSkeletonMelee\t\t2\t30\t8\t3\t7\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t154\r\nMT_XSKELAX\tHorror\tskelaxe\\sklax\t\tskelaxe\\black\tAlways\t128\t553\ttrue\tfalse\t12,8,13,6,17,16\t3,1,1,1,1,1\t3\t5\t6\t12\t20\tSkeletonMelee\t\t3\t35\t8\t4\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t264\r\nMT_RFALLSD\tFallen One\tfalsword\\fall\t\tfalsword\\fallent\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t1\t2\t1\t2\t5\tFallen\t\t0\t15\t8\t1\t4\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t10\tAnimal\t\t\tBottom,Middle\t\t52\r\nMT_DFALLSD\tCarver\tfalsword\\fall\t\tfalsword\\dark\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t2\t3\t3\t5\t9\tFallen\t\t1\t20\t8\t2\t7\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t15\tAnimal\t\t\tBottom,Middle\t\t90\r\nMT_YFALLSD\tDevil Kin\tfalsword\\fall\t\t\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t2\t4\t5\t16\t24\tFallen\t\t2\t25\t8\t4\t10\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t20\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t180\r\nMT_BFALLSD\tDark One\tfalsword\\fall\t\tfalsword\\blue\tAlways\t128\t623\ttrue\ttrue\t12,12,13,11,14,15\t3,1,1,1,1,1\t3\t5\t7\t24\t36\tFallen\t\t3\t30\t8\t4\t12\t0\t5\t0\t0\t0\t0\t0\t0\t0\t0\t25\tAnimal\t\tRESIST_LIGHTNING\tBottom,Middle\t\t280\r\nMT_NSCAV\tScavenger\tscav\\scav\t\t\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t1\t3\t2\t3\t6\tScavenger\t\t0\t20\t7\t1\t5\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t10\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t80\r\nMT_BSCAV\tPlague Eater\tscav\\scav\t\tscav\\scavbr\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t2\t4\t4\t12\t24\tScavenger\t\t1\t30\t7\t1\t8\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t20\tAnimal\t\tRESIST_LIGHTNING\tBottom,Middle\t\t188\r\nMT_WSCAV\tShadow Beast\tscav\\scav\t\tscav\\scavbe\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t3\t5\t6\t24\t36\tScavenger\t\t2\t35\t7\t3\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t375\r\nMT_YSCAV\tBone Gasher\tscav\\scav\t\tscav\\scavw\tAlways\t128\t410\ttrue\tfalse\t12,8,12,6,20,11\t2,1,1,1,1,1\t4\t6\t8\t28\t40\tScavenger\t\t3\t35\t7\t5\t15\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tRESIST_MAGIC\tRESIST_LIGHTNING\tBottom,Middle\t\t552\r\nMT_WSKELBW\tSkeleton\tskelbow\\sklbw\t\tskelbow\\white\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t4,1,1,1,1,1\t2\t3\t3\t2\t4\tSkeletonRanged\t\t0\t15\t12\t1\t2\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t110\r\nMT_TSKELBW\tCorpse Bow\tskelbow\\sklbw\t\tskelbow\\skelt\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t4,1,1,1,1,1\t2\t4\t5\t8\t16\tSkeletonRanged\t\t1\t25\t12\t1\t4\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t210\r\nMT_RSKELBW\tBurning Dead\tskelbow\\sklbw\t\t\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t2,1,1,1,1,1\t3\t5\t7\t10\t24\tSkeletonRanged\t\t2\t30\t12\t1\t6\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t364\r\nMT_XSKELBW\tHorror\tskelbow\\sklbw\t\tskelbow\\black\tAlways\t128\t567\ttrue\tfalse\t9,8,16,5,16,16\t3,1,1,1,1,1\t4\t6\t9\t15\t45\tSkeletonRanged\t\t3\t35\t12\t2\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t594\r\nMT_WSKELSD\tSkeleton Captain\tskelsd\\sklsr\t\tskelsd\\white\tAlways\t128\t575\ttrue\ttrue\t13,8,12,7,15,16\t4,1,1,1,1,1\t1\t3\t2\t3\t6\tSkeletonMelee\t\t0\t20\t8\t2\t7\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t10\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t90\r\nMT_TSKELSD\tCorpse Captain\tskelsd\\sklsr\t\tskelsd\\skelt\tAlways\t128\t575\ttrue\tfalse\t13,8,12,7,15,16\t4,1,1,1,1,1\t2\t4\t4\t12\t20\tSkeletonMelee\t\t1\t30\t8\t3\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t5\tUndead\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t200\r\nMT_RSKELSD\tBurning Dead Captain\tskelsd\\sklsr\t\t\tAlways\t128\t575\ttrue\tfalse\t13,8,12,7,15,16\t4,1,1,1,1,1\t3\t5\t6\t16\t30\tSkeletonMelee\t\t2\t35\t8\t4\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tUndead\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t393\r\nMT_XSKELSD\tHorror Captain\tskelsd\\sklsr\t\tskelsd\\black\tAlways\t128\t575\ttrue\tfalse\t13,8,12,7,15,16\t4,1,1,1,1,1\t4\t6\t8\t35\t50\tSkeletonMelee\tSEARCH\t3\t40\t8\t5\t14\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tUndead\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t604\r\nMT_INVILORD\tInvisible Lord\ttsneak\\tsneak\t\t\tNever\t128\t800\tfalse\tfalse\t13,13,15,11,16,0\t2,1,1,1,1,1\t19\t20\t14\t278\t278\tSkeletonMelee\tSEARCH,CAN_OPEN_DOOR\t3\t65\t8\t16\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t2000\r\nMT_SNEAK\tHidden\tsneak\\sneak\t\t\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t2\t5\t5\t8\t24\tSneak\tHIDDEN\t0\t35\t8\t3\t6\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tDemon\t\t\tBottom,Middle\t\t278\r\nMT_STALKER\tStalker\tsneak\\sneak\t\tsneak\\sneakv2\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t5\t7\t9\t30\t45\tSneak\tHIDDEN,SEARCH\t1\t40\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\t\t\tBottom,Middle\t\t630\r\nMT_UNSEEN\tUnseen\tsneak\\sneak\t\tsneak\\sneakv3\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t6\t8\t11\t35\t50\tSneak\tHIDDEN,SEARCH\t2\t45\t8\t12\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t935\r\nMT_ILLWEAV\tIllusion Weaver\tsneak\\sneak\t\tsneak\\sneakv1\tRetail\t128\t992\ttrue\tfalse\t16,8,12,8,24,15\t2,1,1,1,1,1\t8\t10\t13\t40\t60\tSneak\tHIDDEN,SEARCH\t3\t60\t8\t16\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tRESIST_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,RESIST_FIRE\tBottom,Middle\t\t1500\r\nMT_LRDSAYTR\tSatyr Lord\tgoatlord\\goatl\tnewsfx\\satyr\t\tNever\t160\t800\tfalse\tfalse\t13,13,14,9,16,0\t2,1,1,1,1,1\t21\t22\t28\t160\t200\tSkeletonMelee\tSEARCH\t3\t90\t8\t20\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tAnimal\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t2800\r\nMT_NGOATMC\tFlesh Clan\tgoatmace\\goat\t\t\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t4\t6\t8\t30\t45\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t0\t50\t8\t4\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t40\tDemon\t\t\tBottom,Middle\t\t460\r\nMT_BGOATMC\tStone Clan\tgoatmace\\goat\t\tgoatmace\\beige\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t5\t7\t10\t40\t55\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t1\t60\t8\t6\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t40\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t685\r\nMT_RGOATMC\tFire Clan\tgoatmace\\goat\t\tgoatmace\\red\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t6\t8\t12\t50\t65\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t2\t70\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tRESIST_FIRE\tIMMUNE_FIRE\tBottom,Middle\t\t906\r\nMT_GGOATMC\tNight Clan\tgoatmace\\goat\t\tgoatmace\\gray\tRetail\t128\t1030\ttrue\tfalse\t12,8,12,6,20,12\t2,1,1,1,1,1\t7\t9\t14\t55\t70\tGoatMelee\tSEARCH,CAN_OPEN_DOOR\t3\t80\t8\t10\t20\t15\t0\t30\t30\t0\t0\t0\t0\t0\t0\t50\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t1190\r\nMT_FIEND\tFiend\tbat\\bat\t\tbat\\red\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t2\t3\t3\t3\t6\tBat\t\t0\t35\t5\t1\t6\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tAnimal\t\t\tMiddle,Top\tNone\t102\r\nMT_BLINK\tBlink\tbat\\bat\t\t\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t3\t5\t7\t12\t28\tBat\t\t1\t45\t5\t1\t8\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t15\tAnimal\t\t\tMiddle,Top\tNone\t340\r\nMT_GLOOM\tGloom\tbat\\bat\t\tbat\\grey\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t4\t6\t9\t28\t36\tBat\tSEARCH\t2\t70\t5\t4\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC\tRESIST_MAGIC\tMiddle,Top\tNone\t509\r\nMT_FAMILIAR\tFamiliar\tbat\\bat\t\tbat\\orange\tAlways\t96\t364\tfalse\tfalse\t9,13,10,9,13,0\t1,1,1,1,1,1\t6\t8\t13\t20\t35\tBat\tSEARCH\t3\t50\t5\t4\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tRESIST_MAGIC,IMMUNE_LIGHTNING\tMiddle,Top\tNone\t448\r\nMT_NGOATBW\tFlesh Clan\tgoatbow\\goatb\t\t\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t4\t6\t8\t20\t35\tGoatRanged\tCAN_OPEN_DOOR\t0\t35\t13\t1\t7\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\t\t\tBottom,Middle\t\t448\r\nMT_BGOATBW\tStone Clan\tgoatbow\\goatb\t\tgoatbow\\beige\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t5\t7\t10\t30\t40\tGoatRanged\tCAN_OPEN_DOOR\t1\t40\t13\t2\t9\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t645\r\nMT_RGOATBW\tFire Clan\tgoatbow\\goatb\t\tgoatbow\\red\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t6\t8\t12\t40\t50\tGoatRanged\tSEARCH,CAN_OPEN_DOOR\t2\t45\t13\t3\t11\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_FIRE\tIMMUNE_FIRE\tBottom,Middle\t\t822\r\nMT_GGOATBW\tNight Clan\tgoatbow\\goatb\t\tgoatbow\\gray\tRetail\t128\t1040\tfalse\tfalse\t12,8,16,6,20,0\t3,1,1,1,1,1\t7\t9\t14\t50\t65\tGoatRanged\tSEARCH,CAN_OPEN_DOOR\t3\t50\t13\t4\t13\t15\t0\t0\t0\t0\t0\t0\t0\t0\t0\t40\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC\tBottom,Middle\t\t1092\r\nMT_NACID\tAcid Beast\tacid\\acid\t\t\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t6\t8\t11\t40\t66\tAcid\t\t0\t40\t8\t4\t12\t25\t8\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tIMMUNE_ACID\tIMMUNE_MAGIC,IMMUNE_ACID\tBottom,Middle\t\t846\r\nMT_RACID\tPoison Spitter\tacid\\acid\t\tacid\\acidblk\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t8\t10\t15\t60\t85\tAcid\t\t1\t45\t8\t4\t16\t25\t8\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tIMMUNE_ACID\tIMMUNE_MAGIC,IMMUNE_ACID\tBottom,Middle\t\t1248\r\nMT_BACID\tPit Beast\tacid\\acid\t\tacid\\acidb\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t10\t12\t21\t80\t110\tAcid\t\t2\t55\t8\t8\t18\t35\t8\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC,IMMUNE_ACID\tIMMUNE_MAGIC,RESIST_LIGHTNING,IMMUNE_ACID\tBottom,Middle\t\t2060\r\nMT_XACID\tLava Maw\tacid\\acid\t\tacid\\acidr\tRetail\t128\t716\ttrue\ttrue\t13,8,12,8,16,12\t1,1,1,1,1,1\t12\t14\t25\t100\t150\tAcid\t\t3\t65\t8\t10\t20\t40\t8\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_ACID\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_ACID\tBottom,Middle\t\t2940\r\nMT_SKING\tSkeleton King\tsking\\sking\t\tskelaxe\\white\tNever\t160\t1010\ttrue\ttrue\t8,6,16,6,16,6\t2,1,1,1,1,2\t4\t4\t9\t140\t140\tSkeletonKing\tSEARCH,CAN_OPEN_DOOR\t3\t60\t8\t6\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tUndead\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\tUniq(SKCROWN)\t570\r\nMT_CLEAVER\tThe Butcher\tfatc\\fatc\t\t\tNever\t128\t980\tfalse\tfalse\t10,8,12,6,16,0\t1,1,1,1,1,1\t1\t1\t1\t320\t320\tButcher\t\t3\t50\t8\t6\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\tUniq(CLEAVER)\t710\r\nMT_FAT\tOverlord\tfat\\fat\t\t\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t5\t7\t10\t60\t80\tFat\t\t0\t55\t8\t6\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t55\tDemon\t\tRESIST_FIRE\tBottom,Middle\t\t635\r\nMT_MUDMAN\tMud Man\tfat\\fat\t\tfat\\blue\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t7\t9\t14\t100\t125\tFat\tSEARCH\t1\t60\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\t\tIMMUNE_LIGHTNING\tBottom,Middle\t\t1165\r\nMT_TOAD\tToad Demon\tfat\\fat\t\tfat\\fatb\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t8\t10\t16\t135\t160\tFat\tSEARCH\t2\t70\t8\t8\t16\t40\t0\t8\t20\t0\t0\t0\t0\t0\t0\t65\tDemon\tIMMUNE_MAGIC\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t1380\r\nMT_FLAYED\tFlayed One\tfat\\fat\t\tfat\\fatf\tRetail\t128\t1130\ttrue\tfalse\t8,10,15,6,16,10\t4,1,1,1,1,1\t10\t12\t20\t160\t200\tFat\tSEARCH\t3\t85\t8\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t2058\r\nMT_WYRM\tWyrm\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t5\t7\t11\t60\t90\tSkeletonMelee\t\t0\t40\t8\t4\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tAnimal\tRESIST_MAGIC\tRESIST_MAGIC\tBottom,Middle\t\t660\r\nMT_CAVSLUG\tCave Slug\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t6\t8\t13\t75\t110\tSkeletonMelee\t\t1\t50\t8\t6\t13\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tRESIST_MAGIC\tRESIST_MAGIC\tBottom,Middle\t\t994\r\nMT_DVLWYRM\tDevil Wyrm\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t7\t9\t15\t100\t140\tSkeletonMelee\t\t2\t55\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\tRESIST_MAGIC,RESIST_FIRE\tRESIST_MAGIC,RESIST_FIRE\tBottom,Middle\t\t1320\r\nMT_DEVOUR\tDevourer\tworm\\worm\t\t\tNever\t160\t2420\tfalse\tfalse\t13,13,13,11,19,0\t1,1,1,1,1,1\t8\t10\t17\t125\t200\tSkeletonMelee\t\t3\t60\t8\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t35\tAnimal\tRESIST_MAGIC,RESIST_FIRE\tRESIST_MAGIC,RESIST_FIRE\tBottom,Middle\t\t1827\r\nMT_NMAGMA\tMagma Demon\tmagma\\magma\t\t\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t8\t9\t13\t50\t70\tMagma\tSEARCH,CAN_OPEN_DOOR\t0\t45\t4\t2\t10\t50\t13\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t1076\r\nMT_YMAGMA\tBlood Stone\tmagma\\magma\t\tmagma\\yellow\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t8\t10\t14\t55\t75\tMagma\tSEARCH,CAN_OPEN_DOOR\t1\t50\t4\t2\t12\t50\t14\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t1309\r\nMT_BMAGMA\tHell Stone\tmagma\\magma\t\tmagma\\blue\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t9\t11\t16\t60\t80\tMagma\tSEARCH,CAN_OPEN_DOOR\t2\t60\t4\t2\t20\t60\t14\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t1680\r\nMT_WMAGMA\tLava Lord\tmagma\\magma\t\tmagma\\wierd\tRetail\t128\t1680\ttrue\ttrue\t8,10,14,7,18,18\t2,1,1,1,1,1\t9\t11\t18\t70\t85\tMagma\tSEARCH,CAN_OPEN_DOOR\t3\t75\t4\t4\t24\t60\t14\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2124\r\nMT_HORNED\tHorned Demon\trhino\\rhino\t\t\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t7\t9\t13\t40\t80\tRhino\tSEARCH,CAN_OPEN_DOOR\t0\t60\t7\t2\t16\t100\t0\t5\t32\t0\t0\t0\t0\t0\t0\t40\tAnimal\t\tRESIST_FIRE\tBottom,Middle,Top\t\t1172\r\nMT_MUDRUN\tMud Runner\trhino\\rhino\t\trhino\\orange\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t8\t10\t15\t50\t90\tRhino\tSEARCH,CAN_OPEN_DOOR\t1\t70\t7\t6\t18\t100\t0\t12\t36\t0\t0\t0\t0\t0\t0\t45\tAnimal\t\tRESIST_FIRE\tBottom,Middle,Top\t\t1404\r\nMT_FROSTC\tFrost Charger\trhino\\rhino\t\trhino\\blue\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t9\t11\t17\t60\t100\tRhino\tSEARCH,CAN_OPEN_DOOR\t2\t80\t7\t8\t20\t100\t0\t20\t40\t0\t0\t0\t0\t0\t0\t50\tAnimal\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle,Top\t\t1720\r\nMT_OBLORD\tObsidian Lord\trhino\\rhino\t\trhino\\rhinob\tRetail\t160\t1630\ttrue\ttrue\t8,8,14,6,16,6\t2,1,1,1,1,1\t10\t12\t19\t70\t110\tRhino\tSEARCH,CAN_OPEN_DOOR\t3\t90\t7\t10\t22\t100\t0\t20\t50\t0\t0\t0\t0\t0\t0\t55\tAnimal\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t1809\r\nMT_BONEDMN\toldboned\tdemskel\\demskl\t\t\tNever\t128\t1740\ttrue\ttrue\t10,8,20,6,24,16\t3,1,1,1,1,1\t24\t24\t12\t70\t70\tStorm\t\t0\t60\t8\t6\t14\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle,Top\t\t1344\r\nMT_REDDTH\tRed Death\tthin\\thin\t\tthin\\thinv3\tNever\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t8\t10\t16\t96\t96\tStorm\t\t1\t75\t5\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2168\r\nMT_LTCHDMN\tLitch Demon\tthin\\thin\t\tthin\\thinv3\tNever\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t9\t11\t18\t110\t110\tStorm\t\t2\t80\t5\t10\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2736\r\nMT_UDEDBLRG\tUndead Balrog\tthin\\thin\t\tthin\\thinv3\tNever\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t11\t13\t22\t130\t130\tStorm\t\t3\t85\t5\t12\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3575\r\nMT_INCIN\tIncinerator\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t21\t22\t16\t30\t45\tFireMan\t\t0\t75\t8\t8\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t1888\r\nMT_FLAMLRD\tFlame Lord\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t22\t23\t18\t40\t55\tFireMan\t\t1\t75\t8\t10\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle\t\t2250\r\nMT_DOOMFIRE\tDoom Fire\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t23\t24\t20\t50\t65\tFireMan\t\t2\t80\t8\t12\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t2740\r\nMT_HELLBURN\tHell Burner\tfireman\\firem\t\t\tNever\t128\t1460\ttrue\tfalse\t14,19,20,8,14,23\t1,1,1,1,1,1\t24\t24\t22\t60\t80\tFireMan\t\t3\t85\t8\t15\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t3355\r\nMT_STORM\tRed Storm\tthin\\thin\t\tthin\\thinv3\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t9\t11\t18\t55\t110\tStorm\tSEARCH,CAN_OPEN_DOOR\t0\t80\t5\t8\t18\t75\t8\t4\t16\t0\t0\t0\t0\t0\t0\t30\tDemon\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2160\r\nMT_RSTORM\tStorm Rider\tthin\\thin\t\t\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t10\t12\t20\t60\t120\tStorm\tSEARCH,CAN_OPEN_DOOR\t1\t80\t5\t8\t18\t80\t8\t4\t16\t0\t0\t0\t0\t0\t0\t30\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2391\r\nMT_STORML\tStorm Lord\tthin\\thin\t\tthin\\thinv2\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t11\t13\t22\t75\t135\tStorm\tSEARCH,CAN_OPEN_DOOR\t2\t85\t5\t12\t24\t75\t8\t4\t16\t0\t0\t0\t0\t0\t0\t35\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2775\r\nMT_MAEL\tMaelstrom\tthin\\thin\t\tthin\\thinv1\tRetail\t160\t1740\ttrue\ttrue\t8,8,18,4,17,14\t3,1,1,1,1,1\t12\t14\t24\t90\t150\tStorm\tSEARCH,CAN_OPEN_DOOR\t3\t90\t5\t12\t28\t75\t8\t4\t16\t0\t0\t0\t0\t0\t0\t40\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t3177\r\nMT_BIGFALL\tDevil Kin Brute\tbigfall\\fallg\tnewsfx\\kbrute\t\tNever\t128\t800\ttrue\tfalse\t10,8,11,8,17,0\t1,1,1,1,2,2\t21\t22\t27\t120\t160\tSkeletonMelee\tSEARCH,CAN_OPEN_DOOR\t3\t100\t6\t18\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tAnimal\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t2400\r\nMT_WINGED\tWinged-Demon\tgargoyle\\gargo\t\t\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,2\t5\t7\t9\t45\t60\tGargoyle\tCAN_OPEN_DOOR\t0\t50\t7\t10\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tMiddle,Top\t\t662\r\nMT_GARGOYLE\tGargoyle\tgargoyle\\gargo\t\tgargoyle\\gare\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,2\t7\t9\t13\t60\t90\tGargoyle\tCAN_OPEN_DOOR\t1\t65\t7\t10\t16\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t45\tDemon\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tMiddle,Top\t\t1205\r\nMT_BLOODCLW\tBlood Claw\tgargoyle\\gargo\t\tgargoyle\\gargbr\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,1\t9\t11\t19\t75\t125\tGargoyle\tCAN_OPEN_DOOR\t2\t80\t7\t14\t22\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tMiddle,Top\t\t1873\r\nMT_DEATHW\tDeath Wing\tgargoyle\\gargo\t\tgargoyle\\gargb\tRetail\t160\t1650\ttrue\tfalse\t14,14,14,10,18,14\t1,1,1,1,1,1\t10\t12\t23\t90\t150\tGargoyle\tCAN_OPEN_DOOR\t3\t95\t7\t16\t28\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tMiddle,Top\t\t2278\r\nMT_MEGA\tSlayer\tmega\\mega\t\t\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t10\t12\t20\t120\t140\tMega\tSEARCH,CAN_OPEN_DOOR\t0\t100\t8\t12\t20\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2300\r\nMT_GUARD\tGuardian\tmega\\mega\t\tmega\\guard\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t11\t13\t22\t140\t160\tMega\tSEARCH,CAN_OPEN_DOOR\t1\t110\t8\t14\t22\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t2714\r\nMT_VTEXLRD\tVortex Lord\tmega\\mega\t\tmega\\vtexl\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t12\t14\t24\t160\t180\tMega\tSEARCH,CAN_OPEN_DOOR\t2\t120\t8\t18\t24\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3252\r\nMT_BALROG\tBalrog\tmega\\mega\t\tmega\\balr\tRetail\t160\t2220\ttrue\ttrue\t6,7,14,1,24,5\t3,1,1,1,2,1\t13\t15\t26\t180\t200\tMega\tSEARCH,CAN_OPEN_DOOR\t3\t130\t8\t22\t30\t0\t3\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,IMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3643\r\nMT_NSNAKE\tCave Viper\tsnake\\snake\t\t\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t11\t13\t21\t100\t150\tSnake\tSEARCH\t0\t90\t8\t8\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tIMMUNE_MAGIC\tIMMUNE_MAGIC\tBottom,Middle,Top\t\t2725\r\nMT_RSNAKE\tFire Drake\tsnake\\snake\t\tsnake\\snakr\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t12\t14\t23\t120\t170\tSnake\tSEARCH\t1\t105\t8\t12\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tIMMUNE_MAGIC,RESIST_FIRE\tIMMUNE_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t3139\r\nMT_BSNAKE\tGold Viper\tsnake\\snake\t\tsnake\\snakg\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t13\t14\t25\t140\t180\tSnake\tSEARCH\t2\t120\t8\t15\t26\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tIMMUNE_MAGIC,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3540\r\nMT_GSNAKE\tAzure Drake\tsnake\\snake\t\tsnake\\snakb\tRetail\t160\t1270\tfalse\tfalse\t12,11,13,5,18,0\t2,1,1,1,1,1\t15\t16\t27\t160\t200\tSnake\tSEARCH\t3\t130\t8\t18\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t3791\r\nMT_NBLACK\tBlack Knight\tblack\\black\t\t\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t12\t14\t24\t150\t150\tSkeletonMelee\tSEARCH\t0\t110\t8\t15\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,RESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t3360\r\nMT_RTBLACK\tDoom Guard\tblack\\black\t\tblack\\blkkntrt\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t13\t15\t26\t165\t165\tSkeletonMelee\tSEARCH\t0\t130\t8\t18\t25\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,RESIST_FIRE\tRESIST_MAGIC,IMMUNE_FIRE\tBottom,Middle,Top\t\t3650\r\nMT_BTBLACK\tSteel Lord\tblack\\black\t\tblack\\blkkntbt\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t14\t16\t28\t180\t180\tSkeletonMelee\tSEARCH\t1\t120\t8\t20\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t80\tDemon\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t4252\r\nMT_RBLACK\tBlood Knight\tblack\\black\t\tblack\\blkkntbe\tRetail\t160\t2120\tfalse\tfalse\t8,8,16,4,24,0\t2,1,1,1,1,1\t13\t14\t30\t200\t200\tSkeletonMelee\tSEARCH\t1\t130\t8\t25\t35\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t85\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t5130\r\nMT_UNRAV\tThe Shredded\tunrav\\unrav\tnewsfx\\shred\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t17\t18\t23\t70\t90\tSkeletonMelee\t\t0\t75\t7\t4\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tUndead\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t900\r\nMT_HOLOWONE\tHollow One\tunrav\\unrav\tacid\\acid\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t18\t19\t27\t135\t240\tSkeletonMelee\t\t1\t75\t7\t12\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tUndead\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t4374\r\nMT_PAINMSTR\tPain Master\tunrav\\unrav\tacid\\acid\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t19\t20\t29\t110\t200\tSkeletonMelee\t\t2\t80\t7\t16\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t80\tUndead\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t5147\r\nMT_REALWEAV\tReality Weaver\tunrav\\unrav\tacid\\acid\t\tNever\t96\t484\tfalse\tfalse\t10,10,12,5,16,0\t1,1,1,1,1,1\t20\t20\t30\t135\t240\tSkeletonMelee\t\t3\t85\t7\t20\t35\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t85\tUndead\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t5925\r\nMT_SUCCUBUS\tSuccubus\tsucc\\scbs\t\t\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t12\t14\t24\t120\t150\tSuccubus\tCAN_OPEN_DOOR\t0\t100\t10\t1\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\tRESIST_MAGIC\tIMMUNE_MAGIC,RESIST_FIRE\tBottom,Middle\t\t3696\r\nMT_SNOWWICH\tSnow Witch\tsucc\\scbs\t\tsucc\\succb\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t13\t15\t26\t135\t175\tSuccubus\tCAN_OPEN_DOOR\t1\t110\t10\t1\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t65\tDemon\tRESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_LIGHTNING\tBottom,Middle\t\t4084\r\nMT_HLSPWN\tHell Spawn\tsucc\\scbs\t\tsucc\\succrw\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t14\t16\t28\t150\t200\tSuccubus\tSEARCH,CAN_OPEN_DOOR\t2\t115\t10\t1\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tDemon\tRESIST_MAGIC,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t4480\r\nMT_SOLBRNR\tSoul Burner\tsucc\\scbs\t\tsucc\\succbw\tRetail\t128\t980\tfalse\tfalse\t14,8,16,7,24,0\t1,1,1,1,1,1\t15\t16\t30\t140\t225\tSuccubus\tSEARCH,CAN_OPEN_DOOR\t3\t120\t10\t1\t35\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t85\tDemon\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t4644\r\nMT_COUNSLR\tCounselor\tmage\\mage\t\t\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t13\t14\t25\t70\t70\tCounselor\tCAN_OPEN_DOOR\t0\t90\t8\t8\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t4070\r\nMT_MAGISTR\tMagistrate\tmage\\mage\t\tmage\\cnselg\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t14\t15\t27\t85\t85\tCounselor\tCAN_OPEN_DOOR\t1\t100\t8\t10\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t4478\r\nMT_CABALIST\tCabalist\tmage\\mage\t\tmage\\cnselgd\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t15\t16\t29\t120\t120\tCounselor\tCAN_OPEN_DOOR\t2\t110\t8\t14\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t4929\r\nMT_ADVOCATE\tAdvocate\tmage\\mage\t\tmage\\cnselbk\tRetail\t128\t2000\ttrue\tfalse\t12,1,20,8,28,20\t1,1,1,1,1,1\t16\t16\t30\t145\t145\tCounselor\tCAN_OPEN_DOOR\t3\t120\t8\t15\t25\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t4968\r\nMT_GOLEM\tGolem\tgolem\\golem\tgolem\\golm\t\tNever\t96\t386\ttrue\tfalse\t0,16,12,0,12,20\t1,1,1,1,1,1\t1\t1\t12\t1\t1\tGolem\tCAN_OPEN_DOOR\t0\t0\t7\t1\t1\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t1\tDemon\t\t\t\t\t0\r\nMT_DIABLO\tThe Dark Lord\tdiablo\\diablo\t\t\tNever\t160\t2000\ttrue\ttrue\t16,6,16,6,16,16\t1,1,1,1,1,1\t26\t26\t30\t1666\t1666\tDiablo\tKNOCKBACK,SEARCH,CAN_OPEN_DOOR\t3\t220\t4\t30\t60\t0\t11\t0\t0\t0\t0\t0\t0\t0\t0\t90\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t31666\r\nMT_DARKMAGE\tThe Arch-Litch Malignus\tdarkmage\\dmage\tdarkmage\\dmag\t\tNever\t128\t1060\ttrue\tfalse\t6,1,21,6,23,18\t1,1,1,1,1,1\t21\t21\t30\t160\t160\tCounselor\tCAN_OPEN_DOOR\t3\t120\t8\t20\t40\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t4968\r\nMT_HELLBOAR\tHellboar\tfork\\fork\tnewsfx\\hboar\t\tRetail\t188\t800\tfalse\tfalse\t10,10,15,6,16,0\t2,1,1,1,1,1\t17\t18\t23\t80\t100\tSkeletonMelee\tKNOCKBACK,SEARCH\t2\t70\t7\t16\t24\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tDemon\t\tRESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t750\r\nMT_STINGER\tStinger\tscorp\\scorp\tnewsfx\\stingr\t\tRetail\t64\t305\tfalse\tfalse\t10,10,12,6,15,0\t2,1,1,1,1,1\t17\t18\t22\t30\t40\tSkeletonMelee\t\t3\t85\t8\t1\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tAnimal\t\tRESIST_LIGHTNING\tBottom\t\t500\r\nMT_PSYCHORB\tPsychorb\teye\\eye\tnewsfx\\psyco\t\tRetail\t156\t800\tfalse\tfalse\t12,13,13,7,21,0\t2,1,1,1,1,1\t17\t18\t22\t20\t30\tPsychorb\t\t3\t80\t8\t10\t10\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t40\tAnimal\t\tRESIST_FIRE\tMiddle,Top\t\t450\r\nMT_ARACHNON\tArachnon\tspider\\spider\tnewsfx\\slord\t\tRetail\t148\t800\tfalse\tfalse\t12,10,15,6,20,0\t2,1,1,1,1,1\t17\t18\t22\t60\t80\tSkeletonMelee\tSEARCH\t3\t50\t8\t5\t15\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tAnimal\t\tRESIST_LIGHTNING\tBottom,Middle,Top\t\t500\r\nMT_FELLTWIN\tFelltwin\ttsneak\\tsneak\tnewsfx\\ftwin\t\tRetail\t128\t800\tfalse\tfalse\t13,13,15,11,16,0\t2,1,1,1,1,1\t17\t18\t22\t50\t70\tSkeletonMelee\tSEARCH,CAN_OPEN_DOOR\t3\t70\t8\t10\t18\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tDemon\t\tRESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t600\r\nMT_HORKSPWN\tHork Spawn\tspawn\\spawn\tnewsfx\\hspawn\t\tRetail\t164\t520\tfalse\ttrue\t15,12,14,11,14,0\t1,1,1,1,1,1\t18\t19\t22\t30\t30\tSkeletonMelee\t\t3\t60\t8\t10\t25\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t25\tDemon\tRESIST_MAGIC\tRESIST_MAGIC\tBottom,Middle\t\t250\r\nMT_VENMTAIL\tVenomtail\twscorp\\wscorp\tnewsfx\\stingr\t\tRetail\t86\t305\tfalse\tfalse\t10,10,12,6,15,0\t2,1,1,1,1,1\t19\t20\t24\t40\t50\tSkeletonMelee\t\t3\t85\t8\t1\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tAnimal\tRESIST_LIGHTNING\tIMMUNE_LIGHTNING\tBottom\t\t1000\r\nMT_NECRMORB\tNecromorb\teye2\\eye2\tnewsfx\\psyco\t\tRetail\t140\t800\tfalse\tfalse\t12,13,13,7,21,0\t2,1,1,1,1,1\t19\t20\t24\t30\t40\tNecromorb\t\t3\t80\t8\t20\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tAnimal\tRESIST_FIRE\tIMMUNE_FIRE,RESIST_LIGHTNING\tMiddle,Top\t\t1100\r\nMT_SPIDLORD\tSpider Lord\tbspidr\\bspidr\tnewsfx\\slord\t\tRetail\t148\t800\ttrue\ttrue\t12,10,15,6,20,10\t2,1,1,1,1,1\t19\t20\t24\t80\t100\tAcid\tSEARCH\t3\t60\t8\t8\t20\t75\t8\t10\t10\t0\t0\t0\t0\t0\t0\t60\tAnimal\tRESIST_LIGHTNING\tRESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t1250\r\nMT_LASHWORM\tLashworm\tclasp\\clasp\tnewsfx\\lworm\t\tRetail\t176\t800\tfalse\tfalse\t10,12,15,6,16,0\t1,1,1,1,1,1\t19\t20\t20\t30\t30\tSkeletonMelee\t\t3\t90\t8\t12\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t50\tAnimal\t\tRESIST_FIRE\tBottom,Middle\t\t600\r\nMT_TORCHANT\tTorchant\tantworm\\worm\tnewsfx\\tchant\t\tRetail\t192\t800\tfalse\tfalse\t14,12,12,6,20,0\t2,1,1,1,1,1\t19\t20\t22\t60\t80\tTorchant\t\t3\t75\t8\t20\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tAnimal\tIMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t1250\r\nMT_HORKDMN\tHork Demon\thorkd\\horkd\tnewsfx\\hdemon\t\tNever\t138\t800\ttrue\ttrue\t15,8,16,6,16,9\t2,1,1,1,1,2\t19\t19\t27\t120\t160\tSkeletonMelee\t\t3\t60\t8\t20\t35\t80\t8\t0\t0\t0\t0\t0\t0\t0\t0\t80\tDemon\tRESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t2000\r\nMT_DEFILER\tHell Bug\thellbug\\hellbg\tnewsfx\\defile\t\tNever\t198\t800\ttrue\ttrue\t8,8,14,6,14,12\t1,1,1,1,1,1\t20\t20\t30\t240\t240\tSkeletonMelee\tSEARCH\t3\t110\t8\t20\t30\t90\t8\t50\t60\t0\t0\t0\t0\t0\t0\t80\tDemon\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t5000\r\nMT_GRAVEDIG\tGravedigger\tgravdg\\gravdg\tnewsfx\\gdiggr\t\tRetail\t124\t800\ttrue\ttrue\t24,24,12,6,16,16\t2,1,1,1,1,1\t21\t21\t26\t120\t240\tScavenger\tCAN_OPEN_DOOR\t3\t80\t6\t2\t12\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t20\tUndead\tIMMUNE_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t2000\r\nMT_TOMBRAT\tTomb Rat\trat\\rat\tnewsfx\\tmbrat\t\tRetail\t104\t550\tfalse\tfalse\t11,8,12,6,20,0\t2,1,1,1,1,1\t21\t22\t24\t80\t120\tSkeletonMelee\t\t3\t120\t8\t12\t25\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t30\tAnimal\t\tRESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t1800\r\nMT_FIREBAT\tFirebat\thellbat\\helbat\tnewsfx\\helbat\t\tRetail\t96\t550\tfalse\tfalse\t18,16,14,6,18,11\t2,1,1,1,1,1\t21\t22\t24\t60\t80\tFireBat\t\t3\t100\t8\t15\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tAnimal\tIMMUNE_FIRE\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t2400\r\nMT_SKLWING\tSkullwing\tdemskel\\demskl\tnewsfx\\swing\tskelaxe\\skelt\tRetail\t128\t1740\ttrue\tfalse\t10,8,20,6,24,16\t3,1,1,1,1,1\t21\t22\t27\t70\t70\tSkeletonMelee\t\t0\t75\t7\t15\t20\t75\t9\t15\t20\t0\t0\t0\t0\t0\t0\t80\tUndead\tRESIST_FIRE,RESIST_LIGHTNING\tRESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle,Top\t\t3000\r\nMT_LICH\tLich\tlich\\lich\tnewsfx\\lich\t\tRetail\t96\t800\tfalse\ttrue\t12,10,10,7,21,0\t2,1,1,1,2,1\t21\t22\t25\t80\t100\tLich\t\t3\t100\t8\t15\t20\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t60\tUndead\tRESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t3000\r\nMT_CRYPTDMN\tCrypt Demon\tbubba\\bubba\tnewsfx\\crypt\t\tRetail\t154\t800\tfalse\ttrue\t8,18,12,8,21,0\t3,1,1,1,1,1\t22\t23\t28\t200\t240\tSkeletonMelee\t\t3\t100\t8\t20\t40\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t85\tDemon\tIMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t3200\r\nMT_HELLBAT\tHellbat\thellbat2\\bhelbt\tnewsfx\\helbat\t\tRetail\t96\t550\ttrue\tfalse\t18,16,14,6,18,11\t2,1,1,1,1,1\t23\t24\t29\t100\t140\tTorchant\t\t3\t110\t8\t30\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t80\tDemon\tRESIST_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t3600\r\nMT_BONEDEMN\tBone Demon\tdemskel\\demskl\tnewsfx\\swing\t\tRetail\t128\t1740\ttrue\ttrue\t10,8,20,6,24,16\t3,1,1,1,1,1\t23\t24\t30\t240\t280\tBoneDemon\t\t0\t100\t8\t40\t50\t160\t12\t50\t50\t0\t0\t0\t0\t0\t0\t50\tUndead\tIMMUNE_FIRE,IMMUNE_LIGHTNING\tIMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t5000\r\nMT_ARCHLICH\tArch Lich\tlich2\\lich2\tnewsfx\\lich\t\tRetail\t136\t800\tfalse\ttrue\t12,10,10,7,21,0\t2,1,1,1,2,1\t23\t24\t30\t180\t200\tArchLich\t\t3\t120\t8\t30\t30\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t75\tUndead\tRESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t4000\r\nMT_BICLOPS\tBiclops\tbyclps\\byclps\tnewsfx\\biclop\t\tRetail\t180\t800\tfalse\tfalse\t10,11,16,6,16,0\t2,1,1,1,2,1\t23\t24\t30\t200\t240\tSkeletonMelee\tKNOCKBACK,CAN_OPEN_DOOR\t3\t90\t8\t40\t50\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t80\tDemon\tRESIST_LIGHTNING\tRESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t4000\r\nMT_FLESTHNG\tFlesh Thing\tflesh\\flesh\tnewsfx\\flesht\t\tRetail\t164\t800\tfalse\ttrue\t15,24,15,6,16,0\t1,1,1,1,1,1\t23\t24\t28\t300\t400\tSkeletonMelee\t\t3\t150\t8\t12\t18\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t70\tDemon\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tRESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING\tBottom,Middle\t\t4000\r\nMT_REAPER\tReaper\treaper\\reap\tnewsfx\\reaper\t\tRetail\t180\t800\tfalse\tfalse\t12,10,14,6,16,0\t2,1,1,1,1,1\t23\t24\t30\t260\t300\tSkeletonMelee\t\t3\t120\t8\t30\t35\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t90\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle\t\t6000\r\nMT_NAKRUL\tNa-Krul\tnkr\\nkr\tnewsfx\\nakrul\t\tNever\t226\t1200\ttrue\ttrue\t2,6,16,3,16,16\t1,1,1,1,1,1\t31\t31\t40\t1332\t1332\tSkeletonMelee\tKNOCKBACK,SEARCH,CAN_OPEN_DOOR\t3\t150\t7\t40\t50\t150\t10\t40\t50\t0\t0\t0\t0\t0\t0\t125\tDemon\tIMMUNE_MAGIC,IMMUNE_FIRE,RESIST_LIGHTNING\tIMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING\tBottom,Middle,Top\t\t13333\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/sound/effects-unused.tsv",
    "content": "id\tflags\tpath\r\nDuck\tMisc\tsfx\\towners\\cow8.wav\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/sound/effects.tsv",
    "content": "id\tflags\tpath\r\nWalk\tMisc\tsfx\\misc\\walk1.wav\r\nShootBow\tMisc\tsfx\\misc\\bfire.wav\r\nCastSpell\tMisc\tsfx\\misc\\tmag.wav\r\nSwing\tMisc\tsfx\\misc\\swing.wav\r\nSwing2\tMisc\tsfx\\misc\\swing2.wav\r\nWarriorDeath\tMisc\tsfx\\misc\\dead.wav\r\nQuestDone\tStream\tsfx\\misc\\questdon.wav\r\nBarrelExpload\tMisc\tsfx\\items\\barlfire.wav\r\nBarrelBreak\tMisc\tsfx\\items\\barrel.wav\r\nChestOpen\tMisc\tsfx\\items\\chest.wav\r\nDoorClose\tMisc\tsfx\\items\\doorclos.wav\r\nDoorOpen\tMisc\tsfx\\items\\dooropen.wav\r\nItemAnvilFlip\tMisc\tsfx\\items\\flipanvl.wav\r\nItemAxeFlip\tMisc\tsfx\\items\\flipaxe.wav\r\nItemBloodStoneFlip\tMisc\tsfx\\items\\flipblst.wav\r\nItemBodyPartFlip\tMisc\tsfx\\items\\flipbody.wav\r\nItemBookFlip\tMisc\tsfx\\items\\flipbook.wav\r\nItemBowFlip\tMisc\tsfx\\items\\flipbow.wav\r\nItemCapFlip\tMisc\tsfx\\items\\flipcap.wav\r\nItemArmorFlip\tMisc\tsfx\\items\\flipharm.wav\r\nItemLeatherFlip\tMisc\tsfx\\items\\fliplarm.wav\r\nItemMushroomFlip\tMisc\tsfx\\items\\flipmush.wav\r\nItemPotionFlip\tMisc\tsfx\\items\\flippot.wav\r\nItemRingFlip\tMisc\tsfx\\items\\flipring.wav\r\nItemRockFlip\tMisc\tsfx\\items\\fliprock.wav\r\nItemScrollFlip\tMisc\tsfx\\items\\flipscrl.wav\r\nItemShieldFlip\tMisc\tsfx\\items\\flipshld.wav\r\nItemSignFlip\tMisc\tsfx\\items\\flipsign.wav\r\nItemStaffFlip\tMisc\tsfx\\items\\flipstaf.wav\r\nItemSwordFlip\tMisc\tsfx\\items\\flipswor.wav\r\nItemGold\tMisc\tsfx\\items\\gold.wav\r\nItemAnvil\tMisc\tsfx\\items\\invanvl.wav\r\nItemAxe\tMisc\tsfx\\items\\invaxe.wav\r\nItemBloodStone\tMisc\tsfx\\items\\invblst.wav\r\nItemBodyPart\tMisc\tsfx\\items\\invbody.wav\r\nItemBook\tMisc\tsfx\\items\\invbook.wav\r\nItemBow\tMisc\tsfx\\items\\invbow.wav\r\nItemCap\tMisc\tsfx\\items\\invcap.wav\r\nGrabItem\tMisc\tsfx\\items\\invgrab.wav\r\nItemArmor\tMisc\tsfx\\items\\invharm.wav\r\nItemLeather\tMisc\tsfx\\items\\invlarm.wav\r\nItemMushroom\tMisc\tsfx\\items\\invmush.wav\r\nItemPotion\tMisc\tsfx\\items\\invpot.wav\r\nItemRing\tMisc\tsfx\\items\\invring.wav\r\nItemRock\tMisc\tsfx\\items\\invrock.wav\r\nItemScroll\tMisc\tsfx\\items\\invscrol.wav\r\nItemShield\tMisc\tsfx\\items\\invshiel.wav\r\nItemSign\tMisc\tsfx\\items\\invsign.wav\r\nItemStaff\tMisc\tsfx\\items\\invstaf.wav\r\nItemSword\tMisc\tsfx\\items\\invsword.wav\r\nOperateLever\tMisc\tsfx\\items\\lever.wav\r\nOperateShrine\tMisc\tsfx\\items\\magic.wav\r\nOperateShrine1\tMisc\tsfx\\items\\magic1.wav\r\nReadBook\tMisc\tsfx\\items\\readbook.wav\r\nSarcophagus\tMisc\tsfx\\items\\sarc.wav\r\nMenuMove\tUi\tsfx\\items\\titlemov.wav\r\nMenuSelect\tUi\tsfx\\items\\titlslct.wav\r\nTriggerTrap\tMisc\tsfx\\items\\trap.wav\r\nCastFire\tMisc\tsfx\\misc\\cast2.wav\r\nCastLightning\tMisc\tsfx\\misc\\cast4.wav\r\nCastSkill\tMisc\tsfx\\misc\\cast6.wav\r\nSpellEnd\tMisc\tsfx\\misc\\cast7.wav\r\nCastHealing\tMisc\tsfx\\misc\\cast8.wav\r\nSpellRepair\tMisc\tsfx\\misc\\repair.wav\r\nSpellAcid\tMisc\tsfx\\misc\\acids1.wav\r\nSpellAcid1\tMisc\tsfx\\misc\\acids2.wav\r\nSpellApocalypse\tMisc\tsfx\\misc\\apoc.wav\r\nSpellBloodStar\tMisc\tsfx\\misc\\blodstar.wav\r\nSpellBloodStarHit\tMisc\tsfx\\misc\\blsimpt.wav\r\nSpellBoneSpirit\tMisc\tsfx\\misc\\bonesp.wav\r\nSpellBoneSpiritHit\tMisc\tsfx\\misc\\bsimpct.wav\r\nOperateCaldron\tMisc\tsfx\\misc\\caldron.wav\r\nSpellChargedBolt\tMisc\tsfx\\misc\\cbolt.wav\r\nSpellDoomSerpents\tMisc\tsfx\\misc\\dserp.wav\r\nSpellLightningHit\tMisc\tsfx\\misc\\elecimp1.wav\r\nSpellElemental\tMisc\tsfx\\misc\\elementl.wav\r\nSpellEtherealize\tMisc\tsfx\\misc\\ethereal.wav\r\nSpellFirebolt\tMisc\tsfx\\misc\\fbolt1.wav\r\nSpellFireHit\tMisc\tsfx\\misc\\firimp2.wav\r\nSpellFlameWave\tMisc\tsfx\\misc\\flamwave.wav\r\nOperateFountain\tMisc\tsfx\\misc\\fountain.wav\r\nSpellGolem\tMisc\tsfx\\misc\\golum.wav\r\nOperateGoatShrine\tMisc\tsfx\\misc\\gshrine.wav\r\nSpellGuardian\tMisc\tsfx\\misc\\guard.wav\r\nSpellHolyBolt\tMisc\tsfx\\misc\\holybolt.wav\r\nSpellInfravision\tMisc\tsfx\\misc\\infravis.wav\r\nSpellInvisibility\tMisc\tsfx\\misc\\invisibl.wav\r\nSpellLightning\tMisc\tsfx\\misc\\lning1.wav\r\nSpellManaShield\tMisc\tsfx\\misc\\mshield.wav\r\nSpellNova\tMisc\tsfx\\misc\\nova.wav\r\nSpellPuddle\tMisc\tsfx\\misc\\puddle.wav\r\nSpellResurrect\tMisc\tsfx\\misc\\resur.wav\r\nSpellStoneCurse\tMisc\tsfx\\misc\\scurimp.wav\r\nSpellPortal\tMisc\tsfx\\misc\\sentinel.wav\r\nSpellInferno\tMisc\tsfx\\misc\\spoutstr.wav\r\nSpellTrapDisarm\tMisc\tsfx\\misc\\trapdis.wav\r\nSpellTeleport\tMisc\tsfx\\misc\\teleport.wav\r\nSpellFireWall\tMisc\tsfx\\misc\\wallloop.wav\r\nGillian1\tStream\tsfx\\towners\\bmaid01.wav\r\nGillian2\tStream\tsfx\\towners\\bmaid02.wav\r\nGillian3\tStream\tsfx\\towners\\bmaid03.wav\r\nGillian4\tStream\tsfx\\towners\\bmaid04.wav\r\nGillian5\tStream\tsfx\\towners\\bmaid05.wav\r\nGillian6\tStream\tsfx\\towners\\bmaid06.wav\r\nGillian7\tStream\tsfx\\towners\\bmaid07.wav\r\nGillian8\tStream\tsfx\\towners\\bmaid08.wav\r\nGillian9\tStream\tsfx\\towners\\bmaid09.wav\r\nGillian10\tStream\tsfx\\towners\\bmaid10.wav\r\nGillian11\tStream\tsfx\\towners\\bmaid11.wav\r\nGillian12\tStream\tsfx\\towners\\bmaid12.wav\r\nGillian13\tStream\tsfx\\towners\\bmaid13.wav\r\nGillian14\tStream\tsfx\\towners\\bmaid14.wav\r\nGillian15\tStream\tsfx\\towners\\bmaid15.wav\r\nGillian16\tStream\tsfx\\towners\\bmaid16.wav\r\nGillian17\tStream\tsfx\\towners\\bmaid17.wav\r\nGillian18\tStream\tsfx\\towners\\bmaid18.wav\r\nGillian19\tStream\tsfx\\towners\\bmaid19.wav\r\nGillian20\tStream\tsfx\\towners\\bmaid20.wav\r\nGillian21\tStream\tsfx\\towners\\bmaid21.wav\r\nGillian22\tStream\tsfx\\towners\\bmaid22.wav\r\nGillian23\tStream\tsfx\\towners\\bmaid23.wav\r\nGillian24\tStream\tsfx\\towners\\bmaid24.wav\r\nGillian25\tStream\tsfx\\towners\\bmaid25.wav\r\nGillian26\tStream\tsfx\\towners\\bmaid26.wav\r\nGillian27\tStream\tsfx\\towners\\bmaid27.wav\r\nGillian28\tStream\tsfx\\towners\\bmaid28.wav\r\nGillian29\tStream\tsfx\\towners\\bmaid29.wav\r\nGillian30\tStream\tsfx\\towners\\bmaid30.wav\r\nGillian31\tStream\tsfx\\towners\\bmaid31.wav\r\nGillian32\tStream\tsfx\\towners\\bmaid32.wav\r\nGillian33\tStream\tsfx\\towners\\bmaid33.wav\r\nGillian34\tStream\tsfx\\towners\\bmaid34.wav\r\nGillian35\tStream\tsfx\\towners\\bmaid35.wav\r\nGillian36\tStream\tsfx\\towners\\bmaid36.wav\r\nGillian37\tStream\tsfx\\towners\\bmaid37.wav\r\nGillian38\tStream\tsfx\\towners\\bmaid38.wav\r\nGillian39\tStream\tsfx\\towners\\bmaid39.wav\r\nGillian40\tStream\tsfx\\towners\\bmaid40.wav\r\nGriswold1\tStream\tsfx\\towners\\bsmith01.wav\r\nGriswold2\tStream\tsfx\\towners\\bsmith02.wav\r\nGriswold3\tStream\tsfx\\towners\\bsmith03.wav\r\nGriswold4\tStream\tsfx\\towners\\bsmith04.wav\r\nGriswold5\tStream\tsfx\\towners\\bsmith05.wav\r\nGriswold6\tStream\tsfx\\towners\\bsmith06.wav\r\nGriswold7\tStream\tsfx\\towners\\bsmith07.wav\r\nGriswold8\tStream\tsfx\\towners\\bsmith08.wav\r\nGriswold9\tStream\tsfx\\towners\\bsmith09.wav\r\nGriswold10\tStream\tsfx\\towners\\bsmith10.wav\r\nGriswold12\tStream\tsfx\\towners\\bsmith12.wav\r\nGriswold13\tStream\tsfx\\towners\\bsmith13.wav\r\nGriswold14\tStream\tsfx\\towners\\bsmith14.wav\r\nGriswold15\tStream\tsfx\\towners\\bsmith15.wav\r\nGriswold16\tStream\tsfx\\towners\\bsmith16.wav\r\nGriswold17\tStream\tsfx\\towners\\bsmith17.wav\r\nGriswold18\tStream\tsfx\\towners\\bsmith18.wav\r\nGriswold19\tStream\tsfx\\towners\\bsmith19.wav\r\nGriswold20\tStream\tsfx\\towners\\bsmith20.wav\r\nGriswold21\tStream\tsfx\\towners\\bsmith21.wav\r\nGriswold22\tStream\tsfx\\towners\\bsmith22.wav\r\nGriswold23\tStream\tsfx\\towners\\bsmith23.wav\r\nGriswold24\tStream\tsfx\\towners\\bsmith24.wav\r\nGriswold25\tStream\tsfx\\towners\\bsmith25.wav\r\nGriswold26\tStream\tsfx\\towners\\bsmith26.wav\r\nGriswold27\tStream\tsfx\\towners\\bsmith27.wav\r\nGriswold28\tStream\tsfx\\towners\\bsmith28.wav\r\nGriswold29\tStream\tsfx\\towners\\bsmith29.wav\r\nGriswold30\tStream\tsfx\\towners\\bsmith30.wav\r\nGriswold31\tStream\tsfx\\towners\\bsmith31.wav\r\nGriswold32\tStream\tsfx\\towners\\bsmith32.wav\r\nGriswold33\tStream\tsfx\\towners\\bsmith33.wav\r\nGriswold34\tStream\tsfx\\towners\\bsmith34.wav\r\nGriswold35\tStream\tsfx\\towners\\bsmith35.wav\r\nGriswold36\tStream\tsfx\\towners\\bsmith36.wav\r\nGriswold37\tStream\tsfx\\towners\\bsmith37.wav\r\nGriswold38\tStream\tsfx\\towners\\bsmith38.wav\r\nGriswold39\tStream\tsfx\\towners\\bsmith39.wav\r\nGriswold40\tStream\tsfx\\towners\\bsmith40.wav\r\nGriswold41\tStream\tsfx\\towners\\bsmith41.wav\r\nGriswold42\tStream\tsfx\\towners\\bsmith42.wav\r\nGriswold43\tStream\tsfx\\towners\\bsmith43.wav\r\nGriswold44\tStream\tsfx\\towners\\bsmith44.wav\r\nGriswold45\tStream\tsfx\\towners\\bsmith45.wav\r\nGriswold46\tStream\tsfx\\towners\\bsmith46.wav\r\nGriswold47\tStream\tsfx\\towners\\bsmith47.wav\r\nGriswold48\tStream\tsfx\\towners\\bsmith48.wav\r\nGriswold49\tStream\tsfx\\towners\\bsmith49.wav\r\nGriswold50\tStream\tsfx\\towners\\bsmith50.wav\r\nGriswold51\tStream\tsfx\\towners\\bsmith51.wav\r\nGriswold52\tStream\tsfx\\towners\\bsmith52.wav\r\nGriswold53\tStream\tsfx\\towners\\bsmith53.wav\r\nGriswold55\tStream\tsfx\\towners\\bsmith55.wav\r\nGriswold56\tStream\tsfx\\towners\\bsmith56.wav\r\nCow1\tMisc\tsfx\\towners\\cow1.wav\r\nCow2\tMisc\tsfx\\towners\\cow2.wav\r\nWoundedTownsmanOld\tStream\tsfx\\towners\\deadguy2.wav\r\nFarnham1\tStream\tsfx\\towners\\drunk01.wav\r\nFarnham2\tStream\tsfx\\towners\\drunk02.wav\r\nFarnham3\tStream\tsfx\\towners\\drunk03.wav\r\nFarnham4\tStream\tsfx\\towners\\drunk04.wav\r\nFarnham5\tStream\tsfx\\towners\\drunk05.wav\r\nFarnham6\tStream\tsfx\\towners\\drunk06.wav\r\nFarnham7\tStream\tsfx\\towners\\drunk07.wav\r\nFarnham8\tStream\tsfx\\towners\\drunk08.wav\r\nFarnham9\tStream\tsfx\\towners\\drunk09.wav\r\nFarnham10\tStream\tsfx\\towners\\drunk10.wav\r\nFarnham11\tStream\tsfx\\towners\\drunk11.wav\r\nFarnham12\tStream\tsfx\\towners\\drunk12.wav\r\nFarnham13\tStream\tsfx\\towners\\drunk13.wav\r\nFarnham14\tStream\tsfx\\towners\\drunk14.wav\r\nFarnham15\tStream\tsfx\\towners\\drunk15.wav\r\nFarnham16\tStream\tsfx\\towners\\drunk16.wav\r\nFarnham17\tStream\tsfx\\towners\\drunk17.wav\r\nFarnham18\tStream\tsfx\\towners\\drunk18.wav\r\nFarnham19\tStream\tsfx\\towners\\drunk19.wav\r\nFarnham20\tStream\tsfx\\towners\\drunk20.wav\r\nFarnham21\tStream\tsfx\\towners\\drunk21.wav\r\nFarnham22\tStream\tsfx\\towners\\drunk22.wav\r\nFarnham23\tStream\tsfx\\towners\\drunk23.wav\r\nFarnham24\tStream\tsfx\\towners\\drunk24.wav\r\nFarnham25\tStream\tsfx\\towners\\drunk25.wav\r\nFarnham26\tStream\tsfx\\towners\\drunk26.wav\r\nFarnham27\tStream\tsfx\\towners\\drunk27.wav\r\nFarnham28\tStream\tsfx\\towners\\drunk28.wav\r\nFarnham29\tStream\tsfx\\towners\\drunk29.wav\r\nFarnham30\tStream\tsfx\\towners\\drunk30.wav\r\nFarnham31\tStream\tsfx\\towners\\drunk31.wav\r\nFarnham32\tStream\tsfx\\towners\\drunk32.wav\r\nFarnham33\tStream\tsfx\\towners\\drunk33.wav\r\nFarnham34\tStream\tsfx\\towners\\drunk34.wav\r\nFarnham35\tStream\tsfx\\towners\\drunk35.wav\r\nPepin1\tStream\tsfx\\towners\\healer01.wav\r\nPepin2\tStream\tsfx\\towners\\healer02.wav\r\nPepin3\tStream\tsfx\\towners\\healer03.wav\r\nPepin4\tStream\tsfx\\towners\\healer04.wav\r\nPepin5\tStream\tsfx\\towners\\healer05.wav\r\nPepin6\tStream\tsfx\\towners\\healer06.wav\r\nPepin7\tStream\tsfx\\towners\\healer07.wav\r\nPepin8\tStream\tsfx\\towners\\healer08.wav\r\nPepin9\tStream\tsfx\\towners\\healer09.wav\r\nPepin10\tStream\tsfx\\towners\\healer10.wav\r\nPepin11\tStream\tsfx\\towners\\healer11.wav\r\nPepin12\tStream\tsfx\\towners\\healer12.wav\r\nPepin13\tStream\tsfx\\towners\\healer13.wav\r\nPepin14\tStream\tsfx\\towners\\healer14.wav\r\nPepin15\tStream\tsfx\\towners\\healer15.wav\r\nPepin16\tStream\tsfx\\towners\\healer16.wav\r\nPepin17\tStream\tsfx\\towners\\healer17.wav\r\nPepin18\tStream\tsfx\\towners\\healer18.wav\r\nPepin19\tStream\tsfx\\towners\\healer19.wav\r\nPepin20\tStream\tsfx\\towners\\healer20.wav\r\nPepin21\tStream\tsfx\\towners\\healer21.wav\r\nPepin22\tStream\tsfx\\towners\\healer22.wav\r\nPepin23\tStream\tsfx\\towners\\healer23.wav\r\nPepin24\tStream\tsfx\\towners\\healer24.wav\r\nPepin25\tStream\tsfx\\towners\\healer25.wav\r\nPepin26\tStream\tsfx\\towners\\healer26.wav\r\nPepin27\tStream\tsfx\\towners\\healer27.wav\r\nPepin28\tStream\tsfx\\towners\\healer28.wav\r\nPepin29\tStream\tsfx\\towners\\healer29.wav\r\nPepin30\tStream\tsfx\\towners\\healer30.wav\r\nPepin31\tStream\tsfx\\towners\\healer31.wav\r\nPepin32\tStream\tsfx\\towners\\healer32.wav\r\nPepin33\tStream\tsfx\\towners\\healer33.wav\r\nPepin34\tStream\tsfx\\towners\\healer34.wav\r\nPepin35\tStream\tsfx\\towners\\healer35.wav\r\nPepin36\tStream\tsfx\\towners\\healer36.wav\r\nPepin37\tStream\tsfx\\towners\\healer37.wav\r\nPepin38\tStream\tsfx\\towners\\healer38.wav\r\nPepin39\tStream\tsfx\\towners\\healer39.wav\r\nPepin40\tStream\tsfx\\towners\\healer40.wav\r\nPepin41\tStream\tsfx\\towners\\healer41.wav\r\nPepin42\tStream\tsfx\\towners\\healer42.wav\r\nPepin43\tStream\tsfx\\towners\\healer43.wav\r\nPepin44\tStream\tsfx\\towners\\healer44.wav\r\nPepin45\tStream\tsfx\\towners\\healer45.wav\r\nPepin46\tStream\tsfx\\towners\\healer46.wav\r\nPepin47\tStream\tsfx\\towners\\healer47.wav\r\nWirt1\tStream\tsfx\\towners\\pegboy01.wav\r\nWirt2\tStream\tsfx\\towners\\pegboy02.wav\r\nWirt3\tStream\tsfx\\towners\\pegboy03.wav\r\nWirt4\tStream\tsfx\\towners\\pegboy04.wav\r\nWirt5\tStream\tsfx\\towners\\pegboy05.wav\r\nWirt6\tStream\tsfx\\towners\\pegboy06.wav\r\nWirt7\tStream\tsfx\\towners\\pegboy07.wav\r\nWirt8\tStream\tsfx\\towners\\pegboy08.wav\r\nWirt9\tStream\tsfx\\towners\\pegboy09.wav\r\nWirt10\tStream\tsfx\\towners\\pegboy10.wav\r\nWirt11\tStream\tsfx\\towners\\pegboy11.wav\r\nWirt12\tStream\tsfx\\towners\\pegboy12.wav\r\nWirt13\tStream\tsfx\\towners\\pegboy13.wav\r\nWirt14\tStream\tsfx\\towners\\pegboy14.wav\r\nWirt15\tStream\tsfx\\towners\\pegboy15.wav\r\nWirt16\tStream\tsfx\\towners\\pegboy16.wav\r\nWirt17\tStream\tsfx\\towners\\pegboy17.wav\r\nWirt18\tStream\tsfx\\towners\\pegboy18.wav\r\nWirt19\tStream\tsfx\\towners\\pegboy19.wav\r\nWirt20\tStream\tsfx\\towners\\pegboy20.wav\r\nWirt21\tStream\tsfx\\towners\\pegboy21.wav\r\nWirt22\tStream\tsfx\\towners\\pegboy22.wav\r\nWirt23\tStream\tsfx\\towners\\pegboy23.wav\r\nWirt24\tStream\tsfx\\towners\\pegboy24.wav\r\nWirt25\tStream\tsfx\\towners\\pegboy25.wav\r\nWirt26\tStream\tsfx\\towners\\pegboy26.wav\r\nWirt27\tStream\tsfx\\towners\\pegboy27.wav\r\nWirt28\tStream\tsfx\\towners\\pegboy28.wav\r\nWirt29\tStream\tsfx\\towners\\pegboy29.wav\r\nWirt30\tStream\tsfx\\towners\\pegboy30.wav\r\nWirt31\tStream\tsfx\\towners\\pegboy31.wav\r\nWirt32\tStream\tsfx\\towners\\pegboy32.wav\r\nWirt33\tStream\tsfx\\towners\\pegboy33.wav\r\nWirt34\tStream\tsfx\\towners\\pegboy34.wav\r\nWirt35\tStream\tsfx\\towners\\pegboy35.wav\r\nWirt36\tStream\tsfx\\towners\\pegboy36.wav\r\nWirt37\tStream\tsfx\\towners\\pegboy37.wav\r\nWirt38\tStream\tsfx\\towners\\pegboy38.wav\r\nWirt39\tStream\tsfx\\towners\\pegboy39.wav\r\nWirt40\tStream\tsfx\\towners\\pegboy40.wav\r\nWirt41\tStream\tsfx\\towners\\pegboy41.wav\r\nWirt42\tStream\tsfx\\towners\\pegboy42.wav\r\nWirt43\tStream\tsfx\\towners\\pegboy43.wav\r\nTremain0\tStream\tsfx\\towners\\priest00.wav\r\nTremain1\tStream\tsfx\\towners\\priest01.wav\r\nTremain2\tStream\tsfx\\towners\\priest02.wav\r\nTremain3\tStream\tsfx\\towners\\priest03.wav\r\nTremain4\tStream\tsfx\\towners\\priest04.wav\r\nTremain5\tStream\tsfx\\towners\\priest05.wav\r\nTremain6\tStream\tsfx\\towners\\priest06.wav\r\nTremain7\tStream\tsfx\\towners\\priest07.wav\r\nCain0\tStream\tsfx\\towners\\storyt00.wav\r\nCain1\tStream\tsfx\\towners\\storyt01.wav\r\nCain2\tStream\tsfx\\towners\\storyt02.wav\r\nCain3\tStream\tsfx\\towners\\storyt03.wav\r\nCain4\tStream\tsfx\\towners\\storyt04.wav\r\nCain5\tStream\tsfx\\towners\\storyt05.wav\r\nCain6\tStream\tsfx\\towners\\storyt06.wav\r\nCain7\tStream\tsfx\\towners\\storyt07.wav\r\nCain8\tStream\tsfx\\towners\\storyt08.wav\r\nCain9\tStream\tsfx\\towners\\storyt09.wav\r\nCain10\tStream\tsfx\\towners\\storyt10.wav\r\nCain11\tStream\tsfx\\towners\\storyt11.wav\r\nCain12\tStream\tsfx\\towners\\storyt12.wav\r\nCain13\tStream\tsfx\\towners\\storyt13.wav\r\nCain14\tStream\tsfx\\towners\\storyt14.wav\r\nCain15\tStream\tsfx\\towners\\storyt15.wav\r\nCain16\tStream\tsfx\\towners\\storyt16.wav\r\nCain17\tStream\tsfx\\towners\\storyt17.wav\r\nCain18\tStream\tsfx\\towners\\storyt18.wav\r\nCain19\tStream\tsfx\\towners\\storyt19.wav\r\nCain20\tStream\tsfx\\towners\\storyt20.wav\r\nCain21\tStream\tsfx\\towners\\storyt21.wav\r\nCain22\tStream\tsfx\\towners\\storyt22.wav\r\nCain23\tStream\tsfx\\towners\\storyt23.wav\r\nCain24\tStream\tsfx\\towners\\storyt24.wav\r\nCain25\tStream\tsfx\\towners\\storyt25.wav\r\nCain26\tStream\tsfx\\towners\\storyt26.wav\r\nCain27\tStream\tsfx\\towners\\storyt27.wav\r\nCain28\tStream\tsfx\\towners\\storyt28.wav\r\nCain29\tStream\tsfx\\towners\\storyt29.wav\r\nCain30\tStream\tsfx\\towners\\storyt30.wav\r\nCain31\tStream\tsfx\\towners\\storyt31.wav\r\nCain33\tStream\tsfx\\towners\\storyt33.wav\r\nCain34\tStream\tsfx\\towners\\storyt34.wav\r\nCain35\tStream\tsfx\\towners\\storyt35.wav\r\nCain36\tStream\tsfx\\towners\\storyt36.wav\r\nCain37\tStream\tsfx\\towners\\storyt37.wav\r\nCain38\tStream\tsfx\\towners\\storyt38.wav\r\nOgden0\tStream\tsfx\\towners\\tavown00.wav\r\nOgden1\tStream\tsfx\\towners\\tavown01.wav\r\nOgden2\tStream\tsfx\\towners\\tavown02.wav\r\nOgden3\tStream\tsfx\\towners\\tavown03.wav\r\nOgden4\tStream\tsfx\\towners\\tavown04.wav\r\nOgden5\tStream\tsfx\\towners\\tavown05.wav\r\nOgden6\tStream\tsfx\\towners\\tavown06.wav\r\nOgden7\tStream\tsfx\\towners\\tavown07.wav\r\nOgden8\tStream\tsfx\\towners\\tavown08.wav\r\nOgden9\tStream\tsfx\\towners\\tavown09.wav\r\nOgden10\tStream\tsfx\\towners\\tavown10.wav\r\nOgden11\tStream\tsfx\\towners\\tavown11.wav\r\nOgden12\tStream\tsfx\\towners\\tavown12.wav\r\nOgden13\tStream\tsfx\\towners\\tavown13.wav\r\nOgden14\tStream\tsfx\\towners\\tavown14.wav\r\nOgden15\tStream\tsfx\\towners\\tavown15.wav\r\nOgden16\tStream\tsfx\\towners\\tavown16.wav\r\nOgden17\tStream\tsfx\\towners\\tavown17.wav\r\nOgden18\tStream\tsfx\\towners\\tavown18.wav\r\nOgden19\tStream\tsfx\\towners\\tavown19.wav\r\nOgden20\tStream\tsfx\\towners\\tavown20.wav\r\nOgden21\tStream\tsfx\\towners\\tavown21.wav\r\nOgden22\tStream\tsfx\\towners\\tavown22.wav\r\nOgden23\tStream\tsfx\\towners\\tavown23.wav\r\nOgden24\tStream\tsfx\\towners\\tavown24.wav\r\nOgden25\tStream\tsfx\\towners\\tavown25.wav\r\nOgden26\tStream\tsfx\\towners\\tavown26.wav\r\nOgden27\tStream\tsfx\\towners\\tavown27.wav\r\nOgden28\tStream\tsfx\\towners\\tavown28.wav\r\nOgden29\tStream\tsfx\\towners\\tavown29.wav\r\nOgden30\tStream\tsfx\\towners\\tavown30.wav\r\nOgden31\tStream\tsfx\\towners\\tavown31.wav\r\nOgden32\tStream\tsfx\\towners\\tavown32.wav\r\nOgden33\tStream\tsfx\\towners\\tavown33.wav\r\nOgden34\tStream\tsfx\\towners\\tavown34.wav\r\nOgden35\tStream\tsfx\\towners\\tavown35.wav\r\nOgden36\tStream\tsfx\\towners\\tavown36.wav\r\nOgden37\tStream\tsfx\\towners\\tavown37.wav\r\nOgden38\tStream\tsfx\\towners\\tavown38.wav\r\nOgden39\tStream\tsfx\\towners\\tavown39.wav\r\nOgden40\tStream\tsfx\\towners\\tavown40.wav\r\nOgden41\tStream\tsfx\\towners\\tavown41.wav\r\nOgden43\tStream\tsfx\\towners\\tavown43.wav\r\nOgden44\tStream\tsfx\\towners\\tavown44.wav\r\nOgden45\tStream\tsfx\\towners\\tavown45.wav\r\nAdria1\tStream\tsfx\\towners\\witch01.wav\r\nAdria2\tStream\tsfx\\towners\\witch02.wav\r\nAdria3\tStream\tsfx\\towners\\witch03.wav\r\nAdria4\tStream\tsfx\\towners\\witch04.wav\r\nAdria5\tStream\tsfx\\towners\\witch05.wav\r\nAdria6\tStream\tsfx\\towners\\witch06.wav\r\nAdria7\tStream\tsfx\\towners\\witch07.wav\r\nAdria8\tStream\tsfx\\towners\\witch08.wav\r\nAdria9\tStream\tsfx\\towners\\witch09.wav\r\nAdria10\tStream\tsfx\\towners\\witch10.wav\r\nAdria11\tStream\tsfx\\towners\\witch11.wav\r\nAdria12\tStream\tsfx\\towners\\witch12.wav\r\nAdria13\tStream\tsfx\\towners\\witch13.wav\r\nAdria14\tStream\tsfx\\towners\\witch14.wav\r\nAdria15\tStream\tsfx\\towners\\witch15.wav\r\nAdria16\tStream\tsfx\\towners\\witch16.wav\r\nAdria17\tStream\tsfx\\towners\\witch17.wav\r\nAdria18\tStream\tsfx\\towners\\witch18.wav\r\nAdria19\tStream\tsfx\\towners\\witch19.wav\r\nAdria20\tStream\tsfx\\towners\\witch20.wav\r\nAdria21\tStream\tsfx\\towners\\witch21.wav\r\nAdria22\tStream\tsfx\\towners\\witch22.wav\r\nAdria23\tStream\tsfx\\towners\\witch23.wav\r\nAdria24\tStream\tsfx\\towners\\witch24.wav\r\nAdria25\tStream\tsfx\\towners\\witch25.wav\r\nAdria26\tStream\tsfx\\towners\\witch26.wav\r\nAdria27\tStream\tsfx\\towners\\witch27.wav\r\nAdria28\tStream\tsfx\\towners\\witch28.wav\r\nAdria29\tStream\tsfx\\towners\\witch29.wav\r\nAdria30\tStream\tsfx\\towners\\witch30.wav\r\nAdria31\tStream\tsfx\\towners\\witch31.wav\r\nAdria32\tStream\tsfx\\towners\\witch32.wav\r\nAdria33\tStream\tsfx\\towners\\witch33.wav\r\nAdria34\tStream\tsfx\\towners\\witch34.wav\r\nAdria35\tStream\tsfx\\towners\\witch35.wav\r\nAdria36\tStream\tsfx\\towners\\witch36.wav\r\nAdria37\tStream\tsfx\\towners\\witch37.wav\r\nAdria38\tStream\tsfx\\towners\\witch38.wav\r\nAdria39\tStream\tsfx\\towners\\witch39.wav\r\nAdria40\tStream\tsfx\\towners\\witch40.wav\r\nAdria41\tStream\tsfx\\towners\\witch41.wav\r\nAdria42\tStream\tsfx\\towners\\witch42.wav\r\nAdria43\tStream\tsfx\\towners\\witch43.wav\r\nAdria44\tStream\tsfx\\towners\\witch44.wav\r\nAdria45\tStream\tsfx\\towners\\witch45.wav\r\nAdria46\tStream\tsfx\\towners\\witch46.wav\r\nAdria47\tStream\tsfx\\towners\\witch47.wav\r\nAdria48\tStream\tsfx\\towners\\witch48.wav\r\nAdria49\tStream\tsfx\\towners\\witch49.wav\r\nAdria50\tStream\tsfx\\towners\\witch50.wav\r\nWoundedTownsman\tStream\tsfx\\towners\\wound01.wav\r\nSorceror1\tStream,Sorcerer\tsfx\\sorceror\\mage01.wav\r\nSorceror2\tStream,Sorcerer\tsfx\\sorceror\\mage02.wav\r\nSorceror3\tStream,Sorcerer\tsfx\\sorceror\\mage03.wav\r\nSorceror4\tStream,Sorcerer\tsfx\\sorceror\\mage04.wav\r\nSorceror5\tStream,Sorcerer\tsfx\\sorceror\\mage05.wav\r\nSorceror6\tStream,Sorcerer\tsfx\\sorceror\\mage06.wav\r\nSorceror7\tStream,Sorcerer\tsfx\\sorceror\\mage07.wav\r\nSorceror8\tStream,Sorcerer\tsfx\\sorceror\\mage08.wav\r\nSorceror9\tStream,Sorcerer\tsfx\\sorceror\\mage09.wav\r\nSorceror10\tStream,Sorcerer\tsfx\\sorceror\\mage10.wav\r\nSorceror11\tStream,Sorcerer\tsfx\\sorceror\\mage11.wav\r\nSorceror12\tStream,Sorcerer\tsfx\\sorceror\\mage12.wav\r\nSorceror13\tSorcerer\tsfx\\sorceror\\mage13.wav\r\nSorceror14\tSorcerer\tsfx\\sorceror\\mage14.wav\r\nSorceror15\tSorcerer\tsfx\\sorceror\\mage15.wav\r\nSorceror16\tSorcerer\tsfx\\sorceror\\mage16.wav\r\nSorceror17\tSorcerer\tsfx\\sorceror\\mage17.wav\r\nSorceror18\tSorcerer\tsfx\\sorceror\\mage18.wav\r\nSorceror19\tSorcerer\tsfx\\sorceror\\mage19.wav\r\nSorceror20\tSorcerer\tsfx\\sorceror\\mage20.wav\r\nSorceror21\tSorcerer\tsfx\\sorceror\\mage21.wav\r\nSorceror22\tSorcerer\tsfx\\sorceror\\mage22.wav\r\nSorceror23\tSorcerer\tsfx\\sorceror\\mage23.wav\r\nSorceror24\tSorcerer\tsfx\\sorceror\\mage24.wav\r\nSorceror25\tSorcerer\tsfx\\sorceror\\mage25.wav\r\nSorceror26\tSorcerer\tsfx\\sorceror\\mage26.wav\r\nSorceror27\tSorcerer\tsfx\\sorceror\\mage27.wav\r\nSorceror28\tSorcerer\tsfx\\sorceror\\mage28.wav\r\nSorceror29\tSorcerer\tsfx\\sorceror\\mage29.wav\r\nSorceror30\tSorcerer\tsfx\\sorceror\\mage30.wav\r\nSorceror31\tSorcerer\tsfx\\sorceror\\mage31.wav\r\nSorceror32\tSorcerer\tsfx\\sorceror\\mage32.wav\r\nSorceror33\tSorcerer\tsfx\\sorceror\\mage33.wav\r\nSorceror34\tSorcerer\tsfx\\sorceror\\mage34.wav\r\nSorceror35\tSorcerer\tsfx\\sorceror\\mage35.wav\r\nSorceror36\tSorcerer\tsfx\\sorceror\\mage36.wav\r\nSorceror37\tSorcerer\tsfx\\sorceror\\mage37.wav\r\nSorceror38\tSorcerer\tsfx\\sorceror\\mage38.wav\r\nSorceror39\tSorcerer\tsfx\\sorceror\\mage39.wav\r\nSorceror40\tSorcerer\tsfx\\sorceror\\mage40.wav\r\nSorceror41\tSorcerer\tsfx\\sorceror\\mage41.wav\r\nSorceror42\tSorcerer\tsfx\\sorceror\\mage42.wav\r\nSorceror43\tSorcerer\tsfx\\sorceror\\mage43.wav\r\nSorceror44\tSorcerer\tsfx\\sorceror\\mage44.wav\r\nSorceror45\tSorcerer\tsfx\\sorceror\\mage45.wav\r\nSorceror46\tSorcerer\tsfx\\sorceror\\mage46.wav\r\nSorceror47\tSorcerer\tsfx\\sorceror\\mage47.wav\r\nSorceror48\tSorcerer\tsfx\\sorceror\\mage48.wav\r\nSorceror49\tSorcerer\tsfx\\sorceror\\mage49.wav\r\nSorceror50\tSorcerer\tsfx\\sorceror\\mage50.wav\r\nSorceror51\tStream,Sorcerer\tsfx\\sorceror\\mage51.wav\r\nSorceror52\tStream,Sorcerer\tsfx\\sorceror\\mage52.wav\r\nSorceror53\tStream,Sorcerer\tsfx\\sorceror\\mage53.wav\r\nSorceror54\tStream,Sorcerer\tsfx\\sorceror\\mage54.wav\r\nSorceror55\tStream,Sorcerer\tsfx\\sorceror\\mage55.wav\r\nSorceror56\tStream,Sorcerer\tsfx\\sorceror\\mage56.wav\r\nSorceror57\tSorcerer\tsfx\\sorceror\\mage57.wav\r\nSorceror58\tStream,Sorcerer\tsfx\\sorceror\\mage58.wav\r\nSorceror59\tStream,Sorcerer\tsfx\\sorceror\\mage59.wav\r\nSorceror60\tStream,Sorcerer\tsfx\\sorceror\\mage60.wav\r\nSorceror61\tStream,Sorcerer\tsfx\\sorceror\\mage61.wav\r\nSorceror62\tStream,Sorcerer\tsfx\\sorceror\\mage62.wav\r\nSorceror63\tStream,Sorcerer\tsfx\\sorceror\\mage63.wav\r\nSorceror64\tSorcerer\tsfx\\sorceror\\mage64.wav\r\nSorceror65\tSorcerer\tsfx\\sorceror\\mage65.wav\r\nSorceror66\tSorcerer\tsfx\\sorceror\\mage66.wav\r\nSorceror67\tSorcerer\tsfx\\sorceror\\mage67.wav\r\nSorceror68\tSorcerer\tsfx\\sorceror\\mage68.wav\r\nSorceror69\tSorcerer\tsfx\\sorceror\\mage69.wav\r\nSorceror69b\tSorcerer\tsfx\\sorceror\\mage69b.wav\r\nSorceror70\tSorcerer\tsfx\\sorceror\\mage70.wav\r\nSorceror71\tSorcerer\tsfx\\sorceror\\mage71.wav\r\nSorceror72\tSorcerer\tsfx\\sorceror\\mage72.wav\r\nSorceror73\tSorcerer\tsfx\\sorceror\\mage73.wav\r\nSorceror74\tSorcerer\tsfx\\sorceror\\mage74.wav\r\nSorceror75\tSorcerer\tsfx\\sorceror\\mage75.wav\r\nSorceror76\tSorcerer\tsfx\\sorceror\\mage76.wav\r\nSorceror77\tSorcerer\tsfx\\sorceror\\mage77.wav\r\nSorceror78\tSorcerer\tsfx\\sorceror\\mage78.wav\r\nSorceror79\tSorcerer\tsfx\\sorceror\\mage79.wav\r\nSorceror80\tStream,Sorcerer\tsfx\\sorceror\\mage80.wav\r\nSorceror81\tStream,Sorcerer\tsfx\\sorceror\\mage81.wav\r\nSorceror82\tStream,Sorcerer\tsfx\\sorceror\\mage82.wav\r\nSorceror83\tStream,Sorcerer\tsfx\\sorceror\\mage83.wav\r\nSorceror84\tStream,Sorcerer\tsfx\\sorceror\\mage84.wav\r\nSorceror85\tStream,Sorcerer\tsfx\\sorceror\\mage85.wav\r\nSorceror86\tStream,Sorcerer\tsfx\\sorceror\\mage86.wav\r\nSorceror87\tStream,Sorcerer\tsfx\\sorceror\\mage87.wav\r\nSorceror88\tStream,Sorcerer\tsfx\\sorceror\\mage88.wav\r\nSorceror89\tStream,Sorcerer\tsfx\\sorceror\\mage89.wav\r\nSorceror90\tStream,Sorcerer\tsfx\\sorceror\\mage90.wav\r\nSorceror91\tStream,Sorcerer\tsfx\\sorceror\\mage91.wav\r\nSorceror92\tStream,Sorcerer\tsfx\\sorceror\\mage92.wav\r\nSorceror93\tStream,Sorcerer\tsfx\\sorceror\\mage93.wav\r\nSorceror94\tStream,Sorcerer\tsfx\\sorceror\\mage94.wav\r\nSorceror95\tStream,Sorcerer\tsfx\\sorceror\\mage95.wav\r\nSorceror96\tStream,Sorcerer\tsfx\\sorceror\\mage96.wav\r\nSorceror97\tStream,Sorcerer\tsfx\\sorceror\\mage97.wav\r\nSorceror98\tStream,Sorcerer\tsfx\\sorceror\\mage98.wav\r\nSorceror99\tStream,Sorcerer\tsfx\\sorceror\\mage99.wav\r\nSorceror100\tStream,Sorcerer\tsfx\\sorceror\\mage100.wav\r\nSorceror101\tStream,Sorcerer\tsfx\\sorceror\\mage101.wav\r\nSorceror102\tStream,Sorcerer\tsfx\\sorceror\\mage102.wav\r\nRogue1\tStream,Rogue\tsfx\\rogue\\rogue01.wav\r\nRogue2\tStream,Rogue\tsfx\\rogue\\rogue02.wav\r\nRogue3\tStream,Rogue\tsfx\\rogue\\rogue03.wav\r\nRogue4\tStream,Rogue\tsfx\\rogue\\rogue04.wav\r\nRogue5\tStream,Rogue\tsfx\\rogue\\rogue05.wav\r\nRogue6\tStream,Rogue\tsfx\\rogue\\rogue06.wav\r\nRogue7\tStream,Rogue\tsfx\\rogue\\rogue07.wav\r\nRogue8\tStream,Rogue\tsfx\\rogue\\rogue08.wav\r\nRogue9\tStream,Rogue\tsfx\\rogue\\rogue09.wav\r\nRogue10\tStream,Rogue\tsfx\\rogue\\rogue10.wav\r\nRogue11\tStream,Rogue\tsfx\\rogue\\rogue11.wav\r\nRogue12\tStream,Rogue\tsfx\\rogue\\rogue12.wav\r\nRogue13\tRogue\tsfx\\rogue\\rogue13.wav\r\nRogue14\tRogue\tsfx\\rogue\\rogue14.wav\r\nRogue15\tRogue\tsfx\\rogue\\rogue15.wav\r\nRogue16\tRogue\tsfx\\rogue\\rogue16.wav\r\nRogue17\tRogue\tsfx\\rogue\\rogue17.wav\r\nRogue18\tRogue\tsfx\\rogue\\rogue18.wav\r\nRogue19\tRogue\tsfx\\rogue\\rogue19.wav\r\nRogue20\tRogue\tsfx\\rogue\\rogue20.wav\r\nRogue21\tRogue\tsfx\\rogue\\rogue21.wav\r\nRogue22\tRogue\tsfx\\rogue\\rogue22.wav\r\nRogue23\tRogue\tsfx\\rogue\\rogue23.wav\r\nRogue24\tRogue\tsfx\\rogue\\rogue24.wav\r\nRogue25\tRogue\tsfx\\rogue\\rogue25.wav\r\nRogue26\tRogue\tsfx\\rogue\\rogue26.wav\r\nRogue27\tRogue\tsfx\\rogue\\rogue27.wav\r\nRogue28\tRogue\tsfx\\rogue\\rogue28.wav\r\nRogue29\tRogue\tsfx\\rogue\\rogue29.wav\r\nRogue30\tRogue\tsfx\\rogue\\rogue30.wav\r\nRogue31\tRogue\tsfx\\rogue\\rogue31.wav\r\nRogue32\tRogue\tsfx\\rogue\\rogue32.wav\r\nRogue33\tRogue\tsfx\\rogue\\rogue33.wav\r\nRogue34\tRogue\tsfx\\rogue\\rogue34.wav\r\nRogue35\tRogue\tsfx\\rogue\\rogue35.wav\r\nRogue36\tRogue\tsfx\\rogue\\rogue36.wav\r\nRogue37\tRogue\tsfx\\rogue\\rogue37.wav\r\nRogue38\tRogue\tsfx\\rogue\\rogue38.wav\r\nRogue39\tRogue\tsfx\\rogue\\rogue39.wav\r\nRogue40\tRogue\tsfx\\rogue\\rogue40.wav\r\nRogue41\tRogue\tsfx\\rogue\\rogue41.wav\r\nRogue42\tRogue\tsfx\\rogue\\rogue42.wav\r\nRogue43\tRogue\tsfx\\rogue\\rogue43.wav\r\nRogue44\tRogue\tsfx\\rogue\\rogue44.wav\r\nRogue45\tRogue\tsfx\\rogue\\rogue45.wav\r\nRogue46\tRogue\tsfx\\rogue\\rogue46.wav\r\nRogue47\tRogue\tsfx\\rogue\\rogue47.wav\r\nRogue48\tRogue\tsfx\\rogue\\rogue48.wav\r\nRogue49\tRogue\tsfx\\rogue\\rogue49.wav\r\nRogue50\tRogue\tsfx\\rogue\\rogue50.wav\r\nRogue51\tStream,Rogue\tsfx\\rogue\\rogue51.wav\r\nRogue52\tStream,Rogue\tsfx\\rogue\\rogue52.wav\r\nRogue53\tStream,Rogue\tsfx\\rogue\\rogue53.wav\r\nRogue54\tStream,Rogue\tsfx\\rogue\\rogue54.wav\r\nRogue55\tStream,Rogue\tsfx\\rogue\\rogue55.wav\r\nRogue56\tStream,Rogue\tsfx\\rogue\\rogue56.wav\r\nRogue57\tRogue\tsfx\\rogue\\rogue57.wav\r\nRogue58\tStream,Rogue\tsfx\\rogue\\rogue58.wav\r\nRogue59\tStream,Rogue\tsfx\\rogue\\rogue59.wav\r\nRogue60\tStream,Rogue\tsfx\\rogue\\rogue60.wav\r\nRogue61\tStream,Rogue\tsfx\\rogue\\rogue61.wav\r\nRogue62\tStream,Rogue\tsfx\\rogue\\rogue62.wav\r\nRogue63\tStream,Rogue\tsfx\\rogue\\rogue63.wav\r\nRogue64\tRogue\tsfx\\rogue\\rogue64.wav\r\nRogue65\tRogue\tsfx\\rogue\\rogue65.wav\r\nRogue66\tRogue\tsfx\\rogue\\rogue66.wav\r\nRogue67\tRogue\tsfx\\rogue\\rogue67.wav\r\nRogue68\tRogue\tsfx\\rogue\\rogue68.wav\r\nRogue69\tRogue\tsfx\\rogue\\rogue69.wav\r\nRogue69b\tRogue\tsfx\\rogue\\rogue69b.wav\r\nRogue70\tRogue\tsfx\\rogue\\rogue70.wav\r\nRogue71\tRogue\tsfx\\rogue\\rogue71.wav\r\nRogue72\tRogue\tsfx\\rogue\\rogue72.wav\r\nRogue73\tRogue\tsfx\\rogue\\rogue73.wav\r\nRogue74\tRogue\tsfx\\rogue\\rogue74.wav\r\nRogue75\tRogue\tsfx\\rogue\\rogue75.wav\r\nRogue76\tRogue\tsfx\\rogue\\rogue76.wav\r\nRogue77\tRogue\tsfx\\rogue\\rogue77.wav\r\nRogue78\tRogue\tsfx\\rogue\\rogue78.wav\r\nRogue79\tRogue\tsfx\\rogue\\rogue79.wav\r\nRogue80\tStream,Rogue\tsfx\\rogue\\rogue80.wav\r\nRogue81\tStream,Rogue\tsfx\\rogue\\rogue81.wav\r\nRogue82\tStream,Rogue\tsfx\\rogue\\rogue82.wav\r\nRogue83\tStream,Rogue\tsfx\\rogue\\rogue83.wav\r\nRogue84\tStream,Rogue\tsfx\\rogue\\rogue84.wav\r\nRogue85\tStream,Rogue\tsfx\\rogue\\rogue85.wav\r\nRogue86\tStream,Rogue\tsfx\\rogue\\rogue86.wav\r\nRogue87\tStream,Rogue\tsfx\\rogue\\rogue87.wav\r\nRogue88\tStream,Rogue\tsfx\\rogue\\rogue88.wav\r\nRogue89\tStream,Rogue\tsfx\\rogue\\rogue89.wav\r\nRogue90\tStream,Rogue\tsfx\\rogue\\rogue90.wav\r\nRogue91\tStream,Rogue\tsfx\\rogue\\rogue91.wav\r\nRogue92\tStream,Rogue\tsfx\\rogue\\rogue92.wav\r\nRogue93\tStream,Rogue\tsfx\\rogue\\rogue93.wav\r\nRogue94\tStream,Rogue\tsfx\\rogue\\rogue94.wav\r\nRogue95\tStream,Rogue\tsfx\\rogue\\rogue95.wav\r\nRogue96\tStream,Rogue\tsfx\\rogue\\rogue96.wav\r\nRogue97\tStream,Rogue\tsfx\\rogue\\rogue97.wav\r\nRogue98\tStream,Rogue\tsfx\\rogue\\rogue98.wav\r\nRogue99\tStream,Rogue\tsfx\\rogue\\rogue99.wav\r\nRogue100\tStream,Rogue\tsfx\\rogue\\rogue100.wav\r\nRogue101\tStream,Rogue\tsfx\\rogue\\rogue101.wav\r\nRogue102\tStream,Rogue\tsfx\\rogue\\rogue102.wav\r\nWarrior1\tStream,Warrior\tsfx\\warrior\\warior01.wav\r\nWarrior2\tStream,Warrior\tsfx\\warrior\\warior02.wav\r\nWarrior3\tStream,Warrior\tsfx\\warrior\\warior03.wav\r\nWarrior4\tStream,Warrior\tsfx\\warrior\\warior04.wav\r\nWarrior5\tStream,Warrior\tsfx\\warrior\\warior05.wav\r\nWarrior6\tStream,Warrior\tsfx\\warrior\\warior06.wav\r\nWarrior7\tStream,Warrior\tsfx\\warrior\\warior07.wav\r\nWarrior8\tStream,Warrior\tsfx\\warrior\\warior08.wav\r\nWarrior9\tStream,Warrior\tsfx\\warrior\\warior09.wav\r\nWarrior10\tStream,Warrior\tsfx\\warrior\\warior10.wav\r\nWarrior11\tStream,Warrior\tsfx\\warrior\\warior11.wav\r\nWarrior12\tStream,Warrior\tsfx\\warrior\\warior12.wav\r\nWarrior13\tWarrior\tsfx\\warrior\\warior13.wav\r\nWarrior14\tWarrior\tsfx\\warrior\\warior14.wav\r\nWarrior14b\tWarrior\tsfx\\warrior\\wario14b.wav\r\nWarrior14c\tWarrior\tsfx\\warrior\\wario14c.wav\r\nWarrior15\tWarrior\tsfx\\warrior\\warior15.wav\r\nWarrior15b\tWarrior\tsfx\\warrior\\wario15b.wav\r\nWarrior15c\tWarrior\tsfx\\warrior\\wario15c.wav\r\nWarrior16\tWarrior\tsfx\\warrior\\warior16.wav\r\nWarrior16b\tWarrior\tsfx\\warrior\\wario16b.wav\r\nWarrior16c\tWarrior\tsfx\\warrior\\wario16c.wav\r\nWarrior17\tWarrior\tsfx\\warrior\\warior17.wav\r\nWarrior18\tWarrior\tsfx\\warrior\\warior18.wav\r\nWarrior19\tWarrior\tsfx\\warrior\\warior19.wav\r\nWarrior20\tWarrior\tsfx\\warrior\\warior20.wav\r\nWarrior21\tWarrior\tsfx\\warrior\\warior21.wav\r\nWarrior22\tWarrior\tsfx\\warrior\\warior22.wav\r\nWarrior23\tWarrior\tsfx\\warrior\\warior23.wav\r\nWarrior24\tWarrior\tsfx\\warrior\\warior24.wav\r\nWarrior25\tWarrior\tsfx\\warrior\\warior25.wav\r\nWarrior26\tWarrior\tsfx\\warrior\\warior26.wav\r\nWarrior27\tWarrior\tsfx\\warrior\\warior27.wav\r\nWarrior28\tWarrior\tsfx\\warrior\\warior28.wav\r\nWarrior29\tWarrior\tsfx\\warrior\\warior29.wav\r\nWarrior30\tWarrior\tsfx\\warrior\\warior30.wav\r\nWarrior31\tWarrior\tsfx\\warrior\\warior31.wav\r\nWarrior32\tWarrior\tsfx\\warrior\\warior32.wav\r\nWarrior33\tWarrior\tsfx\\warrior\\warior33.wav\r\nWarrior34\tWarrior\tsfx\\warrior\\warior34.wav\r\nWarrior35\tWarrior\tsfx\\warrior\\warior35.wav\r\nWarrior36\tWarrior\tsfx\\warrior\\warior36.wav\r\nWarrior37\tWarrior\tsfx\\warrior\\warior37.wav\r\nWarrior38\tWarrior\tsfx\\warrior\\warior38.wav\r\nWarrior39\tWarrior\tsfx\\warrior\\warior39.wav\r\nWarrior40\tWarrior\tsfx\\warrior\\warior40.wav\r\nWarrior41\tWarrior\tsfx\\warrior\\warior41.wav\r\nWarrior42\tWarrior\tsfx\\warrior\\warior42.wav\r\nWarrior43\tWarrior\tsfx\\warrior\\warior43.wav\r\nWarrior44\tWarrior\tsfx\\warrior\\warior44.wav\r\nWarrior45\tWarrior\tsfx\\warrior\\warior45.wav\r\nWarrior46\tWarrior\tsfx\\warrior\\warior46.wav\r\nWarrior47\tWarrior\tsfx\\warrior\\warior47.wav\r\nWarrior48\tWarrior\tsfx\\warrior\\warior48.wav\r\nWarrior49\tWarrior\tsfx\\warrior\\warior49.wav\r\nWarrior50\tWarrior\tsfx\\warrior\\warior50.wav\r\nWarrior51\tStream,Warrior\tsfx\\warrior\\warior51.wav\r\nWarrior52\tStream,Warrior\tsfx\\warrior\\warior52.wav\r\nWarrior53\tStream,Warrior\tsfx\\warrior\\warior53.wav\r\nWarrior54\tStream,Warrior\tsfx\\warrior\\warior54.wav\r\nWarrior55\tStream,Warrior\tsfx\\warrior\\warior55.wav\r\nWarrior56\tStream,Warrior\tsfx\\warrior\\warior56.wav\r\nWarrior57\tWarrior\tsfx\\warrior\\warior57.wav\r\nWarrior58\tStream,Warrior\tsfx\\warrior\\warior58.wav\r\nWarrior59\tStream,Warrior\tsfx\\warrior\\warior59.wav\r\nWarrior60\tStream,Warrior\tsfx\\warrior\\warior60.wav\r\nWarrior61\tStream,Warrior\tsfx\\warrior\\warior61.wav\r\nWarrior62\tStream,Warrior\tsfx\\warrior\\warior62.wav\r\nWarrior63\tStream,Warrior\tsfx\\warrior\\warior63.wav\r\nWarrior64\tWarrior\tsfx\\warrior\\warior64.wav\r\nWarrior65\tWarrior\tsfx\\warrior\\warior65.wav\r\nWarrior66\tWarrior\tsfx\\warrior\\warior66.wav\r\nWarrior67\tWarrior\tsfx\\warrior\\warior67.wav\r\nWarrior68\tWarrior\tsfx\\warrior\\warior68.wav\r\nWarrior69\tWarrior\tsfx\\warrior\\warior69.wav\r\nWarrior69b\tWarrior\tsfx\\warrior\\wario69b.wav\r\nWarrior70\tWarrior\tsfx\\warrior\\warior70.wav\r\nWarrior71\tWarrior\tsfx\\warrior\\warior71.wav\r\nWarrior72\tWarrior\tsfx\\warrior\\warior72.wav\r\nWarrior73\tWarrior\tsfx\\warrior\\warior73.wav\r\nWarrior74\tWarrior\tsfx\\warrior\\warior74.wav\r\nWarrior75\tWarrior\tsfx\\warrior\\warior75.wav\r\nWarrior76\tWarrior\tsfx\\warrior\\warior76.wav\r\nWarrior77\tWarrior\tsfx\\warrior\\warior77.wav\r\nWarrior78\tWarrior\tsfx\\warrior\\warior78.wav\r\nWarrior79\tWarrior\tsfx\\warrior\\warior79.wav\r\nWarrior80\tStream,Warrior\tsfx\\warrior\\warior80.wav\r\nWarrior81\tStream,Warrior\tsfx\\warrior\\warior81.wav\r\nWarrior82\tStream,Warrior\tsfx\\warrior\\warior82.wav\r\nWarrior83\tStream,Warrior\tsfx\\warrior\\warior83.wav\r\nWarrior84\tStream,Warrior\tsfx\\warrior\\warior84.wav\r\nWarrior85\tStream,Warrior\tsfx\\warrior\\warior85.wav\r\nWarrior86\tStream,Warrior\tsfx\\warrior\\warior86.wav\r\nWarrior87\tStream,Warrior\tsfx\\warrior\\warior87.wav\r\nWarrior88\tStream,Warrior\tsfx\\warrior\\warior88.wav\r\nWarrior89\tStream,Warrior\tsfx\\warrior\\warior89.wav\r\nWarrior90\tStream,Warrior\tsfx\\warrior\\warior90.wav\r\nWarrior91\tStream,Warrior\tsfx\\warrior\\warior91.wav\r\nWarrior92\tStream,Warrior\tsfx\\warrior\\warior92.wav\r\nWarrior93\tStream,Warrior\tsfx\\warrior\\warior93.wav\r\nWarrior94\tStream,Warrior\tsfx\\warrior\\warior94.wav\r\nWarrior95\tStream,Warrior\tsfx\\warrior\\warior95.wav\r\nWarrior96b\tStream,Warrior\tsfx\\warrior\\wario96b.wav\r\nWarrior97\tStream,Warrior\tsfx\\warrior\\wario97.wav\r\nWarrior98\tStream,Warrior\tsfx\\warrior\\wario98.wav\r\nWarrior99\tStream,Warrior\tsfx\\warrior\\warior99.wav\r\nWarrior100\tStream,Warrior\tsfx\\warrior\\wario100.wav\r\nWarrior101\tStream,Warrior\tsfx\\warrior\\wario101.wav\r\nWarrior102\tStream,Warrior\tsfx\\warrior\\wario102.wav\r\nNarrator1\tStream\tsfx\\narrator\\nar01.wav\r\nNarrator2\tStream\tsfx\\narrator\\nar02.wav\r\nNarrator3\tStream\tsfx\\narrator\\nar03.wav\r\nNarrator4\tStream\tsfx\\narrator\\nar04.wav\r\nNarrator5\tStream\tsfx\\narrator\\nar05.wav\r\nNarrator6\tStream\tsfx\\narrator\\nar06.wav\r\nNarrator7\tStream\tsfx\\narrator\\nar07.wav\r\nNarrator8\tStream\tsfx\\narrator\\nar08.wav\r\nNarrator9\tStream\tsfx\\narrator\\nar09.wav\r\nDiabloGreeting\tStream\tsfx\\misc\\lvl16int.wav\r\nButcherGreeting\tStream\tsfx\\monsters\\butcher.wav\r\nGharbad1\tStream\tsfx\\monsters\\garbud01.wav\r\nGharbad2\tStream\tsfx\\monsters\\garbud02.wav\r\nGharbad3\tStream\tsfx\\monsters\\garbud03.wav\r\nGharbad4\tStream\tsfx\\monsters\\garbud04.wav\r\nLachdanan1\tStream\tsfx\\monsters\\lach01.wav\r\nLachdanan2\tStream\tsfx\\monsters\\lach02.wav\r\nLachdanan3\tStream\tsfx\\monsters\\lach03.wav\r\nLazarusGreeting\tStream\tsfx\\monsters\\laz01.wav\r\nLeoricGreeting\tStream\tsfx\\monsters\\sking01.wav\r\nSnotspill1\tStream\tsfx\\monsters\\snot01.wav\r\nSnotspill2\tStream\tsfx\\monsters\\snot02.wav\r\nSnotspill3\tStream\tsfx\\monsters\\snot03.wav\r\nWarlord\tStream\tsfx\\monsters\\warlrd01.wav\r\nZhar1\tStream\tsfx\\monsters\\zhar01.wav\r\nZhar2\tStream\tsfx\\monsters\\zhar02.wav\r\nDiabloDeath\tStream\tsfx\\monsters\\diablod.wav\r\nShootBow2\tMisc\tsfx\\misc\\sting1.wav\r\nShootFireballBow\tMisc\tsfx\\misc\\fballbow.wav\r\nPodExpload\tMisc\tsfx\\items\\podpop8.wav\r\nPodPop\tMisc\tsfx\\items\\podpop5.wav\r\nUrnExpload\tMisc\tsfx\\items\\urnpop3.wav\r\nUrnBreak\tMisc\tsfx\\items\\urnpop2.wav\r\nBigExplosion\tMisc\tsfx\\misc\\nestxpld.wav\r\nSpellLightningWall\tMisc\tsfx\\misc\\lmag.wav\r\nPig\tMisc\tsfx\\towners\\cow7.wav\r\nMonk1\tStream,Monk\tsfx\\monk\\monk01.wav\r\nMonk8\tStream,Monk\tsfx\\monk\\monk08.wav\r\nMonk9\tStream,Monk\tsfx\\monk\\monk09.wav\r\nMonk10\tStream,Monk\tsfx\\monk\\monk10.wav\r\nMonk11\tStream,Monk\tsfx\\monk\\monk11.wav\r\nMonk12\tStream,Monk\tsfx\\monk\\monk12.wav\r\nMonk13\tMonk\tsfx\\monk\\monk13.wav\r\nMonk14\tMonk\tsfx\\monk\\monk14.wav\r\nMonk15\tMonk\tsfx\\monk\\monk15.wav\r\nMonk16\tMonk\tsfx\\monk\\monk16.wav\r\nMonk24\tMonk\tsfx\\monk\\monk24.wav\r\nMonk27\tMonk\tsfx\\monk\\monk27.wav\r\nMonk29\tMonk\tsfx\\monk\\monk29.wav\r\nMonk34\tMonk\tsfx\\monk\\monk34.wav\r\nMonk35\tMonk\tsfx\\monk\\monk35.wav\r\nMonk43\tMonk\tsfx\\monk\\monk43.wav\r\nMonk46\tMonk\tsfx\\monk\\monk46.wav\r\nMonk49\tMonk\tsfx\\monk\\monk49.wav\r\nMonk50\tMonk\tsfx\\monk\\monk50.wav\r\nMonk52\tStream,Monk\tsfx\\monk\\monk52.wav\r\nMonk54\tStream,Monk\tsfx\\monk\\monk54.wav\r\nMonk55\tStream,Monk\tsfx\\monk\\monk55.wav\r\nMonk56\tStream,Monk\tsfx\\monk\\monk56.wav\r\nMonk61\tStream,Monk\tsfx\\monk\\monk61.wav\r\nMonk62\tStream,Monk\tsfx\\monk\\monk62.wav\r\nMonk68\tMonk\tsfx\\monk\\monk68.wav\r\nMonk69\tMonk\tsfx\\monk\\monk69.wav\r\nMonk69b\tMonk\tsfx\\monk\\monk69b.wav\r\nMonk70\tMonk\tsfx\\monk\\monk70.wav\r\nMonk71\tMonk\tsfx\\monk\\monk71.wav\r\nMonk79\tMonk\tsfx\\monk\\monk79.wav\r\nMonk80\tStream,Monk\tsfx\\monk\\monk80.wav\r\nMonk82\tStream,Monk\tsfx\\monk\\monk82.wav\r\nMonk83\tStream,Monk\tsfx\\monk\\monk83.wav\r\nMonk87\tStream,Monk\tsfx\\monk\\monk87.wav\r\nMonk88\tStream,Monk\tsfx\\monk\\monk88.wav\r\nMonk89\tStream,Monk\tsfx\\monk\\monk89.wav\r\nMonk91\tStream,Monk\tsfx\\monk\\monk91.wav\r\nMonk92\tStream,Monk\tsfx\\monk\\monk92.wav\r\nMonk94\tStream,Monk\tsfx\\monk\\monk94.wav\r\nMonk95\tStream,Monk\tsfx\\monk\\monk95.wav\r\nMonk96\tStream,Monk\tsfx\\monk\\monk96.wav\r\nMonk97\tStream,Monk\tsfx\\monk\\monk97.wav\r\nMonk98\tStream,Monk\tsfx\\monk\\monk98.wav\r\nMonk99\tStream,Monk\tsfx\\monk\\monk99.wav\r\nFarmer1\tStream\tsfx\\hellfire\\farmer1.wav\r\nFarmer2\tStream\tsfx\\hellfire\\farmer2.wav\r\nFarmer2a\tStream\tsfx\\hellfire\\Farmer2a.wav\r\nFarmer3\tStream\tsfx\\hellfire\\farmer3.wav\r\nFarmer4\tStream\tsfx\\hellfire\\farmer4.wav\r\nFarmer5\tStream\tsfx\\hellfire\\farmer5.wav\r\nFarmer6\tStream\tsfx\\hellfire\\farmer6.wav\r\nFarmer7\tStream\tsfx\\hellfire\\farmer7.wav\r\nFarmer8\tStream\tsfx\\hellfire\\farmer8.wav\r\nFarmer9\tStream\tsfx\\hellfire\\farmer9.wav\r\nCelia1\tStream\tsfx\\hellfire\\teddybr1.wav\r\nCelia2\tStream\tsfx\\hellfire\\teddybr2.wav\r\nCelia3\tStream\tsfx\\hellfire\\teddybr3.wav\r\nCelia4\tStream\tsfx\\hellfire\\teddybr4.wav\r\nDefiler1\tStream\tsfx\\hellfire\\defiler1.wav\r\nDefiler2\tStream\tsfx\\hellfire\\defiler2.wav\r\nDefiler3\tStream\tsfx\\hellfire\\defiler3.wav\r\nDefiler4\tStream\tsfx\\hellfire\\defiler4.wav\r\nDefiler8\tStream\tsfx\\hellfire\\defiler8.wav\r\nDefiler6\tStream\tsfx\\hellfire\\defiler6.wav\r\nDefiler7\tStream\tsfx\\hellfire\\defiler7.wav\r\nNaKrul1\tStream\tsfx\\hellfire\\nakrul1.wav\r\nNaKrul2\tStream\tsfx\\hellfire\\nakrul2.wav\r\nNaKrul3\tStream\tsfx\\hellfire\\nakrul3.wav\r\nNaKrul4\tStream\tsfx\\hellfire\\nakrul4.wav\r\nNaKrul5\tStream\tsfx\\hellfire\\nakrul5.wav\r\nNaKrul6\tStream\tsfx\\hellfire\\nakrul6.wav\r\nNarratorHF3\tStream\tsfx\\hellfire\\naratr3.wav\r\nCompleteNut1\tStream\tsfx\\hellfire\\cowsut1.wav\r\nCompleteNut2\tStream\tsfx\\hellfire\\cowsut2.wav\r\nCompleteNut3\tStream\tsfx\\hellfire\\cowsut3.wav\r\nCompleteNut4\tStream\tsfx\\hellfire\\cowsut4.wav\r\nCompleteNut4a\tStream\tsfx\\hellfire\\cowsut4a.wav\r\nCompleteNut5\tStream\tsfx\\hellfire\\cowsut5.wav\r\nCompleteNut6\tStream\tsfx\\hellfire\\cowsut6.wav\r\nCompleteNut7\tStream\tsfx\\hellfire\\cowsut7.wav\r\nCompleteNut8\tStream\tsfx\\hellfire\\cowsut8.wav\r\nCompleteNut9\tStream\tsfx\\hellfire\\cowsut9.wav\r\nCompleteNut10\tStream\tsfx\\hellfire\\cowsut10.wav\r\nCompleteNut11\tStream\tsfx\\hellfire\\cowsut11.wav\r\nCompleteNut12\tStream\tsfx\\hellfire\\cowsut12.wav\r\nNarratorHF6\tStream\tsfx\\hellfire\\naratr6.wav\r\nNarratorHF7\tStream\tsfx\\hellfire\\naratr7.wav\r\nNarratorHF8\tStream\tsfx\\hellfire\\naratr8.wav\r\nNarratorHF5\tStream\tsfx\\hellfire\\naratr5.wav\r\nNarratorHF9\tStream\tsfx\\hellfire\\naratr9.wav\r\nNarratorHF4\tStream\tsfx\\hellfire\\naratr4.wav\r\nCryptDoorOpen\tMisc\tsfx\\items\\cropen.wav\r\nCryptDoorClose\tMisc\tsfx\\items\\crclos.wav\r\nAccessibilityWeapon\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityArmor\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityGold\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityPotion\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityScroll\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityChest\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityDoor\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityStairs\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityMonster\tMisc\tsfx\\items\\titlemov.wav\r\nAccessibilityInteract\tMisc\tsfx\\items\\titlemov.wav"
  },
  {
    "path": "mods/Hellfire/txtdata/spells/spelldat.tsv",
    "content": "id\tname\tsoundId\tbookCost10\tstaffCost10\tmanaCost\tflags\tbookLevel\tstaffLevel\tminIntelligence\tmissiles\tmanaMultiplier\tminMana\tstaffMin\tstaffMax\r\nFirebolt\tFirebolt\tCastFire\t100\t5\t6\tFire,Targeted\t1\t1\t15\tFirebolt\t1\t3\t40\t80\r\nHealing\tHealing\tCastHealing\t100\t5\t5\tMagic,AllowedInTown\t1\t1\t17\tHealing\t3\t1\t20\t40\r\nLightning\tLightning\tCastLightning\t300\t15\t10\tLightning,Targeted\t4\t3\t20\tLightningControl\t1\t6\t20\t60\r\nFlash\tFlash\tCastLightning\t750\t50\t30\tLightning\t5\t4\t33\tFlashBottom,FlashTop\t2\t16\t20\t40\r\nIdentify\tIdentify\tCastSkill\t0\t10\t13\tMagic,AllowedInTown\t-1\t-1\t23\tIdentify\t2\t1\t8\t12\r\nFireWall\tFire Wall\tCastFire\t600\t40\t28\tFire,Targeted\t3\t2\t27\tFireWallControl\t2\t16\t8\t16\r\nTownPortal\tTown Portal\tCastSkill\t300\t20\t35\tMagic,Targeted\t3\t3\t20\tTownPortal\t3\t18\t8\t12\r\nStoneCurse\tStone Curse\tCastFire\t1200\t80\t60\tMagic,Targeted\t6\t5\t51\tStoneCurse\t3\t40\t8\t16\r\nInfravision\tInfravision\tCastHealing\t0\t60\t40\tMagic\t-1\t-1\t36\tInfravision\t5\t20\t0\t0\r\nPhasing\tPhasing\tCastFire\t350\t20\t12\tMagic\t7\t6\t39\tPhasing\t2\t4\t40\t80\r\nManaShield\tMana Shield\tCastFire\t1600\t120\t33\tMagic\t6\t5\t25\tManaShield\t0\t33\t4\t10\r\nFireball\tFireball\tCastFire\t800\t30\t16\tFire,Targeted\t8\t7\t48\tFireball\t1\t10\t40\t80\r\nGuardian\tGuardian\tCastFire\t1400\t95\t50\tFire,Targeted\t9\t8\t61\tGuardian\t2\t30\t16\t32\r\nChainLightning\tChain Lightning\tCastFire\t1100\t75\t30\tLightning\t8\t7\t54\tChainLightning\t1\t18\t20\t60\r\nFlameWave\tFlame Wave\tCastFire\t1000\t65\t35\tFire,Targeted\t9\t8\t54\tFlameWaveControl\t3\t20\t20\t40\r\nDoomSerpents\tDoom Serpents\tCastFire\t0\t0\t0\tLightning\t-1\t-1\t0\t\t0\t0\t40\t80\r\nBloodRitual\tBlood Ritual\tCastFire\t0\t0\t0\tMagic\t-1\t-1\t0\t\t0\t0\t40\t80\r\nNova\tNova\tCastLightning\t2100\t130\t60\tMagic\t14\t10\t87\tNova\t3\t35\t16\t32\r\nInvisibility\tInvisibility\tCastFire\t0\t0\t0\tMagic\t-1\t-1\t0\t\t0\t0\t40\t80\r\nInferno\tInferno\tCastFire\t200\t10\t11\tFire,Targeted\t3\t2\t20\tInfernoControl\t1\t6\t20\t40\r\nGolem\tGolem\tCastFire\t1800\t110\t100\tFire,Targeted\t11\t9\t81\tGolem\t6\t60\t16\t32\r\nRage\tRage\tCastHealing\t0\t0\t15\tMagic\t-1\t-1\t0\tRage\t1\t1\t0\t0\r\nTeleport\tTeleport\tCastSkill\t2000\t125\t35\tMagic,Targeted\t14\t12\t105\tTeleport\t3\t15\t16\t32\r\nApocalypse\tApocalypse\tCastFire\t3000\t200\t150\tFire\t19\t15\t149\tApocalypse\t6\t90\t8\t12\r\nEtherealize\tEtherealize\tCastFire\t2600\t160\t100\tMagic\t-1\t-1\t93\tEtherealize\t0\t100\t2\t6\r\nItemRepair\tItem Repair\tCastSkill\t0\t0\t0\tMagic,AllowedInTown\t-1\t-1\t255\tItemRepair\t0\t0\t40\t80\r\nStaffRecharge\tStaff Recharge\tCastSkill\t0\t0\t0\tMagic,AllowedInTown\t-1\t-1\t255\tStaffRecharge\t0\t0\t40\t80\r\nTrapDisarm\tTrap Disarm\tCastSkill\t0\t0\t0\tMagic\t-1\t-1\t255\tTrapDisarm\t0\t0\t40\t80\r\nElemental\tElemental\tCastFire\t1050\t70\t35\tFire\t8\t6\t68\tElemental\t2\t20\t20\t60\r\nChargedBolt\tCharged Bolt\tCastFire\t100\t5\t6\tLightning,Targeted\t1\t1\t25\tChargedBolt\t1\t6\t40\t80\r\nHolyBolt\tHoly Bolt\tCastFire\t100\t5\t7\tMagic,Targeted\t1\t1\t20\tHolyBolt\t1\t3\t40\t80\r\nResurrect\tResurrect\tCastHealing\t400\t25\t20\tMagic,AllowedInTown\t-1\t5\t30\tResurrect\t0\t20\t4\t10\r\nTelekinesis\tTelekinesis\tCastFire\t250\t20\t15\tMagic\t2\t2\t33\tTelekinesis\t2\t8\t20\t40\r\nHealOther\tHeal Other\tCastHealing\t100\t5\t5\tMagic,AllowedInTown\t1\t1\t17\tHealOther\t3\t1\t20\t40\r\nBloodStar\tBlood Star\tCastFire\t2750\t180\t25\tMagic\t14\t13\t70\tBloodStar\t2\t14\t20\t60\r\nBoneSpirit\tBone Spirit\tCastFire\t1150\t80\t24\tMagic\t9\t7\t34\tBoneSpirit\t1\t12\t20\t60\r\nMana\tMana\tCastHealing\t100\t5\t255\tMagic,AllowedInTown\t-1\t5\t17\tMana\t3\t1\t12\t24\r\nMagi\tthe Magi\tCastHealing\t10000\t20\t255\tMagic,AllowedInTown\t-1\t20\t45\tMagi\t3\t1\t15\t30\r\nJester\tthe Jester\tCastHealing\t10000\t20\t255\tMagic,Targeted\t-1\t4\t30\tJester\t3\t1\t15\t30\r\nLightningWall\tLightning Wall\tCastLightning\t600\t40\t28\tLightning,Targeted\t3\t2\t27\tLightningWallControl\t2\t16\t8\t16\r\nImmolation\tImmolation\tCastFire\t2100\t130\t60\tFire\t14\t10\t87\tImmolation\t3\t35\t16\t32\r\nWarp\tWarp\tCastSkill\t300\t20\t35\tMagic\t3\t3\t25\tWarp\t3\t18\t8\t12\r\nReflect\tReflect\tCastSkill\t300\t20\t35\tMagic\t3\t3\t25\tReflect\t3\t15\t8\t12\r\nBerserk\tBerserk\tCastSkill\t300\t20\t35\tMagic,Targeted\t3\t3\t35\tBerserk\t3\t15\t8\t12\r\nRingOfFire\tRing of Fire\tCastFire\t600\t40\t28\tFire\t5\t5\t27\tRingOfFire\t2\t16\t8\t16\r\nSearch\tSearch\tCastSkill\t300\t20\t15\tMagic\t1\t3\t25\tSearch\t1\t1\t8\t12\r\nRuneOfFire\tRune of Fire\tCastHealing\t800\t30\t255\tMagic,Targeted\t-1\t-1\t48\tRuneOfFire\t1\t10\t40\t80\r\nRuneOfLight\tRune of Light\tCastHealing\t800\t30\t255\tMagic,Targeted\t-1\t-1\t48\tRuneOfLight\t1\t10\t40\t80\r\nRuneOfNova\tRune of Nova\tCastHealing\t800\t30\t255\tMagic,Targeted\t-1\t-1\t48\tRuneOfNova\t1\t10\t40\t80\r\nRuneOfImmolation\tRune of Immolation\tCastHealing\t800\t30\t255\tMagic,Targeted\t-1\t-1\t48\tRuneOfImmolation\t1\t10\t40\t80\r\nRuneOfStone\tRune of Stone\tCastHealing\t800\t30\t255\tMagic,Targeted\t-1\t-1\t48\tRuneOfStone\t1\t10\t40\t80\r\n"
  },
  {
    "path": "mods/Hellfire/txtdata/towners/quest_dialog.tsv",
    "content": "towner_type\tQ_ROCK\tQ_MUSHROOM\tQ_GARBUD\tQ_ZHAR\tQ_VEIL\tQ_DIABLO\tQ_BUTCHER\tQ_LTBANNER\tQ_BLIND\tQ_BLOOD\tQ_ANVIL\tQ_WARLORD\tQ_SKELKING\tQ_PWATER\tQ_SCHAMB\tQ_BETRAYER\tQ_GRAVE\tQ_FARMER\tQ_GIRL\tQ_TRADER\tQ_DEFILER\tQ_NAKRUL\tQ_CORNSTN\tQ_JERSEY\nTOWN_SMITH\tTEXT_INFRA6\tTEXT_MUSH6\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL5\tTEXT_NONE\tTEXT_BUTCH5\tTEXT_BANNER6\tTEXT_BLIND5\tTEXT_BLOOD5\tTEXT_ANVIL6\tTEXT_WARLRD5\tTEXT_KING7\tTEXT_POISON7\tTEXT_BONE5\tTEXT_VILE9\tTEXT_GRAVE2\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_HEALER\tTEXT_INFRA3\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL3\tTEXT_NONE\tTEXT_BUTCH3\tTEXT_BANNER4\tTEXT_BLIND3\tTEXT_BLOOD3\tTEXT_ANVIL3\tTEXT_WARLRD3\tTEXT_KING5\tTEXT_POISON4\tTEXT_BONE3\tTEXT_VILE7\tTEXT_GRAVE3\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_DEADGUY\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_TAVERN\tTEXT_INFRA2\tTEXT_MUSH2\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL2\tTEXT_NONE\tTEXT_BUTCH2\tTEXT_NONE\tTEXT_BLIND2\tTEXT_BLOOD2\tTEXT_ANVIL2\tTEXT_WARLRD2\tTEXT_KING3\tTEXT_POISON2\tTEXT_BONE2\tTEXT_VILE4\tTEXT_GRAVE5\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_STORY\tTEXT_INFRA1\tTEXT_MUSH1\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL1\tTEXT_VILE3\tTEXT_BUTCH1\tTEXT_BANNER1\tTEXT_BLIND1\tTEXT_BLOOD1\tTEXT_ANVIL1\tTEXT_WARLRD1\tTEXT_KING1\tTEXT_POISON1\tTEXT_BONE1\tTEXT_VILE2\tTEXT_GRAVE6\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_DRUNK\tTEXT_INFRA8\tTEXT_MUSH7\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL6\tTEXT_NONE\tTEXT_BUTCH6\tTEXT_BANNER7\tTEXT_BLIND6\tTEXT_BLOOD6\tTEXT_ANVIL8\tTEXT_WARLRD6\tTEXT_KING8\tTEXT_POISON8\tTEXT_BONE6\tTEXT_VILE10\tTEXT_GRAVE7\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_WITCH\tTEXT_INFRA9\tTEXT_MUSH9\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL7\tTEXT_NONE\tTEXT_BUTCH7\tTEXT_BANNER8\tTEXT_BLIND7\tTEXT_BLOOD7\tTEXT_ANVIL9\tTEXT_WARLRD7\tTEXT_KING9\tTEXT_POISON9\tTEXT_BONE7\tTEXT_VILE11\tTEXT_GRAVE1\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_BMAID\tTEXT_INFRA4\tTEXT_MUSH5\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL4\tTEXT_NONE\tTEXT_BUTCH4\tTEXT_BANNER5\tTEXT_BLIND4\tTEXT_BLOOD4\tTEXT_ANVIL4\tTEXT_WARLRD4\tTEXT_KING6\tTEXT_POISON6\tTEXT_BONE4\tTEXT_VILE8\tTEXT_GRAVE8\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_PEGBOY\tTEXT_INFRA10\tTEXT_MUSH13\tTEXT_NONE\tTEXT_NONE\tTEXT_VEIL8\tTEXT_NONE\tTEXT_BUTCH8\tTEXT_BANNER9\tTEXT_BLIND8\tTEXT_BLOOD8\tTEXT_ANVIL10\tTEXT_WARLRD8\tTEXT_KING10\tTEXT_POISON10\tTEXT_BONE8\tTEXT_VILE12\tTEXT_GRAVE9\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_COW\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_FARMER\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_GIRL\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\nTOWN_COWFARM\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\tTEXT_NONE\n"
  },
  {
    "path": "mods/Hellfire/txtdata/towners/towners.tsv",
    "content": "type\tname\tposition_x\tposition_y\tdirection\tanimWidth\tanimPath\tanimFrames\tanimDelay\tgossipTexts\tanimOrder\nTOWN_SMITH\tGriswold the Blacksmith\t62\t63\tSouthWest\t96\ttowners\\smith\\smithn\t16\t3\tTEXT_GRISWOLD2,TEXT_GRISWOLD3,TEXT_GRISWOLD4,TEXT_GRISWOLD5,TEXT_GRISWOLD6,TEXT_GRISWOLD7,TEXT_GRISWOLD8,TEXT_GRISWOLD9,TEXT_GRISWOLD10,TEXT_GRISWOLD12,TEXT_GRISWOLD13\t4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,13,12,11,10,9,8,7,6,5,4,4,5,6,7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3\nTOWN_HEALER\tPepin the Healer\t55\t79\tSouthEast\t96\ttowners\\healer\\healer\t20\t6\tTEXT_PEPIN2,TEXT_PEPIN3,TEXT_PEPIN4,TEXT_PEPIN5,TEXT_PEPIN6,TEXT_PEPIN7,TEXT_PEPIN9,TEXT_PEPIN10,TEXT_PEPIN11\t0,1,2,2,1,0,19,18,18,19,0,1,2,2,1,0,19,18,18,19,0,1,2,2,1,0,19,18,18,19,0,1,2,2,1,0,19,18,18,19,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19\nTOWN_DEADGUY\tWounded Townsman\t24\t32\tNorth\t96\ttowners\\butch\\deadguy\t8\t6\t\t\nTOWN_TAVERN\tOgden the Tavern owner\t55\t62\tSouthWest\t96\ttowners\\twnf\\twnfn\t16\t3\tTEXT_OGDEN2,TEXT_OGDEN3,TEXT_OGDEN4,TEXT_OGDEN5,TEXT_OGDEN6,TEXT_OGDEN8,TEXT_OGDEN9,TEXT_OGDEN10\t0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,2,1,0,15,14,13,13,14,15,0,1,2,1,0,15,14,13,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\nTOWN_STORY\tCain the Elder\t62\t71\tSouth\t96\ttowners\\strytell\\strytell\t25\t3\tTEXT_STORY2,TEXT_STORY3,TEXT_STORY4,TEXT_STORY5,TEXT_STORY6,TEXT_STORY7,TEXT_STORY9,TEXT_STORY10,TEXT_STORY11\t0,0,24,24,23,22,21,20,19,18,17,16,15,14,15,16,17,18,19,20,21,22,23,24,24,24,0,0,0,24,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0\nTOWN_DRUNK\tFarnham the Drunk\t71\t84\tSouth\t96\ttowners\\drunk\\twndrunk\t18\t3\tTEXT_FARNHAM2,TEXT_FARNHAM3,TEXT_FARNHAM4,TEXT_FARNHAM5,TEXT_FARNHAM6,TEXT_FARNHAM8,TEXT_FARNHAM9,TEXT_FARNHAM10,TEXT_FARNHAM11,TEXT_FARNHAM12,TEXT_FARNHAM13\t0,0,0,1,2,3,4,5,6,7,8,9,10,10,10,10,11,12,13,14,15,16,17,17,0,0,0,17,16,15,14,13,12,11,10,9,10,11,12,13,14,15,16,17,0,1,2,3,4,4,4,3,2,1\nTOWN_WITCH\tAdria the Witch\t80\t20\tSouth\t96\ttowners\\townwmn1\\witch\t19\t6\tTEXT_ADRIA2,TEXT_ADRIA3,TEXT_ADRIA4,TEXT_ADRIA5,TEXT_ADRIA6,TEXT_ADRIA7,TEXT_ADRIA8,TEXT_ADRIA9,TEXT_ADRIA10,TEXT_ADRIA12,TEXT_ADRIA13\t3,3,3,4,5,5,5,4,3,14,13,12,12,12,13,14,3,4,5,5,5,4,3,3,3,4,5,5,5,4,3,14,13,12,12,12,13,14,3,4,5,5,5,4,3,3,3,4,5,5,5,4,3,14,13,12,12,12,13,14,3,4,5,5,5,4,3,2,1,0,18,17,18,0,1,0,18,17,18,0,1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,14,14,13,12,12,12,12,13,14,14,14,13,12,11,11,11,10,9,9,9,8,7,8,9,9,10,11,12,13,14,15,16,17,18,0,1,0,18,17,18,0,1,0,1,2\nTOWN_BMAID\tGillian the Barmaid\t43\t66\tSouth\t96\ttowners\\townwmn1\\wmnn\t18\t6\tTEXT_GILLIAN2,TEXT_GILLIAN3,TEXT_GILLIAN4,TEXT_GILLIAN5,TEXT_GILLIAN6,TEXT_GILLIAN7,TEXT_GILLIAN9,TEXT_GILLIAN10\t\nTOWN_PEGBOY\tWirt the Peg-legged boy\t11\t53\tSouth\t96\ttowners\\townboy\\pegkid1\t20\t6\tTEXT_WIRT2,TEXT_WIRT3,TEXT_WIRT4,TEXT_WIRT5,TEXT_WIRT6,TEXT_WIRT7,TEXT_WIRT8,TEXT_WIRT9,TEXT_WIRT11,TEXT_WIRT12\t\nTOWN_COW\tCow\t58\t16\tSouthWest\t128\t\t\t12\t3\t\t\nTOWN_COW\tCow\t56\t14\tNorthWest\t128\t\t\t12\t3\t\t\nTOWN_COW\tCow\t59\t20\tNorth\t128\t\t\t12\t3\t\t\nTOWN_COWFARM\tComplete Nut\t61\t22\tSouthWest\t96\ttowners\\farmer\\cfrmrn2\t15\t3\t\t\nTOWN_FARMER\tLester the farmer\t62\t16\tSouth\t96\ttowners\\farmer\\farmrn2\t15\t3\t\t\nTOWN_GIRL\tCelia\t77\t43\tSouth\t96\ttowners\\girl\\girlw1\t20\t6\t\t\n"
  },
  {
    "path": "test/.clang-format",
    "content": "BasedOnStyle: webkit\nAlignTrailingComments: true\nAllowShortBlocksOnASingleLine: true\nAllowShortCaseLabelsOnASingleLine: true\nAllowShortFunctionsOnASingleLine: All\nAllowShortIfStatementsOnASingleLine: WithoutElse\nPointerAlignment: Right\nTabWidth: 4\nUseTab: ForIndentation\nSortIncludes: true\nNamespaceIndentation: None\nFixNamespaceComments: true\nQualifierAlignment: Left\n"
  },
  {
    "path": "test/Fixtures.cmake",
    "content": "include(functions/copy_files)\r\n\r\nif(NOT DEFINED DEVILUTIONX_TEST_FIXTURES_OUTPUT_DIRECTORY)\r\n  set(DEVILUTIONX_TEST_FIXTURES_OUTPUT_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/test/fixtures\")\r\nendif()\r\n\r\nset(devilutionx_fixtures\r\n  diablo/1-2588.dun\r\n  diablo/1-743271966.dun\r\n  diablo/2-1383137027.dun\r\n  diablo/3-844660068.dun\r\n  diablo/4-609325643.dun\r\n  diablo/4-902156014.dun\r\n  diablo/5-68685319.dun\r\n  diablo/5-1677631846.dun\r\n  diablo/6-1824554527.dun\r\n  diablo/6-2034738122.dun\r\n  diablo/6-2033265779.dun\r\n  diablo/7-680552750.dun\r\n  diablo/7-1607627156.dun\r\n  diablo/8-1999936419.dun\r\n  diablo/9-262005438.dun\r\n  diablo/10-879635115.dun\r\n  diablo/10-1630062353.dun\r\n  diablo/11-384626536.dun\r\n  diablo/12-2104541047.dun\r\n  diablo/13-428074402.dun\r\n  diablo/13-594689775.dun\r\n  diablo/14-717625719.dun\r\n  diablo/14-815743776.dun\r\n  diablo/15-1256511996.dun\r\n  diablo/15-1583642716.dun\r\n  diablo/15-1583642716-changed.dun\r\n  diablo/16-741281013.dun\r\n  hellfire/1-401921334.dun\r\n  hellfire/1-536340718.dun\r\n  hellfire/2-128964898.dun\r\n  hellfire/2-1180526547.dun\r\n  hellfire/3-1369955278.dun\r\n  hellfire/3-1512491184.dun\r\n  hellfire/3-1799396623.dun\r\n  hellfire/4-1190318991.dun\r\n  hellfire/4-1924296259.dun\r\n  hellfire/17-19770182.dun\r\n  hellfire/18-1522546307.dun\r\n  hellfire/19-125121312.dun\r\n  hellfire/20-1511478689.dun\r\n  hellfire/21-2122696790.dun\r\n  hellfire/22-1191662129.dun\r\n  hellfire/23-97055268.dun\r\n  hellfire/24-1324803725.dun\r\n  levels/l1data/banner1.dun\r\n  levels/l1data/banner2.dun\r\n  levels/l1data/rnd6.dun\r\n  levels/l1data/skngdo.dun\r\n  levels/l2data/blind1.dun\r\n  levels/l2data/blood1.dun\r\n  levels/l2data/blood2.dun\r\n  levels/l2data/bonestr1.dun\r\n  levels/l2data/bonestr2.dun\r\n  levels/l3data/anvil.dun\r\n  levels/l4data/diab1.dun\r\n  levels/l4data/diab2a.dun\r\n  levels/l4data/diab2b.dun\r\n  levels/l4data/diab3a.dun\r\n  levels/l4data/diab3b.dun\r\n  levels/l4data/diab4a.dun\r\n  levels/l4data/diab4b.dun\r\n  levels/l4data/vile1.dun\r\n  levels/l4data/warlord.dun\r\n  levels/l4data/warlord2.dun\r\n  memory_map/additionalMissiles.txt\r\n  memory_map/game.txt\r\n  memory_map/hero.txt\r\n  memory_map/item.txt\r\n  memory_map/itemPack.txt\r\n  memory_map/level.txt\r\n  memory_map/levelSeed.txt\r\n  memory_map/lightning.txt\r\n  memory_map/missile.txt\r\n  memory_map/monster.txt\r\n  memory_map/object.txt\r\n  memory_map/player.txt\r\n  memory_map/portal.txt\r\n  memory_map/quest.txt\r\n  timedemo/WarriorLevel1to2/demo_0.dmo\r\n  timedemo/WarriorLevel1to2/demo_0_reference_spawn_0.sv\r\n  timedemo/WarriorLevel1to2/spawn_0.sv\r\n  txtdata/cr.tsv\r\n  txtdata/crlf.tsv\r\n  txtdata/empty.tsv\r\n  txtdata/empty_with_utf8_bom.tsv\r\n  txtdata/lf.tsv\r\n  txtdata/lf_no_trail.tsv\r\n  txtdata/sample.tsv\r\n  txtdata/utf8_bom.tsv\r\n)\r\n\r\ncopy_files(\r\n  FILES ${devilutionx_fixtures}\r\n  SRC_PREFIX test/fixtures/\r\n  OUTPUT_DIR \"${DEVILUTIONX_TEST_FIXTURES_OUTPUT_DIRECTORY}\"\r\n  OUTPUT_VARIABLE DEVILUTIONX_OUTPUT_TEST_FIXTURES_FILES\r\n)\r\n\r\nadd_custom_target(devilutionx_copied_fixtures DEPENDS ${DEVILUTIONX_OUTPUT_TEST_FIXTURES_FILES})\r\nadd_dependencies(test_main devilutionx_copied_fixtures)\r\n"
  },
  {
    "path": "test/animationinfo_test.cpp",
    "content": "#include <iomanip>\r\n\r\n#include <gtest/gtest.h>\r\n\r\n#include \"engine/animationinfo.h\"\r\n#include \"nthread.h\"\r\n\r\nusing namespace devilution;\r\n\r\nenum class TestDataType {\r\n\tSetNewAnimation,\r\n\tGameTick,\r\n\tRendering\r\n};\r\n\r\n/**\r\n * @brief Represents a Action in the game_logic or rendering.\r\n */\r\nstruct TestData {\r\n\tvirtual ~TestData() = default;\r\n\tvirtual TestDataType type() const = 0;\r\n};\r\n\r\n/**\r\n * @brief Represents a call to setNewAnimation\r\n */\r\nstruct SetNewAnimationData : public TestData {\r\n\tSetNewAnimationData(int numberOfFrames, int delayLen, AnimationDistributionFlags params = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0)\r\n\t{\r\n\t\t_NumberOfFrames = numberOfFrames;\r\n\t\t_DelayLen = delayLen;\r\n\t\t_Params = params;\r\n\t\t_NumSkippedFrames = numSkippedFrames;\r\n\t\t_DistributeFramesBeforeFrame = distributeFramesBeforeFrame;\r\n\t}\r\n\r\n\tTestDataType type() const override\r\n\t{\r\n\t\treturn TestDataType::SetNewAnimation;\r\n\t}\r\n\r\n\tint _NumberOfFrames;\r\n\tint _DelayLen;\r\n\tAnimationDistributionFlags _Params;\r\n\tint _NumSkippedFrames;\r\n\tint _DistributeFramesBeforeFrame;\r\n};\r\n\r\n/**\r\n * @brief Represents a GameTick, this includes skipping of Frames (for example because of Fastest Attack Modifier) and processAnimation (which also updates Animation Frame/Count).\r\n */\r\nstruct GameTickData : TestData {\r\n\tint _ExpectedAnimationFrame;\r\n\tint _ExpectedAnimationCnt;\r\n\tGameTickData(int expectedAnimationFrame, int expectedAnimationCnt)\r\n\t{\r\n\t\t_ExpectedAnimationFrame = expectedAnimationFrame;\r\n\t\t_ExpectedAnimationCnt = expectedAnimationCnt;\r\n\t}\r\n\r\n\tTestDataType type() const override\r\n\t{\r\n\t\treturn TestDataType::GameTick;\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief Represents a rendering/drawing Action.\r\n * This happens directly after the game_logic (_fProgressToNextGameTick = 0) or if no GameTick is due between two GameTicks (_fProgressToNextGameTick != 0).\r\n */\r\nstruct RenderingData : TestData {\r\n\t/**\r\n\t * @brief the progress as a fraction (0.0f to 1.0f) in time to the next game tick\r\n\t */\r\n\tfloat _fProgressToNextGameTick;\r\n\tint _ExpectedRenderingFrame;\r\n\tRenderingData(float fProgressToNextGameTick, int expectedRenderingFrame)\r\n\t{\r\n\t\tthis->_fProgressToNextGameTick = fProgressToNextGameTick;\r\n\t\tthis->_ExpectedRenderingFrame = expectedRenderingFrame;\r\n\t}\r\n\r\n\tTestDataType type() const override\r\n\t{\r\n\t\treturn TestDataType::Rendering;\r\n\t}\r\n};\r\n\r\n/**\r\n * @brief\r\n * This UnitTest tries to simulate the GameLoop (GameTickData) and the Rendering that can happen (RenderingData).\r\n * Rendering can happen more often than GameTicks and at any time between two GameTicks.\r\n * The Animation Distribution Logic must adjust to the Rendering that happens at any give point in time.\r\n */\r\nvoid RunAnimationTest(const std::vector<TestData *> &vecTestData)\r\n{\r\n\tAnimationInfo animInfo = {};\r\n\r\n\tint currentGameTick = 0;\r\n\tfor (TestData *x : vecTestData) {\r\n\t\tswitch (x->type()) {\r\n\t\tcase TestDataType::SetNewAnimation: {\r\n\t\t\tauto *setNewAnimationData = static_cast<SetNewAnimationData *>(x);\r\n\t\t\tanimInfo.setNewAnimation(std::nullopt, setNewAnimationData->_NumberOfFrames, setNewAnimationData->_DelayLen, setNewAnimationData->_Params, setNewAnimationData->_NumSkippedFrames, setNewAnimationData->_DistributeFramesBeforeFrame);\r\n\t\t} break;\r\n\t\tcase TestDataType::GameTick: {\r\n\t\t\tauto *gameTickData = static_cast<GameTickData *>(x);\r\n\t\t\tcurrentGameTick += 1;\r\n\t\t\tanimInfo.processAnimation();\r\n\t\t\tEXPECT_EQ(animInfo.currentFrame, gameTickData->_ExpectedAnimationFrame);\r\n\t\t\tEXPECT_EQ(animInfo.tickCounterOfCurrentFrame, gameTickData->_ExpectedAnimationCnt);\r\n\t\t} break;\r\n\t\tcase TestDataType::Rendering: {\r\n\t\t\tauto *renderingData = static_cast<RenderingData *>(x);\r\n\t\t\tProgressToNextGameTick = static_cast<uint8_t>(renderingData->_fProgressToNextGameTick * AnimationInfo::baseValueFraction);\r\n\t\t\tEXPECT_EQ(animInfo.getFrameToUseForRendering(), renderingData->_ExpectedRenderingFrame)\r\n\t\t\t    << std::fixed << std::setprecision(2)\r\n\t\t\t    << \"ProgressToNextGameTick: \" << renderingData->_fProgressToNextGameTick\r\n\t\t\t    << \" currentFrame: \" << animInfo.currentFrame\r\n\t\t\t    << \" DelayCounter: \" << animInfo.tickCounterOfCurrentFrame\r\n\t\t\t    << \" GameTick: \" << currentGameTick;\r\n\t\t} break;\r\n\t\t}\r\n\t}\r\n\tfor (TestData *x : vecTestData) {\r\n\t\tdelete x;\r\n\t}\r\n}\r\n\r\nTEST(AnimationInfo, AttackSwordWarrior) // ProcessAnimationPending should be considered by distribution logic\r\n{\r\n\tRunAnimationTest(\r\n\t    {\r\n\t        new SetNewAnimationData(16, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),\r\n\t        // processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.\r\n\t        new GameTickData(1, 0),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new RenderingData(0.8f, 0),\r\n\t        new GameTickData(2, 0),\r\n\t        new RenderingData(0.0f, 1),\r\n\t        new RenderingData(0.3f, 1),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new RenderingData(0.8f, 2),\r\n\t        new GameTickData(3, 0),\r\n\t        new RenderingData(0.0f, 2),\r\n\t        new RenderingData(0.3f, 2),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new RenderingData(0.8f, 3),\r\n\t        new GameTickData(4, 0),\r\n\t        new RenderingData(0.0f, 3),\r\n\t        new RenderingData(0.3f, 3),\r\n\t        new RenderingData(0.6f, 4),\r\n\t        new RenderingData(0.8f, 4),\r\n\t        new GameTickData(5, 0),\r\n\t        new RenderingData(0.0f, 4),\r\n\t        new RenderingData(0.3f, 4),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new RenderingData(0.8f, 5),\r\n\t        new GameTickData(6, 0),\r\n\t        new RenderingData(0.0f, 5),\r\n\t        new RenderingData(0.3f, 6),\r\n\t        new RenderingData(0.6f, 6),\r\n\t        new RenderingData(0.8f, 6),\r\n\t        new GameTickData(7, 0),\r\n\t        new RenderingData(0.0f, 6),\r\n\t        new RenderingData(0.3f, 7),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new RenderingData(0.8f, 7),\r\n\r\n\t        // After this GameTick, the Animation Distribution Logic is disabled\r\n\t        new GameTickData(8, 0),\r\n\t        new RenderingData(0.1f, 8),\r\n\t        new GameTickData(9, 0),\r\n\t        new RenderingData(0.4f, 9),\r\n\t        new GameTickData(10, 0),\r\n\t        new RenderingData(0.4f, 10),\r\n\t        new GameTickData(11, 0),\r\n\t        new RenderingData(0.3f, 11),\r\n\t        new GameTickData(12, 0),\r\n\t        new RenderingData(0.0f, 12),\r\n\t        new GameTickData(13, 0),\r\n\t        new RenderingData(0.6f, 13),\r\n\t        new GameTickData(14, 0),\r\n\t        new RenderingData(0.6f, 14),\r\n\t        new GameTickData(15, 0),\r\n\t        new RenderingData(0.6f, 15),\r\n\t        // Animation stopped because PM_DoAttack would stop the Animation \"if (plr[pnum].AnimInfo.currentFrame == plr[pnum]._pAFrames - 1) {\"\r\n\t    });\r\n}\r\n\r\nTEST(AnimationInfo, AttackSwordWarriorWithFastestAttack) // Skipped frames and ProcessAnimationPending should be considered by distribution logic\r\n{\r\n\tRunAnimationTest(\r\n\t    {\r\n\t        new SetNewAnimationData(16, 1, AnimationDistributionFlags::ProcessAnimationPending, 2, 9),\r\n\t        // processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.\r\n\t        new GameTickData(3, 0),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new RenderingData(0.8f, 1),\r\n\t        new GameTickData(4, 0),\r\n\t        new RenderingData(0.0f, 1),\r\n\t        new RenderingData(0.3f, 2),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new RenderingData(0.8f, 2),\r\n\t        new GameTickData(5, 0),\r\n\t        new RenderingData(0.0f, 3),\r\n\t        new RenderingData(0.3f, 3),\r\n\t        new RenderingData(0.6f, 4),\r\n\t        new RenderingData(0.8f, 4),\r\n\t        new GameTickData(6, 0),\r\n\t        new RenderingData(0.0f, 4),\r\n\t        new RenderingData(0.3f, 5),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new RenderingData(0.8f, 6),\r\n\t        new GameTickData(7, 0),\r\n\t        new RenderingData(0.0f, 6),\r\n\t        new RenderingData(0.3f, 6),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new RenderingData(0.8f, 7),\r\n\r\n\t        // After this GameTick, the Animation Distribution Logic is disabled\r\n\t        new GameTickData(8, 0),\r\n\t        new RenderingData(0.1f, 8),\r\n\t        new GameTickData(9, 0),\r\n\t        new RenderingData(0.4f, 9),\r\n\t        new GameTickData(10, 0),\r\n\t        new RenderingData(0.4f, 10),\r\n\t        new GameTickData(11, 0),\r\n\t        new RenderingData(0.3f, 11),\r\n\t        new GameTickData(12, 0),\r\n\t        new RenderingData(0.0f, 12),\r\n\t        new GameTickData(13, 0),\r\n\t        new RenderingData(0.6f, 13),\r\n\t        new GameTickData(14, 0),\r\n\t        new RenderingData(0.6f, 14),\r\n\t        new GameTickData(15, 0),\r\n\t        new RenderingData(0.6f, 15),\r\n\t        // Animation stopped because PM_DoAttack would stop the Animation \"if (plr[pnum].AnimInfo.currentFrame == plr[pnum]._pAFrames - 1) {\"\r\n\t    });\r\n}\r\n\r\n/**\r\n * @brief The Warrior make two attacks. The second queued attack cancels the first after the Hit Frame.\r\n */\r\nTEST(AnimationInfo, AttackSwordWarriorRepeated)\r\n{\r\n\tRunAnimationTest(\r\n\t    {\r\n\t        new SetNewAnimationData(16, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),\r\n\t        // processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.\r\n\t        new GameTickData(1, 0),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new RenderingData(0.8f, 0),\r\n\t        new GameTickData(2, 0),\r\n\t        new RenderingData(0.0f, 1),\r\n\t        new RenderingData(0.3f, 1),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new RenderingData(0.8f, 2),\r\n\t        new GameTickData(3, 0),\r\n\t        new RenderingData(0.0f, 2),\r\n\t        new RenderingData(0.3f, 2),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new RenderingData(0.8f, 3),\r\n\t        new GameTickData(4, 0),\r\n\t        new RenderingData(0.0f, 3),\r\n\t        new RenderingData(0.3f, 3),\r\n\t        new RenderingData(0.6f, 4),\r\n\t        new RenderingData(0.8f, 4),\r\n\t        new GameTickData(5, 0),\r\n\t        new RenderingData(0.0f, 4),\r\n\t        new RenderingData(0.3f, 4),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new RenderingData(0.8f, 5),\r\n\t        new GameTickData(6, 0),\r\n\t        new RenderingData(0.0f, 5),\r\n\t        new RenderingData(0.3f, 6),\r\n\t        new RenderingData(0.6f, 6),\r\n\t        new RenderingData(0.8f, 6),\r\n\t        new GameTickData(7, 0),\r\n\t        new RenderingData(0.0f, 6),\r\n\t        new RenderingData(0.3f, 7),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new RenderingData(0.8f, 7),\r\n\r\n\t        // After this GameTick, the Animation Distribution Logic is disabled\r\n\t        new GameTickData(8, 0),\r\n\t        new RenderingData(0.1f, 8),\r\n\t        new GameTickData(9, 0),\r\n\t        new RenderingData(0.3f, 9),\r\n\r\n\t        // Start of repeated attack, because plr[pnum].AnimInfo.currentFrame > plr[myplr]._pAFNum\r\n\t        new SetNewAnimationData(16, 1, static_cast<AnimationDistributionFlags>(AnimationDistributionFlags::ProcessAnimationPending | AnimationDistributionFlags::RepeatedAction), 0, 9),\r\n\t        // processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.\r\n\t        new GameTickData(1, 0),\r\n\t        new RenderingData(0.0f, 10),\r\n\t        new RenderingData(0.3f, 10),\r\n\t        new RenderingData(0.6f, 11),\r\n\t        new RenderingData(0.8f, 11),\r\n\t        new GameTickData(2, 0),\r\n\t        new RenderingData(0.0f, 12),\r\n\t        new RenderingData(0.3f, 12),\r\n\t        new RenderingData(0.6f, 13),\r\n\t        new RenderingData(0.8f, 13),\r\n\t        new GameTickData(3, 0),\r\n\t        new RenderingData(0.0f, 14),\r\n\t        new RenderingData(0.3f, 14),\r\n\t        new RenderingData(0.6f, 15),\r\n\t        new RenderingData(0.8f, 15),\r\n\t        new GameTickData(4, 0),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new RenderingData(0.8f, 1),\r\n\t        new GameTickData(5, 0),\r\n\t        new RenderingData(0.0f, 2),\r\n\t        new RenderingData(0.3f, 2),\r\n\t        new RenderingData(0.6f, 3),\r\n\t        new RenderingData(0.8f, 3),\r\n\t        new GameTickData(6, 0),\r\n\t        new RenderingData(0.0f, 4),\r\n\t        new RenderingData(0.3f, 4),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new RenderingData(0.8f, 5),\r\n\t        new GameTickData(7, 0),\r\n\t        new RenderingData(0.0f, 6),\r\n\t        new RenderingData(0.3f, 6),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new RenderingData(0.8f, 7),\r\n\r\n\t        // After this GameTick, the Animation Distribution Logic is disabled\r\n\t        new GameTickData(8, 0),\r\n\t        new RenderingData(0.1f, 8),\r\n\t        new GameTickData(9, 0),\r\n\t        new RenderingData(0.4f, 9),\r\n\t        new GameTickData(10, 0),\r\n\t        new RenderingData(0.4f, 10),\r\n\t        new GameTickData(11, 0),\r\n\t        new RenderingData(0.3f, 11),\r\n\t        new GameTickData(12, 0),\r\n\t        new RenderingData(0.0f, 12),\r\n\t        new GameTickData(13, 0),\r\n\t        new RenderingData(0.6f, 13),\r\n\t        new GameTickData(14, 0),\r\n\t        new RenderingData(0.6f, 14),\r\n\t        new GameTickData(15, 0),\r\n\t        new RenderingData(0.6f, 15),\r\n\t        // Animation stopped because PM_DoAttack would stop the Animation \"if (plr[pnum].AnimInfo.currentFrame == plr[pnum]._pAFrames - 1) {\"\r\n\t    });\r\n}\r\n\r\nTEST(AnimationInfo, BlockingWarriorNormal) // Ignored delay for last Frame should be considered by distribution logic\r\n{\r\n\tRunAnimationTest(\r\n\t    {\r\n\t        new SetNewAnimationData(2, 3, AnimationDistributionFlags::SkipsDelayOfLastFrame),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new RenderingData(0.8f, 0),\r\n\t        new GameTickData(0, 1),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new RenderingData(0.8f, 0),\r\n\t        new GameTickData(0, 2),\r\n\t        new RenderingData(0.0f, 1),\r\n\t        new RenderingData(0.3f, 1),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new RenderingData(0.8f, 1),\r\n\t        new GameTickData(1, 0),\r\n\t        new RenderingData(0.0f, 1),\r\n\t        new RenderingData(0.3f, 1),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new RenderingData(0.8f, 1),\r\n\t        // Animation stopped because PM_DoBlock would stop the Animation \"if (plr[pnum].AnimInfo.currentFrame >= plr[pnum]._pBFrames) {\"\r\n\t    });\r\n}\r\n\r\nTEST(AnimationInfo, BlockingSorcererWithFastBlock) // Skipped frames and ignored delay for last Frame should be considered by distribution logic\r\n{\r\n\tRunAnimationTest(\r\n\t    {\r\n\t        new SetNewAnimationData(6, 3, AnimationDistributionFlags::SkipsDelayOfLastFrame, 4),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new RenderingData(0.8f, 1),\r\n\t        new GameTickData(4, 1),\r\n\t        new RenderingData(0.0f, 1),\r\n\t        new RenderingData(0.3f, 1),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new RenderingData(0.8f, 2),\r\n\t        new GameTickData(4, 2),\r\n\t        new RenderingData(0.0f, 3),\r\n\t        new RenderingData(0.3f, 3),\r\n\t        new RenderingData(0.6f, 3),\r\n\t        new RenderingData(0.8f, 4),\r\n\t        new GameTickData(5, 0),\r\n\t        new RenderingData(0.0f, 4),\r\n\t        new RenderingData(0.3f, 4),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new RenderingData(0.8f, 5),\r\n\t        // Animation stopped because PM_DoBlock would stop the Animation \"if (plr[pnum].AnimInfo.currentFrame >= plr[pnum]._pBFrames) {\"\r\n\t    });\r\n}\r\n\r\nTEST(AnimationInfo, HitRecoverySorcererHarmony) // Skipped frames and ignored delay for last Frame should be considered by distribution logic\r\n{\r\n\tRunAnimationTest(\r\n\t    {\r\n\t        new SetNewAnimationData(8, 1, AnimationDistributionFlags::None, 3),\r\n\t        new RenderingData(0.0f, 0),\r\n\t        new RenderingData(0.3f, 0),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new RenderingData(0.8f, 1),\r\n\t        new GameTickData(4, 0),\r\n\t        new RenderingData(0.0f, 1),\r\n\t        new RenderingData(0.3f, 2),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new RenderingData(0.8f, 2),\r\n\t        new GameTickData(5, 0),\r\n\t        new RenderingData(0.0f, 3),\r\n\t        new RenderingData(0.3f, 3),\r\n\t        new RenderingData(0.6f, 4),\r\n\t        new RenderingData(0.8f, 4),\r\n\t        new GameTickData(6, 0),\r\n\t        new RenderingData(0.0f, 4),\r\n\t        new RenderingData(0.3f, 5),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new RenderingData(0.8f, 6),\r\n\t        new GameTickData(7, 0),\r\n\t        new RenderingData(0.0f, 6),\r\n\t        new RenderingData(0.3f, 6),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new RenderingData(0.8f, 7),\r\n\t        // Animation stopped because PM_DoGotHit would stop the Animation \"if (plr[pnum].AnimInfo.currentFrame >= plr[pnum]._pHFrames) {\"\r\n\t    });\r\n}\r\nTEST(AnimationInfo, Stand) // Distribution Logic shouldn't change anything here\r\n{\r\n\tRunAnimationTest(\r\n\t    {\r\n\t        new SetNewAnimationData(10, 4),\r\n\t        new RenderingData(0.1f, 0),\r\n\t        new GameTickData(0, 1),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new GameTickData(0, 2),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new GameTickData(0, 3),\r\n\t        new RenderingData(0.6f, 0),\r\n\r\n\t        new GameTickData(1, 0),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new GameTickData(1, 1),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new GameTickData(1, 2),\r\n\t        new RenderingData(0.6f, 1),\r\n\t        new GameTickData(1, 3),\r\n\t        new RenderingData(0.6f, 1),\r\n\r\n\t        new GameTickData(2, 0),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new GameTickData(2, 1),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new GameTickData(2, 2),\r\n\t        new RenderingData(0.6f, 2),\r\n\t        new GameTickData(2, 3),\r\n\t        new RenderingData(0.6f, 2),\r\n\r\n\t        new GameTickData(3, 0),\r\n\t        new RenderingData(0.6f, 3),\r\n\t        new GameTickData(3, 1),\r\n\t        new RenderingData(0.6f, 3),\r\n\t        new GameTickData(3, 2),\r\n\t        new RenderingData(0.6f, 3),\r\n\t        new GameTickData(3, 3),\r\n\t        new RenderingData(0.6f, 3),\r\n\r\n\t        new GameTickData(4, 0),\r\n\t        new RenderingData(0.6f, 4),\r\n\t        new GameTickData(4, 1),\r\n\t        new RenderingData(0.6f, 4),\r\n\t        new GameTickData(4, 2),\r\n\t        new RenderingData(0.6f, 4),\r\n\t        new GameTickData(4, 3),\r\n\t        new RenderingData(0.6f, 4),\r\n\r\n\t        new GameTickData(5, 0),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new GameTickData(5, 1),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new GameTickData(5, 2),\r\n\t        new RenderingData(0.6f, 5),\r\n\t        new GameTickData(5, 3),\r\n\t        new RenderingData(0.6f, 5),\r\n\r\n\t        new GameTickData(6, 0),\r\n\t        new RenderingData(0.6f, 6),\r\n\t        new GameTickData(6, 1),\r\n\t        new RenderingData(0.6f, 6),\r\n\t        new GameTickData(6, 2),\r\n\t        new RenderingData(0.6f, 6),\r\n\t        new GameTickData(6, 3),\r\n\t        new RenderingData(0.6f, 6),\r\n\r\n\t        new GameTickData(7, 0),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new GameTickData(7, 1),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new GameTickData(7, 2),\r\n\t        new RenderingData(0.6f, 7),\r\n\t        new GameTickData(7, 3),\r\n\t        new RenderingData(0.6f, 7),\r\n\r\n\t        new GameTickData(8, 0),\r\n\t        new RenderingData(0.6f, 8),\r\n\t        new GameTickData(8, 1),\r\n\t        new RenderingData(0.6f, 8),\r\n\t        new GameTickData(8, 2),\r\n\t        new RenderingData(0.6f, 8),\r\n\t        new GameTickData(8, 3),\r\n\t        new RenderingData(0.6f, 8),\r\n\r\n\t        new GameTickData(9, 0),\r\n\t        new RenderingData(0.6f, 9),\r\n\t        new GameTickData(9, 1),\r\n\t        new RenderingData(0.6f, 9),\r\n\t        new GameTickData(9, 2),\r\n\t        new RenderingData(0.6f, 9),\r\n\t        new GameTickData(9, 3),\r\n\t        new RenderingData(0.6f, 9),\r\n\r\n\t        // Animation starts again\r\n\t        new GameTickData(0, 0),\r\n\t        new RenderingData(0.1f, 0),\r\n\t        new GameTickData(0, 1),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new GameTickData(0, 2),\r\n\t        new RenderingData(0.6f, 0),\r\n\t        new GameTickData(0, 3),\r\n\t        new RenderingData(0.6f, 0),\r\n\t    });\r\n}\r\n"
  },
  {
    "path": "test/app_fatal_for_testing.cpp",
    "content": "#include <iostream>\r\n#include <string_view>\r\n\r\nnamespace devilution {\r\n\r\n[[noreturn]] void DisplayFatalErrorAndExit(std::string_view title, std::string_view body)\r\n{\r\n\tstd::cerr << \"fatal error: \" << title << \"\\n\"\r\n\t          << body << std::endl;\r\n\tstd::abort();\r\n}\r\n\r\n[[noreturn]] void app_fatal(std::string_view str)\r\n{\r\n\tstd::cerr << \"app_fatal: \" << str << std::endl;\r\n\tstd::abort();\r\n}\r\n\r\n[[noreturn]] void ErrDlg(const char *title, std::string_view error, std::string_view logFilePath, int logLineNr)\r\n{\r\n\tstd::cerr << \"ErrDlg: \" << title << \"\\n\"\r\n\t          << error << \"\\n\"\r\n\t          << logFilePath << \":\" << logLineNr << std::endl;\r\n\tstd::abort();\r\n}\r\n\r\n[[noreturn]] void assert_fail(int nLineNo, const char *pszFile, const char *pszFail)\r\n{\r\n\tstd::cerr << \"assert_fail: \" << pszFile << \":\" << nLineNo << \"\\n\"\r\n\t          << pszFail << std::endl;\r\n\tstd::abort();\r\n}\r\n\r\n[[noreturn]] void InsertCDDlg(std::string_view archiveName)\r\n{\r\n\tstd::cerr << \"InsertCDDlg error: \" << archiveName << std::endl;\r\n\tstd::abort();\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/appfat_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"appfat.h\"\r\n#include \"diablo.h\"\r\n\r\nusing namespace devilution;\r\n\r\nTEST(AppfatTest, app_fatal)\r\n{\r\n\tEXPECT_EXIT(app_fatal(\"test\"), ::testing::ExitedWithCode(1), \"test\");\r\n}\r\n\r\nTEST(AppfatTest, ErrDlg)\r\n{\r\n\tEXPECT_EXIT(ErrDlg(\"Title\", \"Unknown error\", \"appfat.cpp\", 7), ::testing::ExitedWithCode(1), \"Unknown error\\n\\nThe error occurred at: appfat.cpp line 7\");\r\n}\r\n\r\nTEST(AppfatTest, InsertCDDlg)\r\n{\r\n\tEXPECT_EXIT(InsertCDDlg(\"diabdat.mpq\"), ::testing::ExitedWithCode(1), \"diabdat.mpq\");\r\n}\r\n\r\nTEST(AppfatTest, DirErrorDlg)\r\n{\r\n\tEXPECT_EXIT(DirErrorDlg(\"/\"), ::testing::ExitedWithCode(1), \"Unable to write to location:\\n/\");\r\n}\r\n"
  },
  {
    "path": "test/automap_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"automap.h\"\r\n\r\nusing namespace devilution;\r\n\r\nTEST(Automap, InitAutomap)\r\n{\r\n\tInitAutomapOnce();\r\n\tEXPECT_EQ(AutomapActive, false);\r\n\tEXPECT_EQ(AutoMapScale, 50);\r\n\tEXPECT_EQ(AmLine(AmLineLength::DoubleTile), static_cast<int>(AmLineLength::FullTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::FullAndHalfTile), 6);\r\n\tEXPECT_EQ(AmLine(AmLineLength::FullTile), static_cast<int>(AmLineLength::HalfTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::HalfTile), static_cast<int>(AmLineLength::QuarterTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::QuarterTile), 1);\r\n}\r\n\r\nTEST(Automap, StartAutomap)\r\n{\r\n\tStartAutomap();\r\n\tEXPECT_EQ(AutomapOffset.deltaX, 0);\r\n\tEXPECT_EQ(AutomapOffset.deltaY, 0);\r\n\tEXPECT_EQ(AutomapActive, true);\r\n}\r\n\r\nTEST(Automap, AutomapUp)\r\n{\r\n\tAutomapOffset.deltaX = 1;\r\n\tAutomapOffset.deltaY = 1;\r\n\tAutomapUp();\r\n\tEXPECT_EQ(AutomapOffset.deltaX, 0);\r\n\tEXPECT_EQ(AutomapOffset.deltaY, 0);\r\n}\r\n\r\nTEST(Automap, AutomapDown)\r\n{\r\n\tAutomapOffset.deltaX = 1;\r\n\tAutomapOffset.deltaY = 1;\r\n\tAutomapDown();\r\n\tEXPECT_EQ(AutomapOffset.deltaX, 2);\r\n\tEXPECT_EQ(AutomapOffset.deltaY, 2);\r\n}\r\n\r\nTEST(Automap, AutomapLeft)\r\n{\r\n\tAutomapOffset.deltaX = 1;\r\n\tAutomapOffset.deltaY = 1;\r\n\tAutomapLeft();\r\n\tEXPECT_EQ(AutomapOffset.deltaX, 0);\r\n\tEXPECT_EQ(AutomapOffset.deltaY, 2);\r\n}\r\n\r\nTEST(Automap, AutomapRight)\r\n{\r\n\tAutomapOffset.deltaX = 1;\r\n\tAutomapOffset.deltaY = 1;\r\n\tAutomapRight();\r\n\tEXPECT_EQ(AutomapOffset.deltaX, 2);\r\n\tEXPECT_EQ(AutomapOffset.deltaY, 0);\r\n}\r\n\r\nTEST(Automap, AutomapZoomIn)\r\n{\r\n\tAutoMapScale = 50;\r\n\tAutomapZoomIn();\r\n\tEXPECT_EQ(AutoMapScale, 75);\r\n\tEXPECT_EQ(AmLine(AmLineLength::DoubleTile), static_cast<int>(AmLineLength::FullAndHalfTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::FullTile), 6);\r\n\tEXPECT_EQ(AmLine(AmLineLength::HalfTile), 3);\r\n\tEXPECT_EQ(AmLine(AmLineLength::QuarterTile), 1);\r\n}\r\n\r\nTEST(Automap, AutomapZoomIn_Max)\r\n{\r\n\tAutoMapScale = 175;\r\n\tAutoMapScale = 175;\r\n\tAutomapZoomIn();\r\n\tAutomapZoomIn();\r\n\tEXPECT_EQ(AutoMapScale, 200);\r\n\tEXPECT_EQ(AmLine(AmLineLength::DoubleTile), 32);\r\n\tEXPECT_EQ(AmLine(AmLineLength::FullTile), static_cast<int>(AmLineLength::DoubleTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::HalfTile), static_cast<int>(AmLineLength::FullTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::QuarterTile), static_cast<int>(AmLineLength::HalfTile));\r\n}\r\n\r\nTEST(Automap, AutomapZoomOut)\r\n{\r\n\tAutoMapScale = 200;\r\n\tAutomapZoomOut();\r\n\tEXPECT_EQ(AutoMapScale, 175);\r\n\tEXPECT_EQ(AmLine(AmLineLength::DoubleTile), 28);\r\n\tEXPECT_EQ(AmLine(AmLineLength::FullTile), 14);\r\n\tEXPECT_EQ(AmLine(AmLineLength::HalfTile), 7);\r\n\tEXPECT_EQ(AmLine(AmLineLength::QuarterTile), 3);\r\n}\r\n\r\nTEST(Automap, AutomapZoomOut_Min)\r\n{\r\n\tAutoMapScale = 50;\r\n\tAutomapZoomOut();\r\n\tAutomapZoomOut();\r\n\tEXPECT_EQ(AutoMapScale, 25);\r\n\tEXPECT_EQ(AmLine(AmLineLength::DoubleTile), static_cast<int>(AmLineLength::HalfTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::FullTile), static_cast<int>(AmLineLength::QuarterTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::HalfTile), 1);\r\n\tEXPECT_EQ(AmLine(AmLineLength::QuarterTile), 0);\r\n}\r\n\r\nTEST(Automap, AutomapZoomReset)\r\n{\r\n\tAutoMapScale = 50;\r\n\tAutomapOffset.deltaX = 1;\r\n\tAutomapOffset.deltaY = 1;\r\n\tAutomapZoomReset();\r\n\tEXPECT_EQ(AutomapOffset.deltaX, 0);\r\n\tEXPECT_EQ(AutomapOffset.deltaY, 0);\r\n\tEXPECT_EQ(AutoMapScale, 50);\r\n\tEXPECT_EQ(AmLine(AmLineLength::DoubleTile), static_cast<int>(AmLineLength::FullTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::FullTile), static_cast<int>(AmLineLength::HalfTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::HalfTile), static_cast<int>(AmLineLength::QuarterTile));\r\n\tEXPECT_EQ(AmLine(AmLineLength::QuarterTile), 1);\r\n}\r\n"
  },
  {
    "path": "test/clx_render_benchmark.cpp",
    "content": "#include <cstddef>\r\n\r\n#include <benchmark/benchmark.h>\r\n\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/load_clx.hpp\"\r\n#include \"engine/render/clx_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nvoid BM_RenderSmallClx(benchmark::State &state)\r\n{\r\n\tconst SDLSurfaceUniquePtr sdl_surface = SDLWrap::CreateRGBSurfaceWithFormat(\r\n\t    /*flags=*/0, /*width=*/640, /*height=*/480, /*depth=*/8, SDL_PIXELFORMAT_INDEX8);\r\n\tif (sdl_surface == nullptr) {\r\n\t\tLogError(\"Failed to create SDL Surface: {}\", SDL_GetError());\r\n\t\texit(1);\r\n\t}\r\n\tconst Surface out = Surface(sdl_surface.get());\r\n\tconst OwnedClxSpriteList sprites = LoadClx(\"data\\\\resistance.clx\");\r\n\r\n\tconst size_t numSprites = sprites.numSprites();\r\n\tfor (auto _ : state) {\r\n\t\tfor (size_t i = 0; i < numSprites; ++i) {\r\n\t\t\tRenderClxSprite(out, sprites[i], Point { static_cast<int>(i * 100), static_cast<int>(i * 60) });\r\n\t\t}\r\n\t\tuint8_t color = out[Point { 120, 120 }];\r\n\t\tbenchmark::DoNotOptimize(color);\r\n\t}\r\n\tstate.SetBytesProcessed(state.iterations() * sprites.dataSize());\r\n\tstate.SetItemsProcessed(state.iterations() * numSprites);\r\n}\r\n\r\nvoid BM_RenderLargeClx(benchmark::State &state)\r\n{\r\n\tconst SDLSurfaceUniquePtr sdl_surface = SDLWrap::CreateRGBSurfaceWithFormat(\r\n\t    /*flags=*/0, /*width=*/640, /*height=*/480, /*depth=*/8, SDL_PIXELFORMAT_INDEX8);\r\n\tif (sdl_surface == nullptr) {\r\n\t\tLogError(\"Failed to create SDL Surface: {}\", SDL_GetError());\r\n\t\texit(1);\r\n\t}\r\n\tconst Surface out = Surface(sdl_surface.get());\r\n\tconst OwnedClxSpriteList sprites = LoadClx(\"ui_art\\\\dvl_lrpopup.clx\");\r\n\r\n\tfor (auto _ : state) {\r\n\t\tRenderClxSprite(out, sprites[0], Point { 100, 100 });\r\n\t\tuint8_t color = out[Point { 120, 120 }];\r\n\t\tbenchmark::DoNotOptimize(color);\r\n\t}\r\n\tstate.SetBytesProcessed(state.iterations() * sprites.dataSize());\r\n\tstate.SetItemsProcessed(state.iterations());\r\n}\r\n\r\nBENCHMARK(BM_RenderSmallClx);\r\nBENCHMARK(BM_RenderLargeClx);\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/codec_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"codec.h\"\r\n\r\nusing namespace devilution;\r\n\r\nTEST(Codec, codec_get_encoded_len)\r\n{\r\n\tEXPECT_EQ(codec_get_encoded_len(50), 72);\r\n}\r\n\r\nTEST(Codec, codec_get_encoded_len_eq)\r\n{\r\n\tEXPECT_EQ(codec_get_encoded_len(128), 136);\r\n}\r\n"
  },
  {
    "path": "test/crawl_benchmark.cpp",
    "content": "#include <benchmark/benchmark.h>\r\n\r\n#include \"crawl.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nvoid BM_Crawl(benchmark::State &state)\r\n{\r\n\tconst int radius = static_cast<int>(state.range(0));\r\n\tfor (auto _ : state) {\r\n\t\tint sum;\r\n\t\tCrawl(0, radius, [&sum](Displacement d) {\r\n\t\t\tsum += d.deltaX + d.deltaY;\r\n\t\t\treturn false;\r\n\t\t});\r\n\t\tbenchmark::DoNotOptimize(sum);\r\n\t}\r\n}\r\n\r\nBENCHMARK(BM_Crawl)->RangeMultiplier(4)->Range(1, 20);\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/crawl_test.cpp",
    "content": "#include <cmath>\r\n\r\n#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"crawl.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\nusing ::testing::ElementsAre;\r\n\r\nTEST(CrawlTest, BasicTest)\r\n{\r\n\tbool added[40][40];\r\n\tmemset(added, 0, sizeof(added));\r\n\r\n\tint x = 20;\r\n\tint y = 20;\r\n\r\n\tconstexpr int MaxCrawlRadius = 18;\r\n\tCrawl(0, MaxCrawlRadius, [&](Displacement displacement) {\r\n\t\tconst int dx = x + displacement.deltaX;\r\n\t\tconst int dy = y + displacement.deltaY;\r\n\t\tEXPECT_EQ(added[dx][dy], false) << \"displacement \" << displacement.deltaX << \":\" << displacement.deltaY << \" added twice\";\r\n\t\tadded[dx][dy] = true;\r\n\t\treturn false;\r\n\t});\r\n\r\n\tfor (int i = -MaxCrawlRadius; i <= MaxCrawlRadius; i++) {\r\n\t\tfor (int j = -MaxCrawlRadius; j <= MaxCrawlRadius; j++) {\r\n\t\t\tif (added[i + 20][j + 20])\r\n\t\t\t\tcontinue;\r\n\t\t\tif (std::abs(i) == MaxCrawlRadius && std::abs(j) == MaxCrawlRadius)\r\n\t\t\t\tcontinue; // Limit of the crawl table rage\r\n\t\t\tEXPECT_EQ(false, true) << \"while checking location \" << i << \":\" << j;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nTEST(CrawlTest, VisitationOrderTest)\r\n{\r\n\tstd::vector<Displacement> order;\r\n\tCrawl(0, 2, [&](Displacement displacement) {\r\n\t\torder.push_back(displacement);\r\n\t\treturn false;\r\n\t});\r\n\tEXPECT_THAT(\r\n\t    order,\r\n\t    ElementsAre(\r\n\t        Displacement(0, 0),\r\n\t        Displacement(0, 1), Displacement(0, -1),\r\n\t        Displacement(-1, 0), Displacement(1, 0),\r\n\t        Displacement(0, 2), Displacement(0, -2),\r\n\t        Displacement(-1, 2), Displacement(1, 2), Displacement(-1, -2), Displacement(1, -2),\r\n\t        Displacement(-1, 1), Displacement(1, 1), Displacement(-1, -1), Displacement(1, -1),\r\n\t        Displacement(-2, 0), Displacement(2, 0), Displacement(-2, 1),\r\n\t        Displacement(2, 1), Displacement(-2, -1), Displacement(2, -1)));\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/cursor_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"cursor.h\"\r\n\r\nusing namespace devilution;\r\n\r\nTEST(Cursor, NewCursor)\r\n{\r\n\tNewCursor(CURSOR_HOURGLASS);\r\n\tEXPECT_EQ(pcurs, CURSOR_HOURGLASS);\r\n}\r\n"
  },
  {
    "path": "test/data_file_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"data/file.hpp\"\r\n#include \"data/parser.hpp\"\r\n\r\n#include <string_view>\r\n#include <vector>\r\n\r\n#include \"utils/paths.h\"\r\n\r\nnamespace devilution {\r\nauto LoadDataFile(std::string_view file)\r\n{\r\n\tconst std::string unitTestFolderCompletePath = paths::BasePath() + \"/test/fixtures/\";\r\n\tpaths::SetAssetsPath(unitTestFolderCompletePath);\r\n\treturn DataFile::load(file);\r\n}\r\n\r\nvoid TestFileContents(\r\n    const DataFile &dataFile,\r\n    std::vector<std::vector<std::string_view>> expectedContent,\r\n    GetFieldResult::Status expectedEndOfRecordStatus = GetFieldResult::Status::EndOfRecord,\r\n    GetFieldResult::Status expectedEndOfFileStatus = GetFieldResult::Status::EndOfFile)\r\n{\r\n\tGetFieldResult result { dataFile.data() };\r\n\tconst char *end = dataFile.data() + dataFile.size();\r\n\tunsigned row = 0;\r\n\tdo {\r\n\t\tASSERT_LT(row, expectedContent.size()) << \"Too many records\";\r\n\t\tunsigned col = 0;\r\n\t\tdo {\r\n\t\t\tASSERT_LT(col, expectedContent[row].size()) << \"Too many fields in record \" << row;\r\n\t\t\tresult = GetNextField(result.next, end);\r\n\t\t\tEXPECT_EQ(result.value, expectedContent[row][col]) << \"Unexpected value at record \" << row << \" and field \" << col;\r\n\t\t\tcol++;\r\n\t\t} while (!result.endOfRecord());\r\n\t\tif (!result.endOfFile()) {\r\n\t\t\tEXPECT_EQ(result.status, expectedEndOfRecordStatus) << \"Unexpected status when parsing the end of record \" << row;\r\n\t\t}\r\n\r\n\t\tEXPECT_EQ(col, expectedContent[row].size()) << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\trow++;\r\n\t} while (!result.endOfFile());\r\n\tEXPECT_EQ(result.status, expectedEndOfFileStatus) << \"Unexpected status when parsing the end of the file\";\r\n\r\n\tEXPECT_EQ(row, expectedContent.size()) << \"Parsing returned fewer records than expected\";\r\n}\r\n\r\nTEST(DataFileTest, TryLoadMissingFile)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\not_found.tsv\");\r\n\tEXPECT_FALSE(result.has_value()) << \"Trying to load a non-existent file should return an unexpected/error response\";\r\n\r\n\tEXPECT_EQ(result.error(), DataFile::Error::NotFound) << \"The error code should indicate the file was not found\";\r\n}\r\n\r\nTEST(DataFileTest, LoadCRFile)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\cr.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load cr.tsv\";\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\tEXPECT_EQ(dataFile.size(), 33) << \"File size should be reported in code units\";\r\n\r\n\tconst std::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" }\r\n\t};\r\n\r\n\tTestFileContents(dataFile, expectedFields, GetFieldResult::Status::BadRecordTerminator, GetFieldResult::Status::FileTruncated);\r\n}\r\n\r\nTEST(DataFileTest, LoadWindowsFile)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\crlf.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load crlf.tsv\";\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\tEXPECT_EQ(dataFile.size(), 37) << \"File size should be reported in code units\";\r\n\r\n\tconst std::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tTestFileContents(dataFile, expectedFields);\r\n}\r\n\r\nTEST(DataFileTest, LoadTypicalFile)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\tEXPECT_EQ(dataFile.size(), 33) << \"File size should be reported in code units\";\r\n\r\n\tconst std::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tTestFileContents(dataFile, expectedFields);\r\n}\r\n\r\nTEST(DataFileTest, LoadFileWithNoTrailingNewline)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\lf_no_trail.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load lf_no_trail.tsv\";\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\tEXPECT_EQ(dataFile.size(), 32) << \"File size should be reported in code units\";\r\n\r\n\tconst std::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tTestFileContents(dataFile, expectedFields, GetFieldResult::Status::EndOfRecord, GetFieldResult::Status::NoFinalTerminator);\r\n}\r\n\r\nstd::string_view mapError(DataFile::Error error)\r\n{\r\n\tswitch (error) {\r\n\tcase DataFile::Error::NotFound:\r\n\t\treturn \"not found\";\r\n\tcase DataFile::Error::OpenFailed:\r\n\t\treturn \"cannot open\";\r\n\tcase DataFile::Error::BadRead:\r\n\t\treturn \"cannot read contents\";\r\n\tdefault:\r\n\t\treturn \"unexpected error\";\r\n\t}\r\n}\r\n\r\nTEST(DataFileTest, LoadEmptyFile)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\empty.tsv\");\r\n\tif (!result.has_value()) {\r\n\t\tFAIL() << \"Unable to load empty.tsv, error: \" << mapError(result.error());\r\n\t}\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\tEXPECT_EQ(dataFile.size(), 0) << \"File size should be reported in code units\";\r\n\r\n\tconst std::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"\" },\r\n\t};\r\n\r\n\tTestFileContents(dataFile, expectedFields, GetFieldResult::Status::NoFinalTerminator, GetFieldResult::Status::NoFinalTerminator);\r\n}\r\n\r\nTEST(DataFileTest, LoadEmptyFileWithBOM)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\empty_with_utf8_bom.tsv\");\r\n\tif (!result.has_value()) {\r\n\t\tFAIL() << \"Unable to load empty_with_utf8_bom.tsv, error: \" << mapError(result.error());\r\n\t}\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\tEXPECT_EQ(dataFile.size(), 0) << \"Loading a file containing a UTF8 byte order marker should strip that prefix\";\r\n\r\n\tconst std::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"\" },\r\n\t};\r\n\r\n\tTestFileContents(dataFile, expectedFields, GetFieldResult::Status::NoFinalTerminator, GetFieldResult::Status::NoFinalTerminator);\r\n}\r\n\r\nTEST(DataFileTest, LoadUtf8WithBOM)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\utf8_bom.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load utf8_bom.tsv\";\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\tEXPECT_EQ(dataFile.size(), 33) << \"Loading a file containing a UTF8 byte order marker should strip that prefix\";\r\n\r\n\tconst std::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tTestFileContents(dataFile, expectedFields);\r\n}\r\n\r\nTEST(DataFileTest, ParseInt)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\sample.tsv\");\r\n\tif (!result.has_value()) {\r\n\t\tFAIL() << \"Unable to load sample.tsv, error: \" << mapError(result.error());\r\n\t}\r\n\r\n\tDataFile &dataFile = result.value();\r\n\tauto unused = dataFile.parseHeader(nullptr, nullptr, [](std::string_view) -> tl::expected<uint8_t, ColumnDefinition::Error> { return tl::unexpected { ColumnDefinition::Error::UnknownColumn }; });\r\n\r\n\tEXPECT_TRUE(unused.has_value()) << \"Should be able to parse and discard the header from the sample.tsv file\";\r\n\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tauto fieldIt = record.begin();\r\n\t\tauto end = record.end();\r\n\r\n\t\tASSERT_NE(fieldIt, end) << \"sample.tsv must contain at least one field to use as a test value for strings\";\r\n\r\n\t\t// First field is a string that doesn't start with a digit or - character\r\n\t\tDataFileField field = *fieldIt;\r\n\t\tuint8_t shortVal = 5;\r\n\t\tauto parseIntResult = field.parseInt(shortVal);\r\n\t\tif (parseIntResult.has_value()) {\r\n\t\t\tADD_FAILURE() << \"Parsing a string as an int should not succeed\";\r\n\t\t} else {\r\n\t\t\tEXPECT_EQ(parseIntResult.error(), DataFileField::Error::NotANumber) << \"Strings are not uint8_t values\";\r\n\t\t}\r\n\t\tEXPECT_EQ(shortVal, 5) << \"Value is not modified when parsing as uint8_t fails due to non-numeric fields\";\r\n\t\tEXPECT_EQ(*field, \"Sample\") << \"Should be able to access the field value as a string after failure\";\r\n\t\t++fieldIt;\r\n\r\n\t\tASSERT_NE(fieldIt, end) << \"sample.tsv must contain a second field to use as a test value for small ints\";\r\n\r\n\t\t// Second field is a number that fits into an uint8_t value\r\n\t\tfield = *fieldIt;\r\n\t\tshortVal = 5;\r\n\t\tparseIntResult = field.parseInt(shortVal);\r\n\t\tEXPECT_TRUE(parseIntResult.has_value()) << \"Expected \" << field << \" to fit into a uint8_t variable\";\r\n\t\tEXPECT_EQ(shortVal, 145) << \"Parsing should give the expected base 10 value\";\r\n\t\tEXPECT_EQ(*field, \"145\") << \"Should be able to access the field value as a string even after parsing as an int\";\r\n\r\n\t\tint longVal = 1;\r\n\t\tauto parseFixedResult = field.parseFixed6(longVal);\r\n\t\tEXPECT_TRUE(parseFixedResult.has_value()) << \"Expected \" << field << \" to be parsed as a fixed point integer with only the integer part\";\r\n\t\tEXPECT_EQ(longVal, 145 << 6) << \"Parsing should give the expected fixed point base 10 value\";\r\n\r\n\t\t++fieldIt;\r\n\r\n\t\tASSERT_NE(fieldIt, end) << \"sample.tsv must contain a third field to use as a test value for large ints\";\r\n\r\n\t\t// Third field is a number too large for a uint8_t but that fits into an int value\r\n\t\tfield = *fieldIt;\r\n\t\tparseIntResult = field.parseInt(shortVal);\r\n\t\tif (parseIntResult.has_value()) {\r\n\t\t\tADD_FAILURE() << \"Parsing an int into a short variable should not succeed\";\r\n\t\t} else {\r\n\t\t\tEXPECT_EQ(parseIntResult.error(), DataFileField::Error::OutOfRange) << \"A value too large to fit into a uint8_t variable should report an error\";\r\n\t\t}\r\n\t\tEXPECT_EQ(shortVal, 145) << \"Value is not modified when parsing as uint8_t fails due to out of range value\";\r\n\t\tlongVal = 42;\r\n\t\tparseIntResult = field.parseInt(longVal);\r\n\t\tEXPECT_TRUE(parseIntResult.has_value()) << \"Expected \" << field << \" to fit into an int variable\";\r\n\t\tEXPECT_EQ(longVal, 70322) << \"Value is expected to be parsed into a larger type after an out of range failure\";\r\n\t\tEXPECT_EQ(*field, \"70322\") << \"Should be able to access the field value as a string after parsing as an int\";\r\n\t\t++fieldIt;\r\n\r\n\t\tASSERT_NE(fieldIt, end) << \"sample.tsv must contain a fourth field to use as a test value for fields that look like ints\";\r\n\r\n\t\t// Fourth field is not an integer, but a value that starts with one or more digits that fit into an uint8_t value\r\n\t\tfield = *fieldIt;\r\n\t\tparseIntResult = field.parseInt(shortVal);\r\n\t\tEXPECT_TRUE(parseIntResult.has_value()) << \"Expected \" << field << \" to fit into a uint8_t variable (even though it's not really an int)\";\r\n\t\tEXPECT_EQ(shortVal, 6) << \"Value is loaded as expected until the first non-digit character\";\r\n\t\tEXPECT_EQ(*field, \"6.34\") << \"Should be able to access the field value as a string after parsing as an int\";\r\n\t\tint fixedVal = 64;\r\n\t\tparseFixedResult = field.parseFixed6(fixedVal);\r\n\t\tEXPECT_TRUE(parseFixedResult.has_value()) << \"Expected \" << field << \" to be parsed as a fixed point value\";\r\n\t\t// 6.34 is parsed as 384 (6<<6) + 22 (0.34 rounds to 0.34375, 22/64)\r\n\t\tEXPECT_EQ(fixedVal, 406) << \"Value is loaded as a fixed point number\";\r\n\r\n\t\tuint8_t shortFixedVal = 32;\r\n\t\tparseFixedResult = field.parseFixed6(shortFixedVal);\r\n\t\tEXPECT_FALSE(parseFixedResult.has_value()) << \"Expected \" << field << \" to fail to parse into a 2.6 fixed point variable\";\r\n\t\tEXPECT_EQ(parseFixedResult.error(), DataFileField::Error::OutOfRange) << \"A value too large to fit into a 2 bit integer part should report an error\";\r\n\t\tEXPECT_EQ(shortFixedVal, 32) << \"The variable should not be modified when parsing fails\";\r\n\r\n\t\t++fieldIt;\r\n\r\n\t\tASSERT_NE(fieldIt, end) << \"sample.tsv must contain a fifth field to use as a test value for fixed point overflow\";\r\n\r\n\t\tfield = *fieldIt;\r\n\t\tparseFixedResult = field.parseFixed6(shortFixedVal);\r\n\t\tEXPECT_FALSE(parseFixedResult.has_value()) << \"Expected \" << field << \" to fail to parse into a 2.6 fixed point variable\";\r\n\t\tEXPECT_EQ(parseFixedResult.error(), DataFileField::Error::OutOfRange) << \"A value that after rounding is too large to fit into a 2 bit integer part should report an error\";\r\n\t\tEXPECT_EQ(shortFixedVal, 32) << \"The variable should not be modified when parsing fails\";\r\n\t}\r\n}\r\n\r\nTEST(DataFileTest, IterateOverRecords)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\r\n\tstd::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tunsigned row = 0;\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tASSERT_LT(row, expectedFields.size()) << \"Too many records\";\r\n\t\tunsigned col = 0;\r\n\t\tfor (DataFileField field : record) {\r\n\t\t\tif (col < expectedFields[row].size())\r\n\t\t\t\tEXPECT_EQ(*field, expectedFields[row][col]) << \"Unexpected value at record \" << row << \" and field \" << col;\r\n\t\t\telse\r\n\t\t\t\tADD_FAILURE() << \"Extra value '\" << field << \"' in record \" << row << \" at field \" << col;\r\n\t\t\tcol++;\r\n\t\t}\r\n\t\tEXPECT_GE(col, expectedFields[row].size()) << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\trow++;\r\n\t}\r\n\tEXPECT_EQ(row, expectedFields.size()) << \"Parsing returned fewer records than expected\";\r\n}\r\n\r\nTEST(DataFileTest, ParseHeaderThenIterateOverRecords)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tDataFile &dataFile = result.value();\r\n\r\n\tstd::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tauto parseHeaderResult = dataFile.parseHeader(nullptr, nullptr, [](std::string_view) -> tl::expected<uint8_t, ColumnDefinition::Error> { return tl::unexpected { ColumnDefinition::Error::UnknownColumn }; });\r\n\tEXPECT_TRUE(parseHeaderResult.has_value()) << \"Expected to be able to parse and discard the header record\";\r\n\r\n\tunsigned row = 0;\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tASSERT_LT(row, expectedFields.size()) << \"Too many records\";\r\n\t\tEXPECT_EQ(row + 1, record.row()) << \"DataFileRecord (through iterator) should report a 1-indexed row after parsing the header record\";\r\n\t\tunsigned col = 0;\r\n\t\tfor (DataFileField field : record) {\r\n\t\t\tEXPECT_EQ(record.row(), field.row()) << \"Field should report the same row as the current DataFileRecord\";\r\n\t\t\tEXPECT_EQ(col, field.column()) << \"Field (through iterator) should report a 0-indexed column\";\r\n\t\t\tif (col < expectedFields[row].size())\r\n\t\t\t\tEXPECT_EQ(*field, expectedFields[row][col]) << \"Unexpected value at record \" << row << \" and field \" << col;\r\n\t\t\telse\r\n\t\t\t\tADD_FAILURE() << \"Extra value '\" << field << \"' in record \" << row << \" at field \" << col;\r\n\t\t\tcol++;\r\n\t\t}\r\n\t\tEXPECT_GE(col, expectedFields[row].size()) << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\trow++;\r\n\t}\r\n\tEXPECT_EQ(row, expectedFields.size()) << \"Parsing returned fewer records than expected\";\r\n}\r\n\r\nTEST(DataFileTest, DiscardAllAfterFirstField)\r\n{\r\n\tauto loadDataResult = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(loadDataResult.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tconst DataFile &dataFile = loadDataResult.value();\r\n\r\n\tstd::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tGetFieldResult result { dataFile.data() };\r\n\tconst char *end = dataFile.data() + dataFile.size();\r\n\tunsigned row = 0;\r\n\tdo {\r\n\t\tASSERT_LT(row, expectedFields.size()) << \"Too many records\";\r\n\t\tresult = GetNextField(result.next, end);\r\n\t\tEXPECT_EQ(result.value, expectedFields[row][0]) << \"Unexpected first value at record \" << row;\r\n\r\n\t\tif (result.endOfRecord() && !result.endOfFile())\r\n\t\t\tADD_FAILURE() << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\telse\r\n\t\t\tresult = DiscardRemainingFields(result.next, end);\r\n\t\trow++;\r\n\t} while (!result.endOfFile());\r\n\r\n\tEXPECT_EQ(row, expectedFields.size()) << \"Parsing returned fewer records than expected\";\r\n}\r\n\r\nTEST(DataFileTest, DiscardAllAfterFirstFieldIterator)\r\n{\r\n\tauto result = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(result.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tconst DataFile &dataFile = result.value();\r\n\r\n\tstd::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tunsigned row = 0;\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tASSERT_LT(row, expectedFields.size()) << \"Too many records\";\r\n\t\tfor (DataFileField field : record) {\r\n\t\t\tEXPECT_EQ(*field, expectedFields[row][0]) << \"Field with value \" << field << \" does not match the expected value for record \" << row;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\trow++;\r\n\t}\r\n}\r\n\r\nTEST(DataFileTest, DiscardAllUpToLastField)\r\n{\r\n\tauto loadDataResult = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(loadDataResult.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tconst DataFile &dataFile = loadDataResult.value();\r\n\r\n\tstd::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tGetFieldResult result { dataFile.data() };\r\n\tconst char *const end = dataFile.data() + dataFile.size();\r\n\tunsigned row = 0;\r\n\tdo {\r\n\t\tASSERT_LT(row, expectedFields.size()) << \"Too many records\";\r\n\t\tresult = DiscardMultipleFields(result.next, end, 2);\r\n\t\tif (row < expectedFields.size()) {\r\n\t\t\tEXPECT_FALSE(result.endOfRecord()) << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\t\tif (!result.endOfRecord())\r\n\t\t\t\tresult = GetNextField(result.next, end);\r\n\t\t}\r\n\t\tEXPECT_EQ(result.value, expectedFields[row][2]) << \"Unexpected last value at record \" << row;\r\n\r\n\t\tif (!result.endOfRecord()) {\r\n\t\t\tADD_FAILURE() << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\t\tresult = DiscardRemainingFields(result.next, end);\r\n\t\t}\r\n\t\trow++;\r\n\t} while (!result.endOfFile());\r\n\r\n\tEXPECT_EQ(row, expectedFields.size()) << \"Parsing returned fewer records than expected\";\r\n}\r\n\r\nTEST(DataFileTest, SkipFieldIterator)\r\n{\r\n\tauto loadDataResult = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(loadDataResult.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tconst DataFile &dataFile = loadDataResult.value();\r\n\r\n\tstd::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tunsigned row = 0;\r\n\tfor (DataFileRecord record : dataFile) {\r\n\t\tASSERT_LT(row, expectedFields.size()) << \"Too many records\";\r\n\t\tauto fieldIt = record.begin();\r\n\t\tauto endField = record.end();\r\n\t\tfieldIt += 0;\r\n\t\tEXPECT_EQ((*fieldIt).value(), expectedFields[row][0]) << \"Advancing a field iterator by 0 should not discard any values\";\r\n\r\n\t\tfieldIt += 2;\r\n\t\tif (row < expectedFields.size()) {\r\n\t\t\tif (fieldIt == endField) {\r\n\t\t\t\tADD_FAILURE() << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\t\t} else {\r\n\t\t\t\tEXPECT_EQ((*fieldIt).value(), expectedFields[row][2]) << \"Unexpected last value at record \" << row;\r\n\t\t\t\t++fieldIt;\r\n\t\t\t}\r\n\t\t}\r\n\t\tEXPECT_EQ(fieldIt, endField) << \"Parsing returned more fields than expected in record \" << row;\r\n\t\tEXPECT_EQ(fieldIt.column(), expectedFields[row].size() - 1) << \"Field iterator should report the index of the last column\";\r\n\r\n\t\t++row;\r\n\t}\r\n\r\n\tEXPECT_EQ(row, expectedFields.size()) << \"Parsing returned fewer records than expected\";\r\n}\r\n\r\nTEST(DataFileTest, SkipRowIterator)\r\n{\r\n\tauto loadDataResult = LoadDataFile(\"txtdata\\\\lf.tsv\");\r\n\tASSERT_TRUE(loadDataResult.has_value()) << \"Unable to load lf.tsv\";\r\n\r\n\tconst DataFile &dataFile = loadDataResult.value();\r\n\r\n\tstd::vector<std::vector<std::string_view>> expectedFields {\r\n\t\t{ \"Test\", \"Empty\", \"Values\" },\r\n\t\t{ \"\", \"2\", \"3\" },\r\n\t\t{ \"1\", \"2\", \"\" },\r\n\t\t{ \"1\", \"\", \"3\" },\r\n\t};\r\n\r\n\tauto recordIt = dataFile.begin();\r\n\tauto endRecord = dataFile.end();\r\n\trecordIt += 0;\r\n\tEXPECT_EQ((*(*recordIt).begin()).value(), expectedFields[0][0]) << \"Advancing a record iterator by 0 should not discard any values\";\r\n\trecordIt += 2;\r\n\tunsigned row = 2;\r\n\twhile (recordIt != endRecord) {\r\n\t\tASSERT_LT(row, expectedFields.size()) << \"Too many records\";\r\n\t\tunsigned col = 0;\r\n\t\tfor (DataFileField field : *recordIt) {\r\n\t\t\tif (col < expectedFields[row].size())\r\n\t\t\t\tEXPECT_EQ(*field, expectedFields[row][col]) << \"Unexpected value at record \" << row << \" and field \" << col;\r\n\t\t\telse\r\n\t\t\t\tADD_FAILURE() << \"Extra value '\" << field << \"' in record \" << row << \" at field \" << col;\r\n\t\t\tcol++;\r\n\t\t}\r\n\t\tEXPECT_GE(col, expectedFields[row].size()) << \"Parsing returned fewer fields than expected in record \" << row;\r\n\t\t++row;\r\n\t\t++recordIt;\r\n\t}\r\n\r\n\tEXPECT_EQ(row, expectedFields.size()) << \"Parsing returned fewer records than expected\";\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/dead_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"dead.h\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nusing namespace devilution;\r\n\r\nTEST(Corpses, AddCorpse)\r\n{\r\n\tAddCorpse({ 21, 48 }, 8, Direction::West);\r\n\tEXPECT_EQ(dCorpse[21][48], 8 + (static_cast<int>(Direction::West) << 5));\r\n}\r\n\r\nTEST(Corpses, AddCorpse_OOB)\r\n{\r\n\tAddCorpse({ 21, 48 }, MaxCorpses + 1, Direction::West);\r\n\tEXPECT_EQ(dCorpse[21][48], 0 + (static_cast<int>(Direction::West) << 5));\r\n}\r\n"
  },
  {
    "path": "test/diablo_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"diablo.h\"\r\n#include \"multi.h\"\r\n\r\nusing namespace devilution;\r\n\r\nTEST(Diablo, diablo_pause_game_unpause)\r\n{\r\n\tgbIsMultiplayer = false;\r\n\tPauseMode = 1;\r\n\tdiablo_pause_game();\r\n\tEXPECT_EQ(PauseMode, 0);\r\n}\r\n"
  },
  {
    "path": "test/drlg_common_test.cpp",
    "content": "#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include <array>\r\n\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/world_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nnamespace devilution {\r\n\r\nTEST(DrlgTest, RectangleRangeIterator)\r\n{\r\n\tconstexpr WorldTileRectangle topLeftArea { { 1, 1 }, 1 };\r\n\tconstexpr WorldTileRectangle bottomRightArea { { 3, 3 }, 1 };\r\n\t// Dungeon generation depends on the iteration order remaining unchanged to ensure we generate the same layout as vanilla Diablo/Hellfire\r\n\tstd::array<std::array<int, 5>, 5> region {};\r\n\r\n\tint counter = 0;\r\n\t// Iterate over a 9 tile area in the top left of the region.\r\n\tfor (const WorldTilePosition position : PointsInRectangle(topLeftArea)) {\r\n\t\tregion[position.x][position.y] = ++counter;\r\n\t}\r\n\r\n\tEXPECT_EQ(counter, 9) << \"Iterating over a 9 tile range should return exactly 9 points\";\r\n\tEXPECT_EQ(region[2][2], 9) << \"Iterating over a 9 tile range should return exactly 9 points\";\r\n\r\n\tEXPECT_EQ(region[0][0], 1) << \"Default order should be row-major (where x defines the column, y defines the row)\";\r\n\tEXPECT_EQ(region[1][0], 2) << \"Default order should be row-major (where x defines the column, y defines the row)\";\r\n\tEXPECT_EQ(region[2][0], 3) << \"Default order should be row-major (where x defines the column, y defines the row)\";\r\n\tEXPECT_EQ(region[0][2], 7) << \"Default order should be row-major (where x defines the column, y defines the row)\";\r\n\r\n\tEXPECT_EQ(region[0][3], 0) << \"Iterator should not return out of bounds points\";\r\n\tEXPECT_EQ(region[3][0], 0) << \"Iterator should not return out of bounds points\";\r\n\r\n\tregion = {};\r\n\tcounter = 0;\r\n\r\n\tconst auto rowMajorRange = PointsInRectangle(bottomRightArea);\r\n\tstd::for_each(rowMajorRange.rbegin(), rowMajorRange.rend(), [&region, &counter](Point position) { region[position.x][position.y] = ++counter; });\r\n\tEXPECT_EQ(region[4][4], 1) << \"Reverse iterators are required\";\r\n\tEXPECT_EQ(region[2][4], 3) << \"Reverse iterators are required\";\r\n\tEXPECT_EQ(region[4][2], 7) << \"Reverse iterators are required\";\r\n\tEXPECT_EQ(region[2][2], 9) << \"Reverse iterators are required\";\r\n\r\n\tregion = {};\r\n\tcounter = 0;\r\n\r\n\tfor (const WorldTilePosition position : PointsInRectangleColMajor(topLeftArea)) {\r\n\t\tregion[position.x][position.y] = ++counter;\r\n\t}\r\n\r\n\tEXPECT_EQ(counter, 9) << \"Iterating over a 9 tile range should return exactly 9 points\";\r\n\tEXPECT_EQ(region[2][2], 9) << \"Iterating over a 9 tile range should return exactly 9 points\";\r\n\r\n\tEXPECT_EQ(region[0][0], 1) << \"col-major iterator must use col-major order (where x defines the column, y defines the row)\";\r\n\tEXPECT_EQ(region[0][1], 2) << \"col-major iterator must use col-major order (where x defines the column, y defines the row)\";\r\n\tEXPECT_EQ(region[0][2], 3) << \"col-major iterator must use col-major order (where x defines the column, y defines the row)\";\r\n\tEXPECT_EQ(region[2][0], 7) << \"col-major iterator must use col-major order (where x defines the column, y defines the row)\";\r\n\r\n\tEXPECT_EQ(region[0][3], 0) << \"Iterator should not return out of bounds points\";\r\n\tEXPECT_EQ(region[3][0], 0) << \"Iterator should not return out of bounds points\";\r\n\r\n\tregion = {};\r\n\tcounter = 0;\r\n\r\n\tconst auto colMajorRange = PointsInRectangleColMajor(bottomRightArea);\r\n\tstd::for_each(colMajorRange.rbegin(), colMajorRange.rend(), [&region, &counter](Point position) { region[position.x][position.y] = ++counter; });\r\n\tEXPECT_EQ(region[4][4], 1) << \"Reverse iterators are required\";\r\n\tEXPECT_EQ(region[4][2], 3) << \"Reverse iterators are required\";\r\n\tEXPECT_EQ(region[2][4], 7) << \"Reverse iterators are required\";\r\n\tEXPECT_EQ(region[2][2], 9) << \"Reverse iterators are required\";\r\n}\r\n\r\nTEST(DrlgTest, ThemeRoomSize)\r\n{\r\n\tmemset(dungeon, 0, sizeof(dungeon));\r\n\r\n\tEXPECT_EQ(GetSizeForThemeRoom(), WorldTileSize(8, 8)) << \"All floor theme area should be 8x8\";\r\n\r\n\tdungeon[9][9] = 1;\r\n\tEXPECT_EQ(GetSizeForThemeRoom(), WorldTileSize(7, 7)) << \"Corners shrink the chosen dimensions\";\r\n\tdungeon[9][5] = 1;\r\n\tEXPECT_EQ(GetSizeForThemeRoom(), WorldTileSize(7, 3)) << \"Minimum dimensions are determined by corners outside the min area\";\r\n\tdungeon[9][4] = 1;\r\n\tEXPECT_EQ(GetSizeForThemeRoom(), WorldTileSize(7, 8)) << \"Walls below the min size let larger opposing dimensions get picked\";\r\n\tdungeon[9][5] = 0;\r\n\tdungeon[9][4] = 0;\r\n\tdungeon[9][9] = 0;\r\n\r\n\t// Time for some unusual cases\r\n\tdungeon[7][2] = 1;\r\n\tdungeon[5][9] = 1;\r\n\tEXPECT_EQ(GetSizeForThemeRoom(), WorldTileSize(5, 7)) << \"Search space terminates at width 8 due to the wall being in the first three rows\";\r\n\r\n\tdungeon[6][4] = 1;\r\n\tEXPECT_EQ(GetSizeForThemeRoom(), WorldTileSize(4, 7)) << \"Smallest width now defined by row 5, height still extends due to minSize\";\r\n\tdungeon[6][4] = 0;\r\n\r\n\tdungeon[5][9] = 0;\r\n\tdungeon[7][2] = 0;\r\n\r\n\tdungeon[7][0] = 1;\r\n\tdungeon[6][6] = 1;\r\n\tdungeon[8][5] = 1;\r\n\tEXPECT_EQ(GetSizeForThemeRoom(), WorldTileSize(4, 4)) << \"Search is terminated by the 0 width row 7, inset corner gives a larger height than otherwise expected\";\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/drlg_l1_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"drlg_test.hpp\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_diablo_1_2588)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/1-2588.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(1, 2588, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(77, 46));\r\n\tTestCreateDungeon(1, 2588, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(49, 49));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_diablo_1_743271966)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/1-743271966.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(1, 743271966, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(51, 82));\r\n\tTestCreateDungeon(1, 743271966, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(81, 47));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_diablo_2_1383137027)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/2-1383137027.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_PWATER]._qactive = QUEST_INIT;\r\n\tQuests[Q_BUTCHER]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(2, 1383137027, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(57, 74));\r\n\tTestCreateDungeon(2, 1383137027, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(57, 79));\r\n\tTestCreateDungeon(2, 1383137027, ENTRY_RTNLVL);\r\n\tEXPECT_EQ(ViewPosition, Point(49, 88));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_diablo_3_844660068)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/3-844660068.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(3, 844660068, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(67, 52));\r\n\tTestCreateDungeon(3, 844660068, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(85, 45));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_diablo_4_609325643)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/4-609325643.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_LTBANNER]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(4, 609325643, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(85, 78));\r\n\tTestCreateDungeon(4, 609325643, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(55, 47));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_diablo_4_902156014)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/4-902156014.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_LTBANNER]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(4, 902156014, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(75, 56));\r\n\tTestCreateDungeon(4, 902156014, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(51, 59));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_1_401921334)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/1-401921334.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\r\n\tTestCreateDungeon(1, 401921334, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(79, 80));\r\n\tTestCreateDungeon(1, 401921334, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(49, 63));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_1_536340718)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/1-536340718.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\r\n\tTestCreateDungeon(1, 536340718, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(55, 72));\r\n\tTestCreateDungeon(1, 536340718, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(49, 63));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_2_128964898)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/2-128964898.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\tQuests[Q_PWATER]._qactive = QUEST_NOTAVAIL;\r\n\tQuests[Q_BUTCHER]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(2, 128964898, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(55, 68));\r\n\tTestCreateDungeon(2, 128964898, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(49, 63));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_2_1180526547)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/2-1180526547.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\tQuests[Q_PWATER]._qactive = QUEST_NOTAVAIL;\r\n\tQuests[Q_BUTCHER]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(2, 1180526547, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(83, 68));\r\n\tTestCreateDungeon(2, 1180526547, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(81, 45));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_3_1369955278)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/3-1369955278.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\tQuests[Q_SKELKING]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(3, 1369955278, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(63, 86));\r\n\tTestCreateDungeon(3, 1369955278, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(75, 69));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_3_1799396623)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/3-1799396623.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\tQuests[Q_SKELKING]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(3, 1799396623, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(59, 68));\r\n\tTestCreateDungeon(3, 1799396623, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(47, 55));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_3_1512491184)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/3-1512491184.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\tQuests[Q_SKELKING]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(3, 1512491184, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(47, 72));\r\n\tTestCreateDungeon(3, 1512491184, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(79, 45));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_4_1190318991)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/4-1190318991.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\tQuests[Q_LTBANNER]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(4, 1190318991, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(67, 80));\r\n\tTestCreateDungeon(4, 1190318991, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(77, 45));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_hellfire_4_1924296259)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/4-1924296259.dun\");\r\n\r\n\tTestInitGame(true, false);\r\n\tQuests[Q_LTBANNER]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(4, 1924296259, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(83, 54));\r\n\tTestCreateDungeon(4, 1924296259, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(51, 87));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_crypt_1_2122696790)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/21-2122696790.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\r\n\tTestCreateDungeon(21, 2122696790, ENTRY_TWARPDN);\r\n\tEXPECT_EQ(ViewPosition, Point(61, 81));\r\n\tTestCreateDungeon(21, 2122696790, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(53, 67));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_crypt_2_1191662129)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/22-1191662129.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\tQuests[Q_PWATER]._qactive = QUEST_NOTAVAIL;\r\n\tQuests[Q_BUTCHER]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(22, 1191662129, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(71, 47));\r\n\tTestCreateDungeon(22, 1191662129, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(85, 71));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_crypt_3_97055268)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/23-97055268.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\r\n\tTestCreateDungeon(23, 97055268, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(71, 57));\r\n\tTestCreateDungeon(23, 97055268, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(81, 59));\r\n}\r\n\r\nTEST(Drlg_l1, CreateL5Dungeon_crypt_4_1324803725)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/24-1324803725.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\r\n\tTestCreateDungeon(24, 1324803725, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(79, 47));\r\n}\r\n\r\n} // namespace\r\n"
  },
  {
    "path": "test/drlg_l2_test.cpp",
    "content": "#include <fmt/format.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"drlg_test.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_5_1677631846)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/5-1677631846.dun\");\r\n\r\n\tLoadCoreArchives();\r\n\tLoadQuestData();\r\n\r\n\tInitQuests();\r\n\tQuests[Q_BLOOD]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(5, 1677631846, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(27, 28));\r\n\tTestCreateDungeon(5, 1677631846, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(26, 62));\r\n\tTestCreateDungeon(5, 1677631846, ENTRY_TWARPDN);\r\n\tEXPECT_EQ(ViewPosition, Point(33, 56));\r\n}\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_5_68685319)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/5-68685319.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_BLOOD]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(5, 68685319, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(37, 36));\r\n\tTestCreateDungeon(5, 68685319, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(44, 28));\r\n\tTestCreateDungeon(5, 68685319, ENTRY_TWARPDN);\r\n\tEXPECT_EQ(ViewPosition, Point(45, 76));\r\n}\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_6_2034738122)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/6-2034738122.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_SCHAMB]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(6, 2034738122, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(33, 26));\r\n\tTestCreateDungeon(6, 2034738122, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(34, 52));\r\n}\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_6_1824554527)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/6-1824554527.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_SCHAMB]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(6, 1824554527, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(35, 36));\r\n\tTestCreateDungeon(6, 1824554527, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(28, 76));\r\n}\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_6_2033265779)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/6-2033265779.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_SCHAMB]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(6, 2033265779, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(27, 28));\r\n\tTestCreateDungeon(6, 2033265779, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(64, 64));\r\n}\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_7_680552750)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/7-680552750.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_BLIND]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(7, 680552750, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(27, 26));\r\n\tTestCreateDungeon(7, 680552750, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(78, 52));\r\n}\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_7_1607627156)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/7-1607627156.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_BLIND]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(7, 1607627156, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(53, 26));\r\n\tTestCreateDungeon(7, 1607627156, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(50, 88));\r\n}\r\n\r\nTEST(Drlg_l2, CreateL2Dungeon_diablo_8_1999936419)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/8-1999936419.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(8, 1999936419, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(39, 74));\r\n\tTestCreateDungeon(8, 1999936419, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(48, 46));\r\n}\r\n\r\n} // namespace\r\n"
  },
  {
    "path": "test/drlg_l3_test.cpp",
    "content": "#include <fmt/format.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"drlg_test.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_diablo_9_262005438)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/9-262005438.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(9, 262005438, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(41, 73));\r\n\tTestCreateDungeon(9, 262005438, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(73, 59));\r\n\tTestCreateDungeon(9, 262005438, ENTRY_TWARPDN);\r\n\tEXPECT_EQ(ViewPosition, Point(37, 35));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_diablo_10_1630062353)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/10-1630062353.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_ANVIL]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(10, 1630062353, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(55, 37));\r\n\tTestCreateDungeon(10, 1630062353, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(19, 47));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_diablo_10_879635115)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/10-879635115.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_ANVIL]._qlevel = 10;\r\n\tQuests[Q_ANVIL]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(10, 879635115, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(75, 41));\r\n\tTestCreateDungeon(10, 879635115, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(27, 45));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_diablo_11_384626536)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/11-384626536.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(11, 384626536, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(29, 19));\r\n\tTestCreateDungeon(11, 384626536, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(65, 65));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_diablo_12_2104541047)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/12-2104541047.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(12, 2104541047, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(35, 23));\r\n\tTestCreateDungeon(12, 2104541047, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(21, 83));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_hive_1_19770182)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/17-19770182.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\r\n\tTestCreateDungeon(17, 19770182, ENTRY_TWARPDN);\r\n\tEXPECT_EQ(ViewPosition, Point(75, 81));\r\n\tTestCreateDungeon(17, 19770182, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(59, 41));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_hive_2_1522546307)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/18-1522546307.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\r\n\tTestCreateDungeon(18, 1522546307, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(47, 19));\r\n\tTestCreateDungeon(18, 1522546307, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(33, 35));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_hive_3_125121312)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/19-125121312.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\r\n\tTestCreateDungeon(19, 125121312, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(61, 25));\r\n\tTestCreateDungeon(19, 125121312, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(21, 85));\r\n}\r\n\r\nTEST(Drlg_l3, CreateL3Dungeon_hive_4_1511478689)\r\n{\r\n\tLoadExpectedLevelData(\"hellfire/20-1511478689.dun\");\r\n\r\n\tTestInitGame(true, true, true);\r\n\r\n\tTestCreateDungeon(20, 1511478689, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(65, 41));\r\n}\r\n\r\n} // namespace\r\n"
  },
  {
    "path": "test/drlg_l4_test.cpp",
    "content": "#include <fmt/format.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"drlg_test.hpp\"\r\n#include \"levels/gendung.h\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nTEST(Drlg_l4, CreateL4Dungeon_diablo_13_428074402)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/13-428074402.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_WARLORD]._qactive = QUEST_NOTAVAIL;\r\n\r\n\tTestCreateDungeon(13, 428074402, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(26, 64));\r\n\tTestCreateDungeon(13, 428074402, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(49, 77));\r\n\tTestCreateDungeon(13, 428074402, ENTRY_TWARPDN);\r\n\tEXPECT_EQ(ViewPosition, Point(26, 44));\r\n}\r\n\r\nTEST(Drlg_l4, CreateL4Dungeon_diablo_13_594689775)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/13-594689775.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_WARLORD]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(13, 594689775, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(72, 38));\r\n\tTestCreateDungeon(13, 594689775, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(33, 41));\r\n\tTestCreateDungeon(13, 594689775, ENTRY_TWARPDN);\r\n\tEXPECT_EQ(ViewPosition, Point(36, 88));\r\n}\r\n\r\nTEST(Drlg_l4, CreateL4Dungeon_diablo_14_717625719)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/14-717625719.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(14, 717625719, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(90, 64));\r\n\tTestCreateDungeon(14, 717625719, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(51, 29));\r\n}\r\n\r\n// Level which rooms extend to the edge of the quadrant\r\nTEST(Drlg_l4, CreateL4Dungeon_diablo_14_815743776)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/14-815743776.dun\");\r\n\r\n\tTestInitGame();\r\n\r\n\tTestCreateDungeon(14, 815743776, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(66, 60));\r\n\tTestCreateDungeon(14, 815743776, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(27, 75));\r\n}\r\n\r\nTEST(Drlg_l4, CreateL4Dungeon_diablo_15_1583642716)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/15-1583642716.dun\");\r\n\r\n\tTestInitGame();\r\n\tQuests[Q_DIABLO]._qactive = QUEST_INIT;\r\n\r\n\tTestCreateDungeon(15, 1583642716, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(44, 26));\r\n\tTestCreateDungeon(15, 1583642716, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(88, 67));\r\n\r\n\tQuests[Q_BETRAYER]._qactive = QUEST_ACTIVE;\r\n\tTestCreateDungeon(15, 1583642716, ENTRY_MAIN); // Betrayer quest does not change level gen\r\n\tEXPECT_EQ(ViewPosition, Point(44, 26));\r\n\tEXPECT_EQ(Quests[Q_BETRAYER].position, Point(84, 64)) << \"Ensure the portal to lazarus has a spawn position if the player has activated the quest\";\r\n\r\n\tLoadExpectedLevelData(\"diablo/15-1583642716-changed.dun\");\r\n\r\n\tQuests[Q_BETRAYER]._qactive = QUEST_DONE;\r\n\tQuests[Q_DIABLO]._qactive = QUEST_ACTIVE;\r\n\r\n\tTestCreateDungeon(15, 1583642716, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(44, 26));\r\n\tEXPECT_EQ(Quests[Q_BETRAYER].position, Point(84, 64)) << \"Not really required? current bugfix sets this position anyway\";\r\n\tTestCreateDungeon(15, 1583642716, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(88, 67));\r\n\tEXPECT_EQ(Quests[Q_BETRAYER].position, Point(84, 64)) << \"Not really required? current bugfix sets this position anyway\";\r\n}\r\n\r\nTEST(Drlg_l4, CreateL4Dungeon_diablo_15_1256511996)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/15-1256511996.dun\");\r\n\r\n\tTestInitGame(false);\r\n\r\n\tTestCreateDungeon(15, 1256511996, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(80, 70));\r\n\tTestCreateDungeon(15, 1256511996, ENTRY_PREV);\r\n\tEXPECT_EQ(ViewPosition, Point(34, 65));\r\n}\r\n\r\nTEST(Drlg_l4, CreateL4Dungeon_diablo_16_741281013)\r\n{\r\n\tLoadExpectedLevelData(\"diablo/16-741281013.dun\");\r\n\r\n\tTestCreateDungeon(16, 741281013, ENTRY_MAIN);\r\n\tEXPECT_EQ(ViewPosition, Point(58, 42));\r\n}\r\n\r\n} // namespace\r\n"
  },
  {
    "path": "test/drlg_test.hpp",
    "content": "/**\r\n * @file drlg_test.hpp\r\n *\r\n * Helpers for dungeon related tests.\r\n */\r\n#pragma once\r\n\r\n#include <gtest/gtest.h>\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"levels/themes.h\"\r\n#include \"multi.h\"\r\n#include \"player.h\"\r\n#include \"quests.h\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/paths.h\"\r\n\r\nusing namespace devilution;\r\n\r\nint GetTileCount(dungeon_type levelType)\r\n{\r\n\tswitch (levelType) {\r\n\tcase DTYPE_TOWN:\r\n\t\treturn 376;\r\n\tcase DTYPE_CATHEDRAL:\r\n\t\treturn 206;\r\n\tcase DTYPE_CATACOMBS:\r\n\t\treturn 160;\r\n\tcase DTYPE_CAVES:\r\n\t\treturn 206;\r\n\tcase DTYPE_HELL:\r\n\t\treturn 137;\r\n\tcase DTYPE_NEST:\r\n\t\treturn 166;\r\n\tcase DTYPE_CRYPT:\r\n\t\treturn 217;\r\n\tdefault:\r\n\t\tapp_fatal(\"Invalid level type\");\r\n\t}\r\n}\r\n\r\nstd::unique_ptr<uint16_t[]> DunData;\r\n\r\nvoid LoadExpectedLevelData(const char *fixture)\r\n{\r\n\t// Set look up path to the location to load set pieces from later:\r\n\tpaths::SetPrefPath(paths::BasePath() + \"test/fixtures/\");\r\n\tLoadModArchives({});\r\n\tDunData = LoadFileInMem<uint16_t>(fixture);\r\n\tASSERT_NE(DunData, nullptr) << \"Unable to load test fixture \" << fixture;\r\n\tASSERT_EQ(WorldTileSize(DMAXX, DMAXY), GetDunSize(DunData.get()));\r\n}\r\n\r\nvoid TestInitGame(bool fullQuests = true, bool originalCathedral = true, bool hellfire = false)\r\n{\r\n\tPlayers.resize(1);\r\n\tMyPlayer = &Players[0];\r\n\tMyPlayer->pOriginalCathedral = originalCathedral;\r\n\r\n\tsgGameInitInfo.fullQuests = fullQuests ? 1 : 0;\r\n\tgbIsMultiplayer = !fullQuests;\r\n\r\n\tLoadCoreArchives();\r\n\tLoadQuestData();\r\n\r\n\tUnloadModArchives();\r\n\tif (hellfire) {\r\n\t\tLoadModArchives({ { \"Hellfire\" } });\r\n\t} else {\r\n\t\tLoadModArchives({});\r\n\t}\r\n\r\n\tInitQuests();\r\n}\r\n\r\nvoid TestCreateDungeon(int level, uint32_t seed, lvl_entry entry)\r\n{\r\n\tLevelSeeds[level] = std::nullopt;\r\n\tcurrlevel = level;\r\n\tleveltype = GetLevelType(level);\r\n\r\n\tpMegaTiles = std::make_unique<MegaTile[]>(GetTileCount(leveltype));\r\n\r\n\tCreateDungeon(seed, entry);\r\n\tCreateThemeRooms();\r\n\r\n\tconst uint16_t *tileLayer = &DunData[2];\r\n\r\n\tfor (int y = 0; y < DMAXY; y++) {\r\n\t\tfor (int x = 0; x < DMAXX; x++) {\r\n\t\t\tauto tileId = static_cast<uint8_t>(Swap16LE(*tileLayer));\r\n\t\t\ttileLayer++;\r\n\t\t\tASSERT_EQ(dungeon[x][y], tileId) << \"Tiles don't match at \" << x << \"x\" << y;\r\n\t\t}\r\n\t}\r\n\r\n\tconst uint16_t *transparentLayer = &DunData[2 + DMAXX * DMAXY * 13];\r\n\r\n\tfor (int y = 16; y < 16 + DMAXY * 2; y++) {\r\n\t\tfor (int x = 16; x < 16 + DMAXX * 2; x++) {\r\n\t\t\tauto sectorId = static_cast<uint8_t>(Swap16LE(*transparentLayer));\r\n\t\t\ttransparentLayer++;\r\n\t\t\tASSERT_EQ(dTransVal[x][y], sectorId) << \"Room/region indexes don't match at \" << x << \"x\" << y;\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "test/dun_render_benchmark.cpp",
    "content": "#include <array>\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <span>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n#include <benchmark/benchmark.h>\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/clx_sprite.hpp\"\r\n#include \"engine/displacement.hpp\"\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/render/dun_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"lighting.h\"\r\n#include \"options.h\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nSDLSurfaceUniquePtr SdlSurface;\r\nankerl::unordered_dense::map<TileType, std::vector<LevelCelBlock>> Tiles;\r\nstd::unique_ptr<std::byte[]> BmDunCelData;\r\nuint_fast8_t BmMicroTileLen;\r\n\r\nvoid InitOnce()\r\n{\r\n\t[[maybe_unused]] static const bool GlobalInitDone = []() {\r\n\t\tLoadCoreArchives();\r\n\t\tLoadGameArchives();\r\n\t\tif (!HaveMainData()) {\r\n\t\t\tLogError(\"This benchmark needs spawn.mpq or diabdat.mpq\");\r\n\t\t\texit(1);\r\n\t\t}\r\n\r\n\t\tleveltype = DTYPE_CATHEDRAL;\r\n\t\tBmDunCelData = LoadFileInMem(\"levels\\\\l1data\\\\l1.cel\");\r\n\t\tSetDungeonMicros(BmDunCelData, BmMicroTileLen);\r\n\t\tMakeLightTable();\r\n\r\n\t\tSdlSurface = SDLWrap::CreateRGBSurfaceWithFormat(\r\n\t\t    /*flags=*/0, /*width=*/640, /*height=*/480, /*depth=*/8, SDL_PIXELFORMAT_INDEX8);\r\n\t\tif (SdlSurface == nullptr) {\r\n\t\t\tLogError(\"Failed to create SDL Surface: {}\", SDL_GetError());\r\n\t\t\texit(1);\r\n\t\t}\r\n\r\n\t\tfor (size_t i = 0; i < 700; ++i) {\r\n\t\t\tfor (size_t j = 0; j < 10; ++j) {\r\n\t\t\t\tif (const LevelCelBlock levelCelBlock = DPieceMicros[i].mt[j]; levelCelBlock.hasValue()) {\r\n\t\t\t\t\tif ((j == 0 || j == 1) && levelCelBlock.type() == TileType::TransparentSquare) {\r\n\t\t\t\t\t\t// This could actually be re-encoded foliage, which is a triangle followed by TransparentSquare.\r\n\t\t\t\t\t\t// Simply skip it.\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tTiles[levelCelBlock.type()].push_back(levelCelBlock);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tGetOptions().Graphics.perPixelLighting.SetValue(false);\r\n\t\treturn true;\r\n\t}();\r\n}\r\n\r\nvoid RunForTileMaskLight(benchmark::State &state, TileType tileType, MaskType maskType, const uint8_t *lightTable)\r\n{\r\n\tconst Surface out = Surface(SdlSurface.get());\r\n\tstd::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables;\r\n\tconst Lightmap lightmap(/*outBuffer=*/nullptr, /*lightmapBuffer=*/ {}, /*pitch=*/1, lightTables, FullyLitLightTable, FullyDarkLightTable);\r\n\tconst std::span<const LevelCelBlock> tiles = Tiles[tileType];\r\n\tfor (auto _ : state) {\r\n\t\tfor (const LevelCelBlock &levelCelBlock : tiles) {\r\n\t\t\tRenderTile(out, lightmap, Point { 320, 240 }, BmDunCelData.get(), levelCelBlock, maskType, lightTable);\r\n\t\t\tuint8_t color = out[Point { 310, 200 }];\r\n\t\t\tbenchmark::DoNotOptimize(color);\r\n\t\t}\r\n\t}\r\n\tstate.SetItemsProcessed(state.iterations() * tiles.size());\r\n}\r\n\r\nusing GetLightTableFn = const uint8_t *();\r\n\r\nconst uint8_t *FullyLit() { return LightTables[0].data(); }\r\nconst uint8_t *FullyDark() { return LightTables.back().data(); }\r\nconst uint8_t *PartiallyLit() { return LightTables[5].data(); }\r\n\r\ntemplate <TileType TileT, MaskType MaskT, GetLightTableFn GetLightTableFnT>\r\nvoid Render(benchmark::State &state)\r\n{\r\n\tInitOnce();\r\n\tRunForTileMaskLight(state, TileT, MaskT, GetLightTableFnT());\r\n}\r\n\r\n// Define aliases in order to have shorter benchmark names.\r\nconstexpr auto LeftTriangle = TileType::LeftTriangle;\r\nconstexpr auto RightTriangle = TileType::RightTriangle;\r\nconstexpr auto TransparentSquare = TileType::TransparentSquare;\r\nconstexpr auto Square = TileType::Square;\r\nconstexpr auto LeftTrapezoid = TileType::LeftTrapezoid;\r\nconstexpr auto RightTrapezoid = TileType::RightTrapezoid;\r\nconstexpr auto Transparent = MaskType::Transparent;\r\nconstexpr auto Solid = MaskType::Solid;\r\n\r\n#define DEFINE_FOR_TILE_AND_MASK_TYPE(TILE_TYPE, MASK_TYPE)      \\\r\n\tBENCHMARK_TEMPLATE(Render, TILE_TYPE, MASK_TYPE, FullyLit);  \\\r\n\tBENCHMARK_TEMPLATE(Render, TILE_TYPE, MASK_TYPE, FullyDark); \\\r\n\tBENCHMARK_TEMPLATE(Render, TILE_TYPE, MASK_TYPE, PartiallyLit);\r\n\r\n#define DEFINE_FOR_TILE_TYPE(TILE_TYPE)             \\\r\n\tDEFINE_FOR_TILE_AND_MASK_TYPE(TILE_TYPE, Solid) \\\r\n\tDEFINE_FOR_TILE_AND_MASK_TYPE(TILE_TYPE, Transparent)\r\n\r\nDEFINE_FOR_TILE_TYPE(LeftTriangle)\r\nDEFINE_FOR_TILE_TYPE(RightTriangle)\r\nDEFINE_FOR_TILE_TYPE(TransparentSquare)\r\nDEFINE_FOR_TILE_TYPE(Square)\r\nDEFINE_FOR_TILE_TYPE(LeftTrapezoid)\r\nDEFINE_FOR_TILE_TYPE(RightTrapezoid)\r\n\r\nvoid BM_RenderBlackTile(benchmark::State &state)\r\n{\r\n\tInitOnce();\r\n\tconst Surface out = Surface(SdlSurface.get());\r\n\tfor (auto _ : state) {\r\n\t\tworld_draw_black_tile(out, 320, 240);\r\n\t\tuint8_t color = out[Point { 310, 200 }];\r\n\t\tbenchmark::DoNotOptimize(color);\r\n\t}\r\n\tstate.SetItemsProcessed(state.iterations());\r\n}\r\nBENCHMARK(BM_RenderBlackTile);\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/effects_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"effects.h\"\r\n#include \"engine/sound_position.hpp\"\r\n#include \"player.h\"\r\n\r\nusing namespace devilution;\r\n\r\nTEST(Effects, CalculateSoundPosition_center)\r\n{\r\n\tPlayers.resize(1);\r\n\tMyPlayer = &Players[0];\r\n\tMyPlayer->position.tile = { 50, 50 };\r\n\tint plVolume = 0;\r\n\tint plPan = 0;\r\n\tEXPECT_EQ(CalculateSoundPosition({ 50, 50 }, &plVolume, &plPan), true);\r\n\tEXPECT_EQ(plVolume, 0);\r\n\tEXPECT_EQ(plPan, 0);\r\n}\r\n\r\nTEST(Effects, CalculateSoundPosition_near)\r\n{\r\n\tPlayers.resize(1);\r\n\tMyPlayer = &Players[0];\r\n\tMyPlayer->position.tile = { 50, 50 };\r\n\tint plVolume = 0;\r\n\tint plPan = 0;\r\n\tEXPECT_EQ(CalculateSoundPosition({ 55, 50 }, &plVolume, &plPan), true);\r\n\tEXPECT_EQ(plVolume, -320);\r\n\tEXPECT_EQ(plPan, 1280);\r\n}\r\n\r\nTEST(Effects, CalculateSoundPosition_out_of_range)\r\n{\r\n\tPlayers.resize(1);\r\n\tMyPlayer = &Players[0];\r\n\tMyPlayer->position.tile = { 12, 12 };\r\n\tint plVolume = 1234;\r\n\tint plPan = 0;\r\n\tEXPECT_EQ(CalculateSoundPosition({ 112, 112 }, &plVolume, &plPan), false);\r\n\tEXPECT_EQ(plVolume, 1234);\r\n\tEXPECT_EQ(plPan, 0);\r\n}\r\n\r\nTEST(Effects, CalculateSoundPosition_extreme_right)\r\n{\r\n\tPlayers.resize(1);\r\n\tMyPlayer = &Players[0];\r\n\tMyPlayer->position.tile = { 50, 50 };\r\n\tint plVolume = 0;\r\n\tint plPan = 0;\r\n\tEXPECT_EQ(CalculateSoundPosition({ 75, 25 }, &plVolume, &plPan), true);\r\n\tEXPECT_EQ(plVolume, -2176);\r\n\tEXPECT_EQ(plPan, 6400);\r\n}\r\n\r\nTEST(Effects, CalculateSoundPosition_extreme_left)\r\n{\r\n\tPlayers.resize(1);\r\n\tMyPlayer = &Players[0];\r\n\tMyPlayer->position.tile = { 50, 50 };\r\n\tint plVolume = 0;\r\n\tint plPan = 0;\r\n\tEXPECT_EQ(CalculateSoundPosition({ 25, 75 }, &plVolume, &plPan), true);\r\n\tEXPECT_EQ(plVolume, -2176);\r\n\tEXPECT_EQ(plPan, -6400);\r\n}\r\n"
  },
  {
    "path": "test/file_util_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include <cstdio>\r\n\r\n#include \"utils/file_util.h\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nvoid WriteDummyFile(const char *name, std::uintmax_t size)\r\n{\r\n\tstd::printf(\"Writing test file %s\\n\", name);\r\n\tFILE *test_file = std::fopen(name, \"wb\");\r\n\tASSERT_TRUE(test_file != nullptr);\r\n\tconst char c = '\\0';\r\n\tfor (std::uintmax_t i = 0; i < size; ++i) {\r\n\t\tstd::fwrite(&c, sizeof(c), 1, test_file);\r\n\t\tASSERT_EQ(std::ferror(test_file), 0);\r\n\t}\r\n\tstd::fclose(test_file);\r\n}\r\n\r\nstd::string GetTmpPathName(const char *suffix = \".tmp\")\r\n{\r\n\tconst auto *current_test = ::testing::UnitTest::GetInstance()->current_test_info();\r\n\tstd::string result = \"Test_\";\r\n\tresult.append(current_test->test_case_name());\r\n\tresult += '_';\r\n\tresult.append(current_test->name());\r\n\tresult.append(suffix);\r\n\treturn result;\r\n}\r\n\r\nTEST(FileUtil, GetFileSize)\r\n{\r\n\tconst std::string path = GetTmpPathName();\r\n\tWriteDummyFile(path.c_str(), 42);\r\n\tstd::uintmax_t result;\r\n\tASSERT_TRUE(GetFileSize(path.c_str(), &result));\r\n\tEXPECT_EQ(result, 42);\r\n}\r\n\r\nTEST(FileUtil, FileExists)\r\n{\r\n\tEXPECT_FALSE(FileExists(\"this-file-should-not-exist\"));\r\n\tconst std::string path = GetTmpPathName();\r\n\tWriteDummyFile(path.c_str(), 42);\r\n\tEXPECT_TRUE(FileExists(path.c_str()));\r\n}\r\n\r\nTEST(FileUtil, ResizeFile)\r\n{\r\n\tconst std::string path = GetTmpPathName();\r\n\tWriteDummyFile(path.c_str(), 42);\r\n\tstd::uintmax_t size;\r\n\tASSERT_TRUE(GetFileSize(path.c_str(), &size));\r\n\tEXPECT_EQ(size, 42);\r\n\tASSERT_TRUE(ResizeFile(path.c_str(), 30));\r\n\tASSERT_TRUE(GetFileSize(path.c_str(), &size));\r\n\tEXPECT_EQ(size, 30);\r\n}\r\n\r\nTEST(FileUtil, Dirname)\r\n{\r\n\tEXPECT_EQ(Dirname(\"\"), \".\");\r\n\tEXPECT_EQ(Dirname(\"abc\"), \".\");\r\n\tEXPECT_EQ(Dirname(DIRECTORY_SEPARATOR_STR), DIRECTORY_SEPARATOR_STR);\r\n\tEXPECT_EQ(Dirname(DIRECTORY_SEPARATOR_STR DIRECTORY_SEPARATOR_STR), DIRECTORY_SEPARATOR_STR);\r\n\tEXPECT_EQ(Dirname(\"a\" DIRECTORY_SEPARATOR_STR \"b\"), \"a\");\r\n\tEXPECT_EQ(Dirname(\"a\" DIRECTORY_SEPARATOR_STR \"b\" DIRECTORY_SEPARATOR_STR \"c\"),\r\n\t    \"a\" DIRECTORY_SEPARATOR_STR \"b\");\r\n\tEXPECT_EQ(Dirname(\"a\" DIRECTORY_SEPARATOR_STR \"b\" DIRECTORY_SEPARATOR_STR \"c\"),\r\n\t    \"a\" DIRECTORY_SEPARATOR_STR \"b\");\r\n}\r\n\r\nTEST(FileUtil, RecursivelyCreateDir)\r\n{\r\n\tconst std::string path = GetTmpPathName(/*suffix=*/\"\") + DIRECTORY_SEPARATOR_STR\r\n\t    + \"a\" + DIRECTORY_SEPARATOR_STR + \"b\" + DIRECTORY_SEPARATOR_STR + \"c\";\r\n\tRecursivelyCreateDir(path.c_str());\r\n\tEXPECT_TRUE(DirectoryExists(path.c_str()));\r\n}\r\n\r\n} // namespace\r\n"
  },
  {
    "path": "test/fixtures/memory_map/additionalMissiles.txt",
    "content": "R 32 Version\r\nLC_LE 32 MissileCounter\r\nC MissileCounter missile missiles\r\n"
  },
  {
    "path": "test/fixtures/memory_map/game.txt",
    "content": "R 32 header\r\nR 8 setlevel\r\nR 32 setlvlnum\r\nR 32 currlevel\r\nLT 32 leveltype\r\nR 32 viewX\r\nR 32 viewY\r\nR 8 invflag\r\nR 8 CharFlag\r\nLC 32 NumMonsters\r\nLC 32 ItemCount\r\nLC 32 NumMissiles\r\nLC 32 NumObjects\r\nC_DA 17 levelSeed levelSeeds\r\nC_HF 25 levelSeed levelSeeds\r\nC 1 player player\r\nC_DA 16 quest quests\r\nC_HF 24 quest quests\r\nC 4 portal portals\r\nM 200 32 MonsterKillCounts\r\nM_DL 200 32 ActiveMonsters\r\nC_DL NumMonsters monster monsters\r\nM_DL 125 8 ActiveMissiles\r\nM_DL 125 8 AvailableMissiles\r\nC_DL NumMissiles missile missiles\r\nM_DL 127 8 ActiveObjects\r\nM_DL 127 8 AvailableObjects\r\nC_DL NumObjects object objects\r\nLC_DL 32 ActiveLightCount\r\nM_DL 32 8 ActiveLights\r\nC_DL ActiveLightCount lightning lightning\r\nR_DL 32 VisionId\r\nLC_DL 32 VisionCount\r\nC_DL VisionCount lightning vision\r\nM 127 8 ActiveItems\r\nM 127 8 AvailableItems\r\nC ItemCount item items\r\nM 128 8 UniqueItemFlags\r\nM 12544 8 dLight\r\nM 12544 8 dFlags\r\nM 12544 8 dPlayer\r\nM 12544 8 dItem\r\nM_DL 12544 32 dMonster\r\nM_DL 12544 8 dCorpse\r\nM_DL 12544 8 dObject\r\nM_DL 12544 8 dLight\r\nM_DL 12544 8 dPreLight\r\nM_DL 1600 8 AutomapView\r\nM_DL 12544 8 dMissile\r\nR 32 PremiumItemCount\r\nR 32 PremiumItemLevel\r\nC_DA 6 item PremiumItems\r\nC_HF 15 item PremiumItems\r\nR 8 AutomapActive\r\nR 32 AutoMapScale\r\n"
  },
  {
    "path": "test/fixtures/memory_map/hero.txt",
    "content": "R 32 dwLowDateTime\r\nR 32 dwHighDateTime\r\nR 8 destAction\r\nR 8 destParam1\r\nR 8 destParam2\r\nR 8 plrlevel\r\nR 8 px\r\nR 8 py\r\nR 8 targx\r\nR 8 targy\r\nR 256 _pName\r\nR 8 pClass\r\nR 8 pBaseStr\r\nR 8 pBaseMag\r\nR 8 pBaseDex\r\nR 8 pBaseVit\r\nR 8 pLevel\r\nR 8 pStatPts\r\nR 32 pExperience\r\nR 32 pGold\r\nR 32 pHPBase\r\nR 32 pMaxHPBase\r\nR 32 pManaBase\r\nR 32 pMaxManaBase\r\nM 37 8 pSplLvl\r\nR 64 pMemSpells\r\nC 7 itemPack InvBody\r\nC 40 itemPack InvList\r\nM 40 8 InvGrid\r\nR 8 _pNumInv\r\nC 8 itemPack SpdList\r\nR 8 pTownWarps\r\nR 8 pDungMsgs\r\nR 8 pLvlLoad\r\nR 8 pBattleNet\r\nR 8 pManaShield\r\nR 8 pDungMsgs2\r\nR 8 bIsHellfire\r\nR 8 reserved\r\nR 16 wReflections\r\nR 16 reserved\r\nM 10 8 pSplLvl2\r\nR 16 reserved\r\nR 32 pDiabloKillLevel\r\nR 32 pDifficulty\r\nR 32 pDamAcFlags\r\nR 8 friendlyMode\r\nR 8 isOnSetLevel\r\nM 18 8 reserved\r\n"
  },
  {
    "path": "test/fixtures/memory_map/item.txt",
    "content": "R 32 _iSeed\r\nR 16 _iCreateInfo\r\nR 16 alignment\r\nR 32 _itype\r\nR 32 positionX\r\nR 32 positionY\r\nR 32 _iAnimFlag\r\nR 32 _iAnimData\r\nR 32 numberOfFrames\r\nR 32 currentFrame\r\nR 32 _iAnimWidth\r\nR 32 _iAnimWidth2\r\nR 32 unused\r\nR 8 _iSelFlag\r\nR 24 alignment\r\nR 32 _iPostDraw\r\nR 32 _iIdentified\r\nR 8 _iMagical\r\nR 512 _iName\r\nR 512 _iIName\r\nR 8 _iLoc\r\nR 8 _iClass\r\nR 8 alignment\r\nR 32 _iCurs\r\nR 32 _ivalue\r\nR 32 _iIvalue\r\nR 32 _iMinDam\r\nR 32 _iMaxDam\r\nR 32 _iAC\r\nR 32 _iFlags\r\nR 32 _iMiscId\r\nR 32 _iSpell\r\nR 32 _iCharges\r\nR 32 _iMaxCharges\r\nR 32 _iDurability\r\nR 32 _iMaxDur\r\nR 32 _iPLDam\r\nR 32 _iPLToHit\r\nR 32 _iPLAC\r\nR 32 _iPLStr\r\nR 32 _iPLMag\r\nR 32 _iPLDex\r\nR 32 _iPLVit\r\nR 32 _iPLFR\r\nR 32 _iPLLR\r\nR 32 _iPLMR\r\nR 32 _iPLMana\r\nR 32 _iPLHP\r\nR 32 _iPLDamMod\r\nR 32 _iPLGetHit\r\nR 32 _iPLLight\r\nR 8 _iSplLvlAdd\r\nR 8 _iRequest\r\nR 16 alignment\r\nR 32 _iUid\r\nR 32 _iFMinDam\r\nR 32 _iFMaxDam\r\nR 32 _iLMinDam\r\nR 32 _iLMaxDam\r\nR 32 _iPLEnAc\r\nR 8 _iPrePower\r\nR 8 _iSufPower\r\nR 16 alignment\r\nR 32 _iVAdd1\r\nR 32 _iVMult1\r\nR 32 _iVAdd2\r\nR 32 _iVMult2\r\nR 8 _iMinStr\r\nR 8 _iMinMag\r\nR 8 _iMinDex\r\nR 8 alignment\r\nR 32 _iStatFlag\r\nR 32 IDidx\r\nR 32 dwBuff\r\nR_HF 32 _iDamAcFlags\r\n"
  },
  {
    "path": "test/fixtures/memory_map/itemPack.txt",
    "content": "R 32 iSeed\r\nR 16 iCreateInfo\r\nR 16 idx\r\nR 8 bId\r\nR 8 bDur\r\nR 8 bMDur\r\nR 8 bCh\r\nR 8 bMCh\r\nR 16 wValue\r\nR 32 dwBuff\r\n"
  },
  {
    "path": "test/fixtures/memory_map/level.txt",
    "content": "M_DL 12544 8 dCorpse\r\nLC 32 NumMonsters\r\nLC 32 ItemCount\r\nLC 32 NumObjects\r\nM_DL 200 32 ActiveMonsters\r\nC_DL NumMonsters monster monsters\r\nM_DL 127 8 ActiveObjects\r\nM_DL 127 8 AvailableObjects\r\nC_DL NumObjects object objects\r\nM 127 8 ActiveItems\r\nM 127 8 AvailableItems\r\nC ItemCount item items\r\nM 12544 8 dFlags\r\nM 12544 8 dItem\r\nM_DL 12544 32 dMonster\r\nM_DL 12544 8 dObject\r\nM_DL 12544 8 dLight\r\nM_DL 12544 8 dPreLight\r\nM_DL 1600 8 AutomapView\r\n"
  },
  {
    "path": "test/fixtures/memory_map/levelSeed.txt",
    "content": "R 32 DungeonSeeds\r\nR 32 gnLevelTypeTbl\r\n"
  },
  {
    "path": "test/fixtures/memory_map/lightning.txt",
    "content": "R 32 positionX\r\nR 32 positionY\r\nR 32 radius\r\nR 32 _lid\r\nR 32 isInvalid\r\nR 32 hasChanged\r\nR 32 unused\r\nR 32 oldX\r\nR 32 oldY\r\nR 32 oldRadius\r\nR 32 offsetX\r\nR 32 offsetY\r\nR 32 _lflags\r\n"
  },
  {
    "path": "test/fixtures/memory_map/missile.txt",
    "content": "R 32 _mitype\r\nR 32 tileX\r\nR 32 tileY\r\nR 32 offsetX\r\nR 32 offsetY\r\nR 32 velocityX\r\nR 32 velocityY\r\nR 32 startX\r\nR 32 startY\r\nR 32 traveledX\r\nR 32 traveledY\r\nR 32 _mimfnum\r\nR 32 _mispllvl\r\nR 32 _miDelFlag\r\nR 8 _miAnimType\r\nR 24 alignment\r\nR 32 _miAnimFlags\r\nR 32 _miAnimData\r\nR 32 _miAnimDelay\r\nR 32 _miAnimLen\r\nR 32 _miAnimWidth\r\nR 32 _miAnimWidth2\r\nR 32 _miAnimCnt\r\nR 32 _miAnimAdd\r\nR 32 _miAnimFrame\r\nR 32 _miDrawFlag\r\nR 32 _miLightFlag\r\nR 32 _miPreFlag\r\nR 32 _miUniqTrans\r\nR 32 duration\r\nR 32 _misource\r\nR 32 _micaster\r\nR 32 _midam\r\nR 32 _miHitFlag\r\nR 32 _midist\r\nR 32 _mlid\r\nR 32 _mirnd\r\nR 32 var1\r\nR 32 var2\r\nR 32 var3\r\nR 32 var4\r\nR 32 var5\r\nR 32 var6\r\nR 32 var7\r\nR 32 limitReached\r\n"
  },
  {
    "path": "test/fixtures/memory_map/monster.txt",
    "content": "R 32 levelType\r\nR 32 mode\r\nR 8 goal\r\nR 24 alignment\r\nR 32 goalVar1\r\nR 32 goalVar2\r\nR 32 goalVar3\r\nR 32 unused\r\nR 8 pathcount\r\nR 24 alignment\r\nR 32 tileX\r\nR 32 tileY\r\nR 32 futureX\r\nR 32 futureY\r\nR 32 oldX\r\nR 32 oldY\r\nR 32 offsetX\r\nR 32 offsetY\r\nR 32 velocityX\r\nR 32 velocityY\r\nR 32 direction\r\nR 32 enemy\r\nR 8 enemyPositionX\r\nR 8 enemyPositionY\r\nR 16 unused\r\nR 32 _mAnimData\r\nR 32 ticksPerFrame\r\nR 32 tickCounterOfCurrentFrame\r\nR 32 numberOfFrames\r\nR 32 currentFrame\r\nR 32 _meflag\r\nR 32 isInvalid\r\nR 32 var1\r\nR 32 var2\r\nR 32 var3\r\nR 32 tempPositionX\r\nR 32 tempPositionY\r\nR 32 offset2X\r\nR 32 offset2Y\r\nR 32 actionFrame\r\nR 32 maxHitPoints\r\nR 32 hitPoints\r\nR 8 ai\r\nR 8 intelligence\r\nR 16 alignment\r\nR 32 flags\r\nR 8 activeForTicks\r\nR 24 alignment\r\nR 32 unused\r\nR 32 lastX\r\nR 32 lastY\r\nR 32 rndItemSeed\r\nR 32 aiSeed\r\nR 32 unused\r\nR 8 uniqueType\r\nR 8 uniqTrans\r\nR 8 corpseId\r\nR 8 whoHit\r\nR 8 level\r\nR 8 alignment\r\nR 16 exp\r\nR 8 toHit\r\nR 8 minDamage\r\nR 8 maxDamage\r\nR 8 toHitSpecial\r\nR 8 minDamageSpecial\r\nR 8 maxDamageSpecial\r\nR 8 armorClass\r\nR 8 alignment\r\nR 16 resistance\r\nR 16 alignment\r\nR 32 talkMsg\r\nR 8 leader\r\nR 8 leaderRelation\r\nR 8 packSize\r\nR 8 lightId\r\n"
  },
  {
    "path": "test/fixtures/memory_map/object.txt",
    "content": "R 32 _otype\r\nR 32 positionX\r\nR 32 positionY\r\nR 32 applyLighting\r\nR 32 _oAnimFlag\r\nR 32 _oAnimData\r\nR 32 _oAnimDelay\r\nR 32 _oAnimCnt\r\nR 32 _oAnimLen\r\nR 32 _oAnimFrame\r\nR 32 _oAnimWidth\r\nR 32 _oAnimWidth2\r\nR 32 _oDelFlag\r\nR 8 _oBreak\r\nR 24 alignment\r\nR 32 _oSolidFlag\r\nR 32 _oMissFlag\r\nR 8 _oSelFlag\r\nR 24 alignment\r\nR 32 _oPreFlag\r\nR 32 _oTrapFlag\r\nR 32 _oDoorFlag\r\nR 32 _olid\r\nR 32 _oRndSeed\r\nR 32 _oVar1\r\nR 32 _oVar2\r\nR 32 _oVar3\r\nR 32 _oVar4\r\nR 32 _oVar5\r\nR 32 _oVar6\r\nR 32 bookMessage\r\nR 32 _oVar8\r\n"
  },
  {
    "path": "test/fixtures/memory_map/player.txt",
    "content": "R 32 _pmode\r\nM 25 8 walkpath\r\nR 8 plractive\r\nR 16 alignment\r\nR 32 destAction\r\nR 32 destParam1\r\nR 32 destParam2\r\nR 32 destParam3\r\nR 32 destParam4\r\nR 32 level\r\nR 32 tileX\r\nR 32 tileY\r\nR 32 futureX\r\nR 32 futureY\r\nR 32 _ptargx\r\nR 32 _ptargy\r\nR 32 lastX\r\nR 32 lastY\r\nR 32 oldX\r\nR 32 oldY\r\nR 32 offsetX\r\nR 32 offsetY\r\nR 32 velocityX\r\nR 32 velocityY\r\nR 32 pdir\r\nR 32 unused\r\nR 32 pfxnum\r\nR 32 pData\r\nR 32 ticksPerFrame\r\nR 32 tickCounterOfCurrentFrame\r\nR 32 numberOfFrames\r\nR 32 currentFrame\r\nR 32 _pAnimWidth\r\nR 32 _pAnimWidth2\r\nR 32 _peflag\r\nR 32 lightId\r\nR 32 _pvid\r\nR 32 _pSpell\r\nR 8 _pSplType\r\nR 8 _pSplFrom\r\nR 16 alignment\r\nR 32 _pTSpell\r\nR 8 _pTSplType\r\nR 24 alignment\r\nR 32 _pRSpell\r\nR 8 _pRSplType\r\nR 24 alignment\r\nR 32 _pSBkSpell\r\nR 8 _pSBkSplType\r\nM 64 8 spellLevel\r\nR 56 alignment\r\nR 64 _pMemSpells\r\nR 64 _pAblSpells\r\nR 64 _pScrlSpells\r\nR 8 _pSpellFlags\r\nR 24 alignment\r\nM 4 32 _pSplHotKey\r\nM 4 8 _pSplTHotKey\r\nR 32 _pwtype\r\nR 8 _pBlockFlag\r\nR 8 _pInvincible\r\nR 8 _pLightRad\r\nR 8 _pLvlChanging\r\nR 256 _pName\r\nR 8 _pClass\r\nR 24 alignment\r\nR 32 _pStrength\r\nR 32 _pBaseStr\r\nR 32 _pMagic\r\nR 32 _pBaseMag\r\nR 32 _pDexterity\r\nR 32 _pBaseDex\r\nR 32 _pVitality\r\nR 32 _pBaseVit\r\nR 32 _pStatPts\r\nR 32 _pDamageMod\r\nR 32 _pBaseToBlk\r\nR 32 _pHPBase\r\nR 32 _pMaxHPBase\r\nR 32 _pHitPoints\r\nR 32 _pMaxHP\r\nR 32 _pHPPer\r\nR 32 _pManaBase\r\nR 32 _pMaxManaBase\r\nR 32 _pMana\r\nR 32 _pMaxMana\r\nR 32 _pManaPer\r\nR 8 _pLevel\r\nR 8 _pMaxLvl\r\nR 16 alignment\r\nR 32 _pExperience\r\nR 32 _pMaxExp\r\nR 32 _pNextExper\r\nR 8 _pArmorClass\r\nR 8 _pMagResist\r\nR 8 _pFireResist\r\nR 8 _pLghtResist\r\nR 32 _pGold\r\nR 32 _pInfraFlag\r\nR 32 tempPositionX\r\nR 32 tempPositionY\r\nR 32 tempDirection\r\nR 32 spellLevel\r\nR 32 _pVar5\r\nR 32 offset2.x\r\nR 32 offset2.y\r\nR 32 actionFrame\r\nM_DA 17 8 _pLvlVisited\r\nM_HF 25 8 _pLvlVisited\r\nM_DA 17 8 _pSLvlVisited\r\nM_HF 25 8 _pSLvlVisited\r\nR 16 alignment\r\nR 32 _pGFXLoad\r\nM 8 32 _pNAnim\r\nR 32 _pNFrames\r\nR 32 _pNWidth\r\nM 8 32 _pWAnim\r\nR 32 _pWWidth\r\nM 8 32 _pAAnim\r\nR 32 _pAFrames\r\nR 32 _pAWidth\r\nR 32 _pAFNum\r\nM 8 32 _pLAnim\r\nM 8 32 _pFAnim\r\nM 8 32 _pTAnim\r\nR 32 _pSFrames\r\nR 32 _pSWidth\r\nR 32 _pSFNum\r\nR 32 _pHFrames\r\nM 8 32 _pHAnim\r\nR 32 _pHFrames\r\nR 32 _pHWidth\r\nM 8 32 _pDAnim\r\nR 32 _pDFrames\r\nR 32 _pDWidth\r\nM 8 32 _pBAnim\r\nR 32 _pBFrames\r\nR 32 _pBWidth\r\nC 7 item\r\nC 40 item\r\nR 32 _pNumInv\r\nM 40 8 InvGrid\r\nC 8 item\r\nC 1 item\r\nR 32 _pIMinDam\r\nR 32 _pIMaxDam\r\nR 32 _pIAC\r\nR 32 _pIBonusDam\r\nR 32 _pIBonusToHit\r\nR 32 _pIBonusAC\r\nR 32 _pIBonusDamMod\r\nR 32 alignment\r\nR 64 _pISpells\r\nR 32 _pIFlags\r\nR 32 _pIGetHit\r\nR 8 _pISplLvlAdd\r\nR 8 unused\r\nR 16 alignment\r\nR 32 _pISplDur\r\nR 32 _pIEnAc\r\nR 32 _pIFMinDam\r\nR 32 _pIFMaxDam\r\nR 32 _pILMinDam\r\nR 32 _pILMaxDam\r\nR 32 _pOilType\r\nR 8 pTownWarps\r\nR 8 pDungMsgs\r\nR 8 pLvlLoad\r\nR 8 pDungMsgs2\r\nR 8 pManaShield\r\nR 8 pOriginalCathedral\r\nR 16 unused\r\nR 16 wReflections\r\nR 112 unused\r\nR 32 pDiabloKillLevel\r\nR 32 pDifficulty\r\nR 32 pDamAcFlags\r\nR 160 unused\r\n"
  },
  {
    "path": "test/fixtures/memory_map/portal.txt",
    "content": "R 32 open\r\nR 32 positionX\r\nR 32 positionY\r\nR 32 level\r\nR 32 ltype\r\nR 32 setlvl\r\n"
  },
  {
    "path": "test/fixtures/memory_map/quest.txt",
    "content": "R 8 _qlevel\r\nR 8 _qtype\r\nR 8 _qactive\r\nR 8 _qlvltype\r\nR 32 positionX\r\nR 32 positionY\r\nR 8 _qslvl\r\nR 8 _qidx\r\nR_DA 8 _qmsg\r\nR_HF 16 alignment\r\nR_HF 32 _qmsg\r\nR 8 _qvar1\r\nR 8 _qvar2\r\nR 16 alignment\r\nR_DA 8 alignment\r\nR 32 _qlog\r\nR 32 ReturnLvlPositionX\r\nR 32 ReturnLvlPositionY\r\nR 32 ReturnLevel\r\nR 32 ReturnLevelType\r\nR 32 DoomQuestState\r\n"
  },
  {
    "path": "test/fixtures/txtdata/cr.tsv",
    "content": "Test\tEmpty\tValues\r\t2\t3\r1\t2\t\r1\t\t3\r"
  },
  {
    "path": "test/fixtures/txtdata/crlf.tsv",
    "content": "Test\tEmpty\tValues\r\n\t2\t3\r\n1\t2\t\r\n1\t\t3\r\n"
  },
  {
    "path": "test/fixtures/txtdata/empty.tsv",
    "content": ""
  },
  {
    "path": "test/fixtures/txtdata/empty_with_utf8_bom.tsv",
    "content": "﻿"
  },
  {
    "path": "test/fixtures/txtdata/lf.tsv",
    "content": "Test\tEmpty\tValues\n\t2\t3\n1\t2\t\n1\t\t3\n"
  },
  {
    "path": "test/fixtures/txtdata/lf_no_trail.tsv",
    "content": "Test\tEmpty\tValues\n\t2\t3\n1\t2\t\n1\t\t3"
  },
  {
    "path": "test/fixtures/txtdata/sample.tsv",
    "content": "String\tByte\tInt\tFloat\tFloatOverflow\nSample\t145\t70322\t6.34\t3.999\n"
  },
  {
    "path": "test/fixtures/txtdata/utf8_bom.tsv",
    "content": "﻿Test\tEmpty\tValues\n\t2\t3\n1\t2\t\n1\t\t3\n"
  },
  {
    "path": "test/format_int_test.cpp",
    "content": "\r\n#include <gtest/gtest.h>\r\n\r\n#include \"utils/format_int.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nTEST(FormatIntegerTest, OneDigit)\r\n{\r\n\tEXPECT_EQ(FormatInteger(1), \"1\");\r\n\tEXPECT_EQ(FormatInteger(-1), \"-1\");\r\n}\r\n\r\nTEST(FormatIntegerTest, TwoDigits)\r\n{\r\n\tEXPECT_EQ(FormatInteger(12), \"12\");\r\n\tEXPECT_EQ(FormatInteger(-12), \"-12\");\r\n}\r\n\r\nTEST(FormatIntegerTest, ThreeDigits)\r\n{\r\n\tEXPECT_EQ(FormatInteger(123), \"123\");\r\n\tEXPECT_EQ(FormatInteger(-123), \"-123\");\r\n}\r\n\r\nTEST(FormatIntegerTest, FourDigits)\r\n{\r\n\tEXPECT_EQ(FormatInteger(1234), \"1,234\");\r\n\tEXPECT_EQ(FormatInteger(-1234), \"-1,234\");\r\n}\r\n\r\nTEST(FormatIntegerTest, SevenDigits)\r\n{\r\n\tEXPECT_EQ(FormatInteger(1234567), \"1,234,567\");\r\n\tEXPECT_EQ(FormatInteger(-1234567), \"-1,234,567\");\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/ini_test.cpp",
    "content": "#include \"utils/ini.hpp\"\r\n\r\n#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include <string_view>\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nusing ::testing::ElementsAre;\r\nusing ::testing::Eq;\r\nusing ::testing::Field;\r\n\r\nstd::string ReplaceNewlines(std::string_view s)\r\n{\r\n\tstd::string out;\r\n\tbool prevR = false;\r\n\tfor (const char c : s) {\r\n\t\tif (c == '\\r') {\r\n\t\t\tprevR = true;\r\n\t\t} else {\r\n\t\t\tif (c == '\\n' && !prevR) out += '\\r';\r\n\t\t\tprevR = false;\r\n\t\t}\r\n\t\tout += c;\r\n\t}\r\n\treturn out;\r\n}\r\n\r\n} // namespace\r\n\r\nTEST(IniTest, BasicTest)\r\n{\r\n\ttl::expected<Ini, std::string> result = Ini::parse(R\"(\r\n; Section A comment\r\n[sectionA]\r\nkey1 = value1\r\nkey2 = value2\r\n; comment multi 1\r\nmulti = a\r\n; comment multi 2\r\nmulti = b\r\nint=-3\r\nfloat=2.5\r\n; bool yes comment\r\nbool yes=1\r\nbool no=0\r\n\r\n; Section B comment line 1\r\n; Section B comment line 2\r\n[sectionB]\r\nkey = value\r\n)\");\r\n\r\n\tASSERT_TRUE(result.has_value()) << result.error();\r\n\tEXPECT_EQ(result->getString(\"sectionA\", \"key1\"), \"value1\");\r\n\tEXPECT_EQ(result->getString(\"sectionA\", \"key2\"), \"value2\");\r\n\t{\r\n\t\tconst std::span<const Ini::Value> multiVals = result->get(\"sectionA\", \"multi\");\r\n\t\tstd::vector<std::string> multiStrs;\r\n\t\tfor (const Ini::Value &val : multiVals) {\r\n\t\t\tmultiStrs.push_back(val.value);\r\n\t\t}\r\n\t\tEXPECT_THAT(multiStrs, ElementsAre(Eq(\"a\"), Eq(\"b\")));\r\n\t}\r\n\tEXPECT_EQ(result->getInt(\"sectionA\", \"int\", 0), -3);\r\n\tEXPECT_NEAR(result->getFloat(\"sectionA\", \"float\", 0.0f), 2.5f, 0.001f);\r\n\tEXPECT_EQ(result->getString(\"sectionB\", \"key\"), \"value\");\r\n\r\n\tresult->set(\"newSection\", \"newKey\", \"hello\");\r\n\tresult->set(\"sectionA\", \"key1\", \"newValue\");\r\n\tresult->set(\"sectionA\", \"int\", 1337);\r\n\tresult->set(\"sectionA\", \"bool yes\", false);\r\n\tconst std::vector<std::string> newMulti { \"x\", \"y\", \"z\" };\r\n\tresult->set(\"sectionA\", \"multi\", newMulti);\r\n\tresult->set(\"sectionA\", \"float\", 10.5F);\r\n\tEXPECT_EQ(result->serialize(), ReplaceNewlines(R\"(; Section A comment\r\n[sectionA]\r\nkey1=newValue\r\nkey2=value2\r\n; comment multi 1\r\nmulti=x\r\n; comment multi 2\r\nmulti=y\r\nmulti=z\r\nint=1337\r\nfloat=10.5\r\n; bool yes comment\r\nbool yes=0\r\nbool no=0\r\n\r\n; Section B comment line 1\r\n; Section B comment line 2\r\n[sectionB]\r\nkey=value\r\n\r\n[newSection]\r\nnewKey=hello\r\n)\"));\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/inv_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"cursor.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"inv.h\"\r\n#include \"player.h\"\r\n#include \"storm/storm_net.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nconstexpr const char MissingMpqAssetsSkipReason[] = \"MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test suite\";\r\n\r\nclass InvTest : public ::testing::Test {\r\npublic:\r\n\tvoid SetUp() override\r\n\t{\r\n\t\tPlayers.resize(1);\r\n\t\tMyPlayer = &Players[0];\r\n\t\tif (missingMpqAssets_) {\r\n\t\t\tGTEST_SKIP() << MissingMpqAssetsSkipReason;\r\n\t\t}\r\n\t}\r\n\r\n\tstatic void SetUpTestSuite()\r\n\t{\r\n\t\tLoadCoreArchives();\r\n\t\tLoadGameArchives();\r\n\r\n\t\tmissingMpqAssets_ = !HaveMainData();\r\n\t\tif (missingMpqAssets_) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tInitCursor();\r\n\t\tLoadSpellData();\r\n\t\tLoadItemData();\r\n\t}\r\n\r\nprivate:\r\n\tstatic bool missingMpqAssets_;\r\n};\r\n\r\nbool InvTest::missingMpqAssets_ = false;\r\n\r\n/* Set up a given item as a spell scroll, allowing for its usage. */\r\nvoid set_up_scroll(Item &item, SpellID spell)\r\n{\r\n\tpcurs = CURSOR_HAND;\r\n\tleveltype = DTYPE_CATACOMBS;\r\n\tMyPlayer->_pRSpell = static_cast<SpellID>(spell);\r\n\titem._itype = ItemType::Misc;\r\n\titem._iMiscId = IMISC_SCROLL;\r\n\titem._iSpell = spell;\r\n}\r\n\r\n/* Clear the inventory of MyPlayerId. */\r\nvoid clear_inventory()\r\n{\r\n\tfor (int i = 0; i < InventoryGridCells; i++) {\r\n\t\tMyPlayer->InvList[i] = {};\r\n\t\tMyPlayer->InvGrid[i] = 0;\r\n\t}\r\n\tMyPlayer->_pNumInv = 0;\r\n}\r\n\r\n// Test that the scroll is used in the inventory in correct conditions\r\nTEST_F(InvTest, UseScroll_from_inventory)\r\n{\r\n\tset_up_scroll(MyPlayer->InvList[2], SpellID::Firebolt);\r\n\tMyPlayer->_pNumInv = 5;\r\n\tEXPECT_TRUE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n}\r\n\r\n// Test that the scroll is used in the belt in correct conditions\r\nTEST_F(InvTest, UseScroll_from_belt)\r\n{\r\n\tset_up_scroll(MyPlayer->SpdList[2], SpellID::Firebolt);\r\n\tEXPECT_TRUE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n}\r\n\r\n// Test that the scroll is not used in the inventory for each invalid condition\r\nTEST_F(InvTest, UseScroll_from_inventory_invalid_conditions)\r\n{\r\n\t// Empty the belt to prevent using a scroll from the belt\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tMyPlayer->SpdList[i].clear();\r\n\t}\r\n\r\n\t// Adjust inventory size\r\n\tMyPlayer->_pNumInv = 5;\r\n\r\n\tset_up_scroll(MyPlayer->InvList[2], SpellID::Firebolt);\r\n\tleveltype = DTYPE_TOWN;\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n\r\n\tset_up_scroll(MyPlayer->InvList[2], SpellID::Firebolt);\r\n\tMyPlayer->_pRSpell = SpellID::Healing;\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Healing));\r\n\r\n\tset_up_scroll(MyPlayer->InvList[2], SpellID::Firebolt);\r\n\tMyPlayer->InvList[2]._iMiscId = IMISC_STAFF;\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n\r\n\tset_up_scroll(MyPlayer->InvList[2], SpellID::Firebolt);\r\n\tMyPlayer->InvList[2].clear();\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n}\r\n\r\n// Test that the scroll is not used in the belt for each invalid condition\r\nTEST_F(InvTest, UseScroll_from_belt_invalid_conditions)\r\n{\r\n\t// Disable the inventory to prevent using a scroll from the inventory\r\n\tMyPlayer->_pNumInv = 0;\r\n\r\n\tset_up_scroll(MyPlayer->SpdList[2], SpellID::Firebolt);\r\n\tleveltype = DTYPE_TOWN;\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n\r\n\tset_up_scroll(MyPlayer->SpdList[2], SpellID::Firebolt);\r\n\tMyPlayer->_pRSpell = SpellID::Healing;\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Healing));\r\n\r\n\tset_up_scroll(MyPlayer->SpdList[2], SpellID::Firebolt);\r\n\tMyPlayer->SpdList[2]._iMiscId = IMISC_STAFF;\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n\r\n\tset_up_scroll(MyPlayer->SpdList[2], SpellID::Firebolt);\r\n\tMyPlayer->SpdList[2].clear();\r\n\tEXPECT_FALSE(CanUseScroll(*MyPlayer, SpellID::Firebolt));\r\n}\r\n\r\n// Test gold calculation\r\nTEST_F(InvTest, CalculateGold)\r\n{\r\n\tMyPlayer->_pNumInv = 10;\r\n\t// Set up 4 slots of gold in the inventory\r\n\tMyPlayer->InvList[1]._itype = ItemType::Gold;\r\n\tMyPlayer->InvList[5]._itype = ItemType::Gold;\r\n\tMyPlayer->InvList[2]._itype = ItemType::Gold;\r\n\tMyPlayer->InvList[3]._itype = ItemType::Gold;\r\n\t// Set the gold amount to arbitrary values\r\n\tMyPlayer->InvList[1]._ivalue = 100;\r\n\tMyPlayer->InvList[5]._ivalue = 200;\r\n\tMyPlayer->InvList[2]._ivalue = 3;\r\n\tMyPlayer->InvList[3]._ivalue = 30;\r\n\r\n\tEXPECT_EQ(CalculateGold(*MyPlayer), 333);\r\n}\r\n\r\n// Test automatic gold placing\r\nTEST_F(InvTest, GoldAutoPlace)\r\n{\r\n\tSNetInitializeProvider(SELCONN_LOOPBACK, nullptr);\r\n\r\n\t// Empty the inventory\r\n\tclear_inventory();\r\n\r\n\t// Put gold into the inventory:\r\n\t// | 1000 | ... | ...\r\n\tMyPlayer->InvList[0]._itype = ItemType::Gold;\r\n\tMyPlayer->InvList[0]._ivalue = 1000;\r\n\tMyPlayer->_pNumInv = 1;\r\n\t// Put (max gold - 100) gold, which is 4900, into the player's hand\r\n\tMyPlayer->HoldItem._itype = ItemType::Gold;\r\n\tMyPlayer->HoldItem._ivalue = GOLD_MAX_LIMIT - 100;\r\n\r\n\tGoldAutoPlace(*MyPlayer, MyPlayer->HoldItem);\r\n\t// We expect the inventory:\r\n\t// | 5000 | 900 | ...\r\n\tEXPECT_EQ(MyPlayer->InvList[0]._ivalue, GOLD_MAX_LIMIT);\r\n\tEXPECT_EQ(MyPlayer->InvList[1]._ivalue, 900);\r\n}\r\n\r\n// Test removing an item from inventory with no other items.\r\nTEST_F(InvTest, RemoveInvItem)\r\n{\r\n\tSNetInitializeProvider(SELCONN_LOOPBACK, nullptr);\r\n\r\n\tclear_inventory();\r\n\t// Put a two-slot misc item into the inventory:\r\n\t// | (item) | (item) | ... | ...\r\n\tMyPlayer->_pNumInv = 1;\r\n\tMyPlayer->InvGrid[0] = 1;\r\n\tMyPlayer->InvGrid[1] = -1;\r\n\tMyPlayer->InvList[0]._itype = ItemType::Misc;\r\n\r\n\tMyPlayer->RemoveInvItem(0);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[0], 0);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[1], 0);\r\n\tEXPECT_EQ(MyPlayer->_pNumInv, 0);\r\n}\r\n\r\n// Test removing an item from middle of inventory list.\r\nTEST_F(InvTest, RemoveInvItem_shiftsListFromMiddle)\r\n{\r\n\tSNetInitializeProvider(SELCONN_LOOPBACK, nullptr);\r\n\r\n\tclear_inventory();\r\n\t// Put a two-slot misc item and a ring into the inventory, followed by another two-slot misc item:\r\n\t// | (item) | (item) | (ring) | (item) | (item) | ...\r\n\tMyPlayer->_pNumInv = 3;\r\n\tMyPlayer->InvGrid[0] = 1;\r\n\tMyPlayer->InvGrid[1] = -1;\r\n\tMyPlayer->InvList[0]._itype = ItemType::Misc;\r\n\r\n\tMyPlayer->InvGrid[2] = 2;\r\n\tMyPlayer->InvList[1]._itype = ItemType::Ring;\r\n\r\n\tMyPlayer->InvGrid[3] = 3;\r\n\tMyPlayer->InvGrid[4] = -3;\r\n\tMyPlayer->InvList[2]._itype = ItemType::Misc;\r\n\r\n\tMyPlayer->RemoveInvItem(1);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[0], 1);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[1], -1);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[2], 0);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[3], 2);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[4], -2);\r\n\r\n\tEXPECT_EQ(MyPlayer->InvList[0]._itype, ItemType::Misc);\r\n\tEXPECT_EQ(MyPlayer->InvList[1]._itype, ItemType::Misc);\r\n\r\n\tEXPECT_EQ(MyPlayer->_pNumInv, 2);\r\n}\r\n\r\n// Test removing an item from front of inventory list.\r\nTEST_F(InvTest, RemoveInvItem_shiftsListFromFront)\r\n{\r\n\tSNetInitializeProvider(SELCONN_LOOPBACK, nullptr);\r\n\r\n\tclear_inventory();\r\n\t// Put a two-slot misc item and a ring into the inventory, followed by another two-slot misc item:\r\n\t// | (item) | (item) | (ring) | (item) | (item) | ...\r\n\tMyPlayer->_pNumInv = 3;\r\n\tMyPlayer->InvGrid[0] = 1;\r\n\tMyPlayer->InvGrid[1] = -1;\r\n\tMyPlayer->InvList[0]._itype = ItemType::Misc;\r\n\r\n\tMyPlayer->InvGrid[2] = 2;\r\n\tMyPlayer->InvList[1]._itype = ItemType::Ring;\r\n\r\n\tMyPlayer->InvGrid[3] = 3;\r\n\tMyPlayer->InvGrid[4] = -3;\r\n\tMyPlayer->InvList[2]._itype = ItemType::Misc;\r\n\r\n\tMyPlayer->RemoveInvItem(0);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[0], 0);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[1], 0);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[2], 1);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[3], 2);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[4], -2);\r\n\r\n\tEXPECT_EQ(MyPlayer->InvList[0]._itype, ItemType::Ring);\r\n\tEXPECT_EQ(MyPlayer->InvList[1]._itype, ItemType::Misc);\r\n\r\n\tEXPECT_EQ(MyPlayer->_pNumInv, 2);\r\n}\r\n\r\n// Test removing an item from the belt\r\nTEST_F(InvTest, RemoveSpdBarItem)\r\n{\r\n\tSNetInitializeProvider(SELCONN_LOOPBACK, nullptr);\r\n\r\n\t// Clear the belt\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tMyPlayer->SpdList[i].clear();\r\n\t}\r\n\t// Put an item in the belt: | x | x | item | x | x | x | x | x |\r\n\tMyPlayer->SpdList[3]._itype = ItemType::Misc;\r\n\r\n\tMyPlayer->RemoveSpdBarItem(3);\r\n\tEXPECT_TRUE(MyPlayer->SpdList[3].isEmpty());\r\n}\r\n\r\n// Test removing a scroll from the inventory\r\nTEST_F(InvTest, RemoveCurrentSpellScrollFromInventory)\r\n{\r\n\tclear_inventory();\r\n\r\n\t// Put a firebolt scroll into the inventory\r\n\tMyPlayer->_pNumInv = 1;\r\n\tMyPlayer->executedSpell.spellId = SpellID::Firebolt;\r\n\tMyPlayer->executedSpell.spellFrom = INVITEM_INV_FIRST;\r\n\tMyPlayer->InvList[0]._itype = ItemType::Misc;\r\n\tMyPlayer->InvList[0]._iMiscId = IMISC_SCROLL;\r\n\tMyPlayer->InvList[0]._iSpell = SpellID::Firebolt;\r\n\r\n\tConsumeScroll(*MyPlayer);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[0], 0);\r\n\tEXPECT_EQ(MyPlayer->_pNumInv, 0);\r\n}\r\n\r\n// Test removing the first matching scroll from inventory\r\nTEST_F(InvTest, RemoveCurrentSpellScrollFromInventoryFirstMatch)\r\n{\r\n\tclear_inventory();\r\n\r\n\t// Put a firebolt scroll into the inventory\r\n\tMyPlayer->_pNumInv = 1;\r\n\tMyPlayer->executedSpell.spellId = SpellID::Firebolt;\r\n\tMyPlayer->executedSpell.spellFrom = 0; // any matching scroll\r\n\tMyPlayer->InvList[0]._itype = ItemType::Misc;\r\n\tMyPlayer->InvList[0]._iMiscId = IMISC_SCROLL;\r\n\tMyPlayer->InvList[0]._iSpell = SpellID::Firebolt;\r\n\r\n\tConsumeScroll(*MyPlayer);\r\n\tEXPECT_EQ(MyPlayer->InvGrid[0], 0);\r\n\tEXPECT_EQ(MyPlayer->_pNumInv, 0);\r\n}\r\n\r\n// Test removing a scroll from the belt\r\nTEST_F(InvTest, RemoveCurrentSpellScroll_belt)\r\n{\r\n\tSNetInitializeProvider(SELCONN_LOOPBACK, nullptr);\r\n\r\n\t// Clear the belt\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tMyPlayer->SpdList[i].clear();\r\n\t}\r\n\t// Put a firebolt scroll into the belt\r\n\tMyPlayer->executedSpell.spellId = SpellID::Firebolt;\r\n\tMyPlayer->executedSpell.spellFrom = INVITEM_BELT_FIRST + 3;\r\n\tMyPlayer->SpdList[3]._itype = ItemType::Misc;\r\n\tMyPlayer->SpdList[3]._iMiscId = IMISC_SCROLL;\r\n\tMyPlayer->SpdList[3]._iSpell = SpellID::Firebolt;\r\n\r\n\tConsumeScroll(*MyPlayer);\r\n\tEXPECT_TRUE(MyPlayer->SpdList[3].isEmpty());\r\n}\r\n\r\n// Test removing the first matching scroll from the belt\r\nTEST_F(InvTest, RemoveCurrentSpellScrollFirstMatchFromBelt)\r\n{\r\n\tSNetInitializeProvider(SELCONN_LOOPBACK, nullptr);\r\n\r\n\t// Clear the belt\r\n\tfor (int i = 0; i < MaxBeltItems; i++) {\r\n\t\tMyPlayer->SpdList[i].clear();\r\n\t}\r\n\t// Put a firebolt scroll into the belt\r\n\tMyPlayer->executedSpell.spellId = SpellID::Firebolt;\r\n\tMyPlayer->executedSpell.spellFrom = 0; // any matching scroll\r\n\tMyPlayer->SpdList[3]._itype = ItemType::Misc;\r\n\tMyPlayer->SpdList[3]._iMiscId = IMISC_SCROLL;\r\n\tMyPlayer->SpdList[3]._iSpell = SpellID::Firebolt;\r\n\r\n\tConsumeScroll(*MyPlayer);\r\n\tEXPECT_TRUE(MyPlayer->SpdList[3].isEmpty());\r\n}\r\n\r\nTEST_F(InvTest, ItemSizeRuneOfStone)\r\n{\r\n\t// Inventory sizes are currently determined by examining the sprite size\r\n\t// rune of stone and grey suit are adjacent in the sprite list so provide an easy check for off-by-one errors\r\n\tif (!gbIsHellfire) return;\r\n\tItem testItem {};\r\n\tInitializeItem(testItem, IDI_RUNEOFSTONE);\r\n\tEXPECT_EQ(GetInventorySize(testItem), Size(1, 1));\r\n}\r\n\r\nTEST_F(InvTest, ItemSizeGreySuit)\r\n{\r\n\tif (!gbIsHellfire) return;\r\n\tItem testItem {};\r\n\tInitializeItem(testItem, IDI_GREYSUIT);\r\n\tEXPECT_EQ(GetInventorySize(testItem), Size(2, 2));\r\n}\r\n\r\nTEST_F(InvTest, ItemSizeAuric)\r\n{\r\n\t// Auric amulet is the first used hellfire sprite, but there's multiple unused sprites before it in the list.\r\n\t// unfortunately they're the same size so this is less valuable as a test.\r\n\tif (!gbIsHellfire) return;\r\n\tItem testItem {};\r\n\tInitializeItem(testItem, IDI_AURIC);\r\n\tEXPECT_EQ(GetInventorySize(testItem), Size(1, 1));\r\n}\r\n\r\nTEST_F(InvTest, ItemSizeLastDiabloItem)\r\n{\r\n\t// Short battle bow is the last diablo sprite, off by ones will end up loading a 1x1 unused sprite from hellfire,.\r\n\tItem testItem {};\r\n\tInitializeItem(testItem, IDI_SHORT_BATTLE_BOW);\r\n\tEXPECT_EQ(GetInventorySize(testItem), Size(2, 3));\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/items_test.cpp",
    "content": "#include <climits>\r\n#include <random>\r\n\r\n#include <gtest/gtest.h>\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/random.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"items.h\"\r\n#include \"player.h\"\r\n#include \"spells.h\"\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nclass ItemsTest : public ::testing::Test {\r\npublic:\r\n\tvoid SetUp() override\r\n\t{\r\n\t\tPlayers.resize(1);\r\n\t\tMyPlayer = &Players[0];\r\n\t\tfor (auto &flag : UniqueItemFlags)\r\n\t\t\tflag = false;\r\n\t}\r\n\r\n\tstatic void SetUpTestSuite()\r\n\t{\r\n\t\tLoadItemData();\r\n\t\tLoadSpellData();\r\n\t\tgbIsSpawn = false;\r\n\t\tgbIsMultiplayer = false; // to also test UniqueItemFlags\r\n\t}\r\n};\r\n\r\nvoid GenerateAllUniques(bool hellfire, const size_t expectedUniques)\r\n{\r\n\tgbIsHellfire = hellfire;\r\n\tUnloadModArchives();\r\n\tif (hellfire) {\r\n\t\tLoadModArchives({ { \"Hellfire\" } });\r\n\t}\r\n\tLoadItemData();\r\n\r\n\tstd::mt19937 betterRng;\r\n\tconst std::uniform_int_distribution<uint32_t> dist(0, std::numeric_limits<uint32_t>::max());\r\n\r\n\t// Get seed for test run from time. If a test run fails, remember the seed and hardcode it here.\r\n\tconst uint32_t testRunSeed = static_cast<uint32_t>(time(nullptr));\r\n\tbetterRng.seed(testRunSeed);\r\n\r\n\tstd::set<int> foundUniques;\r\n\r\n\tconstexpr int max_iterations = 1000000;\r\n\tint iteration = 0;\r\n\tint uniqueIndex = -1;\r\n\r\n\tfor (auto &uniqueItem : UniqueItems) {\r\n\t\t++uniqueIndex;\r\n\r\n\t\tif (foundUniques.contains(uniqueIndex))\r\n\t\t\tcontinue;\r\n\r\n\t\t_item_indexes uniqueBaseIndex = IDI_GOLD;\r\n\t\tfor (size_t j = 0; j < AllItemsList.size(); j++) {\r\n\t\t\tif (!IsItemAvailable(static_cast<int>(j)))\r\n\t\t\t\tcontinue;\r\n\t\t\tif (AllItemsList[j].iItemId != uniqueItem.UIItemId)\r\n\t\t\t\tcontinue;\r\n\t\t\tif (AllItemsList[j].dropRate > 0)\r\n\t\t\t\tuniqueBaseIndex = static_cast<_item_indexes>(j);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif (uniqueBaseIndex == IDI_GOLD)\r\n\t\t\tcontinue; // Unique not dropable (Quest-Unique)\r\n\r\n\t\tauto &baseItemData = AllItemsList[static_cast<size_t>(uniqueBaseIndex)];\r\n\r\n\t\twhile (true) {\r\n\t\t\titeration += 1;\r\n\r\n\t\t\tif (iteration > max_iterations)\r\n\t\t\t\tFAIL() << StrCat(\"Item \", uniqueItem.UIName, \" not found in \", max_iterations, \" tries with test run seed \", testRunSeed);\r\n\r\n\t\t\tItem testItem = {};\r\n\t\t\ttestItem._iMiscId = baseItemData.iMiscId;\r\n\t\t\tstd::uniform_int_distribution<int32_t> dist(0, INT_MAX);\r\n\t\t\tSetRndSeed(dist(betterRng));\r\n\r\n\t\t\tint targetLvl = uniqueItem.UIMinLvl;\r\n\t\t\tint uper = 1;\r\n\t\t\tif (uniqueItem.UIMinLvl - 4 > 0) {\r\n\t\t\t\tuper = 15;\r\n\t\t\t\ttargetLvl = uniqueItem.UIMinLvl - 4;\r\n\t\t\t}\r\n\r\n\t\t\tSetupAllItems(*MyPlayer, testItem, uniqueBaseIndex, AdvanceRndSeed(), targetLvl, uper, true, false);\r\n\t\t\tTryRandomUniqueItem(testItem, uniqueBaseIndex, targetLvl, uper, true, false);\r\n\t\t\tSetupItem(testItem);\r\n\r\n\t\t\tif (testItem._iMagical != ITEM_QUALITY_UNIQUE)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tfoundUniques.insert(testItem._iUid);\r\n\r\n\t\t\tif (testItem._iUid == uniqueIndex)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tEXPECT_EQ(foundUniques.size(), expectedUniques) << StrCat(\"test run seed \", testRunSeed);\r\n}\r\n\r\nTEST_F(ItemsTest, AllDiabloUniquesCanDrop)\r\n{\r\n\tGenerateAllUniques(false, 79);\r\n}\r\n\r\nTEST_F(ItemsTest, AllHellfireUniquesCanDrop)\r\n{\r\n\tGenerateAllUniques(true, 99);\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/language_for_testing.cpp",
    "content": "#include <string>\r\n#include <string_view>\r\n#include <vector>\r\n\r\nstd::string_view GetLanguageCode() { return \"en\"; }\r\nbool HasTranslation(const std::string &locale) { return true; }\r\nvoid LanguageInitialize() { }\r\nstd::string_view LanguageTranslate(const char *key) { return key; }\r\nstd::string_view LanguagePluralTranslate(const char *singular, std::string_view plural, int count) { return count == 1 ? singular : plural; }\r\nstd::string_view LanguageParticularTranslate(std::string_view context, std::string_view message) { return message; }\r\n\r\nnamespace devilution {\r\nstd::vector<std::string> GetLocales() { return {}; }\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/light_render_benchmark.cpp",
    "content": "#include <array>\r\n#include <cstddef>\r\n#include <cstdio>\r\n\r\n#include <benchmark/benchmark.h>\r\n\r\n#include \"engine/lighting_defs.hpp\"\r\n#include \"engine/render/light_render.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"levels/gendung_defs.hpp\"\r\n#include \"utils/log.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/sdl_wrap.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nvoid BM_BuildLightmap(benchmark::State &state)\r\n{\r\n\tconst std::string benchmarkDataPath = paths::BasePath() + \"test/fixtures/light_render_benchmark/dLight.dmp\";\r\n\tFILE *lightFile = std::fopen(benchmarkDataPath.c_str(), \"rb\");\r\n\tuint8_t dLight[MAXDUNX][MAXDUNY];\r\n\tstd::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables;\r\n\tif (lightFile != nullptr) {\r\n\t\tif (std::fread(&dLight[0][0], sizeof(uint8_t) * MAXDUNX * MAXDUNY, 1, lightFile) != 1) {\r\n\t\t\tstd::perror(\"Failed to read dLight.dmp\");\r\n\t\t\texit(1);\r\n\t\t}\r\n\t\tstd::fclose(lightFile);\r\n\t}\r\n\r\n\tconst SDLSurfaceUniquePtr sdl_surface = SDLWrap::CreateRGBSurfaceWithFormat(\r\n\t    /*flags=*/0, /*width=*/640, /*height=*/480, /*depth=*/8, SDL_PIXELFORMAT_INDEX8);\r\n\tif (sdl_surface == nullptr) {\r\n\t\tstd::fprintf(stderr, \"Failed to create SDL Surface: %s\\n\", SDL_GetError());\r\n\t\texit(1);\r\n\t}\r\n\tconst Surface out = Surface(sdl_surface.get());\r\n\r\n\tconst Point tilePosition { 48, 44 };\r\n\tconst Point targetBufferPosition { 0, -17 };\r\n\tconst int viewportWidth = 640;\r\n\tconst int viewportHeight = 352;\r\n\tconst int rows = 25;\r\n\tconst int columns = 10;\r\n\tconst uint8_t *outBuffer = out.at(0, 0);\r\n\tconst uint16_t outPitch = out.pitch();\r\n\r\n\tfor (auto _ : state) {\r\n\t\tconst Lightmap lightmap = Lightmap::build(/*perPixelLighting=*/true,\r\n\t\t    tilePosition, targetBufferPosition,\r\n\t\t    viewportWidth, viewportHeight, rows, columns,\r\n\t\t    outBuffer, outPitch, lightTables, lightTables[0].data(), lightTables.back().data(),\r\n\t\t    dLight, /*microTileLen=*/10);\r\n\r\n\t\tuint8_t lightLevel = *lightmap.getLightingAt(outBuffer + outPitch * 120 + 120);\r\n\t\tbenchmark::DoNotOptimize(lightLevel);\r\n\t}\r\n\tstate.SetBytesProcessed(state.iterations() * viewportWidth * viewportHeight);\r\n\tstate.SetItemsProcessed(state.iterations() * rows * columns);\r\n}\r\n\r\nBENCHMARK(BM_BuildLightmap);\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/main.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include <iostream>\r\n#include <string>\r\n#include <unordered_map>\r\n\r\n#include \"headless_mode.hpp\"\r\n#include \"options.h\"\r\n#include \"utils/paths.h\"\r\n\r\nnamespace {\r\n\r\n// Custom listener to track and report skipped tests with reasons\r\nclass SkippedTestListener : public testing::EmptyTestEventListener {\r\n\tstd::unordered_map<std::string, int> skipReasons;\r\n\tint totalSkipped = 0;\r\n\r\n\tvoid OnTestPartResult(const testing::TestPartResult &test_part_result) override\r\n\t{\r\n\t\tif (test_part_result.skipped()) {\r\n\t\t\ttotalSkipped++;\r\n\t\t\tstd::string reason = test_part_result.message();\r\n\t\t\tif (reason.empty()) {\r\n\t\t\t\treason = \"No reason provided\";\r\n\t\t\t}\r\n\t\t\tskipReasons[reason]++;\r\n\t\t}\r\n\t}\r\n\r\n\tvoid OnTestProgramEnd(const testing::UnitTest & /*unit_test*/) override\r\n\t{\r\n\t\tif (totalSkipped > 0) {\r\n\t\t\tstd::cout << \"\\n\";\r\n\t\t\tstd::cout << \"========================================\\n\";\r\n\t\t\tstd::cout << \"Test Skip Summary\\n\";\r\n\t\t\tstd::cout << \"========================================\\n\";\r\n\t\t\tstd::cout << \"Total tests skipped: \" << totalSkipped << \"\\n\\n\";\r\n\r\n\t\t\t// Show skip reasons, with most specific reasons first\r\n\t\t\tbool hasMpqReason = false;\r\n\t\t\tbool hasNoReason = false;\r\n\t\t\tint mpqSkipCount = 0;\r\n\t\t\tint noReasonCount = 0;\r\n\r\n\t\t\tfor (const auto &[reason, count] : skipReasons) {\r\n\t\t\t\tif (reason.find(\"MPQ assets\") != std::string::npos) {\r\n\t\t\t\t\thasMpqReason = true;\r\n\t\t\t\t\tmpqSkipCount += count;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif (reason == \"No reason provided\") {\r\n\t\t\t\t\thasNoReason = true;\r\n\t\t\t\t\tnoReasonCount += count;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tstd::cout << \"  • \" << count << \" test\" << (count > 1 ? \"s\" : \"\") << \" skipped: \" << reason << \"\\n\";\r\n\t\t\t}\r\n\r\n\t\t\t// Combine MPQ-related skips for clearer output\r\n\t\t\tif (hasMpqReason) {\r\n\t\t\t\tint totalMpqRelated = mpqSkipCount + (hasNoReason ? noReasonCount : 0);\r\n\t\t\t\tstd::cout << \"  • \" << totalMpqRelated << \" test\" << (totalMpqRelated > 1 ? \"s\" : \"\")\r\n\t\t\t\t          << \" skipped: MPQ assets (spawn.mpq or DIABDAT.MPQ) not found\\n\";\r\n\t\t\t\tif (hasNoReason && noReasonCount > 0) {\r\n\t\t\t\t\tstd::cout << \"    (\" << noReasonCount << \" test\" << (noReasonCount > 1 ? \"s\" : \"\")\r\n\t\t\t\t\t          << \" automatically skipped due to test suite setup failure)\\n\";\r\n\t\t\t\t}\r\n\t\t\t} else if (hasNoReason) {\r\n\t\t\t\t// Only \"No reason provided\" - show it as-is\r\n\t\t\t\tstd::cout << \"  • \" << noReasonCount << \" test\" << (noReasonCount > 1 ? \"s\" : \"\")\r\n\t\t\t\t          << \" skipped: \" << \"No reason provided\" << \"\\n\";\r\n\t\t\t}\r\n\r\n\t\t\tstd::cout << \"========================================\\n\";\r\n\t\t}\r\n\t}\r\n};\r\n\r\n} // namespace\r\n\r\nint main(int argc, char **argv)\r\n{\r\n\t// Disable error dialogs.\r\n\tdevilution::HeadlessMode = true;\r\n\r\n#if SDL_VERSION_ATLEAST(2, 0, 0)\r\n\t// Disable hardware cursor while testing.\r\n\tdevilution::GetOptions().Graphics.hardwareCursor.SetValue(false);\r\n#endif\r\n\r\n#ifdef __APPLE__\r\n\tdevilution::paths::SetAssetsPath(\r\n\t    devilution::paths::BasePath() + \"devilutionx.app/Contents/Resources/\");\r\n#endif\r\n\r\n\ttesting::InitGoogleTest(&argc, argv);\r\n\r\n\t// Add custom listener to track and report skipped tests\r\n\ttesting::TestEventListeners &listeners = testing::UnitTest::GetInstance()->listeners();\r\n\tlisteners.Append(new SkippedTestListener());\r\n\r\n\treturn RUN_ALL_TESTS();\r\n}\r\n"
  },
  {
    "path": "test/math_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"engine/displacement.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nTEST(MathTest, WorldScreenTransformation)\r\n{\r\n\tDisplacement offset { 5, 2 };\r\n\t// Diablo renders tiles with the world origin translated to the top left of the screen, while the normal convention\r\n\t// has the screen origin at the bottom left. This means that we end up with negative offsets in screen space for\r\n\t// tiles in world space where x > y\r\n\tEXPECT_EQ(offset.worldToScreen(), Displacement(-96, -112));\r\n\r\n\t// Transformation should be reversable (as long as it's not truncating)\r\n\tEXPECT_EQ(offset.worldToScreen().screenToWorld(), offset);\r\n\r\n\t// Tiles with y >= x will still have a negative y coordinate in screen space\r\n\toffset = { 2, 5 };\r\n\tEXPECT_EQ(offset.worldToScreen(), Displacement(96, -112));\r\n\r\n\t// Most screen to world transformations will have a further displacement applied, this is a simple case of\r\n\t// selecting a tile on the edge of the world with the default origin\r\n\tconst Displacement cursorPosition = { 342, -150 };\r\n\tEXPECT_EQ(cursorPosition.screenToWorld(), Displacement(0, 10));\r\n\r\n\t// Screen > World transforms lose information, so cannot be reversed exactly using ints\r\n\tEXPECT_EQ(cursorPosition.screenToWorld().worldToScreen(), Displacement(320, -160));\r\n}\r\n\r\nTEST(MathTest, NormalizeDisplacement)\r\n{\r\n\t// Normalizing displacements transforms the value into 16 bit fixed point representations\r\n\tDisplacement vector { 5, 0 };\r\n\tEXPECT_FLOAT_EQ(vector.magnitude(), 5);\r\n\tEXPECT_EQ(vector.normalized(), Displacement(1 << 16, 0)); // (1.0, 0.0)\r\n\r\n\tvector = { 3, 4 };\r\n\tEXPECT_FLOAT_EQ(vector.magnitude(), 5);\r\n\tEXPECT_EQ(vector.normalized(), Displacement(39321, 52428)); // ~(0.6, 0.8)\r\n\r\n\tvector = { -5, 2 };\r\n\tEXPECT_FLOAT_EQ(vector.magnitude(), 5.3851647f);\r\n\tEXPECT_EQ(vector.normalized(), Displacement(-60848, 24339)); // ~(-0.92, 0.37)\r\n}\r\n\r\nTEST(MathTest, MissileTransformation)\r\n{\r\n\t// starting with a Displacement 2 world units West results in a vector pointing left of screen\r\n\tEXPECT_EQ(Displacement(2, -2).worldToNormalScreen(), Displacement(-65536, 0));\r\n\r\n\t// if it's not normalizing the vector then it's a problem :D\r\n\tEXPECT_EQ(Displacement(4, -4).worldToNormalScreen(), Displacement(-65536, 0));\r\n\r\n\t// Because of the isometric projection the y axis gets squashed\r\n\tEXPECT_EQ(Displacement(8, 1).worldToNormalScreen(), Displacement(-40235, -25865)); // ~(0.6, 0.8/2)\r\n\r\n\t// in elevation projection this would be a vector with x == y, isometric projection means y == x/2\r\n\tEXPECT_EQ(Displacement(8, 0).worldToNormalScreen(), Displacement(-46340, -23170)); // ~(0.7, 0.7/2)\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/missiles_test.cpp",
    "content": "#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include <ankerl/unordered_dense.h>\r\n\r\n#include \"engine/random.hpp\"\r\n#include \"missiles.h\"\r\n\r\nusing namespace devilution;\r\nusing ::testing::AllOf;\r\nusing ::testing::Gt;\r\nusing ::testing::Lt;\r\nusing ::testing::Pair;\r\nusing ::testing::UnorderedElementsAre;\r\n\r\nvoid TestArrowRotatesUniformly(Missile &missile, int startingFrame, int leftFrame, int rightFrame)\r\n{\r\n\tankerl::unordered_dense::map<int, unsigned> observed {};\r\n\tfor (auto i = 0; i < 100; i++) {\r\n\t\tmissile._miAnimFrame = startingFrame;\r\n\t\tTestRotateBlockedMissile(missile);\r\n\t\tobserved[missile._miAnimFrame]++;\r\n\t}\r\n\r\n\tEXPECT_THAT(observed, UnorderedElementsAre(Pair(leftFrame, AllOf(Gt(30U), Lt(70U))), Pair(rightFrame, AllOf(Gt(30U), Lt(70U))))) << \"Arrows should rotate either direction roughly 50% of the time\";\r\n}\r\n\r\nvoid TestAnimatedMissileRotatesUniformly(Missile &missile, int startingDir, int leftDir, int rightDir)\r\n{\r\n\tankerl::unordered_dense::map<int, unsigned> observed {};\r\n\tfor (auto i = 0; i < 100; i++) {\r\n\t\tmissile.setFrameGroupRaw(startingDir);\r\n\t\tTestRotateBlockedMissile(missile);\r\n\t\tobserved[missile.getFrameGroupRaw()]++;\r\n\t}\r\n\r\n\tEXPECT_THAT(observed, UnorderedElementsAre(Pair(leftDir, AllOf(Gt(30U), Lt(70U))), Pair(rightDir, AllOf(Gt(30U), Lt(70U))))) << \"Animated missiles should rotate either direction roughly 50% of the time\";\r\n}\r\n\r\nTEST(Missiles, RotateBlockedMissileArrow)\r\n{\r\n\tPlayers.resize(1);\r\n\tMyPlayerId = 0;\r\n\tMyPlayer = &Players[MyPlayerId];\r\n\t*MyPlayer = {};\r\n\tLoadMissileData();\r\n\r\n\tconst devilution::Player &player = Players[0];\r\n\t// missile can be a copy or a reference, there's no nullptr check and the functions that use it don't expect the instance to be part of a global structure so it doesn't really matter for this use.\r\n\tMissile missile = *AddMissile({ 0, 0 }, { 0, 0 }, Direction::South, MissileID::Arrow, TARGET_MONSTERS, player, 0, 0);\r\n\r\n\t// Arrows have a hardcoded frame count and use 1-indexed sprites\r\n\tEXPECT_EQ(missile._miAnimFrame, 1);\r\n\r\n\tTestArrowRotatesUniformly(missile, 5, 4, 6);\r\n\tTestArrowRotatesUniformly(missile, 1, 16, 2);\r\n\tTestArrowRotatesUniformly(missile, 16, 15, 1);\r\n\r\n\t// All other missiles use the number of 0-indexed sprites defined in MissileSpriteData\r\n\tmissile = *AddMissile({ 0, 0 }, { 0, 0 }, Direction::South, MissileID::Firebolt, TARGET_MONSTERS, player, 0, 0);\r\n\tEXPECT_EQ(missile.getFrameGroupRaw(), 0);\r\n\tTestAnimatedMissileRotatesUniformly(missile, 5, 4, 6);\r\n\tTestAnimatedMissileRotatesUniformly(missile, 0, 15, 1);\r\n\tTestAnimatedMissileRotatesUniformly(missile, 15, 14, 0);\r\n}\r\n\r\nTEST(Missiles, GetDirection8)\r\n{\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 0, 0 }, { 15, 15 }));\r\n\tEXPECT_EQ(Direction::SouthWest, GetDirection({ 0, 0 }, { 0, 15 }));\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 0, 0 }, { 8, 15 }));\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 0, 0 }, { 8, 8 }));\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 0, 0 }, { 15, 8 }));\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 0, 0 }, { 15, 7 }));\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 0, 0 }, { 11, 7 }));\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 0, 0 }, { 8, 11 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 15, 15 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::NorthEast, GetDirection({ 0, 15 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 8, 15 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 8, 8 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 15, 8 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 15, 7 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 11, 7 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 8, 11 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 0, 15 }, { 15, 0 }));\r\n\tEXPECT_EQ(Direction::SouthEast, GetDirection({ 0, 0 }, { 15, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 0, 8 }, { 15, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 0, 8 }, { 8, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 0, 15 }, { 8, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 0, 15 }, { 7, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 0, 11 }, { 7, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 0, 8 }, { 11, 0 }));\r\n\r\n\tEXPECT_EQ(Direction::South, GetDirection({ 1, 1 }, { 2, 2 }));\r\n\tEXPECT_EQ(Direction::SouthWest, GetDirection({ 1, 1 }, { 1, 2 }));\r\n\tEXPECT_EQ(Direction::West, GetDirection({ 1, 1 }, { 0, 2 }));\r\n\tEXPECT_EQ(Direction::NorthWest, GetDirection({ 1, 1 }, { 0, 1 }));\r\n\tEXPECT_EQ(Direction::North, GetDirection({ 1, 1 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction::NorthEast, GetDirection({ 1, 1 }, { 1, 0 }));\r\n\tEXPECT_EQ(Direction::East, GetDirection({ 1, 1 }, { 2, 0 }));\r\n\tEXPECT_EQ(Direction::SouthEast, GetDirection({ 1, 1 }, { 2, 1 }));\r\n\r\n\tEXPECT_EQ(Direction::SouthWest, GetDirection({ 0, 0 }, { 0, 0 })) << \"GetDirection is expected to default to Direction::SouthWest when the points occupy the same tile\";\r\n}\r\n\r\nTEST(Missiles, GetDirection16)\r\n{\r\n\tEXPECT_EQ(Direction16::South, GetDirection16({ 0, 0 }, { 15, 15 }));\r\n\tEXPECT_EQ(Direction16::SouthWest, GetDirection16({ 0, 0 }, { 0, 15 }));\r\n\tEXPECT_EQ(Direction16::South_SouthWest, GetDirection16({ 0, 0 }, { 8, 15 }));\r\n\tEXPECT_EQ(Direction16::South, GetDirection16({ 0, 0 }, { 8, 8 }));\r\n\tEXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 0, 0 }, { 15, 8 }));\r\n\tEXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 0, 0 }, { 15, 7 }));\r\n\tEXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 0, 0 }, { 11, 7 }));\r\n\tEXPECT_EQ(Direction16::South, GetDirection16({ 0, 0 }, { 8, 11 }));\r\n\tEXPECT_EQ(Direction16::North, GetDirection16({ 15, 15 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::NorthEast, GetDirection16({ 0, 15 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::North_NorthEast, GetDirection16({ 8, 15 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::North, GetDirection16({ 8, 8 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 15, 8 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 15, 7 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 11, 7 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::North, GetDirection16({ 8, 11 }, { 0, 0 }));\r\n\tEXPECT_EQ(Direction16::East, GetDirection16({ 0, 15 }, { 15, 0 }));\r\n\tEXPECT_EQ(Direction16::SouthEast, GetDirection16({ 0, 0 }, { 15, 0 }));\r\n\tEXPECT_EQ(Direction16::East_SouthEast, GetDirection16({ 0, 8 }, { 15, 0 }));\r\n\tEXPECT_EQ(Direction16::East, GetDirection16({ 0, 8 }, { 8, 0 }));\r\n\tEXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 0, 15 }, { 8, 0 }));\r\n\tEXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 0, 15 }, { 7, 0 }));\r\n\tEXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 0, 11 }, { 7, 0 }));\r\n\tEXPECT_EQ(Direction16::East, GetDirection16({ 0, 8 }, { 11, 0 }));\r\n\r\n\tEXPECT_EQ(Direction16::South, GetDirection16({ 2, 2 }, { 3, 3 }));\r\n\tEXPECT_EQ(Direction16::South_SouthWest, GetDirection16({ 2, 2 }, { 3, 4 }));\r\n\tEXPECT_EQ(Direction16::SouthWest, GetDirection16({ 2, 2 }, { 2, 4 }));\r\n\tEXPECT_EQ(Direction16::West_SouthWest, GetDirection16({ 2, 2 }, { 1, 4 }));\r\n\tEXPECT_EQ(Direction16::West, GetDirection16({ 2, 2 }, { 1, 3 }));\r\n\tEXPECT_EQ(Direction16::West_NorthWest, GetDirection16({ 2, 2 }, { 0, 3 }));\r\n\tEXPECT_EQ(Direction16::NorthWest, GetDirection16({ 2, 2 }, { 0, 2 }));\r\n\tEXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 2, 2 }, { 0, 1 }));\r\n\tEXPECT_EQ(Direction16::North, GetDirection16({ 2, 2 }, { 1, 1 }));\r\n\tEXPECT_EQ(Direction16::North_NorthEast, GetDirection16({ 2, 2 }, { 1, 0 }));\r\n\tEXPECT_EQ(Direction16::NorthEast, GetDirection16({ 2, 2 }, { 2, 0 }));\r\n\tEXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 2, 2 }, { 3, 0 }));\r\n\tEXPECT_EQ(Direction16::East, GetDirection16({ 2, 2 }, { 3, 1 }));\r\n\tEXPECT_EQ(Direction16::East_SouthEast, GetDirection16({ 2, 2 }, { 4, 1 }));\r\n\tEXPECT_EQ(Direction16::SouthEast, GetDirection16({ 2, 2 }, { 4, 2 }));\r\n\tEXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 2, 2 }, { 4, 3 }));\r\n\r\n\tEXPECT_EQ(Direction16::South_SouthWest, GetDirection16({ 0, 0 }, { 0, 0 })) << \"GetDirection16 is expected to default to Direction16::South_SouthWest when the points occupy the same tile\";\r\n}\r\n"
  },
  {
    "path": "test/multi_logging_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"multi.h\"\r\n\r\nnamespace devilution {\r\n\r\nTEST(MultiplayerLogging, NormalExitReason)\r\n{\r\n\tEXPECT_EQ(\"normal exit\", DescribeLeaveReason(net::leaveinfo_t::LEAVE_EXIT));\r\n}\r\n\r\nTEST(MultiplayerLogging, DiabloEndingReason)\r\n{\r\n\tEXPECT_EQ(\"Diablo defeated\", DescribeLeaveReason(net::leaveinfo_t::LEAVE_ENDING));\r\n}\r\n\r\nTEST(MultiplayerLogging, DropReason)\r\n{\r\n\tEXPECT_EQ(\"connection timeout\", DescribeLeaveReason(net::leaveinfo_t::LEAVE_DROP));\r\n}\r\n\r\nTEST(MultiplayerLogging, CustomReasonCode)\r\n{\r\n\tconstexpr net::leaveinfo_t CustomCode = static_cast<net::leaveinfo_t>(0xDEADBEEF);\r\n\tEXPECT_EQ(\"code 0xDEADBEEF\", DescribeLeaveReason(CustomCode));\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/pack_test.cpp",
    "content": "#include <cstdint>\r\n\r\n#include <gtest/gtest.h>\r\n\r\n#include \"cursor.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"pack.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/is_of.hpp\"\r\n#include \"utils/paths.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nconstexpr const char MissingMpqAssetsSkipReason[] = \"MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test suite\";\r\n\r\nvoid SwapLE(ItemPack &pack)\r\n{\r\n\tpack.iSeed = Swap32LE(pack.iSeed);\r\n\tpack.iCreateInfo = Swap16LE(pack.iCreateInfo);\r\n\tpack.idx = Swap16LE(pack.idx);\r\n\tpack.wValue = Swap16LE(pack.wValue);\r\n\tpack.dwBuff = Swap32LE(pack.dwBuff);\r\n}\r\n\r\nvoid SwapLE(PlayerPack &pack)\r\n{\r\n\tpack.dwLowDateTime = Swap32LE(pack.dwLowDateTime);\r\n\tpack.dwHighDateTime = Swap32LE(pack.dwHighDateTime);\r\n\tpack.pExperience = Swap32LE(pack.pExperience);\r\n\tpack.pGold = Swap32LE(pack.pGold);\r\n\tpack.pHPBase = Swap32LE(pack.pHPBase);\r\n\tpack.pMaxHPBase = Swap32LE(pack.pMaxHPBase);\r\n\tpack.pManaBase = Swap32LE(pack.pManaBase);\r\n\tpack.pMaxManaBase = Swap32LE(pack.pMaxManaBase);\r\n\tpack.pMemSpells = Swap64LE(pack.pMemSpells);\r\n\tfor (ItemPack &item : pack.InvBody)\r\n\t\tSwapLE(item);\r\n\tfor (ItemPack &item : pack.InvList)\r\n\t\tSwapLE(item);\r\n\tfor (ItemPack &item : pack.SpdList)\r\n\t\tSwapLE(item);\r\n\tpack.wReflections = Swap16LE(pack.wReflections);\r\n\tpack.pDiabloKillLevel = Swap32LE(pack.pDiabloKillLevel);\r\n\tpack.pDifficulty = Swap32LE(pack.pDifficulty);\r\n\tpack.pDamAcFlags = Swap32LE(pack.pDamAcFlags);\r\n}\r\n\r\nItemPack SwappedLE(const ItemPack &pack)\r\n{\r\n\tItemPack swapped = pack;\r\n\tSwapLE(swapped);\r\n\treturn swapped;\r\n}\r\n\r\nvoid SetHellfireState(bool enable)\r\n{\r\n\tgbIsHellfire = enable;\r\n\tUnloadModArchives();\r\n\tif (enable) {\r\n\t\tLoadModArchives({ { \"Hellfire\" } });\r\n\t}\r\n\tLoadItemData();\r\n\tLoadSpellData();\r\n}\r\n\r\nvoid ComparePackedItems(const ItemPack &item1LE, const ItemPack &item2LE)\r\n{\r\n\t// Packs are little-endian.\r\n\t// Swap to native endianness on big-endian systems before comparison for better error messages.\r\n\tconst ItemPack item1 = SwappedLE(item1LE);\r\n\tconst ItemPack item2 = SwappedLE(item2LE);\r\n\r\n\t// `ItemPack` is packed, so we copy the unaligned values out before comparing them.\r\n\t// This avoids the following UBSAN error such as this one:\r\n\t// runtime error: load of misaligned address for type 'const unsigned int', which requires 4 byte alignment\r\n\t{\r\n\t\tconst auto item1_iSeed = item1.iSeed;\r\n\t\tconst auto item2_iSeed = item2.iSeed;\r\n\t\tEXPECT_EQ(item1_iSeed, item2_iSeed);\r\n\t}\r\n\t{\r\n\t\tconst auto item1_iCreateInfo = item1.iCreateInfo;\r\n\t\tconst auto item2_iCreateInfo = item2.iCreateInfo;\r\n\t\tEXPECT_EQ(item1_iCreateInfo, item2_iCreateInfo);\r\n\t}\r\n\t{\r\n\t\tconst auto item1_idx = item1.idx;\r\n\t\tconst auto item2_idx = item2.idx;\r\n\t\tEXPECT_EQ(item1_idx, item2_idx);\r\n\t}\r\n\tEXPECT_EQ(item1.bId, item2.bId);\r\n\tEXPECT_EQ(item1.bDur, item2.bDur);\r\n\tEXPECT_EQ(item1.bMDur, item2.bMDur);\r\n\tEXPECT_EQ(item1.bCh, item2.bCh);\r\n\tEXPECT_EQ(item1.bMCh, item2.bMCh);\r\n\t{\r\n\t\tconst auto item1_wValue = item1.wValue;\r\n\t\tconst auto item2_wValue = item2.wValue;\r\n\t\tEXPECT_EQ(item1_wValue, item2_wValue);\r\n\t}\r\n\t{\r\n\t\tconst auto item1_dwBuff = item1.dwBuff;\r\n\t\tconst auto item2_dwBuff = item2.dwBuff;\r\n\t\tEXPECT_EQ(item1_dwBuff, item2_dwBuff);\r\n\t}\r\n}\r\ntypedef struct TestItemStruct {\r\n\tchar _iIName[ItemNameLength];\r\n\tItemType _itype;\r\n\tint _iClass;\r\n\tint _iCurs;\r\n\tint _iIvalue;\r\n\tint _iMinDam;\r\n\tint _iMaxDam;\r\n\tint _iAC;\r\n\tItemSpecialEffect _iFlags;\r\n\tint _iMiscId;\r\n\tSpellID _iSpell;\r\n\tint _iCharges;\r\n\tint _iMaxCharges;\r\n\tint _iDurability;\r\n\tint _iMaxDur;\r\n\tint _iPLDam;\r\n\tint _iPLToHit;\r\n\tint _iPLAC;\r\n\tint _iPLStr;\r\n\tint _iPLMag;\r\n\tint _iPLDex;\r\n\tint _iPLVit;\r\n\tint _iPLFR;\r\n\tint _iPLLR;\r\n\tint _iPLMR;\r\n\tint _iPLMana;\r\n\tint _iPLHP;\r\n\tint _iPLDamMod;\r\n\tint _iPLGetHit;\r\n\tint _iPLLight;\r\n\tint8_t _iSplLvlAdd;\r\n\tint _iUid;\r\n\tint _iFMinDam;\r\n\tint _iFMaxDam;\r\n\tint _iLMinDam;\r\n\tint _iLMaxDam;\r\n\tint8_t _iPrePower;\r\n\tint8_t _iSufPower;\r\n\tint8_t _iMinStr;\r\n\tuint8_t _iMinMag;\r\n\tint8_t _iMinDex;\r\n\tint IDidx;\r\n} TestItemStruct;\r\n\r\nstatic void TestItemNameGeneration(const Item &item)\r\n{\r\n\tconst bool allowIdentified = (item._iMiscId != IMISC_EAR); // Ears can't be identified. Item::getName() doesn't handle it, so don't test it.\r\n\tASSERT_EQ(allowIdentified & item._iIdentified, item._iIdentified);\r\n\r\n\tItem testItem = item;\r\n\r\n\ttestItem._iIdentified = false;\r\n\tASSERT_STREQ(testItem.getName().str().data(), testItem._iName) << \"unidentified name\";\r\n\tif (allowIdentified) {\r\n\t\ttestItem._iIdentified = true;\r\n\t\tASSERT_STREQ(testItem.getName().str().data(), testItem._iIName) << \"identified name\";\r\n\r\n\t\t// Check that UpdateHellfireFlag ensures that dwBuff is updated to get the correct name\r\n\t\tif (item._iMagical == ITEM_QUALITY_MAGIC) {\r\n\t\t\tconst bool isHellfireItem = (testItem.dwBuff & CF_HELLFIRE);\r\n\t\t\ttestItem.dwBuff = 0;\r\n\t\t\tUpdateHellfireFlag(testItem, testItem._iIName);\r\n\r\n\t\t\ttestItem._iIdentified = true;\r\n\t\t\tASSERT_STREQ(testItem.getName().str().data(), testItem._iIName) << \"identified name with UpdateHellfireFlag\";\r\n\t\t\tASSERT_TRUE(isHellfireItem || ((item.dwBuff & CF_HELLFIRE) != CF_HELLFIRE)) << \"item was wrongly converted to hellfire\";\r\n\t\t}\r\n\t}\r\n}\r\n\r\nstatic void CompareItems(const Item &item1, const TestItemStruct &item2)\r\n{\r\n\tASSERT_STREQ(item1._iIName, item2._iIName);\r\n\tEXPECT_EQ(item1._itype, item2._itype);\r\n\tEXPECT_EQ(item1._iClass, item2._iClass);\r\n\tEXPECT_EQ(item1._iCurs, item2._iCurs);\r\n\tEXPECT_EQ(item1._iIvalue, item2._iIvalue);\r\n\tEXPECT_EQ(item1._iMinDam, item2._iMinDam);\r\n\tEXPECT_EQ(item1._iMaxDam, item2._iMaxDam);\r\n\tEXPECT_EQ(item1._iAC, item2._iAC);\r\n\tEXPECT_EQ(item1._iFlags, item2._iFlags);\r\n\tEXPECT_EQ(item1._iMiscId, item2._iMiscId);\r\n\tEXPECT_EQ(item1._iSpell, item2._iSpell);\r\n\tEXPECT_EQ(item1._iCharges, item2._iCharges);\r\n\tEXPECT_EQ(item1._iMaxCharges, item2._iMaxCharges);\r\n\tEXPECT_EQ(item1._iDurability, item2._iDurability);\r\n\tEXPECT_EQ(item1._iMaxDur, item2._iMaxDur);\r\n\tEXPECT_EQ(item1._iPLDam, item2._iPLDam);\r\n\tEXPECT_EQ(item1._iPLToHit, item2._iPLToHit);\r\n\tEXPECT_EQ(item1._iPLAC, item2._iPLAC);\r\n\tEXPECT_EQ(item1._iPLStr, item2._iPLStr);\r\n\tEXPECT_EQ(item1._iPLMag, item2._iPLMag);\r\n\tEXPECT_EQ(item1._iPLDex, item2._iPLDex);\r\n\tEXPECT_EQ(item1._iPLVit, item2._iPLVit);\r\n\tEXPECT_EQ(item1._iPLFR, item2._iPLFR);\r\n\tEXPECT_EQ(item1._iPLLR, item2._iPLLR);\r\n\tEXPECT_EQ(item1._iPLMR, item2._iPLMR);\r\n\tEXPECT_EQ(item1._iPLMana, item2._iPLMana);\r\n\tEXPECT_EQ(item1._iPLHP, item2._iPLHP);\r\n\tEXPECT_EQ(item1._iPLDamMod, item2._iPLDamMod);\r\n\tEXPECT_EQ(item1._iPLGetHit, item2._iPLGetHit);\r\n\tEXPECT_EQ(item1._iPLLight, item2._iPLLight);\r\n\tEXPECT_EQ(item1._iSplLvlAdd, item2._iSplLvlAdd);\r\n\tEXPECT_EQ(item1._iUid, item2._iUid);\r\n\tEXPECT_EQ(item1._iFMinDam, item2._iFMinDam);\r\n\tEXPECT_EQ(item1._iFMaxDam, item2._iFMaxDam);\r\n\tEXPECT_EQ(item1._iLMinDam, item2._iLMinDam);\r\n\tEXPECT_EQ(item1._iLMaxDam, item2._iLMaxDam);\r\n\tEXPECT_EQ(item1._iPrePower, item2._iPrePower);\r\n\tEXPECT_EQ(item1._iSufPower, item2._iSufPower);\r\n\tEXPECT_EQ(item1._iMinStr, item2._iMinStr);\r\n\tEXPECT_EQ(item1._iMinMag, item2._iMinMag);\r\n\tEXPECT_EQ(item1._iMinDex, item2._iMinDex);\r\n\tEXPECT_EQ(item1.IDidx, item2.IDidx);\r\n}\r\n\r\nconst ItemPack PackedDiabloItems[] = {\r\n\t// clang-format off\r\n\t//     iSeed,                              iCreateInfo,  idx,  bId,  bDur,  bMDur,  bCh,  bMCh,  wValue,  dwBuff\r\n\t{ 2082213289, 25 | CF_UPER1                           ,   53,    3,    60,     60,    0,     0,       0,       0 }, // Amber Helm of harmony\r\n\t{  338833725, 24 | CF_UPER1                           ,  154,    3,     0,      0,    0,     0,       0,       0 }, // Cobalt Amulet of giants\r\n\t{  545145866, 26 | CF_UPER1                           ,  120,    3,    38,     40,    0,     0,       0,       0 }, // Brutal Sword of gore\r\n\t{ 1504248345, 26 | CF_UPER1  | CF_ONLYGOOD | CF_UNIQUE,   70,    5,   255,    255,    0,     0,       0,       0 }, // Demonspike Coat\r\n\t{ 1884424756,  6 | CF_UPER1  | CF_ONLYGOOD            ,  151,    3,     0,      0,    0,     0,       0,       0 }, // Steel Ring of the jaguar\r\n\t{ 1712759905, 28 | CF_UPER15 | CF_ONLYGOOD            ,  151,    3,     0,      0,    0,     0,       0,       0 }, // Ring of the heavens\r\n\t{  981777658, 30 | CF_UPER1                           ,  153,    2,     0,      0,    0,     0,       0,       0 }, // Ring of sorcery\r\n\t{  844854815, 26 | CF_UPER1                           ,   75,    3,   255,    255,    0,     0,       0,       0 }, // Tower Shield of the ages\r\n\t{ 1151513535, 30 | CF_UPER1                           ,   73,    2,    12,     32,    0,     0,       0,       0 }, // Sapphire Large Shield\r\n\t{  640243885,  6                                      ,   27,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Town Portal\r\n\t{  741806938,  9                                      ,   25,    0,     0,      0,    0,     0,       0,       0 }, // IDI_MANA\r\n\t{ 1456608333,  1 | CF_UPER1                           ,   79,    0,     0,      0,    0,     0,       0,       0 }, // Mana\r\n\t{  554676945, 16                                      ,   30,    0,     0,      0,    0,     0,       0,       0 }, // Full mana\r\n\t{  355389938,  0                                      ,   24,    0,     0,      0,    0,     0,       0,       0 }, // Healing\r\n\t{  868435486, 16                                      ,   29,    0,     0,      0,    0,     0,       0,       0 }, // Full healing\r\n\t{ 1372832903,  0                                      ,    4,    0,    30,     30,    0,     0,       0,       0 }, // IDI_ROGUE\r\n\t{  896239556, 20             | CF_SMITHPREMIUM        ,   53,    3,    56,     60,    0,     0,       0,       0 }, // Jade Helm of the wolf\r\n\t{ 1286225254, 13 | CF_UPER1                           ,  151,    3,     0,      0,    0,     0,       0,       0 }, // Steel Ring of accuracy\r\n\t{  548642293, 10 | CF_UPER1                           ,   21,    0,     0,      0,    0,     0,       0,       0 }, // Blood Stone\r\n\t{  307669016, 14 | CF_UPER1                           ,  151,    3,     0,      0,    0,     0,       0,       0 }, // Ring of power\r\n\t{  204766888, 12 | CF_UPER1  | CF_ONLYGOOD            ,  154,    3,     0,      0,    0,     0,       0,       0 }, // Gold Amulet of accuracy\r\n\t{ 1642744332, 17 | CF_UPER1                           ,  122,    3,    25,     60,    0,     0,       0,       0 }, // Bastard Sword of the bat\r\n\t{ 1031508271, 12             | CF_SMITH               ,   72,    0,    14,     24,    0,     0,       0,       0 }, // Small Shield\r\n\t{ 1384620228, 18 | CF_UPER1  | CF_ONLYGOOD            ,   65,    3,    44,     80,    0,     0,       0,       0 }, // Breast Plate of giants\r\n\t{  681296530, 10 | CF_UPER1                           ,   87,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Healing\r\n\t{  109984285,  6             | CF_HEALER              ,   81,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Rejuvenation - made by Pepin\r\n\t{ 1857753366,  4 | CF_UPER1                           ,   81,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Rejuvenation\r\n\t{  965103261, 17 | CF_UPER1                           ,   82,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Full Rejuvenation\r\n\t{  430621075, 25 | CF_UPER15 | CF_ONLYGOOD            ,  141,    3,    45,     45,    0,     0,       0,       0 }, // Savage Bow of perfection\r\n\t{ 1272669062,  2 | CF_UPER1                           ,  115,    0,    10,     20,    0,     0,       0,       0 }, // Falchion\r\n\t{ 1133884051, 22 | CF_UPER1                           ,  120,    2,    18,     40,    0,     0,       0,       0 }, // Long Sword of vim\r\n\t{ 1743897351,  3 | CF_UPER1                           ,  146,    2,    10,     25,   60,    60,       0,       0 }, // Frog's Staff of Holy Bolt\r\n\t{  429107209,  0                                      ,    5,    0,    25,     25,    9,    40,       0,       0 }, // IDI_SORCERER\r\n\t{  466015738,  1 | CF_UPER1                           ,  146,    0,    18,     25,   50,    50,       0,       0 }, // Staff of Charged Bolt\r\n\t{  686949358,  1 | CF_UPER15 | CF_ONLYGOOD            ,   48,    3,    12,     15,    0,     0,       0,       0 }, // Cap of the mind armor\r\n\t{  888855755,  3 | CF_UPER15 | CF_ONLYGOOD            ,   58,    3,    30,     30,    0,     0,       0,       0 }, // Armor of protection\r\n\t{          2,  8 | CF_UPER1                | CF_UNIQUE,    8,    5,     0,      0,    0,     0,       0,       0 }, // Empyrean Band,\r\n\t{          3,  8 | CF_UPER1                | CF_UNIQUE,   10,    5,     0,      0,    0,     0,       0,       0 }, // Optic Amulet\r\n\t{          4,  4 | CF_UPER1                | CF_UNIQUE,   11,    5,     0,      0,    0,     0,       0,       0 }, // Ring of Truth\r\n\t{          5,  8 | CF_UPER1                | CF_UNIQUE,   13,    5,    15,     15,    0,     0,       0,       0 }, // Harlequin Crest\r\n\t{          6, 15                           | CF_UNIQUE,   14,    5,    60,     60,    0,     0,       0,       0 }, // Veil of Steel\r\n\t{          7, 13 | CF_UPER1                | CF_UNIQUE,   28,    5,    39,     40,    0,     0,       0,       0 }, // Arkaine's Valor\r\n\t{          8, 19 | CF_UPER1                | CF_UNIQUE,   31,    5,    42,     44,    0,     0,       0,       0 }, // Griswold's Edge\r\n\t{  557339094, 16             | CF_WITCH               ,  150,    3,    75,     75,    0,     0,       0,       0 }, // War Staff of haste\r\n\t{ 1684844665, 16             | CF_WITCH               ,  150,    3,    75,     75,   56,    56,       0,       0 }, // White Staff of Lightning\r\n\t{ 1297052552, 26             | CF_SMITHPREMIUM        ,  137,    3,    50,     50,    0,     0,       0,       0 }, // Lightning Maul\r\n\t{  981895960, 25             | CF_SMITHPREMIUM        ,  130,    3,    75,     75,    0,     0,       0,       0 }, // Ivory Great Axe of blood\r\n\t{  935416728, 22             | CF_SMITHPREMIUM        ,   52,    3,    18,     40,    0,     0,       0,       0 }, // Jade Crown of vim\r\n\t{ 1140525626,  1 | CF_UPER1                           ,  138,    3,    16,     30,    0,     0,       0,       0 }, // Short Bow of atrophy\r\n\t{ 1187758333,  2 | CF_UPER1                           ,  113,    3,    11,     16,    0,     0,       0,       0 }, // Brass Dagger of weakness\r\n\t{ 1283803700, 11 | CF_UPER1                           ,  138,    3,    16,     30,    0,     0,       0,       0 }, // Clumsy Short Bow\r\n\t{ 1317748726,  5 | CF_UPER1                           ,  114,    3,    17,     24,    0,     0,       0,       0 }, // Tin Sword of the fool\r\n\t{ 1331764286,  5 | CF_UPER1                           ,  135,    3,     6,     20,    0,     0,       0,       0 }, // Club of paralysis\r\n\t{ 1375639122, 13 | CF_UPER1                           ,  146,    3,    18,     25,   46,    46,       0,       0 }, // Dull Staff of Lightning\r\n\t{  145523894, 21 | CF_UPER1                           ,  115,    3,     6,     20,    0,     0,       0,       0 }, // Falchion of speed\r\n\t{ 1527777846,  3 | CF_UPER1                           ,  115,    3,    14,     20,    0,     0,       0,       0 }, // Bent Falchion\r\n\t{ 1655088363, 32 | CF_UPER1                           ,  146,    3,    13,     25,   98,    98,       0,       0 }, // Plentiful Staff of Firebolt\r\n\t{ 1679472538,  7 | CF_UPER1                           ,  113,    3,     6,     16,    0,     0,       0,       0 }, // Dagger of illness\r\n\t{ 1812092773,  8 | CF_UPER1                           ,   54,    3,     4,     12,    0,     0,       0,       0 }, // Cape of corruption\r\n\t{ 1965885799, 22 | CF_UPER1                           ,  119,    3,    33,     45,    0,     0,       0,       0 }, // Sabre of trouble\r\n\t{ 1970135469,  2 | CF_UPER1                           ,   48,    3,     5,     15,    0,     0,       0,       0 }, // Cap of tears\r\n\t{ 1979635474,  5 | CF_UPER1                           ,  135,    3,    14,     20,    0,     0,       0,       0 }, // Tin Club\r\n\t{ 2008721689,  2 | CF_UPER1                           ,   54,    3,     9,     12,    0,     0,       0,       0 }, // Rusted Cape of dyslexia\r\n\t{ 2082373839,  6 | CF_UPER1                           ,   48,    3,    10,     15,    0,     0,       0,       0 }, // Cap of pain\r\n\t{  278391972,  7 | CF_UPER1                           ,  119,    3,     1,      1,    0,     0,       0,       0 }, // Clumsy Sabre of fragility\r\n\t{  283130709,  4 | CF_UPER1                           ,   48,    3,     5,     15,    0,     0,       0,       0 }, // Vulnerable Cap of health\r\n\t{  308974695,  8 | CF_UPER1                           ,  113,    3,     5,     16,    0,     0,       0,       0 }, // Useless Dagger\r\n\t{  588501657, 44 | CF_UPER1                           ,  146,    3,    17,     25,   36,    36,       0,       0 }, // Bountiful Staff of Fire Wall\r\n\t{  640482348,  3 | CF_UPER1                           ,  131,    3,    22,     32,    0,     0,       0,       0 }, // Mace of frailty\r\n\t{  715324531,  2 | CF_UPER1                           ,  138,    3,    20,     30,    0,     0,       0,       0 }, // Weak Short Bow\r\n\t{  794222370,  3 | CF_UPER1                           ,  146,    3,    12,     25,    0,     0,       0,       0 }, // Short Staff of readiness\r\n\t{   49304273,  6                                      ,   24,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Healing\r\n\t{ 1015622844,  6                                      ,   29,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Full Healing\r\n\t{  376595272,  6                                      ,   25,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Mana\r\n\t{ 1354859033,  6                                      ,   30,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Full Mana\r\n\t{ 2088923858,  6                                      ,   27,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Town Portal\r\n\t{  998169832,  1 | CF_UPER1                | CF_UNIQUE,  138,    5,    30,     30,    0,     0,       0,       0 }, // The Rift Bow\r\n\t{  583181782, 30 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  124,    5,   100,    100,    0,     0,       0,       0 }, // The Grandfather\r\n\t{ 1488997713,  1 | CF_UPER1                           ,   76,    3,    17,     60,    0,     0,       0,       0 }, // Gothic Shield of thorns\r\n\t{ 2140415407, 19 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,   67,    5,    75,     75,    0,     0,       0,       0 }, // Naj's Light Plate\r\n\t{  601465140,  9 | CF_UPER1                | CF_UNIQUE,  151,    5,     0,      0,    0,     0,       0,       0 }, // Constricting Ring\r\n\t{ 1154984294, 24 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,   53,    5,    60,     60,    0,     0,       0,       0 }, // Gotterdamerung\r\n\t{  951404319, 28 | CF_UPER15 | CF_ONLYGOOD            ,  122,    3,    32,     60,    0,     0,       0,       0 }, // King's Bastard Sword\r\n\t{ 1452181783, 38             | CF_BOY                 ,  135,    3,    60,     60,    0,     0,       0,       0 }, // Champion's Club of gore\r\n\t{  846169922, 29             | CF_SMITHPREMIUM        ,  136,    3,    60,     60,    0,     0,       0,       0 }, // Master's Flail\r\n\t{   18974604, 30             | CF_SMITHPREMIUM        ,  121,    3,    60,     60,    0,     0,       0,       0 }, // Knight's Broad Sword\r\n\t{ 1535190647, 28 | CF_UPER1                           ,  115,    3,    13,     20,    0,     0,       0,       0 }, // Lord's Falchion of precision\r\n\t{  300540323, 30 | CF_UPER1                           ,  122,    3,    60,     60,    0,     0,       0,       0 }, // Soldier's Sword of vigor\r\n\t{ 1813930929, 10 | CF_UPER1                           ,  140,    3,    35,     35,    0,     0,       0,       0 }, // Fine Long Bow of the pit\r\n\t{  733908617,  1 | CF_UPER1                           ,  120,    3,    24,     40,    0,     0,       0,       0 }, // Sharp Sword of atrophy\r\n\t{ 1158010141, 63 | CF_UPER1                           ,  145,    3,    60,     60,    0,     0,       0,       0 }, // Emerald Bow of burning\r\n\t// clang-format on\r\n};\r\n\r\nconstexpr ItemSpecialEffect EmpyreanBandSpecialEffect = ItemSpecialEffect::FastHitRecovery | ItemSpecialEffect::HalfTrapDamage;\r\nconstexpr ItemSpecialEffect GrisworldEdgeSpecialEffect = ItemSpecialEffect::FireDamage | ItemSpecialEffect::Knockback | ItemSpecialEffect::FastAttack;\r\nconstexpr ItemSpecialEffect FireArrows = ItemSpecialEffect::FireArrows | ItemSpecialEffect::FireDamage;\r\n\r\nconst TestItemStruct DiabloItems[] = {\r\n\t// clang-format off\r\n\t// _iIName,                       _itype,                 _iClass,  _iCurs,  _iIvalue,  _iMinDam,  _iMaxDam,  _iAC, _iFlags,                                 _iMiscId, _iSpell,               _iCharges,  _iMaxCharges,  _iDurability,  _iMaxDur,  _iPLDam,  _iPLToHit,  _iPLAC,  _iPLStr,  _iPLMag,  _iPLDex,  _iPLVit,  _iPLFR,  _iPLLR,  _iPLMR,  _iPLMana,  _iPLHP,  _iPLDamMod,  _iPLGetHit,  _iPLLight,  _iSplLvlAdd,  _iUid,  _iFMinDam,  _iFMaxDam,  _iLMinDam,  _iLMaxDam,  _iPrePower,  _iSufPower,  _iMinStr,  _iMinMag,  _iMinDex,  IDidx\r\n\t{ \"Amber Helm of harmony\",        ItemType::Helm,               2,      98,     21100,         0,         0,    11, ItemSpecialEffect::FastestHitRecovery,          0, SpellID::Null,                 0,             0,            60,        60,        0,          0,       0,        0,        0,        0,        0,      18,      18,      18,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          11,          59,        50,         0,         0,     53 },\r\n\t{ \"Cobalt Amulet of giants\",      ItemType::Amulet,             3,      45,     26840,         0,         0,     0, ItemSpecialEffect::None,                       26, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,       19,        0,        0,        0,       0,      46,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           9,          19,         0,         0,         0,    159 },\r\n\t{ \"Brutal Long Sword of gore\",    ItemType::Sword,              1,      60,     13119,         2,        10,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            38,        40,       91,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,          12,           0,          0,            0,      0,          0,          0,          0,          0,           2,          61,        30,         0,        30,    125 },\r\n\t{ \"Demonspike Coat\",              ItemType::HeavyArmor,         2,     151,    251175,         0,         0,   100, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,       10,        0,        0,        0,      50,       0,       0,         0,       0,           0,          -6,          0,            0,     78,          0,          0,          0,          0,          -1,          -1,        90,         0,         0,     70 },\r\n\t{ \"Steel Ring of the jaguar\",     ItemType::Ring,               3,      12,     10600,         0,         0,     0, ItemSpecialEffect::None,                       25, SpellID::Null,                 0,             0,             0,         0,        0,         15,       0,        0,        0,        0,        0,       0,       0,       0,         0,    1024,           0,           0,          0,            0,      0,          0,          0,          0,          0,           0,          31,         0,         0,         0,    156 },\r\n\t{ \"Ring of the heavens\",          ItemType::Ring,               3,      12,     37552,         0,         0,     0, ItemSpecialEffect::None,                       25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,       14,       14,       14,       14,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          27,         0,         0,         0,    156 },\r\n\t{ \"Ring of sorcery\",              ItemType::Ring,               3,      12,     10200,         0,         0,     0, ItemSpecialEffect::None,                       25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,       16,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          21,         0,         0,         0,    158 },\r\n\t{ \"Tower Shield of the ages\",     ItemType::Shield,             2,     132,      4850,         0,         0,    18, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          37,        60,         0,         0,     75 },\r\n\t{ \"Sapphire Large Shield\",        ItemType::Shield,             2,     147,     21000,         0,         0,     7, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            12,        32,        0,          0,       0,        0,        0,        0,        0,       0,      60,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           9,          -1,        40,         0,         0,     73 },\r\n\t{ \"Scroll of Town Portal\",        ItemType::Misc,               3,       1,       200,         0,         0,     0, ItemSpecialEffect::None,                       21, SpellID::TownPortal,           0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     27 },\r\n\t{ \"Potion of Mana\",               ItemType::Misc,               3,      39,        50,         0,         0,     0, ItemSpecialEffect::None,                        6, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     25 },\r\n\t{ \"Potion of Mana\",               ItemType::Misc,               3,      39,        50,         0,         0,     0, ItemSpecialEffect::None,                        6, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     79 },\r\n\t{ \"Potion of Full Mana\",          ItemType::Misc,               3,       0,       150,         0,         0,     0, ItemSpecialEffect::None,                        7, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     30 },\r\n\t{ \"Potion of Healing\",            ItemType::Misc,               3,      32,        50,         0,         0,     0, ItemSpecialEffect::None,                        3, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     24 },\r\n\t{ \"Potion of Full Healing\",       ItemType::Misc,               3,      35,       150,         0,         0,     0, ItemSpecialEffect::None,                        2, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     29 },\r\n\t{ \"Short Bow\",                    ItemType::Bow,                1,     118,       100,         1,         4,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            30,        30,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,      4 },\r\n\t{ \"Jade Great Helm of the wolf\",  ItemType::Helm,               2,      98,     22310,         0,         0,    14, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            56,        60,        0,          0,       0,        0,        0,        0,        0,      27,      27,      27,         0,    2112,           0,           0,          0,            0,      0,          0,          0,          0,          0,          11,          31,        50,         0,         0,     53 },\r\n\t{ \"Steel Ring of accuracy\",       ItemType::Ring,               3,      12,     13400,         0,         0,     0, ItemSpecialEffect::None,                       25, SpellID::Null,                 0,             0,             0,         0,        0,         14,       0,        0,        0,       15,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           0,          23,         0,         0,         0,    156 },\r\n\t{ \"Blood Stone\",                  ItemType::Misc,               5,      25,         0,         0,         0,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     21 },\r\n\t{ \"Ring of power\",                ItemType::Ring,               3,      12,      6400,         0,         0,     0, ItemSpecialEffect::None,                       25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,       12,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          19,         0,         0,         0,    156 },\r\n\t{ \"Gold Amulet of accuracy\",      ItemType::Amulet,             3,      45,     20896,         0,         0,     0, ItemSpecialEffect::None,                       26, SpellID::Null,                 0,             0,             0,         0,        0,         25,       0,        0,        0,       14,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           0,          23,         0,         0,         0,    159 },\r\n\t{ \"Bastard Sword of the bat\",     ItemType::Sword,              1,      57,     10500,         6,        15,     0, ItemSpecialEffect::StealMana3,                  0, SpellID::Null,                 0,             0,            25,        60,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          55,        50,         0,         0,    127 },\r\n\t{ \"Small Shield\",                 ItemType::Shield,             2,     105,        90,         0,         0,     3, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            14,        24,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,        25,         0,         0,     72 },\r\n\t{ \"Breast Plate of giants\",       ItemType::HeavyArmor,         2,     153,     23250,         0,         0,    20, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            44,        80,        0,          0,       0,       17,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          19,        40,         0,         0,     65 },\r\n\t{ \"Scroll of Healing\",            ItemType::Misc,               3,       1,        50,         0,         0,     0, ItemSpecialEffect::None,                       21, SpellID::Healing,              0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     91 },\r\n\t{ \"Potion of Rejuvenation\",       ItemType::Misc,               3,      37,       120,         0,         0,     0, ItemSpecialEffect::None,                       18, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     81 },\r\n\t{ \"Potion of Rejuvenation\",       ItemType::Misc,               3,      37,       120,         0,         0,     0, ItemSpecialEffect::None,                       18, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     81 },\r\n\t{ \"Potion of Full Rejuvenation\",  ItemType::Misc,               3,      33,       600,         0,         0,     0, ItemSpecialEffect::None,                       19, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     82 },\r\n\t{ \"Savage Bow of perfection\",     ItemType::Bow,                1,     133,     23438,         3,         6,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            45,        45,      117,          0,       0,        0,        0,       22,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           2,          23,        25,         0,        40,    146 },\r\n\t{ \"Falchion\",                     ItemType::Sword,              1,      62,       250,         4,         8,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            10,        20,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,        30,         0,         0,    120 },\r\n\t{ \"Long Sword of vim\",            ItemType::Sword,              1,      60,      4400,         2,        10,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            18,        40,        0,          0,       0,        0,        0,        0,       15,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          25,        30,         0,        30,    125 },\r\n\t{ \"Frog's Staff of Holy Bolt\",    ItemType::Staff,              1,     109,         1,         2,         4,     0, ItemSpecialEffect::None,                       23, SpellID::HolyBolt,            60,            60,            10,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,      -384,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          34,          -1,         0,        20,         0,    151 },\r\n\t{ \"Short Staff of Charged Bolt\",  ItemType::Staff,              1,     109,       470,         2,         4,     0, ItemSpecialEffect::None,                       23, SpellID::ChargedBolt,          9,            40,            25,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        25,         0,    166 },\r\n\t{ \"Short Staff of Charged Bolt\",  ItemType::Staff,              1,     109,         1,         2,         4,     0, ItemSpecialEffect::None,                       23, SpellID::ChargedBolt,         50,            50,            18,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        25,         0,    151 },\r\n\t{ \"Cap of the mind\",              ItemType::Helm,               2,      91,      1845,         0,         0,     2, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            12,        15,        0,          0,       0,        0,        9,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          21,         0,         0,         0,     48 },\r\n\t{ \"Quilted Armor of protection\",  ItemType::LightArmor,         2,     129,      1200,         0,         0,     7, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            30,        30,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,          -2,          0,            0,      0,          0,          0,          0,          0,          -1,          30,         0,         0,         0,     58 },\r\n\t{ \"Empyrean Band\",                ItemType::Ring,               3,      18,      8000,         0,         0,     0, EmpyreanBandSpecialEffect,                     27, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        2,        2,        2,        2,       0,       0,       0,         0,       0,           0,           0,          2,            0,      2,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,      8 },\r\n\t{ \"Optic Amulet\",                 ItemType::Amulet,             3,      44,      9750,         0,         0,     0, ItemSpecialEffect::None,                       27, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        5,        0,        0,       0,      20,       0,         0,       0,           0,          -1,          2,            0,      3,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     10 },\r\n\t{ \"Ring of Truth\",                ItemType::Ring,               3,      10,      9100,         0,         0,     0, ItemSpecialEffect::None,                       27, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,      10,      10,      10,         0,     640,           0,          -1,          0,            0,      4,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     11 },\r\n\t{ \"Harlequin Crest\",              ItemType::Helm,               2,      81,      4000,         0,         0,    -3, ItemSpecialEffect::None,                       27, SpellID::Null,                 0,             0,            15,        15,        0,          0,       0,        2,        2,        2,        2,       0,       0,       0,       448,     448,           0,          -1,          0,            0,      5,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     13 },\r\n\t{ \"Veil of Steel\",                ItemType::Helm,               2,      85,     63800,         0,         0,    18, ItemSpecialEffect::None,                       27, SpellID::Null,                 0,             0,            60,        60,        0,          0,      60,       15,        0,        0,       15,      50,      50,      50,     -1920,       0,           0,           0,         -2,            0,      6,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     14 },\r\n\t{ \"Arkaine's Valor\",              ItemType::MediumArmor,        2,     157,     42000,         0,         0,    25, ItemSpecialEffect::FastestHitRecovery,         27, SpellID::Null,                 0,             0,            39,        40,        0,          0,       0,        0,        0,        0,       10,       0,       0,       0,         0,       0,           0,          -3,          0,            0,      7,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     28 },\r\n\t{ \"Griswold's Edge\",              ItemType::Sword,              1,      61,     42000,         4,        12,     0, GrisworldEdgeSpecialEffect,                    27, SpellID::Null,                 0,             0,            42,        44,        0,         25,       0,        0,        0,        0,        0,       0,       0,       0,      1280,   -1280,           0,           0,          0,            0,      8,          1,         10,          0,          0,          -1,          -1,        40,         0,         0,     31 },\r\n\t{ \"War Staff of haste\",           ItemType::Staff,              1,     124,     40000,         8,        16,     0, ItemSpecialEffect::FastestAttack,              23, SpellID::Null,                 0,             0,            75,        75,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          58,        30,         0,         0,    155 },\r\n\t{ \"White Staff of Lightning\",     ItemType::Staff,              1,     124,      7160,         8,        16,     0, ItemSpecialEffect::None,                       23, SpellID::Lightning,           56,            56,            75,        75,        0,          0,       0,        0,        0,        0,        0,       0,       0,      13,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          10,          -1,        30,        20,         0,    155 },\r\n\t{ \"Lightning Maul\",               ItemType::Mace,               1,     122,     11800,         6,        20,     0, ItemSpecialEffect::LightningDamage,             0, SpellID::Null,                 0,             0,            50,        50,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          2,         20,          17,          -1,        55,         0,         0,    142 },\r\n\t{ \"Ivory Great Axe of blood\",     ItemType::Axe,                1,     143,     31194,        12,        30,     0, ItemSpecialEffect::StealLife5,                  0, SpellID::Null,                 0,             0,            75,        75,        0,          0,       0,        0,        0,        0,        0,       0,       0,      37,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          10,          56,        80,         0,         0,    135 },\r\n\t{ \"Jade Crown of vim\",            ItemType::Helm,               2,      95,     19200,         0,         0,    10, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            18,        40,        0,          0,       0,        0,        0,        0,       14,      30,      30,      30,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          11,          25,         0,         0,         0,     52 },\r\n\t{ \"Short Bow of atrophy\",         ItemType::Bow,                1,     118,         1,         1,         4,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            16,        30,        0,          0,       0,        0,        0,       -5,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          24,         0,         0,         0,    143 },\r\n\t{ \"Brass Dagger of weakness\",     ItemType::Sword,              1,      51,         1,         1,         4,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            11,        16,        0,         -1,       0,       -5,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           1,          20,         0,         0,         0,    118 },\r\n\t{ \"Clumsy Short Bow\",             ItemType::Bow,                1,     118,         1,         1,         4,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            16,        30,      -67,         -8,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           5,          -1,         0,         0,         0,    143 },\r\n\t{ \"Tin Short Sword of the fool\",  ItemType::Sword,              1,      64,         1,         2,         6,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            17,        24,        0,         -7,       0,        0,       -9,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           1,          22,        18,         0,         0,    119 },\r\n\t{ \"Club of paralysis\",            ItemType::Mace,               1,      66,         1,         1,         6,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             6,        20,        0,          0,       0,        0,        0,       -9,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          24,         0,         0,         0,    140 },\r\n\t{ \"Dull Staff of Lightning\",      ItemType::Staff,              1,     109,         1,         2,         4,     0, ItemSpecialEffect::None,                       23, SpellID::Lightning,           46,            46,            18,        25,      -28,         -1,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           5,          -1,         0,        20,         0,    151 },\r\n\t{ \"Falchion of speed\",            ItemType::Sword,              1,      62,     10000,         4,         8,     0, ItemSpecialEffect::FasterAttack,                0, SpellID::Null,                 0,             0,             6,        20,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          58,        30,         0,         0,    120 },\r\n\t{ \"Bent Falchion\",                ItemType::Sword,              1,      62,         1,         4,         8,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            14,        20,      -68,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           3,          -1,        30,         0,         0,    120 },\r\n\t{ \"Plentiful Staff of Firebolt\",  ItemType::Staff,              1,     109,      3040,         2,         4,     0, ItemSpecialEffect::None,                       23, SpellID::Firebolt,            98,            98,            13,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          15,          -1,         0,        15,         0,    151 },\r\n\t{ \"Dagger of illness\",            ItemType::Sword,              1,      51,         1,         1,         4,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             6,        16,        0,          0,       0,        0,        0,        0,       -8,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          26,         0,         0,         0,    118 },\r\n\t{ \"Cape of corruption\",           ItemType::LightArmor,         2,     150,         1,         0,         0,     3, ItemSpecialEffect::NoMana,                      0, SpellID::Null,                 0,             0,             4,        12,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          46,         0,         0,         0,     54 },\r\n\t{ \"Sabre of trouble\",             ItemType::Sword,              1,      67,         1,         1,         8,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            33,        45,        0,          0,       0,       -6,       -6,       -6,       -6,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          28,        17,         0,         0,    124 },\r\n\t{ \"Cap of tears\",                 ItemType::Helm,               2,      91,         1,         0,         0,     2, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             5,        15,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           1,          0,            0,      0,          0,          0,          0,          0,          -1,          29,         0,         0,         0,     48 },\r\n\t{ \"Tin Club\",                     ItemType::Mace,               1,      66,         1,         1,         6,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            14,        20,        0,         -8,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           1,          -1,         0,         0,         0,    140 },\r\n\t{ \"Rusted Cape of dyslexia\",      ItemType::LightArmor,         2,     150,         1,         0,         0,     2, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             9,        12,        0,          0,     -34,        0,       -4,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           7,          22,         0,         0,         0,     54 },\r\n\t{ \"Cap of pain\",                  ItemType::Helm,               2,      91,         1,         0,         0,     2, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            10,        15,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           2,          0,            0,      0,          0,          0,          0,          0,          -1,          29,         0,         0,         0,     48 },\r\n\t{ \"Clumsy Sabre of fragility\",    ItemType::Sword,              1,      67,         1,         1,         8,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             1,         1,      -75,        -10,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           5,          36,        17,         0,         0,    124 },\r\n\t{ \"Vulnerable Cap of health\",     ItemType::Helm,               2,      91,       185,         0,         0,     1, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             5,        15,        0,          0,     -63,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,          -1,          0,            0,      0,          0,          0,          0,          0,           7,          30,         0,         0,         0,     48 },\r\n\t{ \"Useless Dagger\",               ItemType::Sword,              1,      51,         1,         1,         4,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,             5,        16,     -100,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           3,          -1,         0,         0,         0,    118 },\r\n\t{ \"Bountiful Staff of Fire Wall\", ItemType::Staff,              1,     109,      5970,         2,         4,     0, ItemSpecialEffect::None,                       23, SpellID::FireWall,            36,            36,            17,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          15,          -1,         0,        27,         0,    151 },\r\n\t{ \"Mace of frailty\",              ItemType::Mace,               1,      59,         1,         1,         8,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            22,        32,        0,          0,       0,       -7,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          20,        16,         0,         0,    136 },\r\n\t{ \"Weak Short Bow\",               ItemType::Bow,                1,     118,         1,         1,         4,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            20,        30,      -44,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           3,          -1,         0,         0,         0,    143 },\r\n\t{ \"Short Staff of readiness\",     ItemType::Staff,              1,     109,      2060,         2,         4,     0, ItemSpecialEffect::QuickAttack,                23, SpellID::Null,                 0,             0,            12,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          58,         0,         0,         0,    151 },\r\n\t{ \"Potion of Healing\",            ItemType::Misc,               3,      32,        50,         0,         0,     0, ItemSpecialEffect::None,                        3, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     24 },\r\n\t{ \"Potion of Full Healing\",       ItemType::Misc,               3,      35,       150,         0,         0,     0, ItemSpecialEffect::None,                        2, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     29 },\r\n\t{ \"Potion of Mana\",               ItemType::Misc,               3,      39,        50,         0,         0,     0, ItemSpecialEffect::None,                        6, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     25 },\r\n\t{ \"Potion of Full Mana\",          ItemType::Misc,               3,       0,       150,         0,         0,     0, ItemSpecialEffect::None,                        7, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     30 },\r\n\t{ \"Scroll of Town Portal\",        ItemType::Misc,               3,       1,       200,         0,         0,     0, ItemSpecialEffect::None,                       21, SpellID::TownPortal,           0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     27 },\r\n\t{ \"The Rift Bow\",                 ItemType::Bow,                1,     118,      1800,         1,         4,     0, ItemSpecialEffect::RandomArrowVelocity,         0, SpellID::Null,                 0,             0,            30,        30,        0,          0,       0,        0,        0,       -3,        0,       0,       0,       0,         0,       0,           2,           0,          0,            0,     10,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    143 },\r\n\t{ \"The Grandfather\",              ItemType::Sword,              1,     161,    119800,        10,        20,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,           100,       100,       70,         20,       0,        5,        5,        5,        5,       0,       0,       0,         0,    1280,           0,           0,          0,            0,     35,          0,          0,          0,          0,          -1,          -1,        75,         0,         0,    129 },\r\n\t{ \"Gothic Shield of thorns\",      ItemType::Shield,             2,     148,      5100,         0,         0,    18, ItemSpecialEffect::Thorns,                      0, SpellID::Null,                 0,             0,            17,        60,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          45,        80,         0,         0,     76 },\r\n\t{ \"Naj's Light Plate\",            ItemType::HeavyArmor,         2,     159,     78700,         0,         0,    50, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            75,        75,        0,          0,       0,        0,        5,        0,        0,      20,      20,      20,      1280,       0,           0,           0,          0,            1,     77,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     67 },\r\n\t{ \"Constricting Ring\",            ItemType::Ring,               3,      14,     62000,         0,         0,     0, ItemSpecialEffect::DrainLife,                  25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,      75,      75,      75,         0,       0,           0,           0,          0,            0,     88,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    156 },\r\n\t{ \"Gotterdamerung\",               ItemType::Helm,               2,      85,     54900,         0,         0,    60, ItemSpecialEffect::ZeroResistance,              0, SpellID::Null,                 0,             0,            60,        60,        0,          0,       0,       20,       20,       20,       20,       0,       0,       0,         0,       0,           0,          -4,         -4,            0,     67,          0,          0,          0,          0,          -1,          -1,        50,         0,         0,     53 },\r\n\t{ \"King's Bastard Sword\",         ItemType::Sword,              1,      57,     69730,         6,        15,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            32,        60,      168,         95,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          -1,        50,         0,         0,    127 },\r\n\t{ \"Champion's Club of gore\",      ItemType::Mace,               1,      66,     25576,         1,         6,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            60,        60,      141,         75,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           9,           0,          0,            0,      0,          0,          0,          0,          0,           4,          61,         0,         0,         0,    140 },\r\n\t{ \"Master's Flail\",               ItemType::Mace,               1,     131,     27340,         2,        12,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            60,        60,      123,         44,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          -1,        30,         0,         0,    141 },\r\n\t{ \"Knight's Broad Sword\",         ItemType::Sword,              1,      61,     27597,         4,        12,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            60,        60,      108,         37,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          -1,        40,         0,         0,    126 },\r\n\t{ \"Lord's Falchion of precision\", ItemType::Sword,              1,      62,     17025,         4,         8,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            13,        20,       88,         23,       0,        0,        0,       20,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          23,        30,         0,         0,    120 },\r\n\t{ \"Soldier's Sword of vigor\",     ItemType::Sword,              1,      57,     31600,         6,        15,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            60,        60,       66,         19,       0,        0,        0,        0,       20,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          25,        50,         0,         0,    127 },\r\n\t{ \"Fine Long Bow of the pit\",     ItemType::Bow,                1,     102,      2152,         1,         6,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            35,        35,       49,         10,       0,       -2,       -2,       -2,       -2,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          28,        25,         0,        30,    145 },\r\n\t{ \"Sharp Sword of atrophy\",       ItemType::Sword,              1,      60,      1958,         2,        10,     0, ItemSpecialEffect::None,                        0, SpellID::Null,                 0,             0,            24,        40,       34,          4,       0,        0,        0,       -1,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          24,        30,         0,        30,    125 },\r\n\t{ \"Emerald Bow of burning\",       ItemType::Bow,                1,     120,    107000,         1,        14,     0, FireArrows,                                     0, SpellID::Null,                 0,             0,            60,        60,        0,          0,       0,        0,        0,        0,        0,      50,      50,      50,         0,       0,           0,           0,          0,            0,      0,          1,         16,          0,          0,          11,          42,        45,         0,        80,    150 },\r\n\t// clang-format on\r\n};\r\n\r\nclass PackTest : public ::testing::Test {\r\npublic:\r\n\tvoid SetUp() override\r\n\t{\r\n\t\tPlayers.resize(1);\r\n\t\tMyPlayer = &Players[0];\r\n\t}\r\n\r\n\tstatic void SetUpTestSuite()\r\n\t{\r\n\t\tLoadSpellData();\r\n\t\tLoadItemData();\r\n\t}\r\n};\r\n\r\nTEST_F(PackTest, UnPackItem_diablo)\r\n{\r\n\tItem id;\r\n\tItemPack is;\r\n\r\n\tSetHellfireState(false);\r\n\tgbIsMultiplayer = false;\r\n\tgbIsSpawn = false;\r\n\r\n\tMyPlayer->_pMaxManaBase = 125 << 6;\r\n\tMyPlayer->_pMaxHPBase = 125 << 6;\r\n\r\n\tfor (size_t i = 0; i < sizeof(PackedDiabloItems) / sizeof(*PackedDiabloItems); i++) {\r\n\t\tconst ItemPack packed = SwappedLE(PackedDiabloItems[i]);\r\n\t\tUnPackItem(packed, *MyPlayer, id, false);\r\n\t\tCompareItems(id, DiabloItems[i]);\r\n\t\tTestItemNameGeneration(id);\r\n\r\n\t\tPackItem(is, id, gbIsHellfire);\r\n\t\tComparePackedItems(is, packed);\r\n\t}\r\n}\r\n\r\nTEST_F(PackTest, UnPackItem_diablo_unique_bug)\r\n{\r\n\tconst auto pkItemBug = SwappedLE(ItemPack { 6, 15 | CF_UPER1 | CF_UPER15 | CF_UNIQUE, 14, 5, 60, 60, 0, 0, 0, 0 }); // Veil of Steel - with morph bug\r\n\tconst auto pkItem = SwappedLE(ItemPack { 6, 15 | CF_UPER15 | CF_UNIQUE, 14, 5, 60, 60, 0, 0, 0, 0 });               // Veil of Steel - fixed\r\n\r\n\tSetHellfireState(false);\r\n\tgbIsMultiplayer = false;\r\n\tgbIsSpawn = false;\r\n\r\n\tItem id;\r\n\tUnPackItem(pkItemBug, *MyPlayer, id, false);\r\n\tASSERT_STREQ(id._iIName, \"Veil of Steel\");\r\n\tASSERT_EQ(id._itype, ItemType::Helm);\r\n\tASSERT_EQ(id._iClass, ICLASS_ARMOR);\r\n\tASSERT_EQ(id._iCurs, 85);\r\n\tASSERT_EQ(id._iIvalue, 63800);\r\n\tASSERT_EQ(id._iAC, 18);\r\n\tASSERT_EQ(id._iMiscId, IMISC_UNIQUE);\r\n\tASSERT_EQ(id._iPLAC, 60);\r\n\tASSERT_EQ(id._iPLStr, 15);\r\n\tASSERT_EQ(id._iPLVit, 15);\r\n\tASSERT_EQ(id._iPLFR, 50);\r\n\tASSERT_EQ(id._iPLLR, 50);\r\n\tASSERT_EQ(id._iPLMR, 50);\r\n\tASSERT_EQ(id._iPLMana, -1920);\r\n\tASSERT_EQ(id._iPLLight, -2);\r\n\tASSERT_EQ(id._iUid, 6);\r\n\tASSERT_EQ(id.IDidx, IDI_STEELVEIL);\r\n\r\n\tItemPack is;\r\n\tPackItem(is, id, gbIsHellfire);\r\n\tComparePackedItems(is, pkItem);\r\n}\r\n\r\nconst ItemPack PackedSpawnItems[] = {\r\n\t// clang-format off\r\n\t//     iSeed,  iCreateInfo,  idx,  bId,  bDur,  bMDur,  bCh,  bMCh,  wValue,  dwBuff\r\n\t{ 2060036013, 1 | CF_UPER1,  131,    0,    11,     25,   50,    50,       0,       0 }, // Short Staff of Firebolt\r\n\t{   81574809, 2 | CF_UPER1,   94,    0,     0,      0,    0,     0,       0,       0 }, // Book of Holy Bolt\r\n\t// clang-format on\r\n};\r\n\r\nconst TestItemStruct SpawnItems[] = {\r\n\t// clang-format off\r\n\t// _iIName,                  _itype,           _iClass,  _iCurs,  _iIvalue,  _iMinDam,  _iMaxDam,  _iAC, _iFlags,                  _iMiscId, _iSpell,            _iCharges,  _iMaxCharges,  _iDurability,  _iMaxDur,  _iPLDam,  _iPLToHit,  _iPLAC,  _iPLStr,  _iPLMag,  _iPLDex,  _iPLVit,  _iPLFR,  _iPLLR,  _iPLMR,  _iPLMana,  _iPLHP,  _iPLDamMod,  _iPLGetHit,  _iPLLight,  _iSplLvlAdd,  _iUid,  _iFMinDam,  _iFMaxDam,  _iLMinDam,  _iLMaxDam,  _iPrePower,  _iSufPower,  _iMinStr,  _iMinMag,  _iMinDex,  IDidx\r\n\t{ \"Short Staff of Firebolt\", ItemType::Staff,        1,     109,         1,         2,         4,     0, ItemSpecialEffect::None,        23, SpellID::Firebolt,         50,            50,            11,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        15,         0,    151 },\r\n\t{ \"Book of Holy Bolt\",       ItemType::Misc,         3,      86,      1000,         0,         0,     0, ItemSpecialEffect::None,        24, SpellID::HolyBolt,          0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        20,         0,    114 },\r\n\t// clang-format on\r\n};\r\n\r\nTEST_F(PackTest, UnPackItem_spawn)\r\n{\r\n\tItem id;\r\n\tItemPack is;\r\n\r\n\tSetHellfireState(false);\r\n\tgbIsMultiplayer = false;\r\n\tgbIsSpawn = true;\r\n\r\n\tMyPlayer->_pMaxManaBase = 125 << 6;\r\n\tMyPlayer->_pMaxHPBase = 125 << 6;\r\n\r\n\tfor (size_t i = 0; i < sizeof(PackedSpawnItems) / sizeof(*PackedSpawnItems); i++) {\r\n\t\tconst ItemPack packed = SwappedLE(PackedSpawnItems[i]);\r\n\t\tUnPackItem(packed, *MyPlayer, id, false);\r\n\t\tCompareItems(id, SpawnItems[i]);\r\n\t\tTestItemNameGeneration(id);\r\n\r\n\t\tPackItem(is, id, gbIsHellfire);\r\n\t\tComparePackedItems(is, packed);\r\n\t}\r\n}\r\n\r\nconst ItemPack PackedDiabloMPItems[] = {\r\n\t// clang-format off\r\n\t//     iSeed,                 iCreateInfo,  idx,  bId,  bDur,  bMDur,  bCh,  bMCh,  wValue,  dwBuff\r\n\t{  309674341, 1 | CF_UPER15 | CF_ONLYGOOD,  109,    0,     0,      0,    0,     0,       0,       0 }, // Book of Firebolt\r\n\t{ 1291471654, 6                          ,   34,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Resurrect\r\n\t{ 1580941742, 1 | CF_USEFUL              ,   24,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Healing\r\n\t{  467997257, 4 | CF_USEFUL              ,   27,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Town Portal\r\n\t{  796933756, 1 | CF_USEFUL              ,   25,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Mana\r\n\t// clang-format on\r\n};\r\n\r\nconst TestItemStruct DiabloMPItems[] = {\r\n\t// clang-format off\r\n\t// _iIName,                _itype,          _iClass,  _iCurs,  _iIvalue,  _iMinDam,  _iMaxDam,  _iAC, _iFlags,                  _iMiscId, _iSpell,              _iCharges,  _iMaxCharges,  _iDurability,  _iMaxDur,  _iPLDam,  _iPLToHit,  _iPLAC,  _iPLStr,  _iPLMag,  _iPLDex,  _iPLVit,  _iPLFR,  _iPLLR,  _iPLMR,  _iPLMana,  _iPLHP,  _iPLDamMod,  _iPLGetHit,  _iPLLight,  _iSplLvlAdd,  _iUid,  _iFMinDam,  _iFMaxDam,  _iLMinDam,  _iLMaxDam,  _iPrePower,  _iSufPower,  _iMinStr,  _iMinMag,  _iMinDex,  IDidx\r\n\t{ \"Book of Firebolt\",      ItemType::Misc,        3,      87,      1000,         0,         0,     0, ItemSpecialEffect::None,        24, SpellID::Firebolt,            0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        15,         0,    114 },\r\n\t{ \"Scroll of Resurrect\",   ItemType::Misc,        3,       1,       250,         0,         0,     0, ItemSpecialEffect::None,        22, SpellID::Resurrect,           0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     34 },\r\n\t{ \"Potion of Healing\",     ItemType::Misc,        3,      32,        50,         0,         0,     0, ItemSpecialEffect::None,         3, SpellID::Null,                0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     24 },\r\n\t{ \"Scroll of Town Portal\", ItemType::Misc,        3,       1,       200,         0,         0,     0, ItemSpecialEffect::None,        21, SpellID::TownPortal,          0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     27 },\r\n\t{ \"Potion of Mana\",        ItemType::Misc,        3,      39,        50,         0,         0,     0, ItemSpecialEffect::None,         6, SpellID::Null,                0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     25 },\r\n\t// clang-format on\r\n};\r\n\r\nTEST_F(PackTest, UnPackItem_diablo_multiplayer)\r\n{\r\n\tItem id;\r\n\tItemPack is;\r\n\r\n\tSetHellfireState(false);\r\n\tgbIsMultiplayer = true;\r\n\tgbIsSpawn = false;\r\n\r\n\tMyPlayer->_pMaxManaBase = 125 << 6;\r\n\tMyPlayer->_pMaxHPBase = 125 << 6;\r\n\r\n\tfor (size_t i = 0; i < sizeof(PackedDiabloMPItems) / sizeof(*PackedDiabloMPItems); i++) {\r\n\t\tconst ItemPack packed = SwappedLE(PackedDiabloMPItems[i]);\r\n\t\tUnPackItem(packed, *MyPlayer, id, false);\r\n\t\tCompareItems(id, DiabloMPItems[i]);\r\n\t\tTestItemNameGeneration(id);\r\n\r\n\t\tPackItem(is, id, gbIsHellfire);\r\n\t\tComparePackedItems(is, packed);\r\n\t}\r\n}\r\n\r\nconst ItemPack PackedHellfireItems[] = {\r\n\t// clang-format off\r\n\t//     iSeed,                              iCreateInfo,  idx,  bId,  bDur,  bMDur,  bCh,  bMCh,  wValue,  dwBuff\r\n\t{ 1717442367, 10 | CF_UPER1                           ,  156,    3,     0,      0,    0,     0,       0,       0 }, // Ring of stability\r\n\t{ 1268518156, 18 | CF_UPER1  | CF_ONLYGOOD            ,  157,    3,     0,      0,    0,     0,       0,       0 }, // Ring of precision\r\n\t{  132733863, 27 | CF_UPER1                           ,  157,    3,     0,      0,    0,     0,       0,       0 }, // Obsidian Ring of wizardry\r\n\t{  511953594, 27 | CF_UPER1                           ,  158,    3,     0,      0,    0,     0,       0,       0 }, // Ring of precision\r\n\t{ 1183326923, 26 | CF_UPER1  | CF_ONLYGOOD            ,  160,    3,     0,      0,    0,     0,       0,       0 }, // Amulet of titans\r\n\t{ 1863009736, 24 | CF_UPER1                           ,  160,    3,     0,      0,    0,     0,       0,       0 }, // Gold Amulet\r\n\t{ 1872860650, 30 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  135,    5,    75,     75,    0,     0,       0,       0 }, // Messerschmidt's Reaver\r\n\t{ 1584694222, 25 | CF_UPER1                           ,  142,    3,   127,    128,    0,     0,       0,       0 }, // Vicious Maul of structure\r\n\t{  669112929, 24 | CF_UPER1                           ,  119,    0,    15,     24,    0,     0,       0,       0 }, // Short Sword\r\n\t{  303108965, 24 | CF_UPER1                           ,  148,    3,    18,     50,    0,     0,       0,       0 }, // Long Battle Bow of shock\r\n\t{  575830996,  1 | CF_UPER1                           ,  143,    3,    30,     30,    0,     0,       0,       0 }, // Short Bow of magic\r\n\t{ 1488880650,  2 | CF_UPER15 | CF_ONLYGOOD            ,  152,    3,    35,     35,   22,    33,       0,       0 }, // Red Long Staff of Healing\r\n\t{ 1864450901,  7 | CF_UPER1                           ,   71,    0,     6,     16,    0,     0,       0,       0 }, // Buckler\r\n\t{   28387651,  7 | CF_UPER1                           ,   49,    0,    15,     20,    0,     0,       0,       0 }, // Skull Cap\r\n\t{ 1298183212,  1 | CF_UPER1                           ,   55,    0,     6,      6,    0,     0,       0,       0 }, // Rags\r\n\t{ 1113945523,  4 | CF_UPER1                           ,   58,    0,    30,     30,    0,     0,       0,       0 }, // Quilted Armor\r\n\t{  765757608,  4 | CF_UPER1                           ,   58,    2,    12,     30,    0,     0,       0,       0 }, // Quilted Armor of light\r\n\t{  188812770, 26 | CF_UPER1  | CF_ONLYGOOD            ,   67,    3,    75,     75,    0,     0,       0,       0 }, // Saintly Plate of the stars\r\n\t{  283577043, 22             | CF_SMITHPREMIUM        ,   67,    3,    63,     75,    0,     0,       0,       0 }, // Plate Mail of the stars\r\n\t{  123272767, 16                                      ,   24,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Healing\r\n\t{  433688373, 16                                      ,   29,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Full Healing\r\n\t{ 1213385484,  2             | CF_PREGEN              ,   25,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Mana\r\n\t{ 1405075219, 24 | CF_UPER1                           ,  110,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Golem\r\n\t{ 1478792102,  3 | CF_UPER1                           ,   92,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Search\r\n\t{ 1569255955,  6 | CF_UPER1                           ,   94,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Identify\r\n\t{ 1291205782,  5 | CF_UPER1                           ,   98,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Town Portal\r\n\t{  811925807,  4 | CF_UPER1                           ,   91,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Healing\r\n\t{ 1275007287,  1 | CF_UPER1                           ,  161,    0,     0,      0,    0,     0,       0,       0 }, // Rune of Fire\r\n\t{  561216242, 22 | CF_UPER1                           ,    0,    0,     0,      0,    0,     0,    1663,       0 }, // Gold\r\n\t{          1,  3                           | CF_UNIQUE,    7,    5,    45,     50,    0,     0,       0,       0 }, // The Undead Crown\r\n\t{          2,  6 | CF_UPER1                | CF_UNIQUE,    8,    5,     0,      0,    0,     0,       0,       0 }, // Empyrean Band\r\n\t{          4,  1 | CF_UPER1                | CF_UNIQUE,   11,    5,     0,      0,    0,     0,       0,       0 }, // Ring of Truth\r\n\t{          8,  0                           | CF_UNIQUE,   31,    5,    50,     50,    0,     0,       0,       0 }, // Griswold's Edge\r\n\t{          9, 18 | CF_UPER1  | CF_ONLYGOOD | CF_UNIQUE,   32,    5,   255,    255,    0,     0,       0,       0 }, // Bovine Plate\r\n\t{  410929431,  2 | CF_UPER1                           ,  114,    0,     0,      0,    0,     0,       0,       0 }, // Book of Healing\r\n\t{  876535546,  2 | CF_UPER1                           ,  114,    0,     0,      0,    0,     0,       0,       0 }, // Book of Charged Bolt\r\n\t{ 1009350361,  2 | CF_UPER1                           ,  114,    0,     0,      0,    0,     0,       0,       0 }, // Book of Firebolt\r\n\t{   41417651,  2 | CF_UPER1                           ,   83,    0,     0,      0,    0,     0,       0,       0 }, // Blacksmith Oil\r\n\t{  132200437,  2 | CF_UPER1                           ,   84,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Accuracy\r\n\t{  385651490,  1 | CF_UPER1                           ,   85,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Sharpness\r\n\t{ 1154514759, 34 | CF_UPER1                           ,   86,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Permanence\r\n\t{ 2020998927, 18             | CF_SMITHPREMIUM        ,  131,    3,    23,     32,    0,     0,       0,       0 }, // Doppelganger's Axe\r\n\t{  581541889, 19             | CF_SMITHPREMIUM        ,  141,    3,    36,     36,    0,     0,       0,       0 }, // Flail of vampires\r\n\t{ 1069448901, 12 | CF_UPER1  | CF_ONLYGOOD | CF_UNIQUE,  157,    5,     0,      0,    0,     0,       0,       0 }, // Gladiator's Ring\r\n\t{ 1670063399, 20             | CF_SMITHPREMIUM        ,  155,    3,    75,     75,    0,     0,       0,       0 }, // Warrior's Staff of the moon\r\n\t{  342570085, 18             | CF_BOY                 ,   74,    3,   255,    255,    0,     0,       0,       0 }, // Kite Shield of the ages\r\n\t{ 1514523617, 18             | CF_SMITHPREMIUM        ,  139,    3,    20,     20,    0,     0,       0,       0 }, // Heavy Club of puncturing\r\n\t{  701987341, 16             | CF_WITCH               ,  114,    1,     0,      0,    0,     0,       0,       0 }, // Book of Lightning\r\n\t{  568338383,  4 | CF_UPER15 | CF_ONLYGOOD            ,  124,    3,    23,     45,    0,     0,       0,       0 }, // Jester's Sabre\r\n\t{ 1308277119,  8             | CF_SMITHPREMIUM        ,   72,    3,    24,     24,    0,     0,       0,       0 }, // Small Shield of blocking\r\n\t{          0,  0                           | CF_UNIQUE,    6,    5,    10,     10,    0,     0,       0,       0 }, // The Butcher's Cleaver\r\n\t{ 1621745295,  9             | CF_SMITHPREMIUM        ,  121,    3,    28,     28,    0,     0,       0,       0 }, // Scimitar of peril\r\n\t{  492619876,  6             | CF_SMITHPREMIUM        ,  132,    3,    12,     12,    0,     0,       0,       0 }, // Crystalline Large Axe\r\n\t{ 1859493982,  5             | CF_SMITHPREMIUM        ,   56,    3,    18,     18,    0,     0,       0,       0 }, // Red Cloak\r\n\t{ 1593032051,  2             | CF_SMITHPREMIUM        ,  136,    3,    32,     32,    0,     0,       0,       0 }, // Mace of decay\r\n\t{          4,  0                           | CF_UNIQUE,   11,    5,     0,      0,    0,     0,       0,       0 }, // Ring of Truth\r\n\t{ 1500728519,  4 | CF_UPER1                           ,   61,    3,    18,     45,    0,     0,       0,       0 }, // Red Armor of paralysis\r\n\t{  954183925,  5 | CF_UPER1                           ,  144,    3,    26,     40,    0,     0,       0,       0 }, // Bent Hunter's Bow\r\n\t{  438248055,  7 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  136,    5,    32,     32,    0,     0,       0,       0 }, // Civerb's Cudgel\r\n\t{ 1133027011,  8 | CF_UPER1  | CF_ONLYGOOD            ,  139,    3,     8,     20,    0,     0,       0,       0 }, // Deadly Spiked Club\r\n\t{  224835143, 28 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  144,    5,   255,    255,    0,     0,       0,       0 }, // Gnat Sting\r\n\t{ 1498080548, 28 | CF_UPER1                | CF_UNIQUE,  138,    5,   255,    255,    0,     0,       0,       0 }, // Thunderclap\r\n\t{ 1218409601, 24 | CF_UPER1                | CF_UNIQUE,  155,    5,    75,     75,   50,    50,       0,       0 }, // Rod of Onan\r\n\t{ 1228950066,  7 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  146,    5,   255,    255,    0,     0,       0,       0 }, // Flambeau\r\n\t{  863852923,  5 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  156,    5,     0,      0,    0,     0,       0,       0 }, // Ring of Thunder\r\n\t{   89183927, 12 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  159,    5,     0,      0,    0,     0,       0,       0 }, // Acolyte's Amulet\r\n\t{  858625694, 28 | CF_UPER1                | CF_UNIQUE,  151,    5,    25,     25,   86,    86,       0,       0 }, // The Protector\r\n\t{  127653047, 30 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,   63,    5,    55,     55,    0,     0,       0,       0 }, // Bone Chain Armor\r\n\t{ 1282740811, 34 | CF_UPER1                           ,   86,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Permanence\r\n\t{ 1403842263, 26 | CF_UPER1  | CF_ONLYGOOD | CF_UNIQUE,   70,    5,    90,     90,    0,     0,       0,       0 }, // Demon Plate Armor\r\n\t{ 1543909415, 28 | CF_UPER1                           ,   86,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Fortitude\r\n\t{ 1572202402,  1 | CF_UPER1                | CF_UNIQUE,  157,    5,     0,      0,    0,     0,       0,       0 }, // Ring of Regha\r\n\t{ 1572202657,  1 | CF_UPER1                           ,  156,    3,     0,      0,    0,     0,       0,       0 }, // Bronze Ring of dexterity\r\n\t{ 1642077210,  8 | CF_UPER1                           ,   84,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Accuracy\r\n\t{ 2049461998,  4 | CF_USEFUL                          ,   35,    0,     0,      0,    0,     0,       0,       0 }, // Blacksmith Oil\r\n\t{ 2054447852,  2             | CF_SMITHPREMIUM        ,  151,    3,    25,     25,    0,     0,       0,       0 }, // Spider's Staff of devastation\r\n\t{  257276810, 28 | CF_UPER1                           ,   86,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Hardening\r\n\t{   29449848, 11 | CF_UPER1                           ,   86,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Skill\r\n\t{  296008111, 26 | CF_UPER1                           ,   86,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Mastery\r\n\t{  521895255, 20 | CF_UPER15 | CF_ONLYGOOD | CF_UNIQUE,  146,    5,   255,    255,    0,     0,       0,       0 }, // Blitzen\r\n\t{  580426378, 23 | CF_UPER1                           ,   86,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Death\r\n\t{  626919077,  8 | CF_UPER1                           ,   85,    0,     0,      0,    0,     0,       0,       0 }, // Oil of Sharpness\r\n\t{  979073763, 11 | CF_UPER1                           ,  119,    3,    13,     13,    0,     0,       0,       0 }, // Crystalline Sword of the leech\r\n\t{ 1294354855, 16             | CF_WITCH               ,  153,    3,    45,     45,   14,    14,       0,       0 }, // Plentiful Staff of Mana Shield\r\n\t{  695065155, 30             | CF_SMITHPREMIUM        ,  155,    3,    75,     75,    0,     0,       0,       0 }, // King's War Staff\r\n\t{ 1100844414,  2 | CF_USEFUL                          ,   25,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Mana\r\n\t{ 1944120644,  2 | CF_USEFUL                          ,   27,    0,     0,      0,    0,     0,       0,       0 }, // Scroll of Town Portal\r\n\t{  525564945,  1 | CF_USEFUL                          ,   25,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Mana\r\n\t{ 1988162817,  1 | CF_USEFUL                          ,   24,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Healing\r\n\t{ 1191207687,  1 | CF_USEFUL                          ,   24,    0,     0,      0,    0,     0,       0,       0 }, // Potion of Healing\r\n\t// clang-format on\r\n};\r\n\r\nconstexpr ItemSpecialEffect GnatStingSpecialEffect = ItemSpecialEffect::MultipleArrows | ItemSpecialEffect::QuickAttack;\r\nconstexpr ItemSpecialEffect ThunderclapSpecialEffect = ItemSpecialEffect::FireDamage | ItemSpecialEffect::LightningDamage;\r\nconstexpr ItemSpecialEffect ExplosiveArrows = ItemSpecialEffect::FireArrows | ItemSpecialEffect::LightningArrows;\r\nconstexpr ItemSpecialEffect LightningArrows = ItemSpecialEffect::LightningArrows | ItemSpecialEffect::LightningDamage;\r\n\r\nconst TestItemStruct HellfireItems[] = {\r\n\t// clang-format off\r\n\t// _iIName,                         _itype,                 _iClass,  _iCurs,  _iIvalue,  _iMinDam,  _iMaxDam,  _iAC, _iFlags,                               _iMiscId, _iSpell,               _iCharges,  _iMaxCharges,  _iDurability,  _iMaxDur,  _iPLDam,  _iPLToHit,  _iPLAC,  _iPLStr,  _iPLMag,  _iPLDex,  _iPLVit,  _iPLFR,  _iPLLR,  _iPLMR,  _iPLMana,  _iPLHP,  _iPLDamMod,  _iPLGetHit,  _iPLLight,  _iSplLvlAdd,  _iUid,  _iFMinDam,  _iFMaxDam,  _iLMinDam,  _iLMaxDam,  _iPrePower,  _iSufPower,  _iMinStr,  _iMinMag,  _iMinDex,  IDidx\r\n\t{ \"Ring of stability\",              ItemType::Ring,               3,      12,      8000,         0,         0,     0, ItemSpecialEffect::FasterHitRecovery,        25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          59,         0,         0,         0,    156 },\r\n\t{ \"Ring of precision\",              ItemType::Ring,               3,      12,     10200,         0,         0,     0, ItemSpecialEffect::None,                     25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,       16,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          23,         0,         0,         0,    157 },\r\n\t{ \"Obsidian Ring of wizardry\",      ItemType::Ring,               3,      12,     56928,         0,         0,     0, ItemSpecialEffect::None,                     25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,       27,        0,        0,      37,      37,      37,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          11,          21,         0,         0,         0,    157 },\r\n\t{ \"Ring of precision\",              ItemType::Ring,               3,      12,     10200,         0,         0,     0, ItemSpecialEffect::None,                     25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,       16,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          23,         0,         0,         0,    158 },\r\n\t{ \"Amulet of titans\",               ItemType::Amulet,             3,      45,     20896,         0,         0,     0, ItemSpecialEffect::None,                     26, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,       28,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          19,         0,         0,         0,    160 },\r\n\t{ \"Gold Amulet\",                    ItemType::Amulet,             3,      45,     13692,         0,         0,     0, ItemSpecialEffect::None,                     26, SpellID::Null,                 0,             0,             0,         0,        0,         29,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           0,          -1,         0,         0,         0,    160 },\r\n\t{ \"Messerschmidt's Reaver\",         ItemType::Axe,                1,     163,     58000,        12,        30,     0, ItemSpecialEffect::FireDamage,                0, SpellID::Null,                 0,             0,            75,        75,      200,          0,       0,        5,        5,        5,        5,       0,       0,       0,         0,   -3200,          15,           0,          0,            0,     44,          2,         12,          0,          0,          -1,          -1,        80,         0,         0,    135 },\r\n\t{ \"Vicious Maul of structure\",      ItemType::Mace,               1,     122,     10489,         6,        20,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,           127,       128,       72,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           2,          35,        55,         0,         0,    142 },\r\n\t{ \"Short Sword\",                    ItemType::Sword,              1,      64,       120,         2,         6,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            15,        24,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,        18,         0,         0,    119 },\r\n\t{ \"Long Battle Bow of shock\",       ItemType::Bow,                1,     119,      8000,         1,        10,     0, LightningArrows,                              0, SpellID::Null,                 0,             0,            18,        50,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          1,          6,          -1,          43,        30,         0,        60,    148 },\r\n\t{ \"Short Bow of magic\",             ItemType::Bow,                1,     118,       400,         1,         4,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            30,        30,        0,          0,       0,        0,        1,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          21,         0,         0,         0,    143 },\r\n\t{ \"Red Long Staff of Healing\",      ItemType::Staff,              1,     123,      1360,         4,         8,     0, ItemSpecialEffect::None,                     23, SpellID::Healing,             22,            33,            35,        35,        0,          0,       0,        0,        0,        0,        0,      10,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           8,          -1,         0,        17,         0,    152 },\r\n\t{ \"Buckler\",                        ItemType::Shield,             2,      83,        30,         0,         0,     5, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,             6,        16,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     71 },\r\n\t{ \"Skull Cap\",                      ItemType::Helm,               2,      90,        25,         0,         0,     3, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            15,        20,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     49 },\r\n\t{ \"Rags\",                           ItemType::LightArmor,         2,     128,         5,         0,         0,     4, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,             6,         6,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     55 },\r\n\t{ \"Quilted Armor\",                  ItemType::LightArmor,         2,     129,       200,         0,         0,     7, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            30,        30,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     58 },\r\n\t{ \"Quilted Armor of light\",         ItemType::LightArmor,         2,     129,      1150,         0,         0,    10, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            12,        30,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          2,            0,      0,          0,          0,          0,          0,          -1,          38,         0,         0,         0,     58 },\r\n\t{ \"Saintly Plate of the stars\",     ItemType::HeavyArmor,         2,     103,    140729,         0,         0,    46, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            75,        75,        0,          0,     121,       10,       10,       10,       10,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           6,          27,        60,         0,         0,     67 },\r\n\t{ \"Plate Mail of the stars\",        ItemType::HeavyArmor,         2,     103,     77800,         0,         0,    49, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            63,        75,        0,          0,       0,        8,        8,        8,        8,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          27,        60,         0,         0,     67 },\r\n\t{ \"Potion of Healing\",              ItemType::Misc,               3,      32,        50,         0,         0,     0, ItemSpecialEffect::None,                      3, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     24 },\r\n\t{ \"Potion of Full Healing\",         ItemType::Misc,               3,      35,       150,         0,         0,     0, ItemSpecialEffect::None,                      2, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     29 },\r\n\t{ \"Potion of Mana\",                 ItemType::Misc,               3,      39,        50,         0,         0,     0, ItemSpecialEffect::None,                      6, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     25 },\r\n\t{ \"Scroll of Golem\",                ItemType::Misc,               3,       1,      1100,         0,         0,     0, ItemSpecialEffect::None,                     22, SpellID::Golem,                0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        51,         0,    110 },\r\n\t{ \"Scroll of Search\",               ItemType::Misc,               3,       1,        50,         0,         0,     0, ItemSpecialEffect::None,                     21, SpellID::Search,               0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     92 },\r\n\t{ \"Scroll of Identify\",             ItemType::Misc,               3,       1,       100,         0,         0,     0, ItemSpecialEffect::None,                     21, SpellID::Identify,             0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     94 },\r\n\t{ \"Scroll of Town Portal\",          ItemType::Misc,               3,       1,       200,         0,         0,     0, ItemSpecialEffect::None,                     21, SpellID::TownPortal,           0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     98 },\r\n\t{ \"Scroll of Healing\",              ItemType::Misc,               3,       1,        50,         0,         0,     0, ItemSpecialEffect::None,                     21, SpellID::Healing,              0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     91 },\r\n\t{ \"Rune of Fire\",                   ItemType::Misc,               3,     193,       100,         0,         0,     0, ItemSpecialEffect::None,                     47, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    161 },\r\n\t{ \"Gold\",                           ItemType::Gold,               4,       5,         0,         0,         0,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,      0 },\r\n\t{ \"The Undead Crown\",               ItemType::Helm,               2,      77,     16650,         0,         0,     8, ItemSpecialEffect::RandomStealLife,          27, SpellID::Null,                 0,             0,            45,        50,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      1,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,      7 },\r\n\t{ \"Empyrean Band\",                  ItemType::Ring,               3,      18,      8000,         0,         0,     0, EmpyreanBandSpecialEffect,                   27, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        2,        2,        2,        2,       0,       0,       0,         0,       0,           0,           0,          2,            0,      2,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,      8 },\r\n\t{ \"Ring of Truth\",                  ItemType::Ring,               3,      10,      9100,         0,         0,     0, ItemSpecialEffect::None,                     27, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,      10,      10,      10,         0,     640,           0,          -1,          0,            0,      4,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     11 },\r\n\t{ \"Griswold's Edge\",                ItemType::Sword,              1,      61,     42000,         4,        12,     0, GrisworldEdgeSpecialEffect,                  27, SpellID::Null,                 0,             0,            50,        50,        0,         25,       0,        0,        0,        0,        0,       0,       0,       0,      1280,   -1280,           0,           0,          0,            0,      8,          1,         10,          0,          0,          -1,          -1,        40,         0,         0,     31 },\r\n\t{ \"Bovine Plate\",                   ItemType::HeavyArmor,         2,     226,       400,         0,         0,   150, ItemSpecialEffect::None,                     27, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,        0,        0,        0,        0,      30,      30,      30,     -3200,       0,           0,           0,          5,           -2,      9,          0,          0,          0,          0,          -1,          -1,        50,         0,         0,     32 },\r\n\t{ \"Book of Healing\",                ItemType::Misc,               3,      86,      1000,         0,         0,     0, ItemSpecialEffect::None,                     24, SpellID::Healing,              0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        17,         0,    114 },\r\n\t{ \"Book of Charged Bolt\",           ItemType::Misc,               3,      88,      1000,         0,         0,     0, ItemSpecialEffect::None,                     24, SpellID::ChargedBolt,          0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        25,         0,    114 },\r\n\t{ \"Book of Firebolt\",               ItemType::Misc,               3,      87,      1000,         0,         0,     0, ItemSpecialEffect::None,                     24, SpellID::Firebolt,             0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        15,         0,    114 },\r\n\t{ \"Blacksmith Oil\",                 ItemType::Misc,               3,      30,       100,         0,         0,     0, ItemSpecialEffect::None,                     36, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     83 },\r\n\t{ \"Oil of Accuracy\",                ItemType::Misc,               3,      30,       500,         0,         0,     0, ItemSpecialEffect::None,                     31, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     84 },\r\n\t{ \"Oil of Sharpness\",               ItemType::Misc,               3,      30,       500,         0,         0,     0, ItemSpecialEffect::None,                     33, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     85 },\r\n\t{ \"Oil of Permanence\",              ItemType::Misc,               3,      30,     15000,         0,         0,     0, ItemSpecialEffect::None,                     38, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     86 },\r\n\t{ \"Doppelganger's Axe\",             ItemType::Axe,                1,     144,      6640,         4,        12,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            23,        32,       86,         26,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          89,          -1,        22,         0,         0,    131 },\r\n\t{ \"Flail of vampires\",              ItemType::Mace,               1,     131,     16500,         2,        12,     0, ItemSpecialEffect::StealMana5,                0, SpellID::Null,                 0,             0,            36,        36,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          55,        30,         0,         0,    141 },\r\n\t{ \"Gladiator's Ring\",               ItemType::Ring,               3,     186,     10000,         0,         0,     0, ItemSpecialEffect::None,                     25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,      3200,   -3200,           0,           0,          0,            0,    109,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    157 },\r\n\t{ \"Warrior's Staff of the moon\",    ItemType::Staff,              1,     124,     42332,         8,        16,     0, ItemSpecialEffect::None,                     23, SpellID::Null,                 0,             0,            75,        75,       54,         15,       0,        5,        5,        5,        5,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          27,        30,         0,         0,    155 },\r\n\t{ \"Kite Shield of the ages\",        ItemType::Shield,             2,     113,      2600,         0,         0,    10, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          37,        50,         0,         0,     74 },\r\n\t{ \"Heavy Club of puncturing\",       ItemType::Mace,               1,      70,      5239,         3,         6,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            20,        20,       52,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           2,          57,        18,         0,         0,    139 },\r\n\t{ \"Book of Lightning\",              ItemType::Misc,               3,      88,      3000,         0,         0,     0, ItemSpecialEffect::None,                     24, SpellID::Lightning,            0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,        20,         0,    114 },\r\n\t{ \"Jester's Sabre\",                 ItemType::Sword,              1,      67,      1710,         1,         8,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            23,        45,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          87,          -1,        17,         0,         0,    124 },\r\n\t{ \"Small Shield of blocking\",       ItemType::Shield,             2,     105,      4360,         0,         0,     6, ItemSpecialEffect::FastBlock,                 0, SpellID::Null,                 0,             0,            24,        24,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          60,        25,         0,         0,     72 },\r\n\t{ \"The Butcher's Cleaver\",          ItemType::Axe,                1,     106,      3650,         4,        24,     0, ItemSpecialEffect::None,                     27, SpellID::Null,                 0,             0,            10,        10,        0,          0,       0,       10,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,      6 },\r\n\t{ \"Scimitar of peril\",              ItemType::Sword,              1,      72,       700,         3,         7,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            28,        28,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          86,        23,         0,        23,    121 },\r\n\t{ \"Crystalline Large Axe\",          ItemType::Axe,                1,     142,      5250,         6,        16,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            12,        12,      280,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          88,          -1,        30,         0,         0,    132 },\r\n\t{ \"Red Cloak\",                      ItemType::LightArmor,         2,     149,       580,         0,         0,     3, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            18,        18,        0,          0,       0,        0,        0,        0,        0,      10,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           8,          -1,         0,         0,         0,     56 },\r\n\t{ \"Mace of decay\",                  ItemType::Mace,               1,      59,       600,         1,         8,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            32,        32,      232,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          85,        16,         0,         0,    136 },\r\n\t{ \"Ring of Truth\",                  ItemType::Ring,               3,      10,      9100,         0,         0,     0, ItemSpecialEffect::None,                     27, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,      10,      10,      10,         0,     640,           0,          -1,          0,            0,      4,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     11 },\r\n\t{ \"Red Armor of paralysis\",         ItemType::LightArmor,         2,     107,       800,         0,         0,    17, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            18,        45,        0,          0,       0,        0,        0,       -8,        0,      20,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           8,          24,        20,         0,         0,     61 },\r\n\t{ \"Bent Hunter's Bow\",              ItemType::Bow,                1,     102,         1,         2,         5,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            26,        40,      -69,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           3,          -1,        20,         0,        35,    144 },\r\n\t{ \"Civerb's Cudgel\",                ItemType::Mace,               1,      59,      2000,         1,         8,     0, ItemSpecialEffect::TripleDemonDamage,         0, SpellID::Null,                 0,             0,            32,        32,        0,          0,       0,        0,       -2,       -5,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,     47,          0,          0,          0,          0,          -1,          -1,        16,         0,         0,    136 },\r\n\t{ \"Deadly Spiked Club\",             ItemType::Mace,               1,      70,      1556,         3,         6,     0, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,             8,        20,       47,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           2,          -1,        18,         0,         0,    139 },\r\n\t{ \"Gnat Sting\",                     ItemType::Bow,                1,     210,     30000,         1,         2,     0, GnatStingSpecialEffect,                       0, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,     98,          0,          0,          0,          0,          -1,          -1,        20,         0,        35,    144 },\r\n\t{ \"Thunderclap\",                    ItemType::Mace,               1,     205,     30000,         5,         9,     0, ThunderclapSpecialEffect,                     0, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,       20,        0,        0,        0,       0,      30,       0,         0,       0,           0,           0,          2,            0,    102,          3,          6,          2,          0,          -1,          -1,        40,         0,         0,    138 },\r\n\t{ \"Rod of Onan\",                    ItemType::Staff,              1,     124,     44167,         8,        16,     0, ItemSpecialEffect::None,                     23, SpellID::Golem,               50,            50,            75,        75,      100,          0,       0,        5,        5,        5,        5,       0,       0,       0,         0,       0,           0,           0,          0,            0,     62,          0,          0,          0,          0,          -1,          -1,        30,         0,         0,    155 },\r\n\t{ \"Flambeau\",                       ItemType::Bow,                1,     209,     30000,         0,         0,     0, ExplosiveArrows,                              0, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,     99,         15,         20,          0,          0,          -1,          -1,        25,         0,        40,    146 },\r\n\t{ \"Ring of Thunder\",                ItemType::Ring,               3,     177,      8000,         0,         0,     0, ItemSpecialEffect::None,                     25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,     -30,      60,     -30,         0,       0,           0,           0,          0,            0,     96,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    156 },\r\n\t{ \"Acolyte's Amulet\",               ItemType::Amulet,             3,     183,     10000,         0,         0,     0, ItemSpecialEffect::None,                     26, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,     -3968,    3968,           0,           0,          0,            0,    108,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    159 },\r\n\t{ \"The Protector\",                  ItemType::Staff,              1,     162,     17240,         2,         4,    40, ItemSpecialEffect::Thorns,                   23, SpellID::Healing,             86,            86,            25,        25,        0,          0,       0,        0,        0,        0,        5,       0,       0,       0,         0,       0,           0,          -5,          0,            0,     59,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    151 },\r\n\t{ \"Bone Chain Armor\",               ItemType::MediumArmor,        2,     204,     36000,         0,         0,    40, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            55,        55,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,    106,          0,          0,          0,          0,          -1,          -1,        30,         0,         0,     63 },\r\n\t{ \"Oil of Permanence\",              ItemType::Misc,               3,      30,     15000,         0,         0,     0, ItemSpecialEffect::None,                     38, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     86 },\r\n\t{ \"Demon Plate Armor\",              ItemType::HeavyArmor,         2,     225,     80000,         0,         0,    80, ItemSpecialEffect::None,                      0, SpellID::Null,                 0,             0,            90,        90,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,    107,          0,          0,          0,          0,          -1,          -1,        90,         0,         0,     70 },\r\n\t{ \"Oil of Fortitude\",               ItemType::Misc,               3,      30,      2500,         0,         0,     0, ItemSpecialEffect::None,                     37, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     86 },\r\n\t{ \"Ring of Regha\",                  ItemType::Ring,               3,      11,      4175,         0,         0,     0, ItemSpecialEffect::None,                     25, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,       -3,       10,       -3,        0,       0,       0,      10,         0,       0,           0,           0,          1,            0,     86,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,    157 },\r\n\t{ \"Bronze Ring of dexterity\",       ItemType::Ring,               3,      12,      5200,         0,         0,     0, ItemSpecialEffect::None,                     25, SpellID::Null,                 0,             0,             0,         0,        0,          4,       0,        0,        0,        4,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           0,          23,         0,         0,         0,    156 },\r\n\t{ \"Oil of Accuracy\",                ItemType::Misc,               3,      30,       500,         0,         0,     0, ItemSpecialEffect::None,                     31, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     84 },\r\n\t{ \"Blacksmith Oil\",                 ItemType::Misc,               3,      30,       100,         0,         0,     0, ItemSpecialEffect::None,                     36, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     35 },\r\n\t{ \"Spider's Staff of devastation\",  ItemType::Staff,              1,     109,      2050,         2,         4,     0, ItemSpecialEffect::None,                     23, SpellID::Null,                 0,             0,            25,        25,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,       768,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          33,          84,         0,         0,         0,    151 },\r\n\t{ \"Oil of Hardening\",               ItemType::Misc,               3,      30,       500,         0,         0,     0, ItemSpecialEffect::None,                     39, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     86 },\r\n\t{ \"Oil of Skill\",                   ItemType::Misc,               3,      30,      1500,         0,         0,     0, ItemSpecialEffect::None,                     35, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     86 },\r\n\t{ \"Oil of Mastery\",                 ItemType::Misc,               3,      30,      2500,         0,         0,     0, ItemSpecialEffect::None,                     32, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     86 },\r\n\t{ \"Blitzen\",                        ItemType::Bow,                1,     219,     30000,         0,         0,     0, ExplosiveArrows,                              0, SpellID::Null,                 0,             0,           255,       255,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,    101,         10,         15,          1,          0,          -1,          -1,        25,         0,        40,    146 },\r\n\t{ \"Oil of Death\",                   ItemType::Misc,               3,      30,      2500,         0,         0,     0, ItemSpecialEffect::None,                     34, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     86 },\r\n\t{ \"Oil of Sharpness\",               ItemType::Misc,               3,      30,       500,         0,         0,     0, ItemSpecialEffect::None,                     33, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     85 },\r\n\t{ \"Crystalline Sword of the leech\", ItemType::Sword,              1,      64,     10020,         2,         6,     0, ItemSpecialEffect::StealLife3,                0, SpellID::Null,                 0,             0,            13,        13,      232,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          88,          56,        18,         0,         0,    119 },\r\n\t{ \"Plentiful Staff of Mana Shield\", ItemType::Staff,              1,     166,      6360,         5,        10,     0, ItemSpecialEffect::None,                     23, SpellID::ManaShield,          14,            14,            45,        45,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          15,          -1,         0,        25,         0,    153 },\r\n\t{ \"King's War Staff\",               ItemType::Staff,              1,     124,     92000,         8,        16,     0, ItemSpecialEffect::None,                     23, SpellID::Null,                 0,             0,            75,        75,      175,         76,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,           4,          -1,        30,         0,         0,    155 },\r\n\t{ \"Potion of Mana\",                 ItemType::Misc,               3,      39,        50,         0,         0,     0, ItemSpecialEffect::None,                      6, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     25 },\r\n\t{ \"Scroll of Town Portal\",          ItemType::Misc,               3,       1,       200,         0,         0,     0, ItemSpecialEffect::None,                     21, SpellID::TownPortal,           0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     27 },\r\n\t{ \"Potion of Mana\",                 ItemType::Misc,               3,      39,        50,         0,         0,     0, ItemSpecialEffect::None,                      6, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     25 },\r\n\t{ \"Potion of Healing\",              ItemType::Misc,               3,      32,        50,         0,         0,     0, ItemSpecialEffect::None,                      3, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     24 },\r\n\t{ \"Potion of Healing\",              ItemType::Misc,               3,      32,        50,         0,         0,     0, ItemSpecialEffect::None,                      3, SpellID::Null,                 0,             0,             0,         0,        0,          0,       0,        0,        0,        0,        0,       0,       0,       0,         0,       0,           0,           0,          0,            0,      0,          0,          0,          0,          0,          -1,          -1,         0,         0,         0,     24 },\r\n\t// clang-format on\r\n};\r\n\r\nTEST_F(PackTest, UnPackItem_hellfire)\r\n{\r\n\tItem id;\r\n\tItemPack is;\r\n\r\n\tSetHellfireState(true);\r\n\tgbIsMultiplayer = false;\r\n\tgbIsSpawn = false;\r\n\r\n\tMyPlayer->_pMaxManaBase = 125 << 6;\r\n\tMyPlayer->_pMaxHPBase = 125 << 6;\r\n\r\n\tfor (size_t i = 0; i < sizeof(PackedHellfireItems) / sizeof(*PackedHellfireItems); i++) {\r\n\t\tconst ItemPack packed = SwappedLE(PackedHellfireItems[i]);\r\n\t\tUnPackItem(packed, *MyPlayer, id, true);\r\n\t\tCompareItems(id, HellfireItems[i]);\r\n\t\tTestItemNameGeneration(id);\r\n\r\n\t\tPackItem(is, id, gbIsHellfire);\r\n\t\tis.dwBuff &= ~CF_HELLFIRE;\r\n\t\tComparePackedItems(is, packed);\r\n\t}\r\n}\r\n\r\nTEST_F(PackTest, UnPackItem_diablo_strip_hellfire_items)\r\n{\r\n\tconst auto is = SwappedLE(ItemPack { 1478792102, 3 | CF_UPER1, 92, 0, 0, 0, 0, 0, 0, 0 }); // Scroll of Search\r\n\tItem id;\r\n\r\n\tSetHellfireState(false);\r\n\tgbIsMultiplayer = false;\r\n\tgbIsSpawn = false;\r\n\r\n\tUnPackItem(is, *MyPlayer, id, true);\r\n\tTestItemNameGeneration(id);\r\n\r\n\tASSERT_EQ(id._itype, ItemType::None);\r\n}\r\n\r\nTEST_F(PackTest, UnPackItem_empty)\r\n{\r\n\tconst auto is = SwappedLE(ItemPack { 0, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0 });\r\n\tItem id;\r\n\r\n\tUnPackItem(is, *MyPlayer, id, false);\r\n\tTestItemNameGeneration(id);\r\n\r\n\tASSERT_EQ(id._itype, ItemType::None);\r\n}\r\n\r\nTEST_F(PackTest, PackItem_empty)\r\n{\r\n\tItemPack is;\r\n\tItem id = {};\r\n\r\n\tid._itype = ItemType::None;\r\n\r\n\tPackItem(is, id, gbIsHellfire);\r\n\r\n\t// Copy the value out before comparing to avoid loading a misaligned address.\r\n\tconst auto idx = is.idx;\r\n\tASSERT_EQ(Swap16LE(idx), 0xFFFF);\r\n\tTestItemNameGeneration(id);\r\n}\r\n\r\nstatic void compareGold(const ItemPack &is, int iCurs)\r\n{\r\n\tItem id;\r\n\tUnPackItem(is, *MyPlayer, id, false);\r\n\tASSERT_EQ(id._iCurs, iCurs);\r\n\tASSERT_EQ(id.IDidx, IDI_GOLD);\r\n\t// Copy the value out before comparing to avoid loading a misaligned address.\r\n\tconst auto wvalue = Swap16LE(is.wValue);\r\n\tASSERT_EQ(id._ivalue, wvalue);\r\n\tASSERT_EQ(id._itype, ItemType::Gold);\r\n\tASSERT_EQ(id._iClass, ICLASS_GOLD);\r\n\tTestItemNameGeneration(id);\r\n\r\n\tItemPack is2;\r\n\tPackItem(is2, id, gbIsHellfire);\r\n\tComparePackedItems(is, is2);\r\n}\r\n\r\nTEST_F(PackTest, UnPackItem_gold_small)\r\n{\r\n\tconst auto is = SwappedLE(ItemPack { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 1000, 0 });\r\n\tcompareGold(is, ICURS_GOLD_SMALL);\r\n}\r\n\r\nTEST_F(PackTest, UnPackItem_gold_medium)\r\n{\r\n\tconst auto is = SwappedLE(ItemPack { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 1001, 0 });\r\n\tcompareGold(is, ICURS_GOLD_MEDIUM);\r\n}\r\n\r\nTEST_F(PackTest, UnPackItem_gold_large)\r\n{\r\n\tconst auto is = SwappedLE(ItemPack { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 2500, 0 });\r\n\tcompareGold(is, ICURS_GOLD_LARGE);\r\n}\r\n\r\nTEST_F(PackTest, UnPackItem_ear)\r\n{\r\n\tconst auto is = SwappedLE(ItemPack { 1633955154, 17509, 23, 111, 103, 117, 101, 68, 19843, 0 });\r\n\tItem id;\r\n\r\n\tUnPackItem(is, *MyPlayer, id, false);\r\n\tASSERT_STREQ(id._iName, \"Ear of Dead-RogueDM\");\r\n\tASSERT_EQ(id._ivalue, 3);\r\n\tTestItemNameGeneration(id);\r\n\r\n\tItemPack is2;\r\n\tPackItem(is2, id, gbIsHellfire);\r\n\tComparePackedItems(is, is2);\r\n}\r\n\r\nclass NetPackTest : public ::testing::Test {\r\npublic:\r\n\tvoid SetUp() override\r\n\t{\r\n\t\tif (missingMpqAssets_) {\r\n\t\t\tGTEST_SKIP() << MissingMpqAssetsSkipReason;\r\n\t\t}\r\n\r\n\t\tPlayers.resize(2);\r\n\t\tMyPlayer = &Players[0];\r\n\t\tgbIsMultiplayer = true;\r\n\t\tgbIsSpawn = false;\r\n\r\n\t\tPlayerPack testPack {\r\n\t\t\t0, 0, -1, 9, 0, 2, 61, 24, 0, 0, \"MP-Warrior\", 0, 120, 25, 60, 60, 37, 0, 85670061, 3921, 13568, 13568, 3904, 3904,\r\n\t\t\t{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },\r\n\t\t\t1610612737,\r\n\t\t\t{ { 3160997530, 798, 52, 5, 40, 40, 0, 0, 0, 0 },\r\n\t\t\t    { 1911837482, 286, 152, 3, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 1262914017, 286, 151, 3, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 3846694361, 286, 155, 3, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 3454746195, 2077, 122, 3, 60, 60, 0, 0, 0, 0 },\r\n\t\t\t    { 1560055601, 4117, 75, 3, 50, 50, 0, 0, 0, 0 },\r\n\t\t\t    { 3097669048, 286, 70, 3, 66, 90, 0, 0, 0, 0 } },\r\n\t\t\t{ { 423576018, 16400, 82, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 543375803, 16400, 81, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 1802859062, 8208, 147, 3, 35, 35, 34, 34, 0, 0 },\r\n\t\t\t    { 368922902, 0, 0, 0, 0, 0, 0, 0, 3921, 0 },\r\n\t\t\t    { 1424628865, 8208, 111, 1, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 1128267486, 1, 25, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 885129636, 1, 25, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 1954673116, 260, 93, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 379449999, 260, 93, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 1684106752, 24937, 23, 0, 0, 0, 0, 0, 65, 0 },\r\n\t\t\t    { 1924887070, 385, 24, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 813588879, 194, 56, 2, 6, 18, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },\r\n\t\t\t{ -3, -3, -12, -12, 0, 0, 0, 0, -5, -5, -3, -3, -12, -12, 0, 0, 0, 0, 5, -5, 3, -3, 12, -12, 0, 0, 0, 0, 0, 0, 2, 1, 6, 7, 8, 9, 10, 11, 4, 0 },\r\n\t\t\t12,\r\n\t\t\t{ { 112017676, 16, 24, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 367533949, 16, 24, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 778528030, 16, 24, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 960294091, 16, 24, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 1948311560, 16, 29, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 639577687, 16, 29, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 103356930, 16, 29, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t    { 215810455, 16, 29, 0, 0, 0, 0, 0, 0, 0 } },\r\n\t\t\t0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n\t\t\t{ 0, 0 },\r\n\t\t\t{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\r\n\t\t\t0, 0, 0, 0,\r\n\t\t\t{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }\r\n\t\t};\r\n\r\n\t\tSwapLE(testPack);\r\n\t\tUnPackPlayer(testPack, *MyPlayer);\r\n\t}\r\n\r\n\tstatic void SetUpTestSuite()\r\n\t{\r\n\t\tLoadCoreArchives();\r\n\t\tLoadGameArchives();\r\n\r\n\t\tmissingMpqAssets_ = !HaveMainData();\r\n\t\tif (missingMpqAssets_) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tSetHellfireState(false);\r\n\t\tInitCursor();\r\n\t\tLoadSpellData();\r\n\t\tLoadPlayerDataFiles();\r\n\t\tLoadMonsterData();\r\n\t\tLoadItemData();\r\n\t}\r\n\r\nprivate:\r\n\tstatic bool missingMpqAssets_;\r\n};\r\n\r\nbool NetPackTest::missingMpqAssets_ = false;\r\n\r\nbool TestNetPackValidation()\r\n{\r\n\tPlayerNetPack packed;\r\n\tPackNetPlayer(packed, *MyPlayer);\r\n\treturn UnPackNetPlayer(packed, Players[1]);\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_valid)\r\n{\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_class)\r\n{\r\n\tPlayerNetPack packed;\r\n\tPackNetPlayer(packed, *MyPlayer);\r\n\tpacked.pClass = std::numeric_limits<uint8_t>::max();\r\n\tASSERT_FALSE(UnPackNetPlayer(packed, Players[1]));\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_oob)\r\n{\r\n\tconst WorldTilePosition position = MyPlayer->position.tile;\r\n\r\n\tMyPlayer->position.tile.x = MAXDUNX + 1;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tMyPlayer->position.tile = position;\r\n\tMyPlayer->position.tile.y = MAXDUNY + 1;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_plrlevel)\r\n{\r\n\tMyPlayer->plrlevel = NUMLEVELS;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_hpBase)\r\n{\r\n\tMyPlayer->_pHPBase = -64;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tMyPlayer->_pHPBase = MyPlayer->_pMaxHPBase + 64;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_manaBase)\r\n{\r\n\tMyPlayer->_pManaBase = MyPlayer->_pMaxManaBase + 64;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_baseStr)\r\n{\r\n\tMyPlayer->_pBaseStr = MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Strength) + 1;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_baseMag)\r\n{\r\n\tMyPlayer->_pBaseMag = MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Magic) + 1;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_baseDex)\r\n{\r\n\tMyPlayer->_pBaseDex = MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Dexterity) + 1;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_baseVit)\r\n{\r\n\tMyPlayer->_pBaseVit = MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Vitality) + 1;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_numInv)\r\n{\r\n\tMyPlayer->_pNumInv = InventoryGridCells + 1;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_strength)\r\n{\r\n\tMyPlayer->_pStrength++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_magic)\r\n{\r\n\tMyPlayer->_pMagic++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_dexterity)\r\n{\r\n\tMyPlayer->_pDexterity++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_vitality)\r\n{\r\n\tMyPlayer->_pVitality++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_hitPoints)\r\n{\r\n\tMyPlayer->_pHitPoints++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_maxHP)\r\n{\r\n\tMyPlayer->_pMaxHP++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_mana)\r\n{\r\n\tMyPlayer->_pMana++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_maxMana)\r\n{\r\n\tMyPlayer->_pMaxMana++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_damageMod)\r\n{\r\n\tMyPlayer->_pDamageMod++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_baseToBlk)\r\n{\r\n\tPlayerNetPack packed;\r\n\tPackNetPlayer(packed, *MyPlayer);\r\n\tpacked.pBaseToBlk++;\r\n\tASSERT_FALSE(UnPackNetPlayer(packed, Players[1]));\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iMinDam)\r\n{\r\n\tMyPlayer->_pIMinDam++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iMinDam++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iMaxDam)\r\n{\r\n\tMyPlayer->_pIMaxDam++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iMaxDam++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iAC)\r\n{\r\n\tMyPlayer->_pIAC++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_CHEST]._iAC++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iBonusDam)\r\n{\r\n\tMyPlayer->_pIBonusDam++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iPLDam++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iBonusToHit)\r\n{\r\n\tMyPlayer->_pIBonusToHit++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iPLToHit++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iBonusAC)\r\n{\r\n\tMyPlayer->_pIBonusAC++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_CHEST]._iPLAC++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iBonusDamMod)\r\n{\r\n\tMyPlayer->_pIBonusDamMod++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iPLDamMod++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iGetHit)\r\n{\r\n\tMyPlayer->_pIGetHit++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_CHEST]._iPLGetHit++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iEnAc)\r\n{\r\n\tMyPlayer->_pIEnAc++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_CHEST]._iPLEnAc++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iFMinDam)\r\n{\r\n\tMyPlayer->_pIFMinDam++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iFMinDam++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iFMaxDam)\r\n{\r\n\tMyPlayer->_pIFMaxDam++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iFMaxDam++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iLMinDam)\r\n{\r\n\tMyPlayer->_pILMinDam++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iLMinDam++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_iLMaxDam)\r\n{\r\n\tMyPlayer->_pILMaxDam++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n\r\n\tMyPlayer->InvBody[INVLOC_HAND_LEFT]._iLMaxDam++;\r\n\tCalcPlrItemVals(*MyPlayer, false);\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_maxHPBase)\r\n{\r\n\tMyPlayer->_pMaxHPBase++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_maxManaBase)\r\n{\r\n\tMyPlayer->_pMaxManaBase++;\r\n\tASSERT_FALSE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_pregenItemFlags)\r\n{\r\n\tsize_t count = 0;\r\n\tfor (Item &item : MyPlayer->InvList) {\r\n\t\tif (item.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tif (IsAnyOf(item.IDidx, IDI_GOLD, IDI_EAR))\r\n\t\t\tcontinue;\r\n\t\tconst uint16_t createInfo = item._iCreateInfo;\r\n\t\titem._iCreateInfo |= CF_PREGEN;\r\n\t\tASSERT_FALSE(TestNetPackValidation());\r\n\t\titem._iCreateInfo = createInfo;\r\n\t\tcount++;\r\n\t}\r\n\tASSERT_GT(count, 0);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_usefulItemFlags)\r\n{\r\n\tsize_t count = 0;\r\n\tfor (Item &item : MyPlayer->InvList) {\r\n\t\tif (item.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tif (IsAnyOf(item.IDidx, IDI_GOLD, IDI_EAR))\r\n\t\t\tcontinue;\r\n\t\tif ((item._iCreateInfo & CF_USEFUL) != CF_USEFUL)\r\n\t\t\tcontinue;\r\n\t\tconst uint16_t createInfo = item._iCreateInfo;\r\n\t\titem._iCreateInfo |= CF_ONLYGOOD;\r\n\t\tASSERT_FALSE(TestNetPackValidation());\r\n\t\titem._iCreateInfo = createInfo;\r\n\t\tcount++;\r\n\t}\r\n\tASSERT_GT(count, 0);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_townItemFlags)\r\n{\r\n\tsize_t count = 0;\r\n\tfor (Item &item : MyPlayer->InvList) {\r\n\t\tif (item.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tif (IsAnyOf(item.IDidx, IDI_GOLD, IDI_EAR))\r\n\t\t\tcontinue;\r\n\t\tif ((item._iCreateInfo & CF_TOWN) == 0)\r\n\t\t\tcontinue;\r\n\t\tconst uint16_t createInfo = item._iCreateInfo;\r\n\t\titem._iCreateInfo |= CF_ONLYGOOD;\r\n\t\tASSERT_FALSE(TestNetPackValidation());\r\n\t\titem._iCreateInfo = createInfo;\r\n\t\tcount++;\r\n\t}\r\n\tASSERT_GT(count, 0);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_townItemLevel)\r\n{\r\n\tsize_t boyCount = 0;\r\n\tsize_t otherCount = 0;\r\n\tfor (Item &item : MyPlayer->InvBody) {\r\n\t\tif (item.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tif (IsAnyOf(item.IDidx, IDI_GOLD, IDI_EAR))\r\n\t\t\tcontinue;\r\n\t\tif ((item._iCreateInfo & CF_TOWN) == 0)\r\n\t\t\tcontinue;\r\n\t\tconst uint16_t createInfo = item._iCreateInfo;\r\n\t\tconst bool BoyItem = (item._iCreateInfo & CF_BOY) != 0;\r\n\t\titem._iCreateInfo &= ~CF_LEVEL;\r\n\t\titem._iCreateInfo |= BoyItem ? MyPlayer->getMaxCharacterLevel() + 1 : 31;\r\n\t\tASSERT_FALSE(TestNetPackValidation());\r\n\t\titem._iCreateInfo = createInfo;\r\n\r\n\t\tsize_t &count = BoyItem ? boyCount : otherCount;\r\n\t\tcount++;\r\n\t}\r\n\tASSERT_GT(boyCount, 0);\r\n\tASSERT_GT(otherCount, 0);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_uniqueMonsterItemLevel)\r\n{\r\n\tsize_t count = 0;\r\n\tfor (Item &item : MyPlayer->InvList) {\r\n\t\tif (item.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tif (IsAnyOf(item.IDidx, IDI_GOLD, IDI_EAR))\r\n\t\t\tcontinue;\r\n\t\tif ((item._iCreateInfo & CF_USEFUL) != CF_UPER15)\r\n\t\t\tcontinue;\r\n\t\tconst uint16_t createInfo = item._iCreateInfo;\r\n\t\titem._iCreateInfo &= ~CF_LEVEL;\r\n\t\titem._iCreateInfo |= 31;\r\n\t\tASSERT_FALSE(TestNetPackValidation());\r\n\t\titem._iCreateInfo = createInfo;\r\n\t\tcount++;\r\n\t}\r\n\tASSERT_GT(count, 0);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n}\r\n\r\nTEST_F(NetPackTest, UnPackNetPlayer_invalid_monsterItemLevel)\r\n{\r\n\tsize_t count = 0;\r\n\tfor (Item &item : MyPlayer->InvBody) {\r\n\t\tif (item.isEmpty())\r\n\t\t\tcontinue;\r\n\t\tif (IsAnyOf(item.IDidx, IDI_GOLD, IDI_EAR))\r\n\t\t\tcontinue;\r\n\t\tif ((item._iCreateInfo & CF_TOWN) != 0)\r\n\t\t\tcontinue;\r\n\t\tif ((item._iCreateInfo & CF_USEFUL) == CF_UPER15)\r\n\t\t\tcontinue;\r\n\t\tconst uint16_t createInfo = item._iCreateInfo;\r\n\t\titem._iCreateInfo &= ~CF_LEVEL;\r\n\t\titem._iCreateInfo |= 31;\r\n\t\tASSERT_FALSE(TestNetPackValidation());\r\n\t\titem._iCreateInfo = createInfo;\r\n\t\tcount++;\r\n\t}\r\n\tASSERT_GT(count, 0);\r\n\tASSERT_TRUE(TestNetPackValidation());\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/palette_blending_benchmark.cpp",
    "content": "#include \"utils/palette_blending.hpp\"\r\n\r\n#include <array>\r\n#include <cstdint>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <benchmark/benchmark.h>\r\n\r\n#include \"utils/palette_kd_tree.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nvoid GeneratePalette(SDL_Color palette[256])\r\n{\r\n\tfor (unsigned j = 0; j < 4; ++j) {\r\n\t\tfor (unsigned i = 0; i < 64; ++i) {\r\n\t\t\tpalette[j * 64 + i].r = i * std::max(j, 1U);\r\n\t\t\tpalette[j * 64 + i].g = i * j;\r\n\t\t\tpalette[j * 64 + i].b = i * 2;\r\n#ifndef USE_SDL1\r\n\t\t\tpalette[j * 64 + i].a = SDL_ALPHA_OPAQUE;\r\n#endif\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid BM_GenerateBlendedLookupTable(benchmark::State &state)\r\n{\r\n\tstd::array<SDL_Color, 256> palette;\r\n\tGeneratePalette(palette.data());\r\n\tfor (auto _ : state) {\r\n\t\tGenerateBlendedLookupTable(palette.data());\r\n\t\tint result = paletteTransparencyLookup[17][98];\r\n\t\tbenchmark::DoNotOptimize(result);\r\n\t}\r\n}\r\n\r\nvoid BM_BuildTree(benchmark::State &state)\r\n{\r\n\tstd::array<SDL_Color, 256> palette;\r\n\tGeneratePalette(palette.data());\r\n\r\n\tfor (auto _ : state) {\r\n\t\tPaletteKdTree tree(palette.data(), -1, -1);\r\n\t\tbenchmark::DoNotOptimize(tree);\r\n\t}\r\n}\r\n\r\nvoid BM_FindNearestNeighbor(benchmark::State &state)\r\n{\r\n\tstd::array<SDL_Color, 256> palette;\r\n\tGeneratePalette(palette.data());\r\n\tconst PaletteKdTree tree(palette.data(), -1, -1);\r\n\r\n\tfor (auto _ : state) {\r\n\t\tfor (int r = 0; r < 256; ++r) {\r\n\t\t\tfor (int g = 0; g < 256; ++g) {\r\n\t\t\t\tfor (int b = 0; b < 256; ++b) {\r\n\t\t\t\t\tuint8_t result = tree.findNearestNeighbor({ static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b) });\r\n\t\t\t\t\tbenchmark::DoNotOptimize(result);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tstate.SetItemsProcessed(state.iterations() * 256 * 256 * 256);\r\n}\r\n\r\nBENCHMARK(BM_GenerateBlendedLookupTable);\r\nBENCHMARK(BM_BuildTree);\r\nBENCHMARK(BM_FindNearestNeighbor);\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/palette_blending_test.cpp",
    "content": "#include \"utils/palette_blending.hpp\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <iostream>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_pixels.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"utils/str_cat.hpp\"\r\n\r\nvoid PrintTo(const SDL_Color &color, std::ostream *os)\r\n{\r\n\t*os << \"(\"\r\n\t    << static_cast<int>(color.r) << \", \"\r\n\t    << static_cast<int>(color.g) << \", \"\r\n\t    << static_cast<int>(color.b) << \")\";\r\n}\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nMATCHER_P3(ColorIs, r, g, b,\r\n    StrCat(negation ? \"isn't\" : \"is\", \" (\", r, \", \", g, \", \", b, \")\"))\r\n{\r\n\treturn arg.r == r && arg.g == g && arg.b == b;\r\n}\r\n\r\nvoid GeneratePalette(SDL_Color palette[256])\r\n{\r\n\tfor (unsigned j = 0; j < 4; ++j) {\r\n\t\tfor (unsigned i = 0; i < 64; ++i) {\r\n\t\t\tpalette[j * 64 + i].r = i * std::max(j, 1U);\r\n\t\t\tpalette[j * 64 + i].g = i * j;\r\n\t\t\tpalette[j * 64 + i].b = i * 2;\r\n#ifndef USE_SDL1\r\n\t\t\tpalette[j * 64 + i].a = SDL_ALPHA_OPAQUE;\r\n#endif\r\n\t\t}\r\n\t}\r\n}\r\n\r\nTEST(GenerateBlendedLookupTableTest, BasicTest)\r\n{\r\n\tstd::array<SDL_Color, 256> palette;\r\n\tGeneratePalette(palette.data());\r\n\r\n\tGenerateBlendedLookupTable(palette.data());\r\n\r\n\tEXPECT_EQ(paletteTransparencyLookup[100][100], 100);\r\n\r\n\tEXPECT_THAT(palette[17], ColorIs(17, 0, 34));\r\n\tEXPECT_THAT(palette[150], ColorIs(44, 44, 44));\r\n\tEXPECT_THAT(palette[86], ColorIs(22, 22, 44));\r\n\tEXPECT_EQ(paletteTransparencyLookup[17][150], 86);\r\n\tEXPECT_EQ(paletteTransparencyLookup[150][17], 86);\r\n\r\n\tEXPECT_THAT(palette[27], ColorIs(27, 0, 54));\r\n\tEXPECT_THAT(palette[130], ColorIs(4, 4, 4));\r\n\tEXPECT_THAT(palette[15], ColorIs(15, 0, 30));\r\n\tEXPECT_EQ(paletteTransparencyLookup[27][130], 15);\r\n\tEXPECT_EQ(paletteTransparencyLookup[130][27], 15);\r\n\r\n\tEXPECT_THAT(palette[0], ColorIs(0, 0, 0));\r\n\tEXPECT_THAT(palette[100], ColorIs(36, 36, 72));\r\n\tEXPECT_THAT(palette[82], ColorIs(18, 18, 36));\r\n\tEXPECT_EQ(paletteTransparencyLookup[0][100], 82);\r\n\tEXPECT_EQ(paletteTransparencyLookup[100][0], 82);\r\n\r\n\tEXPECT_THAT(palette[0], ColorIs(0, 0, 0));\r\n\tEXPECT_THAT(palette[200], ColorIs(24, 24, 16));\r\n\tEXPECT_THAT(palette[196], ColorIs(12, 12, 8));\r\n\tEXPECT_EQ(paletteTransparencyLookup[0][200], 196);\r\n\tEXPECT_EQ(paletteTransparencyLookup[200][0], 196);\r\n\r\n#if DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT\r\n\tEXPECT_EQ(paletteTransparencyLookupBlack16[100 | (100 << 8)], 82 | (82 << 8));\r\n\tEXPECT_EQ(paletteTransparencyLookupBlack16[100 | (200 << 8)], 82 | (196 << 8));\r\n#endif\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/parse_int_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"utils/parse_int.hpp\"\r\n\r\nnamespace devilution {\r\nTEST(ParseIntTest, ParseInt)\r\n{\r\n\tParseIntResult<int> result = ParseInt<int>(\"\");\r\n\tASSERT_FALSE(result.has_value());\r\n\tEXPECT_EQ(result.error(), ParseIntError::ParseError);\r\n\r\n\tresult = ParseInt<int>(\"abcd\");\r\n\tASSERT_FALSE(result.has_value());\r\n\tEXPECT_EQ(result.error(), ParseIntError::ParseError);\r\n\r\n\tresult = ParseInt<int>(\"12\");\r\n\tASSERT_TRUE(result.has_value());\r\n\tEXPECT_EQ(result.value(), 12);\r\n\r\n\tresult = ParseInt<int>((\"99999999\"), -5, 100);\r\n\tASSERT_FALSE(result.has_value());\r\n\tEXPECT_EQ(result.error(), ParseIntError::OutOfRange);\r\n\r\n\tParseIntResult<int8_t> shortResult = ParseInt<int8_t>((\"99999999\"));\r\n\tASSERT_FALSE(shortResult.has_value());\r\n\tEXPECT_EQ(shortResult.error(), ParseIntError::OutOfRange);\r\n}\r\n\r\nTEST(ParseIntTest, ParseFixed6Fraction)\r\n{\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"\"), 0);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"0\"), 0);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"00781249\"), 0);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"0078125\"), 1);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"015625\"), 1);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"03125\"), 2);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"046875\"), 3);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"0625\"), 4);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"078125\"), 5);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"09375\"), 6);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"109375\"), 7);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"125\"), 8);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"140625\"), 9);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"15625\"), 10);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"171875\"), 11);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"1875\"), 12);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"203125\"), 13);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"21875\"), 14);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"234375\"), 15);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"25\"), 16);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"265625\"), 17);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"28125\"), 18);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"296875\"), 19);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"3125\"), 20);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"328125\"), 21);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"34375\"), 22);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"359375\"), 23);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"375\"), 24);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"390625\"), 25);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"40625\"), 26);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"421875\"), 27);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"4375\"), 28);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"453125\"), 29);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"46875\"), 30);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"484375\"), 31);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"5\"), 32);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"515625\"), 33);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"53125\"), 34);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"546875\"), 35);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"5625\"), 36);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"578125\"), 37);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"59375\"), 38);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"609375\"), 39);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"625\"), 40);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"640625\"), 41);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"65625\"), 42);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"671875\"), 43);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"6875\"), 44);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"703125\"), 45);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"71875\"), 46);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"734375\"), 47);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"75\"), 48);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"765625\"), 49);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"78125\"), 50);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"796875\"), 51);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"8125\"), 52);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"828125\"), 53);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"84375\"), 54);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"859375\"), 55);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"875\"), 56);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"890625\"), 57);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"90625\"), 58);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"921875\"), 59);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"9375\"), 60);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"953125\"), 61);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"96875\"), 62);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"984375\"), 63);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"99218749\"), 63);\r\n\tEXPECT_EQ(ParseFixed6Fraction(\"9921875\"), 64);\r\n}\r\n\r\nTEST(ParseInt, ParseFixed6)\r\n{\r\n\tParseIntResult<int> result = ParseFixed6<int>(\"\");\r\n\tASSERT_FALSE(result.has_value()) << \"Empty strings are not valid fixed point values.\";\r\n\tEXPECT_EQ(result.error(), ParseIntError::ParseError) << \"ParseFixed6 should give a ParseError code when parsing an empty string.\";\r\n\r\n\tresult = ParseFixed6<int>(\"abcd\");\r\n\tASSERT_FALSE(result.has_value()) << \"Non-numeric strings should not be parsed as a fixed-point value.\";\r\n\tEXPECT_EQ(result.error(), ParseIntError::ParseError) << \"ParseFixed6 should give a ParseError code when parsing a non-numeric string.\";\r\n\r\n\tresult = ParseFixed6<int>(\".\");\r\n\tASSERT_FALSE(result.has_value()) << \"To match std::from_chars ParseFixed6 should fail to parse a decimal string with no digits.\";\r\n\tEXPECT_EQ(result.error(), ParseIntError::ParseError) << \"Decimal strings with no digits are reported as ParseError codes.\";\r\n\r\n\tresult = ParseFixed6<int>(\"1.\");\r\n\tASSERT_TRUE(result.has_value()) << \"A trailing decimal point is permitted for fixed point values\";\r\n\tEXPECT_EQ(result.value(), 1 << 6);\r\n\r\n\tresult = ParseFixed6<int>(\".5\");\r\n\tASSERT_TRUE(result.has_value()) << \"A fixed point value with no integer part is accepted\";\r\n\tEXPECT_EQ(result.value(), 32);\r\n\r\n\tconst std::string_view badString { \"-.\" };\r\n\tconst char *endOfParse = nullptr;\r\n\tresult = ParseFixed6<int>(badString, &endOfParse);\r\n\tASSERT_FALSE(result.has_value()) << \"To match std::from_chars ParseFixed6 should fail to parse a decimal string with no digits, even if it starts with a minus sign.\";\r\n\tEXPECT_EQ(result.error(), ParseIntError::ParseError) << \"Decimal strings with no digits are reported as ParseError codes.\";\r\n\tEXPECT_EQ(endOfParse, badString.data()) << \"Failed fixed point parsing should set the end pointer to match the start of the string even though it read multiple characters\";\r\n\r\n\tresult = ParseFixed6<int>(\"-1.\");\r\n\tASSERT_TRUE(result.has_value()) << \"negative fixed point values are handled when reading into signed types\";\r\n\tEXPECT_EQ(result.value(), -1 << 6);\r\n\r\n\tresult = ParseFixed6<int>(\"-1.25\");\r\n\tASSERT_TRUE(result.has_value()) << \"negative fixed point values are handled when reading into signed types\";\r\n\tEXPECT_EQ(result.value(), -((1 << 6) + 16)) << \"and the fraction part is combined with the integer part respecting the sign\";\r\n\r\n\tresult = ParseFixed6<int>(\"-.25\");\r\n\tASSERT_TRUE(result.has_value()) << \"negative fixed point values with no integer digits are handled when reading into signed types\";\r\n\tEXPECT_EQ(result.value(), -16) << \"and the fraction part is used respecting the sign\";\r\n\r\n\tresult = ParseFixed6<int>(\"-0.25\");\r\n\tASSERT_TRUE(result.has_value()) << \"negative fixed point values with an explicit -0 integer part are handled when reading into signed types\";\r\n\tEXPECT_EQ(result.value(), -16) << \"and the fraction part is used respecting the sign\";\r\n\r\n\tParseIntResult<unsigned> unsignedResult = ParseFixed6<unsigned>(\"-1.\");\r\n\tASSERT_FALSE(unsignedResult.has_value()) << \"negative fixed point values are not permitted when reading into unsigned types\";\r\n\tEXPECT_EQ(unsignedResult.error(), ParseIntError::ParseError) << \"Attempting to parse a negative value into an unsigned type is a ParseError, not an OutOfRange value\";\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/path_benchmark.cpp",
    "content": "#include <cstddef>\r\n#include <cstdint>\r\n\r\n#include <benchmark/benchmark.h>\r\n#include <utility>\r\n\r\n#include \"engine/path.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/points_in_rectangle_range.hpp\"\r\n#include \"engine/size.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nstruct Map {\r\n\tSize size;\r\n\tconst char *data;\r\n\tchar operator[](const Point &p) const { return data[p.y * size.width + p.x]; }\r\n};\r\n\r\nstd::pair<Point, Point> FindStartDest(const Map &m)\r\n{\r\n\tPoint start, dest;\r\n\tfor (const Point p : PointsInRectangle(Rectangle(Point { 0, 0 }, m.size))) {\r\n\t\tswitch (m[p]) {\r\n\t\tcase 'S':\r\n\t\t\tstart = p;\r\n\t\t\tbreak;\r\n\t\tcase 'E':\r\n\t\t\tdest = p;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn { start, dest };\r\n}\r\n\r\nvoid BenchmarkMap(const Map &map, benchmark::State &state)\r\n{\r\n\tconst auto [start, dest] = FindStartDest(map);\r\n\tconst auto posOk = /*posOk=*/[&map](Point p) { return map[p] != '#'; };\r\n\tconstexpr size_t MaxPathLength = 25;\r\n\tfor (auto _ : state) {\r\n\t\tint8_t path[MaxPathLength];\r\n\t\tint result = FindPath(/*canStep=*/[](Point, Point) { return true; },\r\n\t\t    posOk, start, dest, path, MaxPathLength);\r\n\t\tbenchmark::DoNotOptimize(result);\r\n\t}\r\n}\r\n\r\nvoid BM_SinglePath(benchmark::State &state)\r\n{\r\n\tBenchmarkMap(\r\n\t    Map {\r\n\t        Size { 15, 15 },\r\n\t        \"###############\"\r\n\t        \"#...#...#.....#\"\r\n\t        \"#.#.#.#.#.###.#\"\r\n\t        \"#S#...#.#.#...#\"\r\n\t        \"#######.#.#.###\"\r\n\t        \"##...##.#.#E..#\"\r\n\t        \"#######.#.###.#\"\r\n\t        \"###...#...#...#\"\r\n\t        \"###.#######.###\"\r\n\t        \"#...###...#...#\"\r\n\t        \"#.#####.#.###.#\"\r\n\t        \"#.#...#.#.#...#\"\r\n\t        \"#.#.#.#.#.#.###\"\r\n\t        \"#...#...#...###\"\r\n\t        \"###############\" },\r\n\t    state);\r\n}\r\n\r\nvoid BM_Bridges(benchmark::State &state)\r\n{\r\n\tBenchmarkMap(\r\n\t    Map {\r\n\t        Size { 15, 15 },\r\n\t        \"###############\"\r\n\t        \"#.S...........#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"############.##\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"###.###########\"\r\n\t        \"#.....E.......#\"\r\n\t        \"###############\" },\r\n\t    state);\r\n}\r\n\r\nvoid BM_NoPath(benchmark::State &state)\r\n{\r\n\tBenchmarkMap(\r\n\t    Map {\r\n\t        Size { 15, 15 },\r\n\t        \"###############\"\r\n\t        \"#.S...........#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"#.............#\"\r\n\t        \"###############\"\r\n\t        \"#.....E.......#\"\r\n\t        \"###############\" },\r\n\t    state);\r\n}\r\n\r\nvoid BM_NoPathBig(benchmark::State &state)\r\n{\r\n\tBenchmarkMap(\r\n\t    Map {\r\n\t        Size { 30, 30 },\r\n\t        \"##############################\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#............................#\"\r\n\t        \"#.....S......................#\"\r\n\t        \"##############################\"\r\n\t        \"#.....E......................#\"\r\n\t        \"##############################\" },\r\n\t    state);\r\n}\r\n\r\nBENCHMARK(BM_SinglePath);\r\nBENCHMARK(BM_Bridges);\r\nBENCHMARK(BM_NoPath);\r\nBENCHMARK(BM_NoPathBig);\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/path_test.cpp",
    "content": "#include \"engine/path.h\"\r\n\r\n#include <algorithm>\r\n#include <array>\r\n#include <cstddef>\r\n#include <span>\r\n\r\n#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"engine/direction.hpp\"\r\n#include \"utils/algorithm/container.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nextern int TestPathGetHeuristicCost(Point startPosition, Point destinationPosition);\r\n\r\nnamespace {\r\n\r\nusing ::testing::ElementsAreArray;\r\n\r\nTEST(PathTest, Heuristics)\r\n{\r\n\tconstexpr Point source { 25, 32 };\r\n\tPoint destination = source;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), 0) << \"Wrong cost for travelling to the same tile\";\r\n\r\n\tdestination = source + Direction::NorthEast;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathAxisAlignedStepCost) << \"Wrong cost for travelling to horizontal/vertical adjacent tile\";\r\n\tdestination = source + Direction::SouthEast;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathAxisAlignedStepCost) << \"Wrong cost for travelling to horizontal/vertical adjacent tile\";\r\n\tdestination = source + Direction::SouthWest;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathAxisAlignedStepCost) << \"Wrong cost for travelling to horizontal/vertical adjacent tile\";\r\n\tdestination = source + Direction::NorthWest;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathAxisAlignedStepCost) << \"Wrong cost for travelling to horizontal/vertical adjacent tile\";\r\n\r\n\tdestination = source + Direction::North;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathDiagonalStepCost) << \"Wrong cost for travelling to diagonally adjacent tile\";\r\n\tdestination = source + Direction::East;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathDiagonalStepCost) << \"Wrong cost for travelling to diagonally adjacent tile\";\r\n\tdestination = source + Direction::South;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathDiagonalStepCost) << \"Wrong cost for travelling to diagonally adjacent tile\";\r\n\tdestination = source + Direction::West;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathDiagonalStepCost) << \"Wrong cost for travelling to diagonally adjacent tile\";\r\n\tdestination = source + Direction::SouthWest + Direction::SouthEast; // Effectively the same as Direction::South\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathDiagonalStepCost) << \"Wrong cost for travelling to diagonally adjacent tile\";\r\n\r\n\tdestination = source + Direction::NorthEast + Direction::North;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), PathAxisAlignedStepCost + PathDiagonalStepCost) << \"Wrong cost for travelling to a { 2, 1 } offset\";\r\n\tdestination = source + Direction::SouthEast + Direction::SouthEast;\r\n\tEXPECT_EQ(TestPathGetHeuristicCost(source, destination), 2 * PathAxisAlignedStepCost) << \"Wrong cost for travelling to a { 2, 0 } offset\";\r\n}\r\n\r\n// These symbols are in terms of coordinates (not in terms of on-screen direction).\r\n// -1, -1 is top-left.\r\nenum class Dir {\r\n\tNone,\r\n\tUp,\r\n\tLeft,\r\n\tRight,\r\n\tDown,\r\n\tUpLeft,\r\n\tUpRight,\r\n\tDownRight,\r\n\tDownLeft\r\n};\r\nstd::array<std::string_view, 9> DirSymbols = { \"∅\", \"↑\", \"←\", \"→\", \"↓\", \"↖\", \"↗\", \"↘\", \"↙\" };\r\n\r\nstd::ostream &operator<<(std::ostream &os, Dir dir)\r\n{\r\n\treturn os << DirSymbols[static_cast<size_t>(dir)];\r\n}\r\n\r\nstd::vector<Dir> ToSyms(std::span<const std::string> strings)\r\n{\r\n\tstd::vector<Dir> result;\r\n\tresult.reserve(strings.size());\r\n\tfor (const std::string &str : strings)\r\n\t\tresult.emplace_back(static_cast<Dir>(std::distance(DirSymbols.begin(), c_find(DirSymbols, str))));\r\n\treturn result;\r\n}\r\n\r\nstd::vector<Dir> ToSyms(std::span<const int8_t> indices)\r\n{\r\n\tstd::vector<Dir> result;\r\n\tresult.reserve(indices.size());\r\n\tfor (const int8_t idx : indices)\r\n\t\tresult.emplace_back(static_cast<Dir>(idx));\r\n\treturn result;\r\n}\r\n\r\nvoid CheckPath(Point startPosition, Point destinationPosition, std::vector<std::string> expectedSteps)\r\n{\r\n\t// Restrict tests to the longest possible path length in vanilla Diablo\r\n\tconstexpr size_t MaxPathLength = 24;\r\n\tint8_t pathSteps[MaxPathLength];\r\n\tauto pathLength = FindPath(\r\n\t    /*canStep=*/[](Point, Point) { return true; },\r\n\t    /*posOk=*/[](Point) { return true; },\r\n\t    startPosition, destinationPosition, pathSteps, MaxPathLength);\r\n\tEXPECT_THAT(ToSyms(std::span<const int8_t>(pathSteps, pathLength)), ElementsAreArray(ToSyms(expectedSteps)))\r\n\t    << \"Path steps differs from expectation for a path from \"\r\n\t    << startPosition << \" to \" << destinationPosition;\r\n}\r\n\r\nTEST(PathTest, FindPathToSelf)\r\n{\r\n\tCheckPath({ 8, 8 }, { 8, 8 }, {});\r\n}\r\n\r\nTEST(PathTest, FindPathTwoStepsUp)\r\n{\r\n\tCheckPath({ 8, 8 }, { 8, 6 }, { \"↑\", \"↑\" });\r\n}\r\n\r\nTEST(PathTest, FindPathTwoStepsLeft)\r\n{\r\n\tCheckPath({ 8, 8 }, { 6, 8 }, { \"←\", \"←\" });\r\n}\r\n\r\nTEST(PathTest, FindPathTwoStepsRight)\r\n{\r\n\tCheckPath({ 8, 8 }, { 10, 8 }, { \"→\", \"→\" });\r\n}\r\n\r\nTEST(PathTest, FindPathTwoStepsDown)\r\n{\r\n\tCheckPath({ 8, 8 }, { 8, 10 }, { \"↓\", \"↓\" });\r\n}\r\n\r\nTEST(PathTest, FindPathDiagonalsFirst3Left2Up)\r\n{\r\n\t// Pathing biases along diagonals and the diagonal steps will always be first\r\n\tCheckPath({ 8, 8 }, { 5, 6 }, { \"↖\", \"↖\", \"←\" });\r\n}\r\n\r\nTEST(PathTest, FindPathDiagonalsFirst4Left4Up)\r\n{\r\n\tCheckPath({ 8, 8 }, { 4, 4 }, { \"↖\", \"↖\", \"↖\", \"↖\" });\r\n}\r\n\r\nTEST(PathTest, FindPathDiagonalsFirst2Right4Down)\r\n{\r\n\tCheckPath({ 8, 8 }, { 10, 12 }, { \"↘\", \"↘\", \"↓\", \"↓\" });\r\n}\r\n\r\nTEST(PathTest, FindPathDiagonalsFirst4Right12Down)\r\n{\r\n\tCheckPath({ 8, 8 }, { 12, 20 }, { \"↘\", \"↘\", \"↘\", \"↘\", \"↓\", \"↓\", \"↓\", \"↓\", \"↓\", \"↓\", \"↓\", \"↓\" });\r\n}\r\n\r\nTEST(PathTest, LongPaths)\r\n{\r\n\t// Starting from the middle of the world and trying to path to a border exceeds the maximum path size\r\n\tCheckPath({ 56, 56 }, { 0, 0 }, {});\r\n\r\n\t// Longest possible path used to be 24 steps meaning tiles 24 units away are reachable\r\n\tconst Point startingPosition { 56, 56 };\r\n\tCheckPath(startingPosition, startingPosition + Displacement { 24, 24 }, std::vector<std::string>(24, \"↘\"));\r\n\r\n\t// But trying to navigate 25 units fails\r\n\tCheckPath(startingPosition, startingPosition + Displacement { 25, 25 }, {});\r\n}\r\n\r\nTEST(PathTest, FindClosest)\r\n{\r\n\t{\r\n\t\tstd::array<std::array<int, 101>, 101> searchedTiles {};\r\n\r\n\t\tconst std::optional<Point> nearPosition = FindClosestValidPosition(\r\n\t\t    [&searchedTiles](Point testPosition) {\r\n\t\t\t    searchedTiles[testPosition.x][testPosition.y]++;\r\n\t\t\t    return false;\r\n\t\t    },\r\n\t\t    { 50, 50 }, 0, 50);\r\n\r\n\t\tEXPECT_FALSE(nearPosition) << \"Searching with no valid tiles should return an empty optional\";\r\n\r\n\t\tfor (size_t x = 0; x < searchedTiles.size(); x++) {\r\n\t\t\tfor (size_t y = 0; y < searchedTiles[x].size(); y++) {\r\n\t\t\t\tif ((x == 0 || x == 100) && (y == 0 || y == 100)) {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 0) << \"Extreme corners should be skipped due to the inset/rounded search space\";\r\n\t\t\t\t} else {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 1) << \"Position \" << x << \" \" << y << \" should have been searched exactly once\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t{\r\n\t\tstd::array<std::array<int, 5>, 5> searchedTiles {};\r\n\r\n\t\tconst std::optional<Point> nearPosition = FindClosestValidPosition(\r\n\t\t    [&searchedTiles](Point testPosition) {\r\n\t\t\t    searchedTiles[testPosition.x][testPosition.y]++;\r\n\t\t\t    return false;\r\n\t\t    },\r\n\t\t    { 2, 2 }, 1, 2);\r\n\r\n\t\tEXPECT_FALSE(nearPosition) << \"Still shouldn't find a valid position with no valid tiles\";\r\n\r\n\t\tfor (size_t x = 0; x < searchedTiles.size(); x++) {\r\n\t\t\tfor (size_t y = 0; y < searchedTiles[x].size(); y++) {\r\n\t\t\t\tif (x == 2 && y == 2) {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 0) << \"The starting tile should be skipped with a min radius of 1\";\r\n\t\t\t\t} else if ((x == 0 || x == 4) && (y == 0 || y == 4)) {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 0) << \"Corners should be skipped\";\r\n\t\t\t\t} else {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 1) << \"All tiles in range should be searched exactly once\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t{\r\n\t\tstd::array<std::array<int, 3>, 3> searchedTiles {};\r\n\r\n\t\tconst std::optional<Point> nearPosition = FindClosestValidPosition(\r\n\t\t    [&searchedTiles](Point testPosition) {\r\n\t\t\t    searchedTiles[testPosition.x][testPosition.y]++;\r\n\t\t\t    return false;\r\n\t\t    },\r\n\t\t    { 1, 1 }, 0, 0);\r\n\r\n\t\tEXPECT_FALSE(nearPosition) << \"Searching with no valid tiles should return an empty optional\";\r\n\r\n\t\tfor (size_t x = 0; x < searchedTiles.size(); x++) {\r\n\t\t\tfor (size_t y = 0; y < searchedTiles[x].size(); y++) {\r\n\t\t\t\tif (x == 1 && y == 1) {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 1) << \"Only the starting tile should be searched with max radius 0\";\r\n\t\t\t\t} else {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 0) << \"Position \" << x << \" \" << y << \" should not have been searched\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tstd::array<std::array<int, 7>, 7> searchedTiles {};\r\n\r\n\t\tconst std::optional<Point> nearPosition = FindClosestValidPosition(\r\n\t\t    [&searchedTiles](Point testPosition) {\r\n\t\t\t    searchedTiles[testPosition.x][testPosition.y]++;\r\n\t\t\t    return false;\r\n\t\t    },\r\n\t\t    { 3, 3 }, 3, 3);\r\n\r\n\t\tEXPECT_FALSE(nearPosition) << \"Searching with no valid tiles should return an empty optional\";\r\n\r\n\t\tfor (size_t x = 0; x < searchedTiles.size(); x++) {\r\n\t\t\tfor (size_t y = 0; y < searchedTiles[x].size(); y++) {\r\n\t\t\t\tif (((x == 1 || x == 5) && (y == 1 || y == 5))  // inset corners\r\n\t\t\t\t    || ((x == 0 || x == 6) && y != 0 && y != 6) // left/right sides\r\n\t\t\t\t    || (x != 0 && x != 6 && (y == 0 || y == 6)) // top/bottom sides\r\n\t\t\t\t) {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 1) << \"Searching with a fixed radius should make a square with inset corners\";\r\n\t\t\t\t} else {\r\n\t\t\t\t\tEXPECT_EQ(searchedTiles[x][y], 0) << \"Position \" << x << \" \" << y << \" should not have been searched\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t{\r\n\t\tstd::optional<Point> nearPosition = FindClosestValidPosition(\r\n\t\t    [](Point testPosition) {\r\n\t\t\t    return true;\r\n\t\t    },\r\n\t\t    { 50, 50 }, 21, 50);\r\n\r\n\t\tEXPECT_EQ(*nearPosition, (Point { 50, 50 } + Displacement { 0, 21 })) << \"First candidate position with a minimum radius should be at {0, +y}\";\r\n\t}\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/player_test.cpp",
    "content": "#include \"player_test.h\"\r\n\r\n#include <gtest/gtest.h>\r\n\r\n#include \"cursor.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"init.hpp\"\r\n#include \"tables/playerdat.hpp\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace devilution {\r\nextern bool TestPlayerDoGotHit(Player &player);\r\n}\r\n\r\nint RunBlockTest(int frames, ItemSpecialEffect flags)\r\n{\r\n\tdevilution::Player &player = Players[0];\r\n\r\n\tplayer._pHFrames = frames;\r\n\tplayer._pIFlags = flags;\r\n\t// StartPlrHit compares damage (a 6 bit fixed point value) to character level to determine if the player shrugs off the hit.\r\n\t// We don't initialise player so this comparison can't be relied on, instead we use forcehit to ensure the player enters hit mode\r\n\tStartPlrHit(player, 0, true);\r\n\r\n\tint i = 1;\r\n\tfor (; i < 100; i++) {\r\n\t\tTestPlayerDoGotHit(player);\r\n\t\tif (player._pmode != PM_GOTHIT)\r\n\t\t\tbreak;\r\n\t\tplayer.AnimInfo.currentFrame++;\r\n\t}\r\n\r\n\treturn i;\r\n}\r\n\r\nconstexpr ItemSpecialEffect Normal = ItemSpecialEffect::None;\r\nconstexpr ItemSpecialEffect Balance = ItemSpecialEffect::FastHitRecovery;\r\nconstexpr ItemSpecialEffect Stability = ItemSpecialEffect::FasterHitRecovery;\r\nconstexpr ItemSpecialEffect Harmony = ItemSpecialEffect::FastestHitRecovery;\r\nconstexpr ItemSpecialEffect BalanceStability = Balance | Stability;\r\nconstexpr ItemSpecialEffect BalanceHarmony = Balance | Harmony;\r\nconstexpr ItemSpecialEffect StabilityHarmony = Stability | Harmony;\r\n\r\nconstexpr int Warrior = 6;\r\nconstexpr int Rogue = 7;\r\nconstexpr int Sorcerer = 8;\r\n\r\nstruct BlockTestCase {\r\n\tint expectedRecoveryFrame;\r\n\tint maxRecoveryFrame;\r\n\tItemSpecialEffect itemFlags;\r\n};\r\n\r\nBlockTestCase BlockData[] = {\r\n\t{ 6, Warrior, Normal },\r\n\t{ 7, Rogue, Normal },\r\n\t{ 8, Sorcerer, Normal },\r\n\r\n\t{ 5, Warrior, Balance },\r\n\t{ 6, Rogue, Balance },\r\n\t{ 7, Sorcerer, Balance },\r\n\r\n\t{ 4, Warrior, Stability },\r\n\t{ 5, Rogue, Stability },\r\n\t{ 6, Sorcerer, Stability },\r\n\r\n\t{ 3, Warrior, Harmony },\r\n\t{ 4, Rogue, Harmony },\r\n\t{ 5, Sorcerer, Harmony },\r\n\r\n\t{ 4, Warrior, BalanceStability },\r\n\t{ 5, Rogue, BalanceStability },\r\n\t{ 6, Sorcerer, BalanceStability },\r\n\r\n\t{ 3, Warrior, BalanceHarmony },\r\n\t{ 4, Rogue, BalanceHarmony },\r\n\t{ 5, Sorcerer, BalanceHarmony },\r\n\r\n\t{ 3, Warrior, StabilityHarmony },\r\n\t{ 4, Rogue, StabilityHarmony },\r\n\t{ 5, Sorcerer, StabilityHarmony },\r\n};\r\n\r\nTEST(Player, PM_DoGotHit)\r\n{\r\n\tLoadCoreArchives();\r\n\tLoadGameArchives();\r\n\tif (!HaveMainData()) {\r\n\t\tGTEST_SKIP() << \"MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test\";\r\n\t}\r\n\tLoadPlayerDataFiles();\r\n\r\n\tPlayers.resize(1);\r\n\tMyPlayer = &Players[0];\r\n\tfor (size_t i = 0; i < sizeof(BlockData) / sizeof(*BlockData); i++) {\r\n\t\tEXPECT_EQ(BlockData[i].expectedRecoveryFrame, RunBlockTest(BlockData[i].maxRecoveryFrame, BlockData[i].itemFlags));\r\n\t}\r\n}\r\n\r\nstatic void AssertPlayer(devilution::Player &player)\r\n{\r\n\tASSERT_EQ(CountU8(player._pSplLvl, 64), 0);\r\n\tASSERT_EQ(Count8(player.InvGrid, InventoryGridCells), 1);\r\n\tASSERT_EQ(CountItems(player.InvBody, NUM_INVLOC), 1);\r\n\tASSERT_EQ(CountItems(player.InvList, InventoryGridCells), 1);\r\n\tASSERT_EQ(CountItems(player.SpdList, MaxBeltItems), 2);\r\n\tASSERT_EQ(CountItems(&player.HoldItem, 1), 0);\r\n\r\n\tASSERT_EQ(player.position.tile.x, 0);\r\n\tASSERT_EQ(player.position.tile.y, 0);\r\n\tASSERT_EQ(player.position.future.x, 0);\r\n\tASSERT_EQ(player.position.future.y, 0);\r\n\tASSERT_EQ(player.plrlevel, 0);\r\n\tASSERT_EQ(player.destAction, 0);\r\n\tASSERT_STREQ(player._pName, \"\");\r\n\tASSERT_EQ(player._pClass, HeroClass::Rogue);\r\n\tASSERT_EQ(player._pBaseStr, 20);\r\n\tASSERT_EQ(player._pStrength, 20);\r\n\tASSERT_EQ(player._pBaseMag, 15);\r\n\tASSERT_EQ(player._pMagic, 15);\r\n\tASSERT_EQ(player._pBaseDex, 30);\r\n\tASSERT_EQ(player._pDexterity, 30);\r\n\tASSERT_EQ(player._pBaseVit, 20);\r\n\tASSERT_EQ(player._pVitality, 20);\r\n\tASSERT_EQ(player.getCharacterLevel(), 1);\r\n\tASSERT_EQ(player._pStatPts, 0);\r\n\tASSERT_EQ(player._pExperience, 0);\r\n\tASSERT_EQ(player._pGold, 100);\r\n\tASSERT_EQ(player._pMaxHPBase, 2880);\r\n\tASSERT_EQ(player._pHPBase, 2880);\r\n\tASSERT_EQ(player.getBaseToBlock(), 20);\r\n\tASSERT_EQ(player._pMaxManaBase, 1440);\r\n\tASSERT_EQ(player._pManaBase, 1440);\r\n\tASSERT_EQ(player._pMemSpells, 0);\r\n\tASSERT_EQ(player._pNumInv, 1);\r\n\tASSERT_EQ(player.wReflections, 0);\r\n\tASSERT_EQ(player.pTownWarps, 0);\r\n\tASSERT_EQ(player.pDungMsgs, 0);\r\n\tASSERT_EQ(player.pDungMsgs2, 0);\r\n\tASSERT_EQ(player.pLvlLoad, 0);\r\n\tASSERT_EQ(player.pDiabloKillLevel, 0);\r\n\tASSERT_EQ(player.pManaShield, 0);\r\n\tASSERT_EQ(player.pDamAcFlags, ItemSpecialEffectHf::None);\r\n\r\n\tASSERT_EQ(player._pmode, 0);\r\n\tASSERT_EQ(Count8(player.walkpath, MaxPathLengthPlayer), 0);\r\n\tASSERT_EQ(player.queuedSpell.spellId, SpellID::Null);\r\n\tASSERT_EQ(player.queuedSpell.spellType, SpellType::Skill);\r\n\tASSERT_EQ(player.queuedSpell.spellFrom, 0);\r\n\tASSERT_EQ(player.inventorySpell, SpellID::Null);\r\n\tASSERT_EQ(player._pRSpell, SpellID::TrapDisarm);\r\n\tASSERT_EQ(player._pRSplType, SpellType::Skill);\r\n\tASSERT_EQ(player._pSBkSpell, SpellID::Null);\r\n\tASSERT_EQ(player._pAblSpells, 134217728);\r\n\tASSERT_EQ(player._pScrlSpells, 0);\r\n\tASSERT_EQ(player._pSpellFlags, SpellFlag::None);\r\n\tASSERT_EQ(player._pBlockFlag, 0);\r\n\tASSERT_EQ(player._pLightRad, 10);\r\n\tASSERT_EQ(player._pDamageMod, 0);\r\n\tASSERT_EQ(player._pHitPoints, 2880);\r\n\tASSERT_EQ(player._pMaxHP, 2880);\r\n\tASSERT_EQ(player._pMana, 1440);\r\n\tASSERT_EQ(player._pMaxMana, 1440);\r\n\tASSERT_EQ(player.getNextExperienceThreshold(), 2000);\r\n\tASSERT_EQ(player._pMagResist, 0);\r\n\tASSERT_EQ(player._pFireResist, 0);\r\n\tASSERT_EQ(player._pLghtResist, 0);\r\n\tASSERT_EQ(CountBool(player._pLvlVisited, NUMLEVELS), 0);\r\n\tASSERT_EQ(CountBool(player._pSLvlVisited, NUMLEVELS), 0);\r\n\t// This test case uses a Rogue, starting loadout is a short bow with damage 1-4\r\n\tASSERT_EQ(player._pIMinDam, 1);\r\n\tASSERT_EQ(player._pIMaxDam, 4);\r\n\tASSERT_EQ(player._pIAC, 0);\r\n\tASSERT_EQ(player._pIBonusDam, 0);\r\n\tASSERT_EQ(player._pIBonusToHit, 0);\r\n\tASSERT_EQ(player._pIBonusAC, 0);\r\n\tASSERT_EQ(player._pIBonusDamMod, 0);\r\n\tASSERT_EQ(player._pISpells, 0);\r\n\tASSERT_EQ(player._pIFlags, ItemSpecialEffect::None);\r\n\tASSERT_EQ(player._pIGetHit, 0);\r\n\tASSERT_EQ(player._pISplLvlAdd, 0);\r\n\tASSERT_EQ(player._pIEnAc, 0);\r\n\tASSERT_EQ(player._pIFMinDam, 0);\r\n\tASSERT_EQ(player._pIFMaxDam, 0);\r\n\tASSERT_EQ(player._pILMinDam, 0);\r\n\tASSERT_EQ(player._pILMaxDam, 0);\r\n}\r\n\r\nTEST(Player, CreatePlayer)\r\n{\r\n\tLoadCoreArchives();\r\n\tLoadGameArchives();\r\n\r\n\t// The tests need spawn.mpq or diabdat.mpq\r\n\tif (!HaveMainData()) {\r\n\t\tGTEST_SKIP() << \"MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test\";\r\n\t}\r\n\r\n\tLoadPlayerDataFiles();\r\n\tLoadMonsterData();\r\n\tLoadItemData();\r\n\tPlayers.resize(1);\r\n\tCreatePlayer(Players[0], HeroClass::Rogue);\r\n\tAssertPlayer(Players[0]);\r\n}\r\n"
  },
  {
    "path": "test/player_test.h",
    "content": "/**\r\n * @file player_test.h\r\n *\r\n * Helpers for player related tests.\r\n */\r\n#pragma once\r\n\r\n#include \"items.h\"\r\n#include \"player.h\"\r\n\r\nusing namespace devilution;\r\n\r\nstatic size_t CountItems(devilution::Item *items, int n)\r\n{\r\n\treturn std::count_if(items, items + n, [](devilution::Item x) { return !x.isEmpty(); });\r\n}\r\n\r\nstatic size_t Count8(int8_t *ints, int n)\r\n{\r\n\treturn std::count_if(ints, ints + n, [](int8_t x) { return x != 0; });\r\n}\r\n\r\nstatic size_t CountU8(uint8_t *ints, int n)\r\n{\r\n\treturn std::count_if(ints, ints + n, [](uint8_t x) { return x != 0; });\r\n}\r\n\r\nstatic size_t CountBool(bool *bools, int n)\r\n{\r\n\treturn std::count_if(bools, bools + n, [](bool x) { return x; });\r\n}\r\n"
  },
  {
    "path": "test/quests_test.cpp",
    "content": "#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"quests.h\"\r\n\r\n#include \"tables/objdat.h\" // For quest IDs\r\n\r\nnamespace devilution {\r\nvoid ResetQuests()\r\n{\r\n\tfor (auto &quest : Quests)\r\n\t\tquest._qactive = QUEST_INIT;\r\n}\r\n\r\nstd::vector<quest_state> GetActiveFlagsForSlice(std::initializer_list<quest_id> ids)\r\n{\r\n\tstd::vector<quest_state> temp;\r\n\r\n\tfor (auto id : ids)\r\n\t\ttemp.push_back(Quests[id]._qactive);\r\n\r\n\treturn temp;\r\n}\r\n\r\nTEST(QuestTest, SinglePlayerBadPools)\r\n{\r\n\tResetQuests();\r\n\r\n\t// (INT_MIN >> 16) % 2 = 0, so the times when the RNG calls GenerateRnd(2) don't end up with a negative value.\r\n\tInitialiseQuestPools(1457187811, Quests);\r\n\tEXPECT_EQ(Quests[Q_SKELKING]._qactive, QUEST_NOTAVAIL) << \"Skeleton King quest is deactivated with 'bad' seed\";\r\n\tResetQuests();\r\n\r\n\t// Having this seed for level 15 requires starting a game at 1977-12-28 07:44:42 PM or 2087-02-18 10:43:02 PM\r\n\t// Given Diablo was released in 1996 and it's currently 2024 this will never have been naturally hit. It's not\r\n\t//  possible to hit this case on a pre-NT kernel windows system but it may be possible on macos or winnt?\r\n\tInitialiseQuestPools(988045466, Quests);\r\n\tEXPECT_THAT(GetActiveFlagsForSlice({ Q_BUTCHER, Q_LTBANNER, Q_GARBUD }), ::testing::Each(QUEST_INIT)) << \"All quests in pool 2 remain active with 'bad' seed\";\r\n\tResetQuests();\r\n\r\n\t// This seed can only be reached by editing a save file or modifying the game. Given quest state (including\r\n\t//  availability) is saved as part of the game state there's no vanilla compatibility concerns here.\r\n\tInitialiseQuestPools(4203210069U, Quests);\r\n\t// If we wanted to retain the behaviour that vanilla Diablo would've done we should instead deactivate\r\n\t//  Quests[QuestGroup2[-2]]. This would hit QuestGroup1[1] (Ogden's Sign), however that's already marked\r\n\t//  as unavailable with this seed due to the previous quest group's roll.\r\n\tEXPECT_EQ(Quests[Q_LTBANNER]._qactive, QUEST_NOTAVAIL) << \"Ogden's Sign should be deactivated with 'bad' seed\";\r\n\tEXPECT_EQ(Quests[Q_BLIND]._qactive, QUEST_NOTAVAIL) << \"Halls of the Blind should also be deactivated with 'bad' seed\";\r\n\tResetQuests();\r\n\r\n\t// This seed can only be reached by editing a save file or modifying the game. Given quest state (including\r\n\t//  availability) is saved as part of the game state there's no vanilla compatibility concerns here.\r\n\tInitialiseQuestPools(2557708932U, Quests);\r\n\t// If we wanted to retain the behaviour that vanilla Diablo would've done we should instead deactivate\r\n\t//  Quests[QuestGroup3[-2]]. This would hit QuestGroup2[1] (Magic Rock), however that's already marked\r\n\t//  as unavailable with this seed due to the previous quest group's roll.\r\n\tEXPECT_EQ(Quests[Q_ROCK]._qactive, QUEST_NOTAVAIL) << \"Magic Rock should be deactivated with 'bad' seed\";\r\n\tEXPECT_EQ(Quests[Q_MUSHROOM]._qactive, QUEST_NOTAVAIL) << \"Black Mushroom should also be deactivated with 'bad' seed\";\r\n\tResetQuests();\r\n\r\n\tInitialiseQuestPools(1272442071, Quests);\r\n\tEXPECT_EQ(Quests[Q_VEIL]._qactive, QUEST_NOTAVAIL) << \"Lachdan quest is deactivated with 'bad' seed\";\r\n}\r\n\r\nTEST(QuestTest, SinglePlayerGoodPools)\r\n{\r\n\tResetQuests();\r\n\r\n\tInitialiseQuestPools(509604, Quests);\r\n\tEXPECT_EQ(Quests[Q_SKELKING]._qactive, QUEST_INIT) << \"Expected Skeleton King quest to be available with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_PWATER]._qactive, QUEST_NOTAVAIL) << \"Expected Poison Water quest to be deactivated with the given seed\";\r\n\r\n\tEXPECT_EQ(Quests[Q_BUTCHER]._qactive, QUEST_INIT) << \"Expected Butcher quest to be available with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_LTBANNER]._qactive, QUEST_INIT) << \"Expected Ogden's Sign quest to be available with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_GARBUD]._qactive, QUEST_NOTAVAIL) << \"Expected Gharbad the Weak quest to be deactivated with the given seed\";\r\n\r\n\tEXPECT_EQ(Quests[Q_BLIND]._qactive, QUEST_INIT) << \"Expected Halls of the Blind quest to be available with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_ROCK]._qactive, QUEST_NOTAVAIL) << \"Expected Magic Rock quest to be deactivated with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_BLOOD]._qactive, QUEST_INIT) << \"Expected Valor quest to be available with the given seed\";\r\n\r\n\tEXPECT_EQ(Quests[Q_MUSHROOM]._qactive, QUEST_INIT) << \"Expected Black Mushroom quest to be available with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_ZHAR]._qactive, QUEST_NOTAVAIL) << \"Expected Zhar the Mad quest to be deactivated with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_ANVIL]._qactive, QUEST_INIT) << \"Expected Anvil of Fury quest to be available with the given seed\";\r\n\r\n\tEXPECT_EQ(Quests[Q_VEIL]._qactive, QUEST_NOTAVAIL) << \"Expected Lachdanan quest to be deactivated with the given seed\";\r\n\tEXPECT_EQ(Quests[Q_WARLORD]._qactive, QUEST_INIT) << \"Expected Warlord of Blood quest to be available with the given seed\";\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/random_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"engine/random.hpp\"\r\n\r\nnamespace devilution {\r\n\r\n// These tests use ASSERT_EQ as the PRNG is expected to depend on state from the last call, so one failing assertion\r\n// means the rest of the results can't be trusted.\r\nTEST(RandomTest, RandomEngineParams)\r\n{\r\n\t// The core diablo random number generator is an LCG with Borland constants.\r\n\t// This RNG must be available for network/save compatibility for things such as level generation.\r\n\r\n\tconstexpr uint32_t multiplicand = 22695477;\r\n\tconstexpr uint32_t increment = 1;\r\n\r\n\tSetRndSeed(0);\r\n\r\n\t// Starting from a seed of 0 means the multiplicand is dropped and the state advances by increment only\r\n\tASSERT_EQ(GenerateRandomNumber(), increment) << \"Increment factor is incorrect\";\r\n\r\n\t// LCGs use a formula of mult * seed + inc. Using a long form in the code to document the expected factors.\r\n\tASSERT_EQ(GenerateRandomNumber(), (multiplicand * 1) + increment) << \"Multiplicand factor is incorrect\";\r\n\r\n\t// C++11 defines the default seed for a LCG engine as 1. The ten thousandth value is commonly used for sanity checking\r\n\t// a sequence, so as we've had one round since state 1 we need to discard another 9998 values to get to the 10000th state.\r\n\t// To make off by one errors more visible test the 9999th value as well as 10000th\r\n\tDiscardRandomValues(9997);\r\n\r\n\tuint32_t expectedState = 3495122800U;\r\n\tEXPECT_EQ(GenerateRandomNumber(), expectedState) << \"Wrong engine state after 9999 invocations\";\r\n\texpectedState = 3007658545U;\r\n\tASSERT_EQ(GenerateRandomNumber(), expectedState) << \"Wrong engine state after 10000 invocations\";\r\n}\r\n\r\nTEST(RandomTest, AbsDistribution)\r\n{\r\n\t// The default distribution for RNG calls is the absolute value of the generated value interpreted as a signed int\r\n\t// This relies on undefined behaviour when called on std::numeric_limits<int_t>::min(). See C17 7.22.6.1\r\n\t// The current behaviour is this returns the same value (the most negative number of the type).\r\n\tSetRndSeed(1457187811); // yields -2147483648\r\n\tASSERT_EQ(AdvanceRndSeed(), std::numeric_limits<int32_t>::min()) << \"Invalid distribution\";\r\n\tSetRndSeed(3604671459U); // yields 0\r\n\tASSERT_EQ(AdvanceRndSeed(), 0) << \"Invalid distribution\";\r\n\r\n\tSetRndSeed(0); // yields +1\r\n\tASSERT_EQ(AdvanceRndSeed(), 1) << \"Invalid distribution\";\r\n\tSetRndSeed(2914375622U); // yields -1\r\n\tASSERT_EQ(AdvanceRndSeed(), 1) << \"Invalid distribution\";\r\n\r\n\tSetRndSeed(3604671460U); // yields +22695477\r\n\tASSERT_EQ(AdvanceRndSeed(), 22695477) << \"Invalid distribution\";\r\n\tSetRndSeed(3604671458U); // yields -22695477\r\n\tASSERT_EQ(AdvanceRndSeed(), 22695477) << \"Invalid distribution\";\r\n\r\n\tSetRndSeed(1902003768); // yields +429496729\r\n\tASSERT_EQ(AdvanceRndSeed(), 429496729) << \"Invalid distribution\";\r\n\tSetRndSeed(1012371854); // yields -429496729\r\n\tASSERT_EQ(AdvanceRndSeed(), 429496729) << \"Invalid distribution\";\r\n\r\n\tSetRndSeed(189776845); // yields +1212022642\r\n\tASSERT_EQ(AdvanceRndSeed(), 1212022642) << \"Invalid distribution\";\r\n\tSetRndSeed(2724598777U); // yields -1212022642\r\n\tASSERT_EQ(AdvanceRndSeed(), 1212022642) << \"Invalid distribution\";\r\n\r\n\tSetRndSeed(76596137); // yields +2147483646\r\n\tASSERT_EQ(AdvanceRndSeed(), 2147483646) << \"Invalid distribution\";\r\n\tSetRndSeed(2837779485U); // yields -2147483646\r\n\tASSERT_EQ(AdvanceRndSeed(), 2147483646) << \"Invalid distribution\";\r\n\r\n\tSetRndSeed(766891974); // yields +2147483647\r\n\tASSERT_EQ(AdvanceRndSeed(), 2147483647) << \"Invalid distribution\";\r\n\tSetRndSeed(2147483648U); // yields -2147483647\r\n\tASSERT_EQ(AdvanceRndSeed(), 2147483647) << \"Invalid distribution\";\r\n}\r\n\r\n// The bounded distribution function used by Diablo performs a modulo operation on the result of the AbsDistribution\r\n// tested above, with a shift operation applied before the mod when the bound is < 65535.\r\n//\r\n// The current implementation does not allow testing these operations independantly, hopefully this can be changed\r\n// with confidence from these tests.\r\n//\r\n// The result of a mod b when a is negative was implementation defined before C++11, current behaviour is to\r\n// preserve the sign of a. See C++17 [expr.mul] and C++03 TR1 [expr.mul]\r\nTEST(RandomTest, ModDistributionInvalidRange)\r\n{\r\n\t// Calling the modulo distribution with an upper bound <= 0 returns 0 without advancing the engine\r\n\tauto initialSeed = 44444444;\r\n\tSetRndSeed(initialSeed);\r\n\tEXPECT_EQ(GenerateRnd(0), 0) << \"A distribution with an upper bound of 0 must return 0\";\r\n\tEXPECT_EQ(GetLCGEngineState(), initialSeed) << \"Distribution with invalid range must not advance the engine state\";\r\n\tEXPECT_EQ(GenerateRnd(-1), 0) << \"A distribution with a negative upper bound must return 0\";\r\n\tEXPECT_EQ(GetLCGEngineState(), initialSeed) << \"Distribution with invalid range must not advance the engine state\";\r\n\tEXPECT_EQ(GenerateRnd(std::numeric_limits<int32_t>::min()), 0)\r\n\t    << \"A distribution with a negative upper bound must return 0\";\r\n\tEXPECT_EQ(GetLCGEngineState(), initialSeed) << \"Distribution with invalid range must not advance the engine state\";\r\n}\r\n\r\nTEST(RandomTest, ShiftModDistributionSingleRange)\r\n{\r\n\t// All results mod 1 = 0;\r\n\tauto initialSeed = ::testing::UnitTest::GetInstance()->random_seed();\r\n\tSetRndSeed(initialSeed);\r\n\tfor (auto i = 0; i < 100; i++)\r\n\t\tASSERT_EQ(GenerateRnd(1), 0) << \"Interval [0, 1) must return 0\";\r\n\tASSERT_NE(GetLCGEngineState(), initialSeed) << \"Interval of 1 element must still advance the engine state\";\r\n\r\n\t// Just in case -0 has a distinct representation? Shouldn't be possible but cheap to test.\r\n\tSetRndSeed(1457187811);\r\n\tASSERT_EQ(GenerateRnd(1), 0) << \"Interval [0, 1) must return 0 when AbsDistribution yields INT_MIN\";\r\n}\r\n\r\n// When called with an upper bound less than or equal to 0x7FFF this distribution function discards the low 16 bits of the output\r\n// from the default distribution by performing a shift right of 16 bits. This relies on implementation defined\r\n// behaviour for negative numbers, the expectation is shift right uses sign carry. See C++17 [expr.shift]\r\nTEST(RandomTest, ShiftModDistributionSignCarry)\r\n{\r\n\t// This distribution is used when the upper bound is a value in [1, 32768)\r\n\t// Using an upper bound of 1 means the result always maps to 0, see RandomTest_ShiftModDistributionSingleRange\r\n\r\n\t// The only negative value returned from AbsDistribution is -2147483648\r\n\t// A sign-preserving shift right of 16 bits gives a result of -32768.\r\n\t// This is greater in magnitude than the limit so always results in a division.\r\n\tSetRndSeed(1457187811); // Test mod when a division occurs\r\n\tASSERT_EQ(GenerateRnd(32767), -1) << \"Distribution must map negative numbers using sign carry shifts\";\r\n}\r\n\r\n// The Diablo LCG implementation attempts to improve the quality of generated numbers that would only use the low\r\n// bits of the LCG output but due to applying this after taking the absolute value this introduces bias. This may\r\n// be an inconsistency with the implementation in devilutionx, see the comment for RandomTest_ShiftModDistributionHighBits\r\nTEST(RandomTest, ShiftModDistributionLowBits)\r\n{\r\n\tconstexpr auto maxBound = 32767;\r\n\r\n\t// All the following seeds generate values less than 2^16, so after shifting they give a 0 value\r\n\tSetRndSeed(3604671459U); // yields 0\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 0\";\r\n\tSetRndSeed(0); // yields 1\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 1\";\r\n\tSetRndSeed(2914375622U); // yields -1\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -1\";\r\n\tSetRndSeed(538964771); // yields 64\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 64\";\r\n\tSetRndSeed(2375410851U); // yields -64\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -64\";\r\n\tSetRndSeed(1229260608); // yields 65\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 65\";\r\n\tSetRndSeed(1685115014); // yields -65\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -65\";\r\n\tSetRndSeed(1768225379); // yields 128\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 128\";\r\n\tSetRndSeed(1146150243); // yields -128\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -128\";\r\n\tSetRndSeed(1480523688); // yields 7625\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 7625\";\r\n\tSetRndSeed(1433851934); // yields -7625\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -7625\";\r\n\tSetRndSeed(2382565573U); // yields 32458\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 32458\";\r\n\tSetRndSeed(531810049); // yields -32458\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -32458\";\r\n\tSetRndSeed(1625910243); // yields 32768\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 32768\";\r\n\tSetRndSeed(1288465379); // yields -32768\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -32768\";\r\n\r\n\t// -1 from the max bound for the next two to ensure it's not due to a mod with no remainder\r\n\tSetRndSeed(2561524649U); // yields 65534\r\n\tASSERT_EQ(GenerateRnd(maxBound - 1), 0) << \"Invalid distribution when generator yields 65534\";\r\n\tSetRndSeed(352850973U); // yields -65534\r\n\tASSERT_EQ(GenerateRnd(maxBound - 1), 0) << \"Invalid distribution when generator yields -65534\";\r\n\r\n\tSetRndSeed(3251820486U); // yields 65535\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 65535\";\r\n\tSetRndSeed(3957522432U); // yields -65535\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -65535\";\r\n}\r\n\r\n// The highest value GenerateRnd can return is 32767 (0x7FFF). I suspect this is the Borland rand() implementation\r\n// Diablo appears to have reimplemented this method incorrectly as that function was implemented as the following:\r\n// uint seed = mult * seed + inc\r\n// return (seed >> 16) & 0x7FFF\r\n// i.e., no cast from unsigned to signed, no modulo when building the return value.\r\nTEST(RandomTest, ShiftModDistributionHighBits)\r\n{\r\n\tconstexpr auto maxBound = 32767;\r\n\tSetRndSeed(3267226595U); // yields 65536\r\n\tASSERT_EQ(GenerateRnd(maxBound), 1) << \"Invalid distribution when generator yields 65536\";\r\n\tSetRndSeed(3942116323U); // yields -65536\r\n\tASSERT_EQ(GenerateRnd(maxBound), 1) << \"Invalid distribution when generator yields -65536\";\r\n\tSetRndSeed(4279561187U); // yields 131072\r\n\tASSERT_EQ(GenerateRnd(maxBound), 2) << \"Invalid distribution when generator yields 131072\";\r\n\tSetRndSeed(2929781731U); // yields -131072\r\n\tASSERT_EQ(GenerateRnd(maxBound), 2) << \"Invalid distribution when generator yields -131072\";\r\n\tSetRndSeed(659483619); // yields 262144\r\n\tASSERT_EQ(GenerateRnd(maxBound), 4) << \"Invalid distribution when generator yields 262144\";\r\n\tSetRndSeed(2254892003U); // yields -262144\r\n\tASSERT_EQ(GenerateRnd(maxBound), 4) << \"Invalid distribution when generator yields -262144\";\r\n\tSetRndSeed(3604671458U); // yields 22695477\r\n\tASSERT_EQ(GenerateRnd(maxBound), 346) << \"Invalid distribution when generator yields 22695477\";\r\n\tSetRndSeed(3604671460U); // yields -22695477\r\n\tASSERT_EQ(GenerateRnd(maxBound), 346) << \"Invalid distribution when generator yields -22695477\";\r\n\tSetRndSeed(1012371854); // yields 429496729\r\n\tASSERT_EQ(GenerateRnd(maxBound), 6553) << \"Invalid distribution when generator yields 429496729\";\r\n\tSetRndSeed(1902003768); // yields -429496729\r\n\tASSERT_EQ(GenerateRnd(maxBound), 6553) << \"Invalid distribution when generator yields -429496729\";\r\n\tSetRndSeed(189776845); // yields 1212022642\r\n\tASSERT_EQ(GenerateRnd(maxBound), 18493) << \"Invalid distribution when generator yields 1212022642\";\r\n\tSetRndSeed(2724598777); // yields -1212022642\r\n\tASSERT_EQ(GenerateRnd(maxBound), 18493) << \"Invalid distribution when generator yields -1212022642\";\r\n\tSetRndSeed(76596137); // yields 2147483646\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 2147483646\";\r\n\tSetRndSeed(2837779485); // yields -2147483646\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -2147483646\";\r\n\tSetRndSeed(766891974); // yields 2147483647\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields 2147483647\";\r\n\tSetRndSeed(2147483648); // yields -2147483647\r\n\tASSERT_EQ(GenerateRnd(maxBound), 0) << \"Invalid distribution when generator yields -2147483647\";\r\n}\r\n\r\nTEST(RandomTest, ModDistributionSignPreserving)\r\n{\r\n\t// This distribution is used when the upper bound is a value in [32768, 2147483647]\r\n\r\n\t// Sign preserving modulo when no division is performed cannot be tested in isolation with the current implementation.\r\n\tSetRndSeed(1457187811);\r\n\tASSERT_EQ(GenerateRnd(32768), 0) << \"Distribution must map negative numbers using sign preserving modulo\";\r\n\tSetRndSeed(1457187811);\r\n\tASSERT_EQ(GenerateRnd(32769), -2) << \"Distribution must map negative numbers using sign preserving modulo\";\r\n\tSetRndSeed(1457187811);\r\n\tASSERT_EQ(GenerateRnd(65535), -32768) << \"Distribution must map negative numbers using sign preserving modulo\";\r\n\tSetRndSeed(1457187811);\r\n\tASSERT_EQ(GenerateRnd(std::numeric_limits<int32_t>::max()), -1)\r\n\t    << \"Distribution must map negative numbers using sign preserving modulo\";\r\n}\r\n\r\nTEST(RandomTest, NegativeReturnValues)\r\n{\r\n\t// The bug in vanilla RNG stemming from mod instead of bitmasking means that negative values are possible for\r\n\t// non-power of 2 arguments to GenerateRnd\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(3), -2) << \"Unexpected return value for a limit of 3\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(5), -3) << \"Unexpected return value for a limit of 5\";\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(6), -2) << \"Unexpected return value for a limit of 6\";\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(7), -1) << \"Unexpected return value for a limit of 7\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(11), -10) << \"Unexpected return value for a limit of 11\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(17), -9) << \"Unexpected return value for a limit of 17\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(19), -12) << \"Unexpected return value for a limit of 19\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(22), -10) << \"Unexpected return value for a limit of 22\";\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(23), -16) << \"Unexpected return value for a limit of 23\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(25), -18) << \"Unexpected return value for a limit of 25\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(27), -17) << \"Unexpected return value for a limit of 27\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(29), -27) << \"Unexpected return value for a limit of 29\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(31), -1) << \"Unexpected return value for a limit of 31\";\r\n\r\n\tfor (const int i : { 9, 10, 12, 13, 14, 15, 18, 20, 21, 24, 26, 28, 30 }) {\r\n\t\tSetRndSeed(1457187811);\r\n\t\tEXPECT_EQ(GenerateRnd(i), -8) << \"Unexpected return value for a limit of \" << i;\r\n\t}\r\n\r\n\t// The following values are/were used throughout the code\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(37), -23) << \"Unexpected return value for a limit of 37\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(38), -12) << \"Unexpected return value for a limit of 38\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\t// commonly used for dungeon megatile coordinates\r\n\tEXPECT_EQ(GenerateRnd(40), -8) << \"Unexpected return value for a limit of 40\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(41), -9) << \"Unexpected return value for a limit of 41\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\tEXPECT_EQ(GenerateRnd(52), -8) << \"Unexpected return value for a limit of 52\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\t// commonly used for dungeon tile coordinates\r\n\tEXPECT_EQ(GenerateRnd(80), -48) << \"Unexpected return value for a limit of 80\";\r\n\r\n\tSetRndSeed(1457187811);\r\n\t// commonly used for percentage rolls (typically in a context that 0 and -68 lead to the same outcome)\r\n\tEXPECT_EQ(GenerateRnd(100), -68) << \"Unexpected return value for a limit of 100\";\r\n\r\n\tfor (int i = 1; i < 32768; i *= 2) {\r\n\t\tSetRndSeed(1457187811);\r\n\t\tEXPECT_EQ(GenerateRnd(i), 0) << \"Expect powers of 2 such as \" << i << \" to cleanly divide the int_min RNG value \";\r\n\t}\r\n}\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/rectangle_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nTEST(RectangleTest, Contains_LargerSize)\r\n{\r\n\tconst RectangleOf<uint8_t> rect { { 0, 0 }, { 10, 20 } };\r\n\tEXPECT_TRUE(rect.contains(Point(9, 9)));\r\n\tEXPECT_FALSE(rect.contains(Point(-1, -1)));\r\n\tEXPECT_FALSE(rect.contains(Point(257, 257)));\r\n}\r\n\r\nTEST(RectangleTest, Contains_UnsignedRectangle_SignedPointSameSize)\r\n{\r\n\tconst RectangleOf<uint8_t> rect { { 0, 0 }, { 255, 255 } };\r\n\tEXPECT_TRUE(rect.contains(PointOf<int8_t>(5, 5)));\r\n\tEXPECT_FALSE(rect.contains(PointOf<int8_t>(-1, -1)));\r\n\tEXPECT_FALSE(rect.contains(PointOf<int8_t>(-2, -2)));\r\n}\r\n\r\nTEST(RectangleTest, Contains_SignedRectangle_UnsignedPointSameSize)\r\n{\r\n\tconst RectangleOf<int8_t> rect { { -10, -10 }, { 127, 127 } };\r\n\tEXPECT_TRUE(rect.contains(PointOf<uint8_t>(0, 0)));\r\n\tEXPECT_FALSE(rect.contains(PointOf<uint8_t>(255, 255)));\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/scrollrt_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"control/control.hpp\"\r\n#include \"diablo.h\"\r\n#include \"engine/render/scrollrt.h\"\r\n#include \"options.h\"\r\n#include \"utils/ui_fwd.h\"\r\n\r\nusing namespace devilution;\r\n\r\n// TilesInView\r\n\r\nTEST(Scroll_rt, calc_tiles_in_view_original)\r\n{\r\n\tgnScreenWidth = 640;\r\n\tgnScreenHeight = 480;\r\n\tgnViewportHeight = gnScreenHeight - 128;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tint columns = 0;\r\n\tint rows = 0;\r\n\tTilesInView(&columns, &rows);\r\n\tEXPECT_EQ(columns, 10);\r\n\tEXPECT_EQ(rows, 11);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tiles_in_view_original_zoom)\r\n{\r\n\tgnScreenWidth = 640;\r\n\tgnScreenHeight = 480;\r\n\tgnViewportHeight = gnScreenHeight - 128;\r\n\tGetOptions().Graphics.zoom.SetValue(true);\r\n\tint columns = 0;\r\n\tint rows = 0;\r\n\tTilesInView(&columns, &rows);\r\n\tEXPECT_EQ(columns, 5);\r\n\tEXPECT_EQ(rows, 6);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tiles_in_view_960_540)\r\n{\r\n\tgnScreenWidth = 960;\r\n\tgnScreenHeight = 540;\r\n\tgnViewportHeight = gnScreenHeight;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tint columns = 0;\r\n\tint rows = 0;\r\n\tTilesInView(&columns, &rows);\r\n\tEXPECT_EQ(columns, 15);\r\n\tEXPECT_EQ(rows, 17);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tiles_in_view_640_512)\r\n{\r\n\tgnScreenWidth = 640;\r\n\tgnScreenHeight = 512;\r\n\tgnViewportHeight = gnScreenHeight - 128;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tint columns = 0;\r\n\tint rows = 0;\r\n\tTilesInView(&columns, &rows);\r\n\tEXPECT_EQ(columns, 10);\r\n\tEXPECT_EQ(rows, 12);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tiles_in_view_768_480_zoom)\r\n{\r\n\tgnScreenWidth = 768;\r\n\tgnScreenHeight = 480;\r\n\tgnViewportHeight = gnScreenHeight;\r\n\tGetOptions().Graphics.zoom.SetValue(true);\r\n\tint columns = 0;\r\n\tint rows = 0;\r\n\tTilesInView(&columns, &rows);\r\n\tEXPECT_EQ(columns, 6);\r\n\tEXPECT_EQ(rows, 8);\r\n}\r\n\r\n// CalcTileOffset\r\n\r\nTEST(Scroll_rt, calc_tile_offset_original)\r\n{\r\n\tgnScreenWidth = 640;\r\n\tgnScreenHeight = 480;\r\n\tgnViewportHeight = gnScreenHeight - 128;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tint x = 0;\r\n\tint y = 0;\r\n\tCalcTileOffset(&x, &y);\r\n\tEXPECT_EQ(x, 0);\r\n\tEXPECT_EQ(y, 0);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tile_offset_original_zoom)\r\n{\r\n\tgnScreenWidth = 640;\r\n\tgnScreenHeight = 480;\r\n\tgnViewportHeight = gnScreenHeight - 128;\r\n\tGetOptions().Graphics.zoom.SetValue(true);\r\n\tint x = 0;\r\n\tint y = 0;\r\n\tCalcTileOffset(&x, &y);\r\n\tEXPECT_EQ(x, 0);\r\n\tEXPECT_EQ(y, 8);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tile_offset_960_540)\r\n{\r\n\tgnScreenWidth = 960;\r\n\tgnScreenHeight = 540;\r\n\tgnViewportHeight = gnScreenHeight;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tint x = 0;\r\n\tint y = 0;\r\n\tCalcTileOffset(&x, &y);\r\n\tEXPECT_EQ(x, 0);\r\n\tEXPECT_EQ(y, 2);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tile_offset_853_480)\r\n{\r\n\tgnScreenWidth = 853;\r\n\tgnScreenHeight = 480;\r\n\tgnViewportHeight = gnScreenHeight;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tint x = 0;\r\n\tint y = 0;\r\n\tCalcTileOffset(&x, &y);\r\n\tEXPECT_EQ(x, 21);\r\n\tEXPECT_EQ(y, 0);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tile_offset_768_480_zoom)\r\n{\r\n\tgnScreenWidth = 768;\r\n\tgnScreenHeight = 480;\r\n\tgnViewportHeight = gnScreenHeight;\r\n\tGetOptions().Graphics.zoom.SetValue(true);\r\n\tint x = 0;\r\n\tint y = 0;\r\n\tCalcTileOffset(&x, &y);\r\n\tEXPECT_EQ(x, 0);\r\n\tEXPECT_EQ(y, 8);\r\n}\r\n\r\n// RowsCoveredByPanel\r\n\r\nTEST(Scroll_rt, calc_tiles_covered_by_panel_original)\r\n{\r\n\tgnScreenWidth = 640;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tCalculatePanelAreas();\r\n\tEXPECT_EQ(RowsCoveredByPanel(), 0);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tiles_covered_by_panel_960)\r\n{\r\n\tgnScreenWidth = 960;\r\n\tGetOptions().Graphics.zoom.SetValue(false);\r\n\tCalculatePanelAreas();\r\n\tEXPECT_EQ(RowsCoveredByPanel(), 4);\r\n}\r\n\r\nTEST(Scroll_rt, calc_tiles_covered_by_panel_960_zoom)\r\n{\r\n\tgnScreenWidth = 960;\r\n\tGetOptions().Graphics.zoom.SetValue(true);\r\n\tCalculatePanelAreas();\r\n\tEXPECT_EQ(RowsCoveredByPanel(), 2);\r\n}\r\n"
  },
  {
    "path": "test/static_vector_test.cpp",
    "content": "#include <cstdlib>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"engine/random.hpp\"\r\n#include \"utils/static_vector.hpp\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nconstexpr int MAX_SIZE = 32;\r\n\r\nTEST(StaticVector, StaticVector_push_back)\r\n{\r\n\tStaticVector<size_t, MAX_SIZE> container;\r\n\r\n\tSetRndSeed(testing::UnitTest::GetInstance()->random_seed());\r\n\tconst size_t size = RandomIntBetween(10, MAX_SIZE);\r\n\r\n\tfor (size_t i = 0; i < size; i++) {\r\n\t\tcontainer.push_back(i);\r\n\t}\r\n\r\n\tEXPECT_EQ(container.size(), size);\r\n\tfor (size_t i = 0; i < size; i++) {\r\n\t\tEXPECT_EQ(container[i], i);\r\n\t}\r\n}\r\n\r\nTEST(StaticVector, StaticVector_push_back_full)\r\n{\r\n\tStaticVector<size_t, MAX_SIZE> container;\r\n\r\n\tconst size_t size = MAX_SIZE;\r\n\tfor (size_t i = 0; i < size; i++) {\r\n\t\tcontainer.push_back(i);\r\n\t}\r\n\r\n\tEXPECT_EQ(container.size(), MAX_SIZE);\r\n\tfor (size_t i = 0; i < size; i++) {\r\n\t\tEXPECT_EQ(container[i], i);\r\n\t}\r\n\r\n#ifdef _DEBUG\r\n\tASSERT_DEATH(container.push_back(size + 1), \"\");\r\n#endif\r\n}\r\n\r\nTEST(StaticVector, StaticVector_erase)\r\n{\r\n\tStaticVector<size_t, MAX_SIZE> container;\r\n\tstd::vector<size_t> expected;\r\n\r\n\tSetRndSeed(testing::UnitTest::GetInstance()->random_seed());\r\n\r\n#ifdef _DEBUG\r\n\tASSERT_DEATH(container.erase(container.begin()), \"\");\r\n#endif\r\n\r\n\tcontainer = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\r\n\texpected = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };\r\n\tcontainer.erase(container.begin());\r\n\tEXPECT_EQ(container.size(), expected.size());\r\n\tfor (size_t i = 0; i < container.size(); i++) {\r\n\t\tEXPECT_EQ(container[i], expected[i]);\r\n\t}\r\n\r\n\texpected = { 1, 2, 3, 4, 5, 6, 7, 8 };\r\n\tcontainer.erase(container.end() - 1, container.end());\r\n\tEXPECT_EQ(container.size(), expected.size());\r\n\tfor (size_t i = 0; i < container.size(); i++) {\r\n\t\tEXPECT_EQ(container[i], expected[i]);\r\n\t}\r\n\r\n\twhile (!container.empty()) {\r\n\t\tsize_t idx = RandomIntLessThan(static_cast<int32_t>(container.size()));\r\n\t\tcontainer.erase(container.begin() + idx);\r\n\t\texpected.erase(expected.begin() + idx);\r\n\t\tif (container.size() > 0) {\r\n\t\t\tEXPECT_EQ(container.size(), expected.size());\r\n\t\t\tidx = idx <= 1 ? 0 : idx - 1;\r\n\t\t\tEXPECT_EQ(container[idx], expected[idx]);\r\n\t\t\tidx = (idx + 1) >= container.size() ? container.size() - 1 : idx + 1;\r\n\t\t\tEXPECT_EQ(container[idx], expected[idx]);\r\n\t\t}\r\n\t}\r\n\tEXPECT_EQ(container.size(), 0);\r\n\r\n#ifdef _DEBUG\r\n\tASSERT_DEATH(container.erase(container.begin(), container.end() + 1), \"\");\r\n\tASSERT_DEATH(container.erase(container.begin() - 1, container.end()), \"\");\r\n#endif\r\n}\r\n\r\nTEST(StaticVector, StaticVector_erase_random)\r\n{\r\n\tStaticVector<size_t, MAX_SIZE> container;\r\n\tstd::vector<size_t> expected;\r\n\r\n\tSetRndSeed(testing::UnitTest::GetInstance()->random_seed());\r\n\tconst size_t size = RandomIntBetween(10, MAX_SIZE);\r\n\tsize_t erasures = RandomIntBetween(1, static_cast<int32_t>(size) - 1, true);\r\n\r\n\tfor (size_t i = 0; i < size; i++) {\r\n\t\tcontainer.push_back(i);\r\n\t\texpected.push_back(i);\r\n\t}\r\n\r\n\twhile (erasures-- > 0) {\r\n\t\tconst size_t idx = RandomIntLessThan(static_cast<int32_t>(container.size()));\r\n\t\tcontainer.erase(container.begin() + idx);\r\n\t\texpected.erase(expected.begin() + idx);\r\n\t}\r\n\r\n\tEXPECT_EQ(container.size(), expected.size());\r\n\tfor (size_t i = 0; i < expected.size(); i++) {\r\n\t\tEXPECT_EQ(container[i], expected[i]);\r\n\t}\r\n}\r\n\r\nTEST(StaticVector, StaticVector_erase_range)\r\n{\r\n\tStaticVector<size_t, MAX_SIZE> container;\r\n\tconst std::vector<size_t> erase_idx;\r\n\tstd::vector<size_t> expected;\r\n\r\n\tSetRndSeed(testing::UnitTest::GetInstance()->random_seed());\r\n\r\n\tcontainer = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\r\n\texpected = { 3, 4, 5, 6, 7, 8, 9 };\r\n\tcontainer.erase(container.begin(), container.begin() + 3);\r\n\tEXPECT_EQ(container.size(), expected.size());\r\n\tfor (size_t i = 0; i < container.size(); i++) {\r\n\t\tEXPECT_EQ(container[i], expected[i]);\r\n\t}\r\n\r\n\tcontainer.erase(container.begin() + 1, container.begin() + 1);\r\n\tEXPECT_EQ(container.size(), expected.size());\r\n\tfor (size_t i = 0; i < container.size(); i++) {\r\n\t\tEXPECT_EQ(container[i], expected[i]);\r\n\t}\r\n\r\n\tconst int32_t from = RandomIntBetween(0, static_cast<int32_t>(container.size()) - 1);\r\n\tconst int32_t to = RandomIntBetween(from + 1, static_cast<int32_t>(container.size()));\r\n\tcontainer.erase(container.begin() + from, container.begin() + to);\r\n\tfor (int32_t i = to - from; i > 0; i--) {\r\n\t\texpected.erase(expected.begin() + from);\r\n\t}\r\n\r\n\tEXPECT_EQ(container.size(), expected.size());\r\n\tfor (size_t i = 0; i < container.size(); i++) {\r\n\t\tEXPECT_EQ(container[i], expected[i]);\r\n\t}\r\n}\r\n\r\nTEST(StaticVector, StaticVector_clear)\r\n{\r\n\tStaticVector<size_t, MAX_SIZE> container;\r\n\r\n\tcontainer.clear();\r\n\tEXPECT_EQ(container.size(), 0);\r\n\r\n\tcontainer = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\r\n\tcontainer.clear();\r\n\tEXPECT_EQ(container.size(), 0);\r\n}\r\n\r\n} // namespace\r\n"
  },
  {
    "path": "test/stores_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"stores.h\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nTEST(Stores, AddStoreHoldRepair_magic)\r\n{\r\n\tdevilution::Item *item;\r\n\r\n\titem = &PlayerItems[0];\r\n\r\n\titem->_iMaxDur = 60;\r\n\titem->_iDurability = item->_iMaxDur;\r\n\titem->_iMagical = ITEM_QUALITY_MAGIC;\r\n\titem->_iIdentified = true;\r\n\titem->_ivalue = 2000;\r\n\titem->_iIvalue = 19000;\r\n\r\n\tfor (int i = 1; i < item->_iMaxDur; i++) {\r\n\t\titem->_ivalue = 2000;\r\n\t\titem->_iIvalue = 19000;\r\n\t\titem->_iDurability = i;\r\n\t\tCurrentItemIndex = 0;\r\n\t\tAddStoreHoldRepair(item, 0);\r\n\t\tEXPECT_EQ(1, CurrentItemIndex);\r\n\t\tEXPECT_EQ(95 * (item->_iMaxDur - i) / 2, item->_ivalue);\r\n\t}\r\n\r\n\titem->_iDurability = 59;\r\n\tCurrentItemIndex = 0;\r\n\titem->_ivalue = 500;\r\n\titem->_iIvalue = 30; // To cheap to repair\r\n\tAddStoreHoldRepair(item, 0);\r\n\tEXPECT_EQ(0, CurrentItemIndex);\r\n\tEXPECT_EQ(30, item->_iIvalue);\r\n\tEXPECT_EQ(500, item->_ivalue);\r\n}\r\n\r\nTEST(Stores, AddStoreHoldRepair_normal)\r\n{\r\n\tdevilution::Item *item;\r\n\r\n\titem = &PlayerItems[0];\r\n\r\n\titem->_iMaxDur = 20;\r\n\titem->_iDurability = item->_iMaxDur;\r\n\titem->_iMagical = ITEM_QUALITY_NORMAL;\r\n\titem->_iIdentified = true;\r\n\titem->_ivalue = 2000;\r\n\titem->_iIvalue = item->_ivalue;\r\n\r\n\tfor (int i = 1; i < item->_iMaxDur; i++) {\r\n\t\titem->_ivalue = 2000;\r\n\t\titem->_iIvalue = item->_ivalue;\r\n\t\titem->_iDurability = i;\r\n\t\tCurrentItemIndex = 0;\r\n\t\tAddStoreHoldRepair(item, 0);\r\n\t\tEXPECT_EQ(1, CurrentItemIndex);\r\n\t\tEXPECT_EQ(50 * (item->_iMaxDur - i), item->_ivalue);\r\n\t}\r\n\r\n\titem->_iDurability = 19;\r\n\tCurrentItemIndex = 0;\r\n\titem->_ivalue = 10; // less than 1 per dur\r\n\titem->_iIvalue = item->_ivalue;\r\n\tAddStoreHoldRepair(item, 0);\r\n\tEXPECT_EQ(1, CurrentItemIndex);\r\n\tEXPECT_EQ(1, item->_ivalue);\r\n\tEXPECT_EQ(1, item->_iIvalue);\r\n}\r\n} // namespace\r\n"
  },
  {
    "path": "test/str_cat_test.cpp",
    "content": "#include <cstdint>\r\n\r\n#include <gtest/gtest.h>\r\n\r\n#include \"utils/str_cat.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nTEST(StrCatTest, StrCatBasicTest)\r\n{\r\n\tEXPECT_EQ(StrCat(\"a\", \"b\", \"c\", 5), \"abc5\");\r\n}\r\n\r\nTEST(StrCatTest, LeftPadTest)\r\n{\r\n\tEXPECT_EQ(StrCat(LeftPad(static_cast<uint8_t>(5), 2, '0')), \"05\");\r\n}\r\n\r\nTEST(StrCatTest, BufCopyBasicTest)\r\n{\r\n\tchar buf[5];\r\n\tchar *end = BufCopy(buf, \"a\", \"b\", \"c\", 5);\r\n\tEXPECT_EQ(std::string_view(buf, end - buf), \"abc5\");\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/text_render_integration_test.cpp",
    "content": "#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include <cstddef>\r\n#include <cstdint>\r\n#include <iostream>\r\n#include <string>\r\n#include <string_view>\r\n#include <variant>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL_iostream.h>\r\n#include <SDL3/SDL_surface.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include <expected.hpp>\r\n#include <function_ref.hpp>\r\n\r\n#include \"engine/load_file.hpp\"\r\n#include \"engine/palette.h\"\r\n#include \"engine/point.hpp\"\r\n#include \"engine/rectangle.hpp\"\r\n#include \"engine/render/primitive_render.hpp\"\r\n#include \"engine/render/text_render.hpp\"\r\n#include \"engine/size.hpp\"\r\n#include \"engine/surface.hpp\"\r\n#include \"utils/paths.h\"\r\n#include \"utils/png.h\"\r\n#include \"utils/sdl_compat.h\"\r\n#include \"utils/sdl_wrap.h\"\r\n#include \"utils/str_cat.hpp\"\r\n#include \"utils/surface_to_png.hpp\"\r\n\r\n// Invoke with --update_expected to update the expected files with actual results.\r\nstatic bool UpdateExpected;\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nconstexpr char FixturesPath[] = \"test/fixtures/text_render_integration_test/\";\r\n\r\nstruct TestFixture {\r\n\tstd::string name;\r\n\tint width;\r\n\tint height;\r\n\tstd::string_view fmt;\r\n\tstd::vector<DrawStringFormatArg> args {};\r\n\tTextRenderOptions opts { .flags = UiFlags::ColorUiGold };\r\n\r\n\tfriend void PrintTo(const TestFixture &f, std::ostream *os)\r\n\t{\r\n\t\t*os << f.name;\r\n\t}\r\n};\r\n\r\nconst TestFixture Fixtures[] {\r\n\tTestFixture {\r\n\t    .name = \"basic\",\r\n\t    .width = 96,\r\n\t    .height = 15,\r\n\t    .fmt = \"DrawString\",\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"basic-colors\",\r\n\t    .width = 186,\r\n\t    .height = 15,\r\n\t    .fmt = \"{}{}{}{}\",\r\n\t    .args = {\r\n\t        { \"Draw\", UiFlags::ColorUiSilver },\r\n\t        { \"String\", UiFlags::ColorUiGold },\r\n\t        { \"With\", UiFlags::ColorUiSilverDark },\r\n\t        { \"Colors\", UiFlags::ColorUiGoldDark },\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"horizontal_overflow\",\r\n\t    .width = 50,\r\n\t    .height = 28,\r\n\t    .fmt = \"Horizontal\",\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"horizontal_overflow-colors\",\r\n\t    .width = 50,\r\n\t    .height = 28,\r\n\t    .fmt = \"{}{}\",\r\n\t    .args = {\r\n\t        { \"Hori\", UiFlags::ColorUiGold },\r\n\t        { \"zontal\", UiFlags::ColorUiSilverDark },\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing\",\r\n\t    .width = 120,\r\n\t    .height = 15,\r\n\t    .fmt = \"KerningFitSpacing\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::ColorUiSilver,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing-colors\",\r\n\t    .width = 120,\r\n\t    .height = 15,\r\n\t    .fmt = \"{}{}{}\",\r\n\t    .args = {\r\n\t        { \"Kerning\", UiFlags::ColorUiSilver },\r\n\t        { \"Fit\", UiFlags::ColorUiGold },\r\n\t        { \"Spacing\", UiFlags::ColorUiSilverDark },\r\n\t    },\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing__align_center\",\r\n\t    .width = 170,\r\n\t    .height = 15,\r\n\t    .fmt = \"KerningFitSpacing | AlignCenter\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter | UiFlags::ColorUiSilver,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing__align_center-colors\",\r\n\t    .width = 170,\r\n\t    .height = 15,\r\n\t    .fmt = \"{}{}{}\",\r\n\t    .args = {\r\n\t        { \"KerningFitSpacing\", UiFlags::ColorUiSilver },\r\n\t        { \" | \", UiFlags::ColorUiGold },\r\n\t        { \"AlignCenter\", UiFlags::ColorUiSilverDark },\r\n\t    },\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing__align_center__newlines\",\r\n\t    .width = 170,\r\n\t    .height = 42,\r\n\t    .fmt = \"KerningFitSpacing | AlignCenter\\nShort line\\nAnother overly long line\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter | UiFlags::ColorUiSilver,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing__align_center__newlines_in_fmt-colors\",\r\n\t    .width = 170,\r\n\t    .height = 42,\r\n\t    .fmt = \"{}\\n{}\\n{}\",\r\n\t    .args = {\r\n\t        { \"KerningFitSpacing | AlignCenter\", UiFlags::ColorUiSilver },\r\n\t        { \"Short line\", UiFlags::ColorUiGold },\r\n\t        { \"Another overly long line\", UiFlags::ColorUiSilverDark },\r\n\t    },\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing__align_center__newlines_in_value-colors\",\r\n\t    .width = 170,\r\n\t    .height = 42,\r\n\t    .fmt = \"{}{}\",\r\n\t    .args = {\r\n\t        { \"KerningFitSpacing | AlignCenter\\nShort line\\nAnother overly \", UiFlags::ColorUiSilver },\r\n\t        { \"long line\", UiFlags::ColorUiGold },\r\n\t    },\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing__align_right\",\r\n\t    .width = 170,\r\n\t    .height = 15,\r\n\t    .fmt = \"KerningFitSpacing | AlignRight\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::AlignRight | UiFlags::ColorUiSilver,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"kerning_fit_spacing__align_right-colors\",\r\n\t    .width = 170,\r\n\t    .height = 15,\r\n\t    .fmt = \"{}{}{}\",\r\n\t    .args = {\r\n\t        { \"KerningFitSpacing\", UiFlags::ColorUiSilver },\r\n\t        { \" | \", UiFlags::ColorUiGold },\r\n\t        { \"AlignRight\", UiFlags::ColorUiSilverDark },\r\n\t    },\r\n\t    .opts = {\r\n\t        .flags = UiFlags::KerningFitSpacing | UiFlags::AlignRight,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"vertical_overflow\",\r\n\t    .width = 36,\r\n\t    .height = 20,\r\n\t    .fmt = \"One\\nTwo\",\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"vertical_overflow-colors\",\r\n\t    .width = 36,\r\n\t    .height = 20,\r\n\t    .fmt = \"{}\\n{}\",\r\n\t    .args = {\r\n\t        { \"One\", UiFlags::ColorUiGold },\r\n\t        { \"Two\", UiFlags::ColorUiSilverDark },\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"cursor-start\",\r\n\t    .width = 120,\r\n\t    .height = 15,\r\n\t    .fmt = \"Hello World\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .cursorPosition = 0, // Cursor at start\r\n\t        .cursorStatic = true,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"cursor-middle\",\r\n\t    .width = 120,\r\n\t    .height = 15,\r\n\t    .fmt = \"Hello World\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .cursorPosition = 5, // Cursor after \"Hello\",\r\n\t        .cursorStatic = true,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"cursor-end\",\r\n\t    .width = 120,\r\n\t    .height = 15,\r\n\t    .fmt = \"Hello World\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .cursorPosition = 11, // Cursor at end\r\n\t        .cursorStatic = true,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"multiline_cursor-end_first_line\",\r\n\t    .width = 100,\r\n\t    .height = 50,\r\n\t    .fmt = \"First line\\nSecond line\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .cursorPosition = 10, // Cursor at end of first line\r\n\t        .cursorStatic = true,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"multiline_cursor-start_second_line\",\r\n\t    .width = 100,\r\n\t    .height = 50,\r\n\t    .fmt = \"First line\\nSecond line\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .cursorPosition = 11, // Cursor at start of second line\r\n\t        .cursorStatic = true,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"multiline_cursor-middle_second_line\",\r\n\t    .width = 100,\r\n\t    .height = 50,\r\n\t    .fmt = \"First line\\nSecond line\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .cursorPosition = 14, // Cursor at second line, at the 'o' of \"Second\"\r\n\t        .cursorStatic = true,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"multiline_cursor-end_second_line\",\r\n\t    .width = 100,\r\n\t    .height = 50,\r\n\t    .fmt = \"First line\\nSecond line\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .cursorPosition = 22, // Cursor at start of second line\r\n\t        .cursorStatic = true,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"highlight-partial\",\r\n\t    .width = 120,\r\n\t    .height = 15,\r\n\t    .fmt = \"Hello World\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .highlightRange = { 5, 10 }, // Highlight \" Worl\"\r\n\t        .highlightColor = PAL8_BLUE,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"highlight-full\",\r\n\t    .width = 120,\r\n\t    .height = 15,\r\n\t    .fmt = \"Hello World\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .highlightRange = { 0, 11 }, // Highlight entire text\r\n\t        .highlightColor = PAL8_BLUE,\r\n\t    },\r\n\t},\r\n\tTestFixture {\r\n\t    .name = \"multiline_highlight\",\r\n\t    .width = 70,\r\n\t    .height = 50,\r\n\t    .fmt = \"Hello\\nWorld\",\r\n\t    .opts = {\r\n\t        .flags = UiFlags::ColorUiGold,\r\n\t        .highlightRange = { 3, 8 }, // Highlight \"lo\\nWo\"\r\n\t        .highlightColor = PAL8_BLUE,\r\n\t    },\r\n\t},\r\n};\r\n\r\nSDLPaletteUniquePtr LoadPalette()\r\n{\r\n\tstruct Color {\r\n\t\tuint8_t r, g, b;\r\n\t};\r\n\tstd::array<Color, 256> palData;\r\n\tLoadFileInMem(\"ui_art\\\\diablo.pal\", palData);\r\n\tSDLPaletteUniquePtr palette = SDLWrap::AllocPalette(static_cast<int>(palData.size()));\r\n\tfor (unsigned i = 0; i < palData.size(); i++) {\r\n\t\tpalette->colors[i] = SDL_Color {\r\n\t\t\tpalData[i].r, palData[i].g, palData[i].b, SDL_ALPHA_OPAQUE\r\n\t\t};\r\n\t}\r\n\treturn palette;\r\n}\r\n\r\nvoid DrawWithBorder(const Surface &out, const Rectangle &area, tl::function_ref<void(const Rectangle &)> fn)\r\n{\r\n\tconst uint8_t debugColor = PAL8_RED;\r\n\tDrawHorizontalLine(out, area.position, area.size.width, debugColor);\r\n\tDrawHorizontalLine(out, area.position + Displacement { 0, area.size.height - 1 }, area.size.width, debugColor);\r\n\tDrawVerticalLine(out, area.position, area.size.height, debugColor);\r\n\tDrawVerticalLine(out, area.position + Displacement { area.size.width - 1, 0 }, area.size.height, debugColor);\r\n\tfn(Rectangle {\r\n\t    Point { area.position.x + 1, area.position.y + 1 },\r\n\t    Size { area.size.width - 2, area.size.height - 2 } });\r\n}\r\n\r\nbool MaybeUpdateExpected(const std::string &actualPath, const std::string &expectedPath)\r\n{\r\n\tif (!UpdateExpected) return false;\r\n\tCopyFileOverwrite(actualPath.c_str(), expectedPath.c_str());\r\n\tstd::clog << \"⬆️ Updated expected file at \" << expectedPath << std::endl;\r\n\treturn true;\r\n}\r\n\r\nclass TextRenderIntegrationTest : public ::testing::TestWithParam<TestFixture> {\r\npublic:\r\n\tstatic void SetUpTestSuite()\r\n\t{\r\n\t\tpalette = LoadPalette();\r\n\t}\r\n\tstatic void TearDownTestSuite()\r\n\t{\r\n\t\tpalette = nullptr;\r\n\t}\r\n\r\nprotected:\r\n\tstatic SDLPaletteUniquePtr palette;\r\n};\r\n\r\nSDLPaletteUniquePtr TextRenderIntegrationTest::palette;\r\n\r\nTEST_P(TextRenderIntegrationTest, RenderAndCompareTest)\r\n{\r\n\tconst TestFixture &fixture = GetParam();\r\n\r\n\tOwnedSurface out = OwnedSurface { fixture.width + 20, fixture.height + 20 };\r\n\tSDL_SetSurfacePalette(out.surface, palette.get());\r\n\tASSERT_NE(out.surface, nullptr);\r\n\r\n\tDrawWithBorder(out, Rectangle { Point { 10, 10 }, Size { fixture.width, fixture.height } }, [&](const Rectangle &rect) {\r\n\t\tif (fixture.args.empty()) {\r\n\t\t\tDrawString(out, fixture.fmt, rect, fixture.opts);\r\n\t\t} else {\r\n\t\t\tDrawStringWithColors(out, fixture.fmt, fixture.args, rect, fixture.opts);\r\n\t\t}\r\n\t});\r\n\r\n\tconst std::string actualPath = StrCat(paths::BasePath(), FixturesPath, GetParam().name, \"-Actual.png\");\r\n\tconst std::string expectedPath = StrCat(paths::BasePath(), FixturesPath, GetParam().name, \".png\");\r\n\tSDL_IOStream *actual = SDL_IOFromFile(actualPath.c_str(), \"wb\");\r\n\tASSERT_NE(actual, nullptr) << SDL_GetError();\r\n\r\n\tconst tl::expected<void, std::string> result = WriteSurfaceToFilePng(out, actual);\r\n\tASSERT_TRUE(result.has_value()) << result.error();\r\n\r\n\t// We compare pixels rather than PNG file contents because different\r\n\t// versions of SDL may use different PNG encoders.\r\n\tSDLSurfaceUniquePtr actualSurface { LoadPNG(actualPath.c_str()) };\r\n\tASSERT_NE(actualSurface, nullptr) << SDL_GetError();\r\n\tSDLSurfaceUniquePtr expectedSurface { LoadPNG(expectedPath.c_str()) };\r\n\tASSERT_NE(expectedSurface, nullptr) << SDL_GetError();\r\n\tASSERT_NE(actualSurface->pixels, nullptr);\r\n\tASSERT_NE(expectedSurface->pixels, nullptr);\r\n\r\n\tif ((actualSurface->h != expectedSurface->h || actualSurface->w != expectedSurface->w)\r\n\t    && MaybeUpdateExpected(actualPath, expectedPath)) {\r\n\t\treturn;\r\n\t}\r\n\tASSERT_EQ(actualSurface->h, expectedSurface->h);\r\n\tASSERT_EQ(actualSurface->w, expectedSurface->w);\r\n\tfor (int y = 0; y < expectedSurface->h; y++) {\r\n\t\tfor (int x = 0; x < expectedSurface->w; x++) {\r\n\t\t\tconst uint8_t actualPixel = reinterpret_cast<uint8_t *>(actualSurface->pixels)[y * actualSurface->pitch + x];\r\n\t\t\tconst uint8_t expectedPixel = reinterpret_cast<uint8_t *>(expectedSurface->pixels)[y * expectedSurface->pitch + x];\r\n\t\t\tif (actualPixel != expectedPixel) {\r\n\t\t\t\tif (MaybeUpdateExpected(actualPath, expectedPath)) return;\r\n\t\t\t\tASSERT_TRUE(false) << \"Images are different at (\" << x << \", \" << y << \") \"\r\n\t\t\t\t                   << static_cast<int>(actualPixel) << \" != \" << static_cast<int>(expectedPixel);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nINSTANTIATE_TEST_SUITE_P(GoldenTests, TextRenderIntegrationTest,\r\n    testing::ValuesIn(Fixtures),\r\n    [](const testing::TestParamInfo<TestFixture> &info) {\r\n\t    std::string name = info.param.name;\r\n\t    std::replace(name.begin(), name.end(), '-', '_');\r\n\t    return name;\r\n    });\r\n\r\n} // namespace\r\n} // namespace devilution\r\n\r\nint main(int argc, char **argv)\r\n{\r\n\t::testing::InitGoogleTest(&argc, argv);\r\n\tif (argc >= 2) {\r\n\t\tfor (int i = 1; i < argc; ++i) {\r\n\t\t\tif (argv[i] != std::string_view(\"--update_expected\")) {\r\n\t\t\t\tstd::cerr << \"unknown argument: \" << argv[i] << \"\\nUsage: \"\r\n\t\t\t\t          << argv[0] << \" [--update_expected]\" << \"\\n\";\r\n\t\t\t\treturn 64;\r\n\t\t\t}\r\n\t\t}\r\n\t\tUpdateExpected = true;\r\n\t}\r\n\treturn RUN_ALL_TESTS();\r\n}\r\n"
  },
  {
    "path": "test/tile_properties_test.cpp",
    "content": "#include \"levels/tile_properties.hpp\"\r\n\r\n#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"levels/dun_tile.hpp\"\r\n#include \"levels/gendung.h\"\r\n#include \"objects.h\"\r\n#include \"tables/objdat.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nTEST(TilePropertiesTest, Solid)\r\n{\r\n\tdPiece[5][5] = 0;\r\n\tSOLData[0] = TileProperties::Solid;\r\n\tEXPECT_TRUE(IsTileSolid({ 5, 5 })) << \"Solid in-bounds tiles are solid\";\r\n\tEXPECT_FALSE(IsTileNotSolid({ 5, 5 })) << \"IsTileNotSolid returns the inverse of IsTileSolid for in-bounds tiles\";\r\n\r\n\tdPiece[6][6] = 1;\r\n\tSOLData[1] = TileProperties::None;\r\n\tEXPECT_FALSE(IsTileSolid({ 6, 6 })) << \"Non-solid in-bounds tiles are not solid\";\r\n\tEXPECT_TRUE(IsTileNotSolid({ 6, 6 })) << \"IsTileNotSolid returns the inverse of IsTileSolid for in-bounds tiles\";\r\n\r\n\tEXPECT_FALSE(IsTileSolid({ -1, 1 })) << \"Out of bounds tiles are not solid\"; // this reads out of bounds in the current code and may fail unexpectedly\r\n\tEXPECT_FALSE(IsTileNotSolid({ -1, 1 })) << \"Out of bounds tiles are also not not solid\";\r\n}\r\n\r\nTEST(TilePropertiesTest, Walkable)\r\n{\r\n\tdPiece[5][5] = 0;\r\n\tSOLData[0] = TileProperties::Solid; // Doing this manually to save running through the code in gendung.cpp\r\n\tEXPECT_FALSE(IsTileWalkable({ 5, 5 })) << \"Tile which is marked as solid should be considered blocked\";\r\n\tEXPECT_FALSE(IsTileWalkable({ 5, 5 }, true)) << \"Solid non-door tiles remain unwalkable when ignoring doors\";\r\n\r\n\tSOLData[0] = TileProperties::None;\r\n\tEXPECT_TRUE(IsTileWalkable({ 5, 5 })) << \"Non-solid tiles are walkable\";\r\n\tEXPECT_TRUE(IsTileWalkable({ 5, 5 }, true)) << \"Non-solid tiles remain walkable when ignoring doors\";\r\n\r\n\tdObject[5][5] = 1;\r\n\tObjects[0]._oSolidFlag = true;\r\n\tEXPECT_FALSE(IsTileWalkable({ 5, 5 })) << \"Tile occupied by a solid object is unwalkable\";\r\n\tEXPECT_FALSE(IsTileWalkable({ 5, 5 }, true)) << \"Tile occupied by a solid non-door object are unwalkable when ignoring doors\";\r\n\r\n\tObjects[0]._otype = _object_id::OBJ_L1LDOOR;\r\n\tEXPECT_FALSE(IsTileWalkable({ 5, 5 })) << \"Tile occupied by a door which is marked as solid should be considered blocked\";\r\n\tEXPECT_TRUE(IsTileWalkable({ 5, 5 }, true)) << \"Tile occupied by a door is considered walkable when ignoring doors\";\r\n\r\n\tObjects[0]._oSolidFlag = false;\r\n\tEXPECT_TRUE(IsTileWalkable({ 5, 5 })) << \"Tile occupied by an open door is walkable\";\r\n\tEXPECT_TRUE(IsTileWalkable({ 5, 5 }, true)) << \"Tile occupied by a door is considered walkable when ignoring doors\";\r\n\r\n\tSOLData[0] = TileProperties::Solid;\r\n\tEXPECT_FALSE(IsTileWalkable({ 5, 5 })) << \"Solid tiles occupied by an open door remain unwalkable\";\r\n\tEXPECT_TRUE(IsTileWalkable({ 5, 5 }, true)) << \"Solid tiles occupied by an open door become walkable when ignoring doors\";\r\n}\r\n\r\nTEST(TilePropertiesTest, CanStepTest)\r\n{\r\n\tdPiece[0][0] = 0;\r\n\tdPiece[0][1] = 0;\r\n\tdPiece[1][0] = 0;\r\n\tdPiece[1][1] = 0;\r\n\tSOLData[0] = TileProperties::None;\r\n\tEXPECT_TRUE(CanStep({ 0, 0 }, { 1, 1 })) << \"A step in open space is free of solid pieces\";\r\n\tEXPECT_TRUE(CanStep({ 1, 1 }, { 0, 0 })) << \"A step in open space is free of solid pieces\";\r\n\tEXPECT_TRUE(CanStep({ 1, 0 }, { 0, 1 })) << \"A step in open space is free of solid pieces\";\r\n\tEXPECT_TRUE(CanStep({ 0, 1 }, { 1, 0 })) << \"A step in open space is free of solid pieces\";\r\n\r\n\tSOLData[1] = TileProperties::Solid;\r\n\tdPiece[1][0] = 1;\r\n\tEXPECT_TRUE(CanStep({ 0, 1 }, { 1, 0 })) << \"Can path to a destination which is solid\";\r\n\tEXPECT_TRUE(CanStep({ 1, 0 }, { 0, 1 })) << \"Can path from a starting position which is solid\";\r\n\tEXPECT_TRUE(CanStep({ 0, 1 }, { 1, 1 })) << \"Stepping in a cardinal direction ignores solid pieces\";\r\n\tEXPECT_TRUE(CanStep({ 1, 0 }, { 1, 1 })) << \"Stepping in a cardinal direction ignores solid pieces\";\r\n\tEXPECT_TRUE(CanStep({ 0, 0 }, { 1, 0 })) << \"Stepping in a cardinal direction ignores solid pieces\";\r\n\tEXPECT_TRUE(CanStep({ 1, 1 }, { 1, 0 })) << \"Stepping in a cardinal direction ignores solid pieces\";\r\n\r\n\tEXPECT_FALSE(CanStep({ 0, 0 }, { 1, 1 })) << \"Can't cut a solid corner\";\r\n\tEXPECT_FALSE(CanStep({ 1, 1 }, { 0, 0 })) << \"Can't cut a solid corner\";\r\n\tdPiece[0][1] = 1;\r\n\tEXPECT_FALSE(CanStep({ 0, 0 }, { 1, 1 })) << \"Can't walk through the boundary between two corners\";\r\n\tEXPECT_FALSE(CanStep({ 1, 1 }, { 0, 0 })) << \"Can't walk through the boundary between two corners\";\r\n\tdPiece[1][0] = 0;\r\n\tEXPECT_FALSE(CanStep({ 0, 0 }, { 1, 1 })) << \"Can't cut a solid corner\";\r\n\tEXPECT_FALSE(CanStep({ 1, 1 }, { 0, 0 })) << \"Can't cut a solid corner\";\r\n\tdPiece[0][1] = 0;\r\n\r\n\tdPiece[0][0] = 1;\r\n\tEXPECT_FALSE(CanStep({ 1, 0 }, { 0, 1 })) << \"Can't cut a solid corner\";\r\n\tEXPECT_FALSE(CanStep({ 0, 1 }, { 1, 0 })) << \"Can't cut a solid corner\";\r\n\tdPiece[1][1] = 1;\r\n\tEXPECT_FALSE(CanStep({ 1, 0 }, { 0, 1 })) << \"Can't walk through the boundary between two corners\";\r\n\tEXPECT_FALSE(CanStep({ 0, 1 }, { 1, 0 })) << \"Can't walk through the boundary between two corners\";\r\n\tdPiece[0][0] = 0;\r\n\tEXPECT_FALSE(CanStep({ 1, 0 }, { 0, 1 })) << \"Can't cut a solid corner\";\r\n\tEXPECT_FALSE(CanStep({ 0, 1 }, { 1, 0 })) << \"Can't cut a solid corner\";\r\n\tdPiece[1][1] = 0;\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/timedemo_test.cpp",
    "content": "#include <filesystem>\r\n#include <gtest/gtest.h>\r\n#include <iostream>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/demomode.h\"\r\n#include \"game_mode.hpp\"\r\n#include \"headless_mode.hpp\"\r\n#include \"init.hpp\"\r\n#include \"lua/lua_global.hpp\"\r\n#include \"options.h\"\r\n#include \"pfile.h\"\r\n#include \"tables/monstdat.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/display.h\"\r\n#include \"utils/paths.h\"\r\n\r\nusing namespace devilution;\r\n\r\nnamespace {\r\n\r\nbool Dummy_GetHeroInfo(_uiheroinfo *pInfo)\r\n{\r\n\treturn true;\r\n}\r\n\r\nvoid RunTimedemo(std::string timedemoFolderName)\r\n{\r\n\tif (\r\n#ifdef USE_SDL3\r\n\t    !SDL_Init(SDL_INIT_EVENTS)\r\n#elif !defined(USE_SDL1)\r\n\t    SDL_Init(SDL_INIT_EVENTS) < 0\r\n#else\r\n\t    SDL_Init(0) < 0\r\n#endif\r\n\t) {\r\n\t\tErrSdl();\r\n\t}\r\n\r\n\tLoadCoreArchives();\r\n\tLoadGameArchives();\r\n\r\n\t// The tests need spawn.mpq or diabdat.mpq\r\n\tif (!HaveMainData()) {\r\n\t\tGTEST_SKIP() << \"MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test\";\r\n\t}\r\n\r\n\tconst std::string unitTestFolderCompletePath = paths::BasePath() + \"test/fixtures/timedemo/\" + timedemoFolderName;\r\n\tpaths::SetPrefPath(unitTestFolderCompletePath);\r\n\tpaths::SetConfigPath(unitTestFolderCompletePath);\r\n\r\n\tInitKeymapActions();\r\n\tLoadOptions();\r\n\tdemo::OverrideOptions();\r\n\tLuaInitialize();\r\n\r\n\tconst int demoNumber = 0;\r\n\r\n\tPlayers.resize(1);\r\n\tMyPlayerId = demoNumber;\r\n\tMyPlayer = &Players[MyPlayerId];\r\n\t*MyPlayer = {};\r\n\r\n\t// Currently only spawn.mpq is present when building on github actions\r\n\tgbIsSpawn = true;\r\n\tgbIsHellfire = false;\r\n\tgbMusicOn = false;\r\n\tgbSoundOn = false;\r\n\tHeadlessMode = true;\r\n\tdemo::InitPlayBack(demoNumber, true);\r\n\r\n\tLoadSpellData();\r\n\tLoadPlayerDataFiles();\r\n\tLoadMissileData();\r\n\tLoadMonsterData();\r\n\tLoadItemData();\r\n\tLoadObjectData();\r\n\tpfile_ui_set_hero_infos(Dummy_GetHeroInfo);\r\n\tgbLoadGame = true;\r\n\r\n\tdemo::OverrideOptions();\r\n\r\n\tAdjustToScreenGeometry(forceResolution);\r\n\r\n\tStartGame(false, true);\r\n\r\n\tconst HeroCompareResult result = pfile_compare_hero_demo(demoNumber, true);\r\n\tASSERT_EQ(result.status, HeroCompareResult::Same) << result.message;\r\n\tASSERT_FALSE(gbRunGame);\r\n\tgbRunGame = false;\r\n\tinit_cleanup();\r\n\tLuaShutdown();\r\n\tSDL_Quit();\r\n}\r\n\r\n} // namespace\r\n\r\nTEST(Timedemo, WarriorLevel1to2)\r\n{\r\n\tRunTimedemo(\"WarriorLevel1to2\");\r\n}\r\n"
  },
  {
    "path": "test/townerdat_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#ifdef USE_SDL3\r\n#include <SDL3/SDL.h>\r\n#else\r\n#include <SDL.h>\r\n#endif\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"tables/townerdat.hpp\"\r\n#include \"towners.h\"\r\n#include \"utils/paths.h\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nvoid SetTestAssetsPath()\r\n{\r\n\tconst std::string assetsPath = paths::BasePath() + \"/assets/\";\r\n\tpaths::SetAssetsPath(assetsPath);\r\n}\r\n\r\nvoid InitializeSDL()\r\n{\r\n#ifdef USE_SDL3\r\n\tif (!SDL_Init(SDL_INIT_EVENTS)) {\r\n\t\t// SDL_Init returns 0 on success in SDL3\r\n\t\treturn;\r\n\t}\r\n#elif !defined(USE_SDL1)\r\n\tif (SDL_Init(SDL_INIT_EVENTS) >= 0) {\r\n\t\treturn;\r\n\t}\r\n#else\r\n\tif (SDL_Init(0) >= 0) {\r\n\t\treturn;\r\n\t}\r\n#endif\r\n\t// If we get here, SDL initialization failed\r\n\t// In tests, we'll continue anyway as file operations might still work\r\n}\r\n\r\n/**\r\n * @brief Helper to find a towner data entry by type.\r\n */\r\nconst TownerDataEntry *FindTownerDataByType(_talker_id type)\r\n{\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tif (entry.type == type) {\r\n\t\t\treturn &entry;\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\n} // namespace\r\n\r\nTEST(TownerDat, LoadTownerData)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Verify we loaded the expected number of towners from assets\r\n\tASSERT_GE(TownersDataEntries.size(), 4u) << \"Should load at least 4 towners from assets\";\r\n\r\n\t// Check Griswold (TOWN_SMITH)\r\n\tconst TownerDataEntry *smith = FindTownerDataByType(TOWN_SMITH);\r\n\tASSERT_NE(smith, nullptr) << \"Should find TOWN_SMITH data\";\r\n\tEXPECT_EQ(smith->type, TOWN_SMITH);\r\n\tEXPECT_EQ(smith->name, \"Griswold the Blacksmith\");\r\n\tEXPECT_EQ(smith->position.x, 62);\r\n\tEXPECT_EQ(smith->position.y, 63);\r\n\tEXPECT_EQ(smith->direction, Direction::SouthWest);\r\n\tEXPECT_EQ(smith->animWidth, 96);\r\n\tEXPECT_EQ(smith->animPath, \"towners\\\\smith\\\\smithn\");\r\n\tEXPECT_EQ(smith->animFrames, 16);\r\n\tEXPECT_EQ(smith->animDelay, 3);\r\n\tEXPECT_EQ(smith->gossipTexts.size(), 11u);\r\n\tEXPECT_EQ(smith->gossipTexts[0], TEXT_GRISWOLD2);\r\n\tEXPECT_EQ(smith->gossipTexts[10], TEXT_GRISWOLD13);\r\n\tASSERT_GE(smith->animOrder.size(), 4u);\r\n\tEXPECT_EQ(smith->animOrder[0], 4);\r\n\tEXPECT_EQ(smith->animOrder[3], 7);\r\n\r\n\t// Check Pepin (TOWN_HEALER)\r\n\tconst TownerDataEntry *healer = FindTownerDataByType(TOWN_HEALER);\r\n\tASSERT_NE(healer, nullptr) << \"Should find TOWN_HEALER data\";\r\n\tEXPECT_EQ(healer->type, TOWN_HEALER);\r\n\tEXPECT_EQ(healer->name, \"Pepin the Healer\");\r\n\tEXPECT_EQ(healer->position.x, 55);\r\n\tEXPECT_EQ(healer->position.y, 79);\r\n\tEXPECT_EQ(healer->direction, Direction::SouthEast);\r\n\tEXPECT_EQ(healer->animFrames, 20);\r\n\tEXPECT_EQ(healer->gossipTexts.size(), 9u);\r\n\tASSERT_GE(healer->animOrder.size(), 3u);\r\n\r\n\t// Check Dead Guy (TOWN_DEADGUY) - has empty gossip texts and animOrder\r\n\tconst TownerDataEntry *deadguy = FindTownerDataByType(TOWN_DEADGUY);\r\n\tASSERT_NE(deadguy, nullptr) << \"Should find TOWN_DEADGUY data\";\r\n\tEXPECT_EQ(deadguy->type, TOWN_DEADGUY);\r\n\tEXPECT_EQ(deadguy->name, \"Wounded Townsman\");\r\n\tEXPECT_EQ(deadguy->direction, Direction::North);\r\n\tEXPECT_TRUE(deadguy->gossipTexts.empty()) << \"Dead guy should have no gossip texts\";\r\n\tEXPECT_TRUE(deadguy->animOrder.empty()) << \"Dead guy should have no custom anim order\";\r\n\r\n\t// Check Cow (TOWN_COW) - has empty animPath but animFrames and animDelay are set\r\n\tconst TownerDataEntry *cow = FindTownerDataByType(TOWN_COW);\r\n\tASSERT_NE(cow, nullptr) << \"Should find TOWN_COW data\";\r\n\tEXPECT_EQ(cow->type, TOWN_COW);\r\n\tEXPECT_EQ(cow->name, \"Cow\");\r\n\tEXPECT_EQ(cow->position.x, 58);\r\n\tEXPECT_EQ(cow->position.y, 16);\r\n\tEXPECT_EQ(cow->direction, Direction::SouthWest);\r\n\tEXPECT_EQ(cow->animWidth, 128);\r\n\tEXPECT_TRUE(cow->animPath.empty()) << \"Cow should have empty animPath\";\r\n\tEXPECT_EQ(cow->animFrames, 12);\r\n\tEXPECT_EQ(cow->animDelay, 3);\r\n\tEXPECT_TRUE(cow->gossipTexts.empty()) << \"Cow should have no gossip texts\";\r\n\tEXPECT_TRUE(cow->animOrder.empty()) << \"Cow should have no custom anim order\";\r\n}\r\n\r\nTEST(TownerDat, LoadQuestDialogTable)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Check Smith quest dialogs\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_SMITH, Q_BUTCHER), TEXT_BUTCH5);\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_SMITH, Q_LTBANNER), TEXT_BANNER6);\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_SMITH, Q_SKELKING), TEXT_KING7);\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_SMITH, Q_ROCK), TEXT_INFRA6);\r\n\r\n\t// Check Healer quest dialogs\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_HEALER, Q_BUTCHER), TEXT_BUTCH3);\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_HEALER, Q_LTBANNER), TEXT_BANNER4);\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_HEALER, Q_SKELKING), TEXT_KING5);\r\n\r\n\t// Check Dead guy quest dialogs\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_DEADGUY, Q_BUTCHER), TEXT_NONE);\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_DEADGUY, Q_LTBANNER), TEXT_NONE);\r\n}\r\n\r\nTEST(TownerDat, SetTownerQuestDialog)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Verify initial value from assets\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_SMITH, Q_MUSHROOM), TEXT_MUSH6);\r\n\r\n\t// Modify it\r\n\tSetTownerQuestDialog(TOWN_SMITH, Q_MUSHROOM, TEXT_MUSH1);\r\n\r\n\t// Verify it changed\r\n\tEXPECT_EQ(GetTownerQuestDialog(TOWN_SMITH, Q_MUSHROOM), TEXT_MUSH1);\r\n\r\n\t// Reset to original value for other tests\r\n\tSetTownerQuestDialog(TOWN_SMITH, Q_MUSHROOM, TEXT_MUSH6);\r\n}\r\n\r\nTEST(TownerDat, GetQuestDialogInvalidType)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Invalid towner type should return TEXT_NONE\r\n\t// Use a value that's guaranteed to be invalid (beyond enum range)\r\n\t_talker_id invalidType = static_cast<_talker_id>(255);\r\n\t_speech_id result = GetTownerQuestDialog(invalidType, Q_BUTCHER);\r\n\tEXPECT_EQ(result, TEXT_NONE) << \"Should return TEXT_NONE for invalid towner type\";\r\n}\r\n\r\nTEST(TownerDat, GetQuestDialogInvalidQuest)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Invalid quest ID should return TEXT_NONE\r\n\t_speech_id result = GetTownerQuestDialog(TOWN_SMITH, static_cast<quest_id>(-1));\r\n\tEXPECT_EQ(result, TEXT_NONE) << \"Should return TEXT_NONE for invalid quest ID\";\r\n\r\n\tresult = GetTownerQuestDialog(TOWN_SMITH, static_cast<quest_id>(MAXQUESTS));\r\n\tEXPECT_EQ(result, TEXT_NONE) << \"Should return TEXT_NONE for out-of-range quest ID\";\r\n}\r\n\r\nTEST(TownerDat, TownerLongNamesPopulated)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Build TownerLongNames as InitTowners() does\r\n\tTownerLongNames.clear();\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tTownerLongNames.try_emplace(entry.type, entry.name);\r\n\t}\r\n\r\n\t// Verify TownerLongNames is populated correctly\r\n\tEXPECT_FALSE(TownerLongNames.empty()) << \"TownerLongNames should not be empty after loading\";\r\n\r\n\t// Check specific entries\r\n\tauto smithIt = TownerLongNames.find(TOWN_SMITH);\r\n\tASSERT_NE(smithIt, TownerLongNames.end()) << \"Should find TOWN_SMITH in TownerLongNames\";\r\n\tEXPECT_EQ(smithIt->second, \"Griswold the Blacksmith\");\r\n\r\n\tauto healerIt = TownerLongNames.find(TOWN_HEALER);\r\n\tASSERT_NE(healerIt, TownerLongNames.end()) << \"Should find TOWN_HEALER in TownerLongNames\";\r\n\tEXPECT_EQ(healerIt->second, \"Pepin the Healer\");\r\n}\r\n\r\nTEST(TownerDat, GetNumTownerTypes)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Build TownerLongNames as InitTowners() does\r\n\tTownerLongNames.clear();\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tTownerLongNames.try_emplace(entry.type, entry.name);\r\n\t}\r\n\r\n\t// GetNumTownerTypes should return the number of unique towner types\r\n\tsize_t numTypes = GetNumTownerTypes();\r\n\tEXPECT_GT(numTypes, 0u) << \"Should have at least one towner type\";\r\n\tEXPECT_EQ(numTypes, TownerLongNames.size()) << \"GetNumTownerTypes should match TownerLongNames size\";\r\n}\r\n\r\nTEST(TownerDat, MultipleCowsOnlyOneType)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Count how many TOWN_COW entries exist in the data\r\n\tsize_t cowCount = 0;\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tif (entry.type == TOWN_COW) {\r\n\t\t\tcowCount++;\r\n\t\t}\r\n\t}\r\n\r\n\t// There should be multiple cows but only one type entry\r\n\tEXPECT_GT(cowCount, 1u) << \"TSV should have multiple cow entries\";\r\n\r\n\t// Build TownerLongNames\r\n\tTownerLongNames.clear();\r\n\tfor (const auto &entry : TownersDataEntries) {\r\n\t\tTownerLongNames.try_emplace(entry.type, entry.name);\r\n\t}\r\n\r\n\t// But only one entry in TownerLongNames for TOWN_COW\r\n\tauto cowIt = TownerLongNames.find(TOWN_COW);\r\n\tASSERT_NE(cowIt, TownerLongNames.end()) << \"Should find TOWN_COW in TownerLongNames\";\r\n\tEXPECT_EQ(cowIt->second, \"Cow\");\r\n}\r\n\r\nTEST(TownerDat, QuestDialogOptionalColumns)\r\n{\r\n\tInitializeSDL();\r\n\tSetTestAssetsPath();\r\n\tLoadTownerData();\r\n\r\n\t// Verify that missing quest columns default to TEXT_NONE\r\n\t// Q_FARMER, Q_GIRL, Q_DEFILER, Q_NAKRUL, Q_CORNSTN, Q_JERSEY may not be in base TSV\r\n\t// but the code should handle them gracefully\r\n\t_speech_id result = GetTownerQuestDialog(TOWN_SMITH, Q_FARMER);\r\n\t// Should be TEXT_NONE since TOWN_SMITH doesn't have farmer quest dialog\r\n\tEXPECT_EQ(result, TEXT_NONE) << \"Should return TEXT_NONE for unused quest columns\";\r\n}\r\n\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/utf8_test.cpp",
    "content": "\r\n#include <gtest/gtest.h>\r\n\r\n#include \"utils/utf8.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nTEST(DecodeFirstUtf8CodePointTest, OneByteCodePoint)\r\n{\r\n\tsize_t len;\r\n\tconst char32_t cp = DecodeFirstUtf8CodePoint(\"a\", &len);\r\n\tEXPECT_EQ(cp, U'a');\r\n\tEXPECT_EQ(len, 1);\r\n}\r\n\r\nTEST(DecodeFirstUtf8CodePointTest, TwoByteCodePoint)\r\n{\r\n\tsize_t len;\r\n\tconst char32_t cp = DecodeFirstUtf8CodePoint(\"ж\", &len);\r\n\tEXPECT_EQ(cp, U'ж');\r\n\tEXPECT_EQ(len, 2);\r\n}\r\n\r\nTEST(DecodeFirstUtf8CodePointTest, ThreeByteCodePoint)\r\n{\r\n\tsize_t len;\r\n\tconst char32_t cp = DecodeFirstUtf8CodePoint(\"€\", &len);\r\n\tEXPECT_EQ(cp, U'€');\r\n\tEXPECT_EQ(len, 3);\r\n}\r\n\r\nTEST(DecodeFirstUtf8CodePointTest, FourByteCodePoint)\r\n{\r\n\tsize_t len;\r\n\tconst char32_t cp = DecodeFirstUtf8CodePoint(\"💡\", &len);\r\n\tEXPECT_EQ(cp, U'💡');\r\n\tEXPECT_EQ(len, 4);\r\n}\r\n\r\nTEST(DecodeFirstUtf8CodePointTest, InvalidCodePoint)\r\n{\r\n\tsize_t len;\r\n\tconst char32_t cp = DecodeFirstUtf8CodePoint(\"\\xc3\\x28\", &len);\r\n\tEXPECT_EQ(cp, Utf8DecodeError);\r\n\tEXPECT_EQ(len, 1);\r\n}\r\n\r\nTEST(AppendUtf8Test, OneByteCodePoint)\r\n{\r\n\tstd::string s = \"x\";\r\n\tAppendUtf8(U'a', s);\r\n\tEXPECT_EQ(s, \"xa\");\r\n}\r\n\r\nTEST(AppendUtf8Test, TwoByteCodePoint)\r\n{\r\n\tstd::string s = \"x\";\r\n\tAppendUtf8(U'Á', s);\r\n\tEXPECT_EQ(s, \"xÁ\");\r\n}\r\n\r\nTEST(AppendUtf8Test, ThreeByteCodePoint)\r\n{\r\n\tstd::string s;\r\n\tAppendUtf8(U'€', s);\r\n\tEXPECT_EQ(s, \"€\");\r\n}\r\n\r\nTEST(AppendUtf8Test, FourByteCodePoint)\r\n{\r\n\tstd::string s;\r\n\tAppendUtf8(U'💡', s);\r\n\tEXPECT_EQ(s, \"💡\");\r\n}\r\n\r\nTEST(Utf8CodeUnits, ValidCodePoints)\r\n{\r\n\t// Working backwards on this loop to avoid triggering signed integer overflow on platforms where char has an\r\n\t// underlying type of signed char\r\n\tfor (char x = '\\x7F'; static_cast<signed char>(x) >= '\\x00'; x--) {\r\n\t\tEXPECT_FALSE(IsTrailUtf8CodeUnit(x)) << \"Basic Latin and ASCII Control characters are not trail code units\";\r\n\t}\r\n\r\n\tfor (char x = '\\x80'; x <= '\\xBF'; x++) {\r\n\t\tEXPECT_TRUE(IsTrailUtf8CodeUnit(x)) << \"Bytes in the range 0x80 to 0xBF are potentially valid trail code units\";\r\n\t}\r\n\r\n\tfor (char x = '\\xC2'; x <= '\\xF4'; x++) {\r\n\t\tEXPECT_FALSE(IsTrailUtf8CodeUnit(x)) << \"Bytes in the range 0xC2 to 0xF4 are never valid trail code units\";\r\n\t}\r\n}\r\n\r\nTEST(Utf8CodeUnits, InvalidCodePoints)\r\n{\r\n\tfor (char x = '\\xC0'; x <= '\\xC1'; x++) {\r\n\t\tEXPECT_FALSE(IsTrailUtf8CodeUnit(x)) << \"Bytes in the range 0xC0 to oxC1 are not trail code units\";\r\n\t}\r\n\r\n\tfor (char x = '\\xFF'; x >= '\\xF5'; x--) {\r\n\t\tEXPECT_FALSE(IsTrailUtf8CodeUnit(x)) << \"Bytes in the range 0xF5 to 0xFF are not trail code units\";\r\n\t}\r\n}\r\n\r\nTEST(Utf8CodeUnits, BasicLatin)\r\n{\r\n\tfor (char x = '\\x00'; x < '\\x20'; x++) {\r\n\t\tEXPECT_FALSE(IsBasicLatin(x)) << \"ASCII Control characters are not Basic Latin symbols\";\r\n\t}\r\n\r\n\tfor (char x = '\\x20'; x <= '\\x7E'; x++) {\r\n\t\tEXPECT_TRUE(IsBasicLatin(x)) << \"Basic Latin symbols are denoted by the range 0x20 to 0x7E inclusive\";\r\n\t}\r\n\r\n\tEXPECT_FALSE(IsBasicLatin('\\x7F')) << \"ASCII Control character DEL is not a Basic Latin symbol\";\r\n\r\n\t// Tests '\\xFF' separately to avoid infinite loop on platforms with unsigned char.\r\n\tfor (char x = '\\x80'; x < '\\xFF'; x++) {\r\n\t\tEXPECT_FALSE(IsBasicLatin(x)) << \"Multibyte Utf8 code units are not Basic Latin symbols\";\r\n\t}\r\n\tEXPECT_FALSE(IsBasicLatin('\\xFF')) << \"Multibyte Utf8 code units are not Basic Latin symbols\";\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/vendor_test.cpp",
    "content": "#include <gmock/gmock.h>\r\n#include <gtest/gtest.h>\r\n\r\n#include \"items.h\"\r\n#include \"player.h\"\r\n#include \"stores.h\"\r\n#include \"tables/playerdat.hpp\"\r\n\r\n#include \"engine/assets.hpp\"\r\n#include \"engine/random.hpp\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nusing ::testing::AnyOf;\r\nusing ::testing::Eq;\r\n\r\nconstexpr int SEED = 75357;\r\nconstexpr const char MissingMpqAssetsSkipReason[] = \"MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test suite\";\r\n\r\nstd::string itemtype_str(ItemType type);\r\nstd::string misctype_str(item_misc_id type);\r\n\r\nMATCHER_P(SmithTypeMatch, i, \"Valid Diablo item type from Griswold\")\r\n{\r\n\tif (arg >= ItemType::Sword && arg <= ItemType::HeavyArmor) return true;\r\n\r\n\t*result_listener << \"At index \" << i << \": Invalid item type \" << itemtype_str(arg);\r\n\treturn false;\r\n}\r\n\r\nMATCHER_P(SmithTypeMatchHf, i, \"Valid Hellfire item type from Griswold\")\r\n{\r\n\tif (arg >= ItemType::Sword && arg <= ItemType::Staff) return true;\r\n\r\n\t*result_listener << \"At index \" << i << \": Invalid item type \" << itemtype_str(arg);\r\n\treturn false;\r\n}\r\n\r\nMATCHER_P(PremiumTypeMatch, i, \"Valid premium items from Griswold\")\r\n{\r\n\tif (arg >= ItemType::Ring && arg <= ItemType::Amulet) return true;\r\n\r\n\t*result_listener << \"At index \" << i << \": Invalid item type \" << itemtype_str(arg);\r\n\treturn false;\r\n}\r\n\r\nMATCHER_P(WitchTypeMatch, i, \"Valid item type from Adria\")\r\n{\r\n\tif (arg == ItemType::Misc || arg == ItemType::Staff) return true;\r\n\r\n\t*result_listener << \"At index \" << i << \": Invalid item type \" << itemtype_str(arg);\r\n\treturn false;\r\n}\r\n\r\nMATCHER_P(WitchMiscMatch, i, \"Valid misc. item type from Adria\")\r\n{\r\n\tif (arg >= IMISC_ELIXSTR && arg <= IMISC_ELIXVIT) return true;\r\n\tif (arg >= IMISC_REJUV && arg <= IMISC_FULLREJUV) return true;\r\n\tif (arg >= IMISC_SCROLL && arg <= IMISC_SCROLLT) return true;\r\n\tif (arg >= IMISC_RUNEFIRST && arg <= IMISC_RUNELAST) return true;\r\n\tif (arg == IMISC_BOOK) return true;\r\n\r\n\t*result_listener << \"At index \" << i << \": Invalid misc. item type \" << misctype_str(arg);\r\n\treturn false;\r\n}\r\n\r\nMATCHER_P(HealerMiscMatch, i, \"Valid misc. item type from Pepin\")\r\n{\r\n\tif (arg >= IMISC_ELIXSTR && arg <= IMISC_ELIXVIT) return true;\r\n\tif (arg >= IMISC_REJUV && arg <= IMISC_FULLREJUV) return true;\r\n\tif (arg >= IMISC_SCROLL && arg <= IMISC_SCROLLT) return true;\r\n\r\n\t*result_listener << \"At index \" << i << \": Invalid misc. item type \" << misctype_str(arg);\r\n\treturn false;\r\n}\r\n\r\nclass VendorTest : public ::testing::Test {\r\npublic:\r\n\tvoid SetUp() override\r\n\t{\r\n\t\tif (missingMpqAssets_) {\r\n\t\t\tGTEST_SKIP() << MissingMpqAssetsSkipReason;\r\n\t\t}\r\n\r\n\t\tPlayers.resize(1);\r\n\t\tMyPlayer = &Players[0];\r\n\t\tgbIsHellfire = false;\r\n\t\tPremiumItemLevel = 1;\r\n\t\tCreatePlayer(*MyPlayer, HeroClass::Warrior);\r\n\t\tSetRndSeed(SEED);\r\n\t}\r\n\r\n\tstatic void SetUpTestSuite()\r\n\t{\r\n\t\tLoadCoreArchives();\r\n\t\tLoadGameArchives();\r\n\t\tmissingMpqAssets_ = !HaveMainData();\r\n\t\tif (missingMpqAssets_) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tLoadPlayerDataFiles();\r\n\t\tLoadItemData();\r\n\t\tLoadSpellData();\r\n\t}\r\n\r\nprivate:\r\n\tstatic bool missingMpqAssets_;\r\n};\r\n\r\nbool VendorTest::missingMpqAssets_ = false;\r\n\r\nstd::string itemtype_str(ItemType type)\r\n{\r\n\tconst std::string ITEM_TYPES[] = {\r\n\t\t\"ItemType::Misc\",\r\n\t\t\"ItemType::Sword\",\r\n\t\t\"ItemType::Axe\",\r\n\t\t\"ItemType::Bow\",\r\n\t\t\"ItemType::Mace\",\r\n\t\t\"ItemType::Shield\",\r\n\t\t\"ItemType::LightArmor\",\r\n\t\t\"ItemType::Helm\",\r\n\t\t\"ItemType::MediumArmor\",\r\n\t\t\"ItemType::HeavyArmor\",\r\n\t\t\"ItemType::Staff\",\r\n\t\t\"ItemType::Gold\",\r\n\t\t\"ItemType::Ring\",\r\n\t\t\"ItemType::Amulet\",\r\n\t};\r\n\r\n\tif (type == ItemType::None) return \"ItemType::None\";\r\n\tif (type < ItemType::Misc || type > ItemType::Amulet) return \"ItemType does not exist!\";\r\n\treturn ITEM_TYPES[static_cast<int>(type)];\r\n}\r\n\r\nstd::string misctype_str(item_misc_id type)\r\n{\r\n\tconst std::string MISC_TYPES[] = {\r\n\t\t// clang-format off\r\n\t\t\"IMISC_NONE\",\t\t\"IMISC_USEFIRST\",\t\"IMISC_FULLHEAL\",\t\"IMISC_HEAL\",\r\n\t\t\"IMISC_0x4\",\t\t\"IMISC_0x5\",\t\t\"IMISC_MANA\",\t\t\"IMISC_FULLMANA\",\r\n\t\t\"IMISC_0x8\",\t\t\"IMISC_0x9\",\t\t\"IMISC_ELIXSTR\",\t\"IMISC_ELIXMAG\",\r\n\t\t\"IMISC_ELIXDEX\",\t\"IMISC_ELIXVIT\",\t\"IMISC_0xE\",\t\t\"IMISC_0xF\",\r\n\t\t\"IMISC_0x10\",\t\t\"IMISC_0x11\",\t\t\"IMISC_REJUV\",\t\t\"IMISC_FULLREJUV\",\r\n\t\t\"IMISC_USELAST\",\t\"IMISC_SCROLL\",\t\t\"IMISC_SCROLLT\",\t\"IMISC_STAFF\",\r\n\t\t\"IMISC_BOOK\",\t\t\"IMISC_RING\",\t\t\"IMISC_AMULET\",\t\t\"IMISC_UNIQUE\",\r\n\t\t\"IMISC_0x1C\",\t\t\"IMISC_OILFIRST\",\t\"IMISC_OILOF\",\t\t\"IMISC_OILACC\",\r\n\t\t\"IMISC_OILMAST\",\t\"IMISC_OILSHARP\",\t\"IMISC_OILDEATH\",\t\"IMISC_OILSKILL\",\r\n\t\t\"IMISC_OILBSMTH\",\t\"IMISC_OILFORT\",\t\"IMISC_OILPERM\",\t\"IMISC_OILHARD\",\r\n\t\t\"IMISC_OILIMP\",\t\t\"IMISC_OILLAST\",\t\"IMISC_MAPOFDOOM\",\t\"IMISC_EAR\",\r\n\t\t\"IMISC_SPECELIX\",\t\"IMISC_0x2D\",\t\t\"IMISC_RUNEFIRST\",\t\"IMISC_RUNEF\",\r\n\t\t\"IMISC_RUNEL\",\t\t\"IMISC_GR_RUNEL\",\t\"IMISC_GR_RUNEF\",\t\"IMISC_RUNES\",\r\n\t\t\"IMISC_RUNELAST\",\t\"IMISC_AURIC\",\t\t\"IMISC_NOTE\",\t\t\"IMISC_ARENAPOT\"\r\n\t\t// clang-format on\r\n\t};\r\n\r\n\tif (type == IMISC_INVALID) return \"IMISC_INVALID\";\r\n\tif (type < IMISC_NONE || type > IMISC_ARENAPOT) return \"IMISC does not exist!\";\r\n\treturn MISC_TYPES[static_cast<int>(type)];\r\n}\r\n\r\nTEST_F(VendorTest, SmithGen)\r\n{\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tSmithItems.clear();\r\n\tSpawnSmith(16);\r\n\r\n\tSetRndSeed(SEED);\r\n\tconst int N_ITEMS = RandomIntBetween(10, NumSmithBasicItems);\r\n\tEXPECT_EQ(SmithItems.size(), N_ITEMS);\r\n\tEXPECT_LE(SmithItems.size(), NumSmithBasicItems);\r\n\r\n\tfor (size_t i = 0; i < SmithItems.size(); i++) {\r\n\t\tEXPECT_THAT(SmithItems[i]._itype, SmithTypeMatch(i));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, SmithGenHf)\r\n{\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tSmithItems.clear();\r\n\tgbIsHellfire = true;\r\n\tSpawnSmith(16);\r\n\r\n\tSetRndSeed(SEED);\r\n\tconst int N_ITEMS = RandomIntBetween(10, NumSmithBasicItemsHf);\r\n\tEXPECT_EQ(SmithItems.size(), N_ITEMS);\r\n\tEXPECT_LE(SmithItems.size(), NumSmithBasicItemsHf);\r\n\r\n\tfor (size_t i = 0; i < SmithItems.size(); i++) {\r\n\t\tEXPECT_THAT(SmithItems[i]._itype, SmithTypeMatchHf(i));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, PremiumQlvl1to5)\r\n{\r\n\t// Test starting the game as a level 1 character\r\n\tMyPlayer->setCharacterLevel(1);\r\n\tPremiumItems.clear();\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 1, 1, 1, 1, 2, 3 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test level ups\r\n\tMyPlayer->setCharacterLevel(5);\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 4, 4, 5, 5, 6, 7 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, PremiumQlvl25)\r\n{\r\n\tconstexpr int QLVLS[] = { 24, 24, 25, 25, 26, 27 };\r\n\r\n\t// Test starting the game as a level 25 character\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tPremiumItems.clear();\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test buying select items\r\n\tReplacePremium(*MyPlayer, 0);\r\n\tReplacePremium(*MyPlayer, 3);\r\n\tReplacePremium(*MyPlayer, 5);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, PremiumQlvl30Plus)\r\n{\r\n\tconstexpr int QLVLS[] = { 30, 30, 30, 30, 30, 30 };\r\n\r\n\t// Finally test level 30+ characters\r\n\tMyPlayer->setCharacterLevel(31);\r\n\tPremiumItems.clear();\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test buying select items\r\n\tReplacePremium(*MyPlayer, 0);\r\n\tReplacePremium(*MyPlayer, 3);\r\n\tReplacePremium(*MyPlayer, 5);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test 30+ levelling\r\n\tMyPlayer->setCharacterLevel(35);\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test buying select items\r\n\tReplacePremium(*MyPlayer, 0);\r\n\tReplacePremium(*MyPlayer, 3);\r\n\tReplacePremium(*MyPlayer, 5);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItems);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatch(i), PremiumTypeMatch(i)));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, HfPremiumQlvl1to5)\r\n{\r\n\t// Test level 1 character item qlvl\r\n\tMyPlayer->setCharacterLevel(1);\r\n\tPremiumItems.clear();\r\n\tgbIsHellfire = true;\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test level ups\r\n\tMyPlayer->setCharacterLevel(5);\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, HfPremiumQlvl25)\r\n{\r\n\t// Test starting game as a level 25 character\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tPremiumItems.clear();\r\n\tgbIsHellfire = true;\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 28 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test buying select items\r\n\tReplacePremium(*MyPlayer, 0);\r\n\tReplacePremium(*MyPlayer, 7);\r\n\tReplacePremium(*MyPlayer, 14);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 24, 23, 23, 24, 24, 24, 25, 26, 25, 26, 26, 26, 27, 27, 28 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, HfPremiumQlvl30Plus)\r\n{\r\n\t// Finally test level 30+ characters\r\n\tMyPlayer->setCharacterLevel(31);\r\n\tPremiumItems.clear();\r\n\tgbIsHellfire = true;\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test buying select items\r\n\tReplacePremium(*MyPlayer, 0);\r\n\tReplacePremium(*MyPlayer, 7);\r\n\tReplacePremium(*MyPlayer, 14);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tconstexpr int QLVLS[] = { 30, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 };\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\tconstexpr int QLVLS[] = { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 };\r\n\r\n\t// Test 30+ levelling\r\n\tMyPlayer->setCharacterLevel(35);\r\n\tSpawnPremium(*MyPlayer);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n\r\n\t// Test buying select items\r\n\tReplacePremium(*MyPlayer, 0);\r\n\tReplacePremium(*MyPlayer, 7);\r\n\tReplacePremium(*MyPlayer, 14);\r\n\tEXPECT_EQ(PremiumItems.size(), NumSmithItemsHf);\r\n\r\n\tfor (size_t i = 0; i < PremiumItems.size(); i++) {\r\n\t\tEXPECT_EQ(PremiumItems[i]._iCreateInfo & CF_LEVEL, QLVLS[i]) << \"Index: \" << i;\r\n\t\tEXPECT_THAT(PremiumItems[i]._itype, AnyOf(SmithTypeMatchHf(i), PremiumTypeMatch(i)));\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, WitchGen)\r\n{\r\n\tconstexpr _item_indexes PINNED_ITEMS[] = { IDI_MANA, IDI_FULLMANA, IDI_PORTAL };\r\n\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tWitchItems.clear();\r\n\tSpawnWitch(16);\r\n\r\n\tSetRndSeed(SEED);\r\n\tconst int N_ITEMS = RandomIntBetween(10, NumWitchItems);\r\n\tEXPECT_EQ(WitchItems.size(), N_ITEMS);\r\n\tEXPECT_LE(WitchItems.size(), NumWitchItems);\r\n\r\n\tfor (size_t i = 0; i < WitchItems.size(); i++) {\r\n\t\tif (i < NumWitchPinnedItems) {\r\n\t\t\tEXPECT_EQ(WitchItems[i].IDidx, PINNED_ITEMS[i]) << \"Index: \" << i;\r\n\t\t} else {\r\n\t\t\tEXPECT_THAT(WitchItems[i]._itype, WitchTypeMatch(i));\r\n\t\t\tif (WitchItems[i]._itype == ItemType::Misc) {\r\n\t\t\t\tEXPECT_THAT(WitchItems[i]._iMiscId, WitchMiscMatch(i));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, WitchGenHf)\r\n{\r\n\tconstexpr _item_indexes PINNED_ITEMS[] = { IDI_MANA, IDI_FULLMANA, IDI_PORTAL };\r\n\tconstexpr int MAX_PINNED_BOOKS = 4;\r\n\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tWitchItems.clear();\r\n\tgbIsHellfire = true;\r\n\tSpawnWitch(16);\r\n\r\n\tSetRndSeed(SEED);\r\n\tconst int N_PINNED_BOOKS = RandomIntLessThan(MAX_PINNED_BOOKS);\r\n\tconst int N_ITEMS = RandomIntBetween(10, NumWitchItemsHf);\r\n\tEXPECT_EQ(WitchItems.size(), N_ITEMS);\r\n\tEXPECT_LE(WitchItems.size(), NumWitchItemsHf);\r\n\r\n\tint n_books = 0;\r\n\tfor (size_t i = 0; i < WitchItems.size(); i++) {\r\n\t\tif (i < NumWitchPinnedItems) {\r\n\t\t\tEXPECT_EQ(WitchItems[i].IDidx, PINNED_ITEMS[i]) << \"Index: \" << i;\r\n\t\t} else {\r\n\t\t\tEXPECT_THAT(WitchItems[i]._itype, WitchTypeMatch(i));\r\n\t\t\tif (WitchItems[i]._itype == ItemType::Misc) {\r\n\t\t\t\tEXPECT_THAT(WitchItems[i]._iMiscId, WitchMiscMatch(i));\r\n\t\t\t}\r\n\t\t\tif (WitchItems[i]._iMiscId == IMISC_BOOK) n_books++;\r\n\t\t}\r\n\t}\r\n\tEXPECT_GE(n_books, N_PINNED_BOOKS);\r\n}\r\n\r\nTEST_F(VendorTest, HealerGen)\r\n{\r\n\tconstexpr _item_indexes PINNED_ITEMS[] = { IDI_HEAL, IDI_FULLHEAL, IDI_RESURRECT };\r\n\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tHealerItems.clear();\r\n\tSpawnHealer(16);\r\n\r\n\tSetRndSeed(SEED);\r\n\tconst int N_ITEMS = RandomIntBetween(10, NumHealerItems);\r\n\tEXPECT_EQ(HealerItems.size(), N_ITEMS);\r\n\tEXPECT_LE(HealerItems.size(), NumHealerItems);\r\n\r\n\tfor (size_t i = 0; i < HealerItems.size(); i++) {\r\n\t\tif (i < NumHealerPinnedItems) {\r\n\t\t\tEXPECT_EQ(HealerItems[i].IDidx, PINNED_ITEMS[i]) << \"Index: \" << i;\r\n\t\t} else {\r\n\t\t\tEXPECT_THAT(HealerItems[i]._itype, Eq(ItemType::Misc));\r\n\t\t\tEXPECT_THAT(HealerItems[i]._iMiscId, HealerMiscMatch(i));\r\n\t\t}\r\n\t}\r\n}\r\n\r\nTEST_F(VendorTest, HealerGenHf)\r\n{\r\n\tconstexpr _item_indexes PINNED_ITEMS[] = { IDI_HEAL, IDI_FULLHEAL, IDI_RESURRECT };\r\n\r\n\tMyPlayer->setCharacterLevel(25);\r\n\tHealerItems.clear();\r\n\tgbIsHellfire = true;\r\n\tSpawnHealer(16);\r\n\r\n\tSetRndSeed(SEED);\r\n\tconst int N_ITEMS = RandomIntBetween(10, NumHealerItemsHf);\r\n\tEXPECT_EQ(HealerItems.size(), N_ITEMS);\r\n\tEXPECT_LE(HealerItems.size(), NumHealerItemsHf);\r\n\r\n\tfor (size_t i = 0; i < HealerItems.size(); i++) {\r\n\t\tif (i < NumHealerPinnedItems) {\r\n\t\t\tEXPECT_EQ(HealerItems[i].IDidx, PINNED_ITEMS[i]) << \"Index: \" << i;\r\n\t\t} else {\r\n\t\t\tEXPECT_THAT(HealerItems[i]._itype, Eq(ItemType::Misc));\r\n\t\t\tEXPECT_THAT(HealerItems[i]._iMiscId, HealerMiscMatch(i));\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/vision_test.cpp",
    "content": "#include <gtest/gtest.h>\r\n\r\n#include \"vision.hpp\"\r\n\r\nnamespace devilution {\r\n\r\nnamespace {\r\n\r\nconst uint8_t ENV_WIDTH = 25;\r\nconst uint8_t ENV_HEIGHT = 25;\r\n\r\n// Real environment\r\nchar env[ENV_WIDTH][ENV_HEIGHT];\r\n// Visible environment\r\nchar vis[ENV_WIDTH][ENV_HEIGHT];\r\n// Observer position in the center of the environment\r\nconst Point pos(ENV_WIDTH / 2, ENV_HEIGHT / 2);\r\n// Walls (box) around the observer with the specified radius\r\nconst int box_radius = 4;\r\n// Objects around the observer: point, visible-to-observer flag\r\nconst std::pair<Point, bool> objects[] = {\r\n\t{ { 15, 12 }, true },\r\n\t{ { 13, 15 }, true },\r\n\t{ { 10, 11 }, true },\r\n\t{ { 11, 13 }, true },\r\n\t{ { 9, 15 }, false }, // Invisible to the observer, because of the {11,13}\r\n};\r\n\r\n// Build walls around with diagonally adjacent corners\r\nvoid buildWallsAround(char env[ENV_WIDTH][ENV_HEIGHT], Point p, int radius)\r\n{\r\n\tfor (int i = -radius + 1; i < radius; i++) {\r\n\t\tenv[p.x + radius][p.y + i] = '#';\r\n\t\tenv[p.x - radius][p.y + i] = '#';\r\n\t\tenv[p.x - i][p.y + radius] = '#';\r\n\t\tenv[p.x - i][p.y - radius] = '#';\r\n\t}\r\n}\r\n\r\nvoid initEnvironment()\r\n{\r\n\tmemset(env, ' ', sizeof(env));\r\n\tmemset(vis, ' ', sizeof(vis));\r\n\r\n\t// Build walls around with diagonally adjacent corners\r\n\tbuildWallsAround(env, pos, box_radius);\r\n\r\n\t// Place objects\r\n\tfor (const auto &o : objects) {\r\n\t\tenv[o.first.x][o.first.y] = '#';\r\n\t}\r\n\r\n\t// Place observer\r\n\tenv[pos.x][pos.y] = 'x';\r\n}\r\n\r\nvoid doVision()\r\n{\r\n\tinitEnvironment();\r\n\r\n\tauto markVisibleFn = [](Point p) {\r\n\t\tif (env[p.x][p.y] == ' ')\r\n\t\t\t// Mark as hit by the ray\r\n\t\t\tvis[p.x][p.y] = '.';\r\n\t\telse\r\n\t\t\t// Copy visible object\r\n\t\t\tvis[p.x][p.y] = env[p.x][p.y];\r\n\t};\r\n\tauto markTransparentFn = [](Point p) {};\r\n\tauto passesLightFn = [](Point p) {\r\n\t\treturn env[p.x][p.y] != '#';\r\n\t};\r\n\tauto inBoundsFn = [](Point p) { return true; };\r\n\r\n\tDoVision(pos, 15, markVisibleFn, markTransparentFn, passesLightFn, inBoundsFn);\r\n}\r\n\r\n[[maybe_unused]]\r\nvoid dumpVisibleEnv()\r\n{\r\n\tchar buf[4096];\r\n\tint sz = 0;\r\n\tfor (int i = 0; i < ENV_HEIGHT; i++) {\r\n\t\tfor (int j = 0; j < ENV_WIDTH; j++) {\r\n\t\t\tsz += snprintf(buf + sz, sizeof(buf) - sz, \"%c \", vis[i][j]);\r\n\t\t}\r\n\t\tsz += snprintf(buf + sz, sizeof(buf) - sz, \"\\n\");\r\n\t}\r\n#ifdef _WIN32\r\n\t_write(2, buf, sz);\r\n#else\r\n\twrite(2, buf, sz);\r\n#endif\r\n}\r\n\r\n// This test case checks the visibility of surrounding objects\r\nTEST(VisionTest, VisibleObjects)\r\n{\r\n\tdoVision();\r\n\r\n\tfor (const auto &o : objects) {\r\n\t\tif (o.second)\r\n\t\t\t// Visible object\r\n\t\t\tEXPECT_EQ(vis[o.first.x][o.first.y], '#') << \"Expext visible wall or object\";\r\n\t\telse\r\n\t\t\t// Invisible object\r\n\t\t\tEXPECT_EQ(vis[o.first.x][o.first.y], ' ') << \"Expect invisible tile\";\r\n\t}\r\n}\r\n\r\n// This test case checks the visibility of objects in a straight line\r\n// of sight parallel to the X or Y coordinate lines:\r\n// https://github.com/diasurgical/DevilutionX/pull/7901\r\nTEST(VisionTest, VisibilityInStraightLineOfSight)\r\n{\r\n\tdoVision();\r\n\r\n\tDisplacement displacements[] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };\r\n\r\n\tfor (auto &d : displacements) {\r\n\t\tPoint p = pos;\r\n\t\tbool found = false;\r\n\r\n\t\t// Move along the XY coordinate lines until a visible object is hit\r\n\t\twhile (p.x >= 0 && p.y >= 0 && p.x < ENV_WIDTH && p.y < ENV_HEIGHT) {\r\n\t\t\tp += d;\r\n\r\n\t\t\tif (vis[p.x][p.y] == '#') {\r\n\t\t\t\tfound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tEXPECT_TRUE(found) << \"Expect visible wall or object in a straight line of sight\";\r\n\t}\r\n}\r\n\r\n// This test case checks that nothing is visible through the\r\n// diagonally adjacent tiles:\r\n// https://github.com/diasurgical/DevilutionX/pull/7920\r\nTEST(VisionTest, NoVisibilityThroughAdjacentTiles)\r\n{\r\n\tchar mask[ENV_WIDTH][ENV_HEIGHT];\r\n\r\n\tdoVision();\r\n\r\n\tmemset(mask, ' ', sizeof(mask));\r\n\tbuildWallsAround(mask, pos, box_radius);\r\n\r\n\tenum State {\r\n\t\tBehindWall = 0,\r\n\t\tHitWall,\r\n\t\tOnWall,\r\n\t\tInsideBox,\r\n\t} state\r\n\t    = BehindWall;\r\n\r\n\t// Goes over each tile and compares the mask with the visible\r\n\t// environment that is behind the wall\r\n\tfor (int i = 0; i < ENV_HEIGHT; i++) {\r\n\t\tEXPECT_EQ(state, BehindWall);\r\n\t\tfor (int j = 0; j < ENV_WIDTH; j++) {\r\n\t\t\tif (state == BehindWall) {\r\n\t\t\t\t// Mask and environment are compared strictly behind\r\n\t\t\t\t// the wall\r\n\t\t\t\tEXPECT_EQ(mask[i][j], vis[i][j]) << \"Expect no \\\"leaked\\\" light through adjacent tiles\";\r\n\t\t\t}\r\n\r\n\t\t\tif (mask[i][j] == '#') {\r\n\t\t\t\tif (state == BehindWall)\r\n\t\t\t\t\tstate = HitWall;\r\n\t\t\t\telse if (state == HitWall)\r\n\t\t\t\t\tstate = OnWall;\r\n\t\t\t\telse if (state == InsideBox)\r\n\t\t\t\t\tstate = BehindWall;\r\n\t\t\t} else {\r\n\t\t\t\tif (state == HitWall)\r\n\t\t\t\t\tstate = InsideBox;\r\n\t\t\t\telse if (state == OnWall)\r\n\t\t\t\t\tstate = BehindWall;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "test/writehero_test.cpp",
    "content": "#include \"player_test.h\"\r\n\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <vector>\r\n\r\n#include <gtest/gtest.h>\r\n#include <picosha2.h>\r\n\r\n#include \"cursor.h\"\r\n#include \"engine/assets.hpp\"\r\n#include \"game_mode.hpp\"\r\n#include \"init.hpp\"\r\n#include \"loadsave.h\"\r\n#include \"pack.h\"\r\n#include \"pfile.h\"\r\n#include \"tables/playerdat.hpp\"\r\n#include \"utils/endian_swap.hpp\"\r\n#include \"utils/file_util.h\"\r\n#include \"utils/paths.h\"\r\n\r\nnamespace devilution {\r\nnamespace {\r\n\r\nconstexpr int SpellDatVanilla[] = {\r\n\t0, 1, 1, 4, 5, -1, 3, 3, 6, -1, 7, 6, 8, 9,\r\n\t8, 9, -1, -1, -1, -1, 3, 11, -1, 14, -1, -1,\r\n\t-1, -1, -1, 8, 1, 1, -1, 2, 1, 14, 9\r\n};\r\n\r\nvoid SwapLE(ItemPack &pack)\r\n{\r\n\tpack.iSeed = Swap32LE(pack.iSeed);\r\n\tpack.iCreateInfo = Swap16LE(pack.iCreateInfo);\r\n\tpack.idx = Swap16LE(pack.idx);\r\n\tpack.wValue = Swap16LE(pack.wValue);\r\n\tpack.dwBuff = Swap32LE(pack.dwBuff);\r\n}\r\n\r\nvoid SwapLE(PlayerPack &player)\r\n{\r\n\tplayer.dwLowDateTime = Swap32LE(player.dwLowDateTime);\r\n\tplayer.dwHighDateTime = Swap32LE(player.dwHighDateTime);\r\n\tplayer.pExperience = Swap32LE(player.pExperience);\r\n\tplayer.pGold = Swap32LE(player.pGold);\r\n\tplayer.pHPBase = Swap32LE(player.pHPBase);\r\n\tplayer.pMaxHPBase = Swap32LE(player.pMaxHPBase);\r\n\tplayer.pManaBase = Swap32LE(player.pManaBase);\r\n\tplayer.pMaxManaBase = Swap32LE(player.pMaxManaBase);\r\n\tplayer.pMemSpells = Swap64LE(player.pMemSpells);\r\n\tfor (ItemPack &item : player.InvBody) {\r\n\t\tSwapLE(item);\r\n\t}\r\n\tfor (ItemPack &item : player.InvList) {\r\n\t\tSwapLE(item);\r\n\t}\r\n\tfor (ItemPack &item : player.SpdList) {\r\n\t\tSwapLE(item);\r\n\t}\r\n\tplayer.wReflections = Swap16LE(player.wReflections);\r\n\tplayer.pDiabloKillLevel = Swap32LE(player.pDiabloKillLevel);\r\n\tplayer.pDifficulty = Swap32LE(player.pDifficulty);\r\n\tplayer.pDamAcFlags = Swap32LE(player.pDamAcFlags);\r\n}\r\n\r\nvoid PackItemUnique(ItemPack *id, int idx)\r\n{\r\n\tid->idx = idx;\r\n\tid->iCreateInfo = 0x2DE;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_UNIQUE;\r\n\tid->bDur = 40;\r\n\tid->bMDur = 40;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n\tid->iSeed = 0x1C0C44B0;\r\n}\r\n\r\nvoid PackItemStaff(ItemPack *id)\r\n{\r\n\tid->idx = 150;\r\n\tid->iCreateInfo = 0x2010;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_MAGIC;\r\n\tid->bDur = 75;\r\n\tid->bMDur = 75;\r\n\tid->bCh = 12;\r\n\tid->bMCh = 12;\r\n\tid->iSeed = 0x2A15243F;\r\n}\r\n\r\nvoid PackItemBow(ItemPack *id)\r\n{\r\n\tid->idx = 145;\r\n\tid->iCreateInfo = 0x0814;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_MAGIC;\r\n\tid->bDur = 60;\r\n\tid->bMDur = 60;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n\tid->iSeed = 0x449D8992;\r\n}\r\n\r\nvoid PackItemSword(ItemPack *id)\r\n{\r\n\tid->idx = 122;\r\n\tid->iCreateInfo = 0x081E;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_MAGIC;\r\n\tid->bDur = 60;\r\n\tid->bMDur = 60;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n\tid->iSeed = 0x680FAC02;\r\n}\r\n\r\nvoid PackItemRing1(ItemPack *id)\r\n{\r\n\tid->idx = 153;\r\n\tid->iCreateInfo = 0xDE;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_MAGIC;\r\n\tid->bDur = 0;\r\n\tid->bMDur = 0;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n\tid->iSeed = 0x5B41AFA8;\r\n}\r\n\r\nvoid PackItemRing2(ItemPack *id)\r\n{\r\n\tid->idx = 153;\r\n\tid->iCreateInfo = 0xDE;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_MAGIC;\r\n\tid->bDur = 0;\r\n\tid->bMDur = 0;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n\tid->iSeed = 0x1E41FEFC;\r\n}\r\n\r\nvoid PackItemAmulet(ItemPack *id)\r\n{\r\n\tid->idx = 155;\r\n\tid->iCreateInfo = 0xDE;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_MAGIC;\r\n\tid->bDur = 0;\r\n\tid->bMDur = 0;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n\tid->iSeed = 0x70A0383A;\r\n}\r\n\r\nvoid PackItemArmor(ItemPack *id)\r\n{\r\n\tid->idx = 70;\r\n\tid->iCreateInfo = 0xDE;\r\n\tid->bId = 1 + 2 * ITEM_QUALITY_MAGIC;\r\n\tid->bDur = 90;\r\n\tid->bMDur = 90;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n\tid->iSeed = 0x63AAC49B;\r\n}\r\n\r\nvoid PackItemFullRejuv(ItemPack *id, int i)\r\n{\r\n\tconst uint32_t seeds[] = { 0x7C253335, 0x3EEFBFF8, 0x76AFB1A9, 0x38EB45FE, 0x1154E197, 0x5964B644, 0x76B58BEB, 0x002A6E5A };\r\n\tid->idx = ItemMiscIdIdx(IMISC_FULLREJUV);\r\n\tid->iSeed = seeds[i];\r\n\tid->iCreateInfo = 0;\r\n\tid->bId = 2 * ITEM_QUALITY_NORMAL;\r\n\tid->bDur = 0;\r\n\tid->bMDur = 0;\r\n\tid->bCh = 0;\r\n\tid->bMCh = 0;\r\n}\r\n\r\nint PrepareInvSlot(PlayerPack *pPack, int pos, int size, int start = 0)\r\n{\r\n\tstatic char ret = 0;\r\n\tif (start)\r\n\t\tret = 0;\r\n\t++ret;\r\n\tif (size == 0) {\r\n\t\tpPack->InvGrid[pos] = ret;\r\n\t} else if (size == 1) {\r\n\t\tpPack->InvGrid[pos] = ret;\r\n\t\tpPack->InvGrid[pos - 10] = -ret;\r\n\t\tpPack->InvGrid[pos - 20] = -ret;\r\n\t} else if (size == 2) {\r\n\t\tpPack->InvGrid[pos] = ret;\r\n\t\tpPack->InvGrid[pos + 1] = -ret;\r\n\t\tpPack->InvGrid[pos - 10] = -ret;\r\n\t\tpPack->InvGrid[pos - 10 + 1] = -ret;\r\n\t\tpPack->InvGrid[pos - 20] = -ret;\r\n\t\tpPack->InvGrid[pos - 20 + 1] = -ret;\r\n\t} else if (size == 3) {\r\n\t\tpPack->InvGrid[pos] = ret;\r\n\t\tpPack->InvGrid[pos + 1] = -ret;\r\n\t\tpPack->InvGrid[pos - 10] = -ret;\r\n\t\tpPack->InvGrid[pos - 10 + 1] = -ret;\r\n\t} else {\r\n\t\tabort();\r\n\t}\r\n\treturn ret - 1;\r\n}\r\n\r\nvoid PackPlayerTest(PlayerPack *pPack)\r\n{\r\n\tmemset(pPack, 0, 0x4F2);\r\n\tpPack->destAction = -1;\r\n\tpPack->destParam1 = 0;\r\n\tpPack->destParam2 = 0;\r\n\tpPack->plrlevel = 0;\r\n\tpPack->pExperience = 1583495809;\r\n\tpPack->pLevel = 50;\r\n\tpPack->px = 75;\r\n\tpPack->py = 68;\r\n\tpPack->targx = 75;\r\n\tpPack->targy = 68;\r\n\tpPack->pGold = 0;\r\n\tpPack->pStatPts = 0;\r\n\tpPack->pDiabloKillLevel = 3;\r\n\tfor (auto i = 0; i < 40; i++)\r\n\t\tpPack->InvList[i].idx = -1;\r\n\tfor (auto i = 0; i < 7; i++)\r\n\t\tpPack->InvBody[i].idx = -1;\r\n\tfor (auto i = 0; i < MaxBeltItems; i++)\r\n\t\tPackItemFullRejuv(pPack->SpdList + i, i);\r\n\tfor (auto i = 1; i < 37; i++) {\r\n\t\tif (SpellDatVanilla[i] != -1) {\r\n\t\t\tpPack->pMemSpells |= 1ULL << (i - 1);\r\n\t\t\tpPack->pSplLvl[i] = 15;\r\n\t\t}\r\n\t}\r\n\tfor (auto i = 0; i < 7; i++)\r\n\t\tpPack->InvBody[i].idx = -1;\r\n\tstrcpy(pPack->pName, \"TestPlayer\");\r\n\tpPack->pClass = static_cast<uint8_t>(HeroClass::Rogue);\r\n\tpPack->pBaseStr = 20 + 35;\r\n\tpPack->pBaseMag = 15 + 55;\r\n\tpPack->pBaseDex = 30 + 220;\r\n\tpPack->pBaseVit = 20 + 60;\r\n\tpPack->pHPBase = ((20 + 10) << 6) + ((20 + 10) << 5) + 48 * 128 + (60 << 6);\r\n\tpPack->pMaxHPBase = pPack->pHPBase;\r\n\tpPack->pManaBase = (15 << 6) + (15 << 5) + 48 * 128 + (55 << 6);\r\n\tpPack->pMaxManaBase = pPack->pManaBase;\r\n\r\n\tPackItemUnique(pPack->InvBody + INVLOC_HEAD, 52);\r\n\tPackItemRing1(pPack->InvBody + INVLOC_RING_LEFT);\r\n\tPackItemRing2(pPack->InvBody + INVLOC_RING_RIGHT);\r\n\tPackItemAmulet(pPack->InvBody + INVLOC_AMULET);\r\n\tPackItemArmor(pPack->InvBody + INVLOC_CHEST);\r\n\tPackItemBow(pPack->InvBody + INVLOC_HAND_LEFT);\r\n\r\n\tPackItemStaff(pPack->InvList + PrepareInvSlot(pPack, 28, 2, 1));\r\n\tPackItemSword(pPack->InvList + PrepareInvSlot(pPack, 20, 1));\r\n\r\n\tpPack->_pNumInv = 2;\r\n\r\n\tSwapLE(*pPack);\r\n}\r\n\r\nvoid AssertPlayer(Player &player)\r\n{\r\n\tASSERT_EQ(CountU8(player._pSplLvl, 64), 23);\r\n\tASSERT_EQ(Count8(player.InvGrid, InventoryGridCells), 9);\r\n\tASSERT_EQ(CountItems(player.InvBody, NUM_INVLOC), 6);\r\n\tASSERT_EQ(CountItems(player.InvList, InventoryGridCells), 2);\r\n\tASSERT_EQ(CountItems(player.SpdList, MaxBeltItems), 8);\r\n\tASSERT_EQ(CountItems(&player.HoldItem, 1), 0);\r\n\r\n\tASSERT_EQ(player.position.tile.x, 75);\r\n\tASSERT_EQ(player.position.tile.y, 68);\r\n\tASSERT_EQ(player.position.future.x, 75);\r\n\tASSERT_EQ(player.position.future.y, 68);\r\n\tASSERT_EQ(player.plrlevel, 0);\r\n\tASSERT_EQ(player.destAction, -1);\r\n\tASSERT_STREQ(player._pName, \"TestPlayer\");\r\n\tASSERT_EQ(player._pClass, HeroClass::Rogue);\r\n\tASSERT_EQ(player._pBaseStr, 55);\r\n\tASSERT_EQ(player._pStrength, 124);\r\n\tASSERT_EQ(player._pBaseMag, 70);\r\n\tASSERT_EQ(player._pMagic, 80);\r\n\tASSERT_EQ(player._pBaseDex, 250);\r\n\tASSERT_EQ(player._pDexterity, 281);\r\n\tASSERT_EQ(player._pBaseVit, 80);\r\n\tASSERT_EQ(player._pVitality, 90);\r\n\tASSERT_EQ(player.getCharacterLevel(), 50);\r\n\tASSERT_EQ(player._pStatPts, 0);\r\n\tASSERT_EQ(player._pExperience, 1583495809);\r\n\tASSERT_EQ(player._pGold, 0);\r\n\tASSERT_EQ(player._pMaxHPBase, 12864);\r\n\tASSERT_EQ(player._pHPBase, 12864);\r\n\tASSERT_EQ(player.getBaseToBlock(), 20);\r\n\tASSERT_EQ(player._pMaxManaBase, 11104);\r\n\tASSERT_EQ(player._pManaBase, 11104);\r\n\tASSERT_EQ(player._pMemSpells, 66309357295);\r\n\tASSERT_EQ(player._pNumInv, 2);\r\n\tASSERT_EQ(player.wReflections, 0);\r\n\tASSERT_EQ(player.pTownWarps, 0);\r\n\tASSERT_EQ(player.pDungMsgs, 0);\r\n\tASSERT_EQ(player.pDungMsgs2, 0);\r\n\tASSERT_EQ(player.pLvlLoad, 0);\r\n\tASSERT_EQ(player.pDiabloKillLevel, 3);\r\n\tASSERT_EQ(player.pManaShield, 0);\r\n\tASSERT_EQ(player.pDamAcFlags, ItemSpecialEffectHf::None);\r\n\r\n\tASSERT_EQ(player._pmode, 0);\r\n\tASSERT_EQ(Count8(player.walkpath, MaxPathLengthPlayer), MaxPathLengthPlayer);\r\n\tASSERT_EQ(player._pgfxnum, 36);\r\n\tASSERT_EQ(player.AnimInfo.ticksPerFrame, 4);\r\n\tASSERT_EQ(player.AnimInfo.tickCounterOfCurrentFrame, 1);\r\n\tASSERT_EQ(player.AnimInfo.numberOfFrames, 20);\r\n\tASSERT_EQ(player.AnimInfo.currentFrame, 0);\r\n\tASSERT_EQ(player.queuedSpell.spellId, SpellID::Invalid);\r\n\tASSERT_EQ(player.queuedSpell.spellType, SpellType::Invalid);\r\n\tASSERT_EQ(player.queuedSpell.spellFrom, 0);\r\n\tASSERT_EQ(player.inventorySpell, SpellID::Null);\r\n\tASSERT_EQ(player._pRSpell, SpellID::Invalid);\r\n\tASSERT_EQ(player._pRSplType, SpellType::Invalid);\r\n\tASSERT_EQ(player._pSBkSpell, SpellID::Invalid);\r\n\tASSERT_EQ(player._pAblSpells, 134217728);\r\n\tASSERT_EQ(player._pScrlSpells, 0);\r\n\tASSERT_EQ(player._pSpellFlags, SpellFlag::None);\r\n\tASSERT_TRUE(player.UsesRangedWeapon());\r\n\tASSERT_EQ(player._pBlockFlag, 0);\r\n\tASSERT_EQ(player._pLightRad, 11);\r\n\tASSERT_EQ(player._pDamageMod, 101);\r\n\tASSERT_EQ(player._pHitPoints, 16640);\r\n\tASSERT_EQ(player._pMaxHP, 16640);\r\n\tASSERT_EQ(player._pMana, 14624);\r\n\tASSERT_EQ(player._pMaxMana, 14624);\r\n\tASSERT_EQ(player.getNextExperienceThreshold(), 1583495809);\r\n\tASSERT_EQ(player._pMagResist, 75);\r\n\tASSERT_EQ(player._pFireResist, 16);\r\n\tASSERT_EQ(player._pLghtResist, 75);\r\n\tASSERT_EQ(CountBool(player._pLvlVisited, NUMLEVELS), 0);\r\n\tASSERT_EQ(CountBool(player._pSLvlVisited, NUMLEVELS), 0);\r\n\tASSERT_EQ(player._pNFrames, 20);\r\n\tASSERT_EQ(player._pWFrames, 8);\r\n\tASSERT_EQ(player._pAFrames, 0);\r\n\tASSERT_EQ(player._pAFNum, 0);\r\n\tASSERT_EQ(player._pSFrames, 16);\r\n\tASSERT_EQ(player._pSFNum, 12);\r\n\tASSERT_EQ(player._pHFrames, 0);\r\n\tASSERT_EQ(player._pDFrames, 20);\r\n\tASSERT_EQ(player._pBFrames, 0);\r\n\tASSERT_EQ(player._pIMinDam, 1);\r\n\tASSERT_EQ(player._pIMaxDam, 14);\r\n\tASSERT_EQ(player._pIAC, 115);\r\n\tASSERT_EQ(player._pIBonusDam, 0);\r\n\tASSERT_EQ(player._pIBonusToHit, 0);\r\n\tASSERT_EQ(player._pIBonusAC, 0);\r\n\tASSERT_EQ(player._pIBonusDamMod, 0);\r\n\tASSERT_EQ(player._pISpells, 0);\r\n\tASSERT_EQ(player._pIFlags, ItemSpecialEffect::None);\r\n\tASSERT_EQ(player._pIGetHit, 0);\r\n\tASSERT_EQ(player._pISplLvlAdd, 0);\r\n\tASSERT_EQ(player._pIEnAc, 0);\r\n\tASSERT_EQ(player._pIFMinDam, 0);\r\n\tASSERT_EQ(player._pIFMaxDam, 0);\r\n\tASSERT_EQ(player._pILMinDam, 0);\r\n\tASSERT_EQ(player._pILMaxDam, 0);\r\n\tASSERT_EQ(player.pOriginalCathedral, 0);\r\n}\r\n\r\nTEST(Writehero, pfile_write_hero)\r\n{\r\n\tLoadCoreArchives();\r\n\tLoadGameArchives();\r\n\r\n\t// The tests need spawn.mpq or diabdat.mpq\r\n\tif (!HaveMainData()) {\r\n\t\tGTEST_SKIP() << \"MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test\";\r\n\t}\r\n\r\n\tconst std::string savePath = paths::BasePath() + \"multi_0.sv\";\r\n\tpaths::SetPrefPath(paths::BasePath());\r\n\tRemoveFile(savePath.c_str());\r\n\r\n\tgbVanilla = true;\r\n\tgbIsHellfire = false;\r\n\tgbIsSpawn = false;\r\n\tgbIsMultiplayer = true;\r\n\tgbIsHellfireSaveGame = false;\r\n\tleveltype = DTYPE_TOWN;\r\n\tgiNumberOfLevels = 17;\r\n\r\n\tPlayers.resize(1);\r\n\tMyPlayerId = 0;\r\n\tMyPlayer = &Players[MyPlayerId];\r\n\r\n\tLoadSpellData();\r\n\tLoadPlayerDataFiles();\r\n\tLoadMonsterData();\r\n\tLoadItemData();\r\n\t_uiheroinfo info {};\r\n\tinfo.heroclass = HeroClass::Rogue;\r\n\tpfile_ui_save_create(&info);\r\n\tPlayerPack pks;\r\n\tPackPlayerTest(&pks);\r\n\tUnPackPlayer(pks, *MyPlayer);\r\n\tAssertPlayer(Players[0]);\r\n\tpfile_write_hero();\r\n\r\n\tuintmax_t fileSize;\r\n\tASSERT_TRUE(GetFileSize(savePath.c_str(), &fileSize));\r\n\tconst size_t size = static_cast<size_t>(fileSize);\r\n\tFILE *f = OpenFile(savePath.c_str(), \"rb\");\r\n\tASSERT_TRUE(f != nullptr);\r\n\tconst std::unique_ptr<char[]> data { new char[size] };\r\n\tASSERT_EQ(std::fread(data.get(), size, 1, f), 1);\r\n\tstd::fclose(f);\r\n\r\n\tstd::vector<unsigned char> s(picosha2::k_digest_size);\r\n\tpicosha2::hash256(data.get(), data.get() + size, s.begin(), s.end());\r\n\tEXPECT_EQ(picosha2::bytes_to_hex_string(s.begin(), s.end()),\r\n\t    \"a79367caae6192d54703168d82e0316aa289b2a33251255fad8abe34889c1d3a\");\r\n}\r\n\r\n} // namespace\r\n} // namespace devilution\r\n"
  },
  {
    "path": "tools/Dockerfile.s390x",
    "content": "FROM s390x/alpine\r\n\r\n# This command uses the `wget` from BusyBox.\r\nRUN wget -nv -nc https://github.com/diasurgical/devilutionx-assets/releases/download/v2/spawn.mpq -P /opt/\r\n\r\n# We use clang instead of GCC to have ASAN. GCC does not support ASAN with musl.\r\n# We also need to install GCC because it provides crtbeginS.o:\r\n# https://pkgs.alpinelinux.org/contents?file=crtbeginS.o&path=&name=gcc&branch=edge&repo=main&arch=s390x\r\nRUN apk add --no-cache \\\r\n\tclang15 gcc binutils musl-dev ninja cmake ccache sdl2-dev sdl2_image-dev fmt-dev \\\r\n\tlibpng-dev bzip2-dev gtest-dev\r\n\r\nENV CC=/usr/bin/clang CXX=/usr/bin/clang++\r\n"
  },
  {
    "path": "tools/build_and_install_smpq.ps1",
    "content": "<#\r\n.SYNOPSIS\r\n    Downloads, builds and installs SMPQ from source on Windows.\r\n\r\n.DESCRIPTION\r\n    Installs SMPQ to $env:LOCALAPPDATA\\Programs\\smpq for development on Windows.\r\n    Requires: cmake, tar and Visual Studio as setup by following the DevilutionX build instructions\r\n#>\r\n\r\n$ErrorActionPreference = \"Stop\"\r\n\r\nif (-not (Get-Command cmake -ErrorAction SilentlyContinue)) {\r\n    Write-Error \"cmake is required but not found in PATH.\"\r\n}\r\n\r\nif (-not (Get-Command tar -ErrorAction SilentlyContinue)) {\r\n    Write-Error \"tar is required but not found in PATH.\"\r\n}\r\n\r\n$STORMLIB_VERSION = \"e87c2389cd7ed7e3bef4965a482f43cdddcf8f75\"\r\n$SMPQ_VERSION = \"1.7\"\r\n\r\n$ScriptRoot = $PSScriptRoot\r\nif (-not $ScriptRoot) { $ScriptRoot = $PWD }\r\n$WorkDir = Join-Path $ScriptRoot \"tmp\\smpq\"\r\n$StormLib_Src = Join-Path $WorkDir \"StormLib-$STORMLIB_VERSION\"\r\n$StagingDir = Join-Path $WorkDir \"smpq-staging\"\r\n$StagingDirFwd = $StagingDir -replace \"\\\\\", \"/\"\r\n$Smpq_Src = Join-Path $WorkDir \"smpq-$SMPQ_VERSION\"\r\n$Smpq_BuildDir = Join-Path $Smpq_Src \"build\"\r\n$InstallDir = \"$env:LOCALAPPDATA\\Programs\\smpq\"\r\n\r\nif (-not (Test-Path -Path $WorkDir)) {\r\n    New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null\r\n}\r\n\r\n$StormLib_Tar = Join-Path $WorkDir \"stormlib-${STORMLIB_VERSION}.tar.gz\"\r\nif (-not (Test-Path -Path $StormLib_Tar -PathType Leaf)) {\r\n    Write-Host \"Downloading StormLib ${STORMLIB_VERSION}...\"\r\n    $StormLib_Url = \"https://github.com/ladislav-zezula/StormLib/archive/${STORMLIB_VERSION}.tar.gz\"\r\n    Invoke-WebRequest -Uri $StormLib_Url -OutFile $StormLib_Tar\r\n}\r\nelse {\r\n    Write-Host \"StormLib tarball already exists. Skipping download.\"\r\n}\r\n\r\nif (-not (Test-Path -Path $StormLib_Src)) {\r\n    Write-Host \"Extracting StormLib ${STORMLIB_VERSION}...\"\r\n    tar -C $WorkDir -xf $StormLib_Tar\r\n}\r\nelse {\r\n    Write-Host \"StormLib source already exists. Skipping extraction.\"\r\n}\r\n\r\nWrite-Host \"Building and installing StormLib ${STORMLIB_VERSION}...\"\r\n$StormLib_BuildDir = Join-Path $StormLib_Src \"build\"\r\ncmake -S \"$StormLib_Src\" -B \"$StormLib_BuildDir\" `\r\n    -DCMAKE_BUILD_TYPE=Release `\r\n    -DCMAKE_INSTALL_PREFIX=\"$StagingDir\" `\r\n    -DBUILD_SHARED_LIBS=OFF `\r\n    -DSTORM_BUILD_TESTS=OFF `\r\n    -DSTORM_USE_BUNDLED_LIBRARIES=ON `\r\n    -DCMAKE_C_FLAGS=\"/wd4101 /wd4244 /wd4267 /wd4334\" `\r\n    -DCMAKE_CXX_FLAGS=\"/wd4101 /wd4244 /wd4267 /wd4334\"\r\ncmake --build \"$StormLib_BuildDir\" --config Release --target install\r\n\r\n$Smpq_Tar = Join-Path $WorkDir \"smpq_${SMPQ_VERSION}.orig.tar.gz\"\r\nif (-not (Test-Path -Path $Smpq_Tar)) {\r\n    Write-Host \"Downloading SMPQ ${SMPQ_VERSION}...\"\r\n    $Smpq_Url = \"https://launchpad.net/smpq/trunk/${SMPQ_VERSION}/+download/smpq_${SMPQ_VERSION}.orig.tar.gz\"\r\n    Invoke-WebRequest -Uri $Smpq_Url -OutFile $Smpq_Tar\r\n}\r\nelse {\r\n    Write-Host \"SMPQ tarball already exists. Skipping download.\"\r\n}\r\n\r\nif (-not (Test-Path -Path $Smpq_Src)) {\r\n    Write-Host \"Extracting SMPQ ${SMPQ_VERSION}...\"\r\n    tar -C $WorkDir -xf $Smpq_Tar\r\n}\r\nelse {\r\n    Write-Host \"SMPQ source already exists. Skipping extraction.\"\r\n}\r\n\r\nWrite-Host \"Applying patches to SMPQ...\"\r\n$CMakeListPath = Join-Path $Smpq_Src \"CMakeLists.txt\"\r\nif (Test-Path $CMakeListPath) {\r\n    $CMakeParams = Get-Content -Raw $CMakeListPath\r\n    if ($CMakeParams -notmatch \"PROPERTIES LANGUAGE CXX\") {\r\n        Write-Host \"Patching CMakeLists.txt to force C++...\"\r\n        # StormLib is C++ and must be linked with a C++ linker.\r\n        $Patch1 = \"project(SMPQ)`r`nfile(GLOB_RECURSE CFILES `\"`${CMAKE_SOURCE_DIR}/*.c`\")`r`nSET_SOURCE_FILES_PROPERTIES(`${CFILES} PROPERTIES LANGUAGE CXX)\"\r\n        $CMakeParams = $CMakeParams -replace \"project\\(SMPQ\\)\", $Patch1\r\n        \r\n        # Do not generate the manual\r\n        $CMakeParams = $CMakeParams -replace \"if\\(NOT CMAKE_CROSSCOMPILING\\)\", \"if(FALSE)\"\r\n        Set-Content -Path $CMakeListPath -Value $CMakeParams -Encoding UTF8\r\n    }\r\n}\r\n\r\n# Fix C++ compilation errors in dirname.c (implicit void* cast)\r\n$DirnameC = Join-Path $Smpq_Src \"dirname.c\"\r\nif (Test-Path $DirnameC) {\r\n    $DirnameContent = Get-Content -Raw $DirnameC\r\n    if ($DirnameContent -notmatch \"\\(char \\*\\) realloc\") {\r\n        Write-Host \"Patching dirname.c to add explicit casts...\"\r\n        $DirnameContent = $DirnameContent -replace \"retfail = realloc\", \"retfail = (char *) realloc\"\r\n        Set-Content -Path $DirnameC -Value $DirnameContent -Encoding UTF8\r\n    }\r\n}\r\n\r\nWrite-Host \"Building and installing SMPQ ${SMPQ_VERSION}...\"\r\ncmake -S \"$Smpq_Src\" -B \"$Smpq_BuildDir\" `\r\n    -DCMAKE_INSTALL_PREFIX=\"$InstallDir\" `\r\n    -DWITH_KDE=OFF `\r\n    -DCMAKE_PREFIX_PATH=\"$StagingDirFwd\" `\r\n    -DSTORMLIB_INCLUDE_DIR=\"$StagingDirFwd/include\" `\r\n    -DSTORMLIB_LIBRARY=\"$StagingDirFwd/lib/StormLib.lib\" `\r\n    -DCMAKE_CXX_FLAGS=\"-D__STORMLIB_NO_STATIC_LINK__ /wd4312\" `\r\n    -DCMAKE_C_FLAGS=\"-D__STORMLIB_NO_STATIC_LINK__ /wd4312\"\r\ncmake --build \"$Smpq_BuildDir\" --config Release --target install\r\nif ($LASTEXITCODE -eq 0) {\r\n    Write-Host \"SMPQ installed successfully.\"\r\n    # Add to PATH\r\n    $BinPath = Join-Path $InstallDir \"bin\"\r\n    $UserPath = [Environment]::GetEnvironmentVariable(\"Path\", \"User\")\r\n    if ($UserPath -notlike \"*$BinPath*\") {\r\n        Write-Host \"Adding '$BinPath' to User PATH environment variable...\"\r\n        [Environment]::SetEnvironmentVariable(\"Path\", \"$UserPath;$BinPath\", \"User\")\r\n        $env:Path += \";$BinPath\"\r\n    }\r\n    else {\r\n        Write-Host \"'$BinPath' is already in the User PATH.\"\r\n    }\r\n\r\n    Write-Host \"Done.\"\r\n}\r\nelse {\r\n    Write-Error \"Failed to install SMPQ.\"\r\n    exit 1\r\n}\r\n\r\n"
  },
  {
    "path": "tools/build_and_install_smpq.sh",
    "content": "#!/bin/sh\n\n# Downloads, builds, and installs SMPQ from source.\n#\n# Useful when developing on systems that do not have an SMPQ package.\n# Compatible with Linux, *BSD, and macOS.\n# Requires: cmake curl sed sudo zlib bzip2\n\nset -ex\n\nPARALLELISM=\"$(getconf _NPROCESSORS_ONLN)\"\nif [ \"$PARALLELISM\" = \"undefined\" ] && [ -f /usr/sbin/sysctl ]; then\n\t# On older OSX, such as 10.4, _NPROCESSOR_ONLN is not defined.\n\tif [ -z \"$CC\" ]; then\n\t\t# Tiger's default cc is too old to build smpq, so we default to gcc instead (e.g. from macports).\n\t\texport CC=gcc\n\tfi\n\tPARALLELISM=\"$(/usr/sbin/sysctl -n hw.ncpu)\"\nfi\n\nSTORMLIB_VERSION=e01d93cc8ae743cfe2da5450854c5d2e3a939265\nSTORMLIB_SRC=\"/tmp/StormLib-$STORMLIB_VERSION\"\nSMPQ_VERSION=1.7\nSMPQ_SRC=\"/tmp/smpq-$SMPQ_VERSION\"\n\n# Download, build, and install the static version of StormLib, an SMPQ dependency, to the staging prefix.\nif ! [ -d \"$STORMLIB_SRC\" ]; then\n\tcurl -L -s \"https://github.com/ladislav-zezula/StormLib/archive/${STORMLIB_VERSION}.tar.gz\" | tar -C /tmp -xvzf -\nfi\n\ncmake -S\"$STORMLIB_SRC\" -B\"$STORMLIB_SRC\"/build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/tmp/smpq-staging -DBUILD_SHARED_LIBS=OFF \\\n\t-DWITH_STATIC=ON -DSTORM_BUILD_TESTS=OFF -DWITH_LIBTOMCRYPT=OFF\ncmake --build \"$STORMLIB_SRC\"/build --config Release --target install -j\"$PARALLELISM\"\n\n# Download, build, and install SMPQ.\nif ! [ -d \"$SMPQ_SRC\" ]; then\n\tcurl -L -s \"https://launchpad.net/smpq/trunk/${SMPQ_VERSION}/+download/smpq_${SMPQ_VERSION}.orig.tar.gz\" | tar -C /tmp -xvzf -\n\n\t# StormLib.a is C++ and must be linked with a C++ linker (e.g. via g++ instead of gcc).\n\tsed -i.bak -e '/^project/a\\\nfile(GLOB_RECURSE CFILES \"${CMAKE_SOURCE_DIR}/*.c\")\\\nSET_SOURCE_FILES_PROPERTIES(${CFILES} PROPERTIES LANGUAGE CXX)' \"$SMPQ_SRC\"/CMakeLists.txt\n\n\t# StormLib is linked statically, so we need to add links its dynamic link dependencies to smpq itself.\n\tsed -i.bak -e 's|target_link_libraries(smpq ${STORMLIB_LIBRARY})|find_package(ZLIB REQUIRED)\\\n\tfind_package(BZip2 REQUIRED)\\\n\ttarget_link_libraries(smpq ${STORMLIB_LIBRARY} ${ZLIB_LIBRARY} ${BZIP2_LIBRARIES})|' \"$SMPQ_SRC\"/CMakeLists.txt\n\n\t# Do not generate the manual.\n\tsed -i.bak -e 's|if(NOT CMAKE_CROSSCOMPILING)|if(FALSE)|' \"$SMPQ_SRC\"/CMakeLists.txt\n\n\t# Fix missing header includes.\n\tsed -i.bak -e '/#include <string.h>/a\\\n#include <stdio.h>' \"$SMPQ_SRC/append.c\"\n\tsed -i.bak -e '/#include <StormLib.h>/a\\\n#include <string.h>' \"$SMPQ_SRC/remove.c\"\nfi\n\n# The StormLib version check in SMPQ CMake is broken. We bypass it by passing the paths to StormLib explicitly.\ncmake -S\"$SMPQ_SRC\" -B\"$SMPQ_SRC\"/build -DCMAKE_BUILD_TYPE=Release -DWITH_KDE=OFF -DCMAKE_PREFIX_PATH=/tmp/smpq-staging \\\n\t-DSTORMLIB_INCLUDE_DIR=/tmp/smpq-staging/include -DSTORMLIB_LIBRARY=/tmp/smpq-staging/lib/libstorm.a\nsudo cmake --build \"$SMPQ_SRC\"/build --config Release --target install -j\"$PARALLELISM\"\n"
  },
  {
    "path": "tools/build_and_run_benchmark.py",
    "content": "#!/usr/bin/env python\n\nimport subprocess\nimport argparse\nimport os\nimport sys\nimport pathlib\nimport shlex\nimport platform\n\n_PROFILE = \"/tmp/out.profile\"\n\n\ndef run(*args: list[str], env: dict[str, str] | None = None):\n    print(\n        \"+\",\n        *(map(shlex.quote, [f\"{k}={v}\" for k, v in env.items()] if env else [])),\n        *map(shlex.quote, args),\n        file=sys.stderr,\n    )\n    full_env = None\n    if env:\n        full_env = os.environ.copy()\n        for k, v in env.items():\n            full_env[k] = v\n    subprocess.run(args, stdout=sys.stdout, stderr=sys.stderr, check=True, env=full_env)\n\n\ndef nproc():\n    return len(os.sched_getaffinity(0))\n\n\ndef maybe_create_build_dir(dir: str, args: list[str]):\n    if os.path.isdir(dir):\n        return\n    print(\"Creating build directory at \", dir, file=sys.stderr)\n    run(\"cmake\", \"-S.\", f\"-B{dir}\", \"-DCMAKE_BUILD_TYPE=RelWithDebInfo\", *args)\n\n\ndef build_target(dir: str, target: str):\n    run(\"cmake\", \"--build\", dir, \"-j\", str(nproc()), \"--target\", target)\n\n\ndef run_benchmark(dir: str, target: str, benchmark_args: list[str], gperf: bool):\n    args = []\n    if platform.system() == \"Linux\":\n        args.append(\"tools/linux_reduced_cpu_variance_run.sh\")\n    env = None\n    if gperf:\n        env: dict[str, str] = {\"CPUPROFILE\": _PROFILE}\n        if not \"CPUPROFILE_FREQUENCY\" in env:\n            env[\"CPUPROFILE_FREQUENCY\"] = \"1000\"\n    run(*args, f\"{dir}/{target}\", *benchmark_args, env=env)\n\n\ndef run_pprof(dir: str, target: str, port: int):\n    run(\"pprof\", f\"--http=localhost:{port}\", f\"{dir}/{target}\", _PROFILE)\n\n\ndef main():\n    os.chdir(pathlib.Path(__file__).resolve().parent.parent)\n    parser = argparse.ArgumentParser(description=\"Builds and runs a benchmark\")\n    parser.add_argument(\"-B\", \"--build\", help=\"build directory\")\n    parser.add_argument(\n        \"--gperf\", action=argparse.BooleanOptionalAction, help=\"profile with gperftools\"\n    )\n    parser.add_argument(\"--port\", type=int, default=1337, help=\"pprof server port\")\n    parser.add_argument(\"target\", help=\"benchmark target\")\n    parser.add_argument(\n        \"benchmark_args\",\n        nargs=\"*\",\n        help=\"arguments passed to the benchmark binary\",\n    )\n    parser.add_argument(\"--run\", action=argparse.BooleanOptionalAction, default=True, help=\"If false, only builds the target\")\n    args = parser.parse_args()\n    build = args.build\n    if not build:\n        build = \"build-gperf\" if args.gperf else \"build-reld\"\n    configure_args = []\n    if args.gperf:\n        configure_args.append(\"-DGPERF=ON\")\n    try:\n        maybe_create_build_dir(build, configure_args)\n        build_target(build, args.target)\n        if args.run:\n            run_benchmark(build, args.target, args.benchmark_args, args.gperf)\n            if args.gperf:\n                run_pprof(build, args.target, args.port)\n    except subprocess.CalledProcessError as e:\n        print(\"Error:\", e.cmd[0], \"failed\", file=sys.stderr)\n        return e.returncode\n    except KeyboardInterrupt as e:\n        return 1\n\n\nmain()\n"
  },
  {
    "path": "tools/build_pgo.sh",
    "content": "#!/usr/bin/env bash\n\n# Builds a PGO-optimized binary with the profile data gathered by running the test demo.\nset -euo pipefail\n\nPARALLELISM=\"$(getconf _NPROCESSORS_ONLN)\"\n\nset -x\n\nrm -rf build-profile-data/config build-profile-data/profile\nmkdir -p build-profile-data/config\ncd build-profile-data/config\nln -s ../../test/fixtures/timedemo/WarriorLevel1to2/demo_* .\ncp ../../test/fixtures/timedemo/WarriorLevel1to2/spawn_* .\ncd -\n\n# We build both versions with the same FetchContent base directory because otherwise\n# gcc will complain about the source locations for FetchContent dependencies,\n# which are stored in the build directory by default.\n# Ideally, we would only specify the location for the FetchContent src directories\n# but CMake does not support that.\ncmake -S. -Bbuild-profile-generate -G Ninja -DCMAKE_BUILD_TYPE=Release \\\n  -DDEVILUTIONX_PROFILE_GENERATE=ON \\\n  -DDEVILUTIONX_PROFILE_DIR=\"${PWD}/build-profile-data/profile\" \\\n  -DFETCHCONTENT_BASE_DIR=\"${PWD}/build-profile-data/fetchcontent-base\" \\\n  -DBUILD_TESTING=OFF \"$@\"\ncmake --build build-profile-generate -j \"$PARALLELISM\"\nbuild-profile-generate/devilutionx --diablo --spawn --lang en --demo 0 --timedemo \\\n  --save-dir build-profile-data/config\n\ncmake -S. -Bbuild-profile-use -G Ninja -DCMAKE_BUILD_TYPE=Release \\\n  -DDEVILUTIONX_PROFILE_USE=ON \\\n  -DDEVILUTIONX_PROFILE_DIR=\"${PWD}/build-profile-data/profile\" \\\n  -DFETCHCONTENT_BASE_DIR=\"${PWD}/build-profile-data/fetchcontent-base\" \\\n  -DBUILD_TESTING=OFF \"$@\"\ncmake --build build-profile-use -j \"$PARALLELISM\"\n"
  },
  {
    "path": "tools/extract_translation_data.py",
    "content": "#!/usr/bin/env python\nimport csv\nimport pathlib\n\nroot = pathlib.Path(__file__).resolve().parent.parent\ntranslation_dummy_path = root.joinpath(\"Source/translation_dummy.cpp\")\n\nbase_paths = {\n    \"classdat\": root.joinpath(\"assets/txtdata/classes/classdat.tsv\"),\n    \"monstdat\": root.joinpath(\"assets/txtdata/monsters/monstdat.tsv\"),\n    \"unique_monstdat\": root.joinpath(\"assets/txtdata/monsters/unique_monstdat.tsv\"),\n    \"itemdat\": root.joinpath(\"assets/txtdata/items/itemdat.tsv\"),\n    \"unique_itemdat\": root.joinpath(\"assets/txtdata/items/unique_itemdat.tsv\"),\n    \"item_prefixes\": root.joinpath(\"assets/txtdata/items/item_prefixes.tsv\"),\n    \"item_suffixes\": root.joinpath(\"assets/txtdata/items/item_suffixes.tsv\"),\n    \"questdat\": root.joinpath(\"assets/txtdata/quests/questdat.tsv\"),\n    \"spelldat\": root.joinpath(\"assets/txtdata/spells/spelldat.tsv\"),\n    \"textdat\": root.joinpath(\"assets/txtdata/text/textdat.tsv\"),\n}\n\nhf_paths = {\n    \"monstdat\": root.joinpath(\"mods/Hellfire/txtdata/monsters/monstdat.tsv\"),\n    \"unique_itemdat\": root.joinpath(\"mods/Hellfire/txtdata/items/unique_itemdat.tsv\"),\n    \"item_prefixes\": root.joinpath(\"mods/Hellfire/txtdata/items/item_prefixes.tsv\"),\n    \"item_suffixes\": root.joinpath(\"mods/Hellfire/txtdata/items/item_suffixes.tsv\"),\n    \"spelldat\": root.joinpath(\"mods/Hellfire/txtdata/spells/spelldat.tsv\"),\n}\n\nseen_pairs = set()\n\ndef write_entry(temp_source, var_name, context, string_value, use_p):\n    if not string_value:\n        return\n    key = (context, string_value)\n    if key in seen_pairs:\n        return\n    seen_pairs.add(key)\n    if use_p:\n        temp_source.write(f'const char *{var_name} = P_(\"{context}\", \"{string_value}\");\\n')\n    else:\n        temp_source.write(f'const char *{var_name} = N_(\"{string_value}\");\\n')\n\nreplacement_table = str.maketrans(\n    ' -',\n    '__',\n    '\\''\n)\n\ndef create_identifier(value, prefix = '', suffix = ''):\n    return prefix + value.upper().translate(replacement_table) + suffix\n\ndef process_files(paths, temp_source):\n    # Classes\n    if \"classdat\" in paths:\n        with open(paths[\"classdat\"], 'r') as tsv:\n            reader = csv.DictReader(tsv, delimiter='\\t')\n            for i, row in enumerate(reader):\n                var_name = create_identifier(row['className'], 'CLASS_', '_NAME')\n                write_entry(temp_source, var_name, \"default\", row['className'], False)\n\n    # Monsters\n    with open(paths[\"monstdat\"], 'r') as tsv:\n        reader = csv.DictReader(tsv, delimiter='\\t')\n        for row in reader:\n            var_name = create_identifier(row['_monster_id'], '', '_NAME')\n            write_entry(temp_source, var_name, \"monster\", row['name'], True)\n\n    if \"unique_monstdat\" in paths:\n        with open(paths[\"unique_monstdat\"], 'r') as tsv:\n            reader = csv.DictReader(tsv, delimiter='\\t')\n            for row in reader:\n                var_name = create_identifier(row['name'], '', '_NAME')\n                write_entry(temp_source, var_name, \"monster\", row['name'], True)\n\n    # Items\n    if \"itemdat\" in paths:\n        with open(paths[\"itemdat\"], 'r') as tsv:\n            reader = csv.DictReader(tsv, delimiter='\\t')\n            for i, row in enumerate(reader):\n                name = row['name']\n                if name in ('Scroll of None', 'Non Item', 'Book of '):\n                    continue\n                shortName = row['shortName']\n                if row['id']:\n                    base_name = create_identifier(row['id'])\n                else:\n                    base_name = create_identifier(str(i), 'ITEM_')\n\n                write_entry(temp_source, f'{base_name}_NAME', \"default\", name, False)\n                if shortName:\n                    write_entry(temp_source, f'{base_name}_SHORT_NAME', \"default\", shortName, False)\n\n    with open(paths[\"unique_itemdat\"], 'r') as tsv:\n        reader = csv.DictReader(tsv, delimiter='\\t')\n        for i, row in enumerate(reader):\n            write_entry(temp_source, f'UNIQUE_ITEM_{i}_NAME', \"default\", row['name'], False)\n\n    with open(paths[\"item_prefixes\"], 'r') as tsv:\n        reader = csv.DictReader(tsv, delimiter='\\t')\n        for i, row in enumerate(reader):\n            write_entry(temp_source, f'ITEM_PREFIX_{i}_NAME', \"default\", row['name'], False)\n\n    with open(paths[\"item_suffixes\"], 'r') as tsv:\n        reader = csv.DictReader(tsv, delimiter='\\t')\n        for i, row in enumerate(reader):\n            write_entry(temp_source, f'ITEM_SUFFIX_{i}_NAME', \"default\", row['name'], False)\n\n    # Quests\n    if \"questdat\" in paths:\n        with open(paths[\"questdat\"], 'r') as tsv:\n            reader = csv.DictReader(tsv, delimiter='\\t')\n            for i, row in enumerate(reader):\n                var_name = create_identifier(row['qlstr'], 'QUEST_', '_NAME')\n                write_entry(temp_source, var_name, \"default\", row['qlstr'], False)\n\n    # Spells\n    with open(paths[\"spelldat\"], 'r') as tsv:\n        reader = csv.DictReader(tsv, delimiter='\\t')\n        for i, row in enumerate(reader):\n            var_name = create_identifier(row['name'], 'SPELL_', '_NAME')\n            write_entry(temp_source, var_name, \"spell\", row['name'], True)\n\n    # Text/Speeches\n    if \"textdat\" in paths:\n        with open(paths[\"textdat\"], 'r') as tsv:\n            reader = csv.DictReader(tsv, delimiter='\\t')\n            for i, row in enumerate(reader):\n                write_entry(temp_source, f'TEXT_{i}', \"default\", row['txtstr'], False)\n\nwith open(translation_dummy_path, 'w') as temp_source:\n    temp_source.write(f'/**\\n')\n    temp_source.write(f' * @file translation_dummy.cpp\\n')\n    temp_source.write(f' *\\n')\n    temp_source.write(f' * Do not edit this file manually, it is automatically generated\\n')\n    temp_source.write(f' * and updated by the extract_translation_data.py script.\\n')\n    temp_source.write(f' */\\n')\n    temp_source.write(f'#include \"utils/language.h\"\\n\\n')\n    temp_source.write(f'namespace {{\\n\\n')\n\n    process_files(base_paths, temp_source)\n    process_files(hf_paths, temp_source)\n\n    temp_source.write(f'\\n}} // namespace\\n')\n"
  },
  {
    "path": "tools/gdb/README.md",
    "content": "# gdb debugging enhancements\n\nRequires gdb v14.1+.\n\nThe code in this directory is imported via `.gdbinit`.\n\nWorking directory `.gdb` is not loaded by default.\n\nYou can run gdb with `-iex 'add-auto-load-safe-path .'` to load it.\n\nFor example:\n\n```bash\ngdb -iex 'add-auto-load-safe-path .' build/devilutionx\n```\n\nIf you're using VS Code with CMake, you can instead add the following to your `.vscode/settings.json`:\n\n```json\n\"cmake.debugConfig\": {\n  \"setupCommands\": [\n    {\n      \"description\": \"Enable pretty-printing for gdb\",\n      \"text\": \"-enable-pretty-printing\",\n      \"ignoreFailures\": true\n    },\n    {\n      \"description\": \"Load gdb enhancements\",\n      \"text\": \"source ${workspaceFolder}/tools/gdb/devilution_gdb/__init__.py\",\n      \"ignoreFailures\": false\n    }\n  ]\n}\n```\n"
  },
  {
    "path": "tools/gdb/devilution_gdb/__init__.py",
    "content": "import sys\nimport pathlib\n\nsys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent))\n\nimport devilution_gdb.pretty_printers.utils.static_vector_pp as _\n"
  },
  {
    "path": "tools/gdb/devilution_gdb/pretty_printers/utils/static_vector_pp.py",
    "content": "import gdb\n\n\nclass StaticVectorPrinter(gdb.ValuePrinter):\n    def __init__(self, val):\n        self._val = val\n\n    def to_string(self):\n        return f\"{self._val.type} of length {self.num_children()}\"\n\n    def display_hint(self):\n        return \"array\"\n\n    def children(self):\n        return map(lambda i: self.child(i), range(self.num_children()))\n\n    def num_children(self):\n        return int(self._val[\"size_\"])\n\n    def child(self, n):\n        return (f\"[{n}]\", self._elements()[n])\n\n    def _elements(self):\n        return self._val[\"data_\"].reinterpret_cast(self._element_type().pointer())\n\n    def _element_type(self):\n        return self._val.type.template_argument(0)\n\n\ndef StaticVectorPrinter_fn(val):\n    if str(val.type).startswith(\"devilution::StaticVector<\"):\n        return StaticVectorPrinter(val)\n\n\ngdb.pretty_printers.append(StaticVectorPrinter_fn)\n"
  },
  {
    "path": "tools/linux_reduced_cpu_variance_run.sh",
    "content": "#!/usr/bin/env bash\n# See https://google.github.io/benchmark/reducing_variance.html\nset -x\n\nsudo cpupower frequency-set --governor performance 1>/dev/null\necho 0 | sudo tee /sys/devices/system/cpu/cpufreq/boost 1>/dev/null\n\ntaskset -c 0 \"$@\"\n{ set +x; } 2> /dev/null\nresult=$?\nset -x\n\nsudo cpupower frequency-set --governor ondemand 1>/dev/null\necho 1 | sudo tee /sys/devices/system/cpu/cpufreq/boost 1>/dev/null\n\nexit \"$result\"\n"
  },
  {
    "path": "tools/lldb/README.md",
    "content": "# lldb debugging enhancements\n\nThe code in this directory is imported via `.lldbinit`.\n\nWorking directory `.lldbinit` is not loaded by default.\n\nYou can add the following to `~/.lldbinit` to load it when launching `lldb` from the command line:\n\n```\nsettings set target.load-cwd-lldbinit true\n```\n\nIf you're using VS Code, you can instead add the following to your configuration:\n\n```json\n\"lldb.launch.initCommands\": [\"command source ${workspaceFolder}/.lldbinit\"]\n```\n"
  },
  {
    "path": "tools/lldb/devilution_lldb/__init__.py",
    "content": "import lldb\n\nimport devilution_lldb.pretty_printers.utils.static_vector_pp\n\n\ndef init():\n    devilution_lldb.pretty_printers.utils.static_vector_pp.init(lldb.debugger)\n"
  },
  {
    "path": "tools/lldb/devilution_lldb/pretty_printers/utils/static_vector_pp.py",
    "content": "import lldb\n\n\nclass StaticVectorSyntheticChildrenProvider:\n    def __init__(self, valobj: lldb.SBValue, internal_dict):\n        self._val: lldb.SBValue = valobj\n        self._size: lldb.SBValue = self._val.GetChildMemberWithName(\"size_\")\n        self._element_type: lldb.SBType = self._val.GetType().GetTemplateArgumentType(0)\n        self._element_size = self._element_type.GetByteSize()\n        self._data_addr = int(\n            self._val.GetChildMemberWithName(\"data_\").GetLoadAddress()\n        )\n\n    def num_children(self, max_children):\n        return self._size.GetValueAsUnsigned(0)\n\n    def get_child_index(self, name):\n        index = int(name)\n        return index if index < self.num_children() else None\n\n    def get_child_at_index(self, index):\n        return self._val.CreateValueFromAddress(\n            f\"[{index}]\",\n            self._data_addr + self._element_size * index,\n            self._element_type,\n        )\n\n\ndef init(debugger: lldb.debugger):\n    debugger.HandleCommand(\n        'type synthetic add -x \"devilution::StaticVector<\" -l devilution_lldb.pretty_printers.utils.static_vector_pp.StaticVectorSyntheticChildrenProvider'\n    )\n"
  },
  {
    "path": "tools/make_src_dist.py",
    "content": "#!/usr/bin/env python\n\n\"\"\"\nMakes a tarball suitable for distros.\n\nIt contains the following:\n\n1. The repo source code.\n\n2. An additional `dist` directory with:\n\n   1. `FetchContent` dependencies that currently must be vendored.\n       These are stripped from especially heavy bloat.\n\n   2. `devilutionx.mpq`.\n      While this file can be generated by the build system, it requires\n      the `smpq` host dependency which may be missing in some distributions.\n\n   3. `CMakeLists.txt` - a file with the cmake flags containing the version,\n      the path to `devilutionx.mpq` and the `FetchContent` dependency paths.\n\n      This file is automatically used by the build system if present.\n\nThe only stdout output of this script is the path to the generated tarball.\n\"\"\"\n\nimport argparse\nimport logging\nimport pathlib\nimport re\nimport shutil\nimport subprocess\nimport sys\n\n# We only package the dependencies that are:\n# 1. Uncommon in package managers (sdl_audiolib).\n# 2. Require devilutionx forks (all others).\n_DEPS = [\n    \"asio\",\n    \"libmpq\",\n    \"libsmackerdec\",\n    \"libzt\",\n    \"magic_enum\",\n    \"sdl_audiolib\",\n    \"sheenbidi\",\n    \"unordered_dense\",\n]\n_ALWAYS_VENDORED_DEPS = ['asio', 'libmpq', 'libsmackerdec', 'libzt']\n\n# These dependencies are not vendored by default.\n# Run with `--fully_vendored` to include them.\n_DEPS_NOT_VENDORED_BY_DEFAULT = ['googletest', 'benchmark', 'sdl2', 'sdl_image',\n                                 'libpng', 'libfmt', 'bzip2', 'libsodium']\n\n_ROOT_DIR = pathlib.Path(__file__).resolve().parent.parent\n_BUILD_DIR = _ROOT_DIR.joinpath('build-src-dist')\n_ARCHIVE_DIR = _BUILD_DIR.joinpath('archive')\n\n_LOGGER = logging.getLogger()\n_LOGGER.setLevel(logging.INFO)\n_LOGGER.addHandler(logging.StreamHandler(sys.stderr))\n\n\nclass Version():\n\tdef __init__(self, prefix: str, commit_sha: str):\n\t\tself.prefix = prefix\n\t\tself.commit_sha = commit_sha\n\t\tself.str = f'{prefix}-{commit_sha}' if '-' in prefix else prefix\n\n\tdef __str__(self) -> str:\n\t\treturn self.str\n\n\nclass Paths():\n\tdef __init__(self, version: Version, fully_vendored: bool):\n\t\tself.archive_top_level_dir_name = 'devilutionx-src'\n\t\tif fully_vendored:\n\t\t\tself.archive_top_level_dir_name += '-full'\n\t\tself.archive_top_level_dir_name += f'-{version}'\n\t\tself.archive_top_level_dir = _ARCHIVE_DIR.joinpath(\n\t\t\tself.archive_top_level_dir_name)\n\t\tself.dist_dir = self.archive_top_level_dir.joinpath('dist')\n\n\ndef main():\n\tparser = argparse.ArgumentParser()\n\tparser.add_argument('--fully_vendored', default=False, action='store_true')\n\targs = parser.parse_args()\n\n\tconfigure_args = [f'-S{_ROOT_DIR}',\n                   f'-B{_BUILD_DIR}', '-DBUILD_ASSETS_MPQ=ON']\n\tfor dep in sorted(set(_DEPS) - set(_ALWAYS_VENDORED_DEPS)):\n\t\tconfigure_args.append(f'-DDEVILUTIONX_SYSTEM_{dep.upper()}=OFF')\n\tif args.fully_vendored:\n\t\tfor dep in _DEPS_NOT_VENDORED_BY_DEFAULT:\n\t\t\tconfigure_args.append(f'-DDEVILUTIONX_SYSTEM_{dep.upper()}=OFF')\n\t\tconfigure_args.append('-DDISCORD_INTEGRATION=ON')\n\tcmake(*configure_args)\n\tcmake('--build', _BUILD_DIR, '--target', 'devilutionx_mpq')\n\tcmake('--build', _BUILD_DIR, '--target', 'hellfire_mpq')\n\n\tif _ARCHIVE_DIR.exists():\n\t\tshutil.rmtree(_ARCHIVE_DIR)\n\n\tversion = get_version()\n\tpaths = Paths(version, args.fully_vendored)\n\n\t_LOGGER.info(f'Copying repo files...')\n\tfor src_bytes in git('ls-files', '-z').rstrip(b'\\0').split(b'\\0'):\n\t\tsrc = src_bytes.decode()\n\t\tdst_path = paths.archive_top_level_dir.joinpath(src)\n\t\tdst_path.parent.mkdir(parents=True, exist_ok=True)\n\t\tif re.search(r'(^|/)\\.gitkeep$', src):\n\t\t\tcontinue\n\t\tshutil.copy2(_ROOT_DIR.joinpath(src), dst_path, follow_symlinks=False)\n\n\t_LOGGER.info(f'Copying devilutionx.mpq...')\n\tpaths.dist_dir.mkdir(parents=True)\n\tshutil.copy(_BUILD_DIR.joinpath('devilutionx.mpq'), paths.dist_dir)\n\t_LOGGER.info(f'Copying Hellfire.mpq...')\n\tpaths.dist_dir.joinpath('mods').mkdir(exist_ok=True)\n\tshutil.copy(_BUILD_DIR.joinpath('mods', 'Hellfire.mpq'), paths.dist_dir.joinpath('mods'))\n\n\tfor dep in _DEPS + (_DEPS_NOT_VENDORED_BY_DEFAULT if args.fully_vendored else []):\n\t\t_LOGGER.info(f'Copying {dep}...')\n\t\tshutil.copytree(\n\t\t\tsrc=_BUILD_DIR.joinpath('_deps', f'{dep}-src'),\n\t\t\tdst=paths.dist_dir.joinpath(f'{dep}-src'),\n\t\t\tignore=ignore_dep_src)\n\n\twrite_dist_cmakelists(paths, version, args.fully_vendored)\n\tprint(make_archive(paths, args.fully_vendored))\n\n\ndef cmake(*cmd_args):\n\t_LOGGER.info(f'+ cmake {subprocess.list2cmdline(cmd_args)}')\n\tsubprocess.run(['cmake', *cmd_args], cwd=_ROOT_DIR, stdout=subprocess.DEVNULL)\n\n\ndef git(*cmd_args):\n\t_LOGGER.debug(f'+ git {subprocess.list2cmdline(cmd_args)}')\n\treturn subprocess.run(['git', *cmd_args], cwd=_ROOT_DIR, capture_output=True).stdout\n\n\n# Ignore files in dependencies that we don't need.\n# Examples of some heavy ones:\n# 48M libzt-src/ext\n# 9.8M asio-src/asio/src/doc\n_IGNORE_DEP_DIR_RE = re.compile(\n\tr'(/|^)\\.|(/|^)(tests?|other|vcx?proj|examples?|doxygen|docs?|asio-src/asio/src)(/|$)')\n_IGNORE_DEP_FILE_RE = re.compile(\n\tr'(^\\.|Makefile|vcx?proj|example|doxygen|docs?|\\.(doxy|cmd|png|html|ico|icns)$)')\n\n\ndef ignore_dep_src(src, names):\n\tif 'sdl_audiolib' in src:\n\t\t# SDL_audiolib currently fails to compile if any of the files are missing.\n\t\t# TODO: Fix this in SDL_audiolib by making this optional:\n\t\t# https://github.com/realnc/SDL_audiolib/blob/5a700ba556d3a5b5c531c2fa1f45fc0c3214a16b/CMakeLists.txt#L399-L401\n\t\treturn [name for name in names if src.endswith('/sdl_audiolib-src/3rdparty/fmt')]\n\n\tif _IGNORE_DEP_DIR_RE.search(src):\n\t\t_LOGGER.debug(f'Excluded directory {src}')\n\t\treturn names\n\n\tdef ignore_name(name):\n\t\tif _IGNORE_DEP_FILE_RE.search(name) or _IGNORE_DEP_DIR_RE.search(name):\n\t\t\t_LOGGER.debug(f'Excluded file {src}/{name}')\n\t\t\treturn True\n\t\treturn False\n\n\treturn filter(ignore_name, names)\n\n\ndef get_version() -> Version:\n\tversion_prefix = None\n\twith open('VERSION', 'r') as f:\n\t\tversion_prefix = f.read().rstrip()\n\tgit_commit_sha = git('rev-parse', '--short', 'HEAD').rstrip().decode()\n\treturn Version(version_prefix, git_commit_sha)\n\n\ndef write_dist_cmakelists(paths: Paths, version: Version, fully_vendored: bool):\n\twith open(paths.dist_dir.joinpath('CMakeLists.txt'), 'wb') as f:\n\t\tf.write(b'# Generated by tools/make_src_dist.py\\n')\n\t\tif version.commit_sha:\n\t\t\tf.write(b'set(GIT_COMMIT_HASH \"%s\" PARENT_SCOPE)\\n' % version.commit_sha.encode('utf-8'))\n\n\t\tf.write(b'''\n# Pre-generated `devilutionx.mpq` and `mods/Hellfire.mpq` are provided so that distributions do not have to depend on smpq.\nset(DEVILUTIONX_MPQ \"${CMAKE_CURRENT_SOURCE_DIR}/devilutionx.mpq\" PARENT_SCOPE)\nset(HELLFIRE_MPQ \"${CMAKE_CURRENT_SOURCE_DIR}/mods/Hellfire.mpq\" PARENT_SCOPE)\n\n# This would ensure that CMake does not attempt to connect to network.\n# We do not set this to allow for builds for Windows and Android, which do fetch some\n# dependencies even with this source distribution.\n# set(FETCHCONTENT_FULLY_DISCONNECTED ON PARENT_SCOPE)\n\n# Set the path to each dependency that must be vendored:\n''')\n\t\tfor dep in _DEPS:\n\t\t\tf.write(b'set(FETCHCONTENT_SOURCE_DIR_%s \"${CMAKE_CURRENT_SOURCE_DIR}/%s-src\" CACHE STRING \"\")\\n' % (\n\t\t\t\tdep.upper().encode(), dep.encode()))\n\t\tif fully_vendored:\n\t\t\tf.write(b'\\n# These dependencies are not usually vendored but this distribution includes them\\n')\n\t\t\tf.write(b'set(FETCHCONTENT_SOURCE_DIR_DISCORDSRC \"${CMAKE_CURRENT_SOURCE_DIR}/discordsrc-src\" CACHE STRING \"\")\\n')\n\t\t\tfor dep in _DEPS_NOT_VENDORED_BY_DEFAULT:\n\t\t\t\tf.write(b'set(FETCHCONTENT_SOURCE_DIR_%s \"${CMAKE_CURRENT_SOURCE_DIR}/%s-src\" CACHE STRING \"\")\\n' % (\n\t\t\t\t\tdep.upper().encode(), dep.encode()))\n\t\t\t\tf.write(b'''if(NOT DEFINED DEVILUTIONX_SYSTEM_%s)\n  set(DEVILUTIONX_SYSTEM_%s OFF CACHE BOOL \"\")\nendif()\n''' % (dep.upper().encode(), dep.upper().encode()))\n\n\ndef make_archive(paths: Paths, fully_vendored: bool):\n\t_LOGGER.info(f'Compressing {_ARCHIVE_DIR}')\n\treturn shutil.make_archive(\n            format='xztar',\n            logger=_LOGGER,\n            base_name=_BUILD_DIR.joinpath(paths.archive_top_level_dir_name),\n            root_dir=_ARCHIVE_DIR,\n            base_dir=paths.archive_top_level_dir_name)\n\n\nmain()\n"
  },
  {
    "path": "tools/measure_timedemo_performance.py",
    "content": "#!/usr/bin/env python\n\nimport argparse\nimport re\nimport sys\nimport statistics\nimport subprocess\nfrom typing import NamedTuple\n\n_TIME_AND_FPS_REGEX = re.compile(rb'\\d+ frames, (\\d+(?:\\.\\d+)?) seconds: (\\d+(?:\\.\\d+)?) fps')\n\nclass RunMetrics(NamedTuple):\n\ttime: float\n\tfps: float\n\ndef measure(binary: str) -> RunMetrics:\n\tresult: subprocess.CompletedProcess = subprocess.run(\n\t\t[binary, '--diablo', '--spawn', '--lang', 'en', '--demo', '0', '--timedemo'], capture_output=True)\n\tmatch = _TIME_AND_FPS_REGEX.search(result.stderr)\n\tif not match:\n\t\traise Exception(f\"Failed to parse output in:\\n{result.stderr}\")\n\treturn RunMetrics(float(match.group(1)), float(match.group(2)))\n\n\ndef main():\n\tparser = argparse.ArgumentParser()\n\tparser.add_argument('--binary', help='Path to the devilutionx binary', required=True)\n\tparser.add_argument('-n', '--num-runs', type=int, default=16, metavar='N')\n\targs = parser.parse_args()\n\n\tnum_runs = args.num_runs\n\tmetrics = []\n\tfor i in range(1, num_runs + 1):\n\t\tprint(f\"Run {i:>2} of {num_runs}: \", end='', file=sys.stderr, flush=True)\n\t\trun_metrics = measure(args.binary)\n\t\tprint(f\"\\t{run_metrics.time:>5.2f} seconds\\t{run_metrics.fps:>5.1f} FPS\", file=sys.stderr, flush=True)\n\t\tmetrics.append(run_metrics)\n\n\tmean = RunMetrics(statistics.mean(m.time for m in metrics), statistics.mean(m.fps for m in metrics))\n\tstdev = RunMetrics(statistics.stdev((m.time for m in metrics), mean.time), statistics.stdev((m.fps for m in metrics), mean.fps))\n\tprint(f\"{mean.time:.3f} ± {stdev.time:.3f} seconds, {mean.fps:.3f} ± {stdev.fps:.3f} FPS\")\n\nmain()\n"
  },
  {
    "path": "tools/run_big_endian_tests.sh",
    "content": "#!/usr/bin/env bash\n\ncd -- \"$(dirname -- \"${BASH_SOURCE[0]}\")/..\"\nPARALLELISM=\"$(getconf _NPROCESSORS_ONLN)\"\n\nset -xeuo pipefail\n\nif [[ \"$(docker images -q devilutionx-s390x-test)\" = \"\" ]]; then\n\tdocker run --rm --privileged multiarch/qemu-user-static --reset -p yes\n\tdocker build -f tools/Dockerfile.s390x -t devilutionx-s390x-test tools/\nfi\n\n# We disable ASAN and UBSAN for now because of:\n# https://gitlab.alpinelinux.org/alpine/aports/-/issues/14435\ndocker run --platform linux/s390x -u \"$(id -u \"$USER\"):$(id -g \"$USER\")\" --rm --mount \"type=bind,source=${PWD},target=/host\" devilutionx-s390x-test sh -c \"cd /host && \\\nexport CCACHE_DIR=/host/.s390x-ccache && \\\ncmake -S. -Bbuild-s390x-test -G Ninja -DASAN=OFF -DUBSAN=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ \\\n  -DNONET=ON -DNOSOUND=ON && \\\nln -sf /opt/spawn.mpq /host/build-s390x-test/spawn.mpq && \\\ncmake --build build-s390x-test -j ${PARALLELISM} && \\\nctest --test-dir build-s390x-test --output-on-failure -j ${PARALLELISM}\"\n"
  },
  {
    "path": "tools/segmenter/README.md",
    "content": "# Segmenter for gettext (.po) translation files\n\nInserts [ZWSP] between the segments of Chinese and Japanese text.\n\nFor Chinese, uses a high quality `zh_segmentation` model from Google: <https://tfhub.dev/google/zh_segmentation/1>.\n\nFor Japanese, uses [Sudachi](https://github.com/WorksApplications/sudachi.rs).\n\n## Pre-requisites\n\n1. Python. The easiest way to install Python on any Linux system is <https://github.com/asdf-vm/asdf>.\n   On Windows you can use the [official installer](https://www.python.org/downloads/windows/).\n   Note that the Python version must be [supported by tensorflow](https://www.tensorflow.org/install/pip#system-requirements) (this is usually not the latest Python version).\n\n2. `gettext`. On Windows you can use [this installer](https://github.com/mlocati/gettext-iconv-windows/releases).\n\n3. Python packages:\n\n   ```shell\n   pip install --upgrade -r tools/segmenter/requirements.txt\n   ```\n\n## Usage\n\nTo re-segment all the translation files:\n\n```shell\ntools/segmenter/segment_all.py\n```\n\nTo re-segment the Chinese translation files:\n\n```shell\ntools/segmenter/segment_zh.py --input_path Translations/zh_CN.po\ntools/segmenter/segment_zh.py --input_path Translations/zh_TW.po\n```\n\nTo re-segment the Japanese translation files:\n\n```shell\ntools/segmenter/segment_ja.py --input_path Translations/ja.po\n```\n\nAdditionaly, you can provide a different separator, such as `--separator='|'`, for debugging.\n\nThis tool performs a number of replacements to make sure interpolations are not affected etc.\n\nYou can also see the segmenter output for a given string like this:\n\n```console\ntools/segmenter/segment_zh.py --debug '返回到 {:d} 层'\n```\n```\n返回｜到 {:d} 层\n```\n\nWhen inspecting the diffs, you can use `sed` to display the segments, e.g.:\n\n```bash\ngit diff --color | sed \"s/$(echo -ne '\\u200B')/｜/g\"\n```\n\n[ZWSP]: https://en.wikipedia.org/wiki/Zero-width_space\n"
  },
  {
    "path": "tools/segmenter/requirements.txt",
    "content": "tensorflow_text>=2.4.0b0\r\nsudachipy>=0.6.0\r\nsudachidict_core\r\n"
  },
  {
    "path": "tools/segmenter/segment_all.py",
    "content": "#!/usr/bin/env python\nimport pathlib\n\nimport segment_zh\nimport segment_ja\nimport segmenter_lib\n\nroot = pathlib.Path(__file__).resolve().parent.parent.parent\n\nzh_tokenizer = segment_zh.ZhTokenizer()\nsegmenter_lib.ProcessPoFile(tokenizer=zh_tokenizer,\n                            input_path=root.joinpath(\"Translations/zh_CN.po\"))\nsegmenter_lib.ProcessPoFile(tokenizer=zh_tokenizer,\n                            input_path=root.joinpath(\"Translations/zh_TW.po\"))\n\nja_tokenizer = segment_ja.JaTokenizer()\nsegmenter_lib.ProcessPoFile(tokenizer=ja_tokenizer,\n                            input_path=root.joinpath(\"Translations/ja.po\"))\n"
  },
  {
    "path": "tools/segmenter/segment_ja.py",
    "content": "#!/usr/bin/env python\nfrom typing import List, Tuple\n\nimport sudachipy\n\nimport segmenter_lib\n\n\nclass JaTokenizer():\n\t_MODE = sudachipy.SplitMode.C\n\n\tdef __init__(self) -> None:\n\t\tself._tokenizer = sudachipy.Dictionary().create()\n\n\tdef __call__(self, text: bytes) -> Tuple[List[int], List[int]]:\n\t\tunicode_text = text.decode()\n\t\ttokens = self._tokenizer.tokenize(unicode_text)\n\t\tstarts = []\n\t\tends = []\n\t\tfor token in tokens:\n\t\t\tstarts.append(len(unicode_text[:token.begin()].encode()))\n\t\t\tends.append(len(unicode_text[:token.end()].encode()))\n\t\treturn starts, ends\n\n\nif __name__ == \"__main__\":\n\tsegmenter_lib.Main(JaTokenizer())\n"
  },
  {
    "path": "tools/segmenter/segment_zh.py",
    "content": "#!/usr/bin/env python\nfrom typing import List, Tuple\n\nimport tensorflow_text\n\nimport segmenter_lib\n\n\nclass ZhTokenizer():\n\t_MODEL_HANDLE = \"https://tfhub.dev/google/zh_segmentation/1\"\n\n\tdef __init__(self) -> None:\n\t\tself._tokenizer = tensorflow_text.HubModuleTokenizer(self._MODEL_HANDLE)\n\n\tdef __call__(self, text: bytes) -> Tuple[List[int], List[int]]:\n\t\t_tokens, starts, ends = self._tokenizer.tokenize_with_offsets(text)\n\t\treturn starts.numpy(), ends.numpy()\n\n\nif __name__ == \"__main__\":\n\tsegmenter_lib.Main(ZhTokenizer())\n"
  },
  {
    "path": "tools/segmenter/segmenter_lib.py",
    "content": "\nimport re\n\nfrom typing import List, Callable, Tuple, Union\n\n_Tokenizer = Callable[[bytes], Tuple[List[int], List[int]]]\n\nZWSP = \"\\u200B\"\n\n\nclass Segmenter():\n\tdef __init__(self, tokenizer: _Tokenizer, separator: bytes):\n\t\tself._tokenizer = tokenizer\n\t\tself._separator = separator\n\n\t\tescaped_separator = re.escape(separator)\n\t\tself._segmentation_markers_pattern = re.compile(b''.join(\n\t\t\t[b'(?:', escaped_separator, b'|', re.escape(ZWSP.encode()), b')+']))\n\t\tself._redundant_markers_pattern = re.compile(b''.join(\n\t\t\t[b'(?:', escaped_separator, ')?(\\\\n| |　|，|、|。|？|！)'.encode(), b'(?:', escaped_separator, b')?']))\n\n\tdef __call__(self, text: bytes) -> bytes:\n\t\t\"\"\"Runs the segmenter and produces a separator-joined string.\"\"\"\n\t\tif not text:\n\t\t\treturn b''\n\t\ttext = self._RemoveAllMarkers(text)\n\t\tstarts, ends = self._tokenizer(text)\n\t\tstarts, ends = _RecoverGaps(text, starts, ends)\n\t\tstarts, ends = _MergeDisallowedPositions(text, starts, ends)\n\t\tstarts, ends = _RemoveEmptySegments(starts, ends)\n\t\toutput = self._separator.join([text[i:j] for i, j in zip(starts, ends)])\n\t\treturn self._RemoveRedundantMarkers(output)\n\n\tdef _RemoveRedundantMarkers(self, text: bytes) -> bytes:\n\t\t\"\"\"Removes segmentation markers for cases that are handled at runtime anyway.\"\"\"\n\t\treturn re.sub(self._redundant_markers_pattern, r'\\1', text)\n\n\tdef _RemoveAllMarkers(self, text: bytes) -> bytes:\n\t\t\"\"\"Remove the existing segmentation markers to allow for re-segmenting.\"\"\"\n\t\treturn re.sub(self._segmentation_markers_pattern, b'', text)\n\n\ndef _RemoveEmptySegments(starts: List[int], ends: List[int]) -> Tuple[List[int], List[int]]:\n\t\"\"\"Removes entries where start == end.\"\"\"\n\treturn zip(*((start, end) for start, end in zip(starts, ends) if start != end))\n\n\ndef _RecoverGaps(text: bytes, starts: List[int], ends: List[int]) -> Tuple[List[int], List[int]]:\n\t\"\"\"Recovers gaps from the segmenter-produced start and end indices.\n\n\tThe segmenter may produce gaps around spaces, e.g. segment(\"hello world\") => \"hello|world\"\n\t\"\"\"\n\tout_starts = []\n\tout_ends = []\n\tprev_end = 0\n\tfor start, end in zip(starts, ends):\n\t\tif start != prev_end:\n\t\t\tout_starts.append(prev_end)\n\t\t\tout_ends.append(start)\n\t\tout_starts.append(start)\n\t\tout_ends.append(end)\n\t\tprev_end = end\n\tif out_ends[-1] != len(text):\n\t\tout_ends[-1] = len(text)\n\treturn out_starts, out_ends\n\n\n_DISALLOW_SEGMENTATION = re.compile(\n\tr'(?:\\{.*?\\}|\\\\[a-z]|[\\w/-](?::[\\w/-]?)?|[.,;?!=+/#]|.?’.?|.:|%[0-9a-z.]+)+'.encode())\n\n\ndef _MergeDisallowedPositions(text: bytes, starts: List[int], ends: List[int]) -> Tuple[List[int], List[int]]:\n\t\"\"\"Merges segments disallowed by _DISALLOW_SEGMENTATION.\"\"\"\n\tdisallowed = set()\n\tfor m in re.finditer(_DISALLOW_SEGMENTATION, text):\n\t\tfor i in range(m.start() + 1, m.end()):\n\t\t\tdisallowed.add(i)\n\n\tout_starts = [starts[0]]\n\tout_ends = [ends[0]]\n\tfor start, end in zip(starts[1:], ends[1:]):\n\t\tif start in disallowed:\n\t\t\tout_ends[-1] = end\n\t\telse:\n\t\t\tout_starts.append(start)\n\t\t\tout_ends.append(end)\n\treturn out_starts, out_ends\n\n\ndef _QuoteLine(line):\n\treturn b'\"%s\"\\n' % line\n\n\n_MSGSTR_PREFIX = b'msgstr '\n\n\ndef SegmentPo(input: List[bytes], tokenizer: _Tokenizer, separator: bytes = ZWSP.encode()) -> List[bytes]:\n\tsegmenter = Segmenter(tokenizer, separator)\n\toutput = []\n\n\t# Skip poedit header\n\theader_end = input.index(b'\\n') + 1\n\toutput.extend(input[:header_end])\n\tinput = input[header_end:]\n\n\tin_msgstr = False\n\tmsgstr_prefix = \"\"\n\tmsgstr = []\n\n\tdef _ProcessMsgStr():\n\t\ttext = segmenter(b''.join(msgstr))\n\t\toutput.append(msgstr_prefix + _QuoteLine(text))\n\n\tfor line in input:\n\t\tif line.startswith(_MSGSTR_PREFIX):\n\t\t\tmsgstr_prefix, line = line.split(b'\"', maxsplit=1)\n\t\t\tmsgstr.append(line[:-2])\n\t\t\tin_msgstr = True\n\t\telif in_msgstr and line.startswith(b'\"'):\n\t\t\tmsgstr.append(line[1:-2])\n\t\telse:\n\t\t\tif msgstr:\n\t\t\t\t_ProcessMsgStr()\n\t\t\t\tmsgstr.clear()\n\t\t\t\tmsgstr_prefix = \"\"\n\t\t\toutput.append(line)\n\t\t\tin_msgstr = False\n\n\tif msgstr:\n\t\t_ProcessMsgStr()\n\n\treturn output\n\n\n_DEFAULT_SEPARATOR = ZWSP\n_DEFAULT_PO_WRAP_WIDTH = 79\n\n\ndef ProcessPoFile(tokenizer: _Tokenizer, input_path: str, output_path: Union[str, None] = None,\n                  separator: str = _DEFAULT_SEPARATOR, wrap_width: int = _DEFAULT_PO_WRAP_WIDTH):\n\timport subprocess\n\timport os\n\timport sys\n\n\tif not output_path:\n\t\toutput_path = input_path\n\n\twith open(input_path, 'rb') as f:\n\t\tinput = f.readlines()\n\n\toutput = SegmentPo(input, tokenizer, separator=separator.encode())\n\n\twith open(output_path, 'wb') if output_path != \"/dev/stdout\" else os.fdopen(sys.stdout.fileno(), \"wb\", closefd=False) as f:\n\t\tf.write(b''.join(output))\n\n\t# Run gettext's msgcat to reformat the file.\n\tsubprocess.run(['msgcat', '--force-po', f'--width={wrap_width}', '-o', output_path, output_path],\n                stdout=sys.stdout, stderr=sys.stderr)\n\n\ndef Main(tokenizer: _Tokenizer):\n\timport argparse\n\timport os\n\timport sys\n\n\tparser = argparse.ArgumentParser()\n\tparser.add_argument(\"--input_path\", help=\"Path to the input .po file\")\n\tparser.add_argument(\"--output_path\", help=\"Output path (default: in-place)\")\n\tparser.add_argument(\"--separator\", default=_DEFAULT_SEPARATOR,\n                     help=\"Separator to use between segments\")\n\tparser.add_argument(\"--po_wrap_width\", default=_DEFAULT_PO_WRAP_WIDTH,\n                     help=\"Wrap .po text to this many lines\")\n\tparser.add_argument(\"--debug\",\n                     help=\"If this flag is given, segments the given string, joins with \\\"|\\\", and prints it.\")\n\targs = parser.parse_args()\n\n\tif args.debug:\n\t\tsegmenter = Segmenter(tokenizer, separator='｜'.encode())\n\t\twith os.fdopen(sys.stdout.fileno(), \"wb\", closefd=False) as f:\n\t\t\tf.write(segmenter(args.debug.encode()))\n\t\t\tf.write(b'\\n')\n\t\texit()\n\n\tProcessPoFile(input_path=args.input_path, output_path=args.output_path,\n\t              tokenizer=tokenizer, separator=args.separator, wrap_width=args.po_wrap_width)\n"
  },
  {
    "path": "tools/update_bundled_assets.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nif [[ $# -eq 0 ]]; then\n\t>&2 echo \"Usage: tools/update_bundled_assets.sh [path-to-devilutionx-assets-repo-dir]\"\n\texit 64\nfi\n\nASSETS_REPO_DIR=\"$1\"\nOUTPUT_DIR=\"${PWD}/assets\"\n\nset -x\ncd \"${ASSETS_REPO_DIR}/bundled-assets\"\npcx2clx --output-dir \"${OUTPUT_DIR}/data\" data/boxleftend.pcx data/boxmiddle.pcx data/boxrightend.pcx data/charbg.pcx data/health.pcx\npcx2clx --output-dir \"${OUTPUT_DIR}/data\" --num-sprites 2 data/talkbutton.pcx\npcx2clx --output-dir \"${OUTPUT_DIR}/gendata\" gendata/*.pcx\npcx2clx --output-dir \"${OUTPUT_DIR}/ui_art\" ui_art/creditsw.pcx ui_art/dvl_lrpopup.pcx ui_art/hf_titlew.pcx ui_art/mainmenuw.pcx ui_art/supportw.pcx\n\nFONT_CONVERT_ARGS=(--transparent-color 1 --num-sprites 256)\nfor path in fonts/*.pcx; do\n\tif [[ -f \"${path%.pcx}.txt\" ]]; then\n\t\tpcx2clx \"${FONT_CONVERT_ARGS[@]}\" --output-dir \"${OUTPUT_DIR}/fonts\" --crop-widths \"$(cat \"${path%.pcx}.txt\" | paste -sd , -)\" \"${path}\"\n\telse\n\t\tpcx2clx \"${FONT_CONVERT_ARGS[@]}\" --output-dir \"${OUTPUT_DIR}/fonts\" \"${path}\"\n\tfi\ndone\nfor lang_dir in fonts/*/; do\n\tlang_dir=\"${lang_dir%/}\" # remove trailing slash\n\tmkdir -p \"${OUTPUT_DIR}/${lang_dir}\"\n\tfor path in \"$lang_dir\"/*.pcx; do\n\t\tif [[ -f \"${path%.pcx}.txt\" ]]; then\n\t\t\tpcx2clx \"${FONT_CONVERT_ARGS[@]}\" --output-dir \"${OUTPUT_DIR}/${lang_dir}\" --crop-widths \"$(cat \"${path%.pcx}.txt\" | paste -sd , -)\" \"${path}\"\n\t\telse\n\t\t\tpcx2clx \"${FONT_CONVERT_ARGS[@]}\" --output-dir \"${OUTPUT_DIR}/${lang_dir}\" \"${path}\"\n\t\tfi\n\tdone\ndone\n\npcx2clx --num-sprites 2 --output-dir \"${OUTPUT_DIR}/ui_art\" ui_art/dvl_but_sml.pcx\npcx2clx --transparent-color 1 --output-dir \"${OUTPUT_DIR}/data\" data/hintbox.pcx data/hintboxbackground.pcx\npcx2clx --transparent-color 1 --num-sprites 6 --output-dir \"${OUTPUT_DIR}/data\" data/hinticons.pcx\npcx2clx --num-sprites 2 --output-dir \"${OUTPUT_DIR}/data\" data/panel8buc.pcx data/dirtybuc.pcx data/dirtybucp.pcx\npcx2clx --transparent-color 1 --output-dir \"${OUTPUT_DIR}/data\" data/healthbox.pcx\npcx2clx --transparent-color 1 --num-sprites 6 --output-dir \"${OUTPUT_DIR}/data\" data/resistance.pcx\npcx2clx --transparent-color 1 --num-sprites 5 --output-dir \"${OUTPUT_DIR}/data\" data/monstertags.pcx\npcx2clx --transparent-color 1 --output-dir \"${OUTPUT_DIR}/data\" data/stash.pcx\npcx2clx --transparent-color 1 --num-sprites 5 --output-dir \"${OUTPUT_DIR}/data\" data/stashnavbtns.pcx\npcx2clx --num-sprites 6 --output-dir \"${OUTPUT_DIR}/data\" data/panel8bucp.pcx\npcx2clx --transparent-color 1 --output-dir \"${OUTPUT_DIR}/data\" data/xpbar.pcx\ncd -\n"
  },
  {
    "path": "tools/update_sdl_android_project.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nSDL_BASE=https://raw.githubusercontent.com/libsdl-org/SDL/release-2.32.0\nFILES=(\n\tHIDDevice.java\n\tHIDDeviceBLESteamController.java\n\tHIDDeviceManager.java\n\tHIDDeviceUSB.java\n\tSDL.java\n\tSDLActivity.java\n\tSDLAudioManager.java\n\tSDLControllerManager.java\n\tSDLSurface.java\n)\n\nfor f in \"${FILES[@]}\"; do\n\tset -x\n\tcurl -L -O -s \"${SDL_BASE}/android-project/app/src/main/java/org/libsdl/app/${f}\" \\\n\t\t--output-dir android-project/app/src/main/java/org/libsdl/app/\n\t{ set +x; } 2> /dev/null\ndone\n>&2 echo \"Done. Remember to manually check for and sync changes in XML files, such as AndroidManifest.xml\"\n"
  },
  {
    "path": "tools/update_translations_pot.py",
    "content": "#!/usr/bin/env python\n\nimport datetime\nimport glob\nimport os\nimport sys\nimport pathlib\nimport subprocess\n\nfrom packaging.version import Version\n\n\n# Version 0.22 is the first version to support c++-format\n_MIN_XGETTEXT_VERSION = Version(\"0.22\")\n\n_HEADER = \"\"\"\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: DevilutionX\\\\n\"\n\"POT-Creation-Date: {timestamp}\\\\n\"\n\"PO-Revision-Date: \\\\n\"\n\"Last-Translator: \\\\n\"\n\"Language-Team: \\\\n\"\n\"MIME-Version: 1.0\\\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\\\n\"\n\"Content-Transfer-Encoding: 8bit\\\\n\"\n\"X-Generator: xgettext {xgettext_version}\\\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\\\n\"\n\"X-Poedit-KeywordsList: ;_;N_;ngettext:1,2;pgettext:1c,2;P_:1c,2\\\\n\"\n\"X-Poedit-Basepath: ..\\\\n\"\n\"X-Poedit-SearchPath-0: Source\\\\n\"\n\n\"\"\"\n\n\nclass Error(Exception):\n    def __init__(self, message):\n        self.message = message\n\n    def __str__(self):\n        return self.message\n\n\ndef get_xgettext() -> tuple[str, str]:\n    xgettext_bin = os.environ.get(\"XGETTEXT_BIN\", \"xgettext\")\n    result: subprocess.CompletedProcess = subprocess.run(\n        [xgettext_bin, \"--version\"],\n        stdout=subprocess.PIPE,\n        stderr=sys.stderr,\n        check=True,\n    )\n    version_str = result.stdout.split(b\"\\n\")[0].split(b\" \")[-1].decode()\n    version = Version(version_str.split(\"-\")[0])\n    if version < _MIN_XGETTEXT_VERSION:\n        raise Error(\n            f\"{xgettext_bin} version {version} is too low,\"\n            + f\" minimum required is {_MIN_XGETTEXT_VERSION}\"\n        )\n    return xgettext_bin, version_str\n\n\ndef run_xgettext():\n    xgettext_binary, xgettext_version = get_xgettext()\n    files = []\n    for ext in [\"h\", \"c\", \"hpp\", \"cpp\"]:\n        files.extend(glob.glob(f\"Source/**/*.{ext}\", recursive=True))\n    files.sort()\n\n    result: subprocess.CompletedProcess = subprocess.run(\n        [\n            xgettext_binary,\n            \"--output=-\",\n            \"--keyword\",\n            \"--keyword=_\",\n            \"--flag=_:1:pass-c++-format\",\n            \"--keyword=N_\",\n            \"--flag=N_:1:pass-c++-format\",\n            \"--keyword=ngettext:1,2\",\n            \"--flag=ngettext:1:pass-c++-format\",\n            \"--flag=ngettext:2:pass-c++-format\",\n            \"--keyword=pgettext:1c,2\",\n            \"--flag=pgettext:2:pass-c++-format\",\n            \"--keyword=P_:1c,2\",\n            \"--flag=P_:2:pass-c++-format\",\n            \"--flag=runtime:1:c++-format\",\n            \"--flag=Log:1:c++-format\",\n            \"--flag=LogError:1:c++-format\",\n            \"--flag=LogWarn:1:c++-format\",\n            \"--flag=LogInfo:1:c++-format\",\n            \"--flag=LogDebug:1:c++-format\",\n            \"--flag=LogVerbose:1:c++-format\",\n            \"--language=C++\",\n            \"--from-code=UTF-8\",\n            \"--add-comments=TRANSLATORS: \",\n            # Omitting the header causes spurious warnings:\n            # \"msgid contains non-ASCII characters\".\n            #\n            # To avoid the warnings, we generate the header\n            # but skip writing it later.\n            # \"--omit-header\",\n            \"--debug\",\n            *files,\n        ],\n        stdout=subprocess.PIPE,\n        stderr=sys.stderr,\n        check=True,\n    )\n\n    timestamp = datetime.datetime.now(datetime.UTC).strftime(\"%Y-%m-%d %H:%M:%S%z\")\n    with open(\"Translations/devilutionx.pot\", \"wb\") as f:\n        f.write(\n            _HEADER.format(\n                timestamp=timestamp,\n                xgettext_version=xgettext_version,\n            ).encode()\n        )\n        f.write(b\"\\n\\n\".join(result.stdout.split(b\"\\n\\n\")[1:]))\n\n\ndef main():\n    os.chdir(pathlib.Path(__file__).resolve().parent.parent)\n    try:\n        run_xgettext()\n    except Error as e:\n        print(\"Error:\", e, file=sys.stderr)\n        return 1\n    except subprocess.CalledProcessError as e:\n        print(\"Error:\", e.cmd[0], \"failed\", file=sys.stderr)\n        return e.returncode\n\n\nmain()\n"
  },
  {
    "path": "tools/validate_translations.py",
    "content": "#!/usr/bin/env python3\n\nimport re\nfrom glob import glob\n\nimport polib\n\n\ndef validateEntry(original, translation):\n\tif translation == '':\n\t\treturn True\n\n\t# Find fmt arguments in source message\n\tsrc_arguments = re.findall(r\"{.*?}\", original)\n\tif not src_arguments:\n\t\treturn True\n\n\t# Find fmt arguments in translation\n\ttranslated_arguments = re.findall(r\"{.*?}\", translation)\n\n\t# If paramteres are untyped with order, sort so that they still appear equal if reordered\n\t# Note: This does no hadle cases where the translator reordered arguments where not expected\n\t# by the source. Or other advanced but valid usages of the fmt syntax\n\tisOrdered = True\n\tfor argument in src_arguments:\n\t\tif not re.search(r\"^{\\d+}$\", argument):\n\t\t\tisOrdered = False\n\t\t\tbreak\n\n\tif isOrdered:\n\t\tsrc_arguments.sort()\n\t\ttranslated_arguments.sort()\n\n\tif src_arguments == translated_arguments:\n\t\treturn True\n\n\tprint(f\"\\033[36m{original}\\033[0m != \\033[31m{translation}\\033[0m\")\n\n\treturn False\n\n\nstatus = 0\n\nfiles = glob('Translations/*.po')\nfor path in sorted(files):\n\tpo = polib.pofile(path)\n\tprint(f\"\\033[32mValidating {po.metadata['Language']}\\033[0m : {po.percent_translated()}% translated\")\n\n\tfor entry in po:\n\t\tif entry.fuzzy:\n\t\t\tcontinue\n\n\t\tif entry.msgid_plural:\n\t\t\tfor translation in entry.msgstr_plural.values():\n\t\t\t\tif not validateEntry(entry.msgid_plural, translation):\n\t\t\t\t\tstatus = 255\n\t\t\tcontinue\n\n\t\tif not validateEntry(entry.msgid, entry.msgstr):\n\t\t\tstatus = 255\n\nexit(status)\n"
  },
  {
    "path": "uwp-project/Package.appxmanifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n\r\n<Package\r\n  xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\"\r\n  xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"\r\n  xmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\"\r\n  IgnorableNamespaces=\"uap mp\">\r\n\r\n  <Identity\r\n    Name=\"b6830ff4-1ef5-4907-9d9e-1ba808edf70f\"\r\n    Publisher=\"CN=devilutionX\"\r\n    Version=\"0.0.0.0\" />\r\n\r\n  <mp:PhoneIdentity PhoneProductId=\"b6830ff4-1ef5-4907-9d9e-1ba808edf70f\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\r\n\r\n  <Properties>\r\n    <DisplayName>devilutionX</DisplayName>\r\n    <PublisherDisplayName>devilution Team</PublisherDisplayName>\r\n    <Logo>Assets\\StoreLogo.png</Logo>\r\n  </Properties>\r\n\r\n  <Dependencies>\r\n    <TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.10069.0\" MaxVersionTested=\"10.0.10069.0\" />\r\n  </Dependencies>\r\n\r\n  <Resources>\r\n    <Resource Language=\"x-generate\"/>\r\n  </Resources>\r\n\r\n  <Applications>\r\n    <Application Id=\"App\"\r\n      Executable=\"$targetnametoken$.exe\"\r\n      EntryPoint=\"devilutionX.App\">\r\n      <uap:VisualElements\r\n        DisplayName=\"DevilutionX\"\r\n        Square150x150Logo=\"Assets\\Logo.png\"\r\n        Square44x44Logo=\"Assets\\SmallLogo.png\"\r\n        Description=\"DevilutionX\"\r\n        BackgroundColor=\"#000000\">\r\n        <uap:SplashScreen Image=\"Assets\\SplashScreen.png\"  BackgroundColor=\"#000000\"/>\r\n        <uap:DefaultTile Square71x71Logo=\"Assets\\SmallTile.png\" Wide310x150Logo=\"Assets\\WideTile.png\" Square310x310Logo=\"Assets\\LargeTile.png\"/>\r\n        <uap:LockScreen BadgeLogo=\"Assets\\BadgeLogo.png\" Notification=\"badgeAndTileText\"/>\r\n      </uap:VisualElements>\r\n    </Application>\r\n  </Applications>\r\n\r\n  <Capabilities>\r\n    <Capability Name=\"internetClient\" />\r\n    <Capability Name=\"internetClientServer\"/>\r\n  </Capabilities>\r\n</Package>\r\n"
  },
  {
    "path": "uwp-project/Package.appxmanifest.template",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n\r\n<Package\r\n  xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\"\r\n  xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"\r\n  xmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\"\r\n  IgnorableNamespaces=\"uap mp\">\r\n\r\n  <Identity\r\n    Name=\"b6830ff4-1ef5-4907-9d9e-1ba808edf70f\"\r\n    Publisher=\"CN=devilutionX\"\r\n    Version=\"__PROJECT_VERSION__.0\" />\r\n\r\n  <mp:PhoneIdentity PhoneProductId=\"b6830ff4-1ef5-4907-9d9e-1ba808edf70f\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\r\n\r\n  <Properties>\r\n    <DisplayName>devilutionX</DisplayName>\r\n    <PublisherDisplayName>devilution Team</PublisherDisplayName>\r\n    <Logo>Assets\\StoreLogo.png</Logo>\r\n  </Properties>\r\n\r\n  <Dependencies>\r\n    <TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.10069.0\" MaxVersionTested=\"10.0.10069.0\" />\r\n  </Dependencies>\r\n\r\n  <Resources>\r\n    <Resource Language=\"x-generate\"/>\r\n  </Resources>\r\n\r\n  <Applications>\r\n    <Application Id=\"App\"\r\n      Executable=\"$targetnametoken$.exe\"\r\n      EntryPoint=\"devilutionX.App\">\r\n      <uap:VisualElements\r\n        DisplayName=\"DevilutionX\"\r\n        Square150x150Logo=\"Assets\\Logo.png\"\r\n        Square44x44Logo=\"Assets\\SmallLogo.png\"\r\n        Description=\"DevilutionX\"\r\n        BackgroundColor=\"#000000\">\r\n        <uap:SplashScreen Image=\"Assets\\SplashScreen.png\"  BackgroundColor=\"#000000\"/>\r\n        <uap:DefaultTile Square71x71Logo=\"Assets\\SmallTile.png\" Wide310x150Logo=\"Assets\\WideTile.png\" Square310x310Logo=\"Assets\\LargeTile.png\"/>\r\n        <uap:LockScreen BadgeLogo=\"Assets\\BadgeLogo.png\" Notification=\"badgeAndTileText\"/>\r\n      </uap:VisualElements>\r\n    </Application>\r\n  </Applications>\r\n\r\n  <Capabilities>\r\n    <Capability Name=\"internetClient\" />\r\n    <Capability Name=\"internetClientServer\"/>\r\n  </Capabilities>\r\n</Package>\r\n"
  },
  {
    "path": "uwp-project/devilutionx.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Version 17\r\nVisualStudioVersion = 17.0.32014.148\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"devilutionX\", \"devilutionx.vcxproj\", \"{3183A558-46F4-4FEF-8684-0A79B793599F}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|x64 = Debug|x64\r\n\t\tRelease|x64 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{3183A558-46F4-4FEF-8684-0A79B793599F}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{3183A558-46F4-4FEF-8684-0A79B793599F}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{3183A558-46F4-4FEF-8684-0A79B793599F}.Debug|x64.Deploy.0 = Debug|x64\r\n\t\t{3183A558-46F4-4FEF-8684-0A79B793599F}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{3183A558-46F4-4FEF-8684-0A79B793599F}.Release|x64.Build.0 = Release|x64\r\n\t\t{3183A558-46F4-4FEF-8684-0A79B793599F}.Release|x64.Deploy.0 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {D91CBA35-4ECA-4F87-81C4-EBD110EDEE56}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "uwp-project/devilutionx.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|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</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    <ProjectGuid>{3183a558-46f4-4fef-8684-0a79b793599f}</ProjectGuid>\r\n    <Keyword>DirectXApp</Keyword>\r\n    <RootNamespace>devilutionX</RootNamespace>\r\n    <DefaultLanguage>en-US</DefaultLanguage>\r\n    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\r\n    <AppContainerApplication>true</AppContainerApplication>\r\n    <ApplicationType>Windows Store</ApplicationType>\r\n    <ApplicationTypeRevision>8.2</ApplicationTypeRevision>\r\n    <TargetPlatformVersion>10.0.10069.0</TargetPlatformVersion>\r\n    <TargetPlatformMinVersion>10.0.10069.0</TargetPlatformMinVersion>\r\n    <WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>\r\n    <WindowsTargetPlatformMinVersion>10.0.14393.0</WindowsTargetPlatformMinVersion>\r\n    <ProjectName>devilutionX</ProjectName>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n    <Import Project=\"$(VSINSTALLDIR)\\Common7\\IDE\\Extensions\\Microsoft\\VsGraphics\\ImageContentTask.props\" />\r\n    <Import Project=\"$(VSINSTALLDIR)\\Common7\\IDE\\Extensions\\Microsoft\\VsGraphics\\MeshContentTask.props\" />\r\n    <Import Project=\"$(VSINSTALLDIR)\\Common7\\IDE\\Extensions\\Microsoft\\VsGraphics\\ShaderGraphContentTask.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\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 Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\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    <AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>\r\n    <GenerateAppInstallerFile>False</GenerateAppInstallerFile>\r\n    <AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>\r\n    <AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>\r\n    <GenerateTestArtifacts>True</GenerateTestArtifacts>\r\n    <AppxBundle>Always</AppxBundle>\r\n    <AppxBundlePlatforms>x64</AppxBundlePlatforms>\r\n    <HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>\r\n    <AppxPackageDir>..\\build\\uwp-project\\AppxPackages</AppxPackageDir>\r\n    <PackageCertificateThumbprint>0D43FF406F8BFD3F3325F61908D76FBDAB01425C</PackageCertificateThumbprint>\r\n    <PackageCertificateKeyFile>devilutionX_TemporaryKey.pfx</PackageCertificateKeyFile>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <OutDir>..\\build\\uwp-project\\$(Configuration)\\</OutDir>\r\n    <IntDir>..\\build\\uwp-project\\obj\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <OutDir>..\\build\\uwp-project\\$(Configuration)\\</OutDir>\r\n    <IntDir>..\\build\\uwp-project\\obj\\</IntDir>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <Link>\r\n      <AdditionalDependencies>sdl_image.lib;libpng16_staticd.lib;pkware.lib;fmtd.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>..\\build\\SDL\\VisualC-WinRT\\x64\\Debug\\SDL-UWP;..\\build\\3rdParty\\SDL_image\\Debug;..\\build\\_deps\\zlib-build\\Debug;..\\build\\3rdParty\\PKWare\\Debug;..\\build\\3rdParty\\bzip2\\Debug;..\\build\\3rdParty\\libsmackerdec\\Debug;..\\build\\3rdParty\\libmpq\\Debug;..\\build\\_deps\\lua-build\\lua-5.4.7\\Debug;..\\build\\_deps\\sdl_audiolib-build\\Debug;..\\build\\3rdParty\\asio\\Debug;..\\build\\_deps\\libsodium-build\\Debug;..\\build\\_deps\\libzt-build\\lib\\Debug;..\\build\\_deps\\libfmt-build\\Debug;..\\build\\_deps\\libpng-build\\Debug;..\\build\\Source\\libdevilutionx.dir\\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n    </Link>\r\n    <ClCompile>\r\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\r\n      <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>\r\n      <AdditionalIncludeDirectories>..\\Source;..\\build\\SDL\\include;..\\build\\_deps\\sdl_audiolib-src\\include;..\\build\\_deps\\sdl_audiolib-build;..\\build\\_deps\\unordered_dense-src\\include;..\\build\\_deps\\libfmt-src\\include;..\\3rdParty\\tl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r\n      <PreprocessorDefinitions>_DEBUG;__UWP__=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n      <CompileAsWinRT>true</CompileAsWinRT>\r\n      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>\r\n      <EnableModules>false</EnableModules>\r\n    </ClCompile>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <Link>\r\n      <AdditionalDependencies>sdl_image.lib;libpng16_static.lib;pkware.lib;fmt.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;sheenbidi.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>..\\build\\SDL\\VisualC-WinRT\\x64\\Release\\SDL-UWP;..\\build\\3rdParty\\SDL_image\\Release;..\\build\\_deps\\zlib-build\\Release;..\\build\\3rdParty\\PKWare\\Release;..\\build\\3rdParty\\bzip2\\Release;..\\build\\3rdParty\\libsmackerdec\\Release;..\\build\\3rdParty\\libmpq\\Release;..\\build\\_deps\\lua-build\\lua-5.4.7\\Release;..\\build\\_deps\\sdl_audiolib-build\\Release;..\\build\\3rdParty\\asio\\Release;..\\build\\_deps\\libsodium-build\\Release;..\\build\\_deps\\libzt-build\\lib\\Release;..\\build\\_deps\\libfmt-build\\Release;..\\build\\_deps\\libpng-build\\Release;..\\build\\_deps\\sheenbidi-build\\Release;..\\build\\Source\\libdevilutionx.dir\\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n    </Link>\r\n    <ClCompile>\r\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\r\n      <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r\n      <PreprocessorDefinitions>NDEBUG;__UWP__=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r\n      <AdditionalIncludeDirectories>..\\Source;..\\build\\SDL\\include;..\\build\\_deps\\sdl_audiolib-src\\include;..\\build\\_deps\\sdl_audiolib-build;..\\build\\_deps\\unordered_dense-src\\include;..\\build\\_deps\\libfmt-src\\include;..\\3rdParty\\tl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n    </ClCompile>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <Image Include=\"Assets\\BadgeLogo.scale-200.png\" />\r\n    <Image Include=\"Assets\\LargeTile.scale-200.png\" />\r\n    <Image Include=\"Assets\\Logo.scale-200.png\" />\r\n    <Image Include=\"Assets\\SmallLogo.altform-lightunplated_targetsize-48.png\" />\r\n    <Image Include=\"Assets\\SmallLogo.altform-unplated_targetsize-48.png\" />\r\n    <Image Include=\"Assets\\SmallLogo.scale-200.png\" />\r\n    <Image Include=\"Assets\\SmallLogo.targetsize-48.png\" />\r\n    <Image Include=\"Assets\\SmallTile.scale-200.png\" />\r\n    <Image Include=\"Assets\\SplashScreen.scale-200.png\" />\r\n    <Image Include=\"Assets\\StoreLogo.scale-200.png\" />\r\n    <Image Include=\"Assets\\WideTile.scale-200.png\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <AppxManifest Include=\"Package.appxmanifest\">\r\n      <SubType>Designer</SubType>\r\n    </AppxManifest>\r\n    <None Include=\"..\\build\\assets\\*.*\">\r\n      <DeploymentContent>true</DeploymentContent>\r\n      <Link>Assets\\%(RecursiveDir)%(Filename)%(Extension)</Link>\r\n    </None>\r\n    <None Include=\"..\\build\\assets\\**\\*.*\">\r\n      <DeploymentContent>true</DeploymentContent>\r\n      <Link>Assets\\%(RecursiveDir)%(Filename)%(Extension)</Link>\r\n    </None>\r\n    <None Include=\"devilutionX_TemporaryKey.pfx\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"src\\SDL_winrt_main_NonXAML.cpp\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n    <Import Project=\"$(VSINSTALLDIR)\\Common7\\IDE\\Extensions\\Microsoft\\VsGraphics\\ImageContentTask.targets\" />\r\n    <Import Project=\"$(VSINSTALLDIR)\\Common7\\IDE\\Extensions\\Microsoft\\VsGraphics\\MeshContentTask.targets\" />\r\n    <Import Project=\"$(VSINSTALLDIR)\\Common7\\IDE\\Extensions\\Microsoft\\VsGraphics\\ShaderGraphContentTask.targets\" />\r\n  </ImportGroup>\r\n</Project>\r\n"
  },
  {
    "path": "uwp-project/src/SDL_winrt_main_NonXAML.cpp",
    "content": "/*\r\n    SDL_winrt_main_NonXAML.cpp, placed in the public domain by David Ludwig  3/13/14\r\n*/\r\n\r\n#include <SDL.h>\r\n#include <diablo.h>\r\n#include <wrl.h>\r\n\r\n/* At least one file in any SDL/WinRT app appears to require compilation\r\n   with C++/CX, otherwise a Windows Metadata file won't get created, and\r\n   an APPX0702 build error can appear shortly after linking.\r\n\r\n   The following set of preprocessor code forces this file to be compiled\r\n   as C++/CX, which appears to cause Visual C++ 2012's build tools to\r\n   create this .winmd file, and will help allow builds of SDL/WinRT apps\r\n   to proceed without error.\r\n\r\n   If other files in an app's project enable C++/CX compilation, then it might\r\n   be possible for SDL_winrt_main_NonXAML.cpp to be compiled without /ZW,\r\n   for Visual C++'s build tools to create a winmd file, and for the app to\r\n   build without APPX0702 errors.  In this case, if\r\n   SDL_WINRT_METADATA_FILE_AVAILABLE is defined as a C/C++ macro, then\r\n   the #error (to force C++/CX compilation) will be disabled.\r\n\r\n   Please note that /ZW can be specified on a file-by-file basis.  To do this,\r\n   right click on the file in Visual C++, click Properties, then change the\r\n   setting through the dialog that comes up.\r\n*/\r\n#ifndef SDL_WINRT_METADATA_FILE_AVAILABLE\r\n#ifndef __cplusplus_winrt\r\n#error SDL_winrt_main_NonXAML.cpp must be compiled with /ZW, otherwise build errors due to missing .winmd files can occur.\r\n#endif\r\n#endif\r\n\r\n/* Prevent MSVC++ from warning about threading models when defining our\r\n   custom WinMain.  The threading model will instead be set via a direct\r\n   call to Windows::Foundation::Initialize (rather than via an attributed\r\n   function).\r\n\r\n   To note, this warning (C4447) does not seem to come up unless this file\r\n   is compiled with C++/CX enabled (via the /ZW compiler flag).\r\n*/\r\n#ifdef _MSC_VER\r\n#pragma warning(disable:4447)\r\n#endif\r\n\r\n/* Make sure the function to initialize the Windows Runtime gets linked in. */\r\n#ifdef _MSC_VER\r\n#pragma comment(lib, \"runtimeobject.lib\")\r\n#endif\r\n\r\n// This handler is needed otherwise B button will exit the game as it is the behavior default for UWP apps\r\nvoid OnBackRequested(Platform::Object^, Windows::UI::Core::BackRequestedEventArgs^ args)\r\n{\r\n\targs->Handled = true;\r\n}\r\n\r\nvoid onInitialized()\r\n{\r\n\tWindows::UI::Core::SystemNavigationManager::GetForCurrentView()->BackRequested += ref new Windows::Foundation::EventHandler<Windows::UI::Core::BackRequestedEventArgs^>(OnBackRequested);\r\n}\r\n\r\nint CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)\r\n{\r\n\tdevilution::setOnInitialized(&onInitialized);\r\n    return SDL_WinRTRunApp(devilution::DiabloMain, NULL);\r\n}\r\n"
  },
  {
    "path": "vcpkg.json",
    "content": "{\r\n\t\"name\": \"devilutionx\",\r\n\t\"version-string\": \"1.6.0\",\r\n\t\"dependencies\": [\r\n\t\t\"fmt\",\r\n\t\t\"bzip2\",\r\n\t\t\"lua\",\r\n\t\t\"magic-enum\"\r\n\t],\r\n\t\"builtin-baseline\": \"a62ce77d56ee07513b4b67de1ec2daeaebfae51a\",\r\n\t\"features\": {\r\n\t\t\"sdl1\": {\r\n\t\t\t\"description\": \"Use SDL1.2 instead of SDL2\",\r\n\t\t\t\"dependencies\": [ \"sdl1\", \"libpng\" ]\r\n\t\t},\r\n\t\t\"sdl2\": {\r\n\t\t\t\"description\": \"Use SDL2\",\r\n\t\t\t\"dependencies\": [ \"sdl2\", \"sdl2-image\" ]\r\n\t\t},\r\n\t\t\"encryption\": {\r\n\t\t\t\"description\": \"Build libsodium for packet encryption\",\r\n\t\t\t\"dependencies\": [ \"libsodium\" ]\r\n\t\t},\r\n\t\t\"translations\": {\r\n\t\t\t\"description\": \"Build translation files\",\r\n\t\t\t\"dependencies\": [\r\n\t\t\t\t{\r\n\t\t\t\t\t\"name\": \"gettext\",\r\n\t\t\t\t\t\"features\": [ \"tools\" ]\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t},\r\n\t\t\"tests\": {\r\n\t\t\t\"description\": \"Build tests\",\r\n\t\t\t\"dependencies\": [ \"gtest\", \"benchmark\" ]\r\n\t\t}\r\n\t}\r\n}\r\n"
  }
]